[
  {
    "path": ".clang-format",
    "content": "---\nLanguage:        Cpp\nBasedOnStyle:  Google\n...\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/00-bug_report.yml",
    "content": "name: Bug Report\ndescription: Let us know that something does not work as expected.\ntitle: \"[Bug]: Please title this bug report\"\nbody:\n  - type: textarea\n    id: what-happened\n    attributes:\n      label: Describe the issue\n      description: What happened, and what did you expect to happen?\n    validations:\n      required: true\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps to reproduce the problem\n      description: It is 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.\n    validations:\n      required: true\n  - type: textarea\n    id: version\n    attributes:\n      label: What version of Abseil are you using?\n      description: Please include the output of `git rev-parse HEAD` or the name of the LTS release that you are using.\n    validations:\n      required: true\n  - type: textarea\n    id: os\n    attributes:\n      label: What operating system and version are you using?\n      description: If you are using a Linux distribution please include the name and version of the distribution as well.\n    validations:\n      required: true\n  - type: textarea\n    id: compiler\n    attributes:\n      label: What compiler and version are you using?\n      description: Please include the output of `gcc -v` or `clang -v`, or the equivalent for your compiler.\n    validations:\n      required: true\n  - type: textarea\n    id: buildsystem\n    attributes:\n      label: What build system are you using?\n      description: Please include the output of `bazel --version` or `cmake --version`, or the equivalent for your build system.\n    validations:\n      required: true\n  - type: textarea\n    id: additional\n    attributes:\n      label: Additional context\n      description: Add any other context about the problem here.\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n    - name: Question\n      url: https://github.com/abseil/abseil-cpp/discussions\n      about: Have a question? Ask us anything! :-)\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Thank you for your contribution to Abseil!\n\nBefore submitting this PR, please be sure to read our [contributing\nguidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md).\n\nIf you are a Googler, please also note that it is required that you send us a\nPiper CL instead of using the GitHub pull-request process. The code propagation\nprocess will deliver the change to GitHub.\n"
  },
  {
    "path": ".gitignore",
    "content": "# Bzlmod lockfile\nMODULE.bazel.lock\n# Ignore all bazel-* symlinks.\n/bazel-*\n# Ignore Bazel verbose explanations\n--verbose_explanations\n# Ignore CMake usual build directory\nbuild\n# Ignore Vim files\n*.swp\n# Ignore QtCreator Project file\nCMakeLists.txt.user\n# Ignore VS Code files\n.vscode/*\n# Ignore generated python artifacts\n*.pyc\ncopts/__pycache__/\n"
  },
  {
    "path": "ABSEIL_ISSUE_TEMPLATE.md",
    "content": "Please submit a new Abseil Issue using the template below:\n\n## [Short title of proposed API change(s)]\n\n--------------------------------------------------------------------------------\n--------------------------------------------------------------------------------\n\n## Background\n\n[Provide the background information that is required in order to evaluate the\nproposed API changes. No controversial claims should be made here. If there are\ndesign constraints that need to be considered, they should be presented here\n**along with justification for those constraints**. Linking to other docs is\ngood, but please keep the **pertinent information as self contained** as\npossible in this section.]\n\n## Proposed API Change (s)\n\n[Please clearly describe the API change(s) being proposed. If multiple changes,\nplease keep them clearly distinguished. When possible, **use example code\nsnippets to illustrate before-after API usages**. List pros-n-cons. Highlight\nthe main questions that you want to be answered. Given the Abseil project compatibility requirements, describe why the API change is safe.]\n"
  },
  {
    "path": "AUTHORS",
    "content": "# This is the list of Abseil authors for copyright purposes.\n#\n# This does not necessarily list everyone who has contributed code, since in\n# some cases, their employer may be the copyright holder.  To see the full list\n# of contributors, see the revision history in source control.\nGoogle Inc.\n"
  },
  {
    "path": "BUILD.bazel",
    "content": "# Copyright 2020 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\npackage(default_visibility = [\"//visibility:public\"])\n\nlicenses([\"notice\"])  # Apache 2.0\n\n# Expose license for external usage through bazel.\nexports_files([\n    \"AUTHORS\",\n    \"LICENSE\",\n])\n\n# For building with clang-cl.\n# https://bazel.build/configure/windows#clang\nplatform(\n    name = \"x64_windows-clang-cl\",\n    constraint_values = [\n        \"@platforms//cpu:x86_64\",\n        \"@platforms//os:windows\",\n        \"@bazel_tools//tools/cpp:clang-cl\",\n    ],\n)\n"
  },
  {
    "path": "CMake/AbseilDll.cmake",
    "content": "include(CMakeParseArguments)\ninclude(GNUInstallDirs)\n\nset(ABSL_INTERNAL_DLL_FILES\n  \"algorithm/algorithm.h\"\n  \"algorithm/container.h\"\n  \"base/attributes.h\"\n  \"base/call_once.h\"\n  \"base/casts.cc\"\n  \"base/casts.h\"\n  \"base/config.h\"\n  \"base/const_init.h\"\n  \"base/dynamic_annotations.h\"\n  \"base/fast_type_id.h\"\n  \"base/internal/atomic_hook.h\"\n  \"base/internal/cycleclock.cc\"\n  \"base/internal/cycleclock.h\"\n  \"base/internal/cycleclock_config.h\"\n  \"base/internal/direct_mmap.h\"\n  \"base/internal/dynamic_annotations.h\"\n  \"base/internal/endian.h\"\n  \"base/internal/errno_saver.h\"\n  \"base/internal/hardening.cc\"\n  \"base/internal/hardening.h\"\n  \"base/internal/hide_ptr.h\"\n  \"base/internal/iterator_traits.h\"\n  \"base/internal/low_level_alloc.cc\"\n  \"base/internal/low_level_alloc.h\"\n  \"base/internal/low_level_scheduling.h\"\n  \"base/internal/nullability_traits.h\"\n  \"base/internal/per_thread_tls.h\"\n  \"base/internal/poison.cc\"\n  \"base/internal/poison.h\"\n  \"base/internal/pretty_function.h\"\n  \"base/internal/raw_logging.cc\"\n  \"base/internal/raw_logging.h\"\n  \"base/internal/scheduling_mode.h\"\n  \"base/internal/scoped_set_env.cc\"\n  \"base/internal/scoped_set_env.h\"\n  \"base/internal/spinlock.cc\"\n  \"base/internal/spinlock.h\"\n  \"base/internal/spinlock_wait.cc\"\n  \"base/internal/spinlock_wait.h\"\n  \"base/internal/strerror.cc\"\n  \"base/internal/strerror.h\"\n  \"base/internal/sysinfo.cc\"\n  \"base/internal/sysinfo.h\"\n  \"base/internal/thread_identity.cc\"\n  \"base/internal/thread_identity.h\"\n  \"base/internal/tracing.cc\"\n  \"base/internal/tracing.h\"\n  \"base/internal/tsan_mutex_interface.h\"\n  \"base/internal/unaligned_access.h\"\n  \"base/internal/unscaledcycleclock.cc\"\n  \"base/internal/unscaledcycleclock.h\"\n  \"base/internal/unscaledcycleclock_config.h\"\n  \"base/log_severity.cc\"\n  \"base/log_severity.h\"\n  \"base/macros.h\"\n  \"base/no_destructor.h\"\n  \"base/nullability.h\"\n  \"base/optimization.h\"\n  \"base/options.h\"\n  \"base/policy_checks.h\"\n  \"base/port.h\"\n  \"base/prefetch.h\"\n  \"base/thread_annotations.h\"\n  \"base/throw_delegate.cc\"\n  \"base/throw_delegate.h\"\n  \"cleanup/cleanup.h\"\n  \"cleanup/internal/cleanup.h\"\n  \"container/btree_map.h\"\n  \"container/btree_set.h\"\n  \"container/chunked_queue.h\"\n  \"container/fixed_array.h\"\n  \"container/flat_hash_map.h\"\n  \"container/flat_hash_set.h\"\n  \"container/hash_container_defaults.h\"\n  \"container/inlined_vector.h\"\n  \"container/internal/btree.h\"\n  \"container/internal/btree_container.h\"\n  \"container/internal/chunked_queue.h\"\n  \"container/internal/common.h\"\n  \"container/internal/common_policy_traits.h\"\n  \"container/internal/compressed_tuple.h\"\n  \"container/internal/container_memory.h\"\n  \"container/internal/hash_function_defaults.h\"\n  \"container/internal/hash_policy_traits.h\"\n  \"container/internal/hashtable_control_bytes.h\"\n  \"container/internal/hashtable_debug.h\"\n  \"container/internal/hashtable_debug_hooks.h\"\n  \"container/internal/hashtablez_sampler.cc\"\n  \"container/internal/hashtablez_sampler.h\"\n  \"container/internal/hashtablez_sampler_force_weak_definition.cc\"\n  \"container/internal/inlined_vector.h\"\n  \"container/internal/layout.h\"\n  \"container/internal/node_slot_policy.h\"\n  \"container/internal/raw_hash_map.h\"\n  \"container/internal/raw_hash_set.cc\"\n  \"container/internal/raw_hash_set.h\"\n  \"container/internal/raw_hash_set_resize_impl.h\"\n  \"container/internal/tracked.h\"\n  \"container/linked_hash_map.h\"\n  \"container/linked_hash_set.h\"\n  \"container/node_hash_map.h\"\n  \"container/node_hash_set.h\"\n  \"crc/crc32c.cc\"\n  \"crc/crc32c.h\"\n  \"crc/internal/cpu_detect.cc\"\n  \"crc/internal/cpu_detect.h\"\n  \"crc/internal/crc.cc\"\n  \"crc/internal/crc.h\"\n  \"crc/internal/crc32_x86_arm_combined_simd.h\"\n  \"crc/internal/crc32c.h\"\n  \"crc/internal/crc32c_inline.h\"\n  \"crc/internal/crc_cord_state.cc\"\n  \"crc/internal/crc_cord_state.h\"\n  \"crc/internal/crc_internal.h\"\n  \"crc/internal/crc_memcpy.h\"\n  \"crc/internal/crc_memcpy_fallback.cc\"\n  \"crc/internal/crc_memcpy_x86_arm_combined.cc\"\n  \"crc/internal/crc_non_temporal_memcpy.cc\"\n  \"crc/internal/crc_x86_arm_combined.cc\"\n  \"crc/internal/non_temporal_arm_intrinsics.h\"\n  \"crc/internal/non_temporal_memcpy.h\"\n  \"debugging/failure_signal_handler.cc\"\n  \"debugging/failure_signal_handler.h\"\n  \"debugging/internal/address_is_readable.cc\"\n  \"debugging/internal/address_is_readable.h\"\n  \"debugging/internal/addresses.h\"\n  \"debugging/internal/bounded_utf8_length_sequence.h\"\n  \"debugging/internal/decode_rust_punycode.cc\"\n  \"debugging/internal/decode_rust_punycode.h\"\n  \"debugging/internal/demangle.cc\"\n  \"debugging/internal/demangle.h\"\n  \"debugging/internal/demangle_rust.cc\"\n  \"debugging/internal/demangle_rust.h\"\n  \"debugging/internal/elf_mem_image.cc\"\n  \"debugging/internal/elf_mem_image.h\"\n  \"debugging/internal/examine_stack.cc\"\n  \"debugging/internal/examine_stack.h\"\n  \"debugging/internal/stack_consumption.cc\"\n  \"debugging/internal/stack_consumption.h\"\n  \"debugging/internal/stacktrace_config.h\"\n  \"debugging/internal/symbolize.h\"\n  \"debugging/internal/utf8_for_code_point.cc\"\n  \"debugging/internal/utf8_for_code_point.h\"\n  \"debugging/internal/vdso_support.cc\"\n  \"debugging/internal/vdso_support.h\"\n  \"debugging/leak_check.h\"\n  \"debugging/stacktrace.cc\"\n  \"debugging/stacktrace.h\"\n  \"debugging/symbolize.cc\"\n  \"debugging/symbolize.h\"\n  \"functional/any_invocable.h\"\n  \"functional/bind_front.h\"\n  \"functional/function_ref.h\"\n  \"functional/internal/any_invocable.h\"\n  \"functional/internal/front_binder.h\"\n  \"functional/internal/function_ref.h\"\n  \"functional/overload.h\"\n  \"hash/hash.h\"\n  \"hash/internal/city.cc\"\n  \"hash/internal/city.h\"\n  \"hash/internal/hash.cc\"\n  \"hash/internal/hash.h\"\n  \"hash/internal/spy_hash_state.h\"\n  \"hash/internal/weakly_mixed_integer.h\"\n  \"log/absl_check.h\"\n  \"log/absl_log.h\"\n  \"log/absl_vlog_is_on.h\"\n  \"log/check.h\"\n  \"log/die_if_null.cc\"\n  \"log/die_if_null.h\"\n  \"log/globals.cc\"\n  \"log/globals.h\"\n  \"log/initialize.cc\"\n  \"log/initialize.h\"\n  \"log/internal/append_truncated.h\"\n  \"log/internal/check_impl.h\"\n  \"log/internal/check_op.cc\"\n  \"log/internal/check_op.h\"\n  \"log/internal/conditions.cc\"\n  \"log/internal/conditions.h\"\n  \"log/internal/config.h\"\n  \"log/internal/container.h\"\n  \"log/internal/fnmatch.cc\"\n  \"log/internal/fnmatch.h\"\n  \"log/internal/globals.cc\"\n  \"log/internal/globals.h\"\n  \"log/internal/log_format.cc\"\n  \"log/internal/log_format.h\"\n  \"log/internal/log_impl.h\"\n  \"log/internal/log_message.cc\"\n  \"log/internal/log_message.h\"\n  \"log/internal/log_sink_set.cc\"\n  \"log/internal/log_sink_set.h\"\n  \"log/internal/nullguard.cc\"\n  \"log/internal/nullguard.h\"\n  \"log/internal/nullstream.h\"\n  \"log/internal/proto.cc\"\n  \"log/internal/proto.h\"\n  \"log/internal/strip.h\"\n  \"log/internal/structured.h\"\n  \"log/internal/structured_proto.cc\"\n  \"log/internal/structured_proto.h\"\n  \"log/internal/vlog_config.cc\"\n  \"log/internal/vlog_config.h\"\n  \"log/internal/voidify.h\"\n  \"log/log.h\"\n  \"log/log_entry.cc\"\n  \"log/log_entry.h\"\n  \"log/log_sink.cc\"\n  \"log/log_sink.h\"\n  \"log/log_sink_registry.h\"\n  \"log/log_streamer.h\"\n  \"log/structured.h\"\n  \"log/vlog_is_on.h\"\n  \"memory/memory.h\"\n  \"meta/internal/requires.h\"\n  \"meta/type_traits.h\"\n  \"numeric/bits.h\"\n  \"numeric/int128.cc\"\n  \"numeric/int128.h\"\n  \"numeric/internal/bits.h\"\n  \"numeric/internal/representation.h\"\n  \"profiling/hashtable.cc\"\n  \"profiling/hashtable.h\"\n  \"profiling/internal/exponential_biased.cc\"\n  \"profiling/internal/exponential_biased.h\"\n  \"profiling/internal/periodic_sampler.cc\"\n  \"profiling/internal/periodic_sampler.h\"\n  \"profiling/internal/profile_builder.cc\"\n  \"profiling/internal/profile_builder.h\"\n  \"profiling/internal/sample_recorder.h\"\n  \"random/bernoulli_distribution.h\"\n  \"random/beta_distribution.h\"\n  \"random/bit_gen_ref.h\"\n  \"random/discrete_distribution.cc\"\n  \"random/discrete_distribution.h\"\n  \"random/distributions.h\"\n  \"random/exponential_distribution.h\"\n  \"random/gaussian_distribution.cc\"\n  \"random/gaussian_distribution.h\"\n  \"random/internal/distribution_caller.h\"\n  \"random/internal/entropy_pool.cc\"\n  \"random/internal/entropy_pool.h\"\n  \"random/internal/fast_uniform_bits.h\"\n  \"random/internal/fastmath.h\"\n  \"random/internal/generate_real.h\"\n  \"random/internal/iostream_state_saver.h\"\n  \"random/internal/nonsecure_base.h\"\n  \"random/internal/pcg_engine.h\"\n  \"random/internal/platform.h\"\n  \"random/internal/randen.cc\"\n  \"random/internal/randen.h\"\n  \"random/internal/randen_detect.cc\"\n  \"random/internal/randen_detect.h\"\n  \"random/internal/randen_engine.h\"\n  \"random/internal/randen_hwaes.cc\"\n  \"random/internal/randen_hwaes.h\"\n  \"random/internal/randen_round_keys.cc\"\n  \"random/internal/randen_slow.cc\"\n  \"random/internal/randen_slow.h\"\n  \"random/internal/randen_traits.h\"\n  \"random/internal/salted_seed_seq.h\"\n  \"random/internal/seed_material.cc\"\n  \"random/internal/seed_material.h\"\n  \"random/internal/sequence_urbg.h\"\n  \"random/internal/traits.h\"\n  \"random/internal/uniform_helper.h\"\n  \"random/internal/wide_multiply.h\"\n  \"random/log_uniform_int_distribution.h\"\n  \"random/poisson_distribution.h\"\n  \"random/random.h\"\n  \"random/seed_gen_exception.cc\"\n  \"random/seed_gen_exception.h\"\n  \"random/seed_sequences.cc\"\n  \"random/seed_sequences.h\"\n  \"random/uniform_int_distribution.h\"\n  \"random/uniform_real_distribution.h\"\n  \"random/zipf_distribution.h\"\n  \"status/internal/status_internal.cc\"\n  \"status/internal/status_internal.h\"\n  \"status/internal/statusor_internal.h\"\n  \"status/status.cc\"\n  \"status/status.h\"\n  \"status/status_payload_printer.cc\"\n  \"status/status_payload_printer.h\"\n  \"status/statusor.cc\"\n  \"status/statusor.h\"\n  \"strings/ascii.cc\"\n  \"strings/ascii.h\"\n  \"strings/charconv.cc\"\n  \"strings/charconv.h\"\n  \"strings/charset.h\"\n  \"strings/cord.cc\"\n  \"strings/cord.h\"\n  \"strings/cord_analysis.cc\"\n  \"strings/cord_analysis.h\"\n  \"strings/cord_buffer.h\"\n  \"strings/escaping.cc\"\n  \"strings/escaping.h\"\n  \"strings/has_absl_stringify.h\"\n  \"strings/has_ostream_operator.h\"\n  \"strings/internal/append_and_overwrite.h\"\n  \"strings/internal/charconv_bigint.cc\"\n  \"strings/internal/charconv_bigint.h\"\n  \"strings/internal/charconv_parse.cc\"\n  \"strings/internal/charconv_parse.h\"\n  \"strings/internal/cord_data_edge.h\"\n  \"strings/internal/cord_internal.cc\"\n  \"strings/internal/cord_internal.h\"\n  \"strings/internal/cord_rep_btree.cc\"\n  \"strings/internal/cord_rep_btree.h\"\n  \"strings/internal/cord_rep_btree_navigator.cc\"\n  \"strings/internal/cord_rep_btree_navigator.h\"\n  \"strings/internal/cord_rep_btree_reader.cc\"\n  \"strings/internal/cord_rep_btree_reader.h\"\n  \"strings/internal/cord_rep_consume.cc\"\n  \"strings/internal/cord_rep_consume.h\"\n  \"strings/internal/cord_rep_crc.cc\"\n  \"strings/internal/cord_rep_crc.h\"\n  \"strings/internal/cord_rep_flat.h\"\n  \"strings/internal/cordz_functions.cc\"\n  \"strings/internal/cordz_functions.h\"\n  \"strings/internal/cordz_handle.cc\"\n  \"strings/internal/cordz_handle.h\"\n  \"strings/internal/cordz_info.cc\"\n  \"strings/internal/cordz_info.h\"\n  \"strings/internal/cordz_sample_token.cc\"\n  \"strings/internal/cordz_sample_token.h\"\n  \"strings/internal/cordz_statistics.h\"\n  \"strings/internal/cordz_update_scope.h\"\n  \"strings/internal/cordz_update_tracker.h\"\n  \"strings/internal/damerau_levenshtein_distance.cc\"\n  \"strings/internal/damerau_levenshtein_distance.h\"\n  \"strings/internal/escaping.cc\"\n  \"strings/internal/escaping.h\"\n  \"strings/internal/generic_printer.cc\"\n  \"strings/internal/generic_printer.h\"\n  \"strings/internal/generic_printer_internal.h\"\n  \"strings/internal/memutil.cc\"\n  \"strings/internal/memutil.h\"\n  \"strings/internal/ostringstream.cc\"\n  \"strings/internal/ostringstream.h\"\n  \"strings/internal/pow10_helper.cc\"\n  \"strings/internal/pow10_helper.h\"\n  \"strings/internal/resize_uninitialized.h\"\n  \"strings/internal/stl_type_traits.h\"\n  \"strings/internal/str_format/arg.cc\"\n  \"strings/internal/str_format/arg.h\"\n  \"strings/internal/str_format/bind.cc\"\n  \"strings/internal/str_format/bind.h\"\n  \"strings/internal/str_format/checker.h\"\n  \"strings/internal/str_format/constexpr_parser.h\"\n  \"strings/internal/str_format/extension.cc\"\n  \"strings/internal/str_format/extension.h\"\n  \"strings/internal/str_format/float_conversion.cc\"\n  \"strings/internal/str_format/float_conversion.h\"\n  \"strings/internal/str_format/output.cc\"\n  \"strings/internal/str_format/output.h\"\n  \"strings/internal/str_format/parser.cc\"\n  \"strings/internal/str_format/parser.h\"\n  \"strings/internal/str_join_internal.h\"\n  \"strings/internal/str_split_internal.h\"\n  \"strings/internal/string_constant.h\"\n  \"strings/internal/stringify_sink.cc\"\n  \"strings/internal/stringify_sink.h\"\n  \"strings/internal/stringify_stream.h\"\n  \"strings/internal/utf8.cc\"\n  \"strings/internal/utf8.h\"\n  \"strings/match.cc\"\n  \"strings/match.h\"\n  \"strings/numbers.cc\"\n  \"strings/numbers.h\"\n  \"strings/resize_and_overwrite.h\"\n  \"strings/str_cat.cc\"\n  \"strings/str_cat.h\"\n  \"strings/str_format.h\"\n  \"strings/str_join.h\"\n  \"strings/str_replace.cc\"\n  \"strings/str_replace.h\"\n  \"strings/str_split.cc\"\n  \"strings/str_split.h\"\n  \"strings/strip.h\"\n  \"strings/substitute.cc\"\n  \"strings/substitute.h\"\n  \"synchronization/barrier.cc\"\n  \"synchronization/barrier.h\"\n  \"synchronization/blocking_counter.cc\"\n  \"synchronization/blocking_counter.h\"\n  \"synchronization/internal/create_thread_identity.cc\"\n  \"synchronization/internal/create_thread_identity.h\"\n  \"synchronization/internal/futex.h\"\n  \"synchronization/internal/futex_waiter.cc\"\n  \"synchronization/internal/futex_waiter.h\"\n  \"synchronization/internal/graphcycles.cc\"\n  \"synchronization/internal/graphcycles.h\"\n  \"synchronization/internal/kernel_timeout.cc\"\n  \"synchronization/internal/kernel_timeout.h\"\n  \"synchronization/internal/per_thread_sem.cc\"\n  \"synchronization/internal/per_thread_sem.h\"\n  \"synchronization/internal/pthread_waiter.cc\"\n  \"synchronization/internal/pthread_waiter.h\"\n  \"synchronization/internal/sem_waiter.cc\"\n  \"synchronization/internal/sem_waiter.h\"\n  \"synchronization/internal/stdcpp_waiter.cc\"\n  \"synchronization/internal/stdcpp_waiter.h\"\n  \"synchronization/internal/thread_pool.h\"\n  \"synchronization/internal/waiter.h\"\n  \"synchronization/internal/waiter_base.cc\"\n  \"synchronization/internal/waiter_base.h\"\n  \"synchronization/internal/win32_waiter.cc\"\n  \"synchronization/internal/win32_waiter.h\"\n  \"synchronization/mutex.cc\"\n  \"synchronization/mutex.h\"\n  \"synchronization/notification.cc\"\n  \"synchronization/notification.h\"\n  \"time/civil_time.cc\"\n  \"time/civil_time.h\"\n  \"time/clock.cc\"\n  \"time/clock.h\"\n  \"time/clock_interface.cc\"\n  \"time/clock_interface.h\"\n  \"time/duration.cc\"\n  \"time/format.cc\"\n  \"time/internal/cctz/include/cctz/civil_time.h\"\n  \"time/internal/cctz/include/cctz/civil_time_detail.h\"\n  \"time/internal/cctz/include/cctz/time_zone.h\"\n  \"time/internal/cctz/include/cctz/zone_info_source.h\"\n  \"time/internal/cctz/src/civil_time_detail.cc\"\n  \"time/internal/cctz/src/time_zone_fixed.cc\"\n  \"time/internal/cctz/src/time_zone_fixed.h\"\n  \"time/internal/cctz/src/time_zone_format.cc\"\n  \"time/internal/cctz/src/time_zone_if.cc\"\n  \"time/internal/cctz/src/time_zone_if.h\"\n  \"time/internal/cctz/src/time_zone_impl.cc\"\n  \"time/internal/cctz/src/time_zone_impl.h\"\n  \"time/internal/cctz/src/time_zone_info.cc\"\n  \"time/internal/cctz/src/time_zone_info.h\"\n  \"time/internal/cctz/src/time_zone_libc.cc\"\n  \"time/internal/cctz/src/time_zone_libc.h\"\n  \"time/internal/cctz/src/time_zone_lookup.cc\"\n  \"time/internal/cctz/src/time_zone_posix.cc\"\n  \"time/internal/cctz/src/time_zone_posix.h\"\n  \"time/internal/cctz/src/tzfile.h\"\n  \"time/internal/cctz/src/zone_info_source.cc\"\n  \"time/simulated_clock.cc\"\n  \"time/simulated_clock.h\"\n  \"time/time.cc\"\n  \"time/time.h\"\n  \"types/any.h\"\n  \"types/any_span.h\"\n  \"types/compare.h\"\n  \"types/internal/any_span.h\"\n  \"types/internal/span.h\"\n  \"types/optional.h\"\n  \"types/optional_ref.h\"\n  \"types/source_location.h\"\n  \"types/span.h\"\n  \"types/variant.h\"\n  \"utility/utility.h\"\n  \"debugging/leak_check.cc\"\n  \"strings/string_view.h\"\n)\n\nif(MSVC)\n  list(APPEND ABSL_INTERNAL_DLL_FILES\n    \"time/internal/cctz/src/time_zone_name_win.cc\"\n    \"time/internal/cctz/src/time_zone_name_win.h\"\n  )\nelse()\n  list(APPEND ABSL_INTERNAL_DLL_FILES\n    \"flags/commandlineflag.cc\"\n    \"flags/commandlineflag.h\"\n    \"flags/config.h\"\n    \"flags/declare.h\"\n    \"flags/flag.h\"\n    \"flags/internal/commandlineflag.cc\"\n    \"flags/internal/commandlineflag.h\"\n    \"flags/internal/flag.cc\"\n    \"flags/internal/flag.h\"\n    \"flags/internal/parse.h\"\n    \"flags/internal/path_util.h\"\n    \"flags/internal/private_handle_accessor.cc\"\n    \"flags/internal/private_handle_accessor.h\"\n    \"flags/internal/program_name.cc\"\n    \"flags/internal/program_name.h\"\n    \"flags/internal/registry.h\"\n    \"flags/internal/sequence_lock.h\"\n    \"flags/internal/usage.cc\"\n    \"flags/internal/usage.h\"\n    \"flags/marshalling.cc\"\n    \"flags/marshalling.h\"\n    \"flags/parse.cc\"\n    \"flags/parse.h\"\n    \"flags/reflection.cc\"\n    \"flags/reflection.h\"\n    \"flags/usage.cc\"\n    \"flags/usage.h\"\n    \"flags/usage_config.cc\"\n    \"flags/usage_config.h\"\n    \"log/flags.cc\"\n    \"log/flags.h\"\n    \"log/internal/flags.h\"\n  )\nendif()\n\nset(ABSL_INTERNAL_DLL_TARGETS\n  \"absl_check\"\n  \"absl_log\"\n  \"absl_vlog_is_on\"\n  \"algorithm\"\n  \"algorithm_container\"\n  \"any\"\n  \"any_invocable\"\n  \"atomic_hook\"\n  \"base\"\n  \"base_internal\"\n  \"bind_front\"\n  \"bits\"\n  \"btree\"\n  \"check\"\n  \"city\"\n  \"civil_time\"\n  \"compare\"\n  \"compressed_tuple\"\n  \"config\"\n  \"container\"\n  \"container_common\"\n  \"container_memory\"\n  \"cord\"\n  \"cord_internal\"\n  \"cordz_functions\"\n  \"cordz_handle\"\n  \"cordz_info\"\n  \"cordz_sample_token\"\n  \"core_headers\"\n  \"counting_allocator\"\n  \"crc_cord_state\"\n  \"crc_cpu_detect\"\n  \"crc_internal\"\n  \"crc32c\"\n  \"debugging\"\n  \"debugging_internal\"\n  \"demangle_internal\"\n  \"die_if_null\"\n  \"dynamic_annotations\"\n  \"endian\"\n  \"examine_stack\"\n  \"exponential_biased\"\n  \"failure_signal_handler\"\n  \"fixed_array\"\n  \"flat_hash_map\"\n  \"flat_hash_set\"\n  \"function_ref\"\n  \"graphcycles_internal\"\n  \"hash\"\n  \"hash_function_defaults\"\n  \"hash_policy_traits\"\n  \"hashtable_debug\"\n  \"hashtable_debug_hooks\"\n  \"hashtablez_sampler\"\n  \"inlined_vector\"\n  \"inlined_vector_internal\"\n  \"int128\"\n  \"kernel_timeout_internal\"\n  \"layout\"\n  \"leak_check\"\n  \"log_internal_check_impl\"\n  \"log_internal_check_op\"\n  \"log_internal_conditions\"\n  \"log_internal_config\"\n  \"log_internal_fnmatch\"\n  \"log_internal_format\"\n  \"log_internal_globals\"\n  \"log_internal_log_impl\"\n  \"log_internal_proto\"\n  \"log_internal_message\"\n  \"log_internal_log_sink_set\"\n  \"log_internal_nullguard\"\n  \"log_internal_nullstream\"\n  \"log_internal_strip\"\n  \"log_internal_voidify\"\n  \"log_internal_append_truncated\"\n  \"log_globals\"\n  \"log_initialize\"\n  \"log\"\n  \"log_entry\"\n  \"log_sink\"\n  \"log_sink_registry\"\n  \"log_streamer\"\n  \"log_internal_structured\"\n  \"log_severity\"\n  \"log_structured\"\n  \"low_level_hash\"\n  \"malloc_internal\"\n  \"memory\"\n  \"meta\"\n  \"node_hash_map\"\n  \"node_hash_set\"\n  \"node_slot_policy\"\n  \"non_temporal_arm_intrinsics\"\n  \"non_temporal_memcpy\"\n  \"numeric\"\n  \"optional\"\n  \"periodic_sampler\"\n  \"pow10_helper\"\n  \"pretty_function\"\n  \"random_bit_gen_ref\"\n  \"random_distributions\"\n  \"random_internal_distribution_caller\"\n  \"random_internal_distributions\"\n  \"random_internal_explicit_seed_seq\"\n  \"random_internal_fastmath\"\n  \"random_internal_fast_uniform_bits\"\n  \"random_internal_generate_real\"\n  \"random_internal_iostream_state_saver\"\n  \"random_internal_nonsecure_base\"\n  \"random_internal_pcg_engine\"\n  \"random_internal_platform\"\n  \"random_internal_pool_urbg\"\n  \"random_internal_randen\"\n  \"random_internal_randen_engine\"\n  \"random_internal_randen_hwaes\"\n  \"random_internal_randen_hwaes_impl\"\n  \"random_internal_randen_slow\"\n  \"random_internal_salted_seed_seq\"\n  \"random_internal_seed_material\"\n  \"random_internal_sequence_urbg\"\n  \"random_internal_traits\"\n  \"random_internal_uniform_helper\"\n  \"random_internal_wide_multiply\"\n  \"random_random\"\n  \"random_seed_gen_exception\"\n  \"random_seed_sequences\"\n  \"raw_hash_map\"\n  \"raw_hash_set\"\n  \"raw_logging_internal\"\n  \"sample_recorder\"\n  \"scoped_set_env\"\n  \"span\"\n  \"spinlock_wait\"\n  \"spy_hash_state\"\n  \"stack_consumption\"\n  \"stacktrace\"\n  \"status\"\n  \"statusor\"\n  \"str_format\"\n  \"str_format_internal\"\n  \"strerror\"\n  \"strings\"\n  \"strings_internal\"\n  \"string_view\"\n  \"symbolize\"\n  \"synchronization\"\n  \"thread_pool\"\n  \"throw_delegate\"\n  \"time\"\n  \"time_zone\"\n  \"tracked\"\n  \"type_traits\"\n  \"utility\"\n  \"variant\"\n  \"vlog_config_internal\"\n  \"vlog_is_on\"\n)\n\nif(NOT MSVC)\n  list(APPEND ABSL_INTERNAL_DLL_TARGETS\n    \"flags\"\n    \"flags_commandlineflag\"\n    \"flags_commandlineflag_internal\"\n    \"flags_config\"\n    \"flags_internal\"\n    \"flags_marshalling\"\n    \"flags_parse\"\n    \"flags_path_util\"\n    \"flags_private_handle_accessor\"\n    \"flags_program_name\"\n    \"flags_reflection\"\n    \"flags_usage\"\n    \"flags_usage_internal\"\n    \"log_internal_flags\"\n    \"log_flags\"\n  )\nendif()\n\nset(ABSL_INTERNAL_TEST_DLL_FILES\n  \"hash/hash_testing.h\"\n  \"log/scoped_mock_log.cc\"\n  \"log/scoped_mock_log.h\"\n  \"random/internal/chi_square.cc\"\n  \"random/internal/chi_square.h\"\n  \"random/internal/distribution_test_util.cc\"\n  \"random/internal/distribution_test_util.h\"\n  \"random/internal/mock_helpers.h\"\n  \"random/internal/mock_overload_set.h\"\n  \"random/mocking_bit_gen.h\"\n  \"random/mock_distributions.h\"\n  \"status/status_matchers.h\"\n  \"status/internal/status_matchers.cc\"\n  \"status/internal/status_matchers.h\"\n  \"strings/cordz_test_helpers.h\"\n  \"strings/cord_test_helpers.h\"\n)\n\nset(ABSL_INTERNAL_TEST_DLL_TARGETS\n  \"cord_test_helpers\"\n  \"cordz_test_helpers\"\n  \"hash_testing\"\n  \"random_mocking_bit_gen\"\n  \"random_internal_distribution_test_util\"\n  \"random_internal_mock_overload_set\"\n  \"scoped_mock_log\"\n  \"status_matchers\"\n)\n\ninclude(CheckCXXSourceCompiles)\n\ncheck_cxx_source_compiles(\n  [==[\n#ifdef _MSC_VER\n#  if _MSVC_LANG < 201703L\n#    error \"The compiler defaults or is configured for C++ < 17\"\n#  endif\n#elif __cplusplus < 201703L\n#  error \"The compiler defaults or is configured for C++ < 17\"\n#endif\nint main() { return 0; }\n]==]\n  ABSL_INTERNAL_AT_LEAST_CXX17)\n\ncheck_cxx_source_compiles(\n  [==[\n#ifdef _MSC_VER\n#  if _MSVC_LANG < 202002L\n#    error \"The compiler defaults or is configured for C++ < 20\"\n#  endif\n#elif __cplusplus < 202002L\n#  error \"The compiler defaults or is configured for C++ < 20\"\n#endif\nint main() { return 0; }\n]==]\n  ABSL_INTERNAL_AT_LEAST_CXX20)\n\nif(ABSL_INTERNAL_AT_LEAST_CXX20)\n  set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20)\nelseif(ABSL_INTERNAL_AT_LEAST_CXX17)\n  set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17)\nelse()\n  message(FATAL_ERROR \"The compiler defaults to or is configured for C++ < 17. C++ >= 17 is required and Abseil and all libraries that use Abseil must use the same C++ language standard\")\nendif()\n\nfunction(absl_internal_dll_contains)\n  cmake_parse_arguments(ABSL_INTERNAL_DLL\n    \"\"\n    \"OUTPUT;TARGET\"\n    \"\"\n    ${ARGN}\n  )\n\n  STRING(REGEX REPLACE \"^absl::\" \"\" _target ${ABSL_INTERNAL_DLL_TARGET})\n\n  if (_target IN_LIST ABSL_INTERNAL_DLL_TARGETS)\n    set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE)\n  else()\n    set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE)\n  endif()\nendfunction()\n\nfunction(absl_internal_test_dll_contains)\n  cmake_parse_arguments(ABSL_INTERNAL_TEST_DLL\n    \"\"\n    \"OUTPUT;TARGET\"\n    \"\"\n    ${ARGN}\n  )\n\n  STRING(REGEX REPLACE \"^absl::\" \"\" _target ${ABSL_INTERNAL_TEST_DLL_TARGET})\n\n  if (_target IN_LIST ABSL_INTERNAL_TEST_DLL_TARGETS)\n    set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 1 PARENT_SCOPE)\n  else()\n    set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 0 PARENT_SCOPE)\n  endif()\nendfunction()\n\nfunction(absl_internal_dll_targets)\n  cmake_parse_arguments(ABSL_INTERNAL_DLL\n  \"\"\n  \"OUTPUT\"\n  \"DEPS\"\n  ${ARGN}\n  )\n\n  set(_deps \"\")\n  foreach(dep IN LISTS ABSL_INTERNAL_DLL_DEPS)\n    absl_internal_dll_contains(TARGET ${dep} OUTPUT _dll_contains)\n    absl_internal_test_dll_contains(TARGET ${dep} OUTPUT _test_dll_contains)\n    if (_dll_contains)\n      list(APPEND _deps abseil_dll)\n    elseif (_test_dll_contains)\n      list(APPEND _deps abseil_test_dll)\n    else()\n      list(APPEND _deps ${dep})\n    endif()\n  endforeach()\n\n  # Because we may have added the DLL multiple times\n  list(REMOVE_DUPLICATES _deps)\n  set(${ABSL_INTERNAL_DLL_OUTPUT} \"${_deps}\" PARENT_SCOPE)\nendfunction()\n\nfunction(absl_make_dll)\n  cmake_parse_arguments(ABSL_INTERNAL_MAKE_DLL\n  \"\"\n  \"TEST\"\n  \"\"\n  ${ARGN}\n  )\n\n  if (ABSL_INTERNAL_MAKE_DLL_TEST)\n    set(_dll \"abseil_test_dll\")\n    set(_dll_files ${ABSL_INTERNAL_TEST_DLL_FILES})\n    set(_dll_libs \"abseil_dll\" \"GTest::gtest\" \"GTest::gmock\")\n    set(_dll_compile_definitions \"GTEST_LINKED_AS_SHARED_LIBRARY=1\")\n    set(_dll_includes ${absl_gtest_src_dir}/googletest/include ${absl_gtest_src_dir}/googlemock/include)\n    set(_dll_consume \"ABSL_CONSUME_TEST_DLL\")\n    set(_dll_build \"ABSL_BUILD_TEST_DLL\")\n  else()\n    set(_dll \"abseil_dll\")\n    set(_dll_files ${ABSL_INTERNAL_DLL_FILES})\n    set(_dll_libs\n      Threads::Threads\n      # TODO(#1495): Use $<LINK_LIBRARY:FRAMEWORK,CoreFoundation> once our\n      # minimum CMake version >= 3.24\n      $<$<PLATFORM_ID:Darwin>:-Wl,-framework,CoreFoundation>\n    )\n    set(_dll_compile_definitions \"\")\n    set(_dll_includes \"\")\n    set(_dll_consume \"ABSL_CONSUME_DLL\")\n    set(_dll_build \"ABSL_BUILD_DLL\")\n  endif()\n\n  add_library(\n    ${_dll}\n    SHARED\n      ${_dll_files}\n  )\n  target_link_libraries(\n    ${_dll}\n    PRIVATE\n      ${_dll_libs}\n      ${ABSL_DEFAULT_LINKOPTS}\n      $<$<BOOL:${ANDROID}>:-llog>\n      $<$<BOOL:${MINGW}>:-ladvapi32>\n      $<$<BOOL:${MINGW}>:-ldbghelp>\n      $<$<BOOL:${MINGW}>:-lbcrypt>\n  )\n  set_target_properties(${_dll} PROPERTIES\n    LINKER_LANGUAGE \"CXX\"\n    SOVERSION ${ABSL_SOVERSION}\n  )\n  target_include_directories(\n    ${_dll}\n    PUBLIC\n      \"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>\"\n      $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>\n    PRIVATE\n      ${_dll_includes}\n  )\n\n  target_compile_options(\n    ${_dll}\n    PRIVATE\n      ${ABSL_DEFAULT_COPTS}\n  )\n\n  foreach(cflag ${ABSL_CC_LIB_COPTS})\n    if(${cflag} MATCHES \"^(-Wno|/wd)\")\n      # These flags are needed to suppress warnings that might fire in our headers.\n      set(PC_CFLAGS \"${PC_CFLAGS} ${cflag}\")\n    elseif(${cflag} MATCHES \"^(-W|/w[1234eo])\")\n      # Don't impose our warnings on others.\n    else()\n      set(PC_CFLAGS \"${PC_CFLAGS} ${cflag}\")\n    endif()\n  endforeach()\n  string(REPLACE \";\" \" \" PC_LINKOPTS \"${ABSL_CC_LIB_LINKOPTS}\")\n\n  FILE(GENERATE OUTPUT \"${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc\" CONTENT \"\\\nprefix=${CMAKE_INSTALL_PREFIX}\\n\\\nexec_prefix=\\${prefix}\\n\\\nlibdir=${CMAKE_INSTALL_FULL_LIBDIR}\\n\\\nincludedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\\n\\\n\\n\\\nName: ${_dll}\\n\\\nDescription: Abseil DLL library\\n\\\nURL: https://abseil.io/\\n\\\nVersion: ${absl_VERSION}\\n\\\nLibs: -L\\${libdir} $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-l${_dll}> ${PC_LINKOPTS}\\n\\\nCflags: -I\\${includedir}${PC_CFLAGS}\\n\")\n  INSTALL(FILES \"${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc\"\n    DESTINATION \"${CMAKE_INSTALL_LIBDIR}/pkgconfig\")\n\n  target_compile_definitions(\n    ${_dll}\n    PUBLIC\n      ${_dll_compile_definitions}\n    PRIVATE\n      ${_dll_build}\n      NOMINMAX\n    INTERFACE\n      ${ABSL_CC_LIB_DEFINES}\n      ${_dll_consume}\n  )\n\n  if(ABSL_PROPAGATE_CXX_STD)\n    # Abseil libraries require C++17 as the current minimum standard. When\n    # compiled with a higher minimum (either because it is the compiler's\n    # default or explicitly requested), then Abseil requires that standard.\n    target_compile_features(${_dll} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})\n  endif()\n\n  install(TARGETS ${_dll} EXPORT ${PROJECT_NAME}Targets\n        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}\n        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}\n  )\n\n  add_library(absl::${_dll} ALIAS ${_dll})\nendfunction()\n"
  },
  {
    "path": "CMake/AbseilHelpers.cmake",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ninclude(CMakeParseArguments)\ninclude(AbseilConfigureCopts)\ninclude(AbseilDll)\n\n# The IDE folder for Abseil that will be used if Abseil is included in a CMake\n# project that sets\n#    set_property(GLOBAL PROPERTY USE_FOLDERS ON)\n# For example, Visual Studio supports folders.\nif(NOT DEFINED ABSL_IDE_FOLDER)\n  set(ABSL_IDE_FOLDER Abseil)\nendif()\n\nif(ABSL_USE_SYSTEM_INCLUDES)\n  set(ABSL_INTERNAL_INCLUDE_WARNING_GUARD SYSTEM)\nelse()\n  set(ABSL_INTERNAL_INCLUDE_WARNING_GUARD \"\")\nendif()\n\n# absl_cc_library()\n#\n# CMake function to imitate Bazel's cc_library rule.\n#\n# Parameters:\n# NAME: name of target (see Note)\n# HDRS: List of public header files for the library\n# SRCS: List of source files for the library\n# DEPS: List of other libraries to be linked in to the binary targets\n# COPTS: List of private compile options\n# DEFINES: List of public defines\n# LINKOPTS: List of link options\n# PUBLIC: Add this so that this library will be exported under absl::\n# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal.\n# TESTONLY: When added, this target will only be built if both\n#           BUILD_TESTING=ON and ABSL_BUILD_TESTING=ON.\n#\n# Note:\n# By default, absl_cc_library will always create a library named absl_${NAME},\n# and alias target absl::${NAME}.  The absl:: form should always be used.\n# This is to reduce namespace pollution.\n#\n# absl_cc_library(\n#   NAME\n#     awesome\n#   HDRS\n#     \"a.h\"\n#   SRCS\n#     \"a.cc\"\n# )\n# absl_cc_library(\n#   NAME\n#     fantastic_lib\n#   SRCS\n#     \"b.cc\"\n#   DEPS\n#     absl::awesome # not \"awesome\" !\n#   PUBLIC\n# )\n#\n# absl_cc_library(\n#   NAME\n#     main_lib\n#   ...\n#   DEPS\n#     absl::fantastic_lib\n# )\n#\n# TODO(b/320467376): Implement \"ALWAYSLINK\".\nfunction(absl_cc_library)\n  cmake_parse_arguments(ABSL_CC_LIB\n    \"DISABLE_INSTALL;PUBLIC;TESTONLY\"\n    \"NAME\"\n    \"HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS\"\n    ${ARGN}\n  )\n\n  if(ABSL_CC_LIB_TESTONLY AND\n      NOT ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR\n        (ABSL_BUILD_TEST_HELPERS AND ABSL_CC_LIB_PUBLIC)))\n    return()\n  endif()\n\n  if(ABSL_ENABLE_INSTALL)\n    set(_NAME \"${ABSL_CC_LIB_NAME}\")\n  else()\n    set(_NAME \"absl_${ABSL_CC_LIB_NAME}\")\n  endif()\n\n  # Check if this is a header-only library\n  # Note that as of February 2019, many popular OS's (for example, Ubuntu\n  # 16.04 LTS) only come with cmake 3.5 by default.  For this reason, we can't\n  # use list(FILTER...)\n  set(ABSL_CC_SRCS \"${ABSL_CC_LIB_SRCS}\")\n  foreach(src_file IN LISTS ABSL_CC_SRCS)\n    if(${src_file} MATCHES \".*\\\\.(h|inc)\")\n      list(REMOVE_ITEM ABSL_CC_SRCS \"${src_file}\")\n    endif()\n  endforeach()\n\n  if(ABSL_CC_SRCS STREQUAL \"\")\n    set(ABSL_CC_LIB_IS_INTERFACE 1)\n  else()\n    set(ABSL_CC_LIB_IS_INTERFACE 0)\n  endif()\n\n  # Determine this build target's relationship to the DLL. It's one of four things:\n  # 1. \"dll\"     -- This target is part of the DLL\n  # 2. \"dll_dep\" -- This target is not part of the DLL, but depends on the DLL.\n  #                 Note that we assume any target not in the DLL depends on the\n  #                 DLL. This is not a technical necessity but a convenience\n  #                 which happens to be true, because nearly every target is\n  #                 part of the DLL.\n  # 3. \"shared\"  -- This is a shared library, perhaps on a non-windows platform\n  #                 where DLL doesn't make sense.\n  # 4. \"static\"  -- This target does not depend on the DLL and should be built\n  #                 statically.\n  if (${ABSL_BUILD_DLL})\n    if(ABSL_ENABLE_INSTALL)\n      absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)\n      absl_internal_test_dll_contains(TARGET ${_NAME} OUTPUT _in_test_dll)\n    else()\n      absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll)\n      absl_internal_test_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_test_dll)\n    endif()\n    if (${_in_dll} OR ${_in_test_dll})\n      # This target should be replaced by the DLL\n      set(_build_type \"dll\")\n      set(ABSL_CC_LIB_IS_INTERFACE 1)\n    else()\n      # Building a DLL, but this target is not part of the DLL\n      set(_build_type \"dll_dep\")\n    endif()\n  elseif(BUILD_SHARED_LIBS)\n    set(_build_type \"shared\")\n  else()\n    set(_build_type \"static\")\n  endif()\n\n  # Generate a pkg-config file for every library:\n  if(ABSL_ENABLE_INSTALL)\n    if(absl_VERSION)\n      set(PC_VERSION \"${absl_VERSION}\")\n    else()\n      set(PC_VERSION \"head\")\n    endif()\n    if(NOT _build_type STREQUAL \"dll\")\n      set(LNK_LIB \"${LNK_LIB} -labsl_${_NAME}\")\n    endif()\n    foreach(dep ${ABSL_CC_LIB_DEPS})\n      if(${dep} MATCHES \"^absl::(.*)\")\n        # for DLL builds many libs are not created, but add\n        # the pkgconfigs nevertheless, pointing to the dll.\n        if(_build_type STREQUAL \"dll\")\n          # hide this MATCHES in an if-clause so it doesn't overwrite\n          # the CMAKE_MATCH_1 from (${dep} MATCHES \"^absl::(.*)\")\n          if(NOT PC_DEPS MATCHES \"abseil_dll\")\n            # Join deps with commas.\n            if(PC_DEPS)\n              set(PC_DEPS \"${PC_DEPS},\")\n            endif()\n            # don't duplicate dll-dep if it exists already\n            set(PC_DEPS \"${PC_DEPS} abseil_dll = ${PC_VERSION}\")\n            set(LNK_LIB \"${LNK_LIB} -labseil_dll\")\n          endif()\n        else()\n          # Join deps with commas.\n          if(PC_DEPS)\n            set(PC_DEPS \"${PC_DEPS},\")\n          endif()\n          set(PC_DEPS \"${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}\")\n        endif()\n      endif()\n    endforeach()\n    foreach(cflag ${ABSL_CC_LIB_COPTS})\n      # Strip out the CMake-specific `SHELL:` prefix, which is used to construct\n      # a group of space-separated options.\n      # https://cmake.org/cmake/help/v3.30/command/target_compile_options.html#option-de-duplication\n      string(REGEX REPLACE \"^SHELL:\" \"\" cflag \"${cflag}\")\n      if(${cflag} MATCHES \"^-Xarch_\")\n        # An -Xarch_ flag implies that its successor only applies to the\n        # specified platform. Such option groups are each specified in a single\n        # `SHELL:`-prefixed string in the COPTS list, which we simply ignore.\n      elseif(${cflag} MATCHES \"^(-Wno-|/wd)\")\n        # These flags are needed to suppress warnings that might fire in our headers.\n        set(PC_CFLAGS \"${PC_CFLAGS} ${cflag}\")\n      elseif(${cflag} MATCHES \"^(-W|/w[1234eo])\")\n        # Don't impose our warnings on others.\n      elseif(${cflag} MATCHES \"^-m\")\n        # Don't impose CPU instruction requirements on others, as\n        # the code performs feature detection on runtime.\n      else()\n        set(PC_CFLAGS \"${PC_CFLAGS} ${cflag}\")\n      endif()\n    endforeach()\n    string(REPLACE \";\" \" \" PC_LINKOPTS \"${ABSL_CC_LIB_LINKOPTS}\")\n    FILE(GENERATE OUTPUT \"${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc\" CONTENT \"\\\nprefix=${CMAKE_INSTALL_PREFIX}\\n\\\nexec_prefix=\\${prefix}\\n\\\nlibdir=${CMAKE_INSTALL_FULL_LIBDIR}\\n\\\nincludedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\\n\\\n\\n\\\nName: absl_${_NAME}\\n\\\nDescription: Abseil ${_NAME} library\\n\\\nURL: https://abseil.io/\\n\\\nVersion: ${PC_VERSION}\\n\\\nRequires:${PC_DEPS}\\n\\\nLibs: -L\\${libdir} $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:${LNK_LIB}> ${PC_LINKOPTS}\\n\\\nCflags: -I\\${includedir}${PC_CFLAGS}\\n\")\n    INSTALL(FILES \"${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc\"\n            DESTINATION \"${CMAKE_INSTALL_LIBDIR}/pkgconfig\")\n  endif()\n\n  if(NOT ABSL_CC_LIB_IS_INTERFACE)\n    if(_build_type STREQUAL \"dll_dep\")\n      # This target depends on the DLL. When adding dependencies to this target,\n      # any depended-on-target which is contained inside the DLL is replaced\n      # with a dependency on the DLL.\n      add_library(${_NAME} STATIC \"\")\n      target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})\n      absl_internal_dll_targets(\n        DEPS ${ABSL_CC_LIB_DEPS}\n        OUTPUT _dll_deps\n      )\n      target_link_libraries(${_NAME}\n        PUBLIC ${_dll_deps}\n        PRIVATE\n          ${ABSL_CC_LIB_LINKOPTS}\n          ${ABSL_DEFAULT_LINKOPTS}\n      )\n\n      if (ABSL_CC_LIB_TESTONLY)\n        set(_gtest_link_define \"GTEST_LINKED_AS_SHARED_LIBRARY=1\")\n      else()\n        set(_gtest_link_define)\n      endif()\n\n      target_compile_definitions(${_NAME}\n        PUBLIC\n          ABSL_CONSUME_DLL\n          \"${_gtest_link_define}\"\n      )\n\n    elseif(_build_type STREQUAL \"static\" OR _build_type STREQUAL \"shared\")\n      add_library(${_NAME} \"\")\n      target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})\n      if(APPLE)\n        set_target_properties(${_NAME} PROPERTIES\n          INSTALL_RPATH \"@loader_path\")\n      elseif(UNIX)\n        set_target_properties(${_NAME} PROPERTIES\n          INSTALL_RPATH \"$ORIGIN\")\n      endif()\n      target_link_libraries(${_NAME}\n      PUBLIC ${ABSL_CC_LIB_DEPS}\n      PRIVATE\n        ${ABSL_CC_LIB_LINKOPTS}\n        ${ABSL_DEFAULT_LINKOPTS}\n      )\n    else()\n      message(FATAL_ERROR \"Invalid build type: ${_build_type}\")\n    endif()\n\n    # Linker language can be inferred from sources, but in the case of DLLs we\n    # don't have any .cc files so it would be ambiguous. We could set it\n    # explicitly only in the case of DLLs but, because \"CXX\" is always the\n    # correct linker language for static or for shared libraries, we set it\n    # unconditionally.\n    set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE \"CXX\")\n\n    target_include_directories(${_NAME} ${ABSL_INTERNAL_INCLUDE_WARNING_GUARD}\n      PUBLIC\n        \"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>\"\n        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>\n    )\n    target_compile_options(${_NAME}\n      PRIVATE ${ABSL_CC_LIB_COPTS})\n    target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})\n\n    # Add all Abseil targets to a a folder in the IDE for organization.\n    if(ABSL_CC_LIB_PUBLIC)\n      set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})\n    elseif(ABSL_CC_LIB_TESTONLY)\n      set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)\n    else()\n      set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)\n    endif()\n\n    if(ABSL_PROPAGATE_CXX_STD)\n      # Abseil libraries require C++17 as the current minimum standard. When\n      # compiled with a higher standard (either because it is the compiler's\n      # default or explicitly requested), then Abseil requires that standard.\n      target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})\n    endif()\n\n    # When being installed, we lose the absl_ prefix.  We want to put it back\n    # to have properly named lib files.  This is a no-op when we are not being\n    # installed.\n    if(ABSL_ENABLE_INSTALL)\n      set_target_properties(${_NAME} PROPERTIES\n        OUTPUT_NAME \"absl_${_NAME}\"\n        SOVERSION \"${ABSL_SOVERSION}\"\n      )\n    endif()\n  else()\n    # Generating header-only library\n    add_library(${_NAME} INTERFACE)\n    target_include_directories(${_NAME} ${ABSL_INTERNAL_INCLUDE_WARNING_GUARD}\n      INTERFACE\n        \"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>\"\n        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>\n      )\n\n    if (_build_type STREQUAL \"dll\")\n         if(${_in_dll})\n           set(ABSL_CC_LIB_DEPS abseil_dll)\n         endif()\n         if(${_in_test_dll})\n           set(ABSL_CC_LIB_DEPS abseil_test_dll)\n         endif()\n    endif()\n\n    target_link_libraries(${_NAME}\n      INTERFACE\n        ${ABSL_CC_LIB_DEPS}\n        ${ABSL_CC_LIB_LINKOPTS}\n        ${ABSL_DEFAULT_LINKOPTS}\n    )\n    target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})\n\n    if(ABSL_PROPAGATE_CXX_STD)\n      # Abseil libraries require C++17 as the current minimum standard.\n      # Top-level application CMake projects should ensure a consistent C++\n      # standard for all compiled sources by setting CMAKE_CXX_STANDARD.\n      target_compile_features(${_NAME} INTERFACE ${ABSL_INTERNAL_CXX_STD_FEATURE})\n    endif()\n  endif()\n\n  if(ABSL_ENABLE_INSTALL)\n    install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets\n          RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n          LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}\n          ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}\n    )\n  endif()\n\n    add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})\nendfunction()\n\n# absl_cc_test()\n#\n# CMake function to imitate Bazel's cc_test rule.\n#\n# Parameters:\n# NAME: name of target (see Usage below)\n# SRCS: List of source files for the binary\n# DEPS: List of other libraries to be linked in to the binary targets\n# COPTS: List of private compile options\n# DEFINES: List of public defines\n# LINKOPTS: List of link options\n#\n# Note:\n# By default, absl_cc_test will always create a binary named absl_${NAME}.\n# This will also add it to ctest list as absl_${NAME}.\n#\n# Usage:\n# absl_cc_library(\n#   NAME\n#     awesome\n#   HDRS\n#     \"a.h\"\n#   SRCS\n#     \"a.cc\"\n#   PUBLIC\n# )\n#\n# absl_cc_test(\n#   NAME\n#     awesome_test\n#   SRCS\n#     \"awesome_test.cc\"\n#   DEPS\n#     absl::awesome\n#     GTest::gmock\n#     GTest::gtest_main\n# )\nfunction(absl_cc_test)\n  if(NOT (BUILD_TESTING AND ABSL_BUILD_TESTING))\n    return()\n  endif()\n\n  cmake_parse_arguments(ABSL_CC_TEST\n    \"\"\n    \"NAME\"\n    \"SRCS;COPTS;DEFINES;LINKOPTS;DEPS\"\n    ${ARGN}\n  )\n\n  set(_NAME \"absl_${ABSL_CC_TEST_NAME}\")\n\n  add_executable(${_NAME} \"\")\n  target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS})\n  target_include_directories(${_NAME}\n    PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}\n    PRIVATE ${absl_gtest_src_dir}/googletest/include ${absl_gtest_src_dir}/googlemock/include\n  )\n\n  if (${ABSL_BUILD_DLL})\n    target_compile_definitions(${_NAME}\n      PUBLIC\n        ${ABSL_CC_TEST_DEFINES}\n        ABSL_CONSUME_DLL\n        ABSL_CONSUME_TEST_DLL\n        GTEST_LINKED_AS_SHARED_LIBRARY=1\n    )\n\n    # Replace dependencies on targets inside the DLL with abseil_dll itself.\n    absl_internal_dll_targets(\n      DEPS ${ABSL_CC_TEST_DEPS}\n      OUTPUT ABSL_CC_TEST_DEPS\n    )\n    absl_internal_dll_targets(\n      DEPS ${ABSL_CC_TEST_LINKOPTS}\n      OUTPUT ABSL_CC_TEST_LINKOPTS\n    )\n  else()\n    target_compile_definitions(${_NAME}\n      PUBLIC\n        ${ABSL_CC_TEST_DEFINES}\n    )\n  endif()\n  target_compile_options(${_NAME}\n    PRIVATE ${ABSL_CC_TEST_COPTS}\n  )\n\n  target_link_libraries(${_NAME}\n    PUBLIC ${ABSL_CC_TEST_DEPS}\n    PRIVATE ${ABSL_CC_TEST_LINKOPTS}\n  )\n  # Add all Abseil targets to a folder in the IDE for organization.\n  set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)\n\n  if(ABSL_PROPAGATE_CXX_STD)\n    # Abseil libraries require C++17 as the current minimum standard.\n    # Top-level application CMake projects should ensure a consistent C++\n    # standard for all compiled sources by setting CMAKE_CXX_STANDARD.\n    target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})\n  endif()\n\n  add_test(NAME ${_NAME} COMMAND ${_NAME})\nendfunction()\n"
  },
  {
    "path": "CMake/Googletest/CMakeLists.txt.in",
    "content": "cmake_minimum_required(VERSION 3.16)\n\nproject(googletest-external NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(googletest\n  URL               \"${absl_gtest_download_url}\"  # May be empty\n  SOURCE_DIR        \"${absl_gtest_src_dir}\"\n  BINARY_DIR        \"${absl_gtest_build_dir}\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND     \"\"\n  INSTALL_COMMAND   \"\"\n  TEST_COMMAND      \"\"\n)\n"
  },
  {
    "path": "CMake/Googletest/DownloadGTest.cmake",
    "content": "# Integrates googletest at configure time.  Based on the instructions at\n# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project\n\n# Set up the external googletest project, downloading the latest from Github\n# master if requested.\nconfigure_file(\n  ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in\n  ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt\n)\n\nset(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})\nset(ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})\nif (BUILD_SHARED_LIBS)\n  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1\")\nendif()\n\n# Configure and build the googletest source.\nexecute_process(COMMAND ${CMAKE_COMMAND} -G \"${CMAKE_GENERATOR}\" .\n  RESULT_VARIABLE result\n  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external )\nif(result)\n  message(FATAL_ERROR \"CMake step for googletest failed: ${result}\")\nendif()\n\nexecute_process(COMMAND ${CMAKE_COMMAND} --build .\n  RESULT_VARIABLE result\n  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external)\nif(result)\n  message(FATAL_ERROR \"Build step for googletest failed: ${result}\")\nendif()\n\nset(CMAKE_CXX_FLAGS ${ABSL_SAVE_CMAKE_CXX_FLAGS})\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY})\n\n# Prevent overriding the parent project's compiler/linker settings on Windows\nset(gtest_force_shared_crt ON CACHE BOOL \"\" FORCE)\n\n# Add googletest directly to our build. This defines the gtest and gtest_main\n# targets.\nadd_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL)\n"
  },
  {
    "path": "CMake/README.md",
    "content": "# Abseil CMake Build Instructions\n\nAbseil comes with a CMake build script ([CMakeLists.txt](../CMakeLists.txt))\nthat can be used on a wide range of platforms (\"C\" stands for cross-platform.).\nIf you don't have CMake installed already, you can download it for free from\n<https://www.cmake.org/>.\n\nCMake works by generating native makefiles or build projects that can\nbe used in the compiler environment of your choice.\n\nFor API/ABI compatibility reasons, we strongly recommend building Abseil in a\nsubdirectory of your project or as an embedded dependency.\n\n## Incorporating Abseil Into a CMake Project\n\nThe recommendations below are similar to those for using CMake within the\ngoogletest framework\n(<https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project>)\n\n### Step-by-Step Instructions\n\n1. If you want to build the Abseil tests, integrate the Abseil dependency\n[Google Test](https://github.com/google/googletest) into your CMake\nproject. To disable Abseil tests, you have to pass either\n`-DBUILD_TESTING=OFF` or `-DABSL_BUILD_TESTING=OFF` when configuring your\nproject with CMake.\n\n2. Download Abseil and copy it into a subdirectory in your CMake project or add\nAbseil as a [git submodule](https://git-scm.com/docs/git-submodule) in your\nCMake project.\n\n3. You can then use the CMake command\n[`add_subdirectory()`](https://cmake.org/cmake/help/latest/command/add_subdirectory.html)\nto include Abseil directly in your CMake project.\n\n4. Add the **absl::** target you wish to use to the\n[`target_link_libraries()`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)\nsection of your executable or of your library.<br>\nHere is a short CMakeLists.txt example of an application project using Abseil.\n\n```cmake\ncmake_minimum_required(VERSION 3.16)\nproject(my_app_project)\n\n# Pick the C++ standard to compile with.\n# Abseil currently supports C++17 and C++20.\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n\nadd_subdirectory(abseil-cpp)\n\nadd_executable(my_exe source.cpp)\ntarget_link_libraries(my_exe absl::base absl::synchronization absl::strings)\n```\n\nNote that if you are developing a library designed for use by other clients, you\nshould instead leave `CMAKE_CXX_STANDARD` unset (or only set if being built as\nthe current top-level CMake project) and configure the minimum required C++\nstandard at the target level. If you require a later minimum C++ standard than\nAbseil does, it's a good idea to also enforce that `CMAKE_CXX_STANDARD` (which\nwill control Abseil library targets) is set to at least that minimum. For\nexample:\n\n```cmake\ncmake_minimum_required(VERSION 3.16)\nproject(my_lib_project)\n\n# Leave C++ standard up to the root application, so set it only if this is the\n# current top-level CMake project.\nif(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR)\n  set(CMAKE_CXX_STANDARD 17)\n  set(CMAKE_CXX_STANDARD_REQUIRED ON)\nendif()\n\nadd_subdirectory(abseil-cpp)\n\nadd_library(my_lib source.cpp)\ntarget_link_libraries(my_lib absl::base absl::synchronization absl::strings)\n\n# Enforce that my_lib requires C++17. Important to document for clients that they\n# must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility\n# (since otherwise, Abseil library targets could be compiled with a lower C++\n# standard than my_lib).\ntarget_compile_features(my_lib PUBLIC cxx_std_17)\nif(CMAKE_CXX_STANDARD LESS 17)\n  message(FATAL_ERROR\n      \"my_lib_project requires CMAKE_CXX_STANDARD >= 17 (got: ${CMAKE_CXX_STANDARD})\")\nendif()\n```\n\nThen the top-level application project that uses your library is responsible for\nsetting a consistent `CMAKE_CXX_STANDARD` that is sufficiently high.\n\n### Running Abseil Tests with CMake\n\nUse the `-DABSL_BUILD_TESTING=ON` flag to run Abseil tests.  Note that\nBUILD_TESTING must also be on (the default).\n\nYou will need to provide Abseil with a Googletest dependency.  There are two\noptions for how to do this:\n\n* Use `-DABSL_USE_GOOGLETEST_HEAD`.  This will automatically download the latest\nGoogletest source into the build directory at configure time.  Googletest will\nthen be compiled directly alongside Abseil's tests.\n* Manually integrate Googletest with your build.  See\nhttps://github.com/google/googletest/blob/master/googletest/README.md#using-cmake\nfor more information on using Googletest in a CMake project.\n\nFor example, to run just the Abseil tests, you could use this script:\n\n```\ncd path/to/abseil-cpp\nmkdir build\ncd build\ncmake -DABSL_BUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON ..\nmake -j\nctest\n```\n\nCurrently, we only run our tests with CMake in a Linux environment, but we are\nworking on the rest of our supported platforms. See\nhttps://github.com/abseil/abseil-cpp/projects/1 and\nhttps://github.com/abseil/abseil-cpp/issues/109 for more information.\n\n### Available Abseil CMake Public Targets\n\nHere's a non-exhaustive list of Abseil CMake public targets:\n\n```cmake\nabsl::algorithm\nabsl::base\nabsl::debugging\nabsl::flat_hash_map\nabsl::flags\nabsl::memory\nabsl::meta\nabsl::numeric\nabsl::random_random\nabsl::strings\nabsl::synchronization\nabsl::time\nabsl::utility\n```\n\n## Traditional CMake Set-Up\n\nFor larger projects, it may make sense to use the traditional CMake set-up where you build and install projects separately.\n\nFirst, you'd need to build and install Google Test:\n```\ncmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/installation/dir -DBUILD_GMOCK=ON\ncmake --build /build/googletest --target install\n```\n\nThen you need to configure and build Abseil. Make sure you enable `ABSL_USE_EXTERNAL_GOOGLETEST` and `ABSL_FIND_GOOGLETEST`. You also need to enable `ABSL_ENABLE_INSTALL` so that you can install Abseil itself.\n```\ncmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/installation/dir -DCMAKE_INSTALL_PREFIX=/installation/dir -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON\ncmake --build /temporary/build/abseil-cpp\n```\n\n(`CMAKE_PREFIX_PATH` is where you already have Google Test installed; `CMAKE_INSTALL_PREFIX` is where you want to have Abseil installed; they can be different.)\n\nRun the tests:\n```\nctest --test-dir /temporary/build/abseil-cpp\n```\n\nAnd finally install:\n```\ncmake --build /temporary/build/abseil-cpp --target install\n```\n\n# CMake Option Synopsis\n\n## Enable Standard CMake Installation\n\n`-DABSL_ENABLE_INSTALL=ON`\n\n## Google Test Options\n\n`-DABSL_BUILD_TESTING=ON` must be set to enable testing\n\n- Have Abseil download and build Google Test for you: `-DABSL_USE_EXTERNAL_GOOGLETEST=OFF` (default)\n  - Download and build latest Google Test: `-DABSL_USE_GOOGLETEST_HEAD=ON`\n  - Download specific Google Test version (ZIP archive): `-DABSL_GOOGLETEST_DOWNLOAD_URL=https://.../version.zip`\n  - Use Google Test from specific local directory: `-DABSL_LOCAL_GOOGLETEST_DIR=/path/to/googletest`\n- Use Google Test included elsewhere in your project: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON`\n- Use standard CMake `find_package(CTest)` to find installed Google Test: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON`\n"
  },
  {
    "path": "CMake/abslConfig.cmake.in",
    "content": "# absl CMake configuration file.\n\ninclude(CMakeFindDependencyMacro)\nfind_dependency(Threads)\n\n@PACKAGE_INIT@\n\ninclude (\"${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake\")\n"
  },
  {
    "path": "CMake/install_test_project/CMakeLists.txt",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# A simple CMakeLists.txt for testing cmake installation\n\ncmake_minimum_required(VERSION 3.16)\nproject(absl_cmake_testing CXX)\n\nadd_executable(simple simple.cc)\n\nfind_package(absl REQUIRED)\n\ntarget_link_libraries(simple absl::strings absl::config)\n"
  },
  {
    "path": "CMake/install_test_project/simple.cc",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//    https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <iostream>\n#include \"absl/base/config.h\"\n#include \"absl/strings/substitute.h\"\n\n#if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION != 99998877\n#error ABSL_LTS_RELEASE_VERSION is not set correctly.\n#endif\n\n#if !defined(ABSL_LTS_RELEASE_PATCH_LEVEL) || ABSL_LTS_RELEASE_PATCH_LEVEL != 0\n#error ABSL_LTS_RELEASE_PATCH_LEVEL is not set correctly.\n#endif\n\nint main(int argc, char** argv) {\n  for (int i = 0; i < argc; ++i) {\n    std::cout << absl::Substitute(\"Arg $0: $1\\n\", i, argv[i]);\n  }\n}\n"
  },
  {
    "path": "CMake/install_test_project/test.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# Unit and integration tests for Abseil LTS CMake installation\n\n# Fail on any error. Treat unset variables an error. Print commands as executed.\nset -euox pipefail\n\nabsl_dir=/abseil-cpp\nabsl_build_dir=/buildfs\ngoogletest_builddir=/googletest_builddir\ngoogletest_archive=\"googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\"\nproject_dir=\"${absl_dir}/CMake/install_test_project\"\nproject_build_dir=/buildfs/project-build\n\nbuild_shared_libs=\"OFF\"\nif [ \"${LINK_TYPE:-}\" = \"DYNAMIC\" ]; then\n  build_shared_libs=\"ON\"\nfi\n\n# Build and install GoogleTest\nmkdir \"${googletest_builddir}\"\npushd \"${googletest_builddir}\"\ncurl -L \"${ABSL_GOOGLETEST_DOWNLOAD_URL}\" --output \"${googletest_archive}\"\ntar -xz -f \"${googletest_archive}\"\npushd \"googletest-${ABSL_GOOGLETEST_VERSION}\"\nmkdir build\npushd build\ncmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=\"${build_shared_libs}\" ..\nmake -j $(nproc)\nmake install\nldconfig\npopd\npopd\npopd\n\n# Run the LTS transformations\n./create_lts.py 99998877\n\n# Build and install Abseil\npushd \"${absl_build_dir}\"\ncmake \"${absl_dir}\" \\\n  -DABSL_USE_EXTERNAL_GOOGLETEST=ON \\\n  -DABSL_FIND_GOOGLETEST=ON  \\\n  -DCMAKE_BUILD_TYPE=Release \\\n  -DABSL_BUILD_TESTING=ON \\\n  -DBUILD_SHARED_LIBS=\"${build_shared_libs}\"\nmake -j $(nproc)\nctest -j $(nproc) --output-on-failure\nmake install\nldconfig\npopd\n\n# Test the project against the installed Abseil\nmkdir -p \"${project_build_dir}\"\npushd \"${project_build_dir}\"\ncmake \"${project_dir}\"\ncmake --build . --target simple\n\noutput=\"$(${project_build_dir}/simple \"printme\" 2>&1)\"\nif [[ \"${output}\" != *\"Arg 1: printme\"* ]]; then\n  echo \"Faulty output on simple project:\"\n  echo \"${output}\"\n  exit 1\nfi\n\npopd\n\nif ! grep absl::strings \"/usr/local/lib/cmake/absl/abslTargets.cmake\"; then\n  cat \"/usr/local/lib/cmake/absl/abslTargets.cmake\"\n  echo \"CMake targets named incorrectly\"\n  exit 1\nfi\n\npushd \"${HOME}\"\ncat > hello-abseil.cc << EOF\n#include <cstdlib>\n\n#include \"absl/strings/str_format.h\"\n\nint main(int argc, char **argv) {\n  absl::PrintF(\"Hello Abseil!\\n\");\n  return EXIT_SUCCESS;\n}\nEOF\n\nif [ \"${LINK_TYPE:-}\" != \"DYNAMIC\" ]; then\n  pc_args=($(pkg-config --cflags --libs --static absl_str_format))\n  g++ -static -o hello-abseil hello-abseil.cc \"${pc_args[@]}\"\nelse\n  pc_args=($(pkg-config --cflags --libs absl_str_format))\n  g++ -o hello-abseil hello-abseil.cc \"${pc_args[@]}\"\nfi\nhello=\"$(./hello-abseil)\"\n[[ \"${hello}\" == \"Hello Abseil!\" ]]\n\npopd\n\necho \"Install test complete!\"\nexit 0\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md\n# As of 2024-07-01, CMake 3.16 is the minimum supported version.\ncmake_minimum_required(VERSION 3.16)\n\n# Allow the user to specify the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT\nif (POLICY CMP0141)\n  cmake_policy(SET CMP0141 NEW)\nendif (POLICY CMP0141)\n\nproject(absl LANGUAGES CXX)\nset(ABSL_SOVERSION 0)\ninclude(CTest)\n\n# Output directory is correct by default for most build setups. However, when\n# building Abseil as a DLL, it is important to have the DLL in the same\n# directory as the executable using it. Thus, we put all executables in a single\n# /bin directory.\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)\n\n# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp))\n# in the source tree of a project that uses it, install rules are disabled.\nif(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)\n  option(ABSL_ENABLE_INSTALL \"Enable install rule\" OFF)\nelse()\n  option(ABSL_ENABLE_INSTALL \"Enable install rule\" ON)\nendif()\n\nset(CMAKE_INSTALL_RPATH \"$ORIGIN\")\nset(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)\nset(CMAKE_BUILD_RPATH_USE_ORIGIN ON)\n\noption(ABSL_PROPAGATE_CXX_STD\n  \"Use CMake C++ standard meta features (e.g. cxx_std_17) that propagate to targets that link to Abseil\"\n  ON)\n\noption(ABSL_USE_SYSTEM_INCLUDES\n  \"Silence warnings in Abseil headers by marking them as SYSTEM includes\"\n  OFF)\n\nlist(APPEND CMAKE_MODULE_PATH\n  ${CMAKE_CURRENT_LIST_DIR}/CMake\n  ${CMAKE_CURRENT_LIST_DIR}/absl/copts\n)\n\noption(ABSL_MSVC_STATIC_RUNTIME\n  \"Link static runtime libraries\"\n  OFF)\nif(ABSL_MSVC_STATIC_RUNTIME)\n  set(CMAKE_MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>\")\nelse()\n  set(CMAKE_MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>DLL\")\nendif()\n\ninclude(CMakePackageConfigHelpers)\ninclude(GNUInstallDirs)\ninclude(AbseilDll)\ninclude(AbseilHelpers)\n\n\n##\n## Using absl targets\n##\n## all public absl targets are\n## exported with the absl:: prefix\n##\n## e.g absl::base absl::synchronization absl::strings ....\n##\n## DO NOT rely on the internal targets outside of the prefix\n\n\n# include current path\nlist(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})\n\nif(\"${CMAKE_CXX_COMPILER_ID}\" MATCHES \"Clang\")\n  set(ABSL_USING_CLANG ON)\nelse()\n  set(ABSL_USING_CLANG OFF)\nendif()\n\n# find dependencies\n## pthread\nfind_package(Threads REQUIRED)\n\ninclude(CMakeDependentOption)\n\noption(ABSL_BUILD_TESTING\n  \"If ON, Abseil will build all of Abseil's own tests.\" OFF)\n\noption(ABSL_BUILD_TEST_HELPERS\n  \"If ON, Abseil will build libraries that you can use to write tests against Abseil code. This option requires that Abseil is configured to use GoogleTest.\"\n  OFF)\n\noption(ABSL_USE_EXTERNAL_GOOGLETEST\n  \"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_subdirectory.\" OFF)\n\ncmake_dependent_option(ABSL_FIND_GOOGLETEST\n  \"If ON, Abseil will use find_package(GTest) rather than assuming that GoogleTest is already provided by the including project.\"\n  ON\n  \"ABSL_USE_EXTERNAL_GOOGLETEST\"\n  OFF)\n\n\noption(ABSL_USE_GOOGLETEST_HEAD\n  \"If ON, abseil will download HEAD from GoogleTest at config time.\" OFF)\n\nset(ABSL_GOOGLETEST_DOWNLOAD_URL \"\" CACHE STRING \"If set, download GoogleTest from this URL\")\n\nset(ABSL_LOCAL_GOOGLETEST_DIR \"/usr/src/googletest\" CACHE PATH\n  \"If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout.\"\n  )\n\noption(ABSL_BUILD_MONOLITHIC_SHARED_LIBS\n  \"Build Abseil as a single shared library (always enabled for Windows)\"\n  OFF\n)\nif(NOT BUILD_SHARED_LIBS AND ABSL_BUILD_MONOLITHIC_SHARED_LIBS)\n  message(WARNING \"Not building a shared library because BUILD_SHARED_LIBS is not set. Ignoring ABSL_BUILD_MONOLITHIC_SHARED_LIBS.\")\nendif()\n\nif((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS)\n  if (ABSL_USE_EXTERNAL_GOOGLETEST)\n    if (ABSL_FIND_GOOGLETEST)\n      find_package(GTest REQUIRED)\n    elseif(NOT TARGET GTest::gtest)\n      if(TARGET gtest)\n        # When Google Test is included directly rather than through find_package, the aliases are missing.\n        add_library(GTest::gtest ALIAS gtest)\n        add_library(GTest::gtest_main ALIAS gtest_main)\n        add_library(GTest::gmock ALIAS gmock)\n        add_library(GTest::gmock_main ALIAS gmock_main)\n      else()\n        message(FATAL_ERROR \"ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.\")\n      endif()\n    endif()\n  else()\n    set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build)\n    if(ABSL_USE_GOOGLETEST_HEAD AND ABSL_GOOGLETEST_DOWNLOAD_URL)\n      message(FATAL_ERROR \"Do not set both ABSL_USE_GOOGLETEST_HEAD and ABSL_GOOGLETEST_DOWNLOAD_URL\")\n    endif()\n    if(ABSL_USE_GOOGLETEST_HEAD)\n      set(absl_gtest_download_url \"https://github.com/google/googletest/archive/main.zip\")\n    elseif(ABSL_GOOGLETEST_DOWNLOAD_URL)\n      set(absl_gtest_download_url ${ABSL_GOOGLETEST_DOWNLOAD_URL})\n    endif()\n    if(absl_gtest_download_url)\n      set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)\n    else()\n      set(absl_gtest_src_dir ${ABSL_LOCAL_GOOGLETEST_DIR})\n    endif()\n    include(CMake/Googletest/DownloadGTest.cmake)\n  endif()\nendif()\n\nadd_subdirectory(absl)\n\nif(ABSL_ENABLE_INSTALL)\n  # absl:lts-remove-begin(system installation is supported for LTS releases)\n  # We don't support system-wide installation\n  list(APPEND SYSTEM_INSTALL_DIRS \"/usr/local\" \"/usr\" \"/opt/\" \"/opt/local\" \"c:/Program Files/${PROJECT_NAME}\")\n  if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS)\n    message(WARNING \"\\\n  The default and system-level install directories are unsupported except in LTS \\\n  releases of Abseil.  Please set CMAKE_INSTALL_PREFIX to install Abseil in your \\\n  source or build tree directly.\\\n    \")\n  endif()\n  # absl:lts-remove-end\n\n  # install as a subdirectory only\n  install(EXPORT ${PROJECT_NAME}Targets\n    NAMESPACE absl::\n    DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n  )\n\n  configure_package_config_file(\n    CMake/abslConfig.cmake.in\n    \"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\"\n    INSTALL_DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n  )\n  install(FILES \"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\"\n    DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n  )\n\n  # Abseil only has a version in LTS releases.  This mechanism is accomplished\n  # Abseil's internal Copybara (https://github.com/google/copybara) workflows and\n  # isn't visible in the CMake buildsystem itself.\n  if(absl_VERSION)\n    write_basic_package_version_file(\n      \"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\"\n      COMPATIBILITY ExactVersion\n    )\n\n    install(FILES \"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\"\n      DESTINATION \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\"\n    )\n  endif()  # absl_VERSION\n\n  # Install the headers except for \"options.h\" which is installed separately.\n  install(DIRECTORY absl\n    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n    FILES_MATCHING\n      PATTERN \"*.inc\"\n      PATTERN \"*.h\"\n      PATTERN \"options.h\" EXCLUDE\n      PATTERN \"copts\" EXCLUDE\n      PATTERN \"testdata\" EXCLUDE\n    )\n\n  # Rewrite options.h to use the compiled ABI.\n  file(READ \"absl/base/options.h\" ABSL_INTERNAL_OPTIONS_H_CONTENTS)\n\n  # Handle features that require at least C++20.\n  if (ABSL_INTERNAL_AT_LEAST_CXX20)\n    foreach(FEATURE \"ORDERING\" \"SOURCE_LOCATION\")\n      string(REPLACE\n      \"#define ABSL_OPTION_USE_STD_${FEATURE} 2\"\n      \"#define ABSL_OPTION_USE_STD_${FEATURE} 1\"\n      ABSL_INTERNAL_OPTIONS_H_PINNED\n      \"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}\")\n      set(ABSL_INTERNAL_OPTIONS_H_CONTENTS \"${ABSL_INTERNAL_OPTIONS_H_PINNED}\")\n    endforeach()\n  endif()\n\n  # Handle features that require at least C++17.\n  if (ABSL_INTERNAL_AT_LEAST_CXX17)\n    foreach(FEATURE \"ANY\" \"OPTIONAL\" \"STRING_VIEW\" \"VARIANT\")\n      string(REPLACE\n      \"#define ABSL_OPTION_USE_STD_${FEATURE} 2\"\n      \"#define ABSL_OPTION_USE_STD_${FEATURE} 1\"\n      ABSL_INTERNAL_OPTIONS_H_PINNED\n      \"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}\")\n      set(ABSL_INTERNAL_OPTIONS_H_CONTENTS \"${ABSL_INTERNAL_OPTIONS_H_PINNED}\")\n    endforeach()\n  endif()\n\n  # Any feature that still has the value of 2 (because it was not handled above)\n  # should be set to 0.\n  string(REGEX REPLACE\n    \"#define ABSL_OPTION_USE_STD_([^ ]*) 2\"\n    \"#define ABSL_OPTION_USE_STD_\\\\1 0\"\n    ABSL_INTERNAL_OPTIONS_H_PINNED\n    \"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}\")\n\n  # If the file already exists, check if it matches the new contents.\n  # This avoids writing the file if it is already up-to-date when the CMake\n  # generation is triggered and triggering unnecessary rebuilds.\n  set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE TRUE)\n  if (EXISTS \"${CMAKE_BINARY_DIR}/options-pinned.h\")\n    file(READ \"${CMAKE_BINARY_DIR}/options-pinned.h\" ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS)\n    if (\"${ABSL_INTERNAL_OPTIONS_H_PINNED}\" STREQUAL \"${ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS}\")\n      set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE FALSE)\n    endif()\n  endif()\n\n  # If the file needs an update, generate it.\n  if (ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE)\n    file(GENERATE OUTPUT \"${CMAKE_BINARY_DIR}/options-pinned.h\" CONTENT \"${ABSL_INTERNAL_OPTIONS_H_PINNED}\")\n  endif()\n\n  install(FILES \"${CMAKE_BINARY_DIR}/options-pinned.h\"\n         DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base\n         RENAME \"options.h\")\n\nendif()  # ABSL_ENABLE_INSTALL\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to Contribute to Abseil\n\nWe'd love to accept your patches and contributions to this project. There are\njust a few small guidelines you need to follow.\n\nNOTE: If you are new to GitHub, please start by reading [Pull Request\nhowto](https://help.github.com/articles/about-pull-requests/)\n\n## Contributor License Agreement\n\nContributions to this project must be accompanied by a Contributor License\nAgreement. You (or your employer) retain the copyright to your contribution,\nthis simply gives us permission to use and redistribute your contributions as\npart of the project. Head over to <https://cla.developers.google.com/> to see\nyour current agreements on file or to sign a new one.\n\nYou generally only need to submit a CLA once, so if you've already submitted one\n(even if it was for a different project), you probably don't need to do it\nagain.\n\n## Contribution Guidelines\n\nPotential contributors sometimes ask us if the Abseil project is the appropriate\nhome for their utility library code or for specific functions implementing\nmissing portions of the standard. Often, the answer to this question is \"no\".\nWe’d like to articulate our thinking on this issue so that our choices can be\nunderstood by everyone and so that contributors can have a better intuition\nabout whether Abseil might be interested in adopting a new library.\n\n### Priorities\n\nAlthough our mission is to augment the C++ standard library, our goal is not to\nprovide a full forward-compatible implementation of the latest standard. For us\nto consider a library for inclusion in Abseil, it is not enough that a library\nis useful. We generally choose to release a library when it meets at least one\nof the following criteria:\n\n*   **Widespread usage** - Using our internal codebase to help gauge usage, most\n    of the libraries we've released have tens of thousands of users.\n*   **Anticipated widespread usage** - Pre-adoption of some standard-compliant\n    APIs may not have broad adoption initially but can be expected to pick up\n    usage when it replaces legacy APIs. `absl::from_chars`, for example,\n    replaces existing code that converts strings to numbers and will therefore\n    likely see usage growth.\n*   **High impact** - APIs that provide a key solution to a specific problem,\n    such as `absl::FixedArray`, have higher impact than usage numbers may signal\n    and are released because of their importance.\n*   **Direct support for a library that falls under one of the above** - When we\n    want access to a smaller library as an implementation detail for a\n    higher-priority library we plan to release, we may release it, as we did\n    with portions of `absl/meta/type_traits.h`. One consequence of this is that\n    the presence of a library in Abseil does not necessarily mean that other\n    similar libraries would be a high priority.\n\n### API Freeze Consequences\n\nVia the\n[Abseil Compatibility Guidelines](https://abseil.io/about/compatibility), we\nhave promised a large degree of API stability. In particular, we will not make\nbackward-incompatible changes to released APIs without also shipping a tool or\nprocess that can upgrade our users' code. We are not yet at the point of easily\nreleasing such tools. Therefore, at this time, shipping a library establishes an\nAPI contract which is borderline unchangeable. (We can add new functionality,\nbut we cannot easily change existing behavior.) This constraint forces us to\nvery carefully review all APIs that we ship.\n\n\n## Coding Style\n\nTo keep the source consistent, readable, diffable and easy to merge, we use a\nfairly rigid coding style, as defined by the\n[google-styleguide](https://github.com/google/styleguide) project. All patches\nwill be expected to conform to the style outlined\n[here](https://google.github.io/styleguide/cppguide.html).\n\n## Guidelines for Pull Requests\n\n*   If you are a Googler, it is required that you send us a Piper CL instead of\n    using the GitHub pull-request process. The code propagation process will\n    deliver the change to GitHub.\n\n*   Create **small PRs** that are narrowly focused on **addressing a single\n    concern**. We often receive PRs that are trying to fix several things at a\n    time, but if only one fix is considered acceptable, nothing gets merged and\n    both author's & review's time is wasted. Create more PRs to address\n    different concerns and everyone will be happy.\n\n*   For speculative changes, consider opening an [Abseil\n    issue](https://github.com/abseil/abseil-cpp/issues) and discussing it first.\n    If you are suggesting a behavioral or API change, consider starting with an\n    [Abseil proposal template](ABSEIL_ISSUE_TEMPLATE.md).\n\n*   Provide a good **PR description** as a record of **what** change is being\n    made and **why** it was made. Link to a GitHub issue if it exists.\n\n*   Don't fix code style and formatting unless you are already changing that\n    line to address an issue. Formatting of modified lines may be done using\n   `git clang-format`. PRs with irrelevant changes won't be merged. If\n    you do want to fix formatting or style, do that in a separate PR.\n\n*   Unless your PR is trivial, you should expect there will be reviewer comments\n    that you'll need to address before merging. We expect you to be reasonably\n    responsive to those comments, otherwise the PR will be closed after 2-3\n    weeks of inactivity.\n\n*   Maintain **clean commit history** and use **meaningful commit messages**.\n    PRs with messy commit history are difficult to review and won't be merged.\n    Use `rebase -i upstream/master` to curate your commit history and/or to\n    bring in latest changes from master (but avoid rebasing in the middle of a\n    code review).\n\n*   Keep your PR up to date with upstream/master (if there are merge conflicts,\n    we can't really merge your change).\n\n*   **All tests need to be passing** before your change can be merged. We\n    recommend you **run tests locally** (see below)\n\n*   Exceptions to the rules can be made if there's a compelling reason for doing\n    so. That is - the rules are here to serve us, not the other way around, and\n    the rules need to be serving their intended purpose to be valuable.\n\n*   All submissions, including submissions by project members, require review.\n\n## Running Tests\n\nIf you have [Bazel](https://bazel.build/) installed, use `bazel test\n--test_tag_filters=\"-benchmark\" ...` to run the unit tests.\n\nIf you are running the Linux operating system and have\n[Docker](https://www.docker.com/) installed, you can also run the `linux_*.sh`\nscripts under the `ci/`(https://github.com/abseil/abseil-cpp/tree/master/ci)\ndirectory to test Abseil under a variety of conditions.\n\n## Abseil Committers\n\nThe current members of the Abseil engineering team are the only committers at\npresent.\n\n## Release Process\n\nAbseil lives at head, where latest-and-greatest code can be found.\n"
  },
  {
    "path": "FAQ.md",
    "content": "# Abseil FAQ\n\n## Is Abseil the right home for my utility library?\n\nMost often the answer to the question is \"no.\" As both the\n[About Abseil](https://abseil.io/about/) page and our\n[contributing guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines)\nexplain, Abseil contains a variety of core C++ library code that is widely used\nat [Google](https://www.google.com/). As such, Abseil's primary purpose is to be\nused as a dependency by Google's open source C++ projects. While we do hope that\nAbseil is also useful to the C++ community at large, this added constraint also\nmeans that we are unlikely to accept a contribution of utility code that isn't\nalready widely used by Google.\n\n## How do I set the C++ dialect used to build Abseil?\n\nThe short answer is that whatever mechanism you choose, you need to make sure\nthat you set this option consistently at the global level for your entire\nproject. If, for example, you want to set the C++ dialect to C++17, with\n[Bazel](https://bazel.build/) as the build system and `gcc` or `clang` as the\ncompiler, there are several ways to do this: * Pass `--cxxopt=-std=c++17` on the\ncommand line (for example, `bazel build --cxxopt=-std=c++17 ...`) * Set the\nenvironment variable `BAZEL_CXXOPTS` (for example, `BAZEL_CXXOPTS=-std=c++17`) *\nAdd `build --cxxopt=-std=c++17` to your\n[`.bazelrc` file](https://docs.bazel.build/versions/master/guide.html#bazelrc)\n\nIf you are using CMake as the build system, you'll need to add a line like\n`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. If you are\ndeveloping a library designed to be used by other clients, you should instead\nleave `CMAKE_CXX_STANDARD` unset and configure the minimum C++ standard required\nby each of your library targets via `target_compile_features`. See the\n[CMake build instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md)\nfor more information.\n\nFor a longer answer to this question and to understand why some other approaches\ndon't work, see the answer to [\"What is ABI and why don't you recommend using a\npre-compiled version of\nAbseil?\"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil)\n\n## What is ABI and why don't you recommend using a pre-compiled version of Abseil?\n\nFor the purposes of this discussion,\n[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) refers to the\ncompiled representation of code interfaces. This contrasts with\n[API](https://en.wikipedia.org/wiki/Application_programming_interface), which\nrefers to the interfaces defined in the source code. [Abseil has a strong\npromise of API compatibility, but does not make any promise of ABI\ncompatibility](https://abseil.io/about/compatibility). Let's take a look at what\nthis means in practice.\n\nYou might be tempted to do something like this in a\n[Bazel](https://bazel.build/) `BUILD` file:\n\n```\n# DON'T DO THIS!!!\ncc_library(\n    name = \"my_library\",\n    srcs = [\"my_library.cc\"],\n    copts = [\"-std=c++17\"],  # May create a mixed-mode compile!\n    deps = [\"@com_google_absl//absl/strings\"],\n)\n```\n\nApplying `-std=c++17` to an individual target in your `BUILD` file is going to\ncompile that specific target in C++17 mode, but it isn't going to ensure the\nAbseil library is built in C++17 mode, since the Abseil library itself is a\ndifferent build target. If your code includes an Abseil header, then your\nprogram may contain conflicting definitions of the same\nclass/function/variable/enum, etc. As a rule, all compile options that affect\nthe ABI of a program need to be applied to the entire build on a global basis.\n\nC++ has something called the\n[One Definition Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR).\nC++ doesn't allow multiple definitions of the same class/function/variable/enum,\netc. ODR violations sometimes result in linker errors, but linkers do not always\ncatch violations. Uncaught ODR violations can result in strange runtime\nbehaviors or crashes that can be hard to debug.\n\nIf you build the Abseil library and your code using different compile options\nthat affect ABI, there is a good chance you will run afoul of the One Definition\nRule. Examples of GCC compile options that affect ABI include (but aren't\nlimited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`),\ncode generation flags (e.g. `-fexceptions`), and preprocessor defines (e.g.\n`-DNDEBUG`).\n\nIf you use a pre-compiled version of Abseil, (for example, from your Linux\ndistribution package manager or from something like\n[vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to\nensure ABI compatibility across the components of your program. The only way you\ncan be sure your program is going to be correct regarding ABI is to ensure\nyou've used the exact same compile options as were used to build the\npre-compiled library. This does not mean that Abseil cannot work as part of a\nLinux distribution since a knowledgeable binary packager will have ensured that\nall packages have been built with consistent compile options. This is one of the\nreasons we warn against - though do not outright reject - using Abseil as a\npre-compiled library.\n\nAnother possible way that you might run afoul of ABI issues is if you\naccidentally include two versions of Abseil in your program. Multiple versions\nof Abseil can end up within the same binary if your program uses the Abseil\nlibrary and another library also transitively depends on Abseil (resulting in\nwhat is sometimes called the diamond dependency problem). In cases such as this\nyou must structure your build so that all libraries use the same version of\nAbseil.\n[Abseil's strong promise of API compatibility between releases](https://abseil.io/about/compatibility)\nmeans the latest \"HEAD\" release of Abseil is almost certainly the right choice\nif you are doing as we recommend and building all of your code from source.\n\nFor these reasons we recommend you avoid pre-compiled code and build the Abseil\nlibrary yourself in a consistent manner with the rest of your code.\n\n## What is \"live at head\" and how do I do it?\n\nFrom Abseil's point-of-view, \"live at head\" means that every Abseil source\nrelease (which happens on an almost daily basis) is either API compatible with\nthe previous release, or comes with an automated tool that you can run over code\nto make it compatible. In practice, the need to use an automated tool is\nextremely rare. This means that upgrading from one source release to another\nshould be a routine practice that can and should be performed often.\n\nWe recommend you update to the\n[latest commit in the `master` branch of Abseil](https://github.com/abseil/abseil-cpp/commits/master)\nas often as possible. Not only will you pick up bug fixes more quickly, but if\nyou have good automated testing, you will catch and be able to fix any\n[Hyrum's Law](https://www.hyrumslaw.com/) dependency problems on an incremental\nbasis instead of being overwhelmed by them and having difficulty isolating them\nif you wait longer between updates.\n\nIf you are using the [Bazel](https://bazel.build/) build system with\n[Bzlmod](https://bazel.build/external/overview#bzlmod), you can use a\n`git_override` in your `MODULE.bazel` file to track the latest commit.\n\nFor example, to update to the latest commit, you would add (or update) the\nfollowing snippet in your `MODULE.bazel` file:\n\n```starlark\nbazel_dep(name = \"abseil-cpp\", version = \"20260107.1\")\n\ngit_override(\n    module_name = \"abseil-cpp\",\n    remote = \"https://github.com/abseil/abseil-cpp.git\",\n    # Replace the following line with the latest commit.\n    commit = \"6ec9964c325db0610a376b3cb81de073ea6ada90\",\n)\n```\n\nYou can commit the updated `MODULE.bazel` file to your source control every time\nyou update, and if you have good automated testing, you might even consider\nautomating this.\n\n## Why do I see strange behaviors when I use Abseil hash tables?\n\nAbseil's hash function uses a random seed.\n\nMany programmers believe incorrectly that this is a defense against\n[hash flooding](https://en.wikipedia.org/wiki/Collision_attack#Hash_flooding).\nWhile it does make a hash flooding attack more difficult, Abseil's hash function\nprioritizes speed over thorough mixing (and thus is not cryptographically\nsecure), and the current seed implementation is also not cryptographically\nsecure. If you are storing a large amount of attacker-controlled data, the most\nreliable defense against hash-flooding is to use a container that does not have\n`O(n)` worst-case behavior.\n\nThe real reason for hash randomization is to prevent\n[Hyrum's Law](https://www.hyrumslaw.com/) dependencies on iteration order. This\nhas allowed us to roll out steady improvements to the implementation without\nbreaking users who may have otherwise written code that was dependent on\nordering or other characteristics.\n\nThe current implementation uses a global seed, which, if linked incorrectly\n(e.g., static Abseil in multiple DSOs), can cause the ODR violations. If more\nthan one seed is linked, different calls to the hash function may return\ndifferent values, rendering hash elements inaccessible, causing crashes, or\nother arbitrarily bad behaviors.\n\nWe are often asked for a knob to disable hash randomization. The answer is a\nhard \"no\", even under test or under a flag, because people will find a way to\nforce it and allow their code or tests to depend on it. At Google-scale, the\ncompute costs that are saved by preserving the ability to improve the\nimplementation far outweigh the inconvenience of learning how to write code\nresilient to change.\n\n## How do I use the LLVM Sanitizers with Abseil?\n\nLLVM Sanitizers are a suite of powerful, dynamic analysis tools that\nautomatically detect various critical bugs during program execution. They work\nby instrumenting the compiled binary and linking a runtime library to intercept\noperations and report issues.\n\nWe receive many incorrect bug reports from users trying to use the sanitizers.\nThe most common cause of these issues is ODR violations in the form of an\ninstrumentation mismatch. This happens when users try to link libraries compiled\nwith sanitizer instrumentation with uninstrumented libraries. It is important\nthat all code in the application is built with the same sanitizer configuration.\n\nThe easiest way to do this is to use [Bazel](https://bazel.build) and pass the\nsanitizer options on the commandline, but it is important not to overlook the\nimportance of avoiding precompiled system libraries, including the C++ standard\nlibrary. For instance,\n[MemorySanitizer requires an instrumented `libc++`](https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo).\n\nSince most users are not going to build `libc++` with Bazel, here is a\nMemorySanitizer recipe that currently works (and could easily be tweaked for\nThreadSanitizer and friends):\n\n```shell\n# From the root of the LLVM source tree, configure libc++ to be instrumented with MSAN:\ncmake -G Ninja -S runtimes -B build_msan -DLLVM_ENABLE_RUNTIMES=\"libcxx;libcxxabi;libunwind\" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"${HOME}/llvm-msan\" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_USE_SANITIZER=MemoryWithOrigins -DLLVM_TARGETS_TO_BUILD=\"host\"\n\n# Build and install it into ${HOME}/llvm-msan\nninja -C build_msan install-cxx install-cxxabi install-unwind\n\n# Then build (or test) your code like this:\nbazel test --repo_env=CC=clang --repo_env=BAZEL_CXXOPTS=nostdinc++ --repo_env=BAZEL_LINKOPTS=-L${HOME}/llvm-msan/lib:-lc++:-lc++abi:-lgcc_s:-lm:-Wl,-rpath=${HOME}/llvm-msan/lib --repo_env=CPLUS_INCLUDE_PATH=${HOME}/llvm-msan/include/c++/v1 --copt=-fsanitize=memory --linkopt=-fsanitize=memory --linkopt=-fsanitize-link-c++-runtime ...\n```\n\nYou should consider adding these options to a\n[`.bazelrc`](https://bazel.build/run/bazelrc) file to avoid retyping them.\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       https://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "MODULE.bazel",
    "content": "# Copyright 2024 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# https://bazel.build/external/overview#bzlmod\n\nmodule(\n    name = \"abseil-cpp\",\n    version = \"head\",\n    compatibility_level = 1,\n)\n\ncc_configure = use_extension(\"@rules_cc//cc:extensions.bzl\",\n                             \"cc_configure_extension\",\n                             dev_dependency = True)\nuse_repo(cc_configure, \"local_config_cc\")\n\nbazel_dep(name = \"rules_cc\", version = \"0.2.9\")\nbazel_dep(name = \"bazel_skylib\", version = \"1.8.1\")\nbazel_dep(name = \"platforms\", version = \"1.0.0\")\n\nbazel_dep(\n    name = \"google_benchmark\",\n    version = \"1.9.5\",\n    dev_dependency = True,\n)\n\n# Note: Googletest is NOT a dev_dependency. Some Abseil test utilities\n# intended to be used by Abseil users depend on GoogleTest.\nbazel_dep(\n    name = \"googletest\",\n    version = \"1.17.0.bcr.2\",\n)\n"
  },
  {
    "path": "PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>NSPrivacyTracking</key>\n  <false/>\n  <key>NSPrivacyCollectedDataTypes</key>\n  <array/>\n  <key>NSPrivacyTrackingDomains</key>\n  <array/>\n  <key>NSPrivacyAccessedAPITypes</key>\n  <array/>\n</dict>\n</plist>\n"
  },
  {
    "path": "README.md",
    "content": "# Abseil - C++ Common Libraries\n\nThe repository contains the Abseil C++ library code. Abseil is an open-source\ncollection of C++ code (compliant to C++17) designed to augment the C++\nstandard library.\n\n## Table of Contents\n\n- [About Abseil](#about)\n- [Quickstart](#quickstart)\n- [Building Abseil](#build)\n- [Support](#support)\n- [Codemap](#codemap)\n- [Releases](#releases)\n- [License](#license)\n- [Links](#links)\n\n<a name=\"about\"></a>\n## About Abseil\n\nAbseil is an open-source collection of C++ library code designed to augment\nthe C++ standard library. The Abseil library code is collected from Google's\nown C++ code base, has been extensively tested and used in production, and\nis the same code we depend on in our daily coding lives.\n\nIn some cases, Abseil provides pieces missing from the C++ standard; in\nothers, Abseil provides alternatives to the standard for special needs\nwe've found through usage in the Google code base. We denote those cases\nclearly within the library code we provide you.\n\nAbseil is not meant to be a competitor to the standard library; we've\njust found that many of these utilities serve a purpose within our code\nbase, and we now want to provide those resources to the C++ community as\na whole.\n\n<a name=\"quickstart\"></a>\n## Quickstart\n\nIf you want to just get started, make sure you at least run through the\n[Abseil Quickstart](https://abseil.io/docs/cpp/quickstart). The Quickstart\ncontains information about setting up your development environment, downloading\nthe Abseil code, running tests, and getting a simple binary working.\n\n<a name=\"build\"></a>\n## Building Abseil\n\n[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official\nbuild systems for Abseil.\nSee the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information\non building Abseil using the Bazel build system.\nIf you require CMake support, please check the [CMake build\ninstructions](CMake/README.md) and [CMake\nQuickstart](https://abseil.io/docs/cpp/quickstart-cmake).\n\n<a name=\"support\"></a>\n## Support\n\nAbseil follows Google's [Foundational C++ Support\nPolicy](https://opensource.google/documentation/policies/cplusplus-support). See\n[this\ntable](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md)\nfor a list of currently supported versions compilers, platforms, and build\ntools.\n\n<a name=\"codemap\"></a>\n## Codemap\n\nAbseil contains the following C++ library components:\n\n* [`base`](absl/base/)\n  <br /> The `base` library contains initialization code and other code which\n  all other Abseil code depends on. Code within `base` may not depend on any\n  other code (other than the C++ standard library).\n* [`algorithm`](absl/algorithm/)\n  <br /> The `algorithm` library contains additions to the C++ `<algorithm>`\n  library and container-based versions of such algorithms.\n* [`cleanup`](absl/cleanup/)\n  <br /> The `cleanup` library contains the control-flow-construct-like type\n  `absl::Cleanup` which is used for executing a callback on scope exit.\n* [`container`](absl/container/)\n  <br /> The `container` library contains additional STL-style containers,\n  including Abseil's unordered \"Swiss table\" containers.\n* [`crc`](absl/crc/) The `crc` library contains code for\n  computing error-detecting cyclic redundancy checks on data.\n* [`debugging`](absl/debugging/)\n  <br /> The `debugging` library contains code useful for enabling leak\n  checks, and stacktrace and symbolization utilities.\n* [`flags`](absl/flags/)\n  <br /> The `flags` library contains code for handling command line flags for\n  libraries and binaries built with Abseil.\n* [`hash`](absl/hash/)\n  <br /> The `hash` library contains the hashing framework and default hash\n  functor implementations for hashable types in Abseil.\n* [`log`](absl/log/)\n  <br /> The `log` library contains `LOG` and `CHECK` macros and facilities\n  for writing logged messages out to disk, `stderr`, or user-extensible\n  destinations.\n* [`memory`](absl/memory/)\n  <br /> The `memory` library contains memory management facilities that augment\n  C++'s `<memory>` library.\n* [`meta`](absl/meta/)\n  <br /> The `meta` library contains type checks\n  similar to those available in the C++ `<type_traits>` library.\n* [`numeric`](absl/numeric/)\n  <br /> The `numeric` library contains 128-bit integer types as well as\n  implementations of C++20's bitwise math functions.\n* [`profiling`](absl/profiling/)\n  <br /> The `profiling` library contains utility code for profiling C++\n  entities.  It is currently a private dependency of other Abseil libraries.\n* [`random`](absl/random/)\n  <br /> The `random` library contains functions for generating pseudorandom\n  values.\n* [`status`](absl/status/)\n  <br /> The `status` library contains abstractions for error handling,\n  specifically `absl::Status` and `absl::StatusOr<T>`.\n* [`strings`](absl/strings/)\n  <br /> The `strings` library contains a variety of strings routines and\n  utilities.\n* [`synchronization`](absl/synchronization/)\n  <br /> The `synchronization` library contains concurrency primitives (Abseil's\n  `absl::Mutex` class, an alternative to `std::mutex`) and a variety of\n  synchronization abstractions.\n* [`time`](absl/time/)\n  <br /> The `time` library contains abstractions for computing with absolute\n  points in time, durations of time, and formatting and parsing time within\n  time zones.\n* [`types`](absl/types/)\n  <br /> The `types` library contains non-container utility types.\n* [`utility`](absl/utility/)\n  <br /> The `utility` library contains utility and helper code.\n\n<a name=\"releases\"></a>\n## Releases\n\nAbseil recommends users \"live-at-head\" (update to the latest commit from the\nmaster branch as often as possible). However, we realize this philosophy doesn't\nwork for every project, so we also provide [Long Term Support\nReleases](https://github.com/abseil/abseil-cpp/releases) to which we backport\nfixes for severe bugs. See our [release\nmanagement](https://abseil.io/about/releases) document for more details.\n\n<a name=\"license\"></a>\n## License\n\nThe Abseil C++ library is licensed under the terms of the Apache\nlicense. See [LICENSE](LICENSE) for more information.\n\n<a name=\"links\"></a>\n## Links\n\nFor more information about Abseil:\n\n* Consult our [Abseil Introduction](https://abseil.io/about/intro)\n* Read [Why Adopt Abseil](https://abseil.io/about/philosophy) to understand our\n  design philosophy.\n* Peruse our\n  [Abseil Compatibility Guarantees](https://abseil.io/about/compatibility) to\n  understand both what we promise to you, and what we expect of you in return.\n"
  },
  {
    "path": "UPGRADES.md",
    "content": "# C++ Upgrade Tools\n\nAbseil may occasionally release API-breaking changes. As noted in our\n[Compatibility Guidelines][compatibility-guide], we will aim to provide a tool\nto do the work of effecting such API-breaking changes, when absolutely\nnecessary.\n\nThese tools will be listed on the [C++ Upgrade Tools][upgrade-tools] guide on\nhttps://abseil.io.\n\nFor more information, the [C++ Automated Upgrade Guide][api-upgrades-guide]\noutlines this process.\n\n[compatibility-guide]: https://abseil.io/about/compatibility\n[api-upgrades-guide]: https://abseil.io/docs/cpp/tools/api-upgrades\n[upgrade-tools]: https://abseil.io/docs/cpp/tools/upgrades/\n\n"
  },
  {
    "path": "absl/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nlicenses([\"notice\"])\n\nconfig_setting(\n    name = \"clang_compiler\",\n    flag_values = {\n        \"@bazel_tools//tools/cpp:compiler\": \"clang\",\n    },\n    visibility = [\":__subpackages__\"],\n)\n\nconfig_setting(\n    name = \"mingw_unspecified_compiler\",\n    flag_values = {\n        \"@bazel_tools//tools/cpp:compiler\": \"mingw\",\n    },\n    visibility = [\":__subpackages__\"],\n)\n\nconfig_setting(\n    name = \"mingw-gcc_compiler\",\n    flag_values = {\n        \"@bazel_tools//tools/cpp:compiler\": \"mingw-gcc\",\n    },\n    visibility = [\":__subpackages__\"],\n)\n\nconfig_setting(\n    name = \"fuchsia\",\n    constraint_values = [\n        \"@platforms//os:fuchsia\",\n    ],\n    visibility = [\":__subpackages__\"],\n)\n\nselects.config_setting_group(\n    name = \"mingw_compiler\",\n    match_any = [\n        \":mingw_unspecified_compiler\",\n        \":mingw-gcc_compiler\",\n    ],\n    visibility = [\":__subpackages__\"],\n)\n\n# Expose internals to privileged external repositories.\npackage_group(\n    name = \"friends\",\n    packages = [],\n)\n"
  },
  {
    "path": "absl/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nadd_subdirectory(base)\nadd_subdirectory(algorithm)\nadd_subdirectory(cleanup)\nadd_subdirectory(container)\nadd_subdirectory(crc)\nadd_subdirectory(debugging)\nadd_subdirectory(flags)\nadd_subdirectory(functional)\nadd_subdirectory(hash)\nadd_subdirectory(log)\nadd_subdirectory(memory)\nadd_subdirectory(meta)\nadd_subdirectory(numeric)\nadd_subdirectory(profiling)\nadd_subdirectory(random)\nadd_subdirectory(status)\nadd_subdirectory(strings)\nadd_subdirectory(synchronization)\nadd_subdirectory(time)\nadd_subdirectory(types)\nadd_subdirectory(utility)\n\nif (ABSL_BUILD_DLL)\n  absl_make_dll()\n  if ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS)\n    absl_make_dll(TEST ON)\n  endif()\nendif()\n"
  },
  {
    "path": "absl/abseil.podspec.gen.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"This script generates abseil.podspec from all BUILD.bazel files.\n\nThis is expected to run on abseil git repository with Bazel 1.0 on Linux.\nIt recursively analyzes BUILD.bazel files using query command of Bazel to\ndump its build rules in XML format. From these rules, it constructs podspec\nstructure.\n\"\"\"\n\nimport argparse\nimport collections\nimport os\nimport re\nimport subprocess\nimport xml.etree.ElementTree\n\n# Template of root podspec.\nSPEC_TEMPLATE = \"\"\"\n# This file has been automatically generated from a script.\n# Please make modifications to `abseil.podspec.gen.py` instead.\nPod::Spec.new do |s|\n  s.name     = 'abseil'\n  s.version  = '${version}'\n  s.summary  = 'Abseil Common Libraries (C++) from Google'\n  s.homepage = 'https://abseil.io'\n  s.license  = 'Apache License, Version 2.0'\n  s.authors  = { 'Abseil Team' => 'abseil-io@googlegroups.com' }\n  s.source = {\n    :git => 'https://github.com/abseil/abseil-cpp.git',\n    :tag => '${tag}',\n  }\n  s.resource_bundles = {\n    s.module_name => 'PrivacyInfo.xcprivacy',\n  }\n  s.module_name = 'absl'\n  s.header_mappings_dir = 'absl'\n  s.header_dir = 'absl'\n  s.libraries = 'c++'\n  s.compiler_flags = '-Wno-everything'\n  s.pod_target_xcconfig = {\n    'USER_HEADER_SEARCH_PATHS' => '$(inherited) \"$(PODS_TARGET_SRCROOT)\"',\n    'USE_HEADERMAP' => 'NO',\n    'ALWAYS_SEARCH_USER_PATHS' => 'NO',\n    'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',\n  }\n  s.ios.deployment_target = '12.0'\n  s.osx.deployment_target = '10.13'\n  s.tvos.deployment_target = '12.0'\n  s.watchos.deployment_target = '4.0'\n  s.visionos.deployment_target = '1.0'\n  s.subspec 'xcprivacy' do |ss|\n    ss.resource_bundles = {\n      ss.module_name => 'PrivacyInfo.xcprivacy',\n    }\n  end\n\"\"\"\n\n# Rule object representing the rule of Bazel BUILD.\nRule = collections.namedtuple(\n    \"Rule\", \"type name package srcs hdrs textual_hdrs deps visibility testonly\")\n\n\ndef get_elem_value(elem, name):\n  \"\"\"Returns the value of XML element with the given name.\"\"\"\n  for child in elem:\n    if child.attrib.get(\"name\") != name:\n      continue\n    if child.tag == \"string\":\n      return child.attrib.get(\"value\")\n    if child.tag == \"boolean\":\n      return child.attrib.get(\"value\") == \"true\"\n    if child.tag == \"list\":\n      return [nested_child.attrib.get(\"value\") for nested_child in child]\n    raise \"Cannot recognize tag: \" + child.tag\n  return None\n\n\ndef normalize_paths(paths):\n  \"\"\"Returns the list of normalized path.\"\"\"\n  # e.g. [\"//absl/strings:dir/header.h\"] -> [\"absl/strings/dir/header.h\"]\n  return [path.lstrip(\"/\").replace(\":\", \"/\") for path in paths]\n\n\ndef parse_rule(elem, package):\n  \"\"\"Returns a rule from bazel XML rule.\"\"\"\n  return Rule(\n      type=elem.attrib[\"class\"],\n      name=get_elem_value(elem, \"name\"),\n      package=package,\n      srcs=normalize_paths(get_elem_value(elem, \"srcs\") or []),\n      hdrs=normalize_paths(get_elem_value(elem, \"hdrs\") or []),\n      textual_hdrs=normalize_paths(get_elem_value(elem, \"textual_hdrs\") or []),\n      deps=get_elem_value(elem, \"deps\") or [],\n      visibility=get_elem_value(elem, \"visibility\") or [],\n      testonly=get_elem_value(elem, \"testonly\") or False)\n\n\ndef read_build(package):\n  \"\"\"Runs bazel query on given package file and returns all cc rules.\"\"\"\n  result = subprocess.check_output(\n      [\"bazel\", \"query\", package + \":all\", \"--output\", \"xml\"])\n  root = xml.etree.ElementTree.fromstring(result)\n  return [\n      parse_rule(elem, package)\n      for elem in root\n      if elem.tag == \"rule\" and elem.attrib[\"class\"].startswith(\"cc_\")\n  ]\n\n\ndef collect_rules(root_path):\n  \"\"\"Collects and returns all rules from root path recursively.\"\"\"\n  rules = []\n  for cur, _, _ in os.walk(root_path):\n    build_path = os.path.join(cur, \"BUILD.bazel\")\n    if os.path.exists(build_path):\n      rules.extend(read_build(\"//\" + cur))\n  return rules\n\n\ndef relevant_rule(rule):\n  \"\"\"Returns true if a given rule is relevant when generating a podspec.\"\"\"\n  return (\n      # cc_library only (ignore cc_test, cc_binary)\n      rule.type == \"cc_library\" and\n      # ignore empty rule\n      (rule.hdrs + rule.textual_hdrs + rule.srcs) and\n      # ignore test-only rule\n      not rule.testonly)\n\n\ndef get_spec_var(depth):\n  \"\"\"Returns the name of variable for spec with given depth.\"\"\"\n  return \"s\" if depth == 0 else \"s{}\".format(depth)\n\n\ndef get_spec_name(label):\n  \"\"\"Converts the label of bazel rule to the name of podspec.\"\"\"\n  assert label.startswith(\"//absl/\"), \"{} doesn't start with //absl/\".format(\n      label)\n  # e.g. //absl/apple/banana -> abseil/apple/banana\n  return \"abseil/\" + label[7:]\n\n\ndef write_podspec(f, rules, args):\n  \"\"\"Writes a podspec from given rules and args.\"\"\"\n  rule_dir = build_rule_directory(rules)[\"abseil\"]\n  # Write root part with given arguments\n  spec = re.sub(r\"\\$\\{(\\w+)\\}\", lambda x: args[x.group(1)],\n                SPEC_TEMPLATE).lstrip()\n  f.write(spec)\n  # Write all target rules\n  write_podspec_map(f, rule_dir, 0)\n  f.write(\"end\\n\")\n\n\ndef build_rule_directory(rules):\n  \"\"\"Builds a tree-style rule directory from given rules.\"\"\"\n  rule_dir = {}\n  for rule in rules:\n    cur = rule_dir\n    for frag in get_spec_name(rule.package).split(\"/\"):\n      cur = cur.setdefault(frag, {})\n    cur[rule.name] = rule\n  return rule_dir\n\n\ndef write_podspec_map(f, cur_map, depth):\n  \"\"\"Writes podspec from rule map recursively.\"\"\"\n  for key, value in sorted(cur_map.items()):\n    indent = \"  \" * (depth + 1)\n    f.write(\"{indent}{var0}.subspec '{key}' do |{var1}|\\n\".format(\n        indent=indent,\n        key=key,\n        var0=get_spec_var(depth),\n        var1=get_spec_var(depth + 1)))\n    if isinstance(value, dict):\n      write_podspec_map(f, value, depth + 1)\n    else:\n      write_podspec_rule(f, value, depth + 1)\n    f.write(\"{indent}end\\n\".format(indent=indent))\n\n\ndef write_podspec_rule(f, rule, depth):\n  \"\"\"Writes podspec from given rule.\"\"\"\n  indent = \"  \" * (depth + 1)\n  spec_var = get_spec_var(depth)\n  # Puts all files in hdrs, textual_hdrs, and srcs into source_files.\n  # Since CocoaPods treats header_files a bit differently from bazel,\n  # this won't generate a header_files field so that all source_files\n  # are considered as header files.\n  srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs))\n  write_indented_list(\n      f, \"{indent}{var}.source_files = \".format(indent=indent, var=spec_var),\n      srcs)\n  # Writes dependencies of this rule.\n  for dep in sorted(rule.deps):\n    name = get_spec_name(dep.replace(\":\", \"/\"))\n    f.write(\"{indent}{var}.dependency '{dep}'\\n\".format(\n        indent=indent, var=spec_var, dep=name))\n  # Writes dependency to xcprivacy\n  f.write(\n      \"{indent}{var}.dependency '{dep}'\\n\".format(\n          indent=indent, var=spec_var, dep=\"abseil/xcprivacy\"\n      )\n  )\n\n\ndef write_indented_list(f, leading, values):\n  \"\"\"Writes leading values in an indented style.\"\"\"\n  f.write(leading)\n  f.write((\",\\n\" + \" \" * len(leading)).join(\"'{}'\".format(v) for v in values))\n  f.write(\"\\n\")\n\n\ndef generate(args):\n  \"\"\"Generates a podspec file from all BUILD files under absl directory.\"\"\"\n  rules = filter(relevant_rule, collect_rules(\"absl\"))\n  with open(args.output, \"wt\") as f:\n    write_podspec(f, rules, vars(args))\n\n\ndef main():\n  parser = argparse.ArgumentParser(\n      description=\"Generates abseil.podspec from BUILD.bazel\")\n  parser.add_argument(\n      \"-v\", \"--version\", help=\"The version of podspec\", required=True)\n  parser.add_argument(\n      \"-t\",\n      \"--tag\",\n      default=None,\n      help=\"The name of git tag (default: version)\")\n  parser.add_argument(\n      \"-o\",\n      \"--output\",\n      default=\"abseil.podspec\",\n      help=\"The name of output file (default: abseil.podspec)\")\n  args = parser.parse_args()\n  if args.tag is None:\n    args.tag = args.version\n  generate(args)\n\n\nif __name__ == \"__main__\":\n  main()\n"
  },
  {
    "path": "absl/algorithm/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"algorithm\",\n    hdrs = [\"algorithm.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"algorithm_test\",\n    size = \"small\",\n    srcs = [\"algorithm_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":algorithm\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"container\",\n    hdrs = [\n        \"container.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":algorithm\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"container_test\",\n    srcs = [\"container_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/algorithm/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    algorithm\n  HDRS\n    \"algorithm.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    algorithm_test\n  SRCS\n    \"algorithm_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::algorithm\n    absl::config\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    algorithm_container\n  HDRS\n    \"container.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::algorithm\n    absl::config\n    absl::core_headers\n    absl::meta\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    container_test\n  SRCS\n    \"container_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::algorithm_container\n    absl::config\n    absl::core_headers\n    absl::memory\n    absl::random_random\n    absl::span\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/algorithm/algorithm.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: algorithm.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains Google extensions to the standard <algorithm> C++\n// header.\n\n#ifndef ABSL_ALGORITHM_ALGORITHM_H_\n#define ABSL_ALGORITHM_ALGORITHM_H_\n\n#include <algorithm>\n#include <iterator>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// equal()\n// rotate()\n//\n// Historical note: Abseil once provided implementations of these algorithms\n// prior to their adoption in C++14. New code should prefer to use the std\n// variants.\n//\n// See the documentation for the STL <algorithm> header for more information:\n// https://en.cppreference.com/w/cpp/header/algorithm\nusing std::equal;\nusing std::rotate;\n\n// linear_search()\n//\n// Performs a linear search for `value` using the iterator `first` up to\n// but not including `last`, returning true if [`first`, `last`) contains an\n// element equal to `value`.\n//\n// A linear search is of O(n) complexity which is guaranteed to make at most\n// n = (`last` - `first`) comparisons. A linear search over short containers\n// may be faster than a binary search, even when the container is sorted.\ntemplate <typename InputIterator, typename EqualityComparable>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search(\n    InputIterator first, InputIterator last, const EqualityComparable& value) {\n  return std::find(first, last, value) != last;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_ALGORITHM_ALGORITHM_H_\n"
  },
  {
    "path": "absl/algorithm/algorithm_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/algorithm/algorithm.h\"\n\n#include <array>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace {\n\nclass LinearSearchTest : public testing::Test {\n protected:\n  LinearSearchTest() : container_{1, 2, 3} {}\n\n  static bool Is3(int n) { return n == 3; }\n  static bool Is4(int n) { return n == 4; }\n\n  std::vector<int> container_;\n};\n\nTEST_F(LinearSearchTest, linear_search) {\n  EXPECT_TRUE(absl::linear_search(container_.begin(), container_.end(), 3));\n  EXPECT_FALSE(absl::linear_search(container_.begin(), container_.end(), 4));\n}\n\nTEST_F(LinearSearchTest, linear_searchConst) {\n  const std::vector<int> *const const_container = &container_;\n  EXPECT_TRUE(\n      absl::linear_search(const_container->begin(), const_container->end(), 3));\n  EXPECT_FALSE(\n      absl::linear_search(const_container->begin(), const_container->end(), 4));\n}\n\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\nTEST_F(LinearSearchTest, Constexpr) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::linear_search(kArray.begin(), kArray.end(), 3));\n  static_assert(!absl::linear_search(kArray.begin(), kArray.end(), 4));\n}\n\n#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&\n        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\n}  // namespace\n"
  },
  {
    "path": "absl/algorithm/container.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: container.h\n// -----------------------------------------------------------------------------\n//\n// This header file provides Container-based versions of algorithmic functions\n// within the C++ standard library. The following standard library sets of\n// functions are covered within this file:\n//\n//   * Algorithmic <iterator> functions\n//   * Algorithmic <numeric> functions\n//   * <algorithm> functions\n//\n// The standard library functions operate on iterator ranges; the functions\n// within this API operate on containers, though many return iterator ranges.\n//\n// All functions within this API are named with a `c_` prefix. Calls such as\n// `absl::c_xx(container, ...) are equivalent to std:: functions such as\n// `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on\n// iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`)\n// have no equivalent here.\n//\n// For template parameter and variable naming, `C` indicates the container type\n// to which the function is applied, `Pred` indicates the predicate object type\n// to be used by the function and `T` indicates the applicable element type.\n\n#ifndef ABSL_ALGORITHM_CONTAINER_H_\n#define ABSL_ALGORITHM_CONTAINER_H_\n\n#include <algorithm>\n#include <cassert>\n#include <iterator>\n#include <numeric>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"absl/algorithm/algorithm.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_algorithm_internal {\n\n// NOTE: it is important to defer to ADL lookup for building with C++ modules,\n// especially for headers like <valarray> which are not visible from this file\n// but specialize std::begin and std::end.\nusing std::begin;\nusing std::end;\n\n// The type of the iterator given by begin(c) (possibly std::begin(c)).\n// ContainerIter<const vector<T>> gives vector<T>::const_iterator,\n// while ContainerIter<vector<T>> gives vector<T>::iterator.\ntemplate <typename C>\nusing ContainerIter = decltype(begin(std::declval<C&>()));\n\n// An MSVC bug involving template parameter substitution requires us to use\n// decltype() here instead of just std::pair.\ntemplate <typename C1, typename C2>\nusing ContainerIterPairType = decltype(std::make_pair(\n    std::declval<ContainerIter<C1>>(), std::declval<ContainerIter<C2>>()));\n\ntemplate <typename C>\nusing ContainerDifferenceType = decltype(std::distance(\n    std::declval<ContainerIter<C>>(), std::declval<ContainerIter<C>>()));\n\ntemplate <typename C>\nusing ContainerPointerType =\n    typename std::iterator_traits<ContainerIter<C>>::pointer;\n\n// container_algorithm_internal::c_begin and\n// container_algorithm_internal::c_end are abbreviations for proper ADL\n// lookup of std::begin and std::end, i.e.\n//   using std::begin;\n//   using std::end;\n//   std::foo(begin(c), end(c));\n// becomes\n//   std::foo(container_algorithm_internal::c_begin(c),\n//            container_algorithm_internal::c_end(c));\n// These are meant for internal use only.\n\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {\n  return begin(c);\n}\n\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {\n  return end(c);\n}\n\ntemplate <typename T>\nstruct IsUnorderedContainer : std::false_type {};\n\ntemplate <class Key, class T, class Hash, class KeyEqual, class Allocator>\nstruct IsUnorderedContainer<\n    std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};\n\ntemplate <class Key, class Hash, class KeyEqual, class Allocator>\nstruct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>\n    : std::true_type {};\n\n}  // namespace container_algorithm_internal\n\n// PUBLIC API\n\n//------------------------------------------------------------------------------\n// Abseil algorithm.h functions\n//------------------------------------------------------------------------------\n\n// c_linear_search()\n//\n// Container-based version of absl::linear_search() for performing a linear\n// search within a container.\n//\n// For a generalization that uses a predicate, see absl::c_any_of().\ntemplate <typename C, typename EqualityComparable>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search(\n    const C& c, EqualityComparable&& value) {\n  return absl::linear_search(container_algorithm_internal::c_begin(c),\n                             container_algorithm_internal::c_end(c),\n                             std::forward<EqualityComparable>(value));\n}\n\n//------------------------------------------------------------------------------\n// <iterator> algorithms\n//------------------------------------------------------------------------------\n\n// c_distance()\n//\n// Container-based version of the <iterator> `std::distance()` function to\n// return the number of elements within a container.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerDifferenceType<const C>\n    c_distance(const C& c) {\n  return std::distance(container_algorithm_internal::c_begin(c),\n                       container_algorithm_internal::c_end(c));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Non-modifying sequence operations\n//------------------------------------------------------------------------------\n\n// c_all_of()\n//\n// Container-based version of the <algorithm> `std::all_of()` function to\n// test if all elements within a container satisfy a condition.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) {\n  return std::all_of(container_algorithm_internal::c_begin(c),\n                     container_algorithm_internal::c_end(c),\n                     std::forward<Pred>(pred));\n}\n\n// c_any_of()\n//\n// Container-based version of the <algorithm> `std::any_of()` function to\n// test if any element in a container fulfills a condition.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) {\n  return std::any_of(container_algorithm_internal::c_begin(c),\n                     container_algorithm_internal::c_end(c),\n                     std::forward<Pred>(pred));\n}\n\n// c_none_of()\n//\n// Container-based version of the <algorithm> `std::none_of()` function to\n// test if no elements in a container fulfill a condition.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) {\n  return std::none_of(container_algorithm_internal::c_begin(c),\n                      container_algorithm_internal::c_end(c),\n                      std::forward<Pred>(pred));\n}\n\n// c_for_each()\n//\n// Container-based version of the <algorithm> `std::for_each()` function to\n// apply a function to a container's elements.\ntemplate <typename C, typename Function>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c,\n                                                                 Function&& f) {\n  return std::for_each(container_algorithm_internal::c_begin(c),\n                       container_algorithm_internal::c_end(c),\n                       std::forward<Function>(f));\n}\n\n// c_find()\n//\n// Container-based version of the <algorithm> `std::find()` function to find\n// the first element containing the passed value within a container value.\ntemplate <typename C, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_find(C& c, T&& value) {\n  return std::find(container_algorithm_internal::c_begin(c),\n                   container_algorithm_internal::c_end(c),\n                   std::forward<T>(value));\n}\n\n// c_contains()\n//\n// Container-based version of the <algorithm> `std::ranges::contains()` C++23\n// function to search a container for a value.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence,\n                                                    T&& value) {\n  return absl::c_find(sequence, std::forward<T>(value)) !=\n         container_algorithm_internal::c_end(sequence);\n}\n\n// c_find_if()\n//\n// Container-based version of the <algorithm> `std::find_if()` function to find\n// the first element in a container matching the given condition.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_find_if(C& c, Pred&& pred) {\n  return std::find_if(container_algorithm_internal::c_begin(c),\n                      container_algorithm_internal::c_end(c),\n                      std::forward<Pred>(pred));\n}\n\n// c_find_if_not()\n//\n// Container-based version of the <algorithm> `std::find_if_not()` function to\n// find the first element in a container not matching the given condition.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_find_if_not(C& c, Pred&& pred) {\n  return std::find_if_not(container_algorithm_internal::c_begin(c),\n                          container_algorithm_internal::c_end(c),\n                          std::forward<Pred>(pred));\n}\n\n// c_find_end()\n//\n// Container-based version of the <algorithm> `std::find_end()` function to\n// find the last subsequence within a container.\ntemplate <typename Sequence1, typename Sequence2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence1>\n    c_find_end(Sequence1& sequence, Sequence2& subsequence) {\n  return std::find_end(container_algorithm_internal::c_begin(sequence),\n                       container_algorithm_internal::c_end(sequence),\n                       container_algorithm_internal::c_begin(subsequence),\n                       container_algorithm_internal::c_end(subsequence));\n}\n\n// Overload of c_find_end() for using a predicate evaluation other than `==` as\n// the function's test condition.\ntemplate <typename Sequence1, typename Sequence2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence1>\n    c_find_end(Sequence1& sequence, Sequence2& subsequence,\n               BinaryPredicate&& pred) {\n  return std::find_end(container_algorithm_internal::c_begin(sequence),\n                       container_algorithm_internal::c_end(sequence),\n                       container_algorithm_internal::c_begin(subsequence),\n                       container_algorithm_internal::c_end(subsequence),\n                       std::forward<BinaryPredicate>(pred));\n}\n\n// c_find_first_of()\n//\n// Container-based version of the <algorithm> `std::find_first_of()` function to\n// find the first element within the container that is also within the options\n// container.\ntemplate <typename C1, typename C2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C1>\n    c_find_first_of(C1& container, const C2& options) {\n  return std::find_first_of(container_algorithm_internal::c_begin(container),\n                            container_algorithm_internal::c_end(container),\n                            container_algorithm_internal::c_begin(options),\n                            container_algorithm_internal::c_end(options));\n}\n\n// Overload of c_find_first_of() for using a predicate evaluation other than\n// `==` as the function's test condition.\ntemplate <typename C1, typename C2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C1>\n    c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) {\n  return std::find_first_of(container_algorithm_internal::c_begin(container),\n                            container_algorithm_internal::c_end(container),\n                            container_algorithm_internal::c_begin(options),\n                            container_algorithm_internal::c_end(options),\n                            std::forward<BinaryPredicate>(pred));\n}\n\n// c_adjacent_find()\n//\n// Container-based version of the <algorithm> `std::adjacent_find()` function to\n// find equal adjacent elements within a container.\ntemplate <typename Sequence>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_adjacent_find(Sequence& sequence) {\n  return std::adjacent_find(container_algorithm_internal::c_begin(sequence),\n                            container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_adjacent_find() for using a predicate evaluation other than\n// `==` as the function's test condition.\ntemplate <typename Sequence, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) {\n  return std::adjacent_find(container_algorithm_internal::c_begin(sequence),\n                            container_algorithm_internal::c_end(sequence),\n                            std::forward<BinaryPredicate>(pred));\n}\n\n// c_count()\n//\n// Container-based version of the <algorithm> `std::count()` function to count\n// values that match within a container.\ntemplate <typename C, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerDifferenceType<const C>\n    c_count(const C& c, T&& value) {\n  return std::count(container_algorithm_internal::c_begin(c),\n                    container_algorithm_internal::c_end(c),\n                    std::forward<T>(value));\n}\n\n// c_count_if()\n//\n// Container-based version of the <algorithm> `std::count_if()` function to\n// count values matching a condition within a container.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerDifferenceType<const C>\n    c_count_if(const C& c, Pred&& pred) {\n  return std::count_if(container_algorithm_internal::c_begin(c),\n                       container_algorithm_internal::c_end(c),\n                       std::forward<Pred>(pred));\n}\n\n// c_mismatch()\n//\n// Container-based version of the <algorithm> `std::mismatch()` function to\n// return the first element where two ordered containers differ. Applies `==` to\n// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).\ntemplate <typename C1, typename C2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIterPairType<C1, C2>\n    c_mismatch(C1& c1, C2& c2) {\n  return std::mismatch(container_algorithm_internal::c_begin(c1),\n                       container_algorithm_internal::c_end(c1),\n                       container_algorithm_internal::c_begin(c2),\n                       container_algorithm_internal::c_end(c2));\n}\n\n// Overload of c_mismatch() for using a predicate evaluation other than `==` as\n// the function's test condition. Applies `pred`to the first N elements of `c1`\n// and `c2`, where N = min(size(c1), size(c2)).\ntemplate <typename C1, typename C2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIterPairType<C1, C2>\n    c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {\n  return std::mismatch(container_algorithm_internal::c_begin(c1),\n                       container_algorithm_internal::c_end(c1),\n                       container_algorithm_internal::c_begin(c2),\n                       container_algorithm_internal::c_end(c2), pred);\n}\n\n// c_equal()\n//\n// Container-based version of the <algorithm> `std::equal()` function to\n// test whether two containers are equal.\ntemplate <typename C1, typename C2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) {\n  return std::equal(container_algorithm_internal::c_begin(c1),\n                    container_algorithm_internal::c_end(c1),\n                    container_algorithm_internal::c_begin(c2),\n                    container_algorithm_internal::c_end(c2));\n}\n\n// Overload of c_equal() for using a predicate evaluation other than `==` as\n// the function's test condition.\ntemplate <typename C1, typename C2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2,\n                                                 BinaryPredicate&& pred) {\n  return std::equal(container_algorithm_internal::c_begin(c1),\n                    container_algorithm_internal::c_end(c1),\n                    container_algorithm_internal::c_begin(c2),\n                    container_algorithm_internal::c_end(c2),\n                    std::forward<BinaryPredicate>(pred));\n}\n\n// c_is_permutation()\n//\n// Container-based version of the <algorithm> `std::is_permutation()` function\n// to test whether a container is a permutation of another.\ntemplate <typename C1, typename C2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1,\n                                                          const C2& c2) {\n  return std::is_permutation(container_algorithm_internal::c_begin(c1),\n                             container_algorithm_internal::c_end(c1),\n                             container_algorithm_internal::c_begin(c2),\n                             container_algorithm_internal::c_end(c2));\n}\n\n// Overload of c_is_permutation() for using a predicate evaluation other than\n// `==` as the function's test condition.\ntemplate <typename C1, typename C2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(\n    const C1& c1, const C2& c2, BinaryPredicate&& pred) {\n  return std::is_permutation(container_algorithm_internal::c_begin(c1),\n                             container_algorithm_internal::c_end(c1),\n                             container_algorithm_internal::c_begin(c2),\n                             container_algorithm_internal::c_end(c2),\n                             std::forward<BinaryPredicate>(pred));\n}\n\n// c_search()\n//\n// Container-based version of the <algorithm> `std::search()` function to search\n// a container for a subsequence.\ntemplate <typename Sequence1, typename Sequence2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence1>\n    c_search(Sequence1& sequence, Sequence2& subsequence) {\n  return std::search(container_algorithm_internal::c_begin(sequence),\n                     container_algorithm_internal::c_end(sequence),\n                     container_algorithm_internal::c_begin(subsequence),\n                     container_algorithm_internal::c_end(subsequence));\n}\n\n// Overload of c_search() for using a predicate evaluation other than\n// `==` as the function's test condition.\ntemplate <typename Sequence1, typename Sequence2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence1>\n    c_search(Sequence1& sequence, Sequence2& subsequence,\n             BinaryPredicate&& pred) {\n  return std::search(container_algorithm_internal::c_begin(sequence),\n                     container_algorithm_internal::c_end(sequence),\n                     container_algorithm_internal::c_begin(subsequence),\n                     container_algorithm_internal::c_end(subsequence),\n                     std::forward<BinaryPredicate>(pred));\n}\n\n// c_contains_subrange()\n//\n// Container-based version of the <algorithm> `std::ranges::contains_subrange()`\n// C++23 function to search a container for a subsequence.\ntemplate <typename Sequence1, typename Sequence2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(\n    Sequence1& sequence, Sequence2& subsequence) {\n  return absl::c_search(sequence, subsequence) !=\n         container_algorithm_internal::c_end(sequence);\n}\n\n// Overload of c_contains_subrange() for using a predicate evaluation other than\n// `==` as the function's test condition.\ntemplate <typename Sequence1, typename Sequence2, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(\n    Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {\n  return absl::c_search(sequence, subsequence,\n                        std::forward<BinaryPredicate>(pred)) !=\n         container_algorithm_internal::c_end(sequence);\n}\n\n// c_search_n()\n//\n// Container-based version of the <algorithm> `std::search_n()` function to\n// search a container for the first sequence of N elements.\ntemplate <typename Sequence, typename Size, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_search_n(Sequence& sequence, Size count, T&& value) {\n  return std::search_n(container_algorithm_internal::c_begin(sequence),\n                       container_algorithm_internal::c_end(sequence), count,\n                       std::forward<T>(value));\n}\n\n// Overload of c_search_n() for using a predicate evaluation other than\n// `==` as the function's test condition.\ntemplate <typename Sequence, typename Size, typename T,\n          typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_search_n(Sequence& sequence, Size count, T&& value,\n               BinaryPredicate&& pred) {\n  return std::search_n(container_algorithm_internal::c_begin(sequence),\n                       container_algorithm_internal::c_end(sequence), count,\n                       std::forward<T>(value),\n                       std::forward<BinaryPredicate>(pred));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Modifying sequence operations\n//------------------------------------------------------------------------------\n\n// c_copy()\n//\n// Container-based version of the <algorithm> `std::copy()` function to copy a\n// container's elements into an iterator.\ntemplate <typename InputSequence, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_copy(const InputSequence& input, OutputIterator output) {\n  return std::copy(container_algorithm_internal::c_begin(input),\n                   container_algorithm_internal::c_end(input), output);\n}\n\n// c_copy_n()\n//\n// Container-based version of the <algorithm> `std::copy_n()` function to copy a\n// container's first N elements into an iterator.\ntemplate <typename C, typename Size, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_copy_n(const C& input, Size n, OutputIterator output) {\n  return std::copy_n(container_algorithm_internal::c_begin(input), n, output);\n}\n\n// c_copy_if()\n//\n// Container-based version of the <algorithm> `std::copy_if()` function to copy\n// a container's elements satisfying some condition into an iterator.\ntemplate <typename InputSequence, typename OutputIterator, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_copy_if(const InputSequence& input, OutputIterator output, Pred&& pred) {\n  return std::copy_if(container_algorithm_internal::c_begin(input),\n                      container_algorithm_internal::c_end(input), output,\n                      std::forward<Pred>(pred));\n}\n\n// c_copy_backward()\n//\n// Container-based version of the <algorithm> `std::copy_backward()` function to\n// copy a container's elements in reverse order into an iterator.\ntemplate <typename C, typename BidirectionalIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 BidirectionalIterator\nc_copy_backward(const C& src, BidirectionalIterator dest) {\n  return std::copy_backward(container_algorithm_internal::c_begin(src),\n                            container_algorithm_internal::c_end(src), dest);\n}\n\n// c_move()\n//\n// Container-based version of the <algorithm> `std::move()` function to move\n// a container's elements into an iterator.\ntemplate <typename C, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_move(C&& src,\n                                                          OutputIterator dest) {\n  return std::move(container_algorithm_internal::c_begin(src),\n                   container_algorithm_internal::c_end(src), dest);\n}\n\n// c_move_backward()\n//\n// Container-based version of the <algorithm> `std::move_backward()` function to\n// move a container's elements into an iterator in reverse order.\ntemplate <typename C, typename BidirectionalIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 BidirectionalIterator\nc_move_backward(C&& src, BidirectionalIterator dest) {\n  return std::move_backward(container_algorithm_internal::c_begin(src),\n                            container_algorithm_internal::c_end(src), dest);\n}\n\n// c_swap_ranges()\n//\n// Container-based version of the <algorithm> `std::swap_ranges()` function to\n// swap a container's elements with another container's elements. Swaps the\n// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).\ntemplate <typename C1, typename C2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C2>\n    c_swap_ranges(C1& c1, C2& c2) {\n  auto first1 = container_algorithm_internal::c_begin(c1);\n  auto last1 = container_algorithm_internal::c_end(c1);\n  auto first2 = container_algorithm_internal::c_begin(c2);\n  auto last2 = container_algorithm_internal::c_end(c2);\n\n  using std::swap;\n  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {\n    swap(*first1, *first2);\n  }\n  return first2;\n}\n\n// c_transform()\n//\n// Container-based version of the <algorithm> `std::transform()` function to\n// transform a container's elements using the unary operation, storing the\n// result in an iterator pointing to the last transformed element in the output\n// range.\ntemplate <typename InputSequence, typename OutputIterator, typename UnaryOp>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_transform(\n    const InputSequence& input, OutputIterator output, UnaryOp&& unary_op) {\n  return std::transform(container_algorithm_internal::c_begin(input),\n                        container_algorithm_internal::c_end(input), output,\n                        std::forward<UnaryOp>(unary_op));\n}\n\n// Overload of c_transform() for performing a transformation using a binary\n// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,\n// where N = min(size(c1), size(c2)).\ntemplate <typename InputSequence1, typename InputSequence2,\n          typename OutputIterator, typename BinaryOp>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_transform(const InputSequence1& input1, const InputSequence2& input2,\n            OutputIterator output, BinaryOp&& binary_op) {\n  auto first1 = container_algorithm_internal::c_begin(input1);\n  auto last1 = container_algorithm_internal::c_end(input1);\n  auto first2 = container_algorithm_internal::c_begin(input2);\n  auto last2 = container_algorithm_internal::c_end(input2);\n  for (; first1 != last1 && first2 != last2;\n       ++first1, (void)++first2, ++output) {\n    *output = binary_op(*first1, *first2);\n  }\n\n  return output;\n}\n\n// c_replace()\n//\n// Container-based version of the <algorithm> `std::replace()` function to\n// replace a container's elements of some value with a new value. The container\n// is modified in place.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_replace(Sequence& sequence,\n                                                   const T& old_value,\n                                                   const T& new_value) {\n  std::replace(container_algorithm_internal::c_begin(sequence),\n               container_algorithm_internal::c_end(sequence), old_value,\n               new_value);\n}\n\n// c_replace_if()\n//\n// Container-based version of the <algorithm> `std::replace_if()` function to\n// replace a container's elements of some value with a new value based on some\n// condition. The container is modified in place.\ntemplate <typename C, typename Pred, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_replace_if(C& c, Pred&& pred,\n                                                      T&& new_value) {\n  std::replace_if(container_algorithm_internal::c_begin(c),\n                  container_algorithm_internal::c_end(c),\n                  std::forward<Pred>(pred), std::forward<T>(new_value));\n}\n\n// c_replace_copy()\n//\n// Container-based version of the <algorithm> `std::replace_copy()` function to\n// replace a container's elements of some value with a new value  and return the\n// results within an iterator.\ntemplate <typename C, typename OutputIterator, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_replace_copy(\n    const C& c, OutputIterator result, T&& old_value, T&& new_value) {\n  return std::replace_copy(container_algorithm_internal::c_begin(c),\n                           container_algorithm_internal::c_end(c), result,\n                           std::forward<T>(old_value),\n                           std::forward<T>(new_value));\n}\n\n// c_replace_copy_if()\n//\n// Container-based version of the <algorithm> `std::replace_copy_if()` function\n// to replace a container's elements of some value with a new value based on\n// some condition, and return the results within an iterator.\ntemplate <typename C, typename OutputIterator, typename Pred, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_replace_copy_if(\n    const C& c, OutputIterator result, Pred&& pred, const T& new_value) {\n  return std::replace_copy_if(container_algorithm_internal::c_begin(c),\n                              container_algorithm_internal::c_end(c), result,\n                              std::forward<Pred>(pred), new_value);\n}\n\n// c_fill()\n//\n// Container-based version of the <algorithm> `std::fill()` function to fill a\n// container with some value.\ntemplate <typename C, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_fill(C& c, const T& value) {\n  std::fill(container_algorithm_internal::c_begin(c),\n            container_algorithm_internal::c_end(c), value);\n}\n\n// c_fill_n()\n//\n// Container-based version of the <algorithm> `std::fill_n()` function to fill\n// the first N elements in a container with some value.\ntemplate <typename C, typename Size, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_fill_n(C& c, Size n,\n                                                  const T& value) {\n  std::fill_n(container_algorithm_internal::c_begin(c), n, value);\n}\n\n// c_generate()\n//\n// Container-based version of the <algorithm> `std::generate()` function to\n// assign a container's elements to the values provided by the given generator.\ntemplate <typename C, typename Generator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_generate(C& c, Generator&& gen) {\n  std::generate(container_algorithm_internal::c_begin(c),\n                container_algorithm_internal::c_end(c),\n                std::forward<Generator>(gen));\n}\n\n// c_generate_n()\n//\n// Container-based version of the <algorithm> `std::generate_n()` function to\n// assign a container's first N elements to the values provided by the given\n// generator.\ntemplate <typename C, typename Size, typename Generator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_generate_n(C& c, Size n, Generator&& gen) {\n  return std::generate_n(container_algorithm_internal::c_begin(c), n,\n                         std::forward<Generator>(gen));\n}\n\n// Note: `c_xx()` <algorithm> container versions for `remove()`, `remove_if()`,\n// and `unique()` are omitted, because it's not clear whether or not such\n// functions should call erase on their supplied sequences afterwards. Either\n// behavior would be surprising for a different set of users.\n\n// c_remove_copy()\n//\n// Container-based version of the <algorithm> `std::remove_copy()` function to\n// copy a container's elements while removing any elements matching the given\n// `value`.\ntemplate <typename C, typename OutputIterator, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_remove_copy(const C& c, OutputIterator result, const T& value) {\n  return std::remove_copy(container_algorithm_internal::c_begin(c),\n                          container_algorithm_internal::c_end(c), result,\n                          value);\n}\n\n// c_remove_copy_if()\n//\n// Container-based version of the <algorithm> `std::remove_copy_if()` function\n// to copy a container's elements while removing any elements matching the given\n// condition.\ntemplate <typename C, typename OutputIterator, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_remove_copy_if(const C& c, OutputIterator result, Pred&& pred) {\n  return std::remove_copy_if(container_algorithm_internal::c_begin(c),\n                             container_algorithm_internal::c_end(c), result,\n                             std::forward<Pred>(pred));\n}\n\n// c_unique_copy()\n//\n// Container-based version of the <algorithm> `std::unique_copy()` function to\n// copy a container's elements while removing any elements containing duplicate\n// values.\ntemplate <typename C, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_unique_copy(const C& c, OutputIterator result) {\n  return std::unique_copy(container_algorithm_internal::c_begin(c),\n                          container_algorithm_internal::c_end(c), result);\n}\n\n// Overload of c_unique_copy() for using a predicate evaluation other than\n// `==` for comparing uniqueness of the element values.\ntemplate <typename C, typename OutputIterator, typename BinaryPredicate>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_unique_copy(const C& c, OutputIterator result, BinaryPredicate&& pred) {\n  return std::unique_copy(container_algorithm_internal::c_begin(c),\n                          container_algorithm_internal::c_end(c), result,\n                          std::forward<BinaryPredicate>(pred));\n}\n\n// c_reverse()\n//\n// Container-based version of the <algorithm> `std::reverse()` function to\n// reverse a container's elements.\ntemplate <typename Sequence>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_reverse(Sequence& sequence) {\n  std::reverse(container_algorithm_internal::c_begin(sequence),\n               container_algorithm_internal::c_end(sequence));\n}\n\n// c_reverse_copy()\n//\n// Container-based version of the <algorithm> `std::reverse()` function to\n// reverse a container's elements and write them to an iterator range.\ntemplate <typename C, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_reverse_copy(const C& sequence, OutputIterator result) {\n  return std::reverse_copy(container_algorithm_internal::c_begin(sequence),\n                           container_algorithm_internal::c_end(sequence),\n                           result);\n}\n\n// c_rotate()\n//\n// Container-based version of the <algorithm> `std::rotate()` function to\n// shift a container's elements leftward such that the `middle` element becomes\n// the first element in the container.\ntemplate <typename C,\n          typename Iterator = container_algorithm_internal::ContainerIter<C>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 Iterator c_rotate(C& sequence,\n                                                      Iterator middle) {\n  return absl::rotate(container_algorithm_internal::c_begin(sequence), middle,\n                      container_algorithm_internal::c_end(sequence));\n}\n\n// c_rotate_copy()\n//\n// Container-based version of the <algorithm> `std::rotate_copy()` function to\n// shift a container's elements leftward such that the `middle` element becomes\n// the first element in a new iterator range.\ntemplate <typename C, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_rotate_copy(const C& sequence,\n              container_algorithm_internal::ContainerIter<const C> middle,\n              OutputIterator result) {\n  return std::rotate_copy(container_algorithm_internal::c_begin(sequence),\n                          middle, container_algorithm_internal::c_end(sequence),\n                          result);\n}\n\n// c_shuffle()\n//\n// Container-based version of the <algorithm> `std::shuffle()` function to\n// randomly shuffle elements within the container using a `gen()` uniform random\n// number generator.\ntemplate <typename RandomAccessContainer, typename UniformRandomBitGenerator>\nvoid c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) {\n  std::shuffle(container_algorithm_internal::c_begin(c),\n               container_algorithm_internal::c_end(c),\n               std::forward<UniformRandomBitGenerator>(gen));\n}\n\n// c_sample()\n//\n// Container-based version of the <algorithm> `std::sample()` function to\n// randomly sample elements from the container without replacement using a\n// `gen()` uniform random number generator and write them to an iterator range.\ntemplate <typename C, typename OutputIterator, typename Distance,\n          typename UniformRandomBitGenerator>\nOutputIterator c_sample(const C& c, OutputIterator result, Distance n,\n                        UniformRandomBitGenerator&& gen) {\n  return std::sample(container_algorithm_internal::c_begin(c),\n                     container_algorithm_internal::c_end(c), result, n,\n                     std::forward<UniformRandomBitGenerator>(gen));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Partition functions\n//------------------------------------------------------------------------------\n\n// c_is_partitioned()\n//\n// Container-based version of the <algorithm> `std::is_partitioned()` function\n// to test whether all elements in the container for which `pred` returns `true`\n// precede those for which `pred` is `false`.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_partitioned(const C& c,\n                                                          Pred&& pred) {\n  return std::is_partitioned(container_algorithm_internal::c_begin(c),\n                             container_algorithm_internal::c_end(c),\n                             std::forward<Pred>(pred));\n}\n\n// c_partition()\n//\n// Container-based version of the <algorithm> `std::partition()` function\n// to rearrange all elements in a container in such a way that all elements for\n// which `pred` returns `true` precede all those for which it returns `false`,\n// returning an iterator to the first element of the second group.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_partition(C& c, Pred&& pred) {\n  return std::partition(container_algorithm_internal::c_begin(c),\n                        container_algorithm_internal::c_end(c),\n                        std::forward<Pred>(pred));\n}\n\n// c_stable_partition()\n//\n// Container-based version of the <algorithm> `std::stable_partition()` function\n// to rearrange all elements in a container in such a way that all elements for\n// which `pred` returns `true` precede all those for which it returns `false`,\n// preserving the relative ordering between the two groups. The function returns\n// an iterator to the first element of the second group.\ntemplate <typename C, typename Pred>\ncontainer_algorithm_internal::ContainerIter<C> c_stable_partition(C& c,\n                                                                  Pred&& pred) {\n  return std::stable_partition(container_algorithm_internal::c_begin(c),\n                               container_algorithm_internal::c_end(c),\n                               std::forward<Pred>(pred));\n}\n\n// c_partition_copy()\n//\n// Container-based version of the <algorithm> `std::partition_copy()` function\n// to partition a container's elements and return them into two iterators: one\n// for which `pred` returns `true`, and one for which `pred` returns `false.`\n\ntemplate <typename C, typename OutputIterator1, typename OutputIterator2,\n          typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::pair<OutputIterator1, OutputIterator2>\nc_partition_copy(const C& c, OutputIterator1 out_true,\n                 OutputIterator2 out_false, Pred&& pred) {\n  return std::partition_copy(container_algorithm_internal::c_begin(c),\n                             container_algorithm_internal::c_end(c), out_true,\n                             out_false, std::forward<Pred>(pred));\n}\n\n// c_partition_point()\n//\n// Container-based version of the <algorithm> `std::partition_point()` function\n// to return the first element of an already partitioned container for which\n// the given `pred` is not `true`.\ntemplate <typename C, typename Pred>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_partition_point(C& c, Pred&& pred) {\n  return std::partition_point(container_algorithm_internal::c_begin(c),\n                              container_algorithm_internal::c_end(c),\n                              std::forward<Pred>(pred));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Sorting functions\n//------------------------------------------------------------------------------\n\n// c_sort()\n//\n// Container-based version of the <algorithm> `std::sort()` function\n// to sort elements in ascending order of their values.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort(C& c) {\n  std::sort(container_algorithm_internal::c_begin(c),\n            container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_sort() for performing a `comp` comparison other than the\n// default `operator<`.\ntemplate <typename C, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort(C& c, LessThan&& comp) {\n  std::sort(container_algorithm_internal::c_begin(c),\n            container_algorithm_internal::c_end(c),\n            std::forward<LessThan>(comp));\n}\n\n// c_stable_sort()\n//\n// Container-based version of the <algorithm> `std::stable_sort()` function\n// to sort elements in ascending order of their values, preserving the order\n// of equivalents.\ntemplate <typename C>\nvoid c_stable_sort(C& c) {\n  std::stable_sort(container_algorithm_internal::c_begin(c),\n                   container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_stable_sort() for performing a `comp` comparison other than the\n// default `operator<`.\ntemplate <typename C, typename LessThan>\nvoid c_stable_sort(C& c, LessThan&& comp) {\n  std::stable_sort(container_algorithm_internal::c_begin(c),\n                   container_algorithm_internal::c_end(c),\n                   std::forward<LessThan>(comp));\n}\n\n// c_is_sorted()\n//\n// Container-based version of the <algorithm> `std::is_sorted()` function\n// to evaluate whether the given container is sorted in ascending order.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_sorted(const C& c) {\n  return std::is_sorted(container_algorithm_internal::c_begin(c),\n                        container_algorithm_internal::c_end(c));\n}\n\n// c_is_sorted() overload for performing a `comp` comparison other than the\n// default `operator<`.\ntemplate <typename C, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_sorted(const C& c,\n                                                     LessThan&& comp) {\n  return std::is_sorted(container_algorithm_internal::c_begin(c),\n                        container_algorithm_internal::c_end(c),\n                        std::forward<LessThan>(comp));\n}\n\n// c_partial_sort()\n//\n// Container-based version of the <algorithm> `std::partial_sort()` function\n// to rearrange elements within a container such that elements before `middle`\n// are sorted in ascending order.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_partial_sort(\n    RandomAccessContainer& sequence,\n    container_algorithm_internal::ContainerIter<RandomAccessContainer> middle) {\n  std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,\n                    container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_partial_sort() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_partial_sort(\n    RandomAccessContainer& sequence,\n    container_algorithm_internal::ContainerIter<RandomAccessContainer> middle,\n    LessThan&& comp) {\n  std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,\n                    container_algorithm_internal::c_end(sequence),\n                    std::forward<LessThan>(comp));\n}\n\n// c_partial_sort_copy()\n//\n// Container-based version of the <algorithm> `std::partial_sort_copy()`\n// function to sort the elements in the given range `result` within the larger\n// `sequence` in ascending order (and using `result` as the output parameter).\n// At most min(result.last - result.first, sequence.last - sequence.first)\n// elements from the sequence will be stored in the result.\ntemplate <typename C, typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<RandomAccessContainer>\n    c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {\n  return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),\n                                container_algorithm_internal::c_end(sequence),\n                                container_algorithm_internal::c_begin(result),\n                                container_algorithm_internal::c_end(result));\n}\n\n// Overload of c_partial_sort_copy() for performing a `comp` comparison other\n// than the default `operator<`.\ntemplate <typename C, typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<RandomAccessContainer>\n    c_partial_sort_copy(const C& sequence, RandomAccessContainer& result,\n                        LessThan&& comp) {\n  return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),\n                                container_algorithm_internal::c_end(sequence),\n                                container_algorithm_internal::c_begin(result),\n                                container_algorithm_internal::c_end(result),\n                                std::forward<LessThan>(comp));\n}\n\n// c_is_sorted_until()\n//\n// Container-based version of the <algorithm> `std::is_sorted_until()` function\n// to return the first element within a container that is not sorted in\n// ascending order as an iterator.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_is_sorted_until(C& c) {\n  return std::is_sorted_until(container_algorithm_internal::c_begin(c),\n                              container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_is_sorted_until() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename C, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<C>\n    c_is_sorted_until(C& c, LessThan&& comp) {\n  return std::is_sorted_until(container_algorithm_internal::c_begin(c),\n                              container_algorithm_internal::c_end(c),\n                              std::forward<LessThan>(comp));\n}\n\n// c_nth_element()\n//\n// Container-based version of the <algorithm> `std::nth_element()` function\n// to rearrange the elements within a container such that the `nth` element\n// would be in that position in an ordered sequence; other elements may be in\n// any order, except that all preceding `nth` will be less than that element,\n// and all following `nth` will be greater than that element.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_nth_element(\n    RandomAccessContainer& sequence,\n    container_algorithm_internal::ContainerIter<RandomAccessContainer> nth) {\n  std::nth_element(container_algorithm_internal::c_begin(sequence), nth,\n                   container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_nth_element() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_nth_element(\n    RandomAccessContainer& sequence,\n    container_algorithm_internal::ContainerIter<RandomAccessContainer> nth,\n    LessThan&& comp) {\n  std::nth_element(container_algorithm_internal::c_begin(sequence), nth,\n                   container_algorithm_internal::c_end(sequence),\n                   std::forward<LessThan>(comp));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Binary Search\n//------------------------------------------------------------------------------\n\n// c_lower_bound()\n//\n// Container-based version of the <algorithm> `std::lower_bound()` function\n// to return an iterator pointing to the first element in a sorted container\n// which does not compare less than `value`.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_lower_bound(Sequence& sequence, const T& value) {\n  return std::lower_bound(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence), value);\n}\n\n// Overload of c_lower_bound() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename Sequence, typename T, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_lower_bound(Sequence& sequence, const T& value, LessThan&& comp) {\n  return std::lower_bound(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence), value,\n                          std::forward<LessThan>(comp));\n}\n\n// c_upper_bound()\n//\n// Container-based version of the <algorithm> `std::upper_bound()` function\n// to return an iterator pointing to the first element in a sorted container\n// which is greater than `value`.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_upper_bound(Sequence& sequence, const T& value) {\n  return std::upper_bound(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence), value);\n}\n\n// Overload of c_upper_bound() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename Sequence, typename T, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_upper_bound(Sequence& sequence, const T& value, LessThan&& comp) {\n  return std::upper_bound(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence), value,\n                          std::forward<LessThan>(comp));\n}\n\n// c_equal_range()\n//\n// Container-based version of the <algorithm> `std::equal_range()` function\n// to return an iterator pair pointing to the first and last elements in a\n// sorted container which compare equal to `value`.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>\n    c_equal_range(Sequence& sequence, const T& value) {\n  return std::equal_range(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence), value);\n}\n\n// Overload of c_equal_range() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename Sequence, typename T, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>\n    c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) {\n  return std::equal_range(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence), value,\n                          std::forward<LessThan>(comp));\n}\n\n// c_binary_search()\n//\n// Container-based version of the <algorithm> `std::binary_search()` function\n// to test if any element in the sorted container contains a value equivalent to\n// 'value'.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_binary_search(\n    const Sequence& sequence, const T& value) {\n  return std::binary_search(container_algorithm_internal::c_begin(sequence),\n                            container_algorithm_internal::c_end(sequence),\n                            value);\n}\n\n// Overload of c_binary_search() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename Sequence, typename T, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_binary_search(\n    const Sequence& sequence, const T& value, LessThan&& comp) {\n  return std::binary_search(container_algorithm_internal::c_begin(sequence),\n                            container_algorithm_internal::c_end(sequence),\n                            value, std::forward<LessThan>(comp));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Merge functions\n//------------------------------------------------------------------------------\n\n// c_merge()\n//\n// Container-based version of the <algorithm> `std::merge()` function\n// to merge two sorted containers into a single sorted iterator.\ntemplate <typename C1, typename C2, typename OutputIterator>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_merge(const C1& c1, const C2& c2, OutputIterator result) {\n  return std::merge(container_algorithm_internal::c_begin(c1),\n                    container_algorithm_internal::c_end(c1),\n                    container_algorithm_internal::c_begin(c2),\n                    container_algorithm_internal::c_end(c2), result);\n}\n\n// Overload of c_merge() for performing a `comp` comparison other than\n// the default `operator<`.\ntemplate <typename C1, typename C2, typename OutputIterator, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_merge(const C1& c1, const C2& c2, OutputIterator result, LessThan&& comp) {\n  return std::merge(container_algorithm_internal::c_begin(c1),\n                    container_algorithm_internal::c_end(c1),\n                    container_algorithm_internal::c_begin(c2),\n                    container_algorithm_internal::c_end(c2), result,\n                    std::forward<LessThan>(comp));\n}\n\n// c_inplace_merge()\n//\n// Container-based version of the <algorithm> `std::inplace_merge()` function\n// to merge a supplied iterator `middle` into a container.\ntemplate <typename C>\nvoid c_inplace_merge(C& c,\n                     container_algorithm_internal::ContainerIter<C> middle) {\n  std::inplace_merge(container_algorithm_internal::c_begin(c), middle,\n                     container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_inplace_merge() for performing a merge using a `comp` other\n// than `operator<`.\ntemplate <typename C, typename LessThan>\nvoid c_inplace_merge(C& c,\n                     container_algorithm_internal::ContainerIter<C> middle,\n                     LessThan&& comp) {\n  std::inplace_merge(container_algorithm_internal::c_begin(c), middle,\n                     container_algorithm_internal::c_end(c),\n                     std::forward<LessThan>(comp));\n}\n\n// c_includes()\n//\n// Container-based version of the <algorithm> `std::includes()` function\n// to test whether a sorted container `c1` entirely contains another sorted\n// container `c2`.\ntemplate <typename C1, typename C2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_includes(const C1& c1,\n                                                    const C2& c2) {\n  return std::includes(container_algorithm_internal::c_begin(c1),\n                       container_algorithm_internal::c_end(c1),\n                       container_algorithm_internal::c_begin(c2),\n                       container_algorithm_internal::c_end(c2));\n}\n\n// Overload of c_includes() for performing a merge using a `comp` other than\n// `operator<`.\ntemplate <typename C1, typename C2, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_includes(const C1& c1, const C2& c2,\n                                                    LessThan&& comp) {\n  return std::includes(container_algorithm_internal::c_begin(c1),\n                       container_algorithm_internal::c_end(c1),\n                       container_algorithm_internal::c_begin(c2),\n                       container_algorithm_internal::c_end(c2),\n                       std::forward<LessThan>(comp));\n}\n\n// c_set_union()\n//\n// Container-based version of the <algorithm> `std::set_union()` function\n// to return an iterator containing the union of two containers; duplicate\n// values are not copied into the output.\ntemplate <typename C1, typename C2, typename OutputIterator,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_set_union(const C1& c1, const C2& c2, OutputIterator output) {\n  return std::set_union(container_algorithm_internal::c_begin(c1),\n                        container_algorithm_internal::c_end(c1),\n                        container_algorithm_internal::c_begin(c2),\n                        container_algorithm_internal::c_end(c2), output);\n}\n\n// Overload of c_set_union() for performing a merge using a `comp` other than\n// `operator<`.\ntemplate <typename C1, typename C2, typename OutputIterator, typename LessThan,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_union(\n    const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) {\n  return std::set_union(container_algorithm_internal::c_begin(c1),\n                        container_algorithm_internal::c_end(c1),\n                        container_algorithm_internal::c_begin(c2),\n                        container_algorithm_internal::c_end(c2), output,\n                        std::forward<LessThan>(comp));\n}\n\n// c_set_intersection()\n//\n// Container-based version of the <algorithm> `std::set_intersection()` function\n// to return an iterator containing the intersection of two sorted containers.\ntemplate <typename C1, typename C2, typename OutputIterator,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_set_intersection(const C1& c1, const C2& c2, OutputIterator output) {\n  // In debug builds, ensure that both containers are sorted with respect to the\n  // default comparator. std::set_intersection requires the containers be sorted\n  // using operator<.\n  ABSL_ASSERT(absl::c_is_sorted(c1));\n  ABSL_ASSERT(absl::c_is_sorted(c2));\n  return std::set_intersection(container_algorithm_internal::c_begin(c1),\n                               container_algorithm_internal::c_end(c1),\n                               container_algorithm_internal::c_begin(c2),\n                               container_algorithm_internal::c_end(c2), output);\n}\n\n// Overload of c_set_intersection() for performing a merge using a `comp` other\n// than `operator<`.\ntemplate <typename C1, typename C2, typename OutputIterator, typename LessThan,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_intersection(\n    const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) {\n  // In debug builds, ensure that both containers are sorted with respect to the\n  // default comparator. std::set_intersection requires the containers be sorted\n  // using the same comparator.\n  ABSL_ASSERT(absl::c_is_sorted(c1, comp));\n  ABSL_ASSERT(absl::c_is_sorted(c2, comp));\n  return std::set_intersection(container_algorithm_internal::c_begin(c1),\n                               container_algorithm_internal::c_end(c1),\n                               container_algorithm_internal::c_begin(c2),\n                               container_algorithm_internal::c_end(c2), output,\n                               std::forward<LessThan>(comp));\n}\n\n// c_set_difference()\n//\n// Container-based version of the <algorithm> `std::set_difference()` function\n// to return an iterator containing elements present in the first container but\n// not in the second.\ntemplate <typename C1, typename C2, typename OutputIterator,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_set_difference(const C1& c1, const C2& c2, OutputIterator output) {\n  return std::set_difference(container_algorithm_internal::c_begin(c1),\n                             container_algorithm_internal::c_end(c1),\n                             container_algorithm_internal::c_begin(c2),\n                             container_algorithm_internal::c_end(c2), output);\n}\n\n// Overload of c_set_difference() for performing a merge using a `comp` other\n// than `operator<`.\ntemplate <typename C1, typename C2, typename OutputIterator, typename LessThan,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_difference(\n    const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) {\n  return std::set_difference(container_algorithm_internal::c_begin(c1),\n                             container_algorithm_internal::c_end(c1),\n                             container_algorithm_internal::c_begin(c2),\n                             container_algorithm_internal::c_end(c2), output,\n                             std::forward<LessThan>(comp));\n}\n\n// c_set_symmetric_difference()\n//\n// Container-based version of the <algorithm> `std::set_symmetric_difference()`\n// function to return an iterator containing elements present in either one\n// container or the other, but not both.\ntemplate <typename C1, typename C2, typename OutputIterator,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator\nc_set_symmetric_difference(const C1& c1, const C2& c2, OutputIterator output) {\n  return std::set_symmetric_difference(\n      container_algorithm_internal::c_begin(c1),\n      container_algorithm_internal::c_end(c1),\n      container_algorithm_internal::c_begin(c2),\n      container_algorithm_internal::c_end(c2), output);\n}\n\n// Overload of c_set_symmetric_difference() for performing a merge using a\n// `comp` other than `operator<`.\ntemplate <typename C1, typename C2, typename OutputIterator, typename LessThan,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C1>::value,\n              void>::type,\n          typename = typename std::enable_if<\n              !container_algorithm_internal::IsUnorderedContainer<C2>::value,\n              void>::type>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_symmetric_difference(\n    const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) {\n  return std::set_symmetric_difference(\n      container_algorithm_internal::c_begin(c1),\n      container_algorithm_internal::c_end(c1),\n      container_algorithm_internal::c_begin(c2),\n      container_algorithm_internal::c_end(c2), output,\n      std::forward<LessThan>(comp));\n}\n\n//------------------------------------------------------------------------------\n// <algorithm> Heap functions\n//------------------------------------------------------------------------------\n\n// c_push_heap()\n//\n// Container-based version of the <algorithm> `std::push_heap()` function\n// to push a value onto a container heap.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_push_heap(\n    RandomAccessContainer& sequence) {\n  std::push_heap(container_algorithm_internal::c_begin(sequence),\n                 container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_push_heap() for performing a push operation on a heap using a\n// `comp` other than `operator<`.\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_push_heap(\n    RandomAccessContainer& sequence, LessThan&& comp) {\n  std::push_heap(container_algorithm_internal::c_begin(sequence),\n                 container_algorithm_internal::c_end(sequence),\n                 std::forward<LessThan>(comp));\n}\n\n// c_pop_heap()\n//\n// Container-based version of the <algorithm> `std::pop_heap()` function\n// to pop a value from a heap container.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_pop_heap(\n    RandomAccessContainer& sequence) {\n  std::pop_heap(container_algorithm_internal::c_begin(sequence),\n                container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_pop_heap() for performing a pop operation on a heap using a\n// `comp` other than `operator<`.\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_pop_heap(\n    RandomAccessContainer& sequence, LessThan&& comp) {\n  std::pop_heap(container_algorithm_internal::c_begin(sequence),\n                container_algorithm_internal::c_end(sequence),\n                std::forward<LessThan>(comp));\n}\n\n// c_make_heap()\n//\n// Container-based version of the <algorithm> `std::make_heap()` function\n// to make a container a heap.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_make_heap(\n    RandomAccessContainer& sequence) {\n  std::make_heap(container_algorithm_internal::c_begin(sequence),\n                 container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_make_heap() for performing heap comparisons using a\n// `comp` other than `operator<`\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_make_heap(\n    RandomAccessContainer& sequence, LessThan&& comp) {\n  std::make_heap(container_algorithm_internal::c_begin(sequence),\n                 container_algorithm_internal::c_end(sequence),\n                 std::forward<LessThan>(comp));\n}\n\n// c_sort_heap()\n//\n// Container-based version of the <algorithm> `std::sort_heap()` function\n// to sort a heap into ascending order (after which it is no longer a heap).\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort_heap(\n    RandomAccessContainer& sequence) {\n  std::sort_heap(container_algorithm_internal::c_begin(sequence),\n                 container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_sort_heap() for performing heap comparisons using a\n// `comp` other than `operator<`\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort_heap(\n    RandomAccessContainer& sequence, LessThan&& comp) {\n  std::sort_heap(container_algorithm_internal::c_begin(sequence),\n                 container_algorithm_internal::c_end(sequence),\n                 std::forward<LessThan>(comp));\n}\n\n// c_is_heap()\n//\n// Container-based version of the <algorithm> `std::is_heap()` function\n// to check whether the given container is a heap.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_heap(\n    const RandomAccessContainer& sequence) {\n  return std::is_heap(container_algorithm_internal::c_begin(sequence),\n                      container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_is_heap() for performing heap comparisons using a\n// `comp` other than `operator<`\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_heap(\n    const RandomAccessContainer& sequence, LessThan&& comp) {\n  return std::is_heap(container_algorithm_internal::c_begin(sequence),\n                      container_algorithm_internal::c_end(sequence),\n                      std::forward<LessThan>(comp));\n}\n\n// c_is_heap_until()\n//\n// Container-based version of the <algorithm> `std::is_heap_until()` function\n// to find the first element in a given container which is not in heap order.\ntemplate <typename RandomAccessContainer>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<RandomAccessContainer>\n    c_is_heap_until(RandomAccessContainer& sequence) {\n  return std::is_heap_until(container_algorithm_internal::c_begin(sequence),\n                            container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_is_heap_until() for performing heap comparisons using a\n// `comp` other than `operator<`\ntemplate <typename RandomAccessContainer, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n    container_algorithm_internal::ContainerIter<RandomAccessContainer>\n    c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {\n  return std::is_heap_until(container_algorithm_internal::c_begin(sequence),\n                            container_algorithm_internal::c_end(sequence),\n                            std::forward<LessThan>(comp));\n}\n\n//------------------------------------------------------------------------------\n//  <algorithm> Min/max\n//------------------------------------------------------------------------------\n\n// c_min_element()\n//\n// Container-based version of the <algorithm> `std::min_element()` function\n// to return an iterator pointing to the element with the smallest value, using\n// `operator<` to make the comparisons.\ntemplate <typename Sequence>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_min_element(Sequence& sequence) {\n  return std::min_element(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_min_element() for performing a `comp` comparison other than\n// `operator<`.\ntemplate <typename Sequence, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_min_element(Sequence& sequence, LessThan&& comp) {\n  return std::min_element(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence),\n                          std::forward<LessThan>(comp));\n}\n\n// c_max_element()\n//\n// Container-based version of the <algorithm> `std::max_element()` function\n// to return an iterator pointing to the element with the largest value, using\n// `operator<` to make the comparisons.\ntemplate <typename Sequence>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_max_element(Sequence& sequence) {\n  return std::max_element(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence));\n}\n\n// Overload of c_max_element() for performing a `comp` comparison other than\n// `operator<`.\ntemplate <typename Sequence, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerIter<Sequence>\n    c_max_element(Sequence& sequence, LessThan&& comp) {\n  return std::max_element(container_algorithm_internal::c_begin(sequence),\n                          container_algorithm_internal::c_end(sequence),\n                          std::forward<LessThan>(comp));\n}\n\n// c_minmax_element()\n//\n// Container-based version of the <algorithm> `std::minmax_element()` function\n// to return a pair of iterators pointing to the elements containing the\n// smallest and largest values, respectively, using `operator<` to make the\n// comparisons.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerIterPairType<C, C>\n    c_minmax_element(C& c) {\n  return std::minmax_element(container_algorithm_internal::c_begin(c),\n                             container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_minmax_element() for performing `comp` comparisons other than\n// `operator<`.\ntemplate <typename C, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n    container_algorithm_internal::ContainerIterPairType<C, C>\n    c_minmax_element(C& c, LessThan&& comp) {\n  return std::minmax_element(container_algorithm_internal::c_begin(c),\n                             container_algorithm_internal::c_end(c),\n                             std::forward<LessThan>(comp));\n}\n\n//------------------------------------------------------------------------------\n//  <algorithm> Lexicographical Comparisons\n//------------------------------------------------------------------------------\n\n// c_lexicographical_compare()\n//\n// Container-based version of the <algorithm> `std::lexicographical_compare()`\n// function to lexicographically compare (e.g. sort words alphabetically) two\n// container sequences. The comparison is performed using `operator<`. Note\n// that capital letters (\"A-Z\") have ASCII values less than lowercase letters\n// (\"a-z\").\ntemplate <typename Sequence1, typename Sequence2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_lexicographical_compare(\n    const Sequence1& sequence1, const Sequence2& sequence2) {\n  return std::lexicographical_compare(\n      container_algorithm_internal::c_begin(sequence1),\n      container_algorithm_internal::c_end(sequence1),\n      container_algorithm_internal::c_begin(sequence2),\n      container_algorithm_internal::c_end(sequence2));\n}\n\n// Overload of c_lexicographical_compare() for performing a lexicographical\n// comparison using a `comp` operator instead of `operator<`.\ntemplate <typename Sequence1, typename Sequence2, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_lexicographical_compare(\n    const Sequence1& sequence1, const Sequence2& sequence2, LessThan&& comp) {\n  return std::lexicographical_compare(\n      container_algorithm_internal::c_begin(sequence1),\n      container_algorithm_internal::c_end(sequence1),\n      container_algorithm_internal::c_begin(sequence2),\n      container_algorithm_internal::c_end(sequence2),\n      std::forward<LessThan>(comp));\n}\n\n// c_next_permutation()\n//\n// Container-based version of the <algorithm> `std::next_permutation()` function\n// to rearrange a container's elements into the next lexicographically greater\n// permutation.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_next_permutation(C& c) {\n  return std::next_permutation(container_algorithm_internal::c_begin(c),\n                               container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_next_permutation() for performing a lexicographical\n// comparison using a `comp` operator instead of `operator<`.\ntemplate <typename C, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_next_permutation(C& c,\n                                                            LessThan&& comp) {\n  return std::next_permutation(container_algorithm_internal::c_begin(c),\n                               container_algorithm_internal::c_end(c),\n                               std::forward<LessThan>(comp));\n}\n\n// c_prev_permutation()\n//\n// Container-based version of the <algorithm> `std::prev_permutation()` function\n// to rearrange a container's elements into the next lexicographically lesser\n// permutation.\ntemplate <typename C>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_prev_permutation(C& c) {\n  return std::prev_permutation(container_algorithm_internal::c_begin(c),\n                               container_algorithm_internal::c_end(c));\n}\n\n// Overload of c_prev_permutation() for performing a lexicographical\n// comparison using a `comp` operator instead of `operator<`.\ntemplate <typename C, typename LessThan>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_prev_permutation(C& c,\n                                                            LessThan&& comp) {\n  return std::prev_permutation(container_algorithm_internal::c_begin(c),\n                               container_algorithm_internal::c_end(c),\n                               std::forward<LessThan>(comp));\n}\n\n//------------------------------------------------------------------------------\n// <numeric> algorithms\n//------------------------------------------------------------------------------\n\n// c_iota()\n//\n// Container-based version of the <numeric> `std::iota()` function\n// to compute successive values of `value`, as if incremented with `++value`\n// after each element is written, and write them to the container.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_iota(Sequence& sequence,\n                                                const T& value) {\n  std::iota(container_algorithm_internal::c_begin(sequence),\n            container_algorithm_internal::c_end(sequence), value);\n}\n\n// c_accumulate()\n//\n// Container-based version of the <numeric> `std::accumulate()` function\n// to accumulate the element values of a container to `init` and return that\n// accumulation by value.\n//\n// Note: Due to a language technicality this function has return type\n// absl::decay_t<T>. As a user of this function you can casually read\n// this as \"returns T by value\" and assume it does the right thing.\ntemplate <typename Sequence, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_accumulate(\n    const Sequence& sequence, T&& init) {\n  return std::accumulate(container_algorithm_internal::c_begin(sequence),\n                         container_algorithm_internal::c_end(sequence),\n                         std::forward<T>(init));\n}\n\n// Overload of c_accumulate() for using a binary operations other than\n// addition for computing the accumulation.\ntemplate <typename Sequence, typename T, typename BinaryOp>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_accumulate(\n    const Sequence& sequence, T&& init, BinaryOp&& binary_op) {\n  return std::accumulate(container_algorithm_internal::c_begin(sequence),\n                         container_algorithm_internal::c_end(sequence),\n                         std::forward<T>(init),\n                         std::forward<BinaryOp>(binary_op));\n}\n\n// c_inner_product()\n//\n// Container-based version of the <numeric> `std::inner_product()` function\n// to compute the cumulative inner product of container element pairs.\n//\n// Note: Due to a language technicality this function has return type\n// absl::decay_t<T>. As a user of this function you can casually read\n// this as \"returns T by value\" and assume it does the right thing.\ntemplate <typename Sequence1, typename Sequence2, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_inner_product(\n    const Sequence1& factors1, const Sequence2& factors2, T&& sum) {\n  return std::inner_product(container_algorithm_internal::c_begin(factors1),\n                            container_algorithm_internal::c_end(factors1),\n                            container_algorithm_internal::c_begin(factors2),\n                            std::forward<T>(sum));\n}\n\n// Overload of c_inner_product() for using binary operations other than\n// `operator+` (for computing the accumulation) and `operator*` (for computing\n// the product between the two container's element pair).\ntemplate <typename Sequence1, typename Sequence2, typename T,\n          typename BinaryOp1, typename BinaryOp2>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_inner_product(\n    const Sequence1& factors1, const Sequence2& factors2, T&& sum,\n    BinaryOp1&& op1, BinaryOp2&& op2) {\n  return std::inner_product(container_algorithm_internal::c_begin(factors1),\n                            container_algorithm_internal::c_end(factors1),\n                            container_algorithm_internal::c_begin(factors2),\n                            std::forward<T>(sum), std::forward<BinaryOp1>(op1),\n                            std::forward<BinaryOp2>(op2));\n}\n\n// c_adjacent_difference()\n//\n// Container-based version of the <numeric> `std::adjacent_difference()`\n// function to compute the difference between each element and the one preceding\n// it and write it to an iterator.\ntemplate <typename InputSequence, typename OutputIt>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt\nc_adjacent_difference(const InputSequence& input, OutputIt output_first) {\n  return std::adjacent_difference(container_algorithm_internal::c_begin(input),\n                                  container_algorithm_internal::c_end(input),\n                                  output_first);\n}\n\n// Overload of c_adjacent_difference() for using a binary operation other than\n// subtraction to compute the adjacent difference.\ntemplate <typename InputSequence, typename OutputIt, typename BinaryOp>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt c_adjacent_difference(\n    const InputSequence& input, OutputIt output_first, BinaryOp&& op) {\n  return std::adjacent_difference(container_algorithm_internal::c_begin(input),\n                                  container_algorithm_internal::c_end(input),\n                                  output_first, std::forward<BinaryOp>(op));\n}\n\n// c_partial_sum()\n//\n// Container-based version of the <numeric> `std::partial_sum()` function\n// to compute the partial sum of the elements in a sequence and write them\n// to an iterator. The partial sum is the sum of all element values so far in\n// the sequence.\ntemplate <typename InputSequence, typename OutputIt>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt\nc_partial_sum(const InputSequence& input, OutputIt output_first) {\n  return std::partial_sum(container_algorithm_internal::c_begin(input),\n                          container_algorithm_internal::c_end(input),\n                          output_first);\n}\n\n// Overload of c_partial_sum() for using a binary operation other than addition\n// to compute the \"partial sum\".\ntemplate <typename InputSequence, typename OutputIt, typename BinaryOp>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt c_partial_sum(\n    const InputSequence& input, OutputIt output_first, BinaryOp&& op) {\n  return std::partial_sum(container_algorithm_internal::c_begin(input),\n                          container_algorithm_internal::c_end(input),\n                          output_first, std::forward<BinaryOp>(op));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_ALGORITHM_CONTAINER_H_\n"
  },
  {
    "path": "absl/algorithm/container_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/algorithm/container.h\"\n\n#include <algorithm>\n#include <array>\n#include <cstddef>\n#include <functional>\n#include <initializer_list>\n#include <iterator>\n#include <list>\n#include <memory>\n#include <ostream>\n#include <random>\n#include <set>\n#include <unordered_set>\n#include <utility>\n#include <valarray>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/random.h\"\n#include \"absl/types/span.h\"\n\nnamespace {\n\nusing ::testing::Each;\nusing ::testing::ElementsAre;\nusing ::testing::Gt;\nusing ::testing::IsNull;\nusing ::testing::IsSubsetOf;\nusing ::testing::Lt;\nusing ::testing::Pointee;\nusing ::testing::SizeIs;\nusing ::testing::Truly;\nusing ::testing::UnorderedElementsAre;\n\n// Most of these tests just check that the code compiles, not that it\n// does the right thing. That's fine since the functions just forward\n// to the STL implementation.\nclass NonMutatingTest : public testing::Test {\n protected:\n  std::unordered_set<int> container_ = {1, 2, 3};\n  std::list<int> sequence_ = {1, 2, 3};\n  std::vector<int> vector_ = {1, 2, 3};\n  int array_[3] = {1, 2, 3};\n};\n\nstruct AccumulateCalls {\n  void operator()(int value) { calls.push_back(value); }\n  std::vector<int> calls;\n};\n\nbool Predicate(int value) { return value < 3; }\nbool BinPredicate(int v1, int v2) { return v1 < v2; }\nbool Equals(int v1, int v2) { return v1 == v2; }\nbool IsOdd(int x) { return x % 2 != 0; }\n\nTEST_F(NonMutatingTest, Distance) {\n  EXPECT_EQ(container_.size(),\n            static_cast<size_t>(absl::c_distance(container_)));\n  EXPECT_EQ(sequence_.size(), static_cast<size_t>(absl::c_distance(sequence_)));\n  EXPECT_EQ(vector_.size(), static_cast<size_t>(absl::c_distance(vector_)));\n  EXPECT_EQ(ABSL_ARRAYSIZE(array_),\n            static_cast<size_t>(absl::c_distance(array_)));\n\n  // Works with a temporary argument.\n  EXPECT_EQ(vector_.size(),\n            static_cast<size_t>(absl::c_distance(std::vector<int>(vector_))));\n}\n\nTEST_F(NonMutatingTest, Distance_OverloadedBeginEnd) {\n  // Works with classes which have custom ADL-selected overloads of std::begin\n  // and std::end.\n  std::initializer_list<int> a = {1, 2, 3};\n  std::valarray<int> b = {1, 2, 3};\n  EXPECT_EQ(3, absl::c_distance(a));\n  EXPECT_EQ(3, absl::c_distance(b));\n\n  // It is assumed that other c_* functions use the same mechanism for\n  // ADL-selecting begin/end overloads.\n}\n\nTEST_F(NonMutatingTest, ForEach) {\n  AccumulateCalls c = absl::c_for_each(container_, AccumulateCalls());\n  // Don't rely on the unordered_set's order.\n  std::sort(c.calls.begin(), c.calls.end());\n  EXPECT_EQ(vector_, c.calls);\n\n  // Works with temporary container, too.\n  AccumulateCalls c2 =\n      absl::c_for_each(std::unordered_set<int>(container_), AccumulateCalls());\n  std::sort(c2.calls.begin(), c2.calls.end());\n  EXPECT_EQ(vector_, c2.calls);\n}\n\nTEST_F(NonMutatingTest, FindReturnsCorrectType) {\n  auto it = absl::c_find(container_, 3);\n  EXPECT_EQ(3, *it);\n  absl::c_find(absl::implicit_cast<const std::list<int>&>(sequence_), 3);\n}\n\nTEST_F(NonMutatingTest, Contains) {\n  EXPECT_TRUE(absl::c_contains(container_, 3));\n  EXPECT_FALSE(absl::c_contains(container_, 4));\n}\n\nTEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); }\n\nTEST_F(NonMutatingTest, FindIfNot) {\n  absl::c_find_if_not(container_, Predicate);\n}\n\nTEST_F(NonMutatingTest, FindEnd) {\n  absl::c_find_end(sequence_, vector_);\n  absl::c_find_end(vector_, sequence_);\n}\n\nTEST_F(NonMutatingTest, FindEndWithPredicate) {\n  absl::c_find_end(sequence_, vector_, BinPredicate);\n  absl::c_find_end(vector_, sequence_, BinPredicate);\n}\n\nTEST_F(NonMutatingTest, FindFirstOf) {\n  absl::c_find_first_of(container_, sequence_);\n  absl::c_find_first_of(sequence_, container_);\n  absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2});\n}\n\nTEST_F(NonMutatingTest, FindFirstOfWithPredicate) {\n  absl::c_find_first_of(container_, sequence_, BinPredicate);\n  absl::c_find_first_of(sequence_, container_, BinPredicate);\n  absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2}, BinPredicate);\n}\n\nTEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); }\n\nTEST_F(NonMutatingTest, AdjacentFindWithPredicate) {\n  absl::c_adjacent_find(sequence_, BinPredicate);\n}\n\nTEST_F(NonMutatingTest, Count) { EXPECT_EQ(1, absl::c_count(container_, 3)); }\n\nTEST_F(NonMutatingTest, CountIf) {\n  EXPECT_EQ(2, absl::c_count_if(container_, Predicate));\n  const std::unordered_set<int>& const_container = container_;\n  EXPECT_EQ(2, absl::c_count_if(const_container, Predicate));\n}\n\nTEST_F(NonMutatingTest, Mismatch) {\n  // Testing necessary as absl::c_mismatch executes logic.\n  {\n    auto result = absl::c_mismatch(vector_, sequence_);\n    EXPECT_EQ(result.first, vector_.end());\n    EXPECT_EQ(result.second, sequence_.end());\n  }\n  {\n    auto result = absl::c_mismatch(sequence_, vector_);\n    EXPECT_EQ(result.first, sequence_.end());\n    EXPECT_EQ(result.second, vector_.end());\n  }\n\n  sequence_.back() = 5;\n  {\n    auto result = absl::c_mismatch(vector_, sequence_);\n    EXPECT_EQ(result.first, std::prev(vector_.end()));\n    EXPECT_EQ(result.second, std::prev(sequence_.end()));\n  }\n  {\n    auto result = absl::c_mismatch(sequence_, vector_);\n    EXPECT_EQ(result.first, std::prev(sequence_.end()));\n    EXPECT_EQ(result.second, std::prev(vector_.end()));\n  }\n\n  sequence_.pop_back();\n  {\n    auto result = absl::c_mismatch(vector_, sequence_);\n    EXPECT_EQ(result.first, std::prev(vector_.end()));\n    EXPECT_EQ(result.second, sequence_.end());\n  }\n  {\n    auto result = absl::c_mismatch(sequence_, vector_);\n    EXPECT_EQ(result.first, sequence_.end());\n    EXPECT_EQ(result.second, std::prev(vector_.end()));\n  }\n  {\n    struct NoNotEquals {\n      constexpr bool operator==(NoNotEquals) const { return true; }\n      constexpr bool operator!=(NoNotEquals) const = delete;\n    };\n    std::vector<NoNotEquals> first;\n    std::list<NoNotEquals> second;\n\n    // Check this still compiles.\n    absl::c_mismatch(first, second);\n  }\n}\n\nTEST_F(NonMutatingTest, MismatchWithPredicate) {\n  // Testing necessary as absl::c_mismatch executes logic.\n  {\n    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);\n    EXPECT_EQ(result.first, vector_.begin());\n    EXPECT_EQ(result.second, sequence_.begin());\n  }\n  {\n    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);\n    EXPECT_EQ(result.first, sequence_.begin());\n    EXPECT_EQ(result.second, vector_.begin());\n  }\n\n  sequence_.front() = 0;\n  {\n    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);\n    EXPECT_EQ(result.first, vector_.begin());\n    EXPECT_EQ(result.second, sequence_.begin());\n  }\n  {\n    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);\n    EXPECT_EQ(result.first, std::next(sequence_.begin()));\n    EXPECT_EQ(result.second, std::next(vector_.begin()));\n  }\n\n  sequence_.clear();\n  {\n    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);\n    EXPECT_EQ(result.first, vector_.begin());\n    EXPECT_EQ(result.second, sequence_.end());\n  }\n  {\n    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);\n    EXPECT_EQ(result.first, sequence_.end());\n    EXPECT_EQ(result.second, vector_.begin());\n  }\n}\n\nTEST_F(NonMutatingTest, Equal) {\n  EXPECT_TRUE(absl::c_equal(vector_, sequence_));\n  EXPECT_TRUE(absl::c_equal(sequence_, vector_));\n  EXPECT_TRUE(absl::c_equal(sequence_, array_));\n  EXPECT_TRUE(absl::c_equal(array_, vector_));\n\n  // Test that behavior appropriately differs from that of equal().\n  std::vector<int> vector_plus = {1, 2, 3};\n  vector_plus.push_back(4);\n  EXPECT_FALSE(absl::c_equal(vector_plus, sequence_));\n  EXPECT_FALSE(absl::c_equal(sequence_, vector_plus));\n  EXPECT_FALSE(absl::c_equal(array_, vector_plus));\n}\n\nTEST_F(NonMutatingTest, EqualWithPredicate) {\n  EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals));\n  EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals));\n  EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals));\n  EXPECT_TRUE(absl::c_equal(vector_, array_, Equals));\n\n  // Test that behavior appropriately differs from that of equal().\n  std::vector<int> vector_plus = {1, 2, 3};\n  vector_plus.push_back(4);\n  EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals));\n  EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals));\n  EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals));\n}\n\nTEST_F(NonMutatingTest, IsPermutation) {\n  auto vector_permut_ = vector_;\n  std::next_permutation(vector_permut_.begin(), vector_permut_.end());\n  EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_));\n  EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_));\n\n  // Test that behavior appropriately differs from that of is_permutation().\n  std::vector<int> vector_plus = {1, 2, 3};\n  vector_plus.push_back(4);\n  EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_));\n  EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus));\n}\n\nTEST_F(NonMutatingTest, IsPermutationWithPredicate) {\n  auto vector_permut_ = vector_;\n  std::next_permutation(vector_permut_.begin(), vector_permut_.end());\n  EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_, Equals));\n  EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_, Equals));\n\n  // Test that behavior appropriately differs from that of is_permutation().\n  std::vector<int> vector_plus = {1, 2, 3};\n  vector_plus.push_back(4);\n  EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_, Equals));\n  EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus, Equals));\n}\n\nTEST_F(NonMutatingTest, Search) {\n  absl::c_search(sequence_, vector_);\n  absl::c_search(vector_, sequence_);\n  absl::c_search(array_, sequence_);\n}\n\nTEST_F(NonMutatingTest, SearchWithPredicate) {\n  absl::c_search(sequence_, vector_, BinPredicate);\n  absl::c_search(vector_, sequence_, BinPredicate);\n}\n\nTEST_F(NonMutatingTest, ContainsSubrange) {\n  EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_));\n  EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_));\n  EXPECT_TRUE(absl::c_contains_subrange(array_, sequence_));\n}\n\nTEST_F(NonMutatingTest, ContainsSubrangeWithPredicate) {\n  EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_, Equals));\n  EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_, Equals));\n}\n\nTEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); }\n\nTEST_F(NonMutatingTest, SearchNWithPredicate) {\n  absl::c_search_n(sequence_, 3, 1, BinPredicate);\n}\n\nTEST_F(NonMutatingTest, LowerBound) {\n  std::list<int>::iterator i = absl::c_lower_bound(sequence_, 3);\n  ASSERT_TRUE(i != sequence_.end());\n  EXPECT_EQ(2, std::distance(sequence_.begin(), i));\n  EXPECT_EQ(3, *i);\n}\n\nTEST_F(NonMutatingTest, LowerBoundWithPredicate) {\n  std::vector<int> v(vector_);\n  std::sort(v.begin(), v.end(), std::greater<int>());\n  std::vector<int>::iterator i = absl::c_lower_bound(v, 3, std::greater<int>());\n  EXPECT_TRUE(i == v.begin());\n  EXPECT_EQ(3, *i);\n}\n\nTEST_F(NonMutatingTest, UpperBound) {\n  std::list<int>::iterator i = absl::c_upper_bound(sequence_, 1);\n  ASSERT_TRUE(i != sequence_.end());\n  EXPECT_EQ(1, std::distance(sequence_.begin(), i));\n  EXPECT_EQ(2, *i);\n}\n\nTEST_F(NonMutatingTest, UpperBoundWithPredicate) {\n  std::vector<int> v(vector_);\n  std::sort(v.begin(), v.end(), std::greater<int>());\n  std::vector<int>::iterator i = absl::c_upper_bound(v, 1, std::greater<int>());\n  EXPECT_EQ(3, i - v.begin());\n  EXPECT_TRUE(i == v.end());\n}\n\nTEST_F(NonMutatingTest, EqualRange) {\n  std::pair<std::list<int>::iterator, std::list<int>::iterator> p =\n      absl::c_equal_range(sequence_, 2);\n  EXPECT_EQ(1, std::distance(sequence_.begin(), p.first));\n  EXPECT_EQ(2, std::distance(sequence_.begin(), p.second));\n}\n\nTEST_F(NonMutatingTest, EqualRangeArray) {\n  auto p = absl::c_equal_range(array_, 2);\n  EXPECT_EQ(1, std::distance(std::begin(array_), p.first));\n  EXPECT_EQ(2, std::distance(std::begin(array_), p.second));\n}\n\nTEST_F(NonMutatingTest, EqualRangeWithPredicate) {\n  std::vector<int> v(vector_);\n  std::sort(v.begin(), v.end(), std::greater<int>());\n  std::pair<std::vector<int>::iterator, std::vector<int>::iterator> p =\n      absl::c_equal_range(v, 2, std::greater<int>());\n  EXPECT_EQ(1, std::distance(v.begin(), p.first));\n  EXPECT_EQ(2, std::distance(v.begin(), p.second));\n}\n\nTEST_F(NonMutatingTest, BinarySearch) {\n  EXPECT_TRUE(absl::c_binary_search(vector_, 2));\n  EXPECT_TRUE(absl::c_binary_search(std::vector<int>(vector_), 2));\n}\n\nTEST_F(NonMutatingTest, BinarySearchWithPredicate) {\n  std::vector<int> v(vector_);\n  std::sort(v.begin(), v.end(), std::greater<int>());\n  EXPECT_TRUE(absl::c_binary_search(v, 2, std::greater<int>()));\n  EXPECT_TRUE(\n      absl::c_binary_search(std::vector<int>(v), 2, std::greater<int>()));\n}\n\nTEST_F(NonMutatingTest, MinElement) {\n  std::list<int>::iterator i = absl::c_min_element(sequence_);\n  ASSERT_TRUE(i != sequence_.end());\n  EXPECT_EQ(*i, 1);\n}\n\nTEST_F(NonMutatingTest, MinElementWithPredicate) {\n  std::list<int>::iterator i =\n      absl::c_min_element(sequence_, std::greater<int>());\n  ASSERT_TRUE(i != sequence_.end());\n  EXPECT_EQ(*i, 3);\n}\n\nTEST_F(NonMutatingTest, MaxElement) {\n  std::list<int>::iterator i = absl::c_max_element(sequence_);\n  ASSERT_TRUE(i != sequence_.end());\n  EXPECT_EQ(*i, 3);\n}\n\nTEST_F(NonMutatingTest, MaxElementWithPredicate) {\n  std::list<int>::iterator i =\n      absl::c_max_element(sequence_, std::greater<int>());\n  ASSERT_TRUE(i != sequence_.end());\n  EXPECT_EQ(*i, 1);\n}\n\nTEST_F(NonMutatingTest, LexicographicalCompare) {\n  EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_));\n\n  std::vector<int> v;\n  v.push_back(1);\n  v.push_back(2);\n  v.push_back(4);\n\n  EXPECT_TRUE(absl::c_lexicographical_compare(sequence_, v));\n  EXPECT_TRUE(absl::c_lexicographical_compare(std::list<int>(sequence_), v));\n}\n\nTEST_F(NonMutatingTest, LexicographicalCopmareWithPredicate) {\n  EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_,\n                                               std::greater<int>()));\n\n  std::vector<int> v;\n  v.push_back(1);\n  v.push_back(2);\n  v.push_back(4);\n\n  EXPECT_TRUE(\n      absl::c_lexicographical_compare(v, sequence_, std::greater<int>()));\n  EXPECT_TRUE(absl::c_lexicographical_compare(\n      std::vector<int>(v), std::list<int>(sequence_), std::greater<int>()));\n}\n\nTEST_F(NonMutatingTest, Includes) {\n  std::set<int> s(vector_.begin(), vector_.end());\n  s.insert(4);\n  EXPECT_TRUE(absl::c_includes(s, vector_));\n}\n\nTEST_F(NonMutatingTest, IncludesWithPredicate) {\n  std::vector<int> v = {3, 2, 1};\n  std::set<int, std::greater<int>> s(v.begin(), v.end());\n  s.insert(4);\n  EXPECT_TRUE(absl::c_includes(s, v, std::greater<int>()));\n}\n\nclass NumericMutatingTest : public testing::Test {\n protected:\n  std::list<int> list_ = {1, 2, 3};\n  std::vector<int> output_;\n};\n\nTEST_F(NumericMutatingTest, Iota) {\n  absl::c_iota(list_, 5);\n  std::list<int> expected{5, 6, 7};\n  EXPECT_EQ(list_, expected);\n}\n\nTEST_F(NonMutatingTest, Accumulate) {\n  EXPECT_EQ(absl::c_accumulate(sequence_, 4), 1 + 2 + 3 + 4);\n}\n\nTEST_F(NonMutatingTest, AccumulateWithBinaryOp) {\n  EXPECT_EQ(absl::c_accumulate(sequence_, 4, std::multiplies<int>()),\n            1 * 2 * 3 * 4);\n}\n\nTEST_F(NonMutatingTest, AccumulateLvalueInit) {\n  int lvalue = 4;\n  EXPECT_EQ(absl::c_accumulate(sequence_, lvalue), 1 + 2 + 3 + 4);\n}\n\nTEST_F(NonMutatingTest, AccumulateWithBinaryOpLvalueInit) {\n  int lvalue = 4;\n  EXPECT_EQ(absl::c_accumulate(sequence_, lvalue, std::multiplies<int>()),\n            1 * 2 * 3 * 4);\n}\n\nTEST_F(NonMutatingTest, InnerProduct) {\n  EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 1000),\n            1000 + 1 * 1 + 2 * 2 + 3 * 3);\n}\n\nTEST_F(NonMutatingTest, InnerProductWithBinaryOps) {\n  EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 10,\n                                  std::multiplies<int>(), std::plus<int>()),\n            10 * (1 + 1) * (2 + 2) * (3 + 3));\n}\n\nTEST_F(NonMutatingTest, InnerProductLvalueInit) {\n  int lvalue = 1000;\n  EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue),\n            1000 + 1 * 1 + 2 * 2 + 3 * 3);\n}\n\nTEST_F(NonMutatingTest, InnerProductWithBinaryOpsLvalueInit) {\n  int lvalue = 10;\n  EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue,\n                                  std::multiplies<int>(), std::plus<int>()),\n            10 * (1 + 1) * (2 + 2) * (3 + 3));\n}\n\nTEST_F(NumericMutatingTest, AdjacentDifference) {\n  auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_));\n  *last = 1000;\n  std::vector<int> expected{1, 2 - 1, 3 - 2, 1000};\n  EXPECT_EQ(output_, expected);\n}\n\nTEST_F(NumericMutatingTest, AdjacentDifferenceWithBinaryOp) {\n  auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_),\n                                          std::multiplies<int>());\n  *last = 1000;\n  std::vector<int> expected{1, 2 * 1, 3 * 2, 1000};\n  EXPECT_EQ(output_, expected);\n}\n\nTEST_F(NumericMutatingTest, PartialSum) {\n  auto last = absl::c_partial_sum(list_, std::back_inserter(output_));\n  *last = 1000;\n  std::vector<int> expected{1, 1 + 2, 1 + 2 + 3, 1000};\n  EXPECT_EQ(output_, expected);\n}\n\nTEST_F(NumericMutatingTest, PartialSumWithBinaryOp) {\n  auto last = absl::c_partial_sum(list_, std::back_inserter(output_),\n                                  std::multiplies<int>());\n  *last = 1000;\n  std::vector<int> expected{1, 1 * 2, 1 * 2 * 3, 1000};\n  EXPECT_EQ(output_, expected);\n}\n\nTEST_F(NonMutatingTest, LinearSearch) {\n  EXPECT_TRUE(absl::c_linear_search(container_, 3));\n  EXPECT_FALSE(absl::c_linear_search(container_, 4));\n}\n\nTEST_F(NonMutatingTest, AllOf) {\n  const std::vector<int>& v = vector_;\n  EXPECT_FALSE(absl::c_all_of(v, [](int x) { return x > 1; }));\n  EXPECT_TRUE(absl::c_all_of(v, [](int x) { return x > 0; }));\n}\n\nTEST_F(NonMutatingTest, AnyOf) {\n  const std::vector<int>& v = vector_;\n  EXPECT_TRUE(absl::c_any_of(v, [](int x) { return x > 2; }));\n  EXPECT_FALSE(absl::c_any_of(v, [](int x) { return x > 5; }));\n}\n\nTEST_F(NonMutatingTest, NoneOf) {\n  const std::vector<int>& v = vector_;\n  EXPECT_FALSE(absl::c_none_of(v, [](int x) { return x > 2; }));\n  EXPECT_TRUE(absl::c_none_of(v, [](int x) { return x > 5; }));\n}\n\nTEST_F(NonMutatingTest, MinMaxElementLess) {\n  std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator>\n      p = absl::c_minmax_element(vector_, std::less<int>());\n  EXPECT_TRUE(p.first == vector_.begin());\n  EXPECT_TRUE(p.second == vector_.begin() + 2);\n}\n\nTEST_F(NonMutatingTest, MinMaxElementGreater) {\n  std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator>\n      p = absl::c_minmax_element(vector_, std::greater<int>());\n  EXPECT_TRUE(p.first == vector_.begin() + 2);\n  EXPECT_TRUE(p.second == vector_.begin());\n}\n\nTEST_F(NonMutatingTest, MinMaxElementNoPredicate) {\n  std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator>\n      p = absl::c_minmax_element(vector_);\n  EXPECT_TRUE(p.first == vector_.begin());\n  EXPECT_TRUE(p.second == vector_.begin() + 2);\n}\n\nclass SortingTest : public testing::Test {\n protected:\n  std::list<int> sorted_ = {1, 2, 3, 4};\n  std::list<int> unsorted_ = {2, 4, 1, 3};\n  std::list<int> reversed_ = {4, 3, 2, 1};\n};\n\nTEST_F(SortingTest, IsSorted) {\n  EXPECT_TRUE(absl::c_is_sorted(sorted_));\n  EXPECT_FALSE(absl::c_is_sorted(unsorted_));\n  EXPECT_FALSE(absl::c_is_sorted(reversed_));\n}\n\nTEST_F(SortingTest, IsSortedWithPredicate) {\n  EXPECT_FALSE(absl::c_is_sorted(sorted_, std::greater<int>()));\n  EXPECT_FALSE(absl::c_is_sorted(unsorted_, std::greater<int>()));\n  EXPECT_TRUE(absl::c_is_sorted(reversed_, std::greater<int>()));\n}\n\nTEST_F(SortingTest, IsSortedUntil) {\n  EXPECT_EQ(1, *absl::c_is_sorted_until(unsorted_));\n  EXPECT_EQ(4, *absl::c_is_sorted_until(unsorted_, std::greater<int>()));\n}\n\nTEST_F(SortingTest, NthElement) {\n  std::vector<int> unsorted = {2, 4, 1, 3};\n  absl::c_nth_element(unsorted, unsorted.begin() + 2);\n  EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3)));\n  absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>());\n  EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2)));\n}\n\nTEST(MutatingTest, IsPartitioned) {\n  EXPECT_TRUE(\n      absl::c_is_partitioned(std::vector<int>{1, 3, 5, 2, 4, 6}, IsOdd));\n  EXPECT_FALSE(\n      absl::c_is_partitioned(std::vector<int>{1, 2, 3, 4, 5, 6}, IsOdd));\n  EXPECT_FALSE(\n      absl::c_is_partitioned(std::vector<int>{2, 4, 6, 1, 3, 5}, IsOdd));\n}\n\nTEST(MutatingTest, Partition) {\n  std::vector<int> actual = {1, 2, 3, 4, 5};\n  absl::c_partition(actual, IsOdd);\n  EXPECT_THAT(actual, Truly([](const std::vector<int>& c) {\n                return absl::c_is_partitioned(c, IsOdd);\n              }));\n}\n\nTEST(MutatingTest, StablePartition) {\n  std::vector<int> actual = {1, 2, 3, 4, 5};\n  absl::c_stable_partition(actual, IsOdd);\n  EXPECT_THAT(actual, ElementsAre(1, 3, 5, 2, 4));\n}\n\nTEST(MutatingTest, PartitionCopy) {\n  const std::vector<int> initial = {1, 2, 3, 4, 5};\n  std::vector<int> odds, evens;\n  auto ends = absl::c_partition_copy(initial, back_inserter(odds),\n                                     back_inserter(evens), IsOdd);\n  *ends.first = 7;\n  *ends.second = 6;\n  EXPECT_THAT(odds, ElementsAre(1, 3, 5, 7));\n  EXPECT_THAT(evens, ElementsAre(2, 4, 6));\n}\n\nTEST(MutatingTest, PartitionPoint) {\n  const std::vector<int> initial = {1, 3, 5, 2, 4};\n  auto middle = absl::c_partition_point(initial, IsOdd);\n  EXPECT_EQ(2, *middle);\n}\n\nTEST(MutatingTest, CopyMiddle) {\n  const std::vector<int> initial = {4, -1, -2, -3, 5};\n  const std::list<int> input = {1, 2, 3};\n  const std::vector<int> expected = {4, 1, 2, 3, 5};\n\n  std::list<int> test_list(initial.begin(), initial.end());\n  absl::c_copy(input, ++test_list.begin());\n  EXPECT_EQ(std::list<int>(expected.begin(), expected.end()), test_list);\n\n  std::vector<int> test_vector = initial;\n  absl::c_copy(input, test_vector.begin() + 1);\n  EXPECT_EQ(expected, test_vector);\n}\n\nTEST(MutatingTest, CopyFrontInserter) {\n  const std::list<int> initial = {4, 5};\n  const std::list<int> input = {1, 2, 3};\n  const std::list<int> expected = {3, 2, 1, 4, 5};\n\n  std::list<int> test_list = initial;\n  absl::c_copy(input, std::front_inserter(test_list));\n  EXPECT_EQ(expected, test_list);\n}\n\nTEST(MutatingTest, CopyBackInserter) {\n  const std::vector<int> initial = {4, 5};\n  const std::list<int> input = {1, 2, 3};\n  const std::vector<int> expected = {4, 5, 1, 2, 3};\n\n  std::list<int> test_list(initial.begin(), initial.end());\n  absl::c_copy(input, std::back_inserter(test_list));\n  EXPECT_EQ(std::list<int>(expected.begin(), expected.end()), test_list);\n\n  std::vector<int> test_vector = initial;\n  absl::c_copy(input, std::back_inserter(test_vector));\n  EXPECT_EQ(expected, test_vector);\n}\n\nTEST(MutatingTest, CopyN) {\n  const std::vector<int> initial = {1, 2, 3, 4, 5};\n  const std::vector<int> expected = {1, 2};\n  std::vector<int> actual;\n  absl::c_copy_n(initial, 2, back_inserter(actual));\n  EXPECT_EQ(expected, actual);\n}\n\nTEST(MutatingTest, CopyIf) {\n  const std::list<int> input = {1, 2, 3};\n  std::vector<int> output;\n  absl::c_copy_if(input, std::back_inserter(output),\n                  [](int i) { return i != 2; });\n  EXPECT_THAT(output, ElementsAre(1, 3));\n}\n\nTEST(MutatingTest, CopyBackward) {\n  std::vector<int> actual = {1, 2, 3, 4, 5};\n  std::vector<int> expected = {1, 2, 1, 2, 3};\n  absl::c_copy_backward(absl::MakeSpan(actual.data(), 3), actual.end());\n  EXPECT_EQ(expected, actual);\n}\n\nTEST(MutatingTest, Move) {\n  std::vector<std::unique_ptr<int>> src;\n  src.emplace_back(absl::make_unique<int>(1));\n  src.emplace_back(absl::make_unique<int>(2));\n  src.emplace_back(absl::make_unique<int>(3));\n  src.emplace_back(absl::make_unique<int>(4));\n  src.emplace_back(absl::make_unique<int>(5));\n\n  std::vector<std::unique_ptr<int>> dest = {};\n  absl::c_move(src, std::back_inserter(dest));\n  EXPECT_THAT(src, Each(IsNull()));\n  EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(4),\n                                Pointee(5)));\n}\n\nTEST(MutatingTest, MoveBackward) {\n  std::vector<std::unique_ptr<int>> actual;\n  actual.emplace_back(absl::make_unique<int>(1));\n  actual.emplace_back(absl::make_unique<int>(2));\n  actual.emplace_back(absl::make_unique<int>(3));\n  actual.emplace_back(absl::make_unique<int>(4));\n  actual.emplace_back(absl::make_unique<int>(5));\n  auto subrange = absl::MakeSpan(actual.data(), 3);\n  absl::c_move_backward(subrange, actual.end());\n  EXPECT_THAT(actual, ElementsAre(IsNull(), IsNull(), Pointee(1), Pointee(2),\n                                  Pointee(3)));\n}\n\nTEST(MutatingTest, MoveWithRvalue) {\n  auto MakeRValueSrc = [] {\n    std::vector<std::unique_ptr<int>> src;\n    src.emplace_back(absl::make_unique<int>(1));\n    src.emplace_back(absl::make_unique<int>(2));\n    src.emplace_back(absl::make_unique<int>(3));\n    return src;\n  };\n\n  std::vector<std::unique_ptr<int>> dest = MakeRValueSrc();\n  absl::c_move(MakeRValueSrc(), std::back_inserter(dest));\n  EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(1),\n                                Pointee(2), Pointee(3)));\n}\n\nTEST(MutatingTest, SwapRanges) {\n  std::vector<int> odds = {2, 4, 6};\n  std::vector<int> evens = {1, 3, 5};\n  absl::c_swap_ranges(odds, evens);\n  EXPECT_THAT(odds, ElementsAre(1, 3, 5));\n  EXPECT_THAT(evens, ElementsAre(2, 4, 6));\n\n  odds.pop_back();\n  absl::c_swap_ranges(odds, evens);\n  EXPECT_THAT(odds, ElementsAre(2, 4));\n  EXPECT_THAT(evens, ElementsAre(1, 3, 6));\n\n  absl::c_swap_ranges(evens, odds);\n  EXPECT_THAT(odds, ElementsAre(1, 3));\n  EXPECT_THAT(evens, ElementsAre(2, 4, 6));\n}\n\nTEST_F(NonMutatingTest, Transform) {\n  std::vector<int> x{0, 2, 4}, y, z;\n  auto end = absl::c_transform(x, back_inserter(y), std::negate<int>());\n  EXPECT_EQ(std::vector<int>({0, -2, -4}), y);\n  *end = 7;\n  EXPECT_EQ(std::vector<int>({0, -2, -4, 7}), y);\n\n  y = {1, 3, 0};\n  end = absl::c_transform(x, y, back_inserter(z), std::plus<int>());\n  EXPECT_EQ(std::vector<int>({1, 5, 4}), z);\n  *end = 7;\n  EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);\n\n  z.clear();\n  y.pop_back();\n  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());\n  EXPECT_EQ(std::vector<int>({1, 5}), z);\n  *end = 7;\n  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);\n\n  z.clear();\n  std::swap(x, y);\n  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());\n  EXPECT_EQ(std::vector<int>({1, 5}), z);\n  *end = 7;\n  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);\n}\n\nTEST(MutatingTest, Replace) {\n  const std::vector<int> initial = {1, 2, 3, 1, 4, 5};\n  const std::vector<int> expected = {4, 2, 3, 4, 4, 5};\n\n  std::vector<int> test_vector = initial;\n  absl::c_replace(test_vector, 1, 4);\n  EXPECT_EQ(expected, test_vector);\n\n  std::list<int> test_list(initial.begin(), initial.end());\n  absl::c_replace(test_list, 1, 4);\n  EXPECT_EQ(std::list<int>(expected.begin(), expected.end()), test_list);\n}\n\nTEST(MutatingTest, ReplaceIf) {\n  std::vector<int> actual = {1, 2, 3, 4, 5};\n  const std::vector<int> expected = {0, 2, 0, 4, 0};\n\n  absl::c_replace_if(actual, IsOdd, 0);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST(MutatingTest, ReplaceCopy) {\n  const std::vector<int> initial = {1, 2, 3, 1, 4, 5};\n  const std::vector<int> expected = {4, 2, 3, 4, 4, 5};\n\n  std::vector<int> actual;\n  absl::c_replace_copy(initial, back_inserter(actual), 1, 4);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST(MutatingTest, Sort) {\n  std::vector<int> test_vector = {2, 3, 1, 4};\n  absl::c_sort(test_vector);\n  EXPECT_THAT(test_vector, ElementsAre(1, 2, 3, 4));\n}\n\nTEST(MutatingTest, SortWithPredicate) {\n  std::vector<int> test_vector = {2, 3, 1, 4};\n  absl::c_sort(test_vector, std::greater<int>());\n  EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1));\n}\n\n// For absl::c_stable_sort tests. Needs an operator< that does not cover all\n// fields so that the test can check the sort preserves order of equal elements.\nstruct Element {\n  int key;\n  int value;\n  friend bool operator<(const Element& e1, const Element& e2) {\n    return e1.key < e2.key;\n  }\n  // Make gmock print useful diagnostics.\n  friend std::ostream& operator<<(std::ostream& o, const Element& e) {\n    return o << \"{\" << e.key << \", \" << e.value << \"}\";\n  }\n};\n\nMATCHER_P2(IsElement, key, value, \"\") {\n  return arg.key == key && arg.value == value;\n}\n\nTEST(MutatingTest, StableSort) {\n  std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};\n  absl::c_stable_sort(test_vector);\n  EXPECT_THAT(test_vector,\n              ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),\n                          IsElement(2, 0), IsElement(2, 2)));\n}\n\nTEST(MutatingTest, StableSortWithPredicate) {\n  std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};\n  absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) {\n    return e2 < e1;\n  });\n  EXPECT_THAT(test_vector,\n              ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),\n                          IsElement(1, 1), IsElement(1, 0)));\n}\n\nTEST(MutatingTest, ReplaceCopyIf) {\n  const std::vector<int> initial = {1, 2, 3, 4, 5};\n  const std::vector<int> expected = {0, 2, 0, 4, 0};\n\n  std::vector<int> actual;\n  absl::c_replace_copy_if(initial, back_inserter(actual), IsOdd, 0);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST(MutatingTest, Fill) {\n  std::vector<int> actual(5);\n  absl::c_fill(actual, 1);\n  EXPECT_THAT(actual, ElementsAre(1, 1, 1, 1, 1));\n}\n\nTEST(MutatingTest, FillN) {\n  std::vector<int> actual(5, 0);\n  absl::c_fill_n(actual, 2, 1);\n  EXPECT_THAT(actual, ElementsAre(1, 1, 0, 0, 0));\n}\n\nTEST(MutatingTest, Generate) {\n  std::vector<int> actual(5);\n  int x = 0;\n  absl::c_generate(actual, [&x]() { return ++x; });\n  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(MutatingTest, GenerateN) {\n  std::vector<int> actual(5, 0);\n  int x = 0;\n  absl::c_generate_n(actual, 3, [&x]() { return ++x; });\n  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 0, 0));\n}\n\nTEST(MutatingTest, RemoveCopy) {\n  std::vector<int> actual;\n  absl::c_remove_copy(std::vector<int>{1, 2, 3}, back_inserter(actual), 2);\n  EXPECT_THAT(actual, ElementsAre(1, 3));\n}\n\nTEST(MutatingTest, RemoveCopyIf) {\n  std::vector<int> actual;\n  absl::c_remove_copy_if(std::vector<int>{1, 2, 3}, back_inserter(actual),\n                         IsOdd);\n  EXPECT_THAT(actual, ElementsAre(2));\n}\n\nTEST(MutatingTest, UniqueCopy) {\n  std::vector<int> actual;\n  absl::c_unique_copy(std::vector<int>{1, 2, 2, 2, 3, 3, 2},\n                      back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 2));\n}\n\nTEST(MutatingTest, UniqueCopyWithPredicate) {\n  std::vector<int> actual;\n  absl::c_unique_copy(std::vector<int>{1, 2, 3, -1, -2, -3, 1},\n                      back_inserter(actual),\n                      [](int x, int y) { return (x < 0) == (y < 0); });\n  EXPECT_THAT(actual, ElementsAre(1, -1, 1));\n}\n\nTEST(MutatingTest, Reverse) {\n  std::vector<int> test_vector = {1, 2, 3, 4};\n  absl::c_reverse(test_vector);\n  EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1));\n\n  std::list<int> test_list = {1, 2, 3, 4};\n  absl::c_reverse(test_list);\n  EXPECT_THAT(test_list, ElementsAre(4, 3, 2, 1));\n}\n\nTEST(MutatingTest, ReverseCopy) {\n  std::vector<int> actual;\n  absl::c_reverse_copy(std::vector<int>{1, 2, 3, 4}, back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(4, 3, 2, 1));\n}\n\nTEST(MutatingTest, Rotate) {\n  std::vector<int> actual = {1, 2, 3, 4};\n  auto it = absl::c_rotate(actual, actual.begin() + 2);\n  EXPECT_THAT(actual, testing::ElementsAreArray({3, 4, 1, 2}));\n  EXPECT_EQ(*it, 1);\n}\n\nTEST(MutatingTest, RotateCopy) {\n  std::vector<int> initial = {1, 2, 3, 4};\n  std::vector<int> actual;\n  auto end =\n      absl::c_rotate_copy(initial, initial.begin() + 2, back_inserter(actual));\n  *end = 5;\n  EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5));\n}\n\nTEST(MutatingTest, Shuffle) {\n  std::vector<int> actual = {1, 2, 3, 4, 5};\n  absl::c_shuffle(actual, absl::InsecureBitGen());\n  EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(MutatingTest, Sample) {\n  std::vector<int> actual;\n  absl::c_sample(std::vector<int>{1, 2, 3, 4, 5}, std::back_inserter(actual), 3,\n                 absl::InsecureBitGen());\n  EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5}));\n  EXPECT_THAT(actual, SizeIs(3));\n}\n\nTEST(MutatingTest, PartialSort) {\n  std::vector<int> sequence{5, 3, 42, 0};\n  absl::c_partial_sort(sequence, sequence.begin() + 2);\n  EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(0, 3));\n  absl::c_partial_sort(sequence, sequence.begin() + 2, std::greater<int>());\n  EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(42, 5));\n}\n\nTEST(MutatingTest, PartialSortCopy) {\n  const std::vector<int> initial = {5, 3, 42, 0};\n  std::vector<int> actual(2);\n  absl::c_partial_sort_copy(initial, actual);\n  EXPECT_THAT(actual, ElementsAre(0, 3));\n  absl::c_partial_sort_copy(initial, actual, std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(42, 5));\n}\n\nTEST(MutatingTest, Merge) {\n  std::vector<int> actual;\n  absl::c_merge(std::vector<int>{1, 3, 5}, std::vector<int>{2, 4},\n                back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(MutatingTest, MergeWithComparator) {\n  std::vector<int> actual;\n  absl::c_merge(std::vector<int>{5, 3, 1}, std::vector<int>{4, 2},\n                back_inserter(actual), std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1));\n}\n\nTEST(MutatingTest, InplaceMerge) {\n  std::vector<int> actual = {1, 3, 5, 2, 4};\n  absl::c_inplace_merge(actual, actual.begin() + 3);\n  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(MutatingTest, InplaceMergeWithComparator) {\n  std::vector<int> actual = {5, 3, 1, 4, 2};\n  absl::c_inplace_merge(actual, actual.begin() + 3, std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1));\n}\n\nclass SetOperationsTest : public testing::Test {\n protected:\n  std::vector<int> a_ = {1, 2, 3};\n  std::vector<int> b_ = {1, 3, 5};\n\n  std::vector<int> a_reversed_ = {3, 2, 1};\n  std::vector<int> b_reversed_ = {5, 3, 1};\n};\n\nTEST_F(SetOperationsTest, SetUnion) {\n  std::vector<int> actual;\n  absl::c_set_union(a_, b_, back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 5));\n}\n\nTEST_F(SetOperationsTest, SetUnionWithComparator) {\n  std::vector<int> actual;\n  absl::c_set_union(a_reversed_, b_reversed_, back_inserter(actual),\n                    std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(5, 3, 2, 1));\n}\n\nTEST_F(SetOperationsTest, SetIntersection) {\n  std::vector<int> actual;\n  absl::c_set_intersection(a_, b_, back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(1, 3));\n}\n\nTEST_F(SetOperationsTest, SetIntersectionWithComparator) {\n  std::vector<int> actual;\n  absl::c_set_intersection(a_reversed_, b_reversed_, back_inserter(actual),\n                           std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(3, 1));\n}\n\nTEST_F(SetOperationsTest, SetDifference) {\n  std::vector<int> actual;\n  absl::c_set_difference(a_, b_, back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(2));\n}\n\nTEST_F(SetOperationsTest, SetDifferenceWithComparator) {\n  std::vector<int> actual;\n  absl::c_set_difference(a_reversed_, b_reversed_, back_inserter(actual),\n                         std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(2));\n}\n\nTEST_F(SetOperationsTest, SetSymmetricDifference) {\n  std::vector<int> actual;\n  absl::c_set_symmetric_difference(a_, b_, back_inserter(actual));\n  EXPECT_THAT(actual, ElementsAre(2, 5));\n}\n\nTEST_F(SetOperationsTest, SetSymmetricDifferenceWithComparator) {\n  std::vector<int> actual;\n  absl::c_set_symmetric_difference(a_reversed_, b_reversed_,\n                                   back_inserter(actual), std::greater<int>());\n  EXPECT_THAT(actual, ElementsAre(5, 2));\n}\n\nTEST(HeapOperationsTest, WithoutComparator) {\n  std::vector<int> heap = {1, 2, 3};\n  EXPECT_FALSE(absl::c_is_heap(heap));\n  absl::c_make_heap(heap);\n  EXPECT_TRUE(absl::c_is_heap(heap));\n  heap.push_back(4);\n  EXPECT_EQ(3, absl::c_is_heap_until(heap) - heap.begin());\n  absl::c_push_heap(heap);\n  EXPECT_EQ(4, heap[0]);\n  absl::c_pop_heap(heap);\n  EXPECT_EQ(4, heap[3]);\n  absl::c_make_heap(heap);\n  absl::c_sort_heap(heap);\n  EXPECT_THAT(heap, ElementsAre(1, 2, 3, 4));\n  EXPECT_FALSE(absl::c_is_heap(heap));\n}\n\nTEST(HeapOperationsTest, WithComparator) {\n  using greater = std::greater<int>;\n  std::vector<int> heap = {3, 2, 1};\n  EXPECT_FALSE(absl::c_is_heap(heap, greater()));\n  absl::c_make_heap(heap, greater());\n  EXPECT_TRUE(absl::c_is_heap(heap, greater()));\n  heap.push_back(0);\n  EXPECT_EQ(3, absl::c_is_heap_until(heap, greater()) - heap.begin());\n  absl::c_push_heap(heap, greater());\n  EXPECT_EQ(0, heap[0]);\n  absl::c_pop_heap(heap, greater());\n  EXPECT_EQ(0, heap[3]);\n  absl::c_make_heap(heap, greater());\n  absl::c_sort_heap(heap, greater());\n  EXPECT_THAT(heap, ElementsAre(3, 2, 1, 0));\n  EXPECT_FALSE(absl::c_is_heap(heap, greater()));\n}\n\nTEST(MutatingTest, PermutationOperations) {\n  std::vector<int> initial = {1, 2, 3, 4};\n  std::vector<int> permuted = initial;\n\n  absl::c_next_permutation(permuted);\n  EXPECT_TRUE(absl::c_is_permutation(initial, permuted));\n  EXPECT_TRUE(absl::c_is_permutation(initial, permuted, std::equal_to<int>()));\n\n  std::vector<int> permuted2 = initial;\n  absl::c_prev_permutation(permuted2, std::greater<int>());\n  EXPECT_EQ(permuted, permuted2);\n\n  absl::c_prev_permutation(permuted);\n  EXPECT_EQ(initial, permuted);\n}\n\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L\n\nTEST(ConstexprTest, Distance) {\n  // Works at compile time with constexpr containers.\n  static_assert(absl::c_distance(std::array<int, 3>()) == 3);\n}\n\nTEST(ConstexprTest, MinElement) {\n  constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(*absl::c_min_element(kArray) == 1);\n}\n\nTEST(ConstexprTest, MinElementWithPredicate) {\n  constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(*absl::c_min_element(kArray, std::greater<int>()) == 3);\n}\n\nTEST(ConstexprTest, MaxElement) {\n  constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(*absl::c_max_element(kArray) == 3);\n}\n\nTEST(ConstexprTest, MaxElementWithPredicate) {\n  constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(*absl::c_max_element(kArray, std::greater<int>()) == 1);\n}\n\nTEST(ConstexprTest, MinMaxElement) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  constexpr auto kMinMaxPair = absl::c_minmax_element(kArray);\n  static_assert(*kMinMaxPair.first == 1);\n  static_assert(*kMinMaxPair.second == 3);\n}\n\nTEST(ConstexprTest, MinMaxElementWithPredicate) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  constexpr auto kMinMaxPair =\n      absl::c_minmax_element(kArray, std::greater<int>());\n  static_assert(*kMinMaxPair.first == 3);\n  static_assert(*kMinMaxPair.second == 1);\n}\n#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&\n        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L\n\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\nTEST(ConstexprTest, LinearSearch) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_linear_search(kArray, 3));\n  static_assert(!absl::c_linear_search(kArray, 4));\n}\n\nTEST(ConstexprTest, AllOf) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(!absl::c_all_of(kArray, [](int x) { return x > 1; }));\n  static_assert(absl::c_all_of(kArray, [](int x) { return x > 0; }));\n}\n\nTEST(ConstexprTest, AnyOf) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_any_of(kArray, [](int x) { return x > 2; }));\n  static_assert(!absl::c_any_of(kArray, [](int x) { return x > 5; }));\n}\n\nTEST(ConstexprTest, NoneOf) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(!absl::c_none_of(kArray, [](int x) { return x > 2; }));\n  static_assert(absl::c_none_of(kArray, [](int x) { return x > 5; }));\n}\n\nTEST(ConstexprTest, ForEach) {\n  static constexpr std::array<int, 3> kArray = [] {\n    std::array<int, 3> array = {1, 2, 3};\n    absl::c_for_each(array, [](int& x) { x += 1; });\n    return array;\n  }();\n  static_assert(kArray == std::array{2, 3, 4});\n}\n\nTEST(ConstexprTest, Find) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_find(kArray, 1) == kArray.begin());\n  static_assert(absl::c_find(kArray, 4) == kArray.end());\n}\n\nTEST(ConstexprTest, Contains) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_contains(kArray, 1));\n  static_assert(!absl::c_contains(kArray, 4));\n}\n\nTEST(ConstexprTest, FindIf) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_find_if(kArray, [](int x) { return x > 2; }) ==\n                kArray.begin() + 2);\n  static_assert(absl::c_find_if(kArray, [](int x) { return x > 5; }) ==\n                kArray.end());\n}\n\nTEST(ConstexprTest, FindIfNot) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 1; }) ==\n                kArray.begin());\n  static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 0; }) ==\n                kArray.end());\n}\n\nTEST(ConstexprTest, FindEnd) {\n  static constexpr std::array<int, 5> kHaystack = {1, 2, 3, 2, 3};\n  static constexpr std::array<int, 2> kNeedle = {2, 3};\n  static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3);\n}\n\nTEST(ConstexprTest, FindFirstOf) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin());\n}\n\nTEST(ConstexprTest, AdjacentFind) {\n  static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};\n  static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1);\n}\n\nTEST(ConstexprTest, AdjacentFindWithPredicate) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_adjacent_find(kArray, std::less<int>()) ==\n                kArray.begin());\n}\n\nTEST(ConstexprTest, Count) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_count(kArray, 1) == 1);\n  static_assert(absl::c_count(kArray, 2) == 1);\n  static_assert(absl::c_count(kArray, 3) == 1);\n  static_assert(absl::c_count(kArray, 4) == 0);\n}\n\nTEST(ConstexprTest, CountIf) {\n  static constexpr std::array<int, 3> kArray = {1, 2, 3};\n  static_assert(absl::c_count_if(kArray, [](int x) { return x > 0; }) == 3);\n  static_assert(absl::c_count_if(kArray, [](int x) { return x > 1; }) == 2);\n}\n\nTEST(ConstexprTest, Mismatch) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_mismatch(kArray1, kArray2) ==\n                std::pair{kArray1.end(), kArray2.end()});\n  static_assert(absl::c_mismatch(kArray1, kArray3) ==\n                std::pair{kArray1.begin(), kArray3.begin()});\n}\n\nTEST(ConstexprTest, MismatchWithPredicate) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to<int>()) ==\n                std::pair{kArray1.begin(), kArray2.begin()});\n  static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to<int>()) ==\n                std::pair{kArray1.end(), kArray3.end()});\n}\n\nTEST(ConstexprTest, Equal) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_equal(kArray1, kArray2));\n  static_assert(!absl::c_equal(kArray1, kArray3));\n}\n\nTEST(ConstexprTest, EqualWithPredicate) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to<int>()));\n  static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to<int>()));\n}\n\nTEST(ConstexprTest, IsPermutation) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {3, 2, 1};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_is_permutation(kArray1, kArray2));\n  static_assert(!absl::c_is_permutation(kArray1, kArray3));\n}\n\nTEST(ConstexprTest, IsPermutationWithPredicate) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {3, 2, 1};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to<int>()));\n  static_assert(\n      !absl::c_is_permutation(kArray1, kArray3, std::equal_to<int>()));\n}\n\nTEST(ConstexprTest, Search) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_search(kArray1, kArray2) == kArray1.begin());\n  static_assert(absl::c_search(kArray1, kArray3) == kArray1.end());\n}\n\nTEST(ConstexprTest, SearchWithPredicate) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to<int>()) ==\n                kArray1.end());\n  static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to<int>()) ==\n                kArray1.begin());\n}\n\nTEST(ConstexprTest, ContainsSubrange) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(absl::c_contains_subrange(kArray1, kArray2));\n  static_assert(!absl::c_contains_subrange(kArray1, kArray3));\n}\n\nTEST(ConstexprTest, ContainsSubrangeWithPredicate) {\n  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};\n  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};\n  static_assert(\n      !absl::c_contains_subrange(kArray1, kArray2, std::not_equal_to<>()));\n  static_assert(\n      absl::c_contains_subrange(kArray1, kArray3, std::not_equal_to<>()));\n}\n\nTEST(ConstexprTest, SearchN) {\n  static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};\n  static_assert(absl::c_search_n(kArray, 1, 1) == kArray.begin());\n  static_assert(absl::c_search_n(kArray, 2, 2) == kArray.begin() + 1);\n  static_assert(absl::c_search_n(kArray, 1, 4) == kArray.end());\n}\n\nTEST(ConstexprTest, SearchNWithPredicate) {\n  static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};\n  static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to<int>()) ==\n                kArray.begin() + 1);\n  static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to<int>()) ==\n                kArray.end());\n  static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to<int>()) ==\n                kArray.begin());\n}\n\nTEST(ConstexprTest, Copy) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayCopy = [] {\n    std::array<int, 3> array;\n    absl::c_copy(kArray, array.begin());\n    return array;\n  }();\n  static_assert(kArrayCopy == kArray);\n}\n\nTEST(ConstexprTest, CopyN) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayCopy = [] {\n    std::array<int, 2> array;\n    absl::c_copy_n(kArray, 2, array.begin());\n    return array;\n  }();\n  static_assert(kArrayCopy == std::array{1, 2});\n}\n\nTEST(ConstexprTest, CopyIf) {\n  static constexpr std::array kArray = {1, 2, 3, 4};\n  static constexpr auto kArrayCopy = [] {\n    std::array<int, 3> array;\n    absl::c_copy_if(kArray, array.begin(), [](int x) { return x > 1; });\n    return array;\n  }();\n  static_assert(kArrayCopy == std::array{2, 3, 4});\n}\n\nTEST(ConstexprTest, CopyBackward) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayCopy = [] {\n    std::array<int, 3> array;\n    absl::c_copy_backward(kArray, array.end());\n    return array;\n  }();\n  static_assert(kArrayCopy == kArray);\n}\n\nTEST(ConstexprTest, Move) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayMove = [] {\n    std::array<int, 3> array;\n    absl::c_move(kArray, array.begin());\n    return array;\n  }();\n  static_assert(kArrayMove == kArray);\n}\n\nTEST(ConstexprTest, MoveBackward) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayMove = [] {\n    std::array<int, 3> array;\n    absl::c_move_backward(kArray, array.end());\n    return array;\n  }();\n  static_assert(kArrayMove == kArray);\n}\n\nTEST(ConstexprTest, SwapRanges) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {4, 5, 6};\n\n  static constexpr auto kSwapped = [] {\n    std::array arr1 = kArray1;\n    std::array arr2 = kArray2;\n    absl::c_swap_ranges(arr1, arr2);\n    return std::make_pair(arr1, arr2);\n  }();\n\n  static_assert(kSwapped.first == kArray2);\n  static_assert(kSwapped.second == kArray1);\n}\n\nTEST(ConstexprTest, Transform) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayTransform = [] {\n    std::array<int, 3> array;\n    absl::c_transform(kArray, array.begin(), [](int x) { return x + 1; });\n    return array;\n  }();\n  static_assert(kArrayTransform == std::array{2, 3, 4});\n}\n\nTEST(ConstexprTest, Replace) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayReplace = [] {\n    std::array array = kArray;\n    absl::c_replace(array, 1, 4);\n    return array;\n  }();\n  static_assert(kArrayReplace == std::array{4, 2, 3});\n}\n\nTEST(ConstexprTest, ReplaceIf) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayReplaceIf = [] {\n    std::array array = kArray;\n    absl::c_replace_if(array, [](int x) { return x == 1; }, 4);\n    return array;\n  }();\n  static_assert(kArrayReplaceIf == std::array{4, 2, 3});\n}\n\nTEST(ConstexprTest, ReplaceCopy) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayReplaceCopy = [] {\n    std::array<int, 3> array;\n    absl::c_replace_copy(kArray, array.begin(), 1, 4);\n    return array;\n  }();\n  static_assert(kArrayReplaceCopy == std::array{4, 2, 3});\n}\n\nTEST(ConstexprTest, ReplaceCopyIf) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayReplaceCopyIf = [] {\n    std::array<int, 3> array;\n    absl::c_replace_copy_if(\n        kArray, array.begin(), [](int x) { return x == 1; }, 4);\n    return array;\n  }();\n  static_assert(kArrayReplaceCopyIf == std::array{4, 2, 3});\n}\n\nTEST(ConstexprTest, Fill) {\n  static constexpr auto kArrayFill = [] {\n    std::array<int, 3> array;\n    absl::c_fill(array, 4);\n    return array;\n  }();\n  static_assert(kArrayFill == std::array{4, 4, 4});\n}\n\nTEST(ConstexprTest, FillN) {\n  static constexpr auto kArrayFillN = [] {\n    std::array array = {0, 0, 0};\n    absl::c_fill_n(array, 2, 4);\n    return array;\n  }();\n  static_assert(kArrayFillN == std::array{4, 4, 0});\n}\n\nTEST(ConstexprTest, Generate) {\n  static constexpr auto kArrayGenerate = [] {\n    std::array<int, 3> array;\n    absl::c_generate(array, []() { return 4; });\n    return array;\n  }();\n  static_assert(kArrayGenerate == std::array{4, 4, 4});\n}\n\nTEST(ConstexprTest, GenerateN) {\n  static constexpr auto kArrayGenerateN = [] {\n    std::array array = {0, 0, 0};\n    absl::c_generate_n(array, 2, []() { return 4; });\n    return array;\n  }();\n  static_assert(kArrayGenerateN == std::array{4, 4, 0});\n}\n\nTEST(ConstexprTest, RemoveCopy) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayRemoveCopy = [] {\n    std::array<int, 2> array;\n    absl::c_remove_copy(kArray, array.begin(), 1);\n    return array;\n  }();\n  static_assert(kArrayRemoveCopy == std::array{2, 3});\n}\n\nTEST(ConstexprTest, RemoveCopyIf) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayRemoveCopyIf = [] {\n    std::array<int, 2> array;\n    absl::c_remove_copy_if(kArray, array.begin(), [](int x) { return x == 1; });\n    return array;\n  }();\n  static_assert(kArrayRemoveCopyIf == std::array{2, 3});\n}\n\nTEST(ConstexprTest, UniqueCopy) {\n  static constexpr std::array kArray = {1, 2, 2, 3};\n  static constexpr auto kArrayUniqueCopy = [] {\n    std::array<int, 3> array;\n    absl::c_unique_copy(kArray, array.begin());\n    return array;\n  }();\n  static_assert(kArrayUniqueCopy == std::array{1, 2, 3});\n}\n\nTEST(ConstexprTest, UniqueCopyWithPredicate) {\n  static constexpr std::array kArray = {1, 2, 2, 3};\n  static constexpr auto kArrayUniqueCopy = [] {\n    std::array<int, 3> array;\n    absl::c_unique_copy(kArray, array.begin(), std::equal_to<>());\n    return array;\n  }();\n  static_assert(kArrayUniqueCopy == std::array{1, 2, 3});\n}\n\nTEST(ConstexprTest, Reverse) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayReverse = [] {\n    std::array array = kArray;\n    absl::c_reverse(array);\n    return array;\n  }();\n  static_assert(kArrayReverse == std::array{3, 2, 1});\n}\n\nTEST(ConstexprTest, ReverseCopy) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayReverseCopy = [] {\n    std::array<int, 3> array;\n    absl::c_reverse_copy(kArray, array.begin());\n    return array;\n  }();\n  static_assert(kArrayReverseCopy == std::array{3, 2, 1});\n}\n\nTEST(ConstexprTest, Rotate) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayRotate = [] {\n    std::array array = kArray;\n    absl::c_rotate(array, array.begin() + 1);\n    return array;\n  }();\n  static_assert(kArrayRotate == std::array{2, 3, 1});\n}\n\nTEST(ConstexprTest, RotateCopy) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayRotateCopy = [] {\n    std::array<int, 3> array;\n    absl::c_rotate_copy(kArray, kArray.begin() + 1, array.begin());\n    return array;\n  }();\n  static_assert(kArrayRotateCopy == std::array{2, 3, 1});\n}\n\nTEST(ConstexprTest, IsPartitioned) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static_assert(!absl::c_is_partitioned(kArray, [](int x) { return x > 1; }));\n\n  static constexpr std::array kPartitionedArray = {2, 3, 1};\n  static_assert(\n      absl::c_is_partitioned(kPartitionedArray, [](int x) { return x > 1; }));\n}\n\nTEST(ConstexprTest, Partition) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayPartition = [] {\n    std::array array = kArray;\n    absl::c_partition(array, [](int x) { return x > 1; });\n    return array;\n  }();\n  static_assert(\n      absl::c_is_partitioned(kArrayPartition, [](int x) { return x > 1; }));\n}\n\nTEST(ConstexprTest, PartitionCopy) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kPartitioned = [] {\n    std::array<int, 2> true_part;\n    std::array<int, 1> false_part;\n    absl::c_partition_copy(kArray, true_part.begin(), false_part.begin(),\n                           [](int x) { return x > 1; });\n    return std::make_pair(true_part, false_part);\n  }();\n  static_assert(kPartitioned.first == std::array{2, 3});\n  static_assert(kPartitioned.second == std::array{1});\n}\n\nTEST(ConstexprTest, PartitionPoint) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kPartitionPoint =\n      absl::c_partition_point(kArray, [](int x) { return x > 1; });\n  static_assert(kPartitionPoint == kArray.end());\n}\n\nTEST(ConstexprTest, Sort) {\n  static constexpr std::array kArray = {2, 1, 3};\n  static constexpr auto kArraySort = [] {\n    std::array array = kArray;\n    absl::c_sort(array);\n    return array;\n  }();\n  static_assert(kArraySort == std::array{1, 2, 3});\n}\n\nTEST(ConstexprTest, SortWithPredicate) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArraySort = [] {\n    std::array array = kArray;\n    absl::c_sort(array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArraySort == std::array{3, 2, 1});\n}\n\nTEST(ConstexprTest, IsSorted) {\n  static constexpr std::array kSortedArray = {1, 2, 3};\n  static_assert(absl::c_is_sorted(kSortedArray));\n  static constexpr std::array kUnsortedArray = {1, 3, 2};\n  static_assert(!absl::c_is_sorted(kUnsortedArray));\n}\n\nTEST(ConstexprTest, IsSortedWithPredicate) {\n  static constexpr std::array kSortedArray = {3, 2, 1};\n  static_assert(absl::c_is_sorted(kSortedArray, std::greater<>()));\n  static constexpr std::array kUnsortedArray = {1, 3, 2};\n  static_assert(!absl::c_is_sorted(kUnsortedArray, std::greater<>()));\n}\n\nTEST(ConstexprTest, PartialSort) {\n  static constexpr std::array kArray = {3, 1, 4, 2};\n  static constexpr auto kArrayPartialSort = [] {\n    std::array array = kArray;\n    absl::c_partial_sort(array, array.begin() + 2);\n    return array;\n  }();\n  static_assert(kArrayPartialSort[0] == 1);\n  static_assert(kArrayPartialSort[1] == 2);\n}\n\nTEST(ConstexprTest, PartialSortWithPredicate) {\n  static constexpr std::array kArray = {3, 1, 4, 2};\n  static constexpr auto kArrayPartialSort = [] {\n    std::array array = kArray;\n    absl::c_partial_sort(array, array.begin() + 2, std::greater<>());\n    return array;\n  }();\n  static_assert(kArrayPartialSort[0] == 4);\n  static_assert(kArrayPartialSort[1] == 3);\n}\n\nTEST(ConstexprTest, PartialSortCopy) {\n  static constexpr std::array kArray = {3, 1, 4, 2};\n  static constexpr auto kArrayPartialSort = [] {\n    std::array<int, 4> array;\n    absl::c_partial_sort_copy(kArray, array);\n    return array;\n  }();\n  static_assert(kArrayPartialSort[0] == 1);\n  static_assert(kArrayPartialSort[1] == 2);\n}\n\nTEST(ConstexprTest, PartialSortCopyWithPredicate) {\n  static constexpr std::array kArray = {3, 1, 4, 2};\n  static constexpr auto kArrayPartialSort = [] {\n    std::array<int, 4> array;\n    absl::c_partial_sort_copy(kArray, array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArrayPartialSort[0] == 4);\n  static_assert(kArrayPartialSort[1] == 3);\n}\n\nTEST(ConstexprTest, IsSortedUntil) {\n  static constexpr std::array kSortedArray = {1, 2, 3};\n  static_assert(absl::c_is_sorted_until(kSortedArray) == kSortedArray.end());\n  static constexpr std::array kUnsortedArray = {1, 3, 2};\n  static_assert(absl::c_is_sorted_until(kUnsortedArray) ==\n                kUnsortedArray.begin() + 2);\n}\n\nTEST(ConstexprTest, IsSortedUntilWithPredicate) {\n  static constexpr std::array kSortedArray = {3, 2, 1};\n  static_assert(absl::c_is_sorted_until(kSortedArray, std::greater<>()) ==\n                kSortedArray.end());\n  static constexpr std::array kUnsortedArray = {1, 3, 2};\n  static_assert(absl::c_is_sorted_until(kUnsortedArray, std::greater<>()) ==\n                kUnsortedArray.begin() + 1);\n}\n\nTEST(ConstexprTest, NthElement) {\n  static constexpr std::array kArray = {2, 1, 3, 4};\n  static constexpr auto kArrayNthElement = [] {\n    std::array array = kArray;\n    absl::c_nth_element(array, array.begin() + 2);\n    return array;\n  }();\n  static_assert(kArrayNthElement[2] == 3);\n  static_assert(kArrayNthElement[0] <= kArrayNthElement[2]);\n  static_assert(kArrayNthElement[1] <= kArrayNthElement[2]);\n  static_assert(kArrayNthElement[3] >= kArrayNthElement[2]);\n}\n\nTEST(ConstexprTest, NthElementWithPredicate) {\n  static constexpr std::array kArray = {1, 2, 3, 4};\n  static constexpr auto kArrayNthElement = [] {\n    std::array array = kArray;\n    absl::c_nth_element(array, array.begin() + 2, std::greater<>());\n    return array;\n  }();\n  static_assert(kArrayNthElement[2] == 2);\n  static_assert(std::greater<>()(kArrayNthElement[0], kArrayNthElement[2]) ||\n                kArrayNthElement[0] == kArrayNthElement[2]);\n  static_assert(std::greater<>()(kArrayNthElement[1], kArrayNthElement[2]) ||\n                kArrayNthElement[1] == kArrayNthElement[2]);\n  static_assert(std::greater<>()(kArrayNthElement[2], kArrayNthElement[3]) ||\n                kArrayNthElement[2] == kArrayNthElement[3]);\n}\n\nTEST(ConstexprTest, LowerBound) {\n  static constexpr std::array kArray = {1, 2, 3, 4};\n  static constexpr auto kLowerBound = absl::c_lower_bound(kArray, 2);\n  static_assert(kLowerBound == kArray.begin() + 1);\n}\n\nTEST(ConstexprTest, LowerBoundWithPredicate) {\n  static constexpr std::array kArray = {4, 3, 2, 1};\n  static constexpr auto kLowerBound =\n      absl::c_lower_bound(kArray, 2, std::greater<>());\n  static_assert(kLowerBound == kArray.begin() + 2);\n}\n\nTEST(ConstexprTest, UpperBound) {\n  static constexpr std::array kArray = {1, 2, 3, 4};\n  static constexpr auto kUpperBound = absl::c_upper_bound(kArray, 2);\n  static_assert(kUpperBound == kArray.begin() + 2);\n}\n\nTEST(ConstexprTest, UpperBoundWithPredicate) {\n  static constexpr std::array kArray = {4, 3, 2, 1};\n  static constexpr auto kUpperBound =\n      absl::c_upper_bound(kArray, 2, std::greater<>());\n  static_assert(kUpperBound == kArray.begin() + 3);\n}\n\nTEST(ConstexprTest, EqualRange) {\n  static constexpr std::array kArray = {1, 2, 3, 4};\n  static constexpr auto kEqualRange = absl::c_equal_range(kArray, 2);\n  static_assert(kEqualRange.first == kArray.begin() + 1);\n  static_assert(kEqualRange.second == kArray.begin() + 2);\n}\n\nTEST(ConstexprTest, EqualRangeWithPredicate) {\n  static constexpr std::array kArray = {4, 3, 2, 1};\n  static constexpr auto kEqualRange =\n      absl::c_equal_range(kArray, 2, std::greater<>());\n  static_assert(kEqualRange.first == kArray.begin() + 2);\n  static_assert(kEqualRange.second == kArray.begin() + 3);\n}\n\nTEST(ConstexprTest, BinarySearch) {\n  static constexpr std::array kArray = {1, 2, 3, 4};\n  static constexpr bool kBinarySearch = absl::c_binary_search(kArray, 2);\n  static_assert(kBinarySearch);\n}\n\nTEST(ConstexprTest, BinarySearchWithPredicate) {\n  static constexpr std::array kArray = {4, 3, 2, 1};\n  static constexpr bool kBinarySearch =\n      absl::c_binary_search(kArray, 2, std::greater<>());\n  static_assert(kBinarySearch);\n}\n\nTEST(ConstexprTest, Merge) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {4, 5, 6};\n  static constexpr auto kArrayMerge = [] {\n    std::array<int, 6> array;\n    absl::c_merge(kArray1, kArray2, array.begin());\n    return array;\n  }();\n  static_assert(kArrayMerge == std::array{1, 2, 3, 4, 5, 6});\n}\n\nTEST(ConstexprTest, MergeWithPredicate) {\n  static constexpr std::array kArray1 = {3, 2, 1};\n  static constexpr std::array kArray2 = {6, 5, 4};\n  static constexpr auto kArrayMerge = [] {\n    std::array<int, 6> array;\n    absl::c_merge(kArray1, kArray2, array.begin(), std::greater<>());\n    return array;\n  }();\n  static_assert(kArrayMerge == std::array{6, 5, 4, 3, 2, 1});\n}\n\nTEST(ConstexprTest, Includes) {\n  static constexpr std::array kArray1 = {1, 2, 3, 4, 5, 6};\n  static constexpr std::array kArray2 = {2, 3, 5};\n  static constexpr bool kIncludes = absl::c_includes(kArray1, kArray2);\n  static_assert(kIncludes);\n}\n\nTEST(ConstexprTest, IncludesWithPredicate) {\n  static constexpr std::array kArray1 = {6, 5, 4, 3, 2, 1};\n  static constexpr std::array kArray2 = {5, 3, 2};\n  static constexpr bool kIncludes =\n      absl::c_includes(kArray1, kArray2, std::greater<>());\n  static_assert(kIncludes);\n}\n\nTEST(ConstexprTest, SetUnion) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {1, 3, 4};\n  static constexpr auto kArraySetUnion = [] {\n    std::array<int, 4> array;\n    absl::c_set_union(kArray1, kArray2, array.begin());\n    return array;\n  }();\n  static_assert(kArraySetUnion == std::array{1, 2, 3, 4});\n}\n\nTEST(ConstexprTest, SetUnionWithPredicate) {\n  static constexpr std::array kArray1 = {3, 2, 1};\n  static constexpr std::array kArray2 = {4, 3, 1};\n  static constexpr auto kArraySetUnion = [] {\n    std::array<int, 4> array;\n    absl::c_set_union(kArray1, kArray2, array.begin(), std::greater<>());\n    return array;\n  }();\n  static_assert(kArraySetUnion == std::array{4, 3, 2, 1});\n}\n\nTEST(ConstexprTest, SetIntersection) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {1, 3, 4};\n  static constexpr auto kArraySetIntersection = [] {\n    std::array<int, 2> array;\n    absl::c_set_intersection(kArray1, kArray2, array.begin());\n    return array;\n  }();\n  static_assert(kArraySetIntersection == std::array{1, 3});\n}\n\nTEST(ConstexprTest, SetIntersectionWithPredicate) {\n  static constexpr std::array kArray1 = {3, 2, 1};\n  static constexpr std::array kArray2 = {4, 3, 1};\n  static constexpr auto kArraySetIntersection = [] {\n    std::array<int, 2> array;\n    absl::c_set_intersection(kArray1, kArray2, array.begin(), std::greater<>());\n    return array;\n  }();\n  static_assert(kArraySetIntersection == std::array{3, 1});\n}\n\nTEST(ConstexprTest, SetDifference) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {1, 3, 4};\n  static constexpr auto kArraySetDifference = [] {\n    std::array<int, 1> array;\n    absl::c_set_difference(kArray1, kArray2, array.begin());\n    return array;\n  }();\n  static_assert(kArraySetDifference == std::array{2});\n}\n\nTEST(ConstexprTest, SetDifferenceWithPredicate) {\n  static constexpr std::array kArray1 = {3, 2, 1};\n  static constexpr std::array kArray2 = {4, 3, 1};\n  static constexpr auto kArraySetDifference = [] {\n    std::array<int, 1> array;\n    absl::c_set_difference(kArray1, kArray2, array.begin(), std::greater<>());\n    return array;\n  }();\n  static_assert(kArraySetDifference == std::array{2});\n}\n\nTEST(ConstexprTest, SetSymmetricDifference) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {1, 3, 4};\n  static constexpr auto kArraySetSymmetricDifference = [] {\n    std::array<int, 2> array;\n    absl::c_set_symmetric_difference(kArray1, kArray2, array.begin());\n    return array;\n  }();\n  static_assert(kArraySetSymmetricDifference == std::array{2, 4});\n}\n\nTEST(ConstexprTest, SetSymmetricDifferenceWithPredicate) {\n  static constexpr std::array kArray1 = {3, 2, 1};\n  static constexpr std::array kArray2 = {4, 3, 1};\n  static constexpr auto kArraySetSymmetricDifference = [] {\n    std::array<int, 2> array;\n    absl::c_set_symmetric_difference(kArray1, kArray2, array.begin(),\n                                     std::greater<>());\n    return array;\n  }();\n  static_assert(kArraySetSymmetricDifference == std::array{4, 2});\n}\n\nTEST(ConstexprTest, PushHeap) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 2, 3, 4};\n    absl::c_push_heap(array);\n    return array;\n  }();\n  static_assert(kArray[0] == 4);\n}\n\nTEST(ConstexprTest, PushHeapWithPredicate) {\n  static constexpr auto kArray = [] {\n    std::array array = {4, 3, 2, 1};\n    absl::c_push_heap(array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArray[0] == 1);\n}\n\nTEST(ConstexprTest, PopHeap) {\n  static constexpr auto kArray = [] {\n    std::array array = {4, 3, 2, 1};\n    absl::c_pop_heap(array);\n    return array;\n  }();\n  static_assert(kArray[3] == 4);\n}\n\nTEST(ConstexprTest, PopHeapWithPredicate) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 2, 3, 4};\n    absl::c_pop_heap(array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArray[3] == 1);\n}\n\nTEST(ConstexprTest, MakeHeap) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 2, 3, 4};\n    absl::c_make_heap(array);\n    return array;\n  }();\n  static_assert(absl::c_is_heap(kArray));\n}\n\nTEST(ConstexprTest, MakeHeapWithPredicate) {\n  static constexpr auto kArray = [] {\n    std::array array = {4, 3, 2, 1};\n    absl::c_make_heap(array, std::greater<>());\n    return array;\n  }();\n  static_assert(absl::c_is_heap(kArray, std::greater<>()));\n}\n\nTEST(ConstexprTest, SortHeap) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 2, 3, 4};\n    absl::c_make_heap(array);\n    absl::c_sort_heap(array);\n    return array;\n  }();\n  static_assert(kArray == std::array{1, 2, 3, 4});\n}\n\nTEST(ConstexprTest, SortHeapWithPredicate) {\n  static constexpr auto kArray = [] {\n    std::array array = {4, 3, 2, 1};\n    absl::c_make_heap(array, std::greater<>());\n    absl::c_sort_heap(array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArray == std::array{4, 3, 2, 1});\n}\n\nTEST(ConstexprTest, IsHeap) {\n  static constexpr std::array kHeap = {4, 2, 3, 1};\n  static_assert(absl::c_is_heap(kHeap));\n  static constexpr std::array kNotHeap = {1, 2, 3, 4};\n  static_assert(!absl::c_is_heap(kNotHeap));\n}\n\nTEST(ConstexprTest, IsHeapWithPredicate) {\n  static constexpr std::array kHeap = {1, 2, 3, 4};\n  static_assert(absl::c_is_heap(kHeap, std::greater<>()));\n  static constexpr std::array kNotHeap = {4, 3, 2, 1};\n  static_assert(!absl::c_is_heap(kNotHeap, std::greater<>()));\n}\n\nTEST(ConstexprTest, IsHeapUntil) {\n  static constexpr std::array kHeap = {4, 2, 3, 1};\n  static_assert(absl::c_is_heap_until(kHeap) == kHeap.end());\n  static constexpr std::array kNotHeap = {4, 2, 3, 5};\n  static_assert(absl::c_is_heap_until(kNotHeap) == kNotHeap.begin() + 3);\n}\n\nTEST(ConstexprTest, IsHeapUntilWithPredicate) {\n  static constexpr std::array kHeap = {1, 2, 3, 4};\n  static_assert(absl::c_is_heap_until(kHeap, std::greater<>()) == kHeap.end());\n  static constexpr std::array kNotHeap = {1, 2, 3, 0};\n  static_assert(absl::c_is_heap_until(kNotHeap, std::greater<>()) ==\n                kNotHeap.begin() + 3);\n}\n\nTEST(ConstexprTest, LexicographicalCompare) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {1, 2, 4};\n  static constexpr std::array kArray3 = {1, 2, 3};\n  static_assert(absl::c_lexicographical_compare(kArray1, kArray2));\n  static_assert(!absl::c_lexicographical_compare(kArray2, kArray1));\n  static_assert(!absl::c_lexicographical_compare(kArray1, kArray3));\n}\n\nTEST(ConstexprTest, LexicographicalCompareWithPredicate) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {1, 2, 4};\n  static constexpr std::array kArray3 = {1, 2, 3};\n  static_assert(\n      !absl::c_lexicographical_compare(kArray1, kArray2, std::greater<>()));\n  static_assert(\n      absl::c_lexicographical_compare(kArray2, kArray1, std::greater<>()));\n  static_assert(\n      !absl::c_lexicographical_compare(kArray1, kArray3, std::greater<>()));\n}\n\nTEST(ConstexprTest, NextPermutation) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 2, 3};\n    absl::c_next_permutation(array);\n    return array;\n  }();\n  static_assert(kArray == std::array{1, 3, 2});\n}\n\nTEST(ConstexprTest, NextPermutationWithPredicate) {\n  static constexpr auto kArray = [] {\n    std::array array = {3, 2, 1};\n    absl::c_next_permutation(array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArray == std::array{3, 1, 2});\n}\n\nTEST(ConstexprTest, PrevPermutation) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 3, 2};\n    absl::c_prev_permutation(array);\n    return array;\n  }();\n  static_assert(kArray == std::array{1, 2, 3});\n}\n\nTEST(ConstexprTest, PrevPermutationWithPredicate) {\n  static constexpr auto kArray = [] {\n    std::array array = {1, 2, 3};\n    absl::c_prev_permutation(array, std::greater<>());\n    return array;\n  }();\n  static_assert(kArray == std::array{1, 3, 2});\n}\n\nTEST(ConstexprTest, Iota) {\n  static constexpr auto kArray = [] {\n    std::array<int, 3> array;\n    absl::c_iota(array, 1);\n    return array;\n  }();\n  static_assert(kArray == std::array{1, 2, 3});\n}\n\nTEST(ConstexprTest, Accumulate) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static_assert(absl::c_accumulate(kArray, 0) == 6);\n}\n\nTEST(ConstexprTest, AccumulateWithPredicate) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static_assert(absl::c_accumulate(kArray, 1, std::multiplies<>()) == 6);\n}\n\nTEST(ConstexprTest, InnerProduct) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {4, 5, 6};\n  static_assert(absl::c_inner_product(kArray1, kArray2, 0) == 32);\n}\n\nTEST(ConstexprTest, InnerProductWithPredicate) {\n  static constexpr std::array kArray1 = {1, 2, 3};\n  static constexpr std::array kArray2 = {4, 5, 6};\n  static_assert(absl::c_inner_product(kArray1, kArray2, 1, std::multiplies<>(),\n                                      std::plus<>()) == 315);\n}\n\nTEST(ConstexprTest, AdjacentDifference) {\n  static constexpr std::array kArray = {1, 2, 4};\n  static constexpr auto kArrayAdjacentDifference = [] {\n    std::array<int, 3> array;\n    absl::c_adjacent_difference(kArray, array.begin());\n    return array;\n  }();\n  static_assert(kArrayAdjacentDifference == std::array{1, 1, 2});\n}\n\nTEST(ConstexprTest, AdjacentDifferenceWithPredicate) {\n  static constexpr std::array kArray = {1, 2, 4};\n  static constexpr auto kArrayAdjacentDifference = [] {\n    std::array<int, 3> array;\n    absl::c_adjacent_difference(kArray, array.begin(), std::multiplies<>());\n    return array;\n  }();\n  static_assert(kArrayAdjacentDifference == std::array{1, 2, 8});\n}\n\nTEST(ConstexprTest, PartialSum) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayPartialSum = [] {\n    std::array<int, 3> array;\n    absl::c_partial_sum(kArray, array.begin());\n    return array;\n  }();\n  static_assert(kArrayPartialSum == std::array{1, 3, 6});\n}\n\nTEST(ConstexprTest, PartialSumWithPredicate) {\n  static constexpr std::array kArray = {1, 2, 3};\n  static constexpr auto kArrayPartialSum = [] {\n    std::array<int, 3> array;\n    absl::c_partial_sum(kArray, array.begin(), std::multiplies<>());\n    return array;\n  }();\n  static_assert(kArrayPartialSum == std::array{1, 2, 6});\n}\n\n#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&\n        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"atomic_hook\",\n    hdrs = [\"internal/atomic_hook.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":config\",\n        \":core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"errno_saver\",\n    hdrs = [\"internal/errno_saver.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\":config\"],\n)\n\ncc_library(\n    name = \"hardening\",\n    srcs = [\n        \"internal/hardening.cc\",\n    ],\n    hdrs = [\n        \"internal/hardening.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":config\",\n        \":core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"log_severity\",\n    srcs = [\"log_severity.cc\"],\n    hdrs = [\"log_severity.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"no_destructor\",\n    hdrs = [\"no_destructor.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":nullability\",\n    ],\n)\n\ncc_library(\n    name = \"nullability\",\n    hdrs = [\"nullability.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\":config\"],\n)\n\ncc_library(\n    name = \"nullability_traits_internal\",\n    hdrs = [\"internal/nullability_traits.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":config\",\n        \":nullability\",\n    ],\n)\n\ncc_library(\n    name = \"raw_logging_internal\",\n    srcs = [\"internal/raw_logging.cc\"],\n    hdrs = [\"internal/raw_logging.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":atomic_hook\",\n        \":config\",\n        \":core_headers\",\n        \":errno_saver\",\n        \":log_severity\",\n    ],\n)\n\ncc_library(\n    name = \"spinlock_wait\",\n    srcs = [\n        \"internal/spinlock_akaros.inc\",\n        \"internal/spinlock_linux.inc\",\n        \"internal/spinlock_posix.inc\",\n        \"internal/spinlock_wait.cc\",\n        \"internal/spinlock_win32.inc\",\n    ],\n    hdrs = [\"internal/spinlock_wait.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/base:__pkg__\",\n    ],\n    deps = [\n        \":base_internal\",\n        \":core_headers\",\n        \":errno_saver\",\n    ],\n)\n\ncc_library(\n    name = \"config\",\n    hdrs = [\n        \"config.h\",\n        \"options.h\",\n        \"policy_checks.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n)\n\ncc_library(\n    name = \"cycleclock_internal\",\n    hdrs = [\n        \"internal/cycleclock_config.h\",\n        \"internal/unscaledcycleclock_config.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":base_internal\",\n        \":config\",\n    ],\n)\n\ncc_library(\n    name = \"dynamic_annotations\",\n    srcs = [\n        \"internal/dynamic_annotations.h\",\n    ],\n    hdrs = [\n        \"dynamic_annotations.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"core_headers\",\n    hdrs = [\n        \"attributes.h\",\n        \"const_init.h\",\n        \"macros.h\",\n        \"optimization.h\",\n        \"port.h\",\n        \"thread_annotations.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n    ],\n)\n\ncc_library(\n    name = \"malloc_internal\",\n    srcs = [\n        \"internal/low_level_alloc.cc\",\n    ],\n    hdrs = [\n        \"internal/direct_mmap.h\",\n        \"internal/low_level_alloc.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS + select({\n        \"//conditions:default\": [],\n    }),\n    linkopts = select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"@rules_cc//cc/compiler:clang-cl\": [],\n        \"@rules_cc//cc/compiler:emscripten\": [],\n        \"//conditions:default\": [\"-pthread\"],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//visibility:public\",\n    ],\n    deps = [\n        \":base\",\n        \":base_internal\",\n        \":config\",\n        \":core_headers\",\n        \":dynamic_annotations\",\n        \":raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"base_internal\",\n    hdrs = [\n        \"internal/hide_ptr.h\",\n        \"internal/scheduling_mode.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":config\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"base\",\n    srcs = [\n        \"casts.cc\",\n        \"internal/cycleclock.cc\",\n        \"internal/spinlock.cc\",\n        \"internal/sysinfo.cc\",\n        \"internal/thread_identity.cc\",\n        \"internal/unscaledcycleclock.cc\",\n    ],\n    hdrs = [\n        \"call_once.h\",\n        \"casts.h\",\n        \"internal/cycleclock.h\",\n        \"internal/low_level_scheduling.h\",\n        \"internal/per_thread_tls.h\",\n        \"internal/spinlock.h\",\n        \"internal/sysinfo.h\",\n        \"internal/thread_identity.h\",\n        \"internal/tsan_mutex_interface.h\",\n        \"internal/unscaledcycleclock.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [\n            \"-DEFAULTLIB:advapi32.lib\",\n        ],\n        \"@rules_cc//cc/compiler:clang-cl\": [\n            \"-DEFAULTLIB:advapi32.lib\",\n        ],\n        \"//absl:mingw_compiler\": [\n            \"-DEFAULTLIB:advapi32.lib\",\n            \"-ladvapi32\",\n        ],\n        \"@rules_cc//cc/compiler:emscripten\": [],\n        \"//conditions:default\": [\"-pthread\"],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":atomic_hook\",\n        \":base_internal\",\n        \":config\",\n        \":core_headers\",\n        \":cycleclock_internal\",\n        \":nullability\",\n        \":raw_logging_internal\",\n        \":spinlock_wait\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"atomic_hook_test_helper\",\n    testonly = True,\n    srcs = [\"internal/atomic_hook_test_helper.cc\"],\n    hdrs = [\"internal/atomic_hook_test_helper.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":atomic_hook\",\n        \":core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"atomic_hook_test\",\n    size = \"small\",\n    srcs = [\"internal/atomic_hook_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":atomic_hook\",\n        \":atomic_hook_test_helper\",\n        \":core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"bit_cast_test\",\n    size = \"small\",\n    srcs = [\n        \"bit_cast_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":base\",\n        \":core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"attributes_test\",\n    srcs = [\n        \"attributes_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"c_header_test\",\n    srcs = [\"c_header_test.c\"],\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":config\",\n        \":core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"throw_delegate\",\n    srcs = [\n        \"throw_delegate.cc\",\n    ],\n    hdrs = [\n        \"throw_delegate.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":raw_logging_internal\",\n    ],\n)\n\ncc_test(\n    name = \"throw_delegate_test\",\n    srcs = [\"throw_delegate_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":throw_delegate\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"errno_saver_test\",\n    size = \"small\",\n    srcs = [\"internal/errno_saver_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":errno_saver\",\n        \":strerror\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"exception_testing\",\n    testonly = True,\n    hdrs = [\"internal/exception_testing.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":config\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"pretty_function\",\n    hdrs = [\"internal/pretty_function.h\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n)\n\ncc_library(\n    name = \"exception_safety_testing\",\n    testonly = True,\n    srcs = [\"internal/exception_safety_testing.cc\"],\n    hdrs = [\"internal/exception_safety_testing.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":pretty_function\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"exception_safety_testing_test\",\n    srcs = [\"exception_safety_testing_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":exception_safety_testing\",\n        \"//absl/memory\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\n# Common test library made available for use in non-absl code that overrides\n# AbslInternalSpinLockDelay and AbslInternalSpinLockWake.\ncc_library(\n    name = \"spinlock_test_common\",\n    testonly = True,\n    srcs = [\"spinlock_test_common.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":base\",\n        \":base_internal\",\n        \":config\",\n        \":core_headers\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n    ],\n    alwayslink = 1,\n)\n\ncc_test(\n    name = \"spinlock_test\",\n    size = \"medium\",\n    srcs = [\"spinlock_test_common.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":base\",\n        \":base_internal\",\n        \":config\",\n        \":core_headers\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"spinlock_benchmark_common\",\n    testonly = True,\n    srcs = [\"internal/spinlock_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/base:__pkg__\",\n    ],\n    deps = [\n        \":base\",\n        \":base_internal\",\n        \":no_destructor\",\n        \":raw_logging_internal\",\n        \"//absl/synchronization\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n    alwayslink = 1,\n)\n\ncc_binary(\n    name = \"spinlock_benchmark\",\n    testonly = True,\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":spinlock_benchmark_common\",\n    ],\n)\n\ncc_library(\n    name = \"endian\",\n    hdrs = [\n        \"internal/endian.h\",\n        \"internal/unaligned_access.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":base\",\n        \":config\",\n        \":core_headers\",\n        \":nullability\",\n    ],\n)\n\ncc_test(\n    name = \"endian_test\",\n    srcs = [\"internal/endian_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":config\",\n        \":endian\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"config_test\",\n    srcs = [\"config_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \"//absl/synchronization:thread_pool\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"call_once_test\",\n    srcs = [\"call_once_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":base\",\n        \":core_headers\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"casts_test\",\n    size = \"small\",\n    srcs = [\n        \"casts_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":base\",\n        \":config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"hardening_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/hardening_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":hardening\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"no_destructor_test\",\n    srcs = [\"no_destructor_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":no_destructor\",\n        \":raw_logging_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"no_destructor_benchmark\",\n    testonly = True,\n    srcs = [\"no_destructor_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":no_destructor\",\n        \":raw_logging_internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"nullability_test\",\n    srcs = [\"nullability_test.cc\"],\n    deps = [\n        \":nullability\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"nullability_default_nonnull_test\",\n    srcs = [\"nullability_default_nonnull_test.cc\"],\n    deps = [\n        \":nullability\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"nullability_traits_test\",\n    srcs = [\"internal/nullability_traits_test.cc\"],\n    deps = [\n        \":config\",\n        \":nullability\",\n        \":nullability_traits_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"raw_logging_test\",\n    srcs = [\"raw_logging_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":raw_logging_internal\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"sysinfo_test\",\n    size = \"small\",\n    srcs = [\"internal/sysinfo_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":base\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"low_level_alloc_test\",\n    size = \"medium\",\n    srcs = [\"internal/low_level_alloc_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_ios_x86_64\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":malloc_internal\",\n        \"//absl/container:node_hash_map\",\n    ],\n)\n\ncc_test(\n    name = \"thread_identity_test\",\n    srcs = [\"internal/thread_identity_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":base\",\n        \":core_headers\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"thread_identity_benchmark\",\n    testonly = True,\n    srcs = [\"internal/thread_identity_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":base\",\n        \"//absl/synchronization\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"scoped_set_env\",\n    testonly = True,\n    srcs = [\"internal/scoped_set_env.cc\"],\n    hdrs = [\"internal/scoped_set_env.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":config\",\n        \":raw_logging_internal\",\n    ],\n)\n\ncc_test(\n    name = \"scoped_set_env_test\",\n    size = \"small\",\n    srcs = [\"internal/scoped_set_env_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":scoped_set_env\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_severity_test\",\n    size = \"small\",\n    srcs = [\"log_severity_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log_severity\",\n        \"//absl/flags:flag_internal\",\n        \"//absl/flags:marshalling\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"strerror\",\n    srcs = [\"internal/strerror.cc\"],\n    hdrs = [\"internal/strerror.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":config\",\n        \":core_headers\",\n        \":errno_saver\",\n    ],\n)\n\ncc_test(\n    name = \"strerror_test\",\n    size = \"small\",\n    srcs = [\"internal/strerror_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":strerror\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"strerror_benchmark\",\n    testonly = True,\n    srcs = [\"internal/strerror_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strerror\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"fast_type_id\",\n    hdrs = [\"fast_type_id.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n    ],\n)\n\ncc_test(\n    name = \"fast_type_id_test\",\n    size = \"small\",\n    srcs = [\"fast_type_id_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":core_headers\",\n        \":fast_type_id\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"prefetch\",\n    hdrs = [\n        \"prefetch.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"prefetch_test\",\n    size = \"small\",\n    srcs = [\n        \"prefetch_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":prefetch\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"poison\",\n    srcs = [\n        \"internal/poison.cc\",\n    ],\n    hdrs = [\"internal/poison.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":config\",\n        \":core_headers\",\n        \":malloc_internal\",\n    ],\n)\n\ncc_test(\n    name = \"poison_test\",\n    size = \"small\",\n    timeout = \"short\",\n    srcs = [\n        \"internal/poison_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":poison\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"unique_small_name_test\",\n    size = \"small\",\n    srcs = [\"internal/unique_small_name_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    linkstatic = 1,\n    deps = [\n        \":core_headers\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"optimization_test\",\n    size = \"small\",\n    srcs = [\"optimization_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"iterator_traits_internal\",\n    hdrs = [\"internal/iterator_traits.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":config\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"iterator_traits_test\",\n    srcs = [\"internal/iterator_traits_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":iterator_traits_internal\",\n        \":iterator_traits_test_helper\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"tracing_internal\",\n    srcs = [\"internal/tracing.cc\"],\n    hdrs = [\"internal/tracing.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"iterator_traits_test_helper\",\n    hdrs = [\"internal/iterator_traits_test_helper.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\":config\"],\n)\n\ncc_test(\n    name = \"tracing_internal_weak_test\",\n    srcs = [\"internal/tracing_weak_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":tracing_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"tracing_internal_strong_test\",\n    srcs = [\"internal/tracing_strong_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":core_headers\",\n        \":tracing_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/base/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nfind_library(LIBRT rt)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    atomic_hook\n  HDRS\n    \"internal/atomic_hook.h\"\n  DEPS\n    absl::config\n    absl::core_headers\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    errno_saver\n  HDRS\n    \"internal/errno_saver.h\"\n  DEPS\n    absl::config\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\nabsl_cc_library(\n  NAME\n    hardening\n  HDRS\n    \"internal/hardening.h\"\n  SRCS\n    \"internal/hardening.cc\"\n  DEPS\n    absl::config\n    absl::core_headers\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\nabsl_cc_library(\n  NAME\n    log_severity\n  HDRS\n    \"log_severity.h\"\n  SRCS\n    \"log_severity.cc\"\n  DEPS\n    absl::config\n    absl::core_headers\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\nabsl_cc_library(\n  NAME\n    no_destructor\n  HDRS\n    \"no_destructor.h\"\n  DEPS\n    absl::config\n    absl::nullability\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\nabsl_cc_library(\n  NAME\n    nullability\n  HDRS\n    \"nullability.h\"\n  DEPS\n    absl::config\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\nabsl_cc_test(\n  NAME\n    nullability_test\n  SRCS\n    \"nullability_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::nullability\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    nullability_default_nonnull_test\n  SRCS\n    \"nullability_default_nonnull_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::nullability\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    nullability_traits_internal\n  HDRS\n    \"internal/nullability_traits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::nullability\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    nullability_traits_test\n  SRCS\n    \"internal/nullability_traits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::nullability\n    absl::nullability_traits_internal\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    raw_logging_internal\n  HDRS\n    \"internal/raw_logging.h\"\n  SRCS\n    \"internal/raw_logging.cc\"\n  DEPS\n    absl::atomic_hook\n    absl::config\n    absl::core_headers\n    absl::errno_saver\n    absl::log_severity\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    spinlock_wait\n  HDRS\n    \"internal/spinlock_wait.h\"\n  SRCS\n    \"internal/spinlock_akaros.inc\"\n    \"internal/spinlock_linux.inc\"\n    \"internal/spinlock_posix.inc\"\n    \"internal/spinlock_wait.cc\"\n    \"internal/spinlock_win32.inc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base_internal\n    absl::core_headers\n    absl::errno_saver\n)\n\nabsl_cc_library(\n  NAME\n    config\n  HDRS\n    \"config.h\"\n    \"options.h\"\n    \"policy_checks.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    dynamic_annotations\n  HDRS\n    \"dynamic_annotations.h\"\n  SRCS\n    \"internal/dynamic_annotations.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    core_headers\n  HDRS\n    \"attributes.h\"\n    \"const_init.h\"\n    \"macros.h\"\n    \"optimization.h\"\n    \"port.h\"\n    \"thread_annotations.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    malloc_internal\n  HDRS\n    \"internal/direct_mmap.h\"\n    \"internal/low_level_alloc.h\"\n  SRCS\n    \"internal/low_level_alloc.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::base_internal\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::raw_logging_internal\n    Threads::Threads\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    base_internal\n  HDRS\n    \"internal/hide_ptr.h\"\n    \"internal/scheduling_mode.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::type_traits\n)\n\nabsl_cc_library(\n  NAME\n    base\n  HDRS\n    \"call_once.h\"\n    \"casts.h\"\n    \"internal/cycleclock.h\"\n    \"internal/cycleclock_config.h\"\n    \"internal/low_level_scheduling.h\"\n    \"internal/per_thread_tls.h\"\n    \"internal/spinlock.h\"\n    \"internal/sysinfo.h\"\n    \"internal/thread_identity.h\"\n    \"internal/tsan_mutex_interface.h\"\n    \"internal/unscaledcycleclock.h\"\n    \"internal/unscaledcycleclock_config.h\"\n  SRCS\n    \"casts.cc\"\n    \"internal/cycleclock.cc\"\n    \"internal/spinlock.cc\"\n    \"internal/sysinfo.cc\"\n    \"internal/thread_identity.cc\"\n    \"internal/unscaledcycleclock.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n    $<$<BOOL:${LIBRT}>:-lrt>\n    $<$<BOOL:${MINGW}>:-ladvapi32>\n  DEPS\n    absl::atomic_hook\n    absl::base_internal\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::log_severity\n    absl::nullability\n    absl::raw_logging_internal\n    absl::spinlock_wait\n    absl::type_traits\n    Threads::Threads\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    throw_delegate\n  HDRS\n    \"throw_delegate.h\"\n  SRCS\n    \"throw_delegate.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::raw_logging_internal\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    exception_testing\n  HDRS\n    \"internal/exception_testing.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    GTest::gtest\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    pretty_function\n  HDRS\n    \"internal/pretty_function.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    exception_safety_testing\n  HDRS\n    \"internal/exception_safety_testing.h\"\n  SRCS\n    \"internal/exception_safety_testing.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::pretty_function\n    absl::memory\n    absl::meta\n    absl::strings\n    absl::utility\n    GTest::gtest\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    absl_exception_safety_testing_test\n  SRCS\n    \"exception_safety_testing_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::exception_safety_testing\n    absl::memory\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    atomic_hook_test_helper\n  SRCS\n    \"internal/atomic_hook_test_helper.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::atomic_hook\n    absl::core_headers\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    atomic_hook_test\n  SRCS\n    \"internal/atomic_hook_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::atomic_hook_test_helper\n    absl::atomic_hook\n    absl::core_headers\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    attributes_test\n  SRCS\n    \"attributes_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    hardening_test\n  SRCS\n    \"internal/hardening_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hardening\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    bit_cast_test\n  SRCS\n    \"bit_cast_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::core_headers\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    casts_test\n  SRCS\n    \"casts_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::core_headers\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    errno_saver_test\n  SRCS\n    \"internal/errno_saver_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::errno_saver\n    absl::strerror\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    throw_delegate_test\n  SRCS\n    \"throw_delegate_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::throw_delegate\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    spinlock_test_common\n  SRCS\n    \"spinlock_test_common.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::base_internal\n    absl::core_headers\n    absl::synchronization\n    GTest::gtest\n  TESTONLY\n)\n\n# On bazel BUILD this target use \"alwayslink = 1\" which is not implemented here\nabsl_cc_test(\n  NAME\n    spinlock_test\n  SRCS\n    \"spinlock_test_common.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::base_internal\n    absl::config\n    absl::core_headers\n    absl::synchronization\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    endian\n  HDRS\n    \"internal/endian.h\"\n    \"internal/unaligned_access.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::nullability\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    endian_test\n  SRCS\n    \"internal/endian_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::endian\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    config_test\n  SRCS\n    \"config_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::synchronization\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    call_once_test\n  SRCS\n    \"call_once_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::core_headers\n    absl::synchronization\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    no_destructor_test\n  SRCS\n    \"no_destructor_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::no_destructor\n    absl::config\n    absl::raw_logging_internal\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    raw_logging_test\n  SRCS\n    \"raw_logging_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::raw_logging_internal\n    absl::strings\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    sysinfo_test\n  SRCS\n    \"internal/sysinfo_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::synchronization\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    low_level_alloc_test\n  SRCS\n    \"internal/low_level_alloc_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::malloc_internal\n    absl::node_hash_map\n    Threads::Threads\n)\n\nabsl_cc_test(\n  NAME\n    thread_identity_test\n  SRCS\n    \"internal/thread_identity_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::core_headers\n    absl::synchronization\n    Threads::Threads\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    scoped_set_env\n  SRCS\n    \"internal/scoped_set_env.cc\"\n  HDRS\n    \"internal/scoped_set_env.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::raw_logging_internal\n)\n\nabsl_cc_test(\n  NAME\n    scoped_set_env_test\n  SRCS\n    \"internal/scoped_set_env_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::scoped_set_env\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    cmake_thread_test\n  SRCS\n    \"internal/cmake_thread_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n)\n\nabsl_cc_test(\n  NAME\n    log_severity_test\n  SRCS\n    \"log_severity_test.cc\"\n  DEPS\n    absl::flags_internal\n    absl::flags_marshalling\n    absl::log_severity\n    absl::strings\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    strerror\n  SRCS\n    \"internal/strerror.cc\"\n  HDRS\n    \"internal/strerror.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::errno_saver\n)\n\nabsl_cc_test(\n  NAME\n    strerror_test\n  SRCS\n    \"internal/strerror_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strerror\n    absl::strings\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_library(\n  NAME\n    fast_type_id\n  HDRS\n    \"fast_type_id.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    fast_type_id_test\n  SRCS\n    \"fast_type_id_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::core_headers\n    absl::fast_type_id\n    GTest::gtest_main\n)\n\nabsl_cc_library(\n  NAME\n    prefetch\n  HDRS\n    \"prefetch.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n)\n\nabsl_cc_test(\n  NAME\n    prefetch_test\n  SRCS\n    \"prefetch_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::prefetch\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    optimization_test\n  SRCS\n    \"optimization_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::core_headers\n    GTest::gtest_main\n)\n\nabsl_cc_library(\n  NAME\n    poison\n  SRCS\n    \"internal/poison.cc\"\n  HDRS\n    \"internal/poison.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::malloc_internal\n)\n\nabsl_cc_test(\n  NAME\n    poison_test\n  SRCS\n    \"internal/poison_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::poison\n    GTest::gtest_main\n)\n\nabsl_cc_library(\n  NAME\n    tracing_internal\n  HDRS\n    \"internal/tracing.h\"\n  SRCS\n    \"internal/tracing.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n)\n\nabsl_cc_test(\n  NAME\n    tracing_internal_weak_test\n  SRCS\n    \"internal/tracing_weak_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::tracing_internal\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    tracing_internal_strong_test\n  SRCS\n    \"internal/tracing_strong_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::tracing_internal\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    iterator_traits_internal\n  HDRS\n    \"internal/iterator_traits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    iterator_traits_test\n  SRCS\n    \"internal/iterator_traits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::iterator_traits_internal\n    absl::iterator_traits_test_helper_internal\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    iterator_traits_test_helper_internal\n  HDRS\n    \"internal/iterator_traits_test_helper.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n"
  },
  {
    "path": "absl/base/attributes.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This header file defines macros for declaring attributes for functions,\n// types, and variables.\n//\n// These macros are used within Abseil and allow the compiler to optimize, where\n// applicable, certain function calls.\n//\n// Most macros here are exposing GCC or Clang features, and are stubbed out for\n// other compilers.\n//\n// GCC attributes documentation:\n//   https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html\n//   https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html\n//   https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html\n//\n// Most attributes in this file are already supported by GCC 4.7. However, some\n// of them are not supported in older version of Clang. Thus, we check\n// `__has_attribute()` first. If the check fails, we check if we are on GCC and\n// assume the attribute exists on GCC (which is verified on GCC 4.7).\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_BASE_ATTRIBUTES_H_\n#define ABSL_BASE_ATTRIBUTES_H_\n\n#include \"absl/base/config.h\"\n\n// ABSL_HAVE_ATTRIBUTE\n//\n// A function-like feature checking macro that is a wrapper around\n// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a\n// nonzero constant integer if the attribute is supported or 0 if not.\n//\n// It evaluates to zero if `__has_attribute` is not defined by the compiler.\n//\n// GCC: https://gcc.gnu.org/gcc-5/changes.html\n// Clang: https://clang.llvm.org/docs/LanguageExtensions.html\n#ifdef __has_attribute\n#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)\n#else\n#define ABSL_HAVE_ATTRIBUTE(x) 0\n#endif\n\n// ABSL_HAVE_CPP_ATTRIBUTE\n//\n// A function-like feature checking macro that accepts C++11 style attributes.\n// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6\n// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't\n// find `__has_cpp_attribute`, will evaluate to 0.\n#if defined(__cplusplus) && defined(__has_cpp_attribute)\n// NOTE: requiring __cplusplus above should not be necessary, but\n// works around https://bugs.llvm.org/show_bug.cgi?id=23435.\n#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0\n#endif\n\n// -----------------------------------------------------------------------------\n// Function Attributes\n// -----------------------------------------------------------------------------\n//\n// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html\n// Clang: https://clang.llvm.org/docs/AttributeReference.html\n\n// ABSL_PRINTF_ATTRIBUTE\n// ABSL_SCANF_ATTRIBUTE\n//\n// Tells the compiler to perform `printf` format string checking if the\n// compiler supports it; see the 'format' attribute in\n// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.\n//\n// Note: As the GCC manual states, \"[s]ince non-static C++ methods\n// have an implicit 'this' argument, the arguments of such methods\n// should be counted from two, not one.\"\n#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \\\n  __attribute__((__format__(__printf__, string_index, first_to_check)))\n#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \\\n  __attribute__((__format__(__scanf__, string_index, first_to_check)))\n#else\n#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check)\n#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check)\n#endif\n\n// ABSL_ATTRIBUTE_ALWAYS_INLINE\n// ABSL_ATTRIBUTE_NOINLINE\n//\n// Forces functions to either inline or not inline. Introduced in gcc 3.1.\n#if ABSL_HAVE_ATTRIBUTE(always_inline) || \\\n    (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))\n#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1\n#else\n#define ABSL_ATTRIBUTE_ALWAYS_INLINE\n#endif\n\n#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline))\n#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1\n#else\n#define ABSL_ATTRIBUTE_NOINLINE\n#endif\n\n// ABSL_ATTRIBUTE_NO_TAIL_CALL\n//\n// Prevents the compiler from optimizing away stack frames for functions which\n// end in a call to another function.\n#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls)\n#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1\n#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls))\n#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__)\n#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1\n#define ABSL_ATTRIBUTE_NO_TAIL_CALL \\\n  __attribute__((optimize(\"no-optimize-sibling-calls\")))\n#else\n#define ABSL_ATTRIBUTE_NO_TAIL_CALL\n#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0\n#endif\n\n// ABSL_ATTRIBUTE_WEAK\n//\n// Tags a function as weak for the purposes of compilation and linking.\n// Weak attributes did not work properly in LLVM's Windows backend before\n// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598\n// for further information. Weak attributes do not work across DLL boundary.\n// The MinGW compiler doesn't complain about the weak attribute until the link\n// step, presumably because Windows doesn't use ELF binaries.\n#if (ABSL_HAVE_ATTRIBUTE(weak) ||                                 \\\n     (defined(__GNUC__) && !defined(__clang__))) &&               \\\n    (!defined(_WIN32) ||                                          \\\n     (defined(__clang__) && __clang_major__ >= 9 &&               \\\n      !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \\\n    !defined(__MINGW32__)\n#undef ABSL_ATTRIBUTE_WEAK\n#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))\n#define ABSL_HAVE_ATTRIBUTE_WEAK 1\n#else\n#define ABSL_ATTRIBUTE_WEAK\n#define ABSL_HAVE_ATTRIBUTE_WEAK 0\n#endif\n\n// ABSL_ATTRIBUTE_NONNULL\n//\n// Tells the compiler either (a) that a particular function parameter\n// should be a non-null pointer, or (b) that all pointer arguments should\n// be non-null.\n//\n// Note: As the GCC manual states, \"[s]ince non-static C++ methods\n// have an implicit 'this' argument, the arguments of such methods\n// should be counted from two, not one.\"\n//\n// Args are indexed starting at 1.\n//\n// For non-static class member functions, the implicit `this` argument\n// is arg 1, and the first explicit argument is arg 2. For static class member\n// functions, there is no implicit `this`, and the first explicit argument is\n// arg 1.\n//\n// Example:\n//\n//   /* arg_a cannot be null, but arg_b can */\n//   void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1);\n//\n//   class C {\n//     /* arg_a cannot be null, but arg_b can */\n//     void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2);\n//\n//     /* arg_a cannot be null, but arg_b can */\n//     static void StaticMethod(void* arg_a, void* arg_b)\n//     ABSL_ATTRIBUTE_NONNULL(1);\n//   };\n//\n// If no arguments are provided, then all pointer arguments should be non-null.\n//\n//  /* No pointer arguments may be null. */\n//  void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL();\n//\n// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but\n// ABSL_ATTRIBUTE_NONNULL does not.\n#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index)))\n#else\n#define ABSL_ATTRIBUTE_NONNULL(...)\n#endif\n\n// ABSL_ATTRIBUTE_NORETURN\n//\n// Tells the compiler that a given function never returns.\n//\n// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over\n// this macro.\n#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn))\n#elif defined(_MSC_VER)\n#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn)\n#else\n#define ABSL_ATTRIBUTE_NORETURN\n#endif\n\n// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS\n//\n// Tells the AddressSanitizer (or other memory testing tools) to ignore a given\n// function. Useful for cases when a function reads random locations on stack,\n// calls _exit from a cloned subprocess, deliberately accesses buffer\n// out of bounds or does other scary things with memory.\n// NOTE: GCC supports AddressSanitizer(asan) since 4.8.\n// https://gcc.gnu.org/gcc-4.8/changes.html\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \\\n    ABSL_HAVE_ATTRIBUTE(no_sanitize_address)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))\n#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \\\n    _MSC_VER >= 1928\n// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address\n#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address)\n#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize)\n// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU\n// features to detect similar bugs with less CPU and memory overhead.\n// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11.\n// https://gcc.gnu.org/gcc-11/changes.html\n#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \\\n  __attribute__((no_sanitize(\"hwaddress\")))\n#else\n#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS\n#endif\n\n// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY\n//\n// Tells the MemorySanitizer to relax the handling of a given function. All \"Use\n// of uninitialized value\" warnings from such functions will be suppressed, and\n// all values loaded from memory will be considered fully initialized.  This\n// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute\n// above, but deals with initialized-ness rather than addressability issues.\n// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.\n#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))\n#else\n#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY\n#endif\n\n// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD\n//\n// Tells the ThreadSanitizer to not instrument a given function.\n// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.\n// https://gcc.gnu.org/gcc-4.8/changes.html\n#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))\n#else\n#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD\n#endif\n\n// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED\n//\n// Tells the UndefinedSanitizer to ignore a given function. Useful for cases\n// where certain behavior (eg. division by zero) is being used intentionally.\n// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9.\n// https://gcc.gnu.org/gcc-4.9/changes.html\n#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \\\n  __attribute__((no_sanitize_undefined))\n#elif ABSL_HAVE_ATTRIBUTE(no_sanitize)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \\\n  __attribute__((no_sanitize(\"undefined\")))\n#else\n#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED\n#endif\n\n// ABSL_ATTRIBUTE_NO_SANITIZE_CFI\n//\n// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.\n// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.\n#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize(\"cfi\")))\n#else\n#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI\n#endif\n\n// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK\n//\n// Tells the SafeStack to not instrument a given function.\n// See https://clang.llvm.org/docs/SafeStack.html for details.\n#if ABSL_HAVE_ATTRIBUTE(no_sanitize)\n#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \\\n  __attribute__((no_sanitize(\"safe-stack\")))\n#else\n#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK\n#endif\n\n// ABSL_ATTRIBUTE_RETURNS_NONNULL\n//\n// Tells the compiler that a particular function never returns a null pointer.\n#if ABSL_HAVE_ATTRIBUTE(returns_nonnull)\n#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))\n#else\n#define ABSL_ATTRIBUTE_RETURNS_NONNULL\n#endif\n\n// ABSL_HAVE_ATTRIBUTE_SECTION\n//\n// Indicates whether labeled sections are supported. Weak symbol support is\n// a prerequisite. Labeled sections are not supported on Darwin/iOS.\n#ifdef ABSL_HAVE_ATTRIBUTE_SECTION\n#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set\n#elif (ABSL_HAVE_ATTRIBUTE(section) ||                \\\n       (defined(__GNUC__) && !defined(__clang__))) && \\\n    !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK\n#define ABSL_HAVE_ATTRIBUTE_SECTION 1\n\n// ABSL_ATTRIBUTE_SECTION\n//\n// Tells the compiler/linker to put a given function into a section and define\n// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.\n// This functionality is supported by GNU linker.  Any function annotated with\n// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into\n// whatever section its caller is placed into.\n//\n#ifndef ABSL_ATTRIBUTE_SECTION\n#define ABSL_ATTRIBUTE_SECTION(name) \\\n  __attribute__((section(#name))) __attribute__((noinline))\n#endif\n\n// ABSL_ATTRIBUTE_SECTION_VARIABLE\n//\n// Tells the compiler/linker to put a given variable into a section and define\n// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.\n// This functionality is supported by GNU linker.\n#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE\n#ifdef _AIX\n// __attribute__((section(#name))) on AIX is achieved by using the `.csect`\n// pseudo op which includes an additional integer as part of its syntax\n// indicating alignment. If data fall under different alignments then you might\n// get a compilation error indicating a `Section type conflict`.\n#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)\n#else\n#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))\n#endif\n#endif\n\n// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS\n//\n// A weak section declaration to be used as a global declaration\n// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link\n// even without functions with ABSL_ATTRIBUTE_SECTION(name).\n// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's\n// a no-op on ELF but not on Mach-O.\n//\n#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS\n#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name)   \\\n  extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \\\n  extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK\n#endif\n#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS\n#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name)\n#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name)\n#endif\n\n// ABSL_ATTRIBUTE_SECTION_START\n//\n// Returns `void*` pointers to start/end of a section of code with\n// functions having ABSL_ATTRIBUTE_SECTION(name).\n// Returns 0 if no such functions exist.\n// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and\n// link.\n//\n#define ABSL_ATTRIBUTE_SECTION_START(name) \\\n  (reinterpret_cast<void *>(__start_##name))\n#define ABSL_ATTRIBUTE_SECTION_STOP(name) \\\n  (reinterpret_cast<void *>(__stop_##name))\n\n#else  // !ABSL_HAVE_ATTRIBUTE_SECTION\n\n#define ABSL_HAVE_ATTRIBUTE_SECTION 0\n\n// provide dummy definitions\n#define ABSL_ATTRIBUTE_SECTION(name)\n#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)\n#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name)\n#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name)\n#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name)\n#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void *>(0))\n#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(0))\n\n#endif  // ABSL_ATTRIBUTE_SECTION\n\n// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC\n//\n// Support for aligning the stack on 32-bit x86.\n#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \\\n    (defined(__GNUC__) && !defined(__clang__))\n#if defined(__i386__)\n#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \\\n  __attribute__((force_align_arg_pointer))\n#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)\n#elif defined(__x86_64__)\n#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1)\n#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC\n#else  // !__i386__ && !__x86_64\n#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)\n#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC\n#endif  // __i386__\n#else\n#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC\n#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)\n#endif\n\n// ABSL_MUST_USE_RESULT\n//\n// Tells the compiler to warn about unused results.\n//\n// For code or headers that are assured to only build with C++17 and up, prefer\n// just using the standard `[[nodiscard]]` directly over this macro.\n//\n// When annotating a function, it must appear as the first part of the\n// declaration or definition. The compiler will warn if the return value from\n// such a function is unused:\n//\n//   ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket();\n//   AllocateSprocket();  // Triggers a warning.\n//\n// When annotating a class, it is equivalent to annotating every function which\n// returns an instance.\n//\n//   class ABSL_MUST_USE_RESULT Sprocket {};\n//   Sprocket();  // Triggers a warning.\n//\n//   Sprocket MakeSprocket();\n//   MakeSprocket();  // Triggers a warning.\n//\n// Note that references and pointers are not instances:\n//\n//   Sprocket* SprocketPointer();\n//   SprocketPointer();  // Does *not* trigger a warning.\n//\n// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result\n// warning. For that, warn_unused_result is used only for clang but not for gcc.\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425\n//\n// Note: past advice was to place the macro after the argument list.\n//\n// TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is\n// compliant with the stricter [[nodiscard]].\n#if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result)\n#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result))\n#else\n#define ABSL_MUST_USE_RESULT\n#endif\n\n// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD\n//\n// Tells GCC that a function is hot or cold. GCC can use this information to\n// improve static analysis, i.e. a conditional branch to a cold function\n// is likely to be not-taken.\n// This annotation is used for function declarations.\n//\n// Example:\n//\n//   int foo() ABSL_ATTRIBUTE_HOT;\n#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_HOT __attribute__((hot))\n#else\n#define ABSL_ATTRIBUTE_HOT\n#endif\n\n#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_COLD __attribute__((cold))\n#else\n#define ABSL_ATTRIBUTE_COLD\n#endif\n\n// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS\n//\n// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT\n// macro used as an attribute to mark functions that must always or never be\n// instrumented by XRay. Currently, this is only supported in Clang/LLVM.\n//\n// For reference on the LLVM XRay instrumentation, see\n// http://llvm.org/docs/XRay.html.\n//\n// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration\n// will always get the XRay instrumentation sleds. These sleds may introduce\n// some binary size and runtime overhead and must be used sparingly.\n//\n// These attributes only take effect when the following conditions are met:\n//\n//   * The file/target is built in at least C++11 mode, with a Clang compiler\n//     that supports XRay attributes.\n//   * The file/target is built with the -fxray-instrument flag set for the\n//     Clang/LLVM compiler.\n//   * The function is defined in the translation unit (the compiler honors the\n//     attribute in either the definition or the declaration, and must match).\n//\n// There are cases when, even when building with XRay instrumentation, users\n// might want to control specifically which functions are instrumented for a\n// particular build using special-case lists provided to the compiler. These\n// special case lists are provided to Clang via the\n// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The\n// attributes in source take precedence over these special-case lists.\n//\n// To disable the XRay attributes at build-time, users may define\n// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific\n// packages/targets, as this may lead to conflicting definitions of functions at\n// link-time.\n//\n// XRay isn't currently supported on Android:\n// https://github.com/android/ndk/issues/368\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \\\n    !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__)\n#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]\n#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)\n#define ABSL_XRAY_LOG_ARGS(N) \\\n  [[clang::xray_always_instrument, clang::xray_log_args(N)]]\n#else\n#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]]\n#endif\n#else\n#define ABSL_XRAY_ALWAYS_INSTRUMENT\n#define ABSL_XRAY_NEVER_INSTRUMENT\n#define ABSL_XRAY_LOG_ARGS(N)\n#endif\n\n// ABSL_ATTRIBUTE_REINITIALIZES\n//\n// Indicates that a member function reinitializes the entire object to a known\n// state, independent of the previous state of the object.\n//\n// The clang-tidy check bugprone-use-after-move allows member functions marked\n// with this attribute to be called on objects that have been moved from;\n// without the attribute, this would result in a use-after-move warning.\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes)\n#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]\n#else\n#define ABSL_ATTRIBUTE_REINITIALIZES\n#endif\n\n// -----------------------------------------------------------------------------\n// Variable Attributes\n// -----------------------------------------------------------------------------\n\n// ABSL_ATTRIBUTE_UNUSED\n//\n// Prevents the compiler from complaining about variables that appear unused.\n//\n// Deprecated: Use the standard C++17 `[[maybe_unused]]` instead.\n//\n// Due to differences in positioning requirements between the old, compiler\n// specific __attribute__ syntax and the now standard `[[maybe_unused]]`, this\n// macro does not attempt to take advantage of `[[maybe_unused]]`.\n#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))\n#undef ABSL_ATTRIBUTE_UNUSED\n#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))\n#else\n#define ABSL_ATTRIBUTE_UNUSED\n#endif\n\n// ABSL_ATTRIBUTE_INITIAL_EXEC\n//\n// Tells the compiler to use \"initial-exec\" mode for a thread-local variable.\n// See http://people.redhat.com/drepper/tls.pdf for the gory details.\n#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model(\"initial-exec\")))\n#else\n#define ABSL_ATTRIBUTE_INITIAL_EXEC\n#endif\n\n// ABSL_ATTRIBUTE_PACKED\n//\n// Instructs the compiler not to use natural alignment for a tagged data\n// structure, but instead to reduce its alignment to 1.\n//\n// Use of this attribute is HIGHLY DISCOURAGED. Taking the address of or\n// binding a reference to any unaligned member is UB, and it is very easy to\n// do so unintentionally when passing such members as function arguments.\n//\n// DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing\n// so can cause atomic variables to be mis-aligned and silently violate\n// atomicity on x86.\n//\n// This attribute can either be applied to members of a structure or to a\n// structure in its entirety. Applying this attribute (judiciously) to a\n// structure in its entirety to optimize the memory footprint of very\n// commonly-used structs is fine. Do not apply this attribute to a structure in\n// its entirety if the purpose is to control the offsets of the members in the\n// structure. Instead, apply this attribute only to structure members that need\n// it.\n//\n// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the\n// natural alignment of structure members not annotated is preserved. Aligned\n// member accesses are faster than non-aligned member accesses even if the\n// targeted microprocessor supports non-aligned accesses.\n#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))\n#else\n#define ABSL_ATTRIBUTE_PACKED\n#endif\n\n// ABSL_ATTRIBUTE_FUNC_ALIGN\n//\n// Tells the compiler to align the function start at least to certain\n// alignment boundary\n#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes)))\n#else\n#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes)\n#endif\n\n// ABSL_FALLTHROUGH_INTENDED\n//\n// Annotates implicit fall-through between switch labels, allowing a case to\n// indicate intentional fallthrough and turn off warnings about any lack of a\n// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by\n// a semicolon and can be used in most places where `break` can, provided that\n// no statements exist between it and the next switch label.\n//\n// Example:\n//\n//  switch (x) {\n//    case 40:\n//    case 41:\n//      if (truth_is_out_there) {\n//        ++x;\n//        ABSL_FALLTHROUGH_INTENDED;  // Use instead of/along with annotations\n//                                    // in comments\n//      } else {\n//        return x;\n//      }\n//    case 42:\n//      ...\n//\n// Notes: When supported, GCC and Clang can issue a warning on switch labels\n// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See\n// clang documentation on language extensions for details:\n// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough\n//\n// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has\n// no effect on diagnostics. In any case this macro has no effect on runtime\n// behavior and performance of code.\n\n#ifdef ABSL_FALLTHROUGH_INTENDED\n#error \"ABSL_FALLTHROUGH_INTENDED should not be defined.\"\n#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough)\n#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]]\n#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough)\n#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]\n#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough)\n#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]\n#else\n#define ABSL_FALLTHROUGH_INTENDED \\\n  do {                            \\\n  } while (0)\n#endif\n\n// ABSL_DEPRECATED()\n//\n// Marks a deprecated class, struct, enum, function, method and variable\n// declarations. The macro argument is used as a custom diagnostic message (e.g.\n// suggestion of a better alternative).\n//\n// For code or headers that are assured to only build with C++14 and up, prefer\n// just using the standard `[[deprecated(\"message\")]]` directly over this macro.\n//\n// Examples:\n//\n//   class ABSL_DEPRECATED(\"Use Bar instead\") Foo {...};\n//\n//   ABSL_DEPRECATED(\"Use Baz() instead\") void Bar() {...}\n//\n//   template <typename T>\n//   ABSL_DEPRECATED(\"Use DoThat() instead\")\n//   void DoThis();\n//\n//   enum FooEnum {\n//     kBar ABSL_DEPRECATED(\"Use kBaz instead\"),\n//   };\n//\n// Every usage of a deprecated entity will trigger a warning when compiled with\n// GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain\n// turns this warning off by default, instead relying on clang-tidy to report\n// new uses of deprecated code.\n#if ABSL_HAVE_ATTRIBUTE(deprecated)\n#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))\n#else\n#define ABSL_DEPRECATED(message)\n#endif\n\n// When deprecating Abseil code, it is sometimes necessary to turn off the\n// warning within Abseil, until the deprecated code is actually removed. The\n// deprecated code can be surrounded with these directives to achieve that\n// result.\n//\n// class ABSL_DEPRECATED(\"Use Bar instead\") Foo;\n//\n// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\n// Baz ComputeBazFromFoo(Foo f);\n// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n#if defined(__GNUC__) || defined(__clang__)\n// Clang also supports these GCC pragmas.\n#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \\\n  _Pragma(\"GCC diagnostic push\")             \\\n  _Pragma(\"GCC diagnostic ignored \\\"-Wdeprecated-declarations\\\"\")\n#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \\\n  _Pragma(\"GCC diagnostic pop\")\n#elif defined(_MSC_VER)\n#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \\\n  _Pragma(\"warning(push)\") _Pragma(\"warning(disable: 4996)\")\n#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \\\n  _Pragma(\"warning(pop)\")\n#else\n#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\n#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n#endif  // defined(__GNUC__) || defined(__clang__)\n\n// ABSL_REQUIRE_EXPLICIT_INIT\n//\n// ABSL_REQUIRE_EXPLICIT_INIT is placed *after* the data members of an aggregate\n// type to indicate that the annotated member must be explicitly initialized by\n// the user whenever the aggregate is constructed. For example:\n//\n//   struct Coord {\n//     int x ABSL_REQUIRE_EXPLICIT_INIT;\n//     int y ABSL_REQUIRE_EXPLICIT_INIT;\n//   };\n//   Coord coord = {1};  // warning: field 'y' is not explicitly initialized\n//\n// Note that usage on C arrays is not supported in C++.\n// Use a struct (such as std::array) to wrap the array member instead.\n//\n// Avoid applying this attribute to the members of non-aggregate types.\n// The behavior within non-aggregates is unspecified and subject to change.\n//\n// Do NOT attempt to suppress or demote the error generated by this attribute.\n// Just like with a missing function argument, it is a hard error by design.\n//\n// See the upstream documentation for more details:\n// https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization\n#ifdef __cplusplus\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_explicit_initialization)\n// clang-format off\n#define ABSL_REQUIRE_EXPLICIT_INIT \\\n  [[clang::require_explicit_initialization]] = \\\n    AbslInternal_YouForgotToExplicitlyInitializeAField::v\n#else\n#define ABSL_REQUIRE_EXPLICIT_INIT \\\n  = AbslInternal_YouForgotToExplicitlyInitializeAField::v\n#endif\n// clang-format on\n#else\n// clang-format off\n#if ABSL_HAVE_ATTRIBUTE(require_explicit_initialization)\n#define ABSL_REQUIRE_EXPLICIT_INIT \\\n  __attribute__((require_explicit_initialization))\n#else\n#define ABSL_REQUIRE_EXPLICIT_INIT \\\n  /* No portable fallback for C is available */\n#endif\n// clang-format on\n#endif\n\n#ifdef __cplusplus\nstruct AbslInternal_YouForgotToExplicitlyInitializeAField {\n  // A portable version of [[clang::require_explicit_initialization]] that\n  // never builds, as a last resort for all toolchains.\n  // The error messages are poor, so we don't rely on this unless we have to.\n  template <class T>\n#if !defined(SWIG)\n  constexpr\n#endif\n  operator T() const /* NOLINT */ {\n    const void *volatile deliberately_volatile_ptr = nullptr;\n    // Infinite loop to prevent constexpr compilation\n    for (;;) {\n      // This assignment ensures the 'this' pointer is not optimized away, so\n      // that linking always fails.\n      deliberately_volatile_ptr = this;  // Deliberately not constexpr\n      (void)deliberately_volatile_ptr;\n    }\n  }\n  // This is deliberately left undefined to prevent linking\n  static AbslInternal_YouForgotToExplicitlyInitializeAField v;\n};\n#endif\n\n// ABSL_CONST_INIT\n//\n// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will\n// not compile (on supported platforms) unless the variable has a constant\n// initializer. This is useful for variables with static and thread storage\n// duration, because it guarantees that they will not suffer from the so-called\n// \"static init order fiasco\".\n//\n// This attribute must be placed on the initializing declaration of the\n// variable. Some compilers will give a -Wmissing-constinit warning when this\n// attribute is placed on some other declaration but missing from the\n// initializing declaration.\n//\n// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can\n// also be used in a non-initializing declaration to tell the compiler that a\n// variable is already initialized, reducing overhead that would otherwise be\n// incurred by a hidden guard variable. Thus annotating all declarations with\n// this attribute is recommended to potentially enhance optimization.\n//\n// Example:\n//\n//   class MyClass {\n//    public:\n//     ABSL_CONST_INIT static MyType my_var;\n//   };\n//\n//   ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...);\n//\n// For code or headers that are assured to only build with C++20 and up, prefer\n// just using the standard `constinit` keyword directly over this macro.\n//\n// Note that this attribute is redundant if the variable is declared constexpr.\n#if defined(__cpp_constinit) && __cpp_constinit >= 201907L\n#define ABSL_CONST_INIT constinit\n#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)\n#define ABSL_CONST_INIT [[clang::require_constant_initialization]]\n#else\n#define ABSL_CONST_INIT\n#endif\n\n// ABSL_ATTRIBUTE_PURE_FUNCTION\n//\n// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of \"pure\"\n// functions. A function is pure if its return value is only a function of its\n// arguments. The pure attribute prohibits a function from modifying the state\n// of the program that is observable by means other than inspecting the\n// function's return value. Declaring such functions with the pure attribute\n// allows the compiler to avoid emitting some calls in repeated invocations of\n// the function with the same argument values.\n//\n// Example:\n//\n//  ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);\n#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)\n#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]\n#elif ABSL_HAVE_ATTRIBUTE(pure)\n#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))\n#else\n// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since\n// pure functions are useless if its return is ignored.\n#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT\n#endif\n\n// ABSL_ATTRIBUTE_CONST_FUNCTION\n//\n// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of \"const\"\n// functions. A const function is similar to a pure function, with one\n// exception: Pure functions may return value that depend on a non-volatile\n// object that isn't provided as a function argument, while the const function\n// is guaranteed to return the same result given the same arguments.\n//\n// Example:\n//\n//  ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d);\n#if defined(_MSC_VER) && !defined(__clang__)\n// Put the MSVC case first since MSVC seems to parse const as a C++ keyword.\n#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION\n#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const)\n#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]]\n#elif ABSL_HAVE_ATTRIBUTE(const)\n#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const))\n#else\n// Since const functions are more restrictive pure function, we'll fallback to a\n// pure function if the const attribute is not handled.\n#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION\n#endif\n\n// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function\n// parameter or implicit object parameter is retained by the return value of the\n// annotated function (or, for a parameter of a constructor, in the value of the\n// constructed object). This attribute causes warnings to be produced if a\n// temporary object does not live long enough.\n//\n// When applied to a reference parameter, the referenced object is assumed to be\n// retained by the return value of the function. When applied to a non-reference\n// parameter (for example, a pointer or a class type), all temporaries\n// referenced by the parameter are assumed to be retained by the return value of\n// the function.\n//\n// See also the upstream documentation:\n// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound\n// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)\n#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]\n#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound)\n#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]]\n#elif ABSL_HAVE_ATTRIBUTE(lifetimebound)\n#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))\n#else\n#define ABSL_ATTRIBUTE_LIFETIME_BOUND\n#endif\n\n// Internal attribute; name and documentation TBD.\n//\n// See the upstream documentation:\n// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by)\n#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \\\n  [[clang::lifetime_capture_by(Owner)]]\n#else\n#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner)\n#endif\n\n// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a \"view\" of data that it\n// points to, similarly to a span, string_view, or other non-owning reference\n// type.\n// This enables diagnosing certain lifetime issues similar to those enabled by\n// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:\n//\n//   struct ABSL_ATTRIBUTE_VIEW StringView {\n//     template<class R>\n//     StringView(const R&);\n//   };\n//\n//   StringView f(std::string s) {\n//     return s;  // warning: address of stack memory returned\n//   }\n//\n// We disable this on Clang versions < 13 because of the following\n// false-positive:\n//\n//   absl::string_view f(std::optional<absl::string_view> sv) { return *sv; }\n//\n// See the following links for details:\n// https://reviews.llvm.org/D64448\n// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html\n#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \\\n    (!defined(__clang_major__) || __clang_major__ >= 13)\n#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]]\n#else\n#define ABSL_ATTRIBUTE_VIEW\n#endif\n\n// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or\n// similar class that owns all the data that it points to.\n// This enables diagnosing certain lifetime issues similar to those enabled by\n// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:\n//\n//   struct ABSL_ATTRIBUTE_VIEW StringView {\n//     template<class R>\n//     StringView(const R&);\n//   };\n//\n//   struct ABSL_ATTRIBUTE_OWNER String {};\n//\n//   StringView f(String s) {\n//     return s;  // warning: address of stack memory returned\n//   }\n//\n// We disable this on Clang versions < 13 because of the following\n// false-positive:\n//\n//   absl::string_view f(std::optional<absl::string_view> sv) { return *sv; }\n//\n// See the following links for details:\n// https://reviews.llvm.org/D64448\n// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html\n#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \\\n    (!defined(__clang_major__) || __clang_major__ >= 13)\n#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]]\n#else\n#define ABSL_ATTRIBUTE_OWNER\n#endif\n\n// ABSL_ATTRIBUTE_TRIVIAL_ABI\n// Indicates that a type is \"trivially relocatable\" -- meaning it can be\n// relocated without invoking the constructor/destructor, using a form of move\n// elision.\n//\n// From a memory safety point of view, putting aside destructor ordering, it's\n// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location\n// can change over the course of its lifetime: if a constructor can be run one\n// place, and then the object magically teleports to another place where some\n// methods are run, and then the object teleports to yet another place where it\n// is destroyed. This is notably not true for self-referential types, where the\n// move-constructor must keep the self-reference up to date. If the type changed\n// location without invoking the move constructor, it would have a dangling\n// self-reference.\n//\n// The use of this teleporting machinery means that the number of paired\n// move/destroy operations can change, and so it is a bad idea to apply this to\n// a type meant to count the number of moves.\n//\n// Warning: applying this can, rarely, break callers. Objects passed by value\n// will be destroyed at the end of the call, instead of the end of the\n// full-expression containing the call. In addition, it changes the ABI\n// of functions accepting this type by value (e.g. to pass in registers).\n//\n// See also the upstream documentation:\n// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi\n//\n// b/321691395 - This is currently disabled in open-source builds since\n// compiler support differs. If system libraries compiled with GCC are mixed\n// with libraries compiled with Clang, types will have different ideas about\n// their ABI, leading to hard to debug crashes.\n#define ABSL_ATTRIBUTE_TRIVIAL_ABI\n\n// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS\n//\n// Indicates a data member can be optimized to occupy no space (if it is empty)\n// and/or its tail padding can be used for other members.\n//\n// For code that is assured to only build with C++20 or later, prefer using\n// the standard attribute `[[no_unique_address]]` directly instead of this\n// macro.\n//\n// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address\n// Current versions of MSVC have disabled `[[no_unique_address]]` since it\n// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for\n// situations when it can be assured that it is desired. Since Abseil does not\n// claim ABI compatibility in mixed builds, we can offer it unconditionally.\n#if defined(_MSC_VER) && _MSC_VER >= 1929\n#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]\n#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address)\n#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]\n#else\n#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS\n#endif\n\n// ABSL_ATTRIBUTE_UNINITIALIZED\n//\n// GCC and Clang support a flag `-ftrivial-auto-var-init=<option>` (<option>\n// can be \"zero\" or \"pattern\") that can be used to initialize automatic stack\n// variables. Variables with this attribute will be left uninitialized,\n// overriding the compiler flag.\n//\n// See https://clang.llvm.org/docs/AttributeReference.html#uninitialized\n// and https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-uninitialized-variable-attribute\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::uninitialized)\n#define ABSL_ATTRIBUTE_UNINITIALIZED [[clang::uninitialized]]\n#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::uninitialized)\n#define ABSL_ATTRIBUTE_UNINITIALIZED [[gnu::uninitialized]]\n#elif ABSL_HAVE_ATTRIBUTE(uninitialized)\n#define ABSL_ATTRIBUTE_UNINITIALIZED __attribute__((uninitialized))\n#else\n#define ABSL_ATTRIBUTE_UNINITIALIZED\n#endif\n\n// ABSL_ATTRIBUTE_WARN_UNUSED\n//\n// Compilers routinely warn about trivial variables that are unused.  For\n// non-trivial types, this warning is suppressed since the\n// constructor/destructor may be intentional and load-bearing, for example, with\n// a RAII scoped lock.\n//\n// For example:\n//\n// class ABSL_ATTRIBUTE_WARN_UNUSED MyType {\n//  public:\n//   MyType();\n//   ~MyType();\n// };\n//\n// void foo() {\n//   // Warns with ABSL_ATTRIBUTE_WARN_UNUSED attribute present.\n//   MyType unused;\n// }\n//\n// See https://clang.llvm.org/docs/AttributeReference.html#warn-unused and\n// https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-warn_005funused-type-attribute\n#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::warn_unused)\n#define ABSL_ATTRIBUTE_WARN_UNUSED [[gnu::warn_unused]]\n#else\n#define ABSL_ATTRIBUTE_WARN_UNUSED\n#endif\n\n#endif  // ABSL_BASE_ATTRIBUTES_H_\n"
  },
  {
    "path": "absl/base/attributes_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/attributes.h\"\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace {\n\nTEST(Attributes, RequireExplicitInit) {\n  struct Agg {\n    int f1;\n    int f2 ABSL_REQUIRE_EXPLICIT_INIT;\n  };\n  Agg good1 ABSL_ATTRIBUTE_UNUSED = {1, 2};\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n  Agg good2 ABSL_ATTRIBUTE_UNUSED(1, 2);\n#endif\n  Agg good3 ABSL_ATTRIBUTE_UNUSED{1, 2};\n  Agg good4 ABSL_ATTRIBUTE_UNUSED = {1, 2};\n  Agg good5 ABSL_ATTRIBUTE_UNUSED = Agg{1, 2};\n  Agg good6[1] ABSL_ATTRIBUTE_UNUSED = {{1, 2}};\n  Agg good7[1] ABSL_ATTRIBUTE_UNUSED = {Agg{1, 2}};\n  union {\n    Agg agg;\n  } good8 ABSL_ATTRIBUTE_UNUSED = {{1, 2}};\n  constexpr Agg good9 ABSL_ATTRIBUTE_UNUSED = {1, 2};\n  constexpr Agg good10 ABSL_ATTRIBUTE_UNUSED{1, 2};\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/bit_cast_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Unit test for bit_cast template.\n\n#include <cstdint>\n#include <cstring>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/macros.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\ntemplate <int N>\nstruct marshall { char buf[N]; };\n\ntemplate <typename T>\nvoid TestMarshall(const T values[], int num_values) {\n  for (int i = 0; i < num_values; ++i) {\n    T t0 = values[i];\n    marshall<sizeof(T)> m0 = absl::bit_cast<marshall<sizeof(T)> >(t0);\n    T t1 = absl::bit_cast<T>(m0);\n    marshall<sizeof(T)> m1 = absl::bit_cast<marshall<sizeof(T)> >(t1);\n    ASSERT_EQ(0, memcmp(&t0, &t1, sizeof(T)));\n    ASSERT_EQ(0, memcmp(&m0, &m1, sizeof(T)));\n  }\n}\n\n// Convert back and forth to an integral type.  The C++ standard does\n// not guarantee this will work, but we test that this works on all the\n// platforms we support.\n//\n// Likewise, we below make assumptions about sizeof(float) and\n// sizeof(double) which the standard does not guarantee, but which hold on the\n// platforms we support.\n\ntemplate <typename T, typename I>\nvoid TestIntegral(const T values[], int num_values) {\n  for (int i = 0; i < num_values; ++i) {\n    T t0 = values[i];\n    I i0 = absl::bit_cast<I>(t0);\n    T t1 = absl::bit_cast<T>(i0);\n    I i1 = absl::bit_cast<I>(t1);\n    ASSERT_EQ(0, memcmp(&t0, &t1, sizeof(T)));\n    ASSERT_EQ(i0, i1);\n  }\n}\n\nTEST(BitCast, Bool) {\n  static const bool bool_list[] = { false, true };\n  TestMarshall<bool>(bool_list, ABSL_ARRAYSIZE(bool_list));\n}\n\nTEST(BitCast, Int32) {\n  static const int32_t int_list[] =\n    { 0, 1, 100, 2147483647, -1, -100, -2147483647, -2147483647-1 };\n  TestMarshall<int32_t>(int_list, ABSL_ARRAYSIZE(int_list));\n}\n\nTEST(BitCast, Int64) {\n  static const int64_t int64_list[] =\n    { 0, 1, 1LL << 40, -1, -(1LL<<40) };\n  TestMarshall<int64_t>(int64_list, ABSL_ARRAYSIZE(int64_list));\n}\n\nTEST(BitCast, Uint64) {\n  static const uint64_t uint64_list[] =\n    { 0, 1, 1LLU << 40, 1LLU << 63 };\n  TestMarshall<uint64_t>(uint64_list, ABSL_ARRAYSIZE(uint64_list));\n}\n\nTEST(BitCast, Float) {\n  static const float float_list[] =\n    { 0.0f, 1.0f, -1.0f, 10.0f, -10.0f,\n      1e10f, 1e20f, 1e-10f, 1e-20f,\n      2.71828f, 3.14159f };\n  TestMarshall<float>(float_list, ABSL_ARRAYSIZE(float_list));\n  TestIntegral<float, int>(float_list, ABSL_ARRAYSIZE(float_list));\n  TestIntegral<float, unsigned>(float_list, ABSL_ARRAYSIZE(float_list));\n}\n\nTEST(BitCast, Double) {\n  static const double double_list[] =\n    { 0.0, 1.0, -1.0, 10.0, -10.0,\n      1e10, 1e100, 1e-10, 1e-100,\n      2.718281828459045,\n      3.141592653589793238462643383279502884197169399375105820974944 };\n  TestMarshall<double>(double_list, ABSL_ARRAYSIZE(double_list));\n  TestIntegral<double, int64_t>(double_list, ABSL_ARRAYSIZE(double_list));\n  TestIntegral<double, uint64_t>(double_list, ABSL_ARRAYSIZE(double_list));\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/c_header_test.c",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifdef __cplusplus\n#error This is a C compile test\n#endif\n\n// This test ensures that headers that are included in legacy C code are\n// compatible with C. Abseil is a C++ library. We do not desire to expand C\n// compatibility or keep C compatibility forever. This test only exists to\n// ensure C compatibility until it is no longer required. Do not add new code\n// that requires C compatibility.\n#include \"absl/base/attributes.h\"     // IWYU pragma: keep\n#include \"absl/base/config.h\"         // IWYU pragma: keep\n#include \"absl/base/optimization.h\"   // IWYU pragma: keep\n#include \"absl/base/policy_checks.h\"  // IWYU pragma: keep\n#include \"absl/base/port.h\"           // IWYU pragma: keep\n\nint main() { return 0; }\n"
  },
  {
    "path": "absl/base/call_once.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: call_once.h\n// -----------------------------------------------------------------------------\n//\n// This header file provides an Abseil version of `std::call_once` for invoking\n// a given function at most once, across all threads. This Abseil version is\n// faster than the C++11 version and incorporates the C++17 argument-passing\n// fix, so that (for example) non-const references may be passed to the invoked\n// function.\n\n#ifndef ABSL_BASE_CALL_ONCE_H_\n#define ABSL_BASE_CALL_ONCE_H_\n\n#include <algorithm>\n#include <atomic>\n#include <cstdint>\n#include <functional>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/low_level_scheduling.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/internal/spinlock_wait.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass once_flag;\n\nnamespace base_internal {\nstd::atomic<uint32_t>* absl_nonnull ControlWord(\n    absl::once_flag* absl_nonnull flag);\n}  // namespace base_internal\n\n// call_once()\n//\n// For all invocations using a given `once_flag`, invokes a given `fn` exactly\n// once across all threads. The first call to `call_once()` with a particular\n// `once_flag` argument (that does not throw an exception) will run the\n// specified function with the provided `args`; other calls with the same\n// `once_flag` argument will not run the function, but will wait\n// for the provided function to finish running (if it is still running).\n//\n// This mechanism provides a safe, simple, and fast mechanism for one-time\n// initialization in a multi-threaded process.\n//\n// Example:\n//\n// class MyInitClass {\n//  public:\n//  ...\n//  mutable absl::once_flag once_;\n//\n//  MyInitClass* init() const {\n//    absl::call_once(once_, &MyInitClass::Init, this);\n//    return ptr_;\n//  }\n//\ntemplate <typename Callable, typename... Args>\nvoid call_once(absl::once_flag& flag, Callable&& fn, Args&&... args);\n\n// once_flag\n//\n// Objects of this type are used to distinguish calls to `call_once()` and\n// ensure the provided function is only invoked once across all threads. This\n// type is not copyable or movable. However, it has a `constexpr`\n// constructor, and is safe to use as a namespace-scoped global variable.\nclass once_flag {\n public:\n  constexpr once_flag() : control_(0) {}\n  once_flag(const once_flag&) = delete;\n  once_flag& operator=(const once_flag&) = delete;\n\n private:\n  friend std::atomic<uint32_t>* absl_nonnull base_internal::ControlWord(\n      once_flag* absl_nonnull flag);\n  std::atomic<uint32_t> control_;\n};\n\n//------------------------------------------------------------------------------\n// End of public interfaces.\n// Implementation details follow.\n//------------------------------------------------------------------------------\n\nnamespace base_internal {\n\n// Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to\n// initialize entities used by the scheduler implementation.\ntemplate <typename Callable, typename... Args>\nvoid LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,\n                      Args&&... args);\n\n// Disables scheduling while on stack when scheduling mode is non-cooperative.\n// No effect for cooperative scheduling modes.\nclass SchedulingHelper {\n public:\n  explicit SchedulingHelper(base_internal::SchedulingMode mode) : mode_(mode) {\n    if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) {\n      guard_result_ = base_internal::SchedulingGuard::DisableRescheduling();\n    }\n  }\n\n  ~SchedulingHelper() {\n    if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) {\n      base_internal::SchedulingGuard::EnableRescheduling(guard_result_);\n    }\n  }\n\n private:\n  base_internal::SchedulingMode mode_;\n  bool guard_result_ = false;\n};\n\n// Bit patterns for call_once state machine values.  Internal implementation\n// detail, not for use by clients.\n//\n// The bit patterns are arbitrarily chosen from unlikely values, to aid in\n// debugging.  However, kOnceInit must be 0, so that a zero-initialized\n// once_flag will be valid for immediate use.\nenum {\n  kOnceInit = 0,\n  kOnceRunning = 0x65C2937B,\n  kOnceWaiter = 0x05A308D2,\n  // A very small constant is chosen for kOnceDone so that it fit in a single\n  // compare with immediate instruction for most common ISAs.  This is verified\n  // for x86, POWER and ARM.\n  kOnceDone = 221,    // Random Number\n};\n\ntemplate <typename Callable, typename... Args>\n    void\n    CallOnceImpl(std::atomic<uint32_t>* absl_nonnull control,\n                 base_internal::SchedulingMode scheduling_mode, Callable&& fn,\n                 Args&&... args) {\n#ifndef NDEBUG\n  {\n    uint32_t old_control = control->load(std::memory_order_relaxed);\n    if (old_control != kOnceInit &&\n        old_control != kOnceRunning &&\n        old_control != kOnceWaiter &&\n        old_control != kOnceDone) {\n      // Memory corruption may cause this error.\n      ABSL_RAW_LOG(FATAL, \"Unexpected value for control word: 0x%lx\",\n                   static_cast<unsigned long>(old_control));  // NOLINT\n    }\n  }\n#endif  // NDEBUG\n  static const base_internal::SpinLockWaitTransition trans[] = {\n      {kOnceInit, kOnceRunning, true},\n      {kOnceRunning, kOnceWaiter, false},\n      {kOnceDone, kOnceDone, true}};\n\n  // Must do this before potentially modifying control word's state.\n  base_internal::SchedulingHelper maybe_disable_scheduling(scheduling_mode);\n  // Short circuit the simplest case to avoid procedure call overhead.\n  // The base_internal::SpinLockWait() call returns either kOnceInit or\n  // kOnceDone. If it returns kOnceDone, it must have loaded the control word\n  // with std::memory_order_acquire and seen a value of kOnceDone.\n  uint32_t old_control = kOnceInit;\n  if (control->compare_exchange_strong(old_control, kOnceRunning,\n                                       std::memory_order_relaxed) ||\n      base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,\n                                  scheduling_mode) == kOnceInit) {\n    std::invoke(std::forward<Callable>(fn), std::forward<Args>(args)...);\n    old_control =\n        control->exchange(base_internal::kOnceDone, std::memory_order_release);\n    if (old_control == base_internal::kOnceWaiter) {\n      base_internal::SpinLockWake(control, true);\n    }\n  }  // else *control is already kOnceDone\n}\n\ninline std::atomic<uint32_t>* absl_nonnull ControlWord(\n    once_flag* absl_nonnull flag) {\n  return &flag->control_;\n}\n\ntemplate <typename Callable, typename... Args>\nvoid LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,\n                      Args&&... args) {\n  std::atomic<uint32_t>* once = base_internal::ControlWord(flag);\n  uint32_t s = once->load(std::memory_order_acquire);\n  if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {\n    base_internal::CallOnceImpl(once, base_internal::SCHEDULE_KERNEL_ONLY,\n                                std::forward<Callable>(fn),\n                                std::forward<Args>(args)...);\n  }\n}\n\n}  // namespace base_internal\n\ntemplate <typename Callable, typename... Args>\n    void\n    call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {\n  std::atomic<uint32_t>* once = base_internal::ControlWord(&flag);\n  uint32_t s = once->load(std::memory_order_acquire);\n  if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {\n    base_internal::CallOnceImpl(\n        once, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL,\n        std::forward<Callable>(fn), std::forward<Args>(args)...);\n  }\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_CALL_ONCE_H_\n"
  },
  {
    "path": "absl/base/call_once_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/call_once.h\"\n\n#include <thread>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nabsl::once_flag once;\n\nABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);\n\nint running_thread_count ABSL_GUARDED_BY(counters_mu) = 0;\nint call_once_invoke_count ABSL_GUARDED_BY(counters_mu) = 0;\nint call_once_finished_count ABSL_GUARDED_BY(counters_mu) = 0;\nint call_once_return_count ABSL_GUARDED_BY(counters_mu) = 0;\nbool done_blocking ABSL_GUARDED_BY(counters_mu) = false;\n\n// Function to be called from absl::call_once.  Waits for a notification.\nvoid WaitAndIncrement() {\n  counters_mu.lock();\n  ++call_once_invoke_count;\n  counters_mu.unlock();\n\n  counters_mu.LockWhen(Condition(&done_blocking));\n  ++call_once_finished_count;\n  counters_mu.unlock();\n}\n\nvoid ThreadBody() {\n  counters_mu.lock();\n  ++running_thread_count;\n  counters_mu.unlock();\n\n  absl::call_once(once, WaitAndIncrement);\n\n  counters_mu.lock();\n  ++call_once_return_count;\n  counters_mu.unlock();\n}\n\n// Returns true if all threads are set up for the test.\nbool ThreadsAreSetup(void*) ABSL_EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {\n  // All ten threads must be running, and WaitAndIncrement should be blocked.\n  return running_thread_count == 10 && call_once_invoke_count == 1;\n}\n\nTEST(CallOnceTest, ExecutionCount) {\n  std::vector<std::thread> threads;\n\n  // Start 10 threads all calling call_once on the same once_flag.\n  for (int i = 0; i < 10; ++i) {\n    threads.emplace_back(ThreadBody);\n  }\n\n\n  // Wait until all ten threads have started, and WaitAndIncrement has been\n  // invoked.\n  counters_mu.LockWhen(Condition(ThreadsAreSetup, nullptr));\n\n  // WaitAndIncrement should have been invoked by exactly one call_once()\n  // instance.  That thread should be blocking on a notification, and all other\n  // call_once instances should be blocking as well.\n  EXPECT_EQ(call_once_invoke_count, 1);\n  EXPECT_EQ(call_once_finished_count, 0);\n  EXPECT_EQ(call_once_return_count, 0);\n\n  // Allow WaitAndIncrement to finish executing.  Once it does, the other\n  // call_once waiters will be unblocked.\n  done_blocking = true;\n  counters_mu.unlock();\n\n  for (std::thread& thread : threads) {\n    thread.join();\n  }\n\n  counters_mu.lock();\n  EXPECT_EQ(call_once_invoke_count, 1);\n  EXPECT_EQ(call_once_finished_count, 1);\n  EXPECT_EQ(call_once_return_count, 10);\n  counters_mu.unlock();\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/casts.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/casts.h\"\n\n#include <cstdlib>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\n#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE\n#include <cxxabi.h>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace base_internal {\n\nnamespace {\n\nstd::string DemangleCppString(const char* mangled) {\n  std::string out;\n  int status = 0;\n  char* demangled = nullptr;\n#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE\n  demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);\n#endif\n  if (status == 0 && demangled != nullptr) {\n    out.append(demangled);\n    free(demangled);\n  } else {\n    out.append(mangled);\n  }\n  return out;\n}\n\n}  // namespace\n\nvoid BadDownCastCrash(const char* source_type, const char* target_type) {\n  ABSL_RAW_LOG(FATAL, \"down cast from %s to %s failed\",\n               DemangleCppString(source_type).c_str(),\n               DemangleCppString(target_type).c_str());\n}\n\n}  // namespace base_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/casts.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: casts.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines casting templates to fit use cases not covered by\n// the standard casts provided in the C++ standard. As with all cast operations,\n// use these with caution and only if alternatives do not exist.\n\n#ifndef ABSL_BASE_CASTS_H_\n#define ABSL_BASE_CASTS_H_\n\n#include <cstring>\n#include <memory>\n#include <type_traits>\n#include <typeinfo>\n#include <utility>\n\n#ifdef __has_include\n#if __has_include(<version>)\n#include <version>  // For __cpp_lib_bit_cast.\n#endif\n#endif\n\n#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L\n#include <bit>  // For std::bit_cast.\n#endif  // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/options.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// implicit_cast()\n//\n// Performs an implicit conversion between types following the language\n// rules for implicit conversion; if an implicit conversion is otherwise\n// allowed by the language in the given context, this function performs such an\n// implicit conversion.\n//\n// Example:\n//\n//   // If the context allows implicit conversion:\n//   From from;\n//   To to = from;\n//\n//   // Such code can be replaced by:\n//   implicit_cast<To>(from);\n//\n// An `implicit_cast()` may also be used to annotate numeric type conversions\n// that, although safe, may produce compiler warnings (such as `long` to `int`).\n// Additionally, an `implicit_cast()` is also useful within return statements to\n// indicate a specific implicit conversion is being undertaken.\n//\n// Example:\n//\n//   return implicit_cast<double>(size_in_bytes) / capacity_;\n//\n// Annotating code with `implicit_cast()` allows you to explicitly select\n// particular overloads and template instantiations, while providing a safer\n// cast than `reinterpret_cast()` or `static_cast()`.\n//\n// Additionally, an `implicit_cast()` can be used to allow upcasting within a\n// type hierarchy where incorrect use of `static_cast()` could accidentally\n// allow downcasting.\n//\n// Finally, an `implicit_cast()` can be used to perform implicit conversions\n// from unrelated types that otherwise couldn't be implicitly cast directly;\n// C++ will normally only implicitly cast \"one step\" in such conversions.\n//\n// That is, if C is a type which can be implicitly converted to B, with B being\n// a type that can be implicitly converted to A, an `implicit_cast()` can be\n// used to convert C to B (which the compiler can then implicitly convert to A\n// using language rules).\n//\n// Example:\n//\n//   // Assume an object C is convertible to B, which is implicitly convertible\n//   // to A\n//   A a = implicit_cast<B>(C);\n//\n// Such implicit cast chaining may be useful within template logic.\ntemplate <typename To>\nconstexpr std::enable_if_t<\n    !type_traits_internal::IsView<std::enable_if_t<\n        !std::is_reference_v<To>, std::remove_cv_t<To>>>::value,\n    To>\nimplicit_cast(absl::type_identity_t<To> to) {\n  return to;\n}\ntemplate <typename To>\nconstexpr std::enable_if_t<\n    type_traits_internal::IsView<std::enable_if_t<!std::is_reference_v<To>,\n                                                  std::remove_cv_t<To>>>::value,\n    To>\nimplicit_cast(absl::type_identity_t<To> to ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return to;\n}\ntemplate <typename To>\nconstexpr std::enable_if_t<std::is_reference_v<To>, To> implicit_cast(\n    absl::type_identity_t<To> to ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return std::forward<absl::type_identity_t<To>>(to);\n}\n\n// bit_cast()\n//\n// Creates a value of the new type `Dest` whose representation is the same as\n// that of the argument, which is of (deduced) type `Source` (a \"bitwise cast\";\n// every bit in the value representation of the result is equal to the\n// corresponding bit in the object representation of the source). Source and\n// destination types must be of the same size, and both types must be trivially\n// copyable.\n//\n// As with most casts, use with caution. A `bit_cast()` might be needed when you\n// need to treat a value as the value of some other type, for example, to access\n// the individual bits of an object which are not normally accessible through\n// the object's type, such as for working with the binary representation of a\n// floating point value:\n//\n//   float f = 3.14159265358979;\n//   int i = bit_cast<int>(f);\n//   // i = 0x40490fdb\n//\n// Reinterpreting and accessing a value directly as a different type (as shown\n// below) usually results in undefined behavior.\n//\n// Example:\n//\n//   // WRONG\n//   float f = 3.14159265358979;\n//   int i = reinterpret_cast<int&>(f);    // Wrong\n//   int j = *reinterpret_cast<int*>(&f);  // Equally wrong\n//   int k = *bit_cast<int*>(&f);          // Equally wrong\n//\n// Reinterpret-casting results in undefined behavior according to the ISO C++\n// specification, section [basic.lval]. Roughly, this section says: if an object\n// in memory has one type, and a program accesses it with a different type, the\n// result is undefined behavior for most \"different type\".\n//\n// Using bit_cast on a pointer and then dereferencing it is no better than using\n// reinterpret_cast. You should only use bit_cast on the value itself.\n//\n// Such casting results in type punning: holding an object in memory of one type\n// and reading its bits back using a different type. A `bit_cast()` avoids this\n// issue by copying the object representation to a new value, which avoids\n// introducing this undefined behavior (since the original value is never\n// accessed in the wrong way).\n//\n// The requirements of `absl::bit_cast` are more strict than that of\n// `std::bit_cast` unless compiler support is available. Specifically, without\n// compiler support, this implementation also requires `Dest` to be\n// default-constructible. In C++20, `absl::bit_cast` is replaced by\n// `std::bit_cast`.\n#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L\n\nusing std::bit_cast;\n\n#else  // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L\n\ntemplate <\n    typename Dest, typename Source,\n    typename std::enable_if<sizeof(Dest) == sizeof(Source) &&\n                                std::is_trivially_copyable<Source>::value &&\n                                std::is_trivially_copyable<Dest>::value\n#if !ABSL_HAVE_BUILTIN(__builtin_bit_cast)\n                                && std::is_default_constructible<Dest>::value\n#endif  // !ABSL_HAVE_BUILTIN(__builtin_bit_cast)\n                            ,\n                            int>::type = 0>\n#if ABSL_HAVE_BUILTIN(__builtin_bit_cast)\ninline constexpr Dest bit_cast(const Source& source) {\n  return __builtin_bit_cast(Dest, source);\n}\n#else  // ABSL_HAVE_BUILTIN(__builtin_bit_cast)\ninline Dest bit_cast(const Source& source) {\n  Dest dest;\n  memcpy(static_cast<void*>(std::addressof(dest)),\n         static_cast<const void*>(std::addressof(source)), sizeof(dest));\n  return dest;\n}\n#endif  // ABSL_HAVE_BUILTIN(__builtin_bit_cast)\n\n#endif  // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L\n\nnamespace base_internal {\n\n[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void BadDownCastCrash(\n    const char* source_type, const char* target_type);\n\ntemplate <typename To, typename From>\ninline void ValidateDownCast(From* f ABSL_ATTRIBUTE_UNUSED) {\n  // Assert only if RTTI is enabled and in debug mode or hardened asserts are\n  // enabled.\n#ifdef ABSL_INTERNAL_HAS_RTTI\n#if !defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1)\n  // Suppress erroneous nonnull comparison warning on older GCC.\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wnonnull-compare\"\n#endif\n  if (ABSL_PREDICT_FALSE(f != nullptr && dynamic_cast<To>(f) == nullptr)) {\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n    absl::base_internal::BadDownCastCrash(\n        typeid(*f).name(), typeid(std::remove_pointer_t<To>).name());\n  }\n#endif\n#endif\n}\n\n}  // namespace base_internal\n\n// An \"upcast\", i.e. a conversion from a pointer to an object to a pointer to a\n// base subobject, always succeeds if the base is unambiguous and accessible,\n// and so it's fine to use implicit_cast.\n//\n// A \"downcast\", i.e. a conversion from a pointer to an object to a pointer\n// to a more-derived object that may contain the original object as a base\n// subobject, cannot safely be done using static_cast, because you do not\n// generally know whether the source object is really the base subobject of\n// a containing, more-derived object of the target type. Thus, when you\n// downcast in a polymorphic type hierarchy, you should use the following\n// function template.\n//\n// This function only returns null when the input is null. In debug mode, we\n// use dynamic_cast to double-check whether the downcast is legal (we die if\n// it's not). In normal mode, we do the efficient static_cast instead. Because\n// the process will die in debug mode, it's important to test to make sure the\n// cast is legal before calling this function!\n//\n// dynamic_cast should be avoided except as allowed by the style guide\n// (https://google.github.io/styleguide/cppguide.html#Run-Time_Type_Information__RTTI_).\n\ntemplate <typename To, typename From>  // use like this: down_cast<T*>(foo);\n[[nodiscard]]\ninline To down_cast(From* f) {  // so we only accept pointers\n  static_assert(std::is_pointer<To>::value, \"target type not a pointer\");\n  // dynamic_cast allows casting to the same type or a more cv-qualified\n  // version of the same type without them being polymorphic.\n  if constexpr (!std::is_same<std::remove_cv_t<std::remove_pointer_t<To>>,\n                              std::remove_cv_t<From>>::value) {\n    static_assert(std::is_polymorphic<From>::value,\n                  \"source type must be polymorphic\");\n    static_assert(std::is_polymorphic<std::remove_pointer_t<To>>::value,\n                  \"target type must be polymorphic\");\n  }\n  static_assert(\n      std::is_convertible<std::remove_cv_t<std::remove_pointer_t<To>>*,\n                          std::remove_cv_t<From>*>::value,\n      \"target type not derived from source type\");\n\n  absl::base_internal::ValidateDownCast<To>(f);\n\n  return static_cast<To>(f);\n}\n\n// Overload of down_cast for references. Use like this:\n// absl::down_cast<T&>(foo). The code is slightly convoluted because we're still\n// using the pointer form of dynamic cast. (The reference form throws an\n// exception if it fails.)\n//\n// There's no need for a special const overload either for the pointer\n// or the reference form. If you call down_cast with a const T&, the\n// compiler will just bind From to const T.\ntemplate <typename To, typename From>\n[[nodiscard]]\ninline To down_cast(From& f) {\n  static_assert(std::is_lvalue_reference<To>::value,\n                \"target type not a reference\");\n  // dynamic_cast allows casting to the same type or a more cv-qualified\n  // version of the same type without them being polymorphic.\n  if constexpr (!std::is_same<std::remove_cv_t<std::remove_reference_t<To>>,\n                              std::remove_cv_t<From>>::value) {\n    static_assert(std::is_polymorphic<From>::value,\n                  \"source type must be polymorphic\");\n    static_assert(std::is_polymorphic<std::remove_reference_t<To>>::value,\n                  \"target type must be polymorphic\");\n  }\n  static_assert(\n      std::is_convertible<std::remove_cv_t<std::remove_reference_t<To>>*,\n                          std::remove_cv_t<From>*>::value,\n      \"target type not derived from source type\");\n\n  absl::base_internal::ValidateDownCast<std::remove_reference_t<To>*>(\n      std::addressof(f));\n\n  return static_cast<To>(f);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_CASTS_H_\n"
  },
  {
    "path": "absl/base/casts_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/casts.h\"\n\n#include <type_traits>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/options.h\"\n\nnamespace {\n\nstruct BaseForImplicitCast {\n  explicit BaseForImplicitCast(int value) : x(value) {}\n  BaseForImplicitCast(const BaseForImplicitCast& other) = delete;\n  BaseForImplicitCast& operator=(const BaseForImplicitCast& other) = delete;\n  int x;\n};\nstruct DerivedForImplicitCast : BaseForImplicitCast {\n  explicit DerivedForImplicitCast(int value) : BaseForImplicitCast(value) {}\n};\n\nstatic_assert(std::is_same_v<decltype(absl::implicit_cast<BaseForImplicitCast&>(\n                                 std::declval<DerivedForImplicitCast&>())),\n                             BaseForImplicitCast&>);\nstatic_assert(\n    std::is_same_v<decltype(absl::implicit_cast<const BaseForImplicitCast&>(\n                       std::declval<DerivedForImplicitCast>())),\n                   const BaseForImplicitCast&>);\n\nTEST(ImplicitCastTest, LValueReference) {\n  DerivedForImplicitCast derived(5);\n  EXPECT_EQ(&absl::implicit_cast<BaseForImplicitCast&>(derived), &derived);\n  EXPECT_EQ(&absl::implicit_cast<const BaseForImplicitCast&>(derived),\n            &derived);\n}\n\nTEST(ImplicitCastTest, RValueReference) {\n  DerivedForImplicitCast derived(5);\n  BaseForImplicitCast&& base =\n      absl::implicit_cast<BaseForImplicitCast&&>(std::move(derived));\n  EXPECT_EQ(&base, &derived);\n\n  const DerivedForImplicitCast cderived(6);\n  const BaseForImplicitCast&& cbase =\n      absl::implicit_cast<const BaseForImplicitCast&&>(std::move(cderived));\n  EXPECT_EQ(&cbase, &cderived);\n}\n\nclass BaseForDownCast {\n public:\n  virtual ~BaseForDownCast() = default;\n};\n\nclass DerivedForDownCast : public BaseForDownCast {};\nclass Derived2ForDownCast : public BaseForDownCast {};\n\nTEST(DownCastTest, Pointer) {\n  DerivedForDownCast derived;\n  BaseForDownCast* const base_ptr = &derived;\n\n  // Tests casting a BaseForDownCast* to a DerivedForDownCast*.\n  EXPECT_EQ(&derived, absl::down_cast<DerivedForDownCast*>(base_ptr));\n\n  // Tests casting a const BaseForDownCast* to a const DerivedForDownCast*.\n  const BaseForDownCast* const_base_ptr = base_ptr;\n  EXPECT_EQ(&derived,\n            absl::down_cast<const DerivedForDownCast*>(const_base_ptr));\n\n  // Tests casting a BaseForDownCast* to a const DerivedForDownCast*.\n  EXPECT_EQ(&derived, absl::down_cast<const DerivedForDownCast*>(base_ptr));\n\n  // Tests casting a BaseForDownCast* to a BaseForDownCast* (an identity cast).\n  EXPECT_EQ(base_ptr, absl::down_cast<BaseForDownCast*>(base_ptr));\n\n  // Tests down casting NULL.\n  EXPECT_EQ(nullptr,\n            (absl::down_cast<DerivedForDownCast*, BaseForDownCast>(nullptr)));\n\n  // Tests a bad downcast. We have to disguise the badness just enough\n  // that the compiler doesn't warn about it at compile time.\n  BaseForDownCast* base2 = new BaseForDownCast();\n#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1))\n  EXPECT_DEATH(static_cast<void>(absl::down_cast<DerivedForDownCast*>(base2)),\n               \".*down cast from .*BaseForDownCast.* to \"\n               \".*DerivedForDownCast.* failed.*\");\n#endif\n  delete base2;\n}\n\nTEST(DownCastTest, Reference) {\n  DerivedForDownCast derived;\n  BaseForDownCast& base_ref = derived;\n\n  // Tests casting a BaseForDownCast& to a DerivedForDownCast&.\n  // NOLINTNEXTLINE(runtime/casting)\n  EXPECT_EQ(&derived, &absl::down_cast<DerivedForDownCast&>(base_ref));\n\n  // Tests casting a const BaseForDownCast& to a const DerivedForDownCast&.\n  const BaseForDownCast& const_base_ref = base_ref;\n  // NOLINTNEXTLINE(runtime/casting)\n  EXPECT_EQ(&derived,\n            &absl::down_cast<const DerivedForDownCast&>(const_base_ref));\n\n  // Tests casting a BaseForDownCast& to a const DerivedForDownCast&.\n  // NOLINTNEXTLINE(runtime/casting)\n  EXPECT_EQ(&derived, &absl::down_cast<const DerivedForDownCast&>(base_ref));\n\n  // Tests casting a BaseForDownCast& to a BaseForDownCast& (an identity cast).\n  // NOLINTNEXTLINE(runtime/casting)\n  EXPECT_EQ(&base_ref, &absl::down_cast<BaseForDownCast&>(base_ref));\n\n  // Tests a bad downcast. We have to disguise the badness just enough\n  // that the compiler doesn't warn about it at compile time.\n  BaseForDownCast& base2 = *new BaseForDownCast();\n#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1))\n  EXPECT_DEATH(static_cast<void>(absl::down_cast<DerivedForDownCast&>(base2)),\n               \".*down cast from .*BaseForDownCast.* to \"\n               \".*DerivedForDownCast.* failed.*\");\n#endif\n  delete &base2;\n}\n\nTEST(DownCastTest, ErrorMessage) {\n  DerivedForDownCast derived;\n  BaseForDownCast& base = derived;\n  (void)base;\n\n#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1))\n  EXPECT_DEATH(static_cast<void>(absl::down_cast<Derived2ForDownCast&>(base)),\n               \".*down cast from .*DerivedForDownCast.* to \"\n               \".*Derived2ForDownCast.* failed.*\");\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/config.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: config.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a set of macros for checking the presence of\n// important compiler and platform features. Such macros can be used to\n// produce portable code by parameterizing compilation based on the presence or\n// lack of a given feature.\n//\n// We define a \"feature\" as some interface we wish to program to: for example,\n// a library function or system call. A value of `1` indicates support for\n// that feature; any other value indicates the feature support is undefined.\n//\n// Example:\n//\n// Suppose a programmer wants to write a program that uses the 'mmap()' system\n// call. The Abseil macro for that feature (`ABSL_HAVE_MMAP`) allows you to\n// selectively include the `mmap.h` header and bracket code using that feature\n// in the macro:\n//\n//   #include \"absl/base/config.h\"\n//\n//   #ifdef ABSL_HAVE_MMAP\n//   #include \"sys/mman.h\"\n//   #endif  //ABSL_HAVE_MMAP\n//\n//   ...\n//   #ifdef ABSL_HAVE_MMAP\n//   void *ptr = mmap(...);\n//   ...\n//   #endif  // ABSL_HAVE_MMAP\n\n#ifndef ABSL_BASE_CONFIG_H_\n#define ABSL_BASE_CONFIG_H_\n\n// Included for the __GLIBC__ macro (or similar macros on other systems).\n#include <limits.h>\n\n#ifdef __cplusplus\n// Included for __GLIBCXX__, _LIBCPP_VERSION\n#include <cstddef>\n#endif  // __cplusplus\n\n// ABSL_INTERNAL_CPLUSPLUS_LANG\n//\n// MSVC does not set the value of __cplusplus correctly, but instead uses\n// _MSVC_LANG as a stand-in.\n// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros\n//\n// However, there are reports that MSVC even sets _MSVC_LANG incorrectly at\n// times, for example:\n// https://github.com/microsoft/vscode-cpptools/issues/1770\n// https://reviews.llvm.org/D70996\n//\n// For this reason, this symbol is considered INTERNAL and code outside of\n// Abseil must not use it.\n#if defined(_MSVC_LANG)\n#define ABSL_INTERNAL_CPLUSPLUS_LANG _MSVC_LANG\n#elif defined(__cplusplus)\n#define ABSL_INTERNAL_CPLUSPLUS_LANG __cplusplus\n#endif\n\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n// Include library feature test macros.\n#include <version>\n#endif\n\n#if defined(__APPLE__)\n// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,\n// __IPHONE_8_0.\n#include <Availability.h>\n#include <TargetConditionals.h>\n#endif\n\n#include \"absl/base/options.h\"\n#include \"absl/base/policy_checks.h\"\n\n// Abseil long-term support (LTS) releases will define\n// `ABSL_LTS_RELEASE_VERSION` to the integer representing the date string of the\n// LTS release version, and will define `ABSL_LTS_RELEASE_PATCH_LEVEL` to the\n// integer representing the patch-level for that release.\n//\n// For example, for LTS release version \"20300401.2\", this would give us\n// ABSL_LTS_RELEASE_VERSION == 20300401 && ABSL_LTS_RELEASE_PATCH_LEVEL == 2\n//\n// These symbols will not be defined in non-LTS code.\n//\n// Abseil recommends that clients live-at-head. Therefore, if you are using\n// these symbols to assert a minimum version requirement, we recommend you do it\n// as\n//\n// #if defined(ABSL_LTS_RELEASE_VERSION) && ABSL_LTS_RELEASE_VERSION < 20300401\n// #error Project foo requires Abseil LTS version >= 20300401\n// #endif\n//\n// The `defined(ABSL_LTS_RELEASE_VERSION)` part of the check excludes\n// live-at-head clients from the minimum version assertion.\n//\n// See https://abseil.io/about/releases for more information on Abseil release\n// management.\n//\n// LTS releases can be obtained from\n// https://github.com/abseil/abseil-cpp/releases.\n#undef ABSL_LTS_RELEASE_VERSION\n#undef ABSL_LTS_RELEASE_PATCH_LEVEL\n\n// Helper macro to convert a CPP variable to a string literal.\n#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x\n#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)\n\n// -----------------------------------------------------------------------------\n// Abseil namespace annotations\n// -----------------------------------------------------------------------------\n\n// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END\n//\n// An annotation placed at the beginning/end of each `namespace absl` scope.\n// This is used to inject an inline namespace.\n//\n// The proper way to write Abseil code in the `absl` namespace is:\n//\n// namespace absl {\n// ABSL_NAMESPACE_BEGIN\n//\n// void Foo();  // absl::Foo().\n//\n// ABSL_NAMESPACE_END\n// }  // namespace absl\n//\n// Users of Abseil should not use these macros, because users of Abseil should\n// not write `namespace absl {` in their own code for any reason.  (Abseil does\n// not support forward declarations of its own types, nor does it support\n// user-provided specialization of Abseil templates.  Code that violates these\n// rules may be broken without warning.)\n#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \\\n    !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME)\n#error options.h is misconfigured.\n#endif\n\n// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither \"head\" nor \"\"\n#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1\n\n#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \\\n  ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME)\n\nstatic_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\\0',\n              \"options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must \"\n              \"not be empty.\");\nstatic_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||\n                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' ||\n                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' ||\n                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' ||\n                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\\0',\n              \"options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must \"\n              \"be changed to a new, unique identifier name.\");\n\n#endif\n\n#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0\n#define ABSL_NAMESPACE_BEGIN\n#define ABSL_NAMESPACE_END\n#define ABSL_INTERNAL_C_SYMBOL(x) x\n#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1\n#define ABSL_NAMESPACE_BEGIN \\\n  inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME {\n#define ABSL_NAMESPACE_END }\n#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v\n#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \\\n  ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v)\n#define ABSL_INTERNAL_C_SYMBOL(x) \\\n  ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME)\n#else\n#error options.h is misconfigured.\n#endif\n\n// -----------------------------------------------------------------------------\n// Compiler Feature Checks\n// -----------------------------------------------------------------------------\n\n// ABSL_HAVE_BUILTIN()\n//\n// Checks whether the compiler supports a Clang Feature Checking Macro, and if\n// so, checks whether it supports the provided builtin function \"x\" where x\n// is one of the functions noted in\n// https://clang.llvm.org/docs/LanguageExtensions.html\n//\n// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.\n// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html\n#ifdef __has_builtin\n#define ABSL_HAVE_BUILTIN(x) __has_builtin(x)\n#else\n#define ABSL_HAVE_BUILTIN(x) 0\n#endif\n\n#ifdef __has_feature\n#define ABSL_HAVE_FEATURE(f) __has_feature(f)\n#else\n#define ABSL_HAVE_FEATURE(f) 0\n#endif\n\n// Portable check for GCC minimum version:\n// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html\n#if defined(__GNUC__) && defined(__GNUC_MINOR__)\n#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \\\n  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))\n#else\n#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0\n#endif\n\n#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)\n#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \\\n  (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y))\n#else\n#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0\n#endif\n\n// ABSL_HAVE_TLS is defined to 1 when __thread should be supported.\n// We assume __thread is supported on Linux when compiled with Clang or\n// compiled against libstdc++ with _GLIBCXX_HAVE_TLS defined.\n#ifdef ABSL_HAVE_TLS\n#error ABSL_HAVE_TLS cannot be directly set\n#elif (defined(__linux__)) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))\n#define ABSL_HAVE_TLS 1\n#elif defined(__INTEL_LLVM_COMPILER)\n#define ABSL_HAVE_TLS 1\n#endif\n\n// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE\n//\n// Checks whether `std::is_trivially_destructible<T>` is supported.\n#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE\n#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set\n#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1\n#endif\n\n// ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE\n//\n// Checks whether `std::is_trivially_default_constructible<T>` and\n// `std::is_trivially_copy_constructible<T>` are supported.\n#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE\n#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set\n#else\n#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1\n#endif\n\n// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE\n//\n// Checks whether `std::is_trivially_copy_assignable<T>` is supported.\n#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE\n#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot be directly set\n#else\n#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1\n#endif\n\n// ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE\n//\n// Checks whether `std::is_trivially_copyable<T>` is supported.\n#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE\n#error ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set\n#define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1\n#endif\n\n// ABSL_HAVE_THREAD_LOCAL\n//\n// Checks whether the `thread_local` storage duration specifier is supported.\n#ifdef ABSL_HAVE_THREAD_LOCAL\n#error ABSL_HAVE_THREAD_LOCAL cannot be directly set\n#elif !defined(__XTENSA__)\n#define ABSL_HAVE_THREAD_LOCAL 1\n#endif\n\n// ABSL_HAVE_INTRINSIC_INT128\n//\n// Checks whether the __int128 compiler extension for a 128-bit integral type is\n// supported.\n//\n// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is\n// supported, but we avoid using it in certain cases:\n// * On Clang:\n//   * Building using Clang for Windows, where the Clang runtime library has\n//     128-bit support only on LP64 architectures, but Windows is LLP64.\n// * On Nvidia's nvcc:\n//   * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions\n//     actually support __int128.\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set\n#elif defined(__SIZEOF_INT128__)\n#if (defined(__clang__) && !defined(_WIN32)) ||           \\\n    (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \\\n    (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))\n#define ABSL_HAVE_INTRINSIC_INT128 1\n#elif defined(__CUDACC__)\n// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a\n// string explaining that it has been removed starting with CUDA 9. We use\n// nested #ifs because there is no short-circuiting in the preprocessor.\n// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined.\n#if __CUDACC_VER__ >= 70000\n#define ABSL_HAVE_INTRINSIC_INT128 1\n#endif  // __CUDACC_VER__ >= 70000\n#endif  // defined(__CUDACC__)\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n// ABSL_HAVE_EXCEPTIONS\n//\n// Checks whether the compiler both supports and enables exceptions. Many\n// compilers support a \"no exceptions\" mode that disables exceptions.\n//\n// Generally, when ABSL_HAVE_EXCEPTIONS is not defined:\n//\n// * Code using `throw` and `try` may not compile.\n// * The `noexcept` specifier will still compile and behave as normal.\n// * The `noexcept` operator may still return `false`.\n//\n// For further details, consult the compiler's documentation.\n#ifdef ABSL_HAVE_EXCEPTIONS\n#error ABSL_HAVE_EXCEPTIONS cannot be directly set.\n#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6)\n// Clang >= 3.6\n#if ABSL_HAVE_FEATURE(cxx_exceptions)\n#define ABSL_HAVE_EXCEPTIONS 1\n#endif  // ABSL_HAVE_FEATURE(cxx_exceptions)\n#elif defined(__clang__)\n// Clang < 3.6\n// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro\n#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)\n#define ABSL_HAVE_EXCEPTIONS 1\n#endif  // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)\n// Handle remaining special cases and default to exceptions being supported.\n#elif !(defined(__GNUC__) && !defined(__cpp_exceptions)) && \\\n    !(defined(_MSC_VER) && !defined(_CPPUNWIND))\n#define ABSL_HAVE_EXCEPTIONS 1\n#endif\n\n// -----------------------------------------------------------------------------\n// Platform Feature Checks\n// -----------------------------------------------------------------------------\n\n// Currently supported operating systems and associated preprocessor\n// symbols:\n//\n//   Linux and Linux-derived           __linux__\n//   Android                           __ANDROID__ (implies __linux__)\n//   Linux (non-Android)               __linux__ && !__ANDROID__\n//   Darwin (macOS and iOS)            __APPLE__\n//   Akaros (http://akaros.org)        __ros__\n//   Windows                           _WIN32\n//   AsmJS                             __asmjs__\n//   WebAssembly (Emscripten)          __EMSCRIPTEN__\n//   Fuchsia                           __Fuchsia__\n//   WebAssembly (WASI)                _WASI_EMULATED_MMAN (implies __wasi__)\n//\n// Note that since Android defines both __ANDROID__ and __linux__, one\n// may probe for either Linux or Android by simply testing for __linux__.\n\n// ABSL_HAVE_MMAP\n//\n// Checks whether the platform has an mmap(2) implementation as defined in\n// POSIX.1-2001.\n#ifdef ABSL_HAVE_MMAP\n#error ABSL_HAVE_MMAP cannot be directly set\n#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \\\n    defined(_AIX) || defined(__ros__) || defined(__asmjs__) ||            \\\n    defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || defined(__sun) ||  \\\n    defined(__myriad2__) || defined(__HAIKU__) || defined(__OpenBSD__) || \\\n    defined(__NetBSD__) || defined(__QNX__) || defined(__VXWORKS__) ||    \\\n    defined(__hexagon__) || defined(__XTENSA__) ||                        \\\n    defined(_WASI_EMULATED_MMAN)\n#define ABSL_HAVE_MMAP 1\n#endif\n\n// ABSL_HAVE_PTHREAD_GETSCHEDPARAM\n//\n// Checks whether the platform implements the pthread_(get|set)schedparam(3)\n// functions as defined in POSIX.1-2001.\n#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM\n#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set\n#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \\\n    defined(_AIX) || defined(__ros__) || defined(__OpenBSD__) ||          \\\n    defined(__NetBSD__) || defined(__VXWORKS__)\n#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1\n#endif\n\n// ABSL_HAVE_SCHED_GETCPU\n//\n// Checks whether sched_getcpu is available.\n#ifdef ABSL_HAVE_SCHED_GETCPU\n#error ABSL_HAVE_SCHED_GETCPU cannot be directly set\n#elif defined(__linux__)\n#define ABSL_HAVE_SCHED_GETCPU 1\n#endif\n\n// ABSL_HAVE_SCHED_YIELD\n//\n// Checks whether the platform implements sched_yield(2) as defined in\n// POSIX.1-2001.\n#ifdef ABSL_HAVE_SCHED_YIELD\n#error ABSL_HAVE_SCHED_YIELD cannot be directly set\n#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) || \\\n    defined(__VXWORKS__)\n#define ABSL_HAVE_SCHED_YIELD 1\n#endif\n\n// ABSL_HAVE_SEMAPHORE_H\n//\n// Checks whether the platform supports the <semaphore.h> header and sem_init(3)\n// family of functions as standardized in POSIX.1-2001.\n//\n// Note: While Apple provides <semaphore.h> for both iOS and macOS, it is\n// explicitly deprecated and will cause build failures if enabled for those\n// platforms.  We side-step the issue by not defining it here for Apple\n// platforms.\n#ifdef ABSL_HAVE_SEMAPHORE_H\n#error ABSL_HAVE_SEMAPHORE_H cannot be directly set\n#elif defined(__linux__) || defined(__ros__) || defined(__VXWORKS__)\n#define ABSL_HAVE_SEMAPHORE_H 1\n#endif\n\n// ABSL_HAVE_ALARM\n//\n// Checks whether the platform supports the <signal.h> header and alarm(2)\n// function as standardized in POSIX.1-2001.\n#ifdef ABSL_HAVE_ALARM\n#error ABSL_HAVE_ALARM cannot be directly set\n#elif defined(__GOOGLE_GRTE_VERSION__)\n// feature tests for Google's GRTE\n#define ABSL_HAVE_ALARM 1\n#elif defined(__GLIBC__)\n// feature test for glibc\n#define ABSL_HAVE_ALARM 1\n#elif defined(_MSC_VER)\n// feature tests for Microsoft's library\n#elif defined(__MINGW32__)\n// mingw32 doesn't provide alarm(2):\n// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h\n// mingw-w64 provides a no-op implementation:\n// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c\n#elif defined(__EMSCRIPTEN__)\n// emscripten doesn't support signals\n#elif defined(__wasi__)\n// WASI doesn't support signals\n#elif defined(__Fuchsia__)\n// Signals don't exist on fuchsia.\n#elif defined(__hexagon__)\n#else\n// other standard libraries\n#define ABSL_HAVE_ALARM 1\n#endif\n\n// ABSL_IS_LITTLE_ENDIAN\n// ABSL_IS_BIG_ENDIAN\n//\n// Checks the endianness of the platform.\n//\n// Prefer using `std::endian` in C++20, or `absl::endian` from\n// absl/numeric/bits.h prior to C++20.\n//\n// Notes: uses the built in endian macros provided by GCC (since 4.6) and\n// Clang (since 3.2); see\n// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html.\n// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error.\n#if defined(ABSL_IS_BIG_ENDIAN)\n#error \"ABSL_IS_BIG_ENDIAN cannot be directly set.\"\n#endif\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n#error \"ABSL_IS_LITTLE_ENDIAN cannot be directly set.\"\n#endif\n\n#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \\\n     __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#define ABSL_IS_LITTLE_ENDIAN 1\n#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \\\n    __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n#define ABSL_IS_BIG_ENDIAN 1\n#elif defined(_WIN32)\n#define ABSL_IS_LITTLE_ENDIAN 1\n#else\n#error \"absl endian detection needs to be set up for your compiler\"\n#endif\n\n// macOS < 10.13 and iOS < 12 don't support <any>, <optional>, or <variant>\n// because the libc++ shared library shipped on the system doesn't have the\n// requisite exported symbols.  See\n// https://github.com/abseil/abseil-cpp/issues/207 and\n// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes\n//\n// libc++ spells out the availability requirements in the file\n// llvm-project/libcxx/include/__config via the #define\n// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. The set of versions has been\n// modified a few times, via\n// https://github.com/llvm/llvm-project/commit/7fb40e1569dd66292b647f4501b85517e9247953\n// and\n// https://github.com/llvm/llvm-project/commit/0bc451e7e137c4ccadcd3377250874f641ca514a\n// The second has the actually correct versions, thus, is what we copy here.\n#if defined(__APPLE__) &&                                         \\\n    ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&   \\\n      __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) ||  \\\n     (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) &&  \\\n      __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \\\n     (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) &&   \\\n      __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) ||   \\\n     (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) &&      \\\n      __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))\n#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1\n#else\n#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0\n#endif\n\n// Deprecated macros for polyfill detection.\n#define ABSL_HAVE_STD_ANY 1\n#define ABSL_USES_STD_ANY 1\n#define ABSL_HAVE_STD_OPTIONAL 1\n#define ABSL_USES_STD_OPTIONAL 1\n#define ABSL_HAVE_STD_STRING_VIEW 1\n#define ABSL_USES_STD_STRING_VIEW 1\n#define ABSL_HAVE_STD_VARIANT 1\n#define ABSL_USES_STD_VARIANT 1\n\n// ABSL_HAVE_STD_SOURCE_LOCATION\n//\n// Checks whether C++20 std::source_location is available.\n#ifdef ABSL_HAVE_STD_SOURCE_LOCATION\n#error \"ABSL_HAVE_STD_SOURCE_LOCATION cannot be directly set.\"\n#elif (defined(__cpp_lib_source_location) &&    \\\n       __cpp_lib_source_location >= 201907L) || \\\n    (defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&   \\\n     ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L)\n#ifdef __has_include\n#if __has_include(<source_location>)\n#define ABSL_HAVE_STD_SOURCE_LOCATION 1\n#endif\n#else\n// No __has_include support, so just assume C++ language version is correct.\n#define ABSL_HAVE_STD_SOURCE_LOCATION 1\n#endif\n#endif\n\n// ABSL_USES_STD_SOURCE_LOCATION\n//\n// Indicates whether absl::SourceLocation is an alias for std::source_location.\n#if !defined(ABSL_OPTION_USE_STD_SOURCE_LOCATION)\n#error options.h is misconfigured.\n#elif ABSL_OPTION_USE_STD_SOURCE_LOCATION == 0 || \\\n    (ABSL_OPTION_USE_STD_SOURCE_LOCATION == 2 &&  \\\n     !defined(ABSL_HAVE_STD_SOURCE_LOCATION))\n#undef ABSL_USES_STD_SOURCE_LOCATION\n#elif ABSL_OPTION_USE_STD_SOURCE_LOCATION == 1 || \\\n    (ABSL_OPTION_USE_STD_SOURCE_LOCATION == 2 &&  \\\n     defined(ABSL_HAVE_STD_SOURCE_LOCATION))\n#define ABSL_USES_STD_SOURCE_LOCATION 1\n#else\n#error options.h is misconfigured.\n#endif\n\n// ABSL_HAVE_STD_ORDERING\n//\n// Checks whether C++20 std::{partial,weak,strong}_ordering are available.\n//\n// __cpp_lib_three_way_comparison is missing on libc++\n// (https://github.com/llvm/llvm-project/issues/73953) so treat it as defined\n// when building in C++20 mode.\n#ifdef ABSL_HAVE_STD_ORDERING\n#error \"ABSL_HAVE_STD_ORDERING cannot be directly set.\"\n#elif (defined(__cpp_lib_three_way_comparison) &&    \\\n       __cpp_lib_three_way_comparison >= 201907L) || \\\n    (defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&        \\\n     ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L)\n#define ABSL_HAVE_STD_ORDERING 1\n#endif\n\n// ABSL_USES_STD_ORDERING\n//\n// Indicates whether absl::{partial,weak,strong}_ordering are aliases for the\n// std:: ordering types.\n#if !defined(ABSL_OPTION_USE_STD_ORDERING)\n#error options.h is misconfigured.\n#elif ABSL_OPTION_USE_STD_ORDERING == 0 || \\\n    (ABSL_OPTION_USE_STD_ORDERING == 2 && !defined(ABSL_HAVE_STD_ORDERING))\n#undef ABSL_USES_STD_ORDERING\n#elif ABSL_OPTION_USE_STD_ORDERING == 1 || \\\n    (ABSL_OPTION_USE_STD_ORDERING == 2 && defined(ABSL_HAVE_STD_ORDERING))\n#define ABSL_USES_STD_ORDERING 1\n#else\n#error options.h is misconfigured.\n#endif\n\n// ABSL_INTERNAL_MANGLED_NS\n// ABSL_INTERNAL_MANGLED_BACKREFERENCE\n//\n// Internal macros for building up mangled names in our internal fork of CCTZ.\n// This implementation detail is only needed and provided for the MSVC build.\n//\n// These macros both expand to string literals.  ABSL_INTERNAL_MANGLED_NS is\n// the mangled spelling of the `absl` namespace, and\n// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing\n// the proper count to skip past the CCTZ fork namespace names.  (This number\n// is one larger when there is an inline namespace name to skip.)\n#if defined(_MSC_VER)\n#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0\n#define ABSL_INTERNAL_MANGLED_NS \"absl\"\n#define ABSL_INTERNAL_MANGLED_BACKREFERENCE \"5\"\n#else\n#define ABSL_INTERNAL_MANGLED_NS \\\n  ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) \"@absl\"\n#define ABSL_INTERNAL_MANGLED_BACKREFERENCE \"6\"\n#endif\n#endif\n\n// ABSL_DLL\n//\n// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`\n// so we can annotate symbols appropriately as being exported. When used in\n// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so\n// that consumers know the symbol is defined inside the DLL. In all other cases,\n// the macro expands to nothing.\n#if defined(_MSC_VER)\n#if defined(ABSL_BUILD_DLL)\n#define ABSL_DLL __declspec(dllexport)\n#elif defined(ABSL_CONSUME_DLL)\n#define ABSL_DLL __declspec(dllimport)\n#else\n#define ABSL_DLL\n#endif\n#else\n#define ABSL_DLL\n#endif  // defined(_MSC_VER)\n\n#if defined(_MSC_VER)\n#if defined(ABSL_BUILD_TEST_DLL)\n#define ABSL_TEST_DLL __declspec(dllexport)\n#elif defined(ABSL_CONSUME_TEST_DLL)\n#define ABSL_TEST_DLL __declspec(dllimport)\n#else\n#define ABSL_TEST_DLL\n#endif\n#else\n#define ABSL_TEST_DLL\n#endif  // defined(_MSC_VER)\n\n// ABSL_HAVE_MEMORY_SANITIZER\n//\n// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of\n// a compiler instrumentation module and a run-time library.\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n#error \"ABSL_HAVE_MEMORY_SANITIZER cannot be directly set.\"\n#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)\n#define ABSL_HAVE_MEMORY_SANITIZER 1\n#endif\n\n// ABSL_HAVE_THREAD_SANITIZER\n//\n// ThreadSanitizer (TSan) is a fast data race detector.\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n#error \"ABSL_HAVE_THREAD_SANITIZER cannot be directly set.\"\n#elif defined(__SANITIZE_THREAD__)\n#define ABSL_HAVE_THREAD_SANITIZER 1\n#elif ABSL_HAVE_FEATURE(thread_sanitizer)\n#define ABSL_HAVE_THREAD_SANITIZER 1\n#endif\n\n// ABSL_HAVE_ADDRESS_SANITIZER\n//\n// AddressSanitizer (ASan) is a fast memory error detector.\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n#error \"ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set.\"\n#elif defined(__SANITIZE_ADDRESS__)\n#define ABSL_HAVE_ADDRESS_SANITIZER 1\n#elif ABSL_HAVE_FEATURE(address_sanitizer)\n#define ABSL_HAVE_ADDRESS_SANITIZER 1\n#endif\n\n// ABSL_HAVE_HWADDRESS_SANITIZER\n//\n// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan\n// memory error detector which can use CPU features like ARM TBI, Intel LAM or\n// AMD UAI.\n#ifdef ABSL_HAVE_HWADDRESS_SANITIZER\n#error \"ABSL_HAVE_HWADDRESS_SANITIZER cannot be directly set.\"\n#elif defined(__SANITIZE_HWADDRESS__)\n#define ABSL_HAVE_HWADDRESS_SANITIZER 1\n#elif ABSL_HAVE_FEATURE(hwaddress_sanitizer)\n#define ABSL_HAVE_HWADDRESS_SANITIZER 1\n#endif\n\n// ABSL_HAVE_DATAFLOW_SANITIZER\n//\n// Dataflow Sanitizer (or DFSAN) is a generalised dynamic data flow analysis.\n#ifdef ABSL_HAVE_DATAFLOW_SANITIZER\n#error \"ABSL_HAVE_DATAFLOW_SANITIZER cannot be directly set.\"\n#elif defined(DATAFLOW_SANITIZER)\n// GCC provides no method for detecting the presence of the standalone\n// DataFlowSanitizer (-fsanitize=dataflow), so GCC users of -fsanitize=dataflow\n// should also use -DDATAFLOW_SANITIZER.\n#define ABSL_HAVE_DATAFLOW_SANITIZER 1\n#elif ABSL_HAVE_FEATURE(dataflow_sanitizer)\n#define ABSL_HAVE_DATAFLOW_SANITIZER 1\n#endif\n\n// ABSL_HAVE_LEAK_SANITIZER\n//\n// LeakSanitizer (or lsan) is a detector of memory leaks.\n// https://clang.llvm.org/docs/LeakSanitizer.html\n// https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer\n//\n// The macro ABSL_HAVE_LEAK_SANITIZER can be used to detect at compile-time\n// whether the LeakSanitizer is potentially available. However, just because the\n// LeakSanitizer is available does not mean it is active. Use the\n// always-available run-time interface in //absl/debugging/leak_check.h for\n// interacting with LeakSanitizer.\n#ifdef ABSL_HAVE_LEAK_SANITIZER\n#error \"ABSL_HAVE_LEAK_SANITIZER cannot be directly set.\"\n#elif defined(LEAK_SANITIZER)\n// GCC provides no method for detecting the presence of the standalone\n// LeakSanitizer (-fsanitize=leak), so GCC users of -fsanitize=leak should also\n// use -DLEAK_SANITIZER.\n#define ABSL_HAVE_LEAK_SANITIZER 1\n// Clang standalone LeakSanitizer (-fsanitize=leak)\n#elif ABSL_HAVE_FEATURE(leak_sanitizer)\n#define ABSL_HAVE_LEAK_SANITIZER 1\n#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && !defined(_WIN32)\n// GCC or Clang using the LeakSanitizer integrated into AddressSanitizer.\n#define ABSL_HAVE_LEAK_SANITIZER 1\n#endif\n\n// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION\n//\n// Deprecated: always defined to 1.\n// Class template argument deduction is a language feature added in C++17,\n// which means all versions of C++ supported by Abseil have it.\n#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION\n#error \"ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set.\"\n#else\n#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1\n#endif\n\n// `ABSL_INTERNAL_HAS_RTTI` determines whether abseil is being compiled with\n// RTTI support.\n#ifdef ABSL_INTERNAL_HAS_RTTI\n#error ABSL_INTERNAL_HAS_RTTI cannot be directly set\n#elif ABSL_HAVE_FEATURE(cxx_rtti)\n#define ABSL_INTERNAL_HAS_RTTI 1\n#elif defined(__GNUC__) && defined(__GXX_RTTI)\n#define ABSL_INTERNAL_HAS_RTTI 1\n#elif defined(_MSC_VER) && defined(_CPPRTTI)\n#define ABSL_INTERNAL_HAS_RTTI 1\n#elif !defined(__GNUC__) && !defined(_MSC_VER)\n// Unknown compiler, default to RTTI\n#define ABSL_INTERNAL_HAS_RTTI 1\n#endif\n\n// `ABSL_INTERNAL_HAS_CXA_DEMANGLE` determines whether `abi::__cxa_demangle` is\n// available.\n#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE\n#error ABSL_INTERNAL_HAS_CXA_DEMANGLE cannot be directly set\n#elif defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))\n#undef ABSL_INTERNAL_HAS_CXA_DEMANGLE\n#elif defined(__GNUC__)\n#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1\n#elif defined(__clang__) && !defined(_MSC_VER)\n#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1\n#endif\n\n// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support.\n// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of\n// which architectures support the various x86 instruction sets.\n#ifdef ABSL_INTERNAL_HAVE_SSE\n#error ABSL_INTERNAL_HAVE_SSE cannot be directly set\n#elif defined(__SSE__)\n#define ABSL_INTERNAL_HAVE_SSE 1\n#elif (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)) && \\\n    !defined(_M_ARM64EC)\n// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 1\n// indicates that at least SSE was targeted with the /arch:SSE option.\n// All x86-64 processors support SSE, so support can be assumed.\n// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros\n#define ABSL_INTERNAL_HAVE_SSE 1\n#endif\n\n// ABSL_INTERNAL_HAVE_SSE2 is used for compile-time detection of SSE2 support.\n// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of\n// which architectures support the various x86 instruction sets.\n#ifdef ABSL_INTERNAL_HAVE_SSE2\n#error ABSL_INTERNAL_HAVE_SSE2 cannot be directly set\n#elif defined(__SSE2__)\n#define ABSL_INTERNAL_HAVE_SSE2 1\n#elif (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) && \\\n    !defined(_M_ARM64EC)\n// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 2\n// indicates that at least SSE2 was targeted with the /arch:SSE2 option.\n// All x86-64 processors support SSE2, so support can be assumed.\n// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros\n#define ABSL_INTERNAL_HAVE_SSE2 1\n#endif\n\n// ABSL_INTERNAL_HAVE_SSSE3 is used for compile-time detection of SSSE3 support.\n// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of\n// which architectures support the various x86 instruction sets.\n//\n// MSVC does not have a mode that targets SSSE3 at compile-time. To use SSSE3\n// with MSVC requires either assuming that the code will only every run on CPUs\n// that support SSSE3, otherwise __cpuid() can be used to detect support at\n// runtime and fallback to a non-SSSE3 implementation when SSSE3 is unsupported\n// by the CPU.\n#ifdef ABSL_INTERNAL_HAVE_SSSE3\n#error ABSL_INTERNAL_HAVE_SSSE3 cannot be directly set\n#elif defined(__SSSE3__)\n#define ABSL_INTERNAL_HAVE_SSSE3 1\n#endif\n\n// ABSL_INTERNAL_HAVE_ARM_NEON is used for compile-time detection of NEON (ARM\n// SIMD).\n//\n// If __CUDA_ARCH__ is defined, then we are compiling CUDA code in device mode.\n// In device mode, NEON intrinsics are not available, regardless of host\n// platform.\n// https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code\n#ifdef ABSL_INTERNAL_HAVE_ARM_NEON\n#error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set\n#elif defined(__ARM_NEON) && !(defined(__NVCC__) && defined(__CUDACC__))\n#define ABSL_INTERNAL_HAVE_ARM_NEON 1\n#endif\n\n#if ABSL_HAVE_BUILTIN(__builtin_LINE) && ABSL_HAVE_BUILTIN(__builtin_FILE)\n#define ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE 1\n#elif defined(__GNUC__) && !defined(__clang__) && 5 <= __GNUC__ && __GNUC__ < 10\n#define ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE 1\n#elif defined(_MSC_VER) && _MSC_VER >= 1926\n#define ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE 1\n#endif\n\n// ABSL_HAVE_CONSTANT_EVALUATED is used for compile-time detection of\n// constant evaluation support through `absl::is_constant_evaluated`.\n#ifdef ABSL_HAVE_CONSTANT_EVALUATED\n#error ABSL_HAVE_CONSTANT_EVALUATED cannot be directly set\n#endif\n#ifdef __cpp_lib_is_constant_evaluated\n#define ABSL_HAVE_CONSTANT_EVALUATED 1\n#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)\n#define ABSL_HAVE_CONSTANT_EVALUATED 1\n#endif\n\n// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr\n// for different C++ versions.\n//\n// These macros are an implementation detail and will be unconditionally removed\n// once the minimum supported C++ version catches up to a given version.\n//\n// For this reason, this symbol is considered INTERNAL and code outside of\n// Abseil must not use it.\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L\n#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr\n#else\n#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17\n#endif\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr\n#else\n#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20\n#endif\n\n// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros\n// into an integer that can be compared against.\n#ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION\n#error ABSL_INTERNAL_EMSCRIPTEN_VERSION cannot be directly set\n#endif\n#ifdef __EMSCRIPTEN__\n#include <emscripten/version.h>\n#ifdef __EMSCRIPTEN_major__\n#if __EMSCRIPTEN_minor__ >= 1000\n#error __EMSCRIPTEN_minor__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION\n#endif\n#if __EMSCRIPTEN_tiny__ >= 1000\n#error __EMSCRIPTEN_tiny__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION\n#endif\n#define ABSL_INTERNAL_EMSCRIPTEN_VERSION                              \\\n  ((__EMSCRIPTEN_major__) * 1000000 + (__EMSCRIPTEN_minor__) * 1000 + \\\n   (__EMSCRIPTEN_tiny__))\n#endif\n#endif\n\n#endif  // ABSL_BASE_CONFIG_H_\n"
  },
  {
    "path": "absl/base/config_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/config.h\"\n\n#include <cstdint>\n\n#include \"gtest/gtest.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n\nnamespace {\n\nTEST(ConfigTest, Endianness) {\n  union {\n    uint32_t value;\n    uint8_t data[sizeof(uint32_t)];\n  } number;\n  number.data[0] = 0x00;\n  number.data[1] = 0x01;\n  number.data[2] = 0x02;\n  number.data[3] = 0x03;\n#if defined(ABSL_IS_LITTLE_ENDIAN) && defined(ABSL_IS_BIG_ENDIAN)\n#error Both ABSL_IS_LITTLE_ENDIAN and ABSL_IS_BIG_ENDIAN are defined\n#elif defined(ABSL_IS_LITTLE_ENDIAN)\n  EXPECT_EQ(UINT32_C(0x03020100), number.value);\n#elif defined(ABSL_IS_BIG_ENDIAN)\n  EXPECT_EQ(UINT32_C(0x00010203), number.value);\n#else\n#error Unknown endianness\n#endif\n}\n\n#if defined(ABSL_HAVE_THREAD_LOCAL)\nTEST(ConfigTest, ThreadLocal) {\n  static thread_local int mine_mine_mine = 16;\n  EXPECT_EQ(16, mine_mine_mine);\n  {\n    absl::synchronization_internal::ThreadPool pool(1);\n    pool.Schedule([&] {\n      EXPECT_EQ(16, mine_mine_mine);\n      mine_mine_mine = 32;\n      EXPECT_EQ(32, mine_mine_mine);\n    });\n  }\n  EXPECT_EQ(16, mine_mine_mine);\n}\n#endif\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/const_init.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// kConstInit\n// -----------------------------------------------------------------------------\n//\n// A constructor tag used to mark an object as safe for use as a global\n// variable, avoiding the usual lifetime issues that can affect globals.\n\n#ifndef ABSL_BASE_CONST_INIT_H_\n#define ABSL_BASE_CONST_INIT_H_\n\n#include \"absl/base/config.h\"\n\n// In general, objects with static storage duration (such as global variables)\n// can trigger tricky object lifetime situations.  Attempting to access them\n// from the constructors or destructors of other global objects can result in\n// undefined behavior, unless their constructors and destructors are designed\n// with this issue in mind.\n//\n// The normal way to deal with this issue in C++11 is to use constant\n// initialization and trivial destructors.\n//\n// Constant initialization is guaranteed to occur before any other code\n// executes.  Constructors that are declared 'constexpr' are eligible for\n// constant initialization.  You can annotate a variable declaration with the\n// ABSL_CONST_INIT macro to express this intent.  For compilers that support\n// it, this annotation will cause a compilation error for declarations that\n// aren't subject to constant initialization (perhaps because a runtime value\n// was passed as a constructor argument).\n//\n// On program shutdown, lifetime issues can be avoided on global objects by\n// ensuring that they contain  trivial destructors.  A class has a trivial\n// destructor unless it has a user-defined destructor, a virtual method or base\n// class, or a data member or base class with a non-trivial destructor of its\n// own.  Objects with static storage duration and a trivial destructor are not\n// cleaned up on program shutdown, and are thus safe to access from other code\n// running during shutdown.\n//\n// For a few core Abseil classes, we make a best effort to allow for safe global\n// instances, even though these classes have non-trivial destructors.  These\n// objects can be created with the absl::kConstInit tag.  For example:\n//   ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit);\n//\n// The line above declares a global variable of type absl::Mutex which can be\n// accessed at any point during startup or shutdown.  global_mutex's destructor\n// will still run, but will not invalidate the object.  Note that C++ specifies\n// that accessing an object after its destructor has run results in undefined\n// behavior, but this pattern works on the toolchains we support.\n//\n// The absl::kConstInit tag should only be used to define objects with static\n// or thread_local storage duration.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nenum ConstInitType {\n  kConstInit,\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_CONST_INIT_H_\n"
  },
  {
    "path": "absl/base/dynamic_annotations.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file defines dynamic annotations for use with dynamic analysis tool\n// such as valgrind, PIN, etc.\n//\n// Dynamic annotation is a source code annotation that affects the generated\n// code (that is, the annotation is not a comment). Each such annotation is\n// attached to a particular instruction and/or to a particular object (address)\n// in the program.\n//\n// The annotations that should be used by users are macros in all upper-case\n// (e.g., ABSL_ANNOTATE_THREAD_NAME).\n//\n// Actual implementation of these macros may differ depending on the dynamic\n// analysis tool being used.\n//\n// This file supports the following configurations:\n// - Dynamic Annotations enabled (with static thread-safety warnings disabled).\n//   In this case, macros expand to functions implemented by Thread Sanitizer,\n//   when building with TSan. When not provided an external implementation,\n//   dynamic_annotations.cc provides no-op implementations.\n//\n// - Static Clang thread-safety warnings enabled.\n//   When building with a Clang compiler that supports thread-safety warnings,\n//   a subset of annotations can be statically-checked at compile-time. We\n//   expand these macros to static-inline functions that can be analyzed for\n//   thread-safety, but afterwards elided when building the final binary.\n//\n// - All annotations are disabled.\n//   If neither Dynamic Annotations nor Clang thread-safety warnings are\n//   enabled, then all annotation-macros expand to empty.\n\n#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_\n#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#ifdef __cplusplus\n#include \"absl/base/macros.h\"\n#endif\n\n#ifdef ABSL_HAVE_HWADDRESS_SANITIZER\n#include <sanitizer/hwasan_interface.h>\n#endif\n\n// TODO(rogeeff): Remove after the backward compatibility period.\n#include \"absl/base/internal/dynamic_annotations.h\"  // IWYU pragma: export\n\n// -------------------------------------------------------------------------\n// Decide which features are enabled.\n\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n\n#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1\n#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1\n#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1\n#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0\n#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1\n\n#else\n\n#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0\n#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0\n#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0\n\n// Clang provides limited support for static thread-safety analysis through a\n// feature called Annotalysis. We configure macro-definitions according to\n// whether Annotalysis support is available. When running in opt-mode, GCC\n// will issue a warning, if these attributes are compiled. Only include them\n// when compiling using Clang.\n\n#if defined(__clang__)\n#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1\n#if !defined(SWIG)\n#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1\n#endif\n#else\n#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0\n#endif\n\n// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.\n#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \\\n  ABSL_INTERNAL_ANNOTALYSIS_ENABLED\n\n#endif  // ABSL_HAVE_THREAD_SANITIZER\n\n#ifdef __cplusplus\n#define ABSL_INTERNAL_BEGIN_EXTERN_C extern \"C\" {\n#define ABSL_INTERNAL_END_EXTERN_C }  // extern \"C\"\n#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F\n#define ABSL_INTERNAL_STATIC_INLINE inline\n#else\n#define ABSL_INTERNAL_BEGIN_EXTERN_C  // empty\n#define ABSL_INTERNAL_END_EXTERN_C    // empty\n#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F\n#define ABSL_INTERNAL_STATIC_INLINE static inline\n#endif\n\n// -------------------------------------------------------------------------\n// Define race annotations.\n\n#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1\n// Some of the symbols used in this section (e.g. AnnotateBenignRaceSized) are\n// defined by the compiler-based sanitizer implementation, not by the Abseil\n// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.\n\n// -------------------------------------------------------------\n// Annotations that suppress errors. It is usually better to express the\n// program's synchronization using the other annotations, but these can be used\n// when all else fails.\n\n// Report that we may have a benign race at `pointer`, with size\n// \"sizeof(*(pointer))\". `pointer` must be a non-void* pointer. Insert at the\n// point where `pointer` has been allocated, preferably close to the point\n// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.\n#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized)  \\\n  (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)\n\n// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to\n// the memory range [`address`, `address`+`size`).\n#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized)              \\\n  (__FILE__, __LINE__, address, size, description)\n\n// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.\n// This annotation could be useful if you want to skip expensive race analysis\n// during some period of program execution, e.g. during initialization.\n#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable)        \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \\\n  (__FILE__, __LINE__, enable)\n\n// -------------------------------------------------------------\n// Annotations useful for debugging.\n\n// Report the current thread `name` to a race detector.\n#define ABSL_ANNOTATE_THREAD_NAME(name) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)\n\n// -------------------------------------------------------------\n// Annotations useful when implementing locks. They are not normally needed by\n// modules that merely use locks. The `lock` argument is a pointer to the lock\n// object.\n\n// Report that a lock has been created at address `lock`.\n#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)\n\n// Report that a linker initialized lock has been created at address `lock`.\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock)          \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \\\n  (__FILE__, __LINE__, lock)\n#else\n#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \\\n  ABSL_ANNOTATE_RWLOCK_CREATE(lock)\n#endif\n\n// Report that the lock at address `lock` is about to be destroyed.\n#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)\n\n// Report that the lock at address `lock` has been acquired.\n// `is_w`=1 for writer lock, `is_w`=0 for reader lock.\n#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)     \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \\\n  (__FILE__, __LINE__, lock, is_w)\n\n// Report that the lock at address `lock` is about to be released.\n// `is_w`=1 for writer lock, `is_w`=0 for reader lock.\n#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w)     \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \\\n  (__FILE__, __LINE__, lock, is_w)\n\n// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.\n#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description)      \\\n  namespace {                                                          \\\n  class static_var##_annotator {                                       \\\n   public:                                                             \\\n    static_var##_annotator() {                                         \\\n      ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \\\n                                      #static_var \": \" description);   \\\n    }                                                                  \\\n  };                                                                   \\\n  static static_var##_annotator the##static_var##_annotator;           \\\n  }  // namespace\n\n// Function prototypes of annotations provided by the compiler-based sanitizer\n// implementation.\nABSL_INTERNAL_BEGIN_EXTERN_C\nvoid AnnotateRWLockCreate(const char* file, int line,\n                          const volatile void* lock);\nvoid AnnotateRWLockCreateStatic(const char* file, int line,\n                                const volatile void* lock);\nvoid AnnotateRWLockDestroy(const char* file, int line,\n                           const volatile void* lock);\nvoid AnnotateRWLockAcquired(const char* file, int line,\n                            const volatile void* lock, long is_w);  // NOLINT\nvoid AnnotateRWLockReleased(const char* file, int line,\n                            const volatile void* lock, long is_w);  // NOLINT\nvoid AnnotateBenignRace(const char* file, int line,\n                        const volatile void* address, const char* description);\nvoid AnnotateBenignRaceSized(const char* file, int line,\n                             const volatile void* address, size_t size,\n                             const char* description);\nvoid AnnotateThreadName(const char* file, int line, const char* name);\nvoid AnnotateEnableRaceDetection(const char* file, int line, int enable);\nABSL_INTERNAL_END_EXTERN_C\n\n#else  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0\n\n#define ABSL_ANNOTATE_RWLOCK_CREATE(lock)                            // empty\n#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock)                     // empty\n#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock)                           // empty\n#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)                    // empty\n#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w)                    // empty\n#define ABSL_ANNOTATE_BENIGN_RACE(address, description)              // empty\n#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description)  // empty\n#define ABSL_ANNOTATE_THREAD_NAME(name)                              // empty\n#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable)                  // empty\n#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description)    // empty\n\n#endif  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED\n\n// -------------------------------------------------------------------------\n// Define memory annotations.\n\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n\n#include <sanitizer/msan_interface.h>\n\n#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \\\n  __msan_unpoison(address, size)\n\n#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \\\n  __msan_allocated_memory(address, size)\n\n#else  // !defined(ABSL_HAVE_MEMORY_SANITIZER)\n\n#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size)    // empty\n#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size)  // empty\n\n#endif  // ABSL_HAVE_MEMORY_SANITIZER\n\n// -------------------------------------------------------------------------\n// Define IGNORE_READS_BEGIN/_END attributes.\n\n#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n\n#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \\\n  __attribute((exclusive_lock_function(\"*\")))\n#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \\\n  __attribute((unlock_function(\"*\")))\n\n#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n\n#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty\n#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty\n\n#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n\n// -------------------------------------------------------------------------\n// Define IGNORE_READS_BEGIN/_END annotations.\n\n#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1\n// Some of the symbols used in this section (e.g. AnnotateIgnoreReadsBegin) are\n// defined by the compiler-based implementation, not by the Abseil\n// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.\n\n// Request the analysis tool to ignore all reads in the current thread until\n// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey\n// reads, while still checking other reads and all writes.\n// See also ABSL_ANNOTATE_UNPROTECTED_READ.\n#define ABSL_ANNOTATE_IGNORE_READS_BEGIN()              \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin) \\\n  (__FILE__, __LINE__)\n\n// Stop ignoring reads.\n#define ABSL_ANNOTATE_IGNORE_READS_END()              \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \\\n  (__FILE__, __LINE__)\n\n// Function prototypes of annotations provided by the compiler-based sanitizer\n// implementation.\nABSL_INTERNAL_BEGIN_EXTERN_C\nvoid AnnotateIgnoreReadsBegin(const char* file, int line)\n    ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;\nvoid AnnotateIgnoreReadsEnd(const char* file,\n                            int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;\nABSL_INTERNAL_END_EXTERN_C\n\n#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)\n\n// When Annotalysis is enabled without Dynamic Annotations, the use of\n// static-inline functions allows the annotations to be read at compile-time,\n// while still letting the compiler elide the functions from the final build.\n//\n// TODO(delesley) -- The exclusive lock here ignores writes as well, but\n// allows IGNORE_READS_AND_WRITES to work properly.\n\n#define ABSL_ANNOTATE_IGNORE_READS_BEGIN()                          \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(                                      \\\n      ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \\\n  ()\n\n#define ABSL_ANNOTATE_IGNORE_READS_END()                          \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(                                    \\\n      ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \\\n  ()\n\nABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(\n    AbslInternalAnnotateIgnoreReadsBegin)()\n    ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}\n\nABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(\n    AbslInternalAnnotateIgnoreReadsEnd)()\n    ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}\n\n#else\n\n#define ABSL_ANNOTATE_IGNORE_READS_BEGIN()  // empty\n#define ABSL_ANNOTATE_IGNORE_READS_END()    // empty\n\n#endif\n\n// -------------------------------------------------------------------------\n// Define IGNORE_WRITES_BEGIN/_END annotations.\n\n#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1\n\n// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.\n#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)\n\n// Stop ignoring writes.\n#define ABSL_ANNOTATE_IGNORE_WRITES_END() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)\n\n// Function prototypes of annotations provided by the compiler-based sanitizer\n// implementation.\nABSL_INTERNAL_BEGIN_EXTERN_C\nvoid AnnotateIgnoreWritesBegin(const char* file, int line);\nvoid AnnotateIgnoreWritesEnd(const char* file, int line);\nABSL_INTERNAL_END_EXTERN_C\n\n#else\n\n#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN()  // empty\n#define ABSL_ANNOTATE_IGNORE_WRITES_END()    // empty\n\n#endif\n\n// -------------------------------------------------------------------------\n// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more\n// primitive annotations defined above.\n//\n//     Instead of doing\n//        ABSL_ANNOTATE_IGNORE_READS_BEGIN();\n//        ... = x;\n//        ABSL_ANNOTATE_IGNORE_READS_END();\n//     one can use\n//        ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);\n\n#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)\n\n// Start ignoring all memory accesses (both reads and writes).\n#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \\\n  do {                                                \\\n    ABSL_ANNOTATE_IGNORE_READS_BEGIN();               \\\n    ABSL_ANNOTATE_IGNORE_WRITES_BEGIN();              \\\n  } while (0)\n\n// Stop ignoring both reads and writes.\n#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \\\n  do {                                              \\\n    ABSL_ANNOTATE_IGNORE_WRITES_END();              \\\n    ABSL_ANNOTATE_IGNORE_READS_END();               \\\n  } while (0)\n\n#ifdef __cplusplus\n// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.\n#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \\\n  absl::base_internal::AnnotateUnprotectedRead(x)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\ntemplate <typename T>\ninline T AnnotateUnprotectedRead(const volatile T& x) {  // NOLINT\n  ABSL_ANNOTATE_IGNORE_READS_BEGIN();\n  T res = x;\n  ABSL_ANNOTATE_IGNORE_READS_END();\n  return res;\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif\n\n#else\n\n#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN()  // empty\n#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END()    // empty\n#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)\n\n#endif\n\n// -------------------------------------------------------------------------\n// Address sanitizer annotations\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n// Describe the current state of a contiguous container such as e.g.\n// std::vector or std::string. For more details see\n// sanitizer/common_interface_defs.h, which is provided by the compiler.\n#include <sanitizer/common_interface_defs.h>\n\n#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \\\n  __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)\n#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \\\n  struct {                                   \\\n    alignas(8) char x[8];                    \\\n  } name\n\n#else\n\n#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)  // empty\n#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, \"\")\n\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n\n// -------------------------------------------------------------------------\n// HWAddress sanitizer annotations\n\n#ifdef __cplusplus\nnamespace absl {\n#ifdef ABSL_HAVE_HWADDRESS_SANITIZER\n// Under HWASAN changes the tag of the pointer.\ntemplate <typename T>\nT* HwasanTagPointer(T* ptr, uintptr_t tag) {\n  return reinterpret_cast<T*>(__hwasan_tag_pointer(ptr, tag));\n}\n#else\ntemplate <typename T>\nT* HwasanTagPointer(T* ptr, uintptr_t) {\n  return ptr;\n}\n#endif\n}  // namespace absl\n#endif\n\n// -------------------------------------------------------------------------\n// Undefine the macros intended only for this file.\n\n#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED\n#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_BEGIN_EXTERN_C\n#undef ABSL_INTERNAL_END_EXTERN_C\n#undef ABSL_INTERNAL_STATIC_INLINE\n\n#endif  // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_\n"
  },
  {
    "path": "absl/base/exception_safety_testing_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/exception_safety_testing.h\"\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n\n#include <cstddef>\n#include <exception>\n#include <iostream>\n#include <list>\n#include <type_traits>\n#include <vector>\n\n#include \"gtest/gtest-spi.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/memory/memory.h\"\n\nnamespace testing {\n\nnamespace {\n\nusing ::testing::exceptions_internal::SetCountdown;\nusing ::testing::exceptions_internal::TestException;\nusing ::testing::exceptions_internal::UnsetCountdown;\n\n// EXPECT_NO_THROW can't inspect the thrown inspection in general.\ntemplate <typename F>\nvoid ExpectNoThrow(const F& f) {\n  try {\n    f();\n  } catch (const TestException& e) {\n    ADD_FAILURE() << \"Unexpected exception thrown from \" << e.what();\n  }\n}\n\nTEST(ThrowingValueTest, Throws) {\n  SetCountdown();\n  EXPECT_THROW(ThrowingValue<> bomb, TestException);\n\n  // It's not guaranteed that every operator only throws *once*.  The default\n  // ctor only throws once, though, so use it to make sure we only throw when\n  // the countdown hits 0\n  SetCountdown(2);\n  ExpectNoThrow([]() { ThrowingValue<> bomb; });\n  ExpectNoThrow([]() { ThrowingValue<> bomb; });\n  EXPECT_THROW(ThrowingValue<> bomb, TestException);\n\n  UnsetCountdown();\n}\n\n// Tests that an operation throws when the countdown is at 0, doesn't throw when\n// the countdown doesn't hit 0, and doesn't modify the state of the\n// ThrowingValue if it throws\ntemplate <typename F>\nvoid TestOp(const F& f) {\n  ExpectNoThrow(f);\n\n  SetCountdown();\n  EXPECT_THROW(f(), TestException);\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, ThrowingCtors) {\n  ThrowingValue<> bomb;\n\n  TestOp([]() { ThrowingValue<> bomb(1); });\n  TestOp([&]() { ThrowingValue<> bomb1 = bomb; });\n  TestOp([&]() { ThrowingValue<> bomb1 = std::move(bomb); });\n}\n\nTEST(ThrowingValueTest, ThrowingAssignment) {\n  ThrowingValue<> bomb, bomb1;\n\n  TestOp([&]() { bomb = bomb1; });\n  TestOp([&]() { bomb = std::move(bomb1); });\n\n  // Test that when assignment throws, the assignment should fail (lhs != rhs)\n  // and strong guarantee fails (lhs != lhs_copy).\n  {\n    ThrowingValue<> lhs(39), rhs(42);\n    ThrowingValue<> lhs_copy(lhs);\n    SetCountdown();\n    EXPECT_THROW(lhs = rhs, TestException);\n    UnsetCountdown();\n    EXPECT_NE(lhs, rhs);\n    EXPECT_NE(lhs_copy, lhs);\n  }\n  {\n    ThrowingValue<> lhs(39), rhs(42);\n    ThrowingValue<> lhs_copy(lhs), rhs_copy(rhs);\n    SetCountdown();\n    EXPECT_THROW(lhs = std::move(rhs), TestException);\n    UnsetCountdown();\n    EXPECT_NE(lhs, rhs_copy);\n    EXPECT_NE(lhs_copy, lhs);\n  }\n}\n\nTEST(ThrowingValueTest, ThrowingComparisons) {\n  ThrowingValue<> bomb1, bomb2;\n  TestOp([&]() { return bomb1 == bomb2; });\n  TestOp([&]() { return bomb1 != bomb2; });\n  TestOp([&]() { return bomb1 < bomb2; });\n  TestOp([&]() { return bomb1 <= bomb2; });\n  TestOp([&]() { return bomb1 > bomb2; });\n  TestOp([&]() { return bomb1 >= bomb2; });\n}\n\nTEST(ThrowingValueTest, ThrowingArithmeticOps) {\n  ThrowingValue<> bomb1(1), bomb2(2);\n\n  TestOp([&bomb1]() { +bomb1; });\n  TestOp([&bomb1]() { -bomb1; });\n  TestOp([&bomb1]() { ++bomb1; });\n  TestOp([&bomb1]() { bomb1++; });\n  TestOp([&bomb1]() { --bomb1; });\n  TestOp([&bomb1]() { bomb1--; });\n\n  TestOp([&]() { bomb1 + bomb2; });\n  TestOp([&]() { bomb1 - bomb2; });\n  TestOp([&]() { bomb1* bomb2; });\n  TestOp([&]() { bomb1 / bomb2; });\n  TestOp([&]() { bomb1 << 1; });\n  TestOp([&]() { bomb1 >> 1; });\n}\n\nTEST(ThrowingValueTest, ThrowingLogicalOps) {\n  ThrowingValue<> bomb1, bomb2;\n\n  TestOp([&bomb1]() { !bomb1; });\n  TestOp([&]() { bomb1&& bomb2; });\n  TestOp([&]() { bomb1 || bomb2; });\n}\n\nTEST(ThrowingValueTest, ThrowingBitwiseOps) {\n  ThrowingValue<> bomb1, bomb2;\n\n  TestOp([&bomb1]() { ~bomb1; });\n  TestOp([&]() { bomb1 & bomb2; });\n  TestOp([&]() { bomb1 | bomb2; });\n  TestOp([&]() { bomb1 ^ bomb2; });\n}\n\nTEST(ThrowingValueTest, ThrowingCompoundAssignmentOps) {\n  ThrowingValue<> bomb1(1), bomb2(2);\n\n  TestOp([&]() { bomb1 += bomb2; });\n  TestOp([&]() { bomb1 -= bomb2; });\n  TestOp([&]() { bomb1 *= bomb2; });\n  TestOp([&]() { bomb1 /= bomb2; });\n  TestOp([&]() { bomb1 %= bomb2; });\n  TestOp([&]() { bomb1 &= bomb2; });\n  TestOp([&]() { bomb1 |= bomb2; });\n  TestOp([&]() { bomb1 ^= bomb2; });\n  TestOp([&]() { bomb1 *= bomb2; });\n}\n\nTEST(ThrowingValueTest, ThrowingStreamOps) {\n  ThrowingValue<> bomb;\n\n  TestOp([&]() {\n    std::istringstream stream;\n    stream >> bomb;\n  });\n  TestOp([&]() {\n    std::stringstream stream;\n    stream << bomb;\n  });\n}\n\n// Tests the operator<< of ThrowingValue by forcing ConstructorTracker to emit\n// a nonfatal failure that contains the string representation of the Thrower\nTEST(ThrowingValueTest, StreamOpsOutput) {\n  using ::testing::TypeSpec;\n  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);\n\n  // Test default spec list (kEverythingThrows)\n  EXPECT_NONFATAL_FAILURE(\n      {\n        using Thrower = ThrowingValue<TypeSpec{}>;\n        auto thrower = Thrower(123);\n        thrower.~Thrower();\n      },\n      \"ThrowingValue<>(123)\");\n\n  // Test with one item in spec list (kNoThrowCopy)\n  EXPECT_NONFATAL_FAILURE(\n      {\n        using Thrower = ThrowingValue<TypeSpec::kNoThrowCopy>;\n        auto thrower = Thrower(234);\n        thrower.~Thrower();\n      },\n      \"ThrowingValue<kNoThrowCopy>(234)\");\n\n  // Test with multiple items in spec list (kNoThrowMove, kNoThrowNew)\n  EXPECT_NONFATAL_FAILURE(\n      {\n        using Thrower =\n            ThrowingValue<TypeSpec::kNoThrowMove | TypeSpec::kNoThrowNew>;\n        auto thrower = Thrower(345);\n        thrower.~Thrower();\n      },\n      \"ThrowingValue<kNoThrowMove | kNoThrowNew>(345)\");\n\n  // Test with all items in spec list (kNoThrowCopy, kNoThrowMove, kNoThrowNew)\n  EXPECT_NONFATAL_FAILURE(\n      {\n        using Thrower = ThrowingValue<static_cast<TypeSpec>(-1)>;\n        auto thrower = Thrower(456);\n        thrower.~Thrower();\n      },\n      \"ThrowingValue<kNoThrowCopy | kNoThrowMove | kNoThrowNew>(456)\");\n}\n\ntemplate <typename F>\nvoid TestAllocatingOp(const F& f) {\n  ExpectNoThrow(f);\n\n  SetCountdown();\n  EXPECT_THROW(f(), exceptions_internal::TestBadAllocException);\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, ThrowingAllocatingOps) {\n  // make_unique calls unqualified operator new, so these exercise the\n  // ThrowingValue overloads.\n  TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>>(1); });\n  TestAllocatingOp([]() { return absl::make_unique<ThrowingValue<>[]>(2); });\n}\n\nTEST(ThrowingValueTest, NonThrowingMoveCtor) {\n  ThrowingValue<TypeSpec::kNoThrowMove> nothrow_ctor;\n\n  SetCountdown();\n  ExpectNoThrow([&nothrow_ctor]() {\n    ThrowingValue<TypeSpec::kNoThrowMove> nothrow1 = std::move(nothrow_ctor);\n  });\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, NonThrowingMoveAssign) {\n  ThrowingValue<TypeSpec::kNoThrowMove> nothrow_assign1, nothrow_assign2;\n\n  SetCountdown();\n  ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {\n    nothrow_assign1 = std::move(nothrow_assign2);\n  });\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, ThrowingCopyCtor) {\n  ThrowingValue<> tv;\n\n  TestOp([&]() { ThrowingValue<> tv_copy(tv); });\n}\n\nTEST(ThrowingValueTest, ThrowingCopyAssign) {\n  ThrowingValue<> tv1, tv2;\n\n  TestOp([&]() { tv1 = tv2; });\n}\n\nTEST(ThrowingValueTest, NonThrowingCopyCtor) {\n  ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_ctor;\n\n  SetCountdown();\n  ExpectNoThrow([&nothrow_ctor]() {\n    ThrowingValue<TypeSpec::kNoThrowCopy> nothrow1(nothrow_ctor);\n  });\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, NonThrowingCopyAssign) {\n  ThrowingValue<TypeSpec::kNoThrowCopy> nothrow_assign1, nothrow_assign2;\n\n  SetCountdown();\n  ExpectNoThrow([&nothrow_assign1, &nothrow_assign2]() {\n    nothrow_assign1 = nothrow_assign2;\n  });\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, ThrowingSwap) {\n  ThrowingValue<> bomb1, bomb2;\n  TestOp([&]() { std::swap(bomb1, bomb2); });\n}\n\nTEST(ThrowingValueTest, NonThrowingSwap) {\n  ThrowingValue<TypeSpec::kNoThrowMove> bomb1, bomb2;\n  ExpectNoThrow([&]() { std::swap(bomb1, bomb2); });\n}\n\nTEST(ThrowingValueTest, NonThrowingAllocation) {\n  ThrowingValue<TypeSpec::kNoThrowNew>* allocated;\n  ThrowingValue<TypeSpec::kNoThrowNew>* array;\n\n  ExpectNoThrow([&allocated]() {\n    allocated = new ThrowingValue<TypeSpec::kNoThrowNew>(1);\n    delete allocated;\n  });\n  ExpectNoThrow([&array]() {\n    array = new ThrowingValue<TypeSpec::kNoThrowNew>[2];\n    delete[] array;\n  });\n}\n\nTEST(ThrowingValueTest, NonThrowingDelete) {\n  auto* allocated = new ThrowingValue<>(1);\n  auto* array = new ThrowingValue<>[2];\n\n  SetCountdown();\n  ExpectNoThrow([allocated]() { delete allocated; });\n  SetCountdown();\n  ExpectNoThrow([array]() { delete[] array; });\n\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, NonThrowingPlacementDelete) {\n  constexpr int kArrayLen = 2;\n  // We intentionally create extra space to store the tag allocated by placement\n  // new[].\n  constexpr size_t kExtraSpaceLen = sizeof(size_t) * 2;\n\n  alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)];\n  alignas(ThrowingValue<>) unsigned char\n      array_buf[kExtraSpaceLen + sizeof(ThrowingValue<>[kArrayLen])];\n  auto* placed = new (&buf) ThrowingValue<>(1);\n  auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen];\n  auto* placed_array_end = reinterpret_cast<unsigned char*>(placed_array) +\n                           sizeof(ThrowingValue<>[kArrayLen]);\n  EXPECT_LE(placed_array_end, array_buf + sizeof(array_buf));\n\n  SetCountdown();\n  ExpectNoThrow([placed, &buf]() {\n    placed->~ThrowingValue<>();\n    ThrowingValue<>::operator delete(placed, &buf);\n  });\n\n  SetCountdown();\n  ExpectNoThrow([&, placed_array]() {\n    for (int i = 0; i < kArrayLen; ++i) placed_array[i].~ThrowingValue<>();\n    ThrowingValue<>::operator delete[](placed_array, &array_buf);\n  });\n\n  UnsetCountdown();\n}\n\nTEST(ThrowingValueTest, NonThrowingDestructor) {\n  auto* allocated = new ThrowingValue<>();\n\n  SetCountdown();\n  ExpectNoThrow([allocated]() { delete allocated; });\n  UnsetCountdown();\n}\n\nTEST(ThrowingBoolTest, ThrowingBool) {\n  ThrowingBool t = true;\n\n  // Test that it's contextually convertible to bool\n  if (t) {  // NOLINT(whitespace/empty_if_body)\n  }\n  EXPECT_TRUE(t);\n\n  TestOp([&]() { (void)!t; });\n}\n\nTEST(ThrowingAllocatorTest, MemoryManagement) {\n  // Just exercise the memory management capabilities under LSan to make sure we\n  // don't leak.\n  ThrowingAllocator<int> int_alloc;\n  int* ip = int_alloc.allocate(1);\n  int_alloc.deallocate(ip, 1);\n  int* i_array = int_alloc.allocate(2);\n  int_alloc.deallocate(i_array, 2);\n\n  ThrowingAllocator<ThrowingValue<>> tv_alloc;\n  ThrowingValue<>* ptr = tv_alloc.allocate(1);\n  tv_alloc.deallocate(ptr, 1);\n  ThrowingValue<>* tv_array = tv_alloc.allocate(2);\n  tv_alloc.deallocate(tv_array, 2);\n}\n\nTEST(ThrowingAllocatorTest, CallsGlobalNew) {\n  ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate> nothrow_alloc;\n  ThrowingValue<>* ptr;\n\n  SetCountdown();\n  // This will only throw if ThrowingValue::new is called.\n  ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });\n  nothrow_alloc.deallocate(ptr, 1);\n\n  UnsetCountdown();\n}\n\nTEST(ThrowingAllocatorTest, ThrowingConstructors) {\n  ThrowingAllocator<int> int_alloc;\n  int* ip = nullptr;\n\n  SetCountdown();\n  EXPECT_THROW(ip = int_alloc.allocate(1), TestException);\n  ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });\n\n  *ip = 1;\n  SetCountdown();\n  EXPECT_THROW(int_alloc.construct(ip, 2), TestException);\n  EXPECT_EQ(*ip, 1);\n  int_alloc.deallocate(ip, 1);\n\n  UnsetCountdown();\n}\n\nTEST(ThrowingAllocatorTest, NonThrowingConstruction) {\n  {\n    ThrowingAllocator<int, AllocSpec::kNoThrowAllocate> int_alloc;\n    int* ip = nullptr;\n\n    SetCountdown();\n    ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });\n\n    SetCountdown();\n    ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });\n\n    EXPECT_EQ(*ip, 2);\n    int_alloc.deallocate(ip, 1);\n\n    UnsetCountdown();\n  }\n\n  {\n    ThrowingAllocator<int> int_alloc;\n    int* ip = nullptr;\n    ExpectNoThrow([&]() { ip = int_alloc.allocate(1); });\n    ExpectNoThrow([&]() { int_alloc.construct(ip, 2); });\n    EXPECT_EQ(*ip, 2);\n    int_alloc.deallocate(ip, 1);\n  }\n\n  {\n    ThrowingAllocator<ThrowingValue<>, AllocSpec::kNoThrowAllocate>\n        nothrow_alloc;\n    ThrowingValue<>* ptr;\n\n    SetCountdown();\n    ExpectNoThrow([&]() { ptr = nothrow_alloc.allocate(1); });\n\n    SetCountdown();\n    ExpectNoThrow(\n        [&]() { nothrow_alloc.construct(ptr, 2, testing::nothrow_ctor); });\n\n    EXPECT_EQ(ptr->Get(), 2);\n    nothrow_alloc.destroy(ptr);\n    nothrow_alloc.deallocate(ptr, 1);\n\n    UnsetCountdown();\n  }\n\n  {\n    ThrowingAllocator<int> a;\n\n    SetCountdown();\n    ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = a; });\n\n    SetCountdown();\n    ExpectNoThrow([&]() { ThrowingAllocator<double> a1 = std::move(a); });\n\n    UnsetCountdown();\n  }\n}\n\nTEST(ThrowingAllocatorTest, ThrowingAllocatorConstruction) {\n  ThrowingAllocator<int> a;\n  TestOp([]() { ThrowingAllocator<int> a; });\n  TestOp([&]() { a.select_on_container_copy_construction(); });\n}\n\nTEST(ThrowingAllocatorTest, State) {\n  ThrowingAllocator<int> a1, a2;\n  EXPECT_NE(a1, a2);\n\n  auto a3 = a1;\n  EXPECT_EQ(a3, a1);\n  int* ip = a1.allocate(1);\n  EXPECT_EQ(a3, a1);\n  a3.deallocate(ip, 1);\n  EXPECT_EQ(a3, a1);\n}\n\nTEST(ThrowingAllocatorTest, InVector) {\n  std::vector<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> v;\n  for (int i = 0; i < 20; ++i) v.push_back({});\n  for (int i = 0; i < 20; ++i) v.pop_back();\n}\n\nTEST(ThrowingAllocatorTest, InList) {\n  std::list<ThrowingValue<>, ThrowingAllocator<ThrowingValue<>>> l;\n  for (int i = 0; i < 20; ++i) l.push_back({});\n  for (int i = 0; i < 20; ++i) l.pop_back();\n  for (int i = 0; i < 20; ++i) l.push_front({});\n  for (int i = 0; i < 20; ++i) l.pop_front();\n}\n\ntemplate <typename TesterInstance, typename = void>\nstruct NullaryTestValidator : public std::false_type {};\n\ntemplate <typename TesterInstance>\nstruct NullaryTestValidator<\n    TesterInstance,\n    absl::void_t<decltype(std::declval<TesterInstance>().Test())>>\n    : public std::true_type {};\n\ntemplate <typename TesterInstance>\nbool HasNullaryTest(const TesterInstance&) {\n  return NullaryTestValidator<TesterInstance>::value;\n}\n\nvoid DummyOp(void*) {}\n\ntemplate <typename TesterInstance, typename = void>\nstruct UnaryTestValidator : public std::false_type {};\n\ntemplate <typename TesterInstance>\nstruct UnaryTestValidator<\n    TesterInstance,\n    absl::void_t<decltype(std::declval<TesterInstance>().Test(DummyOp))>>\n    : public std::true_type {};\n\ntemplate <typename TesterInstance>\nbool HasUnaryTest(const TesterInstance&) {\n  return UnaryTestValidator<TesterInstance>::value;\n}\n\nTEST(ExceptionSafetyTesterTest, IncompleteTypesAreNotTestable) {\n  using T = exceptions_internal::UninitializedT;\n  auto op = [](T* t) {};\n  auto inv = [](T*) { return testing::AssertionSuccess(); };\n  auto fac = []() { return absl::make_unique<T>(); };\n\n  // Test that providing operation and inveriants still does not allow for the\n  // the invocation of .Test() and .Test(op) because it lacks a factory\n  auto without_fac =\n      testing::MakeExceptionSafetyTester().WithOperation(op).WithContracts(\n          inv, testing::strong_guarantee);\n  EXPECT_FALSE(HasNullaryTest(without_fac));\n  EXPECT_FALSE(HasUnaryTest(without_fac));\n\n  // Test that providing contracts and factory allows the invocation of\n  // .Test(op) but does not allow for .Test() because it lacks an operation\n  auto without_op = testing::MakeExceptionSafetyTester()\n                        .WithContracts(inv, testing::strong_guarantee)\n                        .WithFactory(fac);\n  EXPECT_FALSE(HasNullaryTest(without_op));\n  EXPECT_TRUE(HasUnaryTest(without_op));\n\n  // Test that providing operation and factory still does not allow for the\n  // the invocation of .Test() and .Test(op) because it lacks contracts\n  auto without_inv =\n      testing::MakeExceptionSafetyTester().WithOperation(op).WithFactory(fac);\n  EXPECT_FALSE(HasNullaryTest(without_inv));\n  EXPECT_FALSE(HasUnaryTest(without_inv));\n}\n\nstruct ExampleStruct {};\n\nstd::unique_ptr<ExampleStruct> ExampleFunctionFactory() {\n  return absl::make_unique<ExampleStruct>();\n}\n\nvoid ExampleFunctionOperation(ExampleStruct*) {}\n\ntesting::AssertionResult ExampleFunctionContract(ExampleStruct*) {\n  return testing::AssertionSuccess();\n}\n\nstruct {\n  std::unique_ptr<ExampleStruct> operator()() const {\n    return ExampleFunctionFactory();\n  }\n} example_struct_factory;\n\nstruct {\n  void operator()(ExampleStruct*) const {}\n} example_struct_operation;\n\nstruct {\n  testing::AssertionResult operator()(ExampleStruct* example_struct) const {\n    return ExampleFunctionContract(example_struct);\n  }\n} example_struct_contract;\n\nauto example_lambda_factory = []() { return ExampleFunctionFactory(); };\n\nauto example_lambda_operation = [](ExampleStruct*) {};\n\nauto example_lambda_contract = [](ExampleStruct* example_struct) {\n  return ExampleFunctionContract(example_struct);\n};\n\n// Testing that function references, pointers, structs with operator() and\n// lambdas can all be used with ExceptionSafetyTester\nTEST(ExceptionSafetyTesterTest, MixedFunctionTypes) {\n  // function reference\n  EXPECT_TRUE(testing::MakeExceptionSafetyTester()\n                  .WithFactory(ExampleFunctionFactory)\n                  .WithOperation(ExampleFunctionOperation)\n                  .WithContracts(ExampleFunctionContract)\n                  .Test());\n\n  // function pointer\n  EXPECT_TRUE(testing::MakeExceptionSafetyTester()\n                  .WithFactory(&ExampleFunctionFactory)\n                  .WithOperation(&ExampleFunctionOperation)\n                  .WithContracts(&ExampleFunctionContract)\n                  .Test());\n\n  // struct\n  EXPECT_TRUE(testing::MakeExceptionSafetyTester()\n                  .WithFactory(example_struct_factory)\n                  .WithOperation(example_struct_operation)\n                  .WithContracts(example_struct_contract)\n                  .Test());\n\n  // lambda\n  EXPECT_TRUE(testing::MakeExceptionSafetyTester()\n                  .WithFactory(example_lambda_factory)\n                  .WithOperation(example_lambda_operation)\n                  .WithContracts(example_lambda_contract)\n                  .Test());\n}\n\nstruct NonNegative {\n  bool operator==(const NonNegative& other) const { return i == other.i; }\n  int i;\n};\n\ntesting::AssertionResult CheckNonNegativeInvariants(NonNegative* g) {\n  if (g->i >= 0) {\n    return testing::AssertionSuccess();\n  }\n  return testing::AssertionFailure()\n         << \"i should be non-negative but is \" << g->i;\n}\n\nstruct {\n  template <typename T>\n  void operator()(T* t) const {\n    (*t)();\n  }\n} invoker;\n\nauto tester =\n    testing::MakeExceptionSafetyTester().WithOperation(invoker).WithContracts(\n        CheckNonNegativeInvariants);\nauto strong_tester = tester.WithContracts(testing::strong_guarantee);\n\nstruct FailsBasicGuarantee : public NonNegative {\n  void operator()() {\n    --i;\n    ThrowingValue<> bomb;\n    ++i;\n  }\n};\n\nTEST(ExceptionCheckTest, BasicGuaranteeFailure) {\n  EXPECT_FALSE(tester.WithInitialValue(FailsBasicGuarantee{}).Test());\n}\n\nstruct FollowsBasicGuarantee : public NonNegative {\n  void operator()() {\n    ++i;\n    ThrowingValue<> bomb;\n  }\n};\n\nTEST(ExceptionCheckTest, BasicGuarantee) {\n  EXPECT_TRUE(tester.WithInitialValue(FollowsBasicGuarantee{}).Test());\n}\n\nTEST(ExceptionCheckTest, StrongGuaranteeFailure) {\n  EXPECT_FALSE(strong_tester.WithInitialValue(FailsBasicGuarantee{}).Test());\n  EXPECT_FALSE(strong_tester.WithInitialValue(FollowsBasicGuarantee{}).Test());\n}\n\nstruct BasicGuaranteeWithExtraContracts : public NonNegative {\n  // After operator(), i is incremented.  If operator() throws, i is set to 9999\n  void operator()() {\n    int old_i = i;\n    i = kExceptionSentinel;\n    ThrowingValue<> bomb;\n    i = ++old_i;\n  }\n\n  static constexpr int kExceptionSentinel = 9999;\n};\n\nTEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {\n  auto tester_with_val =\n      tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});\n  EXPECT_TRUE(tester_with_val.Test());\n  EXPECT_TRUE(\n      tester_with_val\n          .WithContracts([](BasicGuaranteeWithExtraContracts* o) {\n            if (o->i == BasicGuaranteeWithExtraContracts::kExceptionSentinel) {\n              return testing::AssertionSuccess();\n            }\n            return testing::AssertionFailure()\n                   << \"i should be \"\n                   << BasicGuaranteeWithExtraContracts::kExceptionSentinel\n                   << \", but is \" << o->i;\n          })\n          .Test());\n}\n\nstruct FollowsStrongGuarantee : public NonNegative {\n  void operator()() { ThrowingValue<> bomb; }\n};\n\nTEST(ExceptionCheckTest, StrongGuarantee) {\n  EXPECT_TRUE(tester.WithInitialValue(FollowsStrongGuarantee{}).Test());\n  EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{}).Test());\n}\n\nstruct HasReset : public NonNegative {\n  void operator()() {\n    i = -1;\n    ThrowingValue<> bomb;\n    i = 1;\n  }\n\n  void reset() { i = 0; }\n};\n\ntesting::AssertionResult CheckHasResetContracts(HasReset* h) {\n  h->reset();\n  return testing::AssertionResult(h->i == 0);\n}\n\nTEST(ExceptionCheckTest, ModifyingChecker) {\n  auto set_to_1000 = [](FollowsBasicGuarantee* g) {\n    g->i = 1000;\n    return testing::AssertionSuccess();\n  };\n  auto is_1000 = [](FollowsBasicGuarantee* g) {\n    return testing::AssertionResult(g->i == 1000);\n  };\n  auto increment = [](FollowsStrongGuarantee* g) {\n    ++g->i;\n    return testing::AssertionSuccess();\n  };\n\n  EXPECT_FALSE(tester.WithInitialValue(FollowsBasicGuarantee{})\n                   .WithContracts(set_to_1000, is_1000)\n                   .Test());\n  EXPECT_TRUE(strong_tester.WithInitialValue(FollowsStrongGuarantee{})\n                  .WithContracts(increment)\n                  .Test());\n  EXPECT_TRUE(testing::MakeExceptionSafetyTester()\n                  .WithInitialValue(HasReset{})\n                  .WithContracts(CheckHasResetContracts)\n                  .Test(invoker));\n}\n\nTEST(ExceptionSafetyTesterTest, ResetsCountdown) {\n  auto test =\n      testing::MakeExceptionSafetyTester()\n          .WithInitialValue(ThrowingValue<>())\n          .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); })\n          .WithOperation([](ThrowingValue<>*) {});\n  ASSERT_TRUE(test.Test());\n  // If the countdown isn't reset because there were no exceptions thrown, then\n  // this will fail with a termination from an unhandled exception\n  EXPECT_TRUE(test.Test());\n}\n\nstruct NonCopyable : public NonNegative {\n  NonCopyable(const NonCopyable&) = delete;\n  NonCopyable() : NonNegative{0} {}\n\n  void operator()() { ThrowingValue<> bomb; }\n};\n\nTEST(ExceptionCheckTest, NonCopyable) {\n  auto factory = []() { return absl::make_unique<NonCopyable>(); };\n  EXPECT_TRUE(tester.WithFactory(factory).Test());\n  EXPECT_TRUE(strong_tester.WithFactory(factory).Test());\n}\n\nstruct NonEqualityComparable : public NonNegative {\n  void operator()() { ThrowingValue<> bomb; }\n\n  void ModifyOnThrow() {\n    ++i;\n    ThrowingValue<> bomb;\n    static_cast<void>(bomb);\n    --i;\n  }\n};\n\nTEST(ExceptionCheckTest, NonEqualityComparable) {\n  auto nec_is_strong = [](NonEqualityComparable* nec) {\n    return testing::AssertionResult(nec->i == NonEqualityComparable().i);\n  };\n  auto strong_nec_tester = tester.WithInitialValue(NonEqualityComparable{})\n                               .WithContracts(nec_is_strong);\n\n  EXPECT_TRUE(strong_nec_tester.Test());\n  EXPECT_FALSE(strong_nec_tester.Test(\n      [](NonEqualityComparable* n) { n->ModifyOnThrow(); }));\n}\n\ntemplate <typename T>\nstruct ExhaustivenessTester {\n  void operator()() {\n    successes |= 1;\n    T b1;\n    static_cast<void>(b1);\n    successes |= (1 << 1);\n    T b2;\n    static_cast<void>(b2);\n    successes |= (1 << 2);\n    T b3;\n    static_cast<void>(b3);\n    successes |= (1 << 3);\n  }\n\n  bool operator==(const ExhaustivenessTester<ThrowingValue<>>&) const {\n    return true;\n  }\n\n  static unsigned char successes;\n};\n\nstruct {\n  template <typename T>\n  testing::AssertionResult operator()(ExhaustivenessTester<T>*) const {\n    return testing::AssertionSuccess();\n  }\n} CheckExhaustivenessTesterContracts;\n\ntemplate <typename T>\nunsigned char ExhaustivenessTester<T>::successes = 0;\n\nTEST(ExceptionCheckTest, Exhaustiveness) {\n  auto exhaust_tester = testing::MakeExceptionSafetyTester()\n                            .WithContracts(CheckExhaustivenessTesterContracts)\n                            .WithOperation(invoker);\n\n  EXPECT_TRUE(\n      exhaust_tester.WithInitialValue(ExhaustivenessTester<int>{}).Test());\n  EXPECT_EQ(ExhaustivenessTester<int>::successes, 0xF);\n\n  EXPECT_TRUE(\n      exhaust_tester.WithInitialValue(ExhaustivenessTester<ThrowingValue<>>{})\n          .WithContracts(testing::strong_guarantee)\n          .Test());\n  EXPECT_EQ(ExhaustivenessTester<ThrowingValue<>>::successes, 0xF);\n}\n\nstruct LeaksIfCtorThrows : private exceptions_internal::TrackedObject {\n  LeaksIfCtorThrows() : TrackedObject(ABSL_PRETTY_FUNCTION) {\n    ++counter;\n    ThrowingValue<> v;\n    static_cast<void>(v);\n    --counter;\n  }\n  LeaksIfCtorThrows(const LeaksIfCtorThrows&) noexcept\n      : TrackedObject(ABSL_PRETTY_FUNCTION) {}\n  static int counter;\n};\nint LeaksIfCtorThrows::counter = 0;\n\nTEST(ExceptionCheckTest, TestLeakyCtor) {\n  testing::TestThrowingCtor<LeaksIfCtorThrows>();\n  EXPECT_EQ(LeaksIfCtorThrows::counter, 1);\n  LeaksIfCtorThrows::counter = 0;\n}\n\nstruct Tracked : private exceptions_internal::TrackedObject {\n  Tracked() : TrackedObject(ABSL_PRETTY_FUNCTION) {}\n};\n\nTEST(ConstructorTrackerTest, CreatedBefore) {\n  Tracked a, b, c;\n  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);\n}\n\nTEST(ConstructorTrackerTest, CreatedAfter) {\n  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);\n  Tracked a, b, c;\n}\n\nTEST(ConstructorTrackerTest, NotDestroyedAfter) {\n  alignas(Tracked) unsigned char storage[sizeof(Tracked)];\n  EXPECT_NONFATAL_FAILURE(\n      {\n        exceptions_internal::ConstructorTracker ct(\n            exceptions_internal::countdown);\n        new (&storage) Tracked();\n      },\n      \"not destroyed\");\n}\n\nTEST(ConstructorTrackerTest, DestroyedTwice) {\n  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);\n  EXPECT_NONFATAL_FAILURE(\n      {\n        Tracked t;\n        t.~Tracked();\n      },\n      \"re-destroyed\");\n}\n\nTEST(ConstructorTrackerTest, ConstructedTwice) {\n  exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);\n  alignas(Tracked) unsigned char storage[sizeof(Tracked)];\n  EXPECT_NONFATAL_FAILURE(\n      {\n        new (&storage) Tracked();\n        new (&storage) Tracked();\n        reinterpret_cast<Tracked*>(&storage)->~Tracked();\n      },\n      \"re-constructed\");\n}\n\nTEST(ThrowingValueTraitsTest, RelationalOperators) {\n  ThrowingValue<> a, b;\n  EXPECT_TRUE((std::is_convertible<decltype(a == b), bool>::value));\n  EXPECT_TRUE((std::is_convertible<decltype(a != b), bool>::value));\n  EXPECT_TRUE((std::is_convertible<decltype(a < b), bool>::value));\n  EXPECT_TRUE((std::is_convertible<decltype(a <= b), bool>::value));\n  EXPECT_TRUE((std::is_convertible<decltype(a > b), bool>::value));\n  EXPECT_TRUE((std::is_convertible<decltype(a >= b), bool>::value));\n}\n\nTEST(ThrowingAllocatorTraitsTest, Assignablility) {\n  EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);\n  EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value);\n  EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value);\n  EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);\n}\n\n}  // namespace\n\n}  // namespace testing\n\n#endif  // ABSL_HAVE_EXCEPTIONS\n"
  },
  {
    "path": "absl/base/fast_type_id.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_BASE_FAST_TYPE_ID_H_\n#define ABSL_BASE_FAST_TYPE_ID_H_\n\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace base_internal {\ntemplate <typename Type>\nstruct FastTypeTag {\n  static constexpr char kDummyVar = 0;\n};\n}  // namespace base_internal\n\n// The type returned by `absl::FastTypeId<T>()`.\nclass FastTypeIdType final {\n public:\n  // Creates a value that does not correspond to any type. This value is\n  // distinct from any value returned by `FastTypeId<T>()`.\n  constexpr FastTypeIdType() = default;\n\n  template <typename H>\n  friend H AbslHashValue(H h, FastTypeIdType x) {\n    return H::combine(std::move(h), x.ptr_);\n  }\n\n  friend constexpr bool operator==(FastTypeIdType a, FastTypeIdType b) {\n    return a.ptr_ == b.ptr_;\n  }\n  friend constexpr bool operator!=(FastTypeIdType a, FastTypeIdType b) {\n    return a.ptr_ != b.ptr_;\n  }\n\n private:\n  // `FastTypeId<T>()` is the generator method for FastTypeIdType values.\n  template <typename T>\n  friend constexpr FastTypeIdType FastTypeId();\n\n  explicit constexpr FastTypeIdType(const void* ptr) : ptr_(ptr) {}\n\n  const void* ptr_ = nullptr;\n};\n\n// `absl::FastTypeId<Type>()` evaluates at compile-time to a unique id for the\n// passed-in type. These are meant to be good match for keys into maps or\n// straight up comparisons.\ntemplate <typename Type>\nconstexpr FastTypeIdType FastTypeId() {\n  return FastTypeIdType(&base_internal::FastTypeTag<Type>::kDummyVar);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_FAST_TYPE_ID_H_\n"
  },
  {
    "path": "absl/base/fast_type_id_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/fast_type_id.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <map>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n\nnamespace {\n\n// Ensure that absl::bit_cast works between FastTypeIdType and void*.\nstatic_assert(sizeof(absl::FastTypeIdType) == sizeof(void*));\n\n// NOLINTBEGIN(runtime/int)\n#define PRIM_TYPES(A)   \\\n  A(bool)               \\\n  A(short)              \\\n  A(unsigned short)     \\\n  A(int)                \\\n  A(unsigned int)       \\\n  A(long)               \\\n  A(unsigned long)      \\\n  A(long long)          \\\n  A(unsigned long long) \\\n  A(float)              \\\n  A(double)             \\\n  A(long double)\n// NOLINTEND(runtime/int)\n\nTEST(FastTypeIdTest, PrimitiveTypes) {\n  // clang-format off\n  constexpr absl::FastTypeIdType kTypeIds[] = {\n#define A(T) absl::FastTypeId<T>(),\n    PRIM_TYPES(A)\n#undef A\n#define A(T) absl::FastTypeId<const T>(),\n    PRIM_TYPES(A)\n#undef A\n#define A(T) absl::FastTypeId<volatile T>(),\n    PRIM_TYPES(A)\n#undef A\n#define A(T) absl::FastTypeId<const volatile T>(),\n    PRIM_TYPES(A)\n#undef A\n  };\n  // clang-format on\n\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(kTypeIds); ++i) {\n    EXPECT_EQ(kTypeIds[i], kTypeIds[i]);\n    for (size_t j = 0; j < i; ++j) {\n      EXPECT_NE(kTypeIds[i], kTypeIds[j]);\n    }\n  }\n}\n\n#define FIXED_WIDTH_TYPES(A) \\\n  A(int8_t)                  \\\n  A(uint8_t)                 \\\n  A(int16_t)                 \\\n  A(uint16_t)                \\\n  A(int32_t)                 \\\n  A(uint32_t)                \\\n  A(int64_t)                 \\\n  A(uint64_t)\n\nTEST(FastTypeIdTest, FixedWidthTypes) {\n  // clang-format off\n  constexpr absl::FastTypeIdType kTypeIds[] = {\n#define A(T) absl::FastTypeId<T>(),\n    FIXED_WIDTH_TYPES(A)\n#undef A\n#define A(T) absl::FastTypeId<const T>(),\n    FIXED_WIDTH_TYPES(A)\n#undef A\n#define A(T) absl::FastTypeId<volatile T>(),\n    FIXED_WIDTH_TYPES(A)\n#undef A\n#define A(T) absl::FastTypeId<const volatile T>(),\n    FIXED_WIDTH_TYPES(A)\n#undef A\n  };\n  // clang-format on\n\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(kTypeIds); ++i) {\n    EXPECT_EQ(kTypeIds[i], kTypeIds[i]);\n    for (size_t j = 0; j < i; ++j) {\n      EXPECT_NE(kTypeIds[i], kTypeIds[j]);\n    }\n  }\n}\n\nTEST(FastTypeIdTest, AliasTypes) {\n  using int_alias = int;\n  EXPECT_EQ(absl::FastTypeId<int_alias>(), absl::FastTypeId<int>());\n}\n\nTEST(FastTypeIdTest, TemplateSpecializations) {\n  EXPECT_NE(absl::FastTypeId<std::vector<int>>(),\n            absl::FastTypeId<std::vector<long>>());  // NOLINT(runtime/int)\n\n  EXPECT_NE((absl::FastTypeId<std::map<int, float>>()),\n            (absl::FastTypeId<std::map<int, double>>()));\n}\n\nstruct Base {};\nstruct Derived : Base {};\nstruct PDerived : private Base {};\n\nTEST(FastTypeIdTest, Inheritance) {\n  EXPECT_NE(absl::FastTypeId<Base>(), absl::FastTypeId<Derived>());\n  EXPECT_NE(absl::FastTypeId<Base>(), absl::FastTypeId<PDerived>());\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/atomic_hook.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_\n#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_\n\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0\n#else\n#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1\n#endif\n\n#if defined(_MSC_VER)\n#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0\n#else\n#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\ntemplate <typename T>\nclass AtomicHook;\n\n// To workaround AtomicHook not being constant-initializable on some platforms,\n// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES`\n// instead of `ABSL_CONST_INIT`.\n#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT\n#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT\n#else\n#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\n#endif\n\n// `AtomicHook` is a helper class, templatized on a raw function pointer type,\n// for implementing Abseil customization hooks.  It is a callable object that\n// dispatches to the registered hook.  Objects of type `AtomicHook` must have\n// static or thread storage duration.\n//\n// A default constructed object performs a no-op (and returns a default\n// constructed object) if no hook has been registered.\n//\n// Hooks can be pre-registered via constant initialization, for example:\n//\n// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()>\n//     my_hook(DefaultAction);\n//\n// and then changed at runtime via a call to `Store()`.\n//\n// Reads and writes guarantee memory_order_acquire/memory_order_release\n// semantics.\ntemplate <typename ReturnType, typename... Args>\nclass AtomicHook<ReturnType (*)(Args...)> {\n public:\n  using FnPtr = ReturnType (*)(Args...);\n\n  // Constructs an object that by default performs a no-op (and\n  // returns a default constructed object) when no hook as been registered.\n  constexpr AtomicHook() : AtomicHook(DummyFunction) {}\n\n  // Constructs an object that by default dispatches to/returns the\n  // pre-registered default_fn when no hook has been registered at runtime.\n#if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT\n  explicit constexpr AtomicHook(FnPtr default_fn)\n      : hook_(default_fn), default_fn_(default_fn) {}\n#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT\n  explicit constexpr AtomicHook(FnPtr default_fn)\n      : hook_(kUninitialized), default_fn_(default_fn) {}\n#else\n  // As of January 2020, on all known versions of MSVC this constructor runs in\n  // the global constructor sequence.  If `Store()` is called by a dynamic\n  // initializer, we want to preserve the value, even if this constructor runs\n  // after the call to `Store()`.  If not, `hook_` will be\n  // zero-initialized by the linker and we have no need to set it.\n  // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html\n  explicit constexpr AtomicHook(FnPtr default_fn)\n      : /* hook_(deliberately omitted), */ default_fn_(default_fn) {\n    static_assert(kUninitialized == 0, \"here we rely on zero-initialization\");\n  }\n#endif\n\n  // Stores the provided function pointer as the value for this hook.\n  //\n  // This is intended to be called once.  Multiple calls are legal only if the\n  // same function pointer is provided for each call.  The store is implemented\n  // as a memory_order_release operation, and read accesses are implemented as\n  // memory_order_acquire.\n  void Store(FnPtr fn) {\n    bool success = DoStore(fn);\n    static_cast<void>(success);\n    assert(success);\n  }\n\n  // Invokes the registered callback.  If no callback has yet been registered, a\n  // default-constructed object of the appropriate type is returned instead.\n  template <typename... CallArgs>\n  ReturnType operator()(CallArgs&&... args) const {\n    return DoLoad()(std::forward<CallArgs>(args)...);\n  }\n\n  // Returns the registered callback, or nullptr if none has been registered.\n  // Useful if client code needs to conditionalize behavior based on whether a\n  // callback was registered.\n  //\n  // Note that atomic_hook.Load()() and atomic_hook() have different semantics:\n  // operator()() will perform a no-op if no callback was registered, while\n  // Load()() will dereference a null function pointer.  Prefer operator()() to\n  // Load()() unless you must conditionalize behavior on whether a hook was\n  // registered.\n  FnPtr Load() const {\n    FnPtr ptr = DoLoad();\n    return (ptr == DummyFunction) ? nullptr : ptr;\n  }\n\n private:\n  static ReturnType DummyFunction(Args...) {\n    return ReturnType();\n  }\n\n  // Current versions of MSVC (as of September 2017) have a broken\n  // implementation of std::atomic<T*>:  Its constructor attempts to do the\n  // equivalent of a reinterpret_cast in a constexpr context, which is not\n  // allowed.\n  //\n  // This causes an issue when building with LLVM under Windows.  To avoid this,\n  // we use a less-efficient, intptr_t-based implementation on Windows.\n#if ABSL_HAVE_WORKING_ATOMIC_POINTER\n  // Return the stored value, or DummyFunction if no value has been stored.\n  FnPtr DoLoad() const { return hook_.load(std::memory_order_acquire); }\n\n  // Store the given value.  Returns false if a different value was already\n  // stored to this object.\n  bool DoStore(FnPtr fn) {\n    assert(fn);\n    FnPtr expected = default_fn_;\n    const bool store_succeeded = hook_.compare_exchange_strong(\n        expected, fn, std::memory_order_acq_rel, std::memory_order_acquire);\n    const bool same_value_already_stored = (expected == fn);\n    return store_succeeded || same_value_already_stored;\n  }\n\n  std::atomic<FnPtr> hook_;\n#else  // !ABSL_HAVE_WORKING_ATOMIC_POINTER\n  // Use a sentinel value unlikely to be the address of an actual function.\n  static constexpr intptr_t kUninitialized = 0;\n\n  static_assert(sizeof(intptr_t) >= sizeof(FnPtr),\n                \"intptr_t can't contain a function pointer\");\n\n  FnPtr DoLoad() const {\n    const intptr_t value = hook_.load(std::memory_order_acquire);\n    if (value == kUninitialized) {\n      return default_fn_;\n    }\n    return reinterpret_cast<FnPtr>(value);\n  }\n\n  bool DoStore(FnPtr fn) {\n    assert(fn);\n    const auto value = reinterpret_cast<intptr_t>(fn);\n    intptr_t expected = kUninitialized;\n    const bool store_succeeded = hook_.compare_exchange_strong(\n        expected, value, std::memory_order_acq_rel, std::memory_order_acquire);\n    const bool same_value_already_stored = (expected == value);\n    return store_succeeded || same_value_already_stored;\n  }\n\n  std::atomic<intptr_t> hook_;\n#endif\n\n  const FnPtr default_fn_;\n};\n\n#undef ABSL_HAVE_WORKING_ATOMIC_POINTER\n#undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_\n"
  },
  {
    "path": "absl/base/internal/atomic_hook_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/atomic_hook.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/atomic_hook_test_helper.h\"\n\nnamespace {\n\nusing ::testing::Eq;\n\nint value = 0;\nvoid TestHook(int x) { value = x; }\n\nTEST(AtomicHookTest, NoDefaultFunction) {\n  ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<\n      void (*)(int)>\n      hook;\n  value = 0;\n\n  // Test the default DummyFunction.\n  EXPECT_TRUE(hook.Load() == nullptr);\n  EXPECT_EQ(value, 0);\n  hook(1);\n  EXPECT_EQ(value, 0);\n\n  // Test a stored hook.\n  hook.Store(TestHook);\n  EXPECT_TRUE(hook.Load() == TestHook);\n  EXPECT_EQ(value, 0);\n  hook(1);\n  EXPECT_EQ(value, 1);\n\n  // Calling Store() with the same hook should not crash.\n  hook.Store(TestHook);\n  EXPECT_TRUE(hook.Load() == TestHook);\n  EXPECT_EQ(value, 1);\n  hook(2);\n  EXPECT_EQ(value, 2);\n}\n\nTEST(AtomicHookTest, WithDefaultFunction) {\n  // Set the default value to TestHook at compile-time.\n  ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<\n      void (*)(int)>\n      hook(TestHook);\n  value = 0;\n\n  // Test the default value is TestHook.\n  EXPECT_TRUE(hook.Load() == TestHook);\n  EXPECT_EQ(value, 0);\n  hook(1);\n  EXPECT_EQ(value, 1);\n\n  // Calling Store() with the same hook should not crash.\n  hook.Store(TestHook);\n  EXPECT_TRUE(hook.Load() == TestHook);\n  EXPECT_EQ(value, 1);\n  hook(2);\n  EXPECT_EQ(value, 2);\n}\n\nABSL_CONST_INIT int override_func_calls = 0;\nvoid OverrideFunc() { override_func_calls++; }\nstatic struct OverrideInstaller {\n  OverrideInstaller() { absl::atomic_hook_internal::func.Store(OverrideFunc); }\n} override_installer;\n\nTEST(AtomicHookTest, DynamicInitFromAnotherTU) {\n  // MSVC 14.2 doesn't do constexpr static init correctly; in particular it\n  // tends to sequence static init (i.e. defaults) of `AtomicHook` objects\n  // after their dynamic init (i.e. overrides), overwriting whatever value was\n  // written during dynamic init.  This regression test validates the fix.\n  // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html\n  EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0));\n  EXPECT_THAT(override_func_calls, Eq(0));\n  absl::atomic_hook_internal::func();\n  EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0));\n  EXPECT_THAT(override_func_calls, Eq(1));\n  EXPECT_THAT(absl::atomic_hook_internal::func.Load(), Eq(OverrideFunc));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/atomic_hook_test_helper.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/atomic_hook_test_helper.h\"\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace atomic_hook_internal {\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<VoidF>\n    func(DefaultFunc);\nABSL_CONST_INIT int default_func_calls = 0;\nvoid DefaultFunc() { default_func_calls++; }\nvoid RegisterFunc(VoidF f) { func.Store(f); }\n\n}  // namespace atomic_hook_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/atomic_hook_test_helper.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_\n#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_\n\n#include \"absl/base/internal/atomic_hook.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace atomic_hook_internal {\n\nusing VoidF = void (*)();\nextern absl::base_internal::AtomicHook<VoidF> func;\nextern int default_func_calls;\nvoid DefaultFunc();\nvoid RegisterFunc(VoidF func);\n\n}  // namespace atomic_hook_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_\n"
  },
  {
    "path": "absl/base/internal/cmake_thread_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <iostream>\n#include \"absl/base/internal/thread_identity.h\"\n\nint main() {\n  auto* tid = absl::base_internal::CurrentThreadIdentityIfPresent();\n  // Make sure the above call can't be optimized out\n  std::cout << (void*)tid << std::endl;\n}\n"
  },
  {
    "path": "absl/base/internal/cycleclock.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// The implementation of CycleClock::Frequency.\n//\n// NOTE: only i386 and x86_64 have been well tested.\n// PPC, sparc, alpha, and ia64 are based on\n//    http://peter.kuscsik.com/wordpress/?p=14\n// with modifications by m3b.  See also\n//    https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h\n\n#include \"absl/base/internal/cycleclock.h\"\n\n#include <atomic>\n#include <chrono>  // NOLINT(build/c++11)\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/unscaledcycleclock.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n\nABSL_CONST_INIT std::atomic<CycleClockSourceFunc>\n    CycleClock::cycle_clock_source_{nullptr};\n\nvoid CycleClockSource::Register(CycleClockSourceFunc source) {\n  // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource.\n  CycleClock::cycle_clock_source_.store(source, std::memory_order_release);\n}\n\n#ifdef _WIN32\nint64_t CycleClock::Now() {\n  auto fn = LoadCycleClockSource();\n  if (fn == nullptr) {\n    return base_internal::UnscaledCycleClock::Now() >> kShift;\n  }\n  return fn() >> kShift;\n}\n#endif\n\n#else\n\nint64_t CycleClock::Now() {\n  return std::chrono::duration_cast<std::chrono::nanoseconds>(\n             std::chrono::steady_clock::now().time_since_epoch())\n      .count();\n}\n\ndouble CycleClock::Frequency() {\n  return 1e9;\n}\n\n#endif\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/cycleclock.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n// -----------------------------------------------------------------------------\n// File: cycleclock.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a `CycleClock`, which yields the value and frequency\n// of a cycle counter that increments at a rate that is approximately constant.\n//\n// NOTE:\n//\n// The cycle counter frequency is not necessarily related to the core clock\n// frequency and should not be treated as such. That is, `CycleClock` cycles are\n// not necessarily \"CPU cycles\" and code should not rely on that behavior, even\n// if experimentally observed.\n//\n// An arbitrary offset may have been added to the counter at power on.\n//\n// On some platforms, the rate and offset of the counter may differ\n// slightly when read from different CPUs of a multiprocessor. Usually,\n// we try to ensure that the operating system adjusts values periodically\n// so that values agree approximately.   If you need stronger guarantees,\n// consider using alternate interfaces.\n//\n// The CPU is not required to maintain the ordering of a cycle counter read\n// with respect to surrounding instructions.\n\n#ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_H_\n#define ABSL_BASE_INTERNAL_CYCLECLOCK_H_\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/cycleclock_config.h\"\n#include \"absl/base/internal/unscaledcycleclock.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nusing CycleClockSourceFunc = int64_t (*)();\n\n// -----------------------------------------------------------------------------\n// CycleClock\n// -----------------------------------------------------------------------------\nclass CycleClock {\n public:\n  // CycleClock::Now()\n  //\n  // Returns the value of a cycle counter that counts at a rate that is\n  // approximately constant.\n  static int64_t Now();\n\n  // CycleClock::Frequency()\n  //\n  // Returns the amount by which `CycleClock::Now()` increases per second. Note\n  // that this value may not necessarily match the core CPU clock frequency.\n  static double Frequency();\n\n private:\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n  static CycleClockSourceFunc LoadCycleClockSource();\n\n  static constexpr int32_t kShift = kCycleClockShift;\n  static constexpr double kFrequencyScale = kCycleClockFrequencyScale;\n\n  ABSL_CONST_INIT static std::atomic<CycleClockSourceFunc> cycle_clock_source_;\n#endif  //  ABSL_USE_UNSCALED_CYCLECLOC\n\n  CycleClock() = delete;  // no instances\n  CycleClock(const CycleClock&) = delete;\n  CycleClock& operator=(const CycleClock&) = delete;\n\n  friend class CycleClockSource;\n};\n\nclass CycleClockSource {\n private:\n  // CycleClockSource::Register()\n  //\n  // Register a function that provides an alternate source for the unscaled CPU\n  // cycle count value. The source function must be async signal safe, must not\n  // call CycleClock::Now(), and must have a frequency that matches that of the\n  // unscaled clock used by CycleClock. A nullptr value resets CycleClock to use\n  // the default source.\n  static void Register(CycleClockSourceFunc source);\n};\n\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n\ninline CycleClockSourceFunc CycleClock::LoadCycleClockSource() {\n#if !defined(__x86_64__)\n  // Optimize for the common case (no callback) by first doing a relaxed load;\n  // this is significantly faster on non-x86 platforms.\n  if (cycle_clock_source_.load(std::memory_order_relaxed) == nullptr) {\n    return nullptr;\n  }\n#endif  // !defined(__x86_64__)\n\n  // This corresponds to the store(std::memory_order_release) in\n  // CycleClockSource::Register, and makes sure that any updates made prior to\n  // registering the callback are visible to this thread before the callback\n  // is invoked.\n  return cycle_clock_source_.load(std::memory_order_acquire);\n}\n\n// Accessing globals in inlined code in Window DLLs is problematic.\n#ifndef _WIN32\ninline int64_t CycleClock::Now() {\n  auto fn = LoadCycleClockSource();\n  if (fn == nullptr) {\n    return base_internal::UnscaledCycleClock::Now() >> kShift;\n  }\n  return fn() >> kShift;\n}\n#endif\n\ninline double CycleClock::Frequency() {\n  return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();\n}\n\n#endif  // ABSL_USE_UNSCALED_CYCLECLOCK\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_CYCLECLOCK_H_\n"
  },
  {
    "path": "absl/base/internal/cycleclock_config.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_\n#define ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/unscaledcycleclock_config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n#ifdef NDEBUG\n#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY\n// Not debug mode and the UnscaledCycleClock frequency is the CPU\n// frequency.  Scale the CycleClock to prevent overflow if someone\n// tries to represent the time as cycles since the Unix epoch.\ninline constexpr int32_t kCycleClockShift = 1;\n#else\n// Not debug mode and the UnscaledCycleClock isn't operating at the\n// raw CPU frequency. There is no need to do any scaling, so don't\n// needlessly sacrifice precision.\ninline constexpr int32_t kCycleClockShift = 0;\n#endif\n#else   // NDEBUG\n// In debug mode use a different shift to discourage depending on a\n// particular shift value.\ninline constexpr int32_t kCycleClockShift = 2;\n#endif  // NDEBUG\n\ninline constexpr double kCycleClockFrequencyScale =\n    1.0 / (1 << kCycleClockShift);\n\n#endif  // ABSL_USE_UNSCALED_CYCLECLOCK\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_\n"
  },
  {
    "path": "absl/base/internal/direct_mmap.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Functions for directly invoking mmap() via syscall, avoiding the case where\n// mmap() has been locally overridden.\n\n#ifndef ABSL_BASE_INTERNAL_DIRECT_MMAP_H_\n#define ABSL_BASE_INTERNAL_DIRECT_MMAP_H_\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_HAVE_MMAP\n\n#include <sys/mman.h>\n\n#ifdef __linux__\n\n#include <sys/types.h>\n#ifdef __BIONIC__\n#include <sys/syscall.h>\n#else\n#include <syscall.h>\n#endif\n\n#include <linux/unistd.h>\n#include <unistd.h>\n#include <cerrno>\n#include <cstdarg>\n#include <cstdint>\n\n#ifdef __mips__\n// Include definitions of the ABI currently in use.\n#if defined(__BIONIC__) || !defined(__GLIBC__)\n// Android doesn't have sgidefs.h, but does have asm/sgidefs.h, which has the\n// definitions we need.\n#include <asm/sgidefs.h>\n#else\n#include <sgidefs.h>\n#endif  // __BIONIC__ || !__GLIBC__\n#endif  // __mips__\n\n// SYS_mmap and SYS_munmap are not defined in Android.\n#ifdef __BIONIC__\nextern \"C\" void* __mmap2(void*, size_t, int, int, int, size_t);\n#if defined(__NR_mmap) && !defined(SYS_mmap)\n#define SYS_mmap __NR_mmap\n#endif\n#ifndef SYS_munmap\n#define SYS_munmap __NR_munmap\n#endif\n#endif  // __BIONIC__\n\n#if defined(__NR_mmap2) && !defined(SYS_mmap2)\n#define SYS_mmap2 __NR_mmap2\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Platform specific logic extracted from\n// https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h\ninline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,\n                        off_t offset) noexcept {\n#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \\\n    defined(__m68k__) || defined(__sh__) ||                                  \\\n    (defined(__hppa__) && !defined(__LP64__)) ||                             \\\n    (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ||                   \\\n    (defined(__PPC__) && !defined(__PPC64__)) ||                             \\\n    (defined(__riscv) && __riscv_xlen == 32) ||                              \\\n    (defined(__s390__) && !defined(__s390x__)) ||                            \\\n    (defined(__sparc__) && !defined(__arch64__))\n  // On these architectures, implement mmap with mmap2.\n  static int pagesize = 0;\n  if (pagesize == 0) {\n#if defined(__wasm__) || defined(__asmjs__)\n    pagesize = getpagesize();\n#else\n    pagesize = sysconf(_SC_PAGESIZE);\n#endif\n  }\n  if (offset < 0 || offset % pagesize != 0) {\n    errno = EINVAL;\n    return MAP_FAILED;\n  }\n#ifdef __BIONIC__\n  // SYS_mmap2 has problems on Android API level <= 16.\n  // Workaround by invoking __mmap2() instead.\n  return __mmap2(start, length, prot, flags, fd,\n                 static_cast<size_t>(offset / pagesize));\n#else\n  return reinterpret_cast<void*>(\n      syscall(SYS_mmap2, start, length, prot, flags, fd,\n              static_cast<unsigned long>(offset / pagesize)));  // NOLINT\n#endif\n#elif defined(__s390x__)\n  // On s390x, mmap() arguments are passed in memory.\n  unsigned long buf[6] = {reinterpret_cast<unsigned long>(start),  // NOLINT\n                          static_cast<unsigned long>(length),      // NOLINT\n                          static_cast<unsigned long>(prot),        // NOLINT\n                          static_cast<unsigned long>(flags),       // NOLINT\n                          static_cast<unsigned long>(fd),          // NOLINT\n                          static_cast<unsigned long>(offset)};     // NOLINT\n  return reinterpret_cast<void*>(syscall(SYS_mmap, buf));\n#elif defined(__x86_64__)\n// The x32 ABI has 32 bit longs, but the syscall interface is 64 bit.\n// We need to explicitly cast to an unsigned 64 bit type to avoid implicit\n// sign extension.  We can't cast pointers directly because those are\n// 32 bits, and gcc will dump ugly warnings about casting from a pointer\n// to an integer of a different size. We also need to make sure __off64_t\n// isn't truncated to 32-bits under x32.\n#define MMAP_SYSCALL_ARG(x) ((uint64_t)(uintptr_t)(x))\n  return reinterpret_cast<void*>(\n      syscall(SYS_mmap, MMAP_SYSCALL_ARG(start), MMAP_SYSCALL_ARG(length),\n              MMAP_SYSCALL_ARG(prot), MMAP_SYSCALL_ARG(flags),\n              MMAP_SYSCALL_ARG(fd), static_cast<uint64_t>(offset)));\n#undef MMAP_SYSCALL_ARG\n#else  // Remaining 64-bit aritectures.\n  static_assert(sizeof(unsigned long) == 8, \"Platform is not 64-bit\");\n  return reinterpret_cast<void*>(\n      syscall(SYS_mmap, start, length, prot, flags, fd, offset));\n#endif\n}\n\ninline int DirectMunmap(void* start, size_t length) {\n  return static_cast<int>(syscall(SYS_munmap, start, length));\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#else  // !__linux__\n\n// For non-linux platforms where we have mmap, just dispatch directly to the\n// actual mmap()/munmap() methods.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\ninline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,\n                        off_t offset) {\n  return mmap(start, length, prot, flags, fd, offset);\n}\n\ninline int DirectMunmap(void* start, size_t length) {\n  return munmap(start, length);\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // __linux__\n\n#endif  // ABSL_HAVE_MMAP\n\n#endif  // ABSL_BASE_INTERNAL_DIRECT_MMAP_H_\n"
  },
  {
    "path": "absl/base/internal/dynamic_annotations.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file defines dynamic annotations for use with dynamic analysis tool\n// such as valgrind, PIN, etc.\n//\n// Dynamic annotation is a source code annotation that affects the generated\n// code (that is, the annotation is not a comment). Each such annotation is\n// attached to a particular instruction and/or to a particular object (address)\n// in the program.\n//\n// The annotations that should be used by users are macros in all upper-case\n// (e.g., ANNOTATE_THREAD_NAME).\n//\n// Actual implementation of these macros may differ depending on the dynamic\n// analysis tool being used.\n//\n// This file supports the following configurations:\n// - Dynamic Annotations enabled (with static thread-safety warnings disabled).\n//   In this case, macros expand to functions implemented by Thread Sanitizer,\n//   when building with TSan. When not provided an external implementation,\n//   dynamic_annotations.cc provides no-op implementations.\n//\n// - Static Clang thread-safety warnings enabled.\n//   When building with a Clang compiler that supports thread-safety warnings,\n//   a subset of annotations can be statically-checked at compile-time. We\n//   expand these macros to static-inline functions that can be analyzed for\n//   thread-safety, but afterwards elided when building the final binary.\n//\n// - All annotations are disabled.\n//   If neither Dynamic Annotations nor Clang thread-safety warnings are\n//   enabled, then all annotation-macros expand to empty.\n\n#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_\n#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_\n\n#include <stddef.h>\n\n#include \"absl/base/config.h\"\n\n// -------------------------------------------------------------------------\n// Decide which features are enabled\n\n#ifndef DYNAMIC_ANNOTATIONS_ENABLED\n#define DYNAMIC_ANNOTATIONS_ENABLED 0\n#endif\n\n#if defined(__clang__) && !defined(SWIG)\n#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1\n#endif\n\n#if DYNAMIC_ANNOTATIONS_ENABLED != 0\n\n#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1\n#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1\n#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1\n#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0\n#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1\n\n#else\n\n#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0\n#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0\n#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0\n\n// Clang provides limited support for static thread-safety analysis through a\n// feature called Annotalysis. We configure macro-definitions according to\n// whether Annotalysis support is available. When running in opt-mode, GCC\n// will issue a warning, if these attributes are compiled. Only include them\n// when compiling using Clang.\n\n// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1\n#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \\\n  defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.\n#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \\\n  ABSL_INTERNAL_ANNOTALYSIS_ENABLED\n#endif\n\n// Memory annotations are also made available to LLVM's Memory Sanitizer\n#if defined(ABSL_HAVE_MEMORY_SANITIZER)\n#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1\n#endif\n\n#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED\n#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0\n#endif\n\n#ifdef __cplusplus\n#define ABSL_INTERNAL_BEGIN_EXTERN_C extern \"C\" {\n#define ABSL_INTERNAL_END_EXTERN_C }  // extern \"C\"\n#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F\n#define ABSL_INTERNAL_STATIC_INLINE inline\n#else\n#define ABSL_INTERNAL_BEGIN_EXTERN_C  // empty\n#define ABSL_INTERNAL_END_EXTERN_C    // empty\n#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F\n#define ABSL_INTERNAL_STATIC_INLINE static inline\n#endif\n\n// -------------------------------------------------------------------------\n// Define race annotations.\n\n#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1\n\n// -------------------------------------------------------------\n// Annotations that suppress errors. It is usually better to express the\n// program's synchronization using the other annotations, but these can be used\n// when all else fails.\n\n// Report that we may have a benign race at `pointer`, with size\n// \"sizeof(*(pointer))\". `pointer` must be a non-void* pointer. Insert at the\n// point where `pointer` has been allocated, preferably close to the point\n// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.\n#define ANNOTATE_BENIGN_RACE(pointer, description)     \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \\\n  (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)\n\n// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to\n// the memory range [`address`, `address`+`size`).\n#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized)         \\\n  (__FILE__, __LINE__, address, size, description)\n\n// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.\n// This annotation could be useful if you want to skip expensive race analysis\n// during some period of program execution, e.g. during initialization.\n#define ANNOTATE_ENABLE_RACE_DETECTION(enable)             \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \\\n  (__FILE__, __LINE__, enable)\n\n// -------------------------------------------------------------\n// Annotations useful for debugging.\n\n// Report the current thread `name` to a race detector.\n#define ANNOTATE_THREAD_NAME(name) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)\n\n// -------------------------------------------------------------\n// Annotations useful when implementing locks. They are not normally needed by\n// modules that merely use locks. The `lock` argument is a pointer to the lock\n// object.\n\n// Report that a lock has been created at address `lock`.\n#define ANNOTATE_RWLOCK_CREATE(lock) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)\n\n// Report that a linker initialized lock has been created at address `lock`.\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n#define ANNOTATE_RWLOCK_CREATE_STATIC(lock)               \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \\\n  (__FILE__, __LINE__, lock)\n#else\n#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)\n#endif\n\n// Report that the lock at address `lock` is about to be destroyed.\n#define ANNOTATE_RWLOCK_DESTROY(lock) \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)\n\n// Report that the lock at address `lock` has been acquired.\n// `is_w`=1 for writer lock, `is_w`=0 for reader lock.\n#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)          \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \\\n  (__FILE__, __LINE__, lock, is_w)\n\n// Report that the lock at address `lock` is about to be released.\n// `is_w`=1 for writer lock, `is_w`=0 for reader lock.\n#define ANNOTATE_RWLOCK_RELEASED(lock, is_w)          \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \\\n  (__FILE__, __LINE__, lock, is_w)\n\n// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.\n#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)      \\\n  namespace {                                                     \\\n  class static_var##_annotator {                                  \\\n   public:                                                        \\\n    static_var##_annotator() {                                    \\\n      ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \\\n                                 #static_var \": \" description);   \\\n    }                                                             \\\n  };                                                              \\\n  static static_var##_annotator the##static_var##_annotator;      \\\n  }  // namespace\n\n#else  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0\n\n#define ANNOTATE_RWLOCK_CREATE(lock)                            // empty\n#define ANNOTATE_RWLOCK_CREATE_STATIC(lock)                     // empty\n#define ANNOTATE_RWLOCK_DESTROY(lock)                           // empty\n#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)                    // empty\n#define ANNOTATE_RWLOCK_RELEASED(lock, is_w)                    // empty\n#define ANNOTATE_BENIGN_RACE(address, description)              // empty\n#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description)  // empty\n#define ANNOTATE_THREAD_NAME(name)                              // empty\n#define ANNOTATE_ENABLE_RACE_DETECTION(enable)                  // empty\n#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)    // empty\n\n#endif  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED\n\n// -------------------------------------------------------------------------\n// Define memory annotations.\n\n#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1\n\n#include <sanitizer/msan_interface.h>\n\n#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \\\n  __msan_unpoison(address, size)\n\n#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \\\n  __msan_allocated_memory(address, size)\n\n#else  // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0\n\n#if DYNAMIC_ANNOTATIONS_ENABLED == 1\n#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \\\n  do {                                                \\\n    (void)(address);                                  \\\n    (void)(size);                                     \\\n  } while (0)\n#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \\\n  do {                                                  \\\n    (void)(address);                                    \\\n    (void)(size);                                       \\\n  } while (0)\n#else\n#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size)    // empty\n#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size)  // empty\n#endif\n\n#endif  // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED\n\n// -------------------------------------------------------------------------\n// Define IGNORE_READS_BEGIN/_END attributes.\n\n#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n\n#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \\\n  __attribute((exclusive_lock_function(\"*\")))\n#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \\\n  __attribute((unlock_function(\"*\")))\n\n#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n\n#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty\n#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty\n\n#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)\n\n// -------------------------------------------------------------------------\n// Define IGNORE_READS_BEGIN/_END annotations.\n\n#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1\n\n// Request the analysis tool to ignore all reads in the current thread until\n// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey\n// reads, while still checking other reads and all writes.\n// See also ANNOTATE_UNPROTECTED_READ.\n#define ANNOTATE_IGNORE_READS_BEGIN() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)\n\n// Stop ignoring reads.\n#define ANNOTATE_IGNORE_READS_END() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)\n\n#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)\n\n// When Annotalysis is enabled without Dynamic Annotations, the use of\n// static-inline functions allows the annotations to be read at compile-time,\n// while still letting the compiler elide the functions from the final build.\n//\n// TODO(delesley) -- The exclusive lock here ignores writes as well, but\n// allows IGNORE_READS_AND_WRITES to work properly.\n\n#define ANNOTATE_IGNORE_READS_BEGIN() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()\n\n#define ANNOTATE_IGNORE_READS_END() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()\n\n#else\n\n#define ANNOTATE_IGNORE_READS_BEGIN()  // empty\n#define ANNOTATE_IGNORE_READS_END()    // empty\n\n#endif\n\n// -------------------------------------------------------------------------\n// Define IGNORE_WRITES_BEGIN/_END annotations.\n\n#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1\n\n// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.\n#define ANNOTATE_IGNORE_WRITES_BEGIN() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)\n\n// Stop ignoring writes.\n#define ANNOTATE_IGNORE_WRITES_END() \\\n  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)\n\n#else\n\n#define ANNOTATE_IGNORE_WRITES_BEGIN()  // empty\n#define ANNOTATE_IGNORE_WRITES_END()    // empty\n\n#endif\n\n// -------------------------------------------------------------------------\n// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more\n// primitive annotations defined above.\n//\n//     Instead of doing\n//        ANNOTATE_IGNORE_READS_BEGIN();\n//        ... = x;\n//        ANNOTATE_IGNORE_READS_END();\n//     one can use\n//        ... = ANNOTATE_UNPROTECTED_READ(x);\n\n#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)\n\n// Start ignoring all memory accesses (both reads and writes).\n#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \\\n  do {                                           \\\n    ANNOTATE_IGNORE_READS_BEGIN();               \\\n    ANNOTATE_IGNORE_WRITES_BEGIN();              \\\n  } while (0)\n\n// Stop ignoring both reads and writes.\n#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \\\n  do {                                         \\\n    ANNOTATE_IGNORE_WRITES_END();              \\\n    ANNOTATE_IGNORE_READS_END();               \\\n  } while (0)\n\n#ifdef __cplusplus\n// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.\n#define ANNOTATE_UNPROTECTED_READ(x) \\\n  absl::base_internal::AnnotateUnprotectedRead(x)\n\n#endif\n\n#else\n\n#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN()  // empty\n#define ANNOTATE_IGNORE_READS_AND_WRITES_END()    // empty\n#define ANNOTATE_UNPROTECTED_READ(x) (x)\n\n#endif\n\n// -------------------------------------------------------------------------\n// Address sanitizer annotations\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n// Describe the current state of a contiguous container such as e.g.\n// std::vector or std::string. For more details see\n// sanitizer/common_interface_defs.h, which is provided by the compiler.\n#include <sanitizer/common_interface_defs.h>\n\n#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \\\n  __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)\n#define ADDRESS_SANITIZER_REDZONE(name)    \\\n  struct {                                 \\\n    char x[8] __attribute__((aligned(8))); \\\n  } name\n\n#else\n\n#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)\n#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, \"\")\n\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n\n// -------------------------------------------------------------------------\n// Undefine the macros intended only for this file.\n\n#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED\n#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED\n#undef ABSL_INTERNAL_BEGIN_EXTERN_C\n#undef ABSL_INTERNAL_END_EXTERN_C\n#undef ABSL_INTERNAL_STATIC_INLINE\n\n#endif  // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_\n"
  },
  {
    "path": "absl/base/internal/endian.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file is for Abseil internal use only.\n// See //absl/numeric/bits.h for supported functions related to endian-ness.\n\n#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_\n#define ABSL_BASE_INTERNAL_ENDIAN_H_\n\n#include <cstdint>\n#include <cstdlib>\n\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/unaligned_access.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/port.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nconstexpr uint64_t gbswap_64(uint64_t x) {\n#if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)\n  return __builtin_bswap64(x);\n#else\n  return (((x & uint64_t{0xFF}) << 56) |\n          ((x & uint64_t{0xFF00}) << 40) |\n          ((x & uint64_t{0xFF0000}) << 24) |\n          ((x & uint64_t{0xFF000000}) << 8) |\n          ((x & uint64_t{0xFF00000000}) >> 8) |\n          ((x & uint64_t{0xFF0000000000}) >> 24) |\n          ((x & uint64_t{0xFF000000000000}) >> 40) |\n          ((x & uint64_t{0xFF00000000000000}) >> 56));\n#endif\n}\n\nconstexpr uint32_t gbswap_32(uint32_t x) {\n#if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)\n  return __builtin_bswap32(x);\n#else\n  return (((x & uint32_t{0xFF}) << 24) |\n          ((x & uint32_t{0xFF00}) << 8) |\n          ((x & uint32_t{0xFF0000}) >> 8) |\n          ((x & uint32_t{0xFF000000}) >> 24));\n#endif\n}\n\nconstexpr uint16_t gbswap_16(uint16_t x) {\n#if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)\n  return __builtin_bswap16(x);\n#else\n  return (((x & uint16_t{0xFF}) << 8) |\n          ((x & uint16_t{0xFF00}) >> 8));\n#endif\n}\n\n#ifdef ABSL_IS_LITTLE_ENDIAN\n\n// Portable definitions for htonl (host-to-network) and friends on little-endian\n// architectures.\ninline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }\ninline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }\ninline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }\n\n#elif defined ABSL_IS_BIG_ENDIAN\n\n// Portable definitions for htonl (host-to-network) etc on big-endian\n// architectures. These definitions are simpler since the host byte order is the\n// same as network byte order.\ninline uint16_t ghtons(uint16_t x) { return x; }\ninline uint32_t ghtonl(uint32_t x) { return x; }\ninline uint64_t ghtonll(uint64_t x) { return x; }\n\n#else\n#error \\\n    \"Unsupported byte order: Either ABSL_IS_BIG_ENDIAN or \" \\\n       \"ABSL_IS_LITTLE_ENDIAN must be defined\"\n#endif  // byte order\n\ninline uint16_t gntohs(uint16_t x) { return ghtons(x); }\ninline uint32_t gntohl(uint32_t x) { return ghtonl(x); }\ninline uint64_t gntohll(uint64_t x) { return ghtonll(x); }\n\n// Utilities to convert numbers between the current hosts's native byte\n// order and little-endian byte order\n//\n// Load/Store methods are alignment safe\nnamespace little_endian {\n// Conversion functions.\n#ifdef ABSL_IS_LITTLE_ENDIAN\n\ninline uint16_t FromHost16(uint16_t x) { return x; }\ninline uint16_t ToHost16(uint16_t x) { return x; }\n\ninline uint32_t FromHost32(uint32_t x) { return x; }\ninline uint32_t ToHost32(uint32_t x) { return x; }\n\ninline uint64_t FromHost64(uint64_t x) { return x; }\ninline uint64_t ToHost64(uint64_t x) { return x; }\n\ninline constexpr bool IsLittleEndian() { return true; }\n\n#elif defined ABSL_IS_BIG_ENDIAN\n\ninline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }\ninline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }\n\ninline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }\ninline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }\n\ninline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }\ninline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }\n\ninline constexpr bool IsLittleEndian() { return false; }\n\n#endif /* ENDIAN */\n\ninline uint8_t FromHost(uint8_t x) { return x; }\ninline uint16_t FromHost(uint16_t x) { return FromHost16(x); }\ninline uint32_t FromHost(uint32_t x) { return FromHost32(x); }\ninline uint64_t FromHost(uint64_t x) { return FromHost64(x); }\ninline uint8_t ToHost(uint8_t x) { return x; }\ninline uint16_t ToHost(uint16_t x) { return ToHost16(x); }\ninline uint32_t ToHost(uint32_t x) { return ToHost32(x); }\ninline uint64_t ToHost(uint64_t x) { return ToHost64(x); }\n\ninline int8_t FromHost(int8_t x) { return x; }\ninline int16_t FromHost(int16_t x) {\n  return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));\n}\ninline int32_t FromHost(int32_t x) {\n  return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));\n}\ninline int64_t FromHost(int64_t x) {\n  return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));\n}\ninline int8_t ToHost(int8_t x) { return x; }\ninline int16_t ToHost(int16_t x) {\n  return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));\n}\ninline int32_t ToHost(int32_t x) {\n  return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));\n}\ninline int64_t ToHost(int64_t x) {\n  return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));\n}\n\n// Functions to do unaligned loads and stores in little-endian order.\ninline uint16_t Load16(const void* absl_nonnull p) {\n  return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));\n}\n\ninline void Store16(void* absl_nonnull p, uint16_t v) {\n  ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));\n}\n\ninline uint32_t Load32(const void* absl_nonnull p) {\n  return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));\n}\n\ninline void Store32(void* absl_nonnull p, uint32_t v) {\n  ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));\n}\n\ninline uint64_t Load64(const void* absl_nonnull p) {\n  return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));\n}\n\ninline void Store64(void* absl_nonnull p, uint64_t v) {\n  ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));\n}\n\n}  // namespace little_endian\n\n// Utilities to convert numbers between the current hosts's native byte\n// order and big-endian byte order (same as network byte order)\n//\n// Load/Store methods are alignment safe\nnamespace big_endian {\n#ifdef ABSL_IS_LITTLE_ENDIAN\n\ninline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }\ninline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }\n\ninline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }\ninline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }\n\ninline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }\ninline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }\n\ninline constexpr bool IsLittleEndian() { return true; }\n\n#elif defined ABSL_IS_BIG_ENDIAN\n\ninline uint16_t FromHost16(uint16_t x) { return x; }\ninline uint16_t ToHost16(uint16_t x) { return x; }\n\ninline uint32_t FromHost32(uint32_t x) { return x; }\ninline uint32_t ToHost32(uint32_t x) { return x; }\n\ninline uint64_t FromHost64(uint64_t x) { return x; }\ninline uint64_t ToHost64(uint64_t x) { return x; }\n\ninline constexpr bool IsLittleEndian() { return false; }\n\n#endif /* ENDIAN */\n\ninline uint8_t FromHost(uint8_t x) { return x; }\ninline uint16_t FromHost(uint16_t x) { return FromHost16(x); }\ninline uint32_t FromHost(uint32_t x) { return FromHost32(x); }\ninline uint64_t FromHost(uint64_t x) { return FromHost64(x); }\ninline uint8_t ToHost(uint8_t x) { return x; }\ninline uint16_t ToHost(uint16_t x) { return ToHost16(x); }\ninline uint32_t ToHost(uint32_t x) { return ToHost32(x); }\ninline uint64_t ToHost(uint64_t x) { return ToHost64(x); }\n\ninline int8_t FromHost(int8_t x) { return x; }\ninline int16_t FromHost(int16_t x) {\n  return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));\n}\ninline int32_t FromHost(int32_t x) {\n  return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));\n}\ninline int64_t FromHost(int64_t x) {\n  return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));\n}\ninline int8_t ToHost(int8_t x) { return x; }\ninline int16_t ToHost(int16_t x) {\n  return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));\n}\ninline int32_t ToHost(int32_t x) {\n  return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));\n}\ninline int64_t ToHost(int64_t x) {\n  return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));\n}\n\n// Functions to do unaligned loads and stores in big-endian order.\ninline uint16_t Load16(const void* absl_nonnull p) {\n  return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));\n}\n\ninline void Store16(void* absl_nonnull p, uint16_t v) {\n  ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));\n}\n\ninline uint32_t Load32(const void* absl_nonnull p) {\n  return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));\n}\n\ninline void Store32(void* absl_nonnull p, uint32_t v) {\n  ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));\n}\n\ninline uint64_t Load64(const void* absl_nonnull p) {\n  return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));\n}\n\ninline void Store64(void* absl_nonnull p, uint64_t v) {\n  ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));\n}\n\n}  // namespace big_endian\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_ENDIAN_H_\n"
  },
  {
    "path": "absl/base/internal/endian_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/endian.h\"\n\n#include <algorithm>\n#include <cstdint>\n#include <limits>\n#include <random>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nconst uint64_t kInitialNumber{0x0123456789abcdef};\nconst uint64_t k64Value{kInitialNumber};\nconst uint32_t k32Value{0x01234567};\nconst uint16_t k16Value{0x0123};\nconst int kNumValuesToTest = 1000000;\nconst int kRandomSeed = 12345;\n\n#if defined(ABSL_IS_BIG_ENDIAN)\nconst uint64_t kInitialInNetworkOrder{kInitialNumber};\nconst uint64_t k64ValueLE{0xefcdab8967452301};\nconst uint32_t k32ValueLE{0x67452301};\nconst uint16_t k16ValueLE{0x2301};\n\nconst uint64_t k64ValueBE{kInitialNumber};\nconst uint32_t k32ValueBE{k32Value};\nconst uint16_t k16ValueBE{k16Value};\n#elif defined(ABSL_IS_LITTLE_ENDIAN)\nconst uint64_t kInitialInNetworkOrder{0xefcdab8967452301};\nconst uint64_t k64ValueLE{kInitialNumber};\nconst uint32_t k32ValueLE{k32Value};\nconst uint16_t k16ValueLE{k16Value};\n\nconst uint64_t k64ValueBE{0xefcdab8967452301};\nconst uint32_t k32ValueBE{0x67452301};\nconst uint16_t k16ValueBE{0x2301};\n#endif\n\nstd::vector<uint16_t> GenerateAllUint16Values() {\n  std::vector<uint16_t> result;\n  result.reserve(size_t{1} << (sizeof(uint16_t) * 8));\n  for (uint32_t i = std::numeric_limits<uint16_t>::min();\n       i <= std::numeric_limits<uint16_t>::max(); ++i) {\n    result.push_back(static_cast<uint16_t>(i));\n  }\n  return result;\n}\n\ntemplate<typename T>\nstd::vector<T> GenerateRandomIntegers(size_t num_values_to_test) {\n  std::vector<T> result;\n  result.reserve(num_values_to_test);\n  std::mt19937_64 rng(kRandomSeed);\n  for (size_t i = 0; i < num_values_to_test; ++i) {\n    result.push_back(rng());\n  }\n  return result;\n}\n\nvoid ManualByteSwap(char* bytes, int length) {\n  if (length == 1)\n    return;\n\n  EXPECT_EQ(0, length % 2);\n  for (int i = 0; i < length / 2; ++i) {\n    int j = (length - 1) - i;\n    using std::swap;\n    swap(bytes[i], bytes[j]);\n  }\n}\n\ntemplate<typename T>\ninline T UnalignedLoad(const char* p) {\n  static_assert(\n      sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,\n      \"Unexpected type size\");\n\n  switch (sizeof(T)) {\n    case 1: return *reinterpret_cast<const T*>(p);\n    case 2:\n      return ABSL_INTERNAL_UNALIGNED_LOAD16(p);\n    case 4:\n      return ABSL_INTERNAL_UNALIGNED_LOAD32(p);\n    case 8:\n      return ABSL_INTERNAL_UNALIGNED_LOAD64(p);\n    default:\n      // Suppresses invalid \"not all control paths return a value\" on MSVC\n      return {};\n  }\n}\n\ntemplate <typename T, typename ByteSwapper>\nstatic void GBSwapHelper(const std::vector<T>& host_values_to_test,\n                         const ByteSwapper& byte_swapper) {\n  // Test byte_swapper against a manual byte swap.\n  for (typename std::vector<T>::const_iterator it = host_values_to_test.begin();\n       it != host_values_to_test.end(); ++it) {\n    T host_value = *it;\n\n    char actual_value[sizeof(host_value)];\n    memcpy(actual_value, &host_value, sizeof(host_value));\n    byte_swapper(actual_value);\n\n    char expected_value[sizeof(host_value)];\n    memcpy(expected_value, &host_value, sizeof(host_value));\n    ManualByteSwap(expected_value, sizeof(host_value));\n\n    ASSERT_EQ(0, memcmp(actual_value, expected_value, sizeof(host_value)))\n        << \"Swap output for 0x\" << std::hex << host_value << \" does not match. \"\n        << \"Expected: 0x\" << UnalignedLoad<T>(expected_value) << \"; \"\n        << \"actual: 0x\" <<  UnalignedLoad<T>(actual_value);\n  }\n}\n\nvoid Swap16(char* bytes) {\n  ABSL_INTERNAL_UNALIGNED_STORE16(\n      bytes, gbswap_16(ABSL_INTERNAL_UNALIGNED_LOAD16(bytes)));\n}\n\nvoid Swap32(char* bytes) {\n  ABSL_INTERNAL_UNALIGNED_STORE32(\n      bytes, gbswap_32(ABSL_INTERNAL_UNALIGNED_LOAD32(bytes)));\n}\n\nvoid Swap64(char* bytes) {\n  ABSL_INTERNAL_UNALIGNED_STORE64(\n      bytes, gbswap_64(ABSL_INTERNAL_UNALIGNED_LOAD64(bytes)));\n}\n\nTEST(EndianessTest, Uint16) {\n  GBSwapHelper(GenerateAllUint16Values(), &Swap16);\n}\n\nTEST(EndianessTest, Uint32) {\n  GBSwapHelper(GenerateRandomIntegers<uint32_t>(kNumValuesToTest), &Swap32);\n}\n\nTEST(EndianessTest, Uint64) {\n  GBSwapHelper(GenerateRandomIntegers<uint64_t>(kNumValuesToTest), &Swap64);\n}\n\nTEST(EndianessTest, ghtonll_gntohll) {\n  // Test that absl::ghtonl compiles correctly\n  uint32_t test = 0x01234567;\n  EXPECT_EQ(absl::gntohl(absl::ghtonl(test)), test);\n\n  uint64_t comp = absl::ghtonll(kInitialNumber);\n  EXPECT_EQ(comp, kInitialInNetworkOrder);\n  comp = absl::gntohll(kInitialInNetworkOrder);\n  EXPECT_EQ(comp, kInitialNumber);\n\n  // Test that htonll and ntohll are each others' inverse functions on a\n  // somewhat assorted batch of numbers. 37 is chosen to not be anything\n  // particularly nice base 2.\n  uint64_t value = 1;\n  for (int i = 0; i < 100; ++i) {\n    comp = absl::ghtonll(absl::gntohll(value));\n    EXPECT_EQ(value, comp);\n    comp = absl::gntohll(absl::ghtonll(value));\n    EXPECT_EQ(value, comp);\n    value *= 37;\n  }\n}\n\nTEST(EndianessTest, little_endian) {\n  // Check little_endian uint16_t.\n  uint64_t comp = little_endian::FromHost16(k16Value);\n  EXPECT_EQ(comp, k16ValueLE);\n  comp = little_endian::ToHost16(k16ValueLE);\n  EXPECT_EQ(comp, k16Value);\n\n  // Check little_endian uint32_t.\n  comp = little_endian::FromHost32(k32Value);\n  EXPECT_EQ(comp, k32ValueLE);\n  comp = little_endian::ToHost32(k32ValueLE);\n  EXPECT_EQ(comp, k32Value);\n\n  // Check little_endian uint64_t.\n  comp = little_endian::FromHost64(k64Value);\n  EXPECT_EQ(comp, k64ValueLE);\n  comp = little_endian::ToHost64(k64ValueLE);\n  EXPECT_EQ(comp, k64Value);\n\n  // Check little-endian Load and store functions.\n  uint16_t u16Buf;\n  uint32_t u32Buf;\n  uint64_t u64Buf;\n\n  little_endian::Store16(&u16Buf, k16Value);\n  EXPECT_EQ(u16Buf, k16ValueLE);\n  comp = little_endian::Load16(&u16Buf);\n  EXPECT_EQ(comp, k16Value);\n\n  little_endian::Store32(&u32Buf, k32Value);\n  EXPECT_EQ(u32Buf, k32ValueLE);\n  comp = little_endian::Load32(&u32Buf);\n  EXPECT_EQ(comp, k32Value);\n\n  little_endian::Store64(&u64Buf, k64Value);\n  EXPECT_EQ(u64Buf, k64ValueLE);\n  comp = little_endian::Load64(&u64Buf);\n  EXPECT_EQ(comp, k64Value);\n}\n\nTEST(EndianessTest, big_endian) {\n  // Check big-endian Load and store functions.\n  uint16_t u16Buf;\n  uint32_t u32Buf;\n  uint64_t u64Buf;\n\n  unsigned char buffer[10];\n  big_endian::Store16(&u16Buf, k16Value);\n  EXPECT_EQ(u16Buf, k16ValueBE);\n  uint64_t comp = big_endian::Load16(&u16Buf);\n  EXPECT_EQ(comp, k16Value);\n\n  big_endian::Store32(&u32Buf, k32Value);\n  EXPECT_EQ(u32Buf, k32ValueBE);\n  comp = big_endian::Load32(&u32Buf);\n  EXPECT_EQ(comp, k32Value);\n\n  big_endian::Store64(&u64Buf, k64Value);\n  EXPECT_EQ(u64Buf, k64ValueBE);\n  comp = big_endian::Load64(&u64Buf);\n  EXPECT_EQ(comp, k64Value);\n\n  big_endian::Store16(buffer + 1, k16Value);\n  EXPECT_EQ(u16Buf, k16ValueBE);\n  comp = big_endian::Load16(buffer + 1);\n  EXPECT_EQ(comp, k16Value);\n\n  big_endian::Store32(buffer + 1, k32Value);\n  EXPECT_EQ(u32Buf, k32ValueBE);\n  comp = big_endian::Load32(buffer + 1);\n  EXPECT_EQ(comp, k32Value);\n\n  big_endian::Store64(buffer + 1, k64Value);\n  EXPECT_EQ(u64Buf, k64ValueBE);\n  comp = big_endian::Load64(buffer + 1);\n  EXPECT_EQ(comp, k64Value);\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/errno_saver.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_ERRNO_SAVER_H_\n#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_\n\n#include <cerrno>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// `ErrnoSaver` captures the value of `errno` upon construction and restores it\n// upon deletion.  It is used in low-level code and must be super fast.  Do not\n// add instrumentation, even in debug modes.\nclass ErrnoSaver {\n public:\n  ErrnoSaver() : saved_errno_(errno) {}\n  ~ErrnoSaver() { errno = saved_errno_; }\n  int operator()() const { return saved_errno_; }\n\n private:\n  const int saved_errno_;\n};\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_\n"
  },
  {
    "path": "absl/base/internal/errno_saver_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/errno_saver.h\"\n\n#include <cerrno>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/strerror.h\"\n\nnamespace {\nusing ::testing::Eq;\n\nstruct ErrnoPrinter {\n  int no;\n};\nstd::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) {\n  return os << absl::base_internal::StrError(ep.no) << \" [\" << ep.no << \"]\";\n}\nbool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; }\n\nTEST(ErrnoSaverTest, Works) {\n  errno = EDOM;\n  {\n    absl::base_internal::ErrnoSaver errno_saver;\n    EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));\n    errno = ERANGE;\n    EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{ERANGE}));\n    EXPECT_THAT(ErrnoPrinter{errno_saver()}, Eq(ErrnoPrinter{EDOM}));\n  }\n  EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));\n}\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/exception_safety_testing.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/exception_safety_testing.h\"\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n\n#include \"gtest/gtest.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace testing {\n\nexceptions_internal::NoThrowTag nothrow_ctor;\n\nexceptions_internal::StrongGuaranteeTagType strong_guarantee;\n\nexceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester() {\n  return {};\n}\n\nnamespace exceptions_internal {\n\nint countdown = -1;\n\nConstructorTracker* ConstructorTracker::current_tracker_instance_ = nullptr;\n\nvoid MaybeThrow(absl::string_view msg, bool throw_bad_alloc) {\n  if (countdown-- == 0) {\n    if (throw_bad_alloc) throw TestBadAllocException(msg);\n    throw TestException(msg);\n  }\n}\n\ntesting::AssertionResult FailureMessage(const TestException& e,\n                                        int countdown) noexcept {\n  return testing::AssertionFailure() << \"Exception thrown from \" << e.what();\n}\n\nstd::string GetSpecString(TypeSpec spec) {\n  std::string out;\n  absl::string_view sep;\n  const auto append = [&](absl::string_view s) {\n    absl::StrAppend(&out, sep, s);\n    sep = \" | \";\n  };\n  if (static_cast<bool>(TypeSpec::kNoThrowCopy & spec)) {\n    append(\"kNoThrowCopy\");\n  }\n  if (static_cast<bool>(TypeSpec::kNoThrowMove & spec)) {\n    append(\"kNoThrowMove\");\n  }\n  if (static_cast<bool>(TypeSpec::kNoThrowNew & spec)) {\n    append(\"kNoThrowNew\");\n  }\n  return out;\n}\n\nstd::string GetSpecString(AllocSpec spec) {\n  return static_cast<bool>(AllocSpec::kNoThrowAllocate & spec)\n             ? \"kNoThrowAllocate\"\n             : \"\";\n}\n\n}  // namespace exceptions_internal\n\n}  // namespace testing\n\n#endif  // ABSL_HAVE_EXCEPTIONS\n"
  },
  {
    "path": "absl/base/internal/exception_safety_testing.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Utilities for testing exception-safety\n\n#ifndef ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_\n#define ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n\n#include <cstddef>\n#include <cstdint>\n#include <functional>\n#include <initializer_list>\n#include <iosfwd>\n#include <string>\n#include <tuple>\n#include <unordered_map>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/pretty_function.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/substitute.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace testing {\n\nenum class TypeSpec;\nenum class AllocSpec;\n\nconstexpr TypeSpec operator|(TypeSpec a, TypeSpec b) {\n  using T = absl::underlying_type_t<TypeSpec>;\n  return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b));\n}\n\nconstexpr TypeSpec operator&(TypeSpec a, TypeSpec b) {\n  using T = absl::underlying_type_t<TypeSpec>;\n  return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b));\n}\n\nconstexpr AllocSpec operator|(AllocSpec a, AllocSpec b) {\n  using T = absl::underlying_type_t<AllocSpec>;\n  return static_cast<AllocSpec>(static_cast<T>(a) | static_cast<T>(b));\n}\n\nconstexpr AllocSpec operator&(AllocSpec a, AllocSpec b) {\n  using T = absl::underlying_type_t<AllocSpec>;\n  return static_cast<AllocSpec>(static_cast<T>(a) & static_cast<T>(b));\n}\n\nnamespace exceptions_internal {\n\nstd::string GetSpecString(TypeSpec);\nstd::string GetSpecString(AllocSpec);\n\nstruct NoThrowTag {};\nstruct StrongGuaranteeTagType {};\n\n// A simple exception class.  We throw this so that test code can catch\n// exceptions specifically thrown by ThrowingValue.\nclass TestException {\n public:\n  explicit TestException(absl::string_view msg) : msg_(msg) {}\n  virtual ~TestException() {}\n  virtual const char* what() const noexcept { return msg_.c_str(); }\n\n private:\n  std::string msg_;\n};\n\n// TestBadAllocException exists because allocation functions must throw an\n// exception which can be caught by a handler of std::bad_alloc.  We use a child\n// class of std::bad_alloc so we can customise the error message, and also\n// derive from TestException so we don't accidentally end up catching an actual\n// bad_alloc exception in TestExceptionSafety.\nclass TestBadAllocException : public std::bad_alloc, public TestException {\n public:\n  explicit TestBadAllocException(absl::string_view msg) : TestException(msg) {}\n  using TestException::what;\n};\n\nextern int countdown;\n\n// Allows the countdown variable to be set manually (defaulting to the initial\n// value of 0)\ninline void SetCountdown(int i = 0) { countdown = i; }\n// Sets the countdown to the terminal value -1\ninline void UnsetCountdown() { SetCountdown(-1); }\n\nvoid MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false);\n\ntesting::AssertionResult FailureMessage(const TestException& e,\n                                        int countdown) noexcept;\n\nstruct TrackedAddress {\n  bool is_alive;\n  std::string description;\n};\n\n// Inspects the constructions and destructions of anything inheriting from\n// TrackedObject. This allows us to safely \"leak\" TrackedObjects, as\n// ConstructorTracker will destroy everything left over in its destructor.\nclass ConstructorTracker {\n public:\n  explicit ConstructorTracker(int count) : countdown_(count) {\n    assert(current_tracker_instance_ == nullptr);\n    current_tracker_instance_ = this;\n  }\n\n  ~ConstructorTracker() {\n    assert(current_tracker_instance_ == this);\n    current_tracker_instance_ = nullptr;\n\n    for (auto& it : address_map_) {\n      void* address = it.first;\n      TrackedAddress& tracked_address = it.second;\n      if (tracked_address.is_alive) {\n        ADD_FAILURE() << ErrorMessage(address, tracked_address.description,\n                                      countdown_, \"Object was not destroyed.\");\n      }\n    }\n  }\n\n  static void ObjectConstructed(void* address, std::string description) {\n    if (!CurrentlyTracking()) return;\n\n    TrackedAddress& tracked_address =\n        current_tracker_instance_->address_map_[address];\n    if (tracked_address.is_alive) {\n      ADD_FAILURE() << ErrorMessage(\n          address, tracked_address.description,\n          current_tracker_instance_->countdown_,\n          \"Object was re-constructed. Current object was constructed by \" +\n              description);\n    }\n    tracked_address = {true, std::move(description)};\n  }\n\n  static void ObjectDestructed(void* address) {\n    if (!CurrentlyTracking()) return;\n\n    auto it = current_tracker_instance_->address_map_.find(address);\n    // Not tracked. Ignore.\n    if (it == current_tracker_instance_->address_map_.end()) return;\n\n    TrackedAddress& tracked_address = it->second;\n    if (!tracked_address.is_alive) {\n      ADD_FAILURE() << ErrorMessage(address, tracked_address.description,\n                                    current_tracker_instance_->countdown_,\n                                    \"Object was re-destroyed.\");\n    }\n    tracked_address.is_alive = false;\n  }\n\n private:\n  static bool CurrentlyTracking() {\n    return current_tracker_instance_ != nullptr;\n  }\n\n  static std::string ErrorMessage(void* address,\n                                  const std::string& address_description,\n                                  int countdown,\n                                  const std::string& error_description) {\n    return absl::Substitute(\n        \"With coundtown at $0:\\n\"\n        \"  $1\\n\"\n        \"  Object originally constructed by $2\\n\"\n        \"  Object address: $3\\n\",\n        countdown, error_description, address_description, address);\n  }\n\n  std::unordered_map<void*, TrackedAddress> address_map_;\n  int countdown_;\n\n  static ConstructorTracker* current_tracker_instance_;\n};\n\nclass TrackedObject {\n public:\n  TrackedObject(const TrackedObject&) = delete;\n  TrackedObject(TrackedObject&&) = delete;\n\n protected:\n  explicit TrackedObject(std::string description) {\n    ConstructorTracker::ObjectConstructed(this, std::move(description));\n  }\n\n  ~TrackedObject() noexcept { ConstructorTracker::ObjectDestructed(this); }\n};\n}  // namespace exceptions_internal\n\nextern exceptions_internal::NoThrowTag nothrow_ctor;\n\nextern exceptions_internal::StrongGuaranteeTagType strong_guarantee;\n\n// A test class which is convertible to bool.  The conversion can be\n// instrumented to throw at a controlled time.\nclass ThrowingBool {\n public:\n  ThrowingBool(bool b) noexcept : b_(b) {}  // NOLINT(runtime/explicit)\n  operator bool() const {                   // NOLINT\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return b_;\n  }\n\n private:\n  bool b_;\n};\n\n/*\n * Configuration enum for the ThrowingValue type that defines behavior for the\n * lifetime of the instance. Use testing::nothrow_ctor to prevent the integer\n * constructor from throwing.\n *\n * kEverythingThrows: Every operation can throw an exception\n * kNoThrowCopy: Copy construction and copy assignment will not throw\n * kNoThrowMove: Move construction and move assignment will not throw\n * kNoThrowNew: Overloaded operators new and new[] will not throw\n */\nenum class TypeSpec {\n  kEverythingThrows = 0,\n  kNoThrowCopy = 1,\n  kNoThrowMove = 1 << 1,\n  kNoThrowNew = 1 << 2,\n};\n\n/*\n * A testing class instrumented to throw an exception at a controlled time.\n *\n * ThrowingValue implements a slightly relaxed version of the Regular concept --\n * that is it's a value type with the expected semantics.  It also implements\n * arithmetic operations.  It doesn't implement member and pointer operators\n * like operator-> or operator[].\n *\n * ThrowingValue can be instrumented to have certain operations be noexcept by\n * using compile-time bitfield template arguments.  That is, to make an\n * ThrowingValue which has noexcept move construction/assignment and noexcept\n * copy construction/assignment, use the following:\n *   ThrowingValue<testing::kNoThrowMove | testing::kNoThrowCopy> my_thrwr{val};\n */\ntemplate <TypeSpec Spec = TypeSpec::kEverythingThrows>\nclass ThrowingValue : private exceptions_internal::TrackedObject {\n  static constexpr bool IsSpecified(TypeSpec spec) {\n    return static_cast<bool>(Spec & spec);\n  }\n\n  static constexpr int kDefaultValue = 0;\n  static constexpr int kBadValue = 938550620;\n\n public:\n  ThrowingValue() : TrackedObject(GetInstanceString(kDefaultValue)) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ = kDefaultValue;\n  }\n\n  ThrowingValue(const ThrowingValue& other) noexcept(\n      IsSpecified(TypeSpec::kNoThrowCopy))\n      : TrackedObject(GetInstanceString(other.dummy_)) {\n    if (!IsSpecified(TypeSpec::kNoThrowCopy)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    }\n    dummy_ = other.dummy_;\n  }\n\n  ThrowingValue(ThrowingValue&& other) noexcept(\n      IsSpecified(TypeSpec::kNoThrowMove))\n      : TrackedObject(GetInstanceString(other.dummy_)) {\n    if (!IsSpecified(TypeSpec::kNoThrowMove)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    }\n    dummy_ = other.dummy_;\n  }\n\n  explicit ThrowingValue(int i) : TrackedObject(GetInstanceString(i)) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ = i;\n  }\n\n  ThrowingValue(int i, exceptions_internal::NoThrowTag) noexcept\n      : TrackedObject(GetInstanceString(i)), dummy_(i) {}\n\n  // absl expects nothrow destructors\n  ~ThrowingValue() noexcept = default;\n\n  ThrowingValue& operator=(const ThrowingValue& other) noexcept(\n      IsSpecified(TypeSpec::kNoThrowCopy)) {\n    dummy_ = kBadValue;\n    if (!IsSpecified(TypeSpec::kNoThrowCopy)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    }\n    dummy_ = other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator=(ThrowingValue&& other) noexcept(\n      IsSpecified(TypeSpec::kNoThrowMove)) {\n    dummy_ = kBadValue;\n    if (!IsSpecified(TypeSpec::kNoThrowMove)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    }\n    dummy_ = other.dummy_;\n    return *this;\n  }\n\n  // Arithmetic Operators\n  ThrowingValue operator+(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ + other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator+() const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator-(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ - other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator-() const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(-dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue& operator++() {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    ++dummy_;\n    return *this;\n  }\n\n  ThrowingValue operator++(int) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    auto out = ThrowingValue(dummy_, nothrow_ctor);\n    ++dummy_;\n    return out;\n  }\n\n  ThrowingValue& operator--() {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    --dummy_;\n    return *this;\n  }\n\n  ThrowingValue operator--(int) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    auto out = ThrowingValue(dummy_, nothrow_ctor);\n    --dummy_;\n    return out;\n  }\n\n  ThrowingValue operator*(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ * other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator/(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ / other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator%(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ % other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator<<(int shift) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ << shift, nothrow_ctor);\n  }\n\n  ThrowingValue operator>>(int shift) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ >> shift, nothrow_ctor);\n  }\n\n  // Comparison Operators\n  // NOTE: We use `ThrowingBool` instead of `bool` because most STL\n  // types/containers requires T to be convertible to bool.\n  friend ThrowingBool operator==(const ThrowingValue& a,\n                                 const ThrowingValue& b) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return a.dummy_ == b.dummy_;\n  }\n  friend ThrowingBool operator!=(const ThrowingValue& a,\n                                 const ThrowingValue& b) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return a.dummy_ != b.dummy_;\n  }\n  friend ThrowingBool operator<(const ThrowingValue& a,\n                                const ThrowingValue& b) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return a.dummy_ < b.dummy_;\n  }\n  friend ThrowingBool operator<=(const ThrowingValue& a,\n                                 const ThrowingValue& b) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return a.dummy_ <= b.dummy_;\n  }\n  friend ThrowingBool operator>(const ThrowingValue& a,\n                                const ThrowingValue& b) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return a.dummy_ > b.dummy_;\n  }\n  friend ThrowingBool operator>=(const ThrowingValue& a,\n                                 const ThrowingValue& b) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return a.dummy_ >= b.dummy_;\n  }\n\n  // Logical Operators\n  ThrowingBool operator!() const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return !dummy_;\n  }\n\n  ThrowingBool operator&&(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return dummy_ && other.dummy_;\n  }\n\n  ThrowingBool operator||(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return dummy_ || other.dummy_;\n  }\n\n  // Bitwise Logical Operators\n  ThrowingValue operator~() const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(~dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator&(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ & other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator|(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ | other.dummy_, nothrow_ctor);\n  }\n\n  ThrowingValue operator^(const ThrowingValue& other) const {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return ThrowingValue(dummy_ ^ other.dummy_, nothrow_ctor);\n  }\n\n  // Compound Assignment operators\n  ThrowingValue& operator+=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ += other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator-=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ -= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator*=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ *= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator/=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ /= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator%=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ %= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator&=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ &= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator|=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ |= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator^=(const ThrowingValue& other) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ ^= other.dummy_;\n    return *this;\n  }\n\n  ThrowingValue& operator<<=(int shift) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ <<= shift;\n    return *this;\n  }\n\n  ThrowingValue& operator>>=(int shift) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ >>= shift;\n    return *this;\n  }\n\n  // Pointer operators\n  void operator&() const = delete;  // NOLINT(runtime/operator)\n\n  // Stream operators\n  friend std::ostream& operator<<(std::ostream& os, const ThrowingValue& tv) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return os << GetInstanceString(tv.dummy_);\n  }\n\n  friend std::istream& operator>>(std::istream& is, const ThrowingValue&) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    return is;\n  }\n\n  // Memory management operators\n  static void* operator new(size_t s) noexcept(\n      IsSpecified(TypeSpec::kNoThrowNew)) {\n    if (!IsSpecified(TypeSpec::kNoThrowNew)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);\n    }\n    return ::operator new(s);\n  }\n\n  static void* operator new[](size_t s) noexcept(\n      IsSpecified(TypeSpec::kNoThrowNew)) {\n    if (!IsSpecified(TypeSpec::kNoThrowNew)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);\n    }\n    return ::operator new[](s);\n  }\n\n  template <typename... Args>\n  static void* operator new(size_t s, Args&&... args) noexcept(\n      IsSpecified(TypeSpec::kNoThrowNew)) {\n    if (!IsSpecified(TypeSpec::kNoThrowNew)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);\n    }\n    return ::operator new(s, std::forward<Args>(args)...);\n  }\n\n  template <typename... Args>\n  static void* operator new[](size_t s, Args&&... args) noexcept(\n      IsSpecified(TypeSpec::kNoThrowNew)) {\n    if (!IsSpecified(TypeSpec::kNoThrowNew)) {\n      exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);\n    }\n    return ::operator new[](s, std::forward<Args>(args)...);\n  }\n\n  // Abseil doesn't support throwing overloaded operator delete.  These are\n  // provided so a throwing operator-new can clean up after itself.\n  void operator delete(void* p) noexcept { ::operator delete(p); }\n\n  template <typename... Args>\n  void operator delete(void* p, Args&&... args) noexcept {\n    ::operator delete(p, std::forward<Args>(args)...);\n  }\n\n  void operator delete[](void* p) noexcept { return ::operator delete[](p); }\n\n  template <typename... Args>\n  void operator delete[](void* p, Args&&... args) noexcept {\n    return ::operator delete[](p, std::forward<Args>(args)...);\n  }\n\n  // Non-standard access to the actual contained value.  No need for this to\n  // throw.\n  int& Get() noexcept { return dummy_; }\n  const int& Get() const noexcept { return dummy_; }\n\n private:\n  static std::string GetInstanceString(int dummy) {\n    return absl::StrCat(\"ThrowingValue<\",\n                        exceptions_internal::GetSpecString(Spec), \">(\", dummy,\n                        \")\");\n  }\n\n  int dummy_;\n};\n// While not having to do with exceptions, explicitly delete comma operator, to\n// make sure we don't use it on user-supplied types.\ntemplate <TypeSpec Spec, typename T>\nvoid operator,(const ThrowingValue<Spec>&, T&&) = delete;\ntemplate <TypeSpec Spec, typename T>\nvoid operator,(T&&, const ThrowingValue<Spec>&) = delete;\n\n/*\n * Configuration enum for the ThrowingAllocator type that defines behavior for\n * the lifetime of the instance.\n *\n * kEverythingThrows: Calls to the member functions may throw\n * kNoThrowAllocate: Calls to the member functions will not throw\n */\nenum class AllocSpec {\n  kEverythingThrows = 0,\n  kNoThrowAllocate = 1,\n};\n\n/*\n * An allocator type which is instrumented to throw at a controlled time, or not\n * to throw, using AllocSpec. The supported settings are the default of every\n * function which is allowed to throw in a conforming allocator possibly\n * throwing, or nothing throws, in line with the ABSL_ALLOCATOR_THROWS\n * configuration macro.\n */\ntemplate <typename T, AllocSpec Spec = AllocSpec::kEverythingThrows>\nclass ThrowingAllocator : private exceptions_internal::TrackedObject {\n  static constexpr bool IsSpecified(AllocSpec spec) {\n    return static_cast<bool>(Spec & spec);\n  }\n\n public:\n  using pointer = T*;\n  using const_pointer = const T*;\n  using reference = T&;\n  using const_reference = const T&;\n  using void_pointer = void*;\n  using const_void_pointer = const void*;\n  using value_type = T;\n  using size_type = size_t;\n  using difference_type = ptrdiff_t;\n\n  using is_nothrow =\n      std::integral_constant<bool, Spec == AllocSpec::kNoThrowAllocate>;\n  using propagate_on_container_copy_assignment = std::true_type;\n  using propagate_on_container_move_assignment = std::true_type;\n  using propagate_on_container_swap = std::true_type;\n  using is_always_equal = std::false_type;\n\n  ThrowingAllocator() : TrackedObject(GetInstanceString(next_id_)) {\n    exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);\n    dummy_ = std::make_shared<const int>(next_id_++);\n  }\n\n  template <typename U>\n  ThrowingAllocator(const ThrowingAllocator<U, Spec>& other) noexcept  // NOLINT\n      : TrackedObject(GetInstanceString(*other.State())),\n        dummy_(other.State()) {}\n\n  // According to C++11 standard [17.6.3.5], Table 28, the move/copy ctors of\n  // allocator shall not exit via an exception, thus they are marked noexcept.\n  ThrowingAllocator(const ThrowingAllocator& other) noexcept\n      : TrackedObject(GetInstanceString(*other.State())),\n        dummy_(other.State()) {}\n\n  template <typename U>\n  ThrowingAllocator(ThrowingAllocator<U, Spec>&& other) noexcept  // NOLINT\n      : TrackedObject(GetInstanceString(*other.State())),\n        dummy_(std::move(other.State())) {}\n\n  ThrowingAllocator(ThrowingAllocator&& other) noexcept\n      : TrackedObject(GetInstanceString(*other.State())),\n        dummy_(std::move(other.State())) {}\n\n  ~ThrowingAllocator() noexcept = default;\n\n  ThrowingAllocator& operator=(const ThrowingAllocator& other) noexcept {\n    dummy_ = other.State();\n    return *this;\n  }\n\n  template <typename U>\n  ThrowingAllocator& operator=(\n      const ThrowingAllocator<U, Spec>& other) noexcept {\n    dummy_ = other.State();\n    return *this;\n  }\n\n  template <typename U>\n  ThrowingAllocator& operator=(ThrowingAllocator<U, Spec>&& other) noexcept {\n    dummy_ = std::move(other.State());\n    return *this;\n  }\n\n  template <typename U>\n  struct rebind {\n    using other = ThrowingAllocator<U, Spec>;\n  };\n\n  pointer allocate(size_type n) noexcept(\n      IsSpecified(AllocSpec::kNoThrowAllocate)) {\n    ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);\n    return static_cast<pointer>(::operator new(n * sizeof(T)));\n  }\n\n  pointer allocate(size_type n, const_void_pointer) noexcept(\n      IsSpecified(AllocSpec::kNoThrowAllocate)) {\n    return allocate(n);\n  }\n\n  void deallocate(pointer ptr, size_type) noexcept {\n    ReadState();\n    ::operator delete(static_cast<void*>(ptr));\n  }\n\n  template <typename U, typename... Args>\n  void construct(U* ptr, Args&&... args) noexcept(\n      IsSpecified(AllocSpec::kNoThrowAllocate)) {\n    ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);\n    ::new (static_cast<void*>(ptr)) U(std::forward<Args>(args)...);\n  }\n\n  template <typename U>\n  void destroy(U* p) noexcept {\n    ReadState();\n    p->~U();\n  }\n\n  size_type max_size() const noexcept {\n    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);\n  }\n\n  ThrowingAllocator select_on_container_copy_construction() noexcept(\n      IsSpecified(AllocSpec::kNoThrowAllocate)) {\n    ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);\n    return *this;\n  }\n\n  template <typename U>\n  bool operator==(const ThrowingAllocator<U, Spec>& other) const noexcept {\n    return dummy_ == other.dummy_;\n  }\n\n  template <typename U>\n  bool operator!=(const ThrowingAllocator<U, Spec>& other) const noexcept {\n    return dummy_ != other.dummy_;\n  }\n\n  template <typename, AllocSpec>\n  friend class ThrowingAllocator;\n\n private:\n  static std::string GetInstanceString(int dummy) {\n    return absl::StrCat(\"ThrowingAllocator<\",\n                        exceptions_internal::GetSpecString(Spec), \">(\", dummy,\n                        \")\");\n  }\n\n  const std::shared_ptr<const int>& State() const { return dummy_; }\n  std::shared_ptr<const int>& State() { return dummy_; }\n\n  void ReadState() {\n    // we know that this will never be true, but the compiler doesn't, so this\n    // should safely force a read of the value.\n    if (*dummy_ < 0) std::abort();\n  }\n\n  void ReadStateAndMaybeThrow(absl::string_view msg) const {\n    if (!IsSpecified(AllocSpec::kNoThrowAllocate)) {\n      exceptions_internal::MaybeThrow(\n          absl::Substitute(\"Allocator id $0 threw from $1\", *dummy_, msg));\n    }\n  }\n\n  static int next_id_;\n  std::shared_ptr<const int> dummy_;\n};\n\ntemplate <typename T, AllocSpec Spec>\nint ThrowingAllocator<T, Spec>::next_id_ = 0;\n\n// Tests for resource leaks by attempting to construct a T using args repeatedly\n// until successful, using the countdown method.  Side effects can then be\n// tested for resource leaks.\ntemplate <typename T, typename... Args>\nvoid TestThrowingCtor(Args&&... args) {\n  struct Cleanup {\n    ~Cleanup() { exceptions_internal::UnsetCountdown(); }\n  } c;\n  for (int count = 0;; ++count) {\n    exceptions_internal::ConstructorTracker ct(count);\n    exceptions_internal::SetCountdown(count);\n    try {\n      T temp(std::forward<Args>(args)...);\n      static_cast<void>(temp);\n      break;\n    } catch (const exceptions_internal::TestException&) {\n    }\n  }\n}\n\n// Tests the nothrow guarantee of the provided nullary operation. If the an\n// exception is thrown, the result will be AssertionFailure(). Otherwise, it\n// will be AssertionSuccess().\ntemplate <typename Operation>\ntesting::AssertionResult TestNothrowOp(const Operation& operation) {\n  struct Cleanup {\n    Cleanup() { exceptions_internal::SetCountdown(); }\n    ~Cleanup() { exceptions_internal::UnsetCountdown(); }\n  } c;\n  try {\n    operation();\n    return testing::AssertionSuccess();\n  } catch (const exceptions_internal::TestException&) {\n    return testing::AssertionFailure()\n           << \"TestException thrown during call to operation() when nothrow \"\n              \"guarantee was expected.\";\n  } catch (...) {\n    return testing::AssertionFailure()\n           << \"Unknown exception thrown during call to operation() when \"\n              \"nothrow guarantee was expected.\";\n  }\n}\n\nnamespace exceptions_internal {\n\n// Dummy struct for ExceptionSafetyTestBuilder<> partial state.\nstruct UninitializedT {};\n\ntemplate <typename T>\nclass DefaultFactory {\n public:\n  explicit DefaultFactory(const T& t) : t_(t) {}\n  std::unique_ptr<T> operator()() const { return absl::make_unique<T>(t_); }\n\n private:\n  T t_;\n};\n\ntemplate <size_t LazyContractsCount, typename LazyFactory,\n          typename LazyOperation>\nusing EnableIfTestable = typename absl::enable_if_t<\n    LazyContractsCount != 0 &&\n    !std::is_same<LazyFactory, UninitializedT>::value &&\n    !std::is_same<LazyOperation, UninitializedT>::value>;\n\ntemplate <typename Factory = UninitializedT,\n          typename Operation = UninitializedT, typename... Contracts>\nclass ExceptionSafetyTestBuilder;\n\n}  // namespace exceptions_internal\n\n/*\n * Constructs an empty ExceptionSafetyTestBuilder. All\n * ExceptionSafetyTestBuilder objects are immutable and all With[thing] mutation\n * methods return new instances of ExceptionSafetyTestBuilder.\n *\n * In order to test a T for exception safety, a factory for that T, a testable\n * operation, and at least one contract callback returning an assertion\n * result must be applied using the respective methods.\n */\nexceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester();\n\nnamespace exceptions_internal {\ntemplate <typename T>\nstruct IsUniquePtr : std::false_type {};\n\ntemplate <typename T, typename D>\nstruct IsUniquePtr<std::unique_ptr<T, D>> : std::true_type {};\n\ntemplate <typename Factory>\nstruct FactoryPtrTypeHelper {\n  using type = decltype(std::declval<const Factory&>()());\n\n  static_assert(IsUniquePtr<type>::value, \"Factories must return a unique_ptr\");\n};\n\ntemplate <typename Factory>\nusing FactoryPtrType = typename FactoryPtrTypeHelper<Factory>::type;\n\ntemplate <typename Factory>\nusing FactoryElementType = typename FactoryPtrType<Factory>::element_type;\n\ntemplate <typename T>\nclass ExceptionSafetyTest {\n  using Factory = std::function<std::unique_ptr<T>()>;\n  using Operation = std::function<void(T*)>;\n  using Contract = std::function<AssertionResult(T*)>;\n\n public:\n  template <typename... Contracts>\n  explicit ExceptionSafetyTest(const Factory& f, const Operation& op,\n                               const Contracts&... contracts)\n      : factory_(f), operation_(op), contracts_{WrapContract(contracts)...} {}\n\n  AssertionResult Test() const {\n    for (int count = 0;; ++count) {\n      exceptions_internal::ConstructorTracker ct(count);\n\n      for (const auto& contract : contracts_) {\n        auto t_ptr = factory_();\n        try {\n          SetCountdown(count);\n          operation_(t_ptr.get());\n          // Unset for the case that the operation throws no exceptions, which\n          // would leave the countdown set and break the *next* exception safety\n          // test after this one.\n          UnsetCountdown();\n          return AssertionSuccess();\n        } catch (const exceptions_internal::TestException& e) {\n          if (!contract(t_ptr.get())) {\n            return AssertionFailure() << e.what() << \" failed contract check\";\n          }\n        }\n      }\n    }\n  }\n\n private:\n  template <typename ContractFn>\n  Contract WrapContract(const ContractFn& contract) {\n    return [contract](T* t_ptr) { return AssertionResult(contract(t_ptr)); };\n  }\n\n  Contract WrapContract(StrongGuaranteeTagType) {\n    return [this](T* t_ptr) { return AssertionResult(*factory_() == *t_ptr); };\n  }\n\n  Factory factory_;\n  Operation operation_;\n  std::vector<Contract> contracts_;\n};\n\n/*\n * Builds a tester object that tests if performing a operation on a T follows\n * exception safety guarantees. Verification is done via contract assertion\n * callbacks applied to T instances post-throw.\n *\n * Template parameters for ExceptionSafetyTestBuilder:\n *\n * - Factory: The factory object (passed in via tester.WithFactory(...) or\n *   tester.WithInitialValue(...)) must be invocable with the signature\n *   `std::unique_ptr<T> operator()() const` where T is the type being tested.\n *   It is used for reliably creating identical T instances to test on.\n *\n * - Operation: The operation object (passed in via tester.WithOperation(...)\n *   or tester.Test(...)) must be invocable with the signature\n *   `void operator()(T*) const` where T is the type being tested. It is used\n *   for performing steps on a T instance that may throw and that need to be\n *   checked for exception safety. Each call to the operation will receive a\n *   fresh T instance so it's free to modify and destroy the T instances as it\n *   pleases.\n *\n * - Contracts...: The contract assertion callback objects (passed in via\n *   tester.WithContracts(...)) must be invocable with the signature\n *   `testing::AssertionResult operator()(T*) const` where T is the type being\n *   tested. Contract assertion callbacks are provided T instances post-throw.\n *   They must return testing::AssertionSuccess when the type contracts of the\n *   provided T instance hold. If the type contracts of the T instance do not\n *   hold, they must return testing::AssertionFailure. Execution order of\n *   Contracts... is unspecified. They will each individually get a fresh T\n *   instance so they are free to modify and destroy the T instances as they\n *   please.\n */\ntemplate <typename Factory, typename Operation, typename... Contracts>\nclass ExceptionSafetyTestBuilder {\n public:\n  /*\n   * Returns a new ExceptionSafetyTestBuilder with an included T factory based\n   * on the provided T instance. The existing factory will not be included in\n   * the newly created tester instance. The created factory returns a new T\n   * instance by copy-constructing the provided const T& t.\n   *\n   * Preconditions for tester.WithInitialValue(const T& t):\n   *\n   * - The const T& t object must be copy-constructible where T is the type\n   *   being tested. For non-copy-constructible objects, use the method\n   *   tester.WithFactory(...).\n   */\n  template <typename T>\n  ExceptionSafetyTestBuilder<DefaultFactory<T>, Operation, Contracts...>\n  WithInitialValue(const T& t) const {\n    return WithFactory(DefaultFactory<T>(t));\n  }\n\n  /*\n   * Returns a new ExceptionSafetyTestBuilder with the provided T factory\n   * included. The existing factory will not be included in the newly-created\n   * tester instance. This method is intended for use with types lacking a copy\n   * constructor. Types that can be copy-constructed should instead use the\n   * method tester.WithInitialValue(...).\n   */\n  template <typename NewFactory>\n  ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...>\n  WithFactory(const NewFactory& new_factory) const {\n    return {new_factory, operation_, contracts_};\n  }\n\n  /*\n   * Returns a new ExceptionSafetyTestBuilder with the provided testable\n   * operation included. The existing operation will not be included in the\n   * newly created tester.\n   */\n  template <typename NewOperation>\n  ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...>\n  WithOperation(const NewOperation& new_operation) const {\n    return {factory_, new_operation, contracts_};\n  }\n\n  /*\n   * Returns a new ExceptionSafetyTestBuilder with the provided MoreContracts...\n   * combined with the Contracts... that were already included in the instance\n   * on which the method was called. Contracts... cannot be removed or replaced\n   * once added to an ExceptionSafetyTestBuilder instance. A fresh object must\n   * be created in order to get an empty Contracts... list.\n   *\n   * In addition to passing in custom contract assertion callbacks, this method\n   * accepts `testing::strong_guarantee` as an argument which checks T instances\n   * post-throw against freshly created T instances via operator== to verify\n   * that any state changes made during the execution of the operation were\n   * properly rolled back.\n   */\n  template <typename... MoreContracts>\n  ExceptionSafetyTestBuilder<Factory, Operation, Contracts...,\n                             absl::decay_t<MoreContracts>...>\n  WithContracts(const MoreContracts&... more_contracts) const {\n    return {\n        factory_, operation_,\n        std::tuple_cat(contracts_, std::tuple<absl::decay_t<MoreContracts>...>(\n                                       more_contracts...))};\n  }\n\n  /*\n   * Returns a testing::AssertionResult that is the reduced result of the\n   * exception safety algorithm. The algorithm short circuits and returns\n   * AssertionFailure after the first contract callback returns an\n   * AssertionFailure. Otherwise, if all contract callbacks return an\n   * AssertionSuccess, the reduced result is AssertionSuccess.\n   *\n   * The passed-in testable operation will not be saved in a new tester instance\n   * nor will it modify/replace the existing tester instance. This is useful\n   * when each operation being tested is unique and does not need to be reused.\n   *\n   * Preconditions for tester.Test(const NewOperation& new_operation):\n   *\n   * - May only be called after at least one contract assertion callback and a\n   *   factory or initial value have been provided.\n   */\n  template <\n      typename NewOperation,\n      typename = EnableIfTestable<sizeof...(Contracts), Factory, NewOperation>>\n  testing::AssertionResult Test(const NewOperation& new_operation) const {\n    return TestImpl(new_operation, absl::index_sequence_for<Contracts...>());\n  }\n\n  /*\n   * Returns a testing::AssertionResult that is the reduced result of the\n   * exception safety algorithm. The algorithm short circuits and returns\n   * AssertionFailure after the first contract callback returns an\n   * AssertionFailure. Otherwise, if all contract callbacks return an\n   * AssertionSuccess, the reduced result is AssertionSuccess.\n   *\n   * Preconditions for tester.Test():\n   *\n   * - May only be called after at least one contract assertion callback, a\n   *   factory or initial value and a testable operation have been provided.\n   */\n  template <\n      typename LazyOperation = Operation,\n      typename = EnableIfTestable<sizeof...(Contracts), Factory, LazyOperation>>\n  testing::AssertionResult Test() const {\n    return Test(operation_);\n  }\n\n private:\n  template <typename, typename, typename...>\n  friend class ExceptionSafetyTestBuilder;\n\n  friend ExceptionSafetyTestBuilder<> testing::MakeExceptionSafetyTester();\n\n  ExceptionSafetyTestBuilder() {}\n\n  ExceptionSafetyTestBuilder(const Factory& f, const Operation& o,\n                             const std::tuple<Contracts...>& i)\n      : factory_(f), operation_(o), contracts_(i) {}\n\n  template <typename SelectedOperation, size_t... Indices>\n  testing::AssertionResult TestImpl(SelectedOperation selected_operation,\n                                    absl::index_sequence<Indices...>) const {\n    return ExceptionSafetyTest<FactoryElementType<Factory>>(\n               factory_, selected_operation, std::get<Indices>(contracts_)...)\n        .Test();\n  }\n\n  Factory factory_;\n  Operation operation_;\n  std::tuple<Contracts...> contracts_;\n};\n\n}  // namespace exceptions_internal\n\n}  // namespace testing\n\n#endif  // ABSL_HAVE_EXCEPTIONS\n\n#endif  // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_\n"
  },
  {
    "path": "absl/base/internal/exception_testing.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Testing utilities for ABSL types which throw exceptions.\n\n#ifndef ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_\n#define ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\n// ABSL_BASE_INTERNAL_EXPECT_FAIL tests either for a specified thrown exception\n// if exceptions are enabled, or for death with a specified text in the error\n// message\n#ifdef ABSL_HAVE_EXCEPTIONS\n\n#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \\\n  EXPECT_THROW(expr, exception_t)\n\n#elif defined(__ANDROID__)\n// Android asserts do not log anywhere that gtest can currently inspect.\n// So we expect exit, but cannot match the message.\n#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \\\n  EXPECT_DEATH(expr, \".*\")\n#else\n#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \\\n  EXPECT_DEATH_IF_SUPPORTED(expr, text)\n\n#endif\n\n#endif  // ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_\n"
  },
  {
    "path": "absl/base/internal/hardening.cc",
    "content": "//\n// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifdef _WIN32\n#include <intrin.h>\n// kFastFailRangeCheckFailure mirrors the FAST_FAIL_RANGE_CHECK_FAILURE macro.\n// Typically FAST_FAIL_RANGE_CHECK_FAILURE would be imported from winnt.h\n// but winnt.h pulls in other dependencies and introduces build failures.\nconstexpr unsigned int kFastFailRangeCheckFailure = 8u;\n#endif\n\n#include \"absl/base/internal/hardening.h\"\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace base_internal {\n\n[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void FailedBoundsCheckAbort() {\n#ifdef _WIN32\n  __fastfail(kFastFailRangeCheckFailure);\n#else\n  ABSL_INTERNAL_HARDENING_ABORT();\n#endif\n}\n\n}  // namespace base_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/hardening.h",
    "content": "//\n// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: hardening.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines macros and functions for checking bounds on\n// accesses to Abseil container types.\n\n#ifndef ABSL_BASE_INTERNAL_HARDENING_H_\n#define ABSL_BASE_INTERNAL_HARDENING_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/options.h\"\n\n#ifdef ABSL_INTERNAL_ATTRIBUTE_NO_MERGE\n#error ABSL_INTERNAL_ATTRIBUTE_NO_MERGE cannot be directly set\n#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::nomerge)\n#define ABSL_INTERNAL_ATTRIBUTE_NO_MERGE [[clang::nomerge]]\n#else\n#define ABSL_INTERNAL_ATTRIBUTE_NO_MERGE\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace base_internal {\n\n[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void FailedBoundsCheckAbort();\n\ninline void HardeningAssertInBounds(size_t index, size_t size) {\n#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)\n  if (ABSL_PREDICT_FALSE(index >= size)) {\n    ABSL_INTERNAL_ATTRIBUTE_NO_MERGE FailedBoundsCheckAbort();\n  }\n#else\n  ABSL_ASSERT(index < size);\n#endif\n}\n\n}  // namespace base_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_INTERNAL_ATTRIBUTE_NO_MERGE\n\n#endif  // ABSL_BASE_INTERNAL_HARDENING_H_\n"
  },
  {
    "path": "absl/base/internal/hardening_test.cc",
    "content": "// Copyright 2026 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/hardening.h\"\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/options.h\"\n\nnamespace {\n\nTEST(BoundsCheckTest, HardeningAssertInBounds) {\n  absl::base_internal::HardeningAssertInBounds(0, 10);\n}\n\nTEST(BoundsChecksDeathTest, HardeningAssertInBounds) {\n#if GTEST_HAS_DEATH_TEST && (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1 || \\\n                                                  ABSL_OPTION_HARDENED == 2))\n  // The underlying mechanism of termination varies, and may include SIGILL\n  // or SIGABRT.\n  EXPECT_DEATH(absl::base_internal::HardeningAssertInBounds(10, 10), \"\");\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/hide_ptr.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_HIDE_PTR_H_\n#define ABSL_BASE_INTERNAL_HIDE_PTR_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Arbitrary value with high bits set. Xor'ing with it is unlikely\n// to map one valid pointer to another valid pointer.\nconstexpr uintptr_t HideMask() {\n  return (uintptr_t{0xF03A5F7BU} << (sizeof(uintptr_t) - 4) * 8) | 0xF03A5F7BU;\n}\n\n// Hide a pointer from the leak checker. For internal use only.\n// Differs from absl::IgnoreLeak(ptr) in that absl::IgnoreLeak(ptr) causes ptr\n// and all objects reachable from ptr to be ignored by the leak checker.\ntemplate <class T>\ninline uintptr_t HidePtr(T* ptr) {\n  return reinterpret_cast<uintptr_t>(ptr) ^ HideMask();\n}\n\n// Return a pointer that has been hidden from the leak checker.\n// For internal use only.\ntemplate <class T>\ninline T* UnhidePtr(uintptr_t hidden) {\n  return reinterpret_cast<T*>(hidden ^ HideMask());\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_HIDE_PTR_H_\n"
  },
  {
    "path": "absl/base/internal/iterator_traits.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: internal/iterator_traits.h\n// -----------------------------------------------------------------------------\n//\n// Helpers for querying traits of iterators, for implementing containers, etc.\n\n#ifndef ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_\n#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_\n\n#include <iterator>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\ntemplate <typename Iterator, typename = void>\nstruct IteratorCategory {};\n\ntemplate <typename Iterator>\nstruct IteratorCategory<\n    Iterator,\n    absl::void_t<typename std::iterator_traits<Iterator>::iterator_category>> {\n  using type = typename std::iterator_traits<Iterator>::iterator_category;\n};\n\ntemplate <typename Iterator, typename = void>\nstruct IteratorConceptImpl : IteratorCategory<Iterator> {};\n\ntemplate <typename Iterator>\nstruct IteratorConceptImpl<\n    Iterator,\n    absl::void_t<typename std::iterator_traits<Iterator>::iterator_concept>> {\n  using type = typename std::iterator_traits<Iterator>::iterator_concept;\n};\n\n// The newer `std::iterator_traits<Iterator>::iterator_concept` if available,\n// else `std::iterator_traits<Iterator>::iterator_category`.\ntemplate <typename Iterator>\nusing IteratorConcept = typename IteratorConceptImpl<Iterator>::type;\n\ntemplate <typename IteratorTag, typename Iterator>\nusing IsAtLeastIterator =\n    std::is_convertible<IteratorConcept<Iterator>, IteratorTag>;\n\ntemplate <typename Iterator>\nusing IsAtLeastInputIterator =\n    IsAtLeastIterator<std::input_iterator_tag, Iterator>;\n\ntemplate <typename Iterator>\nusing IsAtLeastForwardIterator =\n    IsAtLeastIterator<std::forward_iterator_tag, Iterator>;\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_\n"
  },
  {
    "path": "absl/base/internal/iterator_traits_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/iterator_traits.h\"\n\n#include <forward_list>\n#include <iterator>\n#include <list>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/iterator_traits_test_helper.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\nTEST(IsAtLeastIteratorTest, IsAtLeastIterator) {\n  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag, int*>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag, int*>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag, int*>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::random_access_iterator_tag, int*>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,\n                                 std::vector<int>::iterator>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,\n                                 std::vector<int>::iterator>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag,\n                                 std::vector<int>::iterator>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::random_access_iterator_tag,\n                                 std::vector<int>::iterator>()));\n\n  EXPECT_TRUE(\n      (IsAtLeastIterator<std::input_iterator_tag, std::list<int>::iterator>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,\n                                 std::list<int>::iterator>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag,\n                                 std::list<int>::iterator>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,\n                                  std::list<int>::iterator>()));\n\n  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,\n                                 std::forward_list<int>::iterator>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,\n                                 std::forward_list<int>::iterator>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,\n                                  std::forward_list<int>::iterator>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,\n                                  std::forward_list<int>::iterator>()));\n\n  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,\n                                 std::istream_iterator<int>>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::forward_iterator_tag,\n                                  std::istream_iterator<int>>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,\n                                  std::istream_iterator<int>>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,\n                                  std::istream_iterator<int>>()));\n\n  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,\n                                 Cpp20ForwardZipIterator<int*>>()));\n  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,\n                                 Cpp20ForwardZipIterator<int*>>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,\n                                  Cpp20ForwardZipIterator<int*>>()));\n  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,\n                                  Cpp20ForwardZipIterator<int*>>()));\n}\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/iterator_traits_test_helper.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_\n#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_\n\n#include <iterator>\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// This would be a forward_iterator in C++20, but it's only an input iterator\n// before that, since it has a non-reference `reference`.\ntemplate <typename Iterator>\nclass Cpp20ForwardZipIterator {\n  using IteratorReference = typename std::iterator_traits<Iterator>::reference;\n\n public:\n  Cpp20ForwardZipIterator() = default;\n  explicit Cpp20ForwardZipIterator(Iterator left, Iterator right)\n      : left_(left), right_(right) {}\n\n  Cpp20ForwardZipIterator& operator++() {\n    ++left_;\n    ++right_;\n    return *this;\n  }\n\n  Cpp20ForwardZipIterator operator++(int) {\n    Cpp20ForwardZipIterator tmp(*this);\n    ++*this;\n    return *this;\n  }\n\n  std::pair<IteratorReference, IteratorReference> operator*() const {\n    return {*left_, *right_};\n  }\n\n  // C++17 input iterators require `operator->`, but this isn't  possible to\n  // implement. C++20 dropped the requirement.\n\n  friend bool operator==(const Cpp20ForwardZipIterator& lhs,\n                         const Cpp20ForwardZipIterator& rhs) {\n    return lhs.left_ == rhs.left_ && lhs.right_ == rhs.right_;\n  }\n\n  friend bool operator!=(const Cpp20ForwardZipIterator& lhs,\n                         const Cpp20ForwardZipIterator& rhs) {\n    return !(lhs == rhs);\n  }\n\n private:\n  Iterator left_{};\n  Iterator right_{};\n};\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\ntemplate <typename Iterator>\nstruct std::iterator_traits<\n    absl::base_internal::Cpp20ForwardZipIterator<Iterator>> {\n private:\n  using IteratorReference = typename std::iterator_traits<Iterator>::reference;\n\n public:\n  using iterator_category = std::input_iterator_tag;\n  using iterator_concept = std::forward_iterator_tag;\n  using value_type = std::pair<IteratorReference, IteratorReference>;\n  using difference_type =\n      typename std::iterator_traits<Iterator>::difference_type;\n  using reference = value_type;\n  using pointer = void;\n};\n\n#if defined(__cpp_lib_concepts)\nstatic_assert(\n    std::forward_iterator<absl::base_internal::Cpp20ForwardZipIterator<int*>>);\n#endif  // defined(__cpp_lib_concepts)\n\n#endif  // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_\n"
  },
  {
    "path": "absl/base/internal/low_level_alloc.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// A low-level allocator that can be used by other low-level\n// modules without introducing dependency cycles.\n// This allocator is slow and wasteful of memory;\n// it should not be used when performance is key.\n\n#include \"absl/base/internal/low_level_alloc.h\"\n\n#include <stdint.h>\n\n#include <optional>\n#include <type_traits>\n\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/direct_mmap.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/thread_annotations.h\"\n\n// LowLevelAlloc requires that the platform support low-level\n// allocation of virtual memory. Platforms lacking this cannot use\n// LowLevelAlloc.\n#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING\n\n#ifndef _WIN32\n#include <pthread.h>\n#include <signal.h>\n#include <sys/mman.h>\n#include <unistd.h>\n#else\n#include <windows.h>\n#endif\n\n#ifdef __linux__\n#include <sys/prctl.h>\n#endif\n\n#include <string.h>\n\n#include <algorithm>\n#include <atomic>\n#include <cerrno>\n#include <cstddef>\n#include <new>  // for placement-new\n\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/spinlock.h\"\n\n#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// A first-fit allocator with amortized logarithmic free() time.\n\n// ---------------------------------------------------------------------------\nstatic const int kMaxLevel = 30;\n\nnamespace {\n// This struct describes one allocated block, or one free block.\nstruct AllocList {\n  struct Header {\n    // Size of entire region, including this field. Must be\n    // first. Valid in both allocated and unallocated blocks.\n    uintptr_t size;\n\n    // kMagicAllocated or kMagicUnallocated xor this.\n    uintptr_t magic;\n\n    // Pointer to parent arena.\n    LowLevelAlloc::Arena *arena;\n\n    // Aligns regions to 0 mod 2*sizeof(void*).\n    void *dummy_for_alignment;\n  } header;\n\n  // Next two fields: in unallocated blocks: freelist skiplist data\n  //                  in allocated blocks: overlaps with client data\n\n  // Levels in skiplist used.\n  int levels;\n\n  // Actually has levels elements. The AllocList node may not have room\n  // for all kMaxLevel entries. See max_fit in LLA_SkiplistLevels().\n  AllocList *next[kMaxLevel];\n};\n}  // namespace\n\n// ---------------------------------------------------------------------------\n// A trivial skiplist implementation.  This is used to keep the freelist\n// in address order while taking only logarithmic time per insert and delete.\n\n// An integer approximation of log2(size/base)\n// Requires size >= base.\nstatic int IntLog2(size_t size, size_t base) {\n  int result = 0;\n  for (size_t i = size; i > base; i >>= 1) {  // i == floor(size/2**result)\n    result++;\n  }\n  //    floor(size / 2**result) <= base < floor(size / 2**(result-1))\n  // =>     log2(size/(base+1)) <= result < 1+log2(size/base)\n  // => result ~= log2(size/base)\n  return result;\n}\n\n// Return a random integer n:  p(n)=1/(2**n) if 1 <= n; p(n)=0 if n < 1.\nstatic int Random(uint32_t *state) {\n  uint32_t r = *state;\n  int result = 1;\n  while ((((r = r * 1103515245 + 12345) >> 30) & 1) == 0) {\n    result++;\n  }\n  *state = r;\n  return result;\n}\n\n// Return a number of skiplist levels for a node of size bytes, where\n// base is the minimum node size.  Compute level=log2(size / base)+n\n// where n is 1 if random is false and otherwise a random number generated with\n// the standard distribution for a skiplist:  See Random() above.\n// Bigger nodes tend to have more skiplist levels due to the log2(size / base)\n// term, so first-fit searches touch fewer nodes.  \"level\" is clipped so\n// level<kMaxLevel and next[level-1] will fit in the node.\n// 0 < LLA_SkiplistLevels(x,y,false) <= LLA_SkiplistLevels(x,y,true) < kMaxLevel\nstatic int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) {\n  // max_fit is the maximum number of levels that will fit in a node for the\n  // given size.   We can't return more than max_fit, no matter what the\n  // random number generator says.\n  size_t max_fit = (size - offsetof(AllocList, next)) / sizeof(AllocList *);\n  int level = IntLog2(size, base) + (random != nullptr ? Random(random) : 1);\n  if (static_cast<size_t>(level) > max_fit) level = static_cast<int>(max_fit);\n  if (level > kMaxLevel - 1) level = kMaxLevel - 1;\n  ABSL_RAW_CHECK(level >= 1, \"block not big enough for even one level\");\n  return level;\n}\n\n// Return \"atleast\", the first element of AllocList *head s.t. *atleast >= *e.\n// For 0 <= i < head->levels, set prev[i] to \"no_greater\", where no_greater\n// points to the last element at level i in the AllocList less than *e, or is\n// head if no such element exists.\nstatic AllocList *LLA_SkiplistSearch(AllocList *head, AllocList *e,\n                                     AllocList **prev) {\n  AllocList *p = head;\n  for (int level = head->levels - 1; level >= 0; level--) {\n    for (AllocList *n; (n = p->next[level]) != nullptr && n < e; p = n) {\n    }\n    prev[level] = p;\n  }\n  return (head->levels == 0) ? nullptr : prev[0]->next[0];\n}\n\n// Insert element *e into AllocList *head.  Set prev[] as LLA_SkiplistSearch.\n// Requires that e->levels be previously set by the caller (using\n// LLA_SkiplistLevels())\nstatic void LLA_SkiplistInsert(AllocList *head, AllocList *e,\n                               AllocList **prev) {\n  LLA_SkiplistSearch(head, e, prev);\n  for (; head->levels < e->levels; head->levels++) {  // extend prev pointers\n    prev[head->levels] = head;                        // to all *e's levels\n  }\n  for (int i = 0; i != e->levels; i++) {  // add element to list\n    e->next[i] = prev[i]->next[i];\n    prev[i]->next[i] = e;\n  }\n}\n\n// Remove element *e from AllocList *head.  Set prev[] as LLA_SkiplistSearch().\n// Requires that e->levels be previous set by the caller (using\n// LLA_SkiplistLevels())\nstatic void LLA_SkiplistDelete(AllocList *head, AllocList *e,\n                               AllocList **prev) {\n  AllocList *found = LLA_SkiplistSearch(head, e, prev);\n  ABSL_RAW_CHECK(e == found, \"element not in freelist\");\n  for (int i = 0; i != e->levels && prev[i]->next[i] == e; i++) {\n    prev[i]->next[i] = e->next[i];\n  }\n  while (head->levels > 0 && head->next[head->levels - 1] == nullptr) {\n    head->levels--;  // reduce head->levels if level unused\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Arena implementation\n\n// Metadata for an LowLevelAlloc arena instance.\nstruct LowLevelAlloc::Arena {\n  // Constructs an arena with the given LowLevelAlloc flags.\n  explicit Arena(uint32_t flags_value);\n\n  base_internal::SpinLock mu;\n  // Head of free list, sorted by address\n  AllocList freelist ABSL_GUARDED_BY(mu);\n  // Count of allocated blocks\n  int32_t allocation_count ABSL_GUARDED_BY(mu);\n  // flags passed to NewArena\n  const uint32_t flags;\n  // Result of sysconf(_SC_PAGESIZE)\n  const size_t pagesize;\n  // Lowest power of two >= max(16, sizeof(AllocList))\n  const size_t round_up;\n  // Smallest allocation block size\n  const size_t min_size;\n  // PRNG state\n  uint32_t random ABSL_GUARDED_BY(mu);\n};\n\n// ---------------------------------------------------------------\n// An async-signal-safe arena for LowLevelAlloc\nstatic std::atomic<base_internal::LowLevelAlloc::Arena *> g_sig_safe_arena;\n\nbase_internal::LowLevelAlloc::Arena *SigSafeArena() {\n  return g_sig_safe_arena.load(std::memory_order_acquire);\n}\n\nvoid InitSigSafeArena() {\n  if (SigSafeArena() == nullptr) {\n    uint32_t flags = 0;\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n    flags |= base_internal::LowLevelAlloc::kAsyncSignalSafe;\n#endif\n    base_internal::LowLevelAlloc::Arena *new_arena =\n        base_internal::LowLevelAlloc::NewArena(flags);\n    base_internal::LowLevelAlloc::Arena *old_value = nullptr;\n    if (!g_sig_safe_arena.compare_exchange_strong(old_value, new_arena,\n                                                  std::memory_order_release,\n                                                  std::memory_order_relaxed)) {\n      // We lost a race to allocate an arena; deallocate.\n      base_internal::LowLevelAlloc::DeleteArena(new_arena);\n    }\n  }\n}\n\nnamespace {\n// Static storage space for the lazily-constructed, default global arena\n// instances.  We require this space because the whole point of LowLevelAlloc\n// is to avoid relying on malloc/new.\nalignas(LowLevelAlloc::Arena) unsigned char default_arena_storage[sizeof(\n    LowLevelAlloc::Arena)];\nalignas(LowLevelAlloc::Arena) unsigned char unhooked_arena_storage[sizeof(\n    LowLevelAlloc::Arena)];\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\nalignas(\n    LowLevelAlloc::Arena) unsigned char unhooked_async_sig_safe_arena_storage\n    [sizeof(LowLevelAlloc::Arena)];\n#endif\n\n// We must use LowLevelCallOnce here to construct the global arenas, rather than\n// using function-level statics, to avoid recursively invoking the scheduler.\nabsl::once_flag create_globals_once;\n\nvoid CreateGlobalArenas() {\n  new (&default_arena_storage)\n      LowLevelAlloc::Arena(LowLevelAlloc::kCallMallocHook);\n  new (&unhooked_arena_storage) LowLevelAlloc::Arena(0);\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n  new (&unhooked_async_sig_safe_arena_storage)\n      LowLevelAlloc::Arena(LowLevelAlloc::kAsyncSignalSafe);\n#endif\n}\n\n// Returns a global arena that does not call into hooks.  Used by NewArena()\n// when kCallMallocHook is not set.\nLowLevelAlloc::Arena *UnhookedArena() {\n  base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);\n  return reinterpret_cast<LowLevelAlloc::Arena *>(&unhooked_arena_storage);\n}\n\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n// Returns a global arena that is async-signal safe.  Used by NewArena() when\n// kAsyncSignalSafe is set.\nLowLevelAlloc::Arena *UnhookedAsyncSigSafeArena() {\n  base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);\n  return reinterpret_cast<LowLevelAlloc::Arena *>(\n      &unhooked_async_sig_safe_arena_storage);\n}\n#endif\n\n}  // namespace\n\n// Returns the default arena, as used by LowLevelAlloc::Alloc() and friends.\nLowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() {\n  base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);\n  return reinterpret_cast<LowLevelAlloc::Arena *>(&default_arena_storage);\n}\n\n// magic numbers to identify allocated and unallocated blocks\nstatic const uintptr_t kMagicAllocated = 0x4c833e95U;\nstatic const uintptr_t kMagicUnallocated = ~kMagicAllocated;\n\nnamespace {\nclass ABSL_SCOPED_LOCKABLE ArenaLock {\n public:\n  explicit ArenaLock(LowLevelAlloc::Arena *arena)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(arena->mu)\n      : arena_(arena) {\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n    if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {\n      sigset_t all;\n      sigfillset(&all);\n      mask_valid_ = pthread_sigmask(SIG_BLOCK, &all, &mask_) == 0;\n    }\n#endif\n    arena_->mu.lock();\n  }\n  ~ArenaLock() { ABSL_RAW_CHECK(left_, \"haven't left Arena region\"); }\n  void Leave() ABSL_UNLOCK_FUNCTION() {\n    arena_->mu.unlock();\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n    if (mask_valid_) {\n      const int err = pthread_sigmask(SIG_SETMASK, &mask_, nullptr);\n      if (err != 0) {\n        ABSL_RAW_LOG(FATAL, \"pthread_sigmask failed: %d\", err);\n      }\n    }\n#endif\n    left_ = true;\n  }\n\n private:\n  bool left_ = false;  // whether left region\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n  bool mask_valid_ = false;\n  sigset_t mask_;  // old mask of blocked signals\n#endif\n  LowLevelAlloc::Arena *arena_;\n  ArenaLock(const ArenaLock &) = delete;\n  ArenaLock &operator=(const ArenaLock &) = delete;\n};\n}  // namespace\n\n// create an appropriate magic number for an object at \"ptr\"\n// \"magic\" should be kMagicAllocated or kMagicUnallocated\ninline static uintptr_t Magic(uintptr_t magic, AllocList::Header *ptr) {\n  return magic ^ reinterpret_cast<uintptr_t>(ptr);\n}\n\nnamespace {\nsize_t GetPageSize() {\n#ifdef _WIN32\n  SYSTEM_INFO system_info;\n  GetSystemInfo(&system_info);\n  return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity);\n#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__)\n  return static_cast<size_t>(getpagesize());\n#else\n  return static_cast<size_t>(sysconf(_SC_PAGESIZE));\n#endif\n}\n\nsize_t RoundedUpBlockSize() {\n  // Round up block sizes to a power of two close to the header size.\n  size_t round_up = 16;\n  while (round_up < sizeof(AllocList::Header)) {\n    round_up += round_up;\n  }\n  return round_up;\n}\n\n}  // namespace\n\nLowLevelAlloc::Arena::Arena(uint32_t flags_value)\n    : mu(base_internal::SCHEDULE_KERNEL_ONLY),\n      allocation_count(0),\n      flags(flags_value),\n      pagesize(GetPageSize()),\n      round_up(RoundedUpBlockSize()),\n      min_size(2 * round_up),\n      random(0) {\n  freelist.header.size = 0;\n  freelist.header.magic = Magic(kMagicUnallocated, &freelist.header);\n  freelist.header.arena = this;\n  freelist.levels = 0;\n  memset(freelist.next, 0, sizeof(freelist.next));\n}\n\n// L < meta_data_arena->mu\nLowLevelAlloc::Arena *LowLevelAlloc::NewArena(uint32_t flags) {\n  Arena *meta_data_arena = DefaultArena();\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n  if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {\n    meta_data_arena = UnhookedAsyncSigSafeArena();\n  } else  // NOLINT(readability/braces)\n#endif\n      if ((flags & LowLevelAlloc::kCallMallocHook) == 0) {\n    meta_data_arena = UnhookedArena();\n  }\n  Arena *result =\n      new (AllocWithArena(sizeof(*result), meta_data_arena)) Arena(flags);\n  return result;\n}\n\n// L < arena->mu, L < arena->arena->mu\nbool LowLevelAlloc::DeleteArena(Arena *arena) {\n  ABSL_RAW_CHECK(\n      arena != nullptr && arena != DefaultArena() && arena != UnhookedArena(),\n      \"may not delete default arena\");\n  ArenaLock section(arena);\n  if (arena->allocation_count != 0) {\n    section.Leave();\n    return false;\n  }\n  while (arena->freelist.next[0] != nullptr) {\n    AllocList *region = arena->freelist.next[0];\n    size_t size = region->header.size;\n    arena->freelist.next[0] = region->next[0];\n    ABSL_RAW_CHECK(\n        region->header.magic == Magic(kMagicUnallocated, &region->header),\n        \"bad magic number in DeleteArena()\");\n    ABSL_RAW_CHECK(region->header.arena == arena,\n                   \"bad arena pointer in DeleteArena()\");\n    ABSL_RAW_CHECK(size % arena->pagesize == 0,\n                   \"empty arena has non-page-aligned block size\");\n    ABSL_RAW_CHECK(reinterpret_cast<uintptr_t>(region) % arena->pagesize == 0,\n                   \"empty arena has non-page-aligned block\");\n    int munmap_result;\n#ifdef _WIN32\n    munmap_result = VirtualFree(region, 0, MEM_RELEASE);\n    ABSL_RAW_CHECK(munmap_result != 0,\n                   \"LowLevelAlloc::DeleteArena: VitualFree failed\");\n#else\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n    if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) == 0) {\n      munmap_result = munmap(region, size);\n    } else {\n      munmap_result = base_internal::DirectMunmap(region, size);\n    }\n#else\n    munmap_result = munmap(region, size);\n#endif  // ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n    if (munmap_result != 0) {\n      ABSL_RAW_LOG(FATAL, \"LowLevelAlloc::DeleteArena: munmap failed: %d\",\n                   errno);\n    }\n#endif  // _WIN32\n  }\n  section.Leave();\n  arena->~Arena();\n  Free(arena);\n  return true;\n}\n\n// ---------------------------------------------------------------------------\n\n// Addition, checking for overflow.  The intent is to die if an external client\n// manages to push through a request that would cause arithmetic to fail.\nstatic inline uintptr_t CheckedAdd(uintptr_t a, uintptr_t b) {\n  uintptr_t sum = a + b;\n  ABSL_RAW_CHECK(sum >= a, \"LowLevelAlloc arithmetic overflow\");\n  return sum;\n}\n\n// Return value rounded up to next multiple of align.\n// align must be a power of two.\nstatic inline uintptr_t RoundUp(uintptr_t addr, uintptr_t align) {\n  return CheckedAdd(addr, align - 1) & ~(align - 1);\n}\n\n// Equivalent to \"return prev->next[i]\" but with sanity checking\n// that the freelist is in the correct order, that it\n// consists of regions marked \"unallocated\", and that no two regions\n// are adjacent in memory (they should have been coalesced).\nstatic AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(arena->mu) {\n  ABSL_RAW_CHECK(i < prev->levels, \"too few levels in Next()\");\n  AllocList *next = prev->next[i];\n  if (next != nullptr) {\n    ABSL_RAW_CHECK(\n        next->header.magic == Magic(kMagicUnallocated, &next->header),\n        \"bad magic number in Next()\");\n    ABSL_RAW_CHECK(next->header.arena == arena, \"bad arena pointer in Next()\");\n    if (prev != &arena->freelist) {\n      ABSL_RAW_CHECK(prev < next, \"unordered freelist\");\n      ABSL_RAW_CHECK(reinterpret_cast<char *>(prev) + prev->header.size <\n                         reinterpret_cast<char *>(next),\n                     \"malformed freelist\");\n    }\n  }\n  return next;\n}\n\n// Coalesce list item \"a\" with its successor if they are adjacent.\nstatic void Coalesce(AllocList *a) {\n  AllocList *n = a->next[0];\n  if (n != nullptr && reinterpret_cast<char *>(a) + a->header.size ==\n                          reinterpret_cast<char *>(n)) {\n    LowLevelAlloc::Arena *arena = a->header.arena;\n    arena->mu.AssertHeld();\n    a->header.size += n->header.size;\n    n->header.magic = 0;\n    n->header.arena = nullptr;\n    AllocList *prev[kMaxLevel];\n    LLA_SkiplistDelete(&arena->freelist, n, prev);\n    LLA_SkiplistDelete(&arena->freelist, a, prev);\n    a->levels =\n        LLA_SkiplistLevels(a->header.size, arena->min_size, &arena->random);\n    LLA_SkiplistInsert(&arena->freelist, a, prev);\n  }\n}\n\n// Adds block at location \"v\" to the free list\nstatic void AddToFreelist(void *v, LowLevelAlloc::Arena *arena)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(arena->mu) {\n  AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -\n                                               sizeof(f->header));\n  ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),\n                 \"bad magic number in AddToFreelist()\");\n  ABSL_RAW_CHECK(f->header.arena == arena,\n                 \"bad arena pointer in AddToFreelist()\");\n  f->levels =\n      LLA_SkiplistLevels(f->header.size, arena->min_size, &arena->random);\n  AllocList *prev[kMaxLevel];\n  LLA_SkiplistInsert(&arena->freelist, f, prev);\n  f->header.magic = Magic(kMagicUnallocated, &f->header);\n  Coalesce(f);        // maybe coalesce with successor\n  Coalesce(prev[0]);  // maybe coalesce with predecessor\n}\n\n// Frees storage allocated by LowLevelAlloc::Alloc().\n// L < arena->mu\nvoid LowLevelAlloc::Free(void *v) {\n  if (v != nullptr) {\n    AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -\n                                                 sizeof(f->header));\n    LowLevelAlloc::Arena *arena = f->header.arena;\n    ArenaLock section(arena);\n    AddToFreelist(v, arena);\n    ABSL_RAW_CHECK(arena->allocation_count > 0, \"nothing in arena to free\");\n    arena->allocation_count--;\n    section.Leave();\n  }\n}\n\n// allocates and returns a block of size bytes, to be freed with Free()\n// L < arena->mu\nstatic void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {\n  void *result = nullptr;\n  if (request != 0) {\n    AllocList *s;  // will point to region that satisfies request\n    ArenaLock section(arena);\n    // round up with header\n    size_t req_rnd =\n        RoundUp(CheckedAdd(request, sizeof(s->header)), arena->round_up);\n    for (;;) {  // loop until we find a suitable region\n      // find the minimum levels that a block of this size must have\n      int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1;\n      if (i < arena->freelist.levels) {        // potential blocks exist\n        AllocList *before = &arena->freelist;  // predecessor of s\n        while ((s = Next(i, before, arena)) != nullptr &&\n               s->header.size < req_rnd) {\n          before = s;\n        }\n        if (s != nullptr) {  // we found a region\n          break;\n        }\n      }\n      // we unlock before mmap() both because mmap() may call a callback hook,\n      // and because it may be slow.\n      arena->mu.unlock();\n      // mmap generous 64K chunks to decrease\n      // the chances/impact of fragmentation:\n      size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16);\n      void *new_pages;\n#ifdef _WIN32\n      new_pages = VirtualAlloc(nullptr, new_pages_size,\n                               MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);\n      ABSL_RAW_CHECK(new_pages != nullptr, \"VirtualAlloc failed\");\n#else\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n      if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {\n        new_pages = base_internal::DirectMmap(nullptr, new_pages_size,\n            PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);\n      } else {\n        new_pages = mmap(nullptr, new_pages_size, PROT_WRITE | PROT_READ,\n                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n      }\n#else\n      new_pages = mmap(nullptr, new_pages_size, PROT_WRITE | PROT_READ,\n                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n#endif  // ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n      if (new_pages == MAP_FAILED) {\n        ABSL_RAW_LOG(FATAL, \"mmap error: %d\", errno);\n      }\n\n#ifdef __linux__\n#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)\n      // Attempt to name the allocated address range in /proc/$PID/smaps on\n      // Linux.\n      //\n      // This invocation of prctl() may fail if the Linux kernel was not\n      // configured with the CONFIG_ANON_VMA_NAME option.  This is OK since\n      // the naming of arenas is primarily a debugging aid.\n      prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, new_pages, new_pages_size,\n            \"absl\");\n#endif\n#endif  // __linux__\n#endif  // _WIN32\n      arena->mu.lock();\n      s = reinterpret_cast<AllocList *>(new_pages);\n      s->header.size = new_pages_size;\n      // Pretend the block is allocated; call AddToFreelist() to free it.\n      s->header.magic = Magic(kMagicAllocated, &s->header);\n      s->header.arena = arena;\n      AddToFreelist(&s->levels, arena);  // insert new region into free list\n    }\n    AllocList *prev[kMaxLevel];\n    LLA_SkiplistDelete(&arena->freelist, s, prev);  // remove from free list\n    // s points to the first free region that's big enough\n    if (CheckedAdd(req_rnd, arena->min_size) <= s->header.size) {\n      // big enough to split\n      AllocList *n =\n          reinterpret_cast<AllocList *>(req_rnd + reinterpret_cast<char *>(s));\n      n->header.size = s->header.size - req_rnd;\n      n->header.magic = Magic(kMagicAllocated, &n->header);\n      n->header.arena = arena;\n      s->header.size = req_rnd;\n      AddToFreelist(&n->levels, arena);\n    }\n    s->header.magic = Magic(kMagicAllocated, &s->header);\n    ABSL_RAW_CHECK(s->header.arena == arena, \"\");\n    arena->allocation_count++;\n    section.Leave();\n    result = &s->levels;\n  }\n  ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);\n  return result;\n}\n\nvoid *LowLevelAlloc::Alloc(size_t request) {\n  void *result = DoAllocWithArena(request, DefaultArena());\n  return result;\n}\n\nvoid *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) {\n  ABSL_RAW_CHECK(arena != nullptr, \"must pass a valid arena\");\n  void *result = DoAllocWithArena(request, arena);\n  return result;\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOW_LEVEL_ALLOC_MISSING\n"
  },
  {
    "path": "absl/base/internal/low_level_alloc.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_\n#define ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_\n\n// A simple thread-safe memory allocator that does not depend on\n// mutexes or thread-specific data.  It is intended to be used\n// sparingly, and only when malloc() would introduce an unwanted\n// dependency, such as inside the heap-checker, or the Mutex\n// implementation.\n\n// IWYU pragma: private, include \"base/low_level_alloc.h\"\n\n#include <sys/types.h>\n\n#include <cstdint>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n// LowLevelAlloc requires that the platform support low-level\n// allocation of virtual memory. Platforms lacking this cannot use\n// LowLevelAlloc.\n#ifdef ABSL_LOW_LEVEL_ALLOC_MISSING\n#error ABSL_LOW_LEVEL_ALLOC_MISSING cannot be directly set\n#elif !defined(ABSL_HAVE_MMAP) && !defined(_WIN32)\n#define ABSL_LOW_LEVEL_ALLOC_MISSING 1\n#endif\n\n// Using LowLevelAlloc with kAsyncSignalSafe isn't supported on Windows or\n// asm.js / WebAssembly.\n// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html\n// for more information.\n#ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n#error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set\n#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) || \\\n    defined(__hexagon__)\n#define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1\n#endif\n\n#include <cstddef>\n\n#include \"absl/base/port.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nclass LowLevelAlloc {\n public:\n  struct Arena;       // an arena from which memory may be allocated\n\n  // Returns a pointer to a block of at least \"request\" bytes\n  // that have been newly allocated from the specific arena.\n  // for Alloc() call the DefaultArena() is used.\n  // Returns 0 if passed request==0.\n  // Does not return 0 under other circumstances; it crashes if memory\n  // is not available.\n  static void *Alloc(size_t request) ABSL_ATTRIBUTE_SECTION(malloc_hook);\n  static void *AllocWithArena(size_t request, Arena *arena)\n      ABSL_ATTRIBUTE_SECTION(malloc_hook);\n\n  // Deallocates a region of memory that was previously allocated with\n  // Alloc().   Does nothing if passed 0.   \"s\" must be either 0,\n  // or must have been returned from a call to Alloc() and not yet passed to\n  // Free() since that call to Alloc().  The space is returned to the arena\n  // from which it was allocated.\n  static void Free(void *s) ABSL_ATTRIBUTE_SECTION(malloc_hook);\n\n  // ABSL_ATTRIBUTE_SECTION(malloc_hook) for Alloc* and Free\n  // are to put all callers of MallocHook::Invoke* in this module\n  // into special section,\n  // so that MallocHook::GetCallerStackTrace can function accurately.\n\n  // Create a new arena.\n  // The root metadata for the new arena is allocated in the\n  // meta_data_arena; the DefaultArena() can be passed for meta_data_arena.\n  // These values may be ored into flags:\n  enum {\n    // Report calls to Alloc() and Free() via the MallocHook interface.\n    // Set in the DefaultArena.\n    kCallMallocHook = 0x0001,\n\n#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING\n    // Make calls to Alloc(), Free() be async-signal-safe. Not set in\n    // DefaultArena(). Not supported on all platforms.\n    kAsyncSignalSafe = 0x0002,\n#endif\n  };\n  // Construct a new arena.  The allocation of the underlying metadata honors\n  // the provided flags.  For example, the call NewArena(kAsyncSignalSafe)\n  // is itself async-signal-safe, as well as generatating an arena that provides\n  // async-signal-safe Alloc/Free.\n  static Arena *NewArena(uint32_t flags);\n\n  // Destroys an arena allocated by NewArena and returns true,\n  // provided no allocated blocks remain in the arena.\n  // If allocated blocks remain in the arena, does nothing and\n  // returns false.\n  // It is illegal to attempt to destroy the DefaultArena().\n  static bool DeleteArena(Arena *arena);\n\n  // The default arena that always exists.\n  static Arena *DefaultArena();\n\n private:\n  LowLevelAlloc();      // no instances\n};\n\n// Returns a global async-signal-safe arena for LowLevelAlloc.\nLowLevelAlloc::Arena *SigSafeArena();\n\n// Ensures the global async-signal-safe arena for LowLevelAlloc is initialized.\nvoid InitSigSafeArena();\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_\n"
  },
  {
    "path": "absl/base/internal/low_level_alloc_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/low_level_alloc.h\"\n\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <thread>  // NOLINT(build/c++11)\n#include <unordered_map>\n#include <utility>\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#include \"absl/container/node_hash_map.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\n// This test doesn't use gtest since it needs to test that everything\n// works before main().\n#define TEST_ASSERT(x)                                           \\\n  if (!(x)) {                                                    \\\n    printf(\"TEST_ASSERT(%s) FAILED ON LINE %d\\n\", #x, __LINE__); \\\n    abort();                                                     \\\n  }\n\n// a block of memory obtained from the allocator\nstruct BlockDesc {\n  char *ptr;      // pointer to memory\n  int len;        // number of bytes\n  int fill;       // filled with data starting with this\n};\n\n// Check that the pattern placed in the block d\n// by RandomizeBlockDesc is still there.\nstatic void CheckBlockDesc(const BlockDesc &d) {\n  for (int i = 0; i != d.len; i++) {\n    TEST_ASSERT((d.ptr[i] & 0xff) == ((d.fill + i) & 0xff));\n  }\n}\n\n// Fill the block \"*d\" with a pattern\n// starting with a random byte.\nstatic void RandomizeBlockDesc(BlockDesc *d) {\n  d->fill = rand() & 0xff;\n  for (int i = 0; i != d->len; i++) {\n    d->ptr[i] = (d->fill + i) & 0xff;\n  }\n}\n\n// Use to indicate to the malloc hooks that\n// this calls is from LowLevelAlloc.\nstatic bool using_low_level_alloc = false;\n\n// n times, toss a coin, and based on the outcome\n// either allocate a new block or deallocate an old block.\n// New blocks are placed in a std::unordered_map with a random key\n// and initialized with RandomizeBlockDesc().\n// If keys conflict, the older block is freed.\n// Old blocks are always checked with CheckBlockDesc()\n// before being freed.  At the end of the run,\n// all remaining allocated blocks are freed.\n// If use_new_arena is true, use a fresh arena, and then delete it.\n// If call_malloc_hook is true and user_arena is true,\n// allocations and deallocations are reported via the MallocHook\n// interface.\nstatic void Test(bool use_new_arena, bool call_malloc_hook, int n) {\n  typedef absl::node_hash_map<int, BlockDesc> AllocMap;\n  AllocMap allocated;\n  AllocMap::iterator it;\n  BlockDesc block_desc;\n  int rnd;\n  LowLevelAlloc::Arena *arena = nullptr;\n  if (use_new_arena) {\n    int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0;\n    arena = LowLevelAlloc::NewArena(flags);\n  }\n  for (int i = 0; i != n; i++) {\n    if (i != 0 && i % 10000 == 0) {\n      printf(\".\");\n      fflush(stdout);\n    }\n\n    switch (rand() & 1) {      // toss a coin\n    case 0:     // coin came up heads: add a block\n      using_low_level_alloc = true;\n      block_desc.len = rand() & 0x3fff;\n      block_desc.ptr = reinterpret_cast<char *>(\n          arena == nullptr\n              ? LowLevelAlloc::Alloc(block_desc.len)\n              : LowLevelAlloc::AllocWithArena(block_desc.len, arena));\n      using_low_level_alloc = false;\n      RandomizeBlockDesc(&block_desc);\n      rnd = rand();\n      it = allocated.find(rnd);\n      if (it != allocated.end()) {\n        CheckBlockDesc(it->second);\n        using_low_level_alloc = true;\n        LowLevelAlloc::Free(it->second.ptr);\n        using_low_level_alloc = false;\n        it->second = block_desc;\n      } else {\n        allocated[rnd] = block_desc;\n      }\n      break;\n    case 1:     // coin came up tails: remove a block\n      it = allocated.begin();\n      if (it != allocated.end()) {\n        CheckBlockDesc(it->second);\n        using_low_level_alloc = true;\n        LowLevelAlloc::Free(it->second.ptr);\n        using_low_level_alloc = false;\n        allocated.erase(it);\n      }\n      break;\n    }\n  }\n  // remove all remaining blocks\n  while ((it = allocated.begin()) != allocated.end()) {\n    CheckBlockDesc(it->second);\n    using_low_level_alloc = true;\n    LowLevelAlloc::Free(it->second.ptr);\n    using_low_level_alloc = false;\n    allocated.erase(it);\n  }\n  if (use_new_arena) {\n    TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));\n  }\n}\n\n// LowLevelAlloc is designed to be safe to call before main().\nstatic struct BeforeMain {\n  BeforeMain() {\n    Test(false, false, 50000);\n    Test(true, false, 50000);\n    Test(true, true, 50000);\n  }\n} before_main;\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nint main(int argc, char *argv[]) {\n  // The actual test runs in the global constructor of `before_main`.\n  printf(\"PASS\\n\");\n#ifdef __EMSCRIPTEN__\n  // clang-format off\n// This is JS here. Don't try to format it.\n    MAIN_THREAD_EM_ASM({\n      if (ENVIRONMENT_IS_WEB) {\n        if (typeof TEST_FINISH === 'function') {\n          TEST_FINISH($0);\n        } else {\n          console.error('Attempted to exit with status ' + $0);\n          console.error('But TEST_FINSIHED is not a function.');\n        }\n      }\n    }, 0);\n// clang-format on\n#endif\n  return 0;\n}\n"
  },
  {
    "path": "absl/base/internal/low_level_scheduling.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Core interfaces and definitions used by by low-level interfaces such as\n// SpinLock.\n\n#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_\n#define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/macros.h\"\n\n// The following two declarations exist so SchedulingGuard may friend them with\n// the appropriate language linkage.  These callbacks allow libc internals, such\n// as function level statics, to schedule cooperatively when locking.\nextern \"C\" bool __google_disable_rescheduling(void);\nextern \"C\" void __google_enable_rescheduling(bool disable_result);\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nclass CondVar;\nclass Mutex;\n\nnamespace synchronization_internal {\nint MutexDelay(int32_t c, int mode);\n}  // namespace synchronization_internal\n\nnamespace base_internal {\n\nclass SchedulingHelper;  // To allow use of SchedulingGuard.\nclass SpinLock;          // To allow use of SchedulingGuard.\n\n// SchedulingGuard\n// Provides guard semantics that may be used to disable cooperative rescheduling\n// of the calling thread within specific program blocks.  This is used to\n// protect resources (e.g. low-level SpinLocks or Domain code) that cooperative\n// scheduling depends on.\n//\n// Domain implementations capable of rescheduling in reaction to involuntary\n// kernel thread actions (e.g blocking due to a pagefault or syscall) must\n// guarantee that an annotated thread is not allowed to (cooperatively)\n// reschedule until the annotated region is complete.\n//\n// It is an error to attempt to use a cooperatively scheduled resource (e.g.\n// Mutex) within a rescheduling-disabled region.\n//\n// All methods are async-signal safe.\nclass SchedulingGuard {\n public:\n  // Returns true iff the calling thread may be cooperatively rescheduled.\n  static bool ReschedulingIsAllowed();\n  SchedulingGuard(const SchedulingGuard&) = delete;\n  SchedulingGuard& operator=(const SchedulingGuard&) = delete;\n\n  // Disable cooperative rescheduling of the calling thread.  It may still\n  // initiate scheduling operations (e.g. wake-ups), however, it may not itself\n  // reschedule.  Nestable.  The returned result is opaque, clients should not\n  // attempt to interpret it.\n  // REQUIRES: Result must be passed to a pairing EnableScheduling().\n  static bool DisableRescheduling();\n\n  // Marks the end of a rescheduling disabled region, previously started by\n  // DisableRescheduling().\n  // REQUIRES: Pairs with innermost call (and result) of DisableRescheduling().\n  static void EnableRescheduling(bool disable_result);\n\n  // A scoped helper for {Disable, Enable}Rescheduling().\n  // REQUIRES: destructor must run in same thread as constructor.\n  struct ScopedDisable {\n    ScopedDisable() { disabled = SchedulingGuard::DisableRescheduling(); }\n    ~ScopedDisable() { SchedulingGuard::EnableRescheduling(disabled); }\n\n    bool disabled;\n  };\n\n  // A scoped helper to enable rescheduling temporarily.\n  // REQUIRES: destructor must run in same thread as constructor.\n  class ScopedEnable {\n   public:\n    ScopedEnable();\n    ~ScopedEnable();\n\n   private:\n    int scheduling_disabled_depth_;\n  };\n};\n\n//------------------------------------------------------------------------------\n// End of public interfaces.\n//------------------------------------------------------------------------------\n\ninline bool SchedulingGuard::ReschedulingIsAllowed() {\n  ThreadIdentity* identity;\n  identity = CurrentThreadIdentityIfPresent();\n  if (identity != nullptr) {\n    ThreadIdentity::SchedulerState* state;\n    state = &identity->scheduler_state;\n    // For a thread to be eligible for re-scheduling it must have a bound\n    // schedulable (otherwise it's not cooperative) and not be within a\n    // SchedulerGuard region.\n    return state->get_bound_schedulable() != nullptr &&\n           state->scheduling_disabled_depth.load(std::memory_order_relaxed) ==\n               0;\n  } else {\n    // Cooperative threads always have a ThreadIdentity.\n    return false;\n  }\n}\n\n// We don't use [[nodiscard]] here as some clients (e.g.\n// FinishPotentiallyBlockingRegion()) cannot yet properly consume it.\ninline bool SchedulingGuard::DisableRescheduling() {\n  ThreadIdentity* identity;\n  identity = CurrentThreadIdentityIfPresent();\n  if (identity != nullptr) {\n    // The depth is accessed concurrently from other threads, so it must be\n    // atomic, but it's only mutated from this thread, so we don't need an\n    // atomic increment.\n    int old_val = identity->scheduler_state.scheduling_disabled_depth.load(\n        std::memory_order_relaxed);\n    identity->scheduler_state.scheduling_disabled_depth.store(\n        old_val + 1, std::memory_order_relaxed);\n    return true;\n  } else {\n    return false;\n  }\n}\n\ninline void SchedulingGuard::EnableRescheduling(bool disable_result) {\n  if (!disable_result) {\n    // There was no installed thread identity at the time that scheduling was\n    // disabled, so we have nothing to do.  This is an implementation detail\n    // that may change in the future, clients may not depend on it.\n    // EnableRescheduling() must always be called.\n    return;\n  }\n\n  ThreadIdentity* identity;\n  // A thread identity exists, see above\n  identity = CurrentThreadIdentityIfPresent();\n  // The depth is accessed concurrently from other threads, so it must be\n  // atomic, but it's only mutated from this thread, so we don't need an atomic\n  // decrement.\n  int old_val = identity->scheduler_state.scheduling_disabled_depth.load(\n      std::memory_order_relaxed);\n  identity->scheduler_state.scheduling_disabled_depth.store(\n      old_val - 1, std::memory_order_relaxed);\n}\n\ninline SchedulingGuard::ScopedEnable::ScopedEnable() {\n  ThreadIdentity* identity;\n  identity = CurrentThreadIdentityIfPresent();\n  if (identity != nullptr) {\n    scheduling_disabled_depth_ =\n        identity->scheduler_state.scheduling_disabled_depth.load(\n            std::memory_order_relaxed);\n    if (scheduling_disabled_depth_ != 0) {\n      // The store below does not need to be compare_exchange because\n      // the value is never modified concurrently (only accessed).\n      identity->scheduler_state.scheduling_disabled_depth.store(\n          0, std::memory_order_relaxed);\n    }\n  } else {\n    scheduling_disabled_depth_ = 0;\n  }\n}\n\ninline SchedulingGuard::ScopedEnable::~ScopedEnable() {\n  if (scheduling_disabled_depth_ == 0) {\n    return;\n  }\n  ThreadIdentity* identity = CurrentThreadIdentityIfPresent();\n  // itentity is guaranteed to exist, see the constructor above.\n  identity->scheduler_state.scheduling_disabled_depth.store(\n      scheduling_disabled_depth_, std::memory_order_relaxed);\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_\n"
  },
  {
    "path": "absl/base/internal/nullability_traits.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_NULLABILITY_TRAITS_H_\n#define ABSL_BASE_INTERNAL_NULLABILITY_TRAITS_H_\n\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// `value` is true if the type `T` is compatible with nullability annotations\n// (is a raw pointer, a smart pointer, or marked with\n// ABSL_NULLABILITY_COMPATIBLE). Prefer to use the higher-level\n// `AddNonnullIfCompatible` if that is sufficient.\n//\n// NOTE: This should not be used to detect if the compiler is Clang (since\n// Clang is the only compiler that supports nullability annotations).\n#if defined(__clang__) && !defined(__OBJC__) && \\\n    ABSL_HAVE_FEATURE(nullability_on_classes)\ntemplate <class T, class = void>\nstruct IsNullabilityCompatibleType {\n  constexpr static bool value = false;\n};\n\ntemplate <class T>\nstruct IsNullabilityCompatibleType<T, std::void_t<absl_nullable T>> {\n  constexpr static bool value = true;\n};\n#else\n// False when absl_nullable is a no-op (for non-Clang compilers or Objective-C.)\ntemplate <class T, class = void>\nstruct IsNullabilityCompatibleType {\n  constexpr static bool value = false;\n};\n#endif\n\n// A trait to add `absl_nonnull` to a type if it is compatible with nullability\n// annotations.\ntemplate <typename T, bool ShouldAdd = IsNullabilityCompatibleType<T>::value>\nstruct AddNonnullIfCompatible;\n\ntemplate <typename T>\nstruct AddNonnullIfCompatible<T, false> {\n  using type = T;\n};\ntemplate <typename T>\nstruct AddNonnullIfCompatible<T, true> {\n  using type = absl_nonnull T;\n};\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_NULLABILITY_TRAITS_H_\n"
  },
  {
    "path": "absl/base/internal/nullability_traits_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/nullability_traits.h\"\n\n#include <memory>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\nstruct NotSmartPtr {\n  int* x;\n};\n\nclass ABSL_NULLABILITY_COMPATIBLE MySmartPtr : std::unique_ptr<int> {};\n\n// The IsNullabilityCompatibleType trait value can only be true when we define\n// `absl_nullable` (isn't a no-op).\n#if defined(__clang__) && !defined(__OBJC__) && \\\n    ABSL_HAVE_FEATURE(nullability_on_classes)\n#define EXPECT_TRUE_IF_SUPPORTED EXPECT_TRUE\n#else\n#define EXPECT_TRUE_IF_SUPPORTED EXPECT_FALSE\n#endif\n\nTEST(NullabilityTraitsTest, IsNullabilityEligibleTypePrimitives) {\n  EXPECT_FALSE(IsNullabilityCompatibleType<int>::value);\n  EXPECT_FALSE(IsNullabilityCompatibleType<int*&>::value);\n\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<int*>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<int**>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<int* const>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<const int*>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<void (*)(int)>::value);\n}\n\nTEST(NullabilityTraitsTest, IsNullabilityCompatibleTypeAliases) {\n  using MyInt = int;\n  using MyIntPtr = int*;\n  EXPECT_FALSE(IsNullabilityCompatibleType<MyInt>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<MyIntPtr>::value);\n}\n\nTEST(NullabilityTraitsTest, IsNullabilityCompatibleTypeSmartPointers) {\n  EXPECT_TRUE_IF_SUPPORTED(\n      IsNullabilityCompatibleType<std::unique_ptr<int>>::value);\n  EXPECT_TRUE_IF_SUPPORTED(\n      IsNullabilityCompatibleType<std::shared_ptr<int>>::value);\n\n  EXPECT_FALSE(IsNullabilityCompatibleType<NotSmartPtr>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<NotSmartPtr*>::value);\n  EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<MySmartPtr>::value);\n}\n\n#undef EXPECT_TRUE_IF_SUPPORTED\n\nTEST(NullabilityTraitsTest, AddNonnullIfCompatiblePassThroughPrimitives) {\n  EXPECT_TRUE((std::is_same_v<AddNonnullIfCompatible<int>::type, int>));\n  EXPECT_TRUE((std::is_same_v<AddNonnullIfCompatible<int*>::type, int*>));\n  EXPECT_TRUE(\n      (std::is_same_v<AddNonnullIfCompatible<int* const>::type, int* const>));\n}\n\nTEST(NullabilityTraitsTest, AddNonnullIfCompatiblePassThroughSmartPointers) {\n  EXPECT_TRUE(\n      (std::is_same_v<AddNonnullIfCompatible<std::unique_ptr<int>>::type,\n                      std::unique_ptr<int>>));\n  EXPECT_TRUE(\n      (std::is_same_v<AddNonnullIfCompatible<std::shared_ptr<int>>::type,\n                      std::shared_ptr<int>>));\n  EXPECT_TRUE(\n      (std::is_same_v<AddNonnullIfCompatible<NotSmartPtr>::type, NotSmartPtr>));\n  EXPECT_TRUE(\n      (std::is_same_v<AddNonnullIfCompatible<MySmartPtr>::type, MySmartPtr>));\n}\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/per_thread_tls.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_\n#define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_\n\n// This header defines two macros:\n//\n// If the platform supports thread-local storage:\n//\n// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a\n//   thread-local variable\n// * ABSL_PER_THREAD_TLS is 1\n//\n// Otherwise:\n//\n// * ABSL_PER_THREAD_TLS_KEYWORD is empty\n// * ABSL_PER_THREAD_TLS is 0\n//\n// Microsoft C supports thread-local storage.\n// GCC supports it if the appropriate version of glibc is available,\n// which the programmer can indicate by defining ABSL_HAVE_TLS\n\n#include \"absl/base/port.h\"  // For ABSL_HAVE_TLS\n\n#if defined(ABSL_PER_THREAD_TLS)\n#error ABSL_PER_THREAD_TLS cannot be directly set\n#elif defined(ABSL_PER_THREAD_TLS_KEYWORD)\n#error ABSL_PER_THREAD_TLS_KEYWORD cannot be directly set\n#elif defined(ABSL_HAVE_TLS)\n#define ABSL_PER_THREAD_TLS_KEYWORD __thread\n#define ABSL_PER_THREAD_TLS 1\n#elif defined(_MSC_VER)\n#define ABSL_PER_THREAD_TLS_KEYWORD __declspec(thread)\n#define ABSL_PER_THREAD_TLS 1\n#else\n#define ABSL_PER_THREAD_TLS_KEYWORD\n#define ABSL_PER_THREAD_TLS 0\n#endif\n\n#endif  // ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_\n"
  },
  {
    "path": "absl/base/internal/poison.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/poison.h\"\n\n#include <cstdlib>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/direct_mmap.h\"\n\n#ifndef _WIN32\n#include <unistd.h>\n#endif\n\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER)\n#include <sanitizer/asan_interface.h>\n#elif defined(ABSL_HAVE_MEMORY_SANITIZER)\n#include <sanitizer/msan_interface.h>\n#elif defined(ABSL_HAVE_MMAP)\n#include <sys/mman.h>\n#endif\n\n#if defined(_WIN32)\n#include <windows.h>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nnamespace {\n\nsize_t GetPageSize() {\n#ifdef _WIN32\n  SYSTEM_INFO system_info;\n  GetSystemInfo(&system_info);\n  return system_info.dwPageSize;\n#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__)\n  return getpagesize();\n#else\n  return static_cast<size_t>(sysconf(_SC_PAGESIZE));\n#endif\n}\n\n}  // namespace\n\nvoid* InitializePoisonedPointerInternal() {\n  const size_t block_size = GetPageSize();\n  void* data = nullptr;\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER)\n  data = malloc(block_size);\n  ASAN_POISON_MEMORY_REGION(data, block_size);\n#elif defined(ABSL_HAVE_MEMORY_SANITIZER)\n  data = malloc(block_size);\n  __msan_poison(data, block_size);\n#elif defined(ABSL_HAVE_MMAP)\n  data = DirectMmap(nullptr, block_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,\n                    -1, 0);\n  if (data == MAP_FAILED) return GetBadPointerInternal();\n#elif defined(_WIN32)\n  data = VirtualAlloc(nullptr, block_size, MEM_RESERVE | MEM_COMMIT,\n                      PAGE_NOACCESS);\n  if (data == nullptr) return GetBadPointerInternal();\n#else\n  return GetBadPointerInternal();\n#endif\n  // Return the middle of the block so that dereferences before and after the\n  // pointer will both crash.\n  return static_cast<char*>(data) + block_size / 2;\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/poison.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_POISON_H_\n#define ABSL_BASE_INTERNAL_POISON_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\ninline void* GetBadPointerInternal() {\n  // A likely bad pointer. Pointers are required to have high bits that are all\n  // zero or all one for certain 64-bit CPUs. This pointer value will hopefully\n  // cause a crash on dereference and also be clearly recognizable as invalid.\n  constexpr uint64_t kBadPtr = 0xBAD0BAD0BAD0BAD0;\n  auto ret = reinterpret_cast<void*>(static_cast<uintptr_t>(kBadPtr));\n#ifndef _MSC_VER  // MSVC doesn't support inline asm with `volatile`.\n  // Try to prevent the compiler from optimizing out the undefined behavior.\n  asm volatile(\"\" : : \"r\"(ret) :);  // NOLINT\n#endif\n  return ret;\n}\n\nvoid* InitializePoisonedPointerInternal();\n\ninline void* get_poisoned_pointer() {\n#if defined(NDEBUG) && !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \\\n    !defined(ABSL_HAVE_MEMORY_SANITIZER)\n  // In optimized non-sanitized builds, avoid the function-local static because\n  // of the codegen and runtime cost.\n  return GetBadPointerInternal();\n#else\n  // Non-optimized builds may use more robust implementation. Note that we can't\n  // use a static global because Chromium doesn't allow non-constinit globals.\n  static void* ptr = InitializePoisonedPointerInternal();\n  return ptr;\n#endif\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_POISON_H_\n"
  },
  {
    "path": "absl/base/internal/poison_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/poison.h\"\n\n#include <iostream>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\nTEST(PoisonTest, CrashesOnDereference) {\n#ifdef __ANDROID__\n  GTEST_SKIP() << \"On Android, poisoned pointer dereference times out instead \"\n                  \"of crashing.\";\n#endif\n  int* poisoned_ptr = static_cast<int*>(get_poisoned_pointer());\n  EXPECT_DEATH_IF_SUPPORTED(std::cout << *poisoned_ptr, \"\");\n  EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr - 10), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr + 10), \"\");\n}\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/pretty_function.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_\n#define ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_\n\n// ABSL_PRETTY_FUNCTION\n//\n// In C++11, __func__ gives the undecorated name of the current function.  That\n// is, \"main\", not \"int main()\".  Various compilers give extra macros to get the\n// decorated function name, including return type and arguments, to\n// differentiate between overload sets.  ABSL_PRETTY_FUNCTION is a portable\n// version of these macros which forwards to the correct macro on each compiler.\n#if defined(_MSC_VER)\n#define ABSL_PRETTY_FUNCTION __FUNCSIG__\n#elif defined(__GNUC__)\n#define ABSL_PRETTY_FUNCTION __PRETTY_FUNCTION__\n#else\n#error \"Unsupported compiler\"\n#endif\n\n#endif  // ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_\n"
  },
  {
    "path": "absl/base/internal/raw_logging.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/raw_logging.h\"\n\n#include <cstdarg>\n#include <cstddef>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <string>\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten/console.h>\n#endif\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n#include \"absl/base/internal/errno_saver.h\"\n#include \"absl/base/log_severity.h\"\n\n// We know how to perform low-level writes to stderr in POSIX and Windows.  For\n// these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED.\n// Much of raw_logging.cc becomes a no-op when we can't output messages,\n// although a FATAL ABSL_RAW_LOG message will still abort the process.\n\n// ABSL_HAVE_POSIX_WRITE is defined when the platform provides posix write()\n// (as from unistd.h)\n//\n// This preprocessor token is also defined in raw_io.cc.  If you need to copy\n// this, consider moving both to config.h instead.\n#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||     \\\n    defined(__hexagon__) || defined(__Fuchsia__) || defined(__OpenBSD__) || \\\n    defined(__EMSCRIPTEN__) || defined(__ASYLO__)\n\n#include <unistd.h>\n\n#define ABSL_HAVE_POSIX_WRITE 1\n#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1\n#else\n#undef ABSL_HAVE_POSIX_WRITE\n#endif\n\n// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall\n//   syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);\n// for low level operations that want to avoid libc.\n#if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)\n#include <sys/syscall.h>\n#define ABSL_HAVE_SYSCALL_WRITE 1\n#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1\n#else\n#undef ABSL_HAVE_SYSCALL_WRITE\n#endif\n\n#ifdef _WIN32\n#include <io.h>\n\n#define ABSL_HAVE_RAW_IO 1\n#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1\n#else\n#undef ABSL_HAVE_RAW_IO\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace raw_log_internal {\nnamespace {\n\n// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.\n// Explicitly `#error` out when not `ABSL_LOW_LEVEL_WRITE_SUPPORTED`, except for\n// a selected set of platforms for which we expect not to be able to raw log.\n\n#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED\nconstexpr char kTruncated[] = \" ... (message truncated)\\n\";\n\n// sprintf the format to the buffer, adjusting *buf and *size to reflect the\n// consumed bytes, and return whether the message fit without truncation.  If\n// truncation occurred, if possible leave room in the buffer for the message\n// kTruncated[].\nbool VADoRawLog(char** buf, int* size, const char* format, va_list ap)\n    ABSL_PRINTF_ATTRIBUTE(3, 0);\nbool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {\n  if (*size < 0) return false;\n  int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);\n  bool result = true;\n  if (n < 0 || n > *size) {\n    result = false;\n    if (static_cast<size_t>(*size) > sizeof(kTruncated)) {\n      n = *size - static_cast<int>(sizeof(kTruncated));\n    } else {\n      n = 0;  // no room for truncation message\n    }\n  }\n  *size -= n;\n  *buf += n;\n  return result;\n}\n#endif  // ABSL_LOW_LEVEL_WRITE_SUPPORTED\n\nconstexpr int kLogBufSize = 3000;\n\n// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths\n// that invoke malloc() and getenv() that might acquire some locks.\n\n// Helper for RawLog below.\n// *DoRawLog writes to *buf of *size and move them past the written portion.\n// It returns true iff there was no overflow or error.\nbool DoRawLog(char** buf, int* size, const char* format, ...)\n    ABSL_PRINTF_ATTRIBUTE(3, 4);\nbool DoRawLog(char** buf, int* size, const char* format, ...) {\n  if (*size < 0) return false;\n  va_list ap;\n  va_start(ap, format);\n  int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);\n  va_end(ap);\n  if (n < 0 || n > *size) return false;\n  *size -= n;\n  *buf += n;\n  return true;\n}\n\nbool DefaultLogFilterAndPrefix(absl::LogSeverity, const char* file, int line,\n                               char** buf, int* buf_size) {\n  DoRawLog(buf, buf_size, \"[%s : %d] RAW: \", file, line);\n  return true;\n}\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\nabsl::base_internal::AtomicHook<LogFilterAndPrefixHook>\n    log_filter_and_prefix_hook(DefaultLogFilterAndPrefix);\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\nabsl::base_internal::AtomicHook<AbortHook> abort_hook;\n\nvoid RawLogVA(absl::LogSeverity severity, const char* file, int line,\n              const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);\nvoid RawLogVA(absl::LogSeverity severity, const char* file, int line,\n              const char* format, va_list ap) {\n  char buffer[kLogBufSize];\n  char* buf = buffer;\n  int size = sizeof(buffer);\n#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED\n  bool enabled = true;\n#else\n  bool enabled = false;\n#endif\n\n#ifdef ABSL_MIN_LOG_LEVEL\n  if (severity < static_cast<absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL) &&\n      severity < absl::LogSeverity::kFatal) {\n    enabled = false;\n  }\n#endif\n\n  enabled = log_filter_and_prefix_hook(severity, file, line, &buf, &size);\n  const char* const prefix_end = buf;\n\n#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED\n  if (enabled) {\n    bool no_chop = VADoRawLog(&buf, &size, format, ap);\n    if (no_chop) {\n      DoRawLog(&buf, &size, \"\\n\");\n    } else {\n      DoRawLog(&buf, &size, \"%s\", kTruncated);\n    }\n    AsyncSignalSafeWriteError(buffer, static_cast<size_t>(buf - buffer));\n  }\n#else\n  static_cast<void>(format);\n  static_cast<void>(ap);\n  static_cast<void>(enabled);\n#endif\n\n  // Abort the process after logging a FATAL message, even if the output itself\n  // was suppressed.\n  if (severity == absl::LogSeverity::kFatal) {\n    abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize);\n    abort();\n  }\n}\n\n// Non-formatting version of RawLog().\n//\n// TODO(gfalcon): When string_view no longer depends on base, change this\n// interface to take its message as a string_view instead.\nvoid DefaultInternalLog(absl::LogSeverity severity, const char* file, int line,\n                        const std::string& message) {\n  RawLog(severity, file, line, \"%.*s\", static_cast<int>(message.size()),\n         message.data());\n}\n\n}  // namespace\n\nvoid AsyncSignalSafeWriteError(const char* s, size_t len) {\n  if (!len) return;\n  absl::base_internal::ErrnoSaver errno_saver;\n#if defined(__EMSCRIPTEN__)\n  // In WebAssembly, bypass filesystem emulation via fwrite.\n  if (s[len - 1] == '\\n') {\n    // Skip a trailing newline character as emscripten_errn adds one itself.\n    len--;\n  }\n  // emscripten_errn was introduced in 3.1.41 but broken in standalone mode\n  // until 3.1.43.\n#if ABSL_INTERNAL_EMSCRIPTEN_VERSION >= 3001043\n  emscripten_errn(s, len);\n#else\n  char buf[kLogBufSize];\n  if (len >= kLogBufSize) {\n    len = kLogBufSize - 1;\n    constexpr size_t trunc_len = sizeof(kTruncated) - 2;\n    memcpy(buf + len - trunc_len, kTruncated, trunc_len);\n    buf[len] = '\\0';\n    len -= trunc_len;\n  } else {\n    buf[len] = '\\0';\n  }\n  memcpy(buf, s, len);\n  _emscripten_err(buf);\n#endif\n#elif defined(ABSL_HAVE_SYSCALL_WRITE)\n  // We prefer calling write via `syscall` to minimize the risk of libc doing\n  // something \"helpful\".\n  syscall(SYS_write, STDERR_FILENO, s, len);\n#elif defined(ABSL_HAVE_POSIX_WRITE)\n  write(STDERR_FILENO, s, len);\n#elif defined(ABSL_HAVE_RAW_IO)\n  _write(/* stderr */ 2, s, static_cast<unsigned>(len));\n#else\n  // stderr logging unsupported on this platform\n  (void)s;\n  (void)len;\n#endif\n}\n\nvoid RawLog(absl::LogSeverity severity, const char* file, int line,\n            const char* format, ...) {\n  va_list ap;\n  va_start(ap, format);\n  RawLogVA(severity, file, line, format, ap);\n  va_end(ap);\n}\n\nbool RawLoggingFullySupported() {\n#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED\n  return true;\n#else   // !ABSL_LOW_LEVEL_WRITE_SUPPORTED\n  return false;\n#endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED\n}\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL\n    absl::base_internal::AtomicHook<InternalLogFunction>\n        internal_log_function(DefaultInternalLog);\n\nvoid RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func) {\n  log_filter_and_prefix_hook.Store(func);\n}\n\nvoid RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }\n\nvoid RegisterInternalLogFunction(InternalLogFunction func) {\n  internal_log_function.Store(func);\n}\n\n}  // namespace raw_log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/raw_logging.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Thread-safe logging routines that do not allocate any memory or\n// acquire any locks, and can therefore be used by low-level memory\n// allocation, synchronization, and signal-handling code.\n\n#ifndef ABSL_BASE_INTERNAL_RAW_LOGGING_H_\n#define ABSL_BASE_INTERNAL_RAW_LOGGING_H_\n\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n\n// This is similar to LOG(severity) << format..., but\n// * it is to be used ONLY by low-level modules that can't use normal LOG()\n// * it is designed to be a low-level logger that does not allocate any\n//   memory and does not need any locks, hence:\n// * it logs straight and ONLY to STDERR w/o buffering\n// * it uses an explicit printf-format and arguments list\n// * it will silently chop off really long message strings\n// Usage example:\n//   ABSL_RAW_LOG(ERROR, \"Failed foo with %i: %s\", status, error);\n// This will print an almost standard log line like this to stderr only:\n//   E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file\n\n#define ABSL_RAW_LOG(severity, ...)                                            \\\n  do {                                                                         \\\n    constexpr const char* absl_raw_log_internal_basename =                     \\\n        ::absl::raw_log_internal::Basename(__FILE__, sizeof(__FILE__) - 1);    \\\n    ::absl::raw_log_internal::RawLog(ABSL_RAW_LOG_INTERNAL_##severity,         \\\n                                     absl_raw_log_internal_basename, __LINE__, \\\n                                     __VA_ARGS__);                             \\\n    ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity;                        \\\n  } while (0)\n\n// Similar to CHECK(condition) << message, but for low-level modules:\n// we use only ABSL_RAW_LOG that does not allocate memory.\n// We do not want to provide args list here to encourage this usage:\n//   if (!cond)  ABSL_RAW_LOG(FATAL, \"foo ...\", hard_to_compute_args);\n// so that the args are not computed when not needed.\n#define ABSL_RAW_CHECK(condition, message)                             \\\n  do {                                                                 \\\n    if (ABSL_PREDICT_FALSE(!(condition))) {                            \\\n      ABSL_RAW_LOG(FATAL, \"Check %s failed: %s\", #condition, message); \\\n    }                                                                  \\\n  } while (0)\n\n// ABSL_INTERNAL_LOG and ABSL_INTERNAL_CHECK work like the RAW variants above,\n// except that if the richer log library is linked into the binary, we dispatch\n// to that instead.  This is potentially useful for internal logging and\n// assertions, where we are using RAW_LOG neither for its async-signal-safety\n// nor for its non-allocating nature, but rather because raw logging has very\n// few other dependencies.\n//\n// The API is a subset of the above: each macro only takes two arguments.  Use\n// StrCat if you need to build a richer message.\n#define ABSL_INTERNAL_LOG(severity, message)                              \\\n  do {                                                                    \\\n    constexpr const char* absl_raw_log_internal_filename = __FILE__;      \\\n    ::absl::raw_log_internal::internal_log_function(                      \\\n        ABSL_RAW_LOG_INTERNAL_##severity, absl_raw_log_internal_filename, \\\n        __LINE__, message);                                               \\\n    ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity;                   \\\n  } while (0)\n\n#define ABSL_INTERNAL_CHECK(condition, message)                    \\\n  do {                                                             \\\n    if (ABSL_PREDICT_FALSE(!(condition))) {                        \\\n      std::string death_message = \"Check \" #condition \" failed: \"; \\\n      death_message += std::string(message);                       \\\n      ABSL_INTERNAL_LOG(FATAL, death_message);                     \\\n    }                                                              \\\n  } while (0)\n\n#ifndef NDEBUG\n\n#define ABSL_RAW_DLOG(severity, ...) ABSL_RAW_LOG(severity, __VA_ARGS__)\n#define ABSL_RAW_DCHECK(condition, message) ABSL_RAW_CHECK(condition, message)\n\n#else  // NDEBUG\n\n#define ABSL_RAW_DLOG(severity, ...)                   \\\n  while (false) ABSL_RAW_LOG(severity, __VA_ARGS__)\n#define ABSL_RAW_DCHECK(condition, message) \\\n  while (false) ABSL_RAW_CHECK(condition, message)\n\n#endif  // NDEBUG\n\n#define ABSL_RAW_LOG_INTERNAL_INFO ::absl::LogSeverity::kInfo\n#define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning\n#define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError\n#define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal\n#define ABSL_RAW_LOG_INTERNAL_DFATAL ::absl::kLogDebugFatal\n#define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \\\n  ::absl::NormalizeLogSeverity(severity)\n\n#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_INFO\n#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING\n#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR\n#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE()\n#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_DFATAL\n#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace raw_log_internal {\n\n// Helper function to implement ABSL_RAW_LOG\n// Logs format... at \"severity\" level, reporting it\n// as called from file:line.\n// This does not allocate memory or acquire locks.\nvoid RawLog(absl::LogSeverity severity, const char* file, int line,\n            const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);\n\n// Writes the provided buffer directly to stderr, in a signal-safe, low-level\n// manner.  Preserves errno.\nvoid AsyncSignalSafeWriteError(const char* s, size_t len);\n\n// compile-time function to get the \"base\" filename, that is, the part of\n// a filename after the last \"/\" or \"\\\" path separator.  The search starts at\n// the end of the string; the second parameter is the length of the string.\nconstexpr const char* Basename(const char* fname, int offset) {\n  return offset == 0 || fname[offset - 1] == '/' || fname[offset - 1] == '\\\\'\n             ? fname + offset\n             : Basename(fname, offset - 1);\n}\n\n// For testing only.\n// Returns true if raw logging is fully supported. When it is not\n// fully supported, no messages will be emitted, but a log at FATAL\n// severity will cause an abort.\n//\n// TODO(gfalcon): Come up with a better name for this method.\nbool RawLoggingFullySupported();\n\n// Function type for a raw_log customization hook for suppressing messages\n// by severity, and for writing custom prefixes on non-suppressed messages.\n//\n// The installed hook is called for every raw log invocation.  The message will\n// be logged to stderr only if the hook returns true.  FATAL errors will cause\n// the process to abort, even if writing to stderr is suppressed.  The hook is\n// also provided with an output buffer, where it can write a custom log message\n// prefix.\n//\n// The raw_log system does not allocate memory or grab locks.  User-provided\n// hooks must avoid these operations, and must not throw exceptions.\n//\n// 'severity' is the severity level of the message being written.\n// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro\n// was located.\n// 'buf' and 'buf_size' are pointers to the buffer and buffer size.  If the\n// hook writes a prefix, it must increment *buf and decrement *buf_size\n// accordingly.\nusing LogFilterAndPrefixHook = bool (*)(absl::LogSeverity severity,\n                                        const char* file, int line, char** buf,\n                                        int* buf_size);\n\n// Function type for a raw_log customization hook called to abort a process\n// when a FATAL message is logged.  If the provided AbortHook() returns, the\n// logging system will call abort().\n//\n// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro\n// was located.\n// The NUL-terminated logged message lives in the buffer between 'buf_start'\n// and 'buf_end'.  'prefix_end' points to the first non-prefix character of the\n// buffer (as written by the LogFilterAndPrefixHook.)\n//\n// The lifetime of the filename and message buffers will not end while the\n// process remains alive.\nusing AbortHook = void (*)(const char* file, int line, const char* buf_start,\n                           const char* prefix_end, const char* buf_end);\n\n// Internal logging function for ABSL_INTERNAL_LOG to dispatch to.\n//\n// TODO(gfalcon): When string_view no longer depends on base, change this\n// interface to take its message as a string_view instead.\nusing InternalLogFunction = void (*)(absl::LogSeverity severity,\n                                     const char* file, int line,\n                                     const std::string& message);\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<\n    InternalLogFunction>\n    internal_log_function;\n\n// Registers hooks of the above types.  Only a single hook of each type may be\n// registered.  It is an error to call these functions multiple times with\n// different input arguments.\n//\n// These functions are safe to call at any point during initialization; they do\n// not block or malloc, and are async-signal safe.\nvoid RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func);\nvoid RegisterAbortHook(AbortHook func);\nvoid RegisterInternalLogFunction(InternalLogFunction func);\n\n}  // namespace raw_log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_RAW_LOGGING_H_\n"
  },
  {
    "path": "absl/base/internal/scheduling_mode.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Core interfaces and definitions used by by low-level interfaces such as\n// SpinLock.\n\n#ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_\n#define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Used to describe how a thread may be scheduled.  Typically associated with\n// the declaration of a resource supporting synchronized access.\n//\n// SCHEDULE_COOPERATIVE_AND_KERNEL:\n// Specifies that when waiting, a cooperative thread (e.g. a Fiber) may\n// reschedule (using base::scheduling semantics); allowing other cooperative\n// threads to proceed.\n//\n// SCHEDULE_KERNEL_ONLY: (Also described as \"non-cooperative\")\n// Specifies that no cooperative scheduling semantics may be used, even if the\n// current thread is itself cooperatively scheduled.  This means that\n// cooperative threads will NOT allow other cooperative threads to execute in\n// their place while waiting for a resource of this type.  Host operating system\n// semantics (e.g. a futex) may still be used.\n//\n// When optional, clients should strongly prefer SCHEDULE_COOPERATIVE_AND_KERNEL\n// by default.  SCHEDULE_KERNEL_ONLY should only be used for resources on which\n// base::scheduling (e.g. the implementation of a Scheduler) may depend.\n//\n// NOTE: Cooperative resources may not be nested below non-cooperative ones.\n// This means that it is invalid to to acquire a SCHEDULE_COOPERATIVE_AND_KERNEL\n// resource if a SCHEDULE_KERNEL_ONLY resource is already held.\nenum SchedulingMode {\n  SCHEDULE_KERNEL_ONLY = 0,         // Allow scheduling only the host OS.\n  SCHEDULE_COOPERATIVE_AND_KERNEL,  // Also allow cooperative scheduling.\n};\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_\n"
  },
  {
    "path": "absl/base/internal/scoped_set_env.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/scoped_set_env.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#include <cstdlib>\n\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nnamespace {\n\n#ifdef _WIN32\nconst int kMaxEnvVarValueSize = 1024;\n#endif\n\nvoid SetEnvVar(const char* name, const char* value) {\n#ifdef _WIN32\n  SetEnvironmentVariableA(name, value);\n#else\n  if (value == nullptr) {\n    ::unsetenv(name);\n  } else {\n    ::setenv(name, value, 1);\n  }\n#endif\n}\n\n}  // namespace\n\nScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)\n    : var_name_(var_name), was_unset_(false) {\n#ifdef _WIN32\n  char buf[kMaxEnvVarValueSize];\n  auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));\n  ABSL_INTERNAL_CHECK(get_res < sizeof(buf), \"value exceeds buffer size\");\n\n  if (get_res == 0) {\n    was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);\n  } else {\n    old_value_.assign(buf, get_res);\n  }\n\n  SetEnvironmentVariableA(var_name_.c_str(), new_value);\n#else\n  const char* val = ::getenv(var_name_.c_str());\n  if (val == nullptr) {\n    was_unset_ = true;\n  } else {\n    old_value_ = val;\n  }\n#endif\n\n  SetEnvVar(var_name_.c_str(), new_value);\n}\n\nScopedSetEnv::~ScopedSetEnv() {\n  SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/scoped_set_env.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_\n#define ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nclass ScopedSetEnv {\n public:\n  ScopedSetEnv(const char* var_name, const char* new_value);\n  ~ScopedSetEnv();\n\n private:\n  std::string var_name_;\n  std::string old_value_;\n\n  // True if the environment variable was initially not set.\n  bool was_unset_;\n};\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_\n"
  },
  {
    "path": "absl/base/internal/scoped_set_env_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/scoped_set_env.h\"\n\nnamespace {\n\nusing absl::base_internal::ScopedSetEnv;\n\nstd::string GetEnvVar(const char* name) {\n#ifdef _WIN32\n  char buf[1024];\n  auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf));\n  if (get_res >= sizeof(buf)) {\n    return \"TOO_BIG\";\n  }\n\n  if (get_res == 0) {\n    return \"UNSET\";\n  }\n\n  return std::string(buf, get_res);\n#else\n  const char* val = ::getenv(name);\n  if (val == nullptr) {\n    return \"UNSET\";\n  }\n\n  return val;\n#endif\n}\n\nTEST(ScopedSetEnvTest, SetNonExistingVarToString) {\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"UNSET\");\n\n  {\n    ScopedSetEnv scoped_set(\"SCOPED_SET_ENV_TEST_VAR\", \"value\");\n\n    EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"value\");\n  }\n\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"UNSET\");\n}\n\nTEST(ScopedSetEnvTest, SetNonExistingVarToNull) {\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"UNSET\");\n\n  {\n    ScopedSetEnv scoped_set(\"SCOPED_SET_ENV_TEST_VAR\", nullptr);\n\n    EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"UNSET\");\n  }\n\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"UNSET\");\n}\n\nTEST(ScopedSetEnvTest, SetExistingVarToString) {\n  ScopedSetEnv scoped_set(\"SCOPED_SET_ENV_TEST_VAR\", \"value\");\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"value\");\n\n  {\n    ScopedSetEnv scoped_set(\"SCOPED_SET_ENV_TEST_VAR\", \"new_value\");\n\n    EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"new_value\");\n  }\n\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"value\");\n}\n\nTEST(ScopedSetEnvTest, SetExistingVarToNull) {\n  ScopedSetEnv scoped_set(\"SCOPED_SET_ENV_TEST_VAR\", \"value\");\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"value\");\n\n  {\n    ScopedSetEnv scoped_set(\"SCOPED_SET_ENV_TEST_VAR\", nullptr);\n\n    EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"UNSET\");\n  }\n\n  EXPECT_EQ(GetEnvVar(\"SCOPED_SET_ENV_TEST_VAR\"), \"value\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/spinlock.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/spinlock.h\"\n\n#include <algorithm>\n#include <atomic>\n#include <cstdint>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n#include \"absl/base/internal/cycleclock.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/internal/spinlock_wait.h\"\n#include \"absl/base/internal/sysinfo.h\" /* For NumCPUs() */\n#include \"absl/base/internal/tsan_mutex_interface.h\"\n\n// Description of lock-word:\n//  31..00: [............................3][2][1][0]\n//\n//     [0]: kSpinLockHeld\n//     [1]: kSpinLockCooperative\n//     [2]: kSpinLockDisabledScheduling\n// [31..3]: ONLY kSpinLockSleeper OR\n//          Wait time in cycles >> PROFILE_TIMESTAMP_SHIFT\n//\n// Detailed descriptions:\n//\n// Bit [0]: The lock is considered held iff kSpinLockHeld is set.\n//\n// Bit [1]: Eligible waiters (e.g. Fibers) may co-operatively reschedule when\n//          contended iff kSpinLockCooperative is set.\n//\n// Bit [2]: This bit is exclusive from bit [1].  It is used only by a\n//          non-cooperative lock.  When set, indicates that scheduling was\n//          successfully disabled when the lock was acquired.  May be unset,\n//          even if non-cooperative, if a ThreadIdentity did not yet exist at\n//          time of acquisition.\n//\n// Bit [3]: If this is the only upper bit ([31..3]) set then this lock was\n//          acquired without contention, however, at least one waiter exists.\n//\n//          Otherwise, bits [31..3] represent the time spent by the current lock\n//          holder to acquire the lock.  There may be outstanding waiter(s).\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void (*)(\n    const void *lock, int64_t wait_cycles)>\n    submit_profile_data;\n\nvoid RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,\n                                         int64_t wait_cycles)) {\n  submit_profile_data.Store(fn);\n}\n\n// Monitor the lock to see if its value changes within some time period\n// (adaptive_spin_count_ loop iterations). The last value read from the lock\n// is returned from the method.\nABSL_CONST_INIT std::atomic<int> SpinLock::adaptive_spin_count_{0};\nuint32_t SpinLock::SpinLoop() {\n  // We are already in the slow path of SpinLock, initialize the\n  // adaptive_spin_count here.\n  if (adaptive_spin_count_.load(std::memory_order_relaxed) == 0) {\n    int current_spin_count = 0;\n    int new_spin_count = NumCPUs() > 1 ? 1000 : 1;\n    // If this fails, the value will remain unchanged. We may not spin for the\n    // intended duration, but that is still safe. We will try again on the next\n    // call to SpinLoop.\n    adaptive_spin_count_.compare_exchange_weak(\n        current_spin_count, new_spin_count, std::memory_order_relaxed,\n        std::memory_order_relaxed);\n  }\n  int c = adaptive_spin_count_.load(std::memory_order_relaxed);\n  uint32_t lock_value;\n  do {\n    lock_value = lockword_.load(std::memory_order_relaxed);\n  } while ((lock_value & kSpinLockHeld) != 0 && --c > 0);\n  return lock_value;\n}\n\nvoid SpinLock::SlowLock() {\n  uint32_t lock_value = SpinLoop();\n  lock_value = TryLockInternal(lock_value, 0);\n  if ((lock_value & kSpinLockHeld) == 0) {\n    return;\n  }\n\n  SchedulingMode scheduling_mode;\n  if ((lock_value & kSpinLockCooperative) != 0) {\n    scheduling_mode = SCHEDULE_COOPERATIVE_AND_KERNEL;\n  } else {\n    scheduling_mode = SCHEDULE_KERNEL_ONLY;\n  }\n\n  // The lock was not obtained initially, so this thread needs to wait for\n  // it.  Record the current timestamp in the local variable wait_start_time\n  // so the total wait time can be stored in the lockword once this thread\n  // obtains the lock.\n  int64_t wait_start_time = CycleClock::Now();\n  uint32_t wait_cycles = 0;\n  int lock_wait_call_count = 0;\n  while ((lock_value & kSpinLockHeld) != 0) {\n    // If the lock is currently held, but not marked as having a sleeper, mark\n    // it as having a sleeper.\n    if ((lock_value & kWaitTimeMask) == 0) {\n      // Here, just \"mark\" that the thread is going to sleep.  Don't store the\n      // lock wait time in the lock -- the lock word stores the amount of time\n      // that the current holder waited before acquiring the lock, not the wait\n      // time of any thread currently waiting to acquire it.\n      if (lockword_.compare_exchange_strong(\n              lock_value, lock_value | kSpinLockSleeper,\n              std::memory_order_relaxed, std::memory_order_relaxed)) {\n        // Successfully transitioned to kSpinLockSleeper.  Pass\n        // kSpinLockSleeper to the SpinLockWait routine to properly indicate\n        // the last lock_value observed.\n        lock_value |= kSpinLockSleeper;\n      } else if ((lock_value & kSpinLockHeld) == 0) {\n        // Lock is free again, so try and acquire it before sleeping.  The\n        // new lock state will be the number of cycles this thread waited if\n        // this thread obtains the lock.\n        lock_value = TryLockInternal(lock_value, wait_cycles);\n        continue;  // Skip the delay at the end of the loop.\n      } else if ((lock_value & kWaitTimeMask) == 0) {\n        // The lock is still held, without a waiter being marked, but something\n        // else about the lock word changed, causing our CAS to fail. For\n        // example, a new lock holder may have acquired the lock with\n        // kSpinLockDisabledScheduling set, whereas the previous holder had not\n        // set that flag. In this case, attempt again to mark ourselves as a\n        // waiter.\n        continue;\n      }\n    }\n\n    // SpinLockDelay() calls into fiber scheduler, we need to see\n    // synchronization there to avoid false positives.\n    ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);\n    // Wait for an OS specific delay.\n    SpinLockDelay(&lockword_, lock_value, ++lock_wait_call_count,\n                  scheduling_mode);\n    ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);\n    // Spin again after returning from the wait routine to give this thread\n    // some chance of obtaining the lock.\n    lock_value = SpinLoop();\n    wait_cycles = EncodeWaitCycles(wait_start_time, CycleClock::Now());\n    lock_value = TryLockInternal(lock_value, wait_cycles);\n  }\n}\n\nvoid SpinLock::SlowUnlock(uint32_t lock_value) {\n  SpinLockWake(&lockword_,\n               false);  // wake waiter if necessary\n\n  // If our acquisition was contended, collect contentionz profile info.  We\n  // reserve a unitary wait time to represent that a waiter exists without our\n  // own acquisition having been contended.\n  if ((lock_value & kWaitTimeMask) != kSpinLockSleeper) {\n    const int64_t wait_cycles = DecodeWaitCycles(lock_value);\n    ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);\n    submit_profile_data(this, wait_cycles);\n    ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);\n  }\n}\n\n// We use the upper 29 bits of the lock word to store the time spent waiting to\n// acquire this lock.  This is reported by contentionz profiling.  Since the\n// lower bits of the cycle counter wrap very quickly on high-frequency\n// processors we divide to reduce the granularity to 2^kProfileTimestampShift\n// sized units.  On a 4Ghz machine this will lose track of wait times greater\n// than (2^29/4 Ghz)*128 =~ 17.2 seconds.  Such waits should be extremely rare.\nstatic constexpr int kProfileTimestampShift = 7;\n\n// We currently reserve the lower 3 bits.\nstatic constexpr int kLockwordReservedShift = 3;\n\nuint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,\n                                    int64_t wait_end_time) {\n  static const int64_t kMaxWaitTime =\n      std::numeric_limits<uint32_t>::max() >> kLockwordReservedShift;\n  int64_t scaled_wait_time =\n      (wait_end_time - wait_start_time) >> kProfileTimestampShift;\n\n  // Return a representation of the time spent waiting that can be stored in\n  // the lock word's upper bits.\n  uint32_t clamped = static_cast<uint32_t>(\n      std::min(scaled_wait_time, kMaxWaitTime) << kLockwordReservedShift);\n\n  if (clamped == 0) {\n    return kSpinLockSleeper;  // Just wake waiters, but don't record contention.\n  }\n  // Bump up value if necessary to avoid returning kSpinLockSleeper.\n  const uint32_t kMinWaitTime =\n      kSpinLockSleeper + (1 << kLockwordReservedShift);\n  if (clamped == kSpinLockSleeper) {\n    return kMinWaitTime;\n  }\n  return clamped;\n}\n\nint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {\n  // Cast to uint32_t first to ensure bits [63:32] are cleared.\n  const int64_t scaled_wait_time =\n      static_cast<uint32_t>(lock_value & kWaitTimeMask);\n  return scaled_wait_time << (kProfileTimestampShift - kLockwordReservedShift);\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/spinlock.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n//  Most users requiring mutual exclusion should use Mutex.\n//  SpinLock is provided for use in two situations:\n//   - for use by Abseil internal code that Mutex itself depends on\n//   - for async signal safety (see below)\n\n// SpinLock with a SchedulingMode::SCHEDULE_KERNEL_ONLY is async\n// signal safe. If a spinlock is used within a signal handler, all code that\n// acquires the lock must ensure that the signal cannot arrive while they are\n// holding the lock. Typically, this is done by blocking the signal.\n//\n// Threads waiting on a SpinLock may be woken in an arbitrary order.\n\n#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_\n#define ABSL_BASE_INTERNAL_SPINLOCK_H_\n\n#include <atomic>\n#include <cstdint>\n#include <mutex>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/internal/low_level_scheduling.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/internal/tsan_mutex_interface.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/thread_annotations.h\"\n\nnamespace tcmalloc {\nnamespace tcmalloc_internal {\n\nclass AllocationGuardSpinLockHolder;\nclass Static;\n\n}  // namespace tcmalloc_internal\n}  // namespace tcmalloc\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nclass ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock {\n public:\n  constexpr SpinLock() : lockword_(kSpinLockCooperative) { RegisterWithTsan(); }\n\n  // Constructors that allow non-cooperative spinlocks to be created for use\n  // inside thread schedulers.  Normal clients should not use these.\n  constexpr explicit SpinLock(SchedulingMode mode)\n      : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {\n    RegisterWithTsan();\n  }\n\n#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(_WIN32)\n  // Constructor to inline users of the default scheduling mode.\n  //\n  // This only needs to exists for inliner runs, but doesn't work correctly in\n  // clang+windows builds, likely due to mangling differences.\n  ABSL_DEPRECATE_AND_INLINE()\n  constexpr explicit SpinLock(SchedulingMode mode)\n      __attribute__((enable_if(mode == SCHEDULE_COOPERATIVE_AND_KERNEL,\n                               \"Cooperative use default constructor\")))\n      : SpinLock() {}\n#endif\n\n  // Constructor for global SpinLock instances.  See absl/base/const_init.h.\n  ABSL_DEPRECATE_AND_INLINE()\n  constexpr SpinLock(absl::ConstInitType, SchedulingMode mode)\n      : SpinLock(mode) {}\n\n  // For global SpinLock instances prefer trivial destructor when possible.\n  // Default but non-trivial destructor in some build configurations causes an\n  // extra static initializer.\n#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE\n  ~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }\n#else\n  ~SpinLock() = default;\n#endif\n\n  // Acquire this SpinLock.\n  inline void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);\n    if (!TryLockImpl()) {\n      SlowLock();\n    }\n    ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);\n  }\n\n  ABSL_DEPRECATE_AND_INLINE()\n  inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { return lock(); }\n\n  // Try to acquire this SpinLock without blocking and return true if the\n  // acquisition was successful.  If the lock was not acquired, false is\n  // returned.  If this SpinLock is free at the time of the call, try_lock will\n  // return true with high probability.\n  [[nodiscard]] inline bool try_lock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {\n    ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);\n    bool res = TryLockImpl();\n    ABSL_TSAN_MUTEX_POST_LOCK(\n        this, __tsan_mutex_try_lock | (res ? 0 : __tsan_mutex_try_lock_failed),\n        0);\n    return res;\n  }\n\n  ABSL_DEPRECATE_AND_INLINE()\n  [[nodiscard]] inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {\n    return try_lock();\n  }\n\n  // Release this SpinLock, which must be held by the calling thread.\n  inline void unlock() ABSL_UNLOCK_FUNCTION() {\n    ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);\n    uint32_t lock_value = lockword_.load(std::memory_order_relaxed);\n    lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,\n                                    std::memory_order_release);\n\n    if ((lock_value & kSpinLockDisabledScheduling) != 0) {\n      SchedulingGuard::EnableRescheduling(true);\n    }\n    if ((lock_value & kWaitTimeMask) != 0) {\n      // Collect contentionz profile info, and speed the wakeup of any waiter.\n      // The wait_cycles value indicates how long this thread spent waiting\n      // for the lock.\n      SlowUnlock(lock_value);\n    }\n    ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);\n  }\n\n  ABSL_DEPRECATE_AND_INLINE()\n  inline void Unlock() ABSL_UNLOCK_FUNCTION() { unlock(); }\n\n  // Determine if the lock is held.  When the lock is held by the invoking\n  // thread, true will always be returned. Intended to be used as\n  // CHECK(lock.IsHeld()).\n  [[nodiscard]] inline bool IsHeld() const {\n    return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;\n  }\n\n  // Return immediately if this thread holds the SpinLock exclusively.\n  // Otherwise, report an error by crashing with a diagnostic.\n  inline void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK() {\n    if (!IsHeld()) {\n      ABSL_RAW_LOG(FATAL, \"thread should hold the lock on SpinLock\");\n    }\n  }\n\n protected:\n  // These should not be exported except for testing.\n\n  // Store number of cycles between wait_start_time and wait_end_time in a\n  // lock value.\n  static uint32_t EncodeWaitCycles(int64_t wait_start_time,\n                                   int64_t wait_end_time);\n\n  // Extract number of wait cycles in a lock value.\n  static int64_t DecodeWaitCycles(uint32_t lock_value);\n\n  // Provide access to protected method above.  Use for testing only.\n  friend struct SpinLockTest;\n  friend class tcmalloc::tcmalloc_internal::AllocationGuardSpinLockHolder;\n  friend class tcmalloc::tcmalloc_internal::Static;\n\n  static int GetAdaptiveSpinCount() {\n    return adaptive_spin_count_.load(std::memory_order_relaxed);\n  }\n  static void SetAdaptiveSpinCount(int count) {\n    adaptive_spin_count_.store(count, std::memory_order_relaxed);\n  }\n\n  static std::atomic<int> adaptive_spin_count_;\n\n private:\n  // lockword_ is used to store the following:\n  //\n  // bit[0] encodes whether a lock is being held.\n  // bit[1] encodes whether a lock uses cooperative scheduling.\n  // bit[2] encodes whether the current lock holder disabled scheduling when\n  //        acquiring the lock. Only set when kSpinLockHeld is also set.\n  // bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.\n  //        This is set by the lock holder to indicate how long it waited on\n  //        the lock before eventually acquiring it. The number of cycles is\n  //        encoded as a 29-bit unsigned int, or in the case that the current\n  //        holder did not wait but another waiter is queued, the LSB\n  //        (kSpinLockSleeper) is set. The implementation does not explicitly\n  //        track the number of queued waiters beyond this. It must always be\n  //        assumed that waiters may exist if the current holder was required to\n  //        queue.\n  //\n  // Invariant: if the lock is not held, the value is either 0 or\n  // kSpinLockCooperative.\n  static constexpr uint32_t kSpinLockHeld = 1;\n  static constexpr uint32_t kSpinLockCooperative = 2;\n  static constexpr uint32_t kSpinLockDisabledScheduling = 4;\n  static constexpr uint32_t kSpinLockSleeper = 8;\n  // Includes kSpinLockSleeper.\n  static constexpr uint32_t kWaitTimeMask =\n      ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling);\n\n  // Returns true if the provided scheduling mode is cooperative.\n  static constexpr bool IsCooperative(SchedulingMode scheduling_mode) {\n    return scheduling_mode == SCHEDULE_COOPERATIVE_AND_KERNEL;\n  }\n\n  constexpr void RegisterWithTsan() {\n#if ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)\n    if (!__builtin_is_constant_evaluated()) {\n      ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);\n    }\n#endif\n  }\n\n  bool IsCooperative() const {\n    return lockword_.load(std::memory_order_relaxed) & kSpinLockCooperative;\n  }\n\n  uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);\n  void SlowLock() ABSL_ATTRIBUTE_COLD;\n  void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;\n  uint32_t SpinLoop();\n\n  inline bool TryLockImpl() {\n    uint32_t lock_value = lockword_.load(std::memory_order_relaxed);\n    return (TryLockInternal(lock_value, 0) & kSpinLockHeld) == 0;\n  }\n\n  std::atomic<uint32_t> lockword_;\n\n  SpinLock(const SpinLock&) = delete;\n  SpinLock& operator=(const SpinLock&) = delete;\n};\n\n// Corresponding locker object that arranges to acquire a spinlock for\n// the duration of a C++ scope.\nclass ABSL_SCOPED_LOCKABLE [[nodiscard]] SpinLockHolder\n    : public std::lock_guard<SpinLock> {\n public:\n  inline explicit SpinLockHolder(\n      SpinLock& l ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(l)\n      : std::lock_guard<SpinLock>(l) {}\n  ABSL_DEPRECATE_AND_INLINE()\n  inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)\n      : SpinLockHolder(*l) {}\n\n  inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() = default;\n};\n\n// Register a hook for profiling support.\n//\n// The function pointer registered here will be called whenever a spinlock is\n// contended.  The callback is given an opaque handle to the contended spinlock\n// and the number of wait cycles.  This is thread-safe, but only a single\n// profiler can be registered.  It is an error to call this function multiple\n// times with different arguments.\nvoid RegisterSpinLockProfiler(void (*fn)(const void* lock,\n                                         int64_t wait_cycles));\n\n//------------------------------------------------------------------------------\n// Public interface ends here.\n//------------------------------------------------------------------------------\n\n// If (result & kSpinLockHeld) == 0, then *this was successfully locked.\n// Otherwise, returns last observed value for lockword_.\ninline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,\n                                          uint32_t wait_cycles) {\n  if ((lock_value & kSpinLockHeld) != 0) {\n    return lock_value;\n  }\n\n  uint32_t sched_disabled_bit = 0;\n  if ((lock_value & kSpinLockCooperative) == 0) {\n    // For non-cooperative locks we must make sure we mark ourselves as\n    // non-reschedulable before we attempt to CompareAndSwap.\n    if (SchedulingGuard::DisableRescheduling()) {\n      sched_disabled_bit = kSpinLockDisabledScheduling;\n    }\n  }\n\n  if (!lockword_.compare_exchange_strong(\n          lock_value,\n          kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit,\n          std::memory_order_acquire, std::memory_order_relaxed)) {\n    SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0);\n  }\n\n  return lock_value;\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_SPINLOCK_H_\n"
  },
  {
    "path": "absl/base/internal/spinlock_akaros.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file is an Akaros-specific part of spinlock_wait.cc\n\n#include <atomic>\n\n#include \"absl/base/internal/scheduling_mode.h\"\n\nextern \"C\" {\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(\n    std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */,\n    int /* loop */, absl::base_internal::SchedulingMode /* mode */) {\n  // In Akaros, one must take care not to call anything that could cause a\n  // malloc(), a blocking system call, or a uthread_yield() while holding a\n  // spinlock. Our callers assume will not call into libraries or other\n  // arbitrary code.\n}\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(\n    std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}\n\n}  // extern \"C\"\n"
  },
  {
    "path": "absl/base/internal/spinlock_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// See also //absl/synchronization:mutex_benchmark for a comparison of SpinLock\n// and Mutex performance under varying levels of contention.\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/synchronization/internal/create_thread_identity.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\ntemplate <absl::base_internal::SchedulingMode scheduling_mode>\nstatic void BM_TryLock(benchmark::State& state) {\n  // Ensure a ThreadIdentity is installed so that KERNEL_ONLY has an effect.\n  ABSL_INTERNAL_CHECK(\n      absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=\n          nullptr,\n      \"GetOrCreateCurrentThreadIdentity() failed\");\n\n  static absl::NoDestructor<absl::base_internal::SpinLock> spinlock(\n      scheduling_mode);\n  for (auto _ : state) {\n    if (spinlock->try_lock()) spinlock->unlock();\n  }\n}\n\ntemplate <absl::base_internal::SchedulingMode scheduling_mode>\nstatic void BM_SpinLock(benchmark::State& state) {\n  // Ensure a ThreadIdentity is installed so that KERNEL_ONLY has an effect.\n  ABSL_INTERNAL_CHECK(\n      absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=\n          nullptr,\n      \"GetOrCreateCurrentThreadIdentity() failed\");\n\n  static absl::NoDestructor<absl::base_internal::SpinLock> spinlock(\n      scheduling_mode);\n  for (auto _ : state) {\n    absl::base_internal::SpinLockHolder holder(*spinlock.get());\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_SpinLock,\n                   absl::base_internal::SCHEDULE_KERNEL_ONLY)\n    ->UseRealTime()\n    ->Threads(1)\n    ->ThreadPerCpu();\n\nBENCHMARK_TEMPLATE(BM_SpinLock,\n                   absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)\n    ->UseRealTime()\n    ->Threads(1)\n    ->ThreadPerCpu();\n\nBENCHMARK_TEMPLATE(BM_TryLock, absl::base_internal::SCHEDULE_KERNEL_ONLY)\n    ->UseRealTime()\n    ->Threads(1)\n    ->ThreadPerCpu();\n\nBENCHMARK_TEMPLATE(BM_TryLock,\n                   absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)\n    ->UseRealTime()\n    ->Threads(1)\n    ->ThreadPerCpu();\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/spinlock_linux.inc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file is a Linux-specific part of spinlock_wait.cc\n\n#include <linux/futex.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#include <atomic>\n#include <climits>\n#include <cstdint>\n#include <ctime>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/errno_saver.h\"\n\n// The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that\n// `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected\n// by SYS_futex. We also assume that reads/writes done to the lockword\n// by SYS_futex have rational semantics with regard to the\n// std::atomic<> API. C++ provides no guarantees of these assumptions,\n// but they are believed to hold in practice.\nstatic_assert(sizeof(std::atomic<uint32_t>) == sizeof(int),\n              \"SpinLock lockword has the wrong size for a futex\");\n\n// Some Android headers are missing these definitions even though they\n// support these futex operations.\n#ifdef __BIONIC__\n#ifndef SYS_futex\n#define SYS_futex __NR_futex\n#endif\n#ifndef FUTEX_PRIVATE_FLAG\n#define FUTEX_PRIVATE_FLAG 128\n#endif\n#endif\n\n#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)\n#define SYS_futex_time64 __NR_futex_time64\n#endif\n\n#if defined(SYS_futex_time64) && !defined(SYS_futex)\n#define SYS_futex SYS_futex_time64\n#endif\n\nextern \"C\" {\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(\n    std::atomic<uint32_t> *w, uint32_t value, int,\n    absl::base_internal::SchedulingMode) {\n  absl::base_internal::ErrnoSaver errno_saver;\n  syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, nullptr);\n}\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(\n    std::atomic<uint32_t> *w, bool all) {\n  syscall(SYS_futex, w, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, all ? INT_MAX : 1, 0);\n}\n\n}  // extern \"C\"\n"
  },
  {
    "path": "absl/base/internal/spinlock_posix.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file is a Posix-specific part of spinlock_wait.cc\n\n#include <sched.h>\n\n#include <atomic>\n#include <ctime>\n\n#include \"absl/base/internal/errno_saver.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/port.h\"\n\nextern \"C\" {\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(\n    std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,\n    absl::base_internal::SchedulingMode /* mode */) {\n  absl::base_internal::ErrnoSaver errno_saver;\n  if (loop == 0) {\n  } else if (loop == 1) {\n    sched_yield();\n  } else {\n    struct timespec tm;\n    tm.tv_sec = 0;\n    tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);\n    nanosleep(&tm, nullptr);\n  }\n}\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(\n    std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}\n\n}  // extern \"C\"\n"
  },
  {
    "path": "absl/base/internal/spinlock_wait.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// The OS-specific header included below must provide two calls:\n// AbslInternalSpinLockDelay() and AbslInternalSpinLockWake().\n// See spinlock_wait.h for the specs.\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/internal/spinlock_wait.h\"\n\n#if defined(_WIN32)\n#include \"absl/base/internal/spinlock_win32.inc\"\n#elif defined(__linux__)\n#include \"absl/base/internal/spinlock_linux.inc\"\n#elif defined(__akaros__)\n#include \"absl/base/internal/spinlock_akaros.inc\"\n#else\n#include \"absl/base/internal/spinlock_posix.inc\"\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// See spinlock_wait.h for spec.\nuint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,\n                      const SpinLockWaitTransition trans[],\n                      base_internal::SchedulingMode scheduling_mode) {\n  int loop = 0;\n  for (;;) {\n    uint32_t v = w->load(std::memory_order_acquire);\n    int i;\n    for (i = 0; i != n && v != trans[i].from; i++) {\n    }\n    if (i == n) {\n      SpinLockDelay(w, v, ++loop, scheduling_mode);  // no matching transition\n    } else if (trans[i].to == v ||                   // null transition\n               w->compare_exchange_strong(v, trans[i].to,\n                                          std::memory_order_acquire,\n                                          std::memory_order_relaxed)) {\n      if (trans[i].done) return v;\n    }\n  }\n}\n\nstatic std::atomic<uint64_t> delay_rand;\n\n// Return a suggested delay in nanoseconds for iteration number \"loop\"\nint SpinLockSuggestedDelayNS(int loop) {\n  // Weak pseudo-random number generator to get some spread between threads\n  // when many are spinning.\n  uint64_t r = delay_rand.load(std::memory_order_relaxed);\n  r = 0x5deece66dLL * r + 0xb;   // numbers from nrand48()\n  delay_rand.store(r, std::memory_order_relaxed);\n\n  if (loop < 0 || loop > 32) {   // limit loop to 0..32\n    loop = 32;\n  }\n  const int kMinDelay = 128 << 10;  // 128us\n  // Double delay every 8 iterations, up to 16x (2ms).\n  int delay = kMinDelay << (loop / 8);\n  // Randomize in delay..2*delay range, for resulting 128us..4ms range.\n  return delay | ((delay - 1) & static_cast<int>(r));\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/spinlock_wait.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_\n#define ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_\n\n// Operations to make atomic transitions on a word, and to allow\n// waiting for those transitions to become possible.\n\n#include <stdint.h>\n#include <atomic>\n\n#include \"absl/base/internal/scheduling_mode.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// SpinLockWait() waits until it can perform one of several transitions from\n// \"from\" to \"to\".  It returns when it performs a transition where done==true.\nstruct SpinLockWaitTransition {\n  uint32_t from;\n  uint32_t to;\n  bool done;\n};\n\n// Wait until *w can transition from trans[i].from to trans[i].to for some i\n// satisfying 0<=i<n && trans[i].done, atomically make the transition,\n// then return the old value of *w.   Make any other atomic transitions\n// where !trans[i].done, but continue waiting.\n//\n// Wakeups for threads blocked on SpinLockWait do not respect priorities.\nuint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,\n                      const SpinLockWaitTransition trans[],\n                      SchedulingMode scheduling_mode);\n\n// If possible, wake some thread that has called SpinLockDelay(w, ...). If `all`\n// is true, wake all such threads. On some systems, this may be a no-op; on\n// those systems, threads calling SpinLockDelay() will always wake eventually\n// even if SpinLockWake() is never called.\nvoid SpinLockWake(std::atomic<uint32_t> *w, bool all);\n\n// Wait for an appropriate spin delay on iteration \"loop\" of a\n// spin loop on location *w, whose previously observed value was \"value\".\n// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,\n// or may wait for a call to SpinLockWake(w).\nvoid SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,\n                   base_internal::SchedulingMode scheduling_mode);\n\n// Helper used by AbslInternalSpinLockDelay.\n// Returns a suggested delay in nanoseconds for iteration number \"loop\".\nint SpinLockSuggestedDelayNS(int loop);\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// In some build configurations we pass --detect-odr-violations to the\n// gold linker.  This causes it to flag weak symbol overrides as ODR\n// violations.  Because ODR only applies to C++ and not C,\n// --detect-odr-violations ignores symbols not mangled with C++ names.\n// By changing our extension points to be extern \"C\", we dodge this\n// check.\nextern \"C\" {\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(std::atomic<uint32_t> *w,\n                                                      bool all);\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(\n    std::atomic<uint32_t> *w, uint32_t value, int loop,\n    absl::base_internal::SchedulingMode scheduling_mode);\n}\n\ninline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w,\n                                              bool all) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(w, all);\n}\n\ninline void absl::base_internal::SpinLockDelay(\n    std::atomic<uint32_t> *w, uint32_t value, int loop,\n    absl::base_internal::SchedulingMode scheduling_mode) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)\n  (w, value, loop, scheduling_mode);\n}\n\n#endif  // ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_\n"
  },
  {
    "path": "absl/base/internal/spinlock_win32.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file is a Win32-specific part of spinlock_wait.cc\n\n#include <windows.h>\n#include <atomic>\n#include \"absl/base/internal/scheduling_mode.h\"\n\nextern \"C\" {\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(\n    std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,\n    absl::base_internal::SchedulingMode /* mode */) {\n  if (loop == 0) {\n  } else if (loop == 1) {\n    Sleep(0);\n  } else {\n    // SpinLockSuggestedDelayNS() always returns a positive integer, so this\n    // static_cast is safe.\n    Sleep(static_cast<DWORD>(\n        absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000));\n  }\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(\n    std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}\n\n}  // extern \"C\"\n"
  },
  {
    "path": "absl/base/internal/strerror.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/strerror.h\"\n\n#include <array>\n#include <cerrno>\n#include <cstddef>\n#include <cstdio>\n#include <cstring>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/internal/errno_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\nconst char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {\n#if defined(_WIN32)\n  int rc = strerror_s(buf, buflen, errnum);\n  buf[buflen - 1] = '\\0';  // guarantee NUL termination\n  if (rc == 0 && strncmp(buf, \"Unknown error\", buflen) == 0) *buf = '\\0';\n  return buf;\n#else\n  // The type of `ret` is platform-specific; both of these branches must compile\n  // either way but only one will execute on any given platform:\n  auto ret = strerror_r(errnum, buf, buflen);\n  if (std::is_same<decltype(ret), int>::value) {\n    // XSI `strerror_r`; `ret` is `int`:\n    if (ret) *buf = '\\0';\n    return buf;\n  } else {\n    // GNU `strerror_r`; `ret` is `char *`:\n    return reinterpret_cast<const char*>(ret);\n  }\n#endif\n}\n\nstd::string StrErrorInternal(int errnum) {\n  char buf[100];\n  const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);\n  if (*str == '\\0') {\n    snprintf(buf, sizeof buf, \"Unknown error %d\", errnum);\n    str = buf;\n  }\n  return str;\n}\n\n// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back\n// to `StrErrorAdaptor()` if the value is larger than this.\nconstexpr int kSysNerr = 135;\n\nstd::array<std::string, kSysNerr>* NewStrErrorTable() {\n  auto* table = new std::array<std::string, kSysNerr>;\n  for (size_t i = 0; i < table->size(); ++i) {\n    (*table)[i] = StrErrorInternal(static_cast<int>(i));\n  }\n  return table;\n}\n\n}  // namespace\n\nstd::string StrError(int errnum) {\n  absl::base_internal::ErrnoSaver errno_saver;\n  static const auto* table = NewStrErrorTable();\n  if (errnum >= 0 && static_cast<size_t>(errnum) < table->size()) {\n    return (*table)[static_cast<size_t>(errnum)];\n  }\n  return StrErrorInternal(errnum);\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/strerror.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_STRERROR_H_\n#define ABSL_BASE_INTERNAL_STRERROR_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// A portable and thread-safe alternative to C89's `strerror`.\n//\n// The C89 specification of `strerror` is not suitable for use in a\n// multi-threaded application as the returned string may be changed by calls to\n// `strerror` from another thread.  The many non-stdlib alternatives differ\n// enough in their names, availability, and semantics to justify this wrapper\n// around them.  `errno` will not be modified by a call to `absl::StrError`.\nstd::string StrError(int errnum);\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_STRERROR_H_\n"
  },
  {
    "path": "absl/base/internal/strerror_benchmark.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cerrno>\n#include <cstdio>\n#include <string>\n\n#include \"absl/base/internal/strerror.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\nvoid BM_AbslStrError(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));\n  }\n}\nBENCHMARK(BM_AbslStrError);\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/strerror_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/strerror.h\"\n\n#include <atomic>\n#include <cerrno>\n#include <cstdio>\n#include <cstring>\n#include <string>\n#include <thread>  // NOLINT(build/c++11)\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/match.h\"\n\nnamespace {\nusing ::testing::AnyOf;\nusing ::testing::Eq;\n\nTEST(StrErrorTest, ValidErrorCode) {\n  errno = ERANGE;\n  EXPECT_THAT(absl::base_internal::StrError(EDOM), Eq(strerror(EDOM)));\n  EXPECT_THAT(errno, Eq(ERANGE));\n}\n\nTEST(StrErrorTest, InvalidErrorCode) {\n  errno = ERANGE;\n  EXPECT_THAT(absl::base_internal::StrError(-1),\n              AnyOf(Eq(\"No error information\"), Eq(\"Unknown error -1\"),\n                    Eq(\"Unknown error\")));\n  EXPECT_THAT(errno, Eq(ERANGE));\n}\n\nTEST(StrErrorTest, MultipleThreads) {\n  // In this test, we will start up 2 threads and have each one call\n  // StrError 1000 times, each time with a different errnum.  We\n  // expect that StrError(errnum) will return a string equal to the\n  // one returned by strerror(errnum), if the code is known.  Since\n  // strerror is known to be thread-hostile, collect all the expected\n  // strings up front.\n  const int kNumCodes = 1000;\n  std::vector<std::string> expected_strings(kNumCodes);\n  for (int i = 0; i < kNumCodes; ++i) {\n    expected_strings[i] = strerror(i);\n  }\n\n  std::atomic_int counter(0);\n  auto thread_fun = [&]() {\n    for (int i = 0; i < kNumCodes; ++i) {\n      ++counter;\n      errno = ERANGE;\n      const std::string value = absl::base_internal::StrError(i);\n      // EXPECT_* could change errno. Stash it first.\n      int check_err = errno;\n      EXPECT_THAT(check_err, Eq(ERANGE));\n      // Only the GNU implementation is guaranteed to provide the\n      // string \"Unknown error nnn\". POSIX doesn't say anything.\n      if (!absl::StartsWith(value, \"Unknown error \")) {\n        EXPECT_THAT(value, Eq(expected_strings[i]));\n      }\n    }\n  };\n\n  const int kNumThreads = 100;\n  std::vector<std::thread> threads;\n  for (int i = 0; i < kNumThreads; ++i) {\n    threads.push_back(std::thread(thread_fun));\n  }\n  for (auto& thread : threads) {\n    thread.join();\n  }\n\n  EXPECT_THAT(counter, Eq(kNumThreads * kNumCodes));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/sysinfo.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/sysinfo.h\"\n\n#include \"absl/base/attributes.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <fcntl.h>\n#include <pthread.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n#endif\n\n#ifdef __linux__\n#include <sys/syscall.h>\n#endif\n\n#if defined(__APPLE__) || defined(__FreeBSD__)\n#include <sys/sysctl.h>\n#endif\n\n#ifdef __FreeBSD__\n#include <pthread_np.h>\n#endif\n\n#ifdef __NetBSD__\n#include <lwp.h>\n#endif\n\n#if defined(__myriad2__)\n#include <rtems.h>\n#endif\n\n#if defined(__Fuchsia__)\n#include <zircon/process.h>\n#endif\n\n#include <string.h>\n\n#include <cassert>\n#include <cerrno>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <ctime>\n#include <limits>\n#include <thread>  // NOLINT(build/c++11)\n#include <utility>\n#include <vector>\n\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/internal/unscaledcycleclock.h\"\n#include \"absl/base/thread_annotations.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nnamespace {\n\n#if defined(_WIN32)\n\n// Returns number of bits set in `bitMask`\nDWORD Win32CountSetBits(ULONG_PTR bitMask) {\n  for (DWORD bitSetCount = 0; ; ++bitSetCount) {\n    if (bitMask == 0) return bitSetCount;\n    bitMask &= bitMask - 1;\n  }\n}\n\n// Returns the number of logical CPUs using GetLogicalProcessorInformation(), or\n// 0 if the number of processors is not available or can not be computed.\n// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation\nint Win32NumCPUs() {\n#pragma comment(lib, \"kernel32.lib\")\n  using Info = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;\n\n  DWORD info_size = sizeof(Info);\n  Info* info(static_cast<Info*>(malloc(info_size)));\n  if (info == nullptr) return 0;\n\n  bool success = GetLogicalProcessorInformation(info, &info_size);\n  if (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {\n    free(info);\n    info = static_cast<Info*>(malloc(info_size));\n    if (info == nullptr) return 0;\n    success = GetLogicalProcessorInformation(info, &info_size);\n  }\n\n  DWORD logicalProcessorCount = 0;\n  if (success) {\n    Info* ptr = info;\n    DWORD byteOffset = 0;\n    while (byteOffset + sizeof(Info) <= info_size) {\n      switch (ptr->Relationship) {\n        case RelationProcessorCore:\n          logicalProcessorCount += Win32CountSetBits(ptr->ProcessorMask);\n          break;\n\n        case RelationNumaNode:\n        case RelationCache:\n        case RelationProcessorPackage:\n          // Ignore other entries\n          break;\n\n        default:\n          // Ignore unknown entries\n          break;\n      }\n      byteOffset += sizeof(Info);\n      ptr++;\n    }\n  }\n  free(info);\n  return static_cast<int>(logicalProcessorCount);\n}\n\n#endif\n\n}  // namespace\n\nstatic int GetNumCPUs() {\n#if defined(__myriad2__)\n  return 1;\n#elif defined(_WIN32)\n  const int hardware_concurrency = Win32NumCPUs();\n  return hardware_concurrency ? hardware_concurrency : 1;\n#elif defined(_AIX)\n  return sysconf(_SC_NPROCESSORS_ONLN);\n#else\n  // Other possibilities:\n  //  - Read /sys/devices/system/cpu/online and use cpumask_parse()\n  //  - sysconf(_SC_NPROCESSORS_ONLN)\n  return static_cast<int>(std::thread::hardware_concurrency());\n#endif\n}\n\n#if defined(_WIN32)\n\nstatic double GetNominalCPUFrequency() {\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \\\n    !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\n  // UWP apps don't have access to the registry and currently don't provide an\n  // API informing about CPU nominal frequency.\n  return 1.0;\n#else\n#pragma comment(lib, \"advapi32.lib\")  // For Reg* functions.\n  HKEY key;\n  // Use the Reg* functions rather than the SH functions because shlwapi.dll\n  // pulls in gdi32.dll which makes process destruction much more costly.\n  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,\n                    \"HARDWARE\\\\DESCRIPTION\\\\System\\\\CentralProcessor\\\\0\", 0,\n                    KEY_READ, &key) == ERROR_SUCCESS) {\n    DWORD type = 0;\n    DWORD data = 0;\n    DWORD data_size = sizeof(data);\n    auto result = RegQueryValueExA(key, \"~MHz\", nullptr, &type,\n                                   reinterpret_cast<LPBYTE>(&data), &data_size);\n    RegCloseKey(key);\n    if (result == ERROR_SUCCESS && type == REG_DWORD &&\n        data_size == sizeof(data)) {\n      return data * 1e6;  // Value is MHz.\n    }\n  }\n  return 1.0;\n#endif  // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP\n}\n\n#elif defined(CTL_HW) && defined(HW_CPU_FREQ)\n\nstatic double GetNominalCPUFrequency() {\n  unsigned freq;\n  size_t size = sizeof(freq);\n  int mib[2] = {CTL_HW, HW_CPU_FREQ};\n  if (sysctl(mib, 2, &freq, &size, nullptr, 0) == 0) {\n    return static_cast<double>(freq);\n  }\n  return 1.0;\n}\n\n#else\n\n// Helper function for reading a long from a file. Returns true if successful\n// and the memory location pointed to by value is set to the value read.\nstatic bool ReadLongFromFile(const char *file, long *value) {\n  bool ret = false;\n#if defined(_POSIX_C_SOURCE)\n  const int file_mode = (O_RDONLY | O_CLOEXEC);\n#else\n  const int file_mode = O_RDONLY;\n#endif\n\n  int fd = open(file, file_mode);\n  if (fd != -1) {\n    char line[1024];\n    char *err;\n    memset(line, '\\0', sizeof(line));\n    ssize_t len;\n    do {\n      len = read(fd, line, sizeof(line) - 1);\n    } while (len < 0 && errno == EINTR);\n    if (len <= 0) {\n      ret = false;\n    } else {\n      const long temp_value = strtol(line, &err, 10);\n      if (line[0] != '\\0' && (*err == '\\n' || *err == '\\0')) {\n        *value = temp_value;\n        ret = true;\n      }\n    }\n    close(fd);\n  }\n  return ret;\n}\n\n#if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)\n\n// Reads a monotonic time source and returns a value in\n// nanoseconds. The returned value uses an arbitrary epoch, not the\n// Unix epoch.\nstatic int64_t ReadMonotonicClockNanos() {\n  struct timespec t;\n#ifdef CLOCK_MONOTONIC_RAW\n  int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &t);\n#else\n  int rc = clock_gettime(CLOCK_MONOTONIC, &t);\n#endif\n  if (rc != 0) {\n    ABSL_INTERNAL_LOG(\n        FATAL, \"clock_gettime() failed: (\" + std::to_string(errno) + \")\");\n  }\n  return int64_t{t.tv_sec} * 1000000000 + t.tv_nsec;\n}\n\nclass UnscaledCycleClockWrapperForInitializeFrequency {\n public:\n  static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); }\n};\n\nstruct TimeTscPair {\n  int64_t time;  // From ReadMonotonicClockNanos().\n  int64_t tsc;   // From UnscaledCycleClock::Now().\n};\n\n// Returns a pair of values (monotonic kernel time, TSC ticks) that\n// approximately correspond to each other.  This is accomplished by\n// doing several reads and picking the reading with the lowest\n// latency.  This approach is used to minimize the probability that\n// our thread was preempted between clock reads.\nstatic TimeTscPair GetTimeTscPair() {\n  int64_t best_latency = std::numeric_limits<int64_t>::max();\n  TimeTscPair best;\n  for (int i = 0; i < 10; ++i) {\n    int64_t t0 = ReadMonotonicClockNanos();\n    int64_t tsc = UnscaledCycleClockWrapperForInitializeFrequency::Now();\n    int64_t t1 = ReadMonotonicClockNanos();\n    int64_t latency = t1 - t0;\n    if (latency < best_latency) {\n      best_latency = latency;\n      best.time = t0;\n      best.tsc = tsc;\n    }\n  }\n  return best;\n}\n\n// Measures and returns the TSC frequency by taking a pair of\n// measurements approximately `sleep_nanoseconds` apart.\nstatic double MeasureTscFrequencyWithSleep(int sleep_nanoseconds) {\n  auto t0 = GetTimeTscPair();\n  struct timespec ts;\n  ts.tv_sec = 0;\n  ts.tv_nsec = sleep_nanoseconds;\n  while (nanosleep(&ts, &ts) != 0 && errno == EINTR) {}\n  auto t1 = GetTimeTscPair();\n  double elapsed_ticks = t1.tsc - t0.tsc;\n  double elapsed_time = (t1.time - t0.time) * 1e-9;\n  return elapsed_ticks / elapsed_time;\n}\n\n// Measures and returns the TSC frequency by calling\n// MeasureTscFrequencyWithSleep(), doubling the sleep interval until the\n// frequency measurement stabilizes.\nstatic double MeasureTscFrequency() {\n  double last_measurement = -1.0;\n  int sleep_nanoseconds = 1000000;  // 1 millisecond.\n  for (int i = 0; i < 8; ++i) {\n    double measurement = MeasureTscFrequencyWithSleep(sleep_nanoseconds);\n    if (measurement * 0.99 < last_measurement &&\n        last_measurement < measurement * 1.01) {\n      // Use the current measurement if it is within 1% of the\n      // previous measurement.\n      return measurement;\n    }\n    last_measurement = measurement;\n    sleep_nanoseconds *= 2;\n  }\n  return last_measurement;\n}\n\n#endif  // ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY\n\nstatic double GetNominalCPUFrequency() {\n  long freq = 0;\n\n  // Google's production kernel has a patch to export the TSC\n  // frequency through sysfs. If the kernel is exporting the TSC\n  // frequency use that. There are issues where cpuinfo_max_freq\n  // cannot be relied on because the BIOS may be exporting an invalid\n  // p-state (on x86) or p-states may be used to put the processor in\n  // a new mode (turbo mode). Essentially, those frequencies cannot\n  // always be relied upon. The same reasons apply to /proc/cpuinfo as\n  // well.\n  if (ReadLongFromFile(\"/sys/devices/system/cpu/cpu0/tsc_freq_khz\", &freq)) {\n    return freq * 1e3;  // Value is kHz.\n  }\n\n#if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)\n  // On these platforms, the TSC frequency is the nominal CPU\n  // frequency.  But without having the kernel export it directly\n  // though /sys/devices/system/cpu/cpu0/tsc_freq_khz, there is no\n  // other way to reliably get the TSC frequency, so we have to\n  // measure it ourselves.  Some CPUs abuse cpuinfo_max_freq by\n  // exporting \"fake\" frequencies for implementing new features. For\n  // example, Intel's turbo mode is enabled by exposing a p-state\n  // value with a higher frequency than that of the real TSC\n  // rate. Because of this, we prefer to measure the TSC rate\n  // ourselves on i386 and x86-64.\n  return MeasureTscFrequency();\n#else\n\n  // If CPU scaling is in effect, we want to use the *maximum*\n  // frequency, not whatever CPU speed some random processor happens\n  // to be using now.\n  if (ReadLongFromFile(\"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq\",\n                       &freq)) {\n    return freq * 1e3;  // Value is kHz.\n  }\n\n  return 1.0;\n#endif  // !ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY\n}\n\n#endif\n\nABSL_CONST_INIT static once_flag init_num_cpus_once;\nABSL_CONST_INIT static int num_cpus = 0;\n\n// NumCPUs() may be called before main() and before malloc is properly\n// initialized, therefore this must not allocate memory.\nint NumCPUs() {\n  base_internal::LowLevelCallOnce(\n      &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); });\n  return num_cpus;\n}\n\n// A default frequency of 0.0 might be dangerous if it is used in division.\nABSL_CONST_INIT static once_flag init_nominal_cpu_frequency_once;\nABSL_CONST_INIT static double nominal_cpu_frequency = 1.0;\n\n// NominalCPUFrequency() may be called before main() and before malloc is\n// properly initialized, therefore this must not allocate memory.\ndouble NominalCPUFrequency() {\n  base_internal::LowLevelCallOnce(\n      &init_nominal_cpu_frequency_once,\n      []() { nominal_cpu_frequency = GetNominalCPUFrequency(); });\n  return nominal_cpu_frequency;\n}\n\n#if defined(_WIN32)\n\npid_t GetTID() {\n  return pid_t{GetCurrentThreadId()};\n}\n\n#elif defined(__linux__)\n\n#ifndef SYS_gettid\n#define SYS_gettid __NR_gettid\n#endif\n\npid_t GetTID() {\n  return static_cast<pid_t>(syscall(SYS_gettid));\n}\n\n#elif defined(__akaros__)\n\npid_t GetTID() {\n  // Akaros has a concept of \"vcore context\", which is the state the program\n  // is forced into when we need to make a user-level scheduling decision, or\n  // run a signal handler.  This is analogous to the interrupt context that a\n  // CPU might enter if it encounters some kind of exception.\n  //\n  // There is no current thread context in vcore context, but we need to give\n  // a reasonable answer if asked for a thread ID (e.g., in a signal handler).\n  // Thread 0 always exists, so if we are in vcore context, we return that.\n  //\n  // Otherwise, we know (since we are using pthreads) that the uthread struct\n  // current_uthread is pointing to is the first element of a\n  // struct pthread_tcb, so we extract and return the thread ID from that.\n  //\n  // TODO(dcross): Akaros anticipates moving the thread ID to the uthread\n  // structure at some point. We should modify this code to remove the cast\n  // when that happens.\n  if (in_vcore_context())\n    return 0;\n  return reinterpret_cast<struct pthread_tcb *>(current_uthread)->id;\n}\n\n#elif defined(__myriad2__)\n\npid_t GetTID() {\n  uint32_t tid;\n  rtems_task_ident(RTEMS_SELF, 0, &tid);\n  return tid;\n}\n\n#elif defined(__APPLE__)\n\npid_t GetTID() {\n  uint64_t tid;\n  // `nullptr` here implies this thread.  This only fails if the specified\n  // thread is invalid or the pointer-to-tid is null, so we needn't worry about\n  // it.\n  pthread_threadid_np(nullptr, &tid);\n  return static_cast<pid_t>(tid);\n}\n\n#elif defined(__FreeBSD__)\n\npid_t GetTID() { return static_cast<pid_t>(pthread_getthreadid_np()); }\n\n#elif defined(__OpenBSD__)\n\npid_t GetTID() { return getthrid(); }\n\n#elif defined(__NetBSD__)\n\npid_t GetTID() { return static_cast<pid_t>(_lwp_self()); }\n\n#elif defined(__Fuchsia__)\n\npid_t GetTID() {\n  // Use our thread handle as the TID, which should be unique within this\n  // process (but may not be globally unique). The handle value was chosen over\n  // a kernel object ID (KOID) because zx_handle_t (32-bits) can be cast to a\n  // pid_t type without loss of precision, but a zx_koid_t (64-bits) cannot.\n  return static_cast<pid_t>(zx_thread_self());\n}\n\n#else\n\n// Fallback implementation of `GetTID` using `pthread_self`.\npid_t GetTID() {\n  // `pthread_t` need not be arithmetic per POSIX; platforms where it isn't\n  // should be handled above.\n  return static_cast<pid_t>(pthread_self());\n}\n\n#endif\n\n// GetCachedTID() caches the thread ID in thread-local storage (which is a\n// userspace construct) to avoid unnecessary system calls. Without this caching,\n// it can take roughly 98ns, while it takes roughly 1ns with this caching.\npid_t GetCachedTID() {\n#ifdef ABSL_HAVE_THREAD_LOCAL\n  static thread_local pid_t thread_id = GetTID();\n  return thread_id;\n#else\n  return GetTID();\n#endif  // ABSL_HAVE_THREAD_LOCAL\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/sysinfo.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file includes routines to find out characteristics\n// of the machine a program is running on.  It is undoubtedly\n// system-dependent.\n\n// Functions listed here that accept a pid_t as an argument act on the\n// current process if the pid_t argument is 0\n// All functions here are thread-hostile due to file caching unless\n// commented otherwise.\n\n#ifndef ABSL_BASE_INTERNAL_SYSINFO_H_\n#define ABSL_BASE_INTERNAL_SYSINFO_H_\n\n#ifndef _WIN32\n#include <sys/types.h>\n#endif\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/port.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Nominal core processor cycles per second of each processor.   This is _not_\n// necessarily the frequency of the CycleClock counter (see cycleclock.h)\n// Thread-safe.\ndouble NominalCPUFrequency();\n\n// Number of logical processors (hyperthreads) in system. Thread-safe.\nint NumCPUs();\n\n// Return the thread id of the current thread, as told by the system.\n// No two currently-live threads implemented by the OS shall have the same ID.\n// Thread ids of exited threads may be reused.   Multiple user-level threads\n// may have the same thread ID if multiplexed on the same OS thread.\n//\n// On Linux, you may send a signal to the resulting ID with kill().  However,\n// it is recommended for portability that you use pthread_kill() instead.\n#ifdef _WIN32\n// On Windows, process id and thread id are of the same type according to the\n// return types of GetProcessId() and GetThreadId() are both DWORD, an unsigned\n// 32-bit type.\nusing pid_t = uint32_t;\n#endif\npid_t GetTID();\n\n// Like GetTID(), but caches the result in thread-local storage in order\n// to avoid unnecessary system calls. Note that there are some cases where\n// one must call through to GetTID directly, which is why this exists as a\n// separate function. For example, GetCachedTID() is not safe to call in\n// an asynchronous signal-handling context nor right after a call to fork().\npid_t GetCachedTID();\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_SYSINFO_H_\n"
  },
  {
    "path": "absl/base/internal/sysinfo_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/sysinfo.h\"\n\n#ifndef _WIN32\n#include <sys/types.h>\n#include <unistd.h>\n#endif\n\n#include <thread>  // NOLINT(build/c++11)\n#include <unordered_set>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/synchronization/barrier.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\nTEST(SysinfoTest, NumCPUs) {\n  EXPECT_NE(NumCPUs(), 0)\n      << \"NumCPUs() should not have the default value of 0\";\n}\n\nTEST(SysinfoTest, GetTID) {\n  EXPECT_EQ(GetTID(), GetTID());  // Basic compile and equality test.\n  // Test that TIDs are unique to each thread.\n  // Uses a few loops to exercise implementations that reallocate IDs.\n  for (int i = 0; i < 10; ++i) {\n    constexpr int kNumThreads = 10;\n    Barrier all_threads_done(kNumThreads);\n    std::vector<std::thread> threads;\n\n    Mutex mutex;\n    std::unordered_set<pid_t> tids;\n\n    for (int j = 0; j < kNumThreads; ++j) {\n      threads.push_back(std::thread([&]() {\n        pid_t id = GetTID();\n        {\n          MutexLock lock(mutex);\n          ASSERT_TRUE(tids.find(id) == tids.end());\n          tids.insert(id);\n        }\n        // We can't simply join the threads here. The threads need to\n        // be alive otherwise the TID might have been reallocated to\n        // another live thread.\n        all_threads_done.Block();\n      }));\n    }\n    for (auto& thread : threads) {\n      thread.join();\n    }\n  }\n}\n\n#ifdef __linux__\nTEST(SysinfoTest, LinuxGetTID) {\n  // On Linux, for the main thread, GetTID()==getpid() is guaranteed by the API.\n  EXPECT_EQ(GetTID(), getpid());\n}\n#endif\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/thread_identity.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/thread_identity.h\"\n\n#if !defined(_WIN32) || defined(__MINGW32__)\n#include <pthread.h>\n#ifndef __wasi__\n// WASI does not provide this header, either way we disable use\n// of signals with it below.\n#include <signal.h>\n#endif\n#endif\n\n#include <atomic>\n#include <cassert>\n#include <memory>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/spinlock.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n#if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11\nnamespace {\n// Used to co-ordinate one-time creation of our pthread_key\nabsl::once_flag init_thread_identity_key_once;\npthread_key_t thread_identity_pthread_key;\nstd::atomic<bool> pthread_key_initialized(false);\n\nvoid AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) {\n  pthread_key_create(&thread_identity_pthread_key, reclaimer);\n  pthread_key_initialized.store(true, std::memory_order_release);\n}\n}  // namespace\n#endif\n\n#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \\\n    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n// The actual TLS storage for a thread's currently associated ThreadIdentity.\n// This is referenced by inline accessors in the header.\n// \"protected\" visibility ensures that if multiple instances of Abseil code\n// exist within a process (via dlopen() or similar), references to\n// thread_identity_ptr from each instance of the code will refer to\n// *different* instances of this ptr.\n// Apple platforms have the visibility attribute, but issue a compile warning\n// that protected visibility is unsupported.\nABSL_CONST_INIT  // Must come before __attribute__((visibility(\"protected\")))\n#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)\n    __attribute__((visibility(\"protected\")))\n#endif  // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)\n#if ABSL_PER_THREAD_TLS\n    // Prefer __thread to thread_local as benchmarks indicate it is a bit\n    // faster.\n    ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;\n#elif defined(ABSL_HAVE_THREAD_LOCAL)\n    thread_local ThreadIdentity* thread_identity_ptr = nullptr;\n#endif  // ABSL_PER_THREAD_TLS\n#endif  // TLS or CPP11\n\nvoid SetCurrentThreadIdentity(ThreadIdentity* identity,\n                              ThreadIdentityReclaimerFunction reclaimer) {\n  assert(CurrentThreadIdentityIfPresent() == nullptr);\n  // Associate our destructor.\n  // NOTE: This call to pthread_setspecific is currently the only immovable\n  // barrier to CurrentThreadIdentity() always being async signal safe.\n#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC\n  // NOTE: Not async-safe.  But can be open-coded.\n  absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,\n                  reclaimer);\n\n#if defined(__wasi__) || defined(__EMSCRIPTEN__) || defined(__MINGW32__) || \\\n    defined(__hexagon__)\n  // Emscripten, WASI and MinGW pthread implementations does not support\n  // signals. See\n  // https://kripken.github.io/emscripten-site/docs/porting/pthreads.html for\n  // more information.\n  pthread_setspecific(thread_identity_pthread_key,\n                      reinterpret_cast<void*>(identity));\n#else\n  // We must mask signals around the call to setspecific as with current glibc,\n  // a concurrent getspecific (needed for GetCurrentThreadIdentityIfPresent())\n  // may zero our value.\n  //\n  // While not officially async-signal safe, getspecific within a signal handler\n  // is otherwise OK.\n  sigset_t all_signals;\n  sigset_t curr_signals;\n  sigfillset(&all_signals);\n  pthread_sigmask(SIG_SETMASK, &all_signals, &curr_signals);\n  pthread_setspecific(thread_identity_pthread_key,\n                      reinterpret_cast<void*>(identity));\n  pthread_sigmask(SIG_SETMASK, &curr_signals, nullptr);\n#endif  // !__EMSCRIPTEN__ && !__MINGW32__\n\n#elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS\n  // NOTE: Not async-safe.  But can be open-coded.\n  absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,\n                  reclaimer);\n  pthread_setspecific(thread_identity_pthread_key,\n                      reinterpret_cast<void*>(identity));\n  thread_identity_ptr = identity;\n#elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n  thread_local std::unique_ptr<ThreadIdentity, ThreadIdentityReclaimerFunction>\n      holder(identity, reclaimer);\n  thread_identity_ptr = identity;\n#else\n#error Unimplemented ABSL_THREAD_IDENTITY_MODE\n#endif\n}\n\n#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \\\n    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n\n// Please see the comment on `CurrentThreadIdentityIfPresent` in\n// thread_identity.h. When we cannot expose thread_local variables in\n// headers, we opt for the correct-but-slower option of not inlining this\n// function.\n#ifndef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT\nThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; }\n#endif\n#endif\n\nvoid ClearCurrentThreadIdentity() {\n#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \\\n    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n  thread_identity_ptr = nullptr;\n#elif ABSL_THREAD_IDENTITY_MODE == \\\n    ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC\n  // pthread_setspecific expected to clear value on destruction\n  assert(CurrentThreadIdentityIfPresent() == nullptr);\n#endif\n}\n\n#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC\nThreadIdentity* CurrentThreadIdentityIfPresent() {\n  bool initialized = pthread_key_initialized.load(std::memory_order_acquire);\n  if (!initialized) {\n    return nullptr;\n  }\n  return reinterpret_cast<ThreadIdentity*>(\n      pthread_getspecific(thread_identity_pthread_key));\n}\n#endif\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/thread_identity.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Each active thread has an ThreadIdentity that may represent the thread in\n// various level interfaces.  ThreadIdentity objects are never deallocated.\n// When a thread terminates, its ThreadIdentity object may be reused for a\n// thread created later.\n\n#ifndef ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_\n#define ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_\n\n#ifndef _WIN32\n#include <pthread.h>\n// Defines __GOOGLE_GRTE_VERSION__ (via glibc-specific features.h) when\n// supported.\n#include <unistd.h>\n#endif\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/per_thread_tls.h\"\n#include \"absl/base/optimization.h\"\n\n// Forward declare Gloop class for scheduling.\nnamespace base {\nnamespace scheduling {\nclass Schedulable;\n}  // namespace scheduling\n}  // namespace base\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nstruct SynchLocksHeld;\nstruct SynchWaitParams;\n\nnamespace base_internal {\n\nclass SpinLock;\nstruct ThreadIdentity;\n\n// Used by the implementation of absl::Mutex and absl::CondVar.\nstruct PerThreadSynch {\n  // The internal representation of absl::Mutex and absl::CondVar rely\n  // on the alignment of PerThreadSynch. Both store the address of the\n  // PerThreadSynch in the high-order bits of their internal state,\n  // which means the low kLowZeroBits of the address of PerThreadSynch\n  // must be zero.\n  static constexpr int kLowZeroBits = 8;\n  static constexpr int kAlignment = 1 << kLowZeroBits;\n\n  // Returns the associated ThreadIdentity.\n  // This can be implemented as a cast because we guarantee\n  // PerThreadSynch is the first element of ThreadIdentity.\n  ThreadIdentity* thread_identity() {\n    return reinterpret_cast<ThreadIdentity*>(this);\n  }\n\n  PerThreadSynch* next;  // Circular waiter queue; initialized to 0.\n  PerThreadSynch* skip;  // If non-zero, all entries in Mutex queue\n                         // up to and including \"skip\" have same\n                         // condition as this, and will be woken later\n  bool may_skip;         // if false while on mutex queue, a mutex unlocker\n                         // is using this PerThreadSynch as a terminator.  Its\n                         // skip field must not be filled in because the loop\n                         // might then skip over the terminator.\n  bool wake;             // This thread is to be woken from a Mutex.\n  // If \"x\" is on a waiter list for a mutex, \"x->cond_waiter\" is true iff the\n  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.\n  //\n  // The value of \"x->cond_waiter\" is meaningless if \"x\" is not on a\n  // Mutex waiter list.\n  bool cond_waiter;\n  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;\n                         // true if UnlockSlow could be searching\n                         // for a waiter to wake.  Used for an optimization\n                         // in Enqueue().  true is always a valid value.\n                         // Can be reset to false when the unlocker or any\n                         // writer releases the lock, or a reader fully\n                         // releases the lock.  It may not be set to false\n                         // by a reader that decrements the count to\n                         // non-zero. protected by mutex spinlock\n  bool suppress_fatal_errors;  // If true, try to proceed even in the face\n                               // of broken invariants.  This is used within\n                               // fatal signal handlers to improve the\n                               // chances of debug logging information being\n                               // output successfully.\n  int priority;                // Priority of thread (updated every so often).\n\n  // State values:\n  //   kAvailable: This PerThreadSynch is available.\n  //   kQueued: This PerThreadSynch is unavailable, it's currently queued on a\n  //            Mutex or CondVar waistlist.\n  //\n  // Transitions from kQueued to kAvailable require a release\n  // barrier. This is needed as a waiter may use \"state\" to\n  // independently observe that it's no longer queued.\n  //\n  // Transitions from kAvailable to kQueued require no barrier, they\n  // are externally ordered by the Mutex.\n  enum State { kAvailable, kQueued };\n  std::atomic<State> state;\n\n  // The wait parameters of the current wait.  waitp is null if the\n  // thread is not waiting. Transitions from null to non-null must\n  // occur before the enqueue commit point (state = kQueued in\n  // Enqueue() and CondVarEnqueue()). Transitions from non-null to\n  // null must occur after the wait is finished (state = kAvailable in\n  // Mutex::Block() and CondVar::WaitCommon()). This field may be\n  // changed only by the thread that describes this PerThreadSynch.  A\n  // special case is Fer(), which calls Enqueue() on another thread,\n  // but with an identical SynchWaitParams pointer, thus leaving the\n  // pointer unchanged.\n  SynchWaitParams* waitp;\n\n  intptr_t readers;  // Number of readers in mutex.\n\n  // When priority will next be read (cycles).\n  int64_t next_priority_read_cycles;\n\n  // Locks held; used during deadlock detection.\n  // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().\n  SynchLocksHeld* all_locks;\n};\n\n// The instances of this class are allocated in NewThreadIdentity() with an\n// alignment of PerThreadSynch::kAlignment and never destroyed. Initialization\n// should happen in OneTimeInitThreadIdentity().\n//\n// Instances may be reused by new threads - fields should be reset in\n// ResetThreadIdentityBetweenReuse().\n//\n// NOTE: The layout of fields in this structure is critical, please do not\n//       add, remove, or modify the field placements without fully auditing the\n//       layout.\nstruct ThreadIdentity {\n  // Must be the first member.  The Mutex implementation requires that\n  // the PerThreadSynch object associated with each thread is\n  // PerThreadSynch::kAlignment aligned.  We provide this alignment on\n  // ThreadIdentity itself.\n  PerThreadSynch per_thread_synch;\n\n  struct SchedulerState {\n    std::atomic<base::scheduling::Schedulable*> bound_schedulable{nullptr};\n    // Storage space for a SpinLock, which is created through a placement new to\n    // break a dependency cycle.\n    uint32_t association_lock_word;\n    std::atomic<int> scheduling_disabled_depth;\n    int potentially_blocking_depth;\n    uint32_t schedule_next_state;\n\n    // When true, current thread is unlocking a mutex and actively waking a\n    // thread that was previously waiting, but that lock has yet more waiters.\n    // Used to signal to schedulers that work being woken should get an\n    // elevated priority.\n    bool waking_designated_waker;\n\n    inline SpinLock* association_lock() {\n      return reinterpret_cast<SpinLock*>(&association_lock_word);\n    }\n\n    inline base::scheduling::Schedulable* get_bound_schedulable() const {\n      return bound_schedulable.load(std::memory_order_relaxed);\n    }\n  } scheduler_state;  // Private: Reserved for use in Gloop\n\n  // For worker threads that may not be doing any interesting user work, this\n  // tracks the current state of the worker. This is used to handle those\n  // threads differently e.g. when printing stacktraces.\n  //\n  // It should only be written to by the thread itself.\n  //\n  // Note that this is different from the mutex idle bit - threads running user\n  // work can be waiting but still be active.\n  //\n  // Note: not all parts of the code-base may maintain this field correctly and\n  // therefore this field should only be used to improve debugging/monitoring.\n  //\n  // Put it here to reuse some of the padding space.\n  enum class WaitState : uint8_t {\n    kActive = 0,\n    kWaitingForWork = 1,\n  };\n  std::atomic<WaitState> wait_state;\n  static_assert(std::atomic<WaitState>::is_always_lock_free);\n\n  // Add a padding such that scheduler_state is on a different cache line than\n  // waiter state.  We use padding here, so that the size of the structure does\n  // not substantially grow due to the added padding.\n  static constexpr size_t kToBePaddedSize =\n      sizeof(SchedulerState) + sizeof(std::atomic<WaitState>);\n  static_assert(ABSL_CACHELINE_SIZE >= kToBePaddedSize);\n  char padding[ABSL_CACHELINE_SIZE - kToBePaddedSize];\n\n  // Private: Reserved for absl::synchronization_internal::Waiter.\n  struct WaiterState {\n    alignas(void*) char data[256];\n  } waiter_state;\n\n  // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().\n  std::atomic<int>* blocked_count_ptr;\n\n  // The following variables are mostly read/written just by the\n  // thread itself.  The only exception is that these are read by\n  // a ticker thread as a hint.\n  std::atomic<int> ticker;      // Tick counter, incremented once per second.\n  std::atomic<int> wait_start;  // Ticker value when thread started waiting.\n  std::atomic<bool> is_idle;    // Has thread become idle yet?\n\n  // For tracking depth of __cxa_guard_acquire.  This used to recognize heap\n  // allocations for function static objects.\n  int static_initialization_depth;\n\n  ThreadIdentity* next;\n};\n\n// Returns the ThreadIdentity object representing the calling thread; guaranteed\n// to be unique for its lifetime.  The returned object will remain valid for the\n// program's lifetime; although it may be re-assigned to a subsequent thread.\n// If one does not exist, return nullptr instead.\n//\n// Does not malloc(*), and is async-signal safe.\n// [*] Technically pthread_setspecific() does malloc on first use; however this\n// is handled internally within tcmalloc's initialization already. Note that\n// darwin does *not* use tcmalloc, so this can catch you if using MallocHooks\n// on Apple platforms. Whatever function is calling your MallocHooks will need\n// to watch for recursion on Apple platforms.\n//\n// New ThreadIdentity objects can be constructed and associated with a thread\n// by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.\nThreadIdentity* CurrentThreadIdentityIfPresent();\n\nusing ThreadIdentityReclaimerFunction = void (*)(void*);\n\n// Sets the current thread identity to the given value.  'reclaimer' is a\n// pointer to the global function for cleaning up instances on thread\n// destruction.\nvoid SetCurrentThreadIdentity(ThreadIdentity* identity,\n                              ThreadIdentityReclaimerFunction reclaimer);\n\n// Removes the currently associated ThreadIdentity from the running thread.\n// This must be called from inside the ThreadIdentityReclaimerFunction, and only\n// from that function.\nvoid ClearCurrentThreadIdentity();\n\n// May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode\n// index>\n#ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC\n#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be directly set\n#else\n#define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0\n#endif\n\n#ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS\n#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be directly set\n#else\n#define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1\n#endif\n\n#ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be directly set\n#else\n#define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2\n#endif\n\n#ifdef ABSL_THREAD_IDENTITY_MODE\n#error ABSL_THREAD_IDENTITY_MODE cannot be directly set\n#elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)\n#define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE\n#elif defined(_WIN32) && !defined(__MINGW32__)\n#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)\n#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \\\n    (__GOOGLE_GRTE_VERSION__ >= 20140228L)\n// Support for async-safe TLS was specifically added in GRTEv4.  It's not\n// present in the upstream eglibc.\n// Note:  Current default for production systems.\n#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_TLS\n#else\n#define ABSL_THREAD_IDENTITY_MODE \\\n  ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC\n#endif\n\n#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \\\n    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11\n\n#if ABSL_PER_THREAD_TLS\nABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*\n    thread_identity_ptr;\n#elif defined(ABSL_HAVE_THREAD_LOCAL)\nABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;\n#else\n#error Thread-local storage not detected on this platform\n#endif\n\n// thread_local variables cannot be in headers exposed by DLLs or in certain\n// build configurations on Apple platforms. However, it is important for\n// performance reasons in general that `CurrentThreadIdentityIfPresent` be\n// inlined. In the other cases we opt to have the function not be inlined. Note\n// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude\n// this entire inline definition.\n#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) && \\\n    !defined(ABSL_CONSUME_DLL)\n#define ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT 1\n#endif\n\n#ifdef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT\ninline ThreadIdentity* CurrentThreadIdentityIfPresent() {\n  return thread_identity_ptr;\n}\n#endif\n\n#elif ABSL_THREAD_IDENTITY_MODE != \\\n    ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC\n#error Unknown ABSL_THREAD_IDENTITY_MODE\n#endif\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_\n"
  },
  {
    "path": "absl/base/internal/thread_identity_benchmark.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/synchronization/internal/create_thread_identity.h\"\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_SafeCurrentThreadIdentity(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(\n        absl::synchronization_internal::GetOrCreateCurrentThreadIdentity());\n  }\n}\nBENCHMARK(BM_SafeCurrentThreadIdentity);\n\nvoid BM_UnsafeCurrentThreadIdentity(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(\n        absl::base_internal::CurrentThreadIdentityIfPresent());\n  }\n}\nBENCHMARK(BM_UnsafeCurrentThreadIdentity);\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/thread_identity_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/thread_identity.h\"\n\n#include <thread>  // NOLINT(build/c++11)\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\nnamespace {\n\nABSL_CONST_INIT static absl::base_internal::SpinLock map_lock(\n    base_internal::SCHEDULE_KERNEL_ONLY);\nABSL_CONST_INIT static int num_identities_reused ABSL_GUARDED_BY(map_lock);\n\nstatic const void* const kCheckNoIdentity = reinterpret_cast<void*>(1);\n\nstatic void TestThreadIdentityCurrent(const void* assert_no_identity) {\n  ThreadIdentity* identity;\n\n  // We have to test this conditionally, because if the test framework relies\n  // on Abseil, then some previous action may have already allocated an\n  // identity.\n  if (assert_no_identity == kCheckNoIdentity) {\n    identity = CurrentThreadIdentityIfPresent();\n    EXPECT_TRUE(identity == nullptr);\n  }\n\n  identity = synchronization_internal::GetOrCreateCurrentThreadIdentity();\n  EXPECT_TRUE(identity != nullptr);\n  ThreadIdentity* identity_no_init;\n  identity_no_init = CurrentThreadIdentityIfPresent();\n  EXPECT_TRUE(identity == identity_no_init);\n\n  // Check that per_thread_synch is correctly aligned.\n  EXPECT_EQ(0, reinterpret_cast<intptr_t>(&identity->per_thread_synch) %\n                   PerThreadSynch::kAlignment);\n  EXPECT_EQ(identity, identity->per_thread_synch.thread_identity());\n\n  absl::base_internal::SpinLockHolder l(map_lock);\n  num_identities_reused++;\n}\n\nTEST(ThreadIdentityTest, BasicIdentityWorks) {\n  // This tests for the main() thread.\n  TestThreadIdentityCurrent(nullptr);\n}\n\nTEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {\n  // Now try the same basic test with multiple threads being created and\n  // destroyed.  This makes sure that:\n  // - New threads are created without a ThreadIdentity.\n  // - We re-allocate ThreadIdentity objects from the free-list.\n  // - If a thread implementation chooses to recycle threads, that\n  //   correct re-initialization occurs.\n  static const int kNumLoops = 3;\n  static const int kNumThreads = 32;\n  for (int iter = 0; iter < kNumLoops; iter++) {\n    std::vector<std::thread> threads;\n    for (int i = 0; i < kNumThreads; ++i) {\n      threads.push_back(\n          std::thread(TestThreadIdentityCurrent, kCheckNoIdentity));\n    }\n    for (auto& thread : threads) {\n      thread.join();\n    }\n  }\n\n  // We should have recycled ThreadIdentity objects above; while (external)\n  // library threads allocating their own identities may preclude some\n  // reuse, we should have sufficient repetitions to exclude this.\n  absl::base_internal::SpinLockHolder l(map_lock);\n  EXPECT_LT(kNumThreads, num_identities_reused);\n}\n\nTEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) {\n  // This test repeatedly creates and joins a series of threads, each of\n  // which acquires and releases shared Mutex locks. This verifies\n  // Mutex operations work correctly under a reused\n  // ThreadIdentity. Note that the most likely failure mode of this\n  // test is a crash or deadlock.\n  static const int kNumLoops = 10;\n  static const int kNumThreads = 12;\n  static const int kNumMutexes = 3;\n  static const int kNumLockLoops = 5;\n\n  Mutex mutexes[kNumMutexes];\n  for (int iter = 0; iter < kNumLoops; ++iter) {\n    std::vector<std::thread> threads;\n    for (int thread = 0; thread < kNumThreads; ++thread) {\n      threads.push_back(std::thread([&]() {\n        for (int l = 0; l < kNumLockLoops; ++l) {\n          for (int m = 0; m < kNumMutexes; ++m) {\n            MutexLock lock(mutexes[m]);\n          }\n        }\n      }));\n    }\n    for (auto& thread : threads) {\n      thread.join();\n    }\n  }\n}\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/tracing.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/tracing.h\"\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\nextern \"C\" {\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(\n    const void*, ObjectKind) {}\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(\n    const void*, ObjectKind) {}\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(\n    const void*, ObjectKind) {}\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(\n    const void*, ObjectKind) {}\n\n}  // extern \"C\"\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/internal/tracing.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_TRACING_H_\n#define ABSL_BASE_INTERNAL_TRACING_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Well known Abseil object types that have causality.\nenum class ObjectKind { kUnknown, kBlockingCounter, kNotification };\n\n// `TraceWait` and `TraceContinue` record the start and end of a potentially\n// blocking wait operation on `object`. `object` typically represents a higher\n// level synchronization object such as `absl::Notification`.\nvoid TraceWait(const void* object, ObjectKind kind);\nvoid TraceContinue(const void* object, ObjectKind kind);\n\n// `TraceSignal` records a signal on `object`.\nvoid TraceSignal(const void* object, ObjectKind kind);\n\n// `TraceObserved` records the non-blocking observation of a signaled object.\nvoid TraceObserved(const void* object, ObjectKind kind);\n\n// ---------------------------------------------------------------------------\n// Weak implementation detail:\n//\n// We define the weak API as extern \"C\": in some build configurations we pass\n// `--detect-odr-violations` to the gold linker. This causes it to flag weak\n// symbol overrides as ODR violations. Because ODR only applies to C++ and not\n// C, `--detect-odr-violations` ignores symbols not mangled with C++ names.\n// By changing our extension points to be extern \"C\", we dodge this check.\n// ---------------------------------------------------------------------------\nextern \"C\" {\n\n  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,\n                                                     ObjectKind kind);\n  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,\n                                                         ObjectKind kind);\n  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,\n                                                       ObjectKind kind);\n  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,\n                                                         ObjectKind kind);\n\n}  // extern \"C\"\n\ninline void TraceWait(const void* object, ObjectKind kind) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(object, kind);\n}\n\ninline void TraceContinue(const void* object, ObjectKind kind) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(object, kind);\n}\n\ninline void TraceSignal(const void* object, ObjectKind kind) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(object, kind);\n}\n\ninline void TraceObserved(const void* object, ObjectKind kind) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(object, kind);\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_INTERNAL_TRACING_H_\n"
  },
  {
    "path": "absl/base/internal/tracing_strong_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include <tuple>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/tracing.h\"\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\n\nnamespace {\n\nusing ::testing::ElementsAre;\n\nusing ::absl::base_internal::ObjectKind;\n\nenum Function { kWait, kContinue, kSignal, kObserved };\n\nusing Record = std::tuple<Function, const void*, ObjectKind>;\n\nthread_local std::vector<Record>* tls_records = nullptr;\n\n}  // namespace\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Strong extern \"C\" implementation.\nextern \"C\" {\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,\n                                                   ObjectKind kind) {\n  if (tls_records != nullptr) {\n    tls_records->push_back({kWait, object, kind});\n  }\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,\n                                                       ObjectKind kind) {\n  if (tls_records != nullptr) {\n    tls_records->push_back({kContinue, object, kind});\n  }\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,\n                                                     ObjectKind kind) {\n  if (tls_records != nullptr) {\n    tls_records->push_back({kSignal, object, kind});\n  }\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,\n                                                       ObjectKind kind) {\n  if (tls_records != nullptr) {\n    tls_records->push_back({kObserved, object, kind});\n  }\n}\n\n}  // extern \"C\"\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nnamespace {\n\nTEST(TracingInternal, InvokesStrongFunctionWithNullptr) {\n  std::vector<Record> records;\n  tls_records = &records;\n  auto kind = absl::base_internal::ObjectKind::kUnknown;\n  absl::base_internal::TraceWait(nullptr, kind);\n  absl::base_internal::TraceContinue(nullptr, kind);\n  absl::base_internal::TraceSignal(nullptr, kind);\n  absl::base_internal::TraceObserved(nullptr, kind);\n  tls_records = nullptr;\n\n  EXPECT_THAT(records, ElementsAre(Record{kWait, nullptr, kind},\n                                   Record{kContinue, nullptr, kind},\n                                   Record{kSignal, nullptr, kind},\n                                   Record{kObserved, nullptr, kind}));\n}\n\nTEST(TracingInternal, InvokesStrongFunctionWithObjectAddress) {\n  int object = 0;\n  std::vector<Record> records;\n  tls_records = &records;\n  auto kind = absl::base_internal::ObjectKind::kUnknown;\n  absl::base_internal::TraceWait(&object, kind);\n  absl::base_internal::TraceContinue(&object, kind);\n  absl::base_internal::TraceSignal(&object, kind);\n  absl::base_internal::TraceObserved(&object, kind);\n  tls_records = nullptr;\n\n  EXPECT_THAT(records, ElementsAre(Record{kWait, &object, kind},\n                                   Record{kContinue, &object, kind},\n                                   Record{kSignal, &object, kind},\n                                   Record{kObserved, &object, kind}));\n}\n\n}  // namespace\n\n#endif  // ABSL_HAVE_ATTRIBUTE_WEAK\n"
  },
  {
    "path": "absl/base/internal/tracing_weak_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/tracing.h\"\n\nnamespace {\n\nTEST(TracingInternal, HasDefaultImplementation) {\n  auto kind = absl::base_internal::ObjectKind::kUnknown;\n  absl::base_internal::TraceWait(nullptr, kind);\n  absl::base_internal::TraceContinue(nullptr, kind);\n  absl::base_internal::TraceSignal(nullptr, kind);\n  absl::base_internal::TraceObserved(nullptr, kind);\n\n  int object = 0;\n  absl::base_internal::TraceWait(&object, kind);\n  absl::base_internal::TraceContinue(&object, kind);\n  absl::base_internal::TraceSignal(&object, kind);\n  absl::base_internal::TraceObserved(&object, kind);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/tsan_mutex_interface.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file is intended solely for spinlock.h.\n// It provides ThreadSanitizer annotations for custom mutexes.\n// See <sanitizer/tsan_interface.h> for meaning of these annotations.\n\n#ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_\n#define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_\n\n#include \"absl/base/config.h\"\n\n// ABSL_INTERNAL_HAVE_TSAN_INTERFACE\n// Macro intended only for internal use.\n//\n// Checks whether LLVM Thread Sanitizer interfaces are available.\n// First made available in LLVM 5.0 (Sep 2017).\n#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE\n#error \"ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set.\"\n#endif\n\n#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)\n#if __has_include(<sanitizer/tsan_interface.h>)\n#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1\n#endif\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE\n#include <sanitizer/tsan_interface.h>\n\n#define ABSL_TSAN_MUTEX_CREATE __tsan_mutex_create\n#define ABSL_TSAN_MUTEX_DESTROY __tsan_mutex_destroy\n#define ABSL_TSAN_MUTEX_PRE_LOCK __tsan_mutex_pre_lock\n#define ABSL_TSAN_MUTEX_POST_LOCK __tsan_mutex_post_lock\n#define ABSL_TSAN_MUTEX_PRE_UNLOCK __tsan_mutex_pre_unlock\n#define ABSL_TSAN_MUTEX_POST_UNLOCK __tsan_mutex_post_unlock\n#define ABSL_TSAN_MUTEX_PRE_SIGNAL __tsan_mutex_pre_signal\n#define ABSL_TSAN_MUTEX_POST_SIGNAL __tsan_mutex_post_signal\n#define ABSL_TSAN_MUTEX_PRE_DIVERT __tsan_mutex_pre_divert\n#define ABSL_TSAN_MUTEX_POST_DIVERT __tsan_mutex_post_divert\n\n#else\n\n#define ABSL_TSAN_MUTEX_CREATE(...)\n#define ABSL_TSAN_MUTEX_DESTROY(...)\n#define ABSL_TSAN_MUTEX_PRE_LOCK(...)\n#define ABSL_TSAN_MUTEX_POST_LOCK(...)\n#define ABSL_TSAN_MUTEX_PRE_UNLOCK(...)\n#define ABSL_TSAN_MUTEX_POST_UNLOCK(...)\n#define ABSL_TSAN_MUTEX_PRE_SIGNAL(...)\n#define ABSL_TSAN_MUTEX_POST_SIGNAL(...)\n#define ABSL_TSAN_MUTEX_PRE_DIVERT(...)\n#define ABSL_TSAN_MUTEX_POST_DIVERT(...)\n\n#endif\n\n#endif  // ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_\n"
  },
  {
    "path": "absl/base/internal/unaligned_access.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_\n#define ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_\n\n#include <string.h>\n\n#include <cstdint>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\n// unaligned APIs\n\n// Portable handling of unaligned loads, stores, and copies.\n\n// The unaligned API is C++ only.  The declarations use C++ features\n// (namespaces, inline) which are absent or incompatible in C.\n#if defined(__cplusplus)\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\ninline uint16_t UnalignedLoad16(const void* absl_nonnull p) {\n  uint16_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\n\ninline uint32_t UnalignedLoad32(const void* absl_nonnull p) {\n  uint32_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\n\ninline uint64_t UnalignedLoad64(const void* absl_nonnull p) {\n  uint64_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\n\ninline void UnalignedStore16(void* absl_nonnull p, uint16_t v) {\n  memcpy(p, &v, sizeof v);\n}\n\ninline void UnalignedStore32(void* absl_nonnull p, uint32_t v) {\n  memcpy(p, &v, sizeof v);\n}\n\ninline void UnalignedStore64(void* absl_nonnull p, uint64_t v) {\n  memcpy(p, &v, sizeof v);\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \\\n  (absl::base_internal::UnalignedLoad16(_p))\n#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \\\n  (absl::base_internal::UnalignedLoad32(_p))\n#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \\\n  (absl::base_internal::UnalignedLoad64(_p))\n\n#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \\\n  (absl::base_internal::UnalignedStore16(_p, _val))\n#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \\\n  (absl::base_internal::UnalignedStore32(_p, _val))\n#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \\\n  (absl::base_internal::UnalignedStore64(_p, _val))\n\n#endif  // defined(__cplusplus), end of unaligned API\n\n#endif  // ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_\n"
  },
  {
    "path": "absl/base/internal/unique_small_name_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/strings/string_view.h\"\n\n// This test by itself does not do anything fancy, but it serves as binary I can\n// query in shell test.\n\nnamespace {\n\ntemplate <class T>\nvoid DoNotOptimize(const T& var) {\n#ifdef __GNUC__\n  asm volatile(\"\" : \"+m\"(const_cast<T&>(var)));\n#else\n  std::cout << (void*)&var;\n#endif\n}\n\nint very_long_int_variable_name ABSL_INTERNAL_UNIQUE_SMALL_NAME() = 0;\nchar very_long_str_variable_name[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = \"abc\";\n\nTEST(UniqueSmallName, NonAutomaticVar) {\n  EXPECT_EQ(very_long_int_variable_name, 0);\n  EXPECT_EQ(absl::string_view(very_long_str_variable_name), \"abc\");\n}\n\nint VeryLongFreeFunctionName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();\n\nTEST(UniqueSmallName, FreeFunction) {\n  DoNotOptimize(&VeryLongFreeFunctionName);\n\n  EXPECT_EQ(VeryLongFreeFunctionName(), 456);\n}\n\nint VeryLongFreeFunctionName() { return 456; }\n\nstruct VeryLongStructName {\n  explicit VeryLongStructName(int i);\n\n  int VeryLongMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();\n\n  static int VeryLongStaticMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();\n\n private:\n  int fld;\n};\n\nTEST(UniqueSmallName, Struct) {\n  VeryLongStructName var(10);\n\n  DoNotOptimize(var);\n  DoNotOptimize(&VeryLongStructName::VeryLongMethodName);\n  DoNotOptimize(&VeryLongStructName::VeryLongStaticMethodName);\n\n  EXPECT_EQ(var.VeryLongMethodName(), 10);\n  EXPECT_EQ(VeryLongStructName::VeryLongStaticMethodName(), 123);\n}\n\nVeryLongStructName::VeryLongStructName(int i) : fld(i) {}\nint VeryLongStructName::VeryLongMethodName() { return fld; }\nint VeryLongStructName::VeryLongStaticMethodName() { return 123; }\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/internal/unscaledcycleclock.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/internal/unscaledcycleclock.h\"\n\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n\n#if defined(_WIN32)\n#include <intrin.h>\n#endif\n\n#if defined(__powerpc__) || defined(__ppc__)\n#ifdef __GLIBC__\n#include <sys/platform/ppc.h>\n#elif defined(__FreeBSD__)\n// clang-format off\n// This order does actually matter =(.\n#include <sys/types.h>\n#include <sys/sysctl.h>\n// clang-format on\n\n#include \"absl/base/call_once.h\"\n#endif\n#endif\n\n#include \"absl/base/internal/sysinfo.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n#if defined(__i386__)\n\nint64_t UnscaledCycleClock::Now() {\n  int64_t ret;\n  __asm__ volatile(\"rdtsc\" : \"=A\"(ret));\n  return ret;\n}\n\ndouble UnscaledCycleClock::Frequency() {\n  return base_internal::NominalCPUFrequency();\n}\n\n#elif defined(__x86_64__)\n\ndouble UnscaledCycleClock::Frequency() {\n  return base_internal::NominalCPUFrequency();\n}\n\n#elif defined(__powerpc__) || defined(__ppc__)\n\nint64_t UnscaledCycleClock::Now() {\n#ifdef __GLIBC__\n  return static_cast<int64_t>(__ppc_get_timebase());\n#else\n#ifdef __powerpc64__\n  int64_t tbr;\n  asm volatile(\"mfspr %0, 268\" : \"=r\"(tbr));\n  return tbr;\n#else\n  int32_t tbu, tbl, tmp;\n  asm volatile(\n      \"mftbu %[hi32]\\n\"\n      \"mftb %[lo32]\\n\"\n      \"mftbu %[tmp]\\n\"\n      \"cmpw %[tmp],%[hi32]\\n\"\n      \"bne $-16\\n\"  // Retry on failure.\n      : [hi32] \"=r\"(tbu), [lo32] \"=r\"(tbl), [tmp] \"=r\"(tmp));\n  return (static_cast<int64_t>(tbu) << 32) | tbl;\n#endif\n#endif\n}\n\ndouble UnscaledCycleClock::Frequency() {\n#ifdef __GLIBC__\n  return __ppc_get_timebase_freq();\n#elif defined(__linux__)\n  // Fallback for musl + ppc64le: use constant timebase frequency (512 MHz)\n  // Must come after __GLIBC__.\n  return static_cast<double>(512000000);\n#elif defined(_AIX)\n  // This is the same constant value as returned by\n  // __ppc_get_timebase_freq().\n  return static_cast<double>(512000000);\n#elif defined(__FreeBSD__)\n  static once_flag init_timebase_frequency_once;\n  static double timebase_frequency = 0.0;\n  base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() {\n    size_t length = sizeof(timebase_frequency);\n    sysctlbyname(\"kern.timecounter.tc.timebase.frequency\", &timebase_frequency,\n                 &length, nullptr, 0);\n  });\n  return timebase_frequency;\n#else\n#error Must implement UnscaledCycleClock::Frequency()\n#endif\n}\n\n#elif defined(__aarch64__)\n\ndouble UnscaledCycleClock::Frequency() {\n  uint64_t aarch64_timer_frequency;\n  asm volatile(\"mrs %0, cntfrq_el0\" : \"=r\"(aarch64_timer_frequency));\n  return aarch64_timer_frequency;\n}\n\n#elif defined(_M_IX86) || defined(_M_X64)\n\n#pragma intrinsic(__rdtsc)\n\nint64_t UnscaledCycleClock::Now() { return __rdtsc(); }\n\ndouble UnscaledCycleClock::Frequency() {\n  return base_internal::NominalCPUFrequency();\n}\n\n#endif\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_USE_UNSCALED_CYCLECLOCK\n"
  },
  {
    "path": "absl/base/internal/unscaledcycleclock.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// UnscaledCycleClock\n//    An UnscaledCycleClock yields the value and frequency of a cycle counter\n//    that increments at a rate that is approximately constant.\n//    This class is for internal use only, you should consider using CycleClock\n//    instead.\n//\n// Notes:\n// The cycle counter frequency is not necessarily the core clock frequency.\n// That is, CycleCounter cycles are not necessarily \"CPU cycles\".\n//\n// An arbitrary offset may have been added to the counter at power on.\n//\n// On some platforms, the rate and offset of the counter may differ\n// slightly when read from different CPUs of a multiprocessor.  Usually,\n// we try to ensure that the operating system adjusts values periodically\n// so that values agree approximately.   If you need stronger guarantees,\n// consider using alternate interfaces.\n//\n// The CPU is not required to maintain the ordering of a cycle counter read\n// with respect to surrounding instructions.\n\n#ifndef ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_\n#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_\n\n#include <cstdint>\n\n#if defined(__APPLE__)\n#include <TargetConditionals.h>\n#endif\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/unscaledcycleclock_config.h\"\n\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nclass UnscaledCycleClockWrapperForGetCurrentTime;\n}  // namespace time_internal\n\nnamespace base_internal {\nclass CycleClock;\nclass UnscaledCycleClockWrapperForInitializeFrequency;\n\nclass UnscaledCycleClock {\n private:\n  UnscaledCycleClock() = delete;\n\n  // Return the value of a cycle counter that counts at a rate that is\n  // approximately constant.\n  static int64_t Now();\n\n  // Return the how much UnscaledCycleClock::Now() increases per second.\n  // This is not necessarily the core CPU clock frequency.\n  // It may be the nominal value report by the kernel, rather than a measured\n  // value.\n  static double Frequency();\n\n  // Allowed users\n  friend class base_internal::CycleClock;\n  friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;\n  friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;\n};\n\n#if defined(__x86_64__)\n\ninline int64_t UnscaledCycleClock::Now() {\n  uint64_t low, high;\n  __asm__ volatile(\"rdtsc\" : \"=a\"(low), \"=d\"(high));\n  return static_cast<int64_t>((high << 32) | low);\n}\n\n#elif defined(__aarch64__)\n\n// System timer of ARMv8 runs at a different frequency than the CPU's.\n//\n// Frequency is fixed. From Armv8.6-A and Armv9.1-A on, the frequency is 1GHz.\n// Pre-Armv8.6-A, the frequency was a system design choice, typically in the\n// range of 1MHz to 50MHz. See also:\n// https://developer.arm.com/documentation/102379/0101/What-is-the-Generic-Timer-\n//\n// It can be read at CNTFRQ special register.  We assume the OS has set up the\n// virtual timer properly.\ninline int64_t UnscaledCycleClock::Now() {\n  int64_t virtual_timer_value;\n  asm volatile(\"mrs %0, cntvct_el0\" : \"=r\"(virtual_timer_value));\n  return virtual_timer_value;\n}\n\n#endif\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_USE_UNSCALED_CYCLECLOCK\n\n#endif  // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_\n"
  },
  {
    "path": "absl/base/internal/unscaledcycleclock_config.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_\n#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_\n\n#if defined(__APPLE__)\n#include <TargetConditionals.h>\n#endif\n\n// The following platforms have an implementation of a hardware counter.\n#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \\\n    defined(__powerpc__) || defined(__ppc__) || defined(_M_IX86) ||     \\\n    (defined(_M_X64) && !defined(_M_ARM64EC))\n#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1\n#else\n#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0\n#endif\n\n// The following platforms often disable access to the hardware\n// counter (through a sandbox) even if the underlying hardware has a\n// usable counter. The CycleTimer interface also requires a *scaled*\n// CycleClock that runs at atleast 1 MHz. We've found some Android\n// ARM64 devices where this is not the case, so we disable it by\n// default on Android ARM64.\n#if defined(__APPLE__) || \\\n    (defined(__ANDROID__) && defined(__aarch64__))\n#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0\n#else\n#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1\n#endif\n\n// UnscaledCycleClock is an optional internal feature.\n// Use \"#if ABSL_USE_UNSCALED_CYCLECLOCK\" to test for its presence.\n// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1\n#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)\n#define ABSL_USE_UNSCALED_CYCLECLOCK               \\\n  (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \\\n   ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)\n#endif\n\n#if ABSL_USE_UNSCALED_CYCLECLOCK\n// This macro can be used to test if UnscaledCycleClock::Frequency()\n// is NominalCPUFrequency() on a particular platform.\n#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \\\n     defined(_M_X64))\n#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY\n#endif\n#endif\n\n#endif  // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_\n"
  },
  {
    "path": "absl/base/log_severity.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/log_severity.h\"\n\n#include <ostream>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nstd::ostream& operator<<(std::ostream& os, absl::LogSeverity s) {\n  if (s == absl::NormalizeLogSeverity(s)) return os << absl::LogSeverityName(s);\n  return os << \"absl::LogSeverity(\" << static_cast<int>(s) << \")\";\n}\n\nstd::ostream& operator<<(std::ostream& os, absl::LogSeverityAtLeast s) {\n  switch (s) {\n    case absl::LogSeverityAtLeast::kInfo:\n    case absl::LogSeverityAtLeast::kWarning:\n    case absl::LogSeverityAtLeast::kError:\n    case absl::LogSeverityAtLeast::kFatal:\n      return os << \">=\" << static_cast<absl::LogSeverity>(s);\n    case absl::LogSeverityAtLeast::kInfinity:\n      return os << \"INFINITY\";\n  }\n  return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, absl::LogSeverityAtMost s) {\n  switch (s) {\n    case absl::LogSeverityAtMost::kInfo:\n    case absl::LogSeverityAtMost::kWarning:\n    case absl::LogSeverityAtMost::kError:\n    case absl::LogSeverityAtMost::kFatal:\n      return os << \"<=\" << static_cast<absl::LogSeverity>(s);\n    case absl::LogSeverityAtMost::kNegativeInfinity:\n      return os << \"NEGATIVE_INFINITY\";\n  }\n  return os;\n}\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/log_severity.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_LOG_SEVERITY_H_\n#define ABSL_BASE_LOG_SEVERITY_H_\n\n#include <array>\n#include <ostream>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::LogSeverity\n//\n// Four severity levels are defined. Logging APIs should terminate the program\n// when a message is logged at severity `kFatal`; the other levels have no\n// special semantics.\n//\n// Values other than the four defined levels (e.g. produced by `static_cast`)\n// are valid, but their semantics when passed to a function, macro, or flag\n// depend on the function, macro, or flag. The usual behavior is to normalize\n// such values to a defined severity level, however in some cases values other\n// than the defined levels are useful for comparison.\n//\n// Example:\n//\n//   // Effectively disables all logging:\n//   SetMinLogLevel(static_cast<absl::LogSeverity>(100));\n//\n// Abseil flags may be defined with type `LogSeverity`. Dependency layering\n// constraints require that the `AbslParseFlag()` overload be declared and\n// defined in the flags library itself rather than here. The `AbslUnparseFlag()`\n// overload is defined there as well for consistency.\n//\n// absl::LogSeverity Flag String Representation\n//\n// An `absl::LogSeverity` has a string representation used for parsing\n// command-line flags based on the enumerator name (e.g. `kFatal`) or\n// its unprefixed name (without the `k`) in any case-insensitive form. (E.g.\n// \"FATAL\", \"fatal\" or \"Fatal\" are all valid.) Unparsing such flags produces an\n// unprefixed string representation in all caps (e.g. \"FATAL\") or an integer.\n//\n// Additionally, the parser accepts arbitrary integers (as if the type were\n// `int`).\n//\n// Examples:\n//\n//   --my_log_level=kInfo\n//   --my_log_level=INFO\n//   --my_log_level=info\n//   --my_log_level=0\n//\n// `DFATAL` and `kLogDebugFatal` are similarly accepted.\n//\n// Unparsing a flag produces the same result as `absl::LogSeverityName()` for\n// the standard levels and a base-ten integer otherwise.\nenum class LogSeverity : int {\n  kInfo = 0,\n  kWarning = 1,\n  kError = 2,\n  kFatal = 3,\n};\n\n// LogSeverities()\n//\n// Returns an iterable of all standard `absl::LogSeverity` values, ordered from\n// least to most severe.\nconstexpr std::array<absl::LogSeverity, 4> LogSeverities() {\n  return {{absl::LogSeverity::kInfo, absl::LogSeverity::kWarning,\n           absl::LogSeverity::kError, absl::LogSeverity::kFatal}};\n}\n\n// `absl::kLogDebugFatal` equals `absl::LogSeverity::kFatal` in debug builds\n// (i.e. when `NDEBUG` is not defined) and `absl::LogSeverity::kError`\n// otherwise.  Avoid ODR-using this variable as it has internal linkage and thus\n// distinct storage in different TUs.\n#ifdef NDEBUG\nstatic constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kError;\n#else\nstatic constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kFatal;\n#endif\n\n// LogSeverityName()\n//\n// Returns the all-caps string representation (e.g. \"INFO\") of the specified\n// severity level if it is one of the standard levels and \"UNKNOWN\" otherwise.\nconstexpr const char* LogSeverityName(absl::LogSeverity s) {\n  switch (s) {\n    case absl::LogSeverity::kInfo: return \"INFO\";\n    case absl::LogSeverity::kWarning: return \"WARNING\";\n    case absl::LogSeverity::kError: return \"ERROR\";\n    case absl::LogSeverity::kFatal: return \"FATAL\";\n  }\n  return \"UNKNOWN\";\n}\n\n// NormalizeLogSeverity()\n//\n// Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal`\n// normalize to `kError` (**NOT** `kFatal`).\nconstexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {\n  absl::LogSeverity n = s;\n  if (n < absl::LogSeverity::kInfo) n = absl::LogSeverity::kInfo;\n  if (n > absl::LogSeverity::kFatal) n = absl::LogSeverity::kError;\n  return n;\n}\nconstexpr absl::LogSeverity NormalizeLogSeverity(int s) {\n  return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));\n}\n\n// operator<<\n//\n// The exact representation of a streamed `absl::LogSeverity` is deliberately\n// unspecified; do not rely on it.\nstd::ostream& operator<<(std::ostream& os, absl::LogSeverity s);\n\n// Enums representing a lower bound for LogSeverity. APIs that only operate on\n// messages of at least a certain level (for example, `SetMinLogLevel()`) use\n// this type to specify that level. absl::LogSeverityAtLeast::kInfinity is\n// a level above all threshold levels and therefore no log message will\n// ever meet this threshold.\nenum class LogSeverityAtLeast : int {\n  kInfo = static_cast<int>(absl::LogSeverity::kInfo),\n  kWarning = static_cast<int>(absl::LogSeverity::kWarning),\n  kError = static_cast<int>(absl::LogSeverity::kError),\n  kFatal = static_cast<int>(absl::LogSeverity::kFatal),\n  kInfinity = 1000,\n};\n\nstd::ostream& operator<<(std::ostream& os, absl::LogSeverityAtLeast s);\n\n// Enums representing an upper bound for LogSeverity. APIs that only operate on\n// messages of at most a certain level (for example, buffer all messages at or\n// below a certain level) use this type to specify that level.\n// absl::LogSeverityAtMost::kNegativeInfinity is a level below all threshold\n// levels and therefore will exclude all log messages.\nenum class LogSeverityAtMost : int {\n  kNegativeInfinity = -1000,\n  kInfo = static_cast<int>(absl::LogSeverity::kInfo),\n  kWarning = static_cast<int>(absl::LogSeverity::kWarning),\n  kError = static_cast<int>(absl::LogSeverity::kError),\n  kFatal = static_cast<int>(absl::LogSeverity::kFatal),\n};\n\nstd::ostream& operator<<(std::ostream& os, absl::LogSeverityAtMost s);\n\n#define COMPOP(op1, op2, T)                                         \\\n  constexpr bool operator op1(absl::T lhs, absl::LogSeverity rhs) { \\\n    return static_cast<absl::LogSeverity>(lhs) op1 rhs;             \\\n  }                                                                 \\\n  constexpr bool operator op2(absl::LogSeverity lhs, absl::T rhs) { \\\n    return lhs op2 static_cast<absl::LogSeverity>(rhs);             \\\n  }\n\n// Comparisons between `LogSeverity` and `LogSeverityAtLeast`/\n// `LogSeverityAtMost` are only supported in one direction.\n// Valid checks are:\n//   LogSeverity >= LogSeverityAtLeast\n//   LogSeverity < LogSeverityAtLeast\n//   LogSeverity <= LogSeverityAtMost\n//   LogSeverity > LogSeverityAtMost\nCOMPOP(>, <, LogSeverityAtLeast)\nCOMPOP(<=, >=, LogSeverityAtLeast)\nCOMPOP(<, >, LogSeverityAtMost)\nCOMPOP(>=, <=, LogSeverityAtMost)\n#undef COMPOP\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_LOG_SEVERITY_H_\n"
  },
  {
    "path": "absl/base/log_severity_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/log_severity.h\"\n\n#include <cstdint>\n#include <ios>\n#include <limits>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <tuple>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/flags/internal/flag.h\"\n#include \"absl/flags/marshalling.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\nusing ::testing::Eq;\nusing ::testing::IsFalse;\nusing ::testing::IsTrue;\nusing ::testing::TestWithParam;\nusing ::testing::Values;\n\ntemplate <typename T>\nstd::string StreamHelper(T value) {\n  std::ostringstream stream;\n  stream << value;\n  return stream.str();\n}\n\nTEST(StreamTest, Works) {\n  EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(-100)),\n              Eq(\"absl::LogSeverity(-100)\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverity::kInfo), Eq(\"INFO\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverity::kWarning), Eq(\"WARNING\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverity::kError), Eq(\"ERROR\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverity::kFatal), Eq(\"FATAL\"));\n  EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(4)),\n              Eq(\"absl::LogSeverity(4)\"));\n}\n\nstatic_assert(absl::flags_internal::FlagUseValueAndInitBitStorage<\n                  absl::LogSeverity>::value,\n              \"Flags of type absl::LogSeverity ought to be lock-free.\");\n\nusing ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>;\nINSTANTIATE_TEST_SUITE_P(\n    Instantiation, ParseFlagFromOutOfRangeIntegerTest,\n    Values(static_cast<int64_t>(std::numeric_limits<int>::min()) - 1,\n           static_cast<int64_t>(std::numeric_limits<int>::max()) + 1));\nTEST_P(ParseFlagFromOutOfRangeIntegerTest, ReturnsError) {\n  const std::string to_parse = absl::StrCat(GetParam());\n  absl::LogSeverity value;\n  std::string error;\n  EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value;\n}\n\nusing ParseFlagFromAlmostOutOfRangeIntegerTest = TestWithParam<int>;\nINSTANTIATE_TEST_SUITE_P(Instantiation,\n                         ParseFlagFromAlmostOutOfRangeIntegerTest,\n                         Values(std::numeric_limits<int>::min(),\n                                std::numeric_limits<int>::max()));\nTEST_P(ParseFlagFromAlmostOutOfRangeIntegerTest, YieldsExpectedValue) {\n  const auto expected = static_cast<absl::LogSeverity>(GetParam());\n  const std::string to_parse = absl::StrCat(GetParam());\n  absl::LogSeverity value;\n  std::string error;\n  ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;\n  EXPECT_THAT(value, Eq(expected));\n}\n\nusing ParseFlagFromIntegerMatchingEnumeratorTest =\n    TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>;\nINSTANTIATE_TEST_SUITE_P(\n    Instantiation, ParseFlagFromIntegerMatchingEnumeratorTest,\n    Values(std::make_tuple(\"0\", absl::LogSeverity::kInfo),\n           std::make_tuple(\" 0\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"-0\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"+0\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"00\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"0 \", absl::LogSeverity::kInfo),\n           std::make_tuple(\"0x0\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"1\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"+1\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"2\", absl::LogSeverity::kError),\n           std::make_tuple(\"3\", absl::LogSeverity::kFatal)));\nTEST_P(ParseFlagFromIntegerMatchingEnumeratorTest, YieldsExpectedValue) {\n  const absl::string_view to_parse = std::get<0>(GetParam());\n  const absl::LogSeverity expected = std::get<1>(GetParam());\n  absl::LogSeverity value;\n  std::string error;\n  ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;\n  EXPECT_THAT(value, Eq(expected));\n}\n\nusing ParseFlagFromOtherIntegerTest =\n    TestWithParam<std::tuple<absl::string_view, int>>;\nINSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromOtherIntegerTest,\n                         Values(std::make_tuple(\"-1\", -1),\n                                std::make_tuple(\"4\", 4),\n                                std::make_tuple(\"010\", 10),\n                                std::make_tuple(\"0x10\", 16)));\nTEST_P(ParseFlagFromOtherIntegerTest, YieldsExpectedValue) {\n  const absl::string_view to_parse = std::get<0>(GetParam());\n  const auto expected = static_cast<absl::LogSeverity>(std::get<1>(GetParam()));\n  absl::LogSeverity value;\n  std::string error;\n  ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;\n  EXPECT_THAT(value, Eq(expected));\n}\n\nusing ParseFlagFromEnumeratorTest =\n    TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>;\nINSTANTIATE_TEST_SUITE_P(\n    Instantiation, ParseFlagFromEnumeratorTest,\n    Values(std::make_tuple(\"INFO\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"info\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"kInfo\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"iNfO\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"kInFo\", absl::LogSeverity::kInfo),\n           std::make_tuple(\"WARNING\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"warning\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"kWarning\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"WaRnInG\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"KwArNiNg\", absl::LogSeverity::kWarning),\n           std::make_tuple(\"ERROR\", absl::LogSeverity::kError),\n           std::make_tuple(\"error\", absl::LogSeverity::kError),\n           std::make_tuple(\"kError\", absl::LogSeverity::kError),\n           std::make_tuple(\"eRrOr\", absl::LogSeverity::kError),\n           std::make_tuple(\"kErRoR\", absl::LogSeverity::kError),\n           std::make_tuple(\"FATAL\", absl::LogSeverity::kFatal),\n           std::make_tuple(\"fatal\", absl::LogSeverity::kFatal),\n           std::make_tuple(\"kFatal\", absl::LogSeverity::kFatal),\n           std::make_tuple(\"FaTaL\", absl::LogSeverity::kFatal),\n           std::make_tuple(\"KfAtAl\", absl::LogSeverity::kFatal),\n           std::make_tuple(\"DFATAL\", absl::kLogDebugFatal),\n           std::make_tuple(\"dfatal\", absl::kLogDebugFatal),\n           std::make_tuple(\"kLogDebugFatal\", absl::kLogDebugFatal),\n           std::make_tuple(\"dFaTaL\", absl::kLogDebugFatal),\n           std::make_tuple(\"kLoGdEbUgFaTaL\", absl::kLogDebugFatal)));\nTEST_P(ParseFlagFromEnumeratorTest, YieldsExpectedValue) {\n  const absl::string_view to_parse = std::get<0>(GetParam());\n  const absl::LogSeverity expected = std::get<1>(GetParam());\n  absl::LogSeverity value;\n  std::string error;\n  ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;\n  EXPECT_THAT(value, Eq(expected));\n}\n\nusing ParseFlagFromGarbageTest = TestWithParam<absl::string_view>;\nINSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromGarbageTest,\n                         Values(\"\", \"\\0\", \" \", \"garbage\", \"kkinfo\", \"I\",\n                                \"kDFATAL\", \"LogDebugFatal\", \"lOgDeBuGfAtAl\"));\nTEST_P(ParseFlagFromGarbageTest, ReturnsError) {\n  const absl::string_view to_parse = GetParam();\n  absl::LogSeverity value;\n  std::string error;\n  EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value;\n}\n\nusing UnparseFlagToEnumeratorTest =\n    TestWithParam<std::tuple<absl::LogSeverity, absl::string_view>>;\nINSTANTIATE_TEST_SUITE_P(\n    Instantiation, UnparseFlagToEnumeratorTest,\n    Values(std::make_tuple(absl::LogSeverity::kInfo, \"INFO\"),\n           std::make_tuple(absl::LogSeverity::kWarning, \"WARNING\"),\n           std::make_tuple(absl::LogSeverity::kError, \"ERROR\"),\n           std::make_tuple(absl::LogSeverity::kFatal, \"FATAL\")));\nTEST_P(UnparseFlagToEnumeratorTest, ReturnsExpectedValueAndRoundTrips) {\n  const absl::LogSeverity to_unparse = std::get<0>(GetParam());\n  const absl::string_view expected = std::get<1>(GetParam());\n  const std::string stringified_value = absl::UnparseFlag(to_unparse);\n  EXPECT_THAT(stringified_value, Eq(expected));\n  absl::LogSeverity reparsed_value;\n  std::string error;\n  EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error),\n              IsTrue());\n  EXPECT_THAT(reparsed_value, Eq(to_unparse));\n}\n\nusing UnparseFlagToOtherIntegerTest = TestWithParam<int>;\nINSTANTIATE_TEST_SUITE_P(Instantiation, UnparseFlagToOtherIntegerTest,\n                         Values(std::numeric_limits<int>::min(), -1, 4,\n                                std::numeric_limits<int>::max()));\nTEST_P(UnparseFlagToOtherIntegerTest, ReturnsExpectedValueAndRoundTrips) {\n  const absl::LogSeverity to_unparse =\n      static_cast<absl::LogSeverity>(GetParam());\n  const std::string expected = absl::StrCat(GetParam());\n  const std::string stringified_value = absl::UnparseFlag(to_unparse);\n  EXPECT_THAT(stringified_value, Eq(expected));\n  absl::LogSeverity reparsed_value;\n  std::string error;\n  EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error),\n              IsTrue());\n  EXPECT_THAT(reparsed_value, Eq(to_unparse));\n}\n\nTEST(LogThresholdTest, LogSeverityAtLeastTest) {\n  EXPECT_LT(absl::LogSeverity::kError, absl::LogSeverityAtLeast::kFatal);\n  EXPECT_GT(absl::LogSeverityAtLeast::kError, absl::LogSeverity::kInfo);\n\n  EXPECT_LE(absl::LogSeverityAtLeast::kInfo, absl::LogSeverity::kError);\n  EXPECT_GE(absl::LogSeverity::kError, absl::LogSeverityAtLeast::kInfo);\n}\n\nTEST(LogThresholdTest, LogSeverityAtMostTest) {\n  EXPECT_GT(absl::LogSeverity::kError, absl::LogSeverityAtMost::kWarning);\n  EXPECT_LT(absl::LogSeverityAtMost::kError, absl::LogSeverity::kFatal);\n\n  EXPECT_GE(absl::LogSeverityAtMost::kFatal, absl::LogSeverity::kError);\n  EXPECT_LE(absl::LogSeverity::kWarning, absl::LogSeverityAtMost::kError);\n}\n\nTEST(LogThresholdTest, Extremes) {\n  EXPECT_LT(absl::LogSeverity::kFatal, absl::LogSeverityAtLeast::kInfinity);\n  EXPECT_GT(absl::LogSeverity::kInfo,\n            absl::LogSeverityAtMost::kNegativeInfinity);\n}\n\nTEST(LogThresholdTest, Output) {\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kInfo), Eq(\">=INFO\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kWarning),\n              Eq(\">=WARNING\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kError), Eq(\">=ERROR\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kFatal), Eq(\">=FATAL\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kInfinity),\n              Eq(\"INFINITY\"));\n\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kInfo), Eq(\"<=INFO\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kWarning), Eq(\"<=WARNING\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kError), Eq(\"<=ERROR\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kFatal), Eq(\"<=FATAL\"));\n  EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kNegativeInfinity),\n              Eq(\"NEGATIVE_INFINITY\"));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/macros.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: macros.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the set of language macros used within Abseil code.\n// For the set of macros used to determine supported compilers and platforms,\n// see absl/base/config.h instead.\n//\n// This code is compiled directly on many platforms, including client\n// platforms like Windows, Mac, and embedded systems.  Before making\n// any changes here, make sure that you're not breaking any platforms.\n\n#ifndef ABSL_BASE_MACROS_H_\n#define ABSL_BASE_MACROS_H_\n\n#include <cassert>\n#include <cstddef>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/options.h\"\n#include \"absl/base/port.h\"\n\n// ABSL_ARRAYSIZE()\n//\n// Returns the number of elements in an array as a compile-time constant, which\n// can be used in defining new arrays. If you use this macro on a pointer by\n// mistake, you will get a compile-time error.\n#define ABSL_ARRAYSIZE(array) \\\n  (sizeof(::absl::macros_internal::ArraySizeHelper(array)))\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace macros_internal {\n// Note: this internal template function declaration is used by ABSL_ARRAYSIZE.\n// The function doesn't need a definition, as we only use its type.\ntemplate <typename T, size_t N>\nauto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];\n}  // namespace macros_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// ABSL_BAD_CALL_IF()\n//\n// Used on a function overload to trap bad calls: any call that matches the\n// overload will cause a compile-time error. This macro uses a clang-specific\n// \"enable_if\" attribute, as described at\n// https://clang.llvm.org/docs/AttributeReference.html#enable-if\n//\n// Overloads which use this macro should be bracketed by\n// `#ifdef ABSL_BAD_CALL_IF`.\n//\n// Example:\n//\n//   int isdigit(int c);\n//   #ifdef ABSL_BAD_CALL_IF\n//   int isdigit(int c)\n//     ABSL_BAD_CALL_IF(c <= -1 || c > 255,\n//                       \"'c' must have the value of an unsigned char or EOF\");\n//   #endif // ABSL_BAD_CALL_IF\n#if ABSL_HAVE_ATTRIBUTE(enable_if)\n#define ABSL_BAD_CALL_IF(expr, msg) \\\n  __attribute__((enable_if(expr, \"Bad call trap\"), unavailable(msg)))\n#endif\n\n// ABSL_ASSERT()\n//\n// In C++11, `assert` can't be used portably within constexpr functions.\n// `assert` also generates spurious unused-symbol warnings.\n// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr\n// functions, and maintains references to symbols.  Example:\n//\n// constexpr double Divide(double a, double b) {\n//   return ABSL_ASSERT(b != 0), a / b;\n// }\n//\n// This macro is inspired by\n// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/\n#if defined(NDEBUG)\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n// We use `decltype` here to avoid generating unnecessary code that the\n// optimizer then has to optimize away.\n// This not only improves compilation performance by reducing codegen bloat\n// and optimization work, but also guarantees fast run-time performance without\n// having to rely on the optimizer.\n#define ABSL_ASSERT(expr) (decltype((expr) ? void() : void())())\n#else\n// Pre-C++20, lambdas can't be inside unevaluated operands, so we're forced to\n// rely on the optimizer.\n#define ABSL_ASSERT(expr) (false ? ((expr) ? void() : void()) : void())\n#endif\n#else\n#define ABSL_ASSERT(expr)                           \\\n  (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \\\n                             : [] { assert(false && #expr); }())  // NOLINT\n#endif\n\n// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()`\n// aborts the program in release mode (when NDEBUG is defined). The\n// implementation should abort the program as quickly as possible and ideally it\n// should not be possible to ignore the abort request.\n#define ABSL_INTERNAL_HARDENING_ABORT()   \\\n  do {                                    \\\n    ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \\\n    ABSL_INTERNAL_UNREACHABLE_IMPL();     \\\n  } while (false)\n\n// ABSL_HARDENING_ASSERT()\n//\n// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement\n// runtime assertions that should be enabled in hardened builds even when\n// `NDEBUG` is defined.\n//\n// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to\n// `ABSL_ASSERT()`.\n//\n// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on\n// hardened mode.\n#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)\n#define ABSL_HARDENING_ASSERT(expr)                 \\\n  (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \\\n                             : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())\n#else\n#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)\n#endif\n\n// ABSL_HARDENING_ASSERT_SLOW()\n//\n// `ABSL_HARDENING_ASSERT()` is like `ABSL_HARDENING_ASSERT()`,\n//  but specifically for assertions whose predicates are too slow\n//  to be enabled in many applications.\n//\n// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT_SLOW()` is identical to\n// `ABSL_ASSERT()`.\n//\n// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on\n// hardened mode.\n#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)\n#define ABSL_HARDENING_ASSERT_SLOW(expr)            \\\n  (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \\\n                             : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())\n#else\n#define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr)\n#endif\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n#define ABSL_INTERNAL_TRY try\n#define ABSL_INTERNAL_CATCH_ANY catch (...)\n#define ABSL_INTERNAL_RETHROW do { throw; } while (false)\n#else  // ABSL_HAVE_EXCEPTIONS\n#define ABSL_INTERNAL_TRY if (true)\n#define ABSL_INTERNAL_CATCH_ANY else if (false)\n#define ABSL_INTERNAL_RETHROW do {} while (false)\n#endif  // ABSL_HAVE_EXCEPTIONS\n\n// ABSL_REFACTOR_INLINE\n//\n// Marks a function or type for automated refactoring by go/cpp-inliner. It can\n// be used on inline function definitions or type aliases in header files and\n// should be combined with the `[[deprecated]]` attribute.\n//\n// Using `ABSL_REFACTOR_INLINE` differs from using the `[[deprecated]]` alone in\n// the following ways:\n//\n// 1. New uses of the function or type will be discouraged via Tricorder\n//    warnings.\n// 2. If enabled via `METADATA`, automated changes will be sent out inlining the\n//    functions's body or replacing the type where it is used.\n//\n// Examples:\n//\n// [[deprecated(\"Use NewFunc() instead\")]] ABSL_REFACTOR_INLINE\n// inline int OldFunc(int x) {\n//   return NewFunc(x, 0);\n// }\n//\n// using OldType [[deprecated(\"Use NewType instead\")]] ABSL_REFACTOR_INLINE =\n//     NewType;\n//\n// will mark `OldFunc` and `OldType` as deprecated, and the go/cpp-inliner\n// service will replace calls to `OldFunc(x)` with calls to `NewFunc(x, 0)` and\n// `OldType` with `NewType`. Once all replacements have been completed, the old\n// function or type can be deleted.\n//\n// See go/cpp-inliner for more information.\n//\n// Note: go/cpp-inliner is Google-internal service for automated refactoring.\n// While open-source users do not have access to this service, the macro is\n// provided for compatibility.\n#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)\n#define ABSL_REFACTOR_INLINE [[clang::annotate(\"inline-me\")]]\n#else\n#define ABSL_REFACTOR_INLINE\n#endif\n\n// ABSL_DEPRECATE_AND_INLINE()\n//\n// This is the original macro used by go/cpp-inliner that combines\n// [[deprecated]] and ABSL_REFACTOR_INLINE.\n//\n// Examples:\n//\n// ABSL_DEPRECATE_AND_INLINE() inline int OldFunc(int x) {\n//   return NewFunc(x, 0);\n// }\n//\n// using OldType ABSL_DEPRECATE_AND_INLINE() = NewType;\n//\n// The combination of `[[deprecated(\"Use X instead\")]]` and\n// `ABSL_REFACTOR_INLINE` is preferred because it provides a more informative\n// deprecation message to developers, especially those that do not have access\n// to the automated refactoring capabilities of go/cpp-inliner.\n#define ABSL_DEPRECATE_AND_INLINE() [[deprecated]] ABSL_REFACTOR_INLINE\n\n// Requires the compiler to prove that the size of the given object is at least\n// the expected amount.\n#if ABSL_HAVE_ATTRIBUTE(diagnose_if) && ABSL_HAVE_BUILTIN(__builtin_object_size)\n#define ABSL_INTERNAL_NEED_MIN_SIZE(Obj, N)                     \\\n  __attribute__((diagnose_if(__builtin_object_size(Obj, 0) < N, \\\n                             \"object size provably too small \"  \\\n                             \"(this would corrupt memory)\",     \\\n                             \"error\")))\n#else\n#define ABSL_INTERNAL_NEED_MIN_SIZE(Obj, N)\n#endif\n\n#endif  // ABSL_BASE_MACROS_H_\n"
  },
  {
    "path": "absl/base/no_destructor.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: no_destructor.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the absl::NoDestructor<T> wrapper for defining a\n// static type that does not need to be destructed upon program exit. Instead,\n// such an object survives during program exit (and can be safely accessed at\n// any time).\n//\n// absl::NoDestructor<T> is useful when when a variable has static storage\n// duration but its type has a non-trivial destructor. Global constructors are\n// not recommended because of the C++'s static initialization order fiasco (See\n// https://en.cppreference.com/w/cpp/language/siof). Global destructors are not\n// allowed due to similar concerns about destruction ordering. Using\n// absl::NoDestructor<T> as a function-local static prevents both of these\n// issues.\n//\n// See below for complete details.\n\n\n#ifndef ABSL_BASE_NO_DESTRUCTOR_H_\n#define ABSL_BASE_NO_DESTRUCTOR_H_\n\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::NoDestructor<T>\n//\n// NoDestructor<T> is a wrapper around an object of type T that behaves as an\n// object of type T but never calls T's destructor. NoDestructor<T> makes it\n// safer and/or more efficient to use such objects in static storage contexts,\n// ideally as function scope static variables.\n//\n// An instance of absl::NoDestructor<T> has similar type semantics to an\n// instance of T:\n//\n// * Constructs in the same manner as an object of type T through perfect\n//   forwarding.\n// * Provides pointer/reference semantic access to the object of type T via\n//   `->`, `*`, and `get()`.\n//   (Note that `const NoDestructor<T>` works like a pointer to const `T`.)\n//\n// Additionally, NoDestructor<T> provides the following benefits:\n//\n// * Never calls T's destructor for the object\n// * If the object is a function-local static variable, the type can be\n//   lazily constructed.\n//\n// An object of type NoDestructor<T> is \"trivially destructible\" in the notion\n// that its destructor is never run.\n//\n// Usage as Function Scope Static Variables\n//\n// Function static objects will be lazily initialized within static storage:\n//\n//    // Function scope.\n//    const std::string& MyString() {\n//      static const absl::NoDestructor<std::string> x(\"foo\");\n//      return *x;\n//    }\n//\n// For function static variables, NoDestructor avoids heap allocation and can be\n// inlined in static storage, resulting in exactly-once, thread-safe\n// construction of an object, and very fast access thereafter (the cost is a few\n// extra cycles).\n//\n// Using NoDestructor<T> in this manner is generally better than other patterns\n// which require pointer chasing:\n//\n//   // Prefer using absl::NoDestructor<T> instead for the static variable.\n//   const std::string& MyString() {\n//     static const std::string* x = new std::string(\"foo\");\n//     return *x;\n//   }\n//\n// Usage as Global Static Variables\n//\n// NoDestructor<T> allows declaration of a global object of type T that has a\n// non-trivial destructor since its destructor is never run. However, such\n// objects still need to worry about initialization order, so such use is not\n// recommended, strongly discouraged by the Google C++ Style Guide, and outright\n// banned in Chromium.\n// See https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables\n//\n//    // Global or namespace scope.\n//    absl::NoDestructor<MyRegistry> reg{\"foo\", \"bar\", 8008};\n//\n// Note that if your object already has a trivial destructor, you don't need to\n// use NoDestructor<T>.\n//\ntemplate <typename T>\nclass NoDestructor {\n public:\n  // Forwards arguments to the T's constructor: calls T(args...).\n  template <typename... Ts,\n            // Disable this overload when it might collide with copy/move.\n            typename std::enable_if<!std::is_same<void(std::decay_t<Ts>&...),\n                                                  void(NoDestructor&)>::value,\n                                    int>::type = 0>\n  explicit constexpr NoDestructor(Ts&&... args)\n      : impl_(std::forward<Ts>(args)...) {}\n\n  // Forwards copy and move construction for T. Enables usage like this:\n  //   static NoDestructor<std::array<string, 3>> x{{{\"1\", \"2\", \"3\"}}};\n  //   static NoDestructor<std::vector<int>> x{{1, 2, 3}};\n  explicit constexpr NoDestructor(const T& x) : impl_(x) {}\n  explicit constexpr NoDestructor(T&& x)\n      : impl_(std::move(x)) {}\n\n  // No copying.\n  NoDestructor(const NoDestructor&) = delete;\n  NoDestructor& operator=(const NoDestructor&) = delete;\n\n  // Pretend to be a smart pointer to T with deep constness.\n  // Never returns a null pointer.\n  T& operator*() { return *get(); }\n  T* absl_nonnull operator->() { return get(); }\n  T* absl_nonnull get() { return impl_.get(); }\n  const T& operator*() const { return *get(); }\n  const T* absl_nonnull operator->() const { return get(); }\n  const T* absl_nonnull get() const { return impl_.get(); }\n\n private:\n  class DirectImpl {\n   public:\n    template <typename... Args>\n    explicit constexpr DirectImpl(Args&&... args)\n        : value_(std::forward<Args>(args)...) {}\n    const T* absl_nonnull get() const { return &value_; }\n    T* absl_nonnull get() { return &value_; }\n\n   private:\n    T value_;\n  };\n\n  class PlacementImpl {\n   public:\n    template <typename... Args>\n    explicit PlacementImpl(Args&&... args) {\n      new (&space_) T(std::forward<Args>(args)...);\n    }\n    const T* absl_nonnull get() const {\n      return std::launder(reinterpret_cast<const T*>(&space_));\n    }\n    T* absl_nonnull get() {\n      return std::launder(reinterpret_cast<T*>(&space_));\n    }\n\n   private:\n    alignas(T) unsigned char space_[sizeof(T)];\n  };\n\n  // If the object is trivially destructible we use a member directly to avoid\n  // potential once-init runtime initialization. It somewhat defeats the\n  // purpose of NoDestructor in this case, but this makes the class more\n  // friendly to generic code.\n  std::conditional_t<std::is_trivially_destructible<T>::value, DirectImpl,\n                     PlacementImpl>\n      impl_;\n};\n\n// Provide 'Class Template Argument Deduction': the type of NoDestructor's T\n// will be the same type as the argument passed to NoDestructor's constructor.\ntemplate <typename T>\nNoDestructor(T) -> NoDestructor<T>;\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_NO_DESTRUCTOR_H_\n"
  },
  {
    "path": "absl/base/no_destructor_benchmark.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\n// Number of static-NoDestructor-in-a-function to exercise.\n// This must be low enough not to hit template instantiation limits\n// (happens around 1000).\nconstexpr int kNumObjects = 1;  // set to 512 when doing benchmarks\n                                // 1 is faster to compile: just one templated\n                                // function instantiation\n\n// Size of individual objects to benchmark static-NoDestructor-in-a-function\n// usage with.\nconstexpr int kObjSize = sizeof(void*)*1;\n\n// Simple object of kObjSize bytes (rounded to int).\n// We benchmark complete reading of its state via Verify().\nclass BM_Blob {\n public:\n  BM_Blob(int val) { for (auto& d : data_) d = val; }\n  BM_Blob() : BM_Blob(-1) {}\n  void Verify(int val) const {  // val must be the c-tor argument\n    for (auto& d : data_) ABSL_INTERNAL_CHECK(d == val, \"\");\n  }\n private:\n  int data_[kObjSize / sizeof(int) > 0 ? kObjSize / sizeof(int) : 1];\n};\n\n// static-NoDestructor-in-a-function pattern instances.\n// We'll instantiate kNumObjects of them.\ntemplate<int i>\nconst BM_Blob& NoDestrBlobFunc() {\n  static absl::NoDestructor<BM_Blob> x(i);\n  return *x;\n}\n\n// static-heap-ptr-in-a-function pattern instances\n// We'll instantiate kNumObjects of them.\ntemplate<int i>\nconst BM_Blob& OnHeapBlobFunc() {\n  static BM_Blob* x = new BM_Blob(i);\n  return *x;\n}\n\n// Type for NoDestrBlobFunc or OnHeapBlobFunc.\ntypedef const BM_Blob& (*FuncType)();\n\n// ========================================================================= //\n// Simple benchmarks that read a single BM_Blob over and over, hence\n// all they touch fits into L1 CPU cache:\n\n// Direct non-POD global variable (style guide violation) as a baseline.\nstatic BM_Blob direct_blob(0);\n\nvoid BM_Direct(benchmark::State& state) {\n  for (auto s : state) {\n    direct_blob.Verify(0);\n  }\n}\nBENCHMARK(BM_Direct);\n\nvoid BM_NoDestr(benchmark::State& state) {\n  for (auto s : state) {\n    NoDestrBlobFunc<0>().Verify(0);\n  }\n}\nBENCHMARK(BM_NoDestr);\n\nvoid BM_OnHeap(benchmark::State& state) {\n  for (auto s : state) {\n    OnHeapBlobFunc<0>().Verify(0);\n  }\n}\nBENCHMARK(BM_OnHeap);\n\n// ========================================================================= //\n// Benchmarks that read kNumObjects of BM_Blob over and over, hence with\n// appropriate values of sizeof(BM_Blob) and kNumObjects their working set\n// can exceed a given layer of CPU cache.\n\n// Type of benchmark to select between NoDestrBlobFunc and OnHeapBlobFunc.\nenum BM_Type { kNoDestr, kOnHeap, kDirect };\n\n// BlobFunc<n>(t, i) returns the i-th function of type t.\n// n must be larger than i (we'll use kNumObjects for n).\ntemplate<int n>\nFuncType BlobFunc(BM_Type t, int i) {\n  if (i == n) {\n    switch (t) {\n      case kNoDestr:  return &NoDestrBlobFunc<n>;\n      case kOnHeap:   return &OnHeapBlobFunc<n>;\n      case kDirect:   return nullptr;\n    }\n  }\n  return BlobFunc<n-1>(t, i);\n}\n\ntemplate<>\nFuncType BlobFunc<0>(BM_Type t, int i) {\n  ABSL_INTERNAL_CHECK(i == 0, \"\");\n  switch (t) {\n    case kNoDestr:  return &NoDestrBlobFunc<0>;\n    case kOnHeap:   return &OnHeapBlobFunc<0>;\n    case kDirect:   return nullptr;\n  }\n  return nullptr;\n}\n\n// Direct non-POD global variables (style guide violation) as a baseline.\nstatic BM_Blob direct_blobs[kNumObjects];\n\n// Helper that cheaply maps benchmark iteration to randomish index in\n// [0, kNumObjects).\nint RandIdx(int i) {\n  // int64 is to avoid overflow and generating negative return values:\n  return (static_cast<int64_t>(i) * 13) % kNumObjects;\n}\n\n// Generic benchmark working with kNumObjects for any of the possible BM_Type.\ntemplate <BM_Type t>\nvoid BM_Many(benchmark::State& state) {\n  FuncType funcs[kNumObjects];\n  for (int i = 0; i < kNumObjects; ++i) {\n    funcs[i] = BlobFunc<kNumObjects-1>(t, i);\n  }\n  if (t == kDirect) {\n    for (auto s : state) {\n      int idx = RandIdx(state.iterations());\n      direct_blobs[idx].Verify(-1);\n    }\n  } else {\n    for (auto s : state) {\n      int idx = RandIdx(state.iterations());\n      funcs[idx]().Verify(idx);\n    }\n  }\n}\n\nvoid BM_DirectMany(benchmark::State& state) { BM_Many<kDirect>(state); }\nvoid BM_NoDestrMany(benchmark::State& state) { BM_Many<kNoDestr>(state); }\nvoid BM_OnHeapMany(benchmark::State& state) { BM_Many<kOnHeap>(state); }\n\nBENCHMARK(BM_DirectMany);\nBENCHMARK(BM_NoDestrMany);\nBENCHMARK(BM_OnHeapMany);\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/no_destructor_test.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/no_destructor.h\"\n\n#include <array>\n#include <initializer_list>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace {\n\nstruct Blob {\n  Blob() : val(42) {}\n  Blob(int x, int y) : val(x + y) {}\n  Blob(std::initializer_list<int> xs) {\n    val = 0;\n    for (auto& x : xs) val += x;\n  }\n\n  Blob(const Blob& /*b*/) = delete;\n  Blob(Blob&& b) noexcept : val(b.val) {\n    b.moved_out = true;\n  }  // moving is fine\n\n  // no crash: NoDestructor indeed does not destruct (the moved-out Blob\n  // temporaries do get destroyed though)\n  ~Blob() { ABSL_INTERNAL_CHECK(moved_out, \"~Blob\"); }\n\n  int val;\n  bool moved_out = false;\n};\n\nstruct TypeWithDeletedDestructor {\n  ~TypeWithDeletedDestructor() = delete;\n};\n\nTEST(NoDestructorTest, DestructorNeverCalled) {\n  absl::NoDestructor<TypeWithDeletedDestructor> a;\n  (void)a;\n}\n\nTEST(NoDestructorTest, Noncopyable) {\n  using T = absl::NoDestructor<int>;\n\n  EXPECT_FALSE((std::is_constructible<T, T>::value));\n  EXPECT_FALSE((std::is_constructible<T, const T>::value));\n  EXPECT_FALSE((std::is_constructible<T, T&>::value));\n  EXPECT_FALSE((std::is_constructible<T, const T&>::value));\n\n  EXPECT_FALSE((std::is_assignable<T&, T>::value));\n  EXPECT_FALSE((std::is_assignable<T&, const T>::value));\n  EXPECT_FALSE((std::is_assignable<T&, T&>::value));\n  EXPECT_FALSE((std::is_assignable<T&, const T&>::value));\n}\n\nTEST(NoDestructorTest, Interface) {\n  EXPECT_TRUE(std::is_trivially_destructible<absl::NoDestructor<Blob>>::value);\n  EXPECT_TRUE(\n      std::is_trivially_destructible<absl::NoDestructor<const Blob>>::value);\n  {\n    absl::NoDestructor<Blob> b;  // default c-tor\n    // access: *, ->, get()\n    EXPECT_EQ(42, (*b).val);\n    (*b).val = 55;\n    EXPECT_EQ(55, b->val);\n    b->val = 66;\n    EXPECT_EQ(66, b.get()->val);\n    b.get()->val = 42;  // NOLINT\n    EXPECT_EQ(42, (*b).val);\n  }\n  {\n    absl::NoDestructor<const Blob> b(70, 7);  // regular c-tor, const\n    EXPECT_EQ(77, (*b).val);\n    EXPECT_EQ(77, b->val);\n    EXPECT_EQ(77, b.get()->val);\n  }\n  {\n    const absl::NoDestructor<Blob> b{\n        {20, 28, 40}};  // init-list c-tor, deep const\n    // This only works in clang, not in gcc:\n    // const absl::NoDestructor<Blob> b({20, 28, 40});\n    EXPECT_EQ(88, (*b).val);\n    EXPECT_EQ(88, b->val);\n    EXPECT_EQ(88, b.get()->val);\n  }\n}\n\nTEST(NoDestructorTest, SfinaeRegressionAbstractArg) {\n  struct Abstract {\n    virtual ~Abstract() = default;\n    virtual int foo() const = 0;\n  };\n\n  struct Concrete : Abstract {\n    int foo() const override { return 17; }\n  };\n\n  struct UsesAbstractInConstructor {\n    explicit UsesAbstractInConstructor(const Abstract& abstract)\n        : i(abstract.foo()) {}\n    int i;\n  };\n\n  Concrete input;\n  absl::NoDestructor<UsesAbstractInConstructor> foo1(input);\n  EXPECT_EQ(foo1->i, 17);\n  absl::NoDestructor<UsesAbstractInConstructor> foo2(\n      static_cast<const Abstract&>(input));\n  EXPECT_EQ(foo2->i, 17);\n}\n\n// ========================================================================= //\n\nstd::string* Str0() {\n  static absl::NoDestructor<std::string> x;\n  return x.get();\n}\n\nextern const std::string& Str2();\n\nconst char* Str1() {\n  static absl::NoDestructor<std::string> x(Str2() + \"_Str1\");\n  return x->c_str();\n}\n\nconst std::string& Str2() {\n  static absl::NoDestructor<std::string> x(\"Str2\");\n  return *x;\n}\n\nconst std::string& Str2Copy() {\n  // Exercise copy construction\n  static absl::NoDestructor<std::string> x(Str2());\n  return *x;\n}\n\ntypedef std::array<std::string, 3> MyArray;\nconst MyArray& Array() {\n  static absl::NoDestructor<MyArray> x{{{\"foo\", \"bar\", \"baz\"}}};\n  // This only works in clang, not in gcc:\n  // static absl::NoDestructor<MyArray> x({{\"foo\", \"bar\", \"baz\"}});\n  return *x;\n}\n\ntypedef std::vector<int> MyVector;\nconst MyVector& Vector() {\n  static absl::NoDestructor<MyVector> x{{1, 2, 3}};\n  return *x;\n}\n\nconst int& Int() {\n  static absl::NoDestructor<int> x;\n  return *x;\n}\n\nTEST(NoDestructorTest, StaticPattern) {\n  EXPECT_TRUE(\n      std::is_trivially_destructible<absl::NoDestructor<std::string>>::value);\n  EXPECT_TRUE(\n      std::is_trivially_destructible<absl::NoDestructor<MyArray>>::value);\n  EXPECT_TRUE(\n      std::is_trivially_destructible<absl::NoDestructor<MyVector>>::value);\n  EXPECT_TRUE(std::is_trivially_destructible<absl::NoDestructor<int>>::value);\n\n  EXPECT_EQ(*Str0(), \"\");\n  Str0()->append(\"foo\");\n  EXPECT_EQ(*Str0(), \"foo\");\n\n  EXPECT_EQ(std::string(Str1()), \"Str2_Str1\");\n\n  EXPECT_EQ(Str2(), \"Str2\");\n  EXPECT_EQ(Str2Copy(), \"Str2\");\n\n  EXPECT_THAT(Array(), testing::ElementsAre(\"foo\", \"bar\", \"baz\"));\n\n  EXPECT_THAT(Vector(), testing::ElementsAre(1, 2, 3));\n\n  EXPECT_EQ(0, Int());  // should get zero-initialized\n}\n\nTEST(NoDestructorTest, ClassTemplateArgumentDeduction) {\n  absl::NoDestructor i(1);\n  static_assert(std::is_same<decltype(i), absl::NoDestructor<int>>::value,\n                \"Expected deduced type to be int.\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/nullability.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: nullability.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a set of annotations for designating the expected\n// nullability of pointers. These annotations allow you to designate pointers in\n// one of three classification states:\n//\n//  * \"Non-null\" (for pointers annotated `absl_nonnull`), indicating that it is\n//    invalid for the given pointer to ever be null.\n//  * \"Nullable\" (for pointers annotated `absl_nullable`), indicating that it is\n//    valid for the given pointer to be null.\n//  * \"Unknown\" (for pointers annotated `absl_nullability_unknown`), indicating\n//    that the given pointer has not yet been classified as either nullable or\n//    non-null. This is the default state of unannotated pointers.\n//\n// NOTE: Unannotated pointers implicitly bear the annotation\n// `absl_nullability_unknown`; you should rarely, if ever, see this annotation\n// used in the codebase explicitly.\n//\n// -----------------------------------------------------------------------------\n// Nullability and Contracts\n// -----------------------------------------------------------------------------\n//\n// These nullability annotations allow you to more clearly specify contracts on\n// software components by narrowing the *preconditions*, *postconditions*, and\n// *invariants* of pointer state(s) in any given interface. It then depends on\n// context who is responsible for fulfilling the annotation's requirements.\n//\n// For example, a function may receive a pointer argument. Designating that\n// pointer argument as \"non-null\" tightens the precondition of the contract of\n// that function. It is then the responsibility of anyone calling such a\n// function to ensure that the passed pointer is not null.\n//\n// Similarly, a function may have a pointer as a return value. Designating that\n// return value as \"non-null\" tightens the postcondition of the contract of that\n// function. In this case, however, it is the responsibility of the function\n// itself to ensure that the returned pointer is not null.\n//\n// Clearly defining these contracts allows providers (and consumers) of such\n// pointers to have more confidence in their null state. If a function declares\n// a return value as \"non-null\", for example, the caller should not need to\n// check whether the returned value is `nullptr`; it can simply assume the\n// pointer is valid.\n//\n// Of course most interfaces already have expectations on the nullability state\n// of pointers, and these expectations are, in effect, a contract; often,\n// however, those contracts are either poorly or partially specified, assumed,\n// or misunderstood. These nullability annotations are designed to allow you to\n// formalize those contracts within the codebase.\n//\n// -----------------------------------------------------------------------------\n// Annotation Syntax\n// -----------------------------------------------------------------------------\n//\n// The annotations should be positioned as a qualifier for the pointer type. For\n// example, the position of `const` when declaring a const pointer (not a\n// pointer to a const type) is the position you should also use for these\n// annotations.\n//\n// Example:\n//\n// // A const non-null pointer to an `Employee`.\n// Employee* absl_nonnull const e;\n//\n// // A non-null pointer to a const `Employee`.\n// const Employee* absl_nonnull e;\n//\n// // A non-null pointer to a const nullable pointer to an `Employee`.\n// Employee* absl_nullable const* absl_nonnull e;\n//\n// // A non-null function pointer.\n// void (*absl_nonnull func)(int, double);\n//\n// // A non-null array of `Employee`s as a parameter.\n// void func(Employee employees[absl_nonnull]);\n//\n// // A non-null std::unique_ptr to an `Employee`.\n// // As with `const`, it is possible to place the annotation on either side of\n// // a named type not ending in `*`, but placing it before the type it\n// // describes is preferred, unless inconsistent with surrounding code.\n// absl_nonnull std::unique_ptr<Employee> employee;\n//\n// // Invalid annotation usage – this attempts to declare a pointer to a\n// // nullable `Employee`, which is meaningless.\n// absl_nullable Employee* e;\n//\n// -----------------------------------------------------------------------------\n// Using Nullability Annotations\n// -----------------------------------------------------------------------------\n//\n// Each annotation acts as a form of documentation about the contract for the\n// given pointer. Each annotation requires providers or consumers of these\n// pointers across API boundaries to take appropriate steps when setting or\n// using these pointers:\n//\n// * \"Non-null\" pointers should never be null. It is the responsibility of the\n//   provider of this pointer to ensure that the pointer may never be set to\n//   null. Consumers of such pointers can treat such pointers as non-null.\n// * \"Nullable\" pointers may or may not be null. Consumers of such pointers\n//   should precede any usage of that pointer (e.g. a dereference operation)\n//   with a a `nullptr` check.\n// * \"Unknown\" pointers may be either \"non-null\" or \"nullable\" but have not been\n//   definitively determined to be in either classification state. Providers of\n//   such pointers across API boundaries should determine --  over time -- to\n//   annotate the pointer in either of the above two states. Consumers of such\n//   pointers across an API boundary should continue to treat such pointers as\n//   they currently do.\n//\n// Example:\n//\n// // PaySalary() requires the passed pointer to an `Employee` to be non-null.\n// void PaySalary(Employee* absl_nonnull e) {\n//   pay(e->salary);  // OK to dereference\n// }\n//\n// // CompleteTransaction() guarantees the returned pointer to an `Account` to\n// // be non-null.\n// Account* absl_nonnull balance CompleteTransaction(double fee) {\n// ...\n// }\n//\n// // Note that specifying a nullability annotation does not prevent someone\n// // from violating the contract:\n//\n// Employee* absl_nullable find(Map& employees, std::string_view name);\n//\n// void g(Map& employees) {\n//   Employee *e = find(employees, \"Pat\");\n//   // `e` can now be null.\n//   PaySalary(e); // Violates contract, but compiles!\n// }\n//\n// Nullability annotations, in other words, are useful for defining and\n// narrowing contracts; *enforcement* of those contracts depends on use and any\n// additional (static or dynamic analysis) tooling.\n//\n// NOTE: The \"unknown\" annotation state indicates that a pointer's contract has\n// not yet been positively identified. The unknown state therefore acts as a\n// form of documentation of your technical debt, and a codebase that adopts\n// nullability annotations should aspire to annotate every pointer as either\n// \"non-null\" or \"nullable\".\n//\n// -----------------------------------------------------------------------------\n// Applicability of Nullability Annotations\n// -----------------------------------------------------------------------------\n//\n// By default, nullability annotations are applicable to raw and smart\n// pointers. User-defined types can indicate compatibility with nullability\n// annotations by adding the ABSL_NULLABILITY_COMPATIBLE attribute.\n//\n// // Example:\n// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {\n//   ...\n// };\n//\n// Note: Compilers that don't support the `nullability_on_classes` feature will\n// allow nullability annotations to be applied to any type, not just ones\n// marked with `ABSL_NULLABILITY_COMPATIBLE`.\n//\n// DISCLAIMER:\n// ===========================================================================\n// These nullability annotations are primarily a human readable signal about the\n// intended contract of the pointer. They are not *types* and do not currently\n// provide any correctness guarantees. For example, a pointer annotated as\n// `absl_nonnull` is *not guaranteed* to be non-null, and the compiler won't\n// alert or prevent assignment of a `T* absl_nullable` to a `T* absl_nonnull`.\n// ===========================================================================\n#ifndef ABSL_BASE_NULLABILITY_H_\n#define ABSL_BASE_NULLABILITY_H_\n\n#include \"absl/base/config.h\"\n\n// ABSL_POINTERS_DEFAULT_NONNULL\n//\n// This macro specifies that all unannotated pointer types within the given\n// file are designated as nonnull (instead of the default \"unknown\"). This macro\n// exists as a standalone statement and applies default nonnull behavior to all\n// subsequent pointers; as a result, place this macro as the first non-comment,\n// non-`#include` line in a file.\n//\n// Example:\n//\n//     #include \"absl/base/nullability.h\"\n//\n//     ABSL_POINTERS_DEFAULT_NONNULL\n//\n//     void FillMessage(Message *m);                  // implicitly non-null\n//     T* absl_nullable GetNullablePtr();           // explicitly nullable\n//     T* absl_nullability_unknown GetUnknownPtr();  // explicitly unknown\n//\n// The macro can be safely used in header files – it will not affect any files\n// that include it.\n//\n// In files with the macro, plain `T*` syntax means `T* absl_nonnull`, and the\n// exceptions (`absl_nullable` and `absl_nullability_unknown`) must be marked\n// explicitly. The same holds, correspondingly, for smart pointer types.\n//\n// For comparison, without the macro, all unannotated pointers would default to\n// unknown, and otherwise require explicit annotations to change this behavior:\n//\n//     #include \"absl/base/nullability.h\"\n//\n//     void FillMessage(Message* absl_nonnull m);  // explicitly non-null\n//     T* absl_nullable GetNullablePtr();          // explicitly nullable\n//     T* GetUnknownPtr();                           // implicitly unknown\n//\n// No-op except for being a human readable signal.\n#define ABSL_POINTERS_DEFAULT_NONNULL\n\n#if defined(__clang__) && !defined(__OBJC__) && \\\n    ABSL_HAVE_FEATURE(nullability_on_classes)\n// absl_nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`)\n//\n// The indicated pointer is never null. It is the responsibility of the provider\n// of this pointer across an API boundary to ensure that the pointer is never\n// set to null. Consumers of this pointer across an API boundary may safely\n// dereference the pointer.\n//\n// Example:\n//\n// // `employee` is designated as not null.\n// void PaySalary(Employee* absl_nonnull employee) {\n//   pay(*employee);  // OK to dereference\n// }\n#define absl_nonnull _Nonnull\n\n// absl_nullable\n//\n// The indicated pointer may, by design, be either null or non-null. Consumers\n// of this pointer across an API boundary should perform a `nullptr` check\n// before performing any operation using the pointer.\n//\n// Example:\n//\n// // `employee` may  be null.\n// void PaySalary(Employee* absl_nullable employee) {\n//   if (employee != nullptr) {\n//     Pay(*employee);  // OK to dereference\n//   }\n// }\n#define absl_nullable _Nullable\n\n// absl_nullability_unknown  (default without `ABSL_POINTERS_DEFAULT_NONNULL`)\n//\n// The indicated pointer has not yet been determined to be definitively\n// \"non-null\" or \"nullable.\" Providers of such pointers across API boundaries\n// should, over time, annotate such pointers as either \"non-null\" or \"nullable.\"\n// Consumers of these pointers across an API boundary should treat such pointers\n// with the same caution they treat currently unannotated pointers. Most\n// existing code will have \"unknown\"  pointers, which should eventually be\n// migrated into one of the above two nullability states: `absl_nonnull` or\n//  `absl_nullable`.\n//\n// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`,\n// because this annotation is the global default state, unannotated pointers are\n// are assumed to have \"unknown\" semantics. This assumption is designed to\n// minimize churn and reduce clutter within the codebase.\n//\n// Example:\n//\n// // `employee`s nullability state is unknown.\n// void PaySalary(Employee* absl_nullability_unknown employee) {\n//   Pay(*employee); // Potentially dangerous. API provider should investigate.\n// }\n//\n// Note that a pointer without an annotation, by default, is assumed to have the\n// annotation `NullabilityUnknown`.\n//\n// // `employee`s nullability state is unknown.\n// void PaySalary(Employee* employee) {\n//   Pay(*employee); // Potentially dangerous. API provider should investigate.\n// }\n#define absl_nullability_unknown _Null_unspecified\n#else\n// No-op for non-Clang compilers or Objective-C.\n#define absl_nonnull\n// No-op for non-Clang compilers or Objective-C.\n#define absl_nullable\n// No-op for non-Clang compilers or Objective-C.\n#define absl_nullability_unknown\n#endif\n\n// ABSL_NULLABILITY_COMPATIBLE\n//\n// Indicates that a class is compatible with nullability annotations.\n//\n// For example:\n//\n// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {\n//   ...\n// };\n//\n// Note: Compilers that don't support the `nullability_on_classes` feature will\n// allow nullability annotations to be applied to any type, not just ones marked\n// with `ABSL_NULLABILITY_COMPATIBLE`.\n#if ABSL_HAVE_FEATURE(nullability_on_classes)\n#define ABSL_NULLABILITY_COMPATIBLE _Nullable\n#else\n#define ABSL_NULLABILITY_COMPATIBLE\n#endif\n\n#endif  // ABSL_BASE_NULLABILITY_H_\n"
  },
  {
    "path": "absl/base/nullability_default_nonnull_test.cc",
    "content": "// Copyright 2024 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cassert>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/nullability.h\"\n\nABSL_POINTERS_DEFAULT_NONNULL\n\nnamespace {\n\nvoid FuncWithDefaultNonnullArg(int* /*arg*/) {}\ntemplate <typename T>\nvoid FuncWithDeducedDefaultNonnullArg(T* /*arg*/) {}\n\nTEST(DefaultNonnullTest, NonnullArgument) {\n  int var = 0;\n  FuncWithDefaultNonnullArg(&var);\n  FuncWithDeducedDefaultNonnullArg<int>(&var);\n}\n\nint* FuncWithDefaultNonnullReturn() {\n  static int var = 0;\n  return &var;\n}\n\nTEST(DefaultNonnullTest, NonnullReturn) {\n  auto var = FuncWithDefaultNonnullReturn();\n  (void)var;\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/nullability_test.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/nullability.h\"\n\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\nvoid funcWithNonnullArg(int* absl_nonnull /*arg*/) {}\ntemplate <typename T>\nvoid funcWithDeducedNonnullArg(T* absl_nonnull /*arg*/) {}\n\nTEST(NonnullTest, NonnullArgument) {\n  int var = 0;\n  funcWithNonnullArg(&var);\n  funcWithDeducedNonnullArg(&var);\n}\n\nint* absl_nonnull funcWithNonnullReturn() {\n  static int var = 0;\n  return &var;\n}\n\nTEST(NonnullTest, NonnullReturn) {\n  auto var = funcWithNonnullReturn();\n  (void)var;\n}\n\nTEST(PassThroughTest, PassesThroughRawPointerToInt) {\n  EXPECT_TRUE((std::is_same<int* absl_nonnull, int*>::value));\n  EXPECT_TRUE((std::is_same<int* absl_nullable, int*>::value));\n  EXPECT_TRUE((std::is_same<int* absl_nullability_unknown, int*>::value));\n}\n\nTEST(PassThroughTest, PassesThroughRawPointerToVoid) {\n  EXPECT_TRUE((std::is_same<void* absl_nonnull, void*>::value));\n  EXPECT_TRUE((std::is_same<void* absl_nullable, void*>::value));\n  EXPECT_TRUE((std::is_same<void* absl_nullability_unknown, void*>::value));\n}\n\nTEST(PassThroughTest, PassesThroughUniquePointerToInt) {\n  using T = std::unique_ptr<int>;\n  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));\n}\n\nTEST(PassThroughTest, PassesThroughSharedPointerToInt) {\n  using T = std::shared_ptr<int>;\n  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));\n}\n\nTEST(PassThroughTest, PassesThroughSharedPointerToVoid) {\n  using T = std::shared_ptr<void>;\n  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));\n}\n\nTEST(PassThroughTest, PassesThroughPointerToMemberObject) {\n  using T = decltype(&std::pair<int, int>::first);\n  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));\n}\n\nTEST(PassThroughTest, PassesThroughPointerToMemberFunction) {\n  using T = decltype(&std::unique_ptr<int>::reset);\n  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));\n  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));\n}\n}  // namespace\n"
  },
  {
    "path": "absl/base/optimization.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: optimization.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines portable macros for performance optimization.\n//\n// This header is included in both C++ code and legacy C code and thus must\n// remain compatible with both C and C++. C compatibility will be removed if\n// the legacy code is removed or converted to C++. Do not include this header in\n// new code that requires C compatibility or assume C compatibility will remain\n// indefinitely.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_BASE_OPTIMIZATION_H_\n#define ABSL_BASE_OPTIMIZATION_H_\n\n#include <assert.h>\n\n#ifdef __cplusplus\n// Included for std::unreachable()\n#include <utility>\n#endif  // __cplusplus\n\n#include \"absl/base/config.h\"\n#include \"absl/base/options.h\"\n\n// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION\n//\n// Instructs the compiler to avoid optimizing tail-call recursion. This macro is\n// useful when you wish to preserve the existing function order within a stack\n// trace for logging, debugging, or profiling purposes.\n//\n// Example:\n//\n//   int f() {\n//     int result = g();\n//     ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n//     return result;\n//   }\n#if defined(__clang__)\n// Clang will not tail call given inline volatile assembly.\n#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__(\"\")\n#elif defined(__GNUC__)\n// GCC will not tail call given inline volatile assembly.\n#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__(\"\")\n#elif defined(_MSC_VER)\n#include <intrin.h>\n// The __nop() intrinsic blocks the optimisation.\n#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop()\n#else\n#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }\n#endif\n\n// ABSL_CACHELINE_SIZE\n//\n// Explicitly defines the size of the L1 cache for purposes of alignment.\n// Setting the cacheline size allows you to specify that certain objects be\n// aligned on a cacheline boundary with `ABSL_CACHELINE_ALIGNED` declarations.\n// (See below.)\n//\n// NOTE: this macro should be replaced with the following C++17 features, when\n// those are generally available:\n//\n//   * `std::hardware_constructive_interference_size`\n//   * `std::hardware_destructive_interference_size`\n//\n// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html\n// for more information.\n#if defined(__GNUC__)\n// Cache line alignment\n#if defined(__i386__) || defined(__x86_64__)\n#define ABSL_CACHELINE_SIZE 64\n#elif defined(__powerpc64__)\n#define ABSL_CACHELINE_SIZE 128\n#elif defined(__aarch64__)\n// We would need to read special register ctr_el0 to find out L1 dcache size.\n// This value is a good estimate based on a real aarch64 machine.\n#define ABSL_CACHELINE_SIZE 64\n#elif defined(__arm__)\n// Cache line sizes for ARM: These values are not strictly correct since\n// cache line sizes depend on implementations, not architectures.  There\n// are even implementations with cache line sizes configurable at boot\n// time.\n#if defined(__ARM_ARCH_5T__)\n#define ABSL_CACHELINE_SIZE 32\n#elif defined(__ARM_ARCH_7A__)\n#define ABSL_CACHELINE_SIZE 64\n#endif\n#endif\n#endif\n\n#ifndef ABSL_CACHELINE_SIZE\n// A reasonable default guess.  Note that overestimates tend to waste more\n// space, while underestimates tend to waste more time.\n#define ABSL_CACHELINE_SIZE 64\n#endif\n\n// ABSL_CACHELINE_ALIGNED\n//\n// Indicates that the declared object be cache aligned using\n// `ABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to\n// load a set of related objects in the L1 cache for performance improvements.\n// Cacheline aligning objects properly allows constructive memory sharing and\n// prevents destructive (or \"false\") memory sharing.\n//\n// NOTE: callers should replace uses of this macro with `alignas()` using\n// `std::hardware_constructive_interference_size` and/or\n// `std::hardware_destructive_interference_size` when C++17 becomes available to\n// them.\n//\n// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html\n// for more information.\n//\n// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__`\n// or `__declspec` attribute. For compilers where this is not known to work,\n// the macro expands to nothing.\n//\n// No further guarantees are made here. The result of applying the macro\n// to variables and types is always implementation-defined.\n//\n// WARNING: It is easy to use this attribute incorrectly, even to the point\n// of causing bugs that are difficult to diagnose, crash, etc. It does not\n// of itself guarantee that objects are aligned to a cache line.\n//\n// NOTE: Some compilers are picky about the locations of annotations such as\n// this attribute, so prefer to put it at the beginning of your declaration.\n// For example,\n//\n//   ABSL_CACHELINE_ALIGNED static Foo* foo = ...\n//\n//   class ABSL_CACHELINE_ALIGNED Bar { ...\n//\n// Recommendations:\n//\n// 1) Consult compiler documentation; this comment is not kept in sync as\n//    toolchains evolve.\n// 2) Verify your use has the intended effect. This often requires inspecting\n//    the generated machine code.\n// 3) Prefer applying this attribute to individual variables. Avoid\n//    applying it to types. This tends to localize the effect.\n#if defined(__clang__) || defined(__GNUC__)\n#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))\n#elif defined(_MSC_VER)\n#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))\n#else\n#define ABSL_CACHELINE_ALIGNED\n#endif\n\n// ABSL_PREDICT_TRUE, ABSL_PREDICT_FALSE\n//\n// Enables the compiler to prioritize compilation using static analysis for\n// likely paths within a boolean branch.\n//\n// Example:\n//\n//   if (ABSL_PREDICT_TRUE(expression)) {\n//     return result;                        // Faster if more likely\n//   } else {\n//     return 0;\n//   }\n//\n// Compilers can use the information that a certain branch is not likely to be\n// taken (for instance, a CHECK failure) to optimize for the common case in\n// the absence of better information (ie. compiling gcc with `-fprofile-arcs`).\n//\n// Recommendation: Modern CPUs dynamically predict branch execution paths,\n// typically with accuracy greater than 97%. As a result, annotating every\n// branch in a codebase is likely counterproductive; however, annotating\n// specific branches that are both hot and consistently mispredicted is likely\n// to yield performance improvements.\n#if ABSL_HAVE_BUILTIN(__builtin_expect) || \\\n    (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))\n#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))\n#else\n#define ABSL_PREDICT_FALSE(x) (x)\n#define ABSL_PREDICT_TRUE(x) (x)\n#endif\n\n// `ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL()` aborts the program in the fastest\n// possible way, with no attempt at logging. One use is to implement hardening\n// aborts with ABSL_OPTION_HARDENED.  Since this is an internal symbol, it\n// should not be used directly outside of Abseil.\n#if ABSL_HAVE_BUILTIN(__builtin_trap) || \\\n    (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() __builtin_trap()\n#else\n#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() abort()\n#endif\n\n// `ABSL_INTERNAL_UNREACHABLE_IMPL()` is the platform specific directive to\n// indicate that a statement is unreachable, and to allow the compiler to\n// optimize accordingly. Clients should use `ABSL_UNREACHABLE()`, which is\n// defined below.\n#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L\n#define ABSL_INTERNAL_UNREACHABLE_IMPL() std::unreachable()\n#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)\n#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_unreachable()\n#elif ABSL_HAVE_BUILTIN(__builtin_assume)\n#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_assume(false)\n#elif defined(_MSC_VER)\n#define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false)\n#else\n#define ABSL_INTERNAL_UNREACHABLE_IMPL()\n#endif\n\n// `ABSL_UNREACHABLE()` is an unreachable statement.  A program which reaches\n// one has undefined behavior, and the compiler may optimize accordingly.\n#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)\n// Abort in hardened mode to avoid dangerous undefined behavior.\n#define ABSL_UNREACHABLE()                \\\n  do {                                    \\\n    ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \\\n    ABSL_INTERNAL_UNREACHABLE_IMPL();     \\\n  } while (false)\n#else\n// The assert only fires in debug mode to aid in debugging.\n// When NDEBUG is defined, reaching ABSL_UNREACHABLE() is undefined behavior.\n#define ABSL_UNREACHABLE()                       \\\n  do {                                           \\\n    /* NOLINTNEXTLINE: misc-static-assert */     \\\n    assert(false && \"ABSL_UNREACHABLE reached\"); \\\n    ABSL_INTERNAL_UNREACHABLE_IMPL();            \\\n  } while (false)\n#endif\n\n// ABSL_ASSUME(cond)\n//\n// Informs the compiler that a condition is always true and that it can assume\n// it to be true for optimization purposes.\n//\n// WARNING: If the condition is false, the program can produce undefined and\n// potentially dangerous behavior.\n//\n// In !NDEBUG mode, the condition is checked with an assert().\n//\n// NOTE: The expression must not have side effects, as it may only be evaluated\n// in some compilation modes and not others. Some compilers may issue a warning\n// if the compiler cannot prove the expression has no side effects. For example,\n// the expression should not use a function call since the compiler cannot prove\n// that a function call does not have side effects.\n//\n// Example:\n//\n//   int x = ...;\n//   ABSL_ASSUME(x >= 0);\n//   // The compiler can optimize the division to a simple right shift using the\n//   // assumption specified above.\n//   int y = x / 16;\n//\n#if !defined(NDEBUG)\n#define ABSL_ASSUME(cond) assert(cond)\n#elif ABSL_HAVE_BUILTIN(__builtin_assume)\n#define ABSL_ASSUME(cond) __builtin_assume(cond)\n#elif defined(_MSC_VER)\n#define ABSL_ASSUME(cond) __assume(cond)\n#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L\n#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable())\n#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)\n#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable())\n#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case.\n#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())())\n#else\n#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void())\n#endif\n\n// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)\n// This macro forces small unique name on a static file level symbols like\n// static local variables or static functions. This is intended to be used in\n// macro definitions to optimize the cost of generated code. Do NOT use it on\n// symbols exported from translation unit since it may cause a link time\n// conflict.\n//\n// Example:\n//\n// #define MY_MACRO(txt)\n// namespace {\n//  char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt;\n//  const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();\n//  const char* VeryVeryLongFuncName() { return txt; }\n// }\n//\n\n#if defined(__GNUC__)\n#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x\n#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x)\n#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \\\n  asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__))\n#else\n#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()\n#endif\n\n#endif  // ABSL_BASE_OPTIMIZATION_H_\n"
  },
  {
    "path": "absl/base/optimization_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/optimization.h\"\n\n#include <optional>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\n// Tests for the ABSL_PREDICT_TRUE and ABSL_PREDICT_FALSE macros.\n// The tests only verify that the macros are functionally correct - i.e. code\n// behaves as if they weren't used. They don't try to check their impact on\n// optimization.\n\nTEST(PredictTest, PredictTrue) {\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(true));\n  EXPECT_FALSE(ABSL_PREDICT_TRUE(false));\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(1 == 1));\n  EXPECT_FALSE(ABSL_PREDICT_TRUE(1 == 2));\n\n  if (ABSL_PREDICT_TRUE(false)) ADD_FAILURE();\n  if (!ABSL_PREDICT_TRUE(true)) ADD_FAILURE();\n\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(true) && true);\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(true) || false);\n}\n\nTEST(PredictTest, PredictFalse) {\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(true));\n  EXPECT_FALSE(ABSL_PREDICT_FALSE(false));\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(1 == 1));\n  EXPECT_FALSE(ABSL_PREDICT_FALSE(1 == 2));\n\n  if (ABSL_PREDICT_FALSE(false)) ADD_FAILURE();\n  if (!ABSL_PREDICT_FALSE(true)) ADD_FAILURE();\n\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(true) && true);\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(true) || false);\n}\n\nTEST(PredictTest, OneEvaluation) {\n  // Verify that the expression is only evaluated once.\n  int x = 0;\n  if (ABSL_PREDICT_TRUE((++x) == 0)) ADD_FAILURE();\n  EXPECT_EQ(x, 1);\n  if (ABSL_PREDICT_FALSE((++x) == 0)) ADD_FAILURE();\n  EXPECT_EQ(x, 2);\n}\n\nTEST(PredictTest, OperatorOrder) {\n  // Verify that operator order inside and outside the macro behaves well.\n  // These would fail for a naive '#define ABSL_PREDICT_TRUE(x) x'\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(1 && 2) == true);\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(1 && 2) == true);\n  EXPECT_TRUE(!ABSL_PREDICT_TRUE(1 == 2));\n  EXPECT_TRUE(!ABSL_PREDICT_FALSE(1 == 2));\n}\n\nTEST(PredictTest, Pointer) {\n  const int x = 3;\n  const int *good_intptr = &x;\n  const int *null_intptr = nullptr;\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));\n  EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));\n  EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));\n}\n\nTEST(PredictTest, Optional) {\n  // Note: An optional's truth value is the value's existence, not its truth.\n  std::optional<bool> has_value(false);\n  std::optional<bool> no_value;\n  EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));\n  EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));\n  EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));\n  EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));\n}\n\nclass ImplicitlyConvertibleToBool {\n public:\n  explicit ImplicitlyConvertibleToBool(bool value) : value_(value) {}\n  operator bool() const {  // NOLINT(google-explicit-constructor)\n    return value_;\n  }\n\n private:\n  bool value_;\n};\n\nTEST(PredictTest, ImplicitBoolConversion) {\n  const ImplicitlyConvertibleToBool is_true(true);\n  const ImplicitlyConvertibleToBool is_false(false);\n  if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();\n  if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();\n  if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();\n  if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();\n}\n\nclass ExplicitlyConvertibleToBool {\n public:\n  explicit ExplicitlyConvertibleToBool(bool value) : value_(value) {}\n  explicit operator bool() const { return value_; }\n\n private:\n  bool value_;\n};\n\nTEST(PredictTest, ExplicitBoolConversion) {\n  const ExplicitlyConvertibleToBool is_true(true);\n  const ExplicitlyConvertibleToBool is_false(false);\n  if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();\n  if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();\n  if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();\n  if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();\n}\n\n// This verifies that ABSL_ASSUME compiles in a variety of contexts.\n// It does not test optimization.\nTEST(AbslAssume, Compiles) {\n  int x = 0;\n  ABSL_ASSUME(x >= 0);\n  EXPECT_EQ(x, 0);\n\n  // https://github.com/abseil/abseil-cpp/issues/1814\n  ABSL_ASSUME(x >= 0), (x >= 0) ? ++x : --x;\n  EXPECT_EQ(x, 1);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/options.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: options.h\n// -----------------------------------------------------------------------------\n//\n// This file contains Abseil configuration options for setting specific\n// implementations instead of letting Abseil determine which implementation to\n// use at compile-time. Setting these options may be useful for package or build\n// managers who wish to guarantee ABI stability within binary builds (which are\n// otherwise difficult to enforce).\n//\n// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS:  It is important that\n// maintainers of package managers who wish to package Abseil read and\n// understand this file! ***\n//\n// Abseil contains a number of possible configuration endpoints, based on\n// parameters such as the detected platform, language version, or command-line\n// flags used to invoke the underlying binary. As is the case with all\n// libraries, binaries which contain Abseil code must ensure that separate\n// packages use the same compiled copy of Abseil to avoid a diamond dependency\n// problem, which can occur if two packages built with different Abseil\n// configuration settings are linked together. Diamond dependency problems in\n// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in\n// linker errors), or undefined behavior (resulting in crashes).\n//\n// Diamond dependency problems can be avoided if all packages utilize the same\n// exact version of Abseil. Building from source code with the same compilation\n// parameters is the easiest way to avoid such dependency problems. However, for\n// package managers who cannot control such compilation parameters, we are\n// providing the file to allow you to inject ABI (Application Binary Interface)\n// stability across builds. Settings options in this file will neither change\n// API nor ABI, providing a stable copy of Abseil between packages.\n//\n// Care must be taken to keep options within these configurations isolated\n// from any other dynamic settings, such as command-line flags which could alter\n// these options. This file is provided specifically to help build and package\n// managers provide a stable copy of Abseil within their libraries and binaries;\n// other developers should not have need to alter the contents of this file.\n//\n// -----------------------------------------------------------------------------\n// Usage\n// -----------------------------------------------------------------------------\n//\n// For any particular package release, set the appropriate definitions within\n// this file to whatever value makes the most sense for your package(s). Note\n// that, by default, most of these options, at the moment, affect the\n// implementation of types; future options may affect other implementation\n// details.\n//\n// NOTE: the defaults within this file all assume that Abseil can select the\n// proper Abseil implementation at compile-time, which will not be sufficient\n// to guarantee ABI stability to package managers.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_BASE_OPTIONS_H_\n#define ABSL_BASE_OPTIONS_H_\n\n// -----------------------------------------------------------------------------\n// Type Compatibility Options\n// -----------------------------------------------------------------------------\n\n// ABSL_OPTION_USE_STD_SOURCE_LOCATION\n//\n// This option controls whether absl::SourceLocation is implemented as an alias\n// to the std::source_location type, or as an independent implementation.\n//\n// A value of 0 means to use Abseil's implementation.  This requires only C++17\n// support, and is expected to run on every toolchain we support, and to\n// properly capture source location information on every toolchain that supports\n// the necessary built-ins (such as `__builtin_LINE`).\n//\n// A value of 1 means to use aliases.  This requires that all code using Abseil\n// is built in C++20 mode or later.\n//\n// A value of 2 means to detect the C++ version being used to compile Abseil,\n// and use an alias only if working std::source_location types are available.\n// This option is useful when you are building your program from source.  It\n// should not be used otherwise -- for example, if you are distributing Abseil\n// in a binary package manager -- since in mode 2, they will name different\n// types, with different mangled names and binary layout, depending on the\n// compiler flags passed by the end user.  For more info, see\n// https://abseil.io/about/design/dropin-types.\n//\n// User code should not inspect this macro.  To check in the preprocessor if\n// the source location type is an alias of std::source_location type, use the\n// feature macro ABSL_USES_STD_SOURCE_LOCATION.\n//\n#define ABSL_OPTION_USE_STD_SOURCE_LOCATION 2\n\n// ABSL_OPTION_USE_STD_ORDERING\n//\n// This option controls whether absl::{partial,weak,strong}_ordering are\n// implemented as aliases to the std:: ordering types, or as an independent\n// implementation.\n//\n// A value of 0 means to use Abseil's implementation.  This requires only C++11\n// support, and is expected to work on every toolchain we support.\n//\n// A value of 1 means to use aliases.  This requires that all code using Abseil\n// is built in C++20 mode or later.\n//\n// A value of 2 means to detect the C++ version being used to compile Abseil,\n// and use an alias only if working std:: ordering types are available.  This\n// option is useful when you are building your program from source.  It should\n// not be used otherwise -- for example, if you are distributing Abseil in a\n// binary package manager -- since in mode 2, they will name different types,\n// with different mangled names and binary layout, depending on the compiler\n// flags passed by the end user.  For more info, see\n// https://abseil.io/about/design/dropin-types.\n//\n// User code should not inspect this macro.  To check in the preprocessor if\n// the ordering types are aliases of std:: ordering types, use the feature macro\n// ABSL_USES_STD_ORDERING.\n\n#define ABSL_OPTION_USE_STD_ORDERING 2\n\n// ABSL_OPTION_USE_INLINE_NAMESPACE\n// ABSL_OPTION_INLINE_NAMESPACE_NAME\n//\n// These options controls whether all entities in the absl namespace are\n// contained within an inner inline namespace.  This does not affect the\n// user-visible API of Abseil, but it changes the mangled names of all symbols.\n//\n// This can be useful as a version tag if you are distributing Abseil in\n// precompiled form.  This will prevent a binary library build of Abseil with\n// one inline namespace being used with headers configured with a different\n// inline namespace name.  Binary packagers are reminded that Abseil does not\n// guarantee any ABI stability in Abseil, so any update of Abseil or\n// configuration change in such a binary package should be combined with a\n// new, unique value for the inline namespace name.\n//\n// A value of 0 means not to use inline namespaces.\n//\n// A value of 1 means to use an inline namespace with the given name inside\n// namespace absl.  If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also\n// be changed to a new, unique identifier name.  In particular \"head\" is not\n// allowed.\n\n#define ABSL_OPTION_USE_INLINE_NAMESPACE 0\n#define ABSL_OPTION_INLINE_NAMESPACE_NAME head\n\n// ABSL_OPTION_HARDENED\n//\n// This option enables a \"hardened\" build in release mode (in this context,\n// release mode is defined as a build where the `NDEBUG` macro is defined).\n//\n// A value of 0 means that \"hardened\" mode is not enabled.\n//\n// A value of 1 means that \"hardened\" mode is enabled with all checks.\n//\n// A value of 2 means that \"hardened\" mode is partially enabled, with\n// only a subset of checks chosen to minimize performance impact.\n//\n// Hardened builds have additional security checks enabled when `NDEBUG` is\n// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a\n// no-op, as well as disabling other bespoke program consistency checks. By\n// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in\n// release mode. These checks guard against programming errors that may lead to\n// security vulnerabilities. In release mode, when one of these programming\n// errors is encountered, the program will immediately abort, possibly without\n// any attempt at logging.\n//\n// The checks enabled by this option are not free; they do incur runtime cost.\n//\n// The checks enabled by this option are always active when `NDEBUG` is not\n// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The\n// checks enabled by this option may abort the program in a different way and\n// log additional information when `NDEBUG` is not defined.\n\n#define ABSL_OPTION_HARDENED 0\n\n#endif  // ABSL_BASE_OPTIONS_H_\n"
  },
  {
    "path": "absl/base/policy_checks.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: policy_checks.h\n// -----------------------------------------------------------------------------\n//\n// This header enforces a minimum set of policies at build time, such as the\n// supported compiler and library versions. Unsupported configurations are\n// reported with `#error`. This enforcement is best effort, so successfully\n// compiling this header does not guarantee a supported configuration.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_BASE_POLICY_CHECKS_H_\n#define ABSL_BASE_POLICY_CHECKS_H_\n\n// Included for the __GLIBC_PREREQ macro used below.\n#include <limits.h>\n\n// Included for the _STLPORT_VERSION macro used below.\n#if defined(__cplusplus)\n#include <cstddef>\n#endif\n\n// -----------------------------------------------------------------------------\n// Operating System Check\n// -----------------------------------------------------------------------------\n\n#if defined(__CYGWIN__)\n#error \"Cygwin is not supported.\"\n#endif\n\n// -----------------------------------------------------------------------------\n// Toolchain Check\n// -----------------------------------------------------------------------------\n\n// We support Visual Studio 2019 (MSVC++ 16.0) and later.\n// This minimum will go up.\n#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)\n#error \"This package requires Visual Studio 2019 (MSVC++ 16.0) or higher.\"\n#endif\n\n// We support GCC 7 and later.\n// This minimum will go up.\n#if defined(__GNUC__) && !defined(__clang__)\n#if __GNUC__ < 7\n#error \"This package requires GCC 7 or higher.\"\n#endif\n#endif\n\n// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later.\n// This corresponds to Apple Xcode version 4.5.\n// This minimum will go up.\n#if defined(__apple_build_version__) && __apple_build_version__ < 4211165\n#error \"This package requires __apple_build_version__ of 4211165 or higher.\"\n#endif\n\n// -----------------------------------------------------------------------------\n// C++ Version Check\n// -----------------------------------------------------------------------------\n\n// Enforce C++17 as the minimum.\n#if defined(_MSVC_LANG)\n#if _MSVC_LANG < 201703L\n#error \"C++ versions less than C++17 are not supported.\"\n#endif  // _MSVC_LANG < 201703L\n#elif defined(__cplusplus)\n#if __cplusplus < 201703L\n#error \"C++ versions less than C++17 are not supported.\"\n#endif  // __cplusplus < 201703L\n#endif\n\n// -----------------------------------------------------------------------------\n// Standard Library Check\n// -----------------------------------------------------------------------------\n\n#if defined(_STLPORT_VERSION)\n#error \"STLPort is not supported.\"\n#endif\n\n// -----------------------------------------------------------------------------\n// `char` Size Check\n// -----------------------------------------------------------------------------\n\n// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a\n// platform where this is not the case, please provide us with the details about\n// your platform so we can consider relaxing this requirement.\n#if CHAR_BIT != 8\n#error \"Abseil assumes CHAR_BIT == 8.\"\n#endif\n\n// -----------------------------------------------------------------------------\n// `int` Size Check\n// -----------------------------------------------------------------------------\n\n// Abseil currently assumes that an int is 4 bytes. If you would like to use\n// Abseil on a platform where this is not the case, please provide us with the\n// details about your platform so we can consider relaxing this requirement.\n#if INT_MAX < 2147483647\n#error \"Abseil assumes that int is at least 4 bytes. \"\n#endif\n\n#endif  // ABSL_BASE_POLICY_CHECKS_H_\n"
  },
  {
    "path": "absl/base/port.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This files is a forwarding header for other headers containing various\n// portability macros and functions.\n\n#ifndef ABSL_BASE_PORT_H_\n#define ABSL_BASE_PORT_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n\n#endif  // ABSL_BASE_PORT_H_\n"
  },
  {
    "path": "absl/base/prefetch.h",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: prefetch.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines prefetch functions to prefetch memory contents\n// into the first level cache (L1) for the current CPU. The prefetch logic\n// offered in this header is limited to prefetching first level cachelines\n// only, and is aimed at relatively 'simple' prefetching logic.\n//\n#ifndef ABSL_BASE_PREFETCH_H_\n#define ABSL_BASE_PREFETCH_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n#if defined(ABSL_INTERNAL_HAVE_SSE)\n#include <xmmintrin.h>\n#endif\n\n#if defined(_MSC_VER)\n#include <intrin.h>\n#if defined(ABSL_INTERNAL_HAVE_SSE)\n#pragma intrinsic(_mm_prefetch)\n#endif\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Moves data into the L1 cache before it is read, or \"prefetches\" it.\n//\n// The value of `addr` is the address of the memory to prefetch. If\n// the target and compiler support it, data prefetch instructions are\n// generated. If the prefetch is done some time before the memory is\n// read, it may be in the cache by the time the read occurs.\n//\n// This method prefetches data with the highest degree of temporal locality;\n// data is prefetched where possible into all levels of the cache.\n//\n// Incorrect or gratuitous use of this function can degrade performance.\n// Use this function only when representative benchmarks show an improvement.\n//\n// Example:\n//\n//  // Computes incremental checksum for `data`.\n//  int ComputeChecksum(int sum, absl::string_view data);\n//\n//  // Computes cumulative checksum for all values in `data`\n//  int ComputeChecksum(absl::Span<const std::string> data) {\n//    int sum = 0;\n//    auto it = data.begin();\n//    auto pit = data.begin();\n//    auto end = data.end();\n//    for (int dist = 8; dist > 0 && pit != data.end(); --dist, ++pit) {\n//      absl::PrefetchToLocalCache(pit->data());\n//    }\n//    for (; pit != end; ++pit, ++it) {\n//      sum = ComputeChecksum(sum, *it);\n//      absl::PrefetchToLocalCache(pit->data());\n//    }\n//    for (; it != end; ++it) {\n//      sum = ComputeChecksum(sum, *it);\n//    }\n//    return sum;\n//  }\n//\nvoid PrefetchToLocalCache(const void* addr);\n\n// Moves data into the L1 cache before it is read, or \"prefetches\" it.\n//\n// This function is identical to `PrefetchToLocalCache()` except that it has\n// non-temporal locality: the fetched data should not be left in any of the\n// cache tiers. This is useful for cases where the data is used only once /\n// short term, for example, invoking a destructor on an object.\n//\n// Incorrect or gratuitous use of this function can degrade performance.\n// Use this function only when representative benchmarks show an improvement.\n//\n// Example:\n//\n//  template <typename Iterator>\n//  void DestroyPointers(Iterator begin, Iterator end) {\n//    size_t distance = std::min(8U, bars.size());\n//\n//    int dist = 8;\n//    auto prefetch_it = begin;\n//    while (prefetch_it != end && --dist;) {\n//      absl::PrefetchToLocalCacheNta(*prefetch_it++);\n//    }\n//    while (prefetch_it != end) {\n//      delete *begin++;\n//      absl::PrefetchToLocalCacheNta(*prefetch_it++);\n//    }\n//    while (begin != end) {\n//      delete *begin++;\n//    }\n//  }\n//\nvoid PrefetchToLocalCacheNta(const void* addr);\n\n// Moves data into the L1 cache with the intent to modify it.\n//\n// This function is similar to `PrefetchToLocalCache()` except that it\n// prefetches cachelines with an 'intent to modify' This typically includes\n// invalidating cache entries for this address in all other cache tiers, and an\n// exclusive access intent.\n//\n// Incorrect or gratuitous use of this function can degrade performance. As this\n// function can invalidate cached cachelines on other caches and computer cores,\n// incorrect usage of this function can have an even greater negative impact\n// than incorrect regular prefetches.\n// Use this function only when representative benchmarks show an improvement.\n//\n// Example:\n//\n//  void* Arena::Allocate(size_t size) {\n//    void* ptr = AllocateBlock(size);\n//    absl::PrefetchToLocalCacheForWrite(ptr);\n//    return ptr;\n//  }\n//\nvoid PrefetchToLocalCacheForWrite(const void* addr);\n\n#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)\n\n#define ABSL_HAVE_PREFETCH 1\n\n// See __builtin_prefetch:\n// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.\n//\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(\n    const void* addr) {\n  __builtin_prefetch(addr, 0, 3);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(\n    const void* addr) {\n  __builtin_prefetch(addr, 0, 0);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(\n    const void* addr) {\n  // [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1)\n  // unless -march=broadwell or newer; this is not generally the default, so we\n  // manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel\n  // processors and has been present on AMD processors since the K6-2.\n#if defined(__x86_64__) && !defined(__PRFCHW__)\n  asm(\"prefetchw %0\" : : \"m\"(*reinterpret_cast<const char*>(addr)));\n#else\n  __builtin_prefetch(addr, 1, 3);\n#endif\n}\n\n#elif defined(ABSL_INTERNAL_HAVE_SSE)\n\n#define ABSL_HAVE_PREFETCH 1\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(\n    const void* addr) {\n  _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(\n    const void* addr) {\n  _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(\n    const void* addr) {\n#if defined(_MM_HINT_ET0)\n  _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0);\n#elif !defined(_MSC_VER) && defined(__x86_64__)\n  // _MM_HINT_ET0 is not universally supported. As we commented further\n  // up, PREFETCHW is recognized as a no-op on older Intel processors\n  // and has been present on AMD processors since the K6-2. We have this\n  // disabled for MSVC compilers as this miscompiles on older MSVC compilers.\n  asm(\"prefetchw %0\" : : \"m\"(*reinterpret_cast<const char*>(addr)));\n#endif\n}\n\n#else\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(\n    const void* addr) {}\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(\n    const void* addr) {}\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(\n    const void* addr) {}\n\n#endif\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_PREFETCH_H_\n"
  },
  {
    "path": "absl/base/prefetch_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/prefetch.h\"\n\n#include <memory>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\n// Below tests exercise the functions only to guarantee they compile and execute\n// correctly. We make no attempt at verifying any prefetch instructions being\n// generated and executed: we assume the various implementation in terms of\n// __builtin_prefetch() or x86 intrinsics to be correct and well tested.\n\nTEST(PrefetchTest, PrefetchToLocalCache_StackA) {\n  char buf[100] = {};\n  absl::PrefetchToLocalCache(buf);\n  absl::PrefetchToLocalCacheNta(buf);\n  absl::PrefetchToLocalCacheForWrite(buf);\n}\n\nTEST(PrefetchTest, PrefetchToLocalCache_Heap) {\n  auto memory = std::make_unique<char[]>(200 << 10);\n  memset(memory.get(), 0, 200 << 10);\n  absl::PrefetchToLocalCache(memory.get());\n  absl::PrefetchToLocalCacheNta(memory.get());\n  absl::PrefetchToLocalCacheForWrite(memory.get());\n  absl::PrefetchToLocalCache(memory.get() + (50 << 10));\n  absl::PrefetchToLocalCacheNta(memory.get() + (50 << 10));\n  absl::PrefetchToLocalCacheForWrite(memory.get() + (50 << 10));\n  absl::PrefetchToLocalCache(memory.get() + (100 << 10));\n  absl::PrefetchToLocalCacheNta(memory.get() + (100 << 10));\n  absl::PrefetchToLocalCacheForWrite(memory.get() + (100 << 10));\n  absl::PrefetchToLocalCache(memory.get() + (150 << 10));\n  absl::PrefetchToLocalCacheNta(memory.get() + (150 << 10));\n  absl::PrefetchToLocalCacheForWrite(memory.get() + (150 << 10));\n}\n\nTEST(PrefetchTest, PrefetchToLocalCache_Nullptr) {\n  absl::PrefetchToLocalCache(nullptr);\n  absl::PrefetchToLocalCacheNta(nullptr);\n  absl::PrefetchToLocalCacheForWrite(nullptr);\n}\n\nTEST(PrefetchTest, PrefetchToLocalCache_InvalidPtr) {\n  absl::PrefetchToLocalCache(reinterpret_cast<const void*>(0x785326532L));\n  absl::PrefetchToLocalCacheNta(reinterpret_cast<const void*>(0x785326532L));\n  absl::PrefetchToLocalCacheForWrite(reinterpret_cast<const void*>(0x78532L));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/raw_logging_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This test serves primarily as a compilation test for base/raw_logging.h.\n// Raw logging testing is covered by logging_unittest.cc, which is not as\n// portable as this test.\n\n#include \"absl/base/internal/raw_logging.h\"\n\n#include <tuple>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\n\nTEST(RawLoggingCompilationTest, Log) {\n  ABSL_RAW_LOG(INFO, \"RAW INFO: %d\", 1);\n  ABSL_RAW_LOG(INFO, \"RAW INFO: %d %d\", 1, 2);\n  ABSL_RAW_LOG(INFO, \"RAW INFO: %d %d %d\", 1, 2, 3);\n  ABSL_RAW_LOG(INFO, \"RAW INFO: %d %d %d %d\", 1, 2, 3, 4);\n  ABSL_RAW_LOG(INFO, \"RAW INFO: %d %d %d %d %d\", 1, 2, 3, 4, 5);\n  ABSL_RAW_LOG(WARNING, \"RAW WARNING: %d\", 1);\n  ABSL_RAW_LOG(ERROR, \"RAW ERROR: %d\", 1);\n}\n\nTEST(RawLoggingCompilationTest, LogWithNulls) {\n  ABSL_RAW_LOG(INFO, \"RAW INFO: %s%c%s\", \"Hello\", 0, \"World\");\n}\n\nTEST(RawLoggingCompilationTest, PassingCheck) {\n  ABSL_RAW_CHECK(true, \"RAW CHECK\");\n}\n\nTEST(RawLoggingCompilationTest, DebugLog) {\n  ABSL_RAW_DLOG(INFO, \"RAW DLOG: %d\", 1);\n}\n\nTEST(RawLoggingCompilationTest, PassingDebugCheck) {\n  ABSL_RAW_DCHECK(true, \"failure message\");\n}\n\n// Not all platforms support output from raw log, so we don't verify any\n// particular output for RAW check failures (expecting the empty string\n// accomplishes this).  This test is primarily a compilation test, but we\n// are verifying process death when EXPECT_DEATH works for a platform.\nconst char kExpectedDeathOutput[] = \"\";\n\n#if !defined(NDEBUG)  // if debug build\nTEST(RawLoggingDeathTest, FailingDebugCheck) {\n  EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_DCHECK(1 == 0, \"explanation\"),\n                            kExpectedDeathOutput);\n}\n#endif  // if debug build\n\nTEST(RawLoggingDeathTest, FailingCheck) {\n  EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_CHECK(1 == 0, \"explanation\"),\n                            kExpectedDeathOutput);\n}\n\nTEST(RawLoggingDeathTest, LogFatal) {\n  EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_LOG(FATAL, \"my dog has fleas\"),\n                            kExpectedDeathOutput);\n}\n\nTEST(InternalLog, CompilationTest) {\n  ABSL_INTERNAL_LOG(INFO, \"Internal Log\");\n  std::string log_msg = \"Internal Log\";\n  ABSL_INTERNAL_LOG(INFO, log_msg);\n\n  ABSL_INTERNAL_LOG(INFO, log_msg + \" 2\");\n\n  float d = 1.1f;\n  ABSL_INTERNAL_LOG(INFO, absl::StrCat(\"Internal log \", 3, \" + \", d));\n}\n\nTEST(InternalLogDeathTest, FailingCheck) {\n  EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_CHECK(1 == 0, \"explanation\"),\n                            kExpectedDeathOutput);\n}\n\nTEST(InternalLogDeathTest, LogFatal) {\n  EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_LOG(FATAL, \"my dog has fleas\"),\n                            kExpectedDeathOutput);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/base/spinlock_test_common.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// A bunch of threads repeatedly hash an array of ints protected by a\n// spinlock.  If the spinlock is working properly, all elements of the\n// array should be equal at the end of the test.\n\n#include <cstdint>\n#include <limits>\n#include <mutex>  // NOLINT(build/c++11)\n#include <random>\n#include <thread>  // NOLINT(build/c++11)\n#include <type_traits>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/low_level_scheduling.h\"\n#include \"absl/base/internal/scheduling_mode.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/synchronization/blocking_counter.h\"\n#include \"absl/synchronization/notification.h\"\n\nconstexpr uint32_t kNumThreads = 10;\nconstexpr int32_t kIters = 1000;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// This is defined outside of anonymous namespace so that it can be\n// a friend of SpinLock to access protected methods for testing.\nstruct SpinLockTest {\n  static uint32_t EncodeWaitCycles(int64_t wait_start_time,\n                                   int64_t wait_end_time) {\n    return SpinLock::EncodeWaitCycles(wait_start_time, wait_end_time);\n  }\n  static int64_t DecodeWaitCycles(uint32_t lock_value) {\n    return SpinLock::DecodeWaitCycles(lock_value);\n  }\n\n  static bool IsCooperative(const SpinLock& l) { return l.IsCooperative(); }\n};\n\nnamespace {\n\nstatic constexpr size_t kArrayLength = 10;\nstatic uint32_t values[kArrayLength];\n\nABSL_CONST_INIT static SpinLock static_cooperative_spinlock;\nABSL_CONST_INIT static SpinLock static_noncooperative_spinlock(\n    base_internal::SCHEDULE_KERNEL_ONLY);\n\n// Simple integer hash function based on the public domain lookup2 hash.\n// http://burtleburtle.net/bob/c/lookup2.c\nstatic uint32_t Hash32(uint32_t a, uint32_t c) {\n  uint32_t b = 0x9e3779b9UL;  // The golden ratio; an arbitrary value.\n  a -= b;\n  a -= c;\n  a ^= (c >> 13);\n  b -= c;\n  b -= a;\n  b ^= (a << 8);\n  c -= a;\n  c -= b;\n  c ^= (b >> 13);\n  a -= b;\n  a -= c;\n  a ^= (c >> 12);\n  b -= c;\n  b -= a;\n  b ^= (a << 16);\n  c -= a;\n  c -= b;\n  c ^= (b >> 5);\n  a -= b;\n  a -= c;\n  a ^= (c >> 3);\n  b -= c;\n  b -= a;\n  b ^= (a << 10);\n  c -= a;\n  c -= b;\n  c ^= (b >> 15);\n  return c;\n}\n\nstatic void TestFunction(uint32_t thread_salt, SpinLock* spinlock) {\n  for (int i = 0; i < kIters; i++) {\n    SpinLockHolder h(*spinlock);\n    for (size_t j = 0; j < kArrayLength; j++) {\n      const size_t index = (j + thread_salt) % kArrayLength;\n      values[index] = Hash32(values[index], thread_salt);\n      std::this_thread::yield();\n    }\n  }\n}\n\nstatic void ThreadedTest(SpinLock* spinlock) {\n  std::vector<std::thread> threads;\n  threads.reserve(kNumThreads);\n  for (uint32_t i = 0; i < kNumThreads; ++i) {\n    threads.push_back(std::thread(TestFunction, i, spinlock));\n  }\n  for (auto& thread : threads) {\n    thread.join();\n  }\n\n  SpinLockHolder h(*spinlock);\n  for (size_t i = 1; i < kArrayLength; i++) {\n    EXPECT_EQ(values[0], values[i]);\n  }\n}\n\n#ifndef ABSL_HAVE_THREAD_SANITIZER\nstatic_assert(std::is_trivially_destructible<SpinLock>(), \"\");\n#endif\n\nTEST(SpinLock, StackNonCooperativeDisablesScheduling) {\n  SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);\n  SpinLockHolder l(spinlock);\n  EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed());\n}\n\nTEST(SpinLock, StaticNonCooperativeDisablesScheduling) {\n  SpinLockHolder l(static_noncooperative_spinlock);\n  EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed());\n}\n\nTEST(SpinLock, WaitCyclesEncoding) {\n  // These are implementation details not exported by SpinLock.\n  const int kProfileTimestampShift = 7;\n  const int kLockwordReservedShift = 3;\n  const uint32_t kSpinLockSleeper = 8;\n\n  // We should be able to encode up to (1^kMaxCycleBits - 1) without clamping\n  // but the lower kProfileTimestampShift will be dropped.\n  const int kMaxCyclesShift =\n      32 - kLockwordReservedShift + kProfileTimestampShift;\n  const int64_t kMaxCycles = (int64_t{1} << kMaxCyclesShift) - 1;\n\n  // These bits should be zero after encoding.\n  const uint32_t kLockwordReservedMask = (1 << kLockwordReservedShift) - 1;\n\n  // These bits are dropped when wait cycles are encoded.\n  const int64_t kProfileTimestampMask = (1 << kProfileTimestampShift) - 1;\n\n  // Test a bunch of random values\n  std::default_random_engine generator;\n  // Shift to avoid overflow below.\n  std::uniform_int_distribution<int64_t> time_distribution(\n      0, std::numeric_limits<int64_t>::max() >> 3);\n  std::uniform_int_distribution<int64_t> cycle_distribution(0, kMaxCycles);\n\n  for (int i = 0; i < 100; i++) {\n    int64_t start_time = time_distribution(generator);\n    int64_t cycles = cycle_distribution(generator);\n    int64_t end_time = start_time + cycles;\n    uint32_t lock_value = SpinLockTest::EncodeWaitCycles(start_time, end_time);\n    EXPECT_EQ(0u, lock_value & kLockwordReservedMask);\n    int64_t decoded = SpinLockTest::DecodeWaitCycles(lock_value);\n    EXPECT_EQ(0, decoded & kProfileTimestampMask);\n    EXPECT_EQ(cycles & ~kProfileTimestampMask, decoded);\n  }\n\n  // Test corner cases\n  int64_t start_time = time_distribution(generator);\n  EXPECT_EQ(kSpinLockSleeper,\n            SpinLockTest::EncodeWaitCycles(start_time, start_time));\n  EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(0));\n  EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(kLockwordReservedMask));\n  EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask,\n            SpinLockTest::DecodeWaitCycles(~kLockwordReservedMask));\n\n  // Check that we cannot produce kSpinLockSleeper during encoding.\n  int64_t sleeper_cycles = kSpinLockSleeper\n                           << (kProfileTimestampShift - kLockwordReservedShift);\n  uint32_t sleeper_value =\n      SpinLockTest::EncodeWaitCycles(start_time, start_time + sleeper_cycles);\n  EXPECT_NE(sleeper_value, kSpinLockSleeper);\n\n  // Test clamping\n  uint32_t max_value =\n      SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles);\n  int64_t max_value_decoded = SpinLockTest::DecodeWaitCycles(max_value);\n  int64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask;\n  EXPECT_EQ(expected_max_value_decoded, max_value_decoded);\n\n  const int64_t step = (1 << kProfileTimestampShift);\n  uint32_t after_max_value = SpinLockTest::EncodeWaitCycles(\n      start_time, start_time + kMaxCycles + step);\n  int64_t after_max_value_decoded =\n      SpinLockTest::DecodeWaitCycles(after_max_value);\n  EXPECT_EQ(expected_max_value_decoded, after_max_value_decoded);\n\n  uint32_t before_max_value = SpinLockTest::EncodeWaitCycles(\n      start_time, start_time + kMaxCycles - step);\n  int64_t before_max_value_decoded =\n      SpinLockTest::DecodeWaitCycles(before_max_value);\n  EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);\n}\n\nTEST(SpinLockWithThreads, StackSpinLock) {\n  SpinLock spinlock;\n  ThreadedTest(&spinlock);\n}\n\nTEST(SpinLockWithThreads, StackCooperativeSpinLock) {\n  SpinLock spinlock;\n  ThreadedTest(&spinlock);\n}\n\nTEST(SpinLockWithThreads, StackNonCooperativeSpinLock) {\n  SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);\n  ThreadedTest(&spinlock);\n}\n\nTEST(SpinLockWithThreads, StaticCooperativeSpinLock) {\n  ThreadedTest(&static_cooperative_spinlock);\n}\n\nTEST(SpinLockWithThreads, StaticNonCooperativeSpinLock) {\n  ThreadedTest(&static_noncooperative_spinlock);\n}\n\nTEST(SpinLockWithThreads, DoesNotDeadlock) {\n  struct Helper {\n    static void NotifyThenLock(Notification* locked, SpinLock* spinlock,\n                               BlockingCounter* b) {\n      locked->WaitForNotification();  // Wait for LockThenWait() to hold \"s\".\n      b->DecrementCount();\n      SpinLockHolder l(*spinlock);\n    }\n\n    static void LockThenWait(Notification* locked, SpinLock* spinlock,\n                             BlockingCounter* b) {\n      SpinLockHolder l(*spinlock);\n      locked->Notify();\n      b->Wait();\n    }\n\n    static void DeadlockTest(SpinLock* spinlock, int num_spinners) {\n      Notification locked;\n      BlockingCounter counter(num_spinners);\n      std::vector<std::thread> threads;\n\n      threads.push_back(\n          std::thread(Helper::LockThenWait, &locked, spinlock, &counter));\n      for (int i = 0; i < num_spinners; ++i) {\n        threads.push_back(\n            std::thread(Helper::NotifyThenLock, &locked, spinlock, &counter));\n      }\n\n      for (auto& thread : threads) {\n        thread.join();\n      }\n    }\n  };\n\n  int num_threads = base_internal::NumCPUs() * 2;\n  SpinLock stack_cooperative_spinlock;\n  SpinLock stack_noncooperative_spinlock(base_internal::SCHEDULE_KERNEL_ONLY);\n  Helper::DeadlockTest(&stack_cooperative_spinlock, num_threads);\n  Helper::DeadlockTest(&stack_noncooperative_spinlock, num_threads);\n  Helper::DeadlockTest(&static_cooperative_spinlock, num_threads);\n  Helper::DeadlockTest(&static_noncooperative_spinlock, num_threads);\n}\n\nTEST(SpinLockTest, IsCooperative) {\n  SpinLock default_constructor;\n  EXPECT_TRUE(SpinLockTest::IsCooperative(default_constructor));\n\n  SpinLock cooperative;\n  EXPECT_TRUE(SpinLockTest::IsCooperative(cooperative));\n\n  SpinLock kernel_only(base_internal::SCHEDULE_KERNEL_ONLY);\n  EXPECT_FALSE(SpinLockTest::IsCooperative(kernel_only));\n}\n\nTEST(SpinLockTest, ScopedLock) {\n  SpinLock s;\n  std::scoped_lock l(s);\n}\n\n}  // namespace\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/thread_annotations.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: thread_annotations.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains macro definitions for thread safety annotations\n// that allow developers to document the locking policies of multi-threaded\n// code. The annotations can also help program analysis tools to identify\n// potential thread safety issues.\n//\n// These annotations are implemented using compiler attributes. Using the macros\n// defined here instead of raw attributes allow for portability and future\n// compatibility.\n//\n// When referring to mutexes in the arguments of the attributes, you should\n// use variable names or more complex expressions (e.g. my_object->mutex_)\n// that evaluate to a concrete mutex object whenever possible. If the mutex\n// you want to refer to is not in scope, you may use a member pointer\n// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.\n\n#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_\n#define ABSL_BASE_THREAD_ANNOTATIONS_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n// ABSL_GUARDED_BY()\n//\n// Documents if a shared field or global variable needs to be protected by a\n// mutex. ABSL_GUARDED_BY() allows the user to specify a particular mutex that\n// should be held when accessing the annotated variable.\n//\n// Although this annotation (and ABSL_PT_GUARDED_BY, below) cannot be applied to\n// local variables, a local variable and its associated mutex can often be\n// combined into a small class or struct, thereby allowing the annotation.\n//\n// Example:\n//\n//   class Foo {\n//     Mutex mu_;\n//     int p1_ ABSL_GUARDED_BY(mu_);\n//     ...\n//   };\n#if ABSL_HAVE_ATTRIBUTE(guarded_by)\n#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))\n#else\n#define ABSL_GUARDED_BY(x)\n#endif\n\n// ABSL_PT_GUARDED_BY()\n//\n// Documents if the memory location pointed to by a pointer should be guarded\n// by a mutex when dereferencing the pointer.\n//\n// Example:\n//   class Foo {\n//     Mutex mu_;\n//     int *p1_ ABSL_PT_GUARDED_BY(mu_);\n//     ...\n//   };\n//\n// Note that a pointer variable to a shared memory location could itself be a\n// shared variable.\n//\n// Example:\n//\n//   // `q_`, guarded by `mu1_`, points to a shared memory location that is\n//   // guarded by `mu2_`:\n//   int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_);\n#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by)\n#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))\n#else\n#define ABSL_PT_GUARDED_BY(x)\n#endif\n\n// ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()\n//\n// Documents the acquisition order between locks that can be held\n// simultaneously by a thread. For any two locks that need to be annotated\n// to establish an acquisition order, only one of them needs the annotation.\n// (i.e. You don't have to annotate both locks with both ABSL_ACQUIRED_AFTER\n// and ABSL_ACQUIRED_BEFORE.)\n//\n// As with ABSL_GUARDED_BY, this is only applicable to mutexes that are shared\n// fields or global variables.\n//\n// Example:\n//\n//   Mutex m1_;\n//   Mutex m2_ ABSL_ACQUIRED_AFTER(m1_);\n#if ABSL_HAVE_ATTRIBUTE(acquired_after)\n#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))\n#else\n#define ABSL_ACQUIRED_AFTER(...)\n#endif\n\n#if ABSL_HAVE_ATTRIBUTE(acquired_before)\n#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))\n#else\n#define ABSL_ACQUIRED_BEFORE(...)\n#endif\n\n// ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()\n//\n// Documents a function that expects a mutex to be held prior to entry.\n// The mutex is expected to be held both on entry to, and exit from, the\n// function.\n//\n// An exclusive lock allows read-write access to the guarded data member(s), and\n// only one thread can acquire a lock exclusively at any one time. A shared lock\n// allows read-only access, and any number of threads can acquire a shared lock\n// concurrently.\n//\n// Generally, non-const methods should be annotated with\n// ABSL_EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with\n// ABSL_SHARED_LOCKS_REQUIRED.\n//\n// Example:\n//\n//   Mutex mu1, mu2;\n//   int a ABSL_GUARDED_BY(mu1);\n//   int b ABSL_GUARDED_BY(mu2);\n//\n//   void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }\n//   void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }\n#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required)\n#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \\\n  __attribute__((exclusive_locks_required(__VA_ARGS__)))\n#else\n#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)\n#endif\n\n#if ABSL_HAVE_ATTRIBUTE(shared_locks_required)\n#define ABSL_SHARED_LOCKS_REQUIRED(...) \\\n  __attribute__((shared_locks_required(__VA_ARGS__)))\n#else\n#define ABSL_SHARED_LOCKS_REQUIRED(...)\n#endif\n\n// ABSL_LOCKS_EXCLUDED()\n//\n// Documents the locks that cannot be held by callers of this function, as they\n// might be acquired by this function (Abseil's `Mutex` locks are\n// non-reentrant).\n#if ABSL_HAVE_ATTRIBUTE(locks_excluded)\n#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))\n#else\n#define ABSL_LOCKS_EXCLUDED(...)\n#endif\n\n// ABSL_LOCK_RETURNED()\n//\n// Documents a function that returns a mutex without acquiring it.  For example,\n// a public getter method that returns a pointer to a private mutex should\n// be annotated with ABSL_LOCK_RETURNED.\n#if ABSL_HAVE_ATTRIBUTE(lock_returned)\n#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x)))\n#else\n#define ABSL_LOCK_RETURNED(x)\n#endif\n\n// ABSL_LOCKABLE\n//\n// Documents if a class/type is a lockable type (such as the `Mutex` class).\n#if ABSL_HAVE_ATTRIBUTE(lockable)\n#define ABSL_LOCKABLE __attribute__((lockable))\n#else\n#define ABSL_LOCKABLE\n#endif\n\n// ABSL_SCOPED_LOCKABLE\n//\n// Documents if a class does RAII locking (such as the `MutexLock` class).\n// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is\n// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no\n// arguments; the analysis will assume that the destructor unlocks whatever the\n// constructor locked.\n#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)\n#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))\n#else\n#define ABSL_SCOPED_LOCKABLE\n#endif\n\n// ABSL_EXCLUSIVE_LOCK_FUNCTION()\n//\n// Documents functions that acquire a lock in the body of a function, and do\n// not release it.\n#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function)\n#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \\\n  __attribute__((exclusive_lock_function(__VA_ARGS__)))\n#else\n#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)\n#endif\n\n// ABSL_SHARED_LOCK_FUNCTION()\n//\n// Documents functions that acquire a shared (reader) lock in the body of a\n// function, and do not release it.\n#if ABSL_HAVE_ATTRIBUTE(shared_lock_function)\n#define ABSL_SHARED_LOCK_FUNCTION(...) \\\n  __attribute__((shared_lock_function(__VA_ARGS__)))\n#else\n#define ABSL_SHARED_LOCK_FUNCTION(...)\n#endif\n\n// ABSL_UNLOCK_FUNCTION()\n//\n// Documents functions that expect a lock to be held on entry to the function,\n// and release it in the body of the function.\n#if ABSL_HAVE_ATTRIBUTE(unlock_function)\n#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))\n#else\n#define ABSL_UNLOCK_FUNCTION(...)\n#endif\n\n// ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()\n//\n// Documents functions that try to acquire a lock, and return success or failure\n// (or a non-boolean value that can be interpreted as a boolean).\n// The first argument should be `true` for functions that return `true` on\n// success, or `false` for functions that return `false` on success. The second\n// argument specifies the mutex that is locked on success. If unspecified, this\n// mutex is assumed to be `this`.\n#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function)\n#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \\\n  __attribute__((exclusive_trylock_function(__VA_ARGS__)))\n#else\n#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...)\n#endif\n\n#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function)\n#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \\\n  __attribute__((shared_trylock_function(__VA_ARGS__)))\n#else\n#define ABSL_SHARED_TRYLOCK_FUNCTION(...)\n#endif\n\n// ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK()\n//\n// Documents functions that dynamically check to see if a lock is held, and fail\n// if it is not held.\n#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock)\n#define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \\\n  __attribute__((assert_exclusive_lock(__VA_ARGS__)))\n#else\n#define ABSL_ASSERT_EXCLUSIVE_LOCK(...)\n#endif\n\n#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock)\n#define ABSL_ASSERT_SHARED_LOCK(...) \\\n  __attribute__((assert_shared_lock(__VA_ARGS__)))\n#else\n#define ABSL_ASSERT_SHARED_LOCK(...)\n#endif\n\n// ABSL_NO_THREAD_SAFETY_ANALYSIS\n//\n// Turns off thread safety checking within the body of a particular function.\n// This annotation is used to mark functions that are known to be correct, but\n// the locking behavior is more complicated than the analyzer can handle.\n#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis)\n#define ABSL_NO_THREAD_SAFETY_ANALYSIS \\\n  __attribute__((no_thread_safety_analysis))\n#else\n#define ABSL_NO_THREAD_SAFETY_ANALYSIS\n#endif\n\n//------------------------------------------------------------------------------\n// Tool-Supplied Annotations\n//------------------------------------------------------------------------------\n\n// ABSL_TS_UNCHECKED should be placed around lock expressions that are not valid\n// C++ syntax, but which are present for documentation purposes.  These\n// annotations will be ignored by the analysis.\n#define ABSL_TS_UNCHECKED(x) \"\"\n\n// ABSL_TS_FIXME is used to mark lock expressions that are not valid C++ syntax.\n// It is used by automated tools to mark and disable invalid expressions.\n// The annotation should either be fixed, or changed to ABSL_TS_UNCHECKED.\n#define ABSL_TS_FIXME(x) \"\"\n\n// Like ABSL_NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body\n// of a particular function.  However, this attribute is used to mark functions\n// that are incorrect and need to be fixed.  It is used by automated tools to\n// avoid breaking the build when the analysis is updated.\n// Code owners are expected to eventually fix the routine.\n#define ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME ABSL_NO_THREAD_SAFETY_ANALYSIS\n\n// Similar to ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a\n// ABSL_GUARDED_BY annotation that needs to be fixed, because it is producing\n// thread safety warning. It disables the ABSL_GUARDED_BY.\n#define ABSL_GUARDED_BY_FIXME(x)\n\n// Disables warnings for a single read operation.  This can be used to avoid\n// warnings when it is known that the read is not actually involved in a race,\n// but the compiler cannot confirm that.\n#define ABSL_TS_UNCHECKED_READ(x) absl::base_internal::ts_unchecked_read(x)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace base_internal {\n\n// Takes a reference to a guarded data member, and returns an unguarded\n// reference.\n// Do not use this function directly, use ABSL_TS_UNCHECKED_READ instead.\ntemplate <typename T>\ninline const T& ts_unchecked_read(const T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  return v;\n}\n\ntemplate <typename T>\ninline T& ts_unchecked_read(T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  return v;\n}\n\n}  // namespace base_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_THREAD_ANNOTATIONS_H_\n"
  },
  {
    "path": "absl/base/throw_delegate.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/throw_delegate.h\"\n\n#include <cstdlib>\n#include <functional>\n#include <new>\n#include <stdexcept>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nvoid ThrowStdLogicError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::logic_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdLogicError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::logic_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\nvoid ThrowStdInvalidArgument(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::invalid_argument(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdInvalidArgument(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::invalid_argument(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdDomainError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::domain_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdDomainError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::domain_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdLengthError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::length_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdLengthError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::length_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdOutOfRange(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::out_of_range(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdOutOfRange(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::out_of_range(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdRuntimeError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::runtime_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdRuntimeError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::runtime_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdRangeError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::range_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdRangeError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::range_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdOverflowError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::overflow_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdOverflowError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::overflow_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdUnderflowError(const std::string& what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::underflow_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg.c_str());\n  std::abort();\n#endif\n}\nvoid ThrowStdUnderflowError(const char* what_arg) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::underflow_error(what_arg);\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", what_arg);\n  std::abort();\n#endif\n}\n\nvoid ThrowStdBadFunctionCall() {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::bad_function_call();\n#else\n  std::abort();\n#endif\n}\n\nvoid ThrowStdBadAlloc() {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::bad_alloc();\n#else\n  std::abort();\n#endif\n}\n\nvoid ThrowStdBadArrayNewLength() {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw std::bad_array_new_length();\n#else\n  std::abort();\n#endif\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/base/throw_delegate.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_BASE_THROW_DELEGATE_H_\n#define ABSL_BASE_THROW_DELEGATE_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Helper functions that allow throwing exceptions consistently from anywhere.\n// The main use case is for header-based libraries (eg templates), as they will\n// be built by many different targets with their own compiler options.\n// In particular, this will allow a safe way to throw exceptions even if the\n// caller is compiled with -fno-exceptions.  This is intended for implementing\n// things like map<>::at(), which the standard documents as throwing an\n// exception on error.\n//\n// Using other techniques like #if tricks could lead to ODR violations.\n//\n// You shouldn't use it unless you're writing code that you know will be built\n// both with and without exceptions and you need to conform to an interface\n// that uses exceptions.\n\n[[noreturn]] void ThrowStdLogicError(const std::string& what_arg);\n[[noreturn]] void ThrowStdLogicError(const char* what_arg);\n[[noreturn]] void ThrowStdInvalidArgument(const std::string& what_arg);\n[[noreturn]] void ThrowStdInvalidArgument(const char* what_arg);\n[[noreturn]] void ThrowStdDomainError(const std::string& what_arg);\n[[noreturn]] void ThrowStdDomainError(const char* what_arg);\n[[noreturn]] void ThrowStdLengthError(const std::string& what_arg);\n[[noreturn]] void ThrowStdLengthError(const char* what_arg);\n[[noreturn]] void ThrowStdOutOfRange(const std::string& what_arg);\n[[noreturn]] void ThrowStdOutOfRange(const char* what_arg);\n[[noreturn]] void ThrowStdRuntimeError(const std::string& what_arg);\n[[noreturn]] void ThrowStdRuntimeError(const char* what_arg);\n[[noreturn]] void ThrowStdRangeError(const std::string& what_arg);\n[[noreturn]] void ThrowStdRangeError(const char* what_arg);\n[[noreturn]] void ThrowStdOverflowError(const std::string& what_arg);\n[[noreturn]] void ThrowStdOverflowError(const char* what_arg);\n[[noreturn]] void ThrowStdUnderflowError(const std::string& what_arg);\n[[noreturn]] void ThrowStdUnderflowError(const char* what_arg);\n\n[[noreturn]] void ThrowStdBadFunctionCall();\n[[noreturn]] void ThrowStdBadAlloc();\n[[noreturn]] void ThrowStdBadArrayNewLength();\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_BASE_THROW_DELEGATE_H_\n"
  },
  {
    "path": "absl/base/throw_delegate_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/throw_delegate.h\"\n\n#include <functional>\n#include <new>\n#include <stdexcept>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace {\n\nusing absl::ThrowStdBadAlloc;\nusing absl::ThrowStdBadArrayNewLength;\nusing absl::ThrowStdBadFunctionCall;\nusing absl::ThrowStdDomainError;\nusing absl::ThrowStdInvalidArgument;\nusing absl::ThrowStdLengthError;\nusing absl::ThrowStdLogicError;\nusing absl::ThrowStdOutOfRange;\nusing absl::ThrowStdOverflowError;\nusing absl::ThrowStdRangeError;\nusing absl::ThrowStdRuntimeError;\nusing absl::ThrowStdUnderflowError;\n\nconstexpr const char* what_arg = \"The quick brown fox jumps over the lazy dog\";\n\ntemplate <typename E>\nvoid ExpectThrowChar(void (*f)(const char*)) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  try {\n    f(what_arg);\n    FAIL() << \"Didn't throw\";\n  } catch (const E& e) {\n    EXPECT_STREQ(e.what(), what_arg);\n  }\n#else\n  EXPECT_DEATH_IF_SUPPORTED(f(what_arg), what_arg);\n#endif\n}\n\ntemplate <typename E>\nvoid ExpectThrowString(void (*f)(const std::string&)) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  try {\n    f(what_arg);\n    FAIL() << \"Didn't throw\";\n  } catch (const E& e) {\n    EXPECT_STREQ(e.what(), what_arg);\n  }\n#else\n  EXPECT_DEATH_IF_SUPPORTED(f(what_arg), what_arg);\n#endif\n}\n\ntemplate <typename E>\nvoid ExpectThrowNoWhat(void (*f)()) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  try {\n    f();\n    FAIL() << \"Didn't throw\";\n  } catch (const E& e) {\n  }\n#else\n  EXPECT_DEATH_IF_SUPPORTED(f(), \"\");\n#endif\n}\n\nTEST(ThrowDelegate, ThrowStdLogicErrorChar) {\n  ExpectThrowChar<std::logic_error>(ThrowStdLogicError);\n}\n\nTEST(ThrowDelegate, ThrowStdInvalidArgumentChar) {\n  ExpectThrowChar<std::invalid_argument>(ThrowStdInvalidArgument);\n}\n\nTEST(ThrowDelegate, ThrowStdDomainErrorChar) {\n  ExpectThrowChar<std::domain_error>(ThrowStdDomainError);\n}\n\nTEST(ThrowDelegate, ThrowStdLengthErrorChar) {\n  ExpectThrowChar<std::length_error>(ThrowStdLengthError);\n}\n\nTEST(ThrowDelegate, ThrowStdOutOfRangeChar) {\n  ExpectThrowChar<std::out_of_range>(ThrowStdOutOfRange);\n}\n\nTEST(ThrowDelegate, ThrowStdRuntimeErrorChar) {\n  ExpectThrowChar<std::runtime_error>(ThrowStdRuntimeError);\n}\n\nTEST(ThrowDelegate, ThrowStdRangeErrorChar) {\n  ExpectThrowChar<std::range_error>(ThrowStdRangeError);\n}\n\nTEST(ThrowDelegate, ThrowStdOverflowErrorChar) {\n  ExpectThrowChar<std::overflow_error>(ThrowStdOverflowError);\n}\n\nTEST(ThrowDelegate, ThrowStdUnderflowErrorChar) {\n  ExpectThrowChar<std::underflow_error>(ThrowStdUnderflowError);\n}\n\nTEST(ThrowDelegate, ThrowStdLogicErrorString) {\n  ExpectThrowString<std::logic_error>(ThrowStdLogicError);\n}\n\nTEST(ThrowDelegate, ThrowStdInvalidArgumentString) {\n  ExpectThrowString<std::invalid_argument>(ThrowStdInvalidArgument);\n}\n\nTEST(ThrowDelegate, ThrowStdDomainErrorString) {\n  ExpectThrowString<std::domain_error>(ThrowStdDomainError);\n}\n\nTEST(ThrowDelegate, ThrowStdLengthErrorString) {\n  ExpectThrowString<std::length_error>(ThrowStdLengthError);\n}\n\nTEST(ThrowDelegate, ThrowStdOutOfRangeString) {\n  ExpectThrowString<std::out_of_range>(ThrowStdOutOfRange);\n}\n\nTEST(ThrowDelegate, ThrowStdRuntimeErrorString) {\n  ExpectThrowString<std::runtime_error>(ThrowStdRuntimeError);\n}\n\nTEST(ThrowDelegate, ThrowStdRangeErrorString) {\n  ExpectThrowString<std::range_error>(ThrowStdRangeError);\n}\n\nTEST(ThrowDelegate, ThrowStdOverflowErrorString) {\n  ExpectThrowString<std::overflow_error>(ThrowStdOverflowError);\n}\n\nTEST(ThrowDelegate, ThrowStdUnderflowErrorString) {\n  ExpectThrowString<std::underflow_error>(ThrowStdUnderflowError);\n}\n\nTEST(ThrowDelegate, ThrowStdBadFunctionCallNoWhat) {\n  ExpectThrowNoWhat<std::bad_function_call>(ThrowStdBadFunctionCall);\n}\n\nTEST(ThrowDelegate, ThrowStdBadAllocNoWhat) {\n  ExpectThrowNoWhat<std::bad_alloc>(ThrowStdBadAlloc);\n}\n\nTEST(ThrowDelegate, ThrowStdBadArrayNewLength) {\n  ExpectThrowNoWhat<std::bad_array_new_length>(ThrowStdBadArrayNewLength);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/cleanup/BUILD.bazel",
    "content": "# Copyright 2021 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"cleanup_internal\",\n    hdrs = [\"internal/cleanup.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:core_headers\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"cleanup\",\n    hdrs = [\n        \"cleanup.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":cleanup_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"cleanup_test\",\n    size = \"small\",\n    srcs = [\n        \"cleanup_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":cleanup\",\n        \"//absl/base:config\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/cleanup/CMakeLists.txt",
    "content": "# Copyright 2021 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cleanup_internal\n  HDRS\n    \"internal/cleanup.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::core_headers\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    cleanup\n  HDRS\n    \"cleanup.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::cleanup_internal\n    absl::config\n    absl::core_headers\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    cleanup_test\n  SRCS\n    \"cleanup_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::cleanup\n    absl::config\n    absl::utility\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/cleanup/cleanup.h",
    "content": "// Copyright 2021 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: cleanup.h\n// -----------------------------------------------------------------------------\n//\n// `absl::Cleanup` implements the scope guard idiom, invoking the contained\n// callback's `operator()() &&` on scope exit.\n//\n// This class doesn't allocate or take any locks, and is safe to use in a signal\n// handler. Of course the callback with which it is constructed also must be\n// signal safe in order for this to be useful.\n//\n// Example:\n//\n// ```\n//   absl::Status CopyGoodData(const char* source_path, const char* sink_path) {\n//     FILE* source_file = fopen(source_path, \"r\");\n//     if (source_file == nullptr) {\n//       return absl::NotFoundError(\"No source file\");  // No cleanups execute\n//     }\n//\n//     // C++17 style cleanup using class template argument deduction\n//     absl::Cleanup source_closer = [source_file] { fclose(source_file); };\n//\n//     FILE* sink_file = fopen(sink_path, \"w\");\n//     if (sink_file == nullptr) {\n//       return absl::NotFoundError(\"No sink file\");  // First cleanup executes\n//     }\n//\n//     // C++11 style cleanup using the factory function\n//     auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });\n//\n//     Data data;\n//     while (ReadData(source_file, &data)) {\n//       if (!data.IsGood()) {\n//         absl::Status result = absl::FailedPreconditionError(\"Read bad data\");\n//         return result;  // Both cleanups execute\n//       }\n//       SaveData(sink_file, &data);\n//     }\n//\n//     return absl::OkStatus();  // Both cleanups execute\n//   }\n// ```\n//\n// Methods:\n//\n// `std::move(cleanup).Cancel()` will prevent the callback from executing.\n//\n// `std::move(cleanup).Invoke()` will execute the callback early, before\n// destruction, and prevent the callback from executing in the destructor.\n//\n// Usage:\n//\n// `absl::Cleanup` is not an interface type. It is only intended to be used\n// within the body of a function. It is not a value type and instead models a\n// control flow construct. Check out `defer` in Golang for something similar.\n\n#ifndef ABSL_CLEANUP_CLEANUP_H_\n#define ABSL_CLEANUP_CLEANUP_H_\n\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/cleanup/internal/cleanup.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename Arg, typename Callback = void()>\nclass [[nodiscard]] Cleanup final {\n  static_assert(cleanup_internal::WasDeduced<Arg>(),\n                \"Explicit template parameters are not supported.\");\n\n  static_assert(cleanup_internal::ReturnsVoid<Callback>(),\n                \"Callbacks that return values are not supported.\");\n\n public:\n  Cleanup(Callback callback) : storage_(std::move(callback)) {}  // NOLINT\n\n  Cleanup(Cleanup&& other) = default;\n\n  void Cancel() && {\n    ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());\n    storage_.DestroyCallback();\n  }\n\n  void Invoke() && {\n    ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());\n    storage_.InvokeCallback();\n    storage_.DestroyCallback();\n  }\n\n  ~Cleanup() {\n    if (storage_.IsCallbackEngaged()) {\n      storage_.InvokeCallback();\n      storage_.DestroyCallback();\n    }\n  }\n\n private:\n  cleanup_internal::Storage<Callback> storage_;\n};\n\n// `absl::Cleanup c = /* callback */;`\n//\n// C++17 type deduction API for creating an instance of `absl::Cleanup`\ntemplate <typename Callback>\nCleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;\n\n// `auto c = absl::MakeCleanup(/* callback */);`\n//\n// C++11 type deduction API for creating an instance of `absl::Cleanup`\ntemplate <typename... Args, typename Callback>\nabsl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {\n  static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),\n                \"Explicit template parameters are not supported.\");\n\n  static_assert(cleanup_internal::ReturnsVoid<Callback>(),\n                \"Callbacks that return values are not supported.\");\n\n  return {std::move(callback)};\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CLEANUP_CLEANUP_H_\n"
  },
  {
    "path": "absl/cleanup/cleanup_test.cc",
    "content": "// Copyright 2021 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/cleanup/cleanup.h\"\n\n#include <functional>\n#include <type_traits>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace {\n\nusing Tag = absl::cleanup_internal::Tag;\n\ntemplate <typename Type1, typename Type2>\nconstexpr bool IsSame() {\n  return (std::is_same<Type1, Type2>::value);\n}\n\nstruct IdentityFactory {\n  template <typename Callback>\n  static Callback AsCallback(Callback callback) {\n    return Callback(std::move(callback));\n  }\n};\n\n// `FunctorClass` is a type used for testing `absl::Cleanup`. It is intended to\n// represent users that make their own move-only callback types outside of\n// `std::function` and lambda literals.\nclass FunctorClass {\n  using Callback = std::function<void()>;\n\n public:\n  explicit FunctorClass(Callback callback) : callback_(std::move(callback)) {}\n\n  FunctorClass(FunctorClass&& other)\n      : callback_(std::exchange(other.callback_, Callback())) {}\n\n  FunctorClass(const FunctorClass&) = delete;\n\n  FunctorClass& operator=(const FunctorClass&) = delete;\n\n  FunctorClass& operator=(FunctorClass&&) = delete;\n\n  void operator()() const& = delete;\n\n  void operator()() && {\n    ASSERT_TRUE(callback_);\n    callback_();\n    callback_ = nullptr;\n  }\n\n private:\n  Callback callback_;\n};\n\nstruct FunctorClassFactory {\n  template <typename Callback>\n  static FunctorClass AsCallback(Callback callback) {\n    return FunctorClass(std::move(callback));\n  }\n};\n\nstruct StdFunctionFactory {\n  template <typename Callback>\n  static std::function<void()> AsCallback(Callback callback) {\n    return std::function<void()>(std::move(callback));\n  }\n};\n\nusing CleanupTestParams =\n    ::testing::Types<IdentityFactory, FunctorClassFactory, StdFunctionFactory>;\ntemplate <typename>\nstruct CleanupTest : public ::testing::Test {};\nTYPED_TEST_SUITE(CleanupTest, CleanupTestParams);\n\nbool fn_ptr_called = false;\nvoid FnPtrFunction() { fn_ptr_called = true; }\n\nTYPED_TEST(CleanupTest, FactoryProducesCorrectType) {\n  {\n    auto callback = TypeParam::AsCallback([] {});\n    auto cleanup = absl::MakeCleanup(std::move(callback));\n\n    static_assert(\n        IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),\n        \"\");\n  }\n\n  {\n    auto cleanup = absl::MakeCleanup(&FnPtrFunction);\n\n    static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),\n                  \"\");\n  }\n\n  {\n    auto cleanup = absl::MakeCleanup(FnPtrFunction);\n\n    static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),\n                  \"\");\n  }\n}\n\nTYPED_TEST(CleanupTest, CTADProducesCorrectType) {\n  {\n    auto callback = TypeParam::AsCallback([] {});\n    absl::Cleanup cleanup = std::move(callback);\n\n    static_assert(\n        IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),\n        \"\");\n  }\n\n  {\n    absl::Cleanup cleanup = &FnPtrFunction;\n\n    static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),\n                  \"\");\n  }\n\n  {\n    absl::Cleanup cleanup = FnPtrFunction;\n\n    static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),\n                  \"\");\n  }\n}\n\nTYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {\n  {\n    auto callback = IdentityFactory::AsCallback([] {});\n    auto factory_cleanup = absl::MakeCleanup(callback);\n    absl::Cleanup deduction_cleanup = callback;\n\n    static_assert(\n        IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), \"\");\n  }\n\n  {\n    auto factory_cleanup =\n        absl::MakeCleanup(FunctorClassFactory::AsCallback([] {}));\n    absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {});\n\n    static_assert(\n        IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), \"\");\n  }\n\n  {\n    auto factory_cleanup =\n        absl::MakeCleanup(StdFunctionFactory::AsCallback([] {}));\n    absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {});\n\n    static_assert(\n        IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), \"\");\n  }\n\n  {\n    auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction);\n    absl::Cleanup deduction_cleanup = &FnPtrFunction;\n\n    static_assert(\n        IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), \"\");\n  }\n\n  {\n    auto factory_cleanup = absl::MakeCleanup(FnPtrFunction);\n    absl::Cleanup deduction_cleanup = FnPtrFunction;\n\n    static_assert(\n        IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), \"\");\n  }\n}\n\nTYPED_TEST(CleanupTest, BasicUsage) {\n  bool called = false;\n\n  {\n    auto cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));\n    EXPECT_FALSE(called);  // Constructor shouldn't invoke the callback\n  }\n\n  EXPECT_TRUE(called);  // Destructor should invoke the callback\n}\n\nTYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) {\n  fn_ptr_called = false;\n\n  {\n    auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction));\n    EXPECT_FALSE(fn_ptr_called);  // Constructor shouldn't invoke the callback\n  }\n\n  EXPECT_TRUE(fn_ptr_called);  // Destructor should invoke the callback\n}\n\nTYPED_TEST(CleanupTest, Cancel) {\n  bool called = false;\n\n  {\n    auto cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));\n    EXPECT_FALSE(called);  // Constructor shouldn't invoke the callback\n\n    std::move(cleanup).Cancel();\n    EXPECT_FALSE(called);  // Cancel shouldn't invoke the callback\n  }\n\n  EXPECT_FALSE(called);  // Destructor shouldn't invoke the callback\n}\n\nTYPED_TEST(CleanupTest, Invoke) {\n  bool called = false;\n\n  {\n    auto cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));\n    EXPECT_FALSE(called);  // Constructor shouldn't invoke the callback\n\n    std::move(cleanup).Invoke();\n    EXPECT_TRUE(called);  // Invoke should invoke the callback\n\n    called = false;  // Reset tracker before destructor runs\n  }\n\n  EXPECT_FALSE(called);  // Destructor shouldn't invoke the callback\n}\n\nTYPED_TEST(CleanupTest, Move) {\n  bool called = false;\n\n  {\n    auto moved_from_cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));\n    EXPECT_FALSE(called);  // Constructor shouldn't invoke the callback\n\n    {\n      auto moved_to_cleanup = std::move(moved_from_cleanup);\n      EXPECT_FALSE(called);  // Move shouldn't invoke the callback\n    }\n\n    EXPECT_TRUE(called);  // Destructor should invoke the callback\n\n    called = false;  // Reset tracker before destructor runs\n  }\n\n  EXPECT_FALSE(called);  // Destructor shouldn't invoke the callback\n}\n\nint DestructionCount = 0;\n\nstruct DestructionCounter {\n  void operator()() {}\n\n  ~DestructionCounter() { ++DestructionCount; }\n};\n\nTYPED_TEST(CleanupTest, DestructorDestroys) {\n  {\n    auto cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));\n    DestructionCount = 0;\n  }\n\n  EXPECT_EQ(DestructionCount, 1);  // Engaged cleanup destroys\n}\n\nTYPED_TEST(CleanupTest, CancelDestroys) {\n  {\n    auto cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));\n    DestructionCount = 0;\n\n    std::move(cleanup).Cancel();\n    EXPECT_EQ(DestructionCount, 1);  // Cancel destroys\n  }\n\n  EXPECT_EQ(DestructionCount, 1);  // Canceled cleanup does not double destroy\n}\n\nTYPED_TEST(CleanupTest, InvokeDestroys) {\n  {\n    auto cleanup =\n        absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));\n    DestructionCount = 0;\n\n    std::move(cleanup).Invoke();\n    EXPECT_EQ(DestructionCount, 1);  // Invoke destroys\n  }\n\n  EXPECT_EQ(DestructionCount, 1);  // Invoked cleanup does not double destroy\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/cleanup/internal/cleanup.h",
    "content": "// Copyright 2021 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CLEANUP_INTERNAL_CLEANUP_H_\n#define ABSL_CLEANUP_INTERNAL_CLEANUP_H_\n\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/macros.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace cleanup_internal {\n\nstruct Tag {};\n\ntemplate <typename Arg, typename... Args>\nconstexpr bool WasDeduced() {\n  return (std::is_same<cleanup_internal::Tag, Arg>::value) &&\n         (sizeof...(Args) == 0);\n}\n\ntemplate <typename Callback>\nconstexpr bool ReturnsVoid() {\n  return (std::is_same<std::invoke_result_t<Callback>, void>::value);\n}\n\ntemplate <typename Callback>\nclass Storage {\n public:\n  Storage() = delete;\n\n  explicit Storage(Callback callback) {\n    // Placement-new into a character buffer is used for eager destruction when\n    // the cleanup is invoked or cancelled. To ensure this optimizes well, the\n    // behavior is implemented locally instead of using a std::optional.\n    ::new (GetCallbackBuffer()) Callback(std::move(callback));\n    is_callback_engaged_ = true;\n  }\n\n  Storage(Storage&& other) {\n    ABSL_HARDENING_ASSERT(other.IsCallbackEngaged());\n\n    ::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback()));\n    is_callback_engaged_ = true;\n\n    other.DestroyCallback();\n  }\n\n  Storage(const Storage& other) = delete;\n\n  Storage& operator=(Storage&& other) = delete;\n\n  Storage& operator=(const Storage& other) = delete;\n\n  void* GetCallbackBuffer() { return static_cast<void*>(callback_buffer_); }\n\n  Callback& GetCallback() {\n    return *reinterpret_cast<Callback*>(GetCallbackBuffer());\n  }\n\n  bool IsCallbackEngaged() const { return is_callback_engaged_; }\n\n  void DestroyCallback() {\n    is_callback_engaged_ = false;\n    GetCallback().~Callback();\n  }\n\n  void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {\n    std::move(GetCallback())();\n  }\n\n private:\n  bool is_callback_engaged_;\n  alignas(Callback) unsigned char callback_buffer_[sizeof(Callback)];\n};\n\n}  // namespace cleanup_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CLEANUP_INTERNAL_CLEANUP_H_\n"
  },
  {
    "path": "absl/container/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"compressed_tuple\",\n    hdrs = [\"internal/compressed_tuple.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"compressed_tuple_test\",\n    srcs = [\"internal/compressed_tuple_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":compressed_tuple\",\n        \":test_instance_tracker\",\n        \"//absl/memory\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"fixed_array\",\n    hdrs = [\"fixed_array.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":compressed_tuple\",\n        \"//absl/algorithm\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:iterator_traits_internal\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/hash:weakly_mixed_integer\",\n        \"//absl/memory\",\n    ],\n)\n\ncc_test(\n    name = \"fixed_array_test\",\n    srcs = [\"fixed_array_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fixed_array\",\n        \":test_allocator\",\n        \"//absl/base:config\",\n        \"//absl/base:exception_testing\",\n        \"//absl/base:iterator_traits_test_helper\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/memory\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"fixed_array_exception_safety_test\",\n    srcs = [\"fixed_array_exception_safety_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fixed_array\",\n        \"//absl/base:config\",\n        \"//absl/base:exception_safety_testing\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"fixed_array_benchmark\",\n    testonly = True,\n    srcs = [\"fixed_array_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS + [\"$(STACK_FRAME_UNLIMITED)\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":fixed_array\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"inlined_vector_internal\",\n    hdrs = [\"internal/inlined_vector.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":compressed_tuple\",\n        \"//absl/base:base_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"inlined_vector\",\n    hdrs = [\"inlined_vector.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":inlined_vector_internal\",\n        \"//absl/algorithm\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:iterator_traits_internal\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/hash:weakly_mixed_integer\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"test_allocator\",\n    testonly = True,\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    textual_hdrs = [\"internal/test_allocator.h\"],\n    visibility = [\"//visibility:private\"],\n)\n\ncc_test(\n    name = \"inlined_vector_test\",\n    srcs = [\"inlined_vector_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":inlined_vector\",\n        \":test_allocator\",\n        \":test_instance_tracker\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:exception_testing\",\n        \"//absl/base:iterator_traits_test_helper\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/log:check\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"inlined_vector_benchmark\",\n    testonly = True,\n    srcs = [\"inlined_vector_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":inlined_vector\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"inlined_vector_exception_safety_test\",\n    srcs = [\"inlined_vector_exception_safety_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":inlined_vector\",\n        \"//absl/base:config\",\n        \"//absl/base:exception_safety_testing\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"test_instance_tracker\",\n    testonly = True,\n    srcs = [\"internal/test_instance_tracker.cc\"],\n    hdrs = [\"internal/test_instance_tracker.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\"//absl/types:compare\"],\n)\n\ncc_test(\n    name = \"test_instance_tracker_test\",\n    srcs = [\"internal/test_instance_tracker_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":test_instance_tracker\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\nNOTEST_TAGS_MOBILE = [\n    \"no_test_android_arm\",\n    \"no_test_android_arm64\",\n    \"no_test_android_x86\",\n    \"no_test_ios_x86_64\",\n]\n\ncc_library(\n    name = \"flat_hash_map\",\n    hdrs = [\"flat_hash_map.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container_memory\",\n        \":hash_container_defaults\",\n        \":raw_hash_map\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"flat_hash_map_test\",\n    srcs = [\"flat_hash_map_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":flat_hash_map\",\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \":test_allocator\",\n        \":unordered_map_constructor_test\",\n        \":unordered_map_lookup_test\",\n        \":unordered_map_members_test\",\n        \":unordered_map_modifiers_test\",\n        \"//absl/base:config\",\n        \"//absl/log:check\",\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"flat_hash_set\",\n    hdrs = [\"flat_hash_set.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container_memory\",\n        \":hash_container_defaults\",\n        \":raw_hash_set\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:core_headers\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"flat_hash_set_test\",\n    srcs = [\"flat_hash_set_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":container_memory\",\n        \":flat_hash_set\",\n        \":hash_container_defaults\",\n        \":hash_generator_testing\",\n        \":test_allocator\",\n        \":unordered_set_constructor_test\",\n        \":unordered_set_lookup_test\",\n        \":unordered_set_members_test\",\n        \":unordered_set_modifiers_test\",\n        \"//absl/base:config\",\n        \"//absl/hash\",\n        \"//absl/log:check\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"node_hash_map\",\n    hdrs = [\"node_hash_map.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container_memory\",\n        \":hash_container_defaults\",\n        \":node_slot_policy\",\n        \":raw_hash_map\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:core_headers\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"node_hash_map_test\",\n    srcs = [\"node_hash_map_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":hash_policy_testing\",\n        \":node_hash_map\",\n        \":tracked\",\n        \":unordered_map_constructor_test\",\n        \":unordered_map_lookup_test\",\n        \":unordered_map_members_test\",\n        \":unordered_map_modifiers_test\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"node_hash_set\",\n    hdrs = [\"node_hash_set.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container_memory\",\n        \":hash_container_defaults\",\n        \":node_slot_policy\",\n        \":raw_hash_set\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:core_headers\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"node_hash_set_test\",\n    srcs = [\"node_hash_set_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \":node_hash_set\",\n        \":unordered_set_constructor_test\",\n        \":unordered_set_lookup_test\",\n        \":unordered_set_members_test\",\n        \":unordered_set_modifiers_test\",\n        \"//absl/base:config\",\n        \"//absl/memory\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"container_memory\",\n    hdrs = [\"internal/container_memory.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/hash\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"container_memory_test\",\n    srcs = [\"internal/container_memory_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":container_memory\",\n        \":test_instance_tracker\",\n        \"//absl/base:config\",\n        \"//absl/base:no_destructor\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"hash_function_defaults\",\n    hdrs = [\"internal/hash_function_defaults.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":common\",\n        \"//absl/base:config\",\n        \"//absl/hash\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n    ],\n)\n\ncc_library(\n    name = \"hash_container_defaults\",\n    hdrs = [\"hash_container_defaults.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hash_function_defaults\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"hash_function_defaults_test\",\n    srcs = [\"internal/hash_function_defaults_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = NOTEST_TAGS_MOBILE + [\"no_test_loonix\"],\n    deps = [\n        \":flat_hash_map\",\n        \":flat_hash_set\",\n        \":hash_function_defaults\",\n        \"//absl/hash\",\n        \"//absl/random\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n        \"//absl/strings:cord_test_helpers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"hash_generator_testing\",\n    testonly = True,\n    srcs = [\"internal/hash_generator_testing.cc\"],\n    hdrs = [\"internal/hash_generator_testing.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hash_policy_testing\",\n        \"//absl/base:config\",\n        \"//absl/base:no_destructor\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/random\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"hash_policy_testing\",\n    testonly = True,\n    hdrs = [\"internal/hash_policy_testing.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/hash\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_test(\n    name = \"hash_policy_testing_test\",\n    srcs = [\"internal/hash_policy_testing_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hash_policy_testing\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"hash_policy_traits\",\n    hdrs = [\"internal/hash_policy_traits.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":common_policy_traits\",\n        \":container_memory\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"hash_policy_traits_test\",\n    srcs = [\"internal/hash_policy_traits_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container_memory\",\n        \":hash_policy_traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"common_policy_traits\",\n    hdrs = [\"internal/common_policy_traits.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\"//absl/meta:type_traits\"],\n)\n\ncc_test(\n    name = \"common_policy_traits_test\",\n    srcs = [\"internal/common_policy_traits_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":common_policy_traits\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"hashtable_debug\",\n    hdrs = [\"internal/hashtable_debug.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hashtable_debug_hooks\",\n    ],\n)\n\ncc_library(\n    name = \"hashtable_debug_hooks\",\n    hdrs = [\"internal/hashtable_debug_hooks.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"hashtablez_sampler\",\n    srcs = [\n        \"internal/hashtablez_sampler.cc\",\n        \"internal/hashtablez_sampler_force_weak_definition.cc\",\n    ],\n    hdrs = [\"internal/hashtablez_sampler.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/debugging:stacktrace\",\n        \"//absl/memory\",\n        \"//absl/profiling:exponential_biased\",\n        \"//absl/profiling:sample_recorder\",\n        \"//absl/synchronization\",\n        \"//absl/time\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"hashtablez_sampler_test\",\n    srcs = [\"internal/hashtablez_sampler_test.cc\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":hashtablez_sampler\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/profiling:sample_recorder\",\n        \"//absl/random\",\n        \"//absl/synchronization\",\n        \"//absl/synchronization:thread_pool\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"node_slot_policy\",\n    hdrs = [\"internal/node_slot_policy.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\"//absl/base:config\"],\n)\n\ncc_test(\n    name = \"node_slot_policy_test\",\n    srcs = [\"internal/node_slot_policy_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hash_policy_traits\",\n        \":node_slot_policy\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hash_map\",\n    hdrs = [\"internal/raw_hash_map.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":common_policy_traits\",\n        \":container_memory\",\n        \":raw_hash_set\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"common\",\n    hdrs = [\"internal/common.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/meta:type_traits\",\n        \"//absl/types:optional\",\n    ],\n)\n\ncc_library(\n    name = \"hashtable_control_bytes\",\n    hdrs = [\"internal/hashtable_control_bytes.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_test(\n    name = \"hashtable_control_bytes_test\",\n    srcs = [\"internal/hashtable_control_bytes_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hashtable_control_bytes\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hash_set_resize_impl\",\n    hdrs = [\"internal/raw_hash_set_resize_impl.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\"//absl/base:config\"],\n)\n\ncc_test(\n    name = \"raw_hash_set_resize_impl_test\",\n    srcs = [\"internal/raw_hash_set_resize_impl_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":raw_hash_set_resize_impl\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hash_set\",\n    srcs = [\"internal/raw_hash_set.cc\"],\n    hdrs = [\"internal/raw_hash_set.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":common\",\n        \":common_policy_traits\",\n        \":compressed_tuple\",\n        \":container_memory\",\n        \":hash_function_defaults\",\n        \":hash_policy_traits\",\n        \":hashtable_control_bytes\",\n        \":hashtable_debug_hooks\",\n        \":hashtablez_sampler\",\n        \":raw_hash_set_resize_impl\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:endian\",\n        \"//absl/base:iterator_traits_internal\",\n        \"//absl/base:prefetch\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/functional:function_ref\",\n        \"//absl/hash\",\n        \"//absl/hash:weakly_mixed_integer\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"raw_hash_set_test\",\n    srcs = [\"internal/raw_hash_set_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkstatic = 1,\n    tags = NOTEST_TAGS_MOBILE + [\n        \"no_test_chromiumos_arm\",\n        \"no_test_chromiumos_armv7\",\n        \"no_test_chromiumos_x86_64\",\n        \"no_test_loonix\",\n        # TODO(b/237097643): investigate race and remove\n        \"noarm_gemu\",\n    ],\n    deps = [\n        \":container_memory\",\n        \":flat_hash_map\",\n        \":flat_hash_set\",\n        \":hash_function_defaults\",\n        \":hash_policy_testing\",\n        \":hashtable_control_bytes\",\n        \":hashtable_debug\",\n        \":hashtablez_sampler\",\n        \":node_hash_set\",\n        \":raw_hash_set\",\n        \":raw_hash_set_resize_impl\",\n        \":test_allocator\",\n        \":test_instance_tracker\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:prefetch\",\n        \"//absl/functional:function_ref\",\n        \"//absl/hash\",\n        \"//absl/log\",\n        \"//absl/log:check\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:int128\",\n        \"//absl/random\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"raw_hash_set_benchmark\",\n    testonly = True,\n    srcs = [\"internal/raw_hash_set_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":container_memory\",\n        \":hash_function_defaults\",\n        \":raw_hash_set\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/random\",\n        \"//absl/strings:str_format\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_binary(\n    name = \"raw_hash_set_probe_benchmark\",\n    testonly = True,\n    srcs = [\"internal/raw_hash_set_probe_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = select({\n        \"//conditions:default\": [],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":flat_hash_map\",\n        \":hash_function_defaults\",\n        \":hashtable_debug\",\n        \":raw_hash_set\",\n        \"//absl/base:no_destructor\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n    ],\n)\n\ncc_test(\n    name = \"raw_hash_set_allocator_test\",\n    size = \"small\",\n    srcs = [\"internal/raw_hash_set_allocator_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container_memory\",\n        \":raw_hash_set\",\n        \":tracked\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"layout\",\n    hdrs = [\"internal/layout.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/debugging:demangle_internal\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/types:span\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"layout_test\",\n    size = \"small\",\n    srcs = [\"internal/layout_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = NOTEST_TAGS_MOBILE + [\"no_test_loonix\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":layout\",\n        \"//absl/base:config\",\n        \"//absl/log:check\",\n        \"//absl/types:span\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"layout_benchmark\",\n    testonly = True,\n    srcs = [\"internal/layout_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":layout\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"tracked\",\n    testonly = True,\n    hdrs = [\"internal/tracked.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_map_constructor_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_map_constructor_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_map_lookup_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_map_lookup_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_map_modifiers_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_map_modifiers_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_set_constructor_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_set_constructor_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_set_members_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_set_members_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_map_members_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_map_members_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_set_lookup_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_set_lookup_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"unordered_set_modifiers_test\",\n    testonly = True,\n    hdrs = [\"internal/unordered_set_modifiers_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \":hash_generator_testing\",\n        \":hash_policy_testing\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"unordered_set_test\",\n    srcs = [\"internal/unordered_set_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":unordered_set_constructor_test\",\n        \":unordered_set_lookup_test\",\n        \":unordered_set_members_test\",\n        \":unordered_set_modifiers_test\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"unordered_map_test\",\n    srcs = [\"internal/unordered_map_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    deps = [\n        \":unordered_map_constructor_test\",\n        \":unordered_map_lookup_test\",\n        \":unordered_map_members_test\",\n        \":unordered_map_modifiers_test\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"sample_element_size_test\",\n    srcs = [\"sample_element_size_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_loonix\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":flat_hash_map\",\n        \":flat_hash_set\",\n        \":hashtablez_sampler\",\n        \":node_hash_map\",\n        \":node_hash_set\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"btree\",\n    srcs = [\n        \"internal/btree.h\",\n        \"internal/btree_container.h\",\n    ],\n    hdrs = [\n        \"btree_map.h\",\n        \"btree_set.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":common\",\n        \":common_policy_traits\",\n        \":compressed_tuple\",\n        \":container_memory\",\n        \":layout\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/hash:weakly_mixed_integer\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n        \"//absl/types:compare\",\n    ],\n)\n\ncc_library(\n    name = \"btree_test_common\",\n    testonly = True,\n    hdrs = [\"btree_test.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":btree\",\n        \":flat_hash_set\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n        \"//absl/time\",\n    ],\n)\n\ncc_test(\n    name = \"btree_test\",\n    size = \"large\",\n    srcs = [\n        \"btree_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    shard_count = 10,\n    tags = [\n        \"no_test:os:ios\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":btree\",\n        \":btree_test_common\",\n        \":test_allocator\",\n        \":test_instance_tracker\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/flags:flag\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/strings\",\n        \"//absl/types:compare\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"btree_benchmark\",\n    testonly = True,\n    srcs = [\n        \"btree_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":btree\",\n        \":btree_test_common\",\n        \":flat_hash_map\",\n        \":flat_hash_set\",\n        \":hashtable_debug\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/hash\",\n        \"//absl/log\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/strings:cord\",\n        \"//absl/strings:str_format\",\n        \"//absl/time\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"heterogeneous_lookup_testing\",\n    testonly = True,\n    hdrs = [\"internal/heterogeneous_lookup_testing.h\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/container:test_instance_tracker\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"linked_hash_set\",\n    hdrs = [\"linked_hash_set.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":common\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:flat_hash_set\",\n    ],\n)\n\ncc_test(\n    name = \"linked_hash_set_test\",\n    srcs = [\"linked_hash_set_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":heterogeneous_lookup_testing\",\n        \":linked_hash_set\",\n        \"//absl/base:config\",\n        \"//absl/container:hash_generator_testing\",\n        \"//absl/container:hash_policy_testing\",\n        \"//absl/container:test_instance_tracker\",\n        \"//absl/container:unordered_set_constructor_test\",\n        \"//absl/container:unordered_set_lookup_test\",\n        \"//absl/container:unordered_set_members_test\",\n        \"//absl/container:unordered_set_modifiers_test\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"linked_hash_set_benchmark\",\n    testonly = True,\n    srcs = [\"linked_hash_set_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":linked_hash_set\",\n        \"//absl/functional:function_ref\",\n        \"//absl/strings:str_format\",\n        \"//absl/strings:string_view\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"linked_hash_map\",\n    hdrs = [\"linked_hash_map.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":common\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/container:flat_hash_set\",\n    ],\n)\n\ncc_test(\n    name = \"linked_hash_map_test\",\n    srcs = [\"linked_hash_map_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":heterogeneous_lookup_testing\",\n        \":linked_hash_map\",\n        \"//absl/base:config\",\n        \"//absl/base:exception_testing\",\n        \"//absl/container:hash_generator_testing\",\n        \"//absl/container:hash_policy_testing\",\n        \"//absl/container:test_instance_tracker\",\n        \"//absl/container:unordered_map_constructor_test\",\n        \"//absl/container:unordered_map_lookup_test\",\n        \"//absl/container:unordered_map_members_test\",\n        \"//absl/container:unordered_map_modifiers_test\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"linked_hash_map_benchmark\",\n    testonly = True,\n    srcs = [\"linked_hash_map_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":linked_hash_map\",\n        \"//absl/functional:function_ref\",\n        \"//absl/strings:str_format\",\n        \"//absl/strings:string_view\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"chunked_queue\",\n    srcs = [\"internal/chunked_queue.h\"],\n    hdrs = [\"chunked_queue.h\"],\n    deps = [\n        \":layout\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:iterator_traits_internal\",\n    ],\n)\n\ncc_test(\n    name = \"chunked_queue_test\",\n    size = \"small\",\n    srcs = [\"chunked_queue_test.cc\"],\n    deps = [\n        \":chunked_queue\",\n        \":test_allocator\",\n        \"//absl/base:core_headers\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"chunked_queue_benchmark\",\n    testonly = True,\n    srcs = [\"chunked_queue_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":chunked_queue\",\n        \"//absl/random\",\n        \"//absl/status\",\n        \"//absl/strings:cord\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/container/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    btree\n  HDRS\n    \"btree_map.h\"\n    \"btree_set.h\"\n    \"internal/btree.h\"\n    \"internal/btree_container.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::common_policy_traits\n    absl::compare\n    absl::compressed_tuple\n    absl::config\n    absl::container_common\n    absl::container_memory\n    absl::cord\n    absl::core_headers\n    absl::layout\n    absl::memory\n    absl::raw_logging_internal\n    absl::strings\n    absl::throw_delegate\n    absl::type_traits\n    absl::weakly_mixed_integer\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    btree_test_common\n  hdrs\n    \"btree_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::btree\n    absl::cord\n    absl::flat_hash_set\n    absl::strings\n    absl::time\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    btree_test\n  SRCS\n    \"btree_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::algorithm_container\n    absl::btree\n    absl::btree_test_common\n    absl::compare\n    absl::core_headers\n    absl::flags\n    absl::hash_testing\n    absl::random_random\n    absl::raw_logging_internal\n    absl::strings\n    absl::test_allocator\n    absl::test_instance_tracker\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    compressed_tuple\n  HDRS\n    \"internal/compressed_tuple.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    compressed_tuple_test\n  SRCS\n    \"internal/compressed_tuple_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::compressed_tuple\n    absl::memory\n    absl::test_instance_tracker\n    absl::utility\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    fixed_array\n  HDRS\n   \"fixed_array.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::compressed_tuple\n    absl::algorithm\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::iterator_traits_internal\n    absl::throw_delegate\n    absl::memory\n    absl::weakly_mixed_integer\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    fixed_array_test\n  SRCS\n    \"fixed_array_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::fixed_array\n    absl::config\n    absl::exception_testing\n    absl::hash_testing\n    absl::iterator_traits_test_helper_internal\n    absl::memory\n    absl::test_allocator\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    fixed_array_exception_safety_test\n  SRCS\n    \"fixed_array_exception_safety_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::fixed_array\n    absl::config\n    absl::exception_safety_testing\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    inlined_vector_internal\n  HDRS\n   \"internal/inlined_vector.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base_internal\n    absl::compressed_tuple\n    absl::config\n    absl::core_headers\n    absl::memory\n    absl::span\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    inlined_vector\n  HDRS\n   \"inlined_vector.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::algorithm\n    absl::core_headers\n    absl::inlined_vector_internal\n    absl::throw_delegate\n    absl::memory\n    absl::type_traits\n    absl::weakly_mixed_integer\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    test_allocator\n  HDRS\n    \"internal/test_allocator.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    GTest::gmock\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    inlined_vector_test\n  SRCS\n    \"inlined_vector_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::check\n    absl::config\n    absl::core_headers\n    absl::exception_testing\n    absl::hash_testing\n    absl::inlined_vector\n    absl::memory\n    absl::strings\n    absl::test_allocator\n    absl::test_instance_tracker\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    inlined_vector_exception_safety_test\n  SRCS\n    \"inlined_vector_exception_safety_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::inlined_vector\n    absl::config\n    absl::exception_safety_testing\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    test_instance_tracker\n  HDRS\n    \"internal/test_instance_tracker.h\"\n  SRCS\n    \"internal/test_instance_tracker.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::compare\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    test_instance_tracker_test\n  SRCS\n    \"internal/test_instance_tracker_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::test_instance_tracker\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    flat_hash_map\n  HDRS\n    \"flat_hash_map.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::container_memory\n    absl::core_headers\n    absl::hash_container_defaults\n    absl::raw_hash_map\n    absl::algorithm_container\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    flat_hash_map_test\n  SRCS\n    \"flat_hash_map_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::check\n    absl::config\n    absl::flat_hash_map\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    absl::test_allocator\n    absl::type_traits\n    absl::unordered_map_constructor_test\n    absl::unordered_map_lookup_test\n    absl::unordered_map_members_test\n    absl::unordered_map_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    flat_hash_set\n  HDRS\n    \"flat_hash_set.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::container_memory\n    absl::hash_container_defaults\n    absl::raw_hash_set\n    absl::algorithm_container\n    absl::core_headers\n    absl::memory\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    flat_hash_set_test\n  SRCS\n    \"flat_hash_set_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::check\n    absl::config\n    absl::container_memory\n    absl::flat_hash_set\n    absl::hash\n    absl::hash_container_defaults\n    absl::hash_generator_testing\n    absl::memory\n    absl::strings\n    absl::test_allocator\n    absl::unordered_set_constructor_test\n    absl::unordered_set_lookup_test\n    absl::unordered_set_members_test\n    absl::unordered_set_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    node_hash_map\n  HDRS\n    \"node_hash_map.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::container_memory\n    absl::core_headers\n    absl::hash_container_defaults\n    absl::node_slot_policy\n    absl::raw_hash_map\n    absl::algorithm_container\n    absl::memory\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    node_hash_map_test\n  SRCS\n    \"node_hash_map_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hash_policy_testing\n    absl::node_hash_map\n    absl::tracked\n    absl::unordered_map_constructor_test\n    absl::unordered_map_lookup_test\n    absl::unordered_map_members_test\n    absl::unordered_map_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    node_hash_set\n  HDRS\n    \"node_hash_set.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::container_memory\n    absl::core_headers\n    absl::hash_container_defaults\n    absl::node_slot_policy\n    absl::raw_hash_set\n    absl::algorithm_container\n    absl::memory\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    node_hash_set_test\n  SRCS\n    \"node_hash_set_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    absl::memory\n    absl::node_hash_set\n    absl::type_traits\n    absl::unordered_set_constructor_test\n    absl::unordered_set_lookup_test\n    absl::unordered_set_members_test\n    absl::unordered_set_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    hash_container_defaults\n  HDRS\n    \"hash_container_defaults.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::hash_function_defaults\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    container_memory\n  HDRS\n    \"internal/container_memory.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::hash\n    absl::memory\n    absl::type_traits\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    container_memory_test\n  SRCS\n    \"internal/container_memory_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::container_memory\n    absl::no_destructor\n    absl::strings\n    absl::test_instance_tracker\n    absl::type_traits\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hash_function_defaults\n  HDRS\n    \"internal/hash_function_defaults.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::container_common\n    absl::cord\n    absl::hash\n    absl::strings\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    hash_function_defaults_test\n  SRCS\n    \"internal/hash_function_defaults_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::cord\n    absl::cord_test_helpers\n    absl::flat_hash_map\n    absl::flat_hash_set\n    absl::hash_function_defaults\n    absl::hash\n    absl::random_random\n    absl::strings\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hash_generator_testing\n  HDRS\n    \"internal/hash_generator_testing.h\"\n  SRCS\n    \"internal/hash_generator_testing.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hash_policy_testing\n    absl::memory\n    absl::meta\n    absl::no_destructor\n    absl::random_random\n    absl::strings\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hash_policy_testing\n  HDRS\n    \"internal/hash_policy_testing.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash\n    absl::strings\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    hash_policy_testing_test\n  SRCS\n    \"internal/hash_policy_testing_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash_policy_testing\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hash_policy_traits\n  HDRS\n    \"internal/hash_policy_traits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::container_memory\n    absl::common_policy_traits\n    absl::meta\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    hash_policy_traits_test\n  SRCS\n    \"internal/hash_policy_traits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::container_memory\n    absl::hash_policy_traits\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    common_policy_traits\n  HDRS\n    \"internal/common_policy_traits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::meta\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    common_policy_traits_test\n  SRCS\n    \"internal/common_policy_traits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::common_policy_traits\n    absl::config\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hashtablez_sampler\n  HDRS\n    \"internal/hashtablez_sampler.h\"\n  SRCS\n    \"internal/hashtablez_sampler.cc\"\n    \"internal/hashtablez_sampler_force_weak_definition.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::exponential_biased\n    absl::no_destructor\n    absl::raw_logging_internal\n    absl::sample_recorder\n    absl::synchronization\n    absl::time\n)\n\nabsl_cc_test(\n  NAME\n    hashtablez_sampler_test\n  SRCS\n    \"internal/hashtablez_sampler_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hashtablez_sampler\n    absl::random_random\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hashtable_debug\n  HDRS\n    \"internal/hashtable_debug.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::hashtable_debug_hooks\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hashtable_debug_hooks\n  HDRS\n    \"internal/hashtable_debug_hooks.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    node_slot_policy\n  HDRS\n    \"internal/node_slot_policy.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    node_slot_policy_test\n  SRCS\n    \"internal/node_slot_policy_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hash_policy_traits\n    absl::node_slot_policy\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    raw_hash_map\n  HDRS\n    \"internal/raw_hash_map.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::common_policy_traits\n    absl::container_memory\n    absl::core_headers\n    absl::raw_hash_set\n    absl::type_traits\n    absl::throw_delegate\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    container_common\n  HDRS\n    \"internal/common.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    hashtable_control_bytes\n  HDRS\n    \"internal/hashtable_control_bytes.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::bits\n    absl::config\n    absl::core_headers\n    absl::endian\n)\n\nabsl_cc_test(\n  NAME\n    hashtable_control_bytes_test\n  SRCS\n    \"internal/hashtable_control_bytes_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hashtable_control_bytes\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    raw_hash_set\n  HDRS\n    \"internal/raw_hash_set.h\"\n  SRCS\n    \"internal/raw_hash_set.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::bits\n    absl::common_policy_traits\n    absl::compressed_tuple\n    absl::config\n    absl::container_common\n    absl::container_memory\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::endian\n    absl::function_ref\n    absl::hash\n    absl::hash_function_defaults\n    absl::hash_policy_traits\n    absl::hashtable_control_bytes\n    absl::hashtable_debug_hooks\n    absl::hashtablez_sampler\n    absl::iterator_traits_internal\n    absl::memory\n    absl::meta\n    absl::optional\n    absl::prefetch\n    absl::raw_logging_internal\n    absl::utility\n    absl::weakly_mixed_integer\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    raw_hash_set_test\n  SRCS\n    \"internal/raw_hash_set_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::check\n    absl::config\n    absl::container_memory\n    absl::core_headers\n    absl::flat_hash_map\n    absl::flat_hash_set\n    absl::function_ref\n    absl::hash\n    absl::hash_function_defaults\n    absl::hash_policy_testing\n    absl::hashtable_debug\n    absl::hashtablez_sampler\n    absl::int128\n    absl::log\n    absl::memory\n    absl::node_hash_set\n    absl::prefetch\n    absl::random_random\n    absl::raw_hash_set\n    absl::strings\n    absl::test_allocator\n    absl::test_instance_tracker\n    absl::type_traits\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    raw_hash_set_resize_impl\n  HDRS\n    \"internal/raw_hash_set_resize_impl.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    raw_hash_set_resize_impl_test\n  SRCS\n    \"internal/raw_hash_set_resize_impl_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::raw_hash_set_resize_impl\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    raw_hash_set_allocator_test\n  SRCS\n    \"internal/raw_hash_set_allocator_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::container_memory\n    absl::raw_hash_set\n    absl::tracked\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    layout\n  HDRS\n    \"internal/layout.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::debugging_internal\n    absl::meta\n    absl::strings\n    absl::span\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    layout_test\n  SRCS\n    \"internal/layout_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::layout\n    absl::check\n    absl::config\n    absl::span\n    absl::utility\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    tracked\n  HDRS\n    \"internal/tracked.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_map_constructor_test\n  HDRS\n    \"internal/unordered_map_constructor_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_map_lookup_test\n  HDRS\n    \"internal/unordered_map_lookup_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_map_members_test\n  HDRS\n    \"internal/unordered_map_members_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::type_traits\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_map_modifiers_test\n  HDRS\n    \"internal/unordered_map_modifiers_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_set_constructor_test\n  HDRS\n    \"internal/unordered_set_constructor_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_set_lookup_test\n  HDRS\n    \"internal/unordered_set_lookup_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_set_members_test\n  HDRS\n    \"internal/unordered_set_members_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::type_traits\n    GTest::gmock\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    unordered_set_modifiers_test\n  HDRS\n    \"internal/unordered_set_modifiers_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    GTest::gmock\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    unordered_set_test\n  SRCS\n    \"internal/unordered_set_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::unordered_set_constructor_test\n    absl::unordered_set_lookup_test\n    absl::unordered_set_members_test\n    absl::unordered_set_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    unordered_map_test\n  SRCS\n    \"internal/unordered_map_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::unordered_map_constructor_test\n    absl::unordered_map_lookup_test\n    absl::unordered_map_members_test\n    absl::unordered_map_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    sample_element_size_test\n  SRCS\n    \"sample_element_size_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flat_hash_map\n    absl::flat_hash_set\n    absl::node_hash_map\n    absl::node_hash_set\n    absl::hashtablez_sampler\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    heterogeneous_lookup_testing\n  HDRS\n    \"internal/heterogeneous_lookup_testing.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::test_instance_tracker\n    GTest::gmock\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    linked_hash_set\n  HDRS\n    \"linked_hash_set.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n     absl::container_common\n     absl::config\n     absl::core_headers\n     absl::flat_hash_set\n)\n\nabsl_cc_test(\n  NAME\n    linked_hash_set_test\n  SRCS\n    \"linked_hash_set_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::linked_hash_set\n    absl::config\n    absl::heterogeneous_lookup_testing\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    absl::string_view\n    absl::test_instance_tracker\n    absl::unordered_set_constructor_test\n    absl::unordered_set_lookup_test\n    absl::unordered_set_members_test\n    absl::unordered_set_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    linked_hash_map\n  HDRS\n    \"linked_hash_map.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n     absl::container_common\n     absl::config\n     absl::core_headers\n     absl::flat_hash_set\n     absl::throw_delegate\n)\n\nabsl_cc_test(\n  NAME\n    linked_hash_map_test\n  SRCS\n    \"linked_hash_map_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::linked_hash_map\n    absl::config\n    absl::exception_testing\n    absl::heterogeneous_lookup_testing\n    absl::hash_generator_testing\n    absl::hash_policy_testing\n    absl::string_view\n    absl::test_instance_tracker\n    absl::unordered_set_constructor_test\n    absl::unordered_set_lookup_test\n    absl::unordered_set_members_test\n    absl::unordered_set_modifiers_test\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    chunked_queue\n  HDRS\n    \"chunked_queue.h\"\n    \"internal/chunked_queue.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n     absl::config\n     absl::core_headers\n     absl::iterator_traits_internal\n     absl::layout\n)\n\nabsl_cc_test(\n  NAME\n    chunked_queue_test\n  SRCS\n    \"chunked_queue_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::chunked_queue\n    absl::config\n    absl::core_headers\n    absl::strings\n    absl::test_allocator\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/container/btree_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <stdint.h>\n\n#include <algorithm>\n#include <functional>\n#include <map>\n#include <numeric>\n#include <random>\n#include <set>\n#include <string>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <vector>\n\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/container/btree_map.h\"\n#include \"absl/container/btree_set.h\"\n#include \"absl/container/btree_test.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/container/internal/hashtable_debug.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/log/log.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/time/time.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nconstexpr size_t kBenchmarkValues = 1 << 20;\n\n// How many times we add and remove sub-batches in one batch of *AddRem\n// benchmarks.\nconstexpr size_t kAddRemBatchSize = 1 << 2;\n\n// Generates n values in the range [0, 4 * n].\ntemplate <typename V>\nstd::vector<V> GenerateValues(int n) {\n  constexpr int kSeed = 23;\n  return GenerateValuesWithSeed<V>(n, 4 * n, kSeed);\n}\n\n// Benchmark insertion of values into a container.\ntemplate <typename T>\nvoid BM_InsertImpl(benchmark::State& state, bool sorted) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n  if (sorted) {\n    std::sort(values.begin(), values.end());\n  }\n  T container(values.begin(), values.end());\n\n  // Remove and re-insert 10% of the keys per batch.\n  const int batch_size = (kBenchmarkValues + 9) / 10;\n  while (state.KeepRunningBatch(batch_size)) {\n    state.PauseTiming();\n    const auto i = static_cast<int>(state.iterations());\n\n    for (int j = i; j < i + batch_size; j++) {\n      int x = j % kBenchmarkValues;\n      container.erase(key_of_value(values[x]));\n    }\n\n    state.ResumeTiming();\n\n    for (int j = i; j < i + batch_size; j++) {\n      int x = j % kBenchmarkValues;\n      container.insert(values[x]);\n    }\n  }\n}\n\ntemplate <typename T>\nvoid BM_Insert(benchmark::State& state) {\n  BM_InsertImpl<T>(state, false);\n}\n\ntemplate <typename T>\nvoid BM_InsertSorted(benchmark::State& state) {\n  BM_InsertImpl<T>(state, true);\n}\n\n// Benchmark inserting the first few elements in a container. In b-tree, this is\n// when the root node grows.\ntemplate <typename T>\nvoid BM_InsertSmall(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n\n  const int kSize = 8;\n  std::vector<V> values = GenerateValues<V>(kSize);\n  T container;\n\n  while (state.KeepRunningBatch(kSize)) {\n    for (int i = 0; i < kSize; ++i) {\n      benchmark::DoNotOptimize(container.insert(values[i]));\n    }\n    state.PauseTiming();\n    // Do not measure the time it takes to clear the container.\n    container.clear();\n    state.ResumeTiming();\n  }\n}\n\ntemplate <typename T>\nvoid BM_LookupImpl(benchmark::State& state, bool sorted) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n  if (sorted) {\n    std::sort(values.begin(), values.end());\n  }\n  T container(values.begin(), values.end());\n\n  while (state.KeepRunning()) {\n    int idx = state.iterations() % kBenchmarkValues;\n    benchmark::DoNotOptimize(container.find(key_of_value(values[idx])));\n  }\n}\n\n// Benchmark lookup of values in a container.\ntemplate <typename T>\nvoid BM_Lookup(benchmark::State& state) {\n  BM_LookupImpl<T>(state, false);\n}\n\n// Benchmark lookup of values in a full container, meaning that values\n// are inserted in-order to take advantage of biased insertion, which\n// yields a full tree.\ntemplate <typename T>\nvoid BM_FullLookup(benchmark::State& state) {\n  BM_LookupImpl<T>(state, true);\n}\n\n// Benchmark erasing values from a container.\ntemplate <typename T>\nvoid BM_Erase(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n  T container(values.begin(), values.end());\n\n  // Remove and re-insert 10% of the keys per batch.\n  const int batch_size = (kBenchmarkValues + 9) / 10;\n  while (state.KeepRunningBatch(batch_size)) {\n    const int i = state.iterations();\n\n    for (int j = i; j < i + batch_size; j++) {\n      int x = j % kBenchmarkValues;\n      container.erase(key_of_value(values[x]));\n    }\n\n    state.PauseTiming();\n    for (int j = i; j < i + batch_size; j++) {\n      int x = j % kBenchmarkValues;\n      container.insert(values[x]);\n    }\n    state.ResumeTiming();\n  }\n}\n\n// Benchmark erasing multiple values from a container.\ntemplate <typename T>\nvoid BM_EraseRange(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n  T container(values.begin(), values.end());\n\n  // Remove and re-insert 10% of the keys per batch.\n  const int batch_size = (kBenchmarkValues + 9) / 10;\n  while (state.KeepRunningBatch(batch_size)) {\n    const int i = state.iterations();\n\n    const int start_index = i % kBenchmarkValues;\n\n    state.PauseTiming();\n    {\n      std::vector<V> removed;\n      removed.reserve(batch_size);\n      auto itr = container.find(key_of_value(values[start_index]));\n      auto start = itr;\n      for (int j = 0; j < batch_size; j++) {\n        if (itr == container.end()) {\n          state.ResumeTiming();\n          container.erase(start, itr);\n          state.PauseTiming();\n          itr = container.begin();\n          start = itr;\n        }\n        removed.push_back(*itr++);\n      }\n\n      state.ResumeTiming();\n      container.erase(start, itr);\n      state.PauseTiming();\n\n      container.insert(removed.begin(), removed.end());\n    }\n    state.ResumeTiming();\n  }\n}\n\n// Predicate that erases every other element. We can't use a lambda because\n// C++11 doesn't support generic lambdas.\n// TODO(b/207389011): consider adding benchmarks that remove different fractions\n// of keys (e.g. 10%, 90%).\nstruct EraseIfPred {\n  uint64_t i = 0;\n  template <typename T>\n  bool operator()(const T&) {\n    return ++i % 2;\n  }\n};\n\n// Benchmark erasing multiple values from a container with a predicate.\ntemplate <typename T>\nvoid BM_EraseIf(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n\n  // Removes half of the keys per batch.\n  const int batch_size = (kBenchmarkValues + 1) / 2;\n  EraseIfPred pred;\n  while (state.KeepRunningBatch(batch_size)) {\n    state.PauseTiming();\n    {\n      T container(values.begin(), values.end());\n      state.ResumeTiming();\n      erase_if(container, pred);\n      benchmark::DoNotOptimize(container);\n      state.PauseTiming();\n    }\n    state.ResumeTiming();\n  }\n}\n\n// Benchmark steady-state insert (into first half of range) and remove (from\n// second half of range), treating the container approximately like a queue with\n// log-time access for all elements. This benchmark does not test the case where\n// insertion and removal happen in the same region of the tree.  This benchmark\n// counts two value constructors.\ntemplate <typename T>\nvoid BM_QueueAddRem(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n\n  ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, \"for performance\");\n\n  T container;\n\n  const size_t half = kBenchmarkValues / 2;\n  std::vector<int> remove_keys(half);\n  std::vector<int> add_keys(half);\n\n  // We want to do the exact same work repeatedly, and the benchmark can end\n  // after a different number of iterations depending on the speed of the\n  // individual run so we use a large batch size here and ensure that we do\n  // deterministic work every batch.\n  while (state.KeepRunningBatch(half * kAddRemBatchSize)) {\n    state.PauseTiming();\n\n    container.clear();\n\n    for (size_t i = 0; i < half; ++i) {\n      remove_keys[i] = i;\n      add_keys[i] = i;\n    }\n    constexpr int kSeed = 5;\n    std::mt19937_64 rand(kSeed);\n    std::shuffle(remove_keys.begin(), remove_keys.end(), rand);\n    std::shuffle(add_keys.begin(), add_keys.end(), rand);\n\n    // Note needs lazy generation of values.\n    Generator<V> g(kBenchmarkValues * kAddRemBatchSize);\n\n    for (size_t i = 0; i < half; ++i) {\n      container.insert(g(add_keys[i]));\n      container.insert(g(half + remove_keys[i]));\n    }\n\n    // There are three parts each of size \"half\":\n    // 1 is being deleted from  [offset - half, offset)\n    // 2 is standing            [offset, offset + half)\n    // 3 is being inserted into [offset + half, offset + 2 * half)\n    size_t offset = 0;\n\n    for (size_t i = 0; i < kAddRemBatchSize; ++i) {\n      std::shuffle(remove_keys.begin(), remove_keys.end(), rand);\n      std::shuffle(add_keys.begin(), add_keys.end(), rand);\n      offset += half;\n\n      state.ResumeTiming();\n      for (size_t idx = 0; idx < half; ++idx) {\n        container.erase(key_of_value(g(offset - half + remove_keys[idx])));\n        container.insert(g(offset + half + add_keys[idx]));\n      }\n      state.PauseTiming();\n    }\n    state.ResumeTiming();\n  }\n}\n\n// Mixed insertion and deletion in the same range using pre-constructed values.\ntemplate <typename T>\nvoid BM_MixedAddRem(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n\n  ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, \"for performance\");\n\n  T container;\n\n  // Create two random shuffles\n  std::vector<int> remove_keys(kBenchmarkValues);\n  std::vector<int> add_keys(kBenchmarkValues);\n\n  // We want to do the exact same work repeatedly, and the benchmark can end\n  // after a different number of iterations depending on the speed of the\n  // individual run so we use a large batch size here and ensure that we do\n  // deterministic work every batch.\n  while (state.KeepRunningBatch(kBenchmarkValues * kAddRemBatchSize)) {\n    state.PauseTiming();\n\n    container.clear();\n\n    constexpr int kSeed = 7;\n    std::mt19937_64 rand(kSeed);\n\n    std::vector<V> values = GenerateValues<V>(kBenchmarkValues * 2);\n\n    // Insert the first half of the values (already in random order)\n    container.insert(values.begin(), values.begin() + kBenchmarkValues);\n\n    // Insert the first half of the values (already in random order)\n    for (size_t i = 0; i < kBenchmarkValues; ++i) {\n      // remove_keys and add_keys will be swapped before each round,\n      // therefore fill add_keys here w/ the keys being inserted, so\n      // they'll be the first to be removed.\n      remove_keys[i] = i + kBenchmarkValues;\n      add_keys[i] = i;\n    }\n\n    for (size_t i = 0; i < kAddRemBatchSize; ++i) {\n      remove_keys.swap(add_keys);\n      std::shuffle(remove_keys.begin(), remove_keys.end(), rand);\n      std::shuffle(add_keys.begin(), add_keys.end(), rand);\n\n      state.ResumeTiming();\n      for (size_t idx = 0; idx < kBenchmarkValues; ++idx) {\n        container.erase(key_of_value(values[remove_keys[idx]]));\n        container.insert(values[add_keys[idx]]);\n      }\n      state.PauseTiming();\n    }\n    state.ResumeTiming();\n  }\n}\n\n// Insertion at end, removal from the beginning.  This benchmark\n// counts two value constructors.\n// TODO(ezb): we could add a GenerateNext version of generator that could reduce\n// noise for string-like types.\ntemplate <typename T>\nvoid BM_Fifo(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n\n  T container;\n  // Need lazy generation of values as state.max_iterations is large.\n  Generator<V> g(kBenchmarkValues + state.max_iterations);\n\n  for (int i = 0; i < kBenchmarkValues; i++) {\n    container.insert(g(i));\n  }\n\n  while (state.KeepRunning()) {\n    container.erase(container.begin());\n    container.insert(container.end(), g(state.iterations() + kBenchmarkValues));\n  }\n}\n\n// Iteration (forward) through the tree\ntemplate <typename T>\nvoid BM_FwdIter(benchmark::State& state) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n  T container(values.begin(), values.end());\n\n  auto iter = container.end();\n\n  while (state.KeepRunning()) {\n    if (iter == container.end()) iter = container.begin();\n    auto *v = &(*iter);\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(++iter);\n  }\n}\n\n// Benchmark random range-construction of a container.\ntemplate <typename T>\nvoid BM_RangeConstructionImpl(benchmark::State& state, bool sorted) {\n  using V = typename remove_pair_const<typename T::value_type>::type;\n\n  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);\n  if (sorted) {\n    std::sort(values.begin(), values.end());\n  }\n  {\n    T container(values.begin(), values.end());\n  }\n\n  while (state.KeepRunning()) {\n    T container(values.begin(), values.end());\n    benchmark::DoNotOptimize(container);\n  }\n}\n\ntemplate <typename T>\nvoid BM_InsertRangeRandom(benchmark::State& state) {\n  BM_RangeConstructionImpl<T>(state, false);\n}\n\ntemplate <typename T>\nvoid BM_InsertRangeSorted(benchmark::State& state) {\n  BM_RangeConstructionImpl<T>(state, true);\n}\n\n#define STL_ORDERED_TYPES(value)                     \\\n  using stl_set_##value = std::set<value>;           \\\n  using stl_map_##value = std::map<value, intptr_t>; \\\n  using stl_multiset_##value = std::multiset<value>; \\\n  using stl_multimap_##value = std::multimap<value, intptr_t>\n\nusing StdString = std::string;\nSTL_ORDERED_TYPES(int32_t);\nSTL_ORDERED_TYPES(int64_t);\nSTL_ORDERED_TYPES(StdString);\nSTL_ORDERED_TYPES(Cord);\nSTL_ORDERED_TYPES(Time);\n\n#define STL_UNORDERED_TYPES(value)                                       \\\n  using stl_unordered_set_##value = std::unordered_set<value>;           \\\n  using stl_unordered_map_##value = std::unordered_map<value, intptr_t>; \\\n  using flat_hash_set_##value = flat_hash_set<value>;                    \\\n  using flat_hash_map_##value = flat_hash_map<value, intptr_t>;          \\\n  using stl_unordered_multiset_##value = std::unordered_multiset<value>; \\\n  using stl_unordered_multimap_##value =                                 \\\n      std::unordered_multimap<value, intptr_t>\n\n#define STL_UNORDERED_TYPES_CUSTOM_HASH(value, hash)                           \\\n  using stl_unordered_set_##value = std::unordered_set<value, hash>;           \\\n  using stl_unordered_map_##value = std::unordered_map<value, intptr_t, hash>; \\\n  using flat_hash_set_##value = flat_hash_set<value, hash>;                    \\\n  using flat_hash_map_##value = flat_hash_map<value, intptr_t, hash>;          \\\n  using stl_unordered_multiset_##value = std::unordered_multiset<value, hash>; \\\n  using stl_unordered_multimap_##value =                                       \\\n      std::unordered_multimap<value, intptr_t, hash>\n\nSTL_UNORDERED_TYPES_CUSTOM_HASH(Cord, absl::Hash<absl::Cord>);\n\nSTL_UNORDERED_TYPES(int32_t);\nSTL_UNORDERED_TYPES(int64_t);\nSTL_UNORDERED_TYPES(StdString);\nSTL_UNORDERED_TYPES_CUSTOM_HASH(Time, absl::Hash<absl::Time>);\n\n#define BTREE_TYPES(value)                                            \\\n  using btree_256_set_##value =                                       \\\n      btree_set<value, std::less<value>, std::allocator<value>>;      \\\n  using btree_256_map_##value =                                       \\\n      btree_map<value, intptr_t, std::less<value>,                    \\\n                std::allocator<std::pair<const value, intptr_t>>>;    \\\n  using btree_256_multiset_##value =                                  \\\n      btree_multiset<value, std::less<value>, std::allocator<value>>; \\\n  using btree_256_multimap_##value =                                  \\\n      btree_multimap<value, intptr_t, std::less<value>,               \\\n                     std::allocator<std::pair<const value, intptr_t>>>\n\nBTREE_TYPES(int32_t);\nBTREE_TYPES(int64_t);\nBTREE_TYPES(StdString);\nBTREE_TYPES(Cord);\nBTREE_TYPES(Time);\n\n#define MY_BENCHMARK4(type, func)                                              \\\n  void BM_##type##_##func(benchmark::State& state) { BM_##func<type>(state); } \\\n  BENCHMARK(BM_##type##_##func)\n\n#define MY_BENCHMARK3_STL(type)           \\\n  MY_BENCHMARK4(type, Insert);            \\\n  MY_BENCHMARK4(type, InsertSorted);      \\\n  MY_BENCHMARK4(type, InsertSmall);       \\\n  MY_BENCHMARK4(type, Lookup);            \\\n  MY_BENCHMARK4(type, FullLookup);        \\\n  MY_BENCHMARK4(type, Erase);             \\\n  MY_BENCHMARK4(type, EraseRange);        \\\n  MY_BENCHMARK4(type, QueueAddRem);       \\\n  MY_BENCHMARK4(type, MixedAddRem);       \\\n  MY_BENCHMARK4(type, Fifo);              \\\n  MY_BENCHMARK4(type, FwdIter);           \\\n  MY_BENCHMARK4(type, InsertRangeRandom); \\\n  MY_BENCHMARK4(type, InsertRangeSorted)\n\n#define MY_BENCHMARK3(type)     \\\n  MY_BENCHMARK4(type, EraseIf); \\\n  MY_BENCHMARK3_STL(type)\n\n#define MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type) \\\n  MY_BENCHMARK3_STL(stl_##type);                \\\n  MY_BENCHMARK3_STL(stl_unordered_##type);      \\\n  MY_BENCHMARK3(btree_256_##type)\n\n#define MY_BENCHMARK2(type)                \\\n  MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type); \\\n  MY_BENCHMARK3(flat_hash_##type)\n\n// Define MULTI_TESTING to see benchmarks for multi-containers also.\n//\n// You can use --copt=-DMULTI_TESTING.\n#ifdef MULTI_TESTING\n#define MY_BENCHMARK(type)                            \\\n  MY_BENCHMARK2(set_##type);                          \\\n  MY_BENCHMARK2(map_##type);                          \\\n  MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multiset_##type); \\\n  MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multimap_##type)\n#else\n#define MY_BENCHMARK(type)   \\\n  MY_BENCHMARK2(set_##type); \\\n  MY_BENCHMARK2(map_##type)\n#endif\n\nMY_BENCHMARK(int32_t);\nMY_BENCHMARK(int64_t);\nMY_BENCHMARK(StdString);\nMY_BENCHMARK(Cord);\nMY_BENCHMARK(Time);\n\n// Define a type whose size and cost of moving are independently customizable.\n// When sizeof(value_type) increases, we expect btree to no longer have as much\n// cache-locality advantage over STL. When cost of moving increases, we expect\n// btree to actually do more work than STL because it has to move values around\n// and STL doesn't have to.\ntemplate <int Size, int Copies>\nstruct BigType {\n  BigType() : BigType(0) {}\n  explicit BigType(int x) { std::iota(values.begin(), values.end(), x); }\n\n  void Copy(const BigType& other) {\n    for (int i = 0; i < Size && i < Copies; ++i) values[i] = other.values[i];\n    // If Copies > Size, do extra copies.\n    for (int i = Size, idx = 0; i < Copies; ++i) {\n      int64_t tmp = other.values[idx];\n      benchmark::DoNotOptimize(tmp);\n      idx = idx + 1 == Size ? 0 : idx + 1;\n    }\n  }\n\n  BigType(const BigType& other) { Copy(other); }\n  BigType& operator=(const BigType& other) {\n    Copy(other);\n    return *this;\n  }\n\n  // Compare only the first Copies elements if Copies is less than Size.\n  bool operator<(const BigType& other) const {\n    return std::lexicographical_compare(\n        values.begin(), values.begin() + std::min(Size, Copies),\n        other.values.begin(), other.values.begin() + std::min(Size, Copies));\n  }\n  bool operator==(const BigType& other) const {\n    return std::equal(values.begin(), values.begin() + std::min(Size, Copies),\n                      other.values.begin());\n  }\n\n  // Support absl::Hash.\n  template <typename State>\n  friend State AbslHashValue(State h, const BigType& b) {\n    for (int i = 0; i < Size && i < Copies; ++i)\n      h = State::combine(std::move(h), b.values[i]);\n    return h;\n  }\n\n  std::array<int64_t, Size> values;\n};\n\n#define BIG_TYPE_BENCHMARKS(SIZE, COPIES)                                     \\\n  using stl_set_size##SIZE##copies##COPIES = std::set<BigType<SIZE, COPIES>>; \\\n  using stl_map_size##SIZE##copies##COPIES =                                  \\\n      std::map<BigType<SIZE, COPIES>, intptr_t>;                              \\\n  using stl_multiset_size##SIZE##copies##COPIES =                             \\\n      std::multiset<BigType<SIZE, COPIES>>;                                   \\\n  using stl_multimap_size##SIZE##copies##COPIES =                             \\\n      std::multimap<BigType<SIZE, COPIES>, intptr_t>;                         \\\n  using stl_unordered_set_size##SIZE##copies##COPIES =                        \\\n      std::unordered_set<BigType<SIZE, COPIES>,                               \\\n                         absl::Hash<BigType<SIZE, COPIES>>>;                  \\\n  using stl_unordered_map_size##SIZE##copies##COPIES =                        \\\n      std::unordered_map<BigType<SIZE, COPIES>, intptr_t,                     \\\n                         absl::Hash<BigType<SIZE, COPIES>>>;                  \\\n  using flat_hash_set_size##SIZE##copies##COPIES =                            \\\n      flat_hash_set<BigType<SIZE, COPIES>>;                                   \\\n  using flat_hash_map_size##SIZE##copies##COPIES =                            \\\n      flat_hash_map<BigType<SIZE, COPIES>, intptr_t>;                         \\\n  using stl_unordered_multiset_size##SIZE##copies##COPIES =                   \\\n      std::unordered_multiset<BigType<SIZE, COPIES>,                          \\\n                              absl::Hash<BigType<SIZE, COPIES>>>;             \\\n  using stl_unordered_multimap_size##SIZE##copies##COPIES =                   \\\n      std::unordered_multimap<BigType<SIZE, COPIES>, intptr_t,                \\\n                              absl::Hash<BigType<SIZE, COPIES>>>;             \\\n  using btree_256_set_size##SIZE##copies##COPIES =                            \\\n      btree_set<BigType<SIZE, COPIES>>;                                       \\\n  using btree_256_map_size##SIZE##copies##COPIES =                            \\\n      btree_map<BigType<SIZE, COPIES>, intptr_t>;                             \\\n  using btree_256_multiset_size##SIZE##copies##COPIES =                       \\\n      btree_multiset<BigType<SIZE, COPIES>>;                                  \\\n  using btree_256_multimap_size##SIZE##copies##COPIES =                       \\\n      btree_multimap<BigType<SIZE, COPIES>, intptr_t>;                        \\\n  MY_BENCHMARK(size##SIZE##copies##COPIES)\n\n// Define BIG_TYPE_TESTING to see benchmarks for more big types.\n//\n// You can use --copt=-DBIG_TYPE_TESTING.\n#ifndef NODESIZE_TESTING\n#ifdef BIG_TYPE_TESTING\nBIG_TYPE_BENCHMARKS(1, 4);\nBIG_TYPE_BENCHMARKS(4, 1);\nBIG_TYPE_BENCHMARKS(4, 4);\nBIG_TYPE_BENCHMARKS(1, 8);\nBIG_TYPE_BENCHMARKS(8, 1);\nBIG_TYPE_BENCHMARKS(8, 8);\nBIG_TYPE_BENCHMARKS(1, 16);\nBIG_TYPE_BENCHMARKS(16, 1);\nBIG_TYPE_BENCHMARKS(16, 16);\nBIG_TYPE_BENCHMARKS(1, 32);\nBIG_TYPE_BENCHMARKS(32, 1);\nBIG_TYPE_BENCHMARKS(32, 32);\n#else\nBIG_TYPE_BENCHMARKS(32, 32);\n#endif\n#endif\n\n// Benchmark using unique_ptrs to large value types. In order to be able to use\n// the same benchmark code as the other types, use a type that holds a\n// unique_ptr and has a copy constructor.\ntemplate <int Size>\nstruct BigTypePtr {\n  BigTypePtr() : BigTypePtr(0) {}\n  explicit BigTypePtr(int x) {\n    ptr = absl::make_unique<BigType<Size, Size>>(x);\n  }\n  BigTypePtr(const BigTypePtr& other) {\n    ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);\n  }\n  BigTypePtr(BigTypePtr&& other) noexcept = default;\n  BigTypePtr& operator=(const BigTypePtr& other) {\n    ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);\n  }\n  BigTypePtr& operator=(BigTypePtr&& other) noexcept = default;\n\n  bool operator<(const BigTypePtr& other) const { return *ptr < *other.ptr; }\n  bool operator==(const BigTypePtr& other) const { return *ptr == *other.ptr; }\n\n  std::unique_ptr<BigType<Size, Size>> ptr;\n};\n\ntemplate <int Size>\ndouble ContainerInfo(const btree_set<BigTypePtr<Size>>& b) {\n  const double bytes_used =\n      b.bytes_used() + b.size() * sizeof(BigType<Size, Size>);\n  const double bytes_per_value = bytes_used / b.size();\n  BtreeContainerInfoLog(b, bytes_used, bytes_per_value);\n  return bytes_per_value;\n}\ntemplate <int Size>\ndouble ContainerInfo(const btree_map<int, BigTypePtr<Size>>& b) {\n  const double bytes_used =\n      b.bytes_used() + b.size() * sizeof(BigType<Size, Size>);\n  const double bytes_per_value = bytes_used / b.size();\n  BtreeContainerInfoLog(b, bytes_used, bytes_per_value);\n  return bytes_per_value;\n}\n\n#define BIG_TYPE_PTR_BENCHMARKS(SIZE)                                          \\\n  using stl_set_size##SIZE##copies##SIZE##ptr = std::set<BigType<SIZE, SIZE>>; \\\n  using stl_map_size##SIZE##copies##SIZE##ptr =                                \\\n      std::map<int, BigType<SIZE, SIZE>>;                                      \\\n  using stl_unordered_set_size##SIZE##copies##SIZE##ptr =                      \\\n      std::unordered_set<BigType<SIZE, SIZE>,                                  \\\n                         absl::Hash<BigType<SIZE, SIZE>>>;                     \\\n  using stl_unordered_map_size##SIZE##copies##SIZE##ptr =                      \\\n      std::unordered_map<int, BigType<SIZE, SIZE>>;                            \\\n  using flat_hash_set_size##SIZE##copies##SIZE##ptr =                          \\\n      flat_hash_set<BigType<SIZE, SIZE>>;                                      \\\n  using flat_hash_map_size##SIZE##copies##SIZE##ptr =                          \\\n      flat_hash_map<int, BigTypePtr<SIZE>>;                                    \\\n  using btree_256_set_size##SIZE##copies##SIZE##ptr =                          \\\n      btree_set<BigTypePtr<SIZE>>;                                             \\\n  using btree_256_map_size##SIZE##copies##SIZE##ptr =                          \\\n      btree_map<int, BigTypePtr<SIZE>>;                                        \\\n  MY_BENCHMARK3_STL(stl_set_size##SIZE##copies##SIZE##ptr);                    \\\n  MY_BENCHMARK3_STL(stl_unordered_set_size##SIZE##copies##SIZE##ptr);          \\\n  MY_BENCHMARK3(flat_hash_set_size##SIZE##copies##SIZE##ptr);                  \\\n  MY_BENCHMARK3(btree_256_set_size##SIZE##copies##SIZE##ptr);                  \\\n  MY_BENCHMARK3_STL(stl_map_size##SIZE##copies##SIZE##ptr);                    \\\n  MY_BENCHMARK3_STL(stl_unordered_map_size##SIZE##copies##SIZE##ptr);          \\\n  MY_BENCHMARK3(flat_hash_map_size##SIZE##copies##SIZE##ptr);                  \\\n  MY_BENCHMARK3(btree_256_map_size##SIZE##copies##SIZE##ptr)\n\nBIG_TYPE_PTR_BENCHMARKS(32);\n\nvoid BM_BtreeSet_IteratorDifference(benchmark::State& state) {\n  absl::InsecureBitGen bitgen;\n  std::vector<int> vec;\n  // Randomize the set's insertion order so the nodes aren't all full.\n  vec.reserve(state.range(0));\n  for (int i = 0; i < state.range(0); ++i) vec.push_back(i);\n  absl::c_shuffle(vec, bitgen);\n\n  absl::btree_set<int> set;\n  for (int i : vec) set.insert(i);\n\n  size_t distance = absl::Uniform(bitgen, 0u, set.size());\n  while (state.KeepRunningBatch(distance)) {\n    size_t end = absl::Uniform(bitgen, distance, set.size());\n    size_t begin = end - distance;\n    benchmark::DoNotOptimize(set.find(static_cast<int>(end)) -\n                             set.find(static_cast<int>(begin)));\n    distance = absl::Uniform(bitgen, 0u, set.size());\n  }\n}\n\nBENCHMARK(BM_BtreeSet_IteratorDifference)->Range(1 << 10, 1 << 20);\n\nvoid BM_BtreeSet_IteratorAddition(benchmark::State& state) {\n  absl::InsecureBitGen bitgen;\n  std::vector<int> vec;\n  // Randomize the set's insertion order so the nodes aren't all full.\n  vec.reserve(static_cast<size_t>(state.range(0)));\n  for (int i = 0; i < state.range(0); ++i) vec.push_back(i);\n  absl::c_shuffle(vec, bitgen);\n\n  absl::btree_set<int> set;\n  for (int i : vec) set.insert(i);\n\n  size_t distance = absl::Uniform(bitgen, 0u, set.size());\n  while (state.KeepRunningBatch(distance)) {\n    // Let the increment go all the way to the `end` iterator.\n    const size_t begin =\n        absl::Uniform(absl::IntervalClosed, bitgen, 0u, set.size() - distance);\n    auto it = set.find(static_cast<int>(begin));\n    benchmark::DoNotOptimize(it += static_cast<int>(distance));\n    distance = absl::Uniform(bitgen, 0u, set.size());\n  }\n}\n\nBENCHMARK(BM_BtreeSet_IteratorAddition)->Range(1 << 10, 1 << 20);\n\nvoid BM_BtreeSet_IteratorSubtraction(benchmark::State& state) {\n  absl::InsecureBitGen bitgen;\n  std::vector<int> vec;\n  // Randomize the set's insertion order so the nodes aren't all full.\n  vec.reserve(static_cast<size_t>(state.range(0)));\n  for (int i = 0; i < state.range(0); ++i) vec.push_back(i);\n  absl::c_shuffle(vec, bitgen);\n\n  absl::btree_set<int> set;\n  for (int i : vec) set.insert(i);\n\n  size_t distance = absl::Uniform(bitgen, 0u, set.size());\n  while (state.KeepRunningBatch(distance)) {\n    size_t end = absl::Uniform(bitgen, distance, set.size());\n    auto it = set.find(static_cast<int>(end));\n    benchmark::DoNotOptimize(it -= static_cast<int>(distance));\n    distance = absl::Uniform(bitgen, 0u, set.size());\n  }\n}\n\nBENCHMARK(BM_BtreeSet_IteratorSubtraction)->Range(1 << 10, 1 << 20);\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/btree_map.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: btree_map.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines B-tree maps: sorted associative containers mapping\n// keys to values.\n//\n//     * `absl::btree_map<>`\n//     * `absl::btree_multimap<>`\n//\n// These B-tree types are similar to the corresponding types in the STL\n// (`std::map` and `std::multimap`) and generally conform to the STL interfaces\n// of those types. However, because they are implemented using B-trees, they\n// are more efficient in most situations.\n//\n// Unlike `std::map` and `std::multimap`, which are commonly implemented using\n// red-black tree nodes, B-tree maps use more generic B-tree nodes able to hold\n// multiple values per node. Holding multiple values per node often makes\n// B-tree maps perform better than their `std::map` counterparts, because\n// multiple entries can be checked within the same cache hit.\n//\n// However, these types should not be considered drop-in replacements for\n// `std::map` and `std::multimap` as there are some API differences, which are\n// noted in this header file. The most consequential differences with respect to\n// migrating to b-tree from the STL types are listed in the next paragraph.\n// Other API differences are minor.\n//\n// Importantly, insertions and deletions may invalidate outstanding iterators,\n// pointers, and references to elements. Such invalidations are typically only\n// an issue if insertion and deletion operations are interleaved with the use of\n// more than one iterator, pointer, or reference simultaneously.  For this\n// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid\n// iterator at the current position. Another important difference is that\n// key-types must be copy-constructible.\n//\n// There are other API differences: first, btree iterators can be subtracted,\n// and this is faster than using `std::distance`. Additionally, btree\n// iterators can be advanced via `operator+=` and `operator-=`, which is faster\n// than using `std::advance`.\n//\n// B-tree maps are not exception-safe.\n\n#ifndef ABSL_CONTAINER_BTREE_MAP_H_\n#define ABSL_CONTAINER_BTREE_MAP_H_\n\n#include <functional>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/container/internal/btree.h\"  // IWYU pragma: export\n#include \"absl/container/internal/btree_container.h\"  // IWYU pragma: export\n#include \"absl/container/internal/common.h\"\n#include \"absl/container/internal/container_memory.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace container_internal {\n\ntemplate <typename Key, typename Data, typename... Params>\nstruct map_params_impl;\n\ntemplate <typename Key, typename Data>\nstruct btree_map_defaults {\n  using Compare = std::less<Key>;\n  using Alloc = std::allocator<std::pair<const Key, Data>>;\n  using TargetNodeSize = std::integral_constant<int, 256>;\n  using IsMulti = std::false_type;\n};\n\ntemplate <typename Key, typename Data, typename Compare, typename Alloc,\n          int TargetNodeSize, bool IsMulti>\nusing map_params = typename ApplyWithoutDefaultSuffix<\n    map_params_impl,\n    TypeList<void, void, typename btree_map_defaults<Key, Data>::Compare,\n             typename btree_map_defaults<Key, Data>::Alloc,\n             typename btree_map_defaults<Key, Data>::TargetNodeSize,\n             typename btree_map_defaults<Key, Data>::IsMulti>,\n    TypeList<Key, Data, Compare, Alloc,\n             std::integral_constant<int, TargetNodeSize>,\n             std::integral_constant<bool, IsMulti>>>::type;\n\n}  // namespace container_internal\n\n// absl::btree_map<>\n//\n// An `absl::btree_map<K, V>` is an ordered associative container of\n// unique keys and associated values designed to be a more efficient replacement\n// for `std::map` (in most cases).\n//\n// Keys are sorted using an (optional) comparison function, which defaults to\n// `std::less<K>`.\n//\n// An `absl::btree_map<K, V>` uses a default allocator of\n// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate)\n// nodes, and construct and destruct values within those nodes. You may\n// instead specify a custom allocator `A` (which in turn requires specifying a\n// custom comparator `C`) as in `absl::btree_map<K, V, C, A>`.\n//\ntemplate <typename Key, typename Value, typename Compare = std::less<Key>,\n          typename Alloc = std::allocator<std::pair<const Key, Value>>>\nclass ABSL_ATTRIBUTE_OWNER btree_map\n    : public container_internal::btree_map_container<\n          container_internal::btree<container_internal::map_params<\n              Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,\n              /*IsMulti=*/false>>> {\n  using Base = typename btree_map::btree_map_container;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A `btree_map` supports the same overload set as `std::map`\n  // for construction and assignment:\n  //\n  // * Default constructor\n  //\n  //   absl::btree_map<int, std::string> map1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::btree_map<int, std::string> map2 =\n  //       {{1, \"huey\"}, {2, \"dewey\"}, {3, \"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::btree_map<int, std::string> map3(map2);\n  //\n  // * Copy assignment operator\n  //\n  //   absl::btree_map<int, std::string> map4;\n  //   map4 = map3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::btree_map<int, std::string> map5(std::move(map4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::btree_map<int, std::string> map6;\n  //   map6 = std::move(map5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::pair<int, std::string>> v = {{1, \"a\"}, {2, \"b\"}};\n  //   absl::btree_map<int, std::string> map7(v.begin(), v.end());\n  btree_map() {}\n  using Base::Base;\n\n  // btree_map::begin()\n  //\n  // Returns an iterator to the beginning of the `btree_map`.\n  using Base::begin;\n\n  // btree_map::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `btree_map`.\n  using Base::cbegin;\n\n  // btree_map::end()\n  //\n  // Returns an iterator to the end of the `btree_map`.\n  using Base::end;\n\n  // btree_map::cend()\n  //\n  // Returns a const iterator to the end of the `btree_map`.\n  using Base::cend;\n\n  // btree_map::empty()\n  //\n  // Returns whether or not the `btree_map` is empty.\n  using Base::empty;\n\n  // btree_map::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `btree_map` under current memory constraints. This value can be thought\n  // of as the largest value of `std::distance(begin(), end())` for a\n  // `btree_map<Key, T>`.\n  using Base::max_size;\n\n  // btree_map::size()\n  //\n  // Returns the number of elements currently within the `btree_map`.\n  using Base::size;\n\n  // btree_map::clear()\n  //\n  // Removes all elements from the `btree_map`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  using Base::clear;\n\n  // btree_map::erase()\n  //\n  // Erases elements within the `btree_map`. If an erase occurs, any references,\n  // pointers, or iterators are invalidated.\n  // Overloads are listed below.\n  //\n  // iterator erase(iterator position):\n  // iterator erase(const_iterator position):\n  //\n  //   Erases the element at `position` of the `btree_map`, returning\n  //   the iterator pointing to the element after the one that was erased\n  //   (or end() if none exists).\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning\n  //   the iterator pointing to the element after the interval that was erased\n  //   (or end() if none exists).\n  //\n  // template <typename K> size_type erase(const K& key):\n  //\n  //   Erases the element with the matching key, if it exists, returning the\n  //   number of elements erased (0 or 1).\n  using Base::erase;\n\n  // btree_map::insert()\n  //\n  // Inserts an element of the specified value into the `btree_map`,\n  // returning an iterator pointing to the newly inserted element, provided that\n  // an element with the given key does not already exist. If an insertion\n  // occurs, any references, pointers, or iterators are invalidated.\n  // Overloads are listed below.\n  //\n  // std::pair<iterator,bool> insert(const value_type& value):\n  //\n  //   Inserts a value into the `btree_map`. Returns a pair consisting of an\n  //   iterator to the inserted element (or to the element that prevented the\n  //   insertion) and a bool denoting whether the insertion took place.\n  //\n  // std::pair<iterator,bool> insert(value_type&& value):\n  //\n  //   Inserts a moveable value into the `btree_map`. Returns a pair\n  //   consisting of an iterator to the inserted element (or to the element that\n  //   prevented the insertion) and a bool denoting whether the insertion took\n  //   place.\n  //\n  // iterator insert(const_iterator hint, const value_type& value):\n  // iterator insert(const_iterator hint, value_type&& value):\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element, or to the existing element that prevented the\n  //   insertion.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  // void insert(std::initializer_list<init_type> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  using Base::insert;\n\n  // btree_map::insert_or_assign()\n  //\n  // Inserts an element of the specified value into the `btree_map` provided\n  // that a value with the given key does not already exist, or replaces the\n  // corresponding mapped type with the forwarded `obj` argument if a key for\n  // that value already exists, returning an iterator pointing to the newly\n  // inserted element. Overloads are listed below.\n  //\n  // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj):\n  // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj):\n  //\n  //   Inserts/Assigns (or moves) the element of the specified key into the\n  //   `btree_map`. If the returned bool is true, insertion took place, and if\n  //   it's false, assignment took place.\n  //\n  // iterator insert_or_assign(const_iterator hint,\n  //                           const key_type& k, M&& obj):\n  // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj):\n  //\n  //   Inserts/Assigns (or moves) the element of the specified key into the\n  //   `btree_map` using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search.\n  using Base::insert_or_assign;\n\n  // btree_map::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_map`, provided that no element with the given key\n  // already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately. Prefer `try_emplace()` unless your key is not\n  // copyable or moveable.\n  //\n  // If an insertion occurs, any references, pointers, or iterators are\n  // invalidated.\n  using Base::emplace;\n\n  // btree_map::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_map`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search, and only inserts\n  // provided that no element with the given key already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately. Prefer `try_emplace()` unless your key is not\n  // copyable or moveable.\n  //\n  // If an insertion occurs, any references, pointers, or iterators are\n  // invalidated.\n  using Base::emplace_hint;\n\n  // btree_map::try_emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_map`, provided that no element with the given key\n  // already exists. Unlike `emplace()`, if an element with the given key\n  // already exists, we guarantee that no element is constructed.\n  //\n  // If an insertion occurs, any references, pointers, or iterators are\n  // invalidated.\n  //\n  // Overloads are listed below.\n  //\n  //   std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args):\n  //   std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args):\n  //\n  // Inserts (via copy or move) the element of the specified key into the\n  // `btree_map`.\n  //\n  //   iterator try_emplace(const_iterator hint,\n  //                        const key_type& k, Args&&... args):\n  //   iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args):\n  //\n  // Inserts (via copy or move) the element of the specified key into the\n  // `btree_map` using the position of `hint` as a non-binding suggestion\n  // for where to begin the insertion search.\n  using Base::try_emplace;\n\n  // btree_map::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Any references, pointers, or iterators\n  // are invalidated. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the element at the indicated position and returns a node handle\n  //   owning that extracted data.\n  //\n  // template <typename K> node_type extract(const K& k):\n  //\n  //   Extracts the element with the key matching the passed key value and\n  //   returns a node handle owning that extracted data. If the `btree_map`\n  //   does not contain an element with a matching key, this function returns an\n  //   empty node handle.\n  //\n  // NOTE: when compiled in an earlier version of C++ than C++17,\n  // `node_type::key()` returns a const reference to the key instead of a\n  // mutable reference. We cannot safely return a mutable reference without\n  // std::launder (which is not available before C++17).\n  //\n  // NOTE: In this context, `node_type` refers to the C++17 concept of a\n  // move-only type that owns and provides access to the elements in associative\n  // containers (https://en.cppreference.com/w/cpp/container/node_handle).\n  // It does NOT refer to the data layout of the underlying btree.\n  using Base::extract;\n\n  // btree_map::extract_and_get_next()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle along with an iterator to the next\n  // element.\n  //\n  // extract_and_get_next_return_type extract_and_get_next(\n  //     const_iterator position):\n  //\n  //   Extracts the element at the indicated position, returns a struct\n  //   containing a member named `node`: a node handle owning that extracted\n  //   data and a member named `next`: an iterator pointing to the next element\n  //   in the btree.\n  using Base::extract_and_get_next;\n\n  // btree_map::merge()\n  //\n  // Extracts elements from a given `source` btree_map into this\n  // `btree_map`. If the destination `btree_map` already contains an\n  // element with an equivalent key, that element is not extracted.\n  using Base::merge;\n\n  // btree_map::swap(btree_map& other)\n  //\n  // Exchanges the contents of this `btree_map` with those of the `other`\n  // btree_map, avoiding invocation of any move, copy, or swap operations on\n  // individual elements.\n  //\n  // All iterators and references on the `btree_map` remain valid, excepting\n  // for the past-the-end iterator, which is invalidated.\n  using Base::swap;\n\n  // btree_map::at()\n  //\n  // Returns a reference to the mapped value of the element with key equivalent\n  // to the passed key.\n  using Base::at;\n\n  // btree_map::contains()\n  //\n  // template <typename K> bool contains(const K& key) const:\n  //\n  // Determines whether an element comparing equal to the given `key` exists\n  // within the `btree_map`, returning `true` if so or `false` otherwise.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::contains;\n\n  // btree_map::count()\n  //\n  // template <typename K> size_type count(const K& key) const:\n  //\n  // Returns the number of elements comparing equal to the given `key` within\n  // the `btree_map`. Note that this function will return either `1` or `0`\n  // since duplicate elements are not allowed within a `btree_map`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::count;\n\n  // btree_map::equal_range()\n  //\n  // Returns a half-open range [first, last), defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the `btree_map`.\n  using Base::equal_range;\n\n  // btree_map::find()\n  //\n  // template <typename K> iterator find(const K& key):\n  // template <typename K> const_iterator find(const K& key) const:\n  //\n  // Finds an element with the passed `key` within the `btree_map`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::find;\n\n  // btree_map::lower_bound()\n  //\n  // template <typename K> iterator lower_bound(const K& key):\n  // template <typename K> const_iterator lower_bound(const K& key) const:\n  //\n  // Finds the first element with a key that is not less than `key` within the\n  // `btree_map`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::lower_bound;\n\n  // btree_map::upper_bound()\n  //\n  // template <typename K> iterator upper_bound(const K& key):\n  // template <typename K> const_iterator upper_bound(const K& key) const:\n  //\n  // Finds the first element with a key that is greater than `key` within the\n  // `btree_map`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::upper_bound;\n\n  // btree_map::operator[]()\n  //\n  // Returns a reference to the value mapped to the passed key within the\n  // `btree_map`, performing an `insert()` if the key does not already\n  // exist.\n  //\n  // If an insertion occurs, any references, pointers, or iterators are\n  // invalidated. Otherwise iterators are not affected and references are not\n  // invalidated. Overloads are listed below.\n  //\n  // T& operator[](key_type&& key):\n  // T& operator[](const key_type& key):\n  //\n  //   Inserts a value_type object constructed in-place if the element with the\n  //   given key does not exist.\n  using Base::operator[];\n\n  // btree_map::get_allocator()\n  //\n  // Returns the allocator function associated with this `btree_map`.\n  using Base::get_allocator;\n\n  // btree_map::key_comp();\n  //\n  // Returns the key comparator associated with this `btree_map`.\n  using Base::key_comp;\n\n  // btree_map::value_comp();\n  //\n  // Returns the value comparator associated with this `btree_map`.\n  using Base::value_comp;\n};\n\n// absl::swap(absl::btree_map<>, absl::btree_map<>)\n//\n// Swaps the contents of two `absl::btree_map` containers.\ntemplate <typename K, typename V, typename C, typename A>\nvoid swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) {\n  return x.swap(y);\n}\n\n// absl::erase_if(absl::btree_map<>, Pred)\n//\n// Erases all elements that satisfy the predicate pred from the container.\n// Returns the number of erased elements.\ntemplate <typename K, typename V, typename C, typename A, typename Pred>\ntypename btree_map<K, V, C, A>::size_type erase_if(\n    btree_map<K, V, C, A> &map, Pred pred) {\n  return container_internal::btree_access::erase_if(map, std::move(pred));\n}\n\n// absl::btree_multimap\n//\n// An `absl::btree_multimap<K, V>` is an ordered associative container of\n// keys and associated values designed to be a more efficient replacement for\n// `std::multimap` (in most cases). Unlike `absl::btree_map`, a B-tree multimap\n// allows multiple elements with equivalent keys.\n//\n// Keys are sorted using an (optional) comparison function, which defaults to\n// `std::less<K>`.\n//\n// An `absl::btree_multimap<K, V>` uses a default allocator of\n// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate)\n// nodes, and construct and destruct values within those nodes. You may\n// instead specify a custom allocator `A` (which in turn requires specifying a\n// custom comparator `C`) as in `absl::btree_multimap<K, V, C, A>`.\n//\ntemplate <typename Key, typename Value, typename Compare = std::less<Key>,\n          typename Alloc = std::allocator<std::pair<const Key, Value>>>\nclass ABSL_ATTRIBUTE_OWNER btree_multimap\n    : public container_internal::btree_multimap_container<\n          container_internal::btree<container_internal::map_params<\n              Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,\n              /*IsMulti=*/true>>> {\n  using Base = typename btree_multimap::btree_multimap_container;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A `btree_multimap` supports the same overload set as `std::multimap`\n  // for construction and assignment:\n  //\n  // * Default constructor\n  //\n  //   absl::btree_multimap<int, std::string> map1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::btree_multimap<int, std::string> map2 =\n  //       {{1, \"huey\"}, {2, \"dewey\"}, {3, \"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::btree_multimap<int, std::string> map3(map2);\n  //\n  // * Copy assignment operator\n  //\n  //   absl::btree_multimap<int, std::string> map4;\n  //   map4 = map3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::btree_multimap<int, std::string> map5(std::move(map4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::btree_multimap<int, std::string> map6;\n  //   map6 = std::move(map5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::pair<int, std::string>> v = {{1, \"a\"}, {2, \"b\"}};\n  //   absl::btree_multimap<int, std::string> map7(v.begin(), v.end());\n  btree_multimap() {}\n  using Base::Base;\n\n  // btree_multimap::begin()\n  //\n  // Returns an iterator to the beginning of the `btree_multimap`.\n  using Base::begin;\n\n  // btree_multimap::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `btree_multimap`.\n  using Base::cbegin;\n\n  // btree_multimap::end()\n  //\n  // Returns an iterator to the end of the `btree_multimap`.\n  using Base::end;\n\n  // btree_multimap::cend()\n  //\n  // Returns a const iterator to the end of the `btree_multimap`.\n  using Base::cend;\n\n  // btree_multimap::empty()\n  //\n  // Returns whether or not the `btree_multimap` is empty.\n  using Base::empty;\n\n  // btree_multimap::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `btree_multimap` under current memory constraints. This value can be\n  // thought of as the largest value of `std::distance(begin(), end())` for a\n  // `btree_multimap<Key, T>`.\n  using Base::max_size;\n\n  // btree_multimap::size()\n  //\n  // Returns the number of elements currently within the `btree_multimap`.\n  using Base::size;\n\n  // btree_multimap::clear()\n  //\n  // Removes all elements from the `btree_multimap`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  using Base::clear;\n\n  // btree_multimap::erase()\n  //\n  // Erases elements within the `btree_multimap`. If an erase occurs, any\n  // references, pointers, or iterators are invalidated.\n  // Overloads are listed below.\n  //\n  // iterator erase(iterator position):\n  // iterator erase(const_iterator position):\n  //\n  //   Erases the element at `position` of the `btree_multimap`, returning\n  //   the iterator pointing to the element after the one that was erased\n  //   (or end() if none exists).\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning\n  //   the iterator pointing to the element after the interval that was erased\n  //   (or end() if none exists).\n  //\n  // template <typename K> size_type erase(const K& key):\n  //\n  //   Erases the elements matching the key, if any exist, returning the\n  //   number of elements erased.\n  using Base::erase;\n\n  // btree_multimap::insert()\n  //\n  // Inserts an element of the specified value into the `btree_multimap`,\n  // returning an iterator pointing to the newly inserted element.\n  // Any references, pointers, or iterators are invalidated.  Overloads are\n  // listed below.\n  //\n  // iterator insert(const value_type& value):\n  //\n  //   Inserts a value into the `btree_multimap`, returning an iterator to the\n  //   inserted element.\n  //\n  // iterator insert(value_type&& value):\n  //\n  //   Inserts a moveable value into the `btree_multimap`, returning an iterator\n  //   to the inserted element.\n  //\n  // iterator insert(const_iterator hint, const value_type& value):\n  // iterator insert(const_iterator hint, value_type&& value):\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  // void insert(std::initializer_list<init_type> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  using Base::insert;\n\n  // btree_multimap::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_multimap`. Any references, pointers, or iterators are\n  // invalidated.\n  using Base::emplace;\n\n  // btree_multimap::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_multimap`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search.\n  //\n  // Any references, pointers, or iterators are invalidated.\n  using Base::emplace_hint;\n\n  // btree_multimap::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the element at the indicated position and returns a node handle\n  //   owning that extracted data.\n  //\n  // template <typename K> node_type extract(const K& k):\n  //\n  //   Extracts the element with the key matching the passed key value and\n  //   returns a node handle owning that extracted data. If the `btree_multimap`\n  //   does not contain an element with a matching key, this function returns an\n  //   empty node handle.\n  //\n  // NOTE: when compiled in an earlier version of C++ than C++17,\n  // `node_type::key()` returns a const reference to the key instead of a\n  // mutable reference. We cannot safely return a mutable reference without\n  // std::launder (which is not available before C++17).\n  //\n  // NOTE: In this context, `node_type` refers to the C++17 concept of a\n  // move-only type that owns and provides access to the elements in associative\n  // containers (https://en.cppreference.com/w/cpp/container/node_handle).\n  // It does NOT refer to the data layout of the underlying btree.\n  using Base::extract;\n\n  // btree_multimap::extract_and_get_next()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle along with an iterator to the next\n  // element.\n  //\n  // extract_and_get_next_return_type extract_and_get_next(\n  //     const_iterator position):\n  //\n  //   Extracts the element at the indicated position, returns a struct\n  //   containing a member named `node`: a node handle owning that extracted\n  //   data and a member named `next`: an iterator pointing to the next element\n  //   in the btree.\n  using Base::extract_and_get_next;\n\n  // btree_multimap::merge()\n  //\n  // Extracts all elements from a given `source` btree_multimap into this\n  // `btree_multimap`.\n  using Base::merge;\n\n  // btree_multimap::swap(btree_multimap& other)\n  //\n  // Exchanges the contents of this `btree_multimap` with those of the `other`\n  // btree_multimap, avoiding invocation of any move, copy, or swap operations\n  // on individual elements.\n  //\n  // All iterators and references on the `btree_multimap` remain valid,\n  // excepting for the past-the-end iterator, which is invalidated.\n  using Base::swap;\n\n  // btree_multimap::contains()\n  //\n  // template <typename K> bool contains(const K& key) const:\n  //\n  // Determines whether an element comparing equal to the given `key` exists\n  // within the `btree_multimap`, returning `true` if so or `false` otherwise.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::contains;\n\n  // btree_multimap::count()\n  //\n  // template <typename K> size_type count(const K& key) const:\n  //\n  // Returns the number of elements comparing equal to the given `key` within\n  // the `btree_multimap`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::count;\n\n  // btree_multimap::equal_range()\n  //\n  // Returns a half-open range [first, last), defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `btree_multimap`.\n  using Base::equal_range;\n\n  // btree_multimap::find()\n  //\n  // template <typename K> iterator find(const K& key):\n  // template <typename K> const_iterator find(const K& key) const:\n  //\n  // Finds an element with the passed `key` within the `btree_multimap`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::find;\n\n  // btree_multimap::lower_bound()\n  //\n  // template <typename K> iterator lower_bound(const K& key):\n  // template <typename K> const_iterator lower_bound(const K& key) const:\n  //\n  // Finds the first element with a key that is not less than `key` within the\n  // `btree_multimap`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::lower_bound;\n\n  // btree_multimap::upper_bound()\n  //\n  // template <typename K> iterator upper_bound(const K& key):\n  // template <typename K> const_iterator upper_bound(const K& key) const:\n  //\n  // Finds the first element with a key that is greater than `key` within the\n  // `btree_multimap`.\n  //\n  // Supports heterogeneous lookup, provided that the map has a compatible\n  // heterogeneous comparator.\n  using Base::upper_bound;\n\n  // btree_multimap::get_allocator()\n  //\n  // Returns the allocator function associated with this `btree_multimap`.\n  using Base::get_allocator;\n\n  // btree_multimap::key_comp();\n  //\n  // Returns the key comparator associated with this `btree_multimap`.\n  using Base::key_comp;\n\n  // btree_multimap::value_comp();\n  //\n  // Returns the value comparator associated with this `btree_multimap`.\n  using Base::value_comp;\n};\n\n// absl::swap(absl::btree_multimap<>, absl::btree_multimap<>)\n//\n// Swaps the contents of two `absl::btree_multimap` containers.\ntemplate <typename K, typename V, typename C, typename A>\nvoid swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) {\n  return x.swap(y);\n}\n\n// absl::erase_if(absl::btree_multimap<>, Pred)\n//\n// Erases all elements that satisfy the predicate pred from the container.\n// Returns the number of erased elements.\ntemplate <typename K, typename V, typename C, typename A, typename Pred>\ntypename btree_multimap<K, V, C, A>::size_type erase_if(\n    btree_multimap<K, V, C, A> &map, Pred pred) {\n  return container_internal::btree_access::erase_if(map, std::move(pred));\n}\n\nnamespace container_internal {\n\n// A parameters structure for holding the type parameters for a btree_map.\n// Compare and Alloc should be nothrow copy-constructible.\ntemplate <typename Key, typename Data, typename... Params>\nstruct map_params_impl\n    : common_params<\n          Key,\n          GetFromListOr<typename btree_map_defaults<Key, Data>::Compare, 0,\n                        Params...>,\n          GetFromListOr<typename btree_map_defaults<Key, Data>::Alloc, 1,\n                        Params...>,\n          GetFromListOr<typename btree_map_defaults<Key, Data>::TargetNodeSize,\n                        2, Params...>::value,\n          GetFromListOr<typename btree_map_defaults<Key, Data>::IsMulti, 3,\n                        Params...>::value,\n          /*IsMap=*/true, map_slot_policy<Key, Data>> {\n  using super_type = typename map_params_impl::common_params;\n  using mapped_type = Data;\n  // This type allows us to move keys when it is safe to do so. It is safe\n  // for maps in which value_type and mutable_value_type are layout compatible.\n  using slot_policy = typename super_type::slot_policy;\n  using slot_type = typename super_type::slot_type;\n  using value_type = typename super_type::value_type;\n  using init_type = typename super_type::init_type;\n\n  static_assert(\n      std::is_same_v<\n          map_params<\n              Key, Data,\n              GetFromListOr<typename btree_map_defaults<Key, Data>::Compare, 0,\n                            Params...>,\n              GetFromListOr<typename btree_map_defaults<Key, Data>::Alloc, 1,\n                            Params...>,\n              GetFromListOr<\n                  typename btree_map_defaults<Key, Data>::TargetNodeSize, 2,\n                  Params...>::value,\n              GetFromListOr<typename btree_map_defaults<Key, Data>::IsMulti, 3,\n                            Params...>::value>,\n          map_params_impl>);\n\n  template <typename V>\n  static auto key(const V &value ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      -> decltype((value.first)) {\n    return value.first;\n  }\n  static const Key &key(const slot_type *s) { return slot_policy::key(s); }\n  static const Key &key(slot_type *s) { return slot_policy::key(s); }\n  // For use in node handle.\n  static auto mutable_key(slot_type *s)\n      -> decltype(slot_policy::mutable_key(s)) {\n    return slot_policy::mutable_key(s);\n  }\n  static mapped_type &value(value_type *value) { return value->second; }\n};\n\n}  // namespace container_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_BTREE_MAP_H_\n"
  },
  {
    "path": "absl/container/btree_set.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: btree_set.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines B-tree sets: sorted associative containers of\n// values.\n//\n//     * `absl::btree_set<>`\n//     * `absl::btree_multiset<>`\n//\n// These B-tree types are similar to the corresponding types in the STL\n// (`std::set` and `std::multiset`) and generally conform to the STL interfaces\n// of those types. However, because they are implemented using B-trees, they\n// are more efficient in most situations.\n//\n// Unlike `std::set` and `std::multiset`, which are commonly implemented using\n// red-black tree nodes, B-tree sets use more generic B-tree nodes able to hold\n// multiple values per node. Holding multiple values per node often makes\n// B-tree sets perform better than their `std::set` counterparts, because\n// multiple entries can be checked within the same cache hit.\n//\n// However, these types should not be considered drop-in replacements for\n// `std::set` and `std::multiset` as there are some API differences, which are\n// noted in this header file. The most consequential differences with respect to\n// migrating to b-tree from the STL types are listed in the next paragraph.\n// Other API differences are minor.\n//\n// Importantly, insertions and deletions may invalidate outstanding iterators,\n// pointers, and references to elements. Such invalidations are typically only\n// an issue if insertion and deletion operations are interleaved with the use of\n// more than one iterator, pointer, or reference simultaneously. For this\n// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid\n// iterator at the current position.\n//\n// There are other API differences: first, btree iterators can be subtracted,\n// and this is faster than using `std::distance`. Additionally, btree\n// iterators can be advanced via `operator+=` and `operator-=`, which is faster\n// than using `std::advance`.\n//\n// B-tree sets are not exception-safe.\n\n#ifndef ABSL_CONTAINER_BTREE_SET_H_\n#define ABSL_CONTAINER_BTREE_SET_H_\n\n#include <functional>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/container/internal/btree.h\"  // IWYU pragma: export\n#include \"absl/container/internal/btree_container.h\"  // IWYU pragma: export\n#include \"absl/container/internal/common.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace container_internal {\n\ntemplate <typename Key>\nstruct set_slot_policy;\n\ntemplate <typename Key, typename...Params>\nstruct set_params_impl;\n\ntemplate <typename Key>\nstruct btree_set_defaults {\n  using Compare = std::less<Key>;\n  using Alloc = std::allocator<Key>;\n  using TargetNodeSize = std::integral_constant<int, 256>;\n  using IsMulti = std::false_type;\n};\n\ntemplate <typename Key, typename Compare, typename Alloc, int TargetNodeSize,\n          bool IsMulti>\nusing set_params = typename ApplyWithoutDefaultSuffix<\n    set_params_impl,\n    TypeList<void, typename btree_set_defaults<Key>::Compare,\n             typename btree_set_defaults<Key>::Alloc,\n             typename btree_set_defaults<Key>::TargetNodeSize,\n             typename btree_set_defaults<Key>::IsMulti>,\n    TypeList<Key, Compare, Alloc, std::integral_constant<int, TargetNodeSize>,\n             std::integral_constant<bool, IsMulti>>>::type;\n\n}  // namespace container_internal\n\n// absl::btree_set<>\n//\n// An `absl::btree_set<K>` is an ordered associative container of unique key\n// values designed to be a more efficient replacement for `std::set` (in most\n// cases).\n//\n// Keys are sorted using an (optional) comparison function, which defaults to\n// `std::less<K>`.\n//\n// An `absl::btree_set<K>` uses a default allocator of `std::allocator<K>` to\n// allocate (and deallocate) nodes, and construct and destruct values within\n// those nodes. You may instead specify a custom allocator `A` (which in turn\n// requires specifying a custom comparator `C`) as in\n// `absl::btree_set<K, C, A>`.\n//\ntemplate <typename Key, typename Compare = std::less<Key>,\n          typename Alloc = std::allocator<Key>>\nclass ABSL_ATTRIBUTE_OWNER btree_set\n    : public container_internal::btree_set_container<\n          container_internal::btree<container_internal::set_params<\n              Key, Compare, Alloc, /*TargetNodeSize=*/256,\n              /*IsMulti=*/false>>> {\n  using Base = typename btree_set::btree_set_container;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A `btree_set` supports the same overload set as `std::set`\n  // for construction and assignment:\n  //\n  // * Default constructor\n  //\n  //   absl::btree_set<std::string> set1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::btree_set<std::string> set2 =\n  //       {{\"huey\"}, {\"dewey\"}, {\"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::btree_set<std::string> set3(set2);\n  //\n  // * Copy assignment operator\n  //\n  //   absl::btree_set<std::string> set4;\n  //   set4 = set3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::btree_set<std::string> set5(std::move(set4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::btree_set<std::string> set6;\n  //   set6 = std::move(set5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::string> v = {\"a\", \"b\"};\n  //   absl::btree_set<std::string> set7(v.begin(), v.end());\n  btree_set() {}\n  using Base::Base;\n\n  // btree_set::begin()\n  //\n  // Returns an iterator to the beginning of the `btree_set`.\n  using Base::begin;\n\n  // btree_set::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `btree_set`.\n  using Base::cbegin;\n\n  // btree_set::end()\n  //\n  // Returns an iterator to the end of the `btree_set`.\n  using Base::end;\n\n  // btree_set::cend()\n  //\n  // Returns a const iterator to the end of the `btree_set`.\n  using Base::cend;\n\n  // btree_set::empty()\n  //\n  // Returns whether or not the `btree_set` is empty.\n  using Base::empty;\n\n  // btree_set::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `btree_set` under current memory constraints. This value can be thought\n  // of as the largest value of `std::distance(begin(), end())` for a\n  // `btree_set<Key>`.\n  using Base::max_size;\n\n  // btree_set::size()\n  //\n  // Returns the number of elements currently within the `btree_set`.\n  using Base::size;\n\n  // btree_set::clear()\n  //\n  // Removes all elements from the `btree_set`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  using Base::clear;\n\n  // btree_set::erase()\n  //\n  // Erases elements within the `btree_set`. Overloads are listed below.\n  //\n  // iterator erase(iterator position):\n  // iterator erase(const_iterator position):\n  //\n  //   Erases the element at `position` of the `btree_set`, returning\n  //   the iterator pointing to the element after the one that was erased\n  //   (or end() if none exists).\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning\n  //   the iterator pointing to the element after the interval that was erased\n  //   (or end() if none exists).\n  //\n  // template <typename K> size_type erase(const K& key):\n  //\n  //   Erases the element with the matching key, if it exists, returning the\n  //   number of elements erased (0 or 1).\n  using Base::erase;\n\n  // btree_set::insert()\n  //\n  // Inserts an element of the specified value into the `btree_set`,\n  // returning an iterator pointing to the newly inserted element, provided that\n  // an element with the given key does not already exist. If an insertion\n  // occurs, any references, pointers, or iterators are invalidated.\n  // Overloads are listed below.\n  //\n  // std::pair<iterator,bool> insert(const value_type& value):\n  //\n  //   Inserts a value into the `btree_set`. Returns a pair consisting of an\n  //   iterator to the inserted element (or to the element that prevented the\n  //   insertion) and a bool denoting whether the insertion took place.\n  //\n  // std::pair<iterator,bool> insert(value_type&& value):\n  //\n  //   Inserts a moveable value into the `btree_set`. Returns a pair\n  //   consisting of an iterator to the inserted element (or to the element that\n  //   prevented the insertion) and a bool denoting whether the insertion took\n  //   place.\n  //\n  // iterator insert(const_iterator hint, const value_type& value):\n  // iterator insert(const_iterator hint, value_type&& value):\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element, or to the existing element that prevented the\n  //   insertion.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  // void insert(std::initializer_list<init_type> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  using Base::insert;\n\n  // btree_set::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_set`, provided that no element with the given key\n  // already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately.\n  //\n  // If an insertion occurs, any references, pointers, or iterators are\n  // invalidated.\n  using Base::emplace;\n\n  // btree_set::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_set`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search, and only inserts\n  // provided that no element with the given key already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately.\n  //\n  // If an insertion occurs, any references, pointers, or iterators are\n  // invalidated.\n  using Base::emplace_hint;\n\n  // btree_set::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Any references, pointers, or iterators\n  // are invalidated. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the element at the indicated position and returns a node handle\n  //   owning that extracted data.\n  //\n  // template <typename K> node_type extract(const K& k):\n  //\n  //   Extracts the element with the key matching the passed key value and\n  //   returns a node handle owning that extracted data. If the `btree_set`\n  //   does not contain an element with a matching key, this function returns an\n  //   empty node handle.\n  //\n  // NOTE: In this context, `node_type` refers to the C++17 concept of a\n  // move-only type that owns and provides access to the elements in associative\n  // containers (https://en.cppreference.com/w/cpp/container/node_handle).\n  // It does NOT refer to the data layout of the underlying btree.\n  using Base::extract;\n\n  // btree_set::extract_and_get_next()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle along with an iterator to the next\n  // element.\n  //\n  // extract_and_get_next_return_type extract_and_get_next(\n  //     const_iterator position):\n  //\n  //   Extracts the element at the indicated position, returns a struct\n  //   containing a member named `node`: a node handle owning that extracted\n  //   data and a member named `next`: an iterator pointing to the next element\n  //   in the btree.\n  using Base::extract_and_get_next;\n\n  // btree_set::merge()\n  //\n  // Extracts elements from a given `source` btree_set into this\n  // `btree_set`. If the destination `btree_set` already contains an\n  // element with an equivalent key, that element is not extracted.\n  using Base::merge;\n\n  // btree_set::swap(btree_set& other)\n  //\n  // Exchanges the contents of this `btree_set` with those of the `other`\n  // btree_set, avoiding invocation of any move, copy, or swap operations on\n  // individual elements.\n  //\n  // All iterators and references on the `btree_set` remain valid, excepting\n  // for the past-the-end iterator, which is invalidated.\n  using Base::swap;\n\n  // btree_set::contains()\n  //\n  // template <typename K> bool contains(const K& key) const:\n  //\n  // Determines whether an element comparing equal to the given `key` exists\n  // within the `btree_set`, returning `true` if so or `false` otherwise.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::contains;\n\n  // btree_set::count()\n  //\n  // template <typename K> size_type count(const K& key) const:\n  //\n  // Returns the number of elements comparing equal to the given `key` within\n  // the `btree_set`. Note that this function will return either `1` or `0`\n  // since duplicate elements are not allowed within a `btree_set`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::count;\n\n  // btree_set::equal_range()\n  //\n  // Returns a closed range [first, last], defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `btree_set`.\n  using Base::equal_range;\n\n  // btree_set::find()\n  //\n  // template <typename K> iterator find(const K& key):\n  // template <typename K> const_iterator find(const K& key) const:\n  //\n  // Finds an element with the passed `key` within the `btree_set`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::find;\n\n  // btree_set::lower_bound()\n  //\n  // template <typename K> iterator lower_bound(const K& key):\n  // template <typename K> const_iterator lower_bound(const K& key) const:\n  //\n  // Finds the first element that is not less than `key` within the `btree_set`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::lower_bound;\n\n  // btree_set::upper_bound()\n  //\n  // template <typename K> iterator upper_bound(const K& key):\n  // template <typename K> const_iterator upper_bound(const K& key) const:\n  //\n  // Finds the first element that is greater than `key` within the `btree_set`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::upper_bound;\n\n  // btree_set::get_allocator()\n  //\n  // Returns the allocator function associated with this `btree_set`.\n  using Base::get_allocator;\n\n  // btree_set::key_comp();\n  //\n  // Returns the key comparator associated with this `btree_set`.\n  using Base::key_comp;\n\n  // btree_set::value_comp();\n  //\n  // Returns the value comparator associated with this `btree_set`. The keys to\n  // sort the elements are the values themselves, therefore `value_comp` and its\n  // sibling member function `key_comp` are equivalent.\n  using Base::value_comp;\n};\n\n// absl::swap(absl::btree_set<>, absl::btree_set<>)\n//\n// Swaps the contents of two `absl::btree_set` containers.\ntemplate <typename K, typename C, typename A>\nvoid swap(btree_set<K, C, A> &x, btree_set<K, C, A> &y) {\n  return x.swap(y);\n}\n\n// absl::erase_if(absl::btree_set<>, Pred)\n//\n// Erases all elements that satisfy the predicate pred from the container.\n// Returns the number of erased elements.\ntemplate <typename K, typename C, typename A, typename Pred>\ntypename btree_set<K, C, A>::size_type erase_if(btree_set<K, C, A> &set,\n                                                Pred pred) {\n  return container_internal::btree_access::erase_if(set, std::move(pred));\n}\n\n// absl::btree_multiset<>\n//\n// An `absl::btree_multiset<K>` is an ordered associative container of\n// keys and associated values designed to be a more efficient replacement\n// for `std::multiset` (in most cases). Unlike `absl::btree_set`, a B-tree\n// multiset allows equivalent elements.\n//\n// Keys are sorted using an (optional) comparison function, which defaults to\n// `std::less<K>`.\n//\n// An `absl::btree_multiset<K>` uses a default allocator of `std::allocator<K>`\n// to allocate (and deallocate) nodes, and construct and destruct values within\n// those nodes. You may instead specify a custom allocator `A` (which in turn\n// requires specifying a custom comparator `C`) as in\n// `absl::btree_multiset<K, C, A>`.\n//\ntemplate <typename Key, typename Compare = std::less<Key>,\n          typename Alloc = std::allocator<Key>>\nclass ABSL_ATTRIBUTE_OWNER btree_multiset\n    : public container_internal::btree_multiset_container<\n          container_internal::btree<container_internal::set_params<\n              Key, Compare, Alloc, /*TargetNodeSize=*/256,\n              /*IsMulti=*/true>>> {\n  using Base = typename btree_multiset::btree_multiset_container;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A `btree_multiset` supports the same overload set as `std::set`\n  // for construction and assignment:\n  //\n  // * Default constructor\n  //\n  //   absl::btree_multiset<std::string> set1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::btree_multiset<std::string> set2 =\n  //       {{\"huey\"}, {\"dewey\"}, {\"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::btree_multiset<std::string> set3(set2);\n  //\n  // * Copy assignment operator\n  //\n  //   absl::btree_multiset<std::string> set4;\n  //   set4 = set3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::btree_multiset<std::string> set5(std::move(set4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::btree_multiset<std::string> set6;\n  //   set6 = std::move(set5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::string> v = {\"a\", \"b\"};\n  //   absl::btree_multiset<std::string> set7(v.begin(), v.end());\n  btree_multiset() {}\n  using Base::Base;\n\n  // btree_multiset::begin()\n  //\n  // Returns an iterator to the beginning of the `btree_multiset`.\n  using Base::begin;\n\n  // btree_multiset::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `btree_multiset`.\n  using Base::cbegin;\n\n  // btree_multiset::end()\n  //\n  // Returns an iterator to the end of the `btree_multiset`.\n  using Base::end;\n\n  // btree_multiset::cend()\n  //\n  // Returns a const iterator to the end of the `btree_multiset`.\n  using Base::cend;\n\n  // btree_multiset::empty()\n  //\n  // Returns whether or not the `btree_multiset` is empty.\n  using Base::empty;\n\n  // btree_multiset::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `btree_multiset` under current memory constraints. This value can be\n  // thought of as the largest value of `std::distance(begin(), end())` for a\n  // `btree_multiset<Key>`.\n  using Base::max_size;\n\n  // btree_multiset::size()\n  //\n  // Returns the number of elements currently within the `btree_multiset`.\n  using Base::size;\n\n  // btree_multiset::clear()\n  //\n  // Removes all elements from the `btree_multiset`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  using Base::clear;\n\n  // btree_multiset::erase()\n  //\n  // Erases elements within the `btree_multiset`. Overloads are listed below.\n  //\n  // iterator erase(iterator position):\n  // iterator erase(const_iterator position):\n  //\n  //   Erases the element at `position` of the `btree_multiset`, returning\n  //   the iterator pointing to the element after the one that was erased\n  //   (or end() if none exists).\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning\n  //   the iterator pointing to the element after the interval that was erased\n  //   (or end() if none exists).\n  //\n  // template <typename K> size_type erase(const K& key):\n  //\n  //   Erases the elements matching the key, if any exist, returning the\n  //   number of elements erased.\n  using Base::erase;\n\n  // btree_multiset::insert()\n  //\n  // Inserts an element of the specified value into the `btree_multiset`,\n  // returning an iterator pointing to the newly inserted element.\n  // Any references, pointers, or iterators are invalidated.  Overloads are\n  // listed below.\n  //\n  // iterator insert(const value_type& value):\n  //\n  //   Inserts a value into the `btree_multiset`, returning an iterator to the\n  //   inserted element.\n  //\n  // iterator insert(value_type&& value):\n  //\n  //   Inserts a moveable value into the `btree_multiset`, returning an iterator\n  //   to the inserted element.\n  //\n  // iterator insert(const_iterator hint, const value_type& value):\n  // iterator insert(const_iterator hint, value_type&& value):\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  // void insert(std::initializer_list<init_type> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  using Base::insert;\n\n  // btree_multiset::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_multiset`. Any references, pointers, or iterators are\n  // invalidated.\n  using Base::emplace;\n\n  // btree_multiset::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `btree_multiset`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search.\n  //\n  // Any references, pointers, or iterators are invalidated.\n  using Base::emplace_hint;\n\n  // btree_multiset::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the element at the indicated position and returns a node handle\n  //   owning that extracted data.\n  //\n  // template <typename K> node_type extract(const K& k):\n  //\n  //   Extracts the element with the key matching the passed key value and\n  //   returns a node handle owning that extracted data. If the `btree_multiset`\n  //   does not contain an element with a matching key, this function returns an\n  //   empty node handle.\n  //\n  // NOTE: In this context, `node_type` refers to the C++17 concept of a\n  // move-only type that owns and provides access to the elements in associative\n  // containers (https://en.cppreference.com/w/cpp/container/node_handle).\n  // It does NOT refer to the data layout of the underlying btree.\n  using Base::extract;\n\n  // btree_multiset::extract_and_get_next()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle along with an iterator to the next\n  // element.\n  //\n  // extract_and_get_next_return_type extract_and_get_next(\n  //     const_iterator position):\n  //\n  //   Extracts the element at the indicated position, returns a struct\n  //   containing a member named `node`: a node handle owning that extracted\n  //   data and a member named `next`: an iterator pointing to the next element\n  //   in the btree.\n  using Base::extract_and_get_next;\n\n  // btree_multiset::merge()\n  //\n  // Extracts all elements from a given `source` btree_multiset into this\n  // `btree_multiset`.\n  using Base::merge;\n\n  // btree_multiset::swap(btree_multiset& other)\n  //\n  // Exchanges the contents of this `btree_multiset` with those of the `other`\n  // btree_multiset, avoiding invocation of any move, copy, or swap operations\n  // on individual elements.\n  //\n  // All iterators and references on the `btree_multiset` remain valid,\n  // excepting for the past-the-end iterator, which is invalidated.\n  using Base::swap;\n\n  // btree_multiset::contains()\n  //\n  // template <typename K> bool contains(const K& key) const:\n  //\n  // Determines whether an element comparing equal to the given `key` exists\n  // within the `btree_multiset`, returning `true` if so or `false` otherwise.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::contains;\n\n  // btree_multiset::count()\n  //\n  // template <typename K> size_type count(const K& key) const:\n  //\n  // Returns the number of elements comparing equal to the given `key` within\n  // the `btree_multiset`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::count;\n\n  // btree_multiset::equal_range()\n  //\n  // Returns a closed range [first, last], defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `btree_multiset`.\n  using Base::equal_range;\n\n  // btree_multiset::find()\n  //\n  // template <typename K> iterator find(const K& key):\n  // template <typename K> const_iterator find(const K& key) const:\n  //\n  // Finds an element with the passed `key` within the `btree_multiset`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::find;\n\n  // btree_multiset::lower_bound()\n  //\n  // template <typename K> iterator lower_bound(const K& key):\n  // template <typename K> const_iterator lower_bound(const K& key) const:\n  //\n  // Finds the first element that is not less than `key` within the\n  // `btree_multiset`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::lower_bound;\n\n  // btree_multiset::upper_bound()\n  //\n  // template <typename K> iterator upper_bound(const K& key):\n  // template <typename K> const_iterator upper_bound(const K& key) const:\n  //\n  // Finds the first element that is greater than `key` within the\n  // `btree_multiset`.\n  //\n  // Supports heterogeneous lookup, provided that the set has a compatible\n  // heterogeneous comparator.\n  using Base::upper_bound;\n\n  // btree_multiset::get_allocator()\n  //\n  // Returns the allocator function associated with this `btree_multiset`.\n  using Base::get_allocator;\n\n  // btree_multiset::key_comp();\n  //\n  // Returns the key comparator associated with this `btree_multiset`.\n  using Base::key_comp;\n\n  // btree_multiset::value_comp();\n  //\n  // Returns the value comparator associated with this `btree_multiset`. The\n  // keys to sort the elements are the values themselves, therefore `value_comp`\n  // and its sibling member function `key_comp` are equivalent.\n  using Base::value_comp;\n};\n\n// absl::swap(absl::btree_multiset<>, absl::btree_multiset<>)\n//\n// Swaps the contents of two `absl::btree_multiset` containers.\ntemplate <typename K, typename C, typename A>\nvoid swap(btree_multiset<K, C, A> &x, btree_multiset<K, C, A> &y) {\n  return x.swap(y);\n}\n\n// absl::erase_if(absl::btree_multiset<>, Pred)\n//\n// Erases all elements that satisfy the predicate pred from the container.\n// Returns the number of erased elements.\ntemplate <typename K, typename C, typename A, typename Pred>\ntypename btree_multiset<K, C, A>::size_type erase_if(\n   btree_multiset<K, C, A> & set, Pred pred) {\n  return container_internal::btree_access::erase_if(set, std::move(pred));\n}\n\nnamespace container_internal {\n\n// This type implements the necessary functions from the\n// absl::container_internal::slot_type interface for btree_(multi)set.\ntemplate <typename Key>\nstruct set_slot_policy {\n  using slot_type = Key;\n  using value_type = Key;\n  using mutable_value_type = Key;\n\n  static value_type &element(slot_type *slot) { return *slot; }\n  static const value_type &element(const slot_type *slot) { return *slot; }\n\n  template <typename Alloc, class... Args>\n  static void construct(Alloc *alloc, slot_type *slot, Args &&...args) {\n    absl::allocator_traits<Alloc>::construct(*alloc, slot,\n                                             std::forward<Args>(args)...);\n  }\n\n  template <typename Alloc>\n  static void construct(Alloc *alloc, slot_type *slot, slot_type *other) {\n    absl::allocator_traits<Alloc>::construct(*alloc, slot, std::move(*other));\n  }\n\n  template <typename Alloc>\n  static void construct(Alloc *alloc, slot_type *slot, const slot_type *other) {\n    absl::allocator_traits<Alloc>::construct(*alloc, slot, *other);\n  }\n\n  template <typename Alloc>\n  static void destroy(Alloc *alloc, slot_type *slot) {\n    absl::allocator_traits<Alloc>::destroy(*alloc, slot);\n  }\n};\n\n// A parameters structure for holding the type parameters for a btree_set.\n// Compare and Alloc should be nothrow copy-constructible.\ntemplate <typename Key, typename... Params>\nstruct set_params_impl\n    : common_params<\n          Key,\n          GetFromListOr<typename btree_set_defaults<Key>::Compare, 0,\n                        Params...>,\n          GetFromListOr<typename btree_set_defaults<Key>::Alloc, 1, Params...>,\n          GetFromListOr<typename btree_set_defaults<Key>::TargetNodeSize, 2,\n                        Params...>::value,\n          GetFromListOr<typename btree_set_defaults<Key>::IsMulti, 3,\n                        Params...>::value,\n          /*IsMap=*/false, set_slot_policy<Key>> {\n  using value_type = Key;\n  using slot_type = typename set_params_impl::common_params::slot_type;\n\n  static_assert(\n      std::is_same_v<\n          set_params<\n              Key,\n              GetFromListOr<typename btree_set_defaults<Key>::Compare, 0,\n                            Params...>,\n              GetFromListOr<typename btree_set_defaults<Key>::Alloc, 1,\n                            Params...>,\n              GetFromListOr<typename btree_set_defaults<Key>::TargetNodeSize, 2,\n                            Params...>::value,\n              GetFromListOr<typename btree_set_defaults<Key>::IsMulti, 3,\n                            Params...>::value>,\n          set_params_impl>);\n\n  template <typename V>\n  static const V &key(const V &value) {\n    return value;\n  }\n  static const Key &key(const slot_type *slot) { return *slot; }\n  static const Key &key(slot_type *slot) { return *slot; }\n};\n\n}  // namespace container_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_BTREE_SET_H_\n"
  },
  {
    "path": "absl/container/btree_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/btree_test.h\"\n\n#include <algorithm>\n#include <array>\n#include <cstdint>\n#include <functional>\n#include <iostream>\n#include <iterator>\n#include <limits>\n#include <map>\n#include <memory>\n#include <numeric>\n#include <optional>\n#include <stdexcept>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/btree_map.h\"\n#include \"absl/container/btree_set.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/compare.h\"\n\nABSL_FLAG(int, test_values, 10000, \"The number of values to use for tests\");\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::absl::test_internal::CopyableMovableInstance;\nusing ::absl::test_internal::InstanceTracker;\nusing ::absl::test_internal::MovableOnlyInstance;\nusing ::testing::ElementsAre;\nusing ::testing::ElementsAreArray;\nusing ::testing::IsEmpty;\nusing ::testing::IsNull;\nusing ::testing::Pair;\nusing ::testing::SizeIs;\n\ntemplate <typename T, typename U>\nvoid CheckPairEquals(const T &x, const U &y) {\n  ABSL_INTERNAL_CHECK(x == y, \"Values are unequal.\");\n}\n\ntemplate <typename T, typename U, typename V, typename W>\nvoid CheckPairEquals(const std::pair<T, U> &x, const std::pair<V, W> &y) {\n  CheckPairEquals(x.first, y.first);\n  CheckPairEquals(x.second, y.second);\n}\n}  // namespace\n\n// The base class for a sorted associative container checker. TreeType is the\n// container type to check and CheckerType is the container type to check\n// against. TreeType is expected to be btree_{set,map,multiset,multimap} and\n// CheckerType is expected to be {set,map,multiset,multimap}.\ntemplate <typename TreeType, typename CheckerType>\nclass base_checker {\n public:\n  using key_type = typename TreeType::key_type;\n  using value_type = typename TreeType::value_type;\n  using key_compare = typename TreeType::key_compare;\n  using pointer = typename TreeType::pointer;\n  using const_pointer = typename TreeType::const_pointer;\n  using reference = typename TreeType::reference;\n  using const_reference = typename TreeType::const_reference;\n  using size_type = typename TreeType::size_type;\n  using difference_type = typename TreeType::difference_type;\n  using iterator = typename TreeType::iterator;\n  using const_iterator = typename TreeType::const_iterator;\n  using reverse_iterator = typename TreeType::reverse_iterator;\n  using const_reverse_iterator = typename TreeType::const_reverse_iterator;\n\n public:\n  base_checker() : const_tree_(tree_) {}\n  base_checker(const base_checker &other)\n      : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}\n  template <typename InputIterator>\n  base_checker(InputIterator b, InputIterator e)\n      : tree_(b, e), const_tree_(tree_), checker_(b, e) {}\n\n  iterator begin() { return tree_.begin(); }\n  const_iterator begin() const { return tree_.begin(); }\n  iterator end() { return tree_.end(); }\n  const_iterator end() const { return tree_.end(); }\n  reverse_iterator rbegin() { return tree_.rbegin(); }\n  const_reverse_iterator rbegin() const { return tree_.rbegin(); }\n  reverse_iterator rend() { return tree_.rend(); }\n  const_reverse_iterator rend() const { return tree_.rend(); }\n\n  template <typename IterType, typename CheckerIterType>\n  IterType iter_check(IterType tree_iter, CheckerIterType checker_iter) const {\n    if (tree_iter == tree_.end()) {\n      ABSL_INTERNAL_CHECK(checker_iter == checker_.end(),\n                          \"Checker iterator not at end.\");\n    } else {\n      CheckPairEquals(*tree_iter, *checker_iter);\n    }\n    return tree_iter;\n  }\n  template <typename IterType, typename CheckerIterType>\n  IterType riter_check(IterType tree_iter, CheckerIterType checker_iter) const {\n    if (tree_iter == tree_.rend()) {\n      ABSL_INTERNAL_CHECK(checker_iter == checker_.rend(),\n                          \"Checker iterator not at rend.\");\n    } else {\n      CheckPairEquals(*tree_iter, *checker_iter);\n    }\n    return tree_iter;\n  }\n  void value_check(const value_type &v) {\n    typename KeyOfValue<typename TreeType::key_type,\n                        typename TreeType::value_type>::type key_of_value;\n    const key_type &key = key_of_value(v);\n    CheckPairEquals(*find(key), v);\n    lower_bound(key);\n    upper_bound(key);\n    equal_range(key);\n    contains(key);\n    count(key);\n  }\n  void erase_check(const key_type &key) {\n    EXPECT_FALSE(tree_.contains(key));\n    EXPECT_EQ(tree_.find(key), const_tree_.end());\n    EXPECT_FALSE(const_tree_.contains(key));\n    EXPECT_EQ(const_tree_.find(key), tree_.end());\n    EXPECT_EQ(tree_.equal_range(key).first,\n              const_tree_.equal_range(key).second);\n  }\n\n  iterator lower_bound(const key_type &key) {\n    return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));\n  }\n  const_iterator lower_bound(const key_type &key) const {\n    return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));\n  }\n  iterator upper_bound(const key_type &key) {\n    return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));\n  }\n  const_iterator upper_bound(const key_type &key) const {\n    return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));\n  }\n  std::pair<iterator, iterator> equal_range(const key_type &key) {\n    std::pair<typename CheckerType::iterator, typename CheckerType::iterator>\n        checker_res = checker_.equal_range(key);\n    std::pair<iterator, iterator> tree_res = tree_.equal_range(key);\n    iter_check(tree_res.first, checker_res.first);\n    iter_check(tree_res.second, checker_res.second);\n    return tree_res;\n  }\n  std::pair<const_iterator, const_iterator> equal_range(\n      const key_type &key) const {\n    std::pair<typename CheckerType::const_iterator,\n              typename CheckerType::const_iterator>\n        checker_res = checker_.equal_range(key);\n    std::pair<const_iterator, const_iterator> tree_res = tree_.equal_range(key);\n    iter_check(tree_res.first, checker_res.first);\n    iter_check(tree_res.second, checker_res.second);\n    return tree_res;\n  }\n  iterator find(const key_type &key) {\n    return iter_check(tree_.find(key), checker_.find(key));\n  }\n  const_iterator find(const key_type &key) const {\n    return iter_check(tree_.find(key), checker_.find(key));\n  }\n  bool contains(const key_type &key) const { return find(key) != end(); }\n  size_type count(const key_type &key) const {\n    size_type res = checker_.count(key);\n    EXPECT_EQ(res, tree_.count(key));\n    return res;\n  }\n\n  base_checker &operator=(const base_checker &other) {\n    tree_ = other.tree_;\n    checker_ = other.checker_;\n    return *this;\n  }\n\n  int erase(const key_type &key) {\n    int size = tree_.size();\n    int res = checker_.erase(key);\n    EXPECT_EQ(res, tree_.count(key));\n    EXPECT_EQ(res, tree_.erase(key));\n    EXPECT_EQ(tree_.count(key), 0);\n    EXPECT_EQ(tree_.size(), size - res);\n    erase_check(key);\n    return res;\n  }\n  iterator erase(iterator iter) {\n    key_type key = iter.key();\n    int size = tree_.size();\n    int count = tree_.count(key);\n    auto checker_iter = checker_.lower_bound(key);\n    for (iterator tmp(tree_.lower_bound(key)); tmp != iter; ++tmp) {\n      ++checker_iter;\n    }\n    auto checker_next = checker_iter;\n    ++checker_next;\n    checker_.erase(checker_iter);\n    iter = tree_.erase(iter);\n    EXPECT_EQ(tree_.size(), checker_.size());\n    EXPECT_EQ(tree_.size(), size - 1);\n    EXPECT_EQ(tree_.count(key), count - 1);\n    if (count == 1) {\n      erase_check(key);\n    }\n    return iter_check(iter, checker_next);\n  }\n\n  void erase(iterator begin, iterator end) {\n    int size = tree_.size();\n    int count = std::distance(begin, end);\n    auto checker_begin = checker_.lower_bound(begin.key());\n    for (iterator tmp(tree_.lower_bound(begin.key())); tmp != begin; ++tmp) {\n      ++checker_begin;\n    }\n    auto checker_end =\n        end == tree_.end() ? checker_.end() : checker_.lower_bound(end.key());\n    if (end != tree_.end()) {\n      for (iterator tmp(tree_.lower_bound(end.key())); tmp != end; ++tmp) {\n        ++checker_end;\n      }\n    }\n    const auto checker_ret = checker_.erase(checker_begin, checker_end);\n    const auto tree_ret = tree_.erase(begin, end);\n    EXPECT_EQ(std::distance(checker_.begin(), checker_ret),\n              std::distance(tree_.begin(), tree_ret));\n    EXPECT_EQ(tree_.size(), checker_.size());\n    EXPECT_EQ(tree_.size(), size - count);\n  }\n\n  void clear() {\n    tree_.clear();\n    checker_.clear();\n  }\n  void swap(base_checker &other) {\n    tree_.swap(other.tree_);\n    checker_.swap(other.checker_);\n  }\n\n  void verify() const {\n    tree_.verify();\n    EXPECT_EQ(tree_.size(), checker_.size());\n\n    // Move through the forward iterators using increment.\n    auto checker_iter = checker_.begin();\n    const_iterator tree_iter(tree_.begin());\n    for (; tree_iter != tree_.end(); ++tree_iter, ++checker_iter) {\n      CheckPairEquals(*tree_iter, *checker_iter);\n    }\n\n    // Move through the forward iterators using decrement.\n    for (int n = tree_.size() - 1; n >= 0; --n) {\n      iter_check(tree_iter, checker_iter);\n      --tree_iter;\n      --checker_iter;\n    }\n    EXPECT_EQ(tree_iter, tree_.begin());\n    EXPECT_EQ(checker_iter, checker_.begin());\n\n    // Move through the reverse iterators using increment.\n    auto checker_riter = checker_.rbegin();\n    const_reverse_iterator tree_riter(tree_.rbegin());\n    for (; tree_riter != tree_.rend(); ++tree_riter, ++checker_riter) {\n      CheckPairEquals(*tree_riter, *checker_riter);\n    }\n\n    // Move through the reverse iterators using decrement.\n    for (int n = tree_.size() - 1; n >= 0; --n) {\n      riter_check(tree_riter, checker_riter);\n      --tree_riter;\n      --checker_riter;\n    }\n    EXPECT_EQ(tree_riter, tree_.rbegin());\n    EXPECT_EQ(checker_riter, checker_.rbegin());\n  }\n\n  const TreeType &tree() const { return tree_; }\n\n  size_type size() const {\n    EXPECT_EQ(tree_.size(), checker_.size());\n    return tree_.size();\n  }\n  size_type max_size() const { return tree_.max_size(); }\n  bool empty() const {\n    EXPECT_EQ(tree_.empty(), checker_.empty());\n    return tree_.empty();\n  }\n\n protected:\n  TreeType tree_;\n  const TreeType &const_tree_;\n  CheckerType checker_;\n};\n\nnamespace {\n// A checker for unique sorted associative containers. TreeType is expected to\n// be btree_{set,map} and CheckerType is expected to be {set,map}.\ntemplate <typename TreeType, typename CheckerType>\nclass unique_checker : public base_checker<TreeType, CheckerType> {\n  using super_type = base_checker<TreeType, CheckerType>;\n\n public:\n  using iterator = typename super_type::iterator;\n  using value_type = typename super_type::value_type;\n\n public:\n  unique_checker() : super_type() {}\n  unique_checker(const unique_checker &other) : super_type(other) {}\n  template <class InputIterator>\n  unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {}\n  unique_checker &operator=(const unique_checker &) = default;\n\n  // Insertion routines.\n  std::pair<iterator, bool> insert(const value_type &v) {\n    int size = this->tree_.size();\n    std::pair<typename CheckerType::iterator, bool> checker_res =\n        this->checker_.insert(v);\n    std::pair<iterator, bool> tree_res = this->tree_.insert(v);\n    CheckPairEquals(*tree_res.first, *checker_res.first);\n    EXPECT_EQ(tree_res.second, checker_res.second);\n    EXPECT_EQ(this->tree_.size(), this->checker_.size());\n    EXPECT_EQ(this->tree_.size(), size + tree_res.second);\n    return tree_res;\n  }\n  iterator insert(iterator position, const value_type &v) {\n    int size = this->tree_.size();\n    std::pair<typename CheckerType::iterator, bool> checker_res =\n        this->checker_.insert(v);\n    iterator tree_res = this->tree_.insert(position, v);\n    CheckPairEquals(*tree_res, *checker_res.first);\n    EXPECT_EQ(this->tree_.size(), this->checker_.size());\n    EXPECT_EQ(this->tree_.size(), size + checker_res.second);\n    return tree_res;\n  }\n  template <typename InputIterator>\n  void insert(InputIterator b, InputIterator e) {\n    for (; b != e; ++b) {\n      insert(*b);\n    }\n  }\n};\n\n// A checker for multiple sorted associative containers. TreeType is expected\n// to be btree_{multiset,multimap} and CheckerType is expected to be\n// {multiset,multimap}.\ntemplate <typename TreeType, typename CheckerType>\nclass multi_checker : public base_checker<TreeType, CheckerType> {\n  using super_type = base_checker<TreeType, CheckerType>;\n\n public:\n  using iterator = typename super_type::iterator;\n  using value_type = typename super_type::value_type;\n\n public:\n  multi_checker() : super_type() {}\n  multi_checker(const multi_checker &other) : super_type(other) {}\n  template <class InputIterator>\n  multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {}\n  multi_checker &operator=(const multi_checker &) = default;\n\n  // Insertion routines.\n  iterator insert(const value_type &v) {\n    int size = this->tree_.size();\n    auto checker_res = this->checker_.insert(v);\n    iterator tree_res = this->tree_.insert(v);\n    CheckPairEquals(*tree_res, *checker_res);\n    EXPECT_EQ(this->tree_.size(), this->checker_.size());\n    EXPECT_EQ(this->tree_.size(), size + 1);\n    return tree_res;\n  }\n  iterator insert(iterator position, const value_type &v) {\n    int size = this->tree_.size();\n    auto checker_res = this->checker_.insert(v);\n    iterator tree_res = this->tree_.insert(position, v);\n    CheckPairEquals(*tree_res, *checker_res);\n    EXPECT_EQ(this->tree_.size(), this->checker_.size());\n    EXPECT_EQ(this->tree_.size(), size + 1);\n    return tree_res;\n  }\n  template <typename InputIterator>\n  void insert(InputIterator b, InputIterator e) {\n    for (; b != e; ++b) {\n      insert(*b);\n    }\n  }\n};\n\ntemplate <typename T, typename V>\nvoid DoTest(const char *name, T *b, const std::vector<V> &values) {\n  typename KeyOfValue<typename T::key_type, V>::type key_of_value;\n\n  T &mutable_b = *b;\n  const T &const_b = *b;\n\n  // Test insert.\n  for (int i = 0; i < values.size(); ++i) {\n    mutable_b.insert(values[i]);\n    mutable_b.value_check(values[i]);\n  }\n  ASSERT_EQ(mutable_b.size(), values.size());\n\n  const_b.verify();\n\n  // Test copy constructor.\n  T b_copy(const_b);\n  EXPECT_EQ(b_copy.size(), const_b.size());\n  for (int i = 0; i < values.size(); ++i) {\n    CheckPairEquals(*b_copy.find(key_of_value(values[i])), values[i]);\n  }\n\n  // Test range constructor.\n  T b_range(const_b.begin(), const_b.end());\n  EXPECT_EQ(b_range.size(), const_b.size());\n  for (int i = 0; i < values.size(); ++i) {\n    CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);\n  }\n\n  // Test range insertion for values that already exist.\n  b_range.insert(b_copy.begin(), b_copy.end());\n  b_range.verify();\n\n  // Test range insertion for new values.\n  b_range.clear();\n  b_range.insert(b_copy.begin(), b_copy.end());\n  EXPECT_EQ(b_range.size(), b_copy.size());\n  for (int i = 0; i < values.size(); ++i) {\n    CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);\n  }\n\n  // Test assignment to self. Nothing should change.\n  b_range.operator=(b_range);\n  EXPECT_EQ(b_range.size(), b_copy.size());\n\n  // Test assignment of new values.\n  b_range.clear();\n  b_range = b_copy;\n  EXPECT_EQ(b_range.size(), b_copy.size());\n\n  // Test swap.\n  b_range.clear();\n  b_range.swap(b_copy);\n  EXPECT_EQ(b_copy.size(), 0);\n  EXPECT_EQ(b_range.size(), const_b.size());\n  for (int i = 0; i < values.size(); ++i) {\n    CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);\n  }\n  b_range.swap(b_copy);\n\n  // Test non-member function swap.\n  swap(b_range, b_copy);\n  EXPECT_EQ(b_copy.size(), 0);\n  EXPECT_EQ(b_range.size(), const_b.size());\n  for (int i = 0; i < values.size(); ++i) {\n    CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);\n  }\n  swap(b_range, b_copy);\n\n  // Test erase via values.\n  for (int i = 0; i < values.size(); ++i) {\n    mutable_b.erase(key_of_value(values[i]));\n    // Erasing a non-existent key should have no effect.\n    ASSERT_EQ(mutable_b.erase(key_of_value(values[i])), 0);\n  }\n\n  const_b.verify();\n  EXPECT_EQ(const_b.size(), 0);\n\n  // Test erase via iterators.\n  mutable_b = b_copy;\n  for (int i = 0; i < values.size(); ++i) {\n    mutable_b.erase(mutable_b.find(key_of_value(values[i])));\n  }\n\n  const_b.verify();\n  EXPECT_EQ(const_b.size(), 0);\n\n  // Test insert with hint.\n  for (int i = 0; i < values.size(); i++) {\n    mutable_b.insert(mutable_b.upper_bound(key_of_value(values[i])), values[i]);\n  }\n\n  const_b.verify();\n\n  // Test range erase.\n  mutable_b.erase(mutable_b.begin(), mutable_b.end());\n  EXPECT_EQ(mutable_b.size(), 0);\n  const_b.verify();\n\n  // First half.\n  mutable_b = b_copy;\n  typename T::iterator mutable_iter_end = mutable_b.begin();\n  for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end;\n  mutable_b.erase(mutable_b.begin(), mutable_iter_end);\n  EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2);\n  const_b.verify();\n\n  // Second half.\n  mutable_b = b_copy;\n  typename T::iterator mutable_iter_begin = mutable_b.begin();\n  for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin;\n  mutable_b.erase(mutable_iter_begin, mutable_b.end());\n  EXPECT_EQ(mutable_b.size(), values.size() / 2);\n  const_b.verify();\n\n  // Second quarter.\n  mutable_b = b_copy;\n  mutable_iter_begin = mutable_b.begin();\n  for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_begin;\n  mutable_iter_end = mutable_iter_begin;\n  for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end;\n  mutable_b.erase(mutable_iter_begin, mutable_iter_end);\n  EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4);\n  const_b.verify();\n\n  mutable_b.clear();\n}\n\ntemplate <typename T>\nvoid ConstTest() {\n  using value_type = typename T::value_type;\n  typename KeyOfValue<typename T::key_type, value_type>::type key_of_value;\n\n  T mutable_b;\n  const T &const_b = mutable_b;\n\n  // Insert a single value into the container and test looking it up.\n  value_type value = Generator<value_type>(2)(2);\n  mutable_b.insert(value);\n  EXPECT_TRUE(mutable_b.contains(key_of_value(value)));\n  EXPECT_NE(mutable_b.find(key_of_value(value)), const_b.end());\n  EXPECT_TRUE(const_b.contains(key_of_value(value)));\n  EXPECT_NE(const_b.find(key_of_value(value)), mutable_b.end());\n  EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value);\n  EXPECT_EQ(const_b.upper_bound(key_of_value(value)), const_b.end());\n  EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value);\n\n  // We can only create a non-const iterator from a non-const container.\n  typename T::iterator mutable_iter(mutable_b.begin());\n  EXPECT_EQ(mutable_iter, const_b.begin());\n  EXPECT_NE(mutable_iter, const_b.end());\n  EXPECT_EQ(const_b.begin(), mutable_iter);\n  EXPECT_NE(const_b.end(), mutable_iter);\n  typename T::reverse_iterator mutable_riter(mutable_b.rbegin());\n  EXPECT_EQ(mutable_riter, const_b.rbegin());\n  EXPECT_NE(mutable_riter, const_b.rend());\n  EXPECT_EQ(const_b.rbegin(), mutable_riter);\n  EXPECT_NE(const_b.rend(), mutable_riter);\n\n  // We can create a const iterator from a non-const iterator.\n  typename T::const_iterator const_iter(mutable_iter);\n  EXPECT_EQ(const_iter, mutable_b.begin());\n  EXPECT_NE(const_iter, mutable_b.end());\n  EXPECT_EQ(mutable_b.begin(), const_iter);\n  EXPECT_NE(mutable_b.end(), const_iter);\n  typename T::const_reverse_iterator const_riter(mutable_riter);\n  EXPECT_EQ(const_riter, mutable_b.rbegin());\n  EXPECT_NE(const_riter, mutable_b.rend());\n  EXPECT_EQ(mutable_b.rbegin(), const_riter);\n  EXPECT_NE(mutable_b.rend(), const_riter);\n\n  // Make sure various methods can be invoked on a const container.\n  const_b.verify();\n  ASSERT_TRUE(!const_b.empty());\n  EXPECT_EQ(const_b.size(), 1);\n  EXPECT_GT(const_b.max_size(), 0);\n  EXPECT_TRUE(const_b.contains(key_of_value(value)));\n  EXPECT_EQ(const_b.count(key_of_value(value)), 1);\n}\n\ntemplate <typename T, typename C>\nvoid BtreeTest() {\n  ConstTest<T>();\n\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  const std::vector<V> random_values = GenerateValuesWithSeed<V>(\n      absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),\n      GTEST_FLAG_GET(random_seed));\n\n  unique_checker<T, C> container;\n\n  // Test key insertion/deletion in sorted order.\n  std::vector<V> sorted_values(random_values);\n  std::sort(sorted_values.begin(), sorted_values.end());\n  DoTest(\"sorted:    \", &container, sorted_values);\n\n  // Test key insertion/deletion in reverse sorted order.\n  std::reverse(sorted_values.begin(), sorted_values.end());\n  DoTest(\"rsorted:   \", &container, sorted_values);\n\n  // Test key insertion/deletion in random order.\n  DoTest(\"random:    \", &container, random_values);\n}\n\ntemplate <typename T, typename C>\nvoid BtreeMultiTest() {\n  ConstTest<T>();\n\n  using V = typename remove_pair_const<typename T::value_type>::type;\n  const std::vector<V> random_values = GenerateValuesWithSeed<V>(\n      absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),\n      GTEST_FLAG_GET(random_seed));\n\n  multi_checker<T, C> container;\n\n  // Test keys in sorted order.\n  std::vector<V> sorted_values(random_values);\n  std::sort(sorted_values.begin(), sorted_values.end());\n  DoTest(\"sorted:    \", &container, sorted_values);\n\n  // Test keys in reverse sorted order.\n  std::reverse(sorted_values.begin(), sorted_values.end());\n  DoTest(\"rsorted:   \", &container, sorted_values);\n\n  // Test keys in random order.\n  DoTest(\"random:    \", &container, random_values);\n\n  // Test keys in random order w/ duplicates.\n  std::vector<V> duplicate_values(random_values);\n  duplicate_values.insert(duplicate_values.end(), random_values.begin(),\n                          random_values.end());\n  DoTest(\"duplicates:\", &container, duplicate_values);\n\n  // Test all identical keys.\n  std::vector<V> identical_values(100);\n  std::fill(identical_values.begin(), identical_values.end(),\n            Generator<V>(2)(2));\n  DoTest(\"identical: \", &container, identical_values);\n}\n\ntemplate <typename T>\nvoid BtreeMapTest() {\n  using value_type = typename T::value_type;\n  using mapped_type = typename T::mapped_type;\n\n  mapped_type m = Generator<mapped_type>(0)(0);\n  (void)m;\n\n  T b;\n\n  // Verify we can insert using operator[].\n  for (int i = 0; i < 1000; i++) {\n    value_type v = Generator<value_type>(1000)(i);\n    b[v.first] = v.second;\n  }\n  EXPECT_EQ(b.size(), 1000);\n\n  // Test whether we can use the \"->\" operator on iterators and\n  // reverse_iterators. This stresses the btree_map_params::pair_pointer\n  // mechanism.\n  EXPECT_EQ(b.begin()->first, Generator<value_type>(1000)(0).first);\n  EXPECT_EQ(b.begin()->second, Generator<value_type>(1000)(0).second);\n  EXPECT_EQ(b.rbegin()->first, Generator<value_type>(1000)(999).first);\n  EXPECT_EQ(b.rbegin()->second, Generator<value_type>(1000)(999).second);\n}\n\ntemplate <typename T>\nvoid BtreeMultiMapTest() {\n  using mapped_type = typename T::mapped_type;\n  mapped_type m = Generator<mapped_type>(0)(0);\n  (void)m;\n}\n\ntemplate <typename K, int N = 256>\nvoid SetTest() {\n  EXPECT_EQ(\n      sizeof(absl::btree_set<K>),\n      2 * sizeof(void *) + sizeof(typename absl::btree_set<K>::size_type));\n  using BtreeSet = absl::btree_set<K>;\n  BtreeTest<BtreeSet, std::set<K>>();\n}\n\ntemplate <typename K, int N = 256>\nvoid MapTest() {\n  EXPECT_EQ(\n      sizeof(absl::btree_map<K, K>),\n      2 * sizeof(void *) + sizeof(typename absl::btree_map<K, K>::size_type));\n  using BtreeMap = absl::btree_map<K, K>;\n  BtreeTest<BtreeMap, std::map<K, K>>();\n  BtreeMapTest<BtreeMap>();\n}\n\nTEST(Btree, set_int32) { SetTest<int32_t>(); }\nTEST(Btree, set_string) { SetTest<std::string>(); }\nTEST(Btree, set_cord) { SetTest<absl::Cord>(); }\nTEST(Btree, map_int32) { MapTest<int32_t>(); }\nTEST(Btree, map_string) { MapTest<std::string>(); }\nTEST(Btree, map_cord) { MapTest<absl::Cord>(); }\n\ntemplate <typename K, int N = 256>\nvoid MultiSetTest() {\n  EXPECT_EQ(\n      sizeof(absl::btree_multiset<K>),\n      2 * sizeof(void *) + sizeof(typename absl::btree_multiset<K>::size_type));\n  using BtreeMSet = absl::btree_multiset<K>;\n  BtreeMultiTest<BtreeMSet, std::multiset<K>>();\n}\n\ntemplate <typename K, int N = 256>\nvoid MultiMapTest() {\n  EXPECT_EQ(sizeof(absl::btree_multimap<K, K>),\n            2 * sizeof(void *) +\n                sizeof(typename absl::btree_multimap<K, K>::size_type));\n  using BtreeMMap = absl::btree_multimap<K, K>;\n  BtreeMultiTest<BtreeMMap, std::multimap<K, K>>();\n  BtreeMultiMapTest<BtreeMMap>();\n}\n\nTEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }\nTEST(Btree, multiset_string) { MultiSetTest<std::string>(); }\nTEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }\nTEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }\nTEST(Btree, multimap_string) { MultiMapTest<std::string>(); }\nTEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }\n\nstruct CompareIntToString {\n  bool operator()(const std::string &a, const std::string &b) const {\n    return a < b;\n  }\n  bool operator()(const std::string &a, int b) const {\n    return a < absl::StrCat(b);\n  }\n  bool operator()(int a, const std::string &b) const {\n    return absl::StrCat(a) < b;\n  }\n  using is_transparent = void;\n};\n\nstruct NonTransparentCompare {\n  template <typename T, typename U>\n  bool operator()(const T &t, const U &u) const {\n    // Treating all comparators as transparent can cause inefficiencies (see\n    // N3657 C++ proposal). Test that for comparators without 'is_transparent'\n    // alias (like this one), we do not attempt heterogeneous lookup.\n    EXPECT_TRUE((std::is_same<T, U>()));\n    return t < u;\n  }\n};\n\ntemplate <typename T>\nbool CanEraseWithEmptyBrace(T t, decltype(t.erase({})) *) {\n  return true;\n}\n\ntemplate <typename T>\nbool CanEraseWithEmptyBrace(T, ...) {\n  return false;\n}\n\ntemplate <typename T>\nvoid TestHeterogeneous(T table) {\n  auto lb = table.lower_bound(\"3\");\n  EXPECT_EQ(lb, table.lower_bound(3));\n  EXPECT_NE(lb, table.lower_bound(4));\n  EXPECT_EQ(lb, table.lower_bound({\"3\"}));\n  EXPECT_NE(lb, table.lower_bound({}));\n\n  auto ub = table.upper_bound(\"3\");\n  EXPECT_EQ(ub, table.upper_bound(3));\n  EXPECT_NE(ub, table.upper_bound(5));\n  EXPECT_EQ(ub, table.upper_bound({\"3\"}));\n  EXPECT_NE(ub, table.upper_bound({}));\n\n  auto er = table.equal_range(\"3\");\n  EXPECT_EQ(er, table.equal_range(3));\n  EXPECT_NE(er, table.equal_range(4));\n  EXPECT_EQ(er, table.equal_range({\"3\"}));\n  EXPECT_NE(er, table.equal_range({}));\n\n  auto it = table.find(\"3\");\n  EXPECT_EQ(it, table.find(3));\n  EXPECT_NE(it, table.find(4));\n  EXPECT_EQ(it, table.find({\"3\"}));\n  EXPECT_NE(it, table.find({}));\n\n  EXPECT_TRUE(table.contains(3));\n  EXPECT_FALSE(table.contains(4));\n  EXPECT_TRUE(table.count({\"3\"}));\n  EXPECT_FALSE(table.contains({}));\n\n  EXPECT_EQ(1, table.count(3));\n  EXPECT_EQ(0, table.count(4));\n  EXPECT_EQ(1, table.count({\"3\"}));\n  EXPECT_EQ(0, table.count({}));\n\n  auto copy = table;\n  copy.erase(3);\n  EXPECT_EQ(table.size() - 1, copy.size());\n  copy.erase(4);\n  EXPECT_EQ(table.size() - 1, copy.size());\n  copy.erase({\"5\"});\n  EXPECT_EQ(table.size() - 2, copy.size());\n  EXPECT_FALSE(CanEraseWithEmptyBrace(table, nullptr));\n\n  // Also run it with const T&.\n  if (std::is_class<T>()) TestHeterogeneous<const T &>(table);\n}\n\nTEST(Btree, HeterogeneousLookup) {\n  TestHeterogeneous(btree_set<std::string, CompareIntToString>{\"1\", \"3\", \"5\"});\n  TestHeterogeneous(btree_map<std::string, int, CompareIntToString>{\n      {\"1\", 1}, {\"3\", 3}, {\"5\", 5}});\n  TestHeterogeneous(\n      btree_multiset<std::string, CompareIntToString>{\"1\", \"3\", \"5\"});\n  TestHeterogeneous(btree_multimap<std::string, int, CompareIntToString>{\n      {\"1\", 1}, {\"3\", 3}, {\"5\", 5}});\n\n  // Only maps have .at()\n  btree_map<std::string, int, CompareIntToString> map{\n      {\"\", -1}, {\"1\", 1}, {\"3\", 3}, {\"5\", 5}};\n  EXPECT_EQ(1, map.at(1));\n  EXPECT_EQ(3, map.at({\"3\"}));\n  EXPECT_EQ(-1, map.at({}));\n  const auto &cmap = map;\n  EXPECT_EQ(1, cmap.at(1));\n  EXPECT_EQ(3, cmap.at({\"3\"}));\n  EXPECT_EQ(-1, cmap.at({}));\n}\n\nTEST(Btree, NoHeterogeneousLookupWithoutAlias) {\n  using StringSet = absl::btree_set<std::string, NonTransparentCompare>;\n  StringSet s;\n  ASSERT_TRUE(s.insert(\"hello\").second);\n  ASSERT_TRUE(s.insert(\"world\").second);\n  EXPECT_TRUE(s.end() == s.find(\"blah\"));\n  EXPECT_TRUE(s.begin() == s.lower_bound(\"hello\"));\n  EXPECT_EQ(1, s.count(\"world\"));\n  EXPECT_TRUE(s.contains(\"hello\"));\n  EXPECT_TRUE(s.contains(\"world\"));\n  EXPECT_FALSE(s.contains(\"blah\"));\n\n  using StringMultiSet =\n      absl::btree_multiset<std::string, NonTransparentCompare>;\n  StringMultiSet ms;\n  ms.insert(\"hello\");\n  ms.insert(\"world\");\n  ms.insert(\"world\");\n  EXPECT_TRUE(ms.end() == ms.find(\"blah\"));\n  EXPECT_TRUE(ms.begin() == ms.lower_bound(\"hello\"));\n  EXPECT_EQ(2, ms.count(\"world\"));\n  EXPECT_TRUE(ms.contains(\"hello\"));\n  EXPECT_TRUE(ms.contains(\"world\"));\n  EXPECT_FALSE(ms.contains(\"blah\"));\n}\n\nTEST(Btree, DefaultTransparent) {\n  {\n    // `int` does not have a default transparent comparator.\n    // The input value is converted to key_type.\n    btree_set<int> s = {1};\n    double d = 1.1;\n    EXPECT_EQ(s.begin(), s.find(d));\n    EXPECT_TRUE(s.contains(d));\n  }\n\n  {\n    // `std::string` has heterogeneous support.\n    btree_set<std::string> s = {\"A\"};\n    EXPECT_EQ(s.begin(), s.find(absl::string_view(\"A\")));\n    EXPECT_TRUE(s.contains(absl::string_view(\"A\")));\n  }\n}\n\nclass StringLike {\n public:\n  StringLike() = default;\n\n  StringLike(const char *s) : s_(s) {  // NOLINT\n    ++constructor_calls_;\n  }\n\n  bool operator<(const StringLike &a) const { return s_ < a.s_; }\n\n  static void clear_constructor_call_count() { constructor_calls_ = 0; }\n\n  static int constructor_calls() { return constructor_calls_; }\n\n private:\n  static int constructor_calls_;\n  std::string s_;\n};\n\nint StringLike::constructor_calls_ = 0;\n\nTEST(Btree, HeterogeneousLookupDoesntDegradePerformance) {\n  using StringSet = absl::btree_set<StringLike>;\n  StringSet s;\n  for (int i = 0; i < 100; ++i) {\n    ASSERT_TRUE(s.insert(absl::StrCat(i).c_str()).second);\n  }\n  StringLike::clear_constructor_call_count();\n  s.find(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n\n  StringLike::clear_constructor_call_count();\n  s.contains(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n\n  StringLike::clear_constructor_call_count();\n  s.count(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n\n  StringLike::clear_constructor_call_count();\n  s.lower_bound(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n\n  StringLike::clear_constructor_call_count();\n  s.upper_bound(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n\n  StringLike::clear_constructor_call_count();\n  s.equal_range(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n\n  StringLike::clear_constructor_call_count();\n  s.erase(\"50\");\n  ASSERT_EQ(1, StringLike::constructor_calls());\n}\n\n// Verify that swapping btrees swaps the key comparison functors and that we can\n// use non-default constructible comparators.\nstruct SubstringLess {\n  SubstringLess() = delete;\n  explicit SubstringLess(int length) : n(length) {}\n  bool operator()(const std::string &a, const std::string &b) const {\n    return absl::string_view(a).substr(0, n) <\n           absl::string_view(b).substr(0, n);\n  }\n  int n;\n};\n\nTEST(Btree, SwapKeyCompare) {\n  using SubstringSet = absl::btree_set<std::string, SubstringLess>;\n  SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type());\n  SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type());\n\n  ASSERT_TRUE(s1.insert(\"a\").second);\n  ASSERT_FALSE(s1.insert(\"aa\").second);\n\n  ASSERT_TRUE(s2.insert(\"a\").second);\n  ASSERT_TRUE(s2.insert(\"aa\").second);\n  ASSERT_FALSE(s2.insert(\"aaa\").second);\n\n  swap(s1, s2);\n\n  ASSERT_TRUE(s1.insert(\"b\").second);\n  ASSERT_TRUE(s1.insert(\"bb\").second);\n  ASSERT_FALSE(s1.insert(\"bbb\").second);\n\n  ASSERT_TRUE(s2.insert(\"b\").second);\n  ASSERT_FALSE(s2.insert(\"bb\").second);\n}\n\nTEST(Btree, UpperBoundRegression) {\n  // Regress a bug where upper_bound would default-construct a new key_compare\n  // instead of copying the existing one.\n  using SubstringSet = absl::btree_set<std::string, SubstringLess>;\n  SubstringSet my_set(SubstringLess(3));\n  my_set.insert(\"aab\");\n  my_set.insert(\"abb\");\n  // We call upper_bound(\"aaa\").  If this correctly uses the length 3\n  // comparator, aaa < aab < abb, so we should get aab as the result.\n  // If it instead uses the default-constructed length 2 comparator,\n  // aa == aa < ab, so we'll get abb as our result.\n  SubstringSet::iterator it = my_set.upper_bound(\"aaa\");\n  ASSERT_TRUE(it != my_set.end());\n  EXPECT_EQ(\"aab\", *it);\n}\n\nTEST(Btree, Comparison) {\n  const int kSetSize = 1201;\n  absl::btree_set<int64_t> my_set;\n  for (int i = 0; i < kSetSize; ++i) {\n    my_set.insert(i);\n  }\n  absl::btree_set<int64_t> my_set_copy(my_set);\n  EXPECT_TRUE(my_set_copy == my_set);\n  EXPECT_TRUE(my_set == my_set_copy);\n  EXPECT_FALSE(my_set_copy != my_set);\n  EXPECT_FALSE(my_set != my_set_copy);\n\n  my_set.insert(kSetSize);\n  EXPECT_FALSE(my_set_copy == my_set);\n  EXPECT_FALSE(my_set == my_set_copy);\n  EXPECT_TRUE(my_set_copy != my_set);\n  EXPECT_TRUE(my_set != my_set_copy);\n\n  my_set.erase(kSetSize - 1);\n  EXPECT_FALSE(my_set_copy == my_set);\n  EXPECT_FALSE(my_set == my_set_copy);\n  EXPECT_TRUE(my_set_copy != my_set);\n  EXPECT_TRUE(my_set != my_set_copy);\n\n  absl::btree_map<std::string, int64_t> my_map;\n  for (int i = 0; i < kSetSize; ++i) {\n    my_map[std::string(i, 'a')] = i;\n  }\n  absl::btree_map<std::string, int64_t> my_map_copy(my_map);\n  EXPECT_TRUE(my_map_copy == my_map);\n  EXPECT_TRUE(my_map == my_map_copy);\n  EXPECT_FALSE(my_map_copy != my_map);\n  EXPECT_FALSE(my_map != my_map_copy);\n\n  ++my_map_copy[std::string(7, 'a')];\n  EXPECT_FALSE(my_map_copy == my_map);\n  EXPECT_FALSE(my_map == my_map_copy);\n  EXPECT_TRUE(my_map_copy != my_map);\n  EXPECT_TRUE(my_map != my_map_copy);\n\n  my_map_copy = my_map;\n  my_map[\"hello\"] = kSetSize;\n  EXPECT_FALSE(my_map_copy == my_map);\n  EXPECT_FALSE(my_map == my_map_copy);\n  EXPECT_TRUE(my_map_copy != my_map);\n  EXPECT_TRUE(my_map != my_map_copy);\n\n  my_map.erase(std::string(kSetSize - 1, 'a'));\n  EXPECT_FALSE(my_map_copy == my_map);\n  EXPECT_FALSE(my_map == my_map_copy);\n  EXPECT_TRUE(my_map_copy != my_map);\n  EXPECT_TRUE(my_map != my_map_copy);\n}\n\nTEST(Btree, RangeCtorSanity) {\n  std::vector<int> ivec;\n  ivec.push_back(1);\n  std::map<int, int> imap;\n  imap.insert(std::make_pair(1, 2));\n  absl::btree_multiset<int> tmset(ivec.begin(), ivec.end());\n  absl::btree_multimap<int, int> tmmap(imap.begin(), imap.end());\n  absl::btree_set<int> tset(ivec.begin(), ivec.end());\n  absl::btree_map<int, int> tmap(imap.begin(), imap.end());\n  EXPECT_EQ(1, tmset.size());\n  EXPECT_EQ(1, tmmap.size());\n  EXPECT_EQ(1, tset.size());\n  EXPECT_EQ(1, tmap.size());\n}\n\n}  // namespace\n\nclass BtreeNodePeer {\n public:\n  // Yields the size of a leaf node with a specific number of values.\n  template <typename ValueType>\n  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {\n    return btree_node<\n        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,\n                   /*TargetNodeSize=*/256,  // This parameter isn't used here.\n                   /*Multi=*/false>>::SizeWithNSlots(target_values_per_node);\n  }\n\n  // Yields the number of slots in a (non-root) leaf node for this btree.\n  template <typename Btree>\n  constexpr static size_t GetNumSlotsPerNode() {\n    return btree_node<typename Btree::params_type>::kNodeSlots;\n  }\n\n  template <typename Btree>\n  constexpr static size_t GetMaxFieldType() {\n    return std::numeric_limits<\n        typename btree_node<typename Btree::params_type>::field_type>::max();\n  }\n\n  template <typename Btree>\n  constexpr static bool UsesLinearNodeSearch() {\n    return btree_node<typename Btree::params_type>::use_linear_search::value;\n  }\n\n  template <typename Btree>\n  constexpr static bool FieldTypeEqualsSlotType() {\n    return std::is_same<\n        typename btree_node<typename Btree::params_type>::field_type,\n        typename btree_node<typename Btree::params_type>::slot_type>::value;\n  }\n};\n\nnamespace {\n\nclass BtreeMapTest : public ::testing::Test {\n public:\n  struct Key {};\n  struct Cmp {\n    template <typename T>\n    bool operator()(T, T) const {\n      return false;\n    }\n  };\n\n  struct KeyLin {\n    using absl_btree_prefer_linear_node_search = std::true_type;\n  };\n  struct CmpLin : Cmp {\n    using absl_btree_prefer_linear_node_search = std::true_type;\n  };\n\n  struct KeyBin {\n    using absl_btree_prefer_linear_node_search = std::false_type;\n  };\n  struct CmpBin : Cmp {\n    using absl_btree_prefer_linear_node_search = std::false_type;\n  };\n\n  template <typename K, typename C>\n  static bool IsLinear() {\n    return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();\n  }\n};\n\nTEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {\n  // Test requesting linear search by directly exporting an alias.\n  EXPECT_FALSE((IsLinear<Key, Cmp>()));\n  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));\n  EXPECT_TRUE((IsLinear<Key, CmpLin>()));\n  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));\n}\n\nTEST_F(BtreeMapTest, LinearChoiceTree) {\n  // Cmp has precedence, and is forcing binary\n  EXPECT_FALSE((IsLinear<Key, CmpBin>()));\n  EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));\n  EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));\n  EXPECT_FALSE((IsLinear<int, CmpBin>()));\n  EXPECT_FALSE((IsLinear<std::string, CmpBin>()));\n  // Cmp has precedence, and is forcing linear\n  EXPECT_TRUE((IsLinear<Key, CmpLin>()));\n  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));\n  EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));\n  EXPECT_TRUE((IsLinear<int, CmpLin>()));\n  EXPECT_TRUE((IsLinear<std::string, CmpLin>()));\n  // Cmp has no preference, Key determines linear vs binary.\n  EXPECT_FALSE((IsLinear<Key, Cmp>()));\n  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));\n  EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));\n  // arithmetic key w/ std::less or std::greater: linear\n  EXPECT_TRUE((IsLinear<int, std::less<int>>()));\n  EXPECT_TRUE((IsLinear<double, std::greater<double>>()));\n  // arithmetic key w/ custom compare: binary\n  EXPECT_FALSE((IsLinear<int, Cmp>()));\n  // non-arithmetic key: binary\n  EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));\n}\n\nTEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {\n  absl::btree_map<std::string, std::unique_ptr<std::string>> m;\n\n  std::unique_ptr<std::string> &v = m[\"A\"];\n  EXPECT_TRUE(v == nullptr);\n  v = absl::make_unique<std::string>(\"X\");\n\n  auto iter = m.find(\"A\");\n  EXPECT_EQ(\"X\", *iter->second);\n}\n\nTEST(Btree, InitializerListConstructor) {\n  absl::btree_set<std::string> set({\"a\", \"b\"});\n  EXPECT_EQ(set.count(\"a\"), 1);\n  EXPECT_EQ(set.count(\"b\"), 1);\n\n  absl::btree_multiset<int> mset({1, 1, 4});\n  EXPECT_EQ(mset.count(1), 2);\n  EXPECT_EQ(mset.count(4), 1);\n\n  absl::btree_map<int, int> map({{1, 5}, {2, 10}});\n  EXPECT_EQ(map[1], 5);\n  EXPECT_EQ(map[2], 10);\n\n  absl::btree_multimap<int, int> mmap({{1, 5}, {1, 10}});\n  auto range = mmap.equal_range(1);\n  auto it = range.first;\n  ASSERT_NE(it, range.second);\n  EXPECT_EQ(it->second, 5);\n  ASSERT_NE(++it, range.second);\n  EXPECT_EQ(it->second, 10);\n  EXPECT_EQ(++it, range.second);\n}\n\nTEST(Btree, InitializerListInsert) {\n  absl::btree_set<std::string> set;\n  set.insert({\"a\", \"b\"});\n  EXPECT_EQ(set.count(\"a\"), 1);\n  EXPECT_EQ(set.count(\"b\"), 1);\n\n  absl::btree_multiset<int> mset;\n  mset.insert({1, 1, 4});\n  EXPECT_EQ(mset.count(1), 2);\n  EXPECT_EQ(mset.count(4), 1);\n\n  absl::btree_map<int, int> map;\n  map.insert({{1, 5}, {2, 10}});\n  // Test that inserting one element using an initializer list also works.\n  map.insert({3, 15});\n  EXPECT_EQ(map[1], 5);\n  EXPECT_EQ(map[2], 10);\n  EXPECT_EQ(map[3], 15);\n\n  absl::btree_multimap<int, int> mmap;\n  mmap.insert({{1, 5}, {1, 10}});\n  auto range = mmap.equal_range(1);\n  auto it = range.first;\n  ASSERT_NE(it, range.second);\n  EXPECT_EQ(it->second, 5);\n  ASSERT_NE(++it, range.second);\n  EXPECT_EQ(it->second, 10);\n  EXPECT_EQ(++it, range.second);\n}\n\ntemplate <typename Compare, typename Key>\nvoid AssertKeyCompareStringAdapted() {\n  using Adapted = typename key_compare_adapter<Compare, Key>::type;\n  static_assert(\n      std::is_same<Adapted, StringBtreeDefaultLess>::value ||\n          std::is_same<Adapted, StringBtreeDefaultGreater>::value,\n      \"key_compare_adapter should have string-adapted this comparator.\");\n}\ntemplate <typename Compare, typename Key>\nvoid AssertKeyCompareNotStringAdapted() {\n  using Adapted = typename key_compare_adapter<Compare, Key>::type;\n  static_assert(\n      !std::is_same<Adapted, StringBtreeDefaultLess>::value &&\n          !std::is_same<Adapted, StringBtreeDefaultGreater>::value,\n      \"key_compare_adapter shouldn't have string-adapted this comparator.\");\n}\n\nTEST(Btree, KeyCompareAdapter) {\n  AssertKeyCompareStringAdapted<std::less<std::string>, std::string>();\n  AssertKeyCompareStringAdapted<std::greater<std::string>, std::string>();\n  AssertKeyCompareStringAdapted<std::less<absl::string_view>,\n                                absl::string_view>();\n  AssertKeyCompareStringAdapted<std::greater<absl::string_view>,\n                                absl::string_view>();\n  AssertKeyCompareStringAdapted<std::less<absl::Cord>, absl::Cord>();\n  AssertKeyCompareStringAdapted<std::greater<absl::Cord>, absl::Cord>();\n  AssertKeyCompareNotStringAdapted<std::less<int>, int>();\n  AssertKeyCompareNotStringAdapted<std::greater<int>, int>();\n}\n\nTEST(Btree, RValueInsert) {\n  InstanceTracker tracker;\n\n  absl::btree_set<MovableOnlyInstance> set;\n  set.insert(MovableOnlyInstance(1));\n  set.insert(MovableOnlyInstance(3));\n  MovableOnlyInstance two(2);\n  set.insert(set.find(MovableOnlyInstance(3)), std::move(two));\n  auto it = set.find(MovableOnlyInstance(2));\n  ASSERT_NE(it, set.end());\n  ASSERT_NE(++it, set.end());\n  EXPECT_EQ(it->value(), 3);\n\n  absl::btree_multiset<MovableOnlyInstance> mset;\n  MovableOnlyInstance zero(0);\n  MovableOnlyInstance zero2(0);\n  mset.insert(std::move(zero));\n  mset.insert(mset.find(MovableOnlyInstance(0)), std::move(zero2));\n  EXPECT_EQ(mset.count(MovableOnlyInstance(0)), 2);\n\n  absl::btree_map<int, MovableOnlyInstance> map;\n  std::pair<const int, MovableOnlyInstance> p1 = {1, MovableOnlyInstance(5)};\n  std::pair<const int, MovableOnlyInstance> p2 = {2, MovableOnlyInstance(10)};\n  std::pair<const int, MovableOnlyInstance> p3 = {3, MovableOnlyInstance(15)};\n  map.insert(std::move(p1));\n  map.insert(std::move(p3));\n  map.insert(map.find(3), std::move(p2));\n  ASSERT_NE(map.find(2), map.end());\n  EXPECT_EQ(map.find(2)->second.value(), 10);\n\n  absl::btree_multimap<int, MovableOnlyInstance> mmap;\n  std::pair<const int, MovableOnlyInstance> p4 = {1, MovableOnlyInstance(5)};\n  std::pair<const int, MovableOnlyInstance> p5 = {1, MovableOnlyInstance(10)};\n  mmap.insert(std::move(p4));\n  mmap.insert(mmap.find(1), std::move(p5));\n  auto range = mmap.equal_range(1);\n  auto it1 = range.first;\n  ASSERT_NE(it1, range.second);\n  EXPECT_EQ(it1->second.value(), 10);\n  ASSERT_NE(++it1, range.second);\n  EXPECT_EQ(it1->second.value(), 5);\n  EXPECT_EQ(++it1, range.second);\n\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.swaps(), 0);\n}\n\ntemplate <typename Cmp>\nstruct CheckedCompareOptedOutCmp : Cmp, BtreeTestOnlyCheckedCompareOptOutBase {\n  using Cmp::Cmp;\n  CheckedCompareOptedOutCmp() {}\n  CheckedCompareOptedOutCmp(Cmp cmp) : Cmp(std::move(cmp)) {}  // NOLINT\n};\n\n// A btree set with a specific number of values per node. Opt out of\n// checked_compare so that we can expect exact numbers of comparisons.\ntemplate <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>\nclass SizedBtreeSet\n    : public btree_set_container<btree<\n          set_params<Key, CheckedCompareOptedOutCmp<Cmp>, std::allocator<Key>,\n                     BtreeNodePeer::GetTargetNodeSize<Key>(TargetValuesPerNode),\n                     /*Multi=*/false>>> {\n  using Base = typename SizedBtreeSet::btree_set_container;\n\n public:\n  SizedBtreeSet() = default;\n  using Base::Base;\n};\n\ntemplate <typename Set>\nvoid ExpectOperationCounts(const int expected_moves,\n                           const int expected_comparisons,\n                           const std::vector<int> &values,\n                           InstanceTracker *tracker, Set *set) {\n  for (const int v : values) set->insert(MovableOnlyInstance(v));\n  set->clear();\n  EXPECT_EQ(tracker->moves(), expected_moves);\n  EXPECT_EQ(tracker->comparisons(), expected_comparisons);\n  EXPECT_EQ(tracker->copies(), 0);\n  EXPECT_EQ(tracker->swaps(), 0);\n  tracker->ResetCopiesMovesSwaps();\n}\n\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_HWADDRESS_SANITIZER)\nconstexpr bool kAsan = true;\n#else\nconstexpr bool kAsan = false;\n#endif\n\n// Note: when the values in this test change, it is expected to have an impact\n// on performance.\nTEST(Btree, MovesComparisonsCopiesSwapsTracking) {\n  if (kAsan) GTEST_SKIP() << \"We do extra operations in ASan mode.\";\n\n  InstanceTracker tracker;\n  // Note: this is minimum number of values per node.\n  SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4> set4;\n  // Note: this is the default number of values per node for a set of int32s\n  // (with 64-bit pointers).\n  SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61> set61;\n  SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100> set100;\n\n  // Don't depend on flags for random values because then the expectations will\n  // fail if the flags change.\n  std::vector<int> values =\n      GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);\n\n  EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);\n  EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);\n  EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);\n  if (sizeof(void *) == 8) {\n    EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),\n              // When we have generations, there is one fewer slot.\n              BtreeGenerationsEnabled() ? 60 : 61);\n  }\n\n  // Test key insertion/deletion in random order.\n  ExpectOperationCounts(56540, 134212, values, &tracker, &set4);\n  ExpectOperationCounts(386718, 129807, values, &tracker, &set61);\n  ExpectOperationCounts(586761, 130310, values, &tracker, &set100);\n\n  // Test key insertion/deletion in sorted order.\n  std::sort(values.begin(), values.end());\n  ExpectOperationCounts(24972, 85563, values, &tracker, &set4);\n  ExpectOperationCounts(20208, 87757, values, &tracker, &set61);\n  ExpectOperationCounts(20124, 96583, values, &tracker, &set100);\n\n  // Test key insertion/deletion in reverse sorted order.\n  std::reverse(values.begin(), values.end());\n  ExpectOperationCounts(54949, 127531, values, &tracker, &set4);\n  ExpectOperationCounts(338813, 118266, values, &tracker, &set61);\n  ExpectOperationCounts(534529, 125279, values, &tracker, &set100);\n}\n\nstruct MovableOnlyInstanceThreeWayCompare {\n  absl::weak_ordering operator()(const MovableOnlyInstance &a,\n                                 const MovableOnlyInstance &b) const {\n    return a.compare(b);\n  }\n};\n\n// Note: when the values in this test change, it is expected to have an impact\n// on performance.\nTEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {\n  if (kAsan) GTEST_SKIP() << \"We do extra operations in ASan mode.\";\n\n  InstanceTracker tracker;\n  // Note: this is minimum number of values per node.\n  SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4,\n                MovableOnlyInstanceThreeWayCompare>\n      set4;\n  // Note: this is the default number of values per node for a set of int32s\n  // (with 64-bit pointers).\n  SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61,\n                MovableOnlyInstanceThreeWayCompare>\n      set61;\n  SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100,\n                MovableOnlyInstanceThreeWayCompare>\n      set100;\n\n  // Don't depend on flags for random values because then the expectations will\n  // fail if the flags change.\n  std::vector<int> values =\n      GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);\n\n  EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);\n  EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);\n  EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);\n  if (sizeof(void *) == 8) {\n    EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),\n              // When we have generations, there is one fewer slot.\n              BtreeGenerationsEnabled() ? 60 : 61);\n  }\n\n  // Test key insertion/deletion in random order.\n  ExpectOperationCounts(56540, 124221, values, &tracker, &set4);\n  ExpectOperationCounts(386718, 119816, values, &tracker, &set61);\n  ExpectOperationCounts(586761, 120319, values, &tracker, &set100);\n\n  // Test key insertion/deletion in sorted order.\n  std::sort(values.begin(), values.end());\n  ExpectOperationCounts(24972, 85563, values, &tracker, &set4);\n  ExpectOperationCounts(20208, 87757, values, &tracker, &set61);\n  ExpectOperationCounts(20124, 96583, values, &tracker, &set100);\n\n  // Test key insertion/deletion in reverse sorted order.\n  std::reverse(values.begin(), values.end());\n  ExpectOperationCounts(54949, 117532, values, &tracker, &set4);\n  ExpectOperationCounts(338813, 108267, values, &tracker, &set61);\n  ExpectOperationCounts(534529, 115280, values, &tracker, &set100);\n}\n\nstruct NoDefaultCtor {\n  int num;\n  explicit NoDefaultCtor(int i) : num(i) {}\n\n  friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) {\n    return a.num < b.num;\n  }\n};\n\nTEST(Btree, BtreeMapCanHoldNoDefaultCtorTypes) {\n  absl::btree_map<NoDefaultCtor, NoDefaultCtor> m;\n\n  for (int i = 1; i <= 99; ++i) {\n    SCOPED_TRACE(i);\n    EXPECT_TRUE(m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i)).second);\n  }\n  EXPECT_FALSE(m.emplace(NoDefaultCtor(78), NoDefaultCtor(0)).second);\n\n  auto iter99 = m.find(NoDefaultCtor(99));\n  ASSERT_NE(iter99, m.end());\n  EXPECT_EQ(iter99->second.num, 1);\n\n  auto iter1 = m.find(NoDefaultCtor(1));\n  ASSERT_NE(iter1, m.end());\n  EXPECT_EQ(iter1->second.num, 99);\n\n  auto iter50 = m.find(NoDefaultCtor(50));\n  ASSERT_NE(iter50, m.end());\n  EXPECT_EQ(iter50->second.num, 50);\n\n  auto iter25 = m.find(NoDefaultCtor(25));\n  ASSERT_NE(iter25, m.end());\n  EXPECT_EQ(iter25->second.num, 75);\n}\n\nTEST(Btree, BtreeMultimapCanHoldNoDefaultCtorTypes) {\n  absl::btree_multimap<NoDefaultCtor, NoDefaultCtor> m;\n\n  for (int i = 1; i <= 99; ++i) {\n    SCOPED_TRACE(i);\n    m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i));\n  }\n\n  auto iter99 = m.find(NoDefaultCtor(99));\n  ASSERT_NE(iter99, m.end());\n  EXPECT_EQ(iter99->second.num, 1);\n\n  auto iter1 = m.find(NoDefaultCtor(1));\n  ASSERT_NE(iter1, m.end());\n  EXPECT_EQ(iter1->second.num, 99);\n\n  auto iter50 = m.find(NoDefaultCtor(50));\n  ASSERT_NE(iter50, m.end());\n  EXPECT_EQ(iter50->second.num, 50);\n\n  auto iter25 = m.find(NoDefaultCtor(25));\n  ASSERT_NE(iter25, m.end());\n  EXPECT_EQ(iter25->second.num, 75);\n}\n\nTEST(Btree, MapAt) {\n  absl::btree_map<int, int> map = {{1, 2}, {2, 4}};\n  EXPECT_EQ(map.at(1), 2);\n  EXPECT_EQ(map.at(2), 4);\n  map.at(2) = 8;\n  const absl::btree_map<int, int> &const_map = map;\n  EXPECT_EQ(const_map.at(1), 2);\n  EXPECT_EQ(const_map.at(2), 8);\n#ifdef ABSL_HAVE_EXCEPTIONS\n  EXPECT_THROW(map.at(3), std::out_of_range);\n#else\n  EXPECT_DEATH_IF_SUPPORTED(map.at(3), \"absl::btree_map::at\");\n#endif\n}\n\nTEST(Btree, BtreeMultisetEmplace) {\n  const int value_to_insert = 123456;\n  absl::btree_multiset<int> s;\n  auto iter = s.emplace(value_to_insert);\n  ASSERT_NE(iter, s.end());\n  EXPECT_EQ(*iter, value_to_insert);\n  iter = s.emplace(value_to_insert);\n  ASSERT_NE(iter, s.end());\n  EXPECT_EQ(*iter, value_to_insert);\n  auto result = s.equal_range(value_to_insert);\n  EXPECT_EQ(std::distance(result.first, result.second), 2);\n}\n\nTEST(Btree, BtreeMultisetEmplaceHint) {\n  const int value_to_insert = 123456;\n  absl::btree_multiset<int> s;\n  auto iter = s.emplace(value_to_insert);\n  ASSERT_NE(iter, s.end());\n  EXPECT_EQ(*iter, value_to_insert);\n  iter = s.emplace_hint(iter, value_to_insert);\n  // The new element should be before the previously inserted one.\n  EXPECT_EQ(iter, s.lower_bound(value_to_insert));\n  ASSERT_NE(iter, s.end());\n  EXPECT_EQ(*iter, value_to_insert);\n}\n\nTEST(Btree, BtreeMultimapEmplace) {\n  const int key_to_insert = 123456;\n  const char value0[] = \"a\";\n  absl::btree_multimap<int, std::string> m;\n  auto iter = m.emplace(key_to_insert, value0);\n  ASSERT_NE(iter, m.end());\n  EXPECT_EQ(iter->first, key_to_insert);\n  EXPECT_EQ(iter->second, value0);\n  const char value1[] = \"b\";\n  iter = m.emplace(key_to_insert, value1);\n  ASSERT_NE(iter, m.end());\n  EXPECT_EQ(iter->first, key_to_insert);\n  EXPECT_EQ(iter->second, value1);\n  auto result = m.equal_range(key_to_insert);\n  EXPECT_EQ(std::distance(result.first, result.second), 2);\n}\n\nTEST(Btree, BtreeMultimapEmplaceHint) {\n  const int key_to_insert = 123456;\n  const char value0[] = \"a\";\n  absl::btree_multimap<int, std::string> m;\n  auto iter = m.emplace(key_to_insert, value0);\n  ASSERT_NE(iter, m.end());\n  EXPECT_EQ(iter->first, key_to_insert);\n  EXPECT_EQ(iter->second, value0);\n  const char value1[] = \"b\";\n  iter = m.emplace_hint(iter, key_to_insert, value1);\n  // The new element should be before the previously inserted one.\n  EXPECT_EQ(iter, m.lower_bound(key_to_insert));\n  ASSERT_NE(iter, m.end());\n  EXPECT_EQ(iter->first, key_to_insert);\n  EXPECT_EQ(iter->second, value1);\n}\n\nTEST(Btree, ConstIteratorAccessors) {\n  absl::btree_set<int> set;\n  for (int i = 0; i < 100; ++i) {\n    set.insert(i);\n  }\n\n  auto it = set.cbegin();\n  auto r_it = set.crbegin();\n  for (int i = 0; i < 100; ++i, ++it, ++r_it) {\n    ASSERT_EQ(*it, i);\n    ASSERT_EQ(*r_it, 99 - i);\n  }\n  EXPECT_EQ(it, set.cend());\n  EXPECT_EQ(r_it, set.crend());\n}\n\nTEST(Btree, StrSplitCompatible) {\n  const absl::btree_set<std::string> split_set = absl::StrSplit(\"a,b,c\", ',');\n  const absl::btree_set<std::string> expected_set = {\"a\", \"b\", \"c\"};\n\n  EXPECT_EQ(split_set, expected_set);\n}\n\nTEST(Btree, KeyComp) {\n  absl::btree_set<int> s;\n  EXPECT_TRUE(s.key_comp()(1, 2));\n  EXPECT_FALSE(s.key_comp()(2, 2));\n  EXPECT_FALSE(s.key_comp()(2, 1));\n\n  absl::btree_map<int, int> m1;\n  EXPECT_TRUE(m1.key_comp()(1, 2));\n  EXPECT_FALSE(m1.key_comp()(2, 2));\n  EXPECT_FALSE(m1.key_comp()(2, 1));\n\n  // Even though we internally adapt the comparator of `m2` to be three-way and\n  // heterogeneous, the comparator we expose through key_comp() is the original\n  // unadapted comparator.\n  absl::btree_map<std::string, int> m2;\n  EXPECT_TRUE(m2.key_comp()(\"a\", \"b\"));\n  EXPECT_FALSE(m2.key_comp()(\"b\", \"b\"));\n  EXPECT_FALSE(m2.key_comp()(\"b\", \"a\"));\n}\n\nTEST(Btree, ValueComp) {\n  absl::btree_set<int> s;\n  EXPECT_TRUE(s.value_comp()(1, 2));\n  EXPECT_FALSE(s.value_comp()(2, 2));\n  EXPECT_FALSE(s.value_comp()(2, 1));\n\n  absl::btree_map<int, int> m1;\n  EXPECT_TRUE(m1.value_comp()(std::make_pair(1, 0), std::make_pair(2, 0)));\n  EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0)));\n  EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0)));\n\n  // Even though we internally adapt the comparator of `m2` to be three-way and\n  // heterogeneous, the comparator we expose through value_comp() is based on\n  // the original unadapted comparator.\n  absl::btree_map<std::string, int> m2;\n  EXPECT_TRUE(m2.value_comp()(std::make_pair(\"a\", 0), std::make_pair(\"b\", 0)));\n  EXPECT_FALSE(m2.value_comp()(std::make_pair(\"b\", 0), std::make_pair(\"b\", 0)));\n  EXPECT_FALSE(m2.value_comp()(std::make_pair(\"b\", 0), std::make_pair(\"a\", 0)));\n}\n\n// Test that we have the protected members from the std::map::value_compare API.\n// See https://en.cppreference.com/w/cpp/container/map/value_compare.\nTEST(Btree, MapValueCompProtected) {\n  struct key_compare {\n    bool operator()(int l, int r) const { return l < r; }\n    int id;\n  };\n  using value_compare = absl::btree_map<int, int, key_compare>::value_compare;\n  struct value_comp_child : public value_compare {\n    explicit value_comp_child(key_compare kc) : value_compare(kc) {}\n    int GetId() const { return comp.id; }\n  };\n  value_comp_child c(key_compare{10});\n  EXPECT_EQ(c.GetId(), 10);\n}\n\nTEST(Btree, DefaultConstruction) {\n  absl::btree_set<int> s;\n  absl::btree_map<int, int> m;\n  absl::btree_multiset<int> ms;\n  absl::btree_multimap<int, int> mm;\n\n  EXPECT_TRUE(s.empty());\n  EXPECT_TRUE(m.empty());\n  EXPECT_TRUE(ms.empty());\n  EXPECT_TRUE(mm.empty());\n}\n\nTEST(Btree, SwissTableHashable) {\n  static constexpr int kValues = 10000;\n  std::vector<int> values(kValues);\n  std::iota(values.begin(), values.end(), 0);\n  std::vector<std::pair<int, int>> map_values;\n  for (int v : values) map_values.emplace_back(v, -v);\n\n  using set = absl::btree_set<int>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      set{},\n      set{1},\n      set{2},\n      set{1, 2},\n      set{2, 1},\n      set(values.begin(), values.end()),\n      set(values.rbegin(), values.rend()),\n  }));\n\n  using mset = absl::btree_multiset<int>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      mset{},\n      mset{1},\n      mset{1, 1},\n      mset{2},\n      mset{2, 2},\n      mset{1, 2},\n      mset{1, 1, 2},\n      mset{1, 2, 2},\n      mset{1, 1, 2, 2},\n      mset(values.begin(), values.end()),\n      mset(values.rbegin(), values.rend()),\n  }));\n\n  using map = absl::btree_map<int, int>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      map{},\n      map{{1, 0}},\n      map{{1, 1}},\n      map{{2, 0}},\n      map{{2, 2}},\n      map{{1, 0}, {2, 1}},\n      map(map_values.begin(), map_values.end()),\n      map(map_values.rbegin(), map_values.rend()),\n  }));\n\n  using mmap = absl::btree_multimap<int, int>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      mmap{},\n      mmap{{1, 0}},\n      mmap{{1, 1}},\n      mmap{{1, 0}, {1, 1}},\n      mmap{{1, 1}, {1, 0}},\n      mmap{{2, 0}},\n      mmap{{2, 2}},\n      mmap{{1, 0}, {2, 1}},\n      mmap(map_values.begin(), map_values.end()),\n      mmap(map_values.rbegin(), map_values.rend()),\n  }));\n}\n\nTEST(Btree, ComparableSet) {\n  absl::btree_set<int> s1 = {1, 2};\n  absl::btree_set<int> s2 = {2, 3};\n  EXPECT_LT(s1, s2);\n  EXPECT_LE(s1, s2);\n  EXPECT_LE(s1, s1);\n  EXPECT_GT(s2, s1);\n  EXPECT_GE(s2, s1);\n  EXPECT_GE(s1, s1);\n}\n\nTEST(Btree, ComparableSetsDifferentLength) {\n  absl::btree_set<int> s1 = {1, 2};\n  absl::btree_set<int> s2 = {1, 2, 3};\n  EXPECT_LT(s1, s2);\n  EXPECT_LE(s1, s2);\n  EXPECT_GT(s2, s1);\n  EXPECT_GE(s2, s1);\n}\n\nTEST(Btree, ComparableMultiset) {\n  absl::btree_multiset<int> s1 = {1, 2};\n  absl::btree_multiset<int> s2 = {2, 3};\n  EXPECT_LT(s1, s2);\n  EXPECT_LE(s1, s2);\n  EXPECT_LE(s1, s1);\n  EXPECT_GT(s2, s1);\n  EXPECT_GE(s2, s1);\n  EXPECT_GE(s1, s1);\n}\n\nTEST(Btree, ComparableMap) {\n  absl::btree_map<int, int> s1 = {{1, 2}};\n  absl::btree_map<int, int> s2 = {{2, 3}};\n  EXPECT_LT(s1, s2);\n  EXPECT_LE(s1, s2);\n  EXPECT_LE(s1, s1);\n  EXPECT_GT(s2, s1);\n  EXPECT_GE(s2, s1);\n  EXPECT_GE(s1, s1);\n}\n\nTEST(Btree, ComparableMultimap) {\n  absl::btree_multimap<int, int> s1 = {{1, 2}};\n  absl::btree_multimap<int, int> s2 = {{2, 3}};\n  EXPECT_LT(s1, s2);\n  EXPECT_LE(s1, s2);\n  EXPECT_LE(s1, s1);\n  EXPECT_GT(s2, s1);\n  EXPECT_GE(s2, s1);\n  EXPECT_GE(s1, s1);\n}\n\nTEST(Btree, ComparableSetWithCustomComparator) {\n  // As specified by\n  // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf section\n  // [container.requirements.general].12, ordering associative containers always\n  // uses default '<' operator\n  // - even if otherwise the container uses custom functor.\n  absl::btree_set<int, std::greater<int>> s1 = {1, 2};\n  absl::btree_set<int, std::greater<int>> s2 = {2, 3};\n  EXPECT_LT(s1, s2);\n  EXPECT_LE(s1, s2);\n  EXPECT_LE(s1, s1);\n  EXPECT_GT(s2, s1);\n  EXPECT_GE(s2, s1);\n  EXPECT_GE(s1, s1);\n}\n\nTEST(Btree, EraseReturnsIterator) {\n  absl::btree_set<int> set = {1, 2, 3, 4, 5};\n  auto result_it = set.erase(set.begin(), set.find(3));\n  EXPECT_EQ(result_it, set.find(3));\n  result_it = set.erase(set.find(5));\n  EXPECT_EQ(result_it, set.end());\n}\n\nTEST(Btree, ExtractAndInsertNodeHandleSet) {\n  absl::btree_set<int> src1 = {1, 2, 3, 4, 5};\n  auto nh = src1.extract(src1.find(3));\n  EXPECT_THAT(src1, ElementsAre(1, 2, 4, 5));\n  absl::btree_set<int> other;\n  absl::btree_set<int>::insert_return_type res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(3));\n  EXPECT_EQ(res.position, other.find(3));\n  EXPECT_TRUE(res.inserted);\n  EXPECT_TRUE(res.node.empty());\n\n  absl::btree_set<int> src2 = {3, 4};\n  nh = src2.extract(src2.find(3));\n  EXPECT_THAT(src2, ElementsAre(4));\n  res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(3));\n  EXPECT_EQ(res.position, other.find(3));\n  EXPECT_FALSE(res.inserted);\n  ASSERT_FALSE(res.node.empty());\n  EXPECT_EQ(res.node.value(), 3);\n}\n\ntemplate <typename Set>\nvoid TestExtractWithTrackingForSet() {\n  InstanceTracker tracker;\n  {\n    Set s;\n    // Add enough elements to make sure we test internal nodes too.\n    const size_t kSize = 1000;\n    while (s.size() < kSize) {\n      s.insert(MovableOnlyInstance(s.size()));\n    }\n    for (int i = 0; i < kSize; ++i) {\n      // Extract with key\n      auto nh = s.extract(MovableOnlyInstance(i));\n      EXPECT_EQ(s.size(), kSize - 1);\n      EXPECT_EQ(nh.value().value(), i);\n      // Insert with node\n      s.insert(std::move(nh));\n      EXPECT_EQ(s.size(), kSize);\n\n      // Extract with iterator\n      auto it = s.find(MovableOnlyInstance(i));\n      nh = s.extract(it);\n      EXPECT_EQ(s.size(), kSize - 1);\n      EXPECT_EQ(nh.value().value(), i);\n      // Insert with node and hint\n      s.insert(s.begin(), std::move(nh));\n      EXPECT_EQ(s.size(), kSize);\n    }\n  }\n  EXPECT_EQ(0, tracker.instances());\n}\n\ntemplate <typename Map>\nvoid TestExtractWithTrackingForMap() {\n  InstanceTracker tracker;\n  {\n    Map m;\n    // Add enough elements to make sure we test internal nodes too.\n    const size_t kSize = 1000;\n    while (m.size() < kSize) {\n      m.insert(\n          {CopyableMovableInstance(m.size()), MovableOnlyInstance(m.size())});\n    }\n    for (int i = 0; i < kSize; ++i) {\n      // Extract with key\n      auto nh = m.extract(CopyableMovableInstance(i));\n      EXPECT_EQ(m.size(), kSize - 1);\n      EXPECT_EQ(nh.key().value(), i);\n      EXPECT_EQ(nh.mapped().value(), i);\n      // Insert with node\n      m.insert(std::move(nh));\n      EXPECT_EQ(m.size(), kSize);\n\n      // Extract with iterator\n      auto it = m.find(CopyableMovableInstance(i));\n      nh = m.extract(it);\n      EXPECT_EQ(m.size(), kSize - 1);\n      EXPECT_EQ(nh.key().value(), i);\n      EXPECT_EQ(nh.mapped().value(), i);\n      // Insert with node and hint\n      m.insert(m.begin(), std::move(nh));\n      EXPECT_EQ(m.size(), kSize);\n    }\n  }\n  EXPECT_EQ(0, tracker.instances());\n}\n\nTEST(Btree, ExtractTracking) {\n  TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>();\n  TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>();\n  TestExtractWithTrackingForMap<\n      absl::btree_map<CopyableMovableInstance, MovableOnlyInstance>>();\n  TestExtractWithTrackingForMap<\n      absl::btree_multimap<CopyableMovableInstance, MovableOnlyInstance>>();\n}\n\nTEST(Btree, ExtractAndInsertNodeHandleMultiSet) {\n  absl::btree_multiset<int> src1 = {1, 2, 3, 3, 4, 5};\n  auto nh = src1.extract(src1.find(3));\n  EXPECT_THAT(src1, ElementsAre(1, 2, 3, 4, 5));\n  absl::btree_multiset<int> other;\n  auto res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(3));\n  EXPECT_EQ(res, other.find(3));\n\n  absl::btree_multiset<int> src2 = {3, 4};\n  nh = src2.extract(src2.find(3));\n  EXPECT_THAT(src2, ElementsAre(4));\n  res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(3, 3));\n  EXPECT_EQ(res, ++other.find(3));\n}\n\nTEST(Btree, ExtractAndInsertNodeHandleMap) {\n  absl::btree_map<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};\n  auto nh = src1.extract(src1.find(3));\n  EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));\n  absl::btree_map<int, int> other;\n  absl::btree_map<int, int>::insert_return_type res =\n      other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(Pair(3, 4)));\n  EXPECT_EQ(res.position, other.find(3));\n  EXPECT_TRUE(res.inserted);\n  EXPECT_TRUE(res.node.empty());\n\n  absl::btree_map<int, int> src2 = {{3, 6}};\n  nh = src2.extract(src2.find(3));\n  EXPECT_TRUE(src2.empty());\n  res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(Pair(3, 4)));\n  EXPECT_EQ(res.position, other.find(3));\n  EXPECT_FALSE(res.inserted);\n  ASSERT_FALSE(res.node.empty());\n  EXPECT_EQ(res.node.key(), 3);\n  EXPECT_EQ(res.node.mapped(), 6);\n}\n\nTEST(Btree, ExtractAndInsertNodeHandleMultiMap) {\n  absl::btree_multimap<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};\n  auto nh = src1.extract(src1.find(3));\n  EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));\n  absl::btree_multimap<int, int> other;\n  auto res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(Pair(3, 4)));\n  EXPECT_EQ(res, other.find(3));\n\n  absl::btree_multimap<int, int> src2 = {{3, 6}};\n  nh = src2.extract(src2.find(3));\n  EXPECT_TRUE(src2.empty());\n  res = other.insert(std::move(nh));\n  EXPECT_THAT(other, ElementsAre(Pair(3, 4), Pair(3, 6)));\n  EXPECT_EQ(res, ++other.begin());\n}\n\nTEST(Btree, ExtractMultiMapEquivalentKeys) {\n  // Note: using string keys means a three-way comparator.\n  absl::btree_multimap<std::string, int> map;\n  for (int i = 0; i < 100; ++i) {\n    for (int j = 0; j < 100; ++j) {\n      map.insert({absl::StrCat(i), j});\n    }\n  }\n\n  for (int i = 0; i < 100; ++i) {\n    const std::string key = absl::StrCat(i);\n    auto node_handle = map.extract(key);\n    EXPECT_EQ(node_handle.key(), key);\n    EXPECT_EQ(node_handle.mapped(), 0) << i;\n  }\n\n  for (int i = 0; i < 100; ++i) {\n    const std::string key = absl::StrCat(i);\n    auto node_handle = map.extract(key);\n    EXPECT_EQ(node_handle.key(), key);\n    EXPECT_EQ(node_handle.mapped(), 1) << i;\n  }\n}\n\nTEST(Btree, ExtractAndGetNextSet) {\n  absl::btree_set<int> src = {1, 2, 3, 4, 5};\n  auto it = src.find(3);\n  auto extracted_and_next = src.extract_and_get_next(it);\n  EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));\n  EXPECT_EQ(extracted_and_next.node.value(), 3);\n  EXPECT_EQ(*extracted_and_next.next, 4);\n}\n\nTEST(Btree, ExtractAndGetNextMultiSet) {\n  absl::btree_multiset<int> src = {1, 2, 3, 4, 5};\n  auto it = src.find(3);\n  auto extracted_and_next = src.extract_and_get_next(it);\n  EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));\n  EXPECT_EQ(extracted_and_next.node.value(), 3);\n  EXPECT_EQ(*extracted_and_next.next, 4);\n}\n\nTEST(Btree, ExtractAndGetNextMap) {\n  absl::btree_map<int, int> src = {{1, 2}, {3, 4}, {5, 6}};\n  auto it = src.find(3);\n  auto extracted_and_next = src.extract_and_get_next(it);\n  EXPECT_THAT(src, ElementsAre(Pair(1, 2), Pair(5, 6)));\n  EXPECT_EQ(extracted_and_next.node.key(), 3);\n  EXPECT_EQ(extracted_and_next.node.mapped(), 4);\n  EXPECT_THAT(*extracted_and_next.next, Pair(5, 6));\n}\n\nTEST(Btree, ExtractAndGetNextMultiMap) {\n  absl::btree_multimap<int, int> src = {{1, 2}, {3, 4}, {5, 6}};\n  auto it = src.find(3);\n  auto extracted_and_next = src.extract_and_get_next(it);\n  EXPECT_THAT(src, ElementsAre(Pair(1, 2), Pair(5, 6)));\n  EXPECT_EQ(extracted_and_next.node.key(), 3);\n  EXPECT_EQ(extracted_and_next.node.mapped(), 4);\n  EXPECT_THAT(*extracted_and_next.next, Pair(5, 6));\n}\n\nTEST(Btree, ExtractAndGetNextEndIter) {\n  absl::btree_set<int> src = {1, 2, 3, 4, 5};\n  auto it = src.find(5);\n  auto extracted_and_next = src.extract_and_get_next(it);\n  EXPECT_THAT(src, ElementsAre(1, 2, 3, 4));\n  EXPECT_EQ(extracted_and_next.node.value(), 5);\n  EXPECT_EQ(extracted_and_next.next, src.end());\n}\n\nTEST(Btree, ExtractDoesntCauseExtraMoves) {\n#ifdef _MSC_VER\n  // This conditional is to avoid an unreachable code warning.\n  if (_MSC_VER > 0) {\n    GTEST_SKIP() << \"This test fails on MSVC.\";\n  }\n#endif\n\n  using Set = absl::btree_set<MovableOnlyInstance>;\n  std::array<std::function<void(Set &)>, 3> extracters = {\n      [](Set &s) { auto node = s.extract(s.begin()); },\n      [](Set &s) { auto ret = s.extract_and_get_next(s.begin()); },\n      [](Set &s) { auto node = s.extract(MovableOnlyInstance(0)); }};\n\n  InstanceTracker tracker;\n  for (int i = 0; i < 3; ++i) {\n    Set s;\n    s.insert(MovableOnlyInstance(0));\n    tracker.ResetCopiesMovesSwaps();\n\n    extracters[i](s);\n    // We expect to see exactly 1 move: from the original slot into the\n    // extracted node.\n    EXPECT_EQ(tracker.copies(), 0) << i;\n    EXPECT_EQ(tracker.moves(), 1) << i;\n    EXPECT_EQ(tracker.swaps(), 0) << i;\n  }\n}\n\n// For multisets, insert with hint also affects correctness because we need to\n// insert immediately before the hint if possible.\nstruct InsertMultiHintData {\n  int key;\n  int not_key;\n  bool operator==(const InsertMultiHintData other) const {\n    return key == other.key && not_key == other.not_key;\n  }\n};\n\nstruct InsertMultiHintDataKeyCompare {\n  using is_transparent = void;\n  bool operator()(const InsertMultiHintData a,\n                  const InsertMultiHintData b) const {\n    return a.key < b.key;\n  }\n  bool operator()(const int a, const InsertMultiHintData b) const {\n    return a < b.key;\n  }\n  bool operator()(const InsertMultiHintData a, const int b) const {\n    return a.key < b;\n  }\n};\n\nTEST(Btree, InsertHintNodeHandle) {\n  // For unique sets, insert with hint is just a performance optimization.\n  // Test that insert works correctly when the hint is right or wrong.\n  {\n    absl::btree_set<int> src = {1, 2, 3, 4, 5};\n    auto nh = src.extract(src.find(3));\n    EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));\n    absl::btree_set<int> other = {0, 100};\n    // Test a correct hint.\n    auto it = other.insert(other.lower_bound(3), std::move(nh));\n    EXPECT_THAT(other, ElementsAre(0, 3, 100));\n    EXPECT_EQ(it, other.find(3));\n\n    nh = src.extract(src.find(5));\n    // Test an incorrect hint.\n    it = other.insert(other.end(), std::move(nh));\n    EXPECT_THAT(other, ElementsAre(0, 3, 5, 100));\n    EXPECT_EQ(it, other.find(5));\n  }\n\n  absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare> src =\n      {{1, 2}, {3, 4}, {3, 5}};\n  auto nh = src.extract(src.lower_bound(3));\n  EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 4}));\n  absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare>\n      other = {{3, 1}, {3, 2}, {3, 3}};\n  auto it = other.insert(--other.end(), std::move(nh));\n  EXPECT_THAT(\n      other, ElementsAre(InsertMultiHintData{3, 1}, InsertMultiHintData{3, 2},\n                         InsertMultiHintData{3, 4}, InsertMultiHintData{3, 3}));\n  EXPECT_EQ(it, --(--other.end()));\n\n  nh = src.extract(src.find(3));\n  EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 5}));\n  it = other.insert(other.begin(), std::move(nh));\n  EXPECT_THAT(other,\n              ElementsAre(InsertMultiHintData{3, 5}, InsertMultiHintData{3, 1},\n                          InsertMultiHintData{3, 2}, InsertMultiHintData{3, 4},\n                          InsertMultiHintData{3, 3}));\n  EXPECT_EQ(it, other.begin());\n}\n\nstruct IntCompareToCmp {\n  absl::weak_ordering operator()(int a, int b) const {\n    if (a < b) return absl::weak_ordering::less;\n    if (a > b) return absl::weak_ordering::greater;\n    return absl::weak_ordering::equivalent;\n  }\n};\n\nTEST(Btree, MergeIntoUniqueContainers) {\n  absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};\n  absl::btree_multiset<int> src2 = {3, 4, 4, 5};\n  absl::btree_set<int> dst;\n\n  dst.merge(src1);\n  EXPECT_TRUE(src1.empty());\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3));\n  dst.merge(src2);\n  EXPECT_THAT(src2, ElementsAre(3, 4));\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(Btree, MergeIntoUniqueContainersWithCompareTo) {\n  absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};\n  absl::btree_multiset<int> src2 = {3, 4, 4, 5};\n  absl::btree_set<int, IntCompareToCmp> dst;\n\n  dst.merge(src1);\n  EXPECT_TRUE(src1.empty());\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3));\n  dst.merge(src2);\n  EXPECT_THAT(src2, ElementsAre(3, 4));\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(Btree, MergeIntoMultiContainers) {\n  absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};\n  absl::btree_multiset<int> src2 = {3, 4, 4, 5};\n  absl::btree_multiset<int> dst;\n\n  dst.merge(src1);\n  EXPECT_TRUE(src1.empty());\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3));\n  dst.merge(src2);\n  EXPECT_TRUE(src2.empty());\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));\n}\n\nTEST(Btree, MergeIntoMultiContainersWithCompareTo) {\n  absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};\n  absl::btree_multiset<int> src2 = {3, 4, 4, 5};\n  absl::btree_multiset<int, IntCompareToCmp> dst;\n\n  dst.merge(src1);\n  EXPECT_TRUE(src1.empty());\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3));\n  dst.merge(src2);\n  EXPECT_TRUE(src2.empty());\n  EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));\n}\n\nTEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {\n  absl::btree_map<int, int, IntCompareToCmp> src1 = {{1, 1}, {2, 2}, {3, 3}};\n  absl::btree_multimap<int, int, std::greater<int>> src2 = {\n      {5, 5}, {4, 1}, {4, 4}, {3, 2}};\n  absl::btree_multimap<int, int> dst;\n\n  dst.merge(src1);\n  EXPECT_TRUE(src1.empty());\n  EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));\n  dst.merge(src2);\n  EXPECT_TRUE(src2.empty());\n  EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(3, 2),\n                               Pair(4, 1), Pair(4, 4), Pair(5, 5)));\n}\n\nTEST(Btree, MergeIntoSetMovableOnly) {\n  absl::btree_set<MovableOnlyInstance> src;\n  src.insert(MovableOnlyInstance(1));\n  absl::btree_multiset<MovableOnlyInstance> dst1;\n  dst1.insert(MovableOnlyInstance(2));\n  absl::btree_set<MovableOnlyInstance> dst2;\n\n  // Test merge into multiset.\n  dst1.merge(src);\n\n  EXPECT_TRUE(src.empty());\n  // ElementsAre/ElementsAreArray don't work with move-only types.\n  ASSERT_THAT(dst1, SizeIs(2));\n  EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));\n  EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));\n\n  // Test merge into set.\n  dst2.merge(dst1);\n\n  EXPECT_TRUE(dst1.empty());\n  ASSERT_THAT(dst2, SizeIs(2));\n  EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));\n  EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));\n}\n\nstruct KeyCompareToWeakOrdering {\n  template <typename T>\n  absl::weak_ordering operator()(const T &a, const T &b) const {\n    return a < b ? absl::weak_ordering::less\n                 : a == b ? absl::weak_ordering::equivalent\n                          : absl::weak_ordering::greater;\n  }\n};\n\nstruct KeyCompareToStrongOrdering {\n  template <typename T>\n  absl::strong_ordering operator()(const T &a, const T &b) const {\n    return a < b ? absl::strong_ordering::less\n                 : a == b ? absl::strong_ordering::equal\n                          : absl::strong_ordering::greater;\n  }\n};\n\nTEST(Btree, UserProvidedKeyCompareToComparators) {\n  absl::btree_set<int, KeyCompareToWeakOrdering> weak_set = {1, 2, 3};\n  EXPECT_TRUE(weak_set.contains(2));\n  EXPECT_FALSE(weak_set.contains(4));\n\n  absl::btree_set<int, KeyCompareToStrongOrdering> strong_set = {1, 2, 3};\n  EXPECT_TRUE(strong_set.contains(2));\n  EXPECT_FALSE(strong_set.contains(4));\n}\n\nTEST(Btree, TryEmplaceBasicTest) {\n  absl::btree_map<int, std::string> m;\n\n  // Should construct a string from the literal.\n  m.try_emplace(1, \"one\");\n  EXPECT_EQ(1, m.size());\n\n  // Try other string constructors and const lvalue key.\n  const int key(42);\n  m.try_emplace(key, 3, 'a');\n  m.try_emplace(2, std::string(\"two\"));\n\n  EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));\n  EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, std::string>>{\n                     {1, \"one\"}, {2, \"two\"}, {42, \"aaa\"}}));\n}\n\nTEST(Btree, TryEmplaceWithHintWorks) {\n  // Use a counting comparator here to verify that hint is used.\n  int calls = 0;\n  auto cmp = [&calls](int x, int y) {\n    ++calls;\n    return x < y;\n  };\n  using Cmp = decltype(cmp);\n\n  // Use a map that is opted out of key_compare being adapted so we can expect\n  // strict comparison call limits.\n  absl::btree_map<int, int, CheckedCompareOptedOutCmp<Cmp>> m(cmp);\n  for (int i = 0; i < 128; ++i) {\n    m.emplace(i, i);\n  }\n\n  // Sanity check for the comparator\n  calls = 0;\n  m.emplace(127, 127);\n  EXPECT_GE(calls, 4);\n\n  // Try with begin hint:\n  calls = 0;\n  auto it = m.try_emplace(m.begin(), -1, -1);\n  EXPECT_EQ(129, m.size());\n  EXPECT_EQ(it, m.begin());\n  EXPECT_LE(calls, 2);\n\n  // Try with end hint:\n  calls = 0;\n  std::pair<int, int> pair1024 = {1024, 1024};\n  it = m.try_emplace(m.end(), pair1024.first, pair1024.second);\n  EXPECT_EQ(130, m.size());\n  EXPECT_EQ(it, --m.end());\n  EXPECT_LE(calls, 2);\n\n  // Try value already present, bad hint; ensure no duplicate added:\n  calls = 0;\n  it = m.try_emplace(m.end(), 16, 17);\n  EXPECT_EQ(130, m.size());\n  EXPECT_GE(calls, 4);\n  EXPECT_EQ(it, m.find(16));\n\n  // Try value already present, hint points directly to it:\n  calls = 0;\n  it = m.try_emplace(it, 16, 17);\n  EXPECT_EQ(130, m.size());\n  EXPECT_LE(calls, 2);\n  EXPECT_EQ(it, m.find(16));\n\n  m.erase(2);\n  EXPECT_EQ(129, m.size());\n  auto hint = m.find(3);\n  // Try emplace in the middle of two other elements.\n  calls = 0;\n  m.try_emplace(hint, 2, 2);\n  EXPECT_EQ(130, m.size());\n  EXPECT_LE(calls, 2);\n\n  EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));\n}\n\nTEST(Btree, TryEmplaceWithBadHint) {\n  absl::btree_map<int, int> m = {{1, 1}, {9, 9}};\n\n  // Bad hint (too small), should still emplace:\n  auto it = m.try_emplace(m.begin(), 2, 2);\n  EXPECT_EQ(it, ++m.begin());\n  EXPECT_THAT(m, ElementsAreArray(\n                     std::vector<std::pair<int, int>>{{1, 1}, {2, 2}, {9, 9}}));\n\n  // Bad hint, too large this time:\n  it = m.try_emplace(++(++m.begin()), 0, 0);\n  EXPECT_EQ(it, m.begin());\n  EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, int>>{\n                     {0, 0}, {1, 1}, {2, 2}, {9, 9}}));\n}\n\nTEST(Btree, TryEmplaceMaintainsSortedOrder) {\n  absl::btree_map<int, std::string> m;\n  std::pair<int, std::string> pair5 = {5, \"five\"};\n\n  // Test both lvalue & rvalue emplace.\n  m.try_emplace(10, \"ten\");\n  m.try_emplace(pair5.first, pair5.second);\n  EXPECT_EQ(2, m.size());\n  EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));\n\n  int int100{100};\n  m.try_emplace(int100, \"hundred\");\n  m.try_emplace(1, \"one\");\n  EXPECT_EQ(4, m.size());\n  EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));\n}\n\nTEST(Btree, TryEmplaceWithHintAndNoValueArgsWorks) {\n  absl::btree_map<int, int> m;\n  m.try_emplace(m.end(), 1);\n  EXPECT_EQ(0, m[1]);\n}\n\nTEST(Btree, TryEmplaceWithHintAndMultipleValueArgsWorks) {\n  absl::btree_map<int, std::string> m;\n  m.try_emplace(m.end(), 1, 10, 'a');\n  EXPECT_EQ(std::string(10, 'a'), m[1]);\n}\n\ntemplate <typename Alloc>\nusing BtreeSetAlloc = absl::btree_set<int, std::less<int>, Alloc>;\n\nTEST(Btree, AllocatorPropagation) {\n  TestAllocPropagation<BtreeSetAlloc>();\n}\n\nTEST(Btree, MinimumAlignmentAllocator) {\n  absl::btree_set<int8_t, std::less<int8_t>, MinimumAlignmentAlloc<int8_t>> set;\n\n  // Do some basic operations. Test that everything is fine when allocator uses\n  // minimal alignment.\n  for (int8_t i = 0; i < 100; ++i) set.insert(i);\n  set.erase(set.find(50), set.end());\n  for (int8_t i = 51; i < 101; ++i) set.insert(i);\n\n  EXPECT_EQ(set.size(), 100);\n}\n\nTEST(Btree, EmptyTree) {\n  absl::btree_set<int> s;\n  EXPECT_TRUE(s.empty());\n  EXPECT_EQ(s.size(), 0);\n  EXPECT_GT(s.max_size(), 0);\n}\n\nbool IsEven(int k) { return k % 2 == 0; }\n\nTEST(Btree, EraseIf) {\n  // Test that erase_if works with all the container types and supports lambdas.\n  {\n    absl::btree_set<int> s = {1, 3, 5, 6, 100};\n    EXPECT_EQ(erase_if(s, [](int k) { return k > 3; }), 3);\n    EXPECT_THAT(s, ElementsAre(1, 3));\n  }\n  {\n    absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100};\n    EXPECT_EQ(erase_if(s, [](int k) { return k <= 3; }), 3);\n    EXPECT_THAT(s, ElementsAre(5, 6, 6, 100));\n  }\n  {\n    absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}};\n    EXPECT_EQ(\n        erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; }),\n        2);\n    EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3)));\n  }\n  {\n    absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6},\n                                        {6, 6}, {6, 7}, {100, 6}};\n    EXPECT_EQ(\n        erase_if(m,\n                 [](std::pair<const int, int> kv) { return kv.second == 6; }),\n        3);\n    EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7)));\n  }\n  // Test that erasing all elements from a large set works and test support for\n  // function pointers.\n  {\n    absl::btree_set<int> s;\n    for (int i = 0; i < 1000; ++i) s.insert(2 * i);\n    EXPECT_EQ(erase_if(s, IsEven), 1000);\n    EXPECT_THAT(s, IsEmpty());\n  }\n  // Test that erase_if supports other format of function pointers.\n  {\n    absl::btree_set<int> s = {1, 3, 5, 6, 100};\n    EXPECT_EQ(erase_if(s, &IsEven), 2);\n    EXPECT_THAT(s, ElementsAre(1, 3, 5));\n  }\n  // Test that erase_if invokes the predicate once per element.\n  {\n    absl::btree_set<int> s;\n    for (int i = 0; i < 1000; ++i) s.insert(i);\n    int pred_calls = 0;\n    EXPECT_EQ(erase_if(s,\n                       [&pred_calls](int k) {\n                         ++pred_calls;\n                         return k % 2;\n                       }),\n              500);\n    EXPECT_THAT(s, SizeIs(500));\n    EXPECT_EQ(pred_calls, 1000);\n  }\n}\n\nTEST(Btree, InsertOrAssign) {\n  absl::btree_map<int, int> m = {{1, 1}, {3, 3}};\n  using value_type = typename decltype(m)::value_type;\n\n  auto ret = m.insert_or_assign(4, 4);\n  EXPECT_EQ(*ret.first, value_type(4, 4));\n  EXPECT_TRUE(ret.second);\n  ret = m.insert_or_assign(3, 100);\n  EXPECT_EQ(*ret.first, value_type(3, 100));\n  EXPECT_FALSE(ret.second);\n\n  auto hint_ret = m.insert_or_assign(ret.first, 3, 200);\n  EXPECT_EQ(*hint_ret, value_type(3, 200));\n  hint_ret = m.insert_or_assign(m.find(1), 0, 1);\n  EXPECT_EQ(*hint_ret, value_type(0, 1));\n  // Test with bad hint.\n  hint_ret = m.insert_or_assign(m.end(), -1, 1);\n  EXPECT_EQ(*hint_ret, value_type(-1, 1));\n\n  EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200),\n                             Pair(4, 4)));\n}\n\nTEST(Btree, InsertOrAssignMovableOnly) {\n  absl::btree_map<int, MovableOnlyInstance> m;\n  using value_type = typename decltype(m)::value_type;\n\n  auto ret = m.insert_or_assign(4, MovableOnlyInstance(4));\n  EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4)));\n  EXPECT_TRUE(ret.second);\n  ret = m.insert_or_assign(4, MovableOnlyInstance(100));\n  EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100)));\n  EXPECT_FALSE(ret.second);\n\n  auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200));\n  EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200)));\n\n  EXPECT_EQ(m.size(), 2);\n}\n\nTEST(Btree, BitfieldArgument) {\n  union {\n    int n : 1;\n  };\n  n = 0;\n  absl::btree_map<int, int> m;\n  m.erase(n);\n  m.count(n);\n  m.find(n);\n  m.contains(n);\n  m.equal_range(n);\n  m.insert_or_assign(n, n);\n  m.insert_or_assign(m.end(), n, n);\n  m.try_emplace(n);\n  m.try_emplace(m.end(), n);\n  m.at(n);\n  m[n];\n}\n\nTEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {\n  const absl::string_view names[] = {\"n1\", \"n2\"};\n\n  absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)};\n  EXPECT_THAT(name_set1, ElementsAreArray(names));\n\n  absl::btree_set<std::string> name_set2;\n  name_set2.insert(std::begin(names), std::end(names));\n  EXPECT_THAT(name_set2, ElementsAreArray(names));\n}\n\n// A type that is explicitly convertible from int and counts constructor calls.\nstruct ConstructorCounted {\n  explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; }\n  bool operator==(int other) const { return i == other; }\n\n  int i;\n  static int constructor_calls;\n};\nint ConstructorCounted::constructor_calls = 0;\n\nstruct ConstructorCountedCompare {\n  bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; }\n  bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; }\n  bool operator()(const ConstructorCounted &a,\n                  const ConstructorCounted &b) const {\n    return a.i < b.i;\n  }\n  using is_transparent = void;\n};\n\nTEST(Btree,\n     SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {\n  const int i[] = {0, 1, 1};\n  ConstructorCounted::constructor_calls = 0;\n\n  absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{\n      std::begin(i), std::end(i)};\n  EXPECT_THAT(set, ElementsAre(0, 1));\n  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);\n\n  set.insert(std::begin(i), std::end(i));\n  EXPECT_THAT(set, ElementsAre(0, 1));\n  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);\n}\n\nTEST(Btree,\n     SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {\n  const int i[] = {0, 1};\n\n  absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)};\n  EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull())));\n\n  absl::btree_set<std::vector<void *>> s2;\n  s2.insert(std::begin(i), std::end(i));\n  EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));\n}\n\n// libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that\n// prevents explicit conversions between pair types.\n// We only run this test for the libstdc++ from GCC 7 or newer because we can't\n// reliably check the libstdc++ version prior to that release.\n#if !defined(__GLIBCXX__) || \\\n    (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)\nTEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {\n  const std::pair<absl::string_view, int> names[] = {{\"n1\", 1}, {\"n2\", 2}};\n\n  absl::btree_map<std::string, int> name_map1{std::begin(names),\n                                              std::end(names)};\n  EXPECT_THAT(name_map1, ElementsAre(Pair(\"n1\", 1), Pair(\"n2\", 2)));\n\n  absl::btree_map<std::string, int> name_map2;\n  name_map2.insert(std::begin(names), std::end(names));\n  EXPECT_THAT(name_map2, ElementsAre(Pair(\"n1\", 1), Pair(\"n2\", 2)));\n}\n\nTEST(Btree,\n     MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {\n  const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}};\n  ConstructorCounted::constructor_calls = 0;\n\n  absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{\n      std::begin(i), std::end(i)};\n  EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));\n  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);\n\n  map.insert(std::begin(i), std::end(i));\n  EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));\n  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);\n}\n\nTEST(Btree,\n     MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {\n  const std::pair<int, int> i[] = {{0, 1}, {1, 2}};\n\n  absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)};\n  EXPECT_THAT(m1,\n              ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));\n\n  absl::btree_map<std::vector<void *>, int> m2;\n  m2.insert(std::begin(i), std::end(i));\n  EXPECT_THAT(m2,\n              ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));\n}\n\nTEST(Btree, HeterogeneousTryEmplace) {\n  absl::btree_map<std::string, int> m;\n  std::string s = \"key\";\n  absl::string_view sv = s;\n  m.try_emplace(sv, 1);\n  EXPECT_EQ(m[s], 1);\n\n  m.try_emplace(m.end(), sv, 2);\n  EXPECT_EQ(m[s], 1);\n}\n\nTEST(Btree, HeterogeneousOperatorMapped) {\n  absl::btree_map<std::string, int> m;\n  std::string s = \"key\";\n  absl::string_view sv = s;\n  m[sv] = 1;\n  EXPECT_EQ(m[s], 1);\n\n  m[sv] = 2;\n  EXPECT_EQ(m[s], 2);\n}\n\nTEST(Btree, HeterogeneousInsertOrAssign) {\n  absl::btree_map<std::string, int> m;\n  std::string s = \"key\";\n  absl::string_view sv = s;\n  m.insert_or_assign(sv, 1);\n  EXPECT_EQ(m[s], 1);\n\n  m.insert_or_assign(m.end(), sv, 2);\n  EXPECT_EQ(m[s], 2);\n}\n#endif\n\nTEST(Btree, NodeHandleMutableKeyAccess) {\n  {\n    absl::btree_map<std::string, std::string> map;\n\n    map[\"key1\"] = \"mapped\";\n\n    auto nh = map.extract(map.begin());\n    nh.key().resize(3);\n    map.insert(std::move(nh));\n\n    EXPECT_THAT(map, ElementsAre(Pair(\"key\", \"mapped\")));\n  }\n  // Also for multimap.\n  {\n    absl::btree_multimap<std::string, std::string> map;\n\n    map.emplace(\"key1\", \"mapped\");\n\n    auto nh = map.extract(map.begin());\n    nh.key().resize(3);\n    map.insert(std::move(nh));\n\n    EXPECT_THAT(map, ElementsAre(Pair(\"key\", \"mapped\")));\n  }\n}\n\nstruct MultiKey {\n  int i1;\n  int i2;\n};\n\nbool operator==(const MultiKey a, const MultiKey b) {\n  return a.i1 == b.i1 && a.i2 == b.i2;\n}\n\n// A heterogeneous comparator that has different equivalence classes for\n// different lookup types.\nstruct MultiKeyComp {\n  using is_transparent = void;\n  bool operator()(const MultiKey a, const MultiKey b) const {\n    if (a.i1 != b.i1) return a.i1 < b.i1;\n    return a.i2 < b.i2;\n  }\n  bool operator()(const int a, const MultiKey b) const { return a < b.i1; }\n  bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }\n};\n\n// A heterogeneous, three-way comparator that has different equivalence classes\n// for different lookup types.\nstruct MultiKeyThreeWayComp {\n  using is_transparent = void;\n  absl::weak_ordering operator()(const MultiKey a, const MultiKey b) const {\n    if (a.i1 < b.i1) return absl::weak_ordering::less;\n    if (a.i1 > b.i1) return absl::weak_ordering::greater;\n    if (a.i2 < b.i2) return absl::weak_ordering::less;\n    if (a.i2 > b.i2) return absl::weak_ordering::greater;\n    return absl::weak_ordering::equivalent;\n  }\n  absl::weak_ordering operator()(const int a, const MultiKey b) const {\n    if (a < b.i1) return absl::weak_ordering::less;\n    if (a > b.i1) return absl::weak_ordering::greater;\n    return absl::weak_ordering::equivalent;\n  }\n  absl::weak_ordering operator()(const MultiKey a, const int b) const {\n    if (a.i1 < b) return absl::weak_ordering::less;\n    if (a.i1 > b) return absl::weak_ordering::greater;\n    return absl::weak_ordering::equivalent;\n  }\n};\n\ntemplate <typename Compare>\nclass BtreeMultiKeyTest : public ::testing::Test {};\nusing MultiKeyComps = ::testing::Types<MultiKeyComp, MultiKeyThreeWayComp>;\nTYPED_TEST_SUITE(BtreeMultiKeyTest, MultiKeyComps);\n\nTYPED_TEST(BtreeMultiKeyTest, EqualRange) {\n  absl::btree_set<MultiKey, TypeParam> set;\n  for (int i = 0; i < 100; ++i) {\n    for (int j = 0; j < 100; ++j) {\n      set.insert({i, j});\n    }\n  }\n\n  for (int i = 0; i < 100; ++i) {\n    auto equal_range = set.equal_range(i);\n    EXPECT_EQ(equal_range.first->i1, i);\n    EXPECT_EQ(equal_range.first->i2, 0) << i;\n    EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;\n  }\n}\n\nTYPED_TEST(BtreeMultiKeyTest, Extract) {\n  absl::btree_set<MultiKey, TypeParam> set;\n  for (int i = 0; i < 100; ++i) {\n    for (int j = 0; j < 100; ++j) {\n      set.insert({i, j});\n    }\n  }\n\n  for (int i = 0; i < 100; ++i) {\n    auto node_handle = set.extract(i);\n    EXPECT_EQ(node_handle.value().i1, i);\n    EXPECT_EQ(node_handle.value().i2, 0) << i;\n  }\n\n  for (int i = 0; i < 100; ++i) {\n    auto node_handle = set.extract(i);\n    EXPECT_EQ(node_handle.value().i1, i);\n    EXPECT_EQ(node_handle.value().i2, 1) << i;\n  }\n}\n\nTYPED_TEST(BtreeMultiKeyTest, Erase) {\n  absl::btree_set<MultiKey, TypeParam> set = {\n      {1, 1}, {2, 1}, {2, 2}, {3, 1}};\n  EXPECT_EQ(set.erase(2), 2);\n  EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));\n}\n\nTYPED_TEST(BtreeMultiKeyTest, Count) {\n  const absl::btree_set<MultiKey, TypeParam> set = {\n      {1, 1}, {2, 1}, {2, 2}, {3, 1}};\n  EXPECT_EQ(set.count(2), 2);\n}\n\nTEST(Btree, SetIteratorsAreConst) {\n  using Set = absl::btree_set<int>;\n  EXPECT_TRUE(\n      (std::is_same<typename Set::iterator::reference, const int &>::value));\n  EXPECT_TRUE(\n      (std::is_same<typename Set::iterator::pointer, const int *>::value));\n\n  using MSet = absl::btree_multiset<int>;\n  EXPECT_TRUE(\n      (std::is_same<typename MSet::iterator::reference, const int &>::value));\n  EXPECT_TRUE(\n      (std::is_same<typename MSet::iterator::pointer, const int *>::value));\n}\n\nTEST(Btree, AllocConstructor) {\n  using Alloc = CountingAllocator<int>;\n  using Set = absl::btree_set<int, std::less<int>, Alloc>;\n  int64_t bytes_used = 0;\n  Alloc alloc(&bytes_used);\n  Set set(alloc);\n\n  set.insert({1, 2, 3});\n\n  EXPECT_THAT(set, ElementsAre(1, 2, 3));\n  EXPECT_GT(bytes_used, set.size() * sizeof(int));\n}\n\nTEST(Btree, AllocInitializerListConstructor) {\n  using Alloc = CountingAllocator<int>;\n  using Set = absl::btree_set<int, std::less<int>, Alloc>;\n  int64_t bytes_used = 0;\n  Alloc alloc(&bytes_used);\n  Set set({1, 2, 3}, alloc);\n\n  EXPECT_THAT(set, ElementsAre(1, 2, 3));\n  EXPECT_GT(bytes_used, set.size() * sizeof(int));\n}\n\nTEST(Btree, AllocRangeConstructor) {\n  using Alloc = CountingAllocator<int>;\n  using Set = absl::btree_set<int, std::less<int>, Alloc>;\n  int64_t bytes_used = 0;\n  Alloc alloc(&bytes_used);\n  std::vector<int> v = {1, 2, 3};\n  Set set(v.begin(), v.end(), alloc);\n\n  EXPECT_THAT(set, ElementsAre(1, 2, 3));\n  EXPECT_GT(bytes_used, set.size() * sizeof(int));\n}\n\nTEST(Btree, AllocCopyConstructor) {\n  using Alloc = CountingAllocator<int>;\n  using Set = absl::btree_set<int, std::less<int>, Alloc>;\n  int64_t bytes_used1 = 0;\n  Alloc alloc1(&bytes_used1);\n  Set set1(alloc1);\n\n  set1.insert({1, 2, 3});\n\n  int64_t bytes_used2 = 0;\n  Alloc alloc2(&bytes_used2);\n  Set set2(set1, alloc2);\n\n  EXPECT_THAT(set1, ElementsAre(1, 2, 3));\n  EXPECT_THAT(set2, ElementsAre(1, 2, 3));\n  EXPECT_GT(bytes_used1, set1.size() * sizeof(int));\n  EXPECT_EQ(bytes_used1, bytes_used2);\n}\n\nTEST(Btree, AllocMoveConstructor_SameAlloc) {\n  using Alloc = CountingAllocator<int>;\n  using Set = absl::btree_set<int, std::less<int>, Alloc>;\n  int64_t bytes_used = 0;\n  Alloc alloc(&bytes_used);\n  Set set1(alloc);\n\n  set1.insert({1, 2, 3});\n\n  const int64_t original_bytes_used = bytes_used;\n  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));\n\n  Set set2(std::move(set1), alloc);\n\n  EXPECT_THAT(set2, ElementsAre(1, 2, 3));\n  EXPECT_EQ(bytes_used, original_bytes_used);\n}\n\nTEST(Btree, AllocMoveConstructor_DifferentAlloc) {\n  using Alloc = CountingAllocator<int>;\n  using Set = absl::btree_set<int, std::less<int>, Alloc>;\n  int64_t bytes_used1 = 0;\n  Alloc alloc1(&bytes_used1);\n  Set set1(alloc1);\n\n  set1.insert({1, 2, 3});\n\n  const int64_t original_bytes_used = bytes_used1;\n  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));\n\n  int64_t bytes_used2 = 0;\n  Alloc alloc2(&bytes_used2);\n  Set set2(std::move(set1), alloc2);\n\n  EXPECT_THAT(set2, ElementsAre(1, 2, 3));\n  // We didn't free these bytes allocated by `set1` yet.\n  EXPECT_EQ(bytes_used1, original_bytes_used);\n  EXPECT_EQ(bytes_used2, original_bytes_used);\n}\n\nbool IntCmp(const int a, const int b) { return a < b; }\n\nTEST(Btree, SupportsFunctionPtrComparator) {\n  absl::btree_set<int, decltype(IntCmp) *> set(IntCmp);\n  set.insert({1, 2, 3});\n  EXPECT_THAT(set, ElementsAre(1, 2, 3));\n  EXPECT_TRUE(set.key_comp()(1, 2));\n  EXPECT_TRUE(set.value_comp()(1, 2));\n\n  absl::btree_map<int, int, decltype(IntCmp) *> map(&IntCmp);\n  map[1] = 1;\n  EXPECT_THAT(map, ElementsAre(Pair(1, 1)));\n  EXPECT_TRUE(map.key_comp()(1, 2));\n  EXPECT_TRUE(map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2)));\n}\n\ntemplate <typename Compare>\nstruct TransparentPassThroughComp {\n  using is_transparent = void;\n\n  // This will fail compilation if we attempt a comparison that Compare does not\n  // support, and the failure will happen inside the function implementation so\n  // it can't be avoided by using SFINAE on this comparator.\n  template <typename T, typename U>\n  bool operator()(const T &lhs, const U &rhs) const {\n    return Compare()(lhs, rhs);\n  }\n};\n\nTEST(Btree,\n     SupportsTransparentComparatorThatDoesNotImplementAllVisibleOperators) {\n  absl::btree_set<MultiKey, TransparentPassThroughComp<MultiKeyComp>> set;\n  set.insert(MultiKey{1, 2});\n  EXPECT_TRUE(set.contains(1));\n}\n\nTEST(Btree, ConstructImplicitlyWithUnadaptedComparator) {\n  absl::btree_set<MultiKey, MultiKeyComp> set = {{}, MultiKeyComp{}};\n  EXPECT_TRUE(set.empty());\n}\n\nTEST(Btree, InvalidComparatorsCaught) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  {\n    struct ZeroAlwaysLessCmp {\n      bool operator()(int lhs, int rhs) const {\n        if (lhs == 0) return true;\n        return lhs < rhs;\n      }\n    };\n    absl::btree_set<int, ZeroAlwaysLessCmp> set;\n    EXPECT_DEATH(set.insert({0, 1, 2}), \"is_self_equivalent\");\n  }\n  {\n    struct ThreeWayAlwaysLessCmp {\n      absl::weak_ordering operator()(int, int) const {\n        return absl::weak_ordering::less;\n      }\n    };\n    absl::btree_set<int, ThreeWayAlwaysLessCmp> set;\n    EXPECT_DEATH(set.insert({0, 1, 2}), \"is_self_equivalent\");\n  }\n  {\n    struct SumGreaterZeroCmp {\n      bool operator()(int lhs, int rhs) const {\n        // First, do equivalence correctly - so we can test later condition.\n        if (lhs == rhs) return false;\n        return lhs + rhs > 0;\n      }\n    };\n    absl::btree_set<int, SumGreaterZeroCmp> set;\n    // Note: '!' only needs to be escaped when it's the first character.\n    EXPECT_DEATH(set.insert({0, 1, 2}),\n                 R\"regex(\\!lhs_comp_rhs \\|\\| !comp\\(\\)\\(rhs, lhs\\))regex\");\n  }\n  {\n    struct ThreeWaySumGreaterZeroCmp {\n      absl::weak_ordering operator()(int lhs, int rhs) const {\n        // First, do equivalence correctly - so we can test later condition.\n        if (lhs == rhs) return absl::weak_ordering::equivalent;\n\n        if (lhs + rhs > 0) return absl::weak_ordering::less;\n        if (lhs + rhs == 0) return absl::weak_ordering::equivalent;\n        return absl::weak_ordering::greater;\n      }\n    };\n    absl::btree_set<int, ThreeWaySumGreaterZeroCmp> set;\n    EXPECT_DEATH(set.insert({0, 1, 2}), \"lhs_comp_rhs < 0 -> rhs_comp_lhs > 0\");\n  }\n  // Verify that we detect cases of comparators that violate transitivity.\n  // When the comparators below check for the presence of an optional field,\n  // they violate transitivity because instances that have the optional field\n  // compare differently with each other from how they compare with instances\n  // that don't have the optional field.\n  struct ClockTime {\n    std::optional<int> hour;\n    int minute;\n  };\n  // `comp(a,b) && comp(b,c) && !comp(a,c)` violates transitivity.\n  ClockTime a = {std::nullopt, 1};\n  ClockTime b = {2, 5};\n  ClockTime c = {6, 0};\n  {\n    struct NonTransitiveTimeCmp {\n      bool operator()(ClockTime lhs, ClockTime rhs) const {\n        if (lhs.hour.has_value() && rhs.hour.has_value() &&\n            *lhs.hour != *rhs.hour) {\n          return *lhs.hour < *rhs.hour;\n        }\n        return lhs.minute < rhs.minute;\n      }\n    };\n    NonTransitiveTimeCmp cmp;\n    ASSERT_TRUE(cmp(a, b) && cmp(b, c) && !cmp(a, c));\n    absl::btree_set<ClockTime, NonTransitiveTimeCmp> set;\n    EXPECT_DEATH(set.insert({a, b, c}), \"is_ordered_correctly\");\n    absl::btree_multiset<ClockTime, NonTransitiveTimeCmp> mset;\n    EXPECT_DEATH(mset.insert({a, a, b, b, c, c}), \"is_ordered_correctly\");\n  }\n  {\n    struct ThreeWayNonTransitiveTimeCmp {\n      absl::weak_ordering operator()(ClockTime lhs, ClockTime rhs) const {\n        if (lhs.hour.has_value() && rhs.hour.has_value() &&\n            *lhs.hour != *rhs.hour) {\n          return *lhs.hour < *rhs.hour ? absl::weak_ordering::less\n                                       : absl::weak_ordering::greater;\n        }\n        return lhs.minute < rhs.minute    ? absl::weak_ordering::less\n               : lhs.minute == rhs.minute ? absl::weak_ordering::equivalent\n                                          : absl::weak_ordering::greater;\n      }\n    };\n    ThreeWayNonTransitiveTimeCmp cmp;\n    ASSERT_TRUE(cmp(a, b) < 0 && cmp(b, c) < 0 && cmp(a, c) > 0);\n    absl::btree_set<ClockTime, ThreeWayNonTransitiveTimeCmp> set;\n    EXPECT_DEATH(set.insert({a, b, c}), \"is_ordered_correctly\");\n    absl::btree_multiset<ClockTime, ThreeWayNonTransitiveTimeCmp> mset;\n    EXPECT_DEATH(mset.insert({a, a, b, b, c, c}), \"is_ordered_correctly\");\n  }\n}\n\nTEST(Btree, MutatedKeysCaught) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  struct IntPtrCmp {\n    bool operator()(int *lhs, int *rhs) const { return *lhs < *rhs; }\n  };\n  {\n    absl::btree_set<int *, IntPtrCmp> set;\n    int arr[] = {0, 1, 2};\n    set.insert({&arr[0], &arr[1], &arr[2]});\n    arr[0] = 100;\n    EXPECT_DEATH(set.insert(&arr[0]), \"is_ordered_correctly\");\n  }\n  {\n    absl::btree_multiset<int *, IntPtrCmp> set;\n    int arr[] = {0, 1, 2};\n    set.insert({&arr[0], &arr[0], &arr[1], &arr[1], &arr[2], &arr[2]});\n    arr[0] = 100;\n    EXPECT_DEATH(set.insert(&arr[0]), \"is_ordered_correctly\");\n  }\n}\n\n#ifndef _MSC_VER\n// This test crashes on MSVC.\nTEST(Btree, InvalidIteratorUse) {\n  if (!BtreeGenerationsEnabled())\n    GTEST_SKIP() << \"Generation validation for iterators is disabled.\";\n\n  // Invalid memory use can trigger use-after-free in ASan, HWASAN or\n  // invalidated iterator assertions.\n  constexpr const char *kInvalidMemoryDeathMessage =\n      \"use-after-free|invalidated iterator\";\n\n  {\n    absl::btree_set<int> set;\n    for (int i = 0; i < 10; ++i) set.insert(i);\n    auto it = set.begin();\n    set.erase(it++);\n    EXPECT_DEATH(set.erase(it++), kInvalidMemoryDeathMessage);\n  }\n  {\n    absl::btree_set<int> set;\n    for (int i = 0; i < 10; ++i) set.insert(i);\n    auto it = set.insert(20).first;\n    set.insert(30);\n    EXPECT_DEATH(*it, kInvalidMemoryDeathMessage);\n  }\n  {\n    absl::btree_set<int> set;\n    for (int i = 0; i < 10000; ++i) set.insert(i);\n    auto it = set.find(5000);\n    ASSERT_NE(it, set.end());\n    set.erase(1);\n    EXPECT_DEATH(*it, kInvalidMemoryDeathMessage);\n  }\n  {\n    absl::btree_set<int> set;\n    for (int i = 0; i < 10; ++i) set.insert(i);\n    auto it = set.insert(20).first;\n    set.insert(30);\n    EXPECT_DEATH(void(it == set.begin()), kInvalidMemoryDeathMessage);\n    EXPECT_DEATH(void(set.begin() == it), kInvalidMemoryDeathMessage);\n  }\n}\n#endif\n\nclass OnlyConstructibleByAllocator {\n  explicit OnlyConstructibleByAllocator(int i) : i_(i) {}\n\n public:\n  OnlyConstructibleByAllocator(const OnlyConstructibleByAllocator &other)\n      : i_(other.i_) {}\n  OnlyConstructibleByAllocator &operator=(\n      const OnlyConstructibleByAllocator &other) {\n    i_ = other.i_;\n    return *this;\n  }\n  int Get() const { return i_; }\n  bool operator==(int i) const { return i_ == i; }\n\n private:\n  template <typename T>\n  friend class OnlyConstructibleAllocator;\n\n  int i_;\n};\n\ntemplate <typename T = OnlyConstructibleByAllocator>\nclass OnlyConstructibleAllocator : public std::allocator<T> {\n public:\n  OnlyConstructibleAllocator() = default;\n  template <class U>\n  explicit OnlyConstructibleAllocator(const OnlyConstructibleAllocator<U> &) {}\n\n  void construct(OnlyConstructibleByAllocator *p, int i) {\n    new (p) OnlyConstructibleByAllocator(i);\n  }\n  template <typename Pair>\n  void construct(Pair *p, const int i) {\n    OnlyConstructibleByAllocator only(i);\n    new (p) Pair(std::move(only), i);\n  }\n\n  template <class U>\n  struct rebind {\n    using other = OnlyConstructibleAllocator<U>;\n  };\n};\n\nstruct OnlyConstructibleByAllocatorComp {\n  using is_transparent = void;\n  bool operator()(OnlyConstructibleByAllocator a,\n                  OnlyConstructibleByAllocator b) const {\n    return a.Get() < b.Get();\n  }\n  bool operator()(int a, OnlyConstructibleByAllocator b) const {\n    return a < b.Get();\n  }\n  bool operator()(OnlyConstructibleByAllocator a, int b) const {\n    return a.Get() < b;\n  }\n};\n\nTEST(Btree, OnlyConstructibleByAllocatorType) {\n  const std::array<int, 2> arr = {3, 4};\n  {\n    absl::btree_set<OnlyConstructibleByAllocator,\n                    OnlyConstructibleByAllocatorComp,\n                    OnlyConstructibleAllocator<>>\n        set;\n    set.emplace(1);\n    set.emplace_hint(set.end(), 2);\n    set.insert(arr.begin(), arr.end());\n    EXPECT_THAT(set, ElementsAre(1, 2, 3, 4));\n  }\n  {\n    absl::btree_multiset<OnlyConstructibleByAllocator,\n                         OnlyConstructibleByAllocatorComp,\n                         OnlyConstructibleAllocator<>>\n        set;\n    set.emplace(1);\n    set.emplace_hint(set.end(), 2);\n    // TODO(ezb): fix insert_multi to allow this to compile.\n    // set.insert(arr.begin(), arr.end());\n    EXPECT_THAT(set, ElementsAre(1, 2));\n  }\n  {\n    absl::btree_map<OnlyConstructibleByAllocator, int,\n                    OnlyConstructibleByAllocatorComp,\n                    OnlyConstructibleAllocator<>>\n        map;\n    map.emplace(1);\n    map.emplace_hint(map.end(), 2);\n    map.insert(arr.begin(), arr.end());\n    EXPECT_THAT(map,\n                ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(4, 4)));\n  }\n  {\n    absl::btree_multimap<OnlyConstructibleByAllocator, int,\n                         OnlyConstructibleByAllocatorComp,\n                         OnlyConstructibleAllocator<>>\n        map;\n    map.emplace(1);\n    map.emplace_hint(map.end(), 2);\n    // TODO(ezb): fix insert_multi to allow this to compile.\n    // map.insert(arr.begin(), arr.end());\n    EXPECT_THAT(map, ElementsAre(Pair(1, 1), Pair(2, 2)));\n  }\n}\n\nclass NotAssignable {\n public:\n  explicit NotAssignable(int i) : i_(i) {}\n  NotAssignable(const NotAssignable &other) : i_(other.i_) {}\n  NotAssignable &operator=(NotAssignable &&other) = delete;\n  int Get() const { return i_; }\n  bool operator==(int i) const { return i_ == i; }\n  friend bool operator<(NotAssignable a, NotAssignable b) {\n    return a.i_ < b.i_;\n  }\n\n private:\n  int i_;\n};\n\nTEST(Btree, NotAssignableType) {\n  {\n    absl::btree_set<NotAssignable> set;\n    set.emplace(1);\n    set.emplace_hint(set.end(), 2);\n    set.insert(NotAssignable(3));\n    set.insert(set.end(), NotAssignable(4));\n    EXPECT_THAT(set, ElementsAre(1, 2, 3, 4));\n    set.erase(set.begin());\n    EXPECT_THAT(set, ElementsAre(2, 3, 4));\n  }\n  {\n    absl::btree_multiset<NotAssignable> set;\n    set.emplace(1);\n    set.emplace_hint(set.end(), 2);\n    set.insert(NotAssignable(2));\n    set.insert(set.end(), NotAssignable(3));\n    EXPECT_THAT(set, ElementsAre(1, 2, 2, 3));\n    set.erase(set.begin());\n    EXPECT_THAT(set, ElementsAre(2, 2, 3));\n  }\n  {\n    absl::btree_map<NotAssignable, int> map;\n    map.emplace(NotAssignable(1), 1);\n    map.emplace_hint(map.end(), NotAssignable(2), 2);\n    map.insert({NotAssignable(3), 3});\n    map.insert(map.end(), {NotAssignable(4), 4});\n    EXPECT_THAT(map,\n                ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(4, 4)));\n    map.erase(map.begin());\n    EXPECT_THAT(map, ElementsAre(Pair(2, 2), Pair(3, 3), Pair(4, 4)));\n  }\n  {\n    absl::btree_multimap<NotAssignable, int> map;\n    map.emplace(NotAssignable(1), 1);\n    map.emplace_hint(map.end(), NotAssignable(2), 2);\n    map.insert({NotAssignable(2), 3});\n    map.insert(map.end(), {NotAssignable(3), 3});\n    EXPECT_THAT(map,\n                ElementsAre(Pair(1, 1), Pair(2, 2), Pair(2, 3), Pair(3, 3)));\n    map.erase(map.begin());\n    EXPECT_THAT(map, ElementsAre(Pair(2, 2), Pair(2, 3), Pair(3, 3)));\n  }\n}\n\nstruct ArenaLike {\n  void* recycled = nullptr;\n  size_t recycled_size = 0;\n};\n\n// A very simple implementation of arena allocation.\ntemplate <typename T>\nclass ArenaLikeAllocator : public std::allocator<T> {\n public:\n  // Standard library containers require the ability to allocate objects of\n  // different types which they can do so via rebind.other.\n  template <typename U>\n  struct rebind {\n    using other = ArenaLikeAllocator<U>;\n  };\n\n  explicit ArenaLikeAllocator(ArenaLike* arena) noexcept : arena_(arena) {}\n\n  ~ArenaLikeAllocator() {\n    if (arena_->recycled != nullptr) {\n      delete [] static_cast<T*>(arena_->recycled);\n      arena_->recycled = nullptr;\n    }\n  }\n\n  template<typename U>\n  explicit ArenaLikeAllocator(const ArenaLikeAllocator<U>& other) noexcept\n      : arena_(other.arena_) {}\n\n  T* allocate(size_t num_objects, const void* = nullptr) {\n    size_t size = num_objects * sizeof(T);\n    if (arena_->recycled != nullptr && arena_->recycled_size == size) {\n      T* result = static_cast<T*>(arena_->recycled);\n      arena_->recycled = nullptr;\n      return result;\n    }\n    return new T[num_objects];\n  }\n\n  void deallocate(T* p, size_t num_objects) {\n    size_t size = num_objects * sizeof(T);\n\n    // Simulate writing to the freed memory as an actual arena allocator might\n    // do. This triggers an error report if the memory is poisoned.\n    memset(p, 0xde, size);\n\n    if (arena_->recycled == nullptr) {\n      arena_->recycled = p;\n      arena_->recycled_size = size;\n    } else {\n      delete [] p;\n    }\n  }\n\n  ArenaLike* arena_;\n};\n\n// This test verifies that an arena allocator that reuses memory will not be\n// asked to free poisoned BTree memory.\nTEST(Btree, ReusePoisonMemory) {\n  using Alloc = ArenaLikeAllocator<int64_t>;\n  using Set = absl::btree_set<int64_t, std::less<int64_t>, Alloc>;\n  ArenaLike arena;\n  Alloc alloc(&arena);\n  Set set(alloc);\n\n  set.insert(0);\n  set.erase(0);\n  set.insert(0);\n}\n\nTEST(Btree, IteratorDifference) {\n  absl::BitGen bitgen;\n  std::vector<int> vec;\n  // Randomize the set's insertion order so the nodes aren't all full.\n  for (int i = 0; i < 1000000; ++i) vec.push_back(i);\n  absl::c_shuffle(vec, bitgen);\n\n  absl::btree_set<int> set;\n  for (int i : vec) set.insert(i);\n\n  for (int i = 0; i < 1000; ++i) {\n    size_t begin = absl::Uniform(bitgen, 0u, set.size());\n    size_t end = absl::Uniform(bitgen, begin, set.size());\n    ASSERT_EQ(end - begin, set.find(end) - set.find(begin))\n        << begin << \" \" << end;\n  }\n}\n\nTEST(Btree, IteratorAddition) {\n  absl::BitGen bitgen;\n  std::vector<int> vec;\n\n  // Randomize the set's insertion order so the nodes aren't all full.\n  constexpr int kSetSize = 1000000;\n  for (int i = 0; i < kSetSize; ++i) vec.push_back(i);\n  absl::c_shuffle(vec, bitgen);\n\n  absl::btree_set<int> set;\n  for (int i : vec) set.insert(i);\n\n  for (int i = 0; i < 1000; ++i) {\n    int begin = absl::Uniform(bitgen, 0, kSetSize);\n    int end = absl::Uniform(bitgen, begin, kSetSize);\n    ASSERT_LE(begin, end);\n\n    auto it = set.find(begin);\n    it += end - begin;\n    ASSERT_EQ(it, set.find(end)) << end;\n\n    it += begin - end;\n    ASSERT_EQ(it, set.find(begin)) << begin;\n  }\n}\n\nTEST(Btree, IteratorAdditionOutOfBounds) {\n  const absl::btree_set<int> set({5});\n\n  auto it = set.find(5);\n\n  auto forward = it;\n  forward += 1;\n  EXPECT_EQ(forward, set.end());\n\n  auto backward = it;\n  EXPECT_EQ(backward, set.begin());\n\n  if (IsAssertEnabled()) {\n    EXPECT_DEATH(forward += 1, \"n == 0\");\n    EXPECT_DEATH(backward += -1, \"position >= node->start\");\n  }\n}\n\nTEST(Btree, IteratorSubtraction) {\n  absl::BitGen bitgen;\n  std::vector<int> vec;\n\n  // Randomize the set's insertion order so the nodes aren't all full.\n  constexpr int kSetSize = 1000000;\n  for (int i = 0; i < kSetSize; ++i) vec.push_back(i);\n  absl::c_shuffle(vec, bitgen);\n\n  absl::btree_set<int> set;\n  for (int i : vec) set.insert(i);\n\n  for (int i = 0; i < 1000; ++i) {\n    int begin = absl::Uniform(bitgen, 0, kSetSize);\n    int end = absl::Uniform(bitgen, begin, kSetSize);\n    ASSERT_LE(begin, end);\n\n    auto it = set.find(end);\n    it -= end - begin;\n    ASSERT_EQ(it, set.find(begin)) << begin;\n\n    it -= begin - end;\n    ASSERT_EQ(it, set.find(end)) << end;\n  }\n}\n\nTEST(Btree, IteratorSubtractionOutOfBounds) {\n  const absl::btree_set<int> set({5});\n\n  auto it = set.find(5);\n\n  auto backward = it;\n  EXPECT_EQ(backward, set.begin());\n\n  auto forward = it;\n  forward -= -1;\n  EXPECT_EQ(forward, set.end());\n\n  if (IsAssertEnabled()) {\n    EXPECT_DEATH(backward -= 1, \"position >= node->start\");\n    EXPECT_DEATH(forward -= -1, \"n == 0\");\n  }\n}\n\nTEST(Btree, DereferencingEndIterator) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  absl::btree_set<int> set;\n  for (int i = 0; i < 1000; ++i) set.insert(i);\n  EXPECT_DEATH(*set.end(), R\"regex(Dereferencing end\\(\\) iterator)regex\");\n}\n\nTEST(Btree, InvalidIteratorComparison) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  absl::btree_set<int> set1, set2;\n  for (int i = 0; i < 1000; ++i) {\n    set1.insert(i);\n    set2.insert(i);\n  }\n\n  constexpr const char *kValueInitDeathMessage =\n      \"Comparing default-constructed iterator with .*non-default-constructed \"\n      \"iterator\";\n  typename absl::btree_set<int>::iterator iter1, iter2;\n  EXPECT_EQ(iter1, iter2);\n  EXPECT_DEATH(void(set1.begin() == iter1), kValueInitDeathMessage);\n  EXPECT_DEATH(void(iter1 == set1.begin()), kValueInitDeathMessage);\n\n  constexpr const char *kDifferentContainerDeathMessage =\n      \"Comparing iterators from different containers\";\n  iter1 = set1.begin();\n  iter2 = set2.begin();\n  EXPECT_DEATH(void(iter1 == iter2), kDifferentContainerDeathMessage);\n  EXPECT_DEATH(void(iter2 == iter1), kDifferentContainerDeathMessage);\n}\n\nTEST(Btree, InvalidPointerUse) {\n  if (!kAsan)\n    GTEST_SKIP() << \"We only detect invalid pointer use in ASan mode.\";\n\n  absl::btree_set<int> set;\n  set.insert(0);\n  const int *ptr = &*set.begin();\n  set.insert(1);\n  EXPECT_DEATH(std::cout << *ptr, \"use-after-free\");\n  size_t slots_per_node = BtreeNodePeer::GetNumSlotsPerNode<decltype(set)>();\n  for (int i = 2; i < slots_per_node - 1; ++i) set.insert(i);\n  ptr = &*set.begin();\n  set.insert(static_cast<int>(slots_per_node));\n  EXPECT_DEATH(std::cout << *ptr, \"use-after-free\");\n}\n\ntemplate<typename Set>\nvoid TestBasicFunctionality(Set set) {\n  using value_type = typename Set::value_type;\n  for (int i = 0; i < 100; ++i) { set.insert(value_type(i)); }\n  for (int i = 50; i < 100; ++i) { set.erase(value_type(i)); }\n  auto it = set.begin();\n  for (int i = 0; i < 50; ++i, ++it) {\n    ASSERT_EQ(set.find(value_type(i)), it) << i;\n  }\n}\n\ntemplate<size_t align>\nstruct alignas(align) OveralignedKey {\n  explicit OveralignedKey(int i) : key(i) {}\n  bool operator<(const OveralignedKey &other) const { return key < other.key; }\n  int key = 0;\n};\n\nTEST(Btree, OveralignedKey) {\n  // Test basic functionality with both even and odd numbers of slots per node.\n  // The goal here is to detect cases where alignment may be incorrect.\n  TestBasicFunctionality(\n      SizedBtreeSet<OveralignedKey<16>, /*TargetValuesPerNode=*/8>());\n  TestBasicFunctionality(\n      SizedBtreeSet<OveralignedKey<16>, /*TargetValuesPerNode=*/9>());\n}\n\nTEST(Btree, FieldTypeEqualsSlotType) {\n  // This breaks if we try to do layout_type::Pointer<slot_type> because\n  // slot_type is the same as field_type.\n  using set_type = absl::btree_set<uint8_t>;\n  static_assert(BtreeNodePeer::FieldTypeEqualsSlotType<set_type>(), \"\");\n  TestBasicFunctionality(set_type());\n}\n\n// Alias whose only purpose is to have the same length as set_params for better\n// alignment in the test below.\ntemplate <typename... T>\nusing set_p_impl = set_params_impl<T...>;\n\nTEST(BtreeTest, SetParamsStripsDefaults) {\n  using K = int;\n  using DA = btree_set_defaults<int>::Compare;\n  using DB = btree_set_defaults<int>::Alloc;\n  using DC = btree_set_defaults<int>::TargetNodeSize;\n  using DD = btree_set_defaults<int>::IsMulti;\n\n  using XA = std::greater<int>;\n  struct XB {};\n  using XC = std::integral_constant<int, 100>;\n  using XD = std::true_type;\n\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, XB, XC{}, XD{}>,\n                              set_p_impl<K, XA, XB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, XB, XC{}, DD{}>,\n                              set_p_impl<K, XA, XB, XC>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, XB, DC{}, XD{}>,\n                              set_p_impl<K, XA, XB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, XB, DC{}, DD{}>,\n                              set_p_impl<K, XA, XB>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, DB, XC{}, XD{}>,\n                              set_p_impl<K, XA, DB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, DB, XC{}, DD{}>,\n                              set_p_impl<K, XA, DB, XC>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, DB, DC{}, XD{}>,\n                              set_p_impl<K, XA, DB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, XA, DB, DC{}, DD{}>,\n                              set_p_impl<K, XA>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, XB, XC{}, XD{}>,\n                              set_p_impl<K, DA, XB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, XB, XC{}, DD{}>,\n                              set_p_impl<K, DA, XB, XC>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, XB, DC{}, XD{}>,\n                              set_p_impl<K, DA, XB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, XB, DC{}, DD{}>,\n                              set_p_impl<K, DA, XB>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, DB, XC{}, XD{}>,\n                              set_p_impl<K, DA, DB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, DB, XC{}, DD{}>,\n                              set_p_impl<K, DA, DB, XC>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, DB, DC{}, XD{}>,\n                              set_p_impl<K, DA, DB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<set_params<K, DA, DB, DC{}, DD{}>,\n                              set_p_impl<K>>));\n}\n\n// Alias whose only purpose is to have the same length as map_params for better\n// alignment in the test below.\ntemplate <typename... T>\nusing map_p_impl = map_params_impl<T...>;\n\nTEST(BtreeTest, MapParamsStripsDefaults) {\n  using K = int;\n  using V = double;\n  using DA = btree_map_defaults<int, double>::Compare;\n  using DB = btree_map_defaults<int, double>::Alloc;\n  using DC = btree_map_defaults<int, double>::TargetNodeSize;\n  using DD = btree_map_defaults<int, double>::IsMulti;\n\n  using XA = std::greater<int>;\n  struct XB {};\n  using XC = std::integral_constant<int, 100>;\n  using XD = std::true_type;\n\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, XB, XC{}, XD{}>,\n                              map_p_impl<K, V, XA, XB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, XB, XC{}, DD{}>,\n                              map_p_impl<K, V, XA, XB, XC>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, XB, DC{}, XD{}>,\n                              map_p_impl<K, V, XA, XB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, XB, DC{}, DD{}>,\n                              map_p_impl<K, V, XA, XB>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, DB, XC{}, XD{}>,\n                              map_p_impl<K, V, XA, DB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, DB, XC{}, DD{}>,\n                              map_p_impl<K, V, XA, DB, XC>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, DB, DC{}, XD{}>,\n                              map_p_impl<K, V, XA, DB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, XA, DB, DC{}, DD{}>,\n                              map_p_impl<K, V, XA>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, XB, XC{}, XD{}>,\n                              map_p_impl<K, V, DA, XB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, XB, XC{}, DD{}>,\n                              map_p_impl<K, V, DA, XB, XC>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, XB, DC{}, XD{}>,\n                              map_p_impl<K, V, DA, XB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, XB, DC{}, DD{}>,\n                              map_p_impl<K, V, DA, XB>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, DB, XC{}, XD{}>,\n                              map_p_impl<K, V, DA, DB, XC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, DB, XC{}, DD{}>,\n                              map_p_impl<K, V, DA, DB, XC>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, DB, DC{}, XD{}>,\n                              map_p_impl<K, V, DA, DB, DC, XD>>));\n  EXPECT_TRUE((std::is_same_v<map_params<K, V, DA, DB, DC{}, DD{}>,\n                              map_p_impl<K, V>>));\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/btree_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_BTREE_TEST_H_\n#define ABSL_CONTAINER_BTREE_TEST_H_\n\n#include <algorithm>\n#include <cassert>\n#include <random>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/container/btree_map.h\"\n#include \"absl/container/btree_set.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// Like remove_const but propagates the removal through std::pair.\ntemplate <typename T>\nstruct remove_pair_const {\n  using type = typename std::remove_const<T>::type;\n};\ntemplate <typename T, typename U>\nstruct remove_pair_const<std::pair<T, U> > {\n  using type = std::pair<typename remove_pair_const<T>::type,\n                         typename remove_pair_const<U>::type>;\n};\n\n// Utility class to provide an accessor for a key given a value. The default\n// behavior is to treat the value as a pair and return the first element.\ntemplate <typename K, typename V>\nstruct KeyOfValue {\n  struct type {\n    const K& operator()(const V& p) const { return p.first; }\n  };\n};\n\n// Partial specialization of KeyOfValue class for when the key and value are\n// the same type such as in set<> and btree_set<>.\ntemplate <typename K>\nstruct KeyOfValue<K, K> {\n  struct type {\n    const K& operator()(const K& k) const { return k; }\n  };\n};\n\ninline char* GenerateDigits(char buf[16], unsigned val, unsigned maxval) {\n  assert(val <= maxval);\n  constexpr unsigned kBase = 64;  // avoid integer division.\n  unsigned p = 15;\n  buf[p--] = 0;\n  while (maxval > 0) {\n    buf[p--] = ' ' + (val % kBase);\n    val /= kBase;\n    maxval /= kBase;\n  }\n  return buf + p + 1;\n}\n\ntemplate <typename K>\nstruct Generator {\n  int maxval;\n  explicit Generator(int m) : maxval(m) {}\n  K operator()(int i) const {\n    assert(i <= maxval);\n    return K(i);\n  }\n};\n\ntemplate <>\nstruct Generator<absl::Time> {\n  int maxval;\n  explicit Generator(int m) : maxval(m) {}\n  absl::Time operator()(int i) const { return absl::FromUnixMillis(i); }\n};\n\ntemplate <>\nstruct Generator<std::string> {\n  int maxval;\n  explicit Generator(int m) : maxval(m) {}\n  std::string operator()(int i) const {\n    char buf[16];\n    return GenerateDigits(buf, i, maxval);\n  }\n};\n\ntemplate <>\nstruct Generator<Cord> {\n  int maxval;\n  explicit Generator(int m) : maxval(m) {}\n  Cord operator()(int i) const {\n    char buf[16];\n    return Cord(GenerateDigits(buf, i, maxval));\n  }\n};\n\ntemplate <typename T, typename U>\nstruct Generator<std::pair<T, U> > {\n  Generator<typename remove_pair_const<T>::type> tgen;\n  Generator<typename remove_pair_const<U>::type> ugen;\n\n  explicit Generator(int m) : tgen(m), ugen(m) {}\n  std::pair<T, U> operator()(int i) const {\n    return std::make_pair(tgen(i), ugen(i));\n  }\n};\n\n// Generate n values for our tests and benchmarks. Value range is [0, maxval].\ninline std::vector<int> GenerateNumbersWithSeed(int n, int maxval, int seed) {\n  // NOTE: Some tests rely on generated numbers not changing between test runs.\n  // We use std::minstd_rand0 because it is well-defined, but don't use\n  // std::uniform_int_distribution because platforms use different algorithms.\n  std::minstd_rand0 rng(seed);\n\n  std::vector<int> values;\n  absl::flat_hash_set<int> unique_values;\n  if (values.size() < n) {\n    for (int i = values.size(); i < n; i++) {\n      int value;\n      do {\n        value = static_cast<int>(rng()) % (maxval + 1);\n      } while (!unique_values.insert(value).second);\n\n      values.push_back(value);\n    }\n  }\n  return values;\n}\n\n// Generates n values in the range [0, maxval].\ntemplate <typename V>\nstd::vector<V> GenerateValuesWithSeed(int n, int maxval, int seed) {\n  const std::vector<int> nums = GenerateNumbersWithSeed(n, maxval, seed);\n  Generator<V> gen(maxval);\n  std::vector<V> vec;\n\n  vec.reserve(n);\n  for (int i = 0; i < n; i++) {\n    vec.push_back(gen(nums[i]));\n  }\n\n  return vec;\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_BTREE_TEST_H_\n"
  },
  {
    "path": "absl/container/chunked_queue.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: chunked_queue.h\n// -----------------------------------------------------------------------------\n//\n// `std::deque` provides random access and fast push/pop back/front. It is\n// implemented as an array of fixed blocks. It provides no control of block size\n// and implementations differ; libstdc++ tries to allocate blocks of ~512 bytes\n// and libc++ tries for blocks of ~4k bytes.\n//\n// `absl::chunked_queue` provides the same minus random access. It is\n// implemented as a double-linked list of fixed or variable sized blocks.\n//\n// `absl::chunked_queue` is useful when memory usage is paramount as it provides\n//  finegrained and configurable block sizing.\n//\n// The interface supported by this class is limited to:\n//\n//   empty()\n//   size()\n//   max_size()\n//   shrink_to_fit()\n//   resize()\n//   assign()\n//   push_back()\n//   emplace_back()\n//   pop_front()\n//   front()\n//   back()\n//   swap()\n//   clear()\n//   begin(), end()\n//   cbegin(), cend()\n//\n// === ADVANCED USAGE\n//\n// == clear()\n//\n// As an optimization clear() leaves the first block of the chunked_queue\n// allocated (but empty). So clear will not delete all memory of the container.\n// In order to do so, call shrink_to_fit() or swap the container with an empty\n// one.\n//\n//   absl::chunked_queue<int64> q = {1, 2, 3};\n//   q.clear();\n//   q.shrink_to_fit();\n//\n// == block size customization\n//\n// chunked_queue allows customization of the block size for each block. By\n// default the block size is set to 1 element and the size doubles for the next\n// block until it reaches the default max block size, which is 128 elements.\n//\n// = fixed size\n//\n// When only the first block size parameter is specified, it sets a fixed block\n// size for all blocks:\n//\n//   chunked_queue<T, 32>: 32 elements per block\n//\n// The smaller the block size, the less the memory usage for small queues at the\n// cost of performance. Caveat: For large queues, a smaller block size will\n// increase memory usage, and reduce performance.\n//\n// = variable size\n//\n// When both block size parameters are specified, they set the min and max block\n// sizes for the blocks. Initially the queue starts with the min block size and\n// as it grows, the size of each block grows until it reaches the max block\n// size.\n// New blocks are double the size of the tail block (so they at least\n// double the size of the queue).\n//\n//   chunked_queue<T, 4, 64>: first block 4 elements, second block 8 elements,\n//                            third block 16 elements, fourth block 32 elements,\n//                            all other blocks 64 elements\n//\n// One can specify a min and max such that small queues will not waste memory\n// and large queues will not have too many blocks.\n\n#ifndef ABSL_CONTAINER_CHUNKED_QUEUE_H_\n#define ABSL_CONTAINER_CHUNKED_QUEUE_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <initializer_list>\n#include <iterator>\n#include <memory>\n#include <new>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/iterator_traits.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/internal/chunked_queue.h\"\n#include \"absl/container/internal/layout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename T, size_t BLo = 0, size_t BHi = BLo,\n          typename Allocator = std::allocator<T>>\nclass chunked_queue {\n public:\n  static constexpr size_t kBlockSizeMin = (BLo == 0 && BHi == 0) ? 1 : BLo;\n  static constexpr size_t kBlockSizeMax = (BLo == 0 && BHi == 0) ? 128 : BHi;\n\n private:\n  static_assert(kBlockSizeMin > 0, \"Min block size cannot be zero\");\n  static_assert(kBlockSizeMin <= kBlockSizeMax, \"Invalid block size bounds\");\n\n  using Block = container_internal::ChunkedQueueBlock<T, Allocator>;\n  using AllocatorTraits = std::allocator_traits<Allocator>;\n\n  class iterator_common {\n   public:\n    friend bool operator==(const iterator_common& a, const iterator_common& b) {\n      return a.ptr == b.ptr;\n    }\n\n    friend bool operator!=(const iterator_common& a, const iterator_common& b) {\n      return !(a == b);\n    }\n\n   protected:\n    iterator_common() = default;\n    explicit iterator_common(Block* b)\n        : block(b), ptr(b->start()), limit(b->limit()) {}\n\n    void Incr() {\n      // If we do not have a next block, make ptr point one past the end of this\n      // block. If we do have a next block, make ptr point to the first element\n      // of the next block.\n      ++ptr;\n      if (ptr == limit && block->next()) *this = iterator_common(block->next());\n    }\n\n    void IncrBy(size_t n) {\n      while (ptr + n > limit) {\n        n -= limit - ptr;\n        *this = iterator_common(block->next());\n      }\n      ptr += n;\n    }\n\n    Block* block = nullptr;\n    T* ptr = nullptr;\n    T* limit = nullptr;\n  };\n\n  // CT can be either T or const T.\n  template <typename CT>\n  class basic_iterator : public iterator_common {\n   public:\n    using iterator_category = std::forward_iterator_tag;\n    using value_type = typename AllocatorTraits::value_type;\n    using difference_type = typename AllocatorTraits::difference_type;\n    using pointer =\n        typename std::conditional<std::is_const<CT>::value,\n                                  typename AllocatorTraits::const_pointer,\n                                  typename AllocatorTraits::pointer>::type;\n    using reference = CT&;\n\n    basic_iterator() = default;\n\n    // Copy ctor if CT is T.\n    // Otherwise it's a conversion of iterator to const_iterator.\n    basic_iterator(const basic_iterator<T>& it)  // NOLINT(runtime/explicit)\n        : iterator_common(it) {}\n\n    basic_iterator& operator=(const basic_iterator& other) = default;\n\n    reference operator*() const { return *this->ptr; }\n    pointer operator->() const { return this->ptr; }\n    basic_iterator& operator++() {\n      this->Incr();\n      return *this;\n    }\n    basic_iterator operator++(int) {\n      basic_iterator t = *this;\n      ++*this;\n      return t;\n    }\n\n   private:\n    explicit basic_iterator(Block* b) : iterator_common(b) {}\n\n    friend chunked_queue;\n  };\n\n public:\n  using allocator_type = typename AllocatorTraits::allocator_type;\n  using value_type = typename AllocatorTraits::value_type;\n  using size_type = typename AllocatorTraits::size_type;\n  using difference_type = typename AllocatorTraits::difference_type;\n  using reference = value_type&;\n  using const_reference = const value_type&;\n  using iterator = basic_iterator<T>;\n  using const_iterator = basic_iterator<const T>;\n\n  // Constructs an empty queue.\n  chunked_queue() : chunked_queue(allocator_type()) {}\n\n  // Constructs an empty queue with a custom allocator.\n  explicit chunked_queue(const allocator_type& alloc)\n      : alloc_and_size_(alloc) {}\n\n  // Constructs a queue with `count` default-inserted elements.\n  explicit chunked_queue(size_type count,\n                         const allocator_type& alloc = allocator_type())\n      : alloc_and_size_(alloc) {\n    resize(count);\n  }\n\n  // Constructs a queue with `count` copies of `value`.\n  chunked_queue(size_type count, const T& value,\n                const allocator_type& alloc = allocator_type())\n      : alloc_and_size_(alloc) {\n    assign(count, value);\n  }\n\n  // Constructs a queue with the contents of the range [first, last).\n  template <typename Iter,\n            typename = std::enable_if_t<\n                base_internal::IsAtLeastInputIterator<Iter>::value>>\n  chunked_queue(Iter first, Iter last,\n                const allocator_type& alloc = allocator_type())\n      : alloc_and_size_(alloc) {\n    using Tag = typename std::iterator_traits<Iter>::iterator_category;\n    RangeInit(first, last, Tag());\n  }\n\n  // Constructs a queue with the contents of the initializer list `list`.\n  chunked_queue(std::initializer_list<T> list,\n                const allocator_type& alloc = allocator_type())\n      : chunked_queue(list.begin(), list.end(), alloc) {}\n\n  ~chunked_queue();\n\n  // Copy constructor.\n  chunked_queue(const chunked_queue& other)\n      : chunked_queue(other,\n                      AllocatorTraits::select_on_container_copy_construction(\n                          other.alloc_and_size_.allocator())) {}\n\n  // Copy constructor with specific allocator.\n  chunked_queue(const chunked_queue& other, const allocator_type& alloc)\n      : alloc_and_size_(alloc) {\n    for (const_reference item : other) {\n      push_back(item);\n    }\n  }\n\n  // Move constructor.\n  chunked_queue(chunked_queue&& other) noexcept\n      : head_(other.head_),\n        tail_(other.tail_),\n        alloc_and_size_(std::move(other.alloc_and_size_)) {\n    other.head_ = {};\n    other.tail_ = {};\n    other.alloc_and_size_.size = 0;\n  }\n\n  // Replaces contents with those from initializer list `il`.\n  chunked_queue& operator=(std::initializer_list<T> il) {\n    assign(il.begin(), il.end());\n    return *this;\n  }\n\n  // Copy assignment operator.\n  chunked_queue& operator=(const chunked_queue& other) {\n    if (this == &other) {\n      return *this;\n    }\n    if (AllocatorTraits::propagate_on_container_copy_assignment::value &&\n        (alloc_and_size_.allocator() != other.alloc_and_size_.allocator())) {\n      // Destroy all current elements and blocks with the current allocator,\n      // before switching this to use the allocator propagated from \"other\".\n      DestroyAndDeallocateAll();\n      alloc_and_size_ = AllocatorAndSize(other.alloc_and_size_.allocator());\n    }\n    assign(other.begin(), other.end());\n    return *this;\n  }\n\n  // Move assignment operator.\n  chunked_queue& operator=(chunked_queue&& other) noexcept;\n\n  // Returns true if the queue contains no elements.\n  bool empty() const { return alloc_and_size_.size == 0; }\n\n  // Returns the number of elements in the queue.\n  size_t size() const { return alloc_and_size_.size; }\n\n  // Returns the maximum number of elements the queue is able to hold.\n  size_type max_size() const noexcept {\n    return AllocatorTraits::max_size(alloc_and_size_.allocator());\n  }\n\n  // Resizes the container to contain `new_size` elements.\n  // If `new_size > size()`, additional default-inserted elements are appended.\n  // If `new_size < size()`, elements are removed from the end.\n  void resize(size_t new_size);\n\n  // Resizes the container to contain `new_size` elements.\n  // If `new_size > size()`, additional copies of `value` are appended.\n  // If `new_size < size()`, elements are removed from the end.\n  void resize(size_type new_size, const T& value) {\n    if (new_size > size()) {\n      size_t to_add = new_size - size();\n      for (size_t i = 0; i < to_add; ++i) {\n        push_back(value);\n      }\n    } else {\n      resize(new_size);\n    }\n  }\n\n  // Requests the removal of unused capacity.\n  void shrink_to_fit() {\n    // As an optimization clear() leaves the first block of the chunked_queue\n    // allocated (but empty). When empty, shrink_to_fit() deallocates the first\n    // block by swapping it a newly constructed container that has no first\n    // block.\n    if (empty()) {\n      chunked_queue(alloc_and_size_.allocator()).swap(*this);\n    }\n  }\n\n  // Replaces the contents with copies of those in the range [first, last).\n  template <typename Iter,\n            typename = std::enable_if_t<\n                base_internal::IsAtLeastInputIterator<Iter>::value>>\n  void assign(Iter first, Iter last) {\n    auto out = begin();\n    Block* prev_block = nullptr;\n\n    // Overwrite existing elements.\n    for (; out != end() && first != last; ++first) {\n      // Track the previous block so we can correctly update tail_ if we stop\n      // exactly at a block boundary.\n      if (out.ptr + 1 == out.block->limit()) {\n        prev_block = out.block;\n      }\n      *out = *first;\n      ++out;\n    }\n\n    // If we stopped exactly at the start of a block (meaning the previous block\n    // was full), we must ensure tail_ points to the end of the previous block,\n    // not the start of the current (now empty and to be deleted) block.\n    // This maintains the invariant required by back() which assumes tail_\n    // never points to the start of a block (unless it's the only block).\n    if (!empty() && out.block != nullptr && out.ptr == out.block->start() &&\n        prev_block != nullptr) {\n      // Delete the current block and all subsequent blocks.\n      //\n      // NOTE: Calling EraseAllFrom on an iterator that points to the limit of\n      // the previous block will not delete any element from the previous block.\n      iterator prev_block_end(prev_block);\n      prev_block_end.ptr = prev_block->limit();\n      EraseAllFrom(prev_block_end);\n\n      // Update tail_ to point to the end of the previous block.\n      tail_ = prev_block_end;\n      prev_block->set_next(nullptr);\n    } else {\n      // Standard erase from the current position to the end.\n      EraseAllFrom(out);\n    }\n\n    // Append any remaining new elements.\n    for (; first != last; ++first) {\n      push_back(*first);\n    }\n  }\n\n  // Replaces the contents with `count` copies of `value`.\n  void assign(size_type count, const T& value) {\n    clear();\n    for (size_type i = 0; i < count; ++i) {\n      push_back(value);\n    }\n  }\n\n  // Replaces the contents with the elements from the initializer list `il`.\n  void assign(std::initializer_list<T> il) { assign(il.begin(), il.end()); }\n\n  // Appends the given element value to the end of the container.\n  // Invalidates `end()` iterator. References to other elements remain valid.\n  void push_back(const T& val) { emplace_back(val); }\n  void push_back(T&& val) { emplace_back(std::move(val)); }\n\n  // Appends a new element to the end of the container.\n  // The element is constructed in-place with `args`.\n  // Returns a reference to the new element.\n  // Invalidates `end()` iterator. References to other elements remain valid.\n  template <typename... A>\n  T& emplace_back(A&&... args) {\n    T* storage = AllocateBack();\n    AllocatorTraits::construct(alloc_and_size_.allocator(), storage,\n                               std::forward<A>(args)...);\n    return *storage;\n  }\n\n  // Removes the first element of the container.\n  // Invalidates iterators to the removed element.\n  // REQUIRES: !empty()\n  void pop_front();\n\n  // Returns a reference to the first element in the container.\n  // REQUIRES: !empty()\n  T& front() {\n    ABSL_HARDENING_ASSERT(!empty());\n    return *head_;\n  }\n  const T& front() const {\n    ABSL_HARDENING_ASSERT(!empty());\n    return *head_;\n  }\n\n  // Returns a reference to the last element in the container.\n  // REQUIRES: !empty()\n  T& back() {\n    ABSL_HARDENING_ASSERT(!empty());\n    return *(&*tail_ - 1);\n  }\n  const T& back() const {\n    ABSL_HARDENING_ASSERT(!empty());\n    return *(&*tail_ - 1);\n  }\n\n  // Swaps the contents of this queue with `other`.\n  void swap(chunked_queue& other) noexcept {\n    using std::swap;\n    swap(head_, other.head_);\n    swap(tail_, other.tail_);\n    if (AllocatorTraits::propagate_on_container_swap::value) {\n      swap(alloc_and_size_, other.alloc_and_size_);\n    } else {\n      // Swap only the sizes; each object keeps its allocator.\n      //\n      // (It is undefined behavior to swap between two containers with unequal\n      // allocators if propagate_on_container_swap is false, so we don't have to\n      // handle that here like we do in the move-assignment operator.)\n      ABSL_HARDENING_ASSERT(get_allocator() == other.get_allocator());\n      swap(alloc_and_size_.size, other.alloc_and_size_.size);\n    }\n  }\n\n  // Erases all elements from the container.\n  // Note: Leaves one empty block allocated as an optimization.\n  // To free all memory, call shrink_to_fit() after calling clear().\n  void clear();\n\n  iterator begin() { return head_; }\n  iterator end() { return tail_; }\n\n  const_iterator begin() const { return head_; }\n  const_iterator end() const { return tail_; }\n\n  const_iterator cbegin() const { return head_; }\n  const_iterator cend() const { return tail_; }\n\n  // Returns the allocator associated with the container.\n  allocator_type get_allocator() const { return alloc_and_size_.allocator(); }\n\n private:\n  // Empty base-class optimization: bundle storage for our allocator together\n  // with a field we had to store anyway (size), via inheriting from the\n  // allocator, so this allocator instance doesn't consume any storage\n  // when its type has no data members.\n  struct AllocatorAndSize : private allocator_type {\n    explicit AllocatorAndSize(const allocator_type& alloc)\n        : allocator_type(alloc) {}\n    const allocator_type& allocator() const { return *this; }\n    allocator_type& allocator() { return *this; }\n    size_t size = 0;\n  };\n\n  template <typename Iter>\n  void RangeInit(Iter first, Iter last, std::input_iterator_tag) {\n    while (first != last) {\n      AddTailBlock();\n      for (; first != last && tail_.ptr != tail_.limit;\n           ++alloc_and_size_.size, ++tail_.ptr, ++first) {\n        AllocatorTraits::construct(alloc_and_size_.allocator(), tail_.ptr,\n                                   *first);\n      }\n    }\n  }\n\n  void Construct(T* start, T* limit) {\n    ABSL_ASSERT(start <= limit);\n    for (; start != limit; ++start) {\n      AllocatorTraits::construct(alloc_and_size_.allocator(), start);\n    }\n  }\n\n  size_t Destroy(T* start, T* limit) {\n    ABSL_ASSERT(start <= limit);\n    const size_t n = limit - start;\n    for (; start != limit; ++start) {\n      AllocatorTraits::destroy(alloc_and_size_.allocator(), start);\n    }\n    return n;\n  }\n\n  T* block_begin(Block* b) const {\n    return b == head_.block ? head_.ptr : b->start();\n  }\n  T* block_end(Block* b) const {\n    // We have the choice of !b->next or b == tail_.block to determine if b is\n    // the tail or not. !b->next is usually faster because the caller of\n    // block_end() is most likely traversing the list of blocks so b->next is\n    // already fetched into some register.\n    return !b->next() ? tail_.ptr : b->limit();\n  }\n\n  void AddTailBlock();\n  size_t NewBlockSize() {\n    // Double the last block size and bound to [kBlockSizeMin, kBlockSizeMax].\n    if (!tail_.block) return kBlockSizeMin;\n    return (std::min)(kBlockSizeMax, 2 * tail_.block->size());\n  }\n\n  T* AllocateBack();\n  void EraseAllFrom(iterator i);\n\n  // Destroys any contained elements and destroys all allocated storage.\n  // (Like clear(), except this doesn't leave any empty blocks behind.)\n  void DestroyAndDeallocateAll();\n\n  // The set of elements in the queue is the following:\n  //\n  // (1) When we have just one block:\n  //      [head_.ptr .. tail_.ptr-1]\n  // (2) When we have multiple blocks:\n  //      [head_.ptr .. head_.limit-1]\n  //      ... concatenation of all elements from interior blocks ...\n  //      [tail_.ptr .. tail_.limit-1]\n  //\n  // Rep invariants:\n  // When have just one block:\n  //   head_.limit == tail_.limit == &head_.block->element[kBlockSize]\n  // Always:\n  //   head_.ptr <= head_.limit\n  //   tail_.ptr <= tail_.limit\n\n  iterator head_;\n  iterator tail_;\n  AllocatorAndSize alloc_and_size_;\n};\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\nconstexpr size_t chunked_queue<T, BLo, BHi, Allocator>::kBlockSizeMin;\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\nconstexpr size_t chunked_queue<T, BLo, BHi, Allocator>::kBlockSizeMax;\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline void swap(chunked_queue<T, BLo, BHi, Allocator>& a,\n                 chunked_queue<T, BLo, BHi, Allocator>& b) noexcept {\n  a.swap(b);\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\nchunked_queue<T, BLo, BHi, Allocator>&\nchunked_queue<T, BLo, BHi, Allocator>::operator=(\n    chunked_queue&& other) noexcept {\n  if (this == &other) {\n    return *this;\n  }\n  DestroyAndDeallocateAll();\n\n  if constexpr (AllocatorTraits::propagate_on_container_move_assignment::\n                    value) {\n    // Take over the storage of \"other\", along with its allocator.\n    head_ = other.head_;\n    tail_ = other.tail_;\n    alloc_and_size_ = std::move(other.alloc_and_size_);\n    other.head_ = {};\n    other.tail_ = {};\n    other.alloc_and_size_.size = 0;\n  } else if (get_allocator() == other.get_allocator()) {\n    // Take over the storage of \"other\", with which we share an allocator.\n    head_ = other.head_;\n    tail_ = other.tail_;\n    alloc_and_size_.size = other.alloc_and_size_.size;\n    other.head_ = {};\n    other.tail_ = {};\n    other.alloc_and_size_.size = 0;\n  } else {\n    // We cannot take over of the storage from \"other\", since it has a different\n    // allocator; we're stuck move-assigning elements individually.\n    for (auto& elem : other) {\n      push_back(std::move(elem));\n    }\n  }\n  return *this;\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline chunked_queue<T, BLo, BHi, Allocator>::~chunked_queue() {\n  Block* b = head_.block;\n  while (b) {\n    Block* next = b->next();\n    Destroy(block_begin(b), block_end(b));\n    Block::Delete(b, &alloc_and_size_.allocator());\n    b = next;\n  }\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\nvoid chunked_queue<T, BLo, BHi, Allocator>::resize(size_t new_size) {\n  while (new_size > size()) {\n    ptrdiff_t to_add = new_size - size();\n    if (tail_.ptr == tail_.limit) {\n      AddTailBlock();\n    }\n    T* start = tail_.ptr;\n    T* limit = (std::min)(tail_.limit, start + to_add);\n    Construct(start, limit);\n    tail_.ptr = limit;\n    alloc_and_size_.size += limit - start;\n  }\n  if (size() == new_size) {\n    return;\n  }\n  ABSL_ASSERT(new_size < size());\n  auto new_end = begin();\n  new_end.IncrBy(new_size);\n  ABSL_ASSERT(new_end != end());\n  EraseAllFrom(new_end);\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline void chunked_queue<T, BLo, BHi, Allocator>::AddTailBlock() {\n  ABSL_ASSERT(tail_.ptr == tail_.limit);\n  auto* b = Block::New(NewBlockSize(), &alloc_and_size_.allocator());\n  if (!head_.block) {\n    ABSL_ASSERT(!tail_.block);\n    head_ = iterator(b);\n  } else {\n    ABSL_ASSERT(tail_.block);\n    tail_.block->set_next(b);\n  }\n  tail_ = iterator(b);\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline T* chunked_queue<T, BLo, BHi, Allocator>::AllocateBack() {\n  if (tail_.ptr == tail_.limit) {\n    AddTailBlock();\n  }\n  ++alloc_and_size_.size;\n  return tail_.ptr++;\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline void chunked_queue<T, BLo, BHi, Allocator>::EraseAllFrom(iterator i) {\n  if (!i.block) {\n    return;\n  }\n  ABSL_ASSERT(i.ptr);\n  ABSL_ASSERT(i.limit);\n  alloc_and_size_.size -= Destroy(i.ptr, block_end(i.block));\n  Block* b = i.block->next();\n  while (b) {\n    Block* next = b->next();\n    alloc_and_size_.size -= Destroy(b->start(), block_end(b));\n    Block::Delete(b, &alloc_and_size_.allocator());\n    b = next;\n  }\n  tail_ = i;\n  tail_.block->set_next(nullptr);\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline void chunked_queue<T, BLo, BHi, Allocator>::DestroyAndDeallocateAll() {\n  Block* b = head_.block;\n  while (b) {\n    Block* next = b->next();\n    Destroy(block_begin(b), block_end(b));\n    Block::Delete(b, &alloc_and_size_.allocator());\n    b = next;\n  }\n  head_ = iterator();\n  tail_ = iterator();\n  alloc_and_size_.size = 0;\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\ninline void chunked_queue<T, BLo, BHi, Allocator>::pop_front() {\n  ABSL_HARDENING_ASSERT(!empty());\n  ABSL_ASSERT(head_.block);\n  AllocatorTraits::destroy(alloc_and_size_.allocator(), head_.ptr);\n  ++head_.ptr;\n  --alloc_and_size_.size;\n  if (empty()) {\n    // Reset head and tail to the start of the (only) block.\n    ABSL_ASSERT(head_.block == tail_.block);\n    head_.ptr = tail_.ptr = head_.block->start();\n    return;\n  }\n  if (head_.ptr == head_.limit) {\n    Block* n = head_.block->next();\n    Block::Delete(head_.block, &alloc_and_size_.allocator());\n    head_ = iterator(n);\n  }\n}\n\ntemplate <typename T, size_t BLo, size_t BHi, typename Allocator>\nvoid chunked_queue<T, BLo, BHi, Allocator>::clear() {\n  // NOTE: As an optimization we leave one block allocated.\n  Block* b = head_.block;\n  if (!b) {\n    ABSL_ASSERT(empty());\n    return;\n  }\n  while (b) {\n    Block* next = b->next();\n    Destroy(block_begin(b), block_end(b));\n    if (head_.block != b) {\n      Block::Delete(b, &alloc_and_size_.allocator());\n    }\n    b = next;\n  }\n  b = head_.block;\n  b->set_next(nullptr);\n  head_ = tail_ = iterator(b);\n  alloc_and_size_.size = 0;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_CHUNKED_QUEUE_H_\n"
  },
  {
    "path": "absl/container/chunked_queue_benchmark.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n#include <forward_list>\n#include <list>\n#include <random>\n\n#include \"absl/container/chunked_queue.h\"\n#include \"absl/random/random.h\"\n#include \"absl/status/status.h\"\n#include \"absl/strings/cord.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\n// Queue implementation using std::forward_list. Used to benchmark\n// absl::chunked_queue against another plausable implementation.\ntemplate <typename T>\nclass forward_list_queue {\n public:\n  using iterator = typename std::forward_list<T>::iterator;\n\n  forward_list_queue() = default;\n  ~forward_list_queue() = default;\n\n  template <typename... Args>\n  void emplace_back(Args&&... args) {\n    if (list_.empty()) {\n      list_.emplace_front(std::forward<Args>(args)...);\n      tail_ = list_.begin();\n    } else {\n      list_.emplace_after(tail_, std::forward<Args>(args)...);\n      ++tail_;\n    }\n  }\n\n  void push_back(const T& value) { emplace_back(value); }\n  iterator begin() { return list_.begin(); }\n  iterator end() { return list_.end(); }\n  T& front() { return list_.front(); }\n  const T& front() const { return list_.front(); }\n  void pop_front() { list_.pop_front(); }\n  bool empty() const { return list_.empty(); }\n  void clear() { list_.clear(); }\n\n private:\n  std::forward_list<T> list_;\n  typename std::forward_list<T>::iterator tail_;\n};\n\ntemplate <class T>\nusing Deque = std::deque<T>;\ntemplate <class T>\nusing List = std::list<T>;\ntemplate <class T>\nusing FwdList = forward_list_queue<T>;\ntemplate <class T>\nusing Chunked = absl::chunked_queue<T>;\ntemplate <class T>\nusing ExpChunked = absl::chunked_queue<T, 2, 64>;\n\nclass Element {\n public:\n  Element() : Element(-1) {}\n  Element(int type) : type_(type) {}      // NOLINT\n  operator int() const { return type_; }  // NOLINT\n\n private:\n  int type_;\n  absl::Cord item_;\n  absl::Status status_;\n};\n\ntemplate <class Q>\nQ MakeQueue(int64_t num_elements) {\n  Q q;\n  for (int64_t i = 0; i < num_elements; i++) {\n    q.push_back(static_cast<int>(i));\n  }\n  return q;\n}\n\nvoid CustomArgs(benchmark::internal::Benchmark* b) {\n  b->Arg(1 << 4);\n  b->Arg(1 << 10);\n  b->Arg(1 << 17);\n}\n\ntemplate <class Q>\nvoid BM_construct(benchmark::State& state) {\n  for (auto s : state) {\n    Q q;\n    benchmark::DoNotOptimize(q);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_construct, Deque<int64_t>);\nBENCHMARK_TEMPLATE(BM_construct, List<int64_t>);\nBENCHMARK_TEMPLATE(BM_construct, FwdList<int64_t>);\nBENCHMARK_TEMPLATE(BM_construct, Chunked<int64_t>);\nBENCHMARK_TEMPLATE(BM_construct, ExpChunked<int64_t>);\nBENCHMARK_TEMPLATE(BM_construct, Deque<Element>);\nBENCHMARK_TEMPLATE(BM_construct, List<Element>);\nBENCHMARK_TEMPLATE(BM_construct, FwdList<Element>);\nBENCHMARK_TEMPLATE(BM_construct, Chunked<Element>);\nBENCHMARK_TEMPLATE(BM_construct, ExpChunked<Element>);\n\ntemplate <class Q>\nvoid BM_destroy(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  for (auto s : state) {\n    state.PauseTiming();\n    {\n      Q q = MakeQueue<Q>(num_elements);\n      benchmark::DoNotOptimize(q);\n      state.ResumeTiming();\n    }\n  }\n  state.SetItemsProcessed(state.iterations() * num_elements);\n}\n\nBENCHMARK_TEMPLATE(BM_destroy, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_destroy, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_push_back(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q;\n    state.ResumeTiming();\n    for (int j = 0; j < num_elements; j++) q.push_back(j);\n    benchmark::DoNotOptimize(q);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_push_back, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_back, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_pop_front(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q = MakeQueue<Q>(num_elements);\n    state.ResumeTiming();\n    for (int j = 0; j < num_elements; j++) q.pop_front();\n    benchmark::DoNotOptimize(q);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_pop_front, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_pop_front, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_clear(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q = MakeQueue<Q>(num_elements);\n    state.ResumeTiming();\n    q.clear();\n    benchmark::DoNotOptimize(q);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_clear, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_clear, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_iter(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q = MakeQueue<Q>(state.max_iterations);\n    int sum = 0;\n    state.ResumeTiming();\n    for (const auto& v : q) sum += v;\n    benchmark::DoNotOptimize(sum);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_iter, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_iter, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_resize_shrink(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q = MakeQueue<Q>(num_elements * 2);\n    state.ResumeTiming();\n    q.resize(num_elements);\n    benchmark::DoNotOptimize(q);\n  }\n}\n\n// FwdList does not support resize.\nBENCHMARK_TEMPLATE(BM_resize_shrink, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, List<int64_t>)->Apply(CustomArgs);\n// BENCHMARK_TEMPLATE(BM_resize_shrink, FwdList<int64>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, List<Element>)->Apply(CustomArgs);\n// BENCHMARK_TEMPLATE(BM_resize_shrink, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_shrink, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_resize_grow(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q = MakeQueue<Q>(num_elements);\n    state.ResumeTiming();\n    q.resize(static_cast<size_t>(num_elements) * 2);\n    benchmark::DoNotOptimize(q);\n  }\n}\n\n// FwdList does not support resize.\nBENCHMARK_TEMPLATE(BM_resize_grow, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, List<int64_t>)->Apply(CustomArgs);\n// BENCHMARK_TEMPLATE(BM_resize_grow, FwdList<int64>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, List<Element>)->Apply(CustomArgs);\n// BENCHMARK_TEMPLATE(BM_resize_grow, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_resize_grow, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_assign_shrink(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    const Q src = MakeQueue<Q>(num_elements);\n    Q dst = MakeQueue<Q>(num_elements * 2);\n    state.ResumeTiming();\n    dst = src;\n    benchmark::DoNotOptimize(dst);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_assign_shrink, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_shrink, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_assign_grow(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n  for (auto s : state) {\n    state.PauseTiming();\n    const Q src = MakeQueue<Q>(num_elements * 2);\n    Q dst = MakeQueue<Q>(num_elements);\n    state.ResumeTiming();\n    dst = src;\n    benchmark::DoNotOptimize(dst);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_assign_grow, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_assign_grow, ExpChunked<Element>)->Apply(CustomArgs);\n\ntemplate <class Q>\nvoid BM_push_pop(benchmark::State& state) {\n  const int64_t num_elements = state.range(0);\n\n  state.SetItemsProcessed(state.max_iterations * num_elements);\n\n  std::mt19937 rnd;\n  for (auto s : state) {\n    state.PauseTiming();\n    Q q;\n    state.ResumeTiming();\n    for (int j = 0; j < num_elements; j++) {\n      if (q.empty() || absl::Bernoulli(rnd, 0.5)) {\n        q.push_back(state.iterations());\n      } else {\n        q.pop_front();\n      }\n    }\n    benchmark::DoNotOptimize(q);\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_push_pop, Deque<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, List<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, FwdList<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, Chunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, ExpChunked<int64_t>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, Deque<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, List<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, FwdList<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, Chunked<Element>)->Apply(CustomArgs);\nBENCHMARK_TEMPLATE(BM_push_pop, ExpChunked<Element>)->Apply(CustomArgs);\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/chunked_queue_test.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/chunked_queue.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n#include <forward_list>\n#include <iterator>\n#include <list>\n#include <memory>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/strings/str_cat.h\"\n\nusing ::testing::ElementsAre;\nusing ::testing::Pair;\nusing ::testing::Pointee;\nusing ::testing::SizeIs;\n\n// Hide in a namespace to make sure swap is found via ADL.\nnamespace adl_namespace {\nnamespace {\nTEST(ChunkedQueueADLTest, Swap) {\n  absl::chunked_queue<int64_t> q1;\n  absl::chunked_queue<int64_t> q2;\n  q1.push_back(4);\n  q2.push_back(5);\n  q2.push_back(6);\n  swap(q1, q2);\n  EXPECT_THAT(q1, ElementsAre(5, 6));\n  EXPECT_THAT(q2, ElementsAre(4));\n}\n}  // namespace\n}  // namespace adl_namespace\n\nnamespace {\n\ntemplate <class T>\nusing ChunkedQueueBlock =\n    absl::container_internal::ChunkedQueueBlock<T, std::allocator<T>>;\n\nTEST(Internal, elements_in_bytes) {\n  EXPECT_EQ(size_t{1}, ChunkedQueueBlock<int>::block_size_from_bytes(0));\n  EXPECT_EQ(size_t{1}, ChunkedQueueBlock<int>::block_size_from_bytes(\n                           sizeof(ChunkedQueueBlock<int>)));\n  EXPECT_EQ(size_t{1},\n            ChunkedQueueBlock<int>::block_size_from_bytes(sizeof(int)));\n  EXPECT_EQ(size_t{2}, ChunkedQueueBlock<int>::block_size_from_bytes(\n                           sizeof(ChunkedQueueBlock<int>) + 2 * sizeof(int)));\n}\n\nTEST(Internal, BlockSizedDelete) {\n  struct Item {\n    int i;\n    char c;\n  };\n  std::allocator<Item> allocator;\n  auto* block = ChunkedQueueBlock<Item>::New(3, &allocator);\n  ChunkedQueueBlock<Item>::Delete(block, &allocator);\n}\n\ntemplate <size_t elem_size>\nvoid BlockSizeRounding() {\n  struct Elem {\n    char data[elem_size];\n  };\n  typedef ChunkedQueueBlock<Elem> Block;\n  for (size_t n = 1; n < 100; ++n) {\n    SCOPED_TRACE(n);\n    std::allocator<Elem> allocator;\n    Block* b = Block::New(n, &allocator);\n    EXPECT_GE(b->size(), n);\n    Block::Delete(b, &allocator);\n  }\n}\n\nTEST(Internal, BlockSizeRounding1) { BlockSizeRounding<1>(); }\nTEST(Internal, BlockSizeRounding17) { BlockSizeRounding<17>(); }\nTEST(Internal, BlockSizeRounding101) { BlockSizeRounding<101>(); }\nTEST(Internal, BlockSizeRounding528) { BlockSizeRounding<528>(); }\n\nTEST(ChunkedQueue, MinMaxBlockSize) {\n  absl::chunked_queue<int64_t, 1, 2> q = {1, 2, 3};\n  EXPECT_THAT(q, ElementsAre(1, 2, 3));\n}\n\nTEST(ChunkedQueue, Empty) {\n  absl::chunked_queue<int64_t> q;\n  EXPECT_TRUE(q.empty());\n  q.push_back(10);\n  EXPECT_FALSE(q.empty());\n  EXPECT_EQ(q.front(), 10);\n  EXPECT_EQ(q.back(), 10);\n  q.pop_front();\n  EXPECT_TRUE(q.empty());\n  q.clear();\n  EXPECT_TRUE(q.empty());\n}\n\nTEST(ChunkedQueue, CopyConstruct) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t> r(q);\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, CopyConstructMultipleChunks) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.push_back(1);\n  q.push_back(2);\n  q.push_back(3);\n  absl::chunked_queue<int64_t, 2> r(q);\n  EXPECT_THAT(r, ElementsAre(1, 2, 3));\n  EXPECT_EQ(3, r.size());\n}\n\nTEST(ChunkedQueue, BeginEndConstruct) {\n  std::vector<int64_t> src = {1, 2, 3, 4, 5};\n  absl::chunked_queue<int64_t, 2> q(src.begin(), src.end());\n  EXPECT_THAT(q, ElementsAre(1, 2, 3, 4, 5));\n  EXPECT_EQ(5, q.size());\n}\n\nTEST(ChunkedQueue, InitializerListConstruct) {\n  absl::chunked_queue<int64_t, 2> q = {1, 2, 3, 4, 5};\n  EXPECT_THAT(q, ElementsAre(1, 2, 3, 4, 5));\n  EXPECT_EQ(5, q.size());\n}\n\nTEST(ChunkedQueue, CountConstruct) {\n  absl::chunked_queue<int64_t> q(3);\n  EXPECT_THAT(q, ElementsAre(0, 0, 0));\n  EXPECT_EQ(3, q.size());\n}\n\nTEST(ChunkedQueue, CountValueConstruct) {\n  absl::chunked_queue<int64_t> q(3, 10);\n  EXPECT_THAT(q, ElementsAre(10, 10, 10));\n  EXPECT_EQ(3, q.size());\n}\n\nTEST(ChunkedQueue, InitializerListAssign) {\n  absl::chunked_queue<int64_t, 2> q;\n  q = {1, 2, 3, 4, 5};\n  EXPECT_THAT(q, ElementsAre(1, 2, 3, 4, 5));\n  EXPECT_EQ(5, q.size());\n}\n\nTEST(ChunkedQueue, CopyAssign) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t> r = q;\n  EXPECT_THAT(r, ElementsAre(1));\n}\n\nTEST(ChunkedQueue, CopyAssignSelf) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  q = *&q;  // Avoid -Wself-assign.\n  EXPECT_THAT(q, ElementsAre(1));\n  EXPECT_EQ(1, q.size());\n}\n\nTEST(ChunkedQueue, CopyAssignDestinationBigger) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t> r;\n  r.push_back(9);\n  r.push_back(9);\n  r.push_back(9);\n  r = q;\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, CopyAssignSourceBiggerMultipleChunks) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.push_back(1);\n  q.push_back(2);\n  q.push_back(3);\n  absl::chunked_queue<int64_t, 2> r;\n  r.push_back(9);\n  r = q;\n  EXPECT_THAT(r, ElementsAre(1, 2, 3));\n  EXPECT_EQ(3, r.size());\n}\n\nTEST(ChunkedQueue, CopyAssignDestinationBiggerMultipleChunks) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t, 2> r;\n  r.push_back(9);\n  r.push_back(9);\n  r.push_back(9);\n  r = q;\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, AssignCountValue) {\n  absl::chunked_queue<int64_t> q;\n  q.assign(3, 10);\n  EXPECT_THAT(q, ElementsAre(10, 10, 10));\n  EXPECT_EQ(3, q.size());\n\n  q.assign(2, 20);\n  EXPECT_THAT(q, ElementsAre(20, 20));\n  EXPECT_EQ(2, q.size());\n}\n\nTEST(ChunkedQueue, MoveConstruct) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t> r(std::move(q));\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, MoveAssign) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t> r;\n  r = std::move(q);\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, MoveAssignImmovable) {\n  struct Immovable {\n    Immovable() = default;\n\n    Immovable(const Immovable&) = delete;\n    Immovable& operator=(const Immovable&) = delete;\n    Immovable(Immovable&&) = delete;\n    Immovable& operator=(Immovable&&) = delete;\n  };\n  absl::chunked_queue<Immovable> q;\n  q.emplace_back();\n  absl::chunked_queue<Immovable> r;\n  r = std::move(q);\n  EXPECT_THAT(r, SizeIs(1));\n}\n\nTEST(ChunkedQueue, MoveAssignSelf) {\n  absl::chunked_queue<int64_t> q;\n  absl::chunked_queue<int64_t>& q2 = q;\n  q.push_back(1);\n  q = std::move(q2);\n  EXPECT_THAT(q, ElementsAre(1));\n  EXPECT_EQ(1, q.size());\n}\n\nTEST(ChunkedQueue, MoveAssignDestinationBigger) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t> r;\n  r.push_back(9);\n  r.push_back(9);\n  r.push_back(9);\n  r = std::move(q);\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, MoveAssignDestinationBiggerMultipleChunks) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.push_back(1);\n  absl::chunked_queue<int64_t, 2> r;\n  r.push_back(9);\n  r.push_back(9);\n  r.push_back(9);\n  r = std::move(q);\n  EXPECT_THAT(r, ElementsAre(1));\n  EXPECT_EQ(1, r.size());\n}\n\nTEST(ChunkedQueue, ConstFrontBack) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(10);\n  EXPECT_EQ(q.front(), 10);\n  EXPECT_EQ(q.back(), 10);\n  q.front() = 12;\n  EXPECT_EQ(q.front(), 12);\n  EXPECT_EQ(q.back(), 12);\n\n  const absl::chunked_queue<int64_t>& qref = q;\n  EXPECT_EQ(qref.front(), 12);\n  EXPECT_EQ(qref.back(), 12);\n\n  q.pop_front();\n\n  // Test at block bloundary and beyond\n  for (int i = 0; i < 64; ++i) q.push_back(i + 10);\n  EXPECT_EQ(q.front(), 10);\n  EXPECT_EQ(q.back(), 73);\n\n  for (int i = 64; i < 128; ++i) q.push_back(i + 10);\n  EXPECT_EQ(q.front(), 10);\n  EXPECT_EQ(q.back(), 137);\n  q.clear();\n  EXPECT_TRUE(q.empty());\n}\n\nTEST(ChunkedQueue, PushAndPop) {\n  absl::chunked_queue<int64_t> q;\n  EXPECT_TRUE(q.empty());\n  EXPECT_EQ(0, q.size());\n  for (int i = 0; i < 10000; i++) {\n    q.push_back(i);\n    EXPECT_EQ(q.front(), 0) << \": iteration \" << i;\n    EXPECT_FALSE(q.empty());\n    EXPECT_EQ(i + 1, q.size());\n  }\n  for (int i = 0; i < 10000; i++) {\n    EXPECT_FALSE(q.empty());\n    EXPECT_EQ(10000 - i, q.size());\n    EXPECT_EQ(q.front(), i);\n    q.pop_front();\n  }\n  EXPECT_TRUE(q.empty());\n  EXPECT_EQ(0, q.size());\n}\n\nTEST(ChunkedQueue, Swap) {\n  absl::chunked_queue<int64_t> q1;\n  absl::chunked_queue<int64_t> q2;\n  q1.push_back(4);\n  q2.push_back(5);\n  q2.push_back(6);\n  q2.swap(q1);\n  EXPECT_EQ(2, q1.size());\n  EXPECT_EQ(5, q1.front());\n  EXPECT_EQ(1, q2.size());\n  EXPECT_EQ(4, q2.front());\n  q1.pop_front();\n  q1.swap(q2);\n  EXPECT_EQ(1, q1.size());\n  EXPECT_EQ(4, q1.front());\n  EXPECT_EQ(1, q2.size());\n  EXPECT_EQ(6, q2.front());\n  q1.pop_front();\n  q1.swap(q2);\n  EXPECT_EQ(1, q1.size());\n  EXPECT_EQ(6, q1.front());\n  EXPECT_EQ(0, q2.size());\n  q1.clear();\n  EXPECT_TRUE(q1.empty());\n}\n\nTEST(ChunkedQueue, ShrinkToFit) {\n  absl::chunked_queue<int64_t> q;\n  q.shrink_to_fit();  // Should work on empty\n  EXPECT_TRUE(q.empty());\n\n  q.push_back(1);\n  q.shrink_to_fit();  // Should work on non-empty\n  EXPECT_THAT(q, ElementsAre(1));\n\n  q.clear();\n  // We know clear leaves a block and shrink_to_fit should remove it.\n  // Hard to test internal memory state without mocks or inspection.\n  // But at least we verify it doesn't crash or corrupt.\n  q.shrink_to_fit();\n  EXPECT_TRUE(q.empty());\n}\n\nTEST(ChunkedQueue, ResizeExtends) {\n  absl::chunked_queue<int64_t> q;\n  q.resize(2);\n  EXPECT_THAT(q, ElementsAre(0, 0));\n  EXPECT_EQ(2, q.size());\n}\n\nTEST(ChunkedQueue, ResizeShrinks) {\n  absl::chunked_queue<int64_t> q;\n  q.push_back(1);\n  q.push_back(2);\n  q.resize(1);\n  EXPECT_THAT(q, ElementsAre(1));\n  EXPECT_EQ(1, q.size());\n}\n\nTEST(ChunkedQueue, ResizeExtendsMultipleBlocks) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.resize(3);\n  EXPECT_THAT(q, ElementsAre(0, 0, 0));\n  EXPECT_EQ(3, q.size());\n}\n\nTEST(ChunkedQueue, ResizeShrinksMultipleBlocks) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.push_back(1);\n  q.push_back(2);\n  q.push_back(3);\n  q.resize(1);\n  EXPECT_THAT(q, ElementsAre(1));\n  EXPECT_EQ(1, q.size());\n}\n\nTEST(ChunkedQueue, ResizeValue) {\n  absl::chunked_queue<int64_t> q;\n  q.resize(3, 10);\n  EXPECT_THAT(q, ElementsAre(10, 10, 10));\n  EXPECT_EQ(3, q.size());\n\n  q.resize(5, 20);\n  EXPECT_THAT(q, ElementsAre(10, 10, 10, 20, 20));\n  EXPECT_EQ(5, q.size());\n\n  q.resize(2, 30);\n  EXPECT_THAT(q, ElementsAre(10, 10));\n  EXPECT_EQ(2, q.size());\n}\n\nTEST(ChunkedQueue, MaxSize) {\n  absl::chunked_queue<int64_t> q;\n  EXPECT_GE(q.max_size(),\n            size_t{1} << (sizeof(size_t) * 8 - sizeof(int64_t) - 4));\n}\n\nTEST(ChunkedQueue, AssignExtends) {\n  absl::chunked_queue<int64_t, 2> q;\n  std::vector<int64_t> v = {1, 2, 3, 4, 5};\n  q.assign(v.begin(), v.end());\n  EXPECT_THAT(q, ElementsAre(1, 2, 3, 4, 5));\n  EXPECT_EQ(5, q.size());\n}\n\nTEST(ChunkedQueue, AssignShrinks) {\n  absl::chunked_queue<int64_t, 2> q = {1, 2, 3, 4, 5};\n  std::vector<int64_t> v = {1};\n  q.assign(v.begin(), v.end());\n  EXPECT_THAT(q, ElementsAre(1));\n  EXPECT_EQ(1, q.size());\n}\n\nTEST(ChunkedQueue, AssignBoundaryCondition) {\n  // Create a queue with fixed block size of 4.\n  // 3 blocks: [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]\n  absl::chunked_queue<int, 4> q = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};\n\n  // Assign a range that fills exactly the first block (4 elements).\n  // This triggers the boundary condition where the assignment loop ends\n  // exactly at the limit of the first block.\n  std::vector<int> v = {101, 102, 103, 104};\n  q.assign(v.begin(), v.end());\n\n  EXPECT_EQ(q.size(), 4);\n  EXPECT_EQ(q.front(), 101);\n  // Verify back() is valid. If tail_ was incorrectly pointing to the start\n  // of the (now deleted) second block, this might access invalid memory\n  // or fail assertions.\n  EXPECT_EQ(q.back(), 104);\n\n  // Verify we can continue to push elements correctly.\n  q.push_back(105);\n  EXPECT_EQ(q.size(), 5);\n  EXPECT_EQ(q.back(), 105);\n}\n\nTEST(ChunkedQueue, Iterator) {\n  absl::chunked_queue<int64_t> q;\n  EXPECT_TRUE(q.begin() == q.end());\n\n  q.push_back(1);\n  absl::chunked_queue<int64_t>::const_iterator iter = q.begin();\n  ASSERT_FALSE(iter == q.end());\n  ASSERT_EQ(*iter, 1);\n  ++iter;\n  ASSERT_TRUE(iter == q.end());\n\n  q.push_back(2);\n  iter = q.begin();\n  ASSERT_EQ(*iter, 1);\n  ++iter;\n  absl::chunked_queue<int64_t>::const_iterator copy_iter = iter;\n  ASSERT_FALSE(copy_iter == q.end());\n  ASSERT_EQ(*copy_iter, 2);\n  ++copy_iter;\n  ASSERT_TRUE(copy_iter == q.end());\n\n  copy_iter = iter;\n  ASSERT_FALSE(iter == q.end());\n  ASSERT_EQ(*iter, 2);\n  ++iter;\n  ASSERT_TRUE(iter == q.end());\n\n  ASSERT_FALSE(copy_iter == q.end());\n  ASSERT_EQ(*copy_iter, 2);\n  ++copy_iter;\n  ASSERT_TRUE(copy_iter == q.end());\n}\n\nTEST(ChunkedQueue, IteratorDefaultConstructor) {\n  using ConstIter = absl::chunked_queue<int64_t>::const_iterator;\n  using Iter = absl::chunked_queue<int64_t>::iterator;\n  ConstIter const_iter;\n  EXPECT_TRUE(const_iter == ConstIter());\n  Iter iter;\n  EXPECT_TRUE(iter == Iter());\n}\n\nTEST(ChunkedQueue, IteratorConversion) {\n  using ConstIter = absl::chunked_queue<int64_t>::const_iterator;\n  using Iter = absl::chunked_queue<int64_t>::iterator;\n  EXPECT_FALSE((std::is_convertible<ConstIter, Iter>::value));\n  EXPECT_TRUE((std::is_convertible<Iter, ConstIter>::value));\n  absl::chunked_queue<int64_t> q;\n  ConstIter it1 = q.begin();\n  ConstIter it2 = q.cbegin();\n  Iter it3 = q.begin();\n  it1 = q.end();\n  it2 = q.cend();\n  it3 = q.end();\n  EXPECT_FALSE((std::is_assignable<Iter, ConstIter>::value));\n}\n\nstruct TestEntry {\n  int x, y;\n};\n\nTEST(ChunkedQueue, Iterator2) {\n  absl::chunked_queue<TestEntry> q;\n  TestEntry e;\n  e.x = 1;\n  e.y = 2;\n  q.push_back(e);\n  e.x = 3;\n  e.y = 4;\n  q.push_back(e);\n\n  absl::chunked_queue<TestEntry>::const_iterator iter = q.begin();\n  EXPECT_EQ(iter->x, 1);\n  EXPECT_EQ(iter->y, 2);\n  ++iter;\n  EXPECT_EQ(iter->x, 3);\n  EXPECT_EQ(iter->y, 4);\n  ++iter;\n  EXPECT_TRUE(iter == q.end());\n}\n\nTEST(ChunkedQueue, Iterator_MultipleBlocks) {\n  absl::chunked_queue<int64_t> q;\n  for (int i = 0; i < 130; ++i) {\n    absl::chunked_queue<int64_t>::const_iterator iter = q.begin();\n    for (int j = 0; j < i; ++j) {\n      ASSERT_FALSE(iter == q.end());\n      EXPECT_EQ(*iter, j);\n      ++iter;\n    }\n    ASSERT_TRUE(iter == q.end());\n    q.push_back(i);\n  }\n\n  for (int i = 0; i < 130; ++i) {\n    absl::chunked_queue<int64_t>::const_iterator iter = q.begin();\n    for (int j = i; j < 130; ++j) {\n      ASSERT_FALSE(iter == q.end());\n      EXPECT_EQ(*iter, j);\n      ++iter;\n    }\n    q.pop_front();\n  }\n  EXPECT_TRUE(q.empty());\n  EXPECT_TRUE(q.begin() == q.end());\n}\n\nTEST(ChunkedQueue, Iterator_PopFrontInvalidate) {\n  absl::chunked_queue<int64_t> q;\n  for (int i = 0; i < 130; ++i) {\n    q.push_back(i);\n  }\n\n  auto iter = q.begin();\n  for (int i = 0; i < 130; ++i) {\n    auto prev = iter++;\n    ASSERT_FALSE(prev == q.end());\n    EXPECT_EQ(*prev, i);\n    q.pop_front();\n  }\n  ASSERT_TRUE(q.empty());\n}\n\nTEST(ChunkedQueue, Iterator_PushBackInvalidate) {\n  absl::chunked_queue<int64_t, 2> q;\n  q.push_back(0);\n  auto i = q.begin();\n  EXPECT_EQ(*i, 0);\n  q.push_back(1);\n  EXPECT_EQ(*++i, 1);\n  q.push_back(2);\n  EXPECT_EQ(*++i, 2);\n}\n\nstruct MyType {\n  static int constructor_calls;\n  static int destructor_calls;\n\n  explicit MyType(int x) : val(x) { constructor_calls++; }\n  MyType(const MyType& t) : val(t.val) { constructor_calls++; }\n  ~MyType() { destructor_calls++; }\n\n  int val;\n};\n\nint MyType::constructor_calls = 0;\nint MyType::destructor_calls = 0;\n\nTEST(ChunkedQueue, ConstructorDestructorCalls) {\n  for (int i = 0; i < 100; i++) {\n    std::vector<MyType> vals;\n    for (int j = 0; j < i; j++) {\n      vals.push_back(MyType(j));\n    }\n    MyType::constructor_calls = 0;\n    MyType::destructor_calls = 0;\n    {\n      absl::chunked_queue<MyType> q;\n      for (int j = 0; j < i; j++) {\n        q.push_back(vals[j]);\n      }\n      if (i % 10 == 0) {\n        q.clear();\n      } else {\n        for (int j = 0; j < i; j++) {\n          EXPECT_EQ(q.front().val, j);\n          q.pop_front();\n        }\n      }\n    }\n    EXPECT_EQ(MyType::constructor_calls, i);\n    EXPECT_EQ(MyType::destructor_calls, i);\n  }\n}\n\nTEST(ChunkedQueue, MoveObjects) {\n  absl::chunked_queue<std::unique_ptr<int>> q;\n  q.push_back(std::make_unique<int>(10));\n  q.push_back(std::make_unique<int>(11));\n\n  EXPECT_EQ(10, *q.front());\n  q.pop_front();\n  EXPECT_EQ(11, *q.front());\n  q.pop_front();\n}\n\nTEST(ChunkedQueue, EmplaceBack1) {\n  absl::chunked_queue<std::pair<int, int>> q;\n  auto& v = q.emplace_back(1, 2);\n  EXPECT_THAT(v, Pair(1, 2));\n  EXPECT_THAT(q.front(), Pair(1, 2));\n  EXPECT_EQ(&v, &q.back());\n}\n\nTEST(ChunkedQueue, EmplaceBack2) {\n  absl::chunked_queue<std::pair<std::unique_ptr<int>, std::string>> q;\n  auto& v = q.emplace_back(std::make_unique<int>(11), \"val12\");\n  EXPECT_THAT(v, Pair(Pointee(11), \"val12\"));\n  EXPECT_THAT(q.front(), Pair(Pointee(11), \"val12\"));\n}\n\nTEST(ChunkedQueue, OveralignmentEmplaceBack) {\n  struct alignas(64) Overaligned {\n    int x;\n    int y;\n  };\n  absl::chunked_queue<Overaligned, 1, 8> q;\n  for (int i = 0; i < 10; ++i) {\n    auto& v = q.emplace_back(Overaligned{i, i});\n    EXPECT_EQ(reinterpret_cast<uintptr_t>(&v) % 64, 0);\n  }\n}\n\nTEST(ChunkedQueue, StatelessAllocatorDoesntAffectObjectSizes) {\n  // When a stateless allocator type is used -- such as when no explicit\n  // allocator type is given, and the stateless default is used -- it does not\n  // increase the object sizes from what they used to be before allocator\n  // support was added.  (In practice this verifies that allocator support makes\n  // use of the empty base-class optimization.)\n  //\n  // These \"Mock*\" structs model the data members of absl::chunked_queue<> and\n  // its internal ChunkedQueueBlock<> type, without any extra storage for\n  // allocator state.  (We use these to generate expected stateless-allocator\n  // object sizes in a portable way.)\n  struct MockQueue {\n    struct MockIterator {\n      void* block;\n      void* ptr;\n      void* limit;\n    };\n    MockIterator head;\n    MockIterator tail;\n    size_t size;\n  };\n  struct MockBlock {\n    void* next;\n    void* limit;\n  };\n  using TestQueueType = absl::chunked_queue<int64_t, 1, 16>;\n  EXPECT_EQ(sizeof(TestQueueType), sizeof(MockQueue));\n  EXPECT_EQ(sizeof(absl::container_internal::ChunkedQueueBlock<\n                   TestQueueType::value_type, TestQueueType::allocator_type>),\n            sizeof(MockBlock));\n}\n\nTEST(ChunkedQueue, DoesNotRoundBlockSizesUpWithNonDefaultAllocator) {\n  using OneByte = uint8_t;\n  using CustomAllocator = absl::container_internal::CountingAllocator<OneByte>;\n  using Block =\n      absl::container_internal::ChunkedQueueBlock<OneByte, CustomAllocator>;\n  int64_t allocator_live_bytes = 0;\n  CustomAllocator allocator(&allocator_live_bytes);\n  // Create a Block big enough to accomodate at least 1 OneByte.\n  Block* b = Block::New(1, &allocator);\n  ASSERT_TRUE(b != nullptr);\n  // With a non-default allocator in play, the resulting block should have\n  // capacity for exactly 1 element -- the implementation should not round the\n  // allocation size up, which may be inappropriate for non-default allocators.\n  //\n  // (Note that we don't always round up even with the default allocator in use,\n  // e.g. when compiling for ASAN analysis.)\n  EXPECT_EQ(b->size(), 1);\n  Block::Delete(b, &allocator);\n}\n\nTEST(ChunkedQueue, Hardening) {\n  bool hardened = false;\n  ABSL_HARDENING_ASSERT([&hardened]() {\n    hardened = true;\n    return true;\n  }());\n  if (!hardened) {\n    GTEST_SKIP() << \"Not a hardened build\";\n  }\n\n  absl::chunked_queue<int> q;\n  EXPECT_DEATH_IF_SUPPORTED(q.front(), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(q.back(), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(q.pop_front(), \"\");\n\n  const absl::chunked_queue<int> cq;\n  EXPECT_DEATH_IF_SUPPORTED(cq.front(), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(cq.back(), \"\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/fixed_array.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: fixed_array.h\n// -----------------------------------------------------------------------------\n//\n// A `FixedArray<T>` represents a non-resizable array of `T` where the length of\n// the array can be determined at run-time. It is a good replacement for\n// non-standard and deprecated uses of `alloca()` and variable length arrays\n// within the GCC extension. (See\n// https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).\n//\n// `FixedArray` allocates small arrays inline, keeping performance fast by\n// avoiding heap operations. It also helps reduce the chances of\n// accidentally overflowing your stack if large input is passed to\n// your function.\n\n#ifndef ABSL_CONTAINER_FIXED_ARRAY_H_\n#define ABSL_CONTAINER_FIXED_ARRAY_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <iterator>\n#include <limits>\n#include <memory>\n#include <new>\n#include <type_traits>\n\n#include \"absl/algorithm/algorithm.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/iterator_traits.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/container/internal/compressed_tuple.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/memory/memory.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nconstexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);\n\n// -----------------------------------------------------------------------------\n// FixedArray\n// -----------------------------------------------------------------------------\n//\n// A `FixedArray` provides a run-time fixed-size array, allocating a small array\n// inline for efficiency.\n//\n// Most users should not specify the `N` template parameter and let `FixedArray`\n// automatically determine the number of elements to store inline based on\n// `sizeof(T)`. If `N` is specified, the `FixedArray` implementation will use\n// inline storage for arrays with a length <= `N`.\n//\n// Note that a `FixedArray` constructed with a `size_type` argument will\n// default-initialize its values by leaving trivially constructible types\n// uninitialized (e.g. int, int[4], double), and others default-constructed.\n// This matches the behavior of c-style arrays and `std::array`, but not\n// `std::vector`.\ntemplate <typename T, size_t N = kFixedArrayUseDefault,\n          typename A = std::allocator<T>>\nclass ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {\n  static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,\n                \"Arrays with unknown bounds cannot be used with FixedArray.\");\n\n  static constexpr size_t kInlineBytesDefault = 256;\n\n  using AllocatorTraits = std::allocator_traits<A>;\n  template <typename Iterator>\n  using EnableIfInputIterator =\n      std::enable_if_t<base_internal::IsAtLeastInputIterator<Iterator>::value>;\n  static constexpr bool NoexceptCopyable() {\n    return std::is_nothrow_copy_constructible<StorageElement>::value &&\n           absl::allocator_is_nothrow<allocator_type>::value;\n  }\n  static constexpr bool NoexceptMovable() {\n    return std::is_nothrow_move_constructible<StorageElement>::value &&\n           absl::allocator_is_nothrow<allocator_type>::value;\n  }\n  static constexpr bool DefaultConstructorIsNonTrivial() {\n    return !absl::is_trivially_default_constructible<StorageElement>::value;\n  }\n\n public:\n  using allocator_type = typename AllocatorTraits::allocator_type;\n  using value_type = typename AllocatorTraits::value_type;\n  using pointer = typename AllocatorTraits::pointer;\n  using const_pointer = typename AllocatorTraits::const_pointer;\n  using reference = value_type&;\n  using const_reference = const value_type&;\n  using size_type = typename AllocatorTraits::size_type;\n  using difference_type = typename AllocatorTraits::difference_type;\n  using iterator = pointer;\n  using const_iterator = const_pointer;\n  using reverse_iterator = std::reverse_iterator<iterator>;\n  using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n\n  static constexpr size_type inline_elements =\n      (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)\n                                  : static_cast<size_type>(N));\n\n  FixedArray(const FixedArray& other) noexcept(NoexceptCopyable())\n      : FixedArray(other,\n                   AllocatorTraits::select_on_container_copy_construction(\n                       other.storage_.alloc())) {}\n\n  FixedArray(const FixedArray& other,\n             const allocator_type& a) noexcept(NoexceptCopyable())\n      : FixedArray(other.begin(), other.end(), a) {}\n\n  FixedArray(FixedArray&& other) noexcept(NoexceptMovable())\n      : FixedArray(std::move(other), other.storage_.alloc()) {}\n\n  FixedArray(FixedArray&& other,\n             const allocator_type& a) noexcept(NoexceptMovable())\n      : FixedArray(std::make_move_iterator(other.begin()),\n                   std::make_move_iterator(other.end()), a) {}\n\n  // Creates an array object that can store `n` elements.\n  // Note that trivially constructible elements will be uninitialized.\n  explicit FixedArray(size_type n, const allocator_type& a = allocator_type())\n      : storage_(n, a) {\n    if (DefaultConstructorIsNonTrivial()) {\n      memory_internal::ConstructRange(storage_.alloc(), storage_.begin(),\n                                      storage_.end());\n    }\n  }\n\n  // Creates an array initialized with `n` copies of `val`.\n  FixedArray(size_type n, const value_type& val,\n             const allocator_type& a = allocator_type())\n      : storage_(n, a) {\n    memory_internal::ConstructRange(storage_.alloc(), storage_.begin(),\n                                    storage_.end(), val);\n  }\n\n  // Creates an array initialized with the size and contents of `init_list`.\n  FixedArray(std::initializer_list<value_type> init_list,\n             const allocator_type& a = allocator_type())\n      : FixedArray(init_list.begin(), init_list.end(), a) {}\n\n  // Creates an array initialized with the elements from the input\n  // range. The array's size will always be `std::distance(first, last)`.\n  // REQUIRES: Iterator must be a input_iterator or better.\n  template <typename Iterator, EnableIfInputIterator<Iterator>* = nullptr>\n  FixedArray(Iterator first, Iterator last,\n             const allocator_type& a = allocator_type())\n      : storage_(std::distance(first, last), a) {\n    memory_internal::CopyRange(storage_.alloc(), storage_.begin(), first, last);\n  }\n\n  ~FixedArray() noexcept {\n    for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {\n      AllocatorTraits::destroy(storage_.alloc(), cur);\n    }\n  }\n\n  // Assignments are deleted because they break the invariant that the size of a\n  // `FixedArray` never changes.\n  void operator=(FixedArray&&) = delete;\n  void operator=(const FixedArray&) = delete;\n\n  // FixedArray::size()\n  //\n  // Returns the length of the fixed array.\n  size_type size() const { return storage_.size(); }\n\n  // FixedArray::max_size()\n  //\n  // Returns the largest possible value of `std::distance(begin(), end())` for a\n  // `FixedArray<T>`. This is equivalent to the most possible addressable bytes\n  // over the number of bytes taken by T.\n  constexpr size_type max_size() const {\n    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);\n  }\n\n  // FixedArray::empty()\n  //\n  // Returns whether or not the fixed array is empty.\n  bool empty() const { return size() == 0; }\n\n  // FixedArray::memsize()\n  //\n  // Returns the memory size of the fixed array in bytes.\n  size_t memsize() const { return size() * sizeof(value_type); }\n\n  // FixedArray::data()\n  //\n  // Returns a const T* pointer to elements of the `FixedArray`. This pointer\n  // can be used to access (but not modify) the contained elements.\n  const_pointer data() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return AsValueType(storage_.begin());\n  }\n\n  // Overload of FixedArray::data() to return a T* pointer to elements of the\n  // fixed array. This pointer can be used to access and modify the contained\n  // elements.\n  pointer data() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return AsValueType(storage_.begin());\n  }\n\n  // FixedArray::operator[]\n  //\n  // Returns a reference the ith element of the fixed array.\n  // REQUIRES: 0 <= i < size()\n  reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(i < size());\n    return data()[i];\n  }\n\n  // Overload of FixedArray::operator()[] to return a const reference to the\n  // ith element of the fixed array.\n  // REQUIRES: 0 <= i < size()\n  const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(i < size());\n    return data()[i];\n  }\n\n  // FixedArray::at\n  //\n  // Bounds-checked access.  Returns a reference to the ith element of the fixed\n  // array, or throws std::out_of_range\n  reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ABSL_PREDICT_FALSE(i >= size())) {\n      ThrowStdOutOfRange(\"FixedArray::at failed bounds check\");\n    }\n    return data()[i];\n  }\n\n  // Overload of FixedArray::at() to return a const reference to the ith element\n  // of the fixed array.\n  const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ABSL_PREDICT_FALSE(i >= size())) {\n      ThrowStdOutOfRange(\"FixedArray::at failed bounds check\");\n    }\n    return data()[i];\n  }\n\n  // FixedArray::front()\n  //\n  // Returns a reference to the first element of the fixed array.\n  reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[0];\n  }\n\n  // Overload of FixedArray::front() to return a reference to the first element\n  // of a fixed array of const values.\n  const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[0];\n  }\n\n  // FixedArray::back()\n  //\n  // Returns a reference to the last element of the fixed array.\n  reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[size() - 1];\n  }\n\n  // Overload of FixedArray::back() to return a reference to the last element\n  // of a fixed array of const values.\n  const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[size() - 1];\n  }\n\n  // FixedArray::begin()\n  //\n  // Returns an iterator to the beginning of the fixed array.\n  iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }\n\n  // Overload of FixedArray::begin() to return a const iterator to the\n  // beginning of the fixed array.\n  const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }\n\n  // FixedArray::cbegin()\n  //\n  // Returns a const iterator to the beginning of the fixed array.\n  const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return begin();\n  }\n\n  // FixedArray::end()\n  //\n  // Returns an iterator to the end of the fixed array.\n  iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data() + size(); }\n\n  // Overload of FixedArray::end() to return a const iterator to the end of the\n  // fixed array.\n  const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return data() + size();\n  }\n\n  // FixedArray::cend()\n  //\n  // Returns a const iterator to the end of the fixed array.\n  const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }\n\n  // FixedArray::rbegin()\n  //\n  // Returns a reverse iterator from the end of the fixed array.\n  reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return reverse_iterator(end());\n  }\n\n  // Overload of FixedArray::rbegin() to return a const reverse iterator from\n  // the end of the fixed array.\n  const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_reverse_iterator(end());\n  }\n\n  // FixedArray::crbegin()\n  //\n  // Returns a const reverse iterator from the end of the fixed array.\n  const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return rbegin();\n  }\n\n  // FixedArray::rend()\n  //\n  // Returns a reverse iterator from the beginning of the fixed array.\n  reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return reverse_iterator(begin());\n  }\n\n  // Overload of FixedArray::rend() for returning a const reverse iterator\n  // from the beginning of the fixed array.\n  const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_reverse_iterator(begin());\n  }\n\n  // FixedArray::crend()\n  //\n  // Returns a reverse iterator from the beginning of the fixed array.\n  const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return rend();\n  }\n\n  // FixedArray::fill()\n  //\n  // Assigns the given `value` to all elements in the fixed array.\n  void fill(const value_type& val) { std::fill(begin(), end(), val); }\n\n  // Relational operators. Equality operators are elementwise using\n  // `operator==`, while order operators order FixedArrays lexicographically.\n  friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {\n    return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());\n  }\n\n  friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {\n    return !(lhs == rhs);\n  }\n\n  friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {\n    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),\n                                        rhs.end());\n  }\n\n  friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {\n    return rhs < lhs;\n  }\n\n  friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {\n    return !(rhs < lhs);\n  }\n\n  friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {\n    return !(lhs < rhs);\n  }\n\n  template <typename H>\n  friend H AbslHashValue(H h, const FixedArray& v) {\n    return H::combine_contiguous(std::move(h), v.data(), v.size());\n  }\n\n private:\n  // StorageElement\n  //\n  // For FixedArrays with a C-style-array value_type, StorageElement is a POD\n  // wrapper struct called StorageElementWrapper that holds the value_type\n  // instance inside. This is needed for construction and destruction of the\n  // entire array regardless of how many dimensions it has. For all other cases,\n  // StorageElement is just an alias of value_type.\n  //\n  // Maintainer's Note: The simpler solution would be to simply wrap value_type\n  // in a struct whether it's an array or not. That causes some paranoid\n  // diagnostics to misfire, believing that 'data()' returns a pointer to a\n  // single element, rather than the packed array that it really is.\n  // e.g.:\n  //\n  //     FixedArray<char> buf(1);\n  //     sprintf(buf.data(), \"foo\");\n  //\n  //     error: call to int __builtin___sprintf_chk(etc...)\n  //     will always overflow destination buffer [-Werror]\n  //\n  template <typename OuterT, typename InnerT = absl::remove_extent_t<OuterT>,\n            size_t InnerN = std::extent<OuterT>::value>\n  struct StorageElementWrapper {\n    InnerT array[InnerN];\n  };\n\n  using StorageElement =\n      absl::conditional_t<std::is_array<value_type>::value,\n                          StorageElementWrapper<value_type>, value_type>;\n\n  static pointer AsValueType(pointer ptr) { return ptr; }\n  static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {\n    return std::addressof(ptr->array);\n  }\n\n  static_assert(sizeof(StorageElement) == sizeof(value_type), \"\");\n  static_assert(alignof(StorageElement) == alignof(value_type), \"\");\n\n  class NonEmptyInlinedStorage {\n   public:\n    StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }\n    void AnnotateConstruct(size_type n);\n    void AnnotateDestruct(size_type n);\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n    void* RedzoneBegin() { return &redzone_begin_; }\n    void* RedzoneEnd() { return &redzone_end_ + 1; }\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n\n   private:\n    ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);\n    alignas(StorageElement) unsigned char buff_[sizeof(\n        StorageElement[inline_elements])];\n    ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);\n  };\n\n  class EmptyInlinedStorage {\n   public:\n    StorageElement* data() { return nullptr; }\n    void AnnotateConstruct(size_type) {}\n    void AnnotateDestruct(size_type) {}\n  };\n\n  using InlinedStorage =\n      absl::conditional_t<inline_elements == 0, EmptyInlinedStorage,\n                          NonEmptyInlinedStorage>;\n\n  // Storage\n  //\n  // An instance of Storage manages the inline and out-of-line memory for\n  // instances of FixedArray. This guarantees that even when construction of\n  // individual elements fails in the FixedArray constructor body, the\n  // destructor for Storage will still be called and out-of-line memory will be\n  // properly deallocated.\n  //\n  class Storage : public InlinedStorage {\n   public:\n    Storage(size_type n, const allocator_type& a)\n        : size_alloc_(n, a), data_(InitializeData()) {}\n\n    ~Storage() noexcept {\n      if (UsingInlinedStorage(size())) {\n        InlinedStorage::AnnotateDestruct(size());\n      } else {\n        AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());\n      }\n    }\n\n    size_type size() const { return size_alloc_.template get<0>(); }\n    StorageElement* begin() const { return data_; }\n    StorageElement* end() const { return begin() + size(); }\n    allocator_type& alloc() { return size_alloc_.template get<1>(); }\n    const allocator_type& alloc() const {\n      return size_alloc_.template get<1>();\n    }\n\n   private:\n    static bool UsingInlinedStorage(size_type n) {\n      return n <= inline_elements;\n    }\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n    ABSL_ATTRIBUTE_NOINLINE\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n    StorageElement* InitializeData() {\n      if (UsingInlinedStorage(size())) {\n        InlinedStorage::AnnotateConstruct(size());\n        return InlinedStorage::data();\n      } else {\n        return reinterpret_cast<StorageElement*>(\n            AllocatorTraits::allocate(alloc(), size()));\n      }\n    }\n\n    // `CompressedTuple` takes advantage of EBCO for stateless `allocator_type`s\n    container_internal::CompressedTuple<size_type, allocator_type> size_alloc_;\n    StorageElement* data_;\n  };\n\n  Storage storage_;\n};\n\ntemplate <typename T, size_t N, typename A>\nvoid FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(\n    typename FixedArray<T, N, A>::size_type n) {\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  if (!n) return;\n  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(),\n                                     data() + n);\n  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(),\n                                     RedzoneBegin());\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n  static_cast<void>(n);  // Mark used when not in asan mode\n}\n\ntemplate <typename T, size_t N, typename A>\nvoid FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(\n    typename FixedArray<T, N, A>::size_type n) {\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  if (!n) return;\n  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n,\n                                     RedzoneEnd());\n  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(),\n                                     data());\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n  static_cast<void>(n);  // Mark used when not in asan mode\n}\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_FIXED_ARRAY_H_\n"
  },
  {
    "path": "absl/container/fixed_array_benchmark.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <stddef.h>\n\n#include <string>\n\n#include \"absl/container/fixed_array.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\n// For benchmarking -- simple class with constructor and destructor that\n// set an int to a constant..\nclass SimpleClass {\n public:\n  SimpleClass() : i(3) {}\n  ~SimpleClass() { i = 0; }\n\n private:\n  int i;\n};\n\ntemplate <typename C, size_t stack_size>\nvoid BM_FixedArray(benchmark::State& state) {\n  const int size = state.range(0);\n  for (auto _ : state) {\n    absl::FixedArray<C, stack_size> fa(size);\n    benchmark::DoNotOptimize(fa.data());\n  }\n}\nBENCHMARK_TEMPLATE(BM_FixedArray, char, absl::kFixedArrayUseDefault)\n    ->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, char, 0)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, char, 1)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, char, 16)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, char, 256)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, char, 65536)->Range(0, 1 << 16);\n\nBENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, absl::kFixedArrayUseDefault)\n    ->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 0)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 1)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 16)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 256)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, SimpleClass, 65536)->Range(0, 1 << 16);\n\nBENCHMARK_TEMPLATE(BM_FixedArray, std::string, absl::kFixedArrayUseDefault)\n    ->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, std::string, 0)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, std::string, 1)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, std::string, 16)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, std::string, 256)->Range(0, 1 << 16);\nBENCHMARK_TEMPLATE(BM_FixedArray, std::string, 65536)->Range(0, 1 << 16);\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/fixed_array_exception_safety_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/config.h\"\n#include \"absl/container/fixed_array.h\"\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n\n#include <initializer_list>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/exception_safety_testing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\nconstexpr size_t kInlined = 25;\nconstexpr size_t kSmallSize = kInlined / 2;\nconstexpr size_t kLargeSize = kInlined * 2;\n\nconstexpr int kInitialValue = 5;\nconstexpr int kUpdatedValue = 10;\n\nusing ::testing::TestThrowingCtor;\n\nusing Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;\nusing ThrowAlloc =\n    testing::ThrowingAllocator<Thrower, testing::AllocSpec::kEverythingThrows>;\nusing MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;\nusing MoveThrowAlloc =\n    testing::ThrowingAllocator<MoveThrower,\n                               testing::AllocSpec::kEverythingThrows>;\n\nusing FixedArr = absl::FixedArray<Thrower, kInlined>;\nusing FixedArrWithAlloc = absl::FixedArray<Thrower, kInlined, ThrowAlloc>;\n\nusing MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>;\nusing MoveFixedArrWithAlloc =\n    absl::FixedArray<MoveThrower, kInlined, MoveThrowAlloc>;\n\nTEST(FixedArrayExceptionSafety, CopyConstructor) {\n  auto small = FixedArr(kSmallSize);\n  TestThrowingCtor<FixedArr>(small);\n\n  auto large = FixedArr(kLargeSize);\n  TestThrowingCtor<FixedArr>(large);\n}\n\nTEST(FixedArrayExceptionSafety, CopyConstructorWithAlloc) {\n  auto small = FixedArrWithAlloc(kSmallSize);\n  TestThrowingCtor<FixedArrWithAlloc>(small);\n\n  auto large = FixedArrWithAlloc(kLargeSize);\n  TestThrowingCtor<FixedArrWithAlloc>(large);\n}\n\nTEST(FixedArrayExceptionSafety, MoveConstructor) {\n  TestThrowingCtor<FixedArr>(FixedArr(kSmallSize));\n  TestThrowingCtor<FixedArr>(FixedArr(kLargeSize));\n\n  // TypeSpec::kNoThrowMove\n  TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kSmallSize));\n  TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize));\n}\n\nTEST(FixedArrayExceptionSafety, MoveConstructorWithAlloc) {\n  TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kSmallSize));\n  TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kLargeSize));\n\n  // TypeSpec::kNoThrowMove\n  TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kSmallSize));\n  TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kLargeSize));\n}\n\nTEST(FixedArrayExceptionSafety, SizeConstructor) {\n  TestThrowingCtor<FixedArr>(kSmallSize);\n  TestThrowingCtor<FixedArr>(kLargeSize);\n}\n\nTEST(FixedArrayExceptionSafety, SizeConstructorWithAlloc) {\n  TestThrowingCtor<FixedArrWithAlloc>(kSmallSize);\n  TestThrowingCtor<FixedArrWithAlloc>(kLargeSize);\n}\n\nTEST(FixedArrayExceptionSafety, SizeValueConstructor) {\n  TestThrowingCtor<FixedArr>(kSmallSize, Thrower());\n  TestThrowingCtor<FixedArr>(kLargeSize, Thrower());\n}\n\nTEST(FixedArrayExceptionSafety, SizeValueConstructorWithAlloc) {\n  TestThrowingCtor<FixedArrWithAlloc>(kSmallSize, Thrower());\n  TestThrowingCtor<FixedArrWithAlloc>(kLargeSize, Thrower());\n}\n\nTEST(FixedArrayExceptionSafety, IteratorConstructor) {\n  auto small = FixedArr(kSmallSize);\n  TestThrowingCtor<FixedArr>(small.begin(), small.end());\n\n  auto large = FixedArr(kLargeSize);\n  TestThrowingCtor<FixedArr>(large.begin(), large.end());\n}\n\nTEST(FixedArrayExceptionSafety, IteratorConstructorWithAlloc) {\n  auto small = FixedArrWithAlloc(kSmallSize);\n  TestThrowingCtor<FixedArrWithAlloc>(small.begin(), small.end());\n\n  auto large = FixedArrWithAlloc(kLargeSize);\n  TestThrowingCtor<FixedArrWithAlloc>(large.begin(), large.end());\n}\n\nTEST(FixedArrayExceptionSafety, InitListConstructor) {\n  constexpr int small_inlined = 3;\n  using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>;\n\n  TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{});\n  // Test inlined allocation\n  TestThrowingCtor<SmallFixedArr>(\n      std::initializer_list<Thrower>{Thrower{}, Thrower{}});\n  // Test out of line allocation\n  TestThrowingCtor<SmallFixedArr>(std::initializer_list<Thrower>{\n      Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});\n}\n\nTEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) {\n  constexpr int small_inlined = 3;\n  using SmallFixedArrWithAlloc =\n      absl::FixedArray<Thrower, small_inlined, ThrowAlloc>;\n\n  TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{});\n  // Test inlined allocation\n  TestThrowingCtor<SmallFixedArrWithAlloc>(\n      std::initializer_list<Thrower>{Thrower{}, Thrower{}});\n  // Test out of line allocation\n  TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{\n      Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});\n}\n\ntemplate <typename FixedArrT>\ntesting::AssertionResult ReadMemory(FixedArrT* fixed_arr) {\n  int sum = 0;\n  for (const auto& thrower : *fixed_arr) {\n    sum += thrower.Get();\n  }\n  return testing::AssertionSuccess() << \"Values sum to [\" << sum << \"]\";\n}\n\nTEST(FixedArrayExceptionSafety, Fill) {\n  auto test_fill = testing::MakeExceptionSafetyTester()\n                       .WithContracts(ReadMemory<FixedArr>)\n                       .WithOperation([&](FixedArr* fixed_arr_ptr) {\n                         auto thrower =\n                             Thrower(kUpdatedValue, testing::nothrow_ctor);\n                         fixed_arr_ptr->fill(thrower);\n                       });\n\n  EXPECT_TRUE(\n      test_fill.WithInitialValue(FixedArr(kSmallSize, Thrower(kInitialValue)))\n          .Test());\n  EXPECT_TRUE(\n      test_fill.WithInitialValue(FixedArr(kLargeSize, Thrower(kInitialValue)))\n          .Test());\n}\n\nTEST(FixedArrayExceptionSafety, FillWithAlloc) {\n  auto test_fill = testing::MakeExceptionSafetyTester()\n                       .WithContracts(ReadMemory<FixedArrWithAlloc>)\n                       .WithOperation([&](FixedArrWithAlloc* fixed_arr_ptr) {\n                         auto thrower =\n                             Thrower(kUpdatedValue, testing::nothrow_ctor);\n                         fixed_arr_ptr->fill(thrower);\n                       });\n\n  EXPECT_TRUE(test_fill\n                  .WithInitialValue(\n                      FixedArrWithAlloc(kSmallSize, Thrower(kInitialValue)))\n                  .Test());\n  EXPECT_TRUE(test_fill\n                  .WithInitialValue(\n                      FixedArrWithAlloc(kLargeSize, Thrower(kInitialValue)))\n                  .Test());\n}\n\n}  // namespace\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HAVE_EXCEPTIONS\n"
  },
  {
    "path": "absl/container/fixed_array_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/fixed_array.h\"\n\n#include <stdio.h>\n\n#include <cstring>\n#include <forward_list>\n#include <list>\n#include <memory>\n#include <numeric>\n#include <scoped_allocator>\n#include <stdexcept>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/exception_testing.h\"\n#include \"absl/base/internal/iterator_traits_test_helper.h\"\n#include \"absl/base/options.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/memory/memory.h\"\n\nusing ::testing::ElementsAreArray;\n\nnamespace {\n\n// Helper routine to determine if a absl::FixedArray used stack allocation.\ntemplate <typename ArrayType>\nstatic bool IsOnStack(const ArrayType& a) {\n  return a.size() <= ArrayType::inline_elements;\n}\n\nclass ConstructionTester {\n public:\n  ConstructionTester() : self_ptr_(this), value_(0) { constructions++; }\n  ~ConstructionTester() {\n    assert(self_ptr_ == this);\n    self_ptr_ = nullptr;\n    destructions++;\n  }\n\n  // These are incremented as elements are constructed and destructed so we can\n  // be sure all elements are properly cleaned up.\n  static int constructions;\n  static int destructions;\n\n  void CheckConstructed() { assert(self_ptr_ == this); }\n\n  void set(int value) { value_ = value; }\n  int get() { return value_; }\n\n private:\n  // self_ptr_ should always point to 'this' -- that's how we can be sure the\n  // constructor has been called.\n  ConstructionTester* self_ptr_;\n  int value_;\n};\n\nint ConstructionTester::constructions = 0;\nint ConstructionTester::destructions = 0;\n\n// ThreeInts will initialize its three ints to the value stored in\n// ThreeInts::counter. The constructor increments counter so that each object\n// in an array of ThreeInts will have different values.\nclass ThreeInts {\n public:\n  ThreeInts() {\n    x_ = counter;\n    y_ = counter;\n    z_ = counter;\n    ++counter;\n  }\n\n  static int counter;\n\n  int x_, y_, z_;\n};\n\nint ThreeInts::counter = 0;\n\nTEST(FixedArrayTest, CopyCtor) {\n  absl::FixedArray<int, 10> on_stack(5);\n  std::iota(on_stack.begin(), on_stack.end(), 0);\n  absl::FixedArray<int, 10> stack_copy = on_stack;\n  EXPECT_THAT(stack_copy, ElementsAreArray(on_stack));\n  EXPECT_TRUE(IsOnStack(stack_copy));\n\n  absl::FixedArray<int, 10> allocated(15);\n  std::iota(allocated.begin(), allocated.end(), 0);\n  absl::FixedArray<int, 10> alloced_copy = allocated;\n  EXPECT_THAT(alloced_copy, ElementsAreArray(allocated));\n  EXPECT_FALSE(IsOnStack(alloced_copy));\n}\n\nTEST(FixedArrayTest, MoveCtor) {\n  absl::FixedArray<std::unique_ptr<int>, 10> on_stack(5);\n  for (int i = 0; i < 5; ++i) {\n    on_stack[i] = absl::make_unique<int>(i);\n  }\n\n  absl::FixedArray<std::unique_ptr<int>, 10> stack_copy = std::move(on_stack);\n  for (int i = 0; i < 5; ++i) EXPECT_EQ(*(stack_copy[i]), i);\n  EXPECT_EQ(stack_copy.size(), on_stack.size());\n\n  absl::FixedArray<std::unique_ptr<int>, 10> allocated(15);\n  for (int i = 0; i < 15; ++i) {\n    allocated[i] = absl::make_unique<int>(i);\n  }\n\n  absl::FixedArray<std::unique_ptr<int>, 10> alloced_copy =\n      std::move(allocated);\n  for (int i = 0; i < 15; ++i) EXPECT_EQ(*(alloced_copy[i]), i);\n  EXPECT_EQ(allocated.size(), alloced_copy.size());\n}\n\nTEST(FixedArrayTest, SmallObjects) {\n  // Small object arrays\n  {\n    // Short arrays should be on the stack\n    absl::FixedArray<int> array(4);\n    EXPECT_TRUE(IsOnStack(array));\n  }\n\n  {\n    // Large arrays should be on the heap\n    absl::FixedArray<int> array(1048576);\n    EXPECT_FALSE(IsOnStack(array));\n  }\n\n  {\n    // Arrays of <= default size should be on the stack\n    absl::FixedArray<int, 100> array(100);\n    EXPECT_TRUE(IsOnStack(array));\n  }\n\n  {\n    // Arrays of > default size should be on the heap\n    absl::FixedArray<int, 100> array(101);\n    EXPECT_FALSE(IsOnStack(array));\n  }\n\n  {\n    // Arrays with different size elements should use approximately\n    // same amount of stack space\n    absl::FixedArray<int> array1(0);\n    absl::FixedArray<char> array2(0);\n    EXPECT_LE(sizeof(array1), sizeof(array2) + 100);\n    EXPECT_LE(sizeof(array2), sizeof(array1) + 100);\n  }\n\n  {\n    // Ensure that vectors are properly constructed inside a fixed array.\n    absl::FixedArray<std::vector<int>> array(2);\n    EXPECT_EQ(0, array[0].size());\n    EXPECT_EQ(0, array[1].size());\n  }\n\n  {\n    // Regardless of absl::FixedArray implementation, check that a type with a\n    // low alignment requirement and a non power-of-two size is initialized\n    // correctly.\n    ThreeInts::counter = 1;\n    absl::FixedArray<ThreeInts> array(2);\n    EXPECT_EQ(1, array[0].x_);\n    EXPECT_EQ(1, array[0].y_);\n    EXPECT_EQ(1, array[0].z_);\n    EXPECT_EQ(2, array[1].x_);\n    EXPECT_EQ(2, array[1].y_);\n    EXPECT_EQ(2, array[1].z_);\n  }\n}\n\nTEST(FixedArrayTest, AtThrows) {\n  absl::FixedArray<int> a = {1, 2, 3};\n  EXPECT_EQ(a.at(2), 3);\n  ABSL_BASE_INTERNAL_EXPECT_FAIL(a.at(3), std::out_of_range,\n                                 \"failed bounds check\");\n}\n\nTEST(FixedArrayTest, Hardened) {\n#if !defined(NDEBUG) || ABSL_OPTION_HARDENED\n  absl::FixedArray<int> a = {1, 2, 3};\n  EXPECT_EQ(a[2], 3);\n  EXPECT_DEATH_IF_SUPPORTED(a[3], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(a[-1], \"\");\n\n  absl::FixedArray<int> empty(0);\n  EXPECT_DEATH_IF_SUPPORTED(empty[0], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(empty[-1], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(empty.front(), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(empty.back(), \"\");\n#endif\n}\n\nTEST(FixedArrayRelationalsTest, EqualArrays) {\n  for (int i = 0; i < 10; ++i) {\n    absl::FixedArray<int, 5> a1(i);\n    std::iota(a1.begin(), a1.end(), 0);\n    absl::FixedArray<int, 5> a2(a1.begin(), a1.end());\n\n    EXPECT_TRUE(a1 == a2);\n    EXPECT_FALSE(a1 != a2);\n    EXPECT_TRUE(a2 == a1);\n    EXPECT_FALSE(a2 != a1);\n    EXPECT_FALSE(a1 < a2);\n    EXPECT_FALSE(a1 > a2);\n    EXPECT_FALSE(a2 < a1);\n    EXPECT_FALSE(a2 > a1);\n    EXPECT_TRUE(a1 <= a2);\n    EXPECT_TRUE(a1 >= a2);\n    EXPECT_TRUE(a2 <= a1);\n    EXPECT_TRUE(a2 >= a1);\n  }\n}\n\nTEST(FixedArrayRelationalsTest, UnequalArrays) {\n  for (int i = 1; i < 10; ++i) {\n    absl::FixedArray<int, 5> a1(i);\n    std::iota(a1.begin(), a1.end(), 0);\n    absl::FixedArray<int, 5> a2(a1.begin(), a1.end());\n    --a2[i / 2];\n\n    EXPECT_FALSE(a1 == a2);\n    EXPECT_TRUE(a1 != a2);\n    EXPECT_FALSE(a2 == a1);\n    EXPECT_TRUE(a2 != a1);\n    EXPECT_FALSE(a1 < a2);\n    EXPECT_TRUE(a1 > a2);\n    EXPECT_TRUE(a2 < a1);\n    EXPECT_FALSE(a2 > a1);\n    EXPECT_FALSE(a1 <= a2);\n    EXPECT_TRUE(a1 >= a2);\n    EXPECT_TRUE(a2 <= a1);\n    EXPECT_FALSE(a2 >= a1);\n  }\n}\n\ntemplate <int stack_elements>\nstatic void TestArray(int n) {\n  SCOPED_TRACE(n);\n  SCOPED_TRACE(stack_elements);\n  ConstructionTester::constructions = 0;\n  ConstructionTester::destructions = 0;\n  {\n    absl::FixedArray<ConstructionTester, stack_elements> array(n);\n\n    EXPECT_THAT(array.size(), n);\n    EXPECT_THAT(array.memsize(), sizeof(ConstructionTester) * n);\n    EXPECT_THAT(array.begin() + n, array.end());\n\n    // Check that all elements were constructed\n    for (int i = 0; i < n; i++) {\n      array[i].CheckConstructed();\n    }\n    // Check that no other elements were constructed\n    EXPECT_THAT(ConstructionTester::constructions, n);\n\n    // Test operator[]\n    for (int i = 0; i < n; i++) {\n      array[i].set(i);\n    }\n    for (int i = 0; i < n; i++) {\n      EXPECT_THAT(array[i].get(), i);\n      EXPECT_THAT(array.data()[i].get(), i);\n    }\n\n    // Test data()\n    for (int i = 0; i < n; i++) {\n      array.data()[i].set(i + 1);\n    }\n    for (int i = 0; i < n; i++) {\n      EXPECT_THAT(array[i].get(), i + 1);\n      EXPECT_THAT(array.data()[i].get(), i + 1);\n    }\n  }  // Close scope containing 'array'.\n\n  // Check that all constructed elements were destructed.\n  EXPECT_EQ(ConstructionTester::constructions,\n            ConstructionTester::destructions);\n}\n\ntemplate <int elements_per_inner_array, int inline_elements>\nstatic void TestArrayOfArrays(int n) {\n  SCOPED_TRACE(n);\n  SCOPED_TRACE(inline_elements);\n  SCOPED_TRACE(elements_per_inner_array);\n  ConstructionTester::constructions = 0;\n  ConstructionTester::destructions = 0;\n  {\n    using InnerArray = ConstructionTester[elements_per_inner_array];\n    // Heap-allocate the FixedArray to avoid blowing the stack frame.\n    auto array_ptr =\n        absl::make_unique<absl::FixedArray<InnerArray, inline_elements>>(n);\n    auto& array = *array_ptr;\n\n    ASSERT_EQ(array.size(), n);\n    ASSERT_EQ(array.memsize(),\n              sizeof(ConstructionTester) * elements_per_inner_array * n);\n    ASSERT_EQ(array.begin() + n, array.end());\n\n    // Check that all elements were constructed\n    for (int i = 0; i < n; i++) {\n      for (int j = 0; j < elements_per_inner_array; j++) {\n        (array[i])[j].CheckConstructed();\n      }\n    }\n    // Check that no other elements were constructed\n    ASSERT_EQ(ConstructionTester::constructions, n * elements_per_inner_array);\n\n    // Test operator[]\n    for (int i = 0; i < n; i++) {\n      for (int j = 0; j < elements_per_inner_array; j++) {\n        (array[i])[j].set(i * elements_per_inner_array + j);\n      }\n    }\n    for (int i = 0; i < n; i++) {\n      for (int j = 0; j < elements_per_inner_array; j++) {\n        ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j);\n        ASSERT_EQ((array.data()[i])[j].get(), i * elements_per_inner_array + j);\n      }\n    }\n\n    // Test data()\n    for (int i = 0; i < n; i++) {\n      for (int j = 0; j < elements_per_inner_array; j++) {\n        (array.data()[i])[j].set((i + 1) * elements_per_inner_array + j);\n      }\n    }\n    for (int i = 0; i < n; i++) {\n      for (int j = 0; j < elements_per_inner_array; j++) {\n        ASSERT_EQ((array[i])[j].get(), (i + 1) * elements_per_inner_array + j);\n        ASSERT_EQ((array.data()[i])[j].get(),\n                  (i + 1) * elements_per_inner_array + j);\n      }\n    }\n  }  // Close scope containing 'array'.\n\n  // Check that all constructed elements were destructed.\n  EXPECT_EQ(ConstructionTester::constructions,\n            ConstructionTester::destructions);\n}\n\nTEST(IteratorConstructorTest, NonInline) {\n  int const kInput[] = {2, 3, 5, 7, 11, 13, 17};\n  absl::FixedArray<int, ABSL_ARRAYSIZE(kInput) - 1> const fixed(\n      kInput, kInput + ABSL_ARRAYSIZE(kInput));\n  ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {\n    ASSERT_EQ(kInput[i], fixed[i]);\n  }\n}\n\nTEST(IteratorConstructorTest, Inline) {\n  int const kInput[] = {2, 3, 5, 7, 11, 13, 17};\n  absl::FixedArray<int, ABSL_ARRAYSIZE(kInput)> const fixed(\n      kInput, kInput + ABSL_ARRAYSIZE(kInput));\n  ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {\n    ASSERT_EQ(kInput[i], fixed[i]);\n  }\n}\n\nTEST(IteratorConstructorTest, NonPod) {\n  char const* kInput[] = {\"red\",  \"orange\", \"yellow\", \"green\",\n                          \"blue\", \"indigo\", \"violet\"};\n  absl::FixedArray<std::string> const fixed(kInput,\n                                            kInput + ABSL_ARRAYSIZE(kInput));\n  ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {\n    ASSERT_EQ(kInput[i], fixed[i]);\n  }\n}\n\nTEST(IteratorConstructorTest, FromEmptyVector) {\n  std::vector<int> const empty;\n  absl::FixedArray<int> const fixed(empty.begin(), empty.end());\n  EXPECT_EQ(0, fixed.size());\n  EXPECT_EQ(empty.size(), fixed.size());\n}\n\nTEST(IteratorConstructorTest, FromNonEmptyVector) {\n  int const kInput[] = {2, 3, 5, 7, 11, 13, 17};\n  std::vector<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));\n  absl::FixedArray<int> const fixed(items.begin(), items.end());\n  ASSERT_EQ(items.size(), fixed.size());\n  for (size_t i = 0; i < items.size(); ++i) {\n    ASSERT_EQ(items[i], fixed[i]);\n  }\n}\n\nTEST(IteratorConstructorTest, FromBidirectionalIteratorRange) {\n  int const kInput[] = {2, 3, 5, 7, 11, 13, 17};\n  std::list<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));\n  absl::FixedArray<int> const fixed(items.begin(), items.end());\n  EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));\n}\n\nTEST(IteratorConstructorTest, FromCpp20ForwardIteratorRange) {\n  std::forward_list<int> const kUnzippedInput = {2, 3, 5, 7, 11, 13, 17};\n  absl::base_internal::Cpp20ForwardZipIterator<\n      std::forward_list<int>::const_iterator> const\n      begin(std::begin(kUnzippedInput), std::begin(kUnzippedInput));\n  absl::base_internal::\n      Cpp20ForwardZipIterator<std::forward_list<int>::const_iterator> const end(\n          std::end(kUnzippedInput), std::end(kUnzippedInput));\n\n  std::forward_list<std::pair<int, int>> const items(begin, end);\n  absl::FixedArray<std::pair<int, int>> const fixed(begin, end);\n  EXPECT_THAT(fixed, testing::ElementsAreArray(items));\n}\n\nTEST(InitListConstructorTest, InitListConstruction) {\n  absl::FixedArray<int> fixed = {1, 2, 3};\n  EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3}));\n}\n\nTEST(FillConstructorTest, NonEmptyArrays) {\n  absl::FixedArray<int> stack_array(4, 1);\n  EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));\n\n  absl::FixedArray<int, 0> heap_array(4, 1);\n  EXPECT_THAT(heap_array, testing::ElementsAreArray({1, 1, 1, 1}));\n}\n\nTEST(FillConstructorTest, EmptyArray) {\n  absl::FixedArray<int> empty_fill(0, 1);\n  absl::FixedArray<int> empty_size(0);\n  EXPECT_EQ(empty_fill, empty_size);\n}\n\nTEST(FillConstructorTest, NotTriviallyCopyable) {\n  std::string str = \"abcd\";\n  absl::FixedArray<std::string> strings = {str, str, str, str};\n\n  absl::FixedArray<std::string> array(4, str);\n  EXPECT_EQ(array, strings);\n}\n\nTEST(FillConstructorTest, Disambiguation) {\n  absl::FixedArray<size_t> a(1, 2);\n  EXPECT_THAT(a, testing::ElementsAre(2));\n}\n\nTEST(FixedArrayTest, ManySizedArrays) {\n  std::vector<int> sizes;\n  for (int i = 1; i < 100; i++) sizes.push_back(i);\n  for (int i = 100; i <= 1000; i += 100) sizes.push_back(i);\n  for (int n : sizes) {\n    TestArray<0>(n);\n    TestArray<1>(n);\n    TestArray<64>(n);\n    TestArray<1000>(n);\n  }\n}\n\nTEST(FixedArrayTest, ManySizedArraysOfArraysOf1) {\n  for (int n = 1; n < 1000; n++) {\n    ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 0>(n)));\n    ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1>(n)));\n    ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 64>(n)));\n    ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1000>(n)));\n  }\n}\n\nTEST(FixedArrayTest, ManySizedArraysOfArraysOf2) {\n  for (int n = 1; n < 1000; n++) {\n    TestArrayOfArrays<2, 0>(n);\n    TestArrayOfArrays<2, 1>(n);\n    TestArrayOfArrays<2, 64>(n);\n    TestArrayOfArrays<2, 1000>(n);\n  }\n}\n\n// If value_type is put inside of a struct container,\n// we might evoke this error in a hardened build unless data() is carefully\n// written, so check on that.\n//     error: call to int __builtin___sprintf_chk(etc...)\n//     will always overflow destination buffer [-Werror]\nTEST(FixedArrayTest, AvoidParanoidDiagnostics) {\n  absl::FixedArray<char, 32> buf(32);\n  sprintf(buf.data(), \"foo\");  // NOLINT(runtime/printf)\n}\n\nTEST(FixedArrayTest, TooBigInlinedSpace) {\n  struct TooBig {\n    char c[1 << 20];\n  };  // too big for even one on the stack\n\n  // Simulate the data members of absl::FixedArray, a pointer and a size_t.\n  struct Data {\n    TooBig* p;\n    size_t size;\n  };\n\n  // Make sure TooBig objects are not inlined for 0 or default size.\n  static_assert(sizeof(absl::FixedArray<TooBig, 0>) == sizeof(Data),\n                \"0-sized absl::FixedArray should have same size as Data.\");\n  static_assert(alignof(absl::FixedArray<TooBig, 0>) == alignof(Data),\n                \"0-sized absl::FixedArray should have same alignment as Data.\");\n  static_assert(sizeof(absl::FixedArray<TooBig>) == sizeof(Data),\n                \"default-sized absl::FixedArray should have same size as Data\");\n  static_assert(\n      alignof(absl::FixedArray<TooBig>) == alignof(Data),\n      \"default-sized absl::FixedArray should have same alignment as Data.\");\n}\n\n// PickyDelete EXPECTs its class-scope deallocation funcs are unused.\nstruct PickyDelete {\n  PickyDelete() {}\n  ~PickyDelete() {}\n  void operator delete(void* p) {\n    EXPECT_TRUE(false) << __FUNCTION__;\n    ::operator delete(p);\n  }\n  void operator delete[](void* p) {\n    EXPECT_TRUE(false) << __FUNCTION__;\n    ::operator delete[](p);\n  }\n};\n\nTEST(FixedArrayTest, UsesGlobalAlloc) {\n  absl::FixedArray<PickyDelete, 0> a(5);\n  EXPECT_EQ(a.size(), 5);\n}\n\nTEST(FixedArrayTest, Data) {\n  static const int kInput[] = {2, 3, 5, 7, 11, 13, 17};\n  absl::FixedArray<int> fa(std::begin(kInput), std::end(kInput));\n  EXPECT_EQ(fa.data(), &*fa.begin());\n  EXPECT_EQ(fa.data(), &fa[0]);\n\n  const absl::FixedArray<int>& cfa = fa;\n  EXPECT_EQ(cfa.data(), &*cfa.begin());\n  EXPECT_EQ(cfa.data(), &cfa[0]);\n}\n\nTEST(FixedArrayTest, Empty) {\n  absl::FixedArray<int> empty(0);\n  absl::FixedArray<int> inline_filled(1);\n  absl::FixedArray<int, 0> heap_filled(1);\n  EXPECT_TRUE(empty.empty());\n  EXPECT_FALSE(inline_filled.empty());\n  EXPECT_FALSE(heap_filled.empty());\n}\n\nTEST(FixedArrayTest, FrontAndBack) {\n  absl::FixedArray<int, 3 * sizeof(int)> inlined = {1, 2, 3};\n  EXPECT_EQ(inlined.front(), 1);\n  EXPECT_EQ(inlined.back(), 3);\n\n  absl::FixedArray<int, 0> allocated = {1, 2, 3};\n  EXPECT_EQ(allocated.front(), 1);\n  EXPECT_EQ(allocated.back(), 3);\n\n  absl::FixedArray<int> one_element = {1};\n  EXPECT_EQ(one_element.front(), one_element.back());\n}\n\nTEST(FixedArrayTest, ReverseIteratorInlined) {\n  absl::FixedArray<int, 5 * sizeof(int)> a = {0, 1, 2, 3, 4};\n\n  int counter = 5;\n  for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin();\n       iter != a.rend(); ++iter) {\n    counter--;\n    EXPECT_EQ(counter, *iter);\n  }\n  EXPECT_EQ(counter, 0);\n\n  counter = 5;\n  for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin();\n       iter != a.rend(); ++iter) {\n    counter--;\n    EXPECT_EQ(counter, *iter);\n  }\n  EXPECT_EQ(counter, 0);\n\n  counter = 5;\n  for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {\n    counter--;\n    EXPECT_EQ(counter, *iter);\n  }\n  EXPECT_EQ(counter, 0);\n}\n\nTEST(FixedArrayTest, ReverseIteratorAllocated) {\n  absl::FixedArray<int, 0> a = {0, 1, 2, 3, 4};\n\n  int counter = 5;\n  for (absl::FixedArray<int>::reverse_iterator iter = a.rbegin();\n       iter != a.rend(); ++iter) {\n    counter--;\n    EXPECT_EQ(counter, *iter);\n  }\n  EXPECT_EQ(counter, 0);\n\n  counter = 5;\n  for (absl::FixedArray<int>::const_reverse_iterator iter = a.rbegin();\n       iter != a.rend(); ++iter) {\n    counter--;\n    EXPECT_EQ(counter, *iter);\n  }\n  EXPECT_EQ(counter, 0);\n\n  counter = 5;\n  for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {\n    counter--;\n    EXPECT_EQ(counter, *iter);\n  }\n  EXPECT_EQ(counter, 0);\n}\n\nTEST(FixedArrayTest, Fill) {\n  absl::FixedArray<int, 5 * sizeof(int)> inlined(5);\n  int fill_val = 42;\n  inlined.fill(fill_val);\n  for (int i : inlined) EXPECT_EQ(i, fill_val);\n\n  absl::FixedArray<int, 0> allocated(5);\n  allocated.fill(fill_val);\n  for (int i : allocated) EXPECT_EQ(i, fill_val);\n\n  // It doesn't do anything, just make sure this compiles.\n  absl::FixedArray<int> empty(0);\n  empty.fill(fill_val);\n}\n\n#ifndef __GNUC__\nTEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {\n  using T = char;\n  constexpr auto capacity = 10;\n  using FixedArrType = absl::FixedArray<T, capacity>;\n  constexpr auto scrubbed_bits = 0x95;\n  constexpr auto length = capacity / 2;\n\n  alignas(FixedArrType) unsigned char buff[sizeof(FixedArrType)];\n  std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrType));\n\n  FixedArrType* arr =\n      ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);\n  EXPECT_THAT(*arr, testing::Each(scrubbed_bits));\n  arr->~FixedArrType();\n}\n#endif  // __GNUC__\n\nTEST(AllocatorSupportTest, CountInlineAllocations) {\n  constexpr size_t inlined_size = 4;\n  using Alloc = absl::container_internal::CountingAllocator<int>;\n  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;\n\n  int64_t allocated = 0;\n  int64_t active_instances = 0;\n\n  {\n    const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};\n\n    Alloc alloc(&allocated, &active_instances);\n\n    AllocFxdArr arr(ia, ia + inlined_size, alloc);\n    static_cast<void>(arr);\n  }\n\n  EXPECT_EQ(allocated, 0);\n  EXPECT_EQ(active_instances, 0);\n}\n\nTEST(AllocatorSupportTest, CountOutoflineAllocations) {\n  constexpr size_t inlined_size = 4;\n  using Alloc = absl::container_internal::CountingAllocator<int>;\n  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;\n\n  int64_t allocated = 0;\n  int64_t active_instances = 0;\n\n  {\n    const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};\n    Alloc alloc(&allocated, &active_instances);\n\n    AllocFxdArr arr(ia, ia + ABSL_ARRAYSIZE(ia), alloc);\n\n    EXPECT_EQ(allocated, arr.size() * sizeof(int));\n    static_cast<void>(arr);\n  }\n\n  EXPECT_EQ(active_instances, 0);\n}\n\nTEST(AllocatorSupportTest, CountCopyInlineAllocations) {\n  constexpr size_t inlined_size = 4;\n  using Alloc = absl::container_internal::CountingAllocator<int>;\n  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;\n\n  int64_t allocated1 = 0;\n  int64_t allocated2 = 0;\n  int64_t active_instances = 0;\n  Alloc alloc(&allocated1, &active_instances);\n  Alloc alloc2(&allocated2, &active_instances);\n\n  {\n    int initial_value = 1;\n\n    AllocFxdArr arr1(inlined_size / 2, initial_value, alloc);\n\n    EXPECT_EQ(allocated1, 0);\n\n    AllocFxdArr arr2(arr1, alloc2);\n\n    EXPECT_EQ(allocated2, 0);\n    static_cast<void>(arr1);\n    static_cast<void>(arr2);\n  }\n\n  EXPECT_EQ(active_instances, 0);\n}\n\nTEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {\n  constexpr size_t inlined_size = 4;\n  using Alloc = absl::container_internal::CountingAllocator<int>;\n  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;\n\n  int64_t allocated1 = 0;\n  int64_t allocated2 = 0;\n  int64_t active_instances = 0;\n  Alloc alloc(&allocated1, &active_instances);\n  Alloc alloc2(&allocated2, &active_instances);\n\n  {\n    int initial_value = 1;\n\n    AllocFxdArr arr1(inlined_size * 2, initial_value, alloc);\n\n    EXPECT_EQ(allocated1, arr1.size() * sizeof(int));\n\n    AllocFxdArr arr2(arr1, alloc2);\n\n    EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int));\n    static_cast<void>(arr1);\n    static_cast<void>(arr2);\n  }\n\n  EXPECT_EQ(active_instances, 0);\n}\n\nTEST(AllocatorSupportTest, SizeValAllocConstructor) {\n  using testing::AllOf;\n  using testing::Each;\n  using testing::SizeIs;\n\n  constexpr size_t inlined_size = 4;\n  using Alloc = absl::container_internal::CountingAllocator<int>;\n  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;\n\n  {\n    auto len = inlined_size / 2;\n    auto val = 0;\n    int64_t allocated = 0;\n    AllocFxdArr arr(len, val, Alloc(&allocated));\n\n    EXPECT_EQ(allocated, 0);\n    EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));\n  }\n\n  {\n    auto len = inlined_size * 2;\n    auto val = 0;\n    int64_t allocated = 0;\n    AllocFxdArr arr(len, val, Alloc(&allocated));\n\n    EXPECT_EQ(allocated, len * sizeof(int));\n    EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));\n  }\n}\n\nTEST(AllocatorSupportTest, PropagatesStatefulAllocator) {\n  constexpr size_t inlined_size = 4;\n  using Alloc = absl::container_internal::CountingAllocator<int>;\n  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;\n\n  auto len = inlined_size * 2;\n  auto val = 0;\n  int64_t allocated = 0;\n  AllocFxdArr arr(len, val, Alloc(&allocated));\n\n  EXPECT_EQ(allocated, len * sizeof(int));\n\n  AllocFxdArr copy = arr;\n  EXPECT_EQ(allocated, len * sizeof(int) * 2);\n  EXPECT_EQ(copy, arr);\n}\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\nTEST(FixedArrayTest, AddressSanitizerAnnotations1) {\n  absl::FixedArray<int, 32> a(10);\n  int* raw = a.data();\n  raw[0] = 0;\n  raw[9] = 0;\n  EXPECT_DEATH_IF_SUPPORTED(raw[-2] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[10] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[31] = 0, \"container-overflow\");\n}\n\nTEST(FixedArrayTest, AddressSanitizerAnnotations2) {\n  absl::FixedArray<char, 17> a(12);\n  char* raw = a.data();\n  raw[0] = 0;\n  raw[11] = 0;\n  EXPECT_DEATH_IF_SUPPORTED(raw[-7] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[12] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[17] = 0, \"container-overflow\");\n}\n\nTEST(FixedArrayTest, AddressSanitizerAnnotations3) {\n  absl::FixedArray<uint64_t, 20> a(20);\n  uint64_t* raw = a.data();\n  raw[0] = 0;\n  raw[19] = 0;\n  EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[20] = 0, \"container-overflow\");\n}\n\nTEST(FixedArrayTest, AddressSanitizerAnnotations4) {\n  absl::FixedArray<ThreeInts> a(10);\n  ThreeInts* raw = a.data();\n  raw[0] = ThreeInts();\n  raw[9] = ThreeInts();\n  // Note: raw[-1] is pointing to 12 bytes before the container range. However,\n  // there is only a 8-byte red zone before the container range, so we only\n  // access the last 4 bytes of the struct to make sure it stays within the red\n  // zone.\n  EXPECT_DEATH_IF_SUPPORTED(raw[-1].z_ = 0, \"container-overflow\");\n  EXPECT_DEATH_IF_SUPPORTED(raw[10] = ThreeInts(), \"container-overflow\");\n  // The actual size of storage is kDefaultBytes=256, 21*12 = 252,\n  // so reading raw[21] should still trigger the correct warning.\n  EXPECT_DEATH_IF_SUPPORTED(raw[21] = ThreeInts(), \"container-overflow\");\n}\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n\nTEST(FixedArrayTest, AbslHashValueWorks) {\n  using V = absl::FixedArray<int>;\n  std::vector<V> cases;\n\n  // Generate a variety of vectors some of these are small enough for the inline\n  // space but are stored out of line.\n  for (int i = 0; i < 10; ++i) {\n    V v(i);\n    for (int j = 0; j < i; ++j) {\n      v[j] = j;\n    }\n    cases.push_back(v);\n  }\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/flat_hash_map.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: flat_hash_map.h\n// -----------------------------------------------------------------------------\n//\n// An `absl::flat_hash_map<K, V>` is an unordered associative container of\n// unique keys and associated values designed to be a more efficient replacement\n// for `std::unordered_map`. Like `unordered_map`, search, insertion, and\n// deletion of map elements can be done as an `O(1)` operation. However,\n// `flat_hash_map` (and other unordered associative containers known as the\n// collection of Abseil \"Swiss tables\") contain other optimizations that result\n// in both memory and computation advantages.\n//\n// In most cases, your default choice for a hash map should be a map of type\n// `flat_hash_map`.\n//\n// `flat_hash_map` is not exception-safe.\n\n#ifndef ABSL_CONTAINER_FLAT_HASH_MAP_H_\n#define ABSL_CONTAINER_FLAT_HASH_MAP_H_\n\n#include <cstddef>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/hash_container_defaults.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/raw_hash_map.h\"  // IWYU pragma: export\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\ntemplate <class K, class V>\nstruct FlatHashMapPolicy;\n}  // namespace container_internal\n\n// -----------------------------------------------------------------------------\n// absl::flat_hash_map\n// -----------------------------------------------------------------------------\n//\n// An `absl::flat_hash_map<K, V>` is an unordered associative container which\n// has been optimized for both speed and memory footprint in most common use\n// cases. Its interface is similar to that of `std::unordered_map<K, V>` with\n// the following notable differences:\n//\n// * Requires keys that are CopyConstructible\n// * Requires values that are MoveConstructible\n// * Supports heterogeneous lookup, through `find()`, `operator[]()` and\n//   `insert()`, provided that the map is provided a compatible heterogeneous\n//   hashing function and equality operator. See below for details.\n// * Invalidates any references and pointers to elements within the table after\n//   `rehash()` and when the table is moved.\n// * Contains a `capacity()` member function indicating the number of element\n//   slots (open, deleted, and empty) within the hash map.\n// * Returns `void` from the `erase(iterator)` overload.\n//\n// By default, `flat_hash_map` uses the `absl::Hash` hashing framework.\n// All fundamental and Abseil types that support the `absl::Hash` framework have\n// a compatible equality operator for comparing insertions into `flat_hash_map`.\n// If your type is not yet supported by the `absl::Hash` framework, see\n// absl/hash/hash.h for information on extending Abseil hashing to user-defined\n// types.\n//\n// Using `absl::flat_hash_map` at interface boundaries in dynamically loaded\n// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may\n// be randomized across dynamically loaded libraries.\n//\n// To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type\n// parameters can be used or `T` should have public inner types\n// `absl_container_hash` and (optionally) `absl_container_eq`. In either case,\n// `typename Hash::is_transparent` and `typename Eq::is_transparent` should be\n// well-formed. Both types are basically functors:\n// * `Hash` should support `size_t operator()(U val) const` that returns a hash\n// for the given `val`.\n// * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true\n// if `lhs` is equal to `rhs`.\n//\n// In most cases `T` needs only to provide the `absl_container_hash`. In this\n// case `std::equal_to<void>` will be used instead of `eq` part.\n//\n// NOTE: A `flat_hash_map` stores its value types directly inside its\n// implementation array to avoid memory indirection. Because a `flat_hash_map`\n// is designed to move data when rehashed, map values will not retain pointer\n// stability. If you require pointer stability, or if your values are large,\n// consider using `absl::flat_hash_map<Key, std::unique_ptr<Value>>` instead.\n// If your types are not moveable or you require pointer stability for keys,\n// consider `absl::node_hash_map`.\n//\n// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:\n//  * Iteration takes O(capacity) time, not O(size).\n//  * erase() slows down begin() and ++iterator.\n//  * Capacity only shrinks on rehash() or clear() -- not on erase().\n//\n// Example:\n//\n//   // Create a flat hash map of three strings (that map to strings)\n//   absl::flat_hash_map<std::string, std::string> ducks =\n//     {{\"a\", \"huey\"}, {\"b\", \"dewey\"}, {\"c\", \"louie\"}};\n//\n//   // Insert a new element into the flat hash map\n//   ducks.insert({\"d\", \"donald\"});\n//\n//   // Force a rehash of the flat hash map\n//   ducks.rehash(0);\n//\n//   // Find the element with the key \"b\"\n//   std::string search_key = \"b\";\n//   auto result = ducks.find(search_key);\n//   if (result != ducks.end()) {\n//     std::cout << \"Result: \" << result->second << std::endl;\n//   }\ntemplate <\n    class K, class V,\n    class Hash =\n        typename container_internal::FlatHashMapPolicy<K, V>::DefaultHash,\n    class Eq = typename container_internal::FlatHashMapPolicy<K, V>::DefaultEq,\n    class Allocator =\n        typename container_internal::FlatHashMapPolicy<K, V>::DefaultAlloc>\nclass ABSL_ATTRIBUTE_OWNER flat_hash_map\n    : public absl::container_internal::InstantiateRawHashMap<\n          absl::container_internal::FlatHashMapPolicy<K, V>, Hash, Eq,\n          Allocator>::type {\n  using Base = typename flat_hash_map::raw_hash_map;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A flat_hash_map supports the same overload set as `std::unordered_map`\n  // for construction and assignment:\n  //\n  // *  Default constructor\n  //\n  //    // No allocation for the table's elements is made.\n  //    absl::flat_hash_map<int, std::string> map1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::flat_hash_map<int, std::string> map2 =\n  //       {{1, \"huey\"}, {2, \"dewey\"}, {3, \"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::flat_hash_map<int, std::string> map3(map2);\n  //\n  // * Copy assignment operator\n  //\n  //   // Hash functor and Comparator are copied as well\n  //   absl::flat_hash_map<int, std::string> map4;\n  //   map4 = map3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::flat_hash_map<int, std::string> map5(std::move(map4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::flat_hash_map<int, std::string> map6;\n  //   map6 = std::move(map5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::pair<int, std::string>> v = {{1, \"a\"}, {2, \"b\"}};\n  //   absl::flat_hash_map<int, std::string> map7(v.begin(), v.end());\n  //\n  // * from_range constructor (C++23)\n  //\n  //   std::vector<std::pair<int, std::string>> v = {{1, \"a\"}, {2, \"b\"}};\n  //   absl::flat_hash_map<int, std::string> map8(std::from_range, v);\n  flat_hash_map() {}\n  using Base::Base;\n\n  // flat_hash_map::begin()\n  //\n  // Returns an iterator to the beginning of the `flat_hash_map`.\n  using Base::begin;\n\n  // flat_hash_map::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `flat_hash_map`.\n  using Base::cbegin;\n\n  // flat_hash_map::cend()\n  //\n  // Returns a const iterator to the end of the `flat_hash_map`.\n  using Base::cend;\n\n  // flat_hash_map::end()\n  //\n  // Returns an iterator to the end of the `flat_hash_map`.\n  using Base::end;\n\n  // flat_hash_map::capacity()\n  //\n  // Returns the number of element slots (assigned, deleted, and empty)\n  // available within the `flat_hash_map`.\n  //\n  // NOTE: this member function is particular to `absl::flat_hash_map` and is\n  // not provided in the `std::unordered_map` API.\n  using Base::capacity;\n\n  // flat_hash_map::empty()\n  //\n  // Returns whether or not the `flat_hash_map` is empty.\n  using Base::empty;\n\n  // flat_hash_map::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `flat_hash_map` under current memory constraints. This value can be thought\n  // of the largest value of `std::distance(begin(), end())` for a\n  // `flat_hash_map<K, V>`.\n  using Base::max_size;\n\n  // flat_hash_map::size()\n  //\n  // Returns the number of elements currently within the `flat_hash_map`.\n  using Base::size;\n\n  // flat_hash_map::clear()\n  //\n  // Removes all elements from the `flat_hash_map`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  //\n  // NOTE: this operation may shrink the underlying buffer. To avoid shrinking\n  // the underlying buffer call `erase(begin(), end())`.\n  using Base::clear;\n\n  // flat_hash_map::erase()\n  //\n  // Erases elements within the `flat_hash_map`. Erasing does not trigger a\n  // rehash. Overloads are listed below.\n  //\n  // void erase(const_iterator pos):\n  //\n  //   Erases the element at `position` of the `flat_hash_map`, returning\n  //   `void`.\n  //\n  //   NOTE: returning `void` in this case is different than that of STL\n  //   containers in general and `std::unordered_map` in particular (which\n  //   return an iterator to the element following the erased element). If that\n  //   iterator is needed, simply post increment the iterator:\n  //\n  //     map.erase(it++);\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning an\n  //   iterator pointing to `last`. The special case of calling\n  //   `erase(begin(), end())` resets the reserved growth such that if\n  //   `reserve(N)` has previously been called and there has been no intervening\n  //   call to `clear()`, then after calling `erase(begin(), end())`, it is safe\n  //   to assume that inserting N elements will not cause a rehash.\n  //\n  // size_type erase(const key_type& key):\n  //\n  //   Erases the element with the matching key, if it exists, returning the\n  //   number of elements erased (0 or 1).\n  using Base::erase;\n\n  // flat_hash_map::insert()\n  //\n  // Inserts an element of the specified value into the `flat_hash_map`,\n  // returning an iterator pointing to the newly inserted element, provided that\n  // an element with the given key does not already exist. If rehashing occurs\n  // due to the insertion, all iterators are invalidated. Overloads are listed\n  // below.\n  //\n  // std::pair<iterator,bool> insert(const init_type& value):\n  //\n  //   Inserts a value into the `flat_hash_map`. Returns a pair consisting of an\n  //   iterator to the inserted element (or to the element that prevented the\n  //   insertion) and a bool denoting whether the insertion took place.\n  //\n  // std::pair<iterator,bool> insert(T&& value):\n  // std::pair<iterator,bool> insert(init_type&& value):\n  //\n  //   Inserts a moveable value into the `flat_hash_map`. Returns a pair\n  //   consisting of an iterator to the inserted element (or to the element that\n  //   prevented the insertion) and a bool denoting whether the insertion took\n  //   place.\n  //\n  // iterator insert(const_iterator hint, const init_type& value):\n  // iterator insert(const_iterator hint, T&& value):\n  // iterator insert(const_iterator hint, init_type&& value);\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element, or to the existing element that prevented the\n  //   insertion.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently, for `flat_hash_map` we guarantee the\n  //   first match is inserted.\n  //\n  // void insert(std::initializer_list<init_type> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently within the initializer list, for\n  //   `flat_hash_map` we guarantee the first match is inserted.\n  using Base::insert;\n\n  // flat_hash_map::insert_or_assign()\n  //\n  // Inserts an element of the specified value into the `flat_hash_map` provided\n  // that a value with the given key does not already exist, or replaces it with\n  // the element value if a key for that value already exists, returning an\n  // iterator pointing to the newly inserted element.  If rehashing occurs due\n  // to the insertion, all existing iterators are invalidated. Overloads are\n  // listed below.\n  //\n  // pair<iterator, bool> insert_or_assign(const init_type& k, T&& obj):\n  // pair<iterator, bool> insert_or_assign(init_type&& k, T&& obj):\n  //\n  //   Inserts/Assigns (or moves) the element of the specified key into the\n  //   `flat_hash_map`.\n  //\n  // iterator insert_or_assign(const_iterator hint,\n  //                           const init_type& k, T&& obj):\n  // iterator insert_or_assign(const_iterator hint, init_type&& k, T&& obj):\n  //\n  //   Inserts/Assigns (or moves) the element of the specified key into the\n  //   `flat_hash_map` using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search.\n  using Base::insert_or_assign;\n\n  // flat_hash_map::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `flat_hash_map`, provided that no element with the given key\n  // already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately. Prefer `try_emplace()` unless your key is not\n  // copyable or moveable.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace;\n\n  // flat_hash_map::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `flat_hash_map`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search, and only inserts\n  // provided that no element with the given key already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately. Prefer `try_emplace()` unless your key is not\n  // copyable or moveable.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace_hint;\n\n  // flat_hash_map::try_emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `flat_hash_map`, provided that no element with the given key\n  // already exists. Unlike `emplace()`, if an element with the given key\n  // already exists, we guarantee that no element is constructed.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  // Overloads are listed below.\n  //\n  //   pair<iterator, bool> try_emplace(const key_type& k, Args&&... args):\n  //   pair<iterator, bool> try_emplace(key_type&& k, Args&&... args):\n  //\n  // Inserts (via copy or move) the element of the specified key into the\n  // `flat_hash_map`.\n  //\n  //   iterator try_emplace(const_iterator hint,\n  //                        const key_type& k, Args&&... args):\n  //   iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args):\n  //\n  // Inserts (via copy or move) the element of the specified key into the\n  // `flat_hash_map` using the position of `hint` as a non-binding suggestion\n  // for where to begin the insertion search.\n  //\n  // All `try_emplace()` overloads make the same guarantees regarding rvalue\n  // arguments as `std::unordered_map::try_emplace()`, namely that these\n  // functions will not move from rvalue arguments if insertions do not happen.\n  using Base::try_emplace;\n\n  // flat_hash_map::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the key,value pair of the element at the indicated position and\n  //   returns a node handle owning that extracted data.\n  //\n  // node_type extract(const key_type& x):\n  //\n  //   Extracts the key,value pair of the element with a key matching the passed\n  //   key value and returns a node handle owning that extracted data. If the\n  //   `flat_hash_map` does not contain an element with a matching key, this\n  //   function returns an empty node handle.\n  //\n  // NOTE: when compiled in an earlier version of C++ than C++17,\n  // `node_type::key()` returns a const reference to the key instead of a\n  // mutable reference. We cannot safely return a mutable reference without\n  // std::launder (which is not available before C++17).\n  using Base::extract;\n\n  // flat_hash_map::merge()\n  //\n  // Extracts elements from a given `source` flat hash map into this\n  // `flat_hash_map`. If the destination `flat_hash_map` already contains an\n  // element with an equivalent key, that element is not extracted.\n  using Base::merge;\n\n  // flat_hash_map::swap(flat_hash_map& other)\n  //\n  // Exchanges the contents of this `flat_hash_map` with those of the `other`\n  // flat hash map.\n  //\n  // All iterators and references on the `flat_hash_map` remain valid, excepting\n  // for the past-the-end iterator, which is invalidated.\n  //\n  // `swap()` requires that the flat hash map's hashing and key equivalence\n  // functions be Swappable, and are exchanged using unqualified calls to\n  // non-member `swap()`. If the map's allocator has\n  // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`\n  // set to `true`, the allocators are also exchanged using an unqualified call\n  // to non-member `swap()`; otherwise, the allocators are not swapped.\n  using Base::swap;\n\n  // flat_hash_map::rehash(count)\n  //\n  // Rehashes the `flat_hash_map`, setting the number of slots to be at least\n  // the passed value. If the new number of slots increases the load factor more\n  // than the current maximum load factor\n  // (`count` < `size()` / `max_load_factor()`), then the new number of slots\n  // will be at least `size()` / `max_load_factor()`.\n  //\n  // To force a rehash, pass rehash(0).\n  //\n  // NOTE: unlike behavior in `std::unordered_map`, references are also\n  // invalidated upon a `rehash()`.\n  using Base::rehash;\n\n  // flat_hash_map::reserve(count)\n  //\n  // Sets the number of slots in the `flat_hash_map` to the number needed to\n  // accommodate at least `count` total elements without exceeding the current\n  // maximum load factor, and may rehash the container if needed. After this\n  // returns, it is guaranteed that `count - size()` elements can be inserted\n  // into the `flat_hash_map` without another rehash.\n  using Base::reserve;\n\n  // flat_hash_map::at()\n  //\n  // Returns a reference to the mapped value of the element with key equivalent\n  // to the passed key.\n  using Base::at;\n\n  // flat_hash_map::contains()\n  //\n  // Determines whether an element with a key comparing equal to the given `key`\n  // exists within the `flat_hash_map`, returning `true` if so or `false`\n  // otherwise.\n  using Base::contains;\n\n  // flat_hash_map::count(const Key& key) const\n  //\n  // Returns the number of elements with a key comparing equal to the given\n  // `key` within the `flat_hash_map`. note that this function will return\n  // either `1` or `0` since duplicate keys are not allowed within a\n  // `flat_hash_map`.\n  using Base::count;\n\n  // flat_hash_map::equal_range()\n  //\n  // Returns a closed range [first, last], defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `flat_hash_map`.\n  using Base::equal_range;\n\n  // flat_hash_map::find()\n  //\n  // Finds an element with the passed `key` within the `flat_hash_map`.\n  using Base::find;\n\n  // flat_hash_map::operator[]()\n  //\n  // Returns a reference to the value mapped to the passed key within the\n  // `flat_hash_map`, performing an `insert()` if the key does not already\n  // exist.\n  //\n  // If an insertion occurs and results in a rehashing of the container, all\n  // iterators are invalidated. Otherwise iterators are not affected and\n  // references are not invalidated. Overloads are listed below.\n  //\n  // T& operator[](const Key& key):\n  //\n  //   Inserts an init_type object constructed in-place if the element with the\n  //   given key does not exist.\n  //\n  // T& operator[](Key&& key):\n  //\n  //   Inserts an init_type object constructed in-place provided that an element\n  //   with the given key does not exist.\n  using Base::operator[];\n\n  // flat_hash_map::bucket_count()\n  //\n  // Returns the number of \"buckets\" within the `flat_hash_map`. Note that\n  // because a flat hash map contains all elements within its internal storage,\n  // this value simply equals the current capacity of the `flat_hash_map`.\n  using Base::bucket_count;\n\n  // flat_hash_map::load_factor()\n  //\n  // Returns the current load factor of the `flat_hash_map` (the average number\n  // of slots occupied with a value within the hash map).\n  using Base::load_factor;\n\n  // flat_hash_map::max_load_factor()\n  //\n  // Manages the maximum load factor of the `flat_hash_map`. Overloads are\n  // listed below.\n  //\n  // float flat_hash_map::max_load_factor()\n  //\n  //   Returns the current maximum load factor of the `flat_hash_map`.\n  //\n  // void flat_hash_map::max_load_factor(float ml)\n  //\n  //   Sets the maximum load factor of the `flat_hash_map` to the passed value.\n  //\n  //   NOTE: This overload is provided only for API compatibility with the STL;\n  //   `flat_hash_map` will ignore any set load factor and manage its rehashing\n  //   internally as an implementation detail.\n  using Base::max_load_factor;\n\n  // flat_hash_map::get_allocator()\n  //\n  // Returns the allocator function associated with this `flat_hash_map`.\n  using Base::get_allocator;\n\n  // flat_hash_map::hash_function()\n  //\n  // Returns the hashing function used to hash the keys within this\n  // `flat_hash_map`.\n  using Base::hash_function;\n\n  // flat_hash_map::key_eq()\n  //\n  // Returns the function used for comparing keys equality.\n  using Base::key_eq;\n};\n\n// erase_if(flat_hash_map<>, Pred)\n//\n// Erases all elements that satisfy the predicate `pred` from the container `c`.\n// Returns the number of erased elements.\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Predicate>\ntypename flat_hash_map<K, V, H, E, A>::size_type erase_if(\n    flat_hash_map<K, V, H, E, A>& c, Predicate pred) {\n  return container_internal::EraseIf(pred, &c);\n}\n\n// swap(flat_hash_map<>, flat_hash_map<>)\n//\n// Swaps the contents of two `flat_hash_map` containers.\n//\n// NOTE: we need to define this function template in order for\n// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we\n// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a\n// derived-to-base conversion, whereas `std::swap` is a function template so\n// `std::swap` will be preferred by compiler.\ntemplate <typename K, typename V, typename H, typename E, typename A>\nvoid swap(flat_hash_map<K, V, H, E, A>& x,\n          flat_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) {\n  x.swap(y);\n}\n\nnamespace container_internal {\n\n// c_for_each_fast(flat_hash_map<>, Function)\n//\n// Container-based version of the <algorithm> `std::for_each()` function to\n// apply a function to a container's elements.\n// There is no guarantees on the order of the function calls.\n// Erasure and/or insertion of elements in the function is not allowed.\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Function>\ndecay_t<Function> c_for_each_fast(const flat_hash_map<K, V, H, E, A>& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Function>\ndecay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Function>\ndecay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>&& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\n\n}  // namespace container_internal\n\nnamespace container_internal {\n\ntemplate <class K, class V>\nstruct FlatHashMapPolicy {\n  using slot_policy = container_internal::map_slot_policy<K, V>;\n  using slot_type = typename slot_policy::slot_type;\n  using key_type = K;\n  using mapped_type = V;\n  using init_type = std::pair</*non const*/ key_type, mapped_type>;\n\n  using DefaultHash = DefaultHashContainerHash<K>;\n  using DefaultEq = DefaultHashContainerEq<K>;\n  using DefaultAlloc = std::allocator<std::pair<const K, V>>;\n\n  template <class Allocator, class... Args>\n  static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {\n    slot_policy::construct(alloc, slot, std::forward<Args>(args)...);\n  }\n\n  // Returns std::true_type in case destroy is trivial.\n  template <class Allocator>\n  static auto destroy(Allocator* alloc, slot_type* slot) {\n    return slot_policy::destroy(alloc, slot);\n  }\n\n  template <class Allocator>\n  static auto transfer(Allocator* alloc, slot_type* new_slot,\n                       slot_type* old_slot) {\n    return slot_policy::transfer(alloc, new_slot, old_slot);\n  }\n\n  template <class F, class... Args>\n  static decltype(absl::container_internal::DecomposePair(\n      std::declval<F>(), std::declval<Args>()...))\n  apply(F&& f, Args&&... args) {\n    return absl::container_internal::DecomposePair(std::forward<F>(f),\n                                                   std::forward<Args>(args)...);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return memory_internal::IsLayoutCompatible<K, V>::value\n               ? &TypeErasedApplyToSlotFn<Hash, K, kIsDefault>\n               : nullptr;\n  }\n\n  static size_t space_used(const slot_type*) { return 0; }\n\n  static std::pair<const K, V>& element(slot_type* slot) { return slot->value; }\n\n  static V& value(std::pair<const K, V>* kv) { return kv->second; }\n  static const V& value(const std::pair<const K, V>* kv) { return kv->second; }\n};\n\n}  // namespace container_internal\n\nnamespace container_algorithm_internal {\n\n// Specialization of trait in absl/algorithm/container.h\ntemplate <class Key, class T, class Hash, class KeyEqual, class Allocator>\nstruct IsUnorderedContainer<\n    absl::flat_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};\n\n}  // namespace container_algorithm_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_FLAT_HASH_MAP_H_\n"
  },
  {
    "path": "absl/container/flat_hash_map_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/flat_hash_map.h\"\n\n#include <cstddef>\n#include <memory>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/container/internal/unordered_map_constructor_test.h\"\n#include \"absl/container/internal/unordered_map_lookup_test.h\"\n#include \"absl/container/internal/unordered_map_members_test.h\"\n#include \"absl/container/internal/unordered_map_modifiers_test.h\"\n#include \"absl/log/check.h\"\n#include \"absl/meta/type_traits.h\"\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <ranges>  // NOLINT(build/c++20)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::_;\nusing ::testing::IsEmpty;\nusing ::testing::Pair;\nusing ::testing::UnorderedElementsAre;\nusing ::testing::UnorderedElementsAreArray;\n\n// Check that absl::flat_hash_map works in a global constructor.\nstruct BeforeMain {\n  BeforeMain() {\n    absl::flat_hash_map<int, int> x;\n    x.insert({1, 1});\n    CHECK(x.find(0) == x.end()) << \"x should not contain 0\";\n    auto it = x.find(1);\n    CHECK(it != x.end()) << \"x should contain 1\";\n    CHECK(it->second) << \"1 should map to 1\";\n  }\n};\nconst BeforeMain before_main;\n\ntemplate <class K, class V>\nusing Map = flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual,\n                          Alloc<std::pair<const K, V>>>;\n\nstatic_assert(!std::is_standard_layout<NonStandardLayout>(), \"\");\n\nusing MapTypes =\n    ::testing::Types<Map<int, int>, Map<std::string, int>,\n                     Map<Enum, std::string>, Map<EnumClass, int>,\n                     Map<int, NonStandardLayout>, Map<NonStandardLayout, int>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ConstructorTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, MembersTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes);\n\nusing UniquePtrMapTypes = ::testing::Types<Map<int, std::unique_ptr<int>>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, UniquePtrModifiersTest,\n                               UniquePtrMapTypes);\n\nTEST(FlatHashMap, StandardLayout) {\n  struct Int {\n    explicit Int(size_t value) : value(value) {}\n    Int() : value(0) { ADD_FAILURE(); }\n    Int(const Int& other) : value(other.value) { ADD_FAILURE(); }\n    Int(Int&&) = default;\n    bool operator==(const Int& other) const { return value == other.value; }\n    size_t value;\n  };\n  static_assert(std::is_standard_layout<Int>(), \"\");\n\n  struct Hash {\n    size_t operator()(const Int& obj) const { return obj.value; }\n  };\n\n  // Verify that neither the key nor the value get default-constructed or\n  // copy-constructed.\n  {\n    flat_hash_map<Int, Int, Hash> m;\n    m.try_emplace(Int(1), Int(2));\n    m.try_emplace(Int(3), Int(4));\n    m.erase(Int(1));\n    m.rehash(2 * m.bucket_count());\n  }\n  {\n    flat_hash_map<Int, Int, Hash> m;\n    m.try_emplace(Int(1), Int(2));\n    m.try_emplace(Int(3), Int(4));\n    m.erase(Int(1));\n    m.clear();\n  }\n}\n\nTEST(FlatHashMap, Relocatability) {\n  static_assert(absl::is_trivially_relocatable<int>::value);\n  static_assert(\n      std::is_same<decltype(absl::container_internal::FlatHashMapPolicy<\n                            int, int>::transfer<std::allocator<char>>(nullptr,\n                                                                      nullptr,\n                                                                      nullptr)),\n                   std::true_type>::value);\n\n  struct NonRelocatable {\n    NonRelocatable() = default;\n    NonRelocatable(NonRelocatable&&) {}\n    NonRelocatable& operator=(NonRelocatable&&) { return *this; }\n    void* self = nullptr;\n  };\n\n  EXPECT_FALSE(absl::is_trivially_relocatable<NonRelocatable>::value);\n  EXPECT_TRUE(\n      (std::is_same<decltype(absl::container_internal::FlatHashMapPolicy<\n                            int, NonRelocatable>::\n                                transfer<std::allocator<char>>(nullptr, nullptr,\n                                                               nullptr)),\n                   std::false_type>::value));\n}\n\n// gcc becomes unhappy if this is inside the method, so pull it out here.\nstruct balast {};\n\nTEST(FlatHashMap, IteratesMsan) {\n  // Because SwissTable randomizes on pointer addresses, we keep old tables\n  // around to ensure we don't reuse old memory.\n  std::vector<absl::flat_hash_map<int, balast>> garbage;\n  for (int i = 0; i < 100; ++i) {\n    absl::flat_hash_map<int, balast> t;\n    for (int j = 0; j < 100; ++j) {\n      t[j];\n      for (const auto& p : t) EXPECT_THAT(p, Pair(_, _));\n    }\n    garbage.push_back(std::move(t));\n  }\n}\n\n// Demonstration of the \"Lazy Key\" pattern.  This uses heterogeneous insert to\n// avoid creating expensive key elements when the item is already present in the\n// map.\nstruct LazyInt {\n  explicit LazyInt(size_t value, int* tracker)\n      : value(value), tracker(tracker) {}\n\n  explicit operator size_t() const {\n    ++*tracker;\n    return value;\n  }\n\n  size_t value;\n  int* tracker;\n};\n\nstruct Hash {\n  using is_transparent = void;\n  int* tracker;\n  size_t operator()(size_t obj) const {\n    ++*tracker;\n    return obj;\n  }\n  size_t operator()(const LazyInt& obj) const {\n    ++*tracker;\n    return obj.value;\n  }\n};\n\nstruct Eq {\n  using is_transparent = void;\n  bool operator()(size_t lhs, size_t rhs) const { return lhs == rhs; }\n  bool operator()(size_t lhs, const LazyInt& rhs) const {\n    return lhs == rhs.value;\n  }\n};\n\nTEST(FlatHashMap, LazyKeyPattern) {\n  // hashes are only guaranteed in opt mode, we use assertions to track internal\n  // state that can cause extra calls to hash.\n  int conversions = 0;\n  int hashes = 0;\n  flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes});\n  m.reserve(3);\n\n  m[LazyInt(1, &conversions)] = 1;\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1)));\n  EXPECT_EQ(conversions, 1);\n#ifdef NDEBUG\n  EXPECT_EQ(hashes, 1);\n#endif\n\n  m[LazyInt(1, &conversions)] = 2;\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2)));\n  EXPECT_EQ(conversions, 1);\n#ifdef NDEBUG\n  EXPECT_EQ(hashes, 2);\n#endif\n\n  m.try_emplace(LazyInt(2, &conversions), 3);\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(2, 3)));\n  EXPECT_EQ(conversions, 2);\n#ifdef NDEBUG\n  EXPECT_EQ(hashes, 3);\n#endif\n\n  m.try_emplace(LazyInt(2, &conversions), 4);\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(2, 3)));\n  EXPECT_EQ(conversions, 2);\n#ifdef NDEBUG\n  EXPECT_EQ(hashes, 4);\n#endif\n}\n\nTEST(FlatHashMap, BitfieldArgument) {\n  union {\n    int n : 1;\n  };\n  n = 0;\n  flat_hash_map<int, int> m;\n  m.erase(n);\n  m.count(n);\n  m.prefetch(n);\n  m.find(n);\n  m.contains(n);\n  m.equal_range(n);\n  m.insert_or_assign(n, n);\n  m.insert_or_assign(m.end(), n, n);\n  m.try_emplace(n);\n  m.try_emplace(m.end(), n);\n  m.at(n);\n  m[n];\n}\n\nTEST(FlatHashMap, MergeExtractInsert) {\n  // We can't test mutable keys, or non-copyable keys with flat_hash_map.\n  // Test that the nodes have the proper API.\n  absl::flat_hash_map<int, int> m = {{1, 7}, {2, 9}};\n  auto node = m.extract(1);\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.key(), 1);\n  EXPECT_EQ(node.mapped(), 7);\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(2, 9)));\n\n  node.mapped() = 17;\n  m.insert(std::move(node));\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));\n}\n\nbool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; }\n\nTEST(FlatHashMap, EraseIf) {\n  // Erase all elements.\n  {\n    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return true; }), 5);\n    EXPECT_THAT(s, IsEmpty());\n  }\n  // Erase no elements.\n  {\n    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return false; }), 0);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),\n                                        Pair(4, 4), Pair(5, 5)));\n  }\n  // Erase specific elements.\n  {\n    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s,\n                       [](std::pair<const int, int> kvp) {\n                         return kvp.first % 2 == 1;\n                       }),\n              3);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));\n  }\n  // Predicate is function reference.\n  {\n    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, FirstIsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));\n  }\n  // Predicate is function pointer.\n  {\n    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, &FirstIsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));\n  }\n}\n\nTEST(FlatHashMap, CForEach) {\n  flat_hash_map<int, int> m;\n  std::vector<std::pair<int, int>> expected;\n  for (int i = 0; i < 100; ++i) {\n    {\n      SCOPED_TRACE(\"mutable object iteration\");\n      std::vector<std::pair<int, int>> v;\n      absl::container_internal::c_for_each_fast(\n          m, [&v](std::pair<const int, int>& p) { v.push_back(p); });\n      EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const object iteration\");\n      std::vector<std::pair<int, int>> v;\n      const flat_hash_map<int, int>& cm = m;\n      absl::container_internal::c_for_each_fast(\n          cm, [&v](const std::pair<const int, int>& p) { v.push_back(p); });\n      EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const object iteration\");\n      std::vector<std::pair<int, int>> v;\n      absl::container_internal::c_for_each_fast(\n          flat_hash_map<int, int>(m),\n          [&v](std::pair<const int, int>& p) { v.push_back(p); });\n      EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    m[i] = i;\n    expected.emplace_back(i, i);\n  }\n}\n\nTEST(FlatHashMap, CForEachMutate) {\n  flat_hash_map<int, int> s;\n  std::vector<std::pair<int, int>> expected;\n  for (int i = 0; i < 100; ++i) {\n    std::vector<std::pair<int, int>> v;\n    absl::container_internal::c_for_each_fast(\n        s, [&v](std::pair<const int, int>& p) {\n          v.push_back(p);\n          p.second++;\n        });\n    EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    for (auto& p : expected) {\n      p.second++;\n    }\n    EXPECT_THAT(s, UnorderedElementsAreArray(expected));\n    s[i] = i;\n    expected.emplace_back(i, i);\n  }\n}\n\nTEST(FlatHashMap, NodeHandleMutableKeyAccess) {\n  flat_hash_map<std::string, std::string> map;\n\n  map[\"key1\"] = \"mapped\";\n\n  auto nh = map.extract(map.begin());\n  nh.key().resize(3);\n  map.insert(std::move(nh));\n\n  EXPECT_THAT(map, testing::ElementsAre(Pair(\"key\", \"mapped\")));\n}\n\nTEST(FlatHashMap, Reserve) {\n  // Verify that if we reserve(size() + n) then we can perform n insertions\n  // without a rehash, i.e., without invalidating any references.\n  for (size_t trial = 0; trial < 20; ++trial) {\n    for (size_t initial = 3; initial < 100; ++initial) {\n      // Fill in `initial` entries, then erase 2 of them, then reserve space for\n      // two inserts and check for reference stability while doing the inserts.\n      flat_hash_map<size_t, size_t> map;\n      for (size_t i = 0; i < initial; ++i) {\n        map[i] = i;\n      }\n      map.erase(0);\n      map.erase(1);\n      map.reserve(map.size() + 2);\n      size_t& a2 = map[2];\n      // In the event of a failure, asan will complain in one of these two\n      // assignments.\n      map[initial] = a2;\n      map[initial + 1] = a2;\n      // Fail even when not under asan:\n      size_t& a2new = map[2];\n      EXPECT_EQ(&a2, &a2new);\n    }\n  }\n}\n\nTEST(FlatHashMap, RecursiveTypeCompiles) {\n  struct RecursiveType {\n    flat_hash_map<int, RecursiveType> m;\n  };\n  RecursiveType t;\n  t.m[0] = RecursiveType{};\n}\n\nTEST(FlatHashMap, FlatHashMapPolicyDestroyReturnsTrue) {\n  EXPECT_TRUE(\n      (decltype(FlatHashMapPolicy<int, char>::destroy<std::allocator<char>>(\n          nullptr, nullptr))()));\n  EXPECT_FALSE(\n      (decltype(FlatHashMapPolicy<int, char>::destroy<CountingAllocator<char>>(\n          nullptr, nullptr))()));\n  EXPECT_FALSE((decltype(FlatHashMapPolicy<int, std::unique_ptr<int>>::destroy<\n                         std::allocator<char>>(nullptr, nullptr))()));\n}\n\nstruct InconsistentHashEqType {\n  InconsistentHashEqType(int v1, int v2) : v1(v1), v2(v2) {}\n  template <typename H>\n  friend H AbslHashValue(H h, InconsistentHashEqType t) {\n    return H::combine(std::move(h), t.v1);\n  }\n  bool operator==(InconsistentHashEqType t) const { return v2 == t.v2; }\n  int v1, v2;\n};\n\nTEST(Iterator, InconsistentHashEqFunctorsValidation) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  absl::flat_hash_map<InconsistentHashEqType, int> m;\n  for (int i = 0; i < 10; ++i) m[{i, i}] = 1;\n  // We need to insert multiple times to guarantee that we get the assertion\n  // because it's possible for the hash to collide with the inserted element\n  // that has v2==0. In those cases, the new element won't be inserted.\n  auto insert_conflicting_elems = [&] {\n    for (int i = 100; i < 20000; ++i) {\n      EXPECT_EQ((m[{i, 0}]), 1);\n    }\n  };\n\n  const char* crash_message = \"hash/eq functors are inconsistent.\";\n#if defined(__arm__) || defined(__aarch64__)\n  // On ARM, the crash message is garbled so don't expect a specific message.\n  crash_message = \"\";\n#endif\n  EXPECT_DEATH_IF_SUPPORTED(insert_conflicting_elems(), crash_message);\n}\n\n#if defined(__cpp_lib_containers_ranges) && \\\n    __cpp_lib_containers_ranges >= 202202L\nTEST(FlatHashMap, FromRange) {\n  std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};\n  absl::flat_hash_map<int, int> m(std::from_range, v);\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));\n}\n\nTEST(FlatHashMap, FromRangeWithAllocator) {\n  std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};\n  absl::flat_hash_map<int, int,\n                      absl::container_internal::hash_default_hash<int>,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<std::pair<const int, int>>>\n      m(std::from_range, v, 0, Alloc<std::pair<const int, int>>());\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));\n}\n\nTEST(FlatHashMap, FromRangeWithHasherAndAllocator) {\n  std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};\n  using TestingHash = absl::container_internal::StatefulTestingHash;\n  absl::flat_hash_map<int, int, TestingHash,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<std::pair<const int, int>>>\n      m(std::from_range, v, 0, TestingHash{},\n        Alloc<std::pair<const int, int>>());\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));\n}\n#endif\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/flat_hash_set.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: flat_hash_set.h\n// -----------------------------------------------------------------------------\n//\n// An `absl::flat_hash_set<T>` is an unordered associative container designed to\n// be a more efficient replacement for `std::unordered_set`. Like\n// `unordered_set`, search, insertion, and deletion of set elements can be done\n// as an `O(1)` operation. However, `flat_hash_set` (and other unordered\n// associative containers known as the collection of Abseil \"Swiss tables\")\n// contain other optimizations that result in both memory and computation\n// advantages.\n//\n// In most cases, your default choice for a hash set should be a set of type\n// `flat_hash_set`.\n//\n// `flat_hash_set` is not exception-safe.\n\n#ifndef ABSL_CONTAINER_FLAT_HASH_SET_H_\n#define ABSL_CONTAINER_FLAT_HASH_SET_H_\n\n#include <cstddef>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/hash_container_defaults.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/raw_hash_set.h\"  // IWYU pragma: export\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\ntemplate <typename T>\nstruct FlatHashSetPolicy;\n}  // namespace container_internal\n\n// -----------------------------------------------------------------------------\n// absl::flat_hash_set\n// -----------------------------------------------------------------------------\n//\n// An `absl::flat_hash_set<T>` is an unordered associative container which has\n// been optimized for both speed and memory footprint in most common use cases.\n// Its interface is similar to that of `std::unordered_set<T>` with the\n// following notable differences:\n//\n// * Requires keys that are MoveConstructible\n// * Supports heterogeneous lookup, through `find()` and `insert()`, provided\n//   that the set is provided a compatible heterogeneous hashing function and\n//   equality operator. See below for details.\n// * Invalidates any references and pointers to elements within the table after\n//   `rehash()` and when the table is moved.\n// * Contains a `capacity()` member function indicating the number of element\n//   slots (open, deleted, and empty) within the hash set.\n// * Returns `void` from the `erase(iterator)` overload.\n//\n// By default, `flat_hash_set` uses the `absl::Hash` hashing framework. All\n// fundamental and Abseil types that support the `absl::Hash` framework have a\n// compatible equality operator for comparing insertions into `flat_hash_set`.\n// If your type is not yet supported by the `absl::Hash` framework, see\n// absl/hash/hash.h for information on extending Abseil hashing to user-defined\n// types.\n//\n// Using `absl::flat_hash_set` at interface boundaries in dynamically loaded\n// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may\n// be randomized across dynamically loaded libraries.\n//\n// To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type\n// parameters can be used or `T` should have public inner types\n// `absl_container_hash` and (optionally) `absl_container_eq`. In either case,\n// `typename Hash::is_transparent` and `typename Eq::is_transparent` should be\n// well-formed. Both types are basically functors:\n// * `Hash` should support `size_t operator()(U val) const` that returns a hash\n// for the given `val`.\n// * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true\n// if `lhs` is equal to `rhs`.\n//\n// In most cases `T` needs only to provide the `absl_container_hash`. In this\n// case `std::equal_to<void>` will be used instead of `eq` part.\n//\n// NOTE: A `flat_hash_set` stores its keys directly inside its implementation\n// array to avoid memory indirection. Because a `flat_hash_set` is designed to\n// move data when rehashed, set keys will not retain pointer stability. If you\n// require pointer stability, consider using\n// `absl::flat_hash_set<std::unique_ptr<T>>`. If your type is not moveable and\n// you require pointer stability, consider `absl::node_hash_set` instead.\n//\n// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:\n//  * Iteration takes O(capacity) time, not O(size).\n//  * erase() slows down begin() and ++iterator.\n//  * Capacity only shrinks on rehash() or clear() -- not on erase().\n//\n// Example:\n//\n//   // Create a flat hash set of three strings\n//   absl::flat_hash_set<std::string> ducks =\n//     {\"huey\", \"dewey\", \"louie\"};\n//\n//   // Insert a new element into the flat hash set\n//   ducks.insert(\"donald\");\n//\n//   // Force a rehash of the flat hash set\n//   ducks.rehash(0);\n//\n//   // See if \"dewey\" is present\n//   if (ducks.contains(\"dewey\")) {\n//     std::cout << \"We found dewey!\" << std::endl;\n//   }\ntemplate <\n    class T,\n    class Hash = typename container_internal::FlatHashSetPolicy<T>::DefaultHash,\n    class Eq = typename container_internal::FlatHashSetPolicy<T>::DefaultEq,\n    class Allocator =\n        typename container_internal::FlatHashSetPolicy<T>::DefaultAlloc>\nclass ABSL_ATTRIBUTE_OWNER flat_hash_set\n    : public absl::container_internal::InstantiateRawHashSet<\n          absl::container_internal::FlatHashSetPolicy<T>, Hash, Eq,\n          Allocator>::type {\n  using Base = typename flat_hash_set::raw_hash_set;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A flat_hash_set supports the same overload set as `std::unordered_set`\n  // for construction and assignment:\n  //\n  // *  Default constructor\n  //\n  //    // No allocation for the table's elements is made.\n  //    absl::flat_hash_set<std::string> set1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::flat_hash_set<std::string> set2 =\n  //       {{\"huey\"}, {\"dewey\"}, {\"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::flat_hash_set<std::string> set3(set2);\n  //\n  // * Copy assignment operator\n  //\n  //   // Hash functor and Comparator are copied as well\n  //   absl::flat_hash_set<std::string> set4;\n  //   set4 = set3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::flat_hash_set<std::string> set5(std::move(set4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::flat_hash_set<std::string> set6;\n  //   set6 = std::move(set5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::string> v = {\"a\", \"b\"};\n  //   absl::flat_hash_set<std::string> set7(v.begin(), v.end());\n  //\n  // * from_range constructor (C++23)\n  //\n  //   std::vector<std::string> v = {\"a\", \"b\"};\n  //   absl::flat_hash_set<std::string> set8(std::from_range, v);\n  flat_hash_set() {}\n  using Base::Base;\n\n  // flat_hash_set::begin()\n  //\n  // Returns an iterator to the beginning of the `flat_hash_set`.\n  using Base::begin;\n\n  // flat_hash_set::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `flat_hash_set`.\n  using Base::cbegin;\n\n  // flat_hash_set::cend()\n  //\n  // Returns a const iterator to the end of the `flat_hash_set`.\n  using Base::cend;\n\n  // flat_hash_set::end()\n  //\n  // Returns an iterator to the end of the `flat_hash_set`.\n  using Base::end;\n\n  // flat_hash_set::capacity()\n  //\n  // Returns the number of element slots (assigned, deleted, and empty)\n  // available within the `flat_hash_set`.\n  //\n  // NOTE: this member function is particular to `absl::flat_hash_set` and is\n  // not provided in the `std::unordered_set` API.\n  using Base::capacity;\n\n  // flat_hash_set::empty()\n  //\n  // Returns whether or not the `flat_hash_set` is empty.\n  using Base::empty;\n\n  // flat_hash_set::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `flat_hash_set` under current memory constraints. This value can be thought\n  // of the largest value of `std::distance(begin(), end())` for a\n  // `flat_hash_set<T>`.\n  using Base::max_size;\n\n  // flat_hash_set::size()\n  //\n  // Returns the number of elements currently within the `flat_hash_set`.\n  using Base::size;\n\n  // flat_hash_set::clear()\n  //\n  // Removes all elements from the `flat_hash_set`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  //\n  // NOTE: this operation may shrink the underlying buffer. To avoid shrinking\n  // the underlying buffer call `erase(begin(), end())`.\n  using Base::clear;\n\n  // flat_hash_set::erase()\n  //\n  // Erases elements within the `flat_hash_set`. Erasing does not trigger a\n  // rehash. Overloads are listed below.\n  //\n  // void erase(const_iterator pos):\n  //\n  //   Erases the element at `position` of the `flat_hash_set`, returning\n  //   `void`.\n  //\n  //   NOTE: returning `void` in this case is different than that of STL\n  //   containers in general and `std::unordered_set` in particular (which\n  //   return an iterator to the element following the erased element). If that\n  //   iterator is needed, simply post increment the iterator:\n  //\n  //     set.erase(it++);\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning an\n  //   iterator pointing to `last`. The special case of calling\n  //   `erase(begin(), end())` resets the reserved growth such that if\n  //   `reserve(N)` has previously been called and there has been no intervening\n  //   call to `clear()`, then after calling `erase(begin(), end())`, it is safe\n  //   to assume that inserting N elements will not cause a rehash.\n  //\n  // size_type erase(const key_type& key):\n  //\n  //   Erases the element with the matching key, if it exists, returning the\n  //   number of elements erased (0 or 1).\n  using Base::erase;\n\n  // flat_hash_set::insert()\n  //\n  // Inserts an element of the specified value into the `flat_hash_set`,\n  // returning an iterator pointing to the newly inserted element, provided that\n  // an element with the given key does not already exist. If rehashing occurs\n  // due to the insertion, all iterators are invalidated. Overloads are listed\n  // below.\n  //\n  // std::pair<iterator,bool> insert(const T& value):\n  //\n  //   Inserts a value into the `flat_hash_set`. Returns a pair consisting of an\n  //   iterator to the inserted element (or to the element that prevented the\n  //   insertion) and a bool denoting whether the insertion took place.\n  //\n  // std::pair<iterator,bool> insert(T&& value):\n  //\n  //   Inserts a moveable value into the `flat_hash_set`. Returns a pair\n  //   consisting of an iterator to the inserted element (or to the element that\n  //   prevented the insertion) and a bool denoting whether the insertion took\n  //   place.\n  //\n  // iterator insert(const_iterator hint, const T& value):\n  // iterator insert(const_iterator hint, T&& value):\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element, or to the existing element that prevented the\n  //   insertion.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently, for `flat_hash_set` we guarantee the\n  //   first match is inserted.\n  //\n  // void insert(std::initializer_list<T> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently within the initializer list, for\n  //   `flat_hash_set` we guarantee the first match is inserted.\n  using Base::insert;\n\n  // flat_hash_set::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `flat_hash_set`, provided that no element with the given key\n  // already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace;\n\n  // flat_hash_set::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `flat_hash_set`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search, and only inserts\n  // provided that no element with the given key already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace_hint;\n\n  // flat_hash_set::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the element at the indicated position and returns a node handle\n  //   owning that extracted data.\n  //\n  // node_type extract(const key_type& x):\n  //\n  //   Extracts the element with the key matching the passed key value and\n  //   returns a node handle owning that extracted data. If the `flat_hash_set`\n  //   does not contain an element with a matching key, this function returns an\n  //   empty node handle.\n  using Base::extract;\n\n  // flat_hash_set::merge()\n  //\n  // Extracts elements from a given `source` flat hash set into this\n  // `flat_hash_set`. If the destination `flat_hash_set` already contains an\n  // element with an equivalent key, that element is not extracted.\n  using Base::merge;\n\n  // flat_hash_set::swap(flat_hash_set& other)\n  //\n  // Exchanges the contents of this `flat_hash_set` with those of the `other`\n  // flat hash set.\n  //\n  // All iterators and references on the `flat_hash_set` remain valid, excepting\n  // for the past-the-end iterator, which is invalidated.\n  //\n  // `swap()` requires that the flat hash set's hashing and key equivalence\n  // functions be Swappable, and are exchanged using unqualified calls to\n  // non-member `swap()`. If the set's allocator has\n  // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`\n  // set to `true`, the allocators are also exchanged using an unqualified call\n  // to non-member `swap()`; otherwise, the allocators are not swapped.\n  using Base::swap;\n\n  // flat_hash_set::rehash(count)\n  //\n  // Rehashes the `flat_hash_set`, setting the number of slots to be at least\n  // the passed value. If the new number of slots increases the load factor more\n  // than the current maximum load factor\n  // (`count` < `size()` / `max_load_factor()`), then the new number of slots\n  // will be at least `size()` / `max_load_factor()`.\n  //\n  // To force a rehash, pass rehash(0).\n  //\n  // NOTE: unlike behavior in `std::unordered_set`, references are also\n  // invalidated upon a `rehash()`.\n  using Base::rehash;\n\n  // flat_hash_set::reserve(count)\n  //\n  // Sets the number of slots in the `flat_hash_set` to the number needed to\n  // accommodate at least `count` total elements without exceeding the current\n  // maximum load factor, and may rehash the container if needed. After this\n  // returns, it is guaranteed that `count - size()` elements can be inserted\n  // into the `flat_hash_set` without another rehash.\n  using Base::reserve;\n\n  // flat_hash_set::contains()\n  //\n  // Determines whether an element comparing equal to the given `key` exists\n  // within the `flat_hash_set`, returning `true` if so or `false` otherwise.\n  using Base::contains;\n\n  // flat_hash_set::count(const Key& key) const\n  //\n  // Returns the number of elements comparing equal to the given `key` within\n  // the `flat_hash_set`. note that this function will return either `1` or `0`\n  // since duplicate elements are not allowed within a `flat_hash_set`.\n  using Base::count;\n\n  // flat_hash_set::equal_range()\n  //\n  // Returns a closed range [first, last], defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `flat_hash_set`.\n  using Base::equal_range;\n\n  // flat_hash_set::find()\n  //\n  // Finds an element with the passed `key` within the `flat_hash_set`.\n  using Base::find;\n\n  // flat_hash_set::bucket_count()\n  //\n  // Returns the number of \"buckets\" within the `flat_hash_set`. Note that\n  // because a flat hash set contains all elements within its internal storage,\n  // this value simply equals the current capacity of the `flat_hash_set`.\n  using Base::bucket_count;\n\n  // flat_hash_set::load_factor()\n  //\n  // Returns the current load factor of the `flat_hash_set` (the average number\n  // of slots occupied with a value within the hash set).\n  using Base::load_factor;\n\n  // flat_hash_set::max_load_factor()\n  //\n  // Manages the maximum load factor of the `flat_hash_set`. Overloads are\n  // listed below.\n  //\n  // float flat_hash_set::max_load_factor()\n  //\n  //   Returns the current maximum load factor of the `flat_hash_set`.\n  //\n  // void flat_hash_set::max_load_factor(float ml)\n  //\n  //   Sets the maximum load factor of the `flat_hash_set` to the passed value.\n  //\n  //   NOTE: This overload is provided only for API compatibility with the STL;\n  //   `flat_hash_set` will ignore any set load factor and manage its rehashing\n  //   internally as an implementation detail.\n  using Base::max_load_factor;\n\n  // flat_hash_set::get_allocator()\n  //\n  // Returns the allocator function associated with this `flat_hash_set`.\n  using Base::get_allocator;\n\n  // flat_hash_set::hash_function()\n  //\n  // Returns the hashing function used to hash the keys within this\n  // `flat_hash_set`.\n  using Base::hash_function;\n\n  // flat_hash_set::key_eq()\n  //\n  // Returns the function used for comparing keys equality.\n  using Base::key_eq;\n};\n\n// erase_if(flat_hash_set<>, Pred)\n//\n// Erases all elements that satisfy the predicate `pred` from the container `c`.\n// Returns the number of erased elements.\ntemplate <typename T, typename H, typename E, typename A, typename Predicate>\ntypename flat_hash_set<T, H, E, A>::size_type erase_if(\n    flat_hash_set<T, H, E, A>& c, Predicate pred) {\n  return container_internal::EraseIf(pred, &c);\n}\n\n// swap(flat_hash_set<>, flat_hash_set<>)\n//\n// Swaps the contents of two `flat_hash_set` containers.\n//\n// NOTE: we need to define this function template in order for\n// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we\n// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a\n// derived-to-base conversion, whereas `std::swap` is a function template so\n// `std::swap` will be preferred by compiler.\ntemplate <typename T, typename H, typename E, typename A>\nvoid swap(flat_hash_set<T, H, E, A>& x,\n          flat_hash_set<T, H, E, A>& y) noexcept(noexcept(x.swap(y))) {\n  return x.swap(y);\n}\n\nnamespace container_internal {\n\n// c_for_each_fast(flat_hash_set<>, Function)\n//\n// Container-based version of the <algorithm> `std::for_each()` function to\n// apply a function to a container's elements.\n// There is no guarantees on the order of the function calls.\n// Erasure and/or insertion of elements in the function is not allowed.\ntemplate <typename T, typename H, typename E, typename A, typename Function>\ndecay_t<Function> c_for_each_fast(const flat_hash_set<T, H, E, A>& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename T, typename H, typename E, typename A, typename Function>\ndecay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>& c, Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename T, typename H, typename E, typename A, typename Function>\ndecay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>&& c, Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\n\n}  // namespace container_internal\n\nnamespace container_internal {\n\ntemplate <class T>\nstruct FlatHashSetPolicy {\n  using slot_type = T;\n  using key_type = T;\n  using init_type = T;\n  using constant_iterators = std::true_type;\n\n  using DefaultHash = DefaultHashContainerHash<T>;\n  using DefaultEq = DefaultHashContainerEq<T>;\n  using DefaultAlloc = std::allocator<T>;\n\n  template <class Allocator, class... Args>\n  static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {\n    absl::allocator_traits<Allocator>::construct(*alloc, slot,\n                                                 std::forward<Args>(args)...);\n  }\n\n  // Return std::true_type in case destroy is trivial.\n  template <class Allocator>\n  static auto destroy(Allocator* alloc, slot_type* slot) {\n    absl::allocator_traits<Allocator>::destroy(*alloc, slot);\n    return IsDestructionTrivial<Allocator, slot_type>();\n  }\n\n  static T& element(slot_type* slot) { return *slot; }\n\n  template <class F, class... Args>\n  static decltype(absl::container_internal::DecomposeValue(\n      std::declval<F>(), std::declval<Args>()...))\n  apply(F&& f, Args&&... args) {\n    return absl::container_internal::DecomposeValue(\n        std::forward<F>(f), std::forward<Args>(args)...);\n  }\n\n  static size_t space_used(const T*) { return 0; }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return &TypeErasedApplyToSlotFn<Hash, T, kIsDefault>;\n  }\n};\n}  // namespace container_internal\n\nnamespace container_algorithm_internal {\n\n// Specialization of trait in absl/algorithm/container.h\ntemplate <class Key, class Hash, class KeyEqual, class Allocator>\nstruct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>>\n    : std::true_type {};\n\n}  // namespace container_algorithm_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_FLAT_HASH_SET_H_\n"
  },
  {
    "path": "absl/container/flat_hash_set_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/flat_hash_set.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/hash_container_defaults.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/container/internal/unordered_set_constructor_test.h\"\n#include \"absl/container/internal/unordered_set_lookup_test.h\"\n#include \"absl/container/internal/unordered_set_members_test.h\"\n#include \"absl/container/internal/unordered_set_modifiers_test.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/log/check.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/string_view.h\"\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <ranges>  // NOLINT(build/c++20)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::IsEmpty;\nusing ::testing::Pointee;\nusing ::testing::UnorderedElementsAre;\nusing ::testing::UnorderedElementsAreArray;\n\n// Check that absl::flat_hash_set works in a global constructor.\nstruct BeforeMain {\n  BeforeMain() {\n    absl::flat_hash_set<int> x;\n    x.insert(1);\n    CHECK(!x.contains(0)) << \"x should not contain 0\";\n    CHECK(x.contains(1)) << \"x should contain 1\";\n  }\n};\nconst BeforeMain before_main;\n\ntemplate <class T>\nusing Set =\n    absl::flat_hash_set<T, StatefulTestingHash, StatefulTestingEqual, Alloc<T>>;\n\nusing SetTypes =\n    ::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ConstructorTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, LookupTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, MembersTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ModifiersTest, SetTypes);\n\nTEST(FlatHashSet, EmplaceString) {\n  std::vector<std::string> v = {\"a\", \"b\"};\n  absl::flat_hash_set<absl::string_view> hs(v.begin(), v.end());\n  EXPECT_THAT(hs, UnorderedElementsAreArray(v));\n}\n\nTEST(FlatHashSet, BitfieldArgument) {\n  union {\n    int n : 1;\n  };\n  n = 0;\n  absl::flat_hash_set<int> s = {n};\n  s.insert(n);\n  s.insert(s.end(), n);\n  s.insert({n});\n  s.erase(n);\n  s.count(n);\n  s.prefetch(n);\n  s.find(n);\n  s.contains(n);\n  s.equal_range(n);\n}\n\nTEST(FlatHashSet, MergeExtractInsert) {\n  struct Hash {\n    size_t operator()(const std::unique_ptr<int>& p) const { return *p; }\n  };\n  struct Eq {\n    bool operator()(const std::unique_ptr<int>& a,\n                    const std::unique_ptr<int>& b) const {\n      return *a == *b;\n    }\n  };\n  absl::flat_hash_set<std::unique_ptr<int>, Hash, Eq> set1, set2;\n  set1.insert(absl::make_unique<int>(7));\n  set1.insert(absl::make_unique<int>(17));\n\n  set2.insert(absl::make_unique<int>(7));\n  set2.insert(absl::make_unique<int>(19));\n\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17)));\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(19)));\n\n  set1.merge(set2);\n\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17), Pointee(19)));\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7)));\n\n  auto node = set1.extract(absl::make_unique<int>(7));\n  EXPECT_TRUE(node);\n  EXPECT_THAT(node.value(), Pointee(7));\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(17), Pointee(19)));\n\n  auto insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_FALSE(insert_result.inserted);\n  EXPECT_TRUE(insert_result.node);\n  EXPECT_THAT(insert_result.node.value(), Pointee(7));\n  EXPECT_EQ(**insert_result.position, 7);\n  EXPECT_NE(insert_result.position->get(), insert_result.node.value().get());\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7)));\n\n  node = set1.extract(absl::make_unique<int>(17));\n  EXPECT_TRUE(node);\n  EXPECT_THAT(node.value(), Pointee(17));\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(19)));\n\n  node.value() = absl::make_unique<int>(23);\n\n  insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_TRUE(insert_result.inserted);\n  EXPECT_FALSE(insert_result.node);\n  EXPECT_EQ(**insert_result.position, 23);\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));\n}\n\nbool IsEven(int k) { return k % 2 == 0; }\n\nTEST(FlatHashSet, EraseIf) {\n  // Erase all elements.\n  {\n    flat_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, [](int) { return true; }), 5);\n    EXPECT_THAT(s, IsEmpty());\n  }\n  // Erase no elements.\n  {\n    flat_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, [](int) { return false; }), 0);\n    EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n  }\n  // Erase specific elements.\n  {\n    flat_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, [](int k) { return k % 2 == 1; }), 3);\n    EXPECT_THAT(s, UnorderedElementsAre(2, 4));\n  }\n  // Predicate is function reference.\n  {\n    flat_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, IsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));\n  }\n  // Predicate is function pointer.\n  {\n    flat_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, &IsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));\n  }\n}\n\nTEST(FlatHashSet, CForEach) {\n  using ValueType = std::pair<int, int>;\n  flat_hash_set<ValueType> s;\n  std::vector<ValueType> expected;\n  for (int i = 0; i < 100; ++i) {\n    {\n      SCOPED_TRACE(\"mutable object iteration\");\n      std::vector<ValueType> v;\n      absl::container_internal::c_for_each_fast(\n          s, [&v](const ValueType& p) { v.push_back(p); });\n      ASSERT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const object iteration\");\n      std::vector<ValueType> v;\n      const flat_hash_set<ValueType>& cs = s;\n      absl::container_internal::c_for_each_fast(\n          cs, [&v](const ValueType& p) { v.push_back(p); });\n      ASSERT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"temporary object iteration\");\n      std::vector<ValueType> v;\n      absl::container_internal::c_for_each_fast(\n          flat_hash_set<ValueType>(s),\n          [&v](const ValueType& p) { v.push_back(p); });\n      ASSERT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    s.emplace(i, i);\n    expected.emplace_back(i, i);\n  }\n}\n\nclass PoisonSoo {\n  int64_t data_;\n\n public:\n  explicit PoisonSoo(int64_t d) : data_(d) { SanitizerPoisonObject(&data_); }\n  PoisonSoo(const PoisonSoo& that) : PoisonSoo(*that) {}\n  ~PoisonSoo() { SanitizerUnpoisonObject(&data_); }\n\n  int64_t operator*() const {\n    SanitizerUnpoisonObject(&data_);\n    const int64_t ret = data_;\n    SanitizerPoisonObject(&data_);\n    return ret;\n  }\n  template <typename H>\n  friend H AbslHashValue(H h, const PoisonSoo& pi) {\n    return H::combine(std::move(h), *pi);\n  }\n  bool operator==(const PoisonSoo& rhs) const { return **this == *rhs; }\n};\n\nTEST(FlatHashSet, PoisonSooBasic) {\n  PoisonSoo a(0), b(1);\n  flat_hash_set<PoisonSoo> set;\n  set.insert(a);\n  EXPECT_THAT(set, UnorderedElementsAre(a));\n  set.insert(b);\n  EXPECT_THAT(set, UnorderedElementsAre(a, b));\n  set.erase(a);\n  EXPECT_THAT(set, UnorderedElementsAre(b));\n  set.rehash(0);  // Shrink to SOO.\n  EXPECT_THAT(set, UnorderedElementsAre(b));\n}\n\nTEST(FlatHashSet, PoisonSooMoveConstructSooToSoo) {\n  PoisonSoo a(0);\n  flat_hash_set<PoisonSoo> set;\n  set.insert(a);\n  flat_hash_set<PoisonSoo> set2(std::move(set));\n  EXPECT_THAT(set2, UnorderedElementsAre(a));\n}\n\nTEST(FlatHashSet, PoisonSooAllocMoveConstructSooToSoo) {\n  PoisonSoo a(0);\n  flat_hash_set<PoisonSoo> set;\n  set.insert(a);\n  flat_hash_set<PoisonSoo> set2(std::move(set), std::allocator<PoisonSoo>());\n  EXPECT_THAT(set2, UnorderedElementsAre(a));\n}\n\nTEST(FlatHashSet, PoisonSooMoveAssignFullSooToEmptySoo) {\n  PoisonSoo a(0);\n  flat_hash_set<PoisonSoo> set, set2;\n  set.insert(a);\n  set2 = std::move(set);\n  EXPECT_THAT(set2, UnorderedElementsAre(a));\n}\n\nTEST(FlatHashSet, PoisonSooMoveAssignFullSooToFullSoo) {\n  PoisonSoo a(0), b(1);\n  flat_hash_set<PoisonSoo> set, set2;\n  set.insert(a);\n  set2.insert(b);\n  set2 = std::move(set);\n  EXPECT_THAT(set2, UnorderedElementsAre(a));\n}\n\nTEST(FlatHashSet, FlatHashSetPolicyDestroyReturnsTrue) {\n  EXPECT_TRUE((decltype(FlatHashSetPolicy<int>::destroy<std::allocator<int>>(\n      nullptr, nullptr))()));\n  EXPECT_FALSE(\n      (decltype(FlatHashSetPolicy<int>::destroy<CountingAllocator<int>>(\n          nullptr, nullptr))()));\n  EXPECT_FALSE((decltype(FlatHashSetPolicy<std::unique_ptr<int>>::destroy<\n                         std::allocator<int>>(nullptr, nullptr))()));\n}\n\nstruct HashEqInvalidOnMove {\n  HashEqInvalidOnMove() = default;\n  HashEqInvalidOnMove(const HashEqInvalidOnMove& rhs) = default;\n  HashEqInvalidOnMove(HashEqInvalidOnMove&& rhs) { rhs.moved = true; }\n  HashEqInvalidOnMove& operator=(const HashEqInvalidOnMove& rhs) = default;\n  HashEqInvalidOnMove& operator=(HashEqInvalidOnMove&& rhs) {\n    rhs.moved = true;\n    return *this;\n  }\n\n  size_t operator()(int x) const {\n    CHECK(!moved);\n    return absl::HashOf(x);\n  }\n\n  bool operator()(int x, int y) const {\n    CHECK(!moved);\n    return x == y;\n  }\n\n  bool moved = false;\n};\n\nTEST(FlatHashSet, MovedFromCleared_HashMustBeValid) {\n  flat_hash_set<int, HashEqInvalidOnMove> s1, s2;\n  // Moving the hashtable must not move the hasher because we need to support\n  // this behavior.\n  s2 = std::move(s1);\n  s1.clear();\n  s1.insert(2);\n  EXPECT_THAT(s1, UnorderedElementsAre(2));\n}\n\nTEST(FlatHashSet, MovedFromCleared_EqMustBeValid) {\n  flat_hash_set<int, DefaultHashContainerHash<int>, HashEqInvalidOnMove> s1, s2;\n  // Moving the hashtable must not move the equality functor because we need to\n  // support this behavior.\n  s2 = std::move(s1);\n  s1.clear();\n  s1.insert(2);\n  EXPECT_THAT(s1, UnorderedElementsAre(2));\n}\n\nTEST(FlatHashSet, Equality) {\n  {\n    flat_hash_set<int> s1 = {1, 2, 3};\n    flat_hash_set<int> s2 = {1, 2, 3};\n    EXPECT_EQ(s1, s2);\n  }\n  {\n    flat_hash_set<std::string> s1 = {\"a\", \"b\", \"c\"};\n    flat_hash_set<std::string> s2 = {\"a\", \"b\", \"c\"};\n    EXPECT_EQ(s1, s2);\n  }\n}\n\nclass MoveOnlyInt {\n public:\n  explicit MoveOnlyInt(int value) : value_(value) {}\n\n  MoveOnlyInt(const MoveOnlyInt& other) = delete;\n  MoveOnlyInt& operator=(const MoveOnlyInt& other) = delete;\n\n  MoveOnlyInt(MoveOnlyInt&& other) = default;\n  MoveOnlyInt& operator=(MoveOnlyInt&& other) = default;\n\n  bool operator==(const MoveOnlyInt& other) const {\n    return value_ == other.value_;\n  }\n  bool operator==(int other) const { return value_ == other; }\n\n private:\n  template <typename H>\n  friend H AbslHashValue(H h, const MoveOnlyInt& m) {\n    return H::combine(std::move(h), m.value_);\n  }\n\n  int value_;\n};\n\nTEST(FlatHashSet, MoveOnlyKey) {\n  flat_hash_set<MoveOnlyInt> s;\n  s.insert(MoveOnlyInt(1));\n  s.insert(MoveOnlyInt(2));\n  s.insert(MoveOnlyInt(3));\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3));\n}\n\nTEST(FlatHashSet, IsDefaultHash) {\n  using absl::container_internal::hashtable_debug_internal::\n      HashtableDebugAccess;\n  EXPECT_EQ(HashtableDebugAccess<flat_hash_set<int>>::kIsDefaultHash, true);\n  EXPECT_EQ(HashtableDebugAccess<flat_hash_set<std::string>>::kIsDefaultHash,\n            true);\n\n  struct Hash {\n    size_t operator()(size_t i) const { return i; }\n  };\n  EXPECT_EQ((HashtableDebugAccess<flat_hash_set<size_t, Hash>>::kIsDefaultHash),\n            false);\n}\n\n#if defined(__cpp_lib_containers_ranges) && \\\n    __cpp_lib_containers_ranges >= 202202L\nTEST(FlatHashSet, FromRange) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  absl::flat_hash_set<int> s(std::from_range, v);\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(FlatHashSet, FromRangeWithAllocator) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  absl::flat_hash_set<int, absl::container_internal::hash_default_hash<int>,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<int>>\n      s(std::from_range, v, 0, Alloc<int>());\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(FlatHashSet, FromRangeWithHasherAndAllocator) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  using TestingHash = absl::container_internal::StatefulTestingHash;\n  absl::flat_hash_set<int, TestingHash,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<int>>\n      s(std::from_range, v, 0, TestingHash{}, Alloc<int>());\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n#endif\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/hash_container_defaults.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_HASH_CONTAINER_DEFAULTS_H_\n#define ABSL_CONTAINER_HASH_CONTAINER_DEFAULTS_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_function_defaults.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// DefaultHashContainerHash is a convenience alias for the functor that is used\n// by default by Abseil hash-based (unordered) containers for hashing when\n// `Hash` type argument is not explicitly specified.\n//\n// This type alias can be used by generic code that wants to provide more\n// flexibility for defining underlying containers.\ntemplate <typename T>\nusing DefaultHashContainerHash = absl::container_internal::hash_default_hash<T>;\n\n// DefaultHashContainerEq is a convenience alias for the functor that is used by\n// default by Abseil hash-based (unordered) containers for equality check when\n// `Eq` type argument is not explicitly specified.\n//\n// This type alias can be used by generic code that wants to provide more\n// flexibility for defining underlying containers.\ntemplate <typename T>\nusing DefaultHashContainerEq = absl::container_internal::hash_default_eq<T>;\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_HASH_CONTAINER_DEFAULTS_H_\n"
  },
  {
    "path": "absl/container/inlined_vector.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: inlined_vector.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains the declaration and definition of an \"inlined\n// vector\" which behaves in an equivalent fashion to a `std::vector`, except\n// that storage for small sequences of the vector are provided inline without\n// requiring any heap allocation.\n//\n// An `absl::InlinedVector<T, N>` specifies the default capacity `N` as one of\n// its template parameters. Instances where `size() <= N` hold contained\n// elements in inline space. Typically `N` is very small so that sequences that\n// are expected to be short do not require allocations.\n//\n// An `absl::InlinedVector` does not usually require a specific allocator. If\n// the inlined vector grows beyond its initial constraints, it will need to\n// allocate (as any normal `std::vector` would). This is usually performed with\n// the default allocator (defined as `std::allocator<T>`). Optionally, a custom\n// allocator type may be specified as `A` in `absl::InlinedVector<T, N, A>`.\n\n#ifndef ABSL_CONTAINER_INLINED_VECTOR_H_\n#define ABSL_CONTAINER_INLINED_VECTOR_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdlib>\n#include <cstring>\n#include <initializer_list>\n#include <iterator>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/algorithm/algorithm.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/iterator_traits.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/container/internal/inlined_vector.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n// -----------------------------------------------------------------------------\n// InlinedVector\n// -----------------------------------------------------------------------------\n//\n// An `absl::InlinedVector` is designed to be a drop-in replacement for\n// `std::vector` for use cases where the vector's size is sufficiently small\n// that it can be inlined. If the inlined vector does grow beyond its estimated\n// capacity, it will trigger an initial allocation on the heap, and will behave\n// as a `std::vector`. The API of the `absl::InlinedVector` within this file is\n// designed to cover the same API footprint as covered by `std::vector`.\ntemplate <typename T, size_t N, typename A = std::allocator<T>>\nclass ABSL_ATTRIBUTE_WARN_UNUSED InlinedVector {\n  static_assert(N > 0, \"`absl::InlinedVector` requires an inlined capacity.\");\n\n  using Storage = inlined_vector_internal::Storage<T, N, A>;\n\n  template <typename TheA>\n  using AllocatorTraits = inlined_vector_internal::AllocatorTraits<TheA>;\n  template <typename TheA>\n  using MoveIterator = inlined_vector_internal::MoveIterator<TheA>;\n  template <typename TheA>\n  using IsMoveAssignOk = inlined_vector_internal::IsMoveAssignOk<TheA>;\n\n  template <typename TheA, typename Iterator>\n  using IteratorValueAdapter =\n      inlined_vector_internal::IteratorValueAdapter<TheA, Iterator>;\n  template <typename TheA>\n  using CopyValueAdapter = inlined_vector_internal::CopyValueAdapter<TheA>;\n  template <typename TheA>\n  using DefaultValueAdapter =\n      inlined_vector_internal::DefaultValueAdapter<TheA>;\n\n  template <typename Iterator>\n  using EnableIfAtLeastForwardIterator = std::enable_if_t<\n      base_internal::IsAtLeastForwardIterator<Iterator>::value, int>;\n  template <typename Iterator>\n  using DisableIfAtLeastForwardIterator = std::enable_if_t<\n      !base_internal::IsAtLeastForwardIterator<Iterator>::value, int>;\n\n  using MemcpyPolicy = typename Storage::MemcpyPolicy;\n  using ElementwiseAssignPolicy = typename Storage::ElementwiseAssignPolicy;\n  using ElementwiseConstructPolicy =\n      typename Storage::ElementwiseConstructPolicy;\n  using MoveAssignmentPolicy = typename Storage::MoveAssignmentPolicy;\n\n public:\n  using allocator_type = A;\n  using value_type = inlined_vector_internal::ValueType<A>;\n  using pointer = inlined_vector_internal::Pointer<A>;\n  using const_pointer = inlined_vector_internal::ConstPointer<A>;\n  using size_type = inlined_vector_internal::SizeType<A>;\n  using difference_type = inlined_vector_internal::DifferenceType<A>;\n  using reference = inlined_vector_internal::Reference<A>;\n  using const_reference = inlined_vector_internal::ConstReference<A>;\n  using iterator = inlined_vector_internal::Iterator<A>;\n  using const_iterator = inlined_vector_internal::ConstIterator<A>;\n  using reverse_iterator = inlined_vector_internal::ReverseIterator<A>;\n  using const_reverse_iterator =\n      inlined_vector_internal::ConstReverseIterator<A>;\n\n  // ---------------------------------------------------------------------------\n  // InlinedVector Constructors and Destructor\n  // ---------------------------------------------------------------------------\n\n  // Creates an empty inlined vector with a value-initialized allocator.\n  InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {}\n\n  // Creates an empty inlined vector with a copy of `allocator`.\n  explicit InlinedVector(const allocator_type& allocator) noexcept\n      : storage_(allocator) {}\n\n  // Creates an inlined vector with `n` copies of `value_type()`.\n  explicit InlinedVector(size_type n,\n                         const allocator_type& allocator = allocator_type())\n      : storage_(allocator) {\n    storage_.Initialize(DefaultValueAdapter<A>(), n);\n  }\n\n  // Creates an inlined vector with `n` copies of `v`.\n  InlinedVector(size_type n, const_reference v,\n                const allocator_type& allocator = allocator_type())\n      : storage_(allocator) {\n    storage_.Initialize(CopyValueAdapter<A>(std::addressof(v)), n);\n  }\n\n  // Creates an inlined vector with copies of the elements of `list`.\n  InlinedVector(std::initializer_list<value_type> list,\n                const allocator_type& allocator = allocator_type())\n      : InlinedVector(list.begin(), list.end(), allocator) {}\n\n  // Creates an inlined vector with elements constructed from the provided\n  // forward iterator range [`first`, `last`).\n  //\n  // NOTE: the `enable_if` prevents ambiguous interpretation between a call to\n  // this constructor with two integral arguments and a call to the above\n  // `InlinedVector(size_type, const_reference)` constructor.\n  template <typename ForwardIterator,\n            EnableIfAtLeastForwardIterator<ForwardIterator> = 0>\n  InlinedVector(ForwardIterator first, ForwardIterator last,\n                const allocator_type& allocator = allocator_type())\n      : storage_(allocator) {\n    storage_.Initialize(IteratorValueAdapter<A, ForwardIterator>(first),\n                        static_cast<size_t>(std::distance(first, last)));\n  }\n\n  // Creates an inlined vector with elements constructed from the provided input\n  // iterator range [`first`, `last`).\n  template <typename InputIterator,\n            DisableIfAtLeastForwardIterator<InputIterator> = 0>\n  InlinedVector(InputIterator first, InputIterator last,\n                const allocator_type& allocator = allocator_type())\n      : storage_(allocator) {\n    std::copy(first, last, std::back_inserter(*this));\n  }\n\n  // Creates an inlined vector by copying the contents of `other` using\n  // `other`'s allocator.\n  InlinedVector(const InlinedVector& other)\n      : InlinedVector(other, other.storage_.GetAllocator()) {}\n\n  // Creates an inlined vector by copying the contents of `other` using the\n  // provided `allocator`.\n  InlinedVector(const InlinedVector& other, const allocator_type& allocator)\n      : storage_(allocator) {\n    // Fast path: if the other vector is empty, there's nothing for us to do.\n    if (other.empty()) {\n      return;\n    }\n\n    // Fast path: if the value type is trivially copy constructible, we know the\n    // allocator doesn't do anything fancy, and there is nothing on the heap\n    // then we know it is legal for us to simply memcpy the other vector's\n    // inlined bytes to form our copy of its elements.\n    if (absl::is_trivially_copy_constructible<value_type>::value &&\n        std::is_same<A, std::allocator<value_type>>::value &&\n        !other.storage_.GetIsAllocated()) {\n      storage_.MemcpyFrom(other.storage_);\n      return;\n    }\n\n    storage_.InitFrom(other.storage_);\n  }\n\n  // Creates an inlined vector by moving in the contents of `other` without\n  // allocating. If `other` contains allocated memory, the newly-created inlined\n  // vector will take ownership of that memory. However, if `other` does not\n  // contain allocated memory, the newly-created inlined vector will perform\n  // element-wise move construction of the contents of `other`.\n  //\n  // NOTE: since no allocation is performed for the inlined vector in either\n  // case, the `noexcept(...)` specification depends on whether moving the\n  // underlying objects can throw. It is assumed assumed that...\n  //  a) move constructors should only throw due to allocation failure.\n  //  b) if `value_type`'s move constructor allocates, it uses the same\n  //     allocation function as the inlined vector's allocator.\n  // Thus, the move constructor is non-throwing if the allocator is non-throwing\n  // or `value_type`'s move constructor is specified as `noexcept`.\n  InlinedVector(InlinedVector&& other) noexcept(\n      absl::allocator_is_nothrow<allocator_type>::value ||\n      std::is_nothrow_move_constructible<value_type>::value)\n      : storage_(other.storage_.GetAllocator()) {\n    // Fast path: if the value type can be trivially relocated (i.e. moved from\n    // and destroyed), and we know the allocator doesn't do anything fancy, then\n    // it's safe for us to simply adopt the contents of the storage for `other`\n    // and remove its own reference to them. It's as if we had individually\n    // move-constructed each value and then destroyed the original.\n    if (absl::is_trivially_relocatable<value_type>::value &&\n        std::is_same<A, std::allocator<value_type>>::value) {\n      storage_.MemcpyFrom(other.storage_);\n      other.storage_.SetInlinedSize(0);\n      return;\n    }\n\n    // Fast path: if the other vector is on the heap, we can simply take over\n    // its allocation.\n    if (other.storage_.GetIsAllocated()) {\n      storage_.SetAllocation({other.storage_.GetAllocatedData(),\n                              other.storage_.GetAllocatedCapacity()});\n      storage_.SetAllocatedSize(other.storage_.GetSize());\n\n      other.storage_.SetInlinedSize(0);\n      return;\n    }\n\n    // Otherwise we must move each element individually.\n    IteratorValueAdapter<A, MoveIterator<A>> other_values(\n        MoveIterator<A>(other.storage_.GetInlinedData()));\n\n    inlined_vector_internal::ConstructElements<A>(\n        storage_.GetAllocator(), storage_.GetInlinedData(), other_values,\n        other.storage_.GetSize());\n\n    storage_.SetInlinedSize(other.storage_.GetSize());\n  }\n\n  // Creates an inlined vector by moving in the contents of `other` with a copy\n  // of `allocator`.\n  //\n  // NOTE: if `other`'s allocator is not equal to `allocator`, even if `other`\n  // contains allocated memory, this move constructor will still allocate. Since\n  // allocation is performed, this constructor can only be `noexcept` if the\n  // specified allocator is also `noexcept`.\n  InlinedVector(\n      InlinedVector&& other,\n      const allocator_type&\n          allocator) noexcept(absl::allocator_is_nothrow<allocator_type>::value)\n      : storage_(allocator) {\n    // Fast path: if the value type can be trivially relocated (i.e. moved from\n    // and destroyed), and we know the allocator doesn't do anything fancy, then\n    // it's safe for us to simply adopt the contents of the storage for `other`\n    // and remove its own reference to them. It's as if we had individually\n    // move-constructed each value and then destroyed the original.\n    if (absl::is_trivially_relocatable<value_type>::value &&\n        std::is_same<A, std::allocator<value_type>>::value) {\n      storage_.MemcpyFrom(other.storage_);\n      other.storage_.SetInlinedSize(0);\n      return;\n    }\n\n    // Fast path: if the other vector is on the heap and shared the same\n    // allocator, we can simply take over its allocation.\n    if ((storage_.GetAllocator() == other.storage_.GetAllocator()) &&\n        other.storage_.GetIsAllocated()) {\n      storage_.SetAllocation({other.storage_.GetAllocatedData(),\n                              other.storage_.GetAllocatedCapacity()});\n      storage_.SetAllocatedSize(other.storage_.GetSize());\n\n      other.storage_.SetInlinedSize(0);\n      return;\n    }\n\n    // Otherwise we must move each element individually.\n    storage_.Initialize(\n        IteratorValueAdapter<A, MoveIterator<A>>(MoveIterator<A>(other.data())),\n        other.size());\n  }\n\n  ~InlinedVector() {}\n\n  // ---------------------------------------------------------------------------\n  // InlinedVector Member Accessors\n  // ---------------------------------------------------------------------------\n\n  // `InlinedVector::empty()`\n  //\n  // Returns whether the inlined vector contains no elements.\n  bool empty() const noexcept { return !size(); }\n\n  // `InlinedVector::size()`\n  //\n  // Returns the number of elements in the inlined vector.\n  size_type size() const noexcept { return storage_.GetSize(); }\n\n  // `InlinedVector::max_size()`\n  //\n  // Returns the maximum number of elements the inlined vector can hold.\n  size_type max_size() const noexcept {\n    // One bit of the size storage is used to indicate whether the inlined\n    // vector contains allocated memory. As a result, the maximum size that the\n    // inlined vector can express is the minimum of the limit of how many\n    // objects we can allocate and std::numeric_limits<size_type>::max() / 2.\n    return (std::min)(AllocatorTraits<A>::max_size(storage_.GetAllocator()),\n                      (std::numeric_limits<size_type>::max)() / 2);\n  }\n\n  // `InlinedVector::capacity()`\n  //\n  // Returns the number of elements that could be stored in the inlined vector\n  // without requiring a reallocation.\n  //\n  // NOTE: for most inlined vectors, `capacity()` should be equal to the\n  // template parameter `N`. For inlined vectors which exceed this capacity,\n  // they will no longer be inlined and `capacity()` will equal the capactity of\n  // the allocated memory.\n  size_type capacity() const noexcept {\n    return storage_.GetIsAllocated() ? storage_.GetAllocatedCapacity()\n                                     : storage_.GetInlinedCapacity();\n  }\n\n  // `InlinedVector::data()`\n  //\n  // Returns a `pointer` to the elements of the inlined vector. This pointer\n  // can be used to access and modify the contained elements.\n  //\n  // NOTE: only elements within [`data()`, `data() + size()`) are valid.\n  pointer data() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return storage_.GetIsAllocated() ? storage_.GetAllocatedData()\n                                     : storage_.GetInlinedData();\n  }\n\n  // Overload of `InlinedVector::data()` that returns a `const_pointer` to the\n  // elements of the inlined vector. This pointer can be used to access but not\n  // modify the contained elements.\n  //\n  // NOTE: only elements within [`data()`, `data() + size()`) are valid.\n  const_pointer data() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return storage_.GetIsAllocated() ? storage_.GetAllocatedData()\n                                     : storage_.GetInlinedData();\n  }\n\n  // `InlinedVector::operator[](...)`\n  //\n  // Returns a `reference` to the `i`th element of the inlined vector.\n  reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(i < size());\n    return data()[i];\n  }\n\n  // Overload of `InlinedVector::operator[](...)` that returns a\n  // `const_reference` to the `i`th element of the inlined vector.\n  const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(i < size());\n    return data()[i];\n  }\n\n  // `InlinedVector::at(...)`\n  //\n  // Returns a `reference` to the `i`th element of the inlined vector.\n  //\n  // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,\n  // in both debug and non-debug builds, `std::out_of_range` will be thrown.\n  reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ABSL_PREDICT_FALSE(i >= size())) {\n      ThrowStdOutOfRange(\"`InlinedVector::at(size_type)` failed bounds check\");\n    }\n    return data()[i];\n  }\n\n  // Overload of `InlinedVector::at(...)` that returns a `const_reference` to\n  // the `i`th element of the inlined vector.\n  //\n  // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,\n  // in both debug and non-debug builds, `std::out_of_range` will be thrown.\n  const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ABSL_PREDICT_FALSE(i >= size())) {\n      ThrowStdOutOfRange(\n          \"`InlinedVector::at(size_type) const` failed bounds check\");\n    }\n    return data()[i];\n  }\n\n  // `InlinedVector::front()`\n  //\n  // Returns a `reference` to the first element of the inlined vector.\n  reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[0];\n  }\n\n  // Overload of `InlinedVector::front()` that returns a `const_reference` to\n  // the first element of the inlined vector.\n  const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[0];\n  }\n\n  // `InlinedVector::back()`\n  //\n  // Returns a `reference` to the last element of the inlined vector.\n  reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[size() - 1];\n  }\n\n  // Overload of `InlinedVector::back()` that returns a `const_reference` to the\n  // last element of the inlined vector.\n  const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(!empty());\n    return data()[size() - 1];\n  }\n\n  // `InlinedVector::begin()`\n  //\n  // Returns an `iterator` to the beginning of the inlined vector.\n  iterator begin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }\n\n  // Overload of `InlinedVector::begin()` that returns a `const_iterator` to\n  // the beginning of the inlined vector.\n  const_iterator begin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return data();\n  }\n\n  // `InlinedVector::end()`\n  //\n  // Returns an `iterator` to the end of the inlined vector.\n  iterator end() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return data() + size();\n  }\n\n  // Overload of `InlinedVector::end()` that returns a `const_iterator` to the\n  // end of the inlined vector.\n  const_iterator end() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return data() + size();\n  }\n\n  // `InlinedVector::cbegin()`\n  //\n  // Returns a `const_iterator` to the beginning of the inlined vector.\n  const_iterator cbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return begin();\n  }\n\n  // `InlinedVector::cend()`\n  //\n  // Returns a `const_iterator` to the end of the inlined vector.\n  const_iterator cend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return end();\n  }\n\n  // `InlinedVector::rbegin()`\n  //\n  // Returns a `reverse_iterator` from the end of the inlined vector.\n  reverse_iterator rbegin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return reverse_iterator(end());\n  }\n\n  // Overload of `InlinedVector::rbegin()` that returns a\n  // `const_reverse_iterator` from the end of the inlined vector.\n  const_reverse_iterator rbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_reverse_iterator(end());\n  }\n\n  // `InlinedVector::rend()`\n  //\n  // Returns a `reverse_iterator` from the beginning of the inlined vector.\n  reverse_iterator rend() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return reverse_iterator(begin());\n  }\n\n  // Overload of `InlinedVector::rend()` that returns a `const_reverse_iterator`\n  // from the beginning of the inlined vector.\n  const_reverse_iterator rend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_reverse_iterator(begin());\n  }\n\n  // `InlinedVector::crbegin()`\n  //\n  // Returns a `const_reverse_iterator` from the end of the inlined vector.\n  const_reverse_iterator crbegin() const noexcept\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return rbegin();\n  }\n\n  // `InlinedVector::crend()`\n  //\n  // Returns a `const_reverse_iterator` from the beginning of the inlined\n  // vector.\n  const_reverse_iterator crend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return rend();\n  }\n\n  // `InlinedVector::get_allocator()`\n  //\n  // Returns a copy of the inlined vector's allocator.\n  allocator_type get_allocator() const { return storage_.GetAllocator(); }\n\n  // ---------------------------------------------------------------------------\n  // InlinedVector Member Mutators\n  // ---------------------------------------------------------------------------\n\n  // `InlinedVector::operator=(...)`\n  //\n  // Replaces the elements of the inlined vector with copies of the elements of\n  // `list`.\n  InlinedVector& operator=(std::initializer_list<value_type> list) {\n    assign(list.begin(), list.end());\n\n    return *this;\n  }\n\n  // Overload of `InlinedVector::operator=(...)` that replaces the elements of\n  // the inlined vector with copies of the elements of `other`.\n  InlinedVector& operator=(const InlinedVector& other) {\n    if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {\n      const_pointer other_data = other.data();\n      assign(other_data, other_data + other.size());\n    }\n\n    return *this;\n  }\n\n  // Overload of `InlinedVector::operator=(...)` that moves the elements of\n  // `other` into the inlined vector.\n  //\n  // NOTE: as a result of calling this overload, `other` is left in a valid but\n  // unspecified state.\n  InlinedVector& operator=(InlinedVector&& other) {\n    if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {\n      MoveAssignment(MoveAssignmentPolicy{}, std::move(other));\n    }\n\n    return *this;\n  }\n\n  // `InlinedVector::assign(...)`\n  //\n  // Replaces the contents of the inlined vector with `n` copies of `v`.\n  void assign(size_type n, const_reference v) {\n    storage_.Assign(CopyValueAdapter<A>(std::addressof(v)), n);\n  }\n\n  // Overload of `InlinedVector::assign(...)` that replaces the contents of the\n  // inlined vector with copies of the elements of `list`.\n  void assign(std::initializer_list<value_type> list) {\n    assign(list.begin(), list.end());\n  }\n\n  // Overload of `InlinedVector::assign(...)` to replace the contents of the\n  // inlined vector with the range [`first`, `last`).\n  //\n  // NOTE: this overload is for iterators that are \"forward\" category or better.\n  template <typename ForwardIterator,\n            EnableIfAtLeastForwardIterator<ForwardIterator> = 0>\n  void assign(ForwardIterator first, ForwardIterator last) {\n    storage_.Assign(IteratorValueAdapter<A, ForwardIterator>(first),\n                    static_cast<size_t>(std::distance(first, last)));\n  }\n\n  // Overload of `InlinedVector::assign(...)` to replace the contents of the\n  // inlined vector with the range [`first`, `last`).\n  //\n  // NOTE: this overload is for iterators that are \"input\" category.\n  template <typename InputIterator,\n            DisableIfAtLeastForwardIterator<InputIterator> = 0>\n  void assign(InputIterator first, InputIterator last) {\n    size_type i = 0;\n    for (; i < size() && first != last; ++i, static_cast<void>(++first)) {\n      data()[i] = *first;\n    }\n\n    erase(data() + i, data() + size());\n    std::copy(first, last, std::back_inserter(*this));\n  }\n\n  // `InlinedVector::resize(...)`\n  //\n  // Resizes the inlined vector to contain `n` elements.\n  //\n  // NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`\n  // is larger than `size()`, new elements are value-initialized.\n  void resize(size_type n) {\n    ABSL_HARDENING_ASSERT(n <= max_size());\n    storage_.Resize(DefaultValueAdapter<A>(), n);\n  }\n\n  // Overload of `InlinedVector::resize(...)` that resizes the inlined vector to\n  // contain `n` elements.\n  //\n  // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`\n  // is larger than `size()`, new elements are copied-constructed from `v`.\n  void resize(size_type n, const_reference v) {\n    ABSL_HARDENING_ASSERT(n <= max_size());\n    storage_.Resize(CopyValueAdapter<A>(std::addressof(v)), n);\n  }\n\n  // `InlinedVector::insert(...)`\n  //\n  // Inserts a copy of `v` at `pos`, returning an `iterator` to the newly\n  // inserted element.\n  iterator insert(const_iterator pos,\n                  const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return emplace(pos, v);\n  }\n\n  // Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using\n  // move semantics, returning an `iterator` to the newly inserted element.\n  iterator insert(const_iterator pos,\n                  value_type&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return emplace(pos, std::move(v));\n  }\n\n  // Overload of `InlinedVector::insert(...)` that inserts `n` contiguous copies\n  // of `v` starting at `pos`, returning an `iterator` pointing to the first of\n  // the newly inserted elements.\n  iterator insert(const_iterator pos, size_type n,\n                  const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(pos >= begin());\n    ABSL_HARDENING_ASSERT(pos <= end());\n\n    if (ABSL_PREDICT_TRUE(n != 0)) {\n      value_type dealias = v;\n      // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2\n      // It appears that GCC thinks that since `pos` is a const pointer and may\n      // point to uninitialized memory at this point, a warning should be\n      // issued. But `pos` is actually only used to compute an array index to\n      // write to.\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n#endif\n      return storage_.Insert(pos, CopyValueAdapter<A>(std::addressof(dealias)),\n                             n);\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n    } else {\n      return const_cast<iterator>(pos);\n    }\n  }\n\n  // Overload of `InlinedVector::insert(...)` that inserts copies of the\n  // elements of `list` starting at `pos`, returning an `iterator` pointing to\n  // the first of the newly inserted elements.\n  iterator insert(const_iterator pos, std::initializer_list<value_type> list)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return insert(pos, list.begin(), list.end());\n  }\n\n  // Overload of `InlinedVector::insert(...)` that inserts the range [`first`,\n  // `last`) starting at `pos`, returning an `iterator` pointing to the first\n  // of the newly inserted elements.\n  //\n  // NOTE: this overload is for iterators that are \"forward\" category or better.\n  template <typename ForwardIterator,\n            EnableIfAtLeastForwardIterator<ForwardIterator> = 0>\n  iterator insert(const_iterator pos, ForwardIterator first,\n                  ForwardIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(pos >= begin());\n    ABSL_HARDENING_ASSERT(pos <= end());\n\n    if (ABSL_PREDICT_TRUE(first != last)) {\n      return storage_.Insert(\n          pos, IteratorValueAdapter<A, ForwardIterator>(first),\n          static_cast<size_type>(std::distance(first, last)));\n    } else {\n      return const_cast<iterator>(pos);\n    }\n  }\n\n  // Overload of `InlinedVector::insert(...)` that inserts the range [`first`,\n  // `last`) starting at `pos`, returning an `iterator` pointing to the first\n  // of the newly inserted elements.\n  //\n  // NOTE: this overload is for iterators that are \"input\" category.\n  template <typename InputIterator,\n            DisableIfAtLeastForwardIterator<InputIterator> = 0>\n  iterator insert(const_iterator pos, InputIterator first,\n                  InputIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(pos >= begin());\n    ABSL_HARDENING_ASSERT(pos <= end());\n\n    size_type index = static_cast<size_type>(std::distance(cbegin(), pos));\n    for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {\n      insert(data() + i, *first);\n    }\n\n    return iterator(data() + index);\n  }\n\n  // `InlinedVector::emplace(...)`\n  //\n  // Constructs and inserts an element using `args...` in the inlined vector at\n  // `pos`, returning an `iterator` pointing to the newly emplaced element.\n  template <typename... Args>\n  iterator emplace(const_iterator pos,\n                   Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(pos >= begin());\n    ABSL_HARDENING_ASSERT(pos <= end());\n\n    value_type dealias(std::forward<Args>(args)...);\n    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2\n    // It appears that GCC thinks that since `pos` is a const pointer and may\n    // point to uninitialized memory at this point, a warning should be\n    // issued. But `pos` is actually only used to compute an array index to\n    // write to.\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n#endif\n    return storage_.Insert(pos,\n                           IteratorValueAdapter<A, MoveIterator<A>>(\n                               MoveIterator<A>(std::addressof(dealias))),\n                           1);\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n  }\n\n  // `InlinedVector::emplace_back(...)`\n  //\n  // Constructs and inserts an element using `args...` in the inlined vector at\n  // `end()`, returning a `reference` to the newly emplaced element.\n  template <typename... Args>\n  reference emplace_back(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return storage_.EmplaceBack(std::forward<Args>(args)...);\n  }\n\n  // `InlinedVector::push_back(...)`\n  //\n  // Inserts a copy of `v` in the inlined vector at `end()`.\n  void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }\n\n  // Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()`\n  // using move semantics.\n  void push_back(value_type&& v) {\n    static_cast<void>(emplace_back(std::move(v)));\n  }\n\n  // `InlinedVector::pop_back()`\n  //\n  // Destroys the element at `back()`, reducing the size by `1`.\n  void pop_back() noexcept {\n    ABSL_HARDENING_ASSERT(!empty());\n\n    AllocatorTraits<A>::destroy(storage_.GetAllocator(), data() + (size() - 1));\n    storage_.SubtractSize(1);\n  }\n\n  // `InlinedVector::erase(...)`\n  //\n  // Erases the element at `pos`, returning an `iterator` pointing to where the\n  // erased element was located.\n  //\n  // NOTE: may return `end()`, which is not dereferenceable.\n  iterator erase(const_iterator pos) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(pos >= begin());\n    ABSL_HARDENING_ASSERT(pos < end());\n\n    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2\n    // It appears that GCC thinks that since `pos` is a const pointer and may\n    // point to uninitialized memory at this point, a warning should be\n    // issued. But `pos` is actually only used to compute an array index to\n    // write to.\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n#pragma GCC diagnostic ignored \"-Wuninitialized\"\n#endif\n    return storage_.Erase(pos, pos + 1);\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n  }\n\n  // Overload of `InlinedVector::erase(...)` that erases every element in the\n  // range [`from`, `to`), returning an `iterator` pointing to where the first\n  // erased element was located.\n  //\n  // NOTE: may return `end()`, which is not dereferenceable.\n  iterator erase(const_iterator from,\n                 const_iterator to) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    ABSL_HARDENING_ASSERT(from >= begin());\n    ABSL_HARDENING_ASSERT(from <= to);\n    ABSL_HARDENING_ASSERT(to <= end());\n\n    if (ABSL_PREDICT_TRUE(from != to)) {\n      return storage_.Erase(from, to);\n    } else {\n      return const_cast<iterator>(from);\n    }\n  }\n\n  // `InlinedVector::clear()`\n  //\n  // Destroys all elements in the inlined vector, setting the size to `0` and\n  // preserving capacity.\n  void clear() noexcept {\n    inlined_vector_internal::DestroyAdapter<A>::DestroyElements(\n        storage_.GetAllocator(), data(), size());\n    storage_.SetSize(0);\n  }\n\n  // `InlinedVector::reserve(...)`\n  //\n  // Ensures that there is enough room for at least `n` elements.\n  void reserve(size_type n) { storage_.Reserve(n); }\n\n  // `InlinedVector::shrink_to_fit()`\n  //\n  // Attempts to reduce memory usage by moving elements to (or keeping elements\n  // in) the smallest available buffer sufficient for containing `size()`\n  // elements.\n  //\n  // If `size()` is sufficiently small, the elements will be moved into (or kept\n  // in) the inlined space.\n  void shrink_to_fit() {\n    if (storage_.GetIsAllocated()) {\n      storage_.ShrinkToFit();\n    }\n  }\n\n  // `InlinedVector::swap(...)`\n  //\n  // Swaps the contents of the inlined vector with `other`.\n  void swap(InlinedVector& other) {\n    if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {\n      storage_.Swap(std::addressof(other.storage_));\n    }\n  }\n\n private:\n  template <typename H, typename TheT, size_t TheN, typename TheA>\n  friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);\n\n  void MoveAssignment(MemcpyPolicy, InlinedVector&& other) {\n    // Assumption check: we shouldn't be told to use memcpy to implement move\n    // assignment unless we have trivially destructible elements and an\n    // allocator that does nothing fancy.\n    static_assert(absl::is_trivially_destructible<value_type>::value, \"\");\n    static_assert(std::is_same<A, std::allocator<value_type>>::value, \"\");\n\n    // Throw away our existing heap allocation, if any. There is no need to\n    // destroy the existing elements one by one because we know they are\n    // trivially destructible.\n    storage_.DeallocateIfAllocated();\n\n    // Adopt the other vector's inline elements or heap allocation.\n    storage_.MemcpyFrom(other.storage_);\n    other.storage_.SetInlinedSize(0);\n  }\n\n  // Destroy our existing elements, if any, and adopt the heap-allocated\n  // elements of the other vector.\n  //\n  // REQUIRES: other.storage_.GetIsAllocated()\n  void DestroyExistingAndAdopt(InlinedVector&& other) {\n    ABSL_HARDENING_ASSERT(other.storage_.GetIsAllocated());\n\n    inlined_vector_internal::DestroyAdapter<A>::DestroyElements(\n        storage_.GetAllocator(), data(), size());\n    storage_.DeallocateIfAllocated();\n\n    storage_.MemcpyFrom(other.storage_);\n    other.storage_.SetInlinedSize(0);\n  }\n\n  void MoveAssignment(ElementwiseAssignPolicy, InlinedVector&& other) {\n    // Fast path: if the other vector is on the heap then we don't worry about\n    // actually move-assigning each element. Instead we only throw away our own\n    // existing elements and adopt the heap allocation of the other vector.\n    if (other.storage_.GetIsAllocated()) {\n      DestroyExistingAndAdopt(std::move(other));\n      return;\n    }\n\n    storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(\n                        MoveIterator<A>(other.storage_.GetInlinedData())),\n                    other.size());\n  }\n\n  void MoveAssignment(ElementwiseConstructPolicy, InlinedVector&& other) {\n    // Fast path: if the other vector is on the heap then we don't worry about\n    // actually move-assigning each element. Instead we only throw away our own\n    // existing elements and adopt the heap allocation of the other vector.\n    if (other.storage_.GetIsAllocated()) {\n      DestroyExistingAndAdopt(std::move(other));\n      return;\n    }\n\n    inlined_vector_internal::DestroyAdapter<A>::DestroyElements(\n        storage_.GetAllocator(), data(), size());\n    storage_.DeallocateIfAllocated();\n\n    IteratorValueAdapter<A, MoveIterator<A>> other_values(\n        MoveIterator<A>(other.storage_.GetInlinedData()));\n    inlined_vector_internal::ConstructElements<A>(\n        storage_.GetAllocator(), storage_.GetInlinedData(), other_values,\n        other.storage_.GetSize());\n    storage_.SetInlinedSize(other.storage_.GetSize());\n  }\n\n  Storage storage_;\n};\n\n// -----------------------------------------------------------------------------\n// InlinedVector Non-Member Functions\n// -----------------------------------------------------------------------------\n\n// `swap(...)`\n//\n// Swaps the contents of two inlined vectors.\ntemplate <typename T, size_t N, typename A>\nvoid swap(absl::InlinedVector<T, N, A>& a,\n          absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {\n  a.swap(b);\n}\n\n// `operator==(...)`\n//\n// Tests for value-equality of two inlined vectors.\ntemplate <typename T, size_t N, typename A>\nbool operator==(const absl::InlinedVector<T, N, A>& a,\n                const absl::InlinedVector<T, N, A>& b) {\n  auto a_data = a.data();\n  auto b_data = b.data();\n  return std::equal(a_data, a_data + a.size(), b_data, b_data + b.size());\n}\n\n// `operator!=(...)`\n//\n// Tests for value-inequality of two inlined vectors.\ntemplate <typename T, size_t N, typename A>\nbool operator!=(const absl::InlinedVector<T, N, A>& a,\n                const absl::InlinedVector<T, N, A>& b) {\n  return !(a == b);\n}\n\n// `operator<(...)`\n//\n// Tests whether the value of an inlined vector is less than the value of\n// another inlined vector using a lexicographical comparison algorithm.\ntemplate <typename T, size_t N, typename A>\nbool operator<(const absl::InlinedVector<T, N, A>& a,\n               const absl::InlinedVector<T, N, A>& b) {\n  auto a_data = a.data();\n  auto b_data = b.data();\n  return std::lexicographical_compare(a_data, a_data + a.size(), b_data,\n                                      b_data + b.size());\n}\n\n// `operator>(...)`\n//\n// Tests whether the value of an inlined vector is greater than the value of\n// another inlined vector using a lexicographical comparison algorithm.\ntemplate <typename T, size_t N, typename A>\nbool operator>(const absl::InlinedVector<T, N, A>& a,\n               const absl::InlinedVector<T, N, A>& b) {\n  return b < a;\n}\n\n// `operator<=(...)`\n//\n// Tests whether the value of an inlined vector is less than or equal to the\n// value of another inlined vector using a lexicographical comparison algorithm.\ntemplate <typename T, size_t N, typename A>\nbool operator<=(const absl::InlinedVector<T, N, A>& a,\n                const absl::InlinedVector<T, N, A>& b) {\n  return !(b < a);\n}\n\n// `operator>=(...)`\n//\n// Tests whether the value of an inlined vector is greater than or equal to the\n// value of another inlined vector using a lexicographical comparison algorithm.\ntemplate <typename T, size_t N, typename A>\nbool operator>=(const absl::InlinedVector<T, N, A>& a,\n                const absl::InlinedVector<T, N, A>& b) {\n  return !(a < b);\n}\n\n// `AbslHashValue(...)`\n//\n// Provides `absl::Hash` support for `absl::InlinedVector`. It is uncommon to\n// call this directly.\ntemplate <typename H, typename T, size_t N, typename A>\nH AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) {\n  return H::combine_contiguous(std::move(h), a.data(), a.size());\n}\n\ntemplate <typename T, size_t N, typename A, typename Predicate>\nconstexpr typename InlinedVector<T, N, A>::size_type erase_if(\n    InlinedVector<T, N, A>& v, Predicate pred) {\n  const auto it = std::remove_if(v.begin(), v.end(), std::move(pred));\n  const auto removed = static_cast<typename InlinedVector<T, N, A>::size_type>(\n      std::distance(it, v.end()));\n  v.erase(it, v.end());\n  return removed;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INLINED_VECTOR_H_\n"
  },
  {
    "path": "absl/container/inlined_vector_benchmark.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <array>\n#include <string>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_InlinedVectorFill(benchmark::State& state) {\n  const int len = state.range(0);\n  absl::InlinedVector<int, 8> v;\n  v.reserve(len);\n  for (auto _ : state) {\n    v.resize(0);  // Use resize(0) as InlinedVector releases storage on clear().\n    for (int i = 0; i < len; ++i) {\n      v.push_back(i);\n    }\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_InlinedVectorFill)->Range(1, 256);\n\nvoid BM_InlinedVectorFillRange(benchmark::State& state) {\n  const int len = state.range(0);\n  const std::vector<int> src(len, len);\n  absl::InlinedVector<int, 8> v;\n  v.reserve(len);\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(src);\n    v.assign(src.begin(), src.end());\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_InlinedVectorFillRange)->Range(1, 256);\n\nvoid BM_StdVectorFill(benchmark::State& state) {\n  const int len = state.range(0);\n  std::vector<int> v;\n  v.reserve(len);\n  for (auto _ : state) {\n    v.clear();\n    for (int i = 0; i < len; ++i) {\n      v.push_back(i);\n    }\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_StdVectorFill)->Range(1, 256);\n\n// The purpose of the next two benchmarks is to verify that\n// absl::InlinedVector is efficient when moving is more efficient than\n// copying. To do so, we use strings that are larger than the short\n// string optimization.\nbool StringRepresentedInline(std::string s) {\n  const char* chars = s.data();\n  std::string s1 = std::move(s);\n  return s1.data() != chars;\n}\n\nint GetNonShortStringOptimizationSize() {\n  for (int i = 24; i <= 192; i *= 2) {\n    if (!StringRepresentedInline(std::string(i, 'A'))) {\n      return i;\n    }\n  }\n  ABSL_RAW_LOG(\n      FATAL,\n      \"Failed to find a string larger than the short string optimization\");\n  return -1;\n}\n\nvoid BM_InlinedVectorFillString(benchmark::State& state) {\n  const int len = state.range(0);\n  const int no_sso = GetNonShortStringOptimizationSize();\n  std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),\n                            std::string(no_sso, 'C'), std::string(no_sso, 'D')};\n\n  for (auto _ : state) {\n    absl::InlinedVector<std::string, 8> v;\n    for (int i = 0; i < len; i++) {\n      v.push_back(strings[i & 3]);\n    }\n  }\n  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);\n}\nBENCHMARK(BM_InlinedVectorFillString)->Range(0, 1024);\n\nvoid BM_StdVectorFillString(benchmark::State& state) {\n  const int len = state.range(0);\n  const int no_sso = GetNonShortStringOptimizationSize();\n  std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),\n                            std::string(no_sso, 'C'), std::string(no_sso, 'D')};\n\n  for (auto _ : state) {\n    std::vector<std::string> v;\n    for (int i = 0; i < len; i++) {\n      v.push_back(strings[i & 3]);\n    }\n  }\n  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);\n}\nBENCHMARK(BM_StdVectorFillString)->Range(0, 1024);\n\nstruct Buffer {  // some arbitrary structure for benchmarking.\n  char* base;\n  int length;\n  int capacity;\n  void* user_data;\n};\n\nvoid BM_InlinedVectorAssignments(benchmark::State& state) {\n  const int len = state.range(0);\n  using BufferVec = absl::InlinedVector<Buffer, 2>;\n\n  BufferVec src;\n  src.resize(len);\n\n  BufferVec dst;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(dst);\n    benchmark::DoNotOptimize(src);\n    dst = src;\n  }\n}\nBENCHMARK(BM_InlinedVectorAssignments)\n    ->Arg(0)\n    ->Arg(1)\n    ->Arg(2)\n    ->Arg(3)\n    ->Arg(4)\n    ->Arg(20);\n\nvoid BM_CreateFromContainer(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::InlinedVector<int, 4> src{1, 2, 3};\n    benchmark::DoNotOptimize(src);\n    absl::InlinedVector<int, 4> dst(std::move(src));\n    benchmark::DoNotOptimize(dst);\n  }\n}\nBENCHMARK(BM_CreateFromContainer);\n\nstruct LargeCopyableOnly {\n  LargeCopyableOnly() : d(1024, 17) {}\n  LargeCopyableOnly(const LargeCopyableOnly& o) = default;\n  LargeCopyableOnly& operator=(const LargeCopyableOnly& o) = default;\n\n  std::vector<int> d;\n};\n\nstruct LargeCopyableSwappable {\n  LargeCopyableSwappable() : d(1024, 17) {}\n\n  LargeCopyableSwappable(const LargeCopyableSwappable& o) = default;\n\n  LargeCopyableSwappable& operator=(LargeCopyableSwappable o) {\n    using std::swap;\n    swap(*this, o);\n    return *this;\n  }\n\n  friend void swap(LargeCopyableSwappable& a, LargeCopyableSwappable& b) {\n    using std::swap;\n    swap(a.d, b.d);\n  }\n\n  std::vector<int> d;\n};\n\nstruct LargeCopyableMovable {\n  LargeCopyableMovable() : d(1024, 17) {}\n  // Use implicitly defined copy and move.\n\n  std::vector<int> d;\n};\n\nstruct LargeCopyableMovableSwappable {\n  LargeCopyableMovableSwappable() : d(1024, 17) {}\n  LargeCopyableMovableSwappable(const LargeCopyableMovableSwappable& o) =\n      default;\n  LargeCopyableMovableSwappable(LargeCopyableMovableSwappable&& o) = default;\n\n  LargeCopyableMovableSwappable& operator=(LargeCopyableMovableSwappable o) {\n    using std::swap;\n    swap(*this, o);\n    return *this;\n  }\n  LargeCopyableMovableSwappable& operator=(LargeCopyableMovableSwappable&& o) =\n      default;\n\n  friend void swap(LargeCopyableMovableSwappable& a,\n                   LargeCopyableMovableSwappable& b) {\n    using std::swap;\n    swap(a.d, b.d);\n  }\n\n  std::vector<int> d;\n};\n\ntemplate <typename ElementType>\nvoid BM_SwapElements(benchmark::State& state) {\n  const int len = state.range(0);\n  using Vec = absl::InlinedVector<ElementType, 32>;\n  Vec a(len);\n  Vec b;\n  for (auto _ : state) {\n    using std::swap;\n    benchmark::DoNotOptimize(a);\n    benchmark::DoNotOptimize(b);\n    swap(a, b);\n  }\n}\nBENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableOnly)->Range(0, 1024);\nBENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableSwappable)->Range(0, 1024);\nBENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableMovable)->Range(0, 1024);\nBENCHMARK_TEMPLATE(BM_SwapElements, LargeCopyableMovableSwappable)\n    ->Range(0, 1024);\n\n// The following benchmark is meant to track the efficiency of the vector size\n// as a function of stored type via the benchmark label. It is not meant to\n// output useful sizeof operator performance. The loop is a dummy operation\n// to fulfill the requirement of running the benchmark.\ntemplate <typename VecType>\nvoid BM_Sizeof(benchmark::State& state) {\n  int size = 0;\n  for (auto _ : state) {\n    VecType vec;\n    size = sizeof(vec);\n  }\n  state.SetLabel(absl::StrCat(\"sz=\", size));\n}\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 1>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 4>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 7>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<char, 8>);\n\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 1>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 4>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 7>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<int, 8>);\n\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 1>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 4>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 7>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<void*, 8>);\n\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 1>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 4>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 7>);\nBENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 8>);\n\nvoid BM_InlinedVectorIndexInlined(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v[4]);\n  }\n}\nBENCHMARK(BM_InlinedVectorIndexInlined);\n\nvoid BM_InlinedVectorIndexExternal(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v[4]);\n  }\n}\nBENCHMARK(BM_InlinedVectorIndexExternal);\n\nvoid BM_StdVectorIndex(benchmark::State& state) {\n  std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v[4]);\n  }\n}\nBENCHMARK(BM_StdVectorIndex);\n\nvoid BM_InlinedVectorDataInlined(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.data());\n  }\n}\nBENCHMARK(BM_InlinedVectorDataInlined);\n\nvoid BM_InlinedVectorDataExternal(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.data());\n  }\n  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));\n}\nBENCHMARK(BM_InlinedVectorDataExternal);\n\nvoid BM_StdVectorData(benchmark::State& state) {\n  std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.data());\n  }\n  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));\n}\nBENCHMARK(BM_StdVectorData);\n\nvoid BM_InlinedVectorSizeInlined(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.size());\n  }\n}\nBENCHMARK(BM_InlinedVectorSizeInlined);\n\nvoid BM_InlinedVectorSizeExternal(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.size());\n  }\n}\nBENCHMARK(BM_InlinedVectorSizeExternal);\n\nvoid BM_StdVectorSize(benchmark::State& state) {\n  std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.size());\n  }\n}\nBENCHMARK(BM_StdVectorSize);\n\nvoid BM_InlinedVectorEmptyInlined(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.empty());\n  }\n}\nBENCHMARK(BM_InlinedVectorEmptyInlined);\n\nvoid BM_InlinedVectorEmptyExternal(benchmark::State& state) {\n  absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.empty());\n  }\n}\nBENCHMARK(BM_InlinedVectorEmptyExternal);\n\nvoid BM_StdVectorEmpty(benchmark::State& state) {\n  std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(v);\n    benchmark::DoNotOptimize(v.empty());\n  }\n}\nBENCHMARK(BM_StdVectorEmpty);\n\nconstexpr size_t kInlinedCapacity = 4;\nconstexpr size_t kLargeSize = kInlinedCapacity * 2;\nconstexpr size_t kSmallSize = kInlinedCapacity / 2;\nconstexpr size_t kBatchSize = 100;\n\n#define ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_FunctionTemplate, T) \\\n  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize);        \\\n  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize)\n\n#define ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_FunctionTemplate, T)      \\\n  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize, kLargeSize); \\\n  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize, kSmallSize); \\\n  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize, kLargeSize); \\\n  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize, kSmallSize)\n\ntemplate <typename T>\nusing InlVec = absl::InlinedVector<T, kInlinedCapacity>;\n\nstruct TrivialType {\n  size_t val;\n};\n\nclass NontrivialType {\n public:\n  ABSL_ATTRIBUTE_NOINLINE NontrivialType() : val_() {\n    benchmark::DoNotOptimize(*this);\n  }\n\n  ABSL_ATTRIBUTE_NOINLINE NontrivialType(const NontrivialType& other)\n      : val_(other.val_) {\n    benchmark::DoNotOptimize(*this);\n  }\n\n  ABSL_ATTRIBUTE_NOINLINE NontrivialType& operator=(\n      const NontrivialType& other) {\n    val_ = other.val_;\n    benchmark::DoNotOptimize(*this);\n    return *this;\n  }\n\n  ABSL_ATTRIBUTE_NOINLINE ~NontrivialType() noexcept {\n    benchmark::DoNotOptimize(*this);\n  }\n\n private:\n  size_t val_;\n};\n\ntemplate <typename T, typename PrepareVecFn, typename TestVecFn>\nvoid BatchedBenchmark(benchmark::State& state, PrepareVecFn prepare_vec,\n                      TestVecFn test_vec) {\n  std::array<InlVec<T>, kBatchSize> vector_batch{};\n\n  while (state.KeepRunningBatch(kBatchSize)) {\n    // Prepare batch\n    state.PauseTiming();\n    for (size_t i = 0; i < kBatchSize; ++i) {\n      prepare_vec(vector_batch.data() + i, i);\n    }\n    benchmark::DoNotOptimize(vector_batch);\n    state.ResumeTiming();\n\n    // Test batch\n    for (size_t i = 0; i < kBatchSize; ++i) {\n      test_vec(vector_batch.data() + i, i);\n    }\n  }\n}\n\ntemplate <typename T, size_t ToSize>\nvoid BM_ConstructFromSize(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  auto size = ToSize;\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },\n      /* test_vec = */\n      [&](void* ptr, size_t) {\n        benchmark::DoNotOptimize(size);\n        ::new (ptr) VecT(size);\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, NontrivialType);\n\ntemplate <typename T, size_t ToSize>\nvoid BM_ConstructFromSizeRef(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  auto size = ToSize;\n  auto ref = T();\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },\n      /* test_vec = */\n      [&](void* ptr, size_t) {\n        benchmark::DoNotOptimize(size);\n        benchmark::DoNotOptimize(ref);\n        ::new (ptr) VecT(size, ref);\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, NontrivialType);\n\ntemplate <typename T, size_t ToSize>\nvoid BM_ConstructFromRange(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  std::array<T, ToSize> arr{};\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },\n      /* test_vec = */\n      [&](void* ptr, size_t) {\n        benchmark::DoNotOptimize(arr);\n        ::new (ptr) VecT(arr.begin(), arr.end());\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, NontrivialType);\n\ntemplate <typename T, size_t ToSize>\nvoid BM_ConstructFromCopy(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  VecT other_vec(ToSize);\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) { vec->~VecT(); },\n      /* test_vec = */\n      [&](void* ptr, size_t) {\n        benchmark::DoNotOptimize(other_vec);\n        ::new (ptr) VecT(other_vec);\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, NontrivialType);\n\ntemplate <typename T, size_t ToSize>\nvoid BM_ConstructFromMove(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  std::array<VecT, kBatchSize> vector_batch{};\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [&](InlVec<T>* vec, size_t i) {\n        vector_batch[i].clear();\n        vector_batch[i].resize(ToSize);\n        vec->~VecT();\n      },\n      /* test_vec = */\n      [&](void* ptr, size_t i) {\n        benchmark::DoNotOptimize(vector_batch[i]);\n        ::new (ptr) VecT(std::move(vector_batch[i]));\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, NontrivialType);\n\n// Measure cost of copy-constructor+destructor.\nvoid BM_CopyTrivial(benchmark::State& state) {\n  const int n = state.range(0);\n  InlVec<int64_t> src(n);\n  for (auto s : state) {\n    InlVec<int64_t> copy(src);\n    benchmark::DoNotOptimize(copy);\n  }\n}\nBENCHMARK(BM_CopyTrivial)->Arg(0)->Arg(1)->Arg(kLargeSize);\n\n// Measure cost of copy-constructor+destructor.\nvoid BM_CopyNonTrivial(benchmark::State& state) {\n  const int n = state.range(0);\n  InlVec<InlVec<int64_t>> src(n);\n  for (auto s : state) {\n    InlVec<InlVec<int64_t>> copy(src);\n    benchmark::DoNotOptimize(copy);\n  }\n}\nBENCHMARK(BM_CopyNonTrivial)->Arg(0)->Arg(1)->Arg(kLargeSize);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_AssignSizeRef(benchmark::State& state) {\n  auto size = ToSize;\n  auto ref = T();\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t) {\n        benchmark::DoNotOptimize(size);\n        benchmark::DoNotOptimize(ref);\n        vec->assign(size, ref);\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignSizeRef, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignSizeRef, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_AssignRange(benchmark::State& state) {\n  std::array<T, ToSize> arr{};\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t) {\n        benchmark::DoNotOptimize(arr);\n        vec->assign(arr.begin(), arr.end());\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignRange, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignRange, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_AssignFromCopy(benchmark::State& state) {\n  InlVec<T> other_vec(ToSize);\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t) {\n        benchmark::DoNotOptimize(other_vec);\n        *vec = other_vec;\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromCopy, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromCopy, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_AssignFromMove(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  std::array<VecT, kBatchSize> vector_batch{};\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [&](InlVec<T>* vec, size_t i) {\n        vector_batch[i].clear();\n        vector_batch[i].resize(ToSize);\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t i) {\n        benchmark::DoNotOptimize(vector_batch[i]);\n        *vec = std::move(vector_batch[i]);\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromMove, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromMove, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_ResizeSize(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [](InlVec<T>* vec, size_t) { vec->resize(ToSize); });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSize, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSize, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_ResizeSizeRef(benchmark::State& state) {\n  auto t = T();\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t) {\n        benchmark::DoNotOptimize(t);\n        vec->resize(ToSize, t);\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSizeRef, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSizeRef, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_InsertSizeRef(benchmark::State& state) {\n  auto t = T();\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t) {\n        benchmark::DoNotOptimize(t);\n        auto* pos = vec->data() + (vec->size() / 2);\n        vec->insert(pos, t);\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertSizeRef, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertSizeRef, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_InsertRange(benchmark::State& state) {\n  InlVec<T> other_vec(ToSize);\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t) {\n        benchmark::DoNotOptimize(other_vec);\n        auto* pos = vec->data() + (vec->size() / 2);\n        vec->insert(pos, other_vec.begin(), other_vec.end());\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertRange, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertRange, NontrivialType);\n\ntemplate <typename T, size_t FromSize>\nvoid BM_EmplaceBack(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [](InlVec<T>* vec, size_t) { vec->emplace_back(); });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EmplaceBack, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EmplaceBack, NontrivialType);\n\ntemplate <typename T, size_t FromSize>\nvoid BM_PopBack(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [](InlVec<T>* vec, size_t) { vec->pop_back(); });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_PopBack, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_PopBack, NontrivialType);\n\ntemplate <typename T, size_t FromSize>\nvoid BM_EraseOne(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [](InlVec<T>* vec, size_t) {\n        auto* pos = vec->data() + (vec->size() / 2);\n        vec->erase(pos);\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseOne, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseOne, NontrivialType);\n\ntemplate <typename T, size_t FromSize>\nvoid BM_EraseRange(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [](InlVec<T>* vec, size_t) {\n        auto* pos = vec->data() + (vec->size() / 2);\n        vec->erase(pos, pos + 1);\n      });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseRange, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseRange, NontrivialType);\n\ntemplate <typename T, size_t FromSize>\nvoid BM_Clear(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },\n      /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->clear(); });\n}\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, TrivialType);\nABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToCapacity>\nvoid BM_Reserve(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [](InlVec<T>* vec, size_t) { vec->reserve(ToCapacity); });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Reserve, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Reserve, NontrivialType);\n\ntemplate <typename T, size_t FromCapacity, size_t ToCapacity>\nvoid BM_ShrinkToFit(benchmark::State& state) {\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [](InlVec<T>* vec, size_t) {\n        vec->clear();\n        vec->resize(ToCapacity);\n        vec->reserve(FromCapacity);\n      },\n      /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->shrink_to_fit(); });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ShrinkToFit, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ShrinkToFit, NontrivialType);\n\ntemplate <typename T, size_t FromSize, size_t ToSize>\nvoid BM_Swap(benchmark::State& state) {\n  using VecT = InlVec<T>;\n  std::array<VecT, kBatchSize> vector_batch{};\n  BatchedBenchmark<T>(\n      state,\n      /* prepare_vec = */\n      [&](InlVec<T>* vec, size_t i) {\n        vector_batch[i].clear();\n        vector_batch[i].resize(ToSize);\n        vec->resize(FromSize);\n      },\n      /* test_vec = */\n      [&](InlVec<T>* vec, size_t i) {\n        using std::swap;\n        benchmark::DoNotOptimize(vector_batch[i]);\n        swap(*vec, vector_batch[i]);\n      });\n}\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Swap, TrivialType);\nABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Swap, NontrivialType);\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/inlined_vector_exception_safety_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/inlined_vector.h\"\n\n#include \"absl/base/config.h\"\n\n#if defined(ABSL_HAVE_EXCEPTIONS)\n\n#include <array>\n#include <initializer_list>\n#include <iterator>\n#include <memory>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/exception_safety_testing.h\"\n\nnamespace {\n\nconstexpr size_t kInlinedCapacity = 4;\nconstexpr size_t kLargeSize = kInlinedCapacity * 2;\nconstexpr size_t kSmallSize = kInlinedCapacity / 2;\n\nusing Thrower = testing::ThrowingValue<>;\nusing MovableThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;\nusing ThrowAlloc = testing::ThrowingAllocator<Thrower>;\n\nusing ThrowerVec = absl::InlinedVector<Thrower, kInlinedCapacity>;\nusing MovableThrowerVec = absl::InlinedVector<MovableThrower, kInlinedCapacity>;\n\nusing ThrowAllocThrowerVec =\n    absl::InlinedVector<Thrower, kInlinedCapacity, ThrowAlloc>;\nusing ThrowAllocMovableThrowerVec =\n    absl::InlinedVector<MovableThrower, kInlinedCapacity, ThrowAlloc>;\n\n// In GCC, if an element of a `std::initializer_list` throws during construction\n// the elements that were constructed before it are not destroyed. This causes\n// incorrect exception safety test failures. Thus, `testing::nothrow_ctor` is\n// required. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66139\n#define ABSL_INTERNAL_MAKE_INIT_LIST(T, N)                     \\\n  (N > kInlinedCapacity                                        \\\n       ? std::initializer_list<T>{T(0, testing::nothrow_ctor), \\\n                                  T(1, testing::nothrow_ctor), \\\n                                  T(2, testing::nothrow_ctor), \\\n                                  T(3, testing::nothrow_ctor), \\\n                                  T(4, testing::nothrow_ctor), \\\n                                  T(5, testing::nothrow_ctor), \\\n                                  T(6, testing::nothrow_ctor), \\\n                                  T(7, testing::nothrow_ctor)} \\\n                                                               \\\n       : std::initializer_list<T>{T(0, testing::nothrow_ctor), \\\n                                  T(1, testing::nothrow_ctor)})\nstatic_assert(kLargeSize == 8, \"Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)\");\nstatic_assert(kSmallSize == 2, \"Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)\");\n\ntemplate <typename TheVecT, size_t... TheSizes>\nclass TestParams {\n public:\n  using VecT = TheVecT;\n  constexpr static size_t GetSizeAt(size_t i) { return kSizes[1 + i]; }\n\n private:\n  constexpr static size_t kSizes[1 + sizeof...(TheSizes)] = {1, TheSizes...};\n};\n\nusing NoSizeTestParams =\n    ::testing::Types<TestParams<ThrowerVec>, TestParams<MovableThrowerVec>,\n                     TestParams<ThrowAllocThrowerVec>,\n                     TestParams<ThrowAllocMovableThrowerVec>>;\n\nusing OneSizeTestParams =\n    ::testing::Types<TestParams<ThrowerVec, kLargeSize>,\n                     TestParams<ThrowerVec, kSmallSize>,\n                     TestParams<MovableThrowerVec, kLargeSize>,\n                     TestParams<MovableThrowerVec, kSmallSize>,\n                     TestParams<ThrowAllocThrowerVec, kLargeSize>,\n                     TestParams<ThrowAllocThrowerVec, kSmallSize>,\n                     TestParams<ThrowAllocMovableThrowerVec, kLargeSize>,\n                     TestParams<ThrowAllocMovableThrowerVec, kSmallSize>>;\n\nusing TwoSizeTestParams = ::testing::Types<\n    TestParams<ThrowerVec, kLargeSize, kLargeSize>,\n    TestParams<ThrowerVec, kLargeSize, kSmallSize>,\n    TestParams<ThrowerVec, kSmallSize, kLargeSize>,\n    TestParams<ThrowerVec, kSmallSize, kSmallSize>,\n    TestParams<MovableThrowerVec, kLargeSize, kLargeSize>,\n    TestParams<MovableThrowerVec, kLargeSize, kSmallSize>,\n    TestParams<MovableThrowerVec, kSmallSize, kLargeSize>,\n    TestParams<MovableThrowerVec, kSmallSize, kSmallSize>,\n    TestParams<ThrowAllocThrowerVec, kLargeSize, kLargeSize>,\n    TestParams<ThrowAllocThrowerVec, kLargeSize, kSmallSize>,\n    TestParams<ThrowAllocThrowerVec, kSmallSize, kLargeSize>,\n    TestParams<ThrowAllocThrowerVec, kSmallSize, kSmallSize>,\n    TestParams<ThrowAllocMovableThrowerVec, kLargeSize, kLargeSize>,\n    TestParams<ThrowAllocMovableThrowerVec, kLargeSize, kSmallSize>,\n    TestParams<ThrowAllocMovableThrowerVec, kSmallSize, kLargeSize>,\n    TestParams<ThrowAllocMovableThrowerVec, kSmallSize, kSmallSize>>;\n\ntemplate <typename>\nstruct NoSizeTest : ::testing::Test {};\nTYPED_TEST_SUITE(NoSizeTest, NoSizeTestParams);\n\ntemplate <typename>\nstruct OneSizeTest : ::testing::Test {};\nTYPED_TEST_SUITE(OneSizeTest, OneSizeTestParams);\n\ntemplate <typename>\nstruct TwoSizeTest : ::testing::Test {};\nTYPED_TEST_SUITE(TwoSizeTest, TwoSizeTestParams);\n\ntemplate <typename VecT>\nbool InlinedVectorInvariants(VecT* vec) {\n  if (*vec != *vec) return false;\n  if (vec->size() > vec->capacity()) return false;\n  if (vec->size() > vec->max_size()) return false;\n  if (vec->capacity() > vec->max_size()) return false;\n  if (vec->data() != std::addressof(vec->at(0))) return false;\n  if (vec->data() != vec->begin()) return false;\n  if (*vec->data() != *vec->begin()) return false;\n  if (vec->begin() > vec->end()) return false;\n  if ((vec->end() - vec->begin()) != vec->size()) return false;\n  if (std::distance(vec->begin(), vec->end()) != vec->size()) return false;\n  return true;\n}\n\n// Function that always returns false is correct, but refactoring is required\n// for clarity. It's needed to express that, as a contract, certain operations\n// should not throw at all. Execution of this function means an exception was\n// thrown and thus the test should fail.\n// TODO(johnsoncj): Add `testing::NoThrowGuarantee` to the framework\ntemplate <typename VecT>\nbool NoThrowGuarantee(VecT* /* vec */) {\n  return false;\n}\n\nTYPED_TEST(NoSizeTest, DefaultConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using allocator_type = typename VecT::allocator_type;\n\n  testing::TestThrowingCtor<VecT>();\n\n  testing::TestThrowingCtor<VecT>(allocator_type{});\n}\n\nTYPED_TEST(OneSizeTest, SizeConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using allocator_type = typename VecT::allocator_type;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  testing::TestThrowingCtor<VecT>(size);\n\n  testing::TestThrowingCtor<VecT>(size, allocator_type{});\n}\n\nTYPED_TEST(OneSizeTest, SizeRefConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  using allocator_type = typename VecT::allocator_type;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  testing::TestThrowingCtor<VecT>(size, value_type{});\n\n  testing::TestThrowingCtor<VecT>(size, value_type{}, allocator_type{});\n}\n\nTYPED_TEST(OneSizeTest, InitializerListConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  using allocator_type = typename VecT::allocator_type;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  testing::TestThrowingCtor<VecT>(\n      ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size));\n\n  testing::TestThrowingCtor<VecT>(\n      ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size), allocator_type{});\n}\n\nTYPED_TEST(OneSizeTest, RangeConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  using allocator_type = typename VecT::allocator_type;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  std::array<value_type, size> arr{};\n\n  testing::TestThrowingCtor<VecT>(arr.begin(), arr.end());\n\n  testing::TestThrowingCtor<VecT>(arr.begin(), arr.end(), allocator_type{});\n}\n\nTYPED_TEST(OneSizeTest, CopyConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using allocator_type = typename VecT::allocator_type;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  VecT other_vec{size};\n\n  testing::TestThrowingCtor<VecT>(other_vec);\n\n  testing::TestThrowingCtor<VecT>(other_vec, allocator_type{});\n}\n\nTYPED_TEST(OneSizeTest, MoveConstructor) {\n  using VecT = typename TypeParam::VecT;\n  using allocator_type = typename VecT::allocator_type;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  if (!absl::allocator_is_nothrow<allocator_type>::value) {\n    testing::TestThrowingCtor<VecT>(VecT{size});\n\n    testing::TestThrowingCtor<VecT>(VecT{size}, allocator_type{});\n  }\n}\n\nTYPED_TEST(TwoSizeTest, Assign) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  constexpr static auto from_size = TypeParam::GetSizeAt(0);\n  constexpr static auto to_size = TypeParam::GetSizeAt(1);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{from_size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    *vec = ABSL_INTERNAL_MAKE_INIT_LIST(value_type, to_size);\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    VecT other_vec{to_size};\n    *vec = other_vec;\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    VecT other_vec{to_size};\n    *vec = std::move(other_vec);\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    value_type val{};\n    vec->assign(to_size, val);\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    vec->assign(ABSL_INTERNAL_MAKE_INIT_LIST(value_type, to_size));\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    std::array<value_type, to_size> arr{};\n    vec->assign(arr.begin(), arr.end());\n  }));\n}\n\nTYPED_TEST(TwoSizeTest, Resize) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  constexpr static auto from_size = TypeParam::GetSizeAt(0);\n  constexpr static auto to_size = TypeParam::GetSizeAt(1);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{from_size})\n                    .WithContracts(InlinedVectorInvariants<VecT>,\n                                   testing::strong_guarantee);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    vec->resize(to_size);  //\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    vec->resize(to_size, value_type{});  //\n  }));\n}\n\nTYPED_TEST(OneSizeTest, Insert) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  constexpr static auto from_size = TypeParam::GetSizeAt(0);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{from_size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    vec->insert(it, value_type{});\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    vec->insert(it, value_type{});\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->end();\n    vec->insert(it, value_type{});\n  }));\n}\n\nTYPED_TEST(TwoSizeTest, Insert) {\n  using VecT = typename TypeParam::VecT;\n  using value_type = typename VecT::value_type;\n  constexpr static auto from_size = TypeParam::GetSizeAt(0);\n  constexpr static auto count = TypeParam::GetSizeAt(1);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{from_size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    vec->insert(it, count, value_type{});\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    vec->insert(it, count, value_type{});\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->end();\n    vec->insert(it, count, value_type{});\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count));\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count));\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->end();\n    vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count));\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    std::array<value_type, count> arr{};\n    vec->insert(it, arr.begin(), arr.end());\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    std::array<value_type, count> arr{};\n    vec->insert(it, arr.begin(), arr.end());\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->end();\n    std::array<value_type, count> arr{};\n    vec->insert(it, arr.begin(), arr.end());\n  }));\n}\n\nTYPED_TEST(OneSizeTest, EmplaceBack) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  // For testing calls to `emplace_back(...)` that reallocate.\n  VecT full_vec{size};\n  full_vec.resize(full_vec.capacity());\n\n  // For testing calls to `emplace_back(...)` that don't reallocate.\n  VecT nonfull_vec{size};\n  nonfull_vec.reserve(size + 1);\n\n  auto tester = testing::MakeExceptionSafetyTester().WithContracts(\n      InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.WithInitialValue(nonfull_vec).Test([](VecT* vec) {\n    vec->emplace_back();\n  }));\n\n  EXPECT_TRUE(tester.WithInitialValue(full_vec).Test(\n      [](VecT* vec) { vec->emplace_back(); }));\n}\n\nTYPED_TEST(OneSizeTest, PopBack) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{size})\n                    .WithContracts(NoThrowGuarantee<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    vec->pop_back();  //\n  }));\n}\n\nTYPED_TEST(OneSizeTest, Erase) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    vec->erase(it);\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    vec->erase(it);\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() - 1);\n    vec->erase(it);\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    vec->erase(it, it);\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    vec->erase(it, it);\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() - 1);\n    vec->erase(it, it);\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin();\n    vec->erase(it, it + 1);\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() / 2);\n    vec->erase(it, it + 1);\n  }));\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    auto it = vec->begin() + (vec->size() - 1);\n    vec->erase(it, it + 1);\n  }));\n}\n\nTYPED_TEST(OneSizeTest, Clear) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{size})\n                    .WithContracts(NoThrowGuarantee<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    vec->clear();  //\n  }));\n}\n\nTYPED_TEST(TwoSizeTest, Reserve) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto from_size = TypeParam::GetSizeAt(0);\n  constexpr static auto to_capacity = TypeParam::GetSizeAt(1);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{from_size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) { vec->reserve(to_capacity); }));\n}\n\nTYPED_TEST(OneSizeTest, ShrinkToFit) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto size = TypeParam::GetSizeAt(0);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    vec->shrink_to_fit();  //\n  }));\n}\n\nTYPED_TEST(TwoSizeTest, Swap) {\n  using VecT = typename TypeParam::VecT;\n  constexpr static auto from_size = TypeParam::GetSizeAt(0);\n  constexpr static auto to_size = TypeParam::GetSizeAt(1);\n\n  auto tester = testing::MakeExceptionSafetyTester()\n                    .WithInitialValue(VecT{from_size})\n                    .WithContracts(InlinedVectorInvariants<VecT>);\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    VecT other_vec{to_size};\n    vec->swap(other_vec);\n  }));\n\n  EXPECT_TRUE(tester.Test([](VecT* vec) {\n    using std::swap;\n    VecT other_vec{to_size};\n    swap(*vec, other_vec);\n  }));\n}\n\n}  // namespace\n\n#endif  // defined(ABSL_HAVE_EXCEPTIONS)\n"
  },
  {
    "path": "absl/container/inlined_vector_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/inlined_vector.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <forward_list>\n#include <iterator>\n#include <list>\n#include <memory>\n#include <scoped_allocator>\n#include <sstream>\n#include <stdexcept>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/exception_testing.h\"\n#include \"absl/base/internal/iterator_traits_test_helper.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/options.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/log/check.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\n\nusing absl::container_internal::CountingAllocator;\nusing absl::test_internal::CopyableMovableInstance;\nusing absl::test_internal::CopyableOnlyInstance;\nusing absl::test_internal::InstanceTracker;\nusing testing::AllOf;\nusing testing::Each;\nusing testing::ElementsAre;\nusing testing::ElementsAreArray;\nusing testing::IsEmpty;\nusing testing::Eq;\nusing testing::Gt;\nusing testing::Pointee;\nusing testing::Pointwise;\nusing testing::PrintToString;\nusing testing::SizeIs;\n\nusing IntVec = absl::InlinedVector<int, 8>;\n\nMATCHER_P(CapacityIs, n, \"\") {\n  return testing::ExplainMatchResult(n, arg.capacity(), result_listener);\n}\n\nMATCHER_P(ValueIs, e, \"\") {\n  return testing::ExplainMatchResult(e, arg.value(), result_listener);\n}\n\n// TODO(bsamwel): Add support for movable-only types.\n\n// Test fixture for typed tests on BaseCountedInstance derived classes, see\n// test_instance_tracker.h.\ntemplate <typename T>\nclass InstanceTest : public ::testing::Test {};\nTYPED_TEST_SUITE_P(InstanceTest);\n\n// A simple reference counted class to make sure that the proper elements are\n// destroyed in the erase(begin, end) test.\nclass RefCounted {\n public:\n  RefCounted(int value, int* count) : value_(value), count_(count) { Ref(); }\n\n  RefCounted(const RefCounted& v) : value_(v.value_), count_(v.count_) {\n    Ref();\n  }\n\n  ~RefCounted() {\n    Unref();\n    count_ = nullptr;\n  }\n\n  friend void swap(RefCounted& a, RefCounted& b) {\n    using std::swap;\n    swap(a.value_, b.value_);\n    swap(a.count_, b.count_);\n  }\n\n  RefCounted& operator=(RefCounted v) {\n    using std::swap;\n    swap(*this, v);\n    return *this;\n  }\n\n  void Ref() const {\n    CHECK_NE(count_, nullptr);\n    ++(*count_);\n  }\n\n  void Unref() const {\n    --(*count_);\n    CHECK_GE(*count_, 0);\n  }\n\n  int value_;\n  int* count_;\n};\n\nusing RefCountedVec = absl::InlinedVector<RefCounted, 8>;\n\n// A class with a vtable pointer\nclass Dynamic {\n public:\n  virtual ~Dynamic() {}\n};\n\nusing DynamicVec = absl::InlinedVector<Dynamic, 8>;\n\n// Append 0..len-1 to *v\ntemplate <typename Container>\nstatic void Fill(Container* v, size_t len, int offset = 0) {\n  for (size_t i = 0; i < len; i++) {\n    v->push_back(static_cast<int>(i) + offset);\n  }\n}\n\nstatic IntVec Fill(size_t len, int offset = 0) {\n  IntVec v;\n  Fill(&v, len, offset);\n  return v;\n}\n\nTEST(IntVec, SimpleOps) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v;\n    const IntVec& cv = v;  // const alias\n\n    Fill(&v, len);\n    EXPECT_EQ(len, v.size());\n    EXPECT_LE(len, v.capacity());\n\n    for (size_t i = 0; i < len; i++) {\n      EXPECT_EQ(static_cast<int>(i), v[i]);\n      EXPECT_EQ(static_cast<int>(i), v.at(i));\n    }\n    EXPECT_EQ(v.begin(), v.data());\n    EXPECT_EQ(cv.begin(), cv.data());\n\n    size_t counter = 0;\n    for (IntVec::iterator iter = v.begin(); iter != v.end(); ++iter) {\n      EXPECT_EQ(static_cast<int>(counter), *iter);\n      counter++;\n    }\n    EXPECT_EQ(counter, len);\n\n    counter = 0;\n    for (IntVec::const_iterator iter = v.begin(); iter != v.end(); ++iter) {\n      EXPECT_EQ(static_cast<int>(counter), *iter);\n      counter++;\n    }\n    EXPECT_EQ(counter, len);\n\n    counter = 0;\n    for (IntVec::const_iterator iter = v.cbegin(); iter != v.cend(); ++iter) {\n      EXPECT_EQ(static_cast<int>(counter), *iter);\n      counter++;\n    }\n    EXPECT_EQ(counter, len);\n\n    if (len > 0) {\n      EXPECT_EQ(0, v.front());\n      EXPECT_EQ(static_cast<int>(len - 1), v.back());\n      v.pop_back();\n      EXPECT_EQ(len - 1, v.size());\n      for (size_t i = 0; i < v.size(); ++i) {\n        EXPECT_EQ(static_cast<int>(i), v[i]);\n        EXPECT_EQ(static_cast<int>(i), v.at(i));\n      }\n    }\n  }\n}\n\nTEST(IntVec, PopBackNoOverflow) {\n  IntVec v = {1};\n  v.pop_back();\n  EXPECT_EQ(v.size(), 0u);\n}\n\nTEST(IntVec, AtThrows) {\n  IntVec v = {1, 2, 3};\n  EXPECT_EQ(v.at(2), 3);\n  ABSL_BASE_INTERNAL_EXPECT_FAIL(v.at(3), std::out_of_range,\n                                 \"failed bounds check\");\n}\n\nTEST(IntVec, ReverseIterator) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v;\n    Fill(&v, len);\n\n    size_t counter = len;\n    for (IntVec::reverse_iterator iter = v.rbegin(); iter != v.rend(); ++iter) {\n      counter--;\n      EXPECT_EQ(static_cast<int>(counter), *iter);\n    }\n    EXPECT_EQ(counter, 0u);\n\n    counter = len;\n    for (IntVec::const_reverse_iterator iter = v.rbegin(); iter != v.rend();\n         ++iter) {\n      counter--;\n      EXPECT_EQ(static_cast<int>(counter), *iter);\n    }\n    EXPECT_EQ(counter, 0u);\n\n    counter = len;\n    for (IntVec::const_reverse_iterator iter = v.crbegin(); iter != v.crend();\n         ++iter) {\n      counter--;\n      EXPECT_EQ(static_cast<int>(counter), *iter);\n    }\n    EXPECT_EQ(counter, 0u);\n  }\n}\n\nTEST(IntVec, Erase) {\n  for (size_t len = 1; len < 20; len++) {\n    for (size_t i = 0; i < len; ++i) {\n      IntVec v;\n      Fill(&v, len);\n      v.erase(v.begin() + i);\n      EXPECT_EQ(len - 1, v.size());\n      for (size_t j = 0; j < i; ++j) {\n        EXPECT_EQ(static_cast<int>(j), v[j]);\n      }\n      for (size_t j = i; j < len - 1; ++j) {\n        EXPECT_EQ(static_cast<int>(j + 1), v[j]);\n      }\n    }\n  }\n}\n\nTEST(IntVec, Hardened) {\n  IntVec v;\n  Fill(&v, 10);\n  EXPECT_EQ(v[9], 9);\n#if !defined(NDEBUG) || ABSL_OPTION_HARDENED\n  EXPECT_DEATH_IF_SUPPORTED(v[10], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(v[static_cast<size_t>(-1)], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(v.resize(v.max_size() + 1), \"\");\n#endif\n}\n\n// Move construction of a container of unique pointers should work fine, with no\n// leaks, despite the fact that unique pointers are trivially relocatable but\n// not trivially destructible.\nTEST(UniquePtr, MoveConstruct) {\n  for (size_t size = 0; size < 16; ++size) {\n    SCOPED_TRACE(size);\n\n    absl::InlinedVector<std::unique_ptr<size_t>, 2> a;\n    for (size_t i = 0; i < size; ++i) {\n      a.push_back(std::make_unique<size_t>(i));\n    }\n\n    absl::InlinedVector<std::unique_ptr<size_t>, 2> b(std::move(a));\n\n    ASSERT_THAT(b, SizeIs(size));\n    for (size_t i = 0; i < size; ++i) {\n      ASSERT_THAT(b[i], Pointee(i));\n    }\n  }\n}\n\n// Move assignment of a container of unique pointers should work fine, with no\n// leaks, despite the fact that unique pointers are trivially relocatable but\n// not trivially destructible.\nTEST(UniquePtr, MoveAssign) {\n  for (size_t size = 0; size < 16; ++size) {\n    SCOPED_TRACE(size);\n\n    absl::InlinedVector<std::unique_ptr<size_t>, 2> a;\n    for (size_t i = 0; i < size; ++i) {\n      a.push_back(std::make_unique<size_t>(i));\n    }\n\n    absl::InlinedVector<std::unique_ptr<size_t>, 2> b;\n    b = std::move(a);\n\n    ASSERT_THAT(b, SizeIs(size));\n    for (size_t i = 0; i < size; ++i) {\n      ASSERT_THAT(b[i], Pointee(i));\n    }\n  }\n}\n\n// Swapping containers of unique pointers should work fine, with no\n// leaks, despite the fact that unique pointers are trivially relocatable but\n// not trivially destructible.\n// TODO(absl-team): Using unique_ptr here is technically correct, but\n// a trivially relocatable struct would be less semantically confusing.\nTEST(UniquePtr, Swap) {\n  for (size_t size1 = 0; size1 < 5; ++size1) {\n    for (size_t size2 = 0; size2 < 5; ++size2) {\n      absl::InlinedVector<std::unique_ptr<size_t>, 2> a;\n      absl::InlinedVector<std::unique_ptr<size_t>, 2> b;\n      for (size_t i = 0; i < size1; ++i) {\n        a.push_back(std::make_unique<size_t>(i + 10));\n      }\n      for (size_t i = 0; i < size2; ++i) {\n        b.push_back(std::make_unique<size_t>(i + 20));\n      }\n      a.swap(b);\n      ASSERT_THAT(a, SizeIs(size2));\n      ASSERT_THAT(b, SizeIs(size1));\n      for (size_t i = 0; i < a.size(); ++i) {\n        ASSERT_THAT(a[i], Pointee(i + 20));\n      }\n      for (size_t i = 0; i < b.size(); ++i) {\n        ASSERT_THAT(b[i], Pointee(i + 10));\n      }\n    }\n  }\n}\n\n// Erasing from a container of unique pointers should work fine, with no\n// leaks, despite the fact that unique pointers are trivially relocatable but\n// not trivially destructible.\n// TODO(absl-team): Using unique_ptr here is technically correct, but\n// a trivially relocatable struct would be less semantically confusing.\nTEST(UniquePtr, EraseSingle) {\n  for (size_t size = 4; size < 16; ++size) {\n    absl::InlinedVector<std::unique_ptr<size_t>, 8> a;\n    for (size_t i = 0; i < size; ++i) {\n      a.push_back(std::make_unique<size_t>(i));\n    }\n    a.erase(a.begin());\n    ASSERT_THAT(a, SizeIs(size - 1));\n    for (size_t i = 0; i < size - 1; ++i) {\n      ASSERT_THAT(a[i], Pointee(i + 1));\n    }\n    a.erase(a.begin() + 2);\n    ASSERT_THAT(a, SizeIs(size - 2));\n    ASSERT_THAT(a[0], Pointee(1));\n    ASSERT_THAT(a[1], Pointee(2));\n    for (size_t i = 2; i < size - 2; ++i) {\n      ASSERT_THAT(a[i], Pointee(i + 2));\n    }\n  }\n}\n\n// Erasing from a container of unique pointers should work fine, with no\n// leaks, despite the fact that unique pointers are trivially relocatable but\n// not trivially destructible.\n// TODO(absl-team): Using unique_ptr here is technically correct, but\n// a trivially relocatable struct would be less semantically confusing.\nTEST(UniquePtr, EraseMulti) {\n  for (size_t size = 5; size < 16; ++size) {\n    absl::InlinedVector<std::unique_ptr<size_t>, 8> a;\n    for (size_t i = 0; i < size; ++i) {\n      a.push_back(std::make_unique<size_t>(i));\n    }\n    a.erase(a.begin(), a.begin() + 2);\n    ASSERT_THAT(a, SizeIs(size - 2));\n    for (size_t i = 0; i < size - 2; ++i) {\n      ASSERT_THAT(a[i], Pointee(i + 2));\n    }\n    a.erase(a.begin() + 1, a.begin() + 3);\n    ASSERT_THAT(a, SizeIs(size - 4));\n    ASSERT_THAT(a[0], Pointee(2));\n    for (size_t i = 1; i < size - 4; ++i) {\n      ASSERT_THAT(a[i], Pointee(i + 4));\n    }\n  }\n}\n\n// At the end of this test loop, the elements between [erase_begin, erase_end)\n// should have reference counts == 0, and all others elements should have\n// reference counts == 1.\nTEST(RefCountedVec, EraseBeginEnd) {\n  for (size_t len = 1; len < 20; ++len) {\n    for (size_t erase_begin = 0; erase_begin < len; ++erase_begin) {\n      for (size_t erase_end = erase_begin; erase_end <= len; ++erase_end) {\n        std::vector<int> counts(len, 0);\n        RefCountedVec v;\n        for (size_t i = 0; i < len; ++i) {\n          v.push_back(RefCounted(static_cast<int>(i), &counts[i]));\n        }\n\n        size_t erase_len = erase_end - erase_begin;\n\n        v.erase(v.begin() + erase_begin, v.begin() + erase_end);\n\n        EXPECT_EQ(len - erase_len, v.size());\n\n        // Check the elements before the first element erased.\n        for (size_t i = 0; i < erase_begin; ++i) {\n          EXPECT_EQ(static_cast<int>(i), v[i].value_);\n        }\n\n        // Check the elements after the first element erased.\n        for (size_t i = erase_begin; i < v.size(); ++i) {\n          EXPECT_EQ(static_cast<int>(i + erase_len), v[i].value_);\n        }\n\n        // Check that the elements at the beginning are preserved.\n        for (size_t i = 0; i < erase_begin; ++i) {\n          EXPECT_EQ(1, counts[i]);\n        }\n\n        // Check that the erased elements are destroyed\n        for (size_t i = erase_begin; i < erase_end; ++i) {\n          EXPECT_EQ(0, counts[i]);\n        }\n\n        // Check that the elements at the end are preserved.\n        for (size_t i = erase_end; i < len; ++i) {\n          EXPECT_EQ(1, counts[i]);\n        }\n      }\n    }\n  }\n}\n\nstruct NoDefaultCtor {\n  explicit NoDefaultCtor(int) {}\n};\nstruct NoCopy {\n  NoCopy() {}\n  NoCopy(const NoCopy&) = delete;\n};\nstruct NoAssign {\n  NoAssign() {}\n  NoAssign& operator=(const NoAssign&) = delete;\n};\nstruct MoveOnly {\n  MoveOnly() {}\n  MoveOnly(MoveOnly&&) = default;\n  MoveOnly& operator=(MoveOnly&&) = default;\n};\nTEST(InlinedVectorTest, NoDefaultCtor) {\n  absl::InlinedVector<NoDefaultCtor, 1> v(10, NoDefaultCtor(2));\n  (void)v;\n}\nTEST(InlinedVectorTest, NoCopy) {\n  absl::InlinedVector<NoCopy, 1> v(10);\n  (void)v;\n}\nTEST(InlinedVectorTest, NoAssign) {\n  absl::InlinedVector<NoAssign, 1> v(10);\n  (void)v;\n}\nTEST(InlinedVectorTest, MoveOnly) {\n  absl::InlinedVector<MoveOnly, 2> v;\n  v.push_back(MoveOnly{});\n  v.push_back(MoveOnly{});\n  v.push_back(MoveOnly{});\n  v.erase(v.begin());\n  v.push_back(MoveOnly{});\n  v.erase(v.begin(), v.begin() + 1);\n  v.insert(v.begin(), MoveOnly{});\n  v.emplace(v.begin());\n  v.emplace(v.begin(), MoveOnly{});\n}\nTEST(InlinedVectorTest, Noexcept) {\n  EXPECT_TRUE(std::is_nothrow_move_constructible<IntVec>::value);\n  EXPECT_TRUE((std::is_nothrow_move_constructible<\n               absl::InlinedVector<MoveOnly, 2>>::value));\n\n  struct MoveCanThrow {\n    MoveCanThrow(MoveCanThrow&&) {}\n  };\n  EXPECT_EQ(absl::default_allocator_is_nothrow::value,\n            (std::is_nothrow_move_constructible<\n                absl::InlinedVector<MoveCanThrow, 2>>::value));\n}\n\nTEST(InlinedVectorTest, EmplaceBack) {\n  absl::InlinedVector<std::pair<std::string, int>, 1> v;\n\n  auto& inlined_element = v.emplace_back(\"answer\", 42);\n  EXPECT_EQ(&inlined_element, &v[0]);\n  EXPECT_EQ(inlined_element.first, \"answer\");\n  EXPECT_EQ(inlined_element.second, 42);\n\n  auto& allocated_element = v.emplace_back(\"taxicab\", 1729);\n  EXPECT_EQ(&allocated_element, &v[1]);\n  EXPECT_EQ(allocated_element.first, \"taxicab\");\n  EXPECT_EQ(allocated_element.second, 1729);\n}\n\nTEST(InlinedVectorTest, ShrinkToFitGrowingVector) {\n  absl::InlinedVector<std::pair<std::string, int>, 1> v;\n\n  v.shrink_to_fit();\n  EXPECT_EQ(v.capacity(), 1u);\n\n  v.emplace_back(\"answer\", 42);\n  v.shrink_to_fit();\n  EXPECT_EQ(v.capacity(), 1u);\n\n  v.emplace_back(\"taxicab\", 1729);\n  EXPECT_GE(v.capacity(), 2u);\n  v.shrink_to_fit();\n  EXPECT_EQ(v.capacity(), 2u);\n\n  v.reserve(100);\n  EXPECT_GE(v.capacity(), 100u);\n  v.shrink_to_fit();\n  EXPECT_EQ(v.capacity(), 2u);\n}\n\nTEST(InlinedVectorTest, ShrinkToFitEdgeCases) {\n  {\n    absl::InlinedVector<std::pair<std::string, int>, 1> v;\n    v.emplace_back(\"answer\", 42);\n    v.emplace_back(\"taxicab\", 1729);\n    EXPECT_GE(v.capacity(), 2u);\n    v.pop_back();\n    v.shrink_to_fit();\n    EXPECT_EQ(v.capacity(), 1u);\n    EXPECT_EQ(v[0].first, \"answer\");\n    EXPECT_EQ(v[0].second, 42);\n  }\n\n  {\n    absl::InlinedVector<std::string, 2> v(100);\n    v.resize(0);\n    v.shrink_to_fit();\n    EXPECT_EQ(v.capacity(), 2u);  // inlined capacity\n  }\n\n  {\n    absl::InlinedVector<std::string, 2> v(100);\n    v.resize(1);\n    v.shrink_to_fit();\n    EXPECT_EQ(v.capacity(), 2u);  // inlined capacity\n  }\n\n  {\n    absl::InlinedVector<std::string, 2> v(100);\n    v.resize(2);\n    v.shrink_to_fit();\n    EXPECT_EQ(v.capacity(), 2u);\n  }\n\n  {\n    absl::InlinedVector<std::string, 2> v(100);\n    v.resize(3);\n    v.shrink_to_fit();\n    EXPECT_EQ(v.capacity(), 3u);\n  }\n}\n\nTEST(IntVec, Insert) {\n  for (size_t len = 0; len < 20; len++) {\n    for (ptrdiff_t pos = 0; pos <= static_cast<ptrdiff_t>(len); pos++) {\n      {\n        // Single element\n        std::vector<int> std_v;\n        Fill(&std_v, len);\n        IntVec v;\n        Fill(&v, len);\n\n        std_v.insert(std_v.begin() + pos, 9999);\n        IntVec::iterator it = v.insert(v.cbegin() + pos, 9999);\n        EXPECT_THAT(v, ElementsAreArray(std_v));\n        EXPECT_EQ(it, v.cbegin() + pos);\n      }\n      {\n        // n elements\n        std::vector<int> std_v;\n        Fill(&std_v, len);\n        IntVec v;\n        Fill(&v, len);\n\n        IntVec::size_type n = 5;\n        std_v.insert(std_v.begin() + pos, n, 9999);\n        IntVec::iterator it = v.insert(v.cbegin() + pos, n, 9999);\n        EXPECT_THAT(v, ElementsAreArray(std_v));\n        EXPECT_EQ(it, v.cbegin() + pos);\n      }\n      {\n        // Iterator range (random access iterator)\n        std::vector<int> std_v;\n        Fill(&std_v, len);\n        IntVec v;\n        Fill(&v, len);\n\n        const std::vector<int> input = {9999, 8888, 7777};\n        std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());\n        IntVec::iterator it =\n            v.insert(v.cbegin() + pos, input.cbegin(), input.cend());\n        EXPECT_THAT(v, ElementsAreArray(std_v));\n        EXPECT_EQ(it, v.cbegin() + pos);\n      }\n      {\n        // Iterator range (forward iterator)\n        std::vector<int> std_v;\n        Fill(&std_v, len);\n        IntVec v;\n        Fill(&v, len);\n\n        const std::forward_list<int> input = {9999, 8888, 7777};\n        std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());\n        IntVec::iterator it =\n            v.insert(v.cbegin() + pos, input.cbegin(), input.cend());\n        EXPECT_THAT(v, ElementsAreArray(std_v));\n        EXPECT_EQ(it, v.cbegin() + pos);\n      }\n      {\n        // Iterator range (input iterator)\n        std::vector<int> std_v;\n        Fill(&std_v, len);\n        IntVec v;\n        Fill(&v, len);\n\n        std_v.insert(std_v.begin() + pos, {9999, 8888, 7777});\n        std::istringstream input(\"9999 8888 7777\");\n        IntVec::iterator it =\n            v.insert(v.cbegin() + pos, std::istream_iterator<int>(input),\n                     std::istream_iterator<int>());\n        EXPECT_THAT(v, ElementsAreArray(std_v));\n        EXPECT_EQ(it, v.cbegin() + pos);\n      }\n      {\n        // Initializer list\n        std::vector<int> std_v;\n        Fill(&std_v, len);\n        IntVec v;\n        Fill(&v, len);\n\n        std_v.insert(std_v.begin() + pos, {9999, 8888});\n        IntVec::iterator it = v.insert(v.cbegin() + pos, {9999, 8888});\n        EXPECT_THAT(v, ElementsAreArray(std_v));\n        EXPECT_EQ(it, v.cbegin() + pos);\n      }\n    }\n  }\n}\n\nTEST(IntPairVec, Insert) {\n  for (size_t len = 0; len < 20; len++) {\n    for (ptrdiff_t pos = 0; pos <= static_cast<ptrdiff_t>(len); pos++) {\n      // Iterator range (C++20 forward iterator)\n      const std::forward_list<int> unzipped_input = {9999, 8888, 7777};\n      const absl::base_internal::Cpp20ForwardZipIterator<\n          std::forward_list<int>::const_iterator>\n          begin(unzipped_input.cbegin(), unzipped_input.cbegin());\n      const absl::base_internal::Cpp20ForwardZipIterator<\n          std::forward_list<int>::const_iterator>\n          end(unzipped_input.cend(), unzipped_input.cend());\n\n      std::vector<std::pair<int, int>> std_v;\n      absl::InlinedVector<std::pair<int, int>, 8> v;\n      for (size_t i = 0; i < len; ++i) {\n        std_v.emplace_back(i, i);\n        v.emplace_back(i, i);\n      }\n\n      std_v.insert(std_v.begin() + pos, begin, end);\n      auto it = v.insert(v.cbegin() + pos, begin, end);\n      EXPECT_THAT(v, ElementsAreArray(std_v));\n      EXPECT_EQ(it, v.cbegin() + pos);\n    }\n  }\n}\n\nTEST(RefCountedVec, InsertConstructorDestructor) {\n  // Make sure the proper construction/destruction happen during insert\n  // operations.\n  for (size_t len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    for (size_t pos = 0; pos <= len; pos++) {\n      SCOPED_TRACE(pos);\n      std::vector<int> counts(len, 0);\n      int inserted_count = 0;\n      RefCountedVec v;\n      for (size_t i = 0; i < len; ++i) {\n        SCOPED_TRACE(i);\n        v.push_back(RefCounted(static_cast<int>(i), &counts[i]));\n      }\n\n      EXPECT_THAT(counts, Each(Eq(1)));\n\n      RefCounted insert_element(9999, &inserted_count);\n      EXPECT_EQ(1, inserted_count);\n      v.insert(v.begin() + pos, insert_element);\n      EXPECT_EQ(2, inserted_count);\n      // Check that the elements at the end are preserved.\n      EXPECT_THAT(counts, Each(Eq(1)));\n      EXPECT_EQ(2, inserted_count);\n    }\n  }\n}\n\nTEST(IntVec, Resize) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v;\n    Fill(&v, len);\n\n    // Try resizing up and down by k elements\n    static const int kResizeElem = 1000000;\n    for (size_t k = 0; k < 10; k++) {\n      // Enlarging resize\n      v.resize(len + k, kResizeElem);\n      EXPECT_EQ(len + k, v.size());\n      EXPECT_LE(len + k, v.capacity());\n      for (size_t i = 0; i < len + k; i++) {\n        if (i < len) {\n          EXPECT_EQ(static_cast<int>(i), v[i]);\n        } else {\n          EXPECT_EQ(kResizeElem, v[i]);\n        }\n      }\n\n      // Shrinking resize\n      v.resize(len, kResizeElem);\n      EXPECT_EQ(len, v.size());\n      EXPECT_LE(len, v.capacity());\n      for (size_t i = 0; i < len; i++) {\n        EXPECT_EQ(static_cast<int>(i), v[i]);\n      }\n    }\n  }\n}\n\nTEST(IntVec, InitWithLength) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v(len, 7);\n    EXPECT_EQ(len, v.size());\n    EXPECT_LE(len, v.capacity());\n    for (size_t i = 0; i < len; i++) {\n      EXPECT_EQ(7, v[i]);\n    }\n  }\n}\n\nTEST(IntVec, CopyConstructorAndAssignment) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v;\n    Fill(&v, len);\n    EXPECT_EQ(len, v.size());\n    EXPECT_LE(len, v.capacity());\n\n    IntVec v2(v);\n    EXPECT_TRUE(v == v2) << PrintToString(v) << PrintToString(v2);\n\n    for (size_t start_len = 0; start_len < 20; start_len++) {\n      IntVec v3;\n      Fill(&v3, start_len, 99);  // Add dummy elements that should go away\n      v3 = v;\n      EXPECT_TRUE(v == v3) << PrintToString(v) << PrintToString(v3);\n    }\n  }\n}\n\nTEST(IntVec, AliasingCopyAssignment) {\n  for (size_t len = 0; len < 20; ++len) {\n    IntVec original;\n    Fill(&original, len);\n    IntVec dup = original;\n    dup = *&dup;\n    EXPECT_EQ(dup, original);\n  }\n}\n\nTEST(IntVec, MoveConstructorAndAssignment) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v_in;\n    const size_t inlined_capacity = v_in.capacity();\n    Fill(&v_in, len);\n    EXPECT_EQ(len, v_in.size());\n    EXPECT_LE(len, v_in.capacity());\n\n    {\n      IntVec v_temp(v_in);\n      auto* old_data = v_temp.data();\n      IntVec v_out(std::move(v_temp));\n      EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);\n      if (v_in.size() > inlined_capacity) {\n        // Allocation is moved as a whole, data stays in place.\n        EXPECT_TRUE(v_out.data() == old_data);\n      } else {\n        EXPECT_FALSE(v_out.data() == old_data);\n      }\n    }\n    for (size_t start_len = 0; start_len < 20; start_len++) {\n      IntVec v_out;\n      Fill(&v_out, start_len, 99);  // Add dummy elements that should go away\n      IntVec v_temp(v_in);\n      auto* old_data = v_temp.data();\n      v_out = std::move(v_temp);\n      EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);\n      if (v_in.size() > inlined_capacity) {\n        // Allocation is moved as a whole, data stays in place.\n        EXPECT_TRUE(v_out.data() == old_data);\n      } else {\n        EXPECT_FALSE(v_out.data() == old_data);\n      }\n    }\n  }\n}\n\nclass NotTriviallyDestructible {\n public:\n  NotTriviallyDestructible() : p_(new int(1)) {}\n  explicit NotTriviallyDestructible(int i) : p_(new int(i)) {}\n\n  NotTriviallyDestructible(const NotTriviallyDestructible& other)\n      : p_(new int(*other.p_)) {}\n\n  NotTriviallyDestructible& operator=(const NotTriviallyDestructible& other) {\n    p_ = absl::make_unique<int>(*other.p_);\n    return *this;\n  }\n\n  bool operator==(const NotTriviallyDestructible& other) const {\n    return *p_ == *other.p_;\n  }\n\n private:\n  std::unique_ptr<int> p_;\n};\n\nTEST(AliasingTest, Emplace) {\n  for (size_t i = 2; i < 20; ++i) {\n    absl::InlinedVector<NotTriviallyDestructible, 10> vec;\n    for (size_t j = 0; j < i; ++j) {\n      vec.push_back(NotTriviallyDestructible(static_cast<int>(j)));\n    }\n    vec.emplace(vec.begin(), vec[0]);\n    EXPECT_EQ(vec[0], vec[1]);\n    vec.emplace(vec.begin() + i / 2, vec[i / 2]);\n    EXPECT_EQ(vec[i / 2], vec[i / 2 + 1]);\n    vec.emplace(vec.end() - 1, vec.back());\n    EXPECT_EQ(vec[vec.size() - 2], vec.back());\n  }\n}\n\nTEST(AliasingTest, InsertWithCount) {\n  for (size_t i = 1; i < 20; ++i) {\n    absl::InlinedVector<NotTriviallyDestructible, 10> vec;\n    for (size_t j = 0; j < i; ++j) {\n      vec.push_back(NotTriviallyDestructible(static_cast<int>(j)));\n    }\n    for (size_t n = 0; n < 5; ++n) {\n      // We use back where we can because it's guaranteed to become invalidated\n      vec.insert(vec.begin(), n, vec.back());\n      auto b = vec.begin();\n      EXPECT_TRUE(\n          std::all_of(b, b + n, [&vec](const NotTriviallyDestructible& x) {\n            return x == vec.back();\n          }));\n\n      auto m_idx = vec.size() / 2;\n      vec.insert(vec.begin() + m_idx, n, vec.back());\n      auto m = vec.begin() + m_idx;\n      EXPECT_TRUE(\n          std::all_of(m, m + n, [&vec](const NotTriviallyDestructible& x) {\n            return x == vec.back();\n          }));\n\n      // We want distinct values so the equality test is meaningful,\n      // vec[vec.size() - 1] is also almost always invalidated.\n      auto old_e = vec.size() - 1;\n      auto val = vec[old_e];\n      vec.insert(vec.end(), n, vec[old_e]);\n      auto e = vec.begin() + old_e;\n      EXPECT_TRUE(std::all_of(\n          e, e + n,\n          [&val](const NotTriviallyDestructible& x) { return x == val; }));\n    }\n  }\n}\n\nTEST(OverheadTest, Storage) {\n  // Check for size overhead.\n  // In particular, ensure that std::allocator doesn't cost anything to store.\n  // The union should be absorbing some of the allocation bookkeeping overhead\n  // in the larger vectors, leaving only the size_ field as overhead.\n\n  struct T {\n    void* val;\n  };\n  size_t expected_overhead = sizeof(T);\n\n  EXPECT_EQ((2 * expected_overhead),\n            sizeof(absl::InlinedVector<T, 1>) - sizeof(T[1]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 2>) - sizeof(T[2]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 3>) - sizeof(T[3]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 4>) - sizeof(T[4]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 5>) - sizeof(T[5]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 6>) - sizeof(T[6]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 7>) - sizeof(T[7]));\n  EXPECT_EQ(expected_overhead,\n            sizeof(absl::InlinedVector<T, 8>) - sizeof(T[8]));\n}\n\nTEST(IntVec, Clear) {\n  for (size_t len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    IntVec v;\n    Fill(&v, len);\n    size_t capacity_before_clear = v.capacity();\n    v.clear();\n    EXPECT_EQ(v.capacity(), capacity_before_clear);\n    EXPECT_EQ(0u, v.size());\n    EXPECT_EQ(v.begin(), v.end());\n  }\n}\n\nTEST(IntVec, Reserve) {\n  for (size_t len = 0; len < 20; len++) {\n    IntVec v;\n    Fill(&v, len);\n\n    for (size_t newlen = 0; newlen < 100; newlen++) {\n      const int* start_rep = v.data();\n      v.reserve(newlen);\n      const int* final_rep = v.data();\n      if (newlen <= len) {\n        EXPECT_EQ(start_rep, final_rep);\n      }\n      EXPECT_LE(newlen, v.capacity());\n\n      // Filling up to newlen should not change rep\n      while (v.size() < newlen) {\n        v.push_back(0);\n      }\n      EXPECT_EQ(final_rep, v.data());\n    }\n  }\n}\n\nTEST(StringVec, SelfRefPushBack) {\n  std::vector<std::string> std_v;\n  absl::InlinedVector<std::string, 4> v;\n  const std::string s = \"A quite long string to ensure heap.\";\n  std_v.push_back(s);\n  v.push_back(s);\n  for (int i = 0; i < 20; ++i) {\n    EXPECT_THAT(v, ElementsAreArray(std_v));\n\n    v.push_back(v.back());\n    std_v.push_back(std_v.back());\n  }\n  EXPECT_THAT(v, ElementsAreArray(std_v));\n}\n\nTEST(StringVec, SelfRefPushBackWithMove) {\n  std::vector<std::string> std_v;\n  absl::InlinedVector<std::string, 4> v;\n  const std::string s = \"A quite long string to ensure heap.\";\n  std_v.push_back(s);\n  v.push_back(s);\n  for (int i = 0; i < 20; ++i) {\n    EXPECT_EQ(v.back(), std_v.back());\n\n    v.push_back(std::move(v.back()));\n    std_v.push_back(std::move(std_v.back()));\n  }\n  EXPECT_EQ(v.back(), std_v.back());\n}\n\nTEST(StringVec, SelfMove) {\n  const std::string s = \"A quite long string to ensure heap.\";\n  for (int len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    absl::InlinedVector<std::string, 8> v;\n    for (int i = 0; i < len; ++i) {\n      SCOPED_TRACE(i);\n      v.push_back(s);\n    }\n    // Indirection necessary to avoid compiler warning.\n    v = std::move(*(&v));\n    // Ensure that the inlined vector is still in a valid state by copying it.\n    // We don't expect specific contents since a self-move results in an\n    // unspecified valid state.\n    std::vector<std::string> copy(v.begin(), v.end());\n  }\n}\n\nTEST(IntVec, Swap) {\n  for (size_t l1 = 0; l1 < 20; l1++) {\n    SCOPED_TRACE(l1);\n    for (size_t l2 = 0; l2 < 20; l2++) {\n      SCOPED_TRACE(l2);\n      IntVec a = Fill(l1, 0);\n      IntVec b = Fill(l2, 100);\n      {\n        using std::swap;\n        swap(a, b);\n      }\n      EXPECT_EQ(l1, b.size());\n      EXPECT_EQ(l2, a.size());\n      for (size_t i = 0; i < l1; i++) {\n        SCOPED_TRACE(i);\n        EXPECT_EQ(static_cast<int>(i), b[i]);\n      }\n      for (size_t i = 0; i < l2; i++) {\n        SCOPED_TRACE(i);\n        EXPECT_EQ(100 + static_cast<int>(i), a[i]);\n      }\n    }\n  }\n}\n\nTYPED_TEST_P(InstanceTest, Swap) {\n  using Instance = TypeParam;\n  using InstanceVec = absl::InlinedVector<Instance, 8>;\n  for (size_t l1 = 0; l1 < 20; l1++) {\n    SCOPED_TRACE(l1);\n    for (size_t l2 = 0; l2 < 20; l2++) {\n      SCOPED_TRACE(l2);\n      InstanceTracker tracker;\n      InstanceVec a, b;\n      const size_t inlined_capacity = a.capacity();\n      auto min_len = std::min(l1, l2);\n      auto max_len = std::max(l1, l2);\n      for (size_t i = 0; i < l1; i++)\n        a.push_back(Instance(static_cast<int>(i)));\n      for (size_t i = 0; i < l2; i++)\n        b.push_back(Instance(100 + static_cast<int>(i)));\n      EXPECT_EQ(tracker.instances(), static_cast<int>(l1 + l2));\n      tracker.ResetCopiesMovesSwaps();\n      {\n        using std::swap;\n        swap(a, b);\n      }\n      EXPECT_EQ(tracker.instances(), static_cast<int>(l1 + l2));\n      if (a.size() > inlined_capacity && b.size() > inlined_capacity) {\n        EXPECT_EQ(tracker.swaps(), 0);  // Allocations are swapped.\n        EXPECT_EQ(tracker.moves(), 0);\n      } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {\n        EXPECT_EQ(tracker.swaps(), static_cast<int>(min_len));\n        EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),\n                  static_cast<int>(max_len - min_len));\n      } else {\n        // One is allocated and the other isn't. The allocation is transferred\n        // without copying elements, and the inlined instances are copied/moved.\n        EXPECT_EQ(tracker.swaps(), 0);\n        EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),\n                  static_cast<int>(min_len));\n      }\n\n      EXPECT_EQ(l1, b.size());\n      EXPECT_EQ(l2, a.size());\n      for (size_t i = 0; i < l1; i++) {\n        EXPECT_EQ(static_cast<int>(i), b[i].value());\n      }\n      for (size_t i = 0; i < l2; i++) {\n        EXPECT_EQ(100 + static_cast<int>(i), a[i].value());\n      }\n    }\n  }\n}\n\nTEST(IntVec, EqualAndNotEqual) {\n  IntVec a, b;\n  EXPECT_TRUE(a == b);\n  EXPECT_FALSE(a != b);\n\n  a.push_back(3);\n  EXPECT_FALSE(a == b);\n  EXPECT_TRUE(a != b);\n\n  b.push_back(3);\n  EXPECT_TRUE(a == b);\n  EXPECT_FALSE(a != b);\n\n  b.push_back(7);\n  EXPECT_FALSE(a == b);\n  EXPECT_TRUE(a != b);\n\n  a.push_back(6);\n  EXPECT_FALSE(a == b);\n  EXPECT_TRUE(a != b);\n\n  a.clear();\n  b.clear();\n  for (size_t i = 0; i < 100; i++) {\n    a.push_back(static_cast<int>(i));\n    b.push_back(static_cast<int>(i));\n    EXPECT_TRUE(a == b);\n    EXPECT_FALSE(a != b);\n\n    b[i] = b[i] + 1;\n    EXPECT_FALSE(a == b);\n    EXPECT_TRUE(a != b);\n\n    b[i] = b[i] - 1;  // Back to before\n    EXPECT_TRUE(a == b);\n    EXPECT_FALSE(a != b);\n  }\n}\n\nTEST(IntVec, RelationalOps) {\n  IntVec a, b;\n  EXPECT_FALSE(a < b);\n  EXPECT_FALSE(b < a);\n  EXPECT_FALSE(a > b);\n  EXPECT_FALSE(b > a);\n  EXPECT_TRUE(a <= b);\n  EXPECT_TRUE(b <= a);\n  EXPECT_TRUE(a >= b);\n  EXPECT_TRUE(b >= a);\n  b.push_back(3);\n  EXPECT_TRUE(a < b);\n  EXPECT_FALSE(b < a);\n  EXPECT_FALSE(a > b);\n  EXPECT_TRUE(b > a);\n  EXPECT_TRUE(a <= b);\n  EXPECT_FALSE(b <= a);\n  EXPECT_FALSE(a >= b);\n  EXPECT_TRUE(b >= a);\n}\n\nTYPED_TEST_P(InstanceTest, CountConstructorsDestructors) {\n  using Instance = TypeParam;\n  using InstanceVec = absl::InlinedVector<Instance, 8>;\n  InstanceTracker tracker;\n  for (size_t len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    tracker.ResetCopiesMovesSwaps();\n\n    InstanceVec v;\n    const size_t inlined_capacity = v.capacity();\n    for (size_t i = 0; i < len; i++) {\n      v.push_back(Instance(static_cast<int>(i)));\n    }\n    EXPECT_EQ(tracker.instances(), static_cast<int>(len));\n    EXPECT_GE(tracker.copies() + tracker.moves(),\n              static_cast<int>(len));  // More due to reallocation.\n    tracker.ResetCopiesMovesSwaps();\n\n    // Enlarging resize() must construct some objects\n    tracker.ResetCopiesMovesSwaps();\n    v.resize(len + 10, Instance(100));\n    EXPECT_EQ(tracker.instances(), static_cast<int>(len) + 10);\n    if (len <= inlined_capacity && len + 10 > inlined_capacity) {\n      EXPECT_EQ(tracker.copies() + tracker.moves(), 10 + static_cast<int>(len));\n    } else {\n      // Only specify a minimum number of copies + moves. We don't want to\n      // depend on the reallocation policy here.\n      EXPECT_GE(tracker.copies() + tracker.moves(),\n                10);  // More due to reallocation.\n    }\n\n    // Shrinking resize() must destroy some objects\n    tracker.ResetCopiesMovesSwaps();\n    v.resize(len, Instance(100));\n    EXPECT_EQ(tracker.instances(), static_cast<int>(len));\n    EXPECT_EQ(tracker.copies(), 0);\n    EXPECT_EQ(tracker.moves(), 0);\n\n    // reserve() must not increase the number of initialized objects\n    SCOPED_TRACE(\"reserve\");\n    v.reserve(len + 1000);\n    EXPECT_EQ(tracker.instances(), static_cast<int>(len));\n    EXPECT_EQ(tracker.copies() + tracker.moves(), static_cast<int>(len));\n\n    // pop_back() and erase() must destroy one object\n    if (len > 0) {\n      tracker.ResetCopiesMovesSwaps();\n      v.pop_back();\n      EXPECT_EQ(tracker.instances(), static_cast<int>(len) - 1);\n      EXPECT_EQ(tracker.copies(), 0);\n      EXPECT_EQ(tracker.moves(), 0);\n\n      if (!v.empty()) {\n        tracker.ResetCopiesMovesSwaps();\n        v.erase(v.begin());\n        EXPECT_EQ(tracker.instances(), static_cast<int>(len) - 2);\n        EXPECT_EQ(tracker.copies() + tracker.moves(),\n                  static_cast<int>(len) - 2);\n      }\n    }\n\n    tracker.ResetCopiesMovesSwaps();\n    int instances_before_empty_erase = tracker.instances();\n    v.erase(v.begin(), v.begin());\n    EXPECT_EQ(tracker.instances(), instances_before_empty_erase);\n    EXPECT_EQ(tracker.copies() + tracker.moves(), 0);\n  }\n}\n\nTYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnCopyConstruction) {\n  using Instance = TypeParam;\n  using InstanceVec = absl::InlinedVector<Instance, 8>;\n  InstanceTracker tracker;\n  for (int len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    tracker.ResetCopiesMovesSwaps();\n\n    InstanceVec v;\n    for (int i = 0; i < len; i++) {\n      v.push_back(Instance(i));\n    }\n    EXPECT_EQ(tracker.instances(), len);\n    EXPECT_GE(tracker.copies() + tracker.moves(),\n              len);  // More due to reallocation.\n    tracker.ResetCopiesMovesSwaps();\n    {  // Copy constructor should create 'len' more instances.\n      InstanceVec v_copy(v);\n      EXPECT_EQ(v_copy.size(), v.size());\n      EXPECT_EQ(tracker.instances(), len + len);\n      EXPECT_EQ(tracker.copies(), len);\n      EXPECT_EQ(tracker.moves(), 0);\n    }\n    EXPECT_EQ(tracker.instances(), len);\n  }\n}\n\nTYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveConstruction) {\n  using Instance = TypeParam;\n  using InstanceVec = absl::InlinedVector<Instance, 8>;\n  InstanceTracker tracker;\n  for (int len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    tracker.ResetCopiesMovesSwaps();\n\n    InstanceVec v;\n    const size_t inlined_capacity = v.capacity();\n    for (int i = 0; i < len; i++) {\n      v.push_back(Instance(i));\n    }\n    EXPECT_EQ(tracker.instances(), len);\n    EXPECT_GE(tracker.copies() + tracker.moves(),\n              len);  // More due to reallocation.\n    tracker.ResetCopiesMovesSwaps();\n    {\n      InstanceVec v_copy(std::move(v));\n      EXPECT_EQ(v_copy.size(), len);\n      if (static_cast<size_t>(len) > inlined_capacity) {\n        // Allocation is moved as a whole.\n        EXPECT_EQ(tracker.instances(), len);\n        EXPECT_EQ(tracker.live_instances(), len);\n        // Tests an implementation detail, don't rely on this in your code.\n        EXPECT_EQ(v.size(), 0u);  // NOLINT misc-use-after-move\n        EXPECT_EQ(tracker.copies(), 0);\n        EXPECT_EQ(tracker.moves(), 0);\n      } else {\n        EXPECT_EQ(tracker.instances(), len + len);\n        if (Instance::supports_move()) {\n          EXPECT_EQ(tracker.live_instances(), len);\n          EXPECT_EQ(tracker.copies(), 0);\n          EXPECT_EQ(tracker.moves(), len);\n        } else {\n          EXPECT_EQ(tracker.live_instances(), len + len);\n          EXPECT_EQ(tracker.copies(), len);\n          EXPECT_EQ(tracker.moves(), 0);\n        }\n      }\n      EXPECT_EQ(tracker.swaps(), 0);\n    }\n  }\n}\n\nTYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnAssignment) {\n  using Instance = TypeParam;\n  using InstanceVec = absl::InlinedVector<Instance, 8>;\n  InstanceTracker tracker;\n  for (int len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    for (int longorshort = 0; longorshort <= 1; ++longorshort) {\n      SCOPED_TRACE(longorshort);\n      tracker.ResetCopiesMovesSwaps();\n\n      InstanceVec longer, shorter;\n      for (int i = 0; i < len; i++) {\n        longer.push_back(Instance(i));\n        shorter.push_back(Instance(i));\n      }\n      longer.push_back(Instance(len));\n      EXPECT_EQ(tracker.instances(), len + len + 1);\n      EXPECT_GE(tracker.copies() + tracker.moves(),\n                len + len + 1);  // More due to reallocation.\n\n      tracker.ResetCopiesMovesSwaps();\n      if (longorshort) {\n        shorter = longer;\n        EXPECT_EQ(tracker.instances(), (len + 1) + (len + 1));\n        EXPECT_GE(tracker.copies() + tracker.moves(),\n                  len + 1);  // More due to reallocation.\n      } else {\n        longer = shorter;\n        EXPECT_EQ(tracker.instances(), len + len);\n        EXPECT_EQ(tracker.copies() + tracker.moves(), len);\n      }\n    }\n  }\n}\n\nTYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveAssignment) {\n  using Instance = TypeParam;\n  using InstanceVec = absl::InlinedVector<Instance, 8>;\n  InstanceTracker tracker;\n  for (int len = 0; len < 20; len++) {\n    SCOPED_TRACE(len);\n    for (int longorshort = 0; longorshort <= 1; ++longorshort) {\n      SCOPED_TRACE(longorshort);\n      tracker.ResetCopiesMovesSwaps();\n\n      InstanceVec longer, shorter;\n      const size_t inlined_capacity = longer.capacity();\n      for (int i = 0; i < len; i++) {\n        longer.push_back(Instance(i));\n        shorter.push_back(Instance(i));\n      }\n      longer.push_back(Instance(len));\n      EXPECT_EQ(tracker.instances(), len + len + 1);\n      EXPECT_GE(tracker.copies() + tracker.moves(),\n                len + len + 1);  // More due to reallocation.\n\n      tracker.ResetCopiesMovesSwaps();\n      int src_len;\n      if (longorshort) {\n        src_len = len + 1;\n        shorter = std::move(longer);\n      } else {\n        src_len = len;\n        longer = std::move(shorter);\n      }\n      if (static_cast<size_t>(src_len) > inlined_capacity) {\n        // Allocation moved as a whole.\n        EXPECT_EQ(tracker.instances(), src_len);\n        EXPECT_EQ(tracker.live_instances(), src_len);\n        EXPECT_EQ(tracker.copies(), 0);\n        EXPECT_EQ(tracker.moves(), 0);\n      } else {\n        // Elements are all copied.\n        EXPECT_EQ(tracker.instances(), src_len + src_len);\n        if (Instance::supports_move()) {\n          EXPECT_EQ(tracker.copies(), 0);\n          EXPECT_EQ(tracker.moves(), src_len);\n          EXPECT_EQ(tracker.live_instances(), src_len);\n        } else {\n          EXPECT_EQ(tracker.copies(), src_len);\n          EXPECT_EQ(tracker.moves(), 0);\n          EXPECT_EQ(tracker.live_instances(), src_len + src_len);\n        }\n      }\n      EXPECT_EQ(tracker.swaps(), 0);\n    }\n  }\n}\n\nTEST(CountElemAssign, SimpleTypeWithInlineBacking) {\n  const size_t inlined_capacity = absl::InlinedVector<int, 2>().capacity();\n\n  for (size_t original_size = 0; original_size <= 5; ++original_size) {\n    SCOPED_TRACE(original_size);\n    // Original contents are [12345, 12345, ...]\n    std::vector<int> original_contents(original_size, 12345);\n\n    absl::InlinedVector<int, 2> v(original_contents.begin(),\n                                  original_contents.end());\n    v.assign(2, 123);\n    EXPECT_THAT(v, AllOf(SizeIs(2u), ElementsAre(123, 123)));\n    if (original_size <= inlined_capacity) {\n      // If the original had inline backing, it should stay inline.\n      EXPECT_EQ(v.capacity(), inlined_capacity);\n    }\n  }\n}\n\nTEST(CountElemAssign, SimpleTypeWithAllocation) {\n  for (size_t original_size = 0; original_size <= 5; ++original_size) {\n    SCOPED_TRACE(original_size);\n    // Original contents are [12345, 12345, ...]\n    std::vector<int> original_contents(original_size, 12345);\n\n    absl::InlinedVector<int, 2> v(original_contents.begin(),\n                                  original_contents.end());\n    v.assign(3, 123);\n    EXPECT_THAT(v, AllOf(SizeIs(3u), ElementsAre(123, 123, 123)));\n    EXPECT_LE(v.size(), v.capacity());\n  }\n}\n\nTYPED_TEST_P(InstanceTest, CountElemAssignInlineBacking) {\n  using Instance = TypeParam;\n  for (size_t original_size = 0; original_size <= 5; ++original_size) {\n    SCOPED_TRACE(original_size);\n    // Original contents are [12345, 12345, ...]\n    std::vector<Instance> original_contents(original_size, Instance(12345));\n\n    absl::InlinedVector<Instance, 2> v(original_contents.begin(),\n                                       original_contents.end());\n    v.assign(2, Instance(123));\n    EXPECT_THAT(v, AllOf(SizeIs(2u), ElementsAre(ValueIs(123), ValueIs(123))));\n    if (original_size <= 2) {\n      // If the original had inline backing, it should stay inline.\n      EXPECT_EQ(2u, v.capacity());\n    }\n  }\n}\n\ntemplate <typename Instance>\nvoid InstanceCountElemAssignWithAllocationTest() {\n  for (size_t original_size = 0; original_size <= 5; ++original_size) {\n    SCOPED_TRACE(original_size);\n    // Original contents are [12345, 12345, ...]\n    std::vector<Instance> original_contents(original_size, Instance(12345));\n\n    absl::InlinedVector<Instance, 2> v(original_contents.begin(),\n                                       original_contents.end());\n    v.assign(3, Instance(123));\n    EXPECT_THAT(v, AllOf(SizeIs(3u), ElementsAre(ValueIs(123), ValueIs(123),\n                                                 ValueIs(123))));\n    EXPECT_LE(v.size(), v.capacity());\n  }\n}\nTEST(CountElemAssign, WithAllocationCopyableInstance) {\n  InstanceCountElemAssignWithAllocationTest<CopyableOnlyInstance>();\n}\nTEST(CountElemAssign, WithAllocationCopyableMovableInstance) {\n  InstanceCountElemAssignWithAllocationTest<CopyableMovableInstance>();\n}\n\nTEST(RangedConstructor, SimpleType) {\n  std::vector<int> source_v = {4, 5, 6};\n  // First try to fit in inline backing\n  absl::InlinedVector<int, 4> v(source_v.begin(), source_v.end());\n  EXPECT_EQ(3u, v.size());\n  EXPECT_EQ(4u,\n            v.capacity());  // Indication that we're still on inlined storage\n  EXPECT_EQ(4, v[0]);\n  EXPECT_EQ(5, v[1]);\n  EXPECT_EQ(6, v[2]);\n\n  // Now, force a re-allocate\n  absl::InlinedVector<int, 2> realloc_v(source_v.begin(), source_v.end());\n  EXPECT_EQ(3u, realloc_v.size());\n  EXPECT_LT(2u, realloc_v.capacity());\n  EXPECT_EQ(4, realloc_v[0]);\n  EXPECT_EQ(5, realloc_v[1]);\n  EXPECT_EQ(6, realloc_v[2]);\n}\n\n// Test for ranged constructors using Instance as the element type and\n// SourceContainer as the source container type.\ntemplate <typename Instance, typename SourceContainer, int inlined_capacity>\nvoid InstanceRangedConstructorTestForContainer() {\n  InstanceTracker tracker;\n  SourceContainer source_v = {Instance(0), Instance(1)};\n  tracker.ResetCopiesMovesSwaps();\n  absl::InlinedVector<Instance, inlined_capacity> v(source_v.begin(),\n                                                    source_v.end());\n  EXPECT_EQ(2u, v.size());\n  EXPECT_LT(1u, v.capacity());\n  EXPECT_EQ(0, v[0].value());\n  EXPECT_EQ(1, v[1].value());\n  EXPECT_EQ(tracker.copies(), 2);\n  EXPECT_EQ(tracker.moves(), 0);\n}\n\ntemplate <typename Instance, int inlined_capacity>\nvoid InstanceRangedConstructorTestWithCapacity() {\n  // Test with const and non-const, random access and non-random-access sources.\n  // TODO(bsamwel): Test with an input iterator source.\n  {\n    SCOPED_TRACE(\"std::list\");\n    InstanceRangedConstructorTestForContainer<Instance, std::list<Instance>,\n                                              inlined_capacity>();\n    {\n      SCOPED_TRACE(\"const std::list\");\n      InstanceRangedConstructorTestForContainer<\n          Instance, const std::list<Instance>, inlined_capacity>();\n    }\n    {\n      SCOPED_TRACE(\"std::vector\");\n      InstanceRangedConstructorTestForContainer<Instance, std::vector<Instance>,\n                                                inlined_capacity>();\n    }\n    {\n      SCOPED_TRACE(\"const std::vector\");\n      InstanceRangedConstructorTestForContainer<\n          Instance, const std::vector<Instance>, inlined_capacity>();\n    }\n  }\n}\n\nTYPED_TEST_P(InstanceTest, RangedConstructor) {\n  using Instance = TypeParam;\n  SCOPED_TRACE(\"capacity=1\");\n  InstanceRangedConstructorTestWithCapacity<Instance, 1>();\n  SCOPED_TRACE(\"capacity=2\");\n  InstanceRangedConstructorTestWithCapacity<Instance, 2>();\n}\n\nTEST(RangedConstructor, ElementsAreConstructed) {\n  std::vector<std::string> source_v = {\"cat\", \"dog\"};\n\n  // Force expansion and re-allocation of v.  Ensures that when the vector is\n  // expanded that new elements are constructed.\n  absl::InlinedVector<std::string, 1> v(source_v.begin(), source_v.end());\n  EXPECT_EQ(\"cat\", v[0]);\n  EXPECT_EQ(\"dog\", v[1]);\n}\n\nTEST(RangedAssign, SimpleType) {\n  const size_t inlined_capacity = absl::InlinedVector<int, 3>().capacity();\n\n  // Test for all combinations of original sizes (empty and non-empty inline,\n  // and out of line) and target sizes.\n  for (size_t original_size = 0; original_size <= 5; ++original_size) {\n    SCOPED_TRACE(original_size);\n    // Original contents are [12345, 12345, ...]\n    std::vector<int> original_contents(original_size, 12345);\n\n    for (size_t target_size = 0; target_size <= 5; ++target_size) {\n      SCOPED_TRACE(target_size);\n\n      // New contents are [3, 4, ...]\n      std::vector<int> new_contents;\n      for (size_t i = 0; i < target_size; ++i) {\n        new_contents.push_back(static_cast<int>(i + 3));\n      }\n\n      absl::InlinedVector<int, 3> v(original_contents.begin(),\n                                    original_contents.end());\n      v.assign(new_contents.begin(), new_contents.end());\n\n      EXPECT_EQ(new_contents.size(), v.size());\n      EXPECT_LE(new_contents.size(), v.capacity());\n      if (target_size <= inlined_capacity &&\n          original_size <= inlined_capacity) {\n        // Storage should stay inline when target size is small.\n        EXPECT_EQ(v.capacity(), inlined_capacity);\n      }\n      EXPECT_THAT(v, ElementsAreArray(new_contents));\n    }\n  }\n}\n\n// Returns true if lhs and rhs have the same value.\ntemplate <typename Instance>\nstatic bool InstanceValuesEqual(const Instance& lhs, const Instance& rhs) {\n  return lhs.value() == rhs.value();\n}\n\n// Test for ranged assign() using Instance as the element type and\n// SourceContainer as the source container type.\ntemplate <typename Instance, typename SourceContainer>\nvoid InstanceRangedAssignTestForContainer() {\n  // Test for all combinations of original sizes (empty and non-empty inline,\n  // and out of line) and target sizes.\n  for (size_t original_size = 0; original_size <= 5; ++original_size) {\n    SCOPED_TRACE(original_size);\n    // Original contents are [12345, 12345, ...]\n    std::vector<Instance> original_contents(original_size, Instance(12345));\n\n    for (size_t target_size = 0; target_size <= 5; ++target_size) {\n      SCOPED_TRACE(target_size);\n\n      // New contents are [3, 4, ...]\n      // Generate data using a non-const container, because SourceContainer\n      // itself may be const.\n      // TODO(bsamwel): Test with an input iterator.\n      std::vector<Instance> new_contents_in;\n      for (size_t i = 0; i < target_size; ++i) {\n        new_contents_in.push_back(Instance(static_cast<int>(i) + 3));\n      }\n      SourceContainer new_contents(new_contents_in.begin(),\n                                   new_contents_in.end());\n\n      absl::InlinedVector<Instance, 3> v(original_contents.begin(),\n                                         original_contents.end());\n      v.assign(new_contents.begin(), new_contents.end());\n\n      EXPECT_EQ(new_contents.size(), v.size());\n      EXPECT_LE(new_contents.size(), v.capacity());\n      if (target_size <= 3 && original_size <= 3) {\n        // Storage should stay inline when target size is small.\n        EXPECT_EQ(3u, v.capacity());\n      }\n      EXPECT_TRUE(std::equal(v.begin(), v.end(), new_contents.begin(),\n                             InstanceValuesEqual<Instance>));\n    }\n  }\n}\n\nTYPED_TEST_P(InstanceTest, RangedAssign) {\n  using Instance = TypeParam;\n  // Test with const and non-const, random access and non-random-access sources.\n  // TODO(bsamwel): Test with an input iterator source.\n  SCOPED_TRACE(\"std::list\");\n  InstanceRangedAssignTestForContainer<Instance, std::list<Instance>>();\n  SCOPED_TRACE(\"const std::list\");\n  InstanceRangedAssignTestForContainer<Instance, const std::list<Instance>>();\n  SCOPED_TRACE(\"std::vector\");\n  InstanceRangedAssignTestForContainer<Instance, std::vector<Instance>>();\n  SCOPED_TRACE(\"const std::vector\");\n  InstanceRangedAssignTestForContainer<Instance, const std::vector<Instance>>();\n}\n\nTEST(InitializerListConstructor, SimpleTypeWithInlineBacking) {\n  EXPECT_THAT((absl::InlinedVector<int, 4>{4, 5, 6}),\n              AllOf(SizeIs(3u), CapacityIs(4u), ElementsAre(4, 5, 6)));\n}\n\nTEST(InitializerListConstructor, SimpleTypeWithReallocationRequired) {\n  EXPECT_THAT((absl::InlinedVector<int, 2>{4, 5, 6}),\n              AllOf(SizeIs(3u), CapacityIs(Gt(2u)), ElementsAre(4, 5, 6)));\n}\n\nTEST(InitializerListConstructor, DisparateTypesInList) {\n  EXPECT_THAT((absl::InlinedVector<int, 2>{-7, 8ULL}), ElementsAre(-7, 8));\n\n  EXPECT_THAT((absl::InlinedVector<std::string, 2>{\"foo\", std::string(\"bar\")}),\n              ElementsAre(\"foo\", \"bar\"));\n}\n\nTEST(InitializerListConstructor, ComplexTypeWithInlineBacking) {\n  const size_t inlined_capacity =\n      absl::InlinedVector<CopyableMovableInstance, 1>().capacity();\n  EXPECT_THAT(\n      (absl::InlinedVector<CopyableMovableInstance, 1>{\n          CopyableMovableInstance(0)}),\n      AllOf(SizeIs(1u), CapacityIs(inlined_capacity), ElementsAre(ValueIs(0))));\n}\n\nTEST(InitializerListConstructor, ComplexTypeWithReallocationRequired) {\n  EXPECT_THAT((absl::InlinedVector<CopyableMovableInstance, 1>{\n                  CopyableMovableInstance(0), CopyableMovableInstance(1)}),\n              AllOf(SizeIs(2u), CapacityIs(Gt(1u)),\n                    ElementsAre(ValueIs(0), ValueIs(1))));\n}\n\nTEST(InitializerListAssign, SimpleTypeFitsInlineBacking) {\n  for (size_t original_size = 0; original_size <= 4; ++original_size) {\n    SCOPED_TRACE(original_size);\n\n    absl::InlinedVector<int, 2> v1(original_size, 12345);\n    const size_t original_capacity_v1 = v1.capacity();\n    v1.assign({3});\n    EXPECT_THAT(v1, AllOf(SizeIs(1u), CapacityIs(original_capacity_v1),\n                          ElementsAre(3)));\n\n    absl::InlinedVector<int, 2> v2(original_size, 12345);\n    const size_t original_capacity_v2 = v2.capacity();\n    v2 = {3};\n    EXPECT_THAT(v2, AllOf(SizeIs(1u), CapacityIs(original_capacity_v2),\n                          ElementsAre(3)));\n  }\n}\n\nTEST(InitializerListAssign, SimpleTypeDoesNotFitInlineBacking) {\n  for (size_t original_size = 0; original_size <= 4; ++original_size) {\n    SCOPED_TRACE(original_size);\n    absl::InlinedVector<int, 2> v1(original_size, 12345);\n    v1.assign({3, 4, 5});\n    EXPECT_THAT(v1, AllOf(SizeIs(3u), ElementsAre(3, 4, 5)));\n    EXPECT_LE(3u, v1.capacity());\n\n    absl::InlinedVector<int, 2> v2(original_size, 12345);\n    v2 = {3, 4, 5};\n    EXPECT_THAT(v2, AllOf(SizeIs(3u), ElementsAre(3, 4, 5)));\n    EXPECT_LE(3u, v2.capacity());\n  }\n}\n\nTEST(InitializerListAssign, DisparateTypesInList) {\n  absl::InlinedVector<int, 2> v_int1;\n  v_int1.assign({-7, 8ULL});\n  EXPECT_THAT(v_int1, ElementsAre(-7, 8));\n\n  absl::InlinedVector<int, 2> v_int2;\n  v_int2 = {-7, 8ULL};\n  EXPECT_THAT(v_int2, ElementsAre(-7, 8));\n\n  absl::InlinedVector<std::string, 2> v_string1;\n  v_string1.assign({\"foo\", std::string(\"bar\")});\n  EXPECT_THAT(v_string1, ElementsAre(\"foo\", \"bar\"));\n\n  absl::InlinedVector<std::string, 2> v_string2;\n  v_string2 = {\"foo\", std::string(\"bar\")};\n  EXPECT_THAT(v_string2, ElementsAre(\"foo\", \"bar\"));\n}\n\nTYPED_TEST_P(InstanceTest, InitializerListAssign) {\n  using Instance = TypeParam;\n  for (size_t original_size = 0; original_size <= 4; ++original_size) {\n    SCOPED_TRACE(original_size);\n    absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));\n    const size_t original_capacity = v.capacity();\n    v.assign({Instance(3)});\n    EXPECT_THAT(v, AllOf(SizeIs(1u), CapacityIs(original_capacity),\n                         ElementsAre(ValueIs(3))));\n  }\n  for (size_t original_size = 0; original_size <= 4; ++original_size) {\n    SCOPED_TRACE(original_size);\n    absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));\n    v.assign({Instance(3), Instance(4), Instance(5)});\n    EXPECT_THAT(\n        v, AllOf(SizeIs(3u), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));\n    EXPECT_LE(3u, v.capacity());\n  }\n}\n\nREGISTER_TYPED_TEST_SUITE_P(InstanceTest, Swap, CountConstructorsDestructors,\n                            CountConstructorsDestructorsOnCopyConstruction,\n                            CountConstructorsDestructorsOnMoveConstruction,\n                            CountConstructorsDestructorsOnAssignment,\n                            CountConstructorsDestructorsOnMoveAssignment,\n                            CountElemAssignInlineBacking, RangedConstructor,\n                            RangedAssign, InitializerListAssign);\n\nusing InstanceTypes =\n    ::testing::Types<CopyableOnlyInstance, CopyableMovableInstance>;\nINSTANTIATE_TYPED_TEST_SUITE_P(InstanceTestOnTypes, InstanceTest,\n                               InstanceTypes);\n\nTEST(DynamicVec, DynamicVecCompiles) {\n  DynamicVec v;\n  (void)v;\n}\n\nTEST(DynamicVec, CreateNonEmptyDynamicVec) {\n  DynamicVec v(1);\n  EXPECT_EQ(v.size(), 1u);\n}\n\nTEST(DynamicVec, EmplaceBack) {\n  DynamicVec v;\n  v.emplace_back(Dynamic{});\n  EXPECT_EQ(v.size(), 1u);\n}\n\nTEST(DynamicVec, EmplaceBackAfterHeapAllocation) {\n  DynamicVec v;\n  v.reserve(10);\n  v.emplace_back(Dynamic{});\n  EXPECT_EQ(v.size(), 1u);\n}\n\nTEST(DynamicVec, EmptyIteratorComparison) {\n  DynamicVec v;\n  EXPECT_EQ(v.begin(), v.end());\n  EXPECT_EQ(v.cbegin(), v.cend());\n}\n\nTEST(AllocatorSupportTest, Constructors) {\n  using MyAlloc = CountingAllocator<int>;\n  using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;\n  const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};\n  int64_t allocated = 0;\n  MyAlloc alloc(&allocated);\n  { AllocVec ABSL_ATTRIBUTE_UNUSED v; }\n  { AllocVec ABSL_ATTRIBUTE_UNUSED v(alloc); }\n  { AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); }\n  { AllocVec ABSL_ATTRIBUTE_UNUSED v({1, 2, 3}, alloc); }\n\n  AllocVec v2;\n  { AllocVec ABSL_ATTRIBUTE_UNUSED v(v2, alloc); }\n  { AllocVec ABSL_ATTRIBUTE_UNUSED v(std::move(v2), alloc); }\n}\n\nTEST(AllocatorSupportTest, CountAllocations) {\n  using MyAlloc = CountingAllocator<int>;\n  using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;\n  const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};\n  int64_t bytes_allocated = 0;\n  int64_t instance_count = 0;\n  MyAlloc alloc(&bytes_allocated, &instance_count);\n  {\n    AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc);\n    EXPECT_THAT(bytes_allocated, Eq(0));\n    EXPECT_THAT(instance_count, Eq(4));\n  }\n  EXPECT_THAT(bytes_allocated, Eq(0));\n  EXPECT_THAT(instance_count, Eq(0));\n  {\n    AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc);\n    EXPECT_THAT(bytes_allocated,\n                Eq(static_cast<int64_t>(v.size() * sizeof(int))));\n    EXPECT_THAT(instance_count, Eq(static_cast<int64_t>(v.size())));\n  }\n  EXPECT_THAT(bytes_allocated, Eq(0));\n  EXPECT_THAT(instance_count, Eq(0));\n  {\n    AllocVec v(4, 1, alloc);\n    EXPECT_THAT(bytes_allocated, Eq(0));\n    EXPECT_THAT(instance_count, Eq(4));\n\n    int64_t bytes_allocated2 = 0;\n    MyAlloc alloc2(&bytes_allocated2);\n    ABSL_ATTRIBUTE_UNUSED AllocVec v2(v, alloc2);\n    EXPECT_THAT(bytes_allocated2, Eq(0));\n\n    int64_t bytes_allocated3 = 0;\n    MyAlloc alloc3(&bytes_allocated3);\n    ABSL_ATTRIBUTE_UNUSED AllocVec v3(std::move(v), alloc3);\n    EXPECT_THAT(bytes_allocated3, Eq(0));\n  }\n  EXPECT_THAT(bytes_allocated, Eq(0));\n  EXPECT_THAT(instance_count, Eq(0));\n  {\n    AllocVec v(8, 2, alloc);\n    EXPECT_THAT(bytes_allocated,\n                Eq(static_cast<int64_t>(v.size() * sizeof(int))));\n    EXPECT_THAT(instance_count, Eq(static_cast<int64_t>(v.size())));\n\n    int64_t bytes_allocated2 = 0;\n    MyAlloc alloc2(&bytes_allocated2);\n    AllocVec v2(v, alloc2);\n    EXPECT_THAT(bytes_allocated2,\n                Eq(static_cast<int64_t>(v2.size() * sizeof(int))));\n\n    int64_t bytes_allocated3 = 0;\n    MyAlloc alloc3(&bytes_allocated3);\n    AllocVec v3(std::move(v), alloc3);\n    EXPECT_THAT(bytes_allocated3,\n                Eq(static_cast<int64_t>(v3.size() * sizeof(int))));\n  }\n  EXPECT_EQ(bytes_allocated, 0);\n  EXPECT_EQ(instance_count, 0);\n  {\n    // Test shrink_to_fit deallocations.\n    AllocVec v(8, 2, alloc);\n    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(8 * sizeof(int)));\n    EXPECT_EQ(instance_count, 8);\n    v.resize(5);\n    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(8 * sizeof(int)));\n    EXPECT_EQ(instance_count, 5);\n    v.shrink_to_fit();\n    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(5 * sizeof(int)));\n    EXPECT_EQ(instance_count, 5);\n    v.resize(4);\n    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(5 * sizeof(int)));\n    EXPECT_EQ(instance_count, 4);\n    v.shrink_to_fit();\n    EXPECT_EQ(bytes_allocated, 0);\n    EXPECT_EQ(instance_count, 4);\n  }\n  EXPECT_EQ(instance_count, 0);\n}\n\nTEST(AllocatorSupportTest, SwapBothAllocated) {\n  using MyAlloc = CountingAllocator<int>;\n  using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;\n  int64_t allocated1 = 0;\n  int64_t allocated2 = 0;\n  {\n    const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};\n    const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};\n    MyAlloc a1(&allocated1);\n    MyAlloc a2(&allocated2);\n    AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);\n    AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);\n    EXPECT_LT(v1.capacity(), v2.capacity());\n    EXPECT_THAT(allocated1,\n                Eq(static_cast<int64_t>(v1.capacity() * sizeof(int))));\n    EXPECT_THAT(allocated2,\n                Eq(static_cast<int64_t>(v2.capacity() * sizeof(int))));\n    v1.swap(v2);\n    EXPECT_THAT(v1, ElementsAreArray(ia2));\n    EXPECT_THAT(v2, ElementsAreArray(ia1));\n    EXPECT_THAT(allocated1,\n                Eq(static_cast<int64_t>(v2.capacity() * sizeof(int))));\n    EXPECT_THAT(allocated2,\n                Eq(static_cast<int64_t>(v1.capacity() * sizeof(int))));\n  }\n  EXPECT_THAT(allocated1, 0);\n  EXPECT_THAT(allocated2, 0);\n}\n\nTEST(AllocatorSupportTest, SwapOneAllocated) {\n  using MyAlloc = CountingAllocator<int>;\n  using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;\n  int64_t allocated1 = 0;\n  int64_t allocated2 = 0;\n  {\n    const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};\n    const int ia2[] = {0, 1, 2, 3};\n    MyAlloc a1(&allocated1);\n    MyAlloc a2(&allocated2);\n    AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);\n    AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);\n    EXPECT_THAT(allocated1,\n                Eq(static_cast<int64_t>(v1.capacity() * sizeof(int))));\n    EXPECT_THAT(allocated2, Eq(0));\n    v1.swap(v2);\n    EXPECT_THAT(v1, ElementsAreArray(ia2));\n    EXPECT_THAT(v2, ElementsAreArray(ia1));\n    EXPECT_THAT(allocated1,\n                Eq(static_cast<int64_t>(v2.capacity() * sizeof(int))));\n    EXPECT_THAT(allocated2, Eq(0));\n    EXPECT_TRUE(v2.get_allocator() == a1);\n    EXPECT_TRUE(v1.get_allocator() == a2);\n  }\n  EXPECT_THAT(allocated1, 0);\n  EXPECT_THAT(allocated2, 0);\n}\n\nTEST(AllocatorSupportTest, ScopedAllocatorWorksInlined) {\n  using StdVector = std::vector<int, CountingAllocator<int>>;\n  using Alloc = CountingAllocator<StdVector>;\n  using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;\n  using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;\n\n  int64_t total_allocated_byte_count = 0;\n\n  AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));\n\n  // Called only once to remain inlined\n  inlined_case.emplace_back();\n\n  int64_t absl_responsible_for_count = total_allocated_byte_count;\n\n  // MSVC's allocator preemptively allocates in debug mode\n#if !defined(_MSC_VER)\n  EXPECT_EQ(absl_responsible_for_count, 0);\n#endif  // !defined(_MSC_VER)\n\n  inlined_case[0].emplace_back();\n  EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);\n\n  inlined_case.clear();\n  inlined_case.shrink_to_fit();\n  EXPECT_EQ(total_allocated_byte_count, 0);\n}\n\nTEST(AllocatorSupportTest, ScopedAllocatorWorksAllocated) {\n  using StdVector = std::vector<int, CountingAllocator<int>>;\n  using Alloc = CountingAllocator<StdVector>;\n  using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;\n  using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;\n\n  int64_t total_allocated_byte_count = 0;\n\n  AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));\n\n  // Called twice to force into being allocated\n  allocated_case.emplace_back();\n  allocated_case.emplace_back();\n\n  int64_t absl_responsible_for_count = total_allocated_byte_count;\n  EXPECT_GT(absl_responsible_for_count, 0);\n\n  allocated_case[1].emplace_back();\n  EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);\n\n  allocated_case.clear();\n  allocated_case.shrink_to_fit();\n  EXPECT_EQ(total_allocated_byte_count, 0);\n}\n\nTEST(AllocatorSupportTest, SizeAllocConstructor) {\n  constexpr size_t inlined_size = 4;\n  using Alloc = CountingAllocator<int>;\n  using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>;\n\n  {\n    auto len = inlined_size / 2;\n    int64_t allocated = 0;\n    auto v = AllocVec(len, Alloc(&allocated));\n\n    // Inline storage used; allocator should not be invoked\n    EXPECT_THAT(allocated, Eq(0));\n    EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));\n  }\n\n  {\n    auto len = inlined_size * 2;\n    int64_t allocated = 0;\n    auto v = AllocVec(len, Alloc(&allocated));\n\n    // Out of line storage used; allocation of 8 elements expected\n    EXPECT_THAT(allocated, Eq(static_cast<int64_t>(len * sizeof(int))));\n    EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));\n  }\n}\n\nTEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) {\n  using T = int;\n  using A = std::allocator<T>;\n  using ATraits = absl::allocator_traits<A>;\n\n  struct MinimumAllocator {\n    using value_type = T;\n\n    value_type* allocate(size_t n) {\n      A a;\n      return ATraits::allocate(a, n);\n    }\n\n    void deallocate(value_type* p, size_t n) {\n      A a;\n      ATraits::deallocate(a, p, n);\n    }\n  };\n\n  absl::InlinedVector<T, 1, MinimumAllocator> vec;\n  vec.emplace_back();\n  vec.resize(0);\n}\n\nTEST(InlinedVectorTest, AbslHashValueWorks) {\n  using V = absl::InlinedVector<int, 4>;\n  std::vector<V> cases;\n\n  // Generate a variety of vectors some of these are small enough for the inline\n  // space but are stored out of line.\n  for (size_t i = 0; i < 10; ++i) {\n    V v;\n    for (int j = 0; j < static_cast<int>(i); ++j) {\n      v.push_back(j);\n    }\n    cases.push_back(v);\n    v.resize(i % 4);\n    cases.push_back(v);\n  }\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));\n}\n\nclass MoveConstructibleOnlyInstance\n    : public absl::test_internal::BaseCountedInstance {\n public:\n  explicit MoveConstructibleOnlyInstance(int x) : BaseCountedInstance(x) {}\n  MoveConstructibleOnlyInstance(MoveConstructibleOnlyInstance&& other) =\n      default;\n  MoveConstructibleOnlyInstance& operator=(\n      MoveConstructibleOnlyInstance&& other) = delete;\n};\n\nMATCHER(HasValue, \"\") {\n  return ::testing::get<0>(arg).value() == ::testing::get<1>(arg);\n}\n\nTEST(NonAssignableMoveAssignmentTest, AllocatedToInline) {\n  using X = MoveConstructibleOnlyInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> inlined;\n  inlined.emplace_back(1);\n  absl::InlinedVector<X, 2> allocated;\n  allocated.emplace_back(1);\n  allocated.emplace_back(2);\n  allocated.emplace_back(3);\n  tracker.ResetCopiesMovesSwaps();\n\n  inlined = std::move(allocated);\n  // passed ownership of the allocated storage\n  EXPECT_EQ(tracker.moves(), 0);\n  EXPECT_EQ(tracker.live_instances(), 3);\n\n  EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3}));\n}\n\nTEST(NonAssignableMoveAssignmentTest, InlineToAllocated) {\n  using X = MoveConstructibleOnlyInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> inlined;\n  inlined.emplace_back(1);\n  absl::InlinedVector<X, 2> allocated;\n  allocated.emplace_back(1);\n  allocated.emplace_back(2);\n  allocated.emplace_back(3);\n  tracker.ResetCopiesMovesSwaps();\n\n  allocated = std::move(inlined);\n  // Moved elements\n  EXPECT_EQ(tracker.moves(), 1);\n  EXPECT_EQ(tracker.live_instances(), 1);\n\n  EXPECT_THAT(allocated, Pointwise(HasValue(), {1}));\n}\n\nTEST(NonAssignableMoveAssignmentTest, InlineToInline) {\n  using X = MoveConstructibleOnlyInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> inlined_a;\n  inlined_a.emplace_back(1);\n  absl::InlinedVector<X, 2> inlined_b;\n  inlined_b.emplace_back(1);\n  tracker.ResetCopiesMovesSwaps();\n\n  inlined_a = std::move(inlined_b);\n  // Moved elements\n  EXPECT_EQ(tracker.moves(), 1);\n  EXPECT_EQ(tracker.live_instances(), 1);\n\n  EXPECT_THAT(inlined_a, Pointwise(HasValue(), {1}));\n}\n\nTEST(NonAssignableMoveAssignmentTest, AllocatedToAllocated) {\n  using X = MoveConstructibleOnlyInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> allocated_a;\n  allocated_a.emplace_back(1);\n  allocated_a.emplace_back(2);\n  allocated_a.emplace_back(3);\n  absl::InlinedVector<X, 2> allocated_b;\n  allocated_b.emplace_back(4);\n  allocated_b.emplace_back(5);\n  allocated_b.emplace_back(6);\n  allocated_b.emplace_back(7);\n  tracker.ResetCopiesMovesSwaps();\n\n  allocated_a = std::move(allocated_b);\n  // passed ownership of the allocated storage\n  EXPECT_EQ(tracker.moves(), 0);\n  EXPECT_EQ(tracker.live_instances(), 4);\n\n  EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7}));\n}\n\nTEST(NonAssignableMoveAssignmentTest, AssignThis) {\n  using X = MoveConstructibleOnlyInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> v;\n  v.emplace_back(1);\n  v.emplace_back(2);\n  v.emplace_back(3);\n\n  tracker.ResetCopiesMovesSwaps();\n\n  // Obfuscated in order to pass -Wself-move.\n  v = std::move(*std::addressof(v));\n  // nothing happens\n  EXPECT_EQ(tracker.moves(), 0);\n  EXPECT_EQ(tracker.live_instances(), 3);\n\n  EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3}));\n}\n\nclass NonSwappableInstance : public absl::test_internal::BaseCountedInstance {\n public:\n  explicit NonSwappableInstance(int x) : BaseCountedInstance(x) {}\n  NonSwappableInstance(const NonSwappableInstance& other) = default;\n  NonSwappableInstance& operator=(const NonSwappableInstance& other) = default;\n  NonSwappableInstance(NonSwappableInstance&& other) = default;\n  NonSwappableInstance& operator=(NonSwappableInstance&& other) = default;\n};\n\nvoid swap(NonSwappableInstance&, NonSwappableInstance&) = delete;\n\nTEST(NonSwappableSwapTest, InlineAndAllocatedTransferStorageAndMove) {\n  using X = NonSwappableInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> inlined;\n  inlined.emplace_back(1);\n  absl::InlinedVector<X, 2> allocated;\n  allocated.emplace_back(1);\n  allocated.emplace_back(2);\n  allocated.emplace_back(3);\n  tracker.ResetCopiesMovesSwaps();\n\n  inlined.swap(allocated);\n  EXPECT_EQ(tracker.moves(), 1);\n  EXPECT_EQ(tracker.live_instances(), 4);\n\n  EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3}));\n}\n\nTEST(NonSwappableSwapTest, InlineAndInlineMoveIndividualElements) {\n  using X = NonSwappableInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> inlined_a;\n  inlined_a.emplace_back(1);\n  absl::InlinedVector<X, 2> inlined_b;\n  inlined_b.emplace_back(2);\n  tracker.ResetCopiesMovesSwaps();\n\n  inlined_a.swap(inlined_b);\n  EXPECT_EQ(tracker.moves(), 3);\n  EXPECT_EQ(tracker.live_instances(), 2);\n\n  EXPECT_THAT(inlined_a, Pointwise(HasValue(), {2}));\n  EXPECT_THAT(inlined_b, Pointwise(HasValue(), {1}));\n}\n\nTEST(NonSwappableSwapTest, AllocatedAndAllocatedOnlyTransferStorage) {\n  using X = NonSwappableInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> allocated_a;\n  allocated_a.emplace_back(1);\n  allocated_a.emplace_back(2);\n  allocated_a.emplace_back(3);\n  absl::InlinedVector<X, 2> allocated_b;\n  allocated_b.emplace_back(4);\n  allocated_b.emplace_back(5);\n  allocated_b.emplace_back(6);\n  allocated_b.emplace_back(7);\n  tracker.ResetCopiesMovesSwaps();\n\n  allocated_a.swap(allocated_b);\n  EXPECT_EQ(tracker.moves(), 0);\n  EXPECT_EQ(tracker.live_instances(), 7);\n\n  EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7}));\n  EXPECT_THAT(allocated_b, Pointwise(HasValue(), {1, 2, 3}));\n}\n\nTEST(NonSwappableSwapTest, SwapThis) {\n  using X = NonSwappableInstance;\n  InstanceTracker tracker;\n  absl::InlinedVector<X, 2> v;\n  v.emplace_back(1);\n  v.emplace_back(2);\n  v.emplace_back(3);\n\n  tracker.ResetCopiesMovesSwaps();\n\n  v.swap(v);\n  EXPECT_EQ(tracker.moves(), 0);\n  EXPECT_EQ(tracker.live_instances(), 3);\n\n  EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3}));\n}\n\ntemplate <size_t N>\nusing CharVec = absl::InlinedVector<char, N>;\n\n// Warning: This struct \"simulates\" the type `InlinedVector::Storage::Allocated`\n// to make reasonable expectations for inlined storage capacity optimization. If\n// implementation changes `Allocated`, then `MySpan` and tests that use it need\n// to be updated accordingly.\ntemplate <typename T>\nstruct MySpan {\n  T* data;\n  size_t size;\n};\n\nTEST(StorageTest, InlinedCapacityAutoIncrease) {\n  // The requested capacity is auto increased to `sizeof(MySpan<char>)`.\n  EXPECT_GT(CharVec<1>().capacity(), 1);\n  EXPECT_EQ(CharVec<1>().capacity(), sizeof(MySpan<char>));\n  EXPECT_EQ(CharVec<1>().capacity(), CharVec<2>().capacity());\n  EXPECT_EQ(sizeof(CharVec<1>), sizeof(CharVec<2>));\n\n  // The requested capacity is auto increased to\n  // `sizeof(MySpan<int>) / sizeof(int)`.\n  EXPECT_GT((absl::InlinedVector<int, 1>().capacity()), 1);\n  EXPECT_EQ((absl::InlinedVector<int, 1>().capacity()),\n            sizeof(MySpan<int>) / sizeof(int));\n}\n\nTEST(IntVec, EraseIf) {\n  IntVec v = {3, 1, 2, 0};\n  EXPECT_EQ(absl::erase_if(v, [](int i) { return i > 1; }), 2u);\n  EXPECT_THAT(v, ElementsAre(1, 0));\n}\n\nTEST(IntVec, EraseIfMatchesNone) {\n  IntVec v = {1, 2, 3};\n  EXPECT_EQ(absl::erase_if(v, [](int i) { return i > 10; }), 0u);;\n  EXPECT_THAT(v, ElementsAre(1, 2, 3));\n}\n\nTEST(IntVec, EraseIfMatchesAll) {\n  IntVec v = {1, 2, 3};\n  EXPECT_EQ(absl::erase_if(v, [](int i) { return i > 0; }), 3u);\n  EXPECT_THAT(v, IsEmpty());\n}\n\n}  // anonymous namespace\n"
  },
  {
    "path": "absl/container/internal/btree.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// A btree implementation of the STL set and map interfaces. A btree is smaller\n// and generally also faster than STL set/map (refer to the benchmarks below).\n// The red-black tree implementation of STL set/map has an overhead of 3\n// pointers (left, right and parent) plus the node color information for each\n// stored value. So a set<int32_t> consumes 40 bytes for each value stored in\n// 64-bit mode. This btree implementation stores multiple values on fixed\n// size nodes (usually 256 bytes) and doesn't store child pointers for leaf\n// nodes. The result is that a btree_set<int32_t> may use much less memory per\n// stored value. For the random insertion benchmark in btree_bench.cc, a\n// btree_set<int32_t> with node-size of 256 uses 5.1 bytes per stored value.\n//\n// The packing of multiple values on to each node of a btree has another effect\n// besides better space utilization: better cache locality due to fewer cache\n// lines being accessed. Better cache locality translates into faster\n// operations.\n//\n// CAVEATS\n//\n// Insertions and deletions on a btree can cause splitting, merging or\n// rebalancing of btree nodes. And even without these operations, insertions\n// and deletions on a btree will move values around within a node. In both\n// cases, the result is that insertions and deletions can invalidate iterators\n// pointing to values other than the one being inserted/deleted. Therefore, this\n// container does not provide pointer stability. This is notably different from\n// STL set/map which takes care to not invalidate iterators on insert/erase\n// except, of course, for iterators pointing to the value being erased.  A\n// partial workaround when erasing is available: erase() returns an iterator\n// pointing to the item just after the one that was erased (or end() if none\n// exists).\n\n#ifndef ABSL_CONTAINER_INTERNAL_BTREE_H_\n#define ABSL_CONTAINER_INTERNAL_BTREE_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <functional>\n#include <iterator>\n#include <limits>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/container/internal/common.h\"\n#include \"absl/container/internal/common_policy_traits.h\"\n#include \"absl/container/internal/compressed_tuple.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/layout.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/compare.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\n#error ABSL_BTREE_ENABLE_GENERATIONS cannot be directly set\n#elif (defined(ABSL_HAVE_ADDRESS_SANITIZER) ||   \\\n       defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \\\n       defined(ABSL_HAVE_MEMORY_SANITIZER)) &&   \\\n    !defined(NDEBUG_SANITIZER)  // If defined, performance is important.\n// When compiled in sanitizer mode, we add generation integers to the nodes and\n// iterators. When iterators are used, we validate that the container has not\n// been mutated since the iterator was constructed.\n#define ABSL_BTREE_ENABLE_GENERATIONS\n#endif\n\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\nconstexpr bool BtreeGenerationsEnabled() { return true; }\n#else\nconstexpr bool BtreeGenerationsEnabled() { return false; }\n#endif\n\ntemplate <typename Compare, typename T, typename U>\nusing compare_result_t = absl::result_of_t<const Compare(const T &, const U &)>;\n\n// A helper class that indicates if the Compare parameter is a key-compare-to\n// comparator.\ntemplate <typename Compare, typename T>\nusing btree_is_key_compare_to =\n    std::is_convertible<compare_result_t<Compare, T, T>, absl::weak_ordering>;\n\nstruct StringBtreeDefaultLess {\n  using is_transparent = void;\n\n  StringBtreeDefaultLess() = default;\n\n  // Compatibility constructor.\n  StringBtreeDefaultLess(std::less<std::string>) {}        // NOLINT\n  StringBtreeDefaultLess(std::less<absl::string_view>) {}  // NOLINT\n\n  // Allow converting to std::less for use in key_comp()/value_comp().\n  explicit operator std::less<std::string>() const { return {}; }\n  explicit operator std::less<absl::string_view>() const { return {}; }\n  explicit operator std::less<absl::Cord>() const { return {}; }\n\n  absl::weak_ordering operator()(absl::string_view lhs,\n                                 absl::string_view rhs) const {\n    return compare_internal::compare_result_as_ordering(lhs.compare(rhs));\n  }\n  StringBtreeDefaultLess(std::less<absl::Cord>) {}  // NOLINT\n  absl::weak_ordering operator()(const absl::Cord &lhs,\n                                 const absl::Cord &rhs) const {\n    return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));\n  }\n  absl::weak_ordering operator()(const absl::Cord &lhs,\n                                 absl::string_view rhs) const {\n    return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));\n  }\n  absl::weak_ordering operator()(absl::string_view lhs,\n                                 const absl::Cord &rhs) const {\n    return compare_internal::compare_result_as_ordering(-rhs.Compare(lhs));\n  }\n};\n\nstruct StringBtreeDefaultGreater {\n  using is_transparent = void;\n\n  StringBtreeDefaultGreater() = default;\n\n  StringBtreeDefaultGreater(std::greater<std::string>) {}        // NOLINT\n  StringBtreeDefaultGreater(std::greater<absl::string_view>) {}  // NOLINT\n\n  // Allow converting to std::greater for use in key_comp()/value_comp().\n  explicit operator std::greater<std::string>() const { return {}; }\n  explicit operator std::greater<absl::string_view>() const { return {}; }\n  explicit operator std::greater<absl::Cord>() const { return {}; }\n\n  absl::weak_ordering operator()(absl::string_view lhs,\n                                 absl::string_view rhs) const {\n    return compare_internal::compare_result_as_ordering(rhs.compare(lhs));\n  }\n  StringBtreeDefaultGreater(std::greater<absl::Cord>) {}  // NOLINT\n  absl::weak_ordering operator()(const absl::Cord &lhs,\n                                 const absl::Cord &rhs) const {\n    return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));\n  }\n  absl::weak_ordering operator()(const absl::Cord &lhs,\n                                 absl::string_view rhs) const {\n    return compare_internal::compare_result_as_ordering(-lhs.Compare(rhs));\n  }\n  absl::weak_ordering operator()(absl::string_view lhs,\n                                 const absl::Cord &rhs) const {\n    return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));\n  }\n};\n\n// See below comments for checked_compare.\ntemplate <typename Compare, bool is_class = std::is_class<Compare>::value>\nstruct checked_compare_base : Compare {\n  using Compare::Compare;\n  explicit checked_compare_base(Compare c) : Compare(std::move(c)) {}\n  const Compare &comp() const { return *this; }\n};\ntemplate <typename Compare>\nstruct checked_compare_base<Compare, false> {\n  explicit checked_compare_base(Compare c) : compare(std::move(c)) {}\n  const Compare &comp() const { return compare; }\n  Compare compare;\n};\n\n// A mechanism for opting out of checked_compare for use only in btree_test.cc.\nstruct BtreeTestOnlyCheckedCompareOptOutBase {};\n\n// A helper class to adapt the specified comparator for two use cases:\n// (1) When using common Abseil string types with common comparison functors,\n// convert a boolean comparison into a three-way comparison that returns an\n// `absl::weak_ordering`. This helper class is specialized for\n// less<std::string>, greater<std::string>, less<string_view>,\n// greater<string_view>, less<absl::Cord>, and greater<absl::Cord>.\n// (2) Adapt the comparator to diagnose cases of non-strict-weak-ordering (see\n// https://en.cppreference.com/w/cpp/named_req/Compare) in debug mode. Whenever\n// a comparison is made, we will make assertions to verify that the comparator\n// is valid.\ntemplate <typename Compare, typename Key>\nstruct key_compare_adapter {\n  // Inherit from checked_compare_base to support function pointers and also\n  // keep empty-base-optimization (EBO) support for classes.\n  // Note: we can't use CompressedTuple here because that would interfere\n  // with the EBO for `btree::rightmost_`. `btree::rightmost_` is itself a\n  // CompressedTuple and nested `CompressedTuple`s don't support EBO.\n  // TODO(b/214288561): use CompressedTuple instead once it supports EBO for\n  // nested `CompressedTuple`s.\n  struct checked_compare : checked_compare_base<Compare> {\n   private:\n    using Base = typename checked_compare::checked_compare_base;\n    using Base::comp;\n\n    // If possible, returns whether `t` is equivalent to itself. We can only do\n    // this for `Key`s because we can't be sure that it's safe to call\n    // `comp()(k, k)` otherwise. Even if SFINAE allows it, there could be a\n    // compilation failure inside the implementation of the comparison operator.\n    bool is_self_equivalent(const Key &k) const {\n      // Note: this works for both boolean and three-way comparators.\n      return comp()(k, k) == 0;\n    }\n    // If we can't compare `t` with itself, returns true unconditionally.\n    template <typename T>\n    bool is_self_equivalent(const T &) const {\n      return true;\n    }\n\n   public:\n    using Base::Base;\n    checked_compare(Compare cmp) : Base(std::move(cmp)) {}  // NOLINT\n\n    // Allow converting to Compare for use in key_comp()/value_comp().\n    explicit operator Compare() const { return comp(); }\n\n    template <typename T, typename U,\n              absl::enable_if_t<\n                  std::is_same<bool, compare_result_t<Compare, T, U>>::value,\n                  int> = 0>\n    bool operator()(const T &lhs, const U &rhs) const {\n      // NOTE: if any of these assertions fail, then the comparator does not\n      // establish a strict-weak-ordering (see\n      // https://en.cppreference.com/w/cpp/named_req/Compare).\n      assert(is_self_equivalent(lhs));\n      assert(is_self_equivalent(rhs));\n      const bool lhs_comp_rhs = comp()(lhs, rhs);\n      assert(!lhs_comp_rhs || !comp()(rhs, lhs));\n      return lhs_comp_rhs;\n    }\n\n    template <\n        typename T, typename U,\n        absl::enable_if_t<std::is_convertible<compare_result_t<Compare, T, U>,\n                                              absl::weak_ordering>::value,\n                          int> = 0>\n    absl::weak_ordering operator()(const T &lhs, const U &rhs) const {\n      // NOTE: if any of these assertions fail, then the comparator does not\n      // establish a strict-weak-ordering (see\n      // https://en.cppreference.com/w/cpp/named_req/Compare).\n      assert(is_self_equivalent(lhs));\n      assert(is_self_equivalent(rhs));\n      const absl::weak_ordering lhs_comp_rhs = comp()(lhs, rhs);\n#ifndef NDEBUG\n      const absl::weak_ordering rhs_comp_lhs = comp()(rhs, lhs);\n      if (lhs_comp_rhs > 0) {\n        assert(rhs_comp_lhs < 0 && \"lhs_comp_rhs > 0 -> rhs_comp_lhs < 0\");\n      } else if (lhs_comp_rhs == 0) {\n        assert(rhs_comp_lhs == 0 && \"lhs_comp_rhs == 0 -> rhs_comp_lhs == 0\");\n      } else {\n        assert(rhs_comp_lhs > 0 && \"lhs_comp_rhs < 0 -> rhs_comp_lhs > 0\");\n      }\n#endif\n      return lhs_comp_rhs;\n    }\n  };\n  using type = absl::conditional_t<\n      std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase, Compare>::value,\n      Compare, checked_compare>;\n};\n\ntemplate <>\nstruct key_compare_adapter<std::less<std::string>, std::string> {\n  using type = StringBtreeDefaultLess;\n};\n\ntemplate <>\nstruct key_compare_adapter<std::greater<std::string>, std::string> {\n  using type = StringBtreeDefaultGreater;\n};\n\ntemplate <>\nstruct key_compare_adapter<std::less<absl::string_view>, absl::string_view> {\n  using type = StringBtreeDefaultLess;\n};\n\ntemplate <>\nstruct key_compare_adapter<std::greater<absl::string_view>, absl::string_view> {\n  using type = StringBtreeDefaultGreater;\n};\n\ntemplate <>\nstruct key_compare_adapter<std::less<absl::Cord>, absl::Cord> {\n  using type = StringBtreeDefaultLess;\n};\n\ntemplate <>\nstruct key_compare_adapter<std::greater<absl::Cord>, absl::Cord> {\n  using type = StringBtreeDefaultGreater;\n};\n\n// Detects an 'absl_btree_prefer_linear_node_search' member. This is\n// a protocol used as an opt-in or opt-out of linear search.\n//\n//  For example, this would be useful for key types that wrap an integer\n//  and define their own cheap operator<(). For example:\n//\n//   class K {\n//    public:\n//     using absl_btree_prefer_linear_node_search = std::true_type;\n//     ...\n//    private:\n//     friend bool operator<(K a, K b) { return a.k_ < b.k_; }\n//     int k_;\n//   };\n//\n//   btree_map<K, V> m;  // Uses linear search\n//\n// If T has the preference tag, then it has a preference.\n// Btree will use the tag's truth value.\ntemplate <typename T, typename = void>\nstruct has_linear_node_search_preference : std::false_type {};\ntemplate <typename T, typename = void>\nstruct prefers_linear_node_search : std::false_type {};\ntemplate <typename T>\nstruct has_linear_node_search_preference<\n    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>\n    : std::true_type {};\ntemplate <typename T>\nstruct prefers_linear_node_search<\n    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>\n    : T::absl_btree_prefer_linear_node_search {};\n\ntemplate <typename Compare, typename Key>\nconstexpr bool compare_has_valid_result_type() {\n  using compare_result_type = compare_result_t<Compare, Key, Key>;\n  return std::is_same<compare_result_type, bool>::value ||\n         std::is_convertible<compare_result_type, absl::weak_ordering>::value;\n}\n\ntemplate <typename original_key_compare, typename value_type>\nclass map_value_compare {\n  template <typename Params>\n  friend class btree;\n\n  // Note: this `protected` is part of the API of std::map::value_compare. See\n  // https://en.cppreference.com/w/cpp/container/map/value_compare.\n protected:\n  explicit map_value_compare(original_key_compare c) : comp(std::move(c)) {}\n\n  original_key_compare comp;  // NOLINT\n\n public:\n  auto operator()(const value_type &lhs, const value_type &rhs) const\n      -> decltype(comp(lhs.first, rhs.first)) {\n    return comp(lhs.first, rhs.first);\n  }\n};\n\ntemplate <typename Key, typename Compare, typename Alloc, int TargetNodeSize,\n          bool IsMulti, bool IsMap, typename SlotPolicy>\nstruct common_params : common_policy_traits<SlotPolicy> {\n  using original_key_compare = Compare;\n\n  // If Compare is a common comparator for a string-like type, then we adapt it\n  // to use heterogeneous lookup and to be a key-compare-to comparator.\n  // We also adapt the comparator to diagnose invalid comparators in debug mode.\n  // We disable this when `Compare` is invalid in a way that will cause\n  // adaptation to fail (having invalid return type) so that we can give a\n  // better compilation failure in static_assert_validation. If we don't do\n  // this, then there will be cascading compilation failures that are confusing\n  // for users.\n  using key_compare =\n      absl::conditional_t<!compare_has_valid_result_type<Compare, Key>(),\n                          Compare,\n                          typename key_compare_adapter<Compare, Key>::type>;\n\n  static constexpr bool kIsKeyCompareStringAdapted =\n      std::is_same<key_compare, StringBtreeDefaultLess>::value ||\n      std::is_same<key_compare, StringBtreeDefaultGreater>::value;\n  static constexpr bool kIsKeyCompareTransparent =\n      IsTransparent<original_key_compare>::value || kIsKeyCompareStringAdapted;\n\n  // A type which indicates if we have a key-compare-to functor or a plain old\n  // key-compare functor.\n  using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;\n\n  using allocator_type = Alloc;\n  using key_type = Key;\n  using size_type = size_t;\n  using difference_type = ptrdiff_t;\n\n  using slot_policy = SlotPolicy;\n  using slot_type = typename slot_policy::slot_type;\n  using value_type = typename slot_policy::value_type;\n  using init_type = typename slot_policy::mutable_value_type;\n  using pointer = value_type *;\n  using const_pointer = const value_type *;\n  using reference = value_type &;\n  using const_reference = const value_type &;\n\n  using value_compare =\n      absl::conditional_t<IsMap,\n                          map_value_compare<original_key_compare, value_type>,\n                          original_key_compare>;\n  using is_map_container = std::integral_constant<bool, IsMap>;\n\n  // For the given lookup key type, returns whether we can have multiple\n  // equivalent keys in the btree. If this is a multi-container, then we can.\n  // Otherwise, we can have multiple equivalent keys only if all of the\n  // following conditions are met:\n  // - The comparator is transparent.\n  // - The lookup key type is not the same as key_type.\n  // - The comparator is not a StringBtreeDefault{Less,Greater} comparator\n  //   that we know has the same equivalence classes for all lookup types.\n  template <typename LookupKey>\n  constexpr static bool can_have_multiple_equivalent_keys() {\n    return IsMulti || (IsTransparent<key_compare>::value &&\n                       !std::is_same<LookupKey, Key>::value &&\n                       !kIsKeyCompareStringAdapted);\n  }\n\n  enum {\n    kTargetNodeSize = TargetNodeSize,\n\n    // Upper bound for the available space for slots. This is largest for leaf\n    // nodes, which have overhead of at least a pointer + 4 bytes (for storing\n    // 3 field_types and an enum).\n    kNodeSlotSpace = TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4),\n  };\n\n  // This is an integral type large enough to hold as many slots as will fit a\n  // node of TargetNodeSize bytes.\n  using node_count_type =\n      absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >\n                           (std::numeric_limits<uint8_t>::max)()),\n                          uint16_t, uint8_t>;  // NOLINT\n};\n\n// An adapter class that converts a lower-bound compare into an upper-bound\n// compare. Note: there is no need to make a version of this adapter specialized\n// for key-compare-to functors because the upper-bound (the first value greater\n// than the input) is never an exact match.\ntemplate <typename Compare>\nstruct upper_bound_adapter {\n  explicit upper_bound_adapter(const Compare &c) : comp(c) {}\n  template <typename K1, typename K2>\n  bool operator()(const K1 &a, const K2 &b) const {\n    // Returns true when a is not greater than b.\n    return !compare_internal::compare_result_as_less_than(comp(b, a));\n  }\n\n private:\n  Compare comp;\n};\n\nenum class MatchKind : uint8_t { kEq, kNe };\n\ntemplate <typename V, bool IsCompareTo>\nstruct SearchResult {\n  V value;\n  MatchKind match;\n\n  static constexpr bool HasMatch() { return true; }\n  bool IsEq() const { return match == MatchKind::kEq; }\n};\n\n// When we don't use CompareTo, `match` is not present.\n// This ensures that callers can't use it accidentally when it provides no\n// useful information.\ntemplate <typename V>\nstruct SearchResult<V, false> {\n  SearchResult() = default;\n  explicit SearchResult(V v) : value(v) {}\n  SearchResult(V v, MatchKind /*match*/) : value(v) {}\n\n  V value;\n\n  static constexpr bool HasMatch() { return false; }\n  static constexpr bool IsEq() { return false; }\n};\n\n// A node in the btree holding. The same node type is used for both internal\n// and leaf nodes in the btree, though the nodes are allocated in such a way\n// that the children array is only valid in internal nodes.\ntemplate <typename Params>\nclass btree_node {\n  using is_key_compare_to = typename Params::is_key_compare_to;\n  using field_type = typename Params::node_count_type;\n  using allocator_type = typename Params::allocator_type;\n  using slot_type = typename Params::slot_type;\n  using original_key_compare = typename Params::original_key_compare;\n\n public:\n  using params_type = Params;\n  using key_type = typename Params::key_type;\n  using value_type = typename Params::value_type;\n  using pointer = typename Params::pointer;\n  using const_pointer = typename Params::const_pointer;\n  using reference = typename Params::reference;\n  using const_reference = typename Params::const_reference;\n  using key_compare = typename Params::key_compare;\n  using size_type = typename Params::size_type;\n  using difference_type = typename Params::difference_type;\n\n  // Btree decides whether to use linear node search as follows:\n  //   - If the comparator expresses a preference, use that.\n  //   - If the key expresses a preference, use that.\n  //   - If the key is arithmetic and the comparator is std::less or\n  //     std::greater, choose linear.\n  //   - Otherwise, choose binary.\n  // TODO(ezb): Might make sense to add condition(s) based on node-size.\n  using use_linear_search = std::integral_constant<\n      bool, has_linear_node_search_preference<original_key_compare>::value\n                ? prefers_linear_node_search<original_key_compare>::value\n            : has_linear_node_search_preference<key_type>::value\n                ? prefers_linear_node_search<key_type>::value\n                : std::is_arithmetic<key_type>::value &&\n                      (std::is_same<std::less<key_type>,\n                                    original_key_compare>::value ||\n                       std::is_same<std::greater<key_type>,\n                                    original_key_compare>::value)>;\n\n  // This class is organized by absl::container_internal::Layout as if it had\n  // the following structure:\n  //   // A pointer to the node's parent.\n  //   btree_node *parent;\n  //\n  //   // When ABSL_BTREE_ENABLE_GENERATIONS is defined, we also have a\n  //   // generation integer in order to check that when iterators are\n  //   // used, they haven't been invalidated already. Only the generation on\n  //   // the root is used, but we have one on each node because whether a node\n  //   // is root or not can change.\n  //   uint32_t generation;\n  //\n  //   // The position of the node in the node's parent.\n  //   field_type position;\n  //   // The index of the first populated value in `values`.\n  //   // TODO(ezb): right now, `start` is always 0. Update insertion/merge\n  //   // logic to allow for floating storage within nodes.\n  //   field_type start;\n  //   // The index after the last populated value in `values`. Currently, this\n  //   // is the same as the count of values.\n  //   field_type finish;\n  //   // The maximum number of values the node can hold. This is an integer in\n  //   // [1, kNodeSlots] for root leaf nodes, kNodeSlots for non-root leaf\n  //   // nodes, and kInternalNodeMaxCount (as a sentinel value) for internal\n  //   // nodes (even though there are still kNodeSlots values in the node).\n  //   // TODO(ezb): make max_count use only 4 bits and record log2(capacity)\n  //   // to free extra bits for is_root, etc.\n  //   field_type max_count;\n  //\n  //   // The array of values. The capacity is `max_count` for leaf nodes and\n  //   // kNodeSlots for internal nodes. Only the values in\n  //   // [start, finish) have been initialized and are valid.\n  //   slot_type values[max_count];\n  //\n  //   // The array of child pointers. The keys in children[i] are all less\n  //   // than key(i). The keys in children[i + 1] are all greater than key(i).\n  //   // There are 0 children for leaf nodes and kNodeSlots + 1 children for\n  //   // internal nodes.\n  //   btree_node *children[kNodeSlots + 1];\n  //\n  // This class is only constructed by EmptyNodeType. Normally, pointers to the\n  // layout above are allocated, cast to btree_node*, and de-allocated within\n  // the btree implementation.\n  ~btree_node() = default;\n  btree_node(btree_node const &) = delete;\n  btree_node &operator=(btree_node const &) = delete;\n\n protected:\n  btree_node() = default;\n\n private:\n  using layout_type =\n      absl::container_internal::Layout<btree_node *, uint32_t, field_type,\n                                       slot_type, btree_node *>;\n  using leaf_layout_type = typename layout_type::template WithStaticSizes<\n      /*parent*/ 1,\n      /*generation*/ BtreeGenerationsEnabled() ? 1 : 0,\n      /*position, start, finish, max_count*/ 4>;\n  constexpr static size_type SizeWithNSlots(size_type n) {\n    return leaf_layout_type(/*slots*/ n, /*children*/ 0).AllocSize();\n  }\n  // A lower bound for the overhead of fields other than slots in a leaf node.\n  constexpr static size_type MinimumOverhead() {\n    return SizeWithNSlots(1) - sizeof(slot_type);\n  }\n\n  // Compute how many values we can fit onto a leaf node taking into account\n  // padding.\n  constexpr static size_type NodeTargetSlots(const size_type begin,\n                                             const size_type end) {\n    return begin == end ? begin\n           : SizeWithNSlots((begin + end) / 2 + 1) >\n                   params_type::kTargetNodeSize\n               ? NodeTargetSlots(begin, (begin + end) / 2)\n               : NodeTargetSlots((begin + end) / 2 + 1, end);\n  }\n\n  constexpr static size_type kTargetNodeSize = params_type::kTargetNodeSize;\n  constexpr static size_type kNodeTargetSlots =\n      NodeTargetSlots(0, kTargetNodeSize);\n\n  // We need a minimum of 3 slots per internal node in order to perform\n  // splitting (1 value for the two nodes involved in the split and 1 value\n  // propagated to the parent as the delimiter for the split). For performance\n  // reasons, we don't allow 3 slots-per-node due to bad worst case occupancy of\n  // 1/3 (for a node, not a b-tree).\n  constexpr static size_type kMinNodeSlots = 4;\n\n  constexpr static size_type kNodeSlots =\n      kNodeTargetSlots >= kMinNodeSlots ? kNodeTargetSlots : kMinNodeSlots;\n\n  using internal_layout_type = typename layout_type::template WithStaticSizes<\n      /*parent*/ 1,\n      /*generation*/ BtreeGenerationsEnabled() ? 1 : 0,\n      /*position, start, finish, max_count*/ 4, /*slots*/ kNodeSlots,\n      /*children*/ kNodeSlots + 1>;\n\n  // The node is internal (i.e. is not a leaf node) if and only if `max_count`\n  // has this value.\n  constexpr static field_type kInternalNodeMaxCount = 0;\n\n  // Leaves can have less than kNodeSlots values.\n  constexpr static leaf_layout_type LeafLayout(\n      const size_type slot_count = kNodeSlots) {\n    return leaf_layout_type(slot_count, 0);\n  }\n  constexpr static auto InternalLayout() { return internal_layout_type(); }\n  constexpr static size_type LeafSize(const size_type slot_count = kNodeSlots) {\n    return LeafLayout(slot_count).AllocSize();\n  }\n  constexpr static size_type InternalSize() {\n    return InternalLayout().AllocSize();\n  }\n\n  constexpr static size_type Alignment() {\n    static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),\n                  \"Alignment of all nodes must be equal.\");\n    return InternalLayout().Alignment();\n  }\n\n  // N is the index of the type in the Layout definition.\n  // ElementType<N> is the Nth type in the Layout definition.\n  template <size_type N>\n  inline typename layout_type::template ElementType<N> *GetField() {\n    // We assert that we don't read from values that aren't there.\n    assert(N < 4 || is_internal());\n    return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this));\n  }\n  template <size_type N>\n  inline const typename layout_type::template ElementType<N> *GetField() const {\n    assert(N < 4 || is_internal());\n    return InternalLayout().template Pointer<N>(\n        reinterpret_cast<const char *>(this));\n  }\n  void set_parent(btree_node *p) { *GetField<0>() = p; }\n  field_type &mutable_finish() { return GetField<2>()[2]; }\n  slot_type *slot(size_type i) { return &GetField<3>()[i]; }\n  slot_type *start_slot() { return slot(start()); }\n  slot_type *finish_slot() { return slot(finish()); }\n  const slot_type *slot(size_type i) const { return &GetField<3>()[i]; }\n  void set_position(field_type v) { GetField<2>()[0] = v; }\n  void set_start(field_type v) { GetField<2>()[1] = v; }\n  void set_finish(field_type v) { GetField<2>()[2] = v; }\n  // This method is only called by the node init methods.\n  void set_max_count(field_type v) { GetField<2>()[3] = v; }\n\n public:\n  // Whether this is a leaf node or not. This value doesn't change after the\n  // node is created.\n  bool is_leaf() const { return GetField<2>()[3] != kInternalNodeMaxCount; }\n  // Whether this is an internal node or not. This value doesn't change after\n  // the node is created.\n  bool is_internal() const { return !is_leaf(); }\n\n  // Getter for the position of this node in its parent.\n  field_type position() const { return GetField<2>()[0]; }\n\n  // Getter for the offset of the first value in the `values` array.\n  field_type start() const {\n    // TODO(ezb): when floating storage is implemented, return GetField<2>()[1];\n    assert(GetField<2>()[1] == 0);\n    return 0;\n  }\n\n  // Getter for the offset after the last value in the `values` array.\n  field_type finish() const { return GetField<2>()[2]; }\n\n  // Getters for the number of values stored in this node.\n  field_type count() const {\n    assert(finish() >= start());\n    return finish() - start();\n  }\n  field_type max_count() const {\n    // Internal nodes have max_count==kInternalNodeMaxCount.\n    // Leaf nodes have max_count in [1, kNodeSlots].\n    const field_type max_count = GetField<2>()[3];\n    return max_count == field_type{kInternalNodeMaxCount}\n               ? field_type{kNodeSlots}\n               : max_count;\n  }\n\n  // Getter for the parent of this node.\n  // TODO(ezb): assert that the child of the returned node at position\n  // `node_->position()` maps to the current node.\n  btree_node *parent() const { return *GetField<0>(); }\n  // Getter for whether the node is the root of the tree. The parent of the\n  // root of the tree is the leftmost node in the tree which is guaranteed to\n  // be a leaf.\n  bool is_root() const { return parent()->is_leaf(); }\n  void make_root() {\n    assert(parent()->is_root());\n    set_generation(parent()->generation());\n    set_parent(parent()->parent());\n  }\n\n  // Gets the root node's generation integer, which is the one used by the tree.\n  uint32_t *get_root_generation() const {\n    assert(BtreeGenerationsEnabled());\n    const btree_node *curr = this;\n    for (; !curr->is_root(); curr = curr->parent()) continue;\n    return const_cast<uint32_t *>(&curr->GetField<1>()[0]);\n  }\n\n  // Returns the generation for iterator validation.\n  uint32_t generation() const {\n    return BtreeGenerationsEnabled() ? *get_root_generation() : 0;\n  }\n  // Updates generation. Should only be called on a root node or during node\n  // initialization.\n  void set_generation(uint32_t generation) {\n    if (BtreeGenerationsEnabled()) GetField<1>()[0] = generation;\n  }\n  // Updates the generation. We do this whenever the node is mutated.\n  void next_generation() {\n    if (BtreeGenerationsEnabled()) ++*get_root_generation();\n  }\n\n  // Getters for the key/value at position i in the node.\n  const key_type &key(size_type i) const { return params_type::key(slot(i)); }\n  reference value(size_type i) { return params_type::element(slot(i)); }\n  const_reference value(size_type i) const {\n    return params_type::element(slot(i));\n  }\n\n  // Getters/setter for the child at position i in the node.\n  btree_node *child(field_type i) const { return GetField<4>()[i]; }\n  btree_node *start_child() const { return child(start()); }\n  btree_node *&mutable_child(field_type i) { return GetField<4>()[i]; }\n  void clear_child(field_type i) {\n    absl::container_internal::SanitizerPoisonObject(&mutable_child(i));\n  }\n  void set_child_noupdate_position(field_type i, btree_node *c) {\n    absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i));\n    mutable_child(i) = c;\n  }\n  void set_child(field_type i, btree_node *c) {\n    set_child_noupdate_position(i, c);\n    c->set_position(i);\n  }\n  void init_child(field_type i, btree_node *c) {\n    set_child(i, c);\n    c->set_parent(this);\n  }\n\n  // Returns the position of the first value whose key is not less than k.\n  template <typename K>\n  SearchResult<size_type, is_key_compare_to::value> lower_bound(\n      const K &k, const key_compare &comp) const {\n    return use_linear_search::value ? linear_search(k, comp)\n                                    : binary_search(k, comp);\n  }\n  // Returns the position of the first value whose key is greater than k.\n  template <typename K>\n  size_type upper_bound(const K &k, const key_compare &comp) const {\n    auto upper_compare = upper_bound_adapter<key_compare>(comp);\n    return use_linear_search::value ? linear_search(k, upper_compare).value\n                                    : binary_search(k, upper_compare).value;\n  }\n\n  template <typename K, typename Compare>\n  SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>\n  linear_search(const K &k, const Compare &comp) const {\n    return linear_search_impl(k, start(), finish(), comp,\n                              btree_is_key_compare_to<Compare, key_type>());\n  }\n\n  template <typename K, typename Compare>\n  SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>\n  binary_search(const K &k, const Compare &comp) const {\n    return binary_search_impl(k, start(), finish(), comp,\n                              btree_is_key_compare_to<Compare, key_type>());\n  }\n\n  // Returns the position of the first value whose key is not less than k using\n  // linear search performed using plain compare.\n  template <typename K, typename Compare>\n  SearchResult<size_type, false> linear_search_impl(\n      const K &k, size_type s, const size_type e, const Compare &comp,\n      std::false_type /* IsCompareTo */) const {\n    while (s < e) {\n      if (!comp(key(s), k)) {\n        break;\n      }\n      ++s;\n    }\n    return SearchResult<size_type, false>{s};\n  }\n\n  // Returns the position of the first value whose key is not less than k using\n  // linear search performed using compare-to.\n  template <typename K, typename Compare>\n  SearchResult<size_type, true> linear_search_impl(\n      const K &k, size_type s, const size_type e, const Compare &comp,\n      std::true_type /* IsCompareTo */) const {\n    while (s < e) {\n      const absl::weak_ordering c = comp(key(s), k);\n      if (c == 0) {\n        return {s, MatchKind::kEq};\n      } else if (c > 0) {\n        break;\n      }\n      ++s;\n    }\n    return {s, MatchKind::kNe};\n  }\n\n  // Returns the position of the first value whose key is not less than k using\n  // binary search performed using plain compare.\n  template <typename K, typename Compare>\n  SearchResult<size_type, false> binary_search_impl(\n      const K &k, size_type s, size_type e, const Compare &comp,\n      std::false_type /* IsCompareTo */) const {\n    while (s != e) {\n      const size_type mid = (s + e) >> 1;\n      if (comp(key(mid), k)) {\n        s = mid + 1;\n      } else {\n        e = mid;\n      }\n    }\n    return SearchResult<size_type, false>{s};\n  }\n\n  // Returns the position of the first value whose key is not less than k using\n  // binary search performed using compare-to.\n  template <typename K, typename CompareTo>\n  SearchResult<size_type, true> binary_search_impl(\n      const K &k, size_type s, size_type e, const CompareTo &comp,\n      std::true_type /* IsCompareTo */) const {\n    if (params_type::template can_have_multiple_equivalent_keys<K>()) {\n      MatchKind exact_match = MatchKind::kNe;\n      while (s != e) {\n        const size_type mid = (s + e) >> 1;\n        const absl::weak_ordering c = comp(key(mid), k);\n        if (c < 0) {\n          s = mid + 1;\n        } else {\n          e = mid;\n          if (c == 0) {\n            // Need to return the first value whose key is not less than k,\n            // which requires continuing the binary search if there could be\n            // multiple equivalent keys.\n            exact_match = MatchKind::kEq;\n          }\n        }\n      }\n      return {s, exact_match};\n    } else {  // Can't have multiple equivalent keys.\n      while (s != e) {\n        const size_type mid = (s + e) >> 1;\n        const absl::weak_ordering c = comp(key(mid), k);\n        if (c < 0) {\n          s = mid + 1;\n        } else if (c > 0) {\n          e = mid;\n        } else {\n          return {mid, MatchKind::kEq};\n        }\n      }\n      return {s, MatchKind::kNe};\n    }\n  }\n\n  // Returns whether key i is ordered correctly with respect to the other keys\n  // in the node. The motivation here is to detect comparators that violate\n  // transitivity. Note: we only do comparisons of keys on this node rather than\n  // the whole tree so that this is constant time.\n  template <typename Compare>\n  bool is_ordered_correctly(field_type i, const Compare &comp) const {\n    if (std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase,\n                        Compare>::value ||\n        params_type::kIsKeyCompareStringAdapted) {\n      return true;\n    }\n\n    const auto compare = [&](field_type a, field_type b) {\n      const absl::weak_ordering cmp =\n          compare_internal::do_three_way_comparison(comp, key(a), key(b));\n      return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;\n    };\n    int cmp = -1;\n    constexpr bool kCanHaveEquivKeys =\n        params_type::template can_have_multiple_equivalent_keys<key_type>();\n    for (field_type j = start(); j < finish(); ++j) {\n      if (j == i) {\n        if (cmp > 0) return false;\n        continue;\n      }\n      int new_cmp = compare(j, i);\n      if (new_cmp < cmp || (!kCanHaveEquivKeys && new_cmp == 0)) return false;\n      cmp = new_cmp;\n    }\n    return true;\n  }\n\n  // Emplaces a value at position i, shifting all existing values and\n  // children at positions >= i to the right by 1.\n  template <typename... Args>\n  void emplace_value(field_type i, allocator_type *alloc, Args &&...args);\n\n  // Removes the values at positions [i, i + to_erase), shifting all existing\n  // values and children after that range to the left by to_erase. Clears all\n  // children between [i, i + to_erase).\n  void remove_values(field_type i, field_type to_erase, allocator_type *alloc);\n\n  // Rebalances a node with its right sibling.\n  void rebalance_right_to_left(field_type to_move, btree_node *right,\n                               allocator_type *alloc);\n  void rebalance_left_to_right(field_type to_move, btree_node *right,\n                               allocator_type *alloc);\n\n  // Splits a node, moving a portion of the node's values to its right sibling.\n  void split(int insert_position, btree_node *dest, allocator_type *alloc);\n\n  // Merges a node with its right sibling, moving all of the values and the\n  // delimiting key in the parent node onto itself, and deleting the src node.\n  void merge(btree_node *src, allocator_type *alloc);\n\n  // Node allocation/deletion routines.\n  void init_leaf(field_type position, field_type max_count,\n                 btree_node *parent) {\n    set_generation(0);\n    set_parent(parent);\n    set_position(position);\n    set_start(0);\n    set_finish(0);\n    set_max_count(max_count);\n    absl::container_internal::SanitizerPoisonMemoryRegion(\n        start_slot(), max_count * sizeof(slot_type));\n  }\n  void init_internal(field_type position, btree_node *parent) {\n    init_leaf(position, kNodeSlots, parent);\n    // Set `max_count` to a sentinel value to indicate that this node is\n    // internal.\n    set_max_count(kInternalNodeMaxCount);\n    absl::container_internal::SanitizerPoisonMemoryRegion(\n        &mutable_child(start()), (kNodeSlots + 1) * sizeof(btree_node *));\n  }\n\n  static void deallocate(const size_type size, btree_node *node,\n                         allocator_type *alloc) {\n    absl::container_internal::SanitizerUnpoisonMemoryRegion(node, size);\n    absl::container_internal::Deallocate<Alignment()>(alloc, node, size);\n  }\n\n  // Deletes a node and all of its children.\n  static void clear_and_delete(btree_node *node, allocator_type *alloc);\n\n private:\n  template <typename... Args>\n  void value_init(const field_type i, allocator_type *alloc, Args &&...args) {\n    next_generation();\n    absl::container_internal::SanitizerUnpoisonObject(slot(i));\n    params_type::construct(alloc, slot(i), std::forward<Args>(args)...);\n  }\n  void value_destroy(const field_type i, allocator_type *alloc) {\n    next_generation();\n    params_type::destroy(alloc, slot(i));\n    absl::container_internal::SanitizerPoisonObject(slot(i));\n  }\n  void value_destroy_n(const field_type i, const field_type n,\n                       allocator_type *alloc) {\n    next_generation();\n    for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) {\n      params_type::destroy(alloc, s);\n      absl::container_internal::SanitizerPoisonObject(s);\n    }\n  }\n\n  static void transfer(slot_type *dest, slot_type *src, allocator_type *alloc) {\n    absl::container_internal::SanitizerUnpoisonObject(dest);\n    params_type::transfer(alloc, dest, src);\n    absl::container_internal::SanitizerPoisonObject(src);\n  }\n\n  // Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`.\n  void transfer(const size_type dest_i, const size_type src_i,\n                btree_node *src_node, allocator_type *alloc) {\n    next_generation();\n    transfer(slot(dest_i), src_node->slot(src_i), alloc);\n  }\n\n  // Transfers `n` values starting at value `src_i` in `src_node` into the\n  // values starting at value `dest_i` in `this`.\n  void transfer_n(const size_type n, const size_type dest_i,\n                  const size_type src_i, btree_node *src_node,\n                  allocator_type *alloc) {\n    next_generation();\n    for (slot_type *src = src_node->slot(src_i), *end = src + n,\n                   *dest = slot(dest_i);\n         src != end; ++src, ++dest) {\n      transfer(dest, src, alloc);\n    }\n  }\n\n  // Same as above, except that we start at the end and work our way to the\n  // beginning.\n  void transfer_n_backward(const size_type n, const size_type dest_i,\n                           const size_type src_i, btree_node *src_node,\n                           allocator_type *alloc) {\n    next_generation();\n    for (slot_type *src = src_node->slot(src_i + n), *end = src - n,\n                   *dest = slot(dest_i + n);\n         src != end; --src, --dest) {\n      // If we modified the loop index calculations above to avoid the -1s here,\n      // it would result in UB in the computation of `end` (and possibly `src`\n      // as well, if n == 0), since slot() is effectively an array index and it\n      // is UB to compute the address of any out-of-bounds array element except\n      // for one-past-the-end.\n      transfer(dest - 1, src - 1, alloc);\n    }\n  }\n\n  template <typename P>\n  friend class btree;\n  template <typename N, typename R, typename P>\n  friend class btree_iterator;\n  friend class BtreeNodePeer;\n  friend struct btree_access;\n};\n\ntemplate <typename Node>\nbool AreNodesFromSameContainer(const Node *node_a, const Node *node_b) {\n  // If either node is null, then give up on checking whether they're from the\n  // same container. (If exactly one is null, then we'll trigger the\n  // default-constructed assert in Equals.)\n  if (node_a == nullptr || node_b == nullptr) return true;\n  while (!node_a->is_root()) node_a = node_a->parent();\n  while (!node_b->is_root()) node_b = node_b->parent();\n  return node_a == node_b;\n}\n\nclass btree_iterator_generation_info_enabled {\n public:\n  explicit btree_iterator_generation_info_enabled(uint32_t g)\n      : generation_(g) {}\n\n  // Updates the generation. For use internally right before we return an\n  // iterator to the user.\n  template <typename Node>\n  void update_generation(const Node *node) {\n    if (node != nullptr) generation_ = node->generation();\n  }\n  uint32_t generation() const { return generation_; }\n\n  template <typename Node>\n  void assert_valid_generation(const Node *node) const {\n    if (node != nullptr && node->generation() != generation_) {\n      ABSL_INTERNAL_LOG(\n          FATAL,\n          \"Attempting to use an invalidated iterator. The corresponding b-tree \"\n          \"container has been mutated since this iterator was constructed.\");\n    }\n  }\n\n private:\n  // Used to check that the iterator hasn't been invalidated.\n  uint32_t generation_;\n};\n\nclass btree_iterator_generation_info_disabled {\n public:\n  explicit btree_iterator_generation_info_disabled(uint32_t) {}\n  static void update_generation(const void *) {}\n  static uint32_t generation() { return 0; }\n  static void assert_valid_generation(const void *) {}\n};\n\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\nusing btree_iterator_generation_info = btree_iterator_generation_info_enabled;\n#else\nusing btree_iterator_generation_info = btree_iterator_generation_info_disabled;\n#endif\n\ntemplate <typename Node, typename Reference, typename Pointer>\nclass btree_iterator : private btree_iterator_generation_info {\n  using field_type = typename Node::field_type;\n  using key_type = typename Node::key_type;\n  using size_type = typename Node::size_type;\n  using params_type = typename Node::params_type;\n  using is_map_container = typename params_type::is_map_container;\n\n  using node_type = Node;\n  using normal_node = typename std::remove_const<Node>::type;\n  using const_node = const Node;\n  using normal_pointer = typename params_type::pointer;\n  using normal_reference = typename params_type::reference;\n  using const_pointer = typename params_type::const_pointer;\n  using const_reference = typename params_type::const_reference;\n  using slot_type = typename params_type::slot_type;\n\n  // In sets, all iterators are const.\n  using iterator = absl::conditional_t<\n      is_map_container::value,\n      btree_iterator<normal_node, normal_reference, normal_pointer>,\n      btree_iterator<normal_node, const_reference, const_pointer>>;\n  using const_iterator =\n      btree_iterator<const_node, const_reference, const_pointer>;\n\n public:\n  // These aliases are public for std::iterator_traits.\n  using difference_type = typename Node::difference_type;\n  using value_type = typename params_type::value_type;\n  using pointer = Pointer;\n  using reference = Reference;\n  using iterator_category = std::bidirectional_iterator_tag;\n\n  btree_iterator() : btree_iterator(nullptr, -1) {}\n  explicit btree_iterator(Node *n) : btree_iterator(n, n->start()) {}\n  btree_iterator(Node *n, int p)\n      : btree_iterator_generation_info(n != nullptr ? n->generation()\n                                                    : ~uint32_t{}),\n        node_(n),\n        position_(p) {}\n\n  // NOTE: this SFINAE allows for implicit conversions from iterator to\n  // const_iterator, but it specifically avoids hiding the copy constructor so\n  // that the trivial one will be used when possible.\n  template <typename N, typename R, typename P,\n            absl::enable_if_t<\n                std::is_same<btree_iterator<N, R, P>, iterator>::value &&\n                    std::is_same<btree_iterator, const_iterator>::value,\n                int> = 0>\n  btree_iterator(const btree_iterator<N, R, P> other)  // NOLINT\n      : btree_iterator_generation_info(other),\n        node_(other.node_),\n        position_(other.position_) {}\n\n  bool operator==(const iterator &other) const {\n    return Equals(other);\n  }\n  bool operator==(const const_iterator &other) const {\n    return Equals(other);\n  }\n  bool operator!=(const iterator &other) const {\n    return !Equals(other);\n  }\n  bool operator!=(const const_iterator &other) const {\n    return !Equals(other);\n  }\n\n  // Returns n such that n calls to ++other yields *this.\n  // Precondition: n exists.\n  difference_type operator-(const_iterator other) const {\n    if (node_ == other.node_) {\n      if (node_->is_leaf()) return position_ - other.position_;\n      if (position_ == other.position_) return 0;\n    }\n    return distance_slow(other);\n  }\n\n  // Advances the iterator by `n`. Values of `n` must not result in going past\n  // the `end` iterator (for a positive `n`) or before the `begin` iterator (for\n  // a negative `n`).\n  btree_iterator &operator+=(difference_type n) {\n    assert_valid_generation(node_);\n    if (n == 0) return *this;\n    if (n < 0) return decrement_n_slow(-n);\n    return increment_n_slow(n);\n  }\n\n  // Moves the iterator by `n` positions backwards. Values of `n` must not\n  // result in going before the `begin` iterator (for a positive `n`) or past\n  // the `end` iterator (for a negative `n`).\n  btree_iterator &operator-=(difference_type n) {\n    assert_valid_generation(node_);\n    if (n == 0) return *this;\n    if (n < 0) return increment_n_slow(-n);\n    return decrement_n_slow(n);\n  }\n\n  // Accessors for the key/value the iterator is pointing at.\n  reference operator*() const {\n    ABSL_HARDENING_ASSERT(node_ != nullptr);\n    assert_valid_generation(node_);\n    ABSL_HARDENING_ASSERT(position_ >= node_->start());\n    if (position_ >= node_->finish()) {\n      ABSL_HARDENING_ASSERT(!IsEndIterator() && \"Dereferencing end() iterator\");\n      ABSL_HARDENING_ASSERT(position_ < node_->finish());\n    }\n    return node_->value(static_cast<field_type>(position_));\n  }\n  pointer operator->() const { return &operator*(); }\n\n  btree_iterator &operator++() {\n    increment();\n    return *this;\n  }\n  btree_iterator &operator--() {\n    decrement();\n    return *this;\n  }\n  btree_iterator operator++(int) {\n    btree_iterator tmp = *this;\n    ++*this;\n    return tmp;\n  }\n  btree_iterator operator--(int) {\n    btree_iterator tmp = *this;\n    --*this;\n    return tmp;\n  }\n\n private:\n  friend iterator;\n  friend const_iterator;\n  template <typename Params>\n  friend class btree;\n  template <typename Tree>\n  friend class btree_container;\n  template <typename Tree>\n  friend class btree_set_container;\n  template <typename Tree>\n  friend class btree_map_container;\n  template <typename Tree>\n  friend class btree_multiset_container;\n  template <typename TreeType, typename CheckerType>\n  friend class base_checker;\n  friend struct btree_access;\n\n  // This SFINAE allows explicit conversions from const_iterator to\n  // iterator, but also avoids hiding the copy constructor.\n  // NOTE: the const_cast is safe because this constructor is only called by\n  // non-const methods and the container owns the nodes.\n  template <typename N, typename R, typename P,\n            absl::enable_if_t<\n                std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&\n                    std::is_same<btree_iterator, iterator>::value,\n                int> = 0>\n  explicit btree_iterator(const btree_iterator<N, R, P> other)\n      : btree_iterator_generation_info(other.generation()),\n        node_(const_cast<node_type *>(other.node_)),\n        position_(other.position_) {}\n\n  bool Equals(const const_iterator other) const {\n    ABSL_HARDENING_ASSERT(((node_ == nullptr && other.node_ == nullptr) ||\n                           (node_ != nullptr && other.node_ != nullptr)) &&\n                          \"Comparing default-constructed iterator with \"\n                          \"non-default-constructed iterator.\");\n    // Note: we use assert instead of ABSL_HARDENING_ASSERT here because this\n    // changes the complexity of Equals from O(1) to O(log(N) + log(M)) where\n    // N/M are sizes of the containers containing node_/other.node_.\n    assert(AreNodesFromSameContainer(node_, other.node_) &&\n           \"Comparing iterators from different containers.\");\n    assert_valid_generation(node_);\n    other.assert_valid_generation(other.node_);\n    return node_ == other.node_ && position_ == other.position_;\n  }\n\n  bool IsEndIterator() const {\n    if (position_ != node_->finish()) return false;\n    node_type *node = node_;\n    while (!node->is_root()) {\n      if (node->position() != node->parent()->finish()) return false;\n      node = node->parent();\n    }\n    return true;\n  }\n\n  // Returns n such that n calls to ++other yields *this.\n  // Precondition: n exists && (this->node_ != other.node_ ||\n  // !this->node_->is_leaf() || this->position_ != other.position_).\n  difference_type distance_slow(const_iterator other) const;\n\n  // Increment/decrement the iterator.\n  void increment() {\n    assert_valid_generation(node_);\n    if (node_->is_leaf() && ++position_ < node_->finish()) {\n      return;\n    }\n    increment_slow();\n  }\n  void increment_slow();\n  btree_iterator &increment_n_slow(difference_type n);\n\n  void decrement() {\n    assert_valid_generation(node_);\n    if (node_->is_leaf() && --position_ >= node_->start()) {\n      return;\n    }\n    decrement_slow();\n  }\n  void decrement_slow();\n  btree_iterator &decrement_n_slow(difference_type n);\n\n  const key_type &key() const {\n    return node_->key(static_cast<size_type>(position_));\n  }\n  decltype(std::declval<Node *>()->slot(0)) slot() {\n    return node_->slot(static_cast<size_type>(position_));\n  }\n\n  void update_generation() {\n    btree_iterator_generation_info::update_generation(node_);\n  }\n\n  // The node in the tree the iterator is pointing at.\n  Node *node_;\n  // The position within the node of the tree the iterator is pointing at.\n  // NOTE: this is an int rather than a field_type because iterators can point\n  // to invalid positions (such as -1) in certain circumstances.\n  int position_;\n};\n\ntemplate <typename Params>\nclass btree {\n  using node_type = btree_node<Params>;\n  using is_key_compare_to = typename Params::is_key_compare_to;\n  using field_type = typename node_type::field_type;\n\n  // We use a static empty node for the root/leftmost/rightmost of empty btrees\n  // in order to avoid branching in begin()/end().\n  struct EmptyNodeType : node_type {\n    using field_type = typename node_type::field_type;\n    node_type *parent;\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\n    uint32_t generation = 0;\n#endif\n    field_type position = 0;\n    field_type start = 0;\n    field_type finish = 0;\n    // max_count must be != kInternalNodeMaxCount (so that this node is regarded\n    // as a leaf node). max_count() is never called when the tree is empty.\n    field_type max_count = node_type::kInternalNodeMaxCount + 1;\n\n    constexpr EmptyNodeType() : parent(this) {}\n  };\n\n  static node_type *EmptyNode() {\n    alignas(node_type::Alignment()) static constexpr EmptyNodeType empty_node;\n    return const_cast<EmptyNodeType *>(&empty_node);\n  }\n\n  enum : uint32_t {\n    kNodeSlots = node_type::kNodeSlots,\n    kMinNodeValues = kNodeSlots / 2,\n  };\n\n  struct node_stats {\n    using size_type = typename Params::size_type;\n\n    node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {}\n\n    node_stats &operator+=(const node_stats &other) {\n      leaf_nodes += other.leaf_nodes;\n      internal_nodes += other.internal_nodes;\n      return *this;\n    }\n\n    size_type leaf_nodes;\n    size_type internal_nodes;\n  };\n\n public:\n  using key_type = typename Params::key_type;\n  using value_type = typename Params::value_type;\n  using size_type = typename Params::size_type;\n  using difference_type = typename Params::difference_type;\n  using key_compare = typename Params::key_compare;\n  using original_key_compare = typename Params::original_key_compare;\n  using value_compare = typename Params::value_compare;\n  using allocator_type = typename Params::allocator_type;\n  using reference = typename Params::reference;\n  using const_reference = typename Params::const_reference;\n  using pointer = typename Params::pointer;\n  using const_pointer = typename Params::const_pointer;\n  using iterator =\n      typename btree_iterator<node_type, reference, pointer>::iterator;\n  using const_iterator = typename iterator::const_iterator;\n  using reverse_iterator = std::reverse_iterator<iterator>;\n  using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n  using node_handle_type = node_handle<Params, Params, allocator_type>;\n\n  // Internal types made public for use by btree_container types.\n  using params_type = Params;\n  using slot_type = typename Params::slot_type;\n\n private:\n  // Copies or moves (depending on the template parameter) the values in\n  // other into this btree in their order in other. This btree must be empty\n  // before this method is called. This method is used in copy construction,\n  // copy assignment, and move assignment.\n  template <typename Btree>\n  void copy_or_move_values_in_order(Btree &other);\n\n  // Validates that various assumptions/requirements are true at compile time.\n  constexpr static bool static_assert_validation();\n\n public:\n  btree(const key_compare &comp, const allocator_type &alloc)\n      : root_(EmptyNode()), rightmost_(comp, alloc, EmptyNode()), size_(0) {}\n\n  btree(const btree &other) : btree(other, other.allocator()) {}\n  btree(const btree &other, const allocator_type &alloc)\n      : btree(other.key_comp(), alloc) {\n    copy_or_move_values_in_order(other);\n  }\n  btree(btree &&other) noexcept\n      : root_(std::exchange(other.root_, EmptyNode())),\n        rightmost_(std::move(other.rightmost_)),\n        size_(std::exchange(other.size_, 0u)) {\n    other.mutable_rightmost() = EmptyNode();\n  }\n  btree(btree &&other, const allocator_type &alloc)\n      : btree(other.key_comp(), alloc) {\n    if (alloc == other.allocator()) {\n      swap(other);\n    } else {\n      // Move values from `other` one at a time when allocators are different.\n      copy_or_move_values_in_order(other);\n    }\n  }\n\n  ~btree() {\n    // Put static_asserts in destructor to avoid triggering them before the type\n    // is complete.\n    static_assert(static_assert_validation(), \"This call must be elided.\");\n    clear();\n  }\n\n  // Assign the contents of other to *this.\n  btree &operator=(const btree &other);\n  btree &operator=(btree &&other) noexcept;\n\n  iterator begin() { return iterator(leftmost()); }\n  const_iterator begin() const { return const_iterator(leftmost()); }\n  iterator end() { return iterator(rightmost(), rightmost()->finish()); }\n  const_iterator end() const {\n    return const_iterator(rightmost(), rightmost()->finish());\n  }\n  reverse_iterator rbegin() { return reverse_iterator(end()); }\n  const_reverse_iterator rbegin() const {\n    return const_reverse_iterator(end());\n  }\n  reverse_iterator rend() { return reverse_iterator(begin()); }\n  const_reverse_iterator rend() const {\n    return const_reverse_iterator(begin());\n  }\n\n  // Finds the first element whose key is not less than `key`.\n  template <typename K>\n  iterator lower_bound(const K &key) {\n    return internal_end(internal_lower_bound(key).value);\n  }\n  template <typename K>\n  const_iterator lower_bound(const K &key) const {\n    return internal_end(internal_lower_bound(key).value);\n  }\n\n  // Finds the first element whose key is not less than `key` and also returns\n  // whether that element is equal to `key`.\n  template <typename K>\n  std::pair<iterator, bool> lower_bound_equal(const K &key) const;\n\n  // Finds the first element whose key is greater than `key`.\n  template <typename K>\n  iterator upper_bound(const K &key) {\n    return internal_end(internal_upper_bound(key));\n  }\n  template <typename K>\n  const_iterator upper_bound(const K &key) const {\n    return internal_end(internal_upper_bound(key));\n  }\n\n  // Finds the range of values which compare equal to key. The first member of\n  // the returned pair is equal to lower_bound(key). The second member of the\n  // pair is equal to upper_bound(key).\n  template <typename K>\n  std::pair<iterator, iterator> equal_range(const K &key);\n  template <typename K>\n  std::pair<const_iterator, const_iterator> equal_range(const K &key) const {\n    return const_cast<btree *>(this)->equal_range(key);\n  }\n\n  // Inserts a value into the btree only if it does not already exist. The\n  // boolean return value indicates whether insertion succeeded or failed.\n  // Requirement: if `key` already exists in the btree, does not consume `args`.\n  // Requirement: `key` is never referenced after consuming `args`.\n  template <typename K, typename... Args>\n  std::pair<iterator, bool> insert_unique(const K &key, Args &&...args);\n\n  // Inserts with hint. Checks to see if the value should be placed immediately\n  // before `position` in the tree. If so, then the insertion will take\n  // amortized constant time. If not, the insertion will take amortized\n  // logarithmic time as if a call to insert_unique() were made.\n  // Requirement: if `key` already exists in the btree, does not consume `args`.\n  // Requirement: `key` is never referenced after consuming `args`.\n  template <typename K, typename... Args>\n  std::pair<iterator, bool> insert_hint_unique(iterator position, const K &key,\n                                               Args &&...args);\n\n  // Insert a range of values into the btree.\n  // Note: the first overload avoids constructing a value_type if the key\n  // already exists in the btree.\n  template <typename InputIterator,\n            typename = decltype(std::declval<const key_compare &>()(\n                params_type::key(*std::declval<InputIterator>()),\n                std::declval<const key_type &>()))>\n  void insert_iterator_unique(InputIterator b, InputIterator e, int);\n  // We need the second overload for cases in which we need to construct a\n  // value_type in order to compare it with the keys already in the btree.\n  template <typename InputIterator>\n  void insert_iterator_unique(InputIterator b, InputIterator e, char);\n\n  // Inserts a value into the btree.\n  template <typename ValueType>\n  iterator insert_multi(const key_type &key, ValueType &&v);\n\n  // Inserts a value into the btree.\n  template <typename ValueType>\n  iterator insert_multi(ValueType &&v) {\n    return insert_multi(params_type::key(v), std::forward<ValueType>(v));\n  }\n\n  // Insert with hint. Check to see if the value should be placed immediately\n  // before position in the tree. If it does, then the insertion will take\n  // amortized constant time. If not, the insertion will take amortized\n  // logarithmic time as if a call to insert_multi(v) were made.\n  template <typename ValueType>\n  iterator insert_hint_multi(iterator position, ValueType &&v);\n\n  // Insert a range of values into the btree.\n  template <typename InputIterator>\n  void insert_iterator_multi(InputIterator b,\n                             InputIterator e);\n\n  // Erase the specified iterator from the btree. The iterator must be valid\n  // (i.e. not equal to end()).  Return an iterator pointing to the node after\n  // the one that was erased (or end() if none exists).\n  // Requirement: does not read the value at `*iter`.\n  iterator erase(iterator iter);\n\n  // Erases range. Returns the number of keys erased and an iterator pointing\n  // to the element after the last erased element.\n  std::pair<size_type, iterator> erase_range(iterator begin, iterator end);\n\n  // Finds an element with key equivalent to `key` or returns `end()` if `key`\n  // is not present.\n  template <typename K>\n  iterator find(const K &key) {\n    return internal_end(internal_find(key));\n  }\n  template <typename K>\n  const_iterator find(const K &key) const {\n    return internal_end(internal_find(key));\n  }\n\n  // Clear the btree, deleting all of the values it contains.\n  void clear();\n\n  // Swaps the contents of `this` and `other`.\n  void swap(btree &other);\n\n  const key_compare &key_comp() const noexcept {\n    return rightmost_.template get<0>();\n  }\n  template <typename K1, typename K2>\n  bool compare_keys(const K1 &a, const K2 &b) const {\n    return compare_internal::compare_result_as_less_than(key_comp()(a, b));\n  }\n\n  value_compare value_comp() const {\n    return value_compare(original_key_compare(key_comp()));\n  }\n\n  // Verifies the structure of the btree.\n  void verify() const;\n\n  // Size routines.\n  size_type size() const { return size_; }\n  size_type max_size() const { return (std::numeric_limits<size_type>::max)(); }\n  bool empty() const { return size_ == 0; }\n\n  // The height of the btree. An empty tree will have height 0.\n  size_type height() const {\n    size_type h = 0;\n    if (!empty()) {\n      // Count the length of the chain from the leftmost node up to the\n      // root. We actually count from the root back around to the level below\n      // the root, but the calculation is the same because of the circularity\n      // of that traversal.\n      const node_type *n = root();\n      do {\n        ++h;\n        n = n->parent();\n      } while (n != root());\n    }\n    return h;\n  }\n\n  // The number of internal, leaf and total nodes used by the btree.\n  size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; }\n  size_type internal_nodes() const {\n    return internal_stats(root()).internal_nodes;\n  }\n  size_type nodes() const {\n    node_stats stats = internal_stats(root());\n    return stats.leaf_nodes + stats.internal_nodes;\n  }\n\n  // The total number of bytes used by the btree.\n  // TODO(b/169338300): update to support node_btree_*.\n  size_type bytes_used() const {\n    node_stats stats = internal_stats(root());\n    if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {\n      return sizeof(*this) + node_type::LeafSize(root()->max_count());\n    } else {\n      return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() +\n             stats.internal_nodes * node_type::InternalSize();\n    }\n  }\n\n  // The average number of bytes used per value stored in the btree assuming\n  // random insertion order.\n  static double average_bytes_per_value() {\n    // The expected number of values per node with random insertion order is the\n    // average of the maximum and minimum numbers of values per node.\n    const double expected_values_per_node = (kNodeSlots + kMinNodeValues) / 2.0;\n    return node_type::LeafSize() / expected_values_per_node;\n  }\n\n  // The fullness of the btree. Computed as the number of elements in the btree\n  // divided by the maximum number of elements a tree with the current number\n  // of nodes could hold. A value of 1 indicates perfect space\n  // utilization. Smaller values indicate space wastage.\n  // Returns 0 for empty trees.\n  double fullness() const {\n    if (empty()) return 0.0;\n    return static_cast<double>(size()) / (nodes() * kNodeSlots);\n  }\n  // The overhead of the btree structure in bytes per node. Computed as the\n  // total number of bytes used by the btree minus the number of bytes used for\n  // storing elements divided by the number of elements.\n  // Returns 0 for empty trees.\n  double overhead() const {\n    if (empty()) return 0.0;\n    return (bytes_used() - size() * sizeof(value_type)) /\n           static_cast<double>(size());\n  }\n\n  // The allocator used by the btree.\n  allocator_type get_allocator() const { return allocator(); }\n\n private:\n  friend struct btree_access;\n\n  // Internal accessor routines.\n  node_type *root() { return root_; }\n  const node_type *root() const { return root_; }\n  node_type *&mutable_root() noexcept { return root_; }\n  node_type *rightmost() { return rightmost_.template get<2>(); }\n  const node_type *rightmost() const { return rightmost_.template get<2>(); }\n  node_type *&mutable_rightmost() noexcept {\n    return rightmost_.template get<2>();\n  }\n  key_compare *mutable_key_comp() noexcept {\n    return &rightmost_.template get<0>();\n  }\n\n  // The leftmost node is stored as the parent of the root node.\n  node_type *leftmost() { return root()->parent(); }\n  const node_type *leftmost() const { return root()->parent(); }\n\n  // Allocator routines.\n  allocator_type *mutable_allocator() noexcept {\n    return &rightmost_.template get<1>();\n  }\n  const allocator_type &allocator() const noexcept {\n    return rightmost_.template get<1>();\n  }\n\n  // Allocates a correctly aligned node of at least size bytes using the\n  // allocator.\n  node_type *allocate(size_type size) {\n    return reinterpret_cast<node_type *>(\n        absl::container_internal::Allocate<node_type::Alignment()>(\n            mutable_allocator(), size));\n  }\n\n  // Node creation/deletion routines.\n  node_type *new_internal_node(field_type position, node_type *parent) {\n    node_type *n = allocate(node_type::InternalSize());\n    n->init_internal(position, parent);\n    return n;\n  }\n  node_type *new_leaf_node(field_type position, node_type *parent) {\n    node_type *n = allocate(node_type::LeafSize());\n    n->init_leaf(position, kNodeSlots, parent);\n    return n;\n  }\n  node_type *new_leaf_root_node(field_type max_count) {\n    node_type *n = allocate(node_type::LeafSize(max_count));\n    n->init_leaf(/*position=*/0, max_count, /*parent=*/n);\n    return n;\n  }\n\n  // Deletion helper routines.\n  iterator rebalance_after_delete(iterator iter);\n\n  // Rebalances or splits the node iter points to.\n  void rebalance_or_split(iterator *iter);\n\n  // Merges the values of left, right and the delimiting key on their parent\n  // onto left, removing the delimiting key and deleting right.\n  void merge_nodes(node_type *left, node_type *right);\n\n  // Tries to merge node with its left or right sibling, and failing that,\n  // rebalance with its left or right sibling. Returns true if a merge\n  // occurred, at which point it is no longer valid to access node. Returns\n  // false if no merging took place.\n  bool try_merge_or_rebalance(iterator *iter);\n\n  // Tries to shrink the height of the tree by 1.\n  void try_shrink();\n\n  iterator internal_end(iterator iter) {\n    return iter.node_ != nullptr ? iter : end();\n  }\n  const_iterator internal_end(const_iterator iter) const {\n    return iter.node_ != nullptr ? iter : end();\n  }\n\n  // Emplaces a value into the btree immediately before iter. Requires that\n  // key(v) <= iter.key() and (--iter).key() <= key(v).\n  template <typename... Args>\n  iterator internal_emplace(iterator iter, Args &&...args);\n\n  // Returns an iterator pointing to the first value >= the value \"iter\" is\n  // pointing at. Note that \"iter\" might be pointing to an invalid location such\n  // as iter.position_ == iter.node_->finish(). This routine simply moves iter\n  // up in the tree to a valid location. Requires: iter.node_ is non-null.\n  template <typename IterType>\n  static IterType internal_last(IterType iter);\n\n  // Returns an iterator pointing to the leaf position at which key would\n  // reside in the tree, unless there is an exact match - in which case, the\n  // result may not be on a leaf. When there's a three-way comparator, we can\n  // return whether there was an exact match. This allows the caller to avoid a\n  // subsequent comparison to determine if an exact match was made, which is\n  // important for keys with expensive comparison, such as strings.\n  template <typename K>\n  SearchResult<iterator, is_key_compare_to::value> internal_locate(\n      const K &key) const;\n\n  // Internal routine which implements lower_bound().\n  template <typename K>\n  SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(\n      const K &key) const;\n\n  // Internal routine which implements upper_bound().\n  template <typename K>\n  iterator internal_upper_bound(const K &key) const;\n\n  // Internal routine which implements find().\n  template <typename K>\n  iterator internal_find(const K &key) const;\n\n  // Verifies the tree structure of node.\n  size_type internal_verify(const node_type *node, const key_type *lo,\n                            const key_type *hi) const;\n\n  node_stats internal_stats(const node_type *node) const {\n    // The root can be a static empty node.\n    if (node == nullptr || (node == root() && empty())) {\n      return node_stats(0, 0);\n    }\n    if (node->is_leaf()) {\n      return node_stats(1, 0);\n    }\n    node_stats res(0, 1);\n    for (int i = node->start(); i <= node->finish(); ++i) {\n      res += internal_stats(node->child(i));\n    }\n    return res;\n  }\n\n  node_type *root_;\n\n  // A pointer to the rightmost node. Note that the leftmost node is stored as\n  // the root's parent. We use compressed tuple in order to save space because\n  // key_compare and allocator_type are usually empty.\n  absl::container_internal::CompressedTuple<key_compare, allocator_type,\n                                            node_type *>\n      rightmost_;\n\n  // Number of values.\n  size_type size_;\n};\n\n////\n// btree_node methods\ntemplate <typename P>\ntemplate <typename... Args>\ninline void btree_node<P>::emplace_value(const field_type i,\n                                         allocator_type *alloc,\n                                         Args &&...args) {\n  assert(i >= start());\n  assert(i <= finish());\n  // Shift old values to create space for new value and then construct it in\n  // place.\n  if (i < finish()) {\n    transfer_n_backward(finish() - i, /*dest_i=*/i + 1, /*src_i=*/i, this,\n                        alloc);\n  }\n  value_init(static_cast<field_type>(i), alloc, std::forward<Args>(args)...);\n  set_finish(finish() + 1);\n\n  if (is_internal() && finish() > i + 1) {\n    for (field_type j = finish(); j > i + 1; --j) {\n      set_child(j, child(j - 1));\n    }\n    clear_child(i + 1);\n  }\n}\n\ntemplate <typename P>\ninline void btree_node<P>::remove_values(const field_type i,\n                                         const field_type to_erase,\n                                         allocator_type *alloc) {\n  // Transfer values after the removed range into their new places.\n  value_destroy_n(i, to_erase, alloc);\n  const field_type orig_finish = finish();\n  const field_type src_i = i + to_erase;\n  transfer_n(orig_finish - src_i, i, src_i, this, alloc);\n\n  if (is_internal()) {\n    // Delete all children between begin and end.\n    for (field_type j = 0; j < to_erase; ++j) {\n      clear_and_delete(child(i + j + 1), alloc);\n    }\n    // Rotate children after end into new positions.\n    for (field_type j = i + to_erase + 1; j <= orig_finish; ++j) {\n      set_child(j - to_erase, child(j));\n      clear_child(j);\n    }\n  }\n  set_finish(orig_finish - to_erase);\n}\n\ntemplate <typename P>\nvoid btree_node<P>::rebalance_right_to_left(field_type to_move,\n                                            btree_node *right,\n                                            allocator_type *alloc) {\n  assert(parent() == right->parent());\n  assert(position() + 1 == right->position());\n  assert(right->count() >= count());\n  assert(to_move >= 1);\n  assert(to_move <= right->count());\n\n  // 1) Move the delimiting value in the parent to the left node.\n  transfer(finish(), position(), parent(), alloc);\n\n  // 2) Move the (to_move - 1) values from the right node to the left node.\n  transfer_n(to_move - 1, finish() + 1, right->start(), right, alloc);\n\n  // 3) Move the new delimiting value to the parent from the right node.\n  parent()->transfer(position(), right->start() + to_move - 1, right, alloc);\n\n  // 4) Shift the values in the right node to their correct positions.\n  right->transfer_n(right->count() - to_move, right->start(),\n                    right->start() + to_move, right, alloc);\n\n  if (is_internal()) {\n    // Move the child pointers from the right to the left node.\n    for (field_type i = 0; i < to_move; ++i) {\n      init_child(finish() + i + 1, right->child(i));\n    }\n    for (field_type i = right->start(); i <= right->finish() - to_move; ++i) {\n      assert(i + to_move <= right->max_count());\n      right->init_child(i, right->child(i + to_move));\n      right->clear_child(i + to_move);\n    }\n  }\n\n  // Fixup `finish` on the left and right nodes.\n  set_finish(finish() + to_move);\n  right->set_finish(right->finish() - to_move);\n}\n\ntemplate <typename P>\nvoid btree_node<P>::rebalance_left_to_right(field_type to_move,\n                                            btree_node *right,\n                                            allocator_type *alloc) {\n  assert(parent() == right->parent());\n  assert(position() + 1 == right->position());\n  assert(count() >= right->count());\n  assert(to_move >= 1);\n  assert(to_move <= count());\n\n  // Values in the right node are shifted to the right to make room for the\n  // new to_move values. Then, the delimiting value in the parent and the\n  // other (to_move - 1) values in the left node are moved into the right node.\n  // Lastly, a new delimiting value is moved from the left node into the\n  // parent, and the remaining empty left node entries are destroyed.\n\n  // 1) Shift existing values in the right node to their correct positions.\n  right->transfer_n_backward(right->count(), right->start() + to_move,\n                             right->start(), right, alloc);\n\n  // 2) Move the delimiting value in the parent to the right node.\n  right->transfer(right->start() + to_move - 1, position(), parent(), alloc);\n\n  // 3) Move the (to_move - 1) values from the left node to the right node.\n  right->transfer_n(to_move - 1, right->start(), finish() - (to_move - 1), this,\n                    alloc);\n\n  // 4) Move the new delimiting value to the parent from the left node.\n  parent()->transfer(position(), finish() - to_move, this, alloc);\n\n  if (is_internal()) {\n    // Move the child pointers from the left to the right node.\n    for (field_type i = right->finish() + 1; i > right->start(); --i) {\n      right->init_child(i - 1 + to_move, right->child(i - 1));\n      right->clear_child(i - 1);\n    }\n    for (field_type i = 1; i <= to_move; ++i) {\n      right->init_child(i - 1, child(finish() - to_move + i));\n      clear_child(finish() - to_move + i);\n    }\n  }\n\n  // Fixup the counts on the left and right nodes.\n  set_finish(finish() - to_move);\n  right->set_finish(right->finish() + to_move);\n}\n\ntemplate <typename P>\nvoid btree_node<P>::split(const int insert_position, btree_node *dest,\n                          allocator_type *alloc) {\n  assert(dest->count() == 0);\n  assert(max_count() == kNodeSlots);\n  assert(position() + 1 == dest->position());\n  assert(parent() == dest->parent());\n\n  // We bias the split based on the position being inserted. If we're\n  // inserting at the beginning of the left node then bias the split to put\n  // more values on the right node. If we're inserting at the end of the\n  // right node then bias the split to put more values on the left node.\n  if (insert_position == start()) {\n    dest->set_finish(dest->start() + finish() - 1);\n  } else if (insert_position == kNodeSlots) {\n    dest->set_finish(dest->start());\n  } else {\n    dest->set_finish(dest->start() + count() / 2);\n  }\n  set_finish(finish() - dest->count());\n  assert(count() >= 1);\n\n  // Move values from the left sibling to the right sibling.\n  dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc);\n\n  // The split key is the largest value in the left sibling.\n  --mutable_finish();\n  parent()->emplace_value(position(), alloc, finish_slot());\n  value_destroy(finish(), alloc);\n  parent()->set_child_noupdate_position(position() + 1, dest);\n\n  if (is_internal()) {\n    for (field_type i = dest->start(), j = finish() + 1; i <= dest->finish();\n         ++i, ++j) {\n      assert(child(j) != nullptr);\n      dest->init_child(i, child(j));\n      clear_child(j);\n    }\n  }\n}\n\ntemplate <typename P>\nvoid btree_node<P>::merge(btree_node *src, allocator_type *alloc) {\n  assert(parent() == src->parent());\n  assert(position() + 1 == src->position());\n\n  // Move the delimiting value to the left node.\n  value_init(finish(), alloc, parent()->slot(position()));\n\n  // Move the values from the right to the left node.\n  transfer_n(src->count(), finish() + 1, src->start(), src, alloc);\n\n  if (is_internal()) {\n    // Move the child pointers from the right to the left node.\n    for (field_type i = src->start(), j = finish() + 1; i <= src->finish();\n         ++i, ++j) {\n      init_child(j, src->child(i));\n      src->clear_child(i);\n    }\n  }\n\n  // Fixup `finish` on the src and dest nodes.\n  set_finish(start() + 1 + count() + src->count());\n  src->set_finish(src->start());\n\n  // Remove the value on the parent node and delete the src node.\n  parent()->remove_values(position(), /*to_erase=*/1, alloc);\n}\n\ntemplate <typename P>\nvoid btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) {\n  if (node->is_leaf()) {\n    node->value_destroy_n(node->start(), node->count(), alloc);\n    deallocate(LeafSize(node->max_count()), node, alloc);\n    return;\n  }\n  if (node->count() == 0) {\n    deallocate(InternalSize(), node, alloc);\n    return;\n  }\n\n  // The parent of the root of the subtree we are deleting.\n  btree_node *delete_root_parent = node->parent();\n\n  // Navigate to the leftmost leaf under node, and then delete upwards.\n  while (node->is_internal()) node = node->start_child();\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\n  // When generations are enabled, we delete the leftmost leaf last in case it's\n  // the parent of the root and we need to check whether it's a leaf before we\n  // can update the root's generation.\n  // TODO(ezb): if we change btree_node::is_root to check a bool inside the node\n  // instead of checking whether the parent is a leaf, we can remove this logic.\n  btree_node *leftmost_leaf = node;\n#endif\n  // Use `size_type` because `pos` needs to be able to hold `kNodeSlots+1`,\n  // which isn't guaranteed to be a valid `field_type`.\n  size_type pos = node->position();\n  btree_node *parent = node->parent();\n  for (;;) {\n    // In each iteration of the next loop, we delete one leaf node and go right.\n    assert(pos <= parent->finish());\n    do {\n      node = parent->child(static_cast<field_type>(pos));\n      if (node->is_internal()) {\n        // Navigate to the leftmost leaf under node.\n        while (node->is_internal()) node = node->start_child();\n        pos = node->position();\n        parent = node->parent();\n      }\n      node->value_destroy_n(node->start(), node->count(), alloc);\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\n      if (leftmost_leaf != node)\n#endif\n        deallocate(LeafSize(node->max_count()), node, alloc);\n      ++pos;\n    } while (pos <= parent->finish());\n\n    // Once we've deleted all children of parent, delete parent and go up/right.\n    assert(pos > parent->finish());\n    do {\n      node = parent;\n      pos = node->position();\n      parent = node->parent();\n      node->value_destroy_n(node->start(), node->count(), alloc);\n      deallocate(InternalSize(), node, alloc);\n      if (parent == delete_root_parent) {\n#ifdef ABSL_BTREE_ENABLE_GENERATIONS\n        deallocate(LeafSize(leftmost_leaf->max_count()), leftmost_leaf, alloc);\n#endif\n        return;\n      }\n      ++pos;\n    } while (pos > parent->finish());\n  }\n}\n\n////\n// btree_iterator methods\n\n// Note: the implementation here is based on btree_node::clear_and_delete.\ntemplate <typename N, typename R, typename P>\nauto btree_iterator<N, R, P>::distance_slow(const_iterator other) const\n    -> difference_type {\n  const_iterator begin = other;\n  const_iterator end = *this;\n  assert(begin.node_ != end.node_ || !begin.node_->is_leaf() ||\n         begin.position_ != end.position_);\n\n  const node_type *node = begin.node_;\n  // We need to compensate for double counting if begin.node_ is a leaf node.\n  difference_type count = node->is_leaf() ? -begin.position_ : 0;\n\n  // First navigate to the leftmost leaf node past begin.\n  if (node->is_internal()) {\n    ++count;\n    node = node->child(begin.position_ + 1);\n  }\n  while (node->is_internal()) node = node->start_child();\n\n  // Use `size_type` because `pos` needs to be able to hold `kNodeSlots+1`,\n  // which isn't guaranteed to be a valid `field_type`.\n  size_type pos = node->position();\n  const node_type *parent = node->parent();\n  for (;;) {\n    // In each iteration of the next loop, we count one leaf node and go right.\n    assert(pos <= parent->finish());\n    do {\n      node = parent->child(static_cast<field_type>(pos));\n      if (node->is_internal()) {\n        // Navigate to the leftmost leaf under node.\n        while (node->is_internal()) node = node->start_child();\n        pos = node->position();\n        parent = node->parent();\n      }\n      if (node == end.node_) return count + end.position_;\n      if (parent == end.node_ && pos == static_cast<size_type>(end.position_))\n        return count + node->count();\n      // +1 is for the next internal node value.\n      count += node->count() + 1;\n      ++pos;\n    } while (pos <= parent->finish());\n\n    // Once we've counted all children of parent, go up/right.\n    assert(pos > parent->finish());\n    do {\n      node = parent;\n      pos = node->position();\n      parent = node->parent();\n      // -1 because we counted the value at end and shouldn't.\n      if (parent == end.node_ && pos == static_cast<size_type>(end.position_))\n        return count - 1;\n      ++pos;\n    } while (pos > parent->finish());\n  }\n}\n\ntemplate <typename N, typename R, typename P>\nvoid btree_iterator<N, R, P>::increment_slow() {\n  N* node = node_;\n  int position = position_;\n  if (node->is_leaf()) {\n    assert(position >= node->finish());\n    while (position == node->finish() && !node->is_root()) {\n      assert(node->parent()->child(node->position()) == node);\n      position = node->position();\n      node = node->parent();\n    }\n    // TODO(ezb): assert we aren't incrementing end() instead of handling.\n    if (position == node->finish()) {\n      return;\n    }\n  } else {\n    assert(position < node->finish());\n    node = node->child(static_cast<field_type>(position + 1));\n    while (node->is_internal()) {\n      node = node->start_child();\n    }\n    position = node->start();\n  }\n  *this = {node, position};\n}\n\ntemplate <typename N, typename R, typename P>\nvoid btree_iterator<N, R, P>::decrement_slow() {\n  N* node = node_;\n  int position = position_;\n  if (node->is_leaf()) {\n    assert(position <= -1);\n    while (position < node->start() && !node->is_root()) {\n      assert(node->parent()->child(node->position()) == node);\n      position = node->position() - 1;\n      node = node->parent();\n    }\n    // TODO(ezb): assert we aren't decrementing begin() instead of handling.\n    if (position < node->start()) {\n      return;\n    }\n  } else {\n    assert(position >= node->start());\n    node = node->child(static_cast<field_type>(position));\n    while (node->is_internal()) {\n      node = node->child(node->finish());\n    }\n    position = node->finish() - 1;\n  }\n  *this = {node, position};\n}\n\ntemplate <typename N, typename R, typename P>\nbtree_iterator<N, R, P> &btree_iterator<N, R, P>::increment_n_slow(\n    difference_type n) {\n  N *node = node_;\n  int position = position_;\n  ABSL_ASSUME(n > 0);\n  while (n > 0) {\n    if (node->is_leaf()) {\n      if (position + n < node->finish()) {\n        position += n;\n        break;\n      } else {\n        n -= node->finish() - position;\n        position = node->finish();\n        btree_iterator save = {node, position};\n        while (position == node->finish() && !node->is_root()) {\n          position = node->position();\n          node = node->parent();\n        }\n        if (position == node->finish()) {\n          ABSL_HARDENING_ASSERT(n == 0);\n          return *this = save;\n        }\n      }\n    } else {\n      --n;\n      assert(position < node->finish());\n      node = node->child(static_cast<field_type>(position + 1));\n      while (node->is_internal()) {\n        node = node->start_child();\n      }\n      position = node->start();\n    }\n  }\n  node_ = node;\n  position_ = position;\n  return *this;\n}\n\ntemplate <typename N, typename R, typename P>\nbtree_iterator<N, R, P> &btree_iterator<N, R, P>::decrement_n_slow(\n    difference_type n) {\n  N *node = node_;\n  int position = position_;\n  ABSL_ASSUME(n > 0);\n  while (n > 0) {\n    if (node->is_leaf()) {\n      if (position - n >= node->start()) {\n        position -= n;\n        break;\n      } else {\n        n -= 1 + position - node->start();\n        position = node->start() - 1;\n        while (position < node->start() && !node->is_root()) {\n          position = node->position() - 1;\n          node = node->parent();\n        }\n        ABSL_HARDENING_ASSERT(position >= node->start());\n      }\n    } else {\n      --n;\n      assert(position >= node->start());\n      node = node->child(static_cast<field_type>(position));\n      while (node->is_internal()) {\n        node = node->child(node->finish());\n      }\n      position = node->finish() - 1;\n    }\n  }\n  node_ = node;\n  position_ = position;\n  return *this;\n}\n\n////\n// btree methods\ntemplate <typename P>\ntemplate <typename Btree>\nvoid btree<P>::copy_or_move_values_in_order(Btree &other) {\n  static_assert(std::is_same<btree, Btree>::value ||\n                    std::is_same<const btree, Btree>::value,\n                \"Btree type must be same or const.\");\n  assert(empty());\n\n  // We can avoid key comparisons because we know the order of the\n  // values is the same order we'll store them in.\n  auto iter = other.begin();\n  if (iter == other.end()) return;\n  insert_multi(iter.slot());\n  ++iter;\n  for (; iter != other.end(); ++iter) {\n    // If the btree is not empty, we can just insert the new value at the end\n    // of the tree.\n    internal_emplace(end(), iter.slot());\n  }\n}\n\ntemplate <typename P>\nconstexpr bool btree<P>::static_assert_validation() {\n  static_assert(std::is_nothrow_copy_constructible<key_compare>::value,\n                \"Key comparison must be nothrow copy constructible\");\n  static_assert(std::is_nothrow_copy_constructible<allocator_type>::value,\n                \"Allocator must be nothrow copy constructible\");\n  static_assert(std::is_trivially_copyable<iterator>::value,\n                \"iterator not trivially copyable.\");\n\n  // Note: We assert that kTargetValues, which is computed from\n  // Params::kTargetNodeSize, must fit the node_type::field_type.\n  static_assert(\n      kNodeSlots < (1 << (8 * sizeof(typename node_type::field_type))),\n      \"target node size too large\");\n\n  // Verify that key_compare returns an absl::{weak,strong}_ordering or bool.\n  static_assert(\n      compare_has_valid_result_type<key_compare, key_type>(),\n      \"key comparison function must return absl::{weak,strong}_ordering or \"\n      \"bool.\");\n\n  // Test the assumption made in setting kNodeSlotSpace.\n  static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4,\n                \"node space assumption incorrect\");\n\n  return true;\n}\n\ntemplate <typename P>\ntemplate <typename K>\nauto btree<P>::lower_bound_equal(const K &key) const\n    -> std::pair<iterator, bool> {\n  const SearchResult<iterator, is_key_compare_to::value> res =\n      internal_lower_bound(key);\n  const iterator lower = iterator(internal_end(res.value));\n  const bool equal = res.HasMatch()\n                         ? res.IsEq()\n                         : lower != end() && !compare_keys(key, lower.key());\n  return {lower, equal};\n}\n\ntemplate <typename P>\ntemplate <typename K>\nauto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {\n  const std::pair<iterator, bool> lower_and_equal = lower_bound_equal(key);\n  const iterator lower = lower_and_equal.first;\n  if (!lower_and_equal.second) {\n    return {lower, lower};\n  }\n\n  const iterator next = std::next(lower);\n  if (!params_type::template can_have_multiple_equivalent_keys<K>()) {\n    // The next iterator after lower must point to a key greater than `key`.\n    // Note: if this assert fails, then it may indicate that the comparator does\n    // not meet the equivalence requirements for Compare\n    // (see https://en.cppreference.com/w/cpp/named_req/Compare).\n    assert(next == end() || compare_keys(key, next.key()));\n    return {lower, next};\n  }\n  // Try once more to avoid the call to upper_bound() if there's only one\n  // equivalent key. This should prevent all calls to upper_bound() in cases of\n  // unique-containers with heterogeneous comparators in which all comparison\n  // operators have the same equivalence classes.\n  if (next == end() || compare_keys(key, next.key())) return {lower, next};\n\n  // In this case, we need to call upper_bound() to avoid worst case O(N)\n  // behavior if we were to iterate over equal keys.\n  return {lower, upper_bound(key)};\n}\n\ntemplate <typename P>\ntemplate <typename K, typename... Args>\nauto btree<P>::insert_unique(const K &key, Args &&...args)\n    -> std::pair<iterator, bool> {\n  if (empty()) {\n    mutable_root() = mutable_rightmost() = new_leaf_root_node(1);\n  }\n\n  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);\n  iterator iter = res.value;\n\n  if (res.HasMatch()) {\n    if (res.IsEq()) {\n      // The key already exists in the tree, do nothing.\n      return {iter, false};\n    }\n  } else {\n    iterator last = internal_last(iter);\n    if (last.node_ && !compare_keys(key, last.key())) {\n      // The key already exists in the tree, do nothing.\n      return {last, false};\n    }\n  }\n  return {internal_emplace(iter, std::forward<Args>(args)...), true};\n}\n\ntemplate <typename P>\ntemplate <typename K, typename... Args>\ninline auto btree<P>::insert_hint_unique(iterator position, const K &key,\n                                         Args &&...args)\n    -> std::pair<iterator, bool> {\n  if (!empty()) {\n    if (position == end() || compare_keys(key, position.key())) {\n      if (position == begin() || compare_keys(std::prev(position).key(), key)) {\n        // prev.key() < key < position.key()\n        return {internal_emplace(position, std::forward<Args>(args)...), true};\n      }\n    } else if (compare_keys(position.key(), key)) {\n      ++position;\n      if (position == end() || compare_keys(key, position.key())) {\n        // {original `position`}.key() < key < {current `position`}.key()\n        return {internal_emplace(position, std::forward<Args>(args)...), true};\n      }\n    } else {\n      // position.key() == key\n      return {position, false};\n    }\n  }\n  return insert_unique(key, std::forward<Args>(args)...);\n}\n\ntemplate <typename P>\ntemplate <typename InputIterator, typename>\nvoid btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, int) {\n  for (; b != e; ++b) {\n    insert_hint_unique(end(), params_type::key(*b), *b);\n  }\n}\n\ntemplate <typename P>\ntemplate <typename InputIterator>\nvoid btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, char) {\n  for (; b != e; ++b) {\n    // Use a node handle to manage a temp slot.\n    auto node_handle =\n        CommonAccess::Construct<node_handle_type>(get_allocator(), *b);\n    slot_type *slot = CommonAccess::GetSlot(node_handle);\n    insert_hint_unique(end(), params_type::key(slot), slot);\n  }\n}\n\ntemplate <typename P>\ntemplate <typename ValueType>\nauto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {\n  if (empty()) {\n    mutable_root() = mutable_rightmost() = new_leaf_root_node(1);\n  }\n\n  iterator iter = internal_upper_bound(key);\n  if (iter.node_ == nullptr) {\n    iter = end();\n  }\n  return internal_emplace(iter, std::forward<ValueType>(v));\n}\n\ntemplate <typename P>\ntemplate <typename ValueType>\nauto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator {\n  if (!empty()) {\n    const key_type &key = params_type::key(v);\n    if (position == end() || !compare_keys(position.key(), key)) {\n      if (position == begin() ||\n          !compare_keys(key, std::prev(position).key())) {\n        // prev.key() <= key <= position.key()\n        return internal_emplace(position, std::forward<ValueType>(v));\n      }\n    } else {\n      ++position;\n      if (position == end() || !compare_keys(position.key(), key)) {\n        // {original `position`}.key() < key < {current `position`}.key()\n        return internal_emplace(position, std::forward<ValueType>(v));\n      }\n    }\n  }\n  return insert_multi(std::forward<ValueType>(v));\n}\n\ntemplate <typename P>\ntemplate <typename InputIterator>\nvoid btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {\n  for (; b != e; ++b) {\n    insert_hint_multi(end(), *b);\n  }\n}\n\ntemplate <typename P>\nauto btree<P>::operator=(const btree &other) -> btree & {\n  if (this != &other) {\n    clear();\n\n    *mutable_key_comp() = other.key_comp();\n    if (absl::allocator_traits<\n            allocator_type>::propagate_on_container_copy_assignment::value) {\n      *mutable_allocator() = other.allocator();\n    }\n\n    copy_or_move_values_in_order(other);\n  }\n  return *this;\n}\n\ntemplate <typename P>\nauto btree<P>::operator=(btree &&other) noexcept -> btree & {\n  if (this != &other) {\n    clear();\n\n    using std::swap;\n    if (absl::allocator_traits<\n            allocator_type>::propagate_on_container_move_assignment::value) {\n      swap(root_, other.root_);\n      // Note: `rightmost_` also contains the allocator and the key comparator.\n      swap(rightmost_, other.rightmost_);\n      swap(size_, other.size_);\n    } else {\n      if (allocator() == other.allocator()) {\n        swap(mutable_root(), other.mutable_root());\n        swap(*mutable_key_comp(), *other.mutable_key_comp());\n        swap(mutable_rightmost(), other.mutable_rightmost());\n        swap(size_, other.size_);\n      } else {\n        // We aren't allowed to propagate the allocator and the allocator is\n        // different so we can't take over its memory. We must move each element\n        // individually. We need both `other` and `this` to have `other`s key\n        // comparator while moving the values so we can't swap the key\n        // comparators.\n        *mutable_key_comp() = other.key_comp();\n        copy_or_move_values_in_order(other);\n      }\n    }\n  }\n  return *this;\n}\n\ntemplate <typename P>\nauto btree<P>::erase(iterator iter) -> iterator {\n  iter.node_->value_destroy(static_cast<field_type>(iter.position_),\n                            mutable_allocator());\n  iter.update_generation();\n\n  const bool internal_delete = iter.node_->is_internal();\n  if (internal_delete) {\n    // Deletion of a value on an internal node. First, transfer the largest\n    // value from our left child here, then erase/rebalance from that position.\n    // We can get to the largest value from our left child by decrementing iter.\n    iterator internal_iter(iter);\n    --iter;\n    assert(iter.node_->is_leaf());\n    internal_iter.node_->transfer(\n        static_cast<size_type>(internal_iter.position_),\n        static_cast<size_type>(iter.position_), iter.node_,\n        mutable_allocator());\n  } else {\n    // Shift values after erased position in leaf. In the internal case, we\n    // don't need to do this because the leaf position is the end of the node.\n    const field_type transfer_from =\n        static_cast<field_type>(iter.position_ + 1);\n    const field_type num_to_transfer = iter.node_->finish() - transfer_from;\n    iter.node_->transfer_n(num_to_transfer,\n                           static_cast<size_type>(iter.position_),\n                           transfer_from, iter.node_, mutable_allocator());\n  }\n  // Update node finish and container size.\n  iter.node_->set_finish(iter.node_->finish() - 1);\n  --size_;\n\n  // We want to return the next value after the one we just erased. If we\n  // erased from an internal node (internal_delete == true), then the next\n  // value is ++(++iter). If we erased from a leaf node (internal_delete ==\n  // false) then the next value is ++iter. Note that ++iter may point to an\n  // internal node and the value in the internal node may move to a leaf node\n  // (iter.node_) when rebalancing is performed at the leaf level.\n\n  iterator res = rebalance_after_delete(iter);\n\n  // If we erased from an internal node, advance the iterator.\n  if (internal_delete) {\n    ++res;\n  }\n  return res;\n}\n\ntemplate <typename P>\nauto btree<P>::rebalance_after_delete(iterator iter) -> iterator {\n  // Merge/rebalance as we walk back up the tree.\n  iterator res(iter);\n  bool first_iteration = true;\n  for (;;) {\n    if (iter.node_ == root()) {\n      try_shrink();\n      if (empty()) {\n        return end();\n      }\n      break;\n    }\n    if (iter.node_->count() >= kMinNodeValues) {\n      break;\n    }\n    bool merged = try_merge_or_rebalance(&iter);\n    // On the first iteration, we should update `res` with `iter` because `res`\n    // may have been invalidated.\n    if (first_iteration) {\n      res = iter;\n      first_iteration = false;\n    }\n    if (!merged) {\n      break;\n    }\n    iter.position_ = iter.node_->position();\n    iter.node_ = iter.node_->parent();\n  }\n  res.update_generation();\n\n  // Adjust our return value. If we're pointing at the end of a node, advance\n  // the iterator.\n  if (res.position_ == res.node_->finish()) {\n    res.position_ = res.node_->finish() - 1;\n    ++res;\n  }\n\n  return res;\n}\n\n// Note: we tried implementing this more efficiently by erasing all of the\n// elements in [begin, end) at once and then doing rebalancing once at the end\n// (rather than interleaving deletion and rebalancing), but that adds a lot of\n// complexity, which seems to outweigh the performance win.\ntemplate <typename P>\nauto btree<P>::erase_range(iterator begin, iterator end)\n    -> std::pair<size_type, iterator> {\n  size_type count = static_cast<size_type>(end - begin);\n  assert(count >= 0);\n\n  if (count == 0) {\n    return {0, begin};\n  }\n\n  if (static_cast<size_type>(count) == size_) {\n    clear();\n    return {count, this->end()};\n  }\n\n  if (begin.node_ == end.node_) {\n    assert(end.position_ > begin.position_);\n    begin.node_->remove_values(\n        static_cast<field_type>(begin.position_),\n        static_cast<field_type>(end.position_ - begin.position_),\n        mutable_allocator());\n    size_ -= count;\n    return {count, rebalance_after_delete(begin)};\n  }\n\n  const size_type target_size = size_ - count;\n  while (size_ > target_size) {\n    if (begin.node_->is_leaf()) {\n      const size_type remaining_to_erase = size_ - target_size;\n      const size_type remaining_in_node =\n          static_cast<size_type>(begin.node_->finish() - begin.position_);\n      const field_type to_erase = static_cast<field_type>(\n          (std::min)(remaining_to_erase, remaining_in_node));\n      begin.node_->remove_values(static_cast<field_type>(begin.position_),\n                                 to_erase, mutable_allocator());\n      size_ -= to_erase;\n      begin = rebalance_after_delete(begin);\n    } else {\n      begin = erase(begin);\n    }\n  }\n  begin.update_generation();\n  return {count, begin};\n}\n\ntemplate <typename P>\nvoid btree<P>::clear() {\n  if (!empty()) {\n    node_type::clear_and_delete(root(), mutable_allocator());\n  }\n  mutable_root() = mutable_rightmost() = EmptyNode();\n  size_ = 0;\n}\n\ntemplate <typename P>\nvoid btree<P>::swap(btree &other) {\n  using std::swap;\n  if (absl::allocator_traits<\n          allocator_type>::propagate_on_container_swap::value) {\n    // Note: `rightmost_` also contains the allocator and the key comparator.\n    swap(rightmost_, other.rightmost_);\n  } else {\n    // It's undefined behavior if the allocators are unequal here.\n    assert(allocator() == other.allocator());\n    swap(mutable_rightmost(), other.mutable_rightmost());\n    swap(*mutable_key_comp(), *other.mutable_key_comp());\n  }\n  swap(mutable_root(), other.mutable_root());\n  swap(size_, other.size_);\n}\n\ntemplate <typename P>\nvoid btree<P>::verify() const {\n  assert(root() != nullptr);\n  assert(leftmost() != nullptr);\n  assert(rightmost() != nullptr);\n  assert(empty() || size() == internal_verify(root(), nullptr, nullptr));\n  assert(leftmost() == (++const_iterator(root(), -1)).node_);\n  assert(rightmost() == (--const_iterator(root(), root()->finish())).node_);\n  assert(leftmost()->is_leaf());\n  assert(rightmost()->is_leaf());\n}\n\ntemplate <typename P>\nvoid btree<P>::rebalance_or_split(iterator *iter) {\n  node_type *&node = iter->node_;\n  int &insert_position = iter->position_;\n  assert(node->count() == node->max_count());\n  assert(kNodeSlots == node->max_count());\n\n  // First try to make room on the node by rebalancing.\n  node_type *parent = node->parent();\n  if (node != root()) {\n    if (node->position() > parent->start()) {\n      // Try rebalancing with our left sibling.\n      node_type *left = parent->child(node->position() - 1);\n      assert(left->max_count() == kNodeSlots);\n      if (left->count() < kNodeSlots) {\n        // We bias rebalancing based on the position being inserted. If we're\n        // inserting at the end of the right node then we bias rebalancing to\n        // fill up the left node.\n        field_type to_move =\n            (kNodeSlots - left->count()) /\n            (1 + (static_cast<field_type>(insert_position) < kNodeSlots));\n        to_move = (std::max)(field_type{1}, to_move);\n\n        if (static_cast<field_type>(insert_position) - to_move >=\n                node->start() ||\n            left->count() + to_move < kNodeSlots) {\n          left->rebalance_right_to_left(to_move, node, mutable_allocator());\n\n          assert(node->max_count() - node->count() == to_move);\n          insert_position = static_cast<int>(\n              static_cast<field_type>(insert_position) - to_move);\n          if (insert_position < node->start()) {\n            insert_position = insert_position + left->count() + 1;\n            node = left;\n          }\n\n          assert(node->count() < node->max_count());\n          return;\n        }\n      }\n    }\n\n    if (node->position() < parent->finish()) {\n      // Try rebalancing with our right sibling.\n      node_type *right = parent->child(node->position() + 1);\n      assert(right->max_count() == kNodeSlots);\n      if (right->count() < kNodeSlots) {\n        // We bias rebalancing based on the position being inserted. If we're\n        // inserting at the beginning of the left node then we bias rebalancing\n        // to fill up the right node.\n        field_type to_move = (kNodeSlots - right->count()) /\n                             (1 + (insert_position > node->start()));\n        to_move = (std::max)(field_type{1}, to_move);\n\n        if (static_cast<field_type>(insert_position) <=\n                node->finish() - to_move ||\n            right->count() + to_move < kNodeSlots) {\n          node->rebalance_left_to_right(to_move, right, mutable_allocator());\n\n          if (insert_position > node->finish()) {\n            insert_position = insert_position - node->count() - 1;\n            node = right;\n          }\n\n          assert(node->count() < node->max_count());\n          return;\n        }\n      }\n    }\n\n    // Rebalancing failed, make sure there is room on the parent node for a new\n    // value.\n    assert(parent->max_count() == kNodeSlots);\n    if (parent->count() == kNodeSlots) {\n      iterator parent_iter(parent, node->position());\n      rebalance_or_split(&parent_iter);\n      parent = node->parent();\n    }\n  } else {\n    // Rebalancing not possible because this is the root node.\n    // Create a new root node and set the current root node as the child of the\n    // new root.\n    parent = new_internal_node(/*position=*/0, parent);\n    parent->set_generation(root()->generation());\n    parent->init_child(parent->start(), node);\n    mutable_root() = parent;\n    // If the former root was a leaf node, then it's now the rightmost node.\n    assert(parent->start_child()->is_internal() ||\n           parent->start_child() == rightmost());\n  }\n\n  // Split the node.\n  node_type *split_node;\n  if (node->is_leaf()) {\n    split_node = new_leaf_node(node->position() + 1, parent);\n    node->split(insert_position, split_node, mutable_allocator());\n    if (rightmost() == node) mutable_rightmost() = split_node;\n  } else {\n    split_node = new_internal_node(node->position() + 1, parent);\n    node->split(insert_position, split_node, mutable_allocator());\n  }\n\n  if (insert_position > node->finish()) {\n    insert_position = insert_position - node->count() - 1;\n    node = split_node;\n  }\n}\n\ntemplate <typename P>\nvoid btree<P>::merge_nodes(node_type *left, node_type *right) {\n  left->merge(right, mutable_allocator());\n  if (rightmost() == right) mutable_rightmost() = left;\n}\n\ntemplate <typename P>\nbool btree<P>::try_merge_or_rebalance(iterator *iter) {\n  node_type *parent = iter->node_->parent();\n  if (iter->node_->position() > parent->start()) {\n    // Try merging with our left sibling.\n    node_type *left = parent->child(iter->node_->position() - 1);\n    assert(left->max_count() == kNodeSlots);\n    if (1U + left->count() + iter->node_->count() <= kNodeSlots) {\n      iter->position_ += 1 + left->count();\n      merge_nodes(left, iter->node_);\n      iter->node_ = left;\n      return true;\n    }\n  }\n  if (iter->node_->position() < parent->finish()) {\n    // Try merging with our right sibling.\n    node_type *right = parent->child(iter->node_->position() + 1);\n    assert(right->max_count() == kNodeSlots);\n    if (1U + iter->node_->count() + right->count() <= kNodeSlots) {\n      merge_nodes(iter->node_, right);\n      return true;\n    }\n    // Try rebalancing with our right sibling. We don't perform rebalancing if\n    // we deleted the first element from iter->node_ and the node is not\n    // empty. This is a small optimization for the common pattern of deleting\n    // from the front of the tree.\n    if (right->count() > kMinNodeValues &&\n        (iter->node_->count() == 0 || iter->position_ > iter->node_->start())) {\n      field_type to_move = (right->count() - iter->node_->count()) / 2;\n      to_move =\n          (std::min)(to_move, static_cast<field_type>(right->count() - 1));\n      iter->node_->rebalance_right_to_left(to_move, right, mutable_allocator());\n      return false;\n    }\n  }\n  if (iter->node_->position() > parent->start()) {\n    // Try rebalancing with our left sibling. We don't perform rebalancing if\n    // we deleted the last element from iter->node_ and the node is not\n    // empty. This is a small optimization for the common pattern of deleting\n    // from the back of the tree.\n    node_type *left = parent->child(iter->node_->position() - 1);\n    if (left->count() > kMinNodeValues &&\n        (iter->node_->count() == 0 ||\n         iter->position_ < iter->node_->finish())) {\n      field_type to_move = (left->count() - iter->node_->count()) / 2;\n      to_move = (std::min)(to_move, static_cast<field_type>(left->count() - 1));\n      left->rebalance_left_to_right(to_move, iter->node_, mutable_allocator());\n      iter->position_ += to_move;\n      return false;\n    }\n  }\n  return false;\n}\n\ntemplate <typename P>\nvoid btree<P>::try_shrink() {\n  node_type *orig_root = root();\n  if (orig_root->count() > 0) {\n    return;\n  }\n  // Deleted the last item on the root node, shrink the height of the tree.\n  if (orig_root->is_leaf()) {\n    assert(size() == 0);\n    mutable_root() = mutable_rightmost() = EmptyNode();\n  } else {\n    node_type *child = orig_root->start_child();\n    child->make_root();\n    mutable_root() = child;\n  }\n  node_type::clear_and_delete(orig_root, mutable_allocator());\n}\n\ntemplate <typename P>\ntemplate <typename IterType>\ninline IterType btree<P>::internal_last(IterType iter) {\n  assert(iter.node_ != nullptr);\n  while (iter.position_ == iter.node_->finish()) {\n    iter.position_ = iter.node_->position();\n    iter.node_ = iter.node_->parent();\n    if (iter.node_->is_leaf()) {\n      iter.node_ = nullptr;\n      break;\n    }\n  }\n  iter.update_generation();\n  return iter;\n}\n\ntemplate <typename P>\ntemplate <typename... Args>\ninline auto btree<P>::internal_emplace(iterator iter, Args &&...args)\n    -> iterator {\n  if (iter.node_->is_internal()) {\n    // We can't insert on an internal node. Instead, we'll insert after the\n    // previous value which is guaranteed to be on a leaf node.\n    --iter;\n    ++iter.position_;\n  }\n  const field_type max_count = iter.node_->max_count();\n  allocator_type *alloc = mutable_allocator();\n\n  const auto transfer_and_delete = [&](node_type *old_node,\n                                       node_type *new_node) {\n    new_node->transfer_n(old_node->count(), new_node->start(),\n                         old_node->start(), old_node, alloc);\n    new_node->set_finish(old_node->finish());\n    old_node->set_finish(old_node->start());\n    new_node->set_generation(old_node->generation());\n    node_type::clear_and_delete(old_node, alloc);\n  };\n  const auto replace_leaf_root_node = [&](field_type new_node_size) {\n    assert(iter.node_ == root());\n    node_type *old_root = iter.node_;\n    node_type *new_root = iter.node_ = new_leaf_root_node(new_node_size);\n    transfer_and_delete(old_root, new_root);\n    mutable_root() = mutable_rightmost() = new_root;\n  };\n\n  bool replaced_node = false;\n  if (iter.node_->count() == max_count) {\n    // Make room in the leaf for the new item.\n    if (max_count < kNodeSlots) {\n      // Insertion into the root where the root is smaller than the full node\n      // size. Simply grow the size of the root node.\n      replace_leaf_root_node(static_cast<field_type>(\n          (std::min)(static_cast<int>(kNodeSlots), 2 * max_count)));\n      replaced_node = true;\n    } else {\n      rebalance_or_split(&iter);\n    }\n  }\n  (void)replaced_node;\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_HWADDRESS_SANITIZER)\n  if (!replaced_node) {\n    assert(iter.node_->is_leaf());\n    if (iter.node_->is_root()) {\n      replace_leaf_root_node(max_count);\n    } else {\n      node_type *old_node = iter.node_;\n      const bool was_rightmost = rightmost() == old_node;\n      const bool was_leftmost = leftmost() == old_node;\n      node_type *parent = old_node->parent();\n      const field_type position = old_node->position();\n      node_type *new_node = iter.node_ = new_leaf_node(position, parent);\n      parent->set_child_noupdate_position(position, new_node);\n      transfer_and_delete(old_node, new_node);\n      if (was_rightmost) mutable_rightmost() = new_node;\n      // The leftmost node is stored as the parent of the root node.\n      if (was_leftmost) root()->set_parent(new_node);\n    }\n  }\n#endif\n  iter.node_->emplace_value(static_cast<field_type>(iter.position_), alloc,\n                            std::forward<Args>(args)...);\n  assert(\n      iter.node_->is_ordered_correctly(static_cast<field_type>(iter.position_),\n                                       original_key_compare(key_comp())) &&\n      \"If this assert fails, then either (1) the comparator may violate \"\n      \"transitivity, i.e. comp(a,b) && comp(b,c) -> comp(a,c) (see \"\n      \"https://en.cppreference.com/w/cpp/named_req/Compare), or (2) a \"\n      \"key may have been mutated after it was inserted into the tree.\");\n  ++size_;\n  iter.update_generation();\n  return iter;\n}\n\ntemplate <typename P>\ntemplate <typename K>\ninline auto btree<P>::internal_locate(const K &key) const\n    -> SearchResult<iterator, is_key_compare_to::value> {\n  iterator iter(const_cast<node_type *>(root()));\n  for (;;) {\n    SearchResult<size_type, is_key_compare_to::value> res =\n        iter.node_->lower_bound(key, key_comp());\n    iter.position_ = static_cast<int>(res.value);\n    if (res.IsEq()) {\n      return {iter, MatchKind::kEq};\n    }\n    // Note: in the non-key-compare-to case, we don't need to walk all the way\n    // down the tree if the keys are equal, but determining equality would\n    // require doing an extra comparison on each node on the way down, and we\n    // will need to go all the way to the leaf node in the expected case.\n    if (iter.node_->is_leaf()) {\n      break;\n    }\n    iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));\n  }\n  // Note: in the non-key-compare-to case, the key may actually be equivalent\n  // here (and the MatchKind::kNe is ignored).\n  return {iter, MatchKind::kNe};\n}\n\ntemplate <typename P>\ntemplate <typename K>\nauto btree<P>::internal_lower_bound(const K &key) const\n    -> SearchResult<iterator, is_key_compare_to::value> {\n  if (!params_type::template can_have_multiple_equivalent_keys<K>()) {\n    SearchResult<iterator, is_key_compare_to::value> ret = internal_locate(key);\n    ret.value = internal_last(ret.value);\n    return ret;\n  }\n  iterator iter(const_cast<node_type *>(root()));\n  SearchResult<size_type, is_key_compare_to::value> res;\n  bool seen_eq = false;\n  for (;;) {\n    res = iter.node_->lower_bound(key, key_comp());\n    iter.position_ = static_cast<int>(res.value);\n    if (iter.node_->is_leaf()) {\n      break;\n    }\n    seen_eq = seen_eq || res.IsEq();\n    iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));\n  }\n  if (res.IsEq()) return {iter, MatchKind::kEq};\n  return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};\n}\n\ntemplate <typename P>\ntemplate <typename K>\nauto btree<P>::internal_upper_bound(const K &key) const -> iterator {\n  iterator iter(const_cast<node_type *>(root()));\n  for (;;) {\n    iter.position_ = static_cast<int>(iter.node_->upper_bound(key, key_comp()));\n    if (iter.node_->is_leaf()) {\n      break;\n    }\n    iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));\n  }\n  return internal_last(iter);\n}\n\ntemplate <typename P>\ntemplate <typename K>\nauto btree<P>::internal_find(const K &key) const -> iterator {\n  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);\n  if (res.HasMatch()) {\n    if (res.IsEq()) {\n      return res.value;\n    }\n  } else {\n    const iterator iter = internal_last(res.value);\n    if (iter.node_ != nullptr && !compare_keys(key, iter.key())) {\n      return iter;\n    }\n  }\n  return {nullptr, 0};\n}\n\ntemplate <typename P>\ntypename btree<P>::size_type btree<P>::internal_verify(\n    const node_type *node, const key_type *lo, const key_type *hi) const {\n  assert(node->count() > 0);\n  assert(node->count() <= node->max_count());\n  if (lo) {\n    assert(!compare_keys(node->key(node->start()), *lo));\n  }\n  if (hi) {\n    assert(!compare_keys(*hi, node->key(node->finish() - 1)));\n  }\n  for (int i = node->start() + 1; i < node->finish(); ++i) {\n    assert(!compare_keys(node->key(i), node->key(i - 1)));\n  }\n  size_type count = node->count();\n  if (node->is_internal()) {\n    for (field_type i = node->start(); i <= node->finish(); ++i) {\n      assert(node->child(i) != nullptr);\n      assert(node->child(i)->parent() == node);\n      assert(node->child(i)->position() == i);\n      count += internal_verify(node->child(i),\n                               i == node->start() ? lo : &node->key(i - 1),\n                               i == node->finish() ? hi : &node->key(i));\n    }\n  }\n  return count;\n}\n\nstruct btree_access {\n  template <typename BtreeContainer, typename Pred>\n  static auto erase_if(BtreeContainer &container, Pred pred) ->\n      typename BtreeContainer::size_type {\n    const auto initial_size = container.size();\n    auto &tree = container.tree_;\n    auto *alloc = tree.mutable_allocator();\n    for (auto it = container.begin(); it != container.end();) {\n      if (!pred(*it)) {\n        ++it;\n        continue;\n      }\n      auto *node = it.node_;\n      if (node->is_internal()) {\n        // Handle internal nodes normally.\n        it = container.erase(it);\n        continue;\n      }\n      // If this is a leaf node, then we do all the erases from this node\n      // at once before doing rebalancing.\n\n      // The current position to transfer slots to.\n      int to_pos = it.position_;\n      node->value_destroy(it.position_, alloc);\n      while (++it.position_ < node->finish()) {\n        it.update_generation();\n        if (pred(*it)) {\n          node->value_destroy(it.position_, alloc);\n        } else {\n          node->transfer(node->slot(to_pos++), node->slot(it.position_), alloc);\n        }\n      }\n      const int num_deleted = node->finish() - to_pos;\n      tree.size_ -= num_deleted;\n      node->set_finish(to_pos);\n      it.position_ = to_pos;\n      it = tree.rebalance_after_delete(it);\n    }\n    return initial_size - container.size();\n  }\n};\n\n#undef ABSL_BTREE_ENABLE_GENERATIONS\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_BTREE_H_\n"
  },
  {
    "path": "absl/container/internal/btree_container.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_\n#define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_\n\n#include <algorithm>\n#include <initializer_list>\n#include <iterator>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/container/internal/btree.h\"  // IWYU pragma: export\n#include \"absl/container/internal/common.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// A common base class for btree_set, btree_map, btree_multiset, and\n// btree_multimap.\ntemplate <typename Tree>\nclass btree_container {\n  using params_type = typename Tree::params_type;\n\n protected:\n  // Alias used for heterogeneous lookup functions.\n  // `key_arg<K>` evaluates to `K` when the functors are transparent and to\n  // `key_type` otherwise. It permits template argument deduction on `K` for the\n  // transparent case.\n  template <class K>\n  using key_arg =\n      typename KeyArg<params_type::kIsKeyCompareTransparent>::template type<\n          K, typename Tree::key_type>;\n\n public:\n  using key_type = typename Tree::key_type;\n  using value_type = typename Tree::value_type;\n  using size_type = typename Tree::size_type;\n  using difference_type = typename Tree::difference_type;\n  using key_compare = typename Tree::original_key_compare;\n  using value_compare = typename Tree::value_compare;\n  using allocator_type = typename Tree::allocator_type;\n  using reference = typename Tree::reference;\n  using const_reference = typename Tree::const_reference;\n  using pointer = typename Tree::pointer;\n  using const_pointer = typename Tree::const_pointer;\n  using iterator = typename Tree::iterator;\n  using const_iterator = typename Tree::const_iterator;\n  using reverse_iterator = typename Tree::reverse_iterator;\n  using const_reverse_iterator = typename Tree::const_reverse_iterator;\n  using node_type = typename Tree::node_handle_type;\n\n  struct extract_and_get_next_return_type {\n    node_type node;\n    iterator next;\n  };\n\n  // Constructors/assignments.\n  btree_container() : tree_(key_compare(), allocator_type()) {}\n  explicit btree_container(const key_compare &comp,\n                           const allocator_type &alloc = allocator_type())\n      : tree_(comp, alloc) {}\n  explicit btree_container(const allocator_type &alloc)\n      : tree_(key_compare(), alloc) {}\n\n  btree_container(const btree_container &other)\n      : btree_container(other, absl::allocator_traits<allocator_type>::\n                                   select_on_container_copy_construction(\n                                       other.get_allocator())) {}\n  btree_container(const btree_container &other, const allocator_type &alloc)\n      : tree_(other.tree_, alloc) {}\n\n  btree_container(btree_container &&other) noexcept(\n      std::is_nothrow_move_constructible<Tree>::value) = default;\n  btree_container(btree_container &&other, const allocator_type &alloc)\n      : tree_(std::move(other.tree_), alloc) {}\n\n  btree_container &operator=(const btree_container &other) = default;\n  btree_container &operator=(btree_container &&other) noexcept(\n      std::is_nothrow_move_assignable<Tree>::value) = default;\n\n  // Iterator routines.\n  iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.begin(); }\n  const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.begin();\n  }\n  const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.begin();\n  }\n  iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.end(); }\n  const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.end();\n  }\n  const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.end();\n  }\n  reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.rbegin();\n  }\n  const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.rbegin();\n  }\n  const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.rbegin();\n  }\n  reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.rend(); }\n  const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.rend();\n  }\n  const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.rend();\n  }\n\n  // Lookup routines.\n  template <typename K = key_type>\n  size_type count(const key_arg<K> &key) const {\n    auto equal_range = this->equal_range(key);\n    return equal_range.second - equal_range.first;\n  }\n  template <typename K = key_type>\n  iterator find(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.find(key);\n  }\n  template <typename K = key_type>\n  const_iterator find(const key_arg<K> &key) const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.find(key);\n  }\n  template <typename K = key_type>\n  bool contains(const key_arg<K> &key) const {\n    return find(key) != end();\n  }\n  template <typename K = key_type>\n  iterator lower_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.lower_bound(key);\n  }\n  template <typename K = key_type>\n  const_iterator lower_bound(const key_arg<K> &key) const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.lower_bound(key);\n  }\n  template <typename K = key_type>\n  iterator upper_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.upper_bound(key);\n  }\n  template <typename K = key_type>\n  const_iterator upper_bound(const key_arg<K> &key) const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.upper_bound(key);\n  }\n  template <typename K = key_type>\n  std::pair<iterator, iterator> equal_range(const key_arg<K> &key)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.equal_range(key);\n  }\n  template <typename K = key_type>\n  std::pair<const_iterator, const_iterator> equal_range(\n      const key_arg<K> &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.equal_range(key);\n  }\n\n  // Deletion routines. Note that there is also a deletion routine that is\n  // specific to btree_set_container/btree_multiset_container.\n\n  // Erase the specified iterator from the btree. The iterator must be valid\n  // (i.e. not equal to end()).  Return an iterator pointing to the node after\n  // the one that was erased (or end() if none exists).\n  iterator erase(const_iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.erase(iterator(iter));\n  }\n  iterator erase(iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.erase(iter);\n  }\n  iterator erase(const_iterator first,\n                 const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return tree_.erase_range(iterator(first), iterator(last)).second;\n  }\n  template <typename K = key_type>\n  size_type erase(const key_arg<K> &key) {\n    auto equal_range = this->equal_range(key);\n    return tree_.erase_range(equal_range.first, equal_range.second).first;\n  }\n\n  // Extract routines.\n  extract_and_get_next_return_type extract_and_get_next(const_iterator position)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // Use Construct instead of Transfer because the rebalancing code will\n    // destroy the slot later.\n    // Note: we rely on erase() taking place after Construct().\n    return {CommonAccess::Construct<node_type>(get_allocator(),\n                                               iterator(position).slot()),\n            erase(position)};\n  }\n  node_type extract(iterator position) {\n    // Use Construct instead of Transfer because the rebalancing code will\n    // destroy the slot later.\n    auto node =\n        CommonAccess::Construct<node_type>(get_allocator(), position.slot());\n    erase(position);\n    return node;\n  }\n  node_type extract(const_iterator position) {\n    return extract(iterator(position));\n  }\n\n  // Utility routines.\n  ABSL_ATTRIBUTE_REINITIALIZES void clear() { tree_.clear(); }\n  void swap(btree_container &other) { tree_.swap(other.tree_); }\n  void verify() const { tree_.verify(); }\n\n  // Size routines.\n  size_type size() const { return tree_.size(); }\n  size_type max_size() const { return tree_.max_size(); }\n  bool empty() const { return tree_.empty(); }\n\n  friend bool operator==(const btree_container &x, const btree_container &y) {\n    if (x.size() != y.size()) return false;\n    return std::equal(x.begin(), x.end(), y.begin());\n  }\n\n  friend bool operator!=(const btree_container &x, const btree_container &y) {\n    return !(x == y);\n  }\n\n  friend bool operator<(const btree_container &x, const btree_container &y) {\n    return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());\n  }\n\n  friend bool operator>(const btree_container &x, const btree_container &y) {\n    return y < x;\n  }\n\n  friend bool operator<=(const btree_container &x, const btree_container &y) {\n    return !(y < x);\n  }\n\n  friend bool operator>=(const btree_container &x, const btree_container &y) {\n    return !(x < y);\n  }\n\n  // The allocator used by the btree.\n  allocator_type get_allocator() const { return tree_.get_allocator(); }\n\n  // The key comparator used by the btree.\n  key_compare key_comp() const { return key_compare(tree_.key_comp()); }\n  value_compare value_comp() const { return tree_.value_comp(); }\n\n  // Support absl::Hash.\n  template <typename State>\n  friend State AbslHashValue(State h, const btree_container &b) {\n    for (const auto &v : b) {\n      h = State::combine(std::move(h), v);\n    }\n    return State::combine(std::move(h),\n                          hash_internal::WeaklyMixedInteger{b.size()});\n  }\n\n protected:\n  friend struct btree_access;\n  Tree tree_;\n};\n\n// A common base class for btree_set and btree_map.\ntemplate <typename Tree>\nclass btree_set_container : public btree_container<Tree> {\n  using super_type = btree_container<Tree>;\n  using params_type = typename Tree::params_type;\n  using init_type = typename params_type::init_type;\n  using is_key_compare_to = typename params_type::is_key_compare_to;\n  friend class BtreeNodePeer;\n\n protected:\n  template <class K>\n  using key_arg = typename super_type::template key_arg<K>;\n\n public:\n  using key_type = typename Tree::key_type;\n  using value_type = typename Tree::value_type;\n  using size_type = typename Tree::size_type;\n  using key_compare = typename Tree::original_key_compare;\n  using allocator_type = typename Tree::allocator_type;\n  using iterator = typename Tree::iterator;\n  using const_iterator = typename Tree::const_iterator;\n  using node_type = typename super_type::node_type;\n  using insert_return_type = InsertReturnType<iterator, node_type>;\n\n  // Inherit constructors.\n  using super_type::super_type;\n  btree_set_container() {}\n\n  // Range constructors.\n  template <class InputIterator>\n  btree_set_container(InputIterator b, InputIterator e,\n                      const key_compare &comp = key_compare(),\n                      const allocator_type &alloc = allocator_type())\n      : super_type(comp, alloc) {\n    insert(b, e);\n  }\n  template <class InputIterator>\n  btree_set_container(InputIterator b, InputIterator e,\n                      const allocator_type &alloc)\n      : btree_set_container(b, e, key_compare(), alloc) {}\n\n  // Initializer list constructors.\n  btree_set_container(std::initializer_list<init_type> init,\n                      const key_compare &comp = key_compare(),\n                      const allocator_type &alloc = allocator_type())\n      : btree_set_container(init.begin(), init.end(), comp, alloc) {}\n  btree_set_container(std::initializer_list<init_type> init,\n                      const allocator_type &alloc)\n      : btree_set_container(init.begin(), init.end(), alloc) {}\n\n  // Insertion routines.\n  std::pair<iterator, bool> insert(const value_type &v)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_.insert_unique(params_type::key(v), v);\n  }\n  std::pair<iterator, bool> insert(value_type &&v)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_.insert_unique(params_type::key(v), std::move(v));\n  }\n  template <typename... Args>\n  std::pair<iterator, bool> emplace(Args &&...args)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // Use a node handle to manage a temp slot.\n    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),\n                                                   std::forward<Args>(args)...);\n    auto *slot = CommonAccess::GetSlot(node);\n    return this->tree_.insert_unique(params_type::key(slot), slot);\n  }\n  iterator insert(const_iterator hint,\n                  const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_\n        .insert_hint_unique(iterator(hint), params_type::key(v), v)\n        .first;\n  }\n  iterator insert(const_iterator hint,\n                  value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_\n        .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))\n        .first;\n  }\n  template <typename... Args>\n  iterator emplace_hint(const_iterator hint,\n                        Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // Use a node handle to manage a temp slot.\n    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),\n                                                   std::forward<Args>(args)...);\n    auto *slot = CommonAccess::GetSlot(node);\n    return this->tree_\n        .insert_hint_unique(iterator(hint), params_type::key(slot), slot)\n        .first;\n  }\n  template <typename InputIterator>\n  void insert(InputIterator b, InputIterator e) {\n    this->tree_.insert_iterator_unique(b, e, 0);\n  }\n  void insert(std::initializer_list<init_type> init) {\n    this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);\n  }\n  insert_return_type insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!node) return {this->end(), false, node_type()};\n    std::pair<iterator, bool> res =\n        this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),\n                                  CommonAccess::GetSlot(node));\n    if (res.second) {\n      CommonAccess::Destroy(&node);\n      return {res.first, true, node_type()};\n    } else {\n      return {res.first, false, std::move(node)};\n    }\n  }\n  iterator insert(const_iterator hint,\n                  node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!node) return this->end();\n    std::pair<iterator, bool> res = this->tree_.insert_hint_unique(\n        iterator(hint), params_type::key(CommonAccess::GetSlot(node)),\n        CommonAccess::GetSlot(node));\n    if (res.second) CommonAccess::Destroy(&node);\n    return res.first;\n  }\n\n  // Node extraction routines.\n  template <typename K = key_type>\n  node_type extract(const key_arg<K> &key) {\n    const std::pair<iterator, bool> lower_and_equal =\n        this->tree_.lower_bound_equal(key);\n    return lower_and_equal.second ? extract(lower_and_equal.first)\n                                  : node_type();\n  }\n  using super_type::extract;\n\n  // Merge routines.\n  // Moves elements from `src` into `this`. If the element already exists in\n  // `this`, it is left unmodified in `src`.\n  template <\n      typename T,\n      typename absl::enable_if_t<\n          absl::conjunction<\n              std::is_same<value_type, typename T::value_type>,\n              std::is_same<allocator_type, typename T::allocator_type>,\n              std::is_same<typename params_type::is_map_container,\n                           typename T::params_type::is_map_container>>::value,\n          int> = 0>\n  void merge(btree_container<T> &src) {  // NOLINT\n    for (auto src_it = src.begin(); src_it != src.end();) {\n      if (insert(std::move(params_type::element(src_it.slot()))).second) {\n        src_it = src.erase(src_it);\n      } else {\n        ++src_it;\n      }\n    }\n  }\n\n  template <\n      typename T,\n      typename absl::enable_if_t<\n          absl::conjunction<\n              std::is_same<value_type, typename T::value_type>,\n              std::is_same<allocator_type, typename T::allocator_type>,\n              std::is_same<typename params_type::is_map_container,\n                           typename T::params_type::is_map_container>>::value,\n          int> = 0>\n  void merge(btree_container<T> &&src) {\n    merge(src);\n  }\n};\n\n// Base class for btree_map.\ntemplate <typename Tree>\nclass btree_map_container : public btree_set_container<Tree> {\n  using super_type = btree_set_container<Tree>;\n  using params_type = typename Tree::params_type;\n  friend class BtreeNodePeer;\n\n private:\n  template <class K>\n  using key_arg = typename super_type::template key_arg<K>;\n\n  // NOTE: The mess here is to shorten the code for the (very repetitive)\n  // function overloads, and to allow the lifetime-bound overloads to dispatch\n  // to the non-lifetime-bound overloads, to ensure there is a single source of\n  // truth for each overload set.\n  //\n  // Enabled if an assignment from the given type would require the\n  // source object to remain alive for the life of the element.\n  //\n  // TODO(b/402804213): Remove these traits and simplify the overloads whenever\n  // we have a better mechanism available to handle lifetime analysis.\n  template <class K, bool Value, typename = void>\n  using LifetimeBoundK =\n      HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<\n                          typename Tree::key_type, K>>;\n  template <class M, bool Value, typename = void>\n  using LifetimeBoundV =\n      HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<\n                          typename Tree::params_type::mapped_type, M>>;\n  template <class K, bool KValue, class M, bool MValue, typename... Dummy>\n  using LifetimeBoundKV =\n      absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,\n                        LifetimeBoundV<M, MValue>>;\n\n public:\n  using key_type = typename Tree::key_type;\n  using mapped_type = typename params_type::mapped_type;\n  using value_type = typename Tree::value_type;\n  using key_compare = typename Tree::original_key_compare;\n  using allocator_type = typename Tree::allocator_type;\n  using iterator = typename Tree::iterator;\n  using const_iterator = typename Tree::const_iterator;\n\n  // Inherit constructors.\n  using super_type::super_type;\n  btree_map_container() {}\n\n  // TODO(b/402804213): Remove these macros whenever we have a better mechanism\n  // available to handle lifetime analysis.\n#define ABSL_INTERNAL_X(Func, Callee, KQual, MQual, KValue, MValue, ...)     \\\n  template <                                                                 \\\n      typename K = key_type, class M,                                        \\\n      ABSL_INTERNAL_IF_##KValue##_NOR_##MValue(                              \\\n          int = (EnableIf<LifetimeBoundKV<K, KValue, M, MValue,              \\\n                                          IfRRef<int KQual>::AddPtr<K>,      \\\n                                          IfRRef<int MQual>::AddPtr<M>>>()), \\\n          ABSL_INTERNAL_SINGLE_ARG(                                          \\\n              int &...,                                                      \\\n              decltype(EnableIf<LifetimeBoundKV<K, KValue, M, MValue>>()) =  \\\n                  0))>                                                       \\\n  decltype(auto) Func(                                                       \\\n      __VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue(              \\\n          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)),                        \\\n      M MQual obj ABSL_INTERNAL_IF_##MValue(                                 \\\n          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)))                        \\\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {                                        \\\n    return ABSL_INTERNAL_IF_##KValue##_OR_##MValue(                          \\\n        (this->template Func<K, M, 0>), Callee)(                             \\\n        __VA_ARGS__ std::forward<decltype(k)>(k),                            \\\n        std::forward<decltype(obj)>(obj));                                   \\\n  }                                                                          \\\n  friend struct std::enable_if<false> /* just to force a semicolon */\n  // Insertion routines.\n  // Note: the nullptr template arguments and extra `const M&` overloads allow\n  // for supporting bitfield arguments.\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  false, false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  false, true);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  true, false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  true, true);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,\n                  false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,\n                  true);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,\n                  false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,\n                  true);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,\n                  false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,\n                  true);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,\n                  false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,\n                  true);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false,\n                  false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,\n                  const &, false, false,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,\n                  const &, false, true,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,\n                  const &, true, false,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,\n                  const &, true, true,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,\n                  false, false, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,\n                  false, true, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,\n                  true, false, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,\n                  true, true, const_iterator(hint) ABSL_INTERNAL_COMMA);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,\n                  false, false, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,\n                  false, true, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,\n                  true, false, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,\n                  true, true, const_iterator(hint) ABSL_INTERNAL_COMMA);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, false,\n                  false, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, false,\n                  true, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, true,\n                  false, const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, true,\n                  true, const_iterator(hint) ABSL_INTERNAL_COMMA);\n#undef ABSL_INTERNAL_X\n\n#define ABSL_INTERNAL_X(Func, Callee, KQual, KValue, ...)                      \\\n  template <                                                                   \\\n      class K = key_type,                                                      \\\n      ABSL_INTERNAL_IF_##KValue(                                               \\\n          class... Args,                                                       \\\n          int = (EnableIf<                                                     \\\n                 LifetimeBoundK<K, KValue, IfRRef<int KQual>::AddPtr<K>>>())), \\\n      ABSL_INTERNAL_IF_##KValue(                                               \\\n          decltype(EnableIf<LifetimeBoundK<                                    \\\n                       K, KValue, IfRRef<int KQual>::AddPtr<K>>>()) = 0,       \\\n          class... Args),                                                      \\\n      std::enable_if_t<!std::is_convertible<K, const_iterator>::value, int> =  \\\n          0>                                                                   \\\n  decltype(auto) Func(                                                         \\\n      __VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue(                \\\n          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)),                          \\\n      Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {                          \\\n    return ABSL_INTERNAL_IF_##KValue((this->template Func<K, 0>), Callee)(     \\\n        __VA_ARGS__ std::forward<decltype(k)>(k),                              \\\n        std::forward<decltype(args)>(args)...);                                \\\n  }                                                                            \\\n  friend struct std::enable_if<false> /* just to force a semicolon */\n  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, const &, false);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, const &, true);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, &&, false);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, &&, true);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, const &, false,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, const &, true,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, &&, false,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, &&, true,\n                  const_iterator(hint) ABSL_INTERNAL_COMMA);\n#undef ABSL_INTERNAL_X\n\n  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>()>\n  mapped_type &operator[](const key_arg<K> &k) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return try_emplace(k).first->second;\n  }\n  template <class K = key_type, int &..., EnableIf<LifetimeBoundK<K, true>> = 0>\n  mapped_type &operator[](\n      const key_arg<K> &k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template operator[]<K, 0>(k);\n  }\n  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>()>\n  mapped_type &operator[](key_arg<K> &&k) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return try_emplace(std::forward<key_arg<K>>(k)).first->second;\n  }\n  template <class K = key_type, int &..., EnableIf<LifetimeBoundK<K, true>> = 0>\n  mapped_type &operator[](key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(\n      this)) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template operator[]<K, 0>(std::forward<key_arg<K>>(k));\n  }\n\n  template <typename K = key_type>\n  mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto it = this->find(key);\n    if (it == this->end()) ThrowStdOutOfRange(\"absl::btree_map::at\");\n    return it->second;\n  }\n  template <typename K = key_type>\n  const mapped_type &at(const key_arg<K> &key) const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto it = this->find(key);\n    if (it == this->end()) ThrowStdOutOfRange(\"absl::btree_map::at\");\n    return it->second;\n  }\n\n private:\n  // Note: when we call `std::forward<M>(obj)` twice, it's safe because\n  // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when\n  // `ret.second` is false.\n  template <class K, class M>\n  std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {\n    const std::pair<iterator, bool> ret =\n        this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));\n    if (!ret.second) {\n      // NOLINTNEXTLINE(bugprone-use-after-move)\n      ret.first->second = std::forward<M>(obj);\n    }\n    return ret;\n  }\n  template <class K, class M>\n  iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {\n    const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(\n        iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));\n    if (!ret.second) {\n      // NOLINTNEXTLINE(bugprone-use-after-move)\n      ret.first->second = std::forward<M>(obj);\n    }\n    return ret.first;\n  }\n\n  template <class K, class... Args>\n  std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {\n    return this->tree_.insert_unique(\n        // NOLINTNEXTLINE(bugprone-use-after-move)\n        k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),\n        std::forward_as_tuple(std::forward<Args>(args)...));\n  }\n  template <class K, class... Args>\n  iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {\n    return this->tree_\n        .insert_hint_unique(iterator(hint),\n                            // NOLINTNEXTLINE(bugprone-use-after-move)\n                            k, std::piecewise_construct,\n                            std::forward_as_tuple(std::forward<K>(k)),\n                            std::forward_as_tuple(std::forward<Args>(args)...))\n        .first;\n  }\n};\n\n// A common base class for btree_multiset and btree_multimap.\ntemplate <typename Tree>\nclass btree_multiset_container : public btree_container<Tree> {\n  using super_type = btree_container<Tree>;\n  using params_type = typename Tree::params_type;\n  using init_type = typename params_type::init_type;\n  using is_key_compare_to = typename params_type::is_key_compare_to;\n  friend class BtreeNodePeer;\n\n  template <class K>\n  using key_arg = typename super_type::template key_arg<K>;\n\n public:\n  using key_type = typename Tree::key_type;\n  using value_type = typename Tree::value_type;\n  using size_type = typename Tree::size_type;\n  using key_compare = typename Tree::original_key_compare;\n  using allocator_type = typename Tree::allocator_type;\n  using iterator = typename Tree::iterator;\n  using const_iterator = typename Tree::const_iterator;\n  using node_type = typename super_type::node_type;\n\n  // Inherit constructors.\n  using super_type::super_type;\n  btree_multiset_container() {}\n\n  // Range constructors.\n  template <class InputIterator>\n  btree_multiset_container(InputIterator b, InputIterator e,\n                           const key_compare &comp = key_compare(),\n                           const allocator_type &alloc = allocator_type())\n      : super_type(comp, alloc) {\n    insert(b, e);\n  }\n  template <class InputIterator>\n  btree_multiset_container(InputIterator b, InputIterator e,\n                           const allocator_type &alloc)\n      : btree_multiset_container(b, e, key_compare(), alloc) {}\n\n  // Initializer list constructors.\n  btree_multiset_container(std::initializer_list<init_type> init,\n                           const key_compare &comp = key_compare(),\n                           const allocator_type &alloc = allocator_type())\n      : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}\n  btree_multiset_container(std::initializer_list<init_type> init,\n                           const allocator_type &alloc)\n      : btree_multiset_container(init.begin(), init.end(), alloc) {}\n\n  // Insertion routines.\n  iterator insert(const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_.insert_multi(v);\n  }\n  iterator insert(value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_.insert_multi(std::move(v));\n  }\n  iterator insert(const_iterator hint,\n                  const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_.insert_hint_multi(iterator(hint), v);\n  }\n  iterator insert(const_iterator hint,\n                  value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->tree_.insert_hint_multi(iterator(hint), std::move(v));\n  }\n  template <typename InputIterator>\n  void insert(InputIterator b, InputIterator e) {\n    this->tree_.insert_iterator_multi(b, e);\n  }\n  void insert(std::initializer_list<init_type> init) {\n    this->tree_.insert_iterator_multi(init.begin(), init.end());\n  }\n  template <typename... Args>\n  iterator emplace(Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // Use a node handle to manage a temp slot.\n    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),\n                                                   std::forward<Args>(args)...);\n    return this->tree_.insert_multi(CommonAccess::GetSlot(node));\n  }\n  template <typename... Args>\n  iterator emplace_hint(const_iterator hint,\n                        Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // Use a node handle to manage a temp slot.\n    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),\n                                                   std::forward<Args>(args)...);\n    return this->tree_.insert_hint_multi(iterator(hint),\n                                         CommonAccess::GetSlot(node));\n  }\n  iterator insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!node) return this->end();\n    iterator res =\n        this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),\n                                 CommonAccess::GetSlot(node));\n    CommonAccess::Destroy(&node);\n    return res;\n  }\n  iterator insert(const_iterator hint,\n                  node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!node) return this->end();\n    iterator res = this->tree_.insert_hint_multi(\n        iterator(hint),\n        std::move(params_type::element(CommonAccess::GetSlot(node))));\n    CommonAccess::Destroy(&node);\n    return res;\n  }\n\n  // Node extraction routines.\n  template <typename K = key_type>\n  node_type extract(const key_arg<K> &key) {\n    const std::pair<iterator, bool> lower_and_equal =\n        this->tree_.lower_bound_equal(key);\n    return lower_and_equal.second ? extract(lower_and_equal.first)\n                                  : node_type();\n  }\n  using super_type::extract;\n\n  // Merge routines.\n  // Moves all elements from `src` into `this`.\n  template <\n      typename T,\n      typename absl::enable_if_t<\n          absl::conjunction<\n              std::is_same<value_type, typename T::value_type>,\n              std::is_same<allocator_type, typename T::allocator_type>,\n              std::is_same<typename params_type::is_map_container,\n                           typename T::params_type::is_map_container>>::value,\n          int> = 0>\n  void merge(btree_container<T> &src) {  // NOLINT\n    for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {\n      insert(std::move(params_type::element(src_it.slot())));\n    }\n    src.clear();\n  }\n\n  template <\n      typename T,\n      typename absl::enable_if_t<\n          absl::conjunction<\n              std::is_same<value_type, typename T::value_type>,\n              std::is_same<allocator_type, typename T::allocator_type>,\n              std::is_same<typename params_type::is_map_container,\n                           typename T::params_type::is_map_container>>::value,\n          int> = 0>\n  void merge(btree_container<T> &&src) {\n    merge(src);\n  }\n};\n\n// A base class for btree_multimap.\ntemplate <typename Tree>\nclass btree_multimap_container : public btree_multiset_container<Tree> {\n  using super_type = btree_multiset_container<Tree>;\n  using params_type = typename Tree::params_type;\n  friend class BtreeNodePeer;\n\n public:\n  using mapped_type = typename params_type::mapped_type;\n\n  // Inherit constructors.\n  using super_type::super_type;\n  btree_multimap_container() {}\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_\n"
  },
  {
    "path": "absl/container/internal/chunked_queue.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_CHUNKED_QUEUE_H_\n#define ABSL_CONTAINER_INTERNAL_CHUNKED_QUEUE_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <initializer_list>\n#include <iterator>\n#include <memory>\n#include <new>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/internal/layout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// ChunkedQueueBlock defines a node in a forward list of uninitialized storage\n// of size T's. The user is responsible for constructing and destroying T's in\n// said storage.\n//\n// ChunkedQueueBlock::New(size) returns said node, with at least size_hint T's\n// of uninitialized storage.\ntemplate <typename T, typename Allocator>\nclass ChunkedQueueBlock {\n private:\n  using ChunkedQueueBlockAllocator = typename std::allocator_traits<\n      Allocator>::template rebind_alloc<ChunkedQueueBlock>;\n  using ByteAllocator =\n      typename std::allocator_traits<Allocator>::template rebind_alloc<char>;\n\n public:\n  // NB, instances of this must not be created or destroyed directly, only via\n  // the New() and Delete() methods.  (This notionally-private constructor is\n  // public only to allow access from allocator types used by New().)\n  explicit ChunkedQueueBlock(size_t size)\n      : next_(nullptr), limit_(start() + size) {}\n\n  // Must be deleted by ChunkedQueueBlock::Delete.\n  static ChunkedQueueBlock* New(size_t size_hint, Allocator* alloc) {  // NOLINT\n    ABSL_ASSERT(size_hint >= size_t{1});\n    size_t allocation_bytes = AllocSize(size_hint);\n    void* mem;\n    std::tie(mem, allocation_bytes) = Allocate(allocation_bytes, alloc);\n    const size_t element_count =\n        (allocation_bytes - start_offset()) / sizeof(T);\n    ChunkedQueueBlock* as_block = static_cast<ChunkedQueueBlock*>(mem);\n    ChunkedQueueBlockAllocator block_alloc(*alloc);\n    std::allocator_traits<ChunkedQueueBlockAllocator>::construct(\n        block_alloc, as_block, element_count);\n    return as_block;\n  }\n\n  static void Delete(ChunkedQueueBlock* ptr, Allocator* alloc) {\n    const size_t allocation_bytes = AllocSize(ptr->size());\n    ChunkedQueueBlockAllocator block_alloc(*alloc);\n    std::allocator_traits<ChunkedQueueBlockAllocator>::destroy(block_alloc,\n                                                               ptr);\n    if constexpr (std::is_same_v<ByteAllocator, std::allocator<char>>) {\n#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__\n      if (alignment() > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {\n        ::operator delete(ptr\n#ifdef __cpp_sized_deallocation\n                          ,\n                          allocation_bytes\n#endif\n                          ,\n                          std::align_val_t(alignment()));\n        return;\n      }\n#endif\n      ::operator delete(ptr);\n    } else {\n      void* mem = ptr;\n      ByteAllocator byte_alloc(*alloc);\n      std::allocator_traits<ByteAllocator>::deallocate(\n          byte_alloc, static_cast<char*>(mem), allocation_bytes);\n    }\n  }\n\n  ChunkedQueueBlock* next() const { return next_; }\n  void set_next(ChunkedQueueBlock* next) { next_ = next; }\n  T* start() {\n    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) +\n                                start_offset());\n  }\n  T* limit() { return limit_; }\n  size_t size() { return limit() - start(); }\n\n  static constexpr size_t block_size_from_bytes(size_t bytes) {\n    return bytes <= static_cast<size_t>(start_offset())\n               ? size_t{1}\n               : elements_in_bytes(bytes - start_offset());\n  }\n\n private:\n  ChunkedQueueBlock(const ChunkedQueueBlock&) = delete;\n  ChunkedQueueBlock& operator=(const ChunkedQueueBlock&) = delete;\n\n  // The byte size to allocate to ensure space for `min_element_count` elements.\n  static constexpr size_t AllocSize(size_t min_element_count) {\n    return absl::container_internal::Layout<ChunkedQueueBlock, T>(\n               1, min_element_count)\n        .AllocSize();\n  }\n\n  static constexpr ptrdiff_t start_offset() {\n    return absl::container_internal::Layout<ChunkedQueueBlock, T>(1, 1)\n        .template Offset<1>();\n  }\n\n  static constexpr size_t alignment() {\n    return absl::container_internal::Layout<ChunkedQueueBlock, T>(1, 1)\n        .Alignment();\n  }\n\n  static constexpr size_t elements_in_bytes(size_t bytes) {\n    return (bytes + sizeof(T) - 1) / sizeof(T);\n  }\n\n  static std::pair<void*, size_t> Allocate(size_t allocation_bytes,\n                                           Allocator* alloc) {\n    // If we're using the default allocator, then we can use new.\n    void* mem;\n    if constexpr (std::is_same_v<ByteAllocator, std::allocator<char>>) {\n      // Older GCC versions have an unused variable warning on `alloc` inside\n      // this constexpr branch.\n      static_cast<void>(alloc);\n#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__\n      if (alignment() > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {\n        // Align the allocation to respect alignof(T).\n        mem = ::operator new(allocation_bytes, std::align_val_t(alignment()));\n        return {mem, allocation_bytes};\n      }\n#endif\n      mem = ::operator new(allocation_bytes);\n    } else {\n      ByteAllocator byte_alloc(*alloc);\n      mem = std::allocator_traits<ByteAllocator>::allocate(byte_alloc,\n                                                           allocation_bytes);\n    }\n    return {mem, allocation_bytes};\n  }\n\n  ChunkedQueueBlock* next_;\n  T* limit_;\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_CHUNKED_QUEUE_H_\n"
  },
  {
    "path": "absl/container/internal/common.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_COMMON_H_\n#define ABSL_CONTAINER_INTERNAL_COMMON_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <optional>\n#include <tuple>\n#include <type_traits>\n\n#include \"absl/meta/type_traits.h\"\n#include \"absl/types/optional.h\"\n\n// TODO(b/402804213): Clean up these macros when no longer needed.\n#define ABSL_INTERNAL_SINGLE_ARG(...) __VA_ARGS__\n\n#define ABSL_INTERNAL_IF_true(if_satisfied, ...) if_satisfied\n#define ABSL_INTERNAL_IF_false(if_satisfied, ...) __VA_ARGS__\n\n#define ABSL_INTERNAL_IF_true_AND_true ABSL_INTERNAL_IF_true\n#define ABSL_INTERNAL_IF_false_AND_false ABSL_INTERNAL_IF_false\n#define ABSL_INTERNAL_IF_true_AND_false ABSL_INTERNAL_IF_false_AND_false\n#define ABSL_INTERNAL_IF_false_AND_true ABSL_INTERNAL_IF_false_AND_false\n\n#define ABSL_INTERNAL_IF_true_OR_true ABSL_INTERNAL_IF_true\n#define ABSL_INTERNAL_IF_false_OR_false ABSL_INTERNAL_IF_false\n#define ABSL_INTERNAL_IF_true_OR_false ABSL_INTERNAL_IF_true_OR_true\n#define ABSL_INTERNAL_IF_false_OR_true ABSL_INTERNAL_IF_true_OR_true\n\n#define ABSL_INTERNAL_IF_true_NOR_true ABSL_INTERNAL_IF_false_AND_false\n#define ABSL_INTERNAL_IF_false_NOR_false ABSL_INTERNAL_IF_true_AND_true\n#define ABSL_INTERNAL_IF_true_NOR_false ABSL_INTERNAL_IF_false_AND_true\n#define ABSL_INTERNAL_IF_false_NOR_true ABSL_INTERNAL_IF_true_AND_false\n\n#define ABSL_INTERNAL_COMMA ,\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// TODO(b/402804213): Clean up these traits when no longer needed or\n// deduplicate them with absl::functional_internal::EnableIf.\ntemplate <class Cond>\nusing EnableIf = std::enable_if_t<Cond::value, int>;\n\ntemplate <bool Value, class T>\nusing HasValue = std::conditional_t<Value, T, absl::negation<T>>;\n\ntemplate <class T>\nstruct IfRRef {\n  template <class Other>\n  using AddPtr = Other;\n};\n\ntemplate <class T>\nstruct IfRRef<T&&> {\n  template <class Other>\n  using AddPtr = Other*;\n};\n\ntemplate <class, class = void>\nstruct IsTransparent : std::false_type {};\ntemplate <class T>\nstruct IsTransparent<T, absl::void_t<typename T::is_transparent>>\n    : std::true_type {};\n\ntemplate <bool is_transparent>\nstruct KeyArg {\n  // Transparent. Forward `K`.\n  template <typename K, typename key_type>\n  using type = K;\n};\n\ntemplate <>\nstruct KeyArg<false> {\n  // Not transparent. Always use `key_type`.\n  template <typename K, typename key_type>\n  using type = key_type;\n};\n\n// The node_handle concept from C++17.\n// We specialize node_handle for sets and maps. node_handle_base holds the\n// common API of both.\ntemplate <typename PolicyTraits, typename Alloc>\nclass node_handle_base {\n protected:\n  using slot_type = typename PolicyTraits::slot_type;\n\n public:\n  using allocator_type = Alloc;\n\n  constexpr node_handle_base() = default;\n  node_handle_base(node_handle_base&& other) noexcept {\n    *this = std::move(other);\n  }\n  ~node_handle_base() { destroy(); }\n  node_handle_base& operator=(node_handle_base&& other) noexcept {\n    destroy();\n    if (!other.empty()) {\n      alloc_ = other.alloc_;\n      PolicyTraits::transfer(alloc(), slot(), other.slot());\n      other.reset();\n    }\n    return *this;\n  }\n\n  bool empty() const noexcept { return !alloc_; }\n  explicit operator bool() const noexcept { return !empty(); }\n  allocator_type get_allocator() const { return *alloc_; }\n\n protected:\n  friend struct CommonAccess;\n\n  struct transfer_tag_t {};\n  node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s)\n      : alloc_(a) {\n    PolicyTraits::transfer(alloc(), slot(), s);\n  }\n\n  struct construct_tag_t {};\n  template <typename... Args>\n  node_handle_base(construct_tag_t, const allocator_type& a, Args&&... args)\n      : alloc_(a) {\n    PolicyTraits::construct(alloc(), slot(), std::forward<Args>(args)...);\n  }\n\n  void destroy() {\n    if (!empty()) {\n      PolicyTraits::destroy(alloc(), slot());\n      reset();\n    }\n  }\n\n  void reset() {\n    assert(alloc_.has_value());\n    alloc_ = std::nullopt;\n  }\n\n  slot_type* slot() const {\n    assert(!empty());\n    return reinterpret_cast<slot_type*>(std::addressof(slot_space_));\n  }\n  allocator_type* alloc() { return std::addressof(*alloc_); }\n\n private:\n  std::optional<allocator_type> alloc_ = {};\n  alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {};\n};\n\n// For sets.\ntemplate <typename Policy, typename PolicyTraits, typename Alloc,\n          typename = void>\nclass node_handle : public node_handle_base<PolicyTraits, Alloc> {\n  using Base = node_handle_base<PolicyTraits, Alloc>;\n\n public:\n  using value_type = typename PolicyTraits::value_type;\n\n  constexpr node_handle() {}\n\n  value_type& value() const { return PolicyTraits::element(this->slot()); }\n\n private:\n  friend struct CommonAccess;\n\n  using Base::Base;\n};\n\n// For maps.\ntemplate <typename Policy, typename PolicyTraits, typename Alloc>\nclass node_handle<Policy, PolicyTraits, Alloc,\n                  absl::void_t<typename Policy::mapped_type>>\n    : public node_handle_base<PolicyTraits, Alloc> {\n  using Base = node_handle_base<PolicyTraits, Alloc>;\n  using slot_type = typename PolicyTraits::slot_type;\n\n public:\n  using key_type = typename Policy::key_type;\n  using mapped_type = typename Policy::mapped_type;\n\n  constexpr node_handle() {}\n\n  // When C++17 is available, we can use std::launder to provide mutable\n  // access to the key. Otherwise, we provide const access.\n  auto key() const\n      -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {\n    return PolicyTraits::mutable_key(this->slot());\n  }\n\n  mapped_type& mapped() const {\n    return PolicyTraits::value(&PolicyTraits::element(this->slot()));\n  }\n\n private:\n  friend struct CommonAccess;\n\n  using Base::Base;\n};\n\n// Provide access to non-public node-handle functions.\nstruct CommonAccess {\n  template <typename Node>\n  static auto GetSlot(const Node& node) -> decltype(node.slot()) {\n    return node.slot();\n  }\n\n  template <typename Node>\n  static void Destroy(Node* node) {\n    node->destroy();\n  }\n\n  template <typename Node>\n  static void Reset(Node* node) {\n    node->reset();\n  }\n\n  template <typename T, typename... Args>\n  static T Transfer(Args&&... args) {\n    return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...);\n  }\n\n  template <typename T, typename... Args>\n  static T Construct(Args&&... args) {\n    return T(typename T::construct_tag_t{}, std::forward<Args>(args)...);\n  }\n};\n\n// Implement the insert_return_type<> concept of C++17.\ntemplate <class Iterator, class NodeType>\nstruct InsertReturnType {\n  Iterator position;\n  bool inserted;\n  NodeType node;\n};\n\n// Utilities to strip redundant template parameters from the underlying\n// implementation types.\n// We use a variadic pack (ie Params...) to specify required prefix of types for\n// non-default types, and then we use GetFromListOr to select the provided types\n// or the default ones otherwise.\n//\n// These default types do not contribute information for debugging and just\n// bloat the binary.\n// Removing the redundant tail types reduces mangled names and stringified\n// function names like __PRETTY_FUNCTION__.\n//\n// How to use:\n//  1. Define a template with `typename ...Params`\n//  2. Instantiate it via `ApplyWithoutDefaultSuffix<>` to only pass the minimal\n//     set of types.\n//  3. Inside the template use `GetFromListOr` to map back from the existing\n//     `Params` list to the actual types, filling the gaps when types are\n//     missing.\n\ntemplate <typename Or, size_t N, typename... Params>\nusing GetFromListOr = std::tuple_element_t<(std::min)(N, sizeof...(Params)),\n                                           std::tuple<Params..., Or>>;\n\ntemplate <typename... T>\nstruct TypeList {\n  template <template <typename...> class Template>\n  using Apply = Template<T...>;\n};\n\n// Evaluate to `Template<TPrefix...>` where the last type in the list (if any)\n// is different from the corresponding one in the default list.\n// Eg\n//   ApplyWithoutDefaultSuffix<Template, TypeList<a, b, c>, TypeList<a, X, c>>\n// evaluates to\n//   Template<a, X>\ntemplate <template <typename...> class Template, typename D, typename T,\n          typename L = TypeList<>, typename = void>\nstruct ApplyWithoutDefaultSuffix {\n  using type = typename L::template Apply<Template>;\n};\ntemplate <template <typename...> class Template, typename D, typename... Ds,\n          typename T, typename... Ts, typename... L>\nstruct ApplyWithoutDefaultSuffix<\n    Template, TypeList<D, Ds...>, TypeList<T, Ts...>, TypeList<L...>,\n    std::enable_if_t<!std::is_same_v<TypeList<D, Ds...>, TypeList<T, Ts...>>>>\n    : ApplyWithoutDefaultSuffix<Template, TypeList<Ds...>, TypeList<Ts...>,\n                       TypeList<L..., T>> {};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_COMMON_H_\n"
  },
  {
    "path": "absl/container/internal/common_policy_traits.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_\n#define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_\n\n#include <cstddef>\n#include <cstring>\n#include <memory>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class Policy, class = void>\nstruct policy_trait_element_is_owner : std::false_type {};\n\ntemplate <class Policy>\nstruct policy_trait_element_is_owner<\n    Policy,\n    std::enable_if_t<!std::is_void<typename Policy::element_is_owner>::value>>\n    : Policy::element_is_owner {};\n\n// Defines how slots are initialized/destroyed/moved.\ntemplate <class Policy, class = void>\nstruct common_policy_traits {\n  // The actual object stored in the container.\n  using slot_type = typename Policy::slot_type;\n  using reference = decltype(Policy::element(std::declval<slot_type*>()));\n  using value_type = typename std::remove_reference<reference>::type;\n\n  // PRECONDITION: `slot` is UNINITIALIZED\n  // POSTCONDITION: `slot` is INITIALIZED\n  template <class Alloc, class... Args>\n  static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {\n    Policy::construct(alloc, slot, std::forward<Args>(args)...);\n  }\n\n  // PRECONDITION: `slot` is INITIALIZED\n  // POSTCONDITION: `slot` is UNINITIALIZED\n  // Returns std::true_type in case destroy is trivial.\n  template <class Alloc>\n  static auto destroy(Alloc* alloc, slot_type* slot) {\n    return Policy::destroy(alloc, slot);\n  }\n\n  // Transfers the `old_slot` to `new_slot`. Any memory allocated by the\n  // allocator inside `old_slot` to `new_slot` can be transferred.\n  //\n  // OPTIONAL: defaults to:\n  //\n  //     clone(new_slot, std::move(*old_slot));\n  //     destroy(old_slot);\n  //\n  // PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED\n  // POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is\n  //                UNINITIALIZED\n  template <class Alloc>\n  static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {\n    transfer_impl(alloc, new_slot, old_slot, Rank2{});\n  }\n\n  // PRECONDITION: `slot` is INITIALIZED\n  // POSTCONDITION: `slot` is INITIALIZED\n  // Note: we use remove_const_t so that the two overloads have different args\n  // in the case of sets with explicitly const value_types.\n  template <class P = Policy>\n  static auto element(absl::remove_const_t<slot_type>* slot)\n      -> decltype(P::element(slot)) {\n    return P::element(slot);\n  }\n  template <class P = Policy>\n  static auto element(const slot_type* slot) -> decltype(P::element(slot)) {\n    return P::element(slot);\n  }\n\n  static constexpr bool transfer_uses_memcpy() {\n    return std::is_same<decltype(transfer_impl<std::allocator<char>>(\n                            nullptr, nullptr, nullptr, Rank2{})),\n                        std::true_type>::value;\n  }\n\n  // Returns true if destroy is trivial and can be omitted.\n  template <class Alloc>\n  static constexpr bool destroy_is_trivial() {\n    return std::is_same<decltype(destroy<Alloc>(nullptr, nullptr)),\n                        std::true_type>::value;\n  }\n\n private:\n  // Use go/ranked-overloads for dispatching.\n  struct Rank0 {};\n  struct Rank1 : Rank0 {};\n  struct Rank2 : Rank1 {};\n\n  // Use auto -> decltype as an enabler.\n  // P::transfer returns std::true_type if transfer uses memcpy (e.g. in\n  // node_slot_policy).\n  template <class Alloc, class P = Policy>\n  static auto transfer_impl(Alloc* alloc, slot_type* new_slot,\n                            slot_type* old_slot,\n                            Rank2) -> decltype(P::transfer(alloc, new_slot,\n                                                           old_slot)) {\n    return P::transfer(alloc, new_slot, old_slot);\n  }\n\n  // This overload returns true_type for the trait below.\n  // The conditional_t is to make the enabler type dependent.\n  template <class Alloc,\n            typename = std::enable_if_t<absl::is_trivially_relocatable<\n                std::conditional_t<false, Alloc, value_type>>::value>>\n  static std::true_type transfer_impl(Alloc*, slot_type* new_slot,\n                                      slot_type* old_slot, Rank1) {\n    // TODO(b/247130232): remove casts after fixing warnings.\n    // TODO(b/251814870): remove casts after fixing warnings.\n    std::memcpy(\n        static_cast<void*>(std::launder(\n            const_cast<std::remove_const_t<value_type>*>(&element(new_slot)))),\n        static_cast<const void*>(&element(old_slot)), sizeof(value_type));\n    return {};\n  }\n\n  template <class Alloc>\n  static void transfer_impl(Alloc* alloc, slot_type* new_slot,\n                            slot_type* old_slot, Rank0) {\n    construct(alloc, new_slot, std::move(element(old_slot)));\n    destroy(alloc, old_slot);\n  }\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_\n"
  },
  {
    "path": "absl/container/internal/common_policy_traits_test.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/common_policy_traits.h\"\n\n#include <functional>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::MockFunction;\nusing ::testing::AnyNumber;\nusing ::testing::ReturnRef;\n\nusing Slot = int;\n\nstruct PolicyWithoutOptionalOps {\n  using slot_type = Slot;\n  using key_type = Slot;\n  using init_type = Slot;\n\n  struct PolicyFunctions {\n    std::function<void(void*, Slot*, Slot)> construct;\n    std::function<void(void*, Slot*)> destroy;\n    std::function<Slot&(Slot*)> element;\n  };\n\n  static PolicyFunctions* functions() {\n    static PolicyFunctions* functions = new PolicyFunctions();\n    return functions;\n  }\n\n  static void construct(void* a, Slot* b, Slot c) {\n    functions()->construct(a, b, c);\n  }\n  static void destroy(void* a, Slot* b) { functions()->destroy(a, b); }\n  static Slot& element(Slot* b) { return functions()->element(b); }\n};\n\nstruct PolicyWithOptionalOps : PolicyWithoutOptionalOps {\n  struct TransferFunctions {\n    std::function<void(void*, Slot*, Slot*)> transfer;\n  };\n\n  static TransferFunctions* transfer_fn() {\n    static TransferFunctions* transfer_fn = new TransferFunctions();\n    return transfer_fn;\n  }\n  static void transfer(void* a, Slot* b, Slot* c) {\n    transfer_fn()->transfer(a, b, c);\n  }\n};\n\nstruct PolicyWithMemcpyTransferAndTrivialDestroy : PolicyWithoutOptionalOps {\n  static std::true_type transfer(void*, Slot*, Slot*) { return {}; }\n  static std::true_type destroy(void*, Slot*) { return {}; }\n};\n\nstruct Test : ::testing::Test {\n  Test() {\n    PolicyWithoutOptionalOps::functions()->construct = [&](void* a1, Slot* a2,\n                                                           Slot a3) {\n      construct.Call(a1, a2, std::move(a3));\n    };\n    PolicyWithoutOptionalOps::functions()->destroy = [&](void* a1, Slot* a2) {\n      destroy.Call(a1, a2);\n    };\n\n    PolicyWithoutOptionalOps::functions()->element = [&](Slot* a1) -> Slot& {\n      return element.Call(a1);\n    };\n\n    PolicyWithOptionalOps::transfer_fn()->transfer =\n        [&](void* a1, Slot* a2, Slot* a3) { return transfer.Call(a1, a2, a3); };\n  }\n\n  std::allocator<Slot> alloc;\n  int a = 53;\n\n  MockFunction<void(void*, Slot*, Slot)> construct;\n  MockFunction<void(void*, Slot*)> destroy;\n\n  MockFunction<Slot&(Slot*)> element;\n\n  MockFunction<void(void*, Slot*, Slot*)> transfer;\n};\n\nTEST_F(Test, construct) {\n  EXPECT_CALL(construct, Call(&alloc, &a, 53));\n  common_policy_traits<PolicyWithoutOptionalOps>::construct(&alloc, &a, 53);\n}\n\nTEST_F(Test, destroy) {\n  EXPECT_CALL(destroy, Call(&alloc, &a));\n  common_policy_traits<PolicyWithoutOptionalOps>::destroy(&alloc, &a);\n}\n\nTEST_F(Test, element) {\n  int b = 0;\n  EXPECT_CALL(element, Call(&a)).WillOnce(ReturnRef(b));\n  EXPECT_EQ(&b, &common_policy_traits<PolicyWithoutOptionalOps>::element(&a));\n}\n\nTEST_F(Test, without_transfer) {\n  int b = 42;\n  EXPECT_CALL(element, Call(&a)).Times(AnyNumber()).WillOnce(ReturnRef(a));\n  EXPECT_CALL(element, Call(&b)).WillOnce(ReturnRef(b));\n  EXPECT_CALL(construct, Call(&alloc, &a, b)).Times(AnyNumber());\n  EXPECT_CALL(destroy, Call(&alloc, &b)).Times(AnyNumber());\n  common_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b);\n}\n\nTEST_F(Test, with_transfer) {\n  int b = 42;\n  EXPECT_CALL(transfer, Call(&alloc, &a, &b));\n  common_policy_traits<PolicyWithOptionalOps>::transfer(&alloc, &a, &b);\n}\n\nTEST(TransferUsesMemcpy, Basic) {\n  EXPECT_FALSE(\n      common_policy_traits<PolicyWithOptionalOps>::transfer_uses_memcpy());\n  EXPECT_TRUE(\n      common_policy_traits<\n          PolicyWithMemcpyTransferAndTrivialDestroy>::transfer_uses_memcpy());\n}\n\nTEST(DestroyIsTrivial, Basic) {\n  EXPECT_FALSE(common_policy_traits<PolicyWithOptionalOps>::destroy_is_trivial<\n               std::allocator<char>>());\n  EXPECT_TRUE(common_policy_traits<PolicyWithMemcpyTransferAndTrivialDestroy>::\n                  destroy_is_trivial<std::allocator<char>>());\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/compressed_tuple.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Helper class to perform the Empty Base Optimization.\n// Ts can contain classes and non-classes, empty or not. For the ones that\n// are empty classes, we perform the optimization. If all types in Ts are empty\n// classes, then CompressedTuple<Ts...> is itself an empty class.\n//\n// To access the members, use member get<N>() function.\n//\n// Eg:\n//   absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,\n//                                                                    t3);\n//   assert(value.get<0>() == 7);\n//   T1& t1 = value.get<1>();\n//   const T2& t2 = value.get<2>();\n//   ...\n//\n// https://en.cppreference.com/w/cpp/language/ebo\n\n#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_\n#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_\n\n#include <initializer_list>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/utility/utility.h\"\n\n#if defined(_MSC_VER) && !defined(__NVCC__)\n// We need to mark these classes with this declspec to ensure that\n// CompressedTuple happens.\n#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)\n#else\n#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <typename... Ts>\nclass CompressedTuple;\n\nnamespace internal_compressed_tuple {\n\ntemplate <typename D, size_t I>\nstruct Elem;\ntemplate <typename... B, size_t I>\nstruct Elem<CompressedTuple<B...>, I>\n    : std::tuple_element<I, std::tuple<B...>> {};\ntemplate <typename D, size_t I>\nusing ElemT = typename Elem<D, I>::type;\n\n\ntemplate <typename T>\nconstexpr bool ShouldUseBase() {\n  return std::is_class<T>::value && std::is_empty<T>::value &&\n         !std::is_final<T>::value;\n}\n\n// Tag type used to disambiguate Storage types for different CompresseedTuples.\n// Without it, CompressedTuple<T, CompressedTuple<T>> would inherit from\n// Storage<T, 0> twice.\ntemplate <typename... Ts>\nstruct StorageTag;\n\n// The storage class provides two specializations:\n//  - For empty classes, it stores T as a base class.\n//  - For everything else, it stores T as a member.\n// Tag should be set to StorageTag<Ts...>.\ntemplate <typename T, size_t I, typename Tag, bool UseBase = ShouldUseBase<T>()>\nstruct Storage {\n  T value;\n  constexpr Storage() = default;\n  template <typename V>\n  explicit constexpr Storage(absl::in_place_t, V&& v)\n      : value(std::forward<V>(v)) {}\n  constexpr const T& get() const& { return value; }\n  constexpr T& get() & { return value; }\n  constexpr const T&& get() const&& { return std::move(*this).value; }\n  constexpr T&& get() && { return std::move(*this).value; }\n};\n\ntemplate <typename T, size_t I, typename Tag>\nstruct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, Tag, true> : T {\n  constexpr Storage() = default;\n\n  template <typename V>\n  explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward<V>(v)) {}\n\n  constexpr const T& get() const& { return *this; }\n  constexpr T& get() & { return *this; }\n  constexpr const T&& get() const&& { return std::move(*this); }\n  constexpr T&& get() && { return std::move(*this); }\n};\n\ntemplate <typename D, typename I, bool ShouldAnyUseBase>\nstruct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;\n\ntemplate <typename... Ts, size_t... I, bool ShouldAnyUseBase>\nstruct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC\n    CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>,\n                        ShouldAnyUseBase>\n    // We use the dummy identity function through std::integral_constant to\n    // convince MSVC of accepting and expanding I in that context. Without it\n    // you would get:\n    //   error C3548: 'I': parameter pack cannot be used in this context\n    : Storage<Ts, std::integral_constant<size_t, I>::value,\n              StorageTag<Ts...>>... {\n  constexpr CompressedTupleImpl() = default;\n  template <typename... Vs>\n  explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)\n      : Storage<Ts, I, StorageTag<Ts...>>(absl::in_place,\n                                          std::forward<Vs>(args))... {}\n  friend CompressedTuple<Ts...>;\n};\n\ntemplate <typename... Ts, size_t... I>\nstruct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC\n    CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>,\n                        false>\n    // We use the dummy identity function as above...\n    : Storage<Ts, std::integral_constant<size_t, I>::value, StorageTag<Ts...>,\n              false>... {\n  constexpr CompressedTupleImpl() = default;\n  template <typename... Vs>\n  explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)\n      : Storage<Ts, I, StorageTag<Ts...>, false>(absl::in_place,\n                                                 std::forward<Vs>(args))... {}\n  friend CompressedTuple<Ts...>;\n};\n\nstd::false_type Or(std::initializer_list<std::false_type>);\nstd::true_type Or(std::initializer_list<bool>);\n\n// MSVC requires this to be done separately rather than within the declaration\n// of CompressedTuple below.\ntemplate <typename... Ts>\nconstexpr bool ShouldAnyUseBase() {\n  return decltype(\n      Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){};\n}\n\ntemplate <typename T, typename V>\nusing TupleElementMoveConstructible =\n    typename std::conditional<std::is_reference<T>::value,\n                              std::is_convertible<V, T>,\n                              std::is_constructible<T, V&&>>::type;\n\ntemplate <bool SizeMatches, class T, class... Vs>\nstruct TupleMoveConstructible : std::false_type {};\n\ntemplate <class... Ts, class... Vs>\nstruct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...>\n    : std::integral_constant<\n          bool, absl::conjunction<\n                    TupleElementMoveConstructible<Ts, Vs&&>...>::value> {};\n\ntemplate <typename T>\nstruct compressed_tuple_size;\n\ntemplate <typename... Es>\nstruct compressed_tuple_size<CompressedTuple<Es...>>\n    : public std::integral_constant<std::size_t, sizeof...(Es)> {};\n\ntemplate <class T, class... Vs>\nstruct TupleItemsMoveConstructible\n    : std::integral_constant<\n          bool, TupleMoveConstructible<compressed_tuple_size<T>::value ==\n                                           sizeof...(Vs),\n                                       T, Vs...>::value> {};\n\n}  // namespace internal_compressed_tuple\n\n// Helper class to perform the Empty Base Class Optimization.\n// Ts can contain classes and non-classes, empty or not. For the ones that\n// are empty classes, we perform the CompressedTuple. If all types in Ts are\n// empty classes, then CompressedTuple<Ts...> is itself an empty class.\n//\n// To access the members, use member .get<N>() function.\n//\n// Eg:\n//   absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,\n//                                                                    t3);\n//   assert(value.get<0>() == 7);\n//   T1& t1 = value.get<1>();\n//   const T2& t2 = value.get<2>();\n//   ...\n//\n// https://en.cppreference.com/w/cpp/language/ebo\ntemplate <typename... Ts>\nclass ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple\n    : private internal_compressed_tuple::CompressedTupleImpl<\n          CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>,\n          internal_compressed_tuple::ShouldAnyUseBase<Ts...>()> {\n private:\n  template <int I>\n  using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;\n\n  template <int I>\n  using StorageT = internal_compressed_tuple::Storage<\n      ElemT<I>, I, internal_compressed_tuple::StorageTag<Ts...>>;\n\n public:\n  // There seems to be a bug in MSVC dealing in which using '=default' here will\n  // cause the compiler to ignore the body of other constructors. The work-\n  // around is to explicitly implement the default constructor.\n#if defined(_MSC_VER)\n  constexpr CompressedTuple() : CompressedTuple::CompressedTupleImpl() {}\n#else\n  constexpr CompressedTuple() = default;\n#endif\n  explicit constexpr CompressedTuple(const Ts&... base)\n      : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}\n\n  template <typename First, typename... Vs,\n            absl::enable_if_t<\n                absl::conjunction<\n                    // Ensure we are not hiding default copy/move constructors.\n                    absl::negation<std::is_same<void(CompressedTuple),\n                                                void(absl::decay_t<First>)>>,\n                    internal_compressed_tuple::TupleItemsMoveConstructible<\n                        CompressedTuple<Ts...>, First, Vs...>>::value,\n                bool> = true>\n  explicit constexpr CompressedTuple(First&& first, Vs&&... base)\n      : CompressedTuple::CompressedTupleImpl(absl::in_place,\n                                             std::forward<First>(first),\n                                             std::forward<Vs>(base)...) {}\n\n  template <int I>\n  constexpr ElemT<I>& get() & {\n    return StorageT<I>::get();\n  }\n\n  template <int I>\n  constexpr const ElemT<I>& get() const& {\n    return StorageT<I>::get();\n  }\n\n  template <int I>\n  constexpr ElemT<I>&& get() && {\n    return std::move(*this).StorageT<I>::get();\n  }\n\n  template <int I>\n  constexpr const ElemT<I>&& get() const&& {\n    return std::move(*this).StorageT<I>::get();\n  }\n};\n\n// Explicit specialization for a zero-element tuple\n// (needed to avoid ambiguous overloads for the default constructor).\ntemplate <>\nclass ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC\n\n#endif  // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_\n"
  },
  {
    "path": "absl/container/internal/compressed_tuple_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/compressed_tuple.h\"\n\n#include <any>\n#include <memory>\n#include <optional>\n#include <set>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/utility/utility.h\"\n\n// These are declared at global scope purely so that error messages\n// are smaller and easier to understand.\nenum class CallType { kMutableRef, kConstRef, kMutableMove, kConstMove };\n\ntemplate <int>\nstruct Empty {\n  constexpr CallType value() & { return CallType::kMutableRef; }\n  constexpr CallType value() const& { return CallType::kConstRef; }\n  constexpr CallType value() && { return CallType::kMutableMove; }\n  constexpr CallType value() const&& { return CallType::kConstMove; }\n};\n\n// Unconditionally return an lvalue reference to `t`.\ntemplate <typename T>\nconstexpr T& AsLValue(T&& t) {\n  return t;\n}\n\ntemplate <typename T>\nstruct NotEmpty {\n  T value;\n};\n\ntemplate <typename T, typename U>\nstruct TwoValues {\n  T value1;\n  U value2;\n};\n\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing absl::test_internal::CopyableMovableInstance;\nusing absl::test_internal::InstanceTracker;\nusing ::testing::Each;\n\nTEST(CompressedTupleTest, Sizeof) {\n  EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>));\n  EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>));\n  EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>, Empty<1>>));\n  EXPECT_EQ(sizeof(int),\n            sizeof(CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>));\n\n  EXPECT_EQ(sizeof(TwoValues<int, double>),\n            sizeof(CompressedTuple<int, NotEmpty<double>>));\n  EXPECT_EQ(sizeof(TwoValues<int, double>),\n            sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>>));\n  EXPECT_EQ(sizeof(TwoValues<int, double>),\n            sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>));\n}\n\nTEST(CompressedTupleTest, PointerToEmpty) {\n  auto to_void_ptrs = [](const auto&... objs) {\n    return std::vector<const void*>{static_cast<const void*>(&objs)...};\n  };\n  {\n    using Tuple = CompressedTuple<int, Empty<0>>;\n    EXPECT_EQ(sizeof(int), sizeof(Tuple));\n    Tuple t;\n    EXPECT_THAT(to_void_ptrs(t.get<1>()), Each(&t));\n  }\n  {\n    using Tuple = CompressedTuple<int, Empty<0>, Empty<1>>;\n    EXPECT_EQ(sizeof(int), sizeof(Tuple));\n    Tuple t;\n    EXPECT_THAT(to_void_ptrs(t.get<1>(), t.get<2>()), Each(&t));\n  }\n  {\n    using Tuple = CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>;\n    EXPECT_EQ(sizeof(int), sizeof(Tuple));\n    Tuple t;\n    EXPECT_THAT(to_void_ptrs(t.get<1>(), t.get<2>(), t.get<3>()), Each(&t));\n  }\n}\n\nTEST(CompressedTupleTest, OneMoveOnRValueConstructionTemp) {\n  InstanceTracker tracker;\n  CompressedTuple<CopyableMovableInstance> x1(CopyableMovableInstance(1));\n  EXPECT_EQ(tracker.instances(), 1);\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_LE(tracker.moves(), 1);\n  EXPECT_EQ(x1.get<0>().value(), 1);\n}\n\nTEST(CompressedTupleTest, OneMoveOnRValueConstructionMove) {\n  InstanceTracker tracker;\n\n  CopyableMovableInstance i1(1);\n  CompressedTuple<CopyableMovableInstance> x1(std::move(i1));\n  EXPECT_EQ(tracker.instances(), 2);\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_LE(tracker.moves(), 1);\n  EXPECT_EQ(x1.get<0>().value(), 1);\n}\n\nTEST(CompressedTupleTest, OneMoveOnRValueConstructionMixedTypes) {\n  InstanceTracker tracker;\n  CopyableMovableInstance i1(1);\n  CopyableMovableInstance i2(2);\n  Empty<0> empty;\n  CompressedTuple<CopyableMovableInstance, CopyableMovableInstance&, Empty<0>>\n      x1(std::move(i1), i2, empty);\n  EXPECT_EQ(x1.get<0>().value(), 1);\n  EXPECT_EQ(x1.get<1>().value(), 2);\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 1);\n}\n\nstruct IncompleteType;\nCompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>>\nMakeWithIncomplete(CopyableMovableInstance i1,\n                   IncompleteType& t,  // NOLINT\n                   Empty<0> empty) {\n  return CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>>{\n      std::move(i1), t, empty};\n}\n\nstruct IncompleteType {};\nTEST(CompressedTupleTest, OneMoveOnRValueConstructionWithIncompleteType) {\n  InstanceTracker tracker;\n  CopyableMovableInstance i1(1);\n  Empty<0> empty;\n  struct DerivedType : IncompleteType {int value = 0;};\n  DerivedType fd;\n  fd.value = 7;\n\n  CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>> x1 =\n      MakeWithIncomplete(std::move(i1), fd, empty);\n\n  EXPECT_EQ(x1.get<0>().value(), 1);\n  EXPECT_EQ(static_cast<DerivedType&>(x1.get<1>()).value, 7);\n\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 2);\n}\n\nTEST(CompressedTupleTest,\n     OneMoveOnRValueConstructionMixedTypes_BraceInitPoisonPillExpected) {\n  InstanceTracker tracker;\n  CopyableMovableInstance i1(1);\n  CopyableMovableInstance i2(2);\n  CompressedTuple<CopyableMovableInstance, CopyableMovableInstance&, Empty<0>>\n      x1(std::move(i1), i2, {});  // NOLINT\n  EXPECT_EQ(x1.get<0>().value(), 1);\n  EXPECT_EQ(x1.get<1>().value(), 2);\n  EXPECT_EQ(tracker.instances(), 3);\n  // We are forced into the `const Ts&...` constructor (invoking copies)\n  // because we need it to deduce the type of `{}`.\n  // std::tuple also has this behavior.\n  // Note, this test is proof that this is expected behavior, but it is not\n  // _desired_ behavior.\n  EXPECT_EQ(tracker.copies(), 1);\n  EXPECT_EQ(tracker.moves(), 0);\n}\n\nTEST(CompressedTupleTest, OneCopyOnLValueConstruction) {\n  InstanceTracker tracker;\n  CopyableMovableInstance i1(1);\n\n  CompressedTuple<CopyableMovableInstance> x1(i1);\n  EXPECT_EQ(tracker.copies(), 1);\n  EXPECT_EQ(tracker.moves(), 0);\n\n  tracker.ResetCopiesMovesSwaps();\n\n  CopyableMovableInstance i2(2);\n  const CopyableMovableInstance& i2_ref = i2;\n  CompressedTuple<CopyableMovableInstance> x2(i2_ref);\n  EXPECT_EQ(tracker.copies(), 1);\n  EXPECT_EQ(tracker.moves(), 0);\n}\n\nTEST(CompressedTupleTest, OneMoveOnRValueAccess) {\n  InstanceTracker tracker;\n  CopyableMovableInstance i1(1);\n  CompressedTuple<CopyableMovableInstance> x(std::move(i1));\n  tracker.ResetCopiesMovesSwaps();\n\n  CopyableMovableInstance i2 = std::move(x).get<0>();\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 1);\n}\n\nTEST(CompressedTupleTest, OneCopyOnLValueAccess) {\n  InstanceTracker tracker;\n\n  CompressedTuple<CopyableMovableInstance> x(CopyableMovableInstance(0));\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 1);\n\n  CopyableMovableInstance t = x.get<0>();\n  EXPECT_EQ(tracker.copies(), 1);\n  EXPECT_EQ(tracker.moves(), 1);\n}\n\nTEST(CompressedTupleTest, ZeroCopyOnRefAccess) {\n  InstanceTracker tracker;\n\n  CompressedTuple<CopyableMovableInstance> x(CopyableMovableInstance(0));\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 1);\n\n  CopyableMovableInstance& t1 = x.get<0>();\n  const CopyableMovableInstance& t2 = x.get<0>();\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 1);\n  EXPECT_EQ(t1.value(), 0);\n  EXPECT_EQ(t2.value(), 0);\n}\n\nTEST(CompressedTupleTest, Access) {\n  struct S {\n    std::string x;\n  };\n  CompressedTuple<int, Empty<0>, S> x(7, {}, S{\"ABC\"});\n  EXPECT_EQ(sizeof(x), sizeof(TwoValues<int, S>));\n  EXPECT_EQ(7, x.get<0>());\n  EXPECT_EQ(\"ABC\", x.get<2>().x);\n}\n\nTEST(CompressedTupleTest, NonClasses) {\n  CompressedTuple<int, const char*> x(7, \"ABC\");\n  EXPECT_EQ(7, x.get<0>());\n  EXPECT_STREQ(\"ABC\", x.get<1>());\n}\n\nTEST(CompressedTupleTest, MixClassAndNonClass) {\n  CompressedTuple<int, const char*, Empty<0>, NotEmpty<double>> x(7, \"ABC\", {},\n                                                                  {1.25});\n  struct Mock {\n    int v;\n    const char* p;\n    double d;\n  };\n  EXPECT_EQ(sizeof(x), sizeof(Mock));\n  EXPECT_EQ(7, x.get<0>());\n  EXPECT_STREQ(\"ABC\", x.get<1>());\n  EXPECT_EQ(1.25, x.get<3>().value);\n}\n\nTEST(CompressedTupleTest, Nested) {\n  CompressedTuple<int, CompressedTuple<int>,\n                  CompressedTuple<int, CompressedTuple<int>>>\n      x(1, CompressedTuple<int>(2),\n        CompressedTuple<int, CompressedTuple<int>>(3, CompressedTuple<int>(4)));\n  EXPECT_EQ(1, x.get<0>());\n  EXPECT_EQ(2, x.get<1>().get<0>());\n  EXPECT_EQ(3, x.get<2>().get<0>());\n  EXPECT_EQ(4, x.get<2>().get<1>().get<0>());\n\n  CompressedTuple<Empty<0>, Empty<0>,\n                  CompressedTuple<Empty<0>, CompressedTuple<Empty<0>>>>\n      y;\n  std::set<Empty<0>*> empties{&y.get<0>(), &y.get<1>(), &y.get<2>().get<0>(),\n                              &y.get<2>().get<1>().get<0>()};\n#ifdef _MSC_VER\n  // MSVC has a bug where many instances of the same base class are layed out in\n  // the same address when using __declspec(empty_bases).\n  // This will be fixed in a future version of MSVC.\n  int expected = 1;\n#else\n  int expected = 4;\n#endif\n  EXPECT_EQ(expected, sizeof(y));\n  EXPECT_EQ(expected, empties.size());\n  EXPECT_EQ(sizeof(y), sizeof(Empty<0>) * empties.size());\n\n  EXPECT_EQ(4 * sizeof(char),\n            sizeof(CompressedTuple<CompressedTuple<char, char>,\n                                   CompressedTuple<char, char>>));\n  EXPECT_TRUE((std::is_empty<CompressedTuple<Empty<0>, Empty<1>>>::value));\n\n  // Make sure everything still works when things are nested.\n  struct CT_Empty : CompressedTuple<Empty<0>> {};\n  CompressedTuple<Empty<0>, CT_Empty> nested_empty;\n  auto contained = nested_empty.get<0>();\n  auto nested = nested_empty.get<1>().get<0>();\n  EXPECT_TRUE((std::is_same<decltype(contained), decltype(nested)>::value));\n}\n\nTEST(CompressedTupleTest, Reference) {\n  int i = 7;\n  std::string s = \"Very long string that goes in the heap\";\n  CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s);\n\n  // Sanity check. We should have not moved from `s`\n  EXPECT_EQ(s, \"Very long string that goes in the heap\");\n\n  EXPECT_EQ(x.get<0>(), x.get<1>());\n  EXPECT_NE(&x.get<0>(), &x.get<1>());\n  EXPECT_EQ(&x.get<1>(), &i);\n\n  EXPECT_EQ(x.get<2>(), x.get<3>());\n  EXPECT_NE(&x.get<2>(), &x.get<3>());\n  EXPECT_EQ(&x.get<3>(), &s);\n}\n\nTEST(CompressedTupleTest, NoElements) {\n  CompressedTuple<> x;\n  static_cast<void>(x);  // Silence -Wunused-variable.\n  EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);\n}\n\nTEST(CompressedTupleTest, MoveOnlyElements) {\n  CompressedTuple<std::unique_ptr<std::string>> str_tup(\n      absl::make_unique<std::string>(\"str\"));\n\n  CompressedTuple<CompressedTuple<std::unique_ptr<std::string>>,\n                  std::unique_ptr<int>>\n  x(std::move(str_tup), absl::make_unique<int>(5));\n\n  EXPECT_EQ(*x.get<0>().get<0>(), \"str\");\n  EXPECT_EQ(*x.get<1>(), 5);\n\n  std::unique_ptr<std::string> x0 = std::move(x.get<0>()).get<0>();\n  std::unique_ptr<int> x1 = std::move(x).get<1>();\n\n  EXPECT_EQ(*x0, \"str\");\n  EXPECT_EQ(*x1, 5);\n}\n\nTEST(CompressedTupleTest, MoveConstructionMoveOnlyElements) {\n  CompressedTuple<std::unique_ptr<std::string>> base(\n      absl::make_unique<std::string>(\"str\"));\n  EXPECT_EQ(*base.get<0>(), \"str\");\n\n  CompressedTuple<std::unique_ptr<std::string>> copy(std::move(base));\n  EXPECT_EQ(*copy.get<0>(), \"str\");\n}\n\nTEST(CompressedTupleTest, AnyElements) {\n  std::any a(std::string(\"str\"));\n  CompressedTuple<std::any, std::any&> x(std::any(5), a);\n  EXPECT_EQ(std::any_cast<int>(x.get<0>()), 5);\n  EXPECT_EQ(std::any_cast<std::string>(x.get<1>()), \"str\");\n\n  a = 0.5f;\n  EXPECT_EQ(std::any_cast<float>(x.get<1>()), 0.5);\n}\n\nTEST(CompressedTupleTest, Constexpr) {\n  struct NonTrivialStruct {\n    constexpr NonTrivialStruct() = default;\n    constexpr int value() const { return v; }\n    int v = 5;\n  };\n  struct TrivialStruct {\n    TrivialStruct() = default;\n    constexpr int value() const { return v; }\n    int v;\n  };\n\n  using Tuple = CompressedTuple<int, double, CompressedTuple<int>, Empty<0>>;\n\n  constexpr Tuple x(7, 1.25, CompressedTuple<int>(5), {});\n  constexpr int x0 = x.get<0>();\n  constexpr double x1 = x.get<1>();\n  constexpr int x2 = x.get<2>().get<0>();\n  constexpr CallType x3 = x.get<3>().value();\n\n  EXPECT_EQ(x0, 7);\n  EXPECT_EQ(x1, 1.25);\n  EXPECT_EQ(x2, 5);\n  EXPECT_EQ(x3, CallType::kConstRef);\n\n  constexpr int m0 = Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<0>();\n  constexpr double m1 = Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<1>();\n  constexpr int m2 =\n      Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<2>().get<0>();\n  constexpr CallType m3 =\n      Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<3>().value();\n\n  EXPECT_EQ(m0, 5);\n  EXPECT_EQ(m1, 0.25);\n  EXPECT_EQ(m2, 3);\n  EXPECT_EQ(m3, CallType::kMutableMove);\n\n  constexpr CompressedTuple<Empty<0>, TrivialStruct, int> trivial = {};\n  constexpr CallType trivial0 = trivial.get<0>().value();\n  constexpr int trivial1 = trivial.get<1>().value();\n  constexpr int trivial2 = trivial.get<2>();\n\n  EXPECT_EQ(trivial0, CallType::kConstRef);\n  EXPECT_EQ(trivial1, 0);\n  EXPECT_EQ(trivial2, 0);\n\n  constexpr CompressedTuple<Empty<0>, NonTrivialStruct, std::optional<int>>\n      non_trivial = {};\n  constexpr CallType non_trivial0 = non_trivial.get<0>().value();\n  constexpr int non_trivial1 = non_trivial.get<1>().value();\n  constexpr std::optional<int> non_trivial2 = non_trivial.get<2>();\n\n  EXPECT_EQ(non_trivial0, CallType::kConstRef);\n  EXPECT_EQ(non_trivial1, 5);\n  EXPECT_EQ(non_trivial2, std::nullopt);\n\n  static constexpr char data[] = \"DEF\";\n  constexpr CompressedTuple<const char*> z(data);\n  constexpr const char* z1 = z.get<0>();\n  EXPECT_EQ(std::string(z1), std::string(data));\n\n#if defined(__clang__)\n  // An apparent bug in earlier versions of gcc claims these are ambiguous.\n  constexpr int x2m = std::move(x.get<2>()).get<0>();\n  constexpr CallType x3m = std::move(x).get<3>().value();\n  EXPECT_EQ(x2m, 5);\n  EXPECT_EQ(x3m, CallType::kConstMove);\n#endif\n}\n\n#if defined(__clang__) || defined(__GNUC__)\nTEST(CompressedTupleTest, EmptyFinalClass) {\n  struct S final {\n    int f() const { return 5; }\n  };\n  CompressedTuple<S> x;\n  EXPECT_EQ(x.get<0>().f(), 5);\n}\n#endif\n\nTEST(CompressedTupleTest, NestedEbo) {\n  struct Empty1 {};\n  struct Empty2 {};\n  CompressedTuple<Empty1, CompressedTuple<Empty2>, int> x;\n  CompressedTuple<Empty1, Empty2, int> y;\n  EXPECT_EQ(sizeof(x), sizeof(y));\n\n  using NestedEmpty = CompressedTuple<Empty1, CompressedTuple<Empty2>>;\n  EXPECT_TRUE(std::is_empty_v<NestedEmpty>);\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/container_memory.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_\n#define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <memory>\n#include <new>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n#include <sanitizer/asan_interface.h>\n#endif\n\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n#include <sanitizer/msan_interface.h>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <size_t Alignment>\nstruct alignas(Alignment) AlignedType {\n  // When alignment is sufficient for the allocated memory to store pointers,\n  // include a pointer member so that swisstable backing arrays end up in the\n  // pointer-containing partition for heap partitioning.\n  std::conditional_t<(Alignment < alignof(void*)), char, void*> pointer;\n};\n\n// Allocates at least n bytes aligned to the specified alignment.\n// Alignment must be a power of 2. It must be positive.\n//\n// Note that many allocators don't honor alignment requirements above certain\n// threshold (usually either alignof(std::max_align_t) or alignof(void*)).\n// Allocate() doesn't apply alignment corrections. If the underlying allocator\n// returns insufficiently alignment pointer, that's what you are going to get.\ntemplate <size_t Alignment, class Alloc>\nvoid* Allocate(Alloc* alloc, size_t n) {\n  static_assert(Alignment > 0, \"\");\n  assert(n && \"n must be positive\");\n  using M = AlignedType<Alignment>;\n  using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;\n  using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;\n  // On macOS, \"mem_alloc\" is a #define with one argument defined in\n  // rpc/types.h, so we can't name the variable \"mem_alloc\" and initialize it\n  // with the \"foo(bar)\" syntax.\n  A my_mem_alloc(*alloc);\n  void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));\n  assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&\n         \"allocator does not respect alignment\");\n  return p;\n}\n\n// Returns true if the destruction of the value with given Allocator will be\n// trivial.\ntemplate <class Allocator, class ValueType>\nconstexpr auto IsDestructionTrivial() {\n  constexpr bool result =\n      std::is_trivially_destructible<ValueType>::value &&\n      std::is_same<typename absl::allocator_traits<\n                       Allocator>::template rebind_alloc<char>,\n                   std::allocator<char>>::value;\n  return std::integral_constant<bool, result>();\n}\n\n// The pointer must have been previously obtained by calling\n// Allocate<Alignment>(alloc, n).\ntemplate <size_t Alignment, class Alloc>\nvoid Deallocate(Alloc* alloc, void* p, size_t n) {\n  static_assert(Alignment > 0, \"\");\n  assert(n && \"n must be positive\");\n  using M = AlignedType<Alignment>;\n  using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;\n  using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;\n  // On macOS, \"mem_alloc\" is a #define with one argument defined in\n  // rpc/types.h, so we can't name the variable \"mem_alloc\" and initialize it\n  // with the \"foo(bar)\" syntax.\n  A my_mem_alloc(*alloc);\n  AT::deallocate(my_mem_alloc, static_cast<M*>(p),\n                 (n + sizeof(M) - 1) / sizeof(M));\n}\n\nnamespace memory_internal {\n\n// Constructs T into uninitialized storage pointed by `ptr` using the args\n// specified in the tuple.\ntemplate <class Alloc, class T, class Tuple, size_t... I>\nvoid ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t,\n                            absl::index_sequence<I...>) {\n  absl::allocator_traits<Alloc>::construct(\n      *alloc, ptr, std::get<I>(std::forward<Tuple>(t))...);\n}\n\ntemplate <class T, class F>\nstruct WithConstructedImplF {\n  template <class... Args>\n  decltype(std::declval<F>()(std::declval<T>())) operator()(\n      Args&&... args) const {\n    return std::forward<F>(f)(T(std::forward<Args>(args)...));\n  }\n  F&& f;\n};\n\ntemplate <class T, class Tuple, size_t... Is, class F>\ndecltype(std::declval<F>()(std::declval<T>())) WithConstructedImpl(\n    Tuple&& t, absl::index_sequence<Is...>, F&& f) {\n  return WithConstructedImplF<T, F>{std::forward<F>(f)}(\n      std::get<Is>(std::forward<Tuple>(t))...);\n}\n\ntemplate <class T, size_t... Is>\nauto TupleRefImpl(T&& t, absl::index_sequence<Is...>)\n    -> decltype(std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...)) {\n  // NOLINTNEXTLINE(bugprone-use-after-move)\n  return std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...);\n}\n\n// Returns a tuple of references to the elements of the input tuple. T must be a\n// tuple.\ntemplate <class T>\nauto TupleRef(T&& t) -> decltype(TupleRefImpl(\n    std::forward<T>(t),\n    absl::make_index_sequence<\n        std::tuple_size<typename std::decay<T>::type>::value>())) {\n  return TupleRefImpl(\n      std::forward<T>(t),\n      absl::make_index_sequence<\n          std::tuple_size<typename std::decay<T>::type>::value>());\n}\n\ntemplate <class F, class K, class V>\ndecltype(std::declval<F>()(std::declval<const K&>(), std::piecewise_construct,\n                           std::declval<std::tuple<K>>(), std::declval<V>()))\nDecomposePairImpl(F&& f, std::pair<std::tuple<K>, V> p) {\n  const auto& key = std::get<0>(p.first);\n  return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),\n                            std::move(p.second));\n}\n\n}  // namespace memory_internal\n\n// Constructs T into uninitialized storage pointed by `ptr` using the args\n// specified in the tuple.\ntemplate <class Alloc, class T, class Tuple>\nvoid ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) {\n  memory_internal::ConstructFromTupleImpl(\n      alloc, ptr, std::forward<Tuple>(t),\n      absl::make_index_sequence<\n          std::tuple_size<typename std::decay<Tuple>::type>::value>());\n}\n\n// Constructs T using the args specified in the tuple and calls F with the\n// constructed value.\ntemplate <class T, class Tuple, class F>\ndecltype(std::declval<F>()(std::declval<T>())) WithConstructed(Tuple&& t,\n                                                               F&& f) {\n  return memory_internal::WithConstructedImpl<T>(\n      std::forward<Tuple>(t),\n      absl::make_index_sequence<\n          std::tuple_size<typename std::decay<Tuple>::type>::value>(),\n      std::forward<F>(f));\n}\n\n// Given arguments of an std::pair's constructor, PairArgs() returns a pair of\n// tuples with references to the passed arguments. The tuples contain\n// constructor arguments for the first and the second elements of the pair.\n//\n// The following two snippets are equivalent.\n//\n// 1. std::pair<F, S> p(args...);\n//\n// 2. auto a = PairArgs(args...);\n//    std::pair<F, S> p(std::piecewise_construct,\n//                      std::move(a.first), std::move(a.second));\ninline std::pair<std::tuple<>, std::tuple<>> PairArgs() { return {}; }\ntemplate <class F, class S>\nstd::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(F&& f, S&& s) {\n  return {std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)),\n          std::forward_as_tuple(std::forward<S>(s))};\n}\ntemplate <class F, class S>\nstd::pair<std::tuple<const F&>, std::tuple<const S&>> PairArgs(\n    const std::pair<F, S>& p) {\n  return PairArgs(p.first, p.second);\n}\ntemplate <class F, class S>\nstd::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(std::pair<F, S>&& p) {\n  return PairArgs(std::forward<F>(p.first), std::forward<S>(p.second));\n}\ntemplate <class F, class S>\nauto PairArgs(std::piecewise_construct_t, F&& f, S&& s)\n    -> decltype(std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),\n                               memory_internal::TupleRef(std::forward<S>(s)))) {\n  return std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),\n                        memory_internal::TupleRef(std::forward<S>(s)));\n}\n\n// A helper function for implementing apply() in map policies.\ntemplate <class F, class... Args>\nauto DecomposePair(F&& f, Args&&... args)\n    -> decltype(memory_internal::DecomposePairImpl(\n        std::forward<F>(f), PairArgs(std::forward<Args>(args)...))) {\n  return memory_internal::DecomposePairImpl(\n      std::forward<F>(f), PairArgs(std::forward<Args>(args)...));\n}\n\n// A helper function for implementing apply() in set policies.\ntemplate <class F, class Arg>\ndecltype(std::declval<F>()(std::declval<const Arg&>(), std::declval<Arg>()))\nDecomposeValue(F&& f, Arg&& arg) {\n  const auto& key = arg;\n  return std::forward<F>(f)(key, std::forward<Arg>(arg));\n}\n\n// Helper functions for asan and msan.\ninline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  ASAN_POISON_MEMORY_REGION(m, s);\n#endif\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n  __msan_poison(m, s);\n#endif\n  (void)m;\n  (void)s;\n}\n\ninline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  ASAN_UNPOISON_MEMORY_REGION(m, s);\n#endif\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n  __msan_unpoison(m, s);\n#endif\n  (void)m;\n  (void)s;\n}\n\ntemplate <typename T>\ninline void SanitizerPoisonObject(const T* object) {\n  SanitizerPoisonMemoryRegion(object, sizeof(T));\n}\n\ntemplate <typename T>\ninline void SanitizerUnpoisonObject(const T* object) {\n  SanitizerUnpoisonMemoryRegion(object, sizeof(T));\n}\n\nnamespace memory_internal {\n\n// If Pair is a standard-layout type, OffsetOf<Pair>::kFirst and\n// OffsetOf<Pair>::kSecond are equivalent to offsetof(Pair, first) and\n// offsetof(Pair, second) respectively. Otherwise they are -1.\n//\n// The purpose of OffsetOf is to avoid calling offsetof() on non-standard-layout\n// type, which is non-portable.\ntemplate <class Pair, class = std::true_type>\nstruct OffsetOf {\n  static constexpr size_t kFirst = static_cast<size_t>(-1);\n  static constexpr size_t kSecond = static_cast<size_t>(-1);\n};\n\ntemplate <class Pair>\nstruct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type> {\n  static constexpr size_t kFirst = offsetof(Pair, first);\n  static constexpr size_t kSecond = offsetof(Pair, second);\n};\n\ntemplate <class K, class V>\nstruct IsLayoutCompatible {\n private:\n  struct Pair {\n    K first;\n    V second;\n  };\n\n  // Is P layout-compatible with Pair?\n  template <class P>\n  static constexpr bool LayoutCompatible() {\n    return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) &&\n           alignof(P) == alignof(Pair) &&\n           memory_internal::OffsetOf<P>::kFirst ==\n               memory_internal::OffsetOf<Pair>::kFirst &&\n           memory_internal::OffsetOf<P>::kSecond ==\n               memory_internal::OffsetOf<Pair>::kSecond;\n  }\n\n public:\n  // Whether pair<const K, V> and pair<K, V> are layout-compatible. If they are,\n  // then it is safe to store them in a union and read from either.\n  static constexpr bool value = std::is_standard_layout<K>() &&\n                                std::is_standard_layout<Pair>() &&\n                                memory_internal::OffsetOf<Pair>::kFirst == 0 &&\n                                LayoutCompatible<std::pair<K, V>>() &&\n                                LayoutCompatible<std::pair<const K, V>>();\n};\n\n}  // namespace memory_internal\n\n// The internal storage type for key-value containers like flat_hash_map.\n//\n// It is convenient for the value_type of a flat_hash_map<K, V> to be\n// pair<const K, V>; the \"const K\" prevents accidental modification of the key\n// when dealing with the reference returned from find() and similar methods.\n// However, this creates other problems; we want to be able to emplace(K, V)\n// efficiently with move operations, and similarly be able to move a\n// pair<K, V> in insert().\n//\n// The solution is this union, which aliases the const and non-const versions\n// of the pair. This also allows flat_hash_map<const K, V> to work, even though\n// that has the same efficiency issues with move in emplace() and insert() -\n// but people do it anyway.\n//\n// If kMutableKeys is false, only the value member can be accessed.\n//\n// If kMutableKeys is true, key can be accessed through all slots while value\n// and mutable_value must be accessed only via INITIALIZED slots. Slots are\n// created and destroyed via mutable_value so that the key can be moved later.\n//\n// Accessing one of the union fields while the other is active is safe as\n// long as they are layout-compatible, which is guaranteed by the definition of\n// kMutableKeys. For C++11, the relevant section of the standard is\n// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)\ntemplate <class K, class V>\nunion map_slot_type {\n  map_slot_type() {}\n  ~map_slot_type() = delete;\n  using value_type = std::pair<const K, V>;\n  using mutable_value_type =\n      std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;\n\n  value_type value;\n  mutable_value_type mutable_value;\n  absl::remove_const_t<K> key;\n};\n\ntemplate <class K, class V>\nstruct map_slot_policy {\n  using slot_type = map_slot_type<K, V>;\n  using value_type = std::pair<const K, V>;\n  using mutable_value_type =\n      std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;\n\n private:\n  static void emplace(slot_type* slot) {\n    // The construction of union doesn't do anything at runtime but it allows us\n    // to access its members without violating aliasing rules.\n    new (slot) slot_type;\n  }\n  // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one\n  // or the other via slot_type. We are also free to access the key via\n  // slot_type::key in this case.\n  using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;\n\n public:\n  static value_type& element(slot_type* slot) { return slot->value; }\n  static const value_type& element(const slot_type* slot) {\n    return slot->value;\n  }\n\n  static K& mutable_key(slot_type* slot) {\n    // Still check for kMutableKeys so that we can avoid calling std::launder\n    // unless necessary because it can interfere with optimizations.\n    return kMutableKeys::value ? slot->key\n                               : *std::launder(const_cast<K*>(\n                                     std::addressof(slot->value.first)));\n  }\n\n  static const K& key(const slot_type* slot) {\n    return kMutableKeys::value ? slot->key : slot->value.first;\n  }\n\n  template <class Allocator, class... Args>\n  static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {\n    emplace(slot);\n    if (kMutableKeys::value) {\n      absl::allocator_traits<Allocator>::construct(*alloc, &slot->mutable_value,\n                                                   std::forward<Args>(args)...);\n    } else {\n      absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,\n                                                   std::forward<Args>(args)...);\n    }\n  }\n\n  // Construct this slot by moving from another slot.\n  template <class Allocator>\n  static void construct(Allocator* alloc, slot_type* slot, slot_type* other) {\n    emplace(slot);\n    if (kMutableKeys::value) {\n      absl::allocator_traits<Allocator>::construct(\n          *alloc, &slot->mutable_value, std::move(other->mutable_value));\n    } else {\n      absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,\n                                                   std::move(other->value));\n    }\n  }\n\n  // Construct this slot by copying from another slot.\n  template <class Allocator>\n  static void construct(Allocator* alloc, slot_type* slot,\n                        const slot_type* other) {\n    emplace(slot);\n    absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,\n                                                 other->value);\n  }\n\n  template <class Allocator>\n  static auto destroy(Allocator* alloc, slot_type* slot) {\n    if (kMutableKeys::value) {\n      absl::allocator_traits<Allocator>::destroy(*alloc, &slot->mutable_value);\n    } else {\n      absl::allocator_traits<Allocator>::destroy(*alloc, &slot->value);\n    }\n    return IsDestructionTrivial<Allocator, value_type>();\n  }\n\n  template <class Allocator>\n  static auto transfer(Allocator* alloc, slot_type* new_slot,\n                       slot_type* old_slot) {\n    // This should really just be\n    // typename absl::is_trivially_relocatable<value_type>::type()\n    // but std::pair is not trivially copyable in C++23 in some standard\n    // library versions.\n    // See https://github.com/llvm/llvm-project/pull/95444 for instance.\n    auto is_relocatable = typename std::conjunction<\n        absl::is_trivially_relocatable<typename value_type::first_type>,\n        absl::is_trivially_relocatable<typename value_type::second_type>>::\n        type();\n\n    emplace(new_slot);\n    if (is_relocatable) {\n      // TODO(b/247130232,b/251814870): remove casts after fixing warnings.\n      std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),\n                  static_cast<const void*>(&old_slot->value),\n                  sizeof(value_type));\n      return is_relocatable;\n    }\n\n    if (kMutableKeys::value) {\n      absl::allocator_traits<Allocator>::construct(\n          *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));\n    } else {\n      absl::allocator_traits<Allocator>::construct(*alloc, &new_slot->value,\n                                                   std::move(old_slot->value));\n    }\n    destroy(alloc, old_slot);\n    return is_relocatable;\n  }\n};\n\n// Suppress erroneous uninitialized memory errors on GCC. For example, GCC\n// thinks that the call to slot_array() in find_or_prepare_insert() is reading\n// uninitialized memory, but slot_array is only called there when the table is\n// non-empty and this memory is initialized when the table is non-empty.\n#if !defined(__clang__) && defined(__GNUC__)\n#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(x)                    \\\n  _Pragma(\"GCC diagnostic push\")                                   \\\n      _Pragma(\"GCC diagnostic ignored \\\"-Wmaybe-uninitialized\\\"\")  \\\n          _Pragma(\"GCC diagnostic ignored \\\"-Wuninitialized\\\"\") x; \\\n  _Pragma(\"GCC diagnostic pop\")\n#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(x) \\\n  ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(return x)\n#else\n#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(x) x\n#define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(x) return x\n#endif\n\n// Variadic arguments hash function that ignore the rest of the arguments.\n// Useful for usage with policy traits.\ntemplate <class Hash, bool kIsDefault>\nstruct HashElement {\n  HashElement(const Hash& h, size_t s) : hash(h), seed(s) {}\n\n  template <class K, class... Args>\n  size_t operator()(const K& key, Args&&...) const {\n    if constexpr (kIsDefault) {\n      // TODO(b/384509507): resolve `no header providing\n      // \"absl::hash_internal::SupportsHashWithSeed\" is directly included`.\n      // Maybe we should make \"internal/hash.h\" be a separate library.\n      return absl::hash_internal::HashWithSeed().hash(hash, key, seed);\n    }\n    // NOLINTNEXTLINE(clang-diagnostic-sign-conversion)\n    return hash(key) ^ seed;\n  }\n  const Hash& hash;\n  size_t seed;\n};\n\n// No arguments function hash function for a specific key.\ntemplate <class Hash, class Key, bool kIsDefault>\nstruct HashKey {\n  HashKey(const Hash& h, const Key& k) : hash(h), key(k) {}\n\n  size_t operator()(size_t seed) const {\n    return HashElement<Hash, kIsDefault>{hash, seed}(key);\n  }\n  const Hash& hash;\n  const Key& key;\n};\n\n// Variadic arguments equality function that ignore the rest of the arguments.\n// Useful for usage with policy traits.\ntemplate <class K1, class KeyEqual>\nstruct EqualElement {\n  template <class K2, class... Args>\n  bool operator()(const K2& lhs, Args&&...) const {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(eq(lhs, rhs));\n  }\n  const K1& rhs;\n  const KeyEqual& eq;\n};\n\n// Type erased function for computing hash of the slot.\nusing HashSlotFn = size_t (*)(const void* hash_fn, void* slot, size_t seed);\n\n// Type erased function to apply `Fn` to data inside of the `slot`.\n// The data is expected to have type `T`.\ntemplate <class Fn, class T, bool kIsDefault>\nsize_t TypeErasedApplyToSlotFn(const void* fn, void* slot, size_t seed) {\n  const auto* f = static_cast<const Fn*>(fn);\n  return HashElement<Fn, kIsDefault>{*f, seed}(*static_cast<const T*>(slot));\n}\n\n// Type erased function to apply `Fn` to data inside of the `*slot_ptr`.\n// The data is expected to have type `T`.\ntemplate <class Fn, class T, bool kIsDefault>\nsize_t TypeErasedDerefAndApplyToSlotFn(const void* fn, void* slot_ptr,\n                                       size_t seed) {\n  const auto* f = static_cast<const Fn*>(fn);\n  const T* slot = *static_cast<const T**>(slot_ptr);\n  return HashElement<Fn, kIsDefault>{*f, seed}(*slot);\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_\n"
  },
  {
    "path": "absl/container/internal/container_memory_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/container_memory.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <tuple>\n#include <type_traits>\n#include <typeindex>\n#include <typeinfo>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::absl::test_internal::CopyableMovableInstance;\nusing ::absl::test_internal::InstanceTracker;\nusing ::testing::_;\nusing ::testing::ElementsAre;\nusing ::testing::Gt;\nusing ::testing::Pair;\n\n#if ABSL_HAVE_BUILTIN(__builtin_infer_alloc_token)\nTEST(Memory, AlignedTypeAllocToken) {\n#if defined(__wasm__)\n  GTEST_SKIP() << \"Fails on wasm due to lack of heap partitioning support.\";\n#endif\n  EXPECT_GT(__builtin_infer_alloc_token(sizeof(AlignedType<alignof(void*)>)),\n            __builtin_infer_alloc_token(sizeof(int)));\n}\n#endif\n\nTEST(Memory, AlignmentLargerThanBase) {\n  std::allocator<int8_t> alloc;\n  void* mem = Allocate<2>(&alloc, 3);\n  EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) % 2);\n  memcpy(mem, \"abc\", 3);\n  Deallocate<2>(&alloc, mem, 3);\n}\n\nTEST(Memory, AlignmentSmallerThanBase) {\n  std::allocator<int64_t> alloc;\n  void* mem = Allocate<2>(&alloc, 3);\n  EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) % 2);\n  memcpy(mem, \"abc\", 3);\n  Deallocate<2>(&alloc, mem, 3);\n}\n\nstd::map<std::type_index, int>& AllocationMap() {\n  static absl::NoDestructor<std::map<std::type_index, int>> map;\n  return *map;\n}\n\ntemplate <typename T>\nstruct TypeCountingAllocator {\n  TypeCountingAllocator() = default;\n  template <typename U>\n  TypeCountingAllocator(const TypeCountingAllocator<U>&) {}  // NOLINT\n\n  using value_type = T;\n\n  T* allocate(size_t n, const void* = nullptr) {\n    AllocationMap()[typeid(T)] += n;\n    return std::allocator<T>().allocate(n);\n  }\n  void deallocate(T* p, std::size_t n) {\n    AllocationMap()[typeid(T)] -= n;\n    return std::allocator<T>().deallocate(p, n);\n  }\n};\n\nTEST(Memory, AllocateDeallocateMatchType) {\n  TypeCountingAllocator<int> alloc;\n  void* mem = Allocate<1>(&alloc, 1);\n  // Verify that it was allocated\n  EXPECT_THAT(AllocationMap(), ElementsAre(Pair(_, Gt(0))));\n  Deallocate<1>(&alloc, mem, 1);\n  // Verify that the deallocation matched.\n  EXPECT_THAT(AllocationMap(), ElementsAre(Pair(_, 0)));\n}\n\nclass Fixture : public ::testing::Test {\n  using Alloc = std::allocator<std::string>;\n\n public:\n  Fixture() { ptr_ = std::allocator_traits<Alloc>::allocate(*alloc(), 1); }\n  ~Fixture() override {\n    std::allocator_traits<Alloc>::destroy(*alloc(), ptr_);\n    std::allocator_traits<Alloc>::deallocate(*alloc(), ptr_, 1);\n  }\n  std::string* ptr() { return ptr_; }\n  Alloc* alloc() { return &alloc_; }\n\n private:\n  Alloc alloc_;\n  std::string* ptr_;\n};\n\nTEST_F(Fixture, ConstructNoArgs) {\n  ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple());\n  EXPECT_EQ(*ptr(), \"\");\n}\n\nTEST_F(Fixture, ConstructOneArg) {\n  ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple(\"abcde\"));\n  EXPECT_EQ(*ptr(), \"abcde\");\n}\n\nTEST_F(Fixture, ConstructTwoArg) {\n  ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple(5, 'a'));\n  EXPECT_EQ(*ptr(), \"aaaaa\");\n}\n\nTEST(PairArgs, NoArgs) {\n  EXPECT_THAT(PairArgs(),\n              Pair(std::forward_as_tuple(), std::forward_as_tuple()));\n}\n\nTEST(PairArgs, TwoArgs) {\n  EXPECT_EQ(\n      std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')),\n      PairArgs(1, 'A'));\n}\n\nTEST(PairArgs, Pair) {\n  EXPECT_EQ(\n      std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')),\n      PairArgs(std::make_pair(1, 'A')));\n}\n\nTEST(PairArgs, Piecewise) {\n  EXPECT_EQ(\n      std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')),\n      PairArgs(std::piecewise_construct, std::forward_as_tuple(1),\n               std::forward_as_tuple('A')));\n}\n\nTEST(WithConstructed, Simple) {\n  EXPECT_EQ(1, WithConstructed<absl::string_view>(\n                   std::make_tuple(std::string(\"a\")),\n                   [](absl::string_view str) { return str.size(); }));\n}\n\ntemplate <class F, class Arg>\ndecltype(DecomposeValue(std::declval<F>(), std::declval<Arg>()))\nDecomposeValueImpl(int, F&& f, Arg&& arg) {\n  return DecomposeValue(std::forward<F>(f), std::forward<Arg>(arg));\n}\n\ntemplate <class F, class Arg>\nconst char* DecomposeValueImpl(char, F&& f, Arg&& arg) {\n  return \"not decomposable\";\n}\n\ntemplate <class F, class Arg>\ndecltype(DecomposeValueImpl(0, std::declval<F>(), std::declval<Arg>()))\nTryDecomposeValue(F&& f, Arg&& arg) {\n  return DecomposeValueImpl(0, std::forward<F>(f), std::forward<Arg>(arg));\n}\n\nTEST(DecomposeValue, Decomposable) {\n  auto f = [](const int& x, int&& y) {  // NOLINT\n    EXPECT_EQ(&x, &y);\n    EXPECT_EQ(42, x);\n    return 'A';\n  };\n  EXPECT_EQ('A', TryDecomposeValue(f, 42));\n}\n\nTEST(DecomposeValue, NotDecomposable) {\n  auto f = [](void*) {\n    ADD_FAILURE() << \"Must not be called\";\n    return 'A';\n  };\n  EXPECT_STREQ(\"not decomposable\", TryDecomposeValue(f, 42));\n}\n\ntemplate <class F, class... Args>\ndecltype(DecomposePair(std::declval<F>(), std::declval<Args>()...))\nDecomposePairImpl(int, F&& f, Args&&... args) {\n  return DecomposePair(std::forward<F>(f), std::forward<Args>(args)...);\n}\n\ntemplate <class F, class... Args>\nconst char* DecomposePairImpl(char, F&& f, Args&&... args) {\n  return \"not decomposable\";\n}\n\ntemplate <class F, class... Args>\ndecltype(DecomposePairImpl(0, std::declval<F>(), std::declval<Args>()...))\nTryDecomposePair(F&& f, Args&&... args) {\n  return DecomposePairImpl(0, std::forward<F>(f), std::forward<Args>(args)...);\n}\n\nTEST(DecomposePair, Decomposable) {\n  auto f = [](const int& x,  // NOLINT\n              std::piecewise_construct_t, std::tuple<int&&> k,\n              std::tuple<double>&& v) {\n    EXPECT_EQ(&x, &std::get<0>(k));\n    EXPECT_EQ(42, x);\n    EXPECT_EQ(0.5, std::get<0>(v));\n    return 'A';\n  };\n  EXPECT_EQ('A', TryDecomposePair(f, 42, 0.5));\n  EXPECT_EQ('A', TryDecomposePair(f, std::make_pair(42, 0.5)));\n  EXPECT_EQ('A', TryDecomposePair(f, std::piecewise_construct,\n                                  std::make_tuple(42), std::make_tuple(0.5)));\n}\n\nTEST(DecomposePair, NotDecomposable) {\n  auto f = [](...) {\n    ADD_FAILURE() << \"Must not be called\";\n    return 'A';\n  };\n  EXPECT_STREQ(\"not decomposable\", TryDecomposePair(f));\n  EXPECT_STREQ(\"not decomposable\",\n               TryDecomposePair(f, std::piecewise_construct, std::make_tuple(),\n                                std::make_tuple(0.5)));\n}\n\nTEST(MapSlotPolicy, ConstKeyAndValue) {\n  using slot_policy = map_slot_policy<const CopyableMovableInstance,\n                                      const CopyableMovableInstance>;\n  using slot_type = typename slot_policy::slot_type;\n\n  union Slots {\n    Slots() {}\n    ~Slots() {}\n    slot_type slots[100];\n  } slots;\n\n  std::allocator<\n      std::pair<const CopyableMovableInstance, const CopyableMovableInstance>>\n      alloc;\n  InstanceTracker tracker;\n  slot_policy::construct(&alloc, &slots.slots[0], CopyableMovableInstance(1),\n                         CopyableMovableInstance(1));\n  for (int i = 0; i < 99; ++i) {\n    slot_policy::transfer(&alloc, &slots.slots[i + 1], &slots.slots[i]);\n  }\n  slot_policy::destroy(&alloc, &slots.slots[99]);\n\n  EXPECT_EQ(tracker.copies(), 0);\n}\n\nTEST(MapSlotPolicy, TransferReturnsTrue) {\n  {\n    using slot_policy = map_slot_policy<int, float>;\n    EXPECT_TRUE(\n        (std::is_same<decltype(slot_policy::transfer<std::allocator<char>>(\n                          nullptr, nullptr, nullptr)),\n                      std::true_type>::value));\n  }\n  {\n    struct NonRelocatable {\n      NonRelocatable() = default;\n      NonRelocatable(NonRelocatable&&) {}\n      NonRelocatable& operator=(NonRelocatable&&) { return *this; }\n      void* self = nullptr;\n    };\n\n    EXPECT_FALSE(absl::is_trivially_relocatable<NonRelocatable>::value);\n    using slot_policy = map_slot_policy<int, NonRelocatable>;\n    EXPECT_TRUE(\n        (std::is_same<decltype(slot_policy::transfer<std::allocator<char>>(\n                          nullptr, nullptr, nullptr)),\n                      std::false_type>::value));\n  }\n}\n\nTEST(MapSlotPolicy, DestroyReturnsTrue) {\n  {\n    using slot_policy = map_slot_policy<int, float>;\n    EXPECT_TRUE(\n        (std::is_same<decltype(slot_policy::destroy<std::allocator<char>>(\n                          nullptr, nullptr)),\n                      std::true_type>::value));\n  }\n  {\n    EXPECT_FALSE(std::is_trivially_destructible<std::unique_ptr<int>>::value);\n    using slot_policy = map_slot_policy<int, std::unique_ptr<int>>;\n    EXPECT_TRUE(\n        (std::is_same<decltype(slot_policy::destroy<std::allocator<char>>(\n                          nullptr, nullptr)),\n                      std::false_type>::value));\n  }\n}\n\nTEST(ApplyTest, TypeErasedApplyToSlotFn) {\n  size_t x = 7;\n  size_t seed = 100;\n  auto fn = [](size_t v) { return v * 2; };\n  EXPECT_EQ(\n      (TypeErasedApplyToSlotFn<decltype(fn), size_t, /*kIsDefault=*/false>(\n          &fn, &x, seed)),\n      (HashElement<decltype(fn), /*kIsDefault=*/false>(fn, seed)(x)));\n}\n\nTEST(ApplyTest, TypeErasedDerefAndApplyToSlotFn) {\n  size_t x = 7;\n  size_t seed = 100;\n  auto fn = [](size_t v) { return v * 2; };\n  size_t* x_ptr = &x;\n  EXPECT_EQ((TypeErasedDerefAndApplyToSlotFn<decltype(fn), size_t,\n                                             /*kIsDefault=*/false>(&fn, &x_ptr,\n                                                                   seed)),\n            (HashElement<decltype(fn), /*kIsDefault=*/false>(fn, seed)(x)));\n}\n\nTEST(HashElement, DefaultHash) {\n  size_t x = 7;\n  size_t seed = 100;\n  struct HashWithSeed {\n    size_t operator()(size_t v) const { return v * 2; }\n    size_t hash_with_seed(size_t v, size_t seed) const {\n      return v * 2 + seed * 3;\n    }\n  } hash;\n  EXPECT_EQ((HashElement<HashWithSeed, /*kIsDefault=*/true>(hash, seed)(x)),\n            hash.hash_with_seed(x, seed));\n}\n\nTEST(HashElement, NonDefaultHash) {\n  size_t x = 7;\n  size_t seed = 100;\n  auto fn = [](size_t v) { return v * 2; };\n  EXPECT_EQ(\n      (HashElement<decltype(fn), /*kIsDefault=*/false>(\n          fn, seed)(x)),\n      fn(x) ^ seed);\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hash_function_defaults.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Define the default Hash and Eq functions for SwissTable containers.\n//\n// std::hash<T> and std::equal_to<T> are not appropriate hash and equal\n// functions for SwissTable containers. There are two reasons for this.\n//\n// SwissTable containers are power of 2 sized containers:\n//\n// This means they use the lower bits of the hash value to find the slot for\n// each entry. The typical hash function for integral types is the identity.\n// This is a very weak hash function for SwissTable and any power of 2 sized\n// hashtable implementation which will lead to excessive collisions. For\n// SwissTable we use murmur3 style mixing to reduce collisions to a minimum.\n//\n// SwissTable containers support heterogeneous lookup:\n//\n// In order to make heterogeneous lookup work, hash and equal functions must be\n// polymorphic. At the same time they have to satisfy the same requirements the\n// C++ standard imposes on hash functions and equality operators. That is:\n//\n//   if hash_default_eq<T>(a, b) returns true for any a and b of type T, then\n//   hash_default_hash<T>(a) must equal hash_default_hash<T>(b)\n//\n// For SwissTable containers this requirement is relaxed to allow a and b of\n// any and possibly different types. Note that like the standard the hash and\n// equal functions are still bound to T. This is important because some type U\n// can be hashed by/tested for equality differently depending on T. A notable\n// example is `const char*`. `const char*` is treated as a c-style string when\n// the hash function is hash<std::string> but as a pointer when the hash\n// function is hash<void*>.\n//\n#ifndef ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_\n#define ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_\n\n#include <cstddef>\n#include <functional>\n#include <memory>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/common.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// The hash of an object of type T is computed by using absl::Hash.\ntemplate <class T, class E = void>\nstruct HashEq {\n  using Hash = absl::Hash<T>;\n  using Eq = std::equal_to<T>;\n};\n\nstruct StringHash {\n  using is_transparent = void;\n\n  size_t operator()(absl::string_view v) const {\n    return absl::Hash<absl::string_view>{}(v);\n  }\n  size_t operator()(const absl::Cord& v) const {\n    return absl::Hash<absl::Cord>{}(v);\n  }\n\n private:\n  friend struct absl::hash_internal::HashWithSeed;\n\n  size_t hash_with_seed(absl::string_view v, size_t seed) const {\n    return absl::hash_internal::HashWithSeed().hash(\n        absl::Hash<absl::string_view>{}, v, seed);\n  }\n  size_t hash_with_seed(const absl::Cord& v, size_t seed) const {\n    return absl::hash_internal::HashWithSeed().hash(absl::Hash<absl::Cord>{}, v,\n                                                    seed);\n  }\n};\n\nstruct StringEq {\n  using is_transparent = void;\n  bool operator()(absl::string_view lhs, absl::string_view rhs) const {\n    return lhs == rhs;\n  }\n  bool operator()(const absl::Cord& lhs, const absl::Cord& rhs) const {\n    return lhs == rhs;\n  }\n  bool operator()(const absl::Cord& lhs, absl::string_view rhs) const {\n    return lhs == rhs;\n  }\n  bool operator()(absl::string_view lhs, const absl::Cord& rhs) const {\n    return lhs == rhs;\n  }\n};\n\n// Supports heterogeneous lookup for string-like elements.\nstruct StringHashEq {\n  using Hash = StringHash;\n  using Eq = StringEq;\n};\n\ntemplate <>\nstruct HashEq<std::string> : StringHashEq {};\ntemplate <>\nstruct HashEq<absl::string_view> : StringHashEq {};\ntemplate <>\nstruct HashEq<absl::Cord> : StringHashEq {};\n\ntemplate <typename TChar>\nstruct BasicStringHash {\n  using is_transparent = void;\n\n  size_t operator()(std::basic_string_view<TChar> v) const {\n    return absl::Hash<std::basic_string_view<TChar>>{}(v);\n  }\n};\n\ntemplate <typename TChar>\nstruct BasicStringEq {\n  using is_transparent = void;\n  bool operator()(std::basic_string_view<TChar> lhs,\n                  std::basic_string_view<TChar> rhs) const {\n    return lhs == rhs;\n  }\n};\n\n// Supports heterogeneous lookup for w/u16/u32 string + string_view + char*.\ntemplate <typename TChar>\nstruct BasicStringHashEq {\n  using Hash = BasicStringHash<TChar>;\n  using Eq = BasicStringEq<TChar>;\n};\n\ntemplate <>\nstruct HashEq<std::wstring> : BasicStringHashEq<wchar_t> {};\ntemplate <>\nstruct HashEq<std::wstring_view> : BasicStringHashEq<wchar_t> {};\ntemplate <>\nstruct HashEq<std::u16string> : BasicStringHashEq<char16_t> {};\ntemplate <>\nstruct HashEq<std::u16string_view> : BasicStringHashEq<char16_t> {};\ntemplate <>\nstruct HashEq<std::u32string> : BasicStringHashEq<char32_t> {};\ntemplate <>\nstruct HashEq<std::u32string_view> : BasicStringHashEq<char32_t> {};\n\n// Supports heterogeneous lookup for pointers and smart pointers.\ntemplate <class T>\nstruct HashEq<T*> {\n  struct Hash {\n    using is_transparent = void;\n    template <class U>\n    size_t operator()(const U& ptr) const {\n      return absl::Hash<const T*>{}(HashEq::ToPtr(ptr));\n    }\n  };\n  struct Eq {\n    using is_transparent = void;\n    template <class A, class B>\n    bool operator()(const A& a, const B& b) const {\n      return HashEq::ToPtr(a) == HashEq::ToPtr(b);\n    }\n  };\n\n private:\n  static const T* ToPtr(const T* ptr) { return ptr; }\n  template <class U, class D>\n  static const T* ToPtr(const std::unique_ptr<U, D>& ptr) {\n    return ptr.get();\n  }\n  template <class U>\n  static const T* ToPtr(const std::shared_ptr<U>& ptr) {\n    return ptr.get();\n  }\n};\n\ntemplate <class T, class D>\nstruct HashEq<std::unique_ptr<T, D>> : HashEq<T*> {};\ntemplate <class T>\nstruct HashEq<std::shared_ptr<T>> : HashEq<T*> {};\n\ntemplate <typename T, typename E = void>\nstruct HasAbslContainerHash : std::false_type {};\n\ntemplate <typename T>\nstruct HasAbslContainerHash<T, absl::void_t<typename T::absl_container_hash>>\n    : std::true_type {};\n\ntemplate <typename T, typename E = void>\nstruct HasAbslContainerEq : std::false_type {};\n\ntemplate <typename T>\nstruct HasAbslContainerEq<T, absl::void_t<typename T::absl_container_eq>>\n    : std::true_type {};\n\ntemplate <typename T, typename E = void>\nstruct AbslContainerEq {\n  using type = std::equal_to<>;\n};\n\ntemplate <typename T>\nstruct AbslContainerEq<\n    T, typename std::enable_if_t<HasAbslContainerEq<T>::value>> {\n  using type = typename T::absl_container_eq;\n};\n\ntemplate <typename T, typename E = void>\nstruct AbslContainerHash {\n  using type = void;\n};\n\ntemplate <typename T>\nstruct AbslContainerHash<\n    T, typename std::enable_if_t<HasAbslContainerHash<T>::value>> {\n  using type = typename T::absl_container_hash;\n};\n\n// HashEq specialization for user types that provide `absl_container_hash` and\n// (optionally) `absl_container_eq`. This specialization allows user types to\n// provide heterogeneous lookup without requiring to explicitly specify Hash/Eq\n// type arguments in unordered Abseil containers.\n//\n// Both `absl_container_hash` and `absl_container_eq` should be transparent\n// (have inner is_transparent type). While there is no technical reason to\n// restrict to transparent-only types, there is also no feasible use case when\n// it shouldn't be transparent - it is easier to relax the requirement later if\n// such a case arises rather than restricting it.\n//\n// If type provides only `absl_container_hash` then `eq` part will be\n// `std::equal_to<void>`.\n//\n// User types are not allowed to provide only a `Eq` part as there is no\n// feasible use case for this behavior - if Hash should be a default one then Eq\n// should be an equivalent to the `std::equal_to<T>`.\ntemplate <typename T>\nstruct HashEq<T, typename std::enable_if_t<HasAbslContainerHash<T>::value>> {\n  using Hash = typename AbslContainerHash<T>::type;\n  using Eq = typename AbslContainerEq<T>::type;\n  static_assert(IsTransparent<Hash>::value,\n                \"absl_container_hash must be transparent. To achieve it add a \"\n                \"`using is_transparent = void;` clause to this type.\");\n  static_assert(IsTransparent<Eq>::value,\n                \"absl_container_eq must be transparent. To achieve it add a \"\n                \"`using is_transparent = void;` clause to this type.\");\n};\n\n// This header's visibility is restricted.  If you need to access the default\n// hasher please use the container's ::hasher alias instead.\n//\n// Example: typename Hash = typename absl::flat_hash_map<K, V>::hasher\ntemplate <class T>\nusing hash_default_hash = typename container_internal::HashEq<T>::Hash;\n\n// This header's visibility is restricted.  If you need to access the default\n// key equal please use the container's ::key_equal alias instead.\n//\n// Example: typename Eq = typename absl::flat_hash_map<K, V, Hash>::key_equal\ntemplate <class T>\nusing hash_default_eq = typename container_internal::HashEq<T>::Eq;\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_\n"
  },
  {
    "path": "absl/container/internal/hash_function_defaults_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hash_function_defaults.h\"\n\n#include <cstddef>\n#include <functional>\n#include <string_view>\n#include <type_traits>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/cord_test_helpers.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::Types;\n\nTEST(Eq, Int32) {\n  hash_default_eq<int32_t> eq;\n  EXPECT_TRUE(eq(1, 1u));\n  EXPECT_TRUE(eq(1, char{1}));\n  EXPECT_TRUE(eq(1, true));\n  EXPECT_TRUE(eq(1, double{1.1}));\n  EXPECT_FALSE(eq(1, char{2}));\n  EXPECT_FALSE(eq(1, 2u));\n  EXPECT_FALSE(eq(1, false));\n  EXPECT_FALSE(eq(1, 2.));\n}\n\nTEST(Hash, Int32) {\n  hash_default_hash<int32_t> hash;\n  auto h = hash(1);\n  EXPECT_EQ(h, hash(1u));\n  EXPECT_EQ(h, hash(char{1}));\n  EXPECT_EQ(h, hash(true));\n  EXPECT_EQ(h, hash(double{1.1}));\n  EXPECT_NE(h, hash(2u));\n  EXPECT_NE(h, hash(char{2}));\n  EXPECT_NE(h, hash(false));\n  EXPECT_NE(h, hash(2.));\n}\n\nenum class MyEnum { A, B, C, D };\n\nTEST(Eq, Enum) {\n  hash_default_eq<MyEnum> eq;\n  EXPECT_TRUE(eq(MyEnum::A, MyEnum::A));\n  EXPECT_FALSE(eq(MyEnum::A, MyEnum::B));\n}\n\nTEST(Hash, Enum) {\n  hash_default_hash<MyEnum> hash;\n\n  for (MyEnum e : {MyEnum::A, MyEnum::B, MyEnum::C}) {\n    auto h = hash(e);\n    EXPECT_EQ(h, hash_default_hash<int>{}(static_cast<int>(e)));\n    EXPECT_NE(h, hash(MyEnum::D));\n  }\n}\n\nusing StringTypes = ::testing::Types<std::string, absl::string_view>;\n\ntemplate <class T>\nstruct EqString : ::testing::Test {\n  hash_default_eq<T> key_eq;\n};\n\nTYPED_TEST_SUITE(EqString, StringTypes);\n\ntemplate <class T>\nstruct HashString : ::testing::Test {\n  hash_default_hash<T> hasher;\n};\n\nTYPED_TEST_SUITE(HashString, StringTypes);\n\nTYPED_TEST(EqString, Works) {\n  auto eq = this->key_eq;\n  EXPECT_TRUE(eq(\"a\", \"a\"));\n  EXPECT_TRUE(eq(\"a\", absl::string_view(\"a\")));\n  EXPECT_TRUE(eq(\"a\", std::string(\"a\")));\n  EXPECT_FALSE(eq(\"a\", \"b\"));\n  EXPECT_FALSE(eq(\"a\", absl::string_view(\"b\")));\n  EXPECT_FALSE(eq(\"a\", std::string(\"b\")));\n}\n\nTYPED_TEST(HashString, Works) {\n  auto hash = this->hasher;\n  auto h = hash(\"a\");\n  EXPECT_EQ(h, hash(absl::string_view(\"a\")));\n  EXPECT_EQ(h, hash(std::string(\"a\")));\n  EXPECT_NE(h, hash(absl::string_view(\"b\")));\n  EXPECT_NE(h, hash(std::string(\"b\")));\n}\n\nTEST(BasicStringViewTest, WStringEqWorks) {\n  hash_default_eq<std::wstring> eq;\n  EXPECT_TRUE(eq(L\"a\", L\"a\"));\n  EXPECT_TRUE(eq(L\"a\", std::wstring_view(L\"a\")));\n  EXPECT_TRUE(eq(L\"a\", std::wstring(L\"a\")));\n  EXPECT_FALSE(eq(L\"a\", L\"b\"));\n  EXPECT_FALSE(eq(L\"a\", std::wstring_view(L\"b\")));\n  EXPECT_FALSE(eq(L\"a\", std::wstring(L\"b\")));\n}\n\nTEST(BasicStringViewTest, WStringViewEqWorks) {\n  hash_default_eq<std::wstring_view> eq;\n  EXPECT_TRUE(eq(L\"a\", L\"a\"));\n  EXPECT_TRUE(eq(L\"a\", std::wstring_view(L\"a\")));\n  EXPECT_TRUE(eq(L\"a\", std::wstring(L\"a\")));\n  EXPECT_FALSE(eq(L\"a\", L\"b\"));\n  EXPECT_FALSE(eq(L\"a\", std::wstring_view(L\"b\")));\n  EXPECT_FALSE(eq(L\"a\", std::wstring(L\"b\")));\n}\n\nTEST(BasicStringViewTest, U16StringEqWorks) {\n  hash_default_eq<std::u16string> eq;\n  EXPECT_TRUE(eq(u\"a\", u\"a\"));\n  EXPECT_TRUE(eq(u\"a\", std::u16string_view(u\"a\")));\n  EXPECT_TRUE(eq(u\"a\", std::u16string(u\"a\")));\n  EXPECT_FALSE(eq(u\"a\", u\"b\"));\n  EXPECT_FALSE(eq(u\"a\", std::u16string_view(u\"b\")));\n  EXPECT_FALSE(eq(u\"a\", std::u16string(u\"b\")));\n}\n\nTEST(BasicStringViewTest, U16StringViewEqWorks) {\n  hash_default_eq<std::u16string_view> eq;\n  EXPECT_TRUE(eq(u\"a\", u\"a\"));\n  EXPECT_TRUE(eq(u\"a\", std::u16string_view(u\"a\")));\n  EXPECT_TRUE(eq(u\"a\", std::u16string(u\"a\")));\n  EXPECT_FALSE(eq(u\"a\", u\"b\"));\n  EXPECT_FALSE(eq(u\"a\", std::u16string_view(u\"b\")));\n  EXPECT_FALSE(eq(u\"a\", std::u16string(u\"b\")));\n}\n\nTEST(BasicStringViewTest, U32StringEqWorks) {\n  hash_default_eq<std::u32string> eq;\n  EXPECT_TRUE(eq(U\"a\", U\"a\"));\n  EXPECT_TRUE(eq(U\"a\", std::u32string_view(U\"a\")));\n  EXPECT_TRUE(eq(U\"a\", std::u32string(U\"a\")));\n  EXPECT_FALSE(eq(U\"a\", U\"b\"));\n  EXPECT_FALSE(eq(U\"a\", std::u32string_view(U\"b\")));\n  EXPECT_FALSE(eq(U\"a\", std::u32string(U\"b\")));\n}\n\nTEST(BasicStringViewTest, U32StringViewEqWorks) {\n  hash_default_eq<std::u32string_view> eq;\n  EXPECT_TRUE(eq(U\"a\", U\"a\"));\n  EXPECT_TRUE(eq(U\"a\", std::u32string_view(U\"a\")));\n  EXPECT_TRUE(eq(U\"a\", std::u32string(U\"a\")));\n  EXPECT_FALSE(eq(U\"a\", U\"b\"));\n  EXPECT_FALSE(eq(U\"a\", std::u32string_view(U\"b\")));\n  EXPECT_FALSE(eq(U\"a\", std::u32string(U\"b\")));\n}\n\nTEST(BasicStringViewTest, WStringHashWorks) {\n  hash_default_hash<std::wstring> hash;\n  auto h = hash(L\"a\");\n  EXPECT_EQ(h, hash(std::wstring_view(L\"a\")));\n  EXPECT_EQ(h, hash(std::wstring(L\"a\")));\n  EXPECT_NE(h, hash(std::wstring_view(L\"b\")));\n  EXPECT_NE(h, hash(std::wstring(L\"b\")));\n}\n\nTEST(BasicStringViewTest, WStringViewHashWorks) {\n  hash_default_hash<std::wstring_view> hash;\n  auto h = hash(L\"a\");\n  EXPECT_EQ(h, hash(std::wstring_view(L\"a\")));\n  EXPECT_EQ(h, hash(std::wstring(L\"a\")));\n  EXPECT_NE(h, hash(std::wstring_view(L\"b\")));\n  EXPECT_NE(h, hash(std::wstring(L\"b\")));\n}\n\nTEST(BasicStringViewTest, U16StringHashWorks) {\n  hash_default_hash<std::u16string> hash;\n  auto h = hash(u\"a\");\n  EXPECT_EQ(h, hash(std::u16string_view(u\"a\")));\n  EXPECT_EQ(h, hash(std::u16string(u\"a\")));\n  EXPECT_NE(h, hash(std::u16string_view(u\"b\")));\n  EXPECT_NE(h, hash(std::u16string(u\"b\")));\n}\n\nTEST(BasicStringViewTest, U16StringViewHashWorks) {\n  hash_default_hash<std::u16string_view> hash;\n  auto h = hash(u\"a\");\n  EXPECT_EQ(h, hash(std::u16string_view(u\"a\")));\n  EXPECT_EQ(h, hash(std::u16string(u\"a\")));\n  EXPECT_NE(h, hash(std::u16string_view(u\"b\")));\n  EXPECT_NE(h, hash(std::u16string(u\"b\")));\n}\n\nTEST(BasicStringViewTest, U32StringHashWorks) {\n  hash_default_hash<std::u32string> hash;\n  auto h = hash(U\"a\");\n  EXPECT_EQ(h, hash(std::u32string_view(U\"a\")));\n  EXPECT_EQ(h, hash(std::u32string(U\"a\")));\n  EXPECT_NE(h, hash(std::u32string_view(U\"b\")));\n  EXPECT_NE(h, hash(std::u32string(U\"b\")));\n}\n\nTEST(BasicStringViewTest, U32StringViewHashWorks) {\n  hash_default_hash<std::u32string_view> hash;\n  auto h = hash(U\"a\");\n  EXPECT_EQ(h, hash(std::u32string_view(U\"a\")));\n  EXPECT_EQ(h, hash(std::u32string(U\"a\")));\n  EXPECT_NE(h, hash(std::u32string_view(U\"b\")));\n  EXPECT_NE(h, hash(std::u32string(U\"b\")));\n}\n\nstruct NoDeleter {\n  template <class T>\n  void operator()(const T* ptr) const {}\n};\n\nusing PointerTypes =\n    ::testing::Types<const int*, int*, std::unique_ptr<const int>,\n                     std::unique_ptr<const int, NoDeleter>,\n                     std::unique_ptr<int>, std::unique_ptr<int, NoDeleter>,\n                     std::shared_ptr<const int>, std::shared_ptr<int>>;\n\ntemplate <class T>\nstruct EqPointer : ::testing::Test {\n  hash_default_eq<T> key_eq;\n};\n\nTYPED_TEST_SUITE(EqPointer, PointerTypes);\n\ntemplate <class T>\nstruct HashPointer : ::testing::Test {\n  hash_default_hash<T> hasher;\n};\n\nTYPED_TEST_SUITE(HashPointer, PointerTypes);\n\nTYPED_TEST(EqPointer, Works) {\n  int dummy;\n  auto eq = this->key_eq;\n  auto sptr = std::make_shared<int>();\n  std::shared_ptr<const int> csptr = sptr;\n  int* ptr = sptr.get();\n  const int* cptr = ptr;\n  std::unique_ptr<int, NoDeleter> uptr(ptr);\n  std::unique_ptr<const int, NoDeleter> cuptr(ptr);\n\n  EXPECT_TRUE(eq(ptr, cptr));\n  EXPECT_TRUE(eq(ptr, sptr));\n  EXPECT_TRUE(eq(ptr, uptr));\n  EXPECT_TRUE(eq(ptr, csptr));\n  EXPECT_TRUE(eq(ptr, cuptr));\n  EXPECT_FALSE(eq(&dummy, cptr));\n  EXPECT_FALSE(eq(&dummy, sptr));\n  EXPECT_FALSE(eq(&dummy, uptr));\n  EXPECT_FALSE(eq(&dummy, csptr));\n  EXPECT_FALSE(eq(&dummy, cuptr));\n}\n\nTEST(Hash, DerivedAndBase) {\n  struct Base {};\n  struct Derived : Base {};\n\n  hash_default_hash<Base*> hasher;\n\n  Base base;\n  Derived derived;\n  EXPECT_NE(hasher(&base), hasher(&derived));\n  EXPECT_EQ(hasher(static_cast<Base*>(&derived)), hasher(&derived));\n\n  auto dp = std::make_shared<Derived>();\n  EXPECT_EQ(hasher(static_cast<Base*>(dp.get())), hasher(dp));\n}\n\nTEST(Hash, FunctionPointer) {\n  using Func = int (*)();\n  hash_default_hash<Func> hasher;\n  hash_default_eq<Func> eq;\n\n  Func p1 = [] { return 1; }, p2 = [] { return 2; };\n  EXPECT_EQ(hasher(p1), hasher(p1));\n  EXPECT_TRUE(eq(p1, p1));\n\n  EXPECT_NE(hasher(p1), hasher(p2));\n  EXPECT_FALSE(eq(p1, p2));\n}\n\nTYPED_TEST(HashPointer, Works) {\n  int dummy;\n  auto hash = this->hasher;\n  auto sptr = std::make_shared<int>();\n  std::shared_ptr<const int> csptr = sptr;\n  int* ptr = sptr.get();\n  const int* cptr = ptr;\n  std::unique_ptr<int, NoDeleter> uptr(ptr);\n  std::unique_ptr<const int, NoDeleter> cuptr(ptr);\n\n  EXPECT_EQ(hash(ptr), hash(cptr));\n  EXPECT_EQ(hash(ptr), hash(sptr));\n  EXPECT_EQ(hash(ptr), hash(uptr));\n  EXPECT_EQ(hash(ptr), hash(csptr));\n  EXPECT_EQ(hash(ptr), hash(cuptr));\n  EXPECT_NE(hash(&dummy), hash(cptr));\n  EXPECT_NE(hash(&dummy), hash(sptr));\n  EXPECT_NE(hash(&dummy), hash(uptr));\n  EXPECT_NE(hash(&dummy), hash(csptr));\n  EXPECT_NE(hash(&dummy), hash(cuptr));\n}\n\nTEST(EqCord, Works) {\n  hash_default_eq<absl::Cord> eq;\n  const absl::string_view a_string_view = \"a\";\n  const absl::Cord a_cord(a_string_view);\n  const absl::string_view b_string_view = \"b\";\n  const absl::Cord b_cord(b_string_view);\n\n  EXPECT_TRUE(eq(a_cord, a_cord));\n  EXPECT_TRUE(eq(a_cord, a_string_view));\n  EXPECT_TRUE(eq(a_string_view, a_cord));\n  EXPECT_FALSE(eq(a_cord, b_cord));\n  EXPECT_FALSE(eq(a_cord, b_string_view));\n  EXPECT_FALSE(eq(b_string_view, a_cord));\n}\n\nTEST(HashCord, Works) {\n  hash_default_hash<absl::Cord> hash;\n  const absl::string_view a_string_view = \"a\";\n  const absl::Cord a_cord(a_string_view);\n  const absl::string_view b_string_view = \"b\";\n  const absl::Cord b_cord(b_string_view);\n\n  EXPECT_EQ(hash(a_cord), hash(a_cord));\n  EXPECT_EQ(hash(b_cord), hash(b_cord));\n  EXPECT_EQ(hash(a_string_view), hash(a_cord));\n  EXPECT_EQ(hash(b_string_view), hash(b_cord));\n  EXPECT_EQ(hash(absl::Cord(\"\")), hash(\"\"));\n  EXPECT_EQ(hash(absl::Cord()), hash(absl::string_view()));\n\n  EXPECT_NE(hash(a_cord), hash(b_cord));\n  EXPECT_NE(hash(a_cord), hash(b_string_view));\n  EXPECT_NE(hash(a_string_view), hash(b_cord));\n  EXPECT_NE(hash(a_string_view), hash(b_string_view));\n}\n\nvoid NoOpReleaser(absl::string_view data, void* arg) {}\n\nTEST(HashCord, FragmentedCordWorks) {\n  hash_default_hash<absl::Cord> hash;\n  absl::Cord c = absl::MakeFragmentedCord({\"a\", \"b\", \"c\"});\n  EXPECT_FALSE(c.TryFlat().has_value());\n  EXPECT_EQ(hash(c), hash(\"abc\"));\n}\n\nTEST(HashCord, FragmentedLongCordWorks) {\n  hash_default_hash<absl::Cord> hash;\n  // Crete some large strings which do not fit on the stack.\n  std::string a(65536, 'a');\n  std::string b(65536, 'b');\n  absl::Cord c = absl::MakeFragmentedCord({a, b});\n  EXPECT_FALSE(c.TryFlat().has_value());\n  EXPECT_EQ(hash(c), hash(a + b));\n}\n\nTEST(HashCord, RandomCord) {\n  hash_default_hash<absl::Cord> hash;\n  auto bitgen = absl::BitGen();\n  for (int i = 0; i < 1000; ++i) {\n    const int number_of_segments = absl::Uniform(bitgen, 0, 10);\n    std::vector<std::string> pieces;\n    for (size_t s = 0; s < number_of_segments; ++s) {\n      std::string str;\n      str.resize(absl::Uniform(bitgen, 0, 4096));\n      // MSVC needed the explicit return type in the lambda.\n      std::generate(str.begin(), str.end(), [&]() -> char {\n        return static_cast<char>(absl::Uniform<unsigned char>(bitgen));\n      });\n      pieces.push_back(str);\n    }\n    absl::Cord c = absl::MakeFragmentedCord(pieces);\n    EXPECT_EQ(hash(c), hash(std::string(c)));\n  }\n}\n\n// Cartesian product of (std::string, absl::string_view)\n// with (std::string, absl::string_view, const char*, absl::Cord).\nusing StringTypesCartesianProduct = Types<\n    // clang-format off\n    std::pair<absl::Cord, std::string>,\n    std::pair<absl::Cord, absl::string_view>,\n    std::pair<absl::Cord, absl::Cord>,\n    std::pair<absl::Cord, const char*>,\n\n    std::pair<std::string, absl::Cord>,\n    std::pair<absl::string_view, absl::Cord>,\n\n    std::pair<absl::string_view, std::string>,\n    std::pair<absl::string_view, absl::string_view>,\n    std::pair<absl::string_view, const char*>>;\n// clang-format on\n\nconstexpr char kFirstString[] = \"abc123\";\nconstexpr char kSecondString[] = \"ijk456\";\n\ntemplate <typename T>\nstruct StringLikeTest : public ::testing::Test {\n  typename T::first_type a1{kFirstString};\n  typename T::second_type b1{kFirstString};\n  typename T::first_type a2{kSecondString};\n  typename T::second_type b2{kSecondString};\n  hash_default_eq<typename T::first_type> eq;\n  hash_default_hash<typename T::first_type> hash;\n};\n\nTYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct);\n\nTYPED_TEST(StringLikeTest, Eq) {\n  EXPECT_TRUE(this->eq(this->a1, this->b1));\n  EXPECT_TRUE(this->eq(this->b1, this->a1));\n}\n\nTYPED_TEST(StringLikeTest, NotEq) {\n  EXPECT_FALSE(this->eq(this->a1, this->b2));\n  EXPECT_FALSE(this->eq(this->b2, this->a1));\n}\n\nTYPED_TEST(StringLikeTest, HashEq) {\n  EXPECT_EQ(this->hash(this->a1), this->hash(this->b1));\n  EXPECT_EQ(this->hash(this->a2), this->hash(this->b2));\n  // It would be a poor hash function which collides on these strings.\n  EXPECT_NE(this->hash(this->a1), this->hash(this->b2));\n}\n\nstruct TypeWithAbslContainerHash {\n  struct absl_container_hash {\n    using is_transparent = void;\n\n    size_t operator()(const TypeWithAbslContainerHash& foo) const {\n      return absl::HashOf(foo.value);\n    }\n\n    // Extra overload to test that heterogeneity works for this hasher.\n    size_t operator()(int value) const { return absl::HashOf(value); }\n  };\n\n  friend bool operator==(const TypeWithAbslContainerHash& lhs,\n                         const TypeWithAbslContainerHash& rhs) {\n    return lhs.value == rhs.value;\n  }\n\n  friend bool operator==(const TypeWithAbslContainerHash& lhs, int rhs) {\n    return lhs.value == rhs;\n  }\n\n  int value;\n  int noise;\n};\n\nstruct TypeWithAbslContainerHashAndEq {\n  struct absl_container_hash {\n    using is_transparent = void;\n\n    size_t operator()(const TypeWithAbslContainerHashAndEq& foo) const {\n      return absl::HashOf(foo.value);\n    }\n\n    // Extra overload to test that heterogeneity works for this hasher.\n    size_t operator()(int value) const { return absl::HashOf(value); }\n  };\n\n  struct absl_container_eq {\n    using is_transparent = void;\n\n    bool operator()(const TypeWithAbslContainerHashAndEq& lhs,\n                    const TypeWithAbslContainerHashAndEq& rhs) const {\n      return lhs.value == rhs.value;\n    }\n\n    // Extra overload to test that heterogeneity works for this eq.\n    bool operator()(const TypeWithAbslContainerHashAndEq& lhs, int rhs) const {\n      return lhs.value == rhs;\n    }\n  };\n\n  template <typename T>\n  bool operator==(T&& other) const = delete;\n\n  int value;\n  int noise;\n};\n\nusing AbslContainerHashTypes =\n    Types<TypeWithAbslContainerHash, TypeWithAbslContainerHashAndEq>;\n\ntemplate <typename T>\nusing AbslContainerHashTest = ::testing::Test;\n\nTYPED_TEST_SUITE(AbslContainerHashTest, AbslContainerHashTypes);\n\nTYPED_TEST(AbslContainerHashTest, HasherWorks) {\n  hash_default_hash<TypeParam> hasher;\n\n  TypeParam foo1{/*value=*/1, /*noise=*/100};\n  TypeParam foo1_copy{/*value=*/1, /*noise=*/20};\n  TypeParam foo2{/*value=*/2, /*noise=*/100};\n\n  EXPECT_EQ(hasher(foo1), absl::HashOf(1));\n  EXPECT_EQ(hasher(foo2), absl::HashOf(2));\n  EXPECT_EQ(hasher(foo1), hasher(foo1_copy));\n\n  // Heterogeneity works.\n  EXPECT_EQ(hasher(foo1), hasher(1));\n  EXPECT_EQ(hasher(foo2), hasher(2));\n}\n\nTYPED_TEST(AbslContainerHashTest, EqWorks) {\n  hash_default_eq<TypeParam> eq;\n\n  TypeParam foo1{/*value=*/1, /*noise=*/100};\n  TypeParam foo1_copy{/*value=*/1, /*noise=*/20};\n  TypeParam foo2{/*value=*/2, /*noise=*/100};\n\n  EXPECT_TRUE(eq(foo1, foo1_copy));\n  EXPECT_FALSE(eq(foo1, foo2));\n\n  // Heterogeneity works.\n  EXPECT_TRUE(eq(foo1, 1));\n  EXPECT_FALSE(eq(foo1, 2));\n}\n\nTYPED_TEST(AbslContainerHashTest, HeterogeneityInMapWorks) {\n  absl::flat_hash_map<TypeParam, int> map;\n\n  TypeParam foo1{/*value=*/1, /*noise=*/100};\n  TypeParam foo1_copy{/*value=*/1, /*noise=*/20};\n  TypeParam foo2{/*value=*/2, /*noise=*/100};\n  TypeParam foo3{/*value=*/3, /*noise=*/100};\n\n  map[foo1] = 1;\n  map[foo2] = 2;\n\n  EXPECT_TRUE(map.contains(foo1_copy));\n  EXPECT_EQ(map.at(foo1_copy), 1);\n  EXPECT_TRUE(map.contains(1));\n  EXPECT_EQ(map.at(1), 1);\n  EXPECT_TRUE(map.contains(2));\n  EXPECT_EQ(map.at(2), 2);\n  EXPECT_FALSE(map.contains(foo3));\n  EXPECT_FALSE(map.contains(3));\n}\n\nTYPED_TEST(AbslContainerHashTest, HeterogeneityInSetWorks) {\n  absl::flat_hash_set<TypeParam> set;\n\n  TypeParam foo1{/*value=*/1, /*noise=*/100};\n  TypeParam foo1_copy{/*value=*/1, /*noise=*/20};\n  TypeParam foo2{/*value=*/2, /*noise=*/100};\n\n  set.insert(foo1);\n\n  EXPECT_TRUE(set.contains(foo1_copy));\n  EXPECT_TRUE(set.contains(1));\n  EXPECT_FALSE(set.contains(foo2));\n  EXPECT_FALSE(set.contains(2));\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nenum Hash : size_t {\n  kStd = 0x1,  // std::hash\n#ifdef _MSC_VER\n  kExtension = kStd,  // In MSVC, std::hash == ::hash\n#else                 // _MSC_VER\n  kExtension = 0x2,  // ::hash (GCC extension)\n#endif                // _MSC_VER\n};\n\n// H is a bitmask of Hash enumerations.\n// Hashable<H> is hashable via all means specified in H.\ntemplate <int H>\nstruct Hashable {\n  static constexpr bool HashableBy(Hash h) { return h & H; }\n};\n\nnamespace std {\ntemplate <int H>\nstruct hash<Hashable<H>> {\n  template <class E = Hashable<H>,\n            class = typename std::enable_if<E::HashableBy(kStd)>::type>\n  size_t operator()(E) const {\n    return kStd;\n  }\n};\n}  // namespace std\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\ntemplate <class T>\nsize_t Hash(const T& v) {\n  return hash_default_hash<T>()(v);\n}\n\nTEST(Delegate, HashDispatch) {\n  EXPECT_EQ(Hash(kStd), Hash(Hashable<kStd>()));\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hash_generator_testing.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hash_generator_testing.h\"\n\n#include <algorithm>\n#include <deque>\n#include <random>\n#include <string>\n\n#include \"absl/base/no_destructor.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\nstd::string Generator<std::string>::operator()() const {\n  absl::InsecureBitGen gen;\n  // NOLINTNEXTLINE(runtime/int)\n  std::uniform_int_distribution<short> chars(0x20, 0x7E);\n  std::string res;\n  res.resize(32);\n  std::generate(res.begin(), res.end(), [&]() { return chars(gen); });\n  return res;\n}\n\nabsl::string_view Generator<absl::string_view>::operator()() const {\n  static absl::NoDestructor<std::deque<std::string>> arena;\n  absl::InsecureBitGen gen;\n  // NOLINTNEXTLINE(runtime/int)\n  std::uniform_int_distribution<short> chars(0x20, 0x7E);\n  arena->emplace_back();\n  auto& res = arena->back();\n  res.resize(32);\n  std::generate(res.begin(), res.end(), [&]() { return chars(gen); });\n  return res;\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hash_generator_testing.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Generates random values for testing. Specialized only for the few types we\n// care about.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_\n#define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_\n\n#include <stdint.h>\n\n#include <algorithm>\n#include <cassert>\n#include <iosfwd>\n#include <memory>\n#include <random>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace generator_internal {\n\ntemplate <class Container, class = void>\nstruct IsMap : std::false_type {};\n\ntemplate <class Map>\nstruct IsMap<Map, absl::void_t<typename Map::mapped_type>> : std::true_type {};\n\n}  // namespace generator_internal\n\nenum Enum : uint64_t {\n  kEnumEmpty,\n  kEnumDeleted,\n};\n\nenum class EnumClass : uint64_t {\n  kEmpty,\n  kDeleted,\n};\n\ninline std::ostream& operator<<(std::ostream& o, const EnumClass& ec) {\n  return o << static_cast<uint64_t>(ec);\n}\n\ntemplate <class T, class E = void>\nstruct Generator;\n\ntemplate <class T>\nstruct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> {\n  T operator()() const { return dist(gen); }\n  mutable absl::InsecureBitGen gen;\n  mutable std::uniform_int_distribution<T> dist;\n};\n\ntemplate <>\nstruct Generator<Enum> {\n  Enum operator()() const { return static_cast<Enum>(dist(gen)); }\n  mutable absl::InsecureBitGen gen;\n  mutable std::uniform_int_distribution<\n      typename std::underlying_type<Enum>::type>\n      dist;\n};\n\ntemplate <>\nstruct Generator<EnumClass> {\n  EnumClass operator()() const { return static_cast<EnumClass>(dist(gen)); }\n  mutable absl::InsecureBitGen gen;\n  mutable std::uniform_int_distribution<\n      typename std::underlying_type<EnumClass>::type>\n      dist;\n};\n\ntemplate <>\nstruct Generator<std::string> {\n  std::string operator()() const;\n};\n\ntemplate <>\nstruct Generator<absl::string_view> {\n  absl::string_view operator()() const;\n};\n\ntemplate <>\nstruct Generator<NonStandardLayout> {\n  NonStandardLayout operator()() const {\n    return NonStandardLayout(Generator<std::string>()());\n  }\n};\n\ntemplate <class K, class V>\nstruct Generator<std::pair<K, V>> {\n  std::pair<K, V> operator()() const {\n    return std::pair<K, V>(Generator<typename std::decay<K>::type>()(),\n                           Generator<typename std::decay<V>::type>()());\n  }\n};\n\ntemplate <class... Ts>\nstruct Generator<std::tuple<Ts...>> {\n  std::tuple<Ts...> operator()() const {\n    return std::tuple<Ts...>(Generator<typename std::decay<Ts>::type>()()...);\n  }\n};\n\ntemplate <class T>\nstruct Generator<std::unique_ptr<T>> {\n  std::unique_ptr<T> operator()() const {\n    return absl::make_unique<T>(Generator<T>()());\n  }\n};\n\ntemplate <class U>\nstruct Generator<U, absl::void_t<decltype(std::declval<U&>().key()),\n                                 decltype(std::declval<U&>().value())>>\n    : Generator<std::pair<\n          typename std::decay<decltype(std::declval<U&>().key())>::type,\n          typename std::decay<decltype(std::declval<U&>().value())>::type>> {};\n\ntemplate <class Container>\nusing GeneratedType =\n    decltype(std::declval<const Generator<typename std::conditional<\n                 generator_internal::IsMap<Container>::value,\n                 typename Container::value_type,\n                 typename Container::key_type>::type>&>()());\n\n// Naive wrapper that performs a linear search of previous values.\n// Beware this is O(SQR), which is reasonable for smaller kMaxValues.\ntemplate <class T, size_t kMaxValues = 64, class E = void>\nstruct UniqueGenerator {\n  Generator<T, E> gen;\n  std::vector<T> values;\n\n  T operator()() {\n    assert(values.size() < kMaxValues);\n    for (;;) {\n      T value = gen();\n      if (std::find(values.begin(), values.end(), value) == values.end()) {\n        values.push_back(value);\n        return value;\n      }\n    }\n  }\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_\n"
  },
  {
    "path": "absl/container/internal/hash_policy_testing.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Utilities to help tests verify that hash tables properly handle stateful\n// allocators and hash functions.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_\n#define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_\n\n#include <cstdlib>\n#include <limits>\n#include <memory>\n#include <ostream>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/hash/hash.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace hash_testing_internal {\n\ntemplate <class Derived>\nstruct WithId {\n  WithId() : id_(next_id<Derived>()) {}\n  WithId(const WithId& that) : id_(that.id_) {}\n  WithId(WithId&& that) : id_(that.id_) { that.id_ = 0; }\n  WithId& operator=(const WithId& that) {\n    id_ = that.id_;\n    return *this;\n  }\n  WithId& operator=(WithId&& that) {\n    id_ = that.id_;\n    that.id_ = 0;\n    return *this;\n  }\n\n  size_t id() const { return id_; }\n\n  friend bool operator==(const WithId& a, const WithId& b) {\n    return a.id_ == b.id_;\n  }\n  friend bool operator!=(const WithId& a, const WithId& b) { return !(a == b); }\n\n protected:\n  explicit WithId(size_t id) : id_(id) {}\n\n private:\n  size_t id_;\n\n  template <class T>\n  static size_t next_id() {\n    // 0 is reserved for moved from state.\n    static size_t gId = 1;\n    return gId++;\n  }\n};\n\n}  // namespace hash_testing_internal\n\nstruct NonStandardLayout {\n  NonStandardLayout() {}\n  explicit NonStandardLayout(std::string s) : value(std::move(s)) {}\n  virtual ~NonStandardLayout() {}\n\n  friend bool operator==(const NonStandardLayout& a,\n                         const NonStandardLayout& b) {\n    return a.value == b.value;\n  }\n  friend bool operator!=(const NonStandardLayout& a,\n                         const NonStandardLayout& b) {\n    return a.value != b.value;\n  }\n\n  template <typename H>\n  friend H AbslHashValue(H h, const NonStandardLayout& v) {\n    return H::combine(std::move(h), v.value);\n  }\n\n  std::string value;\n};\n\nstruct StatefulTestingHash\n    : absl::container_internal::hash_testing_internal::WithId<\n          StatefulTestingHash> {\n  template <class T>\n  size_t operator()(const T& t) const {\n    return absl::Hash<T>{}(t);\n  }\n};\n\nstruct StatefulTestingEqual\n    : absl::container_internal::hash_testing_internal::WithId<\n          StatefulTestingEqual> {\n  template <class T, class U>\n  bool operator()(const T& t, const U& u) const {\n    return t == u;\n  }\n};\n\n// It is expected that Alloc() == Alloc() for all allocators so we cannot use\n// WithId base. We need to explicitly assign ids.\ntemplate <class T = int>\nstruct Alloc : std::allocator<T> {\n  using propagate_on_container_swap = std::true_type;\n\n  // Using old paradigm for this to ensure compatibility.\n  //\n  // NOTE: As of 2025-05, this constructor cannot be explicit in order to work\n  // with the libstdc++ that ships with GCC15.\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  Alloc(size_t id = 0) : id_(id) {}\n\n  Alloc(const Alloc&) = default;\n  Alloc& operator=(const Alloc&) = default;\n\n  template <class U>\n  Alloc(const Alloc<U>& that) : std::allocator<T>(that), id_(that.id()) {}\n\n  template <class U>\n  struct rebind {\n    using other = Alloc<U>;\n  };\n\n  size_t id() const { return id_; }\n\n  friend bool operator==(const Alloc& a, const Alloc& b) {\n    return a.id_ == b.id_;\n  }\n  friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); }\n\n private:\n  size_t id_ = (std::numeric_limits<size_t>::max)();\n};\n\ntemplate <class Map>\nauto items(const Map& m) -> std::vector<\n    std::pair<typename Map::key_type, typename Map::mapped_type>> {\n  using std::get;\n  std::vector<std::pair<typename Map::key_type, typename Map::mapped_type>> res;\n  res.reserve(m.size());\n  for (const auto& v : m) res.emplace_back(get<0>(v), get<1>(v));\n  return res;\n}\n\ntemplate <class Set>\nauto keys(const Set& s)\n    -> std::vector<typename std::decay<typename Set::key_type>::type> {\n  std::vector<typename std::decay<typename Set::key_type>::type> res;\n  res.reserve(s.size());\n  for (const auto& v : s) res.emplace_back(v);\n  return res;\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_\n"
  },
  {
    "path": "absl/container/internal/hash_policy_testing_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hash_policy_testing.h\"\n\n#include \"gtest/gtest.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nTEST(_, Hash) {\n  StatefulTestingHash h1;\n  EXPECT_EQ(1, h1.id());\n  StatefulTestingHash h2;\n  EXPECT_EQ(2, h2.id());\n  StatefulTestingHash h1c(h1);\n  EXPECT_EQ(1, h1c.id());\n  StatefulTestingHash h2m(std::move(h2));\n  EXPECT_EQ(2, h2m.id());\n  EXPECT_EQ(0, h2.id());\n  StatefulTestingHash h3;\n  EXPECT_EQ(3, h3.id());\n  h3 = StatefulTestingHash();\n  EXPECT_EQ(4, h3.id());\n  h3 = std::move(h1);\n  EXPECT_EQ(1, h3.id());\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hash_policy_traits.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_\n#define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_\n\n#include <cstddef>\n#include <memory>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/container/internal/common_policy_traits.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// Defines how slots are initialized/destroyed/moved.\ntemplate <class Policy, class = void>\nstruct hash_policy_traits : common_policy_traits<Policy> {\n  // The type of the keys stored in the hashtable.\n  using key_type = typename Policy::key_type;\n\n private:\n  struct ReturnKey {\n    template <class Key,\n              absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>\n    static key_type& Impl(Key&& k, int) {\n      return *std::launder(\n          const_cast<key_type*>(std::addressof(std::forward<Key>(k))));\n    }\n\n    template <class Key>\n    static Key Impl(Key&& k, char) {\n      return std::forward<Key>(k);\n    }\n\n    // When Key=T&, we forward the lvalue reference.\n    // When Key=T, we return by value to avoid a dangling reference.\n    // eg, for string_hash_map.\n    template <class Key, class... Args>\n    auto operator()(Key&& k, const Args&...) const\n        -> decltype(Impl(std::forward<Key>(k), 0)) {\n      return Impl(std::forward<Key>(k), 0);\n    }\n  };\n\n  template <class P = Policy, class = void>\n  struct ConstantIteratorsImpl : std::false_type {};\n\n  template <class P>\n  struct ConstantIteratorsImpl<P, absl::void_t<typename P::constant_iterators>>\n      : P::constant_iterators {};\n\n public:\n  // The actual object stored in the hash table.\n  using slot_type = typename Policy::slot_type;\n\n  // The argument type for insertions into the hashtable. This is different\n  // from value_type for increased performance. See initializer_list constructor\n  // and insert() member functions for more details.\n  using init_type = typename Policy::init_type;\n\n  using reference = decltype(Policy::element(std::declval<slot_type*>()));\n  using pointer = typename std::remove_reference<reference>::type*;\n  using value_type = typename std::remove_reference<reference>::type;\n\n  // Policies can set this variable to tell raw_hash_set that all iterators\n  // should be constant, even `iterator`. This is useful for set-like\n  // containers.\n  // Defaults to false if not provided by the policy.\n  using constant_iterators = ConstantIteratorsImpl<>;\n\n  // Returns the amount of memory owned by `slot`, exclusive of `sizeof(*slot)`.\n  //\n  // If `slot` is nullptr, returns the constant amount of memory owned by any\n  // full slot or -1 if slots own variable amounts of memory.\n  //\n  // PRECONDITION: `slot` is INITIALIZED or nullptr\n  template <class P = Policy>\n  static size_t space_used(const slot_type* slot) {\n    return P::space_used(slot);\n  }\n\n  // Provides generalized access to the key for elements, both for elements in\n  // the table and for elements that have not yet been inserted (or even\n  // constructed).  We would like an API that allows us to say: `key(args...)`\n  // but we cannot do that for all cases, so we use this more general API that\n  // can be used for many things, including the following:\n  //\n  //   - Given an element in a table, get its key.\n  //   - Given an element initializer, get its key.\n  //   - Given `emplace()` arguments, get the element key.\n  //\n  // Implementations of this must adhere to a very strict technical\n  // specification around aliasing and consuming arguments:\n  //\n  // Let `value_type` be the result type of `element()` without ref- and\n  // cv-qualifiers. The first argument is a functor, the rest are constructor\n  // arguments for `value_type`. Returns `std::forward<F>(f)(k, xs...)`, where\n  // `k` is the element key, and `xs...` are the new constructor arguments for\n  // `value_type`. It's allowed for `k` to alias `xs...`, and for both to alias\n  // `ts...`. The key won't be touched once `xs...` are used to construct an\n  // element; `ts...` won't be touched at all, which allows `apply()` to consume\n  // any rvalues among them.\n  //\n  // If `value_type` is constructible from `Ts&&...`, `Policy::apply()` must not\n  // trigger a hard compile error unless it originates from `f`. In other words,\n  // `Policy::apply()` must be SFINAE-friendly. If `value_type` is not\n  // constructible from `Ts&&...`, either SFINAE or a hard compile error is OK.\n  //\n  // If `Ts...` is `[cv] value_type[&]` or `[cv] init_type[&]`,\n  // `Policy::apply()` must work. A compile error is not allowed, SFINAE or not.\n  template <class F, class... Ts, class P = Policy>\n  static auto apply(F&& f, Ts&&... ts)\n      -> decltype(P::apply(std::forward<F>(f), std::forward<Ts>(ts)...)) {\n    return P::apply(std::forward<F>(f), std::forward<Ts>(ts)...);\n  }\n\n  // Returns the \"key\" portion of the slot.\n  // Used for node handle manipulation.\n  template <class P = Policy>\n  static auto mutable_key(slot_type* slot)\n      -> decltype(P::apply(ReturnKey(), hash_policy_traits::element(slot))) {\n    return P::apply(ReturnKey(), hash_policy_traits::element(slot));\n  }\n\n  // Returns the \"value\" (as opposed to the \"key\") portion of the element. Used\n  // by maps to implement `operator[]`, `at()` and `insert_or_assign()`.\n  template <class T, class P = Policy>\n  static auto value(T* elem) -> decltype(P::value(elem)) {\n    return P::value(elem);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n// get_hash_slot_fn may return nullptr to signal that non type erased function\n// should be used. GCC warns against comparing function address with nullptr.\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n// silent error: the address of * will never be NULL [-Werror=address]\n#pragma GCC diagnostic ignored \"-Waddress\"\n#endif\n    return Policy::template get_hash_slot_fn<Hash, kIsDefault>() == nullptr\n               ? &hash_slot_fn_non_type_erased<Hash, kIsDefault>\n               : Policy::template get_hash_slot_fn<Hash, kIsDefault>();\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n  }\n\n  // Whether small object optimization is enabled. True by default.\n  static constexpr bool soo_enabled() { return soo_enabled_impl(Rank1{}); }\n\n private:\n  template <class Hash, bool kIsDefault>\n  static size_t hash_slot_fn_non_type_erased(const void* hash_fn, void* slot,\n                                             size_t seed) {\n    return Policy::apply(\n        HashElement<Hash, kIsDefault>{*static_cast<const Hash*>(hash_fn), seed},\n        Policy::element(static_cast<slot_type*>(slot)));\n  }\n\n  // Use go/ranked-overloads for dispatching. Rank1 is preferred.\n  struct Rank0 {};\n  struct Rank1 : Rank0 {};\n\n  // Use auto -> decltype as an enabler.\n  template <class P = Policy>\n  static constexpr auto soo_enabled_impl(Rank1) -> decltype(P::soo_enabled()) {\n    return P::soo_enabled();\n  }\n\n  static constexpr bool soo_enabled_impl(Rank0) { return true; }\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_\n"
  },
  {
    "path": "absl/container/internal/hash_policy_traits_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hash_policy_traits.h\"\n\n#include <cstddef>\n#include <functional>\n#include <memory>\n#include <new>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/container_memory.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::MockFunction;\nusing ::testing::Return;\nusing ::testing::ReturnRef;\n\nusing Alloc = std::allocator<int>;\nusing Slot = int;\n\nstruct PolicyWithoutOptionalOps {\n  using slot_type = Slot;\n  using key_type = Slot;\n  using init_type = Slot;\n\n  static std::function<Slot&(Slot*)> element;\n  static int apply(int v) { return apply_impl(v); }\n  static std::function<int(int)> apply_impl;\n  static std::function<Slot&(Slot*)> value;\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\nstd::function<int(int)> PolicyWithoutOptionalOps::apply_impl;\nstd::function<Slot&(Slot*)> PolicyWithoutOptionalOps::value;\n\nstruct Test : ::testing::Test {\n  Test() {\n    PolicyWithoutOptionalOps::apply_impl = [&](int a1) -> int {\n      return apply.Call(a1);\n    };\n    PolicyWithoutOptionalOps::value = [&](Slot* a1) -> Slot& {\n      return value.Call(a1);\n    };\n  }\n\n  std::allocator<int> alloc;\n  int a = 53;\n  MockFunction<int(int)> apply;\n  MockFunction<Slot&(Slot*)> value;\n};\n\nTEST_F(Test, apply) {\n  EXPECT_CALL(apply, Call(42)).WillOnce(Return(1337));\n  EXPECT_EQ(1337, (hash_policy_traits<PolicyWithoutOptionalOps>::apply(42)));\n}\n\nTEST_F(Test, value) {\n  int b = 0;\n  EXPECT_CALL(value, Call(&a)).WillOnce(ReturnRef(b));\n  EXPECT_EQ(&b, &hash_policy_traits<PolicyWithoutOptionalOps>::value(&a));\n}\n\nstruct Hash {\n  size_t operator()(Slot a) const { return static_cast<size_t>(a) * 5; }\n};\n\nstruct PolicyNoHashFn {\n  using slot_type = Slot;\n  using key_type = Slot;\n  using init_type = Slot;\n\n  static size_t* apply_called_count;\n\n  static Slot& element(Slot* slot) { return *slot; }\n  template <typename Fn>\n  static size_t apply(const Fn& fn, int v) {\n    ++(*apply_called_count);\n    return fn(v);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\nsize_t* PolicyNoHashFn::apply_called_count;\n\nstruct PolicyCustomHashFn : PolicyNoHashFn {\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return &TypeErasedApplyToSlotFn<Hash, int, kIsDefault>;\n  }\n};\n\nTEST(HashTest, PolicyNoHashFn_get_hash_slot_fn) {\n  size_t apply_called_count = 0;\n  PolicyNoHashFn::apply_called_count = &apply_called_count;\n\n  Hash hasher;\n  Slot value = 7;\n  auto* fn = hash_policy_traits<PolicyNoHashFn>::get_hash_slot_fn<\n      Hash, /*kIsDefault=*/false>();\n  EXPECT_NE(fn, nullptr);\n  EXPECT_EQ(fn(&hasher, &value, 100),\n            (HashElement<Hash, /*kIsDefault=*/false>(hasher, 100)(value)));\n  EXPECT_EQ(apply_called_count, 1);\n}\n\nTEST(HashTest, PolicyCustomHashFn_get_hash_slot_fn) {\n  size_t apply_called_count = 0;\n  PolicyNoHashFn::apply_called_count = &apply_called_count;\n\n  Hash hasher;\n  Slot value = 7;\n  auto* fn = hash_policy_traits<PolicyCustomHashFn>::get_hash_slot_fn<\n      Hash, /*kIsDefault=*/false>();\n  EXPECT_EQ(\n      fn, (PolicyCustomHashFn::get_hash_slot_fn<Hash, /*kIsDefault=*/false>()));\n  EXPECT_EQ(fn(&hasher, &value, 100),\n            (HashElement<Hash, /*kIsDefault=*/false>(hasher, 100)(value)));\n  EXPECT_EQ(apply_called_count, 0);\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hashtable_control_bytes.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file contains the implementation of the hashtable control bytes\n// manipulation.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_CONTROL_BYTES_H_\n#define ABSL_CONTAINER_INTERNAL_HASHTABLE_CONTROL_BYTES_H_\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_SSE2\n#include <emmintrin.h>\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_SSSE3\n#include <tmmintrin.h>\n#endif\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_ARM_NEON\n#include <arm_neon.h>\n#endif\n\n#include \"absl/base/optimization.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/base/internal/endian.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n#ifdef ABSL_SWISSTABLE_ASSERT\n#error ABSL_SWISSTABLE_ASSERT cannot be directly set\n#else\n// We use this macro for assertions that users may see when the table is in an\n// invalid state that sanitizers may help diagnose.\n#define ABSL_SWISSTABLE_ASSERT(CONDITION) \\\n  assert((CONDITION) && \"Try enabling sanitizers.\")\n#endif\n\n\ntemplate <typename T>\nuint32_t TrailingZeros(T x) {\n  ABSL_ASSUME(x != 0);\n  return static_cast<uint32_t>(countr_zero(x));\n}\n\n// 8 bytes bitmask with most significant bit set for every byte.\nconstexpr uint64_t kMsbs8Bytes = 0x8080808080808080ULL;\n// 8 kEmpty bytes that is useful for small table initialization.\nconstexpr uint64_t k8EmptyBytes = kMsbs8Bytes;\n\n// An abstract bitmask, such as that emitted by a SIMD instruction.\n//\n// Specifically, this type implements a simple bitset whose representation is\n// controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number\n// of abstract bits in the bitset, while `Shift` is the log-base-two of the\n// width of an abstract bit in the representation.\n// This mask provides operations for any number of real bits set in an abstract\n// bit. To add iteration on top of that, implementation must guarantee no more\n// than the most significant real bit is set in a set abstract bit.\ntemplate <class T, int SignificantBits, int Shift = 0>\nclass NonIterableBitMask {\n public:\n  explicit NonIterableBitMask(T mask) : mask_(mask) {}\n\n  explicit operator bool() const { return mask_ != 0; }\n\n  // Returns the index of the lowest *abstract* bit set in `self`.\n  uint32_t LowestBitSet() const {\n    return container_internal::TrailingZeros(mask_) >> Shift;\n  }\n\n  // Returns the number of trailing zero *abstract* bits.\n  uint32_t TrailingZeros() const {\n    return container_internal::TrailingZeros(mask_) >> Shift;\n  }\n\n  // Returns the number of leading zero *abstract* bits.\n  uint32_t LeadingZeros() const {\n    constexpr int total_significant_bits = SignificantBits << Shift;\n    constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;\n    return static_cast<uint32_t>(\n               countl_zero(static_cast<T>(mask_ << extra_bits))) >>\n           Shift;\n  }\n\n  T mask_;\n};\n\n// Mask that can be iterable\n//\n// For example, when `SignificantBits` is 16 and `Shift` is zero, this is just\n// an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When\n// `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as\n// the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.\n// If NullifyBitsOnIteration is true (only allowed for Shift == 3),\n// non zero abstract bit is allowed to have additional bits\n// (e.g., `0xff`, `0x83` and `0x9c` are ok, but `0x6f` is not).\n//\n// For example:\n//   for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2\n//   for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3\ntemplate <class T, int SignificantBits, int Shift = 0,\n          bool NullifyBitsOnIteration = false>\nclass BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {\n  using Base = NonIterableBitMask<T, SignificantBits, Shift>;\n  static_assert(std::is_unsigned<T>::value, \"\");\n  static_assert(Shift == 0 || Shift == 3, \"\");\n  static_assert(!NullifyBitsOnIteration || Shift == 3, \"\");\n\n public:\n  explicit BitMask(T mask) : Base(mask) {\n    if (Shift == 3 && !NullifyBitsOnIteration) {\n      ABSL_SWISSTABLE_ASSERT(this->mask_ == (this->mask_ & kMsbs8Bytes));\n    }\n  }\n  // BitMask is an iterator over the indices of its abstract bits.\n  using value_type = int;\n  using iterator = BitMask;\n  using const_iterator = BitMask;\n\n  BitMask& operator++() {\n    if (Shift == 3 && NullifyBitsOnIteration) {\n      this->mask_ &= kMsbs8Bytes;\n    }\n    this->mask_ &= (this->mask_ - 1);\n    return *this;\n  }\n\n  uint32_t operator*() const { return Base::LowestBitSet(); }\n\n  BitMask begin() const { return *this; }\n  BitMask end() const { return BitMask(0); }\n\n private:\n  friend bool operator==(const BitMask& a, const BitMask& b) {\n    return a.mask_ == b.mask_;\n  }\n  friend bool operator!=(const BitMask& a, const BitMask& b) {\n    return a.mask_ != b.mask_;\n  }\n};\n\nusing h2_t = uint8_t;\n\n// The values here are selected for maximum performance. See the static asserts\n// below for details.\n\n// A `ctrl_t` is a single control byte, which can have one of four\n// states: empty, deleted, full (which has an associated seven-bit h2_t value)\n// and the sentinel. They have the following bit patterns:\n//\n//      empty: 1 0 0 0 0 0 0 0\n//    deleted: 1 1 1 1 1 1 1 0\n//       full: 0 h h h h h h h  // h represents the hash bits.\n//   sentinel: 1 1 1 1 1 1 1 1\n//\n// These values are specifically tuned for SSE-flavored SIMD.\n// The static_asserts below detail the source of these choices.\n//\n// We use an enum class so that when strict aliasing is enabled, the compiler\n// knows ctrl_t doesn't alias other types.\nenum class ctrl_t : int8_t {\n  kEmpty = -128,   // 0b10000000\n  kDeleted = -2,   // 0b11111110\n  kSentinel = -1,  // 0b11111111\n};\nstatic_assert(\n    (static_cast<int8_t>(ctrl_t::kEmpty) &\n     static_cast<int8_t>(ctrl_t::kDeleted) &\n     static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,\n    \"Special markers need to have the MSB to make checking for them efficient\");\nstatic_assert(\n    ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,\n    \"ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than \"\n    \"ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient\");\nstatic_assert(\n    ctrl_t::kSentinel == static_cast<ctrl_t>(-1),\n    \"ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD \"\n    \"registers (pcmpeqd xmm, xmm)\");\nstatic_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),\n              \"ctrl_t::kEmpty must be -128 to make the SIMD check for its \"\n              \"existence efficient (psignb xmm, xmm)\");\nstatic_assert(\n    (~static_cast<int8_t>(ctrl_t::kEmpty) &\n     ~static_cast<int8_t>(ctrl_t::kDeleted) &\n     static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,\n    \"ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not \"\n    \"shared by ctrl_t::kSentinel to make the scalar test for \"\n    \"MaskEmptyOrDeleted() efficient\");\nstatic_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),\n              \"ctrl_t::kDeleted must be -2 to make the implementation of \"\n              \"ConvertSpecialToEmptyAndFullToDeleted efficient\");\nstatic_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),\n              \"ctrl_t::kEmpty must be -128 to use saturated subtraction in\"\n              \" ConvertSpecialToEmptyAndFullToDeleted\");\n\n// Helpers for checking the state of a control byte.\ninline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }\ninline bool IsFull(ctrl_t c) {\n  // Cast `c` to the underlying type instead of casting `0` to `ctrl_t` as `0`\n  // is not a value in the enum. Both ways are equivalent, but this way makes\n  // linters happier.\n  return static_cast<std::underlying_type_t<ctrl_t>>(c) >= 0;\n}\ninline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }\ninline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }\n\n#ifdef ABSL_INTERNAL_HAVE_SSE2\n// Quick reference guide for intrinsics used below:\n//\n// * __m128i: An XMM (128-bit) word.\n//\n// * _mm_setzero_si128: Returns a zero vector.\n// * _mm_set1_epi8:     Returns a vector with the same i8 in each lane.\n//\n// * _mm_subs_epi8:    Saturating-subtracts two i8 vectors.\n// * _mm_and_si128:    Ands two i128s together.\n// * _mm_or_si128:     Ors two i128s together.\n// * _mm_andnot_si128: And-nots two i128s together.\n//\n// * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,\n//                   filling each lane with 0x00 or 0xff.\n// * _mm_cmpgt_epi8: Same as above, but using > rather than ==.\n//\n// * _mm_loadu_si128:  Performs an unaligned load of an i128.\n// * _mm_storeu_si128: Performs an unaligned store of an i128.\n//\n// * _mm_sign_epi8:     Retains, negates, or zeroes each i8 lane of the first\n//                      argument if the corresponding lane of the second\n//                      argument is positive, negative, or zero, respectively.\n// * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a\n//                      bitmask consisting of those bits.\n// * _mm_shuffle_epi8:  Selects i8s from the first argument, using the low\n//                      four bits of each i8 lane in the second argument as\n//                      indices.\n\n// https://github.com/abseil/abseil-cpp/issues/209\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853\n// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char\n// Work around this by using the portable implementation of Group\n// when using -funsigned-char under GCC.\ninline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {\n#if defined(__GNUC__) && !defined(__clang__)\n  if (std::is_unsigned<char>::value) {\n    const __m128i mask = _mm_set1_epi8(0x80);\n    const __m128i diff = _mm_subs_epi8(b, a);\n    return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);\n  }\n#endif\n  return _mm_cmpgt_epi8(a, b);\n}\n\nstruct GroupSse2Impl {\n  static constexpr size_t kWidth = 16;  // the number of slots per group\n  // There are only 16 bits, but using uint32_t instead of uint16_t allows for\n  // better codegen. In particular, there is no blsr instruction for a 16 bit\n  // register, but there is for a 32 bit register (used in BitMask::operator++).\n  using MaskInt = uint32_t;\n  using BitMaskType = BitMask<MaskInt, kWidth>;\n  using NonIterableBitMaskType = NonIterableBitMask<MaskInt, kWidth>;\n\n  explicit GroupSse2Impl(const ctrl_t* pos) {\n    ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));\n  }\n\n  // Returns a bitmask representing the positions of slots that match hash.\n  BitMaskType Match(h2_t hash) const {\n    auto match = _mm_set1_epi8(static_cast<char>(hash));\n    return BitMaskType(MoveMask(_mm_cmpeq_epi8(match, ctrl)));\n  }\n\n  // Returns a bitmask representing the positions of empty slots.\n  NonIterableBitMaskType MaskEmpty() const {\n#ifdef ABSL_INTERNAL_HAVE_SSSE3\n    // This only works because ctrl_t::kEmpty is -128.\n    return NonIterableBitMaskType(MoveMask(_mm_sign_epi8(ctrl, ctrl)));\n#else\n    auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));\n    return NonIterableBitMaskType(MoveMask(_mm_cmpeq_epi8(match, ctrl)));\n#endif\n  }\n\n  // Returns a bitmask representing the positions of full slots.\n  // Note: for `is_small()` tables group may contain the \"same\" slot twice:\n  // original and mirrored.\n  BitMaskType MaskFull() const { return BitMaskType(MoveMask(ctrl) ^ 0xffff); }\n\n  // Returns a bitmask representing the positions of non full slots.\n  // Note: this includes: kEmpty, kDeleted, kSentinel.\n  // It is useful in contexts when kSentinel is not present.\n  auto MaskNonFull() const { return BitMaskType(MoveMask(ctrl)); }\n\n  // Returns a bitmask representing the positions of empty or deleted slots.\n  NonIterableBitMaskType MaskEmptyOrDeleted() const {\n    auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));\n    return NonIterableBitMaskType(\n        MoveMask(_mm_cmpgt_epi8_fixed(special, ctrl)));\n  }\n\n  // Returns a bitmask representing the positions of full or sentinel slots.\n  // Note: for `is_small()` tables group may contain the \"same\" slot twice:\n  // original and mirrored.\n  NonIterableBitMaskType MaskFullOrSentinel() const {\n    auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel) - 1);\n    return NonIterableBitMaskType(\n        MoveMask(_mm_cmpgt_epi8_fixed(ctrl, special)));\n  }\n\n  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {\n    // Take advantage of the fact that kEmpty is already the smallest signed\n    // char value, and using a saturated subtraction will not affect it.\n    // All special values have the MSB set, so after an AND with MSBS, we\n    // are left with -128 for special values and 0 for full. After applying\n    // subs 2, we arrive at the result of -128(kEmpty) for special and\n    // -2(kDeleted) for full.\n    auto msbs = _mm_set1_epi8(static_cast<char>(-128));\n    auto twos = _mm_set1_epi8(static_cast<char>(2));\n    auto res = _mm_subs_epi8(_mm_and_si128(msbs, ctrl), twos);\n    _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);\n  }\n\n  static MaskInt MoveMask(__m128i xmm) {\n    auto mask = static_cast<MaskInt>(_mm_movemask_epi8(xmm));\n#ifdef __clang__\n    // TODO(b/472522597): Without the inline asm, clang ends up generating an\n    // unnecessary movzx to zero the upper bits of the output, but those bits\n    // are already zero. See https://godbolt.org/z/G6xW1Ecbx.\n    asm(\"\" : \"+r\"(mask));  // NOLINT\n#endif\n    return mask;\n  }\n\n  __m128i ctrl;\n};\n#endif  // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2\n\n#if defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)\nstruct GroupAArch64Impl {\n  static constexpr size_t kWidth = 8;\n  using BitMaskType = BitMask<uint64_t, kWidth, /*Shift=*/3,\n                              /*NullifyBitsOnIteration=*/true>;\n  using NonIterableBitMaskType =\n      NonIterableBitMask<uint64_t, kWidth, /*Shift=*/3>;\n\n  explicit GroupAArch64Impl(const ctrl_t* pos) {\n    ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));\n  }\n\n  auto Match(h2_t hash) const {\n    uint8x8_t dup = vdup_n_u8(hash);\n    auto mask = vceq_u8(ctrl, dup);\n    return BitMaskType(vget_lane_u64(vreinterpret_u64_u8(mask), 0));\n  }\n\n  auto MaskEmpty() const {\n    uint64_t mask =\n        vget_lane_u64(vreinterpret_u64_u8(vceq_s8(\n                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),\n                          vreinterpret_s8_u8(ctrl))),\n                      0);\n    return NonIterableBitMaskType(mask);\n  }\n\n  // Returns a bitmask representing the positions of full slots.\n  // Note: for `is_small()` tables group may contain the \"same\" slot twice:\n  // original and mirrored.\n  auto MaskFull() const {\n    uint64_t mask = vget_lane_u64(\n        vreinterpret_u64_u8(vcge_s8(vreinterpret_s8_u8(ctrl),\n                                    vdup_n_s8(static_cast<int8_t>(0)))),\n        0);\n    return BitMaskType(mask);\n  }\n\n  // Returns a bitmask representing the positions of non full slots.\n  // Note: this includes: kEmpty, kDeleted, kSentinel.\n  // It is useful in contexts when kSentinel is not present.\n  auto MaskNonFull() const {\n    uint64_t mask = vget_lane_u64(\n        vreinterpret_u64_u8(vclt_s8(vreinterpret_s8_u8(ctrl),\n                                    vdup_n_s8(static_cast<int8_t>(0)))),\n        0);\n    return BitMaskType(mask);\n  }\n\n  auto MaskEmptyOrDeleted() const {\n    uint64_t mask =\n        vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(\n                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),\n                          vreinterpret_s8_u8(ctrl))),\n                      0);\n    return NonIterableBitMaskType(mask);\n  }\n\n  NonIterableBitMaskType MaskFullOrSentinel() const {\n    uint64_t mask = vget_lane_u64(\n        vreinterpret_u64_u8(\n            vcgt_s8(vreinterpret_s8_u8(ctrl),\n                    vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel) - 1))),\n        0);\n    return NonIterableBitMaskType(mask);\n  }\n\n  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {\n    uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);\n    constexpr uint64_t slsbs = 0x0202020202020202ULL;\n    constexpr uint64_t midbs = 0x7e7e7e7e7e7e7e7eULL;\n    auto x = slsbs & (mask >> 6);\n    auto res = (x + midbs) | kMsbs8Bytes;\n    little_endian::Store64(dst, res);\n  }\n\n  uint8x8_t ctrl;\n};\n#endif  // ABSL_INTERNAL_HAVE_ARM_NEON && ABSL_IS_LITTLE_ENDIAN\n\nstruct GroupPortableImpl {\n  static constexpr size_t kWidth = 8;\n  using BitMaskType = BitMask<uint64_t, kWidth, /*Shift=*/3,\n                              /*NullifyBitsOnIteration=*/false>;\n  using NonIterableBitMaskType =\n      NonIterableBitMask<uint64_t, kWidth, /*Shift=*/3>;\n\n  explicit GroupPortableImpl(const ctrl_t* pos)\n      : ctrl(little_endian::Load64(pos)) {}\n\n  BitMaskType Match(h2_t hash) const {\n    // For the technique, see:\n    // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord\n    // (Determine if a word has a byte equal to n).\n    //\n    // Caveat: there are false positives but:\n    // - they only occur if there is a real match\n    // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel\n    // - they will be handled gracefully by subsequent checks in code\n    //\n    // Example:\n    //   v = 0x1716151413121110\n    //   hash = 0x12\n    //   retval = (v - lsbs) & ~v & msbs = 0x0000000080800000\n    constexpr uint64_t lsbs = 0x0101010101010101ULL;\n    auto x = ctrl ^ (lsbs * hash);\n    return BitMaskType((x - lsbs) & ~x & kMsbs8Bytes);\n  }\n\n  auto MaskEmpty() const {\n    return NonIterableBitMaskType((ctrl & ~(ctrl << 6)) & kMsbs8Bytes);\n  }\n\n  // Returns a bitmask representing the positions of full slots.\n  // Note: for `is_small()` tables group may contain the \"same\" slot twice:\n  // original and mirrored.\n  auto MaskFull() const {\n    return BitMaskType((ctrl ^ kMsbs8Bytes) & kMsbs8Bytes);\n  }\n\n  // Returns a bitmask representing the positions of non full slots.\n  // Note: this includes: kEmpty, kDeleted, kSentinel.\n  // It is useful in contexts when kSentinel is not present.\n  auto MaskNonFull() const { return BitMaskType(ctrl & kMsbs8Bytes); }\n\n  auto MaskEmptyOrDeleted() const {\n    return NonIterableBitMaskType((ctrl & ~(ctrl << 7)) & kMsbs8Bytes);\n  }\n\n  auto MaskFullOrSentinel() const {\n    return NonIterableBitMaskType((~ctrl | (ctrl << 7)) & kMsbs8Bytes);\n  }\n\n  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {\n    constexpr uint64_t lsbs = 0x0101010101010101ULL;\n    auto x = ctrl & kMsbs8Bytes;\n    auto res = (~x + (x >> 7)) & ~lsbs;\n    little_endian::Store64(dst, res);\n  }\n\n  uint64_t ctrl;\n};\n\n#ifdef ABSL_INTERNAL_HAVE_SSE2\nusing Group = GroupSse2Impl;\nusing GroupFullEmptyOrDeleted = GroupSse2Impl;\n#elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)\nusing Group = GroupAArch64Impl;\n// For Aarch64, we use the portable implementation for counting and masking\n// full, empty or deleted group elements. This is to avoid the latency of moving\n// between data GPRs and Neon registers when it does not provide a benefit.\n// Using Neon is profitable when we call Match(), but is not when we don't,\n// which is the case when we do *EmptyOrDeleted and MaskFull operations.\n// It is difficult to make a similar approach beneficial on other architectures\n// such as x86 since they have much lower GPR <-> vector register transfer\n// latency and 16-wide Groups.\nusing GroupFullEmptyOrDeleted = GroupPortableImpl;\n#else\nusing Group = GroupPortableImpl;\nusing GroupFullEmptyOrDeleted = GroupPortableImpl;\n#endif\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_SWISSTABLE_ASSERT\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLE_CONTROL_BYTES_H_\n"
  },
  {
    "path": "absl/container/internal/hashtable_control_bytes_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hashtable_control_bytes.h\"\n\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::ElementsAreArray;\n\n// Convenience function to static cast to ctrl_t.\nctrl_t CtrlT(int i) { return static_cast<ctrl_t>(i); }\n\nTEST(BitMask, Smoke) {\n  EXPECT_FALSE((BitMask<uint8_t, 8>(0)));\n  EXPECT_TRUE((BitMask<uint8_t, 8>(5)));\n\n  EXPECT_THAT((BitMask<uint8_t, 8>(0)), ElementsAre());\n  EXPECT_THAT((BitMask<uint8_t, 8>(0x1)), ElementsAre(0));\n  EXPECT_THAT((BitMask<uint8_t, 8>(0x2)), ElementsAre(1));\n  EXPECT_THAT((BitMask<uint8_t, 8>(0x3)), ElementsAre(0, 1));\n  EXPECT_THAT((BitMask<uint8_t, 8>(0x4)), ElementsAre(2));\n  EXPECT_THAT((BitMask<uint8_t, 8>(0x5)), ElementsAre(0, 2));\n  EXPECT_THAT((BitMask<uint8_t, 8>(0x55)), ElementsAre(0, 2, 4, 6));\n  EXPECT_THAT((BitMask<uint8_t, 8>(0xAA)), ElementsAre(1, 3, 5, 7));\n}\n\nTEST(BitMask, WithShift_MatchPortable) {\n  // See the non-SSE version of Group for details on what this math is for.\n  uint64_t ctrl = 0x1716151413121110;\n  uint64_t hash = 0x12;\n  constexpr uint64_t lsbs = 0x0101010101010101ULL;\n  auto x = ctrl ^ (lsbs * hash);\n  uint64_t mask = (x - lsbs) & ~x & kMsbs8Bytes;\n  EXPECT_EQ(0x0000000080800000, mask);\n\n  BitMask<uint64_t, 8, 3> b(mask);\n  EXPECT_EQ(*b, 2);\n}\n\nconstexpr uint64_t kSome8BytesMask = /*  */ 0x8000808080008000ULL;\nconstexpr uint64_t kSome8BytesMaskAllOnes = 0xff00ffffff00ff00ULL;\nconstexpr auto kSome8BytesMaskBits = std::array<int, 5>{1, 3, 4, 5, 7};\n\nTEST(BitMask, WithShift_FullMask) {\n  EXPECT_THAT((BitMask<uint64_t, 8, 3>(kMsbs8Bytes)),\n              ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));\n  EXPECT_THAT(\n      (BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(kMsbs8Bytes)),\n      ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));\n  EXPECT_THAT(\n      (BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(~uint64_t{0})),\n      ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));\n}\n\nTEST(BitMask, WithShift_EmptyMask) {\n  EXPECT_THAT((BitMask<uint64_t, 8, 3>(0)), ElementsAre());\n  EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(0)),\n              ElementsAre());\n}\n\nTEST(BitMask, WithShift_SomeMask) {\n  EXPECT_THAT((BitMask<uint64_t, 8, 3>(kSome8BytesMask)),\n              ElementsAreArray(kSome8BytesMaskBits));\n  EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(\n                  kSome8BytesMask)),\n              ElementsAreArray(kSome8BytesMaskBits));\n  EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(\n                  kSome8BytesMaskAllOnes)),\n              ElementsAreArray(kSome8BytesMaskBits));\n}\n\nTEST(BitMask, WithShift_SomeMaskExtraBitsForNullify) {\n  // Verify that adding extra bits into non zero bytes is fine.\n  uint64_t extra_bits = 77;\n  for (int i = 0; i < 100; ++i) {\n    // Add extra bits, but keep zero bytes untouched.\n    uint64_t extra_mask = extra_bits & kSome8BytesMaskAllOnes;\n    EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(\n                    kSome8BytesMask | extra_mask)),\n                ElementsAreArray(kSome8BytesMaskBits))\n        << i << \" \" << extra_mask;\n    extra_bits = (extra_bits + 1) * 3;\n  }\n}\n\nTEST(BitMask, LeadingTrailing) {\n  EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).LeadingZeros()), 3);\n  EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).TrailingZeros()), 6);\n\n  EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).LeadingZeros()), 15);\n  EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).TrailingZeros()), 0);\n\n  EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).LeadingZeros()), 0);\n  EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).TrailingZeros()), 15);\n\n  EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).LeadingZeros()), 3);\n  EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).TrailingZeros()), 1);\n\n  EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000000000000080).LeadingZeros()), 7);\n  EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000000000000080).TrailingZeros()), 0);\n\n  EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x8000000000000000).LeadingZeros()), 0);\n  EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x8000000000000000).TrailingZeros()), 7);\n}\n\ntemplate <class GroupTypeParam>\nclass GroupTest : public testing::Test {};\nusing GroupTypes =\n    ::testing::Types<Group, GroupPortableImpl, GroupFullEmptyOrDeleted>;\nTYPED_TEST_SUITE(GroupTest, GroupTypes);\n\nTYPED_TEST(GroupTest, Match) {\n  using GroupType = TypeParam;\n  if (GroupType::kWidth == 16) {\n    ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted,  CtrlT(3),\n                      ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),\n                      CtrlT(7),       CtrlT(5), CtrlT(3),          CtrlT(1),\n                      CtrlT(1),       CtrlT(1), CtrlT(1),          CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.Match(0), ElementsAre());\n    EXPECT_THAT(GroupType{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));\n    EXPECT_THAT(GroupType{group}.Match(3), ElementsAre(3, 10));\n    EXPECT_THAT(GroupType{group}.Match(5), ElementsAre(5, 9));\n    EXPECT_THAT(GroupType{group}.Match(7), ElementsAre(7, 8));\n  } else if (GroupType::kWidth == 8) {\n    ctrl_t group[] = {ctrl_t::kEmpty,    CtrlT(1), CtrlT(2),\n                      ctrl_t::kDeleted,  CtrlT(2), CtrlT(1),\n                      ctrl_t::kSentinel, CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.Match(0), ElementsAre());\n    EXPECT_THAT(GroupType{group}.Match(1), ElementsAre(1, 5, 7));\n    EXPECT_THAT(GroupType{group}.Match(2), ElementsAre(2, 4));\n  } else {\n    FAIL() << \"No test coverage for Group::kWidth==\" << GroupType::kWidth;\n  }\n}\n\nTYPED_TEST(GroupTest, MaskEmpty) {\n  using GroupType = TypeParam;\n  if (GroupType::kWidth == 16) {\n    ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted,  CtrlT(3),\n                      ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),\n                      CtrlT(7),       CtrlT(5), CtrlT(3),          CtrlT(1),\n                      CtrlT(1),       CtrlT(1), CtrlT(1),          CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskEmpty().LowestBitSet(), 0);\n  } else if (GroupType::kWidth == 8) {\n    ctrl_t group[] = {ctrl_t::kEmpty,    CtrlT(1), CtrlT(2),\n                      ctrl_t::kDeleted,  CtrlT(2), CtrlT(1),\n                      ctrl_t::kSentinel, CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskEmpty().LowestBitSet(), 0);\n  } else {\n    FAIL() << \"No test coverage for Group::kWidth==\" << GroupType::kWidth;\n  }\n}\n\nTYPED_TEST(GroupTest, MaskFull) {\n  using GroupType = TypeParam;\n  if (GroupType::kWidth == 16) {\n    ctrl_t group[] = {\n        ctrl_t::kEmpty, CtrlT(1),          ctrl_t::kDeleted,  CtrlT(3),\n        ctrl_t::kEmpty, CtrlT(5),          ctrl_t::kSentinel, CtrlT(7),\n        CtrlT(7),       CtrlT(5),          ctrl_t::kDeleted,  CtrlT(1),\n        CtrlT(1),       ctrl_t::kSentinel, ctrl_t::kEmpty,    CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskFull(),\n                ElementsAre(1, 3, 5, 7, 8, 9, 11, 12, 15));\n  } else if (GroupType::kWidth == 8) {\n    ctrl_t group[] = {ctrl_t::kEmpty,    CtrlT(1), ctrl_t::kEmpty,\n                      ctrl_t::kDeleted,  CtrlT(2), ctrl_t::kSentinel,\n                      ctrl_t::kSentinel, CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskFull(), ElementsAre(1, 4, 7));\n  } else {\n    FAIL() << \"No test coverage for Group::kWidth==\" << GroupType::kWidth;\n  }\n}\n\nTYPED_TEST(GroupTest, MaskNonFull) {\n  using GroupType = TypeParam;\n  if (GroupType::kWidth == 16) {\n    ctrl_t group[] = {\n        ctrl_t::kEmpty, CtrlT(1),          ctrl_t::kDeleted,  CtrlT(3),\n        ctrl_t::kEmpty, CtrlT(5),          ctrl_t::kSentinel, CtrlT(7),\n        CtrlT(7),       CtrlT(5),          ctrl_t::kDeleted,  CtrlT(1),\n        CtrlT(1),       ctrl_t::kSentinel, ctrl_t::kEmpty,    CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskNonFull(),\n                ElementsAre(0, 2, 4, 6, 10, 13, 14));\n  } else if (GroupType::kWidth == 8) {\n    ctrl_t group[] = {ctrl_t::kEmpty,    CtrlT(1), ctrl_t::kEmpty,\n                      ctrl_t::kDeleted,  CtrlT(2), ctrl_t::kSentinel,\n                      ctrl_t::kSentinel, CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskNonFull(), ElementsAre(0, 2, 3, 5, 6));\n  } else {\n    FAIL() << \"No test coverage for Group::kWidth==\" << GroupType::kWidth;\n  }\n}\n\nTYPED_TEST(GroupTest, MaskEmptyOrDeleted) {\n  using GroupType = TypeParam;\n  if (GroupType::kWidth == 16) {\n    ctrl_t group[] = {ctrl_t::kEmpty,   CtrlT(1), ctrl_t::kEmpty,    CtrlT(3),\n                      ctrl_t::kDeleted, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),\n                      CtrlT(7),         CtrlT(5), CtrlT(3),          CtrlT(1),\n                      CtrlT(1),         CtrlT(1), CtrlT(1),          CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskEmptyOrDeleted().LowestBitSet(), 0);\n  } else if (GroupType::kWidth == 8) {\n    ctrl_t group[] = {ctrl_t::kEmpty,    CtrlT(1), CtrlT(2),\n                      ctrl_t::kDeleted,  CtrlT(2), CtrlT(1),\n                      ctrl_t::kSentinel, CtrlT(1)};\n    EXPECT_THAT(GroupType{group}.MaskEmptyOrDeleted().LowestBitSet(), 0);\n  } else {\n    FAIL() << \"No test coverage for Group::kWidth==\" << GroupType::kWidth;\n  }\n}\n\nTYPED_TEST(GroupTest, MaskFullOrSentinel) {\n  using GroupType = TypeParam;\n  if (GroupType::kWidth == 16) {\n    ctrl_t group[] = {\n        ctrl_t::kEmpty,   ctrl_t::kDeleted, ctrl_t::kEmpty,    CtrlT(3),\n        ctrl_t::kDeleted, CtrlT(5),         ctrl_t::kSentinel, ctrl_t::kEmpty,\n        ctrl_t::kEmpty,   ctrl_t::kDeleted, ctrl_t::kDeleted,  ctrl_t::kDeleted,\n        ctrl_t::kEmpty,   ctrl_t::kDeleted, ctrl_t::kDeleted,  ctrl_t::kDeleted,\n    };\n    EXPECT_THAT(GroupType{group}.MaskFullOrSentinel().LowestBitSet(), 3);\n  } else if (GroupType::kWidth == 8) {\n    ctrl_t group[] = {ctrl_t::kEmpty,   ctrl_t::kDeleted, CtrlT(2),\n                      ctrl_t::kDeleted, CtrlT(2),         ctrl_t::kSentinel,\n                      ctrl_t::kDeleted, ctrl_t::kEmpty};\n    EXPECT_THAT(GroupType{group}.MaskFullOrSentinel().LowestBitSet(), 2);\n  } else {\n    FAIL() << \"No test coverage for Group::kWidth==\" << GroupType::kWidth;\n  }\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hashtable_debug.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This library provides APIs to debug the probing behavior of hash tables.\n//\n// In general, the probing behavior is a black box for users and only the\n// side effects can be measured in the form of performance differences.\n// These APIs give a glimpse on the actual behavior of the probing algorithms in\n// these hashtables given a specified hash function and a set of elements.\n//\n// The probe count distribution can be used to assess the quality of the hash\n// function for that particular hash table. Note that a hash function that\n// performs well in one hash table implementation does not necessarily performs\n// well in a different one.\n//\n// This library supports std::unordered_{set,map}, dense_hash_{set,map} and\n// absl::{flat,node,string}_hash_{set,map}.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_\n#define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_\n\n#include <cstddef>\n#include <algorithm>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/container/internal/hashtable_debug_hooks.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// Returns the number of probes required to lookup `key`.  Returns 0 for a\n// search with no collisions.  Higher values mean more hash collisions occurred;\n// however, the exact meaning of this number varies according to the container\n// type.\ntemplate <typename C>\nsize_t GetHashtableDebugNumProbes(\n    const C& c, const typename C::key_type& key) {\n  return absl::container_internal::hashtable_debug_internal::\n      HashtableDebugAccess<C>::GetNumProbes(c, key);\n}\n\n// Gets a histogram of the number of probes for each elements in the container.\n// The sum of all the values in the vector is equal to container.size().\ntemplate <typename C>\nstd::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container) {\n  std::vector<size_t> v;\n  for (auto it = container.begin(); it != container.end(); ++it) {\n    size_t num_probes = GetHashtableDebugNumProbes(\n        container,\n        absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));\n    v.resize((std::max)(v.size(), num_probes + 1));\n    v[num_probes]++;\n  }\n  return v;\n}\n\nstruct HashtableDebugProbeSummary {\n  size_t total_elements;\n  size_t total_num_probes;\n  double mean;\n};\n\n// Gets a summary of the probe count distribution for the elements in the\n// container.\ntemplate <typename C>\nHashtableDebugProbeSummary GetHashtableDebugProbeSummary(const C& container) {\n  auto probes = GetHashtableDebugNumProbesHistogram(container);\n  HashtableDebugProbeSummary summary = {};\n  for (size_t i = 0; i < probes.size(); ++i) {\n    summary.total_elements += probes[i];\n    summary.total_num_probes += probes[i] * i;\n  }\n  summary.mean = 1.0 * summary.total_num_probes / summary.total_elements;\n  return summary;\n}\n\n// Returns the number of bytes requested from the allocator by the container\n// and not freed.\ntemplate <typename C>\nsize_t AllocatedByteSize(const C& c) {\n  return absl::container_internal::hashtable_debug_internal::\n      HashtableDebugAccess<C>::AllocatedByteSize(c);\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_\n"
  },
  {
    "path": "absl/container/internal/hashtable_debug_hooks.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Provides the internal API for hashtable_debug.h.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_\n#define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_\n\n#include <cstddef>\n\n#include <algorithm>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace hashtable_debug_internal {\n\n// If it is a map, call get<0>().\nusing std::get;\ntemplate <typename T, typename = typename T::mapped_type>\nauto GetKey(const typename T::value_type& pair, int) -> decltype(get<0>(pair)) {\n  return get<0>(pair);\n}\n\n// If it is not a map, return the value directly.\ntemplate <typename T>\nconst typename T::key_type& GetKey(const typename T::key_type& key, char) {\n  return key;\n}\n\n// Containers should specialize this to provide debug information for that\n// container.\ntemplate <class Container, typename Enabler = void>\nstruct HashtableDebugAccess {\n  // Returns the number of probes required to find `key` in `c`.  The \"number of\n  // probes\" is a concept that can vary by container.  Implementations should\n  // return 0 when `key` was found in the minimum number of operations and\n  // should increment the result for each non-trivial operation required to find\n  // `key`.\n  //\n  // The default implementation uses the bucket api from the standard and thus\n  // works for `std::unordered_*` containers.\n  static size_t GetNumProbes(const Container& c,\n                             const typename Container::key_type& key) {\n    if (!c.bucket_count()) return {};\n    size_t num_probes = 0;\n    size_t bucket = c.bucket(key);\n    for (auto it = c.begin(bucket), e = c.end(bucket);; ++it, ++num_probes) {\n      if (it == e) return num_probes;\n      if (c.key_eq()(key, GetKey<Container>(*it, 0))) return num_probes;\n    }\n  }\n\n  // Returns the number of bytes requested from the allocator by the container\n  // and not freed.\n  //\n  // static size_t AllocatedByteSize(const Container& c);\n\n  // Returns a tight lower bound for AllocatedByteSize(c) where `c` is of type\n  // `Container` and `c.size()` is equal to `num_elements`.\n  //\n  // static size_t LowerBoundAllocatedByteSize(size_t num_elements);\n};\n\n}  // namespace hashtable_debug_internal\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_\n"
  },
  {
    "path": "absl/container/internal/hashtablez_sampler.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hashtablez_sampler.h\"\n\n#include <algorithm>\n#include <atomic>\n#include <cassert>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <functional>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/per_thread_tls.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/profiling/internal/exponential_biased.h\"\n#include \"absl/profiling/internal/sample_recorder.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\nnamespace {\nABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{\n    false\n};\nABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};\nstd::atomic<HashtablezConfigListener> g_hashtablez_config_listener{nullptr};\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nABSL_PER_THREAD_TLS_KEYWORD absl::profiling_internal::ExponentialBiased\n    g_exponential_biased_generator;\n#endif\n\nvoid TriggerHashtablezConfigListener() {\n  auto* listener = g_hashtablez_config_listener.load(std::memory_order_acquire);\n  if (listener != nullptr) listener();\n}\n\n}  // namespace\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample = {0, 0};\n#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n\nHashtablezSampler& GlobalHashtablezSampler() {\n  static absl::NoDestructor<HashtablezSampler> sampler;\n  return *sampler;\n}\n\nHashtablezInfo::HashtablezInfo() = default;\nHashtablezInfo::~HashtablezInfo() = default;\n\nvoid HashtablezInfo::PrepareForSampling(int64_t stride,\n                                        size_t inline_element_size_value,\n                                        size_t key_size_value,\n                                        size_t value_size_value,\n                                        uint16_t soo_capacity_value) {\n  capacity.store(0, std::memory_order_relaxed);\n  size.store(0, std::memory_order_relaxed);\n  num_erases.store(0, std::memory_order_relaxed);\n  num_rehashes.store(0, std::memory_order_relaxed);\n  max_probe_length.store(0, std::memory_order_relaxed);\n  total_probe_length.store(0, std::memory_order_relaxed);\n  hashes_bitwise_or.store(0, std::memory_order_relaxed);\n  hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed);\n  max_reserve.store(0, std::memory_order_relaxed);\n\n  create_time = absl::Now();\n  weight = stride;\n  // The inliner makes hardcoded skip_count difficult (especially when combined\n  // with LTO).  We use the ability to exclude stacks by regex when encoding\n  // instead.\n  depth = static_cast<unsigned>(\n      absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth,\n                          /* skip_count= */ 0));\n  inline_element_size = inline_element_size_value;\n  key_size = key_size_value;\n  value_size = value_size_value;\n  soo_capacity = soo_capacity_value;\n}\n\nstatic bool ShouldForceSampling() {\n  enum ForceState {\n    kDontForce,\n    kForce,\n    kUninitialized\n  };\n  ABSL_CONST_INIT static std::atomic<ForceState> global_state{\n      kUninitialized};\n  ForceState state = global_state.load(std::memory_order_relaxed);\n  if (ABSL_PREDICT_TRUE(state == kDontForce)) return false;\n\n  if (state == kUninitialized) {\n    state = ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)()\n                ? kForce\n                : kDontForce;\n    global_state.store(state, std::memory_order_relaxed);\n  }\n  return state == kForce;\n}\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nHashtablezInfoHandle ForcedTrySample(size_t inline_element_size,\n                                     size_t key_size, size_t value_size,\n                                     uint16_t soo_capacity) {\n  return HashtablezInfoHandle(SampleSlow(global_next_sample,\n                                         inline_element_size, key_size,\n                                         value_size, soo_capacity));\n}\nvoid TestOnlyRefreshSamplingStateForCurrentThread() {\n  global_next_sample.next_sample =\n      g_hashtablez_sample_parameter.load(std::memory_order_relaxed);\n  global_next_sample.sample_stride = global_next_sample.next_sample;\n}\n#else\nHashtablezInfoHandle ForcedTrySample(size_t, size_t, size_t, uint16_t) {\n  return HashtablezInfoHandle{nullptr};\n}\nvoid TestOnlyRefreshSamplingStateForCurrentThread() {}\n#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE\n\nHashtablezInfo* SampleSlow(SamplingState& next_sample,\n                           size_t inline_element_size, size_t key_size,\n                           size_t value_size, uint16_t soo_capacity) {\n  if (ABSL_PREDICT_FALSE(ShouldForceSampling())) {\n    next_sample.next_sample = 1;\n    const int64_t old_stride = exchange(next_sample.sample_stride, 1);\n    HashtablezInfo* result = GlobalHashtablezSampler().Register(\n        old_stride, inline_element_size, key_size, value_size, soo_capacity);\n    return result;\n  }\n\n#if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n  next_sample = {\n      std::numeric_limits<int64_t>::max(),\n      std::numeric_limits<int64_t>::max(),\n  };\n  return nullptr;\n#else\n  bool first = next_sample.next_sample < 0;\n\n  const int64_t next_stride = g_exponential_biased_generator.GetStride(\n      g_hashtablez_sample_parameter.load(std::memory_order_relaxed));\n\n  next_sample.next_sample = next_stride;\n  const int64_t old_stride = exchange(next_sample.sample_stride, next_stride);\n  // Small values of interval are equivalent to just sampling next time.\n  ABSL_ASSERT(next_stride >= 1);\n\n  // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold\n  // low enough that we will start sampling in a reasonable time, so we just use\n  // the default sampling rate.\n  if (!g_hashtablez_enabled.load(std::memory_order_relaxed)) return nullptr;\n\n  // We will only be negative on our first count, so we should just retry in\n  // that case.\n  if (first) {\n    if (ABSL_PREDICT_TRUE(--next_sample.next_sample > 0)) return nullptr;\n    return SampleSlow(next_sample, inline_element_size, key_size, value_size,\n                      soo_capacity);\n  }\n\n  return GlobalHashtablezSampler().Register(old_stride, inline_element_size,\n                                            key_size, value_size, soo_capacity);\n#endif\n}\n\nvoid UnsampleSlow(HashtablezInfo* info) {\n  GlobalHashtablezSampler().Unregister(info);\n}\n\nvoid RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {\n#ifdef ABSL_INTERNAL_HAVE_SSE2\n  total_probe_length /= 16;\n#else\n  total_probe_length /= 8;\n#endif\n  info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);\n  info->num_erases.store(0, std::memory_order_relaxed);\n  // There is only one concurrent writer, so `load` then `store` is sufficient\n  // instead of using `fetch_add`.\n  info->num_rehashes.store(\n      1 + info->num_rehashes.load(std::memory_order_relaxed),\n      std::memory_order_relaxed);\n}\n\nvoid RecordReservationSlow(HashtablezInfo* info, size_t target_capacity) {\n  info->max_reserve.store(\n      (std::max)(info->max_reserve.load(std::memory_order_relaxed),\n                 target_capacity),\n      std::memory_order_relaxed);\n}\n\nvoid RecordClearedReservationSlow(HashtablezInfo* info) {\n  info->max_reserve.store(0, std::memory_order_relaxed);\n}\n\nvoid RecordStorageChangedSlow(HashtablezInfo* info, size_t size,\n                              size_t capacity) {\n  info->size.store(size, std::memory_order_relaxed);\n  info->capacity.store(capacity, std::memory_order_relaxed);\n  if (size == 0) {\n    // This is a clear, reset the total/num_erases too.\n    info->total_probe_length.store(0, std::memory_order_relaxed);\n    info->num_erases.store(0, std::memory_order_relaxed);\n  }\n}\n\nvoid RecordInsertMissSlow(HashtablezInfo* info, size_t hash,\n                          size_t distance_from_desired) {\n  // SwissTables probe in groups of 16, so scale this to count items probes and\n  // not offset from desired.\n  size_t probe_length = distance_from_desired;\n#ifdef ABSL_INTERNAL_HAVE_SSE2\n  probe_length /= 16;\n#else\n  probe_length /= 8;\n#endif\n\n  info->hashes_bitwise_and.fetch_and(hash, std::memory_order_relaxed);\n  info->hashes_bitwise_or.fetch_or(hash, std::memory_order_relaxed);\n  info->max_probe_length.store(\n      std::max(info->max_probe_length.load(std::memory_order_relaxed),\n               probe_length),\n      std::memory_order_relaxed);\n  info->total_probe_length.fetch_add(probe_length, std::memory_order_relaxed);\n  info->size.fetch_add(1, std::memory_order_relaxed);\n}\n\nvoid RecordEraseSlow(HashtablezInfo* info) {\n  info->size.fetch_sub(1, std::memory_order_relaxed);\n  // There is only one concurrent writer, so `load` then `store` is sufficient\n  // instead of using `fetch_add`.\n  info->num_erases.store(1 + info->num_erases.load(std::memory_order_relaxed),\n                         std::memory_order_relaxed);\n}\n\nvoid SetHashtablezConfigListener(HashtablezConfigListener l) {\n  g_hashtablez_config_listener.store(l, std::memory_order_release);\n}\n\nbool IsHashtablezEnabled() {\n  return g_hashtablez_enabled.load(std::memory_order_acquire);\n}\n\nvoid SetHashtablezEnabled(bool enabled) {\n  SetHashtablezEnabledInternal(enabled);\n  TriggerHashtablezConfigListener();\n}\n\nvoid SetHashtablezEnabledInternal(bool enabled) {\n  g_hashtablez_enabled.store(enabled, std::memory_order_release);\n}\n\nint32_t GetHashtablezSampleParameter() {\n  return g_hashtablez_sample_parameter.load(std::memory_order_acquire);\n}\n\nvoid SetHashtablezSampleParameter(int32_t rate) {\n  SetHashtablezSampleParameterInternal(rate);\n  TriggerHashtablezConfigListener();\n}\n\nvoid SetHashtablezSampleParameterInternal(int32_t rate) {\n  if (rate > 0) {\n    g_hashtablez_sample_parameter.store(rate, std::memory_order_release);\n  } else {\n    ABSL_RAW_LOG(ERROR, \"Invalid hashtablez sample rate: %lld\",\n                 static_cast<long long>(rate));  // NOLINT(runtime/int)\n  }\n}\n\nsize_t GetHashtablezMaxSamples() {\n  return GlobalHashtablezSampler().GetMaxSamples();\n}\n\nvoid SetHashtablezMaxSamples(size_t max) {\n  SetHashtablezMaxSamplesInternal(max);\n  TriggerHashtablezConfigListener();\n}\n\nvoid SetHashtablezMaxSamplesInternal(size_t max) {\n  if (max > 0) {\n    GlobalHashtablezSampler().SetMaxSamples(max);\n  } else {\n    ABSL_RAW_LOG(ERROR, \"Invalid hashtablez max samples: 0\");\n  }\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hashtablez_sampler.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: hashtablez_sampler.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the API for a low level library to sample hashtables\n// and collect runtime statistics about them.\n//\n// `HashtablezSampler` controls the lifecycle of `HashtablezInfo` objects which\n// store information about a single sample.\n//\n// `Record*` methods store information into samples.\n// `Sample()` and `Unsample()` make use of a single global sampler with\n// properties controlled by the flags hashtablez_enabled,\n// hashtablez_sample_rate, and hashtablez_max_samples.\n//\n// WARNING\n//\n// Using this sampling API may cause sampled Swiss tables to use the global\n// allocator (operator `new`) in addition to any custom allocator.  If you\n// are using a table in an unusual circumstance where allocation or calling a\n// linux syscall is unacceptable, this could interfere.\n//\n// This utility is internal-only. Use at your own risk.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_\n#define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_\n\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <functional>\n#include <memory>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/per_thread_tls.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/profiling/internal/sample_recorder.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/time.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// Stores information about a sampled hashtable.  All mutations to this *must*\n// be made through `Record*` functions below.  All reads from this *must* only\n// occur in the callback to `HashtablezSampler::Iterate`.\nstruct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {\n  // Constructs the object but does not fill in any fields.\n  HashtablezInfo();\n  ~HashtablezInfo();\n  HashtablezInfo(const HashtablezInfo&) = delete;\n  HashtablezInfo& operator=(const HashtablezInfo&) = delete;\n\n  // Puts the object into a clean state, fills in the logically `const` members,\n  // blocking for any readers that are currently sampling the object.\n  void PrepareForSampling(int64_t stride, size_t inline_element_size_value,\n                          size_t key_size, size_t value_size,\n                          uint16_t soo_capacity_value)\n      ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);\n\n  // These fields are mutated by the various Record* APIs and need to be\n  // thread-safe.\n  std::atomic<size_t> capacity;\n  std::atomic<size_t> size;\n  std::atomic<size_t> num_erases;\n  std::atomic<size_t> num_rehashes;\n  std::atomic<size_t> max_probe_length;\n  std::atomic<size_t> total_probe_length;\n  std::atomic<size_t> hashes_bitwise_or;\n  std::atomic<size_t> hashes_bitwise_and;\n  std::atomic<size_t> max_reserve;\n\n  // All of the fields below are set by `PrepareForSampling`, they must not be\n  // mutated in `Record*` functions.  They are logically `const` in that sense.\n  // These are guarded by init_mu, but that is not externalized to clients,\n  // which can read them only during `SampleRecorder::Iterate` which will hold\n  // the lock.\n  static constexpr int kMaxStackDepth = 64;\n  absl::Time create_time;\n  uint32_t depth;\n  // The SOO capacity for this table in elements (not bytes). Note that sampled\n  // tables are never SOO because we need to store the infoz handle on the heap.\n  // Tables that would be SOO if not sampled should have: soo_capacity > 0 &&\n  // size <= soo_capacity && max_reserve <= soo_capacity.\n  uint16_t soo_capacity;\n  void* stack[kMaxStackDepth];\n  size_t inline_element_size;  // How big is the slot in bytes?\n  size_t key_size;             // sizeof(key_type)\n  size_t value_size;           // sizeof(value_type)\n};\n\nvoid RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length);\n\nvoid RecordReservationSlow(HashtablezInfo* info, size_t target_capacity);\n\nvoid RecordClearedReservationSlow(HashtablezInfo* info);\n\nvoid RecordStorageChangedSlow(HashtablezInfo* info, size_t size,\n                              size_t capacity);\n\nvoid RecordInsertMissSlow(HashtablezInfo* info, size_t hash,\n                          size_t distance_from_desired);\n\nvoid RecordEraseSlow(HashtablezInfo* info);\n\nstruct SamplingState {\n  int64_t next_sample;\n  // When we make a sampling decision, we record that distance so we can weight\n  // each sample.\n  int64_t sample_stride;\n};\n\nHashtablezInfo* SampleSlow(SamplingState& next_sample,\n                           size_t inline_element_size, size_t key_size,\n                           size_t value_size, uint16_t soo_capacity);\nvoid UnsampleSlow(HashtablezInfo* info);\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set\n#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nclass HashtablezInfoHandle {\n public:\n  explicit HashtablezInfoHandle() : info_(nullptr) {}\n  explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {}\n\n  // We do not have a destructor. Caller is responsible for calling Unregister\n  // before destroying the handle.\n  void Unregister() {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    UnsampleSlow(info_);\n  }\n\n  inline bool IsSampled() const { return ABSL_PREDICT_FALSE(info_ != nullptr); }\n\n  inline void RecordStorageChanged(size_t size, size_t capacity) {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    RecordStorageChangedSlow(info_, size, capacity);\n  }\n\n  inline void RecordRehash(size_t total_probe_length) {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    RecordRehashSlow(info_, total_probe_length);\n  }\n\n  inline void RecordReservation(size_t target_capacity) {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    RecordReservationSlow(info_, target_capacity);\n  }\n\n  inline void RecordClearedReservation() {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    RecordClearedReservationSlow(info_);\n  }\n\n  inline void RecordInsertMiss(size_t hash, size_t distance_from_desired) {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    RecordInsertMissSlow(info_, hash, distance_from_desired);\n  }\n\n  inline void RecordErase() {\n    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;\n    RecordEraseSlow(info_);\n  }\n\n  friend inline void swap(HashtablezInfoHandle& lhs,\n                          HashtablezInfoHandle& rhs) {\n    std::swap(lhs.info_, rhs.info_);\n  }\n\n private:\n  friend class HashtablezInfoHandlePeer;\n  HashtablezInfo* info_;\n};\n#else\n// Ensure that when Hashtablez is turned off at compile time, HashtablezInfo can\n// be removed by the linker, in order to reduce the binary size.\nclass HashtablezInfoHandle {\n public:\n  explicit HashtablezInfoHandle() = default;\n  explicit HashtablezInfoHandle(std::nullptr_t) {}\n\n  inline void Unregister() {}\n  inline bool IsSampled() const { return false; }\n  inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}\n  inline void RecordRehash(size_t /*total_probe_length*/) {}\n  inline void RecordReservation(size_t /*target_capacity*/) {}\n  inline void RecordClearedReservation() {}\n  inline void RecordInsertMiss(size_t /*hash*/,\n                               size_t /*distance_from_desired*/) {}\n  inline void RecordErase() {}\n\n  friend inline void swap(HashtablezInfoHandle& /*lhs*/,\n                          HashtablezInfoHandle& /*rhs*/) {}\n};\n#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nextern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample;\n#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n\n// Returns true if the next table should be sampled.\n// This function updates the global state.\n// If the function returns true, actual sampling should be done by calling\n// ForcedTrySample().\ninline bool ShouldSampleNextTable() {\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n  if (ABSL_PREDICT_TRUE(--global_next_sample.next_sample > 0)) {\n    return false;\n  }\n  return true;\n#else\n  return false;\n#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE\n}\n\n// Returns a sampling handle.\n// Must be called only if HashSetShouldBeSampled() returned true.\n// Returned handle still can be unsampled if sampling is not possible.\nHashtablezInfoHandle ForcedTrySample(size_t inline_element_size,\n                                     size_t key_size, size_t value_size,\n                                     uint16_t soo_capacity);\n\n// In case sampling needs to be disabled and re-enabled in tests, this function\n// can be used to reset the sampling state for the current thread.\n// It is useful to avoid sampling attempts and sampling delays in tests.\nvoid TestOnlyRefreshSamplingStateForCurrentThread();\n\n// Returns a sampling handle.\ninline HashtablezInfoHandle Sample(size_t inline_element_size, size_t key_size,\n                                   size_t value_size, uint16_t soo_capacity) {\n  if (ABSL_PREDICT_TRUE(!ShouldSampleNextTable())) {\n    return HashtablezInfoHandle(nullptr);\n  }\n  return ForcedTrySample(inline_element_size, key_size, value_size,\n                         soo_capacity);\n}\n\nusing HashtablezSampler =\n    ::absl::profiling_internal::SampleRecorder<HashtablezInfo>;\n\n// Returns a global Sampler.\nHashtablezSampler& GlobalHashtablezSampler();\n\nusing HashtablezConfigListener = void (*)();\nvoid SetHashtablezConfigListener(HashtablezConfigListener l);\n\n// Enables or disables sampling for Swiss tables.\nbool IsHashtablezEnabled();\nvoid SetHashtablezEnabled(bool enabled);\nvoid SetHashtablezEnabledInternal(bool enabled);\n\n// Sets the rate at which Swiss tables will be sampled.\nint32_t GetHashtablezSampleParameter();\nvoid SetHashtablezSampleParameter(int32_t rate);\nvoid SetHashtablezSampleParameterInternal(int32_t rate);\n\n// Sets a soft max for the number of samples that will be kept.\nsize_t GetHashtablezMaxSamples();\nvoid SetHashtablezMaxSamples(size_t max);\nvoid SetHashtablezMaxSamplesInternal(size_t max);\n\n// Configuration override.\n// This allows process-wide sampling without depending on order of\n// initialization of static storage duration objects.\n// The definition of this constant is weak, which allows us to inject a\n// different value for it at link time.\nextern \"C\" bool ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)();\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_\n"
  },
  {
    "path": "absl/container/internal/hashtablez_sampler_force_weak_definition.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hashtablez_sampler.h\"\n\n#include \"absl/base/attributes.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// See hashtablez_sampler.h for details.\nextern \"C\" ABSL_ATTRIBUTE_WEAK bool ABSL_INTERNAL_C_SYMBOL(\n    AbslContainerInternalSampleEverything)() {\n  return false;\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/hashtablez_sampler_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/hashtablez_sampler.h\"\n\n#include <atomic>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <random>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/profiling/internal/sample_recorder.h\"\n#include \"absl/random/random.h\"\n#include \"absl/synchronization/blocking_counter.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/synchronization/notification.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_SSE2\nconstexpr int kProbeLength = 16;\n#else\nconstexpr int kProbeLength = 8;\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nclass HashtablezInfoHandlePeer {\n public:\n  static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }\n};\n#else\nclass HashtablezInfoHandlePeer {\n public:\n  static HashtablezInfo* GetInfo(HashtablezInfoHandle*) { return nullptr; }\n};\n#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n\nnamespace {\nusing ::absl::synchronization_internal::ThreadPool;\nusing ::testing::IsEmpty;\nusing ::testing::UnorderedElementsAre;\n\nstd::vector<size_t> GetSizes(HashtablezSampler* s) {\n  std::vector<size_t> res;\n  s->Iterate([&](const HashtablezInfo& info) {\n    res.push_back(info.size.load(std::memory_order_acquire));\n  });\n  return res;\n}\n\nHashtablezInfo* Register(HashtablezSampler* s, size_t size) {\n  const int64_t test_stride = 123;\n  const size_t test_element_size = 17;\n  const size_t test_key_size = 3;\n  const size_t test_value_size = 5;\n  auto* info =\n      s->Register(test_stride, test_element_size, /*key_size=*/test_key_size,\n                  /*value_size=*/test_value_size, /*soo_capacity=*/0);\n  assert(info != nullptr);\n  info->size.store(size);\n  return info;\n}\n\nTEST(HashtablezInfoTest, PrepareForSampling) {\n  absl::Time test_start = absl::Now();\n  const int64_t test_stride = 123;\n  const size_t test_element_size = 17;\n  const size_t test_key_size = 15;\n  const size_t test_value_size = 13;\n\n  HashtablezInfo info;\n  absl::MutexLock l(info.init_mu);\n  info.PrepareForSampling(test_stride, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n                          /*soo_capacity_value=*/1);\n\n  EXPECT_EQ(info.capacity.load(), 0);\n  EXPECT_EQ(info.size.load(), 0);\n  EXPECT_EQ(info.num_erases.load(), 0);\n  EXPECT_EQ(info.num_rehashes.load(), 0);\n  EXPECT_EQ(info.max_probe_length.load(), 0);\n  EXPECT_EQ(info.total_probe_length.load(), 0);\n  EXPECT_EQ(info.hashes_bitwise_or.load(), 0);\n  EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});\n  EXPECT_EQ(info.max_reserve.load(), 0);\n  EXPECT_GE(info.create_time, test_start);\n  EXPECT_EQ(info.weight, test_stride);\n  EXPECT_EQ(info.inline_element_size, test_element_size);\n  EXPECT_EQ(info.key_size, test_key_size);\n  EXPECT_EQ(info.value_size, test_value_size);\n  EXPECT_EQ(info.soo_capacity, 1);\n\n  info.capacity.store(1, std::memory_order_relaxed);\n  info.size.store(1, std::memory_order_relaxed);\n  info.num_erases.store(1, std::memory_order_relaxed);\n  info.max_probe_length.store(1, std::memory_order_relaxed);\n  info.total_probe_length.store(1, std::memory_order_relaxed);\n  info.hashes_bitwise_or.store(1, std::memory_order_relaxed);\n  info.hashes_bitwise_and.store(1, std::memory_order_relaxed);\n  info.max_reserve.store(1, std::memory_order_relaxed);\n  info.create_time = test_start - absl::Hours(20);\n\n  info.PrepareForSampling(test_stride * 2, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n                          /*soo_capacity_value=*/0);\n  EXPECT_EQ(info.capacity.load(), 0);\n  EXPECT_EQ(info.size.load(), 0);\n  EXPECT_EQ(info.num_erases.load(), 0);\n  EXPECT_EQ(info.num_rehashes.load(), 0);\n  EXPECT_EQ(info.max_probe_length.load(), 0);\n  EXPECT_EQ(info.total_probe_length.load(), 0);\n  EXPECT_EQ(info.hashes_bitwise_or.load(), 0);\n  EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});\n  EXPECT_EQ(info.max_reserve.load(), 0);\n  EXPECT_EQ(info.weight, 2 * test_stride);\n  EXPECT_EQ(info.inline_element_size, test_element_size);\n  EXPECT_EQ(info.key_size, test_key_size);\n  EXPECT_EQ(info.value_size, test_value_size);\n  EXPECT_GE(info.create_time, test_start);\n  EXPECT_EQ(info.soo_capacity, 0);\n}\n\nTEST(HashtablezInfoTest, RecordStorageChanged) {\n  HashtablezInfo info;\n  absl::MutexLock l(info.init_mu);\n  const int64_t test_stride = 21;\n  const size_t test_element_size = 19;\n  const size_t test_key_size = 17;\n  const size_t test_value_size = 15;\n\n  info.PrepareForSampling(test_stride, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n                          /*soo_capacity_value=*/0);\n  RecordStorageChangedSlow(&info, 17, 47);\n  EXPECT_EQ(info.size.load(), 17);\n  EXPECT_EQ(info.capacity.load(), 47);\n  RecordStorageChangedSlow(&info, 20, 20);\n  EXPECT_EQ(info.size.load(), 20);\n  EXPECT_EQ(info.capacity.load(), 20);\n}\n\nTEST(HashtablezInfoTest, RecordInsertMiss) {\n  HashtablezInfo info;\n  absl::MutexLock l(info.init_mu);\n  const int64_t test_stride = 25;\n  const size_t test_element_size = 23;\n  const size_t test_key_size = 21;\n  const size_t test_value_size = 19;\n\n  info.PrepareForSampling(test_stride, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n                          /*soo_capacity_value=*/0);\n  EXPECT_EQ(info.max_probe_length.load(), 0);\n  RecordInsertMissSlow(&info, 0x0000FF00, 6 * kProbeLength);\n  EXPECT_EQ(info.max_probe_length.load(), 6);\n  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000FF00);\n  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x0000FF00);\n  RecordInsertMissSlow(&info, 0x000FF000, 4 * kProbeLength);\n  EXPECT_EQ(info.max_probe_length.load(), 6);\n  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000F000);\n  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x000FFF00);\n  RecordInsertMissSlow(&info, 0x00FF0000, 12 * kProbeLength);\n  EXPECT_EQ(info.max_probe_length.load(), 12);\n  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x00000000);\n  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x00FFFF00);\n}\n\nTEST(HashtablezInfoTest, RecordErase) {\n  const int64_t test_stride = 31;\n  const size_t test_element_size = 29;\n  const size_t test_key_size = 27;\n  const size_t test_value_size = 25;\n\n  HashtablezInfo info;\n  absl::MutexLock l(info.init_mu);\n  info.PrepareForSampling(test_stride, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n                          /*soo_capacity_value=*/1);\n  EXPECT_EQ(info.num_erases.load(), 0);\n  EXPECT_EQ(info.size.load(), 0);\n  RecordInsertMissSlow(&info, 0x0000FF00, 6 * kProbeLength);\n  EXPECT_EQ(info.size.load(), 1);\n  RecordEraseSlow(&info);\n  EXPECT_EQ(info.size.load(), 0);\n  EXPECT_EQ(info.num_erases.load(), 1);\n  EXPECT_EQ(info.inline_element_size, test_element_size);\n  EXPECT_EQ(info.key_size, test_key_size);\n  EXPECT_EQ(info.value_size, test_value_size);\n  EXPECT_EQ(info.soo_capacity, 1);\n}\n\nTEST(HashtablezInfoTest, RecordRehash) {\n  const int64_t test_stride = 33;\n  const size_t test_element_size = 31;\n  const size_t test_key_size = 29;\n  const size_t test_value_size = 27;\n  HashtablezInfo info;\n  absl::MutexLock l(info.init_mu);\n  info.PrepareForSampling(test_stride, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n\n                          /*soo_capacity_value=*/0);\n  RecordInsertMissSlow(&info, 0x1, 0);\n  RecordInsertMissSlow(&info, 0x2, kProbeLength);\n  RecordInsertMissSlow(&info, 0x4, kProbeLength);\n  RecordInsertMissSlow(&info, 0x8, 2 * kProbeLength);\n  EXPECT_EQ(info.size.load(), 4);\n  EXPECT_EQ(info.total_probe_length.load(), 4);\n\n  RecordEraseSlow(&info);\n  RecordEraseSlow(&info);\n  EXPECT_EQ(info.size.load(), 2);\n  EXPECT_EQ(info.total_probe_length.load(), 4);\n  EXPECT_EQ(info.num_erases.load(), 2);\n\n  RecordRehashSlow(&info, 3 * kProbeLength);\n  EXPECT_EQ(info.size.load(), 2);\n  EXPECT_EQ(info.total_probe_length.load(), 3);\n  EXPECT_EQ(info.num_erases.load(), 0);\n  EXPECT_EQ(info.num_rehashes.load(), 1);\n  EXPECT_EQ(info.inline_element_size, test_element_size);\n  EXPECT_EQ(info.key_size, test_key_size);\n  EXPECT_EQ(info.value_size, test_value_size);\n  EXPECT_EQ(info.soo_capacity, 0);\n}\n\nTEST(HashtablezInfoTest, RecordReservation) {\n  HashtablezInfo info;\n  absl::MutexLock l(info.init_mu);\n  const int64_t test_stride = 35;\n  const size_t test_element_size = 33;\n  const size_t test_key_size = 31;\n  const size_t test_value_size = 29;\n\n  info.PrepareForSampling(test_stride, test_element_size,\n                          /*key_size=*/test_key_size,\n                          /*value_size=*/test_value_size,\n\n                          /*soo_capacity_value=*/0);\n  RecordReservationSlow(&info, 3);\n  EXPECT_EQ(info.max_reserve.load(), 3);\n\n  RecordReservationSlow(&info, 2);\n  // High watermark does not change\n  EXPECT_EQ(info.max_reserve.load(), 3);\n\n  RecordReservationSlow(&info, 10);\n  // High watermark does change\n  EXPECT_EQ(info.max_reserve.load(), 10);\n}\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\nTEST(HashtablezSamplerTest, SmallSampleParameter) {\n  const size_t test_element_size = 31;\n  const size_t test_key_size = 33;\n  const size_t test_value_size = 35;\n\n  SetHashtablezEnabled(true);\n  SetHashtablezSampleParameter(100);\n\n  for (int i = 0; i < 1000; ++i) {\n    SamplingState next_sample = {0, 0};\n    HashtablezInfo* sample =\n        SampleSlow(next_sample, test_element_size,\n                   /*key_size=*/test_key_size, /*value_size=*/test_value_size,\n\n                   /*soo_capacity=*/0);\n    EXPECT_GT(next_sample.next_sample, 0);\n    EXPECT_EQ(next_sample.next_sample, next_sample.sample_stride);\n    EXPECT_NE(sample, nullptr);\n    UnsampleSlow(sample);\n  }\n}\n\nTEST(HashtablezSamplerTest, LargeSampleParameter) {\n  const size_t test_element_size = 31;\n  const size_t test_key_size = 33;\n  const size_t test_value_size = 35;\n  SetHashtablezEnabled(true);\n  SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max());\n\n  for (int i = 0; i < 1000; ++i) {\n    SamplingState next_sample = {0, 0};\n    HashtablezInfo* sample =\n        SampleSlow(next_sample, test_element_size,\n                   /*key_size=*/test_key_size, /*value_size=*/test_value_size,\n                   /*soo_capacity=*/0);\n    EXPECT_GT(next_sample.next_sample, 0);\n    EXPECT_EQ(next_sample.next_sample, next_sample.sample_stride);\n    EXPECT_NE(sample, nullptr);\n    UnsampleSlow(sample);\n  }\n}\n\nTEST(HashtablezSamplerTest, Sample) {\n  const size_t test_element_size = 31;\n  const size_t test_key_size = 33;\n  const size_t test_value_size = 35;\n  SetHashtablezEnabled(true);\n  SetHashtablezSampleParameter(100);\n  int64_t num_sampled = 0;\n  int64_t total = 0;\n  double sample_rate = 0.0;\n  for (int i = 0; i < 1000000; ++i) {\n    HashtablezInfoHandle h =\n        Sample(test_element_size,\n               /*key_size=*/test_key_size, /*value_size=*/test_value_size,\n\n               /*soo_capacity=*/0);\n\n    ++total;\n    if (h.IsSampled()) {\n      ++num_sampled;\n    }\n    sample_rate = static_cast<double>(num_sampled) / total;\n    if (0.005 < sample_rate && sample_rate < 0.015) break;\n  }\n  EXPECT_NEAR(sample_rate, 0.01, 0.005);\n}\n\nTEST(HashtablezSamplerTest, Handle) {\n  auto& sampler = GlobalHashtablezSampler();\n  const int64_t test_stride = 41;\n  const size_t test_element_size = 39;\n  const size_t test_key_size = 37;\n  const size_t test_value_size = 35;\n  HashtablezInfoHandle h(sampler.Register(test_stride, test_element_size,\n                                          /*key_size=*/test_key_size,\n                                          /*value_size=*/test_value_size,\n                                          /*soo_capacity=*/0));\n  auto* info = HashtablezInfoHandlePeer::GetInfo(&h);\n  info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed);\n\n  bool found = false;\n  sampler.Iterate([&](const HashtablezInfo& h) {\n    if (&h == info) {\n      EXPECT_EQ(h.weight, test_stride);\n      EXPECT_EQ(h.hashes_bitwise_and.load(), 0x12345678);\n      found = true;\n    }\n  });\n  EXPECT_TRUE(found);\n\n  h.Unregister();\n  h = HashtablezInfoHandle();\n  found = false;\n  sampler.Iterate([&](const HashtablezInfo& h) {\n    if (&h == info) {\n      // this will only happen if some other thread has resurrected the info\n      // the old handle was using.\n      if (h.hashes_bitwise_and.load() == 0x12345678) {\n        found = true;\n      }\n    }\n  });\n  EXPECT_FALSE(found);\n}\n#endif\n\n\nTEST(HashtablezSamplerTest, Registration) {\n  HashtablezSampler sampler;\n  auto* info1 = Register(&sampler, 1);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1));\n\n  auto* info2 = Register(&sampler, 2);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1, 2));\n  info1->size.store(3);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(3, 2));\n\n  sampler.Unregister(info1);\n  sampler.Unregister(info2);\n}\n\nTEST(HashtablezSamplerTest, Unregistration) {\n  HashtablezSampler sampler;\n  std::vector<HashtablezInfo*> infos;\n  for (size_t i = 0; i < 3; ++i) {\n    infos.push_back(Register(&sampler, i));\n  }\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 1, 2));\n\n  sampler.Unregister(infos[1]);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2));\n\n  infos.push_back(Register(&sampler, 3));\n  infos.push_back(Register(&sampler, 4));\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 3, 4));\n  sampler.Unregister(infos[3]);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 4));\n\n  sampler.Unregister(infos[0]);\n  sampler.Unregister(infos[2]);\n  sampler.Unregister(infos[4]);\n  EXPECT_THAT(GetSizes(&sampler), IsEmpty());\n}\n\nTEST(HashtablezSamplerTest, MultiThreaded) {\n  HashtablezSampler sampler;\n  Notification stop;\n  ThreadPool pool(10);\n\n  for (int i = 0; i < 10; ++i) {\n    const int64_t sampling_stride = 11 + i % 3;\n    const size_t elt_size = 10 + i % 2;\n    const size_t key_size = 12 + i % 4;\n    const size_t value_size = 13 + i % 5;\n    pool.Schedule([&sampler, &stop, sampling_stride, elt_size, key_size,\n                   value_size]() {\n      absl::InsecureBitGen gen;\n\n      std::vector<HashtablezInfo*> infoz;\n      while (!stop.HasBeenNotified()) {\n        if (infoz.empty()) {\n          infoz.push_back(sampler.Register(sampling_stride, elt_size,\n                                           /*key_size=*/key_size,\n                                           /*value_size=*/value_size,\n                                           /*soo_capacity=*/0));\n        }\n        switch (std::uniform_int_distribution<>(0, 2)(gen)) {\n          case 0: {\n            infoz.push_back(sampler.Register(sampling_stride, elt_size,\n                                             /*key_size=*/key_size,\n                                             /*value_size=*/value_size,\n\n                                             /*soo_capacity=*/0));\n            break;\n          }\n          case 1: {\n            size_t p =\n                std::uniform_int_distribution<>(0, infoz.size() - 1)(gen);\n            HashtablezInfo* info = infoz[p];\n            infoz[p] = infoz.back();\n            infoz.pop_back();\n            EXPECT_EQ(info->weight, sampling_stride);\n            sampler.Unregister(info);\n            break;\n          }\n          case 2: {\n            absl::Duration oldest = absl::ZeroDuration();\n            sampler.Iterate([&](const HashtablezInfo& info) {\n              oldest = std::max(oldest, absl::Now() - info.create_time);\n            });\n            ASSERT_GE(oldest, absl::ZeroDuration());\n            break;\n          }\n        }\n      }\n    });\n  }\n  // The threads will hammer away.  Give it a little bit of time for tsan to\n  // spot errors.\n  absl::SleepFor(absl::Seconds(3));\n  stop.Notify();\n}\n\nTEST(HashtablezSamplerTest, Callback) {\n  HashtablezSampler sampler;\n\n  auto* info1 = Register(&sampler, 1);\n  auto* info2 = Register(&sampler, 2);\n\n  static const HashtablezInfo* expected;\n\n  auto callback = [](const HashtablezInfo& info) {\n    // We can't use `info` outside of this callback because the object will be\n    // disposed as soon as we return from here.\n    EXPECT_EQ(&info, expected);\n  };\n\n  // Set the callback.\n  EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr);\n  expected = info1;\n  sampler.Unregister(info1);\n\n  // Unset the callback.\n  EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr));\n  expected = nullptr;  // no more calls.\n  sampler.Unregister(info2);\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/heterogeneous_lookup_testing.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_HETEROGENEOUS_LOOKUP_TESTING_H_\n#define ABSL_CONTAINER_INTERNAL_HETEROGENEOUS_LOOKUP_TESTING_H_\n\n#include <cstddef>\n#include <ostream>\n\n#include \"gmock/gmock.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// An expensive class that is convertible to CheapType to demonstrate\n// heterogeneous lookups.\nclass ExpensiveType : public absl::test_internal::CopyableMovableInstance {\n public:\n  explicit ExpensiveType(int value)\n      : absl::test_internal::CopyableMovableInstance(value) {}\n\n  friend std::ostream& operator<<(std::ostream& os, const ExpensiveType& a) {\n    return os << a.value();\n  }\n};\n\nclass CheapType {\n public:\n  explicit CheapType(const int value) : value_(value) {}\n\n  explicit operator ExpensiveType() const { return ExpensiveType(value_); }\n\n  int value() const { return value_; }\n\n private:\n  int value_;\n};\n\nstruct HeterogeneousHash {\n  using is_transparent = void;\n  size_t operator()(const ExpensiveType& a) const { return a.value(); }\n  size_t operator()(const CheapType& a) const { return a.value(); }\n};\n\nstruct HeterogeneousEqual {\n  using is_transparent = void;\n  bool operator()(const ExpensiveType& a, const ExpensiveType& b) const {\n    return a.value() == b.value();\n  }\n  bool operator()(const ExpensiveType& a, const CheapType& b) const {\n    return a.value() == b.value();\n  }\n  bool operator()(const CheapType& a, const ExpensiveType& b) const {\n    return a.value() == b.value();\n  }\n};\n\nMATCHER_P(HasExpensiveValue, n, \"\") {\n  return ::testing::ExplainMatchResult(n, arg.value(), result_listener);\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_HETEROGENEOUS_LOOKUP_TESTING_H_\n"
  },
  {
    "path": "absl/container/internal/inlined_vector.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_\n#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstring>\n#include <iterator>\n#include <limits>\n#include <memory>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/internal/compressed_tuple.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace inlined_vector_internal {\n\n// GCC does not deal very well with the below code\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Warray-bounds\"\n#endif\n\ntemplate <typename A>\nusing AllocatorTraits = std::allocator_traits<A>;\ntemplate <typename A>\nusing ValueType = typename AllocatorTraits<A>::value_type;\ntemplate <typename A>\nusing SizeType = typename AllocatorTraits<A>::size_type;\ntemplate <typename A>\nusing Pointer = typename AllocatorTraits<A>::pointer;\ntemplate <typename A>\nusing ConstPointer = typename AllocatorTraits<A>::const_pointer;\ntemplate <typename A>\nusing SizeType = typename AllocatorTraits<A>::size_type;\ntemplate <typename A>\nusing DifferenceType = typename AllocatorTraits<A>::difference_type;\ntemplate <typename A>\nusing Reference = ValueType<A>&;\ntemplate <typename A>\nusing ConstReference = const ValueType<A>&;\ntemplate <typename A>\nusing Iterator = Pointer<A>;\ntemplate <typename A>\nusing ConstIterator = ConstPointer<A>;\ntemplate <typename A>\nusing ReverseIterator = typename std::reverse_iterator<Iterator<A>>;\ntemplate <typename A>\nusing ConstReverseIterator = typename std::reverse_iterator<ConstIterator<A>>;\ntemplate <typename A>\nusing MoveIterator = typename std::move_iterator<Iterator<A>>;\n\ntemplate <typename A>\nusing IsMoveAssignOk = std::is_move_assignable<ValueType<A>>;\ntemplate <typename A>\nusing IsSwapOk = absl::type_traits_internal::IsSwappable<ValueType<A>>;\n\ntemplate <typename A,\n          bool IsTriviallyDestructible =\n              absl::is_trivially_destructible<ValueType<A>>::value &&\n              std::is_same<A, std::allocator<ValueType<A>>>::value>\nstruct DestroyAdapter;\n\ntemplate <typename A>\nstruct DestroyAdapter<A, /* IsTriviallyDestructible */ false> {\n  static void DestroyElements(A& allocator, Pointer<A> destroy_first,\n                              SizeType<A> destroy_size) {\n    for (SizeType<A> i = destroy_size; i != 0;) {\n      --i;\n      AllocatorTraits<A>::destroy(allocator, destroy_first + i);\n    }\n  }\n};\n\ntemplate <typename A>\nstruct DestroyAdapter<A, /* IsTriviallyDestructible */ true> {\n  static void DestroyElements(A& allocator, Pointer<A> destroy_first,\n                              SizeType<A> destroy_size) {\n    static_cast<void>(allocator);\n    static_cast<void>(destroy_first);\n    static_cast<void>(destroy_size);\n  }\n};\n\ntemplate <typename A>\nstruct Allocation {\n  Pointer<A> data = nullptr;\n  SizeType<A> capacity = 0;\n};\n\ntemplate <typename A,\n          bool IsOverAligned =\n              (alignof(ValueType<A>) > ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT)>\nstruct MallocAdapter {\n  static Allocation<A> Allocate(A& allocator, SizeType<A> requested_capacity) {\n    return {AllocatorTraits<A>::allocate(allocator, requested_capacity),\n            requested_capacity};\n  }\n\n  static void Deallocate(A& allocator, Pointer<A> pointer,\n                         SizeType<A> capacity) {\n    AllocatorTraits<A>::deallocate(allocator, pointer, capacity);\n  }\n};\n\ntemplate <typename A, typename ValueAdapter>\nvoid ConstructElements(absl::type_identity_t<A>& allocator,\n                       Pointer<A> construct_first, ValueAdapter& values,\n                       SizeType<A> construct_size) {\n  for (SizeType<A> i = 0; i < construct_size; ++i) {\n    ABSL_INTERNAL_TRY { values.ConstructNext(allocator, construct_first + i); }\n    ABSL_INTERNAL_CATCH_ANY {\n      DestroyAdapter<A>::DestroyElements(allocator, construct_first, i);\n      ABSL_INTERNAL_RETHROW;\n    }\n  }\n}\n\ntemplate <typename A, typename ValueAdapter>\nvoid AssignElements(Pointer<A> assign_first, ValueAdapter& values,\n                    SizeType<A> assign_size) {\n  for (SizeType<A> i = 0; i < assign_size; ++i) {\n    values.AssignNext(assign_first + i);\n  }\n}\n\ntemplate <typename A>\nstruct StorageView {\n  Pointer<A> data;\n  SizeType<A> size;\n  SizeType<A> capacity;\n};\n\ntemplate <typename A, typename Iterator>\nclass IteratorValueAdapter {\n public:\n  explicit IteratorValueAdapter(const Iterator& it) : it_(it) {}\n\n  void ConstructNext(A& allocator, Pointer<A> construct_at) {\n    AllocatorTraits<A>::construct(allocator, construct_at, *it_);\n    ++it_;\n  }\n\n  void AssignNext(Pointer<A> assign_at) {\n    *assign_at = *it_;\n    ++it_;\n  }\n\n private:\n  Iterator it_;\n};\n\ntemplate <typename A>\nclass CopyValueAdapter {\n public:\n  explicit CopyValueAdapter(ConstPointer<A> p) : ptr_(p) {}\n\n  void ConstructNext(A& allocator, Pointer<A> construct_at) {\n    AllocatorTraits<A>::construct(allocator, construct_at, *ptr_);\n  }\n\n  void AssignNext(Pointer<A> assign_at) { *assign_at = *ptr_; }\n\n private:\n  ConstPointer<A> ptr_;\n};\n\ntemplate <typename A>\nclass DefaultValueAdapter {\n public:\n  explicit DefaultValueAdapter() {}\n\n  void ConstructNext(A& allocator, Pointer<A> construct_at) {\n    AllocatorTraits<A>::construct(allocator, construct_at);\n  }\n\n  void AssignNext(Pointer<A> assign_at) { *assign_at = ValueType<A>(); }\n};\n\ntemplate <typename A>\nclass AllocationTransaction {\n public:\n  explicit AllocationTransaction(A& allocator)\n      : allocator_data_(allocator, nullptr), capacity_(0) {}\n\n  ~AllocationTransaction() {\n    if (DidAllocate()) {\n      MallocAdapter<A>::Deallocate(GetAllocator(), GetData(), GetCapacity());\n    }\n  }\n\n  AllocationTransaction(const AllocationTransaction&) = delete;\n  void operator=(const AllocationTransaction&) = delete;\n\n  A& GetAllocator() { return allocator_data_.template get<0>(); }\n  Pointer<A>& GetData() { return allocator_data_.template get<1>(); }\n  SizeType<A>& GetCapacity() { return capacity_; }\n\n  bool DidAllocate() { return GetData() != nullptr; }\n\n  Pointer<A> Allocate(SizeType<A> requested_capacity) {\n    Allocation<A> result =\n        MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);\n    GetData() = result.data;\n    GetCapacity() = result.capacity;\n    return result.data;\n  }\n\n  [[nodiscard]] Allocation<A> Release() && {\n    Allocation<A> result = {GetData(), GetCapacity()};\n    Reset();\n    return result;\n  }\n\n private:\n  void Reset() {\n    GetData() = nullptr;\n    GetCapacity() = 0;\n  }\n\n  container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;\n  SizeType<A> capacity_;\n};\n\ntemplate <typename A>\nclass ConstructionTransaction {\n public:\n  explicit ConstructionTransaction(A& allocator)\n      : allocator_data_(allocator, nullptr), size_(0) {}\n\n  ~ConstructionTransaction() {\n    if (DidConstruct()) {\n      DestroyAdapter<A>::DestroyElements(GetAllocator(), GetData(), GetSize());\n    }\n  }\n\n  ConstructionTransaction(const ConstructionTransaction&) = delete;\n  void operator=(const ConstructionTransaction&) = delete;\n\n  A& GetAllocator() { return allocator_data_.template get<0>(); }\n  Pointer<A>& GetData() { return allocator_data_.template get<1>(); }\n  SizeType<A>& GetSize() { return size_; }\n\n  bool DidConstruct() { return GetData() != nullptr; }\n  template <typename ValueAdapter>\n  void Construct(Pointer<A> data, ValueAdapter& values, SizeType<A> size) {\n    ConstructElements<A>(GetAllocator(), data, values, size);\n    GetData() = data;\n    GetSize() = size;\n  }\n  void Commit() && {\n    GetData() = nullptr;\n    GetSize() = 0;\n  }\n\n private:\n  container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;\n  SizeType<A> size_;\n};\n\ntemplate <typename T, size_t N, typename A>\nclass Storage {\n public:\n  struct MemcpyPolicy {};\n  struct ElementwiseAssignPolicy {};\n  struct ElementwiseSwapPolicy {};\n  struct ElementwiseConstructPolicy {};\n\n  using MoveAssignmentPolicy = absl::conditional_t<\n      // Fast path: if the value type can be trivially move assigned and\n      // destroyed, and we know the allocator doesn't do anything fancy, then\n      // it's safe for us to simply adopt the contents of the storage for\n      // `other` and remove its own reference to them. It's as if we had\n      // individually move-assigned each value and then destroyed the original.\n      absl::conjunction<absl::is_trivially_move_assignable<ValueType<A>>,\n                        absl::is_trivially_destructible<ValueType<A>>,\n                        std::is_same<A, std::allocator<ValueType<A>>>>::value,\n      MemcpyPolicy,\n      // Otherwise we use move assignment if possible. If not, we simulate\n      // move assignment using move construction.\n      //\n      // Note that this is in contrast to e.g. std::vector and std::optional,\n      // which are themselves not move-assignable when their contained type is\n      // not.\n      absl::conditional_t<IsMoveAssignOk<A>::value, ElementwiseAssignPolicy,\n                          ElementwiseConstructPolicy>>;\n\n  // The policy to be used specifically when swapping inlined elements.\n  using SwapInlinedElementsPolicy = absl::conditional_t<\n      // Fast path: if the value type can be trivially relocated, and we\n      // know the allocator doesn't do anything fancy, then it's safe for us\n      // to simply swap the bytes in the inline storage. It's as if we had\n      // relocated the first vector's elements into temporary storage,\n      // relocated the second's elements into the (now-empty) first's,\n      // and then relocated from temporary storage into the second.\n      absl::conjunction<absl::is_trivially_relocatable<ValueType<A>>,\n                        std::is_same<A, std::allocator<ValueType<A>>>>::value,\n      MemcpyPolicy,\n      absl::conditional_t<IsSwapOk<A>::value, ElementwiseSwapPolicy,\n                          ElementwiseConstructPolicy>>;\n\n  static SizeType<A> NextCapacity(SizeType<A> current_capacity) {\n    return current_capacity * 2;\n  }\n\n  static SizeType<A> ComputeCapacity(SizeType<A> current_capacity,\n                                     SizeType<A> requested_capacity) {\n    return (std::max)(NextCapacity(current_capacity), requested_capacity);\n  }\n\n  // ---------------------------------------------------------------------------\n  // Storage Constructors and Destructor\n  // ---------------------------------------------------------------------------\n\n  Storage() : metadata_(A(), /* size and is_allocated */ 0u) {}\n\n  explicit Storage(const A& allocator)\n      : metadata_(allocator, /* size and is_allocated */ 0u) {}\n\n  ~Storage() {\n    // Fast path: if we are empty and not allocated, there's nothing to do.\n    if (GetSizeAndIsAllocated() == 0) {\n      return;\n    }\n\n    // Fast path: if no destructors need to be run and we know the allocator\n    // doesn't do anything fancy, then all we need to do is deallocate (and\n    // maybe not even that).\n    if (absl::is_trivially_destructible<ValueType<A>>::value &&\n        std::is_same<A, std::allocator<ValueType<A>>>::value) {\n      DeallocateIfAllocated();\n      return;\n    }\n\n    DestroyContents();\n  }\n\n  // ---------------------------------------------------------------------------\n  // Storage Member Accessors\n  // ---------------------------------------------------------------------------\n\n  SizeType<A>& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }\n\n  const SizeType<A>& GetSizeAndIsAllocated() const {\n    return metadata_.template get<1>();\n  }\n\n  SizeType<A> GetSize() const { return GetSizeAndIsAllocated() >> 1; }\n\n  bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }\n\n  Pointer<A> GetAllocatedData() {\n    // GCC 12 has a false-positive -Wmaybe-uninitialized warning here.\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n#endif\n    return data_.allocated.allocated_data;\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic pop\n#endif\n  }\n\n  ConstPointer<A> GetAllocatedData() const {\n    return data_.allocated.allocated_data;\n  }\n\n  // ABSL_ATTRIBUTE_NO_SANITIZE_CFI is used because the memory pointed to may be\n  // uninitialized, a common pattern in allocate()+construct() APIs.\n  // https://clang.llvm.org/docs/ControlFlowIntegrity.html#bad-cast-checking\n  // NOTE: When this was written, LLVM documentation did not explicitly\n  // mention that casting `char*` and using `reinterpret_cast` qualifies\n  // as a bad cast.\n  ABSL_ATTRIBUTE_NO_SANITIZE_CFI Pointer<A> GetInlinedData() {\n    return reinterpret_cast<Pointer<A>>(data_.inlined.inlined_data);\n  }\n\n  ABSL_ATTRIBUTE_NO_SANITIZE_CFI ConstPointer<A> GetInlinedData() const {\n    return reinterpret_cast<ConstPointer<A>>(data_.inlined.inlined_data);\n  }\n\n  SizeType<A> GetAllocatedCapacity() const {\n    return data_.allocated.allocated_capacity;\n  }\n\n  SizeType<A> GetInlinedCapacity() const {\n    return static_cast<SizeType<A>>(kOptimalInlinedSize);\n  }\n\n  StorageView<A> MakeStorageView() {\n    return GetIsAllocated() ? StorageView<A>{GetAllocatedData(), GetSize(),\n                                             GetAllocatedCapacity()}\n                            : StorageView<A>{GetInlinedData(), GetSize(),\n                                             GetInlinedCapacity()};\n  }\n\n  A& GetAllocator() { return metadata_.template get<0>(); }\n\n  const A& GetAllocator() const { return metadata_.template get<0>(); }\n\n  // ---------------------------------------------------------------------------\n  // Storage Member Mutators\n  // ---------------------------------------------------------------------------\n\n  ABSL_ATTRIBUTE_NOINLINE void InitFrom(const Storage& other);\n\n  template <typename ValueAdapter>\n  void Initialize(ValueAdapter values, SizeType<A> new_size);\n\n  template <typename ValueAdapter>\n  void Assign(ValueAdapter values, SizeType<A> new_size);\n\n  template <typename ValueAdapter>\n  void Resize(ValueAdapter values, SizeType<A> new_size);\n\n  template <typename ValueAdapter>\n  Iterator<A> Insert(ConstIterator<A> pos, ValueAdapter values,\n                     SizeType<A> insert_count);\n\n  template <typename... Args>\n  Reference<A> EmplaceBack(Args&&... args);\n\n  Iterator<A> Erase(ConstIterator<A> from, ConstIterator<A> to);\n\n  void Reserve(SizeType<A> requested_capacity);\n\n  void ShrinkToFit();\n\n  void Swap(Storage* other_storage_ptr);\n\n  void SetIsAllocated() {\n    GetSizeAndIsAllocated() |= static_cast<SizeType<A>>(1);\n  }\n\n  void UnsetIsAllocated() {\n    GetSizeAndIsAllocated() &= ((std::numeric_limits<SizeType<A>>::max)() - 1);\n  }\n\n  void SetSize(SizeType<A> size) {\n    GetSizeAndIsAllocated() =\n        (size << 1) | static_cast<SizeType<A>>(GetIsAllocated());\n  }\n\n  void SetAllocatedSize(SizeType<A> size) {\n    GetSizeAndIsAllocated() = (size << 1) | static_cast<SizeType<A>>(1);\n  }\n\n  void SetInlinedSize(SizeType<A> size) {\n    GetSizeAndIsAllocated() = size << static_cast<SizeType<A>>(1);\n  }\n\n  void AddSize(SizeType<A> count) {\n    GetSizeAndIsAllocated() += count << static_cast<SizeType<A>>(1);\n  }\n\n  void SubtractSize(SizeType<A> count) {\n    ABSL_HARDENING_ASSERT(count <= GetSize());\n\n    GetSizeAndIsAllocated() -= count << static_cast<SizeType<A>>(1);\n  }\n\n  void SetAllocation(Allocation<A> allocation) {\n    data_.allocated.allocated_data = allocation.data;\n    data_.allocated.allocated_capacity = allocation.capacity;\n  }\n\n  void MemcpyFrom(const Storage& other_storage) {\n    // Assumption check: it doesn't make sense to memcpy inlined elements unless\n    // we know the allocator doesn't do anything fancy, and one of the following\n    // holds:\n    //\n    //  *  The elements are trivially relocatable.\n    //\n    //  *  It's possible to trivially assign the elements and then destroy the\n    //     source.\n    //\n    //  *  It's possible to trivially copy construct/assign the elements.\n    //\n    {\n      using V = ValueType<A>;\n      ABSL_HARDENING_ASSERT(\n          other_storage.GetIsAllocated() ||\n          (std::is_same<A, std::allocator<V>>::value &&\n           (\n               // First case above\n               absl::is_trivially_relocatable<V>::value ||\n               // Second case above\n               (absl::is_trivially_move_assignable<V>::value &&\n                absl::is_trivially_destructible<V>::value) ||\n               // Third case above\n               (absl::is_trivially_copy_constructible<V>::value ||\n                absl::is_trivially_copy_assignable<V>::value))));\n    }\n\n    GetSizeAndIsAllocated() = other_storage.GetSizeAndIsAllocated();\n    data_ = other_storage.data_;\n  }\n\n  void DeallocateIfAllocated() {\n    if (GetIsAllocated()) {\n      MallocAdapter<A>::Deallocate(GetAllocator(), GetAllocatedData(),\n                                   GetAllocatedCapacity());\n    }\n  }\n\n private:\n  ABSL_ATTRIBUTE_NOINLINE void DestroyContents();\n\n  using Metadata = container_internal::CompressedTuple<A, SizeType<A>>;\n\n  struct Allocated {\n    Pointer<A> allocated_data;\n    SizeType<A> allocated_capacity;\n  };\n\n  // `kOptimalInlinedSize` is an automatically adjusted inlined capacity of the\n  // `InlinedVector`. Sometimes, it is possible to increase the capacity (from\n  // the user requested `N`) without increasing the size of the `InlinedVector`.\n  static constexpr size_t kOptimalInlinedSize =\n      (std::max)(N, sizeof(Allocated) / sizeof(ValueType<A>));\n\n  struct Inlined {\n    alignas(ValueType<A>) unsigned char inlined_data[sizeof(\n        ValueType<A>[kOptimalInlinedSize])];\n  };\n\n  union Data {\n    Allocated allocated;\n    Inlined inlined;\n  };\n\n  void SwapN(ElementwiseSwapPolicy, Storage* other, SizeType<A> n);\n  void SwapN(ElementwiseConstructPolicy, Storage* other, SizeType<A> n);\n\n  void SwapInlinedElements(MemcpyPolicy, Storage* other);\n  template <typename NotMemcpyPolicy>\n  void SwapInlinedElements(NotMemcpyPolicy, Storage* other);\n\n  template <typename... Args>\n  ABSL_ATTRIBUTE_NOINLINE Reference<A> EmplaceBackSlow(Args&&... args);\n\n  Metadata metadata_;\n  Data data_;\n};\n\ntemplate <typename T, size_t N, typename A>\nvoid Storage<T, N, A>::DestroyContents() {\n  Pointer<A> data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();\n  DestroyAdapter<A>::DestroyElements(GetAllocator(), data, GetSize());\n  DeallocateIfAllocated();\n}\n\ntemplate <typename T, size_t N, typename A>\nvoid Storage<T, N, A>::InitFrom(const Storage& other) {\n  const SizeType<A> n = other.GetSize();\n  ABSL_HARDENING_ASSERT(n > 0);  // Empty sources handled handled in caller.\n  ConstPointer<A> src;\n  Pointer<A> dst;\n  if (!other.GetIsAllocated()) {\n    dst = GetInlinedData();\n    src = other.GetInlinedData();\n  } else {\n    // Because this is only called from the `InlinedVector` constructors, it's\n    // safe to take on the allocation with size `0`. If `ConstructElements(...)`\n    // throws, deallocation will be automatically handled by `~Storage()`.\n    SizeType<A> requested_capacity = ComputeCapacity(GetInlinedCapacity(), n);\n    Allocation<A> allocation =\n        MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);\n    SetAllocation(allocation);\n    dst = allocation.data;\n    src = other.GetAllocatedData();\n  }\n\n  // Fast path: if the value type is trivially copy constructible and we know\n  // the allocator doesn't do anything fancy, then we know it is legal for us to\n  // simply memcpy the other vector's elements.\n  if (absl::is_trivially_copy_constructible<ValueType<A>>::value &&\n      std::is_same<A, std::allocator<ValueType<A>>>::value) {\n    std::memcpy(reinterpret_cast<char*>(dst),\n                reinterpret_cast<const char*>(src), n * sizeof(ValueType<A>));\n  } else {\n    auto values = IteratorValueAdapter<A, ConstPointer<A>>(src);\n    ConstructElements<A>(GetAllocator(), dst, values, n);\n  }\n\n  GetSizeAndIsAllocated() = other.GetSizeAndIsAllocated();\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename ValueAdapter>\nauto Storage<T, N, A>::Initialize(ValueAdapter values,\n                                  SizeType<A> new_size) -> void {\n  // Only callable from constructors!\n  ABSL_HARDENING_ASSERT(!GetIsAllocated());\n  ABSL_HARDENING_ASSERT(GetSize() == 0);\n\n  Pointer<A> construct_data;\n  if (new_size > GetInlinedCapacity()) {\n    // Because this is only called from the `InlinedVector` constructors, it's\n    // safe to take on the allocation with size `0`. If `ConstructElements(...)`\n    // throws, deallocation will be automatically handled by `~Storage()`.\n    SizeType<A> requested_capacity =\n        ComputeCapacity(GetInlinedCapacity(), new_size);\n    Allocation<A> allocation =\n        MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);\n    construct_data = allocation.data;\n    SetAllocation(allocation);\n    SetIsAllocated();\n  } else {\n    construct_data = GetInlinedData();\n  }\n\n  ConstructElements<A>(GetAllocator(), construct_data, values, new_size);\n\n  // Since the initial size was guaranteed to be `0` and the allocated bit is\n  // already correct for either case, *adding* `new_size` gives us the correct\n  // result faster than setting it directly.\n  AddSize(new_size);\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename ValueAdapter>\nauto Storage<T, N, A>::Assign(ValueAdapter values,\n                              SizeType<A> new_size) -> void {\n  StorageView<A> storage_view = MakeStorageView();\n\n  AllocationTransaction<A> allocation_tx(GetAllocator());\n\n  absl::Span<ValueType<A>> assign_loop;\n  absl::Span<ValueType<A>> construct_loop;\n  absl::Span<ValueType<A>> destroy_loop;\n\n  if (new_size > storage_view.capacity) {\n    SizeType<A> requested_capacity =\n        ComputeCapacity(storage_view.capacity, new_size);\n    construct_loop = {allocation_tx.Allocate(requested_capacity), new_size};\n    destroy_loop = {storage_view.data, storage_view.size};\n  } else if (new_size > storage_view.size) {\n    assign_loop = {storage_view.data, storage_view.size};\n    construct_loop = {storage_view.data + storage_view.size,\n                      new_size - storage_view.size};\n  } else {\n    assign_loop = {storage_view.data, new_size};\n    destroy_loop = {storage_view.data + new_size, storage_view.size - new_size};\n  }\n\n  AssignElements<A>(assign_loop.data(), values, assign_loop.size());\n\n  ConstructElements<A>(GetAllocator(), construct_loop.data(), values,\n                       construct_loop.size());\n\n  DestroyAdapter<A>::DestroyElements(GetAllocator(), destroy_loop.data(),\n                                     destroy_loop.size());\n\n  if (allocation_tx.DidAllocate()) {\n    DeallocateIfAllocated();\n    SetAllocation(std::move(allocation_tx).Release());\n    SetIsAllocated();\n  }\n\n  SetSize(new_size);\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename ValueAdapter>\nauto Storage<T, N, A>::Resize(ValueAdapter values,\n                              SizeType<A> new_size) -> void {\n  StorageView<A> storage_view = MakeStorageView();\n  Pointer<A> const base = storage_view.data;\n  const SizeType<A> size = storage_view.size;\n  A& alloc = GetAllocator();\n  if (new_size <= size) {\n    // Destroy extra old elements.\n    DestroyAdapter<A>::DestroyElements(alloc, base + new_size, size - new_size);\n  } else if (new_size <= storage_view.capacity) {\n    // Construct new elements in place.\n    ConstructElements<A>(alloc, base + size, values, new_size - size);\n  } else {\n    // Steps:\n    //  a. Allocate new backing store.\n    //  b. Construct new elements in new backing store.\n    //  c. Move existing elements from old backing store to new backing store.\n    //  d. Destroy all elements in old backing store.\n    // Use transactional wrappers for the first two steps so we can roll\n    // back if necessary due to exceptions.\n    AllocationTransaction<A> allocation_tx(alloc);\n    SizeType<A> requested_capacity =\n        ComputeCapacity(storage_view.capacity, new_size);\n    Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);\n\n    ConstructionTransaction<A> construction_tx(alloc);\n    construction_tx.Construct(new_data + size, values, new_size - size);\n\n    IteratorValueAdapter<A, MoveIterator<A>> move_values(\n        (MoveIterator<A>(base)));\n    ConstructElements<A>(alloc, new_data, move_values, size);\n\n    DestroyAdapter<A>::DestroyElements(alloc, base, size);\n    std::move(construction_tx).Commit();\n    DeallocateIfAllocated();\n    SetAllocation(std::move(allocation_tx).Release());\n    SetIsAllocated();\n  }\n  SetSize(new_size);\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename ValueAdapter>\nauto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,\n                              SizeType<A> insert_count) -> Iterator<A> {\n  StorageView<A> storage_view = MakeStorageView();\n\n  auto insert_index = static_cast<SizeType<A>>(\n      std::distance(ConstIterator<A>(storage_view.data), pos));\n  SizeType<A> insert_end_index = insert_index + insert_count;\n  SizeType<A> new_size = storage_view.size + insert_count;\n\n  if (new_size > storage_view.capacity) {\n    AllocationTransaction<A> allocation_tx(GetAllocator());\n    ConstructionTransaction<A> construction_tx(GetAllocator());\n    ConstructionTransaction<A> move_construction_tx(GetAllocator());\n\n    IteratorValueAdapter<A, MoveIterator<A>> move_values(\n        MoveIterator<A>(storage_view.data));\n\n    SizeType<A> requested_capacity =\n        ComputeCapacity(storage_view.capacity, new_size);\n    Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);\n\n    construction_tx.Construct(new_data + insert_index, values, insert_count);\n\n    move_construction_tx.Construct(new_data, move_values, insert_index);\n\n    ConstructElements<A>(GetAllocator(), new_data + insert_end_index,\n                         move_values, storage_view.size - insert_index);\n\n    DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,\n                                       storage_view.size);\n\n    std::move(construction_tx).Commit();\n    std::move(move_construction_tx).Commit();\n    DeallocateIfAllocated();\n    SetAllocation(std::move(allocation_tx).Release());\n\n    SetAllocatedSize(new_size);\n    return Iterator<A>(new_data + insert_index);\n  } else {\n    SizeType<A> move_construction_destination_index =\n        (std::max)(insert_end_index, storage_view.size);\n\n    ConstructionTransaction<A> move_construction_tx(GetAllocator());\n\n    IteratorValueAdapter<A, MoveIterator<A>> move_construction_values(\n        MoveIterator<A>(storage_view.data +\n                        (move_construction_destination_index - insert_count)));\n    absl::Span<ValueType<A>> move_construction = {\n        storage_view.data + move_construction_destination_index,\n        new_size - move_construction_destination_index};\n\n    Pointer<A> move_assignment_values = storage_view.data + insert_index;\n    absl::Span<ValueType<A>> move_assignment = {\n        storage_view.data + insert_end_index,\n        move_construction_destination_index - insert_end_index};\n\n    absl::Span<ValueType<A>> insert_assignment = {move_assignment_values,\n                                                  move_construction.size()};\n\n    absl::Span<ValueType<A>> insert_construction = {\n        insert_assignment.data() + insert_assignment.size(),\n        insert_count - insert_assignment.size()};\n\n    move_construction_tx.Construct(move_construction.data(),\n                                   move_construction_values,\n                                   move_construction.size());\n\n    std::move_backward(move_assignment_values,\n                       move_assignment_values + move_assignment.size(),\n                       move_assignment.data() + move_assignment.size());\n\n    AssignElements<A>(insert_assignment.data(), values,\n                      insert_assignment.size());\n\n    ConstructElements<A>(GetAllocator(), insert_construction.data(), values,\n                         insert_construction.size());\n\n    std::move(move_construction_tx).Commit();\n\n    AddSize(insert_count);\n    return Iterator<A>(storage_view.data + insert_index);\n  }\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename... Args>\nauto Storage<T, N, A>::EmplaceBack(Args&&... args) -> Reference<A> {\n  StorageView<A> storage_view = MakeStorageView();\n  const SizeType<A> n = storage_view.size;\n  if (ABSL_PREDICT_TRUE(n != storage_view.capacity)) {\n    // Fast path; new element fits.\n    Pointer<A> last_ptr = storage_view.data + n;\n    AllocatorTraits<A>::construct(GetAllocator(), last_ptr,\n                                  std::forward<Args>(args)...);\n    AddSize(1);\n    return *last_ptr;\n  }\n  // TODO(b/173712035): Annotate with musttail attribute to prevent regression.\n  return EmplaceBackSlow(std::forward<Args>(args)...);\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename... Args>\nauto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> {\n  StorageView<A> storage_view = MakeStorageView();\n  AllocationTransaction<A> allocation_tx(GetAllocator());\n  IteratorValueAdapter<A, MoveIterator<A>> move_values(\n      MoveIterator<A>(storage_view.data));\n  SizeType<A> requested_capacity = NextCapacity(storage_view.capacity);\n  Pointer<A> construct_data = allocation_tx.Allocate(requested_capacity);\n  Pointer<A> last_ptr = construct_data + storage_view.size;\n\n  // Construct new element.\n  AllocatorTraits<A>::construct(GetAllocator(), last_ptr,\n                                std::forward<Args>(args)...);\n  // Move elements from old backing store to new backing store.\n  ABSL_INTERNAL_TRY {\n    ConstructElements<A>(GetAllocator(), allocation_tx.GetData(), move_values,\n                         storage_view.size);\n  }\n  ABSL_INTERNAL_CATCH_ANY {\n    AllocatorTraits<A>::destroy(GetAllocator(), last_ptr);\n    ABSL_INTERNAL_RETHROW;\n  }\n  // Destroy elements in old backing store.\n  DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,\n                                     storage_view.size);\n\n  DeallocateIfAllocated();\n  SetAllocation(std::move(allocation_tx).Release());\n  SetIsAllocated();\n  AddSize(1);\n  return *last_ptr;\n}\n\ntemplate <typename T, size_t N, typename A>\nauto Storage<T, N, A>::Erase(ConstIterator<A> from,\n                             ConstIterator<A> to) -> Iterator<A> {\n  StorageView<A> storage_view = MakeStorageView();\n\n  auto erase_size = static_cast<SizeType<A>>(std::distance(from, to));\n  auto erase_index = static_cast<SizeType<A>>(\n      std::distance(ConstIterator<A>(storage_view.data), from));\n  SizeType<A> erase_end_index = erase_index + erase_size;\n\n  // Fast path: if the value type is trivially relocatable and we know\n  // the allocator doesn't do anything fancy, then we know it is legal for us to\n  // simply destroy the elements in the \"erasure window\" (which cannot throw)\n  // and then memcpy downward to close the window.\n  if (absl::is_trivially_relocatable<ValueType<A>>::value &&\n      std::is_nothrow_destructible<ValueType<A>>::value &&\n      std::is_same<A, std::allocator<ValueType<A>>>::value) {\n    DestroyAdapter<A>::DestroyElements(\n        GetAllocator(), storage_view.data + erase_index, erase_size);\n    std::memmove(\n        reinterpret_cast<char*>(storage_view.data + erase_index),\n        reinterpret_cast<const char*>(storage_view.data + erase_end_index),\n        (storage_view.size - erase_end_index) * sizeof(ValueType<A>));\n  } else {\n    IteratorValueAdapter<A, MoveIterator<A>> move_values(\n        MoveIterator<A>(storage_view.data + erase_end_index));\n\n    AssignElements<A>(storage_view.data + erase_index, move_values,\n                      storage_view.size - erase_end_index);\n\n    DestroyAdapter<A>::DestroyElements(\n        GetAllocator(), storage_view.data + (storage_view.size - erase_size),\n        erase_size);\n  }\n  SubtractSize(erase_size);\n  return Iterator<A>(storage_view.data + erase_index);\n}\n\ntemplate <typename T, size_t N, typename A>\nauto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void {\n  StorageView<A> storage_view = MakeStorageView();\n\n  if (ABSL_PREDICT_FALSE(requested_capacity <= storage_view.capacity)) return;\n\n  AllocationTransaction<A> allocation_tx(GetAllocator());\n\n  IteratorValueAdapter<A, MoveIterator<A>> move_values(\n      MoveIterator<A>(storage_view.data));\n\n  SizeType<A> new_requested_capacity =\n      ComputeCapacity(storage_view.capacity, requested_capacity);\n  Pointer<A> new_data = allocation_tx.Allocate(new_requested_capacity);\n\n  ConstructElements<A>(GetAllocator(), new_data, move_values,\n                       storage_view.size);\n\n  DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,\n                                     storage_view.size);\n\n  DeallocateIfAllocated();\n  SetAllocation(std::move(allocation_tx).Release());\n  SetIsAllocated();\n}\n\ntemplate <typename T, size_t N, typename A>\nauto Storage<T, N, A>::ShrinkToFit() -> void {\n  // May only be called on allocated instances!\n  ABSL_HARDENING_ASSERT(GetIsAllocated());\n\n  StorageView<A> storage_view{GetAllocatedData(), GetSize(),\n                              GetAllocatedCapacity()};\n\n  if (ABSL_PREDICT_FALSE(storage_view.size == storage_view.capacity)) return;\n\n  AllocationTransaction<A> allocation_tx(GetAllocator());\n\n  IteratorValueAdapter<A, MoveIterator<A>> move_values(\n      MoveIterator<A>(storage_view.data));\n\n  Pointer<A> construct_data;\n  if (storage_view.size > GetInlinedCapacity()) {\n    SizeType<A> requested_capacity = storage_view.size;\n    construct_data = allocation_tx.Allocate(requested_capacity);\n    if (allocation_tx.GetCapacity() >= storage_view.capacity) {\n      // Already using the smallest available heap allocation.\n      return;\n    }\n  } else {\n    construct_data = GetInlinedData();\n  }\n\n  ABSL_INTERNAL_TRY {\n    ConstructElements<A>(GetAllocator(), construct_data, move_values,\n                         storage_view.size);\n  }\n  ABSL_INTERNAL_CATCH_ANY {\n    SetAllocation({storage_view.data, storage_view.capacity});\n    ABSL_INTERNAL_RETHROW;\n  }\n\n  DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,\n                                     storage_view.size);\n\n  MallocAdapter<A>::Deallocate(GetAllocator(), storage_view.data,\n                               storage_view.capacity);\n\n  if (allocation_tx.DidAllocate()) {\n    SetAllocation(std::move(allocation_tx).Release());\n  } else {\n    UnsetIsAllocated();\n  }\n}\n\ntemplate <typename T, size_t N, typename A>\nauto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {\n  using std::swap;\n  ABSL_HARDENING_ASSERT(this != other_storage_ptr);\n\n  if (GetIsAllocated() && other_storage_ptr->GetIsAllocated()) {\n    swap(data_.allocated, other_storage_ptr->data_.allocated);\n  } else if (!GetIsAllocated() && !other_storage_ptr->GetIsAllocated()) {\n    SwapInlinedElements(SwapInlinedElementsPolicy{}, other_storage_ptr);\n  } else {\n    Storage* allocated_ptr = this;\n    Storage* inlined_ptr = other_storage_ptr;\n    if (!allocated_ptr->GetIsAllocated()) swap(allocated_ptr, inlined_ptr);\n\n    StorageView<A> allocated_storage_view{\n        allocated_ptr->GetAllocatedData(), allocated_ptr->GetSize(),\n        allocated_ptr->GetAllocatedCapacity()};\n\n    IteratorValueAdapter<A, MoveIterator<A>> move_values(\n        MoveIterator<A>(inlined_ptr->GetInlinedData()));\n\n    ABSL_INTERNAL_TRY {\n      ConstructElements<A>(inlined_ptr->GetAllocator(),\n                           allocated_ptr->GetInlinedData(), move_values,\n                           inlined_ptr->GetSize());\n    }\n    ABSL_INTERNAL_CATCH_ANY {\n      allocated_ptr->SetAllocation(Allocation<A>{\n          allocated_storage_view.data, allocated_storage_view.capacity});\n      ABSL_INTERNAL_RETHROW;\n    }\n\n    DestroyAdapter<A>::DestroyElements(inlined_ptr->GetAllocator(),\n                                       inlined_ptr->GetInlinedData(),\n                                       inlined_ptr->GetSize());\n\n    inlined_ptr->SetAllocation(Allocation<A>{allocated_storage_view.data,\n                                             allocated_storage_view.capacity});\n  }\n\n  swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated());\n  swap(GetAllocator(), other_storage_ptr->GetAllocator());\n}\n\ntemplate <typename T, size_t N, typename A>\nvoid Storage<T, N, A>::SwapN(ElementwiseSwapPolicy, Storage* other,\n                             SizeType<A> n) {\n  std::swap_ranges(GetInlinedData(), GetInlinedData() + n,\n                   other->GetInlinedData());\n}\n\ntemplate <typename T, size_t N, typename A>\nvoid Storage<T, N, A>::SwapN(ElementwiseConstructPolicy, Storage* other,\n                             SizeType<A> n) {\n  Pointer<A> a = GetInlinedData();\n  Pointer<A> b = other->GetInlinedData();\n  // see note on allocators in `SwapInlinedElements`.\n  A& allocator_a = GetAllocator();\n  A& allocator_b = other->GetAllocator();\n  for (SizeType<A> i = 0; i < n; ++i, ++a, ++b) {\n    ValueType<A> tmp(std::move(*a));\n\n    AllocatorTraits<A>::destroy(allocator_a, a);\n    AllocatorTraits<A>::construct(allocator_b, a, std::move(*b));\n\n    AllocatorTraits<A>::destroy(allocator_b, b);\n    AllocatorTraits<A>::construct(allocator_a, b, std::move(tmp));\n  }\n}\n\ntemplate <typename T, size_t N, typename A>\nvoid Storage<T, N, A>::SwapInlinedElements(MemcpyPolicy, Storage* other) {\n  Data tmp = data_;\n  data_ = other->data_;\n  other->data_ = tmp;\n}\n\ntemplate <typename T, size_t N, typename A>\ntemplate <typename NotMemcpyPolicy>\nvoid Storage<T, N, A>::SwapInlinedElements(NotMemcpyPolicy policy,\n                                           Storage* other) {\n  // Note: `destroy` needs to use pre-swap allocator while `construct` -\n  // post-swap allocator. Allocators will be swapped later on outside of\n  // `SwapInlinedElements`.\n  Storage* small_ptr = this;\n  Storage* large_ptr = other;\n  if (small_ptr->GetSize() > large_ptr->GetSize()) {\n    std::swap(small_ptr, large_ptr);\n  }\n\n  auto small_size = small_ptr->GetSize();\n  auto diff = large_ptr->GetSize() - small_size;\n  SwapN(policy, other, small_size);\n\n  IteratorValueAdapter<A, MoveIterator<A>> move_values(\n      MoveIterator<A>(large_ptr->GetInlinedData() + small_size));\n\n  ConstructElements<A>(large_ptr->GetAllocator(),\n                       small_ptr->GetInlinedData() + small_size, move_values,\n                       diff);\n\n  DestroyAdapter<A>::DestroyElements(large_ptr->GetAllocator(),\n                                     large_ptr->GetInlinedData() + small_size,\n                                     diff);\n}\n\n// End ignore \"array-bounds\"\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n\n}  // namespace inlined_vector_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_\n"
  },
  {
    "path": "absl/container/internal/layout.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n//                           MOTIVATION AND TUTORIAL\n//\n// If you want to put in a single heap allocation N doubles followed by M ints,\n// it's easy if N and M are known at compile time.\n//\n//   struct S {\n//     double a[N];\n//     int b[M];\n//   };\n//\n//   S* p = new S;\n//\n// But what if N and M are known only in run time? Class template Layout to the\n// rescue! It's a portable generalization of the technique known as struct hack.\n//\n//   // This object will tell us everything we need to know about the memory\n//   // layout of double[N] followed by int[M]. It's structurally identical to\n//   // size_t[2] that stores N and M. It's very cheap to create.\n//   const Layout<double, int> layout(N, M);\n//\n//   // Allocate enough memory for both arrays. `AllocSize()` tells us how much\n//   // memory is needed. We are free to use any allocation function we want as\n//   // long as it returns aligned memory.\n//   std::unique_ptr<unsigned char[]> p(new unsigned char[layout.AllocSize()]);\n//\n//   // Obtain the pointer to the array of doubles.\n//   // Equivalent to `reinterpret_cast<double*>(p.get())`.\n//   //\n//   // We could have written layout.Pointer<0>(p) instead. If all the types are\n//   // unique you can use either form, but if some types are repeated you must\n//   // use the index form.\n//   double* a = layout.Pointer<double>(p.get());\n//\n//   // Obtain the pointer to the array of ints.\n//   // Equivalent to `reinterpret_cast<int*>(p.get() + N * 8)`.\n//   int* b = layout.Pointer<int>(p);\n//\n// If we are unable to specify sizes of all fields, we can pass as many sizes as\n// we can to `Partial()`. In return, it'll allow us to access the fields whose\n// locations and sizes can be computed from the provided information.\n// `Partial()` comes in handy when the array sizes are embedded into the\n// allocation.\n//\n//   // size_t[0] containing N, size_t[1] containing M, double[N], int[M].\n//   using L = Layout<size_t, size_t, double, int>;\n//\n//   unsigned char* Allocate(size_t n, size_t m) {\n//     const L layout(1, 1, n, m);\n//     unsigned char* p = new unsigned char[layout.AllocSize()];\n//     *layout.Pointer<0>(p) = n;\n//     *layout.Pointer<1>(p) = m;\n//     return p;\n//   }\n//\n//   void Use(unsigned char* p) {\n//     // First, extract N and M.\n//     // Specify that the first array has only one element. Using `prefix` we\n//     // can access the first two arrays but not more.\n//     constexpr auto prefix = L::Partial(1);\n//     size_t n = *prefix.Pointer<0>(p);\n//     size_t m = *prefix.Pointer<1>(p);\n//\n//     // Now we can get pointers to the payload.\n//     const L layout(1, 1, n, m);\n//     double* a = layout.Pointer<double>(p);\n//     int* b = layout.Pointer<int>(p);\n//   }\n//\n// The layout we used above combines fixed-size with dynamically-sized fields.\n// This is quite common. Layout is optimized for this use case and attempts to\n// generate optimal code. To help the compiler do that in more cases, you can\n// specify the fixed sizes using `WithStaticSizes`. This ensures that all\n// computations that can be performed at compile time are indeed performed at\n// compile time. Note that sometimes the `template` keyword is needed. E.g.:\n//\n//   using SL = L::template WithStaticSizes<1, 1>;\n//\n//   void Use(unsigned char* p) {\n//     // First, extract N and M.\n//     // Using `prefix` we can access the first three arrays but not more.\n//     //\n//     // More details: The first element always has offset 0. `SL`\n//     // has offsets for the second and third array based on sizes of\n//     // the first and second array, specified via `WithStaticSizes`.\n//     constexpr auto prefix = SL::Partial();\n//     size_t n = *prefix.Pointer<0>(p);\n//     size_t m = *prefix.Pointer<1>(p);\n//\n//     // Now we can get a pointer to the final payload.\n//     const SL layout(n, m);\n//     double* a = layout.Pointer<double>(p);\n//     int* b = layout.Pointer<int>(p);\n//   }\n//\n// Efficiency tip: The order of fields matters. In `Layout<T1, ..., TN>` try to\n// ensure that `alignof(T1) >= ... >= alignof(TN)`. This way you'll have no\n// padding in between arrays.\n//\n// You can manually override the alignment of an array by wrapping the type in\n// `Aligned<T, N>`. `Layout<..., Aligned<T, N>, ...>` has exactly the same API\n// and behavior as `Layout<..., T, ...>` except that the first element of the\n// array of `T` is aligned to `N` (the rest of the elements follow without\n// padding). `N` cannot be less than `alignof(T)`.\n//\n// `AllocSize()` and `Pointer()` are the most basic methods for dealing with\n// memory layouts. Check out the reference or code below to discover more.\n//\n//                            EXAMPLE\n//\n//   // Immutable move-only string with sizeof equal to sizeof(void*). The\n//   // string size and the characters are kept in the same heap allocation.\n//   class CompactString {\n//    public:\n//     CompactString(const char* s = \"\") {\n//       const size_t size = strlen(s);\n//       // size_t[1] followed by char[size + 1].\n//       const L layout(size + 1);\n//       p_.reset(new unsigned char[layout.AllocSize()]);\n//       // If running under ASAN, mark the padding bytes, if any, to catch\n//       // memory errors.\n//       layout.PoisonPadding(p_.get());\n//       // Store the size in the allocation.\n//       *layout.Pointer<size_t>(p_.get()) = size;\n//       // Store the characters in the allocation.\n//       memcpy(layout.Pointer<char>(p_.get()), s, size + 1);\n//     }\n//\n//     size_t size() const {\n//       // Equivalent to reinterpret_cast<size_t&>(*p).\n//       return *L::Partial().Pointer<size_t>(p_.get());\n//     }\n//\n//     const char* c_str() const {\n//       // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).\n//       return L::Partial().Pointer<char>(p_.get());\n//     }\n//\n//    private:\n//     // Our heap allocation contains a single size_t followed by an array of\n//     // chars.\n//     using L = Layout<size_t, char>::WithStaticSizes<1>;\n//     std::unique_ptr<unsigned char[]> p_;\n//   };\n//\n//   int main() {\n//     CompactString s = \"hello\";\n//     assert(s.size() == 5);\n//     assert(strcmp(s.c_str(), \"hello\") == 0);\n//   }\n//\n//                               DOCUMENTATION\n//\n// The interface exported by this file consists of:\n// - class `Layout<>` and its public members.\n// - The public members of classes `internal_layout::LayoutWithStaticSizes<>`\n//   and `internal_layout::LayoutImpl<>`. Those classes aren't intended to be\n//   used directly, and their name and template parameter list are internal\n//   implementation details, but the classes themselves provide most of the\n//   functionality in this file. See comments on their members for detailed\n//   documentation.\n//\n// `Layout<T1,... Tn>::Partial(count1,..., countm)` (where `m` <= `n`) returns a\n// `LayoutImpl<>` object. `Layout<T1,..., Tn> layout(count1,..., countn)`\n// creates a `Layout` object, which exposes the same functionality by inheriting\n// from `LayoutImpl<>`.\n\n#ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_\n#define ABSL_CONTAINER_INTERNAL_LAYOUT_H_\n\n#include <assert.h>\n#include <stddef.h>\n#include <stdint.h>\n\n#include <array>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <typeinfo>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/debugging/internal/demangle.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/types/span.h\"\n#include \"absl/utility/utility.h\"\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n#include <sanitizer/asan_interface.h>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// A type wrapper that instructs `Layout` to use the specific alignment for the\n// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API\n// and behavior as `Layout<..., T, ...>` except that the first element of the\n// array of `T` is aligned to `N` (the rest of the elements follow without\n// padding).\n//\n// Requires: `N >= alignof(T)` and `N` is a power of 2.\ntemplate <class T, size_t N>\nstruct Aligned;\n\nnamespace internal_layout {\n\ntemplate <class T>\nstruct NotAligned {};\n\ntemplate <class T, size_t N>\nstruct NotAligned<const Aligned<T, N>> {\n  static_assert(sizeof(T) == 0, \"Aligned<T, N> cannot be const-qualified\");\n};\n\ntemplate <size_t>\nusing IntToSize = size_t;\n\ntemplate <class T>\nstruct Type : NotAligned<T> {\n  using type = T;\n};\n\ntemplate <class T, size_t N>\nstruct Type<Aligned<T, N>> {\n  using type = T;\n};\n\ntemplate <class T>\nstruct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};\n\ntemplate <class T, size_t N>\nstruct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};\n\n// Note: workaround for https://gcc.gnu.org/PR88115\ntemplate <class T>\nstruct AlignOf : NotAligned<T> {\n  static constexpr size_t value = alignof(T);\n};\n\ntemplate <class T, size_t N>\nstruct AlignOf<Aligned<T, N>> {\n  static_assert(N % alignof(T) == 0,\n                \"Custom alignment can't be lower than the type's alignment\");\n  static constexpr size_t value = N;\n};\n\n// Does `Ts...` contain `T`?\ntemplate <class T, class... Ts>\nusing Contains = absl::disjunction<std::is_same<T, Ts>...>;\n\ntemplate <class From, class To>\nusing CopyConst =\n    typename std::conditional<std::is_const<From>::value, const To, To>::type;\n\n// Note: We're not qualifying this with absl:: because it doesn't compile under\n// MSVC.\ntemplate <class T>\nusing SliceType = Span<T>;\n\n// This namespace contains no types. It prevents functions defined in it from\n// being found by ADL.\nnamespace adl_barrier {\n\ntemplate <class Needle, class... Ts>\nconstexpr size_t Find(Needle, Needle, Ts...) {\n  static_assert(!Contains<Needle, Ts...>(), \"Duplicate element type\");\n  return 0;\n}\n\ntemplate <class Needle, class T, class... Ts>\nconstexpr size_t Find(Needle, T, Ts...) {\n  return adl_barrier::Find(Needle(), Ts()...) + 1;\n}\n\nconstexpr bool IsPow2(size_t n) { return !(n & (n - 1)); }\n\n// Returns `q * m` for the smallest `q` such that `q * m >= n`.\n// Requires: `m` is a power of two. It's enforced by IsLegalElementType below.\nconstexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }\n\nconstexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; }\n\nconstexpr size_t Max(size_t a) { return a; }\n\ntemplate <class... Ts>\nconstexpr size_t Max(size_t a, size_t b, Ts... rest) {\n  return adl_barrier::Max(b < a ? a : b, rest...);\n}\n\ntemplate <class T>\nstd::string TypeName() {\n  std::string out;\n#ifdef ABSL_INTERNAL_HAS_RTTI\n  absl::StrAppend(&out, \"<\",\n                  absl::debugging_internal::DemangleString(typeid(T).name()),\n                  \">\");\n#endif\n  return out;\n}\n\n}  // namespace adl_barrier\n\n// Can `T` be a template argument of `Layout`?\ntemplate <class T>\nusing IsLegalElementType = std::integral_constant<\n    bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&\n              !std::is_reference<typename Type<T>::type>::value &&\n              !std::is_volatile<typename Type<T>::type>::value &&\n              adl_barrier::IsPow2(AlignOf<T>::value)>;\n\ntemplate <class Elements, class StaticSizeSeq, class RuntimeSizeSeq,\n          class SizeSeq, class OffsetSeq>\nclass LayoutImpl;\n\n// Public base class of `Layout` and the result type of `Layout::Partial()`.\n//\n// `Elements...` contains all template arguments of `Layout` that created this\n// instance.\n//\n// `StaticSizeSeq...` is an index_sequence containing the sizes specified at\n// compile-time.\n//\n// `RuntimeSizeSeq...` is `[0, NumRuntimeSizes)`, where `NumRuntimeSizes` is the\n// number of arguments passed to `Layout::Partial()` or `Layout::Layout()`.\n//\n// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is `NumRuntimeSizes` plus\n// the number of sizes in `StaticSizeSeq`.\n//\n// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is\n// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we\n// can compute offsets).\ntemplate <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,\n          size_t... SizeSeq, size_t... OffsetSeq>\nclass LayoutImpl<\n    std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,\n    absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,\n    absl::index_sequence<OffsetSeq...>> {\n private:\n  static_assert(sizeof...(Elements) > 0, \"At least one field is required\");\n  static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value,\n                \"Invalid element type (see IsLegalElementType)\");\n  static_assert(sizeof...(StaticSizeSeq) <= sizeof...(Elements),\n                \"Too many static sizes specified\");\n\n  enum {\n    NumTypes = sizeof...(Elements),\n    NumStaticSizes = sizeof...(StaticSizeSeq),\n    NumRuntimeSizes = sizeof...(RuntimeSizeSeq),\n    NumSizes = sizeof...(SizeSeq),\n    NumOffsets = sizeof...(OffsetSeq),\n  };\n\n  // These are guaranteed by `Layout`.\n  static_assert(NumStaticSizes + NumRuntimeSizes == NumSizes, \"Internal error\");\n  static_assert(NumSizes <= NumTypes, \"Internal error\");\n  static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),\n                \"Internal error\");\n  static_assert(NumTypes > 0, \"Internal error\");\n\n  static constexpr std::array<size_t, sizeof...(StaticSizeSeq)> kStaticSizes = {\n      StaticSizeSeq...};\n\n  // Returns the index of `T` in `Elements...`. Results in a compilation error\n  // if `Elements...` doesn't contain exactly one instance of `T`.\n  template <class T>\n  static constexpr size_t ElementIndex() {\n    static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(),\n                  \"Type not found\");\n    return adl_barrier::Find(Type<T>(),\n                             Type<typename Type<Elements>::type>()...);\n  }\n\n  template <size_t N>\n  using ElementAlignment =\n      AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>;\n\n public:\n  // Element types of all arrays packed in a tuple.\n  using ElementTypes = std::tuple<typename Type<Elements>::type...>;\n\n  // Element type of the Nth array.\n  template <size_t N>\n  using ElementType = typename std::tuple_element<N, ElementTypes>::type;\n\n  constexpr explicit LayoutImpl(IntToSize<RuntimeSizeSeq>... sizes)\n      : size_{sizes...} {}\n\n  // Alignment of the layout, equal to the strictest alignment of all elements.\n  // All pointers passed to the methods of layout must be aligned to this value.\n  static constexpr size_t Alignment() {\n    return adl_barrier::Max(AlignOf<Elements>::value...);\n  }\n\n  // Offset in bytes of the Nth array.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   assert(x.Offset<0>() == 0);   // The ints starts from 0.\n  //   assert(x.Offset<1>() == 16);  // The doubles starts from 16.\n  //\n  // Requires: `N <= NumSizes && N < sizeof...(Ts)`.\n  template <size_t N>\n  constexpr size_t Offset() const {\n    if constexpr (N == 0) {\n      return 0;\n    } else {\n      static_assert(N < NumOffsets, \"Index out of bounds\");\n      return adl_barrier::Align(\n          Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>(),\n          ElementAlignment<N>::value);\n    }\n  }\n\n  // Offset in bytes of the array with the specified element type. There must\n  // be exactly one such array and its zero-based index must be at most\n  // `NumSizes`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   assert(x.Offset<int>() == 0);      // The ints starts from 0.\n  //   assert(x.Offset<double>() == 16);  // The doubles starts from 16.\n  template <class T>\n  constexpr size_t Offset() const {\n    return Offset<ElementIndex<T>()>();\n  }\n\n  // Offsets in bytes of all arrays for which the offsets are known.\n  constexpr std::array<size_t, NumOffsets> Offsets() const {\n    return {{Offset<OffsetSeq>()...}};\n  }\n\n  // The number of elements in the Nth array (zero-based).\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   assert(x.Size<0>() == 3);\n  //   assert(x.Size<1>() == 4);\n  //\n  // Requires: `N < NumSizes`.\n  template <size_t N>\n  constexpr size_t Size() const {\n    if constexpr (N < NumStaticSizes) {\n      return kStaticSizes[N];\n    } else {\n      static_assert(N < NumSizes, \"Index out of bounds\");\n      return size_[N - NumStaticSizes];\n    }\n  }\n\n  // The number of elements in the array with the specified element type.\n  // There must be exactly one such array and its zero-based index must be\n  // at most `NumSizes`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   assert(x.Size<int>() == 3);\n  //   assert(x.Size<double>() == 4);\n  template <class T>\n  constexpr size_t Size() const {\n    return Size<ElementIndex<T>()>();\n  }\n\n  // The number of elements of all arrays for which they are known.\n  constexpr std::array<size_t, NumSizes> Sizes() const {\n    return {{Size<SizeSeq>()...}};\n  }\n\n  // Pointer to the beginning of the Nth array.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];\n  //   int* ints = x.Pointer<0>(p);\n  //   double* doubles = x.Pointer<1>(p);\n  //\n  // Requires: `N <= NumSizes && N < sizeof...(Ts)`.\n  // Requires: `p` is aligned to `Alignment()`.\n  template <size_t N, class Char>\n  CopyConst<Char, ElementType<N>>* Pointer(Char* p) const {\n    using C = typename std::remove_const<Char>::type;\n    static_assert(\n        std::is_same<C, char>() || std::is_same<C, unsigned char>() ||\n            std::is_same<C, signed char>(),\n        \"The argument must be a pointer to [const] [signed|unsigned] char\");\n    constexpr size_t alignment = Alignment();\n    (void)alignment;\n    assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);\n    return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>());\n  }\n\n  // Pointer to the beginning of the array with the specified element type.\n  // There must be exactly one such array and its zero-based index must be at\n  // most `NumSizes`.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];\n  //   int* ints = x.Pointer<int>(p);\n  //   double* doubles = x.Pointer<double>(p);\n  //\n  // Requires: `p` is aligned to `Alignment()`.\n  template <class T, class Char>\n  CopyConst<Char, T>* Pointer(Char* p) const {\n    return Pointer<ElementIndex<T>()>(p);\n  }\n\n  // Pointers to all arrays for which pointers are known.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];\n  //\n  //   int* ints;\n  //   double* doubles;\n  //   std::tie(ints, doubles) = x.Pointers(p);\n  //\n  // Requires: `p` is aligned to `Alignment()`.\n  template <class Char>\n  auto Pointers(Char* p) const {\n    return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(\n        Pointer<OffsetSeq>(p)...);\n  }\n\n  // The Nth array.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];\n  //   Span<int> ints = x.Slice<0>(p);\n  //   Span<double> doubles = x.Slice<1>(p);\n  //\n  // Requires: `N < NumSizes`.\n  // Requires: `p` is aligned to `Alignment()`.\n  template <size_t N, class Char>\n  SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const {\n    return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());\n  }\n\n  // The array with the specified element type. There must be exactly one\n  // such array and its zero-based index must be less than `NumSizes`.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];\n  //   Span<int> ints = x.Slice<int>(p);\n  //   Span<double> doubles = x.Slice<double>(p);\n  //\n  // Requires: `p` is aligned to `Alignment()`.\n  template <class T, class Char>\n  SliceType<CopyConst<Char, T>> Slice(Char* p) const {\n    return Slice<ElementIndex<T>()>(p);\n  }\n\n  // All arrays with known sizes.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];\n  //\n  //   Span<int> ints;\n  //   Span<double> doubles;\n  //   std::tie(ints, doubles) = x.Slices(p);\n  //\n  // Requires: `p` is aligned to `Alignment()`.\n  //\n  // Note: We mark the parameter as maybe_unused because GCC detects it is not\n  // used when `SizeSeq` is empty [-Werror=unused-but-set-parameter].\n  template <class Char>\n  auto Slices([[maybe_unused]] Char* p) const {\n    return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(\n        Slice<SizeSeq>(p)...);\n  }\n\n  // The size of the allocation that fits all arrays.\n  //\n  //   // int[3], 4 bytes of padding, double[4].\n  //   Layout<int, double> x(3, 4);\n  //   unsigned char* p = new unsigned char[x.AllocSize()];  // 48 bytes\n  //\n  // Requires: `NumSizes == sizeof...(Ts)`.\n  constexpr size_t AllocSize() const {\n    static_assert(NumTypes == NumSizes, \"You must specify sizes of all fields\");\n    return Offset<NumTypes - 1>() +\n           SizeOf<ElementType<NumTypes - 1>>::value * Size<NumTypes - 1>();\n  }\n\n  // If built with --config=asan, poisons padding bytes (if any) in the\n  // allocation. The pointer must point to a memory block at least\n  // `AllocSize()` bytes in length.\n  //\n  // `Char` must be `[const] [signed|unsigned] char`.\n  //\n  // Requires: `p` is aligned to `Alignment()`.\n  template <class Char, size_t N = NumOffsets - 1>\n  void PoisonPadding(const Char* p) const {\n    if constexpr (N == 0) {\n      Pointer<0>(p);  // verify the requirements on `Char` and `p`\n    } else {\n      static_assert(N < NumOffsets, \"Index out of bounds\");\n      (void)p;\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n    PoisonPadding<Char, N - 1>(p);\n    // The `if` is an optimization. It doesn't affect the observable behaviour.\n    if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {\n      size_t start =\n          Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>();\n      ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);\n    }\n#endif\n    }\n  }\n\n  // Human-readable description of the memory layout. Useful for debugging.\n  // Slow.\n  //\n  //   // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed\n  //   // by an unknown number of doubles.\n  //   auto x = Layout<char, int, double>::Partial(5, 3);\n  //   assert(x.DebugString() ==\n  //          \"@0<char>(1)[5]; @8<int>(4)[3]; @24<double>(8)\");\n  //\n  // Each field is in the following format: @offset<type>(sizeof)[size] (<type>\n  // may be missing depending on the target platform). For example,\n  // @8<int>(4)[3] means that at offset 8 we have an array of ints, where each\n  // int is 4 bytes, and we have 3 of those ints. The size of the last field may\n  // be missing (as in the example above). Only fields with known offsets are\n  // described. Type names may differ across platforms: one compiler might\n  // produce \"unsigned*\" where another produces \"unsigned int *\".\n  std::string DebugString() const {\n    const auto offsets = Offsets();\n    const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>::value...};\n    const std::string types[] = {\n        adl_barrier::TypeName<ElementType<OffsetSeq>>()...};\n    std::string res = absl::StrCat(\"@0\", types[0], \"(\", sizes[0], \")\");\n    for (size_t i = 0; i != NumOffsets - 1; ++i) {\n      absl::StrAppend(&res, \"[\", DebugSize(i), \"]; @\", offsets[i + 1],\n                      types[i + 1], \"(\", sizes[i + 1], \")\");\n    }\n    // NumSizes is a constant that may be zero. Some compilers cannot see that\n    // inside the if statement \"size_[NumSizes - 1]\" must be valid.\n    int last = static_cast<int>(NumSizes) - 1;\n    if (NumTypes == NumSizes && last >= 0) {\n      absl::StrAppend(&res, \"[\", DebugSize(static_cast<size_t>(last)), \"]\");\n    }\n    return res;\n  }\n\n private:\n  size_t DebugSize(size_t n) const {\n    if (n < NumStaticSizes) {\n      return kStaticSizes[n];\n    } else {\n      return size_[n - NumStaticSizes];\n    }\n  }\n\n  // Arguments of `Layout::Partial()` or `Layout::Layout()`.\n  size_t size_[NumRuntimeSizes > 0 ? NumRuntimeSizes : 1];\n};\n\ntemplate <class StaticSizeSeq, size_t NumRuntimeSizes, class... Ts>\nusing LayoutType = LayoutImpl<\n    std::tuple<Ts...>, StaticSizeSeq,\n    absl::make_index_sequence<NumRuntimeSizes>,\n    absl::make_index_sequence<NumRuntimeSizes + StaticSizeSeq::size()>,\n    absl::make_index_sequence<adl_barrier::Min(\n        sizeof...(Ts), NumRuntimeSizes + StaticSizeSeq::size() + 1)>>;\n\ntemplate <class StaticSizeSeq, class... Ts>\nclass LayoutWithStaticSizes\n    : public LayoutType<StaticSizeSeq,\n                        sizeof...(Ts) - adl_barrier::Min(sizeof...(Ts),\n                                                         StaticSizeSeq::size()),\n                        Ts...> {\n private:\n  using Super =\n      LayoutType<StaticSizeSeq,\n                 sizeof...(Ts) -\n                     adl_barrier::Min(sizeof...(Ts), StaticSizeSeq::size()),\n                 Ts...>;\n\n public:\n  // The result type of `Partial()` with `NumSizes` arguments.\n  template <size_t NumSizes>\n  using PartialType =\n      internal_layout::LayoutType<StaticSizeSeq, NumSizes, Ts...>;\n\n  // `Layout` knows the element types of the arrays we want to lay out in\n  // memory but not the number of elements in each array.\n  // `Partial(size1, ..., sizeN)` allows us to specify the latter. The\n  // resulting immutable object can be used to obtain pointers to the\n  // individual arrays.\n  //\n  // It's allowed to pass fewer array sizes than the number of arrays. E.g.,\n  // if all you need is to the offset of the second array, you only need to\n  // pass one argument -- the number of elements in the first array.\n  //\n  //   // int[3] followed by 4 bytes of padding and an unknown number of\n  //   // doubles.\n  //   auto x = Layout<int, double>::Partial(3);\n  //   // doubles start at byte 16.\n  //   assert(x.Offset<1>() == 16);\n  //\n  // If you know the number of elements in all arrays, you can still call\n  // `Partial()` but it's more convenient to use the constructor of `Layout`.\n  //\n  //   Layout<int, double> x(3, 5);\n  //\n  // Note: The sizes of the arrays must be specified in number of elements,\n  // not in bytes.\n  //\n  // Requires: `sizeof...(Sizes) + NumStaticSizes <= sizeof...(Ts)`.\n  // Requires: all arguments are convertible to `size_t`.\n  template <class... Sizes>\n  static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) {\n    static_assert(sizeof...(Sizes) + StaticSizeSeq::size() <= sizeof...(Ts),\n                  \"\");\n    return PartialType<sizeof...(Sizes)>(\n        static_cast<size_t>(std::forward<Sizes>(sizes))...);\n  }\n\n  // Inherit LayoutType's constructor.\n  //\n  // Creates a layout with the sizes of all arrays specified. If you know\n  // only the sizes of the first N arrays (where N can be zero), you can use\n  // `Partial()` defined above. The constructor is essentially equivalent to\n  // calling `Partial()` and passing in all array sizes; the constructor is\n  // provided as a convenient abbreviation.\n  //\n  // Note: The sizes of the arrays must be specified in number of elements,\n  // not in bytes.\n  //\n  // Implementation note: we do this via a `using` declaration instead of\n  // defining our own explicit constructor because the signature of LayoutType's\n  // constructor depends on RuntimeSizeSeq, which we don't have access to here.\n  // If we defined our own constructor here, it would have to use a parameter\n  // pack and then cast the arguments to size_t when calling the superclass\n  // constructor, similar to what Partial() does. But that would suffer from the\n  // same problem that Partial() has, which is that the parameter types are\n  // inferred from the arguments, which may be signed types, which must then be\n  // cast to size_t. This can lead to negative values being silently (i.e. with\n  // no compiler warnings) cast to an unsigned type. Having a constructor with\n  // size_t parameters helps the compiler generate better warnings about\n  // potential bad casts, while avoiding false warnings when positive literal\n  // arguments are used. If an argument is a positive literal integer (e.g.\n  // `1`), the compiler will understand that it can be safely converted to\n  // size_t, and hence not generate a warning. But if a negative literal (e.g.\n  // `-1`) or a variable with signed type is used, then it can generate a\n  // warning about a potentially unsafe implicit cast. It would be great if we\n  // could do this for Partial() too, but unfortunately as of C++23 there seems\n  // to be no way to define a function with a variable number of parameters of a\n  // certain type, a.k.a. homogeneous function parameter packs. So we're forced\n  // to choose between explicitly casting the arguments to size_t, which\n  // suppresses all warnings, even potentially valid ones, or implicitly casting\n  // them to size_t, which generates bogus warnings whenever literal arguments\n  // are used, even if they're positive.\n  using Super::Super;\n};\n\n}  // namespace internal_layout\n\n// Descriptor of arrays of various types and sizes laid out in memory one after\n// another. See the top of the file for documentation.\n//\n// Check out the public API of internal_layout::LayoutWithStaticSizes and\n// internal_layout::LayoutImpl above. Those types are internal to the library\n// but their methods are public, and they are inherited by `Layout`.\ntemplate <class... Ts>\nclass Layout : public internal_layout::LayoutWithStaticSizes<\n                   absl::make_index_sequence<0>, Ts...> {\n private:\n  using Super =\n      internal_layout::LayoutWithStaticSizes<absl::make_index_sequence<0>,\n                                             Ts...>;\n\n public:\n  // If you know the sizes of some or all of the arrays at compile time, you can\n  // use `WithStaticSizes` or `WithStaticSizeSequence` to create a `Layout` type\n  // with those sizes baked in. This can help the compiler generate optimal code\n  // for calculating array offsets and AllocSize().\n  //\n  // Like `Partial()`, the N sizes you specify are for the first N arrays, and\n  // they specify the number of elements in each array, not the number of bytes.\n  template <class StaticSizeSeq>\n  using WithStaticSizeSequence =\n      internal_layout::LayoutWithStaticSizes<StaticSizeSeq, Ts...>;\n\n  template <size_t... StaticSizes>\n  using WithStaticSizes =\n      WithStaticSizeSequence<std::index_sequence<StaticSizes...>>;\n\n  // Inherit LayoutWithStaticSizes's constructor, which requires you to specify\n  // all the array sizes.\n  using Super::Super;\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_LAYOUT_H_\n"
  },
  {
    "path": "absl/container/internal/layout_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Every benchmark should have the same performance as the corresponding\n// headroom benchmark.\n\n#include <cstddef>\n#include <cstdint>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/container/internal/layout.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::benchmark::DoNotOptimize;\n\nusing Int128 = int64_t[2];\n\nconstexpr size_t MyAlign(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }\n\n// This benchmark provides the upper bound on performance for BM_OffsetConstant.\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetConstantHeadroom(benchmark::State& state) {\n  for (auto _ : state) {\n    DoNotOptimize(Offset);\n  }\n}\n\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetConstantStatic(benchmark::State& state) {\n  using L = typename Layout<Ts...>::template WithStaticSizes<3, 5, 7>;\n  ABSL_RAW_CHECK(L::Partial().template Offset<3>() == Offset, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(L::Partial().template Offset<3>());\n  }\n}\n\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetConstant(benchmark::State& state) {\n  using L = Layout<Ts...>;\n  ABSL_RAW_CHECK(L::Partial(3, 5, 7).template Offset<3>() == Offset,\n                 \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(L::Partial(3, 5, 7).template Offset<3>());\n  }\n}\n\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetConstantIndirect(benchmark::State& state) {\n  using L = Layout<Ts...>;\n  auto p = L::Partial(3, 5, 7);\n  ABSL_RAW_CHECK(p.template Offset<3>() == Offset, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(p);\n    DoNotOptimize(p.template Offset<3>());\n  }\n}\n\ntemplate <class... Ts>\nsize_t PartialOffset(size_t k);\n\ntemplate <>\nsize_t PartialOffset<int8_t, int16_t, int32_t, Int128>(size_t k) {\n  constexpr size_t o = MyAlign(MyAlign(3 * 1, 2) + 5 * 2, 4);\n  return MyAlign(o + k * 4, 8);\n}\n\ntemplate <>\nsize_t PartialOffset<Int128, int32_t, int16_t, int8_t>(size_t k) {\n  // No alignment is necessary.\n  return 3 * 16 + 5 * 4 + k * 2;\n}\n\n// This benchmark provides the upper bound on performance for BM_OffsetVariable.\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetPartialHeadroom(benchmark::State& state) {\n  size_t k = 7;\n  ABSL_RAW_CHECK(PartialOffset<Ts...>(k) == Offset, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(k);\n    DoNotOptimize(PartialOffset<Ts...>(k));\n  }\n}\n\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetPartialStatic(benchmark::State& state) {\n  using L = typename Layout<Ts...>::template WithStaticSizes<3, 5>;\n  size_t k = 7;\n  ABSL_RAW_CHECK(L::Partial(k).template Offset<3>() == Offset,\n                 \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(k);\n    DoNotOptimize(L::Partial(k).template Offset<3>());\n  }\n}\n\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetPartial(benchmark::State& state) {\n  using L = Layout<Ts...>;\n  size_t k = 7;\n  ABSL_RAW_CHECK(L::Partial(3, 5, k).template Offset<3>() == Offset,\n                 \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(k);\n    DoNotOptimize(L::Partial(3, 5, k).template Offset<3>());\n  }\n}\n\ntemplate <class... Ts>\nsize_t VariableOffset(size_t n, size_t m, size_t k);\n\ntemplate <>\nsize_t VariableOffset<int8_t, int16_t, int32_t, Int128>(size_t n, size_t m,\n                                                        size_t k) {\n  return MyAlign(MyAlign(MyAlign(n * 1, 2) + m * 2, 4) + k * 4, 8);\n}\n\ntemplate <>\nsize_t VariableOffset<Int128, int32_t, int16_t, int8_t>(size_t n, size_t m,\n                                                        size_t k) {\n  // No alignment is necessary.\n  return n * 16 + m * 4 + k * 2;\n}\n\n// This benchmark provides the upper bound on performance for BM_OffsetVariable.\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetVariableHeadroom(benchmark::State& state) {\n  size_t n = 3;\n  size_t m = 5;\n  size_t k = 7;\n  ABSL_RAW_CHECK(VariableOffset<Ts...>(n, m, k) == Offset, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(n);\n    DoNotOptimize(m);\n    DoNotOptimize(k);\n    DoNotOptimize(VariableOffset<Ts...>(n, m, k));\n  }\n}\n\ntemplate <size_t Offset, class... Ts>\nvoid BM_OffsetVariable(benchmark::State& state) {\n  using L = Layout<Ts...>;\n  size_t n = 3;\n  size_t m = 5;\n  size_t k = 7;\n  ABSL_RAW_CHECK(L::Partial(n, m, k).template Offset<3>() == Offset,\n                 \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(n);\n    DoNotOptimize(m);\n    DoNotOptimize(k);\n    DoNotOptimize(L::Partial(n, m, k).template Offset<3>());\n  }\n}\n\ntemplate <class... Ts>\nsize_t AllocSize(size_t x);\n\ntemplate <>\nsize_t AllocSize<int8_t, int16_t, int32_t, Int128>(size_t x) {\n  constexpr size_t o =\n      Layout<int8_t, int16_t, int32_t, Int128>::Partial(3, 5, 7)\n          .template Offset<Int128>();\n  return o + sizeof(Int128) * x;\n}\n\ntemplate <>\nsize_t AllocSize<Int128, int32_t, int16_t, int8_t>(size_t x) {\n  constexpr size_t o =\n      Layout<Int128, int32_t, int16_t, int8_t>::Partial(3, 5, 7)\n          .template Offset<int8_t>();\n  return o + sizeof(int8_t) * x;\n}\n\n// This benchmark provides the upper bound on performance for BM_AllocSize\ntemplate <size_t Size, class... Ts>\nvoid BM_AllocSizeHeadroom(benchmark::State& state) {\n  size_t x = 9;\n  ABSL_RAW_CHECK(AllocSize<Ts...>(x) == Size, \"Invalid size\");\n  for (auto _ : state) {\n    DoNotOptimize(x);\n    DoNotOptimize(AllocSize<Ts...>(x));\n  }\n}\n\ntemplate <size_t Size, class... Ts>\nvoid BM_AllocSizeStatic(benchmark::State& state) {\n  using L = typename Layout<Ts...>::template WithStaticSizes<3, 5, 7>;\n  size_t x = 9;\n  ABSL_RAW_CHECK(L(x).AllocSize() == Size, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(x);\n    DoNotOptimize(L(x).AllocSize());\n  }\n}\n\ntemplate <size_t Size, class... Ts>\nvoid BM_AllocSize(benchmark::State& state) {\n  using L = Layout<Ts...>;\n  size_t n = 3;\n  size_t m = 5;\n  size_t k = 7;\n  size_t x = 9;\n  ABSL_RAW_CHECK(L(n, m, k, x).AllocSize() == Size, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(n);\n    DoNotOptimize(m);\n    DoNotOptimize(k);\n    DoNotOptimize(x);\n    DoNotOptimize(L(n, m, k, x).AllocSize());\n  }\n}\n\ntemplate <size_t Size, class... Ts>\nvoid BM_AllocSizeIndirect(benchmark::State& state) {\n  using L = Layout<Ts...>;\n  auto l = L(3, 5, 7, 9);\n  ABSL_RAW_CHECK(l.AllocSize() == Size, \"Invalid offset\");\n  for (auto _ : state) {\n    DoNotOptimize(l);\n    DoNotOptimize(l.AllocSize());\n  }\n}\n\n// Run all benchmarks in two modes:\n//\n//   Layout with padding: int8_t[3], int16_t[5], int32_t[7], Int128[?].\n//   Layout without padding: Int128[3], int32_t[5], int16_t[7], int8_t[?].\n\n#define OFFSET_BENCHMARK(NAME, OFFSET, T1, T2, T3, T4) \\\n  auto& NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4 =  \\\n      NAME<OFFSET, T1, T2, T3, T4>;                    \\\n  BENCHMARK(NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4)\n\nOFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 48, int8_t, int16_t, int32_t,\n                 Int128);\nOFFSET_BENCHMARK(BM_OffsetConstantStatic, 48, int8_t, int16_t, int32_t, Int128);\nOFFSET_BENCHMARK(BM_OffsetConstant, 48, int8_t, int16_t, int32_t, Int128);\nOFFSET_BENCHMARK(BM_OffsetConstantIndirect, 48, int8_t, int16_t, int32_t,\n                 Int128);\n\nOFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 82, Int128, int32_t, int16_t,\n                 int8_t);\nOFFSET_BENCHMARK(BM_OffsetConstantStatic, 82, Int128, int32_t, int16_t, int8_t);\nOFFSET_BENCHMARK(BM_OffsetConstant, 82, Int128, int32_t, int16_t, int8_t);\nOFFSET_BENCHMARK(BM_OffsetConstantIndirect, 82, Int128, int32_t, int16_t,\n                 int8_t);\n\nOFFSET_BENCHMARK(BM_OffsetPartialHeadroom, 48, int8_t, int16_t, int32_t,\n                 Int128);\nOFFSET_BENCHMARK(BM_OffsetPartialStatic, 48, int8_t, int16_t, int32_t, Int128);\nOFFSET_BENCHMARK(BM_OffsetPartial, 48, int8_t, int16_t, int32_t, Int128);\n\nOFFSET_BENCHMARK(BM_OffsetPartialHeadroom, 82, Int128, int32_t, int16_t,\n                 int8_t);\nOFFSET_BENCHMARK(BM_OffsetPartialStatic, 82, Int128, int32_t, int16_t, int8_t);\nOFFSET_BENCHMARK(BM_OffsetPartial, 82, Int128, int32_t, int16_t, int8_t);\n\nOFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 48, int8_t, int16_t, int32_t,\n                 Int128);\nOFFSET_BENCHMARK(BM_OffsetVariable, 48, int8_t, int16_t, int32_t, Int128);\n\nOFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 82, Int128, int32_t, int16_t,\n                 int8_t);\nOFFSET_BENCHMARK(BM_OffsetVariable, 82, Int128, int32_t, int16_t, int8_t);\n\nOFFSET_BENCHMARK(BM_AllocSizeHeadroom, 192, int8_t, int16_t, int32_t, Int128);\nOFFSET_BENCHMARK(BM_AllocSizeStatic, 192, int8_t, int16_t, int32_t, Int128);\nOFFSET_BENCHMARK(BM_AllocSize, 192, int8_t, int16_t, int32_t, Int128);\nOFFSET_BENCHMARK(BM_AllocSizeIndirect, 192, int8_t, int16_t, int32_t, Int128);\n\nOFFSET_BENCHMARK(BM_AllocSizeHeadroom, 91, Int128, int32_t, int16_t, int8_t);\nOFFSET_BENCHMARK(BM_AllocSizeStatic, 91, Int128, int32_t, int16_t, int8_t);\nOFFSET_BENCHMARK(BM_AllocSize, 91, Int128, int32_t, int16_t, int8_t);\nOFFSET_BENCHMARK(BM_AllocSizeIndirect, 91, Int128, int32_t, int16_t, int8_t);\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/layout_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/layout.h\"\n\n// We need ::max_align_t because some libstdc++ versions don't provide\n// std::max_align_t\n#include <stddef.h>\n\n#include <cstdint>\n#include <cstring>\n#include <initializer_list>\n#include <memory>\n#include <ostream>\n#include <string>\n#include <tuple>\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/check.h\"\n#include \"absl/types/span.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::absl::Span;\nusing ::testing::ElementsAre;\n\nsize_t Distance(const void* from, const void* to) {\n  CHECK_LE(from, to) << \"Distance must be non-negative\";\n  return static_cast<const char*>(to) - static_cast<const char*>(from);\n}\n\ntemplate <class Expected, class Actual>\nExpected Type(Actual val) {\n  static_assert(std::is_same<Expected, Actual>(), \"\");\n  return val;\n}\n\n// Helper classes to test different size and alignments.\nstruct alignas(8) Int128 {\n  uint64_t a, b;\n  friend bool operator==(Int128 lhs, Int128 rhs) {\n    return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);\n  }\n\n  static std::string Name() {\n    return internal_layout::adl_barrier::TypeName<Int128>();\n  }\n};\n\n// int64_t is *not* 8-byte aligned on all platforms!\nstruct alignas(8) Int64 {\n  int64_t a;\n  friend bool operator==(Int64 lhs, Int64 rhs) { return lhs.a == rhs.a; }\n};\n\n// Properties of types that this test relies on.\nstatic_assert(sizeof(int8_t) == 1, \"\");\nstatic_assert(alignof(int8_t) == 1, \"\");\nstatic_assert(sizeof(int16_t) == 2, \"\");\nstatic_assert(alignof(int16_t) == 2, \"\");\nstatic_assert(sizeof(int32_t) == 4, \"\");\nstatic_assert(alignof(int32_t) == 4, \"\");\nstatic_assert(sizeof(Int64) == 8, \"\");\nstatic_assert(alignof(Int64) == 8, \"\");\nstatic_assert(sizeof(Int128) == 16, \"\");\nstatic_assert(alignof(Int128) == 8, \"\");\n\ntemplate <class Expected, class Actual>\nvoid SameType() {\n  static_assert(std::is_same<Expected, Actual>(), \"\");\n}\n\nTEST(Layout, ElementType) {\n  {\n    using L = Layout<int32_t>;\n    SameType<int32_t, L::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial())::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    SameType<int32_t, L::ElementType<0>>();\n    SameType<int32_t, L::ElementType<1>>();\n    SameType<int32_t, decltype(L::Partial())::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial())::ElementType<1>>();\n    SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    SameType<int8_t, L::ElementType<0>>();\n    SameType<int32_t, L::ElementType<1>>();\n    SameType<Int128, L::ElementType<2>>();\n    SameType<int8_t, decltype(L::Partial())::ElementType<0>>();\n    SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();\n    SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();\n    SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();\n    SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();\n    SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();\n    SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();\n  }\n}\n\nTEST(Layout, ElementTypes) {\n  {\n    using L = Layout<int32_t>;\n    SameType<std::tuple<int32_t>, L::ElementTypes>();\n    SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();\n    SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();\n    SameType<std::tuple<int32_t, int32_t>,\n             decltype(L::Partial())::ElementTypes>();\n    SameType<std::tuple<int32_t, int32_t>,\n             decltype(L::Partial(0))::ElementTypes>();\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();\n    SameType<std::tuple<int8_t, int32_t, Int128>,\n             decltype(L::Partial())::ElementTypes>();\n    SameType<std::tuple<int8_t, int32_t, Int128>,\n             decltype(L::Partial(0))::ElementTypes>();\n    SameType<std::tuple<int8_t, int32_t, Int128>,\n             decltype(L::Partial(0, 0))::ElementTypes>();\n    SameType<std::tuple<int8_t, int32_t, Int128>,\n             decltype(L::Partial(0, 0, 0))::ElementTypes>();\n  }\n}\n\nTEST(Layout, OffsetByIndex) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial().Offset<0>());\n    EXPECT_EQ(0, L::Partial(3).Offset<0>());\n    EXPECT_EQ(0, L(3).Offset<0>());\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(0, L::Partial().Offset<0>());\n    EXPECT_EQ(0, L::Partial(3).Offset<0>());\n    EXPECT_EQ(12, L::Partial(3).Offset<1>());\n    EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());\n    EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());\n    EXPECT_EQ(0, L(3, 5).Offset<0>());\n    EXPECT_EQ(12, L(3, 5).Offset<1>());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(0, L::Partial().Offset<0>());\n    EXPECT_EQ(0, L::Partial(0).Offset<0>());\n    EXPECT_EQ(0, L::Partial(0).Offset<1>());\n    EXPECT_EQ(0, L::Partial(1).Offset<0>());\n    EXPECT_EQ(4, L::Partial(1).Offset<1>());\n    EXPECT_EQ(0, L::Partial(5).Offset<0>());\n    EXPECT_EQ(8, L::Partial(5).Offset<1>());\n    EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());\n    EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());\n    EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());\n    EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());\n    EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());\n    EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());\n    EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());\n    EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());\n    EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());\n    EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());\n    EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());\n    EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());\n    EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());\n    EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());\n    EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());\n    EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());\n    EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());\n    EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());\n    EXPECT_EQ(0, L(5, 3, 1).Offset<0>());\n    EXPECT_EQ(24, L(5, 3, 1).Offset<2>());\n    EXPECT_EQ(8, L(5, 3, 1).Offset<1>());\n  }\n}\n\nTEST(Layout, OffsetByType) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial().Offset<int32_t>());\n    EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());\n    EXPECT_EQ(0, L(3).Offset<int32_t>());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(0, L::Partial().Offset<int8_t>());\n    EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());\n    EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());\n    EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());\n    EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());\n    EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());\n    EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());\n    EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());\n    EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());\n    EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());\n    EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());\n    EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());\n    EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());\n    EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());\n    EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());\n    EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());\n    EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());\n    EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());\n    EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());\n    EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());\n    EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());\n    EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());\n    EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());\n    EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());\n    EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());\n    EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());\n    EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());\n    EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());\n  }\n}\n\nTEST(Layout, Offsets) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));\n    EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));\n    EXPECT_THAT(L(3).Offsets(), ElementsAre(0));\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));\n    EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));\n    EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));\n    EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));\n    EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));\n    EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));\n    EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));\n    EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));\n    EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));\n    EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));\n    EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));\n  }\n}\n\nTEST(Layout, StaticOffsets) {\n  using L = Layout<int8_t, int32_t, Int128>;\n  {\n    using SL = L::WithStaticSizes<>;\n    EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0));\n    EXPECT_THAT(SL::Partial(5).Offsets(), ElementsAre(0, 8));\n    EXPECT_THAT(SL::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(SL(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));\n  }\n  {\n    using SL = L::WithStaticSizes<5>;\n    EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8));\n    EXPECT_THAT(SL::Partial(3).Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(SL::Partial(3, 1).Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(SL(3, 1).Offsets(), ElementsAre(0, 8, 24));\n  }\n  {\n    using SL = L::WithStaticSizes<5, 3>;\n    EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(SL::Partial(1).Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(SL(1).Offsets(), ElementsAre(0, 8, 24));\n  }\n  {\n    using SL = L::WithStaticSizes<5, 3, 1>;\n    EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24));\n    EXPECT_THAT(SL().Offsets(), ElementsAre(0, 8, 24));\n  }\n}\n\nTEST(Layout, AllocSize) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).AllocSize());\n    EXPECT_EQ(12, L::Partial(3).AllocSize());\n    EXPECT_EQ(12, L(3).AllocSize());\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(32, L::Partial(3, 5).AllocSize());\n    EXPECT_EQ(32, L(3, 5).AllocSize());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());\n    EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());\n    EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());\n    EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());\n    EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());\n    EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());\n    EXPECT_EQ(136, L(3, 5, 7).AllocSize());\n  }\n}\n\nTEST(Layout, StaticAllocSize) {\n  using L = Layout<int8_t, int32_t, Int128>;\n  {\n    using SL = L::WithStaticSizes<>;\n    EXPECT_EQ(136, SL::Partial(3, 5, 7).AllocSize());\n    EXPECT_EQ(136, SL(3, 5, 7).AllocSize());\n  }\n  {\n    using SL = L::WithStaticSizes<3>;\n    EXPECT_EQ(136, SL::Partial(5, 7).AllocSize());\n    EXPECT_EQ(136, SL(5, 7).AllocSize());\n  }\n  {\n    using SL = L::WithStaticSizes<3, 5>;\n    EXPECT_EQ(136, SL::Partial(7).AllocSize());\n    EXPECT_EQ(136, SL(7).AllocSize());\n  }\n  {\n    using SL = L::WithStaticSizes<3, 5, 7>;\n    EXPECT_EQ(136, SL::Partial().AllocSize());\n    EXPECT_EQ(136, SL().AllocSize());\n  }\n}\n\nTEST(Layout, SizeByIndex) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Size<0>());\n    EXPECT_EQ(3, L::Partial(3).Size<0>());\n    EXPECT_EQ(3, L(3).Size<0>());\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Size<0>());\n    EXPECT_EQ(3, L::Partial(3).Size<0>());\n    EXPECT_EQ(3, L::Partial(3, 5).Size<0>());\n    EXPECT_EQ(5, L::Partial(3, 5).Size<1>());\n    EXPECT_EQ(3, L(3, 5).Size<0>());\n    EXPECT_EQ(5, L(3, 5).Size<1>());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(3, L::Partial(3).Size<0>());\n    EXPECT_EQ(3, L::Partial(3, 5).Size<0>());\n    EXPECT_EQ(5, L::Partial(3, 5).Size<1>());\n    EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());\n    EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());\n    EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());\n    EXPECT_EQ(3, L(3, 5, 7).Size<0>());\n    EXPECT_EQ(5, L(3, 5, 7).Size<1>());\n    EXPECT_EQ(7, L(3, 5, 7).Size<2>());\n  }\n}\n\nTEST(Layout, SizeByType) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Size<int32_t>());\n    EXPECT_EQ(3, L::Partial(3).Size<int32_t>());\n    EXPECT_EQ(3, L(3).Size<int32_t>());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(3, L::Partial(3).Size<int8_t>());\n    EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());\n    EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());\n    EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());\n    EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());\n    EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());\n    EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());\n    EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());\n    EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());\n  }\n}\n\nTEST(Layout, Sizes) {\n  {\n    using L = Layout<int32_t>;\n    EXPECT_THAT(L::Partial().Sizes(), ElementsAre());\n    EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));\n    EXPECT_THAT(L(3).Sizes(), ElementsAre(3));\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_THAT(L::Partial().Sizes(), ElementsAre());\n    EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));\n    EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));\n    EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_THAT(L::Partial().Sizes(), ElementsAre());\n    EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));\n    EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));\n    EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));\n    EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));\n  }\n}\n\nTEST(Layout, StaticSize) {\n  using L = Layout<int8_t, int32_t, Int128>;\n  {\n    using SL = L::WithStaticSizes<>;\n    EXPECT_THAT(SL::Partial().Sizes(), ElementsAre());\n    EXPECT_THAT(SL::Partial(3).Size<0>(), 3);\n    EXPECT_THAT(SL::Partial(3).Size<int8_t>(), 3);\n    EXPECT_THAT(SL::Partial(3).Sizes(), ElementsAre(3));\n    EXPECT_THAT(SL::Partial(3, 5, 7).Size<0>(), 3);\n    EXPECT_THAT(SL::Partial(3, 5, 7).Size<int8_t>(), 3);\n    EXPECT_THAT(SL::Partial(3, 5, 7).Size<2>(), 7);\n    EXPECT_THAT(SL::Partial(3, 5, 7).Size<Int128>(), 7);\n    EXPECT_THAT(SL::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));\n    EXPECT_THAT(SL(3, 5, 7).Size<0>(), 3);\n    EXPECT_THAT(SL(3, 5, 7).Size<int8_t>(), 3);\n    EXPECT_THAT(SL(3, 5, 7).Size<2>(), 7);\n    EXPECT_THAT(SL(3, 5, 7).Size<Int128>(), 7);\n    EXPECT_THAT(SL(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));\n  }\n}\n\nTEST(Layout, PointerByIndex) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));\n    EXPECT_EQ(12,\n              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));\n    EXPECT_EQ(\n        12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));\n    EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));\n    EXPECT_EQ(4,\n              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));\n    EXPECT_EQ(8,\n              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));\n    EXPECT_EQ(\n        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));\n    EXPECT_EQ(8,\n              Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));\n    EXPECT_EQ(\n        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));\n    EXPECT_EQ(24,\n              Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));\n    EXPECT_EQ(\n        4,\n        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));\n    EXPECT_EQ(\n        8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));\n    EXPECT_EQ(\n        24,\n        Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));\n    EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));\n    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));\n  }\n}\n\nTEST(Layout, PointerByType) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(\n        0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        4,\n        Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(\n                                 L::Partial(0, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(\n                                 L::Partial(1, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));\n    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(\n                                 L::Partial(5, 3).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        24,\n        Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(\n                                 L::Partial(0, 0, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(\n                                 L::Partial(0, 0, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const Int128*>(\n                                 L::Partial(0, 0, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(\n                                 L::Partial(1, 0, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(\n                                 L::Partial(1, 0, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(8, Distance(p, Type<const Int128*>(\n                                 L::Partial(1, 0, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(\n                                 L::Partial(5, 3, 1).Pointer<int8_t>(p))));\n    EXPECT_EQ(24, Distance(p, Type<const Int128*>(\n                                  L::Partial(5, 3, 1).Pointer<Int128>(p))));\n    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(\n                                 L::Partial(5, 3, 1).Pointer<int32_t>(p))));\n    EXPECT_EQ(24,\n              Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));\n  }\n}\n\nTEST(Layout, MutablePointerByIndex) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));\n    EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));\n    EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));\n    EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));\n    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));\n    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));\n    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));\n    EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));\n    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));\n    EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));\n    EXPECT_EQ(4,\n              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));\n    EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));\n    EXPECT_EQ(24,\n              Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));\n    EXPECT_EQ(8,\n              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));\n    EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));\n    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));\n  }\n}\n\nTEST(Layout, MutablePointerByType) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));\n    EXPECT_EQ(4,\n              Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));\n    EXPECT_EQ(8,\n              Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(8,\n              Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(0,\n              Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));\n    EXPECT_EQ(24,\n              Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        4,\n        Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));\n    EXPECT_EQ(\n        8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));\n    EXPECT_EQ(\n        24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));\n    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));\n    EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));\n    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));\n  }\n}\n\nTEST(Layout, Pointers) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  using L = Layout<int8_t, int8_t, Int128>;\n  {\n    const auto x = L::Partial();\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),\n              Type<std::tuple<const int8_t*>>(x.Pointers(p)));\n  }\n  {\n    const auto x = L::Partial(1);\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),\n              (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2, 3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n  {\n    const L x(1, 2, 3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n}\n\nTEST(Layout, MutablePointers) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  using L = Layout<int8_t, int8_t, Int128>;\n  {\n    const auto x = L::Partial();\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),\n              Type<std::tuple<int8_t*>>(x.Pointers(p)));\n  }\n  {\n    const auto x = L::Partial(1);\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),\n              (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2, 3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));\n  }\n  {\n    const L x(1, 2, 3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));\n  }\n}\n\nTEST(Layout, StaticPointers) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  using L = Layout<int8_t, int8_t, Int128>;\n  {\n    const auto x = L::WithStaticSizes<>::Partial();\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),\n              Type<std::tuple<const int8_t*>>(x.Pointers(p)));\n  }\n  {\n    const auto x = L::WithStaticSizes<>::Partial(1);\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),\n              (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));\n  }\n  {\n    const auto x = L::WithStaticSizes<1>::Partial();\n    EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),\n              (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));\n  }\n  {\n    const auto x = L::WithStaticSizes<>::Partial(1, 2, 3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n  {\n    const auto x = L::WithStaticSizes<1>::Partial(2, 3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n  {\n    const auto x = L::WithStaticSizes<1, 2>::Partial(3);\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n  {\n    const auto x = L::WithStaticSizes<1, 2, 3>::Partial();\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n  {\n    const L::WithStaticSizes<1, 2, 3> x;\n    EXPECT_EQ(\n        std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),\n        (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(\n            x.Pointers(p))));\n  }\n}\n\nTEST(Layout, SliceByIndexSize) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());\n    EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());\n    EXPECT_EQ(3, L(3).Slice<0>(p).size());\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());\n    EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());\n    EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());\n    EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());\n    EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());\n    EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());\n  }\n}\n\nTEST(Layout, SliceByTypeSize) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());\n    EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());\n    EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());\n    EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());\n    EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());\n    EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());\n    EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());\n  }\n}\nTEST(Layout, MutableSliceByIndexSize) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());\n    EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());\n    EXPECT_EQ(3, L(3).Slice<0>(p).size());\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());\n    EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());\n    EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());\n    EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());\n    EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());\n    EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());\n  }\n}\n\nTEST(Layout, MutableSliceByTypeSize) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());\n    EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());\n    EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());\n    EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());\n    EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());\n    EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());\n    EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());\n    EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());\n    EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());\n  }\n}\n\nTEST(Layout, StaticSliceSize) {\n  alignas(max_align_t) const unsigned char cp[100] = {0};\n  alignas(max_align_t) unsigned char p[100] = {0};\n  using L = Layout<int8_t, int32_t, Int128>;\n  using SL = L::WithStaticSizes<3, 5>;\n\n  EXPECT_EQ(3, SL::Partial().Slice<0>(cp).size());\n  EXPECT_EQ(3, SL::Partial().Slice<int8_t>(cp).size());\n  EXPECT_EQ(3, SL::Partial(7).Slice<0>(cp).size());\n  EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(cp).size());\n\n  EXPECT_EQ(5, SL::Partial().Slice<1>(cp).size());\n  EXPECT_EQ(5, SL::Partial().Slice<int32_t>(cp).size());\n  EXPECT_EQ(5, SL::Partial(7).Slice<1>(cp).size());\n  EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(cp).size());\n\n  EXPECT_EQ(7, SL::Partial(7).Slice<2>(cp).size());\n  EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(cp).size());\n\n  EXPECT_EQ(3, SL::Partial().Slice<0>(p).size());\n  EXPECT_EQ(3, SL::Partial().Slice<int8_t>(p).size());\n  EXPECT_EQ(3, SL::Partial(7).Slice<0>(p).size());\n  EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(p).size());\n\n  EXPECT_EQ(5, SL::Partial().Slice<1>(p).size());\n  EXPECT_EQ(5, SL::Partial().Slice<int32_t>(p).size());\n  EXPECT_EQ(5, SL::Partial(7).Slice<1>(p).size());\n  EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(p).size());\n\n  EXPECT_EQ(7, SL::Partial(7).Slice<2>(p).size());\n  EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(p).size());\n}\n\nTEST(Layout, SliceByIndexData) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));\n    EXPECT_EQ(0,\n              Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        12,\n        Distance(\n            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        4,\n        Distance(\n            p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        4,\n        Distance(\n            p,\n            Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p,\n            Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        24,\n        Distance(\n            p,\n            Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p,\n            Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        24,\n        Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));\n  }\n}\n\nTEST(Layout, SliceByTypeData) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))\n                        .data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(\n                                 L::Partial(0, 0).Slice<int32_t>(p))\n                                 .data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))\n                        .data()));\n    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(\n                                 L::Partial(1, 0).Slice<int32_t>(p))\n                                 .data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))\n                        .data()));\n    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(\n                                 L::Partial(5, 3).Slice<int32_t>(p))\n                                 .data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(\n                                 L::Partial(0, 0, 0).Slice<int8_t>(p))\n                                 .data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(\n                                 L::Partial(0, 0, 0).Slice<int32_t>(p))\n                                 .data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(\n                                 L::Partial(0, 0, 0).Slice<Int128>(p))\n                                 .data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(\n                                 L::Partial(1, 0, 0).Slice<int8_t>(p))\n                                 .data()));\n    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(\n                                 L::Partial(1, 0, 0).Slice<int32_t>(p))\n                                 .data()));\n    EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(\n                                 L::Partial(1, 0, 0).Slice<Int128>(p))\n                                 .data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(\n                                 L::Partial(5, 3, 1).Slice<int8_t>(p))\n                                 .data()));\n    EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(\n                                  L::Partial(5, 3, 1).Slice<Int128>(p))\n                                  .data()));\n    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(\n                                 L::Partial(5, 3, 1).Slice<int32_t>(p))\n                                 .data()));\n    EXPECT_EQ(\n        0,\n        Distance(p,\n                 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        24,\n        Distance(p,\n                 Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));\n  }\n}\n\nTEST(Layout, MutableSliceByIndexData) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));\n  }\n  {\n    using L = Layout<int32_t, int32_t>;\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        12,\n        Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));\n    EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));\n    EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        4,\n        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        4, Distance(\n               p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));\n    EXPECT_EQ(\n        8, Distance(\n               p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));\n    EXPECT_EQ(\n        24, Distance(\n                p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));\n    EXPECT_EQ(\n        8, Distance(\n               p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));\n    EXPECT_EQ(0,\n              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));\n    EXPECT_EQ(24,\n              Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));\n    EXPECT_EQ(8,\n              Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));\n  }\n}\n\nTEST(Layout, MutableSliceByTypeData) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  {\n    using L = Layout<int32_t>;\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(\n               p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(0,\n              Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));\n  }\n  {\n    using L = Layout<int8_t, int32_t, Int128>;\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p,\n                 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p,\n                 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        4,\n        Distance(\n            p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(p,\n                 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        4,\n        Distance(\n            p,\n            Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p,\n            Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));\n    EXPECT_EQ(\n        0,\n        Distance(\n            p,\n            Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        24,\n        Distance(\n            p,\n            Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(\n            p,\n            Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));\n    EXPECT_EQ(\n        0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));\n    EXPECT_EQ(\n        24,\n        Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));\n    EXPECT_EQ(\n        8,\n        Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));\n  }\n}\n\nTEST(Layout, StaticSliceData) {\n  alignas(max_align_t) const unsigned char cp[100] = {0};\n  alignas(max_align_t) unsigned char p[100] = {0};\n  using L = Layout<int8_t, int32_t, Int128>;\n  using SL = L::WithStaticSizes<3, 5>;\n\n  EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<0>(cp).data()));\n  EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<int8_t>(cp).data()));\n  EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<0>(cp).data()));\n  EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<int8_t>(cp).data()));\n\n  EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<1>(cp).data()));\n  EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<int32_t>(cp).data()));\n  EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<1>(cp).data()));\n  EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<int32_t>(cp).data()));\n\n  EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<2>(cp).data()));\n  EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<Int128>(cp).data()));\n\n  EXPECT_EQ(0, Distance(p, SL::Partial().Slice<0>(p).data()));\n  EXPECT_EQ(0, Distance(p, SL::Partial().Slice<int8_t>(p).data()));\n  EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<0>(p).data()));\n  EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<int8_t>(p).data()));\n\n  EXPECT_EQ(4, Distance(p, SL::Partial().Slice<1>(p).data()));\n  EXPECT_EQ(4, Distance(p, SL::Partial().Slice<int32_t>(p).data()));\n  EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<1>(p).data()));\n  EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<int32_t>(p).data()));\n\n  EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<2>(p).data()));\n  EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<Int128>(p).data()));\n}\n\nMATCHER_P(IsSameSlice, slice, \"\") {\n  return arg.size() == slice.size() && arg.data() == slice.data();\n}\n\ntemplate <typename... M>\nclass TupleMatcher {\n public:\n  explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}\n\n  template <typename Tuple>\n  bool MatchAndExplain(const Tuple& p,\n                       testing::MatchResultListener* /* listener */) const {\n    static_assert(std::tuple_size<Tuple>::value == sizeof...(M), \"\");\n    return MatchAndExplainImpl(\n        p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});\n  }\n\n  // For the matcher concept. Left empty as we don't really need the diagnostics\n  // right now.\n  void DescribeTo(::std::ostream* os) const {}\n  void DescribeNegationTo(::std::ostream* os) const {}\n\n private:\n  template <typename Tuple, size_t... Is>\n  bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {\n    // Using std::min as a simple variadic \"and\".\n    return std::min(\n        {true, testing::SafeMatcherCast<\n                   const typename std::tuple_element<Is, Tuple>::type&>(\n                   std::get<Is>(matchers_))\n                   .Matches(std::get<Is>(p))...});\n  }\n\n  std::tuple<M...> matchers_;\n};\n\ntemplate <typename... M>\ntesting::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {\n  return testing::MakePolymorphicMatcher(\n      TupleMatcher<M...>(std::move(matchers)...));\n}\n\nTEST(Layout, Slices) {\n  alignas(max_align_t) const unsigned char p[100] = {0};\n  using L = Layout<int8_t, int8_t, Int128>;\n  {\n    const auto x = L::Partial();\n    EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());\n  }\n  {\n    const auto x = L::Partial(1);\n    EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),\n                Tuple(IsSameSlice(x.Slice<0>(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2);\n    EXPECT_THAT(\n        (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),\n        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2, 3);\n    EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,\n                                 Span<const Int128>>>(x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),\n                      IsSameSlice(x.Slice<2>(p))));\n  }\n  {\n    const L x(1, 2, 3);\n    EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,\n                                 Span<const Int128>>>(x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),\n                      IsSameSlice(x.Slice<2>(p))));\n  }\n}\n\nTEST(Layout, MutableSlices) {\n  alignas(max_align_t) unsigned char p[100] = {0};\n  using L = Layout<int8_t, int8_t, Int128>;\n  {\n    const auto x = L::Partial();\n    EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());\n  }\n  {\n    const auto x = L::Partial(1);\n    EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),\n                Tuple(IsSameSlice(x.Slice<0>(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2);\n    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));\n  }\n  {\n    const auto x = L::Partial(1, 2, 3);\n    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(\n                    x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),\n                      IsSameSlice(x.Slice<2>(p))));\n  }\n  {\n    const L x(1, 2, 3);\n    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(\n                    x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),\n                      IsSameSlice(x.Slice<2>(p))));\n  }\n}\n\nTEST(Layout, StaticSlices) {\n  alignas(max_align_t) const unsigned char cp[100] = {0};\n  alignas(max_align_t) unsigned char p[100] = {0};\n  using SL = Layout<int8_t, int8_t, Int128>::WithStaticSizes<1, 2>;\n  {\n    const auto x = SL::Partial();\n    EXPECT_THAT(\n        (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(\n            x.Slices(cp))),\n        Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp))));\n    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));\n  }\n  {\n    const auto x = SL::Partial(3);\n    EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,\n                                 Span<const Int128>>>(x.Slices(cp))),\n                Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)),\n                      IsSameSlice(x.Slice<2>(cp))));\n    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(\n                    x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),\n                      IsSameSlice(x.Slice<2>(p))));\n  }\n  {\n    const SL x(3);\n    EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,\n                                 Span<const Int128>>>(x.Slices(cp))),\n                Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)),\n                      IsSameSlice(x.Slice<2>(cp))));\n    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(\n                    x.Slices(p))),\n                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),\n                      IsSameSlice(x.Slice<2>(p))));\n  }\n}\n\nTEST(Layout, UnalignedTypes) {\n  constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);\n  alignas(max_align_t) unsigned char p[x.AllocSize() + 1];\n  EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));\n}\n\nTEST(Layout, CustomAlignment) {\n  constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);\n  alignas(max_align_t) unsigned char p[x.AllocSize()];\n  EXPECT_EQ(10, x.AllocSize());\n  EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));\n}\n\nTEST(Layout, OverAligned) {\n  constexpr size_t M = alignof(max_align_t);\n  constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);\n#ifdef __GNUC__\n  // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug:\n  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357\n  __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()];\n#else\n  alignas(2 * M) unsigned char p[x.AllocSize()];\n#endif\n  EXPECT_EQ(2 * M + 3, x.AllocSize());\n  EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));\n}\n\nTEST(Layout, Alignment) {\n  static_assert(Layout<int8_t>::Alignment() == 1, \"\");\n  static_assert(Layout<int32_t>::Alignment() == 4, \"\");\n  static_assert(Layout<Int64>::Alignment() == 8, \"\");\n  static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, \"\");\n  static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, \"\");\n  static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, \"\");\n  static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, \"\");\n  static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, \"\");\n  static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, \"\");\n  static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, \"\");\n  static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, \"\");\n  static_assert(\n      Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, \"\");\n  static_assert(\n      Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, \"\");\n}\n\nTEST(Layout, StaticAlignment) {\n  static_assert(Layout<int8_t>::WithStaticSizes<>::Alignment() == 1, \"\");\n  static_assert(Layout<int8_t>::WithStaticSizes<0>::Alignment() == 1, \"\");\n  static_assert(Layout<int8_t>::WithStaticSizes<7>::Alignment() == 1, \"\");\n  static_assert(Layout<int32_t>::WithStaticSizes<>::Alignment() == 4, \"\");\n  static_assert(Layout<int32_t>::WithStaticSizes<0>::Alignment() == 4, \"\");\n  static_assert(Layout<int32_t>::WithStaticSizes<3>::Alignment() == 4, \"\");\n  static_assert(\n      Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, \"\");\n  static_assert(\n      Layout<Aligned<int8_t, 64>>::WithStaticSizes<0>::Alignment() == 64, \"\");\n  static_assert(\n      Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, \"\");\n  static_assert(\n      Layout<int32_t, Int64, int8_t>::WithStaticSizes<>::Alignment() == 8, \"\");\n  static_assert(\n      Layout<int32_t, Int64, int8_t>::WithStaticSizes<0, 0, 0>::Alignment() ==\n          8,\n      \"\");\n  static_assert(\n      Layout<int32_t, Int64, int8_t>::WithStaticSizes<1, 1, 1>::Alignment() ==\n          8,\n      \"\");\n}\n\nTEST(Layout, ConstexprPartial) {\n  constexpr size_t M = alignof(max_align_t);\n  constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);\n  static_assert(x.Partial(1).template Offset<1>() == 2 * M, \"\");\n}\n\nTEST(Layout, StaticConstexpr) {\n  constexpr size_t M = alignof(max_align_t);\n  using L = Layout<unsigned char, Aligned<unsigned char, 2 * M>>;\n  using SL = L::WithStaticSizes<1, 3>;\n  constexpr SL x;\n  static_assert(x.Offset<1>() == 2 * M, \"\");\n}\n\n// [from, to)\nstruct Region {\n  size_t from;\n  size_t to;\n};\n\nvoid ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  for (size_t i = 0; i != n; ++i) {\n    EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));\n  }\n#endif\n}\n\ntemplate <size_t N>\nvoid ExpectPoisoned(const unsigned char (&buf)[N],\n                    std::initializer_list<Region> reg) {\n  size_t prev = 0;\n  for (const Region& r : reg) {\n    ExpectRegionPoisoned(buf + prev, r.from - prev, false);\n    ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);\n    prev = r.to;\n  }\n  ExpectRegionPoisoned(buf + prev, N - prev, false);\n}\n\nTEST(Layout, PoisonPadding) {\n  using L = Layout<int8_t, Int64, int32_t, Int128>;\n\n  constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();\n  {\n    constexpr auto x = L::Partial();\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {});\n  }\n  {\n    constexpr auto x = L::Partial(1);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}});\n  }\n  {\n    constexpr auto x = L::Partial(1, 2);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}});\n  }\n  {\n    constexpr auto x = L::Partial(1, 2, 3);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}, {36, 40}});\n  }\n  {\n    constexpr auto x = L::Partial(1, 2, 3, 4);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}, {36, 40}});\n  }\n  {\n    constexpr L x(1, 2, 3, 4);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}, {36, 40}});\n  }\n}\n\nTEST(Layout, StaticPoisonPadding) {\n  using L = Layout<int8_t, Int64, int32_t, Int128>;\n  using SL = L::WithStaticSizes<1, 2>;\n\n  constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();\n  {\n    constexpr auto x = SL::Partial();\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}});\n  }\n  {\n    constexpr auto x = SL::Partial(3);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}, {36, 40}});\n  }\n  {\n    constexpr auto x = SL::Partial(3, 4);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}, {36, 40}});\n  }\n  {\n    constexpr SL x(3, 4);\n    alignas(max_align_t) const unsigned char c[n] = {};\n    x.PoisonPadding(c);\n    EXPECT_EQ(x.Slices(c), x.Slices(c));\n    ExpectPoisoned(c, {{1, 8}, {36, 40}});\n  }\n}\n\nTEST(Layout, DebugString) {\n  {\n    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();\n    EXPECT_EQ(\"@0<signed char>(1)\", x.DebugString());\n  }\n  {\n    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)\", x.DebugString());\n  }\n  {\n    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)\",\n              x.DebugString());\n  }\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);\n    EXPECT_EQ(\n        \"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; \"\n        \"@16\" +\n            Int128::Name() + \"(16)\",\n        x.DebugString());\n  }\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);\n    EXPECT_EQ(\n        \"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; \"\n        \"@16\" +\n            Int128::Name() + \"(16)[4]\",\n        x.DebugString());\n  }\n  {\n    constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);\n    EXPECT_EQ(\n        \"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; \"\n        \"@16\" +\n            Int128::Name() + \"(16)[4]\",\n        x.DebugString());\n  }\n}\n\nTEST(Layout, StaticDebugString) {\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial();\n    EXPECT_EQ(\"@0<signed char>(1)\", x.DebugString());\n  }\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1);\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)\", x.DebugString());\n  }\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial();\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)\", x.DebugString());\n  }\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1,\n                                                                            2);\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)\",\n              x.DebugString());\n  }\n  {\n    constexpr auto x =\n        Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial(2);\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)\",\n              x.DebugString());\n  }\n  {\n    constexpr auto x = Layout<int8_t, int32_t, int8_t,\n                              Int128>::WithStaticSizes<1, 2>::Partial();\n    EXPECT_EQ(\"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)\",\n              x.DebugString());\n  }\n  {\n    constexpr auto x = Layout<int8_t, int32_t, int8_t,\n                              Int128>::WithStaticSizes<1, 2, 3, 4>::Partial();\n    EXPECT_EQ(\n        \"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; \"\n        \"@16\" +\n            Int128::Name() + \"(16)[4]\",\n        x.DebugString());\n  }\n  {\n    constexpr Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1, 2, 3,\n                                                                       4>\n        x;\n    EXPECT_EQ(\n        \"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; \"\n        \"@16\" +\n            Int128::Name() + \"(16)[4]\",\n        x.DebugString());\n  }\n}\n\nTEST(Layout, CharTypes) {\n  constexpr Layout<int32_t> x(1);\n  alignas(max_align_t) char c[x.AllocSize()] = {};\n  alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};\n  alignas(max_align_t) signed char sc[x.AllocSize()] = {};\n  alignas(max_align_t) const char cc[x.AllocSize()] = {};\n  alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};\n  alignas(max_align_t) const signed char csc[x.AllocSize()] = {};\n\n  Type<int32_t*>(x.Pointer<0>(c));\n  Type<int32_t*>(x.Pointer<0>(uc));\n  Type<int32_t*>(x.Pointer<0>(sc));\n  Type<const int32_t*>(x.Pointer<0>(cc));\n  Type<const int32_t*>(x.Pointer<0>(cuc));\n  Type<const int32_t*>(x.Pointer<0>(csc));\n\n  Type<int32_t*>(x.Pointer<int32_t>(c));\n  Type<int32_t*>(x.Pointer<int32_t>(uc));\n  Type<int32_t*>(x.Pointer<int32_t>(sc));\n  Type<const int32_t*>(x.Pointer<int32_t>(cc));\n  Type<const int32_t*>(x.Pointer<int32_t>(cuc));\n  Type<const int32_t*>(x.Pointer<int32_t>(csc));\n\n  Type<std::tuple<int32_t*>>(x.Pointers(c));\n  Type<std::tuple<int32_t*>>(x.Pointers(uc));\n  Type<std::tuple<int32_t*>>(x.Pointers(sc));\n  Type<std::tuple<const int32_t*>>(x.Pointers(cc));\n  Type<std::tuple<const int32_t*>>(x.Pointers(cuc));\n  Type<std::tuple<const int32_t*>>(x.Pointers(csc));\n\n  Type<Span<int32_t>>(x.Slice<0>(c));\n  Type<Span<int32_t>>(x.Slice<0>(uc));\n  Type<Span<int32_t>>(x.Slice<0>(sc));\n  Type<Span<const int32_t>>(x.Slice<0>(cc));\n  Type<Span<const int32_t>>(x.Slice<0>(cuc));\n  Type<Span<const int32_t>>(x.Slice<0>(csc));\n\n  Type<std::tuple<Span<int32_t>>>(x.Slices(c));\n  Type<std::tuple<Span<int32_t>>>(x.Slices(uc));\n  Type<std::tuple<Span<int32_t>>>(x.Slices(sc));\n  Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));\n  Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));\n  Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));\n}\n\nTEST(Layout, ConstElementType) {\n  constexpr Layout<const int32_t> x(1);\n  alignas(int32_t) char c[x.AllocSize()] = {};\n  const char* cc = c;\n  const int32_t* p = reinterpret_cast<const int32_t*>(cc);\n\n  EXPECT_EQ(alignof(int32_t), x.Alignment());\n\n  EXPECT_EQ(0, x.Offset<0>());\n  EXPECT_EQ(0, x.Offset<const int32_t>());\n\n  EXPECT_THAT(x.Offsets(), ElementsAre(0));\n\n  EXPECT_EQ(1, x.Size<0>());\n  EXPECT_EQ(1, x.Size<const int32_t>());\n\n  EXPECT_THAT(x.Sizes(), ElementsAre(1));\n\n  EXPECT_EQ(sizeof(int32_t), x.AllocSize());\n\n  EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));\n  EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));\n\n  EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));\n  EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));\n\n  EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));\n  EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));\n\n  EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),\n              IsSameSlice(Span<const int32_t>(p, 1)));\n  EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),\n              IsSameSlice(Span<const int32_t>(p, 1)));\n\n  EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),\n              IsSameSlice(Span<const int32_t>(p, 1)));\n  EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),\n              IsSameSlice(Span<const int32_t>(p, 1)));\n\n  EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),\n              Tuple(IsSameSlice(Span<const int32_t>(p, 1))));\n  EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),\n              Tuple(IsSameSlice(Span<const int32_t>(p, 1))));\n}\n\nnamespace example {\n\n// Immutable move-only string with sizeof equal to sizeof(void*). The string\n// size and the characters are kept in the same heap allocation.\nclass CompactString {\n public:\n  CompactString(const char* s = \"\") {  // NOLINT\n    const size_t size = strlen(s);\n    // size_t[1], followed by char[size + 1].\n    // This statement doesn't allocate memory.\n    const L layout(1, size + 1);\n    // AllocSize() tells us how much memory we need to allocate for all our\n    // data.\n    p_.reset(new unsigned char[layout.AllocSize()]);\n    // If running under ASAN, mark the padding bytes, if any, to catch memory\n    // errors.\n    layout.PoisonPadding(p_.get());\n    // Store the size in the allocation.\n    // Pointer<size_t>() is a synonym for Pointer<0>().\n    *layout.Pointer<size_t>(p_.get()) = size;\n    // Store the characters in the allocation.\n    memcpy(layout.Pointer<char>(p_.get()), s, size + 1);\n  }\n\n  size_t size() const {\n    // Equivalent to reinterpret_cast<size_t&>(*p).\n    return *L::Partial().Pointer<size_t>(p_.get());\n  }\n\n  const char* c_str() const {\n    // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).\n    // The argument in Partial(1) specifies that we have size_t[1] in front of\n    // the characters.\n    return L::Partial(1).Pointer<char>(p_.get());\n  }\n\n private:\n  // Our heap allocation contains a size_t followed by an array of chars.\n  using L = Layout<size_t, char>;\n  std::unique_ptr<unsigned char[]> p_;\n};\n\nTEST(CompactString, Works) {\n  CompactString s = \"hello\";\n  EXPECT_EQ(5, s.size());\n  EXPECT_STREQ(\"hello\", s.c_str());\n}\n\n// Same as the previous CompactString example, except we set the first array\n// size to 1 statically, since we know it is always 1. This allows us to compute\n// the offset of the character array at compile time.\nclass StaticCompactString {\n public:\n  StaticCompactString(const char* s = \"\") {  // NOLINT\n    const size_t size = strlen(s);\n    const SL layout(size + 1);\n    p_.reset(new unsigned char[layout.AllocSize()]);\n    layout.PoisonPadding(p_.get());\n    *layout.Pointer<size_t>(p_.get()) = size;\n    memcpy(layout.Pointer<char>(p_.get()), s, size + 1);\n  }\n\n  size_t size() const { return *SL::Partial().Pointer<size_t>(p_.get()); }\n\n  const char* c_str() const { return SL::Partial().Pointer<char>(p_.get()); }\n\n private:\n  using SL = Layout<size_t, char>::WithStaticSizes<1>;\n  std::unique_ptr<unsigned char[]> p_;\n};\n\nTEST(StaticCompactString, Works) {\n  StaticCompactString s = \"hello\";\n  EXPECT_EQ(5, s.size());\n  EXPECT_STREQ(\"hello\", s.c_str());\n}\n\n}  // namespace example\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/node_slot_policy.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Adapts a policy for nodes.\n//\n// The node policy should model:\n//\n// struct Policy {\n//   // Returns a new node allocated and constructed using the allocator, using\n//   // the specified arguments.\n//   template <class Alloc, class... Args>\n//   value_type* new_element(Alloc* alloc, Args&&... args) const;\n//\n//   // Destroys and deallocates node using the allocator.\n//   template <class Alloc>\n//   void delete_element(Alloc* alloc, value_type* node) const;\n// };\n//\n// It may also optionally define `value()` and `apply()`. For documentation on\n// these, see hash_policy_traits.h.\n\n#ifndef ABSL_CONTAINER_INTERNAL_NODE_SLOT_POLICY_H_\n#define ABSL_CONTAINER_INTERNAL_NODE_SLOT_POLICY_H_\n\n#include <cassert>\n#include <cstddef>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class Reference, class Policy>\nstruct node_slot_policy {\n  static_assert(std::is_lvalue_reference<Reference>::value, \"\");\n\n  using slot_type = typename std::remove_cv<\n      typename std::remove_reference<Reference>::type>::type*;\n\n  template <class Alloc, class... Args>\n  static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {\n    *slot = Policy::new_element(alloc, std::forward<Args>(args)...);\n  }\n\n  template <class Alloc>\n  static void destroy(Alloc* alloc, slot_type* slot) {\n    Policy::delete_element(alloc, *slot);\n  }\n\n  // Returns true_type to indicate that transfer can use memcpy.\n  template <class Alloc>\n  static std::true_type transfer(Alloc*, slot_type* new_slot,\n                                 slot_type* old_slot) {\n    *new_slot = *old_slot;\n    return {};\n  }\n\n  static size_t space_used(const slot_type* slot) {\n    if (slot == nullptr) return Policy::element_space_used(nullptr);\n    return Policy::element_space_used(*slot);\n  }\n\n  static Reference element(slot_type* slot) { return **slot; }\n\n  template <class T, class P = Policy>\n  static auto value(T* elem) -> decltype(P::value(elem)) {\n    return P::value(elem);\n  }\n\n  template <class... Ts, class P = Policy>\n  static auto apply(Ts&&... ts) -> decltype(P::apply(std::forward<Ts>(ts)...)) {\n    return P::apply(std::forward<Ts>(ts)...);\n  }\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_NODE_SLOT_POLICY_H_\n"
  },
  {
    "path": "absl/container/internal/node_slot_policy_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/node_slot_policy.h\"\n\n#include <memory>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_policy_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::Pointee;\n\nstruct Policy : node_slot_policy<int&, Policy> {\n  using key_type = int;\n  using init_type = int;\n\n  template <class Alloc>\n  static int* new_element(Alloc* alloc, int value) {\n    return new int(value);\n  }\n\n  template <class Alloc>\n  static void delete_element(Alloc* alloc, int* elem) {\n    delete elem;\n  }\n};\n\nusing NodePolicy = hash_policy_traits<Policy>;\n\nstruct NodeTest : ::testing::Test {\n  std::allocator<int> alloc;\n  int n = 53;\n  int* a = &n;\n};\n\nTEST_F(NodeTest, ConstructDestroy) {\n  NodePolicy::construct(&alloc, &a, 42);\n  EXPECT_THAT(a, Pointee(42));\n  NodePolicy::destroy(&alloc, &a);\n}\n\nTEST_F(NodeTest, transfer) {\n  int s = 42;\n  int* b = &s;\n  NodePolicy::transfer(&alloc, &a, &b);\n  EXPECT_EQ(&s, a);\n  EXPECT_TRUE(NodePolicy::transfer_uses_memcpy());\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/raw_hash_map.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_\n#define ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_\n\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/container/internal/common_policy_traits.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/raw_hash_set.h\"  // IWYU pragma: export\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class Policy, class... Params>\nclass raw_hash_map;\n\ntemplate <typename Policy, typename Hash, typename Eq, typename Alloc>\nstruct InstantiateRawHashMap {\n  using type = typename ApplyWithoutDefaultSuffix<\n      raw_hash_map,\n      TypeList<int, typename Policy::DefaultHash, typename Policy::DefaultEq,\n               typename Policy::DefaultAlloc>,\n      TypeList<Policy, Hash, Eq, Alloc>>::type;\n};\n\ntemplate <class Policy, class... Params>\nclass raw_hash_map : public raw_hash_set<Policy, Params...> {\n  // P is Policy. It's passed as a template argument to support maps that have\n  // incomplete types as values, as in unordered_map<K, IncompleteType>.\n  // MappedReference<> may be a non-reference type.\n  template <class P>\n  using MappedReference = decltype(P::value(\n      std::addressof(std::declval<typename raw_hash_map::reference>())));\n\n  // MappedConstReference<> may be a non-reference type.\n  template <class P>\n  using MappedConstReference = decltype(P::value(\n      std::addressof(std::declval<typename raw_hash_map::const_reference>())));\n\n  using Hash = typename raw_hash_map::raw_hash_set::hasher;\n  using Eq = typename raw_hash_map::raw_hash_set::key_equal;\n  using Alloc = typename raw_hash_map::raw_hash_set::allocator_type;\n\n  template <class K>\n  using key_arg =\n      typename KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>::\n          template type<K, typename Policy::key_type>;\n\n  // NOTE: The mess here is to shorten the code for the (very repetitive)\n  // function overloads, and to allow the lifetime-bound overloads to dispatch\n  // to the non-lifetime-bound overloads, to ensure there is a single source of\n  // truth for each overload set.\n  //\n  // Enabled if an assignment from the given type would require the\n  // source object to remain alive for the life of the element.\n  //\n  // TODO(b/402804213): Remove these traits and simplify the overloads whenever\n  // we have a better mechanism available to handle lifetime analysis.\n  template <class K, bool Value, typename = void>\n  using LifetimeBoundK = HasValue<\n      Value, std::conditional_t<policy_trait_element_is_owner<Policy>::value,\n                                std::false_type,\n                                type_traits_internal::IsLifetimeBoundAssignment<\n                                    typename Policy::key_type, K>>>;\n  template <class V, bool Value, typename = void>\n  using LifetimeBoundV =\n      HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<\n                          typename Policy::mapped_type, V>>;\n  template <class K, bool KValue, class V, bool VValue, typename... Dummy>\n  using LifetimeBoundKV =\n      absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,\n                        LifetimeBoundV<V, VValue>>;\n\n public:\n  using key_type = typename Policy::key_type;\n  using mapped_type = typename Policy::mapped_type;\n\n  static_assert(!std::is_reference<key_type>::value, \"\");\n\n  // TODO(b/187807849): Evaluate whether to support reference mapped_type and\n  // remove this assertion if/when it is supported.\n  static_assert(!std::is_reference<mapped_type>::value, \"\");\n\n  using iterator = typename raw_hash_map::raw_hash_set::iterator;\n  using const_iterator = typename raw_hash_map::raw_hash_set::const_iterator;\n\n  raw_hash_map() {}\n  using raw_hash_map::raw_hash_set::raw_hash_set;\n\n  // The last two template parameters ensure that both arguments are rvalues\n  // (lvalue arguments are handled by the overloads below). This is necessary\n  // for supporting bitfield arguments.\n  //\n  //   union { int n : 1; };\n  //   flat_hash_map<int, int> m;\n  //   m.insert_or_assign(n, n);\n  //\n  // TODO(b/402804213): Remove these macros whenever we have a better mechanism\n  // available to handle lifetime analysis.\n#define ABSL_INTERNAL_X(Func, Callee, KQual, VQual, KValue, VValue, Tail, ...) \\\n  template <                                                                   \\\n      typename K = key_type, class V = mapped_type,                            \\\n      ABSL_INTERNAL_IF_##KValue##_NOR_##VValue(                                \\\n          int = (EnableIf<LifetimeBoundKV<K, KValue, V, VValue,                \\\n                                          IfRRef<int KQual>::AddPtr<K>,        \\\n                                          IfRRef<int VQual>::AddPtr<V>>>()),   \\\n          ABSL_INTERNAL_SINGLE_ARG(                                            \\\n              int &...,                                                        \\\n              decltype(EnableIf<LifetimeBoundKV<K, KValue, V, VValue>>()) =    \\\n                  0))>                                                         \\\n  decltype(auto) Func(                                                         \\\n      __VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue(                \\\n          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)),                          \\\n      V VQual v ABSL_INTERNAL_IF_##VValue(ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY( \\\n          this))) ABSL_ATTRIBUTE_LIFETIME_BOUND {                              \\\n    return ABSL_INTERNAL_IF_##KValue##_OR_##VValue(                            \\\n        (this->template Func<K, V, 0>), Callee)(                               \\\n        std::forward<decltype(k)>(k), std::forward<decltype(v)>(v)) Tail;      \\\n  }                                                                            \\\n  static_assert(true, \"This is to force a semicolon.\")\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  false, false, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  false, true, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  true, false, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  true, true, ABSL_INTERNAL_SINGLE_ARG());\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,\n                  false, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,\n                  true, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,\n                  false, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,\n                  true, ABSL_INTERNAL_SINGLE_ARG());\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,\n                  false, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,\n                  true, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,\n                  false, ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,\n                  true, ABSL_INTERNAL_SINGLE_ARG());\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, false,\n                  ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true,\n                  ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false,\n                  ABSL_INTERNAL_SINGLE_ARG());\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true,\n                  ABSL_INTERNAL_SINGLE_ARG());\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  false, false, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  false, true, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  true, false, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,\n                  true, true, .first, const_iterator ABSL_INTERNAL_COMMA);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,\n                  false, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,\n                  true, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,\n                  false, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,\n                  true, .first, const_iterator ABSL_INTERNAL_COMMA);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,\n                  false, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,\n                  true, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,\n                  false, .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,\n                  true, .first, const_iterator ABSL_INTERNAL_COMMA);\n\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, false,\n                  .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true,\n                  .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false,\n                  .first, const_iterator ABSL_INTERNAL_COMMA);\n  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true,\n                  .first, const_iterator ABSL_INTERNAL_COMMA);\n#undef ABSL_INTERNAL_X\n\n  // All `try_emplace()` overloads make the same guarantees regarding rvalue\n  // arguments as `std::unordered_map::try_emplace()`, namely that these\n  // functions will not move from rvalue arguments if insertions do not happen.\n  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false, K *>>(),\n            class... Args,\n            typename std::enable_if<\n                !std::is_convertible<K, const_iterator>::value, int>::type = 0>\n  std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&...args)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return try_emplace_impl(std::forward<key_arg<K>>(k),\n                            std::forward<Args>(args)...);\n  }\n\n  template <class K = key_type, class... Args,\n            EnableIf<LifetimeBoundK<K, true, K *>> = 0,\n            typename std::enable_if<\n                !std::is_convertible<K, const_iterator>::value, int>::type = 0>\n  std::pair<iterator, bool> try_emplace(\n      key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n      Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template try_emplace<K, 0>(std::forward<key_arg<K>>(k),\n                                            std::forward<Args>(args)...);\n  }\n\n  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>(),\n            class... Args,\n            typename std::enable_if<\n                !std::is_convertible<K, const_iterator>::value, int>::type = 0>\n  std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&...args)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return try_emplace_impl(k, std::forward<Args>(args)...);\n  }\n  template <class K = key_type, class... Args,\n            EnableIf<LifetimeBoundK<K, true>> = 0,\n            typename std::enable_if<\n                !std::is_convertible<K, const_iterator>::value, int>::type = 0>\n  std::pair<iterator, bool> try_emplace(\n      const key_arg<K> &k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n      Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template try_emplace<K, 0>(k, std::forward<Args>(args)...);\n  }\n\n  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false, K *>>(),\n            class... Args>\n  iterator try_emplace(const_iterator, key_arg<K> &&k,\n                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return try_emplace(std::forward<key_arg<K>>(k), std::forward<Args>(args)...)\n        .first;\n  }\n  template <class K = key_type, class... Args,\n            EnableIf<LifetimeBoundK<K, true, K *>> = 0>\n  iterator try_emplace(const_iterator hint,\n                       key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template try_emplace<K, 0>(hint, std::forward<key_arg<K>>(k),\n                                            std::forward<Args>(args)...);\n  }\n\n  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>(),\n            class... Args>\n  iterator try_emplace(const_iterator, const key_arg<K> &k,\n                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return try_emplace(k, std::forward<Args>(args)...).first;\n  }\n  template <class K = key_type, class... Args,\n            EnableIf<LifetimeBoundK<K, true>> = 0>\n  iterator try_emplace(const_iterator hint,\n                       const key_arg<K> &k\n                           ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template try_emplace<K, 0>(hint, k,\n                                            std::forward<Args>(args)...);\n  }\n\n  template <class K = key_type, class P = Policy>\n  MappedReference<P> at(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto it = this->find(key);\n    if (it == this->end()) {\n      ThrowStdOutOfRange(\"absl::container_internal::raw_hash_map<>::at\");\n    }\n    return Policy::value(&*it);\n  }\n\n  template <class K = key_type, class P = Policy>\n  MappedConstReference<P> at(const key_arg<K>& key) const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto it = this->find(key);\n    if (it == this->end()) {\n      ThrowStdOutOfRange(\"absl::container_internal::raw_hash_map<>::at\");\n    }\n    return Policy::value(&*it);\n  }\n\n  template <class K = key_type, class P = Policy,\n            int = EnableIf<LifetimeBoundK<K, false, K *>>()>\n  MappedReference<P> operator[](key_arg<K> &&key)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // It is safe to use unchecked_deref here because try_emplace\n    // will always return an iterator pointing to a valid item in the table,\n    // since it inserts if nothing is found for the given key.\n    return Policy::value(&this->unchecked_deref(\n        try_emplace(std::forward<key_arg<K>>(key)).first));\n  }\n  template <class K = key_type, class P = Policy, int &...,\n            EnableIf<LifetimeBoundK<K, true, K *>> = 0>\n  MappedReference<P> operator[](\n      key_arg<K> &&key ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template operator[]<K, P, 0>(std::forward<key_arg<K>>(key));\n  }\n\n  template <class K = key_type, class P = Policy,\n            int = EnableIf<LifetimeBoundK<K, false>>()>\n  MappedReference<P> operator[](const key_arg<K> &key)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    // It is safe to use unchecked_deref here because try_emplace\n    // will always return an iterator pointing to a valid item in the table,\n    // since it inserts if nothing is found for the given key.\n    return Policy::value(&this->unchecked_deref(try_emplace(key).first));\n  }\n  template <class K = key_type, class P = Policy, int &...,\n            EnableIf<LifetimeBoundK<K, true>> = 0>\n  MappedReference<P> operator[](\n      const key_arg<K> &key ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template operator[]<K, P, 0>(key);\n  }\n\n private:\n  static_assert(\n      std::is_same_v<\n          typename InstantiateRawHashMap<Policy, Hash, Eq, Alloc>::type,\n          raw_hash_map>,\n      \"Redundant template parameters were passed. Use InstantiateRawHashMap<> \"\n      \"instead\");\n\n  template <class K, class V>\n  std::pair<iterator, bool> insert_or_assign_impl(K&& k, V&& v)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto res = this->find_or_prepare_insert(k);\n    if (res.second) {\n      this->emplace_at(res.first, std::forward<K>(k), std::forward<V>(v));\n    } else {\n      Policy::value(&*res.first) = std::forward<V>(v);\n    }\n    return res;\n  }\n\n  template <class K = key_type, class... Args>\n  std::pair<iterator, bool> try_emplace_impl(K&& k, Args&&... args)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto res = this->find_or_prepare_insert(k);\n    if (res.second) {\n      this->emplace_at(res.first, std::piecewise_construct,\n                       std::forward_as_tuple(std::forward<K>(k)),\n                       std::forward_as_tuple(std::forward<Args>(args)...));\n    }\n    return res;\n  }\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/raw_hash_set.h\"\n\n#include <atomic>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <memory>\n#include <tuple>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/hashtable_control_bytes.h\"\n#include \"absl/container/internal/hashtablez_sampler.h\"\n#include \"absl/container/internal/raw_hash_set_resize_impl.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/hash/hash.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// Represents a control byte corresponding to a full slot with arbitrary hash.\nconstexpr ctrl_t ZeroCtrlT() { return static_cast<ctrl_t>(0); }\n\n// A single control byte for default-constructed iterators. We leave it\n// uninitialized because reading this memory is a bug.\nABSL_DLL ctrl_t kDefaultIterControl;\n\n// We need one full byte followed by a sentinel byte for iterator::operator++.\nABSL_CONST_INIT ABSL_DLL const ctrl_t kSooControl[2] = {ZeroCtrlT(),\n                                                        ctrl_t::kSentinel};\n\nnamespace {\n\n#ifdef ABSL_SWISSTABLE_ASSERT\n#error ABSL_SWISSTABLE_ASSERT cannot be directly set\n#else\n// We use this macro for assertions that users may see when the table is in an\n// invalid state that sanitizers may help diagnose.\n#define ABSL_SWISSTABLE_ASSERT(CONDITION) \\\n  assert((CONDITION) && \"Try enabling sanitizers.\")\n#endif\n\nvoid ValidateMaxSize([[maybe_unused]] size_t size,\n                     [[maybe_unused]] size_t key_size,\n                     [[maybe_unused]] size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(size <= MaxValidSize(key_size, slot_size));\n}\nvoid ValidateMaxCapacity(size_t capacity, size_t key_size, size_t slot_size) {\n  if (capacity <= 1) return;\n  ValidateMaxSize(CapacityToGrowth(PreviousCapacity(capacity)), key_size,\n                  slot_size);\n}\n\n// Returns \"random\" seed.\ninline size_t RandomSeed() {\n#ifdef ABSL_HAVE_THREAD_LOCAL\n  static thread_local size_t counter = 0;\n  size_t value = ++counter;\n#else   // ABSL_HAVE_THREAD_LOCAL\n  static std::atomic<size_t> counter(0);\n  size_t value = counter.fetch_add(1, std::memory_order_relaxed);\n#endif  // ABSL_HAVE_THREAD_LOCAL\n  return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));\n}\n\nbool ShouldRehashForBugDetection(size_t capacity) {\n  // Note: we can't use the abseil-random library because abseil-random\n  // depends on swisstable. We want to return true with probability\n  // `min(1, RehashProbabilityConstant() / capacity())`. In order to do this,\n  // we probe based on a random hash and see if the offset is less than\n  // RehashProbabilityConstant().\n  return probe(capacity, absl::HashOf(RandomSeed())).offset() <\n         RehashProbabilityConstant();\n}\n\n// Find a non-deterministic hash for single group table.\n// Last two bits are used to find a position for a newly inserted element after\n// resize.\n// This function basically using H2 last bits to save on shift operation.\nsize_t SingleGroupTableH1(size_t hash, PerTableSeed seed) {\n  return hash ^ seed.seed();\n}\n\n// Returns the offset of the new element after resize from capacity 1 to 3.\nsize_t Resize1To3NewOffset(size_t hash, PerTableSeed seed) {\n  // After resize from capacity 1 to 3, we always have exactly the slot with\n  // index 1 occupied, so we need to insert either at index 0 or index 2.\n  static_assert(SooSlotIndex() == 1);\n  return SingleGroupTableH1(hash, seed) & 2;\n}\n\n// Returns the address of the ith slot in slots where each slot occupies\n// slot_size.\ninline void* SlotAddress(void* slot_array, size_t slot, size_t slot_size) {\n  return static_cast<void*>(static_cast<char*>(slot_array) +\n                            (slot * slot_size));\n}\n\n// Returns the address of the slot `i` iterations after `slot` assuming each\n// slot has the specified size.\ninline void* NextSlot(void* slot, size_t slot_size, size_t i = 1) {\n  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) +\n                                 slot_size * i);\n}\n\n// Returns the address of the slot just before `slot` assuming each slot has the\n// specified size.\ninline void* PrevSlot(void* slot, size_t slot_size) {\n  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) - slot_size);\n}\n\n}  // namespace\n\n// Must be defined out-of-line to avoid MSVC error C2482 on some platforms,\n// which is caused by non-constexpr initialization.\nuint16_t HashtableSize::NextSeed() {\n  static_assert(PerTableSeed::kBitCount == 16);\n  thread_local uint16_t seed =\n      static_cast<uint16_t>(reinterpret_cast<uintptr_t>(&seed));\n  seed += uint16_t{0xad53};\n  return seed;\n}\n\nGenerationType* EmptyGeneration() {\n  if (SwisstableGenerationsEnabled()) {\n    constexpr size_t kNumEmptyGenerations = 1024;\n    static constexpr GenerationType kEmptyGenerations[kNumEmptyGenerations]{};\n    return const_cast<GenerationType*>(\n        &kEmptyGenerations[RandomSeed() % kNumEmptyGenerations]);\n  }\n  return nullptr;\n}\n\nbool CommonFieldsGenerationInfoEnabled::\n    should_rehash_for_bug_detection_on_insert(size_t capacity) const {\n  if (reserved_growth_ == kReservedGrowthJustRanOut) return true;\n  if (reserved_growth_ > 0) return false;\n  return ShouldRehashForBugDetection(capacity);\n}\n\nbool CommonFieldsGenerationInfoEnabled::should_rehash_for_bug_detection_on_move(\n    size_t capacity) const {\n  return ShouldRehashForBugDetection(capacity);\n}\n\nnamespace {\n\n// Probes an array of control bits using a probe sequence,\n// and returns the mask corresponding to the first group with a deleted or empty\n// slot.\ninline Group::NonIterableBitMaskType probe_till_first_non_full_group(\n    const ctrl_t* ctrl, probe_seq<Group::kWidth>& seq,\n    [[maybe_unused]] size_t capacity) {\n  while (true) {\n    GroupFullEmptyOrDeleted g{ctrl + seq.offset()};\n    auto mask = g.MaskEmptyOrDeleted();\n    if (mask) {\n      return mask;\n    }\n    seq.next();\n    ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity && \"full table!\");\n  }\n}\n\nFindInfo find_first_non_full_from_h1(const ctrl_t* ctrl, size_t h1,\n                                     size_t capacity) {\n  auto seq = probe_h1(capacity, h1);\n  if (IsEmptyOrDeleted(ctrl[seq.offset()])) {\n    return {seq.offset(), /*probe_length=*/0};\n  }\n  auto mask = probe_till_first_non_full_group(ctrl, seq, capacity);\n  return {seq.offset(mask.LowestBitSet()), seq.index()};\n}\n\n// Probes an array of control bits using a probe sequence derived from `hash`,\n// and returns the offset corresponding to the first deleted or empty slot.\n//\n// Behavior when the entire table is full is undefined.\n//\n// NOTE: this function must work with tables having both empty and deleted\n// slots in the same group. Such tables appear during `erase()`.\nFindInfo find_first_non_full(const CommonFields& common, size_t hash) {\n  return find_first_non_full_from_h1(common.control(), H1(hash),\n                                     common.capacity());\n}\n\n// Same as `find_first_non_full`, but returns the mask corresponding to the\n// first group with a deleted or empty slot.\nstd::pair<FindInfo, Group::NonIterableBitMaskType> find_first_non_full_group(\n    const CommonFields& common, size_t hash) {\n  auto seq = probe(common, hash);\n  auto mask =\n      probe_till_first_non_full_group(common.control(), seq, common.capacity());\n  return {{seq.offset(), seq.index()}, mask};\n}\n\n// Whether a table fits in half a group. A half-group table fits entirely into a\n// probing group, i.e., has a capacity < `Group::kWidth`.\n//\n// In half-group mode we are able to use the whole capacity. The extra control\n// bytes give us at least one \"empty\" control byte to stop the iteration.\n// This is important to make 1 a valid capacity.\n//\n// In half-group mode only the first `capacity` control bytes after the sentinel\n// are valid. The rest contain dummy ctrl_t::kEmpty values that do not\n// represent a real slot.\nconstexpr bool is_half_group(size_t capacity) {\n  return capacity < Group::kWidth - 1;\n}\n\ntemplate <class Fn>\nvoid IterateOverFullSlotsImpl(const CommonFields& c, size_t slot_size, Fn cb) {\n  const size_t cap = c.capacity();\n  ABSL_SWISSTABLE_ASSERT(!IsSmallCapacity(cap));\n  const ctrl_t* ctrl = c.control();\n  void* slot = c.slot_array();\n  if (is_half_group(cap)) {\n    // Mirrored/cloned control bytes in half-group table are also located in the\n    // first group (starting from position 0). We are taking group from position\n    // `capacity` in order to avoid duplicates.\n\n    // Half-group tables capacity fits into portable group, where\n    // GroupPortableImpl::MaskFull is more efficient for the\n    // capacity <= GroupPortableImpl::kWidth.\n    ABSL_SWISSTABLE_ASSERT(cap <= GroupPortableImpl::kWidth &&\n                           \"unexpectedly large half-group capacity\");\n    static_assert(Group::kWidth >= GroupPortableImpl::kWidth,\n                  \"unexpected group width\");\n    // Group starts from kSentinel slot, so indices in the mask will\n    // be increased by 1.\n    const auto mask = GroupPortableImpl(ctrl + cap).MaskFull();\n    --ctrl;\n    slot = PrevSlot(slot, slot_size);\n    for (uint32_t i : mask) {\n      cb(ctrl + i, SlotAddress(slot, i, slot_size));\n    }\n    return;\n  }\n  size_t remaining = c.size();\n  ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = remaining;\n  while (remaining != 0) {\n    for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) {\n      ABSL_SWISSTABLE_ASSERT(IsFull(ctrl[i]) &&\n                             \"hash table was modified unexpectedly\");\n      cb(ctrl + i, SlotAddress(slot, i, slot_size));\n      --remaining;\n    }\n    ctrl += Group::kWidth;\n    slot = NextSlot(slot, slot_size, Group::kWidth);\n    ABSL_SWISSTABLE_ASSERT(\n        (remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) &&\n        \"hash table was modified unexpectedly\");\n  }\n  // NOTE: erasure of the current element is allowed in callback for\n  // absl::erase_if specialization. So we use `>=`.\n  ABSL_SWISSTABLE_ASSERT(original_size_for_assert >= c.size() &&\n                         \"hash table was modified unexpectedly\");\n}\n\n}  // namespace\n\nvoid ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {\n  ABSL_SWISSTABLE_ASSERT(ctrl[capacity] == ctrl_t::kSentinel);\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));\n  for (ctrl_t* pos = ctrl; pos < ctrl + capacity; pos += Group::kWidth) {\n    Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);\n  }\n  // Copy the cloned ctrl bytes.\n  std::memcpy(ctrl + capacity + 1, ctrl, NumClonedBytes());\n  ctrl[capacity] = ctrl_t::kSentinel;\n}\n\nvoid IterateOverFullSlots(const CommonFields& c, size_t slot_size,\n                          absl::FunctionRef<void(const ctrl_t*, void*)> cb) {\n  IterateOverFullSlotsImpl(c, slot_size, cb);\n}\n\nnamespace {\n\nvoid ResetGrowthLeft(GrowthInfo& growth_info, size_t capacity, size_t size) {\n  growth_info.InitGrowthLeftNoDeleted(CapacityToGrowth(capacity) - size);\n}\n\nvoid ResetGrowthLeft(CommonFields& common) {\n  ResetGrowthLeft(common.growth_info(), common.capacity(), common.size());\n}\n\n// Finds guaranteed to exists empty slot from the given position.\n// NOTE: this function is almost never triggered inside of the\n// DropDeletesWithoutResize, so we keep it simple.\n// The table is rather sparse, so empty slot will be found very quickly.\nsize_t FindEmptySlot(size_t start, size_t end, const ctrl_t* ctrl) {\n  for (size_t i = start; i < end; ++i) {\n    if (IsEmpty(ctrl[i])) {\n      return i;\n    }\n  }\n  ABSL_UNREACHABLE();\n}\n\n// Finds guaranteed to exist full slot starting from the given position.\n// NOTE: this function is only triggered for rehash(0), when we need to\n// go back to SOO state, so we keep it simple.\nsize_t FindFirstFullSlot(size_t start, size_t end, const ctrl_t* ctrl) {\n  for (size_t i = start; i < end; ++i) {\n    if (IsFull(ctrl[i])) {\n      return i;\n    }\n  }\n  ABSL_UNREACHABLE();\n}\n\nvoid PrepareInsertCommon(CommonFields& common) {\n  common.increment_size();\n  common.maybe_increment_generation_on_insert();\n}\n\n// Sets sanitizer poisoning for slot corresponding to control byte being set.\ninline void DoSanitizeOnSetCtrl(const CommonFields& c, size_t i, ctrl_t h,\n                                size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(i < c.capacity());\n  auto* slot_i = static_cast<const char*>(c.slot_array()) + i * slot_size;\n  if (IsFull(h)) {\n    SanitizerUnpoisonMemoryRegion(slot_i, slot_size);\n  } else {\n    SanitizerPoisonMemoryRegion(slot_i, slot_size);\n  }\n}\n\n// Sets `ctrl[i]` to `h`.\n//\n// Unlike setting it directly, this function will perform bounds checks and\n// mirror the value to the cloned tail if necessary.\ninline void SetCtrl(const CommonFields& c, size_t i, ctrl_t h,\n                    size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(!c.is_small());\n  DoSanitizeOnSetCtrl(c, i, h, slot_size);\n  ctrl_t* ctrl = c.control();\n  ctrl[i] = h;\n  ctrl[((i - NumClonedBytes()) & c.capacity()) +\n       (NumClonedBytes() & c.capacity())] = h;\n}\n// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.\ninline void SetCtrl(const CommonFields& c, size_t i, h2_t h, size_t slot_size) {\n  SetCtrl(c, i, static_cast<ctrl_t>(h), slot_size);\n}\n\n// Like SetCtrl, but in a single group table, we can save some operations when\n// setting the cloned control byte.\ninline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, ctrl_t h,\n                                      size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(!c.is_small());\n  ABSL_SWISSTABLE_ASSERT(is_single_group(c.capacity()));\n  DoSanitizeOnSetCtrl(c, i, h, slot_size);\n  ctrl_t* ctrl = c.control();\n  ctrl[i] = h;\n  ctrl[i + c.capacity() + 1] = h;\n}\n// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.\ninline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, h2_t h,\n                                      size_t slot_size) {\n  SetCtrlInSingleGroupTable(c, i, static_cast<ctrl_t>(h), slot_size);\n}\n\n// Like SetCtrl, but in a table with capacity >= Group::kWidth - 1,\n// we can save some operations when setting the cloned control byte.\ninline void SetCtrlInLargeTable(const CommonFields& c, size_t i, ctrl_t h,\n                                size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(c.capacity() >= Group::kWidth - 1);\n  DoSanitizeOnSetCtrl(c, i, h, slot_size);\n  ctrl_t* ctrl = c.control();\n  ctrl[i] = h;\n  ctrl[((i - NumClonedBytes()) & c.capacity()) + NumClonedBytes()] = h;\n}\n// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.\ninline void SetCtrlInLargeTable(const CommonFields& c, size_t i, h2_t h,\n                                size_t slot_size) {\n  SetCtrlInLargeTable(c, i, static_cast<ctrl_t>(h), slot_size);\n}\n\nsize_t DropDeletesWithoutResizeAndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t new_hash) {\n  void* set = &common;\n  void* slot_array = common.slot_array();\n  const size_t capacity = common.capacity();\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));\n  ABSL_SWISSTABLE_ASSERT(!is_single_group(capacity));\n  // Algorithm:\n  // - mark all DELETED slots as EMPTY\n  // - mark all FULL slots as DELETED\n  // - for each slot marked as DELETED\n  //     hash = Hash(element)\n  //     target = find_first_non_full(hash)\n  //     if target is in the same group\n  //       mark slot as FULL\n  //     else if target is EMPTY\n  //       transfer element to target\n  //       mark slot as EMPTY\n  //       mark target as FULL\n  //     else if target is DELETED\n  //       swap current element with target element\n  //       mark target as FULL\n  //       repeat procedure for current slot with moved from element (target)\n  ctrl_t* ctrl = common.control();\n  ConvertDeletedToEmptyAndFullToDeleted(ctrl, capacity);\n  const void* hash_fn = policy.hash_fn(common);\n  auto hasher = policy.hash_slot;\n  auto transfer_n = policy.transfer_n;\n  const size_t slot_size = policy.slot_size;\n\n  size_t total_probe_length = 0;\n  void* slot_ptr = SlotAddress(slot_array, 0, slot_size);\n\n  // The index of an empty slot that can be used as temporary memory for\n  // the swap operation.\n  constexpr size_t kUnknownId = ~size_t{};\n  size_t tmp_space_id = kUnknownId;\n\n  for (size_t i = 0; i != capacity;\n       ++i, slot_ptr = NextSlot(slot_ptr, slot_size)) {\n    ABSL_SWISSTABLE_ASSERT(slot_ptr == SlotAddress(slot_array, i, slot_size));\n    if (IsEmpty(ctrl[i])) {\n      tmp_space_id = i;\n      continue;\n    }\n    if (!IsDeleted(ctrl[i])) continue;\n    const size_t hash = (*hasher)(hash_fn, slot_ptr, common.seed().seed());\n    const FindInfo target = find_first_non_full(common, hash);\n    const size_t new_i = target.offset;\n    total_probe_length += target.probe_length;\n\n    // Verify if the old and new i fall within the same group wrt the hash.\n    // If they do, we don't need to move the object as it falls already in the\n    // best probe we can.\n    const size_t probe_offset = probe(common, hash).offset();\n    const h2_t h2 = H2(hash);\n    const auto probe_index = [probe_offset, capacity](size_t pos) {\n      return ((pos - probe_offset) & capacity) / Group::kWidth;\n    };\n\n    // Element doesn't move.\n    if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {\n      SetCtrlInLargeTable(common, i, h2, slot_size);\n      continue;\n    }\n\n    void* new_slot_ptr = SlotAddress(slot_array, new_i, slot_size);\n    if (IsEmpty(ctrl[new_i])) {\n      // Transfer element to the empty spot.\n      // SetCtrl poisons/unpoisons the slots so we have to call it at the\n      // right time.\n      SetCtrlInLargeTable(common, new_i, h2, slot_size);\n      (*transfer_n)(set, new_slot_ptr, slot_ptr, 1);\n      SetCtrlInLargeTable(common, i, ctrl_t::kEmpty, slot_size);\n      // Initialize or change empty space id.\n      tmp_space_id = i;\n    } else {\n      ABSL_SWISSTABLE_ASSERT(IsDeleted(ctrl[new_i]));\n      SetCtrlInLargeTable(common, new_i, h2, slot_size);\n      // Until we are done rehashing, DELETED marks previously FULL slots.\n\n      if (tmp_space_id == kUnknownId) {\n        tmp_space_id = FindEmptySlot(i + 1, capacity, ctrl);\n      }\n      void* tmp_space = SlotAddress(slot_array, tmp_space_id, slot_size);\n      SanitizerUnpoisonMemoryRegion(tmp_space, slot_size);\n\n      // Swap i and new_i elements.\n      (*transfer_n)(set, tmp_space, new_slot_ptr, 1);\n      (*transfer_n)(set, new_slot_ptr, slot_ptr, 1);\n      (*transfer_n)(set, slot_ptr, tmp_space, 1);\n\n      SanitizerPoisonMemoryRegion(tmp_space, slot_size);\n\n      // repeat the processing of the ith slot\n      --i;\n      slot_ptr = PrevSlot(slot_ptr, slot_size);\n    }\n  }\n  // Prepare insert for the new element.\n  PrepareInsertCommon(common);\n  ResetGrowthLeft(common);\n  FindInfo find_info = find_first_non_full(common, new_hash);\n  SetCtrlInLargeTable(common, find_info.offset, H2(new_hash), slot_size);\n  common.infoz().RecordInsertMiss(new_hash, find_info.probe_length);\n  common.infoz().RecordRehash(total_probe_length);\n  return find_info.offset;\n}\n\nbool WasNeverFull(CommonFields& c, size_t index) {\n  if (is_single_group(c.capacity())) {\n    return true;\n  }\n  const size_t index_before = (index - Group::kWidth) & c.capacity();\n  const auto empty_after = Group(c.control() + index).MaskEmpty();\n  const auto empty_before = Group(c.control() + index_before).MaskEmpty();\n\n  // We count how many consecutive non empties we have to the right and to the\n  // left of `it`. If the sum is >= kWidth then there is at least one probe\n  // window that might have seen a full group.\n  return empty_before && empty_after &&\n         static_cast<size_t>(empty_after.TrailingZeros()) +\n                 empty_before.LeadingZeros() <\n             Group::kWidth;\n}\n\n// Updates the control bytes to indicate a completely empty table such that all\n// control bytes are kEmpty except for the kSentinel byte.\nvoid ResetCtrl(CommonFields& common, size_t slot_size) {\n  const size_t capacity = common.capacity();\n  ctrl_t* ctrl = common.control();\n  static constexpr size_t kTwoGroupCapacity = 2 * Group::kWidth - 1;\n  if (ABSL_PREDICT_TRUE(capacity <= kTwoGroupCapacity)) {\n    if (IsSmallCapacity(capacity)) return;\n    std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty), Group::kWidth);\n    std::memset(ctrl + capacity, static_cast<int8_t>(ctrl_t::kEmpty),\n                Group::kWidth);\n    if (capacity == kTwoGroupCapacity) {\n      std::memset(ctrl + Group::kWidth, static_cast<int8_t>(ctrl_t::kEmpty),\n                  Group::kWidth);\n    }\n  } else {\n    std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),\n                capacity + 1 + NumClonedBytes());\n  }\n  ctrl[capacity] = ctrl_t::kSentinel;\n  SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity);\n}\n\n// Initializes control bytes for growing from capacity 1 to 3.\n// `orig_h2` is placed in the position `SooSlotIndex()`.\n// `new_h2` is placed in the position `new_offset`.\nABSL_ATTRIBUTE_ALWAYS_INLINE inline void InitializeThreeElementsControlBytes(\n    h2_t orig_h2, h2_t new_h2, size_t new_offset, ctrl_t* new_ctrl) {\n  static constexpr size_t kNewCapacity = NextCapacity(SooCapacity());\n  static_assert(kNewCapacity == 3);\n  static_assert(is_single_group(kNewCapacity));\n  static_assert(SooSlotIndex() == 1);\n  ABSL_SWISSTABLE_ASSERT(new_offset == 0 || new_offset == 2);\n\n  static constexpr uint64_t kEmptyXorSentinel =\n      static_cast<uint8_t>(ctrl_t::kEmpty) ^\n      static_cast<uint8_t>(ctrl_t::kSentinel);\n  static constexpr uint64_t kEmpty64 = static_cast<uint8_t>(ctrl_t::kEmpty);\n  static constexpr size_t kMirroredSooSlotIndex =\n      SooSlotIndex() + kNewCapacity + 1;\n  // The first 8 bytes, where SOO slot original and mirrored positions are\n  // replaced with 0.\n  // Result will look like: E0ESE0EE\n  static constexpr uint64_t kFirstCtrlBytesWithZeroes =\n      k8EmptyBytes ^ (kEmpty64 << (8 * SooSlotIndex())) ^\n      (kEmptyXorSentinel << (8 * kNewCapacity)) ^\n      (kEmpty64 << (8 * kMirroredSooSlotIndex));\n\n  const uint64_t soo_h2 = static_cast<uint64_t>(orig_h2);\n  const uint64_t new_h2_xor_empty =\n      static_cast<uint64_t>(new_h2 ^ static_cast<uint8_t>(ctrl_t::kEmpty));\n  // Fill the original and mirrored bytes for SOO slot.\n  // Result will look like:\n  // EHESEHEE\n  // Where H = soo_h2, E = kEmpty, S = kSentinel.\n  uint64_t first_ctrl_bytes =\n      ((soo_h2 << (8 * SooSlotIndex())) | kFirstCtrlBytesWithZeroes) |\n      (soo_h2 << (8 * kMirroredSooSlotIndex));\n  // Replace original and mirrored empty bytes for the new position.\n  // Result for new_offset 0 will look like:\n  // NHESNHEE\n  // Where H = soo_h2, N = H2(new_hash), E = kEmpty, S = kSentinel.\n  // Result for new_offset 2 will look like:\n  // EHNSEHNE\n  first_ctrl_bytes ^= (new_h2_xor_empty << (8 * new_offset));\n  size_t new_mirrored_offset = new_offset + kNewCapacity + 1;\n  first_ctrl_bytes ^= (new_h2_xor_empty << (8 * new_mirrored_offset));\n\n  // Fill last bytes with kEmpty.\n  std::memset(new_ctrl + kNewCapacity, static_cast<int8_t>(ctrl_t::kEmpty),\n              Group::kWidth);\n  // Overwrite the first 8 bytes with first_ctrl_bytes.\n  absl::little_endian::Store64(new_ctrl, first_ctrl_bytes);\n\n  // Example for group size 16:\n  // new_ctrl after 1st memset =      ???EEEEEEEEEEEEEEEE\n  // new_offset 0:\n  // new_ctrl after 2nd store  =      NHESNHEEEEEEEEEEEEE\n  // new_offset 2:\n  // new_ctrl after 2nd store  =      EHNSEHNEEEEEEEEEEEE\n\n  // Example for group size 8:\n  // new_ctrl after 1st memset =      ???EEEEEEEE\n  // new_offset 0:\n  // new_ctrl after 2nd store  =      NHESNHEEEEE\n  // new_offset 2:\n  // new_ctrl after 2nd store  =      EHNSEHNEEEE\n}\n\n}  // namespace\n\nvoid EraseMetaOnlySmall(CommonFields& c, bool soo_enabled, size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(c.is_small());\n  if (soo_enabled) {\n    c.set_empty_soo();\n    return;\n  }\n  c.decrement_size();\n  c.infoz().RecordErase();\n  SanitizerPoisonMemoryRegion(c.slot_array(), slot_size);\n}\n\nvoid EraseMetaOnlyLarge(CommonFields& c, const ctrl_t* ctrl, size_t slot_size) {\n  ABSL_SWISSTABLE_ASSERT(!c.is_small());\n  ABSL_SWISSTABLE_ASSERT(IsFull(*ctrl) && \"erasing a dangling iterator\");\n  c.decrement_size();\n  c.infoz().RecordErase();\n\n  size_t index = static_cast<size_t>(ctrl - c.control());\n\n  if (WasNeverFull(c, index)) {\n    SetCtrl(c, index, ctrl_t::kEmpty, slot_size);\n    c.growth_info().OverwriteFullAsEmpty();\n    return;\n  }\n\n  c.growth_info().OverwriteFullAsDeleted();\n  SetCtrlInLargeTable(c, index, ctrl_t::kDeleted, slot_size);\n}\n\nvoid ClearBackingArray(CommonFields& c,\n                       const PolicyFunctions& __restrict policy, void* alloc,\n                       bool reuse, bool soo_enabled) {\n  if (reuse) {\n    c.set_size_to_zero();\n    ABSL_SWISSTABLE_ASSERT(!soo_enabled || c.capacity() > SooCapacity());\n    ResetCtrl(c, policy.slot_size);\n    ResetGrowthLeft(c);\n    c.infoz().RecordStorageChanged(0, c.capacity());\n  } else {\n    // We need to record infoz before calling dealloc, which will unregister\n    // infoz.\n    c.infoz().RecordClearedReservation();\n    c.infoz().RecordStorageChanged(0, soo_enabled ? SooCapacity() : 0);\n    c.infoz().Unregister();\n    (*policy.dealloc)(alloc, c.capacity(), c.control(), policy.slot_size,\n                      policy.slot_align, c.has_infoz());\n    c = soo_enabled ? CommonFields{soo_tag_t{}} : CommonFields{non_soo_tag_t{}};\n  }\n}\n\nnamespace {\n\nenum class ResizeNonSooMode {\n  kGuaranteedEmpty,\n  kGuaranteedAllocated,\n};\n\n// Iterates over full slots in old table, finds new positions for them and\n// transfers the slots.\n// This function is used for reserving or rehashing non-empty tables.\n// This use case is rare so the function is type erased.\n// Returns the total probe length.\nsize_t FindNewPositionsAndTransferSlots(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    ctrl_t* old_ctrl, void* old_slots, size_t old_capacity) {\n  void* new_slots = common.slot_array();\n  const void* hash_fn = policy.hash_fn(common);\n  const size_t slot_size = policy.slot_size;\n  const size_t seed = common.seed().seed();\n\n  const auto insert_slot = [&](void* slot) {\n    size_t hash = policy.hash_slot(hash_fn, slot, seed);\n    FindInfo target;\n    if (common.is_small()) {\n      target = FindInfo{0, 0};\n    } else {\n      target = find_first_non_full(common, hash);\n      SetCtrl(common, target.offset, H2(hash), slot_size);\n    }\n    policy.transfer_n(&common, SlotAddress(new_slots, target.offset, slot_size),\n                      slot, 1);\n    return target.probe_length;\n  };\n  if (IsSmallCapacity(old_capacity)) {\n    if (common.size() == 1) insert_slot(old_slots);\n    return 0;\n  }\n  size_t total_probe_length = 0;\n  for (size_t i = 0; i < old_capacity; ++i) {\n    if (IsFull(old_ctrl[i])) {\n      total_probe_length += insert_slot(old_slots);\n    }\n    old_slots = NextSlot(old_slots, slot_size);\n  }\n  return total_probe_length;\n}\n\nvoid ReportGrowthToInfozImpl(CommonFields& common, HashtablezInfoHandle infoz,\n                             size_t hash, size_t total_probe_length,\n                             size_t distance_from_desired) {\n  ABSL_SWISSTABLE_ASSERT(infoz.IsSampled());\n  infoz.RecordStorageChanged(common.size() - 1, common.capacity());\n  infoz.RecordRehash(total_probe_length);\n  infoz.RecordInsertMiss(hash, distance_from_desired);\n  common.set_has_infoz();\n  // TODO(b/413062340): we could potentially store infoz in place of the\n  // control pointer for the capacity 1 case.\n  common.set_infoz(infoz);\n}\n\n// Specialization to avoid passing two 0s from hot function.\nABSL_ATTRIBUTE_NOINLINE void ReportSingleGroupTableGrowthToInfoz(\n    CommonFields& common, HashtablezInfoHandle infoz, size_t hash) {\n  ReportGrowthToInfozImpl(common, infoz, hash, /*total_probe_length=*/0,\n                          /*distance_from_desired=*/0);\n}\n\nABSL_ATTRIBUTE_NOINLINE void ReportGrowthToInfoz(CommonFields& common,\n                                                 HashtablezInfoHandle infoz,\n                                                 size_t hash,\n                                                 size_t total_probe_length,\n                                                 size_t distance_from_desired) {\n  ReportGrowthToInfozImpl(common, infoz, hash, total_probe_length,\n                          distance_from_desired);\n}\n\nABSL_ATTRIBUTE_NOINLINE void ReportResizeToInfoz(CommonFields& common,\n                                                 HashtablezInfoHandle infoz,\n                                                 size_t total_probe_length) {\n  ABSL_SWISSTABLE_ASSERT(infoz.IsSampled());\n  infoz.RecordStorageChanged(common.size(), common.capacity());\n  infoz.RecordRehash(total_probe_length);\n  common.set_has_infoz();\n  common.set_infoz(infoz);\n}\n\nstruct BackingArrayPtrs {\n  ctrl_t* ctrl;\n  void* slots;\n};\n\nBackingArrayPtrs AllocBackingArray(CommonFields& common,\n                                   const PolicyFunctions& __restrict policy,\n                                   size_t new_capacity, bool has_infoz,\n                                   void* alloc) {\n  RawHashSetLayout layout(new_capacity, policy.slot_size, policy.slot_align,\n                          has_infoz);\n  // Perform a direct call in the common case to allow for profile-guided\n  // heap optimization (PGHO) to understand which allocation function is used.\n  constexpr size_t kDefaultAlignment = BackingArrayAlignment(alignof(size_t));\n  char* mem = static_cast<char*>(\n      ABSL_PREDICT_TRUE(\n          policy.alloc ==\n          (&AllocateBackingArray<kDefaultAlignment, std::allocator<char>>))\n          ? AllocateBackingArray<kDefaultAlignment, std::allocator<char>>(\n                alloc, layout.alloc_size())\n          : policy.alloc(alloc, layout.alloc_size()));\n  const GenerationType old_generation = common.generation();\n  common.set_generation_ptr(\n      reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));\n  common.set_generation(NextGeneration(old_generation));\n\n  return {reinterpret_cast<ctrl_t*>(mem + layout.control_offset()),\n          mem + layout.slot_offset()};\n}\n\ntemplate <ResizeNonSooMode kMode>\nvoid ResizeNonSooImpl(CommonFields& common,\n                      const PolicyFunctions& __restrict policy,\n                      size_t new_capacity, HashtablezInfoHandle infoz) {\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));\n  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());\n\n  [[maybe_unused]] const size_t old_capacity = common.capacity();\n  [[maybe_unused]] ctrl_t* old_ctrl;\n  [[maybe_unused]] void* old_slots;\n  if constexpr (kMode == ResizeNonSooMode::kGuaranteedAllocated) {\n    old_ctrl = common.control();\n    old_slots = common.slot_array();\n  }\n\n  const size_t slot_size = policy.slot_size;\n  [[maybe_unused]] const size_t slot_align = policy.slot_align;\n  const bool has_infoz = infoz.IsSampled();\n  void* alloc = policy.get_char_alloc(common);\n\n  common.set_capacity(new_capacity);\n  const auto [new_ctrl, new_slots] =\n      AllocBackingArray(common, policy, new_capacity, has_infoz, alloc);\n  common.set_control(new_ctrl);\n  common.set_slots(new_slots);\n  common.generate_new_seed(has_infoz);\n\n  size_t total_probe_length = 0;\n  ResetCtrl(common, slot_size);\n  ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedEmpty ||\n                         old_capacity == policy.soo_capacity());\n  ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedAllocated ||\n                         old_capacity > 0);\n  if constexpr (kMode == ResizeNonSooMode::kGuaranteedAllocated) {\n    total_probe_length = FindNewPositionsAndTransferSlots(\n        common, policy, old_ctrl, old_slots, old_capacity);\n    (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,\n                      has_infoz);\n    ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,\n                    common.size());\n  } else {\n    GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(\n        CapacityToGrowth(new_capacity));\n  }\n\n  if (ABSL_PREDICT_FALSE(has_infoz)) {\n    ReportResizeToInfoz(common, infoz, total_probe_length);\n  }\n}\n\nvoid ResizeEmptyNonAllocatedTableImpl(CommonFields& common,\n                                      const PolicyFunctions& __restrict policy,\n                                      size_t new_capacity, bool force_infoz) {\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));\n  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());\n  ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_enabled);\n  ABSL_SWISSTABLE_ASSERT(common.capacity() <= policy.soo_capacity());\n  ABSL_SWISSTABLE_ASSERT(common.empty());\n  const size_t slot_size = policy.slot_size;\n  HashtablezInfoHandle infoz;\n  const bool should_sample =\n      policy.is_hashtablez_eligible && (force_infoz || ShouldSampleNextTable());\n  if (ABSL_PREDICT_FALSE(should_sample)) {\n    infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,\n                            policy.soo_capacity());\n  }\n  ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedEmpty>(common, policy,\n                                                       new_capacity, infoz);\n}\n\n// If the table was SOO, initializes new control bytes and transfers slot.\n// After transferring the slot, sets control and slots in CommonFields.\n// It is rare to resize an SOO table with one element to a large size.\n// Requires: `c` contains SOO data.\nvoid InsertOldSooSlotAndInitializeControlBytes(\n    CommonFields& c, const PolicyFunctions& __restrict policy, ctrl_t* new_ctrl,\n    void* new_slots, bool has_infoz) {\n  ABSL_SWISSTABLE_ASSERT(c.size() == policy.soo_capacity());\n  ABSL_SWISSTABLE_ASSERT(policy.soo_enabled);\n  size_t new_capacity = c.capacity();\n\n  c.generate_new_seed(has_infoz);\n\n  const size_t soo_slot_hash =\n      policy.hash_slot(policy.hash_fn(c), c.soo_data(), c.seed().seed());\n  size_t offset = probe(new_capacity, soo_slot_hash).offset();\n  offset = offset == new_capacity ? 0 : offset;\n  SanitizerPoisonMemoryRegion(new_slots, policy.slot_size * new_capacity);\n  void* target_slot = SlotAddress(new_slots, offset, policy.slot_size);\n  SanitizerUnpoisonMemoryRegion(target_slot, policy.slot_size);\n  policy.transfer_n(&c, target_slot, c.soo_data(), 1);\n  c.set_control(new_ctrl);\n  c.set_slots(new_slots);\n  ResetCtrl(c, policy.slot_size);\n  SetCtrl(c, offset, H2(soo_slot_hash), policy.slot_size);\n}\n\nenum class ResizeFullSooTableSamplingMode {\n  kNoSampling,\n  // Force sampling. If the table was still not sampled, do not resize.\n  kForceSampleNoResizeIfUnsampled,\n};\n\nvoid AssertSoo([[maybe_unused]] CommonFields& common,\n               [[maybe_unused]] const PolicyFunctions& policy) {\n  ABSL_SWISSTABLE_ASSERT(policy.soo_enabled);\n  ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity());\n}\nvoid AssertFullSoo([[maybe_unused]] CommonFields& common,\n                   [[maybe_unused]] const PolicyFunctions& policy) {\n  AssertSoo(common, policy);\n  ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity());\n}\n\nvoid ResizeFullSooTable(CommonFields& common,\n                        const PolicyFunctions& __restrict policy,\n                        size_t new_capacity,\n                        ResizeFullSooTableSamplingMode sampling_mode) {\n  AssertFullSoo(common, policy);\n  const size_t slot_size = policy.slot_size;\n  void* alloc = policy.get_char_alloc(common);\n\n  HashtablezInfoHandle infoz;\n  bool has_infoz = false;\n  if (sampling_mode ==\n      ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled) {\n    if (ABSL_PREDICT_FALSE(policy.is_hashtablez_eligible)) {\n      infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,\n                              policy.soo_capacity());\n    }\n\n    if (!infoz.IsSampled()) return;\n    has_infoz = true;\n  }\n\n  common.set_capacity(new_capacity);\n\n  // We do not set control and slots in CommonFields yet to avoid overriding\n  // SOO data.\n  const auto [new_ctrl, new_slots] =\n      AllocBackingArray(common, policy, new_capacity, has_infoz, alloc);\n\n  InsertOldSooSlotAndInitializeControlBytes(common, policy, new_ctrl, new_slots,\n                                            has_infoz);\n  ResetGrowthLeft(common);\n  if (has_infoz) {\n    common.set_has_infoz();\n    common.set_infoz(infoz);\n    infoz.RecordStorageChanged(common.size(), new_capacity);\n  }\n}\n\nvoid GrowIntoSingleGroupShuffleControlBytes(ctrl_t* __restrict old_ctrl,\n                                            size_t old_capacity,\n                                            ctrl_t* __restrict new_ctrl,\n                                            size_t new_capacity) {\n  ABSL_SWISSTABLE_ASSERT(is_single_group(new_capacity));\n  constexpr size_t kHalfWidth = Group::kWidth / 2;\n  ABSL_ASSUME(old_capacity < kHalfWidth);\n  ABSL_ASSUME(old_capacity > 0);\n  static_assert(Group::kWidth == 8 || Group::kWidth == 16,\n                \"Group size is not supported.\");\n\n  // NOTE: operations are done with compile time known size = 8.\n  // Compiler optimizes that into single ASM operation.\n\n  // Load the bytes from old_capacity. This contains\n  // - the sentinel byte\n  // - all the old control bytes\n  // - the rest is filled with kEmpty bytes\n  // Example:\n  // old_ctrl =     012S012EEEEEEEEE...\n  // copied_bytes = S012EEEE\n  uint64_t copied_bytes = absl::little_endian::Load64(old_ctrl + old_capacity);\n\n  // We change the sentinel byte to kEmpty before storing to both the start of\n  // the new_ctrl, and past the end of the new_ctrl later for the new cloned\n  // bytes. Note that this is faster than setting the sentinel byte to kEmpty\n  // after the copy directly in new_ctrl because we are limited on store\n  // bandwidth.\n  static constexpr uint64_t kEmptyXorSentinel =\n      static_cast<uint8_t>(ctrl_t::kEmpty) ^\n      static_cast<uint8_t>(ctrl_t::kSentinel);\n\n  // Replace the first byte kSentinel with kEmpty.\n  // Resulting bytes will be shifted by one byte old control blocks.\n  // Example:\n  // old_ctrl = 012S012EEEEEEEEE...\n  // before =   S012EEEE\n  // after  =   E012EEEE\n  copied_bytes ^= kEmptyXorSentinel;\n\n  if (Group::kWidth == 8) {\n    // With group size 8, we can grow with two write operations.\n    ABSL_SWISSTABLE_ASSERT(old_capacity < 8 &&\n                           \"old_capacity is too large for group size 8\");\n    absl::little_endian::Store64(new_ctrl, copied_bytes);\n\n    static constexpr uint64_t kSentinal64 =\n        static_cast<uint8_t>(ctrl_t::kSentinel);\n\n    // Prepend kSentinel byte to the beginning of copied_bytes.\n    // We have maximum 3 non-empty bytes at the beginning of copied_bytes for\n    // group size 8.\n    // Example:\n    // old_ctrl = 012S012EEEE\n    // before =   E012EEEE\n    // after  =   SE012EEE\n    copied_bytes = (copied_bytes << 8) ^ kSentinal64;\n    absl::little_endian::Store64(new_ctrl + new_capacity, copied_bytes);\n    // Example for capacity 3:\n    // old_ctrl = 012S012EEEE\n    // After the first store:\n    //           >!\n    // new_ctrl = E012EEEE???????\n    // After the second store:\n    //                  >!\n    // new_ctrl = E012EEESE012EEE\n    return;\n  }\n\n  ABSL_SWISSTABLE_ASSERT(Group::kWidth == 16);  // NOLINT(misc-static-assert)\n\n  // Fill the second half of the main control bytes with kEmpty.\n  // For small capacity that may write into mirrored control bytes.\n  // It is fine as we will overwrite all the bytes later.\n  std::memset(new_ctrl + kHalfWidth, static_cast<int8_t>(ctrl_t::kEmpty),\n              kHalfWidth);\n  // Fill the second half of the mirrored control bytes with kEmpty.\n  std::memset(new_ctrl + new_capacity + kHalfWidth,\n              static_cast<int8_t>(ctrl_t::kEmpty), kHalfWidth);\n  // Copy the first half of the non-mirrored control bytes.\n  absl::little_endian::Store64(new_ctrl, copied_bytes);\n  new_ctrl[new_capacity] = ctrl_t::kSentinel;\n  // Copy the first half of the mirrored control bytes.\n  absl::little_endian::Store64(new_ctrl + new_capacity + 1, copied_bytes);\n\n  // Example for growth capacity 1->3:\n  // old_ctrl =                  0S0EEEEEEEEEEEEEE\n  // new_ctrl at the end =       E0ESE0EEEEEEEEEEEEE\n  //                                    >!\n  // new_ctrl after 1st memset = ????????EEEEEEEE???\n  //                                       >!\n  // new_ctrl after 2nd memset = ????????EEEEEEEEEEE\n  //                            >!\n  // new_ctrl after 1st store =  E0EEEEEEEEEEEEEEEEE\n  // new_ctrl after kSentinel =  E0ESEEEEEEEEEEEEEEE\n  //                                >!\n  // new_ctrl after 2nd store =  E0ESE0EEEEEEEEEEEEE\n\n  // Example for growth capacity 3->7:\n  // old_ctrl =                  012S012EEEEEEEEEEEE\n  // new_ctrl at the end =       E012EEESE012EEEEEEEEEEE\n  //                                    >!\n  // new_ctrl after 1st memset = ????????EEEEEEEE???????\n  //                                           >!\n  // new_ctrl after 2nd memset = ????????EEEEEEEEEEEEEEE\n  //                            >!\n  // new_ctrl after 1st store =  E012EEEEEEEEEEEEEEEEEEE\n  // new_ctrl after kSentinel =  E012EEESEEEEEEEEEEEEEEE\n  //                                >!\n  // new_ctrl after 2nd store =  E012EEESE012EEEEEEEEEEE\n\n  // Example for growth capacity 7->15:\n  // old_ctrl =                  0123456S0123456EEEEEEEE\n  // new_ctrl at the end =       E0123456EEEEEEESE0123456EEEEEEE\n  //                                    >!\n  // new_ctrl after 1st memset = ????????EEEEEEEE???????????????\n  //                                                   >!\n  // new_ctrl after 2nd memset = ????????EEEEEEEE???????EEEEEEEE\n  //                            >!\n  // new_ctrl after 1st store =  E0123456EEEEEEEE???????EEEEEEEE\n  // new_ctrl after kSentinel =  E0123456EEEEEEES???????EEEEEEEE\n  //                                            >!\n  // new_ctrl after 2nd store =  E0123456EEEEEEESE0123456EEEEEEE\n}\n\n// Size of the buffer we allocate on stack for storing probed elements in\n// GrowToNextCapacity algorithm.\nconstexpr size_t kProbedElementsBufferSize = 512;\n\n// Decodes information about probed elements from contiguous memory.\n// Finds new position for each element and transfers it to the new slots.\n// Returns the total probe length.\ntemplate <typename ProbedItem>\nABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertImpl(\n    CommonFields& c, const PolicyFunctions& __restrict policy,\n    const ProbedItem* start, const ProbedItem* end, void* old_slots) {\n  const size_t new_capacity = c.capacity();\n\n  void* new_slots = c.slot_array();\n  ctrl_t* new_ctrl = c.control();\n  size_t total_probe_length = 0;\n\n  const size_t slot_size = policy.slot_size;\n  auto transfer_n = policy.transfer_n;\n\n  for (; start < end; ++start) {\n    const FindInfo target = find_first_non_full_from_h1(\n        new_ctrl, static_cast<size_t>(start->h1), new_capacity);\n    total_probe_length += target.probe_length;\n    const size_t old_index = static_cast<size_t>(start->source_offset);\n    const size_t new_i = target.offset;\n    ABSL_SWISSTABLE_ASSERT(old_index < new_capacity / 2);\n    ABSL_SWISSTABLE_ASSERT(new_i < new_capacity);\n    ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[new_i]));\n    void* src_slot = SlotAddress(old_slots, old_index, slot_size);\n    void* dst_slot = SlotAddress(new_slots, new_i, slot_size);\n    SanitizerUnpoisonMemoryRegion(dst_slot, slot_size);\n    transfer_n(&c, dst_slot, src_slot, 1);\n    SetCtrlInLargeTable(c, new_i, static_cast<h2_t>(start->h2), slot_size);\n  }\n  return total_probe_length;\n}\n\n// Sentinel value for the start of marked elements.\n// Signals that there are no marked elements.\nconstexpr size_t kNoMarkedElementsSentinel = ~size_t{};\n\n// Process probed elements that did not fit into available buffers.\n// We marked them in control bytes as kSentinel.\n// Hash recomputation and full probing is done here.\n// This use case should be extremely rare.\nABSL_ATTRIBUTE_NOINLINE size_t ProcessProbedMarkedElements(\n    CommonFields& c, const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl,\n    void* old_slots, size_t start) {\n  size_t old_capacity = PreviousCapacity(c.capacity());\n  const size_t slot_size = policy.slot_size;\n  void* new_slots = c.slot_array();\n  size_t total_probe_length = 0;\n  const void* hash_fn = policy.hash_fn(c);\n  auto hash_slot = policy.hash_slot;\n  auto transfer_n = policy.transfer_n;\n  const size_t seed = c.seed().seed();\n  for (size_t old_index = start; old_index < old_capacity; ++old_index) {\n    if (old_ctrl[old_index] != ctrl_t::kSentinel) {\n      continue;\n    }\n    void* src_slot = SlotAddress(old_slots, old_index, slot_size);\n    const size_t hash = hash_slot(hash_fn, src_slot, seed);\n    const FindInfo target = find_first_non_full(c, hash);\n    total_probe_length += target.probe_length;\n    const size_t new_i = target.offset;\n    void* dst_slot = SlotAddress(new_slots, new_i, slot_size);\n    SetCtrlInLargeTable(c, new_i, H2(hash), slot_size);\n    transfer_n(&c, dst_slot, src_slot, 1);\n  }\n  return total_probe_length;\n}\n\n// The largest old capacity for which it is guaranteed that all probed elements\n// fit in ProbedItemEncoder's local buffer.\n// For such tables, `encode_probed_element` is trivial.\nconstexpr size_t kMaxLocalBufferOldCapacity =\n    kProbedElementsBufferSize / sizeof(ProbedItem4Bytes) - 1;\nstatic_assert(IsValidCapacity(kMaxLocalBufferOldCapacity));\nconstexpr size_t kMaxLocalBufferNewCapacity =\n    NextCapacity(kMaxLocalBufferOldCapacity);\nstatic_assert(kMaxLocalBufferNewCapacity <= ProbedItem4Bytes::kMaxNewCapacity);\nstatic_assert(NextCapacity(kMaxLocalBufferNewCapacity) <=\n              ProbedItem4Bytes::kMaxNewCapacity);\n\n// Initializes mirrored control bytes after\n// transfer_unprobed_elements_to_next_capacity.\nvoid InitializeMirroredControlBytes(ctrl_t* new_ctrl, size_t new_capacity) {\n  std::memcpy(new_ctrl + new_capacity,\n              // We own GrowthInfo just before control bytes. So it is ok\n              // to read one byte from it.\n              new_ctrl - 1, Group::kWidth);\n  new_ctrl[new_capacity] = ctrl_t::kSentinel;\n}\n\n// Encodes probed elements into available memory.\n// At first, a local (on stack) buffer is used. The size of the buffer is\n// kProbedElementsBufferSize bytes.\n// When the local buffer is full, we switch to `control_` buffer. We are allowed\n// to overwrite `control_` buffer till the `source_offset` byte. In case we have\n// no space in `control_` buffer, we fallback to a naive algorithm for all the\n// rest of the probed elements. We mark elements as kSentinel in control bytes\n// and later process them fully. See ProcessMarkedElements for details. It\n// should be extremely rare.\ntemplate <typename ProbedItemType,\n          // If true, we only use the local buffer and never switch to the\n          // control buffer.\n          bool kGuaranteedFitToBuffer = false>\nclass ProbedItemEncoder {\n public:\n  using ProbedItem = ProbedItemType;\n  explicit ProbedItemEncoder(ctrl_t* control) : control_(control) {}\n\n  // Encode item into the best available location.\n  void EncodeItem(ProbedItem item) {\n    if (ABSL_PREDICT_FALSE(!kGuaranteedFitToBuffer && pos_ >= end_)) {\n      return ProcessEncodeWithOverflow(item);\n    }\n    ABSL_SWISSTABLE_ASSERT(pos_ < end_);\n    *pos_ = item;\n    ++pos_;\n  }\n\n  // Decodes information about probed elements from all available sources.\n  // Finds new position for each element and transfers it to the new slots.\n  // Returns the total probe length.\n  size_t DecodeAndInsertToTable(CommonFields& common,\n                                const PolicyFunctions& __restrict policy,\n                                void* old_slots) const {\n    if (pos_ == buffer_) {\n      return 0;\n    }\n    if constexpr (kGuaranteedFitToBuffer) {\n      return DecodeAndInsertImpl(common, policy, buffer_, pos_, old_slots);\n    }\n    size_t total_probe_length = DecodeAndInsertImpl(\n        common, policy, buffer_,\n        local_buffer_full_ ? buffer_ + kBufferSize : pos_, old_slots);\n    if (!local_buffer_full_) {\n      return total_probe_length;\n    }\n    total_probe_length +=\n        DecodeAndInsertToTableOverflow(common, policy, old_slots);\n    return total_probe_length;\n  }\n\n private:\n  static ProbedItem* AlignToNextItem(void* ptr) {\n    return reinterpret_cast<ProbedItem*>(AlignUpTo(\n        reinterpret_cast<uintptr_t>(ptr), alignof(ProbedItem)));\n  }\n\n  ProbedItem* OverflowBufferStart() const {\n    // We reuse GrowthInfo memory as well.\n    return AlignToNextItem(control_ - ControlOffset(/*has_infoz=*/false));\n  }\n\n  // Encodes item when previously allocated buffer is full.\n  // At first that happens when local buffer is full.\n  // We switch from the local buffer to the control buffer.\n  // Every time this function is called, the available buffer is extended till\n  // `item.source_offset` byte in the control buffer.\n  // After the buffer is extended, this function wouldn't be called till the\n  // buffer is exhausted.\n  //\n  // If there's no space in the control buffer, we fallback to naive algorithm\n  // and mark probed elements as kSentinel in the control buffer. In this case,\n  // we will call this function for every subsequent probed element.\n  ABSL_ATTRIBUTE_NOINLINE void ProcessEncodeWithOverflow(ProbedItem item) {\n    if (!local_buffer_full_) {\n      local_buffer_full_ = true;\n      pos_ = OverflowBufferStart();\n    }\n    const size_t source_offset = static_cast<size_t>(item.source_offset);\n    // We are in fallback mode so we can't reuse control buffer anymore.\n    // Probed elements are marked as kSentinel in the control buffer.\n    if (ABSL_PREDICT_FALSE(marked_elements_starting_position_ !=\n                           kNoMarkedElementsSentinel)) {\n      control_[source_offset] = ctrl_t::kSentinel;\n      return;\n    }\n    // Refresh the end pointer to the new available position.\n    // Invariant: if pos < end, then we have at least sizeof(ProbedItem) bytes\n    // to write.\n    end_ = control_ + source_offset + 1 - sizeof(ProbedItem);\n    if (ABSL_PREDICT_TRUE(pos_ < end_)) {\n      *pos_ = item;\n      ++pos_;\n      return;\n    }\n    control_[source_offset] = ctrl_t::kSentinel;\n    marked_elements_starting_position_ = source_offset;\n    // Now we will always fall down to `ProcessEncodeWithOverflow`.\n    ABSL_SWISSTABLE_ASSERT(pos_ >= end_);\n  }\n\n  // Decodes information about probed elements from control buffer and processes\n  // marked elements.\n  // Finds new position for each element and transfers it to the new slots.\n  // Returns the total probe length.\n  ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertToTableOverflow(\n      CommonFields& common, const PolicyFunctions& __restrict policy,\n      void* old_slots) const {\n    ABSL_SWISSTABLE_ASSERT(local_buffer_full_ &&\n                           \"must not be called when local buffer is not full\");\n    size_t total_probe_length = DecodeAndInsertImpl(\n        common, policy, OverflowBufferStart(), pos_, old_slots);\n    if (ABSL_PREDICT_TRUE(marked_elements_starting_position_ ==\n                          kNoMarkedElementsSentinel)) {\n      return total_probe_length;\n    }\n    total_probe_length +=\n        ProcessProbedMarkedElements(common, policy, control_, old_slots,\n                                    marked_elements_starting_position_);\n    return total_probe_length;\n  }\n\n  static constexpr size_t kBufferSize =\n      kProbedElementsBufferSize / sizeof(ProbedItem);\n  ProbedItem buffer_[kBufferSize];\n  // If local_buffer_full_ is false, then pos_/end_ are in the local buffer,\n  // otherwise, they're in the overflow buffer.\n  ProbedItem* pos_ = buffer_;\n  const void* end_ = buffer_ + kBufferSize;\n  ctrl_t* const control_;\n  size_t marked_elements_starting_position_ = kNoMarkedElementsSentinel;\n  bool local_buffer_full_ = false;\n};\n\n// Grows to next capacity with specified encoder type.\n// Encoder is used to store probed elements that are processed later.\n// Different encoder is used depending on the capacity of the table.\n// Returns total probe length.\ntemplate <typename Encoder>\nsize_t GrowToNextCapacity(CommonFields& common,\n                          const PolicyFunctions& __restrict policy,\n                          ctrl_t* old_ctrl, void* old_slots) {\n  using ProbedItem = typename Encoder::ProbedItem;\n  ABSL_SWISSTABLE_ASSERT(common.capacity() <= ProbedItem::kMaxNewCapacity);\n  Encoder encoder(old_ctrl);\n  policy.transfer_unprobed_elements_to_next_capacity(\n      common, old_ctrl, old_slots, &encoder,\n      [](void* probed_storage, h2_t h2, size_t source_offset, size_t h1) {\n        auto encoder_ptr = static_cast<Encoder*>(probed_storage);\n        encoder_ptr->EncodeItem(ProbedItem(h2, source_offset, h1));\n      });\n  InitializeMirroredControlBytes(common.control(), common.capacity());\n  return encoder.DecodeAndInsertToTable(common, policy, old_slots);\n}\n\n// Grows to next capacity for relatively small tables so that even if all\n// elements are probed, we don't need to overflow the local buffer.\n// Returns total probe length.\nsize_t GrowToNextCapacityThatFitsInLocalBuffer(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    ctrl_t* old_ctrl, void* old_slots) {\n  ABSL_SWISSTABLE_ASSERT(common.capacity() <= kMaxLocalBufferNewCapacity);\n  return GrowToNextCapacity<\n      ProbedItemEncoder<ProbedItem4Bytes, /*kGuaranteedFitToBuffer=*/true>>(\n      common, policy, old_ctrl, old_slots);\n}\n\n// Grows to next capacity with different encodings. Returns total probe length.\n// These functions are useful to simplify profile analysis.\nsize_t GrowToNextCapacity4BytesEncoder(CommonFields& common,\n                                       const PolicyFunctions& __restrict policy,\n                                       ctrl_t* old_ctrl, void* old_slots) {\n  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem4Bytes>>(\n      common, policy, old_ctrl, old_slots);\n}\nsize_t GrowToNextCapacity8BytesEncoder(CommonFields& common,\n                                       const PolicyFunctions& __restrict policy,\n                                       ctrl_t* old_ctrl, void* old_slots) {\n  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem8Bytes>>(\n      common, policy, old_ctrl, old_slots);\n}\nsize_t GrowToNextCapacity16BytesEncoder(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    ctrl_t* old_ctrl, void* old_slots) {\n  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem16Bytes>>(\n      common, policy, old_ctrl, old_slots);\n}\n\n// Grows to next capacity for tables with relatively large capacity so that we\n// can't guarantee that all probed elements fit in the local buffer. Returns\n// total probe length.\nsize_t GrowToNextCapacityOverflowLocalBuffer(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    ctrl_t* old_ctrl, void* old_slots) {\n  const size_t new_capacity = common.capacity();\n  if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem4Bytes::kMaxNewCapacity)) {\n    return GrowToNextCapacity4BytesEncoder(common, policy, old_ctrl, old_slots);\n  }\n  if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem8Bytes::kMaxNewCapacity)) {\n    return GrowToNextCapacity8BytesEncoder(common, policy, old_ctrl, old_slots);\n  }\n  // 16 bytes encoding supports the maximum swisstable capacity.\n  return GrowToNextCapacity16BytesEncoder(common, policy, old_ctrl, old_slots);\n}\n\n// Dispatches to the appropriate `GrowToNextCapacity*` function based on the\n// capacity of the table. Returns total probe length.\nABSL_ATTRIBUTE_NOINLINE\nsize_t GrowToNextCapacityDispatch(CommonFields& common,\n                                  const PolicyFunctions& __restrict policy,\n                                  ctrl_t* old_ctrl, void* old_slots) {\n  const size_t new_capacity = common.capacity();\n  if (ABSL_PREDICT_TRUE(new_capacity <= kMaxLocalBufferNewCapacity)) {\n    return GrowToNextCapacityThatFitsInLocalBuffer(common, policy, old_ctrl,\n                                                   old_slots);\n  } else {\n    return GrowToNextCapacityOverflowLocalBuffer(common, policy, old_ctrl,\n                                                 old_slots);\n  }\n}\n\nvoid IncrementSmallSizeNonSoo(CommonFields& common,\n                              const PolicyFunctions& __restrict policy) {\n  ABSL_SWISSTABLE_ASSERT(common.is_small());\n  common.increment_size();\n  SanitizerUnpoisonMemoryRegion(common.slot_array(), policy.slot_size);\n}\n\nvoid IncrementSmallSize(CommonFields& common,\n                        const PolicyFunctions& __restrict policy) {\n  ABSL_SWISSTABLE_ASSERT(common.is_small());\n  if (policy.soo_enabled) {\n    common.set_full_soo();\n  } else {\n    IncrementSmallSizeNonSoo(common, policy);\n  }\n}\n\nstd::pair<ctrl_t*, void*> Grow1To3AndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    absl::FunctionRef<size_t(size_t)> get_hash) {\n  // TODO(b/413062340): Refactor to reuse more code with\n  // GrowSooTableToNextCapacityAndPrepareInsert.\n  ABSL_SWISSTABLE_ASSERT(common.capacity() == 1);\n  ABSL_SWISSTABLE_ASSERT(!common.empty());\n  ABSL_SWISSTABLE_ASSERT(!policy.soo_enabled);\n  constexpr size_t kOldCapacity = 1;\n  constexpr size_t kNewCapacity = NextCapacity(kOldCapacity);\n  ctrl_t* old_ctrl = common.control();\n  void* old_slots = common.slot_array();\n\n  const size_t slot_size = policy.slot_size;\n  const size_t slot_align = policy.slot_align;\n  void* alloc = policy.get_char_alloc(common);\n  HashtablezInfoHandle infoz = common.infoz();\n  const bool has_infoz = infoz.IsSampled();\n  common.set_capacity(kNewCapacity);\n\n  const auto [new_ctrl, new_slots] =\n      AllocBackingArray(common, policy, kNewCapacity, has_infoz, alloc);\n  common.set_control(new_ctrl);\n  common.set_slots(new_slots);\n  SanitizerPoisonMemoryRegion(new_slots, kNewCapacity * slot_size);\n\n  if (ABSL_PREDICT_TRUE(!has_infoz)) {\n    // When we're sampled, we already have a seed.\n    common.generate_new_seed(/*has_infoz=*/false);\n  }\n  const size_t new_hash = get_hash(common.seed().seed());\n  h2_t new_h2 = H2(new_hash);\n  size_t orig_hash =\n      policy.hash_slot(policy.hash_fn(common), old_slots, common.seed().seed());\n  size_t offset = Resize1To3NewOffset(new_hash, common.seed());\n  InitializeThreeElementsControlBytes(H2(orig_hash), new_h2, offset, new_ctrl);\n\n  void* old_element_target = NextSlot(new_slots, slot_size);\n  SanitizerUnpoisonMemoryRegion(old_element_target, slot_size);\n  policy.transfer_n(&common, old_element_target, old_slots, 1);\n\n  void* new_element_target_slot = SlotAddress(new_slots, offset, slot_size);\n  SanitizerUnpoisonMemoryRegion(new_element_target_slot, slot_size);\n\n  policy.dealloc(alloc, kOldCapacity, old_ctrl, slot_size, slot_align,\n                 has_infoz);\n  PrepareInsertCommon(common);\n  ABSL_SWISSTABLE_ASSERT(common.size() == 2);\n  GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(kNewCapacity - 2);\n\n  if (ABSL_PREDICT_FALSE(has_infoz)) {\n    ReportSingleGroupTableGrowthToInfoz(common, infoz, new_hash);\n  }\n  return {new_ctrl + offset, new_element_target_slot};\n}\n\n// Grows to next capacity and prepares insert for the given new_hash.\n// Returns the offset of the new element.\nsize_t GrowToNextCapacityAndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t new_hash) {\n  ABSL_SWISSTABLE_ASSERT(common.growth_left() == 0);\n  const size_t old_capacity = common.capacity();\n  ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity());\n  ABSL_SWISSTABLE_ASSERT(!IsSmallCapacity(old_capacity));\n\n  const size_t new_capacity = NextCapacity(old_capacity);\n  ctrl_t* old_ctrl = common.control();\n  void* old_slots = common.slot_array();\n\n  common.set_capacity(new_capacity);\n  const size_t slot_size = policy.slot_size;\n  const size_t slot_align = policy.slot_align;\n  void* alloc = policy.get_char_alloc(common);\n  HashtablezInfoHandle infoz = common.infoz();\n  const bool has_infoz = infoz.IsSampled();\n\n  const auto [new_ctrl, new_slots] =\n      AllocBackingArray(common, policy, new_capacity, has_infoz, alloc);\n  common.set_control(new_ctrl);\n  common.set_slots(new_slots);\n  SanitizerPoisonMemoryRegion(new_slots, new_capacity * slot_size);\n\n  h2_t new_h2 = H2(new_hash);\n  size_t total_probe_length = 0;\n  FindInfo find_info;\n  if (ABSL_PREDICT_TRUE(is_single_group(new_capacity))) {\n    size_t offset;\n    GrowIntoSingleGroupShuffleControlBytes(old_ctrl, old_capacity, new_ctrl,\n                                           new_capacity);\n    // We put the new element either at the beginning or at the end of the\n    // table with approximately equal probability.\n    offset =\n        SingleGroupTableH1(new_hash, common.seed()) & 1 ? 0 : new_capacity - 1;\n\n    ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[offset]));\n    SetCtrlInSingleGroupTable(common, offset, new_h2, policy.slot_size);\n    find_info = FindInfo{offset, 0};\n    // Single group tables have all slots full on resize. So we can transfer\n    // all slots without checking the control bytes.\n    ABSL_SWISSTABLE_ASSERT(common.size() == old_capacity);\n    void* target = NextSlot(new_slots, slot_size);\n    SanitizerUnpoisonMemoryRegion(target, old_capacity * slot_size);\n    policy.transfer_n(&common, target, old_slots, old_capacity);\n  } else {\n    total_probe_length =\n        GrowToNextCapacityDispatch(common, policy, old_ctrl, old_slots);\n    find_info = find_first_non_full(common, new_hash);\n    SetCtrlInLargeTable(common, find_info.offset, new_h2, policy.slot_size);\n  }\n  ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity());\n  (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,\n                    has_infoz);\n  PrepareInsertCommon(common);\n  ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,\n                  common.size());\n\n  if (ABSL_PREDICT_FALSE(has_infoz)) {\n    ReportGrowthToInfoz(common, infoz, new_hash, total_probe_length,\n                        find_info.probe_length);\n  }\n  return find_info.offset;\n}\n\n}  // namespace\n\nstd::pair<ctrl_t*, void*> PrepareInsertSmallNonSoo(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    absl::FunctionRef<size_t(size_t)> get_hash) {\n  ABSL_SWISSTABLE_ASSERT(common.is_small());\n  ABSL_SWISSTABLE_ASSERT(!policy.soo_enabled);\n  if (common.capacity() == 1) {\n    if (common.empty()) {\n      IncrementSmallSizeNonSoo(common, policy);\n      if (common.has_infoz()) {\n        common.infoz().RecordInsertMiss(get_hash(common.seed().seed()),\n                                        /*distance_from_desired=*/0);\n      }\n      return {SooControl(), common.slot_array()};\n    } else {\n      return Grow1To3AndPrepareInsert(common, policy, get_hash);\n    }\n  }\n\n  // Growing from 0 to 1 capacity.\n  ABSL_SWISSTABLE_ASSERT(common.capacity() == 0);\n  constexpr size_t kNewCapacity = 1;\n\n  common.set_capacity(kNewCapacity);\n  HashtablezInfoHandle infoz;\n  const bool should_sample =\n      policy.is_hashtablez_eligible && ShouldSampleNextTable();\n  if (ABSL_PREDICT_FALSE(should_sample)) {\n    infoz = ForcedTrySample(policy.slot_size, policy.key_size,\n                            policy.value_size, policy.soo_capacity());\n  }\n  const bool has_infoz = infoz.IsSampled();\n  void* alloc = policy.get_char_alloc(common);\n\n  const auto [new_ctrl, new_slots] =\n      AllocBackingArray(common, policy, kNewCapacity, has_infoz, alloc);\n  common.set_control(new_ctrl);\n  common.set_slots(new_slots);\n\n  static_assert(NextCapacity(0) == 1);\n  PrepareInsertCommon(common);\n\n  if (ABSL_PREDICT_FALSE(has_infoz)) {\n    common.generate_new_seed(/*has_infoz=*/true);\n    ReportSingleGroupTableGrowthToInfoz(common, infoz,\n                                        get_hash(common.seed().seed()));\n  }\n  return {SooControl(), new_slots};\n}\n\nnamespace {\n\n// Called whenever the table needs to vacate empty slots either by removing\n// tombstones via rehash or growth to next capacity.\nABSL_ATTRIBUTE_NOINLINE\nsize_t RehashOrGrowToNextCapacityAndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t new_hash) {\n  const size_t cap = common.capacity();\n  ABSL_ASSUME(cap > 0);\n  if (cap > Group::kWidth &&\n      // Do these calculations in 64-bit to avoid overflow.\n      common.size() * uint64_t{32} <= cap * uint64_t{25}) {\n    // Squash DELETED without growing if there is enough capacity.\n    //\n    // Rehash in place if the current size is <= 25/32 of capacity.\n    // Rationale for such a high factor: 1) DropDeletesWithoutResize() is\n    // faster than resize, and 2) it takes quite a bit of work to add\n    // tombstones.  In the worst case, seems to take approximately 4\n    // insert/erase pairs to create a single tombstone and so if we are\n    // rehashing because of tombstones, we can afford to rehash-in-place as\n    // long as we are reclaiming at least 1/8 the capacity without doing more\n    // than 2X the work.  (Where \"work\" is defined to be size() for rehashing\n    // or rehashing in place, and 1 for an insert or erase.)  But rehashing in\n    // place is faster per operation than inserting or even doubling the size\n    // of the table, so we actually afford to reclaim even less space from a\n    // resize-in-place.  The decision is to rehash in place if we can reclaim\n    // at about 1/8th of the usable capacity (specifically 3/28 of the\n    // capacity) which means that the total cost of rehashing will be a small\n    // fraction of the total work.\n    //\n    // Here is output of an experiment using the BM_CacheInSteadyState\n    // benchmark running the old case (where we rehash-in-place only if we can\n    // reclaim at least 7/16*capacity) vs. this code (which rehashes in place\n    // if we can recover 3/32*capacity).\n    //\n    // Note that although in the worst-case number of rehashes jumped up from\n    // 15 to 190, but the number of operations per second is almost the same.\n    //\n    // Abridged output of running BM_CacheInSteadyState benchmark from\n    // raw_hash_set_benchmark.   N is the number of insert/erase operations.\n    //\n    //      | OLD (recover >= 7/16        | NEW (recover >= 3/32)\n    // size |    N/s LoadFactor NRehashes |    N/s LoadFactor NRehashes\n    //  448 | 145284       0.44        18 | 140118       0.44        19\n    //  493 | 152546       0.24        11 | 151417       0.48        28\n    //  538 | 151439       0.26        11 | 151152       0.53        38\n    //  583 | 151765       0.28        11 | 150572       0.57        50\n    //  628 | 150241       0.31        11 | 150853       0.61        66\n    //  672 | 149602       0.33        12 | 150110       0.66        90\n    //  717 | 149998       0.35        12 | 149531       0.70       129\n    //  762 | 149836       0.37        13 | 148559       0.74       190\n    //  807 | 149736       0.39        14 | 151107       0.39        14\n    //  852 | 150204       0.42        15 | 151019       0.42        15\n    return DropDeletesWithoutResizeAndPrepareInsert(common, policy, new_hash);\n  } else {\n    // Otherwise grow the container.\n    return GrowToNextCapacityAndPrepareInsert(common, policy, new_hash);\n  }\n}\n\n// Slow path for PrepareInsertLarge that is called when the table has deleted\n// slots or need to be resized or rehashed.\nsize_t PrepareInsertLargeSlow(CommonFields& common,\n                              const PolicyFunctions& __restrict policy,\n                              size_t hash) {\n  const GrowthInfo growth_info = common.growth_info();\n  ABSL_SWISSTABLE_ASSERT(!growth_info.HasNoDeletedAndGrowthLeft());\n  if (ABSL_PREDICT_TRUE(growth_info.HasNoGrowthLeftAndNoDeleted())) {\n    // Table without deleted slots (>95% cases) that needs to be resized.\n    ABSL_SWISSTABLE_ASSERT(growth_info.HasNoDeleted() &&\n                           growth_info.GetGrowthLeft() == 0);\n    return GrowToNextCapacityAndPrepareInsert(common, policy, hash);\n  }\n  if (ABSL_PREDICT_FALSE(growth_info.HasNoGrowthLeftAssumingMayHaveDeleted())) {\n    // Table with deleted slots that needs to be rehashed or resized.\n    return RehashOrGrowToNextCapacityAndPrepareInsert(common, policy, hash);\n  }\n  // Table with deleted slots that has space for the inserting element.\n  FindInfo target = find_first_non_full(common, hash);\n  PrepareInsertCommon(common);\n  common.growth_info().OverwriteControlAsFull(common.control()[target.offset]);\n  SetCtrlInLargeTable(common, target.offset, H2(hash), policy.slot_size);\n  common.infoz().RecordInsertMiss(hash, target.probe_length);\n  return target.offset;\n}\n\n// Resizes empty non-allocated SOO table to NextCapacity(SooCapacity()),\n// forces the table to be sampled and prepares the insert.\n// SOO tables need to switch from SOO to heap in order to store the infoz.\n// Requires:\n//   1. `c.capacity() == SooCapacity()`.\n//   2. `c.empty()`.\nABSL_ATTRIBUTE_NOINLINE size_t\nGrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    absl::FunctionRef<size_t(size_t)> get_hash) {\n  ResizeEmptyNonAllocatedTableImpl(common, policy, NextCapacity(SooCapacity()),\n                                   /*force_infoz=*/true);\n  PrepareInsertCommon(common);\n  common.growth_info().OverwriteEmptyAsFull();\n  const size_t new_hash = get_hash(common.seed().seed());\n  SetCtrlInSingleGroupTable(common, SooSlotIndex(), H2(new_hash),\n                            policy.slot_size);\n  common.infoz().RecordInsertMiss(new_hash, /*distance_from_desired=*/0);\n  return SooSlotIndex();\n}\n\n// Resizes empty non-allocated table to the capacity to fit new_size elements.\n// Requires:\n//   1. `c.capacity() == policy.soo_capacity()`.\n//   2. `c.empty()`.\n//   3. `new_size > policy.soo_capacity()`.\n// The table will be attempted to be sampled.\nvoid ReserveEmptyNonAllocatedTableToFitNewSize(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t new_size) {\n  ValidateMaxSize(new_size, policy.key_size, policy.slot_size);\n  ABSL_ASSUME(new_size > 0);\n  ResizeEmptyNonAllocatedTableImpl(common, policy, SizeToCapacity(new_size),\n                                   /*force_infoz=*/false);\n  // This is after resize, to ensure that we have completed the allocation\n  // and have potentially sampled the hashtable.\n  common.infoz().RecordReservation(new_size);\n}\n\n// Type erased version of raw_hash_set::reserve for tables that have an\n// allocated backing array.\n//\n// Requires:\n//   1. `c.capacity() > policy.soo_capacity()` OR `!c.empty()`.\n// Reserving already allocated tables is considered to be a rare case.\nABSL_ATTRIBUTE_NOINLINE void ReserveAllocatedTable(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t new_size) {\n  const size_t cap = common.capacity();\n  ValidateMaxSize(new_size, policy.key_size, policy.slot_size);\n  ABSL_ASSUME(new_size > 0);\n  const size_t new_capacity = SizeToCapacity(new_size);\n  if (cap == policy.soo_capacity()) {\n    ABSL_SWISSTABLE_ASSERT(!common.empty());\n    ResizeFullSooTable(common, policy, new_capacity,\n                       ResizeFullSooTableSamplingMode::kNoSampling);\n  } else {\n    ABSL_SWISSTABLE_ASSERT(cap > policy.soo_capacity());\n    // TODO(b/382423690): consider using GrowToNextCapacity, when applicable.\n    ResizeAllocatedTableWithSeedChange(common, policy, new_capacity);\n  }\n  common.infoz().RecordReservation(new_size);\n}\n\n// As `ResizeFullSooTableToNextCapacity`, except that we also force the SOO\n// table to be sampled. SOO tables need to switch from SOO to heap in order to\n// store the infoz. No-op if sampling is disabled or not possible.\nvoid GrowFullSooTableToNextCapacityForceSampling(\n    CommonFields& common, const PolicyFunctions& __restrict policy) {\n  AssertFullSoo(common, policy);\n  ResizeFullSooTable(\n      common, policy, NextCapacity(SooCapacity()),\n      ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled);\n}\n\n}  // namespace\n\nvoid* GetRefForEmptyClass(CommonFields& common) {\n  // Empty base optimization typically make the empty base class address to be\n  // the same as the first address of the derived class object.\n  // But we generally assume that for empty classes we can return any valid\n  // pointer.\n  return &common;\n}\n\nvoid ResizeAllocatedTableWithSeedChange(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t new_capacity) {\n  ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedAllocated>(\n      common, policy, new_capacity, common.infoz());\n}\n\nvoid ReserveEmptyNonAllocatedTableToFitBucketCount(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    size_t bucket_count) {\n  size_t new_capacity = NormalizeCapacity(bucket_count);\n  ValidateMaxCapacity(new_capacity, policy.key_size, policy.slot_size);\n  ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity,\n                                   /*force_infoz=*/false);\n}\n\n// Resizes a full SOO table to the NextCapacity(SooCapacity()).\ntemplate <size_t SooSlotMemcpySize, bool TransferUsesMemcpy>\nsize_t GrowSooTableToNextCapacityAndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& __restrict policy,\n    absl::FunctionRef<size_t(size_t)> get_hash, bool force_sampling) {\n  AssertSoo(common, policy);\n  if (ABSL_PREDICT_FALSE(force_sampling)) {\n    // The table is empty, it is only used for forced sampling of SOO tables.\n    return GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert(\n        common, policy, get_hash);\n  }\n  ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity());\n  static constexpr size_t kNewCapacity = NextCapacity(SooCapacity());\n  const size_t slot_size = policy.slot_size;\n  void* alloc = policy.get_char_alloc(common);\n  common.set_capacity(kNewCapacity);\n\n  // Since the table is not empty, it will not be sampled.\n  // The decision to sample was already made during the first insertion.\n  //\n  // We do not set control and slots in CommonFields yet to avoid overriding\n  // SOO data.\n  const auto [new_ctrl, new_slots] = AllocBackingArray(\n      common, policy, kNewCapacity, /*has_infoz=*/false, alloc);\n\n  PrepareInsertCommon(common);\n  ABSL_SWISSTABLE_ASSERT(common.size() == 2);\n  GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(kNewCapacity - 2);\n  common.generate_new_seed(/*has_infoz=*/false);\n  const h2_t soo_slot_h2 = H2(policy.hash_slot(\n      policy.hash_fn(common), common.soo_data(), common.seed().seed()));\n  const size_t new_hash = get_hash(common.seed().seed());\n\n  const size_t offset = Resize1To3NewOffset(new_hash, common.seed());\n  InitializeThreeElementsControlBytes(soo_slot_h2, H2(new_hash), offset,\n                                      new_ctrl);\n\n  SanitizerPoisonMemoryRegion(new_slots, slot_size * kNewCapacity);\n  void* target_slot = SlotAddress(new_slots, SooSlotIndex(), slot_size);\n  SanitizerUnpoisonMemoryRegion(target_slot, slot_size);\n  if constexpr (TransferUsesMemcpy) {\n    // Target slot is placed at index 1, but capacity is at\n    // minimum 3. So we are allowed to copy at least twice as much\n    // memory.\n    static_assert(SooSlotIndex() == 1);\n    static_assert(SooSlotMemcpySize > 0);\n    static_assert(SooSlotMemcpySize <= MaxSooSlotSize());\n    ABSL_SWISSTABLE_ASSERT(SooSlotMemcpySize <= 2 * slot_size);\n    ABSL_SWISSTABLE_ASSERT(SooSlotMemcpySize >= slot_size);\n    void* next_slot = SlotAddress(target_slot, 1, slot_size);\n    SanitizerUnpoisonMemoryRegion(next_slot, SooSlotMemcpySize - slot_size);\n    std::memcpy(target_slot, common.soo_data(), SooSlotMemcpySize);\n    SanitizerPoisonMemoryRegion(next_slot, SooSlotMemcpySize - slot_size);\n  } else {\n    static_assert(SooSlotMemcpySize == 0);\n    policy.transfer_n(&common, target_slot, common.soo_data(), 1);\n  }\n  common.set_control(new_ctrl);\n  common.set_slots(new_slots);\n\n  // Full SOO table couldn't be sampled. If SOO table is sampled, it would\n  // have been resized to the next capacity.\n  ABSL_SWISSTABLE_ASSERT(!common.infoz().IsSampled());\n  SanitizerUnpoisonMemoryRegion(SlotAddress(new_slots, offset, slot_size),\n                                slot_size);\n  return offset;\n}\n\nvoid Rehash(CommonFields& common, const PolicyFunctions& __restrict policy,\n            size_t n) {\n  const size_t cap = common.capacity();\n\n  auto clear_backing_array = [&]() {\n    ClearBackingArray(common, policy, policy.get_char_alloc(common),\n                      /*reuse=*/false, policy.soo_enabled);\n  };\n\n  const size_t slot_size = policy.slot_size;\n\n  if (n == 0) {\n    if (cap <= policy.soo_capacity()) return;\n    if (common.empty()) {\n      clear_backing_array();\n      return;\n    }\n    if (common.size() <= policy.soo_capacity()) {\n      // When the table is already sampled, we keep it sampled.\n      if (common.infoz().IsSampled()) {\n        static constexpr size_t kInitialSampledCapacity =\n            NextCapacity(SooCapacity());\n        if (cap > kInitialSampledCapacity) {\n          ResizeAllocatedTableWithSeedChange(common, policy,\n                                             kInitialSampledCapacity);\n        }\n        // This asserts that we didn't lose sampling coverage in `resize`.\n        ABSL_SWISSTABLE_ASSERT(common.infoz().IsSampled());\n        return;\n      }\n      ABSL_SWISSTABLE_ASSERT(slot_size <= sizeof(HeapOrSoo));\n      ABSL_SWISSTABLE_ASSERT(policy.slot_align <= alignof(HeapOrSoo));\n      HeapOrSoo tmp_slot;\n      size_t begin_offset = FindFirstFullSlot(0, cap, common.control());\n      policy.transfer_n(\n          &common, &tmp_slot,\n          SlotAddress(common.slot_array(), begin_offset, slot_size), 1);\n      clear_backing_array();\n      policy.transfer_n(&common, common.soo_data(), &tmp_slot, 1);\n      common.set_full_soo();\n      return;\n    }\n  }\n\n  // bitor is a faster way of doing `max` here. We will round up to the next\n  // power-of-2-minus-1, so bitor is good enough.\n  const size_t new_capacity =\n      NormalizeCapacity(n | SizeToCapacity(common.size()));\n  ValidateMaxCapacity(new_capacity, policy.key_size, policy.slot_size);\n  // n == 0 unconditionally rehashes as per the standard.\n  if (n == 0 || new_capacity > cap) {\n    if (cap == policy.soo_capacity()) {\n      if (common.empty()) {\n        ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity,\n                                         /*force_infoz=*/false);\n      } else {\n        ResizeFullSooTable(common, policy, new_capacity,\n                           ResizeFullSooTableSamplingMode::kNoSampling);\n      }\n    } else {\n      ResizeAllocatedTableWithSeedChange(common, policy, new_capacity);\n    }\n    // This is after resize, to ensure that we have completed the allocation\n    // and have potentially sampled the hashtable.\n    common.infoz().RecordReservation(n);\n  }\n}\n\nvoid Copy(CommonFields& common, const PolicyFunctions& __restrict policy,\n          const CommonFields& other,\n          absl::FunctionRef<void(void*, const void*)> copy_fn) {\n  const size_t size = other.size();\n  ABSL_SWISSTABLE_ASSERT(size > 0);\n  const size_t soo_capacity = policy.soo_capacity();\n  const size_t slot_size = policy.slot_size;\n  const bool soo_enabled = policy.soo_enabled;\n  if (size == 1) {\n    if (!soo_enabled) ReserveTableToFitNewSize(common, policy, 1);\n    IncrementSmallSize(common, policy);\n    const size_t other_capacity = other.capacity();\n    const void* other_slot =\n        other_capacity <= soo_capacity ? other.soo_data()\n        : other.is_small()\n            ? other.slot_array()\n            : SlotAddress(other.slot_array(),\n                          FindFirstFullSlot(0, other_capacity, other.control()),\n                          slot_size);\n    copy_fn(soo_enabled ? common.soo_data() : common.slot_array(), other_slot);\n\n    if (soo_enabled && policy.is_hashtablez_eligible &&\n        ShouldSampleNextTable()) {\n      GrowFullSooTableToNextCapacityForceSampling(common, policy);\n    }\n    return;\n  }\n\n  ReserveTableToFitNewSize(common, policy, size);\n  auto infoz = common.infoz();\n  ABSL_SWISSTABLE_ASSERT(other.capacity() > soo_capacity);\n  const size_t cap = common.capacity();\n  ABSL_SWISSTABLE_ASSERT(cap > soo_capacity);\n  size_t offset = cap;\n  const void* hash_fn = policy.hash_fn(common);\n  auto hasher = policy.hash_slot;\n  const size_t seed = common.seed().seed();\n  IterateOverFullSlotsImpl(\n      other, slot_size, [&](const ctrl_t*, void* that_slot) {\n        // The table is guaranteed to be empty, so we can do faster than\n        // a full `insert`.\n        const size_t hash = (*hasher)(hash_fn, that_slot, seed);\n        FindInfo target = find_first_non_full(common, hash);\n        infoz.RecordInsertMiss(hash, target.probe_length);\n        offset = target.offset;\n        SetCtrl(common, offset, H2(hash), slot_size);\n        copy_fn(SlotAddress(common.slot_array(), offset, slot_size), that_slot);\n        common.maybe_increment_generation_on_insert();\n      });\n  common.increment_size(size);\n  common.growth_info().OverwriteManyEmptyAsFull(size);\n}\n\nvoid ReserveTableToFitNewSize(CommonFields& common,\n                              const PolicyFunctions& __restrict policy,\n                              size_t new_size) {\n  common.reset_reserved_growth(new_size);\n  common.set_reservation_size(new_size);\n  ABSL_SWISSTABLE_ASSERT(new_size > policy.soo_capacity());\n  const size_t cap = common.capacity();\n  if (ABSL_PREDICT_TRUE(common.empty() && cap <= policy.soo_capacity())) {\n    return ReserveEmptyNonAllocatedTableToFitNewSize(common, policy, new_size);\n  }\n\n  ABSL_SWISSTABLE_ASSERT(!common.empty() || cap > policy.soo_capacity());\n  ABSL_SWISSTABLE_ASSERT(cap > 0);\n  const size_t max_size_before_growth =\n      IsSmallCapacity(cap) ? cap : common.size() + common.growth_left();\n  if (new_size <= max_size_before_growth) {\n    return;\n  }\n  ReserveAllocatedTable(common, policy, new_size);\n}\n\nnamespace {\nsize_t PrepareInsertLargeImpl(CommonFields& common,\n                              const PolicyFunctions& __restrict policy,\n                              size_t hash,\n                              Group::NonIterableBitMaskType mask_empty,\n                              FindInfo target_group) {\n  ABSL_SWISSTABLE_ASSERT(!common.is_small());\n  const GrowthInfo growth_info = common.growth_info();\n  // When there are no deleted slots in the table\n  // and growth_left is positive, we can insert at the first\n  // empty slot in the probe sequence (target).\n  if (ABSL_PREDICT_FALSE(!growth_info.HasNoDeletedAndGrowthLeft())) {\n    return PrepareInsertLargeSlow(common, policy, hash);\n  }\n  PrepareInsertCommon(common);\n  common.growth_info().OverwriteEmptyAsFull();\n  target_group.offset += mask_empty.LowestBitSet();\n  target_group.offset &= common.capacity();\n  SetCtrl(common, target_group.offset, H2(hash), policy.slot_size);\n  common.infoz().RecordInsertMiss(hash, target_group.probe_length);\n  return target_group.offset;\n}\n}  // namespace\n\nsize_t PrepareInsertLarge(CommonFields& common,\n                          const PolicyFunctions& __restrict policy, size_t hash,\n                          Group::NonIterableBitMaskType mask_empty,\n                          FindInfo target_group) {\n  // NOLINTNEXTLINE(misc-static-assert)\n  ABSL_SWISSTABLE_ASSERT(!SwisstableGenerationsEnabled());\n  return PrepareInsertLargeImpl(common, policy, hash, mask_empty, target_group);\n}\n\nsize_t PrepareInsertLargeGenerationsEnabled(\n    CommonFields& common, const PolicyFunctions& policy, size_t hash,\n    Group::NonIterableBitMaskType mask_empty, FindInfo target_group,\n    absl::FunctionRef<size_t(size_t)> recompute_hash) {\n  // NOLINTNEXTLINE(misc-static-assert)\n  ABSL_SWISSTABLE_ASSERT(SwisstableGenerationsEnabled());\n  if (common.should_rehash_for_bug_detection_on_insert()) {\n    // Move to a different heap allocation in order to detect bugs.\n    const size_t cap = common.capacity();\n    ResizeAllocatedTableWithSeedChange(\n        common, policy, common.growth_left() > 0 ? cap : NextCapacity(cap));\n    hash = recompute_hash(common.seed().seed());\n    std::tie(target_group, mask_empty) =\n        find_first_non_full_group(common, hash);\n  }\n  return PrepareInsertLargeImpl(common, policy, hash, mask_empty, target_group);\n}\n\nnamespace {\n// Returns true if the following is true\n// 1. OptimalMemcpySizeForSooSlotTransfer(left) >\n//    OptimalMemcpySizeForSooSlotTransfer(left - 1)\n// 2. OptimalMemcpySizeForSooSlotTransfer(left) are equal for all i in [left,\n// right].\n// This function is used to verify that we have all the possible template\n// instantiations for GrowFullSooTableToNextCapacity.\n// With this verification the problem may be detected at compile time instead of\n// link time.\nconstexpr bool VerifyOptimalMemcpySizeForSooSlotTransferRange(size_t left,\n                                                              size_t right) {\n  size_t optimal_size_for_range = OptimalMemcpySizeForSooSlotTransfer(left);\n  if (optimal_size_for_range <= OptimalMemcpySizeForSooSlotTransfer(left - 1)) {\n    return false;\n  }\n  for (size_t i = left + 1; i <= right; ++i) {\n    if (OptimalMemcpySizeForSooSlotTransfer(i) != optimal_size_for_range) {\n      return false;\n    }\n  }\n  return true;\n}\n}  // namespace\n\n// Extern template instantiation for inline function.\ntemplate size_t TryFindNewIndexWithoutProbing(size_t h1, size_t old_index,\n                                              size_t old_capacity,\n                                              ctrl_t* new_ctrl,\n                                              size_t new_capacity);\n\n// We need to instantiate ALL possible template combinations because we define\n// the function in the cc file.\ntemplate size_t GrowSooTableToNextCapacityAndPrepareInsert<0, false>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\ntemplate size_t GrowSooTableToNextCapacityAndPrepareInsert<\n    OptimalMemcpySizeForSooSlotTransfer(1), true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\n\nstatic_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(2, 3));\ntemplate size_t GrowSooTableToNextCapacityAndPrepareInsert<\n    OptimalMemcpySizeForSooSlotTransfer(3), true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\n\nstatic_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(4, 8));\ntemplate size_t GrowSooTableToNextCapacityAndPrepareInsert<\n    OptimalMemcpySizeForSooSlotTransfer(8), true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\n\n#if UINTPTR_MAX == UINT32_MAX\nstatic_assert(MaxSooSlotSize() == 8);\n#else\nstatic_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(9, 16));\ntemplate size_t GrowSooTableToNextCapacityAndPrepareInsert<\n    OptimalMemcpySizeForSooSlotTransfer(16), true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\nstatic_assert(MaxSooSlotSize() == 16);\n#endif\n\ntemplate void* AllocateBackingArray<BackingArrayAlignment(alignof(size_t)),\n                                    std::allocator<char>>(void* alloc,\n                                                          size_t n);\ntemplate void DeallocateBackingArray<BackingArrayAlignment(alignof(size_t)),\n                                     std::allocator<char>>(\n    void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,\n    size_t slot_align, bool had_infoz);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// An open-addressing\n// hashtable with quadratic probing.\n//\n// This is a low level hashtable on top of which different interfaces can be\n// implemented, like flat_hash_set, node_hash_set, string_hash_set, etc.\n//\n// The table interface is similar to that of std::unordered_set. Notable\n// differences are that most member functions support heterogeneous keys when\n// BOTH the hash and eq functions are marked as transparent. They do so by\n// providing a typedef called `is_transparent`.\n//\n// When heterogeneous lookup is enabled, functions that take key_type act as if\n// they have an overload set like:\n//\n//   iterator find(const key_type& key);\n//   template <class K>\n//   iterator find(const K& key);\n//\n//   size_type erase(const key_type& key);\n//   template <class K>\n//   size_type erase(const K& key);\n//\n//   std::pair<iterator, iterator> equal_range(const key_type& key);\n//   template <class K>\n//   std::pair<iterator, iterator> equal_range(const K& key);\n//\n// When heterogeneous lookup is disabled, only the explicit `key_type` overloads\n// exist.\n//\n// In addition the pointer to element and iterator stability guarantees are\n// weaker: all iterators and pointers are invalidated after a new element is\n// inserted.\n//\n// IMPLEMENTATION DETAILS\n//\n// # Table Layout\n//\n// A raw_hash_set's backing array consists of control bytes followed by slots\n// that may or may not contain objects.\n//\n// The layout of the backing array, for `capacity` slots, is thus, as a\n// pseudo-struct:\n//\n//   struct BackingArray {\n//     // Sampling handler. This field isn't present when the sampling is\n//     // disabled or this allocation hasn't been selected for sampling.\n//     HashtablezInfoHandle infoz_;\n//     // The number of elements we can insert before growing the capacity.\n//     size_t growth_left;\n//     // Control bytes for the \"real\" slots.\n//     ctrl_t ctrl[capacity];\n//     // Always `ctrl_t::kSentinel`. This is used by iterators to find when to\n//     // stop and serves no other purpose.\n//     ctrl_t sentinel;\n//     // A copy of the first `kWidth - 1` elements of `ctrl`. This is used so\n//     // that if a probe sequence picks a value near the end of `ctrl`,\n//     // `Group` will have valid control bytes to look at.\n//     ctrl_t clones[kWidth - 1];\n//     // The actual slot data.\n//     slot_type slots[capacity];\n//   };\n//\n// The length of this array is computed by `RawHashSetLayout::alloc_size` below.\n//\n// Control bytes (`ctrl_t`) are bytes (collected into groups of a\n// platform-specific size) that define the state of the corresponding slot in\n// the slot array. Group manipulation is tightly optimized to be as efficient\n// as possible: SSE and friends on x86, clever bit operations on other arches.\n//\n//      Group 1         Group 2        Group 3\n// +---------------+---------------+---------------+\n// | | | | | | | | | | | | | | | | | | | | | | | | |\n// +---------------+---------------+---------------+\n//\n// Each control byte is either a special value for empty slots, deleted slots\n// (sometimes called *tombstones*), and a special end-of-table marker used by\n// iterators, or, if occupied, seven bits (H2) from the hash of the value in the\n// corresponding slot.\n//\n// Storing control bytes in a separate array also has beneficial cache effects,\n// since more logical slots will fit into a cache line.\n//\n// # Small Object Optimization (SOO)\n//\n// When the size/alignment of the value_type and the capacity of the table are\n// small, we enable small object optimization and store the values inline in\n// the raw_hash_set object. This optimization allows us to avoid\n// allocation/deallocation as well as cache/dTLB misses.\n//\n// # Hashing\n//\n// We compute two separate hashes, `H1` and `H2`, from the hash of an object.\n// `H1(hash(x))` is an index into `slots`, and essentially the starting point\n// for the probe sequence. `H2(hash(x))` is a 7-bit value used to filter out\n// objects that cannot possibly be the one we are looking for.\n//\n// # Table operations.\n//\n// The key operations are `insert`, `find`, and `erase`.\n//\n// Since `insert` and `erase` are implemented in terms of `find`, we describe\n// `find` first. To `find` a value `x`, we compute `hash(x)`. From\n// `H1(hash(x))` and the capacity, we construct a `probe_seq` that visits every\n// group of slots in some interesting order.\n//\n// We now walk through these indices. At each index, we select the entire group\n// starting with that index and extract potential candidates: occupied slots\n// with a control byte equal to `H2(hash(x))`. If we find an empty slot in the\n// group, we stop and return an error. Each candidate slot `y` is compared with\n// `x`; if `x == y`, we are done and return `&y`; otherwise we continue to the\n// next probe index. Tombstones effectively behave like full slots that never\n// match the value we're looking for.\n//\n// The `H2` bits ensure when we compare a slot to an object with `==`, we are\n// likely to have actually found the object.  That is, the chance is low that\n// `==` is called and returns `false`.  Thus, when we search for an object, we\n// are unlikely to call `==` many times.  This likelyhood can be analyzed as\n// follows (assuming that H2 is a random enough hash function).\n//\n// Let's assume that there are `k` \"wrong\" objects that must be examined in a\n// probe sequence.  For example, when doing a `find` on an object that is in the\n// table, `k` is the number of objects between the start of the probe sequence\n// and the final found object (not including the final found object).  The\n// expected number of objects with an H2 match is then `k/128`.  Measurements\n// and analysis indicate that even at high load factors, `k` is less than 32,\n// meaning that the number of \"false positive\" comparisons we must perform is\n// less than 1/8 per `find`.\n\n// `insert` is implemented in terms of `unchecked_insert`, which inserts a\n// value presumed to not be in the table (violating this requirement will cause\n// the table to behave erratically). Given `x` and its hash `hash(x)`, to insert\n// it, we construct a `probe_seq` once again, and use it to find the first\n// group with an unoccupied (empty *or* deleted) slot. We place `x` into the\n// first such slot in the group and mark it as full with `x`'s H2.\n//\n// To `insert`, we compose `unchecked_insert` with `find`. We compute `h(x)` and\n// perform a `find` to see if it's already present; if it is, we're done. If\n// it's not, we may decide the table is getting overcrowded (i.e. the load\n// factor is greater than 7/8 for big tables; tables smaller than one probing\n// group use a max load factor of 1); in this case, we allocate a bigger array,\n// `unchecked_insert` each element of the table into the new array (we know that\n// no insertion here will insert an already-present value), and discard the old\n// backing array. At this point, we may `unchecked_insert` the value `x`.\n//\n// Below, `unchecked_insert` is partly implemented by `prepare_insert`, which\n// presents a viable, initialized slot pointee to the caller.\n//\n// `erase` is implemented in terms of `erase_at`, which takes an index to a\n// slot. Given an offset, we simply create a tombstone and destroy its contents.\n// If we can prove that the slot would not appear in a probe sequence, we can\n// make the slot as empty, instead. We can prove this by observing that if a\n// group has any empty slots, it has never been full (assuming we never create\n// an empty slot in a group with no empties, which this heuristic guarantees we\n// never do) and find would stop at this group anyways (since it does not probe\n// beyond groups with empties).\n//\n// `erase` is `erase_at` composed with `find`: if we\n// have a value `x`, we can perform a `find`, and then `erase_at` the resulting\n// slot.\n//\n// To iterate, we simply traverse the array, skipping empty and deleted slots\n// and stopping when we hit a `kSentinel`.\n\n#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_\n#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <functional>\n#include <initializer_list>\n#include <iterator>\n#include <limits>\n#include <memory>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/iterator_traits.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/options.h\"\n#include \"absl/base/port.h\"\n#include \"absl/base/prefetch.h\"\n#include \"absl/container/internal/common.h\"  // IWYU pragma: export // for node_handle\n#include \"absl/container/internal/common_policy_traits.h\"\n#include \"absl/container/internal/compressed_tuple.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/hash_function_defaults.h\"\n#include \"absl/container/internal/hash_policy_traits.h\"\n#include \"absl/container/internal/hashtable_control_bytes.h\"\n#include \"absl/container/internal/hashtable_debug_hooks.h\"\n#include \"absl/container/internal/hashtablez_sampler.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/utility/utility.h\"\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <ranges>  // NOLINT(build/c++20)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n#ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS\n#error ABSL_SWISSTABLE_ENABLE_GENERATIONS cannot be directly set\n#elif (defined(ABSL_HAVE_ADDRESS_SANITIZER) ||   \\\n       defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \\\n       defined(ABSL_HAVE_MEMORY_SANITIZER)) &&   \\\n    !defined(NDEBUG_SANITIZER)  // If defined, performance is important.\n// When compiled in sanitizer mode, we add generation integers to the backing\n// array and iterators. In the backing array, we store the generation between\n// the control bytes and the slots. When iterators are dereferenced, we assert\n// that the container has not been mutated in a way that could cause iterator\n// invalidation since the iterator was initialized.\n#define ABSL_SWISSTABLE_ENABLE_GENERATIONS\n#endif\n\n#ifdef ABSL_SWISSTABLE_ASSERT\n#error ABSL_SWISSTABLE_ASSERT cannot be directly set\n#else\n// We use this macro for assertions that users may see when the table is in an\n// invalid state that sanitizers may help diagnose.\n#define ABSL_SWISSTABLE_ASSERT(CONDITION) \\\n  assert((CONDITION) && \"Try enabling sanitizers.\")\n#endif\n\n// We use uint8_t so we don't need to worry about padding.\nusing GenerationType = uint8_t;\n\n// A sentinel value for empty generations. Using 0 makes it easy to constexpr\n// initialize an array of this value.\nconstexpr GenerationType SentinelEmptyGeneration() { return 0; }\n\nconstexpr GenerationType NextGeneration(GenerationType generation) {\n  return ++generation == SentinelEmptyGeneration() ? ++generation : generation;\n}\n\n#ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS\nconstexpr bool SwisstableGenerationsEnabled() { return true; }\nconstexpr size_t NumGenerationBytes() { return sizeof(GenerationType); }\n#else\nconstexpr bool SwisstableGenerationsEnabled() { return false; }\nconstexpr size_t NumGenerationBytes() { return 0; }\n#endif\n\n// Returns true if we should assert that the table is not accessed after it has\n// been destroyed or during the destruction of the table.\nconstexpr bool SwisstableAssertAccessToDestroyedTable() {\n#ifndef NDEBUG\n  return true;\n#endif\n  return SwisstableGenerationsEnabled();\n}\n\ntemplate <typename AllocType>\nvoid SwapAlloc(AllocType& lhs, AllocType& rhs,\n               std::true_type /* propagate_on_container_swap */) {\n  using std::swap;\n  swap(lhs, rhs);\n}\ntemplate <typename AllocType>\nvoid SwapAlloc([[maybe_unused]] AllocType& lhs, [[maybe_unused]] AllocType& rhs,\n               std::false_type /* propagate_on_container_swap */) {\n  assert(lhs == rhs &&\n         \"It's UB to call swap with unequal non-propagating allocators.\");\n}\n\ntemplate <typename AllocType>\nvoid CopyAlloc(AllocType& lhs, AllocType& rhs,\n               std::true_type /* propagate_alloc */) {\n  lhs = rhs;\n}\ntemplate <typename AllocType>\nvoid CopyAlloc(AllocType&, AllocType&, std::false_type /* propagate_alloc */) {}\n\n// The state for a probe sequence.\n//\n// Currently, the sequence is a triangular progression of the form\n//\n//   p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)\n//\n// The use of `Width` ensures that each probe step does not overlap groups;\n// the sequence effectively outputs the addresses of *groups* (although not\n// necessarily aligned to any boundary). The `Group` machinery allows us\n// to check an entire group with minimal branching.\n//\n// Wrapping around at `mask + 1` is important, but not for the obvious reason.\n// As described above, the first few entries of the control byte array\n// are mirrored at the end of the array, which `Group` will find and use\n// for selecting candidates. However, when those candidates' slots are\n// actually inspected, there are no corresponding slots for the cloned bytes,\n// so we need to make sure we've treated those offsets as \"wrapping around\".\n//\n// It turns out that this probe sequence visits every group exactly once if the\n// number of groups is a power of two, since (i^2+i)/2 is a bijection in\n// Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing\ntemplate <size_t Width>\nclass probe_seq {\n public:\n  // Creates a new probe sequence using `hash` as the initial value of the\n  // sequence and `mask` (usually the capacity of the table) as the mask to\n  // apply to each value in the progression.\n  probe_seq(size_t hash, size_t mask) {\n    ABSL_SWISSTABLE_ASSERT(((mask + 1) & mask) == 0 && \"not a mask\");\n    mask_ = mask;\n    offset_ = hash & mask_;\n  }\n\n  // The offset within the table, i.e., the value `p(i)` above.\n  size_t offset() const { return offset_; }\n  size_t offset(size_t i) const { return (offset_ + i) & mask_; }\n\n  void next() {\n    index_ += Width;\n    offset_ += index_;\n    offset_ &= mask_;\n  }\n  // 0-based probe index, a multiple of `Width`.\n  size_t index() const { return index_; }\n\n private:\n  size_t mask_;\n  size_t offset_;\n  size_t index_ = 0;\n};\n\ntemplate <class ContainerKey, class Hash, class Eq>\nstruct RequireUsableKey {\n  template <class PassedKey, class... Args>\n  std::pair<\n      decltype(std::declval<const Hash&>()(std::declval<const PassedKey&>())),\n      decltype(std::declval<const Eq&>()(std::declval<const ContainerKey&>(),\n                                         std::declval<const PassedKey&>()))>*\n  operator()(const PassedKey&, const Args&...) const;\n};\n\ntemplate <class E, class Policy, class Hash, class Eq, class... Ts>\nstruct IsDecomposable : std::false_type {};\n\ntemplate <class Policy, class Hash, class Eq, class... Ts>\nstruct IsDecomposable<\n    absl::void_t<decltype(Policy::apply(\n        RequireUsableKey<typename Policy::key_type, Hash, Eq>(),\n        std::declval<Ts>()...))>,\n    Policy, Hash, Eq, Ts...> : std::true_type {};\n\nABSL_DLL extern ctrl_t kDefaultIterControl;\n\n// We use these sentinel capacity values in debug mode to indicate different\n// classes of bugs.\nenum InvalidCapacity : size_t {\n  kAboveMaxValidCapacity = ~size_t{} - 100,\n  kReentrance,\n  kDestroyed,\n\n  // These two must be last because we use `>= kMovedFrom` to mean moved-from.\n  kMovedFrom,\n  kSelfMovedFrom,\n};\n\n// Returns a pointer to a control byte that can be used by default-constructed\n// iterators. We don't expect this pointer to be dereferenced.\ninline ctrl_t* DefaultIterControl() { return &kDefaultIterControl; }\n\n// For use in SOO iterators.\n// TODO(b/289225379): we could potentially get rid of this by adding an is_soo\n// bit in iterators. This would add branches but reduce cache misses.\nABSL_DLL extern const ctrl_t kSooControl[2];\n\n// Returns a pointer to a full byte followed by a sentinel byte.\ninline ctrl_t* SooControl() {\n  // Const must be cast away here; no uses of this function will actually write\n  // to it because it is only used for SOO iterators.\n  return const_cast<ctrl_t*>(kSooControl);\n}\n// Whether ctrl is from the SooControl array.\ninline bool IsSooControl(const ctrl_t* ctrl) { return ctrl == SooControl(); }\n\n// Returns a pointer to a generation to use for an empty hashtable.\nGenerationType* EmptyGeneration();\n\n// Returns whether `generation` is a generation for an empty hashtable that\n// could be returned by EmptyGeneration().\ninline bool IsEmptyGeneration(const GenerationType* generation) {\n  return *generation == SentinelEmptyGeneration();\n}\n\n// We only allow a maximum of 1 SOO element, which makes the implementation\n// much simpler. Complications with multiple SOO elements include:\n// - Satisfying the guarantee that erasing one element doesn't invalidate\n//   iterators to other elements means we would probably need actual SOO\n//   control bytes.\n// - In order to prevent user code from depending on iteration order for small\n//   tables, we would need to randomize the iteration order somehow.\nconstexpr size_t SooCapacity() { return 1; }\n// Sentinel type to indicate SOO CommonFields construction.\nstruct soo_tag_t {};\n// Sentinel type to indicate SOO CommonFields construction with full size.\nstruct full_soo_tag_t {};\n// Sentinel type to indicate non-SOO CommonFields construction.\nstruct non_soo_tag_t {};\n// Sentinel value to indicate an uninitialized value explicitly.\nstruct uninitialized_tag_t {};\n// Sentinel value to indicate creation of an empty table without a seed.\nstruct no_seed_empty_tag_t {};\n\n// Per table hash salt. This gets mixed into H1 to randomize iteration order\n// per-table.\n// The seed is needed to ensure non-determinism of iteration order.\nclass PerTableSeed {\n public:\n  // The number of bits in the seed.\n  // It is big enough to ensure non-determinism of iteration order.\n  // We store the seed inside a uint64_t together with size and other metadata.\n  // Using 16 bits allows us to save one `and` instruction in H1 (we use\n  // zero-extended move instead of mov+and). When absl::Hash is inlined, it can\n  // also have lower latency knowing that the high bits of the seed are zero.\n  static constexpr size_t kBitCount = 16;\n\n  // Returns the seed for the table.\n  size_t seed() const { return seed_; }\n\n private:\n  friend class HashtableSize;\n  explicit PerTableSeed(uint16_t seed) : seed_(seed) {}\n\n  // The most significant bit of the seed is always 1 when there is a non-zero\n  // seed. This way, when sign-extended the seed has non-zero high bits.\n  const uint16_t seed_;\n};\n\n// The size and also has additionally\n// 1) one bit that stores whether we have infoz.\n// 2) PerTableSeed::kBitCount bits for the seed. (For SOO tables, the lowest\n//    bit of the seed is repurposed to track if sampling has been tried).\nclass HashtableSize {\n public:\n  static constexpr size_t kSizeBitCount = 64 - PerTableSeed::kBitCount - 1;\n\n  explicit HashtableSize(uninitialized_tag_t) {}\n  explicit HashtableSize(no_seed_empty_tag_t) : data_(0) {}\n  HashtableSize(full_soo_tag_t, bool has_tried_sampling)\n      : data_(kSizeOneNoMetadata |\n              (has_tried_sampling ? kSooHasTriedSamplingMask : 0)) {}\n\n  // Returns actual size of the table.\n  size_t size() const { return static_cast<size_t>(data_ >> kSizeShift); }\n  void increment_size() { data_ += kSizeOneNoMetadata; }\n  void increment_size(size_t size) {\n    data_ += static_cast<uint64_t>(size) << kSizeShift;\n  }\n  void decrement_size() { data_ -= kSizeOneNoMetadata; }\n  // Returns true if the table is empty.\n  bool empty() const { return data_ < kSizeOneNoMetadata; }\n\n  // Returns true if an empty SOO table has already queried should_sample_soo().\n  bool soo_has_tried_sampling() const {\n    return (data_ & kSooHasTriedSamplingMask) != 0;\n  }\n\n  // Records that an empty SOO table has tried sampling.\n  void set_soo_has_tried_sampling() { data_ |= kSooHasTriedSamplingMask; }\n\n  // Sets the size, but keeps all the metadata bits.\n  void set_size_keep_metadata(size_t size) {\n    data_ =\n        (data_ & kMetadataMask) | (static_cast<uint64_t>(size) << kSizeShift);\n  }\n\n  PerTableSeed seed() const {\n    return PerTableSeed(static_cast<size_t>(data_) & kSeedMask);\n  }\n\n  void generate_new_seed() { set_seed(NextSeed()); }\n\n  // We need to use a constant seed when the table is sampled so that sampled\n  // hashes use the same seed and can e.g. identify stuck bits accurately.\n  void set_sampled_seed() { set_seed((std::numeric_limits<uint16_t>::max)()); }\n\n  bool is_sampled_seed() const {\n    return (data_ & kSeedMask) == (std::numeric_limits<uint16_t>::max)();\n  }\n\n  // Returns true if the table has infoz.\n  bool has_infoz() const {\n    return ABSL_PREDICT_FALSE((data_ & kHasInfozMask) != 0);\n  }\n\n  // Sets the has_infoz bit.\n  void set_has_infoz() { data_ |= kHasInfozMask; }\n\n  void set_no_seed_for_testing() { data_ &= ~kSeedMask; }\n\n  // Returns next per-table seed.\n  static uint16_t NextSeed();\n\n private:\n  void set_seed(uint16_t seed) { data_ = (data_ & ~kSeedMask) | seed; }\n  // Bit layout of `data_`:\n  // [63 ... 17] (47 bits) : size\n  // [16]        (1 bit)   : has_infoz\n  // [15 ...  0] (16 bits) : seed\n  static constexpr size_t kSizeShift = 64 - kSizeBitCount;\n  static constexpr uint64_t kSizeOneNoMetadata = uint64_t{1} << kSizeShift;\n  static constexpr uint64_t kMetadataMask = kSizeOneNoMetadata - 1;\n  static constexpr uint64_t kSeedMask =\n      (uint64_t{1} << PerTableSeed::kBitCount) - 1;\n  // The next bit after the seed.\n  static constexpr uint64_t kHasInfozMask = kSeedMask + 1;\n  // For SOO tables, the seed is unused, and bit 0 is repurposed to track\n  // whether the table has already queried should_sample_soo().\n  static constexpr uint64_t kSooHasTriedSamplingMask = 1;\n  uint64_t data_;\n};\n\n// H1 is just the low bits of the hash.\ninline size_t H1(size_t hash) { return hash; }\n\n// Extracts the H2 portion of a hash: the 7 most significant bits.\n//\n// These are used as an occupied control byte.\ninline h2_t H2(size_t hash) { return hash >> (sizeof(size_t) * 8 - 7); }\n\n// When there is an insertion with no reserved growth, we rehash with\n// probability `min(1, RehashProbabilityConstant() / capacity())`. Using a\n// constant divided by capacity ensures that inserting N elements is still O(N)\n// in the average case. Using the constant 16 means that we expect to rehash ~8\n// times more often than when generations are disabled. We are adding expected\n// rehash_probability * #insertions/capacity_growth = 16/capacity * ((7/8 -\n// 7/16) * capacity)/capacity_growth = ~7 extra rehashes per capacity growth.\ninline size_t RehashProbabilityConstant() { return 16; }\n\nclass CommonFieldsGenerationInfoEnabled {\n  // A sentinel value for reserved_growth_ indicating that we just ran out of\n  // reserved growth on the last insertion. When reserve is called and then\n  // insertions take place, reserved_growth_'s state machine is N, ..., 1,\n  // kReservedGrowthJustRanOut, 0.\n  static constexpr size_t kReservedGrowthJustRanOut =\n      (std::numeric_limits<size_t>::max)();\n\n public:\n  CommonFieldsGenerationInfoEnabled() = default;\n  CommonFieldsGenerationInfoEnabled(CommonFieldsGenerationInfoEnabled&& that)\n      : reserved_growth_(that.reserved_growth_),\n        reservation_size_(that.reservation_size_),\n        generation_(that.generation_) {\n    that.reserved_growth_ = 0;\n    that.reservation_size_ = 0;\n    that.generation_ = EmptyGeneration();\n  }\n  CommonFieldsGenerationInfoEnabled& operator=(\n      CommonFieldsGenerationInfoEnabled&&) = default;\n\n  // Whether we should rehash on insert in order to detect bugs of using invalid\n  // references. We rehash on the first insertion after reserved_growth_ reaches\n  // 0 after a call to reserve. We also do a rehash with low probability\n  // whenever reserved_growth_ is zero.\n  bool should_rehash_for_bug_detection_on_insert(size_t capacity) const;\n  // Similar to above, except that we don't depend on reserved_growth_.\n  bool should_rehash_for_bug_detection_on_move(size_t capacity) const;\n  void maybe_increment_generation_on_insert() {\n    if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0;\n\n    if (reserved_growth_ > 0) {\n      if (--reserved_growth_ == 0) reserved_growth_ = kReservedGrowthJustRanOut;\n    } else {\n      increment_generation();\n    }\n  }\n  void increment_generation() { *generation_ = NextGeneration(*generation_); }\n  void reset_reserved_growth(size_t reservation, size_t size) {\n    reserved_growth_ = reservation - size;\n  }\n  size_t reserved_growth() const { return reserved_growth_; }\n  void set_reserved_growth(size_t r) { reserved_growth_ = r; }\n  size_t reservation_size() const { return reservation_size_; }\n  void set_reservation_size(size_t r) { reservation_size_ = r; }\n  GenerationType generation() const { return *generation_; }\n  void set_generation(GenerationType g) { *generation_ = g; }\n  GenerationType* generation_ptr() const { return generation_; }\n  void set_generation_ptr(GenerationType* g) { generation_ = g; }\n\n private:\n  // The number of insertions remaining that are guaranteed to not rehash due to\n  // a prior call to reserve. Note: we store reserved growth in addition to\n  // reservation size because calls to erase() decrease size_ but don't decrease\n  // reserved growth.\n  size_t reserved_growth_ = 0;\n  // The maximum argument to reserve() since the container was cleared. We need\n  // to keep track of this, in addition to reserved growth, because we reset\n  // reserved growth to this when erase(begin(), end()) is called.\n  size_t reservation_size_ = 0;\n  // Pointer to the generation counter, which is used to validate iterators and\n  // is stored in the backing array between the control bytes and the slots.\n  // Note that we can't store the generation inside the container itself and\n  // keep a pointer to the container in the iterators because iterators must\n  // remain valid when the container is moved.\n  // Note: we could derive this pointer from the control pointer, but it makes\n  // the code more complicated, and there's a benefit in having the sizes of\n  // raw_hash_set in sanitizer mode and non-sanitizer mode a bit more different,\n  // which is that tests are less likely to rely on the size remaining the same.\n  GenerationType* generation_ = EmptyGeneration();\n};\n\nclass CommonFieldsGenerationInfoDisabled {\n public:\n  CommonFieldsGenerationInfoDisabled() = default;\n  CommonFieldsGenerationInfoDisabled(CommonFieldsGenerationInfoDisabled&&) =\n      default;\n  CommonFieldsGenerationInfoDisabled& operator=(\n      CommonFieldsGenerationInfoDisabled&&) = default;\n\n  bool should_rehash_for_bug_detection_on_insert(size_t) const { return false; }\n  bool should_rehash_for_bug_detection_on_move(size_t) const { return false; }\n  void maybe_increment_generation_on_insert() {}\n  void increment_generation() {}\n  void reset_reserved_growth(size_t, size_t) {}\n  size_t reserved_growth() const { return 0; }\n  void set_reserved_growth(size_t) {}\n  size_t reservation_size() const { return 0; }\n  void set_reservation_size(size_t) {}\n  GenerationType generation() const { return 0; }\n  void set_generation(GenerationType) {}\n  GenerationType* generation_ptr() const { return nullptr; }\n  void set_generation_ptr(GenerationType*) {}\n};\n\nclass HashSetIteratorGenerationInfoEnabled {\n public:\n  HashSetIteratorGenerationInfoEnabled() = default;\n  explicit HashSetIteratorGenerationInfoEnabled(\n      const GenerationType* generation_ptr)\n      : generation_ptr_(generation_ptr), generation_(*generation_ptr) {}\n\n  GenerationType generation() const { return generation_; }\n  void reset_generation() { generation_ = *generation_ptr_; }\n  const GenerationType* generation_ptr() const { return generation_ptr_; }\n  void set_generation_ptr(const GenerationType* ptr) { generation_ptr_ = ptr; }\n\n private:\n  const GenerationType* generation_ptr_ = EmptyGeneration();\n  GenerationType generation_ = *generation_ptr_;\n};\n\nclass HashSetIteratorGenerationInfoDisabled {\n public:\n  HashSetIteratorGenerationInfoDisabled() = default;\n  explicit HashSetIteratorGenerationInfoDisabled(const GenerationType*) {}\n\n  GenerationType generation() const { return 0; }\n  void reset_generation() {}\n  const GenerationType* generation_ptr() const { return nullptr; }\n  void set_generation_ptr(const GenerationType*) {}\n};\n\n#ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS\nusing CommonFieldsGenerationInfo = CommonFieldsGenerationInfoEnabled;\nusing HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoEnabled;\n#else\nusing CommonFieldsGenerationInfo = CommonFieldsGenerationInfoDisabled;\nusing HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoDisabled;\n#endif\n\n// Stored the information regarding number of slots we can still fill\n// without needing to rehash.\n//\n// We want to ensure sufficient number of empty slots in the table in order\n// to keep probe sequences relatively short. Empty slot in the probe group\n// is required to stop probing.\n//\n// Tombstones (kDeleted slots) are not included in the growth capacity,\n// because we'd like to rehash when the table is filled with tombstones and/or\n// full slots.\n//\n// GrowthInfo also stores a bit that encodes whether table may have any\n// deleted slots.\n// Most of the tables (>95%) have no deleted slots, so some functions can\n// be more efficient with this information.\n//\n// Callers can also force a rehash via the standard `rehash(0)`,\n// which will recompute this value as a side-effect.\n//\n// See also `CapacityToGrowth()`.\nclass GrowthInfo {\n public:\n  // Leaves data member uninitialized.\n  GrowthInfo() = default;\n\n  // Initializes the GrowthInfo assuming we can grow `growth_left` elements\n  // and there are no kDeleted slots in the table.\n  void InitGrowthLeftNoDeleted(size_t growth_left) {\n    growth_left_info_ = growth_left;\n  }\n\n  // Overwrites single full slot with an empty slot.\n  void OverwriteFullAsEmpty() { ++growth_left_info_; }\n\n  // Overwrites single empty slot with a full slot.\n  void OverwriteEmptyAsFull() {\n    ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() > 0);\n    --growth_left_info_;\n  }\n\n  // Overwrites several empty slots with full slots.\n  void OverwriteManyEmptyAsFull(size_t count) {\n    ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() >= count);\n    growth_left_info_ -= count;\n  }\n\n  // Overwrites specified control element with full slot.\n  void OverwriteControlAsFull(ctrl_t ctrl) {\n    ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() >=\n                           static_cast<size_t>(IsEmpty(ctrl)));\n    growth_left_info_ -= static_cast<size_t>(IsEmpty(ctrl));\n  }\n\n  // Overwrites single full slot with a deleted slot.\n  void OverwriteFullAsDeleted() { growth_left_info_ |= kDeletedBit; }\n\n  // Returns true if table satisfies two properties:\n  // 1. Guaranteed to have no kDeleted slots.\n  // 2. There is a place for at least one element to grow.\n  bool HasNoDeletedAndGrowthLeft() const {\n    return static_cast<std::make_signed_t<size_t>>(growth_left_info_) > 0;\n  }\n\n  // Returns true if the table satisfies two properties:\n  // 1. Guaranteed to have no kDeleted slots.\n  // 2. There is no growth left.\n  bool HasNoGrowthLeftAndNoDeleted() const { return growth_left_info_ == 0; }\n\n  // Returns true if GetGrowthLeft() == 0, but must be called only if\n  // HasNoDeleted() is false. It is slightly more efficient.\n  bool HasNoGrowthLeftAssumingMayHaveDeleted() const {\n    ABSL_SWISSTABLE_ASSERT(!HasNoDeleted());\n    return growth_left_info_ == kDeletedBit;\n  }\n\n  // Returns true if table guaranteed to have no kDeleted slots.\n  bool HasNoDeleted() const {\n    return static_cast<std::make_signed_t<size_t>>(growth_left_info_) >= 0;\n  }\n\n  // Returns the number of elements left to grow.\n  size_t GetGrowthLeft() const { return growth_left_info_ & kGrowthLeftMask; }\n\n private:\n  static constexpr size_t kGrowthLeftMask = ((~size_t{}) >> 1);\n  static constexpr size_t kDeletedBit = ~kGrowthLeftMask;\n  // Topmost bit signal whenever there are deleted slots.\n  size_t growth_left_info_;\n};\n\nstatic_assert(sizeof(GrowthInfo) == sizeof(size_t), \"\");\nstatic_assert(alignof(GrowthInfo) == alignof(size_t), \"\");\n\n// Returns whether `n` is a valid capacity (i.e., number of slots).\n//\n// A valid capacity is a non-zero integer `2^m - 1`.\nconstexpr bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }\n\n// Whether a table is small enough that we don't need to hash any keys.\nconstexpr bool IsSmallCapacity(size_t capacity) { return capacity <= 1; }\n\n// Returns the number of \"cloned control bytes\".\n//\n// This is the number of control bytes that are present both at the beginning\n// of the control byte array and at the end, such that we can create a\n// `Group::kWidth`-width probe window starting from any control byte.\nconstexpr size_t NumClonedBytes() { return Group::kWidth - 1; }\n\n// Returns the number of control bytes including cloned.\nconstexpr size_t NumControlBytes(size_t capacity) {\n  return IsSmallCapacity(capacity) ? 0 : capacity + 1 + NumClonedBytes();\n}\n\n// Computes the offset from the start of the backing allocation of control.\n// infoz and growth_info are stored at the beginning of the backing array.\nconstexpr size_t ControlOffset(bool has_infoz) {\n  return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(GrowthInfo);\n}\n\n// Returns the offset of the next item after `offset` that is aligned to `align`\n// bytes. `align` must be a power of two.\nconstexpr size_t AlignUpTo(size_t offset, size_t align) {\n  return (offset + align - 1) & (~align + 1);\n}\n\n// Helper class for computing offsets and allocation size of hash set fields.\nclass RawHashSetLayout {\n public:\n  // TODO(b/413062340): maybe don't allocate growth info for capacity 1 tables.\n  // Doing so may require additional branches/complexity so it might not be\n  // worth it.\n  explicit RawHashSetLayout(size_t capacity, size_t slot_size,\n                            size_t slot_align, bool has_infoz)\n      : control_offset_(ControlOffset(has_infoz)),\n        generation_offset_(control_offset_ + NumControlBytes(capacity)),\n        slot_offset_(\n            AlignUpTo(generation_offset_ + NumGenerationBytes(), slot_align)),\n        alloc_size_(slot_offset_ + capacity * slot_size) {\n    ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));\n    ABSL_SWISSTABLE_ASSERT(\n        slot_size <=\n        ((std::numeric_limits<size_t>::max)() - slot_offset_) / capacity);\n  }\n\n  // Returns precomputed offset from the start of the backing allocation of\n  // control.\n  size_t control_offset() const { return control_offset_; }\n\n  // Given the capacity of a table, computes the offset (from the start of the\n  // backing allocation) of the generation counter (if it exists).\n  size_t generation_offset() const { return generation_offset_; }\n\n  // Given the capacity of a table, computes the offset (from the start of the\n  // backing allocation) at which the slots begin.\n  size_t slot_offset() const { return slot_offset_; }\n\n  // Given the capacity of a table, computes the total size of the backing\n  // array.\n  size_t alloc_size() const { return alloc_size_; }\n\n private:\n  size_t control_offset_;\n  size_t generation_offset_;\n  size_t slot_offset_;\n  size_t alloc_size_;\n};\n\nstruct HashtableFreeFunctionsAccess;\n\n// This allows us to work around an uninitialized memory warning when\n// constructing begin() iterators in empty hashtables.\ntemplate <typename T>\nunion MaybeInitializedPtr {\n  T* get() const { ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(p); }\n  void set(T* ptr) { p = ptr; }\n\n  T* p;\n};\n\nstruct HeapPtrs {\n  // The control bytes (and, also, a pointer near to the base of the backing\n  // array).\n  //\n  // This contains `capacity + 1 + NumClonedBytes()` entries.\n  //\n  // Note that growth_info is stored immediately before this pointer.\n  // May be uninitialized for small tables.\n  MaybeInitializedPtr<ctrl_t> control;\n\n  // The beginning of the slots, located at `SlotOffset()` bytes after\n  // `control`. May be uninitialized for empty tables.\n  // Note: we can't use `slots` because Qt defines \"slots\" as a macro.\n  MaybeInitializedPtr<void> slot_array;\n};\n\n// Returns the maximum size of the SOO slot.\nconstexpr size_t MaxSooSlotSize() { return sizeof(HeapPtrs); }\n\n// Manages the backing array pointers or the SOO slot. When raw_hash_set::is_soo\n// is true, the SOO slot is stored in `soo_data`. Otherwise, we use `heap`.\nunion HeapOrSoo {\n  MaybeInitializedPtr<ctrl_t>& control() {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.control);\n  }\n  MaybeInitializedPtr<ctrl_t> control() const {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.control);\n  }\n  MaybeInitializedPtr<void>& slot_array() {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.slot_array);\n  }\n  MaybeInitializedPtr<void> slot_array() const {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.slot_array);\n  }\n  void* get_soo_data() {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(soo_data);\n  }\n  const void* get_soo_data() const {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(soo_data);\n  }\n\n  HeapPtrs heap;\n  unsigned char soo_data[MaxSooSlotSize()];\n};\n\n// Returns a reference to the GrowthInfo object stored immediately before\n// `control`.\ninline GrowthInfo& GetGrowthInfoFromControl(ctrl_t* control) {\n  auto* gl_ptr = reinterpret_cast<GrowthInfo*>(control) - 1;\n  ABSL_SWISSTABLE_ASSERT(\n      reinterpret_cast<uintptr_t>(gl_ptr) % alignof(GrowthInfo) == 0);\n  return *gl_ptr;\n}\n\n// CommonFields hold the fields in raw_hash_set that do not depend\n// on template parameters. This allows us to conveniently pass all\n// of this state to helper functions as a single argument.\nclass CommonFields : public CommonFieldsGenerationInfo {\n public:\n  explicit CommonFields(soo_tag_t)\n      : capacity_(SooCapacity()), size_(no_seed_empty_tag_t{}) {}\n  explicit CommonFields(full_soo_tag_t, bool has_tried_sampling)\n      : capacity_(SooCapacity()), size_(full_soo_tag_t{}, has_tried_sampling) {}\n  explicit CommonFields(non_soo_tag_t)\n      : capacity_(0), size_(no_seed_empty_tag_t{}) {}\n  // For use in swapping.\n  explicit CommonFields(uninitialized_tag_t) : size_(uninitialized_tag_t{}) {}\n\n  // Not copyable\n  CommonFields(const CommonFields&) = delete;\n  CommonFields& operator=(const CommonFields&) = delete;\n\n  // Copy with guarantee that it is not SOO.\n  CommonFields(non_soo_tag_t, const CommonFields& that)\n      : capacity_(that.capacity_),\n        size_(that.size_),\n        heap_or_soo_(that.heap_or_soo_) {\n  }\n\n  // Movable\n  CommonFields(CommonFields&& that) = default;\n  CommonFields& operator=(CommonFields&&) = default;\n\n  template <bool kSooEnabled>\n  static CommonFields CreateDefault() {\n    return kSooEnabled ? CommonFields{soo_tag_t{}}\n                       : CommonFields{non_soo_tag_t{}};\n  }\n\n  // The inline data for SOO is written on top of control_/slots_.\n  const void* soo_data() const { return heap_or_soo_.get_soo_data(); }\n  void* soo_data() { return heap_or_soo_.get_soo_data(); }\n\n  ctrl_t* control() const {\n    ABSL_SWISSTABLE_ASSERT(capacity() > 0);\n    // Assume that the control bytes don't alias `this`.\n    ctrl_t* ctrl = heap_or_soo_.control().get();\n    [[maybe_unused]] size_t num_control_bytes = NumControlBytes(capacity());\n    ABSL_ASSUME(reinterpret_cast<uintptr_t>(ctrl + num_control_bytes) <=\n                    reinterpret_cast<uintptr_t>(this) ||\n                reinterpret_cast<uintptr_t>(this + 1) <=\n                    reinterpret_cast<uintptr_t>(ctrl));\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(ctrl);\n  }\n\n  void set_control(ctrl_t* c) { heap_or_soo_.control().set(c); }\n\n  // Note: we can't use slots() because Qt defines \"slots\" as a macro.\n  void* slot_array() const { return heap_or_soo_.slot_array().get(); }\n  MaybeInitializedPtr<void> slots_union() const {\n    return heap_or_soo_.slot_array();\n  }\n  void set_slots(void* s) { heap_or_soo_.slot_array().set(s); }\n\n  // The number of filled slots.\n  size_t size() const { return size_.size(); }\n  // Sets the size to zero, but keeps hashinfoz bit and seed.\n  void set_size_to_zero() { size_.set_size_keep_metadata(0); }\n  void set_empty_soo() {\n    AssertInSooMode();\n    size_.set_size_keep_metadata(0);\n  }\n  void set_full_soo() {\n    AssertInSooMode();\n    size_.set_size_keep_metadata(1);\n  }\n  void increment_size() {\n    ABSL_SWISSTABLE_ASSERT(size() < capacity());\n    size_.increment_size();\n  }\n  void increment_size(size_t n) {\n    ABSL_SWISSTABLE_ASSERT(size() + n <= capacity());\n    size_.increment_size(n);\n  }\n  void decrement_size() {\n    ABSL_SWISSTABLE_ASSERT(!empty());\n    size_.decrement_size();\n  }\n  bool empty() const { return size_.empty(); }\n  void set_soo_has_tried_sampling() { size_.set_soo_has_tried_sampling(); }\n  bool soo_has_tried_sampling() const { return size_.soo_has_tried_sampling(); }\n\n  // The seed used for the hash function.\n  PerTableSeed seed() const { return size_.seed(); }\n  // Generates a new seed the hash function.\n  // The table will be invalidated if `!empty()` because hash is being changed.\n  // In such cases, we will need to rehash the table.\n  void generate_new_seed(bool has_infoz) {\n    // Note: we can't use has_infoz() here because we set has_infoz later than\n    // we generate the seed.\n    if (ABSL_PREDICT_FALSE(has_infoz)) {\n      size_.set_sampled_seed();\n      return;\n    }\n    size_.generate_new_seed();\n  }\n  void set_no_seed_for_testing() { size_.set_no_seed_for_testing(); }\n\n  // The total number of available slots.\n  size_t capacity() const { return capacity_; }\n  void set_capacity(size_t c) {\n    // We allow setting above the max valid capacity for debugging purposes.\n    ABSL_SWISSTABLE_ASSERT(c == 0 || IsValidCapacity(c) ||\n                           c > kAboveMaxValidCapacity);\n    capacity_ = c;\n  }\n  bool is_small() const { return IsSmallCapacity(capacity_); }\n\n  // The number of slots we can still fill without needing to rehash.\n  // This is stored in the heap allocation before the control bytes.\n  // TODO(b/289225379): experiment with moving growth_info back inline to\n  // increase room for SOO.\n  size_t growth_left() const { return growth_info().GetGrowthLeft(); }\n\n  GrowthInfo& growth_info() {\n    ABSL_SWISSTABLE_ASSERT(!is_small());\n    return GetGrowthInfoFromControl(control());\n  }\n  GrowthInfo growth_info() const {\n    return const_cast<CommonFields*>(this)->growth_info();\n  }\n\n  bool has_infoz() const { return size_.has_infoz(); }\n  void set_has_infoz() {\n    ABSL_SWISSTABLE_ASSERT(size_.is_sampled_seed());\n    size_.set_has_infoz();\n  }\n\n  HashtablezInfoHandle* infoz_ptr() const {\n    // growth_info is stored before control bytes.\n    ABSL_SWISSTABLE_ASSERT(\n        reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);\n    ABSL_SWISSTABLE_ASSERT(has_infoz());\n    return reinterpret_cast<HashtablezInfoHandle*>(\n        control() - ControlOffset(/*has_infoz=*/true));\n  }\n\n  HashtablezInfoHandle infoz() {\n    return has_infoz() ? *infoz_ptr() : HashtablezInfoHandle();\n  }\n  void set_infoz(HashtablezInfoHandle infoz) {\n    ABSL_SWISSTABLE_ASSERT(has_infoz());\n    *infoz_ptr() = infoz;\n  }\n\n  bool should_rehash_for_bug_detection_on_insert() const {\n    if constexpr (!SwisstableGenerationsEnabled()) {\n      return false;\n    }\n    // As an optimization, we avoid calling ShouldRehashForBugDetection if we\n    // will end up rehashing anyways.\n    if (growth_left() == 0) return false;\n    return CommonFieldsGenerationInfo::\n        should_rehash_for_bug_detection_on_insert(capacity());\n  }\n  bool should_rehash_for_bug_detection_on_move() const {\n    return CommonFieldsGenerationInfo::should_rehash_for_bug_detection_on_move(\n        capacity());\n  }\n  void reset_reserved_growth(size_t reservation) {\n    CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size());\n  }\n\n  // The size of the backing array allocation.\n  size_t alloc_size(size_t slot_size, size_t slot_align) const {\n    return RawHashSetLayout(capacity(), slot_size, slot_align, has_infoz())\n        .alloc_size();\n  }\n\n  // Move fields other than heap_or_soo_.\n  void move_non_heap_or_soo_fields(CommonFields& that) {\n    static_cast<CommonFieldsGenerationInfo&>(*this) =\n        std::move(static_cast<CommonFieldsGenerationInfo&>(that));\n    capacity_ = that.capacity_;\n    size_ = that.size_;\n  }\n\n  // Returns the number of control bytes set to kDeleted. For testing only.\n  size_t TombstonesCount() const {\n    return static_cast<size_t>(\n        std::count(control(), control() + capacity(), ctrl_t::kDeleted));\n  }\n\n  // Helper to enable sanitizer mode validation to protect against reentrant\n  // calls during element constructor/destructor.\n  template <typename F>\n  void RunWithReentrancyGuard(F f) {\n#ifdef NDEBUG\n    f();\n    return;\n#endif\n    const size_t cap = capacity();\n    set_capacity(InvalidCapacity::kReentrance);\n    f();\n    set_capacity(cap);\n  }\n\n private:\n  // We store the has_infoz bit in the lowest bit of size_.\n  static constexpr size_t HasInfozShift() { return 1; }\n  static constexpr size_t HasInfozMask() {\n    return (size_t{1} << HasInfozShift()) - 1;\n  }\n\n  // We can't assert that SOO is enabled because we don't have SooEnabled(), but\n  // we assert what we can.\n  void AssertInSooMode() const {\n    ABSL_SWISSTABLE_ASSERT(capacity() == SooCapacity());\n    ABSL_SWISSTABLE_ASSERT(!has_infoz());\n  }\n\n  // The number of slots in the backing array. This is always 2^N-1 for an\n  // integer N. NOTE: we tried experimenting with compressing the capacity and\n  // storing it together with size_: (a) using 6 bits to store the corresponding\n  // power (N in 2^N-1), and (b) storing 2^N as the most significant bit of\n  // size_ and storing size in the low bits. Both of these experiments were\n  // regressions, presumably because we need capacity to do find operations.\n  size_t capacity_;\n\n  // TODO(b/289225379): we could put size_ into HeapOrSoo and make capacity_\n  // encode the size in SOO case. We would be making size()/capacity() more\n  // expensive in order to have more SOO space.\n  HashtableSize size_;\n\n  // Either the control/slots pointers or the SOO slot.\n  HeapOrSoo heap_or_soo_;\n};\n\ntemplate <class Policy, class... Params>\nclass raw_hash_set;\n\n// Returns the next valid capacity after `n`.\nconstexpr size_t NextCapacity(size_t n) {\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n) || n == 0);\n  return n * 2 + 1;\n}\n\n// Returns the previous valid capacity before `n`.\nconstexpr size_t PreviousCapacity(size_t n) {\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n));\n  return n / 2;\n}\n\n// Applies the following mapping to every byte in the control array:\n//   * kDeleted -> kEmpty\n//   * kEmpty -> kEmpty\n//   * _ -> kDeleted\n// PRECONDITION:\n//   IsValidCapacity(capacity)\n//   ctrl[capacity] == ctrl_t::kSentinel\n//   ctrl[i] != ctrl_t::kSentinel for all i < capacity\nvoid ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);\n\n// Converts `n` into the next valid capacity, per `IsValidCapacity`.\nconstexpr size_t NormalizeCapacity(size_t n) {\n  return n ? ~size_t{} >> countl_zero(n) : 1;\n}\n\n// General notes on capacity/growth methods below:\n// - We use 7/8th as maximum load factor. For 16-wide groups, that gives an\n//   average of two empty slots per group.\n// - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.\n// - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we\n//   never need to probe (the whole table fits in one group) so we don't need a\n//   load factor less than 1.\n\n// Given `capacity`, applies the load factor; i.e., it returns the maximum\n// number of values we should put into the table before a resizing rehash.\nconstexpr size_t CapacityToGrowth(size_t capacity) {\n  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));\n  // `capacity*7/8`\n  if (Group::kWidth == 8 && capacity == 7) {\n    // x-x/8 does not work when x==7.\n    return 6;\n  }\n  return capacity - capacity / 8;\n}\n\n// Given `size`, \"unapplies\" the load factor to find how large the capacity\n// should be to stay within the load factor.\n//\n// For size == 0, returns 0.\n// For other values, returns the same as `NormalizeCapacity(size*8/7)`.\nconstexpr size_t SizeToCapacity(size_t size) {\n  if (size == 0) {\n    return 0;\n  }\n  // The minimum possible capacity is NormalizeCapacity(size).\n  // Shifting right `~size_t{}` by `leading_zeros` yields\n  // NormalizeCapacity(size).\n  int leading_zeros = absl::countl_zero(size);\n  constexpr size_t kLast3Bits = size_t{7} << (sizeof(size_t) * 8 - 3);\n  // max_size_for_next_capacity = max_load_factor * next_capacity\n  //                            = (7/8) * (~size_t{} >> leading_zeros)\n  //                            = (7/8*~size_t{}) >> leading_zeros\n  //                            = kLast3Bits >> leading_zeros\n  size_t max_size_for_next_capacity = kLast3Bits >> leading_zeros;\n  // Decrease shift if size is too big for the minimum capacity.\n  leading_zeros -= static_cast<int>(size > max_size_for_next_capacity);\n  if constexpr (Group::kWidth == 8) {\n    // Formula doesn't work when size==7 for 8-wide groups.\n    leading_zeros -= (size == 7);\n  }\n  return (~size_t{}) >> leading_zeros;\n}\n\ntemplate <class InputIter>\nsize_t SelectBucketCountForIterRange(InputIter first, InputIter last,\n                                     size_t bucket_count) {\n  if (bucket_count != 0) {\n    return bucket_count;\n  }\n  if (base_internal::IsAtLeastIterator<std::random_access_iterator_tag,\n                                       InputIter>()) {\n    return SizeToCapacity(static_cast<size_t>(std::distance(first, last)));\n  }\n  return 0;\n}\n\nconstexpr bool SwisstableDebugEnabled() {\n#if defined(ABSL_SWISSTABLE_ENABLE_GENERATIONS) || \\\n    ABSL_OPTION_HARDENED == 1 || !defined(NDEBUG)\n  return true;\n#else\n  return false;\n#endif\n}\n\ninline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation,\n                         const GenerationType* generation_ptr,\n                         const char* operation) {\n  if (!SwisstableDebugEnabled()) return;\n  // `SwisstableDebugEnabled()` is also true for release builds with hardening\n  // enabled. To minimize their impact in those builds:\n  // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout\n  // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve\n  //   the chances that the hot paths will be inlined.\n  if (ABSL_PREDICT_FALSE(ctrl == nullptr)) {\n    ABSL_RAW_LOG(FATAL, \"%s called on end() iterator.\", operation);\n  }\n  if (ABSL_PREDICT_FALSE(ctrl == DefaultIterControl())) {\n    ABSL_RAW_LOG(FATAL, \"%s called on default-constructed iterator.\",\n                 operation);\n  }\n  if (SwisstableGenerationsEnabled()) {\n    if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {\n      ABSL_RAW_LOG(FATAL,\n                   \"%s called on invalid iterator. The table could have \"\n                   \"rehashed or moved since this iterator was initialized.\",\n                   operation);\n    }\n    if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {\n      ABSL_RAW_LOG(\n          FATAL,\n          \"%s called on invalid iterator. The element was likely erased.\",\n          operation);\n    }\n  } else {\n    if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {\n      ABSL_RAW_LOG(\n          FATAL,\n          \"%s called on invalid iterator. The element might have been erased \"\n          \"or the table might have rehashed. Consider running with \"\n          \"--config=asan to diagnose rehashing issues.\",\n          operation);\n    }\n  }\n}\n\n// Note that for comparisons, null/end iterators are valid.\ninline void AssertIsValidForComparison(const ctrl_t* ctrl,\n                                       GenerationType generation,\n                                       const GenerationType* generation_ptr) {\n  if (!SwisstableDebugEnabled()) return;\n  const bool ctrl_is_valid_for_comparison =\n      ctrl == nullptr || ctrl == DefaultIterControl() || IsFull(*ctrl);\n  if (SwisstableGenerationsEnabled()) {\n    if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {\n      ABSL_RAW_LOG(FATAL,\n                   \"Invalid iterator comparison. The table could have rehashed \"\n                   \"or moved since this iterator was initialized.\");\n    }\n    if (ABSL_PREDICT_FALSE(!ctrl_is_valid_for_comparison)) {\n      ABSL_RAW_LOG(\n          FATAL, \"Invalid iterator comparison. The element was likely erased.\");\n    }\n  } else {\n    ABSL_HARDENING_ASSERT_SLOW(\n        ctrl_is_valid_for_comparison &&\n        \"Invalid iterator comparison. The element might have been erased or \"\n        \"the table might have rehashed. Consider running with --config=asan to \"\n        \"diagnose rehashing issues.\");\n  }\n}\n\n// If the two iterators come from the same container, then their pointers will\n// interleave such that ctrl_a <= ctrl_b < slot_a <= slot_b or vice/versa.\n// Note: we take slots by reference so that it's not UB if they're uninitialized\n// as long as we don't read them (when ctrl is null).\ninline bool AreItersFromSameContainer(const ctrl_t* ctrl_a,\n                                      const ctrl_t* ctrl_b,\n                                      const void* const& slot_a,\n                                      const void* const& slot_b) {\n  // If either control byte is null, then we can't tell.\n  if (ctrl_a == nullptr || ctrl_b == nullptr) return true;\n  const bool a_is_soo = IsSooControl(ctrl_a);\n  if (a_is_soo != IsSooControl(ctrl_b)) return false;\n  if (a_is_soo) return slot_a == slot_b;\n\n  const void* low_slot = slot_a;\n  const void* hi_slot = slot_b;\n  if (ctrl_a > ctrl_b) {\n    std::swap(ctrl_a, ctrl_b);\n    std::swap(low_slot, hi_slot);\n  }\n  return ctrl_b < low_slot && low_slot <= hi_slot;\n}\n\n// Asserts that two iterators come from the same container.\n// Note: we take slots by reference so that it's not UB if they're uninitialized\n// as long as we don't read them (when ctrl is null).\ninline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b,\n                                const void* const& slot_a,\n                                const void* const& slot_b,\n                                const GenerationType* generation_ptr_a,\n                                const GenerationType* generation_ptr_b) {\n  if (!SwisstableDebugEnabled()) return;\n  // `SwisstableDebugEnabled()` is also true for release builds with hardening\n  // enabled. To minimize their impact in those builds:\n  // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout\n  // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve\n  //   the chances that the hot paths will be inlined.\n\n  // fail_if(is_invalid, message) crashes when is_invalid is true and provides\n  // an error message based on `message`.\n  const auto fail_if = [](bool is_invalid, const char* message) {\n    if (ABSL_PREDICT_FALSE(is_invalid)) {\n      ABSL_RAW_LOG(FATAL, \"Invalid iterator comparison. %s\", message);\n    }\n  };\n\n  const bool a_is_default = ctrl_a == DefaultIterControl();\n  const bool b_is_default = ctrl_b == DefaultIterControl();\n  if (a_is_default && b_is_default) return;\n  fail_if(a_is_default != b_is_default,\n          \"Comparing default-constructed hashtable iterator with a \"\n          \"non-default-constructed hashtable iterator.\");\n\n  if (SwisstableGenerationsEnabled()) {\n    if (ABSL_PREDICT_TRUE(generation_ptr_a == generation_ptr_b)) return;\n    const bool a_is_empty = IsEmptyGeneration(generation_ptr_a);\n    const bool b_is_empty = IsEmptyGeneration(generation_ptr_b);\n    fail_if(a_is_empty != b_is_empty,\n            \"Comparing an iterator from an empty hashtable with an iterator \"\n            \"from a non-empty hashtable.\");\n    fail_if(a_is_empty && b_is_empty,\n            \"Comparing iterators from different empty hashtables.\");\n\n    const bool a_is_end = ctrl_a == nullptr;\n    const bool b_is_end = ctrl_b == nullptr;\n    fail_if(a_is_end || b_is_end,\n            \"Comparing iterator with an end() iterator from a different \"\n            \"hashtable.\");\n    fail_if(true, \"Comparing non-end() iterators from different hashtables.\");\n  } else {\n    ABSL_HARDENING_ASSERT_SLOW(\n        AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) &&\n        \"Invalid iterator comparison. The iterators may be from different \"\n        \"containers or the container might have rehashed or moved. Consider \"\n        \"running with --config=asan to diagnose issues.\");\n  }\n}\n\nstruct FindInfo {\n  size_t offset;\n  size_t probe_length;\n};\n\n// Whether a table fits entirely into a probing group.\n// Arbitrary order of elements in such tables is correct.\nconstexpr bool is_single_group(size_t capacity) {\n  return capacity <= Group::kWidth;\n}\n\n// Begins a probing operation on `common.control`, using `hash`.\ninline probe_seq<Group::kWidth> probe_h1(size_t capacity, size_t h1) {\n  return probe_seq<Group::kWidth>(h1, capacity);\n}\ninline probe_seq<Group::kWidth> probe(size_t capacity, size_t hash) {\n  return probe_h1(capacity, H1(hash));\n}\ninline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {\n  return probe(common.capacity(), hash);\n}\n\nconstexpr size_t kProbedElementIndexSentinel = ~size_t{};\n\n// Implementation detail of transfer_unprobed_elements_to_next_capacity_fn.\n// Tries to find the new index for an element whose hash corresponds to\n// `h1` for growth to the next capacity.\n// Returns kProbedElementIndexSentinel if full probing is required.\n//\n// If element is located in the first probing group in the table before growth,\n// returns one of two positions: `old_index` or `old_index + old_capacity + 1`.\n//\n// Otherwise, we will try to insert it into the first probe group of the new\n// table. We only attempt to do so if the first probe group is already\n// initialized.\ntemplate <typename = void>\ninline size_t TryFindNewIndexWithoutProbing(size_t h1, size_t old_index,\n                                            size_t old_capacity,\n                                            ctrl_t* new_ctrl,\n                                            size_t new_capacity) {\n  size_t index_diff = old_index - h1;\n  // The first probe group starts with h1 & capacity.\n  // All following groups start at (h1 + Group::kWidth * K) & capacity.\n  // We can find an index within the floating group as index_diff modulo\n  // Group::kWidth.\n  // Both old and new capacity are larger than Group::kWidth so we can avoid\n  // computing `& capacity`.\n  size_t in_floating_group_index = index_diff & (Group::kWidth - 1);\n  // By subtracting we will get the difference between the first probe group\n  // and the probe group corresponding to old_index.\n  index_diff -= in_floating_group_index;\n  if (ABSL_PREDICT_TRUE((index_diff & old_capacity) == 0)) {\n    size_t new_index = (h1 + in_floating_group_index) & new_capacity;\n    ABSL_ASSUME(new_index != kProbedElementIndexSentinel);\n    return new_index;\n  }\n  ABSL_SWISSTABLE_ASSERT(((old_index - h1) & old_capacity) >= Group::kWidth);\n  // Try to insert element into the first probe group.\n  // new_ctrl is not yet fully initialized so we can't use regular search via\n  // find_first_non_full.\n\n  // We can search in the first probe group only if it is located in already\n  // initialized part of the table.\n  if (ABSL_PREDICT_FALSE((h1 & old_capacity) >= old_index)) {\n    return kProbedElementIndexSentinel;\n  }\n  size_t offset = h1 & new_capacity;\n  Group new_g(new_ctrl + offset);\n  if (auto mask = new_g.MaskNonFull(); ABSL_PREDICT_TRUE(mask)) {\n    size_t result = offset + mask.LowestBitSet();\n    ABSL_ASSUME(result != kProbedElementIndexSentinel);\n    return result;\n  }\n  return kProbedElementIndexSentinel;\n}\n\n// Extern template for inline function keeps possibility of inlining.\n// When compiler decided to not inline, no symbols will be added to the\n// corresponding translation unit.\nextern template size_t TryFindNewIndexWithoutProbing(size_t h1,\n                                                     size_t old_index,\n                                                     size_t old_capacity,\n                                                     ctrl_t* new_ctrl,\n                                                     size_t new_capacity);\n\n// growth_info (which is a size_t) is stored with the backing array.\nconstexpr size_t BackingArrayAlignment(size_t align_of_slot) {\n  return (std::max)(align_of_slot, alignof(GrowthInfo));\n}\n\n// Iterates over all full slots and calls `cb(const ctrl_t*, void*)`.\n// No insertion to the table is allowed during `cb` call.\n// Erasure is allowed only for the element passed to the callback.\n// The table must not be in SOO mode.\nvoid IterateOverFullSlots(const CommonFields& c, size_t slot_size,\n                          absl::FunctionRef<void(const ctrl_t*, void*)> cb);\n\ntemplate <typename CharAlloc>\nconstexpr bool ShouldSampleHashtablezInfoForAlloc() {\n  // Folks with custom allocators often make unwarranted assumptions about the\n  // behavior of their classes vis-a-vis trivial destructability and what\n  // calls they will or won't make.  Avoid sampling for people with custom\n  // allocators to get us out of this mess.  This is not a hard guarantee but\n  // a workaround while we plan the exact guarantee we want to provide.\n  return std::is_same_v<CharAlloc, std::allocator<char>>;\n}\n\n// Allocates `n` bytes for a backing array.\ntemplate <size_t AlignOfBackingArray, typename Alloc>\nvoid* AllocateBackingArray(void* alloc, size_t n) {\n  return Allocate<AlignOfBackingArray>(static_cast<Alloc*>(alloc), n);\n}\n\n// Note: we mark this function as ABSL_ATTRIBUTE_NOINLINE because we don't want\n// it to be inlined into e.g. the destructor to save code size.\ntemplate <size_t AlignOfBackingArray, typename Alloc>\nABSL_ATTRIBUTE_NOINLINE void DeallocateBackingArray(\n    void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,\n    size_t slot_align, bool had_infoz) {\n  RawHashSetLayout layout(capacity, slot_size, slot_align, had_infoz);\n  void* backing_array = ctrl - layout.control_offset();\n  // Unpoison before returning the memory to the allocator.\n  SanitizerUnpoisonMemoryRegion(backing_array, layout.alloc_size());\n  Deallocate<AlignOfBackingArray>(static_cast<Alloc*>(alloc), backing_array,\n                                  layout.alloc_size());\n}\n\n// PolicyFunctions bundles together some information for a particular\n// raw_hash_set<T, ...> instantiation. This information is passed to\n// type-erased functions that want to do small amounts of type-specific\n// work.\nstruct PolicyFunctions {\n  uint32_t key_size;\n  uint32_t value_size;\n  uint32_t slot_size;\n  uint16_t slot_align;\n  bool soo_enabled;\n  bool is_hashtablez_eligible;\n\n  // Returns the pointer to the hash function stored in the set.\n  void* (*hash_fn)(CommonFields& common);\n\n  // Returns the hash of the pointed-to slot.\n  HashSlotFn hash_slot;\n\n  // Transfers the contents of `count` slots from src_slot to dst_slot.\n  // We use ability to transfer several slots in single group table growth.\n  void (*transfer_n)(void* set, void* dst_slot, void* src_slot, size_t count);\n\n  // Returns the pointer to the CharAlloc stored in the set.\n  void* (*get_char_alloc)(CommonFields& common);\n\n  // Allocates n bytes for the backing store for common.\n  void* (*alloc)(void* alloc, size_t n);\n\n  // Deallocates the backing store from common.\n  void (*dealloc)(void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,\n                  size_t slot_align, bool had_infoz);\n\n  // Implementation detail of GrowToNextCapacity.\n  // Iterates over all full slots and transfers unprobed elements.\n  // Initializes the new control bytes except mirrored bytes and kSentinel.\n  // Caller must finish the initialization.\n  // All slots corresponding to the full control bytes are transferred.\n  // Probed elements are reported by `encode_probed_element` callback.\n  // encode_probed_element may overwrite old_ctrl buffer till source_offset.\n  // Different encoding is used depending on the capacity of the table.\n  // See ProbedItem*Bytes classes for details.\n  void (*transfer_unprobed_elements_to_next_capacity)(\n      CommonFields& common, const ctrl_t* old_ctrl, void* old_slots,\n      // TODO(b/382423690): Try to use absl::FunctionRef here.\n      void* probed_storage,\n      void (*encode_probed_element)(void* probed_storage, h2_t h2,\n                                    size_t source_offset, size_t h1));\n\n  uint8_t soo_capacity() const {\n    return static_cast<uint8_t>(soo_enabled ? SooCapacity() : 0);\n  }\n};\n\n// The following functions are used for calculating the max valid size of the\n// table. This is important for security to avoid overflowing size_t when\n// calculating the allocation size of the backing array\n// (https://nvd.nist.gov/vuln/detail/CVE-2025-0838). We also limit the max valid\n// size based on the size of the key_type, and this is an optimization because\n// we ABSL_ASSUME that the size is less than MaxValidSize, which can enable\n// other optimizations for tables with small keys.\n\ntemplate <size_t kSizeOfSizeT = sizeof(size_t)>\nconstexpr size_t MaxSizeAtMaxValidCapacity(size_t slot_size) {\n  using SizeT = std::conditional_t<kSizeOfSizeT == 4, uint32_t, uint64_t>;\n  // We shift right by 2 for a safe margin against overflow.\n  constexpr SizeT kMaxValidCapacity = ~SizeT{} >> 2;\n  return CapacityToGrowth(kMaxValidCapacity) / slot_size;\n}\n\nconstexpr size_t MaxStorableSize() {\n  return static_cast<size_t>(uint64_t{1} << HashtableSize::kSizeBitCount) - 1;\n}\n\n// There are no more than 2^sizeof(key_type) unique key_types (and hashtable\n// keys must be unique) so we can't have a hashtable with more than\n// 2^sizeof(key_type) elements.\ntemplate <size_t kSizeOfSizeT = sizeof(size_t)>\nconstexpr size_t MaxValidSizeForKeySize(size_t key_size) {\n  if (key_size < kSizeOfSizeT) return size_t{1} << 8 * key_size;\n  return (std::numeric_limits<size_t>::max)();\n}\n\ntemplate <size_t kSizeOfSizeT = sizeof(size_t)>\nconstexpr size_t MaxValidSizeForSlotSize(size_t slot_size) {\n  if constexpr (kSizeOfSizeT == 8) {\n    // For small slot sizes we are limited by HashtableSize::kSizeBitCount.\n    if (slot_size < size_t{1} << (64 - HashtableSize::kSizeBitCount)) {\n      return MaxStorableSize();\n    }\n  }\n  return MaxSizeAtMaxValidCapacity<kSizeOfSizeT>(slot_size);\n}\n\n// Returns the maximum valid size for a table, given the key size and slot size.\n// Template parameter is only used to enable testing.\ntemplate <size_t kSizeOfSizeT = sizeof(size_t)>\nconstexpr size_t MaxValidSize(size_t key_size, size_t slot_size) {\n  return (std::min)(MaxValidSizeForKeySize<kSizeOfSizeT>(key_size),\n                    MaxValidSizeForSlotSize<kSizeOfSizeT>(slot_size));\n}\n\n// Returns the index of the SOO slot when growing from SOO to non-SOO in a\n// single group. See also InitializeSmallControlBytesAfterSoo(). It's important\n// to use index 1 so that when resizing from capacity 1 to 3, we can still have\n// random iteration order between the first two inserted elements.\n// I.e. it allows inserting the second element at either index 0 or 2.\nconstexpr size_t SooSlotIndex() { return 1; }\n\n// Maximum capacity for the algorithm for small table after SOO.\n// Note that typical size after SOO is 3, but we allow up to 7.\n// Allowing till 16 would require additional store that can be avoided.\nconstexpr size_t MaxSmallAfterSooCapacity() { return 7; }\n\n// Type erased version of raw_hash_set::reserve. Requires:\n//   1. `new_size > policy.soo_capacity`.\n//   2. `new_size <= kMaxValidSize`.\nvoid ReserveTableToFitNewSize(CommonFields& common,\n                              const PolicyFunctions& policy, size_t new_size);\n\n// Resizes empty non-allocated table to the next valid capacity after\n// `bucket_count`. Requires:\n//   1. `c.capacity() == policy.soo_capacity`.\n//   2. `c.empty()`.\n//   3. `new_size > policy.soo_capacity`.\n//   4. `bucket_count <= MaxValidCapacity()`.\n// The table will be attempted to be sampled.\nvoid ReserveEmptyNonAllocatedTableToFitBucketCount(\n    CommonFields& common, const PolicyFunctions& policy, size_t bucket_count);\n\n// Type erased version of raw_hash_set::rehash.\n// Requires: `n <= MaxValidCapacity()`.\nvoid Rehash(CommonFields& common, const PolicyFunctions& policy, size_t n);\n\n// Type erased version of copy constructor.\nvoid Copy(CommonFields& common, const PolicyFunctions& policy,\n          const CommonFields& other,\n          absl::FunctionRef<void(void*, const void*)> copy_fn);\n\n// Returns the optimal size for memcpy when transferring SOO slot.\n// Otherwise, returns the optimal size for memcpy SOO slot transfer\n// to SooSlotIndex().\n// At the destination we are allowed to copy upto twice more bytes,\n// because there is at least one more slot after SooSlotIndex().\n// The result must not exceed MaxSooSlotSize().\n// Some of the cases are merged to minimize the number of function\n// instantiations.\nconstexpr size_t OptimalMemcpySizeForSooSlotTransfer(\n    size_t slot_size, size_t max_soo_slot_size = MaxSooSlotSize()) {\n  static_assert(MaxSooSlotSize() >= 8, \"unexpectedly small SOO slot size\");\n  if (slot_size == 1) {\n    return 1;\n  }\n  if (slot_size <= 3) {\n    return 4;\n  }\n  // We are merging 4 and 8 into one case because we expect them to be the\n  // hottest cases. Copying 8 bytes is as fast on common architectures.\n  if (slot_size <= 8) {\n    return 8;\n  }\n  if (max_soo_slot_size <= 16) {\n    return max_soo_slot_size;\n  }\n  if (slot_size <= 16) {\n    return 16;\n  }\n  if (max_soo_slot_size <= 24) {\n    return max_soo_slot_size;\n  }\n  static_assert(MaxSooSlotSize() <= 24, \"unexpectedly large SOO slot size\");\n  return 24;\n}\n\n// Resizes SOO table to the NextCapacity(SooCapacity()) and prepares insert for\n// the given new_hash. Returns the offset of the new element.\n// All possible template combinations are defined in cc file to improve\n// compilation time.\ntemplate <size_t SooSlotMemcpySize, bool TransferUsesMemcpy>\nsize_t GrowSooTableToNextCapacityAndPrepareInsert(\n    CommonFields& common, const PolicyFunctions& policy,\n    absl::FunctionRef<size_t(size_t)> get_hash, bool force_sampling);\n\n// PrepareInsert for small tables (is_small()==true).\n// Returns the new control and the new slot.\n// Hash is only computed if the table is sampled or grew to large size\n// (is_small()==false).\nstd::pair<ctrl_t*, void*> PrepareInsertSmallNonSoo(\n    CommonFields& common, const PolicyFunctions& policy,\n    absl::FunctionRef<size_t(size_t)> get_hash);\n\n// Resizes table with allocated slots and change the table seed.\n// Tables with SOO enabled must have capacity > policy.soo_capacity.\n// No sampling will be performed since table is already allocated.\nvoid ResizeAllocatedTableWithSeedChange(CommonFields& common,\n                                        const PolicyFunctions& policy,\n                                        size_t new_capacity);\n\n// ClearBackingArray clears the backing array, either modifying it in place,\n// or creating a new one based on the value of \"reuse\".\n// REQUIRES: c.capacity > 0\nvoid ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,\n                       void* alloc, bool reuse, bool soo_enabled);\n\n// Type-erased versions of raw_hash_set::erase_meta_only_{small,large}.\nvoid EraseMetaOnlySmall(CommonFields& c, bool soo_enabled, size_t slot_size);\nvoid EraseMetaOnlyLarge(CommonFields& c, const ctrl_t* ctrl, size_t slot_size);\n\n// For trivially relocatable types we use memcpy directly. This allows us to\n// share the same function body for raw_hash_set instantiations that have the\n// same slot size as long as they are relocatable.\n// Separate function for relocating single slot cause significant binary bloat.\ntemplate <size_t SizeOfSlot>\nABSL_ATTRIBUTE_NOINLINE void TransferNRelocatable(void*, void* dst, void* src,\n                                                  size_t count) {\n  // TODO(b/382423690): Experiment with making specialization for power of 2 and\n  // non power of 2. This would require passing the size of the slot.\n  memcpy(dst, src, SizeOfSlot * count);\n}\n\n// Returns a pointer to `common`. This is used to implement type erased\n// raw_hash_set::get_hash_ref_fn and raw_hash_set::get_alloc_ref_fn for the\n// empty class cases.\nvoid* GetRefForEmptyClass(CommonFields& common);\n\n// Given the hash of a value not currently in the table and the first group with\n// an empty slot in the probe sequence, finds a viable slot index to insert it\n// at.\n//\n// In case there's no space left, the table can be resized or rehashed\n// (for tables with deleted slots, see FindInsertPositionWithGrowthOrRehash).\n//\n// In the case of absence of deleted slots and positive growth_left, the element\n// can be inserted in one of the empty slots in the provided `target_group`.\n//\n// When the table has deleted slots (according to GrowthInfo), the target\n// position will be searched one more time using `find_first_non_full`.\n//\n// REQUIRES: `!common.is_small()`.\n// REQUIRES: At least one non-full slot available.\n// REQUIRES: `mask_empty` is a mask containing empty slots for the\n//           `target_group`.\n// REQUIRES: `target_group` is a starting position for the group that has\n//            at least one empty slot.\nsize_t PrepareInsertLarge(CommonFields& common, const PolicyFunctions& policy,\n                          size_t hash, Group::NonIterableBitMaskType mask_empty,\n                          FindInfo target_group);\n\n// Same as above, but with generations enabled, we may end up changing the seed,\n// which means we need to be able to recompute the hash.\nsize_t PrepareInsertLargeGenerationsEnabled(\n    CommonFields& common, const PolicyFunctions& policy, size_t hash,\n    Group::NonIterableBitMaskType mask_empty, FindInfo target_group,\n    absl::FunctionRef<size_t(size_t)> recompute_hash);\n\ntemplate <typename Policy, typename Hash, typename Eq, typename Alloc>\nstruct InstantiateRawHashSet {\n  using type = typename ApplyWithoutDefaultSuffix<\n      raw_hash_set,\n      TypeList<void, typename Policy::DefaultHash, typename Policy::DefaultEq,\n               typename Policy::DefaultAlloc>,\n      TypeList<Policy, Hash, Eq, Alloc>>::type;\n};\n\n// A SwissTable.\n//\n// Policy: a policy defines how to perform different operations on\n// the slots of the hashtable (see hash_policy_traits.h for the full interface\n// of policy).\n//\n// Params...: a variadic list of parameters that allows us to omit default\n//            types. This reduces the mangled name of the class and the size of\n//            debug strings like __PRETTY_FUNCTION__. Default types do not give\n//            any new information.\n//\n// Hash: a (possibly polymorphic) functor that hashes keys of the hashtable. The\n// functor should accept a key and return size_t as hash. For best performance\n// it is important that the hash function provides high entropy across all bits\n// of the hash.\n// This is the first element in `Params...` if it exists, or Policy::DefaultHash\n// otherwise.\n//\n// Eq: a (possibly polymorphic) functor that compares two keys for equality. It\n// should accept two (of possibly different type) keys and return a bool: true\n// if they are equal, false if they are not. If two keys compare equal, then\n// their hash values as defined by Hash MUST be equal.\n// This is the second element in `Params...` if it exists, or Policy::DefaultEq\n// otherwise.\n//\n// Allocator: an Allocator\n// [https://en.cppreference.com/w/cpp/named_req/Allocator] with which\n// the storage of the hashtable will be allocated and the elements will be\n// constructed and destroyed.\n// This is the third element in `Params...` if it exists, or\n// Policy::DefaultAlloc otherwise.\ntemplate <class Policy, class... Params>\nclass raw_hash_set {\n  using PolicyTraits = hash_policy_traits<Policy>;\n  using Hash = GetFromListOr<typename Policy::DefaultHash, 0, Params...>;\n  using Eq = GetFromListOr<typename Policy::DefaultEq, 1, Params...>;\n  using Alloc = GetFromListOr<typename Policy::DefaultAlloc, 2, Params...>;\n  using KeyArgImpl =\n      KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;\n\n  static_assert(\n      std::is_same_v<\n          typename InstantiateRawHashSet<Policy, Hash, Eq, Alloc>::type,\n          raw_hash_set>,\n      \"Redundant template parameters were passed. Use InstantiateRawHashSet<> \"\n      \"instead\");\n\n public:\n  using init_type = typename PolicyTraits::init_type;\n  using key_type = typename PolicyTraits::key_type;\n  using allocator_type = Alloc;\n  using size_type = size_t;\n  using difference_type = ptrdiff_t;\n  using hasher = Hash;\n  using key_equal = Eq;\n  using policy_type = Policy;\n  using value_type = typename PolicyTraits::value_type;\n  using reference = value_type&;\n  using const_reference = const value_type&;\n  using pointer = typename absl::allocator_traits<\n      allocator_type>::template rebind_traits<value_type>::pointer;\n  using const_pointer = typename absl::allocator_traits<\n      allocator_type>::template rebind_traits<value_type>::const_pointer;\n\n private:\n  // Alias used for heterogeneous lookup functions.\n  // `key_arg<K>` evaluates to `K` when the functors are transparent and to\n  // `key_type` otherwise. It permits template argument deduction on `K` for the\n  // transparent case.\n  template <class K>\n  using key_arg = typename KeyArgImpl::template type<K, key_type>;\n\n  using slot_type = typename PolicyTraits::slot_type;\n\n  constexpr static bool kIsDefaultHash =\n      std::is_same_v<hasher, absl::Hash<key_type>> ||\n      std::is_same_v<hasher, absl::container_internal::StringHash>;\n\n  // TODO(b/289225379): we could add extra SOO space inside raw_hash_set\n  // after CommonFields to allow inlining larger slot_types (e.g. std::string),\n  // but it's a bit complicated if we want to support incomplete mapped_type in\n  // flat_hash_map. We could potentially do this for flat_hash_set and for an\n  // allowlist of `mapped_type`s of flat_hash_map that includes e.g. arithmetic\n  // types, strings, cords, and pairs/tuples of allowlisted types.\n  constexpr static bool SooEnabled() {\n    return PolicyTraits::soo_enabled() &&\n           sizeof(slot_type) <= sizeof(HeapOrSoo) &&\n           alignof(slot_type) <= alignof(HeapOrSoo);\n  }\n\n  constexpr static size_t DefaultCapacity() {\n    return SooEnabled() ? SooCapacity() : 0;\n  }\n  constexpr static size_t MaxValidSize() {\n    return container_internal::MaxValidSize(sizeof(key_type),\n                                            sizeof(slot_type));\n  }\n  constexpr static size_t MaxValidCapacity() {\n    return SizeToCapacity(MaxValidSize());\n  }\n\n  // Whether `size` fits in the SOO capacity of this table.\n  bool fits_in_soo(size_t size) const {\n    return SooEnabled() && size <= SooCapacity();\n  }\n  // Whether this table is in SOO mode or non-SOO mode.\n  bool is_soo() const { return fits_in_soo(maybe_invalid_capacity()); }\n  bool is_full_soo() const { return is_soo() && !empty(); }\n\n  bool is_small() const { return common().is_small(); }\n\n  // Give an early error when key_type is not hashable/eq.\n  auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));\n  auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));\n\n  // Try to be helpful when the hasher returns an unreasonable type.\n  using key_hash_result =\n      absl::remove_cvref_t<decltype(std::declval<const Hash&>()(\n          std::declval<const key_type&>()))>;\n  static_assert(sizeof(key_hash_result) >= sizeof(size_t),\n                \"`Hash::operator()` should return a `size_t`\");\n\n  using AllocTraits = absl::allocator_traits<allocator_type>;\n  using SlotAlloc = typename absl::allocator_traits<\n      allocator_type>::template rebind_alloc<slot_type>;\n  // People are often sloppy with the exact type of their allocator (sometimes\n  // it has an extra const or is missing the pair, but rebinds made it work\n  // anyway).\n  using CharAlloc =\n      typename absl::allocator_traits<Alloc>::template rebind_alloc<char>;\n  using SlotAllocTraits = typename absl::allocator_traits<\n      allocator_type>::template rebind_traits<slot_type>;\n\n  static_assert(std::is_lvalue_reference<reference>::value,\n                \"Policy::element() must return a reference\");\n\n  // An enabler for insert(T&&): T must be convertible to init_type or be the\n  // same as [cv] value_type [ref].\n  template <class T>\n  using Insertable = absl::disjunction<\n      std::is_same<absl::remove_cvref_t<reference>, absl::remove_cvref_t<T>>,\n      std::is_convertible<T, init_type>>;\n  template <class T>\n  using IsNotBitField = std::is_pointer<T*>;\n\n  // RequiresNotInit is a workaround for gcc prior to 7.1.\n  // See https://godbolt.org/g/Y4xsUh.\n  template <class T>\n  using RequiresNotInit =\n      typename std::enable_if<!std::is_same<T, init_type>::value, int>::type;\n\n  template <class... Ts>\n  using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>;\n\n  template <class T>\n  using IsDecomposableAndInsertable =\n      IsDecomposable<std::enable_if_t<Insertable<T>::value, T>>;\n\n  // Evaluates to true if an assignment from the given type would require the\n  // source object to remain alive for the life of the element.\n  template <class U>\n  using IsLifetimeBoundAssignmentFrom = std::conditional_t<\n      policy_trait_element_is_owner<Policy>::value, std::false_type,\n      type_traits_internal::IsLifetimeBoundAssignment<init_type, U>>;\n\n public:\n  static_assert(std::is_same<pointer, value_type*>::value,\n                \"Allocators with custom pointer types are not supported\");\n  static_assert(std::is_same<const_pointer, const value_type*>::value,\n                \"Allocators with custom pointer types are not supported\");\n\n  class iterator : private HashSetIteratorGenerationInfo {\n    friend class raw_hash_set;\n    friend struct HashtableFreeFunctionsAccess;\n\n   public:\n    using iterator_category = std::forward_iterator_tag;\n    using value_type = typename raw_hash_set::value_type;\n    using reference =\n        absl::conditional_t<PolicyTraits::constant_iterators::value,\n                            const value_type&, value_type&>;\n    using pointer = absl::remove_reference_t<reference>*;\n    using difference_type = typename raw_hash_set::difference_type;\n\n    iterator() {}\n\n    // PRECONDITION: not an end() iterator.\n    reference operator*() const {\n      assert_is_full(\"operator*()\");\n      return unchecked_deref();\n    }\n\n    // PRECONDITION: not an end() iterator.\n    pointer operator->() const {\n      assert_is_full(\"operator->\");\n      return &operator*();\n    }\n\n    // PRECONDITION: not an end() iterator.\n    iterator& operator++() {\n      assert_is_full(\"operator++\");\n      ++ctrl_;\n      ++slot_;\n      skip_empty_or_deleted();\n      if (ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr;\n      return *this;\n    }\n    // PRECONDITION: not an end() iterator.\n    iterator operator++(int) {\n      auto tmp = *this;\n      ++*this;\n      return tmp;\n    }\n\n    friend bool operator==(const iterator& a, const iterator& b) {\n      AssertIsValidForComparison(a.ctrl_, a.generation(), a.generation_ptr());\n      AssertIsValidForComparison(b.ctrl_, b.generation(), b.generation_ptr());\n      AssertSameContainer(a.ctrl_, b.ctrl_, a.slot_, b.slot_,\n                          a.generation_ptr(), b.generation_ptr());\n      return a.ctrl_ == b.ctrl_;\n    }\n    friend bool operator!=(const iterator& a, const iterator& b) {\n      return !(a == b);\n    }\n\n   private:\n    iterator(ctrl_t* ctrl, slot_type* slot,\n             const GenerationType* generation_ptr)\n        : HashSetIteratorGenerationInfo(generation_ptr),\n          ctrl_(ctrl),\n          slot_(slot) {\n      // This assumption helps the compiler know that any non-end iterator is\n      // not equal to any end iterator.\n      ABSL_ASSUME(ctrl != nullptr);\n    }\n    // This constructor is used in begin() to avoid an MSan\n    // use-of-uninitialized-value error. Delegating from this constructor to\n    // the previous one doesn't avoid the error.\n    iterator(ctrl_t* ctrl, MaybeInitializedPtr<void> slot,\n             const GenerationType* generation_ptr)\n        : HashSetIteratorGenerationInfo(generation_ptr),\n          ctrl_(ctrl),\n          slot_(to_slot(slot.get())) {\n      // This assumption helps the compiler know that any non-end iterator is\n      // not equal to any end iterator.\n      ABSL_ASSUME(ctrl != nullptr);\n    }\n    // For end() iterators.\n    explicit iterator(const GenerationType* generation_ptr)\n        : HashSetIteratorGenerationInfo(generation_ptr), ctrl_(nullptr) {}\n\n    void assert_is_full(const char* operation) const {\n      AssertIsFull(ctrl_, generation(), generation_ptr(), operation);\n    }\n\n    // Fixes up `ctrl_` to point to a full or sentinel by advancing `ctrl_` and\n    // `slot_` until they reach one.\n    void skip_empty_or_deleted() {\n      while (IsEmptyOrDeleted(*ctrl_)) {\n        ++ctrl_;\n        ++slot_;\n      }\n    }\n\n    // An equality check which skips ABSL Hardening iterator invalidation\n    // checks.\n    // Should be used when the lifetimes of the iterators are well-enough\n    // understood to prove that they cannot be invalid.\n    bool unchecked_equals(const iterator& b) const {\n      return ctrl_ == b.control();\n    }\n\n    // Dereferences the iterator without ABSL Hardening iterator invalidation\n    // checks.\n    reference unchecked_deref() const { return PolicyTraits::element(slot_); }\n\n    ctrl_t* control() const { return ctrl_; }\n    slot_type* slot() const { return slot_; }\n\n    // We use DefaultIterControl() for default-constructed iterators so that\n    // they can be distinguished from end iterators, which have nullptr ctrl_.\n    ctrl_t* ctrl_ = DefaultIterControl();\n    // To avoid uninitialized member warnings, put slot_ in an anonymous union.\n    // The member is not initialized on singleton and end iterators.\n    union {\n      slot_type* slot_;\n    };\n  };\n\n  class const_iterator {\n    friend class raw_hash_set;\n    template <class Container, typename Enabler>\n    friend struct absl::container_internal::hashtable_debug_internal::\n        HashtableDebugAccess;\n\n   public:\n    using iterator_category = typename iterator::iterator_category;\n    using value_type = typename raw_hash_set::value_type;\n    using reference = typename raw_hash_set::const_reference;\n    using pointer = typename raw_hash_set::const_pointer;\n    using difference_type = typename raw_hash_set::difference_type;\n\n    const_iterator() = default;\n    // Implicit construction from iterator.\n    const_iterator(iterator i) : inner_(std::move(i)) {}  // NOLINT\n\n    reference operator*() const { return *inner_; }\n    pointer operator->() const { return inner_.operator->(); }\n\n    const_iterator& operator++() {\n      ++inner_;\n      return *this;\n    }\n    const_iterator operator++(int) { return inner_++; }\n\n    friend bool operator==(const const_iterator& a, const const_iterator& b) {\n      return a.inner_ == b.inner_;\n    }\n    friend bool operator!=(const const_iterator& a, const const_iterator& b) {\n      return !(a == b);\n    }\n\n   private:\n    const_iterator(const ctrl_t* ctrl, const slot_type* slot,\n                   const GenerationType* gen)\n        : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot), gen) {\n    }\n    bool unchecked_equals(const const_iterator& b) const {\n      return inner_.unchecked_equals(b.inner_);\n    }\n    ctrl_t* control() const { return inner_.control(); }\n    slot_type* slot() const { return inner_.slot(); }\n\n    iterator inner_;\n  };\n\n  using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;\n  using insert_return_type = InsertReturnType<iterator, node_type>;\n\n  // Note: can't use `= default` due to non-default noexcept (causes\n  // problems for some compilers). NOLINTNEXTLINE\n  raw_hash_set() noexcept(\n      std::is_nothrow_default_constructible<hasher>::value &&\n      std::is_nothrow_default_constructible<key_equal>::value &&\n      std::is_nothrow_default_constructible<allocator_type>::value) {}\n\n  explicit raw_hash_set(\n      size_t bucket_count, const hasher& hash = hasher(),\n      const key_equal& eq = key_equal(),\n      const allocator_type& alloc = allocator_type())\n      : settings_(CommonFields::CreateDefault<SooEnabled()>(), hash, eq,\n                  alloc) {\n    if (bucket_count > DefaultCapacity()) {\n      ReserveEmptyNonAllocatedTableToFitBucketCount(\n          common(), GetPolicyFunctions(),\n          (std::min)(bucket_count, MaxValidCapacity()));\n    }\n  }\n\n  raw_hash_set(size_t bucket_count, const hasher& hash,\n               const allocator_type& alloc)\n      : raw_hash_set(bucket_count, hash, key_equal(), alloc) {}\n\n  raw_hash_set(size_t bucket_count, const allocator_type& alloc)\n      : raw_hash_set(bucket_count, hasher(), key_equal(), alloc) {}\n\n  explicit raw_hash_set(const allocator_type& alloc)\n      : raw_hash_set(0, hasher(), key_equal(), alloc) {}\n\n  template <class InputIter>\n  raw_hash_set(InputIter first, InputIter last, size_t bucket_count = 0,\n               const hasher& hash = hasher(), const key_equal& eq = key_equal(),\n               const allocator_type& alloc = allocator_type())\n      : raw_hash_set(SelectBucketCountForIterRange(first, last, bucket_count),\n                     hash, eq, alloc) {\n    insert(first, last);\n  }\n\n  template <class InputIter>\n  raw_hash_set(InputIter first, InputIter last, size_t bucket_count,\n               const hasher& hash, const allocator_type& alloc)\n      : raw_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {}\n\n  template <class InputIter>\n  raw_hash_set(InputIter first, InputIter last, size_t bucket_count,\n               const allocator_type& alloc)\n      : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}\n\n#if defined(__cpp_lib_containers_ranges) && \\\n    __cpp_lib_containers_ranges >= 202202L\n  template <typename R>\n  raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count = 0,\n               const hasher& hash = hasher(), const key_equal& eq = key_equal(),\n               const allocator_type& alloc = allocator_type())\n      : raw_hash_set(std::begin(rg), std::end(rg), bucket_count, hash, eq,\n                     alloc) {}\n\n  template <typename R>\n  raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count,\n               const allocator_type& alloc)\n      : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count,\n                     hasher(), key_equal(), alloc) {}\n\n  template <typename R>\n  raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count,\n               const hasher& hash, const allocator_type& alloc)\n      : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count, hash,\n                     key_equal(), alloc) {}\n#endif\n\n  template <class InputIter>\n  raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)\n      : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}\n\n  // Instead of accepting std::initializer_list<value_type> as the first\n  // argument like std::unordered_set<value_type> does, we have two overloads\n  // that accept std::initializer_list<T> and std::initializer_list<init_type>.\n  // This is advantageous for performance.\n  //\n  //   // Turns {\"abc\", \"def\"} into std::initializer_list<std::string>, then\n  //   // copies the strings into the set.\n  //   std::unordered_set<std::string> s = {\"abc\", \"def\"};\n  //\n  //   // Turns {\"abc\", \"def\"} into std::initializer_list<const char*>, then\n  //   // copies the strings into the set.\n  //   absl::flat_hash_set<std::string> s = {\"abc\", \"def\"};\n  //\n  // The same trick is used in insert().\n  //\n  // The enabler is necessary to prevent this constructor from triggering where\n  // the copy constructor is meant to be called.\n  //\n  //   absl::flat_hash_set<int> a, b{a};\n  //\n  // RequiresNotInit<T> is a workaround for gcc prior to 7.1.\n  template <class T, RequiresNotInit<T> = 0,\n            std::enable_if_t<Insertable<T>::value, int> = 0>\n  raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0,\n               const hasher& hash = hasher(), const key_equal& eq = key_equal(),\n               const allocator_type& alloc = allocator_type())\n      : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}\n\n  raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count = 0,\n               const hasher& hash = hasher(), const key_equal& eq = key_equal(),\n               const allocator_type& alloc = allocator_type())\n      : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}\n\n  template <class T, RequiresNotInit<T> = 0,\n            std::enable_if_t<Insertable<T>::value, int> = 0>\n  raw_hash_set(std::initializer_list<T> init, size_t bucket_count,\n               const hasher& hash, const allocator_type& alloc)\n      : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}\n\n  raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,\n               const hasher& hash, const allocator_type& alloc)\n      : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}\n\n  template <class T, RequiresNotInit<T> = 0,\n            std::enable_if_t<Insertable<T>::value, int> = 0>\n  raw_hash_set(std::initializer_list<T> init, size_t bucket_count,\n               const allocator_type& alloc)\n      : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}\n\n  raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,\n               const allocator_type& alloc)\n      : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}\n\n  template <class T, RequiresNotInit<T> = 0,\n            std::enable_if_t<Insertable<T>::value, int> = 0>\n  raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc)\n      : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}\n\n  raw_hash_set(std::initializer_list<init_type> init,\n               const allocator_type& alloc)\n      : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}\n\n  raw_hash_set(const raw_hash_set& that)\n      : raw_hash_set(that, AllocTraits::select_on_container_copy_construction(\n                               allocator_type(that.char_alloc_ref()))) {}\n\n  raw_hash_set(const raw_hash_set& that, const allocator_type& a)\n      : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) {\n    that.AssertNotDebugCapacity();\n    if (that.empty()) return;\n    Copy(common(), GetPolicyFunctions(), that.common(),\n         [this](void* dst, const void* src) {\n           // TODO(b/413598253): type erase for trivially copyable types via\n           // PolicyTraits.\n           construct(to_slot(dst),\n                     PolicyTraits::element(\n                         static_cast<slot_type*>(const_cast<void*>(src))));\n         });\n  }\n\n  ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(\n      std::is_nothrow_copy_constructible<hasher>::value &&\n      std::is_nothrow_copy_constructible<key_equal>::value &&\n      std::is_nothrow_copy_constructible<allocator_type>::value)\n      :  // Hash, equality and allocator are copied instead of moved because\n         // `that` must be left valid. If Hash is std::function<Key>, moving it\n         // would create a nullptr functor that cannot be called.\n         // Note: we avoid using exchange for better generated code.\n        settings_(PolicyTraits::transfer_uses_memcpy() || !that.is_full_soo()\n                      ? std::move(that.common())\n                      : CommonFields{full_soo_tag_t{},\n                                     that.common().soo_has_tried_sampling()},\n                  that.hash_ref(), that.eq_ref(), that.char_alloc_ref()) {\n    if (!PolicyTraits::transfer_uses_memcpy() && that.is_full_soo()) {\n      transfer(soo_slot(), that.soo_slot());\n    }\n    that.common() = CommonFields::CreateDefault<SooEnabled()>();\n    annotate_for_bug_detection_on_move(that);\n  }\n\n  raw_hash_set(raw_hash_set&& that, const allocator_type& a)\n      : settings_(CommonFields::CreateDefault<SooEnabled()>(), that.hash_ref(),\n                  that.eq_ref(), a) {\n    if (CharAlloc(a) == that.char_alloc_ref()) {\n      swap_common(that);\n      annotate_for_bug_detection_on_move(that);\n    } else {\n      move_elements_allocs_unequal(std::move(that));\n    }\n  }\n\n  raw_hash_set& operator=(const raw_hash_set& that) {\n    that.AssertNotDebugCapacity();\n    if (ABSL_PREDICT_FALSE(this == &that)) return *this;\n    constexpr bool propagate_alloc =\n        AllocTraits::propagate_on_container_copy_assignment::value;\n    // TODO(ezb): maybe avoid allocating a new backing array if this->capacity()\n    // is an exact match for that.size(). If this->capacity() is too big, then\n    // it would make iteration very slow to reuse the allocation. Maybe we can\n    // do the same heuristic as clear() and reuse if it's small enough.\n    allocator_type alloc(propagate_alloc ? that.char_alloc_ref()\n                                         : char_alloc_ref());\n    raw_hash_set tmp(that, alloc);\n    // NOLINTNEXTLINE: not returning *this for performance.\n    return assign_impl<propagate_alloc>(std::move(tmp));\n  }\n\n  raw_hash_set& operator=(raw_hash_set&& that) noexcept(\n      AllocTraits::is_always_equal::value &&\n      std::is_nothrow_move_assignable<hasher>::value &&\n      std::is_nothrow_move_assignable<key_equal>::value) {\n    // TODO(sbenza): We should only use the operations from the noexcept clause\n    // to make sure we actually adhere to that contract.\n    // NOLINTNEXTLINE: not returning *this for performance.\n    return move_assign(\n        std::move(that),\n        typename AllocTraits::propagate_on_container_move_assignment());\n  }\n\n  ~raw_hash_set() {\n    destructor_impl();\n    if constexpr (SwisstableAssertAccessToDestroyedTable()) {\n      common().set_capacity(InvalidCapacity::kDestroyed);\n    }\n  }\n\n  iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ABSL_PREDICT_FALSE(empty())) return end();\n    if (is_small()) return single_iterator();\n    iterator it = {control(), common().slots_union(),\n                   common().generation_ptr()};\n    it.skip_empty_or_deleted();\n    ABSL_SWISSTABLE_ASSERT(IsFull(*it.control()));\n    return it;\n  }\n  iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    AssertNotDebugCapacity();\n    return iterator(common().generation_ptr());\n  }\n\n  const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_cast<raw_hash_set*>(this)->begin();\n  }\n  const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_cast<raw_hash_set*>(this)->end();\n  }\n  const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return begin();\n  }\n  const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }\n\n  bool empty() const { return !size(); }\n  size_t size() const {\n    AssertNotDebugCapacity();\n    const size_t size = common().size();\n    [[maybe_unused]] const size_t kMaxValidSize = MaxValidSize();\n    ABSL_ASSUME(size <= kMaxValidSize);\n    return size;\n  }\n  size_t capacity() const {\n    const size_t cap = common().capacity();\n    // Compiler complains when using functions in ASSUME so use local variables.\n    [[maybe_unused]] const bool kIsValid = IsValidCapacity(cap);\n    [[maybe_unused]] const size_t kDefaultCapacity = DefaultCapacity();\n    [[maybe_unused]] const size_t kMaxValidCapacity = MaxValidCapacity();\n    ABSL_ASSUME(kIsValid || cap == 0);\n    ABSL_ASSUME(cap >= kDefaultCapacity);\n    ABSL_ASSUME(cap <= kMaxValidCapacity);\n    return cap;\n  }\n  size_t max_size() const { return MaxValidSize(); }\n\n  ABSL_ATTRIBUTE_REINITIALIZES void clear() {\n    if (SwisstableGenerationsEnabled() &&\n        maybe_invalid_capacity() >= InvalidCapacity::kMovedFrom) {\n      common().set_capacity(DefaultCapacity());\n    }\n    AssertNotDebugCapacity();\n    // Iterating over this container is O(bucket_count()). When bucket_count()\n    // is much greater than size(), iteration becomes prohibitively expensive.\n    // For clear() it is more important to reuse the allocated array when the\n    // container is small because allocation takes comparatively long time\n    // compared to destruction of the elements of the container. So we pick the\n    // largest bucket_count() threshold for which iteration is still fast and\n    // past that we simply deallocate the array.\n    const size_t cap = capacity();\n    if (cap == 0) {\n      // Already guaranteed to be empty; so nothing to do.\n    } else if (is_small()) {\n      if (!empty()) {\n        destroy(single_slot());\n        decrement_small_size();\n      }\n    } else {\n      destroy_slots();\n      clear_backing_array(/*reuse=*/cap < 128);\n    }\n    common().set_reserved_growth(0);\n    common().set_reservation_size(0);\n  }\n\n  // This overload kicks in when the argument is an rvalue of insertable and\n  // decomposable type other than init_type.\n  //\n  //   flat_hash_map<std::string, int> m;\n  //   m.insert(std::make_pair(\"abc\", 42));\n  template <class T,\n            int = std::enable_if_t<IsDecomposableAndInsertable<T>::value &&\n                                       IsNotBitField<T>::value &&\n                                       !IsLifetimeBoundAssignmentFrom<T>::value,\n                                   int>()>\n  std::pair<iterator, bool> insert(T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return emplace(std::forward<T>(value));\n  }\n\n  template <class T, int&...,\n            std::enable_if_t<IsDecomposableAndInsertable<T>::value &&\n                                 IsNotBitField<T>::value &&\n                                 IsLifetimeBoundAssignmentFrom<T>::value,\n                             int> = 0>\n  std::pair<iterator, bool> insert(\n      T&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template insert<T, 0>(std::forward<T>(value));\n  }\n\n  // This overload kicks in when the argument is a bitfield or an lvalue of\n  // insertable and decomposable type.\n  //\n  //   union { int n : 1; };\n  //   flat_hash_set<int> s;\n  //   s.insert(n);\n  //\n  //   flat_hash_set<std::string> s;\n  //   const char* p = \"hello\";\n  //   s.insert(p);\n  //\n  template <class T, int = std::enable_if_t<\n                         IsDecomposableAndInsertable<const T&>::value &&\n                             !IsLifetimeBoundAssignmentFrom<const T&>::value,\n                         int>()>\n  std::pair<iterator, bool> insert(const T& value)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return emplace(value);\n  }\n  template <class T, int&...,\n            std::enable_if_t<IsDecomposableAndInsertable<const T&>::value &&\n                                 IsLifetimeBoundAssignmentFrom<const T&>::value,\n                             int> = 0>\n  std::pair<iterator, bool> insert(\n      const T& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template insert<T, 0>(value);\n  }\n\n  // This overload kicks in when the argument is an rvalue of init_type. Its\n  // purpose is to handle brace-init-list arguments.\n  //\n  //   flat_hash_map<std::string, int> s;\n  //   s.insert({\"abc\", 42});\n  std::pair<iterator, bool> insert(init_type&& value)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n    requires(!IsLifetimeBoundAssignmentFrom<init_type>::value)\n#endif\n  {\n    return emplace(std::move(value));\n  }\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n  std::pair<iterator, bool> insert(\n      init_type&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND\n    requires(IsLifetimeBoundAssignmentFrom<init_type>::value)\n  {\n    return emplace(std::move(value));\n  }\n#endif\n\n  template <class T,\n            int = std::enable_if_t<IsDecomposableAndInsertable<T>::value &&\n                                       IsNotBitField<T>::value &&\n                                       !IsLifetimeBoundAssignmentFrom<T>::value,\n                                   int>()>\n  iterator insert(const_iterator, T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return insert(std::forward<T>(value)).first;\n  }\n  template <class T, int&...,\n            std::enable_if_t<IsDecomposableAndInsertable<T>::value &&\n                                 IsNotBitField<T>::value &&\n                                 IsLifetimeBoundAssignmentFrom<T>::value,\n                             int> = 0>\n  iterator insert(const_iterator hint,\n                  T&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return this->template insert<T, 0>(hint, std::forward<T>(value));\n  }\n\n  template <class T, std::enable_if_t<\n                         IsDecomposableAndInsertable<const T&>::value, int> = 0>\n  iterator insert(const_iterator,\n                  const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return insert(value).first;\n  }\n\n  iterator insert(const_iterator,\n                  init_type&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return insert(std::move(value)).first;\n  }\n\n  template <class InputIt>\n  void insert(InputIt first, InputIt last) {\n    insert_range(first, last);\n  }\n\n  template <class T, RequiresNotInit<T> = 0,\n            std::enable_if_t<Insertable<const T&>::value, int> = 0>\n  void insert(std::initializer_list<T> ilist) {\n    insert_range(ilist.begin(), ilist.end());\n  }\n\n  void insert(std::initializer_list<init_type> ilist) {\n    insert_range(ilist.begin(), ilist.end());\n  }\n\n  insert_return_type insert(node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!node) return {end(), false, node_type()};\n    const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));\n    auto res = PolicyTraits::apply(\n        InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},\n        elem);\n    if (res.second) {\n      CommonAccess::Reset(&node);\n      return {res.first, true, node_type()};\n    } else {\n      return {res.first, false, std::move(node)};\n    }\n  }\n\n  iterator insert(const_iterator,\n                  node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto res = insert(std::move(node));\n    node = std::move(res.node);\n    return res.position;\n  }\n\n  // This overload kicks in if we can deduce the key from args. This enables us\n  // to avoid constructing value_type if an entry with the same key already\n  // exists.\n  //\n  // For example:\n  //\n  //   flat_hash_map<std::string, std::string> m = {{\"abc\", \"def\"}};\n  //   // Creates no std::string copies and makes no heap allocations.\n  //   m.emplace(\"abc\", \"xyz\");\n  template <class... Args,\n            std::enable_if_t<IsDecomposable<Args...>::value, int> = 0>\n  std::pair<iterator, bool> emplace(Args&&... args)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return PolicyTraits::apply(EmplaceDecomposable{*this},\n                               std::forward<Args>(args)...);\n  }\n\n  // This overload kicks in if we cannot deduce the key from args. It constructs\n  // value_type unconditionally and then either moves it into the table or\n  // destroys.\n  template <class... Args,\n            std::enable_if_t<!IsDecomposable<Args...>::value, int> = 0>\n  std::pair<iterator, bool> emplace(Args&&... args)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    alignas(slot_type) unsigned char raw[sizeof(slot_type)];\n    slot_type* slot = to_slot(&raw);\n\n    construct(slot, std::forward<Args>(args)...);\n    const auto& elem = PolicyTraits::element(slot);\n    return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);\n  }\n\n  template <class... Args>\n  iterator emplace_hint(const_iterator,\n                        Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return emplace(std::forward<Args>(args)...).first;\n  }\n\n  // Extension API: support for lazy emplace.\n  //\n  // Looks up key in the table. If found, returns the iterator to the element.\n  // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`,\n  // and returns an iterator to the new element.\n  //\n  // `f` must abide by several restrictions:\n  //  - it MUST call `raw_hash_set::constructor` with arguments as if a\n  //    `raw_hash_set::value_type` is constructed,\n  //  - it MUST NOT access the container before the call to\n  //    `raw_hash_set::constructor`, and\n  //  - it MUST NOT erase the lazily emplaced element.\n  // Doing any of these is undefined behavior.\n  //\n  // For example:\n  //\n  //   std::unordered_set<ArenaString> s;\n  //   // Makes ArenaStr even if \"abc\" is in the map.\n  //   s.insert(ArenaString(&arena, \"abc\"));\n  //\n  //   flat_hash_set<ArenaStr> s;\n  //   // Makes ArenaStr only if \"abc\" is not in the map.\n  //   s.lazy_emplace(\"abc\", [&](const constructor& ctor) {\n  //     ctor(&arena, \"abc\");\n  //   });\n  //\n  // WARNING: This API is currently experimental. If there is a way to implement\n  // the same thing with the rest of the API, prefer that.\n  class constructor {\n    friend class raw_hash_set;\n\n   public:\n    template <class... Args>\n    void operator()(Args&&... args) const {\n      ABSL_SWISSTABLE_ASSERT(*slot_);\n      PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...);\n      *slot_ = nullptr;\n    }\n\n   private:\n    constructor(allocator_type* a, slot_type** slot) : alloc_(a), slot_(slot) {}\n\n    allocator_type* alloc_;\n    slot_type** slot_;\n  };\n\n  template <class K = key_type, class F>\n  iterator lazy_emplace(const key_arg<K>& key,\n                        F&& f) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto res = find_or_prepare_insert(key);\n    if (res.second) {\n      slot_type* slot = res.first.slot();\n      allocator_type alloc(char_alloc_ref());\n      std::forward<F>(f)(constructor(&alloc, &slot));\n      ABSL_SWISSTABLE_ASSERT(!slot);\n    }\n    return res.first;\n  }\n\n  // Extension API: support for heterogeneous keys.\n  //\n  //   std::unordered_set<std::string> s;\n  //   // Turns \"abc\" into std::string.\n  //   s.erase(\"abc\");\n  //\n  //   flat_hash_set<std::string> s;\n  //   // Uses \"abc\" directly without copying it into std::string.\n  //   s.erase(\"abc\");\n  template <class K = key_type>\n  size_type erase(const key_arg<K>& key) {\n    auto it = find(key);\n    if (it == end()) return 0;\n    erase(it);\n    return 1;\n  }\n\n  // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,\n  // this method returns void to reduce algorithmic complexity to O(1). The\n  // iterator is invalidated so any increment should be done before calling\n  // erase (e.g. `erase(it++)`).\n  void erase(const_iterator cit) { erase(cit.inner_); }\n\n  // This overload is necessary because otherwise erase<K>(const K&) would be\n  // a better match if non-const iterator is passed as an argument.\n  void erase(iterator it) {\n    ABSL_SWISSTABLE_ASSERT(capacity() > 0);\n    AssertNotDebugCapacity();\n    it.assert_is_full(\"erase()\");\n    destroy(it.slot());\n    erase_meta_only(it);\n  }\n\n  iterator erase(const_iterator first,\n                 const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    AssertNotDebugCapacity();\n    // We check for empty first because clear_backing_array requires that\n    // capacity() > 0 as a precondition.\n    if (empty()) return end();\n    if (first == last) return last.inner_;\n    if (is_small()) {\n      destroy(single_slot());\n      erase_meta_only_small();\n      return end();\n    }\n    if (first == begin() && last == end()) {\n      // TODO(ezb): we access control bytes in destroy_slots so it could make\n      // sense to combine destroy_slots and clear_backing_array to avoid cache\n      // misses when the table is large. Note that we also do this in clear().\n      destroy_slots();\n      clear_backing_array(/*reuse=*/true);\n      common().set_reserved_growth(common().reservation_size());\n      return end();\n    }\n    while (first != last) {\n      erase(first++);\n    }\n    return last.inner_;\n  }\n\n  // Moves elements from `src` into `this`.\n  // If the element already exists in `this`, it is left unmodified in `src`.\n  template <\n      typename... Params2,\n      typename = std::enable_if_t<std::is_same_v<\n          Alloc, typename raw_hash_set<Policy, Params2...>::allocator_type>>>\n  void merge(raw_hash_set<Policy, Params2...>& src) {  // NOLINT\n    AssertNotDebugCapacity();\n    src.AssertNotDebugCapacity();\n    assert(this != &src);\n    // Returns whether insertion took place.\n    const auto insert_slot = [this](slot_type* src_slot) {\n      return PolicyTraits::apply(InsertSlot<false>{*this, std::move(*src_slot)},\n                                 PolicyTraits::element(src_slot))\n          .second;\n    };\n\n    if (src.is_small()) {\n      if (src.empty()) return;\n      if (insert_slot(src.single_slot()))\n        src.erase_meta_only_small();\n      return;\n    }\n    for (auto it = src.begin(), e = src.end(); it != e;) {\n      auto next = std::next(it);\n      if (insert_slot(it.slot())) src.erase_meta_only_large(it);\n      it = next;\n    }\n  }\n\n  template <\n      typename... Params2,\n      typename = std::enable_if_t<std::is_same_v<\n          Alloc, typename raw_hash_set<Policy, Params2...>::allocator_type>>>\n  void merge(raw_hash_set<Policy, Params2...>&& src) {  // NOLINT\n    merge(src);\n  }\n\n  node_type extract(const_iterator position) {\n    AssertNotDebugCapacity();\n    position.inner_.assert_is_full(\"extract()\");\n    allocator_type alloc(char_alloc_ref());\n    auto node = CommonAccess::Transfer<node_type>(alloc, position.slot());\n    erase_meta_only(position);\n    return node;\n  }\n\n  template <class K = key_type,\n            std::enable_if_t<!std::is_same<K, iterator>::value, int> = 0>\n  node_type extract(const key_arg<K>& key) {\n    auto it = find(key);\n    return it == end() ? node_type() : extract(const_iterator{it});\n  }\n\n  void swap(raw_hash_set& that) noexcept(\n      AllocTraits::is_always_equal::value &&\n      std::is_nothrow_swappable<hasher>::value &&\n      std::is_nothrow_swappable<key_equal>::value) {\n    AssertNotDebugCapacity();\n    that.AssertNotDebugCapacity();\n    using std::swap;\n    swap_common(that);\n    swap(hash_ref(), that.hash_ref());\n    swap(eq_ref(), that.eq_ref());\n    SwapAlloc(char_alloc_ref(), that.char_alloc_ref(),\n              typename AllocTraits::propagate_on_container_swap{});\n  }\n\n  void rehash(size_t n) {\n    Rehash(common(), GetPolicyFunctions(), (std::min)(n, MaxValidCapacity()));\n  }\n\n  void reserve(size_t n) {\n    if (ABSL_PREDICT_TRUE(n > DefaultCapacity())) {\n      ReserveTableToFitNewSize(common(), GetPolicyFunctions(),\n                               (std::min)(n, MaxValidSize()));\n    }\n  }\n\n  // Extension API: support for heterogeneous keys.\n  //\n  //   std::unordered_set<std::string> s;\n  //   // Turns \"abc\" into std::string.\n  //   s.count(\"abc\");\n  //\n  //   ch_set<std::string> s;\n  //   // Uses \"abc\" directly without copying it into std::string.\n  //   s.count(\"abc\");\n  template <class K = key_type>\n  size_t count(const key_arg<K>& key) const {\n    return find(key) == end() ? 0 : 1;\n  }\n\n  // Issues CPU prefetch instructions for the memory needed to find or insert\n  // a key.  Like all lookup functions, this support heterogeneous keys.\n  //\n  // NOTE: This is a very low level operation and should not be used without\n  // specific benchmarks indicating its importance.\n  template <class K = key_type>\n  void prefetch([[maybe_unused]] const key_arg<K>& key) const {\n    if (capacity() == DefaultCapacity()) return;\n    // Avoid probing if we won't be able to prefetch the addresses received.\n#ifdef ABSL_HAVE_PREFETCH\n    prefetch_heap_block();\n    if (is_small()) return;\n    auto seq = probe(common(), hash_of(key));\n    PrefetchToLocalCache(control() + seq.offset());\n    PrefetchToLocalCache(slot_array() + seq.offset());\n#endif  // ABSL_HAVE_PREFETCH\n  }\n\n  template <class K = key_type>\n  ABSL_DEPRECATE_AND_INLINE()\n  iterator find(const key_arg<K>& key,\n                size_t) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return find(key);\n  }\n  // The API of find() has one extension: the type of the key argument doesn't\n  // have to be key_type. This is so called heterogeneous key support.\n  template <class K = key_type>\n  iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    AssertOnFind(key);\n    if (is_small()) return find_small(key);\n    prefetch_heap_block();\n    return find_large(key, hash_of(key));\n  }\n\n  template <class K = key_type>\n  ABSL_DEPRECATE_AND_INLINE()\n  const_iterator find(const key_arg<K>& key,\n                      size_t) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return find(key);\n  }\n  template <class K = key_type>\n  const_iterator find(const key_arg<K>& key) const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_cast<raw_hash_set*>(this)->find(key);\n  }\n\n  template <class K = key_type>\n  bool contains(const key_arg<K>& key) const {\n    // Here neither the iterator returned by `find()` nor `end()` can be invalid\n    // outside of potential thread-safety issues.\n    // `find()`'s return value is constructed, used, and then destructed\n    // all in this context.\n    return !find(key).unchecked_equals(end());\n  }\n\n  template <class K = key_type>\n  std::pair<iterator, iterator> equal_range(const key_arg<K>& key)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto it = find(key);\n    if (it != end()) return {it, std::next(it)};\n    return {it, it};\n  }\n  template <class K = key_type>\n  std::pair<const_iterator, const_iterator> equal_range(\n      const key_arg<K>& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    auto it = find(key);\n    if (it != end()) return {it, std::next(it)};\n    return {it, it};\n  }\n\n  size_t bucket_count() const { return capacity(); }\n  float load_factor() const {\n    return capacity() ? static_cast<double>(size()) / capacity() : 0.0;\n  }\n  float max_load_factor() const { return 1.0f; }\n  void max_load_factor(float) {\n    // Does nothing.\n  }\n\n  hasher hash_function() const { return hash_ref(); }\n  key_equal key_eq() const { return eq_ref(); }\n  allocator_type get_allocator() const {\n    return allocator_type(char_alloc_ref());\n  }\n\n  friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) {\n    if (a.size() != b.size()) return false;\n    const raw_hash_set* outer = &a;\n    const raw_hash_set* inner = &b;\n    if (outer->capacity() > inner->capacity()) std::swap(outer, inner);\n    for (const value_type& elem : *outer) {\n      auto it = PolicyTraits::apply(FindElement{*inner}, elem);\n      if (it == inner->end()) return false;\n      // Note: we used key_equal to check for key equality in FindElement, but\n      // we may need to do an additional comparison using\n      // value_type::operator==. E.g. the keys could be equal and the\n      // mapped_types could be unequal in a map or even in a set, key_equal\n      // could ignore some fields that aren't ignored by operator==.\n      static constexpr bool kKeyEqIsValueEq =\n          std::is_same<key_type, value_type>::value &&\n          std::is_same<key_equal, hash_default_eq<key_type>>::value;\n      if (!kKeyEqIsValueEq && !(*it == elem)) return false;\n    }\n    return true;\n  }\n\n  friend bool operator!=(const raw_hash_set& a, const raw_hash_set& b) {\n    return !(a == b);\n  }\n\n  template <typename H>\n  friend typename std::enable_if<H::template is_hashable<value_type>::value,\n                                 H>::type\n  AbslHashValue(H h, const raw_hash_set& s) {\n    return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),\n                      hash_internal::WeaklyMixedInteger{s.size()});\n  }\n\n  friend void swap(raw_hash_set& a,\n                   raw_hash_set& b) noexcept(noexcept(a.swap(b))) {\n    a.swap(b);\n  }\n\n private:\n  template <class Container, typename Enabler>\n  friend struct absl::container_internal::hashtable_debug_internal::\n      HashtableDebugAccess;\n\n  friend struct absl::container_internal::HashtableFreeFunctionsAccess;\n\n  struct FindElement {\n    template <class K, class... Args>\n    const_iterator operator()(const K& key, Args&&...) const {\n      return s.find(key);\n    }\n    const raw_hash_set& s;\n  };\n\n  struct EmplaceDecomposable {\n    template <class K, class... Args>\n    std::pair<iterator, bool> operator()(const K& key, Args&&... args) const {\n      auto res = s.find_or_prepare_insert(key);\n      if (res.second) {\n        s.emplace_at(res.first, std::forward<Args>(args)...);\n      }\n      return res;\n    }\n    raw_hash_set& s;\n  };\n\n  template <bool do_destroy>\n  struct InsertSlot {\n    template <class K, class... Args>\n    std::pair<iterator, bool> operator()(const K& key, Args&&...) && {\n      auto res = s.find_or_prepare_insert(key);\n      if (res.second) {\n        s.transfer(res.first.slot(), &slot);\n      } else if (do_destroy) {\n        s.destroy(&slot);\n      }\n      return res;\n    }\n    raw_hash_set& s;\n    // Constructed slot. Either moved into place or destroyed.\n    slot_type&& slot;\n  };\n\n  template <typename... Args>\n  inline void construct(slot_type* slot, Args&&... args) {\n    common().RunWithReentrancyGuard([&] {\n      allocator_type alloc(char_alloc_ref());\n      PolicyTraits::construct(&alloc, slot, std::forward<Args>(args)...);\n    });\n  }\n  inline void destroy(slot_type* slot) {\n    common().RunWithReentrancyGuard([&] {\n      allocator_type alloc(char_alloc_ref());\n      PolicyTraits::destroy(&alloc, slot);\n    });\n  }\n  inline void transfer(slot_type* to, slot_type* from) {\n    common().RunWithReentrancyGuard([&] {\n      allocator_type alloc(char_alloc_ref());\n      PolicyTraits::transfer(&alloc, to, from);\n    });\n  }\n\n  // TODO(b/289225379): consider having a helper class that has the impls for\n  // SOO functionality.\n  template <class K = key_type>\n  iterator find_small(const key_arg<K>& key) {\n    ABSL_SWISSTABLE_ASSERT(is_small());\n    return empty() || !equal_to(key, single_slot()) ? end() : single_iterator();\n  }\n\n  template <class K = key_type>\n  iterator find_large(const key_arg<K>& key, size_t hash) {\n    ABSL_SWISSTABLE_ASSERT(!is_small());\n    auto seq = probe(common(), hash);\n    const h2_t h2 = H2(hash);\n    const ctrl_t* ctrl = control();\n    while (true) {\n#ifndef ABSL_HAVE_MEMORY_SANITIZER\n      absl::PrefetchToLocalCache(slot_array() + seq.offset());\n#endif\n      Group g{ctrl + seq.offset()};\n      for (uint32_t i : g.Match(h2)) {\n        if (ABSL_PREDICT_TRUE(equal_to(key, slot_array() + seq.offset(i))))\n          return iterator_at(seq.offset(i));\n      }\n      if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();\n      seq.next();\n      ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity() && \"full table!\");\n    }\n  }\n\n  // Returns true if the table needs to be sampled. This keeps track of whether\n  // sampling has already been evaluated and ensures that it can only return\n  // true on its first evaluation. All subsequent calls will return false.\n  //\n  // This should be called on insertion into an empty SOO table and in copy\n  // construction when the size can fit in SOO capacity.\n  bool should_sample_soo() {\n    ABSL_SWISSTABLE_ASSERT(is_soo());\n    if (!ShouldSampleHashtablezInfoForAlloc<CharAlloc>()) return false;\n    if (common().soo_has_tried_sampling()) {\n      // Already evaluated sampling on this SOO table; do not re-evaluate\n      // sampling each time it transitions from empty to full SOO state.\n      return false;\n    }\n    // TODO: b/396049910 -- consider managing this flag on the 1->0 size\n    // transition of SOO tables rather than the 0->1 transition.\n    common().set_soo_has_tried_sampling();\n    return ABSL_PREDICT_FALSE(ShouldSampleNextTable());\n  }\n\n  void clear_backing_array(bool reuse) {\n    ABSL_SWISSTABLE_ASSERT(capacity() > DefaultCapacity());\n    ClearBackingArray(common(), GetPolicyFunctions(), &char_alloc_ref(), reuse,\n                      SooEnabled());\n  }\n\n  void destroy_slots() {\n    ABSL_SWISSTABLE_ASSERT(!is_small());\n    if (PolicyTraits::template destroy_is_trivial<Alloc>()) return;\n    auto destroy_slot = [&](const ctrl_t*, void* slot) {\n      this->destroy(static_cast<slot_type*>(slot));\n    };\n    if constexpr (SwisstableAssertAccessToDestroyedTable()) {\n      CommonFields common_copy(non_soo_tag_t{}, this->common());\n      common().set_capacity(InvalidCapacity::kDestroyed);\n      IterateOverFullSlots(common_copy, sizeof(slot_type), destroy_slot);\n      common().set_capacity(common_copy.capacity());\n    } else {\n      IterateOverFullSlots(common(), sizeof(slot_type), destroy_slot);\n    }\n  }\n\n  void dealloc() {\n    ABSL_SWISSTABLE_ASSERT(capacity() > DefaultCapacity());\n    // Unpoison before returning the memory to the allocator.\n    SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * capacity());\n    infoz().Unregister();\n    DeallocateBackingArray<BackingArrayAlignment(alignof(slot_type)),\n                           CharAlloc>(&char_alloc_ref(), capacity(), control(),\n                                      sizeof(slot_type), alignof(slot_type),\n                                      common().has_infoz());\n  }\n\n  void destructor_impl() {\n    if (SwisstableGenerationsEnabled() &&\n        maybe_invalid_capacity() >= InvalidCapacity::kMovedFrom) {\n      return;\n    }\n    if (capacity() == 0) return;\n    if (is_small()) {\n      if (!empty()) {\n        ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(destroy(single_slot()));\n      }\n      if constexpr (SooEnabled()) return;\n    } else {\n      destroy_slots();\n    }\n    dealloc();\n  }\n\n  // Erases, but does not destroy, the value pointed to by `it`.\n  //\n  // This merely updates the pertinent control byte. This can be used in\n  // conjunction with Policy::transfer to move the object to another place.\n  void erase_meta_only(const_iterator it) {\n    if (is_small()) {\n      erase_meta_only_small();\n      return;\n    }\n    erase_meta_only_large(it);\n  }\n  void erase_meta_only_small() {\n    EraseMetaOnlySmall(common(), SooEnabled(), sizeof(slot_type));\n  }\n  void erase_meta_only_large(const_iterator it) {\n    EraseMetaOnlyLarge(common(), it.control(), sizeof(slot_type));\n  }\n\n  template <class K>\n  ABSL_ATTRIBUTE_ALWAYS_INLINE bool equal_to(const K& key,\n                                             slot_type* slot) const {\n    return PolicyTraits::apply(EqualElement<K, key_equal>{key, eq_ref()},\n                               PolicyTraits::element(slot));\n  }\n  template <class K>\n  ABSL_ATTRIBUTE_ALWAYS_INLINE size_t hash_of(const K& key) const {\n    return HashElement<hasher, kIsDefaultHash>{hash_ref(),\n                                               common().seed().seed()}(key);\n  }\n  ABSL_ATTRIBUTE_ALWAYS_INLINE size_t hash_of(slot_type* slot) const {\n    return PolicyTraits::apply(\n        HashElement<hasher, kIsDefaultHash>{hash_ref(), common().seed().seed()},\n        PolicyTraits::element(slot));\n  }\n\n  // Casting directly from e.g. char* to slot_type* can cause compilation errors\n  // on objective-C. This function converts to void* first, avoiding the issue.\n  static ABSL_ATTRIBUTE_ALWAYS_INLINE slot_type* to_slot(void* buf) {\n    return static_cast<slot_type*>(buf);\n  }\n\n  // Requires that lhs does not have a full SOO slot.\n  static void move_common(bool rhs_is_full_soo, CharAlloc& rhs_alloc,\n                          CommonFields& lhs, CommonFields&& rhs) {\n    if (PolicyTraits::transfer_uses_memcpy() || !rhs_is_full_soo) {\n      lhs = std::move(rhs);\n    } else {\n      lhs.move_non_heap_or_soo_fields(rhs);\n      rhs.RunWithReentrancyGuard([&] {\n        lhs.RunWithReentrancyGuard([&] {\n          PolicyTraits::transfer(&rhs_alloc, to_slot(lhs.soo_data()),\n                                 to_slot(rhs.soo_data()));\n        });\n      });\n    }\n  }\n\n  // Swaps common fields making sure to avoid memcpy'ing a full SOO slot if we\n  // aren't allowed to do so.\n  void swap_common(raw_hash_set& that) {\n    using std::swap;\n    if (PolicyTraits::transfer_uses_memcpy()) {\n      swap(common(), that.common());\n      return;\n    }\n    CommonFields tmp = CommonFields(uninitialized_tag_t{});\n    const bool that_is_full_soo = that.is_full_soo();\n    move_common(that_is_full_soo, that.char_alloc_ref(), tmp,\n                std::move(that.common()));\n    move_common(is_full_soo(), char_alloc_ref(), that.common(),\n                std::move(common()));\n    move_common(that_is_full_soo, that.char_alloc_ref(), common(),\n                std::move(tmp));\n  }\n\n  void annotate_for_bug_detection_on_move([[maybe_unused]] raw_hash_set& that) {\n    // We only enable moved-from validation when generations are enabled (rather\n    // than using NDEBUG) to avoid issues in which NDEBUG is enabled in some\n    // translation units but not in others.\n    if (SwisstableGenerationsEnabled()) {\n      that.common().set_capacity(this == &that ? InvalidCapacity::kSelfMovedFrom\n                                               : InvalidCapacity::kMovedFrom);\n    }\n    if (!SwisstableGenerationsEnabled() ||\n        maybe_invalid_capacity() == DefaultCapacity() ||\n        maybe_invalid_capacity() > kAboveMaxValidCapacity) {\n      return;\n    }\n    common().increment_generation();\n    if (!empty() && common().should_rehash_for_bug_detection_on_move()) {\n      ResizeAllocatedTableWithSeedChange(common(), GetPolicyFunctions(),\n                                         capacity());\n    }\n  }\n\n  template <bool propagate_alloc>\n  raw_hash_set& assign_impl(raw_hash_set&& that) {\n    // We don't bother checking for this/that aliasing. We just need to avoid\n    // breaking the invariants in that case.\n    destructor_impl();\n    move_common(that.is_full_soo(), that.char_alloc_ref(), common(),\n                std::move(that.common()));\n    hash_ref() = that.hash_ref();\n    eq_ref() = that.eq_ref();\n    CopyAlloc(char_alloc_ref(), that.char_alloc_ref(),\n              std::integral_constant<bool, propagate_alloc>());\n    that.common() = CommonFields::CreateDefault<SooEnabled()>();\n    annotate_for_bug_detection_on_move(that);\n    return *this;\n  }\n\n  raw_hash_set& move_elements_allocs_unequal(raw_hash_set&& that) {\n    const size_t size = that.size();\n    if (size == 0) return *this;\n    reserve(size);\n    for (iterator it = that.begin(); it != that.end(); ++it) {\n      insert(std::move(PolicyTraits::element(it.slot())));\n      that.destroy(it.slot());\n    }\n    if (!that.is_soo()) that.dealloc();\n    that.common() = CommonFields::CreateDefault<SooEnabled()>();\n    annotate_for_bug_detection_on_move(that);\n    return *this;\n  }\n\n  raw_hash_set& move_assign(raw_hash_set&& that,\n                            std::true_type /*propagate_alloc*/) {\n    return assign_impl<true>(std::move(that));\n  }\n  raw_hash_set& move_assign(raw_hash_set&& that,\n                            std::false_type /*propagate_alloc*/) {\n    if (char_alloc_ref() == that.char_alloc_ref()) {\n      return assign_impl<false>(std::move(that));\n    }\n    // Aliasing can't happen here because allocs would compare equal above.\n    assert(this != &that);\n    destructor_impl();\n    // We can't take over that's memory so we need to move each element.\n    // While moving elements, this should have that's hash/eq so copy hash/eq\n    // before moving elements.\n    hash_ref() = that.hash_ref();\n    eq_ref() = that.eq_ref();\n    return move_elements_allocs_unequal(std::move(that));\n  }\n\n  template <class K>\n  std::pair<iterator, bool> find_or_prepare_insert_soo(const K& key) {\n    ABSL_SWISSTABLE_ASSERT(is_soo());\n    bool force_sampling;\n    if (empty()) {\n      if (!should_sample_soo()) {\n        common().set_full_soo();\n        return {single_iterator(), true};\n      }\n      force_sampling = true;\n    } else if (equal_to(key, single_slot())) {\n      return {single_iterator(), false};\n    } else {\n      force_sampling = false;\n    }\n    ABSL_SWISSTABLE_ASSERT(capacity() == 1);\n    constexpr bool kUseMemcpy =\n        PolicyTraits::transfer_uses_memcpy() && SooEnabled();\n    size_t index = GrowSooTableToNextCapacityAndPrepareInsert<\n        kUseMemcpy ? OptimalMemcpySizeForSooSlotTransfer(sizeof(slot_type)) : 0,\n        kUseMemcpy>(common(), GetPolicyFunctions(),\n                    HashKey<hasher, K, kIsDefaultHash>{hash_ref(), key},\n                    force_sampling);\n    return {iterator_at(index), true};\n  }\n\n  template <class K>\n  std::pair<iterator, bool> find_or_prepare_insert_small(const K& key) {\n    ABSL_SWISSTABLE_ASSERT(is_small());\n    if constexpr (SooEnabled()) {\n      return find_or_prepare_insert_soo(key);\n    }\n    if (!empty()) {\n      if (equal_to(key, single_slot())) {\n        return {single_iterator(), false};\n      }\n    }\n    return {iterator_at_ptr(PrepareInsertSmallNonSoo(\n                common(), GetPolicyFunctions(),\n                HashKey<hasher, K, kIsDefaultHash>{hash_ref(), key})),\n            true};\n  }\n\n  template <class K>\n  std::pair<iterator, bool> find_or_prepare_insert_large(const K& key) {\n    ABSL_SWISSTABLE_ASSERT(!is_soo());\n    prefetch_heap_block();\n    const size_t hash = hash_of(key);\n    auto seq = probe(common(), hash);\n    const h2_t h2 = H2(hash);\n    const ctrl_t* ctrl = control();\n    size_t index;\n    bool inserted;\n    // We use a lambda function to be able to exit from the nested loop without\n    // duplicating generated code for the return statement (e.g. iterator_at).\n    [&]() ABSL_ATTRIBUTE_ALWAYS_INLINE {\n      while (true) {\n#ifndef ABSL_HAVE_MEMORY_SANITIZER\n        absl::PrefetchToLocalCache(slot_array() + seq.offset());\n#endif\n        Group g{ctrl + seq.offset()};\n        for (uint32_t i : g.Match(h2)) {\n          if (ABSL_PREDICT_TRUE(equal_to(key, slot_array() + seq.offset(i)))) {\n            index = seq.offset(i);\n            inserted = false;\n            return;\n          }\n        }\n        auto mask_empty = g.MaskEmpty();\n        if (ABSL_PREDICT_TRUE(mask_empty)) {\n          size_t target_group_offset = seq.offset();\n          index = SwisstableGenerationsEnabled()\n                      ? PrepareInsertLargeGenerationsEnabled(\n                            common(), GetPolicyFunctions(), hash, mask_empty,\n                            FindInfo{target_group_offset, seq.index()},\n                            HashKey<hasher, K, kIsDefaultHash>{hash_ref(), key})\n                      : PrepareInsertLarge(\n                            common(), GetPolicyFunctions(), hash, mask_empty,\n                            FindInfo{target_group_offset, seq.index()});\n          inserted = true;\n          return;\n        }\n        seq.next();\n        ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity() && \"full table!\");\n      }\n    }();\n    return {iterator_at(index), inserted};\n  }\n\n  template <class InputIt>\n  void insert_range(InputIt first, InputIt last) {\n    for (; first != last; ++first) emplace(*first);\n  }\n\n protected:\n  // Asserts for correctness that we run on find/find_or_prepare_insert.\n  template <class K>\n  void AssertOnFind([[maybe_unused]] const K& key) {\n    AssertHashEqConsistent(key);\n    AssertNotDebugCapacity();\n  }\n\n  // Asserts that the capacity is not a sentinel invalid value.\n  void AssertNotDebugCapacity() const {\n#ifdef NDEBUG\n    if (!SwisstableGenerationsEnabled()) {\n      return;\n    }\n#endif\n    const size_t cap = maybe_invalid_capacity();\n    if (ABSL_PREDICT_TRUE(cap < InvalidCapacity::kAboveMaxValidCapacity)) {\n      return;\n    }\n    assert(cap != InvalidCapacity::kReentrance &&\n           \"Reentrant container access during element construction/destruction \"\n           \"is not allowed.\");\n    if constexpr (SwisstableAssertAccessToDestroyedTable()) {\n      if (cap == InvalidCapacity::kDestroyed) {\n        ABSL_RAW_LOG(FATAL, \"Use of destroyed hash table.\");\n      }\n    }\n    if (SwisstableGenerationsEnabled() &&\n        ABSL_PREDICT_FALSE(cap >= InvalidCapacity::kMovedFrom)) {\n      if (cap == InvalidCapacity::kSelfMovedFrom) {\n        // If this log triggers, then a hash table was move-assigned to itself\n        // and then used again later without being reinitialized.\n        ABSL_RAW_LOG(FATAL, \"Use of self-move-assigned hash table.\");\n      }\n      ABSL_RAW_LOG(FATAL, \"Use of moved-from hash table.\");\n    }\n  }\n\n  // Asserts that hash and equal functors provided by the user are consistent,\n  // meaning that `eq(k1, k2)` implies `hash(k1)==hash(k2)`.\n  template <class K>\n  void AssertHashEqConsistent(const K& key) {\n#ifdef NDEBUG\n    return;\n#endif\n    // If the hash/eq functors are known to be consistent, then skip validation.\n    if (std::is_same<hasher, absl::container_internal::StringHash>::value &&\n        std::is_same<key_equal, absl::container_internal::StringEq>::value) {\n      return;\n    }\n    if (std::is_scalar<key_type>::value &&\n        std::is_same<hasher, absl::Hash<key_type>>::value &&\n        std::is_same<key_equal, std::equal_to<key_type>>::value) {\n      return;\n    }\n    if (empty()) return;\n\n    const size_t hash_of_arg = hash_of(key);\n    const auto assert_consistent = [&](const ctrl_t*, void* slot) {\n      const bool is_key_equal = equal_to(key, to_slot(slot));\n      if (!is_key_equal) return;\n\n      [[maybe_unused]] const bool is_hash_equal =\n          hash_of_arg == hash_of(to_slot(slot));\n      assert((!is_key_equal || is_hash_equal) &&\n             \"eq(k1, k2) must imply that hash(k1) == hash(k2). \"\n             \"hash/eq functors are inconsistent.\");\n    };\n\n    if (is_small()) {\n      assert_consistent(/*unused*/ nullptr, single_slot());\n      return;\n    }\n    // We only do validation for small tables so that it's constant time.\n    if (capacity() > 16) return;\n    IterateOverFullSlots(common(), sizeof(slot_type), assert_consistent);\n  }\n\n  // Attempts to find `key` in the table; if it isn't found, returns an iterator\n  // where the value can be inserted into, with the control byte already set to\n  // `key`'s H2. Returns a bool indicating whether an insertion can take place.\n  template <class K>\n  std::pair<iterator, bool> find_or_prepare_insert(const K& key) {\n    AssertOnFind(key);\n    if (is_small()) return find_or_prepare_insert_small(key);\n    return find_or_prepare_insert_large(key);\n  }\n\n  // Constructs the value in the space pointed by the iterator. This only works\n  // after an unsuccessful find_or_prepare_insert() and before any other\n  // modifications happen in the raw_hash_set.\n  //\n  // PRECONDITION: iter was returned from find_or_prepare_insert(k), where k is\n  // the key decomposed from `forward<Args>(args)...`, and the bool returned by\n  // find_or_prepare_insert(k) was true.\n  // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).\n  template <class... Args>\n  void emplace_at(iterator iter, Args&&... args) {\n    construct(iter.slot(), std::forward<Args>(args)...);\n\n    // When is_small, find calls find_small and if size is 0, then it will\n    // return an end iterator. This can happen in the raw_hash_set copy ctor.\n    assert((is_small() ||\n            PolicyTraits::apply(FindElement{*this}, *iter) == iter) &&\n           \"constructed value does not match the lookup key\");\n  }\n\n  iterator iterator_at(size_t i) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return {control() + i, slot_array() + i, common().generation_ptr()};\n  }\n  const_iterator iterator_at(size_t i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return const_cast<raw_hash_set*>(this)->iterator_at(i);\n  }\n  iterator iterator_at_ptr(std::pair<ctrl_t*, void*> ptrs)\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return {ptrs.first, to_slot(ptrs.second), common().generation_ptr()};\n  }\n\n  reference unchecked_deref(iterator it) { return it.unchecked_deref(); }\n\n private:\n  friend struct RawHashSetTestOnlyAccess;\n\n  // The number of slots we can still fill without needing to rehash.\n  //\n  // This is stored separately due to tombstones: we do not include tombstones\n  // in the growth capacity, because we'd like to rehash when the table is\n  // otherwise filled with tombstones: otherwise, probe sequences might get\n  // unacceptably long without triggering a rehash. Callers can also force a\n  // rehash via the standard `rehash(0)`, which will recompute this value as a\n  // side-effect.\n  //\n  // See `CapacityToGrowth()`.\n  size_t growth_left() const {\n    return common().growth_left();\n  }\n\n  GrowthInfo& growth_info() {\n    return common().growth_info();\n  }\n  GrowthInfo growth_info() const {\n    return common().growth_info();\n  }\n\n  // Prefetch the heap-allocated memory region to resolve potential TLB and\n  // cache misses. This is intended to overlap with execution of calculating the\n  // hash for a key.\n  void prefetch_heap_block() const {\n    ABSL_SWISSTABLE_ASSERT(!is_soo());\n#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)\n    __builtin_prefetch(control(), 0, 1);\n#endif\n  }\n\n  CommonFields& common() { return settings_.template get<0>(); }\n  const CommonFields& common() const { return settings_.template get<0>(); }\n\n  // For use when the capacity is potentially invalid so we shouldn't assume\n  // that the capacity is valid (which is done in `capacity()`).\n  size_t maybe_invalid_capacity() const { return common().capacity(); }\n  ctrl_t* control() const {\n    ABSL_SWISSTABLE_ASSERT(!is_soo());\n    return common().control();\n  }\n  slot_type* slot_array() const {\n    ABSL_SWISSTABLE_ASSERT(!is_soo());\n    return static_cast<slot_type*>(common().slot_array());\n  }\n  slot_type* soo_slot() {\n    ABSL_SWISSTABLE_ASSERT(is_soo());\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(\n        static_cast<slot_type*>(common().soo_data()));\n  }\n  const slot_type* soo_slot() const {\n    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(\n        const_cast<raw_hash_set*>(this)->soo_slot());\n  }\n  slot_type* single_slot() {\n    ABSL_SWISSTABLE_ASSERT(is_small());\n    return SooEnabled() ? soo_slot() : slot_array();\n  }\n  const slot_type* single_slot() const {\n    return const_cast<raw_hash_set*>(this)->single_slot();\n  }\n  void decrement_small_size() {\n    ABSL_SWISSTABLE_ASSERT(is_small());\n    SooEnabled() ? common().set_empty_soo() : common().decrement_size();\n    if (!SooEnabled()) {\n      SanitizerPoisonObject(single_slot());\n    }\n  }\n  iterator single_iterator() {\n    return {SooControl(), single_slot(), common().generation_ptr()};\n  }\n  const_iterator single_iterator() const {\n    return const_cast<raw_hash_set*>(this)->single_iterator();\n  }\n  HashtablezInfoHandle infoz() {\n    ABSL_SWISSTABLE_ASSERT(!is_soo());\n    return common().infoz();\n  }\n\n  hasher& hash_ref() { return settings_.template get<1>(); }\n  const hasher& hash_ref() const { return settings_.template get<1>(); }\n  key_equal& eq_ref() { return settings_.template get<2>(); }\n  const key_equal& eq_ref() const { return settings_.template get<2>(); }\n  CharAlloc& char_alloc_ref() { return settings_.template get<3>(); }\n  const CharAlloc& char_alloc_ref() const {\n    return settings_.template get<3>();\n  }\n\n  static void* get_char_alloc_ref_fn(CommonFields& common) {\n    auto* h = reinterpret_cast<raw_hash_set*>(&common);\n    return &h->char_alloc_ref();\n  }\n  static void* get_hash_ref_fn(CommonFields& common) {\n    auto* h = reinterpret_cast<raw_hash_set*>(&common);\n    // TODO(b/397453582): Remove support for const hasher.\n    return const_cast<std::remove_const_t<hasher>*>(&h->hash_ref());\n  }\n  static void transfer_n_slots_fn(void* set, void* dst, void* src,\n                                  size_t count) {\n    auto* src_slot = to_slot(src);\n    auto* dst_slot = to_slot(dst);\n\n    auto* h = static_cast<raw_hash_set*>(set);\n    for (; count > 0; --count, ++src_slot, ++dst_slot) {\n      h->transfer(dst_slot, src_slot);\n    }\n  }\n\n  // TODO(b/382423690): Try to type erase entire function or at least type erase\n  // by GetKey + Hash for memcpyable types.\n  // TODO(b/382423690): Try to type erase for big slots: sizeof(slot_type) > 16.\n  static void transfer_unprobed_elements_to_next_capacity_fn(\n      CommonFields& common, const ctrl_t* old_ctrl, void* old_slots,\n      void* probed_storage,\n      void (*encode_probed_element)(void* probed_storage, h2_t h2,\n                                    size_t source_offset, size_t h1)) {\n    const size_t new_capacity = common.capacity();\n    const size_t old_capacity = PreviousCapacity(new_capacity);\n    ABSL_ASSUME(old_capacity + 1 >= Group::kWidth);\n    ABSL_ASSUME((old_capacity + 1) % Group::kWidth == 0);\n\n    auto* set = reinterpret_cast<raw_hash_set*>(&common);\n    slot_type* old_slots_ptr = to_slot(old_slots);\n    ctrl_t* new_ctrl = common.control();\n    slot_type* new_slots = set->slot_array();\n\n    for (size_t group_index = 0; group_index < old_capacity;\n         group_index += Group::kWidth) {\n      GroupFullEmptyOrDeleted old_g(old_ctrl + group_index);\n      std::memset(new_ctrl + group_index, static_cast<int8_t>(ctrl_t::kEmpty),\n                  Group::kWidth);\n      std::memset(new_ctrl + group_index + old_capacity + 1,\n                  static_cast<int8_t>(ctrl_t::kEmpty), Group::kWidth);\n      // TODO(b/382423690): try to type erase everything outside of the loop.\n      // We will share a lot of code in expense of one function call per group.\n      for (auto in_fixed_group_index : old_g.MaskFull()) {\n        size_t old_index = group_index + in_fixed_group_index;\n        slot_type* old_slot = old_slots_ptr + old_index;\n        // TODO(b/382423690): try to avoid entire hash calculation since we need\n        // only one new bit of h1.\n        size_t hash = set->hash_of(old_slot);\n        size_t h1 = H1(hash);\n        h2_t h2 = H2(hash);\n        size_t new_index = TryFindNewIndexWithoutProbing(\n            h1, old_index, old_capacity, new_ctrl, new_capacity);\n        // Note that encode_probed_element is allowed to use old_ctrl buffer\n        // till and included the old_index.\n        if (ABSL_PREDICT_FALSE(new_index == kProbedElementIndexSentinel)) {\n          encode_probed_element(probed_storage, h2, old_index, h1);\n          continue;\n        }\n        ABSL_SWISSTABLE_ASSERT((new_index & old_capacity) <= old_index);\n        ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[new_index]));\n        new_ctrl[new_index] = static_cast<ctrl_t>(h2);\n        auto* new_slot = new_slots + new_index;\n        SanitizerUnpoisonMemoryRegion(new_slot, sizeof(slot_type));\n        set->transfer(new_slot, old_slot);\n        SanitizerPoisonMemoryRegion(old_slot, sizeof(slot_type));\n      }\n    }\n  }\n\n  static const PolicyFunctions& GetPolicyFunctions() {\n    static_assert(sizeof(slot_type) <= (std::numeric_limits<uint32_t>::max)(),\n                  \"Slot size is too large. Use std::unique_ptr for value type \"\n                  \"or use absl::node_hash_{map,set}.\");\n    static_assert(alignof(slot_type) <=\n                  size_t{(std::numeric_limits<uint16_t>::max)()});\n    static_assert(sizeof(key_type) <=\n                  size_t{(std::numeric_limits<uint32_t>::max)()});\n    static_assert(sizeof(value_type) <=\n                  size_t{(std::numeric_limits<uint32_t>::max)()});\n    static constexpr size_t kBackingArrayAlignment =\n        BackingArrayAlignment(alignof(slot_type));\n    static constexpr PolicyFunctions value = {\n        static_cast<uint32_t>(sizeof(key_type)),\n        static_cast<uint32_t>(sizeof(value_type)),\n        static_cast<uint32_t>(sizeof(slot_type)),\n        static_cast<uint16_t>(alignof(slot_type)), SooEnabled(),\n        ShouldSampleHashtablezInfoForAlloc<CharAlloc>(),\n        // TODO(b/328722020): try to type erase\n        // for standard layout and alignof(Hash) <= alignof(CommonFields).\n        std::is_empty_v<hasher> ? &GetRefForEmptyClass\n                                : &raw_hash_set::get_hash_ref_fn,\n        PolicyTraits::template get_hash_slot_fn<hasher, kIsDefaultHash>(),\n        PolicyTraits::transfer_uses_memcpy()\n            ? TransferNRelocatable<sizeof(slot_type)>\n            : &raw_hash_set::transfer_n_slots_fn,\n        std::is_empty_v<Alloc> ? &GetRefForEmptyClass\n                               : &raw_hash_set::get_char_alloc_ref_fn,\n        &AllocateBackingArray<kBackingArrayAlignment, CharAlloc>,\n        &DeallocateBackingArray<kBackingArrayAlignment, CharAlloc>,\n        &raw_hash_set::transfer_unprobed_elements_to_next_capacity_fn};\n    return value;\n  }\n\n  // Bundle together CommonFields plus other objects which might be empty.\n  // CompressedTuple will ensure that sizeof is not affected by any of the empty\n  // fields that occur after CommonFields.\n  absl::container_internal::CompressedTuple<CommonFields, hasher, key_equal,\n                                            CharAlloc>\n      settings_{CommonFields::CreateDefault<SooEnabled()>(), hasher{},\n                key_equal{}, CharAlloc{}};\n};\n\n// Friend access for free functions in raw_hash_set.h.\nstruct HashtableFreeFunctionsAccess {\n  template <class Predicate, typename Set>\n  static typename Set::size_type EraseIf(Predicate& pred, Set* c) {\n    if (c->empty()) {\n      return 0;\n    }\n    if (c->is_small()) {\n      auto it = c->single_iterator();\n      if (!pred(*it)) {\n        ABSL_SWISSTABLE_ASSERT(c->size() == 1 &&\n                               \"hash table was modified unexpectedly\");\n        return 0;\n      }\n      c->destroy(it.slot());\n      c->erase_meta_only_small();\n      return 1;\n    }\n    [[maybe_unused]] const size_t original_size_for_assert = c->size();\n    size_t num_deleted = 0;\n    using SlotType = typename Set::slot_type;\n    IterateOverFullSlots(\n        c->common(), sizeof(SlotType),\n        [&](const ctrl_t* ctrl, void* slot_void) {\n          auto* slot = static_cast<SlotType*>(slot_void);\n          if (pred(Set::PolicyTraits::element(slot))) {\n            c->destroy(slot);\n            EraseMetaOnlyLarge(c->common(), ctrl, sizeof(*slot));\n            ++num_deleted;\n          }\n        });\n    // NOTE: IterateOverFullSlots allow removal of the current element, so we\n    // verify the size additionally here.\n    ABSL_SWISSTABLE_ASSERT(original_size_for_assert - num_deleted ==\n                               c->size() &&\n                           \"hash table was modified unexpectedly\");\n    return num_deleted;\n  }\n\n  template <class Callback, typename Set>\n  static void ForEach(Callback& cb, Set* c) {\n    if (c->empty()) {\n      return;\n    }\n    if (c->is_small()) {\n      cb(*c->single_iterator());\n      return;\n    }\n    using SlotType = typename Set::slot_type;\n    using ElementTypeWithConstness = decltype(*c->begin());\n    IterateOverFullSlots(\n        c->common(), sizeof(SlotType), [&cb](const ctrl_t*, void* slot) {\n          ElementTypeWithConstness& element =\n              Set::PolicyTraits::element(static_cast<SlotType*>(slot));\n          cb(element);\n        });\n  }\n};\n\n// Erases all elements that satisfy the predicate `pred` from the container `c`.\ntemplate <typename P, typename... Params, typename Predicate>\ntypename raw_hash_set<P, Params...>::size_type EraseIf(\n    Predicate& pred, raw_hash_set<P, Params...>* c) {\n  return HashtableFreeFunctionsAccess::EraseIf(pred, c);\n}\n\n// Calls `cb` for all elements in the container `c`.\ntemplate <typename P, typename... Params, typename Callback>\nvoid ForEach(Callback& cb, raw_hash_set<P, Params...>* c) {\n  return HashtableFreeFunctionsAccess::ForEach(cb, c);\n}\ntemplate <typename P, typename... Params, typename Callback>\nvoid ForEach(Callback& cb, const raw_hash_set<P, Params...>* c) {\n  return HashtableFreeFunctionsAccess::ForEach(cb, c);\n}\n\nnamespace hashtable_debug_internal {\ntemplate <typename Set>\nstruct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {\n  using Traits = typename Set::PolicyTraits;\n  using Slot = typename Traits::slot_type;\n\n  constexpr static bool kIsDefaultHash = Set::kIsDefaultHash;\n\n  static size_t GetNumProbes(const Set& set,\n                             const typename Set::key_type& key) {\n    if (set.is_small()) return 0;\n    size_t num_probes = 0;\n    const size_t hash = set.hash_of(key);\n    auto seq = probe(set.common(), hash);\n    const h2_t h2 = H2(hash);\n    const ctrl_t* ctrl = set.control();\n    while (true) {\n      container_internal::Group g{ctrl + seq.offset()};\n      for (uint32_t i : g.Match(h2)) {\n        if (set.equal_to(key, set.slot_array() + seq.offset(i)))\n          return num_probes;\n        ++num_probes;\n      }\n      if (g.MaskEmpty()) return num_probes;\n      seq.next();\n      ++num_probes;\n    }\n  }\n\n  static size_t AllocatedByteSize(const Set& c) {\n    size_t capacity = c.capacity();\n    if (capacity == 0) return 0;\n    size_t m =\n        c.is_soo() ? 0 : c.common().alloc_size(sizeof(Slot), alignof(Slot));\n\n    size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));\n    if (per_slot != ~size_t{}) {\n      m += per_slot * c.size();\n    } else {\n      for (auto it = c.begin(); it != c.end(); ++it) {\n        m += Traits::space_used(it.slot());\n      }\n    }\n    return m;\n  }\n};\n\n}  // namespace hashtable_debug_internal\n\n// Extern template instantiations reduce binary size and linker input size.\n// Function definition is in raw_hash_set.cc.\nextern template size_t GrowSooTableToNextCapacityAndPrepareInsert<0, false>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\nextern template size_t GrowSooTableToNextCapacityAndPrepareInsert<1, true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\nextern template size_t GrowSooTableToNextCapacityAndPrepareInsert<4, true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\nextern template size_t GrowSooTableToNextCapacityAndPrepareInsert<8, true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\n#if UINTPTR_MAX == UINT64_MAX\nextern template size_t GrowSooTableToNextCapacityAndPrepareInsert<16, true>(\n    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,\n    bool);\n#endif\n\nextern template void* AllocateBackingArray<\n    BackingArrayAlignment(alignof(size_t)), std::allocator<char>>(void* alloc,\n                                                                  size_t n);\nextern template void DeallocateBackingArray<\n    BackingArrayAlignment(alignof(size_t)), std::allocator<char>>(\n    void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,\n    size_t slot_align, bool had_infoz);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_SWISSTABLE_ENABLE_GENERATIONS\n#undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED\n#undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN\n#undef ABSL_SWISSTABLE_ASSERT\n\n#endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set_allocator_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstdint>\n#include <functional>\n#include <limits>\n#include <memory>\n#include <ostream>\n#include <set>\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/raw_hash_set.h\"\n#include \"absl/container/internal/tracked.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\nusing ::testing::AnyOf;\n\nenum AllocSpec {\n  kPropagateOnCopy = 1,\n  kPropagateOnMove = 2,\n  kPropagateOnSwap = 4,\n};\n\nstruct AllocState {\n  size_t num_allocs = 0;\n  std::set<void*> owned;\n};\n\ntemplate <class T,\n          int Spec = kPropagateOnCopy | kPropagateOnMove | kPropagateOnSwap>\nclass CheckedAlloc {\n public:\n  template <class, int>\n  friend class CheckedAlloc;\n\n  using value_type = T;\n\n  CheckedAlloc() {}\n  explicit CheckedAlloc(size_t id) : id_(id) {}\n  CheckedAlloc(const CheckedAlloc&) = default;\n  CheckedAlloc& operator=(const CheckedAlloc&) = default;\n\n  template <class U>\n  CheckedAlloc(const CheckedAlloc<U, Spec>& that)\n      : id_(that.id_), state_(that.state_) {}\n\n  template <class U>\n  struct rebind {\n    using other = CheckedAlloc<U, Spec>;\n  };\n\n  using propagate_on_container_copy_assignment =\n      std::integral_constant<bool, (Spec & kPropagateOnCopy) != 0>;\n\n  using propagate_on_container_move_assignment =\n      std::integral_constant<bool, (Spec & kPropagateOnMove) != 0>;\n\n  using propagate_on_container_swap =\n      std::integral_constant<bool, (Spec & kPropagateOnSwap) != 0>;\n\n  CheckedAlloc select_on_container_copy_construction() const {\n    if (Spec & kPropagateOnCopy) return *this;\n    return {};\n  }\n\n  T* allocate(size_t n) {\n    T* ptr = std::allocator<T>().allocate(n);\n    track_alloc(ptr);\n    return ptr;\n  }\n  void deallocate(T* ptr, size_t n) {\n    memset(ptr, 0, n * sizeof(T));  // The freed memory must be unpoisoned.\n    track_dealloc(ptr);\n    return std::allocator<T>().deallocate(ptr, n);\n  }\n\n  friend bool operator==(const CheckedAlloc& a, const CheckedAlloc& b) {\n    return a.id_ == b.id_;\n  }\n  friend bool operator!=(const CheckedAlloc& a, const CheckedAlloc& b) {\n    return !(a == b);\n  }\n\n  size_t num_allocs() const { return state_->num_allocs; }\n\n  void swap(CheckedAlloc& that) {\n    using std::swap;\n    swap(id_, that.id_);\n    swap(state_, that.state_);\n  }\n\n  friend void swap(CheckedAlloc& a, CheckedAlloc& b) { a.swap(b); }\n\n  friend std::ostream& operator<<(std::ostream& o, const CheckedAlloc& a) {\n    return o << \"alloc(\" << a.id_ << \")\";\n  }\n\n private:\n  void track_alloc(void* ptr) {\n    AllocState* state = state_.get();\n    ++state->num_allocs;\n    if (!state->owned.insert(ptr).second)\n      ADD_FAILURE() << *this << \" got previously allocated memory: \" << ptr;\n  }\n  void track_dealloc(void* ptr) {\n    if (state_->owned.erase(ptr) != 1)\n      ADD_FAILURE() << *this\n                    << \" deleting memory owned by another allocator: \" << ptr;\n  }\n\n  size_t id_ = std::numeric_limits<size_t>::max();\n\n  std::shared_ptr<AllocState> state_ = std::make_shared<AllocState>();\n};\n\nstruct Identity {\n  size_t operator()(int32_t v) const { return static_cast<size_t>(v); }\n};\n\nstruct Policy {\n  using slot_type = Tracked<int32_t>;\n  using init_type = Tracked<int32_t>;\n  using key_type = int32_t;\n\n  using DefaultHash = void;\n  using DefaultEq = void;\n  using DefaultAlloc = void;\n\n  template <class allocator_type, class... Args>\n  static void construct(allocator_type* alloc, slot_type* slot,\n                        Args&&... args) {\n    std::allocator_traits<allocator_type>::construct(\n        *alloc, slot, std::forward<Args>(args)...);\n  }\n\n  template <class allocator_type>\n  static void destroy(allocator_type* alloc, slot_type* slot) {\n    std::allocator_traits<allocator_type>::destroy(*alloc, slot);\n  }\n\n  template <class allocator_type>\n  static void transfer(allocator_type* alloc, slot_type* new_slot,\n                       slot_type* old_slot) {\n    construct(alloc, new_slot, std::move(*old_slot));\n    destroy(alloc, old_slot);\n  }\n\n  template <class F>\n  static auto apply(F&& f, int32_t v) -> decltype(std::forward<F>(f)(v, v)) {\n    return std::forward<F>(f)(v, v);\n  }\n\n  template <class F>\n  static auto apply(F&& f, const slot_type& v)\n      -> decltype(std::forward<F>(f)(v.val(), v)) {\n    return std::forward<F>(f)(v.val(), v);\n  }\n\n  template <class F>\n  static auto apply(F&& f, slot_type&& v)\n      -> decltype(std::forward<F>(f)(v.val(), std::move(v))) {\n    return std::forward<F>(f)(v.val(), std::move(v));\n  }\n\n  static slot_type& element(slot_type* slot) { return *slot; }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\ntemplate <int Spec>\nstruct PropagateTest : public ::testing::Test {\n  using Alloc = CheckedAlloc<Tracked<int32_t>, Spec>;\n\n  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, Alloc>;\n\n  PropagateTest() {\n    EXPECT_EQ(a1, t1.get_allocator());\n    EXPECT_NE(a2, t1.get_allocator());\n  }\n\n  Alloc a1 = Alloc(1);\n  Table t1 = Table(0, a1);\n  Alloc a2 = Alloc(2);\n};\n\nusing PropagateOnAll =\n    PropagateTest<kPropagateOnCopy | kPropagateOnMove | kPropagateOnSwap>;\nusing NoPropagateOnCopy = PropagateTest<kPropagateOnMove | kPropagateOnSwap>;\nusing NoPropagateOnMove = PropagateTest<kPropagateOnCopy | kPropagateOnSwap>;\n\nTEST_F(PropagateOnAll, Empty) { EXPECT_EQ(0, a1.num_allocs()); }\n\nTEST_F(PropagateOnAll, InsertAllocates) {\n  auto it = t1.insert(0).first;\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, InsertDecomposes) {\n  auto it = t1.insert(0).first;\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(0, it->num_copies());\n\n  EXPECT_FALSE(t1.insert(0).second);\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, RehashMoves) {\n  auto it = t1.insert(0).first;\n  EXPECT_EQ(0, it->num_moves());\n  t1.rehash(2 * t1.capacity());\n  EXPECT_EQ(2, a1.num_allocs());\n  it = t1.find(0);\n  EXPECT_EQ(1, it->num_moves());\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, CopyConstructor) {\n  auto it = t1.insert(0).first;\n  Table u(t1);\n  EXPECT_EQ(2, a1.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(NoPropagateOnCopy, CopyConstructor) {\n  auto it = t1.insert(0).first;\n  Table u(t1);\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(1, u.get_allocator().num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, CopyConstructorWithSameAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(t1, a1);\n  EXPECT_EQ(2, a1.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(NoPropagateOnCopy, CopyConstructorWithSameAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(t1, a1);\n  EXPECT_EQ(2, a1.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, CopyConstructorWithDifferentAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(t1, a2);\n  EXPECT_EQ(a2, u.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(1, a2.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(NoPropagateOnCopy, CopyConstructorWithDifferentAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(t1, a2);\n  EXPECT_EQ(a2, u.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(1, a2.num_allocs());\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, MoveConstructor) {\n  t1.insert(0);\n  Table u(std::move(t1));\n  auto it = u.begin();\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(NoPropagateOnMove, MoveConstructor) {\n  t1.insert(0);\n  Table u(std::move(t1));\n  auto it = u.begin();\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, MoveConstructorWithSameAlloc) {\n  t1.insert(0);\n  Table u(std::move(t1), a1);\n  auto it = u.begin();\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(NoPropagateOnMove, MoveConstructorWithSameAlloc) {\n  t1.insert(0);\n  Table u(std::move(t1), a1);\n  auto it = u.begin();\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, MoveConstructorWithDifferentAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(std::move(t1), a2);\n  it = u.find(0);\n  EXPECT_EQ(a2, u.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_THAT(a2.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(1, 2));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(NoPropagateOnMove, MoveConstructorWithDifferentAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(std::move(t1), a2);\n  it = u.find(0);\n  EXPECT_EQ(a2, u.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_THAT(a2.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(1, 2));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, CopyAssignmentWithSameAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(0, a1);\n  u = t1;\n  EXPECT_THAT(a1.num_allocs(), AnyOf(2, 3));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(NoPropagateOnCopy, CopyAssignmentWithSameAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(0, a1);\n  u = t1;\n  EXPECT_THAT(a1.num_allocs(), AnyOf(2, 3));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, CopyAssignmentWithDifferentAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(0, a2);\n  u = t1;\n  EXPECT_EQ(a1, u.get_allocator());\n  EXPECT_THAT(a1.num_allocs(), AnyOf(2, 3));\n  EXPECT_EQ(0, a2.num_allocs());\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(NoPropagateOnCopy, CopyAssignmentWithDifferentAlloc) {\n  auto it = t1.insert(0).first;\n  Table u(0, a2);\n  u = t1;\n  EXPECT_EQ(a2, u.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_THAT(a2.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(1, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, MoveAssignmentWithSameAlloc) {\n  t1.insert(0);\n  Table u(0, a1);\n  u = std::move(t1);\n  auto it = u.begin();\n  EXPECT_EQ(a1, u.get_allocator());\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(NoPropagateOnMove, MoveAssignmentWithSameAlloc) {\n  t1.insert(0);\n  Table u(0, a1);\n  u = std::move(t1);\n  auto it = u.begin();\n  EXPECT_EQ(a1, u.get_allocator());\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, MoveAssignmentWithDifferentAlloc) {\n  t1.insert(0);\n  Table u(0, a2);\n  u = std::move(t1);\n  auto it = u.begin();\n  EXPECT_EQ(a1, u.get_allocator());\n  EXPECT_THAT(a1.num_allocs(), AnyOf(1, 2));\n  EXPECT_EQ(0, a2.num_allocs());\n  EXPECT_THAT(it->num_moves(), AnyOf(0, 1));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(NoPropagateOnMove, MoveAssignmentWithDifferentAlloc) {\n  t1.insert(0);\n  Table u(0, a2);\n  u = std::move(t1);\n  auto it = u.find(0);\n  EXPECT_EQ(a2, u.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_THAT(a2.num_allocs(), AnyOf(1, 2));\n  EXPECT_THAT(it->num_moves(), AnyOf(1, 2));\n  EXPECT_EQ(0, it->num_copies());\n}\n\nTEST_F(PropagateOnAll, Swap) {\n  t1.insert(0);\n  Table u(0, a2);\n  u.swap(t1);\n  EXPECT_EQ(a1, u.get_allocator());\n  EXPECT_EQ(a2, t1.get_allocator());\n  EXPECT_EQ(1, a1.num_allocs());\n  EXPECT_EQ(0, a2.num_allocs());\n  auto it = u.begin();\n  EXPECT_EQ(0, it->num_moves());\n  EXPECT_EQ(0, it->num_copies());\n}\n\n// This allocator is similar to std::pmr::polymorphic_allocator.\n// Note the disabled assignment.\ntemplate <class T>\nclass PAlloc {\n  template <class>\n  friend class PAlloc;\n\n public:\n  // types\n  using value_type = T;\n\n  PAlloc() noexcept = default;\n  explicit PAlloc(size_t id) noexcept : id_(id) {}\n  PAlloc(const PAlloc&) noexcept = default;\n  PAlloc& operator=(const PAlloc&) noexcept = delete;\n\n  template <class U>\n  PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {}  // NOLINT\n\n  template <class U>\n  struct rebind {\n    using other = PAlloc<U>;\n  };\n\n  constexpr PAlloc select_on_container_copy_construction() const { return {}; }\n\n  // public member functions\n  T* allocate(size_t) { return new T; }\n  void deallocate(T* p, size_t) { delete p; }\n\n  friend bool operator==(const PAlloc& a, const PAlloc& b) {\n    return a.id_ == b.id_;\n  }\n  friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); }\n\n private:\n  size_t id_ = std::numeric_limits<size_t>::max();\n};\n\nTEST(NoPropagateDeletedAssignment, CopyConstruct) {\n  using PA = PAlloc<char>;\n  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;\n\n  Table t1(PA{1}), t2(t1);\n  EXPECT_EQ(t1.get_allocator(), PA(1));\n  EXPECT_EQ(t2.get_allocator(), PA());\n}\n\nTEST(NoPropagateDeletedAssignment, CopyAssignment) {\n  using PA = PAlloc<char>;\n  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;\n\n  Table t1(PA{1}), t2(PA{2});\n  t1 = t2;\n  EXPECT_EQ(t1.get_allocator(), PA(1));\n  EXPECT_EQ(t2.get_allocator(), PA(2));\n}\n\nTEST(NoPropagateDeletedAssignment, MoveAssignment) {\n  using PA = PAlloc<char>;\n  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;\n\n  Table t1(PA{1}), t2(PA{2});\n  t1 = std::move(t2);\n  EXPECT_EQ(t1.get_allocator(), PA(1));\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <array>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <numeric>\n#include <random>\n#include <string>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/hash_function_defaults.h\"\n#include \"absl/container/internal/raw_hash_set.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_format.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\nstruct RawHashSetTestOnlyAccess {\n  template <typename C>\n  static auto GetSlots(const C& c) -> decltype(c.slots_) {\n    return c.slots_;\n  }\n};\n\nnamespace {\n\nstruct IntPolicy {\n  using slot_type = int64_t;\n  using key_type = int64_t;\n  using init_type = int64_t;\n\n  using DefaultHash = void;\n  using DefaultEq = void;\n  using DefaultAlloc = void;\n\n  static void construct(void*, int64_t* slot, int64_t v) { *slot = v; }\n  static void destroy(void*, int64_t*) {}\n  static void transfer(void*, int64_t* new_slot, int64_t* old_slot) {\n    *new_slot = *old_slot;\n  }\n\n  static int64_t& element(slot_type* slot) { return *slot; }\n\n  template <class F>\n  static auto apply(F&& f, int64_t x) -> decltype(std::forward<F>(f)(x, x)) {\n    return std::forward<F>(f)(x, x);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\nclass StringPolicy {\n  template <class F, class K, class V,\n            class = typename std::enable_if<\n                std::is_convertible<const K&, absl::string_view>::value>::type>\n  decltype(std::declval<F>()(\n      std::declval<const absl::string_view&>(), std::piecewise_construct,\n      std::declval<std::tuple<K>>(),\n      std::declval<V>())) static apply_impl(F&& f,\n                                            std::pair<std::tuple<K>, V> p) {\n    const absl::string_view& key = std::get<0>(p.first);\n    return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),\n                              std::move(p.second));\n  }\n\n public:\n  struct slot_type {\n    struct ctor {};\n\n    template <class... Ts>\n    slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {}\n\n    std::pair<std::string, std::string> pair;\n  };\n\n  using key_type = std::string;\n  using init_type = std::pair<std::string, std::string>;\n\n  using DefaultHash = void;\n  using DefaultEq = void;\n  using DefaultAlloc = void;\n\n  template <class allocator_type, class... Args>\n  static void construct(allocator_type* alloc, slot_type* slot, Args... args) {\n    std::allocator_traits<allocator_type>::construct(\n        *alloc, slot, typename slot_type::ctor(), std::forward<Args>(args)...);\n  }\n\n  template <class allocator_type>\n  static void destroy(allocator_type* alloc, slot_type* slot) {\n    std::allocator_traits<allocator_type>::destroy(*alloc, slot);\n  }\n\n  template <class allocator_type>\n  static void transfer(allocator_type* alloc, slot_type* new_slot,\n                       slot_type* old_slot) {\n    construct(alloc, new_slot, std::move(old_slot->pair));\n    destroy(alloc, old_slot);\n  }\n\n  static std::pair<std::string, std::string>& element(slot_type* slot) {\n    return slot->pair;\n  }\n\n  template <class F, class... Args>\n  static auto apply(F&& f, Args&&... args)\n      -> decltype(apply_impl(std::forward<F>(f),\n                             PairArgs(std::forward<Args>(args)...))) {\n    return apply_impl(std::forward<F>(f),\n                      PairArgs(std::forward<Args>(args)...));\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\nstruct StringHash : container_internal::hash_default_hash<absl::string_view> {\n  using is_transparent = void;\n};\nstruct StringEq : std::equal_to<absl::string_view> {\n  using is_transparent = void;\n};\n\nstruct StringTable\n    : raw_hash_set<StringPolicy, StringHash, StringEq, std::allocator<int>> {\n  using Base = typename StringTable::raw_hash_set;\n  StringTable() {}\n  using Base::Base;\n};\n\nstruct IntTable\n    : raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>,\n                   std::equal_to<int64_t>, std::allocator<int64_t>> {\n  using Base = typename IntTable::raw_hash_set;\n  IntTable() {}\n  using Base::Base;\n};\n\nstruct string_generator {\n  template <class RNG>\n  std::string operator()(RNG& rng) const {\n    std::string res;\n    res.resize(size);\n    std::uniform_int_distribution<uint32_t> printable_ascii(0x20, 0x7E);\n    std::generate(res.begin(), res.end(), [&] { return printable_ascii(rng); });\n    return res;\n  }\n\n  size_t size;\n};\n\n// Model a cache in steady state.\n//\n// On a table of size N, keep deleting the LRU entry and add a random one.\nvoid BM_CacheInSteadyState(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  string_generator gen{12};\n  StringTable t;\n  std::deque<std::string> keys;\n  while (t.size() < state.range(0)) {\n    auto x = t.emplace(gen(rng), gen(rng));\n    if (x.second) keys.push_back(x.first->first);\n  }\n  ABSL_RAW_CHECK(state.range(0) >= 10, \"\");\n  while (state.KeepRunning()) {\n    // Some cache hits.\n    std::deque<std::string>::const_iterator it;\n    for (int i = 0; i != 90; ++i) {\n      if (i % 10 == 0) it = keys.end();\n      ::benchmark::DoNotOptimize(t.find(*--it));\n    }\n    // Some cache misses.\n    for (int i = 0; i != 10; ++i) ::benchmark::DoNotOptimize(t.find(gen(rng)));\n    ABSL_RAW_CHECK(t.erase(keys.front()), keys.front().c_str());\n    keys.pop_front();\n    while (true) {\n      auto x = t.emplace(gen(rng), gen(rng));\n      if (x.second) {\n        keys.push_back(x.first->first);\n        break;\n      }\n    }\n  }\n  state.SetItemsProcessed(state.iterations());\n  state.SetLabel(absl::StrFormat(\"load_factor=%.2f\", t.load_factor()));\n}\n\nvoid CacheInSteadyStateArgs(::benchmark::Benchmark* bm) {\n  // The default.\n  const float max_load_factor = 0.875;\n  // When the cache is at the steady state, the probe sequence will equal\n  // capacity if there is no reclamation of deleted slots. Pick a number large\n  // enough to make the benchmark slow for that case.\n  const size_t capacity = 1 << 10;\n\n  // Check N data points to cover load factors in [0.4, 0.8).\n  const size_t kNumPoints = 10;\n  for (size_t i = 0; i != kNumPoints; ++i)\n    bm->Arg(std::ceil(\n        capacity * (max_load_factor + i * max_load_factor / kNumPoints) / 2));\n}\nBENCHMARK(BM_CacheInSteadyState)->Apply(CacheInSteadyStateArgs);\n\nvoid BM_EraseEmplace(benchmark::State& state) {\n  IntTable t;\n  int64_t size = state.range(0);\n  for (int64_t i = 0; i < size; ++i) {\n    t.emplace(i);\n  }\n  while (state.KeepRunningBatch(size)) {\n    for (int64_t i = 0; i < size; ++i) {\n      benchmark::DoNotOptimize(t);\n      t.erase(i);\n      t.emplace(i);\n    }\n  }\n}\nBENCHMARK(BM_EraseEmplace)->Arg(1)->Arg(2)->Arg(4)->Arg(8)->Arg(16)->Arg(100);\n\nvoid BM_EraseEmplaceString(benchmark::State& state) {\n  StringTable t;\n  int64_t size = state.range(0);\n  for (int64_t i = 0; i < size; ++i) {\n    std::string s = std::to_string(i);\n    t.emplace(s, s);\n  }\n  while (state.KeepRunningBatch(size)) {\n    for (int64_t i = 0; i < size; ++i) {\n      benchmark::DoNotOptimize(t);\n      std::string s = std::to_string(i);\n      t.erase(s);\n      t.emplace(s, s);\n    }\n  }\n}\nBENCHMARK(BM_EraseEmplaceString)\n    ->Arg(1)\n    ->Arg(2)\n    ->Arg(4)\n    ->Arg(8)\n    ->Arg(16)\n    ->Arg(100);\n\nvoid BM_EndComparison(benchmark::State& state) {\n  StringTable t = {{\"a\", \"a\"}, {\"b\", \"b\"}};\n  auto it = t.begin();\n  for (auto i : state) {\n    benchmark::DoNotOptimize(t);\n    benchmark::DoNotOptimize(it);\n    benchmark::DoNotOptimize(it != t.end());\n  }\n}\nBENCHMARK(BM_EndComparison);\n\nvoid BM_Iteration(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  string_generator gen{12};\n  StringTable t;\n\n  size_t capacity = state.range(0);\n  size_t size = state.range(1);\n  t.reserve(capacity);\n\n  while (t.size() < size) {\n    t.emplace(gen(rng), gen(rng));\n  }\n\n  for (auto i : state) {\n    benchmark::DoNotOptimize(t);\n    for (auto it = t.begin(); it != t.end(); ++it) {\n      benchmark::DoNotOptimize(*it);\n    }\n  }\n}\n\nBENCHMARK(BM_Iteration)\n    ->ArgPair(1, 1)\n    ->ArgPair(2, 2)\n    ->ArgPair(4, 4)\n    ->ArgPair(7, 7)\n    ->ArgPair(10, 10)\n    ->ArgPair(15, 15)\n    ->ArgPair(16, 16)\n    ->ArgPair(54, 54)\n    ->ArgPair(100, 100)\n    ->ArgPair(400, 400)\n    // empty\n    ->ArgPair(0, 0)\n    ->ArgPair(10, 0)\n    ->ArgPair(100, 0)\n    ->ArgPair(1000, 0)\n    ->ArgPair(10000, 0)\n    // sparse\n    ->ArgPair(100, 1)\n    ->ArgPair(1000, 10);\n\nvoid BM_CopyCtorSparseInt(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  IntTable t;\n  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});\n\n  size_t size = state.range(0);\n  t.reserve(size * 10);\n  while (t.size() < size) {\n    t.emplace(dist(rng));\n  }\n\n  for (auto i : state) {\n    IntTable t2 = t;\n    benchmark::DoNotOptimize(t2);\n  }\n}\nBENCHMARK(BM_CopyCtorSparseInt)->Range(1, 4096);\n\nvoid BM_CopyCtorInt(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  IntTable t;\n  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});\n\n  size_t size = state.range(0);\n  while (t.size() < size) {\n    t.emplace(dist(rng));\n  }\n\n  for (auto i : state) {\n    IntTable t2 = t;\n    benchmark::DoNotOptimize(t2);\n  }\n}\nBENCHMARK(BM_CopyCtorInt)->Range(0, 4096);\n\nvoid BM_CopyCtorString(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  StringTable t;\n  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});\n\n  size_t size = state.range(0);\n  while (t.size() < size) {\n    t.emplace(std::to_string(dist(rng)), std::to_string(dist(rng)));\n  }\n\n  for (auto i : state) {\n    StringTable t2 = t;\n    benchmark::DoNotOptimize(t2);\n  }\n}\nBENCHMARK(BM_CopyCtorString)->Range(0, 4096);\n\nvoid BM_CopyAssign(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  IntTable t;\n  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});\n  while (t.size() < state.range(0)) {\n    t.emplace(dist(rng));\n  }\n\n  IntTable t2;\n  for (auto _ : state) {\n    t2 = t;\n    benchmark::DoNotOptimize(t2);\n  }\n}\nBENCHMARK(BM_CopyAssign)->Range(128, 4096);\n\nvoid BM_RangeCtor(benchmark::State& state) {\n  absl::InsecureBitGen rng;\n  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});\n  std::vector<int> values;\n  const size_t desired_size = state.range(0);\n  while (values.size() < desired_size) {\n    values.emplace_back(dist(rng));\n  }\n\n  for (auto unused : state) {\n    IntTable t{values.begin(), values.end()};\n    benchmark::DoNotOptimize(t);\n  }\n}\nBENCHMARK(BM_RangeCtor)->Range(128, 65536);\n\nvoid BM_NoOpReserveIntTable(benchmark::State& state) {\n  IntTable t;\n  t.reserve(100000);\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(t);\n    t.reserve(100000);\n  }\n}\nBENCHMARK(BM_NoOpReserveIntTable);\n\nvoid BM_NoOpReserveStringTable(benchmark::State& state) {\n  StringTable t;\n  t.reserve(100000);\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(t);\n    t.reserve(100000);\n  }\n}\nBENCHMARK(BM_NoOpReserveStringTable);\n\nvoid BM_ReserveIntTable(benchmark::State& state) {\n  constexpr size_t kBatchSize = 1024;\n  size_t reserve_size = static_cast<size_t>(state.range(0));\n\n  std::vector<IntTable> tables;\n  while (state.KeepRunningBatch(kBatchSize)) {\n    state.PauseTiming();\n    tables.clear();\n    tables.resize(kBatchSize);\n    state.ResumeTiming();\n    for (auto& t : tables) {\n      benchmark::DoNotOptimize(t);\n      t.reserve(reserve_size);\n      benchmark::DoNotOptimize(t);\n    }\n  }\n}\nBENCHMARK(BM_ReserveIntTable)\n    ->Arg(1)\n    ->Arg(2)\n    ->Arg(4)\n    ->Arg(8)\n    ->Arg(16)\n    ->Arg(32)\n    ->Arg(64)\n    ->Arg(128)\n    ->Arg(256)\n    ->Arg(512);\n\nvoid BM_ReserveStringTable(benchmark::State& state) {\n  constexpr size_t kBatchSize = 1024;\n  size_t reserve_size = static_cast<size_t>(state.range(0));\n\n  std::vector<StringTable> tables;\n  while (state.KeepRunningBatch(kBatchSize)) {\n    state.PauseTiming();\n    tables.clear();\n    tables.resize(kBatchSize);\n    state.ResumeTiming();\n    for (auto& t : tables) {\n      benchmark::DoNotOptimize(t);\n      t.reserve(reserve_size);\n      benchmark::DoNotOptimize(t);\n    }\n  }\n}\nBENCHMARK(BM_ReserveStringTable)\n    ->Arg(1)\n    ->Arg(2)\n    ->Arg(4)\n    ->Arg(8)\n    ->Arg(16)\n    ->Arg(32)\n    ->Arg(64)\n    ->Arg(128)\n    ->Arg(256)\n    ->Arg(512);\n\n// Like std::iota, except that ctrl_t doesn't support operator++.\ntemplate <typename CtrlIter>\nvoid Iota(CtrlIter begin, CtrlIter end, int value) {\n  for (; begin != end; ++begin, ++value) {\n    *begin = static_cast<ctrl_t>(value);\n  }\n}\n\nvoid BM_Group_Match(benchmark::State& state) {\n  std::array<ctrl_t, Group::kWidth> group;\n  Iota(group.begin(), group.end(), -4);\n  Group g{group.data()};\n  h2_t h = 1;\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(h);\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.Match(h));\n  }\n}\nBENCHMARK(BM_Group_Match);\n\nvoid BM_GroupPortable_Match(benchmark::State& state) {\n  std::array<ctrl_t, GroupPortableImpl::kWidth> group;\n  Iota(group.begin(), group.end(), -4);\n  GroupPortableImpl g{group.data()};\n  h2_t h = 1;\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(h);\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.Match(h));\n  }\n}\nBENCHMARK(BM_GroupPortable_Match);\n\nvoid BM_Group_MaskEmpty(benchmark::State& state) {\n  std::array<ctrl_t, Group::kWidth> group;\n  Iota(group.begin(), group.end(), -4);\n  Group g{group.data()};\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.MaskEmpty());\n  }\n}\nBENCHMARK(BM_Group_MaskEmpty);\n\nvoid BM_Group_MaskEmptyOrDeleted(benchmark::State& state) {\n  std::array<ctrl_t, Group::kWidth> group;\n  Iota(group.begin(), group.end(), -4);\n  Group g{group.data()};\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.MaskEmptyOrDeleted());\n  }\n}\nBENCHMARK(BM_Group_MaskEmptyOrDeleted);\n\nvoid BM_Group_MaskNonFull(benchmark::State& state) {\n  std::array<ctrl_t, Group::kWidth> group;\n  Iota(group.begin(), group.end(), -4);\n  Group g{group.data()};\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.MaskNonFull());\n  }\n}\nBENCHMARK(BM_Group_MaskNonFull);\n\nvoid BM_Group_MatchFirstEmptyOrDeleted(benchmark::State& state) {\n  std::array<ctrl_t, Group::kWidth> group;\n  Iota(group.begin(), group.end(), -2);\n  Group g{group.data()};\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.MaskEmptyOrDeleted().LowestBitSet());\n  }\n}\nBENCHMARK(BM_Group_MatchFirstEmptyOrDeleted);\n\nvoid BM_Group_MatchFirstNonFull(benchmark::State& state) {\n  std::array<ctrl_t, Group::kWidth> group;\n  Iota(group.begin(), group.end(), -2);\n  Group g{group.data()};\n  for (auto _ : state) {\n    ::benchmark::DoNotOptimize(g);\n    ::benchmark::DoNotOptimize(g.MaskNonFull().LowestBitSet());\n  }\n}\nBENCHMARK(BM_Group_MatchFirstNonFull);\n\nvoid BM_DropDeletes(benchmark::State& state) {\n  constexpr size_t capacity = (1 << 20) - 1;\n  std::vector<ctrl_t> ctrl(capacity + 1 + Group::kWidth);\n  ctrl[capacity] = ctrl_t::kSentinel;\n  std::vector<ctrl_t> pattern = {ctrl_t::kEmpty,   static_cast<ctrl_t>(2),\n                                 ctrl_t::kDeleted, static_cast<ctrl_t>(2),\n                                 ctrl_t::kEmpty,   static_cast<ctrl_t>(1),\n                                 ctrl_t::kDeleted};\n  for (size_t i = 0; i != capacity; ++i) {\n    ctrl[i] = pattern[i % pattern.size()];\n  }\n  while (state.KeepRunning()) {\n    state.PauseTiming();\n    std::vector<ctrl_t> ctrl_copy = ctrl;\n    state.ResumeTiming();\n    ConvertDeletedToEmptyAndFullToDeleted(ctrl_copy.data(), capacity);\n    ::benchmark::DoNotOptimize(ctrl_copy[capacity]);\n  }\n}\nBENCHMARK(BM_DropDeletes);\n\nvoid BM_Resize(benchmark::State& state) {\n  // For now just measure a small cheap hash table since we\n  // are mostly interested in the overhead of type-erasure\n  // in resize().\n  constexpr int kElements = 64;\n  const int kCapacity = kElements * 2;\n\n  IntTable table;\n  for (int i = 0; i < kElements; i++) {\n    table.insert(i);\n  }\n  for (auto unused : state) {\n    table.rehash(0);\n    table.rehash(kCapacity);\n  }\n}\nBENCHMARK(BM_Resize);\n\nvoid BM_EraseIf(benchmark::State& state) {\n  int64_t num_elements = state.range(0);\n  size_t num_erased = static_cast<size_t>(state.range(1));\n\n  constexpr size_t kRepetitions = 64;\n\n  absl::BitGen rng;\n\n  std::vector<std::vector<int64_t>> keys(kRepetitions);\n  std::vector<IntTable> tables;\n  std::vector<int64_t> threshold;\n  for (auto& k : keys) {\n    tables.push_back(IntTable());\n    auto& table = tables.back();\n    for (int64_t i = 0; i < num_elements; i++) {\n      // We use random keys to reduce noise.\n      k.push_back(\n          absl::Uniform<int64_t>(rng, 0, std::numeric_limits<int64_t>::max()));\n      if (!table.insert(k.back()).second) {\n        k.pop_back();\n        --i;  // duplicated value, retrying\n      }\n    }\n    std::sort(k.begin(), k.end());\n    threshold.push_back(static_cast<int64_t>(num_erased) < num_elements\n                            ? k[num_erased]\n                            : std::numeric_limits<int64_t>::max());\n  }\n\n  while (state.KeepRunningBatch(static_cast<int64_t>(kRepetitions) *\n                                std::max(num_elements, int64_t{1}))) {\n    benchmark::DoNotOptimize(tables);\n    for (size_t t_id = 0; t_id < kRepetitions; t_id++) {\n      auto& table = tables[t_id];\n      benchmark::DoNotOptimize(num_erased);\n      auto pred = [t = threshold[t_id]](int64_t key) { return key < t; };\n      benchmark::DoNotOptimize(pred);\n      benchmark::DoNotOptimize(table);\n      absl::container_internal::EraseIf(pred, &table);\n    }\n    state.PauseTiming();\n    for (size_t t_id = 0; t_id < kRepetitions; t_id++) {\n      auto& k = keys[t_id];\n      auto& table = tables[t_id];\n      for (size_t i = 0; i < num_erased; i++) {\n        table.insert(k[i]);\n      }\n    }\n    state.ResumeTiming();\n  }\n}\n\nBENCHMARK(BM_EraseIf)\n    ->ArgNames({\"num_elements\", \"num_erased\"})\n    ->ArgPair(10, 0)\n    ->ArgPair(1000, 0)\n    ->ArgPair(10, 5)\n    ->ArgPair(1000, 500)\n    ->ArgPair(10, 10)\n    ->ArgPair(1000, 1000);\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// These methods are here to make it easy to examine the assembly for targeted\n// parts of the API.\nauto CodegenAbslRawHashSetInt64Find(absl::container_internal::IntTable* table,\n                                    int64_t key) -> decltype(table->find(key)) {\n  return table->find(key);\n}\n\nbool CodegenAbslRawHashSetInt64FindNeEnd(\n    absl::container_internal::IntTable* table, int64_t key) {\n  return table->find(key) != table->end();\n}\n\n// This is useful because the find isn't inlined but the iterator comparison is.\nbool CodegenAbslRawHashSetStringFindNeEnd(\n    absl::container_internal::StringTable* table, const std::string& key) {\n  return table->find(key) != table->end();\n}\n\nauto CodegenAbslRawHashSetInt64Insert(absl::container_internal::IntTable* table,\n                                      int64_t key)\n    -> decltype(table->insert(key)) {\n  return table->insert(key);\n}\n\nbool CodegenAbslRawHashSetInt64Contains(\n    absl::container_internal::IntTable* table, int64_t key) {\n  return table->contains(key);\n}\n\nvoid CodegenAbslRawHashSetInt64Iterate(\n    absl::container_internal::IntTable* table) {\n  for (auto x : *table) benchmark::DoNotOptimize(x);\n}\n\nint odr =\n    (::benchmark::DoNotOptimize(std::make_tuple(\n         &CodegenAbslRawHashSetInt64Find, &CodegenAbslRawHashSetInt64FindNeEnd,\n         &CodegenAbslRawHashSetStringFindNeEnd,\n         &CodegenAbslRawHashSetInt64Insert, &CodegenAbslRawHashSetInt64Contains,\n         &CodegenAbslRawHashSetInt64Iterate)),\n     1);\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set_probe_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Generates probe length statistics for many combinations of key types and key\n// distributions, all using the default hash function for swisstable.\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <memory>\n#include <optional>\n#include <regex>  // NOLINT\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/no_destructor.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/internal/hash_function_defaults.h\"\n#include \"absl/container/internal/hashtable_debug.h\"\n#include \"absl/container/internal/raw_hash_set.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\nenum class OutputStyle { kRegular, kBenchmark };\n\n// The --benchmark command line flag.\n// This is populated from main().\n// When run in \"benchmark\" mode, we have different output. This allows\n// A/B comparisons with tools like `benchy`.\nabsl::string_view benchmarks;\n\nOutputStyle output() {\n  return !benchmarks.empty() ? OutputStyle::kBenchmark : OutputStyle::kRegular;\n}\n\ntemplate <class T>\nstruct Policy {\n  using slot_type = T;\n  using key_type = T;\n  using init_type = T;\n\n  using DefaultHash = void;\n  using DefaultEq = void;\n  using DefaultAlloc = void;\n\n  template <class allocator_type, class Arg>\n  static void construct(allocator_type* alloc, slot_type* slot,\n                        const Arg& arg) {\n    std::allocator_traits<allocator_type>::construct(*alloc, slot, arg);\n  }\n\n  template <class allocator_type>\n  static void destroy(allocator_type* alloc, slot_type* slot) {\n    std::allocator_traits<allocator_type>::destroy(*alloc, slot);\n  }\n\n  static slot_type& element(slot_type* slot) { return *slot; }\n\n  template <class F, class... Args>\n  static auto apply(F&& f, const slot_type& arg)\n      -> decltype(std::forward<F>(f)(arg, arg)) {\n    return std::forward<F>(f)(arg, arg);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr auto get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\nabsl::BitGen& GlobalBitGen() {\n  static absl::NoDestructor<absl::BitGen> value;\n  return *value;\n}\n\n// Keeps a pool of allocations and randomly gives one out.\n// This introduces more randomization to the addresses given to swisstable and\n// should help smooth out this factor from probe length calculation.\ntemplate <class T>\nclass RandomizedAllocator {\n public:\n  using value_type = T;\n\n  RandomizedAllocator() = default;\n  template <typename U>\n  RandomizedAllocator(RandomizedAllocator<U>) {}  // NOLINT\n\n  static T* allocate(size_t n) {\n    auto& pointers = GetPointers(n);\n    // Fill the pool\n    while (pointers.size() < kRandomPool) {\n      pointers.push_back(std::allocator<T>{}.allocate(n));\n    }\n\n    // Choose a random one.\n    size_t i = absl::Uniform<size_t>(GlobalBitGen(), 0, pointers.size());\n    T* result = pointers[i];\n    pointers[i] = pointers.back();\n    pointers.pop_back();\n    return result;\n  }\n\n  static void deallocate(T* p, size_t n) {\n    // Just put it back on the pool. No need to release the memory.\n    GetPointers(n).push_back(p);\n  }\n\n private:\n  // We keep at least kRandomPool allocations for each size.\n  static constexpr size_t kRandomPool = 20;\n\n  static std::vector<T*>& GetPointers(size_t n) {\n    static absl::NoDestructor<absl::flat_hash_map<size_t, std::vector<T*>>> m;\n    return (*m)[n];\n  }\n};\n\ntemplate <class T>\nstruct DefaultHash {\n  using type = absl::container_internal::hash_default_hash<T>;\n};\n\ntemplate <class T>\nusing DefaultHashT = typename DefaultHash<T>::type;\n\ntemplate <class T>\nstruct Table : absl::container_internal::raw_hash_set<\n                   Policy<T>, DefaultHashT<T>,\n                   absl::container_internal::hash_default_eq<T>,\n                   RandomizedAllocator<T>> {};\n\nstruct LoadSizes {\n  size_t min_load;\n  size_t max_load;\n};\n\nLoadSizes GetMinMaxLoadSizes() {\n  static const auto sizes = [] {\n    Table<int> t;\n\n    // First, fill enough to have a good distribution.\n    constexpr size_t kMinSize = 10000;\n    while (t.size() < kMinSize) t.insert(t.size());\n\n    const auto reach_min_load_factor = [&] {\n      const double lf = t.load_factor();\n      while (lf <= t.load_factor()) t.insert(t.size());\n    };\n\n    // Then, insert until we reach min load factor.\n    reach_min_load_factor();\n    const size_t min_load_size = t.size();\n\n    // Keep going until we hit min load factor again, then go back one.\n    t.insert(t.size());\n    reach_min_load_factor();\n\n    return LoadSizes{min_load_size, t.size() - 1};\n  }();\n  return sizes;\n}\n\nstruct Ratios {\n  double min_load;\n  double avg_load;\n  double max_load;\n};\n\n// See absl/container/internal/hashtable_debug.h for details on\n// probe length calculation.\ntemplate <class ElemFn>\nRatios CollectMeanProbeLengths() {\n  const auto min_max_sizes = GetMinMaxLoadSizes();\n\n  ElemFn elem;\n  using Key = decltype(elem());\n  Table<Key> t;\n\n  Ratios result;\n  while (t.size() < min_max_sizes.min_load) t.insert(elem());\n  result.min_load =\n      absl::container_internal::GetHashtableDebugProbeSummary(t).mean;\n\n  while (t.size() < (min_max_sizes.min_load + min_max_sizes.max_load) / 2)\n    t.insert(elem());\n  result.avg_load =\n      absl::container_internal::GetHashtableDebugProbeSummary(t).mean;\n\n  while (t.size() < min_max_sizes.max_load) t.insert(elem());\n  result.max_load =\n      absl::container_internal::GetHashtableDebugProbeSummary(t).mean;\n\n  return result;\n}\n\ntemplate <int Align>\nuintptr_t PointerForAlignment() {\n  alignas(Align) static constexpr uintptr_t kInitPointer = 0;\n  return reinterpret_cast<uintptr_t>(&kInitPointer);\n}\n\n// This incomplete type is used for testing hash of pointers of different\n// alignments.\n// NOTE: We are generating invalid pointer values on the fly with\n// reinterpret_cast. There are not \"safely derived\" pointers so using them is\n// technically UB. It is unlikely to be a problem, though.\ntemplate <int Align>\nstruct Ptr;\n\ntemplate <int Align>\nPtr<Align>* MakePtr(uintptr_t v) {\n  if (sizeof(v) == 8) {\n    constexpr int kCopyBits = 16;\n    // Ensure high bits are all the same.\n    v = static_cast<uintptr_t>(static_cast<intptr_t>(v << kCopyBits) >>\n                               kCopyBits);\n  }\n  return reinterpret_cast<Ptr<Align>*>(v);\n}\n\nenum class StringSize { kSmall, kMedium, kLarge, kExtraLarge };\nconstexpr char kStringFormat[] = \"%s/name-%07d-of-9999999.txt\";\n\ntemplate <StringSize size>\nstruct String {\n  std::string value;\n  static std::string Make(uint32_t v) {\n    switch (size) {\n      case StringSize::kSmall:\n        return absl::StrCat(v);\n      case StringSize::kMedium:  // < 32 bytes\n        return absl::StrFormat(kStringFormat, \"/path\", v);\n      case StringSize::kLarge:  // 33-64 bytes\n        return absl::StrFormat(kStringFormat, \"/path/to/file\", v);\n      case StringSize::kExtraLarge:  // > 64 bytes\n        return absl::StrFormat(kStringFormat,\n                               \"/path/to/a/very/long/file/name/so/that/total/\"\n                               \"length/is/larger/than/64/bytes\",\n                               v);\n      default:\n        return \"\";\n    }\n  }\n};\n\ntemplate <class T>\nstruct Sequential {\n  T operator()() const { return current++; }\n  mutable T current{};\n};\n\ntemplate <int Align>\nstruct Sequential<Ptr<Align>*> {\n  Ptr<Align>* operator()() const {\n    auto* result = MakePtr<Align>(current);\n    current += Align;\n    return result;\n  }\n  mutable uintptr_t current = PointerForAlignment<Align>();\n};\n\ntemplate <StringSize size>\nstruct Sequential<String<size>> {\n  std::string operator()() const { return String<size>::Make(current++); }\n  mutable uint32_t current = 0;\n};\n\ntemplate <class T, class U>\nstruct Sequential<std::pair<T, U>> {\n  mutable Sequential<T> tseq;\n  mutable Sequential<U> useq;\n\n  using RealT = decltype(tseq());\n  using RealU = decltype(useq());\n\n  mutable std::vector<RealT> ts;\n  mutable std::vector<RealU> us;\n  mutable size_t ti = 0, ui = 0;\n\n  std::pair<RealT, RealU> operator()() const {\n    std::pair<RealT, RealU> value{get_t(), get_u()};\n    if (ti == 0) {\n      ti = ui + 1;\n      ui = 0;\n    } else {\n      --ti;\n      ++ui;\n    }\n    return value;\n  }\n\n  RealT get_t() const {\n    while (ti >= ts.size()) ts.push_back(tseq());\n    return ts[ti];\n  }\n\n  RealU get_u() const {\n    while (ui >= us.size()) us.push_back(useq());\n    return us[ui];\n  }\n};\n\ntemplate <class T, int percent_skip>\nstruct AlmostSequential {\n  mutable Sequential<T> current;\n\n  auto operator()() const -> decltype(current()) {\n    while (absl::Uniform(GlobalBitGen(), 0.0, 1.0) <= percent_skip / 100.)\n      current();\n    return current();\n  }\n};\n\nstruct Uniform {\n  template <typename T>\n  T operator()(T) const {\n    return absl::Uniform<T>(absl::IntervalClosed, GlobalBitGen(), T{0}, ~T{0});\n  }\n};\n\nstruct Gaussian {\n  template <typename T>\n  T operator()(T) const {\n    double d;\n    do {\n      d = absl::Gaussian<double>(GlobalBitGen(), 1e6, 1e4);\n    } while (d <= 0 || d > std::numeric_limits<T>::max() / 2);\n    return static_cast<T>(d);\n  }\n};\n\nstruct Zipf {\n  template <typename T>\n  T operator()(T) const {\n    return absl::Zipf<T>(GlobalBitGen(), std::numeric_limits<T>::max(), 1.6);\n  }\n};\n\ntemplate <class T, class Dist>\nstruct Random {\n  T operator()() const { return Dist{}(T{}); }\n};\n\ntemplate <class Dist, int Align>\nstruct Random<Ptr<Align>*, Dist> {\n  Ptr<Align>* operator()() const {\n    return MakePtr<Align>(Random<uintptr_t, Dist>{}() * Align);\n  }\n};\n\ntemplate <class Dist, StringSize size>\nstruct Random<String<size>, Dist> {\n  std::string operator()() const {\n    return String<size>::Make(Random<uint32_t, Dist>{}());\n  }\n};\n\ntemplate <class T, class U, class Dist>\nstruct Random<std::pair<T, U>, Dist> {\n  auto operator()() const\n      -> decltype(std::make_pair(Random<T, Dist>{}(), Random<U, Dist>{}())) {\n    return std::make_pair(Random<T, Dist>{}(), Random<U, Dist>{}());\n  }\n};\n\ntemplate <typename>\nstd::string Name();\n\nstd::string Name(uint32_t*) { return \"u32\"; }\nstd::string Name(uint64_t*) { return \"u64\"; }\n\ntemplate <int Align>\nstd::string Name(Ptr<Align>**) {\n  return absl::StrCat(\"Ptr\", Align);\n}\n\ntemplate <StringSize size>\nstd::string Name(String<size>*) {\n  switch (size) {\n    case StringSize::kSmall:\n      return \"StrS\";\n    case StringSize::kMedium:\n      return \"StrM\";\n    case StringSize::kLarge:\n      return \"StrL\";\n    case StringSize::kExtraLarge:\n      return \"StrXL\";\n    default:\n      return \"\";\n  }\n}\n\ntemplate <class T, class U>\nstd::string Name(std::pair<T, U>*) {\n  if (output() == OutputStyle::kBenchmark)\n    return absl::StrCat(\"P_\", Name<T>(), \"_\", Name<U>());\n  return absl::StrCat(\"P<\", Name<T>(), \",\", Name<U>(), \">\");\n}\n\ntemplate <class T>\nstd::string Name(Sequential<T>*) {\n  return \"Sequential\";\n}\n\ntemplate <class T, int P>\nstd::string Name(AlmostSequential<T, P>*) {\n  return absl::StrCat(\"AlmostSeq_\", P);\n}\n\ntemplate <class T>\nstd::string Name(Random<T, Uniform>*) {\n  return \"UnifRand\";\n}\n\ntemplate <class T>\nstd::string Name(Random<T, Gaussian>*) {\n  return \"GausRand\";\n}\n\ntemplate <class T>\nstd::string Name(Random<T, Zipf>*) {\n  return \"ZipfRand\";\n}\n\ntemplate <typename T>\nstd::string Name() {\n  return Name(static_cast<T*>(nullptr));\n}\n\nconstexpr int kNameWidth = 15;\nconstexpr int kDistWidth = 16;\n\nbool CanRunBenchmark(absl::string_view name) {\n  static const absl::NoDestructor<std::optional<std::regex>> filter([] {\n    return benchmarks.empty() || benchmarks == \"all\"\n               ? std::nullopt\n               : std::make_optional(std::regex(std::string(benchmarks)));\n  }());\n  return !filter->has_value() || std::regex_search(std::string(name), **filter);\n}\n\nstruct Result {\n  std::string name;\n  std::string dist_name;\n  Ratios ratios;\n};\n\ntemplate <typename T, typename Dist>\nvoid RunForTypeAndDistribution(std::vector<Result>& results) {\n  std::string name = absl::StrCat(Name<T>(), \"/\", Name<Dist>());\n  // We have to check against all three names (min/avg/max) before we run it.\n  // If any of them is enabled, we run it.\n  if (!CanRunBenchmark(absl::StrCat(name, \"/min\")) &&\n      !CanRunBenchmark(absl::StrCat(name, \"/avg\")) &&\n      !CanRunBenchmark(absl::StrCat(name, \"/max\"))) {\n    return;\n  }\n  results.push_back({Name<T>(), Name<Dist>(), CollectMeanProbeLengths<Dist>()});\n}\n\ntemplate <class T>\nvoid RunForType(std::vector<Result>& results) {\n  RunForTypeAndDistribution<T, Sequential<T>>(results);\n  RunForTypeAndDistribution<T, AlmostSequential<T, 20>>(results);\n  RunForTypeAndDistribution<T, AlmostSequential<T, 50>>(results);\n  RunForTypeAndDistribution<T, Random<T, Uniform>>(results);\n#ifdef NDEBUG\n  // Disable these in non-opt mode because they take too long.\n  RunForTypeAndDistribution<T, Random<T, Gaussian>>(results);\n  RunForTypeAndDistribution<T, Random<T, Zipf>>(results);\n#endif  // NDEBUG\n}\n\n}  // namespace\n\nint main(int argc, char** argv) {\n  // Parse the benchmark flags. Ignore all of them except the regex pattern.\n  for (int i = 1; i < argc; ++i) {\n    absl::string_view arg = argv[i];\n    const auto next = [&] { return argv[std::min(i + 1, argc - 1)]; };\n\n    if (absl::ConsumePrefix(&arg, \"--benchmark_filter\")) {\n      if (arg == \"\") {\n        // --benchmark_filter X\n        benchmarks = next();\n      } else if (absl::ConsumePrefix(&arg, \"=\")) {\n        // --benchmark_filter=X\n        benchmarks = arg;\n      }\n    }\n\n    // Any --benchmark flag turns on the mode.\n    if (absl::ConsumePrefix(&arg, \"--benchmark\")) {\n      if (benchmarks.empty()) benchmarks=\"all\";\n    }\n  }\n\n  std::vector<Result> results;\n  RunForType<uint64_t>(results);\n  RunForType<Ptr<8>*>(results);\n  RunForType<Ptr<16>*>(results);\n  RunForType<Ptr<32>*>(results);\n  RunForType<Ptr<64>*>(results);\n  RunForType<std::pair<uint32_t, uint32_t>>(results);\n  RunForType<String<StringSize::kSmall>>(results);\n  RunForType<String<StringSize::kMedium>>(results);\n  RunForType<String<StringSize::kLarge>>(results);\n  RunForType<String<StringSize::kExtraLarge>>(results);\n  RunForType<std::pair<uint64_t, String<StringSize::kSmall>>>(results);\n  RunForType<std::pair<String<StringSize::kSmall>, uint64_t>>(results);\n  RunForType<std::pair<uint64_t, String<StringSize::kMedium>>>(results);\n  RunForType<std::pair<String<StringSize::kMedium>, uint64_t>>(results);\n  RunForType<std::pair<uint64_t, String<StringSize::kLarge>>>(results);\n  RunForType<std::pair<String<StringSize::kLarge>, uint64_t>>(results);\n  RunForType<std::pair<uint64_t, String<StringSize::kExtraLarge>>>(results);\n  RunForType<std::pair<String<StringSize::kExtraLarge>, uint64_t>>(results);\n\n  switch (output()) {\n    case OutputStyle::kRegular:\n      absl::PrintF(\"%-*s%-*s       Min       Avg       Max\\n%s\\n\", kNameWidth,\n                   \"Type\", kDistWidth, \"Distribution\",\n                   std::string(kNameWidth + kDistWidth + 10 * 3, '-'));\n      for (const auto& result : results) {\n        absl::PrintF(\"%-*s%-*s  %8.4f  %8.4f  %8.4f\\n\", kNameWidth, result.name,\n                     kDistWidth, result.dist_name, result.ratios.min_load,\n                     result.ratios.avg_load, result.ratios.max_load);\n      }\n      break;\n    case OutputStyle::kBenchmark: {\n      absl::PrintF(\"{\\n\");\n      absl::PrintF(\"  \\\"benchmarks\\\": [\\n\");\n      absl::string_view comma;\n      for (const auto& result : results) {\n        auto print = [&](absl::string_view stat, double Ratios::*val) {\n          std::string name =\n              absl::StrCat(result.name, \"/\", result.dist_name, \"/\", stat);\n          // Check the regex again. We might had have enabled only one of the\n          // stats for the benchmark.\n          if (!CanRunBenchmark(name)) return;\n          // Report at least 1, because benchy drops results with zero.\n          double reported_value = std::max(1e9 * result.ratios.*val, 1.0);\n          absl::PrintF(\"    %s{\\n\", comma);\n          absl::PrintF(\"      \\\"cpu_time\\\": %f,\\n\", reported_value);\n          absl::PrintF(\"      \\\"real_time\\\": %f,\\n\", reported_value);\n          absl::PrintF(\"      \\\"iterations\\\": 1,\\n\");\n          absl::PrintF(\"      \\\"name\\\": \\\"%s\\\",\\n\", name);\n          absl::PrintF(\"      \\\"time_unit\\\": \\\"ns\\\"\\n\");\n          absl::PrintF(\"    }\\n\");\n          comma = \",\";\n        };\n        print(\"min\", &Ratios::min_load);\n        print(\"avg\", &Ratios::avg_load);\n        print(\"max\", &Ratios::max_load);\n      }\n      absl::PrintF(\"  ],\\n\");\n      absl::PrintF(\"  \\\"context\\\": {\\n\");\n      absl::PrintF(\"  }\\n\");\n      absl::PrintF(\"}\\n\");\n      break;\n    }\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set_resize_impl.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This is a private implementation detail of resize algorithm of\n// raw_hash_set. It is exposed in a separate file for testing purposes.\n\n#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_RESIZE_IMPL_H_\n#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_RESIZE_IMPL_H_\n\n#include <cstddef>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// Encoding for probed elements used for smaller tables.\n// Data is encoded into single integer.\n// Storage format for 4 bytes:\n// - 7 bits for h2\n// - 12 bits for source_offset\n// - 13 bits for h1\n// Storage format for 8 bytes:\n// - 7 bits for h2\n// - 28 bits for source_offset\n// - 29 bits for h1\n// Storage format for 16 bytes:\n// - 7 bits for h2\n// - 57 bits for source_offset\n// - 58 bits for h1\ntemplate <typename IntType, size_t kTotalBits>\nstruct ProbedItemImpl {\n  static constexpr IntType kH2Bits = 7;\n\n  static constexpr IntType kMaxOldBits = (kTotalBits - kH2Bits) / 2;\n  static constexpr IntType kMaxOldCapacity = (IntType{1} << kMaxOldBits) - 1;\n\n  // We always have one bit more for h1.\n  static constexpr IntType kMaxNewBits = kMaxOldBits + 1;\n  static constexpr IntType kMaxNewCapacity = (IntType{1} << kMaxNewBits) - 1;\n\n  static_assert(kMaxNewBits + kMaxOldBits + kH2Bits == kTotalBits);\n\n  ProbedItemImpl() = default;\n  ProbedItemImpl(uint8_t h2_arg, size_t source_offset_arg, size_t h1_arg)\n      : h2(h2_arg),\n        source_offset(static_cast<IntType>(source_offset_arg)),\n        h1(static_cast<IntType>(h1_arg)) {}\n\n  IntType h2 : kH2Bits;\n  IntType source_offset : kMaxOldBits;\n  IntType h1 : kMaxNewBits;\n};\n\nusing ProbedItem4Bytes = ProbedItemImpl<uint32_t, 32>;\nstatic_assert(sizeof(ProbedItem4Bytes) == 4);\nusing ProbedItem8Bytes = ProbedItemImpl<uint64_t, 64>;\nstatic_assert(sizeof(ProbedItem8Bytes) == 8);\nusing ProbedItem16Bytes = ProbedItemImpl<uint64_t, 7 + 57 + 58>;\nstatic_assert(sizeof(ProbedItem16Bytes) == 16);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_RESIZE_IMPL_H_\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set_resize_impl_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/raw_hash_set_resize_impl.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nconstexpr size_t kSmallSourceOffset = 17;\nconstexpr size_t kSmallH1 = 25;\n\ntemplate <class Encoder>\nclass EncoderTest : public testing::Test {};\n\nusing ProbedItemTypes =\n    ::testing::Types<ProbedItem4Bytes, ProbedItem8Bytes, ProbedItem16Bytes>;\nTYPED_TEST_SUITE(EncoderTest, ProbedItemTypes);\n\nTYPED_TEST(EncoderTest, EncodeDecodeSmall) {\n  using ProbedItem = TypeParam;\n  for (uint8_t h2 = 0; h2 < 128; ++h2) {\n    ProbedItem item(h2, kSmallSourceOffset, kSmallH1);\n    EXPECT_EQ(item.h2, h2);\n    EXPECT_EQ(item.source_offset, kSmallSourceOffset);\n    EXPECT_EQ(item.h1 & ProbedItem::kMaxNewCapacity, kSmallH1);\n  }\n}\n\nTYPED_TEST(EncoderTest, EncodeDecodeMax) {\n  using ProbedItem = TypeParam;\n  for (uint8_t h2 = 0; h2 < 128; ++h2) {\n    size_t source_offset = static_cast<size_t>(std::min<uint64_t>(\n        ProbedItem::kMaxOldCapacity, (std::numeric_limits<size_t>::max)()));\n    size_t h1 = static_cast<size_t>(std::min<uint64_t>(\n        ProbedItem::kMaxNewCapacity, (std::numeric_limits<size_t>::max)()));\n    ProbedItem item(h2, source_offset, h1);\n    EXPECT_EQ(item.h2, h2);\n    EXPECT_EQ(item.source_offset, source_offset);\n    EXPECT_EQ(item.h1 & ProbedItem::kMaxNewCapacity, h1);\n  }\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/raw_hash_set_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/raw_hash_set.h\"\n\n#include <algorithm>\n#include <array>\n#include <atomic>\n#include <bitset>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <deque>\n#include <functional>\n#include <iostream>\n#include <iterator>\n#include <limits>\n#include <list>\n#include <map>\n#include <memory>\n#include <numeric>\n#include <optional>\n#include <ostream>\n#include <random>\n#include <set>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/cycleclock.h\"\n#include \"absl/base/prefetch.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/hash_function_defaults.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/container/internal/hashtable_control_bytes.h\"\n#include \"absl/container/internal/hashtable_debug.h\"\n#include \"absl/container/internal/hashtablez_sampler.h\"\n#include \"absl/container/internal/raw_hash_set_resize_impl.h\"\n#include \"absl/container/internal/test_allocator.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/container/node_hash_set.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/log.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\nstruct RawHashSetTestOnlyAccess {\n  template <typename C>\n  static auto GetCommon(C&& c) -> decltype(std::forward<C>(c).common()) {\n    return std::forward<C>(c).common();\n  }\n  template <typename C>\n  static auto GetSlots(const C& c) -> decltype(c.slot_array()) {\n    return c.slot_array();\n  }\n  template <typename C>\n  static size_t CountTombstones(const C& c) {\n    return c.common().TombstonesCount();\n  }\n};\n\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::Eq;\nusing ::testing::Ge;\nusing ::testing::HasSubstr;\nusing ::testing::Lt;\nusing ::testing::Pair;\nusing ::testing::UnorderedElementsAre;\nusing ::testing::UnorderedElementsAreArray;\n\n// Convenience function to static cast to ctrl_t.\nctrl_t CtrlT(int i) { return static_cast<ctrl_t>(i); }\n\n// Enables sampling with 1 percent sampling rate and\n// resets the rate counter for the current thread.\nvoid SetSamplingRateTo1Percent() {\n  SetHashtablezEnabled(true);\n  SetHashtablezSampleParameter(100);  // Sample ~1% of tables.\n  // Reset rate counter for the current thread.\n  TestOnlyRefreshSamplingStateForCurrentThread();\n}\n\n// Disables sampling and resets the rate counter for the current thread.\nvoid DisableSampling() {\n  SetHashtablezEnabled(false);\n  SetHashtablezSampleParameter(1 << 16);\n  // Reset rate counter for the current thread.\n  TestOnlyRefreshSamplingStateForCurrentThread();\n}\n\nTEST(GrowthInfoTest, GetGrowthLeft) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(5);\n  EXPECT_EQ(gi.GetGrowthLeft(), 5);\n  gi.OverwriteFullAsDeleted();\n  EXPECT_EQ(gi.GetGrowthLeft(), 5);\n}\n\nTEST(GrowthInfoTest, HasNoDeleted) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(5);\n  EXPECT_TRUE(gi.HasNoDeleted());\n  gi.OverwriteFullAsDeleted();\n  EXPECT_FALSE(gi.HasNoDeleted());\n  // After reinitialization we have no deleted slots.\n  gi.InitGrowthLeftNoDeleted(5);\n  EXPECT_TRUE(gi.HasNoDeleted());\n}\n\nTEST(GrowthInfoTest, HasNoDeletedAndGrowthLeft) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(5);\n  EXPECT_TRUE(gi.HasNoDeletedAndGrowthLeft());\n  gi.OverwriteFullAsDeleted();\n  EXPECT_FALSE(gi.HasNoDeletedAndGrowthLeft());\n  gi.InitGrowthLeftNoDeleted(0);\n  EXPECT_FALSE(gi.HasNoDeletedAndGrowthLeft());\n  gi.OverwriteFullAsDeleted();\n  EXPECT_FALSE(gi.HasNoDeletedAndGrowthLeft());\n  // After reinitialization we have no deleted slots.\n  gi.InitGrowthLeftNoDeleted(5);\n  EXPECT_TRUE(gi.HasNoDeletedAndGrowthLeft());\n}\n\nTEST(GrowthInfoTest, HasNoGrowthLeftAndNoDeleted) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(1);\n  EXPECT_FALSE(gi.HasNoGrowthLeftAndNoDeleted());\n  gi.OverwriteEmptyAsFull();\n  EXPECT_TRUE(gi.HasNoGrowthLeftAndNoDeleted());\n  gi.OverwriteFullAsDeleted();\n  EXPECT_FALSE(gi.HasNoGrowthLeftAndNoDeleted());\n  gi.OverwriteFullAsEmpty();\n  EXPECT_FALSE(gi.HasNoGrowthLeftAndNoDeleted());\n  gi.InitGrowthLeftNoDeleted(0);\n  EXPECT_TRUE(gi.HasNoGrowthLeftAndNoDeleted());\n  gi.OverwriteFullAsEmpty();\n  EXPECT_FALSE(gi.HasNoGrowthLeftAndNoDeleted());\n}\n\nTEST(GrowthInfoTest, OverwriteFullAsEmpty) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(5);\n  gi.OverwriteFullAsEmpty();\n  EXPECT_EQ(gi.GetGrowthLeft(), 6);\n  gi.OverwriteFullAsDeleted();\n  EXPECT_EQ(gi.GetGrowthLeft(), 6);\n  gi.OverwriteFullAsEmpty();\n  EXPECT_EQ(gi.GetGrowthLeft(), 7);\n  EXPECT_FALSE(gi.HasNoDeleted());\n}\n\nTEST(GrowthInfoTest, OverwriteEmptyAsFull) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(5);\n  gi.OverwriteEmptyAsFull();\n  EXPECT_EQ(gi.GetGrowthLeft(), 4);\n  gi.OverwriteFullAsDeleted();\n  EXPECT_EQ(gi.GetGrowthLeft(), 4);\n  gi.OverwriteEmptyAsFull();\n  EXPECT_EQ(gi.GetGrowthLeft(), 3);\n  EXPECT_FALSE(gi.HasNoDeleted());\n}\n\nTEST(GrowthInfoTest, OverwriteControlAsFull) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(5);\n  gi.OverwriteControlAsFull(ctrl_t::kEmpty);\n  EXPECT_EQ(gi.GetGrowthLeft(), 4);\n  gi.OverwriteControlAsFull(ctrl_t::kDeleted);\n  EXPECT_EQ(gi.GetGrowthLeft(), 4);\n  gi.OverwriteFullAsDeleted();\n  gi.OverwriteControlAsFull(ctrl_t::kDeleted);\n  // We do not count number of deleted, so the bit sticks till the next rehash.\n  EXPECT_FALSE(gi.HasNoDeletedAndGrowthLeft());\n  EXPECT_FALSE(gi.HasNoDeleted());\n}\n\nTEST(GrowthInfoTest, HasNoGrowthLeftAssumingMayHaveDeleted) {\n  GrowthInfo gi;\n  gi.InitGrowthLeftNoDeleted(1);\n  gi.OverwriteFullAsDeleted();\n  EXPECT_EQ(gi.GetGrowthLeft(), 1);\n  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());\n  gi.OverwriteControlAsFull(ctrl_t::kDeleted);\n  EXPECT_EQ(gi.GetGrowthLeft(), 1);\n  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());\n  gi.OverwriteFullAsEmpty();\n  EXPECT_EQ(gi.GetGrowthLeft(), 2);\n  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());\n  gi.OverwriteEmptyAsFull();\n  EXPECT_EQ(gi.GetGrowthLeft(), 1);\n  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());\n  gi.OverwriteEmptyAsFull();\n  EXPECT_EQ(gi.GetGrowthLeft(), 0);\n  EXPECT_TRUE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());\n}\n\nTEST(Util, OptimalMemcpySizeForSooSlotTransfer) {\n  EXPECT_EQ(1, OptimalMemcpySizeForSooSlotTransfer(1));\n  ASSERT_EQ(4, OptimalMemcpySizeForSooSlotTransfer(2));\n  ASSERT_EQ(4, OptimalMemcpySizeForSooSlotTransfer(3));\n  for (size_t slot_size = 4; slot_size <= 8; ++slot_size) {\n    ASSERT_EQ(8, OptimalMemcpySizeForSooSlotTransfer(slot_size));\n  }\n  // If maximum amount of memory is 16, then we can copy up to 16 bytes.\n  for (size_t slot_size = 9; slot_size <= 16; ++slot_size) {\n    ASSERT_EQ(16,\n              OptimalMemcpySizeForSooSlotTransfer(slot_size,\n                                                  /*max_soo_slot_size=*/16));\n    ASSERT_EQ(16,\n              OptimalMemcpySizeForSooSlotTransfer(slot_size,\n                                                  /*max_soo_slot_size=*/24));\n  }\n  // But we shouldn't try to copy more than maximum amount of memory.\n  for (size_t slot_size = 9; slot_size <= 12; ++slot_size) {\n    ASSERT_EQ(12, OptimalMemcpySizeForSooSlotTransfer(\n                      slot_size, /*max_soo_slot_size=*/12));\n  }\n  for (size_t slot_size = 17; slot_size <= 24; ++slot_size) {\n    ASSERT_EQ(24,\n              OptimalMemcpySizeForSooSlotTransfer(slot_size,\n                                                  /*max_soo_slot_size=*/24));\n  }\n  // We shouldn't copy more than maximum.\n  for (size_t slot_size = 17; slot_size <= 20; ++slot_size) {\n    ASSERT_EQ(20,\n              OptimalMemcpySizeForSooSlotTransfer(slot_size,\n                                                  /*max_soo_slot_size=*/20));\n  }\n}\n\nTEST(Util, NormalizeCapacity) {\n  EXPECT_EQ(1, NormalizeCapacity(0));\n  EXPECT_EQ(1, NormalizeCapacity(1));\n  EXPECT_EQ(3, NormalizeCapacity(2));\n  EXPECT_EQ(3, NormalizeCapacity(3));\n  EXPECT_EQ(7, NormalizeCapacity(4));\n  EXPECT_EQ(7, NormalizeCapacity(7));\n  EXPECT_EQ(15, NormalizeCapacity(8));\n  EXPECT_EQ(15, NormalizeCapacity(15));\n  EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1));\n  EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2));\n}\n\nTEST(Util, SizeToCapacitySmallValues) {\n  EXPECT_EQ(SizeToCapacity(0), 0);\n  EXPECT_EQ(SizeToCapacity(1), 1);\n  EXPECT_EQ(SizeToCapacity(2), 3);\n  EXPECT_EQ(SizeToCapacity(3), 3);\n  EXPECT_EQ(SizeToCapacity(4), 7);\n  EXPECT_EQ(SizeToCapacity(5), 7);\n  EXPECT_EQ(SizeToCapacity(6), 7);\n  if (Group::kWidth == 16) {\n    EXPECT_EQ(SizeToCapacity(7), 7);\n    EXPECT_EQ(SizeToCapacity(14), 15);\n  } else {\n    EXPECT_EQ(SizeToCapacity(7), 15);\n  }\n}\n\nTEST(Util, CapacityToGrowthSmallValues) {\n  EXPECT_EQ(CapacityToGrowth(1), 1);\n  EXPECT_EQ(CapacityToGrowth(3), 3);\n  if (Group::kWidth == 16) {\n    EXPECT_EQ(CapacityToGrowth(7), 7);\n  } else {\n    EXPECT_EQ(CapacityToGrowth(7), 6);\n  }\n  EXPECT_EQ(CapacityToGrowth(15), 14);\n  EXPECT_EQ(CapacityToGrowth(31), 28);\n  EXPECT_EQ(CapacityToGrowth(63), 56);\n}\n\nTEST(Util, GrowthAndCapacity) {\n  // Verify that GrowthToCapacity gives the minimum capacity that has enough\n  // growth.\n  for (size_t growth = 1; growth < 10000; ++growth) {\n    SCOPED_TRACE(growth);\n    size_t capacity = SizeToCapacity(growth);\n    ASSERT_TRUE(IsValidCapacity(capacity));\n    // The capacity is large enough for `growth`.\n    ASSERT_THAT(CapacityToGrowth(capacity), Ge(growth));\n    // For (capacity+1) < kWidth, growth should equal capacity.\n    if (capacity + 1 < Group::kWidth) {\n      ASSERT_THAT(CapacityToGrowth(capacity), Eq(capacity));\n    } else {\n      ASSERT_THAT(CapacityToGrowth(capacity), Lt(capacity));\n    }\n    if (growth != 0 && capacity > 1) {\n      // There is no smaller capacity that works.\n      ASSERT_THAT(CapacityToGrowth(capacity / 2), Lt(growth)) << capacity;\n    }\n  }\n\n  for (size_t capacity = Group::kWidth - 1; capacity < 10000;\n       capacity = 2 * capacity + 1) {\n    SCOPED_TRACE(capacity);\n    size_t growth = CapacityToGrowth(capacity);\n    ASSERT_THAT(growth, Lt(capacity));\n    ASSERT_EQ(SizeToCapacity(growth), capacity);\n    ASSERT_EQ(NormalizeCapacity(SizeToCapacity(growth)), capacity);\n  }\n}\n\nTEST(Util, probe_seq) {\n  probe_seq<16> seq(0, 127);\n  auto gen = [&]() {\n    size_t res = seq.offset();\n    seq.next();\n    return res;\n  };\n  std::vector<size_t> offsets(8);\n  std::generate_n(offsets.begin(), 8, gen);\n  EXPECT_THAT(offsets, ElementsAre(0, 16, 48, 96, 32, 112, 80, 64));\n  seq = probe_seq<16>(128, 127);\n  std::generate_n(offsets.begin(), 8, gen);\n  EXPECT_THAT(offsets, ElementsAre(0, 16, 48, 96, 32, 112, 80, 64));\n}\n\nTEST(Batch, DropDeletes) {\n  constexpr size_t kCapacity = 63;\n  constexpr size_t kGroupWidth = container_internal::Group::kWidth;\n  std::vector<ctrl_t> ctrl(kCapacity + 1 + kGroupWidth);\n  ctrl[kCapacity] = ctrl_t::kSentinel;\n  std::vector<ctrl_t> pattern = {\n      ctrl_t::kEmpty, CtrlT(2), ctrl_t::kDeleted, CtrlT(2),\n      ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted};\n  for (size_t i = 0; i != kCapacity; ++i) {\n    ctrl[i] = pattern[i % pattern.size()];\n    if (i < kGroupWidth - 1)\n      ctrl[i + kCapacity + 1] = pattern[i % pattern.size()];\n  }\n  ConvertDeletedToEmptyAndFullToDeleted(ctrl.data(), kCapacity);\n  ASSERT_EQ(ctrl[kCapacity], ctrl_t::kSentinel);\n  for (size_t i = 0; i < kCapacity + kGroupWidth; ++i) {\n    ctrl_t expected = pattern[i % (kCapacity + 1) % pattern.size()];\n    if (i == kCapacity) expected = ctrl_t::kSentinel;\n    if (expected == ctrl_t::kDeleted) expected = ctrl_t::kEmpty;\n    if (IsFull(expected)) expected = ctrl_t::kDeleted;\n    EXPECT_EQ(ctrl[i], expected)\n        << i << \" \" << static_cast<int>(pattern[i % pattern.size()]);\n  }\n}\n\ntemplate <class T, bool kTransferable = false, bool kSoo = false>\nstruct ValuePolicy {\n  using slot_type = T;\n  using key_type = T;\n  using init_type = T;\n\n  using DefaultHash = hash_default_hash<T>;\n  using DefaultEq = std::equal_to<T>;\n  using DefaultAlloc = std::allocator<T>;\n\n  template <class Allocator, class... Args>\n  static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {\n    absl::allocator_traits<Allocator>::construct(*alloc, slot,\n                                                 std::forward<Args>(args)...);\n  }\n\n  template <class Allocator>\n  static void destroy(Allocator* alloc, slot_type* slot) {\n    absl::allocator_traits<Allocator>::destroy(*alloc, slot);\n  }\n\n  template <class Allocator>\n  static std::integral_constant<bool, kTransferable> transfer(\n      Allocator* alloc, slot_type* new_slot, slot_type* old_slot) {\n    construct(alloc, new_slot, std::move(*old_slot));\n    destroy(alloc, old_slot);\n    return {};\n  }\n\n  static T& element(slot_type* slot) { return *slot; }\n\n  template <class F, class... Args>\n  static decltype(absl::container_internal::DecomposeValue(\n      std::declval<F>(), std::declval<Args>()...))\n  apply(F&& f, Args&&... args) {\n    return absl::container_internal::DecomposeValue(\n        std::forward<F>(f), std::forward<Args>(args)...);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n\n  static constexpr bool soo_enabled() { return kSoo; }\n};\n\nusing IntPolicy = ValuePolicy<int64_t>;\nusing Uint8Policy = ValuePolicy<uint8_t>;\n\n// For testing SOO.\ntemplate <int N>\nclass SizedValue {\n public:\n  SizedValue(int64_t v) {  // NOLINT\n    vals_[0] = v;\n  }\n  SizedValue() : SizedValue(0) {}\n  SizedValue(const SizedValue&) = default;\n  SizedValue& operator=(const SizedValue&) = default;\n\n  int64_t operator*() const {\n    // Suppress erroneous uninitialized memory errors on GCC.\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\"\n#endif\n    return vals_[0];\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n  }\n  explicit operator int() const { return **this; }\n  explicit operator int64_t() const { return **this; }\n\n  template <typename H>\n  friend H AbslHashValue(H h, SizedValue sv) {\n    return H::combine(std::move(h), *sv);\n  }\n  bool operator==(const SizedValue& rhs) const { return **this == *rhs; }\n\n private:\n  int64_t vals_[N / sizeof(int64_t)];\n};\ntemplate <int N, bool kSoo>\nusing SizedValuePolicy =\n    ValuePolicy<SizedValue<N>, /*kTransferable=*/true, kSoo>;\n\n// Value is aligned as type T and contains N copies of it.\ntemplate <typename T, int N>\nclass AlignedValue {\n public:\n  AlignedValue(int64_t v) {  // NOLINT\n    for (int i = 0; i < N; ++i) {\n      vals_[i] = v;\n      if (sizeof(T) < sizeof(int64_t)) {\n        v >>= (8 * sizeof(T));\n      } else {\n        v = 0;\n      }\n    }\n  }\n  AlignedValue() : AlignedValue(0) {}\n  AlignedValue(const AlignedValue&) = default;\n  AlignedValue& operator=(const AlignedValue&) = default;\n\n  int64_t operator*() const {\n    if (sizeof(T) == sizeof(int64_t)) {\n      return vals_[0];\n    }\n    int64_t result = 0;\n    for (int i = N - 1; i >= 0; --i) {\n      result <<= (8 * sizeof(T));\n      result += vals_[i];\n    }\n    return result;\n  }\n  explicit operator int() const { return **this; }\n  explicit operator int64_t() const { return **this; }\n\n  template <typename H>\n  friend H AbslHashValue(H h, AlignedValue sv) {\n    return H::combine(std::move(h), *sv);\n  }\n  bool operator==(const AlignedValue& rhs) const { return **this == *rhs; }\n\n private:\n  T vals_[N];\n};\n\nclass StringPolicy {\n  template <class F, class K, class V,\n            class = typename std::enable_if<\n                std::is_convertible<const K&, absl::string_view>::value>::type>\n  decltype(std::declval<F>()(\n      std::declval<const absl::string_view&>(), std::piecewise_construct,\n      std::declval<std::tuple<K>>(),\n      std::declval<V>())) static apply_impl(F&& f,\n                                            std::pair<std::tuple<K>, V> p) {\n    const absl::string_view& key = std::get<0>(p.first);\n    return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),\n                              std::move(p.second));\n  }\n\n public:\n  struct slot_type {\n    struct ctor {};\n\n    template <class... Ts>\n    explicit slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {}\n\n    std::pair<std::string, std::string> pair;\n  };\n\n  using key_type = std::string;\n  using init_type = std::pair<std::string, std::string>;\n\n  using DefaultHash = void;\n  using DefaultEq = void;\n  using DefaultAlloc = void;\n\n  template <class allocator_type, class... Args>\n  static void construct(allocator_type* alloc, slot_type* slot, Args... args) {\n    std::allocator_traits<allocator_type>::construct(\n        *alloc, slot, typename slot_type::ctor(), std::forward<Args>(args)...);\n  }\n\n  template <class allocator_type>\n  static void destroy(allocator_type* alloc, slot_type* slot) {\n    std::allocator_traits<allocator_type>::destroy(*alloc, slot);\n  }\n\n  template <class allocator_type>\n  static void transfer(allocator_type* alloc, slot_type* new_slot,\n                       slot_type* old_slot) {\n    construct(alloc, new_slot, std::move(old_slot->pair));\n    destroy(alloc, old_slot);\n  }\n\n  static std::pair<std::string, std::string>& element(slot_type* slot) {\n    return slot->pair;\n  }\n\n  template <class F, class... Args>\n  static auto apply(F&& f, Args&&... args)\n      -> decltype(apply_impl(std::forward<F>(f),\n                             PairArgs(std::forward<Args>(args)...))) {\n    return apply_impl(std::forward<F>(f),\n                      PairArgs(std::forward<Args>(args)...));\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\nstruct StringHash : absl::Hash<absl::string_view> {\n  using is_transparent = void;\n};\nstruct StringEq : std::equal_to<absl::string_view> {\n  using is_transparent = void;\n};\n\nstruct StringTable\n    : raw_hash_set<StringPolicy, StringHash, StringEq, std::allocator<int>> {\n  using Base = typename StringTable::raw_hash_set;\n  StringTable() = default;\n  using Base::Base;\n};\n\ntemplate <typename T, bool kTransferable = false, bool kSoo = false,\n          class Alloc = std::allocator<T>>\nstruct ValueTable : InstantiateRawHashSet<ValuePolicy<T, kTransferable, kSoo>,\n                                          hash_default_hash<T>,\n                                          std::equal_to<T>, Alloc>::type {\n  using Base = typename ValueTable::raw_hash_set;\n  using Base::Base;\n};\n\nusing IntTable = ValueTable<int64_t>;\nusing Uint8Table = ValueTable<uint8_t>;\n\nusing TransferableIntTable = ValueTable<int64_t, /*kTransferable=*/true>;\n\ntemplate <typename T>\nstruct CustomAlloc : std::allocator<T> {\n  CustomAlloc() = default;\n\n  template <typename U>\n  explicit CustomAlloc(const CustomAlloc<U>& /*other*/) {}\n\n  template <class U>\n  struct rebind {\n    using other = CustomAlloc<U>;\n  };\n};\n\nstruct CustomAllocIntTable\n    : raw_hash_set<IntPolicy, hash_default_hash<int64_t>,\n                   std::equal_to<int64_t>, CustomAlloc<int64_t>> {\n  using Base = typename CustomAllocIntTable::raw_hash_set;\n  using Base::Base;\n};\n\ntemplate <typename T>\nstruct ChangingSizeAndTrackingTypeAlloc : std::allocator<T> {\n  ChangingSizeAndTrackingTypeAlloc() = default;\n\n  template <typename U>\n  explicit ChangingSizeAndTrackingTypeAlloc(\n      const ChangingSizeAndTrackingTypeAlloc<U>& other) {\n    EXPECT_EQ(other.type_id,\n              ChangingSizeAndTrackingTypeAlloc<U>::ComputeTypeId());\n  }\n\n  template <class U>\n  struct rebind {\n    using other = ChangingSizeAndTrackingTypeAlloc<U>;\n  };\n\n  T* allocate(size_t n) {\n    EXPECT_EQ(type_id, ComputeTypeId());\n    return std::allocator<T>::allocate(n);\n  }\n\n  void deallocate(T* p, std::size_t n) {\n    EXPECT_EQ(type_id, ComputeTypeId());\n    return std::allocator<T>::deallocate(p, n);\n  }\n\n  static size_t ComputeTypeId() { return absl::HashOf(typeid(T).name()); }\n\n  // We add extra data to make the allocator size being changed.\n  // This also make type_id positioned differently, so that assertions in the\n  // allocator can catch bugs more likely.\n  char data_before[sizeof(T) * 3] = {0};\n  size_t type_id = ComputeTypeId();\n  char data_after[sizeof(T) * 5] = {0};\n};\n\nstruct ChangingSizeAllocIntTable\n    : raw_hash_set<IntPolicy, hash_default_hash<int64_t>,\n                   std::equal_to<int64_t>,\n                   ChangingSizeAndTrackingTypeAlloc<int64_t>> {\n  using Base = typename ChangingSizeAllocIntTable::raw_hash_set;\n  using Base::Base;\n};\n\nstruct MinimumAlignmentUint8Table\n    : raw_hash_set<Uint8Policy, hash_default_hash<uint8_t>,\n                   std::equal_to<uint8_t>, MinimumAlignmentAlloc<uint8_t>> {\n  using Base = typename MinimumAlignmentUint8Table::raw_hash_set;\n  using Base::Base;\n};\n\n// Allows for freezing the allocator to expect no further allocations.\ntemplate <typename T>\nstruct FreezableAlloc : std::allocator<T> {\n  explicit FreezableAlloc(bool* f) : frozen(f) {}\n\n  template <typename U>\n  explicit FreezableAlloc(const FreezableAlloc<U>& other)\n      : frozen(other.frozen) {}\n\n  template <class U>\n  struct rebind {\n    using other = FreezableAlloc<U>;\n  };\n\n  T* allocate(size_t n) {\n    EXPECT_FALSE(*frozen);\n    return std::allocator<T>::allocate(n);\n  }\n\n  bool* frozen;\n};\n\ntemplate <int N>\nstruct FreezableSizedValueSooTable\n    : raw_hash_set<SizedValuePolicy<N, /*kSoo=*/true>,\n                   container_internal::hash_default_hash<SizedValue<N>>,\n                   std::equal_to<SizedValue<N>>,\n                   FreezableAlloc<SizedValue<N>>> {\n  using Base = typename FreezableSizedValueSooTable::raw_hash_set;\n  using Base::Base;\n};\n\nstruct BadFastHash {\n  template <class T>\n  size_t operator()(const T&) const {\n    return 0;\n  }\n};\n\nstruct BadHashFreezableIntTable\n    : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<int64_t>,\n                   FreezableAlloc<int64_t>> {\n  using Base = typename BadHashFreezableIntTable::raw_hash_set;\n  using Base::Base;\n};\n\nstruct BadTable : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<int64_t>,\n                               std::allocator<int>> {\n  using Base = typename BadTable::raw_hash_set;\n  BadTable() = default;\n  using Base::Base;\n};\n\nconstexpr size_t kNonSooSize = sizeof(HeapOrSoo) + 8;\nusing NonSooIntTableSlotType = SizedValue<kNonSooSize>;\nstatic_assert(sizeof(NonSooIntTableSlotType) >= kNonSooSize, \"too small\");\nusing NonSooIntTable = ValueTable<NonSooIntTableSlotType>;\nusing SooInt32Table =\n    ValueTable<int32_t, /*kTransferable=*/true, /*kSoo=*/true>;\nusing SooIntTable = ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true>;\nusing NonMemcpyableSooIntTable =\n    ValueTable<int64_t, /*kTransferable=*/false, /*kSoo=*/true>;\nusing MemcpyableSooIntCustomAllocTable =\n    ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true,\n               ChangingSizeAndTrackingTypeAlloc<int64_t>>;\nusing NonMemcpyableSooIntCustomAllocTable =\n    ValueTable<int64_t, /*kTransferable=*/false, /*kSoo=*/true,\n               ChangingSizeAndTrackingTypeAlloc<int64_t>>;\n\nTEST(Table, EmptyFunctorOptimization) {\n  static_assert(std::is_empty<std::equal_to<absl::string_view>>::value, \"\");\n  static_assert(std::is_empty<std::allocator<int>>::value, \"\");\n\n  struct MockTable {\n    size_t capacity;\n    uint64_t size;\n    void* ctrl;\n    void* slots;\n  };\n  struct StatelessHash {\n    size_t operator()(absl::string_view) const { return 0; }\n  };\n  struct StatefulHash : StatelessHash {\n    uint64_t dummy;\n  };\n\n  struct GenerationData {\n    size_t reserved_growth;\n    size_t reservation_size;\n    GenerationType* generation;\n  };\n\n// Ignore unreachable-code warning. Compiler thinks one branch of each ternary\n// conditional is unreachable.\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunreachable-code\"\n#endif\n  constexpr size_t mock_size = sizeof(MockTable);\n  constexpr size_t generation_size =\n      SwisstableGenerationsEnabled() ? sizeof(GenerationData) : 0;\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n\n  EXPECT_EQ(\n      mock_size + generation_size,\n      sizeof(\n          raw_hash_set<StringPolicy, StatelessHash,\n                       std::equal_to<absl::string_view>, std::allocator<int>>));\n\n  EXPECT_EQ(\n      mock_size + sizeof(StatefulHash) + generation_size,\n      sizeof(\n          raw_hash_set<StringPolicy, StatefulHash,\n                       std::equal_to<absl::string_view>, std::allocator<int>>));\n}\n\nTEST(InstantiateRawHashSetTest, VerifyTypes) {\n  using P = ValuePolicy<int>;\n  using DA = typename P::DefaultHash;\n  using DB = typename P::DefaultEq;\n  using DC = typename P::DefaultAlloc;\n\n  struct A {};\n  struct B {};\n  struct C {};\n\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, A, B, C>::type,\n                              raw_hash_set<P, A, B, C>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, A, B, DC>::type,\n                              raw_hash_set<P, A, B>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, A, DB, C>::type,\n                              raw_hash_set<P, A, DB, C>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, A, DB, DC>::type,\n                              raw_hash_set<P, A>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, DA, B, C>::type,\n                              raw_hash_set<P, DA, B, C>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, DA, B, DC>::type,\n                              raw_hash_set<P, DA, B>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, DA, DB, C>::type,\n                              raw_hash_set<P, DA, DB, C>>));\n  EXPECT_TRUE((std::is_same_v<InstantiateRawHashSet<P, DA, DB, DC>::type,\n                              raw_hash_set<P>>));\n}\n\ntemplate <class TableType>\nclass SooTest : public testing::Test {};\n\nusing SooTableTypes =\n    ::testing::Types<SooIntTable, NonSooIntTable, NonMemcpyableSooIntTable,\n                     MemcpyableSooIntCustomAllocTable,\n                     NonMemcpyableSooIntCustomAllocTable>;\nTYPED_TEST_SUITE(SooTest, SooTableTypes);\n\nTYPED_TEST(SooTest, Empty) {\n  TypeParam t;\n  EXPECT_EQ(0, t.size());\n  EXPECT_TRUE(t.empty());\n}\n\nTEST(Table, Prefetch) {\n  IntTable t;\n  t.emplace(1);\n  // Works for both present and absent keys.\n  t.prefetch(1);\n  t.prefetch(2);\n\n  static constexpr int size = 10;\n  for (int i = 0; i < size; ++i) t.insert(i);\n  for (int i = 0; i < size; ++i) {\n    t.prefetch(i);\n    ASSERT_TRUE(t.find(i) != t.end()) << i;\n  }\n}\n\nTYPED_TEST(SooTest, LookupEmpty) {\n  TypeParam t;\n  auto it = t.find(0);\n  EXPECT_TRUE(it == t.end());\n}\n\nTYPED_TEST(SooTest, Insert1) {\n  TypeParam t;\n  EXPECT_TRUE(t.find(0) == t.end());\n  auto res = t.emplace(0);\n  EXPECT_TRUE(res.second);\n  EXPECT_THAT(*res.first, 0);\n  EXPECT_EQ(1, t.size());\n  EXPECT_THAT(*t.find(0), 0);\n}\n\nTYPED_TEST(SooTest, Insert2) {\n  TypeParam t;\n  EXPECT_TRUE(t.find(0) == t.end());\n  auto res = t.emplace(0);\n  EXPECT_TRUE(res.second);\n  EXPECT_THAT(*res.first, 0);\n  EXPECT_EQ(1, t.size());\n  EXPECT_TRUE(t.find(1) == t.end());\n  res = t.emplace(1);\n  EXPECT_TRUE(res.second);\n  EXPECT_THAT(*res.first, 1);\n  EXPECT_EQ(2, t.size());\n  EXPECT_THAT(*t.find(0), 0);\n  EXPECT_THAT(*t.find(1), 1);\n}\n\nTEST(Table, InsertCollision) {\n  BadTable t;\n  EXPECT_TRUE(t.find(1) == t.end());\n  auto res = t.emplace(1);\n  EXPECT_TRUE(res.second);\n  EXPECT_THAT(*res.first, 1);\n  EXPECT_EQ(1, t.size());\n\n  EXPECT_TRUE(t.find(2) == t.end());\n  res = t.emplace(2);\n  EXPECT_THAT(*res.first, 2);\n  EXPECT_TRUE(res.second);\n  EXPECT_EQ(2, t.size());\n\n  EXPECT_THAT(*t.find(1), 1);\n  EXPECT_THAT(*t.find(2), 2);\n}\n\n// Test that we do not add existent element in case we need to search through\n// many groups with deleted elements\nTEST(Table, InsertCollisionAndFindAfterDelete) {\n  BadTable t;  // all elements go to the same group.\n  // Have at least 2 groups with Group::kWidth collisions\n  // plus some extra collisions in the last group.\n  constexpr size_t kNumInserts = Group::kWidth * 2 + 5;\n  for (size_t i = 0; i < kNumInserts; ++i) {\n    auto res = t.emplace(i);\n    EXPECT_TRUE(res.second);\n    EXPECT_THAT(*res.first, i);\n    EXPECT_EQ(i + 1, t.size());\n  }\n\n  // Remove elements one by one and check\n  // that we still can find all other elements.\n  for (size_t i = 0; i < kNumInserts; ++i) {\n    EXPECT_EQ(1, t.erase(i)) << i;\n    for (size_t j = i + 1; j < kNumInserts; ++j) {\n      EXPECT_THAT(*t.find(j), j);\n      auto res = t.emplace(j);\n      EXPECT_FALSE(res.second) << i << \" \" << j;\n      EXPECT_THAT(*res.first, j);\n      EXPECT_EQ(kNumInserts - i - 1, t.size());\n    }\n  }\n  EXPECT_TRUE(t.empty());\n}\n\nTYPED_TEST(SooTest, EraseInSmallTables) {\n  for (int64_t size = 0; size < 64; ++size) {\n    TypeParam t;\n    for (int64_t i = 0; i < size; ++i) {\n      t.insert(i);\n    }\n    for (int64_t i = 0; i < size; ++i) {\n      t.erase(i);\n      EXPECT_EQ(t.size(), size - i - 1);\n      for (int64_t j = i + 1; j < size; ++j) {\n        EXPECT_THAT(*t.find(j), j);\n      }\n    }\n    EXPECT_TRUE(t.empty());\n  }\n}\n\nTYPED_TEST(SooTest, InsertWithinCapacity) {\n  TypeParam t;\n  t.reserve(10);\n  const size_t original_capacity = t.capacity();\n  const auto addr = [&](int i) {\n    return reinterpret_cast<uintptr_t>(&*t.find(i));\n  };\n  // Inserting an element does not change capacity.\n  t.insert(0);\n  EXPECT_THAT(t.capacity(), original_capacity);\n  const uintptr_t original_addr_0 = addr(0);\n  // Inserting another element does not rehash.\n  t.insert(1);\n  EXPECT_THAT(t.capacity(), original_capacity);\n  EXPECT_THAT(addr(0), original_addr_0);\n  // Inserting lots of duplicate elements does not rehash.\n  for (int i = 0; i < 100; ++i) {\n    t.insert(i % 10);\n  }\n  EXPECT_THAT(t.capacity(), original_capacity);\n  EXPECT_THAT(addr(0), original_addr_0);\n  // Inserting a range of duplicate elements does not rehash.\n  std::vector<int> dup_range;\n  for (int i = 0; i < 100; ++i) {\n    dup_range.push_back(i % 10);\n  }\n  t.insert(dup_range.begin(), dup_range.end());\n  EXPECT_THAT(t.capacity(), original_capacity);\n  EXPECT_THAT(addr(0), original_addr_0);\n}\n\ntemplate <class TableType>\nclass SmallTableResizeTest : public testing::Test {};\n\nusing SmallTableTypes = ::testing::Types<\n    IntTable, TransferableIntTable, SooIntTable,\n    // int8\n    ValueTable<int8_t, /*kTransferable=*/true, /*kSoo=*/true>,\n    ValueTable<int8_t, /*kTransferable=*/false, /*kSoo=*/true>,\n    // int16\n    ValueTable<int16_t, /*kTransferable=*/true, /*kSoo=*/true>,\n    ValueTable<int16_t, /*kTransferable=*/false, /*kSoo=*/true>,\n    // int128\n    ValueTable<SizedValue<16>, /*kTransferable=*/true, /*kSoo=*/true>,\n    ValueTable<SizedValue<16>, /*kTransferable=*/false, /*kSoo=*/true>,\n    // int192\n    ValueTable<SizedValue<24>, /*kTransferable=*/true, /*kSoo=*/true>,\n    ValueTable<SizedValue<24>, /*kTransferable=*/false, /*kSoo=*/true>,\n    // Special tables.\n    MinimumAlignmentUint8Table, CustomAllocIntTable, ChangingSizeAllocIntTable,\n    BadTable,\n    // alignment 1, size 2.\n    ValueTable<AlignedValue<uint8_t, 2>, /*kTransferable=*/true, /*kSoo=*/true>,\n    ValueTable<AlignedValue<uint8_t, 2>, /*kTransferable=*/false,\n               /*kSoo=*/true>,\n    // alignment 1, size 7.\n    ValueTable<AlignedValue<uint8_t, 7>, /*kTransferable=*/true, /*kSoo=*/true>,\n    ValueTable<AlignedValue<uint8_t, 7>, /*kTransferable=*/false,\n               /*kSoo=*/true>,\n    // alignment 2, size 6.\n    ValueTable<AlignedValue<uint16_t, 3>, /*kTransferable=*/true,\n               /*kSoo=*/true>,\n    ValueTable<AlignedValue<uint16_t, 3>, /*kTransferable=*/false,\n               /*kSoo=*/true>,\n    // alignment 2, size 10.\n    ValueTable<AlignedValue<uint16_t, 5>, /*kTransferable=*/true,\n               /*kSoo=*/true>,\n    ValueTable<AlignedValue<uint16_t, 5>, /*kTransferable=*/false,\n               /*kSoo=*/true>>;\nTYPED_TEST_SUITE(SmallTableResizeTest, SmallTableTypes);\n\nTYPED_TEST(SmallTableResizeTest, InsertIntoSmallTable) {\n  TypeParam t;\n  for (int i = 0; i < 32; ++i) {\n    t.insert(i);\n    ASSERT_EQ(t.size(), i + 1);\n    for (int j = 0; j < i + 1; ++j) {\n      ASSERT_TRUE(t.find(j) != t.end());\n      EXPECT_EQ(*t.find(j), j);\n    }\n  }\n}\n\nTYPED_TEST(SmallTableResizeTest, ResizeGrowSmallTables) {\n  for (size_t source_size = 0; source_size < 32; ++source_size) {\n    for (size_t target_size = source_size; target_size < 32; ++target_size) {\n      for (bool rehash : {false, true}) {\n        SCOPED_TRACE(absl::StrCat(\"source_size: \", source_size,\n                                  \", target_size: \", target_size,\n                                  \", rehash: \", rehash));\n        TypeParam t;\n        for (size_t i = 0; i < source_size; ++i) {\n          t.insert(static_cast<int>(i));\n        }\n        if (rehash) {\n          t.rehash(target_size);\n        } else {\n          t.reserve(target_size);\n        }\n        for (size_t i = 0; i < source_size; ++i) {\n          ASSERT_TRUE(t.find(static_cast<int>(i)) != t.end());\n          EXPECT_EQ(*t.find(static_cast<int>(i)), static_cast<int>(i));\n        }\n      }\n    }\n  }\n}\n\nTYPED_TEST(SmallTableResizeTest, ResizeReduceSmallTables) {\n  DisableSampling();\n  for (size_t source_size = 0; source_size < 32; ++source_size) {\n    for (size_t target_size = 0; target_size <= source_size; ++target_size) {\n      TypeParam t;\n      size_t inserted_count = std::min<size_t>(source_size, 5);\n      for (size_t i = 0; i < inserted_count; ++i) {\n        t.insert(static_cast<int>(i));\n      }\n      const size_t minimum_capacity = t.capacity();\n      t.reserve(source_size);\n      t.rehash(target_size);\n      if (target_size == 0) {\n        EXPECT_EQ(t.capacity(), minimum_capacity)\n            << \"rehash(0) must resize to the minimum capacity\";\n      }\n      for (size_t i = 0; i < inserted_count; ++i) {\n        ASSERT_TRUE(t.find(static_cast<int>(i)) != t.end());\n        EXPECT_EQ(*t.find(static_cast<int>(i)), static_cast<int>(i));\n      }\n    }\n  }\n}\n\nTEST(Table, LazyEmplace) {\n  StringTable t;\n  bool called = false;\n  auto it = t.lazy_emplace(\"abc\", [&](const StringTable::constructor& f) {\n    called = true;\n    f(\"abc\", \"ABC\");\n  });\n  EXPECT_TRUE(called);\n  EXPECT_THAT(*it, Pair(\"abc\", \"ABC\"));\n  called = false;\n  it = t.lazy_emplace(\"abc\", [&](const StringTable::constructor& f) {\n    called = true;\n    f(\"abc\", \"DEF\");\n  });\n  EXPECT_FALSE(called);\n  EXPECT_THAT(*it, Pair(\"abc\", \"ABC\"));\n}\n\nTYPED_TEST(SooTest, ContainsEmpty) {\n  TypeParam t;\n\n  EXPECT_FALSE(t.contains(0));\n}\n\nTYPED_TEST(SooTest, Contains1) {\n  TypeParam t;\n\n  EXPECT_TRUE(t.insert(0).second);\n  EXPECT_TRUE(t.contains(0));\n  EXPECT_FALSE(t.contains(1));\n\n  EXPECT_EQ(1, t.erase(0));\n  EXPECT_FALSE(t.contains(0));\n}\n\nTYPED_TEST(SooTest, Contains2) {\n  TypeParam t;\n\n  EXPECT_TRUE(t.insert(0).second);\n  EXPECT_TRUE(t.contains(0));\n  EXPECT_FALSE(t.contains(1));\n\n  t.clear();\n  EXPECT_FALSE(t.contains(0));\n\n  EXPECT_TRUE(t.insert(0).second);\n  EXPECT_TRUE(t.contains(0));\n}\n\nint decompose_constructed;\nint decompose_copy_constructed;\nint decompose_copy_assigned;\nint decompose_move_constructed;\nint decompose_move_assigned;\nstruct DecomposeType {\n  DecomposeType(int i = 0) : i(i) {  // NOLINT\n    ++decompose_constructed;\n  }\n\n  explicit DecomposeType(const char* d) : DecomposeType(*d) {}\n\n  DecomposeType(const DecomposeType& other) : i(other.i) {\n    ++decompose_copy_constructed;\n  }\n  DecomposeType& operator=(const DecomposeType& other) {\n    ++decompose_copy_assigned;\n    i = other.i;\n    return *this;\n  }\n  DecomposeType(DecomposeType&& other) : i(other.i) {\n    ++decompose_move_constructed;\n  }\n  DecomposeType& operator=(DecomposeType&& other) {\n    ++decompose_move_assigned;\n    i = other.i;\n    return *this;\n  }\n\n  int i;\n};\n\nstruct DecomposeHash {\n  using is_transparent = void;\n  size_t operator()(const DecomposeType& a) const { return a.i; }\n  size_t operator()(int a) const { return a; }\n  size_t operator()(const char* a) const { return *a; }\n};\n\nstruct DecomposeEq {\n  using is_transparent = void;\n  bool operator()(const DecomposeType& a, const DecomposeType& b) const {\n    return a.i == b.i;\n  }\n  bool operator()(const DecomposeType& a, int b) const { return a.i == b; }\n  bool operator()(const DecomposeType& a, const char* b) const {\n    return a.i == *b;\n  }\n};\n\nstruct DecomposePolicy {\n  using slot_type = DecomposeType;\n  using key_type = DecomposeType;\n  using init_type = DecomposeType;\n\n  using DefaultHash = void;\n  using DefaultEq = void;\n  using DefaultAlloc = void;\n\n  template <typename T>\n  static void construct(void*, DecomposeType* slot, T&& v) {\n    ::new (slot) DecomposeType(std::forward<T>(v));\n  }\n  static void destroy(void*, DecomposeType* slot) { slot->~DecomposeType(); }\n  static DecomposeType& element(slot_type* slot) { return *slot; }\n\n  template <class F, class T>\n  static auto apply(F&& f, const T& x) -> decltype(std::forward<F>(f)(x, x)) {\n    return std::forward<F>(f)(x, x);\n  }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return nullptr;\n  }\n};\n\ntemplate <typename Hash, typename Eq>\nvoid TestDecompose(bool construct_three) {\n  DecomposeType elem{0};\n  const int one = 1;\n  const char* three_p = \"3\";\n  const auto& three = three_p;\n  const int elem_vector_count = 256;\n  std::vector<DecomposeType> elem_vector(elem_vector_count, DecomposeType{0});\n  std::iota(elem_vector.begin(), elem_vector.end(), 0);\n\n  using DecomposeSet =\n      raw_hash_set<DecomposePolicy, Hash, Eq, std::allocator<int>>;\n  DecomposeSet set1;\n\n  decompose_constructed = 0;\n  int expected_constructed = 0;\n  EXPECT_EQ(expected_constructed, decompose_constructed);\n  set1.insert(elem);\n  EXPECT_EQ(expected_constructed, decompose_constructed);\n  set1.insert(1);\n  EXPECT_EQ(++expected_constructed, decompose_constructed);\n  set1.emplace(\"3\");\n  EXPECT_EQ(++expected_constructed, decompose_constructed);\n  EXPECT_EQ(expected_constructed, decompose_constructed);\n\n  {  // insert(T&&)\n    set1.insert(1);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n  }\n\n  {  // insert(const T&)\n    set1.insert(one);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n  }\n\n  {  // insert(hint, T&&)\n    set1.insert(set1.begin(), 1);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n  }\n\n  {  // insert(hint, const T&)\n    set1.insert(set1.begin(), one);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n  }\n\n  {  // emplace(...)\n    set1.emplace(1);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n    set1.emplace(\"3\");\n    expected_constructed += construct_three;\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n    set1.emplace(one);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n    set1.emplace(three);\n    expected_constructed += construct_three;\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n  }\n\n  {  // emplace_hint(...)\n    set1.emplace_hint(set1.begin(), 1);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n    set1.emplace_hint(set1.begin(), \"3\");\n    expected_constructed += construct_three;\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n    set1.emplace_hint(set1.begin(), one);\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n    set1.emplace_hint(set1.begin(), three);\n    expected_constructed += construct_three;\n    EXPECT_EQ(expected_constructed, decompose_constructed);\n  }\n\n  decompose_copy_constructed = 0;\n  decompose_copy_assigned = 0;\n  decompose_move_constructed = 0;\n  decompose_move_assigned = 0;\n  int expected_copy_constructed = 0;\n  int expected_move_constructed = 0;\n  {  // raw_hash_set(first, last) with random-access iterators\n    DecomposeSet set2(elem_vector.begin(), elem_vector.end());\n    // Expect exactly one copy-constructor call for each element if no\n    // rehashing is done.\n    expected_copy_constructed += elem_vector_count;\n    EXPECT_EQ(expected_copy_constructed, decompose_copy_constructed);\n    EXPECT_EQ(expected_move_constructed, decompose_move_constructed);\n    EXPECT_EQ(0, decompose_move_assigned);\n    EXPECT_EQ(0, decompose_copy_assigned);\n  }\n\n  {  // raw_hash_set(first, last) with forward iterators\n    std::list<DecomposeType> elem_list(elem_vector.begin(), elem_vector.end());\n    expected_copy_constructed = decompose_copy_constructed;\n    DecomposeSet set2(elem_list.begin(), elem_list.end());\n    // Expect exactly N elements copied into set, expect at most 2*N elements\n    // moving internally for all resizing needed (for a growth factor of 2).\n    expected_copy_constructed += elem_vector_count;\n    EXPECT_EQ(expected_copy_constructed, decompose_copy_constructed);\n    expected_move_constructed += elem_vector_count;\n    EXPECT_LT(expected_move_constructed, decompose_move_constructed);\n    expected_move_constructed += elem_vector_count;\n    EXPECT_GE(expected_move_constructed, decompose_move_constructed);\n    EXPECT_EQ(0, decompose_move_assigned);\n    EXPECT_EQ(0, decompose_copy_assigned);\n    expected_copy_constructed = decompose_copy_constructed;\n    expected_move_constructed = decompose_move_constructed;\n  }\n\n  {  // insert(first, last)\n    DecomposeSet set2;\n    set2.insert(elem_vector.begin(), elem_vector.end());\n    // Expect exactly N elements copied into set, expect at most 2*N elements\n    // moving internally for all resizing needed (for a growth factor of 2).\n    const int expected_new_elements = elem_vector_count;\n    const int expected_max_element_moves = 2 * elem_vector_count;\n    expected_copy_constructed += expected_new_elements;\n    EXPECT_EQ(expected_copy_constructed, decompose_copy_constructed);\n    expected_move_constructed += expected_max_element_moves;\n    EXPECT_GE(expected_move_constructed, decompose_move_constructed);\n    EXPECT_EQ(0, decompose_move_assigned);\n    EXPECT_EQ(0, decompose_copy_assigned);\n    expected_copy_constructed = decompose_copy_constructed;\n    expected_move_constructed = decompose_move_constructed;\n  }\n}\n\nTEST(Table, Decompose) {\n  if (SwisstableGenerationsEnabled()) {\n    GTEST_SKIP() << \"Generations being enabled causes extra rehashes.\";\n  }\n\n  TestDecompose<DecomposeHash, DecomposeEq>(false);\n\n  struct TransparentHashIntOverload {\n    size_t operator()(const DecomposeType& a) const { return a.i; }\n    size_t operator()(int a) const { return a; }\n  };\n  struct TransparentEqIntOverload {\n    bool operator()(const DecomposeType& a, const DecomposeType& b) const {\n      return a.i == b.i;\n    }\n    bool operator()(const DecomposeType& a, int b) const { return a.i == b; }\n  };\n  TestDecompose<TransparentHashIntOverload, DecomposeEq>(true);\n  TestDecompose<TransparentHashIntOverload, TransparentEqIntOverload>(true);\n  TestDecompose<DecomposeHash, TransparentEqIntOverload>(true);\n}\n\n// Returns the largest m such that a table with m elements has the same number\n// of buckets as a table with n elements.\nsize_t MaxDensitySize(size_t n) {\n  IntTable t;\n  t.reserve(n);\n  for (size_t i = 0; i != n; ++i) t.emplace(i);\n  const size_t c = t.bucket_count();\n  while (c == t.bucket_count()) t.emplace(n++);\n  return t.size() - 1;\n}\n\nstruct Modulo1000Hash {\n  size_t operator()(int64_t x) const { return static_cast<size_t>(x) % 1000; }\n};\n\nstruct Modulo1000HashTable\n    : public raw_hash_set<IntPolicy, Modulo1000Hash, std::equal_to<int64_t>,\n                          std::allocator<int>> {};\n\n// Test that rehash with no resize happen in case of many deleted slots.\nTEST(Table, RehashWithNoResize) {\n  if (SwisstableGenerationsEnabled()) {\n    GTEST_SKIP() << \"Generations being enabled causes extra rehashes.\";\n  }\n\n  Modulo1000HashTable t;\n  // Adding the same length (and the same hash) strings\n  // to have at least kMinFullGroups groups\n  // with Group::kWidth collisions. Then fill up to MaxDensitySize;\n  const size_t kMinFullGroups = 7;\n  std::vector<int> keys;\n  for (size_t i = 0; i < MaxDensitySize(Group::kWidth * kMinFullGroups); ++i) {\n    int k = i * 1000;\n    t.emplace(k);\n    keys.push_back(k);\n  }\n  const size_t capacity = t.capacity();\n\n  // Remove elements from all groups except the first and the last one.\n  // All elements removed from full groups will be marked as ctrl_t::kDeleted.\n  const size_t erase_begin = Group::kWidth / 2;\n  const size_t erase_end = (t.size() / Group::kWidth - 1) * Group::kWidth;\n  for (size_t i = erase_begin; i < erase_end; ++i) {\n    EXPECT_EQ(1, t.erase(keys[i])) << i;\n  }\n  keys.erase(keys.begin() + erase_begin, keys.begin() + erase_end);\n\n  auto last_key = keys.back();\n  size_t last_key_num_probes = GetHashtableDebugNumProbes(t, last_key);\n\n  // Make sure that we have to make a lot of probes for last key.\n  ASSERT_GT(last_key_num_probes, kMinFullGroups);\n\n  int x = 1;\n  // Insert and erase one element, before inplace rehash happen.\n  while (last_key_num_probes == GetHashtableDebugNumProbes(t, last_key)) {\n    t.emplace(x);\n    ASSERT_EQ(capacity, t.capacity());\n    // All elements should be there.\n    ASSERT_TRUE(t.find(x) != t.end()) << x;\n    for (const auto& k : keys) {\n      ASSERT_TRUE(t.find(k) != t.end()) << k;\n    }\n    t.erase(x);\n    ++x;\n  }\n}\n\nTYPED_TEST(SooTest, InsertEraseStressTest) {\n  TypeParam t;\n  const size_t kMinElementCount = 50;\n  std::deque<int> keys;\n  size_t i = 0;\n  for (; i < MaxDensitySize(kMinElementCount); ++i) {\n    t.emplace(static_cast<int64_t>(i));\n    keys.push_back(i);\n  }\n  const size_t kNumIterations = 20000;\n  for (; i < kNumIterations; ++i) {\n    ASSERT_EQ(1, t.erase(keys.front()));\n    keys.pop_front();\n    t.emplace(static_cast<int64_t>(i));\n    keys.push_back(i);\n  }\n}\n\nTEST(Table, InsertOverloads) {\n  StringTable t;\n  // These should all trigger the insert(init_type) overload.\n  t.insert({{}, {}});\n  t.insert({\"ABC\", {}});\n  t.insert({\"DEF\", \"!!!\"});\n\n  EXPECT_THAT(t, UnorderedElementsAre(Pair(\"\", \"\"), Pair(\"ABC\", \"\"),\n                                      Pair(\"DEF\", \"!!!\")));\n}\n\nTYPED_TEST(SooTest, LargeTable) {\n  TypeParam t;\n  for (int64_t i = 0; i != 10000; ++i) {\n    t.emplace(i << 40);\n    ASSERT_EQ(t.size(), i + 1);\n  }\n  for (int64_t i = 0; i != 10000; ++i)\n    ASSERT_EQ(i << 40, static_cast<int64_t>(*t.find(i << 40)));\n}\n\n// Timeout if copy is quadratic as it was in Rust.\nTYPED_TEST(SooTest, EnsureNonQuadraticAsInRust) {\n  static const size_t kLargeSize = 1 << 15;\n\n  TypeParam t;\n  for (size_t i = 0; i != kLargeSize; ++i) {\n    t.insert(i);\n  }\n\n  // If this is quadratic, the test will timeout.\n  TypeParam t2;\n  for (const auto& entry : t) t2.insert(entry);\n}\n\nTYPED_TEST(SooTest, ClearBug) {\n  if (SwisstableGenerationsEnabled()) {\n    GTEST_SKIP() << \"Generations being enabled causes extra rehashes.\";\n  }\n\n  TypeParam t;\n  constexpr size_t capacity = container_internal::Group::kWidth - 1;\n  constexpr size_t max_size = capacity / 2 + 1;\n  for (size_t i = 0; i < max_size; ++i) {\n    t.insert(i);\n  }\n  ASSERT_EQ(capacity, t.capacity());\n  intptr_t original = reinterpret_cast<intptr_t>(&*t.find(2));\n  t.clear();\n  ASSERT_EQ(capacity, t.capacity());\n  for (size_t i = 0; i < max_size; ++i) {\n    t.insert(i);\n  }\n  ASSERT_EQ(capacity, t.capacity());\n  intptr_t second = reinterpret_cast<intptr_t>(&*t.find(2));\n  // We are checking that original and second are close enough to each other\n  // that they are probably still in the same group.  This is not strictly\n  // guaranteed.\n  EXPECT_LT(static_cast<size_t>(std::abs(original - second)),\n            capacity * sizeof(typename TypeParam::value_type));\n}\n\nTYPED_TEST(SooTest, Erase) {\n  TypeParam t;\n  EXPECT_TRUE(t.find(0) == t.end());\n  auto res = t.emplace(0);\n  EXPECT_TRUE(res.second);\n  EXPECT_EQ(1, t.size());\n  t.erase(res.first);\n  EXPECT_EQ(0, t.size());\n  EXPECT_TRUE(t.find(0) == t.end());\n}\n\nTYPED_TEST(SooTest, EraseMaintainsValidIterator) {\n  TypeParam t;\n  const int kNumElements = 100;\n  for (int i = 0; i < kNumElements; i++) {\n    EXPECT_TRUE(t.emplace(i).second);\n  }\n  EXPECT_EQ(t.size(), kNumElements);\n\n  int num_erase_calls = 0;\n  auto it = t.begin();\n  while (it != t.end()) {\n    t.erase(it++);\n    num_erase_calls++;\n  }\n\n  EXPECT_TRUE(t.empty());\n  EXPECT_EQ(num_erase_calls, kNumElements);\n}\n\nTYPED_TEST(SooTest, EraseBeginEnd) {\n  TypeParam t;\n  for (int i = 0; i < 10; ++i) t.insert(i);\n  EXPECT_EQ(t.size(), 10);\n  t.erase(t.begin(), t.end());\n  EXPECT_EQ(t.size(), 0);\n}\n\n// Collect N bad keys by following algorithm:\n// 1. Create an empty table and reserve it to 2 * N.\n// 2. Insert N random elements.\n// 3. Take first Group::kWidth - 1 to bad_keys array.\n// 4. Clear the table without resize.\n// 5. Go to point 2 while N keys not collected\nstd::vector<int64_t> CollectBadMergeKeys(size_t N) {\n  static constexpr int kGroupSize = Group::kWidth - 1;\n\n  auto topk_range = [](size_t b, size_t e,\n                       IntTable* t) -> std::vector<int64_t> {\n    for (size_t i = b; i != e; ++i) {\n      t->emplace(i);\n    }\n    std::vector<int64_t> res;\n    res.reserve(kGroupSize);\n    auto it = t->begin();\n    for (size_t i = b; i != e && i != b + kGroupSize; ++i, ++it) {\n      res.push_back(*it);\n    }\n    return res;\n  };\n\n  std::vector<int64_t> bad_keys;\n  bad_keys.reserve(N);\n  IntTable t;\n  t.reserve(N * 2);\n\n  for (size_t b = 0; bad_keys.size() < N; b += N) {\n    auto keys = topk_range(b, b + N, &t);\n    bad_keys.insert(bad_keys.end(), keys.begin(), keys.end());\n    t.erase(t.begin(), t.end());\n    EXPECT_TRUE(t.empty());\n  }\n  return bad_keys;\n}\n\nstruct ProbeStats {\n  // Number of elements with specific probe length over all tested tables.\n  std::vector<size_t> all_probes_histogram;\n  // Ratios total_probe_length/size for every tested table.\n  std::vector<double> single_table_ratios;\n\n  // Average ratio total_probe_length/size over tables.\n  double AvgRatio() const {\n    return std::accumulate(single_table_ratios.begin(),\n                           single_table_ratios.end(), 0.0) /\n           single_table_ratios.size();\n  }\n\n  // Maximum ratio total_probe_length/size over tables.\n  double MaxRatio() const {\n    return *std::max_element(single_table_ratios.begin(),\n                             single_table_ratios.end());\n  }\n\n  // Percentile ratio total_probe_length/size over tables.\n  double PercentileRatio(double Percentile = 0.95) const {\n    auto r = single_table_ratios;\n    auto mid = r.begin() + static_cast<size_t>(r.size() * Percentile);\n    if (mid != r.end()) {\n      std::nth_element(r.begin(), mid, r.end());\n      return *mid;\n    } else {\n      return MaxRatio();\n    }\n  }\n\n  // Maximum probe length over all elements and all tables.\n  size_t MaxProbe() const { return all_probes_histogram.size(); }\n\n  // Fraction of elements with specified probe length.\n  std::vector<double> ProbeNormalizedHistogram() const {\n    double total_elements = std::accumulate(all_probes_histogram.begin(),\n                                            all_probes_histogram.end(), 0ull);\n    std::vector<double> res;\n    for (size_t p : all_probes_histogram) {\n      res.push_back(p / total_elements);\n    }\n    return res;\n  }\n\n  size_t PercentileProbe(double Percentile = 0.99) const {\n    size_t idx = 0;\n    for (double p : ProbeNormalizedHistogram()) {\n      if (Percentile > p) {\n        Percentile -= p;\n        ++idx;\n      } else {\n        return idx;\n      }\n    }\n    return idx;\n  }\n\n  friend std::ostream& operator<<(std::ostream& out, const ProbeStats& s) {\n    out << \"{AvgRatio:\" << s.AvgRatio() << \", MaxRatio:\" << s.MaxRatio()\n        << \", PercentileRatio:\" << s.PercentileRatio()\n        << \", MaxProbe:\" << s.MaxProbe() << \", Probes=[\";\n    for (double p : s.ProbeNormalizedHistogram()) {\n      out << p << \",\";\n    }\n    out << \"]}\";\n\n    return out;\n  }\n};\n\nstruct ExpectedStats {\n  double avg_ratio;\n  double max_ratio;\n  std::vector<std::pair<double, double>> pecentile_ratios;\n  std::vector<std::pair<double, double>> pecentile_probes;\n\n  friend std::ostream& operator<<(std::ostream& out, const ExpectedStats& s) {\n    out << \"{AvgRatio:\" << s.avg_ratio << \", MaxRatio:\" << s.max_ratio\n        << \", PercentileRatios: [\";\n    for (auto el : s.pecentile_ratios) {\n      out << el.first << \":\" << el.second << \", \";\n    }\n    out << \"], PercentileProbes: [\";\n    for (auto el : s.pecentile_probes) {\n      out << el.first << \":\" << el.second << \", \";\n    }\n    out << \"]}\";\n\n    return out;\n  }\n};\n\nvoid VerifyStats(size_t size, const ExpectedStats& exp,\n                 const ProbeStats& stats) {\n  EXPECT_LT(stats.AvgRatio(), exp.avg_ratio) << size << \" \" << stats;\n  EXPECT_LT(stats.MaxRatio(), exp.max_ratio) << size << \" \" << stats;\n  for (auto pr : exp.pecentile_ratios) {\n    EXPECT_LE(stats.PercentileRatio(pr.first), pr.second)\n        << size << \" \" << pr.first << \" \" << stats;\n  }\n\n  for (auto pr : exp.pecentile_probes) {\n    EXPECT_LE(stats.PercentileProbe(pr.first), pr.second)\n        << size << \" \" << pr.first << \" \" << stats;\n  }\n}\n\nusing ProbeStatsPerSize = std::map<size_t, ProbeStats>;\n\n// Collect total ProbeStats on num_iters iterations of the following algorithm:\n// 1. Create new table and reserve it to keys.size() * 2\n// 2. Insert all keys xored with seed\n// 3. Collect ProbeStats from final table.\nProbeStats CollectProbeStatsOnKeysXoredWithSeed(\n    const std::vector<int64_t>& keys, size_t num_iters) {\n  const size_t reserve_size = keys.size() * 2;\n\n  ProbeStats stats;\n\n  int64_t seed = 0x71b1a19b907d6e33;\n  while (num_iters--) {\n    seed = static_cast<int64_t>(static_cast<uint64_t>(seed) * 17 + 13);\n    IntTable t1;\n    t1.reserve(reserve_size);\n    for (const auto& key : keys) {\n      t1.emplace(key ^ seed);\n    }\n\n    auto probe_histogram = GetHashtableDebugNumProbesHistogram(t1);\n    stats.all_probes_histogram.resize(\n        std::max(stats.all_probes_histogram.size(), probe_histogram.size()));\n    std::transform(probe_histogram.begin(), probe_histogram.end(),\n                   stats.all_probes_histogram.begin(),\n                   stats.all_probes_histogram.begin(), std::plus<size_t>());\n\n    size_t total_probe_seq_length = 0;\n    for (size_t i = 0; i < probe_histogram.size(); ++i) {\n      total_probe_seq_length += i * probe_histogram[i];\n    }\n    stats.single_table_ratios.push_back(total_probe_seq_length * 1.0 /\n                                        keys.size());\n    t1.erase(t1.begin(), t1.end());\n  }\n  return stats;\n}\n\nExpectedStats XorSeedExpectedStats() {\n  constexpr bool kRandomizesInserts =\n#ifdef NDEBUG\n      false;\n#else   // NDEBUG\n      true;\n#endif  // NDEBUG\n\n  // The effective load factor is larger in non-opt mode because we insert\n  // elements out of order.\n  switch (container_internal::Group::kWidth) {\n    case 8:\n      if (kRandomizesInserts) {\n        return {0.05,\n                1.0,\n                {{0.95, 0.5}},\n                {{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}};\n      } else {\n        return {0.05,\n                2.0,\n                {{0.95, 0.1}},\n                {{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}};\n      }\n    case 16:\n      if (kRandomizesInserts) {\n        return {0.1,\n                2.0,\n                {{0.95, 0.1}},\n                {{0.95, 0}, {0.99, 1}, {0.999, 8}, {0.9999, 15}}};\n      } else {\n        return {0.05,\n                1.0,\n                {{0.95, 0.05}},\n                {{0.95, 0}, {0.99, 1}, {0.999, 4}, {0.9999, 10}}};\n      }\n  }\n  LOG(FATAL) << \"Unknown Group width\";\n  return {};\n}\n\n// TODO(b/80415403): Figure out why this test is so flaky, esp. on MSVC\nTEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {\n  ProbeStatsPerSize stats;\n  std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};\n  for (size_t size : sizes) {\n    stats[size] =\n        CollectProbeStatsOnKeysXoredWithSeed(CollectBadMergeKeys(size), 200);\n  }\n  auto expected = XorSeedExpectedStats();\n  for (size_t size : sizes) {\n    auto& stat = stats[size];\n    VerifyStats(size, expected, stat);\n    LOG(INFO) << size << \" \" << stat;\n  }\n}\n\n// Collect total ProbeStats on num_iters iterations of the following algorithm:\n// 1. Create new table\n// 2. Select 10% of keys and insert 10 elements key * 17 + j * 13\n// 3. Collect ProbeStats from final table\nProbeStats CollectProbeStatsOnLinearlyTransformedKeys(\n    const std::vector<int64_t>& keys, size_t num_iters) {\n  ProbeStats stats;\n\n  absl::InsecureBitGen rng;\n  auto linear_transform = [](size_t x, size_t y) { return x * 17 + y * 13; };\n  std::uniform_int_distribution<size_t> dist(0, keys.size() - 1);\n  while (num_iters--) {\n    IntTable t1;\n    size_t num_keys = keys.size() / 10;\n    size_t start = dist(rng);\n    for (size_t i = 0; i != num_keys; ++i) {\n      for (size_t j = 0; j != 10; ++j) {\n        t1.emplace(linear_transform(keys[(i + start) % keys.size()], j));\n      }\n    }\n\n    auto probe_histogram = GetHashtableDebugNumProbesHistogram(t1);\n    stats.all_probes_histogram.resize(\n        std::max(stats.all_probes_histogram.size(), probe_histogram.size()));\n    std::transform(probe_histogram.begin(), probe_histogram.end(),\n                   stats.all_probes_histogram.begin(),\n                   stats.all_probes_histogram.begin(), std::plus<size_t>());\n\n    size_t total_probe_seq_length = 0;\n    for (size_t i = 0; i < probe_histogram.size(); ++i) {\n      total_probe_seq_length += i * probe_histogram[i];\n    }\n    stats.single_table_ratios.push_back(total_probe_seq_length * 1.0 /\n                                        t1.size());\n    t1.erase(t1.begin(), t1.end());\n  }\n  return stats;\n}\n\nExpectedStats LinearTransformExpectedStats() {\n  constexpr bool kRandomizesInserts =\n#ifdef NDEBUG\n      false;\n#else   // NDEBUG\n      true;\n#endif  // NDEBUG\n\n  // The effective load factor is larger in non-opt mode because we insert\n  // elements out of order.\n  switch (container_internal::Group::kWidth) {\n    case 8:\n      if (kRandomizesInserts) {\n        return {0.1,\n                0.5,\n                {{0.95, 0.3}},\n                {{0.95, 0}, {0.99, 1}, {0.999, 8}, {0.9999, 15}}};\n      } else {\n        return {0.4,\n                0.6,\n                {{0.95, 0.5}},\n                {{0.95, 1}, {0.99, 14}, {0.999, 23}, {0.9999, 26}}};\n      }\n    case 16:\n      if (kRandomizesInserts) {\n        return {0.1,\n                0.4,\n                {{0.95, 0.3}},\n                {{0.95, 1}, {0.99, 2}, {0.999, 9}, {0.9999, 15}}};\n      } else {\n        return {0.05,\n                0.2,\n                {{0.95, 0.1}},\n                {{0.95, 0}, {0.99, 1}, {0.999, 6}, {0.9999, 10}}};\n      }\n  }\n  LOG(FATAL) << \"Unknown Group width\";\n  return {};\n}\n\n// TODO(b/80415403): Figure out why this test is so flaky.\nTEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {\n  ProbeStatsPerSize stats;\n  std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};\n  for (size_t size : sizes) {\n    stats[size] = CollectProbeStatsOnLinearlyTransformedKeys(\n        CollectBadMergeKeys(size), 300);\n  }\n  auto expected = LinearTransformExpectedStats();\n  for (size_t size : sizes) {\n    auto& stat = stats[size];\n    VerifyStats(size, expected, stat);\n    LOG(INFO) << size << \" \" << stat;\n  }\n}\n\nTEST(Table, EraseCollision) {\n  BadTable t;\n\n  // 1 2 3\n  t.emplace(1);\n  t.emplace(2);\n  t.emplace(3);\n  EXPECT_THAT(*t.find(1), 1);\n  EXPECT_THAT(*t.find(2), 2);\n  EXPECT_THAT(*t.find(3), 3);\n  EXPECT_EQ(3, t.size());\n\n  // 1 DELETED 3\n  t.erase(t.find(2));\n  EXPECT_THAT(*t.find(1), 1);\n  EXPECT_TRUE(t.find(2) == t.end());\n  EXPECT_THAT(*t.find(3), 3);\n  EXPECT_EQ(2, t.size());\n\n  // DELETED DELETED 3\n  t.erase(t.find(1));\n  EXPECT_TRUE(t.find(1) == t.end());\n  EXPECT_TRUE(t.find(2) == t.end());\n  EXPECT_THAT(*t.find(3), 3);\n  EXPECT_EQ(1, t.size());\n\n  // DELETED DELETED DELETED\n  t.erase(t.find(3));\n  EXPECT_TRUE(t.find(1) == t.end());\n  EXPECT_TRUE(t.find(2) == t.end());\n  EXPECT_TRUE(t.find(3) == t.end());\n  EXPECT_EQ(0, t.size());\n}\n\nTEST(Table, EraseInsertProbing) {\n  BadTable t(100);\n\n  // 1 2 3 4\n  t.emplace(1);\n  t.emplace(2);\n  t.emplace(3);\n  t.emplace(4);\n\n  // 1 DELETED 3 DELETED\n  t.erase(t.find(2));\n  t.erase(t.find(4));\n\n  // 1 10 3 11 12\n  t.emplace(10);\n  t.emplace(11);\n  t.emplace(12);\n\n  EXPECT_EQ(5, t.size());\n  EXPECT_THAT(t, UnorderedElementsAre(1, 10, 3, 11, 12));\n}\n\nTEST(Table, GrowthInfoDeletedBit) {\n  BadTable t;\n  int64_t init_count = static_cast<int64_t>(\n      CapacityToGrowth(NormalizeCapacity(Group::kWidth + 1)));\n  for (int64_t i = 0; i < init_count; ++i) {\n    t.insert(i);\n  }\n  EXPECT_TRUE(\n      RawHashSetTestOnlyAccess::GetCommon(t).growth_info().HasNoDeleted());\n  t.erase(0);\n  EXPECT_EQ(RawHashSetTestOnlyAccess::CountTombstones(t), 1);\n  EXPECT_FALSE(\n      RawHashSetTestOnlyAccess::GetCommon(t).growth_info().HasNoDeleted());\n  t.rehash(0);\n  EXPECT_EQ(RawHashSetTestOnlyAccess::CountTombstones(t), 0);\n  EXPECT_TRUE(\n      RawHashSetTestOnlyAccess::GetCommon(t).growth_info().HasNoDeleted());\n}\n\nTYPED_TEST(SooTest, Clear) {\n  TypeParam t;\n  EXPECT_TRUE(t.find(0) == t.end());\n  t.clear();\n  EXPECT_TRUE(t.find(0) == t.end());\n  auto res = t.emplace(0);\n  EXPECT_TRUE(res.second);\n  EXPECT_EQ(1, t.size());\n  t.clear();\n  EXPECT_EQ(0, t.size());\n  EXPECT_TRUE(t.find(0) == t.end());\n}\n\nTYPED_TEST(SooTest, Swap) {\n  TypeParam t;\n  EXPECT_TRUE(t.find(0) == t.end());\n  auto res = t.emplace(0);\n  EXPECT_TRUE(res.second);\n  EXPECT_EQ(1, t.size());\n  TypeParam u;\n  t.swap(u);\n  EXPECT_EQ(0, t.size());\n  EXPECT_EQ(1, u.size());\n  EXPECT_TRUE(t.find(0) == t.end());\n  EXPECT_THAT(*u.find(0), 0);\n}\n\nTYPED_TEST(SooTest, Rehash) {\n  TypeParam t;\n  EXPECT_TRUE(t.find(0) == t.end());\n  t.emplace(0);\n  t.emplace(1);\n  EXPECT_EQ(2, t.size());\n  t.rehash(128);\n  EXPECT_EQ(2, t.size());\n  EXPECT_THAT(*t.find(0), 0);\n  EXPECT_THAT(*t.find(1), 1);\n}\n\nTYPED_TEST(SooTest, RehashDoesNotRehashWhenNotNecessary) {\n  TypeParam t;\n  t.emplace(0);\n  t.emplace(1);\n  auto* p = &*t.find(0);\n  t.rehash(1);\n  EXPECT_EQ(p, &*t.find(0));\n}\n\n// Following two tests use non-SOO table because they test for 0 capacity.\nTEST(Table, RehashZeroDoesNotAllocateOnEmptyTable) {\n  NonSooIntTable t;\n  t.rehash(0);\n  EXPECT_EQ(0, t.bucket_count());\n}\n\nTEST(Table, RehashZeroDeallocatesEmptyTable) {\n  NonSooIntTable t;\n  t.emplace(0);\n  t.clear();\n  EXPECT_NE(0, t.bucket_count());\n  t.rehash(0);\n  EXPECT_EQ(0, t.bucket_count());\n}\n\nTYPED_TEST(SooTest, RehashZeroForcesRehash) {\n  TypeParam t;\n  t.emplace(0);\n  t.emplace(1);\n  auto* p = &*t.find(0);\n  t.rehash(0);\n  EXPECT_NE(p, &*t.find(0));\n}\n\nTEST(Table, ConstructFromInitList) {\n  using P = std::pair<std::string, std::string>;\n  struct Q {\n    operator P() const { return {}; }  // NOLINT\n  };\n  StringTable t = {P(), Q(), {}, {{}, {}}};\n}\n\nTYPED_TEST(SooTest, CopyConstruct) {\n  TypeParam t;\n  t.emplace(0);\n  EXPECT_EQ(1, t.size());\n  {\n    TypeParam u(t);\n    EXPECT_EQ(1, u.size());\n    EXPECT_THAT(*u.find(0), 0);\n  }\n  {\n    TypeParam u{t};\n    EXPECT_EQ(1, u.size());\n    EXPECT_THAT(*u.find(0), 0);\n  }\n  {\n    TypeParam u = t;\n    EXPECT_EQ(1, u.size());\n    EXPECT_THAT(*u.find(0), 0);\n  }\n}\n\nTYPED_TEST(SooTest, CopyAssignment) {\n  std::vector<size_t> sizes = {0, 1, 7, 25};\n  for (size_t source_size : sizes) {\n    for (size_t target_size : sizes) {\n      SCOPED_TRACE(absl::StrCat(\"source_size: \", source_size,\n                                \" target_size: \", target_size));\n      TypeParam source;\n      std::vector<int> source_elements;\n      for (size_t i = 0; i < source_size; ++i) {\n        source.emplace(static_cast<int>(i) * 2);\n        source_elements.push_back(static_cast<int>(i) * 2);\n      }\n      TypeParam target;\n      for (size_t i = 0; i < target_size; ++i) {\n        target.emplace(static_cast<int>(i) * 3);\n      }\n      target = source;\n      ASSERT_EQ(target.size(), source_size);\n      ASSERT_THAT(target, UnorderedElementsAreArray(source_elements));\n    }\n  }\n}\n\nTYPED_TEST(SooTest, CopyConstructWithSampling) {\n  SetSamplingRateTo1Percent();\n  for (int i = 0; i < 10000; ++i) {\n    TypeParam t;\n    t.emplace(0);\n    EXPECT_EQ(1, t.size());\n    {\n      TypeParam u(t);\n      EXPECT_EQ(1, u.size());\n      EXPECT_THAT(*u.find(0), 0);\n    }\n  }\n}\n\nTYPED_TEST(SooTest, CopyDifferentSizes) {\n  TypeParam t;\n\n  for (int i = 0; i < 100; ++i) {\n    t.emplace(i);\n    TypeParam c = t;\n    for (int j = 0; j <= i; ++j) {\n      ASSERT_TRUE(c.find(j) != c.end()) << \"i=\" << i << \" j=\" << j;\n    }\n    // Testing find miss to verify that table is not full.\n    ASSERT_TRUE(c.find(-1) == c.end());\n  }\n}\n\nTYPED_TEST(SooTest, CopyDifferentCapacities) {\n  for (int cap = 1; cap < 100; cap = cap * 2 + 1) {\n    TypeParam t;\n    t.reserve(static_cast<size_t>(cap));\n    for (int i = 0; i <= cap; ++i) {\n      t.emplace(i);\n      if (i != cap && i % 5 != 0) {\n        continue;\n      }\n      TypeParam c = t;\n      for (int j = 0; j <= i; ++j) {\n        ASSERT_TRUE(c.find(j) != c.end())\n            << \"cap=\" << cap << \" i=\" << i << \" j=\" << j;\n      }\n      // Testing find miss to verify that table is not full.\n      ASSERT_TRUE(c.find(-1) == c.end());\n    }\n  }\n}\n\nTEST(Table, CopyConstructWithAlloc) {\n  StringTable t;\n  t.emplace(\"a\", \"b\");\n  EXPECT_EQ(1, t.size());\n  StringTable u(t, Alloc<std::pair<std::string, std::string>>());\n  EXPECT_EQ(1, u.size());\n  EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n}\n\nstruct ExplicitAllocIntTable\n    : raw_hash_set<IntPolicy, hash_default_hash<int64_t>,\n                   std::equal_to<int64_t>, Alloc<int64_t>> {\n  ExplicitAllocIntTable() = default;\n};\n\nTEST(Table, AllocWithExplicitCtor) {\n  ExplicitAllocIntTable t;\n  EXPECT_EQ(0, t.size());\n}\n\nTEST(Table, MoveConstruct) {\n  {\n    StringTable t;\n    t.emplace(\"a\", \"b\");\n    EXPECT_EQ(1, t.size());\n\n    StringTable u(std::move(t));\n    EXPECT_EQ(1, u.size());\n    EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n  }\n  {\n    StringTable t;\n    t.emplace(\"a\", \"b\");\n    EXPECT_EQ(1, t.size());\n\n    StringTable u{std::move(t)};\n    EXPECT_EQ(1, u.size());\n    EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n  }\n  {\n    StringTable t;\n    t.emplace(\"a\", \"b\");\n    EXPECT_EQ(1, t.size());\n\n    StringTable u = std::move(t);\n    EXPECT_EQ(1, u.size());\n    EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n  }\n}\n\nTEST(Table, MoveConstructWithAlloc) {\n  StringTable t;\n  t.emplace(\"a\", \"b\");\n  EXPECT_EQ(1, t.size());\n  StringTable u(std::move(t), Alloc<std::pair<std::string, std::string>>());\n  EXPECT_EQ(1, u.size());\n  EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n}\n\nTEST(Table, CopyAssign) {\n  StringTable t;\n  t.emplace(\"a\", \"b\");\n  EXPECT_EQ(1, t.size());\n  StringTable u;\n  u = t;\n  EXPECT_EQ(1, u.size());\n  EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n}\n\nTEST(Table, CopySelfAssign) {\n  StringTable t;\n  t.emplace(\"a\", \"b\");\n  EXPECT_EQ(1, t.size());\n  t = *&t;\n  EXPECT_EQ(1, t.size());\n  EXPECT_THAT(*t.find(\"a\"), Pair(\"a\", \"b\"));\n}\n\nTEST(Table, MoveAssign) {\n  StringTable t;\n  t.emplace(\"a\", \"b\");\n  EXPECT_EQ(1, t.size());\n  StringTable u;\n  u = std::move(t);\n  EXPECT_EQ(1, u.size());\n  EXPECT_THAT(*u.find(\"a\"), Pair(\"a\", \"b\"));\n}\n\nTEST(Table, MoveSelfAssign) {\n  StringTable t;\n  t.emplace(\"a\", \"b\");\n  EXPECT_EQ(1, t.size());\n  t = std::move(*&t);\n  if (SwisstableGenerationsEnabled()) {\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t.contains(\"a\"), \"self-move-assigned\");\n  }\n  // As long as we don't crash, it's fine.\n}\n\nTEST(Table, Equality) {\n  StringTable t;\n  std::vector<std::pair<std::string, std::string>> v = {{\"a\", \"b\"},\n                                                        {\"aa\", \"bb\"}};\n  t.insert(std::begin(v), std::end(v));\n  StringTable u = t;\n  EXPECT_EQ(u, t);\n}\n\nTEST(Table, Equality2) {\n  StringTable t;\n  std::vector<std::pair<std::string, std::string>> v1 = {{\"a\", \"b\"},\n                                                         {\"aa\", \"bb\"}};\n  t.insert(std::begin(v1), std::end(v1));\n  StringTable u;\n  std::vector<std::pair<std::string, std::string>> v2 = {{\"a\", \"a\"},\n                                                         {\"aa\", \"aa\"}};\n  u.insert(std::begin(v2), std::end(v2));\n  EXPECT_NE(u, t);\n}\n\nTEST(Table, Equality3) {\n  StringTable t;\n  std::vector<std::pair<std::string, std::string>> v1 = {{\"b\", \"b\"},\n                                                         {\"bb\", \"bb\"}};\n  t.insert(std::begin(v1), std::end(v1));\n  StringTable u;\n  std::vector<std::pair<std::string, std::string>> v2 = {{\"a\", \"a\"},\n                                                         {\"aa\", \"aa\"}};\n  u.insert(std::begin(v2), std::end(v2));\n  EXPECT_NE(u, t);\n}\n\nTYPED_TEST(SooTest, NumDeletedRegression) {\n  TypeParam t;\n  t.emplace(0);\n  t.erase(t.find(0));\n  // construct over a deleted slot.\n  t.emplace(0);\n  t.clear();\n}\n\nTYPED_TEST(SooTest, FindFullDeletedRegression) {\n  TypeParam t;\n  for (int i = 0; i < 1000; ++i) {\n    t.emplace(i);\n    t.erase(t.find(i));\n  }\n  EXPECT_EQ(0, t.size());\n}\n\nTYPED_TEST(SooTest, ReplacingDeletedSlotDoesNotRehash) {\n  // We need to disable hashtablez to avoid issues related to SOO and sampling.\n  DisableSampling();\n\n  size_t n;\n  {\n    // Compute n such that n is the maximum number of elements before rehash.\n    TypeParam t;\n    t.emplace(0);\n    size_t c = t.bucket_count();\n    for (n = 1; c == t.bucket_count(); ++n) t.emplace(n);\n    --n;\n  }\n  TypeParam t;\n  t.rehash(n);\n  const size_t c = t.bucket_count();\n  for (size_t i = 0; i != n; ++i) t.emplace(i);\n  EXPECT_EQ(c, t.bucket_count()) << \"rehashing threshold = \" << n;\n  t.erase(0);\n  t.emplace(0);\n  EXPECT_EQ(c, t.bucket_count()) << \"rehashing threshold = \" << n;\n}\n\nTEST(Table, NoThrowMoveConstruct) {\n  ASSERT_TRUE(\n      std::is_nothrow_copy_constructible<absl::Hash<absl::string_view>>::value);\n  ASSERT_TRUE(std::is_nothrow_copy_constructible<\n              std::equal_to<absl::string_view>>::value);\n  ASSERT_TRUE(std::is_nothrow_copy_constructible<std::allocator<int>>::value);\n  EXPECT_TRUE(std::is_nothrow_move_constructible<StringTable>::value);\n}\n\nTEST(Table, NoThrowMoveAssign) {\n  ASSERT_TRUE(\n      std::is_nothrow_move_assignable<absl::Hash<absl::string_view>>::value);\n  ASSERT_TRUE(\n      std::is_nothrow_move_assignable<std::equal_to<absl::string_view>>::value);\n  ASSERT_TRUE(std::is_nothrow_move_assignable<std::allocator<int>>::value);\n  ASSERT_TRUE(\n      absl::allocator_traits<std::allocator<int>>::is_always_equal::value);\n  EXPECT_TRUE(std::is_nothrow_move_assignable<StringTable>::value);\n}\n\nTEST(Table, NoThrowSwappable) {\n  ASSERT_TRUE(std::is_nothrow_swappable<absl::Hash<absl::string_view>>());\n  ASSERT_TRUE(std::is_nothrow_swappable<std::equal_to<absl::string_view>>());\n  ASSERT_TRUE(std::is_nothrow_swappable<std::allocator<int>>());\n  EXPECT_TRUE(std::is_nothrow_swappable<StringTable>());\n}\n\nTEST(Table, HeterogeneousLookup) {\n  struct Hash {\n    size_t operator()(int64_t i) const { return i; }\n    size_t operator()(double i) const {\n      ADD_FAILURE();\n      return i;\n    }\n  };\n  struct Eq {\n    bool operator()(int64_t a, int64_t b) const { return a == b; }\n    bool operator()(double a, int64_t b) const {\n      ADD_FAILURE();\n      return a == b;\n    }\n    bool operator()(int64_t a, double b) const {\n      ADD_FAILURE();\n      return a == b;\n    }\n    bool operator()(double a, double b) const {\n      ADD_FAILURE();\n      return a == b;\n    }\n  };\n\n  struct THash {\n    using is_transparent = void;\n    size_t operator()(int64_t i) const { return i; }\n    size_t operator()(double i) const { return i; }\n  };\n  struct TEq {\n    using is_transparent = void;\n    bool operator()(int64_t a, int64_t b) const { return a == b; }\n    bool operator()(double a, int64_t b) const { return a == b; }\n    bool operator()(int64_t a, double b) const { return a == b; }\n    bool operator()(double a, double b) const { return a == b; }\n  };\n\n  raw_hash_set<IntPolicy, Hash, Eq, Alloc<int64_t>> s{0, 1, 2};\n  // It will convert to int64_t before the query.\n  EXPECT_EQ(1, *s.find(double{1.1}));\n\n  raw_hash_set<IntPolicy, THash, TEq, Alloc<int64_t>> ts{0, 1, 2};\n  // It will try to use the double, and fail to find the object.\n  EXPECT_TRUE(ts.find(1.1) == ts.end());\n}\n\ntemplate <class Table>\nusing CallFind = decltype(std::declval<Table&>().find(17));\n\ntemplate <class Table>\nusing CallErase = decltype(std::declval<Table&>().erase(17));\n\ntemplate <class Table>\nusing CallExtract = decltype(std::declval<Table&>().extract(17));\n\ntemplate <class Table>\nusing CallPrefetch = decltype(std::declval<Table&>().prefetch(17));\n\ntemplate <class Table>\nusing CallCount = decltype(std::declval<Table&>().count(17));\n\ntemplate <template <typename> class C, class Table, class = void>\nstruct VerifyResultOf : std::false_type {};\n\ntemplate <template <typename> class C, class Table>\nstruct VerifyResultOf<C, Table, absl::void_t<C<Table>>> : std::true_type {};\n\nTEST(Table, HeterogeneousLookupOverloads) {\n  using NonTransparentTable =\n      raw_hash_set<StringPolicy, absl::Hash<absl::string_view>,\n                   std::equal_to<absl::string_view>, std::allocator<int>>;\n\n  EXPECT_FALSE((VerifyResultOf<CallFind, NonTransparentTable>()));\n  EXPECT_FALSE((VerifyResultOf<CallErase, NonTransparentTable>()));\n  EXPECT_FALSE((VerifyResultOf<CallExtract, NonTransparentTable>()));\n  EXPECT_FALSE((VerifyResultOf<CallPrefetch, NonTransparentTable>()));\n  EXPECT_FALSE((VerifyResultOf<CallCount, NonTransparentTable>()));\n\n  using TransparentTable =\n      raw_hash_set<StringPolicy, hash_default_hash<absl::string_view>,\n                   hash_default_eq<absl::string_view>, std::allocator<int>>;\n\n  EXPECT_TRUE((VerifyResultOf<CallFind, TransparentTable>()));\n  EXPECT_TRUE((VerifyResultOf<CallErase, TransparentTable>()));\n  EXPECT_TRUE((VerifyResultOf<CallExtract, TransparentTable>()));\n  EXPECT_TRUE((VerifyResultOf<CallPrefetch, TransparentTable>()));\n  EXPECT_TRUE((VerifyResultOf<CallCount, TransparentTable>()));\n}\n\nTEST(Iterator, IsDefaultConstructible) {\n  StringTable::iterator i;\n  EXPECT_TRUE(i == StringTable::iterator());\n}\n\nTEST(ConstIterator, IsDefaultConstructible) {\n  StringTable::const_iterator i;\n  EXPECT_TRUE(i == StringTable::const_iterator());\n}\n\nTEST(Iterator, ConvertsToConstIterator) {\n  StringTable::iterator i;\n  EXPECT_TRUE(i == StringTable::const_iterator());\n}\n\nTEST(Iterator, Iterates) {\n  IntTable t;\n  for (size_t i = 3; i != 6; ++i) EXPECT_TRUE(t.emplace(i).second);\n  EXPECT_THAT(t, UnorderedElementsAre(3, 4, 5));\n}\n\nTEST(Table, Merge) {\n  StringTable t1, t2;\n  t1.emplace(\"0\", \"-0\");\n  t1.emplace(\"1\", \"-1\");\n  t2.emplace(\"0\", \"~0\");\n  t2.emplace(\"2\", \"~2\");\n\n  EXPECT_THAT(t1, UnorderedElementsAre(Pair(\"0\", \"-0\"), Pair(\"1\", \"-1\")));\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(\"0\", \"~0\"), Pair(\"2\", \"~2\")));\n\n  t1.merge(t2);\n  EXPECT_THAT(t1, UnorderedElementsAre(Pair(\"0\", \"-0\"), Pair(\"1\", \"-1\"),\n                                       Pair(\"2\", \"~2\")));\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(\"0\", \"~0\")));\n}\n\nTEST(Table, MergeSmall) {\n  StringTable t1, t2;\n  t1.emplace(\"1\", \"1\");\n  t2.emplace(\"2\", \"2\");\n\n  EXPECT_THAT(t1, UnorderedElementsAre(Pair(\"1\", \"1\")));\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(\"2\", \"2\")));\n\n  t2.merge(t1);\n  EXPECT_EQ(t1.size(), 0);\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(\"1\", \"1\"), Pair(\"2\", \"2\")));\n}\n\nTEST(Table, IteratorEmplaceConstructibleRequirement) {\n  struct Value {\n    explicit Value(absl::string_view view) : value(view) {}\n    std::string value;\n\n    bool operator==(const Value& other) const { return value == other.value; }\n  };\n  struct H {\n    size_t operator()(const Value& v) const {\n      return absl::Hash<std::string>{}(v.value);\n    }\n  };\n\n  struct Table\n      : InstantiateRawHashSet<ValuePolicy<Value>, H, std::equal_to<Value>,\n                              std::allocator<Value>>::type {\n    using Base = typename Table::raw_hash_set;\n    using Base::Base;\n  };\n\n  std::string input[3]{\"A\", \"B\", \"C\"};\n\n  Table t(std::begin(input), std::end(input));\n  EXPECT_THAT(t, UnorderedElementsAre(Value{\"A\"}, Value{\"B\"}, Value{\"C\"}));\n\n  input[0] = \"D\";\n  input[1] = \"E\";\n  input[2] = \"F\";\n  t.insert(std::begin(input), std::end(input));\n  EXPECT_THAT(t, UnorderedElementsAre(Value{\"A\"}, Value{\"B\"}, Value{\"C\"},\n                                      Value{\"D\"}, Value{\"E\"}, Value{\"F\"}));\n}\n\nTEST(Nodes, EmptyNodeType) {\n  using node_type = StringTable::node_type;\n  node_type n;\n  EXPECT_FALSE(n);\n  EXPECT_TRUE(n.empty());\n\n  EXPECT_TRUE((std::is_same<node_type::allocator_type,\n                            StringTable::allocator_type>::value));\n}\n\nTEST(Nodes, ExtractInsert) {\n  constexpr char k0[] = \"Very long string zero.\";\n  constexpr char k1[] = \"Very long string one.\";\n  constexpr char k2[] = \"Very long string two.\";\n  StringTable t = {{k0, \"\"}, {k1, \"\"}, {k2, \"\"}};\n  EXPECT_THAT(t,\n              UnorderedElementsAre(Pair(k0, \"\"), Pair(k1, \"\"), Pair(k2, \"\")));\n\n  auto node = t.extract(k0);\n  EXPECT_THAT(t, UnorderedElementsAre(Pair(k1, \"\"), Pair(k2, \"\")));\n  EXPECT_TRUE(node);\n  EXPECT_FALSE(node.empty());\n\n  StringTable t2;\n  StringTable::insert_return_type res = t2.insert(std::move(node));\n  EXPECT_TRUE(res.inserted);\n  EXPECT_THAT(*res.position, Pair(k0, \"\"));\n  EXPECT_FALSE(res.node);\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(k0, \"\")));\n\n  // Not there.\n  EXPECT_THAT(t, UnorderedElementsAre(Pair(k1, \"\"), Pair(k2, \"\")));\n  node = t.extract(\"Not there!\");\n  EXPECT_THAT(t, UnorderedElementsAre(Pair(k1, \"\"), Pair(k2, \"\")));\n  EXPECT_FALSE(node);\n\n  // Inserting nothing.\n  res = t2.insert(std::move(node));\n  EXPECT_FALSE(res.inserted);\n  EXPECT_EQ(res.position, t2.end());\n  EXPECT_FALSE(res.node);\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(k0, \"\")));\n\n  t.emplace(k0, \"1\");\n  node = t.extract(k0);\n\n  // Insert duplicate.\n  res = t2.insert(std::move(node));\n  EXPECT_FALSE(res.inserted);\n  EXPECT_THAT(*res.position, Pair(k0, \"\"));\n  EXPECT_TRUE(res.node);\n  EXPECT_FALSE(node);  // NOLINT(bugprone-use-after-move)\n}\n\nTEST(Nodes, ExtractInsertSmall) {\n  constexpr char k0[] = \"Very long string zero.\";\n  StringTable t = {{k0, \"\"}};\n  EXPECT_THAT(t, UnorderedElementsAre(Pair(k0, \"\")));\n\n  auto node = t.extract(k0);\n  EXPECT_EQ(t.size(), 0);\n  EXPECT_TRUE(node);\n  EXPECT_FALSE(node.empty());\n\n  StringTable t2;\n  StringTable::insert_return_type res = t2.insert(std::move(node));\n  EXPECT_TRUE(res.inserted);\n  EXPECT_THAT(*res.position, Pair(k0, \"\"));\n  EXPECT_FALSE(res.node);\n  EXPECT_THAT(t2, UnorderedElementsAre(Pair(k0, \"\")));\n}\n\nTYPED_TEST(SooTest, HintInsert) {\n  TypeParam t = {1, 2, 3};\n  auto node = t.extract(1);\n  EXPECT_THAT(t, UnorderedElementsAre(2, 3));\n  auto it = t.insert(t.begin(), std::move(node));\n  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));\n  EXPECT_EQ(*it, 1);\n  EXPECT_FALSE(node);  // NOLINT(bugprone-use-after-move)\n\n  node = t.extract(2);\n  EXPECT_THAT(t, UnorderedElementsAre(1, 3));\n  // reinsert 2 to make the next insert fail.\n  t.insert(2);\n  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));\n  it = t.insert(t.begin(), std::move(node));\n  EXPECT_EQ(*it, 2);\n  // The node was not emptied by the insert call.\n  EXPECT_TRUE(node);  // NOLINT(bugprone-use-after-move)\n}\n\ntemplate <typename T>\nT MakeSimpleTable(size_t size, bool do_reserve) {\n  T t;\n  if (do_reserve) t.reserve(size);\n  while (t.size() < size) t.insert(t.size());\n  return t;\n}\n\ntemplate <typename T>\nstd::vector<int> OrderOfIteration(const T& t) {\n  std::vector<int> res;\n  for (auto i : t) res.push_back(static_cast<int>(i));\n  return res;\n}\n\n// Generate irrelevant seeds to avoid being stuck in the same last bit\n// in seed.\nvoid GenerateIrrelevantSeeds(int cnt) {\n  for (int i = cnt % 17; i > 0; --i) {\n    HashtableSize::NextSeed();\n  }\n}\n\n// These IterationOrderChanges tests depend on non-deterministic behavior.\n// We are injecting non-determinism to the table.\n// We have to retry enough times to make sure that the seed changes in bits that\n// matter for the iteration order.\nTYPED_TEST(SooTest, IterationOrderChangesByInstance) {\n  DisableSampling();  // We do not want test to pass only because of sampling.\n  for (bool do_reserve : {false, true}) {\n    for (size_t size : {2u, 6u, 12u, 20u}) {\n      SCOPED_TRACE(absl::StrCat(\"size: \", size, \" do_reserve: \", do_reserve));\n      const auto reference_table = MakeSimpleTable<TypeParam>(size, do_reserve);\n      const auto reference = OrderOfIteration(reference_table);\n\n      bool found_difference = false;\n      for (int i = 0; !found_difference && i < 500; ++i) {\n        auto new_table = MakeSimpleTable<TypeParam>(size, do_reserve);\n        found_difference = OrderOfIteration(new_table) != reference;\n        GenerateIrrelevantSeeds(i);\n      }\n      if (!found_difference) {\n        FAIL() << \"Iteration order remained the same across many attempts.\";\n      }\n    }\n  }\n}\n\nTYPED_TEST(SooTest, IterationOrderChangesOnRehash) {\n  DisableSampling();  // We do not want test to pass only because of sampling.\n\n  // We test different sizes with many small numbers, because small table\n  // resize has a different codepath.\n  // Note: iteration order for size() <= 1 is always the same.\n  for (bool do_reserve : {false, true}) {\n    for (size_t size : {2u, 3u, 6u, 7u, 12u, 15u, 20u, 50u}) {\n      for (size_t rehash_size : {\n               size_t{0},        // Force rehash is guaranteed.\n               size * 10  // Rehash to the larger capacity is guaranteed.\n           }) {\n        SCOPED_TRACE(absl::StrCat(\"size: \", size, \" rehash_size: \", rehash_size,\n                                  \" do_reserve: \", do_reserve));\n        bool ok = false;\n        auto t = MakeSimpleTable<TypeParam>(size, do_reserve);\n        const size_t original_capacity = t.capacity();\n        auto reference = OrderOfIteration(t);\n        for (int i = 0; i < 500; ++i) {\n          if (i > 0 && rehash_size != 0) {\n            // Rehash back to original size.\n            t.rehash(0);\n            ASSERT_EQ(t.capacity(), original_capacity);\n            reference = OrderOfIteration(t);\n          }\n          // Force rehash.\n          t.rehash(rehash_size);\n          auto trial = OrderOfIteration(t);\n          if (trial != reference) {\n            // We are done.\n            ok = true;\n            break;\n          }\n          GenerateIrrelevantSeeds(i);\n        }\n        EXPECT_TRUE(ok)\n            << \"Iteration order remained the same across many attempts \" << size\n            << \"->\" << rehash_size << \".\";\n      }\n    }\n  }\n}\n\n// Verify that pointers are invalidated as soon as a second element is inserted.\n// This prevents dependency on pointer stability on small tables.\nTYPED_TEST(SooTest, UnstablePointers) {\n  // We need to disable hashtablez to avoid issues related to SOO and sampling.\n  DisableSampling();\n\n  TypeParam table;\n\n  const auto addr = [&](int i) {\n    return reinterpret_cast<uintptr_t>(&*table.find(i));\n  };\n\n  table.insert(0);\n  const uintptr_t old_ptr = addr(0);\n\n  // This causes a rehash.\n  table.insert(1);\n\n  EXPECT_NE(old_ptr, addr(0));\n}\n\nTEST(TableDeathTest, InvalidIteratorAsserts) {\n  if (!IsAssertEnabled() && !SwisstableGenerationsEnabled())\n    GTEST_SKIP() << \"Assertions not enabled.\";\n\n  NonSooIntTable t;\n  // Extra simple \"regexp\" as regexp support is highly varied across platforms.\n  EXPECT_DEATH_IF_SUPPORTED(++t.end(), \"operator.* called on end.. iterator.\");\n  typename NonSooIntTable::iterator iter;\n  EXPECT_DEATH_IF_SUPPORTED(\n      ++iter, \"operator.* called on default-constructed iterator.\");\n  t.insert(0);\n  t.insert(1);\n  iter = t.begin();\n  t.erase(iter);\n  const char* const kErasedDeathMessage =\n      SwisstableGenerationsEnabled()\n          ? \"operator.* called on invalid iterator.*was likely erased\"\n          : \"operator.* called on invalid iterator.*might have been \"\n            \"erased.*config=asan\";\n  EXPECT_DEATH_IF_SUPPORTED(++iter, kErasedDeathMessage);\n}\n\nTEST(TableDeathTest, InvalidIteratorAssertsSoo) {\n  if (!IsAssertEnabled() && !SwisstableGenerationsEnabled())\n    GTEST_SKIP() << \"Assertions not enabled.\";\n\n  SooIntTable t;\n  // Extra simple \"regexp\" as regexp support is highly varied across platforms.\n  EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()),\n                            \"erase.* called on end.. iterator.\");\n  typename SooIntTable::iterator iter;\n  EXPECT_DEATH_IF_SUPPORTED(\n      ++iter, \"operator.* called on default-constructed iterator.\");\n\n  // We can't detect the erased iterator case as invalid in SOO mode because\n  // the control is static constant.\n}\n\n// Invalid iterator use can trigger use-after-free in asan/hwasan,\n// use-of-uninitialized-value in msan, or invalidated iterator assertions.\ntesting::Matcher<const std::string&> InvalidIteratorMatcher() {\n  return AnyOf(HasSubstr(\"invalidated iterator\"), HasSubstr(\"Invalid iterator\"),\n               HasSubstr(\"invalid iterator\"), HasSubstr(\"use-after-free\"),\n               HasSubstr(\"use-of-uninitialized-value\"));\n}\n\nTYPED_TEST(SooTest, IteratorInvalidAssertsEqualityOperator) {\n  if (!IsAssertEnabled() && !SwisstableGenerationsEnabled())\n    GTEST_SKIP() << \"Assertions not enabled.\";\n\n  TypeParam t;\n  t.insert(1);\n  t.insert(2);\n  t.insert(3);\n  auto iter1 = t.begin();\n  auto iter2 = std::next(iter1);\n  ASSERT_NE(iter1, t.end());\n  ASSERT_NE(iter2, t.end());\n  t.erase(iter1);\n  // Extra simple \"regexp\" as regexp support is highly varied across platforms.\n  const char* const kErasedDeathMessage =\n      SwisstableGenerationsEnabled()\n          ? \"Invalid iterator comparison.*was likely erased\"\n          : \"Invalid iterator comparison.*might have been erased.*config=asan\";\n  EXPECT_DEATH_IF_SUPPORTED(void(iter1 == iter2), kErasedDeathMessage);\n  EXPECT_DEATH_IF_SUPPORTED(void(iter2 != iter1), kErasedDeathMessage);\n  t.erase(iter2);\n  EXPECT_DEATH_IF_SUPPORTED(void(iter1 == iter2), kErasedDeathMessage);\n\n  TypeParam t1, t2;\n  t1.insert(0);\n  t2.insert(0);\n  iter1 = t1.begin();\n  iter2 = t2.begin();\n  const char* const kContainerDiffDeathMessage =\n      SwisstableGenerationsEnabled()\n          ? \"Invalid iterator comparison.*iterators from different.* hashtables\"\n          : \"Invalid iterator comparison.*may be from different \"\n            \".*containers.*config=asan\";\n  EXPECT_DEATH_IF_SUPPORTED(void(iter1 == iter2), kContainerDiffDeathMessage);\n  EXPECT_DEATH_IF_SUPPORTED(void(iter2 == iter1), kContainerDiffDeathMessage);\n}\n\nTYPED_TEST(SooTest, IteratorInvalidAssertsEqualityOperatorRehash) {\n  if (!IsAssertEnabled() && !SwisstableGenerationsEnabled())\n    GTEST_SKIP() << \"Assertions not enabled.\";\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n  GTEST_SKIP() << \"ThreadSanitizer test runs fail on use-after-free even in \"\n                  \"EXPECT_DEATH.\";\n#endif\n\n  TypeParam t;\n  t.insert(0);\n  auto iter = t.begin();\n\n  // Trigger a rehash in t.\n  for (int i = 0; i < 10; ++i) t.insert(i);\n\n  EXPECT_DEATH_IF_SUPPORTED(void(iter == t.begin()), InvalidIteratorMatcher());\n}\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\ntemplate <typename T>\nclass RawHashSamplerTest : public testing::Test {};\n\nusing RawHashSamplerTestTypes = ::testing::Types<\n    // 32 bits to make sure that table is Soo for 32 bits platform as well.\n    // 64 bits table is not SOO due to alignment.\n    SooInt32Table,\n    NonSooIntTable>;\nTYPED_TEST_SUITE(RawHashSamplerTest, RawHashSamplerTestTypes);\n\nTYPED_TEST(RawHashSamplerTest, Sample) {\n  constexpr bool soo_enabled = std::is_same<SooInt32Table, TypeParam>::value;\n  // Enable the feature even if the prod default is off.\n  SetSamplingRateTo1Percent();\n\n  ASSERT_EQ(TypeParam().capacity(), soo_enabled ? SooCapacity() : 0);\n\n  auto& sampler = GlobalHashtablezSampler();\n  size_t start_size = 0;\n\n  // Reserve these utility tables, so that if they sampled, they'll be\n  // preexisting.\n  absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);\n  absl::flat_hash_map<size_t, int> observed_checksums(10);\n  absl::flat_hash_map<ssize_t, int> reservations(10);\n\n  start_size += sampler.Iterate([&](const HashtablezInfo& info) {\n    preexisting_info.insert(&info);\n    ++start_size;\n  });\n\n  std::vector<TypeParam> tables;\n  for (int i = 0; i < 1000000; ++i) {\n    tables.emplace_back();\n\n    const bool do_reserve = (i % 10 > 5);\n    const bool do_rehash = !do_reserve && (i % 10 > 0);\n\n    if (do_reserve) {\n      // Don't reserve on all tables.\n      tables.back().reserve(10 * (i % 10));\n    }\n\n    tables.back().insert(1);\n    tables.back().insert(i % 5);\n\n    if (do_rehash) {\n      // Rehash some other tables.\n      tables.back().rehash(10 * (i % 10));\n    }\n  }\n  size_t end_size = 0;\n  end_size += sampler.Iterate([&](const HashtablezInfo& info) {\n    ++end_size;\n    if (preexisting_info.contains(&info)) return;\n    reservations[info.max_reserve.load(std::memory_order_relaxed)]++;\n    EXPECT_EQ(info.inline_element_size, sizeof(typename TypeParam::value_type));\n    EXPECT_EQ(info.key_size, sizeof(typename TypeParam::key_type));\n    EXPECT_EQ(info.value_size, sizeof(typename TypeParam::value_type));\n\n    if (soo_enabled) {\n      EXPECT_EQ(info.soo_capacity, SooCapacity());\n    } else {\n      EXPECT_EQ(info.soo_capacity, 0);\n    }\n  });\n\n  // Expect that we sampled at the requested sampling rate of ~1%.\n  EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),\n              0.01, 0.005);\n\n  ASSERT_EQ(reservations.size(), 10);\n  for (const auto& [reservation, count] : reservations) {\n    EXPECT_GE(reservation, 0);\n    EXPECT_LT(reservation, 100);\n\n    EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.1, 0.05)\n        << reservation;\n  }\n}\n\ntemplate <typename IntTableType>\nstd::vector<const HashtablezInfo*> SampleTableMutation(\n    absl::FunctionRef<void(IntTableType&)> mutate_table) {\n  // Enable the feature even if the prod default is off.\n  SetSamplingRateTo1Percent();\n\n  auto& sampler = GlobalHashtablezSampler();\n  int64_t start_size = 0;\n  // Reserve the table, so that if it sampled, it'll be preexisting.\n  absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);\n  start_size += sampler.Iterate([&](const HashtablezInfo& info) {\n    preexisting_info.insert(&info);\n    ++start_size;\n  });\n\n  std::vector<IntTableType> tables;\n  for (int i = 0; i < 1000000; ++i) {\n    tables.emplace_back();\n    mutate_table(tables.back());\n  }\n  int64_t end_size = 0;\n  std::vector<const HashtablezInfo*> infos;\n  end_size += sampler.Iterate([&](const HashtablezInfo& info) {\n    ++end_size;\n    if (preexisting_info.contains(&info)) return;\n    infos.push_back(&info);\n  });\n\n  // Expect that we sampled at the requested sampling rate of ~1%.\n  EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),\n              0.01, 0.005);\n  return infos;\n}\n\nstd::vector<const HashtablezInfo*> SampleSooMutation(\n    absl::FunctionRef<void(SooInt32Table&)> mutate_table) {\n  return SampleTableMutation<SooInt32Table>(mutate_table);\n}\n\nstd::vector<const HashtablezInfo*> SampleNonSooMutation(\n    absl::FunctionRef<void(NonSooIntTable&)> mutate_table) {\n  return SampleTableMutation<NonSooIntTable>(mutate_table);\n}\n\nTEST(RawHashSamplerTest, SooTableInsertToEmpty) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) { t.insert(1); });\n\n  for (const HashtablezInfo* info : infos) {\n    ASSERT_EQ(info->inline_element_size,\n              sizeof(typename SooInt32Table::value_type));\n    ASSERT_EQ(info->soo_capacity, SooCapacity());\n    ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));\n    ASSERT_EQ(info->size, 1);\n    ASSERT_EQ(info->max_reserve, 0);\n    ASSERT_EQ(info->num_erases, 0);\n    ASSERT_EQ(info->max_probe_length, 0);\n    ASSERT_EQ(info->total_probe_length, 0);\n  }\n}\n\n// Verifies that repeated insertions and erasures on an SOO table do not cause\n// the sampling decision to be evaluated multiple times, preventing\n// oversampling.\nTEST(RawHashSamplerTest, SooTableRepeatedInsertEraseDoesNotOversample) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) {\n        for (int i = 0; i < 10; ++i) {\n          t.insert(1);\n          t.erase(1);\n        }\n      });\n\n  // SampleSooMutation checks EXPECT_NEAR(sampled/total, 1%, 0.5%).\n  // If the sampling logic is incorrectly evaluated on every 0->1 element\n  // transition, the chance of being sampled per table approaches 10% (1 -\n  // 0.99^10), which is enough to cause this test to fail. By passing, this test\n  // verifies that the sampling decision is evaluated exactly once per SOO table\n  // instance.\n}\n\nTEST(RawHashSamplerTest, NonSooTableRepeatedInsertEraseCountSizeRight) {\n  ASSERT_EQ(NonSooIntTable().capacity(), 0);\n  std::vector<const HashtablezInfo*> infos =\n      SampleNonSooMutation([](NonSooIntTable& t) {\n        for (int i = 0; i < 10; ++i) {\n          t.insert(1);\n          t.erase(1);\n        }\n      });\n  for (const HashtablezInfo* info : infos) {\n    EXPECT_EQ(info->soo_capacity, 0);\n    ASSERT_EQ(info->capacity, 1);\n    ASSERT_EQ(info->size, 0);\n  }\n}\n\n// Verifies that copy-constructing or copy-assigning an SOO table does not\n// incorrectly trigger new sampling evaluations.\nTEST(RawHashSamplerTest, SooTableCopyDoesNotOversample) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) {\n        t.insert(1);\n        t.erase(1);\n        SooInt32Table t_copy(t);\n        for (int i = 0; i < 10; ++i) {\n          t_copy.insert(1);\n          t_copy.erase(1);\n        }\n        t = std::move(t_copy);\n      });\n}\n\n// Verifies that move-constructing or move-assigning an SOO table correctly\n// transfers the sampling state and does not trigger oversampling.\nTEST(RawHashSamplerTest, SooTableMoveDoesNotOversample) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) {\n        t.insert(1);\n        t.erase(1);\n        SooInt32Table t_moved(std::move(t));\n        for (int i = 0; i < 10; ++i) {\n          t_moved.insert(1);\n          t_moved.erase(1);\n        }\n        t = std::move(t_moved);\n      });\n}\n\nTEST(RawHashSamplerTest, SooTableReserveToEmpty) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) { t.reserve(100); });\n\n  for (const HashtablezInfo* info : infos) {\n    ASSERT_EQ(info->inline_element_size,\n              sizeof(typename SooInt32Table::value_type));\n    ASSERT_EQ(info->soo_capacity, SooCapacity());\n    ASSERT_GE(info->capacity, 100);\n    ASSERT_EQ(info->size, 0);\n    ASSERT_EQ(info->max_reserve, 100);\n    ASSERT_EQ(info->num_erases, 0);\n    ASSERT_EQ(info->max_probe_length, 0);\n    ASSERT_EQ(info->total_probe_length, 0);\n  }\n}\n\n// This tests that reserve on a full SOO table doesn't incorrectly result in new\n// (over-)sampling.\nTEST(RawHashSamplerTest, SooTableReserveToFullSoo) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) {\n        t.insert(1);\n        t.reserve(100);\n      });\n\n  for (const HashtablezInfo* info : infos) {\n    ASSERT_EQ(info->inline_element_size,\n              sizeof(typename SooInt32Table::value_type));\n    ASSERT_EQ(info->soo_capacity, SooCapacity());\n    ASSERT_GE(info->capacity, 100);\n    ASSERT_EQ(info->size, 1);\n    ASSERT_EQ(info->max_reserve, 100);\n    ASSERT_EQ(info->num_erases, 0);\n    ASSERT_EQ(info->max_probe_length, 0);\n    ASSERT_EQ(info->total_probe_length, 0);\n  }\n}\n\nTEST(RawHashSamplerTest, SooTableSampleOnCopy) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n\n  SooInt32Table t_orig;\n  t_orig.insert(1);\n\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([&t_orig](SooInt32Table& t) {\n        t = t_orig;\n      });\n\n  for (const HashtablezInfo* info : infos) {\n    ASSERT_EQ(info->inline_element_size,\n              sizeof(typename SooInt32Table::value_type));\n    ASSERT_EQ(info->soo_capacity, SooCapacity());\n    ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));\n    ASSERT_EQ(info->size, 1);\n  }\n}\n\n// This tests that rehash(0) on a sampled table with size that fits in SOO\n// doesn't incorrectly result in losing sampling.\nTEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n  std::vector<const HashtablezInfo*> infos =\n      SampleSooMutation([](SooInt32Table& t) {\n        t.reserve(100);\n        t.insert(1);\n        EXPECT_GE(t.capacity(), 100);\n        t.rehash(0);\n      });\n\n  for (const HashtablezInfo* info : infos) {\n    ASSERT_EQ(info->inline_element_size,\n              sizeof(typename SooInt32Table::value_type));\n    ASSERT_EQ(info->soo_capacity, SooCapacity());\n    ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));\n    ASSERT_EQ(info->size, 1);\n    ASSERT_EQ(info->max_reserve, 100);\n    ASSERT_EQ(info->num_erases, 0);\n    ASSERT_EQ(info->max_probe_length, 0);\n    ASSERT_EQ(info->total_probe_length, 0);\n  }\n}\n\n// Verifies that a moved-from table does not retain the sampled state of the\n// original table, allowing it to be used without incorrectly updating global\n// sampling stats.\nTEST(RawHashSamplerTest, MovedFromTableIsNotSampled) {\n  if (SooInt32Table().capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n\n  SetSamplingRateTo1Percent();\n  auto& sampler = GlobalHashtablezSampler();\n  size_t start_size = 0;\n  absl::flat_hash_set<const HashtablezInfo*> preexisting_info;\n  sampler.Iterate([&](const HashtablezInfo& info) {\n    preexisting_info.insert(&info);\n    ++start_size;\n  });\n\n  SooInt32Table t1;\n  // Loop until t1 is sampled\n  while (true) {\n    t1 = SooInt32Table();\n    t1.insert(1);\n    size_t new_size = 0;\n    sampler.Iterate([&](const HashtablezInfo&) { ++new_size; });\n    if (new_size > start_size) break;\n  }\n\n  // Move the table\n  SooInt32Table t2 = std::move(t1);\n\n  // Disable sampling to ensure any new sampling is a bug.\n  SetHashtablezEnabled(false);\n\n  // t2 is now the sampled table. t1 is moved-from.\n  // We want to verify that t2 is still sampled, and that t1 isn't sampled\n  // anymore, even if we insert a new entry into it.\n  t1.clear();  // Must clear before using a moved-from table.\n  t1.insert(2);\n  t2.insert(2);\n\n  // Verify no new sample was generated, and t2's sample size is now 2.\n  size_t final_size = 0;\n  const HashtablezInfo* latest_info = nullptr;\n  size_t dropped = sampler.Iterate([&](const HashtablezInfo& info) {\n    ++final_size;\n    if (!preexisting_info.contains(&info)) {\n      latest_info = &info;\n    }\n  });\n  EXPECT_EQ(0, dropped);\n  EXPECT_EQ(final_size, start_size + 1);\n  ASSERT_NE(latest_info, nullptr);\n  EXPECT_EQ(latest_info->size.load(std::memory_order_relaxed), 2);\n}\n\n#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE\n\nTEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {\n  // Enable the feature even if the prod default is off.\n  SetSamplingRateTo1Percent();\n\n  auto& sampler = GlobalHashtablezSampler();\n  int64_t start_size = 0;\n  start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });\n\n  std::vector<CustomAllocIntTable> tables;\n  for (int i = 0; i < 100000; ++i) {\n    tables.emplace_back();\n    tables.back().insert(1);\n    tables.push_back(tables.back());  // Copies the table.\n  }\n  int64_t end_size = 0;\n  end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });\n\n  EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),\n              0.00, 0.001);\n}\n\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\ntemplate <class TableType>\nclass SanitizerTest : public testing::Test {};\n\nusing SanitizerTableTypes = ::testing::Types<IntTable, TransferableIntTable>;\nTYPED_TEST_SUITE(SanitizerTest, SanitizerTableTypes);\n\nTYPED_TEST(SanitizerTest, PoisoningUnused) {\n  TypeParam t;\n  for (size_t reserve_size = 2; reserve_size < 1024;\n       reserve_size = reserve_size * 3 / 2) {\n    t.reserve(reserve_size);\n    // Insert something to force an allocation.\n    int64_t& v = *t.insert(0).first;\n\n    // Make sure there is something to test.\n    ASSERT_GT(t.capacity(), 1);\n\n    int64_t* slots = RawHashSetTestOnlyAccess::GetSlots(t);\n    for (size_t i = 0; i < t.capacity(); ++i) {\n      EXPECT_EQ(slots + i != &v, __asan_address_is_poisoned(slots + i)) << i;\n    }\n  }\n}\n\nTYPED_TEST(SanitizerTest, PoisoningUnusedOnGrowth) {\n  TypeParam t;\n  for (int64_t i = 0; i < 100; ++i) {\n    t.insert(i);\n\n    int64_t* slots = RawHashSetTestOnlyAccess::GetSlots(t);\n    int poisoned = 0;\n    for (size_t i = 0; i < t.capacity(); ++i) {\n      poisoned += static_cast<int>(__asan_address_is_poisoned(slots + i));\n    }\n    ASSERT_EQ(poisoned, t.capacity() - t.size());\n  }\n}\n\n// TODO(b/289225379): poison inline space when empty SOO.\nTEST(Sanitizer, PoisoningOnErase) {\n  NonSooIntTable t;\n  auto& v = *t.insert(0).first;\n\n  EXPECT_FALSE(__asan_address_is_poisoned(&v));\n  t.erase(0);\n  EXPECT_TRUE(__asan_address_is_poisoned(&v));\n}\n#endif  // ABSL_HAVE_ADDRESS_SANITIZER\n\ntemplate <typename T>\nclass AlignOneTest : public ::testing::Test {};\nusing AlignOneTestTypes =\n    ::testing::Types<Uint8Table, MinimumAlignmentUint8Table>;\nTYPED_TEST_SUITE(AlignOneTest, AlignOneTestTypes);\n\nTYPED_TEST(AlignOneTest, AlignOne) {\n  // We previously had a bug in which we were copying a control byte over the\n  // first slot when alignof(value_type) is 1. We test repeated\n  // insertions/erases and verify that the behavior is correct.\n  TypeParam t;\n  std::bitset<256> verifier;\n\n  // Do repeated insertions/erases from the table.\n  for (int64_t i = 0; i < 10000; ++i) {\n    SCOPED_TRACE(i);\n    const uint8_t u = (i * -i) & 0xFF;\n    auto it = t.find(u);\n    if (it == t.end()) {\n      ASSERT_FALSE(verifier.test(u));\n      t.insert(u);\n      verifier.set(u);\n    } else {\n      ASSERT_TRUE(verifier.test(u));\n      t.erase(it);\n      verifier.reset(u);\n    }\n  }\n\n  EXPECT_EQ(t.size(), verifier.count());\n  for (uint8_t u : t) {\n    ASSERT_TRUE(verifier.test(u));\n  }\n}\n\nTEST(Iterator, InvalidUseCrashesWithSanitizers) {\n  if (!SwisstableGenerationsEnabled()) GTEST_SKIP() << \"Generations disabled.\";\n\n  NonSooIntTable t;\n  // Start with 1 element so that `it` is never an end iterator.\n  t.insert(-1);\n  for (int i = 0; i < 10; ++i) {\n    auto it = t.begin();\n    t.insert(i);\n    EXPECT_DEATH_IF_SUPPORTED(*it, InvalidIteratorMatcher());\n    EXPECT_DEATH_IF_SUPPORTED(void(it == t.begin()), InvalidIteratorMatcher());\n  }\n}\n\nTEST(Iterator, InvalidUseWithReserveCrashesWithSanitizers) {\n  if (!SwisstableGenerationsEnabled()) GTEST_SKIP() << \"Generations disabled.\";\n\n  IntTable t;\n  t.reserve(10);\n  t.insert(0);\n  auto it = t.begin();\n  // Reserved growth can't rehash.\n  for (int i = 1; i < 10; ++i) {\n    t.insert(i);\n    EXPECT_EQ(*it, 0);\n  }\n  // ptr will become invalidated on rehash.\n  const int64_t* ptr = &*it;\n  (void)ptr;\n\n  // erase decreases size but does not decrease reserved growth so the next\n  // insertion still invalidates iterators.\n  t.erase(0);\n  // The first insert after reserved growth is 0 is guaranteed to rehash when\n  // generations are enabled.\n  t.insert(10);\n  EXPECT_DEATH_IF_SUPPORTED(*it, InvalidIteratorMatcher());\n  EXPECT_DEATH_IF_SUPPORTED(void(it == t.begin()), InvalidIteratorMatcher());\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  EXPECT_DEATH_IF_SUPPORTED(std::cout << *ptr, \"heap-use-after-free\");\n#endif\n}\n\nTEST(Iterator, InvalidUseWithMoveCrashesWithSanitizers) {\n  if (!SwisstableGenerationsEnabled()) GTEST_SKIP() << \"Generations disabled.\";\n\n  NonSooIntTable t1, t2;\n  t1.insert(1);\n  auto it = t1.begin();\n  // ptr will become invalidated on rehash.\n  const auto* ptr = &*it;\n  (void)ptr;\n\n  t2 = std::move(t1);\n  EXPECT_DEATH_IF_SUPPORTED(*it, InvalidIteratorMatcher());\n  EXPECT_DEATH_IF_SUPPORTED(void(it == t2.begin()), InvalidIteratorMatcher());\n#ifdef ABSL_HAVE_ADDRESS_SANITIZER\n  EXPECT_DEATH_IF_SUPPORTED(std::cout << **ptr, \"heap-use-after-free\");\n#endif\n}\n\nTYPED_TEST(SooTest, ReservedGrowthUpdatesWhenTableDoesntGrow) {\n  TypeParam t;\n  for (int i = 0; i < 8; ++i) t.insert(i);\n  // Want to insert twice without invalidating iterators so reserve.\n  const size_t cap = t.capacity();\n  t.reserve(t.size() + 2);\n  // We want to be testing the case in which the reserve doesn't grow the table.\n  ASSERT_EQ(cap, t.capacity());\n  auto it = t.find(0);\n  t.insert(100);\n  t.insert(200);\n  // `it` shouldn't have been invalidated.\n  EXPECT_EQ(*it, 0);\n}\n\ntemplate <class TableType>\nclass InstanceTrackerTest : public testing::Test {};\n\nusing ::absl::test_internal::CopyableMovableInstance;\nusing ::absl::test_internal::InstanceTracker;\n\nstruct InstanceTrackerHash {\n  size_t operator()(const CopyableMovableInstance& t) const {\n    return absl::HashOf(t.value());\n  }\n};\n\nusing InstanceTrackerTableTypes = ::testing::Types<\n    absl::node_hash_set<CopyableMovableInstance, InstanceTrackerHash>,\n    absl::flat_hash_set<CopyableMovableInstance, InstanceTrackerHash>>;\nTYPED_TEST_SUITE(InstanceTrackerTest, InstanceTrackerTableTypes);\n\nTYPED_TEST(InstanceTrackerTest, EraseIfAll) {\n  using Table = TypeParam;\n  InstanceTracker tracker;\n  for (int size = 0; size < 100; ++size) {\n    Table t;\n    for (int i = 0; i < size; ++i) {\n      t.emplace(i);\n    }\n    absl::erase_if(t, [](const auto&) { return true; });\n    ASSERT_EQ(t.size(), 0);\n  }\n  EXPECT_EQ(tracker.live_instances(), 0);\n}\n\nTYPED_TEST(InstanceTrackerTest, EraseIfNone) {\n  using Table = TypeParam;\n  InstanceTracker tracker;\n  {\n    Table t;\n    for (size_t size = 0; size < 100; ++size) {\n      absl::erase_if(t, [](const auto&) { return false; });\n      ASSERT_EQ(t.size(), size);\n      t.emplace(size);\n    }\n  }\n  EXPECT_EQ(tracker.live_instances(), 0);\n}\n\nTYPED_TEST(InstanceTrackerTest, EraseIfPartial) {\n  using Table = TypeParam;\n  InstanceTracker tracker;\n  for (int mod : {0, 1}) {\n    for (int size = 0; size < 100; ++size) {\n      SCOPED_TRACE(absl::StrCat(mod, \" \", size));\n      Table t;\n      std::vector<CopyableMovableInstance> expected;\n      for (int i = 0; i < size; ++i) {\n        t.emplace(i);\n        if (i % 2 != mod) {\n          expected.emplace_back(i);\n        }\n      }\n      absl::erase_if(t, [mod](const auto& x) { return x.value() % 2 == mod; });\n      ASSERT_THAT(t, testing::UnorderedElementsAreArray(expected));\n    }\n  }\n  EXPECT_EQ(tracker.live_instances(), 0);\n}\n\nTYPED_TEST(SooTest, EraseIfAll) {\n  auto pred = [](const auto&) { return true; };\n  for (int size = 0; size < 100; ++size) {\n    TypeParam t;\n    for (int i = 0; i < size; ++i) t.insert(i);\n    absl::container_internal::EraseIf(pred, &t);\n    ASSERT_EQ(t.size(), 0);\n  }\n}\n\nTYPED_TEST(SooTest, EraseIfNone) {\n  auto pred = [](const auto&) { return false; };\n  TypeParam t;\n  for (size_t size = 0; size < 100; ++size) {\n    absl::container_internal::EraseIf(pred, &t);\n    ASSERT_EQ(t.size(), size);\n    t.insert(size);\n  }\n}\n\nTYPED_TEST(SooTest, EraseIfPartial) {\n  for (int mod : {0, 1}) {\n    auto pred = [&](const auto& x) {\n      return static_cast<int64_t>(x) % 2 == mod;\n    };\n    for (int size = 0; size < 100; ++size) {\n      SCOPED_TRACE(absl::StrCat(mod, \" \", size));\n      TypeParam t;\n      std::vector<int64_t> expected;\n      for (int i = 0; i < size; ++i) {\n        t.insert(i);\n        if (i % 2 != mod) {\n          expected.push_back(i);\n        }\n      }\n      absl::container_internal::EraseIf(pred, &t);\n      ASSERT_THAT(t, testing::UnorderedElementsAreArray(expected));\n    }\n  }\n}\n\nTYPED_TEST(SooTest, ForEach) {\n  TypeParam t;\n  std::vector<int64_t> expected;\n  for (int size = 0; size < 100; ++size) {\n    SCOPED_TRACE(size);\n    {\n      SCOPED_TRACE(\"mutable iteration\");\n      std::vector<int64_t> actual;\n      auto f = [&](auto& x) { actual.push_back(static_cast<int64_t>(x)); };\n      absl::container_internal::ForEach(f, &t);\n      ASSERT_THAT(actual, testing::UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const iteration\");\n      std::vector<int64_t> actual;\n      auto f = [&](auto& x) {\n        static_assert(\n            std::is_const<std::remove_reference_t<decltype(x)>>::value,\n            \"no mutable values should be passed to const ForEach\");\n        actual.push_back(static_cast<int64_t>(x));\n      };\n      const auto& ct = t;\n      absl::container_internal::ForEach(f, &ct);\n      ASSERT_THAT(actual, testing::UnorderedElementsAreArray(expected));\n    }\n    t.insert(size);\n    expected.push_back(size);\n  }\n}\n\nTEST(Table, ForEachMutate) {\n  StringTable t;\n  using ValueType = StringTable::value_type;\n  std::vector<ValueType> expected;\n  for (int size = 0; size < 100; ++size) {\n    SCOPED_TRACE(size);\n    std::vector<ValueType> actual;\n    auto f = [&](ValueType& x) {\n      actual.push_back(x);\n      x.second += \"a\";\n    };\n    absl::container_internal::ForEach(f, &t);\n    ASSERT_THAT(actual, testing::UnorderedElementsAreArray(expected));\n    for (ValueType& v : expected) {\n      v.second += \"a\";\n    }\n    ASSERT_THAT(t, testing::UnorderedElementsAreArray(expected));\n    t.emplace(std::to_string(size), std::to_string(size));\n    expected.emplace_back(std::to_string(size), std::to_string(size));\n  }\n}\n\nTYPED_TEST(SooTest, EraseIfReentryDeath) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  auto erase_if_with_removal_reentrance = [](size_t reserve_size) {\n    TypeParam t;\n    t.reserve(reserve_size);\n    int64_t first_value = -1;\n    t.insert(1024);\n    t.insert(5078);\n    auto pred = [&](const auto& x) {\n      if (first_value == -1) {\n        first_value = static_cast<int64_t>(x);\n        return false;\n      }\n      // We erase on second call to `pred` to reduce the chance that assertion\n      // will happen in IterateOverFullSlots.\n      t.erase(first_value);\n      return true;\n    };\n    absl::container_internal::EraseIf(pred, &t);\n  };\n  // Removal will likely happen in a different group.\n  EXPECT_DEATH_IF_SUPPORTED(erase_if_with_removal_reentrance(1024 * 16),\n                            \"hash table was modified unexpectedly\");\n  // Removal will happen in the same group.\n  EXPECT_DEATH_IF_SUPPORTED(\n      erase_if_with_removal_reentrance(CapacityToGrowth(Group::kWidth - 1)),\n      \"hash table was modified unexpectedly\");\n}\n\n// This test is useful to test soo branch.\nTYPED_TEST(SooTest, EraseIfReentrySingleElementDeath) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  auto erase_if_with_removal_reentrance = []() {\n    TypeParam t;\n    t.insert(1024);\n    auto pred = [&](const auto& x) {\n      // We erase ourselves in order to confuse the erase_if.\n      t.erase(static_cast<int64_t>(x));\n      return false;\n    };\n    absl::container_internal::EraseIf(pred, &t);\n  };\n  EXPECT_DEATH_IF_SUPPORTED(erase_if_with_removal_reentrance(),\n                            \"hash table was modified unexpectedly\");\n}\n\nTEST(Table, EraseBeginEndResetsReservedGrowth) {\n  bool frozen = false;\n  BadHashFreezableIntTable t{FreezableAlloc<int64_t>(&frozen)};\n  t.reserve(100);\n  const size_t cap = t.capacity();\n  frozen = true;  // no further allocs allowed\n\n  for (int i = 0; i < 10; ++i) {\n    // Create a long run (hash function returns constant).\n    for (int j = 0; j < 100; ++j) t.insert(j);\n    // Erase elements from the middle of the long run, which creates\n    // tombstones.\n    for (int j = 30; j < 60; ++j) t.erase(j);\n    EXPECT_EQ(t.size(), 70);\n    EXPECT_EQ(t.capacity(), cap);\n    ASSERT_EQ(RawHashSetTestOnlyAccess::CountTombstones(t), 30);\n\n    t.erase(t.begin(), t.end());\n\n    EXPECT_EQ(t.size(), 0);\n    EXPECT_EQ(t.capacity(), cap);\n    ASSERT_EQ(RawHashSetTestOnlyAccess::CountTombstones(t), 0);\n  }\n}\n\nTEST(Table, GenerationInfoResetsOnClear) {\n  if (!SwisstableGenerationsEnabled()) GTEST_SKIP() << \"Generations disabled.\";\n\n  NonSooIntTable t;\n  for (int i = 0; i < 1000; ++i) t.insert(i);\n  t.reserve(t.size() + 100);\n\n  t.clear();\n\n  t.insert(0);\n  auto it = t.begin();\n  t.insert(1);\n  EXPECT_DEATH_IF_SUPPORTED(*it, InvalidIteratorMatcher());\n}\n\nTEST(Table, InvalidReferenceUseCrashesWithSanitizers) {\n  if (!SwisstableGenerationsEnabled()) GTEST_SKIP() << \"Generations disabled.\";\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n  GTEST_SKIP() << \"MSan fails to detect some of these rehashes.\";\n#endif\n\n  NonSooIntTable t;\n  t.insert(0);\n  // Rehashing is guaranteed on every insertion while capacity is less than\n  // RehashProbabilityConstant().\n  int i = 0;\n  while (t.capacity() <= RehashProbabilityConstant()) {\n    // ptr will become invalidated on rehash.\n    const auto* ptr = &*t.begin();\n    t.insert(++i);\n    EXPECT_DEATH_IF_SUPPORTED(std::cout << **ptr, \"use-after-free\") << i;\n  }\n}\n\nTEST(Iterator, InvalidComparisonDifferentTables) {\n  if (!SwisstableGenerationsEnabled()) GTEST_SKIP() << \"Generations disabled.\";\n\n  NonSooIntTable t1, t2;\n  NonSooIntTable::iterator default_constructed_iter;\n  // We randomly use one of N empty generations for generations from empty\n  // hashtables. In general, we won't always detect when iterators from\n  // different empty hashtables are compared, but in this test case, we\n  // should deterministically detect the error due to our randomness yielding\n  // consecutive random generations.\n  EXPECT_DEATH_IF_SUPPORTED(void(t1.end() == t2.end()),\n                            \"Invalid iterator comparison.*empty hashtables\");\n  EXPECT_DEATH_IF_SUPPORTED(void(t1.end() == default_constructed_iter),\n                            \"Invalid iterator comparison.*default-constructed\");\n  t1.insert(0);\n  t1.insert(1);\n  EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == t2.end()),\n                            \"Invalid iterator comparison.*empty hashtable\");\n  EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == default_constructed_iter),\n                            \"Invalid iterator comparison.*default-constructed\");\n  t2.insert(0);\n  t2.insert(1);\n  EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == t2.end()),\n                            \"Invalid iterator comparison.*end.. iterator\");\n  EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == t2.begin()),\n                            \"Invalid iterator comparison.*non-end\");\n}\n\ntemplate <typename Alloc>\nusing RawHashSetAlloc = raw_hash_set<IntPolicy, hash_default_hash<int64_t>,\n                                     std::equal_to<int64_t>, Alloc>;\n\nTEST(Table, AllocatorPropagation) { TestAllocPropagation<RawHashSetAlloc>(); }\n\nstruct CountedHash {\n  size_t operator()(int64_t value) const {\n    ++count;\n    return static_cast<size_t>(value);\n  }\n  mutable int count = 0;\n};\n\nstruct CountedHashIntTable\n    : raw_hash_set<IntPolicy, CountedHash, std::equal_to<int>,\n                   std::allocator<int>> {\n  using Base = typename CountedHashIntTable::raw_hash_set;\n  using Base::Base;\n};\n\nTEST(Table, CountedHash) {\n  // Verify that raw_hash_set does not compute redundant hashes.\n#ifdef NDEBUG\n  constexpr bool kExpectMinimumHashes = true;\n#else\n  constexpr bool kExpectMinimumHashes = false;\n#endif\n  if (!kExpectMinimumHashes) {\n    GTEST_SKIP() << \"Only run under NDEBUG: `assert` statements may cause \"\n                    \"redundant hashing.\";\n  }\n  // When the table is sampled, we need to hash on the first insertion.\n  DisableSampling();\n\n  using Table = CountedHashIntTable;\n  auto HashCount = [](const Table& t) { return t.hash_function().count; };\n  {\n    Table t;\n    t.find(0);\n    EXPECT_EQ(HashCount(t), 0);\n  }\n  {\n    Table t;\n    t.insert(1);\n    t.find(1);\n    EXPECT_EQ(HashCount(t), 0);\n    t.erase(1);\n    EXPECT_EQ(HashCount(t), 0);\n    t.insert(1);\n    t.insert(2);\n    EXPECT_EQ(HashCount(t), 2);\n  }\n  {\n    Table t;\n    t.insert(3);\n    EXPECT_EQ(HashCount(t), 0);\n    auto node = t.extract(3);\n    EXPECT_EQ(HashCount(t), 0);\n    t.insert(std::move(node));\n    EXPECT_EQ(HashCount(t), 0);\n  }\n  {\n    Table t;\n    t.emplace(5);\n    EXPECT_EQ(HashCount(t), 0);\n  }\n  {\n    Table src;\n    src.insert(7);\n    Table dst;\n    dst.merge(src);\n    EXPECT_EQ(HashCount(dst), 0);\n  }\n}\n\n// IterateOverFullSlots doesn't support SOO.\nTEST(Table, IterateOverFullSlotsEmpty) {\n  NonSooIntTable t;\n  using SlotType = NonSooIntTableSlotType;\n  auto fail_if_any = [](const ctrl_t*, void* i) {\n    FAIL() << \"expected no slots \" << **static_cast<SlotType*>(i);\n  };\n  for (size_t i = 2; i < 256; ++i) {\n    t.reserve(i);\n    container_internal::IterateOverFullSlots(\n        RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType), fail_if_any);\n  }\n}\n\nTEST(Table, IterateOverFullSlotsFull) {\n  NonSooIntTable t;\n  using SlotType = NonSooIntTableSlotType;\n\n  std::vector<int64_t> expected_slots;\n  t.insert(0);\n  expected_slots.push_back(0);\n  for (int64_t idx = 1; idx < 128; ++idx) {\n    t.insert(idx);\n    expected_slots.push_back(idx);\n\n    std::vector<int64_t> slots;\n    container_internal::IterateOverFullSlots(\n        RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),\n        [&t, &slots](const ctrl_t* ctrl, void* slot) {\n          SlotType* i = static_cast<SlotType*>(slot);\n          ptrdiff_t ctrl_offset =\n              ctrl - RawHashSetTestOnlyAccess::GetCommon(t).control();\n          ptrdiff_t slot_offset = i - RawHashSetTestOnlyAccess::GetSlots(t);\n          ASSERT_EQ(ctrl_offset, slot_offset);\n          slots.push_back(**i);\n        });\n    EXPECT_THAT(slots, testing::UnorderedElementsAreArray(expected_slots));\n  }\n}\n\nTEST(Table, IterateOverFullSlotsDeathOnRemoval) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  auto iterate_with_reentrant_removal = [](int64_t size,\n                                           int64_t reserve_size = -1) {\n    if (reserve_size == -1) reserve_size = size;\n    for (int64_t idx = 0; idx < size; ++idx) {\n      NonSooIntTable t;\n      using SlotType = NonSooIntTableSlotType;\n      t.reserve(static_cast<size_t>(reserve_size));\n      for (int val = 0; val <= idx; ++val) {\n        t.insert(val);\n      }\n\n      container_internal::IterateOverFullSlots(\n          RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),\n          [&t](const ctrl_t*, void* slot) {\n            int64_t value = **static_cast<SlotType*>(slot);\n            // Erase the other element from 2*k and 2*k+1 pair.\n            t.erase(value ^ 1);\n          });\n    }\n  };\n\n  EXPECT_DEATH_IF_SUPPORTED(iterate_with_reentrant_removal(128),\n                            \"hash table was modified unexpectedly\");\n  // Removal will likely happen in a different group.\n  EXPECT_DEATH_IF_SUPPORTED(iterate_with_reentrant_removal(14, 1024 * 16),\n                            \"hash table was modified unexpectedly\");\n  // Removal will happen in the same group.\n  EXPECT_DEATH_IF_SUPPORTED(iterate_with_reentrant_removal(static_cast<int64_t>(\n                                CapacityToGrowth(Group::kWidth - 1))),\n                            \"hash table was modified unexpectedly\");\n}\n\nTEST(Table, IterateOverFullSlotsDeathOnInsert) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  auto iterate_with_reentrant_insert = [](int64_t reserve_size,\n                                          int64_t size_divisor = 2) {\n    int64_t size = reserve_size / size_divisor;\n    for (int64_t idx = 1; idx <= size; ++idx) {\n      NonSooIntTable t;\n      using SlotType = NonSooIntTableSlotType;\n      t.reserve(static_cast<size_t>(reserve_size));\n      for (int val = 1; val <= idx; ++val) {\n        t.insert(val);\n      }\n\n      container_internal::IterateOverFullSlots(\n          RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),\n          [&t](const ctrl_t*, void* slot) {\n            int64_t value = **static_cast<SlotType*>(slot);\n            t.insert(-value);\n          });\n    }\n  };\n\n  EXPECT_DEATH_IF_SUPPORTED(iterate_with_reentrant_insert(128),\n                            \"hash table was modified unexpectedly\");\n  // Insert will likely happen in a different group.\n  EXPECT_DEATH_IF_SUPPORTED(iterate_with_reentrant_insert(1024 * 16, 1024 * 2),\n                            \"hash table was modified unexpectedly\");\n  // Insert will happen in the same group.\n  EXPECT_DEATH_IF_SUPPORTED(iterate_with_reentrant_insert(static_cast<int64_t>(\n                                CapacityToGrowth(Group::kWidth - 1))),\n                            \"hash table was modified unexpectedly\");\n}\n\ntemplate <typename T>\nclass SooTable : public testing::Test {};\nusing FreezableSooTableTypes =\n    ::testing::Types<FreezableSizedValueSooTable<8>,\n                     FreezableSizedValueSooTable<16>>;\nTYPED_TEST_SUITE(SooTable, FreezableSooTableTypes);\n\nTYPED_TEST(SooTable, Basic) {\n  bool frozen = true;\n  TypeParam t{FreezableAlloc<typename TypeParam::value_type>(&frozen)};\n  if (t.capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n\n  t.insert(0);\n  EXPECT_EQ(t.capacity(), 1);\n  auto it = t.find(0);\n  EXPECT_EQ(it, t.begin());\n  ASSERT_NE(it, t.end());\n  EXPECT_EQ(*it, 0);\n  EXPECT_EQ(++it, t.end());\n  EXPECT_EQ(t.find(1), t.end());\n  EXPECT_EQ(t.size(), 1);\n\n  t.erase(0);\n  EXPECT_EQ(t.size(), 0);\n  t.insert(1);\n  it = t.find(1);\n  EXPECT_EQ(it, t.begin());\n  ASSERT_NE(it, t.end());\n  EXPECT_EQ(*it, 1);\n\n  t.clear();\n  EXPECT_EQ(t.size(), 0);\n}\n\nTEST(Table, RehashToSooUnsampled) {\n  SooIntTable t;\n  if (t.capacity() != SooCapacity()) {\n    CHECK_LT(sizeof(void*), 8) << \"missing SOO coverage\";\n    GTEST_SKIP() << \"not SOO on this platform\";\n  }\n\n  // We disable hashtablez sampling for this test to ensure that the table isn't\n  // sampled. When the table is sampled, it won't rehash down to SOO.\n  DisableSampling();\n\n  t.reserve(100);\n  t.insert(0);\n  EXPECT_EQ(*t.begin(), 0);\n\n  t.rehash(0);  // Rehash back down to SOO table.\n\n  EXPECT_EQ(t.capacity(), SooCapacity());\n  EXPECT_EQ(t.size(), 1);\n  EXPECT_EQ(*t.begin(), 0);\n  EXPECT_EQ(t.find(0), t.begin());\n  EXPECT_EQ(t.find(1), t.end());\n}\n\nTEST(Table, ReserveToNonSoo) {\n  for (size_t reserve_capacity : {2u, 8u, 100000u}) {\n    SooIntTable t;\n    t.insert(0);\n\n    t.reserve(reserve_capacity);\n\n    EXPECT_EQ(t.find(0), t.begin());\n    EXPECT_EQ(t.size(), 1);\n    EXPECT_EQ(*t.begin(), 0);\n    EXPECT_EQ(t.find(1), t.end());\n  }\n}\n\nstruct InconsistentHashEqType {\n  InconsistentHashEqType(int v1, int v2) : v1(v1), v2(v2) {}\n  template <typename H>\n  friend H AbslHashValue(H h, InconsistentHashEqType t) {\n    return H::combine(std::move(h), t.v1);\n  }\n  bool operator==(InconsistentHashEqType t) const { return v2 == t.v2; }\n  int v1, v2;\n};\n\nTEST(Iterator, InconsistentHashEqFunctorsValidation) {\n  if (!IsAssertEnabled()) GTEST_SKIP() << \"Assertions not enabled.\";\n\n  ValueTable<InconsistentHashEqType> t;\n  for (int i = 0; i < 10; ++i) t.insert({i, i});\n  // We need to find/insert multiple times to guarantee that we get the\n  // assertion because it's possible for the hash to collide with the inserted\n  // element that has v2==0. In those cases, the new element won't be inserted.\n  auto find_conflicting_elems = [&] {\n    for (int i = 100; i < 20000; ++i) {\n      EXPECT_EQ(t.find({i, 0}), t.end());\n    }\n  };\n  EXPECT_DEATH_IF_SUPPORTED(find_conflicting_elems(),\n                            \"hash/eq functors are inconsistent.\");\n  auto insert_conflicting_elems = [&] {\n    for (int i = 100; i < 20000; ++i) {\n      EXPECT_EQ(t.insert({i, 0}).second, false);\n    }\n  };\n  EXPECT_DEATH_IF_SUPPORTED(insert_conflicting_elems(),\n                            \"hash/eq functors are inconsistent.\");\n}\n\nstruct ConstructCaller {\n  explicit ConstructCaller(int v) : val(v) {}\n  ConstructCaller(int v, absl::FunctionRef<void()> func) : val(v) { func(); }\n  template <typename H>\n  friend H AbslHashValue(H h, const ConstructCaller& d) {\n    return H::combine(std::move(h), d.val);\n  }\n  bool operator==(const ConstructCaller& c) const { return val == c.val; }\n\n  int val;\n};\n\nstruct DestroyCaller {\n  explicit DestroyCaller(int v) : val(v) {}\n  DestroyCaller(int v, absl::FunctionRef<void()> func)\n      : val(v), destroy_func(func) {}\n  DestroyCaller(DestroyCaller&& that)\n      : val(that.val), destroy_func(std::move(that.destroy_func)) {\n    that.Deactivate();\n  }\n  ~DestroyCaller() {\n    if (destroy_func) (*destroy_func)();\n  }\n  void Deactivate() { destroy_func = std::nullopt; }\n\n  template <typename H>\n  friend H AbslHashValue(H h, const DestroyCaller& d) {\n    return H::combine(std::move(h), d.val);\n  }\n  bool operator==(const DestroyCaller& d) const { return val == d.val; }\n\n  int val;\n  std::optional<absl::FunctionRef<void()>> destroy_func;\n};\n\nTEST(Table, ReentrantCallsFail) {\n#ifdef NDEBUG\n  GTEST_SKIP() << \"Reentrant checks only enabled in debug mode.\";\n#else\n  {\n    ValueTable<ConstructCaller> t;\n    t.insert(ConstructCaller{0});\n    auto erase_begin = [&] { t.erase(t.begin()); };\n    EXPECT_DEATH_IF_SUPPORTED(t.emplace(1, erase_begin), \"\");\n  }\n  {\n    ValueTable<DestroyCaller> t;\n    t.insert(DestroyCaller{0});\n    auto find_0 = [&] { t.find(DestroyCaller{0}); };\n    t.insert(DestroyCaller{1, find_0});\n    for (int i = 10; i < 20; ++i) t.insert(DestroyCaller{i});\n    EXPECT_DEATH_IF_SUPPORTED(t.clear(), \"\");\n    for (auto& elem : t) elem.Deactivate();\n  }\n  {\n    ValueTable<DestroyCaller> t;\n    t.insert(DestroyCaller{0});\n    auto insert_1 = [&] { t.insert(DestroyCaller{1}); };\n    t.insert(DestroyCaller{1, insert_1});\n    for (int i = 10; i < 20; ++i) t.insert(DestroyCaller{i});\n    EXPECT_DEATH_IF_SUPPORTED(t.clear(), \"\");\n    for (auto& elem : t) elem.Deactivate();\n  }\n#endif\n}\n\nTEST(Table, DestroyedCallsFail) {\n#ifdef NDEBUG\n  ASSERT_EQ(SwisstableAssertAccessToDestroyedTable(),\n            SwisstableGenerationsEnabled());\n#else\n  ASSERT_TRUE(SwisstableAssertAccessToDestroyedTable());\n#endif\n  if (!SwisstableAssertAccessToDestroyedTable()) {\n    GTEST_SKIP() << \"Validation not enabled.\";\n  }\n#if !defined(__clang__) && defined(__GNUC__)\n  GTEST_SKIP() << \"Flaky on GCC.\";\n#elif defined(ABSL_HAVE_THREAD_SANITIZER)\n  GTEST_SKIP() << \"Fails on TSan.\";\n  // Note: we use else rather than endif here to avoid unreachable code errors.\n#else\n  std::optional<IntTable> t;\n  t.emplace({1});\n  IntTable* t_ptr = &*t;\n  EXPECT_TRUE(t_ptr->contains(1));\n  t.reset();\n  EXPECT_DEATH_IF_SUPPORTED(\n      t_ptr->contains(1),\n      AnyOf(HasSubstr(\"destroyed hash table\"), HasSubstr(\"use-after-free\"),\n            HasSubstr(\"use-of-uninitialized-value\")));\n\n#endif  // ABSL_HAVE_THREAD_SANITIZER\n}\n\nTEST(Table, DestroyedCallsFailDuringDestruction) {\n  if (!SwisstableAssertAccessToDestroyedTable()) {\n    GTEST_SKIP() << \"Validation not enabled.\";\n  }\n#if !defined(__clang__) && defined(__GNUC__)\n  GTEST_SKIP() << \"Flaky on GCC.\";\n#endif\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(NDEBUG)\n  // TODO(b/487002780): see if we can re-enable this test in opt-ASan mode.\n  GTEST_SKIP() << \"Fails to die in opt ASAN.\";\n#endif\n  // When EXPECT_DEATH_IF_SUPPORTED is not executed, the code after it is not\n  // executed as well.\n  // We need to destruct the table correctly in such a case.\n  // Must be defined before the table for correct destruction order.\n  bool do_lookup = false;\n\n  using Table = absl::flat_hash_map<int, std::shared_ptr<int>>;\n  std::optional<Table> t = Table();\n  Table* t_ptr = &*t;\n  auto destroy = [&](int* ptr) {\n    if (do_lookup) {\n      ASSERT_TRUE(t_ptr->contains(*ptr));\n    }\n    delete ptr;\n  };\n  t->insert({0, std::shared_ptr<int>(new int(0), destroy)});\n  auto destroy_with_lookup = [&] {\n    do_lookup = true;\n    t.reset();\n  };\n  EXPECT_DEATH_IF_SUPPORTED(destroy_with_lookup(),\n                            AnyOf(HasSubstr(\"destroyed hash table\"),\n                                  HasSubstr(\"Reentrant container access\")));\n}\n\nTEST(Table, MovedFromCallsFail) {\n  if (!SwisstableGenerationsEnabled()) {\n    GTEST_SKIP() << \"Moved-from checks only enabled in sanitizer mode.\";\n    return;\n  }\n\n  {\n    ABSL_ATTRIBUTE_UNUSED IntTable t1, t2, t3;\n    t1.insert(1);\n    t2 = std::move(t1);\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), \"moved-from\");\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.swap(t3), \"moved-from\");\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.merge(t3), \"moved-from\");\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(IntTable{t1}, \"moved-from\");\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.begin(), \"moved-from\");\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.end(), \"moved-from\");\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.size(), \"moved-from\");\n  }\n  {\n    ABSL_ATTRIBUTE_UNUSED IntTable t1;\n    t1.insert(1);\n    ABSL_ATTRIBUTE_UNUSED IntTable t2(std::move(t1));\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), \"moved-from\");\n    t1.clear();  // Clearing a moved-from table is allowed.\n  }\n  {\n    // Test that using a table (t3) that was moved-to from a moved-from table\n    // (t1) fails.\n    ABSL_ATTRIBUTE_UNUSED IntTable t1, t2, t3;\n    t1.insert(1);\n    t2 = std::move(t1);\n    // NOLINTNEXTLINE(bugprone-use-after-move)\n    t3 = std::move(t1);\n    EXPECT_DEATH_IF_SUPPORTED(t3.contains(1), \"moved-from\");\n  }\n}\n\nTEST(HashtableSize, GenerateNewSeedDoesntChangeSize) {\n  size_t size = 1;\n  do {\n    HashtableSize hs(no_seed_empty_tag_t{});\n    hs.increment_size(size);\n    EXPECT_EQ(hs.size(), size);\n    hs.generate_new_seed();\n    EXPECT_EQ(hs.size(), size);\n    size = size * 2 + 1;\n  } while (size < std::min(MaxStorableSize(),\n                           MaxSizeAtMaxValidCapacity(/*slot_size=*/1)));\n}\n\nTEST(Table, MaxValidSize) {\n  IntTable t;\n  EXPECT_EQ(\n      MaxValidSize(sizeof(IntTable::key_type), sizeof(IntTable::value_type)),\n      t.max_size());\n  if constexpr (sizeof(size_t) == 8) {\n    for (size_t i = 0; i < 35; ++i) {\n      SCOPED_TRACE(i);\n      size_t slot_size = size_t{1} << i;\n      size_t key_size = slot_size;\n      size_t max_size = MaxValidSize(key_size, slot_size);\n      ASSERT_LT(max_size, uint64_t{1} << 60);\n      if (key_size <= 4) {\n        ASSERT_EQ(max_size, uint64_t{1} << 8 * key_size);\n      } else if (i <= 21) {\n        ASSERT_GE(max_size, uint64_t{1} << 40);\n      }\n      ASSERT_LE(max_size, uint64_t{1} << HashtableSize::kSizeBitCount);\n      ASSERT_LT(absl::uint128(max_size) * slot_size, uint64_t{1} << 63);\n    }\n  }\n  EXPECT_LT(MaxValidSize</*kSizeOfSizeT=*/4>(1, 1), 1 << 30);\n  EXPECT_LT(MaxValidSize</*kSizeOfSizeT=*/4>(2, 2), 1 << 29);\n  for (size_t i = 0; i < 29; ++i) {\n    SCOPED_TRACE(i);\n    size_t slot_size = size_t{1} << i;\n    size_t key_size = slot_size;\n    size_t max_size = MaxValidSize</*kSizeOfSizeT=*/4>(key_size, slot_size);\n    ASSERT_LT(max_size, 1 << 30);\n    size_t max_capacity = SizeToCapacity(max_size);\n    ASSERT_LT(uint64_t{max_capacity} * slot_size, size_t{1} << 31);\n    if (key_size < 4) {\n      ASSERT_EQ(max_size, uint64_t{1} << 8 * key_size);\n    } else {\n      ASSERT_GT(max_capacity, (1 << 29) / slot_size);\n    }\n    ASSERT_LT(max_capacity * slot_size, size_t{1} << 31);\n  }\n}\n\nTEST(Table, MaxSizeOverflow) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  GTEST_SKIP() << \"Skipping test because exceptions are enabled. EXPECT_DEATH \"\n                  \"doesn't work with exceptions.\";\n#elif defined(ABSL_HAVE_THREAD_SANITIZER)\n  GTEST_SKIP() << \"ThreadSanitizer test runs fail on OOM even in EXPECT_DEATH.\";\n#else\n  const std::string expected_death_message =\n      \"new failed|failed to allocate|bad_alloc|exceeds maximum supported size\";\n  size_t overflow = (std::numeric_limits<size_t>::max)();\n  EXPECT_DEATH_IF_SUPPORTED(IntTable t(overflow), expected_death_message);\n  IntTable t;\n  EXPECT_DEATH_IF_SUPPORTED(t.reserve(overflow), expected_death_message);\n  EXPECT_DEATH_IF_SUPPORTED(t.rehash(overflow), expected_death_message);\n  size_t slightly_overflow =\n      MaxValidSize(sizeof(IntTable::key_type), sizeof(IntTable::value_type)) +\n      1;\n  size_t slightly_overflow_capacity =\n      NextCapacity(NormalizeCapacity(slightly_overflow));\n  EXPECT_DEATH_IF_SUPPORTED(IntTable t2(slightly_overflow_capacity - 10),\n                            expected_death_message);\n  EXPECT_DEATH_IF_SUPPORTED(t.reserve(slightly_overflow),\n                            expected_death_message);\n  EXPECT_DEATH_IF_SUPPORTED(t.rehash(slightly_overflow),\n                            expected_death_message);\n  IntTable non_empty_table;\n  non_empty_table.insert(0);\n  EXPECT_DEATH_IF_SUPPORTED(non_empty_table.reserve(slightly_overflow),\n                            expected_death_message);\n#endif  // defined(ABSL_HAVE_THREAD_SANITIZER)\n}\n\n// Tests that reserving enough space for more than the max number of unique keys\n// doesn't crash and we end up with kMaxValidCapacity.\nTEST(Table, MaxSizeOverflowUniqueKeys) {\n  absl::flat_hash_set<uint8_t> t8;\n  t8.reserve(1 << 9);\n  EXPECT_EQ(t8.capacity(), SizeToCapacity(t8.max_size()));\n  absl::flat_hash_set<uint16_t> t16;\n  t16.reserve(1 << 17);\n  EXPECT_EQ(t16.capacity(), SizeToCapacity(t16.max_size()));\n}\n\n// TODO(b/397453582): Remove support for const hasher and remove this test.\nTEST(Table, ConstLambdaHash) {\n  int64_t multiplier = 17;\n  // Make sure that code compiles and work OK with non-empty hasher with const\n  // qualifier.\n  const auto hash = [multiplier](SizedValue<64> value) -> size_t {\n    return static_cast<size_t>(static_cast<int64_t>(value) * multiplier);\n  };\n  static_assert(!std::is_empty_v<decltype(hash)>);\n  absl::flat_hash_set<SizedValue<64>, decltype(hash)> t(0, hash);\n  t.insert(1);\n  EXPECT_EQ(t.size(), 1);\n  EXPECT_EQ(t.find(1), t.begin());\n  EXPECT_EQ(t.find(2), t.end());\n  t.insert(2);\n  EXPECT_EQ(t.size(), 2);\n  EXPECT_NE(t.find(1), t.end());\n  EXPECT_NE(t.find(2), t.end());\n  EXPECT_EQ(t.find(3), t.end());\n}\n\nstruct ZeroHash {\n  template <typename T>\n  size_t operator()(T) const {\n    return 0;\n  }\n};\n\n// This test is imitating growth of a very big table and triggers all buffer\n// overflows.\n// We try to insert all elements into the first probe group.\n// So the resize codepath in test does the following:\n// 1. Insert 16 elements into the first probe group. No other elements will be\n//    inserted into the first probe group.\n// 2. There will be enough elements to fill up the local buffer even for\n//    encoding with 4 bytes.\n// 3. After local buffer is full, we will fill up the control buffer till\n//    some point.\n// 4. Then a few times we will extend control buffer end.\n// 5. Finally we will catch up and go to overflow codepath.\nTEST(Table, GrowExtremelyLargeTable) {\n  // ProbedItem8Bytes causes OOMs on some platforms so we use ProbedItem4Bytes.\n  constexpr size_t kTargetCapacity =\n#if defined(__wasm__) || defined(__asmjs__) || defined(__i386__) || \\\n    defined(_MSC_VER) || defined(ABSL_HAVE_THREAD_SANITIZER) ||     \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) ||                          \\\n    (!defined(__clang__) && defined(__GNUC__))\n      NextCapacity(ProbedItem4Bytes::kMaxNewCapacity);\n#else\n      NextCapacity(ProbedItem8Bytes::kMaxNewCapacity);\n#endif\n\n  absl::flat_hash_set<uint32_t, ZeroHash> t(63);\n  CommonFields& common = RawHashSetTestOnlyAccess::GetCommon(t);\n  // Set 0 seed so that H1 is always 0.\n  common.set_no_seed_for_testing();\n  ASSERT_EQ(H1(t.hash_function()(75)), 0);\n  uint8_t inserted_till = 210;\n  for (uint8_t i = 0; i < inserted_till; ++i) {\n    t.insert(i);\n  }\n  for (uint8_t i = 0; i < inserted_till; ++i) {\n    ASSERT_TRUE(t.contains(i));\n  }\n\n  for (size_t cap = t.capacity(); cap < kTargetCapacity;\n       cap = NextCapacity(cap)) {\n    ASSERT_EQ(t.capacity(), cap);\n    // Update growth info to force resize on the next insert. This way we avoid\n    // having to insert many elements.\n    common.growth_info().OverwriteManyEmptyAsFull(CapacityToGrowth(cap) -\n                                                  t.size());\n    t.insert(inserted_till++);\n    ASSERT_EQ(t.capacity(), NextCapacity(cap));\n    for (uint8_t i = 0; i < inserted_till; ++i) {\n      ASSERT_TRUE(t.contains(i));\n    }\n  }\n  EXPECT_EQ(t.capacity(), kTargetCapacity);\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/test_allocator.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_TEST_ALLOCATOR_H_\n#define ABSL_CONTAINER_INTERNAL_TEST_ALLOCATOR_H_\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// This is a stateful allocator, but the state lives outside of the\n// allocator (in whatever test is using the allocator). This is odd\n// but helps in tests where the allocator is propagated into nested\n// containers - that chain of allocators uses the same state and is\n// thus easier to query for aggregate allocation information.\ntemplate <typename T>\nclass CountingAllocator {\n public:\n  using Allocator = std::allocator<T>;\n  using AllocatorTraits = std::allocator_traits<Allocator>;\n  using value_type = typename AllocatorTraits::value_type;\n  using pointer = typename AllocatorTraits::pointer;\n  using const_pointer = typename AllocatorTraits::const_pointer;\n  using size_type = typename AllocatorTraits::size_type;\n  using difference_type = typename AllocatorTraits::difference_type;\n\n  CountingAllocator() = default;\n  explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {}\n  CountingAllocator(int64_t* bytes_used, int64_t* instance_count)\n      : bytes_used_(bytes_used), instance_count_(instance_count) {}\n\n  template <typename U>\n  CountingAllocator(const CountingAllocator<U>& x)\n      : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {}\n\n  pointer allocate(\n      size_type n,\n      typename AllocatorTraits::const_void_pointer hint = nullptr) {\n    Allocator allocator;\n    pointer ptr = AllocatorTraits::allocate(allocator, n, hint);\n    if (bytes_used_ != nullptr) {\n      *bytes_used_ += n * sizeof(T);\n    }\n    return ptr;\n  }\n\n  void deallocate(pointer p, size_type n) {\n    Allocator allocator;\n    AllocatorTraits::deallocate(allocator, p, n);\n    if (bytes_used_ != nullptr) {\n      *bytes_used_ -= n * sizeof(T);\n    }\n  }\n\n  template <typename U, typename... Args>\n  void construct(U* p, Args&&... args) {\n    Allocator allocator;\n    AllocatorTraits::construct(allocator, p, std::forward<Args>(args)...);\n    if (instance_count_ != nullptr) {\n      *instance_count_ += 1;\n    }\n  }\n\n  template <typename U>\n  void destroy(U* p) {\n    Allocator allocator;\n    // Ignore GCC warning bug.\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wuse-after-free\"\n#endif\n    AllocatorTraits::destroy(allocator, p);\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic pop\n#endif\n    if (instance_count_ != nullptr) {\n      *instance_count_ -= 1;\n    }\n  }\n\n  template <typename U>\n  class rebind {\n   public:\n    using other = CountingAllocator<U>;\n  };\n\n  friend bool operator==(const CountingAllocator& a,\n                         const CountingAllocator& b) {\n    return a.bytes_used_ == b.bytes_used_ &&\n           a.instance_count_ == b.instance_count_;\n  }\n\n  friend bool operator!=(const CountingAllocator& a,\n                         const CountingAllocator& b) {\n    return !(a == b);\n  }\n\n  int64_t* bytes_used_ = nullptr;\n  int64_t* instance_count_ = nullptr;\n};\n\ntemplate <typename T>\nstruct CopyAssignPropagatingCountingAlloc : public CountingAllocator<T> {\n  using propagate_on_container_copy_assignment = std::true_type;\n\n  using Base = CountingAllocator<T>;\n  using Base::Base;\n\n  template <typename U>\n  explicit CopyAssignPropagatingCountingAlloc(\n      const CopyAssignPropagatingCountingAlloc<U>& other)\n      : Base(other.bytes_used_, other.instance_count_) {}\n\n  template <typename U>\n  struct rebind {\n    using other = CopyAssignPropagatingCountingAlloc<U>;\n  };\n};\n\ntemplate <typename T>\nstruct MoveAssignPropagatingCountingAlloc : public CountingAllocator<T> {\n  using propagate_on_container_move_assignment = std::true_type;\n\n  using Base = CountingAllocator<T>;\n  using Base::Base;\n\n  template <typename U>\n  explicit MoveAssignPropagatingCountingAlloc(\n      const MoveAssignPropagatingCountingAlloc<U>& other)\n      : Base(other.bytes_used_, other.instance_count_) {}\n\n  template <typename U>\n  struct rebind {\n    using other = MoveAssignPropagatingCountingAlloc<U>;\n  };\n};\n\ntemplate <typename T>\nstruct SwapPropagatingCountingAlloc : public CountingAllocator<T> {\n  using propagate_on_container_swap = std::true_type;\n\n  using Base = CountingAllocator<T>;\n  using Base::Base;\n\n  template <typename U>\n  explicit SwapPropagatingCountingAlloc(\n      const SwapPropagatingCountingAlloc<U>& other)\n      : Base(other.bytes_used_, other.instance_count_) {}\n\n  template <typename U>\n  struct rebind {\n    using other = SwapPropagatingCountingAlloc<U>;\n  };\n};\n\n// Tries to allocate memory at the minimum alignment even when the default\n// allocator uses a higher alignment.\ntemplate <typename T>\nstruct MinimumAlignmentAlloc : std::allocator<T> {\n  MinimumAlignmentAlloc() = default;\n\n  template <typename U>\n  explicit MinimumAlignmentAlloc(const MinimumAlignmentAlloc<U>& /*other*/) {}\n\n  template <class U>\n  struct rebind {\n    using other = MinimumAlignmentAlloc<U>;\n  };\n\n  T* allocate(size_t n) {\n    T* ptr = std::allocator<T>::allocate(n + 1);\n    char* cptr = reinterpret_cast<char*>(ptr);\n    cptr += alignof(T);\n    return reinterpret_cast<T*>(cptr);\n  }\n\n  void deallocate(T* ptr, size_t n) {\n    char* cptr = reinterpret_cast<char*>(ptr);\n    cptr -= alignof(T);\n    std::allocator<T>::deallocate(reinterpret_cast<T*>(cptr), n + 1);\n  }\n};\n\ninline bool IsAssertEnabled() {\n  // Use an assert with side-effects to figure out if they are actually enabled.\n  bool assert_enabled = false;\n  assert([&]() {  // NOLINT\n    assert_enabled = true;\n    return true;\n  }());\n  return assert_enabled;\n}\n\ntemplate <template <class Alloc> class Container>\nvoid TestCopyAssignAllocPropagation() {\n  int64_t bytes1 = 0, instances1 = 0, bytes2 = 0, instances2 = 0;\n  CopyAssignPropagatingCountingAlloc<int> allocator1(&bytes1, &instances1);\n  CopyAssignPropagatingCountingAlloc<int> allocator2(&bytes2, &instances2);\n\n  // Test propagating allocator_type.\n  {\n    Container<CopyAssignPropagatingCountingAlloc<int>> c1(allocator1);\n    Container<CopyAssignPropagatingCountingAlloc<int>> c2(allocator2);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_NE(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2 = c1;\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 200);\n    EXPECT_EQ(instances2, 0);\n  }\n  // Test non-propagating allocator_type with different allocators.\n  {\n    Container<CountingAllocator<int>> c1(allocator1), c2(allocator2);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_EQ(c2.get_allocator(), allocator2);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2 = c1;\n\n    EXPECT_EQ(c2.get_allocator(), allocator2);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 100);\n  }\n  EXPECT_EQ(bytes1, 0);\n  EXPECT_EQ(instances1, 0);\n  EXPECT_EQ(bytes2, 0);\n  EXPECT_EQ(instances2, 0);\n}\n\ntemplate <template <class Alloc> class Container>\nvoid TestMoveAssignAllocPropagation() {\n  int64_t bytes1 = 0, instances1 = 0, bytes2 = 0, instances2 = 0;\n  MoveAssignPropagatingCountingAlloc<int> allocator1(&bytes1, &instances1);\n  MoveAssignPropagatingCountingAlloc<int> allocator2(&bytes2, &instances2);\n\n  // Test propagating allocator_type.\n  {\n    Container<MoveAssignPropagatingCountingAlloc<int>> c1(allocator1);\n    Container<MoveAssignPropagatingCountingAlloc<int>> c2(allocator2);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_NE(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2 = std::move(c1);\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n  }\n  // Test non-propagating allocator_type with equal allocators.\n  {\n    Container<CountingAllocator<int>> c1(allocator1), c2(allocator1);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2 = std::move(c1);\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n  }\n  // Test non-propagating allocator_type with different allocators.\n  {\n    Container<CountingAllocator<int>> c1(allocator1), c2(allocator2);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_NE(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2 = std::move(c1);\n\n    EXPECT_EQ(c2.get_allocator(), allocator2);\n    EXPECT_LE(instances1, 100);  // The values in c1 may or may not have been\n                                 // destroyed at this point.\n    EXPECT_EQ(instances2, 100);\n  }\n  EXPECT_EQ(bytes1, 0);\n  EXPECT_EQ(instances1, 0);\n  EXPECT_EQ(bytes2, 0);\n  EXPECT_EQ(instances2, 0);\n}\n\ntemplate <template <class Alloc> class Container>\nvoid TestSwapAllocPropagation() {\n  int64_t bytes1 = 0, instances1 = 0, bytes2 = 0, instances2 = 0;\n  SwapPropagatingCountingAlloc<int> allocator1(&bytes1, &instances1);\n  SwapPropagatingCountingAlloc<int> allocator2(&bytes2, &instances2);\n\n  // Test propagating allocator_type.\n  {\n    Container<SwapPropagatingCountingAlloc<int>> c1(allocator1), c2(allocator2);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_NE(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2.swap(c1);\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n  }\n  // Test non-propagating allocator_type with equal allocators.\n  {\n    Container<CountingAllocator<int>> c1(allocator1), c2(allocator1);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n\n    c2.swap(c1);\n\n    EXPECT_EQ(c2.get_allocator(), allocator1);\n    EXPECT_EQ(instances1, 100);\n    EXPECT_EQ(instances2, 0);\n  }\n  // Test non-propagating allocator_type with different allocators.\n  {\n    Container<CountingAllocator<int>> c1(allocator1), c2(allocator2);\n\n    for (int i = 0; i < 100; ++i) c1.insert(i);\n\n    EXPECT_NE(c1.get_allocator(), c2.get_allocator());\n    if (IsAssertEnabled()) {\n      EXPECT_DEATH_IF_SUPPORTED(c2.swap(c1), \"\");\n    }\n  }\n  EXPECT_EQ(bytes1, 0);\n  EXPECT_EQ(instances1, 0);\n  EXPECT_EQ(bytes2, 0);\n  EXPECT_EQ(instances2, 0);\n}\n\ntemplate <template <class Alloc> class Container>\nvoid TestAllocPropagation() {\n  TestCopyAssignAllocPropagation<Container>();\n  TestMoveAssignAllocPropagation<Container>();\n  TestSwapAllocPropagation<Container>();\n}\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_TEST_ALLOCATOR_H_\n"
  },
  {
    "path": "absl/container/internal/test_instance_tracker.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/test_instance_tracker.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace test_internal {\nint BaseCountedInstance::num_instances_ = 0;\nint BaseCountedInstance::num_live_instances_ = 0;\nint BaseCountedInstance::num_moves_ = 0;\nint BaseCountedInstance::num_copies_ = 0;\nint BaseCountedInstance::num_swaps_ = 0;\nint BaseCountedInstance::num_comparisons_ = 0;\n\n}  // namespace test_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/test_instance_tracker.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_\n#define ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_\n\n#include <cstdlib>\n#include <ostream>\n\n#include \"absl/types/compare.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace test_internal {\n\n// A type that counts number of occurrences of the type, the live occurrences of\n// the type, as well as the number of copies, moves, swaps, and comparisons that\n// have occurred on the type. This is used as a base class for the copyable,\n// copyable+movable, and movable types below that are used in actual tests. Use\n// InstanceTracker in tests to track the number of instances.\nclass BaseCountedInstance {\n public:\n  explicit BaseCountedInstance(int x) : value_(x) {\n    ++num_instances_;\n    ++num_live_instances_;\n  }\n  BaseCountedInstance(const BaseCountedInstance& x)\n      : value_(x.value_), is_live_(x.is_live_) {\n    ++num_instances_;\n    if (is_live_) ++num_live_instances_;\n    ++num_copies_;\n  }\n  BaseCountedInstance(BaseCountedInstance&& x)\n      : value_(x.value_), is_live_(x.is_live_) {\n    x.is_live_ = false;\n    ++num_instances_;\n    ++num_moves_;\n  }\n  ~BaseCountedInstance() {\n    --num_instances_;\n    if (is_live_) --num_live_instances_;\n  }\n\n  BaseCountedInstance& operator=(const BaseCountedInstance& x) {\n    value_ = x.value_;\n    if (is_live_) --num_live_instances_;\n    is_live_ = x.is_live_;\n    if (is_live_) ++num_live_instances_;\n    ++num_copies_;\n    return *this;\n  }\n  BaseCountedInstance& operator=(BaseCountedInstance&& x) {\n    value_ = x.value_;\n    if (is_live_) --num_live_instances_;\n    is_live_ = x.is_live_;\n    x.is_live_ = false;\n    ++num_moves_;\n    return *this;\n  }\n\n  bool operator==(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ == x.value_;\n  }\n\n  bool operator!=(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ != x.value_;\n  }\n\n  bool operator<(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ < x.value_;\n  }\n\n  bool operator>(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ > x.value_;\n  }\n\n  bool operator<=(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ <= x.value_;\n  }\n\n  bool operator>=(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ >= x.value_;\n  }\n\n  absl::weak_ordering compare(const BaseCountedInstance& x) const {\n    ++num_comparisons_;\n    return value_ < x.value_\n               ? absl::weak_ordering::less\n               : value_ == x.value_ ? absl::weak_ordering::equivalent\n                                    : absl::weak_ordering::greater;\n  }\n\n  int value() const {\n    if (!is_live_) std::abort();\n    return value_;\n  }\n\n  friend std::ostream& operator<<(std::ostream& o,\n                                  const BaseCountedInstance& v) {\n    return o << \"[value:\" << v.value() << \"]\";\n  }\n\n  // Implementation of efficient swap() that counts swaps.\n  static void SwapImpl(\n      BaseCountedInstance& lhs,    // NOLINT(runtime/references)\n      BaseCountedInstance& rhs) {  // NOLINT(runtime/references)\n    using std::swap;\n    swap(lhs.value_, rhs.value_);\n    swap(lhs.is_live_, rhs.is_live_);\n    ++BaseCountedInstance::num_swaps_;\n  }\n\n private:\n  friend class InstanceTracker;\n\n  int value_;\n\n  // Indicates if the value is live, ie it hasn't been moved away from.\n  bool is_live_ = true;\n\n  // Number of instances.\n  static int num_instances_;\n\n  // Number of live instances (those that have not been moved away from.)\n  static int num_live_instances_;\n\n  // Number of times that BaseCountedInstance objects were moved.\n  static int num_moves_;\n\n  // Number of times that BaseCountedInstance objects were copied.\n  static int num_copies_;\n\n  // Number of times that BaseCountedInstance objects were swapped.\n  static int num_swaps_;\n\n  // Number of times that BaseCountedInstance objects were compared.\n  static int num_comparisons_;\n};\n\n// Helper to track the BaseCountedInstance instance counters. Expects that the\n// number of instances and live_instances are the same when it is constructed\n// and when it is destructed.\nclass InstanceTracker {\n public:\n  InstanceTracker()\n      : start_instances_(BaseCountedInstance::num_instances_),\n        start_live_instances_(BaseCountedInstance::num_live_instances_) {\n    ResetCopiesMovesSwaps();\n  }\n  ~InstanceTracker() {\n    if (instances() != 0) std::abort();\n    if (live_instances() != 0) std::abort();\n  }\n\n  // Returns the number of BaseCountedInstance instances both containing valid\n  // values and those moved away from compared to when the InstanceTracker was\n  // constructed\n  int instances() const {\n    return BaseCountedInstance::num_instances_ - start_instances_;\n  }\n\n  // Returns the number of live BaseCountedInstance instances compared to when\n  // the InstanceTracker was constructed\n  int live_instances() const {\n    return BaseCountedInstance::num_live_instances_ - start_live_instances_;\n  }\n\n  // Returns the number of moves on BaseCountedInstance objects since\n  // construction or since the last call to ResetCopiesMovesSwaps().\n  int moves() const { return BaseCountedInstance::num_moves_ - start_moves_; }\n\n  // Returns the number of copies on BaseCountedInstance objects since\n  // construction or the last call to ResetCopiesMovesSwaps().\n  int copies() const {\n    return BaseCountedInstance::num_copies_ - start_copies_;\n  }\n\n  // Returns the number of swaps on BaseCountedInstance objects since\n  // construction or the last call to ResetCopiesMovesSwaps().\n  int swaps() const { return BaseCountedInstance::num_swaps_ - start_swaps_; }\n\n  // Returns the number of comparisons on BaseCountedInstance objects since\n  // construction or the last call to ResetCopiesMovesSwaps().\n  int comparisons() const {\n    return BaseCountedInstance::num_comparisons_ - start_comparisons_;\n  }\n\n  // Resets the base values for moves, copies, comparisons, and swaps to the\n  // current values, so that subsequent Get*() calls for moves, copies,\n  // comparisons, and swaps will compare to the situation at the point of this\n  // call.\n  void ResetCopiesMovesSwaps() {\n    start_moves_ = BaseCountedInstance::num_moves_;\n    start_copies_ = BaseCountedInstance::num_copies_;\n    start_swaps_ = BaseCountedInstance::num_swaps_;\n    start_comparisons_ = BaseCountedInstance::num_comparisons_;\n  }\n\n private:\n  int start_instances_;\n  int start_live_instances_;\n  int start_moves_;\n  int start_copies_;\n  int start_swaps_;\n  int start_comparisons_;\n};\n\n// Copyable, not movable.\nclass CopyableOnlyInstance : public BaseCountedInstance {\n public:\n  explicit CopyableOnlyInstance(int x) : BaseCountedInstance(x) {}\n  CopyableOnlyInstance(const CopyableOnlyInstance& rhs) = default;\n  CopyableOnlyInstance& operator=(const CopyableOnlyInstance& rhs) = default;\n\n  friend void swap(CopyableOnlyInstance& lhs, CopyableOnlyInstance& rhs) {\n    BaseCountedInstance::SwapImpl(lhs, rhs);\n  }\n\n  static bool supports_move() { return false; }\n};\n\n// Copyable and movable.\nclass CopyableMovableInstance : public BaseCountedInstance {\n public:\n  explicit CopyableMovableInstance(int x) : BaseCountedInstance(x) {}\n  CopyableMovableInstance(const CopyableMovableInstance& rhs) = default;\n  CopyableMovableInstance(CopyableMovableInstance&& rhs) = default;\n  CopyableMovableInstance& operator=(const CopyableMovableInstance& rhs) =\n      default;\n  CopyableMovableInstance& operator=(CopyableMovableInstance&& rhs) = default;\n\n  friend void swap(CopyableMovableInstance& lhs, CopyableMovableInstance& rhs) {\n    BaseCountedInstance::SwapImpl(lhs, rhs);\n  }\n\n  static bool supports_move() { return true; }\n};\n\n// Only movable, not default-constructible.\nclass MovableOnlyInstance : public BaseCountedInstance {\n public:\n  explicit MovableOnlyInstance(int x) : BaseCountedInstance(x) {}\n  MovableOnlyInstance(MovableOnlyInstance&& other) = default;\n  MovableOnlyInstance& operator=(MovableOnlyInstance&& other) = default;\n\n  friend void swap(MovableOnlyInstance& lhs, MovableOnlyInstance& rhs) {\n    BaseCountedInstance::SwapImpl(lhs, rhs);\n  }\n\n  static bool supports_move() { return true; }\n};\n\n}  // namespace test_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_\n"
  },
  {
    "path": "absl/container/internal/test_instance_tracker_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/internal/test_instance_tracker.h\"\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing absl::test_internal::CopyableMovableInstance;\nusing absl::test_internal::CopyableOnlyInstance;\nusing absl::test_internal::InstanceTracker;\nusing absl::test_internal::MovableOnlyInstance;\n\nTEST(TestInstanceTracker, CopyableMovable) {\n  InstanceTracker tracker;\n  CopyableMovableInstance src(1);\n  EXPECT_EQ(1, src.value()) << src;\n  CopyableMovableInstance copy(src);\n  CopyableMovableInstance move(std::move(src));\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(1, tracker.moves());\n  EXPECT_EQ(0, tracker.swaps());\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(2, tracker.live_instances());\n  tracker.ResetCopiesMovesSwaps();\n\n  CopyableMovableInstance copy_assign(1);\n  copy_assign = copy;\n  CopyableMovableInstance move_assign(1);\n  move_assign = std::move(move);\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(1, tracker.moves());\n  EXPECT_EQ(0, tracker.swaps());\n  EXPECT_EQ(5, tracker.instances());\n  EXPECT_EQ(3, tracker.live_instances());\n  tracker.ResetCopiesMovesSwaps();\n\n  {\n    using std::swap;\n    swap(move_assign, copy);\n    swap(copy, move_assign);\n    EXPECT_EQ(2, tracker.swaps());\n    EXPECT_EQ(0, tracker.copies());\n    EXPECT_EQ(0, tracker.moves());\n    EXPECT_EQ(5, tracker.instances());\n    EXPECT_EQ(3, tracker.live_instances());\n  }\n}\n\nTEST(TestInstanceTracker, CopyableOnly) {\n  InstanceTracker tracker;\n  CopyableOnlyInstance src(1);\n  EXPECT_EQ(1, src.value()) << src;\n  CopyableOnlyInstance copy(src);\n  CopyableOnlyInstance copy2(std::move(src));  // NOLINT\n  EXPECT_EQ(2, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(3, tracker.live_instances());\n  tracker.ResetCopiesMovesSwaps();\n\n  CopyableOnlyInstance copy_assign(1);\n  copy_assign = copy;\n  CopyableOnlyInstance copy_assign2(1);\n  copy_assign2 = std::move(copy2);  // NOLINT\n  EXPECT_EQ(2, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_EQ(5, tracker.instances());\n  EXPECT_EQ(5, tracker.live_instances());\n  tracker.ResetCopiesMovesSwaps();\n\n  {\n    using std::swap;\n    swap(src, copy);\n    swap(copy, src);\n    EXPECT_EQ(2, tracker.swaps());\n    EXPECT_EQ(0, tracker.copies());\n    EXPECT_EQ(0, tracker.moves());\n    EXPECT_EQ(5, tracker.instances());\n    EXPECT_EQ(5, tracker.live_instances());\n  }\n}\n\nTEST(TestInstanceTracker, MovableOnly) {\n  InstanceTracker tracker;\n  MovableOnlyInstance src(1);\n  EXPECT_EQ(1, src.value()) << src;\n  MovableOnlyInstance move(std::move(src));\n  MovableOnlyInstance move_assign(2);\n  move_assign = std::move(move);\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(1, tracker.live_instances());\n  EXPECT_EQ(2, tracker.moves());\n  EXPECT_EQ(0, tracker.copies());\n  tracker.ResetCopiesMovesSwaps();\n\n  {\n    using std::swap;\n    MovableOnlyInstance other(2);\n    swap(move_assign, other);\n    swap(other, move_assign);\n    EXPECT_EQ(2, tracker.swaps());\n    EXPECT_EQ(0, tracker.copies());\n    EXPECT_EQ(0, tracker.moves());\n    EXPECT_EQ(4, tracker.instances());\n    EXPECT_EQ(2, tracker.live_instances());\n  }\n}\n\nTEST(TestInstanceTracker, ExistingInstances) {\n  CopyableMovableInstance uncounted_instance(1);\n  CopyableMovableInstance uncounted_live_instance(\n      std::move(uncounted_instance));\n  InstanceTracker tracker;\n  EXPECT_EQ(0, tracker.instances());\n  EXPECT_EQ(0, tracker.live_instances());\n  EXPECT_EQ(0, tracker.copies());\n  {\n    CopyableMovableInstance instance1(1);\n    EXPECT_EQ(1, tracker.instances());\n    EXPECT_EQ(1, tracker.live_instances());\n    EXPECT_EQ(0, tracker.copies());\n    EXPECT_EQ(0, tracker.moves());\n    {\n      InstanceTracker tracker2;\n      CopyableMovableInstance instance2(instance1);\n      CopyableMovableInstance instance3(std::move(instance2));\n      EXPECT_EQ(3, tracker.instances());\n      EXPECT_EQ(2, tracker.live_instances());\n      EXPECT_EQ(1, tracker.copies());\n      EXPECT_EQ(1, tracker.moves());\n      EXPECT_EQ(2, tracker2.instances());\n      EXPECT_EQ(1, tracker2.live_instances());\n      EXPECT_EQ(1, tracker2.copies());\n      EXPECT_EQ(1, tracker2.moves());\n    }\n    EXPECT_EQ(1, tracker.instances());\n    EXPECT_EQ(1, tracker.live_instances());\n    EXPECT_EQ(1, tracker.copies());\n    EXPECT_EQ(1, tracker.moves());\n  }\n  EXPECT_EQ(0, tracker.instances());\n  EXPECT_EQ(0, tracker.live_instances());\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(1, tracker.moves());\n}\n\nTEST(TestInstanceTracker, Comparisons) {\n  InstanceTracker tracker;\n  MovableOnlyInstance one(1), two(2);\n\n  EXPECT_EQ(0, tracker.comparisons());\n  EXPECT_FALSE(one == two);\n  EXPECT_EQ(1, tracker.comparisons());\n  EXPECT_TRUE(one != two);\n  EXPECT_EQ(2, tracker.comparisons());\n  EXPECT_TRUE(one < two);\n  EXPECT_EQ(3, tracker.comparisons());\n  EXPECT_FALSE(one > two);\n  EXPECT_EQ(4, tracker.comparisons());\n  EXPECT_TRUE(one <= two);\n  EXPECT_EQ(5, tracker.comparisons());\n  EXPECT_FALSE(one >= two);\n  EXPECT_EQ(6, tracker.comparisons());\n  EXPECT_TRUE(one.compare(two) < 0);  // NOLINT\n  EXPECT_EQ(7, tracker.comparisons());\n\n  tracker.ResetCopiesMovesSwaps();\n  EXPECT_EQ(0, tracker.comparisons());\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/internal/tracked.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_TRACKED_H_\n#define ABSL_CONTAINER_INTERNAL_TRACKED_H_\n\n#include <stddef.h>\n\n#include <memory>\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\n// A class that tracks its copies and moves so that it can be queried in tests.\ntemplate <class T>\nclass Tracked {\n public:\n  Tracked() {}\n  // NOLINTNEXTLINE(runtime/explicit)\n  Tracked(const T& val) : val_(val) {}\n  Tracked(const Tracked& that)\n      : val_(that.val_),\n        num_moves_(that.num_moves_),\n        num_copies_(that.num_copies_) {\n    ++(*num_copies_);\n  }\n  Tracked(Tracked&& that)\n      : val_(std::move(that.val_)),\n        num_moves_(std::move(that.num_moves_)),\n        num_copies_(std::move(that.num_copies_)) {\n    ++(*num_moves_);\n  }\n  Tracked& operator=(const Tracked& that) {\n    val_ = that.val_;\n    num_moves_ = that.num_moves_;\n    num_copies_ = that.num_copies_;\n    ++(*num_copies_);\n  }\n  Tracked& operator=(Tracked&& that) {\n    val_ = std::move(that.val_);\n    num_moves_ = std::move(that.num_moves_);\n    num_copies_ = std::move(that.num_copies_);\n    ++(*num_moves_);\n  }\n\n  const T& val() const { return val_; }\n\n  friend bool operator==(const Tracked& a, const Tracked& b) {\n    return a.val_ == b.val_;\n  }\n  friend bool operator!=(const Tracked& a, const Tracked& b) {\n    return !(a == b);\n  }\n\n  size_t num_copies() { return *num_copies_; }\n  size_t num_moves() { return *num_moves_; }\n\n private:\n  T val_;\n  std::shared_ptr<size_t> num_moves_ = std::make_shared<size_t>(0);\n  std::shared_ptr<size_t> num_copies_ = std::make_shared<size_t>(0);\n};\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_TRACKED_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_map_constructor_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_\n\n#include <algorithm>\n#include <unordered_map>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordMap>\nclass ConstructorTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(ConstructorTest);\n\nTYPED_TEST_P(ConstructorTest, NoArgs) {\n  TypeParam m;\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCount) {\n  TypeParam m(123);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHash) {\n  using H = typename TypeParam::hasher;\n  H hasher;\n  TypeParam m(123, hasher);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHashEqual) {\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  H hasher;\n  E equal;\n  TypeParam m(123, hasher, equal);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) {\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(123, hasher, equal, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\ntemplate <typename TypeParam>\nvoid BucketCountAllocTest() {\n  using A = typename TypeParam::allocator_type;\n  A alloc(0);\n  TypeParam m(123, alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountAlloc) {\n  BucketCountAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid BucketCountHashAllocTest() {\n  using H = typename TypeParam::hasher;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  A alloc(0);\n  TypeParam m(123, hasher, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {\n  BucketCountHashAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid AllocTest() {\n  using A = typename TypeParam::allocator_type;\n  A alloc(0);\n  TypeParam m(alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(m, ::testing::UnorderedElementsAre());\n}\n\nTYPED_TEST_P(ConstructorTest, Alloc) { AllocTest<TypeParam>(); }\n\nTYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, UniqueGenerator<T>());\n  TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\ntemplate <typename TypeParam>\nvoid InputIteratorBucketAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using A = typename TypeParam::allocator_type;\n  A alloc(0);\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, UniqueGenerator<T>());\n  TypeParam m(values.begin(), values.end(), 123, alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {\n  InputIteratorBucketAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid InputIteratorBucketHashAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  A alloc(0);\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, UniqueGenerator<T>());\n  TypeParam m(values.begin(), values.end(), 123, hasher, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {\n  InputIteratorBucketHashAllocTest<TypeParam>();\n}\n\nTYPED_TEST_P(ConstructorTest, CopyConstructor) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(gen());\n  TypeParam n(m);\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\ntemplate <typename TypeParam>\nvoid CopyConstructorAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(gen());\n  TypeParam n(m, A(11));\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_NE(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {\n  CopyConstructorAllocTest<TypeParam>();\n}\n\n// TODO(alkis): Test non-propagating allocators on copy constructors.\n\nTYPED_TEST_P(ConstructorTest, MoveConstructor) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(gen());\n  TypeParam t(m);\n  TypeParam n(std::move(t));\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\ntemplate <typename TypeParam>\nvoid MoveConstructorAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(gen());\n  TypeParam t(m);\n  TypeParam n(std::move(t), A(1));\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_NE(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {\n  MoveConstructorAllocTest<TypeParam>();\n}\n\n// TODO(alkis): Test non-propagating allocators on move constructors.\n\nTYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {\n  using T = GeneratedType<TypeParam>;\n  UniqueGenerator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(values, 123, hasher, equal, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\ntemplate <typename TypeParam>\nvoid InitializerListBucketAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using A = typename TypeParam::allocator_type;\n  UniqueGenerator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  A alloc(0);\n  TypeParam m(values, 123, alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {\n  InitializerListBucketAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid InitializerListBucketHashAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m(values, 123, hasher, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {\n  InitializerListBucketHashAllocTest<TypeParam>();\n}\n\nTYPED_TEST_P(ConstructorTest, Assignment) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);\n  TypeParam n;\n  n = m;\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m, n);\n}\n\n// TODO(alkis): Test [non-]propagating allocators on move/copy assignments\n// (it depends on traits).\n\nTYPED_TEST_P(ConstructorTest, MoveAssignment) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  UniqueGenerator<T> gen;\n  TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);\n  TypeParam t(m);\n  TypeParam n;\n  n = std::move(t);\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) {\n  using T = GeneratedType<TypeParam>;\n  UniqueGenerator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m;\n  m = values;\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) {\n  using T = GeneratedType<TypeParam>;\n  UniqueGenerator<T> gen;\n  TypeParam m({gen(), gen(), gen()});\n  TypeParam n({gen()});\n  n = m;\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) {\n  using T = GeneratedType<TypeParam>;\n  UniqueGenerator<T> gen;\n  TypeParam m({gen(), gen(), gen()});\n  TypeParam t(m);\n  TypeParam n({gen()});\n  n = std::move(t);\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) {\n  using T = GeneratedType<TypeParam>;\n  UniqueGenerator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m;\n  m = values;\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {\n  using T = GeneratedType<TypeParam>;\n  UniqueGenerator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m(values);\n  m = *&m;  // Avoid -Wself-assign\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n}\n\n// We cannot test self move as standard states that it leaves standard\n// containers in unspecified state (and in practice in causes memory-leak\n// according to heap-checker!).\n\nREGISTER_TYPED_TEST_SUITE_P(\n    ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,\n    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,\n    InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,\n    InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,\n    MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,\n    InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,\n    MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,\n    MoveAssignmentOverwritesExisting,\n    AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_map_lookup_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordMap>\nclass LookupTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(LookupTest);\n\nTYPED_TEST_P(LookupTest, At) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  for (const auto& p : values) {\n    const auto& val = m.at(p.first);\n    EXPECT_EQ(p.second, val) << ::testing::PrintToString(p.first);\n  }\n}\n\nTYPED_TEST_P(LookupTest, OperatorBracket) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& p : values) {\n    auto& val = m[p.first];\n    EXPECT_EQ(V(), val) << ::testing::PrintToString(p.first);\n    val = p.second;\n  }\n  for (const auto& p : values)\n    EXPECT_EQ(p.second, m[p.first]) << ::testing::PrintToString(p.first);\n}\n\nTYPED_TEST_P(LookupTest, Count) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& p : values)\n    EXPECT_EQ(0, m.count(p.first)) << ::testing::PrintToString(p.first);\n  m.insert(values.begin(), values.end());\n  for (const auto& p : values)\n    EXPECT_EQ(1, m.count(p.first)) << ::testing::PrintToString(p.first);\n}\n\nTYPED_TEST_P(LookupTest, Find) {\n  using std::get;\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& p : values)\n    EXPECT_TRUE(m.end() == m.find(p.first))\n        << ::testing::PrintToString(p.first);\n  m.insert(values.begin(), values.end());\n  for (const auto& p : values) {\n    auto it = m.find(p.first);\n    EXPECT_TRUE(m.end() != it) << ::testing::PrintToString(p.first);\n    EXPECT_EQ(p.second, get<1>(*it)) << ::testing::PrintToString(p.first);\n  }\n}\n\nTYPED_TEST_P(LookupTest, EqualRange) {\n  using std::get;\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& p : values) {\n    auto r = m.equal_range(p.first);\n    ASSERT_EQ(0, std::distance(r.first, r.second));\n  }\n  m.insert(values.begin(), values.end());\n  for (const auto& p : values) {\n    auto r = m.equal_range(p.first);\n    ASSERT_EQ(1, std::distance(r.first, r.second));\n    EXPECT_EQ(p.second, get<1>(*r.first)) << ::testing::PrintToString(p.first);\n  }\n}\n\nREGISTER_TYPED_TEST_SUITE_P(LookupTest, At, OperatorBracket, Count, Find,\n                            EqualRange);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_map_members_test.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_\n\n#include <type_traits>\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordMap>\nclass MembersTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(MembersTest);\n\ntemplate <typename T>\nvoid UseType() {}\n\nTYPED_TEST_P(MembersTest, Typedefs) {\n  EXPECT_TRUE((std::is_same<std::pair<const typename TypeParam::key_type,\n                                      typename TypeParam::mapped_type>,\n                            typename TypeParam::value_type>()));\n  EXPECT_TRUE((std::conjunction<\n               std::negation<std::is_signed<typename TypeParam::size_type>>,\n               std::is_integral<typename TypeParam::size_type>>()));\n  EXPECT_TRUE((std::conjunction<\n               std::is_signed<typename TypeParam::difference_type>,\n               std::is_integral<typename TypeParam::difference_type>>()));\n  EXPECT_TRUE((std::is_convertible<\n               decltype(std::declval<const typename TypeParam::hasher&>()(\n                   std::declval<const typename TypeParam::key_type&>())),\n               size_t>()));\n  EXPECT_TRUE((std::is_convertible<\n               decltype(std::declval<const typename TypeParam::key_equal&>()(\n                   std::declval<const typename TypeParam::key_type&>(),\n                   std::declval<const typename TypeParam::key_type&>())),\n               bool>()));\n  EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,\n                            typename TypeParam::value_type>()));\n  EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,\n                            typename TypeParam::reference>()));\n  EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,\n                            typename TypeParam::const_reference>()));\n  EXPECT_TRUE((std::is_same<typename std::allocator_traits<\n                                typename TypeParam::allocator_type>::pointer,\n                            typename TypeParam::pointer>()));\n  EXPECT_TRUE(\n      (std::is_same<typename std::allocator_traits<\n                        typename TypeParam::allocator_type>::const_pointer,\n                    typename TypeParam::const_pointer>()));\n}\n\nTYPED_TEST_P(MembersTest, SimpleFunctions) {\n  EXPECT_GT(TypeParam().max_size(), 0);\n}\n\nTYPED_TEST_P(MembersTest, BeginEnd) {\n  TypeParam t = {typename TypeParam::value_type{}};\n  EXPECT_EQ(t.begin(), t.cbegin());\n  EXPECT_EQ(t.end(), t.cend());\n  EXPECT_NE(t.begin(), t.end());\n  EXPECT_NE(t.cbegin(), t.cend());\n}\n\nREGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_map_modifiers_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_\n\n#include <memory>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordMap>\nclass ModifiersTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(ModifiersTest);\n\nTYPED_TEST_P(ModifiersTest, Clear) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  m.clear();\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAre());\n  EXPECT_TRUE(m.empty());\n}\n\nTYPED_TEST_P(ModifiersTest, Insert) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  auto p = m.insert(val);\n  EXPECT_TRUE(p.second);\n  EXPECT_EQ(val, *p.first);\n  T val2 = {val.first, Generator<V>()()};\n  p = m.insert(val2);\n  EXPECT_FALSE(p.second);\n  EXPECT_EQ(val, *p.first);\n}\n\nTYPED_TEST_P(ModifiersTest, InsertHint) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  auto it = m.insert(m.end(), val);\n  EXPECT_TRUE(it != m.end());\n  EXPECT_EQ(val, *it);\n  T val2 = {val.first, Generator<V>()()};\n  it = m.insert(it, val2);\n  EXPECT_TRUE(it != m.end());\n  EXPECT_EQ(val, *it);\n}\n\nTYPED_TEST_P(ModifiersTest, InsertRange) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  m.insert(values.begin(), values.end());\n  ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nTYPED_TEST_P(ModifiersTest, InsertWithinCapacity) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  m.reserve(10);\n  const size_t original_capacity = m.bucket_count();\n  m.insert(val);\n  EXPECT_EQ(m.bucket_count(), original_capacity);\n  T val2 = {val.first, Generator<V>()()};\n  m.insert(val2);\n  EXPECT_EQ(m.bucket_count(), original_capacity);\n}\n\nTYPED_TEST_P(ModifiersTest, InsertRangeWithinCapacity) {\n#if !defined(__GLIBCXX__)\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> base_values;\n  std::generate_n(std::back_inserter(base_values), 10, Generator<T>());\n  std::vector<T> values;\n  while (values.size() != 100) {\n    std::copy_n(base_values.begin(), 10, std::back_inserter(values));\n  }\n  TypeParam m;\n  m.reserve(10);\n  const size_t original_capacity = m.bucket_count();\n  m.insert(values.begin(), values.end());\n  EXPECT_EQ(m.bucket_count(), original_capacity);\n#endif\n}\n\nTYPED_TEST_P(ModifiersTest, InsertOrAssign) {\n  using std::get;\n  using K = typename TypeParam::key_type;\n  using V = typename TypeParam::mapped_type;\n  K k = Generator<K>()();\n  V val = Generator<V>()();\n  TypeParam m;\n  auto p = m.insert_or_assign(k, val);\n  EXPECT_TRUE(p.second);\n  EXPECT_EQ(k, get<0>(*p.first));\n  EXPECT_EQ(val, get<1>(*p.first));\n  V val2 = Generator<V>()();\n  p = m.insert_or_assign(k, val2);\n  EXPECT_FALSE(p.second);\n  EXPECT_EQ(k, get<0>(*p.first));\n  EXPECT_EQ(val2, get<1>(*p.first));\n}\n\nTYPED_TEST_P(ModifiersTest, InsertOrAssignHint) {\n  using std::get;\n  using K = typename TypeParam::key_type;\n  using V = typename TypeParam::mapped_type;\n  K k = Generator<K>()();\n  V val = Generator<V>()();\n  TypeParam m;\n  auto it = m.insert_or_assign(m.end(), k, val);\n  EXPECT_TRUE(it != m.end());\n  EXPECT_EQ(k, get<0>(*it));\n  EXPECT_EQ(val, get<1>(*it));\n  V val2 = Generator<V>()();\n  it = m.insert_or_assign(it, k, val2);\n  EXPECT_EQ(k, get<0>(*it));\n  EXPECT_EQ(val2, get<1>(*it));\n}\n\nTYPED_TEST_P(ModifiersTest, Emplace) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps\n  // with test traits/policy.\n  auto p = m.emplace(val);\n  EXPECT_TRUE(p.second);\n  EXPECT_EQ(val, *p.first);\n  T val2 = {val.first, Generator<V>()()};\n  p = m.emplace(val2);\n  EXPECT_FALSE(p.second);\n  EXPECT_EQ(val, *p.first);\n}\n\nTYPED_TEST_P(ModifiersTest, EmplaceHint) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps\n  // with test traits/policy.\n  auto it = m.emplace_hint(m.end(), val);\n  EXPECT_EQ(val, *it);\n  T val2 = {val.first, Generator<V>()()};\n  it = m.emplace_hint(it, val2);\n  EXPECT_EQ(val, *it);\n}\n\nTYPED_TEST_P(ModifiersTest, TryEmplace) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps\n  // with test traits/policy.\n  auto p = m.try_emplace(val.first, val.second);\n  EXPECT_TRUE(p.second);\n  EXPECT_EQ(val, *p.first);\n  T val2 = {val.first, Generator<V>()()};\n  p = m.try_emplace(val2.first, val2.second);\n  EXPECT_FALSE(p.second);\n  EXPECT_EQ(val, *p.first);\n}\n\nTYPED_TEST_P(ModifiersTest, TryEmplaceHint) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps\n  // with test traits/policy.\n  auto it = m.try_emplace(m.end(), val.first, val.second);\n  EXPECT_EQ(val, *it);\n  T val2 = {val.first, Generator<V>()()};\n  it = m.try_emplace(it, val2.first, val2.second);\n  EXPECT_EQ(val, *it);\n}\n\ntemplate <class V>\nusing IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type;\n\n// In openmap we chose not to return the iterator from erase because that's\n// more expensive. As such we adapt erase to return an iterator here.\nstruct EraseFirst {\n  template <class Map>\n  auto operator()(Map* m, int) const\n      -> IfNotVoid<decltype(m->erase(m->begin()))> {\n    return m->erase(m->begin());\n  }\n  template <class Map>\n  typename Map::iterator operator()(Map* m, ...) const {\n    auto it = m->begin();\n    m->erase(it++);\n    return it;\n  }\n};\n\nTYPED_TEST_P(ModifiersTest, Erase) {\n  using T = GeneratedType<TypeParam>;\n  using std::get;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  auto& first = *m.begin();\n  std::vector<T> values2;\n  for (const auto& val : values)\n    if (get<0>(val) != get<0>(first)) values2.push_back(val);\n  auto it = EraseFirst()(&m, 0);\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it));\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values2.begin(),\n                                                             values2.end()));\n}\n\nTYPED_TEST_P(ModifiersTest, EraseRange) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  auto it = m.erase(m.begin(), m.end());\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAre());\n  EXPECT_TRUE(it == m.end());\n}\n\nTYPED_TEST_P(ModifiersTest, EraseKey) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_EQ(1, m.erase(values[0].first));\n  EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0]));\n  EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values.begin() + 1,\n                                                             values.end()));\n}\n\nTYPED_TEST_P(ModifiersTest, Swap) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> v1;\n  std::vector<T> v2;\n  std::generate_n(std::back_inserter(v1), 5, Generator<T>());\n  std::generate_n(std::back_inserter(v2), 5, Generator<T>());\n  TypeParam m1(v1.begin(), v1.end());\n  TypeParam m2(v2.begin(), v2.end());\n  EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v1));\n  EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v2));\n  m1.swap(m2);\n  EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v2));\n  EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v1));\n}\n\n// TODO(alkis): Write tests for extract.\n// TODO(alkis): Write tests for merge.\n\nREGISTER_TYPED_TEST_SUITE_P(ModifiersTest, Clear, Insert, InsertHint,\n                            InsertRange, InsertWithinCapacity,\n                            InsertRangeWithinCapacity, InsertOrAssign,\n                            InsertOrAssignHint, Emplace, EmplaceHint,\n                            TryEmplace, TryEmplaceHint, Erase, EraseRange,\n                            EraseKey, Swap);\n\ntemplate <typename Type>\nstruct is_unique_ptr : std::false_type {};\n\ntemplate <typename Type>\nstruct is_unique_ptr<std::unique_ptr<Type>> : std::true_type {};\n\ntemplate <class UnordMap>\nclass UniquePtrModifiersTest : public ::testing::Test {\n protected:\n  UniquePtrModifiersTest() {\n    static_assert(is_unique_ptr<typename UnordMap::mapped_type>::value,\n                  \"UniquePtrModifiersTyest may only be called with a \"\n                  \"std::unique_ptr value type.\");\n  }\n};\n\nGTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniquePtrModifiersTest);\n\nTYPED_TEST_SUITE_P(UniquePtrModifiersTest);\n\n// Test that we do not move from rvalue arguments if an insertion does not\n// happen.\nTYPED_TEST_P(UniquePtrModifiersTest, TryEmplace) {\n  using T = GeneratedType<TypeParam>;\n  using V = typename TypeParam::mapped_type;\n  T val = Generator<T>()();\n  TypeParam m;\n  auto p = m.try_emplace(val.first, std::move(val.second));\n  EXPECT_TRUE(p.second);\n  // A moved from std::unique_ptr is guaranteed to be nullptr.\n  EXPECT_EQ(val.second, nullptr);\n  T val2 = {val.first, Generator<V>()()};\n  p = m.try_emplace(val2.first, std::move(val2.second));\n  EXPECT_FALSE(p.second);\n  EXPECT_NE(val2.second, nullptr);\n}\n\nREGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_map_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <memory>\n#include <unordered_map>\n\n#include \"absl/container/internal/unordered_map_constructor_test.h\"\n#include \"absl/container/internal/unordered_map_lookup_test.h\"\n#include \"absl/container/internal/unordered_map_members_test.h\"\n#include \"absl/container/internal/unordered_map_modifiers_test.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing MapTypes = ::testing::Types<\n    std::unordered_map<int, int, StatefulTestingHash, StatefulTestingEqual,\n                       Alloc<std::pair<const int, int>>>,\n    std::unordered_map<std::string, std::string, StatefulTestingHash,\n                       StatefulTestingEqual,\n                       Alloc<std::pair<const std::string, std::string>>>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ConstructorTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, MembersTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes);\n\nusing UniquePtrMapTypes = ::testing::Types<std::unordered_map<\n    int, std::unique_ptr<int>, StatefulTestingHash, StatefulTestingEqual,\n    Alloc<std::pair<const int, std::unique_ptr<int>>>>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, UniquePtrModifiersTest,\n                               UniquePtrMapTypes);\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/internal/unordered_set_constructor_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_\n\n#include <algorithm>\n#include <unordered_set>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordMap>\nclass ConstructorTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(ConstructorTest);\n\nTYPED_TEST_P(ConstructorTest, NoArgs) {\n  TypeParam m;\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCount) {\n  TypeParam m(123);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHash) {\n  using H = typename TypeParam::hasher;\n  H hasher;\n  TypeParam m(123, hasher);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHashEqual) {\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  H hasher;\n  E equal;\n  TypeParam m(123, hasher, equal);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) {\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(123, hasher, equal, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n\n  const auto& cm = m;\n  EXPECT_EQ(cm.hash_function(), hasher);\n  EXPECT_EQ(cm.key_eq(), equal);\n  EXPECT_EQ(cm.get_allocator(), alloc);\n  EXPECT_TRUE(cm.empty());\n  EXPECT_THAT(keys(cm), ::testing::UnorderedElementsAre());\n  EXPECT_GE(cm.bucket_count(), 123);\n}\n\ntemplate <typename TypeParam>\nvoid BucketCountAllocTest() {\n  using A = typename TypeParam::allocator_type;\n  A alloc(0);\n  TypeParam m(123, alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountAlloc) {\n  BucketCountAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid BucketCountHashAllocTest() {\n  using H = typename TypeParam::hasher;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  A alloc(0);\n  TypeParam m(123, hasher, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {\n  BucketCountHashAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid AllocTest() {\n  using A = typename TypeParam::allocator_type;\n  A alloc(0);\n  TypeParam m(alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_TRUE(m.empty());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n}\n\nTYPED_TEST_P(ConstructorTest, Alloc) { AllocTest<TypeParam>(); }\n\nTYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  std::vector<T> values;\n  for (size_t i = 0; i != 10; ++i) values.push_back(Generator<T>()());\n  TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\ntemplate <typename TypeParam>\nvoid InputIteratorBucketAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using A = typename TypeParam::allocator_type;\n  A alloc(0);\n  std::vector<T> values;\n  for (size_t i = 0; i != 10; ++i) values.push_back(Generator<T>()());\n  TypeParam m(values.begin(), values.end(), 123, alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {\n  InputIteratorBucketAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid InputIteratorBucketHashAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  A alloc(0);\n  std::vector<T> values;\n  for (size_t i = 0; i != 10; ++i) values.push_back(Generator<T>()());\n  TypeParam m(values.begin(), values.end(), 123, hasher, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {\n  InputIteratorBucketHashAllocTest<TypeParam>();\n}\n\nTYPED_TEST_P(ConstructorTest, CopyConstructor) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(Generator<T>()());\n  TypeParam n(m);\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n  EXPECT_NE(TypeParam(0, hasher, equal, alloc), n);\n}\n\ntemplate <typename TypeParam>\nvoid CopyConstructorAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(Generator<T>()());\n  TypeParam n(m, A(11));\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_NE(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {\n  CopyConstructorAllocTest<TypeParam>();\n}\n\n// TODO(alkis): Test non-propagating allocators on copy constructors.\n\nTYPED_TEST_P(ConstructorTest, MoveConstructor) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(Generator<T>()());\n  TypeParam t(m);\n  TypeParam n(std::move(t));\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\ntemplate <typename TypeParam>\nvoid MoveConstructorAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(123, hasher, equal, alloc);\n  for (size_t i = 0; i != 10; ++i) m.insert(Generator<T>()());\n  TypeParam t(m);\n  TypeParam n(std::move(t), A(1));\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_NE(m.get_allocator(), n.get_allocator());\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {\n  MoveConstructorAllocTest<TypeParam>();\n}\n\n// TODO(alkis): Test non-propagating allocators on move constructors.\n\nTYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {\n  using T = GeneratedType<TypeParam>;\n  Generator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  TypeParam m(values, 123, hasher, equal, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.key_eq(), equal);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\ntemplate <typename TypeParam>\nvoid InitializerListBucketAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using A = typename TypeParam::allocator_type;\n  Generator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  A alloc(0);\n  TypeParam m(values, 123, alloc);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {\n  InitializerListBucketAllocTest<TypeParam>();\n}\n\ntemplate <typename TypeParam>\nvoid InitializerListBucketHashAllocTest() {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  A alloc(0);\n  Generator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m(values, 123, hasher, alloc);\n  EXPECT_EQ(m.hash_function(), hasher);\n  EXPECT_EQ(m.get_allocator(), alloc);\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_GE(m.bucket_count(), 123);\n}\n\nTYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {\n  InitializerListBucketHashAllocTest<TypeParam>();\n}\n\nTYPED_TEST_P(ConstructorTest, CopyAssignment) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  Generator<T> gen;\n  TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);\n  TypeParam n;\n  n = m;\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m, n);\n}\n\n// TODO(alkis): Test [non-]propagating allocators on move/copy assignments\n// (it depends on traits).\n\nTYPED_TEST_P(ConstructorTest, MoveAssignment) {\n  using T = GeneratedType<TypeParam>;\n  using H = typename TypeParam::hasher;\n  using E = typename TypeParam::key_equal;\n  using A = typename TypeParam::allocator_type;\n  H hasher;\n  E equal;\n  A alloc(0);\n  Generator<T> gen;\n  TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);\n  TypeParam t(m);\n  TypeParam n;\n  n = std::move(t);\n  EXPECT_EQ(m.hash_function(), n.hash_function());\n  EXPECT_EQ(m.key_eq(), n.key_eq());\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) {\n  using T = GeneratedType<TypeParam>;\n  Generator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m;\n  m = values;\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) {\n  using T = GeneratedType<TypeParam>;\n  Generator<T> gen;\n  TypeParam m({gen(), gen(), gen()});\n  TypeParam n({gen()});\n  n = m;\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) {\n  using T = GeneratedType<TypeParam>;\n  Generator<T> gen;\n  TypeParam m({gen(), gen(), gen()});\n  TypeParam t(m);\n  TypeParam n({gen()});\n  n = std::move(t);\n  EXPECT_EQ(m, n);\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) {\n  using T = GeneratedType<TypeParam>;\n  Generator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m;\n  m = values;\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nTYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {\n  using T = GeneratedType<TypeParam>;\n  Generator<T> gen;\n  std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};\n  TypeParam m(values);\n  m = *&m;  // Avoid -Wself-assign.\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(\n    ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,\n    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,\n    InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,\n    InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,\n    MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,\n    InitializerListBucketAlloc, InitializerListBucketHashAlloc, CopyAssignment,\n    MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,\n    MoveAssignmentOverwritesExisting,\n    AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_set_lookup_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordSet>\nclass LookupTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(LookupTest);\n\nTYPED_TEST_P(LookupTest, Count) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& v : values)\n    EXPECT_EQ(0, m.count(v)) << ::testing::PrintToString(v);\n  m.insert(values.begin(), values.end());\n  for (const auto& v : values)\n    EXPECT_EQ(1, m.count(v)) << ::testing::PrintToString(v);\n}\n\nTYPED_TEST_P(LookupTest, Find) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& v : values)\n    EXPECT_TRUE(m.end() == m.find(v)) << ::testing::PrintToString(v);\n  m.insert(values.begin(), values.end());\n  for (const auto& v : values) {\n    typename TypeParam::iterator it = m.find(v);\n    static_assert(std::is_same<const typename TypeParam::value_type&,\n                               decltype(*it)>::value,\n                  \"\");\n    static_assert(std::is_same<const typename TypeParam::value_type*,\n                               decltype(it.operator->())>::value,\n                  \"\");\n    EXPECT_TRUE(m.end() != it) << ::testing::PrintToString(v);\n    EXPECT_EQ(v, *it) << ::testing::PrintToString(v);\n  }\n}\n\nTYPED_TEST_P(LookupTest, EqualRange) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  for (const auto& v : values) {\n    auto r = m.equal_range(v);\n    ASSERT_EQ(0, std::distance(r.first, r.second));\n  }\n  m.insert(values.begin(), values.end());\n  for (const auto& v : values) {\n    auto r = m.equal_range(v);\n    ASSERT_EQ(1, std::distance(r.first, r.second));\n    EXPECT_EQ(v, *r.first);\n  }\n}\n\nREGISTER_TYPED_TEST_SUITE_P(LookupTest, Count, Find, EqualRange);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_set_members_test.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_\n\n#include <type_traits>\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordSet>\nclass MembersTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(MembersTest);\n\ntemplate <typename T>\nvoid UseType() {}\n\nTYPED_TEST_P(MembersTest, Typedefs) {\n  EXPECT_TRUE((std::is_same<typename TypeParam::key_type,\n                            typename TypeParam::value_type>()));\n  EXPECT_TRUE((std::conjunction<\n               std::negation<std::is_signed<typename TypeParam::size_type>>,\n               std::is_integral<typename TypeParam::size_type>>()));\n  EXPECT_TRUE((std::conjunction<\n               std::is_signed<typename TypeParam::difference_type>,\n               std::is_integral<typename TypeParam::difference_type>>()));\n  EXPECT_TRUE((std::is_convertible<\n               decltype(std::declval<const typename TypeParam::hasher&>()(\n                   std::declval<const typename TypeParam::key_type&>())),\n               size_t>()));\n  EXPECT_TRUE((std::is_convertible<\n               decltype(std::declval<const typename TypeParam::key_equal&>()(\n                   std::declval<const typename TypeParam::key_type&>(),\n                   std::declval<const typename TypeParam::key_type&>())),\n               bool>()));\n  EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,\n                            typename TypeParam::value_type>()));\n  EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,\n                            typename TypeParam::reference>()));\n  EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,\n                            typename TypeParam::const_reference>()));\n  EXPECT_TRUE((std::is_same<typename std::allocator_traits<\n                                typename TypeParam::allocator_type>::pointer,\n                            typename TypeParam::pointer>()));\n  EXPECT_TRUE(\n      (std::is_same<typename std::allocator_traits<\n                        typename TypeParam::allocator_type>::const_pointer,\n                    typename TypeParam::const_pointer>()));\n}\n\nTYPED_TEST_P(MembersTest, SimpleFunctions) {\n  EXPECT_GT(TypeParam().max_size(), 0);\n}\n\nTYPED_TEST_P(MembersTest, BeginEnd) {\n  TypeParam t = {typename TypeParam::value_type{}};\n  EXPECT_EQ(t.begin(), t.cbegin());\n  EXPECT_EQ(t.end(), t.cend());\n  EXPECT_NE(t.begin(), t.end());\n  EXPECT_NE(t.cbegin(), t.cend());\n}\n\nREGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_set_modifiers_test.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_\n#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\n\ntemplate <class UnordSet>\nclass ModifiersTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(ModifiersTest);\n\nTYPED_TEST_P(ModifiersTest, Clear) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  m.clear();\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_TRUE(m.empty());\n}\n\nTYPED_TEST_P(ModifiersTest, Insert) {\n  using T = GeneratedType<TypeParam>;\n  T val = Generator<T>()();\n  TypeParam m;\n  auto p = m.insert(val);\n  EXPECT_TRUE(p.second);\n  EXPECT_EQ(val, *p.first);\n  p = m.insert(val);\n  EXPECT_FALSE(p.second);\n}\n\nTYPED_TEST_P(ModifiersTest, InsertHint) {\n  using T = GeneratedType<TypeParam>;\n  T val = Generator<T>()();\n  TypeParam m;\n  auto it = m.insert(m.end(), val);\n  EXPECT_TRUE(it != m.end());\n  EXPECT_EQ(val, *it);\n  it = m.insert(it, val);\n  EXPECT_TRUE(it != m.end());\n  EXPECT_EQ(val, *it);\n}\n\nTYPED_TEST_P(ModifiersTest, InsertRange) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m;\n  m.insert(values.begin(), values.end());\n  ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n}\n\nTYPED_TEST_P(ModifiersTest, InsertWithinCapacity) {\n  using T = GeneratedType<TypeParam>;\n  T val = Generator<T>()();\n  TypeParam m;\n  m.reserve(10);\n  const size_t original_capacity = m.bucket_count();\n  m.insert(val);\n  EXPECT_EQ(m.bucket_count(), original_capacity);\n  m.insert(val);\n  EXPECT_EQ(m.bucket_count(), original_capacity);\n}\n\nTYPED_TEST_P(ModifiersTest, InsertRangeWithinCapacity) {\n#if !defined(__GLIBCXX__)\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> base_values;\n  std::generate_n(std::back_inserter(base_values), 10, Generator<T>());\n  std::vector<T> values;\n  while (values.size() != 100) {\n    values.insert(values.end(), base_values.begin(), base_values.end());\n  }\n  TypeParam m;\n  m.reserve(10);\n  const size_t original_capacity = m.bucket_count();\n  m.insert(values.begin(), values.end());\n  EXPECT_EQ(m.bucket_count(), original_capacity);\n#endif\n}\n\nTYPED_TEST_P(ModifiersTest, Emplace) {\n  using T = GeneratedType<TypeParam>;\n  T val = Generator<T>()();\n  TypeParam m;\n  // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps\n  // with test traits/policy.\n  auto p = m.emplace(val);\n  EXPECT_TRUE(p.second);\n  EXPECT_EQ(val, *p.first);\n  p = m.emplace(val);\n  EXPECT_FALSE(p.second);\n  EXPECT_EQ(val, *p.first);\n}\n\nTYPED_TEST_P(ModifiersTest, EmplaceHint) {\n  using T = GeneratedType<TypeParam>;\n  T val = Generator<T>()();\n  TypeParam m;\n  // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps\n  // with test traits/policy.\n  auto it = m.emplace_hint(m.end(), val);\n  EXPECT_EQ(val, *it);\n  it = m.emplace_hint(it, val);\n  EXPECT_EQ(val, *it);\n}\n\ntemplate <class V>\nusing IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type;\n\n// In openmap we chose not to return the iterator from erase because that's\n// more expensive. As such we adapt erase to return an iterator here.\nstruct EraseFirst {\n  template <class Map>\n  auto operator()(Map* m, int) const\n      -> IfNotVoid<decltype(m->erase(m->begin()))> {\n    return m->erase(m->begin());\n  }\n  template <class Map>\n  typename Map::iterator operator()(Map* m, ...) const {\n    auto it = m->begin();\n    m->erase(it++);\n    return it;\n  }\n};\n\nTYPED_TEST_P(ModifiersTest, Erase) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  std::vector<T> values2;\n  for (const auto& val : values)\n    if (val != *m.begin()) values2.push_back(val);\n  auto it = EraseFirst()(&m, 0);\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it));\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values2.begin(),\n                                                            values2.end()));\n}\n\nTYPED_TEST_P(ModifiersTest, EraseRange) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  auto it = m.erase(m.begin(), m.end());\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());\n  EXPECT_TRUE(it == m.end());\n}\n\nTYPED_TEST_P(ModifiersTest, EraseKey) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> values;\n  std::generate_n(std::back_inserter(values), 10, Generator<T>());\n  TypeParam m(values.begin(), values.end());\n  ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));\n  EXPECT_EQ(1, m.erase(values[0]));\n  EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0]));\n  EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values.begin() + 1,\n                                                            values.end()));\n}\n\nTYPED_TEST_P(ModifiersTest, Swap) {\n  using T = GeneratedType<TypeParam>;\n  std::vector<T> v1;\n  std::vector<T> v2;\n  std::generate_n(std::back_inserter(v1), 5, Generator<T>());\n  std::generate_n(std::back_inserter(v2), 5, Generator<T>());\n  TypeParam m1(v1.begin(), v1.end());\n  TypeParam m2(v2.begin(), v2.end());\n  EXPECT_THAT(keys(m1), ::testing::UnorderedElementsAreArray(v1));\n  EXPECT_THAT(keys(m2), ::testing::UnorderedElementsAreArray(v2));\n  m1.swap(m2);\n  EXPECT_THAT(keys(m1), ::testing::UnorderedElementsAreArray(v2));\n  EXPECT_THAT(keys(m2), ::testing::UnorderedElementsAreArray(v1));\n}\n\n// TODO(alkis): Write tests for extract.\n// TODO(alkis): Write tests for merge.\n\nREGISTER_TYPED_TEST_SUITE_P(ModifiersTest, Clear, Insert, InsertHint,\n                            InsertRange, InsertWithinCapacity,\n                            InsertRangeWithinCapacity, Emplace, EmplaceHint,\n                            Erase, EraseRange, EraseKey, Swap);\n\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_\n"
  },
  {
    "path": "absl/container/internal/unordered_set_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <unordered_set>\n\n#include \"absl/container/internal/unordered_set_constructor_test.h\"\n#include \"absl/container/internal/unordered_set_lookup_test.h\"\n#include \"absl/container/internal/unordered_set_members_test.h\"\n#include \"absl/container/internal/unordered_set_modifiers_test.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing SetTypes = ::testing::Types<\n    std::unordered_set<int, StatefulTestingHash, StatefulTestingEqual,\n                       Alloc<int>>,\n    std::unordered_set<std::string, StatefulTestingHash, StatefulTestingEqual,\n                       Alloc<std::string>>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ConstructorTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, LookupTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, MembersTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes);\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/linked_hash_map.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: linked_hash_map.h\n// -----------------------------------------------------------------------------\n//\n// This is a simple insertion-ordered map. It provides O(1) amortized\n// insertions and lookups, as well as iteration over the map in the insertion\n// order.\n//\n// This class is thread-compatible.\n//\n// Iterators point into the list and should be stable in the face of\n// mutations, except for an iterator pointing to an element that was just\n// deleted.\n//\n// This class supports heterogeneous lookups.\n\n#ifndef ABSL_CONTAINER_LINKED_HASH_MAP_H_\n#define ABSL_CONTAINER_LINKED_HASH_MAP_H_\n\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <list>\n#include <memory>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/container/internal/common.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename Key, typename Value,\n          typename KeyHash = typename absl::flat_hash_set<Key>::hasher,\n          typename KeyEq =\n              typename absl::flat_hash_set<Key, KeyHash>::key_equal,\n          typename Alloc = std::allocator<std::pair<const Key, Value>>>\nclass linked_hash_map {\n  using KeyArgImpl = absl::container_internal::KeyArg<\n      absl::container_internal::IsTransparent<KeyEq>::value &&\n      absl::container_internal::IsTransparent<KeyHash>::value>;\n\n public:\n  using key_type = Key;\n  using mapped_type = Value;\n  using hasher = KeyHash;\n  using key_equal = KeyEq;\n  using value_type = std::pair<const key_type, mapped_type>;\n  using allocator_type = Alloc;\n  using difference_type = ptrdiff_t;\n\n private:\n  template <class K>\n  using key_arg = typename KeyArgImpl::template type<K, key_type>;\n\n  using ListType = std::list<value_type, Alloc>;\n\n  template <class Fn>\n  class Wrapped {\n    template <typename K>\n    static const K& ToKey(const K& k) {\n      return k;\n    }\n    static const key_type& ToKey(typename ListType::const_iterator it) {\n      return it->first;\n    }\n    static const key_type& ToKey(typename ListType::iterator it) {\n      return it->first;\n    }\n\n    Fn fn_;\n\n    friend linked_hash_map;\n\n   public:\n    using is_transparent = void;\n\n    Wrapped() = default;\n    explicit Wrapped(Fn fn) : fn_(std::move(fn)) {}\n\n    template <class... Args>\n    auto operator()(Args&&... args) const\n        -> decltype(this->fn_(ToKey(args)...)) {\n      return fn_(ToKey(args)...);\n    }\n  };\n  using SetType =\n      absl::flat_hash_set<typename ListType::iterator, Wrapped<hasher>,\n                          Wrapped<key_equal>, Alloc>;\n\n  class NodeHandle {\n   public:\n    using key_type = linked_hash_map::key_type;\n    using mapped_type = linked_hash_map::mapped_type;\n    using allocator_type = linked_hash_map::allocator_type;\n\n    constexpr NodeHandle() noexcept = default;\n    NodeHandle(NodeHandle&& nh) noexcept = default;\n    ~NodeHandle() = default;\n    NodeHandle& operator=(NodeHandle&& node) noexcept = default;\n    bool empty() const noexcept { return list_.empty(); }\n    explicit operator bool() const noexcept { return !empty(); }\n    allocator_type get_allocator() const { return list_.get_allocator(); }\n    const key_type& key() const { return list_.front().first; }\n    mapped_type& mapped() { return list_.front().second; }\n    void swap(NodeHandle& nh) noexcept { list_.swap(nh.list_); }\n\n   private:\n    friend linked_hash_map;\n\n    explicit NodeHandle(ListType list) : list_(std::move(list)) {}\n    ListType list_;\n  };\n\n  template <class Iterator, class NodeType>\n  struct InsertReturnType {\n    Iterator position;\n    bool inserted;\n    NodeType node;\n  };\n\n public:\n  using iterator = typename ListType::iterator;\n  using const_iterator = typename ListType::const_iterator;\n  using reverse_iterator = typename ListType::reverse_iterator;\n  using const_reverse_iterator = typename ListType::const_reverse_iterator;\n  using reference = typename ListType::reference;\n  using const_reference = typename ListType::const_reference;\n  using size_type = typename ListType::size_type;\n  using pointer = typename std::allocator_traits<allocator_type>::pointer;\n  using const_pointer =\n      typename std::allocator_traits<allocator_type>::const_pointer;\n  using node_type = NodeHandle;\n  using insert_return_type = InsertReturnType<iterator, node_type>;\n\n  linked_hash_map() {}\n\n  explicit linked_hash_map(size_t bucket_count, const hasher& hash = hasher(),\n                           const key_equal& eq = key_equal(),\n                           const allocator_type& alloc = allocator_type())\n      : set_(bucket_count, Wrapped<hasher>(hash), Wrapped<key_equal>(eq),\n             alloc),\n        list_(alloc) {}\n\n  linked_hash_map(size_t bucket_count, const hasher& hash,\n                  const allocator_type& alloc)\n      : linked_hash_map(bucket_count, hash, key_equal(), alloc) {}\n\n  linked_hash_map(size_t bucket_count, const allocator_type& alloc)\n      : linked_hash_map(bucket_count, hasher(), key_equal(), alloc) {}\n\n  explicit linked_hash_map(const allocator_type& alloc)\n      : linked_hash_map(0, hasher(), key_equal(), alloc) {}\n\n  template <class InputIt>\n  linked_hash_map(InputIt first, InputIt last, size_t bucket_count = 0,\n                  const hasher& hash = hasher(),\n                  const key_equal& eq = key_equal(),\n                  const allocator_type& alloc = allocator_type())\n      : linked_hash_map(bucket_count, hash, eq, alloc) {\n    insert(first, last);\n  }\n\n  template <class InputIt>\n  linked_hash_map(InputIt first, InputIt last, size_t bucket_count,\n                  const hasher& hash, const allocator_type& alloc)\n      : linked_hash_map(first, last, bucket_count, hash, key_equal(), alloc) {}\n\n  template <class InputIt>\n  linked_hash_map(InputIt first, InputIt last, size_t bucket_count,\n                  const allocator_type& alloc)\n      : linked_hash_map(first, last, bucket_count, hasher(), key_equal(),\n                        alloc) {}\n\n  template <class InputIt>\n  linked_hash_map(InputIt first, InputIt last, const allocator_type& alloc)\n      : linked_hash_map(first, last, /*bucket_count=*/0, hasher(), key_equal(),\n                        alloc) {}\n\n  linked_hash_map(std::initializer_list<value_type> init,\n                  size_t bucket_count = 0, const hasher& hash = hasher(),\n                  const key_equal& eq = key_equal(),\n                  const allocator_type& alloc = allocator_type())\n      : linked_hash_map(init.begin(), init.end(), bucket_count, hash, eq,\n                        alloc) {}\n\n  linked_hash_map(std::initializer_list<value_type> init, size_t bucket_count,\n                  const hasher& hash, const allocator_type& alloc)\n      : linked_hash_map(init, bucket_count, hash, key_equal(), alloc) {}\n\n  linked_hash_map(std::initializer_list<value_type> init, size_t bucket_count,\n                  const allocator_type& alloc)\n      : linked_hash_map(init, bucket_count, hasher(), key_equal(), alloc) {}\n\n  linked_hash_map(std::initializer_list<value_type> init,\n                  const allocator_type& alloc)\n      : linked_hash_map(init, /*bucket_count=*/0, hasher(), key_equal(),\n                        alloc) {}\n\n  linked_hash_map(const linked_hash_map& other)\n      : linked_hash_map(other.bucket_count(), other.hash_function(),\n                        other.key_eq(), other.get_allocator()) {\n    CopyFrom(other);\n  }\n\n  linked_hash_map(const linked_hash_map& other, const allocator_type& alloc)\n      : linked_hash_map(other.bucket_count(), other.hash_function(),\n                        other.key_eq(), alloc) {\n    CopyFrom(other);\n  }\n\n  linked_hash_map(linked_hash_map&& other) noexcept\n      : set_(std::move(other.set_)), list_(std::move(other.list_)) {\n    // Since the list and set must agree for other to end up \"valid\",\n    // explicitly clear them.\n    other.set_.clear();\n    other.list_.clear();\n  }\n\n  linked_hash_map(linked_hash_map&& other, const allocator_type& alloc)\n      : linked_hash_map(0, other.hash_function(), other.key_eq(), alloc) {\n    if (get_allocator() == other.get_allocator()) {\n      *this = std::move(other);\n    } else {\n      CopyFrom(std::move(other));\n    }\n  }\n\n  linked_hash_map& operator=(const linked_hash_map& other) {\n    if (this != &other) {\n      // Make a new set, with other's hash/eq/alloc.\n      set_ = SetType(other.bucket_count(), other.set_.hash_function(),\n                     other.set_.key_eq(), other.get_allocator());\n      // Copy the list, with other's allocator.\n      list_ = ListType(other.get_allocator());\n      CopyFrom(other);\n    }\n    return *this;\n  }\n\n  linked_hash_map& operator=(linked_hash_map&& other) noexcept {\n    if (this != &other) {\n      // underlying containers will handle progagate_on_container_move details\n      set_ = std::move(other.set_);\n      list_ = std::move(other.list_);\n      other.set_.clear();\n      other.list_.clear();\n    }\n    return *this;\n  }\n\n  linked_hash_map& operator=(std::initializer_list<value_type> values) {\n    clear();\n    insert(values.begin(), values.end());\n    return *this;\n  }\n\n  // Derive size_ from set_, as list::size might be O(N).\n  size_type size() const { return set_.size(); }\n  size_type max_size() const noexcept { return ~size_type{}; }\n  bool empty() const { return set_.empty(); }\n\n  // Iteration is list-like, in insertion order.\n  // These are all forwarded.\n  iterator begin() { return list_.begin(); }\n  iterator end() { return list_.end(); }\n  const_iterator begin() const { return list_.begin(); }\n  const_iterator end() const { return list_.end(); }\n  const_iterator cbegin() const { return list_.cbegin(); }\n  const_iterator cend() const { return list_.cend(); }\n  reverse_iterator rbegin() { return list_.rbegin(); }\n  reverse_iterator rend() { return list_.rend(); }\n  const_reverse_iterator rbegin() const { return list_.rbegin(); }\n  const_reverse_iterator rend() const { return list_.rend(); }\n  const_reverse_iterator crbegin() const { return list_.crbegin(); }\n  const_reverse_iterator crend() const { return list_.crend(); }\n  reference front() { return list_.front(); }\n  reference back() { return list_.back(); }\n  const_reference front() const { return list_.front(); }\n  const_reference back() const { return list_.back(); }\n\n  void pop_front() { erase(begin()); }\n  void pop_back() { erase(std::prev(end())); }\n\n  ABSL_ATTRIBUTE_REINITIALIZES void clear() {\n    set_.clear();\n    list_.clear();\n  }\n\n  void reserve(size_t n) { set_.reserve(n); }\n  size_t capacity() const { return set_.capacity(); }\n  size_t bucket_count() const { return set_.bucket_count(); }\n  float load_factor() const { return set_.load_factor(); }\n\n  hasher hash_function() const { return set_.hash_function().fn_; }\n  key_equal key_eq() const { return set_.key_eq().fn_; }\n  allocator_type get_allocator() const { return list_.get_allocator(); }\n\n  template <class K = key_type>\n  size_type erase(const key_arg<K>& key) {\n    auto found = set_.find(key);\n    if (found == set_.end()) return 0;\n    auto list_it = *found;\n    // Erase set entry first since it refers to the list element.\n    set_.erase(found);\n    list_.erase(list_it);\n    return 1;\n  }\n\n  iterator erase(const_iterator position) {\n    auto found = set_.find(position);\n    assert(*found == position);\n    set_.erase(found);\n    return list_.erase(position);\n  }\n\n  iterator erase(iterator position) {\n    return erase(static_cast<const_iterator>(position));\n  }\n\n  iterator erase(iterator first, iterator last) {\n    while (first != last) first = erase(first);\n    return first;\n  }\n\n  iterator erase(const_iterator first, const_iterator last) {\n    while (first != last) first = erase(first);\n    if (first == end()) return end();\n    return *set_.find(first);\n  }\n\n  template <class K = key_type>\n  iterator find(const key_arg<K>& key) {\n    auto found = set_.find(key);\n    if (found == set_.end()) return end();\n    return *found;\n  }\n\n  template <class K = key_type>\n  const_iterator find(const key_arg<K>& key) const {\n    auto found = set_.find(key);\n    if (found == set_.end()) return end();\n    return *found;\n  }\n\n  template <class K = key_type>\n  size_type count(const key_arg<K>& key) const {\n    return contains(key) ? 1 : 0;\n  }\n  template <class K = key_type>\n  bool contains(const key_arg<K>& key) const {\n    return set_.contains(key);\n  }\n\n  template <class K = key_type>\n  mapped_type& at(const key_arg<K>& key) {\n    auto it = find(key);\n    if (ABSL_PREDICT_FALSE(it == end())) {\n      ThrowStdOutOfRange(\"absl::linked_hash_map::at\");\n    }\n    return it->second;\n  }\n\n  template <class K = key_type>\n  const mapped_type& at(const key_arg<K>& key) const {\n    return const_cast<linked_hash_map*>(this)->at(key);\n  }\n\n  template <class K = key_type>\n  std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {\n    auto iter = set_.find(key);\n    if (iter == set_.end()) return {end(), end()};\n    return {*iter, std::next(*iter)};\n  }\n\n  template <class K = key_type>\n  std::pair<const_iterator, const_iterator> equal_range(\n      const key_arg<K>& key) const {\n    auto iter = set_.find(key);\n    if (iter == set_.end()) return {end(), end()};\n    return {*iter, std::next(*iter)};\n  }\n\n  template <class K = key_type>\n  mapped_type& operator[](const key_arg<K>& key) {\n    return LazyEmplaceInternal(key).first->second;\n  }\n\n  template <class K = key_type, K* = nullptr>\n  mapped_type& operator[](key_arg<K>&& key) {\n    return LazyEmplaceInternal(std::forward<key_arg<K>>(key)).first->second;\n  }\n\n  std::pair<iterator, bool> insert(const value_type& v) {\n    return InsertInternal(v);\n  }\n  std::pair<iterator, bool> insert(value_type&& v) {\n    return InsertInternal(std::move(v));\n  }\n\n  iterator insert(const_iterator, const value_type& v) {\n    return insert(v).first;\n  }\n  iterator insert(const_iterator, value_type&& v) {\n    return insert(std::move(v)).first;\n  }\n\n  void insert(std::initializer_list<value_type> ilist) {\n    insert(ilist.begin(), ilist.end());\n  }\n\n  template <class InputIt>\n  void insert(InputIt first, InputIt last) {\n    for (; first != last; ++first) insert(*first);\n  }\n\n  insert_return_type insert(node_type&& node) {\n    if (node.empty()) return {end(), false, node_type()};\n    if (auto [set_itr, inserted] = set_.emplace(node.list_.begin()); inserted) {\n      list_.splice(list_.end(), node.list_);\n      return {*set_itr, true, node_type()};\n    } else {\n      return {*set_itr, false, std::move(node)};\n    }\n  }\n\n  iterator insert(const_iterator, node_type&& node) {\n    return insert(std::move(node)).first;\n  }\n\n  // The last two template parameters ensure that both arguments are rvalues\n  // (lvalue arguments are handled by the overloads below). This is necessary\n  // for supporting bitfield arguments.\n  //\n  //   union { int n : 1; };\n  //   linked_hash_map<int, int> m;\n  //   m.insert_or_assign(n, n);\n  template <class K = key_type, class V = mapped_type, K* = nullptr,\n            V* = nullptr>\n  std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, V&& v) {\n    return InsertOrAssignInternal(std::forward<key_arg<K>>(k),\n                                  std::forward<V>(v));\n  }\n\n  template <class K = key_type, class V = mapped_type, K* = nullptr>\n  std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, const V& v) {\n    return InsertOrAssignInternal(std::forward<key_arg<K>>(k), v);\n  }\n\n  template <class K = key_type, class V = mapped_type, V* = nullptr>\n  std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, V&& v) {\n    return InsertOrAssignInternal(k, std::forward<V>(v));\n  }\n\n  template <class K = key_type, class V = mapped_type>\n  std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, const V& v) {\n    return InsertOrAssignInternal(k, v);\n  }\n\n  template <class K = key_type, class V = mapped_type, K* = nullptr,\n            V* = nullptr>\n  iterator insert_or_assign(const_iterator, key_arg<K>&& k, V&& v) {\n    return insert_or_assign(std::forward<key_arg<K>>(k), std::forward<V>(v))\n        .first;\n  }\n\n  template <class K = key_type, class V = mapped_type, K* = nullptr>\n  iterator insert_or_assign(const_iterator, key_arg<K>&& k, const V& v) {\n    return insert_or_assign(std::forward<key_arg<K>>(k), v).first;\n  }\n\n  template <class K = key_type, class V = mapped_type, V* = nullptr>\n  iterator insert_or_assign(const_iterator, const key_arg<K>& k, V&& v) {\n    return insert_or_assign(k, std::forward<V>(v)).first;\n  }\n\n  template <class K = key_type, class V = mapped_type>\n  iterator insert_or_assign(const_iterator, const key_arg<K>& k, const V& v) {\n    return insert_or_assign(k, v).first;\n  }\n\n  template <typename... Args>\n  std::pair<iterator, bool> emplace(Args&&... args) {\n    ListType node_donor;\n    auto list_iter =\n        node_donor.emplace(node_donor.end(), std::forward<Args>(args)...);\n    auto ins = set_.insert(list_iter);\n    if (!ins.second) return {*ins.first, false};\n    list_.splice(list_.end(), node_donor, list_iter);\n    return {list_iter, true};\n  }\n\n  template <class K = key_type, class... Args, K* = nullptr>\n  iterator try_emplace(const_iterator, key_arg<K>&& k, Args&&... args) {\n    return try_emplace(std::forward<key_arg<K>>(k), std::forward<Args>(args)...)\n        .first;\n  }\n\n  template <typename... Args>\n  iterator emplace_hint(const_iterator, Args&&... args) {\n    return emplace(std::forward<Args>(args)...).first;\n  }\n\n  template <class K = key_type, typename... Args, K* = nullptr>\n  std::pair<iterator, bool> try_emplace(key_arg<K>&& key, Args&&... args) {\n    return LazyEmplaceInternal(std::forward<key_arg<K>>(key),\n                               std::forward<Args>(args)...);\n  }\n\n  template <typename H, typename E>\n  void merge(linked_hash_map<Key, Value, H, E, Alloc>& src) {\n    auto itr = src.list_.begin();\n    while (itr != src.list_.end()) {\n      if (contains(itr->first)) {\n        ++itr;\n      } else {\n        insert(src.extract(itr++));\n      }\n    }\n  }\n\n  template <typename H, typename E>\n  void merge(linked_hash_map<Key, Value, H, E, Alloc>&& src) {\n    merge(src);\n  }\n\n  node_type extract(const_iterator position) {\n    set_.erase(position->first);\n    ListType extracted_node_list;\n    extracted_node_list.splice(extracted_node_list.end(), list_, position);\n    return node_type(std::move(extracted_node_list));\n  }\n\n  template <class K = key_type,\n            std::enable_if_t<!std::is_same_v<K, iterator>, int> = 0>\n  node_type extract(const key_arg<K>& key) {\n    auto node = set_.extract(key);\n    if (node.empty()) return node_type();\n    ListType extracted_node_list;\n    extracted_node_list.splice(extracted_node_list.end(), list_, node.value());\n    return node_type(std::move(extracted_node_list));\n  }\n\n  template <typename H, typename E>\n  void splice(const_iterator, linked_hash_map<Key, Value, H, E, Alloc>& list,\n              const_iterator it) {\n    if (&list == this) {\n      list_.splice(list_.end(), list.list_, it);\n    } else {\n      insert(list.extract(it));\n    }\n  }\n\n  template <class K = key_type, typename... Args>\n  std::pair<iterator, bool> try_emplace(const key_arg<K>& key, Args&&... args) {\n    return LazyEmplaceInternal(key, std::forward<Args>(args)...);\n  }\n\n  template <class K = key_type, typename... Args>\n  iterator try_emplace(const_iterator, const key_arg<K>& key, Args&&... args) {\n    return LazyEmplaceInternal(key, std::forward<Args>(args)...).first;\n  }\n\n  void swap(linked_hash_map& other) noexcept {\n    using std::swap;\n    swap(set_, other.set_);\n    swap(list_, other.list_);\n  }\n\n  friend bool operator==(const linked_hash_map& a, const linked_hash_map& b) {\n    if (a.size() != b.size()) return false;\n    const linked_hash_map* outer = &a;\n    const linked_hash_map* inner = &b;\n    if (outer->capacity() > inner->capacity()) std::swap(outer, inner);\n    for (const value_type& elem : *outer) {\n      auto it = inner->find(elem.first);\n      if (it == inner->end()) return false;\n      if (it->second != elem.second) return false;\n    }\n\n    return true;\n  }\n\n  friend bool operator!=(const linked_hash_map& a, const linked_hash_map& b) {\n    return !(a == b);\n  }\n\n  void rehash(size_t n) { set_.rehash(n); }\n\n private:\n  template <typename Other>\n  void CopyFrom(Other&& other) {\n    for (auto& elem : other.list_) {\n      set_.insert(list_.insert(list_.end(), std::move(elem)));\n    }\n    assert(set_.size() == list_.size());\n  }\n\n  template <typename U>\n  std::pair<iterator, bool> InsertInternal(U&& pair) {  // NOLINT(build/c++11)\n    bool constructed = false;\n    auto set_iter = set_.lazy_emplace(pair.first, [&](const auto& ctor) {\n      constructed = true;\n      ctor(list_.emplace(list_.end(), std::forward<U>(pair)));\n    });\n    return {*set_iter, constructed};\n  }\n\n  template <class K, class V>\n  std::pair<iterator, bool> InsertOrAssignInternal(K&& k, V&& v) {\n    auto [it, inserted] =\n        LazyEmplaceInternal(std::forward<K>(k), std::forward<V>(v));\n    if (!inserted) {\n      // NOLINTNEXTLINE(bugprone-use-after-move)\n      it->second = std::forward<V>(v);\n    }\n    return {it, inserted};\n  }\n\n  template <typename K, typename... Args>\n  std::pair<iterator, bool> LazyEmplaceInternal(K&& key, Args&&... args) {\n    bool constructed = false;\n    auto set_iter = set_.lazy_emplace(\n        key, [this, &constructed, &key, &args...](const auto& ctor) {\n          auto list_iter =\n              list_.emplace(list_.end(), std::piecewise_construct,\n                            std::forward_as_tuple(std::forward<K>(key)),\n                            std::forward_as_tuple(std::forward<Args>(args)...));\n          constructed = true;\n          ctor(list_iter);\n        });\n    return {*set_iter, constructed};\n  }\n\n  // The set component, used for speedy lookups.\n  SetType set_;\n\n  // The list component, used for maintaining insertion order.\n  ListType list_;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_LINKED_HASH_MAP_H_\n"
  },
  {
    "path": "absl/container/linked_hash_map_benchmark.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <cstddef>\n#include <string>\n#include <vector>\n\n#include \"absl/container/linked_hash_map.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nstruct BenchmarkData {\n  std::vector<std::string> sample;\n  size_t str_bytes = 0;\n  explicit BenchmarkData(int size,\n                         absl::FunctionRef<std::string(int)> factory) {\n    sample.reserve(size);\n    for (int i = 0; i < size; ++i) {\n      sample.push_back(factory(i));\n      str_bytes += sample.back().size();\n    }\n  }\n};\n\nvoid BenchmarkTryEmplaceStrings(benchmark::State& state,\n                                absl::FunctionRef<std::string(int)> factory) {\n  BenchmarkData data(state.range(0), factory);\n\n  // Make a batch around 1Mi bytes.\n  const size_t batch_size =\n      std::max(size_t{1}, size_t{1000000} / data.str_bytes);\n  std::vector<absl::linked_hash_map<std::string, int>> sets(batch_size);\n\n  while (state.KeepRunningBatch(batch_size)) {\n    state.PauseTiming();\n    for (auto& set : sets) set.clear();\n    state.ResumeTiming();\n    for (auto& set : sets) {\n      for (const auto& str : data.sample) {\n        benchmark::DoNotOptimize(set.try_emplace(str));\n      }\n    }\n  }\n\n  state.SetItemsProcessed(state.iterations() * state.range(0));\n  state.SetBytesProcessed(state.iterations() * data.str_bytes);\n}\n\nvoid BenchmarkInsertOrAssignStrings(\n    benchmark::State& state, absl::FunctionRef<std::string(int)> factory) {\n  BenchmarkData data(state.range(0), factory);\n\n  // Make a batch around 1Mi bytes.\n  const size_t batch_size = std::max(size_t{1}, 1000000 / data.str_bytes);\n  std::vector<absl::linked_hash_map<std::string, int>> sets(batch_size);\n\n  while (state.KeepRunningBatch(batch_size)) {\n    state.PauseTiming();\n    for (auto& set : sets) set.clear();\n    state.ResumeTiming();\n    for (auto& set : sets) {\n      for (const auto& str : data.sample) {\n        benchmark::DoNotOptimize(set.insert_or_assign(str, 0));\n      }\n    }\n  }\n\n  state.SetItemsProcessed(state.iterations() * state.range(0));\n  state.SetBytesProcessed(state.iterations() * data.str_bytes);\n}\n\nconstexpr absl::string_view kFormatShort = \"%10d\";\nconstexpr absl::string_view kFormatLong =\n    \"a longer string that exceeds the SSO %10d\";\n\nvoid BM_TryEmplaceShortStrings_Hit(benchmark::State& state) {\n  BenchmarkTryEmplaceStrings(\n      state, [](int i) { return absl::StrFormat(kFormatShort, i); });\n}\nBENCHMARK(BM_TryEmplaceShortStrings_Hit)->Range(1, 1 << 16);\n\nvoid BM_TryEmplaceLongStrings_Hit(benchmark::State& state) {\n  BenchmarkTryEmplaceStrings(\n      state, [](int i) { return absl::StrFormat(kFormatLong, i); });\n}\nBENCHMARK(BM_TryEmplaceLongStrings_Hit)->Range(1, 1 << 16);\n\nvoid BM_TryEmplaceShortStrings_Miss(benchmark::State& state) {\n  BenchmarkTryEmplaceStrings(\n      state, [](int i) { return absl::StrFormat(kFormatShort, i % 20); });\n}\nBENCHMARK(BM_TryEmplaceShortStrings_Miss)->Range(1, 1 << 16);\n\nvoid BM_TryEmplaceLongStrings_Miss(benchmark::State& state) {\n  BenchmarkTryEmplaceStrings(\n      state, [](int i) { return absl::StrFormat(kFormatLong, i % 20); });\n}\nBENCHMARK(BM_TryEmplaceLongStrings_Miss)->Range(1, 1 << 16);\n\nvoid BM_InsertOrAssignShortStrings_Hit(benchmark::State& state) {\n  BenchmarkInsertOrAssignStrings(\n      state, [](int i) { return absl::StrFormat(kFormatShort, i); });\n}\nBENCHMARK(BM_InsertOrAssignShortStrings_Hit)->Range(1, 1 << 16);\n\nvoid BM_InsertOrAssignLongStrings_Hit(benchmark::State& state) {\n  BenchmarkInsertOrAssignStrings(\n      state, [](int i) { return absl::StrFormat(kFormatLong, i); });\n}\nBENCHMARK(BM_InsertOrAssignLongStrings_Hit)->Range(1, 1 << 16);\n\nvoid BM_InsertOrAssignShortStrings_Miss(benchmark::State& state) {\n  BenchmarkInsertOrAssignStrings(\n      state, [](int i) { return absl::StrFormat(kFormatShort, i % 20); });\n}\nBENCHMARK(BM_InsertOrAssignShortStrings_Miss)->Range(1, 1 << 16);\n\nvoid BM_InsertOrAssignLongStrings_Miss(benchmark::State& state) {\n  BenchmarkInsertOrAssignStrings(\n      state, [](int i) { return absl::StrFormat(kFormatLong, i % 20); });\n}\nBENCHMARK(BM_InsertOrAssignLongStrings_Miss)->Range(1, 1 << 16);\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/linked_hash_map_test.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/linked_hash_map.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <memory>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/exception_testing.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/container/internal/heterogeneous_lookup_testing.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/container/internal/unordered_map_constructor_test.h\"\n#include \"absl/container/internal/unordered_map_lookup_test.h\"\n#include \"absl/container/internal/unordered_map_members_test.h\"\n#include \"absl/container/internal/unordered_map_modifiers_test.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::Pair;\nusing ::testing::Pointee;\n\ntemplate <class K, class V>\nusing Map = linked_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual,\n                            Alloc<std::pair<const K, V>>>;\n\nstatic_assert(!std::is_standard_layout<NonStandardLayout>(), \"\");\n\nusing MapTypes =\n    ::testing::Types<Map<int, int>, Map<std::string, int>,\n                     Map<Enum, std::string>, Map<EnumClass, int>,\n                     Map<int, NonStandardLayout>, Map<NonStandardLayout, int>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashMap, ConstructorTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashMap, LookupTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashMap, MembersTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashMap, ModifiersTest, MapTypes);\n\n// Tests that the range constructor works.\nTEST(LinkedHashMapTest, RangeConstruct) {\n  const std::pair<int, int> items[] = {{1, 2}, {2, 3}, {3, 4}};\n  EXPECT_THAT((linked_hash_map<int, int>(std::begin(items), std::end(items))),\n              ElementsAre(Pair(1, 2), Pair(2, 3), Pair(3, 4)));\n}\n\n// Tests that copying works.\nTEST(LinkedHashMapTest, Copy) {\n  linked_hash_map<int, int> m{{2, 12}, {3, 13}};\n  auto copy = m;\n\n  EXPECT_TRUE(copy.contains(2));\n  auto found = copy.find(2);\n  ASSERT_TRUE(found != copy.end());\n  for (auto iter = copy.begin(); iter != copy.end(); ++iter) {\n    if (iter == found) return;\n  }\n  FAIL() << \"Copied map's find method returned an invalid iterator.\";\n}\n\n// Tests that assignment works.\nTEST(LinkedHashMapTest, Assign) {\n  linked_hash_map<int, int> m{{2, 12}, {3, 13}};\n  linked_hash_map<int, int> n{{4, 14}};\n\n  n = m;\n  EXPECT_TRUE(n.contains(2));\n  auto found = n.find(2);\n  ASSERT_TRUE(found != n.end());\n  for (auto iter = n.begin(); iter != n.end(); ++iter) {\n    if (iter == found) return;\n  }\n  FAIL() << \"Assigned map's find method returned an invalid iterator.\";\n}\n\n// Tests that self-assignment works.\nTEST(LinkedHashMapTest, SelfAssign) {\n  linked_hash_map<int, int> a{{1, 1}, {2, 2}, {3, 3}};\n  auto& a_ref = a;\n  a = a_ref;\n  EXPECT_THAT(a, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));\n}\n\n// Tests that move constructor works.\nTEST(LinkedHashMapTest, Move) {\n  // Use unique_ptr as an example of a non-copyable type.\n  linked_hash_map<int, std::unique_ptr<int>> m;\n  m[2] = std::make_unique<int>(12);\n  m[3] = std::make_unique<int>(13);\n  linked_hash_map<int, std::unique_ptr<int>> n = std::move(m);\n  EXPECT_THAT(n, ElementsAre(Pair(2, Pointee(12)), Pair(3, Pointee(13))));\n}\n\n// Tests that self-moving works.\nTEST(LinkedHashMapTest, SelfMove) {\n  linked_hash_map<int, int> a{{1, 1}, {2, 2}, {3, 3}};\n  auto& a_ref = a;\n  a = std::move(a_ref);\n  EXPECT_THAT(a, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));\n}\n\nTEST(LinkedHashMapTest, CanInsertMoveOnly) {\n  linked_hash_map<int, std::unique_ptr<int>> m;\n  struct Data {\n    int k, v;\n  };\n  const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};\n  for (const auto& kv : data)\n    m.insert({kv.k, std::make_unique<int>(int{kv.v})});\n  EXPECT_TRUE(m.contains(2));\n  auto found = m.find(2);\n  ASSERT_TRUE(found != m.end());\n  EXPECT_EQ(234, *found->second);\n}\n\nTEST(LinkedHashMapTest, CanEmplaceMoveOnly) {\n  linked_hash_map<int, std::unique_ptr<int>> m;\n  struct Data {\n    int k, v;\n  };\n  const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};\n  for (const auto& kv : data) {\n    m.emplace(std::piecewise_construct, std::make_tuple(kv.k),\n              std::make_tuple(new int{kv.v}));\n  }\n  EXPECT_TRUE(m.contains(2));\n  auto found = m.find(2);\n  ASSERT_TRUE(found != m.end());\n  EXPECT_EQ(234, *found->second);\n}\n\nstruct NoCopy {\n  explicit NoCopy(int x) : x(x) {}\n  NoCopy(const NoCopy&) = delete;\n  NoCopy& operator=(const NoCopy&) = delete;\n  NoCopy(NoCopy&&) = delete;\n  NoCopy& operator=(NoCopy&&) = delete;\n  int x;\n};\n\nTEST(LinkedHashMapTest, CanEmplaceNoMoveNoCopy) {\n  linked_hash_map<int, NoCopy> m;\n  struct Data {\n    int k, v;\n  };\n  const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};\n  for (const auto& kv : data) {\n    m.emplace(std::piecewise_construct, std::make_tuple(kv.k),\n              std::make_tuple(kv.v));\n  }\n  EXPECT_TRUE(m.contains(2));\n  auto found = m.find(2);\n  ASSERT_TRUE(found != m.end());\n  EXPECT_EQ(234, found->second.x);\n}\n\nTEST(LinkedHashMapTest, ConstKeys) {\n  linked_hash_map<int, int> m;\n  m.insert(std::make_pair(1, 2));\n  // Test that keys are const in iteration.\n  std::pair<const int, int>& p = *m.begin();\n  EXPECT_EQ(1, p.first);\n}\n\n// Tests that iteration from begin() to end() works\nTEST(LinkedHashMapTest, Iteration) {\n  linked_hash_map<int, int> m;\n  EXPECT_TRUE(m.begin() == m.end());\n\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(3, 13));\n\n  linked_hash_map<int, int>::iterator i = m.begin();\n  ASSERT_TRUE(m.begin() == i);\n  ASSERT_TRUE(m.end() != i);\n  EXPECT_EQ(2, i->first);\n  EXPECT_EQ(12, i->second);\n\n  ++i;\n  ASSERT_TRUE(m.end() != i);\n  EXPECT_EQ(1, i->first);\n  EXPECT_EQ(11, i->second);\n\n  ++i;\n  ASSERT_TRUE(m.end() != i);\n  EXPECT_EQ(3, i->first);\n  EXPECT_EQ(13, i->second);\n\n  ++i;  // Should be the end of the line.\n  ASSERT_TRUE(m.end() == i);\n}\n\n// Tests that reverse iteration from rbegin() to rend() works\nTEST(LinkedHashMapTest, ReverseIteration) {\n  linked_hash_map<int, int> m;\n  EXPECT_TRUE(m.rbegin() == m.rend());\n\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(3, 13));\n\n  linked_hash_map<int, int>::reverse_iterator i = m.rbegin();\n  ASSERT_TRUE(m.rbegin() == i);\n  ASSERT_TRUE(m.rend() != i);\n  EXPECT_EQ(3, i->first);\n  EXPECT_EQ(13, i->second);\n\n  ++i;\n  ASSERT_TRUE(m.rend() != i);\n  EXPECT_EQ(1, i->first);\n  EXPECT_EQ(11, i->second);\n\n  ++i;\n  ASSERT_TRUE(m.rend() != i);\n  EXPECT_EQ(2, i->first);\n  EXPECT_EQ(12, i->second);\n\n  ++i;  // Should be the end of the line.\n  ASSERT_TRUE(m.rend() == i);\n}\n\n// Tests that clear() works\nTEST(LinkedHashMapTest, Clear) {\n  linked_hash_map<int, int> m;\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(3, 13));\n\n  ASSERT_EQ(3, m.size());\n\n  m.clear();\n\n  EXPECT_EQ(0, m.size());\n\n  m.clear();  // Make sure we can call it on an empty map.\n\n  EXPECT_EQ(0, m.size());\n}\n\n// Tests that size() works.\nTEST(LinkedHashMapTest, Size) {\n  linked_hash_map<int, int> m;\n  EXPECT_EQ(0, m.size());\n  m.insert(std::make_pair(2, 12));\n  EXPECT_EQ(1, m.size());\n  m.insert(std::make_pair(1, 11));\n  EXPECT_EQ(2, m.size());\n  m.insert(std::make_pair(3, 13));\n  EXPECT_EQ(3, m.size());\n  m.clear();\n  EXPECT_EQ(0, m.size());\n}\n\n// Tests empty()\nTEST(LinkedHashMapTest, Empty) {\n  linked_hash_map<int, int> m;\n  ASSERT_TRUE(m.empty());\n  m.insert(std::make_pair(2, 12));\n  ASSERT_FALSE(m.empty());\n  m.clear();\n  ASSERT_TRUE(m.empty());\n}\n\nTEST(LinkedHashMapTest, Erase) {\n  linked_hash_map<int, int> m;\n  ASSERT_EQ(0, m.size());\n  EXPECT_EQ(0, m.erase(2));  // Nothing to erase yet\n\n  m.insert(std::make_pair(2, 12));\n  ASSERT_EQ(1, m.size());\n  EXPECT_EQ(1, m.erase(2));\n  EXPECT_EQ(0, m.size());\n\n  EXPECT_EQ(0, m.erase(2));  // Make sure nothing bad happens if we repeat.\n  EXPECT_EQ(0, m.size());\n}\n\nTEST(LinkedHashMapTest, Erase2) {\n  linked_hash_map<int, int> m;\n  ASSERT_EQ(0, m.size());\n  EXPECT_EQ(0, m.erase(2));  // Nothing to erase yet\n\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(3, 13));\n  m.insert(std::make_pair(4, 14));\n  ASSERT_EQ(4, m.size());\n\n  // Erase middle two\n  EXPECT_EQ(1, m.erase(1));\n  EXPECT_EQ(1, m.erase(3));\n\n  EXPECT_EQ(2, m.size());\n\n  // Make sure we can still iterate over everything that's left.\n  linked_hash_map<int, int>::iterator it = m.begin();\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(12, it->second);\n  ++it;\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(14, it->second);\n  ++it;\n  ASSERT_TRUE(it == m.end());\n\n  EXPECT_EQ(0, m.erase(1));  // Make sure nothing bad happens if we repeat.\n  ASSERT_EQ(2, m.size());\n\n  EXPECT_EQ(1, m.erase(2));\n  EXPECT_EQ(1, m.erase(4));\n  ASSERT_EQ(0, m.size());\n\n  EXPECT_EQ(0, m.erase(1));  // Make sure nothing bad happens if we repeat.\n  ASSERT_EQ(0, m.size());\n}\n\n// Test that erase(iter,iter) and erase(iter) compile and work.\nTEST(LinkedHashMapTest, Erase3) {\n  linked_hash_map<int, int> m;\n\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(3, 13));\n  m.insert(std::make_pair(4, 14));\n\n  // Erase middle two\n  linked_hash_map<int, int>::iterator it2 = m.find(2);\n  linked_hash_map<int, int>::iterator it4 = m.find(4);\n  EXPECT_EQ(m.erase(it2, it4), m.find(4));\n  EXPECT_EQ(2, m.size());\n\n  // Make sure we can still iterate over everything that's left.\n  linked_hash_map<int, int>::iterator it = m.begin();\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(11, it->second);\n  ++it;\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(14, it->second);\n  ++it;\n  ASSERT_TRUE(it == m.end());\n\n  // Erase first one using an iterator.\n  EXPECT_EQ(m.erase(m.begin()), m.find(4));\n\n  // Only the last element should be left.\n  it = m.begin();\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(14, it->second);\n  ++it;\n  ASSERT_TRUE(it == m.end());\n}\n\n// Test all types of insertion\nTEST(LinkedHashMapTest, Insertion) {\n  linked_hash_map<int, int> m;\n  ASSERT_EQ(0, m.size());\n  std::pair<linked_hash_map<int, int>::iterator, bool> result;\n\n  result = m.insert(std::make_pair(2, 12));\n  ASSERT_EQ(1, m.size());\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(2, result.first->first);\n  EXPECT_EQ(12, result.first->second);\n\n  result = m.insert(std::make_pair(1, 11));\n  ASSERT_EQ(2, m.size());\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(1, result.first->first);\n  EXPECT_EQ(11, result.first->second);\n\n  result = m.insert(std::make_pair(3, 13));\n  linked_hash_map<int, int>::iterator result_iterator = result.first;\n  ASSERT_EQ(3, m.size());\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(3, result.first->first);\n  EXPECT_EQ(13, result.first->second);\n\n  result = m.insert(std::make_pair(3, 13));\n  EXPECT_EQ(3, m.size());\n  EXPECT_FALSE(result.second) << \"No insertion should have occurred.\";\n  EXPECT_TRUE(result_iterator == result.first)\n      << \"Duplicate insertion should have given us the original iterator.\";\n\n  std::vector<std::pair<int, int>> v = {{3, 13}, {4, 14}, {5, 15}};\n  m.insert(v.begin(), v.end());\n  // Expect 4 and 5 inserted, 3 not inserted.\n  EXPECT_EQ(5, m.size());\n  EXPECT_EQ(14, m.at(4));\n  EXPECT_EQ(15, m.at(5));\n}\n\nstatic std::pair<const int, int> Pair(int i, int j) { return {i, j}; }\n\n// Test front accessors.\nTEST(LinkedHashMapTest, Front) {\n  linked_hash_map<int, int> m;\n\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(3, 13));\n\n  EXPECT_EQ(3, m.size());\n  EXPECT_EQ(Pair(2, 12), m.front());\n  m.pop_front();\n  EXPECT_EQ(2, m.size());\n  EXPECT_EQ(Pair(1, 11), m.front());\n  m.pop_front();\n  EXPECT_EQ(1, m.size());\n  EXPECT_EQ(Pair(3, 13), m.front());\n  m.pop_front();\n  EXPECT_TRUE(m.empty());\n}\n\n// Test back accessors.\nTEST(LinkedHashMapTest, Back) {\n  linked_hash_map<int, int> m;\n\n  m.insert(std::make_pair(2, 12));\n  m.insert(std::make_pair(1, 11));\n  m.insert(std::make_pair(3, 13));\n\n  EXPECT_EQ(3, m.size());\n  EXPECT_EQ(Pair(3, 13), m.back());\n  m.pop_back();\n  EXPECT_EQ(2, m.size());\n  EXPECT_EQ(Pair(1, 11), m.back());\n  m.pop_back();\n  EXPECT_EQ(1, m.size());\n  EXPECT_EQ(Pair(2, 12), m.back());\n  m.pop_back();\n  EXPECT_TRUE(m.empty());\n}\n\nTEST(LinkedHashMapTest, Find) {\n  linked_hash_map<int, int> m;\n\n  EXPECT_TRUE(m.end() == m.find(1))\n      << \"We shouldn't find anything in an empty map.\";\n\n  m.insert(std::make_pair(2, 12));\n  EXPECT_TRUE(m.end() == m.find(1))\n      << \"We shouldn't find an element that doesn't exist in the map.\";\n\n  std::pair<linked_hash_map<int, int>::iterator, bool> result =\n      m.insert(std::make_pair(1, 11));\n  ASSERT_TRUE(result.second);\n  ASSERT_TRUE(m.end() != result.first);\n  EXPECT_TRUE(result.first == m.find(1))\n      << \"We should have found an element we know exists in the map.\";\n  EXPECT_EQ(11, result.first->second);\n\n  // Check that a follow-up insertion doesn't affect our original\n  m.insert(std::make_pair(3, 13));\n  linked_hash_map<int, int>::iterator it = m.find(1);\n  ASSERT_TRUE(m.end() != it);\n  EXPECT_EQ(11, it->second);\n\n  m.clear();\n  EXPECT_TRUE(m.end() == m.find(1))\n      << \"We shouldn't find anything in a map that we've cleared.\";\n}\n\nTEST(LinkedHashMapTest, Contains) {\n  linked_hash_map<int, int> m;\n\n  EXPECT_FALSE(m.contains(1)) << \"An empty map shouldn't contain anything.\";\n\n  m.insert(std::make_pair(2, 12));\n  EXPECT_FALSE(m.contains(1))\n      << \"The map shouldn't contain an element that doesn't exist.\";\n\n  m.insert(std::make_pair(1, 11));\n  EXPECT_TRUE(m.contains(1))\n      << \"The map should contain an element that we know exists.\";\n\n  m.clear();\n  EXPECT_FALSE(m.contains(1))\n      << \"A map that we've cleared shouldn't contain anything.\";\n}\n\nTEST(LinkedHashMapTest, At) {\n  linked_hash_map<int, int> m = {{1, 2}};\n  EXPECT_EQ(2, m.at(1));\n  ABSL_BASE_INTERNAL_EXPECT_FAIL(m.at(3), std::out_of_range,\n                                 \"linked_hash_map::at\");\n\n  const linked_hash_map<int, int> cm = {{1, 2}};\n  EXPECT_EQ(2, cm.at(1));\n  ABSL_BASE_INTERNAL_EXPECT_FAIL(cm.at(3), std::out_of_range,\n                                 \"linked_hash_map::at\");\n}\n\nTEST(LinkedHashMapTest, Swap) {\n  linked_hash_map<int, int> m1;\n  linked_hash_map<int, int> m2;\n  m1.insert(std::make_pair(1, 1));\n  m1.insert(std::make_pair(2, 2));\n  m2.insert(std::make_pair(3, 3));\n  ASSERT_EQ(2, m1.size());\n  ASSERT_EQ(1, m2.size());\n  m1.swap(m2);\n  ASSERT_EQ(1, m1.size());\n  ASSERT_EQ(2, m2.size());\n}\n\nTEST(LinkedHashMapTest, SelfSwap) {\n  linked_hash_map<int, int> a{{1, 1}, {2, 2}, {3, 3}};\n  using std::swap;\n  swap(a, a);\n  EXPECT_THAT(a, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));\n}\n\nTEST(LinkedHashMapTest, InitializerList) {\n  linked_hash_map<int, int> m{{1, 2}, {3, 4}};\n  ASSERT_EQ(2, m.size());\n  EXPECT_TRUE(m.contains(1));\n  linked_hash_map<int, int>::iterator it = m.find(1);\n  ASSERT_TRUE(m.end() != it);\n  EXPECT_EQ(2, it->second);\n  EXPECT_TRUE(m.contains(3));\n  it = m.find(3);\n  ASSERT_TRUE(m.end() != it);\n  EXPECT_EQ(4, it->second);\n}\n\nTEST(LinkedHashMapTest, CustomHashAndEquality) {\n  struct CustomIntHash {\n    size_t operator()(int x) const { return x; }\n  };\n  struct CustomIntEq {\n    bool operator()(int x, int y) const { return x == y; }\n  };\n  linked_hash_map<int, int, CustomIntHash, CustomIntEq> m;\n  m.insert(std::make_pair(1, 1));\n  EXPECT_TRUE(m.contains(1));\n  EXPECT_EQ(1, m[1]);\n}\n\nTEST(LinkedHashMapTest, EqualRange) {\n  linked_hash_map<int, int> m{{3, 11}, {1, 13}};\n  const auto& const_m = m;\n\n  EXPECT_THAT(m.equal_range(2), testing::Pair(m.end(), m.end()));\n  EXPECT_THAT(const_m.equal_range(2),\n              testing::Pair(const_m.end(), const_m.end()));\n\n  EXPECT_THAT(m.equal_range(1), testing::Pair(m.find(1), ++m.find(1)));\n  EXPECT_THAT(const_m.equal_range(1),\n              testing::Pair(const_m.find(1), ++const_m.find(1)));\n}\n\nTEST(LinkedHashMapTest, ReserveWorks) {\n  linked_hash_map<int, int> m;\n  EXPECT_EQ(0, m.size());\n  EXPECT_EQ(0.0, m.load_factor());\n  m.reserve(10);\n  EXPECT_LE(10, m.capacity());\n  EXPECT_EQ(0, m.size());\n  EXPECT_EQ(0.0, m.load_factor());\n  m.emplace(1, 1);\n  m.emplace(2, 2);\n  EXPECT_LE(10, m.capacity());\n  EXPECT_EQ(2, m.size());\n  EXPECT_LT(0.0, m.load_factor());\n}\n\n// We require key types to have hash and equals.\nclass CopyableMovableType\n    : public absl::test_internal::CopyableMovableInstance {\n public:\n  using CopyableMovableInstance::CopyableMovableInstance;\n\n  bool operator==(const CopyableMovableType& o) const {\n    return value() == o.value();\n  }\n\n  template <typename H>\n  friend H AbslHashValue(H h, const CopyableMovableType& c) {\n    return H::combine(std::move(h), c.value());\n  }\n};\n\nTEST(LinkedHashMapTest, RValueOperatorAt) {\n  absl::test_internal::InstanceTracker tracker;\n\n  linked_hash_map<CopyableMovableType, int> map;\n  map[CopyableMovableType(1)] = 1;\n  EXPECT_EQ(tracker.copies(), 0);\n  CopyableMovableType c(2);\n  map[std::move(c)] = 2;\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_THAT(map, ElementsAre(Pair(CopyableMovableType(1), 1),\n                               Pair(CopyableMovableType(2), 2)));\n}\n\nTEST(LinkedHashMapTest, HeterogeneousTests) {\n  absl::test_internal::InstanceTracker tracker;\n\n  using MapType = linked_hash_map<ExpensiveType, int, HeterogeneousHash,\n                                  HeterogeneousEqual>;\n  MapType map;\n  ExpensiveType one(1);\n  map[one] = 1;\n  // Two instances: 'one' var and an instance in the map.\n  EXPECT_EQ(2, tracker.instances());\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  map[one] = 5;\n  // No construction since key==1 exists.\n  EXPECT_EQ(2, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  map[CheapType(1)] = 10;\n  // No construction since key==1 exists.\n  EXPECT_EQ(2, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  map[CheapType(2)] = 20;\n  // Construction since key==2 doesn't exist in the map.\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(map, ElementsAre(Pair(HasExpensiveValue(1), 10),\n                               Pair(HasExpensiveValue(2), 20)));\n\n  // find\n  auto itr = map.find(CheapType(1));\n  tracker.ResetCopiesMovesSwaps();\n  ASSERT_NE(itr, map.end());\n  EXPECT_EQ(10, itr->second);\n  // contains\n  EXPECT_TRUE(map.contains(CheapType(2)));\n  // count\n  EXPECT_EQ(1, map.count(CheapType(2)));\n  // equal_range\n  auto eq_itr_pair = map.equal_range(CheapType(2));\n  ASSERT_NE(eq_itr_pair.first, map.end());\n  EXPECT_EQ(20, eq_itr_pair.first->second);\n  // No construction for find, contains, count or equal_range.\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  // insert\n  auto three = MapType::value_type(CheapType(3), 30);\n  tracker.ResetCopiesMovesSwaps();\n  map.insert(three);\n  // Two instances: 'three' var and an instance in the map.\n  EXPECT_EQ(5, tracker.instances());\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  map.insert(three);\n  // No additional construction since key==3 exists.\n  EXPECT_EQ(5, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(map, ElementsAre(Pair(HasExpensiveValue(1), 10),\n                               Pair(HasExpensiveValue(2), 20),\n                               Pair(HasExpensiveValue(3), 30)));\n\n  // Test std::move() using operator[] and insert().\n  ExpensiveType four(4);\n  tracker.ResetCopiesMovesSwaps();\n  map[std::move(four)] = 40;\n  // Two constructions (regular and move).\n  EXPECT_EQ(7, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(1, tracker.moves());\n\n  auto five = MapType::value_type(CheapType(5), 50);\n  tracker.ResetCopiesMovesSwaps();\n  map.insert(std::move(five));\n  // Two constructions (regular and move).\n  EXPECT_EQ(9, tracker.instances());\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(map, ElementsAre(Pair(HasExpensiveValue(1), 10),\n                               Pair(HasExpensiveValue(2), 20),\n                               Pair(HasExpensiveValue(3), 30),\n                               Pair(HasExpensiveValue(4), 40),\n                               Pair(HasExpensiveValue(5), 50)));\n\n  // Insert using std::pair.\n  tracker.ResetCopiesMovesSwaps();\n  map.insert(std::make_pair(ExpensiveType(6), 60));\n  EXPECT_EQ(10, tracker.instances());\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(2, tracker.moves());\n\n  // Heterogeneous erase.\n  map.erase(CheapType(1));\n  // No construction and instance reduced by one.\n  tracker.ResetCopiesMovesSwaps();\n  EXPECT_EQ(9, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(map, ElementsAre(Pair(HasExpensiveValue(2), 20),\n                               Pair(HasExpensiveValue(3), 30),\n                               Pair(HasExpensiveValue(4), 40),\n                               Pair(HasExpensiveValue(5), 50),\n                               Pair(HasExpensiveValue(6), 60)));\n}\n\nTEST(LinkedHashMapTest, HeterogeneousStringViewLookup) {\n  linked_hash_map<std::string, int> map;\n  map[\"foo\"] = 1;\n  map[\"bar\"] = 2;\n  map[\"blah\"] = 3;\n\n  {\n    absl::string_view lookup(\"foo\");\n    auto itr = map.find(lookup);\n    ASSERT_NE(itr, map.end());\n    EXPECT_EQ(1, itr->second);\n  }\n\n  // Not found.\n  {\n    absl::string_view lookup(\"foobar\");\n    EXPECT_EQ(map.end(), map.find(lookup));\n  }\n\n  {\n    absl::string_view lookup(\"blah\");\n    auto itr = map.find(lookup);\n    ASSERT_NE(itr, map.end());\n    EXPECT_EQ(3, itr->second);\n  }\n}\n\nTEST(LinkedHashMapTest, UniversalReferenceWorks) {\n  linked_hash_map<std::string, int> map;\n  std::string s = \"very very very very very long string\";\n  map[s] = 1;\n  EXPECT_EQ(s, \"very very very very very long string\");\n}\n\nTEST(LinkedHashMap, ExtractInsert) {\n  linked_hash_map<int, int> m = {{1, 7}, {2, 9}};\n  auto node = m.extract(1);\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.key(), 1);\n  EXPECT_EQ(node.mapped(), 7);\n  EXPECT_THAT(m, ElementsAre(Pair(2, 9)));\n  EXPECT_FALSE(m.contains(1));\n  EXPECT_TRUE(m.contains(2));\n\n  node.mapped() = 17;\n  m.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_THAT(m, ElementsAre(Pair(2, 9), Pair(1, 17)));\n  EXPECT_TRUE(m.contains(2));\n  EXPECT_TRUE(m.contains(1));\n\n  node = m.extract(m.find(1));\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.key(), 1);\n  EXPECT_EQ(node.mapped(), 17);\n  EXPECT_THAT(m, ElementsAre(Pair(2, 9)));\n}\n\nTEST(LinkedHashMap, Merge) {\n  linked_hash_map<int, int> m = {{1, 7}, {3, 6}};\n  linked_hash_map<int, int> src = {{1, 10}, {2, 9}, {4, 16}};\n\n  m.merge(src);\n\n  EXPECT_THAT(m, ElementsAre(Pair(1, 7), Pair(3, 6), Pair(2, 9), Pair(4, 16)));\n  EXPECT_THAT(src, ElementsAre(Pair(1, 10)));\n  for (int i : {2, 9, 4}) {\n    EXPECT_FALSE(src.contains(i));\n  }\n}\n\nTEST(LinkedHashMap, Splice) {\n  linked_hash_map<int, int> m = {{1, 7}, {3, 6}};\n  linked_hash_map<int, int> src = {{1, 10}, {2, 9}, {4, 16}};\n  m.splice(m.end(), m, m.begin());\n\n  EXPECT_THAT(m, ElementsAre(Pair(3, 6), Pair(1, 7)));\n\n  m.splice(m.end(), src, ++src.begin());\n  EXPECT_THAT(m, ElementsAre(Pair(3, 6), Pair(1, 7), Pair(2, 9)));\n  EXPECT_THAT(src, ElementsAre(Pair(1, 10), Pair(4, 16)));\n}\n\nTEST(LinkedHashMap, EraseRange) {\n  linked_hash_map<int, int> map = {{1, 1},  {2, 4},  {3, 9},  {4, 16}, {5, 25},\n                                   {6, 36}, {7, 49}, {8, 64}, {9, 81}};\n  auto start = map.find(3);\n  auto end = map.find(8);\n  auto itr = map.erase(start, end);\n  ASSERT_NE(itr, map.end());\n  EXPECT_THAT(*itr, Pair(8, 64));\n  EXPECT_THAT(map,\n              ElementsAre(Pair(1, 1), Pair(2, 4), Pair(8, 64), Pair(9, 81)));\n  for (int i : {1, 2, 8, 9}) {\n    EXPECT_TRUE(map.contains(i));\n  }\n  for (int i : {3, 4, 5, 6, 7}) {\n    EXPECT_FALSE(map.contains(i));\n  }\n}\n\nTEST(LinkedHashMap, InsertInitializerList) {\n  linked_hash_map<int, int> m;\n  m.insert({{1, 7}, {2, 9}, {3, 29}});\n  EXPECT_THAT(m, ElementsAre(Pair(1, 7), Pair(2, 9), Pair(3, 29)));\n}\n\nTEST(LinkedHashMap, InsertOrAssign) {\n  linked_hash_map<int, int> m;\n  {\n    auto [itr, elem_inserted] = m.insert_or_assign(10, 20);\n    EXPECT_THAT(*itr, Pair(10, 20));\n    EXPECT_EQ(elem_inserted, true);\n  }\n  {\n    auto [itr, elem_inserted] = m.insert_or_assign(10, 30);\n    EXPECT_THAT(*itr, Pair(10, 30));\n    EXPECT_EQ(elem_inserted, false);\n  }\n}\n\nTEST(LinkedHashMap, TryEmplace) {\n  linked_hash_map<int, std::pair<int, std::string>> m;\n  {\n    auto [itr, elem_inserted] = m.try_emplace(10, 20, \"string\");\n    EXPECT_THAT(*itr, Pair(10, Pair(20, \"string\")));\n    EXPECT_EQ(elem_inserted, true);\n  }\n  {\n    absl::test_internal::InstanceTracker tracker;\n    std::string s = \"some string\";\n    auto [itr, elem_inserted] = m.try_emplace(10, 2, std::move(s));\n    EXPECT_THAT(*itr, Pair(10, Pair(20, \"string\")));\n    EXPECT_EQ(elem_inserted, false);\n    EXPECT_THAT(tracker.moves(), 0);\n  }\n}\n\nTEST(LinkedHashMapTest, TryEmplace) {\n  linked_hash_map<int, std::tuple<int, std::string, std::unique_ptr<float>>>\n      map;\n  auto result = map.try_emplace(3, 2, \"foo\", new float(1.0));\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(std::get<0>(result.first->second), 2);\n  EXPECT_EQ(std::get<1>(result.first->second), \"foo\");\n  EXPECT_EQ(*std::get<2>(result.first->second), 1.0);\n\n  // Ptr should not be moved.\n  auto ptr = std::make_unique<float>(3.0);\n  auto result2 = map.try_emplace(3, 22, \"foo-bar\", std::move(ptr));\n  EXPECT_FALSE(result2.second);\n  EXPECT_EQ(std::get<0>(result.first->second), 2);\n  EXPECT_EQ(std::get<1>(result.first->second), \"foo\");\n  EXPECT_EQ(*std::get<2>(result.first->second), 1.0);\n  EXPECT_NE(ptr.get(), nullptr);\n}\n\nstruct CountedHash {\n  explicit CountedHash(int* count) : count(count) {}\n  size_t operator()(int value) const {\n    ++(*count);\n    return value;\n  }\n  int* count = nullptr;\n};\n\n// Makes a map too big for small object optimization.  Counts the number of\n// hashes in `count`, but leaves `count` set to 0.\nlinked_hash_map<int, std::string, CountedHash> MakeNonSmallMap(int* count) {\n  const int kFirstKey = -1000;\n  linked_hash_map<int, std::string, CountedHash> m(0, CountedHash(count));\n  for (int i = kFirstKey; i < kFirstKey + 100; ++i) {\n    m[i] = \"foo\";\n  }\n  *count = 0;\n  return m;\n}\n\nconstexpr bool BuildHasDebugModeRehashes() {\n#if !defined(NDEBUG) || defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)\n  return true;\n#else\n  return false;\n#endif\n}\n\nTEST(LinkedHashMapTest, HashCountInOptBuilds) {\n  if (BuildHasDebugModeRehashes()) {\n    GTEST_SKIP() << \"Only run under NDEBUG: `assert` statements and sanitizer \"\n                    \"rehashing may cause redundant hashing.\";\n  }\n\n  using Map = linked_hash_map<int, std::string, CountedHash>;\n  {\n    int count = 0;\n    Map m = MakeNonSmallMap(&count);\n    m.insert({1, \"foo\"});\n    EXPECT_EQ(count, 1);\n    m.erase(1);\n    EXPECT_EQ(count, 2);\n  }\n  {\n    int count = 0;\n    Map m = MakeNonSmallMap(&count);\n    m[2] = \"bar\";\n    EXPECT_EQ(count, 1);\n  }\n  {\n    int count = 0;\n    Map m = MakeNonSmallMap(&count);\n    m.insert({3, \"baz\"});\n    EXPECT_EQ(count, 1);\n    auto node = m.extract(3);\n    EXPECT_EQ(count, 2);\n    m.insert(std::move(node));\n    EXPECT_EQ(count, 3);\n  }\n  {\n    int count = 0;\n    Map m = MakeNonSmallMap(&count);\n    m.insert_or_assign(4, \"qux\");\n    EXPECT_EQ(count, 1);\n  }\n  {\n    int count = 0;\n    Map m = MakeNonSmallMap(&count);\n    m.emplace(5, \"vog\");\n    EXPECT_EQ(count, 1);\n  }\n  {\n    int count = 0;\n    Map m = MakeNonSmallMap(&count);\n    m.try_emplace(6, 'x', 42);\n    EXPECT_EQ(count, 1);\n  }\n  {\n    int src_count = 0, dst_count = 0;\n    Map src = MakeNonSmallMap(&src_count);\n    Map dst = MakeNonSmallMap(&dst_count);\n    src[7] = \"siete\";\n    dst.merge(src);\n    EXPECT_LE(src_count, 200);\n    EXPECT_LE(dst_count, 200);\n  }\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/linked_hash_set.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: linked_hash_set.h\n// -----------------------------------------------------------------------------\n//\n// This is a simple insertion-ordered set. It provides O(1) amortized\n// insertions and lookups, as well as iteration over the set in the insertion\n// order.\n//\n// This class is thread-compatible.\n//\n// Iterators point into the list and should be stable in the face of\n// mutations, except for an iterator pointing to an element that was just\n// deleted.\n//\n// This class supports heterogeneous lookups.\n\n#ifndef ABSL_CONTAINER_LINKED_HASH_SET_H_\n#define ABSL_CONTAINER_LINKED_HASH_SET_H_\n\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <list>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/container/internal/common.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <\n    typename Key, typename KeyHash = typename absl::flat_hash_set<Key>::hasher,\n    typename KeyEq = typename absl::flat_hash_set<Key, KeyHash>::key_equal,\n    typename Alloc = std::allocator<Key>>\nclass linked_hash_set {\n  using KeyArgImpl = absl::container_internal::KeyArg<\n      absl::container_internal::IsTransparent<KeyEq>::value &&\n      absl::container_internal::IsTransparent<KeyHash>::value>;\n\n public:\n  using key_type = Key;\n  using hasher = KeyHash;\n  using key_equal = KeyEq;\n  using value_type = key_type;\n  using allocator_type = Alloc;\n  using difference_type = ptrdiff_t;\n\n private:\n  template <class K>\n  using key_arg = typename KeyArgImpl::template type<K, key_type>;\n\n  using ListType = std::list<key_type, Alloc>;\n\n  template <class Fn>\n  class Wrapped {\n    template <typename K>\n    static const K& ToKey(const K& k) {\n      return k;\n    }\n    static const key_type& ToKey(typename ListType::const_iterator it) {\n      return *it;\n    }\n    static const key_type& ToKey(typename ListType::iterator it) { return *it; }\n\n    Fn fn_;\n\n    friend linked_hash_set;\n\n   public:\n    using is_transparent = void;\n\n    Wrapped() = default;\n    explicit Wrapped(Fn fn) : fn_(std::move(fn)) {}\n\n    template <class... Args>\n    auto operator()(Args&&... args) const\n        -> decltype(this->fn_(ToKey(args)...)) {\n      return fn_(ToKey(args)...);\n    }\n  };\n  using SetType =\n      absl::flat_hash_set<typename ListType::iterator, Wrapped<hasher>,\n                          Wrapped<key_equal>, Alloc>;\n\n  class NodeHandle {\n   public:\n    using allocator_type = linked_hash_set::allocator_type;\n    using value_type = linked_hash_set::value_type;\n\n    constexpr NodeHandle() noexcept = default;\n    NodeHandle(NodeHandle&& nh) noexcept = default;\n    ~NodeHandle() = default;\n    NodeHandle& operator=(NodeHandle&& node) noexcept = default;\n    bool empty() const noexcept { return list_.empty(); }\n    explicit operator bool() const noexcept { return !empty(); }\n    allocator_type get_allocator() const { return list_.get_allocator(); }\n    value_type& value() { return list_.front(); }\n    void swap(NodeHandle& nh) noexcept { list_.swap(nh.list_); }\n\n   private:\n    friend linked_hash_set;\n\n    explicit NodeHandle(ListType list) : list_(std::move(list)) {}\n    ListType list_;\n  };\n\n  template <class Iterator, class NodeType>\n  struct InsertReturnType {\n    Iterator position;\n    bool inserted;\n    NodeType node;\n  };\n\n public:\n  using iterator = typename ListType::const_iterator;\n  using const_iterator = typename ListType::const_iterator;\n  using reverse_iterator = typename ListType::const_reverse_iterator;\n  using const_reverse_iterator = typename ListType::const_reverse_iterator;\n  using reference = typename ListType::reference;\n  using const_reference = typename ListType::const_reference;\n  using pointer = typename std::allocator_traits<allocator_type>::pointer;\n  using const_pointer =\n      typename std::allocator_traits<allocator_type>::const_pointer;\n  using size_type = typename ListType::size_type;\n  using node_type = NodeHandle;\n  using insert_return_type = InsertReturnType<iterator, node_type>;\n\n  linked_hash_set() {}\n\n  explicit linked_hash_set(size_t bucket_count, const hasher& hash = hasher(),\n                           const key_equal& eq = key_equal(),\n                           const allocator_type& alloc = allocator_type())\n      : set_(bucket_count, Wrapped<hasher>(hash), Wrapped<key_equal>(eq),\n             alloc),\n        list_(alloc) {}\n\n  linked_hash_set(size_t bucket_count, const hasher& hash,\n                  const allocator_type& alloc)\n      : linked_hash_set(bucket_count, hash, key_equal(), alloc) {}\n\n  linked_hash_set(size_t bucket_count, const allocator_type& alloc)\n      : linked_hash_set(bucket_count, hasher(), key_equal(), alloc) {}\n\n  explicit linked_hash_set(const allocator_type& alloc)\n      : linked_hash_set(0, hasher(), key_equal(), alloc) {}\n\n  template <class InputIt>\n  linked_hash_set(InputIt first, InputIt last, size_t bucket_count = 0,\n                  const hasher& hash = hasher(),\n                  const key_equal& eq = key_equal(),\n                  const allocator_type& alloc = allocator_type())\n      : linked_hash_set(bucket_count, hash, eq, alloc) {\n    insert(first, last);\n  }\n\n  template <class InputIter>\n  linked_hash_set(InputIter first, InputIter last, size_t bucket_count,\n                  const hasher& hash, const allocator_type& alloc)\n      : linked_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {}\n\n  template <class InputIter>\n  linked_hash_set(InputIter first, InputIter last, size_t bucket_count,\n                  const allocator_type& alloc)\n      : linked_hash_set(first, last, bucket_count, hasher(), key_equal(),\n                        alloc) {}\n\n  template <class InputIt>\n  linked_hash_set(InputIt first, InputIt last, const allocator_type& alloc)\n      : linked_hash_set(first, last, /*bucket_count=*/0, hasher(), key_equal(),\n                        alloc) {}\n\n  linked_hash_set(std::initializer_list<key_type> init, size_t bucket_count = 0,\n                  const hasher& hash = hasher(),\n                  const key_equal& eq = key_equal(),\n                  const allocator_type& alloc = allocator_type())\n      : linked_hash_set(init.begin(), init.end(), bucket_count, hash, eq,\n                        alloc) {}\n\n  linked_hash_set(std::initializer_list<key_type> init, size_t bucket_count,\n                  const allocator_type& alloc)\n      : linked_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}\n\n  linked_hash_set(std::initializer_list<key_type> init, size_t bucket_count,\n                  const hasher& hash, const allocator_type& alloc)\n      : linked_hash_set(init, bucket_count, hash, key_equal(), alloc) {}\n\n  linked_hash_set(std::initializer_list<key_type> init,\n                  const allocator_type& alloc)\n      : linked_hash_set(init, /*bucket_count=*/0, hasher(), key_equal(),\n                        alloc) {}\n\n  linked_hash_set(const linked_hash_set& other)\n      : linked_hash_set(other.bucket_count(), other.hash_function(),\n                        other.key_eq(), other.get_allocator()) {\n    CopyFrom(other);\n  }\n\n  linked_hash_set(const linked_hash_set& other, const allocator_type& alloc)\n      : linked_hash_set(other.bucket_count(), other.hash_function(),\n                        other.key_eq(), alloc) {\n    CopyFrom(other);\n  }\n\n  linked_hash_set(linked_hash_set&& other) noexcept\n      : set_(std::move(other.set_)), list_(std::move(other.list_)) {\n    // Since the list and set must agree for other to end up \"valid\",\n    // explicitly clear them.\n    other.set_.clear();\n    other.list_.clear();\n  }\n\n  linked_hash_set(linked_hash_set&& other, const allocator_type& alloc)\n      : linked_hash_set(0, other.hash_function(), other.key_eq(), alloc) {\n    if (get_allocator() == other.get_allocator()) {\n      *this = std::move(other);\n    } else {\n      CopyFrom(std::move(other));\n    }\n  }\n\n  linked_hash_set& operator=(const linked_hash_set& other) {\n    if (this != &other) {\n      // Make a new set, with other's hash/eq/alloc.\n      set_ = SetType(other.bucket_count(), other.set_.hash_function(),\n                     other.set_.key_eq(), other.get_allocator());\n      // Copy the list, with other's allocator.\n      list_ = ListType(other.get_allocator());\n      CopyFrom(other);\n    }\n    return *this;\n  }\n\n  linked_hash_set& operator=(linked_hash_set&& other) noexcept {\n    if (this != &other) {\n      set_ = std::move(other.set_);\n      list_ = std::move(other.list_);\n      other.set_.clear();\n      other.list_.clear();\n    }\n    return *this;\n  }\n\n  linked_hash_set& operator=(std::initializer_list<key_type> values) {\n    clear();\n    insert(values.begin(), values.end());\n    return *this;\n  }\n\n  // Derive size from set_, as list::size might be O(N).\n  size_type size() const { return set_.size(); }\n  size_type max_size() const noexcept { return ~size_type{}; }\n  bool empty() const { return set_.empty(); }\n\n  // Iteration is list-like, in insertion order.\n  // These are all forwarded.\n  iterator begin() { return list_.begin(); }\n  iterator end() { return list_.end(); }\n  const_iterator begin() const { return list_.begin(); }\n  const_iterator end() const { return list_.end(); }\n  const_iterator cbegin() const { return list_.cbegin(); }\n  const_iterator cend() const { return list_.cend(); }\n  reverse_iterator rbegin() { return list_.rbegin(); }\n  reverse_iterator rend() { return list_.rend(); }\n  const_reverse_iterator rbegin() const { return list_.rbegin(); }\n  const_reverse_iterator rend() const { return list_.rend(); }\n  const_reverse_iterator crbegin() const { return list_.crbegin(); }\n  const_reverse_iterator crend() const { return list_.crend(); }\n  reference front() { return list_.front(); }\n  reference back() { return list_.back(); }\n  const_reference front() const { return list_.front(); }\n  const_reference back() const { return list_.back(); }\n\n  void pop_front() { erase(begin()); }\n  void pop_back() { erase(std::prev(end())); }\n\n  ABSL_ATTRIBUTE_REINITIALIZES void clear() {\n    set_.clear();\n    list_.clear();\n  }\n\n  void reserve(size_t n) { set_.reserve(n); }\n  size_t bucket_count() const { return set_.bucket_count(); }\n  size_t capacity() const { return set_.capacity(); }\n  float load_factor() const { return set_.load_factor(); }\n\n  hasher hash_function() const { return set_.hash_function().fn_; }\n  key_equal key_eq() const { return set_.key_eq().fn_; }\n  allocator_type get_allocator() const { return list_.get_allocator(); }\n\n  template <typename K = key_type>\n  size_type erase(const key_arg<K>& key) {\n    auto found = set_.find(key);\n    if (found == set_.end()) return 0;\n    auto list_it = *found;\n    // Erase set entry first since it refers to the list element.\n    set_.erase(found);\n    list_.erase(list_it);\n    return 1;\n  }\n\n  iterator erase(const_iterator position) {\n    auto found = set_.find(position);\n    assert(*found == position);\n    set_.erase(found);\n    return list_.erase(position);\n  }\n\n  iterator erase(const_iterator first, const_iterator last) {\n    while (first != last) first = erase(first);\n    return first;\n  }\n\n  template <typename K = key_type>\n  iterator find(const key_arg<K>& key) {\n    auto found = set_.find(key);\n    if (found == set_.end()) return end();\n    return *found;\n  }\n\n  template <typename K = key_type>\n  const_iterator find(const key_arg<K>& key) const {\n    auto found = set_.find(key);\n    if (found == set_.end()) return end();\n    return *found;\n  }\n\n  template <typename K = key_type>\n  size_t count(const key_arg<K>& key) const {\n    return contains(key) ? 1 : 0;\n  }\n  template <typename K = key_type>\n  bool contains(const key_arg<K>& key) const {\n    return set_.contains(key);\n  }\n\n  template <typename K = key_type>\n  std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {\n    auto iter = set_.find(key);\n    if (iter == set_.end()) return {end(), end()};\n    return {*iter, std::next(*iter)};\n  }\n\n  template <typename K = key_type>\n  std::pair<const_iterator, const_iterator> equal_range(\n      const key_arg<K>& key) const {\n    auto iter = set_.find(key);\n    if (iter == set_.end()) return {end(), end()};\n    return {*iter, std::next(*iter)};\n  }\n\n  template <typename K = key_type>\n  std::pair<iterator, bool> insert(const key_arg<K>& k) {\n    return InsertInternal(list_.end(), k);\n  }\n  template <typename K = key_type, K* = nullptr>\n  std::pair<iterator, bool> insert(key_arg<K>&& k) {\n    return InsertInternal(list_.end(), std::move(k));\n  }\n\n  template <typename K = key_type,\n            std::enable_if_t<\n                !std::is_convertible_v<const key_arg<K>&, const_iterator> &&\n                    !std::is_convertible_v<const key_arg<K>&, iterator>,\n                int> = 0>\n  iterator insert(const_iterator hint, const key_arg<K>& k) {\n    return InsertInternal(hint, k).first;\n  }\n  template <\n      typename K = key_type, K* = nullptr,\n      std::enable_if_t<!std::is_convertible_v<key_arg<K>&&, const_iterator> &&\n                           !std::is_convertible_v<key_arg<K>&&, iterator>,\n                       int> = 0>\n  iterator insert(const_iterator hint, key_arg<K>&& k) {\n    return InsertInternal(hint, std::move(k)).first;\n  }\n\n  void insert(std::initializer_list<key_type> ilist) {\n    insert(ilist.begin(), ilist.end());\n  }\n\n  template <class InputIt>\n  void insert(InputIt first, InputIt last) {\n    for (; first != last; ++first) insert(*first);\n  }\n\n  insert_return_type insert(node_type&& node) {\n    if (node.empty()) return {end(), false, node_type()};\n    if (auto [set_itr, inserted] = set_.emplace(node.list_.begin()); inserted) {\n      list_.splice(list_.end(), node.list_);\n      return {*set_itr, true, node_type()};\n    } else {\n      return {*set_itr, false, std::move(node)};\n    }\n  }\n\n  iterator insert(const_iterator, node_type&& node) {\n    return insert(std::move(node)).first;\n  }\n\n  template <typename... Args>\n  std::pair<iterator, bool> emplace(Args&&... args) {\n    return EmplaceInternal(list_.end(), std::forward<Args>(args)...);\n  }\n\n  template <typename... Args>\n  iterator emplace_hint(const_iterator hint, Args&&... args) {\n    return EmplaceInternal(hint, std::forward<Args>(args)...).first;\n  }\n\n  template <typename H, typename E>\n  void merge(linked_hash_set<Key, H, E, Alloc>& src) {\n    auto itr = src.list_.begin();\n    while (itr != src.list_.end()) {\n      if (contains(*itr)) {\n        ++itr;\n      } else {\n        insert(src.extract(itr++));\n      }\n    }\n  }\n\n  template <typename H, typename E>\n  void merge(linked_hash_set<Key, H, E, Alloc>&& src) {\n    merge(src);\n  }\n\n  node_type extract(const_iterator position) {\n    set_.erase(position);\n    ListType extracted_node_list;\n    extracted_node_list.splice(extracted_node_list.end(), list_, position);\n    return node_type(std::move(extracted_node_list));\n  }\n\n  template <class K = key_type, typename std::enable_if_t<\n                                    !std::is_same<K, iterator>::value, int> = 0>\n  node_type extract(const key_arg<K>& key) {\n    auto node = set_.extract(key);\n    if (node.empty()) return node_type();\n    ListType extracted_node_list;\n    extracted_node_list.splice(extracted_node_list.end(), list_, node.value());\n    return node_type(std::move(extracted_node_list));\n  }\n\n  void swap(linked_hash_set& other) noexcept {\n    using std::swap;\n    swap(set_, other.set_);\n    swap(list_, other.list_);\n  }\n\n  friend bool operator==(const linked_hash_set& a, const linked_hash_set& b) {\n    if (a.size() != b.size()) return false;\n    const linked_hash_set* outer = &a;\n    const linked_hash_set* inner = &b;\n    if (outer->capacity() > inner->capacity()) std::swap(outer, inner);\n    for (const value_type& elem : *outer)\n      if (!inner->contains(elem)) return false;\n    return true;\n  }\n\n  friend bool operator!=(const linked_hash_set& a, const linked_hash_set& b) {\n    return !(a == b);\n  }\n\n  void rehash(size_t n) { set_.rehash(n); }\n\n private:\n  template <typename Other>\n  void CopyFrom(Other&& other) {\n    for (auto& elem : other.list_) {\n      set_.insert(list_.insert(list_.end(), std::move(elem)));\n    }\n    assert(set_.size() == list_.size());\n  }\n\n  template <typename... Args>\n  std::pair<iterator, bool> EmplaceInternal(const_iterator hint,\n                                            Args&&... args) {\n    ListType node_donor;\n    auto list_iter =\n        node_donor.emplace(node_donor.end(), std::forward<Args>(args)...);\n    auto ins = set_.insert(list_iter);\n    if (!ins.second) return {*ins.first, false};\n    list_.splice(hint, node_donor, list_iter);\n    return {list_iter, true};\n  }\n\n  template <typename U>\n  std::pair<iterator, bool> InsertInternal(const_iterator hint,\n                                           U&& key) {  // NOLINT(build/c++11)\n    bool constructed = false;\n    auto set_iter = set_.lazy_emplace(key, [&](const auto& ctor) {\n      constructed = true;\n      ctor(list_.emplace(hint, std::forward<U>(key)));\n    });\n    return {*set_iter, constructed};\n  }\n\n  // The set component, used for speedy lookups.\n  SetType set_;\n\n  // The list component, used for maintaining insertion order.\n  ListType list_;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_LINKED_HASH_SET_H_\n"
  },
  {
    "path": "absl/container/linked_hash_set_benchmark.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <cstddef>\n#include <string>\n#include <vector>\n\n#include \"absl/container/linked_hash_set.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BenchmarkInsertStrings(benchmark::State& state,\n                            absl::FunctionRef<std::string(int)> factory) {\n  std::vector<std::string> sample;\n  size_t str_bytes = 0;\n  for (int i = 0; i < state.range(0); ++i) {\n    sample.push_back(factory(i));\n    str_bytes += sample.back().size();\n  }\n\n  // Make a batch around 1Mi bytes.\n  const size_t batch_size = std::max(size_t{1}, size_t{1000000} / str_bytes);\n  std::vector<absl::linked_hash_set<std::string>> sets(batch_size);\n\n  while (state.KeepRunningBatch(batch_size)) {\n    state.PauseTiming();\n    for (auto& set : sets) set.clear();\n    state.ResumeTiming();\n    for (auto& set : sets) {\n      for (const auto& str : sample) {\n        benchmark::DoNotOptimize(set.insert(str));\n      }\n    }\n  }\n\n  state.SetItemsProcessed(state.iterations() * state.range(0));\n  state.SetBytesProcessed(state.iterations() * str_bytes);\n}\n\nconstexpr absl::string_view kFormatShort = \"%10d\";\nconstexpr absl::string_view kFormatLong =\n    \"a longer string that exceeds the SSO %10d\";\n\nvoid BM_InsertShortStrings_Hit(benchmark::State& state) {\n  BenchmarkInsertStrings(\n      state, [](int i) { return absl::StrFormat(kFormatShort, i); });\n}\nBENCHMARK(BM_InsertShortStrings_Hit)->Range(1, 1 << 16);\n\nvoid BM_InsertLongStrings_Hit(benchmark::State& state) {\n  BenchmarkInsertStrings(state,\n                         [](int i) { return absl::StrFormat(kFormatLong, i); });\n}\nBENCHMARK(BM_InsertLongStrings_Hit)->Range(1, 1 << 16);\n\nvoid BM_InsertShortStrings_Miss(benchmark::State& state) {\n  BenchmarkInsertStrings(\n      state, [](int i) { return absl::StrFormat(kFormatShort, i % 20); });\n}\nBENCHMARK(BM_InsertShortStrings_Miss)->Range(1, 1 << 16);\n\nvoid BM_InsertLongStrings_Miss(benchmark::State& state) {\n  BenchmarkInsertStrings(\n      state, [](int i) { return absl::StrFormat(kFormatLong, i % 20); });\n}\nBENCHMARK(BM_InsertLongStrings_Miss)->Range(1, 1 << 16);\n\n}  // namespace\n"
  },
  {
    "path": "absl/container/linked_hash_set_test.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/linked_hash_set.h\"\n\n#include <algorithm>\n#include <cmath>\n#include <cstddef>\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/container/internal/heterogeneous_lookup_testing.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/container/internal/unordered_set_constructor_test.h\"\n#include \"absl/container/internal/unordered_set_lookup_test.h\"\n#include \"absl/container/internal/unordered_set_members_test.h\"\n#include \"absl/container/internal/unordered_set_modifiers_test.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::ElementsAreArray;\nusing ::testing::Pointee;\n\ntemplate <class T>\nusing Set =\n    linked_hash_set<T, StatefulTestingHash, StatefulTestingEqual, Alloc<T>>;\n\nusing SetTypes =\n    ::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashSet, ConstructorTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashSet, LookupTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashSet, MembersTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(LinkedHashSet, ModifiersTest, SetTypes);\n\n// Tests that the range constructor works.\nTEST(LinkedHashSetTest, RangeConstruct) {\n  const auto items = {1, 2, 3};\n  EXPECT_THAT(linked_hash_set<int>(items.begin(), items.end()),\n              ElementsAre(1, 2, 3));\n}\n\n// Tests that copying works.\nTEST(LinkedHashSetTest, Copy) {\n  linked_hash_set<int> m{4, 8, 15, 16, 23, 42};\n  auto copy = m;\n\n  auto found = copy.find(8);\n  ASSERT_TRUE(found != copy.end());\n  for (auto iter = copy.begin(); iter != copy.end(); ++iter) {\n    if (iter == found) return;\n  }\n  FAIL() << \"Copied set's find method returned an invalid iterator.\";\n}\n\n// Tests that assignment works.\nTEST(LinkedHashSetTest, Assign) {\n  linked_hash_set<int> m{2, 3};\n  linked_hash_set<int> n{4};\n\n  n = m;\n  EXPECT_TRUE(n.contains(2));\n  auto found = n.find(2);\n  ASSERT_TRUE(found != n.end());\n  for (auto iter = n.begin(); iter != n.end(); ++iter) {\n    if (iter == found) return;\n  }\n  FAIL() << \"Assigned set's find method returned an invalid iterator.\";\n}\n\n// Tests that self-assignment works.\nTEST(LinkedHashSetTest, SelfAssign) {\n  linked_hash_set<int> a{1, 2, 3};\n  auto& a_ref = a;\n  a = a_ref;\n\n  EXPECT_TRUE(a.contains(2));\n  auto found = a.find(2);\n  ASSERT_TRUE(found != a.end());\n  for (auto iter = a.begin(); iter != a.end(); ++iter) {\n    if (iter == found) return;\n  }\n  FAIL() << \"Assigned set's find method returned an invalid iterator.\";\n}\n\n// Tests that move constructor works.\nTEST(LinkedHashSetTest, Move) {\n  // Use unique_ptr as an example of a non-copyable type.\n  linked_hash_set<std::unique_ptr<int>> m;\n  m.insert(std::make_unique<int>(2));\n  m.insert(std::make_unique<int>(3));\n  linked_hash_set<std::unique_ptr<int>> n = std::move(m);\n  EXPECT_THAT(n, ElementsAre(Pointee(2), Pointee(3)));\n}\n\n// Tests that self-moving works.\nTEST(LinkedHashSetTest, SelfMove) {\n  linked_hash_set<int> a{1, 2, 3};\n  auto& a_ref = a;\n  a = std::move(a_ref);\n  EXPECT_THAT(a, ElementsAre(1, 2, 3));\n}\n\nstruct IntUniquePtrHash {\n  size_t operator()(const std::unique_ptr<int>& p) const {\n    return static_cast<size_t>(*p);\n  }\n};\n\nstruct IntUniquePtrEq {\n  size_t operator()(const std::unique_ptr<int>& a,\n                    const std::unique_ptr<int>& b) const {\n    return *a == *b;\n  }\n};\n\n// Pretty artificial for a set, but unique_ptr is a convenient move-only type.\nTEST(LinkedHashSetTest, CanInsertMoveOnly) {\n  linked_hash_set<std::unique_ptr<int>, IntUniquePtrHash, IntUniquePtrEq> s;\n  std::vector<int> data = {4, 8, 15, 16, 23, 42};\n  for (int x : data) s.insert(std::make_unique<int>(x));\n  EXPECT_EQ(s.size(), data.size());\n  for (const std::unique_ptr<int>& elt : s) {\n    EXPECT_TRUE(s.contains(elt));\n    EXPECT_TRUE(s.find(elt) != s.end());\n  }\n}\n\nTEST(LinkedHashSetTest, CanMoveMoveOnly) {\n  linked_hash_set<std::unique_ptr<int>, IntUniquePtrHash, IntUniquePtrEq> s;\n  std::vector<int> data = {4, 8, 15, 16, 23, 42};\n  for (int x : data) s.insert(std::make_unique<int>(x));\n  linked_hash_set<std::unique_ptr<int>, IntUniquePtrHash, IntUniquePtrEq> ss =\n      std::move(s);\n  EXPECT_EQ(ss.size(), data.size());\n}\n\nTEST(LinkedHashSetTest, CanEmplaceMoveOnly) {\n  linked_hash_set<std::unique_ptr<int>, IntUniquePtrHash, IntUniquePtrEq> s;\n  std::vector<int> data = {4, 8, 15, 16, 23, 42};\n  for (const int x : data) {\n    s.emplace(new int{x});\n  }\n  EXPECT_EQ(s.size(), data.size());\n  for (const std::unique_ptr<int>& elt : s) {\n    EXPECT_TRUE(s.contains(elt));\n    EXPECT_TRUE(s.find(elt) != s.end());\n  }\n}\n\nTEST(LinkedHashSetTest, CanInsertTransparent) {\n  linked_hash_set<std::string> s;\n  s.insert(absl::string_view(\"foo\"));\n  s.insert(absl::string_view(\"bar\"));\n  s.insert(absl::string_view(\"foo\"));\n  EXPECT_THAT(s, ElementsAre(\"foo\", \"bar\"));\n}\n\n// Tests that iteration from begin() to end() works\nTEST(LinkedHashSetTest, Iteration) {\n  linked_hash_set<int> m;\n  EXPECT_TRUE(m.begin() == m.end());\n\n  m.insert(2);\n  m.insert(1);\n  m.insert(3);\n\n  linked_hash_set<int>::iterator i = m.begin();\n  ASSERT_TRUE(m.begin() == i);\n  ASSERT_TRUE(m.end() != i);\n  EXPECT_EQ(2, *i);\n\n  ++i;\n  ASSERT_TRUE(m.end() != i);\n  EXPECT_EQ(1, *i);\n\n  ++i;\n  ASSERT_TRUE(m.end() != i);\n  EXPECT_EQ(3, *i);\n\n  ++i;\n  ASSERT_TRUE(m.end() == i);\n}\n\n// Tests that reverse iteration from rbegin() to rend() works\nTEST(LinkedHashSetTest, ReverseIteration) {\n  linked_hash_set<int> m;\n  EXPECT_TRUE(m.rbegin() == m.rend());\n\n  m.insert(2);\n  m.insert(1);\n  m.insert(3);\n\n  linked_hash_set<int>::reverse_iterator i = m.rbegin();\n  ASSERT_TRUE(m.rbegin() == i);\n  ASSERT_TRUE(m.rend() != i);\n  EXPECT_EQ(3, *i);\n\n  ++i;\n  ASSERT_TRUE(m.rend() != i);\n  EXPECT_EQ(1, *i);\n\n  ++i;\n  ASSERT_TRUE(m.rend() != i);\n  EXPECT_EQ(2, *i);\n\n  ++i;\n  ASSERT_TRUE(m.rend() == i);\n}\n\n// Tests that clear() works\nTEST(LinkedHashSetTest, Clear) {\n  linked_hash_set<int> m{2, 1, 3};\n  ASSERT_EQ(3, m.size());\n\n  m.clear();\n  EXPECT_EQ(0, m.size());\n  EXPECT_FALSE(m.contains(1));\n  EXPECT_TRUE(m.find(1) == m.end());\n\n  // Make sure we can call it on an empty set.\n  m.clear();\n  EXPECT_EQ(0, m.size());\n}\n\n// Tests that size() works.\nTEST(LinkedHashSetTest, Size) {\n  linked_hash_set<int> m;\n  EXPECT_EQ(0, m.size());\n  m.insert(2);\n  EXPECT_EQ(1, m.size());\n  m.insert(11);\n  EXPECT_EQ(2, m.size());\n  m.insert(0);\n  EXPECT_EQ(3, m.size());\n  m.insert(0);\n  EXPECT_EQ(3, m.size());\n  m.clear();\n  EXPECT_EQ(0, m.size());\n}\n\n// Tests empty()\nTEST(LinkedHashSetTest, Empty) {\n  linked_hash_set<int> m;\n  ASSERT_TRUE(m.empty());\n  m.insert(2);\n  ASSERT_FALSE(m.empty());\n  m.clear();\n  ASSERT_TRUE(m.empty());\n}\n\nTEST(LinkedHashSetTest, Erase) {\n  linked_hash_set<int> m;\n  ASSERT_EQ(0, m.size());\n  EXPECT_EQ(0, m.erase(2));  // Nothing to erase yet\n\n  m.insert(2);\n  ASSERT_EQ(1, m.size());\n  EXPECT_EQ(1, m.erase(2));\n  EXPECT_EQ(0, m.size());\n  EXPECT_TRUE(m.empty());\n\n  EXPECT_EQ(0, m.erase(2));  // Make sure nothing bad happens if we repeat.\n  EXPECT_EQ(0, m.size());\n  EXPECT_TRUE(m.empty());\n}\n\nTEST(LinkedHashSetTest, Erase2) {\n  linked_hash_set<int> m;\n  ASSERT_EQ(0, m.size());\n  EXPECT_EQ(0, m.erase(2));  // Nothing to erase yet\n\n  m.insert(2);\n  m.insert(1);\n  m.insert(3);\n  m.insert(4);\n  ASSERT_EQ(4, m.size());\n\n  // Erase middle two\n  EXPECT_EQ(1, m.erase(1));\n  EXPECT_EQ(1, m.erase(3));\n\n  EXPECT_EQ(2, m.size());\n\n  // Make sure we can still iterate over everything that's left.\n  linked_hash_set<int>::iterator it = m.begin();\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(2, *it);\n  ++it;\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(4, *it);\n  ++it;\n  ASSERT_TRUE(it == m.end());\n\n  EXPECT_EQ(0, m.erase(1));  // Make sure nothing bad happens if we repeat.\n  ASSERT_EQ(2, m.size());\n\n  EXPECT_EQ(1, m.erase(2));\n  EXPECT_EQ(1, m.erase(4));\n  ASSERT_EQ(0, m.size());\n  EXPECT_TRUE(m.empty());\n\n  EXPECT_EQ(0, m.erase(1));  // Make sure nothing bad happens if we repeat.\n  ASSERT_EQ(0, m.size());\n  EXPECT_TRUE(m.empty());\n}\n\n// Test that erase(iter,iter) and erase(iter) compile and work.\nTEST(LinkedHashSetTest, Erase3) {\n  linked_hash_set<int> m;\n\n  m.insert(1);\n  m.insert(2);\n  m.insert(3);\n  m.insert(4);\n\n  // Erase middle two\n  linked_hash_set<int>::iterator it2 = m.find(2);\n  linked_hash_set<int>::iterator it4 = m.find(4);\n  EXPECT_EQ(m.erase(it2, it4), m.find(4));\n  EXPECT_FALSE(m.contains(2));\n  EXPECT_TRUE(m.find(2) == m.end());\n  EXPECT_FALSE(m.contains(3));\n  EXPECT_TRUE(m.find(3) == m.end());\n  EXPECT_EQ(2, m.size());\n\n  // Make sure we can still iterate over everything that's left.\n  linked_hash_set<int>::iterator it = m.begin();\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(1, *it);\n  ++it;\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(4, *it);\n  ++it;\n  ASSERT_TRUE(it == m.end());\n\n  // Erase first one using an iterator.\n  EXPECT_EQ(m.erase(m.begin()), m.find(4));\n  EXPECT_FALSE(m.contains(1));\n  EXPECT_TRUE(m.find(1) == m.end());\n\n  // Only the last element should be left.\n  EXPECT_TRUE(m.contains(4));\n  it = m.begin();\n  ASSERT_TRUE(it != m.end());\n  EXPECT_EQ(4, *it);\n  ++it;\n  ASSERT_TRUE(it == m.end());\n}\n\n// Test all types of insertion\nTEST(LinkedHashSetTest, Insertion) {\n  linked_hash_set<int> m;\n  ASSERT_EQ(0, m.size());\n  std::pair<linked_hash_set<int>::iterator, bool> result;\n\n  result = m.insert(2);\n  ASSERT_EQ(1, m.size());\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(2, *result.first);\n  EXPECT_TRUE(m.contains(2));\n  EXPECT_TRUE(m.find(2) != m.end());\n\n  result = m.insert(1);\n  ASSERT_EQ(2, m.size());\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(1, *result.first);\n  EXPECT_TRUE(m.contains(1));\n  EXPECT_TRUE(m.find(1) != m.end());\n\n  result = m.insert(3);\n  linked_hash_set<int>::iterator result_iterator = result.first;\n  ASSERT_EQ(3, m.size());\n  EXPECT_TRUE(result.second);\n  EXPECT_EQ(3, *result.first);\n  EXPECT_TRUE(m.contains(3));\n  EXPECT_TRUE(m.find(3) != m.end());\n\n  result = m.insert(3);\n  EXPECT_EQ(3, m.size());\n  EXPECT_FALSE(result.second) << \"No insertion should have occurred.\";\n  EXPECT_TRUE(result_iterator == result.first)\n      << \"Duplicate insertion should have given us the original iterator.\";\n  EXPECT_TRUE(m.contains(3));\n  EXPECT_TRUE(m.find(3) != m.end());\n\n  std::vector<int> v = {3, 4, 5};\n  m.insert(v.begin(), v.end());\n  // Expect 4 and 5 inserted, 3 not inserted.\n  EXPECT_EQ(5, m.size());\n  EXPECT_TRUE(m.contains(4));\n  EXPECT_NE(m.find(4), m.end());\n  EXPECT_TRUE(m.contains(5));\n  EXPECT_NE(m.find(5), m.end());\n}\n\nTEST(LinkedHashSetTest, HintedInsertionMoveable) {\n  linked_hash_set<int> m = {1, 3};\n  m.insert(m.find(3), 2);\n  EXPECT_THAT(m, ElementsAre(1, 2, 3));\n}\n\nTEST(LinkedHashSetTest, HintedInsertionReference) {\n  linked_hash_set<int> m = {1, 3};\n  const int val = 2;\n  m.insert(m.find(3), val);\n  EXPECT_THAT(m, ElementsAre(1, 2, 3));\n}\n\nTEST(LinkedHashSetTest, HintedEmplaceMoveable) {\n  linked_hash_set<int> m = {1, 3};\n  m.emplace_hint(m.find(3), 2);\n  EXPECT_THAT(m, ElementsAre(1, 2, 3));\n}\n\nTEST(LinkedHashSetTest, HintedEmplaceReference) {\n  linked_hash_set<int> m = {1, 3};\n  const int val = 2;\n  m.emplace_hint(m.find(3), val);\n  EXPECT_THAT(m, ElementsAre(1, 2, 3));\n}\n\n// Test front accessors.\nTEST(LinkedHashSetTest, Front) {\n  linked_hash_set<int> m;\n\n  m.insert(222);\n  m.insert(111);\n  m.insert(333);\n\n  EXPECT_EQ(3, m.size());\n  EXPECT_EQ(222, m.front());\n  m.pop_front();\n  EXPECT_EQ(2, m.size());\n  EXPECT_EQ(111, m.front());\n  m.pop_front();\n  EXPECT_EQ(1, m.size());\n  EXPECT_EQ(333, m.front());\n  m.pop_front();\n  EXPECT_TRUE(m.empty());\n}\n\n// Test back accessors.\nTEST(LinkedHashSetTest, Back) {\n  linked_hash_set<int> m;\n\n  m.insert(222);\n  m.insert(111);\n  m.insert(333);\n\n  EXPECT_EQ(3, m.size());\n  EXPECT_EQ(333, m.back());\n  m.pop_back();\n  EXPECT_EQ(2, m.size());\n  EXPECT_EQ(111, m.back());\n  m.pop_back();\n  EXPECT_EQ(1, m.size());\n  EXPECT_EQ(222, m.back());\n  m.pop_back();\n  EXPECT_TRUE(m.empty());\n}\n\nTEST(LinkedHashSetTest, Find) {\n  linked_hash_set<int> m;\n\n  EXPECT_TRUE(m.end() == m.find(1))\n      << \"We shouldn't find anything in an empty set.\";\n\n  m.insert(2);\n  EXPECT_TRUE(m.end() == m.find(1))\n      << \"We shouldn't find an element that doesn't exist in the set.\";\n\n  std::pair<linked_hash_set<int>::iterator, bool> result = m.insert(1);\n  ASSERT_TRUE(result.second);\n  ASSERT_TRUE(m.end() != result.first);\n  EXPECT_TRUE(result.first == m.find(1))\n      << \"We should have found an element we know exists in the set.\";\n  EXPECT_EQ(1, *result.first);\n\n  // Check that a follow-up insertion doesn't affect our original\n  m.insert(3);\n  linked_hash_set<int>::iterator it = m.find(1);\n  ASSERT_TRUE(m.end() != it);\n  EXPECT_EQ(1, *it);\n\n  m.clear();\n  EXPECT_TRUE(m.end() == m.find(1))\n      << \"We shouldn't find anything in a set that we've cleared.\";\n}\n\nTEST(LinkedHashSetTest, Contains) {\n  linked_hash_set<int> m;\n\n  EXPECT_FALSE(m.contains(1)) << \"The empty set shouldn't contain anything.\";\n\n  m.insert(2);\n  EXPECT_FALSE(m.contains(1))\n      << \"contains() should not return true for an element that doesn't exist \"\n      << \"in the set.\";\n\n  m.insert(1);\n  EXPECT_TRUE(m.contains(1))\n      << \"contains() should return true for an element we know exists in the \"\n      << \"set.\";\n\n  m.clear();\n  EXPECT_FALSE(m.contains(1))\n      << \"A set that we've cleared shouldn't contain anything.\";\n}\n\nTEST(LinkedHashSetTest, Swap) {\n  linked_hash_set<int> m1;\n  linked_hash_set<int> m2;\n  m1.insert(1);\n  m1.insert(2);\n  m2.insert(3);\n  ASSERT_EQ(2, m1.size());\n  ASSERT_EQ(1, m2.size());\n  m1.swap(m2);\n  ASSERT_EQ(1, m1.size());\n  ASSERT_EQ(2, m2.size());\n}\n\nTEST(LinkedHashSetTest, SelfSwap) {\n  linked_hash_set<int> a{1, 2, 3};\n  using std::swap;\n  swap(a, a);\n  EXPECT_THAT(a, ElementsAre(1, 2, 3));\n}\n\nTEST(LinkedHashSetTest, InitializerList) {\n  linked_hash_set<int> m{1, 3};\n  ASSERT_EQ(2, m.size());\n  EXPECT_TRUE(m.contains(1));\n  linked_hash_set<int>::iterator it = m.find(1);\n  ASSERT_TRUE(m.end() != it);\n  EXPECT_EQ(1, *it);\n  it = m.find(3);\n  EXPECT_TRUE(m.contains(3));\n  ASSERT_TRUE(m.end() != it);\n  EXPECT_EQ(3, *it);\n}\n\nTEST(LinkedHashSetTest, CustomHashAndEquality) {\n  struct CustomIntHash {\n    size_t operator()(int x) const { return 0; }\n  };\n  struct CustomIntEq {\n    bool operator()(int x, int y) const { return abs(x) == abs(y); }\n  };\n  linked_hash_set<int, CustomIntHash, CustomIntEq> m;\n  m.insert(1);\n  EXPECT_EQ(1, m.size());\n  m.insert(2);\n  EXPECT_EQ(2, m.size());\n  EXPECT_FALSE(m.insert(-2).second);\n  EXPECT_EQ(2, m.size());\n  EXPECT_TRUE(m.contains(-1));\n  EXPECT_TRUE(m.find(-1) != m.end());\n}\n\nTEST(LinkedHashSetTest, EqualRange) {\n  linked_hash_set<int> m{3, 1};\n  const auto& const_m = m;\n\n  EXPECT_THAT(m.equal_range(2), testing::Pair(m.end(), m.end()));\n  EXPECT_THAT(const_m.equal_range(2),\n              testing::Pair(const_m.end(), const_m.end()));\n\n  EXPECT_THAT(m.equal_range(1), testing::Pair(m.find(1), ++m.find(1)));\n  EXPECT_THAT(const_m.equal_range(1),\n              testing::Pair(const_m.find(1), ++const_m.find(1)));\n}\n\nTEST(LinkedHashSetTest, ReserveWorks) {\n  linked_hash_set<int> m;\n  EXPECT_EQ(0, m.size());\n  EXPECT_EQ(0.0, m.load_factor());\n  m.reserve(10);\n  EXPECT_LE(10, m.capacity());\n  EXPECT_EQ(0, m.size());\n  EXPECT_EQ(0.0, m.load_factor());\n  m.insert(1);\n  m.insert(2);\n  EXPECT_LE(10, m.capacity());\n  EXPECT_EQ(2, m.size());\n  EXPECT_LT(0.0, m.load_factor());\n}\n\nTEST(LinkedHashSetTest, HeterogeneousTests) {\n  absl::test_internal::InstanceTracker tracker;\n\n  linked_hash_set<ExpensiveType, HeterogeneousHash, HeterogeneousEqual> set;\n  ExpensiveType one(1);\n  tracker.ResetCopiesMovesSwaps();\n  set.insert(one);\n  // Two instances: 'one' var and an instance in the set.\n  EXPECT_EQ(2, tracker.instances());\n  EXPECT_EQ(1, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  set.insert(one);\n  // No construction since key==1 exists.\n  EXPECT_EQ(2, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  set.emplace(CheapType(1));\n  // No construction since key==1 exists.\n  EXPECT_EQ(2, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  set.emplace(CheapType(2));\n  // Construction since key==2 doesn't exist in the set.\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(set, ElementsAre(HasExpensiveValue(1), HasExpensiveValue(2)));\n\n  // find\n  tracker.ResetCopiesMovesSwaps();\n  auto itr = set.find(CheapType(1));\n  ASSERT_NE(itr, set.end());\n  EXPECT_EQ(1, itr->value());\n  // contains\n  EXPECT_TRUE(set.contains(CheapType(2)));\n  // count\n  EXPECT_EQ(1, set.count(CheapType(2)));\n  // equal_range\n  auto eq_itr_pair = set.equal_range(CheapType(2));\n  ASSERT_NE(eq_itr_pair.first, set.end());\n  EXPECT_EQ(2, eq_itr_pair.first->value());\n  // No construction for find, contains, count or equal_range.\n  EXPECT_EQ(3, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  // emplace\n  tracker.ResetCopiesMovesSwaps();\n  set.emplace(3);\n  // Just one construction.\n  EXPECT_EQ(4, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n\n  tracker.ResetCopiesMovesSwaps();\n  set.emplace(3);\n  // No additional construction since key==3 exists.\n  EXPECT_EQ(4, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(set, ElementsAre(HasExpensiveValue(1), HasExpensiveValue(2),\n                               HasExpensiveValue(3)));\n\n  // Test std::move() using insert().\n  ExpensiveType four(4);\n  tracker.ResetCopiesMovesSwaps();\n  set.insert(std::move(four));\n  // Two constructions (regular and move).\n  EXPECT_EQ(6, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(1, tracker.moves());\n\n  EXPECT_THAT(set, ElementsAre(HasExpensiveValue(1), HasExpensiveValue(2),\n                               HasExpensiveValue(3), HasExpensiveValue(4)));\n\n  tracker.ResetCopiesMovesSwaps();\n  set.erase(CheapType(1));\n  // No construction and instance reduced by one.\n  EXPECT_EQ(5, tracker.instances());\n  EXPECT_EQ(0, tracker.copies());\n  EXPECT_EQ(0, tracker.moves());\n  EXPECT_THAT(set, ElementsAre(HasExpensiveValue(2), HasExpensiveValue(3),\n                               HasExpensiveValue(4)));\n}\n\nTEST(LinkedHashSetTest, HeterogeneousStringViewLookup) {\n  linked_hash_set<std::string> set;\n  set.insert(\"foo\");\n  set.insert(\"bar\");\n  set.insert(\"blah\");\n\n  {\n    absl::string_view lookup(\"foo\");\n    auto itr = set.find(lookup);\n    ASSERT_NE(itr, set.end());\n    EXPECT_EQ(\"foo\", *itr);\n  }\n\n  // Not found.\n  {\n    absl::string_view lookup(\"foobar\");\n    EXPECT_EQ(set.end(), set.find(lookup));\n  }\n\n  {\n    absl::string_view lookup(\"blah\");\n    auto itr = set.find(lookup);\n    ASSERT_NE(itr, set.end());\n    EXPECT_EQ(\"blah\", *itr);\n  }\n}\n\nTEST(LinkedHashSetTest, EmplaceString) {\n  std::vector<std::string> v = {\"a\", \"b\"};\n  linked_hash_set<absl::string_view> hs(v.begin(), v.end());\n  EXPECT_THAT(hs, ElementsAreArray(v));\n}\n\nTEST(LinkedHashSetTest, BitfieldArgument) {\n  union {\n    int n : 1;\n  };\n  n = 0;\n  linked_hash_set<int> s = {n};\n  s.insert(n);\n  s.insert(s.end(), n);\n  s.insert({n});\n  s.erase(n);\n  s.count(n);\n  s.find(n);\n  s.contains(n);\n  s.equal_range(n);\n}\n\nTEST(LinkedHashSetTest, MergeExtractInsert) {\n  struct Hash {\n    size_t operator()(const std::unique_ptr<int>& p) const { return *p; }\n  };\n  struct Eq {\n    bool operator()(const std::unique_ptr<int>& a,\n                    const std::unique_ptr<int>& b) const {\n      return *a == *b;\n    }\n  };\n  linked_hash_set<std::unique_ptr<int>, Hash, Eq> set1, set2;\n  set1.insert(std::make_unique<int>(7));\n  set1.insert(std::make_unique<int>(17));\n\n  set2.insert(std::make_unique<int>(7));\n  set2.insert(std::make_unique<int>(19));\n\n  EXPECT_THAT(set1, ElementsAre(Pointee(7), Pointee(17)));\n  EXPECT_THAT(set2, ElementsAre(Pointee(7), Pointee(19)));\n\n  set1.merge(set2);\n\n  EXPECT_THAT(set1, ElementsAre(Pointee(7), Pointee(17), Pointee(19)));\n  EXPECT_THAT(set2, ElementsAre(Pointee(7)));\n\n  auto node = set1.extract(std::make_unique<int>(7));\n  EXPECT_TRUE(node);\n  EXPECT_THAT(node.value(), Pointee(7));\n  EXPECT_THAT(set1, ElementsAre(Pointee(17), Pointee(19)));\n\n  auto insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_FALSE(insert_result.inserted);\n  EXPECT_TRUE(insert_result.node);\n  EXPECT_THAT(insert_result.node.value(), Pointee(7));\n  EXPECT_EQ(**insert_result.position, 7);\n  EXPECT_NE(insert_result.position->get(), insert_result.node.value().get());\n  EXPECT_THAT(set2, ElementsAre(Pointee(7)));\n\n  node = set1.extract(std::make_unique<int>(17));\n  EXPECT_TRUE(node);\n  EXPECT_THAT(node.value(), Pointee(17));\n  EXPECT_THAT(set1, ElementsAre(Pointee(19)));\n\n  node.value() = std::make_unique<int>(23);\n\n  insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_TRUE(insert_result.inserted);\n  EXPECT_FALSE(insert_result.node);\n  EXPECT_EQ(**insert_result.position, 23);\n  EXPECT_THAT(set2, ElementsAre(Pointee(7), Pointee(23)));\n}\n\nTEST(LinkedHashSet, ExtractInsert) {\n  linked_hash_set<int> s = {1, 7, 2, 9};\n  auto node = s.extract(1);\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.value(), 1);\n  EXPECT_THAT(s, ElementsAre(7, 2, 9));\n  EXPECT_FALSE(s.contains(1));\n\n  node.value() = 17;\n  s.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_THAT(s, ElementsAre(7, 2, 9, 17));\n  EXPECT_TRUE(s.contains(17));\n\n  node = s.extract(s.find(9));\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.value(), 9);\n  EXPECT_THAT(s, ElementsAre(7, 2, 17));\n  EXPECT_FALSE(s.contains(9));\n}\n\nTEST(LinkedHashSet, Merge) {\n  linked_hash_set<int> m = {1, 7, 3, 6, 10};\n  linked_hash_set<int> src = {1, 2, 9, 10, 4, 16};\n\n  m.merge(src);\n\n  EXPECT_THAT(m, ElementsAre(1, 7, 3, 6, 10, 2, 9, 4, 16));\n  for (int i : {1, 7, 3, 6, 10, 2, 9, 4, 16}) {\n    EXPECT_TRUE(m.contains(i));\n  }\n  EXPECT_THAT(src, ElementsAre(1, 10));\n  for (int i : {1, 10}) {\n    EXPECT_TRUE(src.contains(i));\n  }\n  for (int i : {2, 9, 4, 16}) {\n    EXPECT_FALSE(src.contains(i));\n  }\n}\n\nTEST(LinkedHashSet, EraseRange) {\n  linked_hash_set<int> set = {1, 2, 3, 4, 5, 25, 36, 7, 8, 9, 81};\n  auto start = set.find(3);\n  auto end = set.find(8);\n  auto itr = set.erase(start, end);\n  ASSERT_NE(itr, set.end());\n  EXPECT_THAT(*itr, 8);\n  EXPECT_THAT(set, ElementsAre(1, 2, 8, 9, 81));\n  for (int i : {1, 2, 8, 9, 81}) {\n    EXPECT_TRUE(set.contains(i));\n  }\n  for (int i : {3, 4, 5, 25, 36, 7}) {\n    EXPECT_FALSE(set.contains(i));\n  }\n}\n\nTEST(LinkedHashSet, InsertInitializerList) {\n  linked_hash_set<int> set;\n  set.insert({1, 7, 2, 9, 3, 29});\n  EXPECT_THAT(set, ElementsAre(1, 7, 2, 9, 3, 29));\n  for (int i : {1, 7, 2, 9, 3, 29}) {\n    EXPECT_TRUE(set.contains(i));\n  }\n}\n\nstruct CountedHash {\n  explicit CountedHash(int* count) : count(count) {}\n  size_t operator()(int value) const {\n    ++(*count);\n    return value;\n  }\n  int* count = nullptr;\n};\n\n// Makes a set too big for small object optimization.  Counts the number of\n// hashes in `count`, but leaves `count` set to 0.\nlinked_hash_set<int, CountedHash> MakeNonSmallSet(int* count) {\n  const int kFirstKey = -1000;\n  linked_hash_set<int, CountedHash> s(0, CountedHash(count));\n  for (int i = kFirstKey; i < kFirstKey + 100; ++i) {\n    s.insert(i);\n  }\n  *count = 0;\n  return s;\n}\n\nconstexpr bool BuildHasDebugModeRehashes() {\n#if !defined(NDEBUG) || defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)\n  return true;\n#else\n  return false;\n#endif\n}\n\nTEST(LinkedHashSetTest, HashCountInOptBuilds) {\n  if (BuildHasDebugModeRehashes()) {\n    GTEST_SKIP() << \"Only run under NDEBUG: `assert` statements and sanitizer \"\n                    \"rehashing may cause redundant hashing.\";\n  }\n\n  using Set = linked_hash_set<int, CountedHash>;\n  {\n    int count = 0;\n    Set s = MakeNonSmallSet(&count);\n    s.insert(1);\n    EXPECT_EQ(count, 1);\n    s.erase(1);\n    EXPECT_EQ(count, 2);\n  }\n  {\n    int count = 0;\n    Set s = MakeNonSmallSet(&count);\n    s.insert(3);\n    EXPECT_EQ(count, 1);\n    auto node = s.extract(3);\n    EXPECT_EQ(count, 2);\n    s.insert(std::move(node));\n    EXPECT_EQ(count, 3);\n  }\n  {\n    int count = 0;\n    Set s = MakeNonSmallSet(&count);\n    s.emplace(5);\n    EXPECT_EQ(count, 1);\n  }\n  {\n    int src_count = 0, dst_count = 0;\n    Set src = MakeNonSmallSet(&src_count);\n    Set dst = MakeNonSmallSet(&dst_count);\n    src.insert(7);\n    dst.merge(src);\n    EXPECT_LE(src_count, 200);\n    EXPECT_LE(dst_count, 200);\n  }\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/node_hash_map.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: node_hash_map.h\n// -----------------------------------------------------------------------------\n//\n// An `absl::node_hash_map<K, V>` is an unordered associative container of\n// unique keys and associated values designed to be a more efficient replacement\n// for `std::unordered_map`. Like `unordered_map`, search, insertion, and\n// deletion of map elements can be done as an `O(1)` operation. However,\n// `node_hash_map` (and other unordered associative containers known as the\n// collection of Abseil \"Swiss tables\") contain other optimizations that result\n// in both memory and computation advantages.\n//\n// In most cases, your default choice for a hash map should be a map of type\n// `flat_hash_map`. However, if you need pointer stability and cannot store\n// a `flat_hash_map` with `unique_ptr` elements, a `node_hash_map` may be a\n// valid alternative. As well, if you are migrating your code from using\n// `std::unordered_map`, a `node_hash_map` provides a more straightforward\n// migration, because it guarantees pointer stability. Consider migrating to\n// `node_hash_map` and perhaps converting to a more efficient `flat_hash_map`\n// upon further review.\n//\n// `node_hash_map` is not exception-safe.\n\n#ifndef ABSL_CONTAINER_NODE_HASH_MAP_H_\n#define ABSL_CONTAINER_NODE_HASH_MAP_H_\n\n#include <cstddef>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/container/hash_container_defaults.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/node_slot_policy.h\"\n#include \"absl/container/internal/raw_hash_map.h\"  // IWYU pragma: export\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\ntemplate <class Key, class Value>\nclass NodeHashMapPolicy;\n}  // namespace container_internal\n\n// -----------------------------------------------------------------------------\n// absl::node_hash_map\n// -----------------------------------------------------------------------------\n//\n// An `absl::node_hash_map<K, V>` is an unordered associative container which\n// has been optimized for both speed and memory footprint in most common use\n// cases. Its interface is similar to that of `std::unordered_map<K, V>` with\n// the following notable differences:\n//\n// * Supports heterogeneous lookup, through `find()`, `operator[]()` and\n//   `insert()`, provided that the map is provided a compatible heterogeneous\n//   hashing function and equality operator. See below for details.\n// * Contains a `capacity()` member function indicating the number of element\n//   slots (open, deleted, and empty) within the hash map.\n// * Returns `void` from the `erase(iterator)` overload.\n//\n// By default, `node_hash_map` uses the `absl::Hash` hashing framework.\n// All fundamental and Abseil types that support the `absl::Hash` framework have\n// a compatible equality operator for comparing insertions into `node_hash_map`.\n// If your type is not yet supported by the `absl::Hash` framework, see\n// absl/hash/hash.h for information on extending Abseil hashing to user-defined\n// types.\n//\n// Using `absl::node_hash_map` at interface boundaries in dynamically loaded\n// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may\n// be randomized across dynamically loaded libraries.\n//\n// To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type\n// parameters can be used or `T` should have public inner types\n// `absl_container_hash` and (optionally) `absl_container_eq`. In either case,\n// `typename Hash::is_transparent` and `typename Eq::is_transparent` should be\n// well-formed. Both types are basically functors:\n// * `Hash` should support `size_t operator()(U val) const` that returns a hash\n// for the given `val`.\n// * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true\n// if `lhs` is equal to `rhs`.\n//\n// In most cases `T` needs only to provide the `absl_container_hash`. In this\n// case `std::equal_to<void>` will be used instead of `eq` part.\n//\n// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:\n//  * Iteration takes O(capacity) time, not O(size).\n//  * erase() slows down begin() and ++iterator.\n//  * Capacity only shrinks on rehash() or clear() -- not on erase().\n//\n// Example:\n//\n//   // Create a node hash map of three strings (that map to strings)\n//   absl::node_hash_map<std::string, std::string> ducks =\n//     {{\"a\", \"huey\"}, {\"b\", \"dewey\"}, {\"c\", \"louie\"}};\n//\n//   // Insert a new element into the node hash map\n//   ducks.insert({\"d\", \"donald\"}};\n//\n//   // Force a rehash of the node hash map\n//   ducks.rehash(0);\n//\n//   // Find the element with the key \"b\"\n//   std::string search_key = \"b\";\n//   auto result = ducks.find(search_key);\n//   if (result != ducks.end()) {\n//     std::cout << \"Result: \" << result->second << std::endl;\n//   }\ntemplate <\n    class Key, class Value,\n    class Hash =\n        typename container_internal::NodeHashMapPolicy<Key, Value>::DefaultHash,\n    class Eq =\n        typename container_internal::NodeHashMapPolicy<Key, Value>::DefaultEq,\n    class Alloc = typename container_internal::NodeHashMapPolicy<\n        Key, Value>::DefaultAlloc>\nclass ABSL_ATTRIBUTE_OWNER node_hash_map\n    : public absl::container_internal::InstantiateRawHashMap<\n          absl::container_internal::NodeHashMapPolicy<Key, Value>, Hash, Eq,\n          Alloc>::type {\n  using Base = typename node_hash_map::raw_hash_map;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A node_hash_map supports the same overload set as `std::unordered_map`\n  // for construction and assignment:\n  //\n  // *  Default constructor\n  //\n  //    // No allocation for the table's elements is made.\n  //    absl::node_hash_map<int, std::string> map1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::node_hash_map<int, std::string> map2 =\n  //       {{1, \"huey\"}, {2, \"dewey\"}, {3, \"louie\"},};\n  //\n  // * Copy constructor\n  //\n  //   absl::node_hash_map<int, std::string> map3(map2);\n  //\n  // * Copy assignment operator\n  //\n  //   // Hash functor and Comparator are copied as well\n  //   absl::node_hash_map<int, std::string> map4;\n  //   map4 = map3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::node_hash_map<int, std::string> map5(std::move(map4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::node_hash_map<int, std::string> map6;\n  //   map6 = std::move(map5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::pair<int, std::string>> v = {{1, \"a\"}, {2, \"b\"}};\n  //   absl::node_hash_map<int, std::string> map7(v.begin(), v.end());\n  //\n  // * from_range constructor (C++23)\n  //\n  //   std::vector<std::pair<int, std::string>> v = {{1, \"a\"}, {2, \"b\"}};\n  //   absl::node_hash_map<int, std::string> map8(std::from_range, v);\n  node_hash_map() {}\n  using Base::Base;\n\n  // node_hash_map::begin()\n  //\n  // Returns an iterator to the beginning of the `node_hash_map`.\n  using Base::begin;\n\n  // node_hash_map::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `node_hash_map`.\n  using Base::cbegin;\n\n  // node_hash_map::cend()\n  //\n  // Returns a const iterator to the end of the `node_hash_map`.\n  using Base::cend;\n\n  // node_hash_map::end()\n  //\n  // Returns an iterator to the end of the `node_hash_map`.\n  using Base::end;\n\n  // node_hash_map::capacity()\n  //\n  // Returns the number of element slots (assigned, deleted, and empty)\n  // available within the `node_hash_map`.\n  //\n  // NOTE: this member function is particular to `absl::node_hash_map` and is\n  // not provided in the `std::unordered_map` API.\n  using Base::capacity;\n\n  // node_hash_map::empty()\n  //\n  // Returns whether or not the `node_hash_map` is empty.\n  using Base::empty;\n\n  // node_hash_map::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `node_hash_map` under current memory constraints. This value can be thought\n  // of as the largest value of `std::distance(begin(), end())` for a\n  // `node_hash_map<K, V>`.\n  using Base::max_size;\n\n  // node_hash_map::size()\n  //\n  // Returns the number of elements currently within the `node_hash_map`.\n  using Base::size;\n\n  // node_hash_map::clear()\n  //\n  // Removes all elements from the `node_hash_map`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  //\n  // NOTE: this operation may shrink the underlying buffer. To avoid shrinking\n  // the underlying buffer call `erase(begin(), end())`.\n  using Base::clear;\n\n  // node_hash_map::erase()\n  //\n  // Erases elements within the `node_hash_map`. Erasing does not trigger a\n  // rehash. Overloads are listed below.\n  //\n  // void erase(const_iterator pos):\n  //\n  //   Erases the element at `position` of the `node_hash_map`, returning\n  //   `void`.\n  //\n  //   NOTE: Returning `void` in this case is different than that of STL\n  //   containers in general and `std::unordered_map` in particular (which\n  //   return an iterator to the element following the erased element). If that\n  //   iterator is needed, simply post increment the iterator:\n  //\n  //     map.erase(it++);\n  //\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning an\n  //   iterator pointing to `last`. The special case of calling\n  //   `erase(begin(), end())` resets the reserved growth such that if\n  //   `reserve(N)` has previously been called and there has been no intervening\n  //   call to `clear()`, then after calling `erase(begin(), end())`, it is safe\n  //   to assume that inserting N elements will not cause a rehash.\n  //\n  // size_type erase(const key_type& key):\n  //\n  //   Erases the element with the matching key, if it exists, returning the\n  //   number of elements erased (0 or 1).\n  using Base::erase;\n\n  // node_hash_map::insert()\n  //\n  // Inserts an element of the specified value into the `node_hash_map`,\n  // returning an iterator pointing to the newly inserted element, provided that\n  // an element with the given key does not already exist. If rehashing occurs\n  // due to the insertion, all iterators are invalidated. Overloads are listed\n  // below.\n  //\n  // std::pair<iterator,bool> insert(const init_type& value):\n  //\n  //   Inserts a value into the `node_hash_map`. Returns a pair consisting of an\n  //   iterator to the inserted element (or to the element that prevented the\n  //   insertion) and a `bool` denoting whether the insertion took place.\n  //\n  // std::pair<iterator,bool> insert(T&& value):\n  // std::pair<iterator,bool> insert(init_type&& value):\n  //\n  //   Inserts a moveable value into the `node_hash_map`. Returns a `std::pair`\n  //   consisting of an iterator to the inserted element (or to the element that\n  //   prevented the insertion) and a `bool` denoting whether the insertion took\n  //   place.\n  //\n  // iterator insert(const_iterator hint, const init_type& value):\n  // iterator insert(const_iterator hint, T&& value):\n  // iterator insert(const_iterator hint, init_type&& value);\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element, or to the existing element that prevented the\n  //   insertion.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently, for `node_hash_map` we guarantee the\n  //   first match is inserted.\n  //\n  // void insert(std::initializer_list<init_type> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently within the initializer list, for\n  //   `node_hash_map` we guarantee the first match is inserted.\n  using Base::insert;\n\n  // node_hash_map::insert_or_assign()\n  //\n  // Inserts an element of the specified value into the `node_hash_map` provided\n  // that a value with the given key does not already exist, or replaces it with\n  // the element value if a key for that value already exists, returning an\n  // iterator pointing to the newly inserted element. If rehashing occurs due to\n  // the insertion, all iterators are invalidated. Overloads are listed\n  // below.\n  //\n  // std::pair<iterator, bool> insert_or_assign(const init_type& k, T&& obj):\n  // std::pair<iterator, bool> insert_or_assign(init_type&& k, T&& obj):\n  //\n  //   Inserts/Assigns (or moves) the element of the specified key into the\n  //   `node_hash_map`.\n  //\n  // iterator insert_or_assign(const_iterator hint,\n  //                           const init_type& k, T&& obj):\n  // iterator insert_or_assign(const_iterator hint, init_type&& k, T&& obj):\n  //\n  //   Inserts/Assigns (or moves) the element of the specified key into the\n  //   `node_hash_map` using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search.\n  using Base::insert_or_assign;\n\n  // node_hash_map::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `node_hash_map`, provided that no element with the given key\n  // already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately. Prefer `try_emplace()` unless your key is not\n  // copyable or moveable.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace;\n\n  // node_hash_map::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `node_hash_map`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search, and only inserts\n  // provided that no element with the given key already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately. Prefer `try_emplace()` unless your key is not\n  // copyable or moveable.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace_hint;\n\n  // node_hash_map::try_emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `node_hash_map`, provided that no element with the given key\n  // already exists. Unlike `emplace()`, if an element with the given key\n  // already exists, we guarantee that no element is constructed.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  // Overloads are listed below.\n  //\n  //   std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args):\n  //   std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args):\n  //\n  // Inserts (via copy or move) the element of the specified key into the\n  // `node_hash_map`.\n  //\n  //   iterator try_emplace(const_iterator hint,\n  //                        const key_type& k, Args&&... args):\n  //   iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args):\n  //\n  // Inserts (via copy or move) the element of the specified key into the\n  // `node_hash_map` using the position of `hint` as a non-binding suggestion\n  // for where to begin the insertion search.\n  //\n  // All `try_emplace()` overloads make the same guarantees regarding rvalue\n  // arguments as `std::unordered_map::try_emplace()`, namely that these\n  // functions will not move from rvalue arguments if insertions do not happen.\n  using Base::try_emplace;\n\n  // node_hash_map::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the key,value pair of the element at the indicated position and\n  //   returns a node handle owning that extracted data.\n  //\n  // node_type extract(const key_type& x):\n  //\n  //   Extracts the key,value pair of the element with a key matching the passed\n  //   key value and returns a node handle owning that extracted data. If the\n  //   `node_hash_map` does not contain an element with a matching key, this\n  //   function returns an empty node handle.\n  //\n  // NOTE: when compiled in an earlier version of C++ than C++17,\n  // `node_type::key()` returns a const reference to the key instead of a\n  // mutable reference. We cannot safely return a mutable reference without\n  // std::launder (which is not available before C++17).\n  using Base::extract;\n\n  // node_hash_map::merge()\n  //\n  // Extracts elements from a given `source` node hash map into this\n  // `node_hash_map`. If the destination `node_hash_map` already contains an\n  // element with an equivalent key, that element is not extracted.\n  using Base::merge;\n\n  // node_hash_map::swap(node_hash_map& other)\n  //\n  // Exchanges the contents of this `node_hash_map` with those of the `other`\n  // node hash map.\n  //\n  // All iterators and references on the `node_hash_map` remain valid, excepting\n  // for the past-the-end iterator, which is invalidated.\n  //\n  // `swap()` requires that the node hash map's hashing and key equivalence\n  // functions be Swappable, and are exchanged using unqualified calls to\n  // non-member `swap()`. If the map's allocator has\n  // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`\n  // set to `true`, the allocators are also exchanged using an unqualified call\n  // to non-member `swap()`; otherwise, the allocators are not swapped.\n  using Base::swap;\n\n  // node_hash_map::rehash(count)\n  //\n  // Rehashes the `node_hash_map`, setting the number of slots to be at least\n  // the passed value. If the new number of slots increases the load factor more\n  // than the current maximum load factor\n  // (`count` < `size()` / `max_load_factor()`), then the new number of slots\n  // will be at least `size()` / `max_load_factor()`.\n  //\n  // To force a rehash, pass rehash(0).\n  using Base::rehash;\n\n  // node_hash_map::reserve(count)\n  //\n  // Sets the number of slots in the `node_hash_map` to the number needed to\n  // accommodate at least `count` total elements without exceeding the current\n  // maximum load factor, and may rehash the container if needed. After this\n  // returns, it is guaranteed that `count - size()` elements can be inserted\n  // into the `node_hash_map` without another rehash.\n  using Base::reserve;\n\n  // node_hash_map::at()\n  //\n  // Returns a reference to the mapped value of the element with key equivalent\n  // to the passed key.\n  using Base::at;\n\n  // node_hash_map::contains()\n  //\n  // Determines whether an element with a key comparing equal to the given `key`\n  // exists within the `node_hash_map`, returning `true` if so or `false`\n  // otherwise.\n  using Base::contains;\n\n  // node_hash_map::count(const Key& key) const\n  //\n  // Returns the number of elements with a key comparing equal to the given\n  // `key` within the `node_hash_map`. note that this function will return\n  // either `1` or `0` since duplicate keys are not allowed within a\n  // `node_hash_map`.\n  using Base::count;\n\n  // node_hash_map::equal_range()\n  //\n  // Returns a closed range [first, last], defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `node_hash_map`.\n  using Base::equal_range;\n\n  // node_hash_map::find()\n  //\n  // Finds an element with the passed `key` within the `node_hash_map`.\n  using Base::find;\n\n  // node_hash_map::operator[]()\n  //\n  // Returns a reference to the value mapped to the passed key within the\n  // `node_hash_map`, performing an `insert()` if the key does not already\n  // exist. If an insertion occurs and results in a rehashing of the container,\n  // all iterators are invalidated. Otherwise iterators are not affected and\n  // references are not invalidated. Overloads are listed below.\n  //\n  // T& operator[](const Key& key):\n  //\n  //   Inserts an init_type object constructed in-place if the element with the\n  //   given key does not exist.\n  //\n  // T& operator[](Key&& key):\n  //\n  //   Inserts an init_type object constructed in-place provided that an element\n  //   with the given key does not exist.\n  using Base::operator[];\n\n  // node_hash_map::bucket_count()\n  //\n  // Returns the number of \"buckets\" within the `node_hash_map`.\n  using Base::bucket_count;\n\n  // node_hash_map::load_factor()\n  //\n  // Returns the current load factor of the `node_hash_map` (the average number\n  // of slots occupied with a value within the hash map).\n  using Base::load_factor;\n\n  // node_hash_map::max_load_factor()\n  //\n  // Manages the maximum load factor of the `node_hash_map`. Overloads are\n  // listed below.\n  //\n  // float node_hash_map::max_load_factor()\n  //\n  //   Returns the current maximum load factor of the `node_hash_map`.\n  //\n  // void node_hash_map::max_load_factor(float ml)\n  //\n  //   Sets the maximum load factor of the `node_hash_map` to the passed value.\n  //\n  //   NOTE: This overload is provided only for API compatibility with the STL;\n  //   `node_hash_map` will ignore any set load factor and manage its rehashing\n  //   internally as an implementation detail.\n  using Base::max_load_factor;\n\n  // node_hash_map::get_allocator()\n  //\n  // Returns the allocator function associated with this `node_hash_map`.\n  using Base::get_allocator;\n\n  // node_hash_map::hash_function()\n  //\n  // Returns the hashing function used to hash the keys within this\n  // `node_hash_map`.\n  using Base::hash_function;\n\n  // node_hash_map::key_eq()\n  //\n  // Returns the function used for comparing keys equality.\n  using Base::key_eq;\n};\n\n// erase_if(node_hash_map<>, Pred)\n//\n// Erases all elements that satisfy the predicate `pred` from the container `c`.\n// Returns the number of erased elements.\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Predicate>\ntypename node_hash_map<K, V, H, E, A>::size_type erase_if(\n    node_hash_map<K, V, H, E, A>& c, Predicate pred) {\n  return container_internal::EraseIf(pred, &c);\n}\n\n// swap(node_hash_map<>, node_hash_map<>)\n//\n// Swaps the contents of two `node_hash_map` containers.\n//\n// NOTE: we need to define this function template in order for\n// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we\n// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a\n// derived-to-base conversion, whereas `std::swap` is a function template so\n// `std::swap` will be preferred by compiler.\ntemplate <typename K, typename V, typename H, typename E, typename A>\nvoid swap(node_hash_map<K, V, H, E, A>& x,\n          node_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) {\n  return x.swap(y);\n}\n\nnamespace container_internal {\n\n// c_for_each_fast(node_hash_map<>, Function)\n//\n// Container-based version of the <algorithm> `std::for_each()` function to\n// apply a function to a container's elements.\n// There is no guarantees on the order of the function calls.\n// Erasure and/or insertion of elements in the function is not allowed.\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Function>\ndecay_t<Function> c_for_each_fast(const node_hash_map<K, V, H, E, A>& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Function>\ndecay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename K, typename V, typename H, typename E, typename A,\n          typename Function>\ndecay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>&& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\n\n}  // namespace container_internal\n\nnamespace container_internal {\n\ntemplate <class Key, class Value>\nclass NodeHashMapPolicy\n    : public absl::container_internal::node_slot_policy<\n          std::pair<const Key, Value>&, NodeHashMapPolicy<Key, Value>> {\n  using value_type = std::pair<const Key, Value>;\n\n public:\n  using key_type = Key;\n  using mapped_type = Value;\n  using init_type = std::pair</*non const*/ key_type, mapped_type>;\n\n  using DefaultHash = DefaultHashContainerHash<Key>;\n  using DefaultEq = DefaultHashContainerEq<Key>;\n  using DefaultAlloc = std::allocator<std::pair<const Key, Value>>;\n\n  template <class Allocator, class... Args>\n  static value_type* new_element(Allocator* alloc, Args&&... args) {\n    using PairAlloc = typename absl::allocator_traits<\n        Allocator>::template rebind_alloc<value_type>;\n    PairAlloc pair_alloc(*alloc);\n    value_type* res =\n        absl::allocator_traits<PairAlloc>::allocate(pair_alloc, 1);\n    absl::allocator_traits<PairAlloc>::construct(pair_alloc, res,\n                                                 std::forward<Args>(args)...);\n    return res;\n  }\n\n  template <class Allocator>\n  static void delete_element(Allocator* alloc, value_type* pair) {\n    using PairAlloc = typename absl::allocator_traits<\n        Allocator>::template rebind_alloc<value_type>;\n    PairAlloc pair_alloc(*alloc);\n    absl::allocator_traits<PairAlloc>::destroy(pair_alloc, pair);\n    absl::allocator_traits<PairAlloc>::deallocate(pair_alloc, pair, 1);\n  }\n\n  template <class F, class... Args>\n  static decltype(absl::container_internal::DecomposePair(\n      std::declval<F>(), std::declval<Args>()...))\n  apply(F&& f, Args&&... args) {\n    return absl::container_internal::DecomposePair(std::forward<F>(f),\n                                                   std::forward<Args>(args)...);\n  }\n\n  static size_t element_space_used(const value_type*) {\n    return sizeof(value_type);\n  }\n\n  static Value& value(value_type* elem) { return elem->second; }\n  static const Value& value(const value_type* elem) { return elem->second; }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return memory_internal::IsLayoutCompatible<Key, Value>::value\n               ? &TypeErasedDerefAndApplyToSlotFn<Hash, Key, kIsDefault>\n               : nullptr;\n  }\n};\n}  // namespace container_internal\n\nnamespace container_algorithm_internal {\n\n// Specialization of trait in absl/algorithm/container.h\ntemplate <class Key, class T, class Hash, class KeyEqual, class Allocator>\nstruct IsUnorderedContainer<\n    absl::node_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};\n\n}  // namespace container_algorithm_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_NODE_HASH_MAP_H_\n"
  },
  {
    "path": "absl/container/node_hash_map_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/node_hash_map.h\"\n\n#include <cstddef>\n#include <new>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/container/internal/tracked.h\"\n#include \"absl/container/internal/unordered_map_constructor_test.h\"\n#include \"absl/container/internal/unordered_map_lookup_test.h\"\n#include \"absl/container/internal/unordered_map_members_test.h\"\n#include \"absl/container/internal/unordered_map_modifiers_test.h\"\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <ranges>  // NOLINT(build/c++20)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::Field;\nusing ::testing::IsEmpty;\nusing ::testing::Pair;\nusing ::testing::UnorderedElementsAre;\nusing ::testing::UnorderedElementsAreArray;\n\nusing MapTypes = ::testing::Types<\n    absl::node_hash_map<int, int, StatefulTestingHash, StatefulTestingEqual,\n                        Alloc<std::pair<const int, int>>>,\n    absl::node_hash_map<std::string, std::string, StatefulTestingHash,\n                        StatefulTestingEqual,\n                        Alloc<std::pair<const std::string, std::string>>>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ConstructorTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, LookupTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, MembersTest, MapTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ModifiersTest, MapTypes);\n\nusing M = absl::node_hash_map<std::string, Tracked<int>>;\n\nTEST(NodeHashMap, Emplace) {\n  M m;\n  Tracked<int> t(53);\n  m.emplace(\"a\", t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(1, t.num_copies());\n\n  m.emplace(std::string(\"a\"), t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(1, t.num_copies());\n\n  std::string a(\"a\");\n  m.emplace(a, t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(1, t.num_copies());\n\n  const std::string ca(\"a\");\n  m.emplace(a, t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(1, t.num_copies());\n\n  m.emplace(std::make_pair(\"a\", t));\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(2, t.num_copies());\n\n  m.emplace(std::make_pair(std::string(\"a\"), t));\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(3, t.num_copies());\n\n  std::pair<std::string, Tracked<int>> p(\"a\", t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(4, t.num_copies());\n  m.emplace(p);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(4, t.num_copies());\n\n  const std::pair<std::string, Tracked<int>> cp(\"a\", t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(5, t.num_copies());\n  m.emplace(cp);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(5, t.num_copies());\n\n  std::pair<const std::string, Tracked<int>> pc(\"a\", t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(6, t.num_copies());\n  m.emplace(pc);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(6, t.num_copies());\n\n  const std::pair<const std::string, Tracked<int>> cpc(\"a\", t);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(7, t.num_copies());\n  m.emplace(cpc);\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(7, t.num_copies());\n\n  m.emplace(std::piecewise_construct, std::forward_as_tuple(\"a\"),\n            std::forward_as_tuple(t));\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(7, t.num_copies());\n\n  m.emplace(std::piecewise_construct, std::forward_as_tuple(std::string(\"a\")),\n            std::forward_as_tuple(t));\n  ASSERT_EQ(0, t.num_moves());\n  ASSERT_EQ(7, t.num_copies());\n}\n\nTEST(NodeHashMap, AssignRecursive) {\n  struct Tree {\n    // Verify that unordered_map<K, IncompleteType> can be instantiated.\n    absl::node_hash_map<int, Tree> children;\n  };\n  Tree root;\n  const Tree& child = root.children.emplace().first->second;\n  // Verify that `lhs = rhs` doesn't read rhs after clearing lhs.\n  root = child;\n}\n\nTEST(FlatHashMap, MoveOnlyKey) {\n  struct Key {\n    Key() = default;\n    Key(Key&&) = default;\n    Key& operator=(Key&&) = default;\n  };\n  struct Eq {\n    bool operator()(const Key&, const Key&) const { return true; }\n  };\n  struct Hash {\n    size_t operator()(const Key&) const { return 0; }\n  };\n  absl::node_hash_map<Key, int, Hash, Eq> m;\n  m[Key()];\n}\n\nstruct NonMovableKey {\n  explicit NonMovableKey(int i) : i(i) {}\n  NonMovableKey(NonMovableKey&&) = delete;\n  int i;\n};\nstruct NonMovableKeyHash {\n  using is_transparent = void;\n  size_t operator()(const NonMovableKey& k) const { return k.i; }\n  size_t operator()(int k) const { return k; }\n};\nstruct NonMovableKeyEq {\n  using is_transparent = void;\n  bool operator()(const NonMovableKey& a, const NonMovableKey& b) const {\n    return a.i == b.i;\n  }\n  bool operator()(const NonMovableKey& a, int b) const { return a.i == b; }\n};\n\nTEST(NodeHashMap, MergeExtractInsert) {\n  absl::node_hash_map<NonMovableKey, int, NonMovableKeyHash, NonMovableKeyEq>\n      set1, set2;\n  set1.emplace(std::piecewise_construct, std::make_tuple(7),\n               std::make_tuple(-7));\n  set1.emplace(std::piecewise_construct, std::make_tuple(17),\n               std::make_tuple(-17));\n\n  set2.emplace(std::piecewise_construct, std::make_tuple(7),\n               std::make_tuple(-70));\n  set2.emplace(std::piecewise_construct, std::make_tuple(19),\n               std::make_tuple(-190));\n\n  auto Elem = [](int key, int value) {\n    return Pair(Field(&NonMovableKey::i, key), value);\n  };\n\n  EXPECT_THAT(set1, UnorderedElementsAre(Elem(7, -7), Elem(17, -17)));\n  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(19, -190)));\n\n  // NonMovableKey is neither copyable nor movable. We should still be able to\n  // move nodes around.\n  static_assert(!std::is_move_constructible<NonMovableKey>::value, \"\");\n  set1.merge(set2);\n\n  EXPECT_THAT(set1,\n              UnorderedElementsAre(Elem(7, -7), Elem(17, -17), Elem(19, -190)));\n  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70)));\n\n  auto node = set1.extract(7);\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.key().i, 7);\n  EXPECT_EQ(node.mapped(), -7);\n  EXPECT_THAT(set1, UnorderedElementsAre(Elem(17, -17), Elem(19, -190)));\n\n  auto insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_FALSE(insert_result.inserted);\n  EXPECT_TRUE(insert_result.node);\n  EXPECT_EQ(insert_result.node.key().i, 7);\n  EXPECT_EQ(insert_result.node.mapped(), -7);\n  EXPECT_THAT(*insert_result.position, Elem(7, -70));\n  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70)));\n\n  node = set1.extract(17);\n  EXPECT_TRUE(node);\n  EXPECT_EQ(node.key().i, 17);\n  EXPECT_EQ(node.mapped(), -17);\n  EXPECT_THAT(set1, UnorderedElementsAre(Elem(19, -190)));\n\n  node.mapped() = 23;\n\n  insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_TRUE(insert_result.inserted);\n  EXPECT_FALSE(insert_result.node);\n  EXPECT_THAT(*insert_result.position, Elem(17, 23));\n  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(17, 23)));\n}\n\nbool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; }\n\nTEST(NodeHashMap, EraseIf) {\n  // Erase all elements.\n  {\n    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return true; }), 5);\n    EXPECT_THAT(s, IsEmpty());\n  }\n  // Erase no elements.\n  {\n    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return false; }), 0);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),\n                                        Pair(4, 4), Pair(5, 5)));\n  }\n  // Erase specific elements.\n  {\n    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s,\n                       [](std::pair<const int, int> kvp) {\n                         return kvp.first % 2 == 1;\n                       }),\n              3);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));\n  }\n  // Predicate is function reference.\n  {\n    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, FirstIsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));\n  }\n  // Predicate is function pointer.\n  {\n    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};\n    EXPECT_EQ(erase_if(s, &FirstIsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));\n  }\n}\n\nTEST(NodeHashMap, CForEach) {\n  node_hash_map<int, int> m;\n  std::vector<std::pair<int, int>> expected;\n  for (int i = 0; i < 100; ++i) {\n    {\n      SCOPED_TRACE(\"mutable object iteration\");\n      std::vector<std::pair<int, int>> v;\n      absl::container_internal::c_for_each_fast(\n          m, [&v](std::pair<const int, int>& p) { v.push_back(p); });\n      EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const object iteration\");\n      std::vector<std::pair<int, int>> v;\n      const node_hash_map<int, int>& cm = m;\n      absl::container_internal::c_for_each_fast(\n          cm, [&v](const std::pair<const int, int>& p) { v.push_back(p); });\n      EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const object iteration\");\n      std::vector<std::pair<int, int>> v;\n      absl::container_internal::c_for_each_fast(\n          node_hash_map<int, int>(m),\n          [&v](std::pair<const int, int>& p) { v.push_back(p); });\n      EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    m[i] = i;\n    expected.emplace_back(i, i);\n  }\n}\n\nTEST(NodeHashMap, CForEachMutate) {\n  node_hash_map<int, int> s;\n  std::vector<std::pair<int, int>> expected;\n  for (int i = 0; i < 100; ++i) {\n    std::vector<std::pair<int, int>> v;\n    absl::container_internal::c_for_each_fast(\n        s, [&v](std::pair<const int, int>& p) {\n          v.push_back(p);\n          p.second++;\n        });\n    EXPECT_THAT(v, UnorderedElementsAreArray(expected));\n    for (auto& p : expected) {\n      p.second++;\n    }\n    EXPECT_THAT(s, UnorderedElementsAreArray(expected));\n    s[i] = i;\n    expected.emplace_back(i, i);\n  }\n}\n\nTEST(NodeHashMap, NodeHandleMutableKeyAccess) {\n  node_hash_map<std::string, std::string> map;\n\n  map[\"key1\"] = \"mapped\";\n\n  auto nh = map.extract(map.begin());\n  nh.key().resize(3);\n  map.insert(std::move(nh));\n\n  EXPECT_THAT(map, testing::ElementsAre(Pair(\"key\", \"mapped\")));\n}\n\nTEST(NodeHashMap, RecursiveTypeCompiles) {\n  struct RecursiveType {\n    node_hash_map<int, RecursiveType> m;\n  };\n  RecursiveType t;\n  t.m[0] = RecursiveType{};\n}\n\n#if defined(__cpp_lib_containers_ranges) && \\\n    __cpp_lib_containers_ranges >= 202202L\nTEST(NodeHashMap, FromRange) {\n  std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};\n  absl::node_hash_map<int, int> m(std::from_range, v);\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));\n}\n\nTEST(NodeHashMap, FromRangeWithAllocator) {\n  std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};\n  absl::node_hash_map<int, int,\n                      absl::container_internal::hash_default_hash<int>,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<std::pair<const int, int>>>\n      m(std::from_range, v, 0, Alloc<std::pair<const int, int>>());\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));\n}\n\nTEST(NodeHashMap, FromRangeWithHasherAndAllocator) {\n  std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};\n  using TestingHash = absl::container_internal::StatefulTestingHash;\n  absl::node_hash_map<int, int, TestingHash,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<std::pair<const int, int>>>\n      m(std::from_range, v, 0, TestingHash{},\n        Alloc<std::pair<const int, int>>());\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));\n}\n#endif\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/node_hash_set.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: node_hash_set.h\n// -----------------------------------------------------------------------------\n//\n// An `absl::node_hash_set<T>` is an unordered associative container designed to\n// be a more efficient replacement for `std::unordered_set`. Like\n// `unordered_set`, search, insertion, and deletion of set elements can be done\n// as an `O(1)` operation. However, `node_hash_set` (and other unordered\n// associative containers known as the collection of Abseil \"Swiss tables\")\n// contain other optimizations that result in both memory and computation\n// advantages.\n//\n// In most cases, your default choice for a hash table should be a map of type\n// `flat_hash_map` or a set of type `flat_hash_set`. However, if you need\n// pointer stability, a `node_hash_set` should be your preferred choice. As\n// well, if you are migrating your code from using `std::unordered_set`, a\n// `node_hash_set` should be an easy migration. Consider migrating to\n// `node_hash_set` and perhaps converting to a more efficient `flat_hash_set`\n// upon further review.\n//\n// `node_hash_set` is not exception-safe.\n\n#ifndef ABSL_CONTAINER_NODE_HASH_SET_H_\n#define ABSL_CONTAINER_NODE_HASH_SET_H_\n\n#include <cstddef>\n#include <memory>\n#include <type_traits>\n\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/container/hash_container_defaults.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/container/internal/node_slot_policy.h\"\n#include \"absl/container/internal/raw_hash_set.h\"  // IWYU pragma: export\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\ntemplate <typename T>\nstruct NodeHashSetPolicy;\n}  // namespace container_internal\n\n// -----------------------------------------------------------------------------\n// absl::node_hash_set\n// -----------------------------------------------------------------------------\n//\n// An `absl::node_hash_set<T>` is an unordered associative container which\n// has been optimized for both speed and memory footprint in most common use\n// cases. Its interface is similar to that of `std::unordered_set<T>` with the\n// following notable differences:\n//\n// * Supports heterogeneous lookup, through `find()`, `operator[]()` and\n//   `insert()`, provided that the set is provided a compatible heterogeneous\n//   hashing function and equality operator. See below for details.\n// * Contains a `capacity()` member function indicating the number of element\n//   slots (open, deleted, and empty) within the hash set.\n// * Returns `void` from the `erase(iterator)` overload.\n//\n// By default, `node_hash_set` uses the `absl::Hash` hashing framework.\n// All fundamental and Abseil types that support the `absl::Hash` framework have\n// a compatible equality operator for comparing insertions into `node_hash_set`.\n// If your type is not yet supported by the `absl::Hash` framework, see\n// absl/hash/hash.h for information on extending Abseil hashing to user-defined\n// types.\n//\n// Using `absl::node_hash_set` at interface boundaries in dynamically loaded\n// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may\n// be randomized across dynamically loaded libraries.\n//\n// To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type\n// parameters can be used or `T` should have public inner types\n// `absl_container_hash` and (optionally) `absl_container_eq`. In either case,\n// `typename Hash::is_transparent` and `typename Eq::is_transparent` should be\n// well-formed. Both types are basically functors:\n// * `Hash` should support `size_t operator()(U val) const` that returns a hash\n// for the given `val`.\n// * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true\n// if `lhs` is equal to `rhs`.\n//\n// In most cases `T` needs only to provide the `absl_container_hash`. In this\n// case `std::equal_to<void>` will be used instead of `eq` part.\n//\n// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:\n//  * Iteration takes O(capacity) time, not O(size).\n//  * erase() slows down begin() and ++iterator.\n//  * Capacity only shrinks on rehash() or clear() -- not on erase().\n//\n// Example:\n//\n//   // Create a node hash set of three strings\n//   absl::node_hash_set<std::string> ducks =\n//     {\"huey\", \"dewey\", \"louie\"};\n//\n//   // Insert a new element into the node hash set\n//   ducks.insert(\"donald\");\n//\n//   // Force a rehash of the node hash set\n//   ducks.rehash(0);\n//\n//   // See if \"dewey\" is present\n//   if (ducks.contains(\"dewey\")) {\n//     std::cout << \"We found dewey!\" << std::endl;\n//   }\ntemplate <\n    class T,\n    class Hash = typename container_internal::NodeHashSetPolicy<T>::DefaultHash,\n    class Eq = typename container_internal::NodeHashSetPolicy<T>::DefaultEq,\n    class Alloc =\n        typename container_internal::NodeHashSetPolicy<T>::DefaultAlloc>\nclass ABSL_ATTRIBUTE_OWNER node_hash_set\n    : public absl::container_internal::InstantiateRawHashSet<\n          absl::container_internal::NodeHashSetPolicy<T>, Hash, Eq,\n          Alloc>::type {\n  using Base = typename node_hash_set::raw_hash_set;\n\n public:\n  // Constructors and Assignment Operators\n  //\n  // A node_hash_set supports the same overload set as `std::unordered_set`\n  // for construction and assignment:\n  //\n  // *  Default constructor\n  //\n  //    // No allocation for the table's elements is made.\n  //    absl::node_hash_set<std::string> set1;\n  //\n  // * Initializer List constructor\n  //\n  //   absl::node_hash_set<std::string> set2 =\n  //       {{\"huey\"}, {\"dewey\"}, {\"louie\"}};\n  //\n  // * Copy constructor\n  //\n  //   absl::node_hash_set<std::string> set3(set2);\n  //\n  // * Copy assignment operator\n  //\n  //   // Hash functor and Comparator are copied as well\n  //   absl::node_hash_set<std::string> set4;\n  //   set4 = set3;\n  //\n  // * Move constructor\n  //\n  //   // Move is guaranteed efficient\n  //   absl::node_hash_set<std::string> set5(std::move(set4));\n  //\n  // * Move assignment operator\n  //\n  //   // May be efficient if allocators are compatible\n  //   absl::node_hash_set<std::string> set6;\n  //   set6 = std::move(set5);\n  //\n  // * Range constructor\n  //\n  //   std::vector<std::string> v = {\"a\", \"b\"};\n  //   absl::node_hash_set<std::string> set7(v.begin(), v.end());\n  //\n  // * from_range constructor (C++23)\n  //\n  //   std::vector<std::string> v = {\"a\", \"b\"};\n  //   absl::node_hash_set<std::string> set8(std::from_range, v);\n  node_hash_set() {}\n  using Base::Base;\n\n  // node_hash_set::begin()\n  //\n  // Returns an iterator to the beginning of the `node_hash_set`.\n  using Base::begin;\n\n  // node_hash_set::cbegin()\n  //\n  // Returns a const iterator to the beginning of the `node_hash_set`.\n  using Base::cbegin;\n\n  // node_hash_set::cend()\n  //\n  // Returns a const iterator to the end of the `node_hash_set`.\n  using Base::cend;\n\n  // node_hash_set::end()\n  //\n  // Returns an iterator to the end of the `node_hash_set`.\n  using Base::end;\n\n  // node_hash_set::capacity()\n  //\n  // Returns the number of element slots (assigned, deleted, and empty)\n  // available within the `node_hash_set`.\n  //\n  // NOTE: this member function is particular to `absl::node_hash_set` and is\n  // not provided in the `std::unordered_set` API.\n  using Base::capacity;\n\n  // node_hash_set::empty()\n  //\n  // Returns whether or not the `node_hash_set` is empty.\n  using Base::empty;\n\n  // node_hash_set::max_size()\n  //\n  // Returns the largest theoretical possible number of elements within a\n  // `node_hash_set` under current memory constraints. This value can be thought\n  // of the largest value of `std::distance(begin(), end())` for a\n  // `node_hash_set<T>`.\n  using Base::max_size;\n\n  // node_hash_set::size()\n  //\n  // Returns the number of elements currently within the `node_hash_set`.\n  using Base::size;\n\n  // node_hash_set::clear()\n  //\n  // Removes all elements from the `node_hash_set`. Invalidates any references,\n  // pointers, or iterators referring to contained elements.\n  //\n  // NOTE: this operation may shrink the underlying buffer. To avoid shrinking\n  // the underlying buffer call `erase(begin(), end())`.\n  using Base::clear;\n\n  // node_hash_set::erase()\n  //\n  // Erases elements within the `node_hash_set`. Erasing does not trigger a\n  // rehash. Overloads are listed below.\n  //\n  // void erase(const_iterator pos):\n  //\n  //   Erases the element at `position` of the `node_hash_set`, returning\n  //   `void`.\n  //\n  //   NOTE: Returning `void` in this case is different than that of STL\n  //   containers in general and `std::unordered_map` in particular (which\n  //   return an iterator to the element following the erased element). If that\n  //   iterator is needed, simply post increment the iterator:\n  //\n  //     map.erase(it++);\n  //\n  //\n  // iterator erase(const_iterator first, const_iterator last):\n  //\n  //   Erases the elements in the open interval [`first`, `last`), returning an\n  //   iterator pointing to `last`. The special case of calling\n  //   `erase(begin(), end())` resets the reserved growth such that if\n  //   `reserve(N)` has previously been called and there has been no intervening\n  //   call to `clear()`, then after calling `erase(begin(), end())`, it is safe\n  //   to assume that inserting N elements will not cause a rehash.\n  //\n  // size_type erase(const key_type& key):\n  //\n  //   Erases the element with the matching key, if it exists, returning the\n  //   number of elements erased (0 or 1).\n  using Base::erase;\n\n  // node_hash_set::insert()\n  //\n  // Inserts an element of the specified value into the `node_hash_set`,\n  // returning an iterator pointing to the newly inserted element, provided that\n  // an element with the given key does not already exist. If rehashing occurs\n  // due to the insertion, all iterators are invalidated. Overloads are listed\n  // below.\n  //\n  // std::pair<iterator,bool> insert(const T& value):\n  //\n  //   Inserts a value into the `node_hash_set`. Returns a pair consisting of an\n  //   iterator to the inserted element (or to the element that prevented the\n  //   insertion) and a bool denoting whether the insertion took place.\n  //\n  // std::pair<iterator,bool> insert(T&& value):\n  //\n  //   Inserts a moveable value into the `node_hash_set`. Returns a pair\n  //   consisting of an iterator to the inserted element (or to the element that\n  //   prevented the insertion) and a bool denoting whether the insertion took\n  //   place.\n  //\n  // iterator insert(const_iterator hint, const T& value):\n  // iterator insert(const_iterator hint, T&& value):\n  //\n  //   Inserts a value, using the position of `hint` as a non-binding suggestion\n  //   for where to begin the insertion search. Returns an iterator to the\n  //   inserted element, or to the existing element that prevented the\n  //   insertion.\n  //\n  // void insert(InputIterator first, InputIterator last):\n  //\n  //   Inserts a range of values [`first`, `last`).\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently, for `node_hash_set` we guarantee the\n  //   first match is inserted.\n  //\n  // void insert(std::initializer_list<T> ilist):\n  //\n  //   Inserts the elements within the initializer list `ilist`.\n  //\n  //   NOTE: Although the STL does not specify which element may be inserted if\n  //   multiple keys compare equivalently within the initializer list, for\n  //   `node_hash_set` we guarantee the first match is inserted.\n  using Base::insert;\n\n  // node_hash_set::emplace()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `node_hash_set`, provided that no element with the given key\n  // already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace;\n\n  // node_hash_set::emplace_hint()\n  //\n  // Inserts an element of the specified value by constructing it in-place\n  // within the `node_hash_set`, using the position of `hint` as a non-binding\n  // suggestion for where to begin the insertion search, and only inserts\n  // provided that no element with the given key already exists.\n  //\n  // The element may be constructed even if there already is an element with the\n  // key in the container, in which case the newly constructed element will be\n  // destroyed immediately.\n  //\n  // If rehashing occurs due to the insertion, all iterators are invalidated.\n  using Base::emplace_hint;\n\n  // node_hash_set::extract()\n  //\n  // Extracts the indicated element, erasing it in the process, and returns it\n  // as a C++17-compatible node handle. Overloads are listed below.\n  //\n  // node_type extract(const_iterator position):\n  //\n  //   Extracts the element at the indicated position and returns a node handle\n  //   owning that extracted data.\n  //\n  // node_type extract(const key_type& x):\n  //\n  //   Extracts the element with the key matching the passed key value and\n  //   returns a node handle owning that extracted data. If the `node_hash_set`\n  //   does not contain an element with a matching key, this function returns an\n  // empty node handle.\n  using Base::extract;\n\n  // node_hash_set::merge()\n  //\n  // Extracts elements from a given `source` node hash set into this\n  // `node_hash_set`. If the destination `node_hash_set` already contains an\n  // element with an equivalent key, that element is not extracted.\n  using Base::merge;\n\n  // node_hash_set::swap(node_hash_set& other)\n  //\n  // Exchanges the contents of this `node_hash_set` with those of the `other`\n  // node hash set.\n  //\n  // All iterators and references on the `node_hash_set` remain valid, excepting\n  // for the past-the-end iterator, which is invalidated.\n  //\n  // `swap()` requires that the node hash set's hashing and key equivalence\n  // functions be Swappable, and are exchanged using unqualified calls to\n  // non-member `swap()`. If the set's allocator has\n  // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`\n  // set to `true`, the allocators are also exchanged using an unqualified call\n  // to non-member `swap()`; otherwise, the allocators are not swapped.\n  using Base::swap;\n\n  // node_hash_set::rehash(count)\n  //\n  // Rehashes the `node_hash_set`, setting the number of slots to be at least\n  // the passed value. If the new number of slots increases the load factor more\n  // than the current maximum load factor\n  // (`count` < `size()` / `max_load_factor()`), then the new number of slots\n  // will be at least `size()` / `max_load_factor()`.\n  //\n  // To force a rehash, pass rehash(0).\n  //\n  // NOTE: unlike behavior in `std::unordered_set`, references are also\n  // invalidated upon a `rehash()`.\n  using Base::rehash;\n\n  // node_hash_set::reserve(count)\n  //\n  // Sets the number of slots in the `node_hash_set` to the number needed to\n  // accommodate at least `count` total elements without exceeding the current\n  // maximum load factor, and may rehash the container if needed. After this\n  // returns, it is guaranteed that `count - size()` elements can be inserted\n  // into the `node_hash_set` without another rehash.\n  using Base::reserve;\n\n  // node_hash_set::contains()\n  //\n  // Determines whether an element comparing equal to the given `key` exists\n  // within the `node_hash_set`, returning `true` if so or `false` otherwise.\n  using Base::contains;\n\n  // node_hash_set::count(const Key& key) const\n  //\n  // Returns the number of elements comparing equal to the given `key` within\n  // the `node_hash_set`. note that this function will return either `1` or `0`\n  // since duplicate elements are not allowed within a `node_hash_set`.\n  using Base::count;\n\n  // node_hash_set::equal_range()\n  //\n  // Returns a closed range [first, last], defined by a `std::pair` of two\n  // iterators, containing all elements with the passed key in the\n  // `node_hash_set`.\n  using Base::equal_range;\n\n  // node_hash_set::find()\n  //\n  // Finds an element with the passed `key` within the `node_hash_set`.\n  using Base::find;\n\n  // node_hash_set::bucket_count()\n  //\n  // Returns the number of \"buckets\" within the `node_hash_set`. Note that\n  // because a node hash set contains all elements within its internal storage,\n  // this value simply equals the current capacity of the `node_hash_set`.\n  using Base::bucket_count;\n\n  // node_hash_set::load_factor()\n  //\n  // Returns the current load factor of the `node_hash_set` (the average number\n  // of slots occupied with a value within the hash set).\n  using Base::load_factor;\n\n  // node_hash_set::max_load_factor()\n  //\n  // Manages the maximum load factor of the `node_hash_set`. Overloads are\n  // listed below.\n  //\n  // float node_hash_set::max_load_factor()\n  //\n  //   Returns the current maximum load factor of the `node_hash_set`.\n  //\n  // void node_hash_set::max_load_factor(float ml)\n  //\n  //   Sets the maximum load factor of the `node_hash_set` to the passed value.\n  //\n  //   NOTE: This overload is provided only for API compatibility with the STL;\n  //   `node_hash_set` will ignore any set load factor and manage its rehashing\n  //   internally as an implementation detail.\n  using Base::max_load_factor;\n\n  // node_hash_set::get_allocator()\n  //\n  // Returns the allocator function associated with this `node_hash_set`.\n  using Base::get_allocator;\n\n  // node_hash_set::hash_function()\n  //\n  // Returns the hashing function used to hash the keys within this\n  // `node_hash_set`.\n  using Base::hash_function;\n\n  // node_hash_set::key_eq()\n  //\n  // Returns the function used for comparing keys equality.\n  using Base::key_eq;\n};\n\n// erase_if(node_hash_set<>, Pred)\n//\n// Erases all elements that satisfy the predicate `pred` from the container `c`.\n// Returns the number of erased elements.\ntemplate <typename T, typename H, typename E, typename A, typename Predicate>\ntypename node_hash_set<T, H, E, A>::size_type erase_if(\n    node_hash_set<T, H, E, A>& c, Predicate pred) {\n  return container_internal::EraseIf(pred, &c);\n}\n\n// swap(node_hash_set<>, node_hash_set<>)\n//\n// Swaps the contents of two `node_hash_set` containers.\n//\n// NOTE: we need to define this function template in order for\n// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we\n// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a\n// derived-to-base conversion, whereas `std::swap` is a function template so\n// `std::swap` will be preferred by compiler.\ntemplate <typename T, typename H, typename E, typename A>\nvoid swap(node_hash_set<T, H, E, A>& x,\n          node_hash_set<T, H, E, A>& y) noexcept(noexcept(x.swap(y))) {\n  return x.swap(y);\n}\n\nnamespace container_internal {\n\n// c_for_each_fast(node_hash_set<>, Function)\n//\n// Container-based version of the <algorithm> `std::for_each()` function to\n// apply a function to a container's elements.\n// There is no guarantees on the order of the function calls.\n// Erasure and/or insertion of elements in the function is not allowed.\ntemplate <typename T, typename H, typename E, typename A, typename Function>\ndecay_t<Function> c_for_each_fast(const node_hash_set<T, H, E, A>& c,\n                                  Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename T, typename H, typename E, typename A, typename Function>\ndecay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>& c, Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\ntemplate <typename T, typename H, typename E, typename A, typename Function>\ndecay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>&& c, Function&& f) {\n  container_internal::ForEach(f, &c);\n  return f;\n}\n\n}  // namespace container_internal\n\nnamespace container_internal {\n\ntemplate <class T>\nstruct NodeHashSetPolicy\n    : absl::container_internal::node_slot_policy<T&, NodeHashSetPolicy<T>> {\n  using key_type = T;\n  using init_type = T;\n  using constant_iterators = std::true_type;\n\n  using DefaultHash = DefaultHashContainerHash<T>;\n  using DefaultEq = DefaultHashContainerEq<T>;\n  using DefaultAlloc = std::allocator<T>;\n\n  template <class Allocator, class... Args>\n  static T* new_element(Allocator* alloc, Args&&... args) {\n    using ValueAlloc =\n        typename absl::allocator_traits<Allocator>::template rebind_alloc<T>;\n    ValueAlloc value_alloc(*alloc);\n    T* res = absl::allocator_traits<ValueAlloc>::allocate(value_alloc, 1);\n    absl::allocator_traits<ValueAlloc>::construct(value_alloc, res,\n                                                  std::forward<Args>(args)...);\n    return res;\n  }\n\n  template <class Allocator>\n  static void delete_element(Allocator* alloc, T* elem) {\n    using ValueAlloc =\n        typename absl::allocator_traits<Allocator>::template rebind_alloc<T>;\n    ValueAlloc value_alloc(*alloc);\n    absl::allocator_traits<ValueAlloc>::destroy(value_alloc, elem);\n    absl::allocator_traits<ValueAlloc>::deallocate(value_alloc, elem, 1);\n  }\n\n  template <class F, class... Args>\n  static decltype(absl::container_internal::DecomposeValue(\n      std::declval<F>(), std::declval<Args>()...))\n  apply(F&& f, Args&&... args) {\n    return absl::container_internal::DecomposeValue(\n        std::forward<F>(f), std::forward<Args>(args)...);\n  }\n\n  static size_t element_space_used(const T*) { return sizeof(T); }\n\n  template <class Hash, bool kIsDefault>\n  static constexpr HashSlotFn get_hash_slot_fn() {\n    return &TypeErasedDerefAndApplyToSlotFn<Hash, T, kIsDefault>;\n  }\n};\n}  // namespace container_internal\n\nnamespace container_algorithm_internal {\n\n// Specialization of trait in absl/algorithm/container.h\ntemplate <class Key, class Hash, class KeyEqual, class Allocator>\nstruct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>>\n    : std::true_type {};\n\n}  // namespace container_algorithm_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CONTAINER_NODE_HASH_SET_H_\n"
  },
  {
    "path": "absl/container/node_hash_set_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/container/node_hash_set.h\"\n\n#include <cstddef>\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hash_generator_testing.h\"\n#include \"absl/container/internal/hash_policy_testing.h\"\n#include \"absl/container/internal/unordered_set_constructor_test.h\"\n#include \"absl/container/internal/unordered_set_lookup_test.h\"\n#include \"absl/container/internal/unordered_set_members_test.h\"\n#include \"absl/container/internal/unordered_set_modifiers_test.h\"\n#include \"absl/memory/memory.h\"\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <ranges>  // NOLINT(build/c++20)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\nusing ::testing::IsEmpty;\nusing ::testing::Pointee;\nusing ::testing::UnorderedElementsAre;\nusing ::testing::UnorderedElementsAreArray;\n\nusing SetTypes = ::testing::Types<\n    node_hash_set<int, StatefulTestingHash, StatefulTestingEqual, Alloc<int>>,\n    node_hash_set<std::string, StatefulTestingHash, StatefulTestingEqual,\n                  Alloc<std::string>>,\n    node_hash_set<Enum, StatefulTestingHash, StatefulTestingEqual, Alloc<Enum>>,\n    node_hash_set<EnumClass, StatefulTestingHash, StatefulTestingEqual,\n                  Alloc<EnumClass>>>;\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ConstructorTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, LookupTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, MembersTest, SetTypes);\nINSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ModifiersTest, SetTypes);\n\nTEST(NodeHashSet, MoveableNotCopyableCompiles) {\n  node_hash_set<std::unique_ptr<void*>> t;\n  node_hash_set<std::unique_ptr<void*>> u;\n  u = std::move(t);\n}\n\nTEST(NodeHashSet, MergeExtractInsert) {\n  struct Hash {\n    size_t operator()(const std::unique_ptr<int>& p) const { return *p; }\n  };\n  struct Eq {\n    bool operator()(const std::unique_ptr<int>& a,\n                    const std::unique_ptr<int>& b) const {\n      return *a == *b;\n    }\n  };\n  absl::node_hash_set<std::unique_ptr<int>, Hash, Eq> set1, set2;\n  set1.insert(absl::make_unique<int>(7));\n  set1.insert(absl::make_unique<int>(17));\n\n  set2.insert(absl::make_unique<int>(7));\n  set2.insert(absl::make_unique<int>(19));\n\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17)));\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(19)));\n\n  set1.merge(set2);\n\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(7), Pointee(17), Pointee(19)));\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7)));\n\n  auto node = set1.extract(absl::make_unique<int>(7));\n  EXPECT_TRUE(node);\n  EXPECT_THAT(node.value(), Pointee(7));\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(17), Pointee(19)));\n\n  auto insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_FALSE(insert_result.inserted);\n  EXPECT_TRUE(insert_result.node);\n  EXPECT_THAT(insert_result.node.value(), Pointee(7));\n  EXPECT_EQ(**insert_result.position, 7);\n  EXPECT_NE(insert_result.position->get(), insert_result.node.value().get());\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7)));\n\n  node = set1.extract(absl::make_unique<int>(17));\n  EXPECT_TRUE(node);\n  EXPECT_THAT(node.value(), Pointee(17));\n  EXPECT_THAT(set1, UnorderedElementsAre(Pointee(19)));\n\n  node.value() = absl::make_unique<int>(23);\n\n  insert_result = set2.insert(std::move(node));\n  EXPECT_FALSE(node);\n  EXPECT_TRUE(insert_result.inserted);\n  EXPECT_FALSE(insert_result.node);\n  EXPECT_EQ(**insert_result.position, 23);\n  EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));\n}\n\nbool IsEven(int k) { return k % 2 == 0; }\n\nTEST(NodeHashSet, EraseIf) {\n  // Erase all elements.\n  {\n    node_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, [](int) { return true; }), 5);\n    EXPECT_THAT(s, IsEmpty());\n  }\n  // Erase no elements.\n  {\n    node_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, [](int) { return false; }), 0);\n    EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n  }\n  // Erase specific elements.\n  {\n    node_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, [](int k) { return k % 2 == 1; }), 3);\n    EXPECT_THAT(s, UnorderedElementsAre(2, 4));\n  }\n  // Predicate is function reference.\n  {\n    node_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, IsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));\n  }\n  // Predicate is function pointer.\n  {\n    node_hash_set<int> s = {1, 2, 3, 4, 5};\n    EXPECT_EQ(erase_if(s, &IsEven), 2);\n    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));\n  }\n}\n\nTEST(NodeHashSet, CForEach) {\n  using ValueType = std::pair<int, int>;\n  node_hash_set<ValueType> s;\n  std::vector<ValueType> expected;\n  for (int i = 0; i < 100; ++i) {\n    {\n      SCOPED_TRACE(\"mutable object iteration\");\n      std::vector<ValueType> v;\n      absl::container_internal::c_for_each_fast(\n          s, [&v](const ValueType& p) { v.push_back(p); });\n      ASSERT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"const object iteration\");\n      std::vector<ValueType> v;\n      const node_hash_set<ValueType>& cs = s;\n      absl::container_internal::c_for_each_fast(\n          cs, [&v](const ValueType& p) { v.push_back(p); });\n      ASSERT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    {\n      SCOPED_TRACE(\"temporary object iteration\");\n      std::vector<ValueType> v;\n      absl::container_internal::c_for_each_fast(\n          node_hash_set<ValueType>(s),\n          [&v](const ValueType& p) { v.push_back(p); });\n      ASSERT_THAT(v, UnorderedElementsAreArray(expected));\n    }\n    s.emplace(i, i);\n    expected.emplace_back(i, i);\n  }\n}\n\n#if defined(__cpp_lib_containers_ranges) && \\\n    __cpp_lib_containers_ranges >= 202202L\nTEST(NodeHashSet, FromRange) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  absl::node_hash_set<int> s(std::from_range, v);\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(NodeHashSet, FromRangeWithAllocator) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  absl::node_hash_set<int, absl::container_internal::hash_default_hash<int>,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<int>>\n      s(std::from_range, v, 0, Alloc<int>());\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n\nTEST(NodeHashSet, FromRangeWithHasherAndAllocator) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  using TestingHash = absl::container_internal::StatefulTestingHash;\n  absl::node_hash_set<int, TestingHash,\n                      absl::container_internal::hash_default_eq<int>,\n                      Alloc<int>>\n      s(std::from_range, v, 0, TestingHash{}, Alloc<int>());\n  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));\n}\n#endif\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/container/sample_element_size_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/container/internal/hashtablez_sampler.h\"\n#include \"absl/container/node_hash_map.h\"\n#include \"absl/container/node_hash_set.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace container_internal {\nnamespace {\n\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n// Create some tables of type `Table`, then look at all the new\n// `HashtablezInfo`s to make sure that the `inline_element_size ==\n// expected_element_size`.  The `inline_element_size` is the amount of memory\n// allocated for each slot of a hash table, that is `sizeof(slot_type)`.  Add\n// the new `HashtablezInfo`s to `preexisting_info`.  Store all the new tables\n// into `tables`.\ntemplate <class Table>\nvoid TestInlineElementSize(\n    HashtablezSampler& sampler,\n    // clang-tidy gives a false positive on this declaration.  This unordered\n    // set cannot be flat_hash_set, however, since that would introduce a mutex\n    // deadlock.\n    std::unordered_set<const HashtablezInfo*>& preexisting_info,  // NOLINT\n    std::vector<Table>& tables,\n    const std::vector<typename Table::value_type>& values,\n    size_t expected_element_size) {\n  EXPECT_GT(values.size(), 0);\n  for (int i = 0; i < 10; ++i) {\n    // We create a new table and must store it somewhere so that when we store\n    // a pointer to the resulting `HashtablezInfo` into `preexisting_info`\n    // that we aren't storing a dangling pointer.\n    tables.emplace_back();\n    // We must insert elements to get a hashtablez to instantiate.\n    tables.back().insert(values.begin(), values.end());\n  }\n  size_t new_count = 0;\n  sampler.Iterate([&](const HashtablezInfo& info) {\n    if (preexisting_info.insert(&info).second) {\n      EXPECT_EQ(info.inline_element_size, expected_element_size);\n      ++new_count;\n    }\n  });\n  // Make sure we actually did get a new hashtablez.\n  EXPECT_GT(new_count, 0);\n}\n\nstruct bigstruct {\n  char a[1000];\n  friend bool operator==(const bigstruct& x, const bigstruct& y) {\n    return memcmp(x.a, y.a, sizeof(x.a)) == 0;\n  }\n  template <typename H>\n  friend H AbslHashValue(H h, const bigstruct& c) {\n    return H::combine_contiguous(std::move(h), c.a, sizeof(c.a));\n  }\n};\n#endif\n\nTEST(FlatHashMap, SampleElementSize) {\n#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)\n  // Enable sampling even if the prod default is off.\n  SetHashtablezEnabled(true);\n  SetHashtablezSampleParameter(1);\n  TestOnlyRefreshSamplingStateForCurrentThread();\n\n  auto& sampler = GlobalHashtablezSampler();\n  std::vector<flat_hash_map<int, bigstruct>> flat_map_tables;\n  std::vector<flat_hash_set<bigstruct>> flat_set_tables;\n  std::vector<node_hash_map<int, bigstruct>> node_map_tables;\n  std::vector<node_hash_set<bigstruct>> node_set_tables;\n  std::vector<bigstruct> set_values = {bigstruct{{0}}, bigstruct{{1}}};\n  std::vector<std::pair<const int, bigstruct>> map_values = {{0, bigstruct{}},\n                                                             {1, bigstruct{}}};\n\n  // clang-tidy gives a false positive on this declaration.  This unordered set\n  // cannot be a flat_hash_set, however, since that would introduce a mutex\n  // deadlock.\n  std::unordered_set<const HashtablezInfo*> preexisting_info;  // NOLINT\n  sampler.Iterate(\n      [&](const HashtablezInfo& info) { preexisting_info.insert(&info); });\n  TestInlineElementSize(sampler, preexisting_info, flat_map_tables, map_values,\n                        sizeof(int) + sizeof(bigstruct));\n  TestInlineElementSize(sampler, preexisting_info, node_map_tables, map_values,\n                        sizeof(void*));\n  TestInlineElementSize(sampler, preexisting_info, flat_set_tables, set_values,\n                        sizeof(bigstruct));\n  TestInlineElementSize(sampler, preexisting_info, node_set_tables, set_values,\n                        sizeof(void*));\n#endif\n}\n\n}  // namespace\n}  // namespace container_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/copts/AbseilConfigureCopts.cmake",
    "content": "# See absl/copts/copts.py and absl/copts/generate_copts.py\ninclude(GENERATED_AbseilCopts)\n\nset(ABSL_DEFAULT_LINKOPTS \"\")\n\nif (BUILD_SHARED_LIBS AND (MSVC OR ABSL_BUILD_MONOLITHIC_SHARED_LIBS))\n  set(ABSL_BUILD_DLL TRUE)\n  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)\nelse()\n  set(ABSL_BUILD_DLL FALSE)\nendif()\n\nif(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES [[Clang]])\n  # Some CMake targets (not known at the moment of processing) could be set to\n  # compile for multiple architectures as specified by the OSX_ARCHITECTURES\n  # property, which is target-specific.  We should neither inspect nor rely on\n  # any CMake property or variable to detect an architecture, in particular:\n  #\n  #   - CMAKE_OSX_ARCHITECTURES\n  #     is just an initial value for OSX_ARCHITECTURES; set too early.\n  #\n  #   - OSX_ARCHITECTURES\n  #     is a per-target property; targets could be defined later, and their\n  #     properties could be modified any time later.\n  #\n  #   - CMAKE_SYSTEM_PROCESSOR\n  #     does not reflect multiple architectures at all.\n  #\n  # When compiling for multiple architectures, a build system can invoke a\n  # compiler either\n  #\n  #   - once: a single command line for multiple architectures (Ninja build)\n  #   - twice: two command lines per each architecture (Xcode build system)\n  #\n  # If case of Xcode, it would be possible to set an Xcode-specific attributes\n  # like XCODE_ATTRIBUTE_OTHER_CPLUSPLUSFLAGS[arch=arm64] or similar.\n  #\n  # In both cases, the viable strategy is to pass all arguments at once, allowing\n  # the compiler to dispatch arch-specific arguments to a designated backend.\n  set(ABSL_RANDOM_RANDEN_COPTS \"\")\n  foreach(_arch IN ITEMS \"x86_64\" \"arm64\")\n    string(TOUPPER \"${_arch}\" _arch_uppercase)\n    string(REPLACE \"X86_64\" \"X64\" _arch_uppercase ${_arch_uppercase})\n    foreach(_flag IN LISTS ABSL_RANDOM_HWAES_${_arch_uppercase}_FLAGS)\n      list(APPEND ABSL_RANDOM_RANDEN_COPTS \"SHELL:-Xarch_${_arch} ${_flag}\")\n    endforeach()\n  endforeach()\n  # If a compiler happens to deal with an argument for a currently unused\n  # architecture, it will warn about an unused command line argument.\n  option(ABSL_RANDOM_RANDEN_COPTS_WARNING OFF\n         \"Warn if one of ABSL_RANDOM_RANDEN_COPTS is unused\")\n  if(ABSL_RANDOM_RANDEN_COPTS AND NOT ABSL_RANDOM_RANDEN_COPTS_WARNING)\n    list(APPEND ABSL_RANDOM_RANDEN_COPTS \"-Wno-unused-command-line-argument\")\n  endif()\nelseif(CMAKE_SYSTEM_PROCESSOR MATCHES \"x86_64|amd64|AMD64\")\n  if (MSVC)\n    set(ABSL_RANDOM_RANDEN_COPTS \"${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}\")\n  else()\n    set(ABSL_RANDOM_RANDEN_COPTS \"${ABSL_RANDOM_HWAES_X64_FLAGS}\")\n  endif()\nelseif(CMAKE_SYSTEM_PROCESSOR MATCHES \"arm.*|aarch64\")\n  if (CMAKE_SIZEOF_VOID_P STREQUAL \"8\")\n    set(ABSL_RANDOM_RANDEN_COPTS \"${ABSL_RANDOM_HWAES_ARM64_FLAGS}\")\n  elseif(CMAKE_SIZEOF_VOID_P STREQUAL \"4\")\n    set(ABSL_RANDOM_RANDEN_COPTS \"${ABSL_RANDOM_HWAES_ARM32_FLAGS}\")\n  else()\n    message(WARNING \"Value of CMAKE_SIZEOF_VOID_P (${CMAKE_SIZEOF_VOID_P}) is not supported.\")\n  endif()\nelse()\n  set(ABSL_RANDOM_RANDEN_COPTS \"\")\nendif()\n\n\nif(CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_CXX_COMPILER_ID STREQUAL \"QCC\")\n  set(ABSL_DEFAULT_COPTS \"${ABSL_GCC_FLAGS}\")\n  set(ABSL_TEST_COPTS \"${ABSL_GCC_TEST_FLAGS}\")\nelseif(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")  # MATCHES so we get both Clang and AppleClang\n  if(MSVC)\n    # clang-cl is half MSVC, half LLVM\n    set(ABSL_DEFAULT_COPTS \"${ABSL_CLANG_CL_FLAGS}\")\n    set(ABSL_TEST_COPTS \"${ABSL_CLANG_CL_TEST_FLAGS}\")\n  else()\n    set(ABSL_DEFAULT_COPTS \"${ABSL_LLVM_FLAGS}\")\n    set(ABSL_TEST_COPTS \"${ABSL_LLVM_TEST_FLAGS}\")\n  endif()\nelseif(CMAKE_CXX_COMPILER_ID STREQUAL \"IntelLLVM\")\n  # IntelLLVM is similar to Clang, with some additional flags.\n  if(MSVC)\n    # clang-cl is half MSVC, half LLVM\n    set(ABSL_DEFAULT_COPTS \"${ABSL_CLANG_CL_FLAGS}\")\n    set(ABSL_TEST_COPTS \"${ABSL_CLANG_CL_TEST_FLAGS}\")\n  else()\n    set(ABSL_DEFAULT_COPTS \"${ABSL_LLVM_FLAGS}\")\n    set(ABSL_TEST_COPTS \"${ABSL_LLVM_TEST_FLAGS}\")\n  endif()\nelseif(CMAKE_CXX_COMPILER_ID STREQUAL \"MSVC\")\n  set(ABSL_DEFAULT_COPTS \"${ABSL_MSVC_FLAGS}\")\n  set(ABSL_TEST_COPTS \"${ABSL_MSVC_TEST_FLAGS}\")\n  set(ABSL_DEFAULT_LINKOPTS \"${ABSL_MSVC_LINKOPTS}\")\nelse()\n  message(WARNING \"Unknown compiler: ${CMAKE_CXX_COMPILER}.  Building with no default flags\")\n  set(ABSL_DEFAULT_COPTS \"\")\n  set(ABSL_TEST_COPTS \"\")\nendif()\n\nset(ABSL_CXX_STANDARD \"${CMAKE_CXX_STANDARD}\")\n"
  },
  {
    "path": "absl/copts/GENERATED_AbseilCopts.cmake",
    "content": "# GENERATED! DO NOT MANUALLY EDIT THIS FILE.\n#\n# (1) Edit absl/copts/copts.py.\n# (2) Run `python <path_to_absl>/copts/generate_copts.py`.\n\nlist(APPEND ABSL_CLANG_CL_FLAGS\n    \"/W3\"\n    \"/DNOMINMAX\"\n    \"/DWIN32_LEAN_AND_MEAN\"\n    \"/D_CRT_SECURE_NO_WARNINGS\"\n    \"/D_SCL_SECURE_NO_WARNINGS\"\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\"\n    \"-Wmost\"\n    \"-Wextra\"\n    \"-Wc++98-compat-extra-semi\"\n    \"-Wcast-qual\"\n    \"-Wconversion\"\n    \"-Wdeprecated-pragma\"\n    \"-Wfloat-overflow-conversion\"\n    \"-Wfloat-zero-conversion\"\n    \"-Wfor-loop-analysis\"\n    \"-Wformat-security\"\n    \"-Wgnu-redeclared-enum\"\n    \"-Winfinite-recursion\"\n    \"-Winvalid-constexpr\"\n    \"-Wliteral-conversion\"\n    \"-Wmissing-declarations\"\n    \"-Wnullability-completeness\"\n    \"-Woverlength-strings\"\n    \"-Wpointer-arith\"\n    \"-Wself-assign\"\n    \"-Wshadow-all\"\n    \"-Wshorten-64-to-32\"\n    \"-Wsign-conversion\"\n    \"-Wstring-conversion\"\n    \"-Wtautological-overlap-compare\"\n    \"-Wtautological-unsigned-zero-compare\"\n    \"-Wthread-safety\"\n    \"-Wundef\"\n    \"-Wuninitialized\"\n    \"-Wunreachable-code\"\n    \"-Wunused-comparison\"\n    \"-Wunused-local-typedefs\"\n    \"-Wunused-result\"\n    \"-Wvla\"\n    \"-Wwrite-strings\"\n    \"-Wno-float-conversion\"\n    \"-Wno-implicit-float-conversion\"\n    \"-Wno-implicit-int-float-conversion\"\n    \"-Wno-unknown-warning-option\"\n    \"-Wno-unused-command-line-argument\"\n    \"-DNOMINMAX\"\n)\n\nlist(APPEND ABSL_CLANG_CL_TEST_FLAGS\n    \"/W3\"\n    \"/DNOMINMAX\"\n    \"/DWIN32_LEAN_AND_MEAN\"\n    \"/D_CRT_SECURE_NO_WARNINGS\"\n    \"/D_SCL_SECURE_NO_WARNINGS\"\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\"\n    \"-Wmost\"\n    \"-Wextra\"\n    \"-Wc++98-compat-extra-semi\"\n    \"-Wcast-qual\"\n    \"-Wconversion\"\n    \"-Wdeprecated-pragma\"\n    \"-Wfloat-overflow-conversion\"\n    \"-Wfloat-zero-conversion\"\n    \"-Wfor-loop-analysis\"\n    \"-Wformat-security\"\n    \"-Wgnu-redeclared-enum\"\n    \"-Winfinite-recursion\"\n    \"-Winvalid-constexpr\"\n    \"-Wliteral-conversion\"\n    \"-Wmissing-declarations\"\n    \"-Woverlength-strings\"\n    \"-Wpointer-arith\"\n    \"-Wself-assign\"\n    \"-Wshadow-all\"\n    \"-Wstring-conversion\"\n    \"-Wtautological-overlap-compare\"\n    \"-Wtautological-unsigned-zero-compare\"\n    \"-Wthread-safety\"\n    \"-Wundef\"\n    \"-Wuninitialized\"\n    \"-Wunreachable-code\"\n    \"-Wunused-comparison\"\n    \"-Wunused-local-typedefs\"\n    \"-Wunused-result\"\n    \"-Wvla\"\n    \"-Wwrite-strings\"\n    \"-Wno-float-conversion\"\n    \"-Wno-implicit-float-conversion\"\n    \"-Wno-implicit-int-float-conversion\"\n    \"-Wno-unknown-warning-option\"\n    \"-Wno-unused-command-line-argument\"\n    \"-DNOMINMAX\"\n    \"-Wno-deprecated-declarations\"\n    \"-Wno-implicit-int-conversion\"\n    \"-Wno-missing-prototypes\"\n    \"-Wno-missing-variable-declarations\"\n    \"-Wno-nullability-completeness\"\n    \"-Wno-shadow\"\n    \"-Wno-shorten-64-to-32\"\n    \"-Wno-sign-compare\"\n    \"-Wno-sign-conversion\"\n    \"-Wno-unreachable-code-loop-increment\"\n    \"-Wno-unused-function\"\n    \"-Wno-unused-member-function\"\n    \"-Wno-unused-parameter\"\n    \"-Wno-unused-private-field\"\n    \"-Wno-unused-template\"\n    \"-Wno-used-but-marked-unused\"\n    \"-Wno-gnu-zero-variadic-macro-arguments\"\n)\n\nlist(APPEND ABSL_GCC_FLAGS\n    \"-Wall\"\n    \"-Wextra\"\n    \"-Wcast-qual\"\n    \"-Wconversion-null\"\n    \"-Wformat-security\"\n    \"-Wmissing-declarations\"\n    \"-Wnon-virtual-dtor\"\n    \"-Woverlength-strings\"\n    \"-Wpointer-arith\"\n    \"-Wundef\"\n    \"-Wunused-local-typedefs\"\n    \"-Wunused-result\"\n    \"-Wvarargs\"\n    \"-Wvla\"\n    \"-Wwrite-strings\"\n    \"-DNOMINMAX\"\n)\n\nlist(APPEND ABSL_GCC_TEST_FLAGS\n    \"-Wall\"\n    \"-Wextra\"\n    \"-Wcast-qual\"\n    \"-Wconversion-null\"\n    \"-Wformat-security\"\n    \"-Wnon-virtual-dtor\"\n    \"-Woverlength-strings\"\n    \"-Wpointer-arith\"\n    \"-Wundef\"\n    \"-Wunused-local-typedefs\"\n    \"-Wunused-result\"\n    \"-Wvarargs\"\n    \"-Wvla\"\n    \"-Wwrite-strings\"\n    \"-DNOMINMAX\"\n    \"-Wno-deprecated-declarations\"\n    \"-Wno-missing-declarations\"\n    \"-Wno-self-move\"\n    \"-Wno-sign-compare\"\n    \"-Wno-unused-function\"\n    \"-Wno-unused-parameter\"\n    \"-Wno-unused-private-field\"\n)\n\nlist(APPEND ABSL_LLVM_FLAGS\n    \"-Wall\"\n    \"-Wmost\"\n    \"-Wextra\"\n    \"-Wc++98-compat-extra-semi\"\n    \"-Wcast-qual\"\n    \"-Wconversion\"\n    \"-Wdeprecated-pragma\"\n    \"-Wfloat-overflow-conversion\"\n    \"-Wfloat-zero-conversion\"\n    \"-Wfor-loop-analysis\"\n    \"-Wformat-security\"\n    \"-Wgnu-redeclared-enum\"\n    \"-Winfinite-recursion\"\n    \"-Winvalid-constexpr\"\n    \"-Wliteral-conversion\"\n    \"-Wmissing-declarations\"\n    \"-Wnullability-completeness\"\n    \"-Woverlength-strings\"\n    \"-Wpointer-arith\"\n    \"-Wself-assign\"\n    \"-Wshadow-all\"\n    \"-Wshorten-64-to-32\"\n    \"-Wsign-conversion\"\n    \"-Wstring-conversion\"\n    \"-Wtautological-overlap-compare\"\n    \"-Wtautological-unsigned-zero-compare\"\n    \"-Wthread-safety\"\n    \"-Wundef\"\n    \"-Wuninitialized\"\n    \"-Wunreachable-code\"\n    \"-Wunused-comparison\"\n    \"-Wunused-local-typedefs\"\n    \"-Wunused-result\"\n    \"-Wvla\"\n    \"-Wwrite-strings\"\n    \"-Wno-float-conversion\"\n    \"-Wno-implicit-float-conversion\"\n    \"-Wno-implicit-int-float-conversion\"\n    \"-Wno-unknown-warning-option\"\n    \"-Wno-unused-command-line-argument\"\n    \"-DNOMINMAX\"\n)\n\nlist(APPEND ABSL_LLVM_TEST_FLAGS\n    \"-Wall\"\n    \"-Wmost\"\n    \"-Wextra\"\n    \"-Wc++98-compat-extra-semi\"\n    \"-Wcast-qual\"\n    \"-Wconversion\"\n    \"-Wdeprecated-pragma\"\n    \"-Wfloat-overflow-conversion\"\n    \"-Wfloat-zero-conversion\"\n    \"-Wfor-loop-analysis\"\n    \"-Wformat-security\"\n    \"-Wgnu-redeclared-enum\"\n    \"-Winfinite-recursion\"\n    \"-Winvalid-constexpr\"\n    \"-Wliteral-conversion\"\n    \"-Wmissing-declarations\"\n    \"-Woverlength-strings\"\n    \"-Wpointer-arith\"\n    \"-Wself-assign\"\n    \"-Wshadow-all\"\n    \"-Wstring-conversion\"\n    \"-Wtautological-overlap-compare\"\n    \"-Wtautological-unsigned-zero-compare\"\n    \"-Wthread-safety\"\n    \"-Wundef\"\n    \"-Wuninitialized\"\n    \"-Wunreachable-code\"\n    \"-Wunused-comparison\"\n    \"-Wunused-local-typedefs\"\n    \"-Wunused-result\"\n    \"-Wvla\"\n    \"-Wwrite-strings\"\n    \"-Wno-float-conversion\"\n    \"-Wno-implicit-float-conversion\"\n    \"-Wno-implicit-int-float-conversion\"\n    \"-Wno-unknown-warning-option\"\n    \"-Wno-unused-command-line-argument\"\n    \"-DNOMINMAX\"\n    \"-Wno-deprecated-declarations\"\n    \"-Wno-implicit-int-conversion\"\n    \"-Wno-missing-prototypes\"\n    \"-Wno-missing-variable-declarations\"\n    \"-Wno-nullability-completeness\"\n    \"-Wno-shadow\"\n    \"-Wno-shorten-64-to-32\"\n    \"-Wno-sign-compare\"\n    \"-Wno-sign-conversion\"\n    \"-Wno-unreachable-code-loop-increment\"\n    \"-Wno-unused-function\"\n    \"-Wno-unused-member-function\"\n    \"-Wno-unused-parameter\"\n    \"-Wno-unused-private-field\"\n    \"-Wno-unused-template\"\n    \"-Wno-used-but-marked-unused\"\n    \"-Wno-gnu-zero-variadic-macro-arguments\"\n)\n\nlist(APPEND ABSL_MSVC_FLAGS\n    \"/W3\"\n    \"/bigobj\"\n    \"/wd4005\"\n    \"/wd4068\"\n    \"/wd4180\"\n    \"/wd4503\"\n    \"/wd4800\"\n    \"/DNOMINMAX\"\n    \"/DWIN32_LEAN_AND_MEAN\"\n    \"/D_CRT_SECURE_NO_WARNINGS\"\n    \"/D_SCL_SECURE_NO_WARNINGS\"\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\"\n)\n\nlist(APPEND ABSL_MSVC_LINKOPTS\n    \"-ignore:4221\"\n)\n\nlist(APPEND ABSL_MSVC_TEST_FLAGS\n    \"/W3\"\n    \"/bigobj\"\n    \"/wd4005\"\n    \"/wd4068\"\n    \"/wd4180\"\n    \"/wd4503\"\n    \"/wd4800\"\n    \"/DNOMINMAX\"\n    \"/DWIN32_LEAN_AND_MEAN\"\n    \"/D_CRT_SECURE_NO_WARNINGS\"\n    \"/D_SCL_SECURE_NO_WARNINGS\"\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\"\n    \"/wd4018\"\n    \"/wd4101\"\n    \"/wd4244\"\n    \"/wd4267\"\n    \"/wd4503\"\n    \"/wd4996\"\n    \"/DNOMINMAX\"\n)\n"
  },
  {
    "path": "absl/copts/GENERATED_copts.bzl",
    "content": "\"\"\"GENERATED! DO NOT MANUALLY EDIT THIS FILE.\n\n(1) Edit absl/copts/copts.py.\n(2) Run `python <path_to_absl>/copts/generate_copts.py`.\n\"\"\"\n\nABSL_CLANG_CL_FLAGS = [\n    \"/W3\",\n    \"/DNOMINMAX\",\n    \"/DWIN32_LEAN_AND_MEAN\",\n    \"/D_CRT_SECURE_NO_WARNINGS\",\n    \"/D_SCL_SECURE_NO_WARNINGS\",\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\",\n    \"-Wmost\",\n    \"-Wextra\",\n    \"-Wc++98-compat-extra-semi\",\n    \"-Wcast-qual\",\n    \"-Wconversion\",\n    \"-Wdeprecated-pragma\",\n    \"-Wfloat-overflow-conversion\",\n    \"-Wfloat-zero-conversion\",\n    \"-Wfor-loop-analysis\",\n    \"-Wformat-security\",\n    \"-Wgnu-redeclared-enum\",\n    \"-Winfinite-recursion\",\n    \"-Winvalid-constexpr\",\n    \"-Wliteral-conversion\",\n    \"-Wmissing-declarations\",\n    \"-Wnullability-completeness\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wself-assign\",\n    \"-Wshadow-all\",\n    \"-Wshorten-64-to-32\",\n    \"-Wsign-conversion\",\n    \"-Wstring-conversion\",\n    \"-Wtautological-overlap-compare\",\n    \"-Wtautological-unsigned-zero-compare\",\n    \"-Wthread-safety\",\n    \"-Wundef\",\n    \"-Wuninitialized\",\n    \"-Wunreachable-code\",\n    \"-Wunused-comparison\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    \"-Wno-float-conversion\",\n    \"-Wno-implicit-float-conversion\",\n    \"-Wno-implicit-int-float-conversion\",\n    \"-Wno-unknown-warning-option\",\n    \"-Wno-unused-command-line-argument\",\n    \"-DNOMINMAX\",\n]\n\nABSL_CLANG_CL_TEST_FLAGS = [\n    \"/W3\",\n    \"/DNOMINMAX\",\n    \"/DWIN32_LEAN_AND_MEAN\",\n    \"/D_CRT_SECURE_NO_WARNINGS\",\n    \"/D_SCL_SECURE_NO_WARNINGS\",\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\",\n    \"-Wmost\",\n    \"-Wextra\",\n    \"-Wc++98-compat-extra-semi\",\n    \"-Wcast-qual\",\n    \"-Wconversion\",\n    \"-Wdeprecated-pragma\",\n    \"-Wfloat-overflow-conversion\",\n    \"-Wfloat-zero-conversion\",\n    \"-Wfor-loop-analysis\",\n    \"-Wformat-security\",\n    \"-Wgnu-redeclared-enum\",\n    \"-Winfinite-recursion\",\n    \"-Winvalid-constexpr\",\n    \"-Wliteral-conversion\",\n    \"-Wmissing-declarations\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wself-assign\",\n    \"-Wshadow-all\",\n    \"-Wstring-conversion\",\n    \"-Wtautological-overlap-compare\",\n    \"-Wtautological-unsigned-zero-compare\",\n    \"-Wthread-safety\",\n    \"-Wundef\",\n    \"-Wuninitialized\",\n    \"-Wunreachable-code\",\n    \"-Wunused-comparison\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    \"-Wno-float-conversion\",\n    \"-Wno-implicit-float-conversion\",\n    \"-Wno-implicit-int-float-conversion\",\n    \"-Wno-unknown-warning-option\",\n    \"-Wno-unused-command-line-argument\",\n    \"-DNOMINMAX\",\n    \"-Wno-deprecated-declarations\",\n    \"-Wno-implicit-int-conversion\",\n    \"-Wno-missing-prototypes\",\n    \"-Wno-missing-variable-declarations\",\n    \"-Wno-nullability-completeness\",\n    \"-Wno-shadow\",\n    \"-Wno-shorten-64-to-32\",\n    \"-Wno-sign-compare\",\n    \"-Wno-sign-conversion\",\n    \"-Wno-unreachable-code-loop-increment\",\n    \"-Wno-unused-function\",\n    \"-Wno-unused-member-function\",\n    \"-Wno-unused-parameter\",\n    \"-Wno-unused-private-field\",\n    \"-Wno-unused-template\",\n    \"-Wno-used-but-marked-unused\",\n    \"-Wno-gnu-zero-variadic-macro-arguments\",\n]\n\nABSL_GCC_FLAGS = [\n    \"-Wall\",\n    \"-Wextra\",\n    \"-Wcast-qual\",\n    \"-Wconversion-null\",\n    \"-Wformat-security\",\n    \"-Wmissing-declarations\",\n    \"-Wnon-virtual-dtor\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wundef\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvarargs\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    \"-DNOMINMAX\",\n]\n\nABSL_GCC_TEST_FLAGS = [\n    \"-Wall\",\n    \"-Wextra\",\n    \"-Wcast-qual\",\n    \"-Wconversion-null\",\n    \"-Wformat-security\",\n    \"-Wnon-virtual-dtor\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wundef\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvarargs\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    \"-DNOMINMAX\",\n    \"-Wno-deprecated-declarations\",\n    \"-Wno-missing-declarations\",\n    \"-Wno-self-move\",\n    \"-Wno-sign-compare\",\n    \"-Wno-unused-function\",\n    \"-Wno-unused-parameter\",\n    \"-Wno-unused-private-field\",\n]\n\nABSL_LLVM_FLAGS = [\n    \"-Wall\",\n    \"-Wmost\",\n    \"-Wextra\",\n    \"-Wc++98-compat-extra-semi\",\n    \"-Wcast-qual\",\n    \"-Wconversion\",\n    \"-Wdeprecated-pragma\",\n    \"-Wfloat-overflow-conversion\",\n    \"-Wfloat-zero-conversion\",\n    \"-Wfor-loop-analysis\",\n    \"-Wformat-security\",\n    \"-Wgnu-redeclared-enum\",\n    \"-Winfinite-recursion\",\n    \"-Winvalid-constexpr\",\n    \"-Wliteral-conversion\",\n    \"-Wmissing-declarations\",\n    \"-Wnullability-completeness\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wself-assign\",\n    \"-Wshadow-all\",\n    \"-Wshorten-64-to-32\",\n    \"-Wsign-conversion\",\n    \"-Wstring-conversion\",\n    \"-Wtautological-overlap-compare\",\n    \"-Wtautological-unsigned-zero-compare\",\n    \"-Wthread-safety\",\n    \"-Wundef\",\n    \"-Wuninitialized\",\n    \"-Wunreachable-code\",\n    \"-Wunused-comparison\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    \"-Wno-float-conversion\",\n    \"-Wno-implicit-float-conversion\",\n    \"-Wno-implicit-int-float-conversion\",\n    \"-Wno-unknown-warning-option\",\n    \"-Wno-unused-command-line-argument\",\n    \"-DNOMINMAX\",\n]\n\nABSL_LLVM_TEST_FLAGS = [\n    \"-Wall\",\n    \"-Wmost\",\n    \"-Wextra\",\n    \"-Wc++98-compat-extra-semi\",\n    \"-Wcast-qual\",\n    \"-Wconversion\",\n    \"-Wdeprecated-pragma\",\n    \"-Wfloat-overflow-conversion\",\n    \"-Wfloat-zero-conversion\",\n    \"-Wfor-loop-analysis\",\n    \"-Wformat-security\",\n    \"-Wgnu-redeclared-enum\",\n    \"-Winfinite-recursion\",\n    \"-Winvalid-constexpr\",\n    \"-Wliteral-conversion\",\n    \"-Wmissing-declarations\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wself-assign\",\n    \"-Wshadow-all\",\n    \"-Wstring-conversion\",\n    \"-Wtautological-overlap-compare\",\n    \"-Wtautological-unsigned-zero-compare\",\n    \"-Wthread-safety\",\n    \"-Wundef\",\n    \"-Wuninitialized\",\n    \"-Wunreachable-code\",\n    \"-Wunused-comparison\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    \"-Wno-float-conversion\",\n    \"-Wno-implicit-float-conversion\",\n    \"-Wno-implicit-int-float-conversion\",\n    \"-Wno-unknown-warning-option\",\n    \"-Wno-unused-command-line-argument\",\n    \"-DNOMINMAX\",\n    \"-Wno-deprecated-declarations\",\n    \"-Wno-implicit-int-conversion\",\n    \"-Wno-missing-prototypes\",\n    \"-Wno-missing-variable-declarations\",\n    \"-Wno-nullability-completeness\",\n    \"-Wno-shadow\",\n    \"-Wno-shorten-64-to-32\",\n    \"-Wno-sign-compare\",\n    \"-Wno-sign-conversion\",\n    \"-Wno-unreachable-code-loop-increment\",\n    \"-Wno-unused-function\",\n    \"-Wno-unused-member-function\",\n    \"-Wno-unused-parameter\",\n    \"-Wno-unused-private-field\",\n    \"-Wno-unused-template\",\n    \"-Wno-used-but-marked-unused\",\n    \"-Wno-gnu-zero-variadic-macro-arguments\",\n]\n\nABSL_MSVC_FLAGS = [\n    \"/W3\",\n    \"/bigobj\",\n    \"/wd4005\",\n    \"/wd4068\",\n    \"/wd4180\",\n    \"/wd4503\",\n    \"/wd4800\",\n    \"/DNOMINMAX\",\n    \"/DWIN32_LEAN_AND_MEAN\",\n    \"/D_CRT_SECURE_NO_WARNINGS\",\n    \"/D_SCL_SECURE_NO_WARNINGS\",\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\",\n]\n\nABSL_MSVC_LINKOPTS = [\n    \"-ignore:4221\",\n]\n\nABSL_MSVC_TEST_FLAGS = [\n    \"/W3\",\n    \"/bigobj\",\n    \"/wd4005\",\n    \"/wd4068\",\n    \"/wd4180\",\n    \"/wd4503\",\n    \"/wd4800\",\n    \"/DNOMINMAX\",\n    \"/DWIN32_LEAN_AND_MEAN\",\n    \"/D_CRT_SECURE_NO_WARNINGS\",\n    \"/D_SCL_SECURE_NO_WARNINGS\",\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\",\n    \"/wd4018\",\n    \"/wd4101\",\n    \"/wd4244\",\n    \"/wd4267\",\n    \"/wd4503\",\n    \"/wd4996\",\n    \"/DNOMINMAX\",\n]\n"
  },
  {
    "path": "absl/copts/configure_copts.bzl",
    "content": "\"\"\"absl specific copts.\n\nThis file simply selects the correct options from the generated files.  To\nchange Abseil copts, edit absl/copts/copts.py\n\"\"\"\n\nload(\n    \"//absl:copts/GENERATED_copts.bzl\",\n    \"ABSL_CLANG_CL_FLAGS\",\n    \"ABSL_CLANG_CL_TEST_FLAGS\",\n    \"ABSL_GCC_FLAGS\",\n    \"ABSL_GCC_TEST_FLAGS\",\n    \"ABSL_LLVM_FLAGS\",\n    \"ABSL_LLVM_TEST_FLAGS\",\n    \"ABSL_MSVC_FLAGS\",\n    \"ABSL_MSVC_LINKOPTS\",\n    \"ABSL_MSVC_TEST_FLAGS\",\n)\n\nABSL_DEFAULT_COPTS = select({\n    \"@rules_cc//cc/compiler:msvc-cl\": ABSL_MSVC_FLAGS,\n    \"@rules_cc//cc/compiler:clang-cl\": ABSL_CLANG_CL_FLAGS,\n    \"@rules_cc//cc/compiler:clang\": ABSL_LLVM_FLAGS,\n    \"@rules_cc//cc/compiler:gcc\": ABSL_GCC_FLAGS,\n    \"//conditions:default\": [],\n})\n\nABSL_TEST_COPTS = select({\n    \"@rules_cc//cc/compiler:msvc-cl\": ABSL_MSVC_TEST_FLAGS,\n    \"@rules_cc//cc/compiler:clang-cl\": ABSL_CLANG_CL_TEST_FLAGS,\n    \"@rules_cc//cc/compiler:clang\": ABSL_LLVM_TEST_FLAGS,\n    \"@rules_cc//cc/compiler:gcc\": ABSL_GCC_TEST_FLAGS,\n    \"//conditions:default\": [],\n})\n\nABSL_DEFAULT_LINKOPTS = select({\n    \"@rules_cc//cc/compiler:msvc-cl\": ABSL_MSVC_LINKOPTS,\n    \"//conditions:default\": [],\n})\n"
  },
  {
    "path": "absl/copts/copts.py",
    "content": "\"\"\"Abseil compiler options.\n\nThis is the source of truth for Abseil compiler options.  To modify Abseil\ncompilation options:\n\n  (1) Edit the appropriate list in this file based on the platform the flag is\n      needed on.\n  (2) Run `<path_to_absl>/copts/generate_copts.py`.\n\nThe generated copts are consumed by configure_copts.bzl and\nAbseilConfigureCopts.cmake.\n\"\"\"\n\nABSL_GCC_FLAGS = [\n    \"-Wall\",\n    \"-Wextra\",\n    \"-Wcast-qual\",\n    \"-Wconversion-null\",\n    \"-Wformat-security\",\n    \"-Wmissing-declarations\",\n    \"-Wnon-virtual-dtor\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wundef\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvarargs\",\n    \"-Wvla\",  # variable-length array\n    \"-Wwrite-strings\",\n    # Don't define min and max macros (Build on Windows using gcc)\n    \"-DNOMINMAX\",\n]\n\nABSL_GCC_TEST_ADDITIONAL_FLAGS = [\n    \"-Wno-deprecated-declarations\",\n    \"-Wno-missing-declarations\",\n    \"-Wno-self-move\",\n    \"-Wno-sign-compare\",\n    \"-Wno-unused-function\",\n    \"-Wno-unused-parameter\",\n    \"-Wno-unused-private-field\",\n]\n\n# https://github.com/llvm/llvm-project/issues/102982\n# A list of LLVM base flags without -Wall. This is because clang-cl\n# translates -Wall to -Weverything on Windows, mimicking MSVCs\n# behavior. On most other platforms, -Wall is just a set of very good\n# default flags.\nABSL_LLVM_BASE_FLAGS = [\n    \"-Wmost\",\n    \"-Wextra\",\n    \"-Wc++98-compat-extra-semi\",\n    \"-Wcast-qual\",\n    \"-Wconversion\",\n    \"-Wdeprecated-pragma\",\n    \"-Wfloat-overflow-conversion\",\n    \"-Wfloat-zero-conversion\",\n    \"-Wfor-loop-analysis\",\n    \"-Wformat-security\",\n    \"-Wgnu-redeclared-enum\",\n    \"-Winfinite-recursion\",\n    \"-Winvalid-constexpr\",\n    \"-Wliteral-conversion\",\n    \"-Wmissing-declarations\",\n    \"-Wnullability-completeness\",\n    \"-Woverlength-strings\",\n    \"-Wpointer-arith\",\n    \"-Wself-assign\",\n    \"-Wshadow-all\",\n    \"-Wshorten-64-to-32\",\n    \"-Wsign-conversion\",\n    \"-Wstring-conversion\",\n    \"-Wtautological-overlap-compare\",\n    \"-Wtautological-unsigned-zero-compare\",\n    \"-Wthread-safety\",\n    \"-Wundef\",\n    \"-Wuninitialized\",\n    \"-Wunreachable-code\",\n    \"-Wunused-comparison\",\n    \"-Wunused-local-typedefs\",\n    \"-Wunused-result\",\n    \"-Wvla\",\n    \"-Wwrite-strings\",\n    # Warnings that are enabled by group warning flags like -Wall that we\n    # explicitly disable.\n    \"-Wno-float-conversion\",\n    \"-Wno-implicit-float-conversion\",\n    \"-Wno-implicit-int-float-conversion\",\n    # Disable warnings on unknown warning flags (when warning flags are\n    # unknown on older compiler versions)\n    \"-Wno-unknown-warning-option\",\n    \"-Wno-unused-command-line-argument\",\n    # Don't define min and max macros (Build on Windows using clang)\n    \"-DNOMINMAX\",\n]\n\nABSL_LLVM_FLAGS = [\"-Wall\"] + ABSL_LLVM_BASE_FLAGS\n\nABSL_LLVM_TEST_ADDITIONAL_FLAGS = [\n    \"-Wno-deprecated-declarations\",\n    \"-Wno-implicit-int-conversion\",\n    \"-Wno-missing-prototypes\",\n    \"-Wno-missing-variable-declarations\",\n    \"-Wno-nullability-completeness\",\n    \"-Wno-shadow\",\n    \"-Wno-shorten-64-to-32\",\n    \"-Wno-sign-compare\",\n    \"-Wno-sign-conversion\",\n    \"-Wno-unreachable-code-loop-increment\",\n    \"-Wno-unused-function\",\n    \"-Wno-unused-member-function\",\n    \"-Wno-unused-parameter\",\n    \"-Wno-unused-private-field\",\n    \"-Wno-unused-template\",\n    \"-Wno-used-but-marked-unused\",\n    # gtest depends on this GNU extension being offered.\n    \"-Wno-gnu-zero-variadic-macro-arguments\",\n]\n\n# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...\nMSVC_BIG_WARNING_FLAGS = [\n    \"/W3\",\n]\n\nMSVC_WARNING_FLAGS = [\n    # Increase the number of sections available in object files\n    \"/bigobj\",\n    \"/wd4005\",  # macro-redefinition\n    \"/wd4068\",  # unknown pragma\n    # qualifier applied to function type has no meaning; ignored\n    \"/wd4180\",\n    # The decorated name was longer than the compiler limit\n    \"/wd4503\",\n    # forcing value to bool 'true' or 'false' (performance warning)\n    \"/wd4800\",\n]\n\nMSVC_DEFINES = [\n    \"/DNOMINMAX\",  # Don't define min and max macros (windows.h)\n    # Don't bloat namespace with incompatible winsock versions.\n    \"/DWIN32_LEAN_AND_MEAN\",\n    # Don't warn about usage of insecure C functions.\n    \"/D_CRT_SECURE_NO_WARNINGS\",\n    \"/D_SCL_SECURE_NO_WARNINGS\",\n    # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage\n    \"/D_ENABLE_EXTENDED_ALIGNED_STORAGE\",\n]\n\n\ndef GccStyleFilterAndCombine(default_flags, test_flags):\n  \"\"\"Merges default_flags and test_flags for GCC and LLVM.\n\n  Args:\n    default_flags: A list of default compiler flags\n    test_flags: A list of flags that are only used in tests\n\n  Returns:\n    A combined list of default_flags and test_flags, but with all flags of the\n    form '-Wwarning' removed if test_flags contains a flag of the form\n    '-Wno-warning'\n  \"\"\"\n  remove = set([\"-W\" + f[5:] for f in test_flags if f[:5] == \"-Wno-\"])\n  return [f for f in default_flags if f not in remove] + test_flags\n\nCOPT_VARS = {\n    \"ABSL_GCC_FLAGS\": ABSL_GCC_FLAGS,\n    \"ABSL_GCC_TEST_FLAGS\": GccStyleFilterAndCombine(\n        ABSL_GCC_FLAGS, ABSL_GCC_TEST_ADDITIONAL_FLAGS\n    ),\n    \"ABSL_LLVM_FLAGS\": ABSL_LLVM_FLAGS,\n    \"ABSL_LLVM_TEST_FLAGS\": GccStyleFilterAndCombine(\n        ABSL_LLVM_FLAGS, ABSL_LLVM_TEST_ADDITIONAL_FLAGS\n    ),\n    \"ABSL_CLANG_CL_FLAGS\": (\n        MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + ABSL_LLVM_BASE_FLAGS\n    ),\n    \"ABSL_CLANG_CL_TEST_FLAGS\": (\n        MSVC_BIG_WARNING_FLAGS\n        + MSVC_DEFINES\n        + GccStyleFilterAndCombine(\n            ABSL_LLVM_BASE_FLAGS, ABSL_LLVM_TEST_ADDITIONAL_FLAGS\n        )\n    ),\n    \"ABSL_MSVC_FLAGS\": (\n        MSVC_BIG_WARNING_FLAGS + MSVC_WARNING_FLAGS + MSVC_DEFINES\n    ),\n    \"ABSL_MSVC_TEST_FLAGS\": (\n        MSVC_BIG_WARNING_FLAGS\n        + MSVC_WARNING_FLAGS\n        + MSVC_DEFINES\n        + [\n            \"/wd4018\",  # signed/unsigned mismatch\n            \"/wd4101\",  # unreferenced local variable\n            \"/wd4244\",  # shortening conversion\n            \"/wd4267\",  # shortening conversion\n            \"/wd4503\",  # decorated name length exceeded, name was truncated\n            \"/wd4996\",  # use of deprecated symbol\n            \"/DNOMINMAX\",  # disable the min() and max() macros from <windows.h>\n        ]\n    ),\n    \"ABSL_MSVC_LINKOPTS\": [\n        # Object file doesn't export any previously undefined symbols\n        \"-ignore:4221\",\n    ],\n}\n"
  },
  {
    "path": "absl/copts/generate_copts.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Generate Abseil compile compile option configs.\n\nUsage: <path_to_absl>/copts/generate_copts.py\n\nThe configs are generated from copts.py.\n\"\"\"\n\nfrom os import path\nimport sys\nfrom copts import COPT_VARS\n\n\n# Helper functions\ndef file_header_lines():\n  return [\n      \"GENERATED! DO NOT MANUALLY EDIT THIS FILE.\", \"\",\n      \"(1) Edit absl/copts/copts.py.\",\n      \"(2) Run `python <path_to_absl>/copts/generate_copts.py`.\"\n  ]\n\n\ndef flatten(*lists):\n  return [item for sublist in lists for item in sublist]\n\n\ndef relative_filename(filename):\n  return path.join(path.dirname(__file__), filename)\n\n\n# Style classes.  These contain all the syntactic styling needed to generate a\n# copt file for different build tools.\nclass CMakeStyle(object):\n  \"\"\"Style object for CMake copts file.\"\"\"\n\n  def separator(self):\n    return \"\"\n\n  def list_introducer(self, name):\n    return \"list(APPEND \" + name\n\n  def list_closer(self):\n    return \")\\n\"\n\n  def docstring(self):\n    return \"\\n\".join(((\"# \" + line).strip() for line in file_header_lines()))\n\n  def filename(self):\n    return \"GENERATED_AbseilCopts.cmake\"\n\n\nclass StarlarkStyle(object):\n  \"\"\"Style object for Starlark copts file.\"\"\"\n\n  def separator(self):\n    return \",\"\n\n  def list_introducer(self, name):\n    return name + \" = [\"\n\n  def list_closer(self):\n    return \"]\\n\"\n\n  def docstring(self):\n    docstring_quotes = \"\\\"\\\"\\\"\"\n    return docstring_quotes + \"\\n\".join(\n        flatten(file_header_lines(), [docstring_quotes]))\n\n  def filename(self):\n    return \"GENERATED_copts.bzl\"\n\n\ndef copt_list(name, arg_list, style):\n  \"\"\"Copt file generation.\"\"\"\n\n  make_line = lambda s: \"    \\\"\" + s + \"\\\"\" + style.separator()\n  external_str_list = [make_line(s) for s in arg_list]\n\n  return \"\\n\".join(\n      flatten(\n          [style.list_introducer(name)],\n          external_str_list,\n          [style.list_closer()]))\n\n\ndef generate_copt_file(style):\n  \"\"\"Creates a generated copt file using the given style object.\n\n  Args:\n    style: either StarlarkStyle() or CMakeStyle()\n  \"\"\"\n  with open(relative_filename(style.filename()), \"w\") as f:\n    f.write(style.docstring())\n    f.write(\"\\n\")\n    for var_name, arg_list in sorted(COPT_VARS.items()):\n      f.write(\"\\n\")\n      f.write(copt_list(var_name, arg_list, style))\n\n\ndef main(argv):\n  if len(argv) > 1:\n    raise RuntimeError(\"generate_copts needs no command line args\")\n\n  generate_copt_file(StarlarkStyle())\n  generate_copt_file(CMakeStyle())\n\n\nif __name__ == \"__main__\":\n  main(sys.argv)\n"
  },
  {
    "path": "absl/crc/BUILD.bazel",
    "content": "# Copyright 2022 The Abseil Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:private\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"cpu_detect\",\n    srcs = [\n        \"internal/cpu_detect.cc\",\n    ],\n    hdrs = [\"internal/cpu_detect.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"crc_internal\",\n    srcs = [\n        \"internal/crc.cc\",\n        \"internal/crc_internal.h\",\n        \"internal/crc_x86_arm_combined.cc\",\n    ],\n    hdrs = [\n        \"internal/crc.h\",\n        \"internal/crc32_x86_arm_combined_simd.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cpu_detect\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:prefetch\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/memory\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_library(\n    name = \"crc32c\",\n    srcs = [\n        \"crc32c.cc\",\n        \"internal/crc32c_inline.h\",\n        \"internal/crc_memcpy_fallback.cc\",\n        \"internal/crc_memcpy_x86_arm_combined.cc\",\n        \"internal/crc_non_temporal_memcpy.cc\",\n    ],\n    hdrs = [\n        \"crc32c.h\",\n        \"internal/crc32c.h\",\n        \"internal/crc_memcpy.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":cpu_detect\",\n        \":crc_internal\",\n        \":non_temporal_memcpy\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:prefetch\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n    ],\n)\n\ncc_test(\n    name = \"crc32c_test\",\n    srcs = [\"crc32c_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":crc32c\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"non_temporal_arm_intrinsics\",\n    hdrs = [\"internal/non_temporal_arm_intrinsics.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \":__pkg__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"non_temporal_memcpy\",\n    hdrs = [\"internal/non_temporal_memcpy.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \":__pkg__\",\n    ],\n    deps = [\n        \":non_temporal_arm_intrinsics\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"crc_memcpy_test\",\n    size = \"large\",\n    srcs = [\"internal/crc_memcpy_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    shard_count = 3,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":crc32c\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"non_temporal_memcpy_test\",\n    srcs = [\"internal/non_temporal_memcpy_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":non_temporal_memcpy\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"crc_cord_state\",\n    srcs = [\"internal/crc_cord_state.cc\"],\n    hdrs = [\"internal/crc_cord_state.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//absl/strings:__pkg__\"],\n    deps = [\n        \":crc32c\",\n        \"//absl/base:config\",\n        \"//absl/base:no_destructor\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_test(\n    name = \"crc_cord_state_test\",\n    srcs = [\"internal/crc_cord_state_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":crc32c\",\n        \":crc_cord_state\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"crc32c_benchmark\",\n    testonly = True,\n    srcs = [\"crc32c_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"benchmark\",\n    ],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":crc32c\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/crc/CMakeLists.txt",
    "content": "# Copyright 2022 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    crc_cpu_detect\n  HDRS\n    \"internal/cpu_detect.h\"\n  SRCS\n    \"internal/cpu_detect.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    crc_internal\n  HDRS\n    \"internal/crc.h\"\n    \"internal/crc32_x86_arm_combined_simd.h\"\n  SRCS\n    \"internal/crc.cc\"\n    \"internal/crc_internal.h\"\n    \"internal/crc_x86_arm_combined.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::crc_cpu_detect\n    absl::bits\n    absl::config\n    absl::core_headers\n    absl::endian\n    absl::memory\n    absl::prefetch\n    absl::raw_logging_internal\n)\n\nabsl_cc_library(\n  NAME\n    crc32c\n  HDRS\n    \"crc32c.h\"\n    \"internal/crc32c.h\"\n    \"internal/crc_memcpy.h\"\n  SRCS\n    \"crc32c.cc\"\n    \"internal/crc32c_inline.h\"\n    \"internal/crc_memcpy_fallback.cc\"\n    \"internal/crc_memcpy_x86_arm_combined.cc\"\n    \"internal/crc_non_temporal_memcpy.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::crc_cpu_detect\n    absl::crc_internal\n    absl::non_temporal_memcpy\n    absl::config\n    absl::core_headers\n    absl::endian\n    absl::prefetch\n    absl::str_format\n    absl::strings\n)\n\nabsl_cc_test(\n  NAME\n    crc32c_test\n  SRCS\n    \"crc32c_test.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::crc32c\n    absl::strings\n    absl::str_format\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    non_temporal_arm_intrinsics\n  HDRS\n    \"internal/non_temporal_arm_intrinsics.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    non_temporal_memcpy\n  HDRS\n    \"internal/non_temporal_memcpy.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::non_temporal_arm_intrinsics\n    absl::config\n    absl::core_headers\n)\n\nabsl_cc_test(\n  NAME\n    crc_memcpy_test\n  SRCS\n    \"internal/crc_memcpy_test.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::crc32c\n    absl::memory\n    absl::random_random\n    absl::random_distributions\n    absl::strings\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    non_temporal_memcpy_test\n  SRCS\n    \"internal/non_temporal_memcpy_test.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::non_temporal_memcpy\n    GTest::gtest_main\n)\n\nabsl_cc_library(\n  NAME\n    crc_cord_state\n  HDRS\n    \"internal/crc_cord_state.h\"\n  SRCS\n    \"internal/crc_cord_state.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::crc32c\n    absl::config\n    absl::strings\n    absl::no_destructor\n)\n\nabsl_cc_test(\n  NAME\n    crc_cord_state_test\n  SRCS\n    \"internal/crc_cord_state_test.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::crc_cord_state\n    absl::crc32c\n    GTest::gtest_main\n)\n"
  },
  {
    "path": "absl/crc/crc32c.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/crc32c.h\"\n\n#include <cstdint>\n\n#include \"absl/crc/internal/crc.h\"\n#include \"absl/crc/internal/crc32c.h\"\n#include \"absl/crc/internal/crc_memcpy.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\nconst crc_internal::CRC* CrcEngine() {\n  static const crc_internal::CRC* engine = crc_internal::CRC::Crc32c();\n  return engine;\n}\n\nconstexpr uint32_t kCRC32Xor = 0xffffffffU;\n\n}  // namespace\n\nnamespace crc_internal {\n\ncrc32c_t UnextendCrc32cByZeroes(crc32c_t initial_crc, size_t length) {\n  uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;\n  CrcEngine()->UnextendByZeroes(&crc, length);\n  return static_cast<crc32c_t>(crc ^ kCRC32Xor);\n}\n\n// Called by `absl::ExtendCrc32c()` on strings with size > 64 or when hardware\n// CRC32C support is missing.\ncrc32c_t ExtendCrc32cInternal(crc32c_t initial_crc,\n                              absl::string_view buf_to_add) {\n  uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;\n  CrcEngine()->Extend(&crc, buf_to_add.data(), buf_to_add.size());\n  return static_cast<crc32c_t>(crc ^ kCRC32Xor);\n}\n\n}  // namespace crc_internal\n\ncrc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length) {\n  uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;\n  CrcEngine()->ExtendByZeroes(&crc, length);\n  return static_cast<crc32c_t>(crc ^ kCRC32Xor);\n}\n\ncrc32c_t ConcatCrc32c(crc32c_t lhs_crc, crc32c_t rhs_crc, size_t rhs_len) {\n  uint32_t result = static_cast<uint32_t>(lhs_crc);\n  CrcEngine()->ExtendByZeroes(&result, rhs_len);\n  return crc32c_t{result ^ static_cast<uint32_t>(rhs_crc)};\n}\n\ncrc32c_t RemoveCrc32cPrefix(crc32c_t crc_a, crc32c_t crc_ab, size_t length_b) {\n  return ConcatCrc32c(crc_a, crc_ab, length_b);\n}\n\ncrc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count,\n                      crc32c_t initial_crc) {\n  return static_cast<crc32c_t>(\n      crc_internal::Crc32CAndCopy(dest, src, count, initial_crc, false));\n}\n\n// Remove a Suffix of given size from a buffer\n//\n// Given a CRC32C of an existing buffer, `full_string_crc`; the CRC32C of a\n// suffix of that buffer to remove, `suffix_crc`; and suffix buffer's length,\n// `suffix_len` return the CRC32C of the buffer with suffix removed\n//\n// This operation has a runtime cost of O(log(`suffix_len`))\ncrc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc,\n                            size_t suffix_len) {\n  uint32_t result = static_cast<uint32_t>(full_string_crc) ^\n                    static_cast<uint32_t>(suffix_crc);\n  CrcEngine()->UnextendByZeroes(&result, suffix_len);\n  return crc32c_t{result};\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/crc32c.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: crc32c.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the API for computing CRC32C values as checksums\n// for arbitrary sequences of bytes provided as a string buffer.\n//\n// The API includes the basic functions for computing such CRC32C values and\n// some utility functions for performing more efficient mathematical\n// computations using an existing checksum.\n#ifndef ABSL_CRC_CRC32C_H_\n#define ABSL_CRC_CRC32C_H_\n\n#include <cstdint>\n#include <ostream>\n\n#include \"absl/crc/internal/crc32c_inline.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n//-----------------------------------------------------------------------------\n// crc32c_t\n//-----------------------------------------------------------------------------\n\n// `crc32c_t` defines a strongly-typed integer for holding a CRC32C value.\n//\n// Some operators are intentionally omitted. Only equality operators are defined\n// so that `crc32c_t` can be directly compared. Methods for putting `crc32c_t`\n// directly into a set are omitted because this is bug-prone due to checksum\n// collisions. Use an explicit conversion to the `uint32_t` space for operations\n// that treat `crc32c_t` as an integer.\nclass crc32c_t final {\n public:\n  crc32c_t() = default;\n  constexpr explicit crc32c_t(uint32_t crc) : crc_(crc) {}\n\n  crc32c_t(const crc32c_t&) = default;\n  crc32c_t& operator=(const crc32c_t&) = default;\n\n  explicit operator uint32_t() const { return crc_; }\n\n  friend bool operator==(crc32c_t lhs, crc32c_t rhs) {\n    return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs);\n  }\n\n  friend bool operator!=(crc32c_t lhs, crc32c_t rhs) { return !(lhs == rhs); }\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, crc32c_t crc) {\n    absl::Format(&sink, \"%08x\", static_cast<uint32_t>(crc));\n  }\n\n private:\n  uint32_t crc_;\n};\n\n\nnamespace crc_internal {\n// Non-inline code path for `absl::ExtendCrc32c()`. Do not call directly.\n// Call `absl::ExtendCrc32c()` (defined below) instead.\ncrc32c_t ExtendCrc32cInternal(crc32c_t initial_crc,\n                              absl::string_view buf_to_add);\n}  // namespace crc_internal\n\n// -----------------------------------------------------------------------------\n// CRC32C Computation Functions\n// -----------------------------------------------------------------------------\n\n// ExtendCrc32c()\n//\n// Computes a CRC32C value from an `initial_crc` CRC32C value including the\n// `buf_to_add` bytes of an additional buffer. Using this function is more\n// efficient than computing a CRC32C value for the combined buffer from\n// scratch.\n//\n// Note: `ExtendCrc32c` with an initial_crc of 0 is equivalent to\n// `ComputeCrc32c`.\n//\n// This operation has a runtime cost of O(`buf_to_add.size()`)\ninline crc32c_t ExtendCrc32c(crc32c_t initial_crc,\n                             absl::string_view buf_to_add) {\n  // Approximately 75% of calls have size <= 64.\n  if (buf_to_add.size() <= 64) {\n    uint32_t crc = static_cast<uint32_t>(initial_crc);\n    if (crc_internal::ExtendCrc32cInline(&crc, buf_to_add.data(),\n                                         buf_to_add.size())) {\n      return crc32c_t{crc};\n    }\n  }\n  return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add);\n}\n\n// ComputeCrc32c()\n//\n// Returns the CRC32C value of the provided string.\ninline crc32c_t ComputeCrc32c(absl::string_view buf) {\n  return ExtendCrc32c(crc32c_t{0}, buf);\n}\n\n// ExtendCrc32cByZeroes()\n//\n// Computes a CRC32C value for a buffer with an `initial_crc` CRC32C value,\n// where `length` bytes with a value of 0 are appended to the buffer. Using this\n// function is more efficient than computing a CRC32C value for the combined\n// buffer from scratch.\n//\n// This operation has a runtime cost of O(log(`length`))\ncrc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length);\n\n// MemcpyCrc32c()\n//\n// Copies `src` to `dest` using `memcpy()` semantics, returning the CRC32C\n// value of the copied buffer.\n//\n// Using `MemcpyCrc32c()` is potentially faster than performing the `memcpy()`\n// and `ComputeCrc32c()` operations separately.\ncrc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count,\n                      crc32c_t initial_crc = crc32c_t{0});\n\n// -----------------------------------------------------------------------------\n// CRC32C Arithmetic Functions\n// -----------------------------------------------------------------------------\n\n// The following functions perform arithmetic on CRC32C values, which are\n// generally more efficient than recalculating any given result's CRC32C value.\n\n// ConcatCrc32c()\n//\n// Calculates the CRC32C value of two buffers with known CRC32C values\n// concatenated together.\n//\n// Given a buffer with CRC32C value `crc1` and a buffer with\n// CRC32C value `crc2` and length, `crc2_length`, returns the CRC32C value of\n// the concatenation of these two buffers.\n//\n// This operation has a runtime cost of O(log(`crc2_length`)).\ncrc32c_t ConcatCrc32c(crc32c_t crc1, crc32c_t crc2, size_t crc2_length);\n\n// RemoveCrc32cPrefix()\n//\n// Calculates the CRC32C value of an existing buffer with a series of bytes\n// (the prefix) removed from the beginning of that buffer.\n//\n// Given the CRC32C value of an existing buffer, `full_string_crc`; The CRC32C\n// value of a prefix of that buffer, `prefix_crc`; and the length of the buffer\n// with the prefix removed, `remaining_string_length` , return the CRC32C\n// value of the buffer with the prefix removed.\n//\n// This operation has a runtime cost of O(log(`remaining_string_length`)).\ncrc32c_t RemoveCrc32cPrefix(crc32c_t prefix_crc, crc32c_t full_string_crc,\n                            size_t remaining_string_length);\n// RemoveCrc32cSuffix()\n//\n// Calculates the CRC32C value of an existing buffer with a series of bytes\n// (the suffix) removed from the end of that buffer.\n//\n// Given a CRC32C value of an existing buffer `full_string_crc`, the CRC32C\n// value of the suffix to remove `suffix_crc`, and the length of that suffix\n// `suffix_len`, returns the CRC32C value of the buffer with suffix removed.\n//\n// This operation has a runtime cost of O(log(`suffix_len`))\ncrc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc,\n                            size_t suffix_length);\n\n// operator<<\n//\n// Streams the CRC32C value `crc` to the stream `os`.\ninline std::ostream& operator<<(std::ostream& os, crc32c_t crc) {\n  return os << absl::StreamFormat(\"%08x\", static_cast<uint32_t>(crc));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_CRC32C_H_\n"
  },
  {
    "path": "absl/crc/crc32c_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n\n#include \"absl/crc/crc32c.h\"\n#include \"absl/crc/internal/crc32c.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nstd::string TestString(size_t len) {\n  std::string result;\n  result.reserve(len);\n  for (size_t i = 0; i < len; ++i) {\n    result.push_back(static_cast<char>(i % 256));\n  }\n  return result;\n}\n\nvoid BM_Calculate(benchmark::State& state) {\n  int len = state.range(0);\n  std::string data = TestString(len);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(data);\n    absl::crc32c_t crc = absl::ComputeCrc32c(data);\n    benchmark::DoNotOptimize(crc);\n  }\n}\nBENCHMARK(BM_Calculate)\n    ->Arg(0)\n    ->Arg(1)\n    ->Arg(100)\n    ->Arg(2048)\n    ->Arg(10000)\n    ->Arg(500000);\n\nvoid BM_Extend(benchmark::State& state) {\n  int len = state.range(0);\n  std::string extension = TestString(len);\n  absl::crc32c_t base = absl::crc32c_t{0xC99465AA};  // CRC32C of \"Hello World\"\n  for (auto s : state) {\n    benchmark::DoNotOptimize(base);\n    benchmark::DoNotOptimize(extension);\n    absl::crc32c_t crc = absl::ExtendCrc32c(base, extension);\n    benchmark::DoNotOptimize(crc);\n  }\n}\nBENCHMARK(BM_Extend)\n    ->Arg(0)\n    ->Arg(1)\n    ->Arg(100)\n    ->Arg(2048)\n    ->Arg(10000)\n    ->Arg(500000)\n    ->Arg(100 * 1000 * 1000);\n\n// Make working set >> CPU cache size to benchmark prefetches better\nvoid BM_ExtendCacheMiss(benchmark::State& state) {\n  int len = state.range(0);\n  constexpr int total = 300 * 1000 * 1000;\n  std::string extension = TestString(total);\n  absl::crc32c_t base = absl::crc32c_t{0xC99465AA};  // CRC32C of \"Hello World\"\n  for (auto s : state) {\n    for (int i = 0; i < total; i += len * 2) {\n      benchmark::DoNotOptimize(base);\n      benchmark::DoNotOptimize(extension);\n      absl::crc32c_t crc =\n          absl::ExtendCrc32c(base, absl::string_view(&extension[i], len));\n      benchmark::DoNotOptimize(crc);\n    }\n  }\n  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * total / 2);\n}\nBENCHMARK(BM_ExtendCacheMiss)->Arg(10)->Arg(100)->Arg(1000)->Arg(100000);\n\nvoid BM_ExtendByZeroes(benchmark::State& state) {\n  absl::crc32c_t base = absl::crc32c_t{0xC99465AA};  // CRC32C of \"Hello World\"\n  int num_zeroes = state.range(0);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(base);\n    absl::crc32c_t crc = absl::ExtendCrc32cByZeroes(base, num_zeroes);\n    benchmark::DoNotOptimize(crc);\n  }\n}\nBENCHMARK(BM_ExtendByZeroes)\n    ->RangeMultiplier(10)\n    ->Range(1, 1000000)\n    ->RangeMultiplier(32)\n    ->Range(1, 1 << 20);\n\nvoid BM_UnextendByZeroes(benchmark::State& state) {\n  absl::crc32c_t base = absl::crc32c_t{0xdeadbeef};\n  int num_zeroes = state.range(0);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(base);\n    absl::crc32c_t crc =\n        absl::crc_internal::UnextendCrc32cByZeroes(base, num_zeroes);\n    benchmark::DoNotOptimize(crc);\n  }\n}\nBENCHMARK(BM_UnextendByZeroes)\n    ->RangeMultiplier(10)\n    ->Range(1, 1000000)\n    ->RangeMultiplier(32)\n    ->Range(1, 1 << 20);\n\nvoid BM_Concat(benchmark::State& state) {\n  int string_b_len = state.range(0);\n  std::string string_b = TestString(string_b_len);\n\n  // CRC32C of \"Hello World\"\n  absl::crc32c_t crc_a = absl::crc32c_t{0xC99465AA};\n  absl::crc32c_t crc_b = absl::ComputeCrc32c(string_b);\n\n  for (auto s : state) {\n    benchmark::DoNotOptimize(crc_a);\n    benchmark::DoNotOptimize(crc_b);\n    benchmark::DoNotOptimize(string_b_len);\n    absl::crc32c_t crc_ab = absl::ConcatCrc32c(crc_a, crc_b, string_b_len);\n    benchmark::DoNotOptimize(crc_ab);\n  }\n}\nBENCHMARK(BM_Concat)\n    ->RangeMultiplier(10)\n    ->Range(1, 1000000)\n    ->RangeMultiplier(32)\n    ->Range(1, 1 << 20);\n\nvoid BM_Memcpy(benchmark::State& state) {\n  int string_len = state.range(0);\n\n  std::string source = TestString(string_len);\n  auto dest = absl::make_unique<char[]>(string_len);\n\n  for (auto s : state) {\n    benchmark::DoNotOptimize(source);\n    absl::crc32c_t crc =\n        absl::MemcpyCrc32c(dest.get(), source.data(), source.size());\n    benchmark::DoNotOptimize(crc);\n    benchmark::DoNotOptimize(dest);\n    benchmark::DoNotOptimize(dest.get());\n    benchmark::DoNotOptimize(dest[0]);\n  }\n\n  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *\n                          state.range(0));\n}\nBENCHMARK(BM_Memcpy)->Arg(0)->Arg(1)->Arg(100)->Arg(2048)->Arg(10000)->Arg(\n    500000);\n\nvoid BM_RemoveSuffix(benchmark::State& state) {\n  int full_string_len = state.range(0);\n  int suffix_len = state.range(1);\n\n  std::string full_string = TestString(full_string_len);\n  std::string suffix = full_string.substr(\n    full_string_len - suffix_len, full_string_len);\n\n  absl::crc32c_t full_string_crc = absl::ComputeCrc32c(full_string);\n  absl::crc32c_t suffix_crc = absl::ComputeCrc32c(suffix);\n\n  for (auto s : state) {\n    benchmark::DoNotOptimize(full_string_crc);\n    benchmark::DoNotOptimize(suffix_crc);\n    benchmark::DoNotOptimize(suffix_len);\n    absl::crc32c_t crc = absl::RemoveCrc32cSuffix(full_string_crc, suffix_crc,\n      suffix_len);\n    benchmark::DoNotOptimize(crc);\n  }\n}\nBENCHMARK(BM_RemoveSuffix)\n    ->ArgPair(1, 1)\n    ->ArgPair(100, 10)\n    ->ArgPair(100, 100)\n    ->ArgPair(10000, 1)\n    ->ArgPair(10000, 100)\n    ->ArgPair(10000, 10000)\n    ->ArgPair(500000, 1)\n    ->ArgPair(500000, 100)\n    ->ArgPair(500000, 10000)\n    ->ArgPair(500000, 500000);\n}  // namespace\n"
  },
  {
    "path": "absl/crc/crc32c_test.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/crc32c.h\"\n\n#include <algorithm>\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <limits>\n#include <sstream>\n#include <string>\n#include <tuple>\n\n#include \"gtest/gtest.h\"\n#include \"absl/crc/internal/crc32c.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nTEST(CRC32C, RFC3720) {\n  // Test the results of the vectors from\n  // https://www.rfc-editor.org/rfc/rfc3720#appendix-B.4\n  char data[32];\n\n  // 32 bytes of ones.\n  memset(data, 0, sizeof(data));\n  EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),\n            absl::crc32c_t{0x8a9136aa});\n\n  // 32 bytes of ones.\n  memset(data, 0xff, sizeof(data));\n  EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),\n            absl::crc32c_t{0x62a8ab43});\n\n  // 32 incrementing bytes.\n  for (int i = 0; i < 32; ++i) data[i] = static_cast<char>(i);\n  EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),\n            absl::crc32c_t{0x46dd794e});\n\n  // 32 decrementing bytes.\n  for (int i = 0; i < 32; ++i) data[i] = static_cast<char>(31 - i);\n  EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),\n            absl::crc32c_t{0x113fdb5c});\n\n  // An iSCSI - SCSI Read (10) Command PDU.\n  constexpr uint8_t cmd[48] = {\n      0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,\n      0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  };\n  EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(\n                reinterpret_cast<const char*>(cmd), sizeof(cmd))),\n            absl::crc32c_t{0xd9963a56});\n}\n\nstd::string TestString(size_t len) {\n  std::string result;\n  result.reserve(len);\n  for (size_t i = 0; i < len; ++i) {\n    result.push_back(static_cast<char>(i % 256));\n  }\n  return result;\n}\n\nTEST(CRC32C, Compute) {\n  EXPECT_EQ(absl::ComputeCrc32c(\"\"), absl::crc32c_t{0});\n  EXPECT_EQ(absl::ComputeCrc32c(\"hello world\"), absl::crc32c_t{0xc99465aa});\n}\n\nTEST(CRC32C, Extend) {\n  uint32_t base = 0xC99465AA;  // CRC32C of \"Hello World\"\n  std::string extension = \"Extension String\";\n\n  EXPECT_EQ(\n      absl::ExtendCrc32c(absl::crc32c_t{base}, extension),\n      absl::crc32c_t{0xD2F65090});  // CRC32C of \"Hello WorldExtension String\"\n}\n\nTEST(CRC32C, ExtendByZeroes) {\n  std::string base = \"hello world\";\n  absl::crc32c_t base_crc = absl::crc32c_t{0xc99465aa};\n\n  constexpr size_t kExtendByValues[] = {100, 10000, 100000};\n  for (const size_t extend_by : kExtendByValues) {\n    SCOPED_TRACE(extend_by);\n    absl::crc32c_t crc2 = absl::ExtendCrc32cByZeroes(base_crc, extend_by);\n    EXPECT_EQ(crc2, absl::ComputeCrc32c(base + std::string(extend_by, '\\0')));\n  }\n}\n\n// Test ExtendCrc32cByZeroes() for the full range of the size_t length,\n// including every bit. This is important because ExtendCrc32cByZeroes() is\n// implemented using an array of constants, where each entry in the array is\n// used only when a particular bit in the size_t length is set. This test\n// verifies that every entry in that array is correct.\nTEST(CRC32C, ExtendByZeroesAllLengthBits) {\n  absl::crc32c_t base_crc = absl::crc32c_t{0xc99465aa};\n  const std::array<std::tuple<uint64_t, absl::crc32c_t>, 5> kTestCases = {{\n      {0, absl::crc32c_t(0xc99465aa)},\n      {std::numeric_limits<uint32_t>::max(), absl::crc32c_t(0x9b1d5aaa)},\n      {0x12345678, absl::crc32c_t(0xcf0e9553)},\n      {std::numeric_limits<uint64_t>::max(), absl::crc32c_t(0xf5bff489)},\n      {0x12345678abcdefff, absl::crc32c_t(0xaa1ffb0b)},\n  }};\n  for (const auto &test_case : kTestCases) {\n    uint64_t length = std::get<0>(test_case);\n    absl::crc32c_t expected_value = std::get<1>(test_case);\n    SCOPED_TRACE(length);\n    if (length > std::numeric_limits<size_t>::max()) {\n      // On 32-bit platforms, 64-bit lengths cannot be used or tested.\n      continue;\n    }\n    EXPECT_EQ(absl::ExtendCrc32cByZeroes(base_crc, static_cast<size_t>(length)),\n              expected_value);\n  }\n}\n\nTEST(CRC32C, UnextendByZeroes) {\n  constexpr size_t kExtendByValues[] = {2, 200, 20000, 200000, 20000000};\n  constexpr size_t kUnextendByValues[] = {0, 100, 10000, 100000, 10000000};\n\n  for (auto seed_crc : {absl::crc32c_t{0}, absl::crc32c_t{0xc99465aa}}) {\n    SCOPED_TRACE(seed_crc);\n    for (const size_t size_1 : kExtendByValues) {\n      for (const size_t size_2 : kUnextendByValues) {\n        size_t extend_size = std::max(size_1, size_2);\n        size_t unextend_size = std::min(size_1, size_2);\n        SCOPED_TRACE(extend_size);\n        SCOPED_TRACE(unextend_size);\n\n        // Extending by A zeroes an unextending by B<A zeros should be identical\n        // to extending by A-B zeroes.\n        absl::crc32c_t crc1 = seed_crc;\n        crc1 = absl::ExtendCrc32cByZeroes(crc1, extend_size);\n        crc1 = absl::crc_internal::UnextendCrc32cByZeroes(crc1, unextend_size);\n\n        absl::crc32c_t crc2 = seed_crc;\n        crc2 = absl::ExtendCrc32cByZeroes(crc2, extend_size - unextend_size);\n\n        EXPECT_EQ(crc1, crc2);\n      }\n    }\n  }\n\n  constexpr size_t kSizes[] = {0, 1, 100, 10000};\n  for (const size_t size : kSizes) {\n    SCOPED_TRACE(size);\n    std::string string_before = TestString(size);\n    std::string string_after = string_before + std::string(size, '\\0');\n\n    absl::crc32c_t crc_before = absl::ComputeCrc32c(string_before);\n    absl::crc32c_t crc_after = absl::ComputeCrc32c(string_after);\n\n    EXPECT_EQ(crc_before,\n              absl::crc_internal::UnextendCrc32cByZeroes(crc_after, size));\n  }\n}\n\nTEST(CRC32C, Concat) {\n  std::string hello = \"Hello, \";\n  std::string world = \"world!\";\n  std::string hello_world = absl::StrCat(hello, world);\n\n  absl::crc32c_t crc_a = absl::ComputeCrc32c(hello);\n  absl::crc32c_t crc_b = absl::ComputeCrc32c(world);\n  absl::crc32c_t crc_ab = absl::ComputeCrc32c(hello_world);\n\n  EXPECT_EQ(absl::ConcatCrc32c(crc_a, crc_b, world.size()), crc_ab);\n}\n\nTEST(CRC32C, Memcpy) {\n  constexpr size_t kBytesSize[] = {0, 1, 20, 500, 100000};\n  for (size_t bytes : kBytesSize) {\n    SCOPED_TRACE(bytes);\n    std::string sample_string = TestString(bytes);\n    std::string target_buffer = std::string(bytes, '\\0');\n\n    absl::crc32c_t memcpy_crc =\n        absl::MemcpyCrc32c(&(target_buffer[0]), sample_string.data(), bytes);\n    absl::crc32c_t compute_crc = absl::ComputeCrc32c(sample_string);\n\n    EXPECT_EQ(memcpy_crc, compute_crc);\n    EXPECT_EQ(sample_string, target_buffer);\n  }\n}\n\nTEST(CRC32C, RemovePrefix) {\n  std::string hello = \"Hello, \";\n  std::string world = \"world!\";\n  std::string hello_world = absl::StrCat(hello, world);\n\n  absl::crc32c_t crc_a = absl::ComputeCrc32c(hello);\n  absl::crc32c_t crc_b = absl::ComputeCrc32c(world);\n  absl::crc32c_t crc_ab = absl::ComputeCrc32c(hello_world);\n\n  EXPECT_EQ(absl::RemoveCrc32cPrefix(crc_a, crc_ab, world.size()), crc_b);\n}\n\nTEST(CRC32C, RemoveSuffix) {\n  std::string hello = \"Hello, \";\n  std::string world = \"world!\";\n  std::string hello_world = absl::StrCat(hello, world);\n\n  absl::crc32c_t crc_a = absl::ComputeCrc32c(hello);\n  absl::crc32c_t crc_b = absl::ComputeCrc32c(world);\n  absl::crc32c_t crc_ab = absl::ComputeCrc32c(hello_world);\n\n  EXPECT_EQ(absl::RemoveCrc32cSuffix(crc_ab, crc_b, world.size()), crc_a);\n}\n\nTEST(CRC32C, InsertionOperator) {\n  {\n    std::ostringstream buf;\n    buf << absl::crc32c_t{0xc99465aa};\n    EXPECT_EQ(buf.str(), \"c99465aa\");\n  }\n  {\n    std::ostringstream buf;\n    buf << absl::crc32c_t{0};\n    EXPECT_EQ(buf.str(), \"00000000\");\n  }\n  {\n    std::ostringstream buf;\n    buf << absl::crc32c_t{17};\n    EXPECT_EQ(buf.str(), \"00000011\");\n  }\n}\n\nTEST(CRC32C, AbslStringify) {\n  // StrFormat\n  EXPECT_EQ(absl::StrFormat(\"%v\", absl::crc32c_t{0xc99465aa}), \"c99465aa\");\n  EXPECT_EQ(absl::StrFormat(\"%v\", absl::crc32c_t{0}), \"00000000\");\n  EXPECT_EQ(absl::StrFormat(\"%v\", absl::crc32c_t{17}), \"00000011\");\n\n  // StrCat\n  EXPECT_EQ(absl::StrCat(absl::crc32c_t{0xc99465aa}), \"c99465aa\");\n  EXPECT_EQ(absl::StrCat(absl::crc32c_t{0}), \"00000000\");\n  EXPECT_EQ(absl::StrCat(absl::crc32c_t{17}), \"00000011\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/crc/internal/cpu_detect.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/internal/cpu_detect.h\"\n\n#include <cstdint>\n#include <optional>  // IWYU pragma: keep\n#include <string>\n\n#include \"absl/base/config.h\"\n\n#if defined(__aarch64__) && defined(__linux__)\n#include <asm/hwcap.h>\n#include <sys/auxv.h>\n#endif\n\n#if defined(__aarch64__) && defined(__APPLE__)\n#if defined(__has_include) && __has_include(<arm/cpu_capabilities_public.h>)\n#include <arm/cpu_capabilities_public.h>\n#endif\n#include <sys/sysctl.h>\n#include <sys/types.h>\n#endif\n\n#if defined(_WIN32) || defined(_WIN64)\n#include <intrin.h>\n#endif\n\n#if defined(__x86_64__) || defined(_M_X64)\n#if ABSL_HAVE_BUILTIN(__cpuid)\n// MSVC-equivalent __cpuid intrinsic declaration for clang-like compilers\n// for non-Windows build environments.\nextern void __cpuid(int[4], int);\n#elif !defined(_WIN32) && !defined(_WIN64)\n// MSVC defines this function for us.\n// https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex\nstatic void __cpuid(int cpu_info[4], int info_type) {\n  __asm__ volatile(\"cpuid \\n\\t\"\n                   : \"=a\"(cpu_info[0]), \"=b\"(cpu_info[1]), \"=c\"(cpu_info[2]),\n                     \"=d\"(cpu_info[3])\n                   : \"a\"(info_type), \"c\"(0));\n}\n#endif  // !defined(_WIN32) && !defined(_WIN64)\n#endif  // defined(__x86_64__) || defined(_M_X64)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n#if defined(__x86_64__) || defined(_M_X64)\n\nnamespace {\n\nenum class Vendor {\n  kUnknown,\n  kIntel,\n  kAmd,\n};\n\nVendor GetVendor() {\n  // Get the vendor string (issue CPUID with eax = 0).\n  int cpu_info[4];\n  __cpuid(cpu_info, 0);\n\n  std::string vendor;\n  vendor.append(reinterpret_cast<char*>(&cpu_info[1]), 4);\n  vendor.append(reinterpret_cast<char*>(&cpu_info[3]), 4);\n  vendor.append(reinterpret_cast<char*>(&cpu_info[2]), 4);\n  if (vendor == \"GenuineIntel\") {\n    return Vendor::kIntel;\n  } else if (vendor == \"AuthenticAMD\") {\n    return Vendor::kAmd;\n  } else {\n    return Vendor::kUnknown;\n  }\n}\n\nCpuType GetIntelCpuType() {\n  // To get general information and extended features we send eax = 1 and\n  // ecx = 0 to cpuid.  The response is returned in eax, ebx, ecx and edx.\n  // (See Intel 64 and IA-32 Architectures Software Developer's Manual\n  // Volume 2A: Instruction Set Reference, A-M CPUID).\n  // https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html\n  // https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex\n  int cpu_info[4];\n  __cpuid(cpu_info, 1);\n\n  // Response in eax bits as follows:\n  // 0-3 (stepping id)\n  // 4-7 (model number),\n  // 8-11 (family code),\n  // 12-13 (processor type),\n  // 16-19 (extended model)\n  // 20-27 (extended family)\n\n  int family = (cpu_info[0] >> 8) & 0x0f;\n  int model_num = (cpu_info[0] >> 4) & 0x0f;\n  int ext_family = (cpu_info[0] >> 20) & 0xff;\n  int ext_model_num = (cpu_info[0] >> 16) & 0x0f;\n\n  int brand_id = cpu_info[1] & 0xff;\n\n  // Process the extended family and model info if necessary\n  if (family == 0x0f) {\n    family += ext_family;\n  }\n\n  if (family == 0x0f || family == 0x6) {\n    model_num += (ext_model_num << 4);\n  }\n\n  switch (brand_id) {\n    case 0:  // no brand ID, so parse CPU family/model\n      switch (family) {\n        case 6:  // Most PentiumIII processors are in this category\n          switch (model_num) {\n            case 0x2c:  // Westmere: Gulftown\n              return CpuType::kIntelWestmere;\n            case 0x2d:  // Sandybridge\n              return CpuType::kIntelSandybridge;\n            case 0x3e:  // Ivybridge\n              return CpuType::kIntelIvybridge;\n            case 0x3c:  // Haswell (client)\n            case 0x3f:  // Haswell\n              return CpuType::kIntelHaswell;\n            case 0x4f:  // Broadwell\n            case 0x56:  // BroadwellDE\n              return CpuType::kIntelBroadwell;\n            case 0x55:                 // Skylake Xeon\n              if ((cpu_info[0] & 0x0f) < 5) {  // stepping < 5 is skylake\n                return CpuType::kIntelSkylakeXeon;\n              } else {  // stepping >= 5 is cascadelake\n                return CpuType::kIntelCascadelakeXeon;\n              }\n            case 0x5e:  // Skylake (client)\n              return CpuType::kIntelSkylake;\n            case 0x6a:  // Ice Lake\n              return CpuType::kIntelIcelake;\n            case 0x8f:  // Sapphire Rapids\n              return CpuType::kIntelSapphirerapids;\n            case 0xcf:  // Emerald Rapids\n              return CpuType::kIntelEmeraldrapids;\n            case 0xad:  // Granite Rapids\n              return CpuType::kIntelGraniterapidsap;\n            default:\n              return CpuType::kUnknown;\n          }\n        default:\n          return CpuType::kUnknown;\n      }\n    default:\n      return CpuType::kUnknown;\n  }\n}\n\nCpuType GetAmdCpuType() {\n  // To get general information and extended features we send eax = 1 and\n  // ecx = 0 to cpuid.  The response is returned in eax, ebx, ecx and edx.\n  // (See Intel 64 and IA-32 Architectures Software Developer's Manual\n  // Volume 2A: Instruction Set Reference, A-M CPUID).\n  // https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex\n  int cpu_info[4];\n  __cpuid(cpu_info, 1);\n\n  // Response in eax bits as follows:\n  // 0-3 (stepping id)\n  // 4-7 (model number),\n  // 8-11 (family code),\n  // 12-13 (processor type),\n  // 16-19 (extended model)\n  // 20-27 (extended family)\n\n  int family = (cpu_info[0] >> 8) & 0x0f;\n  int model_num = (cpu_info[0] >> 4) & 0x0f;\n  int ext_family = (cpu_info[0] >> 20) & 0xff;\n  int ext_model_num = (cpu_info[0] >> 16) & 0x0f;\n\n  if (family == 0x0f) {\n    family += ext_family;\n    model_num += (ext_model_num << 4);\n  }\n\n  switch (family) {\n    case 0x17:\n      switch (model_num) {\n        case 0x0:  // Stepping Ax\n        case 0x1:  // Stepping Bx\n          return CpuType::kAmdNaples;\n        case 0x30:  // Stepping Ax\n        case 0x31:  // Stepping Bx\n          return CpuType::kAmdRome;\n        default:\n          return CpuType::kUnknown;\n      }\n      break;\n    case 0x19:\n      switch (model_num) {\n        case 0x0:  // Stepping Ax\n        case 0x1:  // Stepping B0\n          return CpuType::kAmdMilan;\n        case 0x10:  // Stepping A0\n        case 0x11:  // Stepping B0\n          return CpuType::kAmdGenoa;\n        case 0x44:  // Stepping A0\n          return CpuType::kAmdRyzenV3000;\n        default:\n          return CpuType::kUnknown;\n      }\n      break;\n    case 0x1A:\n      switch (model_num) {\n        case 0x2:\n          return CpuType::kAmdTurin;\n        default:\n          return CpuType::kUnknown;\n      }\n      break;\n    default:\n      return CpuType::kUnknown;\n  }\n}\n\n}  // namespace\n\nCpuType GetCpuType() {\n  switch (GetVendor()) {\n    case Vendor::kIntel:\n      return GetIntelCpuType();\n    case Vendor::kAmd:\n      return GetAmdCpuType();\n    default:\n      return CpuType::kUnknown;\n  }\n}\n\nbool SupportsArmCRC32PMULL() { return false; }\n\n#elif defined(__aarch64__) && defined(__linux__)\n\n#ifndef HWCAP_CPUID\n#define HWCAP_CPUID (1 << 11)\n#endif\n\n#define ABSL_INTERNAL_AARCH64_ID_REG_READ(id, val) \\\n  asm(\"mrs %0, \" #id : \"=r\"(val))\n\nCpuType GetCpuType() {\n  // MIDR_EL1 is not visible to EL0, however the access will be emulated by\n  // linux if AT_HWCAP has HWCAP_CPUID set.\n  //\n  // This method will be unreliable on heterogeneous computing systems (ex:\n  // big.LITTLE) since the value of MIDR_EL1 will change based on the calling\n  // thread.\n  uint64_t hwcaps = getauxval(AT_HWCAP);\n  if (hwcaps & HWCAP_CPUID) {\n    uint64_t midr = 0;\n    ABSL_INTERNAL_AARCH64_ID_REG_READ(MIDR_EL1, midr);\n    uint32_t implementer = (midr >> 24) & 0xff;\n    uint32_t part_number = (midr >> 4) & 0xfff;\n    switch (implementer) {\n      case 0x41:\n        switch (part_number) {\n          case 0xd0c: return CpuType::kArmNeoverseN1;\n          case 0xd40: return CpuType::kArmNeoverseV1;\n          case 0xd49: return CpuType::kArmNeoverseN2;\n          case 0xd4f: return CpuType::kArmNeoverseV2;\n          case 0xd8e: return CpuType::kArmNeoverseN3;\n          default:\n            return CpuType::kUnknown;\n        }\n        break;\n      case 0xc0:\n        switch (part_number) {\n          case 0xac3: return CpuType::kAmpereSiryn;\n          default:\n            return CpuType::kUnknown;\n        }\n        break;\n      default:\n        return CpuType::kUnknown;\n    }\n  }\n  return CpuType::kUnknown;\n}\n\nbool SupportsArmCRC32PMULL() {\n#if defined(HWCAP_CRC32) && defined(HWCAP_PMULL)\n  uint64_t hwcaps = getauxval(AT_HWCAP);\n  return (hwcaps & HWCAP_CRC32) && (hwcaps & HWCAP_PMULL);\n#else\n  return false;\n#endif\n}\n\n#elif defined(__aarch64__) && defined(__APPLE__)\n\nCpuType GetCpuType() { return CpuType::kUnknown; }\n\ntemplate <typename T>\nstatic std::optional<T> ReadSysctlByName(const char* name) {\n  T val;\n  size_t val_size = sizeof(T);\n  int ret = sysctlbyname(name, &val, &val_size, nullptr, 0);\n  if (ret == -1) {\n    return std::nullopt;\n  }\n  return val;\n}\n\nbool SupportsArmCRC32PMULL() {\n  // Newer XNU kernels support querying all capabilities in a single\n  // sysctlbyname.\n#if defined(CAP_BIT_CRC32) && defined(CAP_BIT_FEAT_PMULL)\n  static const std::optional<uint64_t> caps =\n      ReadSysctlByName<uint64_t>(\"hw.optional.arm.caps\");\n  if (caps.has_value()) {\n    constexpr uint64_t kCrc32AndPmullCaps =\n        (uint64_t{1} << CAP_BIT_CRC32) | (uint64_t{1} << CAP_BIT_FEAT_PMULL);\n    return (*caps & kCrc32AndPmullCaps) == kCrc32AndPmullCaps;\n  }\n#endif\n\n  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3915619\n  static const std::optional<int> armv8_crc32 =\n      ReadSysctlByName<int>(\"hw.optional.armv8_crc32\");\n  if (armv8_crc32.value_or(0) == 0) {\n    return false;\n  }\n  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855\n  static const std::optional<int> feat_pmull =\n      ReadSysctlByName<int>(\"hw.optional.arm.FEAT_PMULL\");\n  if (feat_pmull.value_or(0) == 0) {\n    return false;\n  }\n  return true;\n}\n\n#else\n\nCpuType GetCpuType() { return CpuType::kUnknown; }\n\nbool SupportsArmCRC32PMULL() { return false; }\n\n#endif\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/internal/cpu_detect.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CPU_DETECT_H_\n#define ABSL_CRC_INTERNAL_CPU_DETECT_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n// Enumeration of architectures that we have special-case tuning parameters for.\n// This set may change over time.\nenum class CpuType {\n  kUnknown,\n  kIntelHaswell,\n  kAmdRome,\n  kAmdNaples,\n  kAmdMilan,\n  kAmdGenoa,\n  kAmdTurin,\n  kAmdRyzenV3000,\n  kIntelCascadelakeXeon,\n  kIntelSkylakeXeon,\n  kIntelBroadwell,\n  kIntelIcelake,\n  kIntelSapphirerapids,\n  kIntelEmeraldrapids,\n  kIntelGraniterapidsap,\n  kIntelSkylake,\n  kIntelIvybridge,\n  kIntelSandybridge,\n  kIntelWestmere,\n  kArmNeoverseN1,\n  kArmNeoverseV1,\n  kAmpereSiryn,\n  kArmNeoverseN2,\n  kArmNeoverseV2,\n  kArmNeoverseN3,\n};\n\n// Returns the type of host CPU this code is running on.  Returns kUnknown if\n// the host CPU is of unknown type, or if detection otherwise fails.\nCpuType GetCpuType();\n\n// Returns whether the host CPU supports the CPU features needed for our\n// accelerated implementations. The CpuTypes enumerated above apart from\n// kUnknown support the required features. On unknown CPUs, we can use\n// this to see if it's safe to use hardware acceleration, though without any\n// tuning.\nbool SupportsArmCRC32PMULL();\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CPU_DETECT_H_\n"
  },
  {
    "path": "absl/crc/internal/crc.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Implementation of CRCs (aka Rabin Fingerprints).\n// Treats the input as a polynomial with coefficients in Z(2),\n// and finds the remainder when divided by an irreducible polynomial\n// of the appropriate length.\n// It handles all CRC sizes from 8 to 128 bits.\n// It's somewhat complicated by having separate implementations optimized for\n// CRC's <=32 bits, <= 64 bits, and <= 128 bits.\n// The input string is prefixed with a \"1\" bit, and has \"degree\" \"0\" bits\n// appended to it before the remainder is found.   This ensures that\n// short strings are scrambled somewhat and that strings consisting\n// of all nulls have a non-zero CRC.\n//\n// Uses the \"interleaved word-by-word\" method from\n// \"Everything we know about CRC but afraid to forget\" by Andrew Kadatch\n// and Bob Jenkins,\n// http://crcutil.googlecode.com/files/crc-doc.1.0.pdf\n//\n// The idea is to compute kStride CRCs simultaneously, allowing the\n// processor to more effectively use multiple execution units. Each of\n// the CRCs is calculated on one word of data followed by kStride - 1\n// words of zeroes; the CRC starting points are staggered by one word.\n// Assuming a stride of 4 with data words \"ABCDABCDABCD\", the first\n// CRC is over A000A000A, the second over 0B000B000B, and so on.\n// The CRC of the whole data is then calculated by properly aligning the\n// CRCs by appending zeroes until the data lengths agree then XORing\n// the CRCs.\n\n#include \"absl/crc/internal/crc.h\"\n\n#include <cstdint>\n\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/prefetch.h\"\n#include \"absl/crc/internal/crc_internal.h\"\n#include \"absl/numeric/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\nnamespace {\n\n// Constants\n#if defined(__i386__) || defined(__x86_64__)\nconstexpr bool kNeedAlignedLoads = false;\n#else\nconstexpr bool kNeedAlignedLoads = true;\n#endif\n\n// We express the number of zeroes as a number in base ZEROES_BASE. By\n// pre-computing the zero extensions for all possible components of such an\n// expression (numbers in a form a*ZEROES_BASE**b), we can calculate the\n// resulting extension by multiplying the extensions for individual components\n// using log_{ZEROES_BASE}(num_zeroes) polynomial multiplications. The tables of\n// zero extensions contain (ZEROES_BASE - 1) * (log_{ZEROES_BASE}(64)) entries.\nconstexpr int ZEROES_BASE_LG = 4;                   // log_2(ZEROES_BASE)\nconstexpr int ZEROES_BASE = (1 << ZEROES_BASE_LG);  // must be a power of 2\n\nconstexpr uint32_t kCrc32cPoly = 0x82f63b78;\n\nuint32_t ReverseBits(uint32_t bits) {\n  bits = (bits & 0xaaaaaaaau) >> 1 | (bits & 0x55555555u) << 1;\n  bits = (bits & 0xccccccccu) >> 2 | (bits & 0x33333333u) << 2;\n  bits = (bits & 0xf0f0f0f0u) >> 4 | (bits & 0x0f0f0f0fu) << 4;\n  return absl::gbswap_32(bits);\n}\n\n// Polynomial long multiplication mod the polynomial of degree 32.\nvoid PolyMultiply(uint32_t* val, uint32_t m, uint32_t poly) {\n  uint32_t l = *val;\n  uint32_t result = 0;\n  auto onebit = uint32_t{0x80000000u};\n  for (uint32_t one = onebit; one != 0; one >>= 1) {\n    if ((l & one) != 0) {\n      result ^= m;\n    }\n    if (m & 1) {\n      m = (m >> 1) ^ poly;\n    } else {\n      m >>= 1;\n    }\n  }\n  *val = result;\n}\n}  // namespace\n\nvoid CRCImpl::FillWordTable(uint32_t poly, uint32_t last, int word_size,\n                            Uint32By256* t) {\n  for (int j = 0; j != word_size; j++) {  // for each byte of extension....\n    t[j][0] = 0;                          // a zero has no effect\n    for (int i = 128; i != 0; i >>= 1) {  // fill in entries for powers of 2\n      if (j == 0 && i == 128) {\n        t[j][i] = last;  // top bit in last byte is given\n      } else {\n        // each successive power of two is derived from the previous\n        // one, either in this table, or the last table\n        uint32_t pred;\n        if (i == 128) {\n          pred = t[j - 1][1];\n        } else {\n          pred = t[j][i << 1];\n        }\n        // Advance the CRC by one bit (multiply by X, and take remainder\n        // through one step of polynomial long division)\n        if (pred & 1) {\n          t[j][i] = (pred >> 1) ^ poly;\n        } else {\n          t[j][i] = pred >> 1;\n        }\n      }\n    }\n    // CRCs have the property that CRC(a xor b) == CRC(a) xor CRC(b)\n    // so we can make all the tables for non-powers of two by\n    // xoring previously created entries.\n    for (int i = 2; i != 256; i <<= 1) {\n      for (int k = i + 1; k != (i << 1); k++) {\n        t[j][k] = t[j][i] ^ t[j][k - i];\n      }\n    }\n  }\n}\n\nint CRCImpl::FillZeroesTable(uint32_t poly, Uint32By256* t) {\n  uint32_t inc = 1;\n  inc <<= 31;\n\n  // Extend by one zero bit. We know degree > 1 so (inc & 1) == 0.\n  inc >>= 1;\n\n  // Now extend by 2, 4, and 8 bits, so now `inc` is extended by one zero byte.\n  for (int i = 0; i < 3; ++i) {\n    PolyMultiply(&inc, inc, poly);\n  }\n\n  int j = 0;\n  for (uint64_t inc_len = 1; inc_len != 0; inc_len <<= ZEROES_BASE_LG) {\n    // Every entry in the table adds an additional inc_len zeroes.\n    uint32_t v = inc;\n    for (int a = 1; a != ZEROES_BASE; a++) {\n      t[0][j] = v;\n      PolyMultiply(&v, inc, poly);\n      j++;\n    }\n    inc = v;\n  }\n  ABSL_RAW_CHECK(j <= 256, \"\");\n  return j;\n}\n\n// Internal version of the \"constructor\".\nCRCImpl* CRCImpl::NewInternal() {\n  // Find an accelearated implementation first.\n  CRCImpl* result = TryNewCRC32AcceleratedX86ARMCombined();\n\n  // Fall back to generic implementions if no acceleration is available.\n  if (result == nullptr) {\n    result = new CRC32();\n  }\n\n  result->InitTables();\n\n  return result;\n}\n\n//  The 32-bit implementation\n\nvoid CRC32::InitTables() {\n  // Compute the table for extending a CRC by one byte.\n  Uint32By256* t = new Uint32By256[4];\n  FillWordTable(kCrc32cPoly, kCrc32cPoly, 1, t);\n  for (int i = 0; i != 256; i++) {\n    this->table0_[i] = t[0][i];\n  }\n\n  // Construct a table for updating the CRC by 4 bytes data followed by\n  // 12 bytes of zeroes.\n  //\n  // Note: the data word size could be larger than the CRC size; it might\n  // be slightly faster to use a 64-bit data word, but doing so doubles the\n  // table size.\n  uint32_t last = kCrc32cPoly;\n  const size_t size = 12;\n  for (size_t i = 0; i < size; ++i) {\n    last = (last >> 8) ^ this->table0_[last & 0xff];\n  }\n  FillWordTable(kCrc32cPoly, last, 4, t);\n  for (size_t b = 0; b < 4; ++b) {\n    for (int i = 0; i < 256; ++i) {\n      this->table_[b][i] = t[b][i];\n    }\n  }\n\n  int j = FillZeroesTable(kCrc32cPoly, t);\n  ABSL_RAW_CHECK(j <= static_cast<int>(ABSL_ARRAYSIZE(this->zeroes_)), \"\");\n  for (int i = 0; i < j; i++) {\n    this->zeroes_[i] = t[0][i];\n  }\n\n  delete[] t;\n\n  // Build up tables for _reversing_ the operation of doing CRC operations on\n  // zero bytes.\n\n  // In C++, extending `crc` by a single zero bit is done by the following:\n  // (A)  bool low_bit_set = (crc & 1);\n  //      crc >>= 1;\n  //      if (low_bit_set) crc ^= kCrc32cPoly;\n  //\n  // In particular note that the high bit of `crc` after this operation will be\n  // set if and only if the low bit of `crc` was set before it.  This means that\n  // no information is lost, and the operation can be reversed, as follows:\n  // (B)  bool high_bit_set = (crc & 0x80000000u);\n  //      if (high_bit_set) crc ^= kCrc32cPoly;\n  //      crc <<= 1;\n  //      if (high_bit_set) crc ^= 1;\n  //\n  // Or, equivalently:\n  // (C)  bool high_bit_set = (crc & 0x80000000u);\n  //      crc <<= 1;\n  //      if (high_bit_set) crc ^= ((kCrc32cPoly << 1) ^ 1);\n  //\n  // The last observation is, if we store our checksums in variable `rcrc`,\n  // with order of the bits reversed, the inverse operation becomes:\n  // (D)  bool low_bit_set = (rcrc & 1);\n  //      rcrc >>= 1;\n  //      if (low_bit_set) rcrc ^= ReverseBits((kCrc32cPoly << 1) ^ 1)\n  //\n  // This is the same algorithm (A) that we started with, only with a different\n  // polynomial bit pattern.  This means that by building up our tables with\n  // this alternate polynomial, we can apply the CRC algorithms to a\n  // bit-reversed CRC checksum to perform inverse zero-extension.\n\n  const uint32_t kCrc32cUnextendPoly =\n      ReverseBits(static_cast<uint32_t>((kCrc32cPoly << 1) ^ 1));\n  FillWordTable(kCrc32cUnextendPoly, kCrc32cUnextendPoly, 1, &reverse_table0_);\n\n  j = FillZeroesTable(kCrc32cUnextendPoly, &reverse_zeroes_);\n  ABSL_RAW_CHECK(j <= static_cast<int>(ABSL_ARRAYSIZE(this->reverse_zeroes_)),\n                 \"\");\n}\n\nvoid CRC32::Extend(uint32_t* crc, const void* bytes, size_t length) const {\n  const uint8_t* p = static_cast<const uint8_t*>(bytes);\n  const uint8_t* e = p + length;\n  uint32_t l = *crc;\n\n  auto step_one_byte = [this, &p, &l]() {\n    int c = (l & 0xff) ^ *p++;\n    l = this->table0_[c] ^ (l >> 8);\n  };\n\n  if (kNeedAlignedLoads) {\n    // point x at first 4-byte aligned byte in string. this might be past the\n    // end of the string.\n    const uint8_t* x = RoundUp<4>(p);\n    if (x <= e) {\n      // Process bytes until finished or p is 4-byte aligned\n      while (p != x) {\n        step_one_byte();\n      }\n    }\n  }\n\n  const size_t kSwathSize = 16;\n  if (static_cast<size_t>(e - p) >= kSwathSize) {\n    // Load one swath of data into the operating buffers.\n    uint32_t buf0 = absl::little_endian::Load32(p) ^ l;\n    uint32_t buf1 = absl::little_endian::Load32(p + 4);\n    uint32_t buf2 = absl::little_endian::Load32(p + 8);\n    uint32_t buf3 = absl::little_endian::Load32(p + 12);\n    p += kSwathSize;\n\n    // Increment a CRC value by a \"swath\"; this combines the four bytes\n    // starting at `ptr` and twelve zero bytes, so that four CRCs can be\n    // built incrementally and combined at the end.\n    const auto step_swath = [this](uint32_t crc_in, const std::uint8_t* ptr) {\n      return absl::little_endian::Load32(ptr) ^\n             this->table_[3][crc_in & 0xff] ^\n             this->table_[2][(crc_in >> 8) & 0xff] ^\n             this->table_[1][(crc_in >> 16) & 0xff] ^\n             this->table_[0][crc_in >> 24];\n    };\n\n    // Run one CRC calculation step over all swaths in one 16-byte stride\n    const auto step_stride = [&]() {\n      buf0 = step_swath(buf0, p);\n      buf1 = step_swath(buf1, p + 4);\n      buf2 = step_swath(buf2, p + 8);\n      buf3 = step_swath(buf3, p + 12);\n      p += 16;\n    };\n\n    // Process kStride interleaved swaths through the data in parallel.\n    while ((e - p) > kPrefetchHorizon) {\n      PrefetchToLocalCacheNta(\n          reinterpret_cast<const void*>(p + kPrefetchHorizon));\n      // Process 64 bytes at a time\n      step_stride();\n      step_stride();\n      step_stride();\n      step_stride();\n    }\n    while (static_cast<size_t>(e - p) >= kSwathSize) {\n      step_stride();\n    }\n\n    // Now advance one word at a time as far as possible. This isn't worth\n    // doing if we have word-advance tables.\n    while (static_cast<size_t>(e - p) >= 4) {\n      buf0 = step_swath(buf0, p);\n      uint32_t tmp = buf0;\n      buf0 = buf1;\n      buf1 = buf2;\n      buf2 = buf3;\n      buf3 = tmp;\n      p += 4;\n    }\n\n    // Combine the results from the different swaths. This is just a CRC\n    // on the data values in the bufX words.\n    auto combine_one_word = [this](uint32_t crc_in, uint32_t w) {\n      w ^= crc_in;\n      for (size_t i = 0; i < 4; ++i) {\n        w = (w >> 8) ^ this->table0_[w & 0xff];\n      }\n      return w;\n    };\n\n    l = combine_one_word(0, buf0);\n    l = combine_one_word(l, buf1);\n    l = combine_one_word(l, buf2);\n    l = combine_one_word(l, buf3);\n  }\n\n  // Process the last few bytes\n  while (p != e) {\n    step_one_byte();\n  }\n\n  *crc = l;\n}\n\nvoid CRC32::ExtendByZeroesImpl(uint32_t* crc, size_t length,\n                               const uint32_t zeroes_table[256],\n                               const uint32_t poly_table[256]) {\n  if (length != 0) {\n    uint32_t l = *crc;\n    // For each ZEROES_BASE_LG bits in length\n    // (after the low-order bits have been removed)\n    // we lookup the appropriate polynomial in the zeroes_ array\n    // and do a polynomial long multiplication (mod the CRC polynomial)\n    // to extend the CRC by the appropriate number of bits.\n    for (int i = 0; length != 0;\n         i += ZEROES_BASE - 1, length >>= ZEROES_BASE_LG) {\n      int c = length & (ZEROES_BASE - 1);  // pick next ZEROES_BASE_LG bits\n      if (c != 0) {                        // if they are not zero,\n                                           // multiply by entry in table\n        // Build a table to aid in multiplying 2 bits at a time.\n        // It takes too long to build tables for more bits.\n        uint64_t m = zeroes_table[c + i - 1];\n        m <<= 1;\n        uint64_t m2 = m << 1;\n        uint64_t mtab[4] = {0, m, m2, m2 ^ m};\n\n        // Do the multiply one byte at a time.\n        uint64_t result = 0;\n        for (int x = 0; x < 32; x += 8) {\n          // The carry-less multiply.\n          result ^= mtab[l & 3] ^ (mtab[(l >> 2) & 3] << 2) ^\n                    (mtab[(l >> 4) & 3] << 4) ^ (mtab[(l >> 6) & 3] << 6);\n          l >>= 8;\n\n          // Reduce modulo the polynomial\n          result = (result >> 8) ^ poly_table[result & 0xff];\n        }\n        l = static_cast<uint32_t>(result);\n      }\n    }\n    *crc = l;\n  }\n}\n\nvoid CRC32::ExtendByZeroes(uint32_t* crc, size_t length) const {\n  return CRC32::ExtendByZeroesImpl(crc, length, zeroes_, table0_);\n}\n\nvoid CRC32::UnextendByZeroes(uint32_t* crc, size_t length) const {\n  // See the comment in CRC32::InitTables() for an explanation of the algorithm\n  // below.\n  *crc = ReverseBits(*crc);\n  ExtendByZeroesImpl(crc, length, reverse_zeroes_, reverse_table0_);\n  *crc = ReverseBits(*crc);\n}\n\nvoid CRC32::Scramble(uint32_t* crc) const {\n  // Rotate by near half the word size plus 1.  See the scramble comment in\n  // crc_internal.h for an explanation.\n  constexpr int scramble_rotate = (32 / 2) + 1;\n  *crc = absl::rotr(static_cast<uint32_t>(*crc + kScrambleLo), scramble_rotate);\n}\n\nvoid CRC32::Unscramble(uint32_t* crc) const {\n  constexpr int scramble_rotate = (32 / 2) + 1;\n  uint64_t rotated = absl::rotl(*crc, scramble_rotate);\n  *crc = static_cast<uint32_t>(rotated - kScrambleLo);\n}\n\n// Constructor and destructor for base class CRC.\nCRC::~CRC() {}\nCRC::CRC() {}\n\n// The \"constructor\" for a CRC32C with a standard polynomial.\nCRC* CRC::Crc32c() {\n  static CRC* singleton = CRCImpl::NewInternal();\n  return singleton;\n}\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/internal/crc.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC_H_\n#define ABSL_CRC_INTERNAL_CRC_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\n// This class implements CRCs (aka Rabin Fingerprints).\n// Treats the input as a polynomial with coefficients in Z(2),\n// and finds the remainder when divided by an primitive polynomial\n// of the appropriate length.\n\n// A polynomial is represented by the bit pattern formed by its coefficients,\n// but with the highest order bit not stored.\n// The highest degree coefficient is stored in the lowest numbered bit\n// in the lowest addressed byte.   Thus, in what follows, the highest degree\n// coefficient that is stored is in the low order bit of \"lo\" or \"*lo\".\n\n// Hardware acceleration is used when available.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\nclass CRC {\n public:\n  virtual ~CRC();\n\n  // If \"*crc\" is the CRC of bytestring A, place the CRC of\n  // the bytestring formed from the concatenation of A and the \"length\"\n  // bytes at \"bytes\" into \"*crc\".\n  virtual void Extend(uint32_t* crc, const void* bytes,\n                      size_t length) const = 0;\n\n  // Equivalent to Extend(crc, bytes, length) where \"bytes\"\n  // points to an array of \"length\" zero bytes.\n  virtual void ExtendByZeroes(uint32_t* crc, size_t length) const = 0;\n\n  // Inverse operation of ExtendByZeroes.  If `crc` is the CRC value of a string\n  // ending in `length` zero bytes, this returns a CRC value of that string\n  // with those zero bytes removed.\n  virtual void UnextendByZeroes(uint32_t* crc, size_t length) const = 0;\n\n  // Apply a non-linear transformation to \"*crc\" so that\n  // it is safe to CRC the result with the same polynomial without\n  // any reduction of error-detection ability in the outer CRC.\n  // Unscramble() performs the inverse transformation.\n  // It is strongly recommended that CRCs be scrambled before storage or\n  // transmission, and unscrambled at the other end before further manipulation.\n  virtual void Scramble(uint32_t* crc) const = 0;\n  virtual void Unscramble(uint32_t* crc) const = 0;\n\n  // Crc32c() returns the singleton implementation of CRC for the CRC32C\n  // polynomial.  Returns a handle that MUST NOT be destroyed with delete.\n  static CRC* Crc32c();\n\n protected:\n  CRC();  // Clients may not call constructor; use Crc32c() instead.\n\n private:\n  CRC(const CRC&) = delete;\n  CRC& operator=(const CRC&) = delete;\n};\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC_H_\n"
  },
  {
    "path": "absl/crc/internal/crc32_x86_arm_combined_simd.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_\n#define ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\n// -------------------------------------------------------------------------\n// Many x86 and ARM machines have CRC acceleration hardware.\n// We can do a faster version of Extend() on such machines.\n// We define a translation layer for both x86 and ARM for the ease of use and\n// most performance gains.\n\n// This implementation requires 64-bit CRC instructions (part of SSE 4.2) and\n// PCLMULQDQ instructions. 32-bit builds with SSE 4.2 do exist, so the\n// __x86_64__ condition is necessary.\n#if defined(__x86_64__) && defined(__SSE4_2__) && defined(__PCLMUL__)\n\n#include <x86intrin.h>\n#define ABSL_CRC_INTERNAL_HAVE_X86_SIMD\n\n#elif defined(_MSC_VER) && !defined(__clang__) && defined(__AVX__) && \\\n    defined(_M_AMD64)\n\n// MSVC AVX (/arch:AVX) implies SSE 4.2 and PCLMULQDQ.\n#include <intrin.h>\n#define ABSL_CRC_INTERNAL_HAVE_X86_SIMD\n\n#elif defined(__aarch64__) && defined(__LITTLE_ENDIAN__) &&                 \\\n    defined(__ARM_FEATURE_CRC32) && defined(ABSL_INTERNAL_HAVE_ARM_NEON) && \\\n    defined(__ARM_FEATURE_CRYPTO)\n\n#include <arm_acle.h>\n#include <arm_neon.h>\n#define ABSL_CRC_INTERNAL_HAVE_ARM_SIMD\n\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \\\n    defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)\n\n#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)\nusing V128 = uint64x2_t;\n#else\n// Note: Do not use __m128i_u, it is not portable.\n// Use V128_LoadU() perform an unaligned load from __m128i*.\nusing V128 = __m128i;\n#endif\n\n// Starting with the initial value in |crc|, accumulates a CRC32 value for\n// unsigned integers of different sizes.\nuint32_t CRC32_u8(uint32_t crc, uint8_t v);\n\nuint32_t CRC32_u16(uint32_t crc, uint16_t v);\n\nuint32_t CRC32_u32(uint32_t crc, uint32_t v);\n\nuint32_t CRC32_u64(uint32_t crc, uint64_t v);\n\n// Loads 128 bits of integer data. |src| must be 16-byte aligned.\nV128 V128_Load(const V128* src);\n\n// Load 128 bits of integer data. |src| does not need to be aligned.\nV128 V128_LoadU(const V128* src);\n\n// Store 128 bits of integer data. |src| must be 16-byte aligned.\nvoid V128_Store(V128* dst, V128 data);\n\n// Polynomially multiplies the high 64 bits of |l| and |r|.\nV128 V128_PMulHi(const V128 l, const V128 r);\n\n// Polynomially multiplies the low 64 bits of |l| and |r|.\nV128 V128_PMulLow(const V128 l, const V128 r);\n\n// Polynomially multiplies the low 64 bits of |r| and high 64 bits of |l|.\nV128 V128_PMul01(const V128 l, const V128 r);\n\n// Polynomially multiplies the low 64 bits of |l| and high 64 bits of |r|.\nV128 V128_PMul10(const V128 l, const V128 r);\n\n// Produces a XOR operation of |l| and |r|.\nV128 V128_Xor(const V128 l, const V128 r);\n\n// Sets the lower half of a 128 bit register to the given 64-bit value and\n// zeroes the upper half.\n// dst[63:0] := |r|\n// dst[127:64] := |0|\nV128 V128_From64WithZeroFill(const uint64_t r);\n\n// Extracts a 32-bit integer from |l|, selected with |imm|.\ntemplate <int imm>\nint V128_Extract32(const V128 l);\n\n// Extracts a 64-bit integer from |l|, selected with |imm|.\ntemplate <int imm>\nuint64_t V128_Extract64(const V128 l);\n\n// Extracts the low 64 bits from V128.\nint64_t V128_Low64(const V128 l);\n\n// Add packed 64-bit integers in |l| and |r|.\nV128 V128_Add64(const V128 l, const V128 r);\n\n#endif\n\n#if defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)\n\ninline uint32_t CRC32_u8(uint32_t crc, uint8_t v) {\n  return _mm_crc32_u8(crc, v);\n}\n\ninline uint32_t CRC32_u16(uint32_t crc, uint16_t v) {\n  return _mm_crc32_u16(crc, v);\n}\n\ninline uint32_t CRC32_u32(uint32_t crc, uint32_t v) {\n  return _mm_crc32_u32(crc, v);\n}\n\ninline uint32_t CRC32_u64(uint32_t crc, uint64_t v) {\n  return static_cast<uint32_t>(_mm_crc32_u64(crc, v));\n}\n\ninline V128 V128_Load(const V128* src) { return _mm_load_si128(src); }\n\ninline V128 V128_LoadU(const V128* src) { return _mm_loadu_si128(src); }\n\ninline void V128_Store(V128* dst, V128 data) { _mm_store_si128(dst, data); }\n\ninline V128 V128_PMulHi(const V128 l, const V128 r) {\n  return _mm_clmulepi64_si128(l, r, 0x11);\n}\n\ninline V128 V128_PMulLow(const V128 l, const V128 r) {\n  return _mm_clmulepi64_si128(l, r, 0x00);\n}\n\ninline V128 V128_PMul01(const V128 l, const V128 r) {\n  return _mm_clmulepi64_si128(l, r, 0x01);\n}\n\ninline V128 V128_PMul10(const V128 l, const V128 r) {\n  return _mm_clmulepi64_si128(l, r, 0x10);\n}\n\ninline V128 V128_Xor(const V128 l, const V128 r) { return _mm_xor_si128(l, r); }\n\ninline V128 V128_From64WithZeroFill(const uint64_t r) {\n  return _mm_set_epi64x(static_cast<int64_t>(0), static_cast<int64_t>(r));\n}\n\ntemplate <int imm>\ninline int V128_Extract32(const V128 l) {\n  return _mm_extract_epi32(l, imm);\n}\n\ntemplate <int imm>\ninline uint64_t V128_Extract64(const V128 l) {\n  return static_cast<uint64_t>(_mm_extract_epi64(l, imm));\n}\n\ninline int64_t V128_Low64(const V128 l) { return _mm_cvtsi128_si64(l); }\n\ninline V128 V128_Add64(const V128 l, const V128 r) {\n  return _mm_add_epi64(l, r);\n}\n\n#elif defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)\n\ninline uint32_t CRC32_u8(uint32_t crc, uint8_t v) { return __crc32cb(crc, v); }\n\ninline uint32_t CRC32_u16(uint32_t crc, uint16_t v) {\n  return __crc32ch(crc, v);\n}\n\ninline uint32_t CRC32_u32(uint32_t crc, uint32_t v) {\n  return __crc32cw(crc, v);\n}\n\ninline uint32_t CRC32_u64(uint32_t crc, uint64_t v) {\n  return __crc32cd(crc, v);\n}\n\ninline V128 V128_Load(const V128* src) {\n  return vld1q_u64(reinterpret_cast<const uint64_t*>(src));\n}\n\ninline V128 V128_LoadU(const V128* src) {\n  return vld1q_u64(reinterpret_cast<const uint64_t*>(src));\n}\n\ninline void V128_Store(V128* dst, V128 data) {\n  vst1q_u64(reinterpret_cast<uint64_t*>(dst), data);\n}\n\n// Using inline assembly as clang does not generate the pmull2 instruction and\n// performance drops by 15-20%.\n// TODO(b/193678732): Investigate why there is a slight performance hit when\n// using intrinsics instead of inline assembly.\ninline V128 V128_PMulHi(const V128 l, const V128 r) {\n  uint64x2_t res;\n  __asm__ __volatile__(\"pmull2 %0.1q, %1.2d, %2.2d \\n\\t\"\n                       : \"=w\"(res)\n                       : \"w\"(l), \"w\"(r));\n  return res;\n}\n\n// TODO(b/193678732): Investigate why the compiler decides to move the constant\n// loop multiplicands from GPR to Neon registers every loop iteration.\ninline V128 V128_PMulLow(const V128 l, const V128 r) {\n  uint64x2_t res;\n  __asm__ __volatile__(\"pmull %0.1q, %1.1d, %2.1d \\n\\t\"\n                       : \"=w\"(res)\n                       : \"w\"(l), \"w\"(r));\n  return res;\n}\n\ninline V128 V128_PMul01(const V128 l, const V128 r) {\n  return reinterpret_cast<V128>(vmull_p64(\n      reinterpret_cast<poly64_t>(vget_high_p64(vreinterpretq_p64_u64(l))),\n      reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(r)))));\n}\n\ninline V128 V128_PMul10(const V128 l, const V128 r) {\n  return reinterpret_cast<V128>(vmull_p64(\n      reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(l))),\n      reinterpret_cast<poly64_t>(vget_high_p64(vreinterpretq_p64_u64(r)))));\n}\n\ninline V128 V128_Xor(const V128 l, const V128 r) { return veorq_u64(l, r); }\n\ninline V128 V128_From64WithZeroFill(const uint64_t r){\n  constexpr uint64x2_t kZero = {0, 0};\n  return vsetq_lane_u64(r, kZero, 0);\n}\n\n\ntemplate <int imm>\ninline int V128_Extract32(const V128 l) {\n  return vgetq_lane_s32(vreinterpretq_s32_u64(l), imm);\n}\n\ntemplate <int imm>\ninline uint64_t V128_Extract64(const V128 l) {\n  return vgetq_lane_u64(l, imm);\n}\n\ninline int64_t V128_Low64(const V128 l) {\n  return vgetq_lane_s64(vreinterpretq_s64_u64(l), 0);\n}\n\ninline V128 V128_Add64(const V128 l, const V128 r) { return vaddq_u64(l, r); }\n\n#endif\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_\n"
  },
  {
    "path": "absl/crc/internal/crc32c.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC32C_H_\n#define ABSL_CRC_INTERNAL_CRC32C_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/crc/crc32c.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n// Modifies a CRC32 value by removing `length` bytes with a value of 0 from\n// the end of the string.\n//\n// This is the inverse operation of ExtendCrc32cByZeroes().\n//\n// This operation has a runtime cost of O(log(`length`))\n//\n// Internal implementation detail, exposed for testing only.\ncrc32c_t UnextendCrc32cByZeroes(crc32c_t initial_crc, size_t length);\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC32C_H_\n"
  },
  {
    "path": "absl/crc/internal/crc32c_inline.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC32C_INLINE_H_\n#define ABSL_CRC_INTERNAL_CRC32C_INLINE_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/crc/internal/crc32_x86_arm_combined_simd.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n// CRC32C implementation optimized for small inputs.\n// Either computes crc and return true, or if there is\n// no hardware support does nothing and returns false.\ninline bool ExtendCrc32cInline(uint32_t* crc, const char* p, size_t n) {\n#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \\\n    defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)\n  constexpr uint32_t kCrc32Xor = 0xffffffffU;\n  *crc ^= kCrc32Xor;\n  if (n & 1) {\n    *crc = CRC32_u8(*crc, static_cast<uint8_t>(*p));\n    n--;\n    p++;\n  }\n  if (n & 2) {\n    *crc = CRC32_u16(*crc, absl::little_endian::Load16(p));\n    n -= 2;\n    p += 2;\n  }\n  if (n & 4) {\n    *crc = CRC32_u32(*crc, absl::little_endian::Load32(p));\n    n -= 4;\n    p += 4;\n  }\n  while (n) {\n    *crc = CRC32_u64(*crc, absl::little_endian::Load64(p));\n    n -= 8;\n    p += 8;\n  }\n  *crc ^= kCrc32Xor;\n  return true;\n#else\n  // No hardware support, signal the need to fallback.\n  static_cast<void>(crc);\n  static_cast<void>(p);\n  static_cast<void>(n);\n  return false;\n#endif  // defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) ||\n        // defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)\n}\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC32C_INLINE_H_\n"
  },
  {
    "path": "absl/crc/internal/crc_cord_state.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/internal/crc_cord_state.h\"\n\n#include <cassert>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/numeric/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\nCrcCordState::RefcountedRep* CrcCordState::RefSharedEmptyRep() {\n  static absl::NoDestructor<CrcCordState::RefcountedRep> empty;\n\n  assert(empty->count.load(std::memory_order_relaxed) >= 1);\n  assert(empty->rep.removed_prefix.length == 0);\n  assert(empty->rep.prefix_crc.empty());\n\n  Ref(empty.get());\n  return empty.get();\n}\n\nCrcCordState::CrcCordState() : refcounted_rep_(new RefcountedRep) {}\n\nCrcCordState::CrcCordState(const CrcCordState& other)\n    : refcounted_rep_(other.refcounted_rep_) {\n  Ref(refcounted_rep_);\n}\n\nCrcCordState::CrcCordState(CrcCordState&& other)\n    : refcounted_rep_(other.refcounted_rep_) {\n  // Make `other` valid for use after move.\n  other.refcounted_rep_ = RefSharedEmptyRep();\n}\n\nCrcCordState& CrcCordState::operator=(const CrcCordState& other) {\n  if (this != &other) {\n    Unref(refcounted_rep_);\n    refcounted_rep_ = other.refcounted_rep_;\n    Ref(refcounted_rep_);\n  }\n  return *this;\n}\n\nCrcCordState& CrcCordState::operator=(CrcCordState&& other) {\n  if (this != &other) {\n    Unref(refcounted_rep_);\n    refcounted_rep_ = other.refcounted_rep_;\n    // Make `other` valid for use after move.\n    other.refcounted_rep_ = RefSharedEmptyRep();\n  }\n  return *this;\n}\n\nCrcCordState::~CrcCordState() {\n  Unref(refcounted_rep_);\n}\n\ncrc32c_t CrcCordState::Checksum() const {\n  if (rep().prefix_crc.empty()) {\n    return absl::crc32c_t{0};\n  }\n  if (IsNormalized()) {\n    return rep().prefix_crc.back().crc;\n  }\n  return absl::RemoveCrc32cPrefix(\n      rep().removed_prefix.crc, rep().prefix_crc.back().crc,\n      rep().prefix_crc.back().length - rep().removed_prefix.length);\n}\n\nCrcCordState::PrefixCrc CrcCordState::NormalizedPrefixCrcAtNthChunk(\n    size_t n) const {\n  assert(n < NumChunks());\n  if (IsNormalized()) {\n    return rep().prefix_crc[n];\n  }\n  size_t length = rep().prefix_crc[n].length - rep().removed_prefix.length;\n  return PrefixCrc(length,\n                   absl::RemoveCrc32cPrefix(rep().removed_prefix.crc,\n                                            rep().prefix_crc[n].crc, length));\n}\n\nvoid CrcCordState::Normalize() {\n  if (IsNormalized() || rep().prefix_crc.empty()) {\n    return;\n  }\n\n  Rep* r = mutable_rep();\n  for (auto& prefix_crc : r->prefix_crc) {\n    size_t remaining = prefix_crc.length - r->removed_prefix.length;\n    prefix_crc.crc = absl::RemoveCrc32cPrefix(r->removed_prefix.crc,\n                                              prefix_crc.crc, remaining);\n    prefix_crc.length = remaining;\n  }\n  r->removed_prefix = PrefixCrc();\n}\n\nvoid CrcCordState::Poison() {\n  Rep* rep = mutable_rep();\n  if (NumChunks() > 0) {\n    for (auto& prefix_crc : rep->prefix_crc) {\n      // This is basically CRC32::Scramble().\n      uint32_t crc = static_cast<uint32_t>(prefix_crc.crc);\n      crc += 0x2e76e41b;\n      crc = absl::rotr(crc, 17);\n      prefix_crc.crc = crc32c_t{crc};\n    }\n  } else {\n    // Add a fake corrupt chunk.\n    rep->prefix_crc.emplace_back(0, crc32c_t{1});\n  }\n}\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/internal/crc_cord_state.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_\n#define ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_\n\n#include <atomic>\n#include <cstddef>\n#include <deque>\n\n#include \"absl/base/config.h\"\n#include \"absl/crc/crc32c.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n// CrcCordState is a copy-on-write class that holds the chunked CRC32C data\n// that allows CrcCord to perform efficient substring operations. CrcCordState\n// is used as a member variable in CrcCord. When a CrcCord is converted to a\n// Cord, the CrcCordState is shallow-copied into the root node of the Cord. If\n// the converted Cord is modified outside of CrcCord, the CrcCordState is\n// discarded from the Cord. If the Cord is converted back to a CrcCord, and the\n// Cord is still carrying the CrcCordState in its root node, the CrcCord can\n// re-use the CrcCordState, making the construction of the CrcCord cheap.\n//\n// CrcCordState does not try to encapsulate the CRC32C state (CrcCord requires\n// knowledge of how CrcCordState represents the CRC32C state). It does\n// encapsulate the copy-on-write nature of the state.\nclass CrcCordState {\n public:\n  // Constructors.\n  CrcCordState();\n  CrcCordState(const CrcCordState&);\n  CrcCordState(CrcCordState&&);\n\n  // Destructor. Atomically unreferences the data.\n  ~CrcCordState();\n\n  // Copy and move operators.\n  CrcCordState& operator=(const CrcCordState&);\n  CrcCordState& operator=(CrcCordState&&);\n\n  // A (length, crc) pair.\n  struct PrefixCrc {\n    PrefixCrc() = default;\n    PrefixCrc(size_t length_arg, absl::crc32c_t crc_arg)\n        : length(length_arg), crc(crc_arg) {}\n\n    size_t length = 0;\n\n    // TODO(absl-team): Memory stomping often zeros out memory. If this struct\n    // gets overwritten, we could end up with {0, 0}, which is the correct CRC\n    // for a string of length 0. Consider storing a scrambled value and\n    // unscrambling it before verifying it.\n    absl::crc32c_t crc = absl::crc32c_t{0};\n  };\n\n  // The representation of the chunked CRC32C data.\n  struct Rep {\n    // `removed_prefix` is the crc and length of any prefix that has been\n    // removed from the Cord (for example, by calling\n    // `CrcCord::RemovePrefix()`). To get the checksum of any prefix of the\n    // cord, this value must be subtracted from `prefix_crc`. See `Checksum()`\n    // for an example.\n    //\n    // CrcCordState is said to be \"normalized\" if removed_prefix.length == 0.\n    PrefixCrc removed_prefix;\n\n    // A deque of (length, crc) pairs, representing length and crc of a prefix\n    // of the Cord, before removed_prefix has been subtracted. The lengths of\n    // the prefixes are stored in increasing order. If the Cord is not empty,\n    // the last value in deque is the contains the CRC32C of the entire Cord\n    // when removed_prefix is subtracted from it.\n    std::deque<PrefixCrc> prefix_crc;\n  };\n\n  // Returns a reference to the representation of the chunked CRC32C data.\n  const Rep& rep() const { return refcounted_rep_->rep; }\n\n  // Returns a mutable reference to the representation of the chunked CRC32C\n  // data. Calling this function will copy the data if another instance also\n  // holds a reference to the data, so it is important to call rep() instead if\n  // the data may not be mutated.\n  Rep* mutable_rep() {\n    if (refcounted_rep_->count.load(std::memory_order_acquire) != 1) {\n      RefcountedRep* copy = new RefcountedRep;\n      copy->rep = refcounted_rep_->rep;\n      Unref(refcounted_rep_);\n      refcounted_rep_ = copy;\n    }\n    return &refcounted_rep_->rep;\n  }\n\n  // Returns the CRC32C of the entire Cord.\n  absl::crc32c_t Checksum() const;\n\n  // Returns true if the chunked CRC32C cached is normalized.\n  bool IsNormalized() const { return rep().removed_prefix.length == 0; }\n\n  // Normalizes the chunked CRC32C checksum cache by subtracting any removed\n  // prefix from the chunks.\n  void Normalize();\n\n  // Returns the number of cached chunks.\n  size_t NumChunks() const { return rep().prefix_crc.size(); }\n\n  // Helper that returns the (length, crc) of the `n`-th cached chunked.\n  PrefixCrc NormalizedPrefixCrcAtNthChunk(size_t n) const;\n\n  // Poisons all chunks to so that Checksum() will likely be incorrect with high\n  // probability.\n  void Poison();\n\n private:\n  struct RefcountedRep {\n    std::atomic<int32_t> count{1};\n    Rep rep;\n  };\n\n  // Adds a reference to the shared global empty `RefcountedRep`, and returns a\n  // pointer to the `RefcountedRep`. This is an optimization to avoid unneeded\n  // allocations when the allocation is unlikely to ever be used. The returned\n  // pointer can be `Unref()`ed when it is no longer needed.  Since the returned\n  // instance will always have a reference counter greater than 1, attempts to\n  // modify it (by calling `mutable_rep()`) will create a new unshared copy.\n  static RefcountedRep* RefSharedEmptyRep();\n\n  static void Ref(RefcountedRep* r) {\n    assert(r != nullptr);\n    r->count.fetch_add(1, std::memory_order_relaxed);\n  }\n\n  static void Unref(RefcountedRep* r) {\n    assert(r != nullptr);\n    if (r->count.fetch_sub(1, std::memory_order_acq_rel) == 1) {\n      delete r;\n    }\n  }\n\n  RefcountedRep* refcounted_rep_;\n};\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_\n"
  },
  {
    "path": "absl/crc/internal/crc_cord_state_test.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/internal/crc_cord_state.h\"\n\n#include <algorithm>\n#include <cstdint>\n#include <string>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/crc/crc32c.h\"\n\nnamespace {\n\nTEST(CrcCordState, Default) {\n  absl::crc_internal::CrcCordState state;\n  EXPECT_TRUE(state.IsNormalized());\n  EXPECT_EQ(state.Checksum(), absl::crc32c_t{0});\n  state.Normalize();\n  EXPECT_EQ(state.Checksum(), absl::crc32c_t{0});\n}\n\nTEST(CrcCordState, Normalize) {\n  absl::crc_internal::CrcCordState state;\n  auto* rep = state.mutable_rep();\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(1000, absl::crc32c_t{1000}));\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(2000, absl::crc32c_t{2000}));\n  rep->removed_prefix =\n      absl::crc_internal::CrcCordState::PrefixCrc(500, absl::crc32c_t{500});\n\n  // The removed_prefix means state is not normalized.\n  EXPECT_FALSE(state.IsNormalized());\n\n  absl::crc32c_t crc = state.Checksum();\n  state.Normalize();\n  EXPECT_TRUE(state.IsNormalized());\n\n  // The checksum should not change as a result of calling Normalize().\n  EXPECT_EQ(state.Checksum(), crc);\n  EXPECT_EQ(rep->removed_prefix.length, 0);\n}\n\nTEST(CrcCordState, Copy) {\n  absl::crc_internal::CrcCordState state;\n  auto* rep = state.mutable_rep();\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(1000, absl::crc32c_t{1000}));\n\n  absl::crc_internal::CrcCordState copy = state;\n\n  EXPECT_EQ(state.Checksum(), absl::crc32c_t{1000});\n  EXPECT_EQ(copy.Checksum(), absl::crc32c_t{1000});\n}\n\nTEST(CrcCordState, UnsharedSelfCopy) {\n  absl::crc_internal::CrcCordState state;\n  auto* rep = state.mutable_rep();\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(1000, absl::crc32c_t{1000}));\n\n  const absl::crc_internal::CrcCordState& ref = state;\n  state = ref;\n\n  EXPECT_EQ(state.Checksum(), absl::crc32c_t{1000});\n}\n\nTEST(CrcCordState, Move) {\n  absl::crc_internal::CrcCordState state;\n  auto* rep = state.mutable_rep();\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(1000, absl::crc32c_t{1000}));\n\n  absl::crc_internal::CrcCordState moved = std::move(state);\n  EXPECT_EQ(moved.Checksum(), absl::crc32c_t{1000});\n}\n\nTEST(CrcCordState, UnsharedSelfMove) {\n  absl::crc_internal::CrcCordState state;\n  auto* rep = state.mutable_rep();\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(1000, absl::crc32c_t{1000}));\n\n  absl::crc_internal::CrcCordState& ref = state;\n  state = std::move(ref);\n\n  EXPECT_EQ(state.Checksum(), absl::crc32c_t{1000});\n}\n\nTEST(CrcCordState, PoisonDefault) {\n  absl::crc_internal::CrcCordState state;\n  state.Poison();\n  EXPECT_NE(state.Checksum(), absl::crc32c_t{0});\n}\n\nTEST(CrcCordState, PoisonData) {\n  absl::crc_internal::CrcCordState state;\n  auto* rep = state.mutable_rep();\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(1000, absl::crc32c_t{1000}));\n  rep->prefix_crc.push_back(\n      absl::crc_internal::CrcCordState::PrefixCrc(2000, absl::crc32c_t{2000}));\n  rep->removed_prefix =\n      absl::crc_internal::CrcCordState::PrefixCrc(500, absl::crc32c_t{500});\n\n  absl::crc32c_t crc = state.Checksum();\n  state.Poison();\n  EXPECT_NE(state.Checksum(), crc);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/crc/internal/crc_internal.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC_INTERNAL_H_\n#define ABSL_CRC_INTERNAL_CRC_INTERNAL_H_\n\n#include <cstdint>\n#include <memory>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/crc/internal/crc.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace crc_internal {\n\n// Prefetch constants used in some Extend() implementations\nconstexpr int kPrefetchHorizon = ABSL_CACHELINE_SIZE * 4;  // Prefetch this far\n// Shorter prefetch distance for smaller buffers\nconstexpr int kPrefetchHorizonMedium = ABSL_CACHELINE_SIZE * 1;\nstatic_assert(kPrefetchHorizon >= 64, \"CRCPrefetchHorizon less than loop len\");\n\n// We require the Scramble() function:\n//  - to be reversible (Unscramble() must exist)\n//  - to be non-linear in the polynomial's Galois field (so the CRC of a\n//    scrambled CRC is not linearly affected by the scrambled CRC, even if\n//    using the same polynomial)\n//  - not to be its own inverse.  Preferably, if X=Scramble^N(X) and N!=0, then\n//    N is large.\n//  - to be fast.\n//  - not to change once defined.\n// We introduce non-linearity in two ways:\n//     Addition of a constant.\n//         - The carries introduce non-linearity; we use bits of an irrational\n//           (phi) to make it unlikely that we introduce no carries.\n//     Rotate by a constant number of bits.\n//         - We use floor(degree/2)+1, which does not divide the degree, and\n//           splits the bits nearly evenly, which makes it less likely the\n//           halves will be the same or one will be all zeroes.\n// We do both things to improve the chances of non-linearity in the face of\n// bit patterns with low numbers of bits set, while still being fast.\n// Below is the constant that we add.  The bits are the first 128 bits of the\n// fractional part of phi, with a 1 ored into the bottom bit to maximize the\n// cycle length of repeated adds.\nconstexpr uint64_t kScrambleHi = (static_cast<uint64_t>(0x4f1bbcdcU) << 32) |\n                                 static_cast<uint64_t>(0xbfa53e0aU);\nconstexpr uint64_t kScrambleLo = (static_cast<uint64_t>(0xf9ce6030U) << 32) |\n                                 static_cast<uint64_t>(0x2e76e41bU);\n\nclass CRCImpl : public CRC {  // Implementation of the abstract class CRC\n public:\n  using Uint32By256 = uint32_t[256];\n\n  CRCImpl() = default;\n  ~CRCImpl() override = default;\n\n  // The internal version of CRC::New().\n  static CRCImpl* NewInternal();\n\n  // Fill in a table for updating a CRC by one word of 'word_size' bytes\n  // [last_lo, last_hi] contains the answer if the last bit in the word\n  // is set.\n  static void FillWordTable(uint32_t poly, uint32_t last, int word_size,\n                            Uint32By256* t);\n\n  // Build the table for extending by zeroes, returning the number of entries.\n  // For a in {1, 2, ..., ZEROES_BASE-1}, b in {0, 1, 2, 3, ...},\n  // entry j=a-1+(ZEROES_BASE-1)*b\n  // contains a polynomial Pi such that multiplying\n  // a CRC by Pi mod P, where P is the CRC polynomial, is equivalent to\n  // appending a*2**(ZEROES_BASE_LG*b) zero bytes to the original string.\n  static int FillZeroesTable(uint32_t poly, Uint32By256* t);\n\n  virtual void InitTables() = 0;\n\n private:\n  CRCImpl(const CRCImpl&) = delete;\n  CRCImpl& operator=(const CRCImpl&) = delete;\n};\n\n// This is the 32-bit implementation.  It handles all sizes from 8 to 32.\nclass CRC32 : public CRCImpl {\n public:\n  CRC32() = default;\n  ~CRC32() override = default;\n\n  void Extend(uint32_t* crc, const void* bytes, size_t length) const override;\n  void ExtendByZeroes(uint32_t* crc, size_t length) const override;\n  void Scramble(uint32_t* crc) const override;\n  void Unscramble(uint32_t* crc) const override;\n  void UnextendByZeroes(uint32_t* crc, size_t length) const override;\n\n  void InitTables() override;\n\n private:\n  // Common implementation guts for ExtendByZeroes and UnextendByZeroes().\n  //\n  // zeroes_table is a table as returned by FillZeroesTable(), containing\n  // polynomials representing CRCs of strings-of-zeros of various lengths,\n  // and which can be combined by polynomial multiplication.  poly_table is\n  // a table of CRC byte extension values.  These tables are determined by\n  // the generator polynomial.\n  //\n  // These will be set to reverse_zeroes_ and reverse_table0_ for Unextend, and\n  // CRC32::zeroes_ and CRC32::table0_ for Extend.\n  static void ExtendByZeroesImpl(uint32_t* crc, size_t length,\n                                 const uint32_t zeroes_table[256],\n                                 const uint32_t poly_table[256]);\n\n  uint32_t table0_[256];  // table of byte extensions\n  uint32_t zeroes_[256];  // table of zero extensions\n\n  // table of 4-byte extensions shifted by 12 bytes of zeroes\n  uint32_t table_[4][256];\n\n  // Reverse lookup tables, using the alternate polynomial used by\n  // UnextendByZeroes().\n  uint32_t reverse_table0_[256];  // table of reverse byte extensions\n  uint32_t reverse_zeroes_[256];  // table of reverse zero extensions\n\n  CRC32(const CRC32&) = delete;\n  CRC32& operator=(const CRC32&) = delete;\n};\n\n// Helpers\n\n// RoundUp<N>(p) returns the lowest address >= p aligned to an N-byte\n// boundary.  Requires that N is a power of 2.\ntemplate <int alignment>\nconst uint8_t* RoundUp(const uint8_t* p) {\n  static_assert((alignment & (alignment - 1)) == 0, \"alignment is not 2^n\");\n  constexpr uintptr_t mask = alignment - 1;\n  const uintptr_t as_uintptr = reinterpret_cast<uintptr_t>(p);\n  return reinterpret_cast<const uint8_t*>((as_uintptr + mask) & ~mask);\n}\n\n// Return a newly created CRC32AcceleratedX86ARMCombined if we can use Intel's\n// or ARM's CRC acceleration for a given polynomial.  Return nullptr otherwise.\nCRCImpl* TryNewCRC32AcceleratedX86ARMCombined();\n\n// Return all possible hardware accelerated implementations. For testing only.\nstd::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll();\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC_INTERNAL_H_\n"
  },
  {
    "path": "absl/crc/internal/crc_memcpy.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_CRC_MEMCPY_H_\n#define ABSL_CRC_INTERNAL_CRC_MEMCPY_H_\n\n#include <cstddef>\n#include <memory>\n\n#include \"absl/base/config.h\"\n#include \"absl/crc/crc32c.h\"\n#include \"absl/crc/internal/crc32_x86_arm_combined_simd.h\"\n\n// Defined if the class AcceleratedCrcMemcpyEngine exists.\n// TODO(b/299127771): Consider relaxing the pclmul requirement once the other\n// intrinsics are conditionally compiled without it.\n#if defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)\n#define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1\n#elif defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)\n#define ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\nclass CrcMemcpyEngine {\n public:\n  virtual ~CrcMemcpyEngine() = default;\n\n  virtual crc32c_t Compute(void* __restrict dst, const void* __restrict src,\n                           std::size_t length, crc32c_t initial_crc) const = 0;\n\n protected:\n  CrcMemcpyEngine() = default;\n};\n\nclass CrcMemcpy {\n public:\n  static crc32c_t CrcAndCopy(void* __restrict dst, const void* __restrict src,\n                             std::size_t length,\n                             crc32c_t initial_crc = crc32c_t{0},\n                             bool non_temporal = false) {\n    static const ArchSpecificEngines engines = GetArchSpecificEngines();\n    auto* engine = non_temporal ? engines.non_temporal : engines.temporal;\n    return engine->Compute(dst, src, length, initial_crc);\n  }\n\n  // For testing only: get an architecture-specific engine for tests.\n  static std::unique_ptr<CrcMemcpyEngine> GetTestEngine(int vector,\n                                                        int integer);\n\n private:\n  struct ArchSpecificEngines {\n    CrcMemcpyEngine* temporal;\n    CrcMemcpyEngine* non_temporal;\n  };\n\n  static ArchSpecificEngines GetArchSpecificEngines();\n};\n\n// Fallback CRC-memcpy engine.\nclass FallbackCrcMemcpyEngine : public CrcMemcpyEngine {\n public:\n  FallbackCrcMemcpyEngine() = default;\n  FallbackCrcMemcpyEngine(const FallbackCrcMemcpyEngine&) = delete;\n  FallbackCrcMemcpyEngine operator=(const FallbackCrcMemcpyEngine&) = delete;\n\n  crc32c_t Compute(void* __restrict dst, const void* __restrict src,\n                   std::size_t length, crc32c_t initial_crc) const override;\n};\n\n// CRC Non-Temporal-Memcpy engine.\nclass CrcNonTemporalMemcpyEngine : public CrcMemcpyEngine {\n public:\n  CrcNonTemporalMemcpyEngine() = default;\n  CrcNonTemporalMemcpyEngine(const CrcNonTemporalMemcpyEngine&) = delete;\n  CrcNonTemporalMemcpyEngine operator=(const CrcNonTemporalMemcpyEngine&) =\n      delete;\n\n  crc32c_t Compute(void* __restrict dst, const void* __restrict src,\n                   std::size_t length, crc32c_t initial_crc) const override;\n};\n\n// CRC Non-Temporal-Memcpy AVX engine.\nclass CrcNonTemporalMemcpyAVXEngine : public CrcMemcpyEngine {\n public:\n  CrcNonTemporalMemcpyAVXEngine() = default;\n  CrcNonTemporalMemcpyAVXEngine(const CrcNonTemporalMemcpyAVXEngine&) = delete;\n  CrcNonTemporalMemcpyAVXEngine operator=(\n      const CrcNonTemporalMemcpyAVXEngine&) = delete;\n\n  crc32c_t Compute(void* __restrict dst, const void* __restrict src,\n                   std::size_t length, crc32c_t initial_crc) const override;\n};\n\n// Copy source to destination and return the CRC32C of the data copied.  If an\n// accelerated version is available, use the accelerated version, otherwise use\n// the generic fallback version.\ninline crc32c_t Crc32CAndCopy(void* __restrict dst, const void* __restrict src,\n                              std::size_t length,\n                              crc32c_t initial_crc = crc32c_t{0},\n                              bool non_temporal = false) {\n  return CrcMemcpy::CrcAndCopy(dst, src, length, initial_crc, non_temporal);\n}\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_CRC_MEMCPY_H_\n"
  },
  {
    "path": "absl/crc/internal/crc_memcpy_fallback.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstring>\n#include <memory>\n\n#include \"absl/base/config.h\"\n#include \"absl/crc/crc32c.h\"\n#include \"absl/crc/internal/crc_memcpy.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\nabsl::crc32c_t FallbackCrcMemcpyEngine::Compute(void* __restrict dst,\n                                                const void* __restrict src,\n                                                std::size_t length,\n                                                crc32c_t initial_crc) const {\n  constexpr size_t kBlockSize = 8192;\n  absl::crc32c_t crc = initial_crc;\n\n  const char* src_bytes = reinterpret_cast<const char*>(src);\n  char* dst_bytes = reinterpret_cast<char*>(dst);\n\n  // Copy + CRC loop - run 8k chunks until we are out of full chunks.  CRC\n  // then copy was found to be slightly more efficient in our test cases.\n  std::size_t offset = 0;\n  for (; offset + kBlockSize < length; offset += kBlockSize) {\n    crc = absl::ExtendCrc32c(crc,\n                             absl::string_view(src_bytes + offset, kBlockSize));\n    memcpy(dst_bytes + offset, src_bytes + offset, kBlockSize);\n  }\n\n  // Save some work if length is 0.\n  if (offset < length) {\n    std::size_t final_copy_size = length - offset;\n    crc = absl::ExtendCrc32c(\n        crc, absl::string_view(src_bytes + offset, final_copy_size));\n    memcpy(dst_bytes + offset, src_bytes + offset, final_copy_size);\n  }\n\n  return crc;\n}\n\n// Compile the following only if we don't have\n#if !defined(ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE) && \\\n    !defined(ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE)\n\nCrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() {\n  CrcMemcpy::ArchSpecificEngines engines;\n  engines.temporal = new FallbackCrcMemcpyEngine();\n  engines.non_temporal = new FallbackCrcMemcpyEngine();\n  return engines;\n}\n\nstd::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int /*vector*/,\n                                                          int /*integer*/) {\n  return std::make_unique<FallbackCrcMemcpyEngine>();\n}\n\n#endif  // !ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE &&\n        // !ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/internal/crc_memcpy_test.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/internal/crc_memcpy.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <limits>\n#include <memory>\n#include <string>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/crc/crc32c.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nenum CrcEngine {\n  ACCELERATED = 0,\n  NONTEMPORAL = 1,\n  FALLBACK = 2,\n};\n\n// Correctness tests:\n// - Every source/destination byte alignment 0-15, every size 0-511 bytes\n// - Arbitrarily aligned source, large size\ntemplate <size_t max_size>\nclass CrcMemcpyTest : public testing::Test {\n protected:\n  CrcMemcpyTest() {\n    source_ = std::make_unique<char[]>(kSize);\n    destination_ = std::make_unique<char[]>(kSize);\n  }\n  static constexpr size_t kAlignment = 16;\n  static constexpr size_t kMaxCopySize = max_size;\n  static constexpr size_t kSize = kAlignment + kMaxCopySize;\n  std::unique_ptr<char[]> source_;\n  std::unique_ptr<char[]> destination_;\n\n  absl::BitGen gen_;\n};\n\n// Small test is slightly larger 4096 bytes to allow coverage of the \"large\"\n// copy function.  The minimum size to exercise all code paths in that function\n// would be around 256 consecutive tests (getting every possible tail value\n// and 0-2 small copy loops after the main block), so testing from 4096-4500\n// will cover all of those code paths multiple times.\ntypedef CrcMemcpyTest<4500> CrcSmallTest;\ntypedef CrcMemcpyTest<(1 << 24)> CrcLargeTest;\n// Parametrize the small test so that it can be done with all configurations.\ntemplate <typename ParamsT>\nclass EngineParamTestTemplate : public CrcSmallTest,\n                                public ::testing::WithParamInterface<ParamsT> {\n protected:\n  EngineParamTestTemplate() {\n    if (GetParam().crc_engine_selector == FALLBACK) {\n      engine_ = std::make_unique<absl::crc_internal::FallbackCrcMemcpyEngine>();\n    } else if (GetParam().crc_engine_selector == NONTEMPORAL) {\n      engine_ =\n          std::make_unique<absl::crc_internal::CrcNonTemporalMemcpyEngine>();\n    } else {\n      engine_ = absl::crc_internal::CrcMemcpy::GetTestEngine(\n          GetParam().vector_lanes, GetParam().integer_lanes);\n    }\n  }\n\n  // Convenience method.\n  ParamsT GetParam() const {\n    return ::testing::WithParamInterface<ParamsT>::GetParam();\n  }\n\n  std::unique_ptr<absl::crc_internal::CrcMemcpyEngine> engine_;\n};\nstruct TestParams {\n  CrcEngine crc_engine_selector = ACCELERATED;\n  int vector_lanes = 0;\n  int integer_lanes = 0;\n};\nusing EngineParamTest = EngineParamTestTemplate<TestParams>;\n// SmallCorrectness is designed to exercise every possible set of code paths\n// in the memcpy code, not including the loop.\nTEST_P(EngineParamTest, SmallCorrectnessCheckSourceAlignment) {\n  constexpr size_t kTestSizes[] = {0, 100, 255, 512, 1024, 4000, kMaxCopySize};\n\n  for (size_t source_alignment = 0; source_alignment < kAlignment;\n       source_alignment++) {\n    for (auto size : kTestSizes) {\n      char* base_data = static_cast<char*>(source_.get()) + source_alignment;\n      for (size_t i = 0; i < size; i++) {\n        *(base_data + i) =\n            static_cast<char>(absl::Uniform<unsigned char>(gen_));\n      }\n      SCOPED_TRACE(absl::StrCat(\"engine=<\", GetParam().vector_lanes, \",\",\n                                GetParam().integer_lanes, \">, \", \"size=\", size,\n                                \", source_alignment=\", source_alignment));\n      absl::crc32c_t initial_crc =\n          absl::crc32c_t{absl::Uniform<uint32_t>(gen_)};\n      absl::crc32c_t experiment_crc =\n          engine_->Compute(destination_.get(), source_.get() + source_alignment,\n                           size, initial_crc);\n      // Check the memory region to make sure it is the same\n      int mem_comparison =\n          memcmp(destination_.get(), source_.get() + source_alignment, size);\n      SCOPED_TRACE(absl::StrCat(\"Error in memcpy of size: \", size,\n                                \" with source alignment: \", source_alignment));\n      ASSERT_EQ(mem_comparison, 0);\n      absl::crc32c_t baseline_crc = absl::ExtendCrc32c(\n          initial_crc,\n          absl::string_view(\n              static_cast<char*>(source_.get()) + source_alignment, size));\n      ASSERT_EQ(baseline_crc, experiment_crc);\n    }\n  }\n}\n\nTEST_P(EngineParamTest, SmallCorrectnessCheckDestAlignment) {\n  constexpr size_t kTestSizes[] = {0, 100, 255, 512, 1024, 4000, kMaxCopySize};\n\n  for (size_t dest_alignment = 0; dest_alignment < kAlignment;\n       dest_alignment++) {\n    for (auto size : kTestSizes) {\n      char* base_data = static_cast<char*>(source_.get());\n      for (size_t i = 0; i < size; i++) {\n        *(base_data + i) =\n            static_cast<char>(absl::Uniform<unsigned char>(gen_));\n      }\n      SCOPED_TRACE(absl::StrCat(\"engine=<\", GetParam().vector_lanes, \",\",\n                                GetParam().integer_lanes, \">, \", \"size=\", size,\n                                \", destination_alignment=\", dest_alignment));\n      absl::crc32c_t initial_crc =\n          absl::crc32c_t{absl::Uniform<uint32_t>(gen_)};\n      absl::crc32c_t experiment_crc =\n          engine_->Compute(destination_.get() + dest_alignment, source_.get(),\n                           size, initial_crc);\n      // Check the memory region to make sure it is the same\n      int mem_comparison =\n          memcmp(destination_.get() + dest_alignment, source_.get(), size);\n      SCOPED_TRACE(absl::StrCat(\"Error in memcpy of size: \", size,\n                                \" with dest alignment: \", dest_alignment));\n      ASSERT_EQ(mem_comparison, 0);\n      absl::crc32c_t baseline_crc = absl::ExtendCrc32c(\n          initial_crc,\n          absl::string_view(static_cast<char*>(source_.get()), size));\n      ASSERT_EQ(baseline_crc, experiment_crc);\n    }\n  }\n}\n\nINSTANTIATE_TEST_SUITE_P(EngineParamTest, EngineParamTest,\n                         ::testing::Values(\n                             // Tests for configurations that may occur in prod.\n                             TestParams{ACCELERATED, 3, 0},\n                             TestParams{ACCELERATED, 1, 2},\n                             TestParams{ACCELERATED, 1, 0},\n                             // Fallback test.\n                             TestParams{FALLBACK, 0, 0},\n                             // Non Temporal\n                             TestParams{NONTEMPORAL, 0, 0}));\n\n}  // namespace\n"
  },
  {
    "path": "absl/crc/internal/crc_memcpy_x86_arm_combined.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Simultaneous memcopy and CRC-32C for x86-64 and ARM 64. Uses integer\n// registers because XMM registers do not support the CRC instruction (yet).\n// While copying, compute the running CRC of the data being copied.\n//\n// It is assumed that any CPU running this code has SSE4.2 instructions\n// available (for CRC32C).  This file will do nothing if that is not true.\n//\n// The CRC instruction has a 3-byte latency, and we are stressing the ALU ports\n// here (unlike a traditional memcopy, which has almost no ALU use), so we will\n// need to copy in such a way that the CRC unit is used efficiently. We have two\n// regimes in this code:\n//  1. For operations of size < kCrcSmallSize, do the CRC then the memcpy\n//  2. For operations of size > kCrcSmallSize:\n//      a) compute an initial CRC + copy on a small amount of data to align the\n//         destination pointer on a 16-byte boundary.\n//      b) Split the data into 3 main regions and a tail (smaller than 48 bytes)\n//      c) Do the copy and CRC of the 3 main regions, interleaving (start with\n//         full cache line copies for each region, then move to single 16 byte\n//         pieces per region).\n//      d) Combine the CRCs with CRC32C::Concat.\n//      e) Copy the tail and extend the CRC with the CRC of the tail.\n// This method is not ideal for op sizes between ~1k and ~8k because CRC::Concat\n// takes a significant amount of time.  A medium-sized approach could be added\n// using 3 CRCs over fixed-size blocks where the zero-extensions required for\n// CRC32C::Concat can be precomputed.\n\n#ifdef __SSE4_2__\n#include <immintrin.h>\n#endif\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#endif\n\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <memory>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/prefetch.h\"\n#include \"absl/crc/crc32c.h\"\n#include \"absl/crc/internal/cpu_detect.h\"\n#include \"absl/crc/internal/crc32_x86_arm_combined_simd.h\"\n#include \"absl/crc/internal/crc_memcpy.h\"\n#include \"absl/strings/string_view.h\"\n\n#if defined(ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE) || \\\n    defined(ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\nnamespace {\n\ninline crc32c_t ShortCrcCopy(char* dst, const char* src, std::size_t length,\n                             crc32c_t crc) {\n  // Small copy: just go 1 byte at a time: being nice to the branch predictor\n  // is more important here than anything else\n  uint32_t crc_uint32 = static_cast<uint32_t>(crc);\n  for (std::size_t i = 0; i < length; i++) {\n    uint8_t data = *reinterpret_cast<const uint8_t*>(src);\n    crc_uint32 = CRC32_u8(crc_uint32, data);\n    *reinterpret_cast<uint8_t*>(dst) = data;\n    ++src;\n    ++dst;\n  }\n  return crc32c_t{crc_uint32};\n}\n\nconstexpr size_t kIntLoadsPerVec = sizeof(V128) / sizeof(uint64_t);\n\n// Common function for copying the tails of multiple large regions.\n// Disable ubsan for benign unaligned access. See b/254108538.\ntemplate <size_t vec_regions, size_t int_regions>\nABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED inline void LargeTailCopy(\n    crc32c_t* crcs, char** dst, const char** src, size_t region_size,\n    size_t copy_rounds) {\n  std::array<V128, vec_regions> data;\n  std::array<uint64_t, kIntLoadsPerVec * int_regions> int_data;\n\n  while (copy_rounds > 0) {\n    for (size_t i = 0; i < vec_regions; i++) {\n      size_t region = i;\n\n      auto* vsrc = reinterpret_cast<const V128*>(*src + region_size * region);\n      auto* vdst = reinterpret_cast<V128*>(*dst + region_size * region);\n\n      // Load the blocks, unaligned\n      data[i] = V128_LoadU(vsrc);\n\n      // Store the blocks, aligned\n      V128_Store(vdst, data[i]);\n\n      // Compute the running CRC\n      crcs[region] = crc32c_t{static_cast<uint32_t>(\n          CRC32_u64(static_cast<uint32_t>(crcs[region]),\n                    static_cast<uint64_t>(V128_Extract64<0>(data[i]))))};\n      crcs[region] = crc32c_t{static_cast<uint32_t>(\n          CRC32_u64(static_cast<uint32_t>(crcs[region]),\n                    static_cast<uint64_t>(V128_Extract64<1>(data[i]))))};\n    }\n\n    for (size_t i = 0; i < int_regions; i++) {\n      size_t region = vec_regions + i;\n\n      auto* usrc =\n          reinterpret_cast<const uint64_t*>(*src + region_size * region);\n      auto* udst = reinterpret_cast<uint64_t*>(*dst + region_size * region);\n\n      for (size_t j = 0; j < kIntLoadsPerVec; j++) {\n        size_t data_index = i * kIntLoadsPerVec + j;\n\n        int_data[data_index] = *(usrc + j);\n        crcs[region] = crc32c_t{CRC32_u64(static_cast<uint32_t>(crcs[region]),\n                                          int_data[data_index])};\n\n        *(udst + j) = int_data[data_index];\n      }\n    }\n\n    // Increment pointers\n    *src += sizeof(V128);\n    *dst += sizeof(V128);\n    --copy_rounds;\n  }\n}\n\n}  // namespace\n\ntemplate <size_t vec_regions, size_t int_regions>\nclass AcceleratedCrcMemcpyEngine : public CrcMemcpyEngine {\n public:\n  AcceleratedCrcMemcpyEngine() = default;\n  AcceleratedCrcMemcpyEngine(const AcceleratedCrcMemcpyEngine&) = delete;\n  AcceleratedCrcMemcpyEngine operator=(const AcceleratedCrcMemcpyEngine&) =\n      delete;\n\n  crc32c_t Compute(void* __restrict dst, const void* __restrict src,\n                   std::size_t length, crc32c_t initial_crc) const override;\n};\n\n// Disable ubsan for benign unaligned access. See b/254108538.\ntemplate <size_t vec_regions, size_t int_regions>\nABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED crc32c_t\nAcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute(\n    void* __restrict dst, const void* __restrict src, std::size_t length,\n    crc32c_t initial_crc) const {\n  constexpr std::size_t kRegions = vec_regions + int_regions;\n  static_assert(kRegions > 0, \"Must specify at least one region.\");\n  constexpr uint32_t kCrcDataXor = uint32_t{0xffffffff};\n  constexpr std::size_t kBlockSize = sizeof(V128);\n  constexpr std::size_t kCopyRoundSize = kRegions * kBlockSize;\n\n  // Number of blocks per cacheline.\n  constexpr std::size_t kBlocksPerCacheLine = ABSL_CACHELINE_SIZE / kBlockSize;\n\n  char* dst_bytes = static_cast<char*>(dst);\n  const char* src_bytes = static_cast<const char*>(src);\n\n  // Make sure that one prefetch per big block is enough to cover the whole\n  // dataset, and we don't prefetch too much.\n  static_assert(ABSL_CACHELINE_SIZE % kBlockSize == 0,\n                \"Cache lines are not divided evenly into blocks, may have \"\n                \"unintended behavior!\");\n\n  // Experimentally-determined boundary between a small and large copy.\n  // Below this number, spin-up and concatenation of CRCs takes enough time that\n  // it kills the throughput gains of using 3 regions and wide vectors.\n  constexpr size_t kCrcSmallSize = 256;\n\n  // Experimentally-determined prefetch distance.  Main loop copies will\n  // prefeth data 2 cache lines ahead.\n  constexpr std::size_t kPrefetchAhead = 2 * ABSL_CACHELINE_SIZE;\n\n  // Small-size CRC-memcpy : just do CRC + memcpy\n  if (length < kCrcSmallSize) {\n    crc32c_t crc =\n        ExtendCrc32c(initial_crc, absl::string_view(src_bytes, length));\n    memcpy(dst, src, length);\n    return crc;\n  }\n\n  // Start work on the CRC: undo the XOR from the previous calculation or set up\n  // the initial value of the CRC.\n  initial_crc = crc32c_t{static_cast<uint32_t>(initial_crc) ^ kCrcDataXor};\n\n  // Do an initial alignment copy, so we can use aligned store instructions to\n  // the destination pointer.  We align the destination pointer because the\n  // penalty for an unaligned load is small compared to the penalty of an\n  // unaligned store on modern CPUs.\n  std::size_t bytes_from_last_aligned =\n      reinterpret_cast<uintptr_t>(dst) & (kBlockSize - 1);\n  if (bytes_from_last_aligned != 0) {\n    std::size_t bytes_for_alignment = kBlockSize - bytes_from_last_aligned;\n\n    // Do the short-sized copy and CRC.\n    initial_crc =\n        ShortCrcCopy(dst_bytes, src_bytes, bytes_for_alignment, initial_crc);\n    src_bytes += bytes_for_alignment;\n    dst_bytes += bytes_for_alignment;\n    length -= bytes_for_alignment;\n  }\n\n  // We are going to do the copy and CRC in kRegions regions to make sure that\n  // we can saturate the CRC unit.  The CRCs will be combined at the end of the\n  // run.  Copying will use the SSE registers, and we will extract words from\n  // the SSE registers to add to the CRC.  Initially, we run the loop one full\n  // cache line per region at a time, in order to insert prefetches.\n\n  // Initialize CRCs for kRegions regions.\n  crc32c_t crcs[kRegions];\n  crcs[0] = initial_crc;\n  for (size_t i = 1; i < kRegions; i++) {\n    crcs[i] = crc32c_t{kCrcDataXor};\n  }\n\n  // Find the number of rounds to copy and the region size.  Also compute the\n  // tail size here.\n  size_t copy_rounds = length / kCopyRoundSize;\n\n  // Find the size of each region and the size of the tail.\n  const std::size_t region_size = copy_rounds * kBlockSize;\n  const std::size_t tail_size = length - (kRegions * region_size);\n\n  // Holding registers for data in each region.\n  std::array<V128, vec_regions> vec_data;\n  std::array<uint64_t, int_regions * kIntLoadsPerVec> int_data;\n\n  // Main loop.\n  while (copy_rounds > kBlocksPerCacheLine) {\n    // Prefetch kPrefetchAhead bytes ahead of each pointer.\n    for (size_t i = 0; i < kRegions; i++) {\n      absl::PrefetchToLocalCache(src_bytes + kPrefetchAhead + region_size * i);\n#ifdef ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE\n      // TODO(b/297082454): investigate dropping prefetch on x86.\n      absl::PrefetchToLocalCache(dst_bytes + kPrefetchAhead + region_size * i);\n#endif\n    }\n\n    // Load and store data, computing CRC on the way.\n    for (size_t i = 0; i < kBlocksPerCacheLine; i++) {\n      // Copy and CRC the data for the CRC regions.\n      for (size_t j = 0; j < vec_regions; j++) {\n        // Cycle which regions get vector load/store and integer load/store, to\n        // engage prefetching logic around vector load/stores and save issue\n        // slots by using the integer registers.\n        size_t region = (j + i) % kRegions;\n\n        auto* vsrc =\n            reinterpret_cast<const V128*>(src_bytes + region_size * region);\n        auto* vdst = reinterpret_cast<V128*>(dst_bytes + region_size * region);\n\n        // Load and CRC data.\n        vec_data[j] = V128_LoadU(vsrc + i);\n        crcs[region] = crc32c_t{static_cast<uint32_t>(\n            CRC32_u64(static_cast<uint32_t>(crcs[region]),\n                      static_cast<uint64_t>(V128_Extract64<0>(vec_data[j]))))};\n        crcs[region] = crc32c_t{static_cast<uint32_t>(\n            CRC32_u64(static_cast<uint32_t>(crcs[region]),\n                      static_cast<uint64_t>(V128_Extract64<1>(vec_data[j]))))};\n\n        // Store the data.\n        V128_Store(vdst + i, vec_data[j]);\n      }\n\n      // Preload the partial CRCs for the CLMUL subregions.\n      for (size_t j = 0; j < int_regions; j++) {\n        // Cycle which regions get vector load/store and integer load/store, to\n        // engage prefetching logic around vector load/stores and save issue\n        // slots by using the integer registers.\n        size_t region = (j + vec_regions + i) % kRegions;\n\n        auto* usrc =\n            reinterpret_cast<const uint64_t*>(src_bytes + region_size * region);\n        auto* udst =\n            reinterpret_cast<uint64_t*>(dst_bytes + region_size * region);\n\n        for (size_t k = 0; k < kIntLoadsPerVec; k++) {\n          size_t data_index = j * kIntLoadsPerVec + k;\n\n          // Load and CRC the data.\n          int_data[data_index] = *(usrc + i * kIntLoadsPerVec + k);\n          crcs[region] = crc32c_t{CRC32_u64(static_cast<uint32_t>(crcs[region]),\n                                            int_data[data_index])};\n\n          // Store the data.\n          *(udst + i * kIntLoadsPerVec + k) = int_data[data_index];\n        }\n      }\n    }\n\n    // Increment pointers\n    src_bytes += kBlockSize * kBlocksPerCacheLine;\n    dst_bytes += kBlockSize * kBlocksPerCacheLine;\n    copy_rounds -= kBlocksPerCacheLine;\n  }\n\n  // Copy and CRC the tails of each region.\n  LargeTailCopy<vec_regions, int_regions>(crcs, &dst_bytes, &src_bytes,\n                                          region_size, copy_rounds);\n\n  // Move the source and destination pointers to the end of the region\n  src_bytes += region_size * (kRegions - 1);\n  dst_bytes += region_size * (kRegions - 1);\n\n  // Copy and CRC the tail through the XMM registers.\n  std::size_t tail_blocks = tail_size / kBlockSize;\n  LargeTailCopy<0, 1>(&crcs[kRegions - 1], &dst_bytes, &src_bytes, 0,\n                      tail_blocks);\n\n  // Final tail copy for under 16 bytes.\n  crcs[kRegions - 1] =\n      ShortCrcCopy(dst_bytes, src_bytes, tail_size - tail_blocks * kBlockSize,\n                   crcs[kRegions - 1]);\n\n  if (kRegions == 1) {\n    // If there is only one region, finalize and return its CRC.\n    return crc32c_t{static_cast<uint32_t>(crcs[0]) ^ kCrcDataXor};\n  }\n\n  // Finalize the first CRCs: XOR the internal CRCs by the XOR mask to undo the\n  // XOR done before doing block copy + CRCs.\n  for (size_t i = 0; i + 1 < kRegions; i++) {\n    crcs[i] = crc32c_t{static_cast<uint32_t>(crcs[i]) ^ kCrcDataXor};\n  }\n\n  // Build a CRC of the first kRegions - 1 regions.\n  crc32c_t full_crc = crcs[0];\n  for (size_t i = 1; i + 1 < kRegions; i++) {\n    full_crc = ConcatCrc32c(full_crc, crcs[i], region_size);\n  }\n\n  // Finalize and concatenate the final CRC, then return.\n  crcs[kRegions - 1] =\n      crc32c_t{static_cast<uint32_t>(crcs[kRegions - 1]) ^ kCrcDataXor};\n  return ConcatCrc32c(full_crc, crcs[kRegions - 1], region_size + tail_size);\n}\n\nCrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() {\n#ifdef UNDEFINED_BEHAVIOR_SANITIZER\n  // UBSAN does not play nicely with unaligned loads (which we use a lot).\n  // Get the underlying architecture.\n  CpuType cpu_type = GetCpuType();\n  switch (cpu_type) {\n    case CpuType::kAmdRome:\n    case CpuType::kAmdNaples:\n    case CpuType::kAmdMilan:\n    case CpuType::kAmdGenoa:\n    case CpuType::kAmdRyzenV3000:\n    case CpuType::kIntelCascadelakeXeon:\n    case CpuType::kIntelSkylakeXeon:\n    case CpuType::kIntelSkylake:\n    case CpuType::kIntelBroadwell:\n    case CpuType::kIntelHaswell:\n    case CpuType::kIntelIvybridge:\n      return {\n          /*.temporal=*/new FallbackCrcMemcpyEngine(),\n          /*.non_temporal=*/new CrcNonTemporalMemcpyAVXEngine(),\n      };\n    // INTEL_SANDYBRIDGE performs better with SSE than AVX.\n    case CpuType::kIntelSandybridge:\n      return {\n          /*.temporal=*/new FallbackCrcMemcpyEngine(),\n          /*.non_temporal=*/new CrcNonTemporalMemcpyEngine(),\n      };\n    default:\n      return {/*.temporal=*/new FallbackCrcMemcpyEngine(),\n              /*.non_temporal=*/new FallbackCrcMemcpyEngine()};\n  }\n#else\n  // Get the underlying architecture.\n  CpuType cpu_type = GetCpuType();\n  switch (cpu_type) {\n    // On Zen 2, PEXTRQ uses 2 micro-ops, including one on the vector store port\n    // which data movement from the vector registers to the integer registers\n    // (where CRC32C happens) to crowd the same units as vector stores.  As a\n    // result, using that path exclusively causes bottlenecking on this port.\n    // We can avoid this bottleneck by using the integer side of the CPU for\n    // most operations rather than the vector side.  We keep a vector region to\n    // engage some of the prefetching logic in the cache hierarchy which seems\n    // to give vector instructions special treatment.  These prefetch units see\n    // strided access to each region, and do the right thing.\n    case CpuType::kAmdRome:\n    case CpuType::kAmdNaples:\n    case CpuType::kAmdMilan:\n    case CpuType::kAmdGenoa:\n    case CpuType::kAmdRyzenV3000:\n      return {\n          /*.temporal=*/new AcceleratedCrcMemcpyEngine<1, 2>(),\n          /*.non_temporal=*/new CrcNonTemporalMemcpyAVXEngine(),\n      };\n    // PCLMULQDQ is slow and we don't have wide enough issue width to take\n    // advantage of it.  For an unknown architecture, don't risk using CLMULs.\n    case CpuType::kIntelCascadelakeXeon:\n    case CpuType::kIntelSkylakeXeon:\n    case CpuType::kIntelSkylake:\n    case CpuType::kIntelBroadwell:\n    case CpuType::kIntelHaswell:\n    case CpuType::kIntelIvybridge:\n      return {\n          /*.temporal=*/new AcceleratedCrcMemcpyEngine<3, 0>(),\n          /*.non_temporal=*/new CrcNonTemporalMemcpyAVXEngine(),\n      };\n    // INTEL_SANDYBRIDGE performs better with SSE than AVX.\n    case CpuType::kIntelSandybridge:\n    // Use SIMD memcpy on ARM cores.\n    case CpuType::kArmNeoverseN1:\n    case CpuType::kArmNeoverseN2:\n    case CpuType::kArmNeoverseV1:\n    case CpuType::kArmNeoverseV2:\n      return {\n          /*.temporal=*/new AcceleratedCrcMemcpyEngine<3, 0>(),\n          /*.non_temporal=*/new CrcNonTemporalMemcpyEngine(),\n      };\n    default:\n      return {/*.temporal=*/new FallbackCrcMemcpyEngine(),\n              /*.non_temporal=*/new FallbackCrcMemcpyEngine()};\n  }\n#endif  // UNDEFINED_BEHAVIOR_SANITIZER\n}\n\n// For testing, allow the user to specify which engine they want.\nstd::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int vector,\n                                                          int integer) {\n  if (vector == 3 && integer == 0) {\n    return std::make_unique<AcceleratedCrcMemcpyEngine<3, 0>>();\n  } else if (vector == 1 && integer == 2) {\n    return std::make_unique<AcceleratedCrcMemcpyEngine<1, 2>>();\n  } else if (vector == 1 && integer == 0) {\n    return std::make_unique<AcceleratedCrcMemcpyEngine<1, 0>>();\n  }\n  return nullptr;\n}\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE ||\n        // ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE\n"
  },
  {
    "path": "absl/crc/internal/crc_non_temporal_memcpy.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n#include \"absl/crc/crc32c.h\"\n#include \"absl/crc/internal/crc_memcpy.h\"\n#include \"absl/crc/internal/non_temporal_memcpy.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\ncrc32c_t CrcNonTemporalMemcpyEngine::Compute(void* __restrict dst,\n                                             const void* __restrict src,\n                                             std::size_t length,\n                                             crc32c_t initial_crc) const {\n  constexpr size_t kBlockSize = 8192;\n  crc32c_t crc = initial_crc;\n\n  const char* src_bytes = reinterpret_cast<const char*>(src);\n  char* dst_bytes = reinterpret_cast<char*>(dst);\n\n  // Copy + CRC loop - run 8k chunks until we are out of full chunks.\n  std::size_t offset = 0;\n  for (; offset + kBlockSize < length; offset += kBlockSize) {\n    crc = absl::ExtendCrc32c(crc,\n                             absl::string_view(src_bytes + offset, kBlockSize));\n    non_temporal_store_memcpy(dst_bytes + offset, src_bytes + offset,\n                              kBlockSize);\n  }\n\n  // Save some work if length is 0.\n  if (offset < length) {\n    std::size_t final_copy_size = length - offset;\n    crc = ExtendCrc32c(crc,\n                       absl::string_view(src_bytes + offset, final_copy_size));\n\n    non_temporal_store_memcpy(dst_bytes + offset, src_bytes + offset,\n                              final_copy_size);\n  }\n\n  return crc;\n}\n\ncrc32c_t CrcNonTemporalMemcpyAVXEngine::Compute(void* __restrict dst,\n                                                const void* __restrict src,\n                                                std::size_t length,\n                                                crc32c_t initial_crc) const {\n  constexpr size_t kBlockSize = 8192;\n  crc32c_t crc = initial_crc;\n\n  const char* src_bytes = reinterpret_cast<const char*>(src);\n  char* dst_bytes = reinterpret_cast<char*>(dst);\n\n  // Copy + CRC loop - run 8k chunks until we are out of full chunks.\n  std::size_t offset = 0;\n  for (; offset + kBlockSize < length; offset += kBlockSize) {\n    crc = ExtendCrc32c(crc, absl::string_view(src_bytes + offset, kBlockSize));\n\n    non_temporal_store_memcpy_avx(dst_bytes + offset, src_bytes + offset,\n                                  kBlockSize);\n  }\n\n  // Save some work if length is 0.\n  if (offset < length) {\n    std::size_t final_copy_size = length - offset;\n    crc = ExtendCrc32c(crc,\n                       absl::string_view(src_bytes + offset, final_copy_size));\n\n    non_temporal_store_memcpy_avx(dst_bytes + offset, src_bytes + offset,\n                                  final_copy_size);\n  }\n\n  return crc;\n}\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/internal/crc_x86_arm_combined.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Hardware accelerated CRC32 computation on Intel and ARM architecture.\n\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/prefetch.h\"\n#include \"absl/crc/internal/cpu_detect.h\"\n#include \"absl/crc/internal/crc32_x86_arm_combined_simd.h\"\n#include \"absl/crc/internal/crc_internal.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/numeric/bits.h\"\n\n#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \\\n    defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)\n#define ABSL_INTERNAL_CAN_USE_SIMD_CRC32C\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n#if defined(ABSL_INTERNAL_CAN_USE_SIMD_CRC32C)\n\n// Implementation details not exported outside of file\nnamespace {\n\n// Some machines have CRC acceleration hardware.\n// We can do a faster version of Extend() on such machines.\nclass CRC32AcceleratedX86ARMCombined : public CRC32 {\n public:\n  CRC32AcceleratedX86ARMCombined() {}\n  ~CRC32AcceleratedX86ARMCombined() override {}\n  void ExtendByZeroes(uint32_t* crc, size_t length) const override;\n  uint32_t ComputeZeroConstant(size_t length) const;\n\n private:\n  CRC32AcceleratedX86ARMCombined(const CRC32AcceleratedX86ARMCombined&) =\n      delete;\n  CRC32AcceleratedX86ARMCombined& operator=(\n      const CRC32AcceleratedX86ARMCombined&) = delete;\n};\n\n// Constants for switching between algorithms.\n// Chosen by comparing speed at different powers of 2.\nconstexpr size_t kSmallCutoff = 256;\nconstexpr size_t kMediumCutoff = 2048;\n\n#define ABSL_INTERNAL_STEP1(crc, p)                   \\\n  do {                                                \\\n    crc = CRC32_u8(static_cast<uint32_t>(crc), *p++); \\\n  } while (0)\n#define ABSL_INTERNAL_STEP2(crc, p)                                            \\\n  do {                                                                         \\\n    crc =                                                                      \\\n        CRC32_u16(static_cast<uint32_t>(crc), absl::little_endian::Load16(p)); \\\n    p += 2;                                                                    \\\n  } while (0)\n#define ABSL_INTERNAL_STEP4(crc, p)                                            \\\n  do {                                                                         \\\n    crc =                                                                      \\\n        CRC32_u32(static_cast<uint32_t>(crc), absl::little_endian::Load32(p)); \\\n    p += 4;                                                                    \\\n  } while (0)\n#define ABSL_INTERNAL_STEP8(crc, p)                                            \\\n  do {                                                                         \\\n    crc =                                                                      \\\n        CRC32_u64(static_cast<uint32_t>(crc), absl::little_endian::Load64(p)); \\\n    p += 8;                                                                    \\\n  } while (0)\n#define ABSL_INTERNAL_STEP8BY2(crc0, crc1, p0, p1) \\\n  do {                                             \\\n    ABSL_INTERNAL_STEP8(crc0, p0);                 \\\n    ABSL_INTERNAL_STEP8(crc1, p1);                 \\\n  } while (0)\n#define ABSL_INTERNAL_STEP8BY3(crc0, crc1, crc2, p0, p1, p2) \\\n  do {                                                       \\\n    ABSL_INTERNAL_STEP8(crc0, p0);                           \\\n    ABSL_INTERNAL_STEP8(crc1, p1);                           \\\n    ABSL_INTERNAL_STEP8(crc2, p2);                           \\\n  } while (0)\n\nnamespace {\n\n// Does polynomial multiplication a * b * x^33 mod G.\n//\n// One of the multiplicands needs to have an extra factor of x^-33 to cancel out\n// the extra factor of x^33. The extra factor of x^33 comes from:\n//\n// - x^1 from the carry-less multiplication, due to the\n//   \"least-significant-bit-first\" convention of CRC-32C.\n//\n// - x^32 from using CRC32_u64() to reduce the carry-less product to 32 bits.\n//\n// Both could be avoided, but at the cost of extra instructions. It's more\n// efficient to just drop a factor of x^33 from one of the multiplicands.\nuint32_t MultiplyWithExtraX33(uint32_t a, uint32_t b) {\n  V128 a_vec = V128_From64WithZeroFill(a);\n  V128 b_vec = V128_From64WithZeroFill(b);\n  V128 res = V128_PMulLow(a_vec, b_vec);\n\n  return CRC32_u64(0, static_cast<uint64_t>(V128_Low64(res)));\n}\n\n// The number of low-order bits that ComputeZeroConstant() drops from the\n// length, i.e. treats as zeroes\nconstexpr int kNumDroppedBits = 4;\n\n// Precomputed constants for faster ExtendByZeroes(). This was generated by\n// gen_crc32c_consts.py. The entry at index i is x^(2^(i + 3 + kNumDroppedBits)\n// - 33) mod G. That is x^-33 times the polynomial by which the CRC value needs\n// to be multiplied to extend it by 2^(i + 3 + kNumDroppedBits) zero bits, or\n// equivalently 2^(i + kNumDroppedBits) zero bytes. The extra factor of x^-33\n// cancels out the extra factor of x^33 that MultiplyWithExtraX33() introduces.\nconstexpr uint32_t kCRC32CPowers[] = {\n    0x493c7d27, 0xba4fc28e, 0x9e4addf8, 0x0d3b6092, 0xb9e02b86, 0xdd7e3b0c,\n    0x170076fa, 0xa51b6135, 0x82f89c77, 0x54a86326, 0x1dc403cc, 0x5ae703ab,\n    0xc5013a36, 0xac2ac6dd, 0x9b4615a9, 0x688d1c61, 0xf6af14e6, 0xb6ffe386,\n    0xb717425b, 0x478b0d30, 0x54cc62e5, 0x7b2102ee, 0x8a99adef, 0xa7568c8f,\n    0xd610d67e, 0x6b086b3f, 0xd94f3c0b, 0xbf818109, 0x780d5a4d, 0x05ec76f1,\n    0x00000001, 0x493c7d27, 0xba4fc28e, 0x9e4addf8, 0x0d3b6092, 0xb9e02b86,\n    0xdd7e3b0c, 0x170076fa, 0xa51b6135, 0x82f89c77, 0x54a86326, 0x1dc403cc,\n    0x5ae703ab, 0xc5013a36, 0xac2ac6dd, 0x9b4615a9, 0x688d1c61, 0xf6af14e6,\n    0xb6ffe386, 0xb717425b, 0x478b0d30, 0x54cc62e5, 0x7b2102ee, 0x8a99adef,\n    0xa7568c8f, 0xd610d67e, 0x6b086b3f, 0xd94f3c0b, 0xbf818109, 0x780d5a4d,\n};\n// There must be an entry for each non-dropped bit in the size_t length.\nstatic_assert(std::size(kCRC32CPowers) >= sizeof(size_t) * 8 - kNumDroppedBits);\n\n}  // namespace\n\n// Compute a magic constant, so that multiplying by it is the same as extending\n// crc by length zeros. The lowest kNumDroppedBits of the length are ignored and\n// treated as zeroes; the caller is assumed to handle any nonzero bits there.\n#if defined(NDEBUG) && ABSL_HAVE_CPP_ATTRIBUTE(clang::no_sanitize)\n// The array accesses in this are safe: `length >= size_t{1} <<\n// kNumDroppedBits`, so `countr_zero(length >> kNumDroppedBits) < sizeof(size_t)\n// * 8 - kNumDroppedBits`, and `length & (length - 1)` cannot introduce bits\n// `>= sizeof(size_t) * 8 - kNumDroppedBits`. The compiler cannot prove this, so\n// manually disable bounds checking.\n[[clang::no_sanitize(\"array-bounds\")]]\n#endif\nuint32_t CRC32AcceleratedX86ARMCombined::ComputeZeroConstant(\n    size_t length) const {\n  length >>= kNumDroppedBits;\n\n  int index = absl::countr_zero(length);\n  uint32_t prev = kCRC32CPowers[index];\n  length &= length - 1;\n\n  while (length) {\n    // For each bit of length, extend by 2**n zeros.\n    index = absl::countr_zero(length);\n    prev = MultiplyWithExtraX33(prev, kCRC32CPowers[index]);\n    length &= length - 1;\n  }\n  return prev;\n}\n\nvoid CRC32AcceleratedX86ARMCombined::ExtendByZeroes(uint32_t* crc,\n                                                    size_t length) const {\n  uint32_t val = *crc;\n  // Don't bother with multiplication for small length.\n  if (length & 1) val = CRC32_u8(val, 0);\n  if (length & 2) val = CRC32_u16(val, 0);\n  if (length & 4) val = CRC32_u32(val, 0);\n  if (length & 8) val = CRC32_u64(val, 0);\n  static_assert(kNumDroppedBits == 4);\n  if (length >= size_t{1} << kNumDroppedBits) {\n    val = MultiplyWithExtraX33(val, ComputeZeroConstant(length));\n  }\n  *crc = val;\n}\n\n// Taken from Intel paper \"Fast CRC Computation for iSCSI Polynomial Using CRC32\n// Instruction\"\n// https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/crc-iscsi-polynomial-crc32-instruction-paper.pdf\n// We only need every 4th value, because we unroll loop by 4.\nconstexpr uint64_t kClmulConstants[] = {\n    0x09e4addf8, 0x0ba4fc28e, 0x00d3b6092, 0x09e4addf8, 0x0ab7aff2a,\n    0x102f9b8a2, 0x0b9e02b86, 0x00d3b6092, 0x1bf2e8b8a, 0x18266e456,\n    0x0d270f1a2, 0x0ab7aff2a, 0x11eef4f8e, 0x083348832, 0x0dd7e3b0c,\n    0x0b9e02b86, 0x0271d9844, 0x1b331e26a, 0x06b749fb2, 0x1bf2e8b8a,\n    0x0e6fc4e6a, 0x0ce7f39f4, 0x0d7a4825c, 0x0d270f1a2, 0x026f6a60a,\n    0x12ed0daac, 0x068bce87a, 0x11eef4f8e, 0x1329d9f7e, 0x0b3e32c28,\n    0x0170076fa, 0x0dd7e3b0c, 0x1fae1cc66, 0x010746f3c, 0x086d8e4d2,\n    0x0271d9844, 0x0b3af077a, 0x093a5f730, 0x1d88abd4a, 0x06b749fb2,\n    0x0c9c8b782, 0x0cec3662e, 0x1ddffc5d4, 0x0e6fc4e6a, 0x168763fa6,\n    0x0b0cd4768, 0x19b1afbc4, 0x0d7a4825c, 0x123888b7a, 0x00167d312,\n    0x133d7a042, 0x026f6a60a, 0x000bcf5f6, 0x19d34af3a, 0x1af900c24,\n    0x068bce87a, 0x06d390dec, 0x16cba8aca, 0x1f16a3418, 0x1329d9f7e,\n    0x19fb2a8b0, 0x02178513a, 0x1a0f717c4, 0x0170076fa,\n};\n\nenum class CutoffStrategy {\n  // Use 3 CRC streams to fold into 1.\n  Fold3,\n  // Unroll CRC instructions for 64 bytes.\n  Unroll64CRC,\n};\n\n// Base class for CRC32AcceleratedX86ARMCombinedMultipleStreams containing the\n// methods and data that don't need the template arguments.\nclass CRC32AcceleratedX86ARMCombinedMultipleStreamsBase\n    : public CRC32AcceleratedX86ARMCombined {\n protected:\n  // Update partialCRC with crc of 64 byte block. Calling FinalizePclmulStream\n  // would produce a single crc checksum, but it is expensive. PCLMULQDQ has a\n  // high latency, so we run 4 128-bit partial checksums that can be reduced to\n  // a single value by FinalizePclmulStream later. Computing crc for arbitrary\n  // polynomialas with PCLMULQDQ is described in Intel paper \"Fast CRC\n  // Computation for Generic Polynomials Using PCLMULQDQ Instruction\"\n  // https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf\n  // We are applying it to CRC32C polynomial.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesPclmul(\n      const uint8_t* p, V128* partialCRC) const {\n    V128 loopMultiplicands =\n        V128_Load(reinterpret_cast<const V128*>(kFoldAcross512Bits));\n\n    V128 partialCRC1 = partialCRC[0];\n    V128 partialCRC2 = partialCRC[1];\n    V128 partialCRC3 = partialCRC[2];\n    V128 partialCRC4 = partialCRC[3];\n\n    V128 tmp1 = V128_PMulHi(partialCRC1, loopMultiplicands);\n    V128 tmp2 = V128_PMulHi(partialCRC2, loopMultiplicands);\n    V128 tmp3 = V128_PMulHi(partialCRC3, loopMultiplicands);\n    V128 tmp4 = V128_PMulHi(partialCRC4, loopMultiplicands);\n    V128 data1 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 0));\n    V128 data2 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 1));\n    V128 data3 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 2));\n    V128 data4 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 3));\n    partialCRC1 = V128_PMulLow(partialCRC1, loopMultiplicands);\n    partialCRC2 = V128_PMulLow(partialCRC2, loopMultiplicands);\n    partialCRC3 = V128_PMulLow(partialCRC3, loopMultiplicands);\n    partialCRC4 = V128_PMulLow(partialCRC4, loopMultiplicands);\n    partialCRC1 = V128_Xor(tmp1, partialCRC1);\n    partialCRC2 = V128_Xor(tmp2, partialCRC2);\n    partialCRC3 = V128_Xor(tmp3, partialCRC3);\n    partialCRC4 = V128_Xor(tmp4, partialCRC4);\n    partialCRC1 = V128_Xor(partialCRC1, data1);\n    partialCRC2 = V128_Xor(partialCRC2, data2);\n    partialCRC3 = V128_Xor(partialCRC3, data3);\n    partialCRC4 = V128_Xor(partialCRC4, data4);\n    partialCRC[0] = partialCRC1;\n    partialCRC[1] = partialCRC2;\n    partialCRC[2] = partialCRC3;\n    partialCRC[3] = partialCRC4;\n  }\n\n  // Reduce partialCRC produced by Process64BytesPclmul into a single value,\n  // that represents crc checksum of all the processed bytes.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE uint64_t\n  FinalizePclmulStream(V128* partialCRC) const {\n    V128 partialCRC1 = partialCRC[0];\n    V128 partialCRC2 = partialCRC[1];\n    V128 partialCRC3 = partialCRC[2];\n    V128 partialCRC4 = partialCRC[3];\n\n    // Combine 4 vectors of partial crc into a single vector.\n    V128 reductionMultiplicands =\n        V128_Load(reinterpret_cast<const V128*>(kFoldAcross256Bits));\n\n    V128 low = V128_PMulLow(reductionMultiplicands, partialCRC1);\n    V128 high = V128_PMulHi(reductionMultiplicands, partialCRC1);\n\n    partialCRC1 = V128_Xor(low, high);\n    partialCRC1 = V128_Xor(partialCRC1, partialCRC3);\n\n    low = V128_PMulLow(reductionMultiplicands, partialCRC2);\n    high = V128_PMulHi(reductionMultiplicands, partialCRC2);\n\n    partialCRC2 = V128_Xor(low, high);\n    partialCRC2 = V128_Xor(partialCRC2, partialCRC4);\n\n    reductionMultiplicands =\n        V128_Load(reinterpret_cast<const V128*>(kFoldAcross128Bits));\n\n    low = V128_PMulLow(reductionMultiplicands, partialCRC1);\n    high = V128_PMulHi(reductionMultiplicands, partialCRC1);\n    V128 fullCRC = V128_Xor(low, high);\n    fullCRC = V128_Xor(fullCRC, partialCRC2);\n\n    // Reduce fullCRC into scalar value.\n    uint32_t crc = 0;\n    crc = CRC32_u64(crc, V128_Extract64<0>(fullCRC));\n    crc = CRC32_u64(crc, V128_Extract64<1>(fullCRC));\n    return crc;\n  }\n\n  // Update crc with 64 bytes of data from p.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE uint64_t Process64BytesCRC(const uint8_t* p,\n                                                          uint64_t crc) const {\n    for (int i = 0; i < 8; i++) {\n      crc =\n          CRC32_u64(static_cast<uint32_t>(crc), absl::little_endian::Load64(p));\n      p += 8;\n    }\n    return crc;\n  }\n\n  // Same as Process64BytesCRC, but just interleaved for 2 streams.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesCRC2Streams(\n      const uint8_t* p0, const uint8_t* p1, uint64_t* crc) const {\n    uint64_t crc0 = crc[0];\n    uint64_t crc1 = crc[1];\n    for (int i = 0; i < 8; i++) {\n      crc0 = CRC32_u64(static_cast<uint32_t>(crc0),\n                       absl::little_endian::Load64(p0));\n      crc1 = CRC32_u64(static_cast<uint32_t>(crc1),\n                       absl::little_endian::Load64(p1));\n      p0 += 8;\n      p1 += 8;\n    }\n    crc[0] = crc0;\n    crc[1] = crc1;\n  }\n\n  // Same as Process64BytesCRC, but just interleaved for 3 streams.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesCRC3Streams(\n      const uint8_t* p0, const uint8_t* p1, const uint8_t* p2,\n      uint64_t* crc) const {\n    uint64_t crc0 = crc[0];\n    uint64_t crc1 = crc[1];\n    uint64_t crc2 = crc[2];\n    for (int i = 0; i < 8; i++) {\n      crc0 = CRC32_u64(static_cast<uint32_t>(crc0),\n                       absl::little_endian::Load64(p0));\n      crc1 = CRC32_u64(static_cast<uint32_t>(crc1),\n                       absl::little_endian::Load64(p1));\n      crc2 = CRC32_u64(static_cast<uint32_t>(crc2),\n                       absl::little_endian::Load64(p2));\n      p0 += 8;\n      p1 += 8;\n      p2 += 8;\n    }\n    crc[0] = crc0;\n    crc[1] = crc1;\n    crc[2] = crc2;\n  }\n\n  // Constants generated by './scripts/gen-crc-consts.py x86_pclmul\n  // crc32_lsb_0x82f63b78' from the Linux kernel.\n  alignas(16) static constexpr uint64_t kFoldAcross512Bits[2] = {\n      // (x^543 mod G) * x^32\n      0x00000000740eef02,\n      // (x^479 mod G) * x^32\n      0x000000009e4addf8};\n  alignas(16) static constexpr uint64_t kFoldAcross256Bits[2] = {\n      // (x^287 mod G) * x^32\n      0x000000003da6d0cb,\n      // (x^223 mod G) * x^32\n      0x00000000ba4fc28e};\n  alignas(16) static constexpr uint64_t kFoldAcross128Bits[2] = {\n      // (x^159 mod G) * x^32\n      0x00000000f20c0dfe,\n      // (x^95 mod G) * x^32\n      0x00000000493c7d27};\n\n  // Medium runs of bytes are broken into groups of kGroupsSmall blocks of same\n  // size. Each group is CRCed in parallel then combined at the end of the\n  // block.\n  static constexpr size_t kGroupsSmall = 3;\n  // For large runs we use up to kMaxStreams blocks computed with CRC\n  // instruction, and up to kMaxStreams blocks computed with PCLMULQDQ, which\n  // are combined in the end.\n  static constexpr size_t kMaxStreams = 3;\n};\n\ntemplate <size_t num_crc_streams, size_t num_pclmul_streams,\n          CutoffStrategy strategy>\nclass CRC32AcceleratedX86ARMCombinedMultipleStreams\n    : public CRC32AcceleratedX86ARMCombinedMultipleStreamsBase {\n  ABSL_ATTRIBUTE_HOT\n  void Extend(uint32_t* crc, const void* bytes,\n              const size_t length) const override {\n    static_assert(num_crc_streams >= 1 && num_crc_streams <= kMaxStreams,\n                  \"Invalid number of crc streams\");\n    static_assert(num_pclmul_streams >= 0 && num_pclmul_streams <= kMaxStreams,\n                  \"Invalid number of pclmul streams\");\n    const uint8_t* p = static_cast<const uint8_t*>(bytes);\n    const uint8_t* e = p + length;\n    uint32_t l = *crc;\n    uint64_t l64;\n\n    // For small blocks just run simple loop, because cost of combining multiple\n    // streams is significant.\n    if (strategy != CutoffStrategy::Unroll64CRC && (length < kSmallCutoff)) {\n      // fallthrough; Use the same strategy as we do for processing the\n      // remaining bytes after any other strategy.\n    }  else if (length < kMediumCutoff) {\n      // For medium blocks we run 3 crc streams and combine them as described in\n      // Intel paper above. Running 4th stream doesn't help, because crc\n      // instruction has latency 3 and throughput 1.\n      l64 = l;\n      if (strategy == CutoffStrategy::Fold3) {\n        uint64_t l641 = 0;\n        uint64_t l642 = 0;\n        const size_t blockSize = 32;\n        size_t bs = static_cast<size_t>(e - p) / kGroupsSmall / blockSize;\n        const uint8_t* p1 = p + bs * blockSize;\n        const uint8_t* p2 = p1 + bs * blockSize;\n\n        for (size_t i = 0; i + 1 < bs; ++i) {\n          ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n          ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n          ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n          ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n          PrefetchToLocalCache(\n              reinterpret_cast<const char*>(p + kPrefetchHorizonMedium));\n          PrefetchToLocalCache(\n              reinterpret_cast<const char*>(p1 + kPrefetchHorizonMedium));\n          PrefetchToLocalCache(\n              reinterpret_cast<const char*>(p2 + kPrefetchHorizonMedium));\n        }\n        // Don't run crc on last 8 bytes.\n        ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n        ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n        ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);\n        ABSL_INTERNAL_STEP8BY2(l64, l641, p, p1);\n\n        V128 magic = *(reinterpret_cast<const V128*>(kClmulConstants) + bs - 1);\n\n        V128 tmp = V128_From64WithZeroFill(l64);\n\n        V128 res1 = V128_PMulLow(tmp, magic);\n\n        tmp = V128_From64WithZeroFill(l641);\n\n        V128 res2 = V128_PMul10(tmp, magic);\n        V128 x = V128_Xor(res1, res2);\n        l64 = static_cast<uint64_t>(V128_Low64(x)) ^\n              absl::little_endian::Load64(p2);\n        l64 = CRC32_u64(static_cast<uint32_t>(l642), l64);\n\n        p = p2 + 8;\n      } else if (strategy == CutoffStrategy::Unroll64CRC) {\n        while ((e - p) >= 64) {\n          l64 = Process64BytesCRC(p, l64);\n          p += 64;\n        }\n      }\n      l = static_cast<uint32_t>(l64);\n    } else {\n      // There is a lot of data, we can ignore combine costs and run all\n      // requested streams (num_crc_streams + num_pclmul_streams),\n      // using prefetch. CRC and PCLMULQDQ use different cpu execution units,\n      // so on some cpus it makes sense to execute both of them for different\n      // streams.\n\n      // Point x at first 8-byte aligned byte in string.\n      const uint8_t* x = RoundUp<8>(p);\n      // Process bytes until p is 8-byte aligned, if that isn't past the end.\n      while (p != x) {\n        ABSL_INTERNAL_STEP1(l, p);\n      }\n\n      size_t bs = static_cast<size_t>(e - p) /\n                  (num_crc_streams + num_pclmul_streams) / 64;\n      const uint8_t* crc_streams[kMaxStreams];\n      const uint8_t* pclmul_streams[kMaxStreams];\n      // We are guaranteed to have at least one crc stream.\n      crc_streams[0] = p;\n      for (size_t i = 1; i < num_crc_streams; i++) {\n        crc_streams[i] = crc_streams[i - 1] + bs * 64;\n      }\n      pclmul_streams[0] = crc_streams[num_crc_streams - 1] + bs * 64;\n      for (size_t i = 1; i < num_pclmul_streams; i++) {\n        pclmul_streams[i] = pclmul_streams[i - 1] + bs * 64;\n      }\n\n      // Per stream crc sums.\n      uint64_t l64_crc[kMaxStreams] = {l};\n      uint64_t l64_pclmul[kMaxStreams] = {0};\n\n      // Peel first iteration, because PCLMULQDQ stream, needs setup.\n      if (num_crc_streams == 1) {\n        l64_crc[0] = Process64BytesCRC(crc_streams[0], l64_crc[0]);\n        crc_streams[0] += 16 * 4;\n      } else if (num_crc_streams == 2) {\n        Process64BytesCRC2Streams(crc_streams[0], crc_streams[1], l64_crc);\n        crc_streams[0] += 16 * 4;\n        crc_streams[1] += 16 * 4;\n      } else {\n        Process64BytesCRC3Streams(crc_streams[0], crc_streams[1],\n                                  crc_streams[2], l64_crc);\n        crc_streams[0] += 16 * 4;\n        crc_streams[1] += 16 * 4;\n        crc_streams[2] += 16 * 4;\n      }\n\n      V128 partialCRC[kMaxStreams][4];\n      for (size_t i = 0; i < num_pclmul_streams; i++) {\n        partialCRC[i][0] = V128_LoadU(\n            reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 0));\n        partialCRC[i][1] = V128_LoadU(\n            reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 1));\n        partialCRC[i][2] = V128_LoadU(\n            reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 2));\n        partialCRC[i][3] = V128_LoadU(\n            reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 3));\n        pclmul_streams[i] += 16 * 4;\n      }\n\n      for (size_t i = 1; i < bs; i++) {\n        // Prefetch data for next iterations.\n        for (size_t j = 0; j < num_crc_streams; j++) {\n          PrefetchToLocalCache(\n              reinterpret_cast<const char*>(crc_streams[j] + kPrefetchHorizon));\n        }\n        for (size_t j = 0; j < num_pclmul_streams; j++) {\n          PrefetchToLocalCache(reinterpret_cast<const char*>(pclmul_streams[j] +\n                                                             kPrefetchHorizon));\n        }\n\n        // We process each stream in 64 byte blocks. This can be written as\n        // for (int i = 0; i < num_pclmul_streams; i++) {\n        //   Process64BytesPclmul(pclmul_streams[i], partialCRC[i]);\n        //   pclmul_streams[i] += 16 * 4;\n        // }\n        // for (int i = 0; i < num_crc_streams; i++) {\n        //   l64_crc[i] = Process64BytesCRC(crc_streams[i], l64_crc[i]);\n        //   crc_streams[i] += 16*4;\n        // }\n        // But unrolling and interleaving PCLMULQDQ and CRC blocks manually\n        // gives ~2% performance boost.\n        if (num_crc_streams == 1) {\n          l64_crc[0] = Process64BytesCRC(crc_streams[0], l64_crc[0]);\n          crc_streams[0] += 16 * 4;\n        } else if (num_crc_streams == 2) {\n          Process64BytesCRC2Streams(crc_streams[0], crc_streams[1], l64_crc);\n          crc_streams[0] += 16 * 4;\n          crc_streams[1] += 16 * 4;\n        } else {\n          Process64BytesCRC3Streams(crc_streams[0], crc_streams[1],\n                                    crc_streams[2], l64_crc);\n          crc_streams[0] += 16 * 4;\n          crc_streams[1] += 16 * 4;\n          crc_streams[2] += 16 * 4;\n        }\n        if (num_pclmul_streams > 0) {\n          Process64BytesPclmul(pclmul_streams[0], partialCRC[0]);\n          pclmul_streams[0] += 16 * 4;\n        }\n        if (num_pclmul_streams > 1) {\n          Process64BytesPclmul(pclmul_streams[1], partialCRC[1]);\n          pclmul_streams[1] += 16 * 4;\n        }\n        if (num_pclmul_streams > 2) {\n          Process64BytesPclmul(pclmul_streams[2], partialCRC[2]);\n          pclmul_streams[2] += 16 * 4;\n        }\n      }\n\n      // PCLMULQDQ based streams require special final step;\n      // CRC based don't.\n      for (size_t i = 0; i < num_pclmul_streams; i++) {\n        l64_pclmul[i] = FinalizePclmulStream(partialCRC[i]);\n      }\n\n      // Combine all streams into single result.\n      static_assert(64 % (1 << kNumDroppedBits) == 0);\n      uint32_t magic = ComputeZeroConstant(bs * 64);\n      l64 = l64_crc[0];\n      for (size_t i = 1; i < num_crc_streams; i++) {\n        l64 = MultiplyWithExtraX33(static_cast<uint32_t>(l64), magic);\n        l64 ^= l64_crc[i];\n      }\n      for (size_t i = 0; i < num_pclmul_streams; i++) {\n        l64 = MultiplyWithExtraX33(static_cast<uint32_t>(l64), magic);\n        l64 ^= l64_pclmul[i];\n      }\n\n      // Update p.\n      if (num_pclmul_streams > 0) {\n        p = pclmul_streams[num_pclmul_streams - 1];\n      } else {\n        p = crc_streams[num_crc_streams - 1];\n      }\n      l = static_cast<uint32_t>(l64);\n    }\n\n    uint64_t remaining_bytes = static_cast<uint64_t>(e - p);\n    // Process the remaining bytes.\n    while ((e - p) >= 16) {\n      ABSL_INTERNAL_STEP8(l, p);\n      ABSL_INTERNAL_STEP8(l, p);\n    }\n\n    if (remaining_bytes & 8) {\n      ABSL_INTERNAL_STEP8(l, p);\n    }\n    if (remaining_bytes & 4) {\n      ABSL_INTERNAL_STEP4(l, p);\n    }\n    if (remaining_bytes & 2) {\n      ABSL_INTERNAL_STEP2(l, p);\n    }\n    if (remaining_bytes & 1) {\n      ABSL_INTERNAL_STEP1(l, p);\n    }\n\n#undef ABSL_INTERNAL_STEP8BY3\n#undef ABSL_INTERNAL_STEP8BY2\n#undef ABSL_INTERNAL_STEP8\n#undef ABSL_INTERNAL_STEP4\n#undef ABSL_INTERNAL_STEP2\n#undef ABSL_INTERNAL_STEP1\n\n    *crc = l;\n  }\n};\n\n}  // namespace\n\n// Intel processors with SSE4.2 have an instruction for one particular\n// 32-bit CRC polynomial:  crc32c\nCRCImpl* TryNewCRC32AcceleratedX86ARMCombined() {\n  CpuType type = GetCpuType();\n  switch (type) {\n    case CpuType::kIntelHaswell:\n    case CpuType::kAmdRome:\n    case CpuType::kAmdNaples:\n    case CpuType::kAmdMilan:\n    case CpuType::kAmdGenoa:\n    case CpuType::kAmdTurin:\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          3, 1, CutoffStrategy::Fold3>();\n    // PCLMULQDQ is fast, use combined PCLMULQDQ + CRC implementation.\n    case CpuType::kIntelCascadelakeXeon:\n    case CpuType::kIntelSkylakeXeon:\n    case CpuType::kIntelBroadwell:\n    case CpuType::kIntelSkylake:\n    case CpuType::kIntelIcelake:\n    case CpuType::kIntelSapphirerapids:\n    case CpuType::kIntelEmeraldrapids:\n    case CpuType::kIntelGraniterapidsap:\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          3, 2, CutoffStrategy::Fold3>();\n    // PCLMULQDQ is slow, don't use it.\n    case CpuType::kIntelIvybridge:\n    case CpuType::kIntelSandybridge:\n    case CpuType::kIntelWestmere:\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          3, 0, CutoffStrategy::Fold3>();\n    case CpuType::kArmNeoverseN1:\n    case CpuType::kArmNeoverseN2:\n    case CpuType::kArmNeoverseV1:\n    case CpuType::kArmNeoverseN3:\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          1, 1, CutoffStrategy::Unroll64CRC>();\n    case CpuType::kAmpereSiryn:\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          3, 2, CutoffStrategy::Fold3>();\n    case CpuType::kArmNeoverseV2:\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          1, 2, CutoffStrategy::Unroll64CRC>();\n#if defined(__aarch64__)\n    default:\n      // Not all ARM processors support the needed instructions, so check here\n      // before trying to use an accelerated implementation.\n      if (SupportsArmCRC32PMULL()) {\n        return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n            1, 1, CutoffStrategy::Unroll64CRC>();\n      } else {\n        return nullptr;\n      }\n#else\n    default:\n      // Something else, play it safe and assume slow PCLMULQDQ.\n      return new CRC32AcceleratedX86ARMCombinedMultipleStreams<\n          3, 0, CutoffStrategy::Fold3>();\n#endif\n  }\n}\n\nstd::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll() {\n  auto ret = std::vector<std::unique_ptr<CRCImpl>>();\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 0, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 1, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 2, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 3, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 0, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 1, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 2, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 3, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 0, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 1, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 2, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 3, CutoffStrategy::Fold3>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 0, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 1, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 2, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    1, 3, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 0, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 1, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 2, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    2, 3, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 0, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 1, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 2, CutoffStrategy::Unroll64CRC>>());\n  ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<\n                    3, 3, CutoffStrategy::Unroll64CRC>>());\n\n  return ret;\n}\n\n#else  // !ABSL_INTERNAL_CAN_USE_SIMD_CRC32C\n\nstd::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll() {\n  return std::vector<std::unique_ptr<CRCImpl>>();\n}\n\n// no hardware acceleration available\nCRCImpl* TryNewCRC32AcceleratedX86ARMCombined() { return nullptr; }\n\n#endif\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/crc/internal/gen_crc32c_consts.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright 2025 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"This script generates kCRC32CPowers[].\"\"\"\n\n\ndef poly_mul(a, b):\n  \"\"\"Polynomial multiplication: a * b.\"\"\"\n  product = 0\n  for i in range(b.bit_length()):\n    if (b & (1 << i)) != 0:\n      product ^= a << i\n  return product\n\n\ndef poly_div(a, b):\n  \"\"\"Polynomial division: floor(a / b).\"\"\"\n  q = 0\n  while a.bit_length() >= b.bit_length():\n    q ^= 1 << (a.bit_length() - b.bit_length())\n    a ^= b << (a.bit_length() - b.bit_length())\n  return q\n\n\ndef poly_reduce(a, b):\n  \"\"\"Polynomial reduction: a mod b.\"\"\"\n  return a ^ poly_mul(poly_div(a, b), b)\n\n\ndef poly_exp(a, b, g):\n  \"\"\"Polynomial exponentiation: a^b mod g.\"\"\"\n  if b == 1:\n    return poly_reduce(a, g)\n  c = poly_exp(a, b // 2, g)\n  c = poly_mul(c, c)\n  if b % 2 != 0:\n    c = poly_mul(c, a)\n  return poly_reduce(c, g)\n\n\ndef bitreflect(a, num_bits):\n  \"\"\"Reflects the bits of the given integer.\"\"\"\n  if a.bit_length() > num_bits:\n    raise ValueError(f'Integer has more than {num_bits} bits')\n  return sum(((a >> i) & 1) << (num_bits - 1 - i) for i in range(num_bits))\n\n\nG = 0x11EDC6F41  # The CRC-32C reducing polynomial, in the \"natural\" bit order\nCRC_BITS = 32  # The degree of G, i.e. the 32 in \"CRC-32C\"\nLSB_FIRST = True  # CRC-32C is a least-significant-bit-first CRC\nNUM_SIZE_BITS = 64  # The maximum number of bits in the length (size_t)\nNUM_DROPPED_BITS = 4  # The number of bits dropped from the length\nLOG2_BITS_PER_BYTE = 3  # log2 of the number of bits in a byte, i.e. log2(8)\nX = 2  # The polynomial 'x', in the \"natural\" bit order\n\n\ndef print_crc32c_powers():\n  \"\"\"Generates kCRC32CPowers[].\n\n  kCRC32CPowers[] is an array of length NUM_SIZE_BITS - NUM_DROPPED_BITS,\n  whose i'th entry is x^(2^(i + LOG2_BITS_PER_BYTE + NUM_DROPPED_BITS) -\n  CRC_BITS - 1) mod G. See kCRC32CPowers[] in the C++ source for more info.\n  \"\"\"\n  for i in range(NUM_SIZE_BITS - NUM_DROPPED_BITS):\n    poly = poly_exp(\n        X,\n        2 ** (i + LOG2_BITS_PER_BYTE + NUM_DROPPED_BITS)\n        - CRC_BITS\n        - (1 if LSB_FIRST else 0),\n        G,\n    )\n    poly = bitreflect(poly, CRC_BITS)\n    print(f'0x{poly:0{2*CRC_BITS//8}x}, ', end='')\n\n\nif __name__ == '__main__':\n  print_crc32c_powers()\n"
  },
  {
    "path": "absl/crc/internal/non_temporal_arm_intrinsics.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_\n#define ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_\n\n#include \"absl/base/config.h\"\n\n#ifdef __aarch64__\n#include <arm_neon.h>\n\ntypedef int64x2_t __m128i; /* 128-bit vector containing integers */\n#define vreinterpretq_m128i_s64(x) (x)\n#define vreinterpretq_s64_m128i(x) (x)\n\n// Guarantees that every preceding store is globally visible before any\n// subsequent store.\n// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx\nstatic inline __attribute__((always_inline)) void _mm_sfence(void) {\n  __sync_synchronize();\n}\n\n// Load 128-bits of integer data from unaligned memory into dst. This intrinsic\n// may perform better than _mm_loadu_si128 when the data crosses a cache line\n// boundary.\n//\n//   dst[127:0] := MEM[mem_addr+127:mem_addr]\n//\n// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128\n#define _mm_lddqu_si128 _mm_loadu_si128\n\n// Loads 128-bit value. :\n// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx\nstatic inline __attribute__((always_inline)) __m128i _mm_loadu_si128(\n    const __m128i *p) {\n  return vreinterpretq_m128i_s64(vld1q_s64((const int64_t*)p));\n}\n\n// Stores the data in a to the address p without polluting the caches.  If the\n// cache line containing address p is already in the cache, the cache will be\n// updated.\n// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx\nstatic inline __attribute__((always_inline)) void _mm_stream_si128(__m128i *p,\n                                                                   __m128i a) {\n#if ABSL_HAVE_BUILTIN(__builtin_nontemporal_store)\n  __builtin_nontemporal_store(a, p);\n#else\n  vst1q_s64((int64_t *)p, vreinterpretq_s64_m128i(a));\n#endif\n}\n\n// Sets the 16 signed 8-bit integer values.\n// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx\nstatic inline __attribute__((always_inline)) __m128i _mm_set_epi8(\n    signed char b15, signed char b14, signed char b13, signed char b12,\n    signed char b11, signed char b10, signed char b9, signed char b8,\n    signed char b7, signed char b6, signed char b5, signed char b4,\n    signed char b3, signed char b2, signed char b1, signed char b0) {\n  int8_t __attribute__((aligned(16)))\n  data[16] = {(int8_t)b0,  (int8_t)b1,  (int8_t)b2,  (int8_t)b3,\n              (int8_t)b4,  (int8_t)b5,  (int8_t)b6,  (int8_t)b7,\n              (int8_t)b8,  (int8_t)b9,  (int8_t)b10, (int8_t)b11,\n              (int8_t)b12, (int8_t)b13, (int8_t)b14, (int8_t)b15};\n  return (__m128i)vld1q_s8(data);\n}\n#endif  // __aarch64__\n\n#endif  // ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_\n"
  },
  {
    "path": "absl/crc/internal/non_temporal_memcpy.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_CRC_INTERNAL_NON_TEMPORAL_MEMCPY_H_\n#define ABSL_CRC_INTERNAL_NON_TEMPORAL_MEMCPY_H_\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#endif\n\n#if defined(__SSE__) || defined(__AVX__)\n// Pulls in both SSE and AVX intrinsics.\n#include <immintrin.h>\n#endif\n\n#ifdef __aarch64__\n#include \"absl/crc/internal/non_temporal_arm_intrinsics.h\"\n#endif\n\n#include <algorithm>\n#include <cassert>\n#include <cstdint>\n#include <cstring>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace crc_internal {\n\n// This non-temporal memcpy does regular load and non-temporal store memory\n// copy. It is compatible to both 16-byte aligned and unaligned addresses. If\n// data at the destination is not immediately accessed, using non-temporal\n// memcpy can save 1 DRAM load of the destination cacheline.\nconstexpr size_t kCacheLineSize = ABSL_CACHELINE_SIZE;\n\n// If the objects overlap, the behavior is undefined. Uses regular memcpy\n// instead of non-temporal memcpy if the required CPU intrinsics are unavailable\n// at compile time.\ninline void *non_temporal_store_memcpy(void *__restrict dst,\n                                       const void *__restrict src, size_t len) {\n#if defined(__SSE3__) || defined(__aarch64__) || \\\n    (defined(_MSC_VER) && defined(__AVX__))\n  // This implementation requires SSE3.\n  // MSVC cannot target SSE3 directly, but when MSVC targets AVX,\n  // SSE3 support is implied.\n  uint8_t *d = reinterpret_cast<uint8_t *>(dst);\n  const uint8_t *s = reinterpret_cast<const uint8_t *>(src);\n\n  // memcpy() the misaligned header. At the end of this if block, <d> is\n  // aligned to a 64-byte cacheline boundary or <len> == 0.\n  if (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1)) {\n    uintptr_t bytes_before_alignment_boundary =\n        kCacheLineSize -\n        (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1));\n    size_t header_len = (std::min)(bytes_before_alignment_boundary, len);\n    assert(bytes_before_alignment_boundary < kCacheLineSize);\n    memcpy(d, s, header_len);\n    d += header_len;\n    s += header_len;\n    len -= header_len;\n  }\n\n  if (len >= kCacheLineSize) {\n    _mm_sfence();\n    __m128i *dst_cacheline = reinterpret_cast<__m128i *>(d);\n    const __m128i *src_cacheline = reinterpret_cast<const __m128i *>(s);\n    constexpr int kOpsPerCacheLine = kCacheLineSize / sizeof(__m128i);\n    size_t loops = len / kCacheLineSize;\n\n    while (len >= kCacheLineSize) {\n      __m128i temp1, temp2, temp3, temp4;\n      temp1 = _mm_lddqu_si128(src_cacheline + 0);\n      temp2 = _mm_lddqu_si128(src_cacheline + 1);\n      temp3 = _mm_lddqu_si128(src_cacheline + 2);\n      temp4 = _mm_lddqu_si128(src_cacheline + 3);\n      _mm_stream_si128(dst_cacheline + 0, temp1);\n      _mm_stream_si128(dst_cacheline + 1, temp2);\n      _mm_stream_si128(dst_cacheline + 2, temp3);\n      _mm_stream_si128(dst_cacheline + 3, temp4);\n      src_cacheline += kOpsPerCacheLine;\n      dst_cacheline += kOpsPerCacheLine;\n      len -= kCacheLineSize;\n    }\n    d += loops * kCacheLineSize;\n    s += loops * kCacheLineSize;\n    _mm_sfence();\n  }\n\n  // memcpy the tail.\n  if (len) {\n    memcpy(d, s, len);\n  }\n  return dst;\n#else\n  // Fallback to regular memcpy.\n  return memcpy(dst, src, len);\n#endif  // __SSE3__ || __aarch64__ || (_MSC_VER && __AVX__)\n}\n\n// We try to force non_temporal_store_memcpy_avx to use AVX instructions\n// so that we can select it at runtime when AVX is available.\n// Clang on Windows has gnu::target but does not make AVX types like __m256i\n// available when trying to force specific functions to use AVX compiles.\n#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::target) && !defined(_MSC_VER) && \\\n    (defined(__x86_64__) || defined(__i386__))\n#define ABSL_INTERNAL_CAN_FORCE_AVX 1\n#endif\n\n// If the objects overlap, the behavior is undefined. Uses regular memcpy\n// instead of non-temporal memcpy if the required CPU intrinsics are unavailable\n// at compile time.\n#ifdef ABSL_INTERNAL_CAN_FORCE_AVX\n[[gnu::target(\"avx\")]]\n#endif\ninline void *non_temporal_store_memcpy_avx(void *__restrict dst,\n                                           const void *__restrict src,\n                                           size_t len) {\n  // This function requires AVX. If possible we compile it with AVX even if the\n  // translation unit isn't built with AVX support. This works because we only\n  // select this implementation at runtime if the CPU supports AVX.\n  // MSVC AVX support implies SSE3 support.\n#if ((defined(__AVX__) || defined(ABSL_INTERNAL_CAN_FORCE_AVX)) && \\\n     defined(__SSE3__)) ||                                         \\\n    (defined(_MSC_VER) && defined(__AVX__))\n  uint8_t *d = reinterpret_cast<uint8_t *>(dst);\n  const uint8_t *s = reinterpret_cast<const uint8_t *>(src);\n\n  // memcpy() the misaligned header. At the end of this if block, <d> is\n  // aligned to a 64-byte cacheline boundary or <len> == 0.\n  if (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1)) {\n    uintptr_t bytes_before_alignment_boundary =\n        kCacheLineSize -\n        (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1));\n    size_t header_len = (std::min)(bytes_before_alignment_boundary, len);\n    assert(bytes_before_alignment_boundary < kCacheLineSize);\n    memcpy(d, s, header_len);\n    d += header_len;\n    s += header_len;\n    len -= header_len;\n  }\n\n  if (len >= kCacheLineSize) {\n    _mm_sfence();\n    __m256i *dst_cacheline = reinterpret_cast<__m256i *>(d);\n    const __m256i *src_cacheline = reinterpret_cast<const __m256i *>(s);\n    constexpr int kOpsPerCacheLine = kCacheLineSize / sizeof(__m256i);\n    size_t loops = len / kCacheLineSize;\n\n    while (len >= kCacheLineSize) {\n      __m256i temp1, temp2;\n      temp1 = _mm256_lddqu_si256(src_cacheline + 0);\n      temp2 = _mm256_lddqu_si256(src_cacheline + 1);\n      _mm256_stream_si256(dst_cacheline + 0, temp1);\n      _mm256_stream_si256(dst_cacheline + 1, temp2);\n      src_cacheline += kOpsPerCacheLine;\n      dst_cacheline += kOpsPerCacheLine;\n      len -= kCacheLineSize;\n    }\n    d += loops * kCacheLineSize;\n    s += loops * kCacheLineSize;\n    _mm_sfence();\n  }\n\n  // memcpy the tail.\n  if (len) {\n    memcpy(d, s, len);\n  }\n  return dst;\n#else\n  // Fallback to regular memcpy so that this function compiles.\n  return memcpy(dst, src, len);\n#endif\n}\n\n#undef ABSL_INTERNAL_CAN_FORCE_AVX\n\n}  // namespace crc_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_CRC_INTERNAL_NON_TEMPORAL_MEMCPY_H_\n"
  },
  {
    "path": "absl/crc/internal/non_temporal_memcpy_test.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/crc/internal/non_temporal_memcpy.h\"\n\n#include <algorithm>\n#include <cstdint>\n#include <iostream>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nstruct TestParam {\n  size_t copy_size;\n  uint32_t src_offset;\n  uint32_t dst_offset;\n};\n\nclass NonTemporalMemcpyTest : public testing::TestWithParam<TestParam> {\n protected:\n  void SetUp() override {\n    // Make buf_size multiple of 16 bytes.\n    size_t buf_size = ((std::max(GetParam().src_offset, GetParam().dst_offset) +\n                        GetParam().copy_size) +\n                       15) /\n                      16 * 16;\n    a_.resize(buf_size);\n    b_.resize(buf_size);\n    for (size_t i = 0; i < buf_size; i++) {\n      a_[i] = static_cast<uint8_t>(i % 256);\n      b_[i] = ~a_[i];\n    }\n  }\n\n  std::vector<uint8_t> a_, b_;\n};\n\nTEST_P(NonTemporalMemcpyTest, SSEEquality) {\n  uint8_t *src = a_.data() + GetParam().src_offset;\n  uint8_t *dst = b_.data() + GetParam().dst_offset;\n  absl::crc_internal::non_temporal_store_memcpy(dst, src, GetParam().copy_size);\n  for (size_t i = 0; i < GetParam().copy_size; i++) {\n    EXPECT_EQ(src[i], dst[i]);\n  }\n}\n\n#ifdef __AVX__\nTEST_P(NonTemporalMemcpyTest, AVXEquality) {\n  uint8_t* src = a_.data() + GetParam().src_offset;\n  uint8_t* dst = b_.data() + GetParam().dst_offset;\n\n  absl::crc_internal::non_temporal_store_memcpy_avx(dst, src,\n                                                    GetParam().copy_size);\n  for (size_t i = 0; i < GetParam().copy_size; i++) {\n    EXPECT_EQ(src[i], dst[i]);\n  }\n}\n#endif\n\n// 63B is smaller than one cacheline operation thus the non-temporal routine\n// will not be called.\n// 4352B is sufficient for testing 4092B data copy with room for offsets.\nconstexpr TestParam params[] = {\n    {63, 0, 0},       {58, 5, 5},    {61, 2, 0},    {61, 0, 2},\n    {58, 5, 2},       {4096, 0, 0},  {4096, 0, 1},  {4096, 0, 2},\n    {4096, 0, 3},     {4096, 0, 4},  {4096, 0, 5},  {4096, 0, 6},\n    {4096, 0, 7},     {4096, 0, 8},  {4096, 0, 9},  {4096, 0, 10},\n    {4096, 0, 11},    {4096, 0, 12}, {4096, 0, 13}, {4096, 0, 14},\n    {4096, 0, 15},    {4096, 7, 7},  {4096, 3, 0},  {4096, 1, 0},\n    {4096, 9, 3},     {4096, 9, 11}, {8192, 0, 0},  {8192, 5, 2},\n    {1024768, 7, 11}, {1, 0, 0},     {1, 0, 1},     {1, 1, 0},\n    {1, 1, 1}};\n\nINSTANTIATE_TEST_SUITE_P(ParameterizedNonTemporalMemcpyTest,\n                         NonTemporalMemcpyTest, testing::ValuesIn(params));\n\n}  // namespace\n"
  },
  {
    "path": "absl/debugging/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"stacktrace\",\n    srcs = [\n        \"internal/stacktrace_aarch64-inl.inc\",\n        \"internal/stacktrace_arm-inl.inc\",\n        \"internal/stacktrace_config.h\",\n        \"internal/stacktrace_emscripten-inl.inc\",\n        \"internal/stacktrace_generic-inl.inc\",\n        \"internal/stacktrace_powerpc-inl.inc\",\n        \"internal/stacktrace_riscv-inl.inc\",\n        \"internal/stacktrace_unimplemented-inl.inc\",\n        \"internal/stacktrace_win32-inl.inc\",\n        \"internal/stacktrace_x86-inl.inc\",\n        \"stacktrace.cc\",\n    ],\n    hdrs = [\"stacktrace.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":debugging_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:malloc_internal\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_test(\n    name = \"stacktrace_test\",\n    srcs = [\"stacktrace_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":stacktrace\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:errno_saver\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"symbolize\",\n    srcs = [\n        \"symbolize.cc\",\n        \"symbolize_darwin.inc\",\n        \"symbolize_elf.inc\",\n        \"symbolize_emscripten.inc\",\n        \"symbolize_unimplemented.inc\",\n        \"symbolize_win32.inc\",\n    ],\n    hdrs = [\n        \"internal/symbolize.h\",\n        \"symbolize.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [\"-DEFAULTLIB:dbghelp.lib\"],\n        \"@rules_cc//cc/compiler:clang-cl\": [\"-DEFAULTLIB:dbghelp.lib\"],\n        \"//absl:mingw_compiler\": [\n            \"-DEFAULTLIB:dbghelp.lib\",\n            \"-ldbghelp\",\n        ],\n        \"//conditions:default\": [],\n    }),\n    deps = [\n        \":debugging_internal\",\n        \":demangle_internal\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:malloc_internal\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_test(\n    name = \"symbolize_test\",\n    srcs = [\"symbolize_test.cc\"],\n    copts = ABSL_TEST_COPTS + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [\"/Z7\"],\n        \"@rules_cc//cc/compiler:clang-cl\": [\"/Z7\"],\n        \"//conditions:default\": [],\n    }),\n    linkopts = ABSL_DEFAULT_LINKOPTS + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [\"/DEBUG\"],\n        \"@rules_cc//cc/compiler:clang-cl\": [\"/DEBUG\"],\n        \"//conditions:default\": [],\n    }),\n    deps = [\n        \":stack_consumption\",\n        \":symbolize\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:malloc_internal\",\n        \"//absl/cleanup\",\n        \"//absl/log\",\n        \"//absl/log:check\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"examine_stack\",\n    srcs = [\n        \"internal/examine_stack.cc\",\n    ],\n    hdrs = [\n        \"internal/examine_stack.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/log/internal:__pkg__\",\n    ],\n    deps = [\n        \":stacktrace\",\n        \":symbolize\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"failure_signal_handler\",\n    srcs = [\"failure_signal_handler.cc\"],\n    hdrs = [\"failure_signal_handler.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":examine_stack\",\n        \":stacktrace\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_test(\n    name = \"failure_signal_handler_test\",\n    srcs = [\"failure_signal_handler_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"@rules_cc//cc/compiler:clang-cl\": [],\n        \"@rules_cc//cc/compiler:emscripten\": [],\n        \"//conditions:default\": [\"-pthread\"],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":failure_signal_handler\",\n        \":stacktrace\",\n        \":symbolize\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/log:check\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"debugging_internal\",\n    srcs = [\n        \"internal/address_is_readable.cc\",\n        \"internal/elf_mem_image.cc\",\n        \"internal/vdso_support.cc\",\n    ],\n    hdrs = [\n        \"internal/address_is_readable.h\",\n        \"internal/addresses.h\",\n        \"internal/elf_mem_image.h\",\n        \"internal/vdso_support.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//absl:friends\"],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:errno_saver\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"demangle_internal\",\n    srcs = [\"internal/demangle.cc\"],\n    hdrs = [\"internal/demangle.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/container:__pkg__\",\n        \"//absl/debugging:__pkg__\",\n    ],\n    deps = [\n        \":demangle_rust\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_test(\n    name = \"demangle_test\",\n    srcs = [\"internal/demangle_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":demangle_internal\",\n        \":stack_consumption\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/log\",\n        \"//absl/memory\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"bounded_utf8_length_sequence\",\n    hdrs = [\"internal/bounded_utf8_length_sequence.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_test(\n    name = \"bounded_utf8_length_sequence_test\",\n    srcs = [\"internal/bounded_utf8_length_sequence_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bounded_utf8_length_sequence\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"decode_rust_punycode\",\n    srcs = [\"internal/decode_rust_punycode.cc\"],\n    hdrs = [\"internal/decode_rust_punycode.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bounded_utf8_length_sequence\",\n        \":utf8_for_code_point\",\n        \"//absl/base:config\",\n        \"//absl/base:nullability\",\n    ],\n)\n\ncc_test(\n    name = \"decode_rust_punycode_test\",\n    srcs = [\"internal/decode_rust_punycode_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":decode_rust_punycode\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"demangle_rust\",\n    srcs = [\"internal/demangle_rust.cc\"],\n    hdrs = [\"internal/demangle_rust.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":decode_rust_punycode\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"demangle_rust_test\",\n    srcs = [\"internal/demangle_rust_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":demangle_rust\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"utf8_for_code_point\",\n    srcs = [\"internal/utf8_for_code_point.cc\"],\n    hdrs = [\"internal/utf8_for_code_point.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\"//absl/base:config\"],\n)\n\ncc_test(\n    name = \"utf8_for_code_point_test\",\n    srcs = [\"internal/utf8_for_code_point_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":utf8_for_code_point\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"leak_check\",\n    srcs = [\"leak_check.cc\"],\n    hdrs = [\"leak_check.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"leak_check_test\",\n    srcs = [\"leak_check_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"notsan\"],\n    deps = [\n        \":leak_check\",\n        \"//absl/base:config\",\n        \"//absl/log\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\n# Binary that leaks memory and expects to fail on exit.  This isn't a\n# test that expected to pass on its own; it exists to be called by a\n# script that checks exit status and output.\n# TODO(absl-team): Write a test to run this with a script that\n# verifies that it correctly fails.\ncc_binary(\n    name = \"leak_check_fail_test_binary\",\n    srcs = [\"leak_check_fail_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":leak_check\",\n        \"//absl/log\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"stack_consumption\",\n    testonly = 1,\n    srcs = [\"internal/stack_consumption.cc\"],\n    hdrs = [\"internal/stack_consumption.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_test(\n    name = \"stack_consumption_test\",\n    srcs = [\"internal/stack_consumption_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"notsan\"],\n    deps = [\n        \":stack_consumption\",\n        \"//absl/base:core_headers\",\n        \"//absl/log\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"stacktrace_benchmark\",\n    testonly = 1,\n    srcs = [\"stacktrace_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":stacktrace\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/cleanup\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/debugging/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nfind_library(EXECINFO_LIBRARY execinfo)\n\nabsl_cc_library(\n  NAME\n    stacktrace\n  HDRS\n    \"stacktrace.h\"\n    \"internal/stacktrace_aarch64-inl.inc\"\n    \"internal/stacktrace_arm-inl.inc\"\n    \"internal/stacktrace_config.h\"\n    \"internal/stacktrace_emscripten-inl.inc\"\n    \"internal/stacktrace_generic-inl.inc\"\n    \"internal/stacktrace_powerpc-inl.inc\"\n    \"internal/stacktrace_riscv-inl.inc\"\n    \"internal/stacktrace_unimplemented-inl.inc\"\n    \"internal/stacktrace_win32-inl.inc\"\n    \"internal/stacktrace_x86-inl.inc\"\n  SRCS\n    \"stacktrace.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    $<$<BOOL:${EXECINFO_LIBRARY}>:${EXECINFO_LIBRARY}>\n  DEPS\n    absl::debugging_internal\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::malloc_internal\n    absl::raw_logging_internal\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    stacktrace_test\n  SRCS\n    \"stacktrace_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::stacktrace\n    absl::config\n    absl::core_headers\n    absl::errno_saver\n    absl::span\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    symbolize\n  HDRS\n    \"symbolize.h\"\n    \"internal/symbolize.h\"\n  SRCS\n    \"symbolize.cc\"\n    \"symbolize_darwin.inc\"\n    \"symbolize_elf.inc\"\n    \"symbolize_emscripten.inc\"\n    \"symbolize_unimplemented.inc\"\n    \"symbolize_win32.inc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n    $<$<BOOL:${MINGW}>:-ldbghelp>\n  DEPS\n    absl::debugging_internal\n    absl::demangle_internal\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::malloc_internal\n    absl::raw_logging_internal\n    absl::strings\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    symbolize_test\n  SRCS\n    \"symbolize_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n    $<$<BOOL:${MSVC}>:-Z7>\n  LINKOPTS\n    $<$<BOOL:${MSVC}>:-DEBUG>\n  DEPS\n    absl::base\n    absl::check\n    absl::cleanup\n    absl::config\n    absl::core_headers\n    absl::log\n    absl::malloc_internal\n    absl::memory\n    absl::stack_consumption\n    absl::strings\n    absl::str_format\n    absl::symbolize\n    GTest::gmock\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    examine_stack\n  HDRS\n    \"internal/examine_stack.h\"\n  SRCS\n    \"internal/examine_stack.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::stacktrace\n    absl::symbolize\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n)\n\nabsl_cc_library(\n  NAME\n    failure_signal_handler\n  HDRS\n    \"failure_signal_handler.h\"\n  SRCS\n    \"failure_signal_handler.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::examine_stack\n    absl::stacktrace\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    failure_signal_handler_test\n  SRCS\n    \"failure_signal_handler_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::check\n    absl::failure_signal_handler\n    absl::stacktrace\n    absl::symbolize\n    absl::strings\n    absl::raw_logging_internal\n    Threads::Threads\n    GTest::gmock\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    debugging_internal\n  HDRS\n    \"internal/address_is_readable.h\"\n    \"internal/addresses.h\"\n    \"internal/elf_mem_image.h\"\n    \"internal/vdso_support.h\"\n  SRCS\n    \"internal/address_is_readable.cc\"\n    \"internal/elf_mem_image.cc\"\n    \"internal/vdso_support.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::core_headers\n    absl::config\n    absl::dynamic_annotations\n    absl::errno_saver\n    absl::raw_logging_internal\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    demangle_internal\n  HDRS\n    \"internal/demangle.h\"\n  SRCS\n    \"internal/demangle.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::demangle_rust\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    demangle_test\n  SRCS\n    \"internal/demangle_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::demangle_internal\n    absl::stack_consumption\n    absl::config\n    absl::core_headers\n    absl::log\n    absl::memory\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    bounded_utf8_length_sequence\n  HDRS\n    \"internal/bounded_utf8_length_sequence.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::bits\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    bounded_utf8_length_sequence_test\n  SRCS\n    \"internal/bounded_utf8_length_sequence_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::bounded_utf8_length_sequence\n    absl::config\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    decode_rust_punycode\n  HDRS\n    \"internal/decode_rust_punycode.h\"\n  SRCS\n    \"internal/decode_rust_punycode.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::bounded_utf8_length_sequence\n    absl::config\n    absl::nullability\n    absl::utf8_for_code_point\n)\n\nabsl_cc_test(\n  NAME\n    decode_rust_punycode_test\n  SRCS\n    \"internal/decode_rust_punycode_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::decode_rust_punycode\n    absl::config\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    demangle_rust\n  HDRS\n    \"internal/demangle_rust.h\"\n  SRCS\n    \"internal/demangle_rust.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::decode_rust_punycode\n)\n\nabsl_cc_test(\n  NAME\n    demangle_rust_test\n  SRCS\n    \"internal/demangle_rust_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::demangle_rust\n    absl::config\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    utf8_for_code_point\n  HDRS\n    \"internal/utf8_for_code_point.h\"\n  SRCS\n    \"internal/utf8_for_code_point.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    utf8_for_code_point_test\n  SRCS\n    \"internal/utf8_for_code_point_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::utf8_for_code_point\n    absl::config\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    leak_check\n  HDRS\n    \"leak_check.h\"\n  SRCS\n    \"leak_check.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    leak_check_test\n  SRCS\n    \"leak_check_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::leak_check\n    absl::base\n    absl::log\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    stack_consumption\n  HDRS\n    \"internal/stack_consumption.h\"\n  SRCS\n    \"internal/stack_consumption.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    stack_consumption_test\n  SRCS\n    \"internal/stack_consumption_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::stack_consumption\n    absl::core_headers\n    absl::log\n    GTest::gmock_main\n)\n\n# component target\nabsl_cc_library(\n  NAME\n    debugging\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::stacktrace\n    absl::leak_check\n  PUBLIC\n)\n"
  },
  {
    "path": "absl/debugging/failure_signal_handler.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#include \"absl/debugging/failure_signal_handler.h\"\n\n#include \"absl/base/config.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <pthread.h>\n#include <sched.h>\n#include <unistd.h>\n#endif\n\n#ifdef __APPLE__\n#include <TargetConditionals.h>\n#endif\n\n#ifdef ABSL_HAVE_MMAP\n#include <sys/mman.h>\n#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n#endif\n\n#ifdef __linux__\n#include <sys/prctl.h>\n#endif\n\n#include <algorithm>\n#include <atomic>\n#include <cerrno>\n#include <csignal>\n#include <cstdio>\n#include <cstring>\n#include <ctime>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/debugging/internal/examine_stack.h\"\n#include \"absl/debugging/stacktrace.h\"\n\n#if !defined(_WIN32) && !defined(__wasi__)\n#define ABSL_HAVE_SIGACTION\n// Apple WatchOS and TVOS don't allow sigaltstack\n// Apple macOS has sigaltstack, but using it makes backtrace() unusable.\n#if !(defined(TARGET_OS_OSX) && TARGET_OS_OSX) &&     \\\n    !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \\\n    !(defined(TARGET_OS_TV) && TARGET_OS_TV) && !defined(__QNX__)\n#define ABSL_HAVE_SIGALTSTACK\n#endif\n#endif\n\n// ABSL_HAVE_PTHREAD_CPU_NUMBER_NP\n//\n// Checks whether pthread_cpu_number_np is available.\n#ifdef ABSL_HAVE_PTHREAD_CPU_NUMBER_NP\n#error ABSL_HAVE_PTHREAD_CPU_NUMBER_NP cannot be directly set\n#elif defined(__APPLE__) && defined(__has_include) &&              \\\n    ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&    \\\n      __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000) ||  \\\n     (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) &&   \\\n      __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140200) || \\\n     (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) &&    \\\n      __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 70100) ||   \\\n     (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) &&       \\\n      __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 140200))\n#define ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options;\n\n// Resets the signal handler for signo to the default action for that\n// signal, then raises the signal.\nstatic void RaiseToDefaultHandler(int signo) {\n  signal(signo, SIG_DFL);\n  raise(signo);\n}\n\nstruct FailureSignalData {\n  const int signo;\n  const char* const as_string;\n#ifdef ABSL_HAVE_SIGACTION\n  struct sigaction previous_action;\n  // StructSigaction is used to silence -Wmissing-field-initializers.\n  using StructSigaction = struct sigaction;\n#define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()\n#else\n  void (*previous_handler)(int);\n#define FSD_PREVIOUS_INIT SIG_DFL\n#endif\n};\n\nABSL_CONST_INIT static FailureSignalData failure_signal_data[] = {\n    {SIGSEGV, \"SIGSEGV\", FSD_PREVIOUS_INIT},\n    {SIGILL, \"SIGILL\", FSD_PREVIOUS_INIT},\n    {SIGFPE, \"SIGFPE\", FSD_PREVIOUS_INIT},\n    {SIGABRT, \"SIGABRT\", FSD_PREVIOUS_INIT},\n    {SIGTERM, \"SIGTERM\", FSD_PREVIOUS_INIT},\n#ifndef _WIN32\n    {SIGBUS, \"SIGBUS\", FSD_PREVIOUS_INIT},\n    {SIGTRAP, \"SIGTRAP\", FSD_PREVIOUS_INIT},\n#endif\n};\n\n#undef FSD_PREVIOUS_INIT\n\nstatic void RaiseToPreviousHandler(int signo) {\n  // Search for the previous handler.\n  for (const auto& it : failure_signal_data) {\n    if (it.signo == signo) {\n#ifdef ABSL_HAVE_SIGACTION\n      sigaction(signo, &it.previous_action, nullptr);\n#else\n      signal(signo, it.previous_handler);\n#endif\n      raise(signo);\n      return;\n    }\n  }\n\n  // Not found, use the default handler.\n  RaiseToDefaultHandler(signo);\n}\n\nnamespace debugging_internal {\n\nconst char* FailureSignalToString(int signo) {\n  for (const auto& it : failure_signal_data) {\n    if (it.signo == signo) {\n      return it.as_string;\n    }\n  }\n  return \"\";\n}\n\n}  // namespace debugging_internal\n\n#ifdef ABSL_HAVE_SIGALTSTACK\n\nstatic bool SetupAlternateStackOnce() {\n#if defined(__wasm__) || defined(__asmjs__)\n  const size_t page_mask = static_cast<size_t>(getpagesize()) - 1;\n#else\n  const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1;\n#endif\n  size_t stack_size =\n      (std::max(static_cast<size_t>(SIGSTKSZ), size_t{65536}) + page_mask) &\n      ~page_mask;\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)\n  // Account for sanitizer instrumentation requiring additional stack space.\n  stack_size *= 5;\n#endif\n\n  stack_t sigstk;\n  memset(&sigstk, 0, sizeof(sigstk));\n  sigstk.ss_size = stack_size;\n\n#ifdef ABSL_HAVE_MMAP\n#ifndef MAP_STACK\n#define MAP_STACK 0\n#endif\n  sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE,\n                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);\n  if (sigstk.ss_sp == MAP_FAILED) {\n    ABSL_RAW_LOG(FATAL, \"mmap() for alternate signal stack failed\");\n  }\n#else\n  sigstk.ss_sp = malloc(sigstk.ss_size);\n  if (sigstk.ss_sp == nullptr) {\n    ABSL_RAW_LOG(FATAL, \"malloc() for alternate signal stack failed\");\n  }\n#endif\n\n  if (sigaltstack(&sigstk, nullptr) != 0) {\n    ABSL_RAW_LOG(FATAL, \"sigaltstack() failed with errno=%d\", errno);\n  }\n\n#ifdef __linux__\n#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)\n  // Make a best-effort attempt to name the allocated region in\n  // /proc/$PID/smaps.\n  //\n  // The call to prctl() may fail if the kernel was not configured with the\n  // CONFIG_ANON_VMA_NAME kernel option.  This is OK since the call is\n  // primarily a debugging aid.\n  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, sigstk.ss_sp, sigstk.ss_size,\n        \"absl-signalstack\");\n#endif\n#endif  // __linux__\n\n  return true;\n}\n\n#endif\n\n#ifdef ABSL_HAVE_SIGACTION\n\n// Sets up an alternate stack for signal handlers once.\n// Returns the appropriate flag for sig_action.sa_flags\n// if the system supports using an alternate stack.\nstatic int MaybeSetupAlternateStack() {\n#ifdef ABSL_HAVE_SIGALTSTACK\n  ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce();\n  return SA_ONSTACK;\n#else\n  return 0;\n#endif\n}\n\nstatic void InstallOneFailureHandler(FailureSignalData* data,\n                                     void (*handler)(int, siginfo_t*, void*)) {\n  struct sigaction act;\n  memset(&act, 0, sizeof(act));\n  sigemptyset(&act.sa_mask);\n  act.sa_flags |= SA_SIGINFO;\n  // SA_NODEFER is required to handle SIGABRT from\n  // ImmediateAbortSignalHandler().\n  act.sa_flags |= SA_NODEFER;\n  if (fsh_options.use_alternate_stack) {\n    act.sa_flags |= MaybeSetupAlternateStack();\n  }\n  act.sa_sigaction = handler;\n  ABSL_RAW_CHECK(sigaction(data->signo, &act, &data->previous_action) == 0,\n                 \"sigaction() failed\");\n}\n\n#else\n\nstatic void InstallOneFailureHandler(FailureSignalData* data,\n                                     void (*handler)(int)) {\n  data->previous_handler = signal(data->signo, handler);\n  ABSL_RAW_CHECK(data->previous_handler != SIG_ERR, \"signal() failed\");\n}\n\n#endif\n\nstatic void WriteSignalMessage(int signo, int cpu,\n                               void (*writerfn)(const char*)) {\n  char buf[96];\n  char on_cpu[32] = {0};\n  if (cpu != -1) {\n    snprintf(on_cpu, sizeof(on_cpu), \" on cpu %d\", cpu);\n  }\n  const char* const signal_string =\n      debugging_internal::FailureSignalToString(signo);\n  if (signal_string != nullptr && signal_string[0] != '\\0') {\n    snprintf(buf, sizeof(buf), \"*** %s received at time=%ld%s ***\\n\",\n             signal_string,\n             static_cast<long>(time(nullptr)),  // NOLINT(runtime/int)\n             on_cpu);\n  } else {\n    snprintf(buf, sizeof(buf), \"*** Signal %d received at time=%ld%s ***\\n\",\n             signo, static_cast<long>(time(nullptr)),  // NOLINT(runtime/int)\n             on_cpu);\n  }\n  writerfn(buf);\n}\n\n// `void*` might not be big enough to store `void(*)(const char*)`.\nstruct WriterFnStruct {\n  void (*writerfn)(const char*);\n};\n\n// Many of the absl::debugging_internal::Dump* functions in\n// examine_stack.h take a writer function pointer that has a void* arg\n// for historical reasons. failure_signal_handler_writer only takes a\n// data pointer. This function converts between these types.\nstatic void WriterFnWrapper(const char* data, void* arg) {\n  static_cast<WriterFnStruct*>(arg)->writerfn(data);\n}\n\n// Convenient wrapper around DumpPCAndFrameSizesAndStackTrace() for signal\n// handlers. \"noinline\" so that GetStackFrames() skips the top-most stack\n// frame for this function.\nABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace(\n    void* ucontext, bool symbolize_stacktrace,\n    void (*writerfn)(const char*, void*), void* writerfn_arg) {\n  constexpr int kNumStackFrames = 32;\n  void* stack[kNumStackFrames];\n  int frame_sizes[kNumStackFrames];\n  int min_dropped_frames;\n  int depth = absl::GetStackFramesWithContext(\n      stack, frame_sizes, kNumStackFrames,\n      1,  // Do not include this function in stack trace.\n      ucontext, &min_dropped_frames);\n  absl::debugging_internal::DumpPCAndFrameSizesAndStackTrace(\n      absl::debugging_internal::GetProgramCounter(ucontext), stack, frame_sizes,\n      depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg);\n}\n\n// Called by AbslFailureSignalHandler() to write the failure info. It is\n// called once with writerfn set to WriteToStderr() and then possibly\n// with writerfn set to the user provided function.\nstatic void WriteFailureInfo(int signo, void* ucontext, int cpu,\n                             void (*writerfn)(const char*)) {\n  WriterFnStruct writerfn_struct{writerfn};\n  WriteSignalMessage(signo, cpu, writerfn);\n  WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,\n                  &writerfn_struct);\n}\n\n// absl::SleepFor() can't be used here since AbslInternalSleepFor()\n// may be overridden to do something that isn't async-signal-safe on\n// some platforms.\nstatic void PortableSleepForSeconds(int seconds) {\n#ifdef _WIN32\n  Sleep(static_cast<DWORD>(seconds * 1000));\n#else\n  struct timespec sleep_time;\n  sleep_time.tv_sec = seconds;\n  sleep_time.tv_nsec = 0;\n  while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {\n  }\n#endif\n}\n\n#ifdef ABSL_HAVE_ALARM\n// AbslFailureSignalHandler() installs this as a signal handler for\n// SIGALRM, then sets an alarm to be delivered to the program after a\n// set amount of time. If AbslFailureSignalHandler() hangs for more than\n// the alarm timeout, ImmediateAbortSignalHandler() will abort the\n// program.\nstatic void ImmediateAbortSignalHandler(int) { RaiseToDefaultHandler(SIGABRT); }\n#endif\n\n// absl::base_internal::GetTID() returns pid_t on most platforms, but\n// returns absl::base_internal::pid_t on Windows.\nusing GetTidType = decltype(absl::base_internal::GetTID());\nABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0);\n\nstatic int GetCpuNumber() {\n#ifdef ABSL_HAVE_SCHED_GETCPU\n  return sched_getcpu();\n#elif defined(ABSL_HAVE_PTHREAD_CPU_NUMBER_NP)\n  size_t cpu_num;\n  if (pthread_cpu_number_np(&cpu_num) == 0) {\n    return static_cast<int>(cpu_num);\n  }\n  return -1;\n#else\n  return -1;\n#endif\n}\n\n#ifndef ABSL_HAVE_SIGACTION\nstatic void AbslFailureSignalHandler(int signo) {\n  void* ucontext = nullptr;\n#else\nstatic void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {\n#endif\n\n  const GetTidType this_tid = absl::base_internal::GetTID();\n  GetTidType previous_failed_tid = 0;\n  if (!failed_tid.compare_exchange_strong(previous_failed_tid, this_tid,\n                                          std::memory_order_acq_rel,\n                                          std::memory_order_relaxed)) {\n    ABSL_RAW_LOG(\n        ERROR,\n        \"Signal %d raised at PC=%p while already in AbslFailureSignalHandler()\",\n        signo, absl::debugging_internal::GetProgramCounter(ucontext));\n    if (this_tid != previous_failed_tid) {\n      // Another thread is already in AbslFailureSignalHandler(), so wait\n      // a bit for it to finish. If the other thread doesn't kill us,\n      // we do so after sleeping.\n      PortableSleepForSeconds(3);\n      RaiseToDefaultHandler(signo);\n      // The recursively raised signal may be blocked until we return.\n      return;\n    }\n  }\n\n  // Increase the chance that the CPU we report was the same CPU on which the\n  // signal was received by doing this as early as possible, i.e. after\n  // verifying that this is not a recursive signal handler invocation.\n  int my_cpu = GetCpuNumber();\n\n#ifdef ABSL_HAVE_ALARM\n  // Set an alarm to abort the program in case this code hangs or deadlocks.\n  if (fsh_options.alarm_on_failure_secs > 0) {\n    alarm(0);  // Cancel any existing alarms.\n    signal(SIGALRM, ImmediateAbortSignalHandler);\n    alarm(static_cast<unsigned int>(fsh_options.alarm_on_failure_secs));\n  }\n#endif\n\n  // First write to stderr.\n  WriteFailureInfo(\n      signo, ucontext, my_cpu, +[](const char* data) {\n        absl::raw_log_internal::AsyncSignalSafeWriteError(data, strlen(data));\n      });\n\n  // Riskier code (because it is less likely to be async-signal-safe)\n  // goes after this point.\n  if (fsh_options.writerfn != nullptr) {\n    WriteFailureInfo(signo, ucontext, my_cpu, fsh_options.writerfn);\n    fsh_options.writerfn(nullptr);\n  }\n\n  if (fsh_options.call_previous_handler) {\n    RaiseToPreviousHandler(signo);\n  } else {\n    RaiseToDefaultHandler(signo);\n  }\n}\n\nvoid InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) {\n  fsh_options = options;\n  for (auto& it : failure_signal_data) {\n    InstallOneFailureHandler(&it, AbslFailureSignalHandler);\n  }\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/failure_signal_handler.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: failure_signal_handler.h\n// -----------------------------------------------------------------------------\n//\n// This file configures the Abseil *failure signal handler* to capture and dump\n// useful debugging information (such as a stacktrace) upon program failure.\n//\n// To use the failure signal handler, call `absl::InstallFailureSignalHandler()`\n// very early in your program, usually in the first few lines of main():\n//\n// int main(int argc, char** argv) {\n//   // Initialize the symbolizer to get a human-readable stack trace\n//   absl::InitializeSymbolizer(argv[0]);\n//\n//   absl::FailureSignalHandlerOptions options;\n//   absl::InstallFailureSignalHandler(options);\n//   DoSomethingInteresting();\n//   return 0;\n// }\n//\n// Any program that raises a fatal signal (such as `SIGSEGV`, `SIGILL`,\n// `SIGFPE`, `SIGABRT`, `SIGTERM`, `SIGBUS`, and `SIGTRAP`) will call the\n// installed failure signal handler and provide debugging information to stderr.\n//\n// Note that you should *not* install the Abseil failure signal handler more\n// than once. You may, of course, have another (non-Abseil) failure signal\n// handler installed (which would be triggered if Abseil's failure signal\n// handler sets `call_previous_handler` to `true`).\n\n#ifndef ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_\n#define ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// FailureSignalHandlerOptions\n//\n// Struct for holding `absl::InstallFailureSignalHandler()` configuration\n// options.\nstruct FailureSignalHandlerOptions {\n  // If true, try to symbolize the stacktrace emitted on failure, provided that\n  // you have initialized a symbolizer for that purpose. (See symbolize.h for\n  // more information.)\n  bool symbolize_stacktrace = true;\n\n  // If true, try to run signal handlers on an alternate stack (if supported on\n  // the given platform). An alternate stack is useful for program crashes due\n  // to a stack overflow; by running on a alternate stack, the signal handler\n  // may run even when normal stack space has been exhausted. The downside of\n  // using an alternate stack is that extra memory for the alternate stack needs\n  // to be pre-allocated.\n  bool use_alternate_stack = true;\n\n  // If positive, indicates the number of seconds after which the failure signal\n  // handler is invoked to abort the program. Setting such an alarm is useful in\n  // cases where the failure signal handler itself may become hung or\n  // deadlocked.\n  int alarm_on_failure_secs = 3;\n\n  // If true, call the previously registered signal handler for the signal that\n  // was received (if one was registered) after the existing signal handler\n  // runs. This mechanism can be used to chain signal handlers together.\n  //\n  // If false, the signal is raised to the default handler for that signal\n  // (which normally terminates the program).\n  //\n  // IMPORTANT: If true, the chained fatal signal handlers must not try to\n  // recover from the fatal signal. Instead, they should terminate the program\n  // via some mechanism, like raising the default handler for the signal, or by\n  // calling `_exit()`. Note that the failure signal handler may put parts of\n  // the Abseil library into a state from which they cannot recover.\n  bool call_previous_handler = false;\n\n  // If non-null, indicates a pointer to a callback function that will be called\n  // upon failure, with a string argument containing failure data. This function\n  // may be used as a hook to write failure data to a secondary location, such\n  // as a log file. This function will also be called with null data, as a hint\n  // to flush any buffered data before the program may be terminated. Consider\n  // flushing any buffered data in all calls to this function.\n  //\n  // Since this function runs within a signal handler, it should be\n  // async-signal-safe if possible.\n  // See http://man7.org/linux/man-pages/man7/signal-safety.7.html\n  void (*writerfn)(const char*) = nullptr;\n};\n\n// InstallFailureSignalHandler()\n//\n// Installs a signal handler for the common failure signals `SIGSEGV`, `SIGILL`,\n// `SIGFPE`, `SIGABRT`, `SIGTERM`, `SIGBUG`, and `SIGTRAP` (provided they exist\n// on the given platform). The failure signal handler dumps program failure data\n// useful for debugging in an unspecified format to stderr. This data may\n// include the program counter, a stacktrace, and register information on some\n// systems; do not rely on an exact format for the output, as it is subject to\n// change.\nvoid InstallFailureSignalHandler(const FailureSignalHandlerOptions& options);\n\nnamespace debugging_internal {\nconst char* FailureSignalToString(int signo);\n}  // namespace debugging_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_\n"
  },
  {
    "path": "absl/debugging/failure_signal_handler_test.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#include \"absl/debugging/failure_signal_handler.h\"\n\n#include <csignal>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <fstream>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/symbolize.h\"\n#include \"absl/log/check.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\n\nusing testing::StartsWith;\n\n#if GTEST_HAS_DEATH_TEST\n\n// For the parameterized death tests. GetParam() returns the signal number.\nusing FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>;\n\n// This function runs in a fork()ed process on most systems.\nvoid InstallHandlerAndRaise(int signo) {\n  absl::InstallFailureSignalHandler(absl::FailureSignalHandlerOptions());\n  raise(signo);\n}\n\nTEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {\n  const int signo = GetParam();\n  std::string exit_regex = absl::StrCat(\n      \"\\\\*\\\\*\\\\* \", absl::debugging_internal::FailureSignalToString(signo),\n      \" received at time=\");\n#ifndef _WIN32\n  EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo),\n              exit_regex);\n#else\n  // Windows doesn't have testing::KilledBySignal().\n  EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex);\n#endif\n}\n\nABSL_CONST_INIT FILE* error_file = nullptr;\n\nvoid WriteToErrorFile(const char* msg) {\n  if (msg != nullptr) {\n    ABSL_RAW_CHECK(fwrite(msg, strlen(msg), 1, error_file) == 1,\n                   \"fwrite() failed\");\n  }\n  ABSL_RAW_CHECK(fflush(error_file) == 0, \"fflush() failed\");\n}\n\nstd::string GetTmpDir() {\n  // TEST_TMPDIR is set by Bazel. Try the others when not running under Bazel.\n  static const char* const kTmpEnvVars[] = {\"TEST_TMPDIR\", \"TMPDIR\", \"TEMP\",\n                                            \"TEMPDIR\", \"TMP\"};\n  for (const char* const var : kTmpEnvVars) {\n    const char* tmp_dir = std::getenv(var);\n    if (tmp_dir != nullptr) {\n      return tmp_dir;\n    }\n  }\n\n  // Try something reasonable.\n  return \"/tmp\";\n}\n\n// This function runs in a fork()ed process on most systems.\nvoid InstallHandlerWithWriteToFileAndRaise(const char* file, int signo) {\n  error_file = fopen(file, \"w\");\n  CHECK_NE(error_file, nullptr) << \"Failed create error_file\";\n  absl::FailureSignalHandlerOptions options;\n  options.writerfn = WriteToErrorFile;\n  absl::InstallFailureSignalHandler(options);\n  raise(signo);\n}\n\nTEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {\n  const int signo = GetParam();\n  std::string tmp_dir = GetTmpDir();\n  std::string file = absl::StrCat(tmp_dir, \"/signo_\", signo);\n\n  std::string exit_regex = absl::StrCat(\n      \"\\\\*\\\\*\\\\* \", absl::debugging_internal::FailureSignalToString(signo),\n      \" received at time=\");\n#ifndef _WIN32\n  EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),\n              testing::KilledBySignal(signo), exit_regex);\n#else\n  // Windows doesn't have testing::KilledBySignal().\n  EXPECT_DEATH_IF_SUPPORTED(\n      InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex);\n#endif\n\n  // Open the file in this process and check its contents.\n  std::fstream error_output(file);\n  ASSERT_TRUE(error_output.is_open()) << file;\n  std::string error_line;\n  std::getline(error_output, error_line);\n  EXPECT_THAT(\n      error_line,\n      StartsWith(absl::StrCat(\n          \"*** \", absl::debugging_internal::FailureSignalToString(signo),\n          \" received at \")));\n\n  // On platforms where it is possible to get the current CPU, the\n  // CPU number is also logged. Check that it is present in output.\n#if defined(__linux__)\n  EXPECT_THAT(error_line, testing::HasSubstr(\" on cpu \"));\n#endif\n\n  if (absl::debugging_internal::StackTraceWorksForTest()) {\n    std::getline(error_output, error_line);\n    EXPECT_THAT(error_line, StartsWith(\"PC: \"));\n  }\n}\n\nconstexpr int kFailureSignals[] = {\n    SIGSEGV, SIGILL,  SIGFPE, SIGABRT, SIGTERM,\n#ifndef _WIN32\n    SIGBUS,  SIGTRAP,\n#endif\n};\n\nstd::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {\n  std::string result =\n      absl::debugging_internal::FailureSignalToString(info.param);\n  if (result.empty()) {\n    result = absl::StrCat(info.param);\n  }\n  return result;\n}\n\nINSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,\n                         ::testing::ValuesIn(kFailureSignals),\n                         SignalParamToString);\n\n#endif  // GTEST_HAS_DEATH_TEST\n\n}  // namespace\n\nint main(int argc, char** argv) {\n  absl::InitializeSymbolizer(argv[0]);\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "absl/debugging/internal/address_is_readable.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// base::AddressIsReadable() probes an address to see whether it is readable,\n// without faulting.\n\n#include \"absl/debugging/internal/address_is_readable.h\"\n\n#if !defined(__linux__) || defined(__ANDROID__)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// On platforms other than Linux, just return true.\nbool AddressIsReadable(const void* /* addr */) { return true; }\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#else  // __linux__ && !__ANDROID__\n\n#include <stdint.h>\n#include <syscall.h>\n#include <unistd.h>\n\n#include \"absl/base/internal/errno_saver.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// NOTE: be extra careful about adding any interposable function calls here\n// (such as open(), read(), etc.). These symbols may be interposed and will get\n// invoked in contexts they don't expect.\n//\n// NOTE: any new system calls here may also require sandbox reconfiguration.\n//\nbool AddressIsReadable(const void *addr) {\n  // rt_sigprocmask below checks 8 contiguous bytes. If addr resides in the\n  // last 7 bytes of a page (unaligned), rt_sigprocmask would additionally\n  // check the readability of the next page, which is not desired. Align\n  // address on 8-byte boundary to check only the current page.\n  const uintptr_t u_addr = reinterpret_cast<uintptr_t>(addr) & ~uintptr_t{7};\n  addr = reinterpret_cast<const void *>(u_addr);\n\n  // rt_sigprocmask below will succeed for this input.\n  if (addr == nullptr) return false;\n\n  absl::base_internal::ErrnoSaver errno_saver;\n\n  // Here we probe with some syscall which\n  // - accepts an 8-byte region of user memory as input\n  // - tests for EFAULT before other validation\n  // - has no problematic side-effects\n  //\n  // rt_sigprocmask(2) works for this.  It copies sizeof(kernel_sigset_t)==8\n  // bytes from the address into the kernel memory before any validation.\n  //\n  // The call can never succeed, since the `how` parameter is not one of\n  // SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK.\n  //\n  // This strategy depends on Linux implementation details,\n  // so we rely on the test to alert us if it stops working.\n  //\n  // Some discarded past approaches:\n  // - msync() doesn't reject PROT_NONE regions\n  // - write() on /dev/null doesn't return EFAULT\n  // - write() on a pipe requires creating it and draining the writes\n  // - connect() works but is problematic for sandboxes and needs a valid\n  //   file descriptor\n  //\n  // This can never succeed (invalid first argument to sigprocmask).\n  ABSL_RAW_CHECK(syscall(SYS_rt_sigprocmask, ~0, addr, nullptr,\n                         /*sizeof(kernel_sigset_t)*/ 8) == -1,\n                 \"unexpected success\");\n  ABSL_RAW_CHECK(errno == EFAULT || errno == EINVAL, \"unexpected errno\");\n  return errno != EFAULT;\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // __linux__ && !__ANDROID__\n"
  },
  {
    "path": "absl/debugging/internal/address_is_readable.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_\n#define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Return whether the byte at *addr is readable, without faulting.\n// Save and restores errno.\nbool AddressIsReadable(const void *addr);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_\n"
  },
  {
    "path": "absl/debugging/internal/addresses.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_\n#define ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_\n\n#include <stdint.h>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Removes any metadata (tag bits) from the given pointer, converting it into a\n// user-readable address.\ninline uintptr_t StripPointerMetadata(uintptr_t ptr) {\n#if defined(__aarch64__)\n  // When PAC-RET (-mbranch-protection=pac-ret) is enabled, return addresses\n  // stored on the stack will be signed, which means that pointer bits outside\n  // of the virtual address range are potentially set. Since the stacktrace code\n  // is expected to return normal code pointers, this function clears those\n  // bits.\n  register uintptr_t x30 __asm__(\"x30\") = ptr;\n  // The normal instruction for clearing PAC bits is XPACI, but for\n  // compatibility with ARM platforms that do not support pointer\n  // authentication, we use the hint space instruction XPACLRI instead. Hint\n  // space instructions behave as NOPs on unsupported platforms.\n#define ABSL_XPACLRI_HINT \"hint #0x7;\"\n  asm(ABSL_XPACLRI_HINT : \"+r\"(x30));  // asm(\"xpaclri\" : \"+r\"(x30));\n#undef ABSL_XPACLRI_HINT\n  return x30;\n#else\n  return ptr;\n#endif\n}\n\ninline uintptr_t StripPointerMetadata(void* ptr) {\n  return StripPointerMetadata(reinterpret_cast<uintptr_t>(ptr));\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_\n"
  },
  {
    "path": "absl/debugging/internal/bounded_utf8_length_sequence.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_BOUNDED_UTF8_LENGTH_SEQUENCE_H_\n#define ABSL_DEBUGGING_INTERNAL_BOUNDED_UTF8_LENGTH_SEQUENCE_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/numeric/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// A sequence of up to max_elements integers between 1 and 4 inclusive, whose\n// insertion operation computes the sum of all the elements before the insertion\n// point.  This is useful in decoding Punycode, where one needs to know where in\n// a UTF-8 byte stream the n-th code point begins.\n//\n// BoundedUtf8LengthSequence is async-signal-safe and suitable for use in\n// symbolizing stack traces in a signal handler, provided max_elements is not\n// improvidently large.  For inputs of lengths accepted by the Rust demangler,\n// up to a couple hundred code points, InsertAndReturnSumOfPredecessors should\n// run in a few dozen clock cycles, on par with the other arithmetic required\n// for Punycode decoding.\ntemplate <uint32_t max_elements>\nclass BoundedUtf8LengthSequence {\n public:\n  // Constructs an empty sequence.\n  BoundedUtf8LengthSequence() = default;\n\n  // Inserts `utf_length` at position `index`, shifting any existing elements at\n  // or beyond `index` one position to the right.  If the sequence is already\n  // full, the rightmost element is discarded.\n  //\n  // Returns the sum of the elements at positions 0 to `index - 1` inclusive.\n  // If `index` is greater than the number of elements already inserted, the\n  // excess positions in the range count 1 apiece.\n  //\n  // REQUIRES: index < max_elements and 1 <= utf8_length <= 4.\n  uint32_t InsertAndReturnSumOfPredecessors(\n      uint32_t index, uint32_t utf8_length) {\n    // The caller shouldn't pass out-of-bounds inputs, but if it does happen,\n    // clamp the values and try to continue.  If we're being called from a\n    // signal handler, the last thing we want to do is crash.  Emitting\n    // malformed UTF-8 is a lesser evil.\n    if (index >= max_elements) index = max_elements - 1;\n    if (utf8_length == 0 || utf8_length > 4) utf8_length = 1;\n\n    const uint32_t word_index = index/32;\n    const uint32_t bit_index = 2 * (index % 32);\n    const uint64_t ones_bit = uint64_t{1} << bit_index;\n\n    // Compute the sum of predecessors.\n    //   - Each value from 1 to 4 is represented by a bit field with value from\n    //     0 to 3, so the desired sum is index plus the sum of the\n    //     representations actually stored.\n    //   - For each bit field, a set low bit should contribute 1 to the sum, and\n    //     a set high bit should contribute 2.\n    //   - Another way to say the same thing is that each set bit contributes 1,\n    //     and each set high bit contributes an additional 1.\n    //   - So the sum we want is index + popcount(everything) + popcount(bits in\n    //     odd positions).\n    const uint64_t odd_bits_mask = 0xaaaaaaaaaaaaaaaa;\n    const uint64_t lower_seminibbles_mask = ones_bit - 1;\n    const uint64_t higher_seminibbles_mask = ~lower_seminibbles_mask;\n    const uint64_t same_word_bits_below_insertion =\n        rep_[word_index] & lower_seminibbles_mask;\n    int full_popcount = absl::popcount(same_word_bits_below_insertion);\n    int odd_popcount =\n        absl::popcount(same_word_bits_below_insertion & odd_bits_mask);\n    for (uint32_t j = word_index; j > 0; --j) {\n      const uint64_t word_below_insertion = rep_[j - 1];\n      full_popcount += absl::popcount(word_below_insertion);\n      odd_popcount += absl::popcount(word_below_insertion & odd_bits_mask);\n    }\n    const uint32_t sum_of_predecessors =\n        index + static_cast<uint32_t>(full_popcount + odd_popcount);\n\n    // Now insert utf8_length's representation, shifting successors up one\n    // place.\n    for (uint32_t j = max_elements/32 - 1; j > word_index; --j) {\n      rep_[j] = (rep_[j] << 2) | (rep_[j - 1] >> 62);\n    }\n    rep_[word_index] =\n        (rep_[word_index] & lower_seminibbles_mask) |\n        (uint64_t{utf8_length - 1} << bit_index) |\n        ((rep_[word_index] & higher_seminibbles_mask) << 2);\n\n    return sum_of_predecessors;\n  }\n\n private:\n  // If the (32 * i + j)-th element of the represented sequence has the value k\n  // (0 <= j < 32, 1 <= k <= 4), then bits 2 * j and 2 * j + 1 of rep_[i]\n  // contain the seminibble (k - 1).\n  //\n  // In particular, the zero-initialization of rep_ makes positions not holding\n  // any inserted element count as 1 in InsertAndReturnSumOfPredecessors.\n  //\n  // Example: rep_ = {0xb1, ... the rest zeroes ...} represents the sequence\n  // (2, 1, 4, 3, ... the rest 1's ...).  Constructing the sequence of Unicode\n  // code points \"Àa🂻中\" = {U+00C0, U+0061, U+1F0BB, U+4E2D} (among many\n  // other examples) would yield this value of rep_.\n  static_assert(max_elements > 0 && max_elements % 32 == 0,\n                \"max_elements must be a positive multiple of 32\");\n  uint64_t rep_[max_elements/32] = {};\n};\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_BOUNDED_UTF8_LENGTH_SEQUENCE_H_\n"
  },
  {
    "path": "absl/debugging/internal/bounded_utf8_length_sequence_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/bounded_utf8_length_sequence.h\"\n\n#include <cstdint>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\nTEST(BoundedUtf8LengthSequenceTest, RemembersAValueOfOneCorrectly) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0);\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(1, 1), 1);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, RemembersAValueOfTwoCorrectly) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 2), 0);\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(1, 1), 2);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, RemembersAValueOfThreeCorrectly) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 3), 0);\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(1, 1), 3);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, RemembersAValueOfFourCorrectly) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 4), 0);\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(1, 1), 4);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, RemembersSeveralAppendedValues) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(1, 4), 1);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(2, 2), 5);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(3, 3), 7);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(4, 1), 10);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, RemembersSeveralPrependedValues) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 4), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 3), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 2), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(4, 1), 10);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(3, 1), 6);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(2, 1), 3);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(1, 1), 1);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, RepeatedInsertsShiftValuesOutTheRightEnd) {\n  BoundedUtf8LengthSequence<32> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 2), 0);\n  for (uint32_t i = 1; i < 31; ++i) {\n    ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0)\n        << \"while moving the 2 into position \" << i;\n    ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(31, 1), 32)\n        << \"after moving the 2 into position \" << i;\n  }\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0)\n      << \"while moving the 2 into position 31\";\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(31, 1), 31)\n      << \"after moving the 2 into position 31\";\n}\n\nTEST(BoundedUtf8LengthSequenceTest, InsertsIntoWord1LeaveWord0Untouched) {\n  BoundedUtf8LengthSequence<64> seq;\n  for (uint32_t i = 0; i < 32; ++i) {\n    ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(i, 2), 2 * i)\n        << \"at index \" << i;\n  }\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(32, 1), 64);\n  EXPECT_EQ(seq.InsertAndReturnSumOfPredecessors(32, 1), 64);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, InsertsIntoWord0ShiftValuesIntoWord1) {\n  BoundedUtf8LengthSequence<64> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(29, 2), 29);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(30, 3), 31);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(31, 4), 34);\n\n  // Pushing two 1's on the front moves the 3 and 4 into the high word.\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(34, 1), 31 + 2 + 3 + 4);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(32, 1), 31 + 2);\n}\n\nTEST(BoundedUtf8LengthSequenceTest, ValuesAreShiftedCorrectlyAmongThreeWords) {\n  BoundedUtf8LengthSequence<96> seq;\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(31, 3), 31);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(63, 4), 62 + 3);\n\n  // This insertion moves both the 3 and the 4 up a word.\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(0, 1), 0);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(65, 1), 63 + 3 + 4);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(64, 1), 63 + 3);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(33, 1), 32 + 3);\n  ASSERT_EQ(seq.InsertAndReturnSumOfPredecessors(32, 1), 32);\n}\n\n}  // namespace\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/decode_rust_punycode.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/decode_rust_punycode.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/debugging/internal/bounded_utf8_length_sequence.h\"\n#include \"absl/debugging/internal/utf8_for_code_point.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nnamespace {\n\n// Decoding Punycode requires repeated random-access insertion into a stream of\n// variable-length UTF-8 code-point encodings.  We need this to be tolerably\n// fast (no N^2 slowdown for unfortunate inputs), and we can't allocate any data\n// structures on the heap (async-signal-safety).\n//\n// It is pragmatic to impose a moderately low limit on the identifier length and\n// bail out if we ever hit it.  Then BoundedUtf8LengthSequence efficiently\n// determines where to insert the next code point, and memmove efficiently makes\n// room for it.\n//\n// The chosen limit is a round number several times larger than identifiers\n// expected in practice, yet still small enough that a memmove of this many\n// UTF-8 characters is not much more expensive than the division and modulus\n// operations that Punycode decoding requires.\nconstexpr uint32_t kMaxChars = 256;\n\n// Constants from RFC 3492 section 5.\nconstexpr uint32_t kBase = 36, kTMin = 1, kTMax = 26, kSkew = 38, kDamp = 700;\n\nconstexpr uint32_t kMaxCodePoint = 0x10ffff;\n\n// Overflow threshold in DecodeRustPunycode's inner loop; see comments there.\nconstexpr uint32_t kMaxI = 1 << 30;\n\n// If punycode_begin .. punycode_end begins with a prefix matching the regular\n// expression [0-9a-zA-Z_]+_, removes that prefix, copies all but the final\n// underscore into out_begin .. out_end, sets num_ascii_chars to the number of\n// bytes copied, and returns true.  (A prefix of this sort represents the\n// nonempty subsequence of ASCII characters in the corresponding plaintext.)\n//\n// If punycode_begin .. punycode_end does not contain an underscore, sets\n// num_ascii_chars to zero and returns true.  (The encoding of a plaintext\n// without any ASCII characters does not carry such a prefix.)\n//\n// Returns false and zeroes num_ascii_chars on failure (either parse error or\n// not enough space in the output buffer).\nbool ConsumeOptionalAsciiPrefix(const char*& punycode_begin,\n                                const char* const punycode_end,\n                                char* const out_begin,\n                                char* const out_end,\n                                uint32_t& num_ascii_chars) {\n  num_ascii_chars = 0;\n\n  // Remember the last underscore if any.  Also use the same string scan to\n  // reject any ASCII bytes that do not belong in an identifier, including NUL,\n  // as well as non-ASCII bytes, which should have been delta-encoded instead.\n  int last_underscore = -1;\n  for (int i = 0; i < punycode_end - punycode_begin; ++i) {\n    const char c = punycode_begin[i];\n    if (c == '_') {\n      last_underscore = i;\n      continue;\n    }\n    // We write out the meaning of absl::ascii_isalnum rather than call that\n    // function because its documentation does not promise it will remain\n    // async-signal-safe under future development.\n    if ('a' <= c && c <= 'z') continue;\n    if ('A' <= c && c <= 'Z') continue;\n    if ('0' <= c && c <= '9') continue;\n    return false;\n  }\n\n  // If there was no underscore, that means there were no ASCII characters in\n  // the plaintext, so there is no prefix to consume.  Our work is done.\n  if (last_underscore < 0) return true;\n\n  // Otherwise there will be an underscore delimiter somewhere.  It can't be\n  // initial because then there would be no ASCII characters to its left, and no\n  // delimiter would have been added in that case.\n  if (last_underscore == 0) return false;\n\n  // Any other position is reasonable.  Make sure there's room in the buffer.\n  if (last_underscore + 1 > out_end - out_begin) return false;\n\n  // Consume and write out the ASCII characters.\n  num_ascii_chars = static_cast<uint32_t>(last_underscore);\n  std::memcpy(out_begin, punycode_begin, num_ascii_chars);\n  out_begin[num_ascii_chars] = '\\0';\n  punycode_begin += num_ascii_chars + 1;\n  return true;\n}\n\n// Returns the value of `c` as a base-36 digit according to RFC 3492 section 5,\n// or -1 if `c` is not such a digit.\nint DigitValue(char c) {\n  if ('0' <= c && c <= '9') return c - '0' + 26;\n  if ('a' <= c && c <= 'z') return c - 'a';\n  if ('A' <= c && c <= 'Z') return c - 'A';\n  return -1;\n}\n\n// Consumes the next delta encoding from punycode_begin .. punycode_end,\n// updating i accordingly.  Returns true on success.  Returns false on parse\n// failure or arithmetic overflow.\nbool ScanNextDelta(const char*& punycode_begin, const char* const punycode_end,\n                   uint32_t bias, uint32_t& i) {\n  uint64_t w = 1;  // 64 bits to prevent overflow in w *= kBase - t\n\n  // \"for k = base to infinity in steps of base do begin ... end\" in RFC 3492\n  // section 6.2.  Each loop iteration scans one digit of the delta.\n  for (uint32_t k = kBase; punycode_begin != punycode_end; k += kBase) {\n    const int digit_value = DigitValue(*punycode_begin++);\n    if (digit_value < 0) return false;\n\n    // Compute this in 64-bit arithmetic so we can check for overflow afterward.\n    const uint64_t new_i = i + static_cast<uint64_t>(digit_value) * w;\n\n    // Valid deltas are bounded by (#chars already emitted) * kMaxCodePoint, but\n    // invalid input could encode an arbitrarily large delta.  Nip that in the\n    // bud here.\n    static_assert(\n        kMaxI >= kMaxChars * kMaxCodePoint,\n        \"kMaxI is too small to prevent spurious failures on good input\");\n    if (new_i > kMaxI) return false;\n\n    static_assert(\n        kMaxI < (uint64_t{1} << 32),\n        \"Make kMaxI smaller or i 64 bits wide to prevent silent wraparound\");\n    i = static_cast<uint32_t>(new_i);\n\n    // Compute the threshold that determines whether this is the last digit and\n    // (if not) what the next digit's place value will be.  This logic from RFC\n    // 3492 section 6.2 is explained in section 3.3.\n    uint32_t t;\n    if (k <= bias + kTMin) {\n      t = kTMin;\n    } else if (k >= bias + kTMax) {\n      t = kTMax;\n    } else {\n      t = k - bias;\n    }\n    if (static_cast<uint32_t>(digit_value) < t) return true;\n\n    // If this gets too large, the range check on new_i in the next iteration\n    // will catch it.  We know this multiplication will not overwrap because w\n    // is 64 bits wide.\n    w *= kBase - t;\n  }\n  return false;\n}\n\n}  // namespace\n\nchar* absl_nullable DecodeRustPunycode(DecodeRustPunycodeOptions options) {\n  const char* punycode_begin = options.punycode_begin;\n  const char* const punycode_end = options.punycode_end;\n  char* const out_begin = options.out_begin;\n  char* const out_end = options.out_end;\n\n  // Write a NUL terminator first.  Later memcpy calls will keep bumping it\n  // along to its new right place.\n  const size_t out_size = static_cast<size_t>(out_end - out_begin);\n  if (out_size == 0) return nullptr;\n  *out_begin = '\\0';\n\n  // RFC 3492 section 6.2 begins here.  We retain the names of integer variables\n  // appearing in that text.\n  uint32_t n = 128, i = 0, bias = 72, num_chars = 0;\n\n  // If there are any ASCII characters, consume them and their trailing\n  // underscore delimiter.\n  if (!ConsumeOptionalAsciiPrefix(punycode_begin, punycode_end,\n                                  out_begin, out_end, num_chars)) {\n    return nullptr;\n  }\n  uint32_t total_utf8_bytes = num_chars;\n\n  BoundedUtf8LengthSequence<kMaxChars> utf8_lengths;\n\n  // \"while the input is not exhausted do begin ... end\"\n  while (punycode_begin != punycode_end) {\n    if (num_chars >= kMaxChars) return nullptr;\n\n    const uint32_t old_i = i;\n\n    if (!ScanNextDelta(punycode_begin, punycode_end, bias, i)) return nullptr;\n\n    // Update bias as in RFC 3492 section 6.1.  (We have inlined adapt.)\n    uint32_t delta = i - old_i;\n    delta /= (old_i == 0 ? kDamp : 2);\n    delta += delta/(num_chars + 1);\n    bias = 0;\n    while (delta > ((kBase - kTMin) * kTMax)/2) {\n      delta /= kBase - kTMin;\n      bias += kBase;\n    }\n    bias += ((kBase - kTMin + 1) * delta)/(delta + kSkew);\n\n    // Back in section 6.2, compute the new code point and insertion index.\n    static_assert(\n        kMaxI + kMaxCodePoint < (uint64_t{1} << 32),\n        \"Make kMaxI smaller or n 64 bits wide to prevent silent wraparound\");\n    n += i/(num_chars + 1);\n    i %= num_chars + 1;\n\n    // To actually insert, we need to convert the code point n to UTF-8 and the\n    // character index i to an index into the byte stream emitted so far.  First\n    // prepare the UTF-8 encoding for n, rejecting surrogates, overlarge values,\n    // and anything that won't fit into the remaining output storage.\n    Utf8ForCodePoint utf8_for_code_point(n);\n    if (!utf8_for_code_point.ok()) return nullptr;\n    if (total_utf8_bytes + utf8_for_code_point.length + 1 > out_size) {\n      return nullptr;\n    }\n\n    // Now insert the new character into both our length map and the output.\n    uint32_t n_index =\n        utf8_lengths.InsertAndReturnSumOfPredecessors(\n            i, utf8_for_code_point.length);\n    std::memmove(\n        out_begin + n_index + utf8_for_code_point.length, out_begin + n_index,\n        total_utf8_bytes + 1 - n_index);\n    std::memcpy(out_begin + n_index, utf8_for_code_point.bytes,\n                utf8_for_code_point.length);\n    total_utf8_bytes += utf8_for_code_point.length;\n    ++num_chars;\n\n    // Finally, advance to the next state before continuing.\n    ++i;\n  }\n\n  return out_begin + total_utf8_bytes;\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/decode_rust_punycode.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_DECODE_RUST_PUNYCODE_H_\n#define ABSL_DEBUGGING_INTERNAL_DECODE_RUST_PUNYCODE_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nstruct DecodeRustPunycodeOptions {\n  const char* absl_nonnull punycode_begin;\n  const char* absl_nonnull punycode_end;\n  char* absl_nonnull out_begin;\n  char* absl_nonnull out_end;\n};\n\n// Given Rust Punycode in `punycode_begin .. punycode_end`, writes the\n// corresponding UTF-8 plaintext into `out_begin .. out_end`, followed by a NUL\n// character, and returns a pointer to that final NUL on success.  On failure\n// returns a null pointer, and the contents of `out_begin .. out_end` are\n// unspecified.\n//\n// Failure occurs in precisely these cases:\n//   - Any input byte does not match [0-9a-zA-Z_].\n//   - The first input byte is an underscore, but no other underscore appears in\n//     the input.\n//   - The delta sequence does not represent a valid sequence of code-point\n//     insertions.\n//   - The plaintext would contain more than 256 code points.\n//\n// DecodeRustPunycode is async-signal-safe with bounded runtime and a small\n// stack footprint, making it suitable for use in demangling Rust symbol names\n// from a signal handler.\nchar* absl_nullable DecodeRustPunycode(DecodeRustPunycodeOptions options);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_DECODE_RUST_PUNYCODE_H_\n"
  },
  {
    "path": "absl/debugging/internal/decode_rust_punycode_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/decode_rust_punycode.h\"\n\n#include <cstddef>\n#include <cstring>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\nusing ::testing::AllOf;\nusing ::testing::Eq;\nusing ::testing::IsNull;\nusing ::testing::Pointee;\nusing ::testing::ResultOf;\nusing ::testing::StrEq;\n\nclass DecodeRustPunycodeTest : public ::testing::Test {\n protected:\n  void FillBufferWithNonzeroBytes() {\n    // The choice of nonzero value to fill with is arbitrary.  The point is just\n    // to fail tests if DecodeRustPunycode forgets to write the final NUL\n    // character.\n    std::memset(buffer_storage_, 0xab, sizeof(buffer_storage_));\n  }\n\n  DecodeRustPunycodeOptions WithAmpleSpace() {\n    FillBufferWithNonzeroBytes();\n\n    DecodeRustPunycodeOptions options;\n    options.punycode_begin = punycode_.data();\n    options.punycode_end = punycode_.data() + punycode_.size();\n    options.out_begin = buffer_storage_;\n    options.out_end = buffer_storage_ + sizeof(buffer_storage_);\n    return options;\n  }\n\n  DecodeRustPunycodeOptions WithJustEnoughSpace() {\n    FillBufferWithNonzeroBytes();\n\n    const size_t begin_offset = sizeof(buffer_storage_) - plaintext_.size() - 1;\n    DecodeRustPunycodeOptions options;\n    options.punycode_begin = punycode_.data();\n    options.punycode_end = punycode_.data() + punycode_.size();\n    options.out_begin = buffer_storage_ + begin_offset;\n    options.out_end = buffer_storage_ + sizeof(buffer_storage_);\n    return options;\n  }\n\n  DecodeRustPunycodeOptions WithOneByteTooFew() {\n    FillBufferWithNonzeroBytes();\n\n    const size_t begin_offset = sizeof(buffer_storage_) - plaintext_.size();\n    DecodeRustPunycodeOptions options;\n    options.punycode_begin = punycode_.data();\n    options.punycode_end = punycode_.data() + punycode_.size();\n    options.out_begin = buffer_storage_ + begin_offset;\n    options.out_end = buffer_storage_ + sizeof(buffer_storage_);\n    return options;\n  }\n\n  // Matches a correct return value of DecodeRustPunycode when `golden` is the\n  // expected plaintext output.\n  auto PointsToTheNulAfter(const std::string& golden) {\n    const size_t golden_size = golden.size();\n    return AllOf(\n        Pointee(Eq('\\0')),\n        ResultOf(\"preceding string body\",\n                 [golden_size](const char* p) { return p - golden_size; },\n                 StrEq(golden)));\n  }\n\n  std::string punycode_;\n  std::string plaintext_;\n  char buffer_storage_[1024];\n};\n\nTEST_F(DecodeRustPunycodeTest, MapsEmptyToEmpty) {\n  punycode_ = \"\";\n  plaintext_ = \"\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest,\n       StripsTheTrailingDelimiterFromAPureRunOfBasicChars) {\n  punycode_ = \"foo_\";\n  plaintext_ = \"foo\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, TreatsTheLastUnderscoreAsTheDelimiter) {\n  punycode_ = \"foo_bar_\";\n  plaintext_ = \"foo_bar\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsALeadingUnderscoreIfNotTheDelimiter) {\n  punycode_ = \"_foo_\";\n  plaintext_ = \"_foo\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, RejectsALeadingUnderscoreDelimiter) {\n  punycode_ = \"_foo\";\n\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, RejectsEmbeddedNul) {\n  punycode_ = std::string(\"foo\\0bar_\", 8);\n\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, RejectsAsciiCharsOtherThanIdentifierChars) {\n  punycode_ = \"foo\\007_\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"foo-_\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"foo;_\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"foo\\177_\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, RejectsRawNonAsciiChars) {\n  punycode_ = \"\\x80\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"\\x80_\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"\\xff\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"\\xff_\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, RecognizesU0080) {\n  // a encodes 0, so the output is the smallest non-ASCII code point standing\n  // alone.  (U+0080 PAD is not an identifier character, but DecodeRustPunycode\n  // does not check whether non-ASCII characters could belong to an identifier.)\n  punycode_ = \"a\";\n  plaintext_ = \"\\xc2\\x80\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, OneByteDeltaSequencesMustBeA) {\n  // Because bias = 72 for the first code point, any digit but a/A is nonfinal\n  // in one of the first two bytes of a delta sequence.\n  punycode_ = \"b\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"z\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"0\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"9\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsDeltaSequenceBA) {\n  punycode_ = \"ba\";\n  plaintext_ = \"\\xc2\\x81\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsOtherDeltaSequencesWithSecondByteA) {\n  punycode_ = \"ca\";\n  plaintext_ = \"\\xc2\\x82\";\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"za\";\n  plaintext_ = \"\\xc2\\x99\";\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"0a\";\n  plaintext_ = \"\\xc2\\x9a\";\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"1a\";\n  plaintext_ = \"\\xc2\\x9b\";\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"9a\";\n  plaintext_ = \"£\";  // Pound sign, U+00A3\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n}\n\nTEST_F(DecodeRustPunycodeTest, RejectsDeltaWhereTheSecondAndLastDigitIsNotA) {\n  punycode_ = \"bb\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"zz\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"00\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n\n  punycode_ = \"99\";\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsDeltasWithSecondByteBFollowedByA) {\n  punycode_ = \"bba\";\n  plaintext_ = \"¤\";  // U+00A4\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"cba\";\n  plaintext_ = \"¥\";  // U+00A5\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"zba\";\n  plaintext_ = \"¼\";  // U+00BC\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"0ba\";\n  plaintext_ = \"½\";  // U+00BD\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"1ba\";\n  plaintext_ = \"¾\";  // U+00BE\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n\n  punycode_ = \"9ba\";\n  plaintext_ = \"Æ\";  // U+00C6\n  EXPECT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n}\n\n// Tests beyond this point use characters allowed in identifiers, so you can\n// prepend _RNvC1cu<decimal length><underscore if [0-9_] follows> to a test\n// input and run it through another Rust demangler to verify that the\n// corresponding golden output is correct.\n\nTEST_F(DecodeRustPunycodeTest, AcceptsTwoByteCharAlone) {\n  punycode_ = \"0ca\";\n  plaintext_ = \"à\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsTwoByteCharBeforeBasicChars) {\n  punycode_ = \"_la_mode_yya\";\n  plaintext_ = \"à_la_mode\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsTwoByteCharAmidBasicChars) {\n  punycode_ = \"verre__vin_m4a\";\n  plaintext_ = \"verre_à_vin\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsTwoByteCharAfterBasicChars) {\n  punycode_ = \"belt_3na\";\n  plaintext_ = \"beltà\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsRepeatedTwoByteChar) {\n  punycode_ = \"0caaaa\";\n  plaintext_ = \"àààà\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsNearbyTwoByteCharsInOrder) {\n  punycode_ = \"3camsuz\";\n  plaintext_ = \"ãéïôù\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsNearbyTwoByteCharsOutOfOrder) {\n  punycode_ = \"3caltsx\";\n  plaintext_ = \"ùéôãï\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsThreeByteCharAlone) {\n  punycode_ = \"fiq\";\n  plaintext_ = \"中\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsRepeatedThreeByteChar) {\n  punycode_ = \"fiqaaaa\";\n  plaintext_ = \"中中中中中\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsThreeByteCharsInOrder) {\n  punycode_ = \"fiq228c\";\n  plaintext_ = \"中文\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsNearbyThreeByteCharsOutOfOrder) {\n  punycode_ = \"fiq128c\";\n  plaintext_ = \"文中\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsFourByteCharAlone) {\n  punycode_ = \"uy7h\";\n  plaintext_ = \"🂻\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsFourByteCharBeforeBasicChars) {\n  punycode_ = \"jack__uh63d\";\n  plaintext_ = \"jack_🂻\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsFourByteCharAmidBasicChars) {\n  punycode_ = \"jack__of_hearts_ki37n\";\n  plaintext_ = \"jack_🂻_of_hearts\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsFourByteCharAfterBasicChars) {\n  punycode_ = \"_of_hearts_kz45i\";\n  plaintext_ = \"🂻_of_hearts\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsRepeatedFourByteChar) {\n  punycode_ = \"uy7haaaa\";\n  plaintext_ = \"🂻🂻🂻🂻🂻\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsNearbyFourByteCharsInOrder) {\n  punycode_ = \"8x7hcjmf\";\n  plaintext_ = \"🂦🂧🂪🂭🂮\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsNearbyFourByteCharsOutOfOrder) {\n  punycode_ = \"8x7hcild\";\n  plaintext_ = \"🂮🂦🂭🂪🂧\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, AcceptsAMixtureOfByteLengths) {\n  punycode_ = \"3caltsx2079ivf8aiuy7cja3a6ak\";\n  plaintext_ = \"ùéôãï中文🂮🂦🂭🂪🂧\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\nTEST_F(DecodeRustPunycodeTest, RejectsOverlargeDeltas) {\n  punycode_ = \"123456789a\";\n\n  EXPECT_THAT(DecodeRustPunycode(WithAmpleSpace()), IsNull());\n}\n\n// Finally, we test on a few prose and poetry snippets as a defense in depth.\n// If our artificial short test inputs did not exercise a bug that is tickled by\n// patterns typical of real human writing, maybe real human writing will catch\n// that.\n//\n// These test inputs are extracted from texts old enough to be out of copyright\n// that probe a variety of ranges of code-point space.  All are longer than 32\n// code points, so they exercise the carrying of seminibbles from one uint64_t\n// to the next higher one in BoundedUtf8LengthSequence.\n\n// The first three lines of the Old English epic _Beowulf_, mostly ASCII with a\n// few archaic two-byte letters interspersed.\nTEST_F(DecodeRustPunycodeTest, Beowulf) {\n  punycode_ = \"hwt_we_gardena_in_geardagum_\"\n              \"eodcyninga_rym_gefrunon_\"\n              \"hu_a_elingas_ellen_fremedon_hxg9c70do9alau\";\n  plaintext_ = \"hwæt_we_gardena_in_geardagum_\"\n               \"þeodcyninga_þrym_gefrunon_\"\n               \"hu_ða_æþelingas_ellen_fremedon\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\n// The whole of 過故人莊 by the 8th-century Chinese poet 孟浩然\n// (Meng Haoran), exercising three-byte-character processing.\nTEST_F(DecodeRustPunycodeTest, MengHaoran) {\n  punycode_ = \"gmq4ss0cfvao1e2wg8mcw8b0wkl9a7tt90a8riuvbk7t8kbv9a66ogofvzlf6\"\n              \"3d01ybn1u28dyqi5q2cxyyxnk5d2gx1ks9ddvfm17bk6gbsd6wftrav60u4ta\";\n  plaintext_ = \"故人具雞黍\" \"邀我至田家\"\n               \"綠樹村邊合\" \"青山郭外斜\"\n               \"開軒面場圃\" \"把酒話桑麻\"\n               \"待到重陽日\" \"還來就菊花\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\n// A poem of the 8th-century Japanese poet 山上憶良 (Yamanoue no Okura).\n// Japanese mixes two-byte and three-byte characters: a good workout for codecs.\nTEST_F(DecodeRustPunycodeTest, YamanoueNoOkura) {\n  punycode_ = \"48jdaa3a6ccpepjrsmlb0q4bwcdtid8fg6c0cai9822utqeruk3om0u4f2wbp0\"\n              \"em23do0op23cc2ff70mb6tae8aq759gja\";\n  plaintext_ = \"瓜食めば\"\n               \"子ども思ほゆ\"\n               \"栗食めば\"\n               \"まして偲はゆ\"\n               \"何処より\"\n               \"来りしものそ\"\n               \"眼交に\"\n               \"もとな懸りて\"\n               \"安眠し寝さぬ\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\n// The first two lines of the Phoenician-language inscription on the sarcophagus\n// of Eshmunazar II of Sidon, 6th century BCE.  Phoenician and many other\n// archaic scripts are allocated in the Supplemental Multilingual Plane (U+10000\n// through U+1FFFF) and thus exercise four-byte-character processing.\nTEST_F(DecodeRustPunycodeTest, EshmunazarSarcophagus) {\n  punycode_ = \"wj9caaabaabbaaohcacxvhdc7bgxbccbdcjeacddcedcdlddbdbddcdbdcknfcee\"\n              \"ifel8del2a7inq9fhcpxikms7a4a9ac9ataaa0g\";\n  plaintext_ = \"𐤁𐤉𐤓𐤇𐤁𐤋𐤁𐤔𐤍𐤕𐤏𐤎𐤓\"\n               \"𐤅𐤀𐤓𐤁𐤏𐤗𐤖𐤖𐤖𐤖𐤋𐤌𐤋𐤊𐤉𐤌𐤋𐤊\"\n               \"𐤀𐤔𐤌𐤍𐤏𐤆𐤓𐤌𐤋𐤊𐤑𐤃𐤍𐤌\"\n               \"𐤁𐤍𐤌𐤋𐤊𐤕𐤁𐤍𐤕𐤌𐤋𐤊𐤑𐤃𐤍𐤌\"\n               \"𐤃𐤁𐤓𐤌𐤋𐤊𐤀𐤔𐤌𐤍𐤏𐤆𐤓𐤌𐤋𐤊\"\n               \"𐤑𐤃𐤍𐤌𐤋𐤀𐤌𐤓𐤍𐤂𐤆𐤋𐤕\";\n\n  ASSERT_THAT(DecodeRustPunycode(WithAmpleSpace()),\n              PointsToTheNulAfter(plaintext_));\n  ASSERT_THAT(DecodeRustPunycode(WithJustEnoughSpace()),\n              PointsToTheNulAfter(plaintext_));\n  EXPECT_THAT(DecodeRustPunycode(WithOneByteTooFew()), IsNull());\n}\n\n}  // namespace\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/demangle.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// For reference check out:\n// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling\n\n#include \"absl/debugging/internal/demangle.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <limits>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/debugging/internal/demangle_rust.h\"\n\n#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE\n#include <cxxabi.h>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\ntypedef struct {\n  const char *abbrev;\n  const char *real_name;\n  // Number of arguments in <expression> context, or 0 if disallowed.\n  int arity;\n} AbbrevPair;\n\n// List of operators from Itanium C++ ABI.\nstatic const AbbrevPair kOperatorList[] = {\n    // New has special syntax.\n    {\"nw\", \"new\", 0},\n    {\"na\", \"new[]\", 0},\n\n    // Special-cased elsewhere to support the optional gs prefix.\n    {\"dl\", \"delete\", 1},\n    {\"da\", \"delete[]\", 1},\n\n    {\"aw\", \"co_await\", 1},\n\n    {\"ps\", \"+\", 1},  // \"positive\"\n    {\"ng\", \"-\", 1},  // \"negative\"\n    {\"ad\", \"&\", 1},  // \"address-of\"\n    {\"de\", \"*\", 1},  // \"dereference\"\n    {\"co\", \"~\", 1},\n\n    {\"pl\", \"+\", 2},\n    {\"mi\", \"-\", 2},\n    {\"ml\", \"*\", 2},\n    {\"dv\", \"/\", 2},\n    {\"rm\", \"%\", 2},\n    {\"an\", \"&\", 2},\n    {\"or\", \"|\", 2},\n    {\"eo\", \"^\", 2},\n    {\"aS\", \"=\", 2},\n    {\"pL\", \"+=\", 2},\n    {\"mI\", \"-=\", 2},\n    {\"mL\", \"*=\", 2},\n    {\"dV\", \"/=\", 2},\n    {\"rM\", \"%=\", 2},\n    {\"aN\", \"&=\", 2},\n    {\"oR\", \"|=\", 2},\n    {\"eO\", \"^=\", 2},\n    {\"ls\", \"<<\", 2},\n    {\"rs\", \">>\", 2},\n    {\"lS\", \"<<=\", 2},\n    {\"rS\", \">>=\", 2},\n    {\"ss\", \"<=>\", 2},\n    {\"eq\", \"==\", 2},\n    {\"ne\", \"!=\", 2},\n    {\"lt\", \"<\", 2},\n    {\"gt\", \">\", 2},\n    {\"le\", \"<=\", 2},\n    {\"ge\", \">=\", 2},\n    {\"nt\", \"!\", 1},\n    {\"aa\", \"&&\", 2},\n    {\"oo\", \"||\", 2},\n    {\"pp\", \"++\", 1},\n    {\"mm\", \"--\", 1},\n    {\"cm\", \",\", 2},\n    {\"pm\", \"->*\", 2},\n    {\"pt\", \"->\", 0},  // Special syntax\n    {\"cl\", \"()\", 0},  // Special syntax\n    {\"ix\", \"[]\", 2},\n    {\"qu\", \"?\", 3},\n    {\"st\", \"sizeof\", 0},  // Special syntax\n    {\"sz\", \"sizeof\", 1},  // Not a real operator name, but used in expressions.\n    {\"sZ\", \"sizeof...\", 0},  // Special syntax\n    {nullptr, nullptr, 0},\n};\n\n// List of builtin types from Itanium C++ ABI.\n//\n// Invariant: only one- or two-character type abbreviations here.\nstatic const AbbrevPair kBuiltinTypeList[] = {\n    {\"v\", \"void\", 0},\n    {\"w\", \"wchar_t\", 0},\n    {\"b\", \"bool\", 0},\n    {\"c\", \"char\", 0},\n    {\"a\", \"signed char\", 0},\n    {\"h\", \"unsigned char\", 0},\n    {\"s\", \"short\", 0},\n    {\"t\", \"unsigned short\", 0},\n    {\"i\", \"int\", 0},\n    {\"j\", \"unsigned int\", 0},\n    {\"l\", \"long\", 0},\n    {\"m\", \"unsigned long\", 0},\n    {\"x\", \"long long\", 0},\n    {\"y\", \"unsigned long long\", 0},\n    {\"n\", \"__int128\", 0},\n    {\"o\", \"unsigned __int128\", 0},\n    {\"f\", \"float\", 0},\n    {\"d\", \"double\", 0},\n    {\"e\", \"long double\", 0},\n    {\"g\", \"__float128\", 0},\n    {\"z\", \"ellipsis\", 0},\n\n    {\"De\", \"decimal128\", 0},      // IEEE 754r decimal floating point (128 bits)\n    {\"Dd\", \"decimal64\", 0},       // IEEE 754r decimal floating point (64 bits)\n    {\"Dc\", \"decltype(auto)\", 0},\n    {\"Da\", \"auto\", 0},\n    {\"Dn\", \"std::nullptr_t\", 0},  // i.e., decltype(nullptr)\n    {\"Df\", \"decimal32\", 0},       // IEEE 754r decimal floating point (32 bits)\n    {\"Di\", \"char32_t\", 0},\n    {\"Du\", \"char8_t\", 0},\n    {\"Ds\", \"char16_t\", 0},\n    {\"Dh\", \"float16\", 0},         // IEEE 754r half-precision float (16 bits)\n    {nullptr, nullptr, 0},\n};\n\n// List of substitutions Itanium C++ ABI.\nstatic const AbbrevPair kSubstitutionList[] = {\n    {\"St\", \"\", 0},\n    {\"Sa\", \"allocator\", 0},\n    {\"Sb\", \"basic_string\", 0},\n    // std::basic_string<char, std::char_traits<char>,std::allocator<char> >\n    {\"Ss\", \"string\", 0},\n    // std::basic_istream<char, std::char_traits<char> >\n    {\"Si\", \"istream\", 0},\n    // std::basic_ostream<char, std::char_traits<char> >\n    {\"So\", \"ostream\", 0},\n    // std::basic_iostream<char, std::char_traits<char> >\n    {\"Sd\", \"iostream\", 0},\n    {nullptr, nullptr, 0},\n};\n\n// State needed for demangling.  This struct is copied in almost every stack\n// frame, so every byte counts.\ntypedef struct {\n  int mangled_idx;                     // Cursor of mangled name.\n  int out_cur_idx;                     // Cursor of output string.\n  int prev_name_idx;                   // For constructors/destructors.\n  unsigned int prev_name_length : 16;  // For constructors/destructors.\n  signed int nest_level : 15;          // For nested names.\n  unsigned int append : 1;             // Append flag.\n  // Note: for some reason MSVC can't pack \"bool append : 1\" into the same int\n  // with the above two fields, so we use an int instead.  Amusingly it can pack\n  // \"signed bool\" as expected, but relying on that to continue to be a legal\n  // type seems ill-advised (as it's illegal in at least clang).\n} ParseState;\n\nstatic_assert(sizeof(ParseState) == 4 * sizeof(int),\n              \"unexpected size of ParseState\");\n\n// One-off state for demangling that's not subject to backtracking -- either\n// constant data, data that's intentionally immune to backtracking (steps), or\n// data that would never be changed by backtracking anyway (recursion_depth).\n//\n// Only one copy of this exists for each call to Demangle, so the size of this\n// struct is nearly inconsequential.\ntypedef struct {\n  const char *mangled_begin;  // Beginning of input string.\n  char *out;                  // Beginning of output string.\n  int out_end_idx;            // One past last allowed output character.\n  int recursion_depth;        // For stack exhaustion prevention.\n  int steps;               // Cap how much work we'll do, regardless of depth.\n  ParseState parse_state;  // Backtrackable state copied for most frames.\n\n  // Conditionally compiled support for marking the position of the first\n  // construct Demangle couldn't parse.  This preprocessor symbol is intended\n  // for use by Abseil demangler maintainers only; its behavior is not part of\n  // Abseil's public interface.\n#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK\n  int high_water_mark;  // Input position where parsing failed.\n  bool too_complex;  // True if any guard.IsTooComplex() call returned true.\n#endif\n} State;\n\nnamespace {\n\n#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK\nvoid UpdateHighWaterMark(State *state) {\n  if (state->high_water_mark < state->parse_state.mangled_idx) {\n    state->high_water_mark = state->parse_state.mangled_idx;\n  }\n}\n\nvoid ReportHighWaterMark(State *state) {\n  // Write out the mangled name with the trouble point marked, provided that the\n  // output buffer is large enough and the mangled name did not hit a complexity\n  // limit (in which case the high water mark wouldn't point out an unparsable\n  // construct, only the point where a budget ran out).\n  const size_t input_length = std::strlen(state->mangled_begin);\n  if (input_length + 6 > static_cast<size_t>(state->out_end_idx) ||\n      state->too_complex) {\n    if (state->out_end_idx > 0) state->out[0] = '\\0';\n    return;\n  }\n  const size_t high_water_mark = static_cast<size_t>(state->high_water_mark);\n  std::memcpy(state->out, state->mangled_begin, high_water_mark);\n  std::memcpy(state->out + high_water_mark, \"--!--\", 5);\n  std::memcpy(state->out + high_water_mark + 5,\n              state->mangled_begin + high_water_mark,\n              input_length - high_water_mark);\n  state->out[input_length + 5] = '\\0';\n}\n#else\nvoid UpdateHighWaterMark(State *) {}\nvoid ReportHighWaterMark(State *) {}\n#endif\n\n// Prevent deep recursion / stack exhaustion.\n// Also prevent unbounded handling of complex inputs.\nclass ComplexityGuard {\n public:\n  explicit ComplexityGuard(State *state) : state_(state) {\n    ++state->recursion_depth;\n    ++state->steps;\n  }\n  ~ComplexityGuard() { --state_->recursion_depth; }\n\n  // 256 levels of recursion seems like a reasonable upper limit on depth.\n  // 128 is not enough to demangle synthetic tests from demangle_unittest.txt:\n  // \"_ZaaZZZZ...\" and \"_ZaaZcvZcvZ...\"\n  static constexpr int kRecursionDepthLimit = 256;\n\n  // We're trying to pick a charitable upper-limit on how many parse steps are\n  // necessary to handle something that a human could actually make use of.\n  // This is mostly in place as a bound on how much work we'll do if we are\n  // asked to demangle an mangled name from an untrusted source, so it should be\n  // much larger than the largest expected symbol, but much smaller than the\n  // amount of work we can do in, e.g., a second.\n  //\n  // Some real-world symbols from an arbitrary binary started failing between\n  // 2^12 and 2^13, so we multiply the latter by an extra factor of 16 to set\n  // the limit.\n  //\n  // Spending one second on 2^17 parse steps would require each step to take\n  // 7.6us, or ~30000 clock cycles, so it's safe to say this can be done in\n  // under a second.\n  static constexpr int kParseStepsLimit = 1 << 17;\n\n  bool IsTooComplex() const {\n    if (state_->recursion_depth > kRecursionDepthLimit ||\n        state_->steps > kParseStepsLimit) {\n#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK\n      state_->too_complex = true;\n#endif\n      return true;\n    }\n    return false;\n  }\n\n private:\n  State *state_;\n};\n}  // namespace\n\n// We don't use strlen() in libc since it's not guaranteed to be async\n// signal safe.\nstatic size_t StrLen(const char *str) {\n  size_t len = 0;\n  while (*str != '\\0') {\n    ++str;\n    ++len;\n  }\n  return len;\n}\n\n// Returns true if \"str\" has at least \"n\" characters remaining.\nstatic bool AtLeastNumCharsRemaining(const char *str, size_t n) {\n  for (size_t i = 0; i < n; ++i) {\n    if (str[i] == '\\0') {\n      return false;\n    }\n  }\n  return true;\n}\n\n// Returns true if \"str\" has \"prefix\" as a prefix.\nstatic bool StrPrefix(const char *str, const char *prefix) {\n  size_t i = 0;\n  while (str[i] != '\\0' && prefix[i] != '\\0' && str[i] == prefix[i]) {\n    ++i;\n  }\n  return prefix[i] == '\\0';  // Consumed everything in \"prefix\".\n}\n\nstatic void InitState(State* state,\n                      const char* mangled,\n                      char* out,\n                      size_t out_size) {\n  state->mangled_begin = mangled;\n  state->out = out;\n  state->out_end_idx = static_cast<int>(out_size);\n  state->recursion_depth = 0;\n  state->steps = 0;\n#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK\n  state->high_water_mark = 0;\n  state->too_complex = false;\n#endif\n\n  state->parse_state.mangled_idx = 0;\n  state->parse_state.out_cur_idx = 0;\n  state->parse_state.prev_name_idx = 0;\n  state->parse_state.prev_name_length = 0;\n  state->parse_state.nest_level = -1;\n  state->parse_state.append = true;\n}\n\nstatic inline const char *RemainingInput(State *state) {\n  return &state->mangled_begin[state->parse_state.mangled_idx];\n}\n\n// Returns true and advances \"mangled_idx\" if we find \"one_char_token\"\n// at \"mangled_idx\" position.  It is assumed that \"one_char_token\" does\n// not contain '\\0'.\nstatic bool ParseOneCharToken(State *state, const char one_char_token) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (RemainingInput(state)[0] == one_char_token) {\n    ++state->parse_state.mangled_idx;\n    UpdateHighWaterMark(state);\n    return true;\n  }\n  return false;\n}\n\n// Returns true and advances \"mangled_idx\" if we find \"two_char_token\"\n// at \"mangled_idx\" position.  It is assumed that \"two_char_token\" does\n// not contain '\\0'.\nstatic bool ParseTwoCharToken(State *state, const char *two_char_token) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (RemainingInput(state)[0] == two_char_token[0] &&\n      RemainingInput(state)[1] == two_char_token[1]) {\n    state->parse_state.mangled_idx += 2;\n    UpdateHighWaterMark(state);\n    return true;\n  }\n  return false;\n}\n\n// Returns true and advances \"mangled_idx\" if we find \"three_char_token\"\n// at \"mangled_idx\" position.  It is assumed that \"three_char_token\" does\n// not contain '\\0'.\nstatic bool ParseThreeCharToken(State *state, const char *three_char_token) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (RemainingInput(state)[0] == three_char_token[0] &&\n      RemainingInput(state)[1] == three_char_token[1] &&\n      RemainingInput(state)[2] == three_char_token[2]) {\n    state->parse_state.mangled_idx += 3;\n    UpdateHighWaterMark(state);\n    return true;\n  }\n  return false;\n}\n\n// Returns true and advances \"mangled_idx\" if we find a copy of the\n// NUL-terminated string \"long_token\" at \"mangled_idx\" position.\nstatic bool ParseLongToken(State *state, const char *long_token) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  int i = 0;\n  for (; long_token[i] != '\\0'; ++i) {\n    // Note that we cannot run off the end of the NUL-terminated input here.\n    // Inside the loop body, long_token[i] is known to be different from NUL.\n    // So if we read the NUL on the end of the input here, we return at once.\n    if (RemainingInput(state)[i] != long_token[i]) return false;\n  }\n  state->parse_state.mangled_idx += i;\n  UpdateHighWaterMark(state);\n  return true;\n}\n\n// Returns true and advances \"mangled_cur\" if we find any character in\n// \"char_class\" at \"mangled_cur\" position.\nstatic bool ParseCharClass(State *state, const char *char_class) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (RemainingInput(state)[0] == '\\0') {\n    return false;\n  }\n  const char *p = char_class;\n  for (; *p != '\\0'; ++p) {\n    if (RemainingInput(state)[0] == *p) {\n      ++state->parse_state.mangled_idx;\n      UpdateHighWaterMark(state);\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic bool ParseDigit(State *state, int *digit) {\n  char c = RemainingInput(state)[0];\n  if (ParseCharClass(state, \"0123456789\")) {\n    if (digit != nullptr) {\n      *digit = c - '0';\n    }\n    return true;\n  }\n  return false;\n}\n\n// This function is used for handling an optional non-terminal.\nstatic bool Optional(bool /*status*/) { return true; }\n\n// This function is used for handling <non-terminal>+ syntax.\ntypedef bool (*ParseFunc)(State *);\nstatic bool OneOrMore(ParseFunc parse_func, State *state) {\n  if (parse_func(state)) {\n    while (parse_func(state)) {\n    }\n    return true;\n  }\n  return false;\n}\n\n// This function is used for handling <non-terminal>* syntax. The function\n// always returns true and must be followed by a termination token or a\n// terminating sequence not handled by parse_func (e.g.\n// ParseOneCharToken(state, 'E')).\nstatic bool ZeroOrMore(ParseFunc parse_func, State *state) {\n  while (parse_func(state)) {\n  }\n  return true;\n}\n\n// Append \"str\" at \"out_cur_idx\".  If there is an overflow, out_cur_idx is\n// set to out_end_idx+1.  The output string is ensured to\n// always terminate with '\\0' as long as there is no overflow.\nstatic void Append(State *state, const char *const str, const size_t length) {\n  for (size_t i = 0; i < length; ++i) {\n    if (state->parse_state.out_cur_idx + 1 <\n        state->out_end_idx) {  // +1 for '\\0'\n      state->out[state->parse_state.out_cur_idx++] = str[i];\n    } else {\n      // signal overflow\n      state->parse_state.out_cur_idx = state->out_end_idx + 1;\n      break;\n    }\n  }\n  if (state->parse_state.out_cur_idx < state->out_end_idx) {\n    state->out[state->parse_state.out_cur_idx] =\n        '\\0';  // Terminate it with '\\0'\n  }\n}\n\n// We don't use equivalents in libc to avoid locale issues.\nstatic bool IsLower(char c) { return c >= 'a' && c <= 'z'; }\n\nstatic bool IsAlpha(char c) {\n  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');\n}\n\nstatic bool IsDigit(char c) { return c >= '0' && c <= '9'; }\n\nstatic bool EndsWith(State *state, const char chr) {\n  return state->parse_state.out_cur_idx > 0 &&\n         state->parse_state.out_cur_idx < state->out_end_idx &&\n         chr == state->out[state->parse_state.out_cur_idx - 1];\n}\n\n// Append \"str\" with some tweaks, iff \"append\" state is true.\nstatic void MaybeAppendWithLength(State *state, const char *const str,\n                                  const size_t length) {\n  if (state->parse_state.append && length > 0) {\n    // Append a space if the output buffer ends with '<' and \"str\"\n    // starts with '<' to avoid <<<.\n    if (str[0] == '<' && EndsWith(state, '<')) {\n      Append(state, \" \", 1);\n    }\n    // Remember the last identifier name for ctors/dtors,\n    // but only if we haven't yet overflown the buffer.\n    if (state->parse_state.out_cur_idx < state->out_end_idx &&\n        (IsAlpha(str[0]) || str[0] == '_')) {\n      state->parse_state.prev_name_idx = state->parse_state.out_cur_idx;\n      state->parse_state.prev_name_length = static_cast<unsigned int>(length);\n    }\n    Append(state, str, length);\n  }\n}\n\n// Appends a positive decimal number to the output if appending is enabled.\nstatic bool MaybeAppendDecimal(State *state, int val) {\n  // Max {32-64}-bit unsigned int is 20 digits.\n  constexpr size_t kMaxLength = 20;\n  char buf[kMaxLength];\n\n  // We can't use itoa or sprintf as neither is specified to be\n  // async-signal-safe.\n  if (state->parse_state.append) {\n    // We can't have a one-before-the-beginning pointer, so instead start with\n    // one-past-the-end and manipulate one character before the pointer.\n    char *p = &buf[kMaxLength];\n    do {  // val=0 is the only input that should write a leading zero digit.\n      *--p = static_cast<char>((val % 10) + '0');\n      val /= 10;\n    } while (p > buf && val != 0);\n\n    // 'p' landed on the last character we set.  How convenient.\n    Append(state, p, kMaxLength - static_cast<size_t>(p - buf));\n  }\n\n  return true;\n}\n\n// A convenient wrapper around MaybeAppendWithLength().\n// Returns true so that it can be placed in \"if\" conditions.\nstatic bool MaybeAppend(State *state, const char *const str) {\n  if (state->parse_state.append) {\n    size_t length = StrLen(str);\n    MaybeAppendWithLength(state, str, length);\n  }\n  return true;\n}\n\n// This function is used for handling nested names.\nstatic bool EnterNestedName(State *state) {\n  state->parse_state.nest_level = 0;\n  return true;\n}\n\n// This function is used for handling nested names.\nstatic bool LeaveNestedName(State *state, int16_t prev_value) {\n  state->parse_state.nest_level = prev_value;\n  return true;\n}\n\n// Disable the append mode not to print function parameters, etc.\nstatic bool DisableAppend(State *state) {\n  state->parse_state.append = false;\n  return true;\n}\n\n// Restore the append mode to the previous state.\nstatic bool RestoreAppend(State *state, bool prev_value) {\n  state->parse_state.append = prev_value;\n  return true;\n}\n\n// Increase the nest level for nested names.\nstatic void MaybeIncreaseNestLevel(State *state) {\n  if (state->parse_state.nest_level > -1) {\n    ++state->parse_state.nest_level;\n  }\n}\n\n// Appends :: for nested names if necessary.\nstatic void MaybeAppendSeparator(State *state) {\n  if (state->parse_state.nest_level >= 1) {\n    MaybeAppend(state, \"::\");\n  }\n}\n\n// Cancel the last separator if necessary.\nstatic void MaybeCancelLastSeparator(State *state) {\n  if (state->parse_state.nest_level >= 1 && state->parse_state.append &&\n      state->parse_state.out_cur_idx >= 2) {\n    state->parse_state.out_cur_idx -= 2;\n    state->out[state->parse_state.out_cur_idx] = '\\0';\n  }\n}\n\n// Returns true if the identifier of the given length pointed to by\n// \"mangled_cur\" is anonymous namespace.\nstatic bool IdentifierIsAnonymousNamespace(State *state, size_t length) {\n  // Returns true if \"anon_prefix\" is a proper prefix of \"mangled_cur\".\n  static const char anon_prefix[] = \"_GLOBAL__N_\";\n  return (length > (sizeof(anon_prefix) - 1) &&\n          StrPrefix(RemainingInput(state), anon_prefix));\n}\n\n// Forward declarations of our parsing functions.\nstatic bool ParseMangledName(State *state);\nstatic bool ParseEncoding(State *state);\nstatic bool ParseName(State *state);\nstatic bool ParseUnscopedName(State *state);\nstatic bool ParseNestedName(State *state);\nstatic bool ParsePrefix(State *state);\nstatic bool ParseUnqualifiedName(State *state);\nstatic bool ParseSourceName(State *state);\nstatic bool ParseLocalSourceName(State *state);\nstatic bool ParseUnnamedTypeName(State *state);\nstatic bool ParseNumber(State *state, int *number_out);\nstatic bool ParseFloatNumber(State *state);\nstatic bool ParseSeqId(State *state);\nstatic bool ParseIdentifier(State *state, size_t length);\nstatic bool ParseOperatorName(State *state, int *arity);\nstatic bool ParseConversionOperatorType(State *state);\nstatic bool ParseSpecialName(State *state);\nstatic bool ParseCallOffset(State *state);\nstatic bool ParseNVOffset(State *state);\nstatic bool ParseVOffset(State *state);\nstatic bool ParseAbiTags(State *state);\nstatic bool ParseCtorDtorName(State *state);\nstatic bool ParseDecltype(State *state);\nstatic bool ParseType(State *state);\nstatic bool ParseCVQualifiers(State *state);\nstatic bool ParseExtendedQualifier(State *state);\nstatic bool ParseBuiltinType(State *state);\nstatic bool ParseVendorExtendedType(State *state);\nstatic bool ParseFunctionType(State *state);\nstatic bool ParseBareFunctionType(State *state);\nstatic bool ParseOverloadAttribute(State *state);\nstatic bool ParseClassEnumType(State *state);\nstatic bool ParseArrayType(State *state);\nstatic bool ParsePointerToMemberType(State *state);\nstatic bool ParseTemplateParam(State *state);\nstatic bool ParseTemplateParamDecl(State *state);\nstatic bool ParseTemplateTemplateParam(State *state);\nstatic bool ParseTemplateArgs(State *state);\nstatic bool ParseTemplateArg(State *state);\nstatic bool ParseBaseUnresolvedName(State *state);\nstatic bool ParseUnresolvedName(State *state);\nstatic bool ParseUnresolvedQualifierLevel(State *state);\nstatic bool ParseUnionSelector(State* state);\nstatic bool ParseFunctionParam(State* state);\nstatic bool ParseBracedExpression(State *state);\nstatic bool ParseExpression(State *state);\nstatic bool ParseInitializer(State *state);\nstatic bool ParseExprPrimary(State *state);\nstatic bool ParseExprCastValueAndTrailingE(State *state);\nstatic bool ParseQRequiresClauseExpr(State *state);\nstatic bool ParseRequirement(State *state);\nstatic bool ParseTypeConstraint(State *state);\nstatic bool ParseLocalName(State *state);\nstatic bool ParseLocalNameSuffix(State *state);\nstatic bool ParseDiscriminator(State *state);\nstatic bool ParseSubstitution(State *state, bool accept_std);\n\n// Implementation note: the following code is a straightforward\n// translation of the Itanium C++ ABI defined in BNF with a couple of\n// exceptions.\n//\n// - Support GNU extensions not defined in the Itanium C++ ABI\n// - <prefix> and <template-prefix> are combined to avoid infinite loop\n// - Reorder patterns to shorten the code\n// - Reorder patterns to give greedier functions precedence\n//   We'll mark \"Less greedy than\" for these cases in the code\n//\n// Each parsing function changes the parse state and returns true on\n// success, or returns false and doesn't change the parse state (note:\n// the parse-steps counter increases regardless of success or failure).\n// To ensure that the parse state isn't changed in the latter case, we\n// save the original state before we call multiple parsing functions\n// consecutively with &&, and restore it if unsuccessful.  See\n// ParseEncoding() as an example of this convention.  We follow the\n// convention throughout the code.\n//\n// Originally we tried to do demangling without following the full ABI\n// syntax but it turned out we needed to follow the full syntax to\n// parse complicated cases like nested template arguments.  Note that\n// implementing a full-fledged demangler isn't trivial (libiberty's\n// cp-demangle.c has +4300 lines).\n//\n// Note that (foo) in <(foo) ...> is a modifier to be ignored.\n//\n// Reference:\n// - Itanium C++ ABI\n//   <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling>\n\n// <mangled-name> ::= _Z <encoding>\nstatic bool ParseMangledName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  return ParseTwoCharToken(state, \"_Z\") && ParseEncoding(state);\n}\n\n// <encoding> ::= <(function) name> <bare-function-type>\n//                [`Q` <requires-clause expr>]\n//            ::= <(data) name>\n//            ::= <special-name>\n//\n// NOTE: Based on http://shortn/_Hoq9qG83rx\nstatic bool ParseEncoding(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  // Since the first two productions both start with <name>, attempt\n  // to parse it only once to avoid exponential blowup of backtracking.\n  //\n  // We're careful about exponential blowup because <encoding> recursively\n  // appears in other productions downstream of its first two productions,\n  // which means that every call to `ParseName` would possibly indirectly\n  // result in two calls to `ParseName` etc.\n  if (ParseName(state)) {\n    if (!ParseBareFunctionType(state)) {\n      return true;  // <(data) name>\n    }\n\n    // Parsed: <(function) name> <bare-function-type>\n    // Pending: [`Q` <requires-clause expr>]\n    ParseQRequiresClauseExpr(state);  // restores state on failure\n    return true;\n  }\n\n  if (ParseSpecialName(state)) {\n    return true;  // <special-name>\n  }\n  return false;\n}\n\n// <name> ::= <nested-name>\n//        ::= <unscoped-template-name> <template-args>\n//        ::= <unscoped-name>\n//        ::= <local-name>\nstatic bool ParseName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseNestedName(state) || ParseLocalName(state)) {\n    return true;\n  }\n\n  // We reorganize the productions to avoid re-parsing unscoped names.\n  // - Inline <unscoped-template-name> productions:\n  //   <name> ::= <substitution> <template-args>\n  //          ::= <unscoped-name> <template-args>\n  //          ::= <unscoped-name>\n  // - Merge the two productions that start with unscoped-name:\n  //   <name> ::= <unscoped-name> [<template-args>]\n\n  ParseState copy = state->parse_state;\n  // \"std<...>\" isn't a valid name.\n  if (ParseSubstitution(state, /*accept_std=*/false) &&\n      ParseTemplateArgs(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Note there's no need to restore state after this since only the first\n  // subparser can fail.\n  return ParseUnscopedName(state) && Optional(ParseTemplateArgs(state));\n}\n\n// <unscoped-name> ::= <unqualified-name>\n//                 ::= St <unqualified-name>\nstatic bool ParseUnscopedName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseUnqualifiedName(state)) {\n    return true;\n  }\n\n  ParseState copy = state->parse_state;\n  if (ParseTwoCharToken(state, \"St\") && MaybeAppend(state, \"std::\") &&\n      ParseUnqualifiedName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <ref-qualifer> ::= R // lvalue method reference qualifier\n//                ::= O // rvalue method reference qualifier\nstatic inline bool ParseRefQualifier(State *state) {\n  return ParseCharClass(state, \"OR\");\n}\n\n// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix>\n//                   <unqualified-name> E\n//               ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>\n//                   <template-args> E\nstatic bool ParseNestedName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'N') && EnterNestedName(state) &&\n      Optional(ParseCVQualifiers(state)) &&\n      Optional(ParseRefQualifier(state)) && ParsePrefix(state) &&\n      LeaveNestedName(state, copy.nest_level) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// This part is tricky.  If we literally translate them to code, we'll\n// end up infinite loop.  Hence we merge them to avoid the case.\n//\n// <prefix> ::= <prefix> <unqualified-name>\n//          ::= <template-prefix> <template-args>\n//          ::= <template-param>\n//          ::= <decltype>\n//          ::= <substitution>\n//          ::= # empty\n// <template-prefix> ::= <prefix> <(template) unqualified-name>\n//                   ::= <template-param>\n//                   ::= <substitution>\n//                   ::= <vendor-extended-type>\nstatic bool ParsePrefix(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  bool has_something = false;\n  while (true) {\n    MaybeAppendSeparator(state);\n    if (ParseTemplateParam(state) || ParseDecltype(state) ||\n        ParseSubstitution(state, /*accept_std=*/true) ||\n        // Although the official grammar does not mention it, nested-names\n        // shaped like Nu14__some_builtinIiE6memberE occur in practice, and it\n        // is not clear what else a compiler is supposed to do when a\n        // vendor-extended type has named members.\n        ParseVendorExtendedType(state) ||\n        ParseUnscopedName(state) ||\n        (ParseOneCharToken(state, 'M') && ParseUnnamedTypeName(state))) {\n      has_something = true;\n      MaybeIncreaseNestLevel(state);\n      continue;\n    }\n    MaybeCancelLastSeparator(state);\n    if (has_something && ParseTemplateArgs(state)) {\n      return ParsePrefix(state);\n    } else {\n      break;\n    }\n  }\n  return true;\n}\n\n// <unqualified-name> ::= <operator-name> [<abi-tags>]\n//                    ::= <ctor-dtor-name> [<abi-tags>]\n//                    ::= <source-name> [<abi-tags>]\n//                    ::= <local-source-name> [<abi-tags>]\n//                    ::= <unnamed-type-name> [<abi-tags>]\n//                    ::= DC <source-name>+ E  # C++17 structured binding\n//                    ::= F <source-name>  # C++20 constrained friend\n//                    ::= F <operator-name>  # C++20 constrained friend\n//\n// <local-source-name> is a GCC extension; see below.\n//\n// For the F notation for constrained friends, see\n// https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-1491130332.\nstatic bool ParseUnqualifiedName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseOperatorName(state, nullptr) || ParseCtorDtorName(state) ||\n      ParseSourceName(state) || ParseLocalSourceName(state) ||\n      ParseUnnamedTypeName(state)) {\n    return ParseAbiTags(state);\n  }\n\n  // DC <source-name>+ E\n  ParseState copy = state->parse_state;\n  if (ParseTwoCharToken(state, \"DC\") && OneOrMore(ParseSourceName, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // F <source-name>\n  // F <operator-name>\n  if (ParseOneCharToken(state, 'F') && MaybeAppend(state, \"friend \") &&\n      (ParseSourceName(state) || ParseOperatorName(state, nullptr))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <abi-tags> ::= <abi-tag> [<abi-tags>]\n// <abi-tag>  ::= B <source-name>\nstatic bool ParseAbiTags(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  while (ParseOneCharToken(state, 'B')) {\n    ParseState copy = state->parse_state;\n    MaybeAppend(state, \"[abi:\");\n\n    if (!ParseSourceName(state)) {\n      state->parse_state = copy;\n      return false;\n    }\n    MaybeAppend(state, \"]\");\n  }\n\n  return true;\n}\n\n// <source-name> ::= <positive length number> <identifier>\nstatic bool ParseSourceName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  int length = -1;\n  if (ParseNumber(state, &length) &&\n      ParseIdentifier(state, static_cast<size_t>(length))) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <local-source-name> ::= L <source-name> [<discriminator>]\n//\n// References:\n//   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775\n//   https://gcc.gnu.org/viewcvs?view=rev&revision=124467\nstatic bool ParseLocalSourceName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'L') && ParseSourceName(state) &&\n      Optional(ParseDiscriminator(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <unnamed-type-name> ::= Ut [<(nonnegative) number>] _\n//                     ::= <closure-type-name>\n// <closure-type-name> ::= Ul <lambda-sig> E [<(nonnegative) number>] _\n// <lambda-sig>        ::= <template-param-decl>* <(parameter) type>+\n//\n// For <template-param-decl>* in <lambda-sig> see:\n//\n// https://github.com/itanium-cxx-abi/cxx-abi/issues/31\nstatic bool ParseUnnamedTypeName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  // Type's 1-based index n is encoded as { \"\", n == 1; itoa(n-2), otherwise }.\n  // Optionally parse the encoded value into 'which' and add 2 to get the index.\n  int which = -1;\n\n  // Unnamed type local to function or class.\n  if (ParseTwoCharToken(state, \"Ut\") && Optional(ParseNumber(state, &which)) &&\n      which <= std::numeric_limits<int>::max() - 2 &&  // Don't overflow.\n      ParseOneCharToken(state, '_')) {\n    MaybeAppend(state, \"{unnamed type#\");\n    MaybeAppendDecimal(state, 2 + which);\n    MaybeAppend(state, \"}\");\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Closure type.\n  which = -1;\n  if (ParseTwoCharToken(state, \"Ul\") && DisableAppend(state) &&\n      ZeroOrMore(ParseTemplateParamDecl, state) &&\n      OneOrMore(ParseType, state) && RestoreAppend(state, copy.append) &&\n      ParseOneCharToken(state, 'E') && Optional(ParseNumber(state, &which)) &&\n      which <= std::numeric_limits<int>::max() - 2 &&  // Don't overflow.\n      ParseOneCharToken(state, '_')) {\n    MaybeAppend(state, \"{lambda()#\");\n    MaybeAppendDecimal(state, 2 + which);\n    MaybeAppend(state, \"}\");\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <number> ::= [n] <non-negative decimal integer>\n// If \"number_out\" is non-null, then *number_out is set to the value of the\n// parsed number on success.\nstatic bool ParseNumber(State *state, int *number_out) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  bool negative = false;\n  if (ParseOneCharToken(state, 'n')) {\n    negative = true;\n  }\n  const char *p = RemainingInput(state);\n  uint64_t number = 0;\n  for (; *p != '\\0'; ++p) {\n    if (IsDigit(*p)) {\n      number = number * 10 + static_cast<uint64_t>(*p - '0');\n    } else {\n      break;\n    }\n  }\n  // Apply the sign with uint64_t arithmetic so overflows aren't UB.  Gives\n  // \"incorrect\" results for out-of-range inputs, but negative values only\n  // appear for literals, which aren't printed.\n  if (negative) {\n    number = ~number + 1;\n  }\n  if (p != RemainingInput(state)) {  // Conversion succeeded.\n    state->parse_state.mangled_idx +=\n        static_cast<int>(p - RemainingInput(state));\n    UpdateHighWaterMark(state);\n    if (number_out != nullptr) {\n      // Note: possibly truncate \"number\".\n      *number_out = static_cast<int>(number);\n    }\n    return true;\n  }\n  return false;\n}\n\n// Floating-point literals are encoded using a fixed-length lowercase\n// hexadecimal string.\nstatic bool ParseFloatNumber(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  const char *p = RemainingInput(state);\n  for (; *p != '\\0'; ++p) {\n    if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) {\n      break;\n    }\n  }\n  if (p != RemainingInput(state)) {  // Conversion succeeded.\n    state->parse_state.mangled_idx +=\n        static_cast<int>(p - RemainingInput(state));\n    UpdateHighWaterMark(state);\n    return true;\n  }\n  return false;\n}\n\n// The <seq-id> is a sequence number in base 36,\n// using digits and upper case letters\nstatic bool ParseSeqId(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  const char *p = RemainingInput(state);\n  for (; *p != '\\0'; ++p) {\n    if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) {\n      break;\n    }\n  }\n  if (p != RemainingInput(state)) {  // Conversion succeeded.\n    state->parse_state.mangled_idx +=\n        static_cast<int>(p - RemainingInput(state));\n    UpdateHighWaterMark(state);\n    return true;\n  }\n  return false;\n}\n\n// <identifier> ::= <unqualified source code identifier> (of given length)\nstatic bool ParseIdentifier(State *state, size_t length) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (!AtLeastNumCharsRemaining(RemainingInput(state), length)) {\n    return false;\n  }\n  if (IdentifierIsAnonymousNamespace(state, length)) {\n    MaybeAppend(state, \"(anonymous namespace)\");\n  } else {\n    MaybeAppendWithLength(state, RemainingInput(state), length);\n  }\n  state->parse_state.mangled_idx += static_cast<int>(length);\n  UpdateHighWaterMark(state);\n  return true;\n}\n\n// <operator-name> ::= nw, and other two letters cases\n//                 ::= cv <type>  # (cast)\n//                 ::= li <source-name>  # C++11 user-defined literal\n//                 ::= v  <digit> <source-name> # vendor extended operator\nstatic bool ParseOperatorName(State *state, int *arity) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (!AtLeastNumCharsRemaining(RemainingInput(state), 2)) {\n    return false;\n  }\n  // First check with \"cv\" (cast) case.\n  ParseState copy = state->parse_state;\n  if (ParseTwoCharToken(state, \"cv\") && MaybeAppend(state, \"operator \") &&\n      EnterNestedName(state) && ParseConversionOperatorType(state) &&\n      LeaveNestedName(state, copy.nest_level)) {\n    if (arity != nullptr) {\n      *arity = 1;\n    }\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Then user-defined literals.\n  if (ParseTwoCharToken(state, \"li\") && MaybeAppend(state, \"operator\\\"\\\" \") &&\n      ParseSourceName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Then vendor extended operators.\n  if (ParseOneCharToken(state, 'v') && ParseDigit(state, arity) &&\n      ParseSourceName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Other operator names should start with a lower alphabet followed\n  // by a lower/upper alphabet.\n  if (!(IsLower(RemainingInput(state)[0]) &&\n        IsAlpha(RemainingInput(state)[1]))) {\n    return false;\n  }\n  // We may want to perform a binary search if we really need speed.\n  const AbbrevPair *p;\n  for (p = kOperatorList; p->abbrev != nullptr; ++p) {\n    if (RemainingInput(state)[0] == p->abbrev[0] &&\n        RemainingInput(state)[1] == p->abbrev[1]) {\n      if (arity != nullptr) {\n        *arity = p->arity;\n      }\n      MaybeAppend(state, \"operator\");\n      if (IsLower(*p->real_name)) {  // new, delete, etc.\n        MaybeAppend(state, \" \");\n      }\n      MaybeAppend(state, p->real_name);\n      state->parse_state.mangled_idx += 2;\n      UpdateHighWaterMark(state);\n      return true;\n    }\n  }\n  return false;\n}\n\n// <operator-name> ::= cv <type>  # (cast)\n//\n// The name of a conversion operator is the one place where cv-qualifiers, *, &,\n// and other simple type combinators are expected to appear in our stripped-down\n// demangling (elsewhere they appear in function signatures or template\n// arguments, which we omit from the output).  We make reasonable efforts to\n// render simple cases accurately.\nstatic bool ParseConversionOperatorType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  // Scan pointers, const, and other easy mangling prefixes with postfix\n  // demanglings.  Remember the range of input for later rescanning.\n  //\n  // See `ParseType` and the `switch` below for the meaning of each char.\n  const char* begin_simple_prefixes = RemainingInput(state);\n  while (ParseCharClass(state, \"OPRCGrVK\")) {}\n  const char* end_simple_prefixes = RemainingInput(state);\n\n  // Emit the base type first.\n  if (!ParseType(state)) {\n    state->parse_state = copy;\n    return false;\n  }\n\n  // Then rescan the easy type combinators in reverse order to emit their\n  // demanglings in the expected output order.\n  while (begin_simple_prefixes != end_simple_prefixes) {\n    switch (*--end_simple_prefixes) {\n      case 'P':\n        MaybeAppend(state, \"*\");\n        break;\n      case 'R':\n        MaybeAppend(state, \"&\");\n        break;\n      case 'O':\n        MaybeAppend(state, \"&&\");\n        break;\n      case 'C':\n        MaybeAppend(state, \" _Complex\");\n        break;\n      case 'G':\n        MaybeAppend(state, \" _Imaginary\");\n        break;\n      case 'r':\n        MaybeAppend(state, \" restrict\");\n        break;\n      case 'V':\n        MaybeAppend(state, \" volatile\");\n        break;\n      case 'K':\n        MaybeAppend(state, \" const\");\n        break;\n    }\n  }\n  return true;\n}\n\n// <special-name> ::= TV <type>\n//                ::= TT <type>\n//                ::= TI <type>\n//                ::= TS <type>\n//                ::= TW <name>  # thread-local wrapper\n//                ::= TH <name>  # thread-local initialization\n//                ::= Tc <call-offset> <call-offset> <(base) encoding>\n//                ::= GV <(object) name>\n//                ::= GR <(object) name> [<seq-id>] _\n//                ::= T <call-offset> <(base) encoding>\n//                ::= GTt <encoding>  # transaction-safe entry point\n//                ::= TA <template-arg>  # nontype template parameter object\n// G++ extensions:\n//                ::= TC <type> <(offset) number> _ <(base) type>\n//                ::= TF <type>\n//                ::= TJ <type>\n//                ::= GR <name>  # without final _, perhaps an earlier form?\n//                ::= GA <encoding>\n//                ::= Th <call-offset> <(base) encoding>\n//                ::= Tv <call-offset> <(base) encoding>\n//\n// Note: Most of these are special data, not functions that occur in stack\n// traces.  Exceptions are TW and TH, which denote functions supporting the\n// thread_local feature.  For these see:\n//\n// https://maskray.me/blog/2021-02-14-all-about-thread-local-storage\n//\n// For TA see https://github.com/itanium-cxx-abi/cxx-abi/issues/63.\nstatic bool ParseSpecialName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  if (ParseTwoCharToken(state, \"TW\")) {\n    MaybeAppend(state, \"thread-local wrapper routine for \");\n    if (ParseName(state)) return true;\n    state->parse_state = copy;\n    return false;\n  }\n\n  if (ParseTwoCharToken(state, \"TH\")) {\n    MaybeAppend(state, \"thread-local initialization routine for \");\n    if (ParseName(state)) return true;\n    state->parse_state = copy;\n    return false;\n  }\n\n  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, \"VTIS\") &&\n      ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Tc\") && ParseCallOffset(state) &&\n      ParseCallOffset(state) && ParseEncoding(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"GV\") && ParseName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) &&\n      ParseEncoding(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // G++ extensions\n  if (ParseTwoCharToken(state, \"TC\") && ParseType(state) &&\n      ParseNumber(state, nullptr) && ParseOneCharToken(state, '_') &&\n      DisableAppend(state) && ParseType(state)) {\n    RestoreAppend(state, copy.append);\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, \"FJ\") &&\n      ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <special-name> ::= GR <(object) name> [<seq-id>] _  # modern standard\n  //                ::= GR <(object) name>  # also recognized\n  if (ParseTwoCharToken(state, \"GR\")) {\n    MaybeAppend(state, \"reference temporary for \");\n    if (!ParseName(state)) {\n      state->parse_state = copy;\n      return false;\n    }\n    const bool has_seq_id = ParseSeqId(state);\n    const bool has_underscore = ParseOneCharToken(state, '_');\n    if (has_seq_id && !has_underscore) {\n      state->parse_state = copy;\n      return false;\n    }\n    return true;\n  }\n\n  if (ParseTwoCharToken(state, \"GA\") && ParseEncoding(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseThreeCharToken(state, \"GTt\") &&\n      MaybeAppend(state, \"transaction clone for \") && ParseEncoding(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, \"hv\") &&\n      ParseCallOffset(state) && ParseEncoding(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"TA\")) {\n    bool append = state->parse_state.append;\n    DisableAppend(state);\n    if (ParseTemplateArg(state)) {\n      RestoreAppend(state, append);\n      MaybeAppend(state, \"template parameter object\");\n      return true;\n    }\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <call-offset> ::= h <nv-offset> _\n//               ::= v <v-offset> _\nstatic bool ParseCallOffset(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'h') && ParseNVOffset(state) &&\n      ParseOneCharToken(state, '_')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'v') && ParseVOffset(state) &&\n      ParseOneCharToken(state, '_')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <nv-offset> ::= <(offset) number>\nstatic bool ParseNVOffset(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  return ParseNumber(state, nullptr);\n}\n\n// <v-offset>  ::= <(offset) number> _ <(virtual offset) number>\nstatic bool ParseVOffset(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseNumber(state, nullptr) && ParseOneCharToken(state, '_') &&\n      ParseNumber(state, nullptr)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2\n// <base-class-type>\n//                  ::= D0 | D1 | D2\n// # GCC extensions: \"unified\" constructor/destructor.  See\n// #\n// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847\n//                  ::= C4 | D4\nstatic bool ParseCtorDtorName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'C')) {\n    if (ParseCharClass(state, \"1234\")) {\n      const char *const prev_name =\n          state->out + state->parse_state.prev_name_idx;\n      MaybeAppendWithLength(state, prev_name,\n                            state->parse_state.prev_name_length);\n      return true;\n    } else if (ParseOneCharToken(state, 'I') && ParseCharClass(state, \"12\") &&\n               ParseClassEnumType(state)) {\n      return true;\n    }\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'D') && ParseCharClass(state, \"0124\")) {\n    const char *const prev_name = state->out + state->parse_state.prev_name_idx;\n    MaybeAppend(state, \"~\");\n    MaybeAppendWithLength(state, prev_name,\n                          state->parse_state.prev_name_length);\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <decltype> ::= Dt <expression> E  # decltype of an id-expression or class\n//                                   # member access (C++0x)\n//            ::= DT <expression> E  # decltype of an expression (C++0x)\nstatic bool ParseDecltype(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'D') && ParseCharClass(state, \"tT\") &&\n      ParseExpression(state) && ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <type> ::= <CV-qualifiers> <type>\n//        ::= P <type>   # pointer-to\n//        ::= R <type>   # reference-to\n//        ::= O <type>   # rvalue reference-to (C++0x)\n//        ::= C <type>   # complex pair (C 2000)\n//        ::= G <type>   # imaginary (C 2000)\n//        ::= <builtin-type>\n//        ::= <function-type>\n//        ::= <class-enum-type>  # note: just an alias for <name>\n//        ::= <array-type>\n//        ::= <pointer-to-member-type>\n//        ::= <template-template-param> <template-args>\n//        ::= <template-param>\n//        ::= <decltype>\n//        ::= <substitution>\n//        ::= Dp <type>          # pack expansion of (C++0x)\n//        ::= Dv <(elements) number> _ <type>  # GNU vector extension\n//        ::= Dv <(bytes) expression> _ <type>\n//        ::= Dk <type-constraint>  # constrained auto\n//\nstatic bool ParseType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  // We should check CV-qualifers, and PRGC things first.\n  //\n  // CV-qualifiers overlap with some operator names, but an operator name is not\n  // valid as a type.  To avoid an ambiguity that can lead to exponential time\n  // complexity, refuse to backtrack the CV-qualifiers.\n  //\n  // _Z4aoeuIrMvvE\n  //  => _Z 4aoeuI        rM  v     v   E\n  //         aoeu<operator%=, void, void>\n  //  => _Z 4aoeuI r Mv v              E\n  //         aoeu<void void::* restrict>\n  //\n  // By consuming the CV-qualifiers first, the former parse is disabled.\n  if (ParseCVQualifiers(state)) {\n    const bool result = ParseType(state);\n    if (!result) state->parse_state = copy;\n    return result;\n  }\n  state->parse_state = copy;\n\n  // Similarly, these tag characters can overlap with other <name>s resulting in\n  // two different parse prefixes that land on <template-args> in the same\n  // place, such as \"C3r1xI...\".  So, disable the \"ctor-name = C3\" parse by\n  // refusing to backtrack the tag characters.\n  if (ParseCharClass(state, \"OPRCG\")) {\n    const bool result = ParseType(state);\n    if (!result) state->parse_state = copy;\n    return result;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Dp\") && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseBuiltinType(state) || ParseFunctionType(state) ||\n      ParseClassEnumType(state) || ParseArrayType(state) ||\n      ParsePointerToMemberType(state) || ParseDecltype(state) ||\n      // \"std\" on its own isn't a type.\n      ParseSubstitution(state, /*accept_std=*/false)) {\n    return true;\n  }\n\n  if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Less greedy than <template-template-param> <template-args>.\n  if (ParseTemplateParam(state)) {\n    return true;\n  }\n\n  // GNU vector extension Dv <number> _ <type>\n  if (ParseTwoCharToken(state, \"Dv\") && ParseNumber(state, nullptr) &&\n      ParseOneCharToken(state, '_') && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // GNU vector extension Dv <expression> _ <type>\n  if (ParseTwoCharToken(state, \"Dv\") && ParseExpression(state) &&\n      ParseOneCharToken(state, '_') && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Dk\") && ParseTypeConstraint(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // For this notation see CXXNameMangler::mangleType in Clang's source code.\n  // The relevant logic and its comment \"not clear how to mangle this!\" date\n  // from 2011, so it may be with us awhile.\n  return ParseLongToken(state, \"_SUBSTPACK_\");\n}\n\n// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>\n// <CV-qualifiers> ::= [r] [V] [K]\n//\n// We don't allow empty <CV-qualifiers> to avoid infinite loop in\n// ParseType().\nstatic bool ParseCVQualifiers(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  int num_cv_qualifiers = 0;\n  while (ParseExtendedQualifier(state)) ++num_cv_qualifiers;\n  num_cv_qualifiers += ParseOneCharToken(state, 'r');\n  num_cv_qualifiers += ParseOneCharToken(state, 'V');\n  num_cv_qualifiers += ParseOneCharToken(state, 'K');\n  return num_cv_qualifiers > 0;\n}\n\n// <extended-qualifier> ::= U <source-name> [<template-args>]\nstatic bool ParseExtendedQualifier(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  if (!ParseOneCharToken(state, 'U')) return false;\n\n  bool append = state->parse_state.append;\n  DisableAppend(state);\n  if (!ParseSourceName(state)) {\n    state->parse_state = copy;\n    return false;\n  }\n  Optional(ParseTemplateArgs(state));\n  RestoreAppend(state, append);\n  return true;\n}\n\n// <builtin-type> ::= v, etc.  # single-character builtin types\n//                ::= <vendor-extended-type>\n//                ::= Dd, etc.  # two-character builtin types\n//                ::= DB (<number> | <expression>) _  # _BitInt(N)\n//                ::= DU (<number> | <expression>) _  # unsigned _BitInt(N)\n//                ::= DF <number> _  # _FloatN (N bits)\n//                ::= DF <number> x  # _FloatNx\n//                ::= DF16b  # std::bfloat16_t\n//\n// Not supported:\n//                ::= [DS] DA <fixed-point-size>\n//                ::= [DS] DR <fixed-point-size>\n// because real implementations of N1169 fixed-point are scant.\nstatic bool ParseBuiltinType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  // DB (<number> | <expression>) _  # _BitInt(N)\n  // DU (<number> | <expression>) _  # unsigned _BitInt(N)\n  if (ParseTwoCharToken(state, \"DB\") ||\n      (ParseTwoCharToken(state, \"DU\") && MaybeAppend(state, \"unsigned \"))) {\n    bool append = state->parse_state.append;\n    DisableAppend(state);\n    int number = -1;\n    if (!ParseNumber(state, &number) && !ParseExpression(state)) {\n      state->parse_state = copy;\n      return false;\n    }\n    RestoreAppend(state, append);\n\n    if (!ParseOneCharToken(state, '_')) {\n      state->parse_state = copy;\n      return false;\n    }\n\n    MaybeAppend(state, \"_BitInt(\");\n    if (number >= 0) {\n      MaybeAppendDecimal(state, number);\n    } else {\n      MaybeAppend(state, \"?\");  // the best we can do for dependent sizes\n    }\n    MaybeAppend(state, \")\");\n    return true;\n  }\n\n  // DF <number> _  # _FloatN\n  // DF <number> x  # _FloatNx\n  // DF16b  # std::bfloat16_t\n  if (ParseTwoCharToken(state, \"DF\")) {\n    if (ParseThreeCharToken(state, \"16b\")) {\n      MaybeAppend(state, \"std::bfloat16_t\");\n      return true;\n    }\n    int number = 0;\n    if (!ParseNumber(state, &number)) {\n      state->parse_state = copy;\n      return false;\n    }\n    MaybeAppend(state, \"_Float\");\n    MaybeAppendDecimal(state, number);\n    if (ParseOneCharToken(state, 'x')) {\n      MaybeAppend(state, \"x\");\n      return true;\n    }\n    if (ParseOneCharToken(state, '_')) return true;\n    state->parse_state = copy;\n    return false;\n  }\n\n  for (const AbbrevPair *p = kBuiltinTypeList; p->abbrev != nullptr; ++p) {\n    // Guaranteed only 1- or 2-character strings in kBuiltinTypeList.\n    if (p->abbrev[1] == '\\0') {\n      if (ParseOneCharToken(state, p->abbrev[0])) {\n        MaybeAppend(state, p->real_name);\n        return true;  // ::= v, etc.  # single-character builtin types\n      }\n    } else if (p->abbrev[2] == '\\0' && ParseTwoCharToken(state, p->abbrev)) {\n      MaybeAppend(state, p->real_name);\n      return true;  // ::= Dd, etc.  # two-character builtin types\n    }\n  }\n\n  return ParseVendorExtendedType(state);\n}\n\n// <vendor-extended-type> ::= u <source-name> [<template-args>]\nstatic bool ParseVendorExtendedType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'u') && ParseSourceName(state) &&\n      Optional(ParseTemplateArgs(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n//  <exception-spec> ::= Do                # non-throwing\n//                                           exception-specification (e.g.,\n//                                           noexcept, throw())\n//                   ::= DO <expression> E # computed (instantiation-dependent)\n//                                           noexcept\n//                   ::= Dw <type>+ E      # dynamic exception specification\n//                                           with instantiation-dependent types\nstatic bool ParseExceptionSpec(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  if (ParseTwoCharToken(state, \"Do\")) return true;\n\n  ParseState copy = state->parse_state;\n  if (ParseTwoCharToken(state, \"DO\") && ParseExpression(state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n  if (ParseTwoCharToken(state, \"Dw\") && OneOrMore(ParseType, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <function-type> ::=\n//     [exception-spec] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E\n//\n// <ref-qualifier> ::= R | O\nstatic bool ParseFunctionType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  Optional(ParseExceptionSpec(state));\n  Optional(ParseTwoCharToken(state, \"Dx\"));\n  if (!ParseOneCharToken(state, 'F')) {\n    state->parse_state = copy;\n    return false;\n  }\n  Optional(ParseOneCharToken(state, 'Y'));\n  if (!ParseBareFunctionType(state)) {\n    state->parse_state = copy;\n    return false;\n  }\n  Optional(ParseCharClass(state, \"RO\"));\n  if (!ParseOneCharToken(state, 'E')) {\n    state->parse_state = copy;\n    return false;\n  }\n  return true;\n}\n\n// <bare-function-type> ::= <overload-attribute>* <(signature) type>+\n//\n// The <overload-attribute>* prefix is nonstandard; see the comment on\n// ParseOverloadAttribute.\nstatic bool ParseBareFunctionType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  DisableAppend(state);\n  if (ZeroOrMore(ParseOverloadAttribute, state) &&\n      OneOrMore(ParseType, state)) {\n    RestoreAppend(state, copy.append);\n    MaybeAppend(state, \"()\");\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <overload-attribute> ::= Ua <name>\n//\n// The nonstandard <overload-attribute> production is sufficient to accept the\n// current implementation of __attribute__((enable_if(condition, \"message\")))\n// and future attributes of a similar shape.  See\n// https://clang.llvm.org/docs/AttributeReference.html#enable-if and the\n// definition of CXXNameMangler::mangleFunctionEncodingBareType in Clang's\n// source code.\nstatic bool ParseOverloadAttribute(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseTwoCharToken(state, \"Ua\") && ParseName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <class-enum-type> ::= <name>\n//                   ::= Ts <name>  # struct Name or class Name\n//                   ::= Tu <name>  # union Name\n//                   ::= Te <name>  # enum Name\n//\n// See http://shortn/_W3YrltiEd0.\nstatic bool ParseClassEnumType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (Optional(ParseTwoCharToken(state, \"Ts\") ||\n               ParseTwoCharToken(state, \"Tu\") ||\n               ParseTwoCharToken(state, \"Te\")) &&\n      ParseName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <array-type> ::= A <(positive dimension) number> _ <(element) type>\n//              ::= A [<(dimension) expression>] _ <(element) type>\nstatic bool ParseArrayType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'A') && ParseNumber(state, nullptr) &&\n      ParseOneCharToken(state, '_') && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) &&\n      ParseOneCharToken(state, '_') && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <pointer-to-member-type> ::= M <(class) type> <(member) type>\nstatic bool ParsePointerToMemberType(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'M') && ParseType(state) && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <template-param> ::= T_\n//                  ::= T <parameter-2 non-negative number> _\n//                  ::= TL <level-1> __\n//                  ::= TL <level-1> _ <parameter-2 non-negative number> _\nstatic bool ParseTemplateParam(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseTwoCharToken(state, \"T_\")) {\n    MaybeAppend(state, \"?\");  // We don't support template substitutions.\n    return true;              // ::= T_\n  }\n\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'T') && ParseNumber(state, nullptr) &&\n      ParseOneCharToken(state, '_')) {\n    MaybeAppend(state, \"?\");  // We don't support template substitutions.\n    return true;              // ::= T <parameter-2 non-negative number> _\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"TL\") && ParseNumber(state, nullptr)) {\n    if (ParseTwoCharToken(state, \"__\")) {\n      MaybeAppend(state, \"?\");  // We don't support template substitutions.\n      return true;              // ::= TL <level-1> __\n    }\n\n    if (ParseOneCharToken(state, '_') && ParseNumber(state, nullptr) &&\n        ParseOneCharToken(state, '_')) {\n      MaybeAppend(state, \"?\");  // We don't support template substitutions.\n      return true;  // ::= TL <level-1> _ <parameter-2 non-negative number> _\n    }\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <template-param-decl>\n//   ::= Ty                                  # template type parameter\n//   ::= Tk <concept name> [<template-args>] # constrained type parameter\n//   ::= Tn <type>                           # template non-type parameter\n//   ::= Tt <template-param-decl>* E         # template template parameter\n//   ::= Tp <template-param-decl>            # template parameter pack\n//\n// NOTE: <concept name> is just a <name>: http://shortn/_MqJVyr0fc1\n// TODO(b/324066279): Implement optional suffix for `Tt`:\n// [Q <requires-clause expr>]\nstatic bool ParseTemplateParamDecl(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  if (ParseTwoCharToken(state, \"Ty\")) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Tk\") && ParseName(state) &&\n      Optional(ParseTemplateArgs(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Tn\") && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Tt\") &&\n      ZeroOrMore(ParseTemplateParamDecl, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"Tp\") && ParseTemplateParamDecl(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <template-template-param> ::= <template-param>\n//                           ::= <substitution>\nstatic bool ParseTemplateTemplateParam(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  return (ParseTemplateParam(state) ||\n          // \"std\" on its own isn't a template.\n          ParseSubstitution(state, /*accept_std=*/false));\n}\n\n// <template-args> ::= I <template-arg>+ [Q <requires-clause expr>] E\nstatic bool ParseTemplateArgs(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  DisableAppend(state);\n  if (ParseOneCharToken(state, 'I') && OneOrMore(ParseTemplateArg, state) &&\n      Optional(ParseQRequiresClauseExpr(state)) &&\n      ParseOneCharToken(state, 'E')) {\n    RestoreAppend(state, copy.append);\n    MaybeAppend(state, \"<>\");\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <template-arg>  ::= <template-param-decl> <template-arg>\n//                 ::= <type>\n//                 ::= <expr-primary>\n//                 ::= J <template-arg>* E        # argument pack\n//                 ::= X <expression> E\nstatic bool ParseTemplateArg(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'J') && ZeroOrMore(ParseTemplateArg, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // There can be significant overlap between the following leading to\n  // exponential backtracking:\n  //\n  //   <expr-primary> ::= L <type> <expr-cast-value> E\n  //                 e.g. L 2xxIvE 1                 E\n  //   <type>         ==> <local-source-name> <template-args>\n  //                 e.g. L 2xx               IvE\n  //\n  // This means parsing an entire <type> twice, and <type> can contain\n  // <template-arg>, so this can generate exponential backtracking.  There is\n  // only overlap when the remaining input starts with \"L <source-name>\", so\n  // parse all cases that can start this way jointly to share the common prefix.\n  //\n  // We have:\n  //\n  //   <template-arg> ::= <type>\n  //                  ::= <expr-primary>\n  //\n  // First, drop all the productions of <type> that must start with something\n  // other than 'L'.  All that's left is <class-enum-type>; inline it.\n  //\n  //   <type> ::= <nested-name> # starts with 'N'\n  //          ::= <unscoped-name>\n  //          ::= <unscoped-template-name> <template-args>\n  //          ::= <local-name> # starts with 'Z'\n  //\n  // Drop and inline again:\n  //\n  //   <type> ::= <unscoped-name>\n  //          ::= <unscoped-name> <template-args>\n  //          ::= <substitution> <template-args> # starts with 'S'\n  //\n  // Merge the first two, inline <unscoped-name>, drop last:\n  //\n  //   <type> ::= <unqualified-name> [<template-args>]\n  //          ::= St <unqualified-name> [<template-args>] # starts with 'S'\n  //\n  // Drop and inline:\n  //\n  //   <type> ::= <operator-name> [<template-args>] # starts with lowercase\n  //          ::= <ctor-dtor-name> [<template-args>] # starts with 'C' or 'D'\n  //          ::= <source-name> [<template-args>] # starts with digit\n  //          ::= <local-source-name> [<template-args>]\n  //          ::= <unnamed-type-name> [<template-args>] # starts with 'U'\n  //\n  // One more time:\n  //\n  //   <type> ::= L <source-name> [<template-args>]\n  //\n  // Likewise with <expr-primary>:\n  //\n  //   <expr-primary> ::= L <type> <expr-cast-value> E\n  //                  ::= LZ <encoding> E # cannot overlap; drop\n  //                  ::= L <mangled_name> E # cannot overlap; drop\n  //\n  // By similar reasoning as shown above, the only <type>s starting with\n  // <source-name> are \"<source-name> [<template-args>]\".  Inline this.\n  //\n  //   <expr-primary> ::= L <source-name> [<template-args>] <expr-cast-value> E\n  //\n  // Now inline both of these into <template-arg>:\n  //\n  //   <template-arg> ::= L <source-name> [<template-args>]\n  //                  ::= L <source-name> [<template-args>] <expr-cast-value> E\n  //\n  // Merge them and we're done:\n  //   <template-arg>\n  //     ::= L <source-name> [<template-args>] [<expr-cast-value> E]\n  if (ParseLocalSourceName(state) && Optional(ParseTemplateArgs(state))) {\n    copy = state->parse_state;\n    if (ParseExprCastValueAndTrailingE(state)) {\n      return true;\n    }\n    state->parse_state = copy;\n    return true;\n  }\n\n  // Now that the overlapping cases can't reach this code, we can safely call\n  // both of these.\n  if (ParseType(state) || ParseExprPrimary(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTemplateParamDecl(state) && ParseTemplateArg(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <unresolved-type> ::= <template-param> [<template-args>]\n//                   ::= <decltype>\n//                   ::= <substitution>\nstatic inline bool ParseUnresolvedType(State *state) {\n  // No ComplexityGuard because we don't copy the state in this stack frame.\n  return (ParseTemplateParam(state) && Optional(ParseTemplateArgs(state))) ||\n         ParseDecltype(state) || ParseSubstitution(state, /*accept_std=*/false);\n}\n\n// <simple-id> ::= <source-name> [<template-args>]\nstatic inline bool ParseSimpleId(State *state) {\n  // No ComplexityGuard because we don't copy the state in this stack frame.\n\n  // Note: <simple-id> cannot be followed by a parameter pack; see comment in\n  // ParseUnresolvedType.\n  return ParseSourceName(state) && Optional(ParseTemplateArgs(state));\n}\n\n// <base-unresolved-name> ::= <source-name> [<template-args>]\n//                        ::= on <operator-name> [<template-args>]\n//                        ::= dn <destructor-name>\nstatic bool ParseBaseUnresolvedName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  if (ParseSimpleId(state)) {\n    return true;\n  }\n\n  ParseState copy = state->parse_state;\n  if (ParseTwoCharToken(state, \"on\") && ParseOperatorName(state, nullptr) &&\n      Optional(ParseTemplateArgs(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"dn\") &&\n      (ParseUnresolvedType(state) || ParseSimpleId(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <unresolved-name> ::= [gs] <base-unresolved-name>\n//                   ::= sr <unresolved-type> <base-unresolved-name>\n//                   ::= srN <unresolved-type> <unresolved-qualifier-level>+ E\n//                         <base-unresolved-name>\n//                   ::= [gs] sr <unresolved-qualifier-level>+ E\n//                         <base-unresolved-name>\n//                   ::= sr St <simple-id> <simple-id>  # nonstandard\n//\n// The last case is not part of the official grammar but has been observed in\n// real-world examples that the GNU demangler (but not the LLVM demangler) is\n// able to decode; see demangle_test.cc for one such symbol name.  The shape\n// sr St <simple-id> <simple-id> was inferred by closed-box testing of the GNU\n// demangler.\nstatic bool ParseUnresolvedName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  ParseState copy = state->parse_state;\n  if (Optional(ParseTwoCharToken(state, \"gs\")) &&\n      ParseBaseUnresolvedName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"sr\") && ParseUnresolvedType(state) &&\n      ParseBaseUnresolvedName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"sr\") && ParseOneCharToken(state, 'N') &&\n      ParseUnresolvedType(state) &&\n      OneOrMore(ParseUnresolvedQualifierLevel, state) &&\n      ParseOneCharToken(state, 'E') && ParseBaseUnresolvedName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (Optional(ParseTwoCharToken(state, \"gs\")) &&\n      ParseTwoCharToken(state, \"sr\") &&\n      OneOrMore(ParseUnresolvedQualifierLevel, state) &&\n      ParseOneCharToken(state, 'E') && ParseBaseUnresolvedName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"sr\") && ParseTwoCharToken(state, \"St\") &&\n      ParseSimpleId(state) && ParseSimpleId(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <unresolved-qualifier-level> ::= <simple-id>\n//                              ::= <substitution> <template-args>\n//\n// The production <substitution> <template-args> is nonstandard but is observed\n// in practice.  An upstream discussion on the best shape of <unresolved-name>\n// has not converged:\n//\n// https://github.com/itanium-cxx-abi/cxx-abi/issues/38\nstatic bool ParseUnresolvedQualifierLevel(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  if (ParseSimpleId(state)) return true;\n\n  ParseState copy = state->parse_state;\n  if (ParseSubstitution(state, /*accept_std=*/false) &&\n      ParseTemplateArgs(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <union-selector> ::= _ [<number>]\n//\n// https://github.com/itanium-cxx-abi/cxx-abi/issues/47\nstatic bool ParseUnionSelector(State *state) {\n  return ParseOneCharToken(state, '_') && Optional(ParseNumber(state, nullptr));\n}\n\n// <function-param> ::= fp <(top-level) CV-qualifiers> _\n//                  ::= fp <(top-level) CV-qualifiers> <number> _\n//                  ::= fL <number> p <(top-level) CV-qualifiers> _\n//                  ::= fL <number> p <(top-level) CV-qualifiers> <number> _\n//                  ::= fpT  # this\nstatic bool ParseFunctionParam(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  ParseState copy = state->parse_state;\n\n  // Function-param expression (level 0).\n  if (ParseTwoCharToken(state, \"fp\") && Optional(ParseCVQualifiers(state)) &&\n      Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Function-param expression (level 1+).\n  if (ParseTwoCharToken(state, \"fL\") && Optional(ParseNumber(state, nullptr)) &&\n      ParseOneCharToken(state, 'p') && Optional(ParseCVQualifiers(state)) &&\n      Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return ParseThreeCharToken(state, \"fpT\");\n}\n\n// <braced-expression> ::= <expression>\n//                     ::= di <field source-name> <braced-expression>\n//                     ::= dx <index expression> <braced-expression>\n//                     ::= dX <expression> <expression> <braced-expression>\nstatic bool ParseBracedExpression(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  ParseState copy = state->parse_state;\n\n  if (ParseTwoCharToken(state, \"di\") && ParseSourceName(state) &&\n      ParseBracedExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"dx\") && ParseExpression(state) &&\n      ParseBracedExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"dX\") &&\n      ParseExpression(state) && ParseExpression(state) &&\n      ParseBracedExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return ParseExpression(state);\n}\n\n// <expression> ::= <1-ary operator-name> <expression>\n//              ::= <2-ary operator-name> <expression> <expression>\n//              ::= <3-ary operator-name> <expression> <expression> <expression>\n//              ::= pp_ <expression>  # ++e; pp <expression> is e++\n//              ::= mm_ <expression>  # --e; mm <expression> is e--\n//              ::= cl <expression>+ E\n//              ::= cp <simple-id> <expression>* E # Clang-specific.\n//              ::= so <type> <expression> [<number>] <union-selector>* [p] E\n//              ::= cv <type> <expression>      # type (expression)\n//              ::= cv <type> _ <expression>* E # type (expr-list)\n//              ::= tl <type> <braced-expression>* E\n//              ::= il <braced-expression>* E\n//              ::= [gs] nw <expression>* _ <type> E\n//              ::= [gs] nw <expression>* _ <type> <initializer>\n//              ::= [gs] na <expression>* _ <type> E\n//              ::= [gs] na <expression>* _ <type> <initializer>\n//              ::= [gs] dl <expression>\n//              ::= [gs] da <expression>\n//              ::= dc <type> <expression>\n//              ::= sc <type> <expression>\n//              ::= cc <type> <expression>\n//              ::= rc <type> <expression>\n//              ::= ti <type>\n//              ::= te <expression>\n//              ::= st <type>\n//              ::= at <type>\n//              ::= az <expression>\n//              ::= nx <expression>\n//              ::= <template-param>\n//              ::= <function-param>\n//              ::= sZ <template-param>\n//              ::= sZ <function-param>\n//              ::= sP <template-arg>* E\n//              ::= <expr-primary>\n//              ::= dt <expression> <unresolved-name> # expr.name\n//              ::= pt <expression> <unresolved-name> # expr->name\n//              ::= sp <expression>         # argument pack expansion\n//              ::= fl <binary operator-name> <expression>\n//              ::= fr <binary operator-name> <expression>\n//              ::= fL <binary operator-name> <expression> <expression>\n//              ::= fR <binary operator-name> <expression> <expression>\n//              ::= tw <expression>\n//              ::= tr\n//              ::= sr <type> <unqualified-name> <template-args>\n//              ::= sr <type> <unqualified-name>\n//              ::= u <source-name> <template-arg>* E  # vendor extension\n//              ::= rq <requirement>+ E\n//              ::= rQ <bare-function-type> _ <requirement>+ E\nstatic bool ParseExpression(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseTemplateParam(state) || ParseExprPrimary(state)) {\n    return true;\n  }\n\n  ParseState copy = state->parse_state;\n\n  // Object/function call expression.\n  if (ParseTwoCharToken(state, \"cl\") && OneOrMore(ParseExpression, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Preincrement and predecrement.  Postincrement and postdecrement are handled\n  // by the operator-name logic later on.\n  if ((ParseThreeCharToken(state, \"pp_\") ||\n       ParseThreeCharToken(state, \"mm_\")) &&\n      ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Clang-specific \"cp <simple-id> <expression>* E\"\n  //   https://clang.llvm.org/doxygen/ItaniumMangle_8cpp_source.html#l04338\n  if (ParseTwoCharToken(state, \"cp\") && ParseSimpleId(state) &&\n      ZeroOrMore(ParseExpression, state) && ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= so <type> <expression> [<number>] <union-selector>* [p] E\n  //\n  // https://github.com/itanium-cxx-abi/cxx-abi/issues/47\n  if (ParseTwoCharToken(state, \"so\") && ParseType(state) &&\n      ParseExpression(state) && Optional(ParseNumber(state, nullptr)) &&\n      ZeroOrMore(ParseUnionSelector, state) &&\n      Optional(ParseOneCharToken(state, 'p')) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= <function-param>\n  if (ParseFunctionParam(state)) return true;\n  state->parse_state = copy;\n\n  // <expression> ::= tl <type> <braced-expression>* E\n  if (ParseTwoCharToken(state, \"tl\") && ParseType(state) &&\n      ZeroOrMore(ParseBracedExpression, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= il <braced-expression>* E\n  if (ParseTwoCharToken(state, \"il\") &&\n      ZeroOrMore(ParseBracedExpression, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= [gs] nw <expression>* _ <type> E\n  //              ::= [gs] nw <expression>* _ <type> <initializer>\n  //              ::= [gs] na <expression>* _ <type> E\n  //              ::= [gs] na <expression>* _ <type> <initializer>\n  if (Optional(ParseTwoCharToken(state, \"gs\")) &&\n      (ParseTwoCharToken(state, \"nw\") || ParseTwoCharToken(state, \"na\")) &&\n      ZeroOrMore(ParseExpression, state) && ParseOneCharToken(state, '_') &&\n      ParseType(state) &&\n      (ParseOneCharToken(state, 'E') || ParseInitializer(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= [gs] dl <expression>\n  //              ::= [gs] da <expression>\n  if (Optional(ParseTwoCharToken(state, \"gs\")) &&\n      (ParseTwoCharToken(state, \"dl\") || ParseTwoCharToken(state, \"da\")) &&\n      ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // dynamic_cast, static_cast, const_cast, reinterpret_cast.\n  //\n  // <expression> ::= (dc | sc | cc | rc) <type> <expression>\n  if (ParseCharClass(state, \"dscr\") && ParseOneCharToken(state, 'c') &&\n      ParseType(state) && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Parse the conversion expressions jointly to avoid re-parsing the <type> in\n  // their common prefix.  Parsed as:\n  // <expression> ::= cv <type> <conversion-args>\n  // <conversion-args> ::= _ <expression>* E\n  //                   ::= <expression>\n  //\n  // Also don't try ParseOperatorName after seeing \"cv\", since ParseOperatorName\n  // also needs to accept \"cv <type>\" in other contexts.\n  if (ParseTwoCharToken(state, \"cv\")) {\n    if (ParseType(state)) {\n      ParseState copy2 = state->parse_state;\n      if (ParseOneCharToken(state, '_') && ZeroOrMore(ParseExpression, state) &&\n          ParseOneCharToken(state, 'E')) {\n        return true;\n      }\n      state->parse_state = copy2;\n      if (ParseExpression(state)) {\n        return true;\n      }\n    }\n  } else {\n    // Parse unary, binary, and ternary operator expressions jointly, taking\n    // care not to re-parse subexpressions repeatedly. Parse like:\n    //   <expression> ::= <operator-name> <expression>\n    //                    [<one-to-two-expressions>]\n    //   <one-to-two-expressions> ::= <expression> [<expression>]\n    int arity = -1;\n    if (ParseOperatorName(state, &arity) &&\n        arity > 0 &&  // 0 arity => disabled.\n        (arity < 3 || ParseExpression(state)) &&\n        (arity < 2 || ParseExpression(state)) &&\n        (arity < 1 || ParseExpression(state))) {\n      return true;\n    }\n  }\n  state->parse_state = copy;\n\n  // typeid(type)\n  if (ParseTwoCharToken(state, \"ti\") && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // typeid(expression)\n  if (ParseTwoCharToken(state, \"te\") && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // sizeof type\n  if (ParseTwoCharToken(state, \"st\") && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // alignof(type)\n  if (ParseTwoCharToken(state, \"at\") && ParseType(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // alignof(expression), a GNU extension\n  if (ParseTwoCharToken(state, \"az\") && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // noexcept(expression) appearing as an expression in a dependent signature\n  if (ParseTwoCharToken(state, \"nx\") && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // sizeof...(pack)\n  //\n  // <expression> ::= sZ <template-param>\n  //              ::= sZ <function-param>\n  if (ParseTwoCharToken(state, \"sZ\") &&\n      (ParseFunctionParam(state) || ParseTemplateParam(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // sizeof...(pack) captured from an alias template\n  //\n  // <expression> ::= sP <template-arg>* E\n  if (ParseTwoCharToken(state, \"sP\") && ZeroOrMore(ParseTemplateArg, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Unary folds (... op pack) and (pack op ...).\n  //\n  // <expression> ::= fl <binary operator-name> <expression>\n  //              ::= fr <binary operator-name> <expression>\n  if ((ParseTwoCharToken(state, \"fl\") || ParseTwoCharToken(state, \"fr\")) &&\n      ParseOperatorName(state, nullptr) && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Binary folds (init op ... op pack) and (pack op ... op init).\n  //\n  // <expression> ::= fL <binary operator-name> <expression> <expression>\n  //              ::= fR <binary operator-name> <expression> <expression>\n  if ((ParseTwoCharToken(state, \"fL\") || ParseTwoCharToken(state, \"fR\")) &&\n      ParseOperatorName(state, nullptr) && ParseExpression(state) &&\n      ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // tw <expression>: throw e\n  if (ParseTwoCharToken(state, \"tw\") && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // tr: throw (rethrows an exception from the handler that caught it)\n  if (ParseTwoCharToken(state, \"tr\")) return true;\n\n  // Object and pointer member access expressions.\n  //\n  // <expression> ::= (dt | pt) <expression> <unresolved-name>\n  if ((ParseTwoCharToken(state, \"dt\") || ParseTwoCharToken(state, \"pt\")) &&\n      ParseExpression(state) && ParseUnresolvedName(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Pointer-to-member access expressions.  This parses the same as a binary\n  // operator, but it's implemented separately because \"ds\" shouldn't be\n  // accepted in other contexts that parse an operator name.\n  if (ParseTwoCharToken(state, \"ds\") && ParseExpression(state) &&\n      ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Parameter pack expansion\n  if (ParseTwoCharToken(state, \"sp\") && ParseExpression(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Vendor extended expressions\n  if (ParseOneCharToken(state, 'u') && ParseSourceName(state) &&\n      ZeroOrMore(ParseTemplateArg, state) && ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= rq <requirement>+ E\n  //\n  // https://github.com/itanium-cxx-abi/cxx-abi/issues/24\n  if (ParseTwoCharToken(state, \"rq\") && OneOrMore(ParseRequirement, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  // <expression> ::= rQ <bare-function-type> _ <requirement>+ E\n  //\n  // https://github.com/itanium-cxx-abi/cxx-abi/issues/24\n  if (ParseTwoCharToken(state, \"rQ\") && ParseBareFunctionType(state) &&\n      ParseOneCharToken(state, '_') && OneOrMore(ParseRequirement, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return ParseUnresolvedName(state);\n}\n\n// <initializer> ::= pi <expression>* E\n//               ::= il <braced-expression>* E\n//\n// The il ... E form is not in the ABI spec but is seen in practice for\n// braced-init-lists in new-expressions, which are standard syntax from C++11\n// on.\nstatic bool ParseInitializer(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  if (ParseTwoCharToken(state, \"pi\") && ZeroOrMore(ParseExpression, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseTwoCharToken(state, \"il\") &&\n      ZeroOrMore(ParseBracedExpression, state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <expr-primary> ::= L <type> <(value) number> E\n//                ::= L <type> <(value) float> E\n//                ::= L <mangled-name> E\n//                // A bug in g++'s C++ ABI version 2 (-fabi-version=2).\n//                ::= LZ <encoding> E\n//\n// Warning, subtle: the \"bug\" LZ production above is ambiguous with the first\n// production where <type> starts with <local-name>, which can lead to\n// exponential backtracking in two scenarios:\n//\n// - When whatever follows the E in the <local-name> in the first production is\n//   not a name, we backtrack the whole <encoding> and re-parse the whole thing.\n//\n// - When whatever follows the <local-name> in the first production is not a\n//   number and this <expr-primary> may be followed by a name, we backtrack the\n//   <name> and re-parse it.\n//\n// Moreover this ambiguity isn't always resolved -- for example, the following\n// has two different parses:\n//\n//   _ZaaILZ4aoeuE1x1EvE\n//   => operator&&<aoeu, x, E, void>\n//   => operator&&<(aoeu::x)(1), void>\n//\n// To resolve this, we just do what GCC's demangler does, and refuse to parse\n// casts to <local-name> types.\nstatic bool ParseExprPrimary(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  // The \"LZ\" special case: if we see LZ, we commit to accept \"LZ <encoding> E\"\n  // or fail, no backtracking.\n  if (ParseTwoCharToken(state, \"LZ\")) {\n    if (ParseEncoding(state) && ParseOneCharToken(state, 'E')) {\n      return true;\n    }\n\n    state->parse_state = copy;\n    return false;\n  }\n\n  if (ParseOneCharToken(state, 'L')) {\n    // There are two special cases in which a literal may or must contain a type\n    // without a value.  The first is that both LDnE and LDn0E are valid\n    // encodings of nullptr, used in different situations.  Recognize LDnE here,\n    // leaving LDn0E to be recognized by the general logic afterward.\n    if (ParseThreeCharToken(state, \"DnE\")) return true;\n\n    // The second special case is a string literal, currently mangled in C++98\n    // style as LA<length + 1>_KcE.  This is inadequate to support C++11 and\n    // later versions, and the discussion of this problem has not converged.\n    //\n    // https://github.com/itanium-cxx-abi/cxx-abi/issues/64\n    //\n    // For now the bare-type mangling is what's used in practice, so we\n    // recognize this form and only this form if an array type appears here.\n    // Someday we'll probably have to accept a new form of value mangling in\n    // LA...E constructs.  (Note also that C++20 allows a wide range of\n    // class-type objects as template arguments, so someday their values will be\n    // mangled and we'll have to recognize them here too.)\n    if (RemainingInput(state)[0] == 'A' /* an array type follows */) {\n      if (ParseType(state) && ParseOneCharToken(state, 'E')) return true;\n      state->parse_state = copy;\n      return false;\n    }\n\n    // The merged cast production.\n    if (ParseType(state) && ParseExprCastValueAndTrailingE(state)) {\n      return true;\n    }\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'L') && ParseMangledName(state) &&\n      ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <number> or <float>, followed by 'E', as described above ParseExprPrimary.\nstatic bool ParseExprCastValueAndTrailingE(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  // We have to be able to backtrack after accepting a number because we could\n  // have e.g. \"7fffE\", which will accept \"7\" as a number but then fail to find\n  // the 'E'.\n  ParseState copy = state->parse_state;\n  if (ParseNumber(state, nullptr) && ParseOneCharToken(state, 'E')) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseFloatNumber(state)) {\n    // <float> for ordinary floating-point types\n    if (ParseOneCharToken(state, 'E')) return true;\n\n    // <float> _ <float> for complex floating-point types\n    if (ParseOneCharToken(state, '_') && ParseFloatNumber(state) &&\n        ParseOneCharToken(state, 'E')) {\n      return true;\n    }\n  }\n  state->parse_state = copy;\n\n  return false;\n}\n\n// Parses `Q <requires-clause expr>`.\n// If parsing fails, applies backtracking to `state`.\n//\n// This function covers two symbols instead of one for convenience,\n// because in LLVM's Itanium ABI mangling grammar, <requires-clause expr>\n// always appears after Q.\n//\n// Does not emit the parsed `requires` clause to simplify the implementation.\n// In other words, these two functions' mangled names will demangle identically:\n//\n// template <typename T>\n// int foo(T) requires IsIntegral<T>;\n//\n// vs.\n//\n// template <typename T>\n// int foo(T);\nstatic bool ParseQRequiresClauseExpr(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  DisableAppend(state);\n\n  // <requires-clause expr> is just an <expression>: http://shortn/_9E1Ul0rIM8\n  if (ParseOneCharToken(state, 'Q') && ParseExpression(state)) {\n    RestoreAppend(state, copy.append);\n    return true;\n  }\n\n  // also restores append\n  state->parse_state = copy;\n  return false;\n}\n\n// <requirement> ::= X <expression> [N] [R <type-constraint>]\n// <requirement> ::= T <type>\n// <requirement> ::= Q <constraint-expression>\n//\n// <constraint-expression> ::= <expression>\n//\n// https://github.com/itanium-cxx-abi/cxx-abi/issues/24\nstatic bool ParseRequirement(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n\n  ParseState copy = state->parse_state;\n\n  if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&\n      Optional(ParseOneCharToken(state, 'N')) &&\n      // This logic backtracks cleanly if we eat an R but a valid type doesn't\n      // follow it.\n      (!ParseOneCharToken(state, 'R') || ParseTypeConstraint(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'T') && ParseType(state)) return true;\n  state->parse_state = copy;\n\n  if (ParseOneCharToken(state, 'Q') && ParseExpression(state)) return true;\n  state->parse_state = copy;\n\n  return false;\n}\n\n// <type-constraint> ::= <name>\nstatic bool ParseTypeConstraint(State *state) {\n  return ParseName(state);\n}\n\n// <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]\n//              ::= Z <(function) encoding> E s [<discriminator>]\n//              ::= Z <(function) encoding> E d [<(parameter) number>] _ <name>\n//\n// Parsing a common prefix of these two productions together avoids an\n// exponential blowup of backtracking.  Parse like:\n//   <local-name> := Z <encoding> E <local-name-suffix>\n//   <local-name-suffix> ::= s [<discriminator>]\n//                       ::= d [<(parameter) number>] _ <name>\n//                       ::= <name> [<discriminator>]\n\nstatic bool ParseLocalNameSuffix(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  // <local-name-suffix> ::= d [<(parameter) number>] _ <name>\n  if (ParseOneCharToken(state, 'd') &&\n      (IsDigit(RemainingInput(state)[0]) || RemainingInput(state)[0] == '_')) {\n    int number = -1;\n    Optional(ParseNumber(state, &number));\n    if (number < -1 || number > 2147483645) {\n      // Work around overflow cases.  We do not expect these outside of a fuzzer\n      // or other source of adversarial input.  If we do detect overflow here,\n      // we'll print {default arg#1}.\n      number = -1;\n    }\n    number += 2;\n\n    // The ::{default arg#1}:: infix must be rendered before the lambda itself,\n    // so print this before parsing the rest of the <local-name-suffix>.\n    MaybeAppend(state, \"::{default arg#\");\n    MaybeAppendDecimal(state, number);\n    MaybeAppend(state, \"}::\");\n    if (ParseOneCharToken(state, '_') && ParseName(state)) return true;\n\n    // On late parse failure, roll back not only the input but also the output,\n    // whose trailing NUL was overwritten.\n    state->parse_state = copy;\n    if (state->parse_state.append &&\n        state->parse_state.out_cur_idx < state->out_end_idx) {\n      state->out[state->parse_state.out_cur_idx] = '\\0';\n    }\n    return false;\n  }\n  state->parse_state = copy;\n\n  // <local-name-suffix> ::= <name> [<discriminator>]\n  if (MaybeAppend(state, \"::\") && ParseName(state) &&\n      Optional(ParseDiscriminator(state))) {\n    return true;\n  }\n  state->parse_state = copy;\n  if (state->parse_state.append &&\n      state->parse_state.out_cur_idx < state->out_end_idx) {\n    state->out[state->parse_state.out_cur_idx] = '\\0';\n  }\n\n  // <local-name-suffix> ::= s [<discriminator>]\n  return ParseOneCharToken(state, 's') && Optional(ParseDiscriminator(state));\n}\n\nstatic bool ParseLocalName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&\n      ParseOneCharToken(state, 'E') && ParseLocalNameSuffix(state)) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <discriminator> := _ <digit>\n//                 := __ <number (>= 10)> _\nstatic bool ParseDiscriminator(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  ParseState copy = state->parse_state;\n\n  // Both forms start with _ so parse that first.\n  if (!ParseOneCharToken(state, '_')) return false;\n\n  // <digit>\n  if (ParseDigit(state, nullptr)) return true;\n\n  // _ <number> _\n  if (ParseOneCharToken(state, '_') && ParseNumber(state, nullptr) &&\n      ParseOneCharToken(state, '_')) {\n    return true;\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// <substitution> ::= S_\n//                ::= S <seq-id> _\n//                ::= St, etc.\n//\n// \"St\" is special in that it's not valid as a standalone name, and it *is*\n// allowed to precede a name without being wrapped in \"N...E\".  This means that\n// if we accept it on its own, we can accept \"St1a\" and try to parse\n// template-args, then fail and backtrack, accept \"St\" on its own, then \"1a\" as\n// an unqualified name and re-parse the same template-args.  To block this\n// exponential backtracking, we disable it with 'accept_std=false' in\n// problematic contexts.\nstatic bool ParseSubstitution(State *state, bool accept_std) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseTwoCharToken(state, \"S_\")) {\n    MaybeAppend(state, \"?\");  // We don't support substitutions.\n    return true;\n  }\n\n  ParseState copy = state->parse_state;\n  if (ParseOneCharToken(state, 'S') && ParseSeqId(state) &&\n      ParseOneCharToken(state, '_')) {\n    MaybeAppend(state, \"?\");  // We don't support substitutions.\n    return true;\n  }\n  state->parse_state = copy;\n\n  // Expand abbreviations like \"St\" => \"std\".\n  if (ParseOneCharToken(state, 'S')) {\n    const AbbrevPair *p;\n    for (p = kSubstitutionList; p->abbrev != nullptr; ++p) {\n      if (RemainingInput(state)[0] == p->abbrev[1] &&\n          (accept_std || p->abbrev[1] != 't')) {\n        MaybeAppend(state, \"std\");\n        if (p->real_name[0] != '\\0') {\n          MaybeAppend(state, \"::\");\n          MaybeAppend(state, p->real_name);\n        }\n        ++state->parse_state.mangled_idx;\n        UpdateHighWaterMark(state);\n        return true;\n      }\n    }\n  }\n  state->parse_state = copy;\n  return false;\n}\n\n// Parse <mangled-name>, optionally followed by either a function-clone suffix\n// or version suffix.  Returns true only if all of \"mangled_cur\" was consumed.\nstatic bool ParseTopLevelMangledName(State *state) {\n  ComplexityGuard guard(state);\n  if (guard.IsTooComplex()) return false;\n  if (ParseMangledName(state)) {\n    if (RemainingInput(state)[0] != '\\0') {\n      // Drop trailing function clone suffix, if any.\n      if (RemainingInput(state)[0] == '.') {\n        return true;\n      }\n      // Append trailing version suffix if any.\n      // ex. _Z3foo@@GLIBCXX_3.4\n      if (RemainingInput(state)[0] == '@') {\n        MaybeAppend(state, RemainingInput(state));\n        return true;\n      }\n      ReportHighWaterMark(state);\n      return false;  // Unconsumed suffix.\n    }\n    return true;\n  }\n\n  ReportHighWaterMark(state);\n  return false;\n}\n\nstatic bool Overflowed(const State *state) {\n  return state->parse_state.out_cur_idx >= state->out_end_idx;\n}\n\n// The demangler entry point.\nbool Demangle(const char* mangled, char* out, size_t out_size) {\n  if (mangled[0] == '_' && mangled[1] == 'R') {\n    return DemangleRustSymbolEncoding(mangled, out, out_size);\n  }\n\n  State state;\n  InitState(&state, mangled, out, out_size);\n  return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&\n         state.parse_state.out_cur_idx > 0;\n}\n\nstd::string DemangleString(const char* mangled) {\n  std::string out;\n  int status = 0;\n  char* demangled = nullptr;\n#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE\n  demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);\n#endif\n  if (status == 0 && demangled != nullptr) {\n    out.append(demangled);\n    free(demangled);\n  } else {\n    out.append(mangled);\n  }\n  return out;\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/demangle.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_\n#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_\n\n#include <string>\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Demangle `mangled`.  On success, return true and write the\n// demangled symbol name to `out`.  Otherwise, return false.\n// `out` is modified even if demangling is unsuccessful.\n//\n// This function provides an alternative to libstdc++'s abi::__cxa_demangle,\n// which is not async signal safe (it uses malloc internally).  It's intended to\n// be used in async signal handlers to symbolize stack traces.\n//\n// Note that this demangler doesn't support full demangling.  More\n// specifically, it doesn't print types of function parameters and\n// types of template arguments.  It just skips them.  However, it's\n// still very useful to extract basic information such as class,\n// function, constructor, destructor, and operator names.\n//\n// See the implementation note in demangle.cc if you are interested.\n//\n// Example:\n//\n// | Mangled Name  | Demangle    | DemangleString\n// |---------------|-------------|-----------------------\n// | _Z1fv         | f()         | f()\n// | _Z1fi         | f()         | f(int)\n// | _Z3foo3bar    | foo()       | foo(bar)\n// | _Z1fIiEvi     | f<>()       | void f<int>(int)\n// | _ZN1N1fE      | N::f        | N::f\n// | _ZN3Foo3BarEv | Foo::Bar()  | Foo::Bar()\n// | _Zrm1XS_\"     | operator%() | operator%(X, X)\n// | _ZN3FooC1Ev   | Foo::Foo()  | Foo::Foo()\n// | _Z1fSs        | f()         | f(std::basic_string<char,\n// |               |             |   std::char_traits<char>,\n// |               |             |   std::allocator<char> >)\n//\n// See the unit test for more examples.\n//\n// Demangle also recognizes Rust mangled names by delegating the parsing of\n// anything that starts with _R to DemangleRustSymbolEncoding (demangle_rust.h).\n//\n// Note: we might want to write demanglers for ABIs other than Itanium\n// C++ ABI in the future.\nbool Demangle(const char* mangled, char* out, size_t out_size);\n\n// A wrapper around `abi::__cxa_demangle()`.  On success, returns the demangled\n// name.  On failure, returns the input mangled name.\n//\n// This function is not async-signal-safe.\nstd::string DemangleString(const char* mangled);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_\n"
  },
  {
    "path": "absl/debugging/internal/demangle_rust.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/demangle_rust.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/debugging/internal/decode_rust_punycode.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nnamespace {\n\n// Same step limit as the C++ demangler in demangle.cc uses.\nconstexpr int kMaxReturns = 1 << 17;\n\nbool IsDigit(char c) { return '0' <= c && c <= '9'; }\nbool IsLower(char c) { return 'a' <= c && c <= 'z'; }\nbool IsUpper(char c) { return 'A' <= c && c <= 'Z'; }\nbool IsAlpha(char c) { return IsLower(c) || IsUpper(c); }\nbool IsIdentifierChar(char c) { return IsAlpha(c) || IsDigit(c) || c == '_'; }\nbool IsLowerHexDigit(char c) { return IsDigit(c) || ('a' <= c && c <= 'f'); }\n\nconst char* BasicTypeName(char c) {\n  switch (c) {\n    case 'a': return \"i8\";\n    case 'b': return \"bool\";\n    case 'c': return \"char\";\n    case 'd': return \"f64\";\n    case 'e': return \"str\";\n    case 'f': return \"f32\";\n    case 'h': return \"u8\";\n    case 'i': return \"isize\";\n    case 'j': return \"usize\";\n    case 'l': return \"i32\";\n    case 'm': return \"u32\";\n    case 'n': return \"i128\";\n    case 'o': return \"u128\";\n    case 'p': return \"_\";\n    case 's': return \"i16\";\n    case 't': return \"u16\";\n    case 'u': return \"()\";\n    case 'v': return \"...\";\n    case 'x': return \"i64\";\n    case 'y': return \"u64\";\n    case 'z': return \"!\";\n  }\n  return nullptr;\n}\n\n// Parser for Rust symbol mangling v0, whose grammar is defined here:\n//\n// https://doc.rust-lang.org/rustc/symbol-mangling/v0.html#symbol-grammar-summary\nclass RustSymbolParser {\n public:\n  // Prepares to demangle the given encoding, a Rust symbol name starting with\n  // _R, into the output buffer [out, out_end).  The caller is expected to\n  // continue by calling the new object's Parse function.\n  RustSymbolParser(const char* encoding, char* out, char* const out_end)\n      : encoding_(encoding), out_(out), out_end_(out_end) {\n    if (out_ != out_end_) *out_ = '\\0';\n  }\n\n  // Parses the constructor's encoding argument, writing output into the range\n  // [out, out_end).  Returns true on success and false for input whose\n  // structure was not recognized or exceeded implementation limits, such as by\n  // nesting structures too deep.  In either case *this should not be used\n  // again.\n  [[nodiscard]] bool Parse() && {\n    // Recursively parses the grammar production named by callee, then resumes\n    // execution at the next statement.\n    //\n    // Recursive-descent parsing is a beautifully readable translation of a\n    // grammar, but it risks stack overflow if implemented by naive recursion on\n    // the C++ call stack.  So we simulate recursion by goto and switch instead,\n    // keeping a bounded stack of \"return addresses\" in the recursion_stack_\n    // member.\n    //\n    // The callee argument is a statement label.  We goto that label after\n    // saving the \"return address\" on recursion_stack_.  The next continue\n    // statement in the for loop below \"returns\" from this \"call\".\n    //\n    // The caller argument names the return point.  Each value of caller must\n    // appear in only one ABSL_DEMANGLER_RECURSE call and be listed in the\n    // definition of enum ReturnAddress.  The switch implements the control\n    // transfer from the end of a \"called\" subroutine back to the statement\n    // after the \"call\".\n    //\n    // Note that not all the grammar productions have to be packed into the\n    // switch, but only those which appear in a cycle in the grammar.  Anything\n    // acyclic can be written as ordinary functions and function calls, e.g.,\n    // ParseIdentifier.\n#define ABSL_DEMANGLER_RECURSE(callee, caller) \\\n    do { \\\n      if (recursion_depth_ == kStackSize) return false; \\\n      /* The next continue will switch on this saved value ... */ \\\n      recursion_stack_[recursion_depth_++] = caller; \\\n      goto callee; \\\n      /* ... and will land here, resuming the suspended code. */ \\\n      case caller: {} \\\n    } while (0)\n\n    // Parse the encoding, counting completed recursive calls to guard against\n    // excessively complex input and infinite-loop bugs.\n    int iter = 0;\n    goto whole_encoding;\n    for (; iter < kMaxReturns && recursion_depth_ > 0; ++iter) {\n      // This switch resumes the code path most recently suspended by\n      // ABSL_DEMANGLER_RECURSE.\n      switch (recursion_stack_[--recursion_depth_]) {\n        //\n        // symbol-name ->\n        // _R decimal-number? path instantiating-crate? vendor-specific-suffix?\n        whole_encoding:\n          if (!Eat('_') || !Eat('R')) return false;\n          // decimal-number? is always empty today, so proceed to path, which\n          // can't start with a decimal digit.\n          ABSL_DEMANGLER_RECURSE(path, kInstantiatingCrate);\n          if (IsAlpha(Peek())) {\n            ++silence_depth_;  // Print nothing more from here on.\n            ABSL_DEMANGLER_RECURSE(path, kVendorSpecificSuffix);\n          }\n          switch (Take()) {\n            case '.': case '$': case '\\0': return true;\n          }\n          return false;  // unexpected trailing content\n\n        // path -> crate-root | inherent-impl | trait-impl | trait-definition |\n        //         nested-path | generic-args | backref\n        //\n        // Note that ABSL_DEMANGLER_RECURSE does not work inside a nested switch\n        // (which would hide the generated case label).  Thus we jump out of the\n        // inner switch with gotos before performing any fake recursion.\n        path:\n          switch (Take()) {\n            case 'C': goto crate_root;\n            case 'M': goto inherent_impl;\n            case 'X': goto trait_impl;\n            case 'Y': goto trait_definition;\n            case 'N': goto nested_path;\n            case 'I': goto generic_args;\n            case 'B': goto path_backref;\n            default: return false;\n          }\n\n        // crate-root -> C identifier (C consumed above)\n        crate_root:\n          if (!ParseIdentifier()) return false;\n          continue;\n\n        // inherent-impl -> M impl-path type (M already consumed)\n        inherent_impl:\n          if (!Emit(\"<\")) return false;\n          ABSL_DEMANGLER_RECURSE(impl_path, kInherentImplType);\n          ABSL_DEMANGLER_RECURSE(type, kInherentImplEnding);\n          if (!Emit(\">\")) return false;\n          continue;\n\n        // trait-impl -> X impl-path type path (X already consumed)\n        trait_impl:\n          if (!Emit(\"<\")) return false;\n          ABSL_DEMANGLER_RECURSE(impl_path, kTraitImplType);\n          ABSL_DEMANGLER_RECURSE(type, kTraitImplInfix);\n          if (!Emit(\" as \")) return false;\n          ABSL_DEMANGLER_RECURSE(path, kTraitImplEnding);\n          if (!Emit(\">\")) return false;\n          continue;\n\n        // impl-path -> disambiguator? path (but never print it!)\n        impl_path:\n          ++silence_depth_;\n          {\n            int ignored_disambiguator;\n            if (!ParseDisambiguator(ignored_disambiguator)) return false;\n          }\n          ABSL_DEMANGLER_RECURSE(path, kImplPathEnding);\n          --silence_depth_;\n          continue;\n\n        // trait-definition -> Y type path (Y already consumed)\n        trait_definition:\n          if (!Emit(\"<\")) return false;\n          ABSL_DEMANGLER_RECURSE(type, kTraitDefinitionInfix);\n          if (!Emit(\" as \")) return false;\n          ABSL_DEMANGLER_RECURSE(path, kTraitDefinitionEnding);\n          if (!Emit(\">\")) return false;\n          continue;\n\n        // nested-path -> N namespace path identifier (N already consumed)\n        // namespace -> lower | upper\n        nested_path:\n          // Uppercase namespaces must be saved on a stack so we can print\n          // ::{closure#0} or ::{shim:vtable#0} or ::{X:name#0} as needed.\n          if (IsUpper(Peek())) {\n            if (!PushNamespace(Take())) return false;\n            ABSL_DEMANGLER_RECURSE(path, kIdentifierInUppercaseNamespace);\n            if (!Emit(\"::\")) return false;\n            if (!ParseIdentifier(PopNamespace())) return false;\n            continue;\n          }\n\n          // Lowercase namespaces, however, are never represented in the output;\n          // they all emit just ::name.\n          if (IsLower(Take())) {\n            ABSL_DEMANGLER_RECURSE(path, kIdentifierInLowercaseNamespace);\n            if (!Emit(\"::\")) return false;\n            if (!ParseIdentifier()) return false;\n            continue;\n          }\n\n          // Neither upper or lower\n          return false;\n\n        // type -> basic-type | array-type | slice-type | tuple-type |\n        //         ref-type | mut-ref-type | const-ptr-type | mut-ptr-type |\n        //         fn-type | dyn-trait-type | path | backref\n        //\n        // We use ifs instead of switch (Take()) because the default case jumps\n        // to path, which will need to see the first character not yet Taken\n        // from the input.  Because we do not use a nested switch here,\n        // ABSL_DEMANGLER_RECURSE works fine in the 'S' case.\n        type:\n          if (IsLower(Peek())) {\n            const char* type_name = BasicTypeName(Take());\n            if (type_name == nullptr || !Emit(type_name)) return false;\n            continue;\n          }\n          if (Eat('A')) {\n            // array-type = A type const\n            if (!Emit(\"[\")) return false;\n            ABSL_DEMANGLER_RECURSE(type, kArraySize);\n            if (!Emit(\"; \")) return false;\n            ABSL_DEMANGLER_RECURSE(constant, kFinishArray);\n            if (!Emit(\"]\")) return false;\n            continue;\n          }\n          if (Eat('S')) {\n            if (!Emit(\"[\")) return false;\n            ABSL_DEMANGLER_RECURSE(type, kSliceEnding);\n            if (!Emit(\"]\")) return false;\n            continue;\n          }\n          if (Eat('T')) goto tuple_type;\n          if (Eat('R')) {\n            if (!Emit(\"&\")) return false;\n            if (!ParseOptionalLifetime()) return false;\n            goto type;\n          }\n          if (Eat('Q')) {\n            if (!Emit(\"&mut \")) return false;\n            if (!ParseOptionalLifetime()) return false;\n            goto type;\n          }\n          if (Eat('P')) {\n            if (!Emit(\"*const \")) return false;\n            goto type;\n          }\n          if (Eat('O')) {\n            if (!Emit(\"*mut \")) return false;\n            goto type;\n          }\n          if (Eat('F')) goto fn_type;\n          if (Eat('D')) goto dyn_trait_type;\n          if (Eat('B')) goto type_backref;\n          goto path;\n\n        // tuple-type -> T type* E (T already consumed)\n        tuple_type:\n          if (!Emit(\"(\")) return false;\n\n          // The toolchain should call the unit type u instead of TE, but the\n          // grammar and other demanglers also recognize TE, so we do too.\n          if (Eat('E')) {\n            if (!Emit(\")\")) return false;\n            continue;\n          }\n\n          // A tuple with one element is rendered (type,) instead of (type).\n          ABSL_DEMANGLER_RECURSE(type, kAfterFirstTupleElement);\n          if (Eat('E')) {\n            if (!Emit(\",)\")) return false;\n            continue;\n          }\n\n          // A tuple with two elements is of course (x, y).\n          if (!Emit(\", \")) return false;\n          ABSL_DEMANGLER_RECURSE(type, kAfterSecondTupleElement);\n          if (Eat('E')) {\n            if (!Emit(\")\")) return false;\n            continue;\n          }\n\n          // And (x, y, z) for three elements.\n          if (!Emit(\", \")) return false;\n          ABSL_DEMANGLER_RECURSE(type, kAfterThirdTupleElement);\n          if (Eat('E')) {\n            if (!Emit(\")\")) return false;\n            continue;\n          }\n\n          // For longer tuples we write (x, y, z, ...), printing none of the\n          // content of the fourth and later types.  Thus we avoid exhausting\n          // output buffers and human readers' patience when some library has a\n          // long tuple as an implementation detail, without having to\n          // completely obfuscate all tuples.\n          if (!Emit(\", ...)\")) return false;\n          ++silence_depth_;\n          while (!Eat('E')) {\n            ABSL_DEMANGLER_RECURSE(type, kAfterSubsequentTupleElement);\n          }\n          --silence_depth_;\n          continue;\n\n        // fn-type -> F fn-sig (F already consumed)\n        // fn-sig -> binder? U? (K abi)? type* E type\n        // abi -> C | undisambiguated-identifier\n        //\n        // We follow the C++ demangler in suppressing details of function\n        // signatures.  Every function type is rendered \"fn...\".\n        fn_type:\n          if (!Emit(\"fn...\")) return false;\n          ++silence_depth_;\n          if (!ParseOptionalBinder()) return false;\n          (void)Eat('U');\n          if (Eat('K')) {\n            if (!Eat('C') && !ParseUndisambiguatedIdentifier()) return false;\n          }\n          while (!Eat('E')) {\n            ABSL_DEMANGLER_RECURSE(type, kContinueParameterList);\n          }\n          ABSL_DEMANGLER_RECURSE(type, kFinishFn);\n          --silence_depth_;\n          continue;\n\n        // dyn-trait-type -> D dyn-bounds lifetime (D already consumed)\n        // dyn-bounds -> binder? dyn-trait* E\n        //\n        // The grammar strangely allows an empty trait list, even though the\n        // compiler should never output one.  We follow existing demanglers in\n        // rendering DEL_ as \"dyn \".\n        //\n        // Because auto traits lengthen a type name considerably without\n        // providing much value to a search for related source code, it would be\n        // desirable to abbreviate\n        //     dyn main::Trait + std::marker::Copy + std::marker::Send\n        // to\n        //     dyn main::Trait + ...,\n        // eliding the auto traits.  But it is difficult to do so correctly, in\n        // part because there is no guarantee that the mangling will list the\n        // main trait first.  So we just print all the traits in their order of\n        // appearance in the mangled name.\n        dyn_trait_type:\n          if (!Emit(\"dyn \")) return false;\n          if (!ParseOptionalBinder()) return false;\n          if (!Eat('E')) {\n            ABSL_DEMANGLER_RECURSE(dyn_trait, kBeginAutoTraits);\n            while (!Eat('E')) {\n              if (!Emit(\" + \")) return false;\n              ABSL_DEMANGLER_RECURSE(dyn_trait, kContinueAutoTraits);\n            }\n          }\n          if (!ParseRequiredLifetime()) return false;\n          continue;\n\n        // dyn-trait -> path dyn-trait-assoc-binding*\n        // dyn-trait-assoc-binding -> p undisambiguated-identifier type\n        //\n        // We render nonempty binding lists as <>, omitting their contents as\n        // for generic-args.\n        dyn_trait:\n          ABSL_DEMANGLER_RECURSE(path, kContinueDynTrait);\n          if (Peek() == 'p') {\n            if (!Emit(\"<>\")) return false;\n            ++silence_depth_;\n            while (Eat('p')) {\n              if (!ParseUndisambiguatedIdentifier()) return false;\n              ABSL_DEMANGLER_RECURSE(type, kContinueAssocBinding);\n            }\n            --silence_depth_;\n          }\n          continue;\n\n        // const -> type const-data | p | backref\n        //\n        // const is a C++ keyword, so we use the label `constant` instead.\n        constant:\n          if (Eat('B')) goto const_backref;\n          if (Eat('p')) {\n            if (!Emit(\"_\")) return false;\n            continue;\n          }\n\n          // Scan the type without printing it.\n          //\n          // The Rust language restricts the type of a const generic argument\n          // much more than the mangling grammar does.  We do not enforce this.\n          //\n          // We also do not bother printing false, true, 'A', and '\\u{abcd}' for\n          // the types bool and char.  Because we do not print generic-args\n          // contents, we expect to print constants only in array sizes, and\n          // those should not be bool or char.\n          ++silence_depth_;\n          ABSL_DEMANGLER_RECURSE(type, kConstData);\n          --silence_depth_;\n\n          // const-data -> n? hex-digit* _\n          //\n          // Although the grammar doesn't say this, existing demanglers expect\n          // that zero is 0, not an empty digit sequence, and no nonzero value\n          // may have leading zero digits.  Also n0_ is accepted and printed as\n          // -0, though a toolchain will probably never write that encoding.\n          if (Eat('n') && !EmitChar('-')) return false;\n          if (!Emit(\"0x\")) return false;\n          if (Eat('0')) {\n            if (!EmitChar('0')) return false;\n            if (!Eat('_')) return false;\n            continue;\n          }\n          while (IsLowerHexDigit(Peek())) {\n            if (!EmitChar(Take())) return false;\n          }\n          if (!Eat('_')) return false;\n          continue;\n\n        // generic-args -> I path generic-arg* E (I already consumed)\n        //\n        // We follow the C++ demangler in omitting all the arguments from the\n        // output, printing only the list opening and closing tokens.\n        generic_args:\n          ABSL_DEMANGLER_RECURSE(path, kBeginGenericArgList);\n          if (!Emit(\"::<>\")) return false;\n          ++silence_depth_;\n          while (!Eat('E')) {\n            ABSL_DEMANGLER_RECURSE(generic_arg, kContinueGenericArgList);\n          }\n          --silence_depth_;\n          continue;\n\n        // generic-arg -> lifetime | type | K const\n        generic_arg:\n          if (Peek() == 'L') {\n            if (!ParseOptionalLifetime()) return false;\n            continue;\n          }\n          if (Eat('K')) goto constant;\n          goto type;\n\n        // backref -> B base-62-number (B already consumed)\n        //\n        // The BeginBackref call parses and range-checks the base-62-number.  We\n        // always do that much.\n        //\n        // The recursive call parses and prints what the backref points at.  We\n        // save CPU and stack by skipping this work if the output would be\n        // suppressed anyway.\n        path_backref:\n          if (!BeginBackref()) return false;\n          if (silence_depth_ == 0) {\n            ABSL_DEMANGLER_RECURSE(path, kPathBackrefEnding);\n          }\n          EndBackref();\n          continue;\n\n        // This represents the same backref production as in path_backref but\n        // parses the target as a type instead of a path.\n        type_backref:\n          if (!BeginBackref()) return false;\n          if (silence_depth_ == 0) {\n            ABSL_DEMANGLER_RECURSE(type, kTypeBackrefEnding);\n          }\n          EndBackref();\n          continue;\n\n        const_backref:\n          if (!BeginBackref()) return false;\n          if (silence_depth_ == 0) {\n            ABSL_DEMANGLER_RECURSE(constant, kConstantBackrefEnding);\n          }\n          EndBackref();\n          continue;\n      }\n    }\n\n    return false;  // hit iteration limit or a bug in our stack handling\n  }\n\n private:\n  // Enumerates resumption points for ABSL_DEMANGLER_RECURSE calls.\n  enum ReturnAddress : uint8_t {\n    kInstantiatingCrate,\n    kVendorSpecificSuffix,\n    kIdentifierInUppercaseNamespace,\n    kIdentifierInLowercaseNamespace,\n    kInherentImplType,\n    kInherentImplEnding,\n    kTraitImplType,\n    kTraitImplInfix,\n    kTraitImplEnding,\n    kImplPathEnding,\n    kTraitDefinitionInfix,\n    kTraitDefinitionEnding,\n    kArraySize,\n    kFinishArray,\n    kSliceEnding,\n    kAfterFirstTupleElement,\n    kAfterSecondTupleElement,\n    kAfterThirdTupleElement,\n    kAfterSubsequentTupleElement,\n    kContinueParameterList,\n    kFinishFn,\n    kBeginAutoTraits,\n    kContinueAutoTraits,\n    kContinueDynTrait,\n    kContinueAssocBinding,\n    kConstData,\n    kBeginGenericArgList,\n    kContinueGenericArgList,\n    kPathBackrefEnding,\n    kTypeBackrefEnding,\n    kConstantBackrefEnding,\n  };\n\n  // Element counts for the stack arrays.  Larger stack sizes accommodate more\n  // deeply nested names at the cost of a larger footprint on the C++ call\n  // stack.\n  enum {\n    // Maximum recursive calls outstanding at one time.\n    kStackSize = 256,\n\n    // Maximum N<uppercase> nested-paths open at once.  We do not expect\n    // closures inside closures inside closures as much as functions inside\n    // modules inside other modules, so we can use a smaller array here.\n    kNamespaceStackSize = 64,\n\n    // Maximum number of nested backrefs.  We can keep this stack pretty small\n    // because we do not follow backrefs inside generic-args or other contexts\n    // that suppress printing, so deep stacking is unlikely in practice.\n    kPositionStackSize = 16,\n  };\n\n  // Returns the next input character without consuming it.\n  char Peek() const { return encoding_[pos_]; }\n\n  // Consumes and returns the next input character.\n  char Take() { return encoding_[pos_++]; }\n\n  // If the next input character is the given character, consumes it and returns\n  // true; otherwise returns false without consuming a character.\n  [[nodiscard]] bool Eat(char want) {\n    if (encoding_[pos_] != want) return false;\n    ++pos_;\n    return true;\n  }\n\n  // Provided there is enough remaining output space, appends c to the output,\n  // writing a fresh NUL terminator afterward, and returns true.  Returns false\n  // if the output buffer had less than two bytes free.\n  [[nodiscard]] bool EmitChar(char c) {\n    if (silence_depth_ > 0) return true;\n    if (out_end_ - out_ < 2) return false;\n    *out_++ = c;\n    *out_ = '\\0';\n    return true;\n  }\n\n  // Provided there is enough remaining output space, appends the C string token\n  // to the output, followed by a NUL character, and returns true.  Returns\n  // false if not everything fit into the output buffer.\n  [[nodiscard]] bool Emit(const char* token) {\n    if (silence_depth_ > 0) return true;\n    const size_t token_length = std::strlen(token);\n    const size_t bytes_to_copy = token_length + 1;  // token and final NUL\n    if (static_cast<size_t>(out_end_ - out_) < bytes_to_copy) return false;\n    std::memcpy(out_, token, bytes_to_copy);\n    out_ += token_length;\n    return true;\n  }\n\n  // Provided there is enough remaining output space, appends the decimal form\n  // of disambiguator (if it's nonnegative) or \"?\" (if it's negative) to the\n  // output, followed by a NUL character, and returns true.  Returns false if\n  // not everything fit into the output buffer.\n  [[nodiscard]] bool EmitDisambiguator(int disambiguator) {\n    if (disambiguator < 0) return EmitChar('?');  // parsed but too large\n    if (disambiguator == 0) return EmitChar('0');\n    // Convert disambiguator to decimal text.  Three digits per byte is enough\n    // because 999 > 256.  The bound will remain correct even if future\n    // maintenance changes the type of the disambiguator variable.\n    char digits[3 * sizeof(disambiguator)] = {};\n    size_t leading_digit_index = sizeof(digits) - 1;\n    for (; disambiguator > 0; disambiguator /= 10) {\n      digits[--leading_digit_index] =\n          static_cast<char>('0' + disambiguator % 10);\n    }\n    return Emit(digits + leading_digit_index);\n  }\n\n  // Consumes an optional disambiguator (s123_) from the input.\n  //\n  // On success returns true and fills value with the encoded value if it was\n  // not too big, otherwise with -1.  If the optional disambiguator was omitted,\n  // value is 0.  On parse failure returns false and sets value to -1.\n  [[nodiscard]] bool ParseDisambiguator(int& value) {\n    value = -1;\n\n    // disambiguator = s base-62-number\n    //\n    // Disambiguators are optional.  An omitted disambiguator is zero.\n    if (!Eat('s')) {\n      value = 0;\n      return true;\n    }\n    int base_62_value = 0;\n    if (!ParseBase62Number(base_62_value)) return false;\n    value = base_62_value < 0 ? -1 : base_62_value + 1;\n    return true;\n  }\n\n  // Consumes a base-62 number like _ or 123_ from the input.\n  //\n  // On success returns true and fills value with the encoded value if it was\n  // not too big, otherwise with -1.  On parse failure returns false and sets\n  // value to -1.\n  [[nodiscard]] bool ParseBase62Number(int& value) {\n    value = -1;\n\n    // base-62-number = (digit | lower | upper)* _\n    //\n    // An empty base-62 digit sequence means 0.\n    if (Eat('_')) {\n      value = 0;\n      return true;\n    }\n\n    // A nonempty digit sequence denotes its base-62 value plus 1.\n    int encoded_number = 0;\n    bool overflowed = false;\n    while (IsAlpha(Peek()) || IsDigit(Peek())) {\n      const char c = Take();\n      if (encoded_number >= std::numeric_limits<int>::max()/62) {\n        // If we are close to overflowing an int, keep parsing but stop updating\n        // encoded_number and remember to return -1 at the end.  The point is to\n        // avoid undefined behavior while parsing crate-root disambiguators,\n        // which are large in practice but not shown in demangling, while\n        // successfully computing closure and shim disambiguators, which are\n        // typically small and are printed out.\n        overflowed = true;\n      } else {\n        int digit;\n        if (IsDigit(c)) {\n          digit = c - '0';\n        } else if (IsLower(c)) {\n          digit = c - 'a' + 10;\n        } else {\n          digit = c - 'A' + 36;\n        }\n        encoded_number = 62 * encoded_number + digit;\n      }\n    }\n\n    if (!Eat('_')) return false;\n    if (!overflowed) value = encoded_number + 1;\n    return true;\n  }\n\n  // Consumes an identifier from the input, returning true on success.\n  //\n  // A nonzero uppercase_namespace specifies the character after the N in a\n  // nested-identifier, e.g., 'C' for a closure, allowing ParseIdentifier to\n  // write out the name with the conventional decoration for that namespace.\n  [[nodiscard]] bool ParseIdentifier(char uppercase_namespace = '\\0') {\n    // identifier -> disambiguator? undisambiguated-identifier\n    int disambiguator = 0;\n    if (!ParseDisambiguator(disambiguator)) return false;\n\n    return ParseUndisambiguatedIdentifier(uppercase_namespace, disambiguator);\n  }\n\n  // Consumes from the input an identifier with no preceding disambiguator,\n  // returning true on success.\n  //\n  // When ParseIdentifier calls this, it passes the N<namespace> character and\n  // disambiguator value so that \"{closure#42}\" and similar forms can be\n  // rendered correctly.\n  //\n  // At other appearances of undisambiguated-identifier in the grammar, this\n  // treatment is not applicable, and the call site omits both arguments.\n  [[nodiscard]] bool ParseUndisambiguatedIdentifier(\n      char uppercase_namespace = '\\0', int disambiguator = 0) {\n    // undisambiguated-identifier -> u? decimal-number _? bytes\n    const bool is_punycoded = Eat('u');\n    if (!IsDigit(Peek())) return false;\n    int num_bytes = 0;\n    if (!ParseDecimalNumber(num_bytes)) return false;\n    (void)Eat('_');  // optional separator, needed if a digit follows\n    if (is_punycoded) {\n      DecodeRustPunycodeOptions options;\n      options.punycode_begin = &encoding_[pos_];\n      options.punycode_end = &encoding_[pos_] + num_bytes;\n      options.out_begin = out_;\n      options.out_end = out_end_;\n      out_ = DecodeRustPunycode(options);\n      if (out_ == nullptr) return false;\n      pos_ += static_cast<size_t>(num_bytes);\n    }\n\n    // Emit the beginnings of braced forms like {shim:vtable#0}.\n    if (uppercase_namespace != '\\0') {\n      switch (uppercase_namespace) {\n        case 'C':\n          if (!Emit(\"{closure\")) return false;\n          break;\n        case 'S':\n          if (!Emit(\"{shim\")) return false;\n          break;\n        default:\n          if (!EmitChar('{') || !EmitChar(uppercase_namespace)) return false;\n          break;\n      }\n      if (num_bytes > 0 && !Emit(\":\")) return false;\n    }\n\n    // Emit the name itself.\n    if (!is_punycoded) {\n      for (int i = 0; i < num_bytes; ++i) {\n        const char c = Take();\n        if (!IsIdentifierChar(c) &&\n            // The spec gives toolchains the choice of Punycode or raw UTF-8 for\n            // identifiers containing code points above 0x7f, so accept bytes\n            // with the high bit set.\n            (c & 0x80) == 0) {\n          return false;\n        }\n        if (!EmitChar(c)) return false;\n      }\n    }\n\n    // Emit the endings of braced forms, e.g., \"#42}\".\n    if (uppercase_namespace != '\\0') {\n      if (!EmitChar('#')) return false;\n      if (!EmitDisambiguator(disambiguator)) return false;\n      if (!EmitChar('}')) return false;\n    }\n\n    return true;\n  }\n\n  // Consumes a decimal number like 0 or 123 from the input.  On success returns\n  // true and fills value with the encoded value.  If the encoded value is too\n  // large or otherwise unparsable, returns false and sets value to -1.\n  [[nodiscard]] bool ParseDecimalNumber(int& value) {\n    value = -1;\n    if (!IsDigit(Peek())) return false;\n    int encoded_number = Take() - '0';\n    if (encoded_number == 0) {\n      // Decimal numbers are never encoded with extra leading zeroes.\n      value = 0;\n      return true;\n    }\n    while (IsDigit(Peek()) &&\n           // avoid overflow\n           encoded_number < std::numeric_limits<int>::max()/10) {\n      encoded_number = 10 * encoded_number + (Take() - '0');\n    }\n    if (IsDigit(Peek())) return false;  // too big\n    value = encoded_number;\n    return true;\n  }\n\n  // Consumes a binder of higher-ranked lifetimes if one is present.  On success\n  // returns true and discards the encoded lifetime count.  On parse failure\n  // returns false.\n  [[nodiscard]] bool ParseOptionalBinder() {\n    // binder -> G base-62-number\n    if (!Eat('G')) return true;\n    int ignored_binding_count;\n    return ParseBase62Number(ignored_binding_count);\n  }\n\n  // Consumes a lifetime if one is present.\n  //\n  // On success returns true and discards the lifetime index.  We do not print\n  // or even range-check lifetimes because they are a finer detail than other\n  // things we omit from output, such as the entire contents of generic-args.\n  //\n  // On parse failure returns false.\n  [[nodiscard]] bool ParseOptionalLifetime() {\n    // lifetime -> L base-62-number\n    if (!Eat('L')) return true;\n    int ignored_de_bruijn_index;\n    return ParseBase62Number(ignored_de_bruijn_index);\n  }\n\n  // Consumes a lifetime just like ParseOptionalLifetime, but returns false if\n  // there is no lifetime here.\n  [[nodiscard]] bool ParseRequiredLifetime() {\n    if (Peek() != 'L') return false;\n    return ParseOptionalLifetime();\n  }\n\n  // Pushes ns onto the namespace stack and returns true if the stack is not\n  // full, else returns false.\n  [[nodiscard]] bool PushNamespace(char ns) {\n    if (namespace_depth_ == kNamespaceStackSize) return false;\n    namespace_stack_[namespace_depth_++] = ns;\n    return true;\n  }\n\n  // Pops the last pushed namespace.  Requires that the namespace stack is not\n  // empty (namespace_depth_ > 0).\n  char PopNamespace() { return namespace_stack_[--namespace_depth_]; }\n\n  // Pushes position onto the position stack and returns true if the stack is\n  // not full, else returns false.\n  [[nodiscard]] bool PushPosition(int position) {\n    if (position_depth_ == kPositionStackSize) return false;\n    position_stack_[position_depth_++] = position;\n    return true;\n  }\n\n  // Pops the last pushed input position.  Requires that the position stack is\n  // not empty (position_depth_ > 0).\n  int PopPosition() { return position_stack_[--position_depth_]; }\n\n  // Consumes a base-62-number denoting a backref target, pushes the current\n  // input position on the data stack, and sets the input position to the\n  // beginning of the backref target.  Returns true on success.  Returns false\n  // if parsing failed, the stack is exhausted, or the backref target position\n  // is out of range.\n  [[nodiscard]] bool BeginBackref() {\n    // backref = B base-62-number (B already consumed)\n    //\n    // Reject backrefs that don't parse, overflow int, or don't point backward.\n    // If the offset looks fine, adjust it to account for the _R prefix.\n    int offset = 0;\n    const int offset_of_this_backref =\n        pos_ - 2 /* _R */ - 1 /* B already consumed */;\n    if (!ParseBase62Number(offset) || offset < 0 ||\n        offset >= offset_of_this_backref) {\n      return false;\n    }\n    offset += 2;\n\n    // Save the old position to restore later.\n    if (!PushPosition(pos_)) return false;\n\n    // Move the input position to the backref target.\n    //\n    // Note that we do not check whether the new position points to the\n    // beginning of a construct matching the context in which the backref\n    // appeared.  We just jump to it and see whether nested parsing succeeds.\n    // We therefore accept various wrong manglings, e.g., a type backref\n    // pointing to an 'l' character inside an identifier, which happens to mean\n    // i32 when parsed as a type mangling.  This saves the complexity and RAM\n    // footprint of remembering which offsets began which kinds of\n    // substructures.  Existing demanglers take similar shortcuts.\n    pos_ = offset;\n    return true;\n  }\n\n  // Cleans up after a backref production by restoring the previous input\n  // position from the data stack.\n  void EndBackref() { pos_ = PopPosition(); }\n\n  // The leftmost recursion_depth_ elements of recursion_stack_ contain the\n  // ReturnAddresses pushed by ABSL_DEMANGLER_RECURSE calls not yet completed.\n  ReturnAddress recursion_stack_[kStackSize] = {};\n  int recursion_depth_ = 0;\n\n  // The leftmost namespace_depth_ elements of namespace_stack_ contain the\n  // uppercase namespace identifiers for open nested-paths, e.g., 'C' for a\n  // closure.\n  char namespace_stack_[kNamespaceStackSize] = {};\n  int namespace_depth_ = 0;\n\n  // The leftmost position_depth_ elements of position_stack_ contain the input\n  // positions to return to after fully printing the targets of backrefs.\n  int position_stack_[kPositionStackSize] = {};\n  int position_depth_ = 0;\n\n  // Anything parsed while silence_depth_ > 0 contributes nothing to the\n  // demangled output.  For constructs omitted from the demangling, such as\n  // impl-path and the contents of generic-args, we will increment\n  // silence_depth_ on the way in and decrement silence_depth_ on the way out.\n  int silence_depth_ = 0;\n\n  // Input: encoding_ points to a Rust mangled symbol, and encoding_[pos_] is\n  // the next input character to be scanned.\n  int pos_ = 0;\n  const char* encoding_ = nullptr;\n\n  // Output: *out_ is where the next output character should be written, and\n  // out_end_ points past the last byte of available space.\n  char* out_ = nullptr;\n  char* out_end_ = nullptr;\n};\n\n}  // namespace\n\nbool DemangleRustSymbolEncoding(const char* mangled, char* out,\n                                size_t out_size) {\n  return RustSymbolParser(mangled, out, out + out_size).Parse();\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/demangle_rust.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_RUST_H_\n#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_RUST_H_\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Demangle the Rust encoding `mangled`.  On success, return true and write the\n// demangled symbol name to `out`.  Otherwise, return false, leaving unspecified\n// contents in `out`.  For example, calling DemangleRustSymbolEncoding with\n// `mangled = \"_RNvC8my_crate7my_func\"` will yield `my_crate::my_func` in `out`,\n// provided `out_size` is large enough for that value and its trailing NUL.\n//\n// DemangleRustSymbolEncoding is async-signal-safe and runs in bounded C++\n// call-stack space.  It is suitable for symbolizing stack traces in a signal\n// handler.\nbool DemangleRustSymbolEncoding(const char* mangled, char* out,\n                                size_t out_size);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_DEMANGLE_RUST_H_\n"
  },
  {
    "path": "absl/debugging/internal/demangle_rust_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/demangle_rust.h\"\n\n#include <cstddef>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\n// If DemangleRustSymbolEncoding(mangled, <buffer with room for buffer_size\n// chars>, buffer_size) returns true and seems not to have overrun its output\n// buffer, returns the string written by DemangleRustSymbolEncoding; otherwise\n// returns an error message.\nstd::string ResultOfDemangling(const char* mangled, size_t buffer_size) {\n  // Fill the buffer with something other than NUL so we test whether Demangle\n  // appends trailing NUL as expected.\n  std::string buffer(buffer_size + 1, '~');\n  constexpr char kCanaryCharacter = 0x7f;  // arbitrary unlikely value\n  buffer[buffer_size] = kCanaryCharacter;\n  if (!DemangleRustSymbolEncoding(mangled, &buffer[0], buffer_size)) {\n    return \"Failed parse\";\n  }\n  if (buffer[buffer_size] != kCanaryCharacter) {\n    return \"Buffer overrun by output: \" + buffer.substr(0, buffer_size + 1)\n        + \"...\";\n  }\n  return buffer.data();  // Not buffer itself: this trims trailing padding.\n}\n\n// Tests that DemangleRustSymbolEncoding converts mangled into plaintext given\n// enough output buffer space but returns false and avoids overrunning a buffer\n// that is one byte too short.\n//\n// The lambda wrapping allows ASSERT_EQ to branch out the first time an\n// expectation is not satisfied, preventing redundant errors for the same bug.\n//\n// We test first with excess space so that if the algorithm just computes the\n// wrong answer, it will be clear from the error log that the bounds checks are\n// unlikely to be the code at fault.\n#define EXPECT_DEMANGLING(mangled, plaintext) \\\n  do { \\\n    [] { \\\n      constexpr size_t plenty_of_space = sizeof(plaintext) + 128; \\\n      constexpr size_t just_enough_space = sizeof(plaintext); \\\n      constexpr size_t one_byte_too_few = sizeof(plaintext) - 1; \\\n      const char* expected_plaintext = plaintext; \\\n      const char* expected_error = \"Failed parse\"; \\\n      ASSERT_EQ(ResultOfDemangling(mangled, plenty_of_space), \\\n                expected_plaintext); \\\n      ASSERT_EQ(ResultOfDemangling(mangled, just_enough_space), \\\n                expected_plaintext); \\\n      ASSERT_EQ(ResultOfDemangling(mangled, one_byte_too_few), \\\n                expected_error); \\\n    }(); \\\n  } while (0)\n\n// Tests that DemangleRustSymbolEncoding rejects the given input (typically, a\n// truncation of a real Rust symbol name).\n#define EXPECT_DEMANGLING_FAILS(mangled) \\\n    do { \\\n      constexpr size_t plenty_of_space = 1024; \\\n      const char* expected_error = \"Failed parse\"; \\\n      EXPECT_EQ(ResultOfDemangling(mangled, plenty_of_space), expected_error); \\\n    } while (0)\n\n// Piping grep -C 1 _R demangle_test.cc into your favorite c++filt\n// implementation allows you to verify that the goldens below are reasonable.\n\nTEST(DemangleRust, EmptyDemangling) {\n  EXPECT_TRUE(DemangleRustSymbolEncoding(\"_RC0\", nullptr, 0));\n}\n\nTEST(DemangleRust, FunctionAtCrateLevel) {\n  EXPECT_DEMANGLING(\"_RNvC10crate_name9func_name\", \"crate_name::func_name\");\n  EXPECT_DEMANGLING(\n      \"_RNvCs09azAZ_10crate_name9func_name\", \"crate_name::func_name\");\n}\n\nTEST(DemangleRust, TruncationsOfFunctionAtCrateLevel) {\n  EXPECT_DEMANGLING_FAILS(\"_R\");\n  EXPECT_DEMANGLING_FAILS(\"_RN\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvC\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvC10\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvC10crate_nam\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvC10crate_name\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvC10crate_name9\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvC10crate_name9func_nam\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvCs\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvCs09azAZ\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvCs09azAZ_\");\n}\n\nTEST(DemangleRust, VendorSuffixes) {\n  EXPECT_DEMANGLING(\"_RNvC10crate_name9func_name.!@#\", \"crate_name::func_name\");\n  EXPECT_DEMANGLING(\"_RNvC10crate_name9func_name$!@#\", \"crate_name::func_name\");\n}\n\nTEST(DemangleRust, UnicodeIdentifiers) {\n  EXPECT_DEMANGLING(\"_RNvC7ice_cap17Eyjafjallajökull\",\n                    \"ice_cap::Eyjafjallajökull\");\n  EXPECT_DEMANGLING(\"_RNvC7ice_caps_u19Eyjafjallajkull_jtb\",\n                    \"ice_cap::Eyjafjallajökull\");\n}\n\nTEST(DemangleRust, FunctionInModule) {\n  EXPECT_DEMANGLING(\"_RNvNtCs09azAZ_10crate_name11module_name9func_name\",\n                    \"crate_name::module_name::func_name\");\n}\n\nTEST(DemangleRust, FunctionInFunction) {\n  EXPECT_DEMANGLING(\n      \"_RNvNvCs09azAZ_10crate_name15outer_func_name15inner_func_name\",\n      \"crate_name::outer_func_name::inner_func_name\");\n}\n\nTEST(DemangleRust, ClosureInFunction) {\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_name0\",\n      \"crate_name::func_name::{closure#0}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_name0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#0}\");\n}\n\nTEST(DemangleRust, ClosureNumbering) {\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_names_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#1}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_names0_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#2}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_names9_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#11}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_namesa_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#12}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_namesz_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#37}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_namesA_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#38}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_namesZ_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#63}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_names10_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#64}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_namesg6_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#1000}\");\n}\n\nTEST(DemangleRust, ClosureNumberOverflowingInt) {\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs09azAZ_10crate_name9func_names1234567_0Cs123_12client_crate\",\n      \"crate_name::func_name::{closure#?}\");\n}\n\nTEST(DemangleRust, UnexpectedlyNamedClosure) {\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs123_10crate_name9func_name12closure_nameCs456_12client_crate\",\n      \"crate_name::func_name::{closure:closure_name#0}\");\n  EXPECT_DEMANGLING(\n      \"_RNCNvCs123_10crate_name9func_names2_12closure_nameCs456_12client_crate\",\n      \"crate_name::func_name::{closure:closure_name#4}\");\n}\n\nTEST(DemangleRust, ItemNestedInsideClosure) {\n  EXPECT_DEMANGLING(\n      \"_RNvNCNvCs123_10crate_name9func_name015inner_func_nameCs_12client_crate\",\n      \"crate_name::func_name::{closure#0}::inner_func_name\");\n}\n\nTEST(DemangleRust, Shim) {\n  EXPECT_DEMANGLING(\n      \"_RNSNvCs123_10crate_name9func_name6vtableCs456_12client_crate\",\n      \"crate_name::func_name::{shim:vtable#0}\");\n}\n\nTEST(DemangleRust, UnknownUppercaseNamespace) {\n  EXPECT_DEMANGLING(\n      \"_RNXNvCs123_10crate_name9func_name14mystery_objectCs456_12client_crate\",\n      \"crate_name::func_name::{X:mystery_object#0}\");\n}\n\nTEST(DemangleRust, NestedUppercaseNamespaces) {\n  EXPECT_DEMANGLING(\n      \"_RNCNXNYCs123_10crate_names0_1ys1_1xs2_0Cs456_12client_crate\",\n      \"crate_name::{Y:y#2}::{X:x#3}::{closure#4}\");\n}\n\nTEST(DemangleRust, TraitDefinition) {\n  EXPECT_DEMANGLING(\n      \"_RNvYNtC7crate_a9my_structNtC7crate_b8my_trait1f\",\n      \"<crate_a::my_struct as crate_b::my_trait>::f\");\n}\n\nTEST(DemangleRust, BasicTypeNames) {\n  EXPECT_DEMANGLING(\"_RNvYaNtC1c1t1f\", \"<i8 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYbNtC1c1t1f\", \"<bool as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYcNtC1c1t1f\", \"<char as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYdNtC1c1t1f\", \"<f64 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYeNtC1c1t1f\", \"<str as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYfNtC1c1t1f\", \"<f32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYhNtC1c1t1f\", \"<u8 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYiNtC1c1t1f\", \"<isize as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYjNtC1c1t1f\", \"<usize as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYlNtC1c1t1f\", \"<i32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYmNtC1c1t1f\", \"<u32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYnNtC1c1t1f\", \"<i128 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYoNtC1c1t1f\", \"<u128 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYpNtC1c1t1f\", \"<_ as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYsNtC1c1t1f\", \"<i16 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYtNtC1c1t1f\", \"<u16 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYuNtC1c1t1f\", \"<() as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYvNtC1c1t1f\", \"<... as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYxNtC1c1t1f\", \"<i64 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYyNtC1c1t1f\", \"<u64 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYzNtC1c1t1f\", \"<! as c::t>::f\");\n\n  EXPECT_DEMANGLING_FAILS(\"_RNvYkNtC1c1t1f\");\n}\n\nTEST(DemangleRust, SliceTypes) {\n  EXPECT_DEMANGLING(\"_RNvYSlNtC1c1t1f\", \"<[i32] as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYSNtC1d1sNtC1c1t1f\", \"<[d::s] as c::t>::f\");\n}\n\nTEST(DemangleRust, ImmutableReferenceTypes) {\n  EXPECT_DEMANGLING(\"_RNvYRlNtC1c1t1f\", \"<&i32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYRNtC1d1sNtC1c1t1f\", \"<&d::s as c::t>::f\");\n}\n\nTEST(DemangleRust, MutableReferenceTypes) {\n  EXPECT_DEMANGLING(\"_RNvYQlNtC1c1t1f\", \"<&mut i32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYQNtC1d1sNtC1c1t1f\", \"<&mut d::s as c::t>::f\");\n}\n\nTEST(DemangleRust, ConstantRawPointerTypes) {\n  EXPECT_DEMANGLING(\"_RNvYPlNtC1c1t1f\", \"<*const i32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYPNtC1d1sNtC1c1t1f\", \"<*const d::s as c::t>::f\");\n}\n\nTEST(DemangleRust, MutableRawPointerTypes) {\n  EXPECT_DEMANGLING(\"_RNvYOlNtC1c1t1f\", \"<*mut i32 as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYONtC1d1sNtC1c1t1f\", \"<*mut d::s as c::t>::f\");\n}\n\nTEST(DemangleRust, TupleLength0) {\n  EXPECT_DEMANGLING(\"_RNvYTENtC1c1t1f\", \"<() as c::t>::f\");\n}\n\nTEST(DemangleRust, TupleLength1) {\n  EXPECT_DEMANGLING(\"_RNvYTlENtC1c1t1f\", \"<(i32,) as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYTNtC1d1sENtC1c1t1f\", \"<(d::s,) as c::t>::f\");\n}\n\nTEST(DemangleRust, TupleLength2) {\n  EXPECT_DEMANGLING(\"_RNvYTlmENtC1c1t1f\", \"<(i32, u32) as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYTNtC1d1xNtC1e1yENtC1c1t1f\",\n                    \"<(d::x, e::y) as c::t>::f\");\n}\n\nTEST(DemangleRust, TupleLength3) {\n  EXPECT_DEMANGLING(\"_RNvYTlmnENtC1c1t1f\", \"<(i32, u32, i128) as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYTNtC1d1xNtC1e1yNtC1f1zENtC1c1t1f\",\n                    \"<(d::x, e::y, f::z) as c::t>::f\");\n}\n\nTEST(DemangleRust, LongerTuplesAbbreviated) {\n  EXPECT_DEMANGLING(\"_RNvYTlmnoENtC1c1t1f\",\n                    \"<(i32, u32, i128, ...) as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYTlmnNtC1d1xNtC1e1yENtC1c1t1f\",\n                    \"<(i32, u32, i128, ...) as c::t>::f\");\n}\n\nTEST(DemangleRust, PathBackrefToCrate) {\n  EXPECT_DEMANGLING(\"_RNvYNtC8my_crate9my_structNtB4_8my_trait1f\",\n                    \"<my_crate::my_struct as my_crate::my_trait>::f\");\n}\n\nTEST(DemangleRust, PathBackrefToNestedPath) {\n  EXPECT_DEMANGLING(\"_RNvYNtNtC1c1m1sNtB4_1t1f\", \"<c::m::s as c::m::t>::f\");\n}\n\nTEST(DemangleRust, PathBackrefAsInstantiatingCrate) {\n  EXPECT_DEMANGLING(\"_RNCNvC8my_crate7my_func0B3_\",\n                    \"my_crate::my_func::{closure#0}\");\n}\n\nTEST(DemangleRust, TypeBackrefsNestedInTuple) {\n  EXPECT_DEMANGLING(\"_RNvYTTRlB4_ERB3_ENtC1c1t1f\",\n                    \"<((&i32, &i32), &(&i32, &i32)) as c::t>::f\");\n}\n\nTEST(DemangleRust, NoInfiniteLoopOnBackrefToTheWhole) {\n  EXPECT_DEMANGLING_FAILS(\"_RB_\");\n  EXPECT_DEMANGLING_FAILS(\"_RNvB_1sNtC1c1t1f\");\n}\n\nTEST(DemangleRust, NoCrashOnForwardBackref) {\n  EXPECT_DEMANGLING_FAILS(\"_RB0_\");\n  EXPECT_DEMANGLING_FAILS(\"_RB1_\");\n  EXPECT_DEMANGLING_FAILS(\"_RB2_\");\n  EXPECT_DEMANGLING_FAILS(\"_RB3_\");\n  EXPECT_DEMANGLING_FAILS(\"_RB4_\");\n}\n\nTEST(DemangleRust, PathBackrefsDoNotRecurseDuringSilence) {\n  // B_ points at the value f (the whole mangling), so the cycle would lead to\n  // parse failure if the parser tried to parse what was pointed to.\n  EXPECT_DEMANGLING(\"_RNvYTlmnNtB_1sENtC1c1t1f\",\n                    \"<(i32, u32, i128, ...) as c::t>::f\");\n}\n\nTEST(DemangleRust, TypeBackrefsDoNotRecurseDuringSilence) {\n  // B2_ points at the tuple type, likewise making a cycle that the parser\n  // avoids following.\n  EXPECT_DEMANGLING(\"_RNvYTlmnB2_ENtC1c1t1f\",\n                    \"<(i32, u32, i128, ...) as c::t>::f\");\n}\n\nTEST(DemangleRust, ConstBackrefsDoNotRecurseDuringSilence) {\n  // B_ points at the whole I...E mangling, which does not parse as a const.\n  EXPECT_DEMANGLING(\"_RINvC1c1fAlB_E\", \"c::f::<>\");\n}\n\nTEST(DemangleRust, ReturnFromBackrefToInputPosition256) {\n  // Show that we can resume at input positions that don't fit into a byte.\n  EXPECT_DEMANGLING(\"_RNvYNtC1c238very_long_type_\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABC\"\n                    \"NtB4_1t1f\",\n                    \"<c::very_long_type_\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABCDEFGHIJabcdefghij\"\n                    \"ABCDEFGHIJabcdefghijABC\"\n                    \" as c::t>::f\");\n}\n\nTEST(DemangleRust, EmptyGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fE\", \"c::f::<>\");\n}\n\nTEST(DemangleRust, OneSimpleTypeInGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1flE\",  // c::f::<i32>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, OneTupleInGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fTlmEE\",  // c::f::<(i32, u32)>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, OnePathInGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fNtC1d1sE\",  // c::f::<d::s>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, LongerGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1flmRNtC1d1sE\",  // c::f::<i32, u32, &d::s>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, BackrefInGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fRlB7_NtB2_1sE\",  // c::f::<&i32, &i32, c::s>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, NestedGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fINtB2_1slEmE\",  // c::f::<c::s::<i32>, u32>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, MonomorphicEntityNestedInsideGeneric) {\n  EXPECT_DEMANGLING(\"_RNvINvC1c1fppE1g\",  // c::f::<_, _>::g\n                    \"c::f::<>::g\");\n}\n\nTEST(DemangleRust, ArrayTypeWithSimpleElementType) {\n  EXPECT_DEMANGLING(\"_RNvYAlj1f_NtC1c1t1f\", \"<[i32; 0x1f] as c::t>::f\");\n}\n\nTEST(DemangleRust, ArrayTypeWithComplexElementType) {\n  EXPECT_DEMANGLING(\"_RNvYAINtC1c1slEj1f_NtB6_1t1f\",\n                    \"<[c::s::<>; 0x1f] as c::t>::f\");\n}\n\nTEST(DemangleRust, NestedArrayType) {\n  EXPECT_DEMANGLING(\"_RNvYAAlj1f_j2e_NtC1c1t1f\",\n                    \"<[[i32; 0x1f]; 0x2e] as c::t>::f\");\n}\n\nTEST(DemangleRust, BackrefArraySize) {\n  EXPECT_DEMANGLING(\"_RNvYAAlj1f_B5_NtC1c1t1f\",\n                    \"<[[i32; 0x1f]; 0x1f] as c::t>::f\");\n}\n\nTEST(DemangleRust, ZeroArraySize) {\n  EXPECT_DEMANGLING(\"_RNvYAlj0_NtC1c1t1f\", \"<[i32; 0x0] as c::t>::f\");\n}\n\nTEST(DemangleRust, SurprisingMinusesInArraySize) {\n  // Compilers shouldn't do this stuff, but existing demanglers accept it.\n  EXPECT_DEMANGLING(\"_RNvYAljn0_NtC1c1t1f\", \"<[i32; -0x0] as c::t>::f\");\n  EXPECT_DEMANGLING(\"_RNvYAljn42_NtC1c1t1f\", \"<[i32; -0x42] as c::t>::f\");\n}\n\nTEST(DemangleRust, NumberAsGenericArg) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fKl8_E\",  // c::f::<0x8>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, NumberAsFirstOfTwoGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fKl8_mE\",  // c::f::<0x8, u32>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, NumberAsSecondOfTwoGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fmKl8_E\",  // c::f::<u32, 0x8>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, NumberPlaceholder) {\n  EXPECT_DEMANGLING(\"_RNvINvC1c1fKpE1g\",  // c::f::<_>::g\n                    \"c::f::<>::g\");\n}\n\nTEST(DemangleRust, InherentImplWithoutDisambiguator) {\n  EXPECT_DEMANGLING(\"_RNvMNtC8my_crate6my_modNtB2_9my_struct7my_func\",\n                    \"<my_crate::my_mod::my_struct>::my_func\");\n}\n\nTEST(DemangleRust, InherentImplWithDisambiguator) {\n  EXPECT_DEMANGLING(\"_RNvMs_NtC8my_crate6my_modNtB4_9my_struct7my_func\",\n                    \"<my_crate::my_mod::my_struct>::my_func\");\n}\n\nTEST(DemangleRust, TraitImplWithoutDisambiguator) {\n  EXPECT_DEMANGLING(\"_RNvXC8my_crateNtB2_9my_structNtB2_8my_trait7my_func\",\n                    \"<my_crate::my_struct as my_crate::my_trait>::my_func\");\n}\n\nTEST(DemangleRust, TraitImplWithDisambiguator) {\n  EXPECT_DEMANGLING(\"_RNvXs_C8my_crateNtB4_9my_structNtB4_8my_trait7my_func\",\n                    \"<my_crate::my_struct as my_crate::my_trait>::my_func\");\n}\n\nTEST(DemangleRust, TraitImplWithNonpathSelfType) {\n  EXPECT_DEMANGLING(\"_RNvXC8my_crateRlNtB2_8my_trait7my_func\",\n                    \"<&i32 as my_crate::my_trait>::my_func\");\n}\n\nTEST(DemangleRust, ThunkType) {\n  EXPECT_DEMANGLING(\"_RNvYFEuNtC1c1t1f\",  // <fn() as c::t>::f\n                    \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, NontrivialFunctionReturnType) {\n  EXPECT_DEMANGLING(\n      \"_RNvYFERTlmENtC1c1t1f\",  // <fn() -> &(i32, u32) as c::t>::f\n      \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, OneParameterType) {\n  EXPECT_DEMANGLING(\"_RNvYFlEuNtC1c1t1f\",  // <fn(i32) as c::t>::f\n                    \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, TwoParameterTypes) {\n  EXPECT_DEMANGLING(\"_RNvYFlmEuNtC1c1t1f\",  // <fn(i32, u32) as c::t>::f\n                    \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, ExternC) {\n  EXPECT_DEMANGLING(\"_RNvYFKCEuNtC1c1t1f\",  // <extern \"C\" fn() as c::t>>::f\n                    \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, ExternOther) {\n  EXPECT_DEMANGLING(\n      \"_RNvYFK5not_CEuNtC1c1t1f\",  // <extern \"not-C\" fn() as c::t>::f\n      \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, Unsafe) {\n  EXPECT_DEMANGLING(\"_RNvYFUEuNtC1c1t1f\",  // <unsafe fn() as c::t>::f\n                    \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, Binder) {\n  EXPECT_DEMANGLING(\n      // <for<'a> fn(&'a i32) -> &'a i32 as c::t>::f\n      \"_RNvYFG_RL0_lEB5_NtC1c1t1f\",\n      \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, AllFnSigFeaturesInOrder) {\n  EXPECT_DEMANGLING(\n      // <for<'a> unsafe extern \"C\" fn(&'a i32) -> &'a i32 as c::t>::f\n      \"_RNvYFG_UKCRL0_lEB8_NtC1c1t1f\",\n      \"<fn... as c::t>::f\");\n}\n\nTEST(DemangleRust, LifetimeInGenericArgs) {\n  EXPECT_DEMANGLING(\"_RINvC1c1fINtB2_1sL_EE\",  // c::f::<c::s::<'_>>\n                    \"c::f::<>\");\n}\n\nTEST(DemangleRust, EmptyDynTrait) {\n  // This shouldn't happen, but the grammar allows it and existing demanglers\n  // accept it.\n  EXPECT_DEMANGLING(\"_RNvYDEL_NtC1c1t1f\",\n                    \"<dyn  as c::t>::f\");\n}\n\nTEST(DemangleRust, SimpleDynTrait) {\n  EXPECT_DEMANGLING(\"_RNvYDNtC1c1tEL_NtC1d1u1f\",\n                    \"<dyn c::t as d::u>::f\");\n}\n\nTEST(DemangleRust, DynTraitWithOneAssociatedType) {\n  EXPECT_DEMANGLING(\n      \"_RNvYDNtC1c1tp1xlEL_NtC1d1u1f\",  // <dyn c::t<x = i32> as d::u>::f\n      \"<dyn c::t<> as d::u>::f\");\n}\n\nTEST(DemangleRust, DynTraitWithTwoAssociatedTypes) {\n  EXPECT_DEMANGLING(\n      // <dyn c::t<x = i32, y = u32> as d::u>::f\n      \"_RNvYDNtC1c1tp1xlp1ymEL_NtC1d1u1f\",\n      \"<dyn c::t<> as d::u>::f\");\n}\n\nTEST(DemangleRust, DynTraitPlusAutoTrait) {\n  EXPECT_DEMANGLING(\n      \"_RNvYDNtC1c1tNtNtC3std6marker4SendEL_NtC1d1u1f\",\n      \"<dyn c::t + std::marker::Send as d::u>::f\");\n}\n\nTEST(DemangleRust, DynTraitPlusTwoAutoTraits) {\n  EXPECT_DEMANGLING(\n      \"_RNvYDNtC1c1tNtNtC3std6marker4CopyNtBc_4SyncEL_NtC1d1u1f\",\n      \"<dyn c::t + std::marker::Copy + std::marker::Sync as d::u>::f\");\n}\n\nTEST(DemangleRust, HigherRankedDynTrait) {\n  EXPECT_DEMANGLING(\n      // <dyn for<'a> c::t::<&'a i32> as d::u>::f\n      \"_RNvYDG_INtC1c1tRL0_lEEL_NtC1d1u1f\",\n      \"<dyn c::t::<> as d::u>::f\");\n}\n\n}  // namespace\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/demangle_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/demangle.h\"\n\n#include <cstdlib>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/debugging/internal/stack_consumption.h\"\n#include \"absl/log/log.h\"\n#include \"absl/memory/memory.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\nusing ::testing::ContainsRegex;\n\nTEST(Demangle, FunctionTemplate) {\n  char tmp[100];\n\n  // template <typename T>\n  // int foo(T);\n  //\n  // foo<int>(5);\n  ASSERT_TRUE(Demangle(\"_Z3fooIiEiT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionTemplateWithNesting) {\n  char tmp[100];\n\n  // template <typename T>\n  // int foo(T);\n  //\n  // foo<Wrapper<int>>({ .value = 5 });\n  ASSERT_TRUE(Demangle(\"_Z3fooI7WrapperIiEEiT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionTemplateWithNonTypeParamConstraint) {\n  char tmp[100];\n\n  // template <std::integral T>\n  // int foo(T);\n  //\n  // foo<int>(5);\n  ASSERT_TRUE(Demangle(\"_Z3fooITkSt8integraliEiT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionTemplateWithFunctionRequiresClause) {\n  char tmp[100];\n\n  // template <typename T>\n  // int foo() requires std::integral<T>;\n  //\n  // foo<int>();\n  ASSERT_TRUE(Demangle(\"_Z3fooIiEivQsr3stdE8integralIT_E\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionWithTemplateParamRequiresClause) {\n  char tmp[100];\n\n  // template <typename T>\n  //     requires std::integral<T>\n  // int foo();\n  //\n  // foo<int>();\n  ASSERT_TRUE(Demangle(\"_Z3fooIiQsr3stdE8integralIT_EEiv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionWithTemplateParamAndFunctionRequiresClauses) {\n  char tmp[100];\n\n  // template <typename T>\n  //     requires std::integral<T>\n  // int foo() requires std::integral<T>;\n  //\n  // foo<int>();\n  ASSERT_TRUE(Demangle(\"_Z3fooIiQsr3stdE8integralIT_EEivQsr3stdE8integralIS0_E\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionTemplateBacktracksOnMalformedRequiresClause) {\n  char tmp[100];\n\n  // template <typename T>\n  // int foo(T);\n  //\n  // foo<int>(5);\n  // Except there's an extra `Q` where the mangled requires clause would be.\n  ASSERT_FALSE(Demangle(\"_Z3fooIiQEiT_\", tmp, sizeof(tmp)));\n}\n\nTEST(Demangle, FunctionTemplateWithAutoParam) {\n  char tmp[100];\n\n  // template <auto>\n  // void foo();\n  //\n  // foo<1>();\n  ASSERT_TRUE(Demangle(\"_Z3fooITnDaLi1EEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionTemplateWithNonTypeParamPack) {\n  char tmp[100];\n\n  // template <int&..., typename T>\n  // void foo(T);\n  //\n  // foo(2);\n  ASSERT_TRUE(Demangle(\"_Z3fooITpTnRiJEiEvT0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, FunctionTemplateTemplateParamWithConstrainedArg) {\n  char tmp[100];\n\n  // template <typename T>\n  // concept True = true;\n  //\n  // template <typename T> requires True<T>\n  // struct Fooer {};\n  //\n  // template <template <typename T> typename>\n  // void foo() {}\n  //\n  // foo<Fooer>();\n  ASSERT_TRUE(Demangle(\"_Z3fooITtTyE5FooerEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, ConstrainedAutoInFunctionTemplate) {\n  char tmp[100];\n\n  // template <typename T> concept C = true;\n  // template <C auto N> void f() {}\n  // template void f<0>();\n  ASSERT_TRUE(Demangle(\"_Z1fITnDk1CLi0EEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"f<>()\");\n}\n\nTEST(Demangle, ConstrainedFriendFunctionTemplate) {\n  char tmp[100];\n\n  // Source:\n  //\n  // namespace ns {\n  // template <class T> struct Y {\n  //   friend void y(Y) requires true {}\n  // };\n  // }  // namespace ns\n  //\n  // y(ns::Y<int>{});\n  //\n  // LLVM demangling:\n  //\n  // ns::Y<int>::friend y(ns::Y<int>) requires true\n  ASSERT_TRUE(Demangle(\"_ZN2ns1YIiEF1yES1_QLb1E\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"ns::Y<>::friend y()\");\n}\n\nTEST(Demangle, ConstrainedFriendOperatorTemplate) {\n  char tmp[100];\n\n  // ns::Y<int>::friend operator*(ns::Y<int>) requires true\n  ASSERT_TRUE(Demangle(\"_ZN2ns1YIiEFdeES1_QLb1E\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"ns::Y<>::friend operator*()\");\n}\n\nTEST(Demangle, NonTemplateBuiltinType) {\n  char tmp[100];\n\n  // void foo(__my_builtin_type t);\n  //\n  // foo({});\n  ASSERT_TRUE(Demangle(\"_Z3foou17__my_builtin_type\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo()\");\n}\n\nTEST(Demangle, SingleArgTemplateBuiltinType) {\n  char tmp[100];\n\n  // template <typename T>\n  // __my_builtin_type<T> foo();\n  //\n  // foo<int>();\n  ASSERT_TRUE(Demangle(\"_Z3fooIiEu17__my_builtin_typeIT_Ev\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, TwoArgTemplateBuiltinType) {\n  char tmp[100];\n\n  // template <typename T, typename U>\n  // __my_builtin_type<T, U> foo();\n  //\n  // foo<int, char>();\n  ASSERT_TRUE(\n      Demangle(\"_Z3fooIicEu17__my_builtin_typeIT_T0_Ev\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, TypeNestedUnderTemplatedBuiltinType) {\n  char tmp[100];\n\n  // Source:\n  //\n  // template <typename T>\n  // typename std::remove_reference_t<T>::type f(T t);\n  //\n  // struct C { using type = C; };\n  //\n  // f<const C&>(C{});\n  //\n  // These days std::remove_reference_t is implemented in terms of a vendor\n  // builtin __remove_reference_t.  A full demangling might look like:\n  //\n  // __remove_reference_t<C const&>::type f<C const&>(C const&)\n  ASSERT_TRUE(Demangle(\"_Z1fIRK1CENu20__remove_reference_tIT_E4typeES3_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, TemplateTemplateParamSubstitution) {\n  char tmp[100];\n\n  // template <typename T>\n  // concept True = true;\n  //\n  // template<std::integral T, T> struct Foolable {};\n  // template<template<typename T, T> typename> void foo() {}\n  //\n  // template void foo<Foolable>();\n  ASSERT_TRUE(Demangle(\"_Z3fooITtTyTnTL0__E8FoolableEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"foo<>()\");\n}\n\nTEST(Demangle, TemplateParamSubstitutionWithGenericLambda) {\n  char tmp[100];\n\n  // template <typename>\n  // struct Fooer {\n  //     template <typename>\n  //     void foo(decltype([](auto x, auto y) {})) {}\n  // };\n  //\n  // Fooer<int> f;\n  // f.foo<int>({});\n  ASSERT_TRUE(\n      Demangle(\"_ZN5FooerIiE3fooIiEEvNS0_UlTL0__TL0_0_E_E\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"Fooer<>::foo<>()\");\n}\n\nTEST(Demangle, LambdaRequiresTrue) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const requires true\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QLb1E\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresSimpleExpression) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const requires 2 + 2 == 4\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QeqplLi2ELi2ELi4E\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionContainingTrue) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const requires requires { true; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqXLb1EE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionContainingConcept) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const\n  // requires requires { std::same_as<decltype(fp), int>; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqXsr3stdE7same_asIDtfp_EiEE\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionContainingNoexceptExpression) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const\n  // requires requires { {fp + fp} noexcept; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqXplfp_fp_NE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionContainingReturnTypeConstraint) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const\n  // requires requires { {fp + fp} -> std::same_as<decltype(fp)>; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqXplfp_fp_RNSt7same_asIDtfp_EEEE\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionWithBothNoexceptAndReturnType) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const\n  // requires requires { {fp + fp} noexcept -> std::same_as<decltype(fp)>; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqXplfp_fp_NRNSt7same_asIDtfp_EEEE\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionContainingType) {\n  char tmp[100];\n\n  // auto $_0::operator()<S>(S) const\n  // requires requires { typename S::T; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clI1SEEDaT_QrqTNS2_1TEE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionNestingAnotherRequires) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const requires requires { requires true; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqQLb1EE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, LambdaRequiresRequiresExpressionContainingTwoRequirements) {\n  char tmp[100];\n\n  // auto $_0::operator()<int>(int) const\n  // requires requires { requires true; requires 2 + 2 == 4; }\n  ASSERT_TRUE(Demangle(\"_ZNK3$_0clIiEEDaT_QrqXLb1EXeqplLi2ELi2ELi4EE\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"$_0::operator()<>()\");\n}\n\nTEST(Demangle, RequiresExpressionWithItsOwnParameter) {\n  char tmp[100];\n\n  // S<requires (int) { fp + fp; }> f<int>(int)\n  ASSERT_TRUE(Demangle(\"_Z1fIiE1SIXrQT__XplfL0p_fp_EEES1_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"f<>()\");\n}\n\nTEST(Demangle, LambdaWithExplicitTypeArgument) {\n  char tmp[100];\n\n  // Source:\n  //\n  // template <class T> T f(T t) {\n  //   return []<class U>(U u) { return u + u; }(t);\n  // }\n  //\n  // template int f<int>(int);\n  //\n  // Full LLVM demangling of the lambda call operator:\n  //\n  // auto int f<int>(int)::'lambda'<typename $T>(int)::\n  // operator()<int>(int) const\n  ASSERT_TRUE(Demangle(\"_ZZ1fIiET_S0_ENKUlTyS0_E_clIiEEDaS0_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"f<>()::{lambda()#1}::operator()<>()\");\n}\n\nTEST(Demangle, LambdaWithExplicitPackArgument) {\n  char tmp[100];\n\n  // Source:\n  //\n  // template <class T> T h(T t) {\n  //   return []<class... U>(U... u) {\n  //     return ((u + u) + ... + 0);\n  //   }(t);\n  // }\n  //\n  // template int h<int>(int);\n  //\n  // Full LLVM demangling of the lambda call operator:\n  //\n  // auto int f<int>(int)::'lambda'<typename ...$T>($T...)::\n  // operator()<int>($T...) const\n  ASSERT_TRUE(Demangle(\"_ZZ1fIiET_S0_ENKUlTpTyDpT_E_clIJiEEEDaS2_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"f<>()::{lambda()#1}::operator()<>()\");\n}\n\nTEST(Demangle, LambdaInClassMemberDefaultArgument) {\n  char tmp[100];\n\n  // Source:\n  //\n  // struct S {\n  //   static auto f(void (*g)() = [] {}) { return g; }\n  // };\n  // void (*p)() = S::f();\n  //\n  // Full LLVM demangling of the lambda call operator:\n  //\n  // S::f(void (*)())::'lambda'()::operator()() const\n  //\n  // Full GNU binutils demangling:\n  //\n  // S::f(void (*)())::{default arg#1}::{lambda()#1}::operator()() const\n  ASSERT_TRUE(Demangle(\"_ZZN1S1fEPFvvEEd_NKUlvE_clEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"S::f()::{default arg#1}::{lambda()#1}::operator()()\");\n\n  // The same but in the second rightmost default argument.\n  ASSERT_TRUE(Demangle(\"_ZZN1S1fEPFvvEEd0_NKUlvE_clEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"S::f()::{default arg#2}::{lambda()#1}::operator()()\");\n\n  // Reject negative <(parameter) number> values.\n  ASSERT_FALSE(Demangle(\"_ZZN1S1fEPFvvEEdn1_NKUlvE_clEv\", tmp, sizeof(tmp)));\n}\n\nTEST(Demangle, AvoidSignedOverflowForUnfortunateParameterNumbers) {\n  char tmp[100];\n\n  // Here <number> + 2 fits in an int, but just barely.  (We expect no such\n  // input in practice: real functions don't have billions of arguments.)\n  ASSERT_TRUE(Demangle(\"_ZZN1S1fEPFvvEEd2147483645_NKUlvE_clEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp,\n               \"S::f()::{default arg#2147483647}::{lambda()#1}::operator()()\");\n\n  // Now <number> is an int, but <number> + 2 is not.\n  ASSERT_TRUE(Demangle(\"_ZZN1S1fEPFvvEEd2147483646_NKUlvE_clEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"S::f()::{default arg#1}::{lambda()#1}::operator()()\");\n\n  // <number> is the largest int.\n  ASSERT_TRUE(Demangle(\"_ZZN1S1fEPFvvEEd2147483647_NKUlvE_clEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"S::f()::{default arg#1}::{lambda()#1}::operator()()\");\n\n  // <number> itself does not fit into an int.  ParseNumber truncates the value\n  // to int, yielding a large negative number, which we strain out.\n  ASSERT_TRUE(Demangle(\"_ZZN1S1fEPFvvEEd2147483648_NKUlvE_clEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"S::f()::{default arg#1}::{lambda()#1}::operator()()\");\n}\n\nTEST(Demangle, SubstpackNotationForTroublesomeTemplatePack) {\n  char tmp[100];\n\n  // Source:\n  //\n  // template <template <class> class, template <class> class> struct B {};\n  //\n  // template <template <class> class... T> struct A {\n  //   template <template <class> class... U> void f(B<T, U>&&...) {}\n  // };\n  //\n  // template void A<>::f<>();\n  //\n  // LLVM can't demangle its own _SUBSTPACK_ notation.\n  ASSERT_TRUE(Demangle(\"_ZN1AIJEE1fIJEEEvDpO1BI_SUBSTPACK_T_E\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"A<>::f<>()\");\n}\n\nTEST(Demangle, TemplateTemplateParamAppearingAsBackrefFollowedByTemplateArgs) {\n  char tmp[100];\n\n  // Source:\n  //\n  // template <template <class> class C> struct W {\n  //   template <class T> static decltype(C<T>::m()) f() { return {}; }\n  // };\n  //\n  // template <class T> struct S { static int m() { return 0; } };\n  // template decltype(S<int>::m()) W<S>::f<int>();\n  ASSERT_TRUE(Demangle(\"_ZN1WI1SE1fIiEEDTclsrS0_IT_EE1mEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(tmp, \"W<>::f<>()\");\n}\n\n// Test corner cases of boundary conditions.\nTEST(Demangle, CornerCases) {\n  char tmp[10];\n  EXPECT_TRUE(Demangle(\"_Z6foobarv\", tmp, sizeof(tmp)));\n  // sizeof(\"foobar()\") == 9\n  EXPECT_STREQ(\"foobar()\", tmp);\n  EXPECT_TRUE(Demangle(\"_Z6foobarv\", tmp, 9));\n  EXPECT_STREQ(\"foobar()\", tmp);\n  EXPECT_FALSE(Demangle(\"_Z6foobarv\", tmp, 8));  // Not enough.\n  EXPECT_FALSE(Demangle(\"_Z6foobarv\", tmp, 1));\n  EXPECT_FALSE(Demangle(\"_Z6foobarv\", tmp, 0));\n  EXPECT_FALSE(Demangle(\"_Z6foobarv\", nullptr, 0));  // Should not cause SEGV.\n  EXPECT_FALSE(Demangle(\"_Z1000000\", tmp, 9));\n}\n\n// Test handling of functions suffixed with .clone.N, which is used\n// by GCC 4.5.x (and our locally-modified version of GCC 4.4.x), and\n// .constprop.N and .isra.N, which are used by GCC 4.6.x.  These\n// suffixes are used to indicate functions which have been cloned\n// during optimization.  We ignore these suffixes.\nTEST(Demangle, Clones) {\n  char tmp[20];\n  EXPECT_TRUE(Demangle(\"_ZL3Foov\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.clone.3\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.constprop.80\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.isra.18\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.isra.2.constprop.18\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // Demangle suffixes produced by -funique-internal-linkage-names.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.__uniq.12345\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.__uniq.12345.isra.2.constprop.18\", tmp,\n                       sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // Suffixes without the number should also demangle.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.clo\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // Suffixes with just the number should also demangle.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.123\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // (.clone. followed by non-number), should also demangle.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.clone.foo\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // (.clone. followed by multiple numbers), should also demangle.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.clone.123.456\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // (a long valid suffix), should demangle.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.part.9.165493.constprop.775.31805\", tmp,\n                       sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  // Other suffixes should demangle too.\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.abc123\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.clone.\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n  EXPECT_TRUE(Demangle(\"_ZL3Foov.isra.2.constprop.\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"Foo()\", tmp);\n}\n\nTEST(Demangle, Discriminators) {\n  char tmp[80];\n\n  // Source:\n  //\n  // using Thunk = void (*)();\n  //\n  // Thunk* f() {\n  //   static Thunk thunks[12] = {};\n  //\n  // #define THUNK(i) [backslash here]\n  //   do { struct S { static void g() {} }; thunks[i] = &S::g; } while (0)\n  //\n  //   THUNK(0);\n  //   [... repeat for 1 to 10 ...]\n  //   THUNK(11);\n  //\n  //   return thunks;\n  // }\n  //\n  // The test inputs are manglings of some of the S::g member functions.\n\n  // The first one omits the discriminator.\n  EXPECT_TRUE(Demangle(\"_ZZ1fvEN1S1gEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()::S::g()\", tmp);\n\n  // The second one encodes 0.\n  EXPECT_TRUE(Demangle(\"_ZZ1fvEN1S1gE_0v\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()::S::g()\", tmp);\n\n  // The eleventh one encodes 9.\n  EXPECT_TRUE(Demangle(\"_ZZ1fvEN1S1gE_9v\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()::S::g()\", tmp);\n\n  // The twelfth one encodes 10 with extra underscores delimiting it.\n  EXPECT_TRUE(Demangle(\"_ZZ1fvEN1S1gE__10_v\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()::S::g()\", tmp);\n}\n\nTEST(Demangle, SingleDigitDiscriminatorFollowedByADigit) {\n  char tmp[80];\n\n  // Don't parse 911 as a number.\n  EXPECT_TRUE(Demangle(\"_ZZ1fvEN1S1gE_911return_type\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()::S::g()\", tmp);\n}\n\nTEST(Demangle, LiteralOfGlobalNamespaceEnumType) {\n  char tmp[80];\n\n  // void f<(E)42>()\n  EXPECT_TRUE(Demangle(\"_Z1fIL1E42EEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NullptrLiterals) {\n  char tmp[80];\n\n  // void f<nullptr>()\n  EXPECT_TRUE(Demangle(\"_Z1fILDnEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // also void f<nullptr>()\n  EXPECT_TRUE(Demangle(\"_Z1fILDn0EEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, StringLiterals) {\n  char tmp[80];\n\n  // void f<\"<char const [42]>\">()\n  EXPECT_TRUE(Demangle(\"_Z1fILA42_KcEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ComplexFloatingPointLiterals) {\n  char tmp[80];\n\n  // Source (use g++ -fext-numeric-literals to compile):\n  //\n  // using C = double _Complex;\n  // template <class T> void f(char (&)[sizeof(C{sizeof(T)} + 4.0j)]) {}\n  // template void f<int>(char (&)[sizeof(C{sizeof(int)} + 4.0j)]);\n  //\n  // GNU demangling:\n  //\n  // void f<int>(char (&) [sizeof (double _Complex{sizeof (int)}+\n  // ((double _Complex)0000000000000000_4010000000000000))])\n  EXPECT_TRUE(Demangle(\n      \"_Z1fIiEvRAszpltlCdstT_ELS0_0000000000000000_4010000000000000E_c\",\n      tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, Float128) {\n  char tmp[80];\n\n  // S::operator _Float128() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvDF128_Ev\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator _Float128()\", tmp);\n}\n\nTEST(Demangle, Float128x) {\n  char tmp[80];\n\n  // S::operator _Float128x() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvDF128xEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator _Float128x()\", tmp);\n}\n\nTEST(Demangle, Bfloat16) {\n  char tmp[80];\n\n  // S::operator std::bfloat16_t() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvDF16bEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator std::bfloat16_t()\", tmp);\n}\n\nTEST(Demangle, SimpleSignedBitInt) {\n  char tmp[80];\n\n  // S::operator _BitInt(256)() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvDB256_Ev\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator _BitInt(256)()\", tmp);\n}\n\nTEST(Demangle, SimpleUnsignedBitInt) {\n  char tmp[80];\n\n  // S::operator unsigned _BitInt(256)() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvDU256_Ev\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator unsigned _BitInt(256)()\", tmp);\n}\n\nTEST(Demangle, DependentBitInt) {\n  char tmp[80];\n\n  // S::operator _BitInt(256)<256>() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvDBT__ILi256EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator _BitInt(?)<>()\", tmp);\n}\n\nTEST(Demangle, ConversionToPointerType) {\n  char tmp[80];\n\n  // S::operator int*() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvPiEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator int*()\", tmp);\n}\n\nTEST(Demangle, ConversionToLvalueReferenceType) {\n  char tmp[80];\n\n  // S::operator int&() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvRiEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator int&()\", tmp);\n}\n\nTEST(Demangle, ConversionToRvalueReferenceType) {\n  char tmp[80];\n\n  // S::operator int&&() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvOiEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator int&&()\", tmp);\n}\n\nTEST(Demangle, ConversionToComplexFloatingPointType) {\n  char tmp[80];\n\n  // S::operator float _Complex() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvCfEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator float _Complex()\", tmp);\n}\n\nTEST(Demangle, ConversionToImaginaryFloatingPointType) {\n  char tmp[80];\n\n  // S::operator float _Imaginary() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvGfEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator float _Imaginary()\", tmp);\n}\n\nTEST(Demangle, ConversionToPointerToCvQualifiedType) {\n  char tmp[80];\n\n  // S::operator int const volatile restrict*() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvPrVKiEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator int const volatile restrict*()\", tmp);\n}\n\nTEST(Demangle, ConversionToLayeredPointerType) {\n  char tmp[80];\n\n  // S::operator int const* const*() const\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvPKPKiEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator int const* const*()\", tmp);\n}\n\nTEST(Demangle, ConversionToTypeWithExtendedQualifier) {\n  char tmp[80];\n\n  // S::operator int const AS128*() const\n  //\n  // Because our scan of easy type constructors stops at the extended qualifier,\n  // the demangling preserves the * but loses the const.\n  EXPECT_TRUE(Demangle(\"_ZNK1ScvPU5AS128KiEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator int*()\", tmp);\n}\n\nTEST(Demangle, GlobalInitializers) {\n  char tmp[80];\n\n  // old form without suffix\n  EXPECT_TRUE(Demangle(\"_ZGR1v\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"reference temporary for v\", tmp);\n\n  // modern form for the whole initializer\n  EXPECT_TRUE(Demangle(\"_ZGR1v_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"reference temporary for v\", tmp);\n\n  // next subobject in depth-first preorder traversal\n  EXPECT_TRUE(Demangle(\"_ZGR1v0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"reference temporary for v\", tmp);\n\n  // subobject with a larger seq-id\n  EXPECT_TRUE(Demangle(\"_ZGR1v1Z_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"reference temporary for v\", tmp);\n}\n\nTEST(Demangle, StructuredBindings) {\n  char tmp[80];\n\n  // Source:\n  //\n  // struct S { int a, b; };\n  // const auto& [x, y] = S{1, 2};\n\n  // [x, y]\n  EXPECT_TRUE(Demangle(\"_ZDC1x1yE\", tmp, sizeof(tmp)));\n\n  // reference temporary for [x, y]\n  EXPECT_TRUE(Demangle(\"_ZGRDC1x1yE_\", tmp, sizeof(tmp)));\n}\n\n// Test the GNU abi_tag extension.\nTEST(Demangle, AbiTags) {\n  char tmp[80];\n\n  // Mangled name generated via:\n  // struct [[gnu::abi_tag(\"abc\")]] A{};\n  // A a;\n  EXPECT_TRUE(Demangle(\"_Z1aB3abc\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"a[abi:abc]\", tmp);\n\n  // Mangled name generated via:\n  // struct B {\n  //   B [[gnu::abi_tag(\"xyz\")]] (){};\n  // };\n  // B b;\n  EXPECT_TRUE(Demangle(\"_ZN1BC2B3xyzEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"B::B[abi:xyz]()\", tmp);\n\n  // Mangled name generated via:\n  // [[gnu::abi_tag(\"foo\", \"bar\")]] void C() {}\n  EXPECT_TRUE(Demangle(\"_Z1CB3barB3foov\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"C[abi:bar][abi:foo]()\", tmp);\n}\n\nTEST(Demangle, SimpleGnuVectorSize) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #define VECTOR(size) __attribute__((vector_size(size)))\n  // void f(int x VECTOR(32)) {}\n  //\n  // The attribute's size is a number of bytes.  The compiler verifies that this\n  // value corresponds to a whole number of elements and emits the number of\n  // elements as a <number> in the mangling.  With sizeof(int) == 4, that yields\n  // 32/4 = 8.\n  //\n  // LLVM demangling:\n  //\n  // f(int vector[8])\n  EXPECT_TRUE(Demangle(\"_Z1fDv8_i\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n}\n\nTEST(Demangle, GnuVectorSizeIsATemplateParameter) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #define VECTOR(size) __attribute__((vector_size(size)))\n  // template <int n> void f(int x VECTOR(n)) {}\n  // template void f<32>(int x VECTOR(32));\n  //\n  // LLVM demangling:\n  //\n  // void f<32>(int vector[32])\n  //\n  // Because the size was dependent on a template parameter, it was encoded\n  // using the general expression encoding.  Nothing in the mangling says how\n  // big the element type is, so the demangler is unable to show the element\n  // count 8 instead of the byte count 32.  Arguably it would have been better\n  // to make the narrow production encode the byte count, so that nondependent\n  // and dependent versions of a 32-byte vector would both come out as\n  // vector[32].\n  EXPECT_TRUE(Demangle(\"_Z1fILi32EEvDvT__i\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, GnuVectorSizeIsADependentOperatorExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #define VECTOR(size) __attribute__((vector_size(size)))\n  // template <int n> void f(int x VECTOR(2 * n)) {}\n  // template void f<32>(int x VECTOR(2 * 32));\n  //\n  // LLVM demangling:\n  //\n  // void f<32>(int vector[2 * 32])\n  EXPECT_TRUE(Demangle(\"_Z1fILi32EEvDvmlLi2ET__i\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, SimpleAddressSpace) {\n  char tmp[80];\n\n  // Source:\n  //\n  // void f(const int __attribute__((address_space(128)))*) {}\n  //\n  // LLVM demangling:\n  //\n  // f(int const AS128*)\n  //\n  // Itanium ABI 5.1.5.1, \"Qualified types\", notes that address_space is mangled\n  // nonuniformly as a legacy exception: the number is part of the source-name\n  // if nondependent but is an expression in template-args if dependent.  Thus\n  // it is a convenient test case for both forms.\n  EXPECT_TRUE(Demangle(\"_Z1fPU5AS128Ki\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n}\n\nTEST(Demangle, DependentAddressSpace) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <int n> void f (const int __attribute__((address_space(n)))*) {}\n  // template void f<128>(const int __attribute__((address_space(128)))*);\n  //\n  // LLVM demangling:\n  //\n  // void f<128>(int AS<128>*)\n  EXPECT_TRUE(Demangle(\"_Z1fILi128EEvPU2ASIT_Ei\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, TransactionSafeEntryPoint) {\n  char tmp[80];\n\n  EXPECT_TRUE(Demangle(\"_ZGTt1fv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"transaction clone for f()\", tmp);\n}\n\nTEST(Demangle, TransactionSafeFunctionType) {\n  char tmp[80];\n\n  // GNU demangling: f(void (*)() transaction_safe)\n  EXPECT_TRUE(Demangle(\"_Z1fPDxFvvE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n}\n\nTEST(Demangle, TemplateParameterObject) {\n  char tmp[80];\n\n  // Source:\n  //\n  // struct S { int x, y; };\n  // template <S s, const S* p = &s> void f() {}\n  // template void f<S{1, 2}>();\n  //\n  // LLVM demangling:\n  //\n  // void f<S{1, 2}, &template parameter object for S{1, 2}>()\n  EXPECT_TRUE(Demangle(\"_Z1fIXtl1SLi1ELi2EEEXadL_ZTAXtlS0_Li1ELi2EEEEEEvv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // The name of the object standing alone.\n  //\n  // LLVM demangling: template parameter object for S{1, 2}\n  EXPECT_TRUE(Demangle(\"_ZTAXtl1SLi1ELi2EEE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"template parameter object\", tmp);\n}\n\nTEST(Demangle, EnableIfAttributeOnGlobalFunction) {\n  char tmp[80];\n\n  // int f(long l) __attribute__((enable_if(l >= 0, \"\"))) { return l; }\n  //\n  // f(long) [enable_if:fp >= 0]\n  EXPECT_TRUE(Demangle(\"_Z1fUa9enable_ifIXgefL0p_Li0EEEl\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n}\n\nTEST(Demangle, EnableIfAttributeOnNamespaceScopeFunction) {\n  char tmp[80];\n\n  // namespace ns {\n  // int f(long l) __attribute__((enable_if(l >= 0, \"\"))) { return l; }\n  // }  // namespace ns\n  //\n  // ns::f(long) [enable_if:fp >= 0]\n  EXPECT_TRUE(Demangle(\"_ZN2ns1fEUa9enable_ifIXgefL0p_Li0EEEl\",\n              tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"ns::f()\", tmp);\n}\n\nTEST(Demangle, EnableIfAttributeOnFunctionTemplate) {\n  char tmp[80];\n\n  // template <class T>\n  // T f(T t) __attribute__((enable_if(t >= T{}, \"\"))) { return t; }\n  // template int f<int>(int);\n  //\n  // int f<int>(int) [enable_if:fp >= int{}]\n  EXPECT_TRUE(Demangle(\"_Z1fIiEUa9enable_ifIXgefL0p_tliEEET_S0_\",\n              tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ThisPointerInDependentSignature) {\n  char tmp[80];\n\n  // decltype(g<int>(this)) S::f<int>()\n  EXPECT_TRUE(Demangle(\"_ZN1S1fIiEEDTcl1gIT_EfpTEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::f<>()\", tmp);\n}\n\nTEST(Demangle, DependentMemberOperatorCall) {\n  char tmp[80];\n\n  // decltype(fp.operator()()) f<C>(C)\n  EXPECT_TRUE(Demangle(\"_Z1fI1CEDTcldtfp_onclEET_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, TypeNestedUnderDecltype) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> struct S { using t = int; };\n  // template <class T> decltype(S<T>{})::t f() { return {}; }\n  // void g() { f<int>(); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(S<int>{})::t f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiENDTtl1SIT_EEE1tEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ElaboratedTypes) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> struct S { class C {}; };\n  // template <class T> void f(class S<T>::C) {}\n  // template void f<int>(class S<int>::C);\n  //\n  // LLVM demangling:\n  //\n  // void f<int>(struct S<int>::C)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEvTsN1SIT_E1CE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // The like for unions.\n  EXPECT_TRUE(Demangle(\"_Z1fIiEvTuN1SIT_E1CE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // The like for enums.\n  EXPECT_TRUE(Demangle(\"_Z1fIiEvTeN1SIT_E1CE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\n// Test subobject-address template parameters.\nTEST(Demangle, SubobjectAddresses) {\n  char tmp[80];\n\n  // void f<a.<char const at offset 123>>()\n  EXPECT_TRUE(Demangle(\"_Z1fIXsoKcL_Z1aE123EEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // void f<&a.<char const at offset 0>>()\n  EXPECT_TRUE(Demangle(\"_Z1fIXadsoKcL_Z1aEEEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // void f<&a.<char const at offset 123>>()\n  EXPECT_TRUE(Demangle(\"_Z1fIXadsoKcL_Z1aE123EEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // void f<&a.<char const at offset 123>>(), past the end this time\n  EXPECT_TRUE(Demangle(\"_Z1fIXadsoKcL_Z1aE123pEEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // void f<&a.<char const at offset 0>>() with union-selectors\n  EXPECT_TRUE(Demangle(\"_Z1fIXadsoKcL_Z1aE__1_234EEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // void f<&a.<char const at offset 123>>(), past the end, with union-selector\n  EXPECT_TRUE(Demangle(\"_Z1fIXadsoKcL_Z1aE123_456pEEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, Preincrement) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T t) -> decltype(T{++t}) { return t; }\n  // template auto f<int>(int t) -> decltype(int{++t});\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{++fp}) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_pp_fp_EES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, Postincrement) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T t) -> decltype(T{t++}) { return t; }\n  // template auto f<int>(int t) -> decltype(int{t++});\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{fp++}) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_ppfp_EES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, Predecrement) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T t) -> decltype(T{--t}) { return t; }\n  // template auto f<int>(int t) -> decltype(int{--t});\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{--fp}) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_mm_fp_EES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, Postdecrement) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T t) -> decltype(T{t--}) { return t; }\n  // template auto f<int>(int t) -> decltype(int{t--});\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{fp--}) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_mmfp_EES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, UnaryFoldExpressions) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <bool b> struct S {};\n  //\n  // template <class... T> auto f(T... t) -> S<((sizeof(T) == 4) || ...)> {\n  //   return {};\n  // }\n  //\n  // void g() { f(1, 2L); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // S<((sizeof (int) == 4, sizeof (long) == 4) || ...)> f<int, long>(int, long)\n  EXPECT_TRUE(Demangle(\"_Z1fIJilEE1SIXfrooeqstT_Li4EEEDpS1_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // The like with a left fold.\n  //\n  // S<(... || (sizeof (int) == 4, sizeof (long) == 4))> f<int, long>(int, long)\n  EXPECT_TRUE(Demangle(\"_Z1fIJilEE1SIXflooeqstT_Li4EEEDpS1_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, BinaryFoldExpressions) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <bool b> struct S {};\n  //\n  // template <class... T> auto f(T... t)\n  //     -> S<((sizeof(T) == 4) || ... || false)> {\n  //   return {};\n  // }\n  //\n  // void g() { f(1, 2L); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // S<((sizeof (int) == 4, sizeof (long) == 4) || ... || false)>\n  // f<int, long>(int, long)\n  EXPECT_TRUE(Demangle(\"_Z1fIJilEE1SIXfRooeqstT_Li4ELb0EEEDpS1_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // The like with a left fold.\n  //\n  // S<(false || ... || (sizeof (int) == 4, sizeof (long) == 4))>\n  // f<int, long>(int, long)\n  EXPECT_TRUE(Demangle(\"_Z1fIJilEE1SIXfLooLb0EeqstT_Li4EEEDpS1_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, SizeofPacks) {\n  char tmp[80];\n\n  // template <size_t i> struct S {};\n  //\n  // template <class... T> auto f(T... p) -> S<sizeof...(T)> { return {}; }\n  // template auto f<int, long>(int, long) -> S<2>;\n  //\n  // template <class... T> auto g(T... p) -> S<sizeof...(p)> { return {}; }\n  // template auto g<int, long>(int, long) -> S<2>;\n\n  // S<sizeof...(int, long)> f<int, long>(int, long)\n  EXPECT_TRUE(Demangle(\"_Z1fIJilEE1SIXsZT_EEDpT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // S<sizeof... (fp)> g<int, long>(int, long)\n  EXPECT_TRUE(Demangle(\"_Z1gIJilEE1SIXsZfp_EEDpT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"g<>()\", tmp);\n}\n\nTEST(Demangle, SizeofPackInvolvingAnAliasTemplate) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class... T> using A = char[sizeof...(T)];\n  // template <class... U> void f(const A<U..., int>&) {}\n  // template void f<int>(const A<int, int>&);\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // void f<int>(char const (&) [sizeof... (int, int)])\n  EXPECT_TRUE(Demangle(\"_Z1fIJiEEvRAsPDpT_iE_Kc\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, UserDefinedLiteral) {\n  char tmp[80];\n\n  // Source:\n  //\n  // unsigned long long operator\"\"_lit(unsigned long long x) { return x; }\n  //\n  // LLVM demangling:\n  //\n  // operator\"\" _lit(unsigned long long)\n  EXPECT_TRUE(Demangle(\"_Zli4_lity\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"operator\\\"\\\" _lit()\", tmp);\n}\n\nTEST(Demangle, Spaceship) {\n  char tmp[80];\n\n  // #include <compare>\n  //\n  // struct S { auto operator<=>(const S&) const = default; };\n  // auto (S::*f) = &S::operator<=>;  // make sure S::operator<=> is emitted\n  //\n  // template <class T> auto g(T x, T y) -> decltype(x <=> y) {\n  //   return x <=> y;\n  // }\n  // template auto g<S>(S x, S y) -> decltype(x <=> y);\n\n  // S::operator<=>(S const&) const\n  EXPECT_TRUE(Demangle(\"_ZNK1SssERKS_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"S::operator<=>()\", tmp);\n\n  // decltype(fp <=> fp0) g<S>(S, S)\n  EXPECT_TRUE(Demangle(\"_Z1gI1SEDTssfp_fp0_ET_S2_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"g<>()\", tmp);\n}\n\nTEST(Demangle, CoAwait) {\n  char tmp[80];\n\n  // ns::Awaitable::operator co_await() const\n  EXPECT_TRUE(Demangle(\"_ZNK2ns9AwaitableawEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"ns::Awaitable::operator co_await()\", tmp);\n}\n\nTEST(Demangle, VendorExtendedExpressions) {\n  char tmp[80];\n\n  // void f<__e()>()\n  EXPECT_TRUE(Demangle(\"_Z1fIXu3__eEEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // void f<__e(int, long)>()\n  EXPECT_TRUE(Demangle(\"_Z1fIXu3__eilEEEvv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, DirectListInitialization) {\n  char tmp[80];\n\n  // template <class T> decltype(T{}) f() { return T{}; }\n  // template decltype(int{}) f<int>();\n  //\n  // struct XYZ { int x, y, z; };\n  // template <class T> decltype(T{1, 2, 3}) g() { return T{1, 2, 3}; }\n  // template decltype(XYZ{1, 2, 3}) g<XYZ>();\n  //\n  // template <class T> decltype(T{.x = 1, .y = 2, .z = 3}) h() {\n  //   return T{.x = 1, .y = 2, .z = 3};\n  // }\n  // template decltype(XYZ{.x = 1, .y = 2, .z = 3}) h<XYZ>();\n  //\n  // // The following two cases require full C99 designated initializers,\n  // // not part of C++ but likely available as an extension if you ask your\n  // // compiler nicely.\n  //\n  // struct A { int a[4]; };\n  // template <class T> decltype(T{.a[2] = 42}) i() { return T{.a[2] = 42}; }\n  // template decltype(A{.a[2] = 42}) i<A>();\n  //\n  // template <class T> decltype(T{.a[1 ... 3] = 42}) j() {\n  //   return T{.a[1 ... 3] = 42};\n  // }\n  // template decltype(A{.a[1 ... 3] = 42}) j<A>();\n\n  // decltype(int{}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_EEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // decltype(XYZ{1, 2, 3}) g<XYZ>()\n  EXPECT_TRUE(Demangle(\"_Z1gI3XYZEDTtlT_Li1ELi2ELi3EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"g<>()\", tmp);\n\n  // decltype(XYZ{.x = 1, .y = 2, .z = 3}) h<XYZ>()\n  EXPECT_TRUE(Demangle(\"_Z1hI3XYZEDTtlT_di1xLi1Edi1yLi2Edi1zLi3EEEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"h<>()\", tmp);\n\n  // decltype(A{.a[2] = 42}) i<A>()\n  EXPECT_TRUE(Demangle(\"_Z1iI1AEDTtlT_di1adxLi2ELi42EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"i<>()\", tmp);\n\n  // decltype(A{.a[1 ... 3] = 42}) j<A>()\n  EXPECT_TRUE(Demangle(\"_Z1jI1AEDTtlT_di1adXLi1ELi3ELi42EEEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"j<>()\", tmp);\n}\n\nTEST(Demangle, SimpleInitializerLists) {\n  char tmp[80];\n\n  // Common preamble of source-code examples in this test function:\n  //\n  // #include <initializer_list>\n  //\n  // template <class T> void g(std::initializer_list<T>) {}\n\n  // Source:\n  //\n  // template <class T> auto f() -> decltype(g<T>({})) {}\n  // template auto f<int>() -> decltype(g<int>({}));\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(g<int>({})) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTcl1gIT_EilEEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // Source:\n  //\n  // template <class T> auto f(T x) -> decltype(g({x})) {}\n  // template auto f<int>(int x) -> decltype(g({x}));\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(g({fp})) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTcl1gilfp_EEET_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // Source:\n  //\n  // template <class T> auto f(T x, T y) -> decltype(g({x, y})) {}\n  // template auto f<int>(int x, int y) -> decltype(g({x, y}));\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(g({fp, fp0})) f<int>(int, int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTcl1gilfp_fp0_EEET_S1_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, BracedListImplicitlyConstructingAClassObject) {\n  char tmp[80];\n\n  // Source:\n  //\n  // struct S { int v; };\n  // void g(S) {}\n  // template <class T> auto f(T x) -> decltype(g({.v = x})) {}\n  // template auto f<int>(int x) -> decltype(g({.v = x}));\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(g({.v = fp})) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTcl1gildi1vfp_EEET_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, SimpleNewExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T}) f() { return T{}; }\n  // template decltype(int{*new int}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new int)}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denw_S0_EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NewExpressionWithEmptyParentheses) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T()}) f() { return T{}; }\n  // template decltype(int{*new int()}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new int)}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denw_S0_piEEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NewExpressionWithNonemptyParentheses) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T(42)}) f() { return T{}; }\n  // template decltype(int{*new int(42)}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new int(42))}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denw_S0_piLi42EEEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, PlacementNewExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #include <new>\n  //\n  // template <class T> auto f(T t) -> decltype(T{*new (&t) T(42)}) {\n  //   return t;\n  // }\n  // template auto f<int>(int t) -> decltype(int{*new (&t) int(42)});\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new(&fp) int(42))}) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denwadfp__S0_piLi42EEEES0_\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, GlobalScopeNewExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*::new T}) f() { return T{}; }\n  // template decltype(int{*::new int}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(::new int)}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_degsnw_S0_EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NewExpressionWithEmptyBraces) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T{}}) f() { return T{}; }\n  // template decltype(int{*new int{}}) f<int>();\n  //\n  // GNU demangling:\n  //\n  // decltype (int{*(new int{})}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denw_S0_ilEEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NewExpressionWithNonemptyBraces) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T{42}}) f() { return T{}; }\n  // template decltype(int{*new int{42}}) f<int>();\n  //\n  // GNU demangling:\n  //\n  // decltype (int{*(new int{42})}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denw_S0_ilLi42EEEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, SimpleArrayNewExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T[1]}) f() { return T{}; }\n  // template decltype(int{*new int[1]}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new[] int)}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_dena_S0_EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ArrayNewExpressionWithEmptyParentheses) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T[1]()}) f() { return T{}; }\n  // template decltype(int{*new int[1]()}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new[] int)}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_dena_S0_piEEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ArrayPlacementNewExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #include <new>\n  //\n  // template <class T> auto f(T t) -> decltype(T{*new (&t) T[1]}) {\n  //   return T{};\n  // }\n  // template auto f<int>(int t) -> decltype(int{*new (&t) int[1]});\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(new[](&fp) int)}) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_denaadfp__S0_EEES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, GlobalScopeArrayNewExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*::new T[1]}) f() { return T{}; }\n  // template decltype(int{*::new int[1]}) f<int>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(int{*(::new[] int)}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_degsna_S0_EEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ArrayNewExpressionWithTwoElementsInBraces) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> decltype(T{*new T[2]{1, 2}}) f() { return T{}; }\n  // template decltype(int{*new int[2]{1, 2}}) f<int>();\n  //\n  // GNU demangling:\n  //\n  // decltype (int{*(new int{1, 2})}) f<int>()\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTtlT_dena_S0_ilLi1ELi2EEEEv\",\n                       tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, SimpleDeleteExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* p) -> decltype(delete p) {}\n  // template auto f<int>(int* p) -> decltype(delete p);\n  //\n  // LLVM demangling:\n  //\n  // decltype(delete fp) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTdlfp_EPT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, GlobalScopeDeleteExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* p) -> decltype(::delete p) {}\n  // template auto f<int>(int* p) -> decltype(::delete p);\n  //\n  // LLVM demangling:\n  //\n  // decltype(::delete fp) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTgsdlfp_EPT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, SimpleArrayDeleteExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* a) -> decltype(delete[] a) {}\n  // template auto f<int>(int* a) -> decltype(delete[] a);\n  //\n  // LLVM demangling:\n  //\n  // decltype(delete[] fp) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTdafp_EPT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, GlobalScopeArrayDeleteExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* a) -> decltype(::delete[] a) {}\n  // template auto f<int>(int* a) -> decltype(::delete[] a);\n  //\n  // LLVM demangling:\n  //\n  // decltype(::delete[] fp) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTgsdafp_EPT_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ReferenceQualifiedFunctionTypes) {\n  char tmp[80];\n\n  // void f(void (*)() const &, int)\n  EXPECT_TRUE(Demangle(\"_Z1fPKFvvREi\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n\n  // void f(void (*)() &&, int)\n  EXPECT_TRUE(Demangle(\"_Z1fPFvvOEi\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n\n  // void f(void (*)(int&) &, int)\n  EXPECT_TRUE(Demangle(\"_Z1fPFvRiREi\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n\n  // void f(void (*)(S&&) &&, int)\n  EXPECT_TRUE(Demangle(\"_Z1fPFvO1SOEi\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f()\", tmp);\n}\n\nTEST(Demangle, DynamicCast) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* p) -> decltype(dynamic_cast<const T*>(p)) {\n  //   return p;\n  // }\n  // struct S {};\n  // void g(S* p) { f(p); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(dynamic_cast<S const*>(fp)) f<S>(S*)\n  EXPECT_TRUE(Demangle(\"_Z1fI1SEDTdcPKT_fp_EPS1_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, StaticCast) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* p) -> decltype(static_cast<const T*>(p)) {\n  //   return p;\n  // }\n  // void g(int* p) { f(p); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(static_cast<int const*>(fp)) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTscPKT_fp_EPS0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ConstCast) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* p) -> decltype(const_cast<const T*>(p)) {\n  //   return p;\n  // }\n  // void g(int* p) { f(p); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(const_cast<int const*>(fp)) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTccPKT_fp_EPS0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ReinterpretCast) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> auto f(T* p)\n  //     -> decltype(reinterpret_cast<const T*>(p)) {\n  //   return p;\n  // }\n  // void g(int* p) { f(p); }\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(reinterpret_cast<int const*>(fp)) f<int>(int*)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTrcPKT_fp_EPS0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, TypeidType) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #include <typeinfo>\n  //\n  // template <class T> decltype(typeid(T).name()) f(T) { return nullptr; }\n  // template decltype(typeid(int).name()) f<int>(int);\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(typeid (int).name()) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTcldttiT_4nameEES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, TypeidExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // #include <typeinfo>\n  //\n  // template <class T> decltype(typeid(T{}).name()) f(T) { return nullptr; }\n  // template decltype(typeid(int{}).name()) f<int>(int);\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(typeid (int{}).name()) f<int>(int)\n  EXPECT_TRUE(Demangle(\"_Z1fIiEDTcldttetlT_E4nameEES0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, AlignofType) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> T f(T (&a)[alignof(T)]) { return a[0]; }\n  // template int f<int>(int (&)[alignof(int)]);\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // int f<int>(int (&) [alignof (int)])\n  EXPECT_TRUE(Demangle(\"_Z1fIiET_RAatS0__S0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, AlignofExpression) {\n  char tmp[80];\n\n  // Source (note that this uses a GNU extension; it is not standard C++):\n  //\n  // template <class T> T f(T (&a)[alignof(T{})]) { return a[0]; }\n  // template int f<int>(int (&)[alignof(int{})]);\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // int f<int>(int (&) [alignof (int{})])\n  EXPECT_TRUE(Demangle(\"_Z1fIiET_RAaztlS0_E_S0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NoexceptExpression) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <class T> void f(T (&a)[noexcept(T{})]) {}\n  // template void f<int>(int (&)[noexcept(int{})]);\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // void f<int>(int (&) [noexcept (int{})])\n  EXPECT_TRUE(Demangle(\"_Z1fIiEvRAnxtlT_E_S0_\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, UnaryThrow) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <bool b> decltype(b ? throw b : 0) f() { return 0; }\n  // template decltype(false ? throw false : 0) f<false>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(false ? throw false : 0) f<false>()\n  EXPECT_TRUE(Demangle(\"_Z1fILb0EEDTquT_twT_Li0EEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, NullaryThrow) {\n  char tmp[80];\n\n  // Source:\n  //\n  // template <bool b> decltype(b ? throw : 0) f() { return 0; }\n  // template decltype(false ? throw : 0) f<false>();\n  //\n  // Full LLVM demangling of the instantiation of f:\n  //\n  // decltype(false ? throw : 0) f<false>()\n  EXPECT_TRUE(Demangle(\"_Z1fILb0EEDTquT_trLi0EEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n}\n\nTEST(Demangle, ThreadLocalWrappers) {\n  char tmp[80];\n\n  EXPECT_TRUE(Demangle(\"_ZTWN2ns3varE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"thread-local wrapper routine for ns::var\", tmp);\n\n  EXPECT_TRUE(Demangle(\"_ZTHN2ns3varE\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"thread-local initialization routine for ns::var\", tmp);\n}\n\nTEST(Demangle, DubiousSrStSymbols) {\n  char tmp[80];\n\n  // GNU demangling (not accepted by LLVM):\n  //\n  // S<std::u<char>::v> f<char>()\n  EXPECT_TRUE(Demangle(\"_Z1fIcE1SIXsrSt1uIT_E1vEEv\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"f<>()\", tmp);\n\n  // A real case from the wild.\n  //\n  // GNU demangling (not accepted by LLVM) with line breaks and indentation\n  // added for readability:\n  //\n  // __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type\n  // std::operator==<char>(\n  //     std::__cxx11::basic_string<char, std::char_traits<char>,\n  //                                std::allocator<char> > const&,\n  //     std::__cxx11::basic_string<char, std::char_traits<char>,\n  //                                std::allocator<char> > const&)\n  EXPECT_TRUE(Demangle(\n      \"_ZSteqIcEN9__gnu_cxx11__enable_if\"\n      \"IXsrSt9__is_charIT_E7__valueEbE\"\n      \"6__typeE\"\n      \"RKNSt7__cxx1112basic_stringIS3_St11char_traitsIS3_ESaIS3_EEESE_\",\n      tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"std::operator==<>()\", tmp);\n}\n\n// Test one Rust symbol to exercise Demangle's delegation path.  Rust demangling\n// itself is more thoroughly tested in demangle_rust_test.cc.\nTEST(Demangle, DelegatesToDemangleRustSymbolEncoding) {\n  char tmp[80];\n\n  EXPECT_TRUE(Demangle(\"_RNvC8my_crate7my_func\", tmp, sizeof(tmp)));\n  EXPECT_STREQ(\"my_crate::my_func\", tmp);\n}\n\n// Tests that verify that Demangle footprint is within some limit.\n// They are not to be run under sanitizers as the sanitizers increase\n// stack consumption by about 4x.\n#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \\\n    !defined(ABSL_HAVE_ADDRESS_SANITIZER) &&                   \\\n    !defined(ABSL_HAVE_MEMORY_SANITIZER) &&                    \\\n    !defined(ABSL_HAVE_THREAD_SANITIZER)\n\nstatic const char *g_mangled;\nstatic char g_demangle_buffer[4096];\nstatic char *g_demangle_result;\n\nstatic void DemangleSignalHandler(int signo) {\n  if (Demangle(g_mangled, g_demangle_buffer, sizeof(g_demangle_buffer))) {\n    g_demangle_result = g_demangle_buffer;\n  } else {\n    g_demangle_result = nullptr;\n  }\n}\n\n// Call Demangle and figure out the stack footprint of this call.\nstatic const char *DemangleStackConsumption(const char *mangled,\n                                            int *stack_consumed) {\n  g_mangled = mangled;\n  *stack_consumed = GetSignalHandlerStackConsumption(DemangleSignalHandler);\n  LOG(INFO) << \"Stack consumption of Demangle: \" << *stack_consumed;\n  return g_demangle_result;\n}\n\n// Demangle stack consumption should be within 9kB for simple mangled names\n// with some level of nesting. With alternate signal stack we have 64K,\n// but some signal handlers run on thread stack, and could have arbitrarily\n// little space left (so we don't want to make this number too large).\nconst int kStackConsumptionUpperLimit = 9670;\n\n// Returns a mangled name nested to the given depth.\nstatic std::string NestedMangledName(int depth) {\n  std::string mangled_name = \"_Z1a\";\n  if (depth > 0) {\n    mangled_name += \"IXL\";\n    mangled_name += NestedMangledName(depth - 1);\n    mangled_name += \"EEE\";\n  }\n  return mangled_name;\n}\n\nTEST(Demangle, DemangleStackConsumption) {\n  // Measure stack consumption of Demangle for nested mangled names of varying\n  // depth.  Since Demangle is implemented as a recursive descent parser,\n  // stack consumption will grow as the nesting depth increases.  By measuring\n  // the stack consumption for increasing depths, we can see the growing\n  // impact of any stack-saving changes made to the code for Demangle.\n  int stack_consumed = 0;\n\n  const char *demangled =\n      DemangleStackConsumption(\"_Z6foobarv\", &stack_consumed);\n  EXPECT_STREQ(\"foobar()\", demangled);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);\n\n  const std::string nested_mangled_name0 = NestedMangledName(0);\n  demangled = DemangleStackConsumption(nested_mangled_name0.c_str(),\n                                       &stack_consumed);\n  EXPECT_STREQ(\"a\", demangled);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);\n\n  const std::string nested_mangled_name1 = NestedMangledName(1);\n  demangled = DemangleStackConsumption(nested_mangled_name1.c_str(),\n                                       &stack_consumed);\n  EXPECT_STREQ(\"a<>\", demangled);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);\n\n  const std::string nested_mangled_name2 = NestedMangledName(2);\n  demangled = DemangleStackConsumption(nested_mangled_name2.c_str(),\n                                       &stack_consumed);\n  EXPECT_STREQ(\"a<>\", demangled);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);\n\n  const std::string nested_mangled_name3 = NestedMangledName(3);\n  demangled = DemangleStackConsumption(nested_mangled_name3.c_str(),\n                                       &stack_consumed);\n  EXPECT_STREQ(\"a<>\", demangled);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);\n}\n\n#endif  // Stack consumption tests\n\nstatic void TestOnInput(const char* input) {\n  static const int kOutSize = 1048576;\n  auto out = absl::make_unique<char[]>(kOutSize);\n  Demangle(input, out.get(), kOutSize);\n}\n\nTEST(DemangleRegression, NegativeLength) {\n  TestOnInput(\"_ZZn4\");\n}\n\nTEST(DemangleRegression, DeeplyNestedArrayType) {\n  const int depth = 100000;\n  std::string data = \"_ZStI\";\n  data.reserve(data.size() + 3 * depth + 1);\n  for (int i = 0; i < depth; i++) {\n    data += \"A1_\";\n  }\n  TestOnInput(data.c_str());\n}\n\nTEST(DemangleRegression, ShortOutputBuffer) {\n  // This should not crash.\n  char buffer[1];\n  EXPECT_FALSE(\n      absl::debugging_internal::Demangle(\"_ZZ2wwE\", buffer, sizeof(buffer)));\n}\n\nstruct Base {\n  virtual ~Base() = default;\n};\n\nstruct Derived : public Base {};\n\nTEST(DemangleStringTest, SupportsSymbolNameReturnedByTypeId) {\n  EXPECT_EQ(DemangleString(typeid(int).name()), \"int\");\n  // We want to test that `DemangleString` can demangle the symbol names\n  // returned by `typeid`, but without hard-coding the actual demangled values\n  // (because they are platform-specific).\n  EXPECT_THAT(\n      DemangleString(typeid(Base).name()),\n      ContainsRegex(\"absl.*debugging_internal.*anonymous namespace.*::Base\"));\n  EXPECT_THAT(DemangleString(typeid(Derived).name()),\n              ContainsRegex(\n                  \"absl.*debugging_internal.*anonymous namespace.*::Derived\"));\n}\n\n}  // namespace\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/elf_mem_image.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Allow dynamic symbol lookup in an in-memory Elf image.\n//\n\n#include \"absl/debugging/internal/elf_mem_image.h\"\n\n#ifdef ABSL_HAVE_ELF_MEM_IMAGE  // defined in elf_mem_image.h\n\n#include <string.h>\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\n// From binutils/include/elf/common.h (this doesn't appear to be documented\n// anywhere else).\n//\n//   /* This flag appears in a Versym structure.  It means that the symbol\n//      is hidden, and is only visible with an explicit version number.\n//      This is a GNU extension.  */\n//   #define VERSYM_HIDDEN           0x8000\n//\n//   /* This is the mask for the rest of the Versym information.  */\n//   #define VERSYM_VERSION          0x7fff\n\n#define VERSYM_VERSION 0x7fff\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nnamespace {\n\n#if __SIZEOF_POINTER__ == 4\nconst int kElfClass = ELFCLASS32;\nint ElfBind(const ElfW(Sym) *symbol) { return ELF32_ST_BIND(symbol->st_info); }\nint ElfType(const ElfW(Sym) *symbol) { return ELF32_ST_TYPE(symbol->st_info); }\n#elif __SIZEOF_POINTER__ == 8\nconst int kElfClass = ELFCLASS64;\nint ElfBind(const ElfW(Sym) *symbol) { return ELF64_ST_BIND(symbol->st_info); }\nint ElfType(const ElfW(Sym) *symbol) { return ELF64_ST_TYPE(symbol->st_info); }\n#else\nconst int kElfClass = -1;\nint ElfBind(const ElfW(Sym) *) {\n  ABSL_RAW_LOG(FATAL, \"Unexpected word size\");\n  return 0;\n}\nint ElfType(const ElfW(Sym) *) {\n  ABSL_RAW_LOG(FATAL, \"Unexpected word size\");\n  return 0;\n}\n#endif\n\n// Extract an element from one of the ELF tables, cast it to desired type.\n// This is just a simple arithmetic and a glorified cast.\n// Callers are responsible for bounds checking.\ntemplate <typename T>\nconst T *GetTableElement(const ElfW(Ehdr) * ehdr, ElfW(Off) table_offset,\n                         ElfW(Word) element_size, size_t index) {\n  return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr)\n                                    + table_offset\n                                    + index * element_size);\n}\n\n}  // namespace\n\n// The value of this variable doesn't matter; it's used only for its\n// unique address.\nconst int ElfMemImage::kInvalidBaseSentinel = 0;\n\nElfMemImage::ElfMemImage(const void *base) {\n  ABSL_RAW_CHECK(base != kInvalidBase, \"bad pointer\");\n  Init(base);\n}\n\nuint32_t ElfMemImage::GetNumSymbols() const { return num_syms_; }\n\nconst ElfW(Sym) * ElfMemImage::GetDynsym(uint32_t index) const {\n  ABSL_RAW_CHECK(index < GetNumSymbols(), \"index out of range\");\n  return dynsym_ + index;\n}\n\nconst ElfW(Versym) *ElfMemImage::GetVersym(uint32_t index) const {\n  ABSL_RAW_CHECK(index < GetNumSymbols(), \"index out of range\");\n  return versym_ + index;\n}\n\nconst ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const {\n  ABSL_RAW_CHECK(index >= 0 && index < ehdr_->e_phnum, \"index out of range\");\n  return GetTableElement<ElfW(Phdr)>(ehdr_, ehdr_->e_phoff, ehdr_->e_phentsize,\n                                     static_cast<size_t>(index));\n}\n\nconst char *ElfMemImage::GetDynstr(ElfW(Word) offset) const {\n  ABSL_RAW_CHECK(offset < strsize_, \"offset out of range\");\n  return dynstr_ + offset;\n}\n\nconst void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const {\n  if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) {\n    // Symbol corresponds to \"special\" (e.g. SHN_ABS) section.\n    return reinterpret_cast<const void *>(sym->st_value);\n  }\n  ABSL_RAW_CHECK(link_base_ < sym->st_value, \"symbol out of range\");\n  return GetTableElement<char>(ehdr_, 0, 1, sym->st_value - link_base_);\n}\n\nconst ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const {\n  ABSL_RAW_CHECK(0 <= index && static_cast<size_t>(index) <= verdefnum_,\n                 \"index out of range\");\n  const ElfW(Verdef) *version_definition = verdef_;\n  while (version_definition->vd_ndx < index && version_definition->vd_next) {\n    const char *const version_definition_as_char =\n        reinterpret_cast<const char *>(version_definition);\n    version_definition =\n        reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char +\n                                               version_definition->vd_next);\n  }\n  return version_definition->vd_ndx == index ? version_definition : nullptr;\n}\n\nconst ElfW(Verdaux) *ElfMemImage::GetVerdefAux(\n    const ElfW(Verdef) *verdef) const {\n  return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1);\n}\n\nconst char *ElfMemImage::GetVerstr(ElfW(Word) offset) const {\n  ABSL_RAW_CHECK(offset < strsize_, \"offset out of range\");\n  return dynstr_ + offset;\n}\n\nvoid ElfMemImage::Init(const void *base) {\n  ehdr_      = nullptr;\n  dynsym_    = nullptr;\n  dynstr_    = nullptr;\n  versym_    = nullptr;\n  verdef_    = nullptr;\n  num_syms_ = 0;\n  strsize_   = 0;\n  verdefnum_ = 0;\n  // Sentinel: PT_LOAD .p_vaddr can't possibly be this.\n  link_base_ = ~ElfW(Addr){0};  // NOLINT(readability/braces)\n  if (!base) {\n    return;\n  }\n  const char *const base_as_char = reinterpret_cast<const char *>(base);\n  if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 ||\n      base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) {\n    assert(false);\n    return;\n  }\n  int elf_class = base_as_char[EI_CLASS];\n  if (elf_class != kElfClass) {\n    assert(false);\n    return;\n  }\n  switch (base_as_char[EI_DATA]) {\n    case ELFDATA2LSB: {\n#ifndef ABSL_IS_LITTLE_ENDIAN\n      assert(false);\n      return;\n#endif\n      break;\n    }\n    case ELFDATA2MSB: {\n#ifndef ABSL_IS_BIG_ENDIAN\n      assert(false);\n      return;\n#endif\n      break;\n    }\n    default: {\n      assert(false);\n      return;\n    }\n  }\n\n  ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base);\n  const ElfW(Phdr) *dynamic_program_header = nullptr;\n  for (int i = 0; i < ehdr_->e_phnum; ++i) {\n    const ElfW(Phdr) *const program_header = GetPhdr(i);\n    switch (program_header->p_type) {\n      case PT_LOAD:\n        if (!~link_base_) {\n          link_base_ = program_header->p_vaddr;\n        }\n        break;\n      case PT_DYNAMIC:\n        dynamic_program_header = program_header;\n        break;\n    }\n  }\n  if (!~link_base_ || !dynamic_program_header) {\n    assert(false);\n    // Mark this image as not present. Can not recur infinitely.\n    Init(nullptr);\n    return;\n  }\n  ptrdiff_t relocation =\n      base_as_char - reinterpret_cast<const char *>(link_base_);\n  ElfW(Dyn)* dynamic_entry = reinterpret_cast<ElfW(Dyn)*>(\n      static_cast<intptr_t>(dynamic_program_header->p_vaddr) + relocation);\n  uint32_t *sysv_hash = nullptr;\n  uint32_t *gnu_hash = nullptr;\n  for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {\n    const auto value =\n        static_cast<intptr_t>(dynamic_entry->d_un.d_val) + relocation;\n    switch (dynamic_entry->d_tag) {\n      case DT_HASH:\n        sysv_hash = reinterpret_cast<uint32_t *>(value);\n        break;\n      case DT_GNU_HASH:\n        gnu_hash = reinterpret_cast<uint32_t *>(value);\n        break;\n      case DT_SYMTAB:\n        dynsym_ = reinterpret_cast<ElfW(Sym) *>(value);\n        break;\n      case DT_STRTAB:\n        dynstr_ = reinterpret_cast<const char *>(value);\n        break;\n      case DT_VERSYM:\n        versym_ = reinterpret_cast<ElfW(Versym) *>(value);\n        break;\n      case DT_VERDEF:\n        verdef_ = reinterpret_cast<ElfW(Verdef) *>(value);\n        break;\n      case DT_VERDEFNUM:\n        verdefnum_ = static_cast<size_t>(dynamic_entry->d_un.d_val);\n        break;\n      case DT_STRSZ:\n        strsize_ = static_cast<size_t>(dynamic_entry->d_un.d_val);\n        break;\n      default:\n        // Unrecognized entries explicitly ignored.\n        break;\n    }\n  }\n  if ((!sysv_hash && !gnu_hash) || !dynsym_ || !dynstr_ || !versym_ ||\n      !verdef_ || !verdefnum_ || !strsize_) {\n    assert(false);  // invalid VDSO\n    // Mark this image as not present. Can not recur infinitely.\n    Init(nullptr);\n    return;\n  }\n  if (sysv_hash) {\n    num_syms_ = sysv_hash[1];\n  } else {\n    assert(gnu_hash);\n    // Compute the number of symbols for DT_GNU_HASH, which is specified by\n    // https://sourceware.org/gnu-gabi/program-loading-and-dynamic-linking.txt\n    uint32_t nbuckets = gnu_hash[0];\n    // The buckets array is located after the header (4 uint32) and the bloom\n    // filter (size_t array of gnu_hash[2] elements).\n    uint32_t *buckets = gnu_hash + 4 + sizeof(size_t) / 4 * gnu_hash[2];\n    // Find the chain of the last non-empty bucket.\n    uint32_t idx = 0;\n    for (uint32_t i = nbuckets; i > 0;) {\n      idx = buckets[--i];\n      if (idx != 0) break;\n    }\n    if (idx != 0) {\n      // Find the last element of the chain, which has an odd value.\n      // Add one to get the number of symbols.\n      uint32_t *chain = buckets + nbuckets - gnu_hash[1];\n      while (chain[idx++] % 2 == 0) {\n      }\n    }\n    num_syms_ = idx;\n  }\n}\n\nbool ElfMemImage::LookupSymbol(const char *name,\n                               const char *version,\n                               int type,\n                               SymbolInfo *info_out) const {\n  for (const SymbolInfo& info : *this) {\n    if (strcmp(info.name, name) == 0 && strcmp(info.version, version) == 0 &&\n        ElfType(info.symbol) == type) {\n      if (info_out) {\n        *info_out = info;\n      }\n      return true;\n    }\n  }\n  return false;\n}\n\nbool ElfMemImage::LookupSymbolByAddress(const void *address,\n                                        SymbolInfo *info_out) const {\n  for (const SymbolInfo& info : *this) {\n    const char *const symbol_start =\n        reinterpret_cast<const char *>(info.address);\n    const char *const symbol_end = symbol_start + info.symbol->st_size;\n    if (symbol_start <= address && address < symbol_end) {\n      if (info_out) {\n        // Client wants to know details for that symbol (the usual case).\n        if (ElfBind(info.symbol) == STB_GLOBAL) {\n          // Strong symbol; just return it.\n          *info_out = info;\n          return true;\n        } else {\n          // Weak or local. Record it, but keep looking for a strong one.\n          *info_out = info;\n        }\n      } else {\n        // Client only cares if there is an overlapping symbol.\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nElfMemImage::SymbolIterator::SymbolIterator(const void *const image,\n                                            uint32_t index)\n    : index_(index), image_(image) {}\n\nconst ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const {\n  return &info_;\n}\n\nconst ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const {\n  return info_;\n}\n\nbool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const {\n  return this->image_ == rhs.image_ && this->index_ == rhs.index_;\n}\n\nbool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const {\n  return !(*this == rhs);\n}\n\nElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() {\n  this->Update(1);\n  return *this;\n}\n\nElfMemImage::SymbolIterator ElfMemImage::begin() const {\n  SymbolIterator it(this, 0);\n  it.Update(0);\n  return it;\n}\n\nElfMemImage::SymbolIterator ElfMemImage::end() const {\n  return SymbolIterator(this, GetNumSymbols());\n}\n\nvoid ElfMemImage::SymbolIterator::Update(uint32_t increment) {\n  const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_);\n  ABSL_RAW_CHECK(image->IsPresent() || increment == 0, \"\");\n  if (!image->IsPresent()) {\n    return;\n  }\n  index_ += increment;\n  if (index_ >= image->GetNumSymbols()) {\n    index_ = image->GetNumSymbols();\n    return;\n  }\n  const ElfW(Sym)    *symbol = image->GetDynsym(index_);\n  const ElfW(Versym) *version_symbol = image->GetVersym(index_);\n  ABSL_RAW_CHECK(symbol && version_symbol, \"\");\n  const char *const symbol_name = image->GetDynstr(symbol->st_name);\n#if defined(__NetBSD__)\n  const int version_index = version_symbol->vs_vers & VERSYM_VERSION;\n#else\n  const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION;\n#endif\n  const ElfW(Verdef) *version_definition = nullptr;\n  const char *version_name = \"\";\n  if (symbol->st_shndx == SHN_UNDEF) {\n    // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and\n    // version_index could well be greater than verdefnum_, so calling\n    // GetVerdef(version_index) may trigger assertion.\n  } else {\n    version_definition = image->GetVerdef(version_index);\n  }\n  if (version_definition) {\n    // I am expecting 1 or 2 auxiliary entries: 1 for the version itself,\n    // optional 2nd if the version has a parent.\n    ABSL_RAW_CHECK(\n        version_definition->vd_cnt == 1 || version_definition->vd_cnt == 2,\n        \"wrong number of entries\");\n    const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition);\n    version_name = image->GetVerstr(version_aux->vda_name);\n  }\n  info_.name    = symbol_name;\n  info_.version = version_name;\n  info_.address = image->GetSymAddr(symbol);\n  info_.symbol  = symbol;\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HAVE_ELF_MEM_IMAGE\n"
  },
  {
    "path": "absl/debugging/internal/elf_mem_image.h",
    "content": "/*\n * Copyright 2017 The Abseil Authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Allow dynamic symbol lookup for in-memory Elf images.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_\n#define ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_\n\n// Including this will define the __GLIBC__ macro if glibc is being\n// used.\n#include <climits>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\n// Maybe one day we can rewrite this file not to require the elf\n// symbol extensions in glibc, but for right now we need them.\n#ifdef ABSL_HAVE_ELF_MEM_IMAGE\n#error ABSL_HAVE_ELF_MEM_IMAGE cannot be directly set\n#endif\n\n#if defined(__ELF__) && !defined(__OpenBSD__) && !defined(__QNX__) &&    \\\n    !defined(__asmjs__) && !defined(__wasm__) && !defined(__HAIKU__) &&  \\\n    !defined(__sun) && !defined(__VXWORKS__) && !defined(__hexagon__) && \\\n    !defined(__XTENSA__)\n#define ABSL_HAVE_ELF_MEM_IMAGE 1\n#endif\n\n#ifdef ABSL_HAVE_ELF_MEM_IMAGE\n\n#include <link.h>  // for ElfW\n\n#if defined(__FreeBSD__) && !defined(ElfW)\n#define ElfW(x) __ElfN(x)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// An in-memory ELF image (may not exist on disk).\nclass ElfMemImage {\n private:\n  // Sentinel: there could never be an elf image at &kInvalidBaseSentinel.\n  static const int kInvalidBaseSentinel;\n\n public:\n  // Sentinel: there could never be an elf image at this address.\n  static constexpr const void *const kInvalidBase =\n    static_cast<const void*>(&kInvalidBaseSentinel);\n\n  // Information about a single vdso symbol.\n  // All pointers are into .dynsym, .dynstr, or .text of the VDSO.\n  // Do not free() them or modify through them.\n  struct SymbolInfo {\n    const char      *name;      // E.g. \"__vdso_getcpu\"\n    const char      *version;   // E.g. \"LINUX_2.6\", could be \"\"\n                                // for unversioned symbol.\n    const void      *address;   // Relocated symbol address.\n    const ElfW(Sym) *symbol;    // Symbol in the dynamic symbol table.\n  };\n\n  // Supports iteration over all dynamic symbols.\n  class SymbolIterator {\n   public:\n    friend class ElfMemImage;\n    const SymbolInfo *operator->() const;\n    const SymbolInfo &operator*() const;\n    SymbolIterator& operator++();\n    bool operator!=(const SymbolIterator &rhs) const;\n    bool operator==(const SymbolIterator &rhs) const;\n   private:\n    SymbolIterator(const void *const image, uint32_t index);\n    void Update(uint32_t incr);\n    SymbolInfo info_;\n    uint32_t index_;\n    const void *const image_;\n  };\n\n\n  explicit ElfMemImage(const void *base);\n  void                 Init(const void *base);\n  bool                 IsPresent() const { return ehdr_ != nullptr; }\n  const ElfW(Phdr)*    GetPhdr(int index) const;\n  const ElfW(Sym) * GetDynsym(uint32_t index) const;\n  const ElfW(Versym)*  GetVersym(uint32_t index) const;\n  const ElfW(Verdef)*  GetVerdef(int index) const;\n  const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const;\n  const char*          GetDynstr(ElfW(Word) offset) const;\n  const void*          GetSymAddr(const ElfW(Sym) *sym) const;\n  const char*          GetVerstr(ElfW(Word) offset) const;\n  uint32_t GetNumSymbols() const;\n\n  SymbolIterator begin() const;\n  SymbolIterator end() const;\n\n  // Look up versioned dynamic symbol in the image.\n  // Returns false if image is not present, or doesn't contain given\n  // symbol/version/type combination.\n  // If info_out is non-null, additional details are filled in.\n  bool LookupSymbol(const char *name, const char *version,\n                    int symbol_type, SymbolInfo *info_out) const;\n\n  // Find info about symbol (if any) which overlaps given address.\n  // Returns true if symbol was found; false if image isn't present\n  // or doesn't have a symbol overlapping given address.\n  // If info_out is non-null, additional details are filled in.\n  bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const;\n\n private:\n  const ElfW(Ehdr) *ehdr_;\n  const ElfW(Sym) *dynsym_;\n  const ElfW(Versym) *versym_;\n  const ElfW(Verdef) *verdef_;\n  const char *dynstr_;\n  uint32_t num_syms_;\n  size_t strsize_;\n  size_t verdefnum_;\n  ElfW(Addr) link_base_;     // Link-time base (p_vaddr of first PT_LOAD).\n};\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HAVE_ELF_MEM_IMAGE\n\n#endif  // ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_\n"
  },
  {
    "path": "absl/debugging/internal/examine_stack.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#include \"absl/debugging/internal/examine_stack.h\"\n\n#ifndef _WIN32\n#include <unistd.h>\n#endif\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_HAVE_MMAP\n#include <sys/mman.h>\n#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n#endif\n\n#if defined(__linux__) || defined(__APPLE__)\n#include <sys/ucontext.h>\n#endif\n\n#include <csignal>\n#include <cstdio>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/symbolize.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nnamespace {\nconstexpr int kDefaultDumpStackFramesLimit = 64;\n// The %p field width for printf() functions is two characters per byte,\n// and two extra for the leading \"0x\".\nconstexpr int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);\n\nABSL_CONST_INIT SymbolizeUrlEmitter debug_stack_trace_hook = nullptr;\n\n// Async-signal safe mmap allocator.\nvoid* Allocate(size_t num_bytes) {\n#ifdef ABSL_HAVE_MMAP\n  void* p = ::mmap(nullptr, num_bytes, PROT_READ | PROT_WRITE,\n                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  return p == MAP_FAILED ? nullptr : p;\n#else\n  (void)num_bytes;\n  return nullptr;\n#endif  // ABSL_HAVE_MMAP\n}\n\nvoid Deallocate(void* p, size_t size) {\n#ifdef ABSL_HAVE_MMAP\n  ::munmap(p, size);\n#else\n  (void)p;\n  (void)size;\n#endif  // ABSL_HAVE_MMAP\n}\n\n// Print a program counter only.\nvoid DumpPC(OutputWriter* writer, void* writer_arg, void* const pc,\n            const char* const prefix) {\n  char buf[100];\n  snprintf(buf, sizeof(buf), \"%s@ %*p\\n\", prefix, kPrintfPointerFieldWidth, pc);\n  writer(buf, writer_arg);\n}\n\n// Print a program counter and the corresponding stack frame size.\nvoid DumpPCAndFrameSize(OutputWriter* writer, void* writer_arg, void* const pc,\n                        int framesize, const char* const prefix) {\n  char buf[100];\n  if (framesize <= 0) {\n    snprintf(buf, sizeof(buf), \"%s@ %*p  (unknown)\\n\", prefix,\n             kPrintfPointerFieldWidth, pc);\n  } else {\n    snprintf(buf, sizeof(buf), \"%s@ %*p  %9d\\n\", prefix,\n             kPrintfPointerFieldWidth, pc, framesize);\n  }\n  writer(buf, writer_arg);\n}\n\n// Print a program counter and the corresponding symbol.\nvoid DumpPCAndSymbol(OutputWriter* writer, void* writer_arg, void* const pc,\n                     const char* const prefix) {\n  char tmp[1024];\n  const char* symbol = \"(unknown)\";\n  // Symbolizes the previous address of pc because pc may be in the\n  // next function.  The overrun happens when the function ends with\n  // a call to a function annotated noreturn (e.g. CHECK).\n  // If symbolization of pc-1 fails, also try pc on the off-chance\n  // that we crashed on the first instruction of a function (that\n  // actually happens very often for e.g. __restore_rt).\n  const uintptr_t prev_pc = reinterpret_cast<uintptr_t>(pc) - 1;\n  if (absl::Symbolize(reinterpret_cast<const char*>(prev_pc), tmp,\n                      sizeof(tmp)) ||\n      absl::Symbolize(pc, tmp, sizeof(tmp))) {\n    symbol = tmp;\n  }\n  char buf[1024];\n  snprintf(buf, sizeof(buf), \"%s@ %*p  %s\\n\", prefix, kPrintfPointerFieldWidth,\n           pc, symbol);\n  writer(buf, writer_arg);\n}\n\n// Print a program counter, its stack frame size, and its symbol name.\n// Note that there is a separate symbolize_pc argument. Return addresses may be\n// at the end of the function, and this allows the caller to back up from pc if\n// appropriate.\nvoid DumpPCAndFrameSizeAndSymbol(OutputWriter* writer, void* writer_arg,\n                                 void* const pc, void* const symbolize_pc,\n                                 int framesize, const char* const prefix) {\n  char tmp[1024];\n  const char* symbol = \"(unknown)\";\n  if (absl::Symbolize(symbolize_pc, tmp, sizeof(tmp))) {\n    symbol = tmp;\n  }\n  char buf[1024];\n  if (framesize <= 0) {\n    snprintf(buf, sizeof(buf), \"%s@ %*p  (unknown)  %s\\n\", prefix,\n             kPrintfPointerFieldWidth, pc, symbol);\n  } else {\n    snprintf(buf, sizeof(buf), \"%s@ %*p  %9d  %s\\n\", prefix,\n             kPrintfPointerFieldWidth, pc, framesize, symbol);\n  }\n  writer(buf, writer_arg);\n}\n\nvoid DebugStackTraceHookLegacyAdapter(void* const stack[], int depth,\n                                      OutputWriter* writer, void* writer_arg) {\n  debug_stack_trace_hook(stack, depth, /*crash_pc=*/nullptr, writer,\n                         writer_arg);\n}\n\n}  // namespace\n\nvoid RegisterDebugStackTraceHook(SymbolizeUrlEmitter hook) {\n  debug_stack_trace_hook = hook;\n}\n\nSymbolizeUrlEmitterLegacy GetDebugStackTraceHookLegacy() {\n  if (debug_stack_trace_hook == nullptr) {\n    // No prior call to RegisterDebugStackTraceHook.\n    return nullptr;\n  }\n  return &DebugStackTraceHookLegacyAdapter;\n}\n\nSymbolizeUrlEmitter GetDebugStackTraceHook() { return debug_stack_trace_hook; }\n\n// Returns the program counter from signal context, nullptr if\n// unknown. vuc is a ucontext_t*. We use void* to avoid the use of\n// ucontext_t on non-POSIX systems.\nvoid* GetProgramCounter(void* const vuc) {\n#ifdef __linux__\n  if (vuc != nullptr) {\n    ucontext_t* context = reinterpret_cast<ucontext_t*>(vuc);\n#if defined(__aarch64__)\n    return reinterpret_cast<void*>(context->uc_mcontext.pc);\n#elif defined(__alpha__)\n    return reinterpret_cast<void*>(context->uc_mcontext.sc_pc);\n#elif defined(__arm__)\n    return reinterpret_cast<void*>(context->uc_mcontext.arm_pc);\n#elif defined(__hppa__)\n    return reinterpret_cast<void*>(context->uc_mcontext.sc_iaoq[0]);\n#elif defined(__i386__)\n    if (14 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))\n      return reinterpret_cast<void*>(context->uc_mcontext.gregs[14]);\n#elif defined(__ia64__)\n    return reinterpret_cast<void*>(context->uc_mcontext.sc_ip);\n#elif defined(__m68k__)\n    return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);\n#elif defined(__mips__)\n    return reinterpret_cast<void*>(context->uc_mcontext.pc);\n#elif defined(__powerpc64__)\n    return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]);\n#elif defined(__powerpc__)\n    return reinterpret_cast<void*>(context->uc_mcontext.uc_regs->gregs[32]);\n#elif defined(__riscv)\n    return reinterpret_cast<void*>(context->uc_mcontext.__gregs[REG_PC]);\n#elif defined(__s390__) && !defined(__s390x__)\n    return reinterpret_cast<void*>(context->uc_mcontext.psw.addr & 0x7fffffff);\n#elif defined(__s390__) && defined(__s390x__)\n    return reinterpret_cast<void*>(context->uc_mcontext.psw.addr);\n#elif defined(__sh__)\n    return reinterpret_cast<void*>(context->uc_mcontext.pc);\n#elif defined(__sparc__) && !defined(__arch64__)\n    return reinterpret_cast<void*>(context->uc_mcontext.gregs[19]);\n#elif defined(__sparc__) && defined(__arch64__)\n    return reinterpret_cast<void*>(context->uc_mcontext.mc_gregs[19]);\n#elif defined(__x86_64__)\n    if (16 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))\n      return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);\n#elif defined(__e2k__)\n    return reinterpret_cast<void*>(context->uc_mcontext.cr0_hi);\n#elif defined(__loongarch__)\n    return reinterpret_cast<void*>(context->uc_mcontext.__pc);\n#else\n#error \"Undefined Architecture.\"\n#endif\n  }\n#elif defined(__APPLE__)\n  if (vuc != nullptr) {\n    ucontext_t* signal_ucontext = reinterpret_cast<ucontext_t*>(vuc);\n#if defined(__aarch64__)\n    return reinterpret_cast<void*>(\n        __darwin_arm_thread_state64_get_pc(signal_ucontext->uc_mcontext->__ss));\n#elif defined(__arm__)\n#if __DARWIN_UNIX03\n    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__pc);\n#else\n    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.pc);\n#endif\n#elif defined(__i386__)\n#if __DARWIN_UNIX03\n    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__eip);\n#else\n    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.eip);\n#endif\n#elif defined(__x86_64__)\n#if __DARWIN_UNIX03\n    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__rip);\n#else\n    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.rip);\n#endif\n#endif\n  }\n#elif defined(__akaros__)\n  auto* ctx = reinterpret_cast<struct user_context*>(vuc);\n  return reinterpret_cast<void*>(get_user_ctx_pc(ctx));\n#endif\n  static_cast<void>(vuc);\n  return nullptr;\n}\n\nvoid DumpPCAndFrameSizesAndStackTrace(void* const pc, void* const stack[],\n                                      int frame_sizes[], int depth,\n                                      int min_dropped_frames,\n                                      bool symbolize_stacktrace,\n                                      OutputWriter* writer, void* writer_arg) {\n  if (pc != nullptr) {\n    // We don't know the stack frame size for PC, use 0.\n    if (symbolize_stacktrace) {\n      DumpPCAndFrameSizeAndSymbol(writer, writer_arg, pc, pc, 0, \"PC: \");\n    } else {\n      DumpPCAndFrameSize(writer, writer_arg, pc, 0, \"PC: \");\n    }\n  }\n  for (int i = 0; i < depth; i++) {\n    if (symbolize_stacktrace) {\n      // Pass the previous address of pc as the symbol address because pc is a\n      // return address, and an overrun may occur when the function ends with a\n      // call to a function annotated noreturn (e.g. CHECK). Note that we don't\n      // do this for pc above, as the adjustment is only correct for return\n      // addresses.\n      DumpPCAndFrameSizeAndSymbol(writer, writer_arg, stack[i],\n                                  reinterpret_cast<char*>(stack[i]) - 1,\n                                  frame_sizes[i], \"    \");\n    } else {\n      DumpPCAndFrameSize(writer, writer_arg, stack[i], frame_sizes[i], \"    \");\n    }\n  }\n  if (min_dropped_frames > 0) {\n    char buf[100];\n    snprintf(buf, sizeof(buf), \"    @ ... and at least %d more frames\\n\",\n             min_dropped_frames);\n    writer(buf, writer_arg);\n  }\n}\n\n// Dump current stack trace as directed by writer.\n// Make sure this function is not inlined to avoid skipping too many top frames.\nABSL_ATTRIBUTE_NOINLINE\nvoid DumpStackTrace(int min_dropped_frames, int max_num_frames,\n                    bool symbolize_stacktrace, OutputWriter* writer,\n                    void* writer_arg) {\n  // Print stack trace\n  void* stack_buf[kDefaultDumpStackFramesLimit];\n  void** stack = stack_buf;\n  int num_stack = kDefaultDumpStackFramesLimit;\n  size_t allocated_bytes = 0;\n\n  if (num_stack >= max_num_frames) {\n    // User requested fewer frames than we already have space for.\n    num_stack = max_num_frames;\n  } else {\n    const size_t needed_bytes =\n        static_cast<size_t>(max_num_frames) * sizeof(stack[0]);\n    void* p = Allocate(needed_bytes);\n    if (p != nullptr) {  // We got the space.\n      num_stack = max_num_frames;\n      stack = reinterpret_cast<void**>(p);\n      allocated_bytes = needed_bytes;\n    }\n  }\n\n  int depth = absl::GetStackTrace(stack, num_stack, min_dropped_frames + 1);\n  for (int i = 0; i < depth; i++) {\n    if (symbolize_stacktrace) {\n      DumpPCAndSymbol(writer, writer_arg, stack[static_cast<size_t>(i)],\n                      \"    \");\n    } else {\n      DumpPC(writer, writer_arg, stack[static_cast<size_t>(i)], \"    \");\n    }\n  }\n\n  auto hook = GetDebugStackTraceHook();\n  if (hook != nullptr) {\n    hook(stack, depth, /*crash_pc=*/nullptr, writer, writer_arg);\n  }\n\n  if (allocated_bytes != 0) Deallocate(stack, allocated_bytes);\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/examine_stack.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_\n#define ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Type of function used for printing in stack trace dumping, etc.\n// We avoid closures to keep things simple.\ntypedef void OutputWriter(const char*, void*);\n\n// RegisterDebugStackTraceHook() allows to register a single routine\n// `hook` that is called each time DumpStackTrace() is called.\n// `hook` may be called from a signal handler.\ntypedef void (*SymbolizeUrlEmitter)(void* const stack[], int depth,\n                                    const void* crash_pc, OutputWriter* writer,\n                                    void* writer_arg);\ntypedef void (*SymbolizeUrlEmitterLegacy)(void* const stack[], int depth,\n                                          OutputWriter* writer,\n                                          void* writer_arg);\n\n// Registration of SymbolizeUrlEmitter for use inside of a signal handler.\n// This is inherently unsafe and must be signal safe code.\nvoid RegisterDebugStackTraceHook(SymbolizeUrlEmitter hook);\nSymbolizeUrlEmitter GetDebugStackTraceHook();\n\nSymbolizeUrlEmitterLegacy GetDebugStackTraceHookLegacy();\n\n// Returns the program counter from signal context, or nullptr if\n// unknown. `vuc` is a ucontext_t*. We use void* to avoid the use of\n// ucontext_t on non-POSIX systems.\nvoid* GetProgramCounter(void* const vuc);\n\n// Uses `writer` to dump the program counter, stack trace, and stack\n// frame sizes.\nvoid DumpPCAndFrameSizesAndStackTrace(void* const pc, void* const stack[],\n                                      int frame_sizes[], int depth,\n                                      int min_dropped_frames,\n                                      bool symbolize_stacktrace,\n                                      OutputWriter* writer, void* writer_arg);\n\n// Dump current stack trace omitting the topmost `min_dropped_frames` stack\n// frames.\nvoid DumpStackTrace(int min_dropped_frames, int max_num_frames,\n                    bool symbolize_stacktrace, OutputWriter* writer,\n                    void* writer_arg);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_\n"
  },
  {
    "path": "absl/debugging/internal/stack_consumption.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/stack_consumption.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n\n#include <signal.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\n#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\n// This code requires that we know the direction in which the stack\n// grows. It is commonly believed that this can be detected by putting\n// a variable on the stack and then passing its address to a function\n// that compares the address of this variable to the address of a\n// variable on the function's own stack. However, this is unspecified\n// behavior in C++: If two pointers p and q of the same type point to\n// different objects that are not members of the same object or\n// elements of the same array or to different functions, or if only\n// one of them is null, the results of p<q, p>q, p<=q, and p>=q are\n// unspecified. Therefore, instead we hardcode the direction of the\n// stack on platforms we know about.\n#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \\\n    defined(__aarch64__) || defined(__riscv)\nconstexpr bool kStackGrowsDown = true;\n#else\n#error Need to define kStackGrowsDown\n#endif\n\n// To measure the stack footprint of some code, we create a signal handler\n// (for SIGUSR2 say) that exercises this code on an alternate stack. This\n// alternate stack is initialized to some known pattern (0x55, 0x55, 0x55,\n// ...). We then self-send this signal, and after the signal handler returns,\n// look at the alternate stack buffer to see what portion has been touched.\n//\n// This trick gives us the the stack footprint of the signal handler.  But the\n// signal handler, even before the code for it is exercised, consumes some\n// stack already. We however only want the stack usage of the code inside the\n// signal handler. To measure this accurately, we install two signal handlers:\n// one that does nothing and just returns, and the user-provided signal\n// handler. The difference between the stack consumption of these two signals\n// handlers should give us the stack foorprint of interest.\n\nvoid EmptySignalHandler(int) {}\n\n// This is arbitrary value, and could be increase further, at the cost of\n// memset()ting it all to known sentinel value.\nconstexpr int kAlternateStackSize = 64 << 10;  // 64KiB\n\nconstexpr int kSafetyMargin = 32;\nconstexpr char kAlternateStackFillValue = 0x55;\n\n// These helper functions look at the alternate stack buffer, and figure\n// out what portion of this buffer has been touched - this is the stack\n// consumption of the signal handler running on this alternate stack.\n// This function will return -1 if the alternate stack buffer has not been\n// touched. It will abort the program if the buffer has overflowed or is about\n// to overflow.\nint GetStackConsumption(const void* const altstack) {\n  const char* begin;\n  int increment;\n  if (kStackGrowsDown) {\n    begin = reinterpret_cast<const char*>(altstack);\n    increment = 1;\n  } else {\n    begin = reinterpret_cast<const char*>(altstack) + kAlternateStackSize - 1;\n    increment = -1;\n  }\n\n  for (int usage_count = kAlternateStackSize; usage_count > 0; --usage_count) {\n    if (*begin != kAlternateStackFillValue) {\n      ABSL_RAW_CHECK(usage_count <= kAlternateStackSize - kSafetyMargin,\n                     \"Buffer has overflowed or is about to overflow\");\n      return usage_count;\n    }\n    begin += increment;\n  }\n\n  ABSL_RAW_LOG(FATAL, \"Unreachable code\");\n  return -1;\n}\n\n}  // namespace\n\nint GetSignalHandlerStackConsumption(void (*signal_handler)(int)) {\n  // The alt-signal-stack cannot be heap allocated because there is a\n  // bug in glibc-2.2 where some signal handler setup code looks at the\n  // current stack pointer to figure out what thread is currently running.\n  // Therefore, the alternate stack must be allocated from the main stack\n  // itself.\n  void* altstack = mmap(nullptr, kAlternateStackSize, PROT_READ | PROT_WRITE,\n                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  ABSL_RAW_CHECK(altstack != MAP_FAILED, \"mmap() failed\");\n\n  // Set up the alt-signal-stack (and save the older one).\n  stack_t sigstk;\n  memset(&sigstk, 0, sizeof(sigstk));\n  sigstk.ss_sp = altstack;\n  sigstk.ss_size = kAlternateStackSize;\n  sigstk.ss_flags = 0;\n  stack_t old_sigstk;\n  memset(&old_sigstk, 0, sizeof(old_sigstk));\n  ABSL_RAW_CHECK(sigaltstack(&sigstk, &old_sigstk) == 0,\n                 \"sigaltstack() failed\");\n\n  // Set up SIGUSR1 and SIGUSR2 signal handlers (and save the older ones).\n  struct sigaction sa;\n  memset(&sa, 0, sizeof(sa));\n  struct sigaction old_sa1, old_sa2;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_ONSTACK;\n\n  // SIGUSR1 maps to EmptySignalHandler.\n  sa.sa_handler = EmptySignalHandler;\n  ABSL_RAW_CHECK(sigaction(SIGUSR1, &sa, &old_sa1) == 0, \"sigaction() failed\");\n\n  // SIGUSR2 maps to signal_handler.\n  sa.sa_handler = signal_handler;\n  ABSL_RAW_CHECK(sigaction(SIGUSR2, &sa, &old_sa2) == 0, \"sigaction() failed\");\n\n  // Send SIGUSR1 signal and measure the stack consumption of the empty\n  // signal handler.\n  // The first signal might use more stack space. Run once and ignore the\n  // results to get that out of the way.\n  ABSL_RAW_CHECK(kill(getpid(), SIGUSR1) == 0, \"kill() failed\");\n\n  memset(altstack, kAlternateStackFillValue, kAlternateStackSize);\n  ABSL_RAW_CHECK(kill(getpid(), SIGUSR1) == 0, \"kill() failed\");\n  int base_stack_consumption = GetStackConsumption(altstack);\n\n  // Send SIGUSR2 signal and measure the stack consumption of signal_handler.\n  ABSL_RAW_CHECK(kill(getpid(), SIGUSR2) == 0, \"kill() failed\");\n  int signal_handler_stack_consumption = GetStackConsumption(altstack);\n\n  // Now restore the old alt-signal-stack and signal handlers.\n  if (old_sigstk.ss_sp == nullptr && old_sigstk.ss_size == 0 &&\n      (old_sigstk.ss_flags & SS_DISABLE)) {\n    // https://git.musl-libc.org/cgit/musl/commit/src/signal/sigaltstack.c?id=7829f42a2c8944555439380498ab8b924d0f2070\n    // The original stack has ss_size==0 and ss_flags==SS_DISABLE, but some\n    // versions of musl have a bug that rejects ss_size==0. Work around this by\n    // setting ss_size to MINSIGSTKSZ, which should be ignored by the kernel\n    // when SS_DISABLE is set.\n    old_sigstk.ss_size = static_cast<size_t>(MINSIGSTKSZ);\n  }\n  ABSL_RAW_CHECK(sigaltstack(&old_sigstk, nullptr) == 0,\n                 \"sigaltstack() failed\");\n  ABSL_RAW_CHECK(sigaction(SIGUSR1, &old_sa1, nullptr) == 0,\n                 \"sigaction() failed\");\n  ABSL_RAW_CHECK(sigaction(SIGUSR2, &old_sa2, nullptr) == 0,\n                 \"sigaction() failed\");\n\n  ABSL_RAW_CHECK(munmap(altstack, kAlternateStackSize) == 0, \"munmap() failed\");\n  if (signal_handler_stack_consumption != -1 && base_stack_consumption != -1) {\n    return signal_handler_stack_consumption - base_stack_consumption;\n  }\n  return -1;\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#else\n\n// https://github.com/abseil/abseil-cpp/issues/1465\n// CMake builds on Apple platforms error when libraries are empty.\n// Our CMake configuration can avoid this error on header-only libraries,\n// but since this library is conditionally empty, including a single\n// variable is an easy workaround.\n#ifdef __APPLE__\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nextern const char kAvoidEmptyStackConsumptionLibraryWarning;\nconst char kAvoidEmptyStackConsumptionLibraryWarning = 0;\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // __APPLE__\n\n#endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n"
  },
  {
    "path": "absl/debugging/internal/stack_consumption.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Helper function for measuring stack consumption of signal handlers.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_\n#define ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_\n\n#include \"absl/base/config.h\"\n\n// The code in this module is not portable.\n// Use this feature test macro to detect its availability.\n#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n#error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly\n#elif !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \\\n    (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \\\n     defined(__aarch64__) || defined(__riscv))\n#define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Returns the stack consumption in bytes for the code exercised by\n// signal_handler.  To measure stack consumption, signal_handler is registered\n// as a signal handler, so the code that it exercises must be async-signal\n// safe.  The argument of signal_handler is an implementation detail of signal\n// handlers and should ignored by the code for signal_handler.  Use global\n// variables to pass information between your test code and signal_handler.\nint GetSignalHandlerStackConsumption(void (*signal_handler)(int));\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_\n"
  },
  {
    "path": "absl/debugging/internal/stack_consumption_test.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/stack_consumption.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n\n#include <string.h>\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\nstatic void SimpleSignalHandler(int signo) {\n  char buf[100];\n  memset(buf, 'a', sizeof(buf));\n\n  // Never true, but prevents compiler from optimizing buf out.\n  if (signo == 0) {\n    LOG(INFO) << static_cast<void*>(buf);\n  }\n}\n\nTEST(SignalHandlerStackConsumptionTest, MeasuresStackConsumption) {\n  // Our handler should consume reasonable number of bytes.\n  EXPECT_GE(GetSignalHandlerStackConsumption(SimpleSignalHandler), 100);\n}\n\n}  // namespace\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_aarch64-inl.inc",
    "content": "#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_\n\n// Generate stack tracer for aarch64\n\n#if defined(__linux__)\n#include <signal.h>\n#include <sys/mman.h>\n#include <ucontext.h>\n#include <unistd.h>\n#endif\n\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n#include <iostream>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/debugging/internal/address_is_readable.h\"\n#include \"absl/debugging/internal/addresses.h\"\n#include \"absl/debugging/internal/vdso_support.h\"  // a no-op on non-elf or non-glibc systems\n#include \"absl/debugging/stacktrace.h\"\n\nstatic const size_t kUnknownFrameSize = 0;\n// Stack end to use when we don't know the actual stack end\n// (effectively just the end of address space).\nconstexpr uintptr_t kUnknownStackEnd =\n    std::numeric_limits<size_t>::max() - sizeof(void *);\n\n#if defined(__linux__)\n// Returns the address of the VDSO __kernel_rt_sigreturn function, if present.\nstatic const unsigned char* GetKernelRtSigreturnAddress() {\n  constexpr uintptr_t kImpossibleAddress = 1;\n  ABSL_CONST_INIT static std::atomic<uintptr_t> memoized{kImpossibleAddress};\n  uintptr_t address = memoized.load(std::memory_order_relaxed);\n  if (address != kImpossibleAddress) {\n    return reinterpret_cast<const unsigned char*>(address);\n  }\n\n  address = reinterpret_cast<uintptr_t>(nullptr);\n\n#ifdef ABSL_HAVE_VDSO_SUPPORT\n  absl::debugging_internal::VDSOSupport vdso;\n  if (vdso.IsPresent()) {\n    absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info;\n    auto lookup = [&](int type) {\n      return vdso.LookupSymbol(\"__kernel_rt_sigreturn\", \"LINUX_2.6.39\", type,\n                               &symbol_info);\n    };\n    if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) ||\n        symbol_info.address == nullptr) {\n      // Unexpected: VDSO is present, yet the expected symbol is missing\n      // or null.\n      assert(false && \"VDSO is present, but doesn't have expected symbol\");\n    } else {\n      if (reinterpret_cast<uintptr_t>(symbol_info.address) !=\n          kImpossibleAddress) {\n        address = reinterpret_cast<uintptr_t>(symbol_info.address);\n      } else {\n        assert(false && \"VDSO returned invalid address\");\n      }\n    }\n  }\n#endif\n\n  memoized.store(address, std::memory_order_relaxed);\n  return reinterpret_cast<const unsigned char*>(address);\n}\n#endif  // __linux__\n\n// Compute the size of a stack frame in [low..high).  We assume that\n// low < high.  Return size of kUnknownFrameSize.\ntemplate<typename T>\nstatic size_t ComputeStackFrameSize(const T* low,\n                                           const T* high) {\n  const char* low_char_ptr = reinterpret_cast<const char *>(low);\n  const char* high_char_ptr = reinterpret_cast<const char *>(high);\n  return low < high ? static_cast<size_t>(high_char_ptr - low_char_ptr)\n                    : kUnknownFrameSize;\n}\n\n// Saves stack info that is expensive to calculate to avoid recalculating per frame.\nstruct StackInfo {\n  uintptr_t stack_low;\n  uintptr_t stack_high;\n  uintptr_t sig_stack_low;\n  uintptr_t sig_stack_high;\n};\n\nstatic bool InsideSignalStack(void** ptr, const StackInfo* stack_info) {\n  uintptr_t comparable_ptr = reinterpret_cast<uintptr_t>(ptr);\n  if (stack_info->sig_stack_high == kUnknownStackEnd)\n    return false;\n  return (comparable_ptr >= stack_info->sig_stack_low &&\n          comparable_ptr < stack_info->sig_stack_high);\n}\n\n// Given a pointer to a stack frame, locate and return the calling\n// stackframe, or return null if no stackframe can be found. Perform sanity\n// checks (the strictness of which is controlled by the boolean parameter\n// \"STRICT_UNWINDING\") to reduce the chance that a bad pointer is returned.\ntemplate<bool STRICT_UNWINDING, bool WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic void **NextStackFrame(void **old_frame_pointer, const void *uc,\n                             const StackInfo *stack_info) {\n  void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer);\n\n#if defined(__linux__)\n  if (WITH_CONTEXT && uc != nullptr) {\n    // Check to see if next frame's return address is __kernel_rt_sigreturn.\n    if (old_frame_pointer[1] == GetKernelRtSigreturnAddress()) {\n      const ucontext_t *ucv = static_cast<const ucontext_t *>(uc);\n      // old_frame_pointer[0] is not suitable for unwinding, look at\n      // ucontext to discover frame pointer before signal.\n      void **const pre_signal_frame_pointer =\n          reinterpret_cast<void **>(ucv->uc_mcontext.regs[29]);\n\n      // The most recent signal always needs special handling to find the frame\n      // pointer, but a nested signal does not.  If pre_signal_frame_pointer is\n      // earlier in the stack than the old_frame_pointer, then use it. If it is\n      // later, then we have already unwound through it and it needs no special\n      // handling.\n      if (pre_signal_frame_pointer > old_frame_pointer) {\n        new_frame_pointer = pre_signal_frame_pointer;\n      }\n    }\n  }\n#endif\n\n  // The frame pointer should be 8-byte aligned.\n  if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 7) != 0)\n    return nullptr;\n\n  uintptr_t new_fp_comparable = reinterpret_cast<uintptr_t>(new_frame_pointer);\n  // Only check the size if both frames are in the same stack.\n  const bool old_inside_signal_stack =\n      InsideSignalStack(old_frame_pointer, stack_info);\n  const bool new_inside_signal_stack =\n      InsideSignalStack(new_frame_pointer, stack_info);\n  if (new_inside_signal_stack == old_inside_signal_stack) {\n    // Check frame size.  In strict mode, we assume frames to be under\n    // 100,000 bytes.  In non-strict mode, we relax the limit to 1MB.\n    const size_t max_size = STRICT_UNWINDING ? 100000 : 1000000;\n    const size_t frame_size =\n        ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);\n    if (frame_size == kUnknownFrameSize)\n       return nullptr;\n    // A very large frame may mean corrupt memory or an erroneous frame\n    // pointer. But also maybe just a plain-old large frame.  Assume that if the\n    // frame is within a known stack, then it is valid.\n    if (frame_size > max_size) {\n      size_t stack_low = stack_info->stack_low;\n      size_t stack_high = stack_info->stack_high;\n      if (new_inside_signal_stack) {\n        stack_low = stack_info->sig_stack_low;\n        stack_high = stack_info->sig_stack_high;\n      }\n      if (stack_high < kUnknownStackEnd &&\n          static_cast<size_t>(getpagesize()) < stack_low) {\n        // Stack bounds are known.\n        if (!(stack_low < new_fp_comparable &&\n              new_fp_comparable <= stack_high)) {\n          // new_frame_pointer is not within a known stack.\n          return nullptr;\n        }\n      } else {\n        // Stack bounds are unknown, prefer truncated stack to possible crash.\n        return nullptr;\n      }\n    }\n  }\n  // New frame pointer is valid if it is inside either known stack or readable.\n  // This assumes that everything within either known stack is readable. Outside\n  // either known stack but readable is unexpected, and possibly corrupt, but\n  // for now assume it is valid. If it isn't actually valid, the next frame will\n  // be corrupt and we will detect that next iteration.\n  if (new_inside_signal_stack ||\n      (new_fp_comparable >= stack_info->stack_low &&\n       new_fp_comparable < stack_info->stack_high) ||\n      absl::debugging_internal::AddressIsReadable(new_frame_pointer)) {\n    return new_frame_pointer;\n  }\n\n  return nullptr;\n}\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\n// We count on the bottom frame being this one. See the comment\n// at prev_return_address\nABSL_ATTRIBUTE_NOINLINE\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic int UnwindImpl(void **result, uintptr_t *frames, int *sizes,\n                      int max_depth, int skip_count, const void *ucp,\n                      int *min_dropped_frames) {\n#ifdef __GNUC__\n  void **frame_pointer = reinterpret_cast<void**>(__builtin_frame_address(0));\n#else\n# error reading stack point not yet supported on this platform.\n#endif\n  skip_count++;    // Skip the frame for this function.\n  int n = 0;\n\n  // Assume that the first page is not stack.\n  StackInfo stack_info;\n  stack_info.stack_low = static_cast<uintptr_t>(getpagesize());\n  stack_info.stack_high = kUnknownStackEnd;\n  stack_info.sig_stack_low = stack_info.stack_low;\n  stack_info.sig_stack_high = kUnknownStackEnd;\n\n  // The frame pointer points to low address of a frame.  The first 64-bit\n  // word of a frame points to the next frame up the call chain, which normally\n  // is just after the high address of the current frame.  The second word of\n  // a frame contains return address of to the caller.   To find a pc value\n  // associated with the current frame, we need to go down a level in the call\n  // chain.  So we remember return the address of the last frame seen.  This\n  // does not work for the first stack frame, which belongs to UnwindImp() but\n  // we skip the frame for UnwindImp() anyway.\n  void* prev_return_address = nullptr;\n  // The nth frame size is the difference between the nth frame pointer and the\n  // the frame pointer below it in the call chain. There is no frame below the\n  // leaf frame, but this function is the leaf anyway, and we skip it.\n  void** prev_frame_pointer = nullptr;\n\n   while (frame_pointer && n < max_depth) {\n    if (skip_count > 0) {\n      skip_count--;\n    } else {\n      result[n] = reinterpret_cast<void *>(\n          absl::debugging_internal::StripPointerMetadata(prev_return_address));\n      if (IS_STACK_FRAMES) {\n        if (frames != nullptr) {\n          frames[n] = absl::debugging_internal::StripPointerMetadata(\n                          prev_frame_pointer) +\n                      2 * sizeof(void *) /* go past the return address */;\n        }\n        if (sizes != nullptr) {\n          sizes[n] = static_cast<int>(\n              ComputeStackFrameSize(prev_frame_pointer, frame_pointer));\n        }\n      }\n      n++;\n    }\n    prev_return_address = frame_pointer[1];\n    prev_frame_pointer = frame_pointer;\n    // The absl::GetStackFrames routine is called when we are in some\n    // informational context (the failure signal handler for example).\n    // Use the non-strict unwinding rules to produce a stack trace\n    // that is as complete as possible (even if it contains a few bogus\n    // entries in some rare cases).\n    frame_pointer = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(\n        frame_pointer, ucp, &stack_info);\n  }\n\n  if (min_dropped_frames != nullptr) {\n    // Implementation detail: we clamp the max of frames we are willing to\n    // count, so as not to spend too much time in the loop below.\n    const int kMaxUnwind = 200;\n    int num_dropped_frames = 0;\n    for (int j = 0; frame_pointer != nullptr && j < kMaxUnwind; j++) {\n      if (skip_count > 0) {\n        skip_count--;\n      } else {\n        num_dropped_frames++;\n      }\n      frame_pointer = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(\n          frame_pointer, ucp, &stack_info);\n    }\n    *min_dropped_frames = num_dropped_frames;\n  }\n  return n;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return true;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_arm-inl.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This is inspired by Craig Silverstein's PowerPC stacktrace code.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_\n\n#include <cstdint>\n\n#include \"absl/debugging/internal/addresses.h\"\n#include \"absl/debugging/stacktrace.h\"\n\n// WARNING:\n// This only works if all your code is in either ARM or THUMB mode.  With\n// interworking, the frame pointer of the caller can either be in r11 (ARM\n// mode) or r7 (THUMB mode).  A callee only saves the frame pointer of its\n// mode in a fixed location on its stack frame.  If the caller is a different\n// mode, there is no easy way to find the frame pointer.  It can either be\n// still in the designated register or saved on stack along with other callee\n// saved registers.\n\n// Given a pointer to a stack frame, locate and return the calling\n// stackframe, or return nullptr if no stackframe can be found. Perform sanity\n// checks (the strictness of which is controlled by the boolean parameter\n// \"STRICT_UNWINDING\") to reduce the chance that a bad pointer is returned.\ntemplate<bool STRICT_UNWINDING>\nstatic void **NextStackFrame(void **old_sp) {\n  void **new_sp = (void**) old_sp[-1];\n\n  // Check that the transition from frame pointer old_sp to frame\n  // pointer new_sp isn't clearly bogus\n  if (STRICT_UNWINDING) {\n    // With the stack growing downwards, older stack frame must be\n    // at a greater address that the current one.\n    if (new_sp <= old_sp) return nullptr;\n    // Assume stack frames larger than 100,000 bytes are bogus.\n    if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return nullptr;\n  } else {\n    // In the non-strict mode, allow discontiguous stack frames.\n    // (alternate-signal-stacks for example).\n    if (new_sp == old_sp) return nullptr;\n    // And allow frames upto about 1MB.\n    if ((new_sp > old_sp)\n        && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return nullptr;\n  }\n  if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return nullptr;\n  return new_sp;\n}\n\n// This ensures that absl::GetStackTrace sets up the Link Register properly.\n#ifdef __GNUC__\nvoid StacktraceArmDummyFunction() __attribute__((noinline));\nvoid StacktraceArmDummyFunction() { __asm__ volatile(\"\"); }\n#else\n# error StacktraceArmDummyFunction() needs to be ported to this platform.\n#endif\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nstatic int UnwindImpl(void **result, uintptr_t *frames, int *sizes,\n                      int max_depth, int skip_count, const void * /* ucp */,\n                      int *min_dropped_frames) {\n#ifdef __GNUC__\n  void **sp = reinterpret_cast<void**>(__builtin_frame_address(0));\n#else\n# error reading stack point not yet supported on this platform.\n#endif\n\n  // On ARM, the return address is stored in the link register (r14).\n  // This is not saved on the stack frame of a leaf function.  To\n  // simplify code that reads return addresses, we call a dummy\n  // function so that the return address of this function is also\n  // stored in the stack frame.  This works at least for gcc.\n  StacktraceArmDummyFunction();\n\n  int n = 0;\n  while (sp && n < max_depth) {\n    // The absl::GetStackFrames routine is called when we are in some\n    // informational context (the failure signal handler for example).\n    // Use the non-strict unwinding rules to produce a stack trace\n    // that is as complete as possible (even if it contains a few bogus\n    // entries in some rare cases).\n    void **next_sp = NextStackFrame<!IS_STACK_FRAMES>(sp);\n\n    if (skip_count > 0) {\n      skip_count--;\n    } else {\n      result[n] = *sp;\n\n      if (IS_STACK_FRAMES) {\n        if (frames != nullptr) {\n          frames[n] = absl::debugging_internal::StripPointerMetadata(sp) +\n                      1 * sizeof(void *) /* go past the return address */;\n        }\n        if (sizes != nullptr) {\n          if (next_sp > sp) {\n            sizes[n] = absl::debugging_internal::StripPointerMetadata(next_sp) -\n                       absl::debugging_internal::StripPointerMetadata(sp);\n          } else {\n            // A frame-size of 0 is used to indicate unknown frame size.\n            sizes[n] = 0;\n          }\n        }\n      }\n      n++;\n    }\n    sp = next_sp;\n  }\n  if (min_dropped_frames != nullptr) {\n    // Implementation detail: we clamp the max of frames we are willing to\n    // count, so as not to spend too much time in the loop below.\n    const int kMaxUnwind = 200;\n    int num_dropped_frames = 0;\n    for (int j = 0; sp != nullptr && j < kMaxUnwind; j++) {\n      if (skip_count > 0) {\n        skip_count--;\n      } else {\n        num_dropped_frames++;\n      }\n      sp = NextStackFrame<!IS_STACK_FRAMES>(sp);\n    }\n    *min_dropped_frames = num_dropped_frames;\n  }\n  return n;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return false;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_config.h",
    "content": "/*\n * Copyright 2017 The Abseil Authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n\n * Defines ABSL_STACKTRACE_INL_HEADER to the *-inl.h containing\n * actual unwinder implementation.\n * This header is \"private\" to stacktrace.cc.\n * DO NOT include it into any other files.\n*/\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_\n\n#include \"absl/base/config.h\"\n\n#if defined(ABSL_STACKTRACE_INL_HEADER)\n#error ABSL_STACKTRACE_INL_HEADER cannot be directly set\n\n#elif defined(_WIN32)\n#define ABSL_STACKTRACE_INL_HEADER \\\n    \"absl/debugging/internal/stacktrace_win32-inl.inc\"\n\n#elif defined(__APPLE__)\n#ifdef ABSL_HAVE_THREAD_LOCAL\n// Thread local support required for UnwindImpl.\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_generic-inl.inc\"\n#endif  // defined(ABSL_HAVE_THREAD_LOCAL)\n\n// Emscripten stacktraces rely on JS. Do not use them in standalone mode.\n#elif defined(__EMSCRIPTEN__) && !defined(STANDALONE_WASM)\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_emscripten-inl.inc\"\n\n#elif defined(__ANDROID__) && __ANDROID_API__ >= 33\n#ifdef ABSL_HAVE_THREAD_LOCAL\n// Use the generic implementation for Android 33+ (Android T+). This is the\n// first version of Android for which <execinfo.h> implements backtrace().\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_generic-inl.inc\"\n#endif  // defined(ABSL_HAVE_THREAD_LOCAL)\n\n#elif defined(__linux__) && !defined(__ANDROID__)\n\n#if defined(NO_FRAME_POINTER) && \\\n    (defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))\n// Note: The libunwind-based implementation is not available to open-source\n// users.\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_libunwind-inl.inc\"\n#define STACKTRACE_USES_LIBUNWIND 1\n#elif defined(NO_FRAME_POINTER) && defined(__has_include)\n#if __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)\n// Note: When using glibc this may require -funwind-tables to function properly.\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_generic-inl.inc\"\n#endif  // __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)\n#elif defined(__i386__) || defined(__x86_64__)\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_x86-inl.inc\"\n#elif defined(__ppc__) || defined(__PPC__)\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_powerpc-inl.inc\"\n#elif defined(__aarch64__)\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_aarch64-inl.inc\"\n#elif defined(__riscv)\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_riscv-inl.inc\"\n#elif defined(__has_include)\n#if __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)\n// Note: When using glibc this may require -funwind-tables to function properly.\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_generic-inl.inc\"\n#endif  // __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)\n#endif  // defined(__has_include)\n\n#endif  // defined(__linux__) && !defined(__ANDROID__)\n\n// Fallback to the empty implementation.\n#if !defined(ABSL_STACKTRACE_INL_HEADER)\n#define ABSL_STACKTRACE_INL_HEADER \\\n  \"absl/debugging/internal/stacktrace_unimplemented-inl.inc\"\n#endif\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_emscripten-inl.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Portable implementation - just use glibc\n//\n// Note:  The glibc implementation may cause a call to malloc.\n// This can cause a deadlock in HeapProfiler.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_\n\n#include <emscripten.h>\n#include <stdint.h>\n\n#include <atomic>\n#include <cstddef>\n#include <cstring>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/debugging/stacktrace.h\"\n\nextern \"C\" {\nuintptr_t emscripten_stack_snapshot();\nuint32_t emscripten_stack_unwind_buffer(uintptr_t pc, void *buffer,\n                                        uint32_t depth);\n}\n\n// Sometimes, we can try to get a stack trace from within a stack\n// trace, which can cause a self-deadlock.\n// Protect against such reentrant call by failing to get a stack trace.\n//\n// We use __thread here because the code here is extremely low level -- it is\n// called while collecting stack traces from within malloc and mmap, and thus\n// can not call anything which might call malloc or mmap itself.\nstatic __thread int recursive = 0;\n\n// The stack trace function might be invoked very early in the program's\n// execution (e.g. from the very first malloc).\n// As such, we suppress usage of backtrace during this early stage of execution.\nstatic std::atomic<bool> disable_stacktraces(true);  // Disabled until healthy.\n// Waiting until static initializers run seems to be late enough.\n// This file is included into stacktrace.cc so this will only run once.\nABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {\n  disable_stacktraces.store(false, std::memory_order_relaxed);\n  return 0;\n}();\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nstatic int UnwindImpl(void **result, uintptr_t *frames, int *sizes,\n                      int max_depth, int skip_count, const void *ucp,\n                      int *min_dropped_frames) {\n  if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {\n    return 0;\n  }\n  ++recursive;\n\n  static_cast<void>(ucp);  // Unused.\n  constexpr int kStackLength = 64;\n  void *stack[kStackLength];\n\n  int size;\n  uintptr_t pc = emscripten_stack_snapshot();\n  size =\n      static_cast<int>(emscripten_stack_unwind_buffer(pc, stack, kStackLength));\n\n  int result_count = size - skip_count;\n  if (result_count < 0) result_count = 0;\n  if (result_count > max_depth) result_count = max_depth;\n  for (int i = 0; i < result_count; i++) result[i] = stack[i + skip_count];\n\n  if (IS_STACK_FRAMES) {\n    // No implementation for finding out the stack frames yet.\n    if (frames != nullptr) {\n      memset(frames, 0, sizeof(*frames) * static_cast<size_t>(result_count));\n    }\n    if (sizes != nullptr) {\n      memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));\n    }\n  }\n  if (min_dropped_frames != nullptr) {\n    if (size - skip_count - max_depth > 0) {\n      *min_dropped_frames = size - skip_count - max_depth;\n    } else {\n      *min_dropped_frames = 0;\n    }\n  }\n\n  --recursive;\n\n  return result_count;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() { return true; }\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_generic-inl.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Portable implementation - just use glibc\n//\n// Note:  The glibc implementation may cause a call to malloc.\n// This can cause a deadlock in HeapProfiler.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_\n\n#include <execinfo.h>\n#include <atomic>\n#include <cstring>\n\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/base/attributes.h\"\n\n// Sometimes, we can try to get a stack trace from within a stack\n// trace, because we don't block signals inside this code (which would be too\n// expensive: the two extra system calls per stack trace do matter here).\n// That can cause a self-deadlock.\n// Protect against such reentrant call by failing to get a stack trace.\n//\n// We use __thread here because the code here is extremely low level -- it is\n// called while collecting stack traces from within malloc and mmap, and thus\n// can not call anything which might call malloc or mmap itself.\nstatic __thread int recursive = 0;\n\n// The stack trace function might be invoked very early in the program's\n// execution (e.g. from the very first malloc if using tcmalloc). Also, the\n// glibc implementation itself will trigger malloc the first time it is called.\n// As such, we suppress usage of backtrace during this early stage of execution.\nstatic std::atomic<bool> disable_stacktraces(true);  // Disabled until healthy.\n// Waiting until static initializers run seems to be late enough.\n// This file is included into stacktrace.cc so this will only run once.\nABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {\n  void* unused_stack[1];\n  // Force the first backtrace to happen early to get the one-time shared lib\n  // loading (allocation) out of the way. After the first call it is much safer\n  // to use backtrace from a signal handler if we crash somewhere later.\n  backtrace(unused_stack, 1);\n  disable_stacktraces.store(false, std::memory_order_relaxed);\n  return 0;\n}();\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nstatic int UnwindImpl(void** result, uintptr_t* frames, int* sizes,\n                      int max_depth, int skip_count, const void* ucp,\n                      int* min_dropped_frames) {\n  if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {\n    return 0;\n  }\n  ++recursive;\n\n  static_cast<void>(ucp);  // Unused.\n  static const int kStackLength = 64;\n  void * stack[kStackLength];\n  int size;\n\n  size = backtrace(stack, kStackLength);\n  skip_count++;  // we want to skip the current frame as well\n  int result_count = size - skip_count;\n  if (result_count < 0)\n    result_count = 0;\n  if (result_count > max_depth)\n    result_count = max_depth;\n  for (int i = 0; i < result_count; i++)\n    result[i] = stack[i + skip_count];\n\n  if (IS_STACK_FRAMES) {\n    // No implementation for finding out the stack frames yet.\n    if (frames != nullptr) {\n      memset(frames, 0, sizeof(*frames) * static_cast<size_t>(result_count));\n    }\n    if (sizes != nullptr) {\n      memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));\n    }\n  }\n  if (min_dropped_frames != nullptr) {\n    if (size - skip_count - max_depth > 0) {\n      *min_dropped_frames = size - skip_count - max_depth;\n    } else {\n      *min_dropped_frames = 0;\n    }\n  }\n\n  --recursive;\n\n  return result_count;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return true;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_powerpc-inl.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Produce stack trace.  I'm guessing (hoping!) the code is much like\n// for x86.  For apple machines, at least, it seems to be; see\n//    https://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html\n//    https://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK\n// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_\n\n#include \"absl/debugging/internal/addresses.h\"\n#if defined(__linux__)\n#include <asm/ptrace.h>   // for PT_NIP.\n#include <ucontext.h>     // for ucontext_t\n#endif\n\n#include <unistd.h>\n#include <cassert>\n#include <cstdint>\n#include <cstdio>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/internal/address_is_readable.h\"\n#include \"absl/debugging/internal/vdso_support.h\"  // a no-op on non-elf or non-glibc systems\n\n// Given a stack pointer, return the saved link register value.\n// Note that this is the link register for a callee.\nstatic inline void **StacktracePowerPCGetLRPtr(void **sp) {\n  // PowerPC has 3 main ABIs, which say where in the stack the\n  // Link Register is.  For DARWIN and AIX (used by apple and\n  // linux ppc64), it's in sp[2].  For SYSV (used by linux ppc),\n  // it's in sp[1].\n#if defined(_CALL_AIX) || defined(_CALL_DARWIN)\n  return (sp + 2);\n#elif defined(_CALL_SYSV)\n  return (sp + 1);\n#elif defined(__APPLE__) || defined(__FreeBSD__) || \\\n    (defined(__linux__) && defined(__PPC64__))\n  // This check is in case the compiler doesn't define _CALL_AIX/etc.\n  return (sp + 2);\n#elif defined(__linux)\n  // This check is in case the compiler doesn't define _CALL_SYSV.\n  return (sp + 1);\n#else\n#error Need to specify the PPC ABI for your architecture.\n#endif\n}\n\n// Given a pointer to a stack frame, locate and return the calling\n// stackframe, or return null if no stackframe can be found. Perform sanity\n// checks (the strictness of which is controlled by the boolean parameter\n// \"STRICT_UNWINDING\") to reduce the chance that a bad pointer is returned.\ntemplate<bool STRICT_UNWINDING, bool IS_WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic void **NextStackFrame(void **old_sp, const void *uc) {\n  void **new_sp = (void **) *old_sp;\n  enum { kStackAlignment = 16 };\n\n  // Check that the transition from frame pointer old_sp to frame\n  // pointer new_sp isn't clearly bogus\n  if (STRICT_UNWINDING) {\n    // With the stack growing downwards, older stack frame must be\n    // at a greater address that the current one.\n    if (new_sp <= old_sp) return nullptr;\n    // Assume stack frames larger than 100,000 bytes are bogus.\n    if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return nullptr;\n  } else {\n    // In the non-strict mode, allow discontiguous stack frames.\n    // (alternate-signal-stacks for example).\n    if (new_sp == old_sp) return nullptr;\n    // And allow frames upto about 1MB.\n    if ((new_sp > old_sp)\n        && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return nullptr;\n  }\n  if ((uintptr_t)new_sp % kStackAlignment != 0) return nullptr;\n\n#if defined(__linux__)\n  enum StackTraceKernelSymbolStatus {\n      kNotInitialized = 0, kAddressValid, kAddressInvalid };\n\n  if (IS_WITH_CONTEXT && uc != nullptr) {\n    static StackTraceKernelSymbolStatus kernel_symbol_status =\n        kNotInitialized;  // Sentinel: not computed yet.\n    // Initialize with sentinel value: __kernel_rt_sigtramp_rt64 can not\n    // possibly be there.\n    static const unsigned char *kernel_sigtramp_rt64_address = nullptr;\n    if (kernel_symbol_status == kNotInitialized) {\n      absl::debugging_internal::VDSOSupport vdso;\n      if (vdso.IsPresent()) {\n        absl::debugging_internal::VDSOSupport::SymbolInfo\n            sigtramp_rt64_symbol_info;\n        if (!vdso.LookupSymbol(\n                \"__kernel_sigtramp_rt64\", \"LINUX_2.6.15\",\n                absl::debugging_internal::VDSOSupport::kVDSOSymbolType,\n                &sigtramp_rt64_symbol_info) ||\n            sigtramp_rt64_symbol_info.address == nullptr) {\n          // Unexpected: VDSO is present, yet the expected symbol is missing\n          // or null.\n          assert(false && \"VDSO is present, but doesn't have expected symbol\");\n          kernel_symbol_status = kAddressInvalid;\n        } else {\n          kernel_sigtramp_rt64_address =\n              reinterpret_cast<const unsigned char *>(\n                  sigtramp_rt64_symbol_info.address);\n          kernel_symbol_status = kAddressValid;\n        }\n      } else {\n        kernel_symbol_status = kAddressInvalid;\n      }\n    }\n\n    if (new_sp != nullptr && kernel_symbol_status == kAddressValid &&\n        *StacktracePowerPCGetLRPtr(new_sp) == kernel_sigtramp_rt64_address) {\n      const ucontext_t* signal_context =\n          reinterpret_cast<const ucontext_t*>(uc);\n      void **const sp_before_signal =\n#if defined(__PPC64__)\n          reinterpret_cast<void **>(signal_context->uc_mcontext.gp_regs[PT_R1]);\n#else\n          reinterpret_cast<void **>(\n              signal_context->uc_mcontext.uc_regs->gregs[PT_R1]);\n#endif\n      // Check that alleged sp before signal is nonnull and is reasonably\n      // aligned.\n      if (sp_before_signal != nullptr &&\n          ((uintptr_t)sp_before_signal % kStackAlignment) == 0) {\n        // Check that alleged stack pointer is actually readable. This is to\n        // prevent a \"double fault\" in case we hit the first fault due to e.g.\n        // a stack corruption.\n        if (absl::debugging_internal::AddressIsReadable(sp_before_signal)) {\n          // Alleged stack pointer is readable, use it for further unwinding.\n          new_sp = sp_before_signal;\n        }\n      }\n    }\n  }\n#endif\n\n  return new_sp;\n}\n\n// This ensures that absl::GetStackTrace sets up the Link Register properly.\nABSL_ATTRIBUTE_NOINLINE static void AbslStacktracePowerPCDummyFunction() {\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic int UnwindImpl(void **result, uintptr_t *frames, int *sizes,\n                      int max_depth, int skip_count, const void *ucp,\n                      int *min_dropped_frames) {\n  void **sp;\n  // Apple macOS uses an old version of gnu as -- both Darwin 7.9.0 (Panther)\n  // and Darwin 8.8.1 (Tiger) use as 1.38.  This means we have to use a\n  // different asm syntax.  I don't know quite the best way to discriminate\n  // systems using the old as from the new one; I've gone with __APPLE__.\n#ifdef __APPLE__\n  __asm__ volatile (\"mr %0,r1\" : \"=r\" (sp));\n#else\n  __asm__ volatile (\"mr %0,1\" : \"=r\" (sp));\n#endif\n\n  // On PowerPC, the \"Link Register\" or \"Link Record\" (LR), is a stack\n  // entry that holds the return address of the subroutine call (what\n  // instruction we run after our function finishes).  This is the\n  // same as the stack-pointer of our parent routine, which is what we\n  // want here.  While the compiler will always(?) set up LR for\n  // subroutine calls, it may not for leaf functions (such as this one).\n  // This routine forces the compiler (at least gcc) to push it anyway.\n  AbslStacktracePowerPCDummyFunction();\n\n  // The LR save area is used by the callee, so the top entry is bogus.\n  skip_count++;\n\n  int n = 0;\n\n  // Unlike ABIs of X86 and ARM, PowerPC ABIs say that return address (in\n  // the link register) of a function call is stored in the caller's stack\n  // frame instead of the callee's.  When we look for the return address\n  // associated with a stack frame, we need to make sure that there is a\n  // caller frame before it.  So we call NextStackFrame before entering the\n  // loop below and check next_sp instead of sp for loop termination.\n  // The outermost frame is set up by runtimes and it does not have a\n  // caller frame, so it is skipped.\n\n  // The absl::GetStackFrames routine is called when we are in some\n  // informational context (the failure signal handler for example).\n  // Use the non-strict unwinding rules to produce a stack trace\n  // that is as complete as possible (even if it contains a few\n  // bogus entries in some rare cases).\n  void **next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp);\n\n  while (next_sp && n < max_depth) {\n    if (skip_count > 0) {\n      skip_count--;\n    } else {\n      void **lr = StacktracePowerPCGetLRPtr(sp);\n      result[n] = *lr;\n      if (IS_STACK_FRAMES) {\n        if (frames != nullptr) {\n          frames[n] = absl::debugging_internal::StripPointerMetadata(lr) +\n                      1 * sizeof(void *) /* go past the return address */;\n        }\n        if (sizes != nullptr) {\n          if (next_sp > sp) {\n            sizes[n] = static_cast<int>(\n                absl::debugging_internal::StripPointerMetadata(next_sp) -\n                absl::debugging_internal::StripPointerMetadata(sp));\n          } else {\n            // A frame-size of 0 is used to indicate unknown frame size.\n            sizes[n] = 0;\n          }\n        }\n      }\n      n++;\n    }\n\n    sp = next_sp;\n    next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp);\n  }\n\n  if (min_dropped_frames != nullptr) {\n    // Implementation detail: we clamp the max of frames we are willing to\n    // count, so as not to spend too much time in the loop below.\n    const int kMaxUnwind = 1000;\n    int num_dropped_frames = 0;\n    for (int j = 0; next_sp != nullptr && j < kMaxUnwind; j++) {\n      if (skip_count > 0) {\n        skip_count--;\n      } else {\n        num_dropped_frames++;\n      }\n      next_sp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(next_sp, ucp);\n    }\n    *min_dropped_frames = num_dropped_frames;\n  }\n  return n;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return true;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_riscv-inl.inc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_RISCV_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_RISCV_INL_H_\n\n// Generate stack trace for riscv\n\n#include <sys/ucontext.h>\n\n#include \"absl/base/config.h\"\n#include \"absl/debugging/internal/addresses.h\"\n#if defined(__linux__)\n#include <sys/mman.h>\n#include <ucontext.h>\n#include <unistd.h>\n#endif\n\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n#include <iostream>\n#include <limits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/debugging/stacktrace.h\"\n\nstatic constexpr ptrdiff_t kUnknownFrameSize = 0;\n\n// Compute the size of a stack frame in [low..high).  We assume that low < high.\n// Return size of kUnknownFrameSize.\ntemplate <typename T>\nstatic inline ptrdiff_t ComputeStackFrameSize(const T *low, const T *high) {\n  const char *low_char_ptr = reinterpret_cast<const char *>(low);\n  const char *high_char_ptr = reinterpret_cast<const char *>(high);\n  return low < high ? static_cast<ptrdiff_t>(high_char_ptr - low_char_ptr)\n                    : kUnknownFrameSize;\n}\n\n// Given a pointer to a stack frame, locate and return the calling stackframe,\n// or return null if no stackframe can be found. Perform sanity checks (the\n// strictness of which is controlled by the boolean parameter\n// \"STRICT_UNWINDING\") to reduce the chance that a bad pointer is returned.\ntemplate <bool STRICT_UNWINDING, bool WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic void ** NextStackFrame(void **old_frame_pointer, const void *uc,\n                              const std::pair<size_t, size_t> range) {\n  //               .\n  //               .\n  //               .\n  //   +-> +----------------+\n  //   |   | return address |\n  //   |   |   previous fp  |\n  //   |   |      ...       |\n  //   |   +----------------+ <-+\n  //   |   | return address |   |\n  //   +---|-  previous fp  |   |\n  //       |      ...       |   |\n  // $fp ->|----------------+   |\n  //       | return address |   |\n  //       |   previous fp -|---+\n  // $sp ->|      ...       |\n  //       +----------------+\n  void **new_frame_pointer = reinterpret_cast<void **>(old_frame_pointer[-2]);\n  uintptr_t frame_pointer = reinterpret_cast<uintptr_t>(new_frame_pointer);\n\n  // The RISCV ELF psABI mandates that the stack pointer is always 16-byte\n  // aligned.\n  // TODO(#1236) this doesn't hold for ILP32E which only mandates a 4-byte\n  // alignment.\n  if (frame_pointer & 15)\n    return nullptr;\n\n  // If the new frame pointer matches the signal context, avoid terminating\n  // early to deal with alternate signal stacks.\n  if (WITH_CONTEXT)\n    if (const ucontext_t *ucv = static_cast<const ucontext_t *>(uc))\n      // RISCV ELF psABI has the frame pointer at x8/fp/s0.\n      // -- RISCV psABI Table 18.2\n      if (ucv->uc_mcontext.__gregs[8] == frame_pointer)\n        return new_frame_pointer;\n\n  // Check frame size.  In strict mode, we assume frames to be under 100,000\n  // bytes.  In non-strict mode, we relax the limit to 1MB.\n  const ptrdiff_t max_size = STRICT_UNWINDING ? 100000 : 1000000;\n  const ptrdiff_t frame_size =\n      ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);\n  if (frame_size == kUnknownFrameSize) {\n    if (STRICT_UNWINDING)\n      return nullptr;\n\n    // In non-strict mode permit non-contiguous stacks (e.g. alternate signal\n    // frame handling).\n    if (reinterpret_cast<uintptr_t>(new_frame_pointer) < range.first ||\n        reinterpret_cast<uintptr_t>(new_frame_pointer) > range.second)\n      return nullptr;\n  }\n\n  if (frame_size > max_size)\n    return nullptr;\n\n  return new_frame_pointer;\n}\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic int UnwindImpl(void **result, uintptr_t *frames, int *sizes,\n                      int max_depth, int skip_count, const void *ucp,\n                      int *min_dropped_frames) {\n  // The `frame_pointer` that is computed here points to the top of the frame.\n  // The two words preceding the address are the return address and the previous\n  // frame pointer.\n#if defined(__GNUC__)\n  void **frame_pointer = reinterpret_cast<void **>(__builtin_frame_address(0));\n#else\n#error reading stack pointer not yet supported on this platform\n#endif\n\n  std::pair<size_t, size_t> stack = {\n      // assume that the first page is not the stack.\n      static_cast<size_t>(sysconf(_SC_PAGESIZE)),\n      std::numeric_limits<size_t>::max() - sizeof(void *)\n  };\n\n  int n = 0;\n  void *return_address = nullptr;\n  while (frame_pointer && n < max_depth) {\n    return_address = frame_pointer[-1];\n\n    // The absl::GetStackFrames routine is called when we are in some\n    // informational context (the failure signal handler for example).  Use the\n    // non-strict unwinding rules to produce a stack trace that is as complete\n    // as possible (even if it contains a few bogus entries in some rare cases).\n    void **next_frame_pointer =\n        NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp,\n                                                          stack);\n\n    if (skip_count > 0) {\n      skip_count--;\n    } else {\n      result[n] = return_address;\n      if (IS_STACK_FRAMES) {\n        // NextStackFrame() has already checked that frame size fits to int\n        if (frames != nullptr) {\n          frames[n] =\n              absl::debugging_internal::StripPointerMetadata(frame_pointer);\n        }\n        if (sizes != nullptr) {\n          sizes[n] = static_cast<int>(\n              ComputeStackFrameSize(frame_pointer, next_frame_pointer));\n        }\n      }\n      n++;\n    }\n\n    frame_pointer = next_frame_pointer;\n  }\n\n  if (min_dropped_frames != nullptr) {\n    // Implementation detail: we clamp the max of frames we are willing to\n    // count, so as not to spend too much time in the loop below.\n    const int kMaxUnwind = 200;\n    int num_dropped_frames = 0;\n    for (int j = 0; frame_pointer != nullptr && j < kMaxUnwind; j++) {\n      if (skip_count > 0) {\n        skip_count--;\n      } else {\n        num_dropped_frames++;\n      }\n      frame_pointer =\n          NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp,\n                                                            stack);\n    }\n    *min_dropped_frames = num_dropped_frames;\n  }\n\n  return n;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() { return true; }\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_unimplemented-inl.inc",
    "content": "#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nstatic int UnwindImpl(void** /* result */, uintptr_t* /* frames */,\n                      int* /* sizes */, int /* max_depth */,\n                      int /* skip_count */, const void* /* ucp */,\n                      int* min_dropped_frames) {\n  if (min_dropped_frames != nullptr) {\n    *min_dropped_frames = 0;\n  }\n  return 0;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return false;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_win32-inl.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Produces a stack trace for Windows.  Normally, one could use\n// stacktrace_x86-inl.h or stacktrace_x86_64-inl.h -- and indeed, that\n// should work for binaries compiled using MSVC in \"debug\" mode.\n// However, in \"release\" mode, Windows uses frame-pointer\n// optimization, which makes getting a stack trace very difficult.\n//\n// There are several approaches one can take.  One is to use Windows\n// intrinsics like StackWalk64.  These can work, but have restrictions\n// on how successful they can be.  Another attempt is to write a\n// version of stacktrace_x86-inl.h that has heuristic support for\n// dealing with FPO, similar to what WinDbg does (see\n// http://www.nynaeve.net/?p=97).  There are (non-working) examples of\n// these approaches, complete with TODOs, in stacktrace_win32-inl.h#1\n//\n// The solution we've ended up doing is to call the undocumented\n// windows function RtlCaptureStackBackTrace, which probably doesn't\n// work with FPO but at least is fast, and doesn't require a symbol\n// server.\n//\n// This code is inspired by a patch from David Vitek:\n//   https://code.google.com/p/google-perftools/issues/detail?id=83\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_\n\n#include <windows.h>  // CaptureStackBackTrace\n\n#include <cassert>\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nstatic int UnwindImpl(void** result, uintptr_t* frames, int* sizes,\n                      int max_depth, int skip_count, const void*,\n                      int* min_dropped_frames) {\n  USHORT n = 0;\n  if (skip_count < 0 || max_depth < 0) {\n    // can't get a stacktrace with no function/invalid args\n  } else {\n    n = CaptureStackBackTrace(static_cast<ULONG>(skip_count) + 2,\n                              static_cast<ULONG>(max_depth), result, 0);\n  }\n  if (IS_STACK_FRAMES) {\n    // No implementation for finding out the stack frames yet.\n    if (frames != nullptr) {\n      memset(frames, 0, sizeof(*frames) * n);\n    }\n    if (sizes != nullptr) {\n      memset(sizes, 0, sizeof(*sizes) * n);\n    }\n  }\n  if (min_dropped_frames != nullptr) {\n    // Not implemented.\n    *min_dropped_frames = 0;\n  }\n  return n;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return false;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_\n"
  },
  {
    "path": "absl/debugging/internal/stacktrace_x86-inl.inc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Produce stack trace\n\n#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_\n#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_\n\n#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))\n#include <ucontext.h>  // for ucontext_t\n#endif\n\n#if !defined(_WIN32)\n#include <unistd.h>\n#endif\n\n#include <cassert>\n#include <cstdint>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/port.h\"\n#include \"absl/debugging/internal/address_is_readable.h\"\n#include \"absl/debugging/internal/addresses.h\"\n#include \"absl/debugging/internal/vdso_support.h\"  // a no-op on non-elf or non-glibc systems\n#include \"absl/debugging/stacktrace.h\"\n\nusing absl::debugging_internal::AddressIsReadable;\n\n#if defined(__linux__) && defined(__i386__)\n// Count \"push %reg\" instructions in VDSO __kernel_vsyscall(),\n// preceding \"syscall\" or \"sysenter\".\n// If __kernel_vsyscall uses frame pointer, answer 0.\n//\n// kMaxBytes tells how many instruction bytes of __kernel_vsyscall\n// to analyze before giving up. Up to kMaxBytes+1 bytes of\n// instructions could be accessed.\n//\n// Here are known __kernel_vsyscall instruction sequences:\n//\n// SYSENTER (linux-2.6.26/arch/x86/vdso/vdso32/sysenter.S).\n// Used on Intel.\n//  0xffffe400 <__kernel_vsyscall+0>:       push   %ecx\n//  0xffffe401 <__kernel_vsyscall+1>:       push   %edx\n//  0xffffe402 <__kernel_vsyscall+2>:       push   %ebp\n//  0xffffe403 <__kernel_vsyscall+3>:       mov    %esp,%ebp\n//  0xffffe405 <__kernel_vsyscall+5>:       sysenter\n//\n// SYSCALL (see linux-2.6.26/arch/x86/vdso/vdso32/syscall.S).\n// Used on AMD.\n//  0xffffe400 <__kernel_vsyscall+0>:       push   %ebp\n//  0xffffe401 <__kernel_vsyscall+1>:       mov    %ecx,%ebp\n//  0xffffe403 <__kernel_vsyscall+3>:       syscall\n//\n\n// The sequence below isn't actually expected in Google fleet,\n// here only for completeness. Remove this comment from OSS release.\n\n// i386 (see linux-2.6.26/arch/x86/vdso/vdso32/int80.S)\n//  0xffffe400 <__kernel_vsyscall+0>:       int $0x80\n//  0xffffe401 <__kernel_vsyscall+1>:       ret\n//\nstatic const int kMaxBytes = 10;\n\n// We use assert()s instead of DCHECK()s -- this is too low level\n// for DCHECK().\n\nstatic int CountPushInstructions(const unsigned char *const addr) {\n  int result = 0;\n  for (int i = 0; i < kMaxBytes; ++i) {\n    if (addr[i] == 0x89) {\n      // \"mov reg,reg\"\n      if (addr[i + 1] == 0xE5) {\n        // Found \"mov %esp,%ebp\".\n        return 0;\n      }\n      ++i;  // Skip register encoding byte.\n    } else if (addr[i] == 0x0F &&\n               (addr[i + 1] == 0x34 || addr[i + 1] == 0x05)) {\n      // Found \"sysenter\" or \"syscall\".\n      return result;\n    } else if ((addr[i] & 0xF0) == 0x50) {\n      // Found \"push %reg\".\n      ++result;\n    } else if (addr[i] == 0xCD && addr[i + 1] == 0x80) {\n      // Found \"int $0x80\"\n      assert(result == 0);\n      return 0;\n    } else {\n      // Unexpected instruction.\n      assert(false && \"unexpected instruction in __kernel_vsyscall\");\n      return 0;\n    }\n  }\n  // Unexpected: didn't find SYSENTER or SYSCALL in\n  // [__kernel_vsyscall, __kernel_vsyscall + kMaxBytes) interval.\n  assert(false && \"did not find SYSENTER or SYSCALL in __kernel_vsyscall\");\n  return 0;\n}\n#endif\n\n// Assume stack frames larger than 100,000 bytes are bogus.\nstatic const int kMaxFrameBytes = 100000;\n// Stack end to use when we don't know the actual stack end\n// (effectively just the end of address space).\nconstexpr uintptr_t kUnknownStackEnd =\n    std::numeric_limits<size_t>::max() - sizeof(void *);\n\n// Returns the stack frame pointer from signal context, 0 if unknown.\n// vuc is a ucontext_t *.  We use void* to avoid the use\n// of ucontext_t on non-POSIX systems.\nstatic uintptr_t GetFP(const void *vuc) {\n#if !defined(__linux__)\n  static_cast<void>(vuc);  // Avoid an unused argument compiler warning.\n#else\n  if (vuc != nullptr) {\n    auto *uc = reinterpret_cast<const ucontext_t *>(vuc);\n#if defined(__i386__)\n    const auto bp = uc->uc_mcontext.gregs[REG_EBP];\n    const auto sp = uc->uc_mcontext.gregs[REG_ESP];\n#elif defined(__x86_64__)\n    const auto bp = uc->uc_mcontext.gregs[REG_RBP];\n    const auto sp = uc->uc_mcontext.gregs[REG_RSP];\n#else\n    const uintptr_t bp = 0;\n    const uintptr_t sp = 0;\n#endif\n    // Sanity-check that the base pointer is valid. It's possible that some\n    // code in the process is compiled with --copt=-fomit-frame-pointer or\n    // --copt=-momit-leaf-frame-pointer.\n    //\n    // TODO(bcmills): -momit-leaf-frame-pointer is currently the default\n    // behavior when building with clang.  Talk to the C++ toolchain team about\n    // fixing that.\n    if (bp >= sp && bp - sp <= kMaxFrameBytes)\n      return static_cast<uintptr_t>(bp);\n\n    // If bp isn't a plausible frame pointer, return the stack pointer instead.\n    // If we're lucky, it points to the start of a stack frame; otherwise, we'll\n    // get one frame of garbage in the stack trace and fail the sanity check on\n    // the next iteration.\n    return static_cast<uintptr_t>(sp);\n  }\n#endif\n  return 0;\n}\n\n// Given a pointer to a stack frame, locate and return the calling\n// stackframe, or return null if no stackframe can be found. Perform sanity\n// checks (the strictness of which is controlled by the boolean parameter\n// \"STRICT_UNWINDING\") to reduce the chance that a bad pointer is returned.\ntemplate <bool STRICT_UNWINDING, bool WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nstatic void **NextStackFrame(void **old_fp, const void *uc,\n                             size_t stack_low, size_t stack_high) {\n  void **new_fp = (void **)*old_fp;\n\n#if defined(__linux__) && defined(__i386__)\n  if (WITH_CONTEXT && uc != nullptr) {\n    // How many \"push %reg\" instructions are there at __kernel_vsyscall?\n    // This is constant for a given kernel and processor, so compute\n    // it only once.\n    static int num_push_instructions = -1;  // Sentinel: not computed yet.\n    // Initialize with sentinel value: __kernel_rt_sigreturn can not possibly\n    // be there.\n    static const unsigned char *kernel_rt_sigreturn_address = nullptr;\n    static const unsigned char *kernel_vsyscall_address = nullptr;\n    if (num_push_instructions == -1) {\n#ifdef ABSL_HAVE_VDSO_SUPPORT\n      absl::debugging_internal::VDSOSupport vdso;\n      if (vdso.IsPresent()) {\n        absl::debugging_internal::VDSOSupport::SymbolInfo\n            rt_sigreturn_symbol_info;\n        absl::debugging_internal::VDSOSupport::SymbolInfo vsyscall_symbol_info;\n        if (!vdso.LookupSymbol(\"__kernel_rt_sigreturn\", \"LINUX_2.5\", STT_FUNC,\n                               &rt_sigreturn_symbol_info) ||\n            !vdso.LookupSymbol(\"__kernel_vsyscall\", \"LINUX_2.5\", STT_FUNC,\n                               &vsyscall_symbol_info) ||\n            rt_sigreturn_symbol_info.address == nullptr ||\n            vsyscall_symbol_info.address == nullptr) {\n          // Unexpected: 32-bit VDSO is present, yet one of the expected\n          // symbols is missing or null.\n          assert(false && \"VDSO is present, but doesn't have expected symbols\");\n          num_push_instructions = 0;\n        } else {\n          kernel_rt_sigreturn_address =\n              reinterpret_cast<const unsigned char *>(\n                  rt_sigreturn_symbol_info.address);\n          kernel_vsyscall_address =\n              reinterpret_cast<const unsigned char *>(\n                  vsyscall_symbol_info.address);\n          num_push_instructions =\n              CountPushInstructions(kernel_vsyscall_address);\n        }\n      } else {\n        num_push_instructions = 0;\n      }\n#else  // ABSL_HAVE_VDSO_SUPPORT\n      num_push_instructions = 0;\n#endif  // ABSL_HAVE_VDSO_SUPPORT\n    }\n    if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr &&\n        old_fp[1] == kernel_rt_sigreturn_address) {\n      const ucontext_t *ucv = static_cast<const ucontext_t *>(uc);\n      // This kernel does not use frame pointer in its VDSO code,\n      // and so %ebp is not suitable for unwinding.\n      void **const reg_ebp =\n          reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_EBP]);\n      const unsigned char *const reg_eip =\n          reinterpret_cast<unsigned char *>(ucv->uc_mcontext.gregs[REG_EIP]);\n      if (new_fp == reg_ebp && kernel_vsyscall_address <= reg_eip &&\n          reg_eip - kernel_vsyscall_address < kMaxBytes) {\n        // We \"stepped up\" to __kernel_vsyscall, but %ebp is not usable.\n        // Restore from 'ucv' instead.\n        void **const reg_esp =\n            reinterpret_cast<void **>(ucv->uc_mcontext.gregs[REG_ESP]);\n        // Check that alleged %esp is not null and is reasonably aligned.\n        if (reg_esp &&\n            ((uintptr_t)reg_esp & (sizeof(reg_esp) - 1)) == 0) {\n          // Check that alleged %esp is actually readable. This is to prevent\n          // \"double fault\" in case we hit the first fault due to e.g. stack\n          // corruption.\n          void *const reg_esp2 = reg_esp[num_push_instructions - 1];\n          if (AddressIsReadable(reg_esp2)) {\n            // Alleged %esp is readable, use it for further unwinding.\n            new_fp = reinterpret_cast<void **>(reg_esp2);\n          }\n        }\n      }\n    }\n  }\n#endif\n\n  const size_t page_size = static_cast<size_t>(getpagesize());\n  const uintptr_t old_fp_u = reinterpret_cast<uintptr_t>(old_fp);\n  const uintptr_t new_fp_u = reinterpret_cast<uintptr_t>(new_fp);\n\n  // Check that the transition from frame pointer old_fp to frame\n  // pointer new_fp isn't clearly bogus.  Skip the checks if new_fp\n  // matches the signal context, so that we don't skip out early when\n  // using an alternate signal stack.\n  //\n  // TODO(bcmills): The GetFP call should be completely unnecessary when\n  // ENABLE_COMBINED_UNWINDER is set (because we should be back in the thread's\n  // stack by this point), but it is empirically still needed (e.g. when the\n  // stack includes a call to abort).  unw_get_reg returns UNW_EBADREG for some\n  // frames.  Figure out why GetValidFrameAddr and/or libunwind isn't doing what\n  // it's supposed to.\n  if (STRICT_UNWINDING &&\n      (!WITH_CONTEXT || uc == nullptr || new_fp_u != GetFP(uc))) {\n    // With the stack growing downwards, older stack frame should be\n    // at a greater address that the current one. However if we get multiple\n    // signals handled on altstack the new frame pointer might return to the\n    // main stack, but be different than the value from the most recent\n    // ucontext.\n    // If we get a very large frame size, it may be an indication that we\n    // guessed frame pointers incorrectly and now risk a paging fault\n    // dereferencing a wrong frame pointer. Or maybe not because large frames\n    // are possible as well. The main stack is assumed to be readable,\n    // so we assume the large frame is legit if we know the real stack bounds\n    // and are within the stack.\n    if (new_fp_u <= old_fp_u || new_fp_u - old_fp_u > kMaxFrameBytes) {\n      if (stack_high < kUnknownStackEnd && page_size < stack_low) {\n        // Stack bounds are known.\n        if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {\n          // new_fp_u is not within the known stack.\n          return nullptr;\n        }\n      } else {\n        // Stack bounds are unknown, prefer truncated stack to possible crash.\n        return nullptr;\n      }\n    }\n    if (stack_low < old_fp_u && old_fp_u <= stack_high) {\n      // Old BP was in the expected stack region...\n      if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {\n        // ... but new BP is outside of expected stack region.\n        // It is most likely bogus.\n        return nullptr;\n      }\n    } else {\n      // We may be here if we are executing in a co-routine with a\n      // separate stack. We can't do safety checks in this case.\n    }\n  } else {\n    if (new_fp == nullptr) return nullptr;  // skip AddressIsReadable() below\n    // In the non-strict mode, allow discontiguous stack frames.\n    // (alternate-signal-stacks for example).\n    if (new_fp == old_fp) return nullptr;\n  }\n\n  if (new_fp_u & (sizeof(void *) - 1)) return nullptr;\n#ifdef __i386__\n  // On 32-bit machines, the stack pointer can be very close to\n  // 0xffffffff, so we explicitly check for a pointer into the\n  // last two pages in the address space\n  if (new_fp_u >= 0xffffe000) return nullptr;\n#endif\n#if !defined(_WIN32)\n  const uintptr_t old_fp_page = old_fp_u & ~(page_size - 1);\n  const uintptr_t new_fp_page = new_fp_u & ~(page_size - 1);\n  if (old_fp_page == new_fp_page && (new_fp_u & (sizeof(void*) - 1)) == 0) {\n    // We dereferenced the old_fp above, so it is safe to dereference\n    // new_fp if it's on the same page as the old_fp and is aligned.\n  } else if (!STRICT_UNWINDING) {\n    // Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test\n    // on AMD-based machines with VDSO-enabled kernels.\n    // Make an extra sanity check to insure new_fp is readable.\n    // Note: NextStackFrame<false>() is only called while the program\n    //       is already on its last leg, so it's ok to be slow here.\n\n    if (!AddressIsReadable(new_fp)) {\n      return nullptr;\n    }\n  }\n#endif\n  return new_fp;\n}\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.\nABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.\nABSL_ATTRIBUTE_NOINLINE\nstatic int UnwindImpl(void **result, uintptr_t *frames, int *sizes,\n                      int max_depth, int skip_count, const void *ucp,\n                      int *min_dropped_frames) {\n  int n = 0;\n  void **fp = reinterpret_cast<void **>(__builtin_frame_address(0));\n\n  // Assume that the first page is not stack.\n  size_t stack_low = static_cast<size_t>(getpagesize());\n  size_t stack_high = kUnknownStackEnd;\n\n  while (fp && n < max_depth) {\n    if (*(fp + 1) == reinterpret_cast<void *>(0)) {\n      // In 64-bit code, we often see a frame that\n      // points to itself and has a return address of 0.\n      break;\n    }\n    void **next_fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(\n        fp, ucp, stack_low, stack_high);\n    if (skip_count > 0) {\n      skip_count--;\n    } else {\n      result[n] = *(fp + 1);\n      if (IS_STACK_FRAMES) {\n        if (frames) {\n          frames[n] = absl::debugging_internal::StripPointerMetadata(fp) +\n                      2 * sizeof(void *) /* go past the return address */;\n        }\n        if (sizes) {\n          if (next_fp > fp) {\n            sizes[n] = static_cast<int>(\n                absl::debugging_internal::StripPointerMetadata(next_fp) -\n                absl::debugging_internal::StripPointerMetadata(fp));\n          } else {\n            // A frame-size of 0 is used to indicate unknown frame size.\n            sizes[n] = 0;\n          }\n        }\n      }\n      n++;\n    }\n    fp = next_fp;\n  }\n  if (min_dropped_frames != nullptr) {\n    // Implementation detail: we clamp the max of frames we are willing to\n    // count, so as not to spend too much time in the loop below.\n    const int kMaxUnwind = 1000;\n    int num_dropped_frames = 0;\n    for (int j = 0; fp != nullptr && j < kMaxUnwind; j++) {\n      if (skip_count > 0) {\n        skip_count--;\n      } else {\n        num_dropped_frames++;\n      }\n      fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(fp, ucp, stack_low,\n                                                             stack_high);\n    }\n    *min_dropped_frames = num_dropped_frames;\n  }\n  return n;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nbool StackTraceWorksForTest() {\n  return true;\n}\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_\n"
  },
  {
    "path": "absl/debugging/internal/symbolize.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file contains internal parts of the Abseil symbolizer.\n// Do not depend on the anything in this file, it may change at anytime.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_\n#define ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_\n\n#ifdef __cplusplus\n\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE\n#error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set\n#elif defined(__ELF__) && defined(__GLIBC__) && !defined(__asmjs__) \\\n      && !defined(__wasm__)\n#define ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE 1\n\n#include <elf.h>\n#include <link.h>  // For ElfW() macro.\n#include <functional>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Iterates over all sections, invoking callback on each with the section name\n// and the section header.\n//\n// Returns true on success; otherwise returns false in case of errors.\n//\n// This is not async-signal-safe.\nbool ForEachSection(int fd,\n                    const std::function<bool(absl::string_view name,\n                                             const ElfW(Shdr) &)>& callback);\n\n// Gets the section header for the given name, if it exists. Returns true on\n// success. Otherwise, returns false.\nbool GetSectionHeaderByName(int fd, const char *name, size_t name_len,\n                            ElfW(Shdr) *out);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE\n\n#ifdef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE\n#error ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE cannot be directly set\n#elif defined(__APPLE__)\n#define ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE 1\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE\n#error ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE cannot be directly set\n#elif defined(__EMSCRIPTEN__)\n#define ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nclass SymbolDecorator;\n\nclass SymbolDecoratorDeleter {\n public:\n  void operator()(SymbolDecorator* ptr);\n};\n\nusing SymbolDecoratorPtr =\n    std::unique_ptr<SymbolDecorator, SymbolDecoratorDeleter>;\n\n// Represents an object that can add additional information to a symbol\n// name.\nclass SymbolDecorator {\n public:\n  // The signature of a factory function used to register and create a symbol\n  // decorator. This function may be called from a signal handler, so it must\n  // use an async-signal-safe allocation mechanism to allocate the returned\n  // object.\n  using Factory = SymbolDecoratorPtr(int fd);\n\n  virtual ~SymbolDecorator() = default;\n\n  // Decorates symbol name with additional information.\n  //\n  // pc represents the program counter we are getting symbolic name for.\n  // relocation is difference between the link-time and the load-time address.\n  // symbol_buf and symbol_buf_size represent the output buffer and its size.\n  // Note that the buffer may not be empty -- default symbolizer may have\n  // already produced some output. You are free to replace or augment the\n  // contents (within the symbol_buf_size limit). tmp_buf and tmp_buf_size\n  // represent temporary scratch space and its size. Use that space in\n  // preference to allocating your own stack buffer to conserve stack.\n  //\n  // This function will not be called concurrently for the same object, but it\n  // may be called from a signal handler, so it must avoid any operation that is\n  // not async-signal-safe. However, it does not have to be reentrant -- if it\n  // is interrupted by a signal and the handler tries to symbolize, the request\n  // will go to a new SymbolDecorator instance.\n  virtual void Decorate(\n      const void* pc,\n      ptrdiff_t relocation,\n      char* symbol_buf, size_t symbol_buf_size,\n      char* tmp_buf, size_t tmp_buf_size) const = 0;\n};\n\n// Registers a new symbol decorator factory and returns the previous one.\nSymbolDecorator::Factory* SetSymbolDecoratorFactory(\n    SymbolDecorator::Factory* factory);\n\n// Registers an address range to a file mapping.\n//\n// Preconditions:\n//   start <= end\n//   filename != nullptr\n//\n// Returns true if the file was successfully registered.\nbool RegisterFileMappingHint(const void* start, const void* end,\n                             uint64_t offset, const char* filename);\n\n// Looks up the file mapping registered by RegisterFileMappingHint for an\n// address range. If there is one, the file name is stored in *filename and\n// *start and *end are modified to reflect the registered mapping. Returns\n// whether any hint was found.\nbool GetFileMappingHint(const void** start, const void** end, uint64_t* offset,\n                        const char** filename);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // __cplusplus\n\n#include <stdbool.h>\n\n#ifdef __cplusplus\nextern \"C\"\n#endif  // __cplusplus\n\n    bool\n    AbslInternalGetFileMappingHint(const void** start, const void** end,\n                                   uint64_t* offset, const char** filename);\n\n#endif  // ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_\n"
  },
  {
    "path": "absl/debugging/internal/utf8_for_code_point.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/utf8_for_code_point.h\"\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\n// UTF-8 encoding bounds.\nconstexpr uint32_t kMinSurrogate = 0xd800, kMaxSurrogate = 0xdfff;\nconstexpr uint32_t kMax1ByteCodePoint = 0x7f;\nconstexpr uint32_t kMax2ByteCodePoint = 0x7ff;\nconstexpr uint32_t kMax3ByteCodePoint = 0xffff;\nconstexpr uint32_t kMaxCodePoint = 0x10ffff;\n\n}  // namespace\n\nUtf8ForCodePoint::Utf8ForCodePoint(uint64_t code_point) {\n  if (code_point <= kMax1ByteCodePoint) {\n    length = 1;\n    bytes[0] = static_cast<char>(code_point);\n    return;\n  }\n\n  if (code_point <= kMax2ByteCodePoint) {\n    length = 2;\n    bytes[0] = static_cast<char>(0xc0 | (code_point >> 6));\n    bytes[1] = static_cast<char>(0x80 | (code_point & 0x3f));\n    return;\n  }\n\n  if (kMinSurrogate <= code_point && code_point <= kMaxSurrogate) return;\n\n  if (code_point <= kMax3ByteCodePoint) {\n    length = 3;\n    bytes[0] = static_cast<char>(0xe0 | (code_point >> 12));\n    bytes[1] = static_cast<char>(0x80 | ((code_point >> 6) & 0x3f));\n    bytes[2] = static_cast<char>(0x80 | (code_point & 0x3f));\n    return;\n  }\n\n  if (code_point > kMaxCodePoint) return;\n\n  length = 4;\n  bytes[0] = static_cast<char>(0xf0 | (code_point >> 18));\n  bytes[1] = static_cast<char>(0x80 | ((code_point >> 12) & 0x3f));\n  bytes[2] = static_cast<char>(0x80 | ((code_point >> 6) & 0x3f));\n  bytes[3] = static_cast<char>(0x80 | (code_point & 0x3f));\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/utf8_for_code_point.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_DEBUGGING_INTERNAL_UTF8_FOR_CODE_POINT_H_\n#define ABSL_DEBUGGING_INTERNAL_UTF8_FOR_CODE_POINT_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nstruct Utf8ForCodePoint {\n  // Converts a Unicode code point to the corresponding UTF-8 byte sequence.\n  // Async-signal-safe to support use in symbolizing stack traces from a signal\n  // handler.\n  explicit Utf8ForCodePoint(uint64_t code_point);\n\n  // Returns true if the constructor's code_point argument was valid.\n  bool ok() const { return length != 0; }\n\n  // If code_point was in range, then 1 <= length <= 4, and the UTF-8 encoding\n  // is found in bytes[0 .. (length - 1)].  If code_point was invalid, then\n  // length == 0.  In either case, the contents of bytes[length .. 3] are\n  // unspecified.\n  char bytes[4] = {};\n  uint32_t length = 0;\n};\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_INTERNAL_UTF8_FOR_CODE_POINT_H_\n"
  },
  {
    "path": "absl/debugging/internal/utf8_for_code_point_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/internal/utf8_for_code_point.h\"\n\n#include <cstdint>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\nnamespace {\n\nTEST(Utf8ForCodePointTest, RecognizesTheSmallestCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0});\n  ASSERT_EQ(utf8.length, 1);\n  EXPECT_EQ(utf8.bytes[0], '\\0');\n}\n\nTEST(Utf8ForCodePointTest, RecognizesAsciiSmallA) {\n  Utf8ForCodePoint utf8(uint64_t{'a'});\n  ASSERT_EQ(utf8.length, 1);\n  EXPECT_EQ(utf8.bytes[0], 'a');\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheLargestOneByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x7f});\n  ASSERT_EQ(utf8.length, 1);\n  EXPECT_EQ(utf8.bytes[0], '\\x7f');\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheSmallestTwoByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x80});\n  ASSERT_EQ(utf8.length, 2);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xc2));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0x80));\n}\n\nTEST(Utf8ForCodePointTest, RecognizesSmallNWithTilde) {\n  Utf8ForCodePoint utf8(uint64_t{0xf1});\n  ASSERT_EQ(utf8.length, 2);\n  const char* want = \"ñ\";\n  EXPECT_EQ(utf8.bytes[0], want[0]);\n  EXPECT_EQ(utf8.bytes[1], want[1]);\n}\n\nTEST(Utf8ForCodePointTest, RecognizesCapitalPi) {\n  Utf8ForCodePoint utf8(uint64_t{0x3a0});\n  ASSERT_EQ(utf8.length, 2);\n  const char* want = \"Π\";\n  EXPECT_EQ(utf8.bytes[0], want[0]);\n  EXPECT_EQ(utf8.bytes[1], want[1]);\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheLargestTwoByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x7ff});\n  ASSERT_EQ(utf8.length, 2);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xdf));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0xbf));\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheSmallestThreeByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x800});\n  ASSERT_EQ(utf8.length, 3);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xe0));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0xa0));\n  EXPECT_EQ(utf8.bytes[2], static_cast<char>(0x80));\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheChineseCharacterZhong1AsInZhong1Wen2) {\n  Utf8ForCodePoint utf8(uint64_t{0x4e2d});\n  ASSERT_EQ(utf8.length, 3);\n  const char* want = \"中\";\n  EXPECT_EQ(utf8.bytes[0], want[0]);\n  EXPECT_EQ(utf8.bytes[1], want[1]);\n  EXPECT_EQ(utf8.bytes[2], want[2]);\n}\n\nTEST(Utf8ForCodePointTest, RecognizesOneBeforeTheSmallestSurrogate) {\n  Utf8ForCodePoint utf8(uint64_t{0xd7ff});\n  ASSERT_EQ(utf8.length, 3);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xed));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0x9f));\n  EXPECT_EQ(utf8.bytes[2], static_cast<char>(0xbf));\n}\n\nTEST(Utf8ForCodePointTest, RejectsTheSmallestSurrogate) {\n  Utf8ForCodePoint utf8(uint64_t{0xd800});\n  EXPECT_EQ(utf8.length, 0);\n}\n\nTEST(Utf8ForCodePointTest, RejectsTheLargestSurrogate) {\n  Utf8ForCodePoint utf8(uint64_t{0xdfff});\n  EXPECT_EQ(utf8.length, 0);\n}\n\nTEST(Utf8ForCodePointTest, RecognizesOnePastTheLargestSurrogate) {\n  Utf8ForCodePoint utf8(uint64_t{0xe000});\n  ASSERT_EQ(utf8.length, 3);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xee));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0x80));\n  EXPECT_EQ(utf8.bytes[2], static_cast<char>(0x80));\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheLargestThreeByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0xffff});\n  ASSERT_EQ(utf8.length, 3);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xef));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0xbf));\n  EXPECT_EQ(utf8.bytes[2], static_cast<char>(0xbf));\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheSmallestFourByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x10000});\n  ASSERT_EQ(utf8.length, 4);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xf0));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0x90));\n  EXPECT_EQ(utf8.bytes[2], static_cast<char>(0x80));\n  EXPECT_EQ(utf8.bytes[3], static_cast<char>(0x80));\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheJackOfHearts) {\n  Utf8ForCodePoint utf8(uint64_t{0x1f0bb});\n  ASSERT_EQ(utf8.length, 4);\n  const char* want = \"🂻\";\n  EXPECT_EQ(utf8.bytes[0], want[0]);\n  EXPECT_EQ(utf8.bytes[1], want[1]);\n  EXPECT_EQ(utf8.bytes[2], want[2]);\n  EXPECT_EQ(utf8.bytes[3], want[3]);\n}\n\nTEST(Utf8ForCodePointTest, RecognizesTheLargestFourByteCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x10ffff});\n  ASSERT_EQ(utf8.length, 4);\n  EXPECT_EQ(utf8.bytes[0], static_cast<char>(0xf4));\n  EXPECT_EQ(utf8.bytes[1], static_cast<char>(0x8f));\n  EXPECT_EQ(utf8.bytes[2], static_cast<char>(0xbf));\n  EXPECT_EQ(utf8.bytes[3], static_cast<char>(0xbf));\n}\n\nTEST(Utf8ForCodePointTest, RejectsTheSmallestOverlargeCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0x110000});\n  EXPECT_EQ(utf8.length, 0);\n}\n\nTEST(Utf8ForCodePointTest, RejectsAThroughlyOverlargeCodePoint) {\n  Utf8ForCodePoint utf8(uint64_t{0xffffffff00000000});\n  EXPECT_EQ(utf8.length, 0);\n}\n\nTEST(Utf8ForCodePointTest, OkReturnsTrueForAValidCodePoint) {\n  EXPECT_TRUE(Utf8ForCodePoint(uint64_t{0}).ok());\n}\n\nTEST(Utf8ForCodePointTest, OkReturnsFalseForAnInvalidCodePoint) {\n  EXPECT_FALSE(Utf8ForCodePoint(uint64_t{0xffffffff00000000}).ok());\n}\n\n}  // namespace\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/internal/vdso_support.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Allow dynamic symbol lookup in the kernel VDSO page.\n//\n// VDSOSupport -- a class representing kernel VDSO (if present).\n\n#include \"absl/debugging/internal/vdso_support.h\"\n#include \"absl/base/attributes.h\"\n\n#ifdef ABSL_HAVE_VDSO_SUPPORT     // defined in vdso_support.h\n\n#if !defined(__has_include)\n#define __has_include(header) 0\n#endif\n\n#include <errno.h>\n#include <fcntl.h>\n#if __has_include(<syscall.h>)\n#include <syscall.h>\n#elif __has_include(<sys/syscall.h>)\n#include <sys/syscall.h>\n#endif\n#include <unistd.h>\n\n#if !defined(__UCLIBC__) && defined(__GLIBC__) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))\n#define ABSL_HAVE_GETAUXVAL\n#endif\n\n#ifdef ABSL_HAVE_GETAUXVAL\n#include <sys/auxv.h>\n#endif\n\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/port.h\"\n\n#ifndef AT_SYSINFO_EHDR\n#define AT_SYSINFO_EHDR 33  // for crosstoolv10\n#endif\n\n#if defined(__NetBSD__)\nusing Elf32_auxv_t = Aux32Info;\nusing Elf64_auxv_t = Aux64Info;\n#endif\n#if defined(__FreeBSD__)\n#if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64\nusing Elf64_auxv_t = Elf64_Auxinfo;\n#endif\nusing Elf32_auxv_t = Elf32_Auxinfo;\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nABSL_CONST_INIT\nstd::atomic<const void *> VDSOSupport::vdso_base_(\n    debugging_internal::ElfMemImage::kInvalidBase);\n\nABSL_CONST_INIT std::atomic<VDSOSupport::GetCpuFn> VDSOSupport::getcpu_fn_(\n    &InitAndGetCPU);\n\nVDSOSupport::VDSOSupport()\n    // If vdso_base_ is still set to kInvalidBase, we got here\n    // before VDSOSupport::Init has been called. Call it now.\n    : image_(vdso_base_.load(std::memory_order_relaxed) ==\n                     debugging_internal::ElfMemImage::kInvalidBase\n                 ? Init()\n                 : vdso_base_.load(std::memory_order_relaxed)) {}\n\n// NOTE: we can't use GoogleOnceInit() below, because we can be\n// called by tcmalloc, and none of the *once* stuff may be functional yet.\n//\n// In addition, we hope that the VDSOSupportHelper constructor\n// causes this code to run before there are any threads, and before\n// InitGoogle() has executed any chroot or setuid calls.\n//\n// Finally, even if there is a race here, it is harmless, because\n// the operation should be idempotent.\nconst void *VDSOSupport::Init() {\n  const auto kInvalidBase = debugging_internal::ElfMemImage::kInvalidBase;\n#ifdef ABSL_HAVE_GETAUXVAL\n  if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {\n    errno = 0;\n    const void *const sysinfo_ehdr =\n        reinterpret_cast<const void *>(getauxval(AT_SYSINFO_EHDR));\n    if (errno == 0) {\n      vdso_base_.store(sysinfo_ehdr, std::memory_order_relaxed);\n    }\n  }\n#endif  // ABSL_HAVE_GETAUXVAL\n  if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {\n    int fd = open(\"/proc/self/auxv\", O_RDONLY);\n    if (fd == -1) {\n      // Kernel too old to have a VDSO.\n      vdso_base_.store(nullptr, std::memory_order_relaxed);\n      getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);\n      return nullptr;\n    }\n    ElfW(auxv_t) aux;\n    while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) {\n      if (aux.a_type == AT_SYSINFO_EHDR) {\n#if defined(__NetBSD__)\n        vdso_base_.store(reinterpret_cast<void *>(aux.a_v),\n                         std::memory_order_relaxed);\n#else\n        vdso_base_.store(reinterpret_cast<void *>(aux.a_un.a_val),\n                         std::memory_order_relaxed);\n#endif\n        break;\n      }\n    }\n    close(fd);\n    if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {\n      // Didn't find AT_SYSINFO_EHDR in auxv[].\n      vdso_base_.store(nullptr, std::memory_order_relaxed);\n    }\n  }\n  GetCpuFn fn = &GetCPUViaSyscall;  // default if VDSO not present.\n  if (vdso_base_.load(std::memory_order_relaxed)) {\n    VDSOSupport vdso;\n    SymbolInfo info;\n    if (vdso.LookupSymbol(\"__vdso_getcpu\", \"LINUX_2.6\", STT_FUNC, &info)) {\n      fn = reinterpret_cast<GetCpuFn>(const_cast<void *>(info.address));\n    }\n  }\n  // Subtle: this code runs outside of any locks; prevent compiler\n  // from assigning to getcpu_fn_ more than once.\n  getcpu_fn_.store(fn, std::memory_order_relaxed);\n  return vdso_base_.load(std::memory_order_relaxed);\n}\n\nconst void *VDSOSupport::SetBase(const void *base) {\n  ABSL_RAW_CHECK(base != debugging_internal::ElfMemImage::kInvalidBase,\n                 \"internal error\");\n  const void *old_base = vdso_base_.load(std::memory_order_relaxed);\n  vdso_base_.store(base, std::memory_order_relaxed);\n  image_.Init(base);\n  // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO.\n  getcpu_fn_.store(&InitAndGetCPU, std::memory_order_relaxed);\n  return old_base;\n}\n\nbool VDSOSupport::LookupSymbol(const char *name,\n                               const char *version,\n                               int type,\n                               SymbolInfo *info) const {\n  return image_.LookupSymbol(name, version, type, info);\n}\n\nbool VDSOSupport::LookupSymbolByAddress(const void *address,\n                                        SymbolInfo *info_out) const {\n  return image_.LookupSymbolByAddress(address, info_out);\n}\n\n// NOLINT on 'long' because this routine mimics kernel api.\nlong VDSOSupport::GetCPUViaSyscall(unsigned *cpu,  // NOLINT(runtime/int)\n                                   void *, void *) {\n#ifdef SYS_getcpu\n  return syscall(SYS_getcpu, cpu, nullptr, nullptr);\n#else\n  // x86_64 never implemented sys_getcpu(), except as a VDSO call.\n  static_cast<void>(cpu);  // Avoid an unused argument compiler warning.\n  errno = ENOSYS;\n  return -1;\n#endif\n}\n\n// Use fast __vdso_getcpu if available.\nlong VDSOSupport::InitAndGetCPU(unsigned *cpu,  // NOLINT(runtime/int)\n                                void *x, void *y) {\n  Init();\n  GetCpuFn fn = getcpu_fn_.load(std::memory_order_relaxed);\n  ABSL_RAW_CHECK(fn != &InitAndGetCPU, \"Init() did not set getcpu_fn_\");\n  return (*fn)(cpu, x, y);\n}\n\n// This function must be very fast, and may be called from very\n// low level (e.g. tcmalloc). Hence I avoid things like\n// GoogleOnceInit() and ::operator new.\n// The destination in VDSO is unknown to CFI and VDSO does not set MSAN\n// shadow for the return value.\nABSL_ATTRIBUTE_NO_SANITIZE_CFI\nABSL_ATTRIBUTE_NO_SANITIZE_MEMORY\nint GetCPU() {\n  unsigned cpu;\n  long ret_code =  // NOLINT(runtime/int)\n      (*VDSOSupport::getcpu_fn_)(&cpu, nullptr, nullptr);\n  return ret_code == 0 ? static_cast<int>(cpu) : static_cast<int>(ret_code);\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HAVE_VDSO_SUPPORT\n"
  },
  {
    "path": "absl/debugging/internal/vdso_support.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n// Allow dynamic symbol lookup in the kernel VDSO page.\n//\n// VDSO stands for \"Virtual Dynamic Shared Object\" -- a page of\n// executable code, which looks like a shared library, but doesn't\n// necessarily exist anywhere on disk, and which gets mmap()ed into\n// every process by kernels which support VDSO, such as 2.6.x for 32-bit\n// executables, and 2.6.24 and above for 64-bit executables.\n//\n// More details could be found here:\n// http://www.trilithium.com/johan/2005/08/linux-gate/\n//\n// VDSOSupport -- a class representing kernel VDSO (if present).\n//\n// Example usage:\n//  VDSOSupport vdso;\n//  VDSOSupport::SymbolInfo info;\n//  typedef (*FN)(unsigned *, void *, void *);\n//  FN fn = nullptr;\n//  if (vdso.LookupSymbol(\"__vdso_getcpu\", \"LINUX_2.6\", STT_FUNC, &info)) {\n//     fn = reinterpret_cast<FN>(info.address);\n//  }\n\n#ifndef ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_\n#define ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_\n\n#include <atomic>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/debugging/internal/elf_mem_image.h\"\n\n#ifdef ABSL_HAVE_ELF_MEM_IMAGE\n\n#ifdef ABSL_HAVE_VDSO_SUPPORT\n#error ABSL_HAVE_VDSO_SUPPORT cannot be directly set\n#else\n#define ABSL_HAVE_VDSO_SUPPORT 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// NOTE: this class may be used from within tcmalloc, and can not\n// use any memory allocation routines.\nclass VDSOSupport {\n public:\n  VDSOSupport();\n\n  typedef ElfMemImage::SymbolInfo SymbolInfo;\n  typedef ElfMemImage::SymbolIterator SymbolIterator;\n\n  // On PowerPC64 VDSO symbols can either be of type STT_FUNC or STT_NOTYPE\n  // depending on how the kernel is built.  The kernel is normally built with\n  // STT_NOTYPE type VDSO symbols.  Let's make things simpler first by using a\n  // compile-time constant.\n#ifdef __powerpc64__\n  enum { kVDSOSymbolType = STT_NOTYPE };\n#else\n  enum { kVDSOSymbolType = STT_FUNC };\n#endif\n\n  // Answers whether we have a vdso at all.\n  bool IsPresent() const { return image_.IsPresent(); }\n\n  // Allow to iterate over all VDSO symbols.\n  SymbolIterator begin() const { return image_.begin(); }\n  SymbolIterator end() const { return image_.end(); }\n\n  // Look up versioned dynamic symbol in the kernel VDSO.\n  // Returns false if VDSO is not present, or doesn't contain given\n  // symbol/version/type combination.\n  // If info_out != nullptr, additional details are filled in.\n  bool LookupSymbol(const char *name, const char *version,\n                    int symbol_type, SymbolInfo *info_out) const;\n\n  // Find info about symbol (if any) which overlaps given address.\n  // Returns true if symbol was found; false if VDSO isn't present\n  // or doesn't have a symbol overlapping given address.\n  // If info_out != nullptr, additional details are filled in.\n  bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const;\n\n  // Used only for testing. Replace real VDSO base with a mock.\n  // Returns previous value of vdso_base_. After you are done testing,\n  // you are expected to call SetBase() with previous value, in order to\n  // reset state to the way it was.\n  const void *SetBase(const void *s);\n\n  // Computes vdso_base_ and returns it. Should be called as early as\n  // possible; before any thread creation, chroot or setuid.\n  static const void *Init();\n\n private:\n  // image_ represents VDSO ELF image in memory.\n  // image_.ehdr_ == nullptr implies there is no VDSO.\n  ElfMemImage image_;\n\n  // Cached value of auxv AT_SYSINFO_EHDR, computed once.\n  // This is a tri-state:\n  //   kInvalidBase   => value hasn't been determined yet.\n  //              0   => there is no VDSO.\n  //           else   => vma of VDSO Elf{32,64}_Ehdr.\n  //\n  // When testing with mock VDSO, low bit is set.\n  // The low bit is always available because vdso_base_ is\n  // page-aligned.\n  static std::atomic<const void *> vdso_base_;\n\n  // NOLINT on 'long' because these routines mimic kernel api.\n  // The 'cache' parameter may be used by some versions of the kernel,\n  // and should be nullptr or point to a static buffer containing at\n  // least two 'long's.\n  static long InitAndGetCPU(unsigned *cpu, void *cache,     // NOLINT 'long'.\n                            void *unused);\n  static long GetCPUViaSyscall(unsigned *cpu, void *cache,  // NOLINT 'long'.\n                               void *unused);\n  typedef long (*GetCpuFn)(unsigned *cpu, void *cache,      // NOLINT 'long'.\n                           void *unused);\n\n  // This function pointer may point to InitAndGetCPU,\n  // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization.\n  ABSL_CONST_INIT static std::atomic<GetCpuFn> getcpu_fn_;\n\n  friend int GetCPU(void);  // Needs access to getcpu_fn_.\n\n  VDSOSupport(const VDSOSupport&) = delete;\n  VDSOSupport& operator=(const VDSOSupport&) = delete;\n};\n\n// Same as sched_getcpu() on later glibc versions.\n// Return current CPU, using (fast) __vdso_getcpu@LINUX_2.6 if present,\n// otherwise use syscall(SYS_getcpu,...).\n// May return -1 with errno == ENOSYS if the kernel doesn't\n// support SYS_getcpu.\nint GetCPU();\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HAVE_ELF_MEM_IMAGE\n\n#endif  // ABSL_DEBUGGING_INTERNAL_VDSO_SUPPORT_H_\n"
  },
  {
    "path": "absl/debugging/leak_check.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Wrappers around lsan_interface functions.\n//\n// These are always-available run-time functions manipulating the LeakSanitizer,\n// even when the lsan_interface (and LeakSanitizer) is not available. When\n// LeakSanitizer is not linked in, these functions become no-op stubs.\n\n#include \"absl/debugging/leak_check.h\"\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n#if defined(ABSL_HAVE_LEAK_SANITIZER)\n\n#include <sanitizer/lsan_interface.h>\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\nextern \"C\" ABSL_ATTRIBUTE_WEAK int __lsan_is_turned_off() { return 0; }\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nbool HaveLeakSanitizer() { return true; }\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\nbool LeakCheckerIsActive() {\n  return __lsan_is_turned_off() == 0;\n}\n#else\nbool LeakCheckerIsActive() { return true; }\n#endif\n\nbool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check() != 0; }\nvoid DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); }\nvoid RegisterLivePointers(const void* ptr, size_t size) {\n  __lsan_register_root_region(ptr, size);\n}\nvoid UnRegisterLivePointers(const void* ptr, size_t size) {\n  __lsan_unregister_root_region(ptr, size);\n}\nLeakCheckDisabler::LeakCheckDisabler() { __lsan_disable(); }\nLeakCheckDisabler::~LeakCheckDisabler() { __lsan_enable(); }\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#else  // defined(ABSL_HAVE_LEAK_SANITIZER)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nbool HaveLeakSanitizer() { return false; }\nbool LeakCheckerIsActive() { return false; }\nvoid DoIgnoreLeak(const void*) { }\nvoid RegisterLivePointers(const void*, size_t) { }\nvoid UnRegisterLivePointers(const void*, size_t) { }\nLeakCheckDisabler::LeakCheckDisabler() = default;\nLeakCheckDisabler::~LeakCheckDisabler() = default;\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // defined(ABSL_HAVE_LEAK_SANITIZER)\n"
  },
  {
    "path": "absl/debugging/leak_check.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: leak_check.h\n// -----------------------------------------------------------------------------\n//\n// This file contains functions that affect leak checking behavior within\n// targets built with the LeakSanitizer (LSan), a memory leak detector that is\n// integrated within the AddressSanitizer (ASan) as an additional component, or\n// which can be used standalone. LSan and ASan are included (or can be provided)\n// as additional components for most compilers such as Clang, gcc and MSVC.\n// Note: this leak checking API is not yet supported in MSVC.\n// Leak checking is enabled by default in all ASan builds.\n//\n// https://clang.llvm.org/docs/LeakSanitizer.html\n// https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer\n//\n// GCC and Clang both automatically enable LeakSanitizer when AddressSanitizer\n// is enabled. To use the mode, simply pass `-fsanitize=address` to both the\n// compiler and linker. An example Bazel command could be\n//\n//   $ bazel test --copt=-fsanitize=address --linkopt=-fsanitize=address ...\n//\n// GCC and Clang auto support a standalone LeakSanitizer mode (a mode which does\n// not also use AddressSanitizer). To use the mode, simply pass\n// `-fsanitize=leak` to both the compiler and linker. Since GCC does not\n// currently provide a way of detecting this mode at compile-time, GCC users\n// must also pass -DLEAK_SANITIZER to the compiler. An example Bazel command\n// could be\n//\n//   $ bazel test --copt=-DLEAK_SANITIZER --copt=-fsanitize=leak\n//     --linkopt=-fsanitize=leak ...\n//\n// -----------------------------------------------------------------------------\n#ifndef ABSL_DEBUGGING_LEAK_CHECK_H_\n#define ABSL_DEBUGGING_LEAK_CHECK_H_\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// HaveLeakSanitizer()\n//\n// Returns true if a leak-checking sanitizer (either ASan or standalone LSan) is\n// currently built into this target.\nbool HaveLeakSanitizer();\n\n// LeakCheckerIsActive()\n//\n// Returns true if a leak-checking sanitizer (either ASan or standalone LSan) is\n// currently built into this target and is turned on.\nbool LeakCheckerIsActive();\n\n// DoIgnoreLeak()\n//\n// Implements `IgnoreLeak()` below. This function should usually\n// not be called directly; calling `IgnoreLeak()` is preferred.\nvoid DoIgnoreLeak(const void* ptr);\n\n// IgnoreLeak()\n//\n// Instruct the leak sanitizer to ignore leak warnings on the object referenced\n// by the passed pointer, as well as all heap objects transitively referenced\n// by it. The passed object pointer can point to either the beginning of the\n// object or anywhere within it.\n//\n// Example:\n//\n//   static T* obj = IgnoreLeak(new T(...));\n//\n// If the passed `ptr` does not point to an actively allocated object at the\n// time `IgnoreLeak()` is called, the call is a no-op; if it is actively\n// allocated, leak sanitizer will assume this object is referenced even if\n// there is no actual reference in user memory.\n//\ntemplate <typename T>\nT* IgnoreLeak(T* ptr) {\n  DoIgnoreLeak(ptr);\n  return ptr;\n}\n\n// FindAndReportLeaks()\n//\n// If any leaks are detected, prints a leak report and returns true.  This\n// function may be called repeatedly, and does not affect end-of-process leak\n// checking.\n//\n// Example:\n// if (FindAndReportLeaks()) {\n//   ... diagnostic already printed. Exit with failure code.\n//   exit(1)\n// }\nbool FindAndReportLeaks();\n\n// LeakCheckDisabler\n//\n// This helper class indicates that any heap allocations done in the code block\n// covered by the scoped object, which should be allocated on the stack, will\n// not be reported as leaks. Leak check disabling will occur within the code\n// block and any nested function calls within the code block.\n//\n// Example:\n//\n//   void Foo() {\n//     LeakCheckDisabler disabler;\n//     ... code that allocates objects whose leaks should be ignored ...\n//   }\n//\n// REQUIRES: Destructor runs in same thread as constructor\nclass LeakCheckDisabler {\n public:\n  LeakCheckDisabler();\n  LeakCheckDisabler(const LeakCheckDisabler&) = delete;\n  LeakCheckDisabler& operator=(const LeakCheckDisabler&) = delete;\n  ~LeakCheckDisabler();\n};\n\n// RegisterLivePointers()\n//\n// Registers `ptr[0,size-1]` as pointers to memory that is still actively being\n// referenced and for which leak checking should be ignored. This function is\n// useful if you store pointers in mapped memory, for memory ranges that we know\n// are correct but for which normal analysis would flag as leaked code.\nvoid RegisterLivePointers(const void* ptr, size_t size);\n\n// UnRegisterLivePointers()\n//\n// Deregisters the pointers previously marked as active in\n// `RegisterLivePointers()`, enabling leak checking of those pointers.\nvoid UnRegisterLivePointers(const void* ptr, size_t size);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_LEAK_CHECK_H_\n"
  },
  {
    "path": "absl/debugging/leak_check_fail_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <memory>\n\n#include \"gtest/gtest.h\"\n#include \"absl/debugging/leak_check.h\"\n#include \"absl/log/log.h\"\n\nnamespace {\n\nTEST(LeakCheckTest, LeakMemory) {\n  // This test is expected to cause lsan failures on program exit. Therefore the\n  // test will be run only by leak_check_test.sh, which will verify a\n  // failed exit code.\n\n  char* foo = strdup(\"lsan should complain about this leaked string\");\n  LOG(INFO) << \"Should detect leaked string \" << foo;\n}\n\nTEST(LeakCheckTest, LeakMemoryAfterDisablerScope) {\n  // This test is expected to cause lsan failures on program exit. Therefore the\n  // test will be run only by external_leak_check_test.sh, which will verify a\n  // failed exit code.\n  { absl::LeakCheckDisabler disabler; }\n  char* foo = strdup(\"lsan should also complain about this leaked string\");\n  LOG(INFO) << \"Re-enabled leak detection.Should detect leaked string \" << foo;\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/debugging/leak_check_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/debugging/leak_check.h\"\n#include \"absl/log/log.h\"\n\nnamespace {\n\nTEST(LeakCheckTest, IgnoreLeakSuppressesLeakedMemoryErrors) {\n  if (!absl::LeakCheckerIsActive()) {\n    GTEST_SKIP() << \"LeakChecker is not active\";\n  }\n  auto foo = absl::IgnoreLeak(new std::string(\"some ignored leaked string\"));\n  LOG(INFO) << \"Ignoring leaked string \" << foo;\n}\n\nTEST(LeakCheckTest, LeakCheckDisablerIgnoresLeak) {\n  if (!absl::LeakCheckerIsActive()) {\n    GTEST_SKIP() << \"LeakChecker is not active\";\n  }\n  absl::LeakCheckDisabler disabler;\n  auto foo = new std::string(\"some string leaked while checks are disabled\");\n  LOG(INFO) << \"Ignoring leaked string \" << foo;\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/debugging/stacktrace.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Produce stack trace.\n//\n// There are three different ways we can try to get the stack trace:\n//\n// 1) Our hand-coded stack-unwinder.  This depends on a certain stack\n//    layout, which is used by gcc (and those systems using a\n//    gcc-compatible ABI) on x86 systems, at least since gcc 2.95.\n//    It uses the frame pointer to do its work.\n//\n// 2) The libunwind library.  This is still in development, and as a\n//    separate library adds a new dependency, but doesn't need a frame\n//    pointer.  It also doesn't call malloc.\n//\n// 3) The gdb unwinder -- also the one used by the c++ exception code.\n//    It's obviously well-tested, but has a fatal flaw: it can call\n//    malloc() from the unwinder.  This is a problem because we're\n//    trying to use the unwinder to instrument malloc().\n//\n// Note: if you add a new implementation here, make sure it works\n// correctly when absl::GetStackTrace() is called with max_depth == 0.\n// Some code may do that.\n\n#include \"absl/debugging/stacktrace.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>\n\n#include <algorithm>\n#include <atomic>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n#include \"absl/debugging/internal/stacktrace_config.h\"\n\n#if defined(ABSL_STACKTRACE_INL_HEADER)\n#include ABSL_STACKTRACE_INL_HEADER\n#else\n#error Cannot calculate stack trace: will need to write for your environment\n\n#include \"absl/debugging/internal/stacktrace_aarch64-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_arm-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_emscripten-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_generic-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_powerpc-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_riscv-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_unimplemented-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_win32-inl.inc\"\n#include \"absl/debugging/internal/stacktrace_x86-inl.inc\"\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\ntypedef int (*Unwinder)(void**, int*, int, int, const void*, int*);\nstd::atomic<Unwinder> custom;\n\ntemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>\nABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, uintptr_t* frames,\n                                               int* sizes, size_t max_depth,\n                                               int skip_count, const void* uc,\n                                               int* min_dropped_frames,\n                                               bool unwind_with_fixup = true) {\n  unwind_with_fixup =\n      unwind_with_fixup && internal_stacktrace::ShouldFixUpStack();\n\n#ifdef _WIN32\n  if (unwind_with_fixup) {\n    // TODO(b/434184677): Fixups are flaky and not supported on Windows\n    unwind_with_fixup = false;\n#ifndef NDEBUG\n    abort();\n#endif\n  }\n#endif\n\n  Unwinder g = custom.load(std::memory_order_acquire);\n  size_t size;\n  // Add 1 to skip count for the unwinder function itself\n  ++skip_count;\n  if (g != nullptr) {\n    size = static_cast<size_t>((*g)(result, sizes, static_cast<int>(max_depth),\n                                    skip_count, uc, min_dropped_frames));\n    // Frame pointers aren't returned by existing hooks, so clear them.\n    if (frames != nullptr) {\n      std::fill(frames, frames + size, uintptr_t());\n    }\n  } else {\n    size = static_cast<size_t>(UnwindImpl<IS_STACK_FRAMES, IS_WITH_CONTEXT>(\n        result, frames, sizes, static_cast<int>(max_depth), skip_count, uc,\n        min_dropped_frames));\n  }\n  if (unwind_with_fixup) {\n    internal_stacktrace::FixUpStack(result, frames, sizes, max_depth, size);\n  }\n\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n  return static_cast<int>(size);\n}\n\n}  // anonymous namespace\n\nABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(\n    void** result, int* sizes, int max_depth, int skip_count) {\n  return Unwind<true, false>(result, nullptr, sizes,\n                             static_cast<size_t>(max_depth), skip_count,\n                             nullptr, nullptr);\n}\n\nABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int\ninternal_stacktrace::GetStackTraceNoFixup(void** result, int max_depth,\n                                          int skip_count) {\n  return Unwind<false, false>(result, nullptr, nullptr,\n                              static_cast<size_t>(max_depth), skip_count,\n                              nullptr, nullptr, /*unwind_with_fixup=*/false);\n}\n\nABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int\nGetStackFramesWithContext(void** result, int* sizes, int max_depth,\n                          int skip_count, const void* uc,\n                          int* min_dropped_frames) {\n  return Unwind<true, true>(result, nullptr, sizes,\n                            static_cast<size_t>(max_depth), skip_count, uc,\n                            min_dropped_frames);\n}\n\nABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(\n    void** result, int max_depth, int skip_count) {\n  return Unwind<false, false>(result, nullptr, nullptr,\n                              static_cast<size_t>(max_depth), skip_count,\n                              nullptr, nullptr);\n}\n\nABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int\nGetStackTraceWithContext(void** result, int max_depth, int skip_count,\n                         const void* uc, int* min_dropped_frames) {\n  return Unwind<false, true>(result, nullptr, nullptr,\n                             static_cast<size_t>(max_depth), skip_count, uc,\n                             min_dropped_frames);\n}\n\nvoid SetStackUnwinder(Unwinder w) {\n  custom.store(w, std::memory_order_release);\n}\n\nint DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip,\n                         const void* uc, int* min_dropped_frames) {\n  skip++;  // For this function\n  decltype(&UnwindImpl<false, false>) f;\n  if (sizes == nullptr) {\n    if (uc == nullptr) {\n      f = &UnwindImpl<false, false>;\n    } else {\n      f = &UnwindImpl<false, true>;\n    }\n  } else {\n    if (uc == nullptr) {\n      f = &UnwindImpl<true, false>;\n    } else {\n      f = &UnwindImpl<true, true>;\n    }\n  }\n  int n = (*f)(pcs, nullptr, sizes, depth, skip, uc, min_dropped_frames);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n  return n;\n}\n\nABSL_ATTRIBUTE_WEAK bool internal_stacktrace::ShouldFixUpStack() {\n  return false;\n}\n\n// Fixes up the stack trace of the current thread, in the first `depth` frames\n// of each buffer. The buffers need to be larger than `depth`, to accommodate\n// any newly inserted elements. `depth` is updated to reflect the new number of\n// elements valid across all the buffers. (It is therefore recommended that all\n// buffer sizes be equal.)\n//\n// The `frames` and `sizes` parameters denote the bounds of the stack frame\n// corresponding to each instruction pointer in the `pcs`.\n// Any elements inside these buffers may be zero or null, in which case that\n// information is assumed to be absent/unavailable.\nABSL_ATTRIBUTE_WEAK void internal_stacktrace::FixUpStack(void**, uintptr_t*,\n                                                         int*, size_t,\n                                                         size_t&) {}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/stacktrace.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: stacktrace.h\n// -----------------------------------------------------------------------------\n//\n// This file contains routines to extract the current stack trace and associated\n// stack frames. These functions are thread-safe and async-signal-safe.\n//\n// Note that stack trace functionality is platform dependent and requires\n// additional support from the compiler/build system in most cases. (That is,\n// this functionality generally only works on platforms/builds that have been\n// specifically configured to support it.)\n//\n// Note: stack traces in Abseil that do not utilize a symbolizer will result in\n// frames consisting of function addresses rather than human-readable function\n// names. (See symbolize.h for information on symbolizing these values.)\n\n#ifndef ABSL_DEBUGGING_STACKTRACE_H_\n#define ABSL_DEBUGGING_STACKTRACE_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace internal_stacktrace {\n\n// As above, but skips fix-ups for efficiency.\nextern int GetStackTraceNoFixup(void** result, int max_depth, int skip_count);\n\n}  // namespace internal_stacktrace\n\n// GetStackFrames()\n//\n// Records program counter values for up to `max_depth` frames, skipping the\n// most recent `skip_count` stack frames, stores their corresponding values\n// and sizes in `results` and `sizes` buffers, and returns the number of frames\n// stored. (Note that the frame generated for the `absl::GetStackFrames()`\n// routine itself is also skipped.)\n//\n// Example:\n//\n//      main() { foo(); }\n//      foo() { bar(); }\n//      bar() {\n//        void* result[10];\n//        int sizes[10];\n//        int depth = absl::GetStackFrames(result, sizes, 10, 1);\n//      }\n//\n// The current stack frame would consist of three function calls: `bar()`,\n// `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets\n// `skip_count` to `1`, it will skip the frame for `bar()`, the most recently\n// invoked function call. It will therefore return 2 and fill `result` with\n// program counters within the following functions:\n//\n//      result[0]       foo()\n//      result[1]       main()\n//\n// (Note: in practice, a few more entries after `main()` may be added to account\n// for startup processes.)\n//\n// Corresponding stack frame sizes will also be recorded:\n//\n//    sizes[0]       16\n//    sizes[1]       16\n//\n// (Stack frame sizes of `16` above are just for illustration purposes.)\n//\n// Stack frame sizes of 0 or less indicate that those frame sizes couldn't\n// be identified.\n//\n// This routine may return fewer stack frame entries than are\n// available. Also note that `result` and `sizes` must both be non-null.\nextern int GetStackFrames(void** result, int* sizes, int max_depth,\n                          int skip_count);\n\n// GetStackFramesWithContext()\n//\n// Records program counter values obtained from a signal handler. Records\n// program counter values for up to `max_depth` frames, skipping the most recent\n// `skip_count` stack frames, stores their corresponding values and sizes in\n// `results` and `sizes` buffers, and returns the number of frames stored. (Note\n// that the frame generated for the `absl::GetStackFramesWithContext()` routine\n// itself is also skipped.)\n//\n// The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value\n// passed to a signal handler registered via the `sa_sigaction` field of a\n// `sigaction` struct. (See\n// http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may\n// help a stack unwinder to provide a better stack trace under certain\n// conditions. `uc` may safely be null.\n//\n// The `min_dropped_frames` output parameter, if non-null, points to the\n// location to note any dropped stack frames, if any, due to buffer limitations\n// or other reasons. (This value will be set to `0` if no frames were dropped.)\n// The number of total stack frames is guaranteed to be >= skip_count +\n// max_depth + *min_dropped_frames.\nextern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,\n                                     int skip_count, const void* uc,\n                                     int* min_dropped_frames);\n\n// GetStackTrace()\n//\n// Records program counter values for up to `max_depth` frames, skipping the\n// most recent `skip_count` stack frames, stores their corresponding values\n// in `results`, and returns the number of frames\n// stored. Note that this function is similar to `absl::GetStackFrames()`\n// except that it returns the stack trace only, and not stack frame sizes.\n//\n// Example:\n//\n//      main() { foo(); }\n//      foo() { bar(); }\n//      bar() {\n//        void* result[10];\n//        int depth = absl::GetStackTrace(result, 10, 1);\n//      }\n//\n// This produces:\n//\n//      result[0]       foo\n//      result[1]       main\n//           ....       ...\n//\n// `result` must not be null.\nextern int GetStackTrace(void** result, int max_depth, int skip_count);\n\n// GetStackTraceWithContext()\n//\n// Records program counter values obtained from a signal handler. Records\n// program counter values for up to `max_depth` frames, skipping the most recent\n// `skip_count` stack frames, stores their corresponding values in `results`,\n// and returns the number of frames stored. (Note that the frame generated for\n// the `absl::GetStackFramesWithContext()` routine itself is also skipped.)\n//\n// The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value\n// passed to a signal handler registered via the `sa_sigaction` field of a\n// `sigaction` struct. (See\n// http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may\n// help a stack unwinder to provide a better stack trace under certain\n// conditions. `uc` may safely be null.\n//\n// The `min_dropped_frames` output parameter, if non-null, points to the\n// location to note any dropped stack frames, if any, due to buffer limitations\n// or other reasons. (This value will be set to `0` if no frames were dropped.)\n// The number of total stack frames is guaranteed to be >= skip_count +\n// max_depth + *min_dropped_frames.\nextern int GetStackTraceWithContext(void** result, int max_depth,\n                                    int skip_count, const void* uc,\n                                    int* min_dropped_frames);\n\n// SetStackUnwinder()\n//\n// Provides a custom function for unwinding stack frames that will be used in\n// place of the default stack unwinder when invoking the static\n// GetStack{Frames,Trace}{,WithContext}() functions above.\n//\n// The arguments passed to the unwinder function will match the\n// arguments passed to `absl::GetStackFramesWithContext()` except that sizes\n// will be non-null iff the caller is interested in frame sizes.\n//\n// If unwinder is set to null, we revert to the default stack-tracing behavior.\n//\n// *****************************************************************************\n// WARNING\n// *****************************************************************************\n//\n// absl::SetStackUnwinder is not suitable for general purpose use.  It is\n// provided for custom runtimes.\n// Some things to watch out for when calling `absl::SetStackUnwinder()`:\n//\n// (a) The unwinder may be called from within signal handlers and\n// therefore must be async-signal-safe.\n//\n// (b) Even after a custom stack unwinder has been unregistered, other\n// threads may still be in the process of using that unwinder.\n// Therefore do not clean up any state that may be needed by an old\n// unwinder.\n// *****************************************************************************\nextern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes,\n                                             int max_depth, int skip_count,\n                                             const void* uc,\n                                             int* min_dropped_frames));\n\n// DefaultStackUnwinder()\n//\n// Records program counter values of up to `max_depth` frames, skipping the most\n// recent `skip_count` stack frames, and stores their corresponding values in\n// `pcs`. (Note that the frame generated for this call itself is also skipped.)\n// This function acts as a generic stack-unwinder; prefer usage of the more\n// specific `GetStack{Trace,Frames}{,WithContext}()` functions above.\n//\n// If you have set your own stack unwinder (with the `SetStackUnwinder()`\n// function above, you can still get the default stack unwinder by calling\n// `DefaultStackUnwinder()`, which will ignore any previously set stack unwinder\n// and use the default one instead.\n//\n// Because this function is generic, only `pcs` is guaranteed to be non-null\n// upon return. It is legal for `sizes`, `uc`, and `min_dropped_frames` to all\n// be null when called.\n//\n// The semantics are the same as the corresponding `GetStack*()` function in the\n// case where `absl::SetStackUnwinder()` was never called. Equivalents are:\n//\n//                       null sizes         |        non-nullptr sizes\n//             |==========================================================|\n//     null uc | GetStackTrace()            | GetStackFrames()            |\n// non-null uc | GetStackTraceWithContext() | GetStackFramesWithContext() |\n//             |==========================================================|\nextern int DefaultStackUnwinder(void** pcs, int* sizes, int max_depth,\n                                int skip_count, const void* uc,\n                                int* min_dropped_frames);\n\nnamespace debugging_internal {\n// Returns true for platforms which are expected to have functioning stack trace\n// implementations. Intended to be used for tests which want to exclude\n// verification of logic known to be broken because stack traces are not\n// working.\nextern bool StackTraceWorksForTest();\n}  // namespace debugging_internal\n\nnamespace internal_stacktrace {\nextern bool ShouldFixUpStack();\n\n// Fixes up the stack trace of the current thread, in the first `depth` frames\n// of each buffer. The buffers need to be larger than `depth`, to accommodate\n// any newly inserted elements. `depth` is updated to reflect the new number of\n// elements valid across all the buffers. (It is therefore recommended that all\n// buffer sizes be equal.)\n//\n// The `frames` and `sizes` parameters denote the bounds of the stack frame\n// corresponding to each instruction pointer in the `pcs`.\n// Any elements inside these buffers may be zero or null, in which case that\n// information is assumed to be absent/unavailable.\nextern void FixUpStack(void** pcs, uintptr_t* frames, int* sizes,\n                       size_t capacity, size_t& depth);\n}  // namespace internal_stacktrace\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_STACKTRACE_H_\n"
  },
  {
    "path": "absl/debugging/stacktrace_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/cleanup/cleanup.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"benchmark/benchmark.h\"\n\nstatic bool g_enable_fixup = false;\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\n// Override these weak symbols if possible.\nbool absl::internal_stacktrace::ShouldFixUpStack() { return g_enable_fixup; }\nvoid absl::internal_stacktrace::FixUpStack(void**, uintptr_t*, int*, size_t,\n                                           size_t&) {}\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nstatic constexpr int kMaxStackDepth = 100;\nstatic constexpr int kCacheSize = (1 << 16);\nvoid* pcs[kMaxStackDepth];\n\nABSL_ATTRIBUTE_NOINLINE void func(benchmark::State& state, int x, int depth) {\n  if (x <= 0) {\n    // Touch a significant amount of memory so that the stack is likely to be\n    // not cached in the L1 cache.\n    state.PauseTiming();\n    int* arr = new int[kCacheSize];\n    for (int i = 0; i < kCacheSize; ++i) benchmark::DoNotOptimize(arr[i] = 100);\n    delete[] arr;\n    state.ResumeTiming();\n    benchmark::DoNotOptimize(absl::GetStackTrace(pcs, depth, 0));\n    return;\n  }\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n  func(state, --x, depth);\n}\n\ntemplate <bool EnableFixup>\nvoid BM_GetStackTrace(benchmark::State& state) {\n  const Cleanup restore_state(\n      [prev = g_enable_fixup]() { g_enable_fixup = prev; });\n  g_enable_fixup = EnableFixup;\n  int depth = state.range(0);\n  for (auto s : state) {\n    func(state, depth, depth);\n  }\n}\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\nauto& BM_GetStackTraceWithFixup = BM_GetStackTrace<true>;\nBENCHMARK(BM_GetStackTraceWithFixup)->DenseRange(10, kMaxStackDepth, 10);\n#endif\n\nauto& BM_GetStackTraceWithoutFixup = BM_GetStackTrace<false>;\nBENCHMARK(BM_GetStackTraceWithoutFixup)->DenseRange(10, kMaxStackDepth, 10);\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/stacktrace_test.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/stacktrace.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <cerrno>\n#include <csignal>\n#include <cstring>\n#include <memory>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/errno_saver.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/types/span.h\"\n\nstatic int g_should_fixup_calls = 0;\nstatic int g_fixup_calls = 0;\nstatic bool g_enable_fixup = false;\nstatic uintptr_t g_last_fixup_frame_address = 0;\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\nbool absl::internal_stacktrace::ShouldFixUpStack() {\n  ++g_should_fixup_calls;\n  return g_enable_fixup;\n}\n\nvoid absl::internal_stacktrace::FixUpStack(void**, uintptr_t*, int*, size_t,\n                                           size_t&) {\n  const void* frame_address = nullptr;\n#if ABSL_HAVE_BUILTIN(__builtin_frame_address)\n  frame_address = __builtin_frame_address(0);\n#endif\n  g_last_fixup_frame_address = reinterpret_cast<uintptr_t>(frame_address);\n  ++g_fixup_calls;\n}\n#endif\n\nnamespace {\n\nusing ::testing::ContainerEq;\nusing ::testing::Contains;\nusing ::testing::internal::Cleanup;\n\nstruct StackTrace {\n  static constexpr int kStackCount = 64;\n  int depth;\n  void* result[kStackCount];\n  int sizes[kStackCount];\n};\n\n// This test is currently only known to pass on Linux x86_64/aarch64.\n#if defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))\nABSL_ATTRIBUTE_NOINLINE void Unwind(void* p) {\n  ABSL_ATTRIBUTE_UNUSED static void* volatile sink = p;\n  constexpr int kSize = 16;\n  void* stack[kSize];\n  int frames[kSize];\n  absl::GetStackTrace(stack, kSize, 0);\n  absl::GetStackFrames(stack, frames, kSize, 0);\n}\n\nABSL_ATTRIBUTE_NOINLINE void HugeFrame() {\n  char buffer[1 << 20];\n  Unwind(buffer);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\nTEST(StackTrace, HugeFrame) {\n  // Ensure that the unwinder is not confused by very large stack frames.\n  HugeFrame();\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n#endif\n\n// This is a separate function to avoid inlining.\nABSL_ATTRIBUTE_NOINLINE static void FixupNoFixupEquivalenceNoInline() {\n#if !ABSL_HAVE_ATTRIBUTE_WEAK\n  const char* kSkipReason = \"Need weak symbol support\";\n#elif defined(__riscv)\n  const char* kSkipReason =\n      \"Skipping test on RISC-V due to pre-existing failure\";\n#elif defined(_WIN32)\n  // TODO(b/434184677): Add support for fixups on Windows if needed\n  const char* kSkipReason =\n      \"Skipping test on Windows due to lack of support for fixups\";\n#else\n  const char* kSkipReason = nullptr;\n#endif\n\n  // This conditional is to avoid an unreachable code warning.\n  if (kSkipReason != nullptr) {\n    GTEST_SKIP() << kSkipReason;\n  }\n\n  bool can_rely_on_frame_pointers = false;\n  if (!can_rely_on_frame_pointers) {\n    GTEST_SKIP() << \"Frame pointers are required, but not guaranteed in OSS\";\n  }\n\n  // This test is known not to pass on MSVC (due to weak symbols)\n\n  const Cleanup restore_state([enable_fixup = g_enable_fixup,\n                               fixup_calls = g_fixup_calls,\n                               should_fixup_calls = g_should_fixup_calls]() {\n    g_enable_fixup = enable_fixup;\n    g_fixup_calls = fixup_calls;\n    g_should_fixup_calls = should_fixup_calls;\n  });\n\n  constexpr int kSkip = 1;  // Skip our own frame, whose return PCs won't match\n  constexpr auto kStackCount = 1;\n\n  StackTrace a;\n  StackTrace b;\n\n  // ==========================================================================\n\n  g_fixup_calls = 0;\n  g_should_fixup_calls = 0;\n  a.depth = absl::GetStackTrace(a.result, kStackCount, kSkip);\n  g_enable_fixup = !g_enable_fixup;\n  b.depth = absl::GetStackTrace(b.result, kStackCount, kSkip);\n  EXPECT_THAT(\n      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),\n      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);\n\n  // ==========================================================================\n\n  g_fixup_calls = 0;\n  g_should_fixup_calls = 0;\n  a.depth = absl::GetStackFrames(a.result, a.sizes, kStackCount, kSkip);\n  g_enable_fixup = !g_enable_fixup;\n  b.depth = absl::GetStackFrames(b.result, b.sizes, kStackCount, kSkip);\n  EXPECT_THAT(\n      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),\n      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));\n  EXPECT_THAT(\n      absl::MakeSpan(a.sizes, static_cast<size_t>(a.depth)),\n      ContainerEq(absl::MakeSpan(b.sizes, static_cast<size_t>(b.depth))));\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);\n\n  // ==========================================================================\n\n  g_fixup_calls = 0;\n  g_should_fixup_calls = 0;\n  a.depth = absl::GetStackTraceWithContext(a.result, kStackCount, kSkip,\n                                           nullptr, nullptr);\n  g_enable_fixup = !g_enable_fixup;\n  b.depth = absl::GetStackTraceWithContext(b.result, kStackCount, kSkip,\n                                           nullptr, nullptr);\n  EXPECT_THAT(\n      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),\n      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);\n\n  // ==========================================================================\n\n  g_fixup_calls = 0;\n  g_should_fixup_calls = 0;\n  a.depth = absl::GetStackFramesWithContext(a.result, a.sizes, kStackCount,\n                                            kSkip, nullptr, nullptr);\n  g_enable_fixup = !g_enable_fixup;\n  b.depth = absl::GetStackFramesWithContext(b.result, b.sizes, kStackCount,\n                                            kSkip, nullptr, nullptr);\n  EXPECT_THAT(\n      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),\n      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));\n  EXPECT_THAT(\n      absl::MakeSpan(a.sizes, static_cast<size_t>(a.depth)),\n      ContainerEq(absl::MakeSpan(b.sizes, static_cast<size_t>(b.depth))));\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);\n}\n\nTEST(StackTrace, FixupNoFixupEquivalence) { FixupNoFixupEquivalenceNoInline(); }\n\nTEST(StackTrace, FixupLowStackUsage) {\n#if !ABSL_HAVE_ATTRIBUTE_WEAK\n  const char* kSkipReason = \"Skipping test on MSVC due to weak symbols\";\n#elif defined(_WIN32)\n  // TODO(b/434184677): Add support for fixups on Windows if needed\n  const char* kSkipReason =\n      \"Skipping test on Windows due to lack of support for fixups\";\n#else\n  const char* kSkipReason = nullptr;\n#endif\n\n  // This conditional is to avoid an unreachable code warning.\n  if (kSkipReason != nullptr) {\n    GTEST_SKIP() << kSkipReason;\n  }\n\n  const Cleanup restore_state([enable_fixup = g_enable_fixup,\n                               fixup_calls = g_fixup_calls,\n                               should_fixup_calls = g_should_fixup_calls]() {\n    g_enable_fixup = enable_fixup;\n    g_fixup_calls = fixup_calls;\n    g_should_fixup_calls = should_fixup_calls;\n  });\n\n  g_enable_fixup = true;\n\n  // Request a ton of stack frames, regardless of how many are actually used.\n  // It's fine to request more frames than we have, since functions preallocate\n  // memory before discovering how high the stack really is, and we're really\n  // just trying to make sure the preallocations don't overflow the stack.\n  //\n  // Note that we loop in order to cover all sides of any branches in the\n  // implementation that switch allocation behavior (e.g., from stack to heap)\n  // and to ensure that no sides allocate too much stack space.\n  constexpr size_t kPageSize = 4096;\n  for (size_t depth = 2; depth < (1 << 20); depth += depth / 2) {\n    const auto stack = std::make_unique<void*[]>(depth);\n    const auto frames = std::make_unique<int[]>(depth);\n\n    absl::GetStackFrames(stack.get(), frames.get(), static_cast<int>(depth), 0);\n    const void* frame_address = nullptr;\n#if ABSL_HAVE_BUILTIN(__builtin_frame_address)\n    frame_address = __builtin_frame_address(0);\n#endif\n    size_t stack_usage =\n        reinterpret_cast<uintptr_t>(frame_address) - g_last_fixup_frame_address;\n    EXPECT_LT(stack_usage, kPageSize);\n  }\n}\n\nTEST(StackTrace, CustomUnwinderPerformsFixup) {\n#if !ABSL_HAVE_ATTRIBUTE_WEAK\n  const char* kSkipReason = \"Need weak symbol support\";\n#elif defined(_WIN32)\n  // TODO(b/434184677): Add support for fixups on Windows if needed\n  const char* kSkipReason =\n      \"Skipping test on Windows due to lack of support for fixups\";\n#else\n  const char* kSkipReason = nullptr;\n#endif\n\n  // This conditional is to avoid an unreachable code warning.\n  if (kSkipReason != nullptr) {\n    GTEST_SKIP() << kSkipReason;\n  }\n\n  constexpr int kSkip = 1;  // Skip our own frame, whose return PCs won't match\n  constexpr auto kStackCount = 1;\n\n  absl::SetStackUnwinder(absl::DefaultStackUnwinder);\n  const Cleanup restore_state([enable_fixup = g_enable_fixup,\n                               fixup_calls = g_fixup_calls,\n                               should_fixup_calls = g_should_fixup_calls]() {\n    absl::SetStackUnwinder(nullptr);\n    g_enable_fixup = enable_fixup;\n    g_fixup_calls = fixup_calls;\n    g_should_fixup_calls = should_fixup_calls;\n  });\n\n  StackTrace trace;\n\n  g_enable_fixup = true;\n  g_should_fixup_calls = 0;\n  g_fixup_calls = 0;\n  absl::GetStackTrace(trace.result, kSkip, kStackCount);\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GT(g_fixup_calls, 0);\n\n  g_enable_fixup = true;\n  g_should_fixup_calls = 0;\n  g_fixup_calls = 0;\n  absl::GetStackFrames(trace.result, trace.sizes, kSkip, kStackCount);\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GT(g_fixup_calls, 0);\n\n  g_enable_fixup = true;\n  g_should_fixup_calls = 0;\n  g_fixup_calls = 0;\n  absl::GetStackTraceWithContext(trace.result, kSkip, kStackCount, nullptr,\n                                 nullptr);\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GT(g_fixup_calls, 0);\n\n  g_enable_fixup = true;\n  g_should_fixup_calls = 0;\n  g_fixup_calls = 0;\n  absl::GetStackFramesWithContext(trace.result, trace.sizes, kSkip, kStackCount,\n                                  nullptr, nullptr);\n  EXPECT_GT(g_should_fixup_calls, 0);\n  EXPECT_GT(g_fixup_calls, 0);\n}\n\n// This test is Linux specific.\n#if defined(__linux__)\nconst void* g_return_address = nullptr;\nbool g_sigusr2_raised = false;\n\nvoid SigUsr2Handler(int, siginfo_t*, void* uc) {\n  absl::base_internal::ErrnoSaver errno_saver;\n  // Many platforms don't support this by default.\n  bool support_is_expected = false;\n  constexpr int kMaxStackDepth = 64;\n  void* result[kMaxStackDepth];\n  int depth =\n      absl::GetStackTraceWithContext(result, kMaxStackDepth, 0, uc, nullptr);\n  // Verify we can unwind past the nested signal handlers.\n  if (support_is_expected) {\n    EXPECT_THAT(absl::MakeSpan(result, static_cast<size_t>(depth)),\n                Contains(g_return_address).Times(1));\n  }\n  depth = absl::GetStackTrace(result, kMaxStackDepth, 0);\n  if (support_is_expected) {\n    EXPECT_THAT(absl::MakeSpan(result, static_cast<size_t>(depth)),\n                Contains(g_return_address).Times(1));\n  }\n  g_sigusr2_raised = true;\n}\n\nvoid SigUsr1Handler(int, siginfo_t*, void*) {\n  raise(SIGUSR2);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\nABSL_ATTRIBUTE_NOINLINE void RaiseSignal() {\n  g_return_address = __builtin_return_address(0);\n  raise(SIGUSR1);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\nABSL_ATTRIBUTE_NOINLINE void TestNestedSignal() {\n  constexpr size_t kAltstackSize = 1 << 14;\n  // Allocate altstack on regular stack to make sure it'll have a higher\n  // address than some of the regular stack frames.\n  char space[kAltstackSize];\n  stack_t altstack;\n  stack_t old_stack;\n  altstack.ss_sp = space;\n  altstack.ss_size = kAltstackSize;\n  altstack.ss_flags = 0;\n  ASSERT_EQ(sigaltstack(&altstack, &old_stack), 0) << strerror(errno);\n  struct sigaction act;\n  struct sigaction oldusr1act;\n  struct sigaction oldusr2act;\n  act.sa_sigaction = SigUsr1Handler;\n  act.sa_flags = SA_SIGINFO | SA_ONSTACK;\n  sigemptyset(&act.sa_mask);\n  ASSERT_EQ(sigaction(SIGUSR1, &act, &oldusr1act), 0) << strerror(errno);\n  act.sa_sigaction = SigUsr2Handler;\n  ASSERT_EQ(sigaction(SIGUSR2, &act, &oldusr2act), 0) << strerror(errno);\n  RaiseSignal();\n  ASSERT_EQ(sigaltstack(&old_stack, nullptr), 0) << strerror(errno);\n  ASSERT_EQ(sigaction(SIGUSR1, &oldusr1act, nullptr), 0) << strerror(errno);\n  ASSERT_EQ(sigaction(SIGUSR2, &oldusr2act, nullptr), 0) << strerror(errno);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\nTEST(StackTrace, NestedSignal) {\n  // Verify we can unwind past the nested signal handlers.\n  TestNestedSignal();\n  EXPECT_TRUE(g_sigusr2_raised);\n}\n#endif\n\n}  // namespace\n"
  },
  {
    "path": "absl/debugging/symbolize.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/symbolize.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/low_level_alloc.h\"\n#include \"absl/debugging/internal/symbolize.h\"\n\n#ifdef _WIN32\n#include <winapifamily.h>\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\n// UWP doesn't have access to win32 APIs.\n#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32\n#endif\n#endif\n\n// Emscripten symbolization relies on JS. Do not use them in standalone mode.\n#if defined(__EMSCRIPTEN__) && !defined(STANDALONE_WASM)\n#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WASM\n#endif\n\n#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)\n#include \"absl/debugging/symbolize_elf.inc\"\n#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)\n// The Windows Symbolizer only works if PDB files containing the debug info\n// are available to the program at runtime.\n#include \"absl/debugging/symbolize_win32.inc\"\n#elif defined(__APPLE__)\n#include \"absl/debugging/symbolize_darwin.inc\"\n#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WASM)\n#include \"absl/debugging/symbolize_emscripten.inc\"\n#else\n#include \"absl/debugging/symbolize_unimplemented.inc\"\n#endif\n\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace debugging_internal {\n\nvoid SymbolDecoratorDeleter::operator()(SymbolDecorator* ptr) {\n  ptr->~SymbolDecorator();\n  base_internal::LowLevelAlloc::Free(ptr);\n}\n\n}  // namespace debugging_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/symbolize.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: symbolize.h\n// -----------------------------------------------------------------------------\n//\n// This file configures the Abseil symbolizer for use in converting instruction\n// pointer addresses (program counters) into human-readable names (function\n// calls, etc.) within Abseil code.\n//\n// The symbolizer may be invoked from several sources:\n//\n//   * Implicitly, through the installation of an Abseil failure signal handler.\n//     (See failure_signal_handler.h for more information.)\n//   * By calling `Symbolize()` directly on a program counter you obtain through\n//     `absl::GetStackTrace()` or `absl::GetStackFrames()`. (See stacktrace.h\n//     for more information.\n//   * By calling `Symbolize()` directly on a program counter you obtain through\n//     other means (which would be platform-dependent).\n//\n// In all of the above cases, the symbolizer must first be initialized before\n// any program counter values can be symbolized. If you are installing a failure\n// signal handler, initialize the symbolizer before you do so.\n//\n// Example:\n//\n//   int main(int argc, char** argv) {\n//     // Initialize the Symbolizer before installing the failure signal handler\n//     absl::InitializeSymbolizer(argv[0]);\n//\n//     // Now you may install the failure signal handler\n//     absl::FailureSignalHandlerOptions options;\n//     absl::InstallFailureSignalHandler(options);\n//\n//     // Start running your main program\n//     ...\n//     return 0;\n//  }\n//\n#ifndef ABSL_DEBUGGING_SYMBOLIZE_H_\n#define ABSL_DEBUGGING_SYMBOLIZE_H_\n\n#include \"absl/debugging/internal/symbolize.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// InitializeSymbolizer()\n//\n// Initializes the program counter symbolizer, given the path of the program\n// (typically obtained through `main()`s `argv[0]`). The Abseil symbolizer\n// allows you to read program counters (instruction pointer values) using their\n// human-readable names within output such as stack traces.\n//\n// Example:\n//\n// int main(int argc, char *argv[]) {\n//   absl::InitializeSymbolizer(argv[0]);\n//   // Now you can use the symbolizer\n// }\nvoid InitializeSymbolizer(const char* argv0);\n//\n// Symbolize()\n//\n// Symbolizes a program counter (instruction pointer value) `pc` and, on\n// success, writes the name to `out`. The symbol name is demangled, if possible.\n// Note that the symbolized name may be truncated and will be NUL-terminated.\n// Demangling is supported for symbols generated by GCC 3.x or newer). Returns\n// `false` on failure.\n//\n// Example:\n//\n//   // Print a program counter and its symbol name.\n//   static void DumpPCAndSymbol(void *pc) {\n//     char tmp[1024];\n//     const char *symbol = \"(unknown)\";\n//     if (absl::Symbolize(pc, tmp, sizeof(tmp))) {\n//       symbol = tmp;\n//     }\n//     absl::PrintF(\"%p  %s\\n\", pc, symbol);\n//  }\nbool Symbolize(const void *pc, char *out, int out_size);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_DEBUGGING_SYMBOLIZE_H_\n"
  },
  {
    "path": "absl/debugging/symbolize_darwin.inc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cxxabi.h>\n#include <execinfo.h>\n\n#include <algorithm>\n#include <cstring>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/debugging/internal/demangle.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nvoid InitializeSymbolizer(const char*) {}\n\nnamespace debugging_internal {\nnamespace {\n\nstatic std::string GetSymbolString(absl::string_view backtrace_line) {\n  // Example Backtrace lines:\n  // 0   libimaging_shared.dylib             0x018c152a\n  // _ZNSt11_Deque_baseIN3nik7mediadb4PageESaIS2_EE17_M_initialize_mapEm + 3478\n  //\n  // or\n  // 0   libimaging_shared.dylib             0x0000000001895c39\n  // _ZN3nik4util19register_shared_ptrINS_3gpu7TextureEEEvPKvS5_ + 39\n  //\n  // or\n  // 0   mysterious_app                      0x0124000120120009 main + 17\n  auto address_pos = backtrace_line.find(\" 0x\");\n  if (address_pos == absl::string_view::npos) return std::string();\n  absl::string_view symbol_view = backtrace_line.substr(address_pos + 1);\n\n  auto space_pos = symbol_view.find(\" \");\n  if (space_pos == absl::string_view::npos) return std::string();\n  symbol_view = symbol_view.substr(space_pos + 1);  // to mangled symbol\n\n  auto plus_pos = symbol_view.find(\" + \");\n  if (plus_pos == absl::string_view::npos) return std::string();\n  symbol_view = symbol_view.substr(0, plus_pos);  // strip remainng\n\n  return std::string(symbol_view);\n}\n\n}  // namespace\n}  // namespace debugging_internal\n\nbool Symbolize(const void* pc, char* out, int out_size) {\n  if (out_size <= 0 || pc == nullptr) {\n    out = nullptr;\n    return false;\n  }\n\n  // This allocates a char* array.\n  char** frame_strings = backtrace_symbols(const_cast<void**>(&pc), 1);\n\n  if (frame_strings == nullptr) return false;\n\n  std::string symbol = debugging_internal::GetSymbolString(frame_strings[0]);\n  free(frame_strings);\n\n  char tmp_buf[1024];\n  if (debugging_internal::Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {\n    size_t len = strlen(tmp_buf);\n    if (len + 1 <= static_cast<size_t>(out_size)) {  // +1 for '\\0'\n      assert(len < sizeof(tmp_buf));\n      memmove(out, tmp_buf, len + 1);\n    }\n  } else {\n    strncpy(out, symbol.c_str(), static_cast<size_t>(out_size));\n  }\n\n  if (out[out_size - 1] != '\\0') {\n    // strncpy() does not '\\0' terminate when it truncates.\n    static constexpr char kEllipsis[] = \"...\";\n    size_t ellipsis_size =\n        std::min(sizeof(kEllipsis) - 1, static_cast<size_t>(out_size) - 1);\n    memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);\n    out[out_size - 1] = '\\0';\n  }\n\n  return true;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/symbolize_elf.inc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This library provides Symbolize() function that symbolizes program\n// counters to their corresponding symbol names on linux platforms.\n// This library has a minimal implementation of an ELF symbol table\n// reader (i.e. it doesn't depend on libelf, etc.).\n//\n// The algorithm used in Symbolize() is as follows.\n//\n//   1. Go through a list of maps in /proc/self/maps and find the map\n//   containing the program counter.\n//\n//   2. Open the mapped file and find a regular symbol table inside.\n//   Iterate over symbols in the symbol table and look for the symbol\n//   containing the program counter.  If such a symbol is found,\n//   obtain the symbol name, and demangle the symbol if possible.\n//   If the symbol isn't found in the regular symbol table (binary is\n//   stripped), try the same thing with a dynamic symbol table.\n//\n// Note that Symbolize() is originally implemented to be used in\n// signal handlers, hence it doesn't use malloc() and other unsafe\n// operations.  It should be both thread-safe and async-signal-safe.\n//\n// Implementation note:\n//\n// We don't use heaps but only use stacks.  We want to reduce the\n// stack consumption so that the symbolizer can run on small stacks.\n//\n// Here are some numbers collected with GCC 4.1.0 on x86:\n// - sizeof(Elf32_Sym)  = 16\n// - sizeof(Elf32_Shdr) = 40\n// - sizeof(Elf64_Sym)  = 24\n// - sizeof(Elf64_Shdr) = 64\n//\n// This implementation is intended to be async-signal-safe but uses some\n// functions which are not guaranteed to be so, such as memchr() and\n// memmove().  We assume they are async-signal-safe.\n\n#include <dlfcn.h>\n#include <elf.h>\n#include <fcntl.h>\n#include <link.h>  // For ElfW() macro.\n#include <sys/resource.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include <algorithm>\n#include <array>\n#include <atomic>\n#include <cerrno>\n#include <cinttypes>\n#include <climits>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <memory>\n\n#include \"absl/base/casts.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/low_level_alloc.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/port.h\"\n#include \"absl/debugging/internal/demangle.h\"\n#include \"absl/debugging/internal/vdso_support.h\"\n#include \"absl/strings/string_view.h\"\n\n#if defined(__FreeBSD__) && !defined(ElfW)\n#define ElfW(x) __ElfN(x)\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Value of argv[0]. Used by MaybeInitializeObjFile().\nstatic char *argv0_value = nullptr;\n\nvoid InitializeSymbolizer(const char *argv0) {\n#ifdef ABSL_HAVE_VDSO_SUPPORT\n  // We need to make sure VDSOSupport::Init() is called before any setuid or\n  // chroot calls, so InitializeSymbolizer() should be called very early in the\n  // life of a program.\n  absl::debugging_internal::VDSOSupport::Init();\n#endif\n  if (argv0_value != nullptr) {\n    free(argv0_value);\n    argv0_value = nullptr;\n  }\n  if (argv0 != nullptr && argv0[0] != '\\0') {\n    argv0_value = strdup(argv0);\n  }\n}\n\nnamespace debugging_internal {\nnamespace {\n\n// Re-runs fn until it doesn't cause EINTR.\n#define NO_INTR(fn) \\\n  do {              \\\n  } while ((fn) < 0 && errno == EINTR)\n\n// On Linux, ELF_ST_* are defined in <linux/elf.h>.  To make this portable\n// we define our own ELF_ST_BIND and ELF_ST_TYPE if not available.\n#ifndef ELF_ST_BIND\n#define ELF_ST_BIND(info) (((unsigned char)(info)) >> 4)\n#endif\n\n#ifndef ELF_ST_TYPE\n#define ELF_ST_TYPE(info) (((unsigned char)(info)) & 0xF)\n#endif\n\n// Some platforms use a special .opd section to store function pointers.\nconst char kOpdSectionName[] = \".opd\";\n\n#if defined(__powerpc64__) && defined(_CALL_ELF)\n#if _CALL_ELF <= 1\n#define ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI 1\n#endif\n#endif\n#if defined(ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI) || defined(__ia64)\n// Use opd section for function descriptors on these platforms, the function\n// address is the first word of the descriptor.\n//\n// https://maskray.me/blog/2023-02-26-linker-notes-on-power-isa notes that\n// opd sections are used on 64-bit PowerPC with the ELFv1 ABI.\ninline constexpr bool kPlatformUsesOPDSections = true;\n#else\ninline constexpr bool kPlatformUsesOPDSections = false;\n#endif\n\n// This works for PowerPC & IA64 only.  A function descriptor consist of two\n// pointers and the first one is the function's entry.\nconst size_t kFunctionDescriptorSize = sizeof(void *) * 2;\n\nstd::atomic<SymbolDecorator::Factory*> g_decorator_factory = nullptr;\n\nstruct FileMappingHint {\n  const void *start;\n  const void *end;\n  uint64_t offset;\n  const char *filename;\n};\n\nconst int kMaxFileMappingHints = 8;\nint g_num_file_mapping_hints;\nFileMappingHint g_file_mapping_hints[kMaxFileMappingHints];\n// Protects g_file_mapping_hints.\nABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu(\n    absl::base_internal::SCHEDULE_KERNEL_ONLY);\n\n// Async-signal-safe function to zero a buffer.\n// memset() is not guaranteed to be async-signal-safe.\nstatic void SafeMemZero(void *p, size_t size) {\n  unsigned char *c = static_cast<unsigned char *>(p);\n  while (size--) {\n    *c++ = 0;\n  }\n}\n\nstruct ObjFile {\n  char *filename = nullptr;\n  const void *start_addr = nullptr;\n  const void *end_addr = nullptr;\n  uint64_t offset = 0;\n\n  // The following fields are initialized on the first access to the\n  // object file.\n  int fd = -1;\n  int elf_type = -1;\n  ElfW(Ehdr) elf_header = {};\n\n  // PT_LOAD program header describing executable code.\n  // Normally we expect just one, but SWIFT binaries have two.\n  // CUDA binaries have 3 (see cr/473913254 description).\n  std::array<ElfW(Phdr), 4> phdr = {};\n\n  SymbolDecoratorPtr decorator = {};\n};\n\n// Build 4-way associative cache for symbols. Within each cache line, symbols\n// are replaced in LRU order.\nenum {\n  ASSOCIATIVITY = 4,\n};\nstruct SymbolCacheLine {\n  const void *pc[ASSOCIATIVITY];\n  char *name[ASSOCIATIVITY];\n\n  // age[i] is incremented when a line is accessed. it's reset to zero if the\n  // i'th entry is read.\n  uint32_t age[ASSOCIATIVITY];\n};\n\n// ---------------------------------------------------------------\n// An AddrMap is a vector of ObjFile, using SigSafeArena() for allocation.\n\nclass AddrMap {\n public:\n  AddrMap() : size_(0), allocated_(0), obj_(nullptr) {}\n  ~AddrMap() { base_internal::LowLevelAlloc::Free(obj_); }\n  size_t Size() const { return size_; }\n  ObjFile *At(size_t i) { return &obj_[i]; }\n  ObjFile *Add();\n  void Clear();\n\n private:\n  size_t size_;       // count of valid elements (<= allocated_)\n  size_t allocated_;  // count of allocated elements\n  ObjFile *obj_;      // array of allocated_ elements\n  AddrMap(const AddrMap &) = delete;\n  AddrMap &operator=(const AddrMap &) = delete;\n};\n\nvoid AddrMap::Clear() {\n  for (size_t i = 0; i != size_; i++) {\n    At(i)->~ObjFile();\n  }\n  size_ = 0;\n}\n\nObjFile *AddrMap::Add() {\n  if (size_ == allocated_) {\n    size_t new_allocated = allocated_ * 2 + 50;\n    ObjFile *new_obj_ =\n        static_cast<ObjFile *>(base_internal::LowLevelAlloc::AllocWithArena(\n            new_allocated * sizeof(*new_obj_), base_internal::SigSafeArena()));\n    if (obj_) {\n      std::uninitialized_move_n(obj_, size_, new_obj_);\n      std::destroy_n(obj_, size_);\n      base_internal::LowLevelAlloc::Free(obj_);\n    }\n    obj_ = new_obj_;\n    allocated_ = new_allocated;\n  }\n  return new (&obj_[size_++]) ObjFile;\n}\n\nclass CachingFile {\n public:\n  // Setup reader for fd that uses buf[0, buf_size-1] as a cache.\n  CachingFile(int fd, char *buf, size_t buf_size)\n      : fd_(fd),\n        cache_(buf),\n        cache_size_(buf_size),\n        cache_start_(0),\n        cache_limit_(0) {}\n\n  int fd() const { return fd_; }\n  ssize_t ReadFromOffset(void *buf, size_t count, off_t offset);\n  bool ReadFromOffsetExact(void *buf, size_t count, off_t offset);\n\n private:\n  // Bytes [cache_start_, cache_limit_-1] from fd_ are stored in\n  // a prefix of cache_[0, cache_size_-1].\n  int fd_;\n  char *cache_;\n  size_t cache_size_;\n  off_t cache_start_;\n  off_t cache_limit_;\n};\n\n// ---------------------------------------------------------------\n\nenum FindSymbolResult { SYMBOL_NOT_FOUND = 1, SYMBOL_TRUNCATED, SYMBOL_FOUND };\n\nclass Symbolizer {\n public:\n  Symbolizer();\n  ~Symbolizer();\n  const char *GetSymbol(const void *const pc);\n\n  void UpdateDecoratorsIfNeeded(SymbolDecorator::Factory* decorator_factory);\n\n private:\n  char *CopyString(const char *s) {\n    size_t len = strlen(s);\n    char *dst =\n        static_cast<char *>(base_internal::LowLevelAlloc::AllocWithArena(\n            len + 1, base_internal::SigSafeArena()));\n    ABSL_RAW_CHECK(dst != nullptr, \"out of memory\");\n    memcpy(dst, s, len + 1);\n    return dst;\n  }\n  ObjFile *FindObjFile(const void *const start,\n                       size_t size) ABSL_ATTRIBUTE_NOINLINE;\n  static bool RegisterObjFile(const char *filename,\n                              const void *const start_addr,\n                              const void *const end_addr, uint64_t offset,\n                              void *arg);\n  SymbolCacheLine *GetCacheLine(const void *const pc);\n  const char *FindSymbolInCache(const void *const pc);\n  const char *InsertSymbolInCache(const void *const pc, const char *name);\n  void AgeSymbols(SymbolCacheLine *line);\n  void ClearAddrMap();\n  FindSymbolResult GetSymbolFromObjectFile(const ObjFile &obj,\n                                           const void *const pc,\n                                           const ptrdiff_t relocation,\n                                           char *out, size_t out_size,\n                                           char *tmp_buf, size_t tmp_buf_size);\n  const char *GetUncachedSymbol(const void *pc);\n\n  enum {\n    SYMBOL_BUF_SIZE = 3072,\n    TMP_BUF_SIZE = 1024,\n    SYMBOL_CACHE_LINES = 128,\n    FILE_CACHE_SIZE = 8192,\n  };\n\n  AddrMap addr_map_;\n  SymbolDecorator::Factory* decorator_factory_ = nullptr;\n\n  bool ok_;\n  bool addr_map_read_;\n\n  char symbol_buf_[SYMBOL_BUF_SIZE];\n  char file_cache_[FILE_CACHE_SIZE];\n\n  // tmp_buf_ will be used to store arrays of ElfW(Shdr) and ElfW(Sym)\n  // so we ensure that tmp_buf_ is properly aligned to store either.\n  alignas(16) char tmp_buf_[TMP_BUF_SIZE];\n  static_assert(alignof(ElfW(Shdr)) <= 16,\n                \"alignment of tmp buf too small for Shdr\");\n  static_assert(alignof(ElfW(Sym)) <= 16,\n                \"alignment of tmp buf too small for Sym\");\n\n  SymbolCacheLine symbol_cache_[SYMBOL_CACHE_LINES];\n};\n\n// Protect against client code closing low-valued file descriptors it doesn't\n// actually own.\nint OpenReadOnlyWithHighFD(const char *fname) {\n  static int high_fd = [] {\n    struct rlimit rlim{};\n    const int rc = getrlimit(RLIMIT_NOFILE, &rlim);\n    if (rc == 0 && rlim.rlim_cur >= 2000) {\n      const int max_fd = static_cast<int>(rlim.rlim_cur);\n\n      // This will return 2000 on reasonably-configured systems.\n      return std::min<int>(2000, max_fd - 1000);\n    }\n    ABSL_RAW_LOG(WARNING, \"Unable to get high fd: rc=%d, limit=%ld\",  //\n                 rc, static_cast<long>(rlim.rlim_cur));\n    return -1;\n  }();\n  constexpr int kOpenFlags = O_RDONLY | O_CLOEXEC;\n  if (high_fd >= 1000) {\n    const int fd = open(fname, kOpenFlags);\n    if (fd != -1 && fd < high_fd) {\n      // Try to relocate fd to high range.\n      static_assert(kOpenFlags & O_CLOEXEC,\n                    \"F_DUPFD_CLOEXEC assumes O_CLOEXEC\");\n      const int fd2 = fcntl(fd, F_DUPFD_CLOEXEC, high_fd);\n      if (fd2 != -1) {\n        // Successfully obtained high fd. Use it.\n        close(fd);\n        return fd2;\n      } else {\n        ABSL_RAW_LOG(WARNING, \"Unable to dup fd=%d above %d, errno=%d\", fd,\n                     high_fd, errno);\n      }\n    }\n    // Either open failed and fd==-1, or fd is already above high_fd, or fcntl\n    // failed and fd is valid (but low).\n    return fd;\n  }\n  return open(fname, kOpenFlags);\n}\n\nstatic std::atomic<Symbolizer *> g_cached_symbolizer;\n\n}  // namespace\n\nstatic size_t SymbolizerSize() {\n#if defined(__wasm__) || defined(__asmjs__)\n  auto pagesize = static_cast<size_t>(getpagesize());\n#else\n  auto pagesize = static_cast<size_t>(sysconf(_SC_PAGESIZE));\n#endif\n  return ((sizeof(Symbolizer) - 1) / pagesize + 1) * pagesize;\n}\n\n// Return (and set null) g_cached_symbolized_state if it is not null.\n// Otherwise return a new symbolizer.\nstatic Symbolizer *AllocateSymbolizer() {\n  base_internal::InitSigSafeArena();\n  Symbolizer *symbolizer =\n      g_cached_symbolizer.exchange(nullptr, std::memory_order_acquire);\n  if (symbolizer == nullptr) {\n    void* ptr = base_internal::LowLevelAlloc::AllocWithArena(\n        SymbolizerSize(), base_internal::SigSafeArena());\n    symbolizer = new (ptr) Symbolizer();\n  }\n  symbolizer->UpdateDecoratorsIfNeeded(\n      g_decorator_factory.load(std::memory_order_acquire));\n  return symbolizer;\n}\n\n// Set g_cached_symbolize_state to s if it is null, otherwise\n// delete s.\nstatic void FreeSymbolizer(Symbolizer *s) {\n  Symbolizer *old_cached_symbolizer = nullptr;\n  if (!g_cached_symbolizer.compare_exchange_strong(old_cached_symbolizer, s,\n                                                   std::memory_order_release,\n                                                   std::memory_order_relaxed)) {\n    s->~Symbolizer();\n    base_internal::LowLevelAlloc::Free(s);\n  }\n}\n\nSymbolizer::Symbolizer() : ok_(true), addr_map_read_(false) {\n  for (SymbolCacheLine &symbol_cache_line : symbol_cache_) {\n    for (size_t j = 0; j < std::size(symbol_cache_line.name); ++j) {\n      symbol_cache_line.pc[j] = nullptr;\n      symbol_cache_line.name[j] = nullptr;\n      symbol_cache_line.age[j] = 0;\n    }\n  }\n}\n\nSymbolizer::~Symbolizer() {\n  for (SymbolCacheLine &symbol_cache_line : symbol_cache_) {\n    for (char *s : symbol_cache_line.name) {\n      base_internal::LowLevelAlloc::Free(s);\n    }\n  }\n  ClearAddrMap();\n}\n\nvoid Symbolizer::UpdateDecoratorsIfNeeded(\n    SymbolDecorator::Factory* decorator_factory) {\n  if (decorator_factory_ == decorator_factory) return;\n\n  for (SymbolCacheLine& symbol_cache_line : symbol_cache_) {\n    for (size_t j = 0; j < std::size(symbol_cache_line.name); ++j) {\n      symbol_cache_line.pc[j] = nullptr;\n      base_internal::LowLevelAlloc::Free(symbol_cache_line.name[j]);\n      symbol_cache_line.name[j] = nullptr;\n      symbol_cache_line.age[j] = 0;\n    }\n  }\n\n  decorator_factory_ = decorator_factory;\n  for (size_t i = 0, end = addr_map_.Size(); i < end; ++i) {\n    ObjFile* obj = addr_map_.At(i);\n    obj->decorator.reset();\n  }\n}\n\n// We don't use assert() since it's not guaranteed to be\n// async-signal-safe.  Instead we define a minimal assertion\n// macro. So far, we don't need pretty printing for __FILE__, etc.\n#define SAFE_ASSERT(expr) ((expr) ? static_cast<void>(0) : abort())\n\n// Read up to \"count\" bytes from file descriptor \"fd\" into the buffer\n// starting at \"buf\" while handling short reads and EINTR.  On\n// success, return the number of bytes read.  Otherwise, return -1.\nstatic ssize_t ReadPersistent(int fd, void *buf, size_t count) {\n  SAFE_ASSERT(fd >= 0);\n  SAFE_ASSERT(count <= SSIZE_MAX);\n  char *buf0 = reinterpret_cast<char *>(buf);\n  size_t num_bytes = 0;\n  while (num_bytes < count) {\n    ssize_t len;\n    NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes));\n    if (len < 0) {  // There was an error other than EINTR.\n      ABSL_RAW_LOG(WARNING, \"read failed: errno=%d\", errno);\n      return -1;\n    }\n    if (len == 0) {  // Reached EOF.\n      break;\n    }\n    num_bytes += static_cast<size_t>(len);\n  }\n  SAFE_ASSERT(num_bytes <= count);\n  return static_cast<ssize_t>(num_bytes);\n}\n\n// Read up to \"count\" bytes from \"offset\" into the buffer starting at \"buf\",\n// while handling short reads and EINTR.  On success, return the number of bytes\n// read.  Otherwise, return -1.\nssize_t CachingFile::ReadFromOffset(void *buf, size_t count, off_t offset) {\n  char *dst = static_cast<char *>(buf);\n  size_t read = 0;\n  while (read < count) {\n    // Look in cache first.\n    if (offset >= cache_start_ && offset < cache_limit_) {\n      const char *hit_start = &cache_[offset - cache_start_];\n      const size_t n =\n          std::min(count - read, static_cast<size_t>(cache_limit_ - offset));\n      memcpy(dst, hit_start, n);\n      dst += n;\n      read += static_cast<size_t>(n);\n      offset += static_cast<off_t>(n);\n      continue;\n    }\n\n    cache_start_ = 0;\n    cache_limit_ = 0;\n    ssize_t n = pread(fd_, cache_, cache_size_, offset);\n    if (n < 0) {\n      if (errno == EINTR) {\n        continue;\n      }\n      ABSL_RAW_LOG(WARNING, \"read failed: errno=%d\", errno);\n      return -1;\n    }\n    if (n == 0) {  // Reached EOF.\n      break;\n    }\n\n    cache_start_ = offset;\n    cache_limit_ = offset + static_cast<off_t>(n);\n    // Next iteration will copy from cache into dst.\n  }\n  return static_cast<ssize_t>(read);\n}\n\n// Try reading exactly \"count\" bytes from \"offset\" bytes into the buffer\n// starting at \"buf\" while handling short reads and EINTR.  On success, return\n// true. Otherwise, return false.\nbool CachingFile::ReadFromOffsetExact(void *buf, size_t count, off_t offset) {\n  ssize_t len = ReadFromOffset(buf, count, offset);\n  return len >= 0 && static_cast<size_t>(len) == count;\n}\n\n// Returns elf_header.e_type if the file pointed by fd is an ELF binary.\nstatic int FileGetElfType(CachingFile *file) {\n  ElfW(Ehdr) elf_header;\n  if (!file->ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) {\n    return -1;\n  }\n  if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) {\n    return -1;\n  }\n  return elf_header.e_type;\n}\n\n// Read the section headers in the given ELF binary, and if a section\n// of the specified type is found, set the output to this section header\n// and return true.  Otherwise, return false.\n// To keep stack consumption low, we would like this function to not get\n// inlined.\nstatic ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(\n    CachingFile *file, ElfW(Half) sh_num, const off_t sh_offset,\n    ElfW(Word) type, ElfW(Shdr) * out, char *tmp_buf, size_t tmp_buf_size) {\n  ElfW(Shdr) *buf = reinterpret_cast<ElfW(Shdr) *>(tmp_buf);\n  const size_t buf_entries = tmp_buf_size / sizeof(buf[0]);\n  const size_t buf_bytes = buf_entries * sizeof(buf[0]);\n\n  for (size_t i = 0; static_cast<int>(i) < sh_num;) {\n    const size_t num_bytes_left =\n        (static_cast<size_t>(sh_num) - i) * sizeof(buf[0]);\n    const size_t num_bytes_to_read =\n        (buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes;\n    const off_t offset = sh_offset + static_cast<off_t>(i * sizeof(buf[0]));\n    const ssize_t len = file->ReadFromOffset(buf, num_bytes_to_read, offset);\n    if (len <= 0) {\n      ABSL_RAW_LOG(WARNING, \"Reading %zu bytes from offset %ju returned %zd.\",\n                   num_bytes_to_read, static_cast<intmax_t>(offset), len);\n      return false;\n    }\n    if (static_cast<size_t>(len) % sizeof(buf[0]) != 0) {\n      ABSL_RAW_LOG(\n          WARNING,\n          \"Reading %zu bytes from offset %jd returned %zd which is not a \"\n          \"multiple of %zu.\",\n          num_bytes_to_read, static_cast<intmax_t>(offset), len,\n          sizeof(buf[0]));\n      return false;\n    }\n    const size_t num_headers_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);\n    SAFE_ASSERT(num_headers_in_buf <= buf_entries);\n    for (size_t j = 0; j < num_headers_in_buf; ++j) {\n      if (buf[j].sh_type == type) {\n        *out = buf[j];\n        return true;\n      }\n    }\n    i += num_headers_in_buf;\n  }\n  return false;\n}\n\n// There is no particular reason to limit section name to 63 characters,\n// but there has (as yet) been no need for anything longer either.\nconst int kMaxSectionNameLen = 64;\n\n// Small cache to use for miscellaneous file reads.\nconst int kSmallFileCacheSize = 100;\n\nbool ForEachSection(int fd,\n                    const std::function<bool(absl::string_view name,\n                                             const ElfW(Shdr) &)> &callback) {\n  char buf[kSmallFileCacheSize];\n  CachingFile file(fd, buf, sizeof(buf));\n\n  ElfW(Ehdr) elf_header;\n  if (!file.ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) {\n    return false;\n  }\n\n  // Technically it can be larger, but in practice this never happens.\n  if (elf_header.e_shentsize != sizeof(ElfW(Shdr))) {\n    return false;\n  }\n\n  ElfW(Shdr) shstrtab;\n  off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +\n                          elf_header.e_shentsize * elf_header.e_shstrndx;\n  if (!file.ReadFromOffsetExact(&shstrtab, sizeof(shstrtab), shstrtab_offset)) {\n    return false;\n  }\n\n  for (int i = 0; i < elf_header.e_shnum; ++i) {\n    ElfW(Shdr) out;\n    off_t section_header_offset =\n        static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i;\n    if (!file.ReadFromOffsetExact(&out, sizeof(out), section_header_offset)) {\n      return false;\n    }\n    off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out.sh_name;\n    char header_name[kMaxSectionNameLen];\n    ssize_t n_read =\n        file.ReadFromOffset(&header_name, kMaxSectionNameLen, name_offset);\n    if (n_read < 0) {\n      return false;\n    } else if (n_read > kMaxSectionNameLen) {\n      // Long read?\n      return false;\n    }\n\n    absl::string_view name(header_name,\n                           strnlen(header_name, static_cast<size_t>(n_read)));\n    if (!callback(name, out)) {\n      break;\n    }\n  }\n  return true;\n}\n\n// name_len should include terminating '\\0'.\nbool GetSectionHeaderByName(int fd, const char *name, size_t name_len,\n                            ElfW(Shdr) * out) {\n  char header_name[kMaxSectionNameLen];\n  if (sizeof(header_name) < name_len) {\n    ABSL_RAW_LOG(WARNING,\n                 \"Section name '%s' is too long (%zu); \"\n                 \"section will not be found (even if present).\",\n                 name, name_len);\n    // No point in even trying.\n    return false;\n  }\n\n  char buf[kSmallFileCacheSize];\n  CachingFile file(fd, buf, sizeof(buf));\n  ElfW(Ehdr) elf_header;\n  if (!file.ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) {\n    return false;\n  }\n\n  // Technically it can be larger, but in practice this never happens.\n  if (elf_header.e_shentsize != sizeof(ElfW(Shdr))) {\n    return false;\n  }\n\n  ElfW(Shdr) shstrtab;\n  off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +\n                          elf_header.e_shentsize * elf_header.e_shstrndx;\n  if (!file.ReadFromOffsetExact(&shstrtab, sizeof(shstrtab), shstrtab_offset)) {\n    return false;\n  }\n\n  for (int i = 0; i < elf_header.e_shnum; ++i) {\n    off_t section_header_offset =\n        static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i;\n    if (!file.ReadFromOffsetExact(out, sizeof(*out), section_header_offset)) {\n      return false;\n    }\n    off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out->sh_name;\n    ssize_t n_read = file.ReadFromOffset(&header_name, name_len, name_offset);\n    if (n_read < 0) {\n      return false;\n    } else if (static_cast<size_t>(n_read) != name_len) {\n      // Short read -- name could be at end of file.\n      continue;\n    }\n    if (memcmp(header_name, name, name_len) == 0) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// Compare symbols at in the same address.\n// Return true if we should pick symbol1.\nstatic bool ShouldPickFirstSymbol(const ElfW(Sym) & symbol1,\n                                  const ElfW(Sym) & symbol2) {\n  // If one of the symbols is weak and the other is not, pick the one\n  // this is not a weak symbol.\n  char bind1 = ELF_ST_BIND(symbol1.st_info);\n  char bind2 = ELF_ST_BIND(symbol1.st_info);\n  if (bind1 == STB_WEAK && bind2 != STB_WEAK) return false;\n  if (bind2 == STB_WEAK && bind1 != STB_WEAK) return true;\n\n  // If one of the symbols has zero size and the other is not, pick the\n  // one that has non-zero size.\n  if (symbol1.st_size != 0 && symbol2.st_size == 0) {\n    return true;\n  }\n  if (symbol1.st_size == 0 && symbol2.st_size != 0) {\n    return false;\n  }\n\n  // If one of the symbols has no type and the other is not, pick the\n  // one that has a type.\n  char type1 = ELF_ST_TYPE(symbol1.st_info);\n  char type2 = ELF_ST_TYPE(symbol1.st_info);\n  if (type1 != STT_NOTYPE && type2 == STT_NOTYPE) {\n    return true;\n  }\n  if (type1 == STT_NOTYPE && type2 != STT_NOTYPE) {\n    return false;\n  }\n\n  // Pick the first one, if we still cannot decide.\n  return true;\n}\n\n// Return true if an address is inside a section.\nstatic bool InSection(const void *address, ptrdiff_t relocation,\n                      const ElfW(Shdr) * section) {\n  const char *start = reinterpret_cast<const char *>(\n      section->sh_addr + static_cast<ElfW(Addr)>(relocation));\n  size_t size = static_cast<size_t>(section->sh_size);\n  return start <= address && address < (start + size);\n}\n\nstatic const char *ComputeOffset(const char *base, ptrdiff_t offset) {\n  // Note: cast to intptr_t to avoid undefined behavior when base evaluates to\n  // zero and offset is non-zero.\n  return reinterpret_cast<const char *>(reinterpret_cast<intptr_t>(base) +\n                                        offset);\n}\n\n// Read a symbol table and look for the symbol containing the\n// pc. Iterate over symbols in a symbol table and look for the symbol\n// containing \"pc\".  If the symbol is found, and its name fits in\n// out_size, the name is written into out and SYMBOL_FOUND is returned.\n// If the name does not fit, truncated name is written into out,\n// and SYMBOL_TRUNCATED is returned. Out is NUL-terminated.\n// If the symbol is not found, SYMBOL_NOT_FOUND is returned;\n// To keep stack consumption low, we would like this function to not get\n// inlined.\nstatic ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(\n    const void *const pc, CachingFile *file, char *out, size_t out_size,\n    ptrdiff_t relocation, const ElfW(Shdr) * strtab, const ElfW(Shdr) * symtab,\n    const ElfW(Shdr) * opd, char *tmp_buf, size_t tmp_buf_size) {\n  if (symtab == nullptr) {\n    return SYMBOL_NOT_FOUND;\n  }\n\n  // Read multiple symbols at once to save read() calls.\n  ElfW(Sym) *buf = reinterpret_cast<ElfW(Sym) *>(tmp_buf);\n  const size_t buf_entries = tmp_buf_size / sizeof(buf[0]);\n\n  const size_t num_symbols = symtab->sh_size / symtab->sh_entsize;\n\n  // On platforms using an .opd section (PowerPC & IA64), a function symbol\n  // has the address of a function descriptor, which contains the real\n  // starting address.  However, we do not always want to use the real\n  // starting address because we sometimes want to symbolize a function\n  // pointer into the .opd section, e.g. FindSymbol(&foo,...).\n  const bool pc_in_opd = kPlatformUsesOPDSections && opd != nullptr &&\n                         InSection(pc, relocation, opd);\n  const bool deref_function_descriptor_pointer =\n      kPlatformUsesOPDSections && opd != nullptr && !pc_in_opd;\n\n  ElfW(Sym) best_match;\n  SafeMemZero(&best_match, sizeof(best_match));\n  bool found_match = false;\n  for (size_t i = 0; i < num_symbols;) {\n    off_t offset =\n        static_cast<off_t>(symtab->sh_offset + i * symtab->sh_entsize);\n    const size_t num_remaining_symbols = num_symbols - i;\n    const size_t entries_in_chunk =\n        std::min(num_remaining_symbols, buf_entries);\n    const size_t bytes_in_chunk = entries_in_chunk * sizeof(buf[0]);\n    const ssize_t len = file->ReadFromOffset(buf, bytes_in_chunk, offset);\n    SAFE_ASSERT(len >= 0);\n    SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);\n    const size_t num_symbols_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);\n    SAFE_ASSERT(num_symbols_in_buf <= entries_in_chunk);\n    for (size_t j = 0; j < num_symbols_in_buf; ++j) {\n      const ElfW(Sym) &symbol = buf[j];\n\n      // For a DSO, a symbol address is relocated by the loading address.\n      // We keep the original address for opd redirection below.\n      const char *const original_start_address =\n          reinterpret_cast<const char *>(symbol.st_value);\n      const char *start_address =\n          ComputeOffset(original_start_address, relocation);\n\n#ifdef __arm__\n      // ARM functions are always aligned to multiples of two bytes; the\n      // lowest-order bit in start_address is ignored by the CPU and indicates\n      // whether the function contains ARM (0) or Thumb (1) code. We don't care\n      // about what encoding is being used; we just want the real start address\n      // of the function.\n      start_address = reinterpret_cast<const char *>(\n          reinterpret_cast<uintptr_t>(start_address) & ~1u);\n#endif\n\n      if (deref_function_descriptor_pointer &&\n          InSection(original_start_address, /*relocation=*/0, opd)) {\n        // The opd section is mapped into memory.  Just dereference\n        // start_address to get the first double word, which points to the\n        // function entry.\n        start_address = *reinterpret_cast<const char *const *>(start_address);\n      }\n\n      // If pc is inside the .opd section, it points to a function descriptor.\n      const size_t size = pc_in_opd ? kFunctionDescriptorSize : symbol.st_size;\n      const void *const end_address =\n          ComputeOffset(start_address, static_cast<ptrdiff_t>(size));\n      if (symbol.st_value != 0 &&  // Skip null value symbols.\n          symbol.st_shndx != 0 &&  // Skip undefined symbols.\n#ifdef STT_TLS\n          ELF_ST_TYPE(symbol.st_info) != STT_TLS &&  // Skip thread-local data.\n#endif                                               // STT_TLS\n          ((start_address <= pc && pc < end_address) ||\n           (start_address == pc && pc == end_address))) {\n        if (!found_match || ShouldPickFirstSymbol(symbol, best_match)) {\n          found_match = true;\n          best_match = symbol;\n        }\n      }\n    }\n    i += num_symbols_in_buf;\n  }\n\n  if (found_match) {\n    const off_t off =\n        static_cast<off_t>(strtab->sh_offset) + best_match.st_name;\n    const ssize_t n_read = file->ReadFromOffset(out, out_size, off);\n    if (n_read <= 0) {\n      // This should never happen.\n      ABSL_RAW_LOG(WARNING,\n                   \"Unable to read from fd %d at offset %lld: n_read = %zd\",\n                   file->fd(), static_cast<long long>(off), n_read);\n      return SYMBOL_NOT_FOUND;\n    }\n    ABSL_RAW_CHECK(static_cast<size_t>(n_read) <= out_size,\n                   \"ReadFromOffset read too much data.\");\n\n    // strtab->sh_offset points into .strtab-like section that contains\n    // NUL-terminated strings: '\\0foo\\0barbaz\\0...\".\n    //\n    // sh_offset+st_name points to the start of symbol name, but we don't know\n    // how long the symbol is, so we try to read as much as we have space for,\n    // and usually over-read (i.e. there is a NUL somewhere before n_read).\n    if (memchr(out, '\\0', static_cast<size_t>(n_read)) == nullptr) {\n      // Either out_size was too small (n_read == out_size and no NUL), or\n      // we tried to read past the EOF (n_read < out_size) and .strtab is\n      // corrupt (missing terminating NUL; should never happen for valid ELF).\n      out[n_read - 1] = '\\0';\n      return SYMBOL_TRUNCATED;\n    }\n    return SYMBOL_FOUND;\n  }\n\n  return SYMBOL_NOT_FOUND;\n}\n\n// Get the symbol name of \"pc\" from the file pointed by \"fd\".  Process\n// both regular and dynamic symbol tables if necessary.\n// See FindSymbol() comment for description of return value.\nFindSymbolResult Symbolizer::GetSymbolFromObjectFile(\n    const ObjFile &obj, const void *const pc, const ptrdiff_t relocation,\n    char *out, size_t out_size, char *tmp_buf, size_t tmp_buf_size) {\n  ElfW(Shdr) symtab;\n  ElfW(Shdr) strtab;\n  ElfW(Shdr) opd;\n  ElfW(Shdr) *opd_ptr = nullptr;\n\n  // On platforms using an .opd sections for function descriptor, read\n  // the section header.  The .opd section is in data segment and should be\n  // loaded but we check that it is mapped just to be extra careful.\n  if (kPlatformUsesOPDSections) {\n    if (GetSectionHeaderByName(obj.fd, kOpdSectionName,\n                               sizeof(kOpdSectionName) - 1, &opd) &&\n        FindObjFile(reinterpret_cast<const char *>(opd.sh_addr) + relocation,\n                    opd.sh_size) != nullptr) {\n      opd_ptr = &opd;\n    } else {\n      return SYMBOL_NOT_FOUND;\n    }\n  }\n\n  CachingFile file(obj.fd, file_cache_, sizeof(file_cache_));\n\n  // Consult a regular symbol table, then fall back to the dynamic symbol table.\n  for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) {\n    if (!GetSectionHeaderByType(&file, obj.elf_header.e_shnum,\n                                static_cast<off_t>(obj.elf_header.e_shoff),\n                                static_cast<ElfW(Word)>(symbol_table_type),\n                                &symtab, tmp_buf, tmp_buf_size)) {\n      continue;\n    }\n    if (!file.ReadFromOffsetExact(\n            &strtab, sizeof(strtab),\n            static_cast<off_t>(obj.elf_header.e_shoff +\n                               symtab.sh_link * sizeof(symtab)))) {\n      continue;\n    }\n    const FindSymbolResult rc =\n        FindSymbol(pc, &file, out, out_size, relocation, &strtab, &symtab,\n                   opd_ptr, tmp_buf, tmp_buf_size);\n    if (rc != SYMBOL_NOT_FOUND) {\n      return rc;\n    }\n  }\n\n  return SYMBOL_NOT_FOUND;\n}\n\nnamespace {\n// Thin wrapper around a file descriptor so that the file descriptor\n// gets closed for sure.\nclass FileDescriptor {\n public:\n  explicit FileDescriptor(int fd) : fd_(fd) {}\n  FileDescriptor(const FileDescriptor &) = delete;\n  FileDescriptor &operator=(const FileDescriptor &) = delete;\n\n  ~FileDescriptor() {\n    if (fd_ >= 0) {\n      close(fd_);\n    }\n  }\n\n  int get() const { return fd_; }\n\n private:\n  const int fd_;\n};\n\n// Helper class for reading lines from file.\n//\n// Note: we don't use ProcMapsIterator since the object is big (it has\n// a 5k array member) and uses async-unsafe functions such as sscanf()\n// and snprintf().\nclass LineReader {\n public:\n  explicit LineReader(int fd, char *buf, size_t buf_len)\n      : fd_(fd),\n        buf_len_(buf_len),\n        buf_(buf),\n        bol_(buf),\n        eol_(buf),\n        eod_(buf) {}\n\n  LineReader(const LineReader &) = delete;\n  LineReader &operator=(const LineReader &) = delete;\n\n  // Read '\\n'-terminated line from file.  On success, modify \"bol\"\n  // and \"eol\", then return true.  Otherwise, return false.\n  //\n  // Note: if the last line doesn't end with '\\n', the line will be\n  // dropped.  It's an intentional behavior to make the code simple.\n  bool ReadLine(const char **bol, const char **eol) {\n    if (BufferIsEmpty()) {  // First time.\n      const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_);\n      if (num_bytes <= 0) {  // EOF or error.\n        return false;\n      }\n      eod_ = buf_ + num_bytes;\n      bol_ = buf_;\n    } else {\n      bol_ = eol_ + 1;            // Advance to the next line in the buffer.\n      SAFE_ASSERT(bol_ <= eod_);  // \"bol_\" can point to \"eod_\".\n      if (!HasCompleteLine()) {\n        const auto incomplete_line_length = static_cast<size_t>(eod_ - bol_);\n        // Move the trailing incomplete line to the beginning.\n        memmove(buf_, bol_, incomplete_line_length);\n        // Read text from file and append it.\n        char *const append_pos = buf_ + incomplete_line_length;\n        const size_t capacity_left = buf_len_ - incomplete_line_length;\n        const ssize_t num_bytes =\n            ReadPersistent(fd_, append_pos, capacity_left);\n        if (num_bytes <= 0) {  // EOF or error.\n          return false;\n        }\n        eod_ = append_pos + num_bytes;\n        bol_ = buf_;\n      }\n    }\n    eol_ = FindLineFeed();\n    if (eol_ == nullptr) {  // '\\n' not found.  Malformed line.\n      return false;\n    }\n    *eol_ = '\\0';  // Replace '\\n' with '\\0'.\n\n    *bol = bol_;\n    *eol = eol_;\n    return true;\n  }\n\n private:\n  char *FindLineFeed() const {\n    return reinterpret_cast<char *>(\n        memchr(bol_, '\\n', static_cast<size_t>(eod_ - bol_)));\n  }\n\n  bool BufferIsEmpty() const { return buf_ == eod_; }\n\n  bool HasCompleteLine() const {\n    return !BufferIsEmpty() && FindLineFeed() != nullptr;\n  }\n\n  const int fd_;\n  const size_t buf_len_;\n  char *const buf_;\n  char *bol_;\n  char *eol_;\n  const char *eod_;  // End of data in \"buf_\".\n};\n}  // namespace\n\n// Place the hex number read from \"start\" into \"*hex\".  The pointer to\n// the first non-hex character or \"end\" is returned.\nstatic const char *GetHex(const char *start, const char *end,\n                          uint64_t *const value) {\n  uint64_t hex = 0;\n  const char *p;\n  for (p = start; p < end; ++p) {\n    int ch = *p;\n    if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||\n        (ch >= 'a' && ch <= 'f')) {\n      hex = (hex << 4) |\n            static_cast<uint64_t>(ch < 'A' ? ch - '0' : (ch & 0xF) + 9);\n    } else {  // Encountered the first non-hex character.\n      break;\n    }\n  }\n  SAFE_ASSERT(p <= end);\n  *value = hex;\n  return p;\n}\n\nstatic const char *GetHex(const char *start, const char *end,\n                          const void **const addr) {\n  uint64_t hex = 0;\n  const char *p = GetHex(start, end, &hex);\n  *addr = reinterpret_cast<void *>(hex);\n  return p;\n}\n\n// Normally we are only interested in \"r?x\" maps.\n// On the PowerPC, function pointers point to descriptors in the .opd\n// section.  The descriptors themselves are not executable code, so\n// we need to relax the check below to \"r??\".\nstatic bool ShouldUseMapping(const char *const flags) {\n  return flags[0] == 'r' && (kPlatformUsesOPDSections || flags[2] == 'x');\n}\n\n// Read /proc/self/maps and run \"callback\" for each mmapped file found.  If\n// \"callback\" returns false, stop scanning and return true. Else continue\n// scanning /proc/self/maps. Return true if no parse error is found.\nstatic ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap(\n    bool (*callback)(const char *filename, const void *const start_addr,\n                     const void *const end_addr, uint64_t offset, void *arg),\n    void *arg, void *tmp_buf, size_t tmp_buf_size) {\n  // Use /proc/self/task/<pid>/maps instead of /proc/self/maps. The latter\n  // requires kernel to stop all threads, and is significantly slower when there\n  // are 1000s of threads.\n  char maps_path[80];\n  snprintf(maps_path, sizeof(maps_path), \"/proc/self/task/%d/maps\", getpid());\n\n  int maps_fd;\n  NO_INTR(maps_fd = OpenReadOnlyWithHighFD(maps_path));\n  FileDescriptor wrapped_maps_fd(maps_fd);\n  if (wrapped_maps_fd.get() < 0) {\n    ABSL_RAW_LOG(WARNING, \"%s: errno=%d\", maps_path, errno);\n    return false;\n  }\n\n  // Iterate over maps and look for the map containing the pc.  Then\n  // look into the symbol tables inside.\n  LineReader reader(wrapped_maps_fd.get(), static_cast<char *>(tmp_buf),\n                    tmp_buf_size);\n  while (true) {\n    const char *cursor;\n    const char *eol;\n    if (!reader.ReadLine(&cursor, &eol)) {  // EOF or malformed line.\n      break;\n    }\n\n    const char *line = cursor;\n    const void *start_address;\n    // Start parsing line in /proc/self/maps.  Here is an example:\n    //\n    // 08048000-0804c000 r-xp 00000000 08:01 2142121    /bin/cat\n    //\n    // We want start address (08048000), end address (0804c000), flags\n    // (r-xp) and file name (/bin/cat).\n\n    // Read start address.\n    cursor = GetHex(cursor, eol, &start_address);\n    if (cursor == eol || *cursor != '-') {\n      ABSL_RAW_LOG(WARNING, \"Corrupt /proc/self/maps line: %s\", line);\n      return false;\n    }\n    ++cursor;  // Skip '-'.\n\n    // Read end address.\n    const void *end_address;\n    cursor = GetHex(cursor, eol, &end_address);\n    if (cursor == eol || *cursor != ' ') {\n      ABSL_RAW_LOG(WARNING, \"Corrupt /proc/self/maps line: %s\", line);\n      return false;\n    }\n    ++cursor;  // Skip ' '.\n\n    // Read flags.  Skip flags until we encounter a space or eol.\n    const char *const flags_start = cursor;\n    while (cursor < eol && *cursor != ' ') {\n      ++cursor;\n    }\n    // We expect at least four letters for flags (ex. \"r-xp\").\n    if (cursor == eol || cursor < flags_start + 4) {\n      ABSL_RAW_LOG(WARNING, \"Corrupt /proc/self/maps: %s\", line);\n      return false;\n    }\n\n    // Check flags.\n    if (!ShouldUseMapping(flags_start)) {\n      continue;  // We skip this map.\n    }\n    ++cursor;  // Skip ' '.\n\n    // Read file offset.\n    uint64_t offset;\n    cursor = GetHex(cursor, eol, &offset);\n    ++cursor;  // Skip ' '.\n\n    // Skip to file name.  \"cursor\" now points to dev.  We need to skip at least\n    // two spaces for dev and inode.\n    int num_spaces = 0;\n    while (cursor < eol) {\n      if (*cursor == ' ') {\n        ++num_spaces;\n      } else if (num_spaces >= 2) {\n        // The first non-space character after  skipping two spaces\n        // is the beginning of the file name.\n        break;\n      }\n      ++cursor;\n    }\n\n    // Check whether this entry corresponds to our hint table for the true\n    // filename.\n    bool hinted =\n        GetFileMappingHint(&start_address, &end_address, &offset, &cursor);\n    if (!hinted && (cursor == eol || cursor[0] == '[')) {\n      // not an object file, typically [vdso] or [vsyscall]\n      continue;\n    }\n    if (!callback(cursor, start_address, end_address, offset, arg)) break;\n  }\n  return true;\n}\n\n// Find the objfile mapped in address region containing [addr, addr + len).\nObjFile *Symbolizer::FindObjFile(const void *const addr, size_t len) {\n  for (int i = 0; i < 2; ++i) {\n    if (!ok_) return nullptr;\n\n    // Read /proc/self/maps if necessary\n    if (!addr_map_read_) {\n      addr_map_read_ = true;\n      if (!ReadAddrMap(RegisterObjFile, this, tmp_buf_, TMP_BUF_SIZE)) {\n        ok_ = false;\n        return nullptr;\n      }\n    }\n\n    size_t lo = 0;\n    size_t hi = addr_map_.Size();\n    while (lo < hi) {\n      size_t mid = (lo + hi) / 2;\n      if (addr < addr_map_.At(mid)->end_addr) {\n        hi = mid;\n      } else {\n        lo = mid + 1;\n      }\n    }\n    if (lo != addr_map_.Size()) {\n      ObjFile *obj = addr_map_.At(lo);\n      SAFE_ASSERT(obj->end_addr > addr);\n      if (addr >= obj->start_addr &&\n          reinterpret_cast<const char *>(addr) + len <= obj->end_addr)\n        return obj;\n    }\n\n    // The address mapping may have changed since it was last read.  Retry.\n    ClearAddrMap();\n  }\n  return nullptr;\n}\n\nvoid Symbolizer::ClearAddrMap() {\n  for (size_t i = 0; i != addr_map_.Size(); i++) {\n    ObjFile *o = addr_map_.At(i);\n    base_internal::LowLevelAlloc::Free(o->filename);\n    if (o->fd >= 0) {\n      close(o->fd);\n    }\n  }\n  addr_map_.Clear();\n  addr_map_read_ = false;\n}\n\n// Callback for ReadAddrMap to register objfiles in an in-memory table.\nbool Symbolizer::RegisterObjFile(const char *filename,\n                                 const void *const start_addr,\n                                 const void *const end_addr, uint64_t offset,\n                                 void *arg) {\n  Symbolizer *impl = static_cast<Symbolizer *>(arg);\n\n  // Files are supposed to be added in the increasing address order.  Make\n  // sure that's the case.\n  size_t addr_map_size = impl->addr_map_.Size();\n  if (addr_map_size != 0) {\n    ObjFile *old = impl->addr_map_.At(addr_map_size - 1);\n    if (old->end_addr > end_addr) {\n      ABSL_RAW_LOG(ERROR,\n                   \"Unsorted addr map entry: 0x%\" PRIxPTR \": %s <-> 0x%\" PRIxPTR\n                   \": %s\",\n                   reinterpret_cast<uintptr_t>(end_addr), filename,\n                   reinterpret_cast<uintptr_t>(old->end_addr), old->filename);\n      return true;\n    } else if (old->end_addr == end_addr) {\n      // The same entry appears twice. This sometimes happens for [vdso].\n      if (old->start_addr != start_addr ||\n          strcmp(old->filename, filename) != 0) {\n        ABSL_RAW_LOG(ERROR,\n                     \"Duplicate addr 0x%\" PRIxPTR \": %s <-> 0x%\" PRIxPTR \": %s\",\n                     reinterpret_cast<uintptr_t>(end_addr), filename,\n                     reinterpret_cast<uintptr_t>(old->end_addr), old->filename);\n      }\n      return true;\n    } else if (old->end_addr == start_addr &&\n               reinterpret_cast<uintptr_t>(old->start_addr) - old->offset ==\n                   reinterpret_cast<uintptr_t>(start_addr) - offset &&\n               strcmp(old->filename, filename) == 0) {\n      // Two contiguous map entries that span a contiguous region of the file,\n      // perhaps because some part of the file was mlock()ed. Combine them.\n      old->end_addr = end_addr;\n      return true;\n    }\n  }\n  ObjFile *obj = impl->addr_map_.Add();\n  obj->filename = impl->CopyString(filename);\n  obj->start_addr = start_addr;\n  obj->end_addr = end_addr;\n  obj->offset = offset;\n  obj->elf_type = -1;  // filled on demand\n  obj->fd = -1;        // opened on demand\n  return true;\n}\n\n// This function wraps the Demangle function to provide an interface\n// where the input symbol is demangled in-place.\n// To keep stack consumption low, we would like this function to not\n// get inlined.\nstatic ABSL_ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size,\n                                                    char *tmp_buf,\n                                                    size_t tmp_buf_size) {\n  if (Demangle(out, tmp_buf, tmp_buf_size)) {\n    // Demangling succeeded. Copy to out if the space allows.\n    size_t len = strlen(tmp_buf);\n    if (len + 1 <= out_size) {  // +1 for '\\0'.\n      SAFE_ASSERT(len < tmp_buf_size);\n      memmove(out, tmp_buf, len + 1);\n    }\n  }\n}\n\nSymbolCacheLine *Symbolizer::GetCacheLine(const void *const pc) {\n  uintptr_t pc0 = reinterpret_cast<uintptr_t>(pc);\n  pc0 >>= 3;  // drop the low 3 bits\n\n  // Shuffle bits.\n  pc0 ^= (pc0 >> 6) ^ (pc0 >> 12) ^ (pc0 >> 18);\n  return &symbol_cache_[pc0 % SYMBOL_CACHE_LINES];\n}\n\nvoid Symbolizer::AgeSymbols(SymbolCacheLine *line) {\n  for (uint32_t &age : line->age) {\n    ++age;\n  }\n}\n\nconst char *Symbolizer::FindSymbolInCache(const void *const pc) {\n  if (pc == nullptr) return nullptr;\n\n  SymbolCacheLine *line = GetCacheLine(pc);\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) {\n    if (line->pc[i] == pc) {\n      AgeSymbols(line);\n      line->age[i] = 0;\n      return line->name[i];\n    }\n  }\n  return nullptr;\n}\n\nconst char *Symbolizer::InsertSymbolInCache(const void *const pc,\n                                            const char *name) {\n  SAFE_ASSERT(pc != nullptr);\n\n  SymbolCacheLine *line = GetCacheLine(pc);\n  uint32_t max_age = 0;\n  size_t oldest_index = 0;\n  bool found_oldest_index = false;\n  for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) {\n    if (line->pc[i] == nullptr) {\n      AgeSymbols(line);\n      line->pc[i] = pc;\n      line->name[i] = CopyString(name);\n      line->age[i] = 0;\n      return line->name[i];\n    }\n    if (line->age[i] >= max_age) {\n      max_age = line->age[i];\n      oldest_index = i;\n      found_oldest_index = true;\n    }\n  }\n\n  AgeSymbols(line);\n  ABSL_RAW_CHECK(found_oldest_index, \"Corrupt cache\");\n  base_internal::LowLevelAlloc::Free(line->name[oldest_index]);\n  line->pc[oldest_index] = pc;\n  line->name[oldest_index] = CopyString(name);\n  line->age[oldest_index] = 0;\n  return line->name[oldest_index];\n}\n\nstatic void MaybeOpenFdFromSelfExe(ObjFile *obj) {\n  if (memcmp(obj->start_addr, ELFMAG, SELFMAG) != 0) {\n    return;\n  }\n  int fd = OpenReadOnlyWithHighFD(\"/proc/self/exe\");\n  if (fd == -1) {\n    return;\n  }\n  // Verify that contents of /proc/self/exe matches in-memory image of\n  // the binary. This can fail if the \"deleted\" binary is in fact not\n  // the main executable, or for binaries that have the first PT_LOAD\n  // segment smaller than 4K. We do it in four steps so that the\n  // buffer is smaller and we don't consume too much stack space.\n  const char *mem = reinterpret_cast<const char *>(obj->start_addr);\n  for (int i = 0; i < 4; ++i) {\n    char buf[1024];\n    ssize_t n = read(fd, buf, sizeof(buf));\n    if (n != sizeof(buf) || memcmp(buf, mem, sizeof(buf)) != 0) {\n      close(fd);\n      return;\n    }\n    mem += sizeof(buf);\n  }\n  obj->fd = fd;\n}\n\nstatic bool MaybeInitializeObjFile(\n    ObjFile* obj, SymbolDecorator::Factory* decorator_factory) {\n  if (obj->fd < 0) {\n    obj->fd = OpenReadOnlyWithHighFD(obj->filename);\n\n    if (obj->fd < 0) {\n      // Getting /proc/self/exe here means that we were hinted.\n      if (strcmp(obj->filename, \"/proc/self/exe\") == 0) {\n        // /proc/self/exe may be inaccessible (due to setuid, etc.), so try\n        // accessing the binary via argv0.\n        if (argv0_value != nullptr) {\n          obj->fd = OpenReadOnlyWithHighFD(argv0_value);\n        }\n      } else {\n        MaybeOpenFdFromSelfExe(obj);\n      }\n    }\n\n    if (obj->fd < 0) {\n      ABSL_RAW_LOG(WARNING, \"%s: open failed: errno=%d\", obj->filename, errno);\n      return false;\n    }\n\n    char buf[kSmallFileCacheSize];\n    CachingFile file(obj->fd, buf, sizeof(buf));\n\n    obj->elf_type = FileGetElfType(&file);\n    if (obj->elf_type < 0) {\n      ABSL_RAW_LOG(WARNING, \"%s: wrong elf type: %d\", obj->filename,\n                   obj->elf_type);\n      return false;\n    }\n\n    if (!file.ReadFromOffsetExact(&obj->elf_header, sizeof(obj->elf_header),\n                                  0)) {\n      ABSL_RAW_LOG(WARNING, \"%s: failed to read elf header\", obj->filename);\n      return false;\n    }\n    const int phnum = obj->elf_header.e_phnum;\n    const int phentsize = obj->elf_header.e_phentsize;\n    auto phoff = static_cast<off_t>(obj->elf_header.e_phoff);\n    size_t num_interesting_load_segments = 0;\n    for (int j = 0; j < phnum; j++) {\n      ElfW(Phdr) phdr;\n      if (!file.ReadFromOffsetExact(&phdr, sizeof(phdr), phoff)) {\n        ABSL_RAW_LOG(WARNING, \"%s: failed to read program header %d\",\n                     obj->filename, j);\n        return false;\n      }\n      phoff += phentsize;\n\n#ifdef ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI\n      // On the PowerPC 64-bit ELFv1 ABI, function pointers actually point to\n      // function descriptors. These descriptors are stored in an .opd section,\n      // which is mapped read-only. We thus need to look at all readable\n      // segments, not just the executable ones.\n      constexpr int interesting = PF_R;\n#else\n      constexpr int interesting = PF_X | PF_R;\n#endif\n\n      if (phdr.p_type != PT_LOAD ||\n          (phdr.p_flags & interesting) != interesting) {\n        // Not a LOAD segment, not executable code, and not a function\n        // descriptor.\n        continue;\n      }\n      if (num_interesting_load_segments < obj->phdr.size()) {\n        memcpy(&obj->phdr[num_interesting_load_segments++], &phdr,\n               sizeof(phdr));\n      } else {\n        ABSL_RAW_LOG(\n            WARNING, \"%s: too many interesting LOAD segments: %zu >= %zu\",\n            obj->filename, num_interesting_load_segments, obj->phdr.size());\n        break;\n      }\n    }\n    if (num_interesting_load_segments == 0) {\n      // This object has no interesting LOAD segments. That's unexpected.\n      ABSL_RAW_LOG(WARNING, \"%s: no interesting LOAD segments\", obj->filename);\n      return false;\n    }\n  }\n  if (decorator_factory != nullptr && obj->decorator == nullptr) {\n    obj->decorator = decorator_factory(obj->fd);\n  }\n  return true;\n}\n\n// The implementation of our symbolization routine.  If it\n// successfully finds the symbol containing \"pc\" and obtains the\n// symbol name, returns pointer to that symbol. Otherwise, returns nullptr.\n// If any symbol decorators have been installed via InstallSymbolDecorator(),\n// they are called here as well.\n// To keep stack consumption low, we would like this function to not\n// get inlined.\nconst char *Symbolizer::GetUncachedSymbol(const void *pc) {\n  ObjFile *const obj = FindObjFile(pc, 1);\n  ptrdiff_t relocation = 0;\n  if (obj != nullptr) {\n    if (MaybeInitializeObjFile(obj, decorator_factory_)) {\n      const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);\n      if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {\n        // This object was relocated.\n        //\n        // For obj->offset > 0, adjust the relocation since a mapping at offset\n        // X in the file will have a start address of [true relocation]+X.\n        relocation = static_cast<ptrdiff_t>(start_addr - obj->offset);\n\n        // Note: some binaries have multiple LOAD segments that can contain\n        // function pointers. We must find the right one.\n        ElfW(Phdr) *phdr = nullptr;\n        for (size_t j = 0; j < obj->phdr.size(); j++) {\n          ElfW(Phdr) &p = obj->phdr[j];\n          if (p.p_type != PT_LOAD) {\n            // We only expect PT_LOADs. This must be PT_NULL that we didn't\n            // write over (i.e. we exhausted all interesting PT_LOADs).\n            ABSL_RAW_CHECK(p.p_type == PT_NULL, \"unexpected p_type\");\n            break;\n          }\n          if (pc <\n              reinterpret_cast<void *>(start_addr + p.p_vaddr + p.p_memsz)) {\n            phdr = &p;\n            break;\n          }\n        }\n        if (phdr == nullptr) {\n          // That's unexpected. Hope for the best.\n          ABSL_RAW_LOG(\n              WARNING,\n              \"%s: unable to find LOAD segment for pc: %p, start_addr: %zx\",\n              obj->filename, pc, start_addr);\n        } else {\n          // Adjust relocation in case phdr.p_vaddr != 0.\n          // This happens for binaries linked with `lld --rosegment`, and for\n          // binaries linked with BFD `ld -z separate-code`.\n          relocation -= phdr->p_vaddr - phdr->p_offset;\n        }\n      }\n\n      if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,\n                                  sizeof(symbol_buf_), tmp_buf_,\n                                  sizeof(tmp_buf_)) == SYMBOL_FOUND) {\n        // Only try to demangle the symbol name if it fit into symbol_buf_.\n        DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,\n                        sizeof(tmp_buf_));\n      }\n    }\n  } else {\n#if ABSL_HAVE_VDSO_SUPPORT\n    VDSOSupport vdso;\n    if (vdso.IsPresent()) {\n      VDSOSupport::SymbolInfo symbol_info;\n      if (vdso.LookupSymbolByAddress(pc, &symbol_info)) {\n        // All VDSO symbols are known to be short.\n        size_t len = strlen(symbol_info.name);\n        ABSL_RAW_CHECK(len + 1 < sizeof(symbol_buf_),\n                       \"VDSO symbol unexpectedly long\");\n        memcpy(symbol_buf_, symbol_info.name, len + 1);\n      }\n    }\n#endif\n  }\n\n  if (obj != nullptr && obj->decorator != nullptr) {\n    obj->decorator->Decorate(pc, relocation, symbol_buf_, sizeof(symbol_buf_),\n                             tmp_buf_, sizeof(tmp_buf_));\n  }\n  if (symbol_buf_[0] == '\\0') {\n    return nullptr;\n  }\n  symbol_buf_[sizeof(symbol_buf_) - 1] = '\\0';  // Paranoia.\n  return InsertSymbolInCache(pc, symbol_buf_);\n}\n\nconst char *Symbolizer::GetSymbol(const void *pc) {\n  const char *entry = FindSymbolInCache(pc);\n  if (entry != nullptr) {\n    return entry;\n  }\n  symbol_buf_[0] = '\\0';\n\n#ifdef __hppa__\n  {\n    // In some contexts (e.g., return addresses), PA-RISC uses the lowest two\n    // bits of the address to indicate the privilege level. Clear those bits\n    // before trying to symbolize.\n    const auto pc_bits = reinterpret_cast<uintptr_t>(pc);\n    const auto address = pc_bits & ~0x3;\n    entry = GetUncachedSymbol(reinterpret_cast<const void *>(address));\n    if (entry != nullptr) {\n      return entry;\n    }\n\n    // In some contexts, PA-RISC also uses bit 1 of the address to indicate that\n    // this is a cross-DSO function pointer. Such function pointers actually\n    // point to a procedure label, a struct whose first 32-bit (pointer) element\n    // actually points to the function text. With no symbol found for this\n    // address so far, try interpreting it as a cross-DSO function pointer and\n    // see how that goes.\n    if (pc_bits & 0x2) {\n      return GetUncachedSymbol(*reinterpret_cast<const void *const *>(address));\n    }\n\n    return nullptr;\n  }\n#else\n  return GetUncachedSymbol(pc);\n#endif\n}\n\nSymbolDecorator::Factory* SetSymbolDecoratorFactory(\n    SymbolDecorator::Factory* factory) {\n  return g_decorator_factory.exchange(factory, std::memory_order_acq_rel);\n}\n\nbool RegisterFileMappingHint(const void *start, const void *end,\n                             uint64_t offset, const char *filename) {\n  SAFE_ASSERT(start <= end);\n  SAFE_ASSERT(filename != nullptr);\n\n  base_internal::InitSigSafeArena();\n\n  if (!g_file_mapping_mu.try_lock()) {\n    return false;\n  }\n\n  bool ret = true;\n  if (g_num_file_mapping_hints >= kMaxFileMappingHints) {\n    ret = false;\n  } else {\n    // TODO(ckennelly): Move this into a string copy routine.\n    size_t len = strlen(filename);\n    char *dst =\n        static_cast<char *>(base_internal::LowLevelAlloc::AllocWithArena(\n            len + 1, base_internal::SigSafeArena()));\n    ABSL_RAW_CHECK(dst != nullptr, \"out of memory\");\n    memcpy(dst, filename, len + 1);\n\n    auto &hint = g_file_mapping_hints[g_num_file_mapping_hints++];\n    hint.start = start;\n    hint.end = end;\n    hint.offset = offset;\n    hint.filename = dst;\n  }\n\n  g_file_mapping_mu.unlock();\n  return ret;\n}\n\nbool GetFileMappingHint(const void **start, const void **end, uint64_t *offset,\n                        const char **filename) {\n  if (!g_file_mapping_mu.try_lock()) {\n    return false;\n  }\n  bool found = false;\n  for (int i = 0; i < g_num_file_mapping_hints; i++) {\n    if (g_file_mapping_hints[i].start <= *start &&\n        *end <= g_file_mapping_hints[i].end) {\n      // We assume that the start_address for the mapping is the base\n      // address of the ELF section, but when [start_address,end_address) is\n      // not strictly equal to [hint.start, hint.end), that assumption is\n      // invalid.\n      //\n      // This uses the hint's start address (even though hint.start is not\n      // necessarily equal to start_address) to ensure the correct\n      // relocation is computed later.\n      *start = g_file_mapping_hints[i].start;\n      *end = g_file_mapping_hints[i].end;\n      *offset = g_file_mapping_hints[i].offset;\n      *filename = g_file_mapping_hints[i].filename;\n      found = true;\n      break;\n    }\n  }\n  g_file_mapping_mu.unlock();\n  return found;\n}\n\n}  // namespace debugging_internal\n\nbool Symbolize(const void *pc, char *out, int out_size) {\n  // Symbolization is very slow under tsan.\n  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();\n  SAFE_ASSERT(out_size >= 0);\n  debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();\n  const char *name = s->GetSymbol(pc);\n  bool ok = false;\n  if (name != nullptr && out_size > 0) {\n    strncpy(out, name, static_cast<size_t>(out_size));\n    ok = true;\n    if (out[static_cast<size_t>(out_size) - 1] != '\\0') {\n      // strncpy() does not '\\0' terminate when it truncates.  Do so, with\n      // trailing ellipsis.\n      static constexpr char kEllipsis[] = \"...\";\n      size_t ellipsis_size =\n          std::min(strlen(kEllipsis), static_cast<size_t>(out_size) - 1);\n      memcpy(out + static_cast<size_t>(out_size) - ellipsis_size - 1, kEllipsis,\n             ellipsis_size);\n      out[static_cast<size_t>(out_size) - 1] = '\\0';\n    }\n  }\n  debugging_internal::FreeSymbolizer(s);\n  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();\n  return ok;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\nextern \"C\" bool AbslInternalGetFileMappingHint(const void **start,\n                                               const void **end,\n                                               uint64_t *offset,\n                                               const char **filename) {\n  return absl::debugging_internal::GetFileMappingHint(start, end, offset,\n                                                      filename);\n}\n\n#undef ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI\n"
  },
  {
    "path": "absl/debugging/symbolize_emscripten.inc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cxxabi.h>\n#include <emscripten.h>\n\n#include <algorithm>\n#include <cstring>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/debugging/internal/demangle.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nextern \"C\" {\nconst char* emscripten_pc_get_function(const void* pc);\nvoid* emscripten_stack_snapshot();\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nvoid InitializeSymbolizer(const char*) {}\n\nbool Symbolize(const void* pc, char* out, int out_size) {\n  if (pc == nullptr || out_size <= 0) {\n    return false;\n  }\n  // Need to capture a snapshot first.\n  emscripten_stack_snapshot();\n  const char* func_name = emscripten_pc_get_function(pc);\n  if (func_name == nullptr) {\n    return false;\n  }\n\n  strncpy(out, func_name, static_cast<size_t>(out_size));\n\n  if (out[out_size - 1] != '\\0') {\n    // strncpy() does not '\\0' terminate when it truncates.\n    static constexpr char kEllipsis[] = \"...\";\n    size_t ellipsis_size =\n        std::min(sizeof(kEllipsis) - 1, static_cast<size_t>(out_size) - 1);\n    memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);\n    out[out_size - 1] = '\\0';\n  }\n\n  return true;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/symbolize_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/debugging/symbolize.h\"\n#include <cstddef>\n\n#include \"absl/debugging/internal/symbolize.h\"\n#include \"absl/strings/str_format.h\"\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#ifndef _WIN32\n#include <fcntl.h>\n#include <sys/mman.h>\n#endif\n\n#include <cstring>\n#include <iostream>\n#include <memory>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/low_level_alloc.h\"\n#include \"absl/base/internal/per_thread_tls.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/cleanup/cleanup.h\"\n#include \"absl/debugging/internal/stack_consumption.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/log.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/string_view.h\"\n\n#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\nusing testing::Contains;\n\n#ifdef _WIN32\n#define ABSL_SYMBOLIZE_TEST_NOINLINE __declspec(noinline)\n#else\n#define ABSL_SYMBOLIZE_TEST_NOINLINE ABSL_ATTRIBUTE_NOINLINE\n#endif\n\n// Functions to symbolize. Use C linkage to avoid mangled names.\nextern \"C\" {\nABSL_SYMBOLIZE_TEST_NOINLINE void nonstatic_func() {\n  // The next line makes this a unique function to prevent the compiler from\n  // folding identical functions together.\n  volatile int x = __LINE__;\n  static_cast<void>(x);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\nABSL_SYMBOLIZE_TEST_NOINLINE static void static_func() {\n  // The next line makes this a unique function to prevent the compiler from\n  // folding identical functions together.\n  volatile int x = __LINE__;\n  static_cast<void>(x);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n}  // extern \"C\"\n\nstruct Foo {\n  static void func(int x);\n};\n\n// A C++ method that should have a mangled name.\nABSL_SYMBOLIZE_TEST_NOINLINE void Foo::func(int) {\n  // The next line makes this a unique function to prevent the compiler from\n  // folding identical functions together.\n  volatile int x = __LINE__;\n  static_cast<void>(x);\n  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();\n}\n\n// Create functions that will remain in different text sections in the\n// final binary when linker option \"-z,keep-text-section-prefix\" is used.\nint ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.unlikely) unlikely_func() {\n  return 0;\n}\n\nint ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.hot) hot_func() { return 0; }\n\nint ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.startup) startup_func() { return 0; }\n\nint ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.exit) exit_func() { return 0; }\n\nint /*ABSL_ATTRIBUTE_SECTION_VARIABLE(.text)*/ regular_func() { return 0; }\n\n// Thread-local data may confuse the symbolizer, ensure that it does not.\n// Variable sizes and order are important.\n#if ABSL_PER_THREAD_TLS\nstatic ABSL_PER_THREAD_TLS_KEYWORD char symbolize_test_thread_small[1];\nstatic ABSL_PER_THREAD_TLS_KEYWORD char\n    symbolize_test_thread_big[2 * 1024 * 1024];\n#endif\n\n#if !defined(__EMSCRIPTEN__)\n// Used below to hopefully inhibit some compiler/linker optimizations\n// that may remove kHpageTextPadding, kPadding0, and kPadding1 from\n// the binary.\nstatic volatile bool volatile_bool = false;\n\n// Force the binary to be large enough that a THP .text remap will succeed.\nstatic constexpr size_t kHpageSize = 1 << 21;\nconst char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(\n        .text) = \"\";\n\n#endif  // !defined(__EMSCRIPTEN__)\n\nstatic char try_symbolize_buffer[4096];\n\n// A wrapper function for absl::Symbolize() to make the unit test simple.  The\n// limit must be < sizeof(try_symbolize_buffer).  Returns null if\n// absl::Symbolize() returns false, otherwise returns try_symbolize_buffer with\n// the result of absl::Symbolize().\nstatic const char *TrySymbolizeWithLimit(void *pc, int limit) {\n  CHECK_LE(limit, sizeof(try_symbolize_buffer))\n      << \"try_symbolize_buffer is too small\";\n\n  // Use the heap to facilitate heap and buffer sanitizer tools.\n  auto heap_buffer = absl::make_unique<char[]>(sizeof(try_symbolize_buffer));\n  bool found = absl::Symbolize(pc, heap_buffer.get(), limit);\n  if (found) {\n    CHECK_LT(static_cast<int>(\n                 strnlen(heap_buffer.get(), static_cast<size_t>(limit))),\n             limit)\n        << \"absl::Symbolize() did not properly terminate the string\";\n    strncpy(try_symbolize_buffer, heap_buffer.get(),\n            sizeof(try_symbolize_buffer) - 1);\n    try_symbolize_buffer[sizeof(try_symbolize_buffer) - 1] = '\\0';\n  }\n\n  return found ? try_symbolize_buffer : nullptr;\n}\n\n// A wrapper for TrySymbolizeWithLimit(), with a large limit.\nstatic const char *TrySymbolize(void *pc) {\n  return TrySymbolizeWithLimit(pc, sizeof(try_symbolize_buffer));\n}\n\n#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) ||    \\\n    defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE) || \\\n    defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE)\n\n// Test with a return address.\nvoid ABSL_ATTRIBUTE_NOINLINE TestWithReturnAddress() {\n#if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)\n  void *return_address = __builtin_return_address(0);\n  const char *symbol = TrySymbolize(return_address);\n  ASSERT_NE(symbol, nullptr) << \"TestWithReturnAddress failed\";\n  EXPECT_STREQ(symbol, \"main\") << \"TestWithReturnAddress failed\";\n#endif\n}\n\nTEST(Symbolize, Cached) {\n  // Compilers should give us pointers to them.\n  EXPECT_STREQ(\"nonstatic_func\", TrySymbolize((void*)(&nonstatic_func)));\n  // The name of an internal linkage symbol is not specified; allow either a\n  // mangled or an unmangled name here.\n  const char* static_func_symbol = TrySymbolize((void*)(&static_func));\n  EXPECT_TRUE(strcmp(\"static_func\", static_func_symbol) == 0 ||\n              strcmp(\"static_func()\", static_func_symbol) == 0);\n\n  EXPECT_TRUE(nullptr == TrySymbolize(nullptr));\n}\n\nTEST(Symbolize, Truncation) {\n  constexpr char kNonStaticFunc[] = \"nonstatic_func\";\n  EXPECT_STREQ(\"nonstatic_func\",\n               TrySymbolizeWithLimit((void*)(&nonstatic_func),\n                                     strlen(kNonStaticFunc) + 1));\n  EXPECT_STREQ(\"nonstatic_...\",\n               TrySymbolizeWithLimit((void*)(&nonstatic_func),\n                                     strlen(kNonStaticFunc) + 0));\n  EXPECT_STREQ(\"nonstatic...\",\n               TrySymbolizeWithLimit((void*)(&nonstatic_func),\n                                     strlen(kNonStaticFunc) - 1));\n  EXPECT_STREQ(\"n...\", TrySymbolizeWithLimit((void*)(&nonstatic_func), 5));\n  EXPECT_STREQ(\"...\", TrySymbolizeWithLimit((void*)(&nonstatic_func), 4));\n  EXPECT_STREQ(\"..\", TrySymbolizeWithLimit((void*)(&nonstatic_func), 3));\n  EXPECT_STREQ(\".\", TrySymbolizeWithLimit((void*)(&nonstatic_func), 2));\n  EXPECT_STREQ(\"\", TrySymbolizeWithLimit((void*)(&nonstatic_func), 1));\n  EXPECT_EQ(nullptr, TrySymbolizeWithLimit((void*)(&nonstatic_func), 0));\n}\n\nTEST(Symbolize, SymbolizeWithDemangling) {\n  Foo::func(100);\n#ifdef __EMSCRIPTEN__\n  // Emscripten's online symbolizer is more precise with arguments.\n  EXPECT_STREQ(\"Foo::func(int)\", TrySymbolize((void*)(&Foo::func)));\n#else\n  EXPECT_STREQ(\"Foo::func()\", TrySymbolize((void*)(&Foo::func)));\n#endif\n}\n\nTEST(Symbolize, SymbolizeSplitTextSections) {\n  EXPECT_STREQ(\"unlikely_func()\", TrySymbolize((void*)(&unlikely_func)));\n  EXPECT_STREQ(\"hot_func()\", TrySymbolize((void*)(&hot_func)));\n  EXPECT_STREQ(\"startup_func()\", TrySymbolize((void*)(&startup_func)));\n  EXPECT_STREQ(\"exit_func()\", TrySymbolize((void*)(&exit_func)));\n  EXPECT_STREQ(\"regular_func()\", TrySymbolize((void*)(&regular_func)));\n}\n\n// Tests that verify that Symbolize stack footprint is within some limit.\n#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n\nstatic void *g_pc_to_symbolize;\nstatic char g_symbolize_buffer[4096];\nstatic char *g_symbolize_result;\n\nstatic void SymbolizeSignalHandler(int signo) {\n  if (absl::Symbolize(g_pc_to_symbolize, g_symbolize_buffer,\n                      sizeof(g_symbolize_buffer))) {\n    g_symbolize_result = g_symbolize_buffer;\n  } else {\n    g_symbolize_result = nullptr;\n  }\n}\n\n// Call Symbolize and figure out the stack footprint of this call.\nstatic const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {\n  g_pc_to_symbolize = pc;\n  *stack_consumed = absl::debugging_internal::GetSignalHandlerStackConsumption(\n      SymbolizeSignalHandler);\n  return g_symbolize_result;\n}\n\nstatic int GetStackConsumptionUpperLimit() {\n  // Symbolize stack consumption should be within 2kB.\n  int stack_consumption_upper_limit = 2048;\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)\n  // Account for sanitizer instrumentation requiring additional stack space.\n  stack_consumption_upper_limit *= 5;\n#endif\n  return stack_consumption_upper_limit;\n}\n\nTEST(Symbolize, SymbolizeStackConsumption) {\n  int stack_consumed = 0;\n\n  const char *symbol =\n      SymbolizeStackConsumption((void *)(&nonstatic_func), &stack_consumed);\n  EXPECT_STREQ(\"nonstatic_func\", symbol);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());\n\n  // The name of an internal linkage symbol is not specified; allow either a\n  // mangled or an unmangled name here.\n  symbol = SymbolizeStackConsumption((void *)(&static_func), &stack_consumed);\n  EXPECT_TRUE(strcmp(\"static_func\", symbol) == 0 ||\n              strcmp(\"static_func()\", symbol) == 0);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());\n}\n\nTEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {\n  Foo::func(100);\n  int stack_consumed = 0;\n\n  const char *symbol =\n      SymbolizeStackConsumption((void *)(&Foo::func), &stack_consumed);\n\n  EXPECT_STREQ(\"Foo::func()\", symbol);\n  EXPECT_GT(stack_consumed, 0);\n  EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());\n}\n\n#endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION\n\n#if !defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE) && \\\n    !defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE)\n// Use a 64K page size for PPC.\nconst size_t kPageSize = 64 << 10;\n// We place a read-only symbols into the .text section and verify that we can\n// symbolize them and other symbols after remapping them.\nconst char kPadding0[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = \"\";\nconst char kPadding1[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = \"\";\n\nstatic int FilterElfHeader(struct dl_phdr_info *info, size_t size, void *data) {\n  for (int i = 0; i < info->dlpi_phnum; i++) {\n    if (info->dlpi_phdr[i].p_type == PT_LOAD &&\n        info->dlpi_phdr[i].p_flags == (PF_R | PF_X)) {\n      const void *const vaddr =\n          absl::bit_cast<void *>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);\n      const auto segsize = info->dlpi_phdr[i].p_memsz;\n\n      const char *self_exe;\n      if (info->dlpi_name != nullptr && info->dlpi_name[0] != '\\0') {\n        self_exe = info->dlpi_name;\n      } else {\n        self_exe = \"/proc/self/exe\";\n      }\n\n      absl::debugging_internal::RegisterFileMappingHint(\n          vaddr, reinterpret_cast<const char *>(vaddr) + segsize,\n          info->dlpi_phdr[i].p_offset, self_exe);\n\n      return 1;\n    }\n  }\n\n  return 1;\n}\n\nTEST(Symbolize, SymbolizeWithMultipleMaps) {\n  // Force kPadding0 and kPadding1 to be linked in.\n  if (volatile_bool) {\n    LOG(INFO) << kPadding0;\n    LOG(INFO) << kPadding1;\n  }\n\n  // Verify we can symbolize everything.\n  char buf[512];\n  memset(buf, 0, sizeof(buf));\n  absl::Symbolize(kPadding0, buf, sizeof(buf));\n  EXPECT_STREQ(\"kPadding0\", buf);\n\n  memset(buf, 0, sizeof(buf));\n  absl::Symbolize(kPadding1, buf, sizeof(buf));\n  EXPECT_STREQ(\"kPadding1\", buf);\n\n  // Specify a hint for the executable segment.\n  dl_iterate_phdr(FilterElfHeader, nullptr);\n\n  // Reload at least one page out of kPadding0, kPadding1\n  const char *ptrs[] = {kPadding0, kPadding1};\n\n  for (const char *ptr : ptrs) {\n    const int kMapFlags = MAP_ANONYMOUS | MAP_PRIVATE;\n    void *addr = mmap(nullptr, kPageSize, PROT_READ, kMapFlags, 0, 0);\n    ASSERT_NE(addr, MAP_FAILED);\n\n    // kPadding[0-1] is full of zeroes, so we can remap anywhere within it, but\n    // we ensure there is at least a full page of padding.\n    void *remapped = reinterpret_cast<void *>(\n        reinterpret_cast<uintptr_t>(ptr + kPageSize) & ~(kPageSize - 1ULL));\n\n    const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED);\n    void *ret = mremap(addr, kPageSize, kPageSize, kMremapFlags, remapped);\n    ASSERT_NE(ret, MAP_FAILED);\n  }\n\n  // Invalidate the symbolization cache so we are forced to rely on the hint.\n  absl::Symbolize(nullptr, buf, sizeof(buf));\n\n  // Verify we can still symbolize.\n  const char *expected[] = {\"kPadding0\", \"kPadding1\"};\n  const size_t offsets[] = {0, kPageSize, 2 * kPageSize, 3 * kPageSize};\n\n  for (int i = 0; i < 2; i++) {\n    for (size_t offset : offsets) {\n      memset(buf, 0, sizeof(buf));\n      absl::Symbolize(ptrs[i] + offset, buf, sizeof(buf));\n      EXPECT_STREQ(expected[i], buf);\n    }\n  }\n}\n\ntemplate <char C>\nclass TestSymbolDecorator final\n    : public absl::debugging_internal::SymbolDecorator {\n public:\n  static absl::debugging_internal::SymbolDecoratorPtr Factory(int /*fd*/) {\n    void* ptr = absl::base_internal::LowLevelAlloc::AllocWithArena(\n        sizeof(TestSymbolDecorator), absl::base_internal::SigSafeArena());\n    return absl::debugging_internal::SymbolDecoratorPtr(\n        new (ptr) TestSymbolDecorator());\n  }\n\n  void Decorate(const void* /*pc*/, ptrdiff_t /*relocation*/, char* symbol_buf,\n                size_t symbol_buf_size, char* /*tmp_buf*/,\n                size_t /*tmp_buf_size*/) const override {\n    const size_t len = strlen(symbol_buf);\n    absl::SNPrintF(symbol_buf + len, symbol_buf_size - len, \" hello %c\", C);\n  }\n};\n\nTEST(Symbolize, SetSymbolDecorator) {\n  absl::Cleanup cleanup =\n      [old_decorator = absl::debugging_internal::SetSymbolDecoratorFactory(\n           &TestSymbolDecorator<'a'>::Factory)] {\n        absl::debugging_internal::SetSymbolDecoratorFactory(old_decorator);\n      };\n\n  EXPECT_STREQ(\"nonstatic_func hello a\",\n               TrySymbolize(reinterpret_cast<void*>(&nonstatic_func)));\n\n  EXPECT_EQ(absl::debugging_internal::SetSymbolDecoratorFactory(\n                &TestSymbolDecorator<'b'>::Factory),\n            &TestSymbolDecorator<'a'>::Factory);\n\n  EXPECT_STREQ(\"nonstatic_func hello b\",\n               TrySymbolize(reinterpret_cast<void*>(&nonstatic_func)));\n}\n\n// Some versions of Clang with optimizations enabled seem to be able\n// to optimize away the .data section if no variables live in the\n// section. This variable should get placed in the .data section, and\n// the test below checks for the existence of a .data section.\nstatic int in_data_section = 1;\n\nTEST(Symbolize, ForEachSection) {\n  int fd = TEMP_FAILURE_RETRY(open(\"/proc/self/exe\", O_RDONLY));\n  ASSERT_NE(fd, -1);\n\n  std::vector<std::string> sections;\n  ASSERT_TRUE(absl::debugging_internal::ForEachSection(\n      fd, [&sections](const absl::string_view name, const ElfW(Shdr) &) {\n        sections.emplace_back(name);\n        return true;\n      }));\n\n  // Check for the presence of common section names.\n  EXPECT_THAT(sections, Contains(\".text\"));\n  EXPECT_THAT(sections, Contains(\".rodata\"));\n  EXPECT_THAT(sections, Contains(\".bss\"));\n  ++in_data_section;\n  EXPECT_THAT(sections, Contains(\".data\"));\n\n  close(fd);\n}\n#endif  // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE &&\n        // !ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE\n\n// x86 specific tests.  Uses some inline assembler.\nextern \"C\" {\ninline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {\n  void *pc = nullptr;\n#if defined(__i386__)\n  __asm__ __volatile__(\"call 1f;\\n 1: pop %[PC]\" : [PC] \"=r\"(pc));\n#elif defined(__x86_64__)\n  __asm__ __volatile__(\"leaq 0(%%rip),%[PC];\\n\" : [PC] \"=r\"(pc));\n#endif\n  return pc;\n}\n\nvoid *ABSL_ATTRIBUTE_NOINLINE non_inline_func() {\n  void *pc = nullptr;\n#if defined(__i386__)\n  __asm__ __volatile__(\"call 1f;\\n 1: pop %[PC]\" : [PC] \"=r\"(pc));\n#elif defined(__x86_64__)\n  __asm__ __volatile__(\"leaq 0(%%rip),%[PC];\\n\" : [PC] \"=r\"(pc));\n#endif\n  return pc;\n}\n\nvoid ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() {\n#if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) && \\\n    (defined(__i386__) || defined(__x86_64__))\n  void *pc = non_inline_func();\n  const char *symbol = TrySymbolize(pc);\n  ASSERT_NE(symbol, nullptr) << \"TestWithPCInsideNonInlineFunction failed\";\n  EXPECT_STREQ(symbol, \"non_inline_func\")\n      << \"TestWithPCInsideNonInlineFunction failed\";\n#endif\n}\n\nvoid ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() {\n#if defined(ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE) && \\\n    (defined(__i386__) || defined(__x86_64__))\n  void *pc = inline_func();  // Must be inlined.\n  const char *symbol = TrySymbolize(pc);\n  ASSERT_NE(symbol, nullptr) << \"TestWithPCInsideInlineFunction failed\";\n  EXPECT_STREQ(symbol, __FUNCTION__) << \"TestWithPCInsideInlineFunction failed\";\n#endif\n}\n}\n\n#if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && \\\n    ((__ARM_ARCH >= 7) || !defined(__ARM_PCS_VFP))\n// Test that we correctly identify bounds of Thumb functions on ARM.\n//\n// Thumb functions have the lowest-order bit set in their addresses in the ELF\n// symbol table. This requires some extra logic to properly compute function\n// bounds. To test this logic, nudge a Thumb function right up against an ARM\n// function and try to symbolize the ARM function.\n//\n// A naive implementation will simply use the Thumb function's entry point as\n// written in the symbol table and will therefore treat the Thumb function as\n// extending one byte further in the instruction stream than it actually does.\n// When asked to symbolize the start of the ARM function, it will identify an\n// overlap between the Thumb and ARM functions, and it will return the name of\n// the Thumb function.\n//\n// A correct implementation, on the other hand, will null out the lowest-order\n// bit in the Thumb function's entry point. It will correctly compute the end of\n// the Thumb function, it will find no overlap between the Thumb and ARM\n// functions, and it will return the name of the ARM function.\n//\n// Unfortunately we cannot perform this test on armv6 or lower systems that use\n// the hard float ABI because gcc refuses to compile thumb functions on such\n// systems with a \"sorry, unimplemented: Thumb-1 hard-float VFP ABI\" error.\n\n__attribute__((target(\"thumb\"))) int ArmThumbOverlapThumb(int x) {\n  return x * x * x;\n}\n\n__attribute__((target(\"arm\"))) int ArmThumbOverlapArm(int x) {\n  return x * x * x;\n}\n\nvoid ABSL_ATTRIBUTE_NOINLINE TestArmThumbOverlap() {\n#if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)\n  const char *symbol = TrySymbolize((void *)&ArmThumbOverlapArm);\n  ASSERT_NE(symbol, nullptr) << \"TestArmThumbOverlap failed\";\n  EXPECT_STREQ(\"ArmThumbOverlapArm()\", symbol) << \"TestArmThumbOverlap failed\";\n#endif\n}\n\n#endif  // defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && ((__ARM_ARCH >= 7)\n        // || !defined(__ARM_PCS_VFP))\n\n#elif defined(_WIN32)\n#if !defined(ABSL_CONSUME_DLL)\n\nTEST(Symbolize, Basics) {\n  EXPECT_STREQ(\"nonstatic_func\", TrySymbolize((void *)(&nonstatic_func)));\n\n  // The name of an internal linkage symbol is not specified; allow either a\n  // mangled or an unmangled name here.\n  const char *static_func_symbol = TrySymbolize((void *)(&static_func));\n  ASSERT_TRUE(static_func_symbol != nullptr);\n  EXPECT_TRUE(strstr(static_func_symbol, \"static_func\") != nullptr);\n\n  EXPECT_TRUE(nullptr == TrySymbolize(nullptr));\n}\n\nTEST(Symbolize, Truncation) {\n  constexpr char kNonStaticFunc[] = \"nonstatic_func\";\n  EXPECT_STREQ(\"nonstatic_func\",\n               TrySymbolizeWithLimit((void *)(&nonstatic_func),\n                                     strlen(kNonStaticFunc) + 1));\n  EXPECT_STREQ(\"nonstatic_...\",\n               TrySymbolizeWithLimit((void *)(&nonstatic_func),\n                                     strlen(kNonStaticFunc) + 0));\n  EXPECT_STREQ(\"nonstatic...\",\n               TrySymbolizeWithLimit((void *)(&nonstatic_func),\n                                     strlen(kNonStaticFunc) - 1));\n  EXPECT_STREQ(\"n...\", TrySymbolizeWithLimit((void *)(&nonstatic_func), 5));\n  EXPECT_STREQ(\"...\", TrySymbolizeWithLimit((void *)(&nonstatic_func), 4));\n  EXPECT_STREQ(\"..\", TrySymbolizeWithLimit((void *)(&nonstatic_func), 3));\n  EXPECT_STREQ(\".\", TrySymbolizeWithLimit((void *)(&nonstatic_func), 2));\n  EXPECT_STREQ(\"\", TrySymbolizeWithLimit((void *)(&nonstatic_func), 1));\n  EXPECT_EQ(nullptr, TrySymbolizeWithLimit((void *)(&nonstatic_func), 0));\n}\n\nTEST(Symbolize, SymbolizeWithDemangling) {\n  const char *result = TrySymbolize((void *)(&Foo::func));\n  ASSERT_TRUE(result != nullptr);\n  EXPECT_TRUE(strstr(result, \"Foo::func\") != nullptr) << result;\n}\n\n#endif  // !defined(ABSL_CONSUME_DLL)\n#else   // Symbolizer unimplemented\nTEST(Symbolize, Unimplemented) {\n  char buf[64];\n  EXPECT_FALSE(absl::Symbolize((void *)(&nonstatic_func), buf, sizeof(buf)));\n  EXPECT_FALSE(absl::Symbolize((void *)(&static_func), buf, sizeof(buf)));\n  EXPECT_FALSE(absl::Symbolize((void *)(&Foo::func), buf, sizeof(buf)));\n}\n\n#endif\n\nint main(int argc, char **argv) {\n#if !defined(__EMSCRIPTEN__)\n  // Make sure kHpageTextPadding is linked into the binary.\n  if (volatile_bool) {\n    LOG(INFO) << kHpageTextPadding;\n  }\n#endif  // !defined(__EMSCRIPTEN__)\n\n#if ABSL_PER_THREAD_TLS\n  // Touch the per-thread variables.\n  symbolize_test_thread_small[0] = 0;\n  symbolize_test_thread_big[0] = 0;\n#endif\n\n  absl::InitializeSymbolizer(argv[0]);\n  testing::InitGoogleTest(&argc, argv);\n\n#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) ||        \\\n    defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE) || \\\n    defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)\n  TestWithPCInsideInlineFunction();\n  TestWithPCInsideNonInlineFunction();\n  TestWithReturnAddress();\n#if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && \\\n    ((__ARM_ARCH >= 7) || !defined(__ARM_PCS_VFP))\n  TestArmThumbOverlap();\n#endif\n#endif\n\n#if !defined(__EMSCRIPTEN__)\n  // All of these test cases rely on symbolizing function pointers.\n  // On most platforms, function pointers directly map to PC.\n  // In WebAssembly, function pointers are indices into the function table\n  // and there is no longer a mapping from function index back into the\n  // file offset for symbolization.\n  return RUN_ALL_TESTS();\n#endif  // !defined(__EMSCRIPTEN__)\n}\n"
  },
  {
    "path": "absl/debugging/symbolize_unimplemented.inc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n\n#include \"absl/debugging/internal/symbolize.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace debugging_internal {\n\nSymbolDecorator::Factory* SetSymbolDecoratorFactory(SymbolDecorator::Factory*) {\n  return nullptr;\n}\nbool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) {\n  return false;\n}\nbool GetFileMappingHint(const void **, const void **, uint64_t *, const char **) {\n  return false;\n}\n\n}  // namespace debugging_internal\n\nvoid InitializeSymbolizer(const char*) {}\nbool Symbolize(const void *, char *, int) { return false; }\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/debugging/symbolize_win32.inc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// See \"Retrieving Symbol Information by Address\":\n// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx\n\n#include <windows.h>\n#include <winternl.h>\n\n// MSVC header dbghelp.h has a warning for an ignored typedef.\n#pragma warning(push)\n#pragma warning(disable:4091)\n#include <dbghelp.h>\n#pragma warning(pop)\n\n#pragma comment(lib, \"dbghelp.lib\")\n\n#include <algorithm>\n#include <cstring>\n\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nstatic HANDLE process = NULL;\n\nvoid InitializeSymbolizer(const char*) {\n  if (process != nullptr) {\n    return;\n  }\n  process = GetCurrentProcess();\n\n  // Symbols are not loaded until a reference is made requiring the\n  // symbols be loaded. This is the fastest, most efficient way to use\n  // the symbol handler.\n  SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);\n  DWORD syminitialize_error;\n  constexpr int kSymInitializeRetries = 5;\n  for (int i = 0; i < kSymInitializeRetries; ++i) {\n    if (SymInitialize(process, nullptr, true)) {\n      return;\n    }\n\n    // SymInitialize can fail sometimes with a STATUS_INFO_LENGTH_MISMATCH\n    // NTSTATUS (0xC0000004), which can happen when a module load occurs during\n    // the SymInitialize call. In this case, we should try calling SymInitialize\n    // again.\n    constexpr DWORD kStatusInfoLengthMismatch = DWORD{0xC0000004};\n    syminitialize_error = GetLastError();\n    if (syminitialize_error != kStatusInfoLengthMismatch) {\n      break;\n    }\n  }\n\n  // GetLastError() returns a Win32 DWORD, but we assign to\n  // unsigned long long to simplify the ABSL_RAW_LOG case below.  The uniform\n  // initialization guarantees this is not a narrowing conversion.\n  const unsigned long long error{syminitialize_error};\n  ABSL_RAW_LOG(FATAL, \"SymInitialize() failed: %llu\", error);\n}\n\nbool Symbolize(const void* pc, char* out, int out_size) {\n  if (out_size <= 0) {\n    return false;\n  }\n  alignas(SYMBOL_INFO) char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];\n  SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buf);\n  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);\n  symbol->MaxNameLen = MAX_SYM_NAME;\n  if (!SymFromAddr(process, reinterpret_cast<DWORD64>(pc), nullptr, symbol)) {\n    return false;\n  }\n  const size_t out_size_t = static_cast<size_t>(out_size);\n  strncpy(out, symbol->Name, out_size_t);\n  if (out[out_size_t - 1] != '\\0') {\n    // strncpy() does not '\\0' terminate when it truncates.\n    static constexpr char kEllipsis[] = \"...\";\n    size_t ellipsis_size =\n        std::min(sizeof(kEllipsis) - 1, out_size_t - 1);\n    memcpy(out + out_size_t - ellipsis_size - 1, kEllipsis, ellipsis_size);\n    out[out_size_t - 1] = '\\0';\n  }\n  return true;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"path_util\",\n    hdrs = [\n        \"internal/path_util.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/flags:__pkg__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"program_name\",\n    srcs = [\n        \"internal/program_name.cc\",\n    ],\n    hdrs = [\n        \"internal/program_name.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/flags:__pkg__\",\n        \"//absl/log:__pkg__\",\n    ],\n    deps = [\n        \":path_util\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"config\",\n    srcs = [\n        \"usage_config.cc\",\n    ],\n    hdrs = [\n        \"config.h\",\n        \"usage_config.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":path_util\",\n        \":program_name\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"marshalling\",\n    srcs = [\n        \"marshalling.cc\",\n    ],\n    hdrs = [\n        \"marshalling.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/numeric:int128\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:optional\",\n    ],\n)\n\ncc_library(\n    name = \"commandlineflag_internal\",\n    srcs = [\n        \"internal/commandlineflag.cc\",\n    ],\n    hdrs = [\n        \"internal/commandlineflag.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:fast_type_id\",\n    ],\n)\n\ncc_library(\n    name = \"commandlineflag\",\n    srcs = [\n        \"commandlineflag.cc\",\n    ],\n    hdrs = [\n        \"commandlineflag.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":commandlineflag_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/base:nullability\",\n        \"//absl/strings\",\n        \"//absl/types:optional\",\n    ],\n)\n\ncc_library(\n    name = \"private_handle_accessor\",\n    srcs = [\n        \"internal/private_handle_accessor.cc\",\n    ],\n    hdrs = [\n        \"internal/private_handle_accessor.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/flags:__pkg__\",\n        \"//absl/flags/rust:__pkg__\",\n    ],\n    deps = [\n        \":commandlineflag\",\n        \":commandlineflag_internal\",\n        \"//absl/base:config\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"reflection\",\n    srcs = [\n        \"reflection.cc\",\n    ],\n    hdrs = [\n        \"internal/registry.h\",\n        \"reflection.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":commandlineflag\",\n        \":commandlineflag_internal\",\n        \":config\",\n        \":private_handle_accessor\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/base:no_destructor\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"flag_internal\",\n    srcs = [\n        \"internal/flag.cc\",\n    ],\n    hdrs = [\n        \"internal/flag.h\",\n        \"internal/sequence_lock.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//absl/base:__subpackages__\"],\n    deps = [\n        \":commandlineflag\",\n        \":commandlineflag_internal\",\n        \":config\",\n        \":marshalling\",\n        \":reflection\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/base:no_destructor\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"flag\",\n    hdrs = [\n        \"declare.h\",\n        \"flag.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":commandlineflag\",\n        \":config\",\n        \":flag_internal\",\n        \":reflection\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"usage_internal\",\n    srcs = [\n        \"internal/usage.cc\",\n    ],\n    hdrs = [\n        \"internal/usage.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/flags:__pkg__\",\n    ],\n    deps = [\n        \":commandlineflag\",\n        \":config\",\n        \":flag\",\n        \":flag_internal\",\n        \":path_util\",\n        \":private_handle_accessor\",\n        \":program_name\",\n        \":reflection\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"usage\",\n    srcs = [\n        \"usage.cc\",\n    ],\n    hdrs = [\n        \"usage.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":usage_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"parse\",\n    srcs = [\"parse.cc\"],\n    hdrs = [\n        \"internal/parse.h\",\n        \"parse.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":commandlineflag\",\n        \":commandlineflag_internal\",\n        \":config\",\n        \":flag\",\n        \":flag_internal\",\n        \":private_handle_accessor\",\n        \":program_name\",\n        \":reflection\",\n        \":usage\",\n        \":usage_internal\",\n        \"//absl/algorithm:container\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\n############################################################################\n# Unit tests in alphabetical order.\n\ncc_test(\n    name = \"commandlineflag_test\",\n    size = \"small\",\n    srcs = [\n        \"commandlineflag_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:android\",\n        \"no_test:os:ios\",\n        \"no_test_android\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":commandlineflag\",\n        \":config\",\n        \":flag\",\n        \":private_handle_accessor\",\n        \":reflection\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"config_test\",\n    size = \"small\",\n    srcs = [\n        \"config_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"flag_test\",\n    size = \"small\",\n    srcs = [\n        \"flag_test.cc\",\n        \"flag_test_defs.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:android\",\n        \"no_test:os:ios\",\n        \"no_test_android\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":config\",\n        \":flag\",\n        \":flag_internal\",\n        \":marshalling\",\n        \":parse\",\n        \":reflection\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:malloc_internal\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/numeric:int128\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"flag_benchmark\",\n    testonly = True,\n    srcs = [\n        \"flag_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = select({\n        \"//conditions:default\": [],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \"flag_benchmark.lds\",\n        \":flag\",\n        \":marshalling\",\n        \":parse\",\n        \":reflection\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"marshalling_test\",\n    size = \"small\",\n    srcs = [\n        \"marshalling_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":marshalling\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"parse_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\n        \"parse_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:android\",\n        \"no_test:os:ios\",\n        \"no_test_android\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":config\",\n        \":flag\",\n        \":parse\",\n        \":reflection\",\n        \":usage_internal\",\n        \"//absl/base:scoped_set_env\",\n        \"//absl/log\",\n        \"//absl/strings\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"path_util_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/path_util_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":path_util\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"program_name_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/program_name_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_fuchsia_x64\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":program_name\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"reflection_test\",\n    size = \"small\",\n    srcs = [\n        \"reflection_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:android\",\n        \"no_test:os:ios\",\n        \"no_test_android\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":config\",\n        \":flag\",\n        \":reflection\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"sequence_lock_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\n        \"internal/sequence_lock_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    shard_count = 31,\n    tags = [\"no_test_wasm\"],\n    deps = [\n        \":flag_internal\",\n        \"//absl/base\",\n        \"//absl/container:fixed_array\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"usage_config_test\",\n    size = \"small\",\n    srcs = [\n        \"usage_config_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":config\",\n        \":path_util\",\n        \":program_name\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"usage_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/usage_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:android\",\n        \"no_test:os:ios\",\n        \"no_test_android\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":config\",\n        \":flag\",\n        \":parse\",\n        \":path_util\",\n        \":program_name\",\n        \":reflection\",\n        \":usage\",\n        \":usage_internal\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n    ],\n)\n"
  },
  {
    "path": "absl/flags/CMakeLists.txt",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    flags_path_util\n  HDRS\n    \"internal/path_util.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::strings\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    flags_program_name\n  SRCS\n    \"internal/program_name.cc\"\n  HDRS\n    \"internal/program_name.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::no_destructor\n    absl::flags_path_util\n    absl::strings\n    absl::synchronization\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    flags_config\n  SRCS\n    \"usage_config.cc\"\n  HDRS\n    \"config.h\"\n    \"usage_config.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::flags_path_util\n    absl::flags_program_name\n    absl::core_headers\n    absl::no_destructor\n    absl::strings\n    absl::synchronization\n)\n\nabsl_cc_library(\n  NAME\n    flags_marshalling\n  SRCS\n    \"marshalling.cc\"\n  HDRS\n    \"marshalling.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_severity\n    absl::int128\n    absl::optional\n    absl::strings\n    absl::str_format\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    flags_commandlineflag_internal\n  SRCS\n    \"internal/commandlineflag.cc\"\n  HDRS\n    \"internal/commandlineflag.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::dynamic_annotations\n    absl::fast_type_id\n)\n\nabsl_cc_library(\n  NAME\n    flags_commandlineflag\n  SRCS\n    \"commandlineflag.cc\"\n  HDRS\n    \"commandlineflag.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::fast_type_id\n    absl::flags_commandlineflag_internal\n    absl::nullability\n    absl::optional\n    absl::strings\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    flags_private_handle_accessor\n  SRCS\n    \"internal/private_handle_accessor.cc\"\n  HDRS\n    \"internal/private_handle_accessor.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::flags_commandlineflag\n    absl::flags_commandlineflag_internal\n    absl::strings\n)\n\nabsl_cc_library(\n  NAME\n    flags_reflection\n  SRCS\n    \"reflection.cc\"\n  HDRS\n    \"reflection.h\"\n    \"internal/registry.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::fast_type_id\n    absl::flags_commandlineflag\n    absl::flags_private_handle_accessor\n    absl::flags_config\n    absl::strings\n    absl::synchronization\n    absl::flat_hash_map\n    absl::no_destructor\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    flags_internal\n  SRCS\n    \"internal/flag.cc\"\n  HDRS\n    \"internal/flag.h\"\n    \"internal/sequence_lock.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::fast_type_id\n    absl::flags_commandlineflag\n    absl::flags_commandlineflag_internal\n    absl::flags_config\n    absl::flags_marshalling\n    absl::no_destructor\n    absl::synchronization\n    absl::meta\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    flags\n  HDRS\n    \"declare.h\"\n    \"flag.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::flags_commandlineflag\n    absl::flags_config\n    absl::flags_internal\n    absl::flags_reflection\n    absl::core_headers\n    absl::nullability\n    absl::strings\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    flags_usage_internal\n  SRCS\n    \"internal/usage.cc\"\n  HDRS\n    \"internal/usage.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::flags_config\n    absl::flags\n    absl::flags_commandlineflag\n    absl::flags_internal\n    absl::flags_path_util\n    absl::flags_private_handle_accessor\n    absl::flags_program_name\n    absl::flags_reflection\n    absl::strings\n    absl::synchronization\n)\n\nabsl_cc_library(\n  NAME\n    flags_usage\n  SRCS\n    \"usage.cc\"\n  HDRS\n    \"usage.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::flags_usage_internal\n    absl::no_destructor\n    absl::raw_logging_internal\n    absl::strings\n    absl::synchronization\n)\n\nabsl_cc_library(\n  NAME\n    flags_parse\n  SRCS\n    \"parse.cc\"\n  HDRS\n    \"internal/parse.h\"\n    \"parse.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::algorithm_container\n    absl::config\n    absl::core_headers\n    absl::flags_config\n    absl::flags\n    absl::flags_commandlineflag\n    absl::flags_commandlineflag_internal\n    absl::flags_internal\n    absl::flags_private_handle_accessor\n    absl::flags_program_name\n    absl::flags_reflection\n    absl::flags_usage\n    absl::no_destructor\n    absl::strings\n    absl::synchronization\n)\n\n############################################################################\n# Unit tests in alphabetical order.\n\nabsl_cc_test(\n  NAME\n    flags_commandlineflag_test\n  SRCS\n    \"commandlineflag_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags\n    absl::flags_commandlineflag\n    absl::flags_config\n    absl::flags_private_handle_accessor\n    absl::flags_reflection\n    absl::memory\n    absl::strings\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_config_test\n  SRCS\n    \"config_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags_config\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_flag_test\n  SRCS\n    \"flag_test.cc\"\n    \"flag_test_defs.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::core_headers\n    absl::flags\n    absl::flags_config\n    absl::flags_internal\n    absl::flags_marshalling\n    absl::flags_parse\n    absl::flags_reflection\n    absl::int128\n    absl::raw_logging_internal\n    absl::strings\n    absl::time\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_marshalling_test\n  SRCS\n    \"marshalling_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags_marshalling\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_parse_test\n  SRCS\n    \"parse_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags\n    absl::flags_config\n    absl::flags_parse\n    absl::flags_reflection\n    absl::flags_usage_internal\n    absl::log\n    absl::scoped_set_env\n    absl::span\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_path_util_test\n  SRCS\n    \"internal/path_util_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags_path_util\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_program_name_test\n  SRCS\n    \"internal/program_name_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags_program_name\n    absl::strings\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_reflection_test\n  SRCS\n    \"reflection_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags\n    absl::flags_config\n    absl::flags_reflection\n    absl::flags_usage\n    absl::memory\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_sequence_lock_test\n  SRCS\n    \"internal/sequence_lock_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::flags_internal\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_usage_config_test\n  SRCS\n    \"usage_config_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags_config\n    absl::flags_path_util\n    absl::flags_program_name\n    absl::strings\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    flags_usage_test\n  SRCS\n    \"internal/usage_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags_config\n    absl::flags\n    absl::flags_path_util\n    absl::flags_program_name\n    absl::flags_parse\n    absl::flags_reflection\n    absl::flags_usage\n    absl::strings\n    GTest::gmock\n)\n"
  },
  {
    "path": "absl/flags/commandlineflag.cc",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/commandlineflag.h\"\n\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nabsl::string_view CommandLineFlag::TypeName() const { return \"\"; }\nbool CommandLineFlag::IsRetired() const { return false; }\nbool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {\n  return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,\n                   flags_internal::kProgrammaticChange, *error);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/commandlineflag.h",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: commandlineflag.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the `CommandLineFlag`, which acts as a type-erased\n// handle for accessing metadata about the Abseil Flag in question.\n//\n// Because an actual Abseil flag is of an unspecified type, you should not\n// manipulate or interact directly with objects of that type. Instead, use the\n// CommandLineFlag type as an intermediary.\n#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_\n#define ABSL_FLAGS_COMMANDLINEFLAG_H_\n\n#include <memory>\n#include <optional>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\nclass PrivateHandleAccessor;\n}  // namespace flags_internal\n\n// CommandLineFlag\n//\n// This type acts as a type-erased handle for an instance of an Abseil Flag and\n// holds reflection information pertaining to that flag. Use CommandLineFlag to\n// access a flag's name, location, help string etc.\n//\n// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`\n// passing it the flag name string.\n//\n// Example:\n//\n//   // Obtain reflection handle for a flag named \"flagname\".\n//   const absl::CommandLineFlag* my_flag_data =\n//        absl::FindCommandLineFlag(\"flagname\");\n//\n//   // Now you can get flag info from that reflection handle.\n//   std::string flag_location = my_flag_data->Filename();\n//   ...\n\n// These are only used as constexpr global objects.\n// They do not use a virtual destructor to simplify their implementation.\n// They are not destroyed except at program exit, so leaks do not matter.\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wnon-virtual-dtor\"\n#endif\nclass CommandLineFlag {\n public:\n  constexpr CommandLineFlag() = default;\n\n  // Not copyable/assignable.\n  CommandLineFlag(const CommandLineFlag&) = delete;\n  CommandLineFlag& operator=(const CommandLineFlag&) = delete;\n\n  // absl::CommandLineFlag::IsOfType()\n  //\n  // Return true iff flag has type T.\n  template <typename T>\n  inline bool IsOfType() const {\n    return TypeId() == FastTypeId<T>();\n  }\n\n  // absl::CommandLineFlag::TryGet()\n  //\n  // Attempts to retrieve the flag value. Returns value on success,\n  // std::nullopt otherwise.\n  template <typename T>\n  std::optional<T> TryGet() const {\n    if (IsRetired() || !IsOfType<T>()) {\n      return std::nullopt;\n    }\n\n    // Implementation notes:\n    //\n    // We are wrapping a union around the value of `T` to serve three purposes:\n    //\n    //  1. `U.value` has correct size and alignment for a value of type `T`\n    //  2. The `U.value` constructor is not invoked since U's constructor does\n    //     not do it explicitly.\n    //  3. The `U.value` destructor is invoked since U's destructor does it\n    //     explicitly. This makes `U` a kind of RAII wrapper around non default\n    //     constructible value of T, which is destructed when we leave the\n    //     scope. We do need to destroy U.value, which is constructed by\n    //     CommandLineFlag::Read even though we left it in a moved-from state\n    //     after std::move.\n    //\n    // All of this serves to avoid requiring `T` being default constructible.\n    union U {\n      T value;\n      U() {}\n      ~U() { value.~T(); }\n    };\n    U u;\n\n    Read(&u.value);\n    // allow retired flags to be \"read\", so we can report invalid access.\n    if (IsRetired()) {\n      return std::nullopt;\n    }\n    return std::move(u.value);\n  }\n\n  // absl::CommandLineFlag::Name()\n  //\n  // Returns name of this flag.\n  virtual absl::string_view Name() const = 0;\n\n  // absl::CommandLineFlag::Filename()\n  //\n  // Returns name of the file where this flag is defined.\n  virtual std::string Filename() const = 0;\n\n  // absl::CommandLineFlag::Help()\n  //\n  // Returns help message associated with this flag.\n  virtual std::string Help() const = 0;\n\n  // absl::CommandLineFlag::IsRetired()\n  //\n  // Returns true iff this object corresponds to retired flag.\n  virtual bool IsRetired() const;\n\n  // absl::CommandLineFlag::DefaultValue()\n  //\n  // Returns the default value for this flag.\n  virtual std::string DefaultValue() const = 0;\n\n  // absl::CommandLineFlag::CurrentValue()\n  //\n  // Returns the current value for this flag.\n  virtual std::string CurrentValue() const = 0;\n\n  // absl::CommandLineFlag::ParseFrom()\n  //\n  // Sets the value of the flag based on specified string `value`. If the flag\n  // was successfully set to new value, it returns true. Otherwise, sets `error`\n  // to indicate the error, leaves the flag unchanged, and returns false.\n  bool ParseFrom(absl::string_view value, std::string* absl_nonnull error);\n\n protected:\n  ~CommandLineFlag() = default;\n\n private:\n  friend class flags_internal::PrivateHandleAccessor;\n\n  // Sets the value of the flag based on specified string `value`. If the flag\n  // was successfully set to new value, it returns true. Otherwise, sets `error`\n  // to indicate the error, leaves the flag unchanged, and returns false. There\n  // are three ways to set the flag's value:\n  //  * Update the current flag value\n  //  * Update the flag's default value\n  //  * Update the current flag value if it was never set before\n  // The mode is selected based on `set_mode` parameter.\n  virtual bool ParseFrom(absl::string_view value,\n                         flags_internal::FlagSettingMode set_mode,\n                         flags_internal::ValueSource source,\n                         std::string& error) = 0;\n\n  // Returns id of the flag's value type.\n  virtual flags_internal::FlagFastTypeId TypeId() const = 0;\n\n  // Interface to save flag to some persistent state. Returns current flag state\n  // or nullptr if flag does not support saving and restoring a state.\n  virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;\n\n  // Copy-construct a new value of the flag's type in a memory referenced by\n  // the dst based on the current flag's value.\n  virtual void Read(void* absl_nonnull dst) const = 0;\n\n  // To be deleted. Used to return true if flag's current value originated from\n  // command line.\n  virtual bool IsSpecifiedOnCommandLine() const = 0;\n\n  // Validates supplied value using validator or parseflag routine\n  virtual bool ValidateInputValue(absl::string_view value) const = 0;\n\n  // Checks that flags default value can be converted to string and back to the\n  // flag's value type.\n  virtual void CheckDefaultValueParsingRoundtrip() const = 0;\n\n  // absl::CommandLineFlag::TypeName()\n  //\n  // Returns string representation of the type of this flag\n  // (the way it is spelled in the ABSL_FLAG macro).\n  // The default implementation returns the empty string.\n  virtual absl::string_view TypeName() const;\n};\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_COMMANDLINEFLAG_H_\n"
  },
  {
    "path": "absl/flags/commandlineflag_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/commandlineflag.h\"\n\n#include <memory>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/internal/private_handle_accessor.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nABSL_FLAG(int, int_flag, 201, \"int_flag help\");\nABSL_FLAG(std::string, string_flag, \"dflt\",\n          absl::StrCat(\"string_flag\", \" help\"));\nABSL_RETIRED_FLAG(bool, bool_retired_flag, false, \"bool_retired_flag help\");\n\n// These are only used to test default values.\nABSL_FLAG(int, int_flag2, 201, \"\");\nABSL_FLAG(std::string, string_flag2, \"dflt\", \"\");\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\n\nclass CommandLineFlagTest : public testing::Test {\n protected:\n  static void SetUpTestSuite() {\n    // Install a function to normalize filenames before this test is run.\n    absl::FlagsUsageConfig default_config;\n    default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;\n    absl::SetFlagsUsageConfig(default_config);\n  }\n\n  void SetUp() override {\n#if ABSL_FLAGS_STRIP_NAMES\n    GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n    flag_saver_ = absl::make_unique<absl::FlagSaver>();\n  }\n  void TearDown() override { flag_saver_.reset(); }\n\n private:\n  static std::string NormalizeFileName(absl::string_view fname) {\n#ifdef _WIN32\n    std::string normalized(fname);\n    std::replace(normalized.begin(), normalized.end(), '\\\\', '/');\n    fname = normalized;\n#endif\n    return std::string(fname);\n  }\n\n  std::unique_ptr<absl::FlagSaver> flag_saver_;\n};\n\nTEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {\n  auto* flag_01 = absl::FindCommandLineFlag(\"int_flag\");\n\n  ASSERT_TRUE(flag_01);\n  EXPECT_EQ(flag_01->Name(), \"int_flag\");\n  EXPECT_EQ(flag_01->Help(), \"int_flag help\");\n  EXPECT_TRUE(!flag_01->IsRetired());\n  EXPECT_TRUE(flag_01->IsOfType<int>());\n  EXPECT_TRUE(!flag_01->IsOfType<bool>());\n  EXPECT_TRUE(!flag_01->IsOfType<std::string>());\n  EXPECT_TRUE(absl::EndsWith(flag_01->Filename(),\n                             \"absl/flags/commandlineflag_test.cc\"))\n      << flag_01->Filename();\n\n  auto* flag_02 = absl::FindCommandLineFlag(\"string_flag\");\n\n  ASSERT_TRUE(flag_02);\n  EXPECT_EQ(flag_02->Name(), \"string_flag\");\n  EXPECT_EQ(flag_02->Help(), \"string_flag help\");\n  EXPECT_TRUE(!flag_02->IsRetired());\n  EXPECT_TRUE(flag_02->IsOfType<std::string>());\n  EXPECT_TRUE(!flag_02->IsOfType<bool>());\n  EXPECT_TRUE(!flag_02->IsOfType<int>());\n  EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),\n                             \"absl/flags/commandlineflag_test.cc\"))\n      << flag_02->Filename();\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(CommandLineFlagTest, TestValueAccessMethods) {\n  absl::SetFlag(&FLAGS_int_flag2, 301);\n  auto* flag_01 = absl::FindCommandLineFlag(\"int_flag2\");\n\n  ASSERT_TRUE(flag_01);\n  EXPECT_EQ(flag_01->CurrentValue(), \"301\");\n  EXPECT_EQ(flag_01->DefaultValue(), \"201\");\n\n  absl::SetFlag(&FLAGS_string_flag2, \"new_str_value\");\n  auto* flag_02 = absl::FindCommandLineFlag(\"string_flag2\");\n\n  ASSERT_TRUE(flag_02);\n  EXPECT_EQ(flag_02->CurrentValue(), \"new_str_value\");\n  EXPECT_EQ(flag_02->DefaultValue(), \"dflt\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {\n  std::string err;\n\n  auto* flag_01 = absl::FindCommandLineFlag(\"int_flag\");\n  EXPECT_FALSE(\n      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"11\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);\n  EXPECT_FALSE(\n      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"-123\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);\n  EXPECT_FALSE(\n      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"xyz\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);\n  EXPECT_EQ(err, \"Illegal value 'xyz' specified for flag 'int_flag'\");\n  EXPECT_FALSE(\n      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"A1\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);\n  EXPECT_EQ(err, \"Illegal value 'A1' specified for flag 'int_flag'\");\n  EXPECT_FALSE(\n      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"0x10\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);\n  EXPECT_FALSE(\n      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"011\", flags::SET_FLAGS_VALUE, flags::kCommandLine, err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);\n  EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));\n\n  EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));\n  EXPECT_EQ(err, \"Illegal value '' specified for flag 'int_flag'\");\n\n  auto* flag_02 = absl::FindCommandLineFlag(\"string_flag\");\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_02, \"xyz\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), \"xyz\");\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_02, \"\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), \"\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {\n  std::string err;\n\n  auto* flag_01 = absl::FindCommandLineFlag(\"int_flag\");\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"111\", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(flag_01->DefaultValue(), \"111\");\n\n  auto* flag_02 = absl::FindCommandLineFlag(\"string_flag\");\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_02, \"abc\", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(flag_02->DefaultValue(), \"abc\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(CommandLineFlagTest, TestParseFromIfDefault) {\n  std::string err;\n\n  auto* flag_01 = absl::FindCommandLineFlag(\"int_flag\");\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"22\", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,\n      err))\n      << err;\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"33\", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);\n  // EXPECT_EQ(err, \"ERROR: int_flag is already set to 22\");\n\n  // Reset back to default value\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"201\", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,\n      err));\n\n  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(\n      *flag_01, \"33\", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,\n      err));\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);\n  // EXPECT_EQ(err, \"ERROR: int_flag is already set to 201\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/config.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_CONFIG_H_\n#define ABSL_FLAGS_CONFIG_H_\n\n// Determine if we should strip string literals from the Flag objects.\n// By default we strip string literals on mobile platforms.\n#if !defined(ABSL_FLAGS_STRIP_NAMES)\n\n#if defined(__ANDROID__)\n#define ABSL_FLAGS_STRIP_NAMES 1\n\n#elif defined(__APPLE__)\n#include <TargetConditionals.h>\n#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE\n#define ABSL_FLAGS_STRIP_NAMES 1\n#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED\n#define ABSL_FLAGS_STRIP_NAMES 1\n#endif  // TARGET_OS_*\n#endif\n\n#endif  // !defined(ABSL_FLAGS_STRIP_NAMES)\n\n#if !defined(ABSL_FLAGS_STRIP_NAMES)\n// If ABSL_FLAGS_STRIP_NAMES wasn't set on the command line or above,\n// the default is not to strip.\n#define ABSL_FLAGS_STRIP_NAMES 0\n#endif\n\n#if !defined(ABSL_FLAGS_STRIP_HELP)\n// By default, if we strip names, we also strip help.\n#define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES\n#endif\n\n// These macros represent the \"source of truth\" for the list of supported\n// built-in types.\n#define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \\\n  A(bool, bool)                              \\\n  A(short, short)                            \\\n  A(unsigned short, unsigned_short)          \\\n  A(int, int)                                \\\n  A(unsigned int, unsigned_int)              \\\n  A(long, long)                              \\\n  A(unsigned long, unsigned_long)            \\\n  A(long long, long_long)                    \\\n  A(unsigned long long, unsigned_long_long)  \\\n  A(double, double)                          \\\n  A(float, float)\n\n#define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \\\n  ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A)         \\\n  A(std::string, std_string)                   \\\n  A(std::vector<std::string>, std_vector_of_string)\n\n#endif  // ABSL_FLAGS_CONFIG_H_\n"
  },
  {
    "path": "absl/flags/config_test.cc",
    "content": "//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/config.h\"\n\n#ifdef __APPLE__\n#include <TargetConditionals.h>\n#endif\n\n#include \"gtest/gtest.h\"\n\n#ifndef ABSL_FLAGS_STRIP_NAMES\n#error ABSL_FLAGS_STRIP_NAMES is not defined\n#endif\n\n#ifndef ABSL_FLAGS_STRIP_HELP\n#error ABSL_FLAGS_STRIP_HELP is not defined\n#endif\n\nnamespace {\n\n// Test that ABSL_FLAGS_STRIP_NAMES and ABSL_FLAGS_STRIP_HELP are configured how\n// we expect them to be configured by default. If you override this\n// configuration, this test will fail, but the code should still be safe to use.\nTEST(FlagsConfigTest, Test) {\n#if defined(__ANDROID__)\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);\n#elif defined(__myriad2__)\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);\n#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);\n#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);\n#elif defined(__APPLE__)\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);\n#elif defined(_WIN32)\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);\n#elif defined(__linux__)\n  EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);\n  EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/declare.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: declare.h\n// -----------------------------------------------------------------------------\n//\n// This file defines the ABSL_DECLARE_FLAG macro, allowing you to declare an\n// `absl::Flag` for use within a translation unit. You should place this\n// declaration within the header file associated with the .cc file that defines\n// and owns the `Flag`.\n\n#ifndef ABSL_FLAGS_DECLARE_H_\n#define ABSL_FLAGS_DECLARE_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG.\ntemplate <typename T>\nclass Flag;\n\n}  // namespace flags_internal\n\n// Flag\n//\n// Forward declaration of the `absl::Flag` type for use in defining the macro.\ntemplate <typename T>\nusing Flag = flags_internal::Flag<T>;\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// ABSL_DECLARE_FLAG()\n//\n// This macro is a convenience for declaring use of an `absl::Flag` within a\n// translation unit. This macro should be used within a header file to\n// declare usage of the flag within any .cc file including that header file.\n//\n// The ABSL_DECLARE_FLAG(type, name) macro expands to:\n//\n//   extern absl::Flag<type> FLAGS_name;\n#define ABSL_DECLARE_FLAG(type, name) ABSL_DECLARE_FLAG_INTERNAL(type, name)\n\n// Internal implementation of ABSL_DECLARE_FLAG to allow macro expansion of its\n// arguments. Clients must use ABSL_DECLARE_FLAG instead.\n//\n// The non-MSVC implementation declares the flag twice. This is to allow\n// applying attributes to the second declaration. However, this causes a\n// compile error (C4273) in MSVC if a `__declspec` is prepended to the macro.\n#if defined(_MSC_VER)\n#define ABSL_DECLARE_FLAG_INTERNAL(type, name) \\\n  extern absl::Flag<type> FLAGS_##name\n#else\n#define ABSL_DECLARE_FLAG_INTERNAL(type, name)               \\\n  extern absl::Flag<type> FLAGS_##name;                      \\\n  namespace absl /* block flags in namespaces */ {}          \\\n  /* second redeclaration is to allow applying attributes */ \\\n  extern absl::Flag<type> FLAGS_##name\n#endif  // _MSC_VER\n\n#endif  // ABSL_FLAGS_DECLARE_H_\n"
  },
  {
    "path": "absl/flags/flag.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: flag.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the `absl::Flag<T>` type for holding command-line\n// flag data, and abstractions to create, get and set such flag data.\n//\n// It is important to note that this type is **unspecified** (an implementation\n// detail) and you do not construct or manipulate actual `absl::Flag<T>`\n// instances. Instead, you define and declare flags using the\n// `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values\n// using the `absl::GetFlag()` and `absl::SetFlag()` functions.\n\n#ifndef ABSL_FLAGS_FLAG_H_\n#define ABSL_FLAGS_FLAG_H_\n\n#include <cstdint>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/internal/flag.h\"\n#include \"absl/flags/internal/registry.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Flag\n//\n// An `absl::Flag` holds a command-line flag value, providing a runtime\n// parameter to a binary. Such flags should be defined in the global namespace\n// and (preferably) in the module containing the binary's `main()` function.\n//\n// You should not construct and cannot use the `absl::Flag` type directly;\n// instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro\n// within a header file, and define your flag using `ABSL_FLAG()` within your\n// header's associated `.cc` file. Such flags will be named `FLAGS_name`.\n//\n// Example:\n//\n//    .h file\n//\n//      // Declares usage of a flag named \"FLAGS_count\"\n//      ABSL_DECLARE_FLAG(int, count);\n//\n//    .cc file\n//\n//      // Defines a flag named \"FLAGS_count\" with a default `int` value of 0.\n//      ABSL_FLAG(int, count, 0, \"Count of items to process\");\n//\n// No public methods of `absl::Flag<T>` are part of the Abseil Flags API.\n//\n// For type support of Abseil Flags, see the marshalling.h header file, which\n// discusses supported standard types, optional flags, and additional Abseil\n// type support.\n\ntemplate <typename T>\nusing Flag = flags_internal::Flag<T>;\n\n// GetFlag()\n//\n// Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do\n// not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`;\n// instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).\n// Because this function returns by value and not by reference, it is\n// thread-safe, but note that the operation may be expensive; as a result, avoid\n// `absl::GetFlag()` within any tight loops.\n//\n// Example:\n//\n//   // FLAGS_count is a Flag of type `int`\n//   int my_count = absl::GetFlag(FLAGS_count);\n//\n//   // FLAGS_firstname is a Flag of type `std::string`\n//   std::string first_name = absl::GetFlag(FLAGS_firstname);\ntemplate <typename T>\n[[nodiscard]] T GetFlag(const absl::Flag<T>& flag) {\n  return flags_internal::FlagImplPeer::InvokeGet<T>(flag);\n}\n\n// SetFlag()\n//\n// Sets the value of an `absl::Flag` to the value `v`. Do not construct an\n// `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the\n// flag's variable name (e.g. `FLAGS_name`). This function is\n// thread-safe, but is potentially expensive. Avoid setting flags in general,\n// but especially within performance-critical code.\ntemplate <typename T>\nvoid SetFlag(absl::Flag<T>* absl_nonnull flag, const T& v) {\n  flags_internal::FlagImplPeer::InvokeSet(*flag, v);\n}\n\n// Overload of `SetFlag()` to allow callers to pass in a value that is\n// convertible to `T`. E.g., use this overload to pass a \"const char*\" when `T`\n// is `std::string`.\ntemplate <typename T, typename V>\nvoid SetFlag(absl::Flag<T>* absl_nonnull flag, const V& v) {\n  T value(v);\n  flags_internal::FlagImplPeer::InvokeSet(*flag, value);\n}\n\n// GetFlagReflectionHandle()\n//\n// Returns the reflection handle corresponding to specified Abseil Flag\n// instance. Use this handle to access flag's reflection information, like name,\n// location, default value etc.\n//\n// Example:\n//\n//   std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();\n\ntemplate <typename T>\nconst CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {\n  return flags_internal::FlagImplPeer::InvokeReflect(f);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n\n// ABSL_FLAG()\n//\n// This macro defines an `absl::Flag<T>` instance of a specified type `T`:\n//\n//   ABSL_FLAG(T, name, default_value, help);\n//\n// where:\n//\n//   * `T` is a supported flag type (see the list of types in `marshalling.h`),\n//   * `name` designates the name of the flag (as a global variable\n//     `FLAGS_name`),\n//   * `default_value` is an expression holding the default value for this flag\n//     (which must be implicitly convertible to `T`),\n//   * `help` is the help text, which can also be an expression.\n//\n// This macro expands to a flag named 'FLAGS_name' of type 'T':\n//\n//   absl::Flag<T> FLAGS_name = ...;\n//\n// Note that all such instances are created as global variables.\n//\n// For `ABSL_FLAG()` values that you wish to expose to other translation units,\n// it is recommended to define those flags within the `.cc` file associated with\n// the header where the flag is declared.\n//\n// Note: do not construct objects of type `absl::Flag<T>` directly. Only use the\n// `ABSL_FLAG()` macro for such construction.\n#define ABSL_FLAG(Type, name, default_value, help) \\\n  ABSL_FLAG_IMPL(Type, name, default_value, help)\n\n// ABSL_FLAG().OnUpdate()\n//\n// Defines a flag of type `T` with a callback attached:\n//\n//   ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);\n//\n// `callback` should be convertible to `void (*)()`.\n//\n// After any setting of the flag value, the callback will be called at least\n// once. A rapid sequence of changes may be merged together into the same\n// callback. No concurrent calls to the callback will be made for the same\n// flag. Callbacks are allowed to read the current value of the flag but must\n// not mutate that flag.\n//\n// The update mechanism guarantees \"eventual consistency\"; if the callback\n// derives an auxiliary data structure from the flag value, it is guaranteed\n// that eventually the flag value and the derived data structure will be\n// consistent.\n//\n// Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this\n// comment serves as its API documentation.\n\n// -----------------------------------------------------------------------------\n// Implementation details below this section\n// -----------------------------------------------------------------------------\n\n// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES\n#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag\n#define ABSL_FLAG_IMPL_HELP_ARG(name)                      \\\n  absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \\\n      FLAGS_help_storage_##name)\n#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \\\n  absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)\n\n#if ABSL_FLAGS_STRIP_NAMES\n#define ABSL_FLAG_IMPL_FLAGNAME(txt) \"\"\n#define ABSL_FLAG_IMPL_TYPENAME(txt) \"\"\n#define ABSL_FLAG_IMPL_FILENAME() \"\"\n#define ABSL_FLAG_IMPL_REGISTRAR(T, flag)                                      \\\n  absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \\\n                                                nullptr)\n#else\n#define ABSL_FLAG_IMPL_FLAGNAME(txt) txt\n#define ABSL_FLAG_IMPL_TYPENAME(txt) txt\n#define ABSL_FLAG_IMPL_FILENAME() __FILE__\n#define ABSL_FLAG_IMPL_REGISTRAR(T, flag)                                     \\\n  absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \\\n                                               __FILE__)\n#endif\n\n// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP\n\n#if ABSL_FLAGS_STRIP_HELP\n#define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp\n#else\n#define ABSL_FLAG_IMPL_FLAGHELP(txt) txt\n#endif\n\n// AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)\n// and lazy (method NonConst) evaluation of help message expression. We choose\n// between the two via the call to HelpArg in absl::Flag instantiation below.\n// If help message expression is constexpr evaluable compiler will optimize\n// away this whole struct.\n// TODO(rogeeff): place these generated structs into local namespace and apply\n// ABSL_INTERNAL_UNIQUE_SHORT_NAME.\n// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name\n#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                       \\\n  struct AbslFlagHelpGenFor##name {                                          \\\n    /* The expression is run in the caller as part of the   */               \\\n    /* default value argument. That keeps temporaries alive */               \\\n    /* long enough for NonConst to work correctly.          */               \\\n    static constexpr absl::string_view Value(                                \\\n        absl::string_view absl_flag_help ABSL_ATTRIBUTE_LIFETIME_BOUND  =     \\\n            ABSL_FLAG_IMPL_FLAGHELP(txt)) {                                  \\\n      return absl_flag_help;                                                 \\\n    }                                                                        \\\n    static std::string NonConst() { return std::string(Value()); }           \\\n  };                                                                         \\\n  constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \\\n      ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) =                     \\\n          absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \\\n              0);\n\n#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)     \\\n  struct AbslFlagDefaultGenFor##name {                                        \\\n    Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \\\n    static void Gen(void* absl_flag_default_loc) {                            \\\n      new (absl_flag_default_loc) Type(AbslFlagDefaultGenFor##name{}.value);  \\\n    }                                                                         \\\n  };\n\n// ABSL_FLAG_IMPL\n//\n// Note: Name of registrar object is not arbitrary. It is used to \"grab\"\n// global name for FLAGS_no<flag_name> symbol, thus preventing the possibility\n// of defining two flags with names foo and nofoo.\n#define ABSL_FLAG_IMPL(Type, name, default_value, help)               \\\n  extern ::absl::Flag<Type> FLAGS_##name;                             \\\n  namespace absl /* block flags in namespaces */ {}                   \\\n  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)   \\\n  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                     \\\n  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                      \\\n      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_TYPENAME(#Type), \\\n      ABSL_FLAG_IMPL_FILENAME(), ABSL_FLAG_IMPL_HELP_ARG(name),       \\\n      ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)};                        \\\n  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;     \\\n  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =           \\\n      ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)\n\n// ABSL_RETIRED_FLAG\n//\n// Designates the flag (which is usually pre-existing) as \"retired.\" A retired\n// flag is a flag that is now unused by the program, but may still be passed on\n// the command line, usually by production scripts. A retired flag is ignored\n// and code can't access it at runtime.\n//\n// This macro registers a retired flag with given name and type, with a name\n// identical to the name of the original flag you are retiring. The retired\n// flag's type can change over time, so that you can retire code to support a\n// custom flag type.\n//\n// This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply\n// replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the\n// arguments unchanged (unless of course you actually want to retire the flag\n// type at this time as well).\n//\n// `default_value` and `explanation` are unused.\n// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of\n// retired flags are cleaned up.\n#define ABSL_RETIRED_FLAG(type, name, default_value, explanation)      \\\n  static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \\\n  ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name =   \\\n      (RETIRED_FLAGS_##name.Retire(#name),                             \\\n       ::absl::flags_internal::FlagRegistrarEmpty{})\n\n#endif  // ABSL_FLAGS_FLAG_H_\n"
  },
  {
    "path": "absl/flags/flag_benchmark.cc",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <stdint.h>\n\n#include <optional>\n#include <string>\n#include <vector>\n\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/marshalling.h\"\n#include \"absl/flags/parse.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\nusing String = std::string;\nusing VectorOfStrings = std::vector<std::string>;\nusing AbslDuration = absl::Duration;\n\n// We do not want to take over marshalling for the types std::optional<int>,\n// std::optional<std::string> which we do not own. Instead we introduce unique\n// \"aliases\" to these types, which we do.\nusing AbslOptionalInt = std::optional<int>;\nstruct OptionalInt : AbslOptionalInt {\n  using AbslOptionalInt::AbslOptionalInt;\n};\n// Next two functions represent Abseil Flags marshalling for OptionalInt.\nbool AbslParseFlag(absl::string_view src, OptionalInt* flag,\n                   std::string* error) {\n  int val;\n  if (src.empty())\n    flag->reset();\n  else if (!absl::ParseFlag(src, &val, error))\n    return false;\n  *flag = val;\n  return true;\n}\nstd::string AbslUnparseFlag(const OptionalInt& flag) {\n  return !flag ? \"\" : absl::UnparseFlag(*flag);\n}\n\nusing AbslOptionalString = std::optional<std::string>;\nstruct OptionalString : AbslOptionalString {\n  using AbslOptionalString::AbslOptionalString;\n};\n// Next two functions represent Abseil Flags marshalling for OptionalString.\nbool AbslParseFlag(absl::string_view src, OptionalString* flag,\n                   std::string* error) {\n  std::string val;\n  if (src.empty())\n    flag->reset();\n  else if (!absl::ParseFlag(src, &val, error))\n    return false;\n  *flag = val;\n  return true;\n}\nstd::string AbslUnparseFlag(const OptionalString& flag) {\n  return !flag ? \"\" : absl::UnparseFlag(*flag);\n}\n\nstruct UDT {\n  UDT() = default;\n  UDT(const UDT&) {}\n  UDT& operator=(const UDT&) { return *this; }\n};\n// Next two functions represent Abseil Flags marshalling for UDT.\nbool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }\nstd::string AbslUnparseFlag(const UDT&) { return \"\"; }\n\n}  // namespace\n\n#define BENCHMARKED_TYPES(A) \\\n  A(bool)                    \\\n  A(int16_t)                 \\\n  A(uint16_t)                \\\n  A(int32_t)                 \\\n  A(uint32_t)                \\\n  A(int64_t)                 \\\n  A(uint64_t)                \\\n  A(double)                  \\\n  A(float)                   \\\n  A(String)                  \\\n  A(VectorOfStrings)         \\\n  A(OptionalInt)             \\\n  A(OptionalString)          \\\n  A(AbslDuration)            \\\n  A(UDT)\n\n#define REPLICATE_0(A, T, name, index) A(T, name, index)\n#define REPLICATE_1(A, T, name, index) \\\n  REPLICATE_0(A, T, name, index##0) REPLICATE_0(A, T, name, index##1)\n#define REPLICATE_2(A, T, name, index) \\\n  REPLICATE_1(A, T, name, index##0) REPLICATE_1(A, T, name, index##1)\n#define REPLICATE_3(A, T, name, index) \\\n  REPLICATE_2(A, T, name, index##0) REPLICATE_2(A, T, name, index##1)\n#define REPLICATE_4(A, T, name, index) \\\n  REPLICATE_3(A, T, name, index##0) REPLICATE_3(A, T, name, index##1)\n#define REPLICATE_5(A, T, name, index) \\\n  REPLICATE_4(A, T, name, index##0) REPLICATE_4(A, T, name, index##1)\n#define REPLICATE_6(A, T, name, index) \\\n  REPLICATE_5(A, T, name, index##0) REPLICATE_5(A, T, name, index##1)\n#define REPLICATE_7(A, T, name, index) \\\n  REPLICATE_6(A, T, name, index##0) REPLICATE_6(A, T, name, index##1)\n#define REPLICATE_8(A, T, name, index) \\\n  REPLICATE_7(A, T, name, index##0) REPLICATE_7(A, T, name, index##1)\n#define REPLICATE_9(A, T, name, index) \\\n  REPLICATE_8(A, T, name, index##0) REPLICATE_8(A, T, name, index##1)\n#if defined(_MSC_VER)\n#define REPLICATE(A, T, name) \\\n  REPLICATE_7(A, T, name, 0) REPLICATE_7(A, T, name, 1)\n#define SINGLE_FLAG(T) FLAGS_##T##_flag_00000000\n#else\n#define REPLICATE(A, T, name) \\\n  REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)\n#define SINGLE_FLAG(T) FLAGS_##T##_flag_0000000000\n#endif\n#define REPLICATE_ALL(A, T, name) \\\n  REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)\n\n#define COUNT(T, name, index) +1\nconstexpr size_t kNumFlags = 0 REPLICATE(COUNT, _, _);\n\n#if defined(__clang__) && defined(__linux__)\n// Force the flags used for benchmarks into a separate ELF section.\n// This ensures that, even when other parts of the code might change size,\n// the layout of the flags across cachelines is kept constant. This makes\n// benchmark results more reproducible across unrelated code changes.\n#pragma clang section data = \".benchmark_flags\"\n#endif\n#define DEFINE_FLAG(T, name, index) ABSL_FLAG(T, name##_##index, {}, \"\");\n#define FLAG_DEF(T) REPLICATE(DEFINE_FLAG, T, T##_flag)\nBENCHMARKED_TYPES(FLAG_DEF)\n#if defined(__clang__) && defined(__linux__)\n#pragma clang section data = \"\"\n#endif\n// Register thousands of flags to bloat up the size of the registry.\n// This mimics real life production binaries.\n#define BLOAT_FLAG(_unused1, _unused2, index) \\\n  ABSL_FLAG(int, bloat_flag_##index, 0, \"\");\nREPLICATE_ALL(BLOAT_FLAG, _, _)\n\nnamespace {\n\n#define FLAG_PTR(T, name, index) &FLAGS_##name##_##index,\n#define FLAG_PTR_ARR(T)                              \\\n  static constexpr absl::Flag<T>* FlagPtrs_##T[] = { \\\n      REPLICATE(FLAG_PTR, T, T##_flag)};\nBENCHMARKED_TYPES(FLAG_PTR_ARR)\n\n#define BM_SingleGetFlag(T)                                    \\\n  void BM_SingleGetFlag_##T(benchmark::State& state) {         \\\n    for (auto _ : state) {                                     \\\n      benchmark::DoNotOptimize(absl::GetFlag(SINGLE_FLAG(T))); \\\n    }                                                          \\\n  }                                                            \\\n  BENCHMARK(BM_SingleGetFlag_##T)->ThreadRange(1, 16);\n\nBENCHMARKED_TYPES(BM_SingleGetFlag)\n\ntemplate <typename T>\nstruct Accumulator {\n  using type = T;\n};\ntemplate <>\nstruct Accumulator<String> {\n  using type = size_t;\n};\ntemplate <>\nstruct Accumulator<VectorOfStrings> {\n  using type = size_t;\n};\ntemplate <>\nstruct Accumulator<OptionalInt> {\n  using type = bool;\n};\ntemplate <>\nstruct Accumulator<OptionalString> {\n  using type = bool;\n};\ntemplate <>\nstruct Accumulator<UDT> {\n  using type = bool;\n};\n\ntemplate <typename T>\nvoid Accumulate(typename Accumulator<T>::type& a, const T& f) {\n  a += f;\n}\nvoid Accumulate(bool& a, bool f) { a = a || f; }\nvoid Accumulate(size_t& a, const std::string& f) { a += f.size(); }\nvoid Accumulate(size_t& a, const std::vector<std::string>& f) { a += f.size(); }\nvoid Accumulate(bool& a, const OptionalInt& f) { a |= f.has_value(); }\nvoid Accumulate(bool& a, const OptionalString& f) { a |= f.has_value(); }\nvoid Accumulate(bool& a, const UDT& f) {\n  a |= reinterpret_cast<int64_t>(&f) & 0x1;\n}\n\n#define BM_ManyGetFlag(T)                            \\\n  void BM_ManyGetFlag_##T(benchmark::State& state) { \\\n    Accumulator<T>::type res = {};                   \\\n    while (state.KeepRunningBatch(kNumFlags)) {      \\\n      for (auto* flag_ptr : FlagPtrs_##T) {          \\\n        Accumulate(res, absl::GetFlag(*flag_ptr));   \\\n      }                                              \\\n    }                                                \\\n    benchmark::DoNotOptimize(res);                   \\\n  }                                                  \\\n  BENCHMARK(BM_ManyGetFlag_##T)->ThreadRange(1, 8);\n\nBENCHMARKED_TYPES(BM_ManyGetFlag)\n\nvoid BM_ThreadedFindCommandLineFlag(benchmark::State& state) {\n  char dummy[] = \"dummy\";\n  char* argv[] = {dummy};\n  // We need to ensure that flags have been parsed. That is where the registry\n  // is finalized.\n  absl::ParseCommandLine(1, argv);\n\n  while (state.KeepRunningBatch(kNumFlags)) {\n    for (auto* flag_ptr : FlagPtrs_bool) {\n      benchmark::DoNotOptimize(absl::FindCommandLineFlag(flag_ptr->Name()));\n    }\n  }\n}\nBENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);\n\n}  // namespace\n\n#ifdef __llvm__\n// To view disassembly use: gdb ${BINARY}  -batch -ex \"disassemble /s $FUNC\"\n#define InvokeGetFlag(T)                                             \\\n  T AbslInvokeGetFlag##T() { return absl::GetFlag(SINGLE_FLAG(T)); } \\\n  int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1);\n\nBENCHMARKED_TYPES(InvokeGetFlag)\n#endif  // __llvm__\n"
  },
  {
    "path": "absl/flags/flag_benchmark.lds",
    "content": "/* This linker script forces the flags used by flags_benchmark\n * into a separate page-aligned section. This isn't necessary for\n * correctness but ensures that the benchmark results are more\n * reproducible across unrelated code changes.\n */\nSECTIONS {\n  .benchmark_flags : {\n    . = ALIGN(0x1000);\n    * (.benchmark_flags);\n  }\n}\n\nINSERT AFTER .data\n"
  },
  {
    "path": "absl/flags/flag_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/flag.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <atomic>\n#include <optional>\n#include <string>\n#include <thread>  // NOLINT\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/declare.h\"\n#include \"absl/flags/internal/flag.h\"\n#include \"absl/flags/marshalling.h\"\n#include \"absl/flags/parse.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);\nABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\n\nstd::string TestHelpMsg() { return \"dynamic help\"; }\n#if defined(_MSC_VER) && !defined(__clang__)\nstd::string TestLiteralHelpMsg() { return \"literal help\"; }\n#endif\ntemplate <typename T>\nvoid TestMakeDflt(void* dst) {\n  new (dst) T{};\n}\nvoid TestCallback() {}\n\nstruct UDT {\n  UDT() = default;\n  UDT(const UDT&) = default;\n  UDT& operator=(const UDT&) = default;\n};\nbool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }\nstd::string AbslUnparseFlag(const UDT&) { return \"\"; }\n\nclass FlagTest : public testing::Test {\n protected:\n  static void SetUpTestSuite() {\n    // Install a function to normalize filenames before this test is run.\n    absl::FlagsUsageConfig default_config;\n    default_config.normalize_filename = &FlagTest::NormalizeFileName;\n    absl::SetFlagsUsageConfig(default_config);\n  }\n\n private:\n  static std::string NormalizeFileName(absl::string_view fname) {\n#ifdef _WIN32\n    std::string normalized(fname);\n    std::replace(normalized.begin(), normalized.end(), '\\\\', '/');\n    fname = normalized;\n#endif\n    return std::string(fname);\n  }\n  absl::FlagSaver flag_saver_;\n};\n\nstruct S1 {\n  S1() = default;\n  S1(const S1&) = default;\n  int32_t f1;\n  int64_t f2;\n};\n\nstruct S2 {\n  S2() = default;\n  S2(const S2&) = default;\n  int64_t f1;\n  double f2;\n};\n\nTEST_F(FlagTest, Traits) {\n  EXPECT_EQ(flags::StorageKind<int>(),\n            flags::FlagValueStorageKind::kValueAndInitBit);\n  EXPECT_EQ(flags::StorageKind<bool>(),\n            flags::FlagValueStorageKind::kValueAndInitBit);\n  EXPECT_EQ(flags::StorageKind<double>(),\n            flags::FlagValueStorageKind::kOneWordAtomic);\n  EXPECT_EQ(flags::StorageKind<int64_t>(),\n            flags::FlagValueStorageKind::kOneWordAtomic);\n\n  EXPECT_EQ(flags::StorageKind<S1>(),\n            flags::FlagValueStorageKind::kSequenceLocked);\n  EXPECT_EQ(flags::StorageKind<S2>(),\n            flags::FlagValueStorageKind::kSequenceLocked);\n// Make sure absl::Duration uses the sequence-locked code path. MSVC 2015\n// doesn't consider absl::Duration to be trivially-copyable so we just\n// restrict this to clang as it seems to be a well-behaved compiler.\n#ifdef __clang__\n  EXPECT_EQ(flags::StorageKind<absl::Duration>(),\n            flags::FlagValueStorageKind::kSequenceLocked);\n#endif\n\n  EXPECT_EQ(flags::StorageKind<std::string>(),\n            flags::FlagValueStorageKind::kHeapAllocated);\n  EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),\n            flags::FlagValueStorageKind::kHeapAllocated);\n\n  EXPECT_EQ(flags::StorageKind<absl::int128>(),\n            flags::FlagValueStorageKind::kSequenceLocked);\n  EXPECT_EQ(flags::StorageKind<absl::uint128>(),\n            flags::FlagValueStorageKind::kSequenceLocked);\n}\n\n// --------------------------------------------------------------------\n\nconstexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg(\"literal help\"),\n                                      flags::FlagHelpKind::kLiteral};\n\nusing String = std::string;\nusing int128 = absl::int128;\nusing uint128 = absl::uint128;\n\n#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                        \\\n  constexpr flags::FlagDefaultArg f1default##T{                            \\\n      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};     \\\n  constexpr absl::Flag<T> f1##T{\"f1\", #T, \"file\", help_arg, f1default##T}; \\\n  ABSL_CONST_INIT absl::Flag<T> f2##T {                                    \\\n    \"f2\", #T, \"file\",                                                      \\\n        {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \\\n        flags::FlagDefaultArg {                                            \\\n      flags::FlagDefaultSrc(&TestMakeDflt<T>),                             \\\n          flags::FlagDefaultKind::kGenFunc                                 \\\n    }                                                                      \\\n  }\n\nDEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);\nDEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);\nDEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);\nDEFINE_CONSTRUCTED_FLAG(int128, 13, kGenFunc);\nDEFINE_CONSTRUCTED_FLAG(uint128, 14, kGenFunc);\n\ntemplate <typename T>\nbool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {\n  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), \"f1\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), \"literal help\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), \"file\");\n\n  flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2), nullptr)\n      .OnUpdate(TestCallback);\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), \"f2\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), \"dynamic help\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), \"file\");\n\n  return true;\n}\n\n#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);\n\nTEST_F(FlagTest, TestConstruction) {\n  TEST_CONSTRUCTED_FLAG(bool);\n  TEST_CONSTRUCTED_FLAG(int16_t);\n  TEST_CONSTRUCTED_FLAG(uint16_t);\n  TEST_CONSTRUCTED_FLAG(int32_t);\n  TEST_CONSTRUCTED_FLAG(uint32_t);\n  TEST_CONSTRUCTED_FLAG(int64_t);\n  TEST_CONSTRUCTED_FLAG(uint64_t);\n  TEST_CONSTRUCTED_FLAG(float);\n  TEST_CONSTRUCTED_FLAG(double);\n  TEST_CONSTRUCTED_FLAG(String);\n  TEST_CONSTRUCTED_FLAG(UDT);\n  TEST_CONSTRUCTED_FLAG(int128);\n  TEST_CONSTRUCTED_FLAG(uint128);\n}\n\n// --------------------------------------------------------------------\n\n}  // namespace\n\nABSL_DECLARE_FLAG(bool, test_flag_01);\nABSL_DECLARE_FLAG(int, test_flag_02);\nABSL_DECLARE_FLAG(int16_t, test_flag_03);\nABSL_DECLARE_FLAG(uint16_t, test_flag_04);\nABSL_DECLARE_FLAG(int32_t, test_flag_05);\nABSL_DECLARE_FLAG(uint32_t, test_flag_06);\nABSL_DECLARE_FLAG(int64_t, test_flag_07);\nABSL_DECLARE_FLAG(uint64_t, test_flag_08);\nABSL_DECLARE_FLAG(double, test_flag_09);\nABSL_DECLARE_FLAG(float, test_flag_10);\nABSL_DECLARE_FLAG(std::string, test_flag_11);\nABSL_DECLARE_FLAG(absl::Duration, test_flag_12);\nABSL_DECLARE_FLAG(absl::int128, test_flag_13);\nABSL_DECLARE_FLAG(absl::uint128, test_flag_14);\n\nnamespace {\n\nTEST_F(FlagTest, TestFlagDeclaration) {\n#if ABSL_FLAGS_STRIP_NAMES\n  GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n  // test that we can access flag objects.\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),\n            \"test_flag_01\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),\n            \"test_flag_02\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),\n            \"test_flag_03\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),\n            \"test_flag_04\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),\n            \"test_flag_05\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),\n            \"test_flag_06\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),\n            \"test_flag_07\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),\n            \"test_flag_08\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),\n            \"test_flag_09\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),\n            \"test_flag_10\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),\n            \"test_flag_11\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),\n            \"test_flag_12\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),\n            \"test_flag_13\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),\n            \"test_flag_14\");\n}\n\n}  // namespace\n\n#if ABSL_FLAGS_STRIP_NAMES\n// The intent of this helper struct and an expression below is to make sure that\n// in the configuration where ABSL_FLAGS_STRIP_NAMES=1 registrar construction\n// (in cases of no Tail calls like OnUpdate) is constexpr and thus can and\n// should be completely optimized away, thus avoiding the cost/overhead of\n// static initializers.\nstruct VerifyConsteval {\n  friend consteval flags::FlagRegistrarEmpty operator+(\n      flags::FlagRegistrarEmpty, VerifyConsteval) {\n    return {};\n  }\n};\n\nABSL_FLAG(int, test_registrar_const_init, 0, \"\") + VerifyConsteval();\n#endif\n\n// --------------------------------------------------------------------\n\nABSL_FLAG(bool, test_flag_01, true, \"test flag 01\");\nABSL_FLAG(int, test_flag_02, 1234, \"test flag 02\");\nABSL_FLAG(int16_t, test_flag_03, -34, \"test flag 03\");\nABSL_FLAG(uint16_t, test_flag_04, 189, \"test flag 04\");\nABSL_FLAG(int32_t, test_flag_05, 10765, \"test flag 05\");\nABSL_FLAG(uint32_t, test_flag_06, 40000, \"test flag 06\");\nABSL_FLAG(int64_t, test_flag_07, -1234567, \"test flag 07\");\nABSL_FLAG(uint64_t, test_flag_08, 9876543, \"test flag 08\");\nABSL_FLAG(double, test_flag_09, -9.876e-50, \"test flag 09\");\nABSL_FLAG(float, test_flag_10, 1.234e12f, \"test flag 10\");\nABSL_FLAG(std::string, test_flag_11, \"\", \"test flag 11\");\nABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), \"test flag 12\");\nABSL_FLAG(absl::int128, test_flag_13, absl::MakeInt128(-1, 0), \"test flag 13\");\nABSL_FLAG(absl::uint128, test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD),\n          \"test flag 14\");\n\nnamespace {\n\nTEST_F(FlagTest, TestFlagDefinition) {\n#if ABSL_FLAGS_STRIP_NAMES\n  GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n  absl::string_view expected_file_name = \"absl/flags/flag_test.cc\";\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),\n            \"test_flag_01\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),\n            \"test flag 01\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),\n            \"test_flag_02\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),\n            \"test flag 02\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),\n            \"test_flag_03\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),\n            \"test flag 03\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),\n            \"test_flag_04\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),\n            \"test flag 04\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),\n            \"test_flag_05\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),\n            \"test flag 05\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),\n            \"test_flag_06\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),\n            \"test flag 06\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),\n            \"test_flag_07\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),\n            \"test flag 07\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),\n            \"test_flag_08\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),\n            \"test flag 08\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),\n            \"test_flag_09\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),\n            \"test flag 09\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),\n            \"test_flag_10\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),\n            \"test flag 10\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),\n            \"test_flag_11\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),\n            \"test flag 11\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),\n            \"test_flag_12\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),\n            \"test flag 12\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),\n            \"test_flag_13\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Help(),\n            \"test flag 13\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename();\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),\n            \"test_flag_14\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Help(),\n            \"test flag 14\");\n  EXPECT_TRUE(absl::EndsWith(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename(),\n      expected_file_name))\n      << absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename();\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestDefault) {\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),\n            \"true\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),\n            \"1234\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),\n            \"-34\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),\n            \"189\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),\n            \"10765\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),\n            \"40000\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),\n            \"-1234567\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),\n            \"9876543\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),\n            \"-9.876e-50\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),\n            \"1.234e+12\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),\n            \"\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),\n            \"10m\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).DefaultValue(),\n            \"-18446744073709551616\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).DefaultValue(),\n            \"1152827684197027293\");\n\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),\n            \"true\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),\n            \"1234\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),\n            \"-34\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),\n            \"189\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),\n            \"10765\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),\n            \"40000\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),\n            \"-1234567\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),\n            \"9876543\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),\n            \"-9.876e-50\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),\n            \"1.234e+12\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),\n            \"\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),\n            \"10m\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).CurrentValue(),\n            \"-18446744073709551616\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).CurrentValue(),\n            \"1152827684197027293\");\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), \"\");\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),\n            absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));\n}\n\n// --------------------------------------------------------------------\n\nstruct NonTriviallyCopyableAggregate {\n  NonTriviallyCopyableAggregate() = default;\n  // NOLINTNEXTLINE\n  NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)\n      : value(rhs.value) {}\n  // NOLINTNEXTLINE\n  NonTriviallyCopyableAggregate& operator=(\n      const NonTriviallyCopyableAggregate& rhs) {\n    value = rhs.value;\n    return *this;\n  }\n\n  int value;\n};\nbool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,\n                   std::string* e) {\n  return absl::ParseFlag(src, &f->value, e);\n}\nstd::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {\n  return absl::StrCat(ntc.value);\n}\n\nbool operator==(const NonTriviallyCopyableAggregate& ntc1,\n                const NonTriviallyCopyableAggregate& ntc2) {\n  return ntc1.value == ntc2.value;\n}\n\n}  // namespace\n\nABSL_FLAG(bool, test_flag_eb_01, {}, \"\");\nABSL_FLAG(int32_t, test_flag_eb_02, {}, \"\");\nABSL_FLAG(int64_t, test_flag_eb_03, {}, \"\");\nABSL_FLAG(double, test_flag_eb_04, {}, \"\");\nABSL_FLAG(std::string, test_flag_eb_05, {}, \"\");\nABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, \"\");\n\nnamespace {\n\nTEST_F(FlagTest, TestEmptyBracesDefault) {\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),\n            \"false\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),\n            \"0\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),\n            \"0\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),\n            \"0\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),\n            \"\");\n  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),\n            \"0\");\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), \"\");\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),\n            NonTriviallyCopyableAggregate{});\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestGetSet) {\n  absl::SetFlag(&FLAGS_test_flag_01, false);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);\n\n  absl::SetFlag(&FLAGS_test_flag_02, 321);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);\n\n  absl::SetFlag(&FLAGS_test_flag_03, 67);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);\n\n  absl::SetFlag(&FLAGS_test_flag_04, 1);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);\n\n  absl::SetFlag(&FLAGS_test_flag_05, -908);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);\n\n  absl::SetFlag(&FLAGS_test_flag_06, 4001);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);\n\n  absl::SetFlag(&FLAGS_test_flag_07, -23456);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);\n\n  absl::SetFlag(&FLAGS_test_flag_08, 975310);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);\n\n  absl::SetFlag(&FLAGS_test_flag_09, 1.00001);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);\n\n  absl::SetFlag(&FLAGS_test_flag_10, -3.54f);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);\n\n  absl::SetFlag(&FLAGS_test_flag_11, \"asdf\");\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), \"asdf\");\n\n  absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));\n\n  absl::SetFlag(&FLAGS_test_flag_13, absl::MakeInt128(-1, 0));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));\n\n  absl::SetFlag(&FLAGS_test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),\n            absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestGetViaReflection) {\n#if ABSL_FLAGS_STRIP_NAMES\n  GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n  auto* handle = absl::FindCommandLineFlag(\"test_flag_01\");\n  EXPECT_EQ(*handle->TryGet<bool>(), true);\n  handle = absl::FindCommandLineFlag(\"test_flag_02\");\n  EXPECT_EQ(*handle->TryGet<int>(), 1234);\n  handle = absl::FindCommandLineFlag(\"test_flag_03\");\n  EXPECT_EQ(*handle->TryGet<int16_t>(), -34);\n  handle = absl::FindCommandLineFlag(\"test_flag_04\");\n  EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);\n  handle = absl::FindCommandLineFlag(\"test_flag_05\");\n  EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);\n  handle = absl::FindCommandLineFlag(\"test_flag_06\");\n  EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);\n  handle = absl::FindCommandLineFlag(\"test_flag_07\");\n  EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);\n  handle = absl::FindCommandLineFlag(\"test_flag_08\");\n  EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);\n  handle = absl::FindCommandLineFlag(\"test_flag_09\");\n  EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);\n  handle = absl::FindCommandLineFlag(\"test_flag_10\");\n  EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);\n  handle = absl::FindCommandLineFlag(\"test_flag_11\");\n  EXPECT_EQ(*handle->TryGet<std::string>(), \"\");\n  handle = absl::FindCommandLineFlag(\"test_flag_12\");\n  EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));\n  handle = absl::FindCommandLineFlag(\"test_flag_13\");\n  EXPECT_EQ(*handle->TryGet<absl::int128>(), absl::MakeInt128(-1, 0));\n  handle = absl::FindCommandLineFlag(\"test_flag_14\");\n  EXPECT_EQ(*handle->TryGet<absl::uint128>(),\n            absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, ConcurrentSetAndGet) {\n#if ABSL_FLAGS_STRIP_NAMES\n  GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n  static constexpr int kNumThreads = 8;\n  // Two arbitrary durations. One thread will concurrently flip the flag\n  // between these two values, while the other threads read it and verify\n  // that no other value is seen.\n  static const absl::Duration kValidDurations[] = {\n      absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),\n      absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};\n  absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);\n\n  std::atomic<bool> stop{false};\n  std::vector<std::thread> threads;\n  auto* handle = absl::FindCommandLineFlag(\"test_flag_12\");\n  for (int i = 0; i < kNumThreads; i++) {\n    threads.emplace_back([&]() {\n      while (!stop.load(std::memory_order_relaxed)) {\n        // Try loading the flag both directly and via a reflection\n        // handle.\n        absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);\n        EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);\n        v = *handle->TryGet<absl::Duration>();\n        EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);\n      }\n    });\n  }\n  absl::Time end_time = absl::Now() + absl::Seconds(1);\n  int i = 0;\n  while (absl::Now() < end_time) {\n    absl::SetFlag(&FLAGS_test_flag_12,\n                  kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);\n  }\n  stop.store(true, std::memory_order_relaxed);\n  for (auto& t : threads) t.join();\n}\n\n// --------------------------------------------------------------------\n\nint GetDflt1() { return 1; }\n\n}  // namespace\n\nABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),\n          \"test int flag non const default\");\nABSL_FLAG(std::string, test_string_flag_with_non_const_default,\n          absl::StrCat(\"AAA\", \"BBB\"), \"test string flag non const default\");\n\nnamespace {\n\nTEST_F(FlagTest, TestNonConstexprDefault) {\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),\n            \"AAABBB\");\n}\n\n// --------------------------------------------------------------------\n\n}  // namespace\n\nABSL_FLAG(bool, test_flag_with_non_const_help, true,\n          absl::StrCat(\"test \", \"flag \", \"non const help\"));\n\nnamespace {\n\n#if !ABSL_FLAGS_STRIP_HELP\nTEST_F(FlagTest, TestNonConstexprHelp) {\n  EXPECT_EQ(\n      absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),\n      \"test flag non const help\");\n}\n#endif  //! ABSL_FLAGS_STRIP_HELP\n\n// --------------------------------------------------------------------\n\nint cb_test_value = -1;\nvoid TestFlagCB();\n\n}  // namespace\n\nABSL_FLAG(int, test_flag_with_cb, 100, \"\").OnUpdate(TestFlagCB);\n\nABSL_FLAG(int, test_flag_with_lambda_cb, 200, \"\").OnUpdate([]() {\n  cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +\n                  absl::GetFlag(FLAGS_test_flag_with_cb);\n});\n\nnamespace {\n\nvoid TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }\n\n// Tests side-effects of callback invocation.\nTEST_F(FlagTest, CallbackInvocation) {\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);\n  EXPECT_EQ(cb_test_value, 300);\n\n  absl::SetFlag(&FLAGS_test_flag_with_cb, 1);\n  EXPECT_EQ(cb_test_value, 1);\n\n  absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);\n  EXPECT_EQ(cb_test_value, 4);\n}\n\n// --------------------------------------------------------------------\n\nstruct CustomUDT {\n  CustomUDT() : a(1), b(1) {}\n  CustomUDT(int a_, int b_) : a(a_), b(b_) {}\n\n  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {\n    return f1.a == f2.a && f1.b == f2.b;\n  }\n\n  int a;\n  int b;\n};\nbool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {\n  std::vector<absl::string_view> parts =\n      absl::StrSplit(in, ':', absl::SkipWhitespace());\n\n  if (parts.size() != 2) return false;\n\n  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;\n\n  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;\n\n  return true;\n}\nstd::string AbslUnparseFlag(const CustomUDT& f) {\n  return absl::StrCat(f.a, \":\", f.b);\n}\n\n}  // namespace\n\nABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), \"test flag custom UDT\");\n\nnamespace {\n\nTEST_F(FlagTest, TestCustomUDT) {\n  EXPECT_EQ(flags::StorageKind<CustomUDT>(),\n            flags::FlagValueStorageKind::kOneWordAtomic);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));\n  absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));\n}\n\n// MSVC produces link error on the type mismatch.\n// Linux does not have build errors and validations work as expected.\n#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST\nusing FlagDeathTest = FlagTest;\n\nTEST_F(FlagDeathTest, TestTypeMismatchValidations) {\n#if ABSL_FLAGS_STRIP_NAMES\n  GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n#if !defined(NDEBUG)\n  EXPECT_DEATH_IF_SUPPORTED(\n      static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),\n      \"Flag 'mistyped_int_flag' is defined as one type and declared \"\n      \"as another\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),\n      \"Flag 'mistyped_string_flag' is defined as one type and \"\n      \"declared as another\");\n#endif\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      absl::SetFlag(&FLAGS_mistyped_int_flag, 1),\n      \"Flag 'mistyped_int_flag' is defined as one type and declared \"\n      \"as another\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),\n      \"Flag 'mistyped_string_flag' is defined as one type and declared as \"\n      \"another\");\n}\n\n#endif\n\n// --------------------------------------------------------------------\n\n// A contrived type that offers implicit and explicit conversion from specific\n// source types.\nstruct ConversionTestVal {\n  ConversionTestVal() = default;\n  explicit ConversionTestVal(int a_in) : a(a_in) {}\n\n  enum class ViaImplicitConv { kTen = 10, kEleven };\n  // NOLINTNEXTLINE\n  ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}\n\n  int a;\n};\n\nbool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,\n                   std::string*) {\n  if (!absl::SimpleAtoi(in, &val_out->a)) {\n    return false;\n  }\n  return true;\n}\nstd::string AbslUnparseFlag(const ConversionTestVal& val) {\n  return absl::StrCat(val.a);\n}\n\n}  // namespace\n\n// Flag default values can be specified with a value that converts to the flag\n// value type implicitly.\nABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,\n          ConversionTestVal::ViaImplicitConv::kTen,\n          \"test flag init via implicit conversion\");\n\nnamespace {\n\nTEST_F(FlagTest, CanSetViaImplicitConversion) {\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);\n  absl::SetFlag(&FLAGS_test_flag_implicit_conv,\n                ConversionTestVal::ViaImplicitConv::kEleven);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);\n}\n\n// --------------------------------------------------------------------\n\nstruct NonDfltConstructible {\n public:\n  // This constructor tests that we can initialize the flag with int value\n  NonDfltConstructible(int i) : value(i) {}  // NOLINT\n\n  // This constructor tests that we can't initialize the flag with char value\n  // but can with explicitly constructed NonDfltConstructible.\n  explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}\n\n  int value;\n};\n\nbool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,\n                   std::string*) {\n  return absl::SimpleAtoi(in, &ndc_out->value);\n}\nstd::string AbslUnparseFlag(const NonDfltConstructible& ndc) {\n  return absl::StrCat(ndc.value);\n}\n\n}  // namespace\n\nABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),\n          \"Flag with non default constructible type\");\nABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,\n          \"Flag with non default constructible type\");\n\nnamespace {\n\nTEST_F(FlagTest, TestNonDefaultConstructibleType) {\n  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);\n  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);\n\n  absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));\n  absl::SetFlag(&FLAGS_ndc_flag2, 25);\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);\n  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);\n}\n\n}  // namespace\n\n// --------------------------------------------------------------------\n\nABSL_RETIRED_FLAG(bool, old_bool_flag, true, \"old descr\");\nABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), \"old descr\");\nABSL_RETIRED_FLAG(std::string, old_str_flag, \"\", absl::StrCat(\"old \", \"descr\"));\n\nnamespace {\n\nbool initialization_order_fiasco_test ABSL_ATTRIBUTE_UNUSED = [] {\n  // Iterate over all the flags during static initialization.\n  // This should not trigger ASan's initialization-order-fiasco.\n  auto* handle1 = absl::FindCommandLineFlag(\"flag_on_separate_file\");\n  auto* handle2 = absl::FindCommandLineFlag(\"retired_flag_on_separate_file\");\n  if (handle1 != nullptr && handle2 != nullptr) {\n    return handle1->Name() == handle2->Name();\n  }\n  return true;\n}();\n\nTEST_F(FlagTest, TestRetiredFlagRegistration) {\n  auto* handle = absl::FindCommandLineFlag(\"old_bool_flag\");\n  EXPECT_TRUE(handle->IsOfType<bool>());\n  EXPECT_TRUE(handle->IsRetired());\n  handle = absl::FindCommandLineFlag(\"old_int_flag\");\n  EXPECT_TRUE(handle->IsOfType<int>());\n  EXPECT_TRUE(handle->IsRetired());\n  handle = absl::FindCommandLineFlag(\"old_str_flag\");\n  EXPECT_TRUE(handle->IsOfType<std::string>());\n  EXPECT_TRUE(handle->IsRetired());\n}\n\n}  // namespace\n\n// --------------------------------------------------------------------\n\nnamespace {\n\n// User-defined type with small alignment, but size exceeding 16.\nstruct SmallAlignUDT {\n  SmallAlignUDT() : c('A'), s(12) {}\n  char c;\n  int16_t s;\n  char bytes[14];\n};\n\nbool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {\n  return true;\n}\nstd::string AbslUnparseFlag(const SmallAlignUDT&) { return \"\"; }\n\n}  // namespace\n\nABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, \"help\");\n\nnamespace {\n\nTEST_F(FlagTest, TestSmallAlignUDT) {\n  EXPECT_EQ(flags::StorageKind<SmallAlignUDT>(),\n            flags::FlagValueStorageKind::kSequenceLocked);\n  SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);\n  EXPECT_EQ(value.c, 'A');\n  EXPECT_EQ(value.s, 12);\n\n  value.c = 'B';\n  value.s = 45;\n  absl::SetFlag(&FLAGS_test_flag_sa_udt, value);\n  value = absl::GetFlag(FLAGS_test_flag_sa_udt);\n  EXPECT_EQ(value.c, 'B');\n  EXPECT_EQ(value.s, 45);\n}\n}  // namespace\n\n// --------------------------------------------------------------------\n\nnamespace {\n\n// User-defined not trivially copyable type.\ntemplate <int id>\nstruct NonTriviallyCopyableUDT {\n  NonTriviallyCopyableUDT() : c('A') { s_num_instance++; }\n  NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {\n    s_num_instance++;\n  }\n  NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {\n    c = rhs.c;\n    return *this;\n  }\n  ~NonTriviallyCopyableUDT() { s_num_instance--; }\n\n  static uint64_t s_num_instance;\n  char c;\n};\n\ntemplate <int id>\nuint64_t NonTriviallyCopyableUDT<id>::s_num_instance = 0;\n\ntemplate <int id>\nbool AbslParseFlag(absl::string_view txt, NonTriviallyCopyableUDT<id>* f,\n                   std::string*) {\n  f->c = txt.empty() ? '\\0' : txt[0];\n  return true;\n}\ntemplate <int id>\nstd::string AbslUnparseFlag(const NonTriviallyCopyableUDT<id>&) {\n  return \"\";\n}\n\ntemplate <int id, typename F>\nvoid TestExpectedLeaks(\n    F&& f, uint64_t num_leaks,\n    std::optional<uint64_t> num_new_instances = std::nullopt) {\n  if (!num_new_instances.has_value()) num_new_instances = num_leaks;\n\n  auto num_leaked_before = flags::NumLeakedFlagValues();\n  auto num_instances_before = NonTriviallyCopyableUDT<id>::s_num_instance;\n  f();\n  EXPECT_EQ(num_leaked_before + num_leaks, flags::NumLeakedFlagValues());\n  EXPECT_EQ(num_instances_before + num_new_instances.value(),\n            NonTriviallyCopyableUDT<id>::s_num_instance);\n}\n}  // namespace\n\nABSL_FLAG(NonTriviallyCopyableUDT<1>, test_flag_ntc_udt1, {}, \"help\");\nABSL_FLAG(NonTriviallyCopyableUDT<2>, test_flag_ntc_udt2, {}, \"help\");\nABSL_FLAG(NonTriviallyCopyableUDT<3>, test_flag_ntc_udt3, {}, \"help\");\nABSL_FLAG(NonTriviallyCopyableUDT<4>, test_flag_ntc_udt4, {}, \"help\");\nABSL_FLAG(NonTriviallyCopyableUDT<5>, test_flag_ntc_udt5, {}, \"help\");\n\nnamespace {\n\nTEST_F(FlagTest, TestNonTriviallyCopyableGetSetSet) {\n  EXPECT_EQ(flags::StorageKind<NonTriviallyCopyableUDT<1>>(),\n            flags::FlagValueStorageKind::kHeapAllocated);\n\n  TestExpectedLeaks<1>(\n      [&] {\n        NonTriviallyCopyableUDT<1> value =\n            absl::GetFlag(FLAGS_test_flag_ntc_udt1);\n        EXPECT_EQ(value.c, 'A');\n      },\n      0);\n\n  TestExpectedLeaks<1>(\n      [&] {\n        NonTriviallyCopyableUDT<1> value;\n        value.c = 'B';\n        absl::SetFlag(&FLAGS_test_flag_ntc_udt1, value);\n        EXPECT_EQ(value.c, 'B');\n      },\n      1);\n\n  TestExpectedLeaks<1>(\n      [&] {\n        NonTriviallyCopyableUDT<1> value;\n        value.c = 'C';\n        absl::SetFlag(&FLAGS_test_flag_ntc_udt1, value);\n      },\n      0);\n}\n\nTEST_F(FlagTest, TestNonTriviallyCopyableParseSet) {\n  TestExpectedLeaks<2>(\n      [&] {\n        const char* in_argv[] = {\"testbin\", \"--test_flag_ntc_udt2=A\"};\n        absl::ParseCommandLine(2, const_cast<char**>(in_argv));\n      },\n      0);\n\n  TestExpectedLeaks<2>(\n      [&] {\n        NonTriviallyCopyableUDT<2> value;\n        value.c = 'B';\n        absl::SetFlag(&FLAGS_test_flag_ntc_udt2, value);\n        EXPECT_EQ(value.c, 'B');\n      },\n      0);\n}\n\nTEST_F(FlagTest, TestNonTriviallyCopyableSet) {\n  TestExpectedLeaks<3>(\n      [&] {\n        NonTriviallyCopyableUDT<3> value;\n        value.c = 'B';\n        absl::SetFlag(&FLAGS_test_flag_ntc_udt3, value);\n        EXPECT_EQ(value.c, 'B');\n      },\n      0);\n}\n\n// One new instance created during initialization and stored in the flag.\nauto premain_utd4_get =\n    (TestExpectedLeaks<4>([] { (void)absl::GetFlag(FLAGS_test_flag_ntc_udt4); },\n                          0, 1),\n     false);\n\nTEST_F(FlagTest, TestNonTriviallyCopyableGetBeforeMainParseGet) {\n  TestExpectedLeaks<4>(\n      [&] {\n        const char* in_argv[] = {\"testbin\", \"--test_flag_ntc_udt4=C\"};\n        absl::ParseCommandLine(2, const_cast<char**>(in_argv));\n      },\n      1);\n\n  TestExpectedLeaks<4>(\n      [&] {\n        NonTriviallyCopyableUDT<4> value =\n            absl::GetFlag(FLAGS_test_flag_ntc_udt4);\n        EXPECT_EQ(value.c, 'C');\n      },\n      0);\n}\n\n// One new instance created during initialization, which is reused since it was\n// never read.\nauto premain_utd5_set = (TestExpectedLeaks<5>(\n                             [] {\n                               NonTriviallyCopyableUDT<5> value;\n                               value.c = 'B';\n                               absl::SetFlag(&FLAGS_test_flag_ntc_udt5, value);\n                             },\n                             0, 1),\n                         false);\n\nTEST_F(FlagTest, TestNonTriviallyCopyableSetParseGet) {\n  TestExpectedLeaks<5>(\n      [&] {\n        const char* in_argv[] = {\"testbin\", \"--test_flag_ntc_udt5=C\"};\n        absl::ParseCommandLine(2, const_cast<char**>(in_argv));\n      },\n      0);\n\n  TestExpectedLeaks<5>(\n      [&] {\n        NonTriviallyCopyableUDT<5> value =\n            absl::GetFlag(FLAGS_test_flag_ntc_udt5);\n        EXPECT_EQ(value.c, 'C');\n      },\n      0);\n}\n\n}  // namespace\n\n// --------------------------------------------------------------------\n\nnamespace {\n\nenum TestE { A = 1, B = 2, C = 3 };\n\nstruct EnumWrapper {\n  EnumWrapper() : e(A) {}\n\n  TestE e;\n};\n\nbool AbslParseFlag(absl::string_view, EnumWrapper*, std::string*) {\n  return true;\n}\nstd::string AbslUnparseFlag(const EnumWrapper&) { return \"\"; }\n\n}  // namespace\n\nABSL_FLAG(EnumWrapper, test_enum_wrapper_flag, {}, \"help\");\n\nTEST_F(FlagTest, TesTypeWrappingEnum) {\n  EnumWrapper value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);\n  EXPECT_EQ(value.e, A);\n\n  value.e = B;\n  absl::SetFlag(&FLAGS_test_enum_wrapper_flag, value);\n  value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);\n  EXPECT_EQ(value.e, B);\n}\n\n// This is a compile test to ensure macros are expanded within ABSL_FLAG and\n// ABSL_DECLARE_FLAG.\n#define FLAG_NAME_MACRO(name) prefix_##name\nABSL_DECLARE_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag));\nABSL_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag), 0,\n          \"Testing macro expansion within ABSL_FLAG\");\n\nTEST_F(FlagTest, MacroWithinAbslFlag) {\n  EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 0);\n  absl::SetFlag(&FLAGS_prefix_test_macro_named_flag, 1);\n  EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 1);\n}\n\n// --------------------------------------------------------------------\n\nABSL_FLAG(std::optional<bool>, optional_bool, std::nullopt, \"help\");\nABSL_FLAG(std::optional<int>, optional_int, {}, \"help\");\nABSL_FLAG(std::optional<double>, optional_double, 9.3, \"help\");\nABSL_FLAG(std::optional<std::string>, optional_string, std::nullopt, \"help\");\nABSL_FLAG(std::optional<absl::Duration>, optional_duration, std::nullopt,\n          \"help\");\nABSL_FLAG(std::optional<std::optional<int>>, optional_optional_int,\n          std::nullopt, \"help\");\n#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)\nABSL_FLAG(std::optional<int64_t>, std_optional_int64, std::nullopt, \"help\");\n#endif\n\nnamespace {\n\nTEST_F(FlagTest, TestOptionalBool) {\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), std::nullopt);\n\n  absl::SetFlag(&FLAGS_optional_bool, false);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), false);\n\n  absl::SetFlag(&FLAGS_optional_bool, true);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), true);\n\n  absl::SetFlag(&FLAGS_optional_bool, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestOptionalInt) {\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), std::nullopt);\n\n  absl::SetFlag(&FLAGS_optional_int, 0);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 0);\n\n  absl::SetFlag(&FLAGS_optional_int, 10);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 10);\n\n  absl::SetFlag(&FLAGS_optional_int, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestOptionalDouble) {\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());\n  EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 9.3);\n\n  absl::SetFlag(&FLAGS_optional_double, 0.0);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), 0.0);\n\n  absl::SetFlag(&FLAGS_optional_double, 1.234);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());\n  EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 1.234);\n\n  absl::SetFlag(&FLAGS_optional_double, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_double).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestOptionalString) {\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), std::nullopt);\n\n  // Setting optional string to \"\" leads to undefined behavior.\n\n  absl::SetFlag(&FLAGS_optional_string, \" \");\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), \" \");\n\n  absl::SetFlag(&FLAGS_optional_string, \"QWERTY\");\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), \"QWERTY\");\n\n  absl::SetFlag(&FLAGS_optional_string, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestOptionalDuration) {\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), std::nullopt);\n\n  absl::SetFlag(&FLAGS_optional_duration, absl::ZeroDuration());\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Seconds(0));\n\n  absl::SetFlag(&FLAGS_optional_duration, absl::Hours(3));\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Hours(3));\n\n  absl::SetFlag(&FLAGS_optional_duration, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagTest, TestOptionalOptional) {\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), std::nullopt);\n\n  std::optional<int> nullint{std::nullopt};\n\n  absl::SetFlag(&FLAGS_optional_optional_int, nullint);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());\n  EXPECT_NE(absl::GetFlag(FLAGS_optional_optional_int), nullint);\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int),\n            std::optional<std::optional<int>>{nullint});\n\n  absl::SetFlag(&FLAGS_optional_optional_int, 0);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);\n\n  absl::SetFlag(&FLAGS_optional_optional_int, std::optional<int>{0});\n  EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), std::optional<int>{0});\n\n  absl::SetFlag(&FLAGS_optional_optional_int, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\n#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)\n\nTEST_F(FlagTest, TestStdOptional) {\n  EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);\n\n  absl::SetFlag(&FLAGS_std_optional_int64, 0);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0);\n\n  absl::SetFlag(&FLAGS_std_optional_int64, 0xFFFFFFFFFF16);\n  EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0xFFFFFFFFFF16);\n\n  absl::SetFlag(&FLAGS_std_optional_int64, std::nullopt);\n  EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());\n  EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);\n}\n\n// --------------------------------------------------------------------\n\n#endif\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/flag_test_defs.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file is used to test the mismatch of the flag type between definition\n// and declaration. These are definitions. flag_test.cc contains declarations.\n#include <string>\n#include \"absl/flags/flag.h\"\n\nABSL_FLAG(int, mistyped_int_flag, 0, \"\");\nABSL_FLAG(std::string, mistyped_string_flag, \"\", \"\");\nABSL_FLAG(bool, flag_on_separate_file, false, \"\");\nABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, \"\");\n"
  },
  {
    "path": "absl/flags/internal/commandlineflag.cc",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/commandlineflag.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\nFlagStateInterface::~FlagStateInterface() = default;\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/internal/commandlineflag.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_\n#define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// An alias for flag fast type id. This value identifies the flag value type\n// similarly to typeid(T), without relying on RTTI being available. In most\n// cases this id is enough to uniquely identify the flag's value type. In a few\n// cases we'll have to resort to using actual RTTI implementation if it is\n// available.\nusing FlagFastTypeId = absl::FastTypeIdType;\n\n// Options that control SetCommandLineOptionWithMode.\nenum FlagSettingMode {\n  // update the flag's value unconditionally (can call this multiple times).\n  SET_FLAGS_VALUE,\n  // update the flag's value, but *only if* it has not yet been updated\n  // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or \"FLAGS_xxx = nondef\".\n  SET_FLAG_IF_DEFAULT,\n  // set the flag's default value to this.  If the flag has not been updated\n  // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or \"FLAGS_xxx = nondef\")\n  // change the flag's current value to the new default value as well.\n  SET_FLAGS_DEFAULT\n};\n\n// Options that control ParseFrom: Source of a value.\nenum ValueSource {\n  // Flag is being set by value specified on a command line.\n  kCommandLine,\n  // Flag is being set by value specified in the code.\n  kProgrammaticChange,\n};\n\n// Handle to FlagState objects. Specific flag state objects will restore state\n// of a flag produced this flag state from method CommandLineFlag::SaveState().\nclass FlagStateInterface {\n public:\n  virtual ~FlagStateInterface();\n\n  // Restores the flag originated this object to the saved state.\n  virtual void Restore() && = 0;\n};\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_\n"
  },
  {
    "path": "absl/flags/internal/flag.cc",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/flag.h\"\n\n#include <assert.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <string.h>\n\n#include <array>\n#include <atomic>\n#include <cstring>\n#include <memory>\n#include <string>\n#include <typeinfo>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// The help message indicating that the commandline flag has been stripped. It\n// will not show up when doing \"-help\" and its variants. The flag is stripped\n// if ABSL_FLAGS_STRIP_HELP is set to 1 before including absl/flags/flag.h\nconst char kStrippedFlagHelp[] = \"\\001\\002\\003\\004 (unknown) \\004\\003\\002\\001\";\n\nnamespace {\n\n// Currently we only validate flag values for user-defined flag types.\nbool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {\n#define DONT_VALIDATE(T, _) \\\n  if (flag_type_id == absl::FastTypeId<T>()) return false;\n  ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)\n#undef DONT_VALIDATE\n\n  return true;\n}\n\n// RAII helper used to temporarily unlock and relock `absl::Mutex`.\n// This is used when we need to ensure that locks are released while\n// invoking user supplied callbacks and then reacquired, since callbacks may\n// need to acquire these locks themselves.\nclass MutexRelock {\n public:\n  explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.unlock(); }\n  ~MutexRelock() { mu_.lock(); }\n\n  MutexRelock(const MutexRelock&) = delete;\n  MutexRelock& operator=(const MutexRelock&) = delete;\n\n private:\n  absl::Mutex& mu_;\n};\n\n// This is a freelist of leaked flag values and guard for its access.\n// When we can't guarantee it is safe to reuse the memory for flag values,\n// we move the memory to the freelist where it lives indefinitely, so it can\n// still be safely accessed. This also prevents leak checkers from complaining\n// about the leaked memory that can no longer be accessed through any pointer.\nabsl::Mutex& FreelistMutex() {\n  static absl::NoDestructor<absl::Mutex> mutex;\n  return *mutex;\n}\nABSL_CONST_INIT std::vector<void*>* s_freelist ABSL_GUARDED_BY(FreelistMutex())\n    ABSL_PT_GUARDED_BY(FreelistMutex()) = nullptr;\n\nvoid AddToFreelist(void* p) {\n  absl::MutexLock l(FreelistMutex());\n  if (!s_freelist) {\n    s_freelist = new std::vector<void*>;\n  }\n  s_freelist->push_back(p);\n}\n\n}  // namespace\n\n///////////////////////////////////////////////////////////////////////////////\n\nuint64_t NumLeakedFlagValues() {\n  absl::MutexLock l(FreelistMutex());\n  return s_freelist == nullptr ? 0u : s_freelist->size();\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// Persistent state of the flag data.\n\nclass FlagImpl;\n\nclass FlagState : public flags_internal::FlagStateInterface {\n public:\n  template <typename V>\n  FlagState(FlagImpl& flag_impl, const V& v, bool modified,\n            bool on_command_line, int64_t counter)\n      : flag_impl_(flag_impl),\n        value_(v),\n        modified_(modified),\n        on_command_line_(on_command_line),\n        counter_(counter) {}\n\n  ~FlagState() override {\n    if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kHeapAllocated &&\n        flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)\n      return;\n    flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);\n  }\n\n private:\n  friend class FlagImpl;\n\n  // Restores the flag to the saved state.\n  void Restore() && override {\n    if (!std::move(flag_impl_).RestoreState(*this)) return;\n\n    ABSL_INTERNAL_LOG(INFO,\n                      absl::StrCat(\"Restore saved value of \", flag_impl_.Name(),\n                                   \" to: \", flag_impl_.CurrentValue()));\n  }\n\n  // Flag and saved flag data.\n  FlagImpl& flag_impl_;\n  union SavedValue {\n    explicit SavedValue(void* v) : heap_allocated(v) {}\n    explicit SavedValue(int64_t v) : one_word(v) {}\n\n    void* heap_allocated;\n    int64_t one_word;\n  } value_;\n  bool modified_;\n  bool on_command_line_;\n  int64_t counter_;\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag implementation, which does not depend on flag value type.\n\nDynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}\n\nvoid DynValueDeleter::operator()(void* ptr) const {\n  if (op == nullptr) return;\n\n  Delete(op, ptr);\n}\n\nMaskedPointer::MaskedPointer(ptr_t rhs, bool is_candidate) : ptr_(rhs) {\n  if (is_candidate) {\n    ApplyMask(kUnprotectedReadCandidate);\n  }\n}\n\nbool MaskedPointer::IsUnprotectedReadCandidate() const {\n  return CheckMask(kUnprotectedReadCandidate);\n}\n\nbool MaskedPointer::HasBeenRead() const { return CheckMask(kHasBeenRead); }\n\nvoid MaskedPointer::Set(FlagOpFn op, const void* src, bool is_candidate) {\n  flags_internal::Copy(op, src, Ptr());\n  if (is_candidate) {\n    ApplyMask(kUnprotectedReadCandidate);\n  }\n}\nvoid MaskedPointer::MarkAsRead() { ApplyMask(kHasBeenRead); }\n\nvoid MaskedPointer::ApplyMask(mask_t mask) {\n  ptr_ = reinterpret_cast<ptr_t>(reinterpret_cast<mask_t>(ptr_) | mask);\n}\nbool MaskedPointer::CheckMask(mask_t mask) const {\n  return (reinterpret_cast<mask_t>(ptr_) & mask) != 0;\n}\n\nvoid FlagImpl::Init() {\n  new (&data_guard_) absl::Mutex;\n\n  auto def_kind = static_cast<FlagDefaultKind>(def_kind_);\n\n  switch (ValueStorageKind()) {\n    case FlagValueStorageKind::kValueAndInitBit:\n    case FlagValueStorageKind::kOneWordAtomic: {\n      alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};\n      if (def_kind == FlagDefaultKind::kGenFunc) {\n        (*default_value_.gen_func)(buf.data());\n      } else {\n        assert(def_kind != FlagDefaultKind::kDynamicValue);\n        std::memcpy(buf.data(), &default_value_, Sizeof(op_));\n      }\n      if (ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit) {\n        // We presume here the memory layout of FlagValueAndInitBit struct.\n        uint8_t initialized = 1;\n        std::memcpy(buf.data() + Sizeof(op_), &initialized,\n                    sizeof(initialized));\n      }\n      // Type can contain valid uninitialized bits, e.g. padding.\n      ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buf.data(), buf.size());\n      OneWordValue().store(absl::bit_cast<int64_t>(buf),\n                           std::memory_order_release);\n      break;\n    }\n    case FlagValueStorageKind::kSequenceLocked: {\n      // For this storage kind the default_value_ always points to gen_func\n      // during initialization.\n      assert(def_kind == FlagDefaultKind::kGenFunc);\n      (*default_value_.gen_func)(AtomicBufferValue());\n      break;\n    }\n    case FlagValueStorageKind::kHeapAllocated:\n      // For this storage kind the default_value_ always points to gen_func\n      // during initialization.\n      assert(def_kind == FlagDefaultKind::kGenFunc);\n      // Flag value initially points to the internal buffer.\n      MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);\n      (*default_value_.gen_func)(ptr_value.Ptr());\n      // Default value is a candidate for an unprotected read.\n      PtrStorage().store(MaskedPointer(ptr_value.Ptr(), true),\n                         std::memory_order_release);\n      break;\n  }\n  seq_lock_.MarkInitialized();\n}\n\nabsl::Mutex& FlagImpl::DataGuard() const {\n  absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,\n                  const_cast<FlagImpl*>(this));\n\n  // data_guard_ is initialized inside Init.\n  return *reinterpret_cast<absl::Mutex*>(&data_guard_);\n}\n\nvoid FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,\n                               const std::type_info* (*gen_rtti)()) const {\n  FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);\n\n  // `rhs_type_id` is the fast type id corresponding to the declaration\n  // visible at the call site. `lhs_type_id` is the fast type id\n  // corresponding to the type specified in flag definition. They must match\n  //  for this operation to be well-defined.\n  if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;\n\n  const std::type_info* lhs_runtime_type_id =\n      flags_internal::RuntimeTypeId(op_);\n  const std::type_info* rhs_runtime_type_id = (*gen_rtti)();\n\n  if (lhs_runtime_type_id == rhs_runtime_type_id) return;\n\n#ifdef ABSL_INTERNAL_HAS_RTTI\n  if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;\n#endif\n\n  ABSL_INTERNAL_LOG(\n      FATAL, absl::StrCat(\"Flag '\", Name(),\n                          \"' is defined as one type and declared as another\"));\n}\n\nstd::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {\n  void* res = nullptr;\n  switch (DefaultKind()) {\n    case FlagDefaultKind::kDynamicValue:\n      res = flags_internal::Clone(op_, default_value_.dynamic_value);\n      break;\n    case FlagDefaultKind::kGenFunc:\n      res = flags_internal::Alloc(op_);\n      (*default_value_.gen_func)(res);\n      break;\n    default:\n      res = flags_internal::Clone(op_, &default_value_);\n      break;\n  }\n  return {res, DynValueDeleter{op_}};\n}\n\nvoid FlagImpl::StoreValue(const void* src, ValueSource source) {\n  switch (ValueStorageKind()) {\n    case FlagValueStorageKind::kValueAndInitBit:\n    case FlagValueStorageKind::kOneWordAtomic: {\n      // Load the current value to avoid setting 'init' bit manually.\n      int64_t one_word_val = OneWordValue().load(std::memory_order_acquire);\n      std::memcpy(&one_word_val, src, Sizeof(op_));\n      OneWordValue().store(one_word_val, std::memory_order_release);\n      seq_lock_.IncrementModificationCount();\n      break;\n    }\n    case FlagValueStorageKind::kSequenceLocked: {\n      seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));\n      break;\n    }\n    case FlagValueStorageKind::kHeapAllocated:\n      MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);\n\n      if (ptr_value.IsUnprotectedReadCandidate() && ptr_value.HasBeenRead()) {\n        // If current value is a candidate for an unprotected read and if it was\n        // already read at least once, follow up reads (if any) are done without\n        // mutex protection. We can't guarantee it is safe to reuse this memory\n        // since it may have been accessed by another thread concurrently, so\n        // instead we move the memory to a freelist so it can still be safely\n        // accessed, and allocate a new one for the new value.\n        AddToFreelist(ptr_value.Ptr());\n        ptr_value = MaskedPointer(Clone(op_, src), source == kCommandLine);\n      } else {\n        // Current value either was set programmatically or was never read.\n        // We can reuse the memory since all accesses to this value (if any)\n        // were protected by mutex. That said, if a new value comes from command\n        // line it now becomes a candidate for an unprotected read.\n        ptr_value.Set(op_, src, source == kCommandLine);\n      }\n\n      PtrStorage().store(ptr_value, std::memory_order_release);\n      seq_lock_.IncrementModificationCount();\n      break;\n  }\n  modified_ = true;\n  InvokeCallback();\n}\n\nabsl::string_view FlagImpl::Name() const { return name_; }\n\nabsl::string_view FlagImpl::TypeName() const { return type_name_; }\n\nstd::string FlagImpl::Filename() const {\n  return flags_internal::GetUsageConfig().normalize_filename(filename_);\n}\n\nstd::string FlagImpl::Help() const {\n  return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal\n                                                    : help_.gen_func();\n}\n\nFlagFastTypeId FlagImpl::TypeId() const {\n  return flags_internal::FastTypeId(op_);\n}\n\nint64_t FlagImpl::ModificationCount() const {\n  return seq_lock_.ModificationCount();\n}\n\nbool FlagImpl::IsSpecifiedOnCommandLine() const {\n  absl::MutexLock l(DataGuard());\n  return on_command_line_;\n}\n\nstd::string FlagImpl::DefaultValue() const {\n  absl::MutexLock l(DataGuard());\n\n  auto obj = MakeInitValue();\n  return flags_internal::Unparse(op_, obj.get());\n}\n\nstd::string FlagImpl::CurrentValue() const {\n  auto& guard = DataGuard();  // Make sure flag initialized\n  switch (ValueStorageKind()) {\n    case FlagValueStorageKind::kValueAndInitBit:\n    case FlagValueStorageKind::kOneWordAtomic: {\n      const auto one_word_val =\n          absl::bit_cast<std::array<char, sizeof(int64_t)>>(\n              OneWordValue().load(std::memory_order_acquire));\n      return flags_internal::Unparse(op_, one_word_val.data());\n    }\n    case FlagValueStorageKind::kSequenceLocked: {\n      std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),\n                                                    DynValueDeleter{op_});\n      ReadSequenceLockedData(cloned.get());\n      return flags_internal::Unparse(op_, cloned.get());\n    }\n    case FlagValueStorageKind::kHeapAllocated: {\n      absl::MutexLock l(guard);\n      return flags_internal::Unparse(\n          op_, PtrStorage().load(std::memory_order_acquire).Ptr());\n    }\n  }\n\n  return \"\";\n}\n\nvoid FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {\n  absl::MutexLock l(DataGuard());\n\n  if (callback_ == nullptr) {\n    callback_ = new FlagCallback;\n  }\n  callback_->func = mutation_callback;\n\n  InvokeCallback();\n}\n\nvoid FlagImpl::InvokeCallback() const {\n  if (!callback_) return;\n\n  // Make a copy of the C-style function pointer that we are about to invoke\n  // before we release the lock guarding it.\n  FlagCallbackFunc cb = callback_->func;\n\n  // If the flag has a mutation callback this function invokes it. While the\n  // callback is being invoked the primary flag's mutex is unlocked and it is\n  // re-locked back after call to callback is completed. Callback invocation is\n  // guarded by flag's secondary mutex instead which prevents concurrent\n  // callback invocation. Note that it is possible for other thread to grab the\n  // primary lock and update flag's value at any time during the callback\n  // invocation. This is by design. Callback can get a value of the flag if\n  // necessary, but it might be different from the value initiated the callback\n  // and it also can be different by the time the callback invocation is\n  // completed. Requires that *primary_lock be held in exclusive mode; it may be\n  // released and reacquired by the implementation.\n  MutexRelock relock(DataGuard());\n  absl::MutexLock lock(callback_->guard);\n  cb();\n}\n\nstd::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {\n  absl::MutexLock l(DataGuard());\n\n  bool modified = modified_;\n  bool on_command_line = on_command_line_;\n  switch (ValueStorageKind()) {\n    case FlagValueStorageKind::kValueAndInitBit:\n    case FlagValueStorageKind::kOneWordAtomic: {\n      return absl::make_unique<FlagState>(\n          *this, OneWordValue().load(std::memory_order_acquire), modified,\n          on_command_line, ModificationCount());\n    }\n    case FlagValueStorageKind::kSequenceLocked: {\n      void* cloned = flags_internal::Alloc(op_);\n      // Read is guaranteed to be successful because we hold the lock.\n      bool success =\n          seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));\n      assert(success);\n      static_cast<void>(success);\n      return absl::make_unique<FlagState>(*this, cloned, modified,\n                                          on_command_line, ModificationCount());\n    }\n    case FlagValueStorageKind::kHeapAllocated: {\n      return absl::make_unique<FlagState>(\n          *this,\n          flags_internal::Clone(\n              op_, PtrStorage().load(std::memory_order_acquire).Ptr()),\n          modified, on_command_line, ModificationCount());\n    }\n  }\n  return nullptr;\n}\n\nbool FlagImpl::RestoreState(const FlagState& flag_state) {\n  absl::MutexLock l(DataGuard());\n  if (flag_state.counter_ == ModificationCount()) {\n    return false;\n  }\n\n  switch (ValueStorageKind()) {\n    case FlagValueStorageKind::kValueAndInitBit:\n    case FlagValueStorageKind::kOneWordAtomic:\n      StoreValue(&flag_state.value_.one_word, kProgrammaticChange);\n      break;\n    case FlagValueStorageKind::kSequenceLocked:\n    case FlagValueStorageKind::kHeapAllocated:\n      StoreValue(flag_state.value_.heap_allocated, kProgrammaticChange);\n      break;\n  }\n\n  modified_ = flag_state.modified_;\n  on_command_line_ = flag_state.on_command_line_;\n\n  return true;\n}\n\ntemplate <typename StorageT>\nStorageT* FlagImpl::OffsetValue() const {\n  char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));\n  // The offset is deduced via Flag value type specific op_.\n  ptrdiff_t offset = flags_internal::ValueOffset(op_);\n\n  return reinterpret_cast<StorageT*>(p + offset);\n}\n\nstd::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {\n  assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);\n  return OffsetValue<std::atomic<uint64_t>>();\n}\n\nstd::atomic<int64_t>& FlagImpl::OneWordValue() const {\n  assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||\n         ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);\n  return OffsetValue<FlagOneWordValue>()->value;\n}\n\nstd::atomic<MaskedPointer>& FlagImpl::PtrStorage() const {\n  assert(ValueStorageKind() == FlagValueStorageKind::kHeapAllocated);\n  return OffsetValue<FlagMaskedPointerValue>()->value;\n}\n\n// Attempts to parse supplied `value` string using parsing routine in the `flag`\n// argument. If parsing successful, this function replaces the dst with newly\n// parsed value. In case if any error is encountered in either step, the error\n// message is stored in 'err'\nstd::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(\n    absl::string_view value, std::string& err) const {\n  std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();\n\n  std::string parse_err;\n  if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {\n    absl::string_view err_sep = parse_err.empty() ? \"\" : \"; \";\n    err = absl::StrCat(\"Illegal value '\", value, \"' specified for flag '\",\n                       Name(), \"'\", err_sep, parse_err);\n    return nullptr;\n  }\n\n  return tentative_value;\n}\n\nvoid FlagImpl::Read(void* dst) const {\n  auto& guard = DataGuard();  // Make sure flag initialized\n  switch (ValueStorageKind()) {\n    case FlagValueStorageKind::kValueAndInitBit:\n    case FlagValueStorageKind::kOneWordAtomic: {\n      const int64_t one_word_val =\n          OneWordValue().load(std::memory_order_acquire);\n      std::memcpy(dst, &one_word_val, Sizeof(op_));\n      break;\n    }\n    case FlagValueStorageKind::kSequenceLocked: {\n      ReadSequenceLockedData(dst);\n      break;\n    }\n    case FlagValueStorageKind::kHeapAllocated: {\n      absl::MutexLock l(guard);\n      MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);\n\n      flags_internal::CopyConstruct(op_, ptr_value.Ptr(), dst);\n\n      // For unprotected read candidates, mark that the value as has been read.\n      if (ptr_value.IsUnprotectedReadCandidate() && !ptr_value.HasBeenRead()) {\n        ptr_value.MarkAsRead();\n        PtrStorage().store(ptr_value, std::memory_order_release);\n      }\n      break;\n    }\n  }\n}\n\nint64_t FlagImpl::ReadOneWord() const {\n  assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||\n         ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);\n  auto& guard = DataGuard();  // Make sure flag initialized\n  (void)guard;\n  return OneWordValue().load(std::memory_order_acquire);\n}\n\nbool FlagImpl::ReadOneBool() const {\n  assert(ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);\n  auto& guard = DataGuard();  // Make sure flag initialized\n  (void)guard;\n  return absl::bit_cast<FlagValueAndInitBit<bool>>(\n             OneWordValue().load(std::memory_order_acquire))\n      .value;\n}\n\nvoid FlagImpl::ReadSequenceLockedData(void* dst) const {\n  size_t size = Sizeof(op_);\n  // Attempt to read using the sequence lock.\n  if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {\n    return;\n  }\n  // We failed due to contention. Acquire the lock to prevent contention\n  // and try again.\n  absl::ReaderMutexLock l(DataGuard());\n  bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);\n  assert(success);\n  static_cast<void>(success);\n}\n\nvoid FlagImpl::Write(const void* src) {\n  absl::MutexLock l(DataGuard());\n\n  if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {\n    std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),\n                                               DynValueDeleter{op_}};\n    std::string ignored_error;\n    std::string src_as_str = flags_internal::Unparse(op_, src);\n    if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {\n      ABSL_INTERNAL_LOG(ERROR, absl::StrCat(\"Attempt to set flag '\", Name(),\n                                            \"' to invalid value \", src_as_str));\n    }\n  }\n\n  StoreValue(src, kProgrammaticChange);\n}\n\n// Sets the value of the flag based on specified string `value`. If the flag\n// was successfully set to new value, it returns true. Otherwise, sets `err`\n// to indicate the error, leaves the flag unchanged, and returns false. There\n// are three ways to set the flag's value:\n//  * Update the current flag value\n//  * Update the flag's default value\n//  * Update the current flag value if it was never set before\n// The mode is selected based on 'set_mode' parameter.\nbool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,\n                         ValueSource source, std::string& err) {\n  absl::MutexLock l(DataGuard());\n\n  switch (set_mode) {\n    case SET_FLAGS_VALUE: {\n      // set or modify the flag's value\n      auto tentative_value = TryParse(value, err);\n      if (!tentative_value) return false;\n\n      StoreValue(tentative_value.get(), source);\n\n      if (source == kCommandLine) {\n        on_command_line_ = true;\n      }\n      break;\n    }\n    case SET_FLAG_IF_DEFAULT: {\n      // set the flag's value, but only if it hasn't been set by someone else\n      if (modified_) {\n        // TODO(rogeeff): review and fix this semantic. Currently we do not fail\n        // in this case if flag is modified. This is misleading since the flag's\n        // value is not updated even though we return true.\n        // *err = absl::StrCat(Name(), \" is already set to \",\n        //                     CurrentValue(), \"\\n\");\n        // return false;\n        return true;\n      }\n      auto tentative_value = TryParse(value, err);\n      if (!tentative_value) return false;\n\n      StoreValue(tentative_value.get(), source);\n      break;\n    }\n    case SET_FLAGS_DEFAULT: {\n      auto tentative_value = TryParse(value, err);\n      if (!tentative_value) return false;\n\n      if (DefaultKind() == FlagDefaultKind::kDynamicValue) {\n        void* old_value = default_value_.dynamic_value;\n        default_value_.dynamic_value = tentative_value.release();\n        tentative_value.reset(old_value);\n      } else {\n        default_value_.dynamic_value = tentative_value.release();\n        def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);\n      }\n\n      if (!modified_) {\n        // Need to set both default value *and* current, in this case.\n        StoreValue(default_value_.dynamic_value, source);\n        modified_ = false;\n      }\n      break;\n    }\n  }\n\n  return true;\n}\n\nvoid FlagImpl::CheckDefaultValueParsingRoundtrip() const {\n  std::string v = DefaultValue();\n\n  absl::MutexLock lock(DataGuard());\n\n  auto dst = MakeInitValue();\n  std::string error;\n  if (!flags_internal::Parse(op_, v, dst.get(), &error)) {\n    ABSL_INTERNAL_LOG(\n        FATAL,\n        absl::StrCat(\"Flag \", Name(), \" (from \", Filename(),\n                     \"): string form of default value '\", v,\n                     \"' could not be parsed; error=\", error));\n  }\n\n  // We do not compare dst to def since parsing/unparsing may make\n  // small changes, e.g., precision loss for floating point types.\n}\n\nbool FlagImpl::ValidateInputValue(absl::string_view value) const {\n  absl::MutexLock l(DataGuard());\n\n  auto obj = MakeInitValue();\n  std::string ignored_error;\n  return flags_internal::Parse(op_, value, obj.get(), &ignored_error);\n}\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/internal/flag.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_FLAG_H_\n#define ABSL_FLAGS_INTERNAL_FLAG_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <atomic>\n#include <cstring>\n#include <memory>\n#include <string>\n#include <type_traits>\n#include <typeinfo>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/flags/internal/registry.h\"\n#include \"absl/flags/internal/sequence_lock.h\"\n#include \"absl/flags/marshalling.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n///////////////////////////////////////////////////////////////////////////////\n// Forward declaration of absl::Flag<T> public API.\nnamespace flags_internal {\ntemplate <typename T>\nclass Flag;\n}  // namespace flags_internal\n\ntemplate <typename T>\nusing Flag = flags_internal::Flag<T>;\n\ntemplate <typename T>\n[[nodiscard]] T GetFlag(const absl::Flag<T>& flag);\n\ntemplate <typename T>\nvoid SetFlag(absl::Flag<T>* flag, const T& v);\n\ntemplate <typename T, typename V>\nvoid SetFlag(absl::Flag<T>* flag, const V& v);\n\ntemplate <typename U>\nconst CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag value type operations, eg., parsing, copying, etc. are provided\n// by function specific to that type with a signature matching FlagOpFn.\n\nnamespace flags_internal {\n\nenum class FlagOp {\n  kAlloc,\n  kDelete,\n  kCopy,\n  kCopyConstruct,\n  kSizeof,\n  kFastTypeId,\n  kRuntimeTypeId,\n  kParse,\n  kUnparse,\n  kValueOffset,\n};\nusing FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);\n\n// Forward declaration for Flag value specific operations.\ntemplate <typename T>\nvoid* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);\n\n// Allocate aligned memory for a flag value.\ninline void* Alloc(FlagOpFn op) {\n  return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);\n}\n// Deletes memory interpreting obj as flag value type pointer.\ninline void Delete(FlagOpFn op, void* obj) {\n  op(FlagOp::kDelete, nullptr, obj, nullptr);\n}\n// Copies src to dst interpreting as flag value type pointers.\ninline void Copy(FlagOpFn op, const void* src, void* dst) {\n  op(FlagOp::kCopy, src, dst, nullptr);\n}\n// Construct a copy of flag value in a location pointed by dst\n// based on src - pointer to the flag's value.\ninline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {\n  op(FlagOp::kCopyConstruct, src, dst, nullptr);\n}\n// Makes a copy of flag value pointed by obj.\ninline void* Clone(FlagOpFn op, const void* obj) {\n  void* res = flags_internal::Alloc(op);\n  flags_internal::CopyConstruct(op, obj, res);\n  return res;\n}\n// Returns true if parsing of input text is successful.\ninline bool Parse(FlagOpFn op, absl::string_view text, void* dst,\n                  std::string* error) {\n  return op(FlagOp::kParse, &text, dst, error) != nullptr;\n}\n// Returns string representing supplied value.\ninline std::string Unparse(FlagOpFn op, const void* val) {\n  std::string result;\n  op(FlagOp::kUnparse, val, &result, nullptr);\n  return result;\n}\n// Returns size of flag value type.\ninline size_t Sizeof(FlagOpFn op) {\n  // This sequence of casts reverses the sequence from\n  // `flags_internal::FlagOps()`\n  return static_cast<size_t>(reinterpret_cast<intptr_t>(\n      op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));\n}\n// Returns fast type id corresponding to the value type.\ninline FlagFastTypeId FastTypeId(FlagOpFn op) {\n  return absl::bit_cast<FlagFastTypeId>(\n      op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));\n}\n// Returns fast type id corresponding to the value type.\ninline const std::type_info* RuntimeTypeId(FlagOpFn op) {\n  return reinterpret_cast<const std::type_info*>(\n      op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));\n}\n// Returns offset of the field value_ from the field impl_ inside of\n// absl::Flag<T> data. Given FlagImpl pointer p you can get the\n// location of the corresponding value as:\n//      reinterpret_cast<char*>(p) + ValueOffset().\ninline ptrdiff_t ValueOffset(FlagOpFn op) {\n  // This sequence of casts reverses the sequence from\n  // `flags_internal::FlagOps()`\n  return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(\n      op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));\n}\n\n// Returns an address of RTTI's typeid(T).\ntemplate <typename T>\ninline const std::type_info* GenRuntimeTypeId() {\n#ifdef ABSL_INTERNAL_HAS_RTTI\n  return &typeid(T);\n#else\n  return nullptr;\n#endif\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag help auxiliary structs.\n\n// This is help argument for absl::Flag encapsulating the string literal pointer\n// or pointer to function generating it as well as enum discriminating two\n// cases.\nusing HelpGenFunc = std::string (*)();\n\ntemplate <size_t N>\nstruct FixedCharArray {\n  char value[N];\n\n  template <size_t... I>\n  static constexpr FixedCharArray<N> FromLiteralString(\n      absl::string_view str, absl::index_sequence<I...>) {\n    return (void)str, FixedCharArray<N>({{str[I]..., '\\0'}});\n  }\n};\n\ntemplate <typename Gen, size_t N = Gen::Value().size()>\nconstexpr FixedCharArray<N + 1> HelpStringAsArray(int) {\n  return FixedCharArray<N + 1>::FromLiteralString(\n      Gen::Value(), absl::make_index_sequence<N>{});\n}\n\ntemplate <typename Gen>\nconstexpr std::false_type HelpStringAsArray(char) {\n  return std::false_type{};\n}\n\nunion FlagHelpMsg {\n  constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}\n  constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}\n\n  const char* literal;\n  HelpGenFunc gen_func;\n};\n\nenum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };\n\nstruct FlagHelpArg {\n  FlagHelpMsg source;\n  FlagHelpKind kind;\n};\n\nextern const char kStrippedFlagHelp[];\n\n// These two HelpArg overloads allows us to select at compile time one of two\n// way to pass Help argument to absl::Flag. We'll be passing\n// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer\n// first overload if possible. If help message is evaluatable on constexpr\n// context We'll be able to make FixedCharArray out of it and we'll choose first\n// overload. In this case the help message expression is immediately evaluated\n// and is used to construct the absl::Flag. No additional code is generated by\n// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the\n// consideration, in which case the second overload will be used. The second\n// overload does not attempt to evaluate the help message expression\n// immediately and instead delays the evaluation by returning the function\n// pointer (&T::NonConst) generating the help message when necessary. This is\n// evaluatable in constexpr context, but the cost is an extra function being\n// generated in the ABSL_FLAG code.\ntemplate <typename Gen, size_t N>\nconstexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {\n  return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};\n}\n\ntemplate <typename Gen>\nconstexpr FlagHelpArg HelpArg(std::false_type) {\n  return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag default value auxiliary structs.\n\n// Signature for the function generating the initial flag value (usually\n// based on default value supplied in flag's definition)\nusing FlagDfltGenFunc = void (*)(void*);\n\nunion FlagDefaultSrc {\n  constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)\n      : gen_func(gen_func_arg) {}\n\n#define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \\\n  T name##_value;                                  \\\n  constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {}  // NOLINT\n  ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)\n#undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE\n\n  void* dynamic_value;\n  FlagDfltGenFunc gen_func;\n};\n\nenum class FlagDefaultKind : uint8_t {\n  kDynamicValue = 0,\n  kGenFunc = 1,\n  kOneWord = 2  // for default values UP to one word in size\n};\n\nstruct FlagDefaultArg {\n  FlagDefaultSrc source;\n  FlagDefaultKind kind;\n};\n\n// This struct and corresponding overload to InitDefaultValue are used to\n// facilitate usage of {} as default value in ABSL_FLAG macro.\n// TODO(rogeeff): Fix handling types with explicit constructors.\nstruct EmptyBraces {};\n\ntemplate <typename T>\nconstexpr T InitDefaultValue(T t) {\n  return t;\n}\n\ntemplate <typename T>\nconstexpr T InitDefaultValue(EmptyBraces) {\n  return T{};\n}\n\ntemplate <typename ValueT, typename GenT,\n          typename std::enable_if<std::is_integral<ValueT>::value, int>::type =\n              ((void)GenT{}, 0)>\nconstexpr FlagDefaultArg DefaultArg(int) {\n  return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};\n}\n\ntemplate <typename ValueT, typename GenT>\nconstexpr FlagDefaultArg DefaultArg(char) {\n  return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag storage selector traits. Each trait indicates what kind of storage kind\n// to use for the flag value.\n\ntemplate <typename T>\nusing FlagUseValueAndInitBitStorage =\n    std::integral_constant<bool, std::is_trivially_copyable<T>::value &&\n                                     std::is_default_constructible<T>::value &&\n                                     (sizeof(T) < 8)>;\n\ntemplate <typename T>\nusing FlagUseOneWordStorage =\n    std::integral_constant<bool, std::is_trivially_copyable<T>::value &&\n                                     (sizeof(T) <= 8)>;\n\ntemplate <class T>\nusing FlagUseSequenceLockStorage =\n    std::integral_constant<bool, std::is_trivially_copyable<T>::value &&\n                                     (sizeof(T) > 8)>;\n\nenum class FlagValueStorageKind : uint8_t {\n  kValueAndInitBit = 0,\n  kOneWordAtomic = 1,\n  kSequenceLocked = 2,\n  kHeapAllocated = 3,\n};\n\n// This constexpr function returns the storage kind for the given flag value\n// type.\ntemplate <typename T>\nstatic constexpr FlagValueStorageKind StorageKind() {\n  return FlagUseValueAndInitBitStorage<T>::value\n             ? FlagValueStorageKind::kValueAndInitBit\n         : FlagUseOneWordStorage<T>::value\n             ? FlagValueStorageKind::kOneWordAtomic\n         : FlagUseSequenceLockStorage<T>::value\n             ? FlagValueStorageKind::kSequenceLocked\n             : FlagValueStorageKind::kHeapAllocated;\n}\n\n// This is a base class for the storage classes used by kOneWordAtomic and\n// kValueAndInitBit storage kinds. It literally just stores the one word value\n// as an atomic. By default, it is initialized to a magic value that is unlikely\n// a valid value for the flag value type.\nstruct FlagOneWordValue {\n  constexpr static int64_t Uninitialized() {\n    return static_cast<int64_t>(0xababababababababll);\n  }\n\n  constexpr FlagOneWordValue() : value(Uninitialized()) {}\n  constexpr explicit FlagOneWordValue(int64_t v) : value(v) {}\n  std::atomic<int64_t> value;\n};\n\n// This class represents a memory layout used by kValueAndInitBit storage kind.\ntemplate <typename T>\nstruct alignas(8) FlagValueAndInitBit {\n  T value;\n  // Use an int instead of a bool to guarantee that a non-zero value has\n  // a bit set.\n  uint8_t init;\n};\n\n// This class implements an aligned pointer with two options stored via masks\n// in unused bits of the pointer value (due to alignment requirement).\n//  - IsUnprotectedReadCandidate - indicates that the value can be switched to\n//    unprotected read without a lock.\n//  - HasBeenRead - indicates that the value has been read at least once.\n//  - AllowsUnprotectedRead - combination of the two options above and indicates\n//    that the value can now be read without a lock.\n// Further details of these options and their use is covered in the description\n// of the FlagValue<T, FlagValueStorageKind::kHeapAllocated> specialization.\nclass MaskedPointer {\n public:\n  using mask_t = uintptr_t;\n  using ptr_t = void*;\n\n  static constexpr int RequiredAlignment() { return 4; }\n\n  constexpr MaskedPointer() : ptr_(nullptr) {}\n  constexpr explicit MaskedPointer(ptr_t rhs) : ptr_(rhs) {}\n  MaskedPointer(ptr_t rhs, bool is_candidate);\n\n  MaskedPointer(const MaskedPointer& rhs) = default;\n  MaskedPointer& operator=(const MaskedPointer& rhs) = default;\n\n  void* Ptr() const {\n    return reinterpret_cast<void*>(reinterpret_cast<mask_t>(ptr_) &\n                                   kPtrValueMask);\n  }\n  bool AllowsUnprotectedRead() const {\n    return (reinterpret_cast<mask_t>(ptr_) & kAllowsUnprotectedRead) ==\n           kAllowsUnprotectedRead;\n  }\n  bool IsUnprotectedReadCandidate() const;\n  bool HasBeenRead() const;\n\n  void Set(FlagOpFn op, const void* src, bool is_candidate);\n  void MarkAsRead();\n\n private:\n  // Masks\n  // Indicates that the flag value either default or originated from command\n  // line.\n  static constexpr mask_t kUnprotectedReadCandidate = 0x1u;\n  // Indicates that flag has been read.\n  static constexpr mask_t kHasBeenRead = 0x2u;\n  static constexpr mask_t kAllowsUnprotectedRead =\n      kUnprotectedReadCandidate | kHasBeenRead;\n  static constexpr mask_t kPtrValueMask = ~kAllowsUnprotectedRead;\n\n  void ApplyMask(mask_t mask);\n  bool CheckMask(mask_t mask) const;\n\n  ptr_t ptr_;\n};\n\n// This class implements a type erased storage of the heap allocated flag value.\n// It is used as a base class for the storage class for kHeapAllocated storage\n// kind. The initial_buffer is expected to have an alignment of at least\n// MaskedPointer::RequiredAlignment(), so that the bits used by the\n// MaskedPointer to store masks are set to 0. This guarantees that value starts\n// in an uninitialized state.\nstruct FlagMaskedPointerValue {\n  constexpr explicit FlagMaskedPointerValue(MaskedPointer::ptr_t initial_buffer)\n      : value(MaskedPointer(initial_buffer)) {}\n\n  std::atomic<MaskedPointer> value;\n};\n\n// This is the forward declaration for the template that represents a storage\n// for the flag values. This template is expected to be explicitly specialized\n// for each storage kind and it does not have a generic default\n// implementation.\ntemplate <typename T,\n          FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>\nstruct FlagValue;\n\n// This specialization represents the storage of flag values types with the\n// kValueAndInitBit storage kind. It is based on the FlagOneWordValue class\n// and relies on memory layout in FlagValueAndInitBit<T> to indicate that the\n// value has been initialized or not.\ntemplate <typename T>\nstruct FlagValue<T, FlagValueStorageKind::kValueAndInitBit> : FlagOneWordValue {\n  constexpr FlagValue() : FlagOneWordValue(0) {}\n  bool Get(const SequenceLock&, T& dst) const {\n    int64_t storage = value.load(std::memory_order_acquire);\n    if (ABSL_PREDICT_FALSE(storage == 0)) {\n      // This assert is to ensure that the initialization inside FlagImpl::Init\n      // is able to set init member correctly.\n      static_assert(offsetof(FlagValueAndInitBit<T>, init) == sizeof(T),\n                    \"Unexpected memory layout of FlagValueAndInitBit\");\n      return false;\n    }\n    dst = absl::bit_cast<FlagValueAndInitBit<T>>(storage).value;\n    return true;\n  }\n};\n\n// This specialization represents the storage of flag values types with the\n// kOneWordAtomic storage kind. It is based on the FlagOneWordValue class\n// and relies on the magic uninitialized state of default constructed instead of\n// FlagOneWordValue to indicate that the value has been initialized or not.\ntemplate <typename T>\nstruct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {\n  constexpr FlagValue() : FlagOneWordValue() {}\n  bool Get(const SequenceLock&, T& dst) const {\n    int64_t one_word_val = value.load(std::memory_order_acquire);\n    if (ABSL_PREDICT_FALSE(one_word_val == FlagOneWordValue::Uninitialized())) {\n      return false;\n    }\n    std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));\n    return true;\n  }\n};\n\n// This specialization represents the storage of flag values types with the\n// kSequenceLocked storage kind. This storage is used by trivially copyable\n// types with size greater than 8 bytes. This storage relies on uninitialized\n// state of the SequenceLock to indicate that the value has been initialized or\n// not. This storage also provides lock-free read access to the underlying\n// value once it is initialized.\ntemplate <typename T>\nstruct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {\n  bool Get(const SequenceLock& lock, T& dst) const {\n    return lock.TryRead(&dst, value_words, sizeof(T));\n  }\n\n  static constexpr int kNumWords =\n      flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);\n\n  alignas(T) alignas(\n      std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];\n};\n\n// This specialization represents the storage of flag values types with the\n// kHeapAllocated storage kind. This is a storage of last resort and is used\n// if none of other storage kinds are applicable.\n//\n// Generally speaking the values with this storage kind can't be accessed\n// atomically and thus can't be read without holding a lock. If we would ever\n// want to avoid the lock, we'd need to leak the old value every time new flag\n// value is being set (since we are in danger of having a race condition\n// otherwise).\n//\n// Instead of doing that, this implementation attempts to cater to some common\n// use cases by allowing at most 2 values to be leaked - default value and\n// value set from the command line.\n//\n// This specialization provides an initial buffer for the first flag value. This\n// is where the default value is going to be stored. We attempt to reuse this\n// buffer if possible, including storing the value set from the command line\n// there.\n//\n// As long as we only read this value, we can access it without a lock (in\n// practice we still use the lock for the very first read to be able set\n// \"has been read\" option on this flag).\n//\n// If flag is specified on the command line we store the parsed value either\n// in the internal buffer (if the default value never been read) or we leak the\n// default value and allocate the new storage for the parse value. This value is\n// also a candidate for an unprotected read. If flag is set programmatically\n// after the command line is parsed, the storage for this value is going to be\n// leaked. Note that in both scenarios we are not going to have a real leak.\n// Instead we'll store the leaked value pointers in the internal freelist to\n// avoid triggering the memory leak checker complains.\n//\n// If the flag is ever set programmatically, it stops being the candidate for an\n// unprotected read, and any follow up access to the flag value requires a lock.\n// Note that if the value if set programmatically before the command line is\n// parsed, we can switch back to enabling unprotected reads for that value.\ntemplate <typename T>\nstruct FlagValue<T, FlagValueStorageKind::kHeapAllocated>\n    : FlagMaskedPointerValue {\n  // We const initialize the value with unmasked pointer to the internal buffer,\n  // making sure it is not a candidate for unprotected read. This way we can\n  // ensure Init is done before any access to the flag value.\n  constexpr FlagValue() : FlagMaskedPointerValue(&buffer[0]) {}\n\n  bool Get(const SequenceLock&, T& dst) const {\n    MaskedPointer ptr_value = value.load(std::memory_order_acquire);\n\n    if (ABSL_PREDICT_TRUE(ptr_value.AllowsUnprotectedRead())) {\n      ::new (static_cast<void*>(&dst)) T(*static_cast<T*>(ptr_value.Ptr()));\n      return true;\n    }\n    return false;\n  }\n\n  alignas(MaskedPointer::RequiredAlignment()) alignas(\n      T) char buffer[sizeof(T)]{};\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag callback auxiliary structs.\n\n// Signature for the mutation callback used by watched Flags\n// The callback is noexcept.\n// TODO(rogeeff): add noexcept after C++17 support is added.\nusing FlagCallbackFunc = void (*)();\n\nstruct FlagCallback {\n  FlagCallbackFunc func;\n  absl::Mutex guard;  // Guard for concurrent callback invocations.\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Flag implementation, which does not depend on flag value type.\n// The class encapsulates the Flag's data and access to it.\n\nstruct DynValueDeleter {\n  explicit DynValueDeleter(FlagOpFn op_arg = nullptr);\n  void operator()(void* ptr) const;\n\n  FlagOpFn op;\n};\n\nclass FlagState;\n\n// These are only used as constexpr global objects.\n// They do not use a virtual destructor to simplify their implementation.\n// They are not destroyed except at program exit, so leaks do not matter.\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wnon-virtual-dtor\"\n#endif\nclass FlagImpl final : public CommandLineFlag {\n public:\n  constexpr FlagImpl(const char* name, const char* type_name,\n                     const char* filename, FlagOpFn op, FlagHelpArg help,\n                     FlagValueStorageKind value_kind,\n                     FlagDefaultArg default_arg)\n      : name_(name),\n        type_name_(type_name),\n        filename_(filename),\n        op_(op),\n        help_(help.source),\n        help_source_kind_(static_cast<uint8_t>(help.kind)),\n        value_storage_kind_(static_cast<uint8_t>(value_kind)),\n        def_kind_(static_cast<uint8_t>(default_arg.kind)),\n        modified_(false),\n        on_command_line_(false),\n        callback_(nullptr),\n        default_value_(default_arg.source),\n        data_guard_{} {}\n\n  // Constant access methods\n  int64_t ReadOneWord() const ABSL_LOCKS_EXCLUDED(DataGuard());\n  bool ReadOneBool() const ABSL_LOCKS_EXCLUDED(DataGuard());\n  void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(DataGuard());\n  void Read(bool* value) const ABSL_LOCKS_EXCLUDED(DataGuard()) {\n    *value = ReadOneBool();\n  }\n  template <typename T,\n            absl::enable_if_t<flags_internal::StorageKind<T>() ==\n                                  FlagValueStorageKind::kOneWordAtomic,\n                              int> = 0>\n  void Read(T* value) const ABSL_LOCKS_EXCLUDED(DataGuard()) {\n    int64_t v = ReadOneWord();\n    std::memcpy(value, static_cast<const void*>(&v), sizeof(T));\n  }\n  template <typename T,\n            typename std::enable_if<flags_internal::StorageKind<T>() ==\n                                        FlagValueStorageKind::kValueAndInitBit,\n                                    int>::type = 0>\n  void Read(T* value) const ABSL_LOCKS_EXCLUDED(DataGuard()) {\n    *value = absl::bit_cast<FlagValueAndInitBit<T>>(ReadOneWord()).value;\n  }\n\n  // Mutating access methods\n  void Write(const void* src) ABSL_LOCKS_EXCLUDED(DataGuard());\n\n  // Interfaces to operate on callbacks.\n  void SetCallback(const FlagCallbackFunc mutation_callback)\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n  void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(DataGuard());\n\n  // Used in read/write operations to validate source/target has correct type.\n  // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to\n  // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed\n  // int. To do that we pass the assumed type id (which is deduced from type\n  // int) as an argument `type_id`, which is in turn is validated against the\n  // type id stored in flag object by flag definition statement.\n  void AssertValidType(FlagFastTypeId type_id,\n                       const std::type_info* (*gen_rtti)()) const;\n\n private:\n  template <typename T>\n  friend class Flag;\n  friend class FlagState;\n\n  // Ensures that `data_guard_` is initialized and returns it.\n  absl::Mutex& DataGuard() const\n      ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));\n  // Returns heap allocated value of type T initialized with default value.\n  std::unique_ptr<void, DynValueDeleter> MakeInitValue() const\n      ABSL_EXCLUSIVE_LOCKS_REQUIRED(DataGuard());\n  // Flag initialization called via absl::call_once.\n  void Init();\n\n  // Offset value access methods. One per storage kind. These methods to not\n  // respect const correctness, so be very careful using them.\n\n  // This is a shared helper routine which encapsulates most of the magic. Since\n  // it is only used inside the three routines below, which are defined in\n  // flag.cc, we can define it in that file as well.\n  template <typename StorageT>\n  StorageT* OffsetValue() const;\n\n  // The same as above, but used for sequencelock-protected storage.\n  std::atomic<uint64_t>* AtomicBufferValue() const;\n\n  // This is an accessor for a value stored as one word atomic. Returns a\n  // mutable reference to an atomic value.\n  std::atomic<int64_t>& OneWordValue() const;\n\n  std::atomic<MaskedPointer>& PtrStorage() const;\n\n  // Attempts to parse supplied `value` string. If parsing is successful,\n  // returns new value. Otherwise returns nullptr.\n  std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,\n                                                  std::string& err) const\n      ABSL_EXCLUSIVE_LOCKS_REQUIRED(DataGuard());\n  // Stores the flag value based on the pointer to the source.\n  void StoreValue(const void* src, ValueSource source)\n      ABSL_EXCLUSIVE_LOCKS_REQUIRED(DataGuard());\n\n  // Copy the flag data, protected by `seq_lock_` into `dst`.\n  //\n  // REQUIRES: ValueStorageKind() == kSequenceLocked.\n  void ReadSequenceLockedData(void* dst) const ABSL_LOCKS_EXCLUDED(DataGuard());\n\n  FlagHelpKind HelpSourceKind() const {\n    return static_cast<FlagHelpKind>(help_source_kind_);\n  }\n  FlagValueStorageKind ValueStorageKind() const {\n    return static_cast<FlagValueStorageKind>(value_storage_kind_);\n  }\n  FlagDefaultKind DefaultKind() const\n      ABSL_EXCLUSIVE_LOCKS_REQUIRED(DataGuard()) {\n    return static_cast<FlagDefaultKind>(def_kind_);\n  }\n\n  // CommandLineFlag interface implementation\n  absl::string_view Name() const override;\n  absl::string_view TypeName() const override;\n  std::string Filename() const override;\n  std::string Help() const override;\n  FlagFastTypeId TypeId() const override;\n  bool IsSpecifiedOnCommandLine() const override\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n  std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(DataGuard());\n  std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(DataGuard());\n  bool ValidateInputValue(absl::string_view value) const override\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n  void CheckDefaultValueParsingRoundtrip() const override\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n\n  int64_t ModificationCount() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(DataGuard());\n\n  // Interfaces to save and restore flags to/from persistent state.\n  // Returns current flag state or nullptr if flag does not support\n  // saving and restoring a state.\n  std::unique_ptr<FlagStateInterface> SaveState() override\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n\n  // Restores the flag state to the supplied state object. If there is\n  // nothing to restore returns false. Otherwise returns true.\n  bool RestoreState(const FlagState& flag_state)\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n\n  bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,\n                 ValueSource source, std::string& error) override\n      ABSL_LOCKS_EXCLUDED(DataGuard());\n\n  // Immutable flag's state.\n\n  // Flags name passed to ABSL_FLAG as second arg.\n  const char* const name_;\n\n  // Flags type passed to ABSL_FLAG as first arg.\n  const char* const type_name_;\n\n  // The file name where ABSL_FLAG resides.\n  const char* const filename_;\n  // Type-specific operations vtable.\n  const FlagOpFn op_;\n  // Help message literal or function to generate it.\n  const FlagHelpMsg help_;\n  // Indicates if help message was supplied as literal or generator func.\n  const uint8_t help_source_kind_ : 1;\n  // Kind of storage this flag is using for the flag's value.\n  const uint8_t value_storage_kind_ : 2;\n\n  uint8_t : 0;  // The bytes containing the const bitfields must not be\n                // shared with bytes containing the mutable bitfields.\n\n  // Mutable flag's state (guarded by `data_guard_`).\n\n  // def_kind_ is not guard by DataGuard() since it is accessed in Init without\n  // locks.\n  uint8_t def_kind_ : 2;\n  // Has this flag's value been modified?\n  bool modified_ : 1 ABSL_GUARDED_BY(DataGuard());\n  // Has this flag been specified on command line.\n  bool on_command_line_ : 1 ABSL_GUARDED_BY(DataGuard());\n\n  // Unique tag for absl::call_once call to initialize this flag.\n  absl::once_flag init_control_;\n\n  // Sequence lock / mutation counter.\n  flags_internal::SequenceLock seq_lock_;\n\n  // Optional flag's callback and absl::Mutex to guard the invocations.\n  FlagCallback* callback_ ABSL_GUARDED_BY(DataGuard());\n  // Either a pointer to the function generating the default value based on the\n  // value specified in ABSL_FLAG or pointer to the dynamically set default\n  // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish\n  // these two cases.\n  FlagDefaultSrc default_value_;\n\n  // This is reserved space for an absl::Mutex to guard flag data. It will be\n  // initialized in FlagImpl::Init via placement new.\n  // We can't use \"absl::Mutex data_guard_\", since this class is not literal.\n  // We do not want to use \"absl::Mutex* data_guard_\", since this would require\n  // heap allocation during initialization, which is both slows program startup\n  // and can fail. Using reserved space + placement new allows us to avoid both\n  // problems.\n  alignas(absl::Mutex) mutable unsigned char data_guard_[sizeof(absl::Mutex)];\n};\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n// The Flag object parameterized by the flag's value type. This class implements\n// flag reflection handle interface.\n\ntemplate <typename T>\nclass Flag {\n public:\n  constexpr Flag(const char* name, const char* type_name, const char* filename,\n                 FlagHelpArg help, const FlagDefaultArg default_arg)\n      : impl_(name, type_name, filename, &FlagOps<T>, help,\n              flags_internal::StorageKind<T>(), default_arg),\n        value_() {}\n\n  // CommandLineFlag interface\n  absl::string_view Name() const { return impl_.Name(); }\n  std::string Filename() const { return impl_.Filename(); }\n  std::string Help() const { return impl_.Help(); }\n  // Do not use. To be removed.\n  bool IsSpecifiedOnCommandLine() const {\n    return impl_.IsSpecifiedOnCommandLine();\n  }\n  std::string DefaultValue() const { return impl_.DefaultValue(); }\n  std::string CurrentValue() const { return impl_.CurrentValue(); }\n\n private:\n  template <typename, bool>\n  friend class FlagRegistrar;\n  friend class FlagImplPeer;\n\n  T Get() const {\n    // See implementation notes in CommandLineFlag::Get().\n    union U {\n      T value;\n      U() {}\n      ~U() { value.~T(); }\n    };\n    U u;\n\n#if !defined(NDEBUG)\n    impl_.AssertValidType(absl::FastTypeId<T>(), &GenRuntimeTypeId<T>);\n#endif\n\n    if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {\n      impl_.Read(&u.value);\n    }\n    return std::move(u.value);\n  }\n  void Set(const T& v) {\n    impl_.AssertValidType(absl::FastTypeId<T>(), &GenRuntimeTypeId<T>);\n    impl_.Write(&v);\n  }\n\n  // Access to the reflection.\n  const CommandLineFlag& Reflect() const { return impl_; }\n\n  // Flag's data\n  // The implementation depends on value_ field to be placed exactly after the\n  // impl_ field, so that impl_ can figure out the offset to the value and\n  // access it.\n  FlagImpl impl_;\n  FlagValue<T> value_;\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Trampoline for friend access\n\nclass FlagImplPeer {\n public:\n  template <typename T, typename FlagType>\n  static T InvokeGet(const FlagType& flag) {\n    return flag.Get();\n  }\n  template <typename FlagType, typename T>\n  static void InvokeSet(FlagType& flag, const T& v) {\n    flag.Set(v);\n  }\n  template <typename FlagType>\n  static const CommandLineFlag& InvokeReflect(const FlagType& f) {\n    return f.Reflect();\n  }\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Implementation of Flag value specific operations routine.\ntemplate <typename T>\nvoid* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {\n  struct AlignedSpace {\n    alignas(MaskedPointer::RequiredAlignment()) alignas(\n        T) unsigned char buf[sizeof(T)];\n  };\n  using Allocator = std::allocator<AlignedSpace>;\n  switch (op) {\n    case FlagOp::kAlloc: {\n      Allocator alloc;\n      return std::allocator_traits<Allocator>::allocate(alloc, 1);\n    }\n    case FlagOp::kDelete: {\n      T* p = static_cast<T*>(v2);\n      p->~T();\n      Allocator alloc;\n      std::allocator_traits<Allocator>::deallocate(\n          alloc, reinterpret_cast<AlignedSpace*>(p), 1);\n      return nullptr;\n    }\n    case FlagOp::kCopy:\n      *static_cast<T*>(v2) = *static_cast<const T*>(v1);\n      return nullptr;\n    case FlagOp::kCopyConstruct:\n      new (v2) T(*static_cast<const T*>(v1));\n      return nullptr;\n    case FlagOp::kSizeof:\n      return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));\n    case FlagOp::kFastTypeId:\n      return absl::bit_cast<void*>(absl::FastTypeId<T>());\n    case FlagOp::kRuntimeTypeId:\n      return const_cast<std::type_info*>(GenRuntimeTypeId<T>());\n    case FlagOp::kParse: {\n      // Initialize the temporary instance of type T based on current value in\n      // destination (which is going to be flag's default value).\n      T temp(*static_cast<T*>(v2));\n      if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,\n                              static_cast<std::string*>(v3))) {\n        return nullptr;\n      }\n      *static_cast<T*>(v2) = std::move(temp);\n      return v2;\n    }\n    case FlagOp::kUnparse:\n      *static_cast<std::string*>(v2) =\n          absl::UnparseFlag<T>(*static_cast<const T*>(v1));\n      return nullptr;\n    case FlagOp::kValueOffset: {\n      // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the\n      // offset of the data.\n      size_t round_to = alignof(FlagValue<T>);\n      size_t offset = (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;\n      return reinterpret_cast<void*>(offset);\n    }\n  }\n  return nullptr;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// This class facilitates Flag object registration and tail expression-based\n// flag definition, for example:\n// ABSL_FLAG(int, foo, 42, \"Foo help\").OnUpdate(NotifyFooWatcher);\nstruct FlagRegistrarEmpty {};\ntemplate <typename T, bool do_register>\nclass FlagRegistrar {\n public:\n  constexpr explicit FlagRegistrar(Flag<T>& flag, const char* filename)\n      : flag_(flag) {\n    if (do_register)\n      flags_internal::RegisterCommandLineFlag(flag_.impl_, filename);\n  }\n\n  FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {\n    flag_.impl_.SetCallback(cb);\n    return *this;\n  }\n\n  // Makes the registrar die gracefully as an empty struct on a line where\n  // registration happens. Registrar objects are intended to live only as\n  // temporary.\n  constexpr operator FlagRegistrarEmpty() const { return {}; }  // NOLINT\n\n private:\n  Flag<T>& flag_;  // Flag being registered (not owned).\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Test only API\nuint64_t NumLeakedFlagValues();\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_FLAG_H_\n"
  },
  {
    "path": "absl/flags/internal/parse.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_PARSE_H_\n#define ABSL_FLAGS_INTERNAL_PARSE_H_\n\n#include <iostream>\n#include <ostream>\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/flags/declare.h\"\n#include \"absl/flags/internal/usage.h\"\n#include \"absl/strings/string_view.h\"\n\nABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);\nABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);\nABSL_DECLARE_FLAG(std::vector<std::string>, tryfromenv);\nABSL_DECLARE_FLAG(std::vector<std::string>, undefok);\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\nenum class UsageFlagsAction { kHandleUsage, kIgnoreUsage };\nenum class OnUndefinedFlag {\n  kIgnoreUndefined,\n  kReportUndefined,\n  kAbortIfUndefined\n};\n\n// This is not a public interface. This interface exists to expose the ability\n// to change help output stream in case of parsing errors. This is used by\n// internal unit tests to validate expected outputs.\n// When this was written, `EXPECT_EXIT` only supported matchers on stderr,\n// but not on stdout.\nstd::vector<char*> ParseCommandLineImpl(\n    int argc, char* argv[], UsageFlagsAction usage_flag_action,\n    OnUndefinedFlag undef_flag_action,\n    std::ostream& error_help_output = std::cout);\n\n// --------------------------------------------------------------------\n// Inspect original command line\n\n// Returns true if flag with specified name was either present on the original\n// command line or specified in flag file present on the original command line.\nbool WasPresentOnCommandLine(absl::string_view flag_name);\n\n// Return existing flags similar to the parameter, in order to help in case of\n// misspellings.\nstd::vector<std::string> GetMisspellingHints(absl::string_view flag);\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_PARSE_H_\n"
  },
  {
    "path": "absl/flags/internal/path_util.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_PATH_UTIL_H_\n#define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// A portable interface that returns the basename of the filename passed as an\n// argument. It is similar to basename(3)\n// <https://linux.die.net/man/3/basename>.\n// For example:\n//     flags_internal::Basename(\"a/b/prog/file.cc\")\n// returns \"file.cc\"\n//     flags_internal::Basename(\"file.cc\")\n// returns \"file.cc\"\ninline absl::string_view Basename(absl::string_view filename) {\n  auto last_slash_pos = filename.find_last_of(\"/\\\\\");\n\n  return last_slash_pos == absl::string_view::npos\n             ? filename\n             : filename.substr(last_slash_pos + 1);\n}\n\n// A portable interface that returns the directory name of the filename\n// passed as an argument, including the trailing slash.\n// Returns the empty string if a slash is not found in the input file name.\n// For example:\n//      flags_internal::Package(\"a/b/prog/file.cc\")\n// returns \"a/b/prog/\"\n//      flags_internal::Package(\"file.cc\")\n// returns \"\"\ninline absl::string_view Package(absl::string_view filename) {\n  auto last_slash_pos = filename.find_last_of(\"/\\\\\");\n\n  return last_slash_pos == absl::string_view::npos\n             ? absl::string_view()\n             : filename.substr(0, last_slash_pos + 1);\n}\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_\n"
  },
  {
    "path": "absl/flags/internal/path_util_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/path_util.h\"\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\n\nTEST(FlagsPathUtilTest, TestBasename) {\n  EXPECT_EQ(flags::Basename(\"\"), \"\");\n  EXPECT_EQ(flags::Basename(\"a.cc\"), \"a.cc\");\n  EXPECT_EQ(flags::Basename(\"dir/a.cc\"), \"a.cc\");\n  EXPECT_EQ(flags::Basename(\"dir1/dir2/a.cc\"), \"a.cc\");\n  EXPECT_EQ(flags::Basename(\"../dir1/dir2/a.cc\"), \"a.cc\");\n  EXPECT_EQ(flags::Basename(\"/dir1/dir2/a.cc\"), \"a.cc\");\n  EXPECT_EQ(flags::Basename(\"/dir1/dir2/../dir3/a.cc\"), \"a.cc\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(FlagsPathUtilTest, TestPackage) {\n  EXPECT_EQ(flags::Package(\"\"), \"\");\n  EXPECT_EQ(flags::Package(\"a.cc\"), \"\");\n  EXPECT_EQ(flags::Package(\"dir/a.cc\"), \"dir/\");\n  EXPECT_EQ(flags::Package(\"dir1/dir2/a.cc\"), \"dir1/dir2/\");\n  EXPECT_EQ(flags::Package(\"../dir1/dir2/a.cc\"), \"../dir1/dir2/\");\n  EXPECT_EQ(flags::Package(\"/dir1/dir2/a.cc\"), \"/dir1/dir2/\");\n  EXPECT_EQ(flags::Package(\"/dir1/dir2/../dir3/a.cc\"), \"/dir1/dir2/../dir3/\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/internal/private_handle_accessor.cc",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/private_handle_accessor.h\"\n\n#include <memory>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\nFlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {\n  return flag.TypeId();\n}\n\nstd::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(\n    CommandLineFlag& flag) {\n  return flag.SaveState();\n}\n\nbool PrivateHandleAccessor::IsSpecifiedOnCommandLine(\n    const CommandLineFlag& flag) {\n  return flag.IsSpecifiedOnCommandLine();\n}\n\nbool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag,\n                                               absl::string_view value) {\n  return flag.ValidateInputValue(value);\n}\n\nvoid PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(\n    const CommandLineFlag& flag) {\n  flag.CheckDefaultValueParsingRoundtrip();\n}\n\nbool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag,\n                                      absl::string_view value,\n                                      flags_internal::FlagSettingMode set_mode,\n                                      flags_internal::ValueSource source,\n                                      std::string& error) {\n  return flag.ParseFrom(value, set_mode, source, error);\n}\n\nabsl::string_view PrivateHandleAccessor::TypeName(const CommandLineFlag& flag) {\n  return flag.TypeName();\n}\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n"
  },
  {
    "path": "absl/flags/internal/private_handle_accessor.h",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_\n#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_\n\n#include <memory>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// This class serves as a trampoline to access private methods of\n// CommandLineFlag. This class is intended for use exclusively internally inside\n// of the Abseil Flags implementation.\nclass PrivateHandleAccessor {\n public:\n  // Access to CommandLineFlag::TypeId.\n  static FlagFastTypeId TypeId(const CommandLineFlag& flag);\n\n  // Access to CommandLineFlag::SaveState.\n  static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);\n\n  // Access to CommandLineFlag::IsSpecifiedOnCommandLine.\n  static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);\n\n  // Access to CommandLineFlag::ValidateInputValue.\n  static bool ValidateInputValue(const CommandLineFlag& flag,\n                                 absl::string_view value);\n\n  // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.\n  static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);\n\n  static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,\n                        flags_internal::FlagSettingMode set_mode,\n                        flags_internal::ValueSource source, std::string& error);\n\n  // Access to CommandLineFlag::TypeName.\n  static absl::string_view TypeName(const CommandLineFlag& flag);\n};\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_\n"
  },
  {
    "path": "absl/flags/internal/program_name.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/program_name.h\"\n\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/internal/path_util.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\nstatic absl::Mutex& ProgramNameMutex() {\n  static absl::NoDestructor<absl::Mutex> mutex;\n  return *mutex;\n}\nABSL_CONST_INIT static std::string* program_name ABSL_GUARDED_BY(\n    ProgramNameMutex()) ABSL_PT_GUARDED_BY(ProgramNameMutex()) = nullptr;\n\nstd::string ProgramInvocationName() {\n  absl::MutexLock l(ProgramNameMutex());\n  return program_name ? *program_name : \"UNKNOWN\";\n}\n\nstd::string ShortProgramInvocationName() {\n  absl::MutexLock l(ProgramNameMutex());\n  return program_name ? std::string(flags_internal::Basename(*program_name))\n                      : \"UNKNOWN\";\n}\n\nvoid SetProgramInvocationName(absl::string_view prog_name_str) {\n  absl::MutexLock l(ProgramNameMutex());\n  if (!program_name) {\n    program_name = new std::string(prog_name_str);\n  } else {\n    program_name->assign(prog_name_str.data(), prog_name_str.size());\n  }\n}\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/internal/program_name.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_\n#define ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\n// --------------------------------------------------------------------\n// Program name\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// Returns program invocation name or \"UNKNOWN\" if `SetProgramInvocationName()`\n// is never called. At the moment this is always set to argv[0] as part of\n// library initialization.\nstd::string ProgramInvocationName();\n\n// Returns base name for program invocation name. For example, if\n//   ProgramInvocationName() == \"a/b/mybinary\"\n// then\n//   ShortProgramInvocationName() == \"mybinary\"\nstd::string ShortProgramInvocationName();\n\n// Sets program invocation name to a new value. Should only be called once\n// during program initialization, before any threads are spawned.\nvoid SetProgramInvocationName(absl::string_view prog_name_str);\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_\n"
  },
  {
    "path": "absl/flags/internal/program_name_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/program_name.h\"\n\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\n\nTEST(FlagsPathUtilTest, TestProgamNameInterfaces) {\n  flags::SetProgramInvocationName(\"absl/flags/program_name_test\");\n  std::string program_name = flags::ProgramInvocationName();\n  for (char& c : program_name)\n    if (c == '\\\\') c = '/';\n\n#if !defined(__wasm__) && !defined(__asmjs__)\n  const std::string expect_name = \"absl/flags/program_name_test\";\n  const std::string expect_basename = \"program_name_test\";\n#else\n  // For targets that generate javascript or webassembly the invocation name\n  // has the special value below.\n  const std::string expect_name = \"this.program\";\n  const std::string expect_basename = \"this.program\";\n#endif\n\n  EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name;\n  EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename);\n\n  flags::SetProgramInvocationName(\"a/my_test\");\n\n  EXPECT_EQ(flags::ProgramInvocationName(), \"a/my_test\");\n  EXPECT_EQ(flags::ShortProgramInvocationName(), \"my_test\");\n\n  absl::string_view not_null_terminated(\"absl/aaa/bbb\");\n  not_null_terminated = not_null_terminated.substr(1, 10);\n\n  flags::SetProgramInvocationName(not_null_terminated);\n\n  EXPECT_EQ(flags::ProgramInvocationName(), \"bsl/aaa/bb\");\n  EXPECT_EQ(flags::ShortProgramInvocationName(), \"bb\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/internal/registry.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_REGISTRY_H_\n#define ABSL_FLAGS_INTERNAL_REGISTRY_H_\n\n#include <functional>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/strings/string_view.h\"\n\n// --------------------------------------------------------------------\n// Global flags registry API.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// Executes specified visitor for each non-retired flag in the registry. While\n// callback are executed, the registry is locked and can't be changed.\nvoid ForEachFlag(std::function<void(CommandLineFlag&)> visitor);\n\n//-----------------------------------------------------------------------------\n\nbool RegisterCommandLineFlag(CommandLineFlag&, const char* filename);\n\nvoid FinalizeRegistry();\n\n//-----------------------------------------------------------------------------\n// Retired registrations:\n//\n// Retired flag registrations are treated specially. A 'retired' flag is\n// provided only for compatibility with automated invocations that still\n// name it.  A 'retired' flag:\n//   - is not bound to a C++ FLAGS_ reference.\n//   - has a type and a value, but that value is intentionally inaccessible.\n//   - does not appear in --help messages.\n//   - is fully supported by _all_ flag parsing routines.\n//   - consumes args normally, and complains about type mismatches in its\n//     argument.\n//   - emits a complaint but does not die (e.g. LOG(ERROR)) if it is\n//     accessed by name through the flags API for parsing or otherwise.\n//\n// The registrations for a flag happen in an unspecified order as the\n// initializers for the namespace-scope objects of a program are run.\n// Any number of weak registrations for a flag can weakly define the flag.\n// One non-weak registration will upgrade the flag from weak to non-weak.\n// Further weak registrations of a non-weak flag are ignored.\n//\n// This mechanism is designed to support moving dead flags into a\n// 'graveyard' library.  An example migration:\n//\n//   0: Remove references to this FLAGS_flagname in the C++ codebase.\n//   1: Register as 'retired' in old_lib.\n//   2: Make old_lib depend on graveyard.\n//   3: Add a redundant 'retired' registration to graveyard.\n//   4: Remove the old_lib 'retired' registration.\n//   5: Eventually delete the graveyard registration entirely.\n//\n\n// Retire flag with name \"name\" and type indicated by ops.\nvoid Retire(const char* name, FlagFastTypeId type_id, unsigned char* buf);\n\nconstexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);\nconstexpr size_t kRetiredFlagObjAlignment = alignof(void*);\n\n// Registered a retired flag with name 'flag_name' and type 'T'.\ntemplate <typename T>\nclass RetiredFlag {\n public:\n  void Retire(const char* flag_name) {\n    flags_internal::Retire(flag_name, absl::FastTypeId<T>(), buf_);\n  }\n\n private:\n  alignas(kRetiredFlagObjAlignment) unsigned char buf_[kRetiredFlagObjSize];\n};\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_REGISTRY_H_\n"
  },
  {
    "path": "absl/flags/internal/sequence_lock.h",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_\n#define ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <atomic>\n#include <cassert>\n#include <cstring>\n\n#include \"absl/base/optimization.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// Align 'x' up to the nearest 'align' bytes.\ninline constexpr size_t AlignUp(size_t x, size_t align) {\n  return align * ((x + align - 1) / align);\n}\n\n// A SequenceLock implements lock-free reads. A sequence counter is incremented\n// before and after each write, and readers access the counter before and after\n// accessing the protected data. If the counter is verified to not change during\n// the access, and the sequence counter value was even, then the reader knows\n// that the read was race-free and valid. Otherwise, the reader must fall back\n// to a Mutex-based code path.\n//\n// This particular SequenceLock starts in an \"uninitialized\" state in which\n// TryRead() returns false. It must be enabled by calling MarkInitialized().\n// This serves as a marker that the associated flag value has not yet been\n// initialized and a slow path needs to be taken.\n//\n// The memory reads and writes protected by this lock must use the provided\n// `TryRead()` and `Write()` functions. These functions behave similarly to\n// `memcpy()`, with one oddity: the protected data must be an array of\n// `std::atomic<uint64>`. This is to comply with the C++ standard, which\n// considers data races on non-atomic objects to be undefined behavior. See \"Can\n// Seqlocks Get Along With Programming Language Memory Models?\"[1] by Hans J.\n// Boehm for more details.\n//\n// [1] https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf\nclass SequenceLock {\n public:\n  constexpr SequenceLock() : lock_(kUninitialized) {}\n\n  // Mark that this lock is ready for use.\n  void MarkInitialized() {\n    assert(lock_.load(std::memory_order_relaxed) == kUninitialized);\n    lock_.store(0, std::memory_order_release);\n  }\n\n  // Copy \"size\" bytes of data from \"src\" to \"dst\", protected as a read-side\n  // critical section of the sequence lock.\n  //\n  // Unlike traditional sequence lock implementations which loop until getting a\n  // clean read, this implementation returns false in the case of concurrent\n  // calls to `Write`. In such a case, the caller should fall back to a\n  // locking-based slow path.\n  //\n  // Returns false if the sequence lock was not yet marked as initialized.\n  //\n  // NOTE: If this returns false, \"dst\" may be overwritten with undefined\n  // (potentially uninitialized) data.\n  bool TryRead(void* dst, const std::atomic<uint64_t>* src, size_t size) const {\n    // Acquire barrier ensures that no loads done by f() are reordered\n    // above the first load of the sequence counter.\n    int64_t seq_before = lock_.load(std::memory_order_acquire);\n    if (ABSL_PREDICT_FALSE(seq_before & 1) == 1) return false;\n    RelaxedCopyFromAtomic(dst, src, size);\n    // Another acquire fence ensures that the load of 'lock_' below is\n    // strictly ordered after the RelaxedCopyToAtomic call above.\n    std::atomic_thread_fence(std::memory_order_acquire);\n    int64_t seq_after = lock_.load(std::memory_order_relaxed);\n    return ABSL_PREDICT_TRUE(seq_before == seq_after);\n  }\n\n  // Copy \"size\" bytes from \"src\" to \"dst\" as a write-side critical section\n  // of the sequence lock. Any concurrent readers will be forced to retry\n  // until they get a read that does not conflict with this write.\n  //\n  // This call must be externally synchronized against other calls to Write,\n  // but may proceed concurrently with reads.\n  void Write(std::atomic<uint64_t>* dst, const void* src, size_t size) {\n    // We can use relaxed instructions to increment the counter since we\n    // are extenally synchronized. The std::atomic_thread_fence below\n    // ensures that the counter updates don't get interleaved with the\n    // copy to the data.\n    int64_t orig_seq = lock_.load(std::memory_order_relaxed);\n    assert((orig_seq & 1) == 0);  // Must be initially unlocked.\n    lock_.store(orig_seq + 1, std::memory_order_relaxed);\n\n    // We put a release fence between update to lock_ and writes to shared data.\n    // Thus all stores to shared data are effectively release operations and\n    // update to lock_ above cannot be re-ordered past any of them. Note that\n    // this barrier is not for the fetch_add above.  A release barrier for the\n    // fetch_add would be before it, not after.\n    std::atomic_thread_fence(std::memory_order_release);\n    RelaxedCopyToAtomic(dst, src, size);\n    // \"Release\" semantics ensure that none of the writes done by\n    // RelaxedCopyToAtomic() can be reordered after the following modification.\n    lock_.store(orig_seq + 2, std::memory_order_release);\n  }\n\n  // Return the number of times that Write() has been called.\n  //\n  // REQUIRES: This must be externally synchronized against concurrent calls to\n  // `Write()` or `IncrementModificationCount()`.\n  // REQUIRES: `MarkInitialized()` must have been previously called.\n  int64_t ModificationCount() const {\n    int64_t val = lock_.load(std::memory_order_relaxed);\n    assert(val != kUninitialized && (val & 1) == 0);\n    return val / 2;\n  }\n\n  // REQUIRES: This must be externally synchronized against concurrent calls to\n  // `Write()` or `ModificationCount()`.\n  // REQUIRES: `MarkInitialized()` must have been previously called.\n  void IncrementModificationCount() {\n    int64_t val = lock_.load(std::memory_order_relaxed);\n    assert(val != kUninitialized);\n    lock_.store(val + 2, std::memory_order_relaxed);\n  }\n\n private:\n  // Perform the equivalent of \"memcpy(dst, src, size)\", but using relaxed\n  // atomics.\n  static void RelaxedCopyFromAtomic(void* dst, const std::atomic<uint64_t>* src,\n                                    size_t size) {\n    char* dst_byte = static_cast<char*>(dst);\n    while (size >= sizeof(uint64_t)) {\n      uint64_t word = src->load(std::memory_order_relaxed);\n      std::memcpy(dst_byte, &word, sizeof(word));\n      dst_byte += sizeof(word);\n      src++;\n      size -= sizeof(word);\n    }\n    if (size > 0) {\n      uint64_t word = src->load(std::memory_order_relaxed);\n      std::memcpy(dst_byte, &word, size);\n    }\n  }\n\n  // Perform the equivalent of \"memcpy(dst, src, size)\", but using relaxed\n  // atomics.\n  static void RelaxedCopyToAtomic(std::atomic<uint64_t>* dst, const void* src,\n                                  size_t size) {\n    const char* src_byte = static_cast<const char*>(src);\n    while (size >= sizeof(uint64_t)) {\n      uint64_t word;\n      std::memcpy(&word, src_byte, sizeof(word));\n      dst->store(word, std::memory_order_relaxed);\n      src_byte += sizeof(word);\n      dst++;\n      size -= sizeof(word);\n    }\n    if (size > 0) {\n      uint64_t word = 0;\n      std::memcpy(&word, src_byte, size);\n      dst->store(word, std::memory_order_relaxed);\n    }\n  }\n\n  static constexpr int64_t kUninitialized = -1;\n  std::atomic<int64_t> lock_;\n};\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_\n"
  },
  {
    "path": "absl/flags/internal/sequence_lock_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/flags/internal/sequence_lock.h\"\n\n#include <algorithm>\n#include <atomic>\n#include <thread>  // NOLINT(build/c++11)\n#include <tuple>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/container/fixed_array.h\"\n#include \"absl/time/clock.h\"\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\n\nclass ConcurrentSequenceLockTest\n    : public testing::TestWithParam<std::tuple<int, int>> {\n public:\n  ConcurrentSequenceLockTest()\n      : buf_bytes_(std::get<0>(GetParam())),\n        num_threads_(std::get<1>(GetParam())) {}\n\n protected:\n  const int buf_bytes_;\n  const int num_threads_;\n};\n\nTEST_P(ConcurrentSequenceLockTest, ReadAndWrite) {\n  const int buf_words =\n      flags::AlignUp(buf_bytes_, sizeof(uint64_t)) / sizeof(uint64_t);\n\n  // The buffer that will be protected by the SequenceLock.\n  absl::FixedArray<std::atomic<uint64_t>> protected_buf(buf_words);\n  for (auto& v : protected_buf) v = -1;\n\n  flags::SequenceLock seq_lock;\n  std::atomic<bool> stop{false};\n  std::atomic<int64_t> bad_reads{0};\n  std::atomic<int64_t> good_reads{0};\n  std::atomic<int64_t> unsuccessful_reads{0};\n\n  // Start a bunch of threads which read 'protected_buf' under the sequence\n  // lock. The main thread will concurrently update 'protected_buf'. The updates\n  // always consist of an array of identical integers. The reader ensures that\n  // any data it reads matches that pattern (i.e. the reads are not \"torn\").\n  std::vector<std::thread> threads;\n  for (int i = 0; i < num_threads_; i++) {\n    threads.emplace_back([&]() {\n      absl::FixedArray<char> local_buf(buf_bytes_);\n      while (!stop.load(std::memory_order_relaxed)) {\n        if (seq_lock.TryRead(local_buf.data(), protected_buf.data(),\n                             buf_bytes_)) {\n          bool good = true;\n          for (const auto& v : local_buf) {\n            if (v != local_buf[0]) good = false;\n          }\n          if (good) {\n            good_reads.fetch_add(1, std::memory_order_relaxed);\n          } else {\n            bad_reads.fetch_add(1, std::memory_order_relaxed);\n          }\n        } else {\n          unsuccessful_reads.fetch_add(1, std::memory_order_relaxed);\n        }\n      }\n    });\n  }\n  while (unsuccessful_reads.load(std::memory_order_relaxed) < num_threads_) {\n    absl::SleepFor(absl::Milliseconds(1));\n  }\n  seq_lock.MarkInitialized();\n\n  // Run a maximum of 5 seconds. On Windows, the scheduler behavior seems\n  // somewhat unfair and without an explicit timeout for this loop, the tests\n  // can run a long time.\n  absl::Time deadline = absl::Now() + absl::Seconds(5);\n  for (int i = 0; i < 100 && absl::Now() < deadline; i++) {\n    absl::FixedArray<char> writer_buf(buf_bytes_);\n    for (auto& v : writer_buf) v = i;\n    seq_lock.Write(protected_buf.data(), writer_buf.data(), buf_bytes_);\n    absl::SleepFor(absl::Microseconds(10));\n  }\n  stop.store(true, std::memory_order_relaxed);\n  for (auto& t : threads) t.join();\n  ASSERT_GE(good_reads, 0);\n  ASSERT_EQ(bad_reads, 0);\n}\n\n// Simple helper for generating a range of thread counts.\n// Generates [low, low*scale, low*scale^2, ...high)\n// (even if high is between low*scale^k and low*scale^(k+1)).\nstd::vector<int> MultiplicativeRange(int low, int high, int scale) {\n  std::vector<int> result;\n  for (int current = low; current < high; current *= scale) {\n    result.push_back(current);\n  }\n  result.push_back(high);\n  return result;\n}\n\n#ifndef ABSL_HAVE_THREAD_SANITIZER\nconst int kMaxThreads = absl::base_internal::NumCPUs();\n#else\n// With TSAN, a lot of threads contending for atomic access on the sequence\n// lock make this test run too slowly.\nconst int kMaxThreads = std::min(absl::base_internal::NumCPUs(), 4);\n#endif\n\n// Return all of the interesting buffer sizes worth testing:\n// powers of two and adjacent values.\nstd::vector<int> InterestingBufferSizes() {\n  std::vector<int> ret;\n  for (int v : MultiplicativeRange(1, 128, 2)) {\n    ret.push_back(v);\n    if (v > 1) {\n      ret.push_back(v - 1);\n    }\n    ret.push_back(v + 1);\n  }\n  return ret;\n}\n\nINSTANTIATE_TEST_SUITE_P(\n    TestManyByteSizes, ConcurrentSequenceLockTest,\n    testing::Combine(\n        // Buffer size (bytes).\n        testing::ValuesIn(InterestingBufferSizes()),\n        // Number of reader threads.\n        testing::ValuesIn(MultiplicativeRange(1, kMaxThreads, 2))));\n\n// Simple single-threaded test, parameterized by the size of the buffer to be\n// protected.\nclass SequenceLockTest : public testing::TestWithParam<int> {};\n\nTEST_P(SequenceLockTest, SingleThreaded) {\n  const int size = GetParam();\n  absl::FixedArray<std::atomic<uint64_t>> protected_buf(\n      flags::AlignUp(size, sizeof(uint64_t)) / sizeof(uint64_t));\n\n  flags::SequenceLock seq_lock;\n  seq_lock.MarkInitialized();\n\n  std::vector<char> src_buf(size, 'x');\n  seq_lock.Write(protected_buf.data(), src_buf.data(), size);\n\n  std::vector<char> dst_buf(size, '0');\n  ASSERT_TRUE(seq_lock.TryRead(dst_buf.data(), protected_buf.data(), size));\n  ASSERT_EQ(src_buf, dst_buf);\n}\nINSTANTIATE_TEST_SUITE_P(TestManyByteSizes, SequenceLockTest,\n                         // Buffer size (bytes).\n                         testing::Range(1, 128));\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/internal/usage.cc",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/usage.h\"\n\n#include <stdint.h>\n\n#include <algorithm>\n#include <cstdlib>\n#include <functional>\n#include <iterator>\n#include <map>\n#include <ostream>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/internal/flag.h\"\n#include \"absl/flags/internal/path_util.h\"\n#include \"absl/flags/internal/private_handle_accessor.h\"\n#include \"absl/flags/internal/program_name.h\"\n#include \"absl/flags/internal/registry.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/synchronization/mutex.h\"\n\n// Dummy global variables to prevent anyone else defining these.\nbool FLAGS_help = false;\nbool FLAGS_helpfull = false;\nbool FLAGS_helpshort = false;\nbool FLAGS_helppackage = false;\nbool FLAGS_version = false;\nbool FLAGS_only_check_args = false;\nbool FLAGS_helpon = false;\nbool FLAGS_helpmatch = false;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\nnamespace {\n\nusing PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;\n\n// Maximum length size in a human readable format.\nconstexpr size_t kHrfMaxLineLength = 80;\n\n// This class is used to emit an XML element with `tag` and `text`.\n// It adds opening and closing tags and escapes special characters in the text.\n// For example:\n// std::cout << XMLElement(\"title\", \"Milk & Cookies\");\n// prints \"<title>Milk &amp; Cookies</title>\"\nclass XMLElement {\n public:\n  XMLElement(absl::string_view tag, absl::string_view txt)\n      : tag_(tag), txt_(txt) {}\n\n  friend std::ostream& operator<<(std::ostream& out,\n                                  const XMLElement& xml_elem) {\n    out << \"<\" << xml_elem.tag_ << \">\";\n\n    for (auto c : xml_elem.txt_) {\n      switch (c) {\n        case '\"':\n          out << \"&quot;\";\n          break;\n        case '\\'':\n          out << \"&apos;\";\n          break;\n        case '&':\n          out << \"&amp;\";\n          break;\n        case '<':\n          out << \"&lt;\";\n          break;\n        case '>':\n          out << \"&gt;\";\n          break;\n        case '\\n':\n        case '\\v':\n        case '\\f':\n        case '\\t':\n          out << \" \";\n          break;\n        default:\n          if (IsValidXmlCharacter(static_cast<unsigned char>(c))) {\n            out << c;\n          }\n          break;\n      }\n    }\n\n    return out << \"</\" << xml_elem.tag_ << \">\";\n  }\n\n private:\n  static bool IsValidXmlCharacter(unsigned char c) { return c >= 0x20; }\n  absl::string_view tag_;\n  absl::string_view txt_;\n};\n\n// --------------------------------------------------------------------\n// Helper class to pretty-print info about a flag.\n\nclass FlagHelpPrettyPrinter {\n public:\n  // Pretty printer holds on to the std::ostream& reference to direct an output\n  // to that stream.\n  FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,\n                        size_t wrapped_line_indent, std::ostream& out)\n      : out_(out),\n        max_line_len_(max_line_len),\n        min_line_len_(min_line_len),\n        wrapped_line_indent_(wrapped_line_indent),\n        line_len_(0),\n        first_line_(true) {}\n\n  void Write(absl::string_view str, bool wrap_line = false) {\n    // Empty string - do nothing.\n    if (str.empty()) return;\n\n    std::vector<absl::string_view> tokens;\n    if (wrap_line) {\n      for (auto line : absl::StrSplit(str, absl::ByAnyChar(\"\\n\\r\"))) {\n        if (!tokens.empty()) {\n          // Keep line separators in the input string.\n          tokens.emplace_back(\"\\n\");\n        }\n        for (auto token :\n             absl::StrSplit(line, absl::ByAnyChar(\" \\t\"), absl::SkipEmpty())) {\n          tokens.push_back(token);\n        }\n      }\n    } else {\n      tokens.push_back(str);\n    }\n\n    for (auto token : tokens) {\n      bool new_line = (line_len_ == 0);\n\n      // Respect line separators in the input string.\n      if (token == \"\\n\") {\n        EndLine();\n        continue;\n      }\n\n      // Write the token, ending the string first if necessary/possible.\n      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {\n        EndLine();\n        new_line = true;\n      }\n\n      if (new_line) {\n        StartLine();\n      } else {\n        out_ << ' ';\n        ++line_len_;\n      }\n\n      out_ << token;\n      line_len_ += token.size();\n    }\n  }\n\n  void StartLine() {\n    if (first_line_) {\n      line_len_ = min_line_len_;\n      first_line_ = false;\n    } else {\n      line_len_ = min_line_len_ + wrapped_line_indent_;\n    }\n    out_ << std::string(line_len_, ' ');\n  }\n  void EndLine() {\n    out_ << '\\n';\n    line_len_ = 0;\n  }\n\n private:\n  std::ostream& out_;\n  const size_t max_line_len_;\n  const size_t min_line_len_;\n  const size_t wrapped_line_indent_;\n  size_t line_len_;\n  bool first_line_;\n};\n\nvoid FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {\n  FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);\n\n  // Flag name.\n  printer.Write(absl::StrCat(\"--\", flag.Name()));\n\n  // Flag help.\n  printer.Write(absl::StrCat(\"(\", flag.Help(), \");\"), /*wrap_line=*/true);\n\n  // The listed default value will be the actual default from the flag\n  // definition in the originating source file, unless the value has\n  // subsequently been modified using SetCommandLineOption() with mode\n  // SET_FLAGS_DEFAULT.\n  std::string dflt_val = flag.DefaultValue();\n  std::string curr_val = flag.CurrentValue();\n  bool is_modified = curr_val != dflt_val;\n\n  if (flag.IsOfType<std::string>()) {\n    dflt_val = absl::StrCat(\"\\\"\", dflt_val, \"\\\"\");\n  }\n  printer.Write(absl::StrCat(\"default: \", dflt_val, \";\"));\n\n  if (is_modified) {\n    if (flag.IsOfType<std::string>()) {\n      curr_val = absl::StrCat(\"\\\"\", curr_val, \"\\\"\");\n    }\n    printer.Write(absl::StrCat(\"currently: \", curr_val, \";\"));\n  }\n\n  printer.EndLine();\n}\n\n// Shows help for every filename which matches any of the filters\n// If filters are empty, shows help for every file.\n// If a flag's help message has been stripped (e.g. by adding '#define\n// STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'\n// and its variants.\nvoid FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,\n                   HelpFormat format, absl::string_view program_usage_message) {\n  if (format == HelpFormat::kHumanReadable) {\n    out << flags_internal::ShortProgramInvocationName() << \": \"\n        << program_usage_message << \"\\n\\n\";\n  } else {\n    // XML schema is not a part of our public API for now.\n    out << \"<?xml version=\\\"1.0\\\"?>\\n\"\n        << \"<!-- This output should be used with care. We do not report type \"\n           \"names for flags with user defined types -->\\n\"\n        << \"<!-- Prefer flag only_check_args for validating flag inputs -->\\n\"\n        // The document.\n        << \"<AllFlags>\\n\"\n        // The program name and usage.\n        << XMLElement(\"program\", flags_internal::ShortProgramInvocationName())\n        << '\\n'\n        << XMLElement(\"usage\", program_usage_message) << '\\n';\n  }\n\n  // Ordered map of package name to\n  //   map of file name to\n  //     vector of flags in the file.\n  // This map is used to output matching flags grouped by package and file\n  // name.\n  std::map<std::string,\n           std::map<std::string, std::vector<const absl::CommandLineFlag*>>>\n      matching_flags;\n\n  flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {\n    // Ignore retired flags.\n    if (flag.IsRetired()) return;\n\n    // If the flag has been stripped, pretend that it doesn't exist.\n    if (flag.Help() == flags_internal::kStrippedFlagHelp) return;\n\n    // Make sure flag satisfies the filter\n    if (!filter_cb(flag)) return;\n\n    std::string flag_filename = flag.Filename();\n\n    matching_flags[std::string(flags_internal::Package(flag_filename))]\n                  [flag_filename]\n                      .push_back(&flag);\n  });\n\n  absl::string_view package_separator;  // controls blank lines between packages\n  absl::string_view file_separator;     // controls blank lines between files\n  for (auto& package : matching_flags) {\n    if (format == HelpFormat::kHumanReadable) {\n      out << package_separator;\n      package_separator = \"\\n\\n\";\n    }\n\n    file_separator = \"\";\n    for (auto& flags_in_file : package.second) {\n      if (format == HelpFormat::kHumanReadable) {\n        out << file_separator << \"  Flags from \" << flags_in_file.first\n            << \":\\n\";\n        file_separator = \"\\n\";\n      }\n\n      std::sort(std::begin(flags_in_file.second),\n                std::end(flags_in_file.second),\n                [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {\n                  return lhs->Name() < rhs->Name();\n                });\n\n      for (const auto* flag : flags_in_file.second) {\n        flags_internal::FlagHelp(out, *flag, format);\n      }\n    }\n  }\n\n  if (format == HelpFormat::kHumanReadable) {\n    FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);\n\n    if (filter_cb && matching_flags.empty()) {\n      printer.Write(\"No flags matched.\\n\", true);\n    }\n    printer.EndLine();\n    printer.Write(\n        \"Try --helpfull to get a list of all flags or --help=substring \"\n        \"shows help for flags which include specified substring in either \"\n        \"in the name, or description or path.\\n\",\n        true);\n  } else {\n    // The end of the document.\n    out << \"</AllFlags>\\n\";\n  }\n}\n\nvoid FlagsHelpImpl(std::ostream& out,\n                   flags_internal::FlagKindFilter filename_filter_cb,\n                   HelpFormat format, absl::string_view program_usage_message) {\n  FlagsHelpImpl(\n      out,\n      [&](const absl::CommandLineFlag& flag) {\n        return filename_filter_cb && filename_filter_cb(flag.Filename());\n      },\n      format, program_usage_message);\n}\n\n}  // namespace\n\n// --------------------------------------------------------------------\n// Produces the help message describing specific flag.\nvoid FlagHelp(std::ostream& out, const CommandLineFlag& flag,\n              HelpFormat format) {\n  if (format == HelpFormat::kHumanReadable)\n    flags_internal::FlagHelpHumanReadable(flag, out);\n}\n\n// --------------------------------------------------------------------\n// Produces the help messages for all flags matching the filename filter.\n// If filter is empty produces help messages for all flags.\nvoid FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,\n               absl::string_view program_usage_message) {\n  flags_internal::FlagKindFilter filter_cb = [&](absl::string_view filename) {\n    return filter.empty() || absl::StrContains(filename, filter);\n  };\n  flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message);\n}\n\n// --------------------------------------------------------------------\n// Checks all the 'usage' command line flags to see if any have been set.\n// If so, handles them appropriately.\nHelpMode HandleUsageFlags(std::ostream& out,\n                          absl::string_view program_usage_message) {\n  switch (GetFlagsHelpMode()) {\n    case HelpMode::kNone:\n      break;\n    case HelpMode::kImportant:\n      flags_internal::FlagsHelpImpl(\n          out, flags_internal::GetUsageConfig().contains_help_flags,\n          GetFlagsHelpFormat(), program_usage_message);\n      break;\n\n    case HelpMode::kShort:\n      flags_internal::FlagsHelpImpl(\n          out, flags_internal::GetUsageConfig().contains_helpshort_flags,\n          GetFlagsHelpFormat(), program_usage_message);\n      break;\n\n    case HelpMode::kFull:\n      flags_internal::FlagsHelp(out, \"\", GetFlagsHelpFormat(),\n                                program_usage_message);\n      break;\n\n    case HelpMode::kPackage:\n      flags_internal::FlagsHelpImpl(\n          out, flags_internal::GetUsageConfig().contains_helppackage_flags,\n          GetFlagsHelpFormat(), program_usage_message);\n      break;\n\n    case HelpMode::kMatch: {\n      std::string substr = GetFlagsHelpMatchSubstr();\n      if (substr.empty()) {\n        // show all options\n        flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),\n                                  program_usage_message);\n      } else {\n        auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {\n          if (absl::StrContains(flag.Name(), substr)) return true;\n          if (absl::StrContains(flag.Filename(), substr)) return true;\n          if (absl::StrContains(flag.Help(), substr)) return true;\n\n          return false;\n        };\n        flags_internal::FlagsHelpImpl(\n            out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);\n      }\n      break;\n    }\n    case HelpMode::kVersion:\n      if (flags_internal::GetUsageConfig().version_string)\n        out << flags_internal::GetUsageConfig().version_string();\n      // Unlike help, we may be asking for version in a script, so return 0\n      break;\n\n    case HelpMode::kOnlyCheckArgs:\n      break;\n  }\n\n  return GetFlagsHelpMode();\n}\n\n// --------------------------------------------------------------------\n// Globals representing usage reporting flags\n\nnamespace {\n\nabsl::Mutex& HelpAttributesMutex() {\n  static absl::NoDestructor<absl::Mutex> mutex;\n  return *mutex;\n}\nABSL_CONST_INIT std::string* match_substr ABSL_GUARDED_BY(HelpAttributesMutex())\n    ABSL_PT_GUARDED_BY(HelpAttributesMutex()) = nullptr;\nABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(HelpAttributesMutex()) =\n    HelpMode::kNone;\nABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(HelpAttributesMutex()) =\n    HelpFormat::kHumanReadable;\n\n}  // namespace\n\nstd::string GetFlagsHelpMatchSubstr() {\n  absl::MutexLock l(HelpAttributesMutex());\n  if (match_substr == nullptr) return \"\";\n  return *match_substr;\n}\n\nvoid SetFlagsHelpMatchSubstr(absl::string_view substr) {\n  absl::MutexLock l(HelpAttributesMutex());\n  if (match_substr == nullptr) match_substr = new std::string;\n  match_substr->assign(substr.data(), substr.size());\n}\n\nHelpMode GetFlagsHelpMode() {\n  absl::MutexLock l(HelpAttributesMutex());\n  return help_mode;\n}\n\nvoid SetFlagsHelpMode(HelpMode mode) {\n  absl::MutexLock l(HelpAttributesMutex());\n  help_mode = mode;\n}\n\nHelpFormat GetFlagsHelpFormat() {\n  absl::MutexLock l(HelpAttributesMutex());\n  return help_format;\n}\n\nvoid SetFlagsHelpFormat(HelpFormat format) {\n  absl::MutexLock l(HelpAttributesMutex());\n  help_format = format;\n}\n\n// Deduces usage flags from the input argument in a form --name=value or\n// --name. argument is already split into name and value before we call this\n// function.\nbool DeduceUsageFlags(absl::string_view name, absl::string_view value) {\n  if (absl::ConsumePrefix(&name, \"help\")) {\n    if (name.empty()) {\n      if (value.empty()) {\n        SetFlagsHelpMode(HelpMode::kImportant);\n      } else {\n        SetFlagsHelpMode(HelpMode::kMatch);\n        SetFlagsHelpMatchSubstr(value);\n      }\n      return true;\n    }\n\n    if (name == \"match\") {\n      SetFlagsHelpMode(HelpMode::kMatch);\n      SetFlagsHelpMatchSubstr(value);\n      return true;\n    }\n\n    if (name == \"on\") {\n      SetFlagsHelpMode(HelpMode::kMatch);\n      SetFlagsHelpMatchSubstr(absl::StrCat(\"/\", value, \".\"));\n      return true;\n    }\n\n    if (name == \"full\") {\n      SetFlagsHelpMode(HelpMode::kFull);\n      return true;\n    }\n\n    if (name == \"short\") {\n      SetFlagsHelpMode(HelpMode::kShort);\n      return true;\n    }\n\n    if (name == \"package\") {\n      SetFlagsHelpMode(HelpMode::kPackage);\n      return true;\n    }\n\n    return false;\n  }\n\n  if (name == \"version\") {\n    SetFlagsHelpMode(HelpMode::kVersion);\n    return true;\n  }\n\n  if (name == \"only_check_args\") {\n    SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);\n    return true;\n  }\n\n  return false;\n}\n\n// --------------------------------------------------------------------\n\nvoid MaybeExit(HelpMode mode) {\n  switch (mode) {\n    case flags_internal::HelpMode::kNone:\n      return;\n    case flags_internal::HelpMode::kOnlyCheckArgs:\n    case flags_internal::HelpMode::kVersion:\n      std::exit(0);\n    default:  // For all the other modes we exit with 1\n      std::exit(1);\n  }\n}\n\n// --------------------------------------------------------------------\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/internal/usage.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_INTERNAL_USAGE_H_\n#define ABSL_FLAGS_INTERNAL_USAGE_H_\n\n#include <iosfwd>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/strings/string_view.h\"\n\n// --------------------------------------------------------------------\n// Usage reporting interfaces\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// The format to report the help messages in.\nenum class HelpFormat {\n  kHumanReadable,\n};\n\n// The kind of usage help requested.\nenum class HelpMode {\n  kNone,\n  kImportant,\n  kShort,\n  kFull,\n  kPackage,\n  kMatch,\n  kVersion,\n  kOnlyCheckArgs\n};\n\n// Streams the help message describing `flag` to `out`.\n// The default value for `flag` is included in the output.\nvoid FlagHelp(std::ostream& out, const CommandLineFlag& flag,\n              HelpFormat format = HelpFormat::kHumanReadable);\n\n// Produces the help messages for all flags matching the filter. A flag matches\n// the filter if it is defined in a file with a filename which includes\n// filter string as a substring. You can use '/' and '.' to restrict the\n// matching to a specific file names. For example:\n//   FlagsHelp(out, \"/path/to/file.\");\n// restricts help to only flags which resides in files named like:\n//  .../path/to/file.<ext>\n// for any extension 'ext'. If the filter is empty this function produces help\n// messages for all flags.\nvoid FlagsHelp(std::ostream& out, absl::string_view filter,\n               HelpFormat format, absl::string_view program_usage_message);\n\n// --------------------------------------------------------------------\n\n// If any of the 'usage' related command line flags (listed on the bottom of\n// this file) has been set this routine produces corresponding help message in\n// the specified output stream and returns HelpMode that was handled. Otherwise\n// it returns HelpMode::kNone.\nHelpMode HandleUsageFlags(std::ostream& out,\n                          absl::string_view program_usage_message);\n\n// --------------------------------------------------------------------\n// Encapsulates the logic of exiting the binary depending on handled help mode.\n\nvoid MaybeExit(HelpMode mode);\n\n// --------------------------------------------------------------------\n// Globals representing usage reporting flags\n\n// Returns substring to filter help output (--help=substr argument)\nstd::string GetFlagsHelpMatchSubstr();\n// Returns the requested help mode.\nHelpMode GetFlagsHelpMode();\n// Returns the requested help format.\nHelpFormat GetFlagsHelpFormat();\n\n// These are corresponding setters to the attributes above.\nvoid SetFlagsHelpMatchSubstr(absl::string_view);\nvoid SetFlagsHelpMode(HelpMode);\nvoid SetFlagsHelpFormat(HelpFormat);\n\n// Deduces usage flags from the input argument in a form --name=value or\n// --name. argument is already split into name and value before we call this\n// function.\nbool DeduceUsageFlags(absl::string_view name, absl::string_view value);\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_INTERNAL_USAGE_H_\n"
  },
  {
    "path": "absl/flags/internal/usage_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/internal/usage.h\"\n\n#include <stdint.h>\n\n#include <sstream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/internal/parse.h\"\n#include \"absl/flags/internal/program_name.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/flags/usage.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n\nABSL_FLAG(int, usage_reporting_test_flag_01, 101,\n          \"usage_reporting_test_flag_01 help message\");\nABSL_FLAG(bool, usage_reporting_test_flag_02, false,\n          \"usage_reporting_test_flag_02 help message\");\nABSL_FLAG(double, usage_reporting_test_flag_03, 1.03,\n          \"usage_reporting_test_flag_03 help message\");\nABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L,\n          \"usage_reporting_test_flag_04 help message\");\nABSL_FLAG(std::string, usage_reporting_test_flag_07, \"\\r\\n\\f\\v\\a\\b\\t \",\n          \"usage_reporting_test_flag_07 help \\r\\n\\f\\v\\a\\b\\t \");\n\nstatic const char kTestUsageMessage[] = \"Custom usage message\";\n\nstruct UDT {\n  UDT() = default;\n  UDT(const UDT&) = default;\n  UDT& operator=(const UDT&) = default;\n};\nstatic bool AbslParseFlag(absl::string_view, UDT*, std::string*) {\n  return true;\n}\nstatic std::string AbslUnparseFlag(const UDT&) { return \"UDT{}\"; }\n\nABSL_FLAG(UDT, usage_reporting_test_flag_05, {},\n          \"usage_reporting_test_flag_05 help message\");\n\nABSL_FLAG(\n    std::string, usage_reporting_test_flag_06, {},\n    \"usage_reporting_test_flag_06 help message.\\n\"\n    \"\\n\"\n    \"Some more help.\\n\"\n    \"Even more long long long long long long long long long long long long \"\n    \"help message.\");\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\n\nstatic std::string NormalizeFileName(absl::string_view fname) {\n#ifdef _WIN32\n  std::string normalized(fname);\n  std::replace(normalized.begin(), normalized.end(), '\\\\', '/');\n  fname = normalized;\n#endif\n\n  auto absl_pos = fname.rfind(\"absl/\");\n  if (absl_pos != absl::string_view::npos) {\n    fname = fname.substr(absl_pos);\n  }\n  return std::string(fname);\n}\n\nclass UsageReportingTest : public testing::Test {\n protected:\n  UsageReportingTest() {\n    // Install default config for the use on this unit test.\n    // Binary may install a custom config before tests are run.\n    absl::FlagsUsageConfig default_config;\n    default_config.normalize_filename = &NormalizeFileName;\n    absl::SetFlagsUsageConfig(default_config);\n  }\n  ~UsageReportingTest() override {\n    flags::SetFlagsHelpMode(flags::HelpMode::kNone);\n    flags::SetFlagsHelpMatchSubstr(\"\");\n    flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);\n  }\n  void SetUp() override {\n#if ABSL_FLAGS_STRIP_NAMES\n    GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n  }\n\n private:\n  absl::FlagSaver flag_saver_;\n};\n\n// --------------------------------------------------------------------\n\nusing UsageReportingDeathTest = UsageReportingTest;\n\nTEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {\n#if !defined(GTEST_HAS_ABSL) || !GTEST_HAS_ABSL\n  // Check for kTestUsageMessage set in main() below.\n  EXPECT_EQ(absl::ProgramUsageMessage(), kTestUsageMessage);\n#else\n  // Check for part of the usage message set by GoogleTest.\n  EXPECT_THAT(absl::ProgramUsageMessage(),\n              ::testing::HasSubstr(\n                  \"This program contains tests written using Google Test\"));\n#endif\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      absl::SetProgramUsageMessage(\"custom usage message\"),\n      ::testing::HasSubstr(\"SetProgramUsageMessage() called twice\"));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {\n  const auto* flag = absl::FindCommandLineFlag(\"usage_reporting_test_flag_01\");\n  std::stringstream test_buf;\n\n  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n)\");\n}\n\nTEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {\n  const auto* flag = absl::FindCommandLineFlag(\"usage_reporting_test_flag_02\");\n  std::stringstream test_buf;\n\n  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n)\");\n}\n\nTEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {\n  const auto* flag = absl::FindCommandLineFlag(\"usage_reporting_test_flag_03\");\n  std::stringstream test_buf;\n\n  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n)\");\n}\n\nTEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {\n  const auto* flag = absl::FindCommandLineFlag(\"usage_reporting_test_flag_04\");\n  std::stringstream test_buf;\n\n  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n)\");\n}\n\nTEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {\n  const auto* flag = absl::FindCommandLineFlag(\"usage_reporting_test_flag_05\");\n  std::stringstream test_buf;\n\n  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n)\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestFlagsHelpHRF) {\n  std::string usage_test_flags_out =\n      R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n    --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\n      message.); default: \"\";)\"\n\n      \"\\n    --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 \"\n      \"help\\n\\n      \\f\\v\\a\\b ); default: \\\"\\r\\n\\f\\v\\a\\b\\t \\\";\\n\"\n\n      R\"(\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\";\n\n  std::stringstream test_buf_01;\n  flags::FlagsHelp(test_buf_01, \"usage_test.cc\",\n                   flags::HelpFormat::kHumanReadable, kTestUsageMessage);\n  EXPECT_EQ(test_buf_01.str(), usage_test_flags_out);\n\n  std::stringstream test_buf_02;\n  flags::FlagsHelp(test_buf_02, \"flags/internal/usage_test.cc\",\n                   flags::HelpFormat::kHumanReadable, kTestUsageMessage);\n  EXPECT_EQ(test_buf_02.str(), usage_test_flags_out);\n\n  std::stringstream test_buf_03;\n  flags::FlagsHelp(test_buf_03, \"usage_test\", flags::HelpFormat::kHumanReadable,\n                   kTestUsageMessage);\n  EXPECT_EQ(test_buf_03.str(), usage_test_flags_out);\n\n  std::stringstream test_buf_04;\n  flags::FlagsHelp(test_buf_04, \"flags/invalid_file_name.cc\",\n                   flags::HelpFormat::kHumanReadable, kTestUsageMessage);\n  EXPECT_EQ(test_buf_04.str(),\n            R\"(usage_test: Custom usage message\n\nNo flags matched.\n\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n\n  std::stringstream test_buf_05;\n  flags::FlagsHelp(test_buf_05, \"\", flags::HelpFormat::kHumanReadable,\n                   kTestUsageMessage);\n  std::string test_out = test_buf_05.str();\n  absl::string_view test_out_str(test_out);\n  EXPECT_TRUE(\n      absl::StartsWith(test_out_str, \"usage_test: Custom usage message\"));\n  EXPECT_TRUE(absl::StrContains(\n      test_out_str, \"Flags from absl/flags/internal/usage_test.cc:\"));\n  EXPECT_TRUE(\n      absl::StrContains(test_out_str, \"-usage_reporting_test_flag_01 \"));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestNoUsageFlags) {\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kNone);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_helpshort) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kShort);\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kShort);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n    --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\n      message.); default: \"\";)\"\n\n      \"\\n    --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 \"\n      \"help\\n\\n      \\f\\v\\a\\b ); default: \\\"\\r\\n\\f\\v\\a\\b\\t \\\";\\n\"\n\n      R\"(\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_help_simple) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kImportant);\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kImportant);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n    --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\n      message.); default: \"\";)\"\n\n      \"\\n    --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 \"\n      \"help\\n\\n      \\f\\v\\a\\b ); default: \\\"\\r\\n\\f\\v\\a\\b\\t \\\";\\n\"\n\n      R\"(\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);\n  flags::SetFlagsHelpMatchSubstr(\"usage_reporting_test_flag_06\");\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kMatch);\n  EXPECT_EQ(test_buf.str(),\n            R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --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\n      message.); default: \"\";\n\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);\n  flags::SetFlagsHelpMatchSubstr(\"test_flag\");\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kMatch);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n    --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\n      message.); default: \"\";)\"\n\n      \"\\n    --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 \"\n      \"help\\n\\n      \\f\\v\\a\\b ); default: \\\"\\r\\n\\f\\v\\a\\b\\t \\\";\\n\"\n\n      R\"(\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_helppackage) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kPackage);\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kPackage);\n  EXPECT_EQ(\n      test_buf.str(),\n      R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n    --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\n      message.); default: \"\";)\"\n\n      \"\\n    --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 \"\n      \"help\\n\\n      \\f\\v\\a\\b ); default: \\\"\\r\\n\\f\\v\\a\\b\\t \\\";\\n\"\n\n      R\"(\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_version) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kVersion);\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kVersion);\n#ifndef NDEBUG\n  EXPECT_EQ(test_buf.str(), \"usage_test\\nDebug build (NDEBUG not #defined)\\n\");\n#else\n  EXPECT_EQ(test_buf.str(), \"usage_test\\n\");\n#endif\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);\n\n  std::stringstream test_buf;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage),\n            flags::HelpMode::kOnlyCheckArgs);\n  EXPECT_EQ(test_buf.str(), \"\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(UsageReportingTest, TestUsageFlag_helpon) {\n  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);\n  flags::SetFlagsHelpMatchSubstr(\"/bla-bla.\");\n\n  std::stringstream test_buf_01;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage),\n            flags::HelpMode::kMatch);\n  EXPECT_EQ(test_buf_01.str(),\n            R\"(usage_test: Custom usage message\n\nNo flags matched.\n\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n\n  flags::SetFlagsHelpMatchSubstr(\"/usage_test.\");\n\n  std::stringstream test_buf_02;\n  EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage),\n            flags::HelpMode::kMatch);\n  EXPECT_EQ(\n      test_buf_02.str(),\n      R\"(usage_test: Custom usage message\n\n  Flags from absl/flags/internal/usage_test.cc:\n    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);\n      default: 101;\n    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);\n      default: false;\n    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);\n      default: 1.03;\n    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);\n      default: 1000000000000004;\n    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);\n      default: UDT{};\n    --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\n      message.); default: \"\";)\"\n\n      \"\\n    --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 \"\n      \"help\\n\\n      \\f\\v\\a\\b ); default: \\\"\\r\\n\\f\\v\\a\\b\\t \\\";\\n\"\n\n      R\"(\nTry --helpfull to get a list of all flags or --help=substring shows help for\nflags which include specified substring in either in the name, or description or\npath.\n)\");\n}\n\n// --------------------------------------------------------------------\n\n}  // namespace\n\nint main(int argc, char* argv[]) {\n  (void)absl::GetFlag(FLAGS_undefok);  // Force linking of parse.cc\n  flags::SetProgramInvocationName(\"usage_test\");\n#if !defined(GTEST_HAS_ABSL) || !GTEST_HAS_ABSL\n  // GoogleTest calls absl::SetProgramUsageMessage() already.\n  absl::SetProgramUsageMessage(kTestUsageMessage);\n#endif\n  ::testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "absl/flags/marshalling.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/marshalling.h\"\n\n#include <stddef.h>\n\n#include <cmath>\n#include <limits>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_join.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// --------------------------------------------------------------------\n// AbslParseFlag specializations for boolean type.\n\nbool AbslParseFlag(absl::string_view text, bool* dst, std::string*) {\n  return SimpleAtob(absl::StripAsciiWhitespace(text), dst);\n}\n\n// --------------------------------------------------------------------\n// AbslParseFlag for integral types.\n\n// Return the base to use for parsing text as an integer.  Leading 0x\n// puts us in base 16.  But leading 0 does not put us in base 8. It\n// caused too many bugs when we had that behavior.\nstatic int NumericBase(absl::string_view text) {\n  if (text.empty()) return 0;\n  size_t num_start = (text[0] == '-' || text[0] == '+') ? 1 : 0;\n  const bool hex = (text.size() >= num_start + 2 && text[num_start] == '0' &&\n                    (text[num_start + 1] == 'x' || text[num_start + 1] == 'X'));\n  return hex ? 16 : 10;\n}\n\ntemplate <typename IntType>\ninline bool ParseFlagImpl(absl::string_view text, IntType& dst) {\n  text = absl::StripAsciiWhitespace(text);\n\n  return absl::numbers_internal::safe_strtoi_base(text, &dst,\n                                                  NumericBase(text));\n}\n\nbool AbslParseFlag(absl::string_view text, short* dst, std::string*) {\n  int val;\n  if (!ParseFlagImpl(text, val)) return false;\n  if (static_cast<short>(val) != val)  // worked, but number out of range\n    return false;\n  *dst = static_cast<short>(val);\n  return true;\n}\n\nbool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {\n  unsigned int val;\n  if (!ParseFlagImpl(text, val)) return false;\n  if (static_cast<unsigned short>(val) !=\n      val)  // worked, but number out of range\n    return false;\n  *dst = static_cast<unsigned short>(val);\n  return true;\n}\n\nbool AbslParseFlag(absl::string_view text, int* dst, std::string*) {\n  return ParseFlagImpl(text, *dst);\n}\n\nbool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {\n  return ParseFlagImpl(text, *dst);\n}\n\nbool AbslParseFlag(absl::string_view text, long* dst, std::string*) {\n  return ParseFlagImpl(text, *dst);\n}\n\nbool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {\n  return ParseFlagImpl(text, *dst);\n}\n\nbool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {\n  return ParseFlagImpl(text, *dst);\n}\n\nbool AbslParseFlag(absl::string_view text, unsigned long long* dst,\n                   std::string*) {\n  return ParseFlagImpl(text, *dst);\n}\n\nbool AbslParseFlag(absl::string_view text, absl::int128* dst, std::string*) {\n  text = absl::StripAsciiWhitespace(text);\n\n  // check hex\n  int base = NumericBase(text);\n  if (!absl::numbers_internal::safe_strto128_base(text, dst, base)) {\n    return false;\n  }\n\n  return base == 16 ? absl::SimpleHexAtoi(text, dst)\n                    : absl::SimpleAtoi(text, dst);\n}\n\nbool AbslParseFlag(absl::string_view text, absl::uint128* dst, std::string*) {\n  text = absl::StripAsciiWhitespace(text);\n\n  // check hex\n  int base = NumericBase(text);\n  if (!absl::numbers_internal::safe_strtou128_base(text, dst, base)) {\n    return false;\n  }\n\n  return base == 16 ? absl::SimpleHexAtoi(text, dst)\n                    : absl::SimpleAtoi(text, dst);\n}\n\n// --------------------------------------------------------------------\n// AbslParseFlag for floating point types.\n\nbool AbslParseFlag(absl::string_view text, float* dst, std::string*) {\n  return absl::SimpleAtof(text, dst);\n}\n\nbool AbslParseFlag(absl::string_view text, double* dst, std::string*) {\n  return absl::SimpleAtod(text, dst);\n}\n\n// --------------------------------------------------------------------\n// AbslParseFlag for strings.\n\nbool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) {\n  dst->assign(text.data(), text.size());\n  return true;\n}\n\n// --------------------------------------------------------------------\n// AbslParseFlag for vector of strings.\n\nbool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst,\n                   std::string*) {\n  // An empty flag value corresponds to an empty vector, not a vector\n  // with a single, empty std::string.\n  if (text.empty()) {\n    dst->clear();\n    return true;\n  }\n  *dst = absl::StrSplit(text, ',', absl::AllowEmpty());\n  return true;\n}\n\n// --------------------------------------------------------------------\n// AbslUnparseFlag specializations for various builtin flag types.\n\nstd::string Unparse(bool v) { return v ? \"true\" : \"false\"; }\nstd::string Unparse(short v) { return absl::StrCat(v); }\nstd::string Unparse(unsigned short v) { return absl::StrCat(v); }\nstd::string Unparse(int v) { return absl::StrCat(v); }\nstd::string Unparse(unsigned int v) { return absl::StrCat(v); }\nstd::string Unparse(long v) { return absl::StrCat(v); }\nstd::string Unparse(unsigned long v) { return absl::StrCat(v); }\nstd::string Unparse(long long v) { return absl::StrCat(v); }\nstd::string Unparse(unsigned long long v) { return absl::StrCat(v); }\nstd::string Unparse(absl::int128 v) {\n  std::stringstream ss;\n  ss << v;\n  return ss.str();\n}\nstd::string Unparse(absl::uint128 v) {\n  std::stringstream ss;\n  ss << v;\n  return ss.str();\n}\n\ntemplate <typename T>\nstd::string UnparseFloatingPointVal(T v) {\n  // digits10 is guaranteed to roundtrip correctly in string -> value -> string\n  // conversions, but may not be enough to represent all the values correctly.\n  std::string digit10_str =\n      absl::StrFormat(\"%.*g\", std::numeric_limits<T>::digits10, v);\n  if (std::isnan(v) || std::isinf(v)) return digit10_str;\n\n  T roundtrip_val = 0;\n  std::string err;\n  if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) &&\n      roundtrip_val == v) {\n    return digit10_str;\n  }\n\n  // max_digits10 is the number of base-10 digits that are necessary to uniquely\n  // represent all distinct values.\n  return absl::StrFormat(\"%.*g\", std::numeric_limits<T>::max_digits10, v);\n}\nstd::string Unparse(float v) { return UnparseFloatingPointVal(v); }\nstd::string Unparse(double v) { return UnparseFloatingPointVal(v); }\nstd::string AbslUnparseFlag(absl::string_view v) { return std::string(v); }\nstd::string AbslUnparseFlag(const std::vector<std::string>& v) {\n  return absl::StrJoin(v, \",\");\n}\n\n}  // namespace flags_internal\n\nbool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst,\n                   std::string* err) {\n  text = absl::StripAsciiWhitespace(text);\n  if (text.empty()) {\n    *err = \"no value provided\";\n    return false;\n  }\n  if (absl::EqualsIgnoreCase(text, \"dfatal\")) {\n    *dst = absl::kLogDebugFatal;\n    return true;\n  }\n  if (absl::EqualsIgnoreCase(text, \"klogdebugfatal\")) {\n    *dst = absl::kLogDebugFatal;\n    return true;\n  }\n  if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1);\n  if (absl::EqualsIgnoreCase(text, \"info\")) {\n    *dst = absl::LogSeverity::kInfo;\n    return true;\n  }\n  if (absl::EqualsIgnoreCase(text, \"warning\")) {\n    *dst = absl::LogSeverity::kWarning;\n    return true;\n  }\n  if (absl::EqualsIgnoreCase(text, \"error\")) {\n    *dst = absl::LogSeverity::kError;\n    return true;\n  }\n  if (absl::EqualsIgnoreCase(text, \"fatal\")) {\n    *dst = absl::LogSeverity::kFatal;\n    return true;\n  }\n  std::underlying_type<absl::LogSeverity>::type numeric_value;\n  if (absl::ParseFlag(text, &numeric_value, err)) {\n    *dst = static_cast<absl::LogSeverity>(numeric_value);\n    return true;\n  }\n  *err =\n      \"only integers, absl::LogSeverity enumerators, and DFATAL are accepted\";\n  return false;\n}\n\nstd::string AbslUnparseFlag(absl::LogSeverity v) {\n  if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v);\n  return absl::UnparseFlag(static_cast<int>(v));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/marshalling.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: marshalling.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the API for extending Abseil flag support to\n// custom types, and defines the set of overloads for fundamental types.\n//\n// Out of the box, the Abseil flags library supports the following types:\n//\n// * `bool`\n// * `int16_t`\n// * `uint16_t`\n// * `int32_t`\n// * `uint32_t`\n// * `int64_t`\n// * `uint64_t`\n// * `float`\n// * `double`\n// * `std::string`\n// * `std::vector<std::string>`\n// * `std::optional<T>`\n// * `absl::LogSeverity` (provided natively for layering reasons)\n//\n// Note that support for integral types is implemented using overloads for\n// variable-width fundamental types (`short`, `int`, `long`, etc.). However,\n// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,\n// etc.) we've noted above within flag definitions.\n//\n// In addition, several Abseil libraries provide their own custom support for\n// Abseil flags. Documentation for these formats is provided in the type's\n// `AbslParseFlag()` definition.\n//\n// The Abseil time library provides the following support for civil time values:\n//\n// * `absl::CivilSecond`\n// * `absl::CivilMinute`\n// * `absl::CivilHour`\n// * `absl::CivilDay`\n// * `absl::CivilMonth`\n// * `absl::CivilYear`\n//\n// and also provides support for the following absolute time values:\n//\n// * `absl::Duration`\n// * `absl::Time`\n//\n// Additional support for Abseil types will be noted here as it is added.\n//\n// You can also provide your own custom flags by adding overloads for\n// `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See\n// below.)\n//\n// -----------------------------------------------------------------------------\n// Optional Flags\n// -----------------------------------------------------------------------------\n//\n// The Abseil flags library supports flags of type `std::optional<T>` where\n// `T` is a type of one of the supported flags. We refer to this flag type as\n// an \"optional flag.\" An optional flag is either \"valueless\", holding no value\n// of type `T` (indicating that the flag has not been set) or a value of type\n// `T`. The valueless state in C++ code is represented by a value of\n// `std::nullopt` for the optional flag.\n//\n// Using `std::nullopt` as an optional flag's default value allows you to check\n// whether such a flag was ever specified on the command line:\n//\n//   if (absl::GetFlag(FLAGS_foo).has_value()) {\n//     // flag was set on command line\n//   } else {\n//     // flag was not passed on command line\n//   }\n//\n// Using an optional flag in this manner avoids common workarounds for\n// indicating such an unset flag (such as using sentinel values to indicate this\n// state).\n//\n// An optional flag also allows a developer to pass a flag in an \"unset\"\n// valueless state on the command line, allowing the flag to later be set in\n// binary logic. An optional flag's valueless state is indicated by the special\n// notation of passing the value as an empty string through the syntax `--flag=`\n// or `--flag \"\"`.\n//\n//   $ binary_with_optional --flag_in_unset_state=\n//   $ binary_with_optional --flag_in_unset_state \"\"\n//\n// Note: as a result of the above syntax requirements, an optional flag cannot\n// be set to a `T` of any value which unparses to the empty string.\n//\n// -----------------------------------------------------------------------------\n// Adding Type Support for Abseil Flags\n// -----------------------------------------------------------------------------\n//\n// To add support for your user-defined type, add overloads of `AbslParseFlag()`\n// and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T`\n// is a class type, these functions can be friend function definitions. These\n// overloads must be added to the same namespace where the type is defined, so\n// that they can be discovered by Argument-Dependent Lookup (ADL).\n//\n// Example:\n//\n//   namespace foo {\n//\n//   enum OutputMode { kPlainText, kHtml };\n//\n//   // AbslParseFlag converts from a string to OutputMode.\n//   // Must be in same namespace as OutputMode.\n//\n//   // Parses an OutputMode from the command line flag value `text`. Returns\n//   // `true` and sets `*mode` on success; returns `false` and sets `*error`\n//   // on failure.\n//   bool AbslParseFlag(absl::string_view text,\n//                      OutputMode* mode,\n//                      std::string* error) {\n//     if (text == \"plaintext\") {\n//       *mode = kPlainText;\n//       return true;\n//     }\n//     if (text == \"html\") {\n//       *mode = kHtml;\n//      return true;\n//     }\n//     *error = \"unknown value for enumeration\";\n//     return false;\n//  }\n//\n//  // AbslUnparseFlag converts from an OutputMode to a string.\n//  // Must be in same namespace as OutputMode.\n//\n//  // Returns a textual flag value corresponding to the OutputMode `mode`.\n//  std::string AbslUnparseFlag(OutputMode mode) {\n//    switch (mode) {\n//      case kPlainText: return \"plaintext\";\n//      case kHtml: return \"html\";\n//    }\n//    return absl::StrCat(mode);\n//  }\n//\n// Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class\n// members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads\n// for a type should only be declared in the same file and namespace as said\n// type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a\n// given type will be discovered via Argument-Dependent Lookup (ADL).\n//\n// `AbslParseFlag()` may need, in turn, to parse simpler constituent types\n// using `absl::ParseFlag()`. For example, a custom struct `MyFlagType`\n// consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()`\n// overload for its `MyFlagType` like so:\n//\n// Example:\n//\n//   namespace my_flag_type {\n//\n//   struct MyFlagType {\n//     std::pair<int, std::string> my_flag_data;\n//   };\n//\n//   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,\n//                      std::string* err);\n//\n//   std::string AbslUnparseFlag(const MyFlagType&);\n//\n//   // Within the implementation, `AbslParseFlag()` will, in turn invoke\n//   // `absl::ParseFlag()` on its constituent `int` and `std::string` types\n//   // (which have built-in Abseil flag support).\n//\n//   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,\n//                      std::string* err) {\n//     std::pair<absl::string_view, absl::string_view> tokens =\n//         absl::StrSplit(text, ',');\n//     if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err))\n//         return false;\n//     if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err))\n//         return false;\n//     return true;\n//   }\n//\n//   // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on\n//   // the constituent types.\n//   std::string AbslUnparseFlag(const MyFlagType& flag) {\n//     return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first),\n//                         \",\",\n//                         absl::UnparseFlag(flag.my_flag_data.second));\n//   }\n#ifndef ABSL_FLAGS_MARSHALLING_H_\n#define ABSL_FLAGS_MARSHALLING_H_\n\n#include <optional>\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Forward declaration to be used inside composable flag parse/unparse\n// implementations\ntemplate <typename T>\ninline bool ParseFlag(absl::string_view input, T* dst, std::string* error);\ntemplate <typename T>\ninline std::string UnparseFlag(const T& v);\n\nnamespace flags_internal {\n\n// Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.\nbool AbslParseFlag(absl::string_view, bool*, std::string*);\nbool AbslParseFlag(absl::string_view, short*, std::string*);           // NOLINT\nbool AbslParseFlag(absl::string_view, unsigned short*, std::string*);  // NOLINT\nbool AbslParseFlag(absl::string_view, int*, std::string*);             // NOLINT\nbool AbslParseFlag(absl::string_view, unsigned int*, std::string*);    // NOLINT\nbool AbslParseFlag(absl::string_view, long*, std::string*);            // NOLINT\nbool AbslParseFlag(absl::string_view, unsigned long*, std::string*);   // NOLINT\nbool AbslParseFlag(absl::string_view, long long*, std::string*);       // NOLINT\nbool AbslParseFlag(absl::string_view, unsigned long long*,             // NOLINT\n                   std::string*);\nbool AbslParseFlag(absl::string_view, absl::int128*, std::string*);    // NOLINT\nbool AbslParseFlag(absl::string_view, absl::uint128*, std::string*);   // NOLINT\nbool AbslParseFlag(absl::string_view, float*, std::string*);\nbool AbslParseFlag(absl::string_view, double*, std::string*);\nbool AbslParseFlag(absl::string_view, std::string*, std::string*);\nbool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*);\n\ntemplate <typename T>\nbool AbslParseFlag(absl::string_view text, std::optional<T>* f,\n                   std::string* err) {\n  if (text.empty()) {\n    *f = std::nullopt;\n    return true;\n  }\n  T value;\n  if (!absl::ParseFlag(text, &value, err)) return false;\n\n  *f = std::move(value);\n  return true;\n}\n\ntemplate <typename T>\nbool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) {\n  // Comment on next line provides a good compiler error message if T\n  // does not have AbslParseFlag(absl::string_view, T*, std::string*).\n  return AbslParseFlag(input, dst, err);  // Is T missing AbslParseFlag?\n}\n\n// Strings and std:: containers do not have the same overload resolution\n// considerations as fundamental types. Naming these 'AbslUnparseFlag' means we\n// can avoid the need for additional specializations of Unparse (below).\nstd::string AbslUnparseFlag(absl::string_view v);\nstd::string AbslUnparseFlag(const std::vector<std::string>&);\n\ntemplate <typename T>\nstd::string AbslUnparseFlag(const std::optional<T>& f) {\n  return f.has_value() ? absl::UnparseFlag(*f) : \"\";\n}\n\ntemplate <typename T>\nstd::string Unparse(const T& v) {\n  // Comment on next line provides a good compiler error message if T does not\n  // have UnparseFlag.\n  return AbslUnparseFlag(v);  // Is T missing AbslUnparseFlag?\n}\n\n// Overloads for builtin types.\nstd::string Unparse(bool v);\nstd::string Unparse(short v);               // NOLINT\nstd::string Unparse(unsigned short v);      // NOLINT\nstd::string Unparse(int v);                 // NOLINT\nstd::string Unparse(unsigned int v);        // NOLINT\nstd::string Unparse(long v);                // NOLINT\nstd::string Unparse(unsigned long v);       // NOLINT\nstd::string Unparse(long long v);           // NOLINT\nstd::string Unparse(unsigned long long v);  // NOLINT\nstd::string Unparse(absl::int128 v);\nstd::string Unparse(absl::uint128 v);\nstd::string Unparse(float v);\nstd::string Unparse(double v);\n\n}  // namespace flags_internal\n\n// ParseFlag()\n//\n// Parses a string value into a flag value of type `T`. Do not add overloads of\n// this function for your type directly; instead, add an `AbslParseFlag()`\n// free function as documented above.\n//\n// Some implementations of `AbslParseFlag()` for types which consist of other,\n// constituent types which already have Abseil flag support, may need to call\n// `absl::ParseFlag()` on those consituent string values. (See above.)\ntemplate <typename T>\ninline bool ParseFlag(absl::string_view input, T* dst, std::string* error) {\n  return flags_internal::InvokeParseFlag(input, dst, error);\n}\n\n// UnparseFlag()\n//\n// Unparses a flag value of type `T` into a string value. Do not add overloads\n// of this function for your type directly; instead, add an `AbslUnparseFlag()`\n// free function as documented above.\n//\n// Some implementations of `AbslUnparseFlag()` for types which consist of other,\n// constituent types which already have Abseil flag support, may want to call\n// `absl::UnparseFlag()` on those constituent types. (See above.)\ntemplate <typename T>\ninline std::string UnparseFlag(const T& v) {\n  return flags_internal::Unparse(v);\n}\n\n// Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's\n// definition because it is layered below flags.  See proper documentation in\n// base/log_severity.h.\nenum class LogSeverity : int;\nbool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*);\nstd::string AbslUnparseFlag(absl::LogSeverity);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_MARSHALLING_H_\n"
  },
  {
    "path": "absl/flags/marshalling_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/marshalling.h\"\n\n#include <stdint.h>\n\n#include <cmath>\n#include <limits>\n#include <optional>\n#include <string>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nTEST(MarshallingTest, TestBoolParsing) {\n  std::string err;\n  bool value;\n\n  // True values.\n  EXPECT_TRUE(absl::ParseFlag(\"True\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"true\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"TRUE\", &value, &err));\n  EXPECT_TRUE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"Yes\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"yes\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"YES\", &value, &err));\n  EXPECT_TRUE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"t\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"T\", &value, &err));\n  EXPECT_TRUE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"y\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"Y\", &value, &err));\n  EXPECT_TRUE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_TRUE(value);\n\n  // False values.\n  EXPECT_TRUE(absl::ParseFlag(\"False\", &value, &err));\n  EXPECT_FALSE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"false\", &value, &err));\n  EXPECT_FALSE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"FALSE\", &value, &err));\n  EXPECT_FALSE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"No\", &value, &err));\n  EXPECT_FALSE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"no\", &value, &err));\n  EXPECT_FALSE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"NO\", &value, &err));\n  EXPECT_FALSE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"f\", &value, &err));\n  EXPECT_FALSE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"F\", &value, &err));\n  EXPECT_FALSE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"n\", &value, &err));\n  EXPECT_FALSE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"N\", &value, &err));\n  EXPECT_FALSE(value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_FALSE(value);\n\n  // Whitespace handling.\n  EXPECT_TRUE(absl::ParseFlag(\"  true\", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"true  \", &value, &err));\n  EXPECT_TRUE(value);\n  EXPECT_TRUE(absl::ParseFlag(\"  true   \", &value, &err));\n  EXPECT_TRUE(value);\n\n  // Invalid input.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"11\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"tt\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt16Parsing) {\n  std::string err;\n  int16_t value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_EQ(value, -1);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"-18765\", &value, &err));\n  EXPECT_EQ(value, -18765);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"-001\", &value, &err));\n  EXPECT_EQ(value, -1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0X234\", &value, &err));\n  EXPECT_EQ(value, 564);\n  EXPECT_TRUE(absl::ParseFlag(\"-0x7FFD\", &value, &err));\n  EXPECT_EQ(value, -32765);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10  \", &value, &err));\n  EXPECT_EQ(value, 10);\n  EXPECT_TRUE(absl::ParseFlag(\"  11\", &value, &err));\n  EXPECT_EQ(value, 11);\n  EXPECT_TRUE(absl::ParseFlag(\"  012  \", &value, &err));\n  EXPECT_EQ(value, 12);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x22    \", &value, &err));\n  EXPECT_EQ(value, 34);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"40000\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint16Parsing) {\n  std::string err;\n  uint16_t value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"001\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0X234\", &value, &err));\n  EXPECT_EQ(value, 564);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10  \", &value, &err));\n  EXPECT_EQ(value, 10);\n  EXPECT_TRUE(absl::ParseFlag(\"  11\", &value, &err));\n  EXPECT_EQ(value, 11);\n  EXPECT_TRUE(absl::ParseFlag(\"  012  \", &value, &err));\n  EXPECT_EQ(value, 12);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x22    \", &value, &err));\n  EXPECT_EQ(value, 34);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"70000\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt32Parsing) {\n  std::string err;\n  int32_t value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_EQ(value, -1);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"-98765\", &value, &err));\n  EXPECT_EQ(value, -98765);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"-001\", &value, &err));\n  EXPECT_EQ(value, -1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0X234\", &value, &err));\n  EXPECT_EQ(value, 564);\n\n  EXPECT_TRUE(absl::ParseFlag(\"-0x7FFFFFFD\", &value, &err));\n  EXPECT_EQ(value, -2147483645);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10  \", &value, &err));\n  EXPECT_EQ(value, 10);\n  EXPECT_TRUE(absl::ParseFlag(\"  11\", &value, &err));\n  EXPECT_EQ(value, 11);\n  EXPECT_TRUE(absl::ParseFlag(\"  012  \", &value, &err));\n  EXPECT_EQ(value, 12);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x22    \", &value, &err));\n  EXPECT_EQ(value, 34);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"70000000000\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint32Parsing) {\n  std::string err;\n  uint32_t value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0X234\", &value, &err));\n  EXPECT_EQ(value, 564);\n  EXPECT_TRUE(absl::ParseFlag(\"0xFFFFFFFD\", &value, &err));\n  EXPECT_EQ(value, 4294967293);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10  \", &value, &err));\n  EXPECT_EQ(value, 10);\n  EXPECT_TRUE(absl::ParseFlag(\"  11\", &value, &err));\n  EXPECT_EQ(value, 11);\n  EXPECT_TRUE(absl::ParseFlag(\"  012  \", &value, &err));\n  EXPECT_EQ(value, 12);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x22    \", &value, &err));\n  EXPECT_EQ(value, 34);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"140000000000\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt64Parsing) {\n  std::string err;\n  int64_t value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_EQ(value, -1);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"-98765\", &value, &err));\n  EXPECT_EQ(value, -98765);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"001\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0XFFFAAABBBCCCDDD\", &value, &err));\n  EXPECT_EQ(value, 1152827684197027293);\n  EXPECT_TRUE(absl::ParseFlag(\"-0x7FFFFFFFFFFFFFFE\", &value, &err));\n  EXPECT_EQ(value, -9223372036854775806);\n  EXPECT_TRUE(absl::ParseFlag(\"-0x02\", &value, &err));\n  EXPECT_EQ(value, -2);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10  \", &value, &err));\n  EXPECT_EQ(value, 10);\n  EXPECT_TRUE(absl::ParseFlag(\"  11\", &value, &err));\n  EXPECT_EQ(value, 11);\n  EXPECT_TRUE(absl::ParseFlag(\"  012  \", &value, &err));\n  EXPECT_EQ(value, 12);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x7F    \", &value, &err));\n  EXPECT_EQ(value, 127);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"0xFFFFFFFFFFFFFFFFFF\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUInt64Parsing) {\n  std::string err;\n  uint64_t value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"+13\", &value, &err));\n  EXPECT_EQ(value, 13);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"001\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000300\", &value, &err));\n  EXPECT_EQ(value, 300);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0XFFFF\", &value, &err));\n  EXPECT_EQ(value, 65535);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10  \", &value, &err));\n  EXPECT_EQ(value, 10);\n  EXPECT_TRUE(absl::ParseFlag(\"  11\", &value, &err));\n  EXPECT_EQ(value, 11);\n  EXPECT_TRUE(absl::ParseFlag(\"  012  \", &value, &err));\n  EXPECT_EQ(value, 12);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"0xFFFFFFFFFFFFFFFFFF\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt128Parsing) {\n  std::string err;\n  absl::int128 value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_EQ(value, -1);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"-98765\", &value, &err));\n  EXPECT_EQ(value, -98765);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"001\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0xFFFAAABBBCCCDDD\", &value, &err));\n  EXPECT_EQ(value, 1152827684197027293);\n  EXPECT_TRUE(absl::ParseFlag(\"0xFFF0FFFFFFFFFFFFFFF\", &value, &err));\n  EXPECT_EQ(value, absl::MakeInt128(0x000000000000fff, 0xFFFFFFFFFFFFFFF));\n\n  EXPECT_TRUE(absl::ParseFlag(\"-0x10000000000000000\", &value, &err));\n  EXPECT_EQ(value, absl::MakeInt128(-1, 0));\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"16  \", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"  16\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"  0100  \", &value, &err));\n  EXPECT_EQ(value, 100);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x7B    \", &value, &err));\n  EXPECT_EQ(value, 123);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint128Parsing) {\n  std::string err;\n  absl::uint128 value;\n\n  // Decimal values.\n  EXPECT_TRUE(absl::ParseFlag(\"0\", &value, &err));\n  EXPECT_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"123\", &value, &err));\n  EXPECT_EQ(value, 123);\n  EXPECT_TRUE(absl::ParseFlag(\"+3\", &value, &err));\n  EXPECT_EQ(value, 3);\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"001\", &value, &err));\n  EXPECT_EQ(value, 1);\n  EXPECT_TRUE(absl::ParseFlag(\"0000100\", &value, &err));\n  EXPECT_EQ(value, 100);\n\n  // Hex values.\n  EXPECT_TRUE(absl::ParseFlag(\"0x10\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"0xFFFAAABBBCCCDDD\", &value, &err));\n  EXPECT_EQ(value, 1152827684197027293);\n  EXPECT_TRUE(absl::ParseFlag(\"0xFFF0FFFFFFFFFFFFFFF\", &value, &err));\n  EXPECT_EQ(value, absl::MakeInt128(0x000000000000fff, 0xFFFFFFFFFFFFFFF));\n  EXPECT_TRUE(absl::ParseFlag(\"+0x31\", &value, &err));\n  EXPECT_EQ(value, 49);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"16  \", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"  16\", &value, &err));\n  EXPECT_EQ(value, 16);\n  EXPECT_TRUE(absl::ParseFlag(\"  0100  \", &value, &err));\n  EXPECT_EQ(value, 100);\n  EXPECT_TRUE(absl::ParseFlag(\" 0x7B    \", &value, &err));\n  EXPECT_EQ(value, 123);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"-1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2U\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"FFF\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"-0x10000000000000000\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestFloatParsing) {\n  std::string err;\n  float value;\n\n  // Ordinary values.\n  EXPECT_TRUE(absl::ParseFlag(\"1.3\", &value, &err));\n  EXPECT_FLOAT_EQ(value, 1.3f);\n  EXPECT_TRUE(absl::ParseFlag(\"-0.1\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, -0.1f);\n  EXPECT_TRUE(absl::ParseFlag(\"+0.01\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.01f);\n\n  // Scientific values.\n  EXPECT_TRUE(absl::ParseFlag(\"1.2e3\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 1.2e3f);\n  EXPECT_TRUE(absl::ParseFlag(\"9.8765402e-37\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 9.8765402e-37f);\n  EXPECT_TRUE(absl::ParseFlag(\"0.11e+3\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.11e+3f);\n  EXPECT_TRUE(absl::ParseFlag(\"1.e-2300\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.f);\n  EXPECT_TRUE(absl::ParseFlag(\"1.e+2300\", &value, &err));\n  EXPECT_TRUE(std::isinf(value));\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01.6\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 1.6f);\n  EXPECT_TRUE(absl::ParseFlag(\"000.0001\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.0001f);\n\n  // Trailing zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"-5.1000\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, -5.1f);\n\n  // Exceptional values.\n  EXPECT_TRUE(absl::ParseFlag(\"NaN\", &value, &err));\n  EXPECT_TRUE(std::isnan(value));\n  EXPECT_TRUE(absl::ParseFlag(\"Inf\", &value, &err));\n  EXPECT_TRUE(std::isinf(value));\n\n  // Hex values\n  EXPECT_TRUE(absl::ParseFlag(\"0x10.23p12\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 66096.f);\n  EXPECT_TRUE(absl::ParseFlag(\"-0xF1.A3p-2\", &value, &err));\n  EXPECT_NEAR(value, -60.4092f, 5e-5f);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x0.0AAp-12\", &value, &err));\n  EXPECT_NEAR(value, 1.01328e-05f, 5e-11f);\n  EXPECT_TRUE(absl::ParseFlag(\"0x.01p1\", &value, &err));\n  EXPECT_NEAR(value, 0.0078125f, 5e-8f);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10.1  \", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 10.1f);\n  EXPECT_TRUE(absl::ParseFlag(\"  2.34\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 2.34f);\n  EXPECT_TRUE(absl::ParseFlag(\"  5.7  \", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 5.7f);\n  EXPECT_TRUE(absl::ParseFlag(\"  -0xE0.F3p01  \", &value, &err));\n  EXPECT_NEAR(value, -449.8984375f, 5e-8f);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2.3xxx\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"0x0.1pAA\", &value, &err));\n  // TODO(rogeeff): below assertion should fail\n  EXPECT_TRUE(absl::ParseFlag(\"0x0.1\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestDoubleParsing) {\n  std::string err;\n  double value;\n\n  // Ordinary values.\n  EXPECT_TRUE(absl::ParseFlag(\"1.3\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 1.3);\n  EXPECT_TRUE(absl::ParseFlag(\"-0.1\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, -0.1);\n  EXPECT_TRUE(absl::ParseFlag(\"+0.01\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.01);\n\n  // Scientific values.\n  EXPECT_TRUE(absl::ParseFlag(\"1.2e3\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 1.2e3);\n  EXPECT_TRUE(absl::ParseFlag(\"9.00000002e-123\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 9.00000002e-123);\n  EXPECT_TRUE(absl::ParseFlag(\"0.11e+3\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.11e+3);\n  EXPECT_TRUE(absl::ParseFlag(\"1.e-2300\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0);\n  EXPECT_TRUE(absl::ParseFlag(\"1.e+2300\", &value, &err));\n  EXPECT_TRUE(std::isinf(value));\n\n  // Leading zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"01.6\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 1.6);\n  EXPECT_TRUE(absl::ParseFlag(\"000.0001\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 0.0001);\n\n  // Trailing zero values.\n  EXPECT_TRUE(absl::ParseFlag(\"-5.1000\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, -5.1);\n\n  // Exceptional values.\n  EXPECT_TRUE(absl::ParseFlag(\"NaN\", &value, &err));\n  EXPECT_TRUE(std::isnan(value));\n  EXPECT_TRUE(absl::ParseFlag(\"nan\", &value, &err));\n  EXPECT_TRUE(std::isnan(value));\n  EXPECT_TRUE(absl::ParseFlag(\"Inf\", &value, &err));\n  EXPECT_TRUE(std::isinf(value));\n  EXPECT_TRUE(absl::ParseFlag(\"inf\", &value, &err));\n  EXPECT_TRUE(std::isinf(value));\n\n  // Hex values\n  EXPECT_TRUE(absl::ParseFlag(\"0x10.23p12\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 66096);\n  EXPECT_TRUE(absl::ParseFlag(\"-0xF1.A3p-2\", &value, &err));\n  EXPECT_NEAR(value, -60.4092, 5e-5);\n  EXPECT_TRUE(absl::ParseFlag(\"+0x0.0AAp-12\", &value, &err));\n  EXPECT_NEAR(value, 1.01328e-05, 5e-11);\n  EXPECT_TRUE(absl::ParseFlag(\"0x.01p1\", &value, &err));\n  EXPECT_NEAR(value, 0.0078125, 5e-8);\n\n  // Whitespace handling\n  EXPECT_TRUE(absl::ParseFlag(\"10.1  \", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 10.1);\n  EXPECT_TRUE(absl::ParseFlag(\"  2.34\", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 2.34);\n  EXPECT_TRUE(absl::ParseFlag(\"  5.7  \", &value, &err));\n  EXPECT_DOUBLE_EQ(value, 5.7);\n  EXPECT_TRUE(absl::ParseFlag(\"  -0xE0.F3p01  \", &value, &err));\n  EXPECT_NEAR(value, -449.8984375, 5e-8);\n\n  // Invalid values.\n  EXPECT_FALSE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"  \", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"--1\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"2.3xxx\", &value, &err));\n  EXPECT_FALSE(absl::ParseFlag(\"0x0.1pAA\", &value, &err));\n  // TODO(rogeeff): below assertion should fail\n  EXPECT_TRUE(absl::ParseFlag(\"0x0.1\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestStringParsing) {\n  std::string err;\n  std::string value;\n\n  EXPECT_TRUE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_EQ(value, \"\");\n  EXPECT_TRUE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_EQ(value, \" \");\n  EXPECT_TRUE(absl::ParseFlag(\"   \", &value, &err));\n  EXPECT_EQ(value, \"   \");\n  EXPECT_TRUE(absl::ParseFlag(\"\\n\", &value, &err));\n  EXPECT_EQ(value, \"\\n\");\n  EXPECT_TRUE(absl::ParseFlag(\"\\t\", &value, &err));\n  EXPECT_EQ(value, \"\\t\");\n  EXPECT_TRUE(absl::ParseFlag(\"asdfg\", &value, &err));\n  EXPECT_EQ(value, \"asdfg\");\n  EXPECT_TRUE(absl::ParseFlag(\"asdf ghjk\", &value, &err));\n  EXPECT_EQ(value, \"asdf ghjk\");\n  EXPECT_TRUE(absl::ParseFlag(\"a\\nb\\nc\", &value, &err));\n  EXPECT_EQ(value, \"a\\nb\\nc\");\n  EXPECT_TRUE(absl::ParseFlag(\"asd\\0fgh\", &value, &err));\n  EXPECT_EQ(value, \"asd\");\n  EXPECT_TRUE(absl::ParseFlag(\"\\\\\\\\\", &value, &err));\n  EXPECT_EQ(value, \"\\\\\\\\\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestVectorOfStringParsing) {\n  std::string err;\n  std::vector<std::string> value;\n\n  EXPECT_TRUE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>{});\n  EXPECT_TRUE(absl::ParseFlag(\"1\", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>({\"1\"}));\n  EXPECT_TRUE(absl::ParseFlag(\"a,b\", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>({\"a\", \"b\"}));\n  EXPECT_TRUE(absl::ParseFlag(\"a,b,c,\", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>({\"a\", \"b\", \"c\", \"\"}));\n  EXPECT_TRUE(absl::ParseFlag(\"a,,\", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>({\"a\", \"\", \"\"}));\n  EXPECT_TRUE(absl::ParseFlag(\",\", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>({\"\", \"\"}));\n  EXPECT_TRUE(absl::ParseFlag(\"a, b,c \", &value, &err));\n  EXPECT_EQ(value, std::vector<std::string>({\"a\", \" b\", \"c \"}));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalBoolParsing) {\n  std::string err;\n  std::optional<bool> value;\n\n  EXPECT_TRUE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(value.has_value());\n\n  EXPECT_TRUE(absl::ParseFlag(\"true\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_TRUE(*value);\n\n  EXPECT_TRUE(absl::ParseFlag(\"false\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_FALSE(*value);\n\n  EXPECT_FALSE(absl::ParseFlag(\"nullopt\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalIntParsing) {\n  std::string err;\n  std::optional<int> value;\n\n  EXPECT_TRUE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(value.has_value());\n\n  EXPECT_TRUE(absl::ParseFlag(\"10\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, 10);\n\n  EXPECT_TRUE(absl::ParseFlag(\"0x1F\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, 31);\n\n  EXPECT_FALSE(absl::ParseFlag(\"nullopt\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalDoubleParsing) {\n  std::string err;\n  std::optional<double> value;\n\n  EXPECT_TRUE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(value.has_value());\n\n  EXPECT_TRUE(absl::ParseFlag(\"1.11\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, 1.11);\n\n  EXPECT_TRUE(absl::ParseFlag(\"-0.12\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, -0.12);\n\n  EXPECT_FALSE(absl::ParseFlag(\"nullopt\", &value, &err));\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalStringParsing) {\n  std::string err;\n  std::optional<std::string> value;\n\n  EXPECT_TRUE(absl::ParseFlag(\"\", &value, &err));\n  EXPECT_FALSE(value.has_value());\n\n  EXPECT_TRUE(absl::ParseFlag(\" \", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, \" \");\n\n  EXPECT_TRUE(absl::ParseFlag(\"aqswde\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, \"aqswde\");\n\n  EXPECT_TRUE(absl::ParseFlag(\"nullopt\", &value, &err));\n  EXPECT_TRUE(value.has_value());\n  EXPECT_EQ(*value, \"nullopt\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestBoolUnparsing) {\n  EXPECT_EQ(absl::UnparseFlag(true), \"true\");\n  EXPECT_EQ(absl::UnparseFlag(false), \"false\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt16Unparsing) {\n  int16_t value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = -1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-1\");\n  value = 9876;\n  EXPECT_EQ(absl::UnparseFlag(value), \"9876\");\n  value = -987;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-987\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint16Unparsing) {\n  uint16_t value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = 19876;\n  EXPECT_EQ(absl::UnparseFlag(value), \"19876\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt32Unparsing) {\n  int32_t value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = -1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-1\");\n  value = 12345;\n  EXPECT_EQ(absl::UnparseFlag(value), \"12345\");\n  value = -987;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-987\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint32Unparsing) {\n  uint32_t value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = 1234500;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1234500\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt64Unparsing) {\n  int64_t value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = -1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-1\");\n  value = 123456789L;\n  EXPECT_EQ(absl::UnparseFlag(value), \"123456789\");\n  value = -987654321L;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-987654321\");\n  value = 0x7FFFFFFFFFFFFFFF;\n  EXPECT_EQ(absl::UnparseFlag(value), \"9223372036854775807\");\n  value = 0xFFFFFFFFFFFFFFFF;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-1\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint64Unparsing) {\n  uint64_t value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = 123456789L;\n  EXPECT_EQ(absl::UnparseFlag(value), \"123456789\");\n  value = 0xFFFFFFFFFFFFFFFF;\n  EXPECT_EQ(absl::UnparseFlag(value), \"18446744073709551615\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestInt128Unparsing) {\n  absl::int128 value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = -1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-1\");\n  value = 123456789L;\n  EXPECT_EQ(absl::UnparseFlag(value), \"123456789\");\n  value = -987654321L;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-987654321\");\n  value = 0x7FFFFFFFFFFFFFFF;\n  EXPECT_EQ(absl::UnparseFlag(value), \"9223372036854775807\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestUint128Unparsing) {\n  absl::uint128 value;\n\n  value = 1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = 123456789L;\n  EXPECT_EQ(absl::UnparseFlag(value), \"123456789\");\n  value = absl::MakeUint128(0, 0xFFFFFFFFFFFFFFFF);\n  EXPECT_EQ(absl::UnparseFlag(value), \"18446744073709551615\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestFloatUnparsing) {\n  float value;\n\n  value = 1.1f;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1.1\");\n  value = 0.01f;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0.01\");\n  value = 1.23e-2f;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0.0123\");\n  value = -0.71f;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-0.71\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestDoubleUnparsing) {\n  double value;\n\n  value = 1.1;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1.1\");\n  value = 0.01;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0.01\");\n  value = 1.23e-2;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0.0123\");\n  value = -0.71;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-0.71\");\n  value = -0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = std::nan(\"\");\n  EXPECT_EQ(absl::UnparseFlag(value), \"nan\");\n  value = std::numeric_limits<double>::infinity();\n  EXPECT_EQ(absl::UnparseFlag(value), \"inf\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestStringUnparsing) {\n  EXPECT_EQ(absl::UnparseFlag(\"\"), \"\");\n  EXPECT_EQ(absl::UnparseFlag(\" \"), \" \");\n  EXPECT_EQ(absl::UnparseFlag(\"qwerty\"), \"qwerty\");\n  EXPECT_EQ(absl::UnparseFlag(\"ASDFGH\"), \"ASDFGH\");\n  EXPECT_EQ(absl::UnparseFlag(\"\\n\\t  \"), \"\\n\\t  \");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalBoolUnparsing) {\n  std::optional<bool> value;\n\n  EXPECT_EQ(absl::UnparseFlag(value), \"\");\n  value = true;\n  EXPECT_EQ(absl::UnparseFlag(value), \"true\");\n  value = false;\n  EXPECT_EQ(absl::UnparseFlag(value), \"false\");\n  value = std::nullopt;\n  EXPECT_EQ(absl::UnparseFlag(value), \"\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalIntUnparsing) {\n  std::optional<int> value;\n\n  EXPECT_EQ(absl::UnparseFlag(value), \"\");\n  value = 0;\n  EXPECT_EQ(absl::UnparseFlag(value), \"0\");\n  value = -12;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-12\");\n  value = std::nullopt;\n  EXPECT_EQ(absl::UnparseFlag(value), \"\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalDoubleUnparsing) {\n  std::optional<double> value;\n\n  EXPECT_EQ(absl::UnparseFlag(value), \"\");\n  value = 1.;\n  EXPECT_EQ(absl::UnparseFlag(value), \"1\");\n  value = -1.23;\n  EXPECT_EQ(absl::UnparseFlag(value), \"-1.23\");\n  value = std::nullopt;\n  EXPECT_EQ(absl::UnparseFlag(value), \"\");\n}\n\n// --------------------------------------------------------------------\n\nTEST(MarshallingTest, TestOptionalStringUnparsing) {\n  std::optional<std::string> strvalue;\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \"\");\n\n  strvalue = \"asdfg\";\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \"asdfg\");\n\n  strvalue = \" \";\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \" \");\n\n  strvalue = \"\";  // It is UB to set an optional string flag to \"\"\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \"\");\n}\n\n// --------------------------------------------------------------------\n\n#if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)\n\nTEST(MarshallingTest, TestStdOptionalUnparsing) {\n  std::optional<std::string> strvalue;\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \"\");\n\n  strvalue = \"asdfg\";\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \"asdfg\");\n\n  strvalue = \" \";\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \" \");\n\n  strvalue = \"\";  // It is UB to set an optional string flag to \"\"\n  EXPECT_EQ(absl::UnparseFlag(strvalue), \"\");\n\n  std::optional<int> intvalue;\n  EXPECT_EQ(absl::UnparseFlag(intvalue), \"\");\n\n  intvalue = 10;\n  EXPECT_EQ(absl::UnparseFlag(intvalue), \"10\");\n}\n\n// --------------------------------------------------------------------\n\n#endif\n\ntemplate <typename T>\nvoid TestRoundtrip(T v) {\n  T new_v;\n  std::string err;\n  EXPECT_TRUE(absl::ParseFlag(absl::UnparseFlag(v), &new_v, &err));\n  EXPECT_EQ(new_v, v);\n}\n\nTEST(MarshallingTest, TestFloatRoundTrip) {\n  TestRoundtrip(0.1f);\n  TestRoundtrip(0.12f);\n  TestRoundtrip(0.123f);\n  TestRoundtrip(0.1234f);\n  TestRoundtrip(0.12345f);\n  TestRoundtrip(0.123456f);\n  TestRoundtrip(0.1234567f);\n  TestRoundtrip(0.12345678f);\n\n  TestRoundtrip(0.1e20f);\n  TestRoundtrip(0.12e20f);\n  TestRoundtrip(0.123e20f);\n  TestRoundtrip(0.1234e20f);\n  TestRoundtrip(0.12345e20f);\n  TestRoundtrip(0.123456e20f);\n  TestRoundtrip(0.1234567e20f);\n  TestRoundtrip(0.12345678e20f);\n\n  TestRoundtrip(0.1e-20f);\n  TestRoundtrip(0.12e-20f);\n  TestRoundtrip(0.123e-20f);\n  TestRoundtrip(0.1234e-20f);\n  TestRoundtrip(0.12345e-20f);\n  TestRoundtrip(0.123456e-20f);\n  TestRoundtrip(0.1234567e-20f);\n  TestRoundtrip(0.12345678e-20f);\n}\n\nTEST(MarshallingTest, TestDoubleRoundTrip) {\n  TestRoundtrip(0.1);\n  TestRoundtrip(0.12);\n  TestRoundtrip(0.123);\n  TestRoundtrip(0.1234);\n  TestRoundtrip(0.12345);\n  TestRoundtrip(0.123456);\n  TestRoundtrip(0.1234567);\n  TestRoundtrip(0.12345678);\n  TestRoundtrip(0.123456789);\n  TestRoundtrip(0.1234567891);\n  TestRoundtrip(0.12345678912);\n  TestRoundtrip(0.123456789123);\n  TestRoundtrip(0.1234567891234);\n  TestRoundtrip(0.12345678912345);\n  TestRoundtrip(0.123456789123456);\n  TestRoundtrip(0.1234567891234567);\n  TestRoundtrip(0.12345678912345678);\n\n  TestRoundtrip(0.1e50);\n  TestRoundtrip(0.12e50);\n  TestRoundtrip(0.123e50);\n  TestRoundtrip(0.1234e50);\n  TestRoundtrip(0.12345e50);\n  TestRoundtrip(0.123456e50);\n  TestRoundtrip(0.1234567e50);\n  TestRoundtrip(0.12345678e50);\n  TestRoundtrip(0.123456789e50);\n  TestRoundtrip(0.1234567891e50);\n  TestRoundtrip(0.12345678912e50);\n  TestRoundtrip(0.123456789123e50);\n  TestRoundtrip(0.1234567891234e50);\n  TestRoundtrip(0.12345678912345e50);\n  TestRoundtrip(0.123456789123456e50);\n  TestRoundtrip(0.1234567891234567e50);\n  TestRoundtrip(0.12345678912345678e50);\n\n  TestRoundtrip(0.1e-50);\n  TestRoundtrip(0.12e-50);\n  TestRoundtrip(0.123e-50);\n  TestRoundtrip(0.1234e-50);\n  TestRoundtrip(0.12345e-50);\n  TestRoundtrip(0.123456e-50);\n  TestRoundtrip(0.1234567e-50);\n  TestRoundtrip(0.12345678e-50);\n  TestRoundtrip(0.123456789e-50);\n  TestRoundtrip(0.1234567891e-50);\n  TestRoundtrip(0.12345678912e-50);\n  TestRoundtrip(0.123456789123e-50);\n  TestRoundtrip(0.1234567891234e-50);\n  TestRoundtrip(0.12345678912345e-50);\n  TestRoundtrip(0.123456789123456e-50);\n  TestRoundtrip(0.1234567891234567e-50);\n  TestRoundtrip(0.12345678912345678e-50);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/parse.cc",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/parse.h\"\n\n#include <stdlib.h>\n\n#include <algorithm>\n#include <cstdint>\n#include <cstdlib>\n#include <fstream>\n#include <iostream>\n#include <ostream>\n#include <string>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#include \"absl/algorithm/container.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n#include \"absl/flags/internal/flag.h\"\n#include \"absl/flags/internal/parse.h\"\n#include \"absl/flags/internal/private_handle_accessor.h\"\n#include \"absl/flags/internal/program_name.h\"\n#include \"absl/flags/internal/usage.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/flags/usage.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/internal/damerau_levenshtein_distance.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_join.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/synchronization/mutex.h\"\n\n// --------------------------------------------------------------------\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\nnamespace {\n\nabsl::Mutex& ProcessingChecksMutex() {\n  static absl::NoDestructor<absl::Mutex> mutex;\n  return *mutex;\n}\n\nABSL_CONST_INIT bool flagfile_needs_processing\n    ABSL_GUARDED_BY(ProcessingChecksMutex()) = false;\nABSL_CONST_INIT bool fromenv_needs_processing\n    ABSL_GUARDED_BY(ProcessingChecksMutex()) = false;\nABSL_CONST_INIT bool tryfromenv_needs_processing\n    ABSL_GUARDED_BY(ProcessingChecksMutex()) = false;\n\nabsl::Mutex& SpecifiedFlagsMutex() {\n  static absl::NoDestructor<absl::Mutex> mutex;\n  return *mutex;\n}\n\nABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags\n    ABSL_GUARDED_BY(SpecifiedFlagsMutex()) = nullptr;\n\n// Suggesting at most kMaxHints flags in case of misspellings.\nABSL_CONST_INIT const size_t kMaxHints = 100;\n// Suggesting only flags which have a smaller distance than kMaxDistance.\nABSL_CONST_INIT const size_t kMaxDistance = 3;\n\nstruct SpecifiedFlagsCompare {\n  bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {\n    return a->Name() < b->Name();\n  }\n  bool operator()(const CommandLineFlag* a, absl::string_view b) const {\n    return a->Name() < b;\n  }\n  bool operator()(absl::string_view a, const CommandLineFlag* b) const {\n    return a < b->Name();\n  }\n};\n\n}  // namespace\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// These flags influence how command line flags are parsed and are only intended\n// to be set on the command line.  Avoid reading or setting them from C++ code.\nABSL_FLAG(std::vector<std::string>, flagfile, {},\n          \"comma-separated list of files to load flags from\")\n    .OnUpdate([]() {\n      if (absl::GetFlag(FLAGS_flagfile).empty()) return;\n\n      absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex());\n\n      // Setting this flag twice before it is handled most likely an internal\n      // error and should be reviewed by developers.\n      if (absl::flags_internal::flagfile_needs_processing) {\n        ABSL_INTERNAL_LOG(WARNING, \"flagfile set twice before it is handled\");\n      }\n\n      absl::flags_internal::flagfile_needs_processing = true;\n    });\nABSL_FLAG(std::vector<std::string>, fromenv, {},\n          \"comma-separated list of flags to set from the environment\"\n          \" [use 'export FLAGS_flag1=value']\")\n    .OnUpdate([]() {\n      if (absl::GetFlag(FLAGS_fromenv).empty()) return;\n\n      absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex());\n\n      // Setting this flag twice before it is handled most likely an internal\n      // error and should be reviewed by developers.\n      if (absl::flags_internal::fromenv_needs_processing) {\n        ABSL_INTERNAL_LOG(WARNING, \"fromenv set twice before it is handled.\");\n      }\n\n      absl::flags_internal::fromenv_needs_processing = true;\n    });\nABSL_FLAG(std::vector<std::string>, tryfromenv, {},\n          \"comma-separated list of flags to try to set from the environment if \"\n          \"present\")\n    .OnUpdate([]() {\n      if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;\n\n      absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex());\n\n      // Setting this flag twice before it is handled most likely an internal\n      // error and should be reviewed by developers.\n      if (absl::flags_internal::tryfromenv_needs_processing) {\n        ABSL_INTERNAL_LOG(WARNING,\n                          \"tryfromenv set twice before it is handled.\");\n      }\n\n      absl::flags_internal::tryfromenv_needs_processing = true;\n    });\n\n// Rather than reading or setting --undefok from C++ code, please consider using\n// ABSL_RETIRED_FLAG instead.\nABSL_FLAG(std::vector<std::string>, undefok, {},\n          \"comma-separated list of flag names that it is okay to specify \"\n          \"on the command line even if the program does not define a flag \"\n          \"with that name\");\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\nnamespace {\n\nclass ArgsList {\n public:\n  ArgsList() : next_arg_(0) {}\n  ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}\n  explicit ArgsList(const std::vector<std::string>& args)\n      : args_(args), next_arg_(0) {}\n\n  // Returns success status: true if parsing successful, false otherwise.\n  bool ReadFromFlagfile(const std::string& flag_file_name);\n\n  size_t Size() const { return args_.size() - next_arg_; }\n  size_t FrontIndex() const { return next_arg_; }\n  absl::string_view Front() const { return args_[next_arg_]; }\n  void PopFront() { next_arg_++; }\n\n private:\n  std::vector<std::string> args_;\n  size_t next_arg_;\n};\n\nbool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {\n  std::ifstream flag_file(flag_file_name);\n\n  if (!flag_file) {\n    flags_internal::ReportUsageError(\n        absl::StrCat(\"Can't open flagfile \", flag_file_name), true);\n\n    return false;\n  }\n\n  // This argument represents fake argv[0], which should be present in all arg\n  // lists.\n  args_.emplace_back(\"\");\n\n  std::string line;\n  bool success = true;\n  int line_number = 0;\n\n  while (std::getline(flag_file, line)) {\n    line_number++;\n    absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line);\n\n    if (stripped.empty() || stripped[0] == '#') {\n      // Comment or empty line; just ignore.\n      continue;\n    }\n\n    if (stripped[0] == '-') {\n      if (stripped == \"--\") {\n        flags_internal::ReportUsageError(\n            \"Flagfile can't contain position arguments or --\", true);\n\n        success = false;\n        break;\n      }\n\n      args_.emplace_back(stripped);\n      continue;\n    }\n\n    flags_internal::ReportUsageError(\n        absl::StrCat(\"Unexpected line \", line_number, \" in the flagfile \",\n                     flag_file_name),\n        true);\n\n    success = false;\n  }\n\n  return success;\n}\n\n// --------------------------------------------------------------------\n\n// Reads the environment variable with name `name` and stores results in\n// `value`. If variable is not present in environment returns false, otherwise\n// returns true.\nbool GetEnvVar(const char* var_name, std::string& var_value) {\n#ifdef _WIN32\n  char buf[1024];\n  auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));\n  if (get_res >= sizeof(buf)) {\n    return false;\n  }\n\n  if (get_res == 0) {\n    return false;\n  }\n\n  var_value = std::string(buf, get_res);\n#else\n  const char* val = ::getenv(var_name);\n  if (val == nullptr) {\n    return false;\n  }\n\n  var_value = val;\n#endif\n\n  return true;\n}\n\n// --------------------------------------------------------------------\n\n// Returns:\n//  Flag name or empty if arg= --\n//  Flag value after = in --flag=value (empty if --foo)\n//  \"Is empty value\" status. True if arg= --foo=, false otherwise. This is\n//  required to separate --foo from --foo=.\n// For example:\n//      arg           return values\n//   \"--foo=bar\" -> {\"foo\", \"bar\", false}.\n//   \"--foo\"     -> {\"foo\", \"\", false}.\n//   \"--foo=\"    -> {\"foo\", \"\", true}.\nstd::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(\n    absl::string_view arg) {\n  // Allow -foo and --foo\n  absl::ConsumePrefix(&arg, \"-\");\n\n  if (arg.empty()) {\n    return std::make_tuple(\"\", \"\", false);\n  }\n\n  auto equal_sign_pos = arg.find('=');\n\n  absl::string_view flag_name = arg.substr(0, equal_sign_pos);\n\n  absl::string_view value;\n  bool is_empty_value = false;\n\n  if (equal_sign_pos != absl::string_view::npos) {\n    value = arg.substr(equal_sign_pos + 1);\n    is_empty_value = value.empty();\n  }\n\n  return std::make_tuple(flag_name, value, is_empty_value);\n}\n\n// --------------------------------------------------------------------\n\n// Returns:\n//  found flag or nullptr\n//  is negative in case of --nofoo\nstd::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {\n  CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);\n  bool is_negative = false;\n\n  if (!flag && absl::ConsumePrefix(&flag_name, \"no\")) {\n    flag = absl::FindCommandLineFlag(flag_name);\n    is_negative = true;\n  }\n\n  return std::make_tuple(flag, is_negative);\n}\n\n// --------------------------------------------------------------------\n\n// Verify that default values of typed flags must be convertible to string and\n// back.\nvoid CheckDefaultValuesParsingRoundtrip() {\n#ifndef NDEBUG\n  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {\n    if (flag.IsRetired()) return;\n\n#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \\\n  if (flag.IsOfType<T>()) return;\n\n    ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)\n#undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE\n\n    flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(\n        flag);\n  });\n#endif\n}\n\n// --------------------------------------------------------------------\n\n// Returns success status, which is true if we successfully read all flag files,\n// in which case new ArgLists are appended to the input_args in a reverse order\n// of file names in the input flagfiles list. This order ensures that flags from\n// the first flagfile in the input list are processed before the second flagfile\n// etc.\nbool ReadFlagfiles(const std::vector<std::string>& flagfiles,\n                   std::vector<ArgsList>& input_args) {\n  bool success = true;\n  for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {\n    ArgsList al;\n\n    if (al.ReadFromFlagfile(*it)) {\n      input_args.push_back(al);\n    } else {\n      success = false;\n    }\n  }\n\n  return success;\n}\n\n// Returns success status, which is true if were able to locate all environment\n// variables correctly or if fail_on_absent_in_env is false. The environment\n// variable names are expected to be of the form `FLAGS_<flag_name>`, where\n// `flag_name` is a string from the input flag_names list. If successful we\n// append a single ArgList at the end of the input_args.\nbool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,\n                      std::vector<ArgsList>& input_args,\n                      bool fail_on_absent_in_env) {\n  bool success = true;\n  std::vector<std::string> args;\n\n  // This argument represents fake argv[0], which should be present in all arg\n  // lists.\n  args.emplace_back(\"\");\n\n  for (const auto& flag_name : flag_names) {\n    // Avoid infinite recursion.\n    if (flag_name == \"fromenv\" || flag_name == \"tryfromenv\") {\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Infinite recursion on flag \", flag_name), true);\n\n      success = false;\n      continue;\n    }\n\n    const std::string envname = absl::StrCat(\"FLAGS_\", flag_name);\n    std::string envval;\n    if (!GetEnvVar(envname.c_str(), envval)) {\n      if (fail_on_absent_in_env) {\n        flags_internal::ReportUsageError(\n            absl::StrCat(envname, \" not found in environment\"), true);\n\n        success = false;\n      }\n\n      continue;\n    }\n\n    args.push_back(absl::StrCat(\"--\", flag_name, \"=\", envval));\n  }\n\n  if (success) {\n    input_args.emplace_back(args);\n  }\n\n  return success;\n}\n\n// --------------------------------------------------------------------\n\n// Returns success status, which is true if were able to handle all generator\n// flags (flagfile, fromenv, tryfromemv) successfully.\nbool HandleGeneratorFlags(std::vector<ArgsList>& input_args,\n                          std::vector<std::string>& flagfile_value) {\n  bool success = true;\n\n  absl::MutexLock l(flags_internal::ProcessingChecksMutex());\n\n  // flagfile could have been set either on a command line or\n  // programmatically before invoking ParseCommandLine. Note that we do not\n  // actually process arguments specified in the flagfile, but instead\n  // create a secondary arguments list to be processed along with the rest\n  // of the command line arguments. Since we always the process most recently\n  // created list of arguments first, this will result in flagfile argument\n  // being processed before any other argument in the command line. If\n  // FLAGS_flagfile contains more than one file name we create multiple new\n  // levels of arguments in a reverse order of file names. Thus we always\n  // process arguments from first file before arguments containing in a\n  // second file, etc. If flagfile contains another\n  // --flagfile inside of it, it will produce new level of arguments and\n  // processed before the rest of the flagfile. We are also collecting all\n  // flagfiles set on original command line. Unlike the rest of the flags,\n  // this flag can be set multiple times and is expected to be handled\n  // multiple times. We are collecting them all into a single list and set\n  // the value of FLAGS_flagfile to that value at the end of the parsing.\n  if (flags_internal::flagfile_needs_processing) {\n    auto flagfiles = absl::GetFlag(FLAGS_flagfile);\n\n    if (input_args.size() == 1) {\n      flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),\n                            flagfiles.end());\n    }\n\n    success &= ReadFlagfiles(flagfiles, input_args);\n\n    flags_internal::flagfile_needs_processing = false;\n  }\n\n  // Similar to flagfile fromenv/tryfromemv can be set both\n  // programmatically and at runtime on a command line. Unlike flagfile these\n  // can't be recursive.\n  if (flags_internal::fromenv_needs_processing) {\n    auto flags_list = absl::GetFlag(FLAGS_fromenv);\n\n    success &= ReadFlagsFromEnv(flags_list, input_args, true);\n\n    flags_internal::fromenv_needs_processing = false;\n  }\n\n  if (flags_internal::tryfromenv_needs_processing) {\n    auto flags_list = absl::GetFlag(FLAGS_tryfromenv);\n\n    success &= ReadFlagsFromEnv(flags_list, input_args, false);\n\n    flags_internal::tryfromenv_needs_processing = false;\n  }\n\n  return success;\n}\n\n// --------------------------------------------------------------------\n\nvoid ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {\n  // Setting flagfile to the value which collates all the values set on a\n  // command line and programmatically. So if command line looked like\n  // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is\n  // going to be {\"f1\", \"f2\"}\n  if (!flagfile_value.empty()) {\n    absl::SetFlag(&FLAGS_flagfile, flagfile_value);\n    absl::MutexLock l(flags_internal::ProcessingChecksMutex());\n    flags_internal::flagfile_needs_processing = false;\n  }\n\n  // fromenv/tryfromenv are set to <undefined> value.\n  if (!absl::GetFlag(FLAGS_fromenv).empty()) {\n    absl::SetFlag(&FLAGS_fromenv, {});\n  }\n  if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {\n    absl::SetFlag(&FLAGS_tryfromenv, {});\n  }\n\n  absl::MutexLock l(flags_internal::ProcessingChecksMutex());\n  flags_internal::fromenv_needs_processing = false;\n  flags_internal::tryfromenv_needs_processing = false;\n}\n\n// --------------------------------------------------------------------\n\n// Returns:\n//  success status\n//  deduced value\n// We are also mutating curr_list in case if we need to get a hold of next\n// argument in the input.\nstd::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,\n                                                    absl::string_view value,\n                                                    bool is_negative,\n                                                    bool is_empty_value,\n                                                    ArgsList* curr_list) {\n  // Value is either an argument suffix after `=` in \"--foo=<value>\"\n  // or separate argument in case of \"--foo\" \"<value>\".\n\n  // boolean flags have these forms:\n  //   --foo\n  //   --nofoo\n  //   --foo=true\n  //   --foo=false\n  //   --nofoo=<value> is not supported\n  //   --foo <value> is not supported\n\n  // non boolean flags have these forms:\n  // --foo=<value>\n  // --foo <value>\n  // --nofoo is not supported\n\n  if (flag.IsOfType<bool>()) {\n    if (value.empty()) {\n      if (is_empty_value) {\n        // \"--bool_flag=\" case\n        flags_internal::ReportUsageError(\n            absl::StrCat(\n                \"Missing the value after assignment for the boolean flag '\",\n                flag.Name(), \"'\"),\n            true);\n        return std::make_tuple(false, \"\");\n      }\n\n      // \"--bool_flag\" case\n      value = is_negative ? \"0\" : \"1\";\n    } else if (is_negative) {\n      // \"--nobool_flag=Y\" case\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Negative form with assignment is not valid for the \"\n                       \"boolean flag '\",\n                       flag.Name(), \"'\"),\n          true);\n      return std::make_tuple(false, \"\");\n    }\n  } else if (is_negative) {\n    // \"--noint_flag=1\" case\n    flags_internal::ReportUsageError(\n        absl::StrCat(\"Negative form is not valid for the flag '\", flag.Name(),\n                     \"'\"),\n        true);\n    return std::make_tuple(false, \"\");\n  } else if (value.empty() && (!is_empty_value)) {\n    if (curr_list->Size() == 1) {\n      // \"--int_flag\" case\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Missing the value for the flag '\", flag.Name(), \"'\"),\n          true);\n      return std::make_tuple(false, \"\");\n    }\n\n    // \"--int_flag\" \"10\" case\n    curr_list->PopFront();\n    value = curr_list->Front();\n\n    // Heuristic to detect the case where someone treats a string arg\n    // like a bool or just forgets to pass a value:\n    // --my_string_var --foo=bar\n    // We look for a flag of string type, whose value begins with a\n    // dash and corresponds to known flag or standalone --.\n    if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) {\n      auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));\n\n      if (maybe_flag_name.empty() ||\n          std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {\n        // \"--string_flag\" \"--known_flag\" case\n        ABSL_INTERNAL_LOG(\n            WARNING,\n            absl::StrCat(\"Did you really mean to set flag '\", flag.Name(),\n                         \"' to the value '\", value, \"'?\"));\n      }\n    }\n  }\n\n  return std::make_tuple(true, value);\n}\n\n// --------------------------------------------------------------------\n\nbool CanIgnoreUndefinedFlag(absl::string_view flag_name) {\n  auto undefok = absl::GetFlag(FLAGS_undefok);\n  if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {\n    return true;\n  }\n\n  if (absl::ConsumePrefix(&flag_name, \"no\") &&\n      std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {\n    return true;\n  }\n\n  return false;\n}\n\n// --------------------------------------------------------------------\n\nvoid ReportUnrecognizedFlags(\n    const std::vector<UnrecognizedFlag>& unrecognized_flags,\n    bool report_as_fatal_error) {\n  for (const auto& unrecognized : unrecognized_flags) {\n    // Verify if flag_name has the \"no\" already removed\n    std::vector<std::string> misspelling_hints;\n    if (unrecognized.source == UnrecognizedFlag::kFromArgv) {\n      misspelling_hints =\n          flags_internal::GetMisspellingHints(unrecognized.flag_name);\n    }\n\n    if (misspelling_hints.empty()) {\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Unknown command line flag '\", unrecognized.flag_name,\n                       \"'\"),\n          report_as_fatal_error);\n    } else {\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Unknown command line flag '\", unrecognized.flag_name,\n                       \"'. Did you mean: \",\n                       absl::StrJoin(misspelling_hints, \", \"), \" ?\"),\n          report_as_fatal_error);\n    }\n  }\n}\n\n}  // namespace\n\n// --------------------------------------------------------------------\n\nbool WasPresentOnCommandLine(absl::string_view flag_name) {\n  absl::ReaderMutexLock l(SpecifiedFlagsMutex());\n  ABSL_INTERNAL_CHECK(specified_flags != nullptr,\n                      \"ParseCommandLine is not invoked yet\");\n\n  return std::binary_search(specified_flags->begin(), specified_flags->end(),\n                            flag_name, SpecifiedFlagsCompare{});\n}\n\n// --------------------------------------------------------------------\n\nstruct BestHints {\n  explicit BestHints(uint8_t _max) : best_distance(_max + 1) {}\n  bool AddHint(absl::string_view hint, uint8_t distance) {\n    if (hints.size() >= kMaxHints) return false;\n    if (distance == best_distance) {\n      hints.emplace_back(hint);\n    }\n    if (distance < best_distance) {\n      best_distance = distance;\n      hints = std::vector<std::string>{std::string(hint)};\n    }\n    return true;\n  }\n\n  uint8_t best_distance;\n  std::vector<std::string> hints;\n};\n\n// Return the list of flags with the smallest Damerau-Levenshtein distance to\n// the given flag.\nstd::vector<std::string> GetMisspellingHints(const absl::string_view flag) {\n  const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);\n  auto undefok = absl::GetFlag(FLAGS_undefok);\n  BestHints best_hints(static_cast<uint8_t>(maxCutoff));\n  flags_internal::ForEachFlag([&](const CommandLineFlag& f) {\n    if (best_hints.hints.size() >= kMaxHints) return;\n    uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(\n        flag, f.Name(), best_hints.best_distance);\n    best_hints.AddHint(f.Name(), distance);\n    // For boolean flags, also calculate distance to the negated form.\n    if (f.IsOfType<bool>()) {\n      const std::string negated_flag = absl::StrCat(\"no\", f.Name());\n      distance = strings_internal::CappedDamerauLevenshteinDistance(\n          flag, negated_flag, best_hints.best_distance);\n      best_hints.AddHint(negated_flag, distance);\n    }\n  });\n  // Finally calculate distance to flags in \"undefok\".\n  absl::c_for_each(undefok, [&](const absl::string_view f) {\n    if (best_hints.hints.size() >= kMaxHints) return;\n    uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(\n        flag, f, best_hints.best_distance);\n    best_hints.AddHint(absl::StrCat(f, \" (undefok)\"), distance);\n  });\n  return best_hints.hints;\n}\n\n// --------------------------------------------------------------------\n\nstd::vector<char*> ParseCommandLineImpl(int argc, char* argv[],\n                                        UsageFlagsAction usage_flag_action,\n                                        OnUndefinedFlag undef_flag_action,\n                                        std::ostream& error_help_output) {\n  std::vector<char*> positional_args;\n  std::vector<UnrecognizedFlag> unrecognized_flags;\n\n  auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(\n      argc, argv, positional_args, unrecognized_flags, usage_flag_action);\n\n  if (undef_flag_action != OnUndefinedFlag::kIgnoreUndefined) {\n    flags_internal::ReportUnrecognizedFlags(\n        unrecognized_flags,\n        (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));\n\n    if (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {\n      if (!unrecognized_flags.empty()) {\n        flags_internal::HandleUsageFlags(error_help_output,\n        ProgramUsageMessage()); std::exit(1);\n      }\n    }\n  }\n\n  flags_internal::MaybeExit(help_mode);\n\n  return positional_args;\n}\n\n// --------------------------------------------------------------------\n\n// This function handles all Abseil Flags and built-in usage flags and, if any\n// help mode was handled, it returns that help mode. The caller of this function\n// can decide to exit based on the returned help mode.\n// The caller may decide to handle unrecognized positional arguments and\n// unrecognized flags first before exiting.\n//\n// Returns:\n// * HelpMode::kFull if parsing errors were detected in recognized arguments\n// * The HelpMode that was handled in case when `usage_flag_action` is\n//   UsageFlagsAction::kHandleUsage and a usage flag was specified on the\n//   commandline\n// * Otherwise it returns HelpMode::kNone\nHelpMode ParseAbseilFlagsOnlyImpl(\n    int argc, char* argv[], std::vector<char*>& positional_args,\n    std::vector<UnrecognizedFlag>& unrecognized_flags,\n    UsageFlagsAction usage_flag_action) {\n  ABSL_INTERNAL_CHECK(argc > 0, \"Missing argv[0]\");\n\n  using flags_internal::ArgsList;\n  using flags_internal::specified_flags;\n\n  std::vector<std::string> flagfile_value;\n  std::vector<ArgsList> input_args;\n\n  // Once parsing has started we will not allow more flag registrations.\n  flags_internal::FinalizeRegistry();\n\n  // This routine does not return anything since we abort on failure.\n  flags_internal::CheckDefaultValuesParsingRoundtrip();\n\n  input_args.push_back(ArgsList(argc, argv));\n\n  // Set program invocation name if it is not set before.\n  if (flags_internal::ProgramInvocationName() == \"UNKNOWN\") {\n    flags_internal::SetProgramInvocationName(argv[0]);\n  }\n  positional_args.push_back(argv[0]);\n\n  absl::MutexLock l(flags_internal::SpecifiedFlagsMutex());\n  if (specified_flags == nullptr) {\n    specified_flags = new std::vector<const CommandLineFlag*>;\n  } else {\n    specified_flags->clear();\n  }\n\n  // Iterate through the list of the input arguments. First level are\n  // arguments originated from argc/argv. Following levels are arguments\n  // originated from recursive parsing of flagfile(s).\n  bool success = true;\n  while (!input_args.empty()) {\n    // First we process the built-in generator flags.\n    success &= flags_internal::HandleGeneratorFlags(input_args, flagfile_value);\n\n    // Select top-most (most recent) arguments list. If it is empty drop it\n    // and re-try.\n    ArgsList& curr_list = input_args.back();\n\n    // Every ArgsList starts with real or fake program name, so we can always\n    // start by skipping it.\n    curr_list.PopFront();\n\n    if (curr_list.Size() == 0) {\n      input_args.pop_back();\n      continue;\n    }\n\n    // Handle the next argument in the current list. If the stack of argument\n    // lists contains only one element - we are processing an argument from\n    // the original argv.\n    absl::string_view arg(curr_list.Front());\n    bool arg_from_argv = input_args.size() == 1;\n\n    // If argument does not start with '-' or is just \"-\" - this is\n    // positional argument.\n    if (!absl::ConsumePrefix(&arg, \"-\") || arg.empty()) {\n      ABSL_INTERNAL_CHECK(arg_from_argv,\n                          \"Flagfile cannot contain positional argument\");\n\n      positional_args.push_back(argv[curr_list.FrontIndex()]);\n      continue;\n    }\n\n    // Split the current argument on '=' to deduce the argument flag name and\n    // value. If flag name is empty it means we've got an \"--\" argument. Value\n    // can be empty either if there were no '=' in argument string at all or\n    // an argument looked like \"--foo=\". In a latter case is_empty_value is\n    // true.\n    absl::string_view flag_name;\n    absl::string_view value;\n    bool is_empty_value = false;\n\n    std::tie(flag_name, value, is_empty_value) =\n        flags_internal::SplitNameAndValue(arg);\n\n    // Standalone \"--\" argument indicates that the rest of the arguments are\n    // positional. We do not support positional arguments in flagfiles.\n    if (flag_name.empty()) {\n      ABSL_INTERNAL_CHECK(arg_from_argv,\n                          \"Flagfile cannot contain positional argument\");\n\n      curr_list.PopFront();\n      break;\n    }\n\n    // Locate the flag based on flag name. Handle both --foo and --nofoo.\n    CommandLineFlag* flag = nullptr;\n    bool is_negative = false;\n    std::tie(flag, is_negative) = flags_internal::LocateFlag(flag_name);\n\n    if (flag == nullptr) {\n      // Usage flags are not modeled as Abseil flags. Locate them separately.\n      if (flags_internal::DeduceUsageFlags(flag_name, value)) {\n        continue;\n      }\n      unrecognized_flags.emplace_back(arg_from_argv\n                                          ? UnrecognizedFlag::kFromArgv\n                                          : UnrecognizedFlag::kFromFlagfile,\n                                      flag_name);\n      continue;\n    }\n\n    // Deduce flag's value (from this or next argument).\n    bool value_success = true;\n    std::tie(value_success, value) = flags_internal::DeduceFlagValue(\n        *flag, value, is_negative, is_empty_value, &curr_list);\n    success &= value_success;\n\n    // Set the located flag to a new value, unless it is retired. Setting\n    // retired flag fails, but we ignoring it here while also reporting access\n    // to retired flag.\n    std::string error;\n    if (!flags_internal::PrivateHandleAccessor::ParseFrom(\n            *flag, value, flags_internal::SET_FLAGS_VALUE,\n            flags_internal::kCommandLine, error)) {\n      if (flag->IsRetired()) continue;\n\n      flags_internal::ReportUsageError(error, true);\n      success = false;\n    } else {\n      specified_flags->push_back(flag);\n    }\n  }\n\n  flags_internal::ResetGeneratorFlags(flagfile_value);\n\n  // All the remaining arguments are positional.\n  if (!input_args.empty()) {\n    for (size_t arg_index = input_args.back().FrontIndex();\n         arg_index < static_cast<size_t>(argc); ++arg_index) {\n      positional_args.push_back(argv[arg_index]);\n    }\n  }\n\n  // Trim and sort the vector.\n  specified_flags->shrink_to_fit();\n  std::sort(specified_flags->begin(), specified_flags->end(),\n            flags_internal::SpecifiedFlagsCompare{});\n\n  // Filter out unrecognized flags, which are ok to ignore.\n  std::vector<UnrecognizedFlag> filtered;\n  filtered.reserve(unrecognized_flags.size());\n  for (const auto& unrecognized : unrecognized_flags) {\n    if (flags_internal::CanIgnoreUndefinedFlag(unrecognized.flag_name))\n      continue;\n    filtered.push_back(unrecognized);\n  }\n\n  std::swap(unrecognized_flags, filtered);\n\n  if (!success) {\n#if ABSL_FLAGS_STRIP_NAMES\n    flags_internal::ReportUsageError(\n        \"NOTE: command line flags are disabled in this build\", true);\n#else\n    flags_internal::HandleUsageFlags(std::cerr, ProgramUsageMessage());\n#endif\n    return HelpMode::kFull;  // We just need to make sure the exit with\n                             // code 1.\n  }\n\n  return usage_flag_action == UsageFlagsAction::kHandleUsage\n             ? flags_internal::HandleUsageFlags(std::cout,\n                                                ProgramUsageMessage())\n             : HelpMode::kNone;\n}\n\n}  // namespace flags_internal\n\nvoid ParseAbseilFlagsOnly(int argc, char* argv[],\n                          std::vector<char*>& positional_args,\n                          std::vector<UnrecognizedFlag>& unrecognized_flags) {\n  auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(\n      argc, argv, positional_args, unrecognized_flags,\n      flags_internal::UsageFlagsAction::kHandleUsage);\n\n  flags_internal::MaybeExit(help_mode);\n}\n\n// --------------------------------------------------------------------\n\nvoid ReportUnrecognizedFlags(\n    const std::vector<UnrecognizedFlag>& unrecognized_flags) {\n  flags_internal::ReportUnrecognizedFlags(unrecognized_flags, true);\n}\n\n// --------------------------------------------------------------------\n\nstd::vector<char*> ParseCommandLine(int argc, char* argv[]) {\n  return flags_internal::ParseCommandLineImpl(\n      argc, argv, flags_internal::UsageFlagsAction::kHandleUsage,\n      flags_internal::OnUndefinedFlag::kAbortIfUndefined);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/parse.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: parse.h\n// -----------------------------------------------------------------------------\n//\n// This file defines the main parsing function for Abseil flags:\n// `absl::ParseCommandLine()`.\n\n#ifndef ABSL_FLAGS_PARSE_H_\n#define ABSL_FLAGS_PARSE_H_\n\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/flags/internal/parse.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// This type represent information about an unrecognized flag in the command\n// line.\nstruct UnrecognizedFlag {\n  enum Source { kFromArgv, kFromFlagfile };\n\n  explicit UnrecognizedFlag(Source s, absl::string_view f)\n      : source(s), flag_name(f) {}\n  // This field indicates where we found this flag: on the original command line\n  // or read in some flag file.\n  Source source;\n  // Name of the flag we did not recognize in --flag_name=value or --flag_name.\n  std::string flag_name;\n};\n\ninline bool operator==(const UnrecognizedFlag& lhs,\n                       const UnrecognizedFlag& rhs) {\n  return lhs.source == rhs.source && lhs.flag_name == rhs.flag_name;\n}\n\nnamespace flags_internal {\n\nHelpMode ParseAbseilFlagsOnlyImpl(\n    int argc, char* argv[], std::vector<char*>& positional_args,\n    std::vector<UnrecognizedFlag>& unrecognized_flags,\n    UsageFlagsAction usage_flag_action);\n\n}  // namespace flags_internal\n\n// ParseAbseilFlagsOnly()\n//\n// Parses a list of command-line arguments, passed in the `argc` and `argv[]`\n// parameters, into a set of Abseil Flag values, returning any unparsed\n// arguments in `positional_args` and `unrecognized_flags` output parameters.\n//\n// This function classifies all the arguments (including content of the\n// flagfiles, if any) into one of the following groups:\n//\n//   * arguments specified as \"--flag=value\" or \"--flag value\" that match\n//     registered or built-in Abseil Flags. These are \"Abseil Flag arguments.\"\n//   * arguments specified as \"--flag\" that are unrecognized as Abseil Flags\n//   * arguments that are not specified as \"--flag\" are positional arguments\n//   * arguments that follow the flag-terminating delimiter (`--`) are also\n//     treated as positional arguments regardless of their syntax.\n//\n// All of the deduced Abseil Flag arguments are then parsed into their\n// corresponding flag values. If any syntax errors are found in these arguments,\n// the binary exits with code 1.\n//\n// This function also handles Abseil Flags built-in usage flags (e.g. --help)\n// if any were present on the command line.\n//\n// All the remaining positional arguments including original program name\n// (argv[0]) are are returned in the `positional_args` output parameter.\n//\n// All unrecognized flags that are not otherwise ignored are returned in the\n// `unrecognized_flags` output parameter. Note that the special `undefok`\n// flag allows you to specify flags which can be safely ignored; `undefok`\n// specifies these flags as a comma-separated list. Any unrecognized flags\n// that appear within `undefok` will therefore be ignored and not included in\n// the `unrecognized_flag` output parameter.\n//\nvoid ParseAbseilFlagsOnly(int argc, char* argv[],\n                          std::vector<char*>& positional_args,\n                          std::vector<UnrecognizedFlag>& unrecognized_flags);\n\n// ReportUnrecognizedFlags()\n//\n// Reports an error to `stderr` for all non-ignored unrecognized flags in\n// the provided `unrecognized_flags` list.\nvoid ReportUnrecognizedFlags(\n    const std::vector<UnrecognizedFlag>& unrecognized_flags);\n\n// ParseCommandLine()\n//\n// First parses Abseil Flags only from the command line according to the\n// description in `ParseAbseilFlagsOnly`. In addition this function handles\n// unrecognized and usage flags.\n//\n// If any unrecognized flags are located they are reported using\n// `ReportUnrecognizedFlags`.\n//\n// If any errors detected during command line parsing, this routine reports a\n// usage message and aborts the program.\n//\n// If any built-in usage flags were specified on the command line (e.g.\n// `--help`), this function reports help messages and then gracefully exits the\n// program.\n//\n// This function returns all the remaining positional arguments collected by\n// `ParseAbseilFlagsOnly`.\nstd::vector<char*> ParseCommandLine(int argc, char* argv[]);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_PARSE_H_\n"
  },
  {
    "path": "absl/flags/parse_test.cc",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/parse.h\"\n\n#include <stdlib.h>\n\n#include <fstream>\n#include <iostream>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/scoped_set_env.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/internal/parse.h\"\n#include \"absl/flags/internal/usage.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/log/log.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/substitute.h\"\n#include \"absl/types/span.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n// Define 125 similar flags to test kMaxHints for flag suggestions.\n#define FLAG_MULT(x) F3(x)\n#define TEST_FLAG_HEADER FLAG_HEADER_\n\n#define F(name) ABSL_FLAG(int, name, 0, \"\")\n\n#define F1(name) \\\n  F(name##1);    \\\n  F(name##2);    \\\n  F(name##3);    \\\n  F(name##4);    \\\n  F(name##5)\n/**/\n#define F2(name) \\\n  F1(name##1);   \\\n  F1(name##2);   \\\n  F1(name##3);   \\\n  F1(name##4);   \\\n  F1(name##5)\n/**/\n#define F3(name) \\\n  F2(name##1);   \\\n  F2(name##2);   \\\n  F2(name##3);   \\\n  F2(name##4);   \\\n  F2(name##5)\n/**/\n\nFLAG_MULT(TEST_FLAG_HEADER);\n\nnamespace {\n\nusing absl::base_internal::ScopedSetEnv;\n\nstruct UDT {\n  UDT() = default;\n  UDT(const UDT&) = default;\n  UDT& operator=(const UDT&) = default;\n  UDT(int v) : value(v) {}  // NOLINT\n\n  int value;\n};\n\nbool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) {\n  if (in == \"A\") {\n    udt->value = 1;\n    return true;\n  }\n  if (in == \"AAA\") {\n    udt->value = 10;\n    return true;\n  }\n\n  *err = \"Use values A, AAA instead\";\n  return false;\n}\nstd::string AbslUnparseFlag(const UDT& udt) {\n  return udt.value == 1 ? \"A\" : \"AAA\";\n}\n\nstd::string GetTestTmpDirEnvVar(const char* const env_var_name) {\n#ifdef _WIN32\n  char buf[MAX_PATH];\n  auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));\n  if (get_res >= sizeof(buf) || get_res == 0) {\n    return \"\";\n  }\n\n  return std::string(buf, get_res);\n#else\n  const char* val = ::getenv(env_var_name);\n  if (val == nullptr) {\n    return \"\";\n  }\n\n  return val;\n#endif\n}\n\nconst std::string& GetTestTempDir() {\n  static std::string* temp_dir_name = []() -> std::string* {\n    std::string* res = new std::string(GetTestTmpDirEnvVar(\"TEST_TMPDIR\"));\n\n    if (res->empty()) {\n      *res = GetTestTmpDirEnvVar(\"TMPDIR\");\n    }\n\n    if (res->empty()) {\n#ifdef _WIN32\n      char temp_path_buffer[MAX_PATH];\n\n      auto len = GetTempPathA(MAX_PATH, temp_path_buffer);\n      if (len < MAX_PATH && len != 0) {\n        std::string temp_dir_name = temp_path_buffer;\n        if (!absl::EndsWith(temp_dir_name, \"\\\\\")) {\n          temp_dir_name.push_back('\\\\');\n        }\n        absl::StrAppend(&temp_dir_name, \"parse_test.\", GetCurrentProcessId());\n        if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {\n          *res = temp_dir_name;\n        }\n      }\n#else\n      char temp_dir_template[] = \"/tmp/parse_test.XXXXXX\";\n      if (auto* unique_name = ::mkdtemp(temp_dir_template)) {\n        *res = unique_name;\n      }\n#endif\n    }\n\n    if (res->empty()) {\n      LOG(FATAL) << \"Failed to make temporary directory for data files\";\n    }\n\n#ifdef _WIN32\n    *res += \"\\\\\";\n#else\n    *res += \"/\";\n#endif\n\n    return res;\n  }();\n\n  return *temp_dir_name;\n}\n\nstruct FlagfileData {\n  const absl::string_view file_name;\n  const absl::Span<const char* const> file_lines;\n};\n\n// clang-format off\nconstexpr const char* const ff1_data[] = {\n    \"# comment    \",\n    \"  # comment  \",\n    \"\",\n    \"     \",\n    \"--int_flag=-1\",\n    \"  --string_flag=q2w2  \",\n    \"  ##   \",\n    \"  --double_flag=0.1\",\n    \"--bool_flag=Y  \"\n};\n\nconstexpr const char* const ff2_data[] = {\n    \"# Setting legacy flag\",\n    \"--legacy_int=1111\",\n    \"--legacy_bool\",\n    \"--nobool_flag\",\n    \"--legacy_str=aqsw\",\n    \"--int_flag=100\",\n    \"   ## =============\"\n};\n// clang-format on\n\n// Builds flagfile flag in the flagfile_flag buffer and returns it. This\n// function also creates a temporary flagfile based on FlagfileData input.\n// We create a flagfile in a temporary directory with the name specified in\n// FlagfileData and populate it with lines specified in FlagfileData. If $0 is\n// referenced in any of the lines in FlagfileData they are replaced with\n// temporary directory location. This way we can test inclusion of one flagfile\n// from another flagfile.\nconst char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,\n                            std::string& flagfile_flag) {\n  flagfile_flag = \"--flagfile=\";\n  absl::string_view separator;\n  for (const auto& flagfile_data : ffd) {\n    std::string flagfile_name =\n        absl::StrCat(GetTestTempDir(), flagfile_data.file_name);\n\n    std::ofstream flagfile_out(flagfile_name);\n    for (auto line : flagfile_data.file_lines) {\n      flagfile_out << absl::Substitute(line, GetTestTempDir()) << \"\\n\";\n    }\n\n    absl::StrAppend(&flagfile_flag, separator, flagfile_name);\n    separator = \",\";\n  }\n\n  return flagfile_flag.c_str();\n}\n\n}  // namespace\n\nABSL_FLAG(int, int_flag, 1, \"\");\nABSL_FLAG(double, double_flag, 1.1, \"\");\nABSL_FLAG(std::string, string_flag, \"a\", \"\");\nABSL_FLAG(bool, bool_flag, false, \"\");\nABSL_FLAG(UDT, udt_flag, -1, \"\");\nABSL_RETIRED_FLAG(int, legacy_int, 1, \"\");\nABSL_RETIRED_FLAG(bool, legacy_bool, false, \"\");\nABSL_RETIRED_FLAG(std::string, legacy_str, \"l\", \"\");\n\nnamespace {\n\nnamespace flags = absl::flags_internal;\nusing testing::AllOf;\nusing testing::ElementsAreArray;\nusing testing::HasSubstr;\n\nclass ParseTest : public testing::Test {\n public:\n  ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }\n\n  void SetUp() override {\n#if ABSL_FLAGS_STRIP_NAMES\n    GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n  }\n\n private:\n  absl::FlagSaver flag_saver_;\n};\n\n// --------------------------------------------------------------------\n\ntemplate <int N>\nflags::HelpMode InvokeParseAbslOnlyImpl(const char* (&in_argv)[N]) {\n  std::vector<char*> positional_args;\n  std::vector<absl::UnrecognizedFlag> unrecognized_flags;\n\n  return flags::ParseAbseilFlagsOnlyImpl(N, const_cast<char**>(in_argv),\n                                         positional_args, unrecognized_flags,\n                                         flags::UsageFlagsAction::kHandleUsage);\n}\n\n// --------------------------------------------------------------------\n\ntemplate <int N>\nvoid InvokeParseAbslOnly(const char* (&in_argv)[N]) {\n  std::vector<char*> positional_args;\n  std::vector<absl::UnrecognizedFlag> unrecognized_flags;\n\n  absl::ParseAbseilFlagsOnly(2, const_cast<char**>(in_argv), positional_args,\n                             unrecognized_flags);\n}\n\n// --------------------------------------------------------------------\n\ntemplate <int N>\nstd::vector<char*> InvokeParseCommandLineImpl(const char* (&in_argv)[N]) {\n  return flags::ParseCommandLineImpl(\n      N, const_cast<char**>(in_argv), flags::UsageFlagsAction::kHandleUsage,\n      flags::OnUndefinedFlag::kAbortIfUndefined, std::cerr);\n}\n\n// --------------------------------------------------------------------\n\ntemplate <int N>\nstd::vector<char*> InvokeParse(const char* (&in_argv)[N]) {\n  return absl::ParseCommandLine(N, const_cast<char**>(in_argv));\n}\n\n// --------------------------------------------------------------------\n\ntemplate <int N>\nvoid TestParse(const char* (&in_argv)[N], int int_flag_value,\n               double double_flag_val, absl::string_view string_flag_val,\n               bool bool_flag_val, int exp_position_args = 0) {\n  auto out_args = InvokeParse(in_argv);\n\n  EXPECT_EQ(out_args.size(), 1 + exp_position_args);\n  EXPECT_STREQ(out_args[0], \"testbin\");\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);\n  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);\n  EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestEmptyArgv) {\n  const char* in_argv[] = {\"testbin\"};\n\n  auto out_args = InvokeParse(in_argv);\n\n  EXPECT_EQ(out_args.size(), 1);\n  EXPECT_STREQ(out_args[0], \"testbin\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidIntArg) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--int_flag=10\",\n  };\n  TestParse(in_args1, 10, 1.1, \"a\", false);\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"-int_flag=020\",\n  };\n  TestParse(in_args2, 20, 1.1, \"a\", false);\n\n  const char* in_args3[] = {\n      \"testbin\",\n      \"--int_flag\",\n      \"-30\",\n  };\n  TestParse(in_args3, -30, 1.1, \"a\", false);\n\n  const char* in_args4[] = {\n      \"testbin\",\n      \"-int_flag\",\n      \"0x21\",\n  };\n  TestParse(in_args4, 33, 1.1, \"a\", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidDoubleArg) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--double_flag=2.3\",\n  };\n  TestParse(in_args1, 1, 2.3, \"a\", false);\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--double_flag=0x1.2\",\n  };\n  TestParse(in_args2, 1, 1.125, \"a\", false);\n\n  const char* in_args3[] = {\n      \"testbin\",\n      \"--double_flag\",\n      \"99.7\",\n  };\n  TestParse(in_args3, 1, 99.7, \"a\", false);\n\n  const char* in_args4[] = {\n      \"testbin\",\n      \"--double_flag\",\n      \"0x20.1\",\n  };\n  TestParse(in_args4, 1, 32.0625, \"a\", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidStringArg) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--string_flag=aqswde\",\n  };\n  TestParse(in_args1, 1, 1.1, \"aqswde\", false);\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"-string_flag=a=b=c\",\n  };\n  TestParse(in_args2, 1, 1.1, \"a=b=c\", false);\n\n  const char* in_args3[] = {\n      \"testbin\",\n      \"--string_flag\",\n      \"zaxscd\",\n  };\n  TestParse(in_args3, 1, 1.1, \"zaxscd\", false);\n\n  const char* in_args4[] = {\n      \"testbin\",\n      \"-string_flag\",\n      \"--int_flag\",\n  };\n  TestParse(in_args4, 1, 1.1, \"--int_flag\", false);\n\n  const char* in_args5[] = {\n      \"testbin\",\n      \"--string_flag\",\n      \"--no_a_flag=11\",\n  };\n  TestParse(in_args5, 1, 1.1, \"--no_a_flag=11\", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidBoolArg) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--bool_flag\",\n  };\n  TestParse(in_args1, 1, 1.1, \"a\", true);\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--nobool_flag\",\n  };\n  TestParse(in_args2, 1, 1.1, \"a\", false);\n\n  const char* in_args3[] = {\n      \"testbin\",\n      \"--bool_flag=true\",\n  };\n  TestParse(in_args3, 1, 1.1, \"a\", true);\n\n  const char* in_args4[] = {\n      \"testbin\",\n      \"-bool_flag=false\",\n  };\n  TestParse(in_args4, 1, 1.1, \"a\", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidUDTArg) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--udt_flag=A\",\n  };\n  InvokeParse(in_args1);\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);\n\n  const char* in_args2[] = {\"testbin\", \"--udt_flag\", \"AAA\"};\n  InvokeParse(in_args2);\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidMultipleArg) {\n  const char* in_args1[] = {\n      \"testbin\",           \"--bool_flag\",       \"--int_flag=2\",\n      \"--double_flag=0.1\", \"--string_flag=asd\",\n  };\n  TestParse(in_args1, 2, 0.1, \"asd\", true);\n\n  const char* in_args2[] = {\n      \"testbin\", \"--string_flag=\", \"--nobool_flag\", \"--int_flag\",\n      \"-011\",    \"--double_flag\",  \"-1e-2\",\n  };\n  TestParse(in_args2, -11, -0.01, \"\", false);\n\n  const char* in_args3[] = {\n      \"testbin\",          \"--int_flag\",         \"-0\", \"--string_flag\", \"\\\"\\\"\",\n      \"--bool_flag=true\", \"--double_flag=1e18\",\n  };\n  TestParse(in_args3, 0, 1e18, \"\\\"\\\"\", true);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestPositionalArgs) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"p1\",\n      \"p2\",\n  };\n  TestParse(in_args1, 1, 1.1, \"a\", false, 2);\n\n  auto out_args1 = InvokeParse(in_args1);\n\n  EXPECT_STREQ(out_args1[1], \"p1\");\n  EXPECT_STREQ(out_args1[2], \"p2\");\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--int_flag=2\",\n      \"p1\",\n  };\n  TestParse(in_args2, 2, 1.1, \"a\", false, 1);\n\n  auto out_args2 = InvokeParse(in_args2);\n\n  EXPECT_STREQ(out_args2[1], \"p1\");\n\n  const char* in_args3[] = {\"testbin\", \"p1\",          \"--int_flag=3\",\n                            \"p2\",      \"--bool_flag\", \"true\"};\n  TestParse(in_args3, 3, 1.1, \"a\", true, 3);\n\n  auto out_args3 = InvokeParse(in_args3);\n\n  EXPECT_STREQ(out_args3[1], \"p1\");\n  EXPECT_STREQ(out_args3[2], \"p2\");\n  EXPECT_STREQ(out_args3[3], \"true\");\n\n  const char* in_args4[] = {\n      \"testbin\",\n      \"--\",\n      \"p1\",\n      \"p2\",\n  };\n  TestParse(in_args4, 3, 1.1, \"a\", true, 2);\n\n  auto out_args4 = InvokeParse(in_args4);\n\n  EXPECT_STREQ(out_args4[1], \"p1\");\n  EXPECT_STREQ(out_args4[2], \"p2\");\n\n  const char* in_args5[] = {\n      \"testbin\", \"p1\", \"--int_flag=4\", \"--\", \"--bool_flag\", \"false\", \"p2\",\n  };\n  TestParse(in_args5, 4, 1.1, \"a\", true, 4);\n\n  auto out_args5 = InvokeParse(in_args5);\n\n  EXPECT_STREQ(out_args5[1], \"p1\");\n  EXPECT_STREQ(out_args5[2], \"--bool_flag\");\n  EXPECT_STREQ(out_args5[3], \"false\");\n  EXPECT_STREQ(out_args5[4], \"p2\");\n}\n\n// --------------------------------------------------------------------\n\nusing ParseDeathTest = ParseTest;\n\nTEST_F(ParseDeathTest, TestUndefinedArg) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--undefined_flag\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),\n                            \"Unknown command line flag 'undefined_flag'\");\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--noprefixed_flag\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),\n                            \"Unknown command line flag 'noprefixed_flag'\");\n\n  const char* in_args3[] = {\n      \"testbin\",\n      \"--Int_flag=1\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),\n                            \"Unknown command line flag 'Int_flag'\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--bool_flag=\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(\n      InvokeParse(in_args1),\n      \"Missing the value after assignment for the boolean flag 'bool_flag'\");\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--nobool_flag=true\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),\n               \"Negative form with assignment is not valid for the boolean \"\n               \"flag 'bool_flag'\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--nostring_flag\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),\n               \"Negative form is not valid for the flag 'string_flag'\");\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--int_flag\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),\n               \"Missing the value for the flag 'int_flag'\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--udt_flag=1\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),\n               \"Illegal value '1' specified for flag 'udt_flag'; Use values A, \"\n               \"AAA instead\");\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--udt_flag\",\n      \"AA\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),\n               \"Illegal value 'AA' specified for flag 'udt_flag'; Use values \"\n               \"A, AAA instead\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestFlagSuggestions) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--legacy_boo\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(\n      InvokeParse(in_args1),\n      \"Unknown command line flag 'legacy_boo'. Did you mean: legacy_bool ?\");\n\n  const char* in_args2[] = {\"testbin\", \"--foo\", \"--undefok=foo1\"};\n  EXPECT_DEATH_IF_SUPPORTED(\n      InvokeParse(in_args2),\n      \"Unknown command line flag 'foo'. Did you mean: foo1 \\\\(undefok\\\\)?\");\n\n  const char* in_args3[] = {\n      \"testbin\",\n      \"--nolegacy_ino\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),\n                            \"Unknown command line flag 'nolegacy_ino'. Did \"\n                            \"you mean: nolegacy_bool, legacy_int ?\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, GetHints) {\n  EXPECT_THAT(absl::flags_internal::GetMisspellingHints(\"legacy_boo\"),\n              testing::ContainerEq(std::vector<std::string>{\"legacy_bool\"}));\n  EXPECT_THAT(absl::flags_internal::GetMisspellingHints(\"nolegacy_itn\"),\n              testing::ContainerEq(std::vector<std::string>{\"legacy_int\"}));\n  EXPECT_THAT(absl::flags_internal::GetMisspellingHints(\"nolegacy_int1\"),\n              testing::ContainerEq(std::vector<std::string>{\"legacy_int\"}));\n  EXPECT_THAT(absl::flags_internal::GetMisspellingHints(\"nolegacy_int\"),\n              testing::ContainerEq(std::vector<std::string>{\"legacy_int\"}));\n  EXPECT_THAT(absl::flags_internal::GetMisspellingHints(\"nolegacy_ino\"),\n              testing::ContainerEq(\n                  std::vector<std::string>{\"nolegacy_bool\", \"legacy_int\"}));\n  EXPECT_THAT(\n      absl::flags_internal::GetMisspellingHints(\"FLAG_HEADER_000\").size(), 100);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestLegacyFlags) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--legacy_int=11\",\n  };\n  TestParse(in_args1, 1, 1.1, \"a\", false);\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--legacy_bool\",\n  };\n  TestParse(in_args2, 1, 1.1, \"a\", false);\n\n  const char* in_args3[] = {\n      \"testbin\",       \"--legacy_int\", \"22\",           \"--int_flag=2\",\n      \"--legacy_bool\", \"true\",         \"--legacy_str\", \"--string_flag=qwe\",\n  };\n  TestParse(in_args3, 2, 1.1, \"a\", false, 1);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestSimpleValidFlagfile) {\n  std::string flagfile_flag;\n\n  const char* in_args1[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff1\", absl::MakeConstSpan(ff1_data)}},\n                      flagfile_flag),\n  };\n  TestParse(in_args1, -1, 0.1, \"q2w2  \", true);\n\n  const char* in_args2[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff2\", absl::MakeConstSpan(ff2_data)}},\n                      flagfile_flag),\n  };\n  TestParse(in_args2, 100, 0.1, \"q2w2  \", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestValidMultiFlagfile) {\n  std::string flagfile_flag;\n\n  const char* in_args1[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff2\", absl::MakeConstSpan(ff2_data)},\n                       {\"parse_test.ff1\", absl::MakeConstSpan(ff1_data)}},\n                      flagfile_flag),\n  };\n  TestParse(in_args1, -1, 0.1, \"q2w2  \", true);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {\n  std::string flagfile_flag;\n\n  const char* in_args1[] = {\n      \"testbin\", \"--int_flag=3\",\n      GetFlagfileFlag({{\"parse_test.ff1\", absl::MakeConstSpan(ff1_data)}},\n                      flagfile_flag),\n      \"-double_flag=0.2\"};\n  TestParse(in_args1, -1, 0.2, \"q2w2  \", true);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestFlagfileInFlagfile) {\n  std::string flagfile_flag;\n\n  constexpr const char* const ff3_data[] = {\n      \"--flagfile=$0/parse_test.ff1\",\n      \"--flagfile=$0/parse_test.ff2\",\n  };\n\n  GetFlagfileFlag({{\"parse_test.ff2\", absl::MakeConstSpan(ff2_data)},\n                   {\"parse_test.ff1\", absl::MakeConstSpan(ff1_data)}},\n                      flagfile_flag);\n\n  const char* in_args1[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff3\", absl::MakeConstSpan(ff3_data)}},\n                      flagfile_flag),\n  };\n  TestParse(in_args1, 100, 0.1, \"q2w2  \", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestInvalidFlagfiles) {\n  std::string flagfile_flag;\n\n  constexpr const char* const ff4_data[] = {\n    \"--unknown_flag=10\"\n  };\n\n  const char* in_args1[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff4\",\n                        absl::MakeConstSpan(ff4_data)}}, flagfile_flag),\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),\n               \"Unknown command line flag 'unknown_flag'\");\n\n  constexpr const char* const ff5_data[] = {\n    \"--int_flag 10\",\n  };\n\n  const char* in_args2[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff5\",\n                        absl::MakeConstSpan(ff5_data)}}, flagfile_flag),\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),\n               \"Unknown command line flag 'int_flag 10'\");\n\n  constexpr const char* const ff6_data[] = {\n      \"--int_flag=10\", \"--\", \"arg1\", \"arg2\", \"arg3\",\n  };\n\n  const char* in_args3[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff6\", absl::MakeConstSpan(ff6_data)}},\n                      flagfile_flag),\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),\n               \"Flagfile can't contain position arguments or --\");\n\n  const char* in_args4[] = {\n      \"testbin\",\n      \"--flagfile=invalid_flag_file\",\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4),\n                            \"Can't open flagfile invalid_flag_file\");\n\n  constexpr const char* const ff7_data[] = {\n      \"--int_flag=10\",\n      \"*bin*\",\n      \"--str_flag=aqsw\",\n  };\n\n  const char* in_args5[] = {\n      \"testbin\",\n      GetFlagfileFlag({{\"parse_test.ff7\", absl::MakeConstSpan(ff7_data)}},\n                      flagfile_flag),\n  };\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),\n               \"Unexpected line 2 in the flagfile .*\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {\n  const char* in_args1[] = {\"testbin\",\n                            \"--fromenv=int_flag,bool_flag,string_flag\"};\n\n  ScopedSetEnv set_int_flag(\"FLAGS_int_flag\", \"33\");\n  ScopedSetEnv set_bool_flag(\"FLAGS_bool_flag\", \"True\");\n  ScopedSetEnv set_string_flag(\"FLAGS_string_flag\", \"AQ12\");\n\n  TestParse(in_args1, 33, 1.1, \"AQ12\", true);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {\n  const char* in_args1[] = {\"testbin\", \"--fromenv=int_flag\"};\n\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),\n               \"FLAGS_int_flag not found in environment\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {\n  const char* in_args1[] = {\"testbin\", \"--fromenv=tryfromenv\"};\n\n  ScopedSetEnv set_tryfromenv(\"FLAGS_tryfromenv\", \"int_flag\");\n\n  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),\n                            \"Infinite recursion on flag tryfromenv\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {\n  const char* in_args1[] = {\n      \"testbin\", \"--tryfromenv=int_flag,bool_flag,string_flag,other_flag\"};\n\n  ScopedSetEnv set_int_flag(\"FLAGS_int_flag\", \"17\");\n  ScopedSetEnv set_bool_flag(\"FLAGS_bool_flag\", \"Y\");\n\n  TestParse(in_args1, 17, 1.1, \"a\", true);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--bool_flag=T\",\n      \"--tryfromenv=int_flag,bool_flag\",\n      \"--int_flag=-21\",\n  };\n\n  ScopedSetEnv set_int_flag(\"FLAGS_int_flag\", \"-15\");\n  ScopedSetEnv set_bool_flag(\"FLAGS_bool_flag\", \"F\");\n\n  TestParse(in_args1, -21, 1.1, \"a\", false);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--help\",\n  };\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kImportant);\n  EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), \"\");\n\n  const char* in_args2[] = {\n      \"testbin\",\n      \"--help\",\n      \"--int_flag=3\",\n  };\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kImportant);\n  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);\n\n  const char* in_args3[] = {\"testbin\", \"--help\", \"some_positional_arg\"};\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args3), flags::HelpMode::kImportant);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestSubstringHelpFlagHandling) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--help=abcd\",\n  };\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kMatch);\n  EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), \"abcd\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, TestVersionHandling) {\n  const char* in_args1[] = {\n      \"testbin\",\n      \"--version\",\n  };\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kVersion);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, TestCheckArgsHandling) {\n  const char* in_args1[] = {\"testbin\", \"--only_check_args\", \"--int_flag=211\"};\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kOnlyCheckArgs);\n  EXPECT_EXIT(InvokeParseAbslOnly(in_args1), testing::ExitedWithCode(0), \"\");\n  EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(0), \"\");\n\n  const char* in_args2[] = {\"testbin\", \"--only_check_args\", \"--unknown_flag=a\"};\n\n  EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kOnlyCheckArgs);\n  EXPECT_EXIT(InvokeParseAbslOnly(in_args2), testing::ExitedWithCode(0), \"\");\n  EXPECT_EXIT(InvokeParse(in_args2), testing::ExitedWithCode(1), \"\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, WasPresentOnCommandLine) {\n  const char* in_args1[] = {\n      \"testbin\",        \"arg1\", \"--bool_flag\",\n      \"--int_flag=211\", \"arg2\", \"--double_flag=1.1\",\n      \"--string_flag\",  \"asd\",  \"--\",\n      \"--some_flag\",    \"arg4\",\n  };\n\n  InvokeParse(in_args1);\n\n  EXPECT_TRUE(flags::WasPresentOnCommandLine(\"bool_flag\"));\n  EXPECT_TRUE(flags::WasPresentOnCommandLine(\"int_flag\"));\n  EXPECT_TRUE(flags::WasPresentOnCommandLine(\"double_flag\"));\n  EXPECT_TRUE(flags::WasPresentOnCommandLine(\"string_flag\"));\n  EXPECT_FALSE(flags::WasPresentOnCommandLine(\"some_flag\"));\n  EXPECT_FALSE(flags::WasPresentOnCommandLine(\"another_flag\"));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, ParseAbseilFlagsOnlySuccess) {\n  const char* in_args[] = {\n      \"testbin\",\n      \"arg1\",\n      \"--bool_flag\",\n      \"--int_flag=211\",\n      \"arg2\",\n      \"--double_flag=1.1\",\n      \"--undef_flag1\",\n      \"--undef_flag2=123\",\n      \"--string_flag\",\n      \"asd\",\n      \"--\",\n      \"--some_flag\",\n      \"arg4\",\n  };\n\n  std::vector<char*> positional_args;\n  std::vector<absl::UnrecognizedFlag> unrecognized_flags;\n\n  absl::ParseAbseilFlagsOnly(13, const_cast<char**>(in_args), positional_args,\n                             unrecognized_flags);\n  EXPECT_THAT(positional_args,\n              ElementsAreArray(\n                  {absl::string_view(\"testbin\"), absl::string_view(\"arg1\"),\n                   absl::string_view(\"arg2\"), absl::string_view(\"--some_flag\"),\n                   absl::string_view(\"arg4\")}));\n  EXPECT_THAT(unrecognized_flags,\n              ElementsAreArray(\n                  {absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,\n                                          \"undef_flag1\"),\n                   absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,\n                                          \"undef_flag2\")}));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, ParseAbseilFlagsOnlyFailure) {\n  const char* in_args[] = {\n      \"testbin\",\n      \"--int_flag=21.1\",\n  };\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      InvokeParseAbslOnly(in_args),\n      \"Illegal value '21.1' specified for flag 'int_flag'\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, UndefOkFlagsAreIgnored) {\n  const char* in_args[] = {\n      \"testbin\",           \"--undef_flag1\",\n      \"--undef_flag2=123\", \"--undefok=undef_flag2\",\n      \"--undef_flag3\",     \"value\",\n  };\n\n  std::vector<char*> positional_args;\n  std::vector<absl::UnrecognizedFlag> unrecognized_flags;\n\n  absl::ParseAbseilFlagsOnly(6, const_cast<char**>(in_args), positional_args,\n                             unrecognized_flags);\n  EXPECT_THAT(positional_args, ElementsAreArray({absl::string_view(\"testbin\"),\n                                                 absl::string_view(\"value\")}));\n  EXPECT_THAT(unrecognized_flags,\n              ElementsAreArray(\n                  {absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,\n                                          \"undef_flag1\"),\n                   absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,\n                                          \"undef_flag3\")}));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseTest, AllUndefOkFlagsAreIgnored) {\n  const char* in_args[] = {\n      \"testbin\",\n      \"--undef_flag1\",\n      \"--undef_flag2=123\",\n      \"--undefok=undef_flag2,undef_flag1,undef_flag3\",\n      \"--undef_flag3\",\n      \"value\",\n      \"--\",\n      \"--undef_flag4\",\n  };\n\n  std::vector<char*> positional_args;\n  std::vector<absl::UnrecognizedFlag> unrecognized_flags;\n\n  absl::ParseAbseilFlagsOnly(8, const_cast<char**>(in_args), positional_args,\n                             unrecognized_flags);\n  EXPECT_THAT(positional_args,\n              ElementsAreArray({absl::string_view(\"testbin\"),\n                                absl::string_view(\"value\"),\n                                absl::string_view(\"--undef_flag4\")}));\n  EXPECT_THAT(unrecognized_flags, testing::IsEmpty());\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ParseDeathTest, ExitOnUnrecognizedFlagPrintsHelp) {\n  const char* in_args[] = {\n      \"testbin\",\n      \"--undef_flag1\",\n      \"--help=int_flag\",\n  };\n\n  EXPECT_EXIT(InvokeParseCommandLineImpl(in_args), testing::ExitedWithCode(1),\n              AllOf(HasSubstr(\"Unknown command line flag 'undef_flag1'\"),\n                    HasSubstr(\"Try --helpfull to get a list of all flags\")));\n}\n\n// --------------------------------------------------------------------\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/reflection.cc",
    "content": "//\n//  Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/reflection.h\"\n\n#include <assert.h>\n\n#include <atomic>\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/internal/private_handle_accessor.h\"\n#include \"absl/flags/internal/registry.h\"\n#include \"absl/flags/usage_config.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\n// --------------------------------------------------------------------\n// FlagRegistry\n//    A FlagRegistry singleton object holds all flag objects indexed by their\n//    names so that if you know a flag's name, you can access or set it. If the\n//    function is named FooLocked(), you must own the registry lock before\n//    calling the function; otherwise, you should *not* hold the lock, and the\n//    function will acquire it itself if needed.\n// --------------------------------------------------------------------\n\nclass FlagRegistry {\n public:\n  FlagRegistry() = default;\n  ~FlagRegistry() = default;\n\n  // Store a flag in this registry. Takes ownership of *flag.\n  void RegisterFlag(CommandLineFlag& flag, const char* filename);\n\n  void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.lock(); }\n  inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock(); }\n\n  void unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.unlock(); }\n  inline void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { unlock(); }\n\n  // Returns the flag object for the specified name, or nullptr if not found.\n  // Will emit a warning if a 'retired' flag is specified.\n  CommandLineFlag* FindFlag(absl::string_view name);\n\n  static FlagRegistry& GlobalRegistry();  // returns a singleton registry\n\n private:\n  friend class flags_internal::FlagSaverImpl;  // reads all the flags in order\n                                               // to copy them\n  friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);\n  friend void FinalizeRegistry();\n\n  // The map from name to flag, for FindFlag().\n  using FlagMap = absl::flat_hash_map<absl::string_view, CommandLineFlag*>;\n  using FlagIterator = FlagMap::iterator;\n  using FlagConstIterator = FlagMap::const_iterator;\n  FlagMap flags_;\n  std::vector<CommandLineFlag*> flat_flags_;\n  std::atomic<bool> finalized_flags_{false};\n\n  absl::Mutex lock_;\n\n  // Disallow\n  FlagRegistry(const FlagRegistry&);\n  FlagRegistry& operator=(const FlagRegistry&);\n};\n\nnamespace {\n\nclass FlagRegistryLock {\n public:\n  explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.lock(); }\n  ~FlagRegistryLock() { fr_.unlock(); }\n\n private:\n  FlagRegistry& fr_;\n};\n\n}  // namespace\n\nCommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {\n  if (finalized_flags_.load(std::memory_order_acquire)) {\n    // We could save some gcus here if we make `Name()` be non-virtual.\n    // We could move the `const char*` name to the base class.\n    auto it = std::partition_point(\n        flat_flags_.begin(), flat_flags_.end(),\n        [=](CommandLineFlag* f) { return f->Name() < name; });\n    if (it != flat_flags_.end() && (*it)->Name() == name) return *it;\n  }\n\n  FlagRegistryLock frl(*this);\n  auto it = flags_.find(name);\n  return it != flags_.end() ? it->second : nullptr;\n}\n\nvoid FlagRegistry::RegisterFlag(CommandLineFlag& flag, const char* filename) {\n  if (filename != nullptr &&\n      flag.Filename() != GetUsageConfig().normalize_filename(filename)) {\n    flags_internal::ReportUsageError(\n        absl::StrCat(\n            \"Inconsistency between flag object and registration for flag '\",\n            flag.Name(),\n            \"', likely due to duplicate flags or an ODR violation. Relevant \"\n            \"files: \",\n            flag.Filename(), \" and \", filename),\n        true);\n    std::exit(1);\n  }\n\n  FlagRegistryLock registry_lock(*this);\n\n  std::pair<FlagIterator, bool> ins =\n      flags_.insert(FlagMap::value_type(flag.Name(), &flag));\n  if (ins.second == false) {  // means the name was already in the map\n    CommandLineFlag& old_flag = *ins.first->second;\n    if (flag.IsRetired() != old_flag.IsRetired()) {\n      // All registrations must agree on the 'retired' flag.\n      flags_internal::ReportUsageError(\n          absl::StrCat(\n              \"Retired flag '\", flag.Name(), \"' was defined normally in file '\",\n              (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), \"'.\"),\n          true);\n    } else if (flags_internal::PrivateHandleAccessor::TypeId(flag) !=\n               flags_internal::PrivateHandleAccessor::TypeId(old_flag)) {\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Flag '\", flag.Name(),\n                       \"' was defined more than once but with \"\n                       \"differing types. Defined in files '\",\n                       old_flag.Filename(), \"' and '\", flag.Filename(), \"'.\"),\n          true);\n    } else if (old_flag.IsRetired()) {\n      return;\n    } else if (old_flag.Filename() != flag.Filename()) {\n      flags_internal::ReportUsageError(\n          absl::StrCat(\"Flag '\", flag.Name(),\n                       \"' was defined more than once (in files '\",\n                       old_flag.Filename(), \"' and '\", flag.Filename(), \"').\"),\n          true);\n    } else {\n      flags_internal::ReportUsageError(\n          absl::StrCat(\n              \"Something is wrong with flag '\", flag.Name(), \"' in file '\",\n              flag.Filename(), \"'. One possibility: file '\", flag.Filename(),\n              \"' is being linked both statically and dynamically into this \"\n              \"executable. e.g. some files listed as srcs to a test and also \"\n              \"listed as srcs of some shared lib deps of the same test.\"),\n          true);\n    }\n    // All cases above are fatal, except for the retired flags.\n    std::exit(1);\n  }\n}\n\nFlagRegistry& FlagRegistry::GlobalRegistry() {\n  static absl::NoDestructor<FlagRegistry> global_registry;\n  return *global_registry;\n}\n\n// --------------------------------------------------------------------\n\nvoid ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {\n  FlagRegistry& registry = FlagRegistry::GlobalRegistry();\n\n  if (registry.finalized_flags_.load(std::memory_order_acquire)) {\n    for (const auto& i : registry.flat_flags_) visitor(*i);\n  }\n\n  FlagRegistryLock frl(registry);\n  for (const auto& i : registry.flags_) visitor(*i.second);\n}\n\n// --------------------------------------------------------------------\n\nbool RegisterCommandLineFlag(CommandLineFlag& flag, const char* filename) {\n  FlagRegistry::GlobalRegistry().RegisterFlag(flag, filename);\n  return true;\n}\n\nvoid FinalizeRegistry() {\n  auto& registry = FlagRegistry::GlobalRegistry();\n  FlagRegistryLock frl(registry);\n  if (registry.finalized_flags_.load(std::memory_order_relaxed)) {\n    // Was already finalized. Ignore the second time.\n    return;\n  }\n  registry.flat_flags_.reserve(registry.flags_.size());\n  for (const auto& f : registry.flags_) {\n    registry.flat_flags_.push_back(f.second);\n  }\n  std::sort(std::begin(registry.flat_flags_), std::end(registry.flat_flags_),\n            [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {\n              return lhs->Name() < rhs->Name();\n            });\n  registry.flags_.clear();\n  registry.finalized_flags_.store(true, std::memory_order_release);\n}\n\n// --------------------------------------------------------------------\n\nnamespace {\n\n// These are only used as constexpr global objects.\n// They do not use a virtual destructor to simplify their implementation.\n// They are not destroyed except at program exit, so leaks do not matter.\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wnon-virtual-dtor\"\n#endif\nclass RetiredFlagObj final : public CommandLineFlag {\n public:\n  constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)\n      : name_(name), type_id_(type_id) {}\n\n private:\n  absl::string_view Name() const override { return name_; }\n  std::string Filename() const override {\n    OnAccess();\n    return \"RETIRED\";\n  }\n  FlagFastTypeId TypeId() const override { return type_id_; }\n  std::string Help() const override {\n    OnAccess();\n    return \"\";\n  }\n  bool IsRetired() const override { return true; }\n  bool IsSpecifiedOnCommandLine() const override {\n    OnAccess();\n    return false;\n  }\n  std::string DefaultValue() const override {\n    OnAccess();\n    return \"\";\n  }\n  std::string CurrentValue() const override {\n    OnAccess();\n    return \"\";\n  }\n\n  // Any input is valid\n  bool ValidateInputValue(absl::string_view) const override {\n    OnAccess();\n    return true;\n  }\n\n  std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {\n    return nullptr;\n  }\n\n  bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,\n                 flags_internal::ValueSource, std::string&) override {\n    OnAccess();\n    return false;\n  }\n\n  void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }\n\n  void Read(void*) const override { OnAccess(); }\n\n  void OnAccess() const {\n    flags_internal::ReportUsageError(\n        absl::StrCat(\"Accessing retired flag '\", name_, \"'\"), false);\n  }\n\n  // Data members\n  const char* const name_;\n  const FlagFastTypeId type_id_;\n};\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n}  // namespace\n\nvoid Retire(const char* name, FlagFastTypeId type_id, unsigned char* buf) {\n  static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, \"\");\n  static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, \"\");\n  auto* flag = ::new (buf) flags_internal::RetiredFlagObj(name, type_id);\n  FlagRegistry::GlobalRegistry().RegisterFlag(*flag, nullptr);\n}\n\n// --------------------------------------------------------------------\n\nclass FlagSaverImpl {\n public:\n  FlagSaverImpl() = default;\n  FlagSaverImpl(const FlagSaverImpl&) = delete;\n  void operator=(const FlagSaverImpl&) = delete;\n\n  // Saves the flag states from the flag registry into this object.\n  // It's an error to call this more than once.\n  void SaveFromRegistry() {\n    assert(backup_registry_.empty());  // call only once!\n    flags_internal::ForEachFlag([&](CommandLineFlag& flag) {\n      if (auto flag_state =\n              flags_internal::PrivateHandleAccessor::SaveState(flag)) {\n        backup_registry_.emplace_back(std::move(flag_state));\n      }\n    });\n  }\n\n  // Restores the saved flag states into the flag registry.\n  void RestoreToRegistry() && {\n    for (const auto& flag_state : backup_registry_) {\n      std::move(*flag_state).Restore();\n    }\n  }\n\n private:\n  std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>\n      backup_registry_;\n};\n\n}  // namespace flags_internal\n\nFlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {\n  impl_->SaveFromRegistry();\n}\n\nFlagSaver::~FlagSaver() {\n  if (!impl_) return;\n\n  std::move(*impl_).RestoreToRegistry();\n  delete impl_;\n}\n\n// --------------------------------------------------------------------\n\nCommandLineFlag* FindCommandLineFlag(absl::string_view name) {\n  if (name.empty()) return nullptr;\n  flags_internal::FlagRegistry& registry =\n      flags_internal::FlagRegistry::GlobalRegistry();\n  return registry.FindFlag(name);\n}\n\n// --------------------------------------------------------------------\n\nabsl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {\n  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;\n  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {\n    if (!flag.IsRetired()) res.insert({flag.Name(), &flag});\n  });\n  return res;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/reflection.h",
    "content": "//\n// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: reflection.h\n// -----------------------------------------------------------------------------\n//\n// This file defines the routines to access and operate on an Abseil Flag's\n// reflection handle.\n\n#ifndef ABSL_FLAGS_REFLECTION_H_\n#define ABSL_FLAGS_REFLECTION_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/flags/commandlineflag.h\"\n#include \"absl/flags/internal/commandlineflag.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\nclass FlagSaverImpl;\n}  // namespace flags_internal\n\n// FindCommandLineFlag()\n//\n// Returns the reflection handle of an Abseil flag of the specified name, or\n// `nullptr` if not found. This function will emit a warning if the name of a\n// 'retired' flag is specified.\nabsl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);\n\n// Returns current state of the Flags registry in a form of mapping from flag\n// name to a flag reflection handle.\nabsl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();\n\n//------------------------------------------------------------------------------\n// FlagSaver\n//------------------------------------------------------------------------------\n//\n// A FlagSaver object stores the state of flags in the scope where the FlagSaver\n// is defined, allowing modification of those flags within that scope and\n// automatic restoration of the flags to their previous state upon leaving the\n// scope.\n//\n// A FlagSaver can be used within tests to temporarily change the test\n// environment and restore the test case to its previous state.\n//\n// Example:\n//\n//   void MyFunc() {\n//    absl::FlagSaver fs;\n//    ...\n//    absl::SetFlag(&FLAGS_myFlag, otherValue);\n//    ...\n//  } // scope of FlagSaver left, flags return to previous state\n//\n// This class is thread-safe.\n\nclass FlagSaver {\n public:\n  FlagSaver();\n  ~FlagSaver();\n\n  FlagSaver(const FlagSaver&) = delete;\n  void operator=(const FlagSaver&) = delete;\n\n private:\n  flags_internal::FlagSaverImpl* impl_;\n};\n\n//-----------------------------------------------------------------------------\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_REFLECTION_H_\n"
  },
  {
    "path": "absl/flags/reflection_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/reflection.h\"\n\n#include <memory>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/flags/config.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n\nABSL_FLAG(int, int_flag, 1, \"int_flag help\");\nABSL_FLAG(std::string, string_flag, \"dflt\", \"string_flag help\");\nABSL_RETIRED_FLAG(bool, bool_retired_flag, false, \"bool_retired_flag help\");\n\nnamespace {\n\nclass ReflectionTest : public testing::Test {\n protected:\n  void SetUp() override {\n#if ABSL_FLAGS_STRIP_NAMES\n    GTEST_SKIP() << \"This test requires flag names to be present\";\n#endif\n    flag_saver_ = absl::make_unique<absl::FlagSaver>();\n  }\n  void TearDown() override { flag_saver_.reset(); }\n\n private:\n  std::unique_ptr<absl::FlagSaver> flag_saver_;\n};\n\n// --------------------------------------------------------------------\n\nTEST_F(ReflectionTest, TestFindCommandLineFlag) {\n  auto* handle = absl::FindCommandLineFlag(\"some_flag\");\n  EXPECT_EQ(handle, nullptr);\n\n  handle = absl::FindCommandLineFlag(\"int_flag\");\n  EXPECT_NE(handle, nullptr);\n\n  handle = absl::FindCommandLineFlag(\"string_flag\");\n  EXPECT_NE(handle, nullptr);\n\n  handle = absl::FindCommandLineFlag(\"bool_retired_flag\");\n  EXPECT_NE(handle, nullptr);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ReflectionTest, TestGetAllFlags) {\n  auto all_flags = absl::GetAllFlags();\n  EXPECT_NE(all_flags.find(\"int_flag\"), all_flags.end());\n  EXPECT_EQ(all_flags.find(\"bool_retired_flag\"), all_flags.end());\n  EXPECT_EQ(all_flags.find(\"some_undefined_flag\"), all_flags.end());\n\n  std::vector<absl::string_view> flag_names_first_attempt;\n  auto all_flags_1 = absl::GetAllFlags();\n  for (auto f : all_flags_1) {\n    flag_names_first_attempt.push_back(f.first);\n  }\n\n  std::vector<absl::string_view> flag_names_second_attempt;\n  auto all_flags_2 = absl::GetAllFlags();\n  for (auto f : all_flags_2) {\n    flag_names_second_attempt.push_back(f.first);\n  }\n\n  EXPECT_THAT(flag_names_first_attempt,\n              ::testing::UnorderedElementsAreArray(flag_names_second_attempt));\n}\n\n// --------------------------------------------------------------------\n\nstruct CustomUDT {\n  CustomUDT() : a(1), b(1) {}\n  CustomUDT(int a_, int b_) : a(a_), b(b_) {}\n\n  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {\n    return f1.a == f2.a && f1.b == f2.b;\n  }\n\n  int a;\n  int b;\n};\nbool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {\n  std::vector<absl::string_view> parts =\n      absl::StrSplit(in, ':', absl::SkipWhitespace());\n\n  if (parts.size() != 2) return false;\n\n  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;\n\n  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;\n\n  return true;\n}\nstd::string AbslUnparseFlag(const CustomUDT& f) {\n  return absl::StrCat(f.a, \":\", f.b);\n}\n\n}  // namespace\n\n// --------------------------------------------------------------------\n\nABSL_FLAG(bool, test_flag_01, true, \"\");\nABSL_FLAG(int, test_flag_02, 1234, \"\");\nABSL_FLAG(int16_t, test_flag_03, -34, \"\");\nABSL_FLAG(uint16_t, test_flag_04, 189, \"\");\nABSL_FLAG(int32_t, test_flag_05, 10765, \"\");\nABSL_FLAG(uint32_t, test_flag_06, 40000, \"\");\nABSL_FLAG(int64_t, test_flag_07, -1234567, \"\");\nABSL_FLAG(uint64_t, test_flag_08, 9876543, \"\");\nABSL_FLAG(double, test_flag_09, -9.876e-50, \"\");\nABSL_FLAG(float, test_flag_10, 1.234e12f, \"\");\nABSL_FLAG(std::string, test_flag_11, \"\", \"\");\nABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), \"\");\nstatic int counter = 0;\nABSL_FLAG(int, test_flag_13, 200, \"\").OnUpdate([]() { counter++; });\nABSL_FLAG(CustomUDT, test_flag_14, {}, \"\");\n\nnamespace {\n\nTEST_F(ReflectionTest, TestFlagSaverInScope) {\n  {\n    absl::FlagSaver s;\n    counter = 0;\n    absl::SetFlag(&FLAGS_test_flag_01, false);\n    absl::SetFlag(&FLAGS_test_flag_02, -1021);\n    absl::SetFlag(&FLAGS_test_flag_03, 6009);\n    absl::SetFlag(&FLAGS_test_flag_04, 44);\n    absl::SetFlag(&FLAGS_test_flag_05, +800);\n    absl::SetFlag(&FLAGS_test_flag_06, -40978756);\n    absl::SetFlag(&FLAGS_test_flag_07, 23405);\n    absl::SetFlag(&FLAGS_test_flag_08, 975310);\n    absl::SetFlag(&FLAGS_test_flag_09, 1.00001);\n    absl::SetFlag(&FLAGS_test_flag_10, -3.54f);\n    absl::SetFlag(&FLAGS_test_flag_11, \"asdf\");\n    absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20));\n    absl::SetFlag(&FLAGS_test_flag_13, 4);\n    absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2});\n  }\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), \"\");\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});\n  EXPECT_EQ(counter, 2);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) {\n  {\n    absl::FlagSaver s;\n    counter = 0;\n    std::string error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_01\")->ParseFrom(\"false\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_02\")->ParseFrom(\"-4536\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_03\")->ParseFrom(\"111\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_04\")->ParseFrom(\"909\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_05\")->ParseFrom(\"-2004\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_06\")->ParseFrom(\"1000023\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_07\")->ParseFrom(\"69305\", &error))\n        << error;\n    EXPECT_TRUE(absl::FindCommandLineFlag(\"test_flag_08\")\n                    ->ParseFrom(\"1000000001\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_09\")->ParseFrom(\"2.09021\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_10\")->ParseFrom(\"-33.1\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_11\")->ParseFrom(\"ADD_FOO\", &error))\n        << error;\n    EXPECT_TRUE(absl::FindCommandLineFlag(\"test_flag_12\")\n                    ->ParseFrom(\"3h11m16s\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_13\")->ParseFrom(\"0\", &error))\n        << error;\n    EXPECT_TRUE(\n        absl::FindCommandLineFlag(\"test_flag_14\")->ParseFrom(\"10:1\", &error))\n        << error;\n  }\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);\n  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), \"\");\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});\n  EXPECT_EQ(counter, 2);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) {\n  {\n    absl::FlagSaver s;\n    absl::SetFlag(&FLAGS_test_flag_08, 10);\n    EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);\n    {\n      absl::FlagSaver s;\n      absl::SetFlag(&FLAGS_test_flag_08, 20);\n      EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);\n      {\n        absl::FlagSaver s;\n        absl::SetFlag(&FLAGS_test_flag_08, -200);\n        EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200);\n      }\n      EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);\n    }\n    EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);\n  }\n  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/flags/usage.cc",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/flags/usage.h\"\n\n#include <stdlib.h>\n\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/internal/usage.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\nnamespace {\nABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);\nABSL_CONST_INIT std::string* program_usage_message\n    ABSL_GUARDED_BY(usage_message_guard) = nullptr;\n}  // namespace\n}  // namespace flags_internal\n\n// --------------------------------------------------------------------\n// Sets the \"usage\" message to be used by help reporting routines.\nvoid SetProgramUsageMessage(absl::string_view new_usage_message) {\n  absl::MutexLock l(flags_internal::usage_message_guard);\n\n  if (flags_internal::program_usage_message != nullptr) {\n    ABSL_INTERNAL_LOG(FATAL, \"SetProgramUsageMessage() called twice.\");\n    std::exit(1);\n  }\n\n  flags_internal::program_usage_message = new std::string(new_usage_message);\n}\n\n// --------------------------------------------------------------------\n// Returns the usage message set by SetProgramUsageMessage().\n// Note: We able to return string_view here only because calling\n// SetProgramUsageMessage twice is prohibited.\nabsl::string_view ProgramUsageMessage() {\n  absl::MutexLock l(flags_internal::usage_message_guard);\n\n  return flags_internal::program_usage_message != nullptr\n             ? absl::string_view(*flags_internal::program_usage_message)\n             : \"Warning: SetProgramUsageMessage() never called\";\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/usage.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FLAGS_USAGE_H_\n#define ABSL_FLAGS_USAGE_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\n// --------------------------------------------------------------------\n// Usage reporting interfaces\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Sets the \"usage\" message to be used by help reporting routines.\n// For example:\n//  absl::SetProgramUsageMessage(\n//      absl::StrCat(\"This program does nothing.  Sample usage:\\n\", argv[0],\n//                   \" <uselessarg1> <uselessarg2>\"));\n// Do not include commandline flags in the usage: we do that for you!\n// Note: Calling SetProgramUsageMessage twice will trigger a call to std::exit.\nvoid SetProgramUsageMessage(absl::string_view new_usage_message);\n\n// Returns the usage message set by SetProgramUsageMessage().\nabsl::string_view ProgramUsageMessage();\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FLAGS_USAGE_H_\n"
  },
  {
    "path": "absl/flags/usage_config.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/usage_config.h\"\n\n#include <functional>\n#include <iostream>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/flags/internal/path_util.h\"\n#include \"absl/flags/internal/program_name.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/synchronization/mutex.h\"\n\nextern \"C\" {\n\n// Additional report of fatal usage error message before we std::exit. Error is\n// fatal if is_fatal argument to ReportUsageError is true.\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(\n    AbslInternalReportFatalUsageError)(absl::string_view) {}\n\n}  // extern \"C\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace flags_internal {\n\nnamespace {\n\n// --------------------------------------------------------------------\n// Returns true if flags defined in the filename should be reported with\n// -helpshort flag.\n\nbool ContainsHelpshortFlags(absl::string_view filename) {\n  // By default we only want flags in binary's main. We expect the main\n  // routine to reside in <program>.cc or <program>-main.cc or\n  // <program>_main.cc, where the <program> is the name of the binary\n  // (without .exe on Windows).\n  auto suffix = flags_internal::Basename(filename);\n  auto program_name = flags_internal::ShortProgramInvocationName();\n  absl::string_view program_name_ref = program_name;\n#if defined(_WIN32)\n  absl::ConsumeSuffix(&program_name_ref, \".exe\");\n#endif\n  if (!absl::ConsumePrefix(&suffix, program_name_ref))\n    return false;\n  return absl::StartsWith(suffix, \".\") || absl::StartsWith(suffix, \"-main.\") ||\n         absl::StartsWith(suffix, \"_main.\");\n}\n\n// --------------------------------------------------------------------\n// Returns true if flags defined in the filename should be reported with\n// -helppackage flag.\n\nbool ContainsHelppackageFlags(absl::string_view filename) {\n  // TODO(rogeeff): implement properly when registry is available.\n  return ContainsHelpshortFlags(filename);\n}\n\n// --------------------------------------------------------------------\n// Generates program version information into supplied output.\n\nstd::string VersionString() {\n  std::string version_str(flags_internal::ShortProgramInvocationName());\n\n  version_str += \"\\n\";\n\n#if !defined(NDEBUG)\n  version_str += \"Debug build (NDEBUG not #defined)\\n\";\n#endif\n\n  return version_str;\n}\n\n// --------------------------------------------------------------------\n// Normalizes the filename specific to the build system/filesystem used.\n\nstd::string NormalizeFilename(absl::string_view filename) {\n  // Skip any leading slashes\n  auto pos = filename.find_first_not_of(\"\\\\/\");\n  if (pos == absl::string_view::npos) return \"\";\n\n  filename.remove_prefix(pos);\n  return std::string(filename);\n}\n\n// --------------------------------------------------------------------\n\nabsl::Mutex& CustomUsageConfigMutex() {\n  static absl::NoDestructor<absl::Mutex> mutex;\n  return *mutex;\n}\nABSL_CONST_INIT FlagsUsageConfig* custom_usage_config\n    ABSL_GUARDED_BY(CustomUsageConfigMutex())\n        ABSL_PT_GUARDED_BY(CustomUsageConfigMutex()) = nullptr;\n\n}  // namespace\n\nFlagsUsageConfig GetUsageConfig() {\n  absl::MutexLock l(CustomUsageConfigMutex());\n\n  if (custom_usage_config) return *custom_usage_config;\n\n  FlagsUsageConfig default_config;\n  default_config.contains_helpshort_flags = &ContainsHelpshortFlags;\n  default_config.contains_help_flags = &ContainsHelppackageFlags;\n  default_config.contains_helppackage_flags = &ContainsHelppackageFlags;\n  default_config.version_string = &VersionString;\n  default_config.normalize_filename = &NormalizeFilename;\n\n  return default_config;\n}\n\nvoid ReportUsageError(absl::string_view msg, bool is_fatal) {\n  std::cerr << \"ERROR: \" << msg << std::endl;\n\n  if (is_fatal) {\n    ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(msg);\n  }\n}\n\n}  // namespace flags_internal\n\nvoid SetFlagsUsageConfig(FlagsUsageConfig usage_config) {\n  absl::MutexLock l(flags_internal::CustomUsageConfigMutex());\n\n  if (!usage_config.contains_helpshort_flags)\n    usage_config.contains_helpshort_flags =\n        flags_internal::ContainsHelpshortFlags;\n\n  if (!usage_config.contains_help_flags)\n    usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags;\n\n  if (!usage_config.contains_helppackage_flags)\n    usage_config.contains_helppackage_flags =\n        flags_internal::ContainsHelppackageFlags;\n\n  if (!usage_config.version_string)\n    usage_config.version_string = flags_internal::VersionString;\n\n  if (!usage_config.normalize_filename)\n    usage_config.normalize_filename = flags_internal::NormalizeFilename;\n\n  if (flags_internal::custom_usage_config)\n    *flags_internal::custom_usage_config = usage_config;\n  else\n    flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/flags/usage_config.h",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: usage_config.h\n// -----------------------------------------------------------------------------\n//\n// This file defines the main usage reporting configuration interfaces and\n// documents Abseil's supported built-in usage flags. If these flags are found\n// when parsing a command-line, Abseil will exit the program and display\n// appropriate help messages.\n#ifndef ABSL_FLAGS_USAGE_CONFIG_H_\n#define ABSL_FLAGS_USAGE_CONFIG_H_\n\n#include <functional>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\n// -----------------------------------------------------------------------------\n// Built-in Usage Flags\n// -----------------------------------------------------------------------------\n//\n// Abseil supports the following built-in usage flags. When passed, these flags\n// exit the program and :\n//\n// * --help\n//     Shows help on important flags for this binary\n// * --helpfull\n//     Shows help on all flags\n// * --helpshort\n//     Shows help on only the main module for this program\n// * --helppackage\n//     Shows help on all modules in the main package\n// * --version\n//     Shows the version and build info for this binary and exits\n// * --only_check_args\n//     Exits after checking all flags\n// * --helpon\n//     Shows help on the modules named by this flag value\n// * --helpmatch\n//     Shows help on modules whose name contains the specified substring\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace flags_internal {\nusing FlagKindFilter = std::function<bool (absl::string_view)>;\n}  // namespace flags_internal\n\n// FlagsUsageConfig\n//\n// This structure contains the collection of callbacks for changing the behavior\n// of the usage reporting routines in Abseil Flags.\nstruct FlagsUsageConfig {\n  // Returns true if flags defined in the given source code file should be\n  // reported with --helpshort flag. For example, if the file\n  // \"path/to/my/code.cc\" defines the flag \"--my_flag\", and\n  // contains_helpshort_flags(\"path/to/my/code.cc\") returns true, invoking the\n  // program with --helpshort will include information about --my_flag in the\n  // program output.\n  flags_internal::FlagKindFilter contains_helpshort_flags;\n\n  // Returns true if flags defined in the filename should be reported with\n  // --help flag. For example, if the file\n  // \"path/to/my/code.cc\" defines the flag \"--my_flag\", and\n  // contains_help_flags(\"path/to/my/code.cc\") returns true, invoking the\n  // program with --help will include information about --my_flag in the\n  // program output.\n  flags_internal::FlagKindFilter contains_help_flags;\n\n  // Returns true if flags defined in the filename should be reported with\n  // --helppackage flag. For example, if the file\n  // \"path/to/my/code.cc\" defines the flag \"--my_flag\", and\n  // contains_helppackage_flags(\"path/to/my/code.cc\") returns true, invoking the\n  // program with --helppackage will include information about --my_flag in the\n  // program output.\n  flags_internal::FlagKindFilter contains_helppackage_flags;\n\n  // Generates string containing program version. This is the string reported\n  // when user specifies --version in a command line.\n  std::function<std::string()> version_string;\n\n  // Normalizes the filename specific to the build system/filesystem used. This\n  // routine is used when we report the information about the flag definition\n  // location. For instance, if your build resides at some location you do not\n  // want to expose in the usage output, you can trim it to show only relevant\n  // part.\n  // For example:\n  //   normalize_filename(\"/my_company/some_long_path/src/project/file.cc\")\n  // might produce\n  //   \"project/file.cc\".\n  std::function<std::string(absl::string_view)> normalize_filename;\n};\n\n// SetFlagsUsageConfig()\n//\n// Sets the usage reporting configuration callbacks. If any of the callbacks are\n// not set in usage_config instance, then the default value of the callback is\n// used.\nvoid SetFlagsUsageConfig(FlagsUsageConfig usage_config);\n\nnamespace flags_internal {\n\nFlagsUsageConfig GetUsageConfig();\n\nvoid ReportUsageError(absl::string_view msg, bool is_fatal);\n\n}  // namespace flags_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nextern \"C\" {\n\n// Additional report of fatal usage error message before we std::exit. Error is\n// fatal if is_fatal argument to ReportUsageError is true.\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(\n    absl::string_view);\n\n}  // extern \"C\"\n\n#endif  // ABSL_FLAGS_USAGE_CONFIG_H_\n"
  },
  {
    "path": "absl/flags/usage_config_test.cc",
    "content": "//\n//  Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/usage_config.h\"\n\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/flags/internal/path_util.h\"\n#include \"absl/flags/internal/program_name.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nclass FlagsUsageConfigTest : public testing::Test {\n protected:\n  void SetUp() override {\n    // Install Default config for the use on this unit test.\n    // Binary may install a custom config before tests are run.\n    absl::FlagsUsageConfig default_config;\n    absl::SetFlagsUsageConfig(default_config);\n  }\n};\n\nnamespace flags = absl::flags_internal;\n\nbool TstContainsHelpshortFlags(absl::string_view f) {\n  return absl::StartsWith(flags::Basename(f), \"progname.\");\n}\n\nbool TstContainsHelppackageFlags(absl::string_view f) {\n  return absl::EndsWith(flags::Package(f), \"aaa/\");\n}\n\nbool TstContainsHelpFlags(absl::string_view f) {\n  return absl::EndsWith(flags::Package(f), \"zzz/\");\n}\n\nstd::string TstVersionString() { return \"program 1.0.0\"; }\n\nstd::string TstNormalizeFilename(absl::string_view filename) {\n  return std::string(filename.substr(2));\n}\n\nvoid TstReportUsageMessage(absl::string_view msg) {}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) {\n  EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);\n  EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);\n  EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);\n  EXPECT_TRUE(flags::GetUsageConfig().version_string);\n  EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);\n\n  absl::FlagsUsageConfig empty_config;\n  empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;\n  empty_config.contains_help_flags = &TstContainsHelpFlags;\n  empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;\n  empty_config.version_string = &TstVersionString;\n  empty_config.normalize_filename = &TstNormalizeFilename;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);\n  EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);\n  EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);\n  EXPECT_TRUE(flags::GetUsageConfig().version_string);\n  EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) {\n#if defined(_WIN32)\n  flags::SetProgramInvocationName(\"usage_config_test.exe\");\n#else\n  flags::SetProgramInvocationName(\"usage_config_test\");\n#endif\n\n  auto config = flags::GetUsageConfig();\n  EXPECT_TRUE(config.contains_helpshort_flags(\"adir/cd/usage_config_test.cc\"));\n  EXPECT_TRUE(\n      config.contains_helpshort_flags(\"aaaa/usage_config_test-main.cc\"));\n  EXPECT_TRUE(config.contains_helpshort_flags(\"abc/usage_config_test_main.cc\"));\n  EXPECT_FALSE(config.contains_helpshort_flags(\"usage_config_main.cc\"));\n\n  absl::FlagsUsageConfig empty_config;\n  empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_TRUE(\n      flags::GetUsageConfig().contains_helpshort_flags(\"aaa/progname.cpp\"));\n  EXPECT_FALSE(\n      flags::GetUsageConfig().contains_helpshort_flags(\"aaa/progmane.cpp\"));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagsUsageConfigTest, TestContainsHelpFlags) {\n  flags::SetProgramInvocationName(\"usage_config_test\");\n\n  auto config = flags::GetUsageConfig();\n  EXPECT_TRUE(config.contains_help_flags(\"zzz/usage_config_test.cc\"));\n  EXPECT_TRUE(\n      config.contains_help_flags(\"bdir/a/zzz/usage_config_test-main.cc\"));\n  EXPECT_TRUE(\n      config.contains_help_flags(\"//aqse/zzz/usage_config_test_main.cc\"));\n  EXPECT_FALSE(config.contains_help_flags(\"zzz/aa/usage_config_main.cc\"));\n\n  absl::FlagsUsageConfig empty_config;\n  empty_config.contains_help_flags = &TstContainsHelpFlags;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags(\"zzz/main-body.c\"));\n  EXPECT_FALSE(\n      flags::GetUsageConfig().contains_help_flags(\"zzz/dir/main-body.c\"));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagsUsageConfigTest, TestContainsHelppackageFlags) {\n  flags::SetProgramInvocationName(\"usage_config_test\");\n\n  auto config = flags::GetUsageConfig();\n  EXPECT_TRUE(config.contains_helppackage_flags(\"aaa/usage_config_test.cc\"));\n  EXPECT_TRUE(\n      config.contains_helppackage_flags(\"bbdir/aaa/usage_config_test-main.cc\"));\n  EXPECT_TRUE(config.contains_helppackage_flags(\n      \"//aqswde/aaa/usage_config_test_main.cc\"));\n  EXPECT_FALSE(config.contains_helppackage_flags(\"aadir/usage_config_main.cc\"));\n\n  absl::FlagsUsageConfig empty_config;\n  empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_TRUE(\n      flags::GetUsageConfig().contains_helppackage_flags(\"aaa/main-body.c\"));\n  EXPECT_FALSE(\n      flags::GetUsageConfig().contains_helppackage_flags(\"aadir/main-body.c\"));\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagsUsageConfigTest, TestVersionString) {\n  flags::SetProgramInvocationName(\"usage_config_test\");\n\n#ifdef NDEBUG\n  std::string expected_output = \"usage_config_test\\n\";\n#else\n  std::string expected_output =\n      \"usage_config_test\\nDebug build (NDEBUG not #defined)\\n\";\n#endif\n\n  EXPECT_EQ(flags::GetUsageConfig().version_string(), expected_output);\n\n  absl::FlagsUsageConfig empty_config;\n  empty_config.version_string = &TstVersionString;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_EQ(flags::GetUsageConfig().version_string(), \"program 1.0.0\");\n}\n\n// --------------------------------------------------------------------\n\nTEST_F(FlagsUsageConfigTest, TestNormalizeFilename) {\n  // This tests the default implementation.\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"a/a.cc\"), \"a/a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"/a/a.cc\"), \"a/a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"///a/a.cc\"), \"a/a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"/\"), \"\");\n\n  // This tests that the custom implementation is called.\n  absl::FlagsUsageConfig empty_config;\n  empty_config.normalize_filename = &TstNormalizeFilename;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"a/a.cc\"), \"a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"aaa/a.cc\"), \"a/a.cc\");\n\n  // This tests that the default implementation is called.\n  empty_config.normalize_filename = nullptr;\n  absl::SetFlagsUsageConfig(empty_config);\n\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"a/a.cc\"), \"a/a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"/a/a.cc\"), \"a/a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"///a/a.cc\"), \"a/a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"\\\\a\\\\a.cc\"), \"a\\\\a.cc\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"//\"), \"\");\n  EXPECT_EQ(flags::GetUsageConfig().normalize_filename(\"\\\\\\\\\"), \"\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/functional/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"any_invocable\",\n    srcs = [\"internal/any_invocable.h\"],\n    hdrs = [\"any_invocable.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/meta:type_traits\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"any_invocable_test\",\n    srcs = [\n        \"any_invocable_test.cc\",\n        \"internal/any_invocable.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":any_invocable\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/meta:type_traits\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"bind_front\",\n    srcs = [\"internal/front_binder.h\"],\n    hdrs = [\"bind_front.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/container:compressed_tuple\",\n        \"//absl/meta:type_traits\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"bind_front_test\",\n    srcs = [\"bind_front_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bind_front\",\n        \"//absl/memory\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"function_ref\",\n    srcs = [\"internal/function_ref.h\"],\n    hdrs = [\"function_ref.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":any_invocable\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"function_ref_test\",\n    size = \"small\",\n    srcs = [\"function_ref_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":any_invocable\",\n        \":function_ref\",\n        \"//absl/base:config\",\n        \"//absl/container:test_instance_tracker\",\n        \"//absl/memory\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"overload\",\n    hdrs = [\"overload.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"overload_test\",\n    size = \"small\",\n    srcs = [\"overload_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":overload\",\n        \"//absl/base:config\",\n        \"//absl/strings\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"function_type_benchmark\",\n    testonly = True,\n    srcs = [\n        \"function_type_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":any_invocable\",\n        \":function_ref\",\n        \"//absl/base:core_headers\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/functional/CMakeLists.txt",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    any_invocable\n  SRCS\n    \"internal/any_invocable.h\"\n  HDRS\n    \"any_invocable.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::type_traits\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    any_invocable_test\n  SRCS\n    \"any_invocable_test.cc\"\n    \"internal/any_invocable.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::any_invocable\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::type_traits\n    absl::utility\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    bind_front\n  SRCS\n    \"internal/front_binder.h\"\n  HDRS\n    \"bind_front.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::compressed_tuple\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    bind_front_test\n  SRCS\n    \"bind_front_test.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::bind_front\n    absl::memory\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    function_ref\n  SRCS\n    \"internal/function_ref.h\"\n  HDRS\n    \"function_ref.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::any_invocable\n    absl::meta\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    function_ref_test\n  SRCS\n    \"function_ref_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::function_ref\n    absl::memory\n    absl::test_instance_tracker\n    absl::utility\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    overload\n  HDRS\n    \"overload.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::meta\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    overload_test\n  SRCS\n    \"overload_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::overload\n    absl::string_view\n    absl::strings\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/functional/any_invocable.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: any_invocable.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines an `absl::AnyInvocable` type that assumes ownership\n// and wraps an object of an invocable type. (Invocable types adhere to the\n// concept specified in https://en.cppreference.com/w/cpp/concepts/invocable.)\n//\n// In general, prefer `absl::AnyInvocable` when you need a type-erased\n// function parameter that needs to take ownership of the type.\n//\n// NOTE: `absl::AnyInvocable` is similar to the C++23 `std::move_only_function`\n// abstraction, but has a slightly different API and is not designed to be a\n// drop-in replacement or backfill of that type.\n//\n// Credits to Matt Calabrese (https://github.com/mattcalabrese) for the original\n// implementation.\n\n#ifndef ABSL_FUNCTIONAL_ANY_INVOCABLE_H_\n#define ABSL_FUNCTIONAL_ANY_INVOCABLE_H_\n\n#include <cstddef>\n#include <functional>\n#include <initializer_list>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/functional/internal/any_invocable.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::AnyInvocable\n//\n// `absl::AnyInvocable` is a functional wrapper type, like `std::function`, that\n// assumes ownership of an invocable object. Unlike `std::function`, an\n// `absl::AnyInvocable` is more type-safe and provides the following additional\n// benefits:\n//\n// * Properly adheres to const correctness of the underlying type\n// * Is move-only so avoids concurrency problems with copied invocables and\n//   unnecessary copies in general.\n// * Supports reference qualifiers allowing it to perform unique actions (noted\n//   below).\n//\n// `absl::AnyInvocable` is a template, and an `absl::AnyInvocable` instantiation\n// may wrap any invocable object with a compatible function signature, e.g.\n// having arguments and return types convertible to types matching the\n// `absl::AnyInvocable` signature, and also matching any stated reference\n// qualifiers, as long as that type is moveable. It therefore provides broad\n// type erasure for functional objects.\n//\n// An `absl::AnyInvocable` is typically used as a type-erased function parameter\n// for accepting various functional objects:\n//\n// // Define a function taking an AnyInvocable parameter.\n// void my_func(absl::AnyInvocable<int()> f) {\n//   ...\n// };\n//\n// // That function can accept any invocable type:\n//\n// // Accept a function reference. We don't need to move a reference.\n// int func1() { return 0; };\n// my_func(func1);\n//\n// // Accept a lambda. We use std::move here because otherwise my_func would\n// // copy the lambda.\n// auto lambda = []() { return 0; };\n// my_func(std::move(lambda));\n//\n// // Accept a function pointer. We don't need to move a function pointer.\n// func2 = &func1;\n// my_func(func2);\n//\n// // Accept an std::function by moving it. Note that the lambda is copyable\n// // (satisfying std::function requirements) and moveable (satisfying\n// // absl::AnyInvocable requirements).\n// std::function<int()> func6 = []() { return 0; };\n// my_func(std::move(func6));\n//\n// `AnyInvocable` also properly respects `const` qualifiers, reference\n// qualifiers, and the `noexcept` specification  as part of the user-specified\n// function type (e.g. `AnyInvocable<void() const && noexcept>`). These\n// qualifiers will be applied to the `AnyInvocable` object's `operator()`, and\n// the underlying invocable must be compatible with those qualifiers.\n//\n// Comparison of const and non-const function types:\n//\n//   // Store a closure inside of `func` with the function type `int()`.\n//   // Note that we have made `func` itself `const`.\n//   const AnyInvocable<int()> func = [](){ return 0; };\n//\n//   func();  // Compile-error: the passed type `int()` isn't `const`.\n//\n//   // Store a closure inside of `const_func` with the function type\n//   // `int() const`.\n//   // Note that we have also made `const_func` itself `const`.\n//   const AnyInvocable<int() const> const_func = [](){ return 0; };\n//\n//   const_func();  // Fine: `int() const` is `const`.\n//\n// In the above example, the call `func()` would have compiled if\n// `std::function` were used even though the types are not const compatible.\n// This is a bug, and using `absl::AnyInvocable` properly detects that bug.\n//\n// In addition to affecting the signature of `operator()`, the `const` and\n// reference qualifiers of the function type also appropriately constrain which\n// kinds of invocable objects you are allowed to place into the `AnyInvocable`\n// instance. If you specify a function type that is const-qualified, then\n// anything that you attempt to put into the `AnyInvocable` must be callable on\n// a `const` instance of that type.\n//\n// Constraint example:\n//\n//   // Fine because the lambda is callable when `const`.\n//   AnyInvocable<int() const> func = [=](){ return 0; };\n//\n//   // This is a compile-error because the lambda isn't callable when `const`.\n//   AnyInvocable<int() const> error = [=]() mutable { return 0; };\n//\n// An `&&` qualifier can be used to express that an `absl::AnyInvocable`\n// instance should be invoked at most once:\n//\n//   // Invokes `continuation` with the logical result of an operation when\n//   // that operation completes (common in asynchronous code).\n//   void CallOnCompletion(AnyInvocable<void(int)&&> continuation) {\n//     int result_of_foo = foo();\n//\n//     // `std::move` is required because the `operator()` of `continuation` is\n//     // rvalue-reference qualified.\n//     std::move(continuation)(result_of_foo);\n//   }\n//\n// Attempting to call `absl::AnyInvocable` multiple times in such a case\n// results in undefined behavior.\n//\n// Invoking an empty `absl::AnyInvocable` results in undefined behavior:\n//\n//   // Create an empty instance using the default constructor.\n//   AnyInvocable<void()> empty;\n//   empty();  // WARNING: Undefined behavior!\ntemplate <class Sig>\nclass ABSL_NULLABILITY_COMPATIBLE ABSL_ATTRIBUTE_OWNER AnyInvocable\n    : private internal_any_invocable::Impl<Sig> {\n private:\n  static_assert(\n      std::is_function<Sig>::value,\n      \"The template argument of AnyInvocable must be a function type.\");\n\n  using Impl = internal_any_invocable::Impl<Sig>;\n\n public:\n  // The return type of Sig\n  using result_type = typename Impl::result_type;\n  using absl_internal_is_view = std::false_type;\n\n  // Constructors\n\n  // Constructs the `AnyInvocable` in an empty state.\n  // Invoking it results in undefined behavior.\n  AnyInvocable() noexcept = default;\n  AnyInvocable(std::nullptr_t) noexcept {}  // NOLINT\n\n  // Constructs the `AnyInvocable` from an existing `AnyInvocable` by a move.\n  // Note that `f` is not guaranteed to be empty after move-construction,\n  // although it may be.\n  AnyInvocable(AnyInvocable&& /*f*/) noexcept = default;\n\n  // Constructs an `AnyInvocable` from an invocable object.\n  //\n  // Upon construction, `*this` is only empty if `f` is a function pointer or\n  // member pointer type and is null, or if `f` is an `AnyInvocable` that is\n  // empty.\n  template <class F, typename = absl::enable_if_t<\n                         internal_any_invocable::CanConvert<Sig, F>::value>>\n  AnyInvocable(F&& f)  // NOLINT\n      : Impl(internal_any_invocable::ConversionConstruct(),\n             std::forward<F>(f)) {}\n\n  // Constructs an `AnyInvocable` that holds an invocable object of type `T`,\n  // which is constructed in-place from the given arguments.\n  //\n  // Example:\n  //\n  //   AnyInvocable<int(int)> func(\n  //       absl::in_place_type<PossiblyImmovableType>, arg1, arg2);\n  //\n  template <class T, class... Args,\n            typename = absl::enable_if_t<\n                internal_any_invocable::CanEmplace<Sig, T, Args...>::value>>\n  explicit AnyInvocable(absl::in_place_type_t<T>, Args&&... args)\n      : Impl(absl::in_place_type<absl::decay_t<T>>,\n             std::forward<Args>(args)...) {\n    static_assert(std::is_same<T, absl::decay_t<T>>::value,\n                  \"The explicit template argument of in_place_type is required \"\n                  \"to be an unqualified object type.\");\n  }\n\n  // Overload of the above constructor to support list-initialization.\n  template <class T, class U, class... Args,\n            typename = absl::enable_if_t<internal_any_invocable::CanEmplace<\n                Sig, T, std::initializer_list<U>&, Args...>::value>>\n  explicit AnyInvocable(absl::in_place_type_t<T>,\n                        std::initializer_list<U> ilist, Args&&... args)\n      : Impl(absl::in_place_type<absl::decay_t<T>>, ilist,\n             std::forward<Args>(args)...) {\n    static_assert(std::is_same<T, absl::decay_t<T>>::value,\n                  \"The explicit template argument of in_place_type is required \"\n                  \"to be an unqualified object type.\");\n  }\n\n  // Assignment Operators\n\n  // Assigns an `AnyInvocable` through move-assignment.\n  // Note that `f` is not guaranteed to be empty after move-assignment\n  // although it may be.\n  AnyInvocable& operator=(AnyInvocable&& /*f*/) noexcept = default;\n\n  // Assigns an `AnyInvocable` from a nullptr, clearing the `AnyInvocable`. If\n  // not empty, destroys the target, putting `*this` into an empty state.\n  AnyInvocable& operator=(std::nullptr_t) noexcept {\n    this->Clear();\n    return *this;\n  }\n\n  // Assigns an `AnyInvocable` from an existing `AnyInvocable` instance.\n  //\n  // Upon assignment, `*this` is only empty if `f` is a function pointer or\n  // member pointer type and is null, or if `f` is an `AnyInvocable` that is\n  // empty.\n  template <class F, typename = absl::enable_if_t<\n                         internal_any_invocable::CanAssign<Sig, F>::value>>\n  AnyInvocable& operator=(F&& f) {\n    *this = AnyInvocable(std::forward<F>(f));\n    return *this;\n  }\n\n  // Assigns an `AnyInvocable` from a reference to an invocable object.\n  // Upon assignment, stores a reference to the invocable object in the\n  // `AnyInvocable` instance.\n  template <\n      class F,\n      typename = absl::enable_if_t<\n          internal_any_invocable::CanAssignReferenceWrapper<Sig, F>::value>>\n  AnyInvocable& operator=(std::reference_wrapper<F> f) noexcept {\n    *this = AnyInvocable(f);\n    return *this;\n  }\n\n  // Destructor\n\n  // If not empty, destroys the target.\n  ~AnyInvocable() = default;\n\n  // absl::AnyInvocable::swap()\n  //\n  // Exchanges the targets of `*this` and `other`.\n  void swap(AnyInvocable& other) noexcept { std::swap(*this, other); }\n\n  // absl::AnyInvocable::operator bool()\n  //\n  // Returns `true` if `*this` is not empty.\n  //\n  // WARNING: An `AnyInvocable` that wraps an empty `std::function` is not\n  // itself empty. This behavior is consistent with the standard equivalent\n  // `std::move_only_function`. In the following example, `a()` will actually\n  // invoke `f()`, leading to an `std::bad_function_call` exception:\n  //   std::function<void()> f;  // empty\n  //   absl::AnyInvocable<void()> a = f;  // not empty\n  //\n  // Invoking an empty `AnyInvocable` results in undefined behavior.\n  explicit operator bool() const noexcept { return this->HasValue(); }\n\n  // Invokes the target object of `*this`. `*this` must not be empty.\n  //\n  // Note: The signature of this function call operator is the same as the\n  //       template parameter `Sig`.\n  using Impl::operator();\n\n  // Equality operators\n\n  // Returns `true` if `f` is empty.\n  friend bool operator==(const AnyInvocable& f, std::nullptr_t) noexcept {\n    return !f.HasValue();\n  }\n\n  // Returns `true` if `f` is empty.\n  friend bool operator==(std::nullptr_t, const AnyInvocable& f) noexcept {\n    return !f.HasValue();\n  }\n\n  // Returns `false` if `f` is empty.\n  friend bool operator!=(const AnyInvocable& f, std::nullptr_t) noexcept {\n    return f.HasValue();\n  }\n\n  // Returns `false` if `f` is empty.\n  friend bool operator!=(std::nullptr_t, const AnyInvocable& f) noexcept {\n    return f.HasValue();\n  }\n\n  // swap()\n  //\n  // Exchanges the targets of `f1` and `f2`.\n  friend void swap(AnyInvocable& f1, AnyInvocable& f2) noexcept { f1.swap(f2); }\n\n private:\n  // Friending other instantiations is necessary for conversions.\n  template <bool /*SigIsNoexcept*/, class /*ReturnType*/, class... /*P*/>\n  friend class internal_any_invocable::CoreImpl;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_ANY_INVOCABLE_H_\n"
  },
  {
    "path": "absl/functional/any_invocable_test.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/functional/any_invocable.h\"\n\n#include <cstddef>\n#include <cstdlib>\n#include <functional>\n#include <initializer_list>\n#include <iterator>\n#include <memory>\n#include <numeric>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\nstatic_assert(absl::internal_any_invocable::kStorageSize >= sizeof(void*),\n              \"These tests assume that the small object storage is at least \"\n              \"the size of a pointer.\");\n\nnamespace {\n\n// A dummy type we use when passing qualifiers to metafunctions\nstruct _ {};\n\ntemplate <class T>\nstruct Wrapper {\n  template <class U,\n            class = absl::enable_if_t<std::is_convertible<U, T>::value>>\n  Wrapper(U&&);  // NOLINT\n};\n\n// This will cause a recursive trait instantiation if the SFINAE checks are\n// not ordered correctly for constructibility.\nstatic_assert(std::is_constructible<Wrapper<absl::AnyInvocable<void()>>,\n                                    Wrapper<absl::AnyInvocable<void()>>>::value,\n              \"\");\n\n// A metafunction that takes the cv and l-value reference qualifiers that were\n// associated with a function type (here passed via qualifiers of an object\n// type), and .\ntemplate <class Qualifiers, class This>\nstruct QualifiersForThisImpl {\n  static_assert(std::is_object<This>::value, \"\");\n  using type =\n      absl::conditional_t<std::is_const<Qualifiers>::value, const This, This>&;\n};\n\ntemplate <class Qualifiers, class This>\nstruct QualifiersForThisImpl<Qualifiers&, This>\n    : QualifiersForThisImpl<Qualifiers, This> {};\n\ntemplate <class Qualifiers, class This>\nstruct QualifiersForThisImpl<Qualifiers&&, This> {\n  static_assert(std::is_object<This>::value, \"\");\n  using type =\n      absl::conditional_t<std::is_const<Qualifiers>::value, const This, This>&&;\n};\n\ntemplate <class Qualifiers, class This>\nusing QualifiersForThis =\n    typename QualifiersForThisImpl<Qualifiers, This>::type;\n\n// A metafunction that takes the cv and l-value reference qualifier of T and\n// applies them to U's function type qualifiers.\ntemplate <class T, class Fun>\nstruct GiveQualifiersToFunImpl;\n\ntemplate <class T, class R, class... P>\nstruct GiveQualifiersToFunImpl<T, R(P...)> {\n  using type =\n      absl::conditional_t<std::is_const<T>::value, R(P...) const, R(P...)>;\n};\n\ntemplate <class T, class R, class... P>\nstruct GiveQualifiersToFunImpl<T&, R(P...)> {\n  using type =\n      absl::conditional_t<std::is_const<T>::value, R(P...) const&, R(P...)&>;\n};\n\ntemplate <class T, class R, class... P>\nstruct GiveQualifiersToFunImpl<T&&, R(P...)> {\n  using type =\n      absl::conditional_t<std::is_const<T>::value, R(P...) const&&, R(P...) &&>;\n};\n\ntemplate <class T, class R, class... P>\nstruct GiveQualifiersToFunImpl<T, R(P...) noexcept> {\n  using type = absl::conditional_t<std::is_const<T>::value,\n                                   R(P...) const noexcept, R(P...) noexcept>;\n};\n\ntemplate <class T, class R, class... P>\nstruct GiveQualifiersToFunImpl<T&, R(P...) noexcept> {\n  using type =\n      absl::conditional_t<std::is_const<T>::value, R(P...) const & noexcept,\n                          R(P...) & noexcept>;\n};\n\ntemplate <class T, class R, class... P>\nstruct GiveQualifiersToFunImpl<T&&, R(P...) noexcept> {\n  using type =\n      absl::conditional_t<std::is_const<T>::value, R(P...) const && noexcept,\n                          R(P...) && noexcept>;\n};\n\ntemplate <class T, class Fun>\nusing GiveQualifiersToFun = typename GiveQualifiersToFunImpl<T, Fun>::type;\n\n// This is used in template parameters to decide whether or not to use a type\n// that fits in the small object optimization storage.\nenum class ObjSize { small, large };\n\n// A base type that is used with classes as a means to insert an\n// appropriately-sized dummy datamember when Size is ObjSize::large so that the\n// user's class type is guaranteed to not fit in small object storage.\ntemplate <ObjSize Size>\nstruct TypeErasedPadding;\n\ntemplate <>\nstruct TypeErasedPadding<ObjSize::small> {};\n\ntemplate <>\nstruct TypeErasedPadding<ObjSize::large> {\n  char dummy_data[absl::internal_any_invocable::kStorageSize + 1] = {};\n};\n\nstruct Int {\n  Int(int v) noexcept : value(v) {}  // NOLINT\n#ifndef _MSC_VER\n  Int(Int&&) noexcept {\n    // NOTE: Prior to C++17, this not being called requires optimizations to\n    //       take place when performing the top-level invocation. In practice,\n    //       most supported compilers perform this optimization prior to C++17.\n    std::abort();\n  }\n#else\n  Int(Int&& v) noexcept = default;\n#endif\n  operator int() && noexcept { return value; }  // NOLINT\n\n  int MemberFunctionAdd(int const& b, int c) noexcept {  // NOLINT\n    return value + b + c;\n  }\n\n  int value;\n};\n\nenum class Movable { no, yes, nothrow, trivial };\n\nenum class NothrowCall { no, yes };\n\nenum class Destructible { nothrow, trivial };\n\nenum class ObjAlign : std::size_t {\n  normal = absl::internal_any_invocable::kAlignment,\n  large = absl::internal_any_invocable::kAlignment * 2,\n};\n\n// A function-object template that has knobs for each property that can affect\n// how the object is stored in AnyInvocable.\ntemplate <Movable Movability, Destructible Destructibility, class Qual,\n          NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>\nstruct add;\n\n#define ABSL_INTERNALS_ADD(qual)                                              \\\n  template <NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>  \\\n  struct alignas(static_cast<std::size_t>(Alignment))                         \\\n      add<Movable::trivial, Destructible::trivial, _ qual, CallExceptionSpec, \\\n          Size, Alignment> : TypeErasedPadding<Size> {                        \\\n    explicit add(int state_init) : state(state_init) {}                       \\\n    explicit add(std::initializer_list<int> state_init, int tail)             \\\n        : state(std::accumulate(std::begin(state_init), std::end(state_init), \\\n                                0) +                                          \\\n                tail) {}                                                      \\\n    add(add&& other) = default; /*NOLINT*/                                    \\\n    Int operator()(int a, int b, int c) qual                                  \\\n        noexcept(CallExceptionSpec == NothrowCall::yes) {                     \\\n      return state + a + b + c;                                               \\\n    }                                                                         \\\n    int state;                                                                \\\n  };                                                                          \\\n                                                                              \\\n  template <NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>  \\\n  struct alignas(static_cast<std::size_t>(Alignment))                         \\\n      add<Movable::trivial, Destructible::nothrow, _ qual, CallExceptionSpec, \\\n          Size, Alignment> : TypeErasedPadding<Size> {                        \\\n    explicit add(int state_init) : state(state_init) {}                       \\\n    explicit add(std::initializer_list<int> state_init, int tail)             \\\n        : state(std::accumulate(std::begin(state_init), std::end(state_init), \\\n                                0) +                                          \\\n                tail) {}                                                      \\\n    ~add() noexcept {}                                                        \\\n    add(add&& other) = default; /*NOLINT*/                                    \\\n    Int operator()(int a, int b, int c) qual                                  \\\n        noexcept(CallExceptionSpec == NothrowCall::yes) {                     \\\n      return state + a + b + c;                                               \\\n    }                                                                         \\\n    int state;                                                                \\\n  }\n\n// Explicitly specify an empty argument.\n// MSVC (at least up to _MSC_VER 1931, if not beyond) warns that\n// ABSL_INTERNALS_ADD() is an undefined zero-arg overload.\n#define ABSL_INTERNALS_NOARG\nABSL_INTERNALS_ADD(ABSL_INTERNALS_NOARG);\n#undef ABSL_INTERNALS_NOARG\n\nABSL_INTERNALS_ADD(const);\nABSL_INTERNALS_ADD(&);\nABSL_INTERNALS_ADD(const&);\nABSL_INTERNALS_ADD(&&);       // NOLINT\nABSL_INTERNALS_ADD(const&&);  // NOLINT\n\n#undef ABSL_INTERNALS_ADD\n\ntemplate <Destructible Destructibility, class Qual,\n          NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>\nstruct add<Movable::no, Destructibility, Qual, CallExceptionSpec, Size,\n           Alignment> : private add<Movable::trivial, Destructibility, Qual,\n                                    CallExceptionSpec, Size, Alignment> {\n  using Base = add<Movable::trivial, Destructibility, Qual, CallExceptionSpec,\n                   Size, Alignment>;\n\n  explicit add(int state_init) : Base(state_init) {}\n\n  explicit add(std::initializer_list<int> state_init, int tail)\n      : Base(state_init, tail) {}\n\n  add(add&&) = delete;\n\n  using Base::operator();\n  using Base::state;\n};\n\ntemplate <Destructible Destructibility, class Qual,\n          NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>\nstruct add<Movable::yes, Destructibility, Qual, CallExceptionSpec, Size,\n           Alignment> : private add<Movable::trivial, Destructibility, Qual,\n                                    CallExceptionSpec, Size, Alignment> {\n  using Base = add<Movable::trivial, Destructibility, Qual, CallExceptionSpec,\n                   Size, Alignment>;\n\n  explicit add(int state_init) : Base(state_init) {}\n\n  explicit add(std::initializer_list<int> state_init, int tail)\n      : Base(state_init, tail) {}\n\n  add(add&& other) noexcept(false) : Base(other.state) {}  // NOLINT\n\n  using Base::operator();\n  using Base::state;\n};\n\ntemplate <Destructible Destructibility, class Qual,\n          NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>\nstruct add<Movable::nothrow, Destructibility, Qual, CallExceptionSpec, Size,\n           Alignment> : private add<Movable::trivial, Destructibility, Qual,\n                                    CallExceptionSpec, Size, Alignment> {\n  using Base = add<Movable::trivial, Destructibility, Qual, CallExceptionSpec,\n                   Size, Alignment>;\n\n  explicit add(int state_init) : Base(state_init) {}\n\n  explicit add(std::initializer_list<int> state_init, int tail)\n      : Base(state_init, tail) {}\n\n  add(add&& other) noexcept : Base(other.state) {}\n\n  using Base::operator();\n  using Base::state;\n};\n\n// Actual non-member functions rather than function objects\nInt add_function(Int&& a, int b, int c) noexcept { return a.value + b + c; }\n\nInt mult_function(Int&& a, int b, int c) noexcept { return a.value * b * c; }\n\nInt square_function(Int const&& a) noexcept { return a.value * a.value; }\n\ntemplate <class Sig>\nusing AnyInvocable = absl::AnyInvocable<Sig>;\n\n// Instantiations of this template contains all of the compile-time parameters\n// for a given instantiation of the AnyInvocable test suite.\ntemplate <Movable Movability, Destructible Destructibility, class Qual,\n          NothrowCall CallExceptionSpec, ObjSize Size, ObjAlign Alignment>\nstruct TestParams {\n  static constexpr Movable kMovability = Movability;\n  static constexpr Destructible kDestructibility = Destructibility;\n  using Qualifiers = Qual;\n  static constexpr NothrowCall kCallExceptionSpec = CallExceptionSpec;\n  static constexpr bool kIsNoexcept = kCallExceptionSpec == NothrowCall::yes;\n  static constexpr bool kIsRvalueQualified =\n      std::is_rvalue_reference<Qual>::value;\n  static constexpr ObjSize kSize = Size;\n  static constexpr ObjAlign kAlignment = Alignment;\n\n  // These types are used when testing with member object pointer Invocables\n  using UnqualifiedUnaryFunType = int(Int const&&) noexcept(CallExceptionSpec ==\n                                                            NothrowCall::yes);\n  using UnaryFunType = GiveQualifiersToFun<Qualifiers, UnqualifiedUnaryFunType>;\n  using MemObjPtrType = int(Int::*);\n  using UnaryAnyInvType = AnyInvocable<UnaryFunType>;\n  using UnaryThisParamType = QualifiersForThis<Qualifiers, UnaryAnyInvType>;\n\n  template <class T>\n  static UnaryThisParamType ToUnaryThisParam(T&& fun) {\n    return static_cast<UnaryThisParamType>(fun);\n  }\n\n  // This function type intentionally uses 3 \"kinds\" of parameter types.\n  //     - A user-defined type\n  //     - A reference type\n  //     - A scalar type\n  //\n  // These were chosen because internal forwarding takes place on parameters\n  // differently depending based on type properties (scalars are forwarded by\n  // value).\n  using ResultType = Int;\n  using AnyInvocableFunTypeNotNoexcept = Int(Int, const int&, int);\n  using UnqualifiedFunType =\n      typename std::conditional<kIsNoexcept, Int(Int, const int&, int) noexcept,\n                                Int(Int, const int&, int)>::type;\n  using FunType = GiveQualifiersToFun<Qualifiers, UnqualifiedFunType>;\n  using MemFunPtrType =\n      typename std::conditional<kIsNoexcept,\n                                Int (Int::*)(const int&, int) noexcept,\n                                Int (Int::*)(const int&, int)>::type;\n  using AnyInvType = AnyInvocable<FunType>;\n  using AddType = add<kMovability, kDestructibility, Qualifiers,\n                      kCallExceptionSpec, kSize, kAlignment>;\n  using ThisParamType = QualifiersForThis<Qualifiers, AnyInvType>;\n\n  template <class T>\n  static ThisParamType ToThisParam(T&& fun) {\n    return static_cast<ThisParamType>(fun);\n  }\n\n  // These typedefs are used when testing void return type covariance.\n  using UnqualifiedVoidFunType =\n      typename std::conditional<kIsNoexcept,\n                                void(Int, const int&, int) noexcept,\n                                void(Int, const int&, int)>::type;\n  using VoidFunType = GiveQualifiersToFun<Qualifiers, UnqualifiedVoidFunType>;\n  using VoidAnyInvType = AnyInvocable<VoidFunType>;\n  using VoidThisParamType = QualifiersForThis<Qualifiers, VoidAnyInvType>;\n\n  template <class T>\n  static VoidThisParamType ToVoidThisParam(T&& fun) {\n    return static_cast<VoidThisParamType>(fun);\n  }\n\n  using CompatibleAnyInvocableFunType =\n      absl::conditional_t<std::is_rvalue_reference<Qual>::value,\n                          GiveQualifiersToFun<const _&&, UnqualifiedFunType>,\n                          GiveQualifiersToFun<const _&, UnqualifiedFunType>>;\n\n  using CompatibleAnyInvType = AnyInvocable<CompatibleAnyInvocableFunType>;\n\n  using IncompatibleInvocable =\n      absl::conditional_t<std::is_rvalue_reference<Qual>::value,\n                          GiveQualifiersToFun<_&, UnqualifiedFunType>(_::*),\n                          GiveQualifiersToFun<_&&, UnqualifiedFunType>(_::*)>;\n};\n\n// Given a member-pointer type, this metafunction yields the target type of the\n// pointer, not including the class-type. It is used to verify that the function\n// call operator of AnyInvocable has the proper signature, corresponding to the\n// function type that the user provided.\ntemplate <class MemberPtrType>\nstruct MemberTypeOfImpl;\n\ntemplate <class Class, class T>\nstruct MemberTypeOfImpl<T(Class::*)> {\n  using type = T;\n};\n\ntemplate <class MemberPtrType>\nusing MemberTypeOf = typename MemberTypeOfImpl<MemberPtrType>::type;\n\ntemplate <class T, class = void>\nstruct IsMemberSwappableImpl : std::false_type {\n  static constexpr bool kIsNothrow = false;\n};\n\ntemplate <class T>\nstruct IsMemberSwappableImpl<\n    T, absl::void_t<decltype(std::declval<T&>().swap(std::declval<T&>()))>>\n    : std::true_type {\n  static constexpr bool kIsNothrow =\n      noexcept(std::declval<T&>().swap(std::declval<T&>()));\n};\n\ntemplate <class T>\nusing IsMemberSwappable = IsMemberSwappableImpl<T>;\n\ntemplate <class T>\nusing IsNothrowMemberSwappable =\n    std::integral_constant<bool, IsMemberSwappableImpl<T>::kIsNothrow>;\n\ntemplate <class T>\nclass AnyInvTestBasic : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestBasic);\n\nTYPED_TEST_P(AnyInvTestBasic, DefaultConstruction) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n\n  EXPECT_TRUE(std::is_nothrow_default_constructible<AnyInvType>::value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionNullptr) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun = nullptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n\n  EXPECT_TRUE(\n      (std::is_nothrow_constructible<AnyInvType, std::nullptr_t>::value));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionNullFunctionPtr) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using UnqualifiedFunType = typename TypeParam::UnqualifiedFunType;\n\n  UnqualifiedFunType* const null_fun_ptr = nullptr;\n  AnyInvType fun = null_fun_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionNullMemberFunctionPtr) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using MemFunPtrType = typename TypeParam::MemFunPtrType;\n\n  const MemFunPtrType null_mem_fun_ptr = nullptr;\n  AnyInvType fun = null_mem_fun_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionNullMemberObjectPtr) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n  using MemObjPtrType = typename TypeParam::MemObjPtrType;\n\n  const MemObjPtrType null_mem_obj_ptr = nullptr;\n  UnaryAnyInvType fun = null_mem_obj_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionMemberFunctionPtr) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun = &Int::MemberFunctionAdd;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionMemberObjectPtr) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n\n  UnaryAnyInvType fun = &Int::value;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(13, TypeParam::ToUnaryThisParam(fun)(13));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionFunctionReferenceDecay) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun = add_function;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionCompatibleAnyInvocableEmpty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using CompatibleAnyInvType = typename TypeParam::CompatibleAnyInvType;\n\n  CompatibleAnyInvType other;\n  AnyInvType fun = std::move(other);\n\n  EXPECT_FALSE(static_cast<bool>(other));  // NOLINT\n  EXPECT_EQ(other, nullptr);               // NOLINT\n  EXPECT_EQ(nullptr, other);               // NOLINT\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConstructionCompatibleAnyInvocableNonempty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using CompatibleAnyInvType = typename TypeParam::CompatibleAnyInvType;\n\n  CompatibleAnyInvType other = &add_function;\n  AnyInvType fun = std::move(other);\n\n  EXPECT_FALSE(static_cast<bool>(other));  // NOLINT\n  EXPECT_EQ(other, nullptr);               // NOLINT\n  EXPECT_EQ(nullptr, other);               // NOLINT\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ConversionToBool) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  {\n    AnyInvType fun;\n\n    // This tests contextually-convertible-to-bool.\n    EXPECT_FALSE(fun ? true : false);  // NOLINT\n\n    // Make sure that the conversion is not implicit.\n    EXPECT_TRUE(\n        (std::is_nothrow_constructible<bool, const AnyInvType&>::value));\n    EXPECT_FALSE((std::is_convertible<const AnyInvType&, bool>::value));\n  }\n\n  {\n    AnyInvType fun = &add_function;\n\n    // This tests contextually-convertible-to-bool.\n    EXPECT_TRUE(fun ? true : false);  // NOLINT\n  }\n}\n\nTYPED_TEST_P(AnyInvTestBasic, Invocation) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  using FunType = typename TypeParam::FunType;\n  using AnyInvCallType = MemberTypeOf<decltype(&AnyInvType::operator())>;\n\n  // Make sure the function call operator of AnyInvocable always has the\n  // type that was specified via the template argument.\n  EXPECT_TRUE((std::is_same<AnyInvCallType, FunType>::value));\n\n  AnyInvType fun = &add_function;\n\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceConstruction) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun(absl::in_place_type<AddType>, 5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceConstructionInitializerList) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun(absl::in_place_type<AddType>, {1, 2, 3, 4}, 5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(39, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceNullFunPtrConstruction) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using UnqualifiedFunType = typename TypeParam::UnqualifiedFunType;\n\n  AnyInvType fun(absl::in_place_type<UnqualifiedFunType*>, nullptr);\n\n  // In-place construction does not lead to empty.\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceNullFunPtrConstructionValueInit) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using UnqualifiedFunType = typename TypeParam::UnqualifiedFunType;\n\n  AnyInvType fun(absl::in_place_type<UnqualifiedFunType*>);\n\n  // In-place construction does not lead to empty.\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceNullMemFunPtrConstruction) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using MemFunPtrType = typename TypeParam::MemFunPtrType;\n\n  AnyInvType fun(absl::in_place_type<MemFunPtrType>, nullptr);\n\n  // In-place construction does not lead to empty.\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceNullMemFunPtrConstructionValueInit) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using MemFunPtrType = typename TypeParam::MemFunPtrType;\n\n  AnyInvType fun(absl::in_place_type<MemFunPtrType>);\n\n  // In-place construction does not lead to empty.\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceNullMemObjPtrConstruction) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n  using MemObjPtrType = typename TypeParam::MemObjPtrType;\n\n  UnaryAnyInvType fun(absl::in_place_type<MemObjPtrType>, nullptr);\n\n  // In-place construction does not lead to empty.\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceNullMemObjPtrConstructionValueInit) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n  using MemObjPtrType = typename TypeParam::MemObjPtrType;\n\n  UnaryAnyInvType fun(absl::in_place_type<MemObjPtrType>);\n\n  // In-place construction does not lead to empty.\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, InPlaceVoidCovarianceConstruction) {\n  using VoidAnyInvType = typename TypeParam::VoidAnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  VoidAnyInvType fun(absl::in_place_type<AddType>, 5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestBasic, MoveConstructionFromEmpty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  absl_nullable AnyInvType source_fun;\n  absl_nullable AnyInvType fun(std::move(source_fun));\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n\n  EXPECT_TRUE(std::is_nothrow_move_constructible<AnyInvType>::value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, MoveConstructionFromNonEmpty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType source_fun(absl::in_place_type<AddType>, 5);\n  AnyInvType fun(std::move(source_fun));\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n\n  EXPECT_TRUE(std::is_nothrow_move_constructible<AnyInvType>::value);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ComparisonWithNullptrEmpty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun;\n\n  EXPECT_TRUE(fun == nullptr);\n  EXPECT_TRUE(nullptr == fun);\n\n  EXPECT_FALSE(fun != nullptr);\n  EXPECT_FALSE(nullptr != fun);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ComparisonWithNullptrNonempty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun(absl::in_place_type<AddType>, 5);\n\n  EXPECT_FALSE(fun == nullptr);\n  EXPECT_FALSE(nullptr == fun);\n\n  EXPECT_TRUE(fun != nullptr);\n  EXPECT_TRUE(nullptr != fun);\n}\n\nTYPED_TEST_P(AnyInvTestBasic, ResultType) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using ExpectedResultType = typename TypeParam::ResultType;\n\n  EXPECT_TRUE((std::is_same<typename AnyInvType::result_type,\n                            ExpectedResultType>::value));\n}\n\ntemplate <class T>\nclass AnyInvTestCombinatoric : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestCombinatoric);\n\nTYPED_TEST_P(AnyInvTestCombinatoric, MoveAssignEmptyEmptyLhsRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType source_fun;\n  AnyInvType fun;\n\n  fun = std::move(source_fun);\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, MoveAssignEmptyLhsNonemptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType source_fun(absl::in_place_type<AddType>, 5);\n  AnyInvType fun;\n\n  fun = std::move(source_fun);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, MoveAssignNonemptyEmptyLhsRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType source_fun;\n  AnyInvType fun(absl::in_place_type<AddType>, 5);\n\n  fun = std::move(source_fun);\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, MoveAssignNonemptyLhsNonemptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType source_fun(absl::in_place_type<AddType>, 5);\n  AnyInvType fun(absl::in_place_type<AddType>, 20);\n\n  fun = std::move(source_fun);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, SelfMoveAssignEmpty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType source_fun;\n  source_fun = std::move(source_fun);\n\n  // This space intentionally left blank.\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, SelfMoveAssignNonempty) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType source_fun(absl::in_place_type<AddType>, 5);\n  source_fun = std::move(source_fun);\n\n  // This space intentionally left blank.\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullptrEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun;\n  fun = nullptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullFunctionPtrEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using UnqualifiedFunType = typename TypeParam::UnqualifiedFunType;\n\n  UnqualifiedFunType* const null_fun_ptr = nullptr;\n  AnyInvType fun;\n  fun = null_fun_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullMemberFunctionPtrEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using MemFunPtrType = typename TypeParam::MemFunPtrType;\n\n  const MemFunPtrType null_mem_fun_ptr = nullptr;\n  AnyInvType fun;\n  fun = null_mem_fun_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullMemberObjectPtrEmptyLhs) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n  using MemObjPtrType = typename TypeParam::MemObjPtrType;\n\n  const MemObjPtrType null_mem_obj_ptr = nullptr;\n  UnaryAnyInvType fun;\n  fun = null_mem_obj_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignMemberFunctionPtrEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun;\n  fun = &Int::MemberFunctionAdd;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignMemberObjectPtrEmptyLhs) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n\n  UnaryAnyInvType fun;\n  fun = &Int::value;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(13, TypeParam::ToUnaryThisParam(fun)(13));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignFunctionReferenceDecayEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun;\n  fun = add_function;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric,\n             AssignCompatibleAnyInvocableEmptyLhsEmptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using CompatibleAnyInvType = typename TypeParam::CompatibleAnyInvType;\n\n  CompatibleAnyInvType other;\n  AnyInvType fun;\n  fun = std::move(other);\n\n  EXPECT_FALSE(static_cast<bool>(other));  // NOLINT\n  EXPECT_EQ(other, nullptr);               // NOLINT\n  EXPECT_EQ(nullptr, other);               // NOLINT\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric,\n             AssignCompatibleAnyInvocableEmptyLhsNonemptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using CompatibleAnyInvType = typename TypeParam::CompatibleAnyInvType;\n\n  CompatibleAnyInvType other = &add_function;\n  AnyInvType fun;\n  fun = std::move(other);\n\n  EXPECT_FALSE(static_cast<bool>(other));  // NOLINT\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullptrNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun = &mult_function;\n  fun = nullptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullFunctionPtrNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using UnqualifiedFunType = typename TypeParam::UnqualifiedFunType;\n\n  UnqualifiedFunType* const null_fun_ptr = nullptr;\n  AnyInvType fun = &mult_function;\n  fun = null_fun_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullMemberFunctionPtrNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using MemFunPtrType = typename TypeParam::MemFunPtrType;\n\n  const MemFunPtrType null_mem_fun_ptr = nullptr;\n  AnyInvType fun = &mult_function;\n  fun = null_mem_fun_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignNullMemberObjectPtrNonemptyLhs) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n  using MemObjPtrType = typename TypeParam::MemObjPtrType;\n\n  const MemObjPtrType null_mem_obj_ptr = nullptr;\n  UnaryAnyInvType fun = &square_function;\n  fun = null_mem_obj_ptr;\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignMemberFunctionPtrNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun = &mult_function;\n  fun = &Int::MemberFunctionAdd;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignMemberObjectPtrNonemptyLhs) {\n  using UnaryAnyInvType = typename TypeParam::UnaryAnyInvType;\n\n  UnaryAnyInvType fun = &square_function;\n  fun = &Int::value;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(13, TypeParam::ToUnaryThisParam(fun)(13));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, AssignFunctionReferenceDecayNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  AnyInvType fun = &mult_function;\n  fun = add_function;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric,\n             AssignCompatibleAnyInvocableNonemptyLhsEmptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using CompatibleAnyInvType = typename TypeParam::CompatibleAnyInvType;\n\n  CompatibleAnyInvType other;\n  AnyInvType fun = &mult_function;\n  fun = std::move(other);\n\n  EXPECT_FALSE(static_cast<bool>(other));  // NOLINT\n  EXPECT_EQ(other, nullptr);               // NOLINT\n  EXPECT_EQ(nullptr, other);               // NOLINT\n\n  EXPECT_FALSE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric,\n             AssignCompatibleAnyInvocableNonemptyLhsNonemptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using CompatibleAnyInvType = typename TypeParam::CompatibleAnyInvType;\n\n  CompatibleAnyInvType other = &add_function;\n  AnyInvType fun = &mult_function;\n  fun = std::move(other);\n\n  EXPECT_FALSE(static_cast<bool>(other));  // NOLINT\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(24, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, SwapEmptyLhsEmptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  // Swap idiom\n  {\n    AnyInvType fun;\n    AnyInvType other;\n\n    using std::swap;\n    swap(fun, other);\n\n    EXPECT_FALSE(static_cast<bool>(fun));\n    EXPECT_FALSE(static_cast<bool>(other));\n\n    EXPECT_TRUE(\n        absl::type_traits_internal::IsNothrowSwappable<AnyInvType>::value);\n  }\n\n  // Member swap\n  {\n    AnyInvType fun;\n    AnyInvType other;\n\n    fun.swap(other);\n\n    EXPECT_FALSE(static_cast<bool>(fun));\n    EXPECT_FALSE(static_cast<bool>(other));\n\n    EXPECT_TRUE(IsNothrowMemberSwappable<AnyInvType>::value);\n  }\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, SwapEmptyLhsNonemptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  // Swap idiom\n  {\n    AnyInvType fun;\n    AnyInvType other(absl::in_place_type<AddType>, 5);\n\n    using std::swap;\n    swap(fun, other);\n\n    EXPECT_TRUE(static_cast<bool>(fun));\n    EXPECT_FALSE(static_cast<bool>(other));\n\n    EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n\n    EXPECT_TRUE(\n        absl::type_traits_internal::IsNothrowSwappable<AnyInvType>::value);\n  }\n\n  // Member swap\n  {\n    AnyInvType fun;\n    AnyInvType other(absl::in_place_type<AddType>, 5);\n\n    fun.swap(other);\n\n    EXPECT_TRUE(static_cast<bool>(fun));\n    EXPECT_FALSE(static_cast<bool>(other));\n\n    EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n\n    EXPECT_TRUE(IsNothrowMemberSwappable<AnyInvType>::value);\n  }\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, SwapNonemptyLhsEmptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  // Swap idiom\n  {\n    AnyInvType fun(absl::in_place_type<AddType>, 5);\n    AnyInvType other;\n\n    using std::swap;\n    swap(fun, other);\n\n    EXPECT_FALSE(static_cast<bool>(fun));\n    EXPECT_TRUE(static_cast<bool>(other));\n\n    EXPECT_EQ(29, TypeParam::ToThisParam(other)(7, 8, 9).value);\n\n    EXPECT_TRUE(\n        absl::type_traits_internal::IsNothrowSwappable<AnyInvType>::value);\n  }\n\n  // Member swap\n  {\n    AnyInvType fun(absl::in_place_type<AddType>, 5);\n    AnyInvType other;\n\n    fun.swap(other);\n\n    EXPECT_FALSE(static_cast<bool>(fun));\n    EXPECT_TRUE(static_cast<bool>(other));\n\n    EXPECT_EQ(29, TypeParam::ToThisParam(other)(7, 8, 9).value);\n\n    EXPECT_TRUE(IsNothrowMemberSwappable<AnyInvType>::value);\n  }\n}\n\nTYPED_TEST_P(AnyInvTestCombinatoric, SwapNonemptyLhsNonemptyRhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  // Swap idiom\n  {\n    AnyInvType fun(absl::in_place_type<AddType>, 5);\n    AnyInvType other(absl::in_place_type<AddType>, 6);\n\n    using std::swap;\n    swap(fun, other);\n\n    EXPECT_TRUE(static_cast<bool>(fun));\n    EXPECT_TRUE(static_cast<bool>(other));\n\n    EXPECT_EQ(30, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n    EXPECT_EQ(29, TypeParam::ToThisParam(other)(7, 8, 9).value);\n\n    EXPECT_TRUE(\n        absl::type_traits_internal::IsNothrowSwappable<AnyInvType>::value);\n  }\n\n  // Member swap\n  {\n    AnyInvType fun(absl::in_place_type<AddType>, 5);\n    AnyInvType other(absl::in_place_type<AddType>, 6);\n\n    fun.swap(other);\n\n    EXPECT_TRUE(static_cast<bool>(fun));\n    EXPECT_TRUE(static_cast<bool>(other));\n\n    EXPECT_EQ(30, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n    EXPECT_EQ(29, TypeParam::ToThisParam(other)(7, 8, 9).value);\n\n    EXPECT_TRUE(IsNothrowMemberSwappable<AnyInvType>::value);\n  }\n}\n\ntemplate <class T>\nclass AnyInvTestMovable : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestMovable);\n\nTYPED_TEST_P(AnyInvTestMovable, ConversionConstructionUserDefinedType) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun(AddType(5));\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestMovable, ConversionConstructionVoidCovariance) {\n  using VoidAnyInvType = typename TypeParam::VoidAnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  VoidAnyInvType fun(AddType(5));\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\nTYPED_TEST_P(AnyInvTestMovable, ConversionAssignUserDefinedTypeEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun;\n  fun = AddType(5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestMovable, ConversionAssignUserDefinedTypeNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun = &add_function;\n  fun = AddType(5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n}\n\nTYPED_TEST_P(AnyInvTestMovable, ConversionAssignVoidCovariance) {\n  using VoidAnyInvType = typename TypeParam::VoidAnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  VoidAnyInvType fun;\n  fun = AddType(5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n}\n\ntemplate <class T>\nclass AnyInvTestNoexceptFalse : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestNoexceptFalse);\n\nTYPED_TEST_P(AnyInvTestNoexceptFalse, ConversionConstructionConstraints) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  EXPECT_TRUE((std::is_constructible<\n               AnyInvType,\n               typename TypeParam::AnyInvocableFunTypeNotNoexcept*>::value));\n  EXPECT_FALSE((\n      std::is_constructible<AnyInvType,\n                            typename TypeParam::IncompatibleInvocable>::value));\n}\n\nTYPED_TEST_P(AnyInvTestNoexceptFalse, ConversionAssignConstraints) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  EXPECT_TRUE((std::is_assignable<\n               AnyInvType&,\n               typename TypeParam::AnyInvocableFunTypeNotNoexcept*>::value));\n  EXPECT_FALSE(\n      (std::is_assignable<AnyInvType&,\n                          typename TypeParam::IncompatibleInvocable>::value));\n}\n\ntemplate <class T>\nclass AnyInvTestNoexceptTrue : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestNoexceptTrue);\n\nTYPED_TEST_P(AnyInvTestNoexceptTrue, ConversionConstructionConstraints) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  EXPECT_FALSE((std::is_constructible<\n                AnyInvType,\n                typename TypeParam::AnyInvocableFunTypeNotNoexcept*>::value));\n  EXPECT_FALSE((\n      std::is_constructible<AnyInvType,\n                            typename TypeParam::IncompatibleInvocable>::value));\n}\n\nTYPED_TEST_P(AnyInvTestNoexceptTrue, ConversionAssignConstraints) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  EXPECT_FALSE((std::is_assignable<\n                AnyInvType&,\n                typename TypeParam::AnyInvocableFunTypeNotNoexcept*>::value));\n  EXPECT_FALSE(\n      (std::is_assignable<AnyInvType&,\n                          typename TypeParam::IncompatibleInvocable>::value));\n}\n\ntemplate <class T>\nclass AnyInvTestNonRvalue : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestNonRvalue);\n\nTYPED_TEST_P(AnyInvTestNonRvalue, ConversionConstructionReferenceWrapper) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AddType add(4);\n  AnyInvType fun = std::ref(add);\n  add.state = 5;\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(38, TypeParam::ToThisParam(fun)(10, 11, 12).value);\n}\n\nTYPED_TEST_P(AnyInvTestNonRvalue, NonMoveableResultType) {\n  // Define a result type that cannot be copy- or move-constructed.\n  struct Result {\n    int x;\n\n    explicit Result(const int x_in) : x(x_in) {}\n    Result(Result&&) = delete;\n  };\n\n  static_assert(!std::is_move_constructible<Result>::value, \"\");\n  static_assert(!std::is_copy_constructible<Result>::value, \"\");\n\n  // Assumption check: it should nevertheless be possible to use functors that\n  // return a Result struct according to the language rules.\n  const auto return_17 = []() noexcept { return Result(17); };\n  EXPECT_EQ(17, return_17().x);\n\n  // Just like plain functors, it should work fine to use an AnyInvocable that\n  // returns the non-moveable type.\n  using UnqualifiedFun =\n      absl::conditional_t<TypeParam::kIsNoexcept, Result() noexcept, Result()>;\n\n  using Fun =\n      GiveQualifiersToFun<typename TypeParam::Qualifiers, UnqualifiedFun>;\n\n  AnyInvocable<Fun> any_inv(return_17);\n  EXPECT_EQ(17, any_inv().x);\n}\n\nTYPED_TEST_P(AnyInvTestNonRvalue, ConversionAssignReferenceWrapperEmptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AddType add(4);\n  AnyInvType fun;\n  fun = std::ref(add);\n  add.state = 5;\n  EXPECT_TRUE(\n      (std::is_nothrow_assignable<AnyInvType&,\n                                  std::reference_wrapper<AddType>>::value));\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(38, TypeParam::ToThisParam(fun)(10, 11, 12).value);\n}\n\nTYPED_TEST_P(AnyInvTestNonRvalue, ConversionAssignReferenceWrapperNonemptyLhs) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AddType add(4);\n  AnyInvType fun = &mult_function;\n  fun = std::ref(add);\n  add.state = 5;\n  EXPECT_TRUE(\n      (std::is_nothrow_assignable<AnyInvType&,\n                                  std::reference_wrapper<AddType>>::value));\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(29, TypeParam::ToThisParam(fun)(7, 8, 9).value);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  EXPECT_EQ(38, TypeParam::ToThisParam(fun)(10, 11, 12).value);\n}\n\ntemplate <class T>\nclass AnyInvTestRvalue : public ::testing::Test {};\n\nTYPED_TEST_SUITE_P(AnyInvTestRvalue);\n\nTYPED_TEST_P(AnyInvTestRvalue, ConversionConstructionReferenceWrapper) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  EXPECT_FALSE((\n      std::is_convertible<std::reference_wrapper<AddType>, AnyInvType>::value));\n}\n\nTYPED_TEST_P(AnyInvTestRvalue, NonMoveableResultType) {\n  // Define a result type that cannot be copy- or move-constructed.\n  struct Result {\n    int x;\n\n    explicit Result(const int x_in) : x(x_in) {}\n    Result(Result&&) = delete;\n  };\n\n  static_assert(!std::is_move_constructible<Result>::value, \"\");\n  static_assert(!std::is_copy_constructible<Result>::value, \"\");\n\n  // Assumption check: it should nevertheless be possible to use functors that\n  // return a Result struct according to the language rules.\n  const auto return_17 = []() noexcept { return Result(17); };\n  EXPECT_EQ(17, return_17().x);\n\n  // Just like plain functors, it should work fine to use an AnyInvocable that\n  // returns the non-moveable type.\n  using UnqualifiedFun =\n      absl::conditional_t<TypeParam::kIsNoexcept, Result() noexcept, Result()>;\n\n  using Fun =\n      GiveQualifiersToFun<typename TypeParam::Qualifiers, UnqualifiedFun>;\n\n  EXPECT_EQ(17, AnyInvocable<Fun>(return_17)().x);\n}\n\nTYPED_TEST_P(AnyInvTestRvalue, ConversionAssignReferenceWrapper) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  EXPECT_FALSE((\n      std::is_assignable<AnyInvType&, std::reference_wrapper<AddType>>::value));\n}\n\nTYPED_TEST_P(AnyInvTestRvalue, NonConstCrashesOnSecondCall) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n  using AddType = typename TypeParam::AddType;\n\n  AnyInvType fun(absl::in_place_type<AddType>, 5);\n\n  EXPECT_TRUE(static_cast<bool>(fun));\n  std::move(fun)(7, 8, 9);\n\n  // Ensure we're still valid\n  EXPECT_TRUE(static_cast<bool>(fun));  // NOLINT(bugprone-use-after-move)\n\n#if !defined(NDEBUG)\n  EXPECT_DEATH_IF_SUPPORTED(std::move(fun)(7, 8, 9), \"\");\n#endif\n}\n\n// Ensure that any qualifiers (in particular &&-qualifiers) do not affect\n// when the destructor is actually run.\nTYPED_TEST_P(AnyInvTestRvalue, QualifierIndependentObjectLifetime) {\n  using AnyInvType = typename TypeParam::AnyInvType;\n\n  auto refs = std::make_shared<std::nullptr_t>();\n  {\n    AnyInvType fun([refs](auto&&...) noexcept { return 0; });\n    EXPECT_GT(refs.use_count(), 1);\n\n    std::move(fun)(7, 8, 9);\n\n    // Ensure destructor hasn't run even if rref-qualified\n    EXPECT_GT(refs.use_count(), 1);\n  }\n  EXPECT_EQ(refs.use_count(), 1);\n}\n\n// NOTE: This test suite originally attempted to enumerate all possible\n// combinations of type properties but the build-time started getting too large.\n// Instead, it is now assumed that certain parameters are orthogonal and so\n// some combinations are elided.\n\n// A metafunction to form a TypeList of all cv and non-rvalue ref combinations,\n// coupled with all of the other explicitly specified parameters.\ntemplate <Movable Mov, Destructible Dest, NothrowCall CallExceptionSpec,\n          ObjSize Size, ObjAlign Align>\nusing NonRvalueQualifiedTestParams = ::testing::Types<               //\n    TestParams<Mov, Dest, _, CallExceptionSpec, Size, Align>,        //\n    TestParams<Mov, Dest, const _, CallExceptionSpec, Size, Align>,  //\n    TestParams<Mov, Dest, _&, CallExceptionSpec, Size, Align>,       //\n    TestParams<Mov, Dest, const _&, CallExceptionSpec, Size, Align>>;\n\n// A metafunction to form a TypeList of const and non-const rvalue ref\n// qualifiers, coupled with all of the other explicitly specified parameters.\ntemplate <Movable Mov, Destructible Dest, NothrowCall CallExceptionSpec,\n          ObjSize Size, ObjAlign Align>\nusing RvalueQualifiedTestParams = ::testing::Types<\n    TestParams<Mov, Dest, _&&, CallExceptionSpec, Size, Align>,       //\n    TestParams<Mov, Dest, const _&&, CallExceptionSpec, Size, Align>  //\n    >;\n\n// All qualifier combinations and a noexcept function type\nusing TestParameterListNonRvalueQualifiersNothrowCall =\n    NonRvalueQualifiedTestParams<Movable::trivial, Destructible::trivial,\n                                 NothrowCall::yes, ObjSize::small,\n                                 ObjAlign::normal>;\nusing TestParameterListRvalueQualifiersNothrowCall =\n    RvalueQualifiedTestParams<Movable::trivial, Destructible::trivial,\n                              NothrowCall::yes, ObjSize::small,\n                              ObjAlign::normal>;\n\n// All qualifier combinations and a non-noexcept function type\nusing TestParameterListNonRvalueQualifiersCallMayThrow =\n    NonRvalueQualifiedTestParams<Movable::trivial, Destructible::trivial,\n                                 NothrowCall::no, ObjSize::small,\n                                 ObjAlign::normal>;\nusing TestParameterListRvalueQualifiersCallMayThrow =\n    RvalueQualifiedTestParams<Movable::trivial, Destructible::trivial,\n                              NothrowCall::no, ObjSize::small,\n                              ObjAlign::normal>;\n\n// Lists of various cases that should lead to remote storage\nusing TestParameterListRemoteMovable = ::testing::Types<\n    // \"Normal\" aligned types that are large and have trivial destructors\n    TestParams<Movable::trivial, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>,  //\n    TestParams<Movable::nothrow, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>,  //\n    TestParams<Movable::yes, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n    TestParams<Movable::yes, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>,  //\n\n    // Same as above but with non-trivial destructors\n    TestParams<Movable::trivial, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>,  //\n    TestParams<Movable::nothrow, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>,  //\n    TestParams<Movable::yes, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n    TestParams<Movable::yes, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>  //\n\n    // Types that must use remote storage because of a large alignment.\n    ,\n    TestParams<Movable::trivial, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::large>,  //\n    TestParams<Movable::nothrow, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::large>,  //\n    TestParams<Movable::trivial, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::large>,  //\n    TestParams<Movable::nothrow, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::large>  //\n    >;\nusing TestParameterListRemoteNonMovable = ::testing::Types<\n    // \"Normal\" aligned types that are large and have trivial destructors\n    TestParams<Movable::no, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n    TestParams<Movable::no, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>,  //\n    // Same as above but with non-trivial destructors\n    TestParams<Movable::no, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n    TestParams<Movable::no, Destructible::nothrow, _, NothrowCall::no,\n               ObjSize::large, ObjAlign::normal>  //\n    >;\n\n// Parameters that lead to local storage\nusing TestParameterListLocal = ::testing::Types<\n    // Types that meet the requirements and have trivial destructors\n    TestParams<Movable::trivial, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n    TestParams<Movable::nothrow, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n\n    // Same as above but with non-trivial destructors\n    TestParams<Movable::trivial, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>,  //\n    TestParams<Movable::nothrow, Destructible::trivial, _, NothrowCall::no,\n               ObjSize::small, ObjAlign::normal>  //\n    >;\n\n// All of the tests that are run for every possible combination of types.\nREGISTER_TYPED_TEST_SUITE_P(\n    AnyInvTestBasic, DefaultConstruction, ConstructionNullptr,\n    ConstructionNullFunctionPtr, ConstructionNullMemberFunctionPtr,\n    ConstructionNullMemberObjectPtr, ConstructionMemberFunctionPtr,\n    ConstructionMemberObjectPtr, ConstructionFunctionReferenceDecay,\n    ConstructionCompatibleAnyInvocableEmpty,\n    ConstructionCompatibleAnyInvocableNonempty, InPlaceConstruction,\n    ConversionToBool, Invocation, InPlaceConstructionInitializerList,\n    InPlaceNullFunPtrConstruction, InPlaceNullFunPtrConstructionValueInit,\n    InPlaceNullMemFunPtrConstruction, InPlaceNullMemFunPtrConstructionValueInit,\n    InPlaceNullMemObjPtrConstruction, InPlaceNullMemObjPtrConstructionValueInit,\n    InPlaceVoidCovarianceConstruction, MoveConstructionFromEmpty,\n    MoveConstructionFromNonEmpty, ComparisonWithNullptrEmpty,\n    ComparisonWithNullptrNonempty, ResultType);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(\n    NonRvalueCallMayThrow, AnyInvTestBasic,\n    TestParameterListNonRvalueQualifiersCallMayThrow);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestBasic,\n                               TestParameterListRvalueQualifiersCallMayThrow);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestBasic,\n                               TestParameterListRemoteMovable);\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestBasic,\n                               TestParameterListRemoteNonMovable);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestBasic, TestParameterListLocal);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestBasic,\n                               TestParameterListNonRvalueQualifiersNothrowCall);\nINSTANTIATE_TYPED_TEST_SUITE_P(CallNothrowRvalue, AnyInvTestBasic,\n                               TestParameterListRvalueQualifiersNothrowCall);\n\n// Tests for functions that take two operands.\nREGISTER_TYPED_TEST_SUITE_P(\n    AnyInvTestCombinatoric, MoveAssignEmptyEmptyLhsRhs,\n    MoveAssignEmptyLhsNonemptyRhs, MoveAssignNonemptyEmptyLhsRhs,\n    MoveAssignNonemptyLhsNonemptyRhs, SelfMoveAssignEmpty,\n    SelfMoveAssignNonempty, AssignNullptrEmptyLhs,\n    AssignNullFunctionPtrEmptyLhs, AssignNullMemberFunctionPtrEmptyLhs,\n    AssignNullMemberObjectPtrEmptyLhs, AssignMemberFunctionPtrEmptyLhs,\n    AssignMemberObjectPtrEmptyLhs, AssignFunctionReferenceDecayEmptyLhs,\n    AssignCompatibleAnyInvocableEmptyLhsEmptyRhs,\n    AssignCompatibleAnyInvocableEmptyLhsNonemptyRhs, AssignNullptrNonemptyLhs,\n    AssignNullFunctionPtrNonemptyLhs, AssignNullMemberFunctionPtrNonemptyLhs,\n    AssignNullMemberObjectPtrNonemptyLhs, AssignMemberFunctionPtrNonemptyLhs,\n    AssignMemberObjectPtrNonemptyLhs, AssignFunctionReferenceDecayNonemptyLhs,\n    AssignCompatibleAnyInvocableNonemptyLhsEmptyRhs,\n    AssignCompatibleAnyInvocableNonemptyLhsNonemptyRhs, SwapEmptyLhsEmptyRhs,\n    SwapEmptyLhsNonemptyRhs, SwapNonemptyLhsEmptyRhs,\n    SwapNonemptyLhsNonemptyRhs);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(\n    NonRvalueCallMayThrow, AnyInvTestCombinatoric,\n    TestParameterListNonRvalueQualifiersCallMayThrow);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestCombinatoric,\n                               TestParameterListRvalueQualifiersCallMayThrow);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestCombinatoric,\n                               TestParameterListRemoteMovable);\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestCombinatoric,\n                               TestParameterListRemoteNonMovable);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestCombinatoric,\n                               TestParameterListLocal);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestCombinatoric,\n                               TestParameterListNonRvalueQualifiersNothrowCall);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestCombinatoric,\n                               TestParameterListRvalueQualifiersNothrowCall);\n\nREGISTER_TYPED_TEST_SUITE_P(AnyInvTestMovable,\n                            ConversionConstructionUserDefinedType,\n                            ConversionConstructionVoidCovariance,\n                            ConversionAssignUserDefinedTypeEmptyLhs,\n                            ConversionAssignUserDefinedTypeNonemptyLhs,\n                            ConversionAssignVoidCovariance);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(\n    NonRvalueCallMayThrow, AnyInvTestMovable,\n    TestParameterListNonRvalueQualifiersCallMayThrow);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestMovable,\n                               TestParameterListRvalueQualifiersCallMayThrow);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestMovable,\n                               TestParameterListRemoteMovable);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestMovable,\n                               TestParameterListLocal);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestMovable,\n                               TestParameterListNonRvalueQualifiersNothrowCall);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestMovable,\n                               TestParameterListRvalueQualifiersNothrowCall);\n\nREGISTER_TYPED_TEST_SUITE_P(AnyInvTestNoexceptFalse,\n                            ConversionConstructionConstraints,\n                            ConversionAssignConstraints);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(\n    NonRvalueCallMayThrow, AnyInvTestNoexceptFalse,\n    TestParameterListNonRvalueQualifiersCallMayThrow);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestNoexceptFalse,\n                               TestParameterListRvalueQualifiersCallMayThrow);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestNoexceptFalse,\n                               TestParameterListRemoteMovable);\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestNoexceptFalse,\n                               TestParameterListRemoteNonMovable);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestNoexceptFalse,\n                               TestParameterListLocal);\n\nREGISTER_TYPED_TEST_SUITE_P(AnyInvTestNoexceptTrue,\n                            ConversionConstructionConstraints,\n                            ConversionAssignConstraints);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestNoexceptTrue,\n                               TestParameterListNonRvalueQualifiersNothrowCall);\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallNothrow, AnyInvTestNoexceptTrue,\n                               TestParameterListRvalueQualifiersNothrowCall);\n\nREGISTER_TYPED_TEST_SUITE_P(AnyInvTestNonRvalue,\n                            ConversionConstructionReferenceWrapper,\n                            NonMoveableResultType,\n                            ConversionAssignReferenceWrapperEmptyLhs,\n                            ConversionAssignReferenceWrapperNonemptyLhs);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(\n    NonRvalueCallMayThrow, AnyInvTestNonRvalue,\n    TestParameterListNonRvalueQualifiersCallMayThrow);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteMovable, AnyInvTestNonRvalue,\n                               TestParameterListRemoteMovable);\nINSTANTIATE_TYPED_TEST_SUITE_P(RemoteNonMovable, AnyInvTestNonRvalue,\n                               TestParameterListRemoteNonMovable);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(Local, AnyInvTestNonRvalue,\n                               TestParameterListLocal);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(NonRvalueCallNothrow, AnyInvTestNonRvalue,\n                               TestParameterListNonRvalueQualifiersNothrowCall);\n\nREGISTER_TYPED_TEST_SUITE_P(AnyInvTestRvalue,\n                            ConversionConstructionReferenceWrapper,\n                            NonMoveableResultType,\n                            ConversionAssignReferenceWrapper,\n                            NonConstCrashesOnSecondCall,\n                            QualifierIndependentObjectLifetime);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(RvalueCallMayThrow, AnyInvTestRvalue,\n                               TestParameterListRvalueQualifiersCallMayThrow);\n\nINSTANTIATE_TYPED_TEST_SUITE_P(CallNothrowRvalue, AnyInvTestRvalue,\n                               TestParameterListRvalueQualifiersNothrowCall);\n\n// Minimal SFINAE testing for platforms where we can't run the tests, but we can\n// build binaries for.\nstatic_assert(\n    std::is_convertible<void (*)(), absl::AnyInvocable<void() &&>>::value, \"\");\nstatic_assert(!std::is_convertible<void*, absl::AnyInvocable<void() &&>>::value,\n              \"\");\n\n}  // namespace\n"
  },
  {
    "path": "absl/functional/bind_front.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: bind_front.h\n// -----------------------------------------------------------------------------\n//\n// `absl::bind_front()` returns a functor by binding a number of arguments to\n// the front of a provided (usually more generic) functor. Unlike `std::bind`,\n// it does not require the use of argument placeholders. The simpler syntax of\n// `absl::bind_front()` allows you to avoid known misuses with `std::bind()`.\n//\n// `absl::bind_front()` is meant as a drop-in replacement for C++20's upcoming\n// `std::bind_front()`, which similarly resolves these issues with\n// `std::bind()`. Both `bind_front()` alternatives, unlike `std::bind()`, allow\n// partial function application. (See\n// https://en.wikipedia.org/wiki/Partial_application).\n\n#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_\n#define ABSL_FUNCTIONAL_BIND_FRONT_H_\n\n#ifdef __has_include\n#if __has_include(<version>)\n#include <version>\n#endif\n#endif\n\n#if defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L\n#include <functional>  // For std::bind_front.\n#endif  // defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L\n\n#include <utility>\n\n#include \"absl/functional/internal/front_binder.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// bind_front()\n//\n// Binds the first N arguments of an invocable object and stores them by value.\n//\n// Like `std::bind()`, `absl::bind_front()` is implicitly convertible to\n// `std::function`.  In particular, it may be used as a simpler replacement for\n// `std::bind()` in most cases, as it does not require placeholders to be\n// specified. More importantly, it provides more reliable correctness guarantees\n// than `std::bind()`; while `std::bind()` will silently ignore passing more\n// parameters than expected, for example, `absl::bind_front()` will report such\n// mis-uses as errors. In C++20, `absl::bind_front` is replaced by\n// `std::bind_front`.\n//\n// absl::bind_front(a...) can be seen as storing the results of\n// std::make_tuple(a...).\n//\n// Example: Binding a free function.\n//\n//   int Minus(int a, int b) { return a - b; }\n//\n//   assert(absl::bind_front(Minus)(3, 2) == 3 - 2);\n//   assert(absl::bind_front(Minus, 3)(2) == 3 - 2);\n//   assert(absl::bind_front(Minus, 3, 2)() == 3 - 2);\n//\n// Example: Binding a member function.\n//\n//   struct Math {\n//     int Double(int a) const { return 2 * a; }\n//   };\n//\n//   Math math;\n//\n//   assert(absl::bind_front(&Math::Double)(&math, 3) == 2 * 3);\n//   // Stores a pointer to math inside the functor.\n//   assert(absl::bind_front(&Math::Double, &math)(3) == 2 * 3);\n//   // Stores a copy of math inside the functor.\n//   assert(absl::bind_front(&Math::Double, math)(3) == 2 * 3);\n//   // Stores std::unique_ptr<Math> inside the functor.\n//   assert(absl::bind_front(&Math::Double,\n//                           std::unique_ptr<Math>(new Math))(3) == 2 * 3);\n//\n// Example: Using `absl::bind_front()`, instead of `std::bind()`, with\n//          `std::function`.\n//\n//   class FileReader {\n//    public:\n//     void ReadFileAsync(const std::string& filename, std::string* content,\n//                        const std::function<void()>& done) {\n//       // Calls Executor::Schedule(std::function<void()>).\n//       Executor::DefaultExecutor()->Schedule(\n//           absl::bind_front(&FileReader::BlockingRead, this,\n//                            filename, content, done));\n//     }\n//\n//    private:\n//     void BlockingRead(const std::string& filename, std::string* content,\n//                       const std::function<void()>& done) {\n//       CHECK_OK(file::GetContents(filename, content, {}));\n//       done();\n//     }\n//   };\n//\n// `absl::bind_front()` stores bound arguments explicitly using the type passed\n// rather than implicitly based on the type accepted by its functor.\n//\n// Example: Binding arguments explicitly.\n//\n//   void LogStringView(absl::string_view sv) {\n//     LOG(INFO) << sv;\n//   }\n//\n//   Executor* e = Executor::DefaultExecutor();\n//   std::string s = \"hello\";\n//   absl::string_view sv = s;\n//\n//   // absl::bind_front(LogStringView, arg) makes a copy of arg and stores it.\n//   e->Schedule(absl::bind_front(LogStringView, sv)); // ERROR: dangling\n//                                                     // string_view.\n//\n//   e->Schedule(absl::bind_front(LogStringView, s));  // OK: stores a copy of\n//                                                     // s.\n//\n// To store some of the arguments passed to `absl::bind_front()` by reference,\n//  use std::ref()` and `std::cref()`.\n//\n// Example: Storing some of the bound arguments by reference.\n//\n//   class Service {\n//    public:\n//     void Serve(const Request& req, std::function<void()>* done) {\n//       // The request protocol buffer won't be deleted until done is called.\n//       // It's safe to store a reference to it inside the functor.\n//       Executor::DefaultExecutor()->Schedule(\n//           absl::bind_front(&Service::BlockingServe, this, std::cref(req),\n//           done));\n//     }\n//\n//    private:\n//     void BlockingServe(const Request& req, std::function<void()>* done);\n//   };\n//\n// Example: Storing bound arguments by reference.\n//\n//   void Print(const std::string& a, const std::string& b) {\n//     std::cerr << a << b;\n//   }\n//\n//   std::string hi = \"Hello, \";\n//   std::vector<std::string> names = {\"Chuk\", \"Gek\"};\n//   // Doesn't copy hi.\n//   for_each(names.begin(), names.end(),\n//            absl::bind_front(Print, std::ref(hi)));\n//\n//   // DO NOT DO THIS: the functor may outlive \"hi\", resulting in\n//   // dangling references.\n//   foo->DoInFuture(absl::bind_front(Print, std::ref(hi), \"Guest\"));  // BAD!\n//   auto f = absl::bind_front(Print, std::ref(hi), \"Guest\"); // BAD!\n//\n// Example: Storing reference-like types.\n//\n//   void Print(absl::string_view a, const std::string& b) {\n//     std::cerr << a << b;\n//   }\n//\n//   std::string hi = \"Hello, \";\n//   // Copies \"hi\".\n//   absl::bind_front(Print, hi)(\"Chuk\");\n//\n//   // Compile error: std::reference_wrapper<const string> is not implicitly\n//   // convertible to string_view.\n//   // absl::bind_front(Print, std::cref(hi))(\"Chuk\");\n//\n//   // Doesn't copy \"hi\".\n//   absl::bind_front(Print, absl::string_view(hi))(\"Chuk\");\n//\n#if defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L\nusing std::bind_front;\n#else   // defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L\ntemplate <class F, class... BoundArgs>\nconstexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front(\n    F&& func, BoundArgs&&... args) {\n  return functional_internal::bind_front_t<F, BoundArgs...>(\n      absl::in_place, std::forward<F>(func), std::forward<BoundArgs>(args)...);\n}\n#endif  // defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_BIND_FRONT_H_\n"
  },
  {
    "path": "absl/functional/bind_front_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/functional/bind_front.h\"\n\n#include <stddef.h>\n\n#include <functional>\n#include <memory>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/memory/memory.h\"\n\nnamespace {\n\nchar CharAt(const char* s, size_t index) { return s[index]; }\n\nTEST(BindTest, Basics) {\n  EXPECT_EQ('C', absl::bind_front(CharAt)(\"ABC\", 2));\n  EXPECT_EQ('C', absl::bind_front(CharAt, \"ABC\")(2));\n  EXPECT_EQ('C', absl::bind_front(CharAt, \"ABC\", 2)());\n}\n\nTEST(BindTest, Lambda) {\n  auto lambda = [](int x, int y, int z) { return x + y + z; };\n  EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3));\n  EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3));\n  EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3));\n  EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)());\n}\n\nstruct Functor {\n  std::string operator()() & { return \"&\"; }\n  std::string operator()() const& { return \"const&\"; }\n  std::string operator()() && { return \"&&\"; }\n  std::string operator()() const&& { return \"const&&\"; }\n};\n\nTEST(BindTest, PerfectForwardingOfBoundArgs) {\n  auto f = absl::bind_front(Functor());\n  const auto& cf = f;\n  EXPECT_EQ(\"&\", f());\n  EXPECT_EQ(\"const&\", cf());\n  EXPECT_EQ(\"&&\", std::move(f)());\n  EXPECT_EQ(\"const&&\", std::move(cf)());\n}\n\nstruct ArgDescribe {\n  std::string operator()(int&) const { return \"&\"; }             // NOLINT\n  std::string operator()(const int&) const { return \"const&\"; }  // NOLINT\n  std::string operator()(int&&) const { return \"&&\"; }\n  std::string operator()(const int&&) const { return \"const&&\"; }\n};\n\nTEST(BindTest, PerfectForwardingOfFreeArgs) {\n  ArgDescribe f;\n  int i;\n  EXPECT_EQ(\"&\", absl::bind_front(f)(static_cast<int&>(i)));\n  EXPECT_EQ(\"const&\", absl::bind_front(f)(static_cast<const int&>(i)));\n  EXPECT_EQ(\"&&\", absl::bind_front(f)(static_cast<int&&>(i)));\n  EXPECT_EQ(\"const&&\", absl::bind_front(f)(static_cast<const int&&>(i)));\n}\n\nstruct NonCopyableFunctor {\n  NonCopyableFunctor() = default;\n  NonCopyableFunctor(const NonCopyableFunctor&) = delete;\n  NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete;\n  const NonCopyableFunctor* operator()() const { return this; }\n};\n\nTEST(BindTest, RefToFunctor) {\n  // It won't copy/move the functor and use the original object.\n  NonCopyableFunctor ncf;\n  auto bound_ncf = absl::bind_front(std::ref(ncf));\n  auto bound_ncf_copy = bound_ncf;\n  EXPECT_EQ(&ncf, bound_ncf_copy());\n}\n\nstruct Struct {\n  std::string value;\n};\n\nTEST(BindTest, StoreByCopy) {\n  Struct s = {\"hello\"};\n  auto f = absl::bind_front(&Struct::value, s);\n  auto g = f;\n  EXPECT_EQ(\"hello\", f());\n  EXPECT_EQ(\"hello\", g());\n  EXPECT_NE(&s.value, &f());\n  EXPECT_NE(&s.value, &g());\n  EXPECT_NE(&g(), &f());\n}\n\nstruct NonCopyable {\n  explicit NonCopyable(const std::string& s) : value(s) {}\n  NonCopyable(const NonCopyable&) = delete;\n  NonCopyable& operator=(const NonCopyable&) = delete;\n\n  std::string value;\n};\n\nconst std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; }\n\nTEST(BindTest, StoreByRef) {\n  NonCopyable s(\"hello\");\n  auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s));\n  EXPECT_EQ(\"hello\", f());\n  EXPECT_EQ(&s.value, &f());\n  auto g = std::move(f);  // NOLINT\n  EXPECT_EQ(\"hello\", g());\n  EXPECT_EQ(&s.value, &g());\n  s.value = \"goodbye\";\n  EXPECT_EQ(\"goodbye\", g());\n}\n\nTEST(BindTest, StoreByCRef) {\n  NonCopyable s(\"hello\");\n  auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s));\n  EXPECT_EQ(\"hello\", f());\n  EXPECT_EQ(&s.value, &f());\n  auto g = std::move(f);  // NOLINT\n  EXPECT_EQ(\"hello\", g());\n  EXPECT_EQ(&s.value, &g());\n  s.value = \"goodbye\";\n  EXPECT_EQ(\"goodbye\", g());\n}\n\nconst std::string& GetNonCopyableValueByWrapper(\n    std::reference_wrapper<NonCopyable> n) {\n  return n.get().value;\n}\n\nTEST(BindTest, StoreByRefInvokeByWrapper) {\n  NonCopyable s(\"hello\");\n  auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s));\n  EXPECT_EQ(\"hello\", f());\n  EXPECT_EQ(&s.value, &f());\n  auto g = std::move(f);\n  EXPECT_EQ(\"hello\", g());\n  EXPECT_EQ(&s.value, &g());\n  s.value = \"goodbye\";\n  EXPECT_EQ(\"goodbye\", g());\n}\n\nTEST(BindTest, StoreByPointer) {\n  NonCopyable s(\"hello\");\n  auto f = absl::bind_front(&NonCopyable::value, &s);\n  EXPECT_EQ(\"hello\", f());\n  EXPECT_EQ(&s.value, &f());\n  auto g = std::move(f);\n  EXPECT_EQ(\"hello\", g());\n  EXPECT_EQ(&s.value, &g());\n}\n\nint Sink(std::unique_ptr<int> p) {\n  return *p;\n}\n\nstd::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }\n\nTEST(BindTest, NonCopyableArg) {\n  EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42)));\n  EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(42))());\n}\n\nTEST(BindTest, NonCopyableResult) {\n  EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42));\n  EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42));\n}\n\n// is_copy_constructible<FalseCopyable<unique_ptr<T>> is true but an attempt to\n// instantiate the copy constructor leads to a compile error. This is similar\n// to how standard containers behave.\ntemplate <class T>\nstruct FalseCopyable {\n  FalseCopyable() {}\n  FalseCopyable(const FalseCopyable& other) : m(other.m) {}\n  FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {}\n  T m;\n};\n\nint GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; }\n\nTEST(BindTest, WrappedMoveOnly) {\n  FalseCopyable<std::unique_ptr<int>> x;\n  x.m = absl::make_unique<int>(42);\n  auto f = absl::bind_front(&GetMember, std::move(x));\n  EXPECT_EQ(42, std::move(f)());\n}\n\nint Plus(int a, int b) { return a + b; }\n\nTEST(BindTest, ConstExpr) {\n  constexpr auto f = absl::bind_front(CharAt);\n  EXPECT_EQ(f(\"ABC\", 1), 'B');\n  static constexpr int five = 5;\n  constexpr auto plus5 = absl::bind_front(Plus, five);\n  EXPECT_EQ(plus5(1), 6);\n\n  static constexpr char data[] = \"DEF\";\n  constexpr auto g = absl::bind_front(CharAt, data);\n  EXPECT_EQ(g(1), 'E');\n}\n\nstruct ManglingCall {\n  int operator()(int, double, std::string) const { return 0; }\n};\n\nTEST(BindTest, Mangling) {\n  // We just want to generate a particular instantiation to see its mangling.\n  absl::bind_front(ManglingCall{}, 1, 3.3)(\"A\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/functional/function_ref.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: function_ref.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the `absl::FunctionRef` type for holding a\n// non-owning reference to an object of any invocable type. This function\n// reference is typically most useful as a type-erased argument type for\n// accepting function types that neither take ownership nor copy the type; using\n// the reference type in this case avoids a copy and an allocation. Best\n// practices of other non-owning reference-like objects (such as\n// `absl::string_view`) apply here.\n//\n//  An `absl::FunctionRef` is similar in usage to a `std::function` but has the\n//  following differences:\n//\n//  * It doesn't own the underlying object.\n//  * It doesn't have a null or empty state.\n//  * It never performs deep copies or allocations.\n//  * It's much faster and cheaper to construct.\n//  * It's trivially copyable and destructable.\n//\n// Generally, `absl::FunctionRef` should not be used as a return value, data\n// member, or to initialize a `std::function`. Such usages will often lead to\n// problematic lifetime issues. Once you convert something to an\n// `absl::FunctionRef` you cannot make a deep copy later.\n//\n// This class is suitable for use wherever a \"const std::function<>&\"\n// would be used without making a copy. ForEach functions and other versions of\n// the visitor pattern are a good example of when this class should be used.\n//\n// This class is trivial to copy and should be passed by value.\n#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_\n#define ABSL_FUNCTIONAL_FUNCTION_REF_H_\n\n#include <cassert>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/functional/internal/function_ref.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// FunctionRef\n//\n// Dummy class declaration to allow the partial specialization based on function\n// types below.\ntemplate <typename T>\nclass FunctionRef;\n\n// FunctionRef\n//\n// An `absl::FunctionRef` is a lightweight wrapper to any invocable object with\n// a compatible signature. Generally, an `absl::FunctionRef` should only be used\n// as an argument type and should be preferred as an argument over a const\n// reference to a `std::function`. `absl::FunctionRef` itself does not allocate,\n// although the wrapped invocable may.\n//\n// Example:\n//\n//   // The following function takes a function callback by const reference\n//   bool Visitor(const std::function<void(my_proto&,\n//                                         absl::string_view)>& callback);\n//\n//   // Assuming that the function is not stored or otherwise copied, it can be\n//   // replaced by an `absl::FunctionRef`:\n//   bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)>\n//                  callback);\ntemplate <typename R, typename... Args>\nclass ABSL_ATTRIBUTE_VIEW FunctionRef<R(Args...)> {\n protected:\n  // Used to disable constructors for objects that are not compatible with the\n  // signature of this FunctionRef.\n  template <typename F, typename... U>\n  using EnableIfCompatible =\n      std::enable_if_t<std::is_invocable_r<R, F, U..., Args...>::value>;\n\n  // Internal constructor to supersede the copying constructor\n  template <typename F>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(std::in_place_t, F&& f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {\n    absl::functional_internal::AssertNonNull(f);\n    ptr_.obj = &f;\n  }\n\n public:\n  // Constructs a FunctionRef from any invocable type.\n  template <typename F,\n            typename = EnableIfCompatible<std::enable_if_t<\n                !std::is_same_v<FunctionRef, absl::remove_cvref_t<F>>, F&>>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(F&& f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : FunctionRef(std::in_place, std::forward<F>(f)) {}\n\n  // Overload for function pointers. This eliminates a level of indirection that\n  // would happen if the above overload was used (it lets us store the pointer\n  // instead of a pointer to a pointer).\n  //\n  // This overload is also used for references to functions, since references to\n  // functions can decay to function pointers implicitly.\n  template <typename F, typename = EnableIfCompatible<F*>,\n            absl::functional_internal::EnableIf<std::is_function_v<F>> = 0>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(F* f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) {\n    assert(f != nullptr);\n    ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);\n  }\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n  // Similar to the other overloads, but passes the address of a known callable\n  // `F` at compile time. This allows calling arbitrary functions while avoiding\n  // an indirection.\n  // Needs C++20 as `nontype_t` needs C++20 for `auto` template parameters.\n  template <auto F, typename = EnableIfCompatible<decltype(F)>>\n  FunctionRef(nontype_t<F>) noexcept  // NOLINT(google-explicit-constructor)\n      : invoker_(&absl::functional_internal::InvokeFunction<decltype(F), F, R,\n                                                            Args...>) {}\n\n  template <\n      auto F, typename Obj,\n      typename = EnableIfCompatible<decltype(F), std::remove_reference_t<Obj>&>,\n      absl::functional_internal::EnableIf<!std::is_rvalue_reference_v<Obj&&>> =\n          0>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(nontype_t<F>, Obj&& obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : invoker_(&absl::functional_internal::InvokeObject<Obj&, decltype(F), F,\n                                                          R, Args...>) {\n    ptr_.obj = std::addressof(obj);\n  }\n\n  template <auto F, typename Obj,\n            typename = EnableIfCompatible<decltype(F), Obj*>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(nontype_t<F>, Obj* obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : invoker_(&absl::functional_internal::InvokePtr<Obj, decltype(F), F, R,\n                                                       Args...>) {\n    ptr_.obj = obj;\n  }\n#endif\n\n  using absl_internal_is_view = std::true_type;\n\n  // Call the underlying object.\n  R operator()(Args... args) const {\n    return invoker_(ptr_, std::forward<Args>(args)...);\n  }\n\n private:\n  absl::functional_internal::VoidPtr ptr_;\n  absl::functional_internal::Invoker<R, Args...> invoker_;\n};\n\n// Allow const qualified function signatures. Since FunctionRef requires\n// constness anyway we can just make this a no-op.\ntemplate <typename R, typename... Args>\nclass ABSL_ATTRIBUTE_VIEW\n    FunctionRef<R(Args...) const> : private FunctionRef<R(Args...)> {\n  using Base = FunctionRef<R(Args...)>;\n\n  template <typename F, typename... U>\n  using EnableIfCompatible =\n      typename Base::template EnableIfCompatible<F, U...>;\n\n public:\n  template <\n      typename F,\n      typename = EnableIfCompatible<std::enable_if_t<\n          !std::is_same_v<FunctionRef, absl::remove_cvref_t<F>>, const F&>>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(const F& f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : Base(std::in_place_t(), f) {}\n\n  template <typename F, typename = EnableIfCompatible<F*>,\n            absl::functional_internal::EnableIf<std::is_function_v<F>> = 0>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(F* f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept : Base(f) {}\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n  template <auto F, typename = EnableIfCompatible<decltype(F)>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(nontype_t<F> arg) noexcept : Base(arg) {}\n\n  template <auto F, typename Obj,\n            typename = EnableIfCompatible<decltype(F),\n                                          const std::remove_reference_t<Obj>&>,\n            absl::functional_internal::EnableIf<\n                !std::is_rvalue_reference_v<Obj&&>> = 0>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(nontype_t<F> arg,\n              Obj&& obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : Base(arg, std::forward<Obj>(obj)) {}\n\n  template <auto F, typename Obj,\n            typename = EnableIfCompatible<decltype(F), const Obj*>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  FunctionRef(nontype_t<F> arg,\n              const Obj* obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : Base(arg, obj) {}\n#endif\n\n  using absl_internal_is_view = std::true_type;\n\n  using Base::operator();\n};\n\ntemplate <class F>\nFunctionRef(F*) -> FunctionRef<F>;\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\ntemplate <auto Func>\nFunctionRef(nontype_t<Func>)\n    -> FunctionRef<std::remove_pointer_t<decltype(Func)>>;\n\ntemplate <class M, class T, M T::* Func, class U>\nFunctionRef(nontype_t<Func>, U&&)\n    -> FunctionRef<std::enable_if_t<std::is_member_pointer_v<M T::*>, M>>;\n\ntemplate <class M, class T, M T::* Func, class U>\nFunctionRef(nontype_t<Func>, U&&) -> FunctionRef<std::enable_if_t<\n    std::is_object_v<M>, std::invoke_result_t<decltype(Func), U&>()>>;\n\ntemplate <class R, class T, class... Args, R (*Func)(T, Args...), class U>\nFunctionRef(nontype_t<Func>, U&&) -> FunctionRef<R(Args...)>;\n#endif\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_FUNCTION_REF_H_\n"
  },
  {
    "path": "absl/functional/function_ref_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/functional/function_ref.h\"\n\n#include <functional>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/container/internal/test_instance_tracker.h\"\n#include \"absl/functional/any_invocable.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nstruct Class {\n  int Func() { return 42; }\n  int CFunc() const { return 43; }\n};\n\nint Function() { return 1337; }\n\ntemplate <typename T>\nT Dereference(const T* v) {\n  return *v;\n}\n\ntemplate <typename T>\nT Copy(const T& v) {\n  return v;\n}\n\nTEST(FunctionRefTest, Function1) {\n  FunctionRef<int()> ref(&Function);\n  EXPECT_EQ(1337, ref());\n}\n\nTEST(FunctionRefTest, Function2) {\n  FunctionRef<int()> ref(Function);\n  EXPECT_EQ(1337, ref());\n}\n\nTEST(FunctionRefTest, ConstFunction) {\n  FunctionRef<int() const> ref(Function);\n  EXPECT_EQ(1337, ref());\n}\n\nTEST(FunctionRefTest, CopyAssignment) {\n  FunctionRef<int()> a = +[]() -> int {\n    ADD_FAILURE() << \"Unexpectedly called\";\n    return 0;\n  };\n  FunctionRef<int()> b = +[] { return 1337; };\n  a = b;\n  EXPECT_EQ(1337, a());\n}\n\nint NoExceptFunction() noexcept { return 1337; }\n\n// TODO(jdennett): Add a test for noexcept member functions.\nTEST(FunctionRefTest, NoExceptFunction) {\n  FunctionRef<int()> ref(NoExceptFunction);\n  EXPECT_EQ(1337, ref());\n}\n\nTEST(FunctionRefTest, ForwardsArgs) {\n  auto l = [](std::unique_ptr<int> i) { return *i; };\n  FunctionRef<int(std::unique_ptr<int>)> ref(l);\n  EXPECT_EQ(42, ref(absl::make_unique<int>(42)));\n}\n\nTEST(FunctionRef, ReturnMoveOnly) {\n  auto l = [] { return absl::make_unique<int>(29); };\n  FunctionRef<std::unique_ptr<int>()> ref(l);\n  EXPECT_EQ(29, *ref());\n}\n\nTEST(FunctionRef, ManyArgs) {\n  auto l = [](int a, int b, int c) { return a + b + c; };\n  FunctionRef<int(int, int, int)> ref(l);\n  EXPECT_EQ(6, ref(1, 2, 3));\n}\n\nTEST(FunctionRef, VoidResultFromNonVoidFunctor) {\n  bool ran = false;\n  auto l = [&]() -> int {\n    ran = true;\n    return 2;\n  };\n  FunctionRef<void()> ref(l);\n  ref();\n  EXPECT_TRUE(ran);\n}\n\nTEST(FunctionRef, CastFromDerived) {\n  struct Base {};\n  struct Derived : public Base {};\n\n  Derived d;\n  auto l1 = [&](Base* b) { EXPECT_EQ(&d, b); };\n  FunctionRef<void(Derived*)> ref1(l1);\n  ref1(&d);\n\n  auto l2 = [&]() -> Derived* { return &d; };\n  FunctionRef<Base*()> ref2(l2);\n  EXPECT_EQ(&d, ref2());\n}\n\nTEST(FunctionRef, VoidResultFromNonVoidFuncton) {\n  FunctionRef<void()> ref(Function);\n  ref();\n}\n\nTEST(FunctionRef, MemberPtr) {\n  struct S {\n    int i;\n  };\n\n  S s{1100111};\n  auto mem_ptr = &S::i;\n  FunctionRef<int(const S& s)> ref(mem_ptr);\n  EXPECT_EQ(1100111, ref(s));\n}\n\nTEST(FunctionRef, MemberFun) {\n  struct S {\n    int i;\n    int get_i() const { return i; }\n  };\n\n  S s{22};\n  auto mem_fun_ptr = &S::get_i;\n  FunctionRef<int(const S& s)> ref(mem_fun_ptr);\n  EXPECT_EQ(22, ref(s));\n}\n\nTEST(FunctionRef, MemberFunRefqualified) {\n  struct S {\n    int i;\n    int get_i() && { return i; }\n  };\n  auto mem_fun_ptr = &S::get_i;\n  S s{22};\n  FunctionRef<int(S && s)> ref(mem_fun_ptr);\n  EXPECT_EQ(22, ref(std::move(s)));\n}\n\n#if !defined(_WIN32) && defined(GTEST_HAS_DEATH_TEST)\n\nTEST(FunctionRef, MemberFunRefqualifiedNull) {\n  struct S {\n    int i;\n    int get_i() && { return i; }\n  };\n  auto mem_fun_ptr = &S::get_i;\n  mem_fun_ptr = nullptr;\n  EXPECT_DEBUG_DEATH({ FunctionRef<int(S && s)> ref(mem_fun_ptr); }, \"\");\n}\n\nTEST(FunctionRef, NullMemberPtrAssertFails) {\n  struct S {\n    int i;\n  };\n  using MemberPtr = int S::*;\n  MemberPtr mem_ptr = nullptr;\n  EXPECT_DEBUG_DEATH({ FunctionRef<int(const S& s)> ref(mem_ptr); }, \"\");\n}\n\nTEST(FunctionRef, NullStdFunctionAssertPasses) {\n  std::function<void()> function = []() {};\n  FunctionRef<void()> ref(function);\n}\n\nTEST(FunctionRef, NullStdFunctionAssertFails) {\n  std::function<void()> function = nullptr;\n  EXPECT_DEBUG_DEATH({ FunctionRef<void()> ref(function); }, \"\");\n}\n\nTEST(FunctionRef, NullAnyInvocableAssertPasses) {\n  AnyInvocable<void() const> invocable = []() {};\n  FunctionRef<void()> ref(invocable);\n}\nTEST(FunctionRef, NullAnyInvocableAssertFails) {\n  AnyInvocable<void() const> invocable = nullptr;\n  EXPECT_DEBUG_DEATH({ FunctionRef<void()> ref(invocable); }, \"\");\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\nTEST(FunctionRef, CopiesAndMovesPerPassByValue) {\n  absl::test_internal::InstanceTracker tracker;\n  absl::test_internal::CopyableMovableInstance instance(0);\n  auto l = [](absl::test_internal::CopyableMovableInstance) {};\n  FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);\n  ref(instance);\n  EXPECT_EQ(tracker.copies(), 1);\n  EXPECT_EQ(tracker.moves(), 1);\n}\n\nTEST(FunctionRef, CopiesAndMovesPerPassByRef) {\n  absl::test_internal::InstanceTracker tracker;\n  absl::test_internal::CopyableMovableInstance instance(0);\n  auto l = [](const absl::test_internal::CopyableMovableInstance&) {};\n  FunctionRef<void(const absl::test_internal::CopyableMovableInstance&)> ref(l);\n  ref(instance);\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 0);\n}\n\nTEST(FunctionRef, CopiesAndMovesPerPassByValueCallByMove) {\n  absl::test_internal::InstanceTracker tracker;\n  absl::test_internal::CopyableMovableInstance instance(0);\n  auto l = [](absl::test_internal::CopyableMovableInstance) {};\n  FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);\n  ref(std::move(instance));\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 2);\n}\n\nTEST(FunctionRef, CopiesAndMovesPerPassByValueToRef) {\n  absl::test_internal::InstanceTracker tracker;\n  absl::test_internal::CopyableMovableInstance instance(0);\n  auto l = [](const absl::test_internal::CopyableMovableInstance&) {};\n  FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);\n  ref(std::move(instance));\n  EXPECT_EQ(tracker.copies(), 0);\n  EXPECT_EQ(tracker.moves(), 1);\n}\n\nTEST(FunctionRef, PassByValueTypes) {\n  using absl::functional_internal::Invoker;\n  using absl::functional_internal::VoidPtr;\n  using absl::test_internal::CopyableMovableInstance;\n  struct Trivial {\n    void* p[2];\n  };\n  struct LargeTrivial {\n    void* p[3];\n  };\n\n  static_assert(std::is_same<Invoker<void, int>, void (*)(VoidPtr, int)>::value,\n                \"Scalar types should be passed by value\");\n  static_assert(\n      std::is_same<Invoker<void, Trivial>, void (*)(VoidPtr, Trivial)>::value,\n      \"Small trivial types should be passed by value\");\n  static_assert(std::is_same<Invoker<void, LargeTrivial>,\n                             void (*)(VoidPtr, LargeTrivial&&)>::value,\n                \"Large trivial types should be passed by rvalue reference\");\n  static_assert(\n      std::is_same<Invoker<void, CopyableMovableInstance>,\n                   void (*)(VoidPtr, CopyableMovableInstance&&)>::value,\n      \"Types with copy/move ctor should be passed by rvalue reference\");\n\n  // References are passed as references.\n  static_assert(\n      std::is_same<Invoker<void, int&>, void (*)(VoidPtr, int&)>::value,\n      \"Reference types should be preserved\");\n  static_assert(\n      std::is_same<Invoker<void, CopyableMovableInstance&>,\n                   void (*)(VoidPtr, CopyableMovableInstance&)>::value,\n      \"Reference types should be preserved\");\n  static_assert(\n      std::is_same<Invoker<void, CopyableMovableInstance&&>,\n                   void (*)(VoidPtr, CopyableMovableInstance&&)>::value,\n      \"Reference types should be preserved\");\n\n  // Make sure the address of an object received by reference is the same as the\n  // address of the object passed by the caller.\n  {\n    LargeTrivial obj;\n    auto test = [&obj](LargeTrivial& input) { ASSERT_EQ(&input, &obj); };\n    absl::FunctionRef<void(LargeTrivial&)> ref(test);\n    ref(obj);\n  }\n\n  {\n    Trivial obj;\n    auto test = [&obj](Trivial& input) { ASSERT_EQ(&input, &obj); };\n    absl::FunctionRef<void(Trivial&)> ref(test);\n    ref(obj);\n  }\n}\n\nTEST(FunctionRef, ReferenceToIncompleteType) {\n  struct IncompleteType;\n  auto test = [](IncompleteType&) {};\n  absl::FunctionRef<void(IncompleteType&)> ref(test);\n\n  struct IncompleteType {};\n  IncompleteType obj;\n  ref(obj);\n}\n\nTEST(FunctionRefTest, CorrectConstQualifiers) {\n  struct S {\n    int operator()() { return 42; }\n    int operator()() const { return 1337; }\n  };\n  S s;\n  EXPECT_EQ(42, FunctionRef<int()>(s)());\n  EXPECT_EQ(1337, FunctionRef<int() const>(s)());\n  EXPECT_EQ(1337, FunctionRef<int()>(std::as_const(s))());\n  EXPECT_EQ(1337, FunctionRef<int() const>(std::as_const(s))());\n}\n\nTEST(FunctionRefTest, Lambdas) {\n  // Stateless lambdas implicitly convert to function pointers, so their\n  // mutability is irrelevant.\n  EXPECT_TRUE(FunctionRef<bool()>([]() /*const*/ { return true; })());\n  EXPECT_TRUE(FunctionRef<bool()>([]() mutable { return true; })());\n  EXPECT_TRUE(FunctionRef<bool() const>([]() /*const*/ { return true; })());\n#if defined(__clang__) || (ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L && \\\n                           defined(_MSC_VER) && !defined(__EDG__))\n  // MSVC has problems compiling the following code pre-C++20:\n  //   const auto f = []() mutable {};\n  //   f();\n  // EDG's MSVC-compatible mode (which Visual C++ uses for Intellisense)\n  // exhibits the bug in C++20 as well. So we don't support them.\n  EXPECT_TRUE(FunctionRef<bool() const>([]() mutable { return true; })());\n#endif\n\n  // Stateful lambdas are not implicitly convertible to function pointers, so\n  // a const stateful lambda is not mutably callable.\n  EXPECT_TRUE(FunctionRef<bool()>([v = true]() /*const*/ { return v; })());\n  EXPECT_TRUE(FunctionRef<bool()>([v = true]() mutable { return v; })());\n  EXPECT_TRUE(\n      FunctionRef<bool() const>([v = true]() /*const*/ { return v; })());\n  const auto func = [v = true]() mutable { return v; };\n  static_assert(\n      !std::is_convertible_v<decltype(func), FunctionRef<bool() const>>);\n}\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\nstatic_assert(std::is_same_v<decltype(FunctionRef(nontype<&Class::Func>,\n                                                  std::declval<Class&>())),\n                             FunctionRef<int()>>);\nstatic_assert(std::is_same_v<decltype(FunctionRef(nontype<&Class::CFunc>,\n                                                  std::declval<Class&>())),\n                             FunctionRef<int() const>>);\n\nstatic_assert(std::is_same_v<decltype(FunctionRef(nontype<&Class::Func>,\n                                                  std::declval<Class*>())),\n                             FunctionRef<int()>>);\nstatic_assert(std::is_same_v<decltype(FunctionRef(nontype<&Class::CFunc>,\n                                                  std::declval<Class*>())),\n                             FunctionRef<int() const>>);\n\nTEST(FunctionRefTest, NonTypeParameterWithTemporaries) {\n  static_assert(!std::is_constructible_v<FunctionRef<int()>,\n                                         nontype_t<&Class::Func>, Class&&>);\n  static_assert(\n      !std::is_constructible_v<FunctionRef<int()>, nontype_t<&Class::Func>,\n                               const Class&&>);\n  static_assert(!std::is_constructible_v<FunctionRef<int() const>,\n                                         nontype_t<&Class::CFunc>, Class&&>);\n  static_assert(\n      !std::is_constructible_v<FunctionRef<int() const>,\n                               nontype_t<&Class::CFunc>, const Class&&>);\n}\n\nTEST(FunctionRefTest, NonTypeParameterWithDeductionGuides) {\n  EXPECT_EQ(1337, FunctionRef(nontype<&Function>)());\n  EXPECT_EQ(42, FunctionRef(nontype<&Copy<int>>,\n                            std::integral_constant<int, 42>::value)());\n  EXPECT_EQ(42, FunctionRef(nontype<&Dereference<int>>,\n                            &std::integral_constant<int, 42>::value)());\n\n  Class c;\n  EXPECT_EQ(42, FunctionRef<int()>(nontype<&Class::Func>, c)());\n  EXPECT_EQ(43, FunctionRef<int() const>(nontype<&Class::CFunc>, c)());\n\n  EXPECT_EQ(42, FunctionRef<int()>(nontype<&Class::Func>, &c)());\n  EXPECT_EQ(43, FunctionRef<int() const>(nontype<&Class::CFunc>, &c)());\n}\n#endif\n\nTEST(FunctionRefTest, OptionalArguments) {\n  struct S {\n    int operator()(int = 0) const { return 1337; }\n  };\n  S s;\n  EXPECT_EQ(1337, FunctionRef<int()>(s)());\n}\n\nTEST(FunctionRefTest, NonConstToConstConversion) {\n  // The const-qualified version might inherit from the non-const version.\n  // We want to make sure that this doesn't introduce a bug when an instance of\n  // the base (non-const) class is forwarded through the derived (const) class.\n  // This has the potential to trigger the copy constructor, thus incorrectly\n  // producing a copy rather than another indirection.\n  absl::FunctionRef<int()> a = +[]() { return 1; };\n  absl::FunctionRef<int() const> b = a;\n  a = +[]() { return 2; };\n  EXPECT_EQ(b(), 2);\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/functional/function_type_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <functional>\n#include <memory>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/functional/any_invocable.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nint dummy = 0;\n\nvoid FreeFunction() { benchmark::DoNotOptimize(dummy); }\n\nstruct TrivialFunctor {\n  void operator()() const { benchmark::DoNotOptimize(dummy); }\n};\n\nstruct LargeFunctor {\n  void operator()() const { benchmark::DoNotOptimize(this); }\n  std::string a, b, c;\n};\n\ntemplate <typename Function, typename... Args>\nvoid ABSL_ATTRIBUTE_NOINLINE CallFunction(Function f, Args&&... args) {\n  f(std::forward<Args>(args)...);\n}\n\ntemplate <typename Function, typename Callable, typename... Args>\nvoid ConstructAndCallFunctionBenchmark(benchmark::State& state,\n                                       const Callable& c, Args&&... args) {\n  for (auto _ : state) {\n    CallFunction<Function>(c, std::forward<Args>(args)...);\n  }\n}\n\nvoid BM_TrivialStdFunction(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<std::function<void()>>(state,\n                                                           TrivialFunctor{});\n}\nBENCHMARK(BM_TrivialStdFunction);\n\nvoid BM_TrivialFunctionRef(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state,\n                                                         TrivialFunctor{});\n}\nBENCHMARK(BM_TrivialFunctionRef);\n\nvoid BM_TrivialAnyInvocable(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<AnyInvocable<void()>>(state,\n                                                          TrivialFunctor{});\n}\nBENCHMARK(BM_TrivialAnyInvocable);\n\nvoid BM_LargeStdFunction(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<std::function<void()>>(state,\n                                                           LargeFunctor{});\n}\nBENCHMARK(BM_LargeStdFunction);\n\nvoid BM_LargeFunctionRef(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, LargeFunctor{});\n}\nBENCHMARK(BM_LargeFunctionRef);\n\n\nvoid BM_LargeAnyInvocable(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<AnyInvocable<void()>>(state,\n                                                          LargeFunctor{});\n}\nBENCHMARK(BM_LargeAnyInvocable);\n\nvoid BM_FunPtrStdFunction(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<std::function<void()>>(state, FreeFunction);\n}\nBENCHMARK(BM_FunPtrStdFunction);\n\nvoid BM_FunPtrFunctionRef(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, FreeFunction);\n}\nBENCHMARK(BM_FunPtrFunctionRef);\n\nvoid BM_FunPtrAnyInvocable(benchmark::State& state) {\n  ConstructAndCallFunctionBenchmark<AnyInvocable<void()>>(state, FreeFunction);\n}\nBENCHMARK(BM_FunPtrAnyInvocable);\n\n// Doesn't include construction or copy overhead in the loop.\ntemplate <typename Function, typename Callable, typename... Args>\nvoid CallFunctionBenchmark(benchmark::State& state, const Callable& c,\n                           Args... args) {\n  Function f = c;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(&f);\n    f(args...);\n  }\n}\n\nstruct FunctorWithTrivialArgs {\n  void operator()(int a, int b, int c) const {\n    benchmark::DoNotOptimize(a);\n    benchmark::DoNotOptimize(b);\n    benchmark::DoNotOptimize(c);\n  }\n};\n\nvoid BM_TrivialArgsStdFunction(benchmark::State& state) {\n  CallFunctionBenchmark<std::function<void(int, int, int)>>(\n      state, FunctorWithTrivialArgs{}, 1, 2, 3);\n}\nBENCHMARK(BM_TrivialArgsStdFunction);\n\nvoid BM_TrivialArgsFunctionRef(benchmark::State& state) {\n  CallFunctionBenchmark<FunctionRef<void(int, int, int)>>(\n      state, FunctorWithTrivialArgs{}, 1, 2, 3);\n}\nBENCHMARK(BM_TrivialArgsFunctionRef);\n\nvoid BM_TrivialArgsAnyInvocable(benchmark::State& state) {\n  CallFunctionBenchmark<AnyInvocable<void(int, int, int)>>(\n      state, FunctorWithTrivialArgs{}, 1, 2, 3);\n}\nBENCHMARK(BM_TrivialArgsAnyInvocable);\n\nstruct FunctorWithNonTrivialArgs {\n  void operator()(std::string a, std::string b, std::string c) const {\n    benchmark::DoNotOptimize(&a);\n    benchmark::DoNotOptimize(&b);\n    benchmark::DoNotOptimize(&c);\n  }\n};\n\nvoid BM_NonTrivialArgsStdFunction(benchmark::State& state) {\n  std::string a, b, c;\n  CallFunctionBenchmark<\n      std::function<void(std::string, std::string, std::string)>>(\n      state, FunctorWithNonTrivialArgs{}, a, b, c);\n}\nBENCHMARK(BM_NonTrivialArgsStdFunction);\n\nvoid BM_NonTrivialArgsFunctionRef(benchmark::State& state) {\n  std::string a, b, c;\n  CallFunctionBenchmark<\n      FunctionRef<void(std::string, std::string, std::string)>>(\n      state, FunctorWithNonTrivialArgs{}, a, b, c);\n}\nBENCHMARK(BM_NonTrivialArgsFunctionRef);\n\nvoid BM_NonTrivialArgsAnyInvocable(benchmark::State& state) {\n  std::string a, b, c;\n  CallFunctionBenchmark<\n      AnyInvocable<void(std::string, std::string, std::string)>>(\n      state, FunctorWithNonTrivialArgs{}, a, b, c);\n}\nBENCHMARK(BM_NonTrivialArgsAnyInvocable);\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/functional/internal/any_invocable.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Implementation details for `absl::AnyInvocable`\n\n#ifndef ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_\n#define ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_\n\n////////////////////////////////////////////////////////////////////////////////\n//                                                                            //\n// This implementation chooses between local storage and remote storage for   //\n// the contained target object based on the target object's size, alignment   //\n// requirements, and whether or not it has a nothrow move constructor.        //\n// Additional optimizations are performed when the object is a trivially      //\n// copyable type [basic.types].                                               //\n//                                                                            //\n// There are three datamembers per `AnyInvocable` instance                    //\n//                                                                            //\n// 1) A union containing either                                               //\n//        - A pointer to the target object referred to via a void*, or        //\n//        - the target object, emplaced into a raw char buffer                //\n//                                                                            //\n// 2) A function pointer to a \"manager\" function operation that takes a       //\n//    discriminator and logically branches to either perform a move operation //\n//    or destroy operation based on that discriminator.                       //\n//                                                                            //\n// 3) A function pointer to an \"invoker\" function operation that invokes the  //\n//    target object, directly returning the result.                           //\n//                                                                            //\n// When in the logically empty state, the manager function is an empty        //\n// function and the invoker function is one that would be undefined behavior  //\n// to call.                                                                   //\n//                                                                            //\n// An additional optimization is performed when converting from one           //\n// AnyInvocable to another where only the noexcept specification and/or the   //\n// cv/ref qualifiers of the function type differ. In these cases, the         //\n// conversion works by \"moving the guts\", similar to if they were the same    //\n// exact type, as opposed to having to perform an additional layer of         //\n// wrapping through remote storage.                                           //\n//                                                                            //\n////////////////////////////////////////////////////////////////////////////////\n\n// IWYU pragma: private, include \"absl/functional/any_invocable.h\"\n\n#include <cassert>\n#include <cstddef>\n#include <cstring>\n#include <exception>\n#include <functional>\n#include <memory>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Defined in functional/any_invocable.h\ntemplate <class Sig>\nclass ABSL_NULLABILITY_COMPATIBLE AnyInvocable;\n\nnamespace internal_any_invocable {\n\n// Constants relating to the small-object-storage for AnyInvocable\nenum StorageProperty : std::size_t {\n  kAlignment = alignof(std::max_align_t),  // The alignment of the storage\n  kStorageSize = sizeof(void*) * 2         // The size of the storage\n};\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// A metafunction for checking if a type is an AnyInvocable instantiation.\n// This is used during conversion operations.\ntemplate <class T>\nstruct IsAnyInvocable : std::false_type {};\n\ntemplate <class Sig>\nstruct IsAnyInvocable<AnyInvocable<Sig>> : std::true_type {};\n//\n////////////////////////////////////////////////////////////////////////////////\n\n// A metafunction that tells us whether or not a target function type should be\n// stored locally in the small object optimization storage\ntemplate <class T>\nconstexpr bool IsStoredLocally() {\n  if constexpr (sizeof(T) <= kStorageSize && alignof(T) <= kAlignment &&\n                kAlignment % alignof(T) == 0) {\n    return std::is_nothrow_move_constructible<T>::value;\n  }\n  return false;\n}\n\n// An implementation of std::remove_cvref_t of C++20.\ntemplate <class T>\nusing RemoveCVRef =\n    typename std::remove_cv<typename std::remove_reference<T>::type>::type;\n\n// An implementation of std::invoke_r of C++23.\ntemplate <class ReturnType, class F, class... P>\nReturnType InvokeR(F&& f, P&&... args) {\n  if constexpr (std::is_void_v<ReturnType>) {\n    std::invoke(std::forward<F>(f), std::forward<P>(args)...);\n  } else {\n    return std::invoke(std::forward<F>(f), std::forward<P>(args)...);\n  }\n}\n\n//\n////////////////////////////////////////////////////////////////////////////////\n\n////////////////////////////////////////////////////////////////////////////////\n///\n// A metafunction that takes a \"T\" corresponding to a parameter type of the\n// user's specified function type, and yields the parameter type to use for the\n// type-erased invoker. In order to prevent observable moves, this must be\n// either a reference or, if the type is trivial, the original parameter type\n// itself. Since the parameter type may be incomplete at the point that this\n// metafunction is used, we can only do this optimization for scalar types\n// rather than for any trivial type.\ntemplate <typename T>\nT ForwardImpl(std::true_type);\n\ntemplate <typename T>\nT&& ForwardImpl(std::false_type);\n\n// NOTE: We deliberately use an intermediate struct instead of a direct alias,\n// as a workaround for b/206991861 on MSVC versions < 1924.\ntemplate <class T>\nstruct ForwardedParameter {\n  using type = decltype((\n      ForwardImpl<T>)(std::integral_constant<bool,\n                                             std::is_scalar<T>::value>()));\n};\n\ntemplate <class T>\nusing ForwardedParameterType = typename ForwardedParameter<T>::type;\n//\n////////////////////////////////////////////////////////////////////////////////\n\n// A discriminator when calling the \"manager\" function that describes operation\n// type-erased operation should be invoked.\n//\n// \"dispose\" specifies that the manager should perform a destroy.\n//\n// \"relocate_from_to\" specifies that the manager should perform a move.\n//\n// \"relocate_from_to_and_query_rust\" is identical to \"relocate_from_to\" for C++\n// managers, but instructs Rust managers to perform a special operation that\n// can be detected by the caller.\nenum class FunctionToCall : unsigned char {\n  dispose,\n  relocate_from_to,\n  relocate_from_to_and_query_rust,\n};\n\n// The portion of `AnyInvocable` state that contains either a pointer to the\n// target object or the object itself in local storage\nunion TypeErasedState {\n  struct {\n    // A pointer to the type-erased object when remotely stored\n    void* target;\n    // The size of the object for `RemoteManagerTrivial`\n    std::size_t size;\n  } remote;\n\n  // Local-storage for the type-erased object when small and trivial enough\n  alignas(kAlignment) unsigned char storage[kStorageSize];\n};\n\n// A typed accessor for the object in `TypeErasedState` storage\ntemplate <class T>\nT& ObjectInLocalStorage(TypeErasedState* const state) {\n  // We launder here because the storage may be reused with the same type.\n  return *std::launder(reinterpret_cast<T*>(&state->storage));\n}\n\n// The type for functions issuing lifetime-related operations: move and dispose\n// A pointer to such a function is contained in each `AnyInvocable` instance.\n// NOTE: When specifying `FunctionToCall::`dispose, the same state must be\n// passed as both \"from\" and \"to\".\nusing ManagerType = void(FunctionToCall /*operation*/,\n                         TypeErasedState* /*from*/,\n                         TypeErasedState* /*to*/) noexcept(true);\n\n// The type for functions issuing the actual invocation of the object\n// A pointer to such a function is contained in each AnyInvocable instance.\ntemplate <bool SigIsNoexcept, class ReturnType, class... P>\nusing InvokerType = ReturnType(\n    TypeErasedState*, ForwardedParameterType<P>...) noexcept(SigIsNoexcept);\n\n// The manager that is used when AnyInvocable is empty\ninline void EmptyManager(FunctionToCall /*operation*/,\n                         TypeErasedState* /*from*/,\n                         TypeErasedState* /*to*/) noexcept {}\n\n// The manager that is used when a target function is in local storage and is\n// a trivially copyable type.\ninline void LocalManagerTrivial(FunctionToCall /*operation*/,\n                                TypeErasedState* const from,\n                                TypeErasedState* const to) noexcept {\n  // This single statement without branching handles both possible operations.\n  //\n  // For FunctionToCall::dispose, \"from\" and \"to\" point to the same state, and\n  // so this assignment logically would do nothing.\n  //\n  // Note: Correctness here relies on http://wg21.link/p0593, which has only\n  // become standard in C++20, though implementations do not break it in\n  // practice for earlier versions of C++.\n  //\n  // The correct way to do this without that paper is to first placement-new a\n  // default-constructed T in \"to->storage\" prior to the memmove, but doing so\n  // requires a different function to be created for each T that is stored\n  // locally, which can cause unnecessary bloat and be less cache friendly.\n  *to = *from;\n\n  // Note: Because the type is trivially copyable, the destructor does not need\n  // to be called (\"trivially copyable\" requires a trivial destructor).\n}\n\n// The manager that is used when a target function is in local storage and is\n// not a trivially copyable type.\ntemplate <class T>\nvoid LocalManagerNontrivial(FunctionToCall operation,\n                            TypeErasedState* const from,\n                            TypeErasedState* const to) noexcept {\n  static_assert(IsStoredLocally<T>(),\n                \"Local storage must only be used for supported types.\");\n  static_assert(!std::is_trivially_copyable<T>::value,\n                \"Locally stored types must be trivially copyable.\");\n\n  T& from_object = (ObjectInLocalStorage<T>)(from);\n\n  switch (operation) {\n    case FunctionToCall::relocate_from_to:\n    case FunctionToCall::relocate_from_to_and_query_rust:\n      // NOTE: Requires that the left-hand operand is already empty.\n      ::new (static_cast<void*>(&to->storage)) T(std::move(from_object));\n      ABSL_FALLTHROUGH_INTENDED;\n    case FunctionToCall::dispose:\n      from_object.~T();  // Must not throw. // NOLINT\n      return;\n  }\n  ABSL_UNREACHABLE();\n}\n\n// The invoker that is used when a target function is in local storage\n// Note: QualTRef here is the target function type along with cv and reference\n// qualifiers that must be used when calling the function.\ntemplate <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>\nReturnType LocalInvoker(\n    TypeErasedState* const state,\n    ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {\n  using RawT = RemoveCVRef<QualTRef>;\n  static_assert(\n      IsStoredLocally<RawT>(),\n      \"Target object must be in local storage in order to be invoked from it.\");\n\n  auto& f = (ObjectInLocalStorage<RawT>)(state);\n  return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),\n                               static_cast<ForwardedParameterType<P>>(args)...);\n}\n\n// The manager that is used when a target function is in remote storage and it\n// has a trivial destructor\ninline void RemoteManagerTrivial(FunctionToCall operation,\n                                 TypeErasedState* const from,\n                                 TypeErasedState* const to) noexcept {\n  switch (operation) {\n    case FunctionToCall::relocate_from_to:\n    case FunctionToCall::relocate_from_to_and_query_rust:\n      // NOTE: Requires that the left-hand operand is already empty.\n      to->remote = from->remote;\n      return;\n    case FunctionToCall::dispose:\n#if defined(__cpp_sized_deallocation)\n      ::operator delete(from->remote.target, from->remote.size);\n#else   // __cpp_sized_deallocation\n      ::operator delete(from->remote.target);\n#endif  // __cpp_sized_deallocation\n      return;\n  }\n  ABSL_UNREACHABLE();\n}\n\n// The manager that is used when a target function is in remote storage and the\n// destructor of the type is not trivial\ntemplate <class T>\nvoid RemoteManagerNontrivial(FunctionToCall operation,\n                             TypeErasedState* const from,\n                             TypeErasedState* const to) noexcept {\n  static_assert(!IsStoredLocally<T>(),\n                \"Remote storage must only be used for types that do not \"\n                \"qualify for local storage.\");\n\n  switch (operation) {\n    case FunctionToCall::relocate_from_to:\n    case FunctionToCall::relocate_from_to_and_query_rust:\n      // NOTE: Requires that the left-hand operand is already empty.\n      to->remote.target = from->remote.target;\n      return;\n    case FunctionToCall::dispose:\n      ::delete static_cast<T*>(from->remote.target);  // Must not throw.\n      return;\n  }\n  ABSL_UNREACHABLE();\n}\n\n// The invoker that is used when a target function is in remote storage\ntemplate <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>\nReturnType RemoteInvoker(\n    TypeErasedState* const state,\n    ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {\n  using RawT = RemoveCVRef<QualTRef>;\n  static_assert(!IsStoredLocally<RawT>(),\n                \"Target object must be in remote storage in order to be \"\n                \"invoked from it.\");\n\n  auto& f = *static_cast<RawT*>(state->remote.target);\n  return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),\n                               static_cast<ForwardedParameterType<P>>(args)...);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// A metafunction that checks if a type T is an instantiation of\n// absl::in_place_type_t (needed for constructor constraints of AnyInvocable).\ntemplate <class T>\nstruct IsInPlaceType : std::false_type {};\n\ntemplate <class T>\nstruct IsInPlaceType<absl::in_place_type_t<T>> : std::true_type {};\n//\n////////////////////////////////////////////////////////////////////////////////\n\n// A constructor name-tag used with CoreImpl (below) to request the\n// conversion-constructor. QualDecayedTRef is the decayed-type of the object to\n// wrap, along with the cv and reference qualifiers that must be applied when\n// performing an invocation of the wrapped object.\ntemplate <class QualDecayedTRef>\nstruct TypedConversionConstruct {};\n\n// A helper base class for all core operations of AnyInvocable. Most notably,\n// this class creates the function call operator and constraint-checkers so that\n// the top-level class does not have to be a series of partial specializations.\n//\n// Note: This definition exists (as opposed to being a declaration) so that if\n// the user of the top-level template accidentally passes a template argument\n// that is not a function type, they will get a static_assert in AnyInvocable's\n// class body rather than an error stating that Impl is not defined.\ntemplate <class Sig>\nclass Impl {};  // Note: This is partially-specialized later.\n\n// A std::unique_ptr deleter that deletes memory allocated via ::operator new.\n#if defined(__cpp_sized_deallocation)\nclass TrivialDeleter {\n public:\n  explicit TrivialDeleter(std::size_t size) : size_(size) {}\n\n  void operator()(void* target) const {\n    ::operator delete(target, size_);\n  }\n\n private:\n  std::size_t size_;\n};\n#else   // __cpp_sized_deallocation\nclass TrivialDeleter {\n public:\n  explicit TrivialDeleter(std::size_t) {}\n\n  void operator()(void* target) const { ::operator delete(target); }\n};\n#endif  // __cpp_sized_deallocation\n\ntemplate <bool SigIsNoexcept, class ReturnType, class... P>\nclass CoreImpl;\n\nconstexpr bool IsCompatibleConversion(void*, void*) { return false; }\ntemplate <bool NoExceptSrc, bool NoExceptDest, class... T>\nconstexpr bool IsCompatibleConversion(CoreImpl<NoExceptSrc, T...>*,\n                                      CoreImpl<NoExceptDest, T...>*) {\n  return !NoExceptDest || NoExceptSrc;\n}\n\n// A helper base class for all core operations of AnyInvocable that do not\n// depend on the cv/ref qualifiers of the function type.\ntemplate <bool SigIsNoexcept, class ReturnType, class... P>\nclass CoreImpl {\n public:\n  using result_type = ReturnType;\n\n  CoreImpl() noexcept : manager_(EmptyManager), invoker_(nullptr) {}\n\n  // Note: QualDecayedTRef here includes the cv-ref qualifiers associated with\n  // the invocation of the Invocable. The unqualified type is the target object\n  // type to be stored.\n  template <class QualDecayedTRef, class F>\n  explicit CoreImpl(TypedConversionConstruct<QualDecayedTRef>, F&& f) {\n    using DecayedT = RemoveCVRef<QualDecayedTRef>;\n\n    if constexpr (std::is_pointer<DecayedT>::value ||\n                  std::is_member_pointer<DecayedT>::value) {\n      // This condition handles types that decay into pointers. This includes\n      // function references, which cannot be null. GCC warns against comparing\n      // their decayed form with nullptr (https://godbolt.org/z/9r9TMTcPK).\n      // We could work around this warning with constexpr programming, using\n      // std::is_function_v<std::remove_reference_t<F>>, but we choose to ignore\n      // it instead of writing more code.\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wpragmas\"\n#pragma GCC diagnostic ignored \"-Waddress\"\n#pragma GCC diagnostic ignored \"-Wnonnull-compare\"\n#endif\n      if (static_cast<DecayedT>(f) == nullptr) {\n#if !defined(__clang__) && defined(__GNUC__)\n#pragma GCC diagnostic pop\n#endif\n        manager_ = EmptyManager;\n        invoker_ = nullptr;\n      } else {\n        InitializeStorage<QualDecayedTRef>(std::forward<F>(f));\n      }\n    } else if constexpr (IsCompatibleAnyInvocable<DecayedT>::value) {\n      // In this case we can \"steal the guts\" of the other AnyInvocable.\n      f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_);\n      manager_ = f.manager_;\n      invoker_ = f.invoker_;\n\n      f.manager_ = EmptyManager;\n      f.invoker_ = nullptr;\n    } else if constexpr (IsAnyInvocable<DecayedT>::value) {\n      if (f.HasValue()) {\n        InitializeStorage<QualDecayedTRef>(std::forward<F>(f));\n      } else {\n        manager_ = EmptyManager;\n        invoker_ = nullptr;\n      }\n    } else {\n      InitializeStorage<QualDecayedTRef>(std::forward<F>(f));\n    }\n  }\n\n  // Note: QualTRef here includes the cv-ref qualifiers associated with the\n  // invocation of the Invocable. The unqualified type is the target object\n  // type to be stored.\n  template <class QualTRef, class... Args>\n  explicit CoreImpl(absl::in_place_type_t<QualTRef>, Args&&... args) {\n    InitializeStorage<QualTRef>(std::forward<Args>(args)...);\n  }\n\n  CoreImpl(CoreImpl&& other) noexcept {\n    other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);\n    manager_ = other.manager_;\n    invoker_ = other.invoker_;\n    other.manager_ = EmptyManager;\n    other.invoker_ = nullptr;\n  }\n\n  CoreImpl& operator=(CoreImpl&& other) noexcept {\n    // Put the left-hand operand in an empty state.\n    //\n    // Note: A full reset that leaves us with an object that has its invariants\n    // intact is necessary in order to handle self-move. This is required by\n    // types that are used with certain operations of the standard library, such\n    // as the default definition of std::swap when both operands target the same\n    // object.\n    Clear();\n\n    // Perform the actual move/destroy operation on the target function.\n    other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);\n    manager_ = other.manager_;\n    invoker_ = other.invoker_;\n    other.manager_ = EmptyManager;\n    other.invoker_ = nullptr;\n\n    return *this;\n  }\n\n  ~CoreImpl() { manager_(FunctionToCall::dispose, &state_, &state_); }\n\n  // Check whether or not the AnyInvocable is in the empty state.\n  bool HasValue() const { return invoker_ != nullptr; }\n\n  // Effects: Puts the object into its empty state.\n  void Clear() {\n    manager_(FunctionToCall::dispose, &state_, &state_);\n    manager_ = EmptyManager;\n    invoker_ = nullptr;\n  }\n\n  // Use local (inline) storage for applicable target object types.\n  template <class QualTRef, class... Args>\n  void InitializeStorage(Args&&... args) {\n    using RawT = RemoveCVRef<QualTRef>;\n    if constexpr (IsStoredLocally<RawT>()) {\n      ::new (static_cast<void*>(&state_.storage))\n          RawT(std::forward<Args>(args)...);\n      invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;\n      // We can simplify our manager if we know the type is trivially copyable.\n      if constexpr (std::is_trivially_copyable_v<RawT>) {\n        manager_ = LocalManagerTrivial;\n      } else {\n        manager_ = LocalManagerNontrivial<RawT>;\n      }\n    } else {\n      InitializeRemoteManager<RawT>(std::forward<Args>(args)...);\n      // This is set after everything else in case an exception is thrown in an\n      // earlier step of the initialization.\n      invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;\n    }\n  }\n\n  template <class T, class... Args>\n  void InitializeRemoteManager(Args&&... args) {\n    if constexpr (std::is_trivially_destructible_v<T> &&\n                  alignof(T) <= ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT) {\n      // unique_ptr is used for exception-safety in case construction throws.\n      std::unique_ptr<void, TrivialDeleter> uninitialized_target(\n          ::operator new(sizeof(T)), TrivialDeleter(sizeof(T)));\n      ::new (uninitialized_target.get()) T(std::forward<Args>(args)...);\n      state_.remote.target = uninitialized_target.release();\n      state_.remote.size = sizeof(T);\n      manager_ = RemoteManagerTrivial;\n    } else {\n      state_.remote.target = ::new T(std::forward<Args>(args)...);\n      manager_ = RemoteManagerNontrivial<T>;\n    }\n  }\n\n  //////////////////////////////////////////////////////////////////////////////\n  //\n  // Type trait to determine if the template argument is an AnyInvocable whose\n  // function type is compatible enough with ours such that we can\n  // \"move the guts\" out of it when moving, rather than having to place a new\n  // object into remote storage.\n\n  template <typename Other>\n  struct IsCompatibleAnyInvocable {\n    static constexpr bool value = false;\n  };\n\n  template <typename Sig>\n  struct IsCompatibleAnyInvocable<AnyInvocable<Sig>> {\n    static constexpr bool value =\n        (IsCompatibleConversion)(static_cast<\n                                     typename AnyInvocable<Sig>::CoreImpl*>(\n                                     nullptr),\n                                 static_cast<CoreImpl*>(nullptr));\n  };\n\n  //\n  //////////////////////////////////////////////////////////////////////////////\n\n  TypeErasedState state_;\n  ManagerType* manager_;\n  InvokerType<SigIsNoexcept, ReturnType, P...>* invoker_;\n};\n\n// A constructor name-tag used with Impl to request the\n// conversion-constructor\nstruct ConversionConstruct {};\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// A metafunction that is normally an identity metafunction except that when\n// given a std::reference_wrapper<T>, it yields T&. This is necessary because\n// currently std::reference_wrapper's operator() is not conditionally noexcept,\n// so when checking if such an Invocable is nothrow-invocable, we must pull out\n// the underlying type.\ntemplate <class T>\nstruct UnwrapStdReferenceWrapperImpl {\n  using type = T;\n};\n\ntemplate <class T>\nstruct UnwrapStdReferenceWrapperImpl<std::reference_wrapper<T>> {\n  using type = T&;\n};\n\ntemplate <class T>\nusing UnwrapStdReferenceWrapper =\n    typename UnwrapStdReferenceWrapperImpl<T>::type;\n//\n////////////////////////////////////////////////////////////////////////////////\n\n// An alias that always yields std::true_type (used with constraints) where\n// substitution failures happen when forming the template arguments.\ntemplate <class... T>\nusing TrueAlias =\n    std::integral_constant<bool, sizeof(absl::void_t<T...>*) != 0>;\n\n/*SFINAE constraints for the conversion-constructor.*/\ntemplate <class Sig, class F,\n          class = absl::enable_if_t<\n              !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>\nusing CanConvert = TrueAlias<\n    absl::enable_if_t<!IsInPlaceType<RemoveCVRef<F>>::value>,\n    absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,\n    absl::enable_if_t<\n        Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,\n    absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;\n\n/*SFINAE constraints for the std::in_place constructors.*/\ntemplate <class Sig, class F, class... Args>\nusing CanEmplace = TrueAlias<\n    absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,\n    absl::enable_if_t<\n        Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,\n    absl::enable_if_t<std::is_constructible<absl::decay_t<F>, Args...>::value>>;\n\n/*SFINAE constraints for the conversion-assign operator.*/\ntemplate <class Sig, class F,\n          class = absl::enable_if_t<\n              !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>\nusing CanAssign = TrueAlias<\n    absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,\n    absl::enable_if_t<\n        Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,\n    absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;\n\n/*SFINAE constraints for the reference-wrapper conversion-assign operator.*/\ntemplate <class Sig, class F>\nusing CanAssignReferenceWrapper = TrueAlias<\n    absl::enable_if_t<\n        Impl<Sig>::template CallIsValid<std::reference_wrapper<F>>::value>,\n    absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<\n        std::reference_wrapper<F>>::value>>;\n\n// The constraint for checking whether or not a call meets the noexcept\n// callability requirements. We use a preprocessor macro because specifying it\n// this way as opposed to a disjunction/branch can improve the user-side error\n// messages and avoids an instantiation of std::is_nothrow_invocable_r in the\n// cases where the user did not specify a noexcept function type.\n//\n// The disjunction below is because we can't rely on std::is_nothrow_invocable_r\n// to give the right result when ReturnType is non-moveable in toolchains that\n// don't treat non-moveable result types correctly. For example this was the\n// case in libc++ before commit c3a24882 (2022-05).\n#define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true(inv_quals)      \\\n  absl::enable_if_t<absl::disjunction<                                       \\\n      std::is_nothrow_invocable_r<                                           \\\n          ReturnType, UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \\\n          P...>,                                                             \\\n      std::conjunction<                                                      \\\n          std::is_nothrow_invocable<                                         \\\n              UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>,  \\\n          std::is_same<                                                      \\\n              ReturnType,                                                    \\\n              std::invoke_result_t<                                          \\\n                  UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals,     \\\n                  P...>>>>::value>\n\n#define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false(inv_quals)\n//\n////////////////////////////////////////////////////////////////////////////////\n\n// A macro to generate partial specializations of Impl with the different\n// combinations of supported cv/reference qualifiers and noexcept specifier.\n//\n// Here, `cv` are the cv-qualifiers if any, `ref` is the ref-qualifier if any,\n// inv_quals is the reference type to be used when invoking the target, and\n// noex is \"true\" if the function type is noexcept, or false if it is not.\n//\n// The CallIsValid condition is more complicated than simply using\n// std::is_invocable_r because we can't rely on it to give the right result\n// when ReturnType is non-moveable in toolchains that don't treat non-moveable\n// result types correctly. For example this was the case in libc++ before commit\n// c3a24882 (2022-05).\n#define ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, noex)            \\\n  template <class ReturnType, class... P>                                      \\\n  class Impl<ReturnType(P...) cv ref noexcept(noex)>                           \\\n      : public CoreImpl<noex, ReturnType, P...> {                              \\\n   public:                                                                     \\\n    /*The base class, which contains the datamembers and core operations*/     \\\n    using Core = CoreImpl<noex, ReturnType, P...>;                             \\\n                                                                               \\\n    /*SFINAE constraint to check if F is invocable with the proper signature*/ \\\n    template <class F>                                                         \\\n    using CallIsValid = TrueAlias<absl::enable_if_t<absl::disjunction<         \\\n        std::is_invocable_r<ReturnType, absl::decay_t<F> inv_quals, P...>,     \\\n        std::is_same<                                                          \\\n            ReturnType,                                                        \\\n            std::invoke_result_t<absl::decay_t<F> inv_quals, P...>>>::value>>; \\\n                                                                               \\\n    /*SFINAE constraint to check if F is nothrow-invocable when necessary*/    \\\n    template <class F>                                                         \\\n    using CallIsNoexceptIfSigIsNoexcept =                                      \\\n        TrueAlias<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex(      \\\n            inv_quals)>;                                                       \\\n                                                                               \\\n    /*Put the AnyInvocable into an empty state.*/                              \\\n    Impl() = default;                                                          \\\n                                                                               \\\n    /*The implementation of a conversion-constructor from \"f*/                 \\\n    /*This forwards to Core, attaching inv_quals so that the base class*/      \\\n    /*knows how to properly type-erase the invocation.*/                       \\\n    template <class F>                                                         \\\n    explicit Impl(ConversionConstruct, F&& f)                                  \\\n        : Core(TypedConversionConstruct<                                       \\\n                   typename std::decay<F>::type inv_quals>(),                  \\\n               std::forward<F>(f)) {}                                          \\\n                                                                               \\\n    /*Forward along the in-place construction parameters.*/                    \\\n    template <class T, class... Args>                                          \\\n    explicit Impl(absl::in_place_type_t<T>, Args&&... args)                    \\\n        : Core(absl::in_place_type<absl::decay_t<T> inv_quals>,                \\\n               std::forward<Args>(args)...) {}                                 \\\n                                                                               \\\n    /*Raises a fatal error when the AnyInvocable is invoked after a move*/     \\\n    static ReturnType InvokedAfterMove(                                        \\\n        TypeErasedState*, ForwardedParameterType<P>...) noexcept(noex) {       \\\n      ABSL_HARDENING_ASSERT(false && \"AnyInvocable use-after-move\");           \\\n      std::terminate();                                                        \\\n    }                                                                          \\\n                                                                               \\\n    InvokerType<noex, ReturnType, P...>* ExtractInvoker() cv {                 \\\n      using QualifiedTestType = int cv ref;                                    \\\n      auto* invoker = this->invoker_;                                          \\\n      if (!std::is_const<QualifiedTestType>::value &&                          \\\n          std::is_rvalue_reference<QualifiedTestType>::value) {                \\\n        ABSL_ASSERT([this]() {                                                 \\\n          /* We checked that this isn't const above, so const_cast is safe */  \\\n          const_cast<Impl*>(this)->invoker_ = InvokedAfterMove;                \\\n          return this->HasValue();                                             \\\n        }());                                                                  \\\n      }                                                                        \\\n      return invoker;                                                          \\\n    }                                                                          \\\n                                                                               \\\n    /*The actual invocation operation with the proper signature*/              \\\n    ReturnType operator()(P... args) cv ref noexcept(noex) {                   \\\n      assert(this->invoker_ != nullptr);                                       \\\n      return this->ExtractInvoker()(                                           \\\n          const_cast<TypeErasedState*>(&this->state_),                         \\\n          static_cast<ForwardedParameterType<P>>(args)...);                    \\\n    }                                                                          \\\n  }\n\n// A convenience macro that defines specializations for the noexcept(true) and\n// noexcept(false) forms, given the other properties.\n#define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals)    \\\n  ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false); \\\n  ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, true)\n\n// Non-ref-qualified partial specializations\nABSL_INTERNAL_ANY_INVOCABLE_IMPL(, , &);\nABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, , const&);\n\n// Lvalue-ref-qualified partial specializations\nABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &, &);\nABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &, const&);\n\n// Rvalue-ref-qualified partial specializations\nABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &&, &&);\nABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &&, const&&);\n\n// Undef the detail-only macros.\n#undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL\n#undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL_\n#undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false\n#undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true\n\n}  // namespace internal_any_invocable\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_\n"
  },
  {
    "path": "absl/functional/internal/front_binder.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Implementation details for `absl::bind_front()`.\n\n#ifndef ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_\n#define ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_\n\n#include <cstddef>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/container/internal/compressed_tuple.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace functional_internal {\n\n// Invoke the method, expanding the tuple of bound arguments.\ntemplate <class R, class Tuple, size_t... Idx, class... Args>\nR Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) {\n  return std::invoke(std::forward<Tuple>(bound).template get<Idx>()...,\n                     std::forward<Args>(free)...);\n}\n\ntemplate <class F, class... BoundArgs>\nclass FrontBinder {\n  using BoundArgsT = absl::container_internal::CompressedTuple<F, BoundArgs...>;\n  using Idx = absl::make_index_sequence<sizeof...(BoundArgs) + 1>;\n\n  BoundArgsT bound_args_;\n\n public:\n  template <class... Ts>\n  constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts)\n      : bound_args_(std::forward<Ts>(ts)...) {}\n\n  template <class... FreeArgs,\n            class R = std::invoke_result_t<F&, BoundArgs&..., FreeArgs&&...>>\n  R operator()(FreeArgs&&... free_args) & {\n    return functional_internal::Apply<R>(bound_args_, Idx(),\n                                         std::forward<FreeArgs>(free_args)...);\n  }\n\n  template <class... FreeArgs,\n            class R = std::invoke_result_t<const F&, const BoundArgs&...,\n                                           FreeArgs&&...>>\n  R operator()(FreeArgs&&... free_args) const& {\n    return functional_internal::Apply<R>(bound_args_, Idx(),\n                                         std::forward<FreeArgs>(free_args)...);\n  }\n\n  template <class... FreeArgs,\n            class R = std::invoke_result_t<F&&, BoundArgs&&..., FreeArgs&&...>>\n  R operator()(FreeArgs&&... free_args) && {\n    // This overload is called when *this is an rvalue. If some of the bound\n    // arguments are stored by value or rvalue reference, we move them.\n    return functional_internal::Apply<R>(std::move(bound_args_), Idx(),\n                                         std::forward<FreeArgs>(free_args)...);\n  }\n\n  template <class... FreeArgs,\n            class R = std::invoke_result_t<const F&&, const BoundArgs&&...,\n                                           FreeArgs&&...>>\n  R operator()(FreeArgs&&... free_args) const&& {\n    // This overload is called when *this is an rvalue. If some of the bound\n    // arguments are stored by value or rvalue reference, we move them.\n    return functional_internal::Apply<R>(std::move(bound_args_), Idx(),\n                                         std::forward<FreeArgs>(free_args)...);\n  }\n};\n\ntemplate <class F, class... BoundArgs>\nusing bind_front_t = FrontBinder<decay_t<F>, absl::decay_t<BoundArgs>...>;\n\n}  // namespace functional_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_\n"
  },
  {
    "path": "absl/functional/internal/function_ref.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_\n#define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_\n\n#include <cassert>\n#include <functional>\n#include <type_traits>\n\n#include \"absl/functional/any_invocable.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace functional_internal {\n\n// Like a void* that can handle function pointers as well. The standard does not\n// allow function pointers to round-trip through void*, but void(*)() is fine.\n//\n// Note: It's important that this class remains trivial and is the same size as\n// a pointer, since this allows the compiler to perform tail-call optimizations\n// when the underlying function is a callable object with a matching signature.\nunion VoidPtr {\n  const void* obj;\n  void (*fun)();\n};\n\n// Chooses the best type for passing T as an argument.\n// Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are\n// passed by value.\ntemplate <typename T,\n          bool IsLValueReference = std::is_lvalue_reference<T>::value>\nstruct PassByValue : std::false_type {};\n\ntemplate <typename T>\nstruct PassByValue<T, /*IsLValueReference=*/false>\n    : std::integral_constant<bool,\n                             absl::is_trivially_copy_constructible<T>::value &&\n                                 absl::is_trivially_copy_assignable<\n                                     typename std::remove_cv<T>::type>::value &&\n                                 std::is_trivially_destructible<T>::value &&\n                                 sizeof(T) <= 2 * sizeof(void*)> {};\n\ntemplate <typename T>\nstruct ForwardT : std::conditional<PassByValue<T>::value, T, T&&> {};\n\n// An Invoker takes a pointer to the type-erased invokable object, followed by\n// the arguments that the invokable object expects.\n//\n// Note: The order of arguments here is an optimization, since member functions\n// have an implicit \"this\" pointer as their first argument, putting VoidPtr\n// first allows the compiler to perform tail-call optimization in many cases.\ntemplate <typename R, typename... Args>\nusing Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...);\n\n//\n// InvokeObject and InvokeFunction provide static \"Invoke\" functions that can be\n// used as Invokers for objects or functions respectively.\n//\n// static_cast<R> handles the case the return type is void.\ntemplate <typename Obj, typename R, typename... Args>\nR InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {\n  using T = std::remove_reference_t<Obj>;\n  return static_cast<R>(std::invoke(\n      std::forward<Obj>(*const_cast<T*>(static_cast<const T*>(ptr.obj))),\n      std::forward<typename ForwardT<Args>::type>(args)...));\n}\n\ntemplate <typename Obj, typename Fun, Fun F, typename R, typename... Args>\nR InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {\n  using T = std::remove_reference_t<Obj>;\n  Obj&& obj =\n      std::forward<Obj>(*const_cast<T*>(static_cast<const T*>(ptr.obj)));\n  // Avoid std::invoke() since the callee is a known function at compile time\n  if constexpr (std::is_member_function_pointer_v<Fun>) {\n    return static_cast<R>((std::forward<Obj>(obj).*F)(\n        std::forward<typename ForwardT<Args>::type>(args)...));\n  } else {\n    return static_cast<R>(\n        F(std::forward<Obj>(obj),\n          std::forward<typename ForwardT<Args>::type>(args)...));\n  }\n}\n\ntemplate <typename T, typename Fun, Fun F, typename R, typename... Args>\nR InvokePtr(VoidPtr ptr, typename ForwardT<Args>::type... args) {\n  T* obj = const_cast<T*>(static_cast<const T*>(ptr.obj));\n  // Avoid std::invoke() since the callee is a known function at compile time\n  if constexpr (std::is_member_function_pointer_v<Fun>) {\n    return static_cast<R>(\n        (obj->*F)(std::forward<typename ForwardT<Args>::type>(args)...));\n  } else {\n    return static_cast<R>(\n        F(obj, std::forward<typename ForwardT<Args>::type>(args)...));\n  }\n}\n\ntemplate <typename Fun, typename R, typename... Args>\nR InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {\n  auto f = reinterpret_cast<Fun>(ptr.fun);\n  return static_cast<R>(\n      std::invoke(f, std::forward<typename ForwardT<Args>::type>(args)...));\n}\n\ntemplate <typename Fun, Fun F, typename R, typename... Args>\nR InvokeFunction(VoidPtr, typename ForwardT<Args>::type... args) {\n  return static_cast<R>(\n      F(std::forward<typename ForwardT<Args>::type>(args)...));\n}\n\ntemplate <typename Sig>\nvoid AssertNonNull(const std::function<Sig>& f) {\n  assert(f != nullptr);\n  (void)f;\n}\n\ntemplate <typename Sig>\nvoid AssertNonNull(const AnyInvocable<Sig>& f) {\n  assert(f != nullptr);\n  (void)f;\n}\n\ntemplate <typename F>\nvoid AssertNonNull(const F&) {}\n\ntemplate <typename F, typename C>\nvoid AssertNonNull(F C::* f) {\n  assert(f != nullptr);\n  (void)f;\n}\n\ntemplate <bool C>\nusing EnableIf = typename ::std::enable_if<C, int>::type;\n\n}  // namespace functional_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_\n"
  },
  {
    "path": "absl/functional/overload.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: overload.h\n// -----------------------------------------------------------------------------\n//\n// `absl::Overload` is a functor that provides overloads based on the functors\n// with which it is created. This can, for example, be used to locally define an\n// anonymous visitor type for `std::visit` inside a function using lambdas.\n//\n// Before using this function, consider whether named function overloads would\n// be a better design.\n//\n// Example:\n//\n//     std::variant<std::string, int32_t, int64_t> v(int32_t{1});\n//     const size_t result =\n//         std::visit(absl::Overload{\n//                        [](const std::string& s) { return s.size(); },\n//                        [](const auto& s) { return sizeof(s); },\n//                    },\n//                    v);\n//     assert(result == 4);\n//\n\n#ifndef ABSL_FUNCTIONAL_OVERLOAD_H_\n#define ABSL_FUNCTIONAL_OVERLOAD_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename... T>\nstruct Overload final : T... {\n  using T::operator()...;\n\n  // For historical reasons we want to support use that looks like a function\n  // call:\n  //\n  //     absl::Overload(lambda_1, lambda_2)\n  //\n  // This works automatically in C++20 because we have support for parenthesized\n  // aggregate initialization. Before then we must provide a constructor that\n  // makes this work.\n  //\n  constexpr explicit Overload(T... ts) : T(std::move(ts))... {}\n};\n\n// Before C++20, which added support for CTAD for aggregate types, we must also\n// teach the compiler how to deduce the template arguments for Overload.\n//\ntemplate <typename... T>\nOverload(T...) -> Overload<T...>;\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_FUNCTIONAL_OVERLOAD_H_\n"
  },
  {
    "path": "absl/functional/overload_test.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/functional/overload.h\"\n\n#include <cstdint>\n#include <string>\n#include <type_traits>\n#include <variant>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nTEST(OverloadTest, DispatchConsidersTypeWithAutoFallback) {\n  auto overloaded = absl::Overload{\n      [](int v) { return absl::StrCat(\"int \", v); },\n      [](double v) { return absl::StrCat(\"double \", v); },\n      [](const char* v) { return absl::StrCat(\"const char* \", v); },\n      [](auto v) { return absl::StrCat(\"auto \", v); },\n  };\n\n  EXPECT_EQ(\"int 1\", overloaded(1));\n  EXPECT_EQ(\"double 2.5\", overloaded(2.5));\n  EXPECT_EQ(\"const char* hello\", overloaded(\"hello\"));\n  EXPECT_EQ(\"auto 1.5\", overloaded(1.5f));\n}\n\nTEST(OverloadTest, DispatchConsidersNumberOfArguments) {\n  auto overloaded = absl::Overload{\n      [](int a) { return a + 1; },\n      [](int a, int b) { return a * b; },\n      []() -> absl::string_view { return \"none\"; },\n  };\n\n  EXPECT_EQ(3, overloaded(2));\n  EXPECT_EQ(21, overloaded(3, 7));\n  EXPECT_EQ(\"none\", overloaded());\n}\n\nTEST(OverloadTest, SupportsConstantEvaluation) {\n  auto overloaded = absl::Overload{\n      [](int a) { return a + 1; },\n      [](int a, int b) { return a * b; },\n      []() -> absl::string_view { return \"none\"; },\n  };\n\n  static_assert(overloaded() == \"none\");\n  static_assert(overloaded(2) == 3);\n  static_assert(overloaded(3, 7) == 21);\n}\n\nTEST(OverloadTest, PropogatesDefaults) {\n  auto overloaded = absl::Overload{\n      [](int a, int b = 5) { return a * b; },\n      [](double c) { return c; },\n  };\n\n  EXPECT_EQ(21, overloaded(3, 7));\n  EXPECT_EQ(35, overloaded(7));\n  EXPECT_EQ(2.5, overloaded(2.5));\n}\n\nTEST(OverloadTest, AmbiguousWithDefaultsNotInvocable) {\n  auto overloaded = absl::Overload{\n      [](int a, int b = 5) { return a * b; },\n      [](int c) { return c; },\n  };\n\n  static_assert(!std::is_invocable_v<decltype(overloaded), int>);\n  static_assert(std::is_invocable_v<decltype(overloaded), int, int>);\n}\n\nTEST(OverloadTest, AmbiguousDuplicatesNotInvocable) {\n  auto overloaded = absl::Overload{\n      [](int a) { return a; },\n      [](int c) { return c; },\n  };\n\n  static_assert(!std::is_invocable_v<decltype(overloaded), int>);\n}\n\nTEST(OverloadTest, AmbiguousConversionNotInvocable) {\n  auto overloaded = absl::Overload{\n      [](uint16_t a) { return a; },\n      [](uint64_t c) { return c; },\n  };\n\n  static_assert(!std::is_invocable_v<decltype(overloaded), int>);\n}\n\nTEST(OverloadTest, AmbiguousConversionWithAutoNotInvocable) {\n  auto overloaded = absl::Overload{\n      [](auto a) { return a; },\n      [](auto c) { return c; },\n  };\n\n  static_assert(!std::is_invocable_v<decltype(overloaded), int>);\n}\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\nTEST(OverloadTest, AmbiguousConversionWithAutoAndTemplateNotInvocable) {\n  auto overloaded = absl::Overload{\n      [](auto a) { return a; },\n      []<class T>(T c) { return c; },\n  };\n\n  static_assert(!std::is_invocable_v<decltype(overloaded), int>);\n}\n\nTEST(OverloadTest, DispatchConsidersTypeWithTemplateFallback) {\n  auto overloaded = absl::Overload{\n      [](int a) { return a; },\n      []<class T>(T c) { return c * 2; },\n  };\n\n  EXPECT_EQ(7, overloaded(7));\n  EXPECT_EQ(14.0, overloaded(7.0));\n}\n\n#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\nTEST(OverloadTest, DispatchConsidersSfinae) {\n  auto overloaded = absl::Overload{\n      [](auto a) -> decltype(a + 1) { return a + 1; },\n  };\n\n  static_assert(std::is_invocable_v<decltype(overloaded), int>);\n  static_assert(!std::is_invocable_v<decltype(overloaded), std::string>);\n}\n\nTEST(OverloadTest, VariantVisitDispatchesCorrectly) {\n  std::variant<int, double, std::string> v(1);\n  auto overloaded = absl::Overload{\n      [](int) -> absl::string_view { return \"int\"; },\n      [](double) -> absl::string_view { return \"double\"; },\n      [](const std::string&) -> absl::string_view { return \"string\"; },\n  };\n\n  EXPECT_EQ(\"int\", std::visit(overloaded, v));\n  v = 1.1;\n  EXPECT_EQ(\"double\", std::visit(overloaded, v));\n  v = \"hello\";\n  EXPECT_EQ(\"string\", std::visit(overloaded, v));\n}\n\nTEST(OverloadTest, VariantVisitWithAutoFallbackDispatchesCorrectly) {\n  std::variant<std::string, int32_t, int64_t> v(int32_t{1});\n  auto overloaded = absl::Overload{\n      [](const std::string& s) { return s.size(); },\n      [](const auto& s) { return sizeof(s); },\n  };\n\n  EXPECT_EQ(4, std::visit(overloaded, v));\n  v = int64_t{1};\n  EXPECT_EQ(8, std::visit(overloaded, v));\n  v = std::string(\"hello\");\n  EXPECT_EQ(5, std::visit(overloaded, v));\n}\n\n// This API used to be exported as a function, so it should also work fine to\n// use parantheses when initializing it.\nTEST(OverloadTest, UseWithParentheses) {\n  const auto overloaded =\n      absl::Overload([](const std::string& s) { return s.size(); },\n                     [](const auto& s) { return sizeof(s); });\n\n  std::variant<std::string, int32_t, int64_t> v(int32_t{1});\n  EXPECT_EQ(4, std::visit(overloaded, v));\n\n  v = int64_t{1};\n  EXPECT_EQ(8, std::visit(overloaded, v));\n\n  v = std::string(\"hello\");\n  EXPECT_EQ(5, std::visit(overloaded, v));\n}\n\nTEST(OverloadTest, HasConstexprConstructor) {\n  constexpr auto overloaded = absl::Overload{\n      [](int v) { return absl::StrCat(\"int \", v); },\n      [](double v) { return absl::StrCat(\"double \", v); },\n      [](const char* v) { return absl::StrCat(\"const char* \", v); },\n      [](auto v) { return absl::StrCat(\"auto \", v); },\n  };\n\n  EXPECT_EQ(\"int 1\", overloaded(1));\n  EXPECT_EQ(\"double 2.5\", overloaded(2.5));\n  EXPECT_EQ(\"const char* hello\", overloaded(\"hello\"));\n  EXPECT_EQ(\"auto 1.5\", overloaded(1.5f));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/hash/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"hash\",\n    srcs = [\n        \"internal/hash.cc\",\n        \"internal/hash.h\",\n    ],\n    hdrs = [\"hash.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":city\",\n        \":weakly_mixed_integer\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:prefetch\",\n        \"//absl/container:fixed_array\",\n        \"//absl/functional:function_ref\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/numeric:int128\",\n        \"//absl/strings\",\n        \"//absl/types:optional\",\n        \"//absl/types:variant\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"hash_testing\",\n    testonly = True,\n    hdrs = [\"hash_testing.h\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":spy_hash_state\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/types:variant\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"hash_test\",\n    size = \"large\",\n    srcs = [\n        \"hash_test.cc\",\n        \"internal/hash_test.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hash\",\n        \":hash_testing\",\n        \":spy_hash_state\",\n        \"//absl/base:config\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/container:flat_hash_set\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/strings:cord_test_helpers\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"hash_instantiated_test\",\n    srcs = [\n        \"hash_instantiated_test.cc\",\n        \"internal/hash_test.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":hash\",\n        \":hash_testing\",\n        \"//absl/base:config\",\n        \"//absl/container:btree\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/container:flat_hash_set\",\n        \"//absl/container:node_hash_map\",\n        \"//absl/container:node_hash_set\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"hash_benchmark\",\n    testonly = True,\n    srcs = [\"hash_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":hash\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:flat_hash_set\",\n        \"//absl/random\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n        \"//absl/strings:cord_test_helpers\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"spy_hash_state\",\n    testonly = True,\n    hdrs = [\"internal/spy_hash_state.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":hash\",\n        \":weakly_mixed_integer\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n    ],\n)\n\ncc_library(\n    name = \"city\",\n    srcs = [\"internal/city.cc\"],\n    hdrs = [\n        \"internal/city.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_test(\n    name = \"city_test\",\n    srcs = [\"internal/city_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":city\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"weakly_mixed_integer\",\n    hdrs = [\"internal/weakly_mixed_integer.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl/container:__pkg__\",\n        \"//absl/strings:__pkg__\",\n        \"//absl/types:__pkg__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"low_level_hash_test\",\n    srcs = [\"internal/low_level_hash_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":hash\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/hash/CMakeLists.txt",
    "content": "#\n# Copyright 2018 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    hash\n  HDRS\n    \"hash.h\"\n  SRCS\n    \"internal/hash.cc\"\n    \"internal/hash.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::bits\n    absl::city\n    absl::config\n    absl::core_headers\n    absl::endian\n    absl::fixed_array\n    absl::function_ref\n    absl::meta\n    absl::int128\n    absl::strings\n    absl::optional\n    absl::variant\n    absl::utility\n    absl::weakly_mixed_integer\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    hash_testing\n  HDRS\n    \"hash_testing.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::spy_hash_state\n    absl::meta\n    absl::strings\n    absl::variant\n    GTest::gmock\n  TESTONLY\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    hash_test\n  SRCS\n    \"hash_test.cc\"\n    \"internal/hash_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::bits\n    absl::cord_test_helpers\n    absl::flat_hash_map\n    absl::flat_hash_set\n    absl::hash\n    absl::hash_testing\n    absl::memory\n    absl::meta\n    absl::spy_hash_state\n    absl::string_view\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    hash_instantiated_test\n  SRCS\n    \"hash_instantiated_test.cc\"\n    \"internal/hash_test.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash\n    absl::hash_testing\n    absl::config\n    absl::btree\n    absl::flat_hash_map\n    absl::flat_hash_set\n    absl::node_hash_map\n    absl::node_hash_set\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\n#\n# Note: Even though external code should not depend on this target\n# directly, it must be marked PUBLIC since it is a dependency of\n# hash_testing.\nabsl_cc_library(\n  NAME\n    spy_hash_state\n  HDRS\n    \"internal/spy_hash_state.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::hash\n    absl::strings\n    absl::str_format\n    absl::weakly_mixed_integer\n  TESTONLY\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    city\n  HDRS\n    \"internal/city.h\"\n  SRCS\n    \"internal/city.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::bits\n    absl::endian\n)\n\nabsl_cc_test(\n  NAME\n    city_test\n  SRCS\n    \"internal/city_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::city\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    weakly_mixed_integer\n  HDRS\n    \"internal/weakly_mixed_integer.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    low_level_hash_test\n  SRCS\n    \"internal/low_level_hash_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::hash\n    absl::strings\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/hash/hash.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: hash.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the Abseil `hash` library and the Abseil hashing\n// framework. This framework consists of the following:\n//\n//   * The `absl::Hash` functor, which is used to invoke the hasher within the\n//     Abseil hashing framework. `absl::Hash<T>` supports most basic types and\n//     a number of Abseil types out of the box.\n//   * `AbslHashValue`, an extension point that allows you to extend types to\n//     support Abseil hashing without requiring you to define a hashing\n//     algorithm.\n//   * `HashState`, a type-erased class which implements the manipulation of the\n//     hash state (H) itself; contains member functions `combine()`,\n//     `combine_contiguous()`, and `combine_unordered()`; and which you can use\n//     to contribute to an existing hash state when hashing your types.\n//\n// Unlike `std::hash` or other hashing frameworks, the Abseil hashing framework\n// provides most of its utility by abstracting away the hash algorithm (and its\n// implementation) entirely. Instead, a type invokes the Abseil hashing\n// framework by simply combining its state with the state of known, hashable\n// types. Hashing of that combined state is separately done by `absl::Hash`.\n//\n// One should assume that a hash algorithm is chosen randomly at the start of\n// each process.  E.g., `absl::Hash<int>{}(9)` in one process and\n// `absl::Hash<int>{}(9)` in another process are likely to differ.\n//\n// `absl::Hash` may also produce different values from different dynamically\n// loaded libraries. For this reason, `absl::Hash` values must never cross\n// boundaries in dynamically loaded libraries (including when used in types like\n// hash containers.)\n//\n// `absl::Hash` is intended to strongly mix input bits with a target of passing\n// an [Avalanche Test](https://en.wikipedia.org/wiki/Avalanche_effect).\n//\n// Example:\n//\n//   // Suppose we have a class `Circle` for which we want to add hashing:\n//   class Circle {\n//    public:\n//     ...\n//    private:\n//     std::pair<int, int> center_;\n//     int radius_;\n//   };\n//\n//   // To add hashing support to `Circle`, we simply need to add a free\n//   // (non-member) function `AbslHashValue()`, and return the combined hash\n//   // state of the existing hash state and the class state. You can add such a\n//   // free function using a friend declaration within the body of the class:\n//   class Circle {\n//    public:\n//     ...\n//     template <typename H>\n//     friend H AbslHashValue(H h, const Circle& c) {\n//       return H::combine(std::move(h), c.center_, c.radius_);\n//     }\n//     ...\n//   };\n//\n// For more information, see Adding Type Support to `absl::Hash` below.\n//\n#ifndef ABSL_HASH_HASH_H_\n#define ABSL_HASH_HASH_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/hash/internal/hash.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// `absl::Hash`\n// -----------------------------------------------------------------------------\n//\n// `absl::Hash<T>` is a convenient general-purpose hash functor for any type `T`\n// satisfying any of the following conditions (in order):\n//\n//  * T is an arithmetic or pointer type\n//  * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary\n//    hash state `H`.\n//  - T defines a specialization of `std::hash<T>`\n//\n// `absl::Hash` intrinsically supports the following types:\n//\n//   * All integral types (including bool)\n//   * All enum types\n//   * All floating-point types (although hashing them is discouraged)\n//   * All pointer types, including nullptr_t\n//   * std::pair<T1, T2>, if T1 and T2 are hashable\n//   * std::tuple<Ts...>, if all the Ts... are hashable\n//   * std::unique_ptr and std::shared_ptr\n//   * All string-like types including:\n//     * absl::Cord\n//     * std::string (as well as any instance of std::basic_string that\n//       uses one of {char, wchar_t, char16_t, char32_t} and its associated\n//       std::char_traits)\n//     * std::string_view (as well as any instance of std::basic_string_view\n//       that uses one of {char, wchar_t, char16_t, char32_t} and its associated\n//       std::char_traits)\n//  * All the standard sequence containers (provided the elements are hashable)\n//  * All the standard associative containers (provided the elements are\n//    hashable)\n//  * absl types such as the following:\n//    * absl::string_view\n//    * absl::uint128\n//    * absl::Time, absl::Duration, and absl::TimeZone\n//  * absl containers (provided the elements are hashable) such as the\n//    following:\n//    * absl::flat_hash_set, absl::node_hash_set, absl::btree_set\n//    * absl::flat_hash_map, absl::node_hash_map, absl::btree_map\n//    * absl::btree_multiset, absl::btree_multimap\n//    * absl::InlinedVector\n//    * absl::FixedArray\n//\n// When absl::Hash is used to hash an unordered container with a custom hash\n// functor, the elements are hashed using default absl::Hash semantics, not\n// the custom hash functor.  This is consistent with the behavior of\n// operator==() on unordered containers, which compares elements pairwise with\n// operator==() rather than the custom equality functor.  It is usually a\n// mistake to use either operator==() or absl::Hash on unordered collections\n// that use functors incompatible with operator==() equality.\n//\n// Note: the list above is not meant to be exhaustive. Additional type support\n// may be added, in which case the above list will be updated.\n//\n// -----------------------------------------------------------------------------\n// absl::Hash Invocation Evaluation\n// -----------------------------------------------------------------------------\n//\n// When invoked, `absl::Hash<T>` searches for supplied hash functions in the\n// following order:\n//\n//   * Natively supported types out of the box (see above)\n//   * Types for which an `AbslHashValue()` overload is provided (such as\n//     user-defined types). See \"Adding Type Support to `absl::Hash`\" below.\n//   * Types which define a `std::hash<T>` specialization\n//\n// The fallback to legacy hash functions exists mainly for backwards\n// compatibility. If you have a choice, prefer defining an `AbslHashValue`\n// overload instead of specializing any legacy hash functors.\n//\n// -----------------------------------------------------------------------------\n// The Hash State Concept, and using `HashState` for Type Erasure\n// -----------------------------------------------------------------------------\n//\n// The `absl::Hash` framework relies on the Concept of a \"hash state.\" Such a\n// hash state is used in several places:\n//\n// * Within existing implementations of `absl::Hash<T>` to store the hashed\n//   state of an object. Note that it is up to the implementation how it stores\n//   such state. A hash table, for example, may mix the state to produce an\n//   integer value; a testing framework may simply hold a vector of that state.\n// * Within implementations of `AbslHashValue()` used to extend user-defined\n//   types. (See \"Adding Type Support to absl::Hash\" below.)\n// * Inside a `HashState`, providing type erasure for the concept of a hash\n//   state, which you can use to extend the `absl::Hash` framework for types\n//   that are otherwise difficult to extend using `AbslHashValue()`. (See the\n//   `HashState` class below.)\n//\n// The \"hash state\" concept contains three member functions for mixing hash\n// state:\n//\n// * `H::combine(state, values...)`\n//\n//   Combines an arbitrary number of values into a hash state, returning the\n//   updated state. Note that the existing hash state is move-only and must be\n//   passed by value.\n//\n//   Each of the value types T must be hashable by H.\n//\n//   NOTE:\n//\n//     state = H::combine(std::move(state), value1, value2, value3);\n//\n//   must be guaranteed to produce the same hash expansion as\n//\n//     state = H::combine(std::move(state), value1);\n//     state = H::combine(std::move(state), value2);\n//     state = H::combine(std::move(state), value3);\n//\n// * `H::combine_contiguous(state, data, size)`\n//\n//    Combines a contiguous array of `size` elements into a hash state,\n//    returning the updated state. Note that the existing hash state is\n//    move-only and must be passed by value.\n//\n//    NOTE:\n//\n//      state = H::combine_contiguous(std::move(state), data, size);\n//\n//    need NOT be guaranteed to produce the same hash expansion as a loop\n//    (it may perform internal optimizations). If you need this guarantee, use a\n//    loop instead.\n//\n// * `H::combine_unordered(state, begin, end)`\n//\n//    Combines a set of elements denoted by an iterator pair into a hash\n//    state, returning the updated state.  Note that the existing hash\n//    state is move-only and must be passed by value.\n//\n//    Unlike the other two methods, the hashing is order-independent.\n//    This can be used to hash unordered collections.\n//\n// -----------------------------------------------------------------------------\n// Adding Type Support to `absl::Hash`\n// -----------------------------------------------------------------------------\n//\n// To add support for your user-defined type, add a proper `AbslHashValue()`\n// overload as a free (non-member) function. The overload will take an\n// existing hash state and should combine that state with state from the type.\n//\n// Example:\n//\n//   template <typename H>\n//   H AbslHashValue(H state, const MyType& v) {\n//     return H::combine(std::move(state), v.field1, ..., v.fieldN);\n//   }\n//\n// where `(field1, ..., fieldN)` are the members you would use on your\n// `operator==` to define equality.\n//\n// Notice that `AbslHashValue` is not a class member, but an ordinary function.\n// An `AbslHashValue` overload for a type should only be declared in the same\n// file and namespace as said type. The proper `AbslHashValue` implementation\n// for a given type will be discovered via ADL.\n//\n// Note: unlike `std::hash', `absl::Hash` should never be specialized. It must\n// only be extended by adding `AbslHashValue()` overloads.\n//\ntemplate <typename T>\nusing Hash = absl::hash_internal::Hash<T>;\n\n// HashOf\n//\n// absl::HashOf() is a helper that generates a hash from the values of its\n// arguments.  It dispatches to absl::Hash directly, as follows:\n//  * HashOf(t) == absl::Hash<T>{}(t)\n//  * HashOf(a, b, c) == HashOf(std::make_tuple(a, b, c))\n//\n// HashOf(a1, a2, ...) == HashOf(b1, b2, ...) is guaranteed when\n//  * The argument lists have pairwise identical C++ types\n//  * a1 == b1 && a2 == b2 && ...\n//\n// The requirement that the arguments match in both type and value is critical.\n// It means that `a == b` does not necessarily imply `HashOf(a) == HashOf(b)` if\n// `a` and `b` have different types. For example, `HashOf(2) != HashOf(2.0)`.\ntemplate <int&... ExplicitArgumentBarrier, typename... Types>\nsize_t HashOf(const Types&... values) {\n  auto tuple = std::tie(values...);\n  return absl::Hash<decltype(tuple)>{}(tuple);\n}\n\n// HashState\n//\n// A type erased version of the hash state concept, for use in user-defined\n// `AbslHashValue` implementations that can't use templates (such as PImpl\n// classes, virtual functions, etc.). The type erasure adds overhead so it\n// should be avoided unless necessary.\n//\n// Note: This wrapper will only erase calls to\n//     combine_contiguous(H, const unsigned char*, size_t)\n//     RunCombineUnordered(H, CombinerF)\n//\n// All other calls will be handled internally and will not invoke overloads\n// provided by the wrapped class.\n//\n// Users of this class should still define a template `AbslHashValue` function,\n// but can use `absl::HashState::Create(&state)` to erase the type of the hash\n// state and dispatch to their private hashing logic.\n//\n// This state can be used like any other hash state. In particular, you can call\n// `HashState::combine()` and `HashState::combine_contiguous()` on it.\n//\n// Example:\n//\n//   class Interface {\n//    public:\n//     template <typename H>\n//     friend H AbslHashValue(H state, const Interface& value) {\n//       state = H::combine(std::move(state), std::type_index(typeid(*this)));\n//       value.HashValue(absl::HashState::Create(&state));\n//       return state;\n//     }\n//    private:\n//     virtual void HashValue(absl::HashState state) const = 0;\n//   };\n//\n//   class Impl : Interface {\n//    private:\n//     void HashValue(absl::HashState state) const override {\n//       absl::HashState::combine(std::move(state), v1_, v2_);\n//     }\n//     int v1_;\n//     std::string v2_;\n//   };\nclass HashState : public hash_internal::HashStateBase<HashState> {\n public:\n  // HashState::Create()\n  //\n  // Create a new `HashState` instance that wraps `state`. All calls to\n  // `combine()` and `combine_contiguous()` on the new instance will be\n  // redirected to the original `state` object. The `state` object must outlive\n  // the `HashState` instance. `T` must be a subclass of `HashStateBase<T>` -\n  // users should not define their own HashState types.\n  template <\n      typename T,\n      absl::enable_if_t<\n          std::is_base_of<hash_internal::HashStateBase<T>, T>::value, int> = 0>\n  static HashState Create(T* state) {\n    HashState s;\n    s.Init(state);\n    return s;\n  }\n\n  HashState(const HashState&) = delete;\n  HashState& operator=(const HashState&) = delete;\n  HashState(HashState&&) = default;\n  HashState& operator=(HashState&&) = default;\n\n  // HashState::combine()\n  //\n  // Combines an arbitrary number of values into a hash state, returning the\n  // updated state.\n  using HashState::HashStateBase::combine;\n\n  // HashState::combine_contiguous()\n  //\n  // Combines a contiguous array of `size` elements into a hash state, returning\n  // the updated state.\n  static HashState combine_contiguous(HashState hash_state,\n                                      const unsigned char* first, size_t size) {\n    hash_state.combine_contiguous_(hash_state.state_, first, size);\n    return hash_state;\n  }\n\n  static HashState combine_weakly_mixed_integer(\n      HashState hash_state, hash_internal::WeaklyMixedInteger value) {\n    hash_state.combine_weakly_mixed_integer_(hash_state.state_, value);\n    return hash_state;\n  }\n  using HashState::HashStateBase::combine_contiguous;\n\n private:\n  HashState() = default;\n\n  friend class HashState::HashStateBase;\n  friend struct hash_internal::CombineRaw;\n\n  template <typename T>\n  static void CombineContiguousImpl(void* p, const unsigned char* first,\n                                    size_t size) {\n    T& state = *static_cast<T*>(p);\n    state = T::combine_contiguous(std::move(state), first, size);\n  }\n\n  template <typename T>\n  static void CombineWeaklyMixedIntegerImpl(\n      void* p, hash_internal::WeaklyMixedInteger value) {\n    T& state = *static_cast<T*>(p);\n    state = T::combine_weakly_mixed_integer(std::move(state), value);\n  }\n\n  static HashState combine_raw(HashState hash_state, uint64_t value) {\n    hash_state.combine_raw_(hash_state.state_, value);\n    return hash_state;\n  }\n\n  template <typename T>\n  static void CombineRawImpl(void* p, uint64_t value) {\n    T& state = *static_cast<T*>(p);\n    state = hash_internal::CombineRaw()(std::move(state), value);\n  }\n\n  template <typename T>\n  void Init(T* state) {\n    state_ = state;\n    combine_weakly_mixed_integer_ = &CombineWeaklyMixedIntegerImpl<T>;\n    combine_contiguous_ = &CombineContiguousImpl<T>;\n    combine_raw_ = &CombineRawImpl<T>;\n    run_combine_unordered_ = &RunCombineUnorderedImpl<T>;\n  }\n\n  template <typename HS>\n  struct CombineUnorderedInvoker {\n    template <typename T, typename ConsumerT>\n    void operator()(T inner_state, ConsumerT inner_cb) {\n      f(HashState::Create(&inner_state),\n        [&](HashState& inner_erased) { inner_cb(inner_erased.Real<T>()); });\n    }\n\n    absl::FunctionRef<void(HS, absl::FunctionRef<void(HS&)>)> f;\n  };\n\n  template <typename T>\n  static HashState RunCombineUnorderedImpl(\n      HashState state,\n      absl::FunctionRef<void(HashState, absl::FunctionRef<void(HashState&)>)>\n          f) {\n    // Note that this implementation assumes that inner_state and outer_state\n    // are the same type.  This isn't true in the SpyHash case, but SpyHash\n    // types are move-convertible to each other, so this still works.\n    T& real_state = state.Real<T>();\n    real_state = T::RunCombineUnordered(\n        std::move(real_state), CombineUnorderedInvoker<HashState>{f});\n    return state;\n  }\n\n  template <typename CombinerT>\n  static HashState RunCombineUnordered(HashState state, CombinerT combiner) {\n    auto* run = state.run_combine_unordered_;\n    return run(std::move(state), std::ref(combiner));\n  }\n\n  // Do not erase an already erased state.\n  void Init(HashState* state) {\n    state_ = state->state_;\n    combine_weakly_mixed_integer_ = state->combine_weakly_mixed_integer_;\n    combine_contiguous_ = state->combine_contiguous_;\n    combine_raw_ = state->combine_raw_;\n    run_combine_unordered_ = state->run_combine_unordered_;\n  }\n\n  template <typename T>\n  T& Real() {\n    return *static_cast<T*>(state_);\n  }\n\n  void* state_;\n  void (*combine_weakly_mixed_integer_)(\n      void*, absl::hash_internal::WeaklyMixedInteger);\n  void (*combine_contiguous_)(void*, const unsigned char*, size_t);\n  void (*combine_raw_)(void*, uint64_t);\n  HashState (*run_combine_unordered_)(\n      HashState state,\n      absl::FunctionRef<void(HashState, absl::FunctionRef<void(HashState&)>)>);\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HASH_HASH_H_\n"
  },
  {
    "path": "absl/hash/hash_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <typeindex>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/cord_test_helpers.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nusing absl::Hash;\n\ntemplate <template <typename> class H, typename T>\nvoid RunBenchmark(benchmark::State& state, T value) {\n  H<T> h;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(value);\n    benchmark::DoNotOptimize(h(value));\n  }\n}\n\n}  // namespace\n\ntemplate <typename T>\nusing AbslHash = absl::Hash<T>;\n\nclass TypeErasedInterface {\n public:\n  virtual ~TypeErasedInterface() = default;\n\n  template <typename H>\n  friend H AbslHashValue(H state, const TypeErasedInterface& wrapper) {\n    state = H::combine(std::move(state), std::type_index(typeid(wrapper)));\n    wrapper.HashValue(absl::HashState::Create(&state));\n    return state;\n  }\n\n private:\n  virtual void HashValue(absl::HashState state) const = 0;\n};\n\ntemplate <typename T>\nstruct TypeErasedAbslHash {\n  class Wrapper : public TypeErasedInterface {\n   public:\n    explicit Wrapper(const T& value) : value_(value) {}\n\n   private:\n    void HashValue(absl::HashState state) const override {\n      absl::HashState::combine(std::move(state), value_);\n    }\n\n    const T& value_;\n  };\n\n  size_t operator()(const T& value) {\n    return absl::Hash<Wrapper>{}(Wrapper(value));\n  }\n};\n\nabsl::Cord FlatCord(size_t size) {\n  absl::Cord result(std::string(size, 'a'));\n  result.Flatten();\n  return result;\n}\n\nabsl::Cord FragmentedCord(size_t size) {\n  const size_t orig_size = size;\n  std::vector<std::string> chunks;\n  size_t chunk_size = std::max<size_t>(1, size / 10);\n  while (size > chunk_size) {\n    chunks.push_back(std::string(chunk_size, 'a'));\n    size -= chunk_size;\n  }\n  if (size > 0) {\n    chunks.push_back(std::string(size, 'a'));\n  }\n  absl::Cord result = absl::MakeFragmentedCord(chunks);\n  (void) orig_size;\n  assert(result.size() == orig_size);\n  return result;\n}\n\ntemplate <typename T>\nstd::vector<T> Vector(size_t count) {\n  std::vector<T> result;\n  for (size_t v = 0; v < count; ++v) {\n    result.push_back(v);\n  }\n  return result;\n}\n\n// Bogus type that replicates an unorderd_set's bit mixing, but with\n// vector-speed iteration. This is intended to measure the overhead of unordered\n// hashing without counting the speed of unordered_set iteration.\ntemplate <typename T>\nstruct FastUnorderedSet {\n  explicit FastUnorderedSet(size_t count) {\n    for (size_t v = 0; v < count; ++v) {\n      values.push_back(v);\n    }\n  }\n  std::vector<T> values;\n\n  template <typename H>\n  friend H AbslHashValue(H h, const FastUnorderedSet& fus) {\n    return H::combine(H::combine_unordered(std::move(h), fus.values.begin(),\n                                           fus.values.end()),\n                      fus.values.size());\n  }\n};\n\ntemplate <typename T>\nabsl::flat_hash_set<T> FlatHashSet(size_t count) {\n  absl::flat_hash_set<T> result;\n  for (size_t v = 0; v < count; ++v) {\n    result.insert(v);\n  }\n  return result;\n}\n\ntemplate <typename T>\nstruct LongCombine {\n  T a[200]{};\n  template <typename H>\n  friend H AbslHashValue(H state, const LongCombine& v) {\n    // This is testing a single call to `combine` with a lot of arguments to\n    // test the performance of the folding logic.\n    return H::combine(\n        std::move(state),  //\n        v.a[0], v.a[1], v.a[2], v.a[3], v.a[4], v.a[5], v.a[6], v.a[7], v.a[8],\n        v.a[9], v.a[10], v.a[11], v.a[12], v.a[13], v.a[14], v.a[15], v.a[16],\n        v.a[17], v.a[18], v.a[19], v.a[20], v.a[21], v.a[22], v.a[23], v.a[24],\n        v.a[25], v.a[26], v.a[27], v.a[28], v.a[29], v.a[30], v.a[31], v.a[32],\n        v.a[33], v.a[34], v.a[35], v.a[36], v.a[37], v.a[38], v.a[39], v.a[40],\n        v.a[41], v.a[42], v.a[43], v.a[44], v.a[45], v.a[46], v.a[47], v.a[48],\n        v.a[49], v.a[50], v.a[51], v.a[52], v.a[53], v.a[54], v.a[55], v.a[56],\n        v.a[57], v.a[58], v.a[59], v.a[60], v.a[61], v.a[62], v.a[63], v.a[64],\n        v.a[65], v.a[66], v.a[67], v.a[68], v.a[69], v.a[70], v.a[71], v.a[72],\n        v.a[73], v.a[74], v.a[75], v.a[76], v.a[77], v.a[78], v.a[79], v.a[80],\n        v.a[81], v.a[82], v.a[83], v.a[84], v.a[85], v.a[86], v.a[87], v.a[88],\n        v.a[89], v.a[90], v.a[91], v.a[92], v.a[93], v.a[94], v.a[95], v.a[96],\n        v.a[97], v.a[98], v.a[99], v.a[100], v.a[101], v.a[102], v.a[103],\n        v.a[104], v.a[105], v.a[106], v.a[107], v.a[108], v.a[109], v.a[110],\n        v.a[111], v.a[112], v.a[113], v.a[114], v.a[115], v.a[116], v.a[117],\n        v.a[118], v.a[119], v.a[120], v.a[121], v.a[122], v.a[123], v.a[124],\n        v.a[125], v.a[126], v.a[127], v.a[128], v.a[129], v.a[130], v.a[131],\n        v.a[132], v.a[133], v.a[134], v.a[135], v.a[136], v.a[137], v.a[138],\n        v.a[139], v.a[140], v.a[141], v.a[142], v.a[143], v.a[144], v.a[145],\n        v.a[146], v.a[147], v.a[148], v.a[149], v.a[150], v.a[151], v.a[152],\n        v.a[153], v.a[154], v.a[155], v.a[156], v.a[157], v.a[158], v.a[159],\n        v.a[160], v.a[161], v.a[162], v.a[163], v.a[164], v.a[165], v.a[166],\n        v.a[167], v.a[168], v.a[169], v.a[170], v.a[171], v.a[172], v.a[173],\n        v.a[174], v.a[175], v.a[176], v.a[177], v.a[178], v.a[179], v.a[180],\n        v.a[181], v.a[182], v.a[183], v.a[184], v.a[185], v.a[186], v.a[187],\n        v.a[188], v.a[189], v.a[190], v.a[191], v.a[192], v.a[193], v.a[194],\n        v.a[195], v.a[196], v.a[197], v.a[198], v.a[199]);\n  }\n};\n\ntemplate <typename T>\nauto MakeLongTuple() {\n  auto t1 = std::tuple<T>();\n  auto t2 = std::tuple_cat(t1, t1);\n  auto t3 = std::tuple_cat(t2, t2);\n  auto t4 = std::tuple_cat(t3, t3);\n  auto t5 = std::tuple_cat(t4, t4);\n  auto t6 = std::tuple_cat(t5, t5);\n  // Ideally this would be much larger, but some configurations can't handle\n  // making tuples with that many elements. They break inside std::tuple itself.\n  static_assert(std::tuple_size<decltype(t6)>::value == 32, \"\");\n  return t6;\n}\n\n// Generates a benchmark and a codegen method for the provided types.  The\n// codegen method provides a well known entrypoint for dumping assembly.\n#define MAKE_BENCHMARK(hash, name, ...)                          \\\n  namespace {                                                    \\\n  void BM_##hash##_##name(benchmark::State& state) {             \\\n    RunBenchmark<hash>(state, __VA_ARGS__);                      \\\n  }                                                              \\\n  BENCHMARK(BM_##hash##_##name);                                 \\\n  }                                                              \\\n  size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg);  \\\n  size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg) { \\\n    return hash<decltype(__VA_ARGS__)>{}(arg);                   \\\n  }                                                              \\\n  bool absl_hash_test_odr_use##hash##name =                      \\\n      (benchmark::DoNotOptimize(&Codegen##hash##name), false)\n\nMAKE_BENCHMARK(AbslHash, Int32, int32_t{});\nMAKE_BENCHMARK(AbslHash, Int64, int64_t{});\nMAKE_BENCHMARK(AbslHash, Double, 1.2);\nMAKE_BENCHMARK(AbslHash, DoubleZero, 0.0);\nMAKE_BENCHMARK(AbslHash, PairInt32Int32, std::pair<int32_t, int32_t>{});\nMAKE_BENCHMARK(AbslHash, PairInt64Int64, std::pair<int64_t, int64_t>{});\nMAKE_BENCHMARK(AbslHash, TupleInt32BoolInt64,\n               std::tuple<int32_t, bool, int64_t>{});\nMAKE_BENCHMARK(AbslHash, String_0, std::string());\nMAKE_BENCHMARK(AbslHash, String_1, std::string(1, 'a'));\nMAKE_BENCHMARK(AbslHash, String_2, std::string(2, 'a'));\nMAKE_BENCHMARK(AbslHash, String_4, std::string(4, 'a'));\nMAKE_BENCHMARK(AbslHash, String_8, std::string(8, 'a'));\nMAKE_BENCHMARK(AbslHash, String_10, std::string(10, 'a'));\nMAKE_BENCHMARK(AbslHash, String_30, std::string(30, 'a'));\nMAKE_BENCHMARK(AbslHash, String_90, std::string(90, 'a'));\nMAKE_BENCHMARK(AbslHash, String_200, std::string(200, 'a'));\nMAKE_BENCHMARK(AbslHash, String_5000, std::string(5000, 'a'));\nMAKE_BENCHMARK(AbslHash, Cord_Flat_0, absl::Cord());\nMAKE_BENCHMARK(AbslHash, Cord_Flat_10, FlatCord(10));\nMAKE_BENCHMARK(AbslHash, Cord_Flat_30, FlatCord(30));\nMAKE_BENCHMARK(AbslHash, Cord_Flat_90, FlatCord(90));\nMAKE_BENCHMARK(AbslHash, Cord_Flat_200, FlatCord(200));\nMAKE_BENCHMARK(AbslHash, Cord_Flat_5000, FlatCord(5000));\nMAKE_BENCHMARK(AbslHash, Cord_Fragmented_200, FragmentedCord(200));\nMAKE_BENCHMARK(AbslHash, Cord_Fragmented_5000, FragmentedCord(5000));\nMAKE_BENCHMARK(AbslHash, VectorInt64_10, Vector<int64_t>(10));\nMAKE_BENCHMARK(AbslHash, VectorInt64_100, Vector<int64_t>(100));\nMAKE_BENCHMARK(AbslHash, VectorInt64_1000, Vector<int64_t>(1000));\nMAKE_BENCHMARK(AbslHash, VectorDouble_10, Vector<double>(10));\nMAKE_BENCHMARK(AbslHash, VectorDouble_100, Vector<double>(100));\nMAKE_BENCHMARK(AbslHash, VectorDouble_1000, Vector<double>(1000));\nMAKE_BENCHMARK(AbslHash, FlatHashSetInt64_10, FlatHashSet<int64_t>(10));\nMAKE_BENCHMARK(AbslHash, FlatHashSetInt64_100, FlatHashSet<int64_t>(100));\nMAKE_BENCHMARK(AbslHash, FlatHashSetInt64_1000, FlatHashSet<int64_t>(1000));\nMAKE_BENCHMARK(AbslHash, FlatHashSetDouble_10, FlatHashSet<double>(10));\nMAKE_BENCHMARK(AbslHash, FlatHashSetDouble_100, FlatHashSet<double>(100));\nMAKE_BENCHMARK(AbslHash, FlatHashSetDouble_1000, FlatHashSet<double>(1000));\nMAKE_BENCHMARK(AbslHash, FastUnorderedSetInt64_1000,\n               FastUnorderedSet<int64_t>(1000));\nMAKE_BENCHMARK(AbslHash, FastUnorderedSetDouble_1000,\n               FastUnorderedSet<double>(1000));\nMAKE_BENCHMARK(AbslHash, PairStringString_0,\n               std::make_pair(std::string(), std::string()));\nMAKE_BENCHMARK(AbslHash, PairStringString_10,\n               std::make_pair(std::string(10, 'a'), std::string(10, 'b')));\nMAKE_BENCHMARK(AbslHash, PairStringString_30,\n               std::make_pair(std::string(30, 'a'), std::string(30, 'b')));\nMAKE_BENCHMARK(AbslHash, PairStringString_90,\n               std::make_pair(std::string(90, 'a'), std::string(90, 'b')));\nMAKE_BENCHMARK(AbslHash, PairStringString_200,\n               std::make_pair(std::string(200, 'a'), std::string(200, 'b')));\nMAKE_BENCHMARK(AbslHash, PairStringString_5000,\n               std::make_pair(std::string(5000, 'a'), std::string(5000, 'b')));\nMAKE_BENCHMARK(AbslHash, LongTupleInt32, MakeLongTuple<int>());\nMAKE_BENCHMARK(AbslHash, LongTupleString, MakeLongTuple<std::string>());\nMAKE_BENCHMARK(AbslHash, LongCombineInt32, LongCombine<int>());\nMAKE_BENCHMARK(AbslHash, LongCombineString, LongCombine<std::string>());\n\nMAKE_BENCHMARK(TypeErasedAbslHash, Int32, int32_t{});\nMAKE_BENCHMARK(TypeErasedAbslHash, Int64, int64_t{});\nMAKE_BENCHMARK(TypeErasedAbslHash, PairInt32Int32,\n               std::pair<int32_t, int32_t>{});\nMAKE_BENCHMARK(TypeErasedAbslHash, PairInt64Int64,\n               std::pair<int64_t, int64_t>{});\nMAKE_BENCHMARK(TypeErasedAbslHash, TupleInt32BoolInt64,\n               std::tuple<int32_t, bool, int64_t>{});\nMAKE_BENCHMARK(TypeErasedAbslHash, String_0, std::string());\nMAKE_BENCHMARK(TypeErasedAbslHash, String_10, std::string(10, 'a'));\nMAKE_BENCHMARK(TypeErasedAbslHash, String_30, std::string(30, 'a'));\nMAKE_BENCHMARK(TypeErasedAbslHash, String_90, std::string(90, 'a'));\nMAKE_BENCHMARK(TypeErasedAbslHash, String_200, std::string(200, 'a'));\nMAKE_BENCHMARK(TypeErasedAbslHash, String_5000, std::string(5000, 'a'));\nMAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_10,\n               std::vector<double>(10, 1.1));\nMAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_100,\n               std::vector<double>(100, 1.1));\nMAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_1000,\n               std::vector<double>(1000, 1.1));\nMAKE_BENCHMARK(TypeErasedAbslHash, FlatHashSetInt64_10,\n               FlatHashSet<int64_t>(10));\nMAKE_BENCHMARK(TypeErasedAbslHash, FlatHashSetInt64_100,\n               FlatHashSet<int64_t>(100));\nMAKE_BENCHMARK(TypeErasedAbslHash, FlatHashSetInt64_1000,\n               FlatHashSet<int64_t>(1000));\nMAKE_BENCHMARK(TypeErasedAbslHash, FlatHashSetDouble_10,\n               FlatHashSet<double>(10));\nMAKE_BENCHMARK(TypeErasedAbslHash, FlatHashSetDouble_100,\n               FlatHashSet<double>(100));\nMAKE_BENCHMARK(TypeErasedAbslHash, FlatHashSetDouble_1000,\n               FlatHashSet<double>(1000));\nMAKE_BENCHMARK(TypeErasedAbslHash, FastUnorderedSetInt64_1000,\n               FastUnorderedSet<int64_t>(1000));\nMAKE_BENCHMARK(TypeErasedAbslHash, FastUnorderedSetDouble_1000,\n               FastUnorderedSet<double>(1000));\n\n// The latency benchmark attempts to model the speed of the hash function in\n// production. When a hash function is used for hashtable lookups it is rarely\n// used to hash N items in a tight loop nor on constant sized strings. Instead,\n// after hashing there is a potential equality test plus a (usually) large\n// amount of user code. To simulate this effectively we introduce a data\n// dependency between elements we hash by using the hash of the Nth element as\n// the selector of the N+1th element to hash. This isolates the hash function\n// code much like in production. As a bonus we use the hash to generate strings\n// of size [1,N] (instead of fixed N) to disable perfect branch predictions in\n// hash function implementations.\nnamespace {\n// 16kb fits in L1 cache of most CPUs we care about. Keeping memory latency low\n// will allow us to attribute most time to CPU which means more accurate\n// measurements.\nstatic constexpr size_t kEntropySize = 16 << 10;\nstatic char entropy[kEntropySize + 1024];\nABSL_ATTRIBUTE_UNUSED static const bool kInitialized = [] {\n  absl::BitGen gen;\n  static_assert(sizeof(entropy) % sizeof(uint64_t) == 0, \"\");\n  for (int i = 0; i != sizeof(entropy); i += sizeof(uint64_t)) {\n    auto rand = absl::Uniform<uint64_t>(gen);\n    memcpy(&entropy[i], &rand, sizeof(uint64_t));\n  }\n  return true;\n}();\n}  // namespace\n\nstruct PodPairInt64 {\n  int64_t a;\n  int64_t b;\n\n  template <typename H>\n  friend H AbslHashValue(H h, const PodPairInt64& p) {\n    return H::combine(std::move(h), p.a, p.b);\n  }\n};\n\ntemplate <class T>\nstruct PodRand {\n  static_assert(std::is_pod<T>::value, \"\");\n  static_assert(kEntropySize + sizeof(T) < sizeof(entropy), \"\");\n\n  T Get(size_t i) const {\n    T v;\n    memcpy(&v, &entropy[i % kEntropySize], sizeof(T));\n    return v;\n  }\n};\n\ntemplate <size_t N>\nstruct StringRand {\n  static_assert(kEntropySize + N < sizeof(entropy), \"\");\n\n  absl::string_view Get(size_t i) const {\n    // This has a small bias towards small numbers. Because max N is ~200 this\n    // is very small and prefer to be very fast instead of absolutely accurate.\n    // Also we pass N = 2^K+1 so that mod reduces to a bitand.\n    size_t s = (i % (N - 1)) + 1;\n    return {&entropy[i % kEntropySize], s};\n  }\n};\n\n#define MAKE_LATENCY_BENCHMARK(hash, name, ...)              \\\n  namespace {                                                \\\n  void BM_latency_##hash##_##name(benchmark::State& state) { \\\n    __VA_ARGS__ r;                                           \\\n    hash<decltype(r.Get(0))> h;                              \\\n    size_t i = 871401241;                                    \\\n    for (auto _ : state) {                                   \\\n      benchmark::DoNotOptimize(i = h(r.Get(i)));             \\\n    }                                                        \\\n  }                                                          \\\n  BENCHMARK(BM_latency_##hash##_##name);                     \\\n  }  // namespace\n\nMAKE_LATENCY_BENCHMARK(AbslHash, Int32, PodRand<int32_t>)\nMAKE_LATENCY_BENCHMARK(AbslHash, Int64, PodRand<int64_t>)\nMAKE_LATENCY_BENCHMARK(AbslHash, PairInt64, PodRand<PodPairInt64>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String3, StringRand<3>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String5, StringRand<5>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String9, StringRand<9>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String17, StringRand<17>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String33, StringRand<33>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String65, StringRand<65>)\nMAKE_LATENCY_BENCHMARK(AbslHash, String257, StringRand<257>)\n"
  },
  {
    "path": "absl/hash/hash_instantiated_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file contains a few select absl::Hash tests that, due to their reliance\n// on INSTANTIATE_TYPED_TEST_SUITE_P, require a large amount of memory to\n// compile. Put new tests in hash_test.cc, not this file.\n\n#include \"absl/hash/hash.h\"\n\n#include <stddef.h>\n\n#include <algorithm>\n#include <deque>\n#include <forward_list>\n#include <initializer_list>\n#include <list>\n#include <map>\n#include <set>\n#include <string>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/container/btree_map.h\"\n#include \"absl/container/btree_set.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/container/node_hash_map.h\"\n#include \"absl/container/node_hash_set.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/hash/internal/hash_test.h\"\n\nnamespace {\n\nusing ::absl::hash_test_internal::is_hashable;\nusing ::absl::hash_test_internal::TypeErasedContainer;\n\n// Dummy type with unordered equality and hashing semantics.  This preserves\n// input order internally, and is used below to ensure we get test coverage\n// for equal sequences with different iteration orders.\ntemplate <typename T>\nclass UnorderedSequence {\n public:\n  UnorderedSequence() = default;\n  template <typename TT>\n  UnorderedSequence(std::initializer_list<TT> l)\n      : values_(l.begin(), l.end()) {}\n  template <typename ForwardIterator,\n            typename std::enable_if<!std::is_integral<ForwardIterator>::value,\n                                    bool>::type = true>\n  UnorderedSequence(ForwardIterator begin, ForwardIterator end)\n      : values_(begin, end) {}\n  // one-argument constructor of value type T, to appease older toolchains that\n  // get confused by one-element initializer lists in some contexts\n  explicit UnorderedSequence(const T& v) : values_(&v, &v + 1) {}\n\n  using value_type = T;\n\n  size_t size() const { return values_.size(); }\n  typename std::vector<T>::const_iterator begin() const {\n    return values_.begin();\n  }\n  typename std::vector<T>::const_iterator end() const { return values_.end(); }\n\n  friend bool operator==(const UnorderedSequence& lhs,\n                         const UnorderedSequence& rhs) {\n    return lhs.size() == rhs.size() &&\n           std::is_permutation(lhs.begin(), lhs.end(), rhs.begin());\n  }\n  friend bool operator!=(const UnorderedSequence& lhs,\n                         const UnorderedSequence& rhs) {\n    return !(lhs == rhs);\n  }\n  template <typename H>\n  friend H AbslHashValue(H h, const UnorderedSequence& u) {\n    return H::combine(H::combine_unordered(std::move(h), u.begin(), u.end()),\n                      u.size());\n  }\n\n private:\n  std::vector<T> values_;\n};\n\ntemplate <typename T>\nclass HashValueSequenceTest : public testing::Test {};\nTYPED_TEST_SUITE_P(HashValueSequenceTest);\n\nTYPED_TEST_P(HashValueSequenceTest, BasicUsage) {\n  EXPECT_TRUE((is_hashable<TypeParam>::value));\n\n  using IntType = typename TypeParam::value_type;\n  auto a = static_cast<IntType>(0);\n  auto b = static_cast<IntType>(23);\n  auto c = static_cast<IntType>(42);\n\n  std::vector<TypeParam> exemplars = {\n      TypeParam(),        TypeParam(),        TypeParam{a, b, c},\n      TypeParam{a, c, b}, TypeParam{c, a, b}, TypeParam{a},\n      TypeParam{a, a},    TypeParam{a, a, a}, TypeParam{a, a, b},\n      TypeParam{a, b, a}, TypeParam{b, a, a}, TypeParam{a, b},\n      TypeParam{b, c}};\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(HashValueSequenceTest, BasicUsage);\nusing IntSequenceTypes = testing::Types<\n    std::deque<int>, std::forward_list<int>, std::list<int>, std::vector<int>,\n    std::vector<bool>, TypeErasedContainer<std::vector<int>>, std::set<int>,\n    std::multiset<int>, UnorderedSequence<int>,\n    TypeErasedContainer<UnorderedSequence<int>>, std::unordered_set<int>,\n    std::unordered_multiset<int>, absl::flat_hash_set<int>,\n    absl::node_hash_set<int>, absl::btree_set<int>>;\nINSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueSequenceTest, IntSequenceTypes);\n\ntemplate <typename T>\nclass HashValueNestedSequenceTest : public testing::Test {};\nTYPED_TEST_SUITE_P(HashValueNestedSequenceTest);\n\nTYPED_TEST_P(HashValueNestedSequenceTest, BasicUsage) {\n  using T = TypeParam;\n  using V = typename T::value_type;\n  std::vector<T> exemplars = {\n      // empty case\n      T{},\n      // sets of empty sets\n      T{V{}}, T{V{}, V{}}, T{V{}, V{}, V{}},\n      // multisets of different values\n      T{V{1}}, T{V{1, 1}, V{1, 1}}, T{V{1, 1, 1}, V{1, 1, 1}, V{1, 1, 1}},\n      // various orderings of same nested sets\n      T{V{}, V{1, 2}}, T{V{}, V{2, 1}}, T{V{1, 2}, V{}}, T{V{2, 1}, V{}},\n      // various orderings of various nested sets, case 2\n      T{V{1, 2}, V{3, 4}}, T{V{1, 2}, V{4, 3}}, T{V{1, 3}, V{2, 4}},\n      T{V{1, 3}, V{4, 2}}, T{V{1, 4}, V{2, 3}}, T{V{1, 4}, V{3, 2}},\n      T{V{2, 3}, V{1, 4}}, T{V{2, 3}, V{4, 1}}, T{V{2, 4}, V{1, 3}},\n      T{V{2, 4}, V{3, 1}}, T{V{3, 4}, V{1, 2}}, T{V{3, 4}, V{2, 1}}};\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(HashValueNestedSequenceTest, BasicUsage);\ntemplate <typename T>\nusing TypeErasedSet = TypeErasedContainer<UnorderedSequence<T>>;\n\nusing NestedIntSequenceTypes = testing::Types<\n    std::vector<std::vector<int>>, std::vector<UnorderedSequence<int>>,\n    std::vector<TypeErasedSet<int>>, UnorderedSequence<std::vector<int>>,\n    UnorderedSequence<UnorderedSequence<int>>,\n    UnorderedSequence<TypeErasedSet<int>>, TypeErasedSet<std::vector<int>>,\n    TypeErasedSet<UnorderedSequence<int>>, TypeErasedSet<TypeErasedSet<int>>>;\nINSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueNestedSequenceTest,\n                               NestedIntSequenceTypes);\n\ntemplate <typename T>\nclass HashValueAssociativeMapTest : public testing::Test {};\nTYPED_TEST_SUITE_P(HashValueAssociativeMapTest);\n\nTYPED_TEST_P(HashValueAssociativeMapTest, BasicUsage) {\n  using M = TypeParam;\n  using V = typename M::value_type;\n  std::vector<M> exemplars{M{},\n                           M{V{0, \"foo\"}},\n                           M{V{1, \"foo\"}},\n                           M{V{0, \"bar\"}},\n                           M{V{1, \"bar\"}},\n                           M{V{0, \"foo\"}, V{42, \"bar\"}},\n                           M{V{42, \"bar\"}, V{0, \"foo\"}},\n                           M{V{1, \"foo\"}, V{42, \"bar\"}},\n                           M{V{1, \"foo\"}, V{43, \"bar\"}},\n                           M{V{1, \"foo\"}, V{43, \"baz\"}}};\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(HashValueAssociativeMapTest, BasicUsage);\nusing AssociativeMapTypes = testing::Types<\n    std::map<int, std::string>, std::unordered_map<int, std::string>,\n    absl::flat_hash_map<int, std::string>,\n    absl::node_hash_map<int, std::string>, absl::btree_map<int, std::string>,\n    UnorderedSequence<std::pair<const int, std::string>>>;\nINSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueAssociativeMapTest,\n                               AssociativeMapTypes);\n\ntemplate <typename T>\nclass HashValueAssociativeMultimapTest : public testing::Test {};\nTYPED_TEST_SUITE_P(HashValueAssociativeMultimapTest);\n\nTYPED_TEST_P(HashValueAssociativeMultimapTest, BasicUsage) {\n  using MM = TypeParam;\n  using V = typename MM::value_type;\n  std::vector<MM> exemplars{MM{},\n                            MM{V{0, \"foo\"}},\n                            MM{V{1, \"foo\"}},\n                            MM{V{0, \"bar\"}},\n                            MM{V{1, \"bar\"}},\n                            MM{V{0, \"foo\"}, V{0, \"bar\"}},\n                            MM{V{0, \"bar\"}, V{0, \"foo\"}},\n                            MM{V{0, \"foo\"}, V{42, \"bar\"}},\n                            MM{V{1, \"foo\"}, V{42, \"bar\"}},\n                            MM{V{1, \"foo\"}, V{1, \"foo\"}, V{43, \"bar\"}},\n                            MM{V{1, \"foo\"}, V{43, \"bar\"}, V{1, \"foo\"}},\n                            MM{V{1, \"foo\"}, V{43, \"baz\"}}};\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(exemplars));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(HashValueAssociativeMultimapTest, BasicUsage);\nusing AssociativeMultimapTypes =\n    testing::Types<std::multimap<int, std::string>,\n                   std::unordered_multimap<int, std::string>>;\nINSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueAssociativeMultimapTest,\n                               AssociativeMultimapTypes);\n\n}  // namespace\n"
  },
  {
    "path": "absl/hash/hash_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/hash/hash.h\"\n\n#include <algorithm>\n#include <array>\n#include <bitset>\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <functional>\n#include <initializer_list>\n#include <ios>\n#include <limits>\n#include <memory>\n#include <optional>\n#include <ostream>\n#include <set>\n#include <string>\n#include <string_view>\n#include <tuple>\n#include <type_traits>\n#include <unordered_map>\n#include <utility>\n#include <variant>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/hash/internal/hash_test.h\"\n#include \"absl/hash/internal/spy_hash_state.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/strings/cord_test_helpers.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE\n#include <filesystem>  // NOLINT\n#endif\n\nnamespace {\n\nusing ::absl::Hash;\nusing ::absl::container_internal::hashtable_debug_internal::\n    HashtableDebugAccess;\nusing ::absl::hash_internal::SpyHashState;\nusing ::absl::hash_test_internal::is_hashable;\nusing ::absl::hash_test_internal::TypeErasedContainer;\nusing ::absl::hash_test_internal::TypeErasedValue;\n\ntemplate <typename T>\nusing TypeErasedVector = TypeErasedContainer<std::vector<T>>;\n\ntemplate <typename T>\nclass HashValueIntTest : public testing::Test {\n};\nTYPED_TEST_SUITE_P(HashValueIntTest);\n\ntemplate <typename T>\nSpyHashState SpyHash(const T& value) {\n  return SpyHashState::combine(SpyHashState(), value);\n}\n\nTYPED_TEST_P(HashValueIntTest, BasicUsage) {\n  EXPECT_TRUE((is_hashable<TypeParam>::value));\n\n  TypeParam n = 42;\n  EXPECT_EQ(SpyHash(n), SpyHash(TypeParam{42}));\n  EXPECT_NE(SpyHash(n), SpyHash(TypeParam{0}));\n  EXPECT_NE(SpyHash(std::numeric_limits<TypeParam>::max()),\n            SpyHash(std::numeric_limits<TypeParam>::min()));\n}\n\nTYPED_TEST_P(HashValueIntTest, FastPath) {\n  // Test the fast-path to make sure the values are the same.\n  TypeParam n = 42;\n  EXPECT_EQ(absl::Hash<TypeParam>{}(n),\n            absl::Hash<std::tuple<TypeParam>>{}(std::tuple<TypeParam>(n)));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(HashValueIntTest, BasicUsage, FastPath);\nusing IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,\n                                uint32_t, uint64_t, size_t>;\nINSTANTIATE_TYPED_TEST_SUITE_P(My, HashValueIntTest, IntTypes);\n\nenum LegacyEnum { kValue1, kValue2, kValue3 };\n\nenum class EnumClass { kValue4, kValue5, kValue6 };\n\nTEST(HashValueTest, EnumAndBool) {\n  EXPECT_TRUE((is_hashable<LegacyEnum>::value));\n  EXPECT_TRUE((is_hashable<EnumClass>::value));\n  EXPECT_TRUE((is_hashable<bool>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(true, false)));\n}\n\nTEST(HashValueTest, HashConsistentAcrossIntTypes){\n  std::vector<size_t> hashes = {\n      absl::Hash<int8_t>{}(1),  absl::Hash<uint8_t>{}(1),\n      absl::Hash<int16_t>{}(1), absl::Hash<uint16_t>{}(1),\n      absl::Hash<int32_t>{}(1), absl::Hash<uint32_t>{}(1),\n      absl::Hash<int64_t>{}(1), absl::Hash<uint64_t>{}(1)};\n  EXPECT_THAT(hashes, testing::Each(absl::Hash<int>{}(1)));\n}\n\nTEST(HashValueTest, FloatingPoint) {\n  EXPECT_TRUE((is_hashable<float>::value));\n  EXPECT_TRUE((is_hashable<double>::value));\n  EXPECT_TRUE((is_hashable<long double>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),\n                      -std::numeric_limits<float>::infinity())));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),\n                      -std::numeric_limits<double>::infinity())));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      // Add some values with small exponent to test that NORMAL values also\n      // append their category.\n      .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,\n      17 * static_cast<long double>(std::numeric_limits<double>::max()),\n      std::numeric_limits<long double>::infinity(),\n      -std::numeric_limits<long double>::infinity())));\n}\n\nTEST(HashValueTest, Pointer) {\n  EXPECT_TRUE((is_hashable<int*>::value));\n  EXPECT_TRUE((is_hashable<int(*)(char, float)>::value));\n  EXPECT_TRUE((is_hashable<void(*)(int, int, ...)>::value));\n\n  int i;\n  int* ptr = &i;\n  int* n = nullptr;\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));\n}\n\nTEST(HashValueTest, PointerAlignment) {\n  // We want to make sure that pointer alignment will not cause too many bits to\n  // be stuck.\n\n  constexpr size_t kTotalSize = 1 << 20;\n  std::unique_ptr<char[]> data(new char[kTotalSize]);\n  constexpr size_t kLog2NumValues = 5;\n  constexpr size_t kNumValues = 1 << kLog2NumValues;\n\n  int64_t test_count = 0;\n  int64_t total_stuck_bit_count = 0;\n\n  for (size_t align = 1; align < kTotalSize / kNumValues;\n       align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {\n    SCOPED_TRACE(align);\n    ASSERT_LE(align * kNumValues, kTotalSize);\n\n    size_t bits_or = 0;\n    size_t bits_and = ~size_t{};\n\n    for (size_t i = 0; i < kNumValues; ++i) {\n      size_t hash = absl::Hash<void*>()(data.get() + i * align);\n      bits_or |= hash;\n      bits_and &= hash;\n    }\n\n    // Limit the scope to the bits we would be using for Swisstable.\n    constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;\n    size_t stuck_bits = (~bits_or | bits_and) & kMask;\n    int stuck_bit_count = absl::popcount(stuck_bits);\n    size_t max_stuck_bits = 5;\n    EXPECT_LE(stuck_bit_count, max_stuck_bits)\n        << \"0x\" << std::hex << stuck_bits;\n\n    total_stuck_bit_count += stuck_bit_count;\n    ++test_count;\n  }\n  // Test that average across alignments are at most 0.2 stuck bits.\n  // As of 2025-05-30 test is also passing with 0.07 stuck bits.\n  EXPECT_LE(total_stuck_bit_count, 0.2 * test_count);\n}\n\nTEST(HashValueTest, PointerToMember) {\n  struct Bass {\n    void q() {}\n  };\n\n  struct A : Bass {\n    virtual ~A() = default;\n    virtual void vfa() {}\n\n    static auto pq() -> void (A::*)() { return &A::q; }\n  };\n\n  struct B : Bass {\n    virtual ~B() = default;\n    virtual void vfb() {}\n\n    static auto pq() -> void (B::*)() { return &B::q; }\n  };\n\n  struct Foo : A, B {\n    void f1() {}\n    void f2() const {}\n\n    int g1() & { return 0; }\n    int g2() const & { return 0; }\n    int g3() && { return 0; }\n    int g4() const && { return 0; }\n\n    int h1() & { return 0; }\n    int h2() const & { return 0; }\n    int h3() && { return 0; }\n    int h4() const && { return 0; }\n\n    int a;\n    int b;\n\n    const int c = 11;\n    const int d = 22;\n  };\n\n  EXPECT_TRUE((is_hashable<float Foo::*>::value));\n  EXPECT_TRUE((is_hashable<double (Foo::*)(int, int)&&>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(&Foo::a, &Foo::b, static_cast<int Foo::*>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(&Foo::c, &Foo::d, static_cast<const int Foo::*>(nullptr),\n                      &Foo::a, &Foo::b)));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      &Foo::f1, static_cast<void (Foo::*)()>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      &Foo::f2, static_cast<void (Foo::*)() const>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      &Foo::g1, &Foo::h1, static_cast<int (Foo::*)() &>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      &Foo::g2, &Foo::h2, static_cast<int (Foo::*)() const &>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      &Foo::g3, &Foo::h3, static_cast<int (Foo::*)() &&>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      &Foo::g4, &Foo::h4, static_cast<int (Foo::*)() const &&>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(static_cast<void (Foo::*)()>(&Foo::vfa),\n                      static_cast<void (Foo::*)()>(&Foo::vfb),\n                      static_cast<void (Foo::*)()>(nullptr))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(static_cast<void (Foo::*)()>(Foo::A::pq()),\n                      static_cast<void (Foo::*)()>(Foo::B::pq()),\n                      static_cast<void (Foo::*)()>(nullptr))));\n}\n\nTEST(HashValueTest, PairAndTuple) {\n  EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));\n  EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));\n  EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));\n  EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),\n      std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),\n                      std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),\n                      std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),\n                      std::make_tuple(0, 0, -42))));\n\n  // Test that tuples of lvalue references work (so we need a few lvalues):\n  int a = 0, b = 1, c = 17, d = 23;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));\n\n  // Test that tuples of rvalue references work:\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),\n      std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),\n      std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),\n      std::forward_as_tuple(0, 0, -42))));\n}\n\nTEST(HashValueTest, CombineContiguousWorks) {\n  std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};\n  std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};\n\n  auto vh1 = SpyHash(v1);\n  auto vh2 = SpyHash(v2);\n  EXPECT_NE(vh1, vh2);\n}\n\nstruct DummyDeleter {\n  template <typename T>\n  void operator() (T*) {}\n};\n\nstruct SmartPointerEq {\n  template <typename T, typename U>\n  bool operator()(const T& t, const U& u) const {\n    return GetPtr(t) == GetPtr(u);\n  }\n\n  template <typename T>\n  static auto GetPtr(const T& t) -> decltype(&*t) {\n    return t ? &*t : nullptr;\n  }\n\n  static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }\n};\n\nTEST(HashValueTest, SmartPointers) {\n  EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));\n  EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));\n  EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));\n\n  int i, j;\n  std::unique_ptr<int, DummyDeleter> unique1(&i);\n  std::unique_ptr<int, DummyDeleter> unique2(&i);\n  std::unique_ptr<int, DummyDeleter> unique_other(&j);\n  std::unique_ptr<int, DummyDeleter> unique_null;\n\n  std::shared_ptr<int> shared1(&i, DummyDeleter());\n  std::shared_ptr<int> shared2(&i, DummyDeleter());\n  std::shared_ptr<int> shared_other(&j, DummyDeleter());\n  std::shared_ptr<int> shared_null;\n\n  // Sanity check of the Eq function.\n  ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));\n  ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));\n  ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));\n  ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::forward_as_tuple(&i, nullptr,                    //\n                            unique1, unique2, unique_null,  //\n                            absl::make_unique<int>(),       //\n                            shared1, shared2, shared_null,  //\n                            std::make_shared<int>()),\n      SmartPointerEq{}));\n}\n\nTEST(HashValueTest, FunctionPointer) {\n  using Func = int (*)();\n  EXPECT_TRUE(is_hashable<Func>::value);\n\n  Func p1 = [] { return 2; }, p2 = [] { return 1; };\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(p1, p2, nullptr)));\n}\n\nstruct WrapInTuple {\n  template <typename T>\n  std::tuple<int, T, size_t> operator()(const T& t) const {\n    return std::make_tuple(7, t, 0xdeadbeef);\n  }\n};\n\nabsl::Cord FlatCord(absl::string_view sv) {\n  absl::Cord c(sv);\n  c.Flatten();\n  return c;\n}\n\nabsl::Cord FragmentedCord(absl::string_view sv) {\n  if (sv.size() < 2) {\n    return absl::Cord(sv);\n  }\n  size_t halfway = sv.size() / 2;\n  std::vector<absl::string_view> parts = {sv.substr(0, halfway),\n                                          sv.substr(halfway)};\n  return absl::MakeFragmentedCord(parts);\n}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\nTEST(HashValueTest, TestIntrinsicInt128) {\n  EXPECT_TRUE((is_hashable<__int128_t>::value));\n  EXPECT_TRUE((is_hashable<__uint128_t>::value));\n\n  absl::flat_hash_map<size_t, int> hash_to_index;\n  std::vector<__uint128_t> values;\n  for (int i = 0; i < 128; ++i) {\n    // Some arbitrary pattern to check if changing each bit changes the hash.\n    static constexpr __uint128_t kPattern =\n        __uint128_t{0x0123456789abcdef} |\n        (__uint128_t{0x0123456789abcdef} << 64);\n    const __uint128_t value = kPattern ^ (__uint128_t{1} << i);\n    const __int128_t as_signed = static_cast<__int128_t>(value);\n\n    values.push_back(value);\n    auto [it, inserted] =\n        hash_to_index.insert({absl::Hash<__uint128_t>{}(value), i});\n    ASSERT_TRUE(inserted) << \"Duplicate hash: \" << i << \" vs \" << it->second;\n\n    // Verify that the fast-path for MixingHashState does not break the hash.\n    EXPECT_EQ(absl::HashOf(value), absl::Hash<__uint128_t>{}(value));\n    EXPECT_EQ(absl::HashOf(as_signed), absl::Hash<__int128_t>{}(as_signed));\n  }\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(values));\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::vector<__int128_t>(values.begin(), values.end())));\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nTEST(HashValueTest, Strings) {\n  EXPECT_TRUE((is_hashable<std::string>::value));\n\n  const std::string small = \"foo\";\n  const std::string dup = \"foofoo\";\n  const std::string large = std::string(2048, 'x');  // multiple of chunk size\n  const std::string huge = std::string(5000, 'a');   // not a multiple\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::string(), absl::string_view(), absl::Cord(), std::string(\"\"),\n      absl::string_view(\"\"), absl::Cord(\"\"), std::string(small),\n      absl::string_view(small), absl::Cord(small), FragmentedCord(small),\n      std::string(dup), absl::string_view(dup), absl::Cord(dup),\n      std::string(large), absl::string_view(large), absl::Cord(large),\n      std::string(huge), absl::string_view(huge), FlatCord(huge),\n      FragmentedCord(huge))));\n\n  // Also check that nested types maintain the same hash.\n  const WrapInTuple t{};\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      t(std::string()), t(absl::string_view()), t(absl::Cord()),\n      t(std::string(\"\")), t(absl::string_view(\"\")), t(absl::Cord(\"\")),\n      t(std::string(small)), t(absl::string_view(small)), t(absl::Cord(small)),\n      t(FragmentedCord(small)), t(std::string(dup)), t(absl::string_view(dup)),\n      t(absl::Cord(dup)), t(std::string(large)), t(absl::string_view(large)),\n      t(absl::Cord(large)), t(std::string(huge)), t(absl::string_view(huge)),\n      t(FlatCord(huge)), t(FragmentedCord(huge)))));\n\n  // Make sure that hashing a `const char*` does not use its string-value.\n  EXPECT_NE(SpyHash(static_cast<const char*>(\"ABC\")),\n            SpyHash(absl::string_view(\"ABC\")));\n}\n\nTEST(HashValueTest, StringsVector) {\n  using Vec = std::vector<std::string>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      Vec{\"abc\", \"def\"}, Vec{\"abcde\", \"f\"},\n      Vec{\"abcdefghijklmnopqrstuvwxyz\", \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"},\n      Vec{\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY\", \"Z\"})));\n}\n\nTEST(HashValueTest, WString) {\n  EXPECT_TRUE((is_hashable<std::wstring>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::wstring(), std::wstring(L\"ABC\"), std::wstring(L\"ABC\"),\n      std::wstring(L\"Some other different string\"),\n      std::wstring(L\"Iñtërnâtiônàlizætiøn\"))));\n}\n\nTEST(HashValueTest, U16String) {\n  EXPECT_TRUE((is_hashable<std::u16string>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::u16string(), std::u16string(u\"ABC\"), std::u16string(u\"ABC\"),\n      std::u16string(u\"Some other different string\"),\n      std::u16string(u\"Iñtërnâtiônàlizætiøn\"))));\n}\n\nTEST(HashValueTest, U32String) {\n  EXPECT_TRUE((is_hashable<std::u32string>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::u32string(), std::u32string(U\"ABC\"), std::u32string(U\"ABC\"),\n      std::u32string(U\"Some other different string\"),\n      std::u32string(U\"Iñtërnâtiônàlizætiøn\"))));\n}\n\nTEST(HashValueTest, WStringView) {\n  EXPECT_TRUE((is_hashable<std::wstring_view>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      std::wstring_view(), std::wstring_view(L\"ABC\"), std::wstring_view(L\"ABC\"),\n      std::wstring_view(L\"Some other different string_view\"),\n      std::wstring_view(L\"Iñtërnâtiônàlizætiøn\"))));\n}\n\nTEST(HashValueTest, U16StringView) {\n  EXPECT_TRUE((is_hashable<std::u16string_view>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(std::u16string_view(), std::u16string_view(u\"ABC\"),\n                      std::u16string_view(u\"ABC\"),\n                      std::u16string_view(u\"Some other different string_view\"),\n                      std::u16string_view(u\"Iñtërnâtiônàlizætiøn\"))));\n}\n\nTEST(HashValueTest, U32StringView) {\n  EXPECT_TRUE((is_hashable<std::u32string_view>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(std::u32string_view(), std::u32string_view(U\"ABC\"),\n                      std::u32string_view(U\"ABC\"),\n                      std::u32string_view(U\"Some other different string_view\"),\n                      std::u32string_view(U\"Iñtërnâtiônàlizætiøn\"))));\n}\n\nTEST(HashValueTest, StdFilesystemPath) {\n#ifndef ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE\n  GTEST_SKIP() << \"std::filesystem::path is unavailable on this platform\";\n#else\n  EXPECT_TRUE((is_hashable<std::filesystem::path>::value));\n\n  // clang-format off\n  const auto kTestCases = std::make_tuple(\n      std::filesystem::path(),\n      std::filesystem::path(\"/\"),\n#ifndef __GLIBCXX__\n      // libstdc++ has a known issue normalizing \"//\".\n      // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106452\n      std::filesystem::path(\"//\"),\n#endif\n      std::filesystem::path(\"/a/b\"),\n      std::filesystem::path(\"/a//b\"),\n      std::filesystem::path(\"a/b\"),\n      std::filesystem::path(\"a/b/\"),\n      std::filesystem::path(\"a//b\"),\n      std::filesystem::path(\"a//b/\"),\n      std::filesystem::path(\"c:/\"),\n      std::filesystem::path(\"c:\\\\\"),\n      std::filesystem::path(\"c:\\\\/\"),\n      std::filesystem::path(\"c:\\\\//\"),\n      std::filesystem::path(\"c://\"),\n      std::filesystem::path(\"c://\\\\\"),\n      std::filesystem::path(\"/e/p\"),\n      std::filesystem::path(\"/s/../e/p\"),\n      std::filesystem::path(\"e/p\"),\n      std::filesystem::path(\"s/../e/p\"));\n  // clang-format on\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(kTestCases));\n#endif\n}\n\nTEST(HashValueTest, StdArray) {\n  EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));\n}\n\nTEST(HashValueTest, StdBitset) {\n  EXPECT_TRUE((is_hashable<std::bitset<257>>::value));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      {std::bitset<2>(\"00\"), std::bitset<2>(\"01\"), std::bitset<2>(\"10\"),\n       std::bitset<2>(\"11\")}));\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      {std::bitset<5>(\"10101\"), std::bitset<5>(\"10001\"), std::bitset<5>()}));\n\n  constexpr int kNumBits = 256;\n  std::array<std::string, 6> bit_strings;\n  bit_strings.fill(std::string(kNumBits, '1'));\n  bit_strings[1][0] = '0';\n  bit_strings[2][1] = '0';\n  bit_strings[3][kNumBits / 3] = '0';\n  bit_strings[4][kNumBits - 2] = '0';\n  bit_strings[5][kNumBits - 1] = '0';\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      {std::bitset<kNumBits>(bit_strings[0].c_str()),\n       std::bitset<kNumBits>(bit_strings[1].c_str()),\n       std::bitset<kNumBits>(bit_strings[2].c_str()),\n       std::bitset<kNumBits>(bit_strings[3].c_str()),\n       std::bitset<kNumBits>(bit_strings[4].c_str()),\n       std::bitset<kNumBits>(bit_strings[5].c_str())}));\n}  // namespace\n\n// Private type that only supports AbslHashValue to make sure our chosen hash\n// implementation is recursive within absl::Hash.\n// It uses std::abs() on the value to provide different bitwise representations\n// of the same logical value.\nstruct Private {\n  int i;\n  template <typename H>\n  friend H AbslHashValue(H h, Private p) {\n    return H::combine(std::move(h), std::abs(p.i));\n  }\n\n  friend bool operator==(Private a, Private b) {\n    return std::abs(a.i) == std::abs(b.i);\n  }\n\n  friend std::ostream& operator<<(std::ostream& o, Private p) {\n    return o << p.i;\n  }\n};\n\n// Test helper for combine_piecewise_buffer.  It holds a string_view to the\n// buffer-to-be-hashed.  Its AbslHashValue specialization will split up its\n// contents at the character offsets requested.\nclass PiecewiseHashTester {\n public:\n  // Create a hash view of a buffer to be hashed contiguously.\n  explicit PiecewiseHashTester(absl::string_view buf)\n      : buf_(buf), piecewise_(false), split_locations_() {}\n\n  // Create a hash view of a buffer to be hashed piecewise, with breaks at the\n  // given locations.\n  PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations)\n      : buf_(buf),\n        piecewise_(true),\n        split_locations_(std::move(split_locations)) {}\n\n  template <typename H>\n  friend H AbslHashValue(H h, const PiecewiseHashTester& p) {\n    if (!p.piecewise_) {\n      return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size());\n    }\n    absl::hash_internal::PiecewiseCombiner combiner;\n    if (p.split_locations_.empty()) {\n      h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size());\n      return combiner.finalize(std::move(h));\n    }\n    size_t begin = 0;\n    for (size_t next : p.split_locations_) {\n      absl::string_view chunk = p.buf_.substr(begin, next - begin);\n      h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size());\n      begin = next;\n    }\n    absl::string_view last_chunk = p.buf_.substr(begin);\n    if (!last_chunk.empty()) {\n      h = combiner.add_buffer(std::move(h), last_chunk.data(),\n                              last_chunk.size());\n    }\n    return combiner.finalize(std::move(h));\n  }\n\n private:\n  absl::string_view buf_;\n  bool piecewise_;\n  std::set<size_t> split_locations_;\n};\n\n// Dummy object that hashes as two distinct contiguous buffers, \"foo\" followed\n// by \"bar\"\nstruct DummyFooBar {\n  template <typename H>\n  friend H AbslHashValue(H h, const DummyFooBar&) {\n    const char* foo = \"foo\";\n    const char* bar = \"bar\";\n    h = H::combine_contiguous(std::move(h), foo, 3);\n    h = H::combine_contiguous(std::move(h), bar, 3);\n    return h;\n  }\n};\n\nTEST(HashValueTest, CombinePiecewiseBuffer) {\n  absl::Hash<PiecewiseHashTester> hash;\n\n  // Check that hashing an empty buffer through the piecewise API works.\n  EXPECT_EQ(hash(PiecewiseHashTester(\"\")), hash(PiecewiseHashTester(\"\", {})));\n\n  // Similarly, small buffers should give consistent results\n  EXPECT_EQ(hash(PiecewiseHashTester(\"foobar\")),\n            hash(PiecewiseHashTester(\"foobar\", {})));\n  EXPECT_EQ(hash(PiecewiseHashTester(\"foobar\")),\n            hash(PiecewiseHashTester(\"foobar\", {3})));\n\n  // But hashing \"foobar\" in pieces gives a different answer than hashing \"foo\"\n  // contiguously, then \"bar\" contiguously.\n  EXPECT_NE(hash(PiecewiseHashTester(\"foobar\", {3})),\n            absl::Hash<DummyFooBar>()(DummyFooBar{}));\n\n  // Test hashing a large buffer incrementally, broken up in several different\n  // ways.  Arrange for breaks on and near the stride boundaries to look for\n  // off-by-one errors in the implementation.\n  //\n  // This test is run on a buffer that is a multiple of the stride size, and one\n  // that isn't.\n  const size_t kChunkSize = absl::hash_internal::PiecewiseChunkSize();\n  for (size_t big_buffer_size :\n       {2 * kChunkSize + kChunkSize / 2, 3 * kChunkSize}) {\n    SCOPED_TRACE(big_buffer_size);\n    std::string big_buffer;\n    for (size_t i = 0; i < big_buffer_size; ++i) {\n      // Arbitrary string\n      big_buffer.push_back(32 + (i * (i / 3)) % 64);\n    }\n    auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));\n\n    const int possible_breaks = 9;\n    size_t breaks[possible_breaks] = {1,\n                                      kChunkSize / 2,\n                                      kChunkSize - 1,\n                                      kChunkSize,\n                                      kChunkSize + 1,\n                                      kChunkSize + kChunkSize / 2,\n                                      2 * kChunkSize - 1,\n                                      2 * kChunkSize,\n                                      2 * kChunkSize + 1};\n    for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);\n         ++test_mask) {\n      SCOPED_TRACE(test_mask);\n      std::set<size_t> break_locations;\n      for (int j = 0; j < possible_breaks; ++j) {\n        if (test_mask & (1u << j)) {\n          break_locations.insert(breaks[j]);\n        }\n      }\n      ASSERT_EQ(\n          hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),\n          big_buffer_hash);\n    }\n  }\n}\n\nTEST(HashValueTest, PrivateSanity) {\n  // Sanity check that Private is working as the tests below expect it to work.\n  EXPECT_TRUE(is_hashable<Private>::value);\n  EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));\n  EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));\n}\n\nTEST(HashValueTest, Optional) {\n  EXPECT_TRUE(is_hashable<std::optional<Private>>::value);\n\n  using O = std::optional<Private>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));\n}\n\nTEST(HashValueTest, Variant) {\n  using V = std::variant<Private, std::string>;\n  EXPECT_TRUE(is_hashable<V>::value);\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      V(Private{1}), V(Private{-1}), V(Private{2}), V(\"ABC\"), V(\"BCD\"))));\n\n  struct S {};\n  EXPECT_FALSE(is_hashable<std::variant<S>>::value);\n}\n\nTEST(HashValueTest, ReferenceWrapper) {\n  EXPECT_TRUE(is_hashable<std::reference_wrapper<Private>>::value);\n\n  Private p1{1}, p10{10};\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      p1, p10, std::ref(p1), std::ref(p10), std::cref(p1), std::cref(p10))));\n\n  EXPECT_TRUE(is_hashable<std::reference_wrapper<int>>::value);\n  int one = 1, ten = 10;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(\n      one, ten, std::ref(one), std::ref(ten), std::cref(one), std::cref(ten))));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      std::make_tuple(std::tuple<std::reference_wrapper<int>>(std::ref(one)),\n                      std::tuple<std::reference_wrapper<int>>(std::ref(ten)),\n                      std::tuple<int>(one), std::tuple<int>(ten))));\n}\n\ntemplate <typename T, typename = void>\nstruct IsHashCallable : std::false_type {};\n\ntemplate <typename T>\nstruct IsHashCallable<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()(\n                            std::declval<const T&>()))>> : std::true_type {};\n\ntemplate <typename T, typename = void>\nstruct IsAggregateInitializable : std::false_type {};\n\ntemplate <typename T>\nstruct IsAggregateInitializable<T, absl::void_t<decltype(T{})>>\n    : std::true_type {};\n\nTEST(IsHashableTest, ValidHash) {\n  EXPECT_TRUE((is_hashable<int>::value));\n  EXPECT_TRUE(std::is_default_constructible<absl::Hash<int>>::value);\n  EXPECT_TRUE(std::is_copy_constructible<absl::Hash<int>>::value);\n  EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value);\n  EXPECT_TRUE(absl::is_copy_assignable<absl::Hash<int>>::value);\n  EXPECT_TRUE(absl::is_move_assignable<absl::Hash<int>>::value);\n  EXPECT_TRUE(IsHashCallable<int>::value);\n  EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);\n}\n\nTEST(IsHashableTest, PoisonHash) {\n  struct X {};\n  EXPECT_FALSE((is_hashable<X>::value));\n  EXPECT_FALSE(std::is_default_constructible<absl::Hash<X>>::value);\n  EXPECT_FALSE(std::is_copy_constructible<absl::Hash<X>>::value);\n  EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value);\n  EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value);\n  EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value);\n  EXPECT_FALSE(IsHashCallable<X>::value);\n#if !defined(__GNUC__) || defined(__clang__)\n  // TODO(b/144368551): As of GCC 8.4 this does not compile.\n  EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);\n#endif\n}\n\n// Hashable types\n//\n// These types exist simply to exercise various AbslHashValue behaviors, so\n// they are named by what their AbslHashValue overload does.\nstruct NoOp {\n  template <typename HashCode>\n  friend HashCode AbslHashValue(HashCode h, NoOp n) {\n    return h;\n  }\n};\n\nstruct EmptyCombine {\n  template <typename HashCode>\n  friend HashCode AbslHashValue(HashCode h, EmptyCombine e) {\n    return HashCode::combine(std::move(h));\n  }\n};\n\ntemplate <typename Int>\nstruct CombineIterative {\n  template <typename HashCode>\n  friend HashCode AbslHashValue(HashCode h, CombineIterative c) {\n    for (int i = 0; i < 5; ++i) {\n      h = HashCode::combine(std::move(h), Int(i));\n    }\n    return h;\n  }\n};\n\ntemplate <typename Int>\nstruct CombineVariadic {\n  template <typename HashCode>\n  friend HashCode AbslHashValue(HashCode h, CombineVariadic c) {\n    return HashCode::combine(std::move(h), Int(0), Int(1), Int(2), Int(3),\n                             Int(4));\n  }\n};\nenum class InvokeTag {\n  kUniquelyRepresented,\n  kHashValue,\n#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_\n  kLegacyHash,\n#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_\n  kStdHash,\n  kNone\n};\n\ntemplate <InvokeTag T>\nusing InvokeTagConstant = std::integral_constant<InvokeTag, T>;\n\ntemplate <InvokeTag... Tags>\nstruct MinTag;\n\ntemplate <InvokeTag a, InvokeTag b, InvokeTag... Tags>\nstruct MinTag<a, b, Tags...> : MinTag<(a < b ? a : b), Tags...> {};\n\ntemplate <InvokeTag a>\nstruct MinTag<a> : InvokeTagConstant<a> {};\n\ntemplate <InvokeTag... Tags>\nstruct CustomHashType {\n  explicit CustomHashType(size_t val) : value(val) {}\n  size_t value;\n};\n\ntemplate <InvokeTag allowed, InvokeTag... tags>\nstruct EnableIfContained\n    : std::enable_if<absl::disjunction<\n          std::integral_constant<bool, allowed == tags>...>::value> {};\n\ntemplate <\n    typename H, InvokeTag... Tags,\n    typename = typename EnableIfContained<InvokeTag::kHashValue, Tags...>::type>\nH AbslHashValue(H state, CustomHashType<Tags...> t) {\n  static_assert(MinTag<Tags...>::value == InvokeTag::kHashValue, \"\");\n  return H::combine(std::move(state),\n                    t.value + static_cast<int>(InvokeTag::kHashValue));\n}\n\n}  // namespace\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\ntemplate <InvokeTag... Tags>\nstruct is_uniquely_represented<\n    CustomHashType<Tags...>,\n    typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type>\n    : std::true_type {};\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_\nnamespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE {\ntemplate <InvokeTag... Tags>\nstruct hash<CustomHashType<Tags...>> {\n  template <InvokeTag... TagsIn, typename = typename EnableIfContained<\n                                     InvokeTag::kLegacyHash, TagsIn...>::type>\n  size_t operator()(CustomHashType<TagsIn...> t) const {\n    static_assert(MinTag<Tags...>::value == InvokeTag::kLegacyHash, \"\");\n    return t.value + static_cast<int>(InvokeTag::kLegacyHash);\n  }\n};\n}  // namespace ABSL_INTERNAL_LEGACY_HASH_NAMESPACE\n#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_\n\nnamespace std {\ntemplate <InvokeTag... Tags>  // NOLINT\nstruct hash<CustomHashType<Tags...>> {\n  template <InvokeTag... TagsIn, typename = typename EnableIfContained<\n                                     InvokeTag::kStdHash, TagsIn...>::type>\n  size_t operator()(CustomHashType<TagsIn...> t) const {\n    static_assert(MinTag<Tags...>::value == InvokeTag::kStdHash, \"\");\n    return t.value + static_cast<int>(InvokeTag::kStdHash);\n  }\n};\n}  // namespace std\n\nnamespace {\n\ntemplate <typename... T>\nvoid TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>, T...) {\n  using type = CustomHashType<T::value...>;\n  SCOPED_TRACE(testing::PrintToString(std::vector<InvokeTag>{T::value...}));\n  EXPECT_TRUE(is_hashable<type>());\n  EXPECT_TRUE(is_hashable<const type>());\n  EXPECT_TRUE(is_hashable<const type&>());\n\n  const size_t offset = static_cast<int>(std::min({T::value...}));\n  EXPECT_EQ(SpyHash(type(7)), SpyHash(size_t{7 + offset}));\n}\n\nvoid TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {\n  // is_hashable is false if we don't support any of the hooks.\n  using type = CustomHashType<>;\n  EXPECT_FALSE(is_hashable<type>());\n  EXPECT_FALSE(is_hashable<const type>());\n  EXPECT_FALSE(is_hashable<const type&>());\n}\n\ntemplate <InvokeTag Tag, typename... T>\nvoid TestCustomHashType(InvokeTagConstant<Tag> tag, T... t) {\n  constexpr auto next = static_cast<InvokeTag>(static_cast<int>(Tag) + 1);\n  TestCustomHashType(InvokeTagConstant<next>(), tag, t...);\n  TestCustomHashType(InvokeTagConstant<next>(), t...);\n}\n\nTEST(HashTest, CustomHashType) {\n  TestCustomHashType(InvokeTagConstant<InvokeTag{}>());\n}\n\nTEST(HashTest, NoOpsAreEquivalent) {\n  EXPECT_EQ(Hash<NoOp>()({}), Hash<NoOp>()({}));\n  EXPECT_EQ(Hash<NoOp>()({}), Hash<EmptyCombine>()({}));\n}\n\ntemplate <typename T>\nclass HashIntTest : public testing::Test {\n};\nTYPED_TEST_SUITE_P(HashIntTest);\n\nTYPED_TEST_P(HashIntTest, BasicUsage) {\n  EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));\n  EXPECT_NE(Hash<NoOp>()({}),\n            Hash<TypeParam>()(std::numeric_limits<TypeParam>::max()));\n  if (std::numeric_limits<TypeParam>::min() != 0) {\n    EXPECT_NE(Hash<NoOp>()({}),\n              Hash<TypeParam>()(std::numeric_limits<TypeParam>::min()));\n  }\n\n  EXPECT_EQ(Hash<CombineIterative<TypeParam>>()({}),\n            Hash<CombineVariadic<TypeParam>>()({}));\n}\n\nREGISTER_TYPED_TEST_SUITE_P(HashIntTest, BasicUsage);\nusing IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,\n                                uint32_t, uint64_t, size_t>;\nINSTANTIATE_TYPED_TEST_SUITE_P(My, HashIntTest, IntTypes);\n\nstruct StructWithPadding {\n  char c;\n  int i;\n\n  template <typename H>\n  friend H AbslHashValue(H hash_state, const StructWithPadding& s) {\n    return H::combine(std::move(hash_state), s.c, s.i);\n  }\n};\n\nstatic_assert(sizeof(StructWithPadding) > sizeof(char) + sizeof(int),\n              \"StructWithPadding doesn't have padding\");\nstatic_assert(std::is_standard_layout<StructWithPadding>::value, \"\");\n\n// This check has to be disabled because libstdc++ doesn't support it.\n// static_assert(std::is_trivially_constructible<StructWithPadding>::value, \"\");\n\ntemplate <typename T>\nstruct ArraySlice {\n  T* begin;\n  T* end;\n\n  template <typename H>\n  friend H AbslHashValue(H hash_state, const ArraySlice& slice) {\n    for (auto t = slice.begin; t != slice.end; ++t) {\n      hash_state = H::combine(std::move(hash_state), *t);\n    }\n    return hash_state;\n  }\n};\n\nTEST(HashTest, HashNonUniquelyRepresentedType) {\n  // Create equal StructWithPadding objects that are known to have non-equal\n  // padding bytes.\n  static const size_t kNumStructs = 10;\n  unsigned char buffer1[kNumStructs * sizeof(StructWithPadding)];\n  std::memset(buffer1, 0, sizeof(buffer1));\n  auto* s1 = reinterpret_cast<StructWithPadding*>(buffer1);\n\n  unsigned char buffer2[kNumStructs * sizeof(StructWithPadding)];\n  std::memset(buffer2, 255, sizeof(buffer2));\n  auto* s2 = reinterpret_cast<StructWithPadding*>(buffer2);\n  for (size_t i = 0; i < kNumStructs; ++i) {\n    SCOPED_TRACE(i);\n    s1[i].c = s2[i].c = static_cast<char>('0' + i);\n    s1[i].i = s2[i].i = static_cast<int>(i);\n    ASSERT_FALSE(memcmp(buffer1 + i * sizeof(StructWithPadding),\n                        buffer2 + i * sizeof(StructWithPadding),\n                        sizeof(StructWithPadding)) == 0)\n        << \"Bug in test code: objects do not have unequal\"\n        << \" object representations\";\n  }\n\n  EXPECT_EQ(Hash<StructWithPadding>()(s1[0]), Hash<StructWithPadding>()(s2[0]));\n  EXPECT_EQ(Hash<ArraySlice<StructWithPadding>>()({s1, s1 + kNumStructs}),\n            Hash<ArraySlice<StructWithPadding>>()({s2, s2 + kNumStructs}));\n}\n\nTEST(HashTest, StandardHashContainerUsage) {\n  std::unordered_map<int, std::string, Hash<int>> map = {{0, \"foo\"},\n                                                         {42, \"bar\"}};\n\n  EXPECT_NE(map.find(0), map.end());\n  EXPECT_EQ(map.find(1), map.end());\n  EXPECT_NE(map.find(0u), map.end());\n}\n\nstruct ConvertibleFromNoOp {\n  ConvertibleFromNoOp(NoOp) {}  // NOLINT(runtime/explicit)\n\n  template <typename H>\n  friend H AbslHashValue(H hash_state, ConvertibleFromNoOp) {\n    return H::combine(std::move(hash_state), 1);\n  }\n};\n\nTEST(HashTest, HeterogeneousCall) {\n  EXPECT_NE(Hash<ConvertibleFromNoOp>()(NoOp()),\n            Hash<NoOp>()(NoOp()));\n}\n\nTEST(IsUniquelyRepresentedTest, SanityTest) {\n  using absl::hash_internal::is_uniquely_represented;\n\n  EXPECT_TRUE(is_uniquely_represented<unsigned char>::value);\n  EXPECT_TRUE(is_uniquely_represented<int>::value);\n  EXPECT_FALSE(is_uniquely_represented<bool>::value);\n  EXPECT_FALSE(is_uniquely_represented<int*>::value);\n}\n\nstruct IntAndString {\n  int i;\n  std::string s;\n\n  template <typename H>\n  friend H AbslHashValue(H hash_state, IntAndString int_and_string) {\n    return H::combine(std::move(hash_state), int_and_string.s,\n                      int_and_string.i);\n  }\n};\n\nTEST(HashTest, SmallValueOn64ByteBoundary) {\n  Hash<IntAndString>()(IntAndString{0, std::string(63, '0')});\n}\n\nTEST(HashTest, TypeErased) {\n  EXPECT_TRUE((is_hashable<TypeErasedValue<size_t>>::value));\n  EXPECT_TRUE((is_hashable<std::pair<TypeErasedValue<size_t>, int>>::value));\n\n  EXPECT_EQ(SpyHash(TypeErasedValue<size_t>(7)), SpyHash(size_t{7}));\n  EXPECT_NE(SpyHash(TypeErasedValue<size_t>(7)), SpyHash(size_t{13}));\n\n  EXPECT_EQ(SpyHash(std::make_pair(TypeErasedValue<size_t>(7), 17)),\n            SpyHash(std::make_pair(size_t{7}, 17)));\n\n  absl::flat_hash_set<absl::flat_hash_set<int>> ss = {{1, 2}, {3, 4}};\n  TypeErasedContainer<absl::flat_hash_set<absl::flat_hash_set<int>>> es = {\n      absl::flat_hash_set<int>{1, 2}, {3, 4}};\n  absl::flat_hash_set<TypeErasedContainer<absl::flat_hash_set<int>>> se = {\n      {1, 2}, {3, 4}};\n  EXPECT_EQ(SpyHash(ss), SpyHash(es));\n  EXPECT_EQ(SpyHash(ss), SpyHash(se));\n}\n\nstruct ValueWithBoolConversion {\n  operator bool() const { return false; }\n  int i;\n};\n\n}  // namespace\nnamespace std {\ntemplate <>\nstruct hash<ValueWithBoolConversion> {\n  size_t operator()(ValueWithBoolConversion v) {\n    return static_cast<size_t>(v.i);\n  }\n};\n}  // namespace std\n\nnamespace {\n\nTEST(HashTest, DoesNotUseImplicitConversionsToBool) {\n  EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),\n            absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));\n}\n\nTEST(HashOf, MatchesHashForSingleArgument) {\n  std::string s = \"forty two\";\n  double d = 42.0;\n  std::tuple<int, int> t{4, 2};\n  int i = 42;\n  int neg_i = -42;\n  int16_t i16 = 42;\n  int16_t neg_i16 = -42;\n  int8_t i8 = 42;\n  int8_t neg_i8 = -42;\n\n  EXPECT_EQ(absl::HashOf(s), absl::Hash<std::string>{}(s));\n  EXPECT_EQ(absl::HashOf(d), absl::Hash<double>{}(d));\n  EXPECT_EQ(absl::HashOf(t), (absl::Hash<std::tuple<int, int>>{}(t)));\n  EXPECT_EQ(absl::HashOf(i), absl::Hash<int>{}(i));\n  EXPECT_EQ(absl::HashOf(neg_i), absl::Hash<int>{}(neg_i));\n  EXPECT_EQ(absl::HashOf(i16), absl::Hash<int16_t>{}(i16));\n  EXPECT_EQ(absl::HashOf(neg_i16), absl::Hash<int16_t>{}(neg_i16));\n  EXPECT_EQ(absl::HashOf(i8), absl::Hash<int8_t>{}(i8));\n  EXPECT_EQ(absl::HashOf(neg_i8), absl::Hash<int8_t>{}(neg_i8));\n}\n\nTEST(HashOf, MatchesHashOfTupleForMultipleArguments) {\n  std::string hello = \"hello\";\n  std::string world = \"world\";\n\n  EXPECT_EQ(absl::HashOf(), absl::HashOf(std::make_tuple()));\n  EXPECT_EQ(absl::HashOf(hello), absl::HashOf(std::make_tuple(hello)));\n  EXPECT_EQ(absl::HashOf(hello, world),\n            absl::HashOf(std::make_tuple(hello, world)));\n}\n\ntemplate <typename T>\nstd::true_type HashOfExplicitParameter(decltype(absl::HashOf<T>(0))) {\n  return {};\n}\ntemplate <typename T>\nstd::false_type HashOfExplicitParameter(size_t) {\n  return {};\n}\n\nTEST(HashOf, CantPassExplicitTemplateParameters) {\n  EXPECT_FALSE(HashOfExplicitParameter<int>(0));\n}\n\nstruct TypeErasedHashStateUser {\n  int a;\n  std::string b;\n\n  template <typename H>\n  friend H AbslHashValue(H state, const TypeErasedHashStateUser& value) {\n    absl::HashState type_erased_state = absl::HashState::Create(&state);\n    absl::HashState::combine(std::move(type_erased_state), value.a, value.b);\n    return state;\n  }\n};\n\nTEST(HashOf, MatchesTypeErasedHashState) {\n  std::string s = \"s\";\n  EXPECT_EQ(absl::HashOf(1, s), absl::Hash<TypeErasedHashStateUser>{}(\n                                    TypeErasedHashStateUser{1, s}));\n}\n\nstruct AutoReturnTypeUser {\n  int a;\n  std::string b;\n\n  template <typename H>\n  friend auto AbslHashValue(H state, const AutoReturnTypeUser& value) {\n    return H::combine(std::move(state), value.a, value.b);\n  }\n};\n\nTEST(HashOf, AutoReturnTypeUser) {\n  std::string s = \"s\";\n  EXPECT_EQ(absl::HashOf(1, s),\n            absl::Hash<AutoReturnTypeUser>{}(AutoReturnTypeUser{1, s}));\n}\n\nTEST(HashOf, DoubleSignCollision) {\n  // These values differ only in their most significant bit.\n  EXPECT_NE(absl::HashOf(-1.0), absl::HashOf(1.0));\n}\n\n// Test for collisions in short strings if PrecombineLengthMix is low quality.\nTEST(PrecombineLengthMix, ShortStringCollision) {\n#if defined(__wasm__)\n  GTEST_SKIP() << \"Fails flakily on wasm due to no ASLR and 32-bit size_t.\";\n#endif\n  std::string s1 = \"00\";\n  std::string s2 = \"000\";\n  constexpr char kMinChar = 0;\n  constexpr char kMaxChar = 32;\n  for (s1[0] = kMinChar; s1[0] < kMaxChar; ++s1[0]) {\n    for (s1[1] = kMinChar; s1[1] < kMaxChar; ++s1[1]) {\n      for (s2[0] = kMinChar; s2[0] < kMaxChar; ++s2[0]) {\n        for (s2[1] = kMinChar; s2[1] < kMaxChar; ++s2[1]) {\n          for (s2[2] = kMinChar; s2[2] < kMaxChar; ++s2[2]) {\n            ASSERT_NE(absl::HashOf(s1), absl::HashOf(s2))\n                << \"s1[0]: \" << static_cast<int>(s1[0])\n                << \"; s1[1]: \" << static_cast<int>(s1[1])\n                << \"; s2[0]: \" << static_cast<int>(s2[0])\n                << \"; s2[1]: \" << static_cast<int>(s2[1])\n                << \"; s2[2]: \" << static_cast<int>(s2[2]);\n          }\n        }\n      }\n    }\n  }\n}\n\n// Test that we don't cause excessive collisions on the hash table for\n// doubles in the range [-1024, 1024]. See cl/773069881 for more information.\nTEST(SwisstableCollisions, DoubleRange) {\n  absl::flat_hash_set<double> set;\n  for (double t = -1024.0; t < 1024.0; t += 1.0) {\n    set.insert(t);\n    ASSERT_LT(HashtableDebugAccess<decltype(set)>::GetNumProbes(set, t), 64)\n        << t;\n  }\n}\n\n// Test that for each pair of adjacent bytes in a string, if there's only\n// entropy in those two bytes, then we don't have excessive collisions.\nTEST(SwisstableCollisions, LowEntropyStrings) {\n  constexpr char kMinChar = 0;\n  constexpr char kMaxChar = 64;\n  // These sizes cover the different hashing cases.\n  for (size_t size : {8u, 16u, 32u, 64u, 128u}) {\n    for (size_t b = 0; b < size - 1; ++b) {\n      absl::flat_hash_set<std::string> set;\n      std::string s(size, '\\0');\n      for (char c1 = kMinChar; c1 < kMaxChar; ++c1) {\n        for (char c2 = kMinChar; c2 < kMaxChar; ++c2) {\n          s[b] = c1;\n          s[b + 1] = c2;\n          set.insert(s);\n          ASSERT_LT(HashtableDebugAccess<decltype(set)>::GetNumProbes(set, s),\n                    64)\n              << \"size: \" << size << \"; bit: \" << b;\n        }\n      }\n    }\n  }\n}\n\n// Test that we don't have excessive collisions when keys are consecutive\n// integers rotated by N bits.\nTEST(SwisstableCollisions, LowEntropyInts) {\n  constexpr int kSizeTBits = sizeof(size_t) * 8;\n  for (int bit = 0; bit < kSizeTBits; ++bit) {\n    absl::flat_hash_set<size_t> set;\n    for (size_t i = 0; i < 128 * 1024; ++i) {\n      size_t v = absl::rotl(i, bit);\n      set.insert(v);\n      ASSERT_LT(HashtableDebugAccess<decltype(set)>::GetNumProbes(set, v), 48)\n          << bit << \" \" << i;\n    }\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/hash/hash_testing.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_HASH_HASH_TESTING_H_\n#define ABSL_HASH_HASH_TESTING_H_\n\n#include <cstddef>\n#include <initializer_list>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <variant>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/hash/internal/spy_hash_state.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/types/variant.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Run the absl::Hash algorithm over all the elements passed in and verify that\n// their hash expansion is congruent with their `==` operator.\n//\n// It is used in conjunction with EXPECT_TRUE. Failures will output information\n// on what requirement failed and on which objects.\n//\n// Users should pass a collection of types as either an initializer list or a\n// container of cases.\n//\n//   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n//       {v1, v2, ..., vN}));\n//\n//   std::vector<MyType> cases;\n//   // Fill cases...\n//   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));\n//\n// Users can pass a variety of types for testing heterogeneous lookup with\n// `std::make_tuple`:\n//\n//   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n//       std::make_tuple(v1, v2, ..., vN)));\n//\n//\n// Ideally, the values passed should provide enough coverage of the `==`\n// operator and the AbslHashValue implementations.\n// For dynamically sized types, the empty state should usually be included in\n// the values.\n//\n// The function accepts an optional comparator function, in case that `==` is\n// not enough for the values provided.\n//\n// Usage:\n//\n//   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n//       std::make_tuple(v1, v2, ..., vN), MyCustomEq{}));\n//\n// It checks the following requirements:\n//   1. The expansion for a value is deterministic.\n//   2. For any two objects `a` and `b` in the sequence, if `a == b` evaluates\n//      to true, then their hash expansion must be equal.\n//   3. If `a == b` evaluates to false their hash expansion must be unequal.\n//   4. If `a == b` evaluates to false neither hash expansion can be a\n//      suffix of the other.\n//   5. AbslHashValue overloads should not be called by the user. They are only\n//      meant to be called by the framework. Users should call H::combine() and\n//      H::combine_contiguous().\n//   6. No moved-from instance of the hash state is used in the implementation\n//      of AbslHashValue.\n//\n// The values do not have to have the same type. This can be useful for\n// equivalent types that support heterogeneous lookup.\n//\n// A possible reason for breaking (2) is combining state in the hash expansion\n// that was not used in `==`.\n// For example:\n//\n// struct Bad2 {\n//   int a, b;\n//   template <typename H>\n//   friend H AbslHashValue(H state, Bad2 x) {\n//     // Uses a and b.\n//     return H::combine(std::move(state), x.a, x.b);\n//   }\n//   friend bool operator==(Bad2 x, Bad2 y) {\n//     // Only uses a.\n//     return x.a == y.a;\n//   }\n// };\n//\n// As for (3), breaking this usually means that there is state being passed to\n// the `==` operator that is not used in the hash expansion.\n// For example:\n//\n// struct Bad3 {\n//   int a, b;\n//   template <typename H>\n//   friend H AbslHashValue(H state, Bad3 x) {\n//     // Only uses a.\n//     return H::combine(std::move(state), x.a);\n//   }\n//   friend bool operator==(Bad3 x, Bad3 y) {\n//     // Uses a and b.\n//     return x.a == y.a && x.b == y.b;\n//   }\n// };\n//\n// Finally, a common way to break 4 is by combining dynamic ranges without\n// combining the size of the range.\n// For example:\n//\n// struct Bad4 {\n//   int *p, size;\n//   template <typename H>\n//   friend H AbslHashValue(H state, Bad4 x) {\n//     return H::combine_contiguous(std::move(state), x.p, x.p + x.size);\n//   }\n//   friend bool operator==(Bad4 x, Bad4 y) {\n//    // Compare two ranges for equality. C++14 code can instead use std::equal.\n//     return absl::equal(x.p, x.p + x.size, y.p, y.p + y.size);\n//   }\n// };\n//\n// An easy solution to this is to combine the size after combining the range,\n// like so:\n// template <typename H>\n// friend H AbslHashValue(H state, Bad4 x) {\n//   return H::combine(\n//       H::combine_contiguous(std::move(state), x.p, x.p + x.size), x.size);\n// }\n//\ntemplate <int&... ExplicitBarrier, typename Container>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    const Container& values);\n\ntemplate <int&... ExplicitBarrier, typename Container, typename Eq>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    const Container& values, Eq equals);\n\ntemplate <int&..., typename T>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    std::initializer_list<T> values);\n\ntemplate <int&..., typename T, typename Eq>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    std::initializer_list<T> values, Eq equals);\n\nnamespace hash_internal {\n\nstruct PrintVisitor {\n  size_t index;\n  template <typename T>\n  std::string operator()(const T* value) const {\n    return absl::StrCat(\"#\", index, \"(\", testing::PrintToString(*value), \")\");\n  }\n};\n\ntemplate <typename Eq>\nstruct EqVisitor {\n  Eq eq;\n  template <typename T, typename U>\n  bool operator()(const T* t, const U* u) const {\n    return eq(*t, *u);\n  }\n};\n\nstruct ExpandVisitor {\n  template <typename T>\n  SpyHashState operator()(const T* value) const {\n    return SpyHashState::combine(SpyHashState(), *value);\n  }\n};\n\ntemplate <typename Container, typename Eq>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    const Container& values, Eq equals) {\n  using V = typename Container::value_type;\n\n  struct Info {\n    const V& value;\n    size_t index;\n    std::string ToString() const {\n      return std::visit(PrintVisitor{index}, value);\n    }\n    SpyHashState expand() const { return std::visit(ExpandVisitor{}, value); }\n  };\n\n  using EqClass = std::vector<Info>;\n  std::vector<EqClass> classes;\n\n  // Gather the values in equivalence classes.\n  size_t i = 0;\n  for (const auto& value : values) {\n    EqClass* c = nullptr;\n    for (auto& eqclass : classes) {\n      if (std::visit(EqVisitor<Eq>{equals}, value, eqclass[0].value)) {\n        c = &eqclass;\n        break;\n      }\n    }\n    if (c == nullptr) {\n      classes.emplace_back();\n      c = &classes.back();\n    }\n    c->push_back({value, i});\n    ++i;\n\n    // Verify potential errors captured by SpyHashState.\n    if (auto error = c->back().expand().error()) {\n      return testing::AssertionFailure() << *error;\n    }\n  }\n\n  if (classes.size() < 2) {\n    return testing::AssertionFailure()\n           << \"At least two equivalence classes are expected.\";\n  }\n\n  // We assume that equality is correctly implemented.\n  // Now we verify that AbslHashValue is also correctly implemented.\n\n  for (const auto& c : classes) {\n    // All elements of the equivalence class must have the same hash\n    // expansion.\n    const SpyHashState expected = c[0].expand();\n    for (const Info& v : c) {\n      if (v.expand() != v.expand()) {\n        return testing::AssertionFailure()\n               << \"Hash expansion for \" << v.ToString()\n               << \" is non-deterministic.\";\n      }\n      if (v.expand() != expected) {\n        return testing::AssertionFailure()\n               << \"Values \" << c[0].ToString() << \" and \" << v.ToString()\n               << \" evaluate as equal but have unequal hash expansions (\"\n               << expected << \" vs. \" << v.expand() << \").\";\n      }\n    }\n\n    // Elements from other classes must have different hash expansion.\n    for (const auto& c2 : classes) {\n      if (&c == &c2) continue;\n      const SpyHashState c2_hash = c2[0].expand();\n      switch (SpyHashState::Compare(expected, c2_hash)) {\n        case SpyHashState::CompareResult::kEqual:\n          return testing::AssertionFailure()\n                 << \"Values \" << c[0].ToString() << \" and \" << c2[0].ToString()\n                 << \" evaluate as unequal but have an equal hash expansion:\"\n                 << c2_hash << \".\";\n        case SpyHashState::CompareResult::kBSuffixA:\n          return testing::AssertionFailure()\n                 << \"Hash expansion of \" << c2[0].ToString() << \";\" << c2_hash\n                 << \" is a suffix of the hash expansion of \" << c[0].ToString()\n                 << \";\" << expected << \".\";\n        case SpyHashState::CompareResult::kASuffixB:\n          return testing::AssertionFailure()\n                 << \"Hash expansion of \" << c[0].ToString() << \";\"\n                 << expected << \" is a suffix of the hash expansion of \"\n                 << c2[0].ToString() << \";\" << c2_hash << \".\";\n        case SpyHashState::CompareResult::kUnequal:\n          break;\n      }\n    }\n  }\n  return testing::AssertionSuccess();\n}\n\ntemplate <typename... T>\nstruct TypeSet {\n  template <typename U, bool = disjunction<std::is_same<T, U>...>::value>\n  struct Insert {\n    using type = TypeSet<U, T...>;\n  };\n  template <typename U>\n  struct Insert<U, true> {\n    using type = TypeSet;\n  };\n\n  template <template <typename...> class C>\n  using apply = C<T...>;\n};\n\ntemplate <typename... T>\nstruct MakeTypeSet : TypeSet<> {};\ntemplate <typename T, typename... Ts>\nstruct MakeTypeSet<T, Ts...> : MakeTypeSet<Ts...>::template Insert<T>::type {};\n\ntemplate <typename... T>\nusing VariantForTypes = typename MakeTypeSet<\n    const typename std::decay<T>::type*...>::template apply<std::variant>;\n\ntemplate <typename Container>\nstruct ContainerAsVector {\n  using V = std::variant<const typename Container::value_type*>;\n  using Out = std::vector<V>;\n\n  static Out Do(const Container& values) {\n    Out out;\n    for (const auto& v : values) out.push_back(&v);\n    return out;\n  }\n};\n\ntemplate <typename... T>\nstruct ContainerAsVector<std::tuple<T...>> {\n  using V = VariantForTypes<T...>;\n  using Out = std::vector<V>;\n\n  template <size_t... I>\n  static Out DoImpl(const std::tuple<T...>& tuple, absl::index_sequence<I...>) {\n    return Out{&std::get<I>(tuple)...};\n  }\n\n  static Out Do(const std::tuple<T...>& values) {\n    return DoImpl(values, absl::index_sequence_for<T...>());\n  }\n};\n\ntemplate <>\nstruct ContainerAsVector<std::tuple<>> {\n  static std::vector<VariantForTypes<int>> Do(std::tuple<>) { return {}; }\n};\n\nstruct DefaultEquals {\n  template <typename T, typename U>\n  bool operator()(const T& t, const U& u) const {\n    return t == u;\n  }\n};\n\n}  // namespace hash_internal\n\ntemplate <int&..., typename Container>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    const Container& values) {\n  return hash_internal::VerifyTypeImplementsAbslHashCorrectly(\n      hash_internal::ContainerAsVector<Container>::Do(values),\n      hash_internal::DefaultEquals{});\n}\n\ntemplate <int&..., typename Container, typename Eq>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    const Container& values, Eq equals) {\n  return hash_internal::VerifyTypeImplementsAbslHashCorrectly(\n      hash_internal::ContainerAsVector<Container>::Do(values), equals);\n}\n\ntemplate <int&..., typename T>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    std::initializer_list<T> values) {\n  return hash_internal::VerifyTypeImplementsAbslHashCorrectly(\n      hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),\n      hash_internal::DefaultEquals{});\n}\n\ntemplate <int&..., typename T, typename Eq>\ntesting::AssertionResult VerifyTypeImplementsAbslHashCorrectly(\n    std::initializer_list<T> values, Eq equals) {\n  return hash_internal::VerifyTypeImplementsAbslHashCorrectly(\n      hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),\n      equals);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HASH_HASH_TESTING_H_\n"
  },
  {
    "path": "absl/hash/internal/city.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file provides CityHash64() and related functions.\n//\n// It's probably possible to create even faster hash functions by\n// writing a program that systematically explores some of the space of\n// possible hash functions, by using SIMD instructions, or by\n// compromising on hash quality.\n\n#include \"absl/hash/internal/city.h\"\n\n#include <algorithm>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/unaligned_access.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/numeric/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\n\n#ifdef ABSL_IS_BIG_ENDIAN\n#define uint32_in_expected_order(x) (absl::gbswap_32(x))\n#define uint64_in_expected_order(x) (absl::gbswap_64(x))\n#else\n#define uint32_in_expected_order(x) (x)\n#define uint64_in_expected_order(x) (x)\n#endif\n\nstatic uint64_t Fetch64(const char *p) {\n  return uint64_in_expected_order(ABSL_INTERNAL_UNALIGNED_LOAD64(p));\n}\n\nstatic uint32_t Fetch32(const char *p) {\n  return uint32_in_expected_order(ABSL_INTERNAL_UNALIGNED_LOAD32(p));\n}\n\n// Some primes between 2^63 and 2^64 for various uses.\nstatic const uint64_t k0 = 0xc3a5c85c97cb3127ULL;\nstatic const uint64_t k1 = 0xb492b66fbe98f273ULL;\nstatic const uint64_t k2 = 0x9ae16a3b2f90404fULL;\n\n// Magic numbers for 32-bit hashing.  Copied from Murmur3.\nstatic const uint32_t c1 = 0xcc9e2d51;\nstatic const uint32_t c2 = 0x1b873593;\n\n// A 32-bit to 32-bit integer hash copied from Murmur3.\nstatic uint32_t fmix(uint32_t h) {\n  h ^= h >> 16;\n  h *= 0x85ebca6b;\n  h ^= h >> 13;\n  h *= 0xc2b2ae35;\n  h ^= h >> 16;\n  return h;\n}\n\n#undef PERMUTE3\n#define PERMUTE3(a, b, c) \\\n  do {                    \\\n    std::swap(a, b);      \\\n    std::swap(a, c);      \\\n  } while (0)\n\nstatic uint32_t Mur(uint32_t a, uint32_t h) {\n  // Helper from Murmur3 for combining two 32-bit values.\n  a *= c1;\n  a = absl::rotr(a, 17);\n  a *= c2;\n  h ^= a;\n  h = absl::rotr(h, 19);\n  return h * 5 + 0xe6546b64;\n}\n\nstatic uint32_t Hash32Len13to24(const char *s, size_t len) {\n  uint32_t a = Fetch32(s - 4 + (len >> 1));\n  uint32_t b = Fetch32(s + 4);\n  uint32_t c = Fetch32(s + len - 8);\n  uint32_t d = Fetch32(s + (len >> 1));\n  uint32_t e = Fetch32(s);\n  uint32_t f = Fetch32(s + len - 4);\n  uint32_t h = static_cast<uint32_t>(len);\n\n  return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));\n}\n\nstatic uint32_t Hash32Len0to4(const char *s, size_t len) {\n  uint32_t b = 0;\n  uint32_t c = 9;\n  for (size_t i = 0; i < len; i++) {\n    signed char v = static_cast<signed char>(s[i]);\n    b = b * c1 + static_cast<uint32_t>(v);\n    c ^= b;\n  }\n  return fmix(Mur(b, Mur(static_cast<uint32_t>(len), c)));\n}\n\nstatic uint32_t Hash32Len5to12(const char *s, size_t len) {\n  uint32_t a = static_cast<uint32_t>(len), b = a * 5, c = 9, d = b;\n  a += Fetch32(s);\n  b += Fetch32(s + len - 4);\n  c += Fetch32(s + ((len >> 1) & 4));\n  return fmix(Mur(c, Mur(b, Mur(a, d))));\n}\n\nuint32_t CityHash32(const char *s, size_t len) {\n  if (len <= 24) {\n    return len <= 12\n               ? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len))\n               : Hash32Len13to24(s, len);\n  }\n\n  // len > 24\n  uint32_t h = static_cast<uint32_t>(len), g = c1 * h, f = g;\n\n  uint32_t a0 = absl::rotr(Fetch32(s + len - 4) * c1, 17) * c2;\n  uint32_t a1 = absl::rotr(Fetch32(s + len - 8) * c1, 17) * c2;\n  uint32_t a2 = absl::rotr(Fetch32(s + len - 16) * c1, 17) * c2;\n  uint32_t a3 = absl::rotr(Fetch32(s + len - 12) * c1, 17) * c2;\n  uint32_t a4 = absl::rotr(Fetch32(s + len - 20) * c1, 17) * c2;\n  h ^= a0;\n  h = absl::rotr(h, 19);\n  h = h * 5 + 0xe6546b64;\n  h ^= a2;\n  h = absl::rotr(h, 19);\n  h = h * 5 + 0xe6546b64;\n  g ^= a1;\n  g = absl::rotr(g, 19);\n  g = g * 5 + 0xe6546b64;\n  g ^= a3;\n  g = absl::rotr(g, 19);\n  g = g * 5 + 0xe6546b64;\n  f += a4;\n  f = absl::rotr(f, 19);\n  f = f * 5 + 0xe6546b64;\n  size_t iters = (len - 1) / 20;\n  do {\n    uint32_t b0 = absl::rotr(Fetch32(s) * c1, 17) * c2;\n    uint32_t b1 = Fetch32(s + 4);\n    uint32_t b2 = absl::rotr(Fetch32(s + 8) * c1, 17) * c2;\n    uint32_t b3 = absl::rotr(Fetch32(s + 12) * c1, 17) * c2;\n    uint32_t b4 = Fetch32(s + 16);\n    h ^= b0;\n    h = absl::rotr(h, 18);\n    h = h * 5 + 0xe6546b64;\n    f += b1;\n    f = absl::rotr(f, 19);\n    f = f * c1;\n    g += b2;\n    g = absl::rotr(g, 18);\n    g = g * 5 + 0xe6546b64;\n    h ^= b3 + b1;\n    h = absl::rotr(h, 19);\n    h = h * 5 + 0xe6546b64;\n    g ^= b4;\n    g = absl::gbswap_32(g) * 5;\n    h += b4 * 5;\n    h = absl::gbswap_32(h);\n    f += b0;\n    PERMUTE3(f, h, g);\n    s += 20;\n  } while (--iters != 0);\n  g = absl::rotr(g, 11) * c1;\n  g = absl::rotr(g, 17) * c1;\n  f = absl::rotr(f, 11) * c1;\n  f = absl::rotr(f, 17) * c1;\n  h = absl::rotr(h + g, 19);\n  h = h * 5 + 0xe6546b64;\n  h = absl::rotr(h, 17) * c1;\n  h = absl::rotr(h + f, 19);\n  h = h * 5 + 0xe6546b64;\n  h = absl::rotr(h, 17) * c1;\n  return h;\n}\n\nstatic uint64_t ShiftMix(uint64_t val) { return val ^ (val >> 47); }\n\nstatic uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {\n  // Murmur-inspired hashing.\n  uint64_t a = (u ^ v) * mul;\n  a ^= (a >> 47);\n  uint64_t b = (v ^ a) * mul;\n  b ^= (b >> 47);\n  b *= mul;\n  return b;\n}\n\nstatic uint64_t HashLen16(uint64_t u, uint64_t v) {\n  const uint64_t kMul = 0x9ddfea08eb382d69ULL;\n  return HashLen16(u, v, kMul);\n}\n\nstatic uint64_t HashLen0to16(const char *s, size_t len) {\n  if (len >= 8) {\n    uint64_t mul = k2 + len * 2;\n    uint64_t a = Fetch64(s) + k2;\n    uint64_t b = Fetch64(s + len - 8);\n    uint64_t c = absl::rotr(b, 37) * mul + a;\n    uint64_t d = (absl::rotr(a, 25) + b) * mul;\n    return HashLen16(c, d, mul);\n  }\n  if (len >= 4) {\n    uint64_t mul = k2 + len * 2;\n    uint64_t a = Fetch32(s);\n    return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);\n  }\n  if (len > 0) {\n    uint8_t a = static_cast<uint8_t>(s[0]);\n    uint8_t b = static_cast<uint8_t>(s[len >> 1]);\n    uint8_t c = static_cast<uint8_t>(s[len - 1]);\n    uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);\n    uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);\n    return ShiftMix(y * k2 ^ z * k0) * k2;\n  }\n  return k2;\n}\n\n// This probably works well for 16-byte strings as well, but it may be overkill\n// in that case.\nstatic uint64_t HashLen17to32(const char *s, size_t len) {\n  uint64_t mul = k2 + len * 2;\n  uint64_t a = Fetch64(s) * k1;\n  uint64_t b = Fetch64(s + 8);\n  uint64_t c = Fetch64(s + len - 8) * mul;\n  uint64_t d = Fetch64(s + len - 16) * k2;\n  return HashLen16(absl::rotr(a + b, 43) + absl::rotr(c, 30) + d,\n                   a + absl::rotr(b + k2, 18) + c, mul);\n}\n\n// Return a 16-byte hash for 48 bytes.  Quick and dirty.\n// Callers do best to use \"random-looking\" values for a and b.\nstatic std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(\n    uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) {\n  a += w;\n  b = absl::rotr(b + a + z, 21);\n  uint64_t c = a;\n  a += x;\n  a += y;\n  b += absl::rotr(a, 44);\n  return std::make_pair(a + z, b + c);\n}\n\n// Return a 16-byte hash for s[0] ... s[31], a, and b.  Quick and dirty.\nstatic std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s,\n                                                            uint64_t a,\n                                                            uint64_t b) {\n  return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),\n                                Fetch64(s + 24), a, b);\n}\n\n// Return an 8-byte hash for 33 to 64 bytes.\nstatic uint64_t HashLen33to64(const char *s, size_t len) {\n  uint64_t mul = k2 + len * 2;\n  uint64_t a = Fetch64(s) * k2;\n  uint64_t b = Fetch64(s + 8);\n  uint64_t c = Fetch64(s + len - 24);\n  uint64_t d = Fetch64(s + len - 32);\n  uint64_t e = Fetch64(s + 16) * k2;\n  uint64_t f = Fetch64(s + 24) * 9;\n  uint64_t g = Fetch64(s + len - 8);\n  uint64_t h = Fetch64(s + len - 16) * mul;\n  uint64_t u = absl::rotr(a + g, 43) + (absl::rotr(b, 30) + c) * 9;\n  uint64_t v = ((a + g) ^ d) + f + 1;\n  uint64_t w = absl::gbswap_64((u + v) * mul) + h;\n  uint64_t x = absl::rotr(e + f, 42) + c;\n  uint64_t y = (absl::gbswap_64((v + w) * mul) + g) * mul;\n  uint64_t z = e + f + c;\n  a = absl::gbswap_64((x + z) * mul + y) + b;\n  b = ShiftMix((z + a) * mul + d + h) * mul;\n  return b + x;\n}\n\nuint64_t CityHash64(const char *s, size_t len) {\n  if (len <= 32) {\n    if (len <= 16) {\n      return HashLen0to16(s, len);\n    } else {\n      return HashLen17to32(s, len);\n    }\n  } else if (len <= 64) {\n    return HashLen33to64(s, len);\n  }\n\n  // For strings over 64 bytes we hash the end first, and then as we\n  // loop we keep 56 bytes of state: v, w, x, y, and z.\n  uint64_t x = Fetch64(s + len - 40);\n  uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56);\n  uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));\n  std::pair<uint64_t, uint64_t> v =\n      WeakHashLen32WithSeeds(s + len - 64, len, z);\n  std::pair<uint64_t, uint64_t> w =\n      WeakHashLen32WithSeeds(s + len - 32, y + k1, x);\n  x = x * k1 + Fetch64(s);\n\n  // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.\n  len = (len - 1) & ~static_cast<size_t>(63);\n  do {\n    x = absl::rotr(x + y + v.first + Fetch64(s + 8), 37) * k1;\n    y = absl::rotr(y + v.second + Fetch64(s + 48), 42) * k1;\n    x ^= w.second;\n    y += v.first + Fetch64(s + 40);\n    z = absl::rotr(z + w.first, 33) * k1;\n    v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);\n    w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));\n    std::swap(z, x);\n    s += 64;\n    len -= 64;\n  } while (len != 0);\n  return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,\n                   HashLen16(v.second, w.second) + x);\n}\n\nuint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) {\n  return CityHash64WithSeeds(s, len, k2, seed);\n}\n\nuint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,\n                             uint64_t seed1) {\n  return HashLen16(CityHash64(s, len) - seed0, seed1);\n}\n\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/hash/internal/city.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// https://code.google.com/p/cityhash/\n//\n// This file provides a few functions for hashing strings.  All of them are\n// high-quality functions in the sense that they pass standard tests such\n// as Austin Appleby's SMHasher.  They are also fast.\n//\n// For 64-bit x86 code, on short strings, we don't know of anything faster than\n// CityHash64 that is of comparable quality.  We believe our nearest competitor\n// is Murmur3.  For 64-bit x86 code, CityHash64 is an excellent choice for hash\n// tables and most other hashing (excluding cryptography).\n//\n// For 32-bit x86 code, we don't know of anything faster than CityHash32 that\n// is of comparable quality.  We believe our nearest competitor is Murmur3A.\n// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)\n//\n// Functions in the CityHash family are not suitable for cryptography.\n//\n// Please see CityHash's README file for more details on our performance\n// measurements and so on.\n//\n// WARNING: This code has been only lightly tested on big-endian platforms!\n// It is known to work well on little-endian platforms that have a small penalty\n// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.\n// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;\n// bug reports are welcome.\n//\n// By the way, for some hash functions, given strings a and b, the hash\n// of a+b is easily derived from the hashes of a and b.  This property\n// doesn't hold for any hash functions in this file.\n\n#ifndef ABSL_HASH_INTERNAL_CITY_H_\n#define ABSL_HASH_INTERNAL_CITY_H_\n\n#include <stdint.h>\n#include <stdlib.h>  // for size_t.\n\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\n\n// Hash function for a byte array.\nuint64_t CityHash64(const char *s, size_t len);\n\n// Hash function for a byte array.  For convenience, a 64-bit seed is also\n// hashed into the result.\nuint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed);\n\n// Hash function for a byte array.  For convenience, two seeds are also\n// hashed into the result.\nuint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,\n                             uint64_t seed1);\n\n// Hash function for a byte array.  Most useful in 32-bit binaries.\nuint32_t CityHash32(const char *s, size_t len);\n\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HASH_INTERNAL_CITY_H_\n"
  },
  {
    "path": "absl/hash/internal/city_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/hash/internal/city.h\"\n\n#include <string.h>\n#include <cstdio>\n#include <iostream>\n#include \"gtest/gtest.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\nnamespace {\n\nstatic const uint64_t k0 = 0xc3a5c85c97cb3127ULL;\nstatic const uint64_t kSeed0 = 1234567;\nstatic const uint64_t kSeed1 = k0;\nstatic const int kDataSize = 1 << 20;\nstatic const int kTestSize = 300;\n\nstatic char data[kDataSize];\n\n// Initialize data to pseudorandom values.\nvoid setup() {\n  uint64_t a = 9;\n  uint64_t b = 777;\n  for (int i = 0; i < kDataSize; i++) {\n    a += b;\n    b += a;\n    a = (a ^ (a >> 41)) * k0;\n    b = (b ^ (b >> 41)) * k0 + i;\n    uint8_t u = b >> 37;\n    memcpy(data + i, &u, 1);  // uint8_t -> char\n  }\n}\n\n#define C(x) 0x##x##ULL\nstatic const uint64_t testdata[kTestSize][4] = {\n    {C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766),\n     C(dc56d17a)},\n    {C(541150e87f415e96), C(1aef0d24b3148a1a), C(bacc300e1e82345a),\n     C(99929334)},\n    {C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2), C(4252edb7)},\n    {C(ef923a7a1af78eab), C(79163b1e1e9a9b18), C(df3b2aca6e1e4a30),\n     C(ebc34f3c)},\n    {C(11df592596f41d88), C(843ec0bce9042f9c), C(cce2ea1e08b1eb30),\n     C(26f2b463)},\n    {C(831f448bdc5600b3), C(62a24be3120a6919), C(1b44098a41e010da),\n     C(b042c047)},\n    {C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d), C(e73bb0a8)},\n    {C(1b5a063fb4c7f9f1), C(318dbc24af66dee9), C(10ef7b32d5c719af),\n     C(91dfdd75)},\n    {C(a0f10149a0e538d6), C(69d008c20f87419f), C(41b36376185b3e9e),\n     C(c87f95de)},\n    {C(fb8d9c70660b910b), C(a45b0cc3476bff1b), C(b28d1996144f0207),\n     C(3f5538ef)},\n    {C(236827beae282a46), C(e43970221139c946), C(4f3ac6faa837a3aa),\n     C(70eb1a1f)},\n    {C(c385e435136ecf7c), C(d9d17368ff6c4a08), C(1b31eed4e5251a67),\n     C(cfd63b83)},\n    {C(e3f6828b6017086d), C(21b4d1900554b3b0), C(bef38be1809e24f1),\n     C(894a52ef)},\n    {C(851fff285561dca0), C(4d1277d73cdf416f), C(28ccffa61010ebe2),\n     C(9cde6a54)},\n    {C(61152a63595a96d9), C(d1a3a91ef3a7ba45), C(443b6bb4a493ad0c),\n     C(6c4898d5)},\n    {C(44473e03be306c88), C(30097761f872472a), C(9fd1b669bfad82d7),\n     C(13e1978e)},\n    {C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303), C(51b4ba8)},\n    {C(6abbfde37ee03b5b), C(83febf188d2cc113), C(cda7b62d94d5b8ee),\n     C(b6b06e40)},\n    {C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a), C(240a2f2)},\n    {C(d72ce05171ef8a1a), C(c6bd6bd869203894), C(c760e6396455d23a),\n     C(5dcefc30)},\n    {C(4182832b52d63735), C(337097e123eea414), C(b5a72ca0456df910),\n     C(7a48b105)},\n    {C(d6cdae892584a2cb), C(58de0fa4eca17dcd), C(43df30b8f5f1cb00),\n     C(fd55007b)},\n    {C(5c8e90bc267c5ee4), C(e9ae044075d992d9), C(f234cbfd1f0a1e59),\n     C(6b95894c)},\n    {C(bbd7f30ac310a6f3), C(b23b570d2666685f), C(fb13fb08c9814fe7),\n     C(3360e827)},\n    {C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a), C(45177e0b)},\n    {C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5), C(7c6fffe4)},\n    {C(441593e0da922dfe), C(936ef46061469b32), C(204a1921197ddd87),\n     C(bbc78da4)},\n    {C(2ba3883d71cc2133), C(72f2bbb32bed1a3c), C(27e1bd96d4843251),\n     C(c5c25d39)},\n    {C(f2b6d2adf8423600), C(7514e2f016a48722), C(43045743a50396ba),\n     C(b6e5d06e)},\n    {C(38fffe7f3680d63c), C(d513325255a7a6d1), C(31ed47790f6ca62f),\n     C(6178504e)},\n    {C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac), C(bd4c3637)},\n    {C(55bdb0e71e3edebd), C(c7ab562bcf0568bc), C(43166332f9ee684f),\n     C(6e7ac474)},\n    {C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e), C(1fb4b518)},\n    {C(c5dc19b876d37a80), C(15ffcff666cfd710), C(e8c30c72003103e2),\n     C(31d13d6d)},\n    {C(5e1141711d2d6706), C(b537f6dee8de6933), C(3af0a1fbbe027c54),\n     C(26fa72e3)},\n    {C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32), C(6a7433bf)},\n    {C(d26285842ff04d44), C(8f38d71341eacca9), C(5ca436f4db7a883c),\n     C(4e6df758)},\n    {C(c6ab830865a6bae6), C(6aa8e8dd4b98815c), C(efe3846713c371e5),\n     C(d57f63ea)},\n    {C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964), C(52ef73b3)},\n    {C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a), C(3cb36c3)},\n    {C(4ec0b54cf1566aff), C(30d2c7269b206bf4), C(77c22e82295e1061),\n     C(72c39bea)},\n    {C(ed8b7a4b34954ff7), C(56432de31f4ee757), C(85bd3abaa572b155),\n     C(a65aa25c)},\n    {C(5d28b43694176c26), C(714cc8bc12d060ae), C(3437726273a83fe6),\n     C(74740539)},\n    {C(6a1ef3639e1d202e), C(919bc1bd145ad928), C(30f3f7e48c28a773),\n     C(c3ae3c26)},\n    {C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51), C(f29db8a2)},\n    {C(cc0a840725a7e25b), C(57c69454396e193a), C(976eaf7eee0b4540),\n     C(1ef4cbf4)},\n    {C(a2b27ee22f63c3f1), C(9ebde0ce1b3976b2), C(2fe6a92a257af308),\n     C(a9be6c41)},\n    {C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f), C(fa31801)},\n    {C(584f28543864844f), C(d7cee9fc2d46f20d), C(a38dca5657387205),\n     C(8331c5d8)},\n    {C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f), C(e9876db8)},\n    {C(9a87bea227491d20), C(a468657e2b9c43e7), C(af9ba60db8d89ef7),\n     C(27b0604e)},\n    {C(27688c24958d1a5c), C(e3b4a1c9429cf253), C(48a95811f70d64bc),\n     C(dcec07f2)},\n    {C(5d1d37790a1873ad), C(ed9cd4bcc5fa1090), C(ce51cde05d8cd96a),\n     C(cff0a82a)},\n    {C(1f03fd18b711eea9), C(566d89b1946d381a), C(6e96e83fc92563ab),\n     C(fec83621)},\n    {C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71), C(743d8dc)},\n    {C(297008bcb3e3401d), C(61a8e407f82b0c69), C(a4a35bff0524fa0e),\n     C(64d41d26)},\n    {C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f), C(acd90c81)},\n    {C(ce38a9a54fad6599), C(6d6f4a90b9e8755e), C(c3ecc79ff105de3f),\n     C(7c746a4b)},\n    {C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1), C(b1047e99)},\n    {C(e71be7c28e84d119), C(eb6ace59932736e6), C(70c4397807ba12c5),\n     C(d1fd1068)},\n    {C(b5b58c24b53aaa19), C(d2a6ab0773dd897f), C(ef762fe01ecb5b97),\n     C(56486077)},\n    {C(44dd59bd301995cf), C(3ccabd76493ada1a), C(540db4c87d55ef23),\n     C(6069be80)},\n    {C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3), C(2078359b)},\n    {C(12807833c463737c), C(58e927ea3b3776b4), C(72dd20ef1c2f8ad0),\n     C(9ea21004)},\n    {C(e88419922b87176f), C(bcf32f41a7ddbf6f), C(d6ebefd8085c1a0f),\n     C(9c9cfe88)},\n    {C(105191e0ec8f7f60), C(5918dbfcca971e79), C(6b285c8a944767b9),\n     C(b70a6ddd)},\n    {C(a5b88bf7399a9f07), C(fca3ddfd96461cc4), C(ebe738fdc0282fc6),\n     C(dea37298)},\n    {C(d08c3f5747d84f50), C(4e708b27d1b6f8ac), C(70f70fd734888606),\n     C(8f480819)},\n    {C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36), C(30b3b16)},\n    {C(aa1f61fdc5c2e11e), C(c2c56cd11277ab27), C(a1e73069fdf1f94f),\n     C(f31bc4e8)},\n    {C(9489b36fe2246244), C(3355367033be74b8), C(5f57c2277cbce516),\n     C(419f953b)},\n    {C(358d7c0476a044cd), C(e0b7b47bcbd8854f), C(ffb42ec696705519),\n     C(20e9e76d)},\n    {C(b0c48df14275265a), C(9da4448975905efa), C(d716618e414ceb6d),\n     C(646f0ff8)},\n    {C(daa70bb300956588), C(410ea6883a240c6d), C(f5c8239fb5673eb3),\n     C(eeb7eca8)},\n    {C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685), C(8112bb9)},\n    {C(5c3323628435a2e8), C(1bea45ce9e72a6e3), C(904f0a7027ddb52e),\n     C(85a6d477)},\n    {C(c1ef26bea260abdb), C(6ee423f2137f9280), C(df2118b946ed0b43),\n     C(56f76c84)},\n    {C(6be7381b115d653a), C(ed046190758ea511), C(de6a45ffc3ed1159),\n     C(9af45d55)},\n    {C(ae3eece1711b2105), C(14fd3f4027f81a4a), C(abb7e45177d151db),\n     C(d1c33760)},\n    {C(376c28588b8fb389), C(6b045e84d8491ed2), C(4e857effb7d4e7dc),\n     C(c56bbf69)},\n    {C(58d943503bb6748f), C(419c6c8e88ac70f6), C(586760cbf3d3d368),\n     C(abecfb9b)},\n    {C(dfff5989f5cfd9a1), C(bcee2e7ea3a96f83), C(681c7874adb29017),\n     C(8de13255)},\n    {C(7fb19eb1a496e8f5), C(d49e5dfdb5c0833f), C(c0d5d7b2f7c48dc7),\n     C(a98ee299)},\n    {C(5dba5b0dadccdbaa), C(4ba8da8ded87fcdc), C(f693fdd25badf2f0),\n     C(3015f556)},\n    {C(688bef4b135a6829), C(8d31d82abcd54e8e), C(f95f8a30d55036d7),\n     C(5a430e29)},\n    {C(d8323be05433a412), C(8d48fa2b2b76141d), C(3d346f23978336a5),\n     C(2797add0)},\n    {C(3b5404278a55a7fc), C(23ca0b327c2d0a81), C(a6d65329571c892c),\n     C(27d55016)},\n    {C(2a96a3f96c5e9bbc), C(8caf8566e212dda8), C(904de559ca16e45e),\n     C(84945a82)},\n    {C(22bebfdcc26d18ff), C(4b4d8dcb10807ba1), C(40265eee30c6b896),\n     C(3ef7e224)},\n    {C(627a2249ec6bbcc2), C(c0578b462a46735a), C(4974b8ee1c2d4f1f),\n     C(35ed8dc8)},\n    {C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4), C(6a75e43d)},\n    {C(3931ac68c5f1b2c9), C(efe3892363ab0fb0), C(40b707268337cd36),\n     C(235d9805)},\n    {C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2), C(f7d69572)},\n    {C(7f7729a33e58fcc4), C(2e4bc1e7a023ead4), C(e707008ea7ca6222),\n     C(bacd0199)},\n    {C(42a0aa9ce82848b3), C(57232730e6bee175), C(f89bb3f370782031),\n     C(e428f50e)},\n    {C(6b2c6d38408a4889), C(de3ef6f68fb25885), C(20754f456c203361),\n     C(81eaaad3)},\n    {C(930380a3741e862a), C(348d28638dc71658), C(89dedcfd1654ea0d),\n     C(addbd3e3)},\n    {C(94808b5d2aa25f9a), C(cec72968128195e0), C(d9f4da2bdc1e130f),\n     C(e66dbca0)},\n    {C(b31abb08ae6e3d38), C(9eb9a95cbd9e8223), C(8019e79b7ee94ea9),\n     C(afe11fd5)},\n    {C(dccb5534a893ea1a), C(ce71c398708c6131), C(fe2396315457c164),\n     C(a71a406f)},\n    {C(6369163565814de6), C(8feb86fb38d08c2f), C(4976933485cc9a20),\n     C(9d90eaf5)},\n    {C(edee4ff253d9f9b3), C(96ef76fb279ef0ad), C(a4d204d179db2460),\n     C(6665db10)},\n    {C(941993df6e633214), C(929bc1beca5b72c6), C(141fc52b8d55572d),\n     C(9c977cbf)},\n    {C(859838293f64cd4c), C(484403b39d44ad79), C(bf674e64d64b9339),\n     C(ee83ddd4)},\n    {C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51), C(26519cc)},\n    {C(f963b63b9006c248), C(9e9bf727ffaa00bc), C(c73bacc75b917e3a),\n     C(a485a53f)},\n    {C(6a8aa0852a8c1f3b), C(c8f1e5e206a21016), C(2aa554aed1ebb524),\n     C(f62bc412)},\n    {C(740428b4d45e5fb8), C(4c95a4ce922cb0a5), C(e99c3ba78feae796),\n     C(8975a436)},\n    {C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1), C(94ff7f41)},\n    {C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680), C(760aa031)},\n    {C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4), C(3bda76df)},\n    {C(810bc8aa0c40bcb0), C(448a019568d01441), C(f60ec52f60d3aeae),\n     C(498e2e65)},\n    {C(22036327deb59ed7), C(adc05ceb97026a02), C(48bff0654262672b),\n     C(d38deb48)},\n    {C(7d14dfa9772b00c8), C(595735efc7eeaed7), C(29872854f94c3507),\n     C(82b3fb6b)},\n    {C(2d777cddb912675d), C(278d7b10722a13f9), C(f5c02bfb7cc078af),\n     C(e500e25f)},\n    {C(f2ec98824e8aa613), C(5eb7e3fb53fe3bed), C(12c22860466e1dd4),\n     C(bd2bb07c)},\n    {C(5e763988e21f487f), C(24189de8065d8dc5), C(d1519d2403b62aa0),\n     C(3a2b431d)},\n    {C(48949dc327bb96ad), C(e1fd21636c5c50b4), C(3f6eb7f13a8712b4),\n     C(7322a83d)},\n    {C(b7c4209fb24a85c5), C(b35feb319c79ce10), C(f0d3de191833b922),\n     C(a645ca1c)},\n    {C(9c9e5be0943d4b05), C(b73dc69e45201cbb), C(aab17180bfe5083d),\n     C(8909a45a)},\n    {C(3898bca4dfd6638d), C(f911ff35efef0167), C(24bdf69e5091fc88),\n     C(bd30074c)},\n    {C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb), C(c17cf001)},\n    {C(a927ed8b2bf09bb6), C(606e52f10ae94eca), C(71c2203feb35a9ee),\n     C(26ffd25a)},\n    {C(8d25746414aedf28), C(34b1629d28b33d3a), C(4d5394aea5f82d7b),\n     C(f1d8ce3c)},\n    {C(b5bbdb73458712f2), C(1ff887b3c2a35137), C(7f7231f702d0ace9),\n     C(3ee8fb17)},\n    {C(3d32a26e3ab9d254), C(fc4070574dc30d3a), C(f02629579c2b27c9),\n     C(a77acc2a)},\n    {C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c), C(f4556dee)},\n    {C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9), C(de287a64)},\n    {C(b2e23e8116c2ba9f), C(7e4d9c0060101151), C(3310da5e5028f367),\n     C(878e55b9)},\n    {C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5), C(7648486)},\n    {C(858fea922c7fe0c3), C(cfe8326bf733bc6f), C(4e5e2018cf8f7dfc),\n     C(57ac0fb1)},\n    {C(46ef25fdec8392b1), C(e48d7b6d42a5cd35), C(56a6fe1c175299ca),\n     C(d01967ca)},\n    {C(8d078f726b2df464), C(b50ee71cdcabb299), C(f4af300106f9c7ba),\n     C(96ecdf74)},\n    {C(35ea86e6960ca950), C(34fe1fe234fc5c76), C(a00207a3dc2a72b7),\n     C(779f5506)},\n    {C(8aee9edbc15dd011), C(51f5839dc8462695), C(b2213e17c37dca2d),\n     C(3c94c2de)},\n    {C(c3e142ba98432dda), C(911d060cab126188), C(b753fbfa8365b844),\n     C(39f98faf)},\n    {C(123ba6b99c8cd8db), C(448e582672ee07c4), C(cebe379292db9e65),\n     C(7af31199)},\n    {C(ba87acef79d14f53), C(b3e0fcae63a11558), C(d5ac313a593a9f45),\n     C(e341a9d6)},\n    {C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472), C(ca24aeeb)},\n    {C(61442ff55609168e), C(6447c5fc76e8c9cf), C(6a846de83ae15728),\n     C(b2252b57)},\n    {C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f), C(72c81da1)},\n    {C(531e8e77b363161c), C(eece0b43e2dae030), C(8294b82c78f34ed1),\n     C(6b9fce95)},\n    {C(f71e9c926d711e2b), C(d77af2853a4ceaa1), C(9aa0d6d76a36fae7),\n     C(19399857)},\n    {C(cb20ac28f52df368), C(e6705ee7880996de), C(9b665cc3ec6972f2),\n     C(3c57a994)},\n    {C(e4a794b4acb94b55), C(89795358057b661b), C(9c4cdcec176d7a70),\n     C(c053e729)},\n    {C(cb942e91443e7208), C(e335de8125567c2a), C(d4d74d268b86df1f),\n     C(51cbbba7)},\n    {C(ecca7563c203f7ba), C(177ae2423ef34bb2), C(f60b7243400c5731),\n     C(1acde79a)},\n    {C(1652cb940177c8b5), C(8c4fe7d85d2a6d6d), C(f6216ad097e54e72),\n     C(2d160d13)},\n    {C(31fed0fc04c13ce8), C(3d5d03dbf7ff240a), C(727c5c9b51581203),\n     C(787f5801)},\n    {C(e7b668947590b9b3), C(baa41ad32938d3fa), C(abcbc8d4ca4b39e4),\n     C(c9629828)},\n    {C(1de2119923e8ef3c), C(6ab27c096cf2fe14), C(8c3658edca958891),\n     C(be139231)},\n    {C(1269df1e69e14fa7), C(992f9d58ac5041b7), C(e97fcf695a7cbbb4),\n     C(7df699ef)},\n    {C(820826d7aba567ff), C(1f73d28e036a52f3), C(41c4c5a73f3b0893),\n     C(8ce6b96d)},\n    {C(ffe0547e4923cef9), C(3534ed49b9da5b02), C(548a273700fba03d),\n     C(6f9ed99c)},\n    {C(72da8d1b11d8bc8b), C(ba94b56b91b681c6), C(4e8cc51bd9b0fc8c),\n     C(e0244796)},\n    {C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465), C(4ccf7e75)},\n    {C(d0f06c28c7b36823), C(1008cb0874de4bb8), C(d6c7ff816c7a737b),\n     C(915cef86)},\n    {C(99b7042460d72ec6), C(2a53e5e2b8e795c2), C(53a78132d9e1b3e3),\n     C(5cb59482)},\n    {C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3), C(6ca3f532)},\n    {C(fe86bf9d4422b9ae), C(ebce89c90641ef9c), C(1c84e2292c0b5659),\n     C(e24f3859)},\n    {C(a90d81060932dbb0), C(8acfaa88c5fbe92b), C(7c6f3447e90f7f3f),\n     C(adf5a9c7)},\n    {C(17938a1b0e7f5952), C(22cadd2f56f8a4be), C(84b0d1183d5ed7c1),\n     C(32264b75)},\n    {C(de9e0cb0e16f6e6d), C(238e6283aa4f6594), C(4fb9c914c2f0a13b),\n     C(a64b3376)},\n    {C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5), C(d33890e)},\n    {C(e698fa3f54e6ea22), C(bd28e20e7455358c), C(9ace161f6ea76e66),\n     C(926d4b63)},\n    {C(7bc0deed4fb349f7), C(1771aff25dc722fa), C(19ff0644d9681917),\n     C(d51ba539)},\n    {C(db4b15e88533f622), C(256d6d2419b41ce9), C(9d7c5378396765d5),\n     C(7f37636d)},\n    {C(922834735e86ecb2), C(363382685b88328e), C(e9c92960d7144630),\n     C(b98026c0)},\n    {C(30f1d72c812f1eb8), C(b567cd4a69cd8989), C(820b6c992a51f0bc),\n     C(b877767e)},\n    {C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a), C(aefae77)},\n    {C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d), C(f686911)},\n    {C(aa2d6cf22e3cc252), C(9b4dec4f5e179f16), C(76fb0fba1d99a99a),\n     C(3deadf12)},\n    {C(7bf5ffd7f69385c7), C(fc077b1d8bc82879), C(9c04e36f9ed83a24),\n     C(ccf02a4e)},\n    {C(e89c8ff9f9c6e34b), C(f54c0f669a49f6c4), C(fc3e46f5d846adef),\n     C(176c1722)},\n    {C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c), C(26f82ad)},\n    {C(2d54f40cc4088b17), C(59d15633b0cd1399), C(a8cc04bb1bffd15b),\n     C(b5244f42)},\n    {C(69276946cb4e87c7), C(62bdbe6183be6fa9), C(3ba9773dac442a1a),\n     C(49a689e5)},\n    {C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28), C(59fcdd3)},\n    {C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf), C(4f4b04e9)},\n    {C(cd0d79f2164da014), C(4c386bb5c5d6ca0c), C(8e771b03647c3b63),\n     C(8b00f891)},\n    {C(e0e6fc0b1628af1d), C(29be5fb4c27a2949), C(1c3f781a604d3630),\n     C(16e114f3)},\n    {C(2058927664adfd93), C(6e8f968c7963baa5), C(af3dced6fff7c394),\n     C(d6b6dadc)},\n    {C(dc107285fd8e1af7), C(a8641a0609321f3f), C(db06e89ffdc54466),\n     C(897e20ac)},\n    {C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a), C(f996e05d)},\n    {C(bfa10785ddc1011b), C(b6e1c4d2f670f7de), C(517d95604e4fcc1f),\n     C(c4306af6)},\n    {C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363), C(6dcad433)},\n    {C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545), C(3c07374d)},\n    {C(f0d6044f6efd7598), C(e044d6ba4369856e), C(91968e4f8c8a1a4c),\n     C(f0f4602c)},\n    {C(3d69e52049879d61), C(76610636ea9f74fe), C(e9bf5602f89310c0),\n     C(3e1ea071)},\n    {C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de), C(67580f0c)},\n    {C(461c82656a74fb57), C(d84b491b275aa0f7), C(8f262cb29a6eb8b2),\n     C(4e109454)},\n    {C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3), C(88a474a7)},\n    {C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4), C(5b5bedd)},\n    {C(43c64d7484f7f9b2), C(5da002b64aafaeb7), C(b576c1e45800a716),\n     C(1aaddfa7)},\n    {C(a7dec6ad81cf7fa1), C(180c1ab708683063), C(95e0fd7008d67cff),\n     C(5be07fd8)},\n    {C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e), C(cbca8606)},\n    {C(a8b27a6bcaeeed4b), C(aec1eeded6a87e39), C(9daf246d6fed8326),\n     C(bde64d01)},\n    {C(9a952a8246fdc269), C(d0dcfcac74ef278c), C(250f7139836f0f1f),\n     C(ee90cf33)},\n    {C(c930841d1d88684f), C(5eb66eb18b7f9672), C(e455d413008a2546),\n     C(4305c3ce)},\n    {C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5), C(4b3a1d76)},\n    {C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456), C(a8bb6d80)},\n    {C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5), C(1f9fa607)},\n    {C(da60e6b14479f9df), C(3bdccf69ece16792), C(18ebf45c4fecfdc9),\n     C(8d0e4ed2)},\n    {C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09), C(1bf31347)},\n    {C(ebd22d4b70946401), C(6863602bf7139017), C(c0b1ac4e11b00666),\n     C(1ae3fc5b)},\n    {C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364), C(459c3930)},\n    {C(38908e43f7ba5ef0), C(1ab035d4e7781e76), C(41d133e8c0a68ff7),\n     C(e00c4184)},\n    {C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8), C(ffc7a781)},\n    {C(86215c45dcac9905), C(ea546afe851cae4b), C(d85b6457e489e374),\n     C(6a125480)},\n    {C(420fc255c38db175), C(d503cd0f3c1208d1), C(d4684e74c825a0bc),\n     C(88a1512b)},\n    {C(1d7a31f5bc8fe2f9), C(4763991092dcf836), C(ed695f55b97416f4),\n     C(549bbbe5)},\n    {C(94129a84c376a26e), C(c245e859dc231933), C(1b8f74fecf917453),\n     C(c133d38c)},\n    {C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb), C(fcace348)},\n    {C(90fa3ccbd60848da), C(dfa6e0595b569e11), C(e585d067a1f5135d),\n     C(ed7b6f9a)},\n    {C(2dbb4fc71b554514), C(9650e04b86be0f82), C(60f2304fba9274d3),\n     C(6d907dda)},\n    {C(b98bf4274d18374a), C(1b669fd4c7f9a19a), C(b1f5972b88ba2b7a),\n     C(7a4d48d5)},\n    {C(d6781d0b5e18eb68), C(b992913cae09b533), C(58f6021caaee3a40),\n     C(e686f3db)},\n    {C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42), C(cce7c55)},\n    {C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8), C(f58b96b)},\n    {C(c6df6364a24f75a3), C(c294e2c84c4f5df8), C(a88df65c6a89313b),\n     C(1bbf6f60)},\n    {C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625), C(ce5e0cc2)},\n    {C(aae06f9146db885f), C(3598736441e280d9), C(fba339b117083e55),\n     C(584cfd6f)},\n    {C(8955ef07631e3bcc), C(7d70965ea3926f83), C(39aed4134f8b2db6),\n     C(8f9bbc33)},\n    {C(ad611c609cfbe412), C(d3c00b18bf253877), C(90b2172e1f3d0bfd),\n     C(d7640d95)},\n    {C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf), C(3d12a2b)},\n    {C(40d0aeff521375a8), C(77ba1ad7ecebd506), C(547c6f1a7d9df427),\n     C(aaeafed0)},\n    {C(8b2d54ae1a3df769), C(11e7adaee3216679), C(3483781efc563e03),\n     C(95b9b814)},\n    {C(99c175819b4eae28), C(932e8ff9f7a40043), C(ec78dcab07ca9f7c),\n     C(45fbe66e)},\n    {C(2a418335779b82fc), C(af0295987849a76b), C(c12bc5ff0213f46e),\n     C(b4baa7a8)},\n    {C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c), C(83e962fe)},\n    {C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234), C(aac3531c)},\n    {C(293a5c1c4e203cd4), C(6b3329f1c130cefe), C(f2e32f8ec76aac91),\n     C(2b1db7cc)},\n    {C(4290e018ffaedde7), C(a14948545418eb5e), C(72d851b202284636),\n     C(cf00cd31)},\n    {C(f919a59cbde8bf2f), C(a56d04203b2dc5a5), C(38b06753ac871e48),\n     C(7d3c43b8)},\n    {C(1d70a3f5521d7fa4), C(fb97b3fdc5891965), C(299d49bbbe3535af),\n     C(cbd5fac6)},\n    {C(6af98d7b656d0d7c), C(d2e99ae96d6b5c0c), C(f63bd1603ef80627),\n     C(76d0fec4)},\n    {C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9), C(405e3402)},\n    {C(3822dd82c7df012f), C(b9029b40bd9f122b), C(fd25b988468266c4),\n     C(c732c481)},\n    {C(79f7efe4a80b951a), C(dd3a3fddfc6c9c41), C(ab4c812f9e27aa40),\n     C(a8d123c9)},\n    {C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59), C(1e80ad7d)},\n    {C(8959dbbf07387d36), C(b4658afce48ea35d), C(8f3f82437d8cb8d6),\n     C(52aeb863)},\n    {C(4739613234278a49), C(99ea5bcd340bf663), C(258640912e712b12),\n     C(ef7c0c18)},\n    {C(420e6c926bc54841), C(96dbbf6f4e7c75cd), C(d8d40fa70c3c67bb),\n     C(b6ad4b68)},\n    {C(c8601bab561bc1b7), C(72b26272a0ff869a), C(56fdfc986d6bc3c4),\n     C(c1e46b17)},\n    {C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6), C(57b8df25)},\n    {C(7966f53c37b6c6d7), C(8e6abcfb3aa2b88f), C(7f2e5e0724e5f345),\n     C(e9fa36d6)},\n    {C(be9bb0abd03b7368), C(13bca93a3031be55), C(e864f4f52b55b472),\n     C(8f8daefc)},\n    {C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c), C(6e1bb7e)},\n    {C(7c386f0ffe0465ac), C(530419c9d843dbf3), C(7450e3a4f72b8d8c),\n     C(fd0076f0)},\n    {C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe), C(899b17b6)},\n    {C(cd80dea24321eea4), C(52b4fdc8130c2b15), C(f3ea100b154bfb82),\n     C(e3e84e31)},\n    {C(d599a04125372c3a), C(313136c56a56f363), C(1e993c3677625832),\n     C(eef79b6b)},\n    {C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534), C(868e3315)},\n    {C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485), C(4639a426)},\n    {C(d86603ced1ed4730), C(f9de718aaada7709), C(db8b9755194c6535),\n     C(f3213646)},\n    {C(915263c671b28809), C(a815378e7ad762fd), C(abec6dc9b669f559),\n     C(17f148e9)},\n    {C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad), C(bfd94880)},\n    {C(2d107419073b9cd0), C(a96db0740cef8f54), C(ec41ee91b3ecdc1b),\n     C(bb1fa7f3)},\n    {C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8), C(88816b1)},\n    {C(1160987c8fe86f7d), C(879e6db1481eb91b), C(d7dcb802bfe6885d),\n     C(5c2faeb3)},\n    {C(eab8112c560b967b), C(97f550b58e89dbae), C(846ed506d304051f),\n     C(51b5fc6f)},\n    {C(1addcf0386d35351), C(b5f436561f8f1484), C(85d38e22181c9bb1),\n     C(33d94752)},\n    {C(d445ba84bf803e09), C(1216c2497038f804), C(2293216ea2237207),\n     C(b0c92948)},\n    {C(37235a096a8be435), C(d9b73130493589c2), C(3b1024f59378d3be),\n     C(c7171590)},\n    {C(763ad6ea2fe1c99d), C(cf7af5368ac1e26b), C(4d5e451b3bb8d3d4),\n     C(240a67fb)},\n    {C(ea627fc84cd1b857), C(85e372494520071f), C(69ec61800845780b),\n     C(e1843cd5)},\n    {C(1f2ffd79f2cdc0c8), C(726a1bc31b337aaa), C(678b7f275ef96434),\n     C(fda1452b)},\n    {C(39a9e146ec4b3210), C(f63f75802a78b1ac), C(e2e22539c94741c3),\n     C(a2cad330)},\n    {C(74cba303e2dd9d6d), C(692699b83289fad1), C(dfb9aa7874678480),\n     C(53467e16)},\n    {C(4cbc2b73a43071e0), C(56c5db4c4ca4e0b7), C(1b275a162f46bd3d),\n     C(da14a8d0)},\n    {C(875638b9715d2221), C(d9ba0615c0c58740), C(616d4be2dfe825aa),\n     C(67333551)},\n    {C(fb686b2782994a8d), C(edee60693756bb48), C(e6bc3cae0ded2ef5),\n     C(a0ebd66e)},\n    {C(ab21d81a911e6723), C(4c31b07354852f59), C(835da384c9384744),\n     C(4b769593)},\n    {C(33d013cc0cd46ecf), C(3de726423aea122c), C(116af51117fe21a9),\n     C(6aa75624)},\n    {C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f), C(602a3f96)},\n    {C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee), C(cd183c4d)},\n    {C(9c8502050e9c9458), C(d6d2a1a69964beb9), C(1675766f480229b5),\n     C(960a4d07)},\n    {C(348176ca2fa2fdd2), C(3a89c514cc360c2d), C(9f90b8afb318d6d0),\n     C(9ae998c4)},\n    {C(4a3d3dfbbaea130b), C(4e221c920f61ed01), C(553fd6cd1304531f),\n     C(74e2179d)},\n    {C(b371f768cdf4edb9), C(bdef2ace6d2de0f0), C(e05b4100f7f1baec),\n     C(ee9bae25)},\n    {C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df), C(b66edf10)},\n    {C(8be53d466d4728f2), C(86a5ac8e0d416640), C(984aa464cdb5c8bb),\n     C(d6209737)},\n    {C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a), C(b994a88)},\n    {C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40), C(a05d43c0)},\n    {C(fda9877ea8e3805f), C(31e868b6ffd521b7), C(b08c90681fb6a0fd),\n     C(c79f73a8)},\n    {C(2e36f523ca8f5eb5), C(8b22932f89b27513), C(331cd6ecbfadc1bb),\n     C(a490aff5)},\n    {C(21a378ef76828208), C(a5c13037fa841da2), C(506d22a53fbe9812),\n     C(dfad65b4)},\n    {C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9), C(1d07dfb)},\n    {C(7854468f4e0cabd0), C(3a3f6b4f098d0692), C(ae2423ec7799d30d),\n     C(416df9a0)},\n    {C(7f88db5346d8f997), C(88eac9aacc653798), C(68a4d0295f8eefa1),\n     C(1f8fb9cc)},\n    {C(bb3fb5fb01d60fcf), C(1b7cc0847a215eb6), C(1246c994437990a1),\n     C(7abf48e3)},\n    {C(2e783e1761acd84d), C(39158042bac975a0), C(1cd21c5a8071188d),\n     C(dea4e3dd)},\n    {C(392058251cf22acc), C(944ec4475ead4620), C(b330a10b5cb94166),\n     C(c6064f22)},\n    {C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c), C(743bed9c)},\n    {C(6bc1db2c2bee5aba), C(e63b0ed635307398), C(7b2eca111f30dbbc),\n     C(fce254d5)},\n    {C(b00f898229efa508), C(83b7590ad7f6985c), C(2780e70a0592e41d),\n     C(e47ec9d1)},\n    {C(b56eb769ce0d9a8c), C(ce196117bfbcaf04), C(b26c3c3797d66165),\n     C(334a145c)},\n    {C(70c0637675b94150), C(259e1669305b0a15), C(46e1dd9fd387a58d),\n     C(adec1e3c)},\n    {C(74c0b8a6821faafe), C(abac39d7491370e7), C(faf0b2a48a4e6aed),\n     C(f6a9fbf8)},\n    {C(5fb5e48ac7b7fa4f), C(a96170f08f5acbc7), C(bbf5c63d4f52a1e5),\n     C(5398210c)},\n};\n\nvoid TestUnchanging(const uint64_t* expected, int offset, int len) {\n  EXPECT_EQ(expected[0], CityHash64(data + offset, len));\n  EXPECT_EQ(expected[3], CityHash32(data + offset, len));\n  EXPECT_EQ(expected[1], CityHash64WithSeed(data + offset, len, kSeed0));\n  EXPECT_EQ(expected[2],\n            CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1));\n}\n\nTEST(CityHashTest, Unchanging) {\n  setup();\n  int i = 0;\n  for (; i < kTestSize - 1; i++) {\n    TestUnchanging(testdata[i], i * i, i);\n  }\n  TestUnchanging(testdata[i], 0, kDataSize);\n}\n\n}  // namespace\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/hash/internal/hash.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/hash/internal/hash.h\"\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/unaligned_access.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/prefetch.h\"\n#include \"absl/hash/internal/city.h\"\n\n#ifdef ABSL_AES_INTERNAL_HAVE_X86_SIMD\n#error ABSL_AES_INTERNAL_HAVE_X86_SIMD cannot be directly set\n#elif defined(__SSE4_2__) && defined(__AES__)\n#define ABSL_AES_INTERNAL_HAVE_X86_SIMD\n#endif\n\n\n#ifdef ABSL_AES_INTERNAL_HAVE_X86_SIMD\n#include <smmintrin.h>\n#include <wmmintrin.h>\n#include <xmmintrin.h>\n#endif  // ABSL_AES_INTERNAL_HAVE_X86_SIMD\n\n#ifdef ABSL_AES_INTERNAL_HAVE_ARM_SIMD\n#error ABSL_AES_INTERNAL_HAVE_ARM_SIMD cannot be directly set\n#elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)\n#include <arm_neon.h>\n#define ABSL_AES_INTERNAL_HAVE_ARM_SIMD\n#endif  // ABSL_INTERNAL_HAVE_ARM_NEON\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\n\nnamespace {\n\nvoid PrefetchFutureDataToLocalCache(const uint8_t* ptr) {\n  PrefetchToLocalCache(ptr + 5 * ABSL_CACHELINE_SIZE);\n}\n\n#if defined(ABSL_AES_INTERNAL_HAVE_X86_SIMD) || \\\n    defined(ABSL_AES_INTERNAL_HAVE_ARM_SIMD)\n\n#if defined(ABSL_AES_INTERNAL_HAVE_X86_SIMD)\nusing Vector128 = __m128i;\n\ninline Vector128 Load128(const uint8_t* ptr) {\n  return _mm_loadu_si128(reinterpret_cast<const Vector128*>(ptr));\n}\n\ninline Vector128 Set128(uint64_t a, uint64_t b) {\n  return _mm_set_epi64x(static_cast<int64_t>(a), static_cast<int64_t>(b));\n}\n\ninline Vector128 Add128(Vector128 a, Vector128 b) {\n  return _mm_add_epi64(a, b);\n}\n\ninline Vector128 Sub128(Vector128 a, Vector128 b) {\n  return _mm_sub_epi64(a, b);\n}\n\n// Bits of the second argument to Encrypt128/Decrypt128 are XORed with the\n// first argument after encryption/decryption.\n\ninline Vector128 Encrypt128(Vector128 data, Vector128 key) {\n  return _mm_aesenc_si128(data, key);\n}\n\ninline Vector128 Decrypt128(Vector128 data, Vector128 key) {\n  return _mm_aesdec_si128(data, key);\n}\n\n// We use each value as the first argument to shuffle all the bits around. We do\n// not add any salt to the state or loaded data, instead we vary instructions\n// used to mix bits Encrypt128/Decrypt128 and Add128/Sub128. On x86,\n// Add128/Sub128 are combined to one instruction with data loading like\n// `vpaddq xmm1, xmm0, xmmword ptr [rdi]`.\n\ninline Vector128 MixA(Vector128 a, Vector128 state) {\n  return Decrypt128(Add128(state, a), state);\n}\n\ninline Vector128 MixB(Vector128 b, Vector128 state) {\n  return Decrypt128(Sub128(state, b), state);\n}\n\ninline Vector128 MixC(Vector128 c, Vector128 state) {\n  return Encrypt128(Add128(state, c), state);\n}\n\ninline Vector128 MixD(Vector128 d, Vector128 state) {\n  return Encrypt128(Sub128(state, d), state);\n}\n\ninline uint64_t ExtractLow64(Vector128 v) {\n  return static_cast<uint64_t>(_mm_cvtsi128_si64(v));\n}\n\ninline uint64_t ExtractHigh64(Vector128 v) {\n  return static_cast<uint64_t>(_mm_extract_epi64(v, 1));\n}\n\ninline uint64_t Mix4x16Vectors(Vector128 a, Vector128 b, Vector128 c,\n                               Vector128 d) {\n  Vector128 res128 =\n      Add128(Encrypt128(Add128(a, c), d), Decrypt128(Sub128(b, d), a));\n  uint64_t x64 = ExtractLow64(res128);\n  uint64_t y64 = ExtractHigh64(res128);\n  return x64 ^ y64;\n}\n\n#else  // ABSL_AES_INTERNAL_HAVE_ARM_SIMD\n\nusing Vector128 = uint8x16_t;\n\ninline Vector128 Load128(const uint8_t* ptr) { return vld1q_u8(ptr); }\n\ninline Vector128 Set128(uint64_t a, uint64_t b) {\n  return vreinterpretq_u8_u64(vsetq_lane_u64(a, vdupq_n_u64(b), 1));\n}\n\ninline Vector128 Add128(Vector128 a, Vector128 b) {\n  return vreinterpretq_u8_u64(\n      vaddq_u64(vreinterpretq_u64_u8(a), vreinterpretq_u64_u8(b)));\n}\n\n// Bits of the second argument to Decrypt128/Encrypt128 are XORed with the\n// state argument BEFORE encryption (in x86 version they are XORed after).\n\ninline Vector128 Encrypt128(Vector128 data, Vector128 key) {\n  return vaesmcq_u8(vaeseq_u8(data, key));\n}\n\ninline Vector128 Decrypt128(Vector128 data, Vector128 key) {\n  return vaesimcq_u8(vaesdq_u8(data, key));\n}\n\n// We use decryption for a, b and encryption for c, d. That helps us to avoid\n// collisions for trivial byte rotations. Mix4x16Vectors later uses\n// encrypted/decrypted pairs differently to ensure that the order of blocks is\n// important for the hash value.\n// We also avoid using Add128/Sub128 instructions because state is being mixed\n// before encryption/decryption. On ARM, there is no fusion of load and add/sub\n// instructions so it is more expensive to use them.\n\ninline Vector128 MixA(Vector128 a, Vector128 state) {\n  return Decrypt128(a, state);\n}\n\ninline Vector128 MixB(Vector128 b, Vector128 state) {\n  return Decrypt128(b, state);\n}\n\ninline Vector128 MixC(Vector128 c, Vector128 state) {\n  return Encrypt128(c, state);\n}\n\ninline Vector128 MixD(Vector128 d, Vector128 state) {\n  return Encrypt128(d, state);\n}\n\ninline uint64_t ExtractLow64(Vector128 v) {\n  return vgetq_lane_u64(vreinterpretq_u64_u8(v), 0);\n}\n\ninline uint64_t ExtractHigh64(Vector128 v) {\n  return vgetq_lane_u64(vreinterpretq_u64_u8(v), 1);\n}\n\nuint64_t Mix4x16Vectors(Vector128 a, Vector128 b, Vector128 c, Vector128 d) {\n  Vector128 res128 = Add128(Encrypt128(a, c), Decrypt128(b, d));\n  uint64_t x64 = ExtractLow64(res128);\n  uint64_t y64 = ExtractHigh64(res128);\n  return x64 ^ y64;\n}\n\n#endif  // ABSL_AES_INTERNAL_HAVE_X86_SIMD\n\nuint64_t LowLevelHash33To64(uint64_t seed, const uint8_t* ptr, size_t len) {\n  assert(len > 32);\n  assert(len <= 64);\n  Vector128 state = Set128(seed, len);\n  Vector128 a = Load128(ptr);\n  Vector128 b = Load128(ptr + 16);\n  auto* last32_ptr = ptr + len - 32;\n  Vector128 c = Load128(last32_ptr);\n  Vector128 d = Load128(last32_ptr + 16);\n\n  Vector128 na = MixA(a, state);\n  Vector128 nb = MixB(b, state);\n  Vector128 nc = MixC(c, state);\n  Vector128 nd = MixD(d, state);\n\n  // We perform another round of encryption to mix bits between two halves of\n  // the input.\n  return Mix4x16Vectors(na, nb, nc, nd);\n}\n\n[[maybe_unused]] ABSL_ATTRIBUTE_NOINLINE uint64_t\nLowLevelHashLenGt64(uint64_t seed, const void* data, size_t len) {\n  assert(len > 64);\n  const uint8_t* ptr = static_cast<const uint8_t*>(data);\n  const uint8_t* last_32_ptr = ptr + len - 32;\n\n  // If we have more than 64 bytes, we're going to handle chunks of 64\n  // bytes at a time. We're going to build up four separate hash states\n  // which we will then hash together. This avoids short dependency chains.\n  Vector128 state0 = Set128(seed, len);\n  Vector128 state1 = state0;\n  Vector128 state2 = state1;\n  Vector128 state3 = state2;\n\n  // Mixing two 128-bit vectors at a time with corresponding states.\n  // All variables are mixed slightly differently to avoid hash collision\n  // due to trivial byte rotation.\n  // We combine state and data with _mm_add_epi64/_mm_sub_epi64 before applying\n  // AES encryption to make hash function dependent on the order of the blocks.\n  // See comments in LowLevelHash33To64 for more considerations.\n  auto mix_ab = [&state0,\n                 &state1](const uint8_t* p) ABSL_ATTRIBUTE_ALWAYS_INLINE {\n    Vector128 a = Load128(p);\n    Vector128 b = Load128(p + 16);\n    state0 = MixA(a, state0);\n    state1 = MixB(b, state1);\n  };\n  auto mix_cd = [&state2,\n                 &state3](const uint8_t* p) ABSL_ATTRIBUTE_ALWAYS_INLINE {\n    Vector128 c = Load128(p);\n    Vector128 d = Load128(p + 16);\n    state2 = MixC(c, state2);\n    state3 = MixD(d, state3);\n  };\n\n  do {\n    PrefetchFutureDataToLocalCache(ptr);\n    mix_ab(ptr);\n    mix_cd(ptr + 32);\n\n    ptr += 64;\n    len -= 64;\n  } while (len > 64);\n\n  // We now have a data `ptr` with at most 64 bytes.\n  if (len > 32) {\n    mix_ab(ptr);\n  }\n  mix_cd(last_32_ptr);\n\n  return Mix4x16Vectors(state0, state1, state2, state3);\n}\n#else\nuint64_t Mix32Bytes(const uint8_t* ptr, uint64_t current_state) {\n  uint64_t a = absl::base_internal::UnalignedLoad64(ptr);\n  uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);\n  uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16);\n  uint64_t d = absl::base_internal::UnalignedLoad64(ptr + 24);\n\n  uint64_t cs0 = Mix(a ^ kStaticRandomData[1], b ^ current_state);\n  uint64_t cs1 = Mix(c ^ kStaticRandomData[2], d ^ current_state);\n  return cs0 ^ cs1;\n}\n\nuint64_t LowLevelHash33To64(uint64_t seed, const uint8_t* ptr, size_t len) {\n  assert(len > 32);\n  assert(len <= 64);\n  uint64_t current_state = seed ^ kStaticRandomData[0] ^ len;\n  const uint8_t* last_32_ptr = ptr + len - 32;\n  return Mix32Bytes(last_32_ptr, Mix32Bytes(ptr, current_state));\n}\n\n[[maybe_unused]] ABSL_ATTRIBUTE_NOINLINE uint64_t\nLowLevelHashLenGt64(uint64_t seed, const void* data, size_t len) {\n  assert(len > 64);\n  const uint8_t* ptr = static_cast<const uint8_t*>(data);\n  uint64_t current_state = seed ^ kStaticRandomData[0] ^ len;\n  const uint8_t* last_32_ptr = ptr + len - 32;\n  // If we have more than 64 bytes, we're going to handle chunks of 64\n  // bytes at a time. We're going to build up four separate hash states\n  // which we will then hash together. This avoids short dependency chains.\n  uint64_t duplicated_state0 = current_state;\n  uint64_t duplicated_state1 = current_state;\n  uint64_t duplicated_state2 = current_state;\n\n  do {\n    PrefetchFutureDataToLocalCache(ptr);\n\n    uint64_t a = absl::base_internal::UnalignedLoad64(ptr);\n    uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);\n    uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16);\n    uint64_t d = absl::base_internal::UnalignedLoad64(ptr + 24);\n    uint64_t e = absl::base_internal::UnalignedLoad64(ptr + 32);\n    uint64_t f = absl::base_internal::UnalignedLoad64(ptr + 40);\n    uint64_t g = absl::base_internal::UnalignedLoad64(ptr + 48);\n    uint64_t h = absl::base_internal::UnalignedLoad64(ptr + 56);\n\n    current_state = Mix(a ^ kStaticRandomData[1], b ^ current_state);\n    duplicated_state0 = Mix(c ^ kStaticRandomData[2], d ^ duplicated_state0);\n\n    duplicated_state1 = Mix(e ^ kStaticRandomData[3], f ^ duplicated_state1);\n    duplicated_state2 = Mix(g ^ kStaticRandomData[4], h ^ duplicated_state2);\n\n    ptr += 64;\n    len -= 64;\n  } while (len > 64);\n\n  current_state = (current_state ^ duplicated_state0) ^\n                  (duplicated_state1 + duplicated_state2);\n  // We now have a data `ptr` with at most 64 bytes and the current state\n  // of the hashing state machine stored in current_state.\n  if (len > 32) {\n    current_state = Mix32Bytes(ptr, current_state);\n  }\n\n  // We now have a data `ptr` with at most 32 bytes and the current state\n  // of the hashing state machine stored in current_state. But we can\n  // safely read from `ptr + len - 32`.\n  return Mix32Bytes(last_32_ptr, current_state);\n}\n#endif  // ABSL_AES_INTERNAL_HAVE_X86_SIMD\n\n[[maybe_unused]] uint64_t LowLevelHashLenGt32(uint64_t seed, const void* data,\n                                              size_t len) {\n  assert(len > 32);\n  if (ABSL_PREDICT_FALSE(len > 64)) {\n    return LowLevelHashLenGt64(seed, data, len);\n  }\n  return LowLevelHash33To64(seed, static_cast<const uint8_t*>(data), len);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t HashBlockOn32Bit(\n    uint64_t state, const unsigned char* data, size_t len) {\n  // TODO(b/417141985): expose and use CityHash32WithSeed.\n  // Note: we can't use PrecombineLengthMix here because len can be up to 1024.\n  return CombineRawImpl(\n      state + len,\n      hash_internal::CityHash32(reinterpret_cast<const char*>(data), len));\n}\n\nABSL_ATTRIBUTE_NOINLINE uint64_t\nSplitAndCombineOn32Bit(uint64_t state, const unsigned char* first, size_t len) {\n  while (len >= PiecewiseChunkSize()) {\n    state = HashBlockOn32Bit(state, first, PiecewiseChunkSize());\n    len -= PiecewiseChunkSize();\n    first += PiecewiseChunkSize();\n  }\n  // Do not call CombineContiguousImpl for empty range since it is modifying\n  // state.\n  if (len == 0) {\n    return state;\n  }\n  // Handle the remainder.\n  return CombineContiguousImpl(state, first, len,\n                               std::integral_constant<int, 4>{});\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t HashBlockOn64Bit(\n    uint64_t state, const unsigned char* data, size_t len) {\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  return LowLevelHashLenGt32(state, data, len);\n#else\n  return hash_internal::CityHash64WithSeed(reinterpret_cast<const char*>(data),\n                                           len, state);\n#endif\n}\n\nABSL_ATTRIBUTE_NOINLINE uint64_t\nSplitAndCombineOn64Bit(uint64_t state, const unsigned char* first, size_t len) {\n  while (len >= PiecewiseChunkSize()) {\n    state = HashBlockOn64Bit(state, first, PiecewiseChunkSize());\n    len -= PiecewiseChunkSize();\n    first += PiecewiseChunkSize();\n  }\n  // Do not call CombineContiguousImpl for empty range since it is modifying\n  // state.\n  if (len == 0) {\n    return state;\n  }\n  // Handle the remainder.\n  return CombineContiguousImpl(state, first, len,\n                               std::integral_constant<int, 8>{});\n}\n\n}  // namespace\n\nuint64_t CombineLargeContiguousImplOn32BitLengthGt8(uint64_t state,\n                                                    const unsigned char* first,\n                                                    size_t len) {\n  assert(len > 8);\n  assert(sizeof(size_t) == 4);  // NOLINT(misc-static-assert)\n  if (ABSL_PREDICT_TRUE(len <= PiecewiseChunkSize())) {\n    return HashBlockOn32Bit(state, first, len);\n  }\n  return SplitAndCombineOn32Bit(state, first, len);\n}\n\nuint64_t CombineLargeContiguousImplOn64BitLengthGt32(uint64_t state,\n                                                     const unsigned char* first,\n                                                     size_t len) {\n  assert(len > 32);\n  assert(sizeof(size_t) == 8);  // NOLINT(misc-static-assert)\n  if (ABSL_PREDICT_TRUE(len <= PiecewiseChunkSize())) {\n    return HashBlockOn64Bit(state, first, len);\n  }\n  return SplitAndCombineOn64Bit(state, first, len);\n}\n\nABSL_CONST_INIT const void* const MixingHashState::kSeed = &kSeed;\n\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/hash/internal/hash.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: hash.h\n// -----------------------------------------------------------------------------\n//\n#ifndef ABSL_HASH_INTERNAL_HASH_H_\n#define ABSL_HASH_INTERNAL_HASH_H_\n\n#ifdef __APPLE__\n#include <Availability.h>\n#include <TargetConditionals.h>\n#endif\n\n// We include config.h here to make sure that ABSL_INTERNAL_CPLUSPLUS_LANG is\n// defined.\n#include \"absl/base/config.h\"\n\n// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using\n// <version> instead, even though <version> is not available in C++17 mode prior\n// to GCC9.\n#if defined(__has_include)\n#if __has_include(<version>)\n#define ABSL_INTERNAL_VERSION_HEADER_AVAILABLE 1\n#endif\n#endif\n\n// For feature testing and determining which headers can be included.\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || \\\n    defined(ABSL_INTERNAL_VERSION_HEADER_AVAILABLE)\n#include <version>\n#else\n#include <ciso646>\n#endif\n\n#undef ABSL_INTERNAL_VERSION_HEADER_AVAILABLE\n\n#include <algorithm>\n#include <array>\n#include <bitset>\n#include <cassert>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <deque>\n#include <forward_list>\n#include <functional>\n#include <iterator>\n#include <limits>\n#include <list>\n#include <map>\n#include <memory>\n#include <optional>\n#include <set>\n#include <string>\n#include <string_view>\n#include <tuple>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <variant>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/unaligned_access.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n#include \"absl/container/fixed_array.h\"\n#include \"absl/hash/internal/city.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n#include \"absl/types/variant.h\"\n#include \"absl/utility/utility.h\"\n\n#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \\\n    !defined(__XTENSA__)\n#include <filesystem>  // NOLINT\n#endif\n\n// 32-bit builds with SSE 4.2 do not have _mm_crc32_u64, so the\n// __x86_64__ condition is necessary.\n#if defined(__SSE4_2__) && defined(__x86_64__)\n\n#include <x86intrin.h>\n#define ABSL_HASH_INTERNAL_HAS_CRC32\n#define ABSL_HASH_INTERNAL_CRC32_U64 _mm_crc32_u64\n#define ABSL_HASH_INTERNAL_CRC32_U32 _mm_crc32_u32\n#define ABSL_HASH_INTERNAL_CRC32_U8 _mm_crc32_u8\n\n// 32-bit builds with AVX do not have _mm_crc32_u64, so the _M_X64 condition is\n// necessary.\n#elif defined(_MSC_VER) && !defined(__clang__) && defined(__AVX__) && \\\n    defined(_M_X64)\n\n// MSVC AVX (/arch:AVX) implies SSE 4.2.\n#include <intrin.h>\n#define ABSL_HASH_INTERNAL_HAS_CRC32\n#define ABSL_HASH_INTERNAL_CRC32_U64 _mm_crc32_u64\n#define ABSL_HASH_INTERNAL_CRC32_U32 _mm_crc32_u32\n#define ABSL_HASH_INTERNAL_CRC32_U8 _mm_crc32_u8\n\n#elif defined(__ARM_FEATURE_CRC32)\n\n#include <arm_acle.h>\n#define ABSL_HASH_INTERNAL_HAS_CRC32\n// Casting to uint32_t to be consistent with x86 intrinsic (_mm_crc32_u64\n// accepts crc as 64 bit integer).\n#define ABSL_HASH_INTERNAL_CRC32_U64(crc, data) \\\n  __crc32cd(static_cast<uint32_t>(crc), data)\n#define ABSL_HASH_INTERNAL_CRC32_U32 __crc32cw\n#define ABSL_HASH_INTERNAL_CRC32_U8 __crc32cb\n\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass HashState;\n\nnamespace hash_internal {\n\n// Internal detail: Large buffers are hashed in smaller chunks.  This function\n// returns the size of these chunks.\nconstexpr size_t PiecewiseChunkSize() { return 1024; }\n\n// PiecewiseCombiner is an internal-only helper class for hashing a piecewise\n// buffer of `char` or `unsigned char` as though it were contiguous.  This class\n// provides two methods:\n//\n//   H add_buffer(state, data, size)\n//   H finalize(state)\n//\n// `add_buffer` can be called zero or more times, followed by a single call to\n// `finalize`.  This will produce the same hash expansion as concatenating each\n// buffer piece into a single contiguous buffer, and passing this to\n// `H::combine_contiguous`.\n//\n//  Example usage:\n//    PiecewiseCombiner combiner;\n//    for (const auto& piece : pieces) {\n//      state = combiner.add_buffer(std::move(state), piece.data, piece.size);\n//    }\n//    return combiner.finalize(std::move(state));\nclass PiecewiseCombiner {\n public:\n  PiecewiseCombiner() = default;\n  PiecewiseCombiner(const PiecewiseCombiner&) = delete;\n  PiecewiseCombiner& operator=(const PiecewiseCombiner&) = delete;\n\n  // Appends the given range of bytes to the sequence to be hashed, which may\n  // modify the provided hash state.\n  template <typename H>\n  H add_buffer(H state, const unsigned char* data, size_t size);\n  template <typename H>\n  H add_buffer(H state, const char* data, size_t size) {\n    return add_buffer(std::move(state),\n                      reinterpret_cast<const unsigned char*>(data), size);\n  }\n\n  // Finishes combining the hash sequence, which may may modify the provided\n  // hash state.\n  //\n  // Once finalize() is called, add_buffer() may no longer be called. The\n  // resulting hash state will be the same as if the pieces passed to\n  // add_buffer() were concatenated into a single flat buffer, and then provided\n  // to H::combine_contiguous().\n  template <typename H>\n  H finalize(H state);\n\n private:\n  unsigned char buf_[PiecewiseChunkSize()];\n  size_t position_ = 0;\n  bool added_something_ = false;\n};\n\n// Trait class which returns true if T is hashable by the absl::Hash framework.\n// Used for the AbslHashValue implementations for composite types below.\ntemplate <typename T>\nstruct is_hashable;\n\n// HashStateBase is an internal implementation detail that contains common\n// implementation details for all of the \"hash state objects\" objects generated\n// by Abseil.  This is not a public API; users should not create classes that\n// inherit from this.\n//\n// A hash state object is the template argument `H` passed to `AbslHashValue`.\n// It represents an intermediate state in the computation of an unspecified hash\n// algorithm. `HashStateBase` provides a CRTP style base class for hash state\n// implementations. Developers adding type support for `absl::Hash` should not\n// rely on any parts of the state object other than the following member\n// functions:\n//\n//   * HashStateBase::combine()\n//   * HashStateBase::combine_contiguous()\n//   * HashStateBase::combine_unordered()\n//\n// A derived hash state class of type `H` must provide a public member function\n// with a signature similar to the following:\n//\n//    `static H combine_contiguous(H state, const unsigned char*, size_t)`.\n//\n// It must also provide a private template method named RunCombineUnordered.\n//\n// A \"consumer\" is a 1-arg functor returning void.  Its argument is a reference\n// to an inner hash state object, and it may be called multiple times.  When\n// called, the functor consumes the entropy from the provided state object,\n// and resets that object to its empty state.\n//\n// A \"combiner\" is a stateless 2-arg functor returning void.  Its arguments are\n// an inner hash state object and an ElementStateConsumer functor.  A combiner\n// uses the provided inner hash state object to hash each element of the\n// container, passing the inner hash state object to the consumer after hashing\n// each element.\n//\n// Given these definitions, a derived hash state class of type H\n// must provide a private template method with a signature similar to the\n// following:\n//\n//    `template <typename CombinerT>`\n//    `static H RunCombineUnordered(H outer_state, CombinerT combiner)`\n//\n// This function is responsible for constructing the inner state object and\n// providing a consumer to the combiner.  It uses side effects of the consumer\n// and combiner to mix the state of each element in an order-independent manner,\n// and uses this to return an updated value of `outer_state`.\n//\n// This inside-out approach generates efficient object code in the normal case,\n// but allows us to use stack storage to implement the absl::HashState type\n// erasure mechanism (avoiding heap allocations while hashing).\n//\n// `HashStateBase` will provide a complete implementation for a hash state\n// object in terms of these two methods.\n//\n// Example:\n//\n//   // Use CRTP to define your derived class.\n//   struct MyHashState : HashStateBase<MyHashState> {\n//       static H combine_contiguous(H state, const unsigned char*, size_t);\n//       using MyHashState::HashStateBase::combine;\n//       using MyHashState::HashStateBase::combine_contiguous;\n//       using MyHashState::HashStateBase::combine_unordered;\n//     private:\n//       template <typename CombinerT>\n//       static H RunCombineUnordered(H state, CombinerT combiner);\n//   };\ntemplate <typename H>\nclass HashStateBase {\n public:\n  // Combines an arbitrary number of values into a hash state, returning the\n  // updated state.\n  //\n  // Each of the value types `T` must be separately hashable by the Abseil\n  // hashing framework.\n  //\n  // NOTE:\n  //\n  //   state = H::combine(std::move(state), value1, value2, value3);\n  //\n  // is guaranteed to produce the same hash expansion as:\n  //\n  //   state = H::combine(std::move(state), value1);\n  //   state = H::combine(std::move(state), value2);\n  //   state = H::combine(std::move(state), value3);\n  template <typename T, typename... Ts>\n  static H combine(H state, const T& value, const Ts&... values);\n  static H combine(H state) { return state; }\n\n  // Combines a contiguous array of `size` elements into a hash state, returning\n  // the updated state.\n  //\n  // NOTE:\n  //\n  //   state = H::combine_contiguous(std::move(state), data, size);\n  //\n  // is NOT guaranteed to produce the same hash expansion as a for-loop (it may\n  // perform internal optimizations).  If you need this guarantee, use the\n  // for-loop instead.\n  template <typename T>\n  static H combine_contiguous(H state, const T* data, size_t size);\n\n  template <typename I>\n  static H combine_unordered(H state, I begin, I end);\n\n  using AbslInternalPiecewiseCombiner = PiecewiseCombiner;\n\n  template <typename T>\n  using is_hashable = absl::hash_internal::is_hashable<T>;\n\n private:\n  // Common implementation of the iteration step of a \"combiner\", as described\n  // above.\n  template <typename I>\n  struct CombineUnorderedCallback {\n    I begin;\n    I end;\n\n    template <typename InnerH, typename ElementStateConsumer>\n    void operator()(InnerH inner_state, ElementStateConsumer cb) {\n      for (; begin != end; ++begin) {\n        inner_state = H::combine(std::move(inner_state), *begin);\n        cb(inner_state);\n      }\n    }\n  };\n};\n\n// `is_uniquely_represented<T>` is a trait class that indicates whether `T`\n// is uniquely represented.\n//\n// A type is \"uniquely represented\" if two equal values of that type are\n// guaranteed to have the same bytes in their underlying storage. In other\n// words, if `a == b`, then `memcmp(&a, &b, sizeof(T))` is guaranteed to be\n// zero. This property cannot be detected automatically, so this trait is false\n// by default, but can be specialized by types that wish to assert that they are\n// uniquely represented. This makes them eligible for certain optimizations.\n//\n// If you have any doubt whatsoever, do not specialize this template.\n// The default is completely safe, and merely disables some optimizations\n// that will not matter for most types. Specializing this template,\n// on the other hand, can be very hazardous.\n//\n// To be uniquely represented, a type must not have multiple ways of\n// representing the same value; for example, float and double are not\n// uniquely represented, because they have distinct representations for\n// +0 and -0. Furthermore, the type's byte representation must consist\n// solely of user-controlled data, with no padding bits and no compiler-\n// controlled data such as vptrs or sanitizer metadata. This is usually\n// very difficult to guarantee, because in most cases the compiler can\n// insert data and padding bits at its own discretion.\n//\n// If you specialize this template for a type `T`, you must do so in the file\n// that defines that type (or in this file). If you define that specialization\n// anywhere else, `is_uniquely_represented<T>` could have different meanings\n// in different places.\n//\n// The Enable parameter is meaningless; it is provided as a convenience,\n// to support certain SFINAE techniques when defining specializations.\ntemplate <typename T, typename Enable = void>\nstruct is_uniquely_represented : std::false_type {};\n\n// unsigned char is a synonym for \"byte\", so it is guaranteed to be\n// uniquely represented.\ntemplate <>\nstruct is_uniquely_represented<unsigned char> : std::true_type {};\n\n// is_uniquely_represented for non-standard integral types\n//\n// Integral types other than bool should be uniquely represented on any\n// platform that this will plausibly be ported to.\ntemplate <typename Integral>\nstruct is_uniquely_represented<\n    Integral, typename std::enable_if<std::is_integral<Integral>::value>::type>\n    : std::true_type {};\n\ntemplate <>\nstruct is_uniquely_represented<bool> : std::false_type {};\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n// Specialize the trait for GNU extension types.\ntemplate <>\nstruct is_uniquely_represented<__int128> : std::true_type {};\ntemplate <>\nstruct is_uniquely_represented<unsigned __int128> : std::true_type {};\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\ntemplate <typename T>\nstruct FitsIn64Bits : std::integral_constant<bool, sizeof(T) <= 8> {};\n\nstruct CombineRaw {\n  template <typename H>\n  H operator()(H state, uint64_t value) const {\n    return H::combine_raw(std::move(state), value);\n  }\n};\n\n// For use in `raw_hash_set` to pass a seed to the hash function.\nstruct HashWithSeed {\n  template <typename Hasher, typename T>\n  size_t hash(const Hasher& hasher, const T& value, size_t seed) const {\n    // NOLINTNEXTLINE(clang-diagnostic-sign-conversion)\n    return hasher.hash_with_seed(value, seed);\n  }\n};\n\n// Convenience function that combines `hash_state` with the byte representation\n// of `value`.\ntemplate <typename H, typename T,\n          absl::enable_if_t<FitsIn64Bits<T>::value, int> = 0>\nH hash_bytes(H hash_state, const T& value) {\n  const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);\n  uint64_t v;\n  if constexpr (sizeof(T) == 1) {\n    v = *start;\n  } else if constexpr (sizeof(T) == 2) {\n    v = absl::base_internal::UnalignedLoad16(start);\n  } else if constexpr (sizeof(T) == 4) {\n    v = absl::base_internal::UnalignedLoad32(start);\n  } else {\n    static_assert(sizeof(T) == 8);\n    v = absl::base_internal::UnalignedLoad64(start);\n  }\n  return CombineRaw()(std::move(hash_state), v);\n}\ntemplate <typename H, typename T,\n          absl::enable_if_t<!FitsIn64Bits<T>::value, int> = 0>\nH hash_bytes(H hash_state, const T& value) {\n  const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);\n  return H::combine_contiguous(std::move(hash_state), start, sizeof(value));\n}\n\ntemplate <typename H>\nH hash_weakly_mixed_integer(H hash_state, WeaklyMixedInteger value) {\n  return H::combine_weakly_mixed_integer(std::move(hash_state), value);\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Basic Types\n// -----------------------------------------------------------------------------\n\n// Note: Default `AbslHashValue` implementations live in `hash_internal`. This\n// allows us to block lexical scope lookup when doing an unqualified call to\n// `AbslHashValue` below. User-defined implementations of `AbslHashValue` can\n// only be found via ADL.\n\n// AbslHashValue() for hashing bool values\n//\n// We use SFINAE to ensure that this overload only accepts bool, not types that\n// are convertible to bool.\ntemplate <typename H, typename B>\ntypename std::enable_if<std::is_same<B, bool>::value, H>::type AbslHashValue(\n    H hash_state, B value) {\n  // We use ~size_t{} instead of 1 so that all bits are different between\n  // true/false instead of only 1.\n  return H::combine(std::move(hash_state),\n                    static_cast<size_t>(value ? ~size_t{} : 0));\n}\n\n// AbslHashValue() for hashing enum values\ntemplate <typename H, typename Enum>\ntypename std::enable_if<std::is_enum<Enum>::value, H>::type AbslHashValue(\n    H hash_state, Enum e) {\n  // In practice, we could almost certainly just invoke hash_bytes directly,\n  // but it's possible that a sanitizer might one day want to\n  // store data in the unused bits of an enum. To avoid that risk, we\n  // convert to the underlying type before hashing. Hopefully this will get\n  // optimized away; if not, we can reopen discussion with c-toolchain-team.\n  return H::combine(std::move(hash_state),\n                    static_cast<typename std::underlying_type<Enum>::type>(e));\n}\n// AbslHashValue() for hashing floating-point values\ntemplate <typename H, typename Float>\ntypename std::enable_if<std::is_same<Float, float>::value ||\n                            std::is_same<Float, double>::value,\n                        H>::type\nAbslHashValue(H hash_state, Float value) {\n  return hash_internal::hash_bytes(std::move(hash_state),\n                                   value == 0 ? 0 : value);\n}\n\n// Long double has the property that it might have extra unused bytes in it.\n// For example, in x86 sizeof(long double)==16 but it only really uses 80-bits\n// of it. This means we can't use hash_bytes on a long double and have to\n// convert it to something else first.\ntemplate <typename H, typename LongDouble>\ntypename std::enable_if<std::is_same<LongDouble, long double>::value, H>::type\nAbslHashValue(H hash_state, LongDouble value) {\n  const int category = std::fpclassify(value);\n  switch (category) {\n    case FP_INFINITE:\n      // Add the sign bit to differentiate between +Inf and -Inf\n      hash_state = H::combine(std::move(hash_state), std::signbit(value));\n      break;\n\n    case FP_NAN:\n    case FP_ZERO:\n    default:\n      // Category is enough for these.\n      break;\n\n    case FP_NORMAL:\n    case FP_SUBNORMAL:\n      // We can't convert `value` directly to double because this would have\n      // undefined behavior if the value is out of range.\n      // std::frexp gives us a value in the range (-1, -.5] or [.5, 1) that is\n      // guaranteed to be in range for `double`. The truncation is\n      // implementation defined, but that works as long as it is deterministic.\n      int exp;\n      auto mantissa = static_cast<double>(std::frexp(value, &exp));\n      hash_state = H::combine(std::move(hash_state), mantissa, exp);\n  }\n\n  return H::combine(std::move(hash_state), category);\n}\n\n// Without this overload, an array decays to a pointer and we hash that, which\n// is not likely to be what the caller intended.\ntemplate <typename H, typename T, size_t N>\nH AbslHashValue(H hash_state, T (&)[N]) {\n  static_assert(\n      sizeof(T) == -1,\n      \"Hashing C arrays is not allowed. For string literals, wrap the literal \"\n      \"in absl::string_view(). To hash the array contents, use \"\n      \"absl::MakeSpan() or make the array an std::array. To hash the array \"\n      \"address, use &array[0].\");\n  return hash_state;\n}\n\n// AbslHashValue() for hashing pointers\ntemplate <typename H, typename T>\nstd::enable_if_t<std::is_pointer<T>::value, H> AbslHashValue(H hash_state,\n                                                             T ptr) {\n  auto v = reinterpret_cast<uintptr_t>(ptr);\n  // Due to alignment, pointers tend to have low bits as zero, and the next few\n  // bits follow a pattern since they are also multiples of some base value.\n  // The PointerAlignment test verifies that our mixing is good enough to handle\n  // these cases.\n  return H::combine(std::move(hash_state), v);\n}\n\n// AbslHashValue() for hashing nullptr_t\ntemplate <typename H>\nH AbslHashValue(H hash_state, std::nullptr_t) {\n  return H::combine(std::move(hash_state), static_cast<void*>(nullptr));\n}\n\n// AbslHashValue() for hashing pointers-to-member\ntemplate <typename H, typename T, typename C>\nH AbslHashValue(H hash_state, T C::*ptr) {\n  auto salient_ptm_size = [](std::size_t n) -> std::size_t {\n#if defined(_MSC_VER)\n    // Pointers-to-member-function on MSVC consist of one pointer plus 0, 1, 2,\n    // or 3 ints. In 64-bit mode, they are 8-byte aligned and thus can contain\n    // padding (namely when they have 1 or 3 ints). The value below is a lower\n    // bound on the number of salient, non-padding bytes that we use for\n    // hashing.\n    if constexpr (alignof(T C::*) == alignof(int)) {\n      // No padding when all subobjects have the same size as the total\n      // alignment. This happens in 32-bit mode.\n      return n;\n    } else {\n      // Padding for 1 int (size 16) or 3 ints (size 24).\n      // With 2 ints, the size is 16 with no padding, which we pessimize.\n      return n == 24 ? 20 : n == 16 ? 12 : n;\n    }\n#else\n  // On other platforms, we assume that pointers-to-members do not have\n  // padding.\n#ifdef __cpp_lib_has_unique_object_representations\n    static_assert(std::has_unique_object_representations<T C::*>::value);\n#endif  // __cpp_lib_has_unique_object_representations\n    return n;\n#endif\n  };\n  return H::combine_contiguous(std::move(hash_state),\n                               reinterpret_cast<unsigned char*>(&ptr),\n                               salient_ptm_size(sizeof ptr));\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Composite Types\n// -----------------------------------------------------------------------------\n\n// AbslHashValue() for hashing pairs\ntemplate <typename H, typename T1, typename T2>\ntypename std::enable_if<is_hashable<T1>::value && is_hashable<T2>::value,\n                        H>::type\nAbslHashValue(H hash_state, const std::pair<T1, T2>& p) {\n  return H::combine(std::move(hash_state), p.first, p.second);\n}\n\n// Helper function for hashing a tuple. The third argument should\n// be an index_sequence running from 0 to tuple_size<Tuple> - 1.\ntemplate <typename H, typename Tuple, size_t... Is>\nH hash_tuple(H hash_state, const Tuple& t, absl::index_sequence<Is...>) {\n  return H::combine(std::move(hash_state), std::get<Is>(t)...);\n}\n\n// AbslHashValue for hashing tuples\ntemplate <typename H, typename... Ts>\n#if defined(_MSC_VER)\n// This SFINAE gets MSVC confused under some conditions. Let's just disable it\n// for now.\nH\n#else   // _MSC_VER\ntypename std::enable_if<absl::conjunction<is_hashable<Ts>...>::value, H>::type\n#endif  // _MSC_VER\nAbslHashValue(H hash_state, const std::tuple<Ts...>& t) {\n  return hash_internal::hash_tuple(std::move(hash_state), t,\n                                   absl::make_index_sequence<sizeof...(Ts)>());\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Pointers\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing unique_ptr\ntemplate <typename H, typename T, typename D>\nH AbslHashValue(H hash_state, const std::unique_ptr<T, D>& ptr) {\n  return H::combine(std::move(hash_state), ptr.get());\n}\n\n// AbslHashValue for hashing shared_ptr\ntemplate <typename H, typename T>\nH AbslHashValue(H hash_state, const std::shared_ptr<T>& ptr) {\n  return H::combine(std::move(hash_state), ptr.get());\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for String-Like Types\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing strings\n//\n// All the string-like types supported here provide the same hash expansion for\n// the same character sequence. These types are:\n//\n//  - `absl::Cord`\n//  - `std::string` (and std::basic_string<T, std::char_traits<T>, A> for\n//      any allocator A and any T in {char, wchar_t, char16_t, char32_t})\n//  - `absl::string_view`, `std::string_view`, `std::wstring_view`,\n//    `std::u16string_view`, and `std::u32_string_view`.\n//\n// For simplicity, we currently support only strings built on `char`, `wchar_t`,\n// `char16_t`, or `char32_t`. This support may be broadened, if necessary, but\n// with some caution - this overload would misbehave in cases where the traits'\n// `eq()` member isn't equivalent to `==` on the underlying character type.\ntemplate <typename H>\nH AbslHashValue(H hash_state, absl::string_view str) {\n  return H::combine_contiguous(std::move(hash_state), str.data(), str.size());\n}\n\n// Support std::wstring, std::u16string and std::u32string.\ntemplate <typename Char, typename Alloc, typename H,\n          typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||\n                                       std::is_same<Char, char16_t>::value ||\n                                       std::is_same<Char, char32_t>::value>>\nH AbslHashValue(\n    H hash_state,\n    const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) {\n  return H::combine_contiguous(std::move(hash_state), str.data(), str.size());\n}\n\n// Support std::wstring_view, std::u16string_view and std::u32string_view.\ntemplate <typename Char, typename H,\n          typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||\n                                       std::is_same<Char, char16_t>::value ||\n                                       std::is_same<Char, char32_t>::value>>\nH AbslHashValue(H hash_state, std::basic_string_view<Char> str) {\n  return H::combine_contiguous(std::move(hash_state), str.data(), str.size());\n}\n\n#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \\\n    (!defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) ||        \\\n     __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) &&       \\\n    (!defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||         \\\n     __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500) &&        \\\n    (!defined(__XTENSA__))\n\n#define ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE 1\n\n// Support std::filesystem::path. The SFINAE is required because some string\n// types are implicitly convertible to std::filesystem::path.\ntemplate <typename Path, typename H,\n          typename = absl::enable_if_t<\n              std::is_same_v<Path, std::filesystem::path>>>\nH AbslHashValue(H hash_state, const Path& path) {\n  // This is implemented by deferring to the standard library to compute the\n  // hash.  The standard library requires that for two paths, `p1 == p2`, then\n  // `hash_value(p1) == hash_value(p2)`. `AbslHashValue` has the same\n  // requirement. Since `operator==` does platform specific matching, deferring\n  // to the standard library is the simplest approach.\n  return H::combine(std::move(hash_state), std::filesystem::hash_value(path));\n}\n\n#endif  // ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Sequence Containers\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing std::array\ntemplate <typename H, typename T, size_t N>\ntypename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(\n    H hash_state, const std::array<T, N>& array) {\n  return H::combine_contiguous(std::move(hash_state), array.data(),\n                               array.size());\n}\n\n// AbslHashValue for hashing std::deque\ntemplate <typename H, typename T, typename Allocator>\ntypename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(\n    H hash_state, const std::deque<T, Allocator>& deque) {\n  // TODO(gromer): investigate a more efficient implementation taking\n  // advantage of the chunk structure.\n  for (const auto& t : deque) {\n    hash_state = H::combine(std::move(hash_state), t);\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{deque.size()});\n}\n\n// AbslHashValue for hashing std::forward_list\ntemplate <typename H, typename T, typename Allocator>\ntypename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(\n    H hash_state, const std::forward_list<T, Allocator>& list) {\n  size_t size = 0;\n  for (const T& t : list) {\n    hash_state = H::combine(std::move(hash_state), t);\n    ++size;\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{size});\n}\n\n// AbslHashValue for hashing std::list\ntemplate <typename H, typename T, typename Allocator>\ntypename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(\n    H hash_state, const std::list<T, Allocator>& list) {\n  for (const auto& t : list) {\n    hash_state = H::combine(std::move(hash_state), t);\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{list.size()});\n}\n\n// AbslHashValue for hashing std::vector\n//\n// Do not use this for vector<bool> on platforms that have a working\n// implementation of std::hash. It does not have a .data(), and a fallback for\n// std::hash<> is most likely faster.\ntemplate <typename H, typename T, typename Allocator>\ntypename std::enable_if<is_hashable<T>::value && !std::is_same<T, bool>::value,\n                        H>::type\nAbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {\n  return H::combine_contiguous(std::move(hash_state), vector.data(),\n                               vector.size());\n}\n\n// AbslHashValue special cases for hashing std::vector<bool>\n\n#if defined(ABSL_IS_BIG_ENDIAN) && \\\n    (defined(__GLIBCXX__) || defined(__GLIBCPP__))\n\n// std::hash in libstdc++ does not work correctly with vector<bool> on Big\n// Endian platforms therefore we need to implement a custom AbslHashValue for\n// it. More details on the bug:\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102531\ntemplate <typename H, typename T, typename Allocator>\ntypename std::enable_if<is_hashable<T>::value && std::is_same<T, bool>::value,\n                        H>::type\nAbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {\n  typename H::AbslInternalPiecewiseCombiner combiner;\n  for (const auto& i : vector) {\n    unsigned char c = static_cast<unsigned char>(i);\n    hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));\n  }\n  return H::combine(combiner.finalize(std::move(hash_state)),\n                    WeaklyMixedInteger{vector.size()});\n}\n#else\n// When not working around the libstdc++ bug above, we still have to contend\n// with the fact that std::hash<vector<bool>> is often poor quality, hashing\n// directly on the internal words and on no other state.  On these platforms,\n// vector<bool>{1, 1} and vector<bool>{1, 1, 0} hash to the same value.\n//\n// Mixing in the size (as we do in our other vector<> implementations) on top\n// of the library-provided hash implementation avoids this QOI issue.\ntemplate <typename H, typename T, typename Allocator>\ntypename std::enable_if<is_hashable<T>::value && std::is_same<T, bool>::value,\n                        H>::type\nAbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {\n  return H::combine(std::move(hash_state),\n                    std::hash<std::vector<T, Allocator>>{}(vector),\n                    WeaklyMixedInteger{vector.size()});\n}\n#endif\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Ordered Associative Containers\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing std::map\ntemplate <typename H, typename Key, typename T, typename Compare,\n          typename Allocator>\ntypename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,\n                        H>::type\nAbslHashValue(H hash_state, const std::map<Key, T, Compare, Allocator>& map) {\n  for (const auto& t : map) {\n    hash_state = H::combine(std::move(hash_state), t);\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{map.size()});\n}\n\n// AbslHashValue for hashing std::multimap\ntemplate <typename H, typename Key, typename T, typename Compare,\n          typename Allocator>\ntypename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,\n                        H>::type\nAbslHashValue(H hash_state,\n              const std::multimap<Key, T, Compare, Allocator>& map) {\n  for (const auto& t : map) {\n    hash_state = H::combine(std::move(hash_state), t);\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{map.size()});\n}\n\n// AbslHashValue for hashing std::set\ntemplate <typename H, typename Key, typename Compare, typename Allocator>\ntypename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(\n    H hash_state, const std::set<Key, Compare, Allocator>& set) {\n  for (const auto& t : set) {\n    hash_state = H::combine(std::move(hash_state), t);\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{set.size()});\n}\n\n// AbslHashValue for hashing std::multiset\ntemplate <typename H, typename Key, typename Compare, typename Allocator>\ntypename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(\n    H hash_state, const std::multiset<Key, Compare, Allocator>& set) {\n  for (const auto& t : set) {\n    hash_state = H::combine(std::move(hash_state), t);\n  }\n  return H::combine(std::move(hash_state), WeaklyMixedInteger{set.size()});\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Unordered Associative Containers\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing std::unordered_set\ntemplate <typename H, typename Key, typename Hash, typename KeyEqual,\n          typename Alloc>\ntypename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(\n    H hash_state, const std::unordered_set<Key, Hash, KeyEqual, Alloc>& s) {\n  return H::combine(\n      H::combine_unordered(std::move(hash_state), s.begin(), s.end()),\n      WeaklyMixedInteger{s.size()});\n}\n\n// AbslHashValue for hashing std::unordered_multiset\ntemplate <typename H, typename Key, typename Hash, typename KeyEqual,\n          typename Alloc>\ntypename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(\n    H hash_state,\n    const std::unordered_multiset<Key, Hash, KeyEqual, Alloc>& s) {\n  return H::combine(\n      H::combine_unordered(std::move(hash_state), s.begin(), s.end()),\n      WeaklyMixedInteger{s.size()});\n}\n\n// AbslHashValue for hashing std::unordered_set\ntemplate <typename H, typename Key, typename T, typename Hash,\n          typename KeyEqual, typename Alloc>\ntypename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,\n                        H>::type\nAbslHashValue(H hash_state,\n              const std::unordered_map<Key, T, Hash, KeyEqual, Alloc>& s) {\n  return H::combine(\n      H::combine_unordered(std::move(hash_state), s.begin(), s.end()),\n      WeaklyMixedInteger{s.size()});\n}\n\n// AbslHashValue for hashing std::unordered_multiset\ntemplate <typename H, typename Key, typename T, typename Hash,\n          typename KeyEqual, typename Alloc>\ntypename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,\n                        H>::type\nAbslHashValue(H hash_state,\n              const std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>& s) {\n  return H::combine(\n      H::combine_unordered(std::move(hash_state), s.begin(), s.end()),\n      WeaklyMixedInteger{s.size()});\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Wrapper Types\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing std::reference_wrapper\ntemplate <typename H, typename T>\ntypename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(\n    H hash_state, std::reference_wrapper<T> opt) {\n  return H::combine(std::move(hash_state), opt.get());\n}\n\n// AbslHashValue for hashing std::optional\ntemplate <typename H, typename T>\ntypename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(\n    H hash_state, const std::optional<T>& opt) {\n  if (opt) hash_state = H::combine(std::move(hash_state), *opt);\n  return H::combine(std::move(hash_state), opt.has_value());\n}\n\ntemplate <typename H>\nstruct VariantVisitor {\n  H&& hash_state;\n  template <typename T>\n  H operator()(const T& t) const {\n    return H::combine(std::move(hash_state), t);\n  }\n};\n\n// AbslHashValue for hashing std::variant\ntemplate <typename H, typename... T>\ntypename std::enable_if<conjunction<is_hashable<T>...>::value, H>::type\nAbslHashValue(H hash_state, const std::variant<T...>& v) {\n  if (!v.valueless_by_exception()) {\n    hash_state = std::visit(VariantVisitor<H>{std::move(hash_state)}, v);\n  }\n  return H::combine(std::move(hash_state), v.index());\n}\n\n// -----------------------------------------------------------------------------\n// AbslHashValue for Other Types\n// -----------------------------------------------------------------------------\n\n// AbslHashValue for hashing std::bitset is not defined on Little Endian\n// platforms, for the same reason as for vector<bool> (see std::vector above):\n// It does not expose the raw bytes, and a fallback to std::hash<> is most\n// likely faster.\n\n#if defined(ABSL_IS_BIG_ENDIAN) && \\\n    (defined(__GLIBCXX__) || defined(__GLIBCPP__))\n// AbslHashValue for hashing std::bitset\n//\n// std::hash in libstdc++ does not work correctly with std::bitset on Big Endian\n// platforms therefore we need to implement a custom AbslHashValue for it. More\n// details on the bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102531\ntemplate <typename H, size_t N>\nH AbslHashValue(H hash_state, const std::bitset<N>& set) {\n  typename H::AbslInternalPiecewiseCombiner combiner;\n  for (size_t i = 0; i < N; i++) {\n    unsigned char c = static_cast<unsigned char>(set[i]);\n    hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));\n  }\n  return H::combine(combiner.finalize(std::move(hash_state)), N);\n}\n#endif\n\n// -----------------------------------------------------------------------------\n\n// Mixes all values in the range [data, data+size) into the hash state.\n// This overload accepts only uniquely-represented types, and hashes them by\n// hashing the entire range of bytes.\ntemplate <typename H, typename T>\ntypename std::enable_if<is_uniquely_represented<T>::value, H>::type\nhash_range_or_bytes(H hash_state, const T* data, size_t size) {\n  const auto* bytes = reinterpret_cast<const unsigned char*>(data);\n  return H::combine_contiguous(std::move(hash_state), bytes, sizeof(T) * size);\n}\n\ntemplate <typename H, typename T>\ntypename std::enable_if<!is_uniquely_represented<T>::value, H>::type\nhash_range_or_bytes(H hash_state, const T* data, size_t size) {\n  for (const auto end = data + size; data < end; ++data) {\n    hash_state = H::combine(std::move(hash_state), *data);\n  }\n  return H::combine(std::move(hash_state),\n                    hash_internal::WeaklyMixedInteger{size});\n}\n\ninline constexpr uint64_t kMul = uint64_t{0x79d5f9e0de1e8cf5};\n\n// Random data taken from the hexadecimal digits of Pi's fractional component.\n// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number\nABSL_CACHELINE_ALIGNED inline constexpr uint64_t kStaticRandomData[] = {\n    0x243f'6a88'85a3'08d3, 0x1319'8a2e'0370'7344, 0xa409'3822'299f'31d0,\n    0x082e'fa98'ec4e'6c89, 0x4528'21e6'38d0'1377,\n};\n\n// Extremely weak mixture of length that is mixed into the state before\n// combining the data. It is used only for small strings. This also ensures that\n// we have high entropy in all bits of the state.\ninline uint64_t PrecombineLengthMix(uint64_t state, size_t len) {\n  ABSL_ASSUME(len + sizeof(uint64_t) <= sizeof(kStaticRandomData));\n  uint64_t data = absl::base_internal::UnalignedLoad64(\n      reinterpret_cast<const unsigned char*>(&kStaticRandomData[0]) + len);\n  return state ^ data;\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t Mix(uint64_t lhs, uint64_t rhs) {\n  // Though the 128-bit product needs multiple instructions on non-x86-64\n  // platforms, it is still a good balance between speed and hash quality.\n  absl::uint128 m = lhs;\n  m *= rhs;\n  return Uint128High64(m) ^ Uint128Low64(m);\n}\n\n// Suppress erroneous array bounds errors on GCC.\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Warray-bounds\"\n#endif\ninline uint32_t Read4(const unsigned char* p) {\n  return absl::base_internal::UnalignedLoad32(p);\n}\ninline uint64_t Read8(const unsigned char* p) {\n  return absl::base_internal::UnalignedLoad64(p);\n}\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n// Reads 9 to 16 bytes from p.\n// The first 8 bytes are in .first, and the rest of the bytes are in .second\n// along with duplicated bytes from .first if len<16.\ninline std::pair<uint64_t, uint64_t> Read9To16(const unsigned char* p,\n                                               size_t len) {\n  return {Read8(p), Read8(p + len - 8)};\n}\n\n// Reads 4 to 8 bytes from p.\n// Bytes are permuted and some input bytes may be duplicated in output.\ninline uint64_t Read4To8(const unsigned char* p, size_t len) {\n  // If `len < 8`, we duplicate bytes. We always put low memory at the end.\n  // E.g., on little endian platforms:\n  // `ABCD` will be read as `ABCDABCD`.\n  // `ABCDE` will be read as `BCDEABCD`.\n  // `ABCDEF` will be read as `CDEFABCD`.\n  // `ABCDEFG` will be read as `DEFGABCD`.\n  // `ABCDEFGH` will be read as `EFGHABCD`.\n  // We also do not care about endianness. On big-endian platforms, bytes will\n  // be permuted differently. We always shift low memory by 32, because that\n  // can be pipelined earlier. Reading high memory requires computing\n  // `p + len - 4`.\n  uint64_t most_significant =\n      static_cast<uint64_t>(absl::base_internal::UnalignedLoad32(p)) << 32;\n  uint64_t least_significant =\n      absl::base_internal::UnalignedLoad32(p + len - 4);\n  return most_significant | least_significant;\n}\n\n// Reads 1 to 3 bytes from p. Some input bytes may be duplicated in output.\ninline uint32_t Read1To3(const unsigned char* p, size_t len) {\n  // The trick used by this implementation is to avoid branches.\n  // We always read three bytes by duplicating.\n  // E.g.,\n  // `A` is read as `AAA`.\n  // `AB` is read as `ABB`.\n  // `ABC` is read as `ABC`.\n  // We always shift `p[0]` so that it can be pipelined better.\n  // Other bytes require extra computation to find indices.\n  uint32_t mem0 = (static_cast<uint32_t>(p[0]) << 16) | p[len - 1];\n  uint32_t mem1 = static_cast<uint32_t>(p[len / 2]) << 8;\n  return mem0 | mem1;\n}\n\n#ifdef ABSL_HASH_INTERNAL_HAS_CRC32\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineRawImpl(uint64_t state,\n                                                            uint64_t value) {\n  // We use a union to access the high and low 32 bits of the state.\n  union {\n    uint64_t u64;\n    struct {\n#ifdef ABSL_IS_LITTLE_ENDIAN\n      uint32_t low, high;\n#else  // big endian\n      uint32_t high, low;\n#endif\n    } u32s;\n  } s;\n  s.u64 = state;\n  // The general idea here is to do two CRC32 operations in parallel using the\n  // low and high 32 bits of state as CRC states. Note that: (1) when absl::Hash\n  // is inlined into swisstable lookups, we know that the seed's high bits are\n  // zero so s.u32s.high is available immediately. (2) We chose to multiply\n  // value by 3 for the low CRC because (a) multiplication by 3 can be done in 1\n  // cycle on x86/ARM and (b) multiplication has carry bits so it's nonlinear in\n  // GF(2) and therefore ensures that the two CRCs are independent (unlike bit\n  // rotation, XOR, etc). (3) We also tried using addition instead of\n  // multiplication by 3, but (a) code size is larger and (b) if the input keys\n  // all have 0s in the bits where the addition constant has 1s, then the\n  // addition is equivalent to XOR and linear in GF(2). (4) The union makes it\n  // easy for the compiler to understand that the high and low CRC states are\n  // independent from each other so that when CombineRawImpl is repeated (e.g.\n  // for std::pair<size_t, size_t>), the CRC chains can run in parallel. We\n  // originally tried using bswaps rather than shifting by 32 bits (to get from\n  // high to low bits) because bswap is one byte smaller in code size, but the\n  // compiler couldn't understand that the CRC chains were independent.\n  s.u32s.high =\n      static_cast<uint32_t>(ABSL_HASH_INTERNAL_CRC32_U64(s.u32s.high, value));\n  s.u32s.low = static_cast<uint32_t>(\n      ABSL_HASH_INTERNAL_CRC32_U64(s.u32s.low, 3 * value));\n  return s.u64;\n}\n#else   // ABSL_HASH_INTERNAL_HAS_CRC32\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineRawImpl(uint64_t state,\n                                                            uint64_t value) {\n  return Mix(state ^ value, kMul);\n}\n#endif  // ABSL_HASH_INTERNAL_HAS_CRC32\n\n// Slow dispatch path for calls to CombineContiguousImpl with a size argument\n// larger than inlined size. Has the same effect as calling\n// CombineContiguousImpl() repeatedly with the chunk stride size.\nuint64_t CombineLargeContiguousImplOn32BitLengthGt8(uint64_t state,\n                                                    const unsigned char* first,\n                                                    size_t len);\nuint64_t CombineLargeContiguousImplOn64BitLengthGt32(uint64_t state,\n                                                     const unsigned char* first,\n                                                     size_t len);\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineSmallContiguousImpl(\n    uint64_t state, const unsigned char* first, size_t len) {\n  ABSL_ASSUME(len <= 8);\n  uint64_t v;\n  if (len >= 4) {\n    v = Read4To8(first, len);\n  } else if (len > 0) {\n    v = Read1To3(first, len);\n  } else {\n    // Empty string must modify the state.\n    v = 0x57;\n  }\n  return CombineRawImpl(state, v);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineContiguousImpl9to16(\n    uint64_t state, const unsigned char* first, size_t len) {\n  ABSL_ASSUME(len >= 9);\n  ABSL_ASSUME(len <= 16);\n  // Note: any time one half of the mix function becomes zero it will fail to\n  // incorporate any bits from the other half. However, there is exactly 1 in\n  // 2^64 values for each side that achieve this, and only when the size is\n  // exactly 16 -- for smaller sizes there is an overlapping byte that makes\n  // this impossible unless the seed is *also* incredibly unlucky.\n  auto p = Read9To16(first, len);\n  return Mix(state ^ p.first, kMul ^ p.second);\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE inline uint64_t CombineContiguousImpl17to32(\n    uint64_t state, const unsigned char* first, size_t len) {\n  ABSL_ASSUME(len >= 17);\n  ABSL_ASSUME(len <= 32);\n  // Do two mixes of overlapping 16-byte ranges in parallel to minimize\n  // latency.\n  const uint64_t m0 =\n      Mix(Read8(first) ^ kStaticRandomData[1], Read8(first + 8) ^ state);\n\n  const unsigned char* tail_16b_ptr = first + (len - 16);\n  const uint64_t m1 = Mix(Read8(tail_16b_ptr) ^ kStaticRandomData[3],\n                          Read8(tail_16b_ptr + 8) ^ state);\n  return m0 ^ m1;\n}\n\n// Implementation of the base case for combine_contiguous where we actually\n// mix the bytes into the state.\n// Dispatch to different implementations of combine_contiguous depending\n// on the value of `sizeof(size_t)`.\ninline uint64_t CombineContiguousImpl(\n    uint64_t state, const unsigned char* first, size_t len,\n    std::integral_constant<int, 4> /* sizeof_size_t */) {\n  // For large values we use CityHash, for small ones we use custom low latency\n  // hash.\n  if (len <= 8) {\n    return CombineSmallContiguousImpl(PrecombineLengthMix(state, len), first,\n                                      len);\n  }\n  return CombineLargeContiguousImplOn32BitLengthGt8(state, first, len);\n}\n\n#ifdef ABSL_HASH_INTERNAL_HAS_CRC32\ninline uint64_t CombineContiguousImpl(\n    uint64_t state, const unsigned char* first, size_t len,\n    std::integral_constant<int, 8> /* sizeof_size_t */) {\n  if (ABSL_PREDICT_FALSE(len > 32)) {\n    return CombineLargeContiguousImplOn64BitLengthGt32(state, first, len);\n  }\n  // `mul` is the salt that is used for final mixing. It is important to fill\n  // high 32 bits because CRC wipes out high 32 bits.\n  // `rotr` is important to mix `len` into high 32 bits.\n  uint64_t mul = absl::rotr(kMul, static_cast<int>(len));\n  // Only low 32 bits of each uint64_t are used in CRC32 so we use gbswap_64 to\n  // move high 32 bits to low 32 bits. It has slightly smaller binary size than\n  // `>> 32`. `state + 8 * len` is a single instruction on both x86 and ARM, so\n  // we use it to better mix length. Although only the low 32 bits of the pair\n  // elements are used, we use pair<uint64_t, uint64_t> for better generated\n  // code.\n  std::pair<uint64_t, uint64_t> crcs = {state + 8 * len,\n                                        absl::gbswap_64(state)};\n\n  // All CRC operations here directly read bytes from the memory.\n  // Single fused instructions are used, like `crc32 rcx, qword ptr [rsi]`.\n  // On x86, llvm-mca reports latency `R + 2` for such fused instructions, while\n  // `R + 3` for two separate `mov` + `crc` instructions. `R` is the latency of\n  // reading the memory. Fused instructions also reduce register pressure\n  // allowing surrounding code to be more efficient when this code is inlined.\n  if (len > 8) {\n    crcs = {ABSL_HASH_INTERNAL_CRC32_U64(crcs.first, Read8(first)),\n            ABSL_HASH_INTERNAL_CRC32_U64(crcs.second, Read8(first + len - 8))};\n    if (len > 16) {\n      // We compute the second round of dependent CRC32 operations.\n      crcs = {ABSL_HASH_INTERNAL_CRC32_U64(crcs.first, Read8(first + len - 16)),\n              ABSL_HASH_INTERNAL_CRC32_U64(crcs.second, Read8(first + 8))};\n    }\n  } else {\n    if (len >= 4) {\n      // We use CRC for 4 bytes to benefit from the fused instruction and better\n      // hash quality.\n      // Using `xor` or `add` may reduce latency for this case, but would\n      // require more registers, more instructions and will have worse hash\n      // quality.\n      crcs = {ABSL_HASH_INTERNAL_CRC32_U32(static_cast<uint32_t>(crcs.first),\n                                           Read4(first)),\n              ABSL_HASH_INTERNAL_CRC32_U32(static_cast<uint32_t>(crcs.second),\n                                           Read4(first + len - 4))};\n    } else if (len >= 1) {\n      // We mix three bytes all into different output registers.\n      // This way, we do not need shifting of these bytes (so they don't overlap\n      // with each other).\n      crcs = {ABSL_HASH_INTERNAL_CRC32_U8(static_cast<uint32_t>(crcs.first),\n                                          first[0]),\n              ABSL_HASH_INTERNAL_CRC32_U8(static_cast<uint32_t>(crcs.second),\n                                          first[len - 1])};\n      // Middle byte is mixed weaker. It is a new byte only for len == 3.\n      // Mixing is independent from CRC operations so it is scheduled ASAP.\n      mul += first[len / 2];\n    }\n  }\n  // `mul` is mixed into both sides of `Mix` to guarantee non-zero values for\n  // both multiplicands. Using Mix instead of just multiplication here improves\n  // hash quality, especially for short strings.\n  return Mix(mul - crcs.first, crcs.second - mul);\n}\n#else\ninline uint64_t CombineContiguousImpl(\n    uint64_t state, const unsigned char* first, size_t len,\n    std::integral_constant<int, 8> /* sizeof_size_t */) {\n  // For large values we use LowLevelHash or CityHash depending on the platform,\n  // for small ones we use custom low latency hash.\n  if (len <= 8) {\n    return CombineSmallContiguousImpl(PrecombineLengthMix(state, len), first,\n                                      len);\n  }\n  if (len <= 16) {\n    return CombineContiguousImpl9to16(PrecombineLengthMix(state, len), first,\n                                      len);\n  }\n  if (len <= 32) {\n    return CombineContiguousImpl17to32(PrecombineLengthMix(state, len), first,\n                                       len);\n  }\n  // We must not mix length into the state here because calling\n  // CombineContiguousImpl twice with PiecewiseChunkSize() must be equivalent\n  // to calling CombineLargeContiguousImpl once with 2 * PiecewiseChunkSize().\n  return CombineLargeContiguousImplOn64BitLengthGt32(state, first, len);\n}\n#endif  // ABSL_HASH_INTERNAL_HAS_CRC32\n\n#if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE)\n#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1\n#else\n#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0\n#endif\n\n// Type trait to select the appropriate hash implementation to use.\n// HashSelect::type<T> will give the proper hash implementation, to be invoked\n// as:\n//   HashSelect::type<T>::Invoke(state, value)\n// Also, HashSelect::type<T>::value is a boolean equal to `true` if there is a\n// valid `Invoke` function. Types that are not hashable will have a ::value of\n// `false`.\nstruct HashSelect {\n private:\n  struct WeaklyMixedIntegerProbe {\n    template <typename H>\n    static H Invoke(H state, WeaklyMixedInteger value) {\n      return hash_internal::hash_weakly_mixed_integer(std::move(state), value);\n    }\n  };\n\n  struct State : HashStateBase<State> {\n    static State combine_contiguous(State hash_state, const unsigned char*,\n                                    size_t);\n    using State::HashStateBase::combine_contiguous;\n    static State combine_raw(State state, uint64_t value);\n    static State combine_weakly_mixed_integer(State hash_state,\n                                              WeaklyMixedInteger value);\n  };\n\n  struct UniquelyRepresentedProbe {\n    template <typename H, typename T>\n    static auto Invoke(H state, const T& value)\n        -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {\n      return hash_internal::hash_bytes(std::move(state), value);\n    }\n  };\n\n  struct HashValueProbe {\n    template <typename H, typename T>\n    static auto Invoke(H state, const T& value) -> absl::enable_if_t<\n        std::is_same<H,\n                     decltype(AbslHashValue(std::move(state), value))>::value,\n        H> {\n      return AbslHashValue(std::move(state), value);\n    }\n  };\n\n  struct LegacyHashProbe {\n#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_\n    template <typename H, typename T>\n    static auto Invoke(H state, const T& value) -> absl::enable_if_t<\n        std::is_convertible<\n            decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),\n            size_t>::value,\n        H> {\n      return hash_internal::hash_bytes(\n          std::move(state),\n          ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));\n    }\n#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_\n  };\n\n  struct StdHashProbe {\n    template <typename H, typename T>\n    static auto Invoke(H state, const T& value)\n        -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {\n      return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));\n    }\n  };\n\n  template <typename Hash, typename T>\n  struct Probe : Hash {\n   private:\n    template <typename H, typename = decltype(H::Invoke(\n                              std::declval<State>(), std::declval<const T&>()))>\n    static std::true_type Test(int);\n    template <typename U>\n    static std::false_type Test(char);\n\n   public:\n    static constexpr bool value = decltype(Test<Hash>(0))::value;\n  };\n\n public:\n  // Probe each implementation in order.\n  // disjunction provides short circuiting wrt instantiation.\n  template <typename T>\n  using Apply = absl::disjunction<         //\n      Probe<WeaklyMixedIntegerProbe, T>,   //\n      Probe<UniquelyRepresentedProbe, T>,  //\n      Probe<HashValueProbe, T>,            //\n      Probe<LegacyHashProbe, T>,           //\n      Probe<StdHashProbe, T>,              //\n      std::false_type>;\n};\n\ntemplate <typename T>\nstruct is_hashable\n    : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};\n\nclass ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {\n  template <typename T>\n  using IntegralFastPath =\n      conjunction<std::is_integral<T>, is_uniquely_represented<T>,\n                  FitsIn64Bits<T>>;\n\n public:\n  // Move only\n  MixingHashState(MixingHashState&&) = default;\n  MixingHashState& operator=(MixingHashState&&) = default;\n\n  // Fundamental base case for hash recursion: mixes the given range of bytes\n  // into the hash state.\n  static MixingHashState combine_contiguous(MixingHashState hash_state,\n                                            const unsigned char* first,\n                                            size_t size) {\n    return MixingHashState(\n        CombineContiguousImpl(hash_state.state_, first, size,\n                              std::integral_constant<int, sizeof(size_t)>{}));\n  }\n  using MixingHashState::HashStateBase::combine_contiguous;\n\n  template <typename T>\n  static size_t hash(const T& value) {\n    return hash_with_seed(value, Seed());\n  }\n\n  // For performance reasons in non-opt mode, we specialize this for\n  // integral types.\n  // Otherwise we would be instantiating and calling dozens of functions for\n  // something that is just one multiplication and a couple xor's.\n  // The result should be the same as running the whole algorithm, but faster.\n  template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0>\n  static size_t hash_with_seed(T value, size_t seed) {\n    return static_cast<size_t>(\n        CombineRawImpl(seed, static_cast<std::make_unsigned_t<T>>(value)));\n  }\n\n  template <typename T, absl::enable_if_t<!IntegralFastPath<T>::value, int> = 0>\n  static size_t hash_with_seed(const T& value, size_t seed) {\n    return static_cast<size_t>(combine(MixingHashState{seed}, value).state_);\n  }\n\n private:\n  friend class MixingHashState::HashStateBase;\n  template <typename H>\n  friend H absl::hash_internal::hash_weakly_mixed_integer(H,\n                                                          WeaklyMixedInteger);\n  // Allow the HashState type-erasure implementation to invoke\n  // RunCombinedUnordered() directly.\n  friend class absl::HashState;\n  friend struct CombineRaw;\n\n  // For use in Seed().\n  static const void* const kSeed;\n\n  // Invoked only once for a given argument; that plus the fact that this is\n  // move-only ensures that there is only one non-moved-from object.\n  MixingHashState() : state_(Seed()) {}\n\n  // Workaround for MSVC bug.\n  // We make the type copyable to fix the calling convention, even though we\n  // never actually copy it. Keep it private to not affect the public API of the\n  // type.\n  MixingHashState(const MixingHashState&) = default;\n\n  explicit MixingHashState(uint64_t state) : state_(state) {}\n\n  // Combines a raw value from e.g. integrals/floats/pointers/etc. This allows\n  // us to be consistent with IntegralFastPath when combining raw types, but\n  // optimize Read1To3 and Read4To8 differently for the string case.\n  static MixingHashState combine_raw(MixingHashState hash_state,\n                                     uint64_t value) {\n    return MixingHashState(CombineRawImpl(hash_state.state_, value));\n  }\n\n  static MixingHashState combine_weakly_mixed_integer(\n      MixingHashState hash_state, WeaklyMixedInteger value) {\n    // Some transformation for the value is needed to make an empty\n    // string/container change the mixing hash state.\n    // We use constant smaller than 8 bits to make compiler use\n    // `add` with an immediate operand with 1 byte value.\n    return MixingHashState{hash_state.state_ + (0x57 + value.value)};\n  }\n\n  template <typename CombinerT>\n  static MixingHashState RunCombineUnordered(MixingHashState state,\n                                             CombinerT combiner) {\n    uint64_t unordered_state = 0;\n    combiner(MixingHashState{}, [&](MixingHashState& inner_state) {\n      // Add the hash state of the element to the running total, but mix the\n      // carry bit back into the low bit.  This in intended to avoid losing\n      // entropy to overflow, especially when unordered_multisets contain\n      // multiple copies of the same value.\n      auto element_state = inner_state.state_;\n      unordered_state += element_state;\n      if (unordered_state < element_state) {\n        ++unordered_state;\n      }\n      inner_state = MixingHashState{};\n    });\n    return MixingHashState::combine(std::move(state), unordered_state);\n  }\n\n  // A non-deterministic seed.\n  //\n  // The current purpose of this seed is to generate non-deterministic results\n  // and prevent having users depend on the particular hash values.\n  // It is not meant as a security feature right now, but it leaves the door\n  // open to upgrade it to a true per-process random seed. A true random seed\n  // costs more and we don't need to pay for that right now.\n  //\n  // On platforms with ASLR, we take advantage of it to make a per-process\n  // random value.\n  // See https://en.wikipedia.org/wiki/Address_space_layout_randomization\n  //\n  // On other platforms this is still going to be non-deterministic but most\n  // probably per-build and not per-process.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE static size_t Seed() {\n#if (!defined(__clang__) || __clang_major__ > 11) && \\\n    (!defined(__apple_build_version__) ||            \\\n     __apple_build_version__ >= 19558921)  // Xcode 12\n    return static_cast<size_t>(reinterpret_cast<uintptr_t>(&kSeed));\n#else\n    // Workaround the absence of\n    // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021.\n    return static_cast<size_t>(reinterpret_cast<uintptr_t>(kSeed));\n#endif\n  }\n\n  uint64_t state_;\n};\n\nstruct AggregateBarrier {};\n\n// Add a private base class to make sure this type is not an aggregate.\n// Aggregates can be aggregate initialized even if the default constructor is\n// deleted.\nstruct PoisonedHash : private AggregateBarrier {\n  PoisonedHash() = delete;\n  PoisonedHash(const PoisonedHash&) = delete;\n  PoisonedHash& operator=(const PoisonedHash&) = delete;\n};\n\ntemplate <typename T>\nstruct HashImpl {\n  size_t operator()(const T& value) const {\n    return MixingHashState::hash(value);\n  }\n\n private:\n  friend struct HashWithSeed;\n\n  size_t hash_with_seed(const T& value, size_t seed) const {\n    return MixingHashState::hash_with_seed(value, seed);\n  }\n};\n\ntemplate <typename T>\nstruct Hash\n    : absl::conditional_t<is_hashable<T>::value, HashImpl<T>, PoisonedHash> {};\n\ntemplate <typename H>\ntemplate <typename T, typename... Ts>\nH HashStateBase<H>::combine(H state, const T& value, const Ts&... values) {\n  return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke(\n                        std::move(state), value),\n                    values...);\n}\n\ntemplate <typename H>\ntemplate <typename T>\nH HashStateBase<H>::combine_contiguous(H state, const T* data, size_t size) {\n  return hash_internal::hash_range_or_bytes(std::move(state), data, size);\n}\n\ntemplate <typename H>\ntemplate <typename I>\nH HashStateBase<H>::combine_unordered(H state, I begin, I end) {\n  return H::RunCombineUnordered(std::move(state),\n                                CombineUnorderedCallback<I>{begin, end});\n}\n\ntemplate <typename H>\nH PiecewiseCombiner::add_buffer(H state, const unsigned char* data,\n                                size_t size) {\n  if (position_ + size < PiecewiseChunkSize()) {\n    // This partial chunk does not fill our existing buffer\n    memcpy(buf_ + position_, data, size);\n    position_ += size;\n    return state;\n  }\n  added_something_ = true;\n  // If the buffer is partially filled we need to complete the buffer\n  // and hash it.\n  if (position_ != 0) {\n    const size_t bytes_needed = PiecewiseChunkSize() - position_;\n    memcpy(buf_ + position_, data, bytes_needed);\n    state = H::combine_contiguous(std::move(state), buf_, PiecewiseChunkSize());\n    data += bytes_needed;\n    size -= bytes_needed;\n  }\n\n  // Hash whatever chunks we can without copying\n  while (size >= PiecewiseChunkSize()) {\n    state = H::combine_contiguous(std::move(state), data, PiecewiseChunkSize());\n    data += PiecewiseChunkSize();\n    size -= PiecewiseChunkSize();\n  }\n  // Fill the buffer with the remainder\n  memcpy(buf_, data, size);\n  position_ = size;\n  return state;\n}\n\ntemplate <typename H>\nH PiecewiseCombiner::finalize(H state) {\n  // Do not call combine_contiguous with empty remainder since it is modifying\n  // state.\n  if (added_something_ && position_ == 0) {\n    return state;\n  }\n  // We still call combine_contiguous for the entirely empty buffer.\n  return H::combine_contiguous(std::move(state), buf_, position_);\n}\n\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_HASH_INTERNAL_HAS_CRC32\n#undef ABSL_HASH_INTERNAL_CRC32_U64\n#undef ABSL_HASH_INTERNAL_CRC32_U32\n#undef ABSL_HASH_INTERNAL_CRC32_U8\n\n#endif  // ABSL_HASH_INTERNAL_HASH_H_\n"
  },
  {
    "path": "absl/hash/internal/hash_test.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Common code shared between absl/hash/hash_test.cc and\n// absl/hash/hash_instantiated_test.cc.\n\n#ifndef ABSL_HASH_INTERNAL_HASH_TEST_H_\n#define ABSL_HASH_INTERNAL_HASH_TEST_H_\n\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/hash/hash.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_test_internal {\n\n// Utility wrapper of T for the purposes of testing the `AbslHash` type erasure\n// mechanism.  `TypeErasedValue<T>` can be constructed with a `T`, and can\n// be compared and hashed.  However, all hashing goes through the hashing\n// type-erasure framework.\ntemplate <typename T>\nclass TypeErasedValue {\n public:\n  TypeErasedValue() = default;\n  TypeErasedValue(const TypeErasedValue&) = default;\n  TypeErasedValue(TypeErasedValue&&) = default;\n  explicit TypeErasedValue(const T& n) : n_(n) {}\n\n  template <typename H>\n  friend H AbslHashValue(H hash_state, const TypeErasedValue& v) {\n    v.HashValue(absl::HashState::Create(&hash_state));\n    return hash_state;\n  }\n\n  void HashValue(absl::HashState state) const {\n    absl::HashState::combine(std::move(state), n_);\n  }\n\n  bool operator==(const TypeErasedValue& rhs) const { return n_ == rhs.n_; }\n  bool operator!=(const TypeErasedValue& rhs) const { return !(*this == rhs); }\n\n private:\n  T n_;\n};\n\n// A TypeErasedValue refinement, for containers.  It exposes the wrapped\n// `value_type` and is constructible from an initializer list.\ntemplate <typename T>\nclass TypeErasedContainer : public TypeErasedValue<T> {\n public:\n  using value_type = typename T::value_type;\n  TypeErasedContainer() = default;\n  TypeErasedContainer(const TypeErasedContainer&) = default;\n  TypeErasedContainer(TypeErasedContainer&&) = default;\n  explicit TypeErasedContainer(const T& n) : TypeErasedValue<T>(n) {}\n  TypeErasedContainer(std::initializer_list<value_type> init_list)\n      : TypeErasedContainer(T(init_list.begin(), init_list.end())) {}\n  // one-argument constructor of value type T, to appease older toolchains that\n  // get confused by one-element initializer lists in some contexts\n  explicit TypeErasedContainer(const value_type& v)\n      : TypeErasedContainer(T(&v, &v + 1)) {}\n};\n\n// Helper trait to verify if T is hashable. We use absl::Hash's poison status to\n// detect it.\ntemplate <typename T>\nusing is_hashable = std::is_default_constructible<absl::Hash<T>>;\n\n}  // namespace hash_test_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HASH_INTERNAL_HASH_TEST_H_\n"
  },
  {
    "path": "absl/hash/internal/low_level_hash_test.cc",
    "content": "// Copyright 2020 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstdint>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/string_view.h\"\n\n#define UPDATE_GOLDEN 0\n\nnamespace {\n\nTEST(LowLevelHashTest, VerifyGolden) {\n  constexpr size_t kNumGoldenOutputs = 95;\n  static struct {\n    absl::string_view base64_data;\n    uint64_t seed;\n  } cases[kNumGoldenOutputs] = {\n      {\"VprUGNH+5NnNRaORxgH/ySrZFQFDL+4VAodhfBNinmn8cg==\",\n       uint64_t{0x531858a40bfa7ea1}},\n      {\"gc1xZaY+q0nPcUvOOnWnT3bqfmT/geth/f7Dm2e/DemMfk4=\",\n       uint64_t{0x86689478a7a7e8fa}},\n      {\"Mr35fIxqx1ukPAL0su1yFuzzAU3wABCLZ8+ZUFsXn47UmAph\",\n       uint64_t{0x4ec948b8e7f27288}},\n      {\"A9G8pw2+m7+rDtWYAdbl8tb2fT7FFo4hLi2vAsa5Y8mKH3CX3g==\",\n       uint64_t{0xce46c7213c10032}},\n      {\"DFaJGishGwEHDdj9ixbCoaTjz9KS0phLNWHVVdFsM93CvPft3hM=\",\n       uint64_t{0xf63e96ee6f32a8b6}},\n      {\"7+Ugx+Kr3aRNgYgcUxru62YkTDt5Hqis+2po81hGBkcrJg4N0uuy\",\n       uint64_t{0x1cfe85e65fc5225}},\n      {\"H2w6O8BUKqu6Tvj2xxaecxEI2wRgIgqnTTG1WwOgDSINR13Nm4d4Vg==\",\n       uint64_t{0x45c474f1cee1d2e8}},\n      {\"1XBMnIbqD5jy65xTDaf6WtiwtdtQwv1dCVoqpeKj+7cTR1SaMWMyI04=\",\n       uint64_t{0x6e024e14015f329c}},\n      {\"znZbdXG2TSFrKHEuJc83gPncYpzXGbAebUpP0XxzH0rpe8BaMQ17nDbt\",\n       uint64_t{0x760c40502103ae1c}},\n      {\"ylu8Atu13j1StlcC1MRMJJXIl7USgDDS22HgVv0WQ8hx/8pNtaiKB17hCQ==\",\n       uint64_t{0x17fd05c3c560c320}},\n      {\"M6ZVVzsd7vAvbiACSYHioH/440dp4xG2mLlBnxgiqEvI/aIEGpD0Sf4VS0g=\",\n       uint64_t{0x8b34200a6f8e90d9}},\n      {\"li3oFSXLXI+ubUVGJ4blP6mNinGKLHWkvGruun85AhVn6iuMtocbZPVhqxzn\",\n       uint64_t{0x6be89e50818bdf69}},\n      {\"kFuQHuUCqBF3Tc3hO4dgdIp223ShaCoog48d5Do5zMqUXOh5XpGK1t5XtxnfGA==\",\n       uint64_t{0xfb389773315b47d8}},\n      {\"jWmOad0v0QhXVJd1OdGuBZtDYYS8wBVHlvOeTQx9ZZnm8wLEItPMeihj72E0nWY=\",\n       uint64_t{0x4f2512a23f61efee}},\n      {\"z+DHU52HaOQdW4JrZwDQAebEA6rm13Zg/9lPYA3txt3NjTBqFZlOMvTRnVzRbl23\",\n       uint64_t{0x59ccd92fc16c6fda}},\n      {\"MmBiGDfYeTayyJa/tVycg+rN7f9mPDFaDc+23j0TlW9094er0ADigsl4QX7V3gG/qw==\",\n       uint64_t{0x25c5a7f5bd330919}},\n      {\"774RK+9rOL4iFvs1q2qpo/JVc/I39buvNjqEFDtDvyoB0FXxPI2vXqOrk08VPfIHkmU=\",\n       uint64_t{0x51df4174d34c97d7}},\n      {\"+slatXiQ7/2lK0BkVUI1qzNxOOLP3I1iK6OfHaoxgqT63FpzbElwEXSwdsryq3UlHK0I\",\n       uint64_t{0x80ce6d76f89cb57}},\n      {\"64mVTbQ47dHjHlOHGS/hjJwr/\"\n       \"K2frCNpn87exOqMzNUVYiPKmhCbfS7vBUce5tO6Ec9osQ==\",\n       uint64_t{0x20961c911965f684}},\n      {\"fIsaG1r530SFrBqaDj1kqE0AJnvvK8MNEZbII2Yw1OK77v0V59xabIh0B5axaz/\"\n       \"+a2V5WpA=\",\n       uint64_t{0x4e5b926ec83868e7}},\n      {\"PGih0zDEOWCYGxuHGDFu9Ivbff/\"\n       \"iE7BNUq65tycTR2R76TerrXALRosnzaNYO5fjFhTi+CiS\",\n       uint64_t{0x3927b30b922eecef}},\n      {\"RnpA/\"\n       \"zJnEnnLjmICORByRVb9bCOgxF44p3VMiW10G7PvW7IhwsWajlP9kIwNA9FjAD2GoQHk2Q=\"\n       \"=\",\n       uint64_t{0xbd0291284a49b61c}},\n      {\"qFklMceaTHqJpy2qavJE+EVBiNFOi6OxjOA3LeIcBop1K7w8xQi3TrDk+\"\n       \"BrWPRIbfprszSaPfrI=\",\n       uint64_t{0x73a77c575bcc956}},\n      {\"cLbfUtLl3EcQmITWoTskUR8da/VafRDYF/ylPYwk7/\"\n       \"zazk6ssyrzxMN3mmSyvrXR2yDGNZ3WDrTT\",\n       uint64_t{0x766a0e2ade6d09a6}},\n      {\"s/\"\n       \"Jf1+\"\n       \"FbsbCpXWPTUSeWyMH6e4CvTFvPE5Fs6Z8hvFITGyr0dtukHzkI84oviVLxhM1xMxrMAy1db\"\n       \"w==\",\n       uint64_t{0x2599f4f905115869}},\n      {\"FvyQ00+j7nmYZVQ8hI1Edxd0AWplhTfWuFGiu34AK5X8u2hLX1bE97sZM0CmeLe+\"\n       \"7LgoUT1fJ/axybE=\",\n       uint64_t{0xd8256e5444d21e53}},\n      {\"L8ncxMaYLBH3g9buPu8hfpWZNlOF7nvWLNv9IozH07uQsIBWSKxoPy8+\"\n       \"LW4tTuzC6CIWbRGRRD1sQV/4\",\n       uint64_t{0xf664a91333fb8dfd}},\n      {\"CDK0meI07yrgV2kQlZZ+\"\n       \"wuVqhc2NmzqeLH7bmcA6kchsRWFPeVF5Wqjjaj556ABeUoUr3yBmfU3kWOakkg==\",\n       uint64_t{0x9625b859be372cd1}},\n      {\"d23/vc5ONh/\"\n       \"HkMiq+gYk4gaCNYyuFKwUkvn46t+dfVcKfBTYykr4kdvAPNXGYLjM4u1YkAEFpJP+\"\n       \"nX7eOvs=\",\n       uint64_t{0x7b99940782e29898}},\n      {\"NUR3SRxBkxTSbtQORJpu/GdR6b/h6sSGfsMj/KFd99ahbh+9r7LSgSGmkGVB/\"\n       \"mGoT0pnMTQst7Lv2q6QN6Vm\",\n       uint64_t{0x4fe12fa5383b51a8}},\n      {\"2BOFlcI3Z0RYDtS9T9Ie9yJoXlOdigpPeeT+CRujb/\"\n       \"O39Ih5LPC9hP6RQk1kYESGyaLZZi3jtabHs7DiVx/VDg==\",\n       uint64_t{0xe2ccb09ac0f5b4b6}},\n      {\"FF2HQE1FxEvWBpg6Z9zAMH+Zlqx8S1JD/\"\n       \"wIlViL6ZDZY63alMDrxB0GJQahmAtjlm26RGLnjW7jmgQ4Ie3I+014=\",\n       uint64_t{0x7d0a37adbd7b753b}},\n      {\"tHmO7mqVL/PX11nZrz50Hc+M17Poj5lpnqHkEN+4bpMx/\"\n       \"YGbkrGOaYjoQjgmt1X2QyypK7xClFrjeWrCMdlVYtbW\",\n       uint64_t{0xd3ae96ef9f7185f2}},\n      {\"/WiHi9IQcxRImsudkA/KOTqGe8/\"\n       \"gXkhKIHkjddv5S9hi02M049dIK3EUyAEjkjpdGLUs+BN0QzPtZqjIYPOgwsYE9g==\",\n       uint64_t{0x4fb88ea63f79a0d8}},\n      {\"qds+1ExSnU11L4fTSDz/QE90g4Jh6ioqSh3KDOTOAo2pQGL1k/\"\n       \"9CCC7J23YF27dUTzrWsCQA2m4epXoCc3yPHb3xElA=\",\n       uint64_t{0xed564e259bb5ebe9}},\n      {\"8FVYHx40lSQPTHheh08Oq0/\"\n       \"pGm2OlG8BEf8ezvAxHuGGdgCkqpXIueJBF2mQJhTfDy5NncO8ntS7vaKs7sCNdDaNGOEi\",\n       uint64_t{0x3e3256b60c428000}},\n      {\"4ZoEIrJtstiCkeew3oRzmyJHVt/pAs2pj0HgHFrBPztbQ10NsQ/\"\n       \"lM6DM439QVxpznnBSiHMgMQJhER+70l72LqFTO1JiIQ==\",\n       uint64_t{0xfb05bad59ec8705}},\n      {\"hQPtaYI+wJyxXgwD5n8jGIKFKaFA/\"\n       \"P83KqCKZfPthnjwdOFysqEOYwAaZuaaiv4cDyi9TyS8hk5cEbNP/jrI7q6pYGBLbsM=\",\n       uint64_t{0xafdc251dbf97b5f8}},\n      {\"S4gpMSKzMD7CWPsSfLeYyhSpfWOntyuVZdX1xSBjiGvsspwOZcxNKCRIOqAA0moUfOh3I5+\"\n       \"juQV4rsqYElMD/gWfDGpsWZKQ\",\n       uint64_t{0x10ec9c92ddb5dcbc}},\n      {\"oswxop+\"\n       \"bthuDLT4j0PcoSKby4LhF47ZKg8K17xxHf74UsGCzTBbOz0MM8hQEGlyqDT1iUiAYnaPaUp\"\n       \"L2mRK0rcIUYA4qLt5uOw==\",\n       uint64_t{0x9a767d5822c7dac4}},\n      {\"0II/\"\n       \"697p+\"\n       \"BtLSjxj5989OXI004TogEb94VUnDzOVSgMXie72cuYRvTFNIBgtXlKfkiUjeqVpd4a+\"\n       \"n5bxNOD1TGrjQtzKU5r7obo=\",\n       uint64_t{0xee46254080d6e2db}},\n      {\"E84YZW2qipAlMPmctrg7TKlwLZ68l4L+c0xRDUfyyFrA4MAti0q9sHq3TDFviH0Y+\"\n       \"Kq3tEE5srWFA8LM9oomtmvm5PYxoaarWPLc\",\n       uint64_t{0xbbb669588d8bf398}},\n      {\"x3pa4HIElyZG0Nj7Vdy9IdJIR4izLmypXw5PCmZB5y68QQ4uRaVVi3UthsoJROvbjDJkP2D\"\n       \"Q6L/eN8pFeLFzNPKBYzcmuMOb5Ull7w==\",\n       uint64_t{0xdc2afaa529beef44}},\n      {\"jVDKGYIuWOP/\"\n       \"QKLdd2wi8B2VJA8Wh0c8PwrXJVM8FOGM3voPDVPyDJOU6QsBDPseoR8uuKd19OZ/\"\n       \"zAvSCB+zlf6upAsBlheUKgCfKww=\",\n       uint64_t{0xf1f67391d45013a8}},\n      {\"mkquunhmYe1aR2wmUz4vcvLEcKBoe6H+kjUok9VUn2+eTSkWs4oDDtJvNCWtY5efJwg/\"\n       \"j4PgjRYWtqnrCkhaqJaEvkkOwVfgMIwF3e+d\",\n       uint64_t{0x16fce2b8c65a3429}},\n      {\"fRelvKYonTQ+s+rnnvQw+JzGfFoPixtna0vzcSjiDqX5s2Kg2//\"\n       \"UGrK+AVCyMUhO98WoB1DDbrsOYSw2QzrcPe0+3ck9sePvb+Q/IRaHbw==\",\n       uint64_t{0xf4b096699f49fe67}},\n      {\"DUwXFJzagljo44QeJ7/\"\n       \"6ZKw4QXV18lhkYT2jglMr8WB3CHUU4vdsytvw6AKv42ZcG6fRkZkq9fpnmXy6xG0aO3WPT1\"\n       \"eHuyFirAlkW+zKtwg=\",\n       uint64_t{0xca584c4bc8198682}},\n      {\"cYmZCrOOBBongNTr7e4nYn52uQUy2mfe48s50JXx2AZ6cRAt/\"\n       \"xRHJ5QbEoEJOeOHsJyM4nbzwFm++SlT6gFZZHJpkXJ92JkR86uS/eV1hJUR\",\n       uint64_t{0xed269fc3818b6aad}},\n      {\"EXeHBDfhwzAKFhsMcH9+2RHwV+mJaN01+9oacF6vgm8mCXRd6jeN9U2oAb0of5c5cO4i+\"\n       \"Vb/LlHZSMI490SnHU0bejhSCC2gsC5d2K30ER3iNA==\",\n       uint64_t{0x33f253cbb8fe66a8}},\n      {\"FzkzRYoNjkxFhZDso94IHRZaJUP61nFYrh5MwDwv9FNoJ5jyNCY/\"\n       \"eazPZk+tbmzDyJIGw2h3GxaWZ9bSlsol/vK98SbkMKCQ/wbfrXRLcDzdd/8=\",\n       uint64_t{0xd0b76b2c1523d99c}},\n      {\"Re4aXISCMlYY/XsX7zkIFR04ta03u4zkL9dVbLXMa/q6hlY/CImVIIYRN3VKP4pnd0AUr/\"\n       \"ugkyt36JcstAInb4h9rpAGQ7GMVOgBniiMBZ/MGU7H\",\n       uint64_t{0xfd28f0811a2a237f}},\n      {\"ueLyMcqJXX+MhO4UApylCN9WlTQ+\"\n       \"ltJmItgG7vFUtqs2qNwBMjmAvr5u0sAKd8jpzV0dDPTwchbIeAW5zbtkA2NABJV6hFM48ib\"\n       \"4/J3A5mseA3cS8w==\",\n       uint64_t{0x6261fb136482e84}},\n      {\"6Si7Yi11L+jZMkwaN+GUuzXMrlvEqviEkGOilNq0h8TdQyYKuFXzkYc/\"\n       \"q74gP3pVCyiwz9KpVGMM9vfnq36riMHRknkmhQutxLZs5fbmOgEO69HglCU=\",\n       uint64_t{0x458efc750bca7c3a}},\n      {\"Q6AbOofGuTJOegPh9Clm/\"\n       \"9crtUMQqylKrTc1fhfJo1tqvpXxhU4k08kntL1RG7woRnFrVh2UoMrL1kjin+s9CanT+\"\n       \"y4hHwLqRranl9FjvxfVKm3yvg68\",\n       uint64_t{0xa7e69ff84e5e7c27}},\n      {\"ieQEbIPvqY2YfIjHnqfJiO1/MIVRk0RoaG/WWi3kFrfIGiNLCczYoklgaecHMm/\"\n       \"1sZ96AjO+a5stQfZbJQwS7Sc1ODABEdJKcTsxeW2hbh9A6CFzpowP1A==\",\n       uint64_t{0x3c59bfd0c29efe9e}},\n      {\"zQUv8hFB3zh2GGl3KTvCmnfzE+\"\n       \"SUgQPVaSVIELFX5H9cE3FuVFGmymkPQZJLAyzC90Cmi8GqYCvPqTuAAB//\"\n       \"XTJxy4bCcVArgZG9zJXpjowpNBfr3ngWrSE=\",\n       uint64_t{0x10befacc6afd298d}},\n      {\"US4hcC1+op5JKGC7eIs8CUgInjKWKlvKQkapulxW262E/\"\n       \"B2ye79QxOexf188u2mFwwe3WTISJHRZzS61IwljqAWAWoBAqkUnW8SHmIDwHUP31J0p5sGd\"\n       \"P47L\",\n       uint64_t{0x41d5320b0a38efa7}},\n      {\"9bHUWFna2LNaGF6fQLlkx1Hkt24nrkLE2CmFdWgTQV3FFbUe747SSqYw6ebpTa07MWSpWRP\"\n       \"sHesVo2B9tqHbe7eQmqYebPDFnNqrhSdZwFm9arLQVs+7a3Ic6A==\",\n       uint64_t{0x58db1c7450fe17f3}},\n      {\"Kb3DpHRUPhtyqgs3RuXjzA08jGb59hjKTOeFt1qhoINfYyfTt2buKhD6YVffRCPsgK9SeqZ\"\n       \"qRPJSyaqsa0ovyq1WnWW8jI/NhvAkZTVHUrX2pC+cD3OPYT05Dag=\",\n       uint64_t{0x6098c055a335b7a6}},\n      {\"gzxyMJIPlU+bJBwhFUCHSofZ/\"\n       \"319LxqMoqnt3+L6h2U2+ZXJCSsYpE80xmR0Ta77Jq54o92SMH87HV8dGOaCTuAYF+\"\n       \"lDL42SY1P316Cl0sZTS2ow3ZqwGbcPNs/1\",\n       uint64_t{0x1bbacec67845a801}},\n      {\"uR7V0TW+FGVMpsifnaBAQ3IGlr1wx5sKd7TChuqRe6OvUXTlD4hKWy8S+\"\n       \"8yyOw8lQabism19vOQxfmocEOW/\"\n       \"vzY0pEa87qHrAZy4s9fH2Bltu8vaOIe+agYohhYORQ==\",\n       uint64_t{0xc419cfc7442190}},\n      {\"1UR5eoo2aCwhacjZHaCh9bkOsITp6QunUxHQ2SfeHv0imHetzt/\"\n       \"Z70mhyWZBalv6eAx+YfWKCUib2SHDtz/\"\n       \"A2dc3hqUWX5VfAV7FQsghPUAtu6IiRatq4YSLpDvKZBQ=\",\n       uint64_t{0xc95e510d94ba270c}},\n      {\"opubR7H63BH7OtY+Avd7QyQ25UZ8kLBdFDsBTwZlY6gA/\"\n       \"u+x+\"\n       \"czC9AaZMgmQrUy15DH7YMGsvdXnviTtI4eVI4aF1H9Rl3NXMKZgwFOsdTfdcZeeHVRzBBKX\"\n       \"8jUfh1il\",\n       uint64_t{0xff1ae05c98089c3f}},\n      {\"DC0kXcSXtfQ9FbSRwirIn5tgPri0sbzHSa78aDZVDUKCMaBGyFU6BmrulywYX8yzvwprdLs\"\n       \"oOwTWN2wMjHlPDqrvVHNEjnmufRDblW+nSS+xtKNs3N5xsxXdv6JXDrAB/Q==\",\n       uint64_t{0x90c02b8dceced493}},\n      {\"BXRBk+3wEP3Lpm1y75wjoz+PgB0AMzLe8tQ1AYU2/\"\n       \"oqrQB2YMC6W+9QDbcOfkGbeH+b7IBkt/\"\n       \"gwCMw2HaQsRFEsurXtcQ3YwRuPz5XNaw5NAvrNa67Fm7eRzdE1+hWLKtA8=\",\n       uint64_t{0x9f8a76697ab1aa36}},\n      {\"RRBSvEGYnzR9E45Aps/+WSnpCo/X7gJLO4DRnUqFrJCV/kzWlusLE/\"\n       \"6ZU6RoUf2ROwcgEvUiXTGjLs7ts3t9SXnJHxC1KiOzxHdYLMhVvgNd3hVSAXODpKFSkVXND\"\n       \"55G2L1W\",\n       uint64_t{0x6ba1bf3d811a531d}},\n      {\"jeh6Qazxmdi57pa9S3XSnnZFIRrnc6s8QLrah5OX3SB/V2ErSPoEAumavzQPkdKF1/\"\n       \"SfvmdL+qgF1C+Yawy562QaFqwVGq7+tW0yxP8FStb56ZRgNI4IOmI30s1Ei7iops9Uuw==\",\n       uint64_t{0x6a418974109c67b4}},\n      {\"6QO5nnDrY2/\"\n       \"wrUXpltlKy2dSBcmK15fOY092CR7KxAjNfaY+\"\n       \"aAmtWbbzQk3MjBg03x39afSUN1fkrWACdyQKRaGxgwq6MGNxI6W+8DLWJBHzIXrntrE/\"\n       \"ml6fnNXEpxplWJ1vEs4=\",\n       uint64_t{0x8472f1c2b3d230a3}},\n      {\"0oPxeEHhqhcFuwonNfLd5jF3RNATGZS6NPoS0WklnzyokbTqcl4BeBkMn07+fDQv83j/\"\n       \"BpGUwcWO05f3+DYzocfnizpFjLJemFGsls3gxcBYxcbqWYev51tG3lN9EvRE+X9+Pwww\",\n       uint64_t{0x5e06068f884e73a7}},\n      {\"naSBSjtOKgAOg8XVbR5cHAW3Y+QL4Pb/JO9/\"\n       \"oy6L08wvVRZqo0BrssMwhzBP401Um7A4ppAupbQeJFdMrysY34AuSSNvtNUy5VxjNECwiNt\"\n       \"gwYHw7yakDUv8WvonctmnoSPKENegQg==\",\n       uint64_t{0x55290b1a8f170f59}},\n      {\"vPyl8DxVeRe1OpilKb9KNwpGkQRtA94UpAHetNh+\"\n       \"95V7nIW38v7PpzhnTWIml5kw3So1Si0TXtIUPIbsu32BNhoH7QwFvLM+\"\n       \"JACgSpc5e3RjsL6Qwxxi11npwxRmRUqATDeMUfRAjxg=\",\n       uint64_t{0x5501cfd83dfe706a}},\n      {\"QC9i2GjdTMuNC1xQJ74ngKfrlA4w3o58FhvNCltdIpuMhHP1YsDA78scQPLbZ3OCUgeQguY\"\n       \"f/vw6zAaVKSgwtaykqg5ka/4vhz4hYqWU5ficdXqClHl+zkWEY26slCNYOM5nnDlly8Cj\",\n       uint64_t{0xe43ed13d13a66990}},\n      {\"7CNIgQhAHX27nxI0HeB5oUTnTdgKpRDYDKwRcXfSFGP1XeT9nQF6WKCMjL1tBV6x7KuJ91G\"\n       \"Zz11F4c+8s+MfqEAEpd4FHzamrMNjGcjCyrVtU6y+7HscMVzr7Q/\"\n       \"ODLcPEFztFnwjvCjmHw==\",\n       uint64_t{0xdf43bc375cf5283f}},\n      {\"Qa/hC2RPXhANSospe+gUaPfjdK/yhQvfm4cCV6/pdvCYWPv8p1kMtKOX3h5/\"\n       \"8oZ31fsmx4Axphu5qXJokuhZKkBUJueuMpxRyXpwSWz2wELx5glxF7CM0Fn+\"\n       \"OevnkhUn5jsPlG2r5jYlVn8=\",\n       uint64_t{0x8112b806d288d7b5}},\n      {\"kUw/0z4l3a89jTwN5jpG0SHY5km/\"\n       \"IVhTjgM5xCiPRLncg40aqWrJ5vcF891AOq5hEpSq0bUCJUMFXgct7kvnys905HjerV7Vs1G\"\n       \"y84tgVJ70/2+pAZTsB/PzNOE/G6sOj4+GbTzkQu819OLB\",\n       uint64_t{0xd52a18abb001cb46}},\n      {\"VDdfSDbO8Tdj3T5W0XM3EI7iHh5xpIutiM6dvcJ/fhe23V/srFEkDy5iZf/\"\n       \"VnA9kfi2C79ENnFnbOReeuZW1b3MUXB9lgC6U4pOTuC+\"\n       \"jHK3Qnpyiqzj7h3ISJSuo2pob7vY6VHZo6Fn7exEqHg==\",\n       uint64_t{0xe12b76a2433a1236}},\n      {\"Ldfvy3ORdquM/R2fIkhH/ONi69mcP1AEJ6n/\"\n       \"oropwecAsLJzQSgezSY8bEiEs0VnFTBBsW+RtZY6tDj03fnb3amNUOq1b7jbqyQkL9hpl+\"\n       \"2Z2J8IaVSeownWl+bQcsR5/xRktIMckC5AtF4YHfU=\",\n       uint64_t{0x175bf7319cf1fa00}},\n      {\"BrbNpb42+\"\n       \"VzZAjJw6QLirXzhweCVRfwlczzZ0VX2xluskwBqyfnGovz5EuX79JJ31VNXa5hTkAyQat3l\"\n       \"YKRADTdAdwE5PqM1N7YaMqqsqoAAAeuYVXuk5eWCykYmClNdSspegwgCuT+403JigBzi\",\n       uint64_t{0xd63d57b3f67525ae}},\n      {\"gB3NGHJJvVcuPyF0ZSvHwnWSIfmaI7La24VMPQVoIIWF7Z74NltPZZpx2f+cocESM+\"\n       \"ILzQW9p+BC8x5IWz7N4Str2WLGKMdgmaBfNkEhSHQDU0IJEOnpUt0HmjhFaBlx0/\"\n       \"LTmhua+rQ6Wup8ezLwfg==\",\n       uint64_t{0x933faea858832b73}},\n      {\"hTKHlRxx6Pl4gjG+6ksvvj0CWFicUg3WrPdSJypDpq91LUWRni2KF6+\"\n       \"81ZoHBFhEBrCdogKqeK+hy9bLDnx7g6rAFUjtn1+cWzQ2YjiOpz4+\"\n       \"ROBB7lnwjyTGWzJD1rXtlso1g2qVH8XJVigC5M9AIxM=\",\n       uint64_t{0x53d061e5f8e7c04f}},\n      {\"IWQBelSQnhrr0F3BhUpXUIDauhX6f95Qp+A0diFXiUK7irwPG1oqBiqHyK/SH/\"\n       \"9S+\"\n       \"rln9DlFROAmeFdH0OCJi2tFm4afxYzJTFR4HnR4cG4x12JqHaZLQx6iiu6CE3rtWBVz99oA\"\n       \"wCZUOEXIsLU24o2Y\",\n       uint64_t{0xdb4124556dd515e0}},\n      {\"TKo+l+\"\n       \"1dOXdLvIrFqeLaHdm0HZnbcdEgOoLVcGRiCbAMR0j5pIFw8D36tefckAS1RCFOH5IgP8yiF\"\n       \"T0Gd0a2hI3+\"\n       \"fTKA7iK96NekxWeoeqzJyctc6QsoiyBlkZerRxs5RplrxoeNg29kKDTM0K94mnhD9g==\",\n       uint64_t{0x4fb31a0dd681ee71}},\n      {\"YU4e7G6EfQYvxCFoCrrT0EFgVLHFfOWRTJQJ5gxM3G2b+\"\n       \"1kJf9YPrpsxF6Xr6nYtS8reEEbDoZJYqnlk9lXSkVArm88Cqn6d25VCx3+\"\n       \"49MqC0trIlXtb7SXUUhwpJK16T0hJUfPH7s5cMZXc6YmmbFuBNPE=\",\n       uint64_t{0x27cc72eefa138e4c}},\n      {\"/I/\"\n       \"eImMwPo1U6wekNFD1Jxjk9XQVi1D+\"\n       \"FPdqcHifYXQuP5aScNQfxMAmaPR2XhuOQhADV5tTVbBKwCDCX4E3jcDNHzCiPvViZF1W27t\"\n       \"xaf2BbFQdwKrNCmrtzcluBFYu0XZfc7RU1RmxK/RtnF1qHsq/O4pp\",\n       uint64_t{0x44bc2dfba4bd3ced}},\n      {\"CJTT9WGcY2XykTdo8KodRIA29qsqY0iHzWZRjKHb9alwyJ7RZAE3V5Juv4MY3MeYEr1EPCC\"\n       \"MxO7yFXqT8XA8YTjaMp3bafRt17Pw8JC4iKJ1zN+WWKOESrj+\"\n       \"3aluGQqn8z1EzqY4PH7rLG575PYeWsP98BugdA==\",\n       uint64_t{0x242da1e3a439bed8}},\n      {\"ZlhyQwLhXQyIUEnMH/\"\n       \"AEW27vh9xrbNKJxpWGtrEmKhd+nFqAfbeNBQjW0SfG1YI0xQkQMHXjuTt4P/\"\n       \"EpZRtA47ibZDVS8TtaxwyBjuIDwqcN09eCtpC+Ls+\"\n       \"vWDTLmBeDM3u4hmzz4DQAYsLiZYSJcldg9Q3wszw=\",\n       uint64_t{0xdc559c746e35c139}},\n      {\"v2KU8y0sCrBghmnm8lzGJlwo6D6ObccAxCf10heoDtYLosk4ztTpLlpSFEyu23MLA1tJkcg\"\n       \"Rko04h19QMG0mOw/\"\n       \"wc93EXAweriBqXfvdaP85sZABwiKO+6rtS9pacRVpYYhHJeVTQ5NzrvBvi1huxAr+\"\n       \"xswhVMfL\",\n       uint64_t{0xd0b0350275b9989}},\n      {\"QhKlnIS6BuVCTQsnoE67E/\"\n       \"yrgogE8EwO7xLaEGei26m0gEU4OksefJgppDh3X0x0Cs78Dr9IHK5b977CmZlrTRmwhlP8p\"\n       \"M+UzXPNRNIZuN3ntOum/QhUWP8SGpirheXENWsXMQ/\"\n       \"nxtxakyEtrNkKk471Oov9juP8oQ==\",\n       uint64_t{0xb04489e41d17730c}},\n      {\"/ZRMgnoRt+Uo6fUPr9FqQvKX7syhgVqWu+\"\n       \"WUSsiQ68UlN0efSP6Eced5gJZL6tg9gcYJIkhjuQNITU0Q3TjVAnAcobgbJikCn6qZ6pRxK\"\n       \"BY4MTiAlfGD3T7R7hwJwx554MAy++Zb/YUFlnCaCJiwQMnowF7aQzwYFCo=\",\n       uint64_t{0x2217285eb4572156}},\n      {\"NB7tU5fNE8nI+SXGfipc7sRkhnSkUF1krjeo6k+8FITaAtdyz+\"\n       \"o7mONgXmGLulBPH9bEwyYhKNVY0L+njNQrZ9YC2aXsFD3PdZsxAFaBT3VXEzh+\"\n       \"NGBTjDASNL3mXyS8Yv1iThGfHoY7T4aR0NYGJ+k+pR6f+KrPC96M\",\n       uint64_t{0x12c2e8e68aede73b}},\n      {\"8T6wrqCtEO6/rwxF6lvMeyuigVOLwPipX/FULvwyu+1wa5sQGav/\"\n       \"2FsLHUVn6cGSi0LlFwLewGHPFJDLR0u4t7ZUyM//\"\n       \"x6da0sWgOa5hzDqjsVGmjxEHXiaXKW3i4iSZNuxoNbMQkIbVML+\"\n       \"DkYu9ND0O2swg4itGeVSzXA==\",\n       uint64_t{0x4d612125bdc4fd00}},\n      {\"Ntf1bMRdondtMv1CYr3G80iDJ4WSAlKy5H34XdGruQiCrnRGDBa+\"\n       \"eUi7vKp4gp3BBcVGl8eYSasVQQjn7MLvb3BjtXx6c/\"\n       \"bCL7JtpzQKaDnPr9GWRxpBXVxKREgMM7d8lm35EODv0w+\"\n       \"hQLfVSh8OGs7fsBb68nNWPLeeSOo=\",\n       uint64_t{0x81826b553954464e}},\n      {\"VsSAw72Ro6xks02kaiLuiTEIWBC5bgqr4WDnmP8vglXzAhixk7td926rm9jNimL+\"\n       \"kroPSygZ9gl63aF5DCPOACXmsbmhDrAQuUzoh9ZKhWgElLQsrqo1KIjWoZT5b5QfVUXY9lS\"\n       \"IBg3U75SqORoTPq7HalxxoIT5diWOcJQi\",\n       uint64_t{0xc2e5d345dc0ddd2d}},\n      {\"j+loZ+C87+\"\n       \"bJxNVebg94gU0mSLeDulcHs84tQT7BZM2rzDSLiCNxUedHr1ZWJ9ejTiBa0dqy2I2ABc++\"\n       \"xzOLcv+//YfibtjKtYggC6/3rv0XCc7xu6d/\"\n       \"O6xO+XOBhOWAQ+IHJVHf7wZnDxIXB8AUHsnjEISKj7823biqXjyP3g==\",\n       uint64_t{0x3da6830a9e32631e}},\n      {\"f3LlpcPElMkspNtDq5xXyWU62erEaKn7RWKlo540gR6mZsNpK1czV/\"\n       \"sOmqaq8XAQLEn68LKj6/\"\n       \"cFkJukxRzCa4OF1a7cCAXYFp9+wZDu0bw4y63qbpjhdCl8GO6Z2lkcXy7KOzbPE01ukg7+\"\n       \"gN+7uKpoohgAhIwpAKQXmX5xtd0=\",\n       uint64_t{0xc9ae5c8759b4877a}},\n  };\n\n#if defined(ABSL_IS_BIG_ENDIAN) || !defined(ABSL_HAVE_INTRINSIC_INT128) || \\\n    UINTPTR_MAX != UINT64_MAX\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {};\n  // This conditional is to avoid an unreachable code warning.\n  bool skip = true;\n  if (skip) {\n    GTEST_SKIP()\n        << \"We only maintain golden data for little endian 64 bit systems with \"\n           \"128 bit intristics.\";\n  }\n#elif (defined(__SSE4_2__) && defined(__AES__))\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0xd6bdb2c9ba5e55f2, 0xffd3e23d4115a8ae, 0x2c3218ef486127de,\n      0x554fa7f3a262b886, 0x06304cbf82e312d3, 0x490b3fb5af80622c,\n      0x7398a90b8cc59c5d, 0x65fb3168b98030ab, 0xd4564363c53617bb,\n      0x0545c26351925fe7, 0xc30700723b634bf4, 0xfb23a140a76dbe94,\n      0x2fa1467fe218a47c, 0x92e05ec3a7b966eb, 0x6112b56e5624dd50,\n      0x8760801365f9d722, 0x41f7187b61db0e5e, 0x7fe9188a1f5f50ad,\n      0x25800bd4c2002ef1, 0x91fecd33a78ef0aa, 0x93986ad71e983613,\n      0xe4c78173c7ea537b, 0x0bbdc2bcabdb50b1, 0xd9aa134df2d87623,\n      0x6c4907c9477a9409, 0xc3e418a5dbda52e5, 0x4d24f3e9d0dda93a,\n      0xcdb565a363dbe45f, 0xa95f228c8ee57478, 0x6b8f00bab5130227,\n      0x2d05a0f44818b67a, 0xd6bf7d990b5f44cb, 0xa3608bdb4712861a,\n      0xf20c33e5e355330b, 0xbc86e1b13130180d, 0x0848221b397b839a,\n      0x17cc0acf44a7e210, 0xc18c6dc584fe0f62, 0x896c7858a59f991d,\n      0xeab1e6d7d2856ed7, 0x7e4b2d99c23edc51, 0x9aeeeb7fa46e7cf0,\n      0x161b9f2e3611790f, 0x5f82aae18d971b36, 0x8d0dd9965881e162,\n      0x56700ea26285895a, 0xcd919c86c29a053e, 0x3e5d589282d9a722,\n      0x92caee9f48a66604, 0x7e1a2fd9b06f14b0, 0xce1d5293f95b0178,\n      0x8101361290e70a11, 0x570e3e9c9eafc1c6, 0x77b6241926a7a568,\n      0x313e5cb34f346699, 0xab8ebeab0514b82b, 0x6e0a43763a310408,\n      0x761b76ec22b2e440, 0x4238c84a9ec00528, 0xb9ea1f6d4d5552af,\n      0xd21f8f110b9dc060, 0xb3d3842b69ac3689, 0xd0a88aa1dcf59869,\n      0xf3f69f637b123403, 0xf5f34b1068cac7da, 0xe69a08d604774abf,\n      0x57648d3a73332437, 0x9762947f5013d00d, 0x35c5d734a0015922,\n      0xbee2fe5a104ce209, 0xedb060efa6efca34, 0x5ccf0f4786d97bc2,\n      0x1ef8ed72e80d7bef, 0x58522deb49c5e30f, 0xde97cd2a6f8bd13b,\n      0x3fae37c6f9855d09, 0xea99ae786feca261, 0x8c6d1d46670b0943,\n      0x84658b2a232c7bfb, 0x7058b7a7968de394, 0x0d44fba68e25aa8f,\n      0xc7f687020f8eb00b, 0xbf9671e1196153d6, 0x1009be891b7f83e7,\n      0x4f9457fb4aa12865, 0x30a49d9563643b32, 0x0302e2c5b46d5a3a,\n      0x77553f42fb0bfbf7, 0x26b95e89f0077110, 0x76ce68ebe01191ba,\n      0x724110fb509e4376, 0xebe74b016b5cfb88, 0x3b0fe11dcf175fc9,\n      0x20b737b9c0490538, 0x0db21c429b45fd17,\n  };\n#elif (defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(__ARM_FEATURE_CRYPTO))\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0xe3de56d839559570, 0x77afbb8906ccf19a, 0xe66e02ad8e92c12f,\n      0x36cc6f2fe751bc64, 0xf4d28aea3ed69ade, 0xf246fd6a4ca33ab3,\n      0xcae9edaf829a6575, 0x11fa7c88bf4cc73a, 0x98c47bfbae3d8c02,\n      0x27545ea34451a56f, 0x14b4c1a27d26d2b2, 0x7613ca9857e7cbe0,\n      0x02efc8f12e71bb88, 0x9c1a83672eee7d5b, 0x2b89aa9cfde6d9b3,\n      0xabeb2cf68ab463dc, 0xfb3db51d62d71d28, 0x3177cc3e0927e344,\n      0xb5798fc1d348beb6, 0x212c471510859095, 0x191df651c270548d,\n      0x1b15d6b8e8cc3105, 0xdc51a9e369fbab13, 0xb674fd0372fab5aa,\n      0x048aec21666fc8d5, 0x8b15383bc4a7e244, 0xf8945c253a43469f,\n      0x513f31e6bf240064, 0xc37c6225063c266f, 0x2a6747f8952ec44c,\n      0xa7a0f11d3607f268, 0x9b58d5c889166fb3, 0xb75ca76a67212a39,\n      0x9a71a476bf4933f3, 0x3f049a71b475edf7, 0x7a49c8907a278e5e,\n      0xf9a78757d9355ac9, 0xbe1bd9d70ee46398, 0x600e24a76a359a39,\n      0x235905ade793a5f0, 0x940c36e0df8ec13a, 0x9300c551cb93a286,\n      0x5e265b90e4828aba, 0x42dee1626c647735, 0x8cd32910c1f17a8c,\n      0x642f44f3f8290fb0, 0xb73ee167c5f8655e, 0x9d05deadb2a47fe4,\n      0x03b359dff5351708, 0x19a6427c0ee9c907, 0x0692dc026847e0d9,\n      0xe4023ba608b25f1e, 0xf438ad7eea71dfc1, 0x205120c9355d4ac8,\n      0xd4cf2cb1f412c846, 0x82d7d98b87ecf53a, 0x2cc779469cc3d690,\n      0xf93545883141ce8e, 0x0f794c869b82a28a, 0x014e9fccfe7f7d9e,\n      0xb6953652e49e4e0a, 0x68035eabb056e9b6, 0xf1b3a6847e610274,\n      0x59dc584137c0cb55, 0xafb36238ad797ec6, 0xb9f331777a030104,\n      0x2899a97f98140d3b, 0x0ae342d8d4f80ad0, 0xcfb25544c873fbd1,\n      0xcb2498ca84b01a4c, 0x1a50e4a0d8db8406, 0x0afbf05b7c8c146e,\n      0x1b45ee2ee670d71b, 0xef9204d9fcc31075, 0x2a5750d2ef558495,\n      0x8e151888d0ce024e, 0x26882404dd58bcc9, 0x6c830f947bf2195f,\n      0x2ff0c1fa64bf8cfb, 0x8f108f869e11d224, 0x7ce757787a04fd76,\n      0xee55da944ebbbd85, 0x43563645bb00dcd0, 0x643848bf73336681,\n      0x050f54d0478ffd52, 0xc5c1bff1bc3c008c, 0x48fd0f2729c9402d,\n      0x7685b990e3e264af, 0x940dccac3264ed16, 0x688f94ee88c9ba90,\n      0xca112c7825f3944b, 0x584cb5ddba130be2, 0xb7ced01f7140dff6,\n      0xc10dcbb4e77168e6, 0xb5ea4360351ebaef,\n  };\n#else\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0x669da02f8d009e0f, 0xceb19bf2255445cd, 0x0e746992d6d43a7c,\n      0x41ed623b9dcc5fde, 0x187a5a30d7c72edc, 0x949ae2a9c1eb925a,\n      0x7e9c76a7b7c35e68, 0x4f96bf15b8309ff6, 0x26c0c1fde233732e,\n      0xb0453f72aa151615, 0xf24b621a9ce9fece, 0x99ed798408687b5f,\n      0x3b13ec1221423b66, 0xc67cf148a28afe59, 0x22f7e0173f92e3fa,\n      0x14186c5fda6683a0, 0x97d608caa2603b2c, 0xfde3b0bbba24ffa9,\n      0xb7068eb48c472c77, 0x9e34d72866b9fda0, 0xbbb99c884cdef88e,\n      0x81d3e01f472a8a1a, 0xf84f506b3b60366d, 0xfe3f42f01300db37,\n      0xe385712a51c1f836, 0x41dfd5e394245c79, 0x60855dbedadb900a,\n      0xbdb4c0aa38567476, 0x9748802e8eec02cc, 0x5ced256d257f88de,\n      0x55acccdf9a80f155, 0xa64b55b071afbbea, 0xa205bfe6c724ce4d,\n      0x69dd26ca8ac21744, 0xef80e2ff2f6a9bc0, 0xde266c0baa202c20,\n      0xfa3463080ac74c50, 0x379d968a40125c2b, 0x4cbbd0a7b3c7d648,\n      0xc92afd93f4c665d2, 0x6e28f5adb7ae38dc, 0x7c689c9c237be35e,\n      0xaea41b29bd9d0f73, 0x832cef631d77e59f, 0x70cac8e87bc37dd3,\n      0x8e8c98bbde68e764, 0xd6117aeb3ddedded, 0xd796ab808e766240,\n      0x8953d0ea1a7d9814, 0xa212eba4281b391c, 0x21a555a8939ce597,\n      0x809d31660f6d81a8, 0x2356524b20ab400f, 0x5bc611e1e49d0478,\n      0xba9c065e2f385ce2, 0xb0a0fd12f4e83899, 0x14d076a35b1ff2ca,\n      0x8acd0bb8cf9a93c0, 0xe62e8ec094039ee4, 0x38a536a7072bdc61,\n      0xca256297602524f8, 0xfc62ebfb3530caeb, 0x8d8b0c05520569f6,\n      0xbbaca65cf154c59d, 0x3739b5ada7e338d3, 0xdb9ea31f47365340,\n      0x410b5c9c1da56755, 0x7e0abc03dbd10283, 0x136f87be70ed442e,\n      0x6b727d4feddbe1e9, 0x074ebb21183b01df, 0x3fe92185b1985484,\n      0xc5d8efd3c68305ca, 0xd9bada21b17e272e, 0x64d73133e1360f83,\n      0xeb8563aa993e21f9, 0xe5e8da50cceab28f, 0x7a6f92eb3223d2f3,\n      0xbdaf98370ea9b31b, 0x1682a84457f077bc, 0x4abd2d33b6e3be37,\n      0xb35bc81a7c9d4c04, 0x3e5bde3fb7cfe63d, 0xff3abe6e2ffec974,\n      0xb8116dd26cf6feec, 0x7a77a6e4ed0cf081, 0xb71eec2d5a184316,\n      0x6fa932f77b4da817, 0x795f79b33909b2c4, 0x1b8755ef6b5eb34e,\n      0x2255b72d7d6b2d79, 0xf2bdafafa90bd50a, 0x442a578f02cb1fc8,\n      0xc25aefe55ecf83db, 0x3114c056f9c5a676,\n  };\n#endif\n\n  auto hash_fn = [](absl::string_view s, uint64_t state) {\n    return absl::hash_internal::CombineLargeContiguousImplOn64BitLengthGt32(\n        state, reinterpret_cast<const unsigned char*>(s.data()), s.size());\n  };\n\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    std::string str;\n    ASSERT_TRUE(absl::Base64Unescape(cases[i].base64_data, &str));\n    ASSERT_GT(str.size(), 32);\n    uint64_t h = hash_fn(str, cases[i].seed);\n    printf(\"0x%016\" PRIx64 \", \", h);\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n  EXPECT_FALSE(true);\n#else\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    SCOPED_TRACE(::testing::Message()\n                 << \"i = \" << i << \"; input = \" << cases[i].base64_data);\n    std::string str;\n    ASSERT_TRUE(absl::Base64Unescape(cases[i].base64_data, &str));\n    ASSERT_GT(str.size(), 32);\n    EXPECT_EQ(hash_fn(str, cases[i].seed), kGolden[i]);\n  }\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/hash/internal/print_hash_of.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdlib>\n\n#include \"absl/hash/hash.h\"\n\n// Prints the hash of argv[1].\nint main(int argc, char** argv) {\n  if (argc < 2) return 1;\n  printf(\"%zu\\n\", absl::Hash<int>{}(std::atoi(argv[1])));  // NOLINT\n}\n"
  },
  {
    "path": "absl/hash/internal/spy_hash_state.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_\n#define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <optional>\n#include <ostream>\n#include <string>\n#include <vector>\n\n#include \"absl/hash/hash.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_join.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\n\n// SpyHashState is an implementation of the HashState API that simply\n// accumulates all input bytes in an internal buffer. This makes it useful\n// for testing AbslHashValue overloads (so long as they are templated on the\n// HashState parameter), since it can report the exact hash representation\n// that the AbslHashValue overload produces.\n//\n// Sample usage:\n// EXPECT_EQ(SpyHashState::combine(SpyHashState(), foo),\n//           SpyHashState::combine(SpyHashState(), bar));\ntemplate <typename T>\nclass SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {\n public:\n  SpyHashStateImpl() : error_(std::make_shared<std::optional<std::string>>()) {\n    static_assert(std::is_void<T>::value, \"\");\n  }\n\n  // Move-only\n  SpyHashStateImpl(const SpyHashStateImpl&) = delete;\n  SpyHashStateImpl& operator=(const SpyHashStateImpl&) = delete;\n\n  SpyHashStateImpl(SpyHashStateImpl&& other) noexcept {\n    *this = std::move(other);\n  }\n\n  SpyHashStateImpl& operator=(SpyHashStateImpl&& other) noexcept {\n    hash_representation_ = std::move(other.hash_representation_);\n    error_ = other.error_;\n    moved_from_ = other.moved_from_;\n    other.moved_from_ = true;\n    return *this;\n  }\n\n  template <typename U>\n  SpyHashStateImpl(SpyHashStateImpl<U>&& other) {  // NOLINT\n    hash_representation_ = std::move(other.hash_representation_);\n    error_ = other.error_;\n    moved_from_ = other.moved_from_;\n    other.moved_from_ = true;\n  }\n\n  template <typename A, typename... Args>\n  static SpyHashStateImpl combine(SpyHashStateImpl s, const A& a,\n                                  const Args&... args) {\n    // Pass an instance of SpyHashStateImpl<A> when trying to combine `A`. This\n    // allows us to test that the user only uses this instance for combine calls\n    // and does not call AbslHashValue directly.\n    // See AbslHashValue implementation at the bottom.\n    s = SpyHashStateImpl<A>::HashStateBase::combine(std::move(s), a);\n    return SpyHashStateImpl::combine(std::move(s), args...);\n  }\n  static SpyHashStateImpl combine(SpyHashStateImpl s) {\n    if (direct_absl_hash_value_error_) {\n      *s.error_ = \"AbslHashValue should not be invoked directly.\";\n    } else if (s.moved_from_) {\n      *s.error_ = \"Used moved-from instance of the hash state object.\";\n    }\n    return s;\n  }\n\n  static void SetDirectAbslHashValueError() {\n    direct_absl_hash_value_error_ = true;\n  }\n\n  // Two SpyHashStateImpl objects are equal if they hold equal hash\n  // representations.\n  friend bool operator==(const SpyHashStateImpl& lhs,\n                         const SpyHashStateImpl& rhs) {\n    return lhs.hash_representation_ == rhs.hash_representation_;\n  }\n\n  friend bool operator!=(const SpyHashStateImpl& lhs,\n                         const SpyHashStateImpl& rhs) {\n    return !(lhs == rhs);\n  }\n\n  enum class CompareResult {\n    kEqual,\n    kASuffixB,\n    kBSuffixA,\n    kUnequal,\n  };\n\n  static CompareResult Compare(const SpyHashStateImpl& a,\n                               const SpyHashStateImpl& b) {\n    const std::string a_flat = absl::StrJoin(a.hash_representation_, \"\");\n    const std::string b_flat = absl::StrJoin(b.hash_representation_, \"\");\n    if (a_flat == b_flat) return CompareResult::kEqual;\n    if (absl::EndsWith(a_flat, b_flat)) return CompareResult::kBSuffixA;\n    if (absl::EndsWith(b_flat, a_flat)) return CompareResult::kASuffixB;\n    return CompareResult::kUnequal;\n  }\n\n  // operator<< prints the hash representation as a hex and ASCII dump, to\n  // facilitate debugging.\n  friend std::ostream& operator<<(std::ostream& out,\n                                  const SpyHashStateImpl& hash_state) {\n    out << \"[\\n\";\n    for (auto& s : hash_state.hash_representation_) {\n      size_t offset = 0;\n      for (char c : s) {\n        if (offset % 16 == 0) {\n          out << absl::StreamFormat(\"\\n0x%04x: \", offset);\n        }\n        if (offset % 2 == 0) {\n          out << \" \";\n        }\n        out << absl::StreamFormat(\"%02x\", c);\n        ++offset;\n      }\n      out << \"\\n\";\n    }\n    return out << \"]\";\n  }\n\n  // The base case of the combine recursion, which writes raw bytes into the\n  // internal buffer.\n  static SpyHashStateImpl combine_contiguous(SpyHashStateImpl hash_state,\n                                             const unsigned char* begin,\n                                             size_t size) {\n    if (size == 0) {\n      return SpyHashStateImpl::combine_raw(std::move(hash_state), 0);\n    }\n    const size_t large_chunk_stride = PiecewiseChunkSize();\n    // Combining a large contiguous buffer must have the same effect as\n    // doing it piecewise by the stride length, followed by the (possibly\n    // empty) remainder.\n    while (size > large_chunk_stride) {\n      hash_state = SpyHashStateImpl::combine_contiguous(\n          std::move(hash_state), begin, large_chunk_stride);\n      begin += large_chunk_stride;\n      size -= large_chunk_stride;\n    }\n\n    if (size > 0) {\n      hash_state.hash_representation_.emplace_back(\n          reinterpret_cast<const char*>(begin), size);\n      hash_state = SpyHashStateImpl::combine_raw(std::move(hash_state), size);\n    }\n    return hash_state;\n  }\n\n  static SpyHashStateImpl combine_weakly_mixed_integer(\n      SpyHashStateImpl hash_state, WeaklyMixedInteger value) {\n    return combine(std::move(hash_state), value.value);\n  }\n\n  using SpyHashStateImpl::HashStateBase::combine_contiguous;\n\n  template <typename CombinerT>\n  static SpyHashStateImpl RunCombineUnordered(SpyHashStateImpl state,\n                                              CombinerT combiner) {\n    UnorderedCombinerCallback cb;\n\n    combiner(SpyHashStateImpl<void>{}, std::ref(cb));\n\n    std::sort(cb.element_hash_representations.begin(),\n              cb.element_hash_representations.end());\n    state.hash_representation_.insert(state.hash_representation_.end(),\n                                      cb.element_hash_representations.begin(),\n                                      cb.element_hash_representations.end());\n    if (cb.error && cb.error->has_value()) {\n      state.error_ = std::move(cb.error);\n    }\n    return state;\n  }\n\n  std::optional<std::string> error() const {\n    if (moved_from_) {\n      return \"Returned a moved-from instance of the hash state object.\";\n    }\n    return *error_;\n  }\n\n private:\n  template <typename U>\n  friend class SpyHashStateImpl;\n  friend struct CombineRaw;\n\n  struct UnorderedCombinerCallback {\n    std::vector<std::string> element_hash_representations;\n    std::shared_ptr<std::optional<std::string>> error;\n\n    // The inner spy can have a different type.\n    template <typename U>\n    void operator()(SpyHashStateImpl<U>& inner) {\n      element_hash_representations.push_back(\n          absl::StrJoin(inner.hash_representation_, \"\"));\n      if (inner.error_->has_value()) {\n        error = std::move(inner.error_);\n      }\n      inner = SpyHashStateImpl<void>{};\n    }\n  };\n\n  // Combines raw data from e.g. integrals/floats/pointers/etc.\n  static SpyHashStateImpl combine_raw(SpyHashStateImpl state, uint64_t value) {\n    state.hash_representation_.emplace_back(\n        reinterpret_cast<const char*>(&value), 8);\n    return state;\n  }\n\n  // This is true if SpyHashStateImpl<T> has been passed to a call of\n  // AbslHashValue with the wrong type. This detects that the user called\n  // AbslHashValue directly (because the hash state type does not match).\n  static bool direct_absl_hash_value_error_;\n\n  std::vector<std::string> hash_representation_;\n  // This is a shared_ptr because we want all instances of the particular\n  // SpyHashState run to share the field. This way we can set the error for\n  // use-after-move and all the copies will see it.\n  std::shared_ptr<std::optional<std::string>> error_;\n  bool moved_from_ = false;\n};\n\ntemplate <typename T>\nbool SpyHashStateImpl<T>::direct_absl_hash_value_error_;\n\ntemplate <bool& B>\nstruct OdrUse {\n  constexpr OdrUse() {}\n  bool& b = B;\n};\n\ntemplate <void (*)()>\nstruct RunOnStartup {\n  static bool run;\n  static constexpr OdrUse<run> kOdrUse{};\n};\n\ntemplate <void (*f)()>\nbool RunOnStartup<f>::run = (f(), true);\n\ntemplate <\n    typename T, typename U,\n    // Only trigger for when (T != U),\n    typename = absl::enable_if_t<!std::is_same<T, U>::value>,\n    // This statement works in two ways:\n    //  - First, it instantiates RunOnStartup and forces the initialization of\n    //    `run`, which set the global variable.\n    //  - Second, it triggers a SFINAE error disabling the overload to prevent\n    //    compile time errors. If we didn't disable the overload we would get\n    //    ambiguous overload errors, which we don't want.\n    int = RunOnStartup<SpyHashStateImpl<T>::SetDirectAbslHashValueError>::run>\nvoid AbslHashValue(SpyHashStateImpl<T>, const U&);\n\nusing SpyHashState = SpyHashStateImpl<void>;\n\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_\n"
  },
  {
    "path": "absl/hash/internal/weakly_mixed_integer.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_\n#define ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace hash_internal {\n\n// Contains an integer that will be mixed into a hash state more weakly than\n// regular integers. It is useful for cases in which an integer is a part of a\n// larger object and needs to be mixed as a supplement. E.g., absl::string_view\n// and absl::Span are mixing their size wrapped with WeaklyMixedInteger.\nstruct WeaklyMixedInteger {\n  size_t value;\n};\n\n}  // namespace hash_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_\n"
  },
  {
    "path": "absl/log/BUILD.bazel",
    "content": "#\n# Copyright 2022 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\n# Public targets\n\ncc_library(\n    name = \"absl_check\",\n    hdrs = [\"absl_check.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/log/internal:check_impl\",\n    ],\n)\n\ncc_library(\n    name = \"absl_log\",\n    hdrs = [\"absl_log.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/log/internal:log_impl\",\n    ],\n)\n\ncc_library(\n    name = \"check\",\n    hdrs = [\"check.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/log/internal:check_impl\",\n        \"//absl/log/internal:check_op\",\n        \"//absl/log/internal:conditions\",\n        \"//absl/log/internal:log_message\",\n        \"//absl/log/internal:strip\",\n    ],\n)\n\ncc_library(\n    name = \"die_if_null\",\n    srcs = [\"die_if_null.cc\"],\n    hdrs = [\"die_if_null.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/base:nullability_traits_internal\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"flags\",\n    srcs = [\"flags.cc\"],\n    hdrs = [\"flags.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":globals\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/flags:flag\",\n        \"//absl/flags:marshalling\",\n        \"//absl/log/internal:config\",\n        \"//absl/log/internal:flags\",\n        \"//absl/log/internal:vlog_config\",\n        \"//absl/strings\",\n    ],\n    # Binaries which do not access these flags from C++ still want this library linked in.\n    alwayslink = True,\n)\n\ncc_library(\n    name = \"globals\",\n    srcs = [\"globals.cc\"],\n    hdrs = [\"globals.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \"//absl/base:atomic_hook\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/hash\",\n        \"//absl/log/internal:vlog_config\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"initialize\",\n    srcs = [\"initialize.cc\"],\n    hdrs = [\"initialize.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":globals\",\n        \"//absl/base:config\",\n        \"//absl/log/internal:globals\",\n        \"//absl/time\",\n    ],\n)\n\ncc_library(\n    name = \"log\",\n    hdrs = [\"log.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":vlog_is_on\",\n        \"//absl/log/internal:log_impl\",\n    ],\n)\n\ncc_library(\n    name = \"log_entry\",\n    srcs = [\"log_entry.cc\"],\n    hdrs = [\"log_entry.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log/internal:config\",\n        \"//absl/log/internal:proto\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"log_sink\",\n    srcs = [\"log_sink.cc\"],\n    hdrs = [\"log_sink.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log_entry\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"log_sink_registry\",\n    hdrs = [\"log_sink_registry.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log_sink\",\n        \"//absl/base:config\",\n        \"//absl/base:nullability\",\n        \"//absl/log/internal:log_sink_set\",\n    ],\n)\n\ncc_library(\n    name = \"log_streamer\",\n    hdrs = [\"log_streamer.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":absl_log\",\n        \"//absl/base:config\",\n        \"//absl/base:log_severity\",\n        \"//absl/strings\",\n        \"//absl/strings:internal\",\n        \"//absl/types:optional\",\n        \"//absl/types:source_location\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"scoped_mock_log\",\n    testonly = True,\n    srcs = [\"scoped_mock_log.cc\"],\n    hdrs = [\"scoped_mock_log.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log_entry\",\n        \":log_sink\",\n        \":log_sink_registry\",\n        \"//absl/base:config\",\n        \"//absl/base:log_severity\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"structured\",\n    hdrs = [\"structured.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/log/internal:structured\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"absl_vlog_is_on\",\n    hdrs = [\"absl_vlog_is_on.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/log/internal:vlog_config\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"vlog_is_on\",\n    hdrs = [\"vlog_is_on.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":absl_vlog_is_on\",\n    ],\n)\n\n# TODO(b/200695798): run this in TAP projects with -DABSL_MAX_VLOG_VERBOSITY={-100,100}\ncc_test(\n    name = \"vlog_is_on_test\",\n    size = \"small\",\n    srcs = [\n        \"vlog_is_on_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":flags\",\n        \":globals\",\n        \":log\",\n        \":scoped_mock_log\",\n        \":vlog_is_on\",\n        \"//absl/base:log_severity\",\n        \"//absl/flags:flag\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\n# Test targets\n\ncc_test(\n    name = \"absl_check_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"absl_check_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:ios\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":absl_check\",\n        \":check_test_impl\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"absl_log_basic_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"absl_log_basic_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":absl_log\",\n        \":log_basic_test_impl\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"check_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"check_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:ios\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":check\",\n        \":check_test_impl\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"check_test_impl\",\n    testonly = True,\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:ios\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    textual_hdrs = [\"check_test_impl.inc\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/status\",\n        \"//absl/strings\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"die_if_null_test\",\n    size = \"small\",\n    srcs = [\"die_if_null_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":die_if_null\",\n        \"//absl/base:core_headers\",\n        \"//absl/log/internal:test_helpers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"flags_test\",\n    size = \"small\",\n    srcs = [\"flags_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":flags\",\n        \":globals\",\n        \":log\",\n        \":scoped_mock_log\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/flags:flag\",\n        \"//absl/flags:reflection\",\n        \"//absl/log/internal:flags\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"//absl/strings\",\n        \"//absl/types:source_location\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"globals_test\",\n    size = \"small\",\n    srcs = [\"globals_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":globals\",\n        \":log\",\n        \":scoped_mock_log\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log/internal:globals\",\n        \"//absl/log/internal:test_helpers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_basic_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"log_basic_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log\",\n        \":log_basic_test_impl\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"log_basic_test_impl\",\n    testonly = True,\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    textual_hdrs = [\"log_basic_test_impl.inc\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:log_severity\",\n        \"//absl/log:globals\",\n        \"//absl/log:log_entry\",\n        \"//absl/log:scoped_mock_log\",\n        \"//absl/log/internal:globals\",\n        \"//absl/log/internal:test_actions\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"log_entry_test\",\n    size = \"small\",\n    srcs = [\"log_entry_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log_entry\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log/internal:append_truncated\",\n        \"//absl/log/internal:format\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_format_test\",\n    size = \"small\",\n    srcs = [\"log_format_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":check\",\n        \":log\",\n        \":scoped_mock_log\",\n        \"//absl/base:config\",\n        \"//absl/log/internal:test_matchers\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_macro_hygiene_test\",\n    size = \"small\",\n    srcs = [\"log_macro_hygiene_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log\",\n        \":scoped_mock_log\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_sink_test\",\n    size = \"medium\",\n    srcs = [\"log_sink_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:ios\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":log\",\n        \":log_sink\",\n        \":log_sink_registry\",\n        \":scoped_mock_log\",\n        \"//absl/base:core_headers\",\n        \"//absl/log/internal:test_actions\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_streamer_test\",\n    size = \"medium\",\n    srcs = [\"log_streamer_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log\",\n        \":log_streamer\",\n        \":scoped_mock_log\",\n        \"//absl/base\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log/internal:test_actions\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"//absl/strings\",\n        \"//absl/types:source_location\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_modifier_methods_test\",\n    size = \"small\",\n    srcs = [\"log_modifier_methods_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log\",\n        \":log_sink\",\n        \":scoped_mock_log\",\n        \"//absl/log/internal:test_actions\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"//absl/types:source_location\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"scoped_mock_log_test\",\n    size = \"small\",\n    srcs = [\"scoped_mock_log_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    linkstatic = 1,\n    tags = [\n        \"no_test:os:ios\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":globals\",\n        \":log\",\n        \":scoped_mock_log\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"stripping_test\",\n    size = \"small\",\n    srcs = [\"stripping_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    # This test requires all code live in the binary (instead of shared libraries)\n    # because we test for the existence of specific literals in the binary.\n    linkstatic = 1,\n    deps = [\n        \":check\",\n        \":log\",\n        \"//absl/base:log_severity\",\n        \"//absl/base:strerror\",\n        \"//absl/flags:program_name\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/status\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"structured_test\",\n    size = \"small\",\n    srcs = [\"structured_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log\",\n        \":scoped_mock_log\",\n        \":structured\",\n        \"//absl/base:core_headers\",\n        \"//absl/log/internal:test_helpers\",\n        \"//absl/log/internal:test_matchers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_benchmark\",\n    size = \"small\",\n    srcs = [\"log_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":check\",\n        \":flags\",\n        \":globals\",\n        \":log\",\n        \":log_entry\",\n        \":log_sink\",\n        \":log_sink_registry\",\n        \":vlog_is_on\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/flags:flag\",\n        \"//absl/log/internal:flags\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/log/CMakeLists.txt",
    "content": "# Copyright 2022 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Internal targets\nabsl_cc_library(\n  NAME\n    log_internal_check_impl\n  SRCS\n  HDRS\n    \"internal/check_impl.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log_internal_check_op\n    absl::log_internal_conditions\n    absl::log_internal_strip\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_check_op\n  SRCS\n    \"internal/check_op.cc\"\n  HDRS\n    \"internal/check_op.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::has_ostream_operator\n    absl::leak_check\n    absl::log_internal_nullguard\n    absl::log_internal_nullstream\n    absl::log_internal_strip\n    absl::nullability\n    absl::strings\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_conditions\n  SRCS\n    \"internal/conditions.cc\"\n  HDRS\n    \"internal/conditions.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::log_internal_voidify\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_config\n  SRCS\n  HDRS\n    \"internal/config.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_flags\n  SRCS\n  HDRS\n    \"internal/flags.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::flags\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_format\n  SRCS\n    \"internal/log_format.cc\"\n  HDRS\n    \"internal/log_format.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_internal_append_truncated\n    absl::log_internal_config\n    absl::log_internal_globals\n    absl::log_severity\n    absl::strings\n    absl::str_format\n    absl::time\n    absl::span\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_globals\n  SRCS\n    \"internal/globals.cc\"\n  HDRS\n    \"internal/globals.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_severity\n    absl::raw_logging_internal\n    absl::strings\n    absl::time\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_log_impl\n  SRCS\n  HDRS\n    \"internal/log_impl.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_conditions\n    absl::log_internal_message\n    absl::log_internal_strip\n    absl::absl_vlog_is_on\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_proto\n  SRCS\n    \"internal/proto.cc\"\n  HDRS\n    \"internal/proto.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::strings\n    absl::span\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_message\n  SRCS\n    \"internal/log_message.cc\"\n  HDRS\n    \"internal/log_message.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::errno_saver\n    absl::examine_stack\n    absl::inlined_vector\n    absl::log_internal_append_truncated\n    absl::log_internal_format\n    absl::log_internal_globals\n    absl::log_internal_proto\n    absl::log_internal_log_sink_set\n    absl::log_internal_nullguard\n    absl::log_internal_structured_proto\n    absl::log_globals\n    absl::log_entry\n    absl::log_severity\n    absl::log_sink\n    absl::log_sink_registry\n    absl::memory\n    absl::nullability\n    absl::raw_logging_internal\n    absl::source_location\n    absl::span\n    absl::strerror\n    absl::strings\n    absl::strings_internal\n    absl::time\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_log_sink_set\n  SRCS\n    \"internal/log_sink_set.cc\"\n  HDRS\n    \"internal/log_sink_set.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n    $<$<BOOL:${ANDROID}>:-llog>\n  DEPS\n    absl::base\n    absl::cleanup\n    absl::config\n    absl::core_headers\n    absl::log_internal_config\n    absl::log_internal_globals\n    absl::log_globals\n    absl::log_entry\n    absl::log_severity\n    absl::log_sink\n    absl::no_destructor\n    absl::raw_logging_internal\n    absl::synchronization\n    absl::span\n    absl::strings\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_nullguard\n  SRCS\n    \"internal/nullguard.cc\"\n  HDRS\n    \"internal/nullguard.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_nullstream\n  SRCS\n  HDRS\n    \"internal/nullstream.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_severity\n    absl::strings\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_strip\n  SRCS\n  HDRS\n    \"internal/strip.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log_internal_message\n    absl::log_internal_nullstream\n    absl::log_severity\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_test_actions\n  SRCS\n    \"internal/test_actions.cc\"\n  HDRS\n    \"internal/test_actions.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_entry\n    absl::log_severity\n    absl::strings\n    absl::time\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_test_helpers\n  SRCS\n    \"internal/test_helpers.cc\"\n  HDRS\n    \"internal/test_helpers.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_globals\n    absl::log_initialize\n    absl::log_internal_globals\n    absl::log_severity\n    GTest::gtest\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_test_matchers\n  SRCS\n    \"internal/test_matchers.cc\"\n  HDRS\n    \"internal/test_matchers.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_entry\n    absl::log_internal_test_helpers\n    absl::log_severity\n    absl::strings\n    absl::time\n    GTest::gtest\n    GTest::gmock\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_voidify\n  SRCS\n  HDRS\n    \"internal/voidify.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_append_truncated\n  SRCS\n  HDRS\n    \"internal/append_truncated.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::strings\n    absl::strings_internal\n    absl::span\n)\n\n# Public targets\nabsl_cc_library(\n  NAME\n    absl_check\n  SRCS\n  HDRS\n    \"absl_check.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_check_impl\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    absl_log\n  SRCS\n  HDRS\n    \"absl_log.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_log_impl\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    check\n  SRCS\n  HDRS\n    \"check.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_check_impl\n    absl::core_headers\n    absl::log_internal_check_op\n    absl::log_internal_conditions\n    absl::log_internal_message\n    absl::log_internal_strip\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    die_if_null\n  SRCS\n    \"die_if_null.cc\"\n  HDRS\n    \"die_if_null.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log\n    absl::nullability\n    absl::nullability_traits_internal\n    absl::strings\n  PUBLIC\n)\n\n# Warning: Many linkers will strip the contents of this library because its\n# symbols are only used in a global constructor. A workaround is for clients\n# to link this using $<LINK_LIBRARY:WHOLE_ARCHIVE,absl::log_flags> instead of\n# the plain absl::log_flags.\n# TODO(b/320467376): Implement the equivalent of Bazel's alwayslink=True.\nabsl_cc_library(\n  NAME\n    log_flags\n  SRCS\n    \"flags.cc\"\n  HDRS\n    \"flags.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_globals\n    absl::log_severity\n    absl::log_internal_config\n    absl::log_internal_flags\n    absl::flags\n    absl::flags_marshalling\n    absl::strings\n    absl::vlog_config_internal\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    log_globals\n  SRCS\n    \"globals.cc\"\n  HDRS\n    \"globals.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::atomic_hook\n    absl::config\n    absl::core_headers\n    absl::hash\n    absl::log_severity\n    absl::raw_logging_internal\n    absl::strings\n    absl::vlog_config_internal\n)\n\nabsl_cc_library(\n  NAME\n    log_initialize\n  SRCS\n    \"initialize.cc\"\n  HDRS\n    \"initialize.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_globals\n    absl::log_internal_globals\n    absl::time\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    log\n  SRCS\n  HDRS\n    \"log.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_log_impl\n    absl::vlog_is_on\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    log_entry\n  SRCS\n    \"log_entry.cc\"\n  HDRS\n    \"log_entry.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_internal_config\n    absl::log_internal_proto\n    absl::log_severity\n    absl::span\n    absl::strings\n    absl::time\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    log_sink\n  SRCS\n    \"log_sink.cc\"\n  HDRS\n    \"log_sink.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_entry\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    log_sink_registry\n  SRCS\n  HDRS\n    \"log_sink_registry.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_sink\n    absl::log_internal_log_sink_set\n    absl::nullability\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    log_streamer\n  SRCS\n  HDRS\n    \"log_streamer.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::absl_log\n    absl::log_severity\n    absl::optional\n    absl::source_location\n    absl::strings\n    absl::strings_internal\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    scoped_mock_log\n  SRCS\n    \"scoped_mock_log.cc\"\n  HDRS\n    \"scoped_mock_log.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_entry\n    absl::log_severity\n    absl::log_sink\n    absl::log_sink_registry\n    absl::raw_logging_internal\n    absl::strings\n    GTest::gmock\n    GTest::gtest\n  PUBLIC\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_structured\n  HDRS\n    \"internal/structured.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::any_invocable\n    absl::config\n    absl::core_headers\n    absl::log_internal_message\n    absl::log_internal_structured_proto\n    absl::strings\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_structured_proto\n  SRCS\n    \"internal/structured_proto.cc\"\n  HDRS\n    \"internal/structured_proto.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_proto\n    absl::config\n    absl::span\n    absl::strings\n    absl::variant\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    log_internal_structured_proto_test\n  SRCS\n    \"internal/structured_proto_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_internal_structured_proto\n    absl::span\n    absl::string_view\n    absl::utility\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    log_structured\n  HDRS\n    \"structured.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_internal_structured\n    absl::strings\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    vlog_config_internal\n  SRCS\n    \"internal/vlog_config.cc\"\n  HDRS\n    \"internal/vlog_config.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::log_internal_fnmatch\n    absl::memory\n    absl::no_destructor\n    absl::nullability\n    absl::strings\n    absl::synchronization\n)\n\nabsl_cc_library(\n  NAME\n    absl_vlog_is_on\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  HDRS\n    \"absl_vlog_is_on.h\"\n  DEPS\n    absl::vlog_config_internal\n    absl::config\n    absl::core_headers\n    absl::strings\n)\n\nabsl_cc_library(\n  NAME\n    vlog_is_on\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  HDRS\n    \"vlog_is_on.h\"\n  DEPS\n    absl::absl_vlog_is_on\n)\n\nabsl_cc_test(\n  NAME\n    vlog_is_on_test\n  SRCS\n    \"vlog_is_on_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::log_flags\n    absl::log_globals\n    absl::scoped_mock_log\n    absl::vlog_is_on\n    absl::log_severity\n    absl::flags\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_fnmatch\n  SRCS\n    \"internal/fnmatch.cc\"\n  HDRS\n    \"internal/fnmatch.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::strings\n)\n\n# Test targets\n\nabsl_cc_test(\n  NAME\n    absl_check_test\n  SRCS\n    \"absl_check_test.cc\"\n    \"check_test_impl.inc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::absl_check\n    absl::config\n    absl::core_headers\n    absl::log_internal_test_helpers\n    absl::status\n    absl::strings\n    absl::string_view\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    absl_log_basic_test\n  SRCS\n    \"log_basic_test.cc\"\n    \"log_basic_test_impl.inc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::absl_log\n    absl::log_entry\n    absl::log_globals\n    absl::log_severity\n    absl::log_internal_globals\n    absl::log_internal_test_actions\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::scoped_mock_log\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    check_test\n  SRCS\n    \"check_test.cc\"\n    \"check_test_impl.inc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::check\n    absl::config\n    absl::core_headers\n    absl::log_internal_test_helpers\n    absl::status\n    absl::strings\n    absl::string_view\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    die_if_null_test\n  SRCS\n    \"die_if_null_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::die_if_null\n    absl::log_internal_test_helpers\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    log_basic_test\n  SRCS\n    \"log_basic_test.cc\"\n    \"log_basic_test_impl.inc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::log\n    absl::log_entry\n    absl::log_globals\n    absl::log_severity\n    absl::log_internal_test_actions\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::scoped_mock_log\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_entry_test\n  SRCS\n    \"log_entry_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::log_entry\n    absl::log_internal_append_truncated\n    absl::log_internal_format\n    absl::log_internal_globals\n    absl::log_internal_test_helpers\n    absl::log_severity\n    absl::span\n    absl::strings\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_flags_test\n  SRCS\n    \"flags_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_flags\n    absl::log_globals\n    absl::log_internal_flags\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::log_severity\n    absl::flags\n    absl::flags_reflection\n    absl::scoped_mock_log\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_globals_test\n  SRCS\n    \"globals_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_globals\n    absl::log_internal_globals\n    absl::log_internal_test_helpers\n    absl::log_severity\n    absl::scoped_mock_log\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_format_test\n  SRCS\n    \"log_format_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::check\n    absl::config\n    absl::log\n    absl::log_internal_test_matchers\n    absl::scoped_mock_log\n    absl::str_format\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_macro_hygiene_test\n  SRCS\n    \"log_macro_hygiene_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_severity\n    absl::scoped_mock_log\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_sink_test\n  SRCS\n    \"log_sink_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_internal_test_actions\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::log_sink\n    absl::log_sink_registry\n    absl::log_severity\n    absl::scoped_mock_log\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_streamer_test\n  SRCS\n    \"log_streamer_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::core_headers\n    absl::log\n    absl::log_internal_test_actions\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::log_streamer\n    absl::log_severity\n    absl::scoped_mock_log\n    absl::source_location\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_modifier_methods_test\n  SRCS\n    \"log_modifier_methods_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::log_internal_test_actions\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::log_sink\n    absl::scoped_mock_log\n    absl::source_location\n    absl::strings\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    scoped_mock_log_test\n  SRCS\n    \"scoped_mock_log_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_globals\n    absl::log_internal_globals\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::log_severity\n    absl::memory\n    absl::scoped_mock_log\n    absl::strings\n    absl::synchronization\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    log_internal_stderr_log_sink_test\n  SRCS\n    \"internal/stderr_log_sink_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_globals\n    absl::log_internal_test_helpers\n    absl::log_severity\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_stripping_test\n  SRCS\n    \"stripping_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::check\n    absl::flags_program_name\n    absl::log\n    absl::log_internal_test_helpers\n    absl::log_severity\n    absl::status\n    absl::strerror\n    absl::strings\n    absl::str_format\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    log_structured_test\n  SRCS\n    \"structured_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::log_internal_test_helpers\n    absl::log_internal_test_matchers\n    absl::log_structured\n    absl::scoped_mock_log\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    internal_fnmatch_test\n  SRCS\n    \"internal/fnmatch_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log_internal_fnmatch\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    log_internal_container\n  HDRS\n    \"internal/container.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::requires_internal\n    absl::strings\n)\n\nabsl_cc_test(\n  NAME\n    internal_container_test\n  SRCS\n    \"internal/container_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::log_internal_container\n    absl::span\n    absl::strings\n    absl::str_format\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/log/absl_check.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/absl_check.h\n// -----------------------------------------------------------------------------\n//\n// This header declares a family of `ABSL_CHECK` macros as alternative spellings\n// for `CHECK` macros in `check.h`.\n//\n// Except for those whose names begin with `ABSL_DCHECK`, these macros are not\n// controlled by `NDEBUG` (cf. `assert`), so the check will be executed\n// regardless of compilation mode. `ABSL_CHECK` and friends are thus useful for\n// confirming invariants in situations where continuing to run would be worse\n// than terminating, e.g., due to risk of data corruption or security\n// compromise.  It is also more robust and portable to deliberately terminate\n// at a particular place with a useful message and backtrace than to assume some\n// ultimately unspecified and unreliable crashing behavior (such as a\n// \"segmentation fault\").\n//\n// For full documentation of each macro, see comments in `check.h`, which has an\n// identical set of macros without the ABSL_* prefix.\n\n#ifndef ABSL_LOG_ABSL_CHECK_H_\n#define ABSL_LOG_ABSL_CHECK_H_\n\n#include \"absl/log/internal/check_impl.h\"\n\n#define ABSL_CHECK(condition) \\\n  ABSL_LOG_INTERNAL_CHECK_IMPL((condition), #condition)\n#define ABSL_QCHECK(condition) \\\n  ABSL_LOG_INTERNAL_QCHECK_IMPL((condition), #condition)\n#define ABSL_PCHECK(condition) \\\n  ABSL_LOG_INTERNAL_PCHECK_IMPL((condition), #condition)\n#define ABSL_DCHECK(condition) \\\n  ABSL_LOG_INTERNAL_DCHECK_IMPL((condition), #condition)\n\n#define ABSL_CHECK_EQ(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_EQ_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_CHECK_NE(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_NE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_CHECK_LE(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_LE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_CHECK_LT(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_LT_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_CHECK_GE(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_GE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_CHECK_GT(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_GT_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_QCHECK_EQ(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_QCHECK_NE(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_NE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_QCHECK_LE(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_LE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_QCHECK_LT(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_LT_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_QCHECK_GE(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_GE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_QCHECK_GT(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_GT_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_DCHECK_EQ(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_DCHECK_NE(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_NE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_DCHECK_LE(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_LE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_DCHECK_LT(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_LT_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_DCHECK_GE(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_GE_IMPL((val1), #val1, (val2), #val2)\n#define ABSL_DCHECK_GT(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_GT_IMPL((val1), #val1, (val2), #val2)\n\n#define ABSL_CHECK_OK(status) ABSL_LOG_INTERNAL_CHECK_OK_IMPL((status), #status)\n#define ABSL_QCHECK_OK(status) \\\n  ABSL_LOG_INTERNAL_QCHECK_OK_IMPL((status), #status)\n#define ABSL_DCHECK_OK(status) \\\n  ABSL_LOG_INTERNAL_DCHECK_OK_IMPL((status), #status)\n\n#define ABSL_CHECK_STREQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_CHECK_STRNE(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_CHECK_STRCASEEQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_CHECK_STRCASENE(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_QCHECK_STREQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_QCHECK_STRNE(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_QCHECK_STRCASEEQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_QCHECK_STRCASENE(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_DCHECK_STREQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_DCHECK_STRNE(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_DCHECK_STRCASEEQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)\n#define ABSL_DCHECK_STRCASENE(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)\n\n#endif  // ABSL_LOG_ABSL_CHECK_H_\n"
  },
  {
    "path": "absl/log/absl_check_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/absl_check.h\"\n\n#define ABSL_TEST_CHECK ABSL_CHECK\n#define ABSL_TEST_CHECK_OK ABSL_CHECK_OK\n#define ABSL_TEST_CHECK_EQ ABSL_CHECK_EQ\n#define ABSL_TEST_CHECK_NE ABSL_CHECK_NE\n#define ABSL_TEST_CHECK_GE ABSL_CHECK_GE\n#define ABSL_TEST_CHECK_LE ABSL_CHECK_LE\n#define ABSL_TEST_CHECK_GT ABSL_CHECK_GT\n#define ABSL_TEST_CHECK_LT ABSL_CHECK_LT\n#define ABSL_TEST_CHECK_STREQ ABSL_CHECK_STREQ\n#define ABSL_TEST_CHECK_STRNE ABSL_CHECK_STRNE\n#define ABSL_TEST_CHECK_STRCASEEQ ABSL_CHECK_STRCASEEQ\n#define ABSL_TEST_CHECK_STRCASENE ABSL_CHECK_STRCASENE\n\n#define ABSL_TEST_DCHECK ABSL_DCHECK\n#define ABSL_TEST_DCHECK_OK ABSL_DCHECK_OK\n#define ABSL_TEST_DCHECK_EQ ABSL_DCHECK_EQ\n#define ABSL_TEST_DCHECK_NE ABSL_DCHECK_NE\n#define ABSL_TEST_DCHECK_GE ABSL_DCHECK_GE\n#define ABSL_TEST_DCHECK_LE ABSL_DCHECK_LE\n#define ABSL_TEST_DCHECK_GT ABSL_DCHECK_GT\n#define ABSL_TEST_DCHECK_LT ABSL_DCHECK_LT\n#define ABSL_TEST_DCHECK_STREQ ABSL_DCHECK_STREQ\n#define ABSL_TEST_DCHECK_STRNE ABSL_DCHECK_STRNE\n#define ABSL_TEST_DCHECK_STRCASEEQ ABSL_DCHECK_STRCASEEQ\n#define ABSL_TEST_DCHECK_STRCASENE ABSL_DCHECK_STRCASENE\n\n#define ABSL_TEST_QCHECK ABSL_QCHECK\n#define ABSL_TEST_QCHECK_OK ABSL_QCHECK_OK\n#define ABSL_TEST_QCHECK_EQ ABSL_QCHECK_EQ\n#define ABSL_TEST_QCHECK_NE ABSL_QCHECK_NE\n#define ABSL_TEST_QCHECK_GE ABSL_QCHECK_GE\n#define ABSL_TEST_QCHECK_LE ABSL_QCHECK_LE\n#define ABSL_TEST_QCHECK_GT ABSL_QCHECK_GT\n#define ABSL_TEST_QCHECK_LT ABSL_QCHECK_LT\n#define ABSL_TEST_QCHECK_STREQ ABSL_QCHECK_STREQ\n#define ABSL_TEST_QCHECK_STRNE ABSL_QCHECK_STRNE\n#define ABSL_TEST_QCHECK_STRCASEEQ ABSL_QCHECK_STRCASEEQ\n#define ABSL_TEST_QCHECK_STRCASENE ABSL_QCHECK_STRCASENE\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/check_test_impl.inc\"\n"
  },
  {
    "path": "absl/log/absl_log.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/absl_log.h\n// -----------------------------------------------------------------------------\n//\n// This header declares a family of `ABSL_LOG` macros as alternative spellings\n// for macros in `log.h`.\n//\n// Basic invocation looks like this:\n//\n//   ABSL_LOG(INFO) << \"Found \" << num_cookies << \" cookies\";\n//\n// Most `ABSL_LOG` macros take a severity level argument. The severity levels\n// are `INFO`, `WARNING`, `ERROR`, and `FATAL`.\n//\n// For full documentation, see comments in `log.h`, which includes full\n// reference documentation on use of the equivalent `LOG` macro and has an\n// identical set of macros without the ABSL_* prefix.\n\n#ifndef ABSL_LOG_ABSL_LOG_H_\n#define ABSL_LOG_ABSL_LOG_H_\n\n#include \"absl/log/internal/log_impl.h\"\n\n#define ABSL_LOG(severity) ABSL_LOG_INTERNAL_LOG_IMPL(_##severity)\n#define ABSL_PLOG(severity) ABSL_LOG_INTERNAL_PLOG_IMPL(_##severity)\n#define ABSL_DLOG(severity) ABSL_LOG_INTERNAL_DLOG_IMPL(_##severity)\n\n#define ABSL_VLOG(verbose_level) ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level)\n#define ABSL_DVLOG(verbose_level) ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level)\n\n#define ABSL_LOG_IF(severity, condition) \\\n  ABSL_LOG_INTERNAL_LOG_IF_IMPL(_##severity, condition)\n#define ABSL_PLOG_IF(severity, condition) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_IMPL(_##severity, condition)\n#define ABSL_DLOG_IF(severity, condition) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_IMPL(_##severity, condition)\n\n#define ABSL_LOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(_##severity, n)\n#define ABSL_LOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(_##severity, n)\n#define ABSL_LOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(_##severity)\n#define ABSL_LOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)\n\n#define ABSL_PLOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(_##severity, n)\n#define ABSL_PLOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(_##severity, n)\n#define ABSL_PLOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(_##severity)\n#define ABSL_PLOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)\n\n#define ABSL_DLOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(_##severity, n)\n#define ABSL_DLOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(_##severity, n)\n#define ABSL_DLOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(_##severity)\n#define ABSL_DLOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)\n\n#define ABSL_VLOG_EVERY_N(verbose_level, n) \\\n  ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n)\n#define ABSL_VLOG_FIRST_N(verbose_level, n) \\\n  ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n)\n#define ABSL_VLOG_EVERY_POW_2(verbose_level, n) \\\n  ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level, n)\n#define ABSL_VLOG_EVERY_N_SEC(verbose_level, n) \\\n  ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n)\n\n#define ABSL_LOG_IF_EVERY_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(_##severity, condition, n)\n#define ABSL_LOG_IF_FIRST_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(_##severity, condition, n)\n#define ABSL_LOG_IF_EVERY_POW_2(severity, condition) \\\n  ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(_##severity, condition)\n#define ABSL_LOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \\\n  ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)\n\n#define ABSL_PLOG_IF_EVERY_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(_##severity, condition, n)\n#define ABSL_PLOG_IF_FIRST_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(_##severity, condition, n)\n#define ABSL_PLOG_IF_EVERY_POW_2(severity, condition) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)\n#define ABSL_PLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)\n\n#define ABSL_DLOG_IF_EVERY_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(_##severity, condition, n)\n#define ABSL_DLOG_IF_FIRST_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(_##severity, condition, n)\n#define ABSL_DLOG_IF_EVERY_POW_2(severity, condition) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)\n#define ABSL_DLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)\n\n#endif  // ABSL_LOG_ABSL_LOG_H_\n"
  },
  {
    "path": "absl/log/absl_log_basic_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/absl_log.h\"\n\n#define ABSL_TEST_LOG ABSL_LOG\n#define ABSL_TEST_DLOG ABSL_DLOG\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/log_basic_test_impl.inc\"\n"
  },
  {
    "path": "absl/log/absl_vlog_is_on.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/absl_vlog_is_on.h\n// -----------------------------------------------------------------------------\n//\n// This header defines the `ABSL_VLOG_IS_ON()` macro that controls the\n// variable-verbosity conditional logging.\n//\n// It's used by `VLOG` in log.h, or it can also be used directly like this:\n//\n//   if (ABSL_VLOG_IS_ON(2)) {\n//     foo_server.RecomputeStatisticsExpensive();\n//     LOG(INFO) << foo_server.LastStatisticsAsString();\n//   }\n//\n// Each source file has an effective verbosity level that's a non-negative\n// integer computed from the `--vmodule` and `--v` flags.\n// `ABSL_VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity\n// level is greater than or equal to `n`.\n//\n// `--vmodule` takes a comma-delimited list of key=value pairs.  Each key is a\n// pattern matched against filenames, and the values give the effective severity\n// level applied to matching files.  '?' and '*' characters in patterns are\n// interpreted as single-character and zero-or-more-character wildcards.\n// Patterns including a slash character are matched against full pathnames,\n// while those without are matched against basenames only.  One suffix (i.e. the\n// last . and everything after it) is stripped from each filename prior to\n// matching, as is the special suffix \"-inl\".\n//\n// Example: --vmodule=module_a=1,module_b=2\n//\n// Files are matched against globs in `--vmodule` in order, and the first match\n// determines the verbosity level.\n//\n// Files which do not match any pattern in `--vmodule` use the value of `--v` as\n// their effective verbosity level.  The default is 0.\n//\n// SetVLogLevel helper function is provided to do limited dynamic control over\n// V-logging by appending to `--vmodule`. Because these go at the beginning of\n// the list, they take priority over any globs previously added.\n//\n// Resetting --vmodule will override all previous modifications to `--vmodule`,\n// including via SetVLogLevel.\n\n#ifndef ABSL_LOG_ABSL_VLOG_IS_ON_H_\n#define ABSL_LOG_ABSL_VLOG_IS_ON_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/vlog_config.h\"  // IWYU pragma: export\n#include \"absl/strings/string_view.h\"\n\n// IWYU pragma: private, include \"absl/log/log.h\"\n\n// This is expanded at the callsite to allow the compiler to optimize\n// always-false cases out of the build.\n// An ABSL_MAX_VLOG_VERBOSITY of 2 means that VLOG(3) and above should never\n// log.\n#ifdef ABSL_MAX_VLOG_VERBOSITY\n#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x) \\\n  ((x) <= ABSL_MAX_VLOG_VERBOSITY)&&\n#else\n#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x)\n#endif\n\n// Each ABSL_VLOG_IS_ON call site gets its own VLogSite that registers with the\n// global linked list of sites to asynchronously update its verbosity level on\n// changes to --v or --vmodule. The verbosity can also be set by manually\n// calling SetVLogLevel.\n//\n// ABSL_VLOG_IS_ON is not async signal safe, but it is guaranteed not to\n// allocate new memory.\n#define ABSL_VLOG_IS_ON(verbose_level)                                     \\\n  (ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(verbose_level)[]()            \\\n       ->::absl::log_internal::VLogSite *                                  \\\n   {                                                                       \\\n     ABSL_CONST_INIT static ::absl::log_internal::VLogSite site(__FILE__); \\\n     return &site;                                                         \\\n   }()                                                                     \\\n       ->IsEnabled(verbose_level))\n\n#endif  // ABSL_LOG_ABSL_VLOG_IS_ON_H_\n"
  },
  {
    "path": "absl/log/check.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/check.h\n// -----------------------------------------------------------------------------\n//\n// This header declares a family of `CHECK` macros.\n//\n// `CHECK` macros terminate the program with a fatal error if the specified\n// condition is not true.\n//\n// Except for those whose names begin with `DCHECK`, these macros are not\n// controlled by `NDEBUG` (cf. `assert`), so the check will be executed\n// regardless of compilation mode. `CHECK` and friends are thus useful for\n// confirming invariants in situations where continuing to run would be worse\n// than terminating, e.g., due to risk of data corruption or security\n// compromise.  It is also more robust and portable to deliberately terminate\n// at a particular place with a useful message and backtrace than to assume some\n// ultimately unspecified and unreliable crashing behavior (such as a\n// \"segmentation fault\").\n\n#ifndef ABSL_LOG_CHECK_H_\n#define ABSL_LOG_CHECK_H_\n\n#include \"absl/log/internal/check_impl.h\"\n#include \"absl/log/internal/check_op.h\"     // IWYU pragma: export\n#include \"absl/log/internal/conditions.h\"   // IWYU pragma: export\n#include \"absl/log/internal/log_message.h\"  // IWYU pragma: export\n#include \"absl/log/internal/strip.h\"        // IWYU pragma: export\n\n// CHECK()\n//\n// `CHECK` enforces that the `condition` is true. If the condition is false,\n// the program is terminated with a fatal error.\n//\n// The message may include additional information such as stack traces, when\n// available.\n//\n// Example:\n//\n//   CHECK(!cheese.empty()) << \"Out of Cheese\";\n//\n// Might produce a message like:\n//\n//   Check failed: !cheese.empty() Out of Cheese\n#define CHECK(condition) ABSL_LOG_INTERNAL_CHECK_IMPL((condition), #condition)\n\n// QCHECK()\n//\n// `QCHECK` behaves like `CHECK` but does not print a full stack trace and does\n// not run registered error handlers (as `QFATAL`).  It is useful when the\n// problem is definitely unrelated to program flow, e.g. when validating user\n// input.\n#define QCHECK(condition) ABSL_LOG_INTERNAL_QCHECK_IMPL((condition), #condition)\n\n// PCHECK()\n//\n// `PCHECK` behaves like `CHECK` but appends a description of the current state\n// of `errno` to the failure message.\n//\n// Example:\n//\n//   int fd = open(\"/var/empty/missing\", O_RDONLY);\n//   PCHECK(fd != -1) << \"posix is difficult\";\n//\n// Might produce a message like:\n//\n//   Check failed: fd != -1 posix is difficult: No such file or directory [2]\n#define PCHECK(condition) ABSL_LOG_INTERNAL_PCHECK_IMPL((condition), #condition)\n\n// DCHECK()\n//\n// `DCHECK` behaves like `CHECK` in debug mode and does nothing otherwise (as\n// `DLOG`).  Unlike with `CHECK` (but as with `assert`), it is not safe to rely\n// on evaluation of `condition`: when `NDEBUG` is enabled, DCHECK does not\n// evaluate the condition.\n#define DCHECK(condition) ABSL_LOG_INTERNAL_DCHECK_IMPL((condition), #condition)\n\n// `CHECK_EQ` and friends are syntactic sugar for `CHECK(x == y)` that\n// automatically output the expression being tested and the evaluated values on\n// either side.\n//\n// Example:\n//\n//   int x = 3, y = 5;\n//   CHECK_EQ(2 * x, y) << \"oops!\";\n//\n// Might produce a message like:\n//\n//   Check failed: 2 * x == y (6 vs. 5) oops!\n//\n// The values must implement the appropriate comparison operator as well as\n// `operator<<(std::ostream&, ...)`.  Care is taken to ensure that each\n// argument is evaluated exactly once, and that anything which is legal to pass\n// as a function argument is legal here.  In particular, the arguments may be\n// temporary expressions which will end up being destroyed at the end of the\n// statement,\n//\n// Example:\n//\n//   CHECK_EQ(std::string(\"abc\")[1], 'b');\n//\n// WARNING: Passing `NULL` as an argument to `CHECK_EQ` and similar macros does\n// not compile.  Use `nullptr` instead.\n#define CHECK_EQ(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_EQ_IMPL((val1), #val1, (val2), #val2)\n#define CHECK_NE(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_NE_IMPL((val1), #val1, (val2), #val2)\n#define CHECK_LE(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_LE_IMPL((val1), #val1, (val2), #val2)\n#define CHECK_LT(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_LT_IMPL((val1), #val1, (val2), #val2)\n#define CHECK_GE(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_GE_IMPL((val1), #val1, (val2), #val2)\n#define CHECK_GT(val1, val2) \\\n  ABSL_LOG_INTERNAL_CHECK_GT_IMPL((val1), #val1, (val2), #val2)\n#define QCHECK_EQ(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL((val1), #val1, (val2), #val2)\n#define QCHECK_NE(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_NE_IMPL((val1), #val1, (val2), #val2)\n#define QCHECK_LE(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_LE_IMPL((val1), #val1, (val2), #val2)\n#define QCHECK_LT(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_LT_IMPL((val1), #val1, (val2), #val2)\n#define QCHECK_GE(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_GE_IMPL((val1), #val1, (val2), #val2)\n#define QCHECK_GT(val1, val2) \\\n  ABSL_LOG_INTERNAL_QCHECK_GT_IMPL((val1), #val1, (val2), #val2)\n#define DCHECK_EQ(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL((val1), #val1, (val2), #val2)\n#define DCHECK_NE(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_NE_IMPL((val1), #val1, (val2), #val2)\n#define DCHECK_LE(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_LE_IMPL((val1), #val1, (val2), #val2)\n#define DCHECK_LT(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_LT_IMPL((val1), #val1, (val2), #val2)\n#define DCHECK_GE(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_GE_IMPL((val1), #val1, (val2), #val2)\n#define DCHECK_GT(val1, val2) \\\n  ABSL_LOG_INTERNAL_DCHECK_GT_IMPL((val1), #val1, (val2), #val2)\n\n// `CHECK_OK` and friends validate that the provided `absl::Status` or\n// `absl::StatusOr<T>` is OK.  If it isn't, they print a failure message that\n// includes the actual status and terminate the program.\n//\n// As with all `DCHECK` variants, `DCHECK_OK` has no effect (not even\n// evaluating its argument) if `NDEBUG` is enabled.\n//\n// Example:\n//\n//   CHECK_OK(FunctionReturnsStatus(x, y, z)) << \"oops!\";\n//\n// Might produce a message like:\n//\n//   Check failed: FunctionReturnsStatus(x, y, z) is OK (ABORTED: timeout) oops!\n#define CHECK_OK(status) ABSL_LOG_INTERNAL_CHECK_OK_IMPL((status), #status)\n#define QCHECK_OK(status) ABSL_LOG_INTERNAL_QCHECK_OK_IMPL((status), #status)\n#define DCHECK_OK(status) ABSL_LOG_INTERNAL_DCHECK_OK_IMPL((status), #status)\n\n// `CHECK_STREQ` and friends provide `CHECK_EQ` functionality for C strings,\n// i.e., null-terminated char arrays.  The `CASE` versions are case-insensitive.\n//\n// Example:\n//\n//   CHECK_STREQ(argv[0], \"./skynet\");\n//\n// Note that both arguments may be temporary strings which are destroyed by the\n// compiler at the end of the current full expression.\n//\n// Example:\n//\n//   CHECK_STREQ(Foo().c_str(), Bar().c_str());\n#define CHECK_STREQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL((s1), #s1, (s2), #s2)\n#define CHECK_STRNE(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL((s1), #s1, (s2), #s2)\n#define CHECK_STRCASEEQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)\n#define CHECK_STRCASENE(s1, s2) \\\n  ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)\n#define QCHECK_STREQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)\n#define QCHECK_STRNE(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)\n#define QCHECK_STRCASEEQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)\n#define QCHECK_STRCASENE(s1, s2) \\\n  ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)\n#define DCHECK_STREQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)\n#define DCHECK_STRNE(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)\n#define DCHECK_STRCASEEQ(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)\n#define DCHECK_STRCASENE(s1, s2) \\\n  ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)\n\n#endif  // ABSL_LOG_CHECK_H_\n"
  },
  {
    "path": "absl/log/check_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/check.h\"\n\n#define ABSL_TEST_CHECK CHECK\n#define ABSL_TEST_CHECK_OK CHECK_OK\n#define ABSL_TEST_CHECK_EQ CHECK_EQ\n#define ABSL_TEST_CHECK_NE CHECK_NE\n#define ABSL_TEST_CHECK_GE CHECK_GE\n#define ABSL_TEST_CHECK_LE CHECK_LE\n#define ABSL_TEST_CHECK_GT CHECK_GT\n#define ABSL_TEST_CHECK_LT CHECK_LT\n#define ABSL_TEST_CHECK_STREQ CHECK_STREQ\n#define ABSL_TEST_CHECK_STRNE CHECK_STRNE\n#define ABSL_TEST_CHECK_STRCASEEQ CHECK_STRCASEEQ\n#define ABSL_TEST_CHECK_STRCASENE CHECK_STRCASENE\n\n#define ABSL_TEST_DCHECK DCHECK\n#define ABSL_TEST_DCHECK_OK DCHECK_OK\n#define ABSL_TEST_DCHECK_EQ DCHECK_EQ\n#define ABSL_TEST_DCHECK_NE DCHECK_NE\n#define ABSL_TEST_DCHECK_GE DCHECK_GE\n#define ABSL_TEST_DCHECK_LE DCHECK_LE\n#define ABSL_TEST_DCHECK_GT DCHECK_GT\n#define ABSL_TEST_DCHECK_LT DCHECK_LT\n#define ABSL_TEST_DCHECK_STREQ DCHECK_STREQ\n#define ABSL_TEST_DCHECK_STRNE DCHECK_STRNE\n#define ABSL_TEST_DCHECK_STRCASEEQ DCHECK_STRCASEEQ\n#define ABSL_TEST_DCHECK_STRCASENE DCHECK_STRCASENE\n\n#define ABSL_TEST_QCHECK QCHECK\n#define ABSL_TEST_QCHECK_OK QCHECK_OK\n#define ABSL_TEST_QCHECK_EQ QCHECK_EQ\n#define ABSL_TEST_QCHECK_NE QCHECK_NE\n#define ABSL_TEST_QCHECK_GE QCHECK_GE\n#define ABSL_TEST_QCHECK_LE QCHECK_LE\n#define ABSL_TEST_QCHECK_GT QCHECK_GT\n#define ABSL_TEST_QCHECK_LT QCHECK_LT\n#define ABSL_TEST_QCHECK_STREQ QCHECK_STREQ\n#define ABSL_TEST_QCHECK_STRNE QCHECK_STRNE\n#define ABSL_TEST_QCHECK_STRCASEEQ QCHECK_STRCASEEQ\n#define ABSL_TEST_QCHECK_STRCASENE QCHECK_STRCASENE\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/check_test_impl.inc\"\n"
  },
  {
    "path": "absl/log/check_test_impl.inc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_LOG_CHECK_TEST_IMPL_H_\n#define ABSL_LOG_CHECK_TEST_IMPL_H_\n\n// Verify that both sets of macros behave identically by parameterizing the\n// entire test file.\n#ifndef ABSL_TEST_CHECK\n#error ABSL_TEST_CHECK must be defined for these tests to work.\n#endif\n\n#include <cstdint>\n#include <limits>\n#include <ostream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/status/status.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/substitute.h\"\n\n// NOLINTBEGIN(misc-definitions-in-headers)\n\nnamespace absl_log_internal {\n\nusing ::testing::AllOf;\nusing ::testing::AnyOf;\nusing ::testing::ContainsRegex;\nusing ::testing::HasSubstr;\nusing ::testing::Not;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\n#if GTEST_HAS_DEATH_TEST\n\nTEST(CHECKDeathTest, TestBasicValues) {\n  ABSL_TEST_CHECK(true);\n\n  EXPECT_DEATH(ABSL_TEST_CHECK(false), \"Check failed: false\");\n\n  int i = 2;\n  ABSL_TEST_CHECK(i != 3);  // NOLINT\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\nTEST(CHECKTest, TestLogicExpressions) {\n  int i = 5;\n  ABSL_TEST_CHECK(i > 0 && i < 10);\n  ABSL_TEST_CHECK(i < 0 || i > 3);\n}\n\nABSL_CONST_INIT const auto global_var_check = [](int i) {\n  ABSL_TEST_CHECK(i > 0);  // NOLINT\n  return i + 1;\n}(3);\n\nABSL_CONST_INIT const auto global_var = [](int i) {\n  ABSL_TEST_CHECK_GE(i, 0);  // NOLINT\n  return i + 1;\n}(global_var_check);\n\nTEST(CHECKTest, TestPlacementsInCompoundStatements) {\n  // check placement inside if/else clauses\n  if (true) ABSL_TEST_CHECK(true);\n\n  if (false)\n    ;  // NOLINT\n  else\n    ABSL_TEST_CHECK(true);\n\n  switch (0)\n  case 0:\n    ABSL_TEST_CHECK(true);  // NOLINT\n\n  constexpr auto var = [](int i) {\n    ABSL_TEST_CHECK(i > 0);  // NOLINT\n    return i + 1;\n  }(global_var);\n  (void)var;\n}\n\nTEST(CHECKTest, TestBoolConvertible) {\n  struct Tester {\n  } tester;\n  ABSL_TEST_CHECK([&]() { return &tester; }());\n}\n\n#if GTEST_HAS_DEATH_TEST\n\nTEST(CHECKDeathTest, TestChecksWithSideEffects) {\n  int var = 0;\n  ABSL_TEST_CHECK([&var]() {\n    ++var;\n    return true;\n  }());\n  EXPECT_EQ(var, 1);\n\n  EXPECT_DEATH(ABSL_TEST_CHECK([&var]() {\n                 ++var;\n                 return false;\n               }()) << var,\n               \"Check failed: .* 2\");\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\ntemplate <int a, int b>\nconstexpr int sum() {\n  return a + b;\n}\n#define MACRO_ONE 1\n#define TEMPLATE_SUM(a, b) sum<a, b>()\n#define CONCAT(a, b) a b\n#define IDENTITY(x) x\n\nTEST(CHECKTest, TestPassingMacroExpansion) {\n  ABSL_TEST_CHECK(IDENTITY(true));\n  ABSL_TEST_CHECK_EQ(TEMPLATE_SUM(MACRO_ONE, 2), 3);\n  ABSL_TEST_CHECK_STREQ(CONCAT(\"x\", \"y\"), \"xy\");\n}\n\n#if GTEST_HAS_DEATH_TEST\n\nTEST(CHECKTest, TestMacroExpansionInMessage) {\n  auto MessageGen = []() { ABSL_TEST_CHECK(IDENTITY(false)); };\n  EXPECT_DEATH(MessageGen(), HasSubstr(\"IDENTITY(false)\"));\n}\n\nTEST(CHECKTest, TestNestedMacroExpansionInMessage) {\n  EXPECT_DEATH(ABSL_TEST_CHECK(IDENTITY(false)), HasSubstr(\"IDENTITY(false)\"));\n}\n\nTEST(CHECKTest, TestMacroExpansionCompare) {\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(IDENTITY(false), IDENTITY(true)),\n               HasSubstr(\"IDENTITY(false) == IDENTITY(true)\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GT(IDENTITY(1), IDENTITY(2)),\n               HasSubstr(\"IDENTITY(1) > IDENTITY(2)\"));\n}\n\nTEST(CHECKTest, TestMacroExpansionStrCompare) {\n  EXPECT_DEATH(ABSL_TEST_CHECK_STREQ(IDENTITY(\"x\"), IDENTITY(\"y\")),\n               HasSubstr(\"IDENTITY(\\\"x\\\") == IDENTITY(\\\"y\\\")\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_STRCASENE(IDENTITY(\"a\"), IDENTITY(\"A\")),\n               HasSubstr(\"IDENTITY(\\\"a\\\") != IDENTITY(\\\"A\\\")\"));\n}\n\nTEST(CHECKTest, TestMacroExpansionStatus) {\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_OK(IDENTITY(absl::FailedPreconditionError(\"message\"))),\n      HasSubstr(\"IDENTITY(absl::FailedPreconditionError(\\\"message\\\"))\"));\n}\n\nTEST(CHECKTest, TestMacroExpansionComma) {\n  EXPECT_DEATH(ABSL_TEST_CHECK(TEMPLATE_SUM(MACRO_ONE, 2) == 4),\n               HasSubstr(\"TEMPLATE_SUM(MACRO_ONE, 2) == 4\"));\n}\n\nTEST(CHECKTest, TestMacroExpansionCommaCompare) {\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(TEMPLATE_SUM(2, MACRO_ONE), TEMPLATE_SUM(3, 2)),\n      HasSubstr(\"TEMPLATE_SUM(2, MACRO_ONE) == TEMPLATE_SUM(3, 2)\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_GT(TEMPLATE_SUM(2, MACRO_ONE), TEMPLATE_SUM(3, 2)),\n      HasSubstr(\"TEMPLATE_SUM(2, MACRO_ONE) > TEMPLATE_SUM(3, 2)\"));\n}\n\nTEST(CHECKTest, TestMacroExpansionCommaStrCompare) {\n  EXPECT_DEATH(ABSL_TEST_CHECK_STREQ(CONCAT(\"x\", \"y\"), \"z\"),\n               HasSubstr(\"CONCAT(\\\"x\\\", \\\"y\\\") == \\\"z\\\"\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_STRNE(CONCAT(\"x\", \"y\"), \"xy\"),\n               HasSubstr(\"CONCAT(\\\"x\\\", \\\"y\\\") != \\\"xy\\\"\"));\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\n#undef TEMPLATE_SUM\n#undef CONCAT\n#undef MACRO\n#undef ONE\n\n#if GTEST_HAS_DEATH_TEST\n\nTEST(CHECKDeachTest, TestOrderOfInvocationsBetweenCheckAndMessage) {\n  int counter = 0;\n\n  auto GetStr = [&counter]() -> std::string {\n    return counter++ == 0 ? \"\" : \"non-empty\";\n  };\n\n  EXPECT_DEATH(ABSL_TEST_CHECK(!GetStr().empty()) << GetStr(),\n               HasSubstr(\"non-empty\"));\n}\n\nTEST(CHECKTest, TestSecondaryFailure) {\n  auto FailingRoutine = []() {\n    ABSL_TEST_CHECK(false) << \"Secondary\";\n    return false;\n  };\n  EXPECT_DEATH(ABSL_TEST_CHECK(FailingRoutine()) << \"Primary\",\n               AllOf(HasSubstr(\"Secondary\"), Not(HasSubstr(\"Primary\"))));\n}\n\nTEST(CHECKTest, TestSecondaryFailureInMessage) {\n  auto MessageGen = []() {\n    ABSL_TEST_CHECK(false) << \"Secondary\";\n    return \"Primary\";\n  };\n  EXPECT_DEATH(ABSL_TEST_CHECK(false) << MessageGen(),\n               AllOf(HasSubstr(\"Secondary\"), Not(HasSubstr(\"Primary\"))));\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\nTEST(CHECKTest, TestBinaryChecksWithPrimitives) {\n  ABSL_TEST_CHECK_EQ(1, 1);\n  ABSL_TEST_CHECK_NE(1, 2);\n  ABSL_TEST_CHECK_GE(1, 1);\n  ABSL_TEST_CHECK_GE(2, 1);\n  ABSL_TEST_CHECK_LE(1, 1);\n  ABSL_TEST_CHECK_LE(1, 2);\n  ABSL_TEST_CHECK_GT(2, 1);\n  ABSL_TEST_CHECK_LT(1, 2);\n}\n\nTEST(CHECKTest, TestBinaryChecksWithStringComparison) {\n  const std::string a = \"a\";\n  ABSL_TEST_CHECK_EQ(a, \"a\");\n  ABSL_TEST_CHECK_NE(a, \"b\");\n  ABSL_TEST_CHECK_GE(a, a);\n  ABSL_TEST_CHECK_GE(\"b\", a);\n  ABSL_TEST_CHECK_LE(a, \"a\");\n  ABSL_TEST_CHECK_LE(a, \"b\");\n  ABSL_TEST_CHECK_GT(\"b\", a);\n  ABSL_TEST_CHECK_LT(a, \"b\");\n}\n\nTEST(CHECKDeathTest, CheckWithCharStarAndStringPrintsTheCharStar) {\n  std::string str = \"B\";\n\n  // When the comparison happens as strings, then we print the CharT* as a\n  // string.\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(\"A\", str),\n               R\"re(Check failed: \\\"A\\\" == str \\(A vs. B\\))re\");\n}\n\n#if defined(GTEST_USES_SIMPLE_RE) && GTEST_USES_SIMPLE_RE\n#define POINTER_VALUE_RE R\"re(\\w*)re\"\n#else\n#define POINTER_VALUE_RE R\"re((0x)*[0-9a-fA-F]*)re\"\n#endif\n\n#define POINTER_VS_POINTER_RE(lhs, rhs) \"\\\\(\" lhs \" vs. \" rhs \"\\\\)\"\n\ntemplate <typename CharT>\nvoid TestCharStarComparison() {\n  // When the comparison happens as pointers, we only print the pointer and not\n  // interpret it as a C-String because it might not be.\n  // Leave the CharTs uninitialized to trigger ASan/MSan failures if we actually\n  // read the pointers.\n  CharT* p1 = new CharT;\n  CharT* p2 = new CharT;\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(p1, p2),\n               R\"re(Check failed: p1 == p2 )re\" POINTER_VS_POINTER_RE(\n                   POINTER_VALUE_RE, POINTER_VALUE_RE));\n  CharT as_array[10];\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(p1, as_array),\n               R\"re(Check failed: p1 == as_array )re\" POINTER_VS_POINTER_RE(\n                   POINTER_VALUE_RE, POINTER_VALUE_RE));\n\n  const void* as_void = as_array;\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(as_void, p2),\n               R\"re(Check failed: as_void == p2 )re\" POINTER_VS_POINTER_RE(\n                   POINTER_VALUE_RE, POINTER_VALUE_RE));\n\n  delete p1;\n  delete p2;\n}\n\nTEST(CHECKDeathTest, CheckWithCharStarStringification) {\n  TestCharStarComparison<char>();\n  TestCharStarComparison<signed char>();\n  TestCharStarComparison<unsigned char>();\n  TestCharStarComparison<wchar_t>();\n#if defined(__cpp_char8_t)\n  TestCharStarComparison<char8_t>();\n#endif\n  TestCharStarComparison<char16_t>();\n  TestCharStarComparison<char32_t>();\n}\n\n// For testing using CHECK*() on anonymous enums.\nenum { CASE_A, CASE_B };\n\nTEST(CHECKTest, TestBinaryChecksWithEnumValues) {\n  // Tests using CHECK*() on anonymous enums.\n  ABSL_TEST_CHECK_EQ(CASE_A, CASE_A);\n  ABSL_TEST_CHECK_NE(CASE_A, CASE_B);\n  ABSL_TEST_CHECK_GE(CASE_A, CASE_A);\n  ABSL_TEST_CHECK_GE(CASE_B, CASE_A);\n  ABSL_TEST_CHECK_LE(CASE_A, CASE_A);\n  ABSL_TEST_CHECK_LE(CASE_A, CASE_B);\n  ABSL_TEST_CHECK_GT(CASE_B, CASE_A);\n  ABSL_TEST_CHECK_LT(CASE_A, CASE_B);\n}\n\nTEST(CHECKTest, TestBinaryChecksWithNullptr) {\n  const void* p_null = nullptr;\n  const void* p_not_null = &p_null;\n  ABSL_TEST_CHECK_EQ(p_null, nullptr);\n  ABSL_TEST_CHECK_EQ(nullptr, p_null);\n  ABSL_TEST_CHECK_NE(p_not_null, nullptr);\n  ABSL_TEST_CHECK_NE(nullptr, p_not_null);\n}\n\nstruct ExampleTypeThatHasNoStreamOperator {\n  bool x;\n\n  bool operator==(const ExampleTypeThatHasNoStreamOperator& other) const {\n    return x == other.x;\n  }\n  bool operator==(const bool& other) const { return x == other; }\n};\n\nTEST(CHECKDeathTest, TestBinaryChecksWithUnprintable) {\n  ExampleTypeThatHasNoStreamOperator a{true};\n  ExampleTypeThatHasNoStreamOperator b{false};\n  ABSL_TEST_CHECK_EQ(a, a);\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b), \"Check failed: a == b\");\n  ABSL_TEST_CHECK_EQ(a, true);\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, false),\n               \"Check failed: a == false \\\\(UNPRINTABLE vs. 0\\\\)\");\n}\n\n#if GTEST_HAS_DEATH_TEST\n\n// Test logging of various char-typed values by failing CHECK*().\nTEST(CHECKDeathTest, TestComparingCharsValues) {\n  {\n    char a = ';';\n    char b = 'b';\n    EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n                 \"Check failed: a == b \\\\(';' vs. 'b'\\\\)\");\n    b = 1;\n    EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n                 \"Check failed: a == b \\\\(';' vs. char value 1\\\\)\");\n  }\n  {\n    signed char a = ';';\n    signed char b = 'b';\n    EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n                 \"Check failed: a == b \\\\(';' vs. 'b'\\\\)\");\n    b = -128;\n    EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n                 \"Check failed: a == b \\\\(';' vs. signed char value -128\\\\)\");\n  }\n  {\n    unsigned char a = ';';\n    unsigned char b = 'b';\n    EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n                 \"Check failed: a == b \\\\(';' vs. 'b'\\\\)\");\n    b = 128;\n    EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n                 \"Check failed: a == b \\\\(';' vs. unsigned char value 128\\\\)\");\n  }\n}\n\nTEST(CHECKDeathTest, TestNullValuesAreReportedCleanly) {\n  const char* a = nullptr;\n  const char* b = nullptr;\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(a, b),\n               \"Check failed: a != b \\\\(\\\\(null\\\\) vs. \\\\(null\\\\)\\\\)\");\n\n  a = \"xx\";\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),\n               R\"re(Check failed: a == b )re\" POINTER_VS_POINTER_RE(\n                   POINTER_VALUE_RE, \"\\\\(null\\\\)\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(b, a),\n               R\"re(Check failed: b == a )re\" POINTER_VS_POINTER_RE(\n                   \"\\\\(null\\\\)\", POINTER_VALUE_RE));\n\n  std::nullptr_t n{};\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(n, nullptr),\n               \"Check failed: n != nullptr \\\\(\\\\(null\\\\) vs. \\\\(null\\\\)\\\\)\");\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\nTEST(CHECKTest, TestSTREQ) {\n  ABSL_TEST_CHECK_STREQ(\"this\", \"this\");\n  ABSL_TEST_CHECK_STREQ(nullptr, nullptr);\n  ABSL_TEST_CHECK_STRCASEEQ(\"this\", \"tHiS\");\n  ABSL_TEST_CHECK_STRCASEEQ(nullptr, nullptr);\n  ABSL_TEST_CHECK_STRNE(\"this\", \"tHiS\");\n  ABSL_TEST_CHECK_STRNE(\"this\", nullptr);\n  ABSL_TEST_CHECK_STRCASENE(\"this\", \"that\");\n  ABSL_TEST_CHECK_STRCASENE(nullptr, \"that\");\n  ABSL_TEST_CHECK_STREQ((std::string(\"a\") + \"b\").c_str(), \"ab\");\n  ABSL_TEST_CHECK_STREQ(std::string(\"test\").c_str(),\n                        (std::string(\"te\") + std::string(\"st\")).c_str());\n}\n\nTEST(CHECKTest, TestComparisonPlacementsInCompoundStatements) {\n  // check placement inside if/else clauses\n  if (true) ABSL_TEST_CHECK_EQ(1, 1);\n  if (true) ABSL_TEST_CHECK_STREQ(\"c\", \"c\");\n\n  if (false)\n    ;  // NOLINT\n  else\n    ABSL_TEST_CHECK_LE(0, 1);\n\n  if (false)\n    ;  // NOLINT\n  else\n    ABSL_TEST_CHECK_STRNE(\"a\", \"b\");\n\n  switch (0)\n  case 0:\n    ABSL_TEST_CHECK_NE(1, 0);\n\n  switch (0)\n  case 0:\n    ABSL_TEST_CHECK_STRCASEEQ(\"A\", \"a\");\n\n  constexpr auto var = [](int i) {\n    ABSL_TEST_CHECK_GT(i, 0);\n    return i + 1;\n  }(global_var);\n  (void)var;\n\n  // CHECK_STR... checks are not supported in constexpr routines.\n  // constexpr auto var2 = [](int i) {\n  //  ABSL_TEST_CHECK_STRNE(\"c\", \"d\");\n  //  return i + 1;\n  // }(global_var);\n\n#if defined(__GNUC__)\n  int var3 = (({ ABSL_TEST_CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0;\n  (void)var3;\n\n  int var4 = (({ ABSL_TEST_CHECK_STREQ(\"a\", \"a\"); }), global_var < 10) ? 1 : 0;\n  (void)var4;\n#endif  // __GNUC__\n}\n\nTEST(CHECKTest, TestDCHECK) {\n#ifdef NDEBUG\n  ABSL_TEST_DCHECK(1 == 2) << \" DCHECK's shouldn't be compiled in normal mode\";\n#endif\n  ABSL_TEST_DCHECK(1 == 1);  // NOLINT(readability/check)\n  ABSL_TEST_DCHECK_EQ(1, 1);\n  ABSL_TEST_DCHECK_NE(1, 2);\n  ABSL_TEST_DCHECK_GE(1, 1);\n  ABSL_TEST_DCHECK_GE(2, 1);\n  ABSL_TEST_DCHECK_LE(1, 1);\n  ABSL_TEST_DCHECK_LE(1, 2);\n  ABSL_TEST_DCHECK_GT(2, 1);\n  ABSL_TEST_DCHECK_LT(1, 2);\n\n  // Test DCHECK on std::nullptr_t\n  const void* p_null = nullptr;\n  const void* p_not_null = &p_null;\n  ABSL_TEST_DCHECK_EQ(p_null, nullptr);\n  ABSL_TEST_DCHECK_EQ(nullptr, p_null);\n  ABSL_TEST_DCHECK_NE(p_not_null, nullptr);\n  ABSL_TEST_DCHECK_NE(nullptr, p_not_null);\n}\n\nTEST(CHECKTest, TestQCHECK) {\n  // The tests that QCHECK does the same as CHECK\n  ABSL_TEST_QCHECK(1 == 1);  // NOLINT(readability/check)\n  ABSL_TEST_QCHECK_EQ(1, 1);\n  ABSL_TEST_QCHECK_NE(1, 2);\n  ABSL_TEST_QCHECK_GE(1, 1);\n  ABSL_TEST_QCHECK_GE(2, 1);\n  ABSL_TEST_QCHECK_LE(1, 1);\n  ABSL_TEST_QCHECK_LE(1, 2);\n  ABSL_TEST_QCHECK_GT(2, 1);\n  ABSL_TEST_QCHECK_LT(1, 2);\n\n  // Tests using QCHECK*() on anonymous enums.\n  ABSL_TEST_QCHECK_EQ(CASE_A, CASE_A);\n  ABSL_TEST_QCHECK_NE(CASE_A, CASE_B);\n  ABSL_TEST_QCHECK_GE(CASE_A, CASE_A);\n  ABSL_TEST_QCHECK_GE(CASE_B, CASE_A);\n  ABSL_TEST_QCHECK_LE(CASE_A, CASE_A);\n  ABSL_TEST_QCHECK_LE(CASE_A, CASE_B);\n  ABSL_TEST_QCHECK_GT(CASE_B, CASE_A);\n  ABSL_TEST_QCHECK_LT(CASE_A, CASE_B);\n}\n\nTEST(CHECKTest, TestQCHECKPlacementsInCompoundStatements) {\n  // check placement inside if/else clauses\n  if (true) ABSL_TEST_QCHECK(true);\n\n  if (false)\n    ;  // NOLINT\n  else\n    ABSL_TEST_QCHECK(true);\n\n  if (false)\n    ;  // NOLINT\n  else\n    ABSL_TEST_QCHECK(true);\n\n  switch (0)\n  case 0:\n    ABSL_TEST_QCHECK(true);\n\n  constexpr auto var = [](int i) {\n    ABSL_TEST_QCHECK(i > 0);  // NOLINT\n    return i + 1;\n  }(global_var);\n  (void)var;\n\n#if defined(__GNUC__)\n  int var2 = (({ ABSL_TEST_CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0;\n  (void)var2;\n#endif  // __GNUC__\n}\n\nclass ComparableType {\n public:\n  explicit ComparableType(int v) : v_(v) {}\n\n  void MethodWithCheck(int i) {\n    ABSL_TEST_CHECK_EQ(*this, i);\n    ABSL_TEST_CHECK_EQ(i, *this);\n  }\n\n  int Get() const { return v_; }\n\n private:\n  friend bool operator==(const ComparableType& lhs, const ComparableType& rhs) {\n    return lhs.v_ == rhs.v_;\n  }\n  friend bool operator!=(const ComparableType& lhs, const ComparableType& rhs) {\n    return lhs.v_ != rhs.v_;\n  }\n  friend bool operator<(const ComparableType& lhs, const ComparableType& rhs) {\n    return lhs.v_ < rhs.v_;\n  }\n  friend bool operator<=(const ComparableType& lhs, const ComparableType& rhs) {\n    return lhs.v_ <= rhs.v_;\n  }\n  friend bool operator>(const ComparableType& lhs, const ComparableType& rhs) {\n    return lhs.v_ > rhs.v_;\n  }\n  friend bool operator>=(const ComparableType& lhs, const ComparableType& rhs) {\n    return lhs.v_ >= rhs.v_;\n  }\n  friend bool operator==(const ComparableType& lhs, int rhs) {\n    return lhs.v_ == rhs;\n  }\n  friend bool operator==(int lhs, const ComparableType& rhs) {\n    return lhs == rhs.v_;\n  }\n\n  friend std::ostream& operator<<(std::ostream& out, const ComparableType& v) {\n    return out << \"ComparableType{\" << v.Get() << \"}\";\n  }\n\n  int v_;\n};\n\nTEST(CHECKTest, TestUserDefinedCompOp) {\n  ABSL_TEST_CHECK_EQ(ComparableType{0}, ComparableType{0});\n  ABSL_TEST_CHECK_NE(ComparableType{1}, ComparableType{2});\n  ABSL_TEST_CHECK_LT(ComparableType{1}, ComparableType{2});\n  ABSL_TEST_CHECK_LE(ComparableType{1}, ComparableType{2});\n  ABSL_TEST_CHECK_GT(ComparableType{2}, ComparableType{1});\n  ABSL_TEST_CHECK_GE(ComparableType{2}, ComparableType{2});\n}\n\nTEST(CHECKTest, TestCheckInMethod) {\n  ComparableType v{1};\n  v.MethodWithCheck(1);\n}\n\nTEST(CHECKDeathTest, TestUserDefinedStreaming) {\n  ComparableType v1{1};\n  ComparableType v2{2};\n\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(v1, v2),\n      HasSubstr(\n          \"Check failed: v1 == v2 (ComparableType{1} vs. ComparableType{2})\"));\n}\n\n// A type that can be printed using AbslStringify.\nstruct StringifiableType {\n  int x = 0;\n  explicit StringifiableType(int x) : x(x) {}\n  friend bool operator==(const StringifiableType& lhs,\n                         const StringifiableType& rhs) {\n    return lhs.x == rhs.x;\n  }\n  friend bool operator!=(const StringifiableType& lhs,\n                         const StringifiableType& rhs) {\n    return lhs.x != rhs.x;\n  }\n  friend bool operator<(const StringifiableType& lhs,\n                        const StringifiableType& rhs) {\n    return lhs.x < rhs.x;\n  }\n  friend bool operator>(const StringifiableType& lhs,\n                        const StringifiableType& rhs) {\n    return lhs.x > rhs.x;\n  }\n  friend bool operator<=(const StringifiableType& lhs,\n                         const StringifiableType& rhs) {\n    return lhs.x <= rhs.x;\n  }\n  friend bool operator>=(const StringifiableType& lhs,\n                         const StringifiableType& rhs) {\n    return lhs.x >= rhs.x;\n  }\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const StringifiableType& obj) {\n    absl::Format(&sink, \"StringifiableType{%d}\", obj.x);\n  }\n\n  // Make sure no unintended copy happens.\n  StringifiableType(const StringifiableType&) = delete;\n};\n\nTEST(CHECKTest, TestUserDefinedAbslStringify) {\n  const StringifiableType v1(1);\n  const StringifiableType v2(2);\n\n  ABSL_TEST_CHECK_EQ(v1, v1);\n  ABSL_TEST_CHECK_NE(v1, v2);\n  ABSL_TEST_CHECK_LT(v1, v2);\n  ABSL_TEST_CHECK_LE(v1, v2);\n  ABSL_TEST_CHECK_GT(v2, v1);\n  ABSL_TEST_CHECK_GE(v2, v1);\n}\n\nTEST(CHECKDeathTest, TestUserDefinedAbslStringify) {\n  const StringifiableType v1(1);\n  const StringifiableType v2(2);\n\n  // Returns a matcher for the expected check failure message when comparing two\n  // values.\n  auto expected_output = [](int lhs, absl::string_view condition, int rhs) {\n    return HasSubstr(\n        absl::Substitute(\"Check failed: v$0 $1 v$2 (StringifiableType{$0} vs. \"\n                         \"StringifiableType{$2})\",\n                         lhs, condition, rhs));\n  };\n  // Test comparisons where the check fails.\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(v1, v2), expected_output(1, \"==\", 2));\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(v1, v1), expected_output(1, \"!=\", 1));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LT(v2, v1), expected_output(2, \"<\", 1));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LE(v2, v1), expected_output(2, \"<=\", 1));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GT(v1, v2), expected_output(1, \">\", 2));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GE(v1, v2), expected_output(1, \">=\", 2));\n}\n\n// A type that can be printed using both AbslStringify and operator<<.\nstruct StringifiableStreamableType {\n  int x = 0;\n  explicit StringifiableStreamableType(int x) : x(x) {}\n\n  friend bool operator==(const StringifiableStreamableType& lhs,\n                         const StringifiableStreamableType& rhs) {\n    return lhs.x == rhs.x;\n  }\n  friend bool operator!=(const StringifiableStreamableType& lhs,\n                         const StringifiableStreamableType& rhs) {\n    return lhs.x != rhs.x;\n  }\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink,\n                            const StringifiableStreamableType& obj) {\n    absl::Format(&sink, \"Strigified{%d}\", obj.x);\n  }\n  friend std::ostream& operator<<(std::ostream& out,\n                                  const StringifiableStreamableType& obj) {\n    return out << \"Streamed{\" << obj.x << \"}\";\n  }\n\n  // Avoid unintentional copy.\n  StringifiableStreamableType(const StringifiableStreamableType&) = delete;\n};\n\nTEST(CHECKDeathTest, TestStreamingPreferredOverAbslStringify) {\n  StringifiableStreamableType v1(1);\n  StringifiableStreamableType v2(2);\n\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(v1, v2),\n      HasSubstr(\"Check failed: v1 == v2 (Streamed{1} vs. Streamed{2})\"));\n}\n\n// A type whose pointer can be passed to AbslStringify.\nstruct PointerIsStringifiable {};\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, const PointerIsStringifiable* var) {\n  sink.Append(\"PointerIsStringifiable\");\n}\n\n// Verifies that a pointer is printed as a number despite having AbslStringify\n// defined. Users may implement AbslStringify that dereferences the pointer, and\n// doing so as part of DCHECK would not be good.\nTEST(CHECKDeathTest, TestPointerPrintedAsNumberDespiteAbslStringify) {\n  const auto* p = reinterpret_cast<const PointerIsStringifiable*>(0x1234);\n\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(p, nullptr),\n      AnyOf(\n          HasSubstr(\"Check failed: p == nullptr (0000000000001234 vs. (null))\"),\n          HasSubstr(\"Check failed: p == nullptr (0x1234 vs. (null))\")));\n}\n\n// An uncopyable object with operator<<.\nstruct Uncopyable {\n  int x;\n  explicit Uncopyable(int x) : x(x) {}\n  Uncopyable(const Uncopyable&) = delete;\n  friend bool operator==(const Uncopyable& lhs, const Uncopyable& rhs) {\n    return lhs.x == rhs.x;\n  }\n  friend bool operator!=(const Uncopyable& lhs, const Uncopyable& rhs) {\n    return lhs.x != rhs.x;\n  }\n  friend std::ostream& operator<<(std::ostream& os, const Uncopyable& obj) {\n    return os << \"Uncopyable{\" << obj.x << \"}\";\n  }\n};\n\n// Test that an uncopyable object can be used.\n// Will catch us if implementation has an unintended copy.\nTEST(CHECKDeathTest, TestUncopyable) {\n  const Uncopyable v1(1);\n  const Uncopyable v2(2);\n\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(v1, v2),\n      HasSubstr(\"Check failed: v1 == v2 (Uncopyable{1} vs. Uncopyable{2})\"));\n}\n\nenum class ScopedEnum { kValue1 = 1, kValue2 = 2 };\n\nTEST(CHECKTest, TestScopedEnumComparisonChecks) {\n  ABSL_TEST_CHECK_EQ(ScopedEnum::kValue1, ScopedEnum::kValue1);\n  ABSL_TEST_CHECK_NE(ScopedEnum::kValue1, ScopedEnum::kValue2);\n  ABSL_TEST_CHECK_LT(ScopedEnum::kValue1, ScopedEnum::kValue2);\n  ABSL_TEST_CHECK_LE(ScopedEnum::kValue1, ScopedEnum::kValue2);\n  ABSL_TEST_CHECK_GT(ScopedEnum::kValue2, ScopedEnum::kValue1);\n  ABSL_TEST_CHECK_GE(ScopedEnum::kValue2, ScopedEnum::kValue2);\n  ABSL_TEST_DCHECK_EQ(ScopedEnum::kValue1, ScopedEnum::kValue1);\n  ABSL_TEST_DCHECK_NE(ScopedEnum::kValue1, ScopedEnum::kValue2);\n  ABSL_TEST_DCHECK_LT(ScopedEnum::kValue1, ScopedEnum::kValue2);\n  ABSL_TEST_DCHECK_LE(ScopedEnum::kValue1, ScopedEnum::kValue2);\n  ABSL_TEST_DCHECK_GT(ScopedEnum::kValue2, ScopedEnum::kValue1);\n  ABSL_TEST_DCHECK_GE(ScopedEnum::kValue2, ScopedEnum::kValue2);\n\n  // Check that overloads work correctly with references as well.\n  const ScopedEnum x = ScopedEnum::kValue1;\n  const ScopedEnum& x_ref = x;\n  ABSL_TEST_CHECK_EQ(x, x_ref);\n  ABSL_TEST_CHECK_EQ(x_ref, x_ref);\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(CHECKDeathTest, TestScopedEnumCheckFailureMessagePrintsIntegerValues) {\n  const auto e1 = ScopedEnum::kValue1;\n  const auto e2 = ScopedEnum::kValue2;\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(e1, e2),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 2\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(e1, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 1\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GT(e1, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 1\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GE(e1, e2),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 2\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LT(e2, e2),\n               ContainsRegex(R\"re(Check failed:.*\\(2 vs. 2\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LE(e2, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(2 vs. 1\\))re\"));\n\n  const auto& e1_ref = e1;\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(e1_ref, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 1\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(e1_ref, e1_ref),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 1\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(e2, e1_ref),\n               ContainsRegex(R\"re(Check failed:.*\\(2 vs. 1\\))re\"));\n\n#ifndef NDEBUG\n  EXPECT_DEATH(ABSL_TEST_DCHECK_EQ(e2, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(2 vs. 1\\))re\"));\n#else\n  // DHECK_EQ is not evaluated in non-debug mode.\n  ABSL_TEST_DCHECK_EQ(e2, e1);\n#endif  // NDEBUG\n}\n#endif  // GTEST_HAS_DEATH_TEST\n\nenum class ScopedInt8Enum : int8_t {\n  kValue1 = 1,\n  kValue2 = 66  // Printable ascii value 'B'.\n};\n\nTEST(CHECKDeathTest, TestScopedInt8EnumCheckFailureMessagePrintsCharValues) {\n  const auto e1 = ScopedInt8Enum::kValue1;\n  const auto e2 = ScopedInt8Enum::kValue2;\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(e1, e2),\n      ContainsRegex(R\"re(Check failed:.*\\(signed char value 1 vs. 'B'\\))re\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_NE(e1, e1),\n      ContainsRegex(\n          R\"re(Check failed:.*\\(signed char value 1 vs. signed char value 1\\))re\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_GT(e1, e1),\n      ContainsRegex(\n          R\"re(Check failed:.*\\(signed char value 1 vs. signed char value 1\\))re\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_GE(e1, e2),\n      ContainsRegex(R\"re(Check failed:.*\\(signed char value 1 vs. 'B'\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LT(e2, e2),\n               ContainsRegex(R\"re(Check failed:.*\\('B' vs. 'B'\\))re\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_LE(e2, e1),\n      ContainsRegex(R\"re(Check failed:.*\\('B' vs. signed char value 1\\))re\"));\n}\n\nenum class ScopedUnsignedEnum : uint16_t {\n  kValue1 = std::numeric_limits<uint16_t>::min(),\n  kValue2 = std::numeric_limits<uint16_t>::max()\n};\n\nTEST(CHECKDeathTest,\n     TestScopedUnsignedEnumCheckFailureMessagePrintsCorrectValues) {\n  const auto e1 = ScopedUnsignedEnum::kValue1;\n  const auto e2 = ScopedUnsignedEnum::kValue2;\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(e1, e2),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 65535\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(e1, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 0\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GT(e1, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 0\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GE(e1, e2),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 65535\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LT(e1, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 0\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LE(e2, e1),\n               ContainsRegex(R\"re(Check failed:.*\\(65535 vs. 0\\))re\"));\n}\n\nenum class ScopedInt64Enum : int64_t {\n  kMin = std::numeric_limits<int64_t>::min(),\n  kMax = std::numeric_limits<int64_t>::max(),\n};\n\n// Tests that int64-backed enums are printed correctly even for very large and\n// very small values.\nTEST(CHECKDeathTest, TestScopedInt64EnumCheckFailureMessage) {\n  const auto min = ScopedInt64Enum::kMin;\n  const auto max = ScopedInt64Enum::kMax;\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(max, min),\n      ContainsRegex(\n          \"Check failed:.*9223372036854775807 vs. -9223372036854775808\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_NE(max, max),\n      ContainsRegex(\n          \"Check failed:.*9223372036854775807 vs. 9223372036854775807\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_GT(min, min),\n      ContainsRegex(\n          \"Check failed:.*-9223372036854775808 vs. -9223372036854775808\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_GE(min, max),\n      ContainsRegex(\n          R\"(Check failed:.*-9223372036854775808 vs. 9223372036854775807)\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_LT(max, max),\n      ContainsRegex(\n          R\"(Check failed:.*9223372036854775807 vs. 9223372036854775807)\"));\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_LE(max, min),\n      ContainsRegex(\n          R\"(Check failed:.*9223372036854775807 vs. -9223372036854775808)\"));\n}\n\nenum class ScopedBoolEnum : bool {\n  kFalse,\n  kTrue,\n};\n\nTEST(CHECKDeathTest, TestScopedBoolEnumCheckFailureMessagePrintsCorrectValues) {\n  const auto t = ScopedBoolEnum::kTrue;\n  const auto f = ScopedBoolEnum::kFalse;\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(t, f),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 0\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_NE(f, f),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 0\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GT(f, f),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 0\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_GE(f, t),\n               ContainsRegex(R\"re(Check failed:.*\\(0 vs. 1\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LT(t, t),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 1\\))re\"));\n  EXPECT_DEATH(ABSL_TEST_CHECK_LE(t, f),\n               ContainsRegex(R\"re(Check failed:.*\\(1 vs. 0\\))re\"));\n}\n\nenum class ScopedEnumWithAbslStringify {\n  kValue1 = 1,\n  kValue2 = 2,\n  kValue3 = 3\n};\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, ScopedEnumWithAbslStringify v) {\n  switch (v) {\n    case ScopedEnumWithAbslStringify::kValue1:\n      sink.Append(\"AbslStringify: kValue1\");\n      break;\n    case ScopedEnumWithAbslStringify::kValue2:\n      sink.Append(\"AbslStringify: kValue2\");\n      break;\n    case ScopedEnumWithAbslStringify::kValue3:\n      sink.Append(\"AbslStringify: kValue3\");\n      break;\n  }\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(CHECKDeathTest, TestScopedEnumUsesAbslStringify) {\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(ScopedEnumWithAbslStringify::kValue1,\n                                  ScopedEnumWithAbslStringify::kValue2),\n               ContainsRegex(\"Check failed:.*AbslStringify: kValue1 vs. \"\n                             \"AbslStringify: kValue2\"));\n}\n#endif  // GTEST_HAS_DEATH_TEST\n\nenum class ScopedEnumWithOutputOperator {\n  kValue1 = 1,\n  kValue2 = 2,\n};\n\nstd::ostream& operator<<(std::ostream& os, ScopedEnumWithOutputOperator v) {\n  switch (v) {\n    case ScopedEnumWithOutputOperator::kValue1:\n      os << \"OutputOperator: kValue1\";\n      break;\n    case ScopedEnumWithOutputOperator::kValue2:\n      os << \"OutputOperator: kValue2\";\n      break;\n  }\n  return os;\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(CHECKDeathTest, TestOutputOperatorIsUsedForScopedEnum) {\n  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(ScopedEnumWithOutputOperator::kValue1,\n                                  ScopedEnumWithOutputOperator::kValue2),\n               ContainsRegex(\"Check failed:.*OutputOperator: kValue1 vs. \"\n                             \"OutputOperator: kValue2\"));\n}\n#endif  // GTEST_HAS_DEATH_TEST\n\nenum class ScopedEnumWithAbslStringifyAndOutputOperator {\n  kValue1 = 1,\n  kValue2 = 2,\n};\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, ScopedEnumWithAbslStringifyAndOutputOperator v) {\n  switch (v) {\n    case ScopedEnumWithAbslStringifyAndOutputOperator::kValue1:\n      sink.Append(\"AbslStringify: kValue1\");\n      break;\n    case ScopedEnumWithAbslStringifyAndOutputOperator::kValue2:\n      sink.Append(\"AbslStringify: kValue2\");\n      break;\n  }\n}\n\nstd::ostream& operator<<(std::ostream& os,\n                         ScopedEnumWithAbslStringifyAndOutputOperator v) {\n  switch (v) {\n    case ScopedEnumWithAbslStringifyAndOutputOperator::kValue1:\n      os << \"OutputOperator: kValue1\";\n      break;\n    case ScopedEnumWithAbslStringifyAndOutputOperator::kValue2:\n      os << \"OutputOperator: kValue2\";\n      break;\n  }\n  return os;\n}\n\n#if GTEST_HAS_DEATH_TEST\n\n// Test that, if operator<< and AbslStringify are both defined for a scoped\n// enum, streaming takes precedence over AbslStringify.\nTEST(CHECKDeathTest, TestScopedEnumPrefersOutputOperatorOverAbslStringify) {\n  EXPECT_DEATH(\n      ABSL_TEST_CHECK_EQ(ScopedEnumWithAbslStringifyAndOutputOperator::kValue1,\n                         ScopedEnumWithAbslStringifyAndOutputOperator::kValue2),\n      ContainsRegex(\"Check failed:.*OutputOperator: kValue1 vs. \"\n                    \"OutputOperator: kValue2\"));\n}\n#endif  // GTEST_HAS_DEATH_TEST\n\n}  // namespace absl_log_internal\n\n// NOLINTEND(misc-definitions-in-headers)\n\n#endif  // ABSL_LOG_CHECK_TEST_IMPL_H_\n"
  },
  {
    "path": "absl/log/die_if_null.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/die_if_null.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/log/log.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nvoid DieBecauseNull(const char* absl_nonnull file, int line,\n                    const char* absl_nonnull exprtext) {\n  LOG(FATAL).AtLocation(file, line)\n      << absl::StrCat(\"Check failed: '\", exprtext, \"' Must be non-null\");\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/die_if_null.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/die_if_null.h\n// -----------------------------------------------------------------------------\n//\n// This header declares macro `ABSL_DIE_IF_NULL`.\n\n#ifndef ABSL_LOG_DIE_IF_NULL_H_\n#define ABSL_LOG_DIE_IF_NULL_H_\n\n#include <stdint.h>\n\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/nullability_traits.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n\n// ABSL_DIE_IF_NULL()\n//\n// `ABSL_DIE_IF_NULL` behaves as `CHECK_NE` against `nullptr` but *also*\n// \"returns\" its argument.  It is useful in initializers where statements (like\n// `CHECK_NE`) can't be used.  Outside initializers, prefer `CHECK` or\n// `CHECK_NE`. `ABSL_DIE_IF_NULL` works for both raw pointers and (compatible)\n// smart pointers including `std::unique_ptr` and `std::shared_ptr`; more\n// generally, it works for any type that can be compared to nullptr_t.  For\n// types that aren't raw pointers, `ABSL_DIE_IF_NULL` returns a reference to\n// its argument, preserving the value category. Example:\n//\n//   Foo() : bar_(ABSL_DIE_IF_NULL(MethodReturningUniquePtr())) {}\n//\n// Use `CHECK(ptr)` or `CHECK(ptr != nullptr)` if the returned pointer is\n// unused.\n#define ABSL_DIE_IF_NULL(val) \\\n  ::absl::log_internal::DieIfNull(__FILE__, __LINE__, #val, (val))\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// Crashes the process after logging `exprtext` annotated at the `file` and\n// `line` location. Called when `ABSL_DIE_IF_NULL` fails. Calling this function\n// generates less code than its implementation would if inlined, for a slight\n// code size reduction each time `ABSL_DIE_IF_NULL` is called.\n[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void DieBecauseNull(\n    const char* absl_nonnull file, int line, const char* absl_nonnull exprtext);\n\n// Helper for `ABSL_DIE_IF_NULL`.\n\n// Since we use `remove_reference_t` before `AddNonnullIfCompatible`, we need\n// to explicitly have overloads for both lvalue reference and rvalue reference\n// arguments and returns.\ntemplate <typename T>\n[[nodiscard]] typename absl::base_internal::AddNonnullIfCompatible<\n    std::remove_reference_t<T>>::type&\nDieIfNull(const char* absl_nonnull file, int line,\n          const char* absl_nonnull exprtext, T& t) {\n  if (ABSL_PREDICT_FALSE(t == nullptr)) {\n    // Call a non-inline helper function for a small code size improvement.\n    DieBecauseNull(file, line, exprtext);\n  }\n  return t;\n}\n\ntemplate <typename T>\n[[nodiscard]] typename absl::base_internal::AddNonnullIfCompatible<\n    std::remove_reference_t<T>>::type&&\nDieIfNull(const char* absl_nonnull file, int line,\n          const char* absl_nonnull exprtext, T&& t) {\n  if (ABSL_PREDICT_FALSE(t == nullptr)) {\n    // Call a non-inline helper function for a small code size improvement.\n    DieBecauseNull(file, line, exprtext);\n  }\n  return std::forward<T>(t);\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_DIE_IF_NULL_H_\n"
  },
  {
    "path": "absl/log/die_if_null_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/die_if_null.h\"\n\n#include <stdint.h>\n\n#include <memory>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/log/internal/test_helpers.h\"\n\nnamespace {\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\n// TODO(b/69907837): Revisit these tests with the goal of making them less\n// convoluted.\nTEST(AbslDieIfNull, Simple) {\n  int64_t t;\n  void* ptr = static_cast<void*>(&t);\n  void* ref = ABSL_DIE_IF_NULL(ptr);\n  ASSERT_EQ(ptr, ref);\n\n  char* t_as_char;\n  t_as_char = ABSL_DIE_IF_NULL(reinterpret_cast<char*>(&t));\n  (void)t_as_char;\n\n  unsigned char* t_as_uchar;\n  t_as_uchar = ABSL_DIE_IF_NULL(reinterpret_cast<unsigned char*>(&t));\n  (void)t_as_uchar;\n\n  int* t_as_int;\n  t_as_int = ABSL_DIE_IF_NULL(reinterpret_cast<int*>(&t));\n  (void)t_as_int;\n\n  int64_t* t_as_int64_t;\n  t_as_int64_t = ABSL_DIE_IF_NULL(reinterpret_cast<int64_t*>(&t));\n  (void)t_as_int64_t;\n\n  std::unique_ptr<int64_t> sptr(new int64_t);\n  EXPECT_EQ(sptr.get(), ABSL_DIE_IF_NULL(sptr).get());\n  ABSL_DIE_IF_NULL(sptr).reset();\n\n  int64_t* int_ptr = new int64_t();\n  EXPECT_EQ(int_ptr, ABSL_DIE_IF_NULL(std::unique_ptr<int64_t>(int_ptr)).get());\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(DeathCheckAbslDieIfNull, Simple) {\n  void* ptr;\n  ASSERT_DEATH({ ptr = ABSL_DIE_IF_NULL(nullptr); }, \"\");\n  (void)ptr;\n\n  std::unique_ptr<int64_t> sptr;\n  ASSERT_DEATH(ptr = ABSL_DIE_IF_NULL(sptr).get(), \"\");\n}\n#endif\n\n// Ensures that ABSL_DIE_IF_NULL works with C++11's std::unique_ptr and\n// std::shared_ptr.\nTEST(AbslDieIfNull, DoesNotCompareSmartPointerToNULL) {\n  std::unique_ptr<int> up(new int);\n  EXPECT_EQ(&up, &ABSL_DIE_IF_NULL(up));\n  ABSL_DIE_IF_NULL(up).reset();\n\n  std::shared_ptr<int> sp(new int);\n  EXPECT_EQ(&sp, &ABSL_DIE_IF_NULL(sp));\n  ABSL_DIE_IF_NULL(sp).reset();\n}\n\n// Verifies that ABSL_DIE_IF_NULL returns an rvalue reference if its argument is\n// an rvalue reference.\nTEST(AbslDieIfNull, PreservesRValues) {\n  int64_t* ptr = new int64_t();\n  auto uptr = ABSL_DIE_IF_NULL(std::unique_ptr<int64_t>(ptr));\n  EXPECT_EQ(ptr, uptr.get());\n}\n\n// Verifies that ABSL_DIE_IF_NULL returns an lvalue if its argument is an\n// lvalue.\nTEST(AbslDieIfNull, PreservesLValues) {\n  int64_t array[2] = {0};\n  int64_t* a = array + 0;\n  int64_t* b = array + 1;\n  using std::swap;\n  swap(ABSL_DIE_IF_NULL(a), ABSL_DIE_IF_NULL(b));\n  EXPECT_EQ(array + 1, a);\n  EXPECT_EQ(array + 0, b);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/flags.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/flags.h\"\n\n#include <stddef.h>\n\n#include <algorithm>\n#include <cstdlib>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/marshalling.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/config.h\"\n#include \"absl/log/internal/vlog_config.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\n\nvoid SyncLoggingFlags() {\n  absl::SetFlag(&FLAGS_minloglevel, static_cast<int>(absl::MinLogLevel()));\n  absl::SetFlag(&FLAGS_log_prefix, absl::ShouldPrependLogPrefix());\n}\n\nbool RegisterSyncLoggingFlags() {\n  log_internal::SetLoggingGlobalsListener(&SyncLoggingFlags);\n  return true;\n}\n\nABSL_ATTRIBUTE_UNUSED const bool unused = RegisterSyncLoggingFlags();\n\ntemplate <typename T>\nT GetFromEnv(const char* varname, T dflt) {\n  const char* val = ::getenv(varname);\n  if (val != nullptr) {\n    std::string err;\n    ABSL_INTERNAL_CHECK(absl::ParseFlag(val, &dflt, &err), err.c_str());\n  }\n  return dflt;\n}\n\nconstexpr absl::LogSeverityAtLeast StderrThresholdDefault() {\n  return absl::LogSeverityAtLeast::kError;\n}\n\n}  // namespace\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nABSL_FLAG(int, stderrthreshold,\n          static_cast<int>(absl::log_internal::StderrThresholdDefault()),\n          \"Log messages at or above this threshold level are copied to stderr.\")\n    .OnUpdate([] {\n      absl::log_internal::RawSetStderrThreshold(\n          static_cast<absl::LogSeverityAtLeast>(\n              absl::GetFlag(FLAGS_stderrthreshold)));\n    });\n\nABSL_FLAG(int, minloglevel, static_cast<int>(absl::LogSeverityAtLeast::kInfo),\n          \"Messages logged at a lower level than this don't actually \"\n          \"get logged anywhere\")\n    .OnUpdate([] {\n      absl::log_internal::RawSetMinLogLevel(\n          static_cast<absl::LogSeverityAtLeast>(\n              absl::GetFlag(FLAGS_minloglevel)));\n    });\n\nABSL_FLAG(std::string, log_backtrace_at, \"\",\n          \"Emit a backtrace when logging at file:linenum.\")\n    .OnUpdate([] {\n      const std::string log_backtrace_at =\n          absl::GetFlag(FLAGS_log_backtrace_at);\n      if (log_backtrace_at.empty()) {\n        absl::ClearLogBacktraceLocation();\n        return;\n      }\n\n      const size_t last_colon = log_backtrace_at.rfind(':');\n      if (last_colon == log_backtrace_at.npos) {\n        absl::ClearLogBacktraceLocation();\n        return;\n      }\n\n      const absl::string_view file =\n          absl::string_view(log_backtrace_at).substr(0, last_colon);\n      int line;\n      if (!absl::SimpleAtoi(\n              absl::string_view(log_backtrace_at).substr(last_colon + 1),\n              &line)) {\n        absl::ClearLogBacktraceLocation();\n        return;\n      }\n      absl::SetLogBacktraceLocation(file, line);\n    });\n\nABSL_FLAG(bool, log_prefix, true,\n          \"Prepend the log prefix to the start of each log line\")\n    .OnUpdate([] {\n      absl::log_internal::RawEnableLogPrefix(absl::GetFlag(FLAGS_log_prefix));\n    });\n\nABSL_FLAG(int, v, 0,\n          \"Show all VLOG(m) messages for m <= this. Overridable by --vmodule.\")\n    .OnUpdate([] {\n      absl::log_internal::UpdateGlobalVLogLevel(absl::GetFlag(FLAGS_v));\n    });\n\nABSL_FLAG(\n    std::string, vmodule, \"\",\n    \"per-module log verbosity level.\"\n    \" Argument is a comma-separated list of <module name>=<log level>.\"\n    \" <module name> is a glob pattern, matched against the filename base\"\n    \" (that is, name ignoring .cc/.h./-inl.h).\"\n    \" A pattern without slashes matches just the file name portion, otherwise\"\n    \" the whole file path below the workspace root\"\n    \" (still without .cc/.h./-inl.h) is matched.\"\n    \" ? and * in the glob pattern match any single or sequence of characters\"\n    \" respectively including slashes.\"\n    \" <log level> overrides any value given by --v.\")\n    .OnUpdate([] {\n      absl::log_internal::UpdateVModule(absl::GetFlag(FLAGS_vmodule));\n    });\n"
  },
  {
    "path": "absl/log/flags.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/flags.h\n// -----------------------------------------------------------------------------\n//\n\n#ifndef ABSL_LOG_FLAGS_H_\n#define ABSL_LOG_FLAGS_H_\n\n// The Abseil Logging library supports the following command line flags to\n// configure logging behavior at runtime:\n//\n// --stderrthreshold=<value>\n// Log messages at or above this threshold level are copied to stderr.\n//\n// --minloglevel=<value>\n// Messages logged at a lower level than this are discarded and don't actually\n// get logged anywhere.\n//\n// --log_backtrace_at=<file:linenum>\n// Emit a backtrace (stack trace) when logging at file:linenum.\n//\n// To use these commandline flags, the //absl/log:flags library must be\n// explicitly linked, and absl::ParseCommandLine() must be called before the\n// call to absl::InitializeLog().\n//\n// To configure the Log library programmatically, use the interfaces defined in\n// absl/log/globals.h.\n\n#endif  // ABSL_LOG_FLAGS_H_\n"
  },
  {
    "path": "absl/log/flags_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/flags.h\"\n\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\nusing ::absl::log_internal::TextMessage;\n\nusing ::testing::HasSubstr;\nusing ::testing::Not;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\nconstexpr static absl::LogSeverityAtLeast DefaultStderrThreshold() {\n  return absl::LogSeverityAtLeast::kError;\n}\n\nclass LogFlagsTest : public ::testing::Test {\n protected:\n  absl::FlagSaver flag_saver_;\n};\n\n// This test is disabled because it adds order dependency to the test suite.\n// This order dependency is currently not fixable due to the way the\n// stderrthreshold global value is out of sync with the stderrthreshold flag.\nTEST_F(LogFlagsTest, DISABLED_StderrKnobsDefault) {\n  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());\n}\n\nTEST_F(LogFlagsTest, SetStderrThreshold) {\n  absl::SetFlag(&FLAGS_stderrthreshold,\n                static_cast<int>(absl::LogSeverityAtLeast::kInfo));\n\n  EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kInfo);\n\n  absl::SetFlag(&FLAGS_stderrthreshold,\n                static_cast<int>(absl::LogSeverityAtLeast::kError));\n\n  EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kError);\n}\n\nTEST_F(LogFlagsTest, SetMinLogLevel) {\n  absl::SetFlag(&FLAGS_minloglevel,\n                static_cast<int>(absl::LogSeverityAtLeast::kError));\n\n  EXPECT_EQ(absl::MinLogLevel(), absl::LogSeverityAtLeast::kError);\n\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(\n      absl::LogSeverityAtLeast::kWarning);\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_minloglevel),\n            static_cast<int>(absl::LogSeverityAtLeast::kWarning));\n}\n\nTEST_F(LogFlagsTest, PrependLogPrefix) {\n  absl::SetFlag(&FLAGS_log_prefix, false);\n\n  EXPECT_EQ(absl::ShouldPrependLogPrefix(), false);\n\n  absl::EnableLogPrefix(true);\n\n  EXPECT_EQ(absl::GetFlag(FLAGS_log_prefix), true);\n}\n\nTEST_F(LogFlagsTest, EmptyBacktraceAtFlag) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at, \"\");\n  LOG(INFO) << \"hello world\";\n}\n\nTEST_F(LogFlagsTest, BacktraceAtNonsense) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at, \"gibberish\");\n  LOG(INFO) << \"hello world\";\n}\n\nTEST_F(LogFlagsTest, BacktraceAtWrongFile) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { LOG(INFO) << \"hello world\"; };\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at,\n                absl::StrCat(\"some_other_file.cc:\", log_line));\n  do_log();\n}\n\nTEST_F(LogFlagsTest, BacktraceAtWrongLine) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { LOG(INFO) << \"hello world\"; };\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at,\n                absl::StrCat(\"flags_test.cc:\", log_line + 1));\n  do_log();\n}\n\nTEST_F(LogFlagsTest, BacktraceAtWholeFilename) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { LOG(INFO) << \"hello world\"; };\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at, absl::StrCat(__FILE__, \":\", log_line));\n  do_log();\n}\n\nTEST_F(LogFlagsTest, BacktraceAtNonmatchingSuffix) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { LOG(INFO) << \"hello world\"; };\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at,\n                absl::StrCat(\"flags_test.cc:\", log_line, \"gibberish\"));\n  do_log();\n}\n\nTEST_F(LogFlagsTest, LogsBacktrace) {\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfo);\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { LOG(INFO) << \"hello world\"; };\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  testing::InSequence seq;\n  EXPECT_CALL(test_sink, Send(TextMessage(HasSubstr(\"(stacktrace:\"))));\n  EXPECT_CALL(test_sink, Send(TextMessage(Not(HasSubstr(\"(stacktrace:\")))));\n\n  test_sink.StartCapturingLogs();\n  absl::SetFlag(&FLAGS_log_backtrace_at,\n                absl::StrCat(\"flags_test.cc:\", log_line));\n  do_log();\n  absl::SetFlag(&FLAGS_log_backtrace_at, \"\");\n  do_log();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/globals.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/globals.h\"\n\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\n// These atomics represent logging library configuration.\n// Integer types are used instead of absl::LogSeverity to ensure that a\n// lock-free std::atomic is used when possible.\nABSL_CONST_INIT std::atomic<int> min_log_level{\n    static_cast<int>(absl::LogSeverityAtLeast::kInfo)};\nABSL_CONST_INIT std::atomic<int> stderrthreshold{\n    static_cast<int>(absl::LogSeverityAtLeast::kError)};\n// We evaluate this value as a hash comparison to avoid having to\n// hold a mutex or make a copy (to access the value of a string-typed flag) in\n// very hot codepath.\nABSL_CONST_INIT std::atomic<size_t> log_backtrace_at_hash{0};\nABSL_CONST_INIT std::atomic<bool> prepend_log_prefix{true};\n\nconstexpr char kDefaultAndroidTag[] = \"native\";\nABSL_CONST_INIT std::atomic<const char*> android_log_tag{kDefaultAndroidTag};\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\nabsl::base_internal::AtomicHook<log_internal::LoggingGlobalsListener>\n    logging_globals_listener;\n\nsize_t HashSiteForLogBacktraceAt(absl::string_view file, int line) {\n  return absl::HashOf(file, line);\n}\n\nvoid TriggerLoggingGlobalsListener() {\n  auto* listener = logging_globals_listener.Load();\n  if (listener != nullptr) listener();\n}\n\n}  // namespace\n\nnamespace log_internal {\n\nvoid RawSetMinLogLevel(absl::LogSeverityAtLeast severity) {\n  min_log_level.store(static_cast<int>(severity), std::memory_order_release);\n}\n\nvoid RawSetStderrThreshold(absl::LogSeverityAtLeast severity) {\n  stderrthreshold.store(static_cast<int>(severity), std::memory_order_release);\n}\n\nvoid RawEnableLogPrefix(bool on_off) {\n  prepend_log_prefix.store(on_off, std::memory_order_release);\n}\n\nvoid SetLoggingGlobalsListener(LoggingGlobalsListener l) {\n  logging_globals_listener.Store(l);\n}\n\n}  // namespace log_internal\n\nabsl::LogSeverityAtLeast MinLogLevel() {\n  return static_cast<absl::LogSeverityAtLeast>(\n      min_log_level.load(std::memory_order_acquire));\n}\n\nvoid SetMinLogLevel(absl::LogSeverityAtLeast severity) {\n  log_internal::RawSetMinLogLevel(severity);\n  TriggerLoggingGlobalsListener();\n}\n\nnamespace log_internal {\n\nScopedMinLogLevel::ScopedMinLogLevel(absl::LogSeverityAtLeast severity)\n    : saved_severity_(absl::MinLogLevel()) {\n  absl::SetMinLogLevel(severity);\n}\nScopedMinLogLevel::~ScopedMinLogLevel() {\n  absl::SetMinLogLevel(saved_severity_);\n}\n\n}  // namespace log_internal\n\nabsl::LogSeverityAtLeast StderrThreshold() {\n  return static_cast<absl::LogSeverityAtLeast>(\n      stderrthreshold.load(std::memory_order_acquire));\n}\n\nvoid SetStderrThreshold(absl::LogSeverityAtLeast severity) {\n  log_internal::RawSetStderrThreshold(severity);\n  TriggerLoggingGlobalsListener();\n}\n\nScopedStderrThreshold::ScopedStderrThreshold(absl::LogSeverityAtLeast severity)\n    : saved_severity_(absl::StderrThreshold()) {\n  absl::SetStderrThreshold(severity);\n}\n\nScopedStderrThreshold::~ScopedStderrThreshold() {\n  absl::SetStderrThreshold(saved_severity_);\n}\n\nnamespace log_internal {\n\nconst char* GetAndroidNativeTag() {\n  return android_log_tag.load(std::memory_order_acquire);\n}\n\n}  // namespace log_internal\n\nvoid SetAndroidNativeTag(const char* tag) {\n  ABSL_CONST_INIT static std::atomic<const std::string*> user_log_tag(nullptr);\n  ABSL_INTERNAL_CHECK(tag, \"tag must be non-null.\");\n\n  const std::string* tag_str = new std::string(tag);\n  ABSL_INTERNAL_CHECK(\n      android_log_tag.exchange(tag_str->c_str(), std::memory_order_acq_rel) ==\n          kDefaultAndroidTag,\n      \"SetAndroidNativeTag() must only be called once per process!\");\n  user_log_tag.store(tag_str, std::memory_order_relaxed);\n}\n\nnamespace log_internal {\n\nbool ShouldLogBacktraceAt(absl::string_view file, int line) {\n  const size_t flag_hash =\n      log_backtrace_at_hash.load(std::memory_order_relaxed);\n\n  return flag_hash != 0 && flag_hash == HashSiteForLogBacktraceAt(file, line);\n}\n\n}  // namespace log_internal\n\nvoid SetLogBacktraceLocation(absl::string_view file, int line) {\n  log_backtrace_at_hash.store(HashSiteForLogBacktraceAt(file, line),\n                              std::memory_order_relaxed);\n}\n\nvoid ClearLogBacktraceLocation() {\n  log_backtrace_at_hash.store(0, std::memory_order_relaxed);\n}\n\nbool ShouldPrependLogPrefix() {\n  return prepend_log_prefix.load(std::memory_order_acquire);\n}\n\nvoid EnableLogPrefix(bool on_off) {\n  log_internal::RawEnableLogPrefix(on_off);\n  TriggerLoggingGlobalsListener();\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/globals.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/globals.h\n// -----------------------------------------------------------------------------\n//\n// This header declares global logging library configuration knobs.\n\n#ifndef ABSL_LOG_GLOBALS_H_\n#define ABSL_LOG_GLOBALS_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/vlog_config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n//------------------------------------------------------------------------------\n//  Minimum Log Level\n//------------------------------------------------------------------------------\n//\n// Messages logged at or above this severity are directed to all registered log\n// sinks or skipped otherwise. This parameter can also be modified using\n// command line flag --minloglevel.\n// See absl/base/log_severity.h for descriptions of severity levels.\n\n// MinLogLevel()\n//\n// Returns the value of the Minimum Log Level parameter.\n// This function is async-signal-safe.\n[[nodiscard]] absl::LogSeverityAtLeast MinLogLevel();\n\n// SetMinLogLevel()\n//\n// Updates the value of Minimum Log Level parameter.\n// This function is async-signal-safe.\nvoid SetMinLogLevel(absl::LogSeverityAtLeast severity);\n\nnamespace log_internal {\n\n// ScopedMinLogLevel\n//\n// RAII type used to temporarily update the Min Log Level parameter.\nclass ScopedMinLogLevel final {\n public:\n  explicit ScopedMinLogLevel(absl::LogSeverityAtLeast severity);\n  ScopedMinLogLevel(const ScopedMinLogLevel&) = delete;\n  ScopedMinLogLevel& operator=(const ScopedMinLogLevel&) = delete;\n  ~ScopedMinLogLevel();\n\n private:\n  absl::LogSeverityAtLeast saved_severity_;\n};\n\n}  // namespace log_internal\n\n//------------------------------------------------------------------------------\n// Stderr Threshold\n//------------------------------------------------------------------------------\n//\n// Messages logged at or above this level are directed to stderr in\n// addition to other registered log sinks. This parameter can also be modified\n// using command line flag --stderrthreshold.\n// See absl/base/log_severity.h for descriptions of severity levels.\n\n// StderrThreshold()\n//\n// Returns the value of the Stderr Threshold parameter.\n// This function is async-signal-safe.\n[[nodiscard]] absl::LogSeverityAtLeast StderrThreshold();\n\n// SetStderrThreshold()\n//\n// Updates the Stderr Threshold parameter.\n// This function is async-signal-safe.\nvoid SetStderrThreshold(absl::LogSeverityAtLeast severity);\ninline void SetStderrThreshold(absl::LogSeverity severity) {\n  absl::SetStderrThreshold(static_cast<absl::LogSeverityAtLeast>(severity));\n}\n\n// ScopedStderrThreshold\n//\n// RAII type used to temporarily update the Stderr Threshold parameter.\nclass ScopedStderrThreshold final {\n public:\n  explicit ScopedStderrThreshold(absl::LogSeverityAtLeast severity);\n  ScopedStderrThreshold(const ScopedStderrThreshold&) = delete;\n  ScopedStderrThreshold& operator=(const ScopedStderrThreshold&) = delete;\n  ~ScopedStderrThreshold();\n\n private:\n  absl::LogSeverityAtLeast saved_severity_;\n};\n\n//------------------------------------------------------------------------------\n// Log Backtrace At\n//------------------------------------------------------------------------------\n//\n// Users can request an existing `LOG` statement, specified by file and line\n// number, to also include a backtrace when logged.\n\n// ShouldLogBacktraceAt()\n//\n// Returns true if we should log a backtrace at the specified location.\nnamespace log_internal {\n[[nodiscard]] bool ShouldLogBacktraceAt(absl::string_view file, int line);\n}  // namespace log_internal\n\n// SetLogBacktraceLocation()\n//\n// Sets the location the backtrace should be logged at.  If the specified\n// location isn't a `LOG` statement, the effect will be the same as\n// `ClearLogBacktraceLocation` (but less efficient).\nvoid SetLogBacktraceLocation(absl::string_view file, int line);\n\n// ClearLogBacktraceLocation()\n//\n// Clears the set location so that backtraces will no longer be logged at it.\nvoid ClearLogBacktraceLocation();\n\n//------------------------------------------------------------------------------\n// Prepend Log Prefix\n//------------------------------------------------------------------------------\n//\n// This option tells the logging library that every logged message\n// should include the prefix (severity, date, time, PID, etc.)\n//\n// ShouldPrependLogPrefix()\n//\n// Returns the value of the Prepend Log Prefix option.\n// This function is async-signal-safe.\n[[nodiscard]] bool ShouldPrependLogPrefix();\n\n// EnableLogPrefix()\n//\n// Updates the value of the Prepend Log Prefix option.\n// This function is async-signal-safe.\nvoid EnableLogPrefix(bool on_off);\n\n//------------------------------------------------------------------------------\n// `VLOG` Configuration\n//------------------------------------------------------------------------------\n//\n// These methods set the `(ABSL_)VLOG(_IS_ON)` threshold.  They allow\n// programmatic control of the thresholds set by the --v and --vmodule flags.\n//\n// Only `VLOG`s with a severity level LESS THAN OR EQUAL TO the threshold will\n// be evaluated.\n//\n// For example, if the threshold is 2, then:\n//\n//   VLOG(2) << \"This message will be logged.\";\n//   VLOG(3) << \"This message will NOT be logged.\";\n//\n// The default threshold is 0. Since `VLOG` levels must not be negative, a\n// negative threshold value will turn off all VLOGs.\n\n// SetGlobalVLogLevel()\n//\n// Sets the global `VLOG` level to threshold. Returns the previous global\n// threshold.\ninline int SetGlobalVLogLevel(int threshold) {\n  return absl::log_internal::UpdateGlobalVLogLevel(threshold);\n}\n\n// SetVLogLevel()\n//\n// Sets the `VLOG` threshold for all files that match `module_pattern`,\n// overwriting any prior value. Files that don't match aren't affected.\n// Returns the threshold that previously applied to `module_pattern`.\ninline int SetVLogLevel(absl::string_view module_pattern, int threshold) {\n  return absl::log_internal::PrependVModule(module_pattern, threshold);\n}\n\n//------------------------------------------------------------------------------\n// Configure Android Native Log Tag\n//------------------------------------------------------------------------------\n//\n// The logging library forwards to the Android system log API when built for\n// Android.  That API takes a string \"tag\" value in addition to a message and\n// severity level.  The tag is used to identify the source of messages and to\n// filter them.  This library uses the tag \"native\" by default.\n\n// SetAndroidNativeTag()\n//\n// Stores a copy of the string pointed to by `tag` and uses it as the Android\n// logging tag thereafter. `tag` must not be null.\n// This function must not be called more than once!\nvoid SetAndroidNativeTag(const char* tag);\n\nnamespace log_internal {\n// GetAndroidNativeTag()\n//\n// Returns the configured Android logging tag.\nconst char* GetAndroidNativeTag();\n}  // namespace log_internal\n\nnamespace log_internal {\n\nusing LoggingGlobalsListener = void (*)();\nvoid SetLoggingGlobalsListener(LoggingGlobalsListener l);\n\n// Internal implementation for the setter routines. These are used\n// to break circular dependencies between flags and globals. Each \"Raw\"\n// routine corresponds to the non-\"Raw\" counterpart and used to set the\n// configuration parameter directly without calling back to the listener.\nvoid RawSetMinLogLevel(absl::LogSeverityAtLeast severity);\nvoid RawSetStderrThreshold(absl::LogSeverityAtLeast severity);\nvoid RawEnableLogPrefix(bool on_off);\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_GLOBALS_H_\n"
  },
  {
    "path": "absl/log/globals_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/globals.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/globals.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n\nnamespace {\nusing ::testing::_;\nusing ::testing::StrEq;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\nconstexpr static absl::LogSeverityAtLeast DefaultMinLogLevel() {\n  return absl::LogSeverityAtLeast::kInfo;\n}\nconstexpr static absl::LogSeverityAtLeast DefaultStderrThreshold() {\n  return absl::LogSeverityAtLeast::kError;\n}\n\nTEST(TestGlobals, MinLogLevel) {\n  EXPECT_EQ(absl::MinLogLevel(), DefaultMinLogLevel());\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kError);\n  EXPECT_EQ(absl::MinLogLevel(), absl::LogSeverityAtLeast::kError);\n  absl::SetMinLogLevel(DefaultMinLogLevel());\n}\n\nTEST(TestGlobals, ScopedMinLogLevel) {\n  EXPECT_EQ(absl::MinLogLevel(), DefaultMinLogLevel());\n  {\n    absl::log_internal::ScopedMinLogLevel scoped_stderr_threshold(\n        absl::LogSeverityAtLeast::kError);\n    EXPECT_EQ(absl::MinLogLevel(), absl::LogSeverityAtLeast::kError);\n  }\n  EXPECT_EQ(absl::MinLogLevel(), DefaultMinLogLevel());\n}\n\nTEST(TestGlobals, StderrThreshold) {\n  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());\n  absl::SetStderrThreshold(absl::LogSeverityAtLeast::kError);\n  EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kError);\n  absl::SetStderrThreshold(DefaultStderrThreshold());\n}\n\nTEST(TestGlobals, ScopedStderrThreshold) {\n  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());\n  {\n    absl::ScopedStderrThreshold scoped_stderr_threshold(\n        absl::LogSeverityAtLeast::kError);\n    EXPECT_EQ(absl::StderrThreshold(), absl::LogSeverityAtLeast::kError);\n  }\n  EXPECT_EQ(absl::StderrThreshold(), DefaultStderrThreshold());\n}\n\nTEST(TestGlobals, LogBacktraceAt) {\n  EXPECT_FALSE(absl::log_internal::ShouldLogBacktraceAt(\"some_file.cc\", 111));\n  absl::SetLogBacktraceLocation(\"some_file.cc\", 111);\n  EXPECT_TRUE(absl::log_internal::ShouldLogBacktraceAt(\"some_file.cc\", 111));\n  EXPECT_FALSE(\n      absl::log_internal::ShouldLogBacktraceAt(\"another_file.cc\", 222));\n}\n\nTEST(TestGlobals, LogPrefix) {\n  EXPECT_TRUE(absl::ShouldPrependLogPrefix());\n  absl::EnableLogPrefix(false);\n  EXPECT_FALSE(absl::ShouldPrependLogPrefix());\n  absl::EnableLogPrefix(true);\n  EXPECT_TRUE(absl::ShouldPrependLogPrefix());\n}\n\nTEST(TestGlobals, SetGlobalVLogLevel) {\n  EXPECT_EQ(absl::SetGlobalVLogLevel(42), 0);\n  EXPECT_EQ(absl::SetGlobalVLogLevel(1337), 42);\n  // Restore the value since it affects the default unset module value for\n  // `SetVLogLevel()`.\n  EXPECT_EQ(absl::SetGlobalVLogLevel(0), 1337);\n}\n\nTEST(TestGlobals, SetVLogLevel) {\n  EXPECT_EQ(absl::SetVLogLevel(\"setvloglevel\", 42), 0);\n  EXPECT_EQ(absl::SetVLogLevel(\"setvloglevel\", 1337), 42);\n  EXPECT_EQ(absl::SetVLogLevel(\"othersetvloglevel\", 50), 0);\n\n  EXPECT_EQ(absl::SetVLogLevel(\"*pattern*\", 1), 0);\n  EXPECT_EQ(absl::SetVLogLevel(\"*less_generic_pattern*\", 2), 1);\n  // \"pattern_match\" matches the pattern \"*pattern*\". Therefore, the previous\n  // level must be 1.\n  EXPECT_EQ(absl::SetVLogLevel(\"pattern_match\", 3), 1);\n  // \"less_generic_pattern_match\" matches the pattern \"*pattern*\". Therefore,\n  // the previous level must be 2.\n  EXPECT_EQ(absl::SetVLogLevel(\"less_generic_pattern_match\", 4), 2);\n}\n\nTEST(TestGlobals, AndroidLogTag) {\n  // Verify invalid tags result in a check failure.\n  EXPECT_DEATH_IF_SUPPORTED(absl::SetAndroidNativeTag(nullptr), \".*\");\n\n  // Verify valid tags applied.\n  EXPECT_THAT(absl::log_internal::GetAndroidNativeTag(), StrEq(\"native\"));\n  absl::SetAndroidNativeTag(\"test_tag\");\n  EXPECT_THAT(absl::log_internal::GetAndroidNativeTag(), StrEq(\"test_tag\"));\n\n  // Verify that additional calls (more than 1) result in a check failure.\n  EXPECT_DEATH_IF_SUPPORTED(absl::SetAndroidNativeTag(\"test_tag_fail\"), \".*\");\n}\n\nTEST(TestExitOnDFatal, OffTest) {\n  // Turn off...\n  absl::log_internal::SetExitOnDFatal(false);\n  EXPECT_FALSE(absl::log_internal::ExitOnDFatal());\n\n  // We don't die.\n  {\n    absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n    // LOG(DFATAL) has severity FATAL if debugging, but is\n    // downgraded to ERROR if not debugging.\n    EXPECT_CALL(log, Log(absl::kLogDebugFatal, _, \"This should not be fatal\"));\n\n    log.StartCapturingLogs();\n    LOG(DFATAL) << \"This should not be fatal\";\n  }\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(TestDeathWhileExitOnDFatal, OnTest) {\n  absl::log_internal::SetExitOnDFatal(true);\n  EXPECT_TRUE(absl::log_internal::ExitOnDFatal());\n\n  // Death comes on little cats' feet.\n  EXPECT_DEBUG_DEATH({ LOG(DFATAL) << \"This should be fatal in debug mode\"; },\n                     \"This should be fatal in debug mode\");\n}\n#endif\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/initialize.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/initialize.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/globals.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\nvoid InitializeLogImpl(absl::TimeZone time_zone) {\n  // This comes first since it is used by RAW_LOG.\n  absl::log_internal::SetTimeZone(time_zone);\n\n  // Note that initialization is complete, so logs can now be sent to their\n  // proper destinations rather than stderr.\n  log_internal::SetInitialized();\n}\n}  // namespace\n\nvoid InitializeLog() { InitializeLogImpl(absl::LocalTimeZone()); }\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/initialize.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/initialize.h\n// -----------------------------------------------------------------------------\n//\n// This header declares the Abseil Log initialization routine InitializeLog().\n\n#ifndef ABSL_LOG_INITIALIZE_H_\n#define ABSL_LOG_INITIALIZE_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// InitializeLog()\n//\n// Initializes the Abseil logging library.\n//\n// Before this function is called, all log messages are directed only to stderr.\n// After initialization is finished, log messages are directed to all registered\n// `LogSink`s.\n//\n// It is an error to call this function twice.\n//\n// There is no corresponding function to shut down the logging library.\nvoid InitializeLog();\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INITIALIZE_H_\n"
  },
  {
    "path": "absl/log/internal/BUILD.bazel",
    "content": "#\n# Copyright 2022 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\n        \":internal_users\",\n    ],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\npackage_group(\n    name = \"internal_users\",\n    includes = [\n        \"//absl:friends\",\n    ],\n    packages = [\n        \"//absl/log\",\n    ],\n)\n\npackage_group(\n    name = \"structured_proto_users\",\n    packages = [\n        \"//absl/log/...\",\n    ],\n)\n\ncc_library(\n    name = \"check_impl\",\n    hdrs = [\"check_impl.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":check_op\",\n        \":conditions\",\n        \":strip\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"check_op\",\n    srcs = [\"check_op.cc\"],\n    hdrs = [\"check_op.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//absl/log:__pkg__\"],\n    deps = [\n        \":nullguard\",\n        \":nullstream\",\n        \":strip\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/debugging:leak_check\",\n        \"//absl/strings\",\n        \"//absl/strings:has_ostream_operator\",\n    ],\n)\n\ncc_library(\n    name = \"conditions\",\n    srcs = [\"conditions.cc\"],\n    hdrs = [\"conditions.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":voidify\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"config\",\n    hdrs = [\"config.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/log:__pkg__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"flags\",\n    hdrs = [\"flags.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/flags:flag\",\n    ],\n)\n\ncc_library(\n    name = \"format\",\n    srcs = [\"log_format.cc\"],\n    hdrs = [\"log_format.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":append_truncated\",\n        \":config\",\n        \":globals\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"//absl/time\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"globals\",\n    srcs = [\"globals.cc\"],\n    hdrs = [\"globals.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/log:__pkg__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"//absl/time\",\n    ],\n)\n\ncc_library(\n    name = \"log_impl\",\n    hdrs = [\"log_impl.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":conditions\",\n        \":log_message\",\n        \":strip\",\n        \"//absl/log:absl_vlog_is_on\",\n    ],\n)\n\ncc_library(\n    name = \"log_message\",\n    srcs = [\"log_message.cc\"],\n    hdrs = [\"log_message.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/log:__pkg__\",\n    ],\n    deps = [\n        \":append_truncated\",\n        \":format\",\n        \":globals\",\n        \":log_sink_set\",\n        \":nullguard\",\n        \":proto\",\n        \":structured_proto\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:errno_saver\",\n        \"//absl/base:log_severity\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/base:strerror\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/debugging:examine_stack\",\n        \"//absl/log:globals\",\n        \"//absl/log:log_entry\",\n        \"//absl/log:log_sink\",\n        \"//absl/log:log_sink_registry\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"//absl/strings:internal\",\n        \"//absl/time\",\n        \"//absl/types:source_location\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"append_truncated\",\n    hdrs = [\"append_truncated.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/strings\",\n        \"//absl/strings:internal\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"log_sink_set\",\n    srcs = [\"log_sink_set.cc\"],\n    hdrs = [\"log_sink_set.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS + select({\n        \"//conditions:default\": [],\n        \"@platforms//os:android\": [\"-llog\"],\n    }),\n    deps = [\n        \":config\",\n        \":globals\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/cleanup\",\n        \"//absl/log:globals\",\n        \"//absl/log:log_entry\",\n        \"//absl/log:log_sink\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"nullguard\",\n    srcs = [\"nullguard.cc\"],\n    hdrs = [\"nullguard.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"nullstream\",\n    hdrs = [\"nullstream.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"strip\",\n    hdrs = [\"strip.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":log_message\",\n        \":nullstream\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n    ],\n)\n\ncc_library(\n    name = \"structured\",\n    hdrs = [\"structured.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \":internal_users\",\n        \":structured_proto_users\",\n    ],\n    deps = [\n        \":log_message\",\n        \":structured_proto\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/functional:any_invocable\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"structured_proto\",\n    srcs = [\"structured_proto.cc\"],\n    hdrs = [\"structured_proto.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \":structured_proto_users\",\n    ],\n    deps = [\n        \":proto\",\n        \"//absl/base:config\",\n        \"//absl/strings\",\n        \"//absl/types:span\",\n        \"//absl/types:variant\",\n    ],\n)\n\ncc_test(\n    name = \"structured_proto_test\",\n    srcs = [\"structured_proto_test.cc\"],\n    deps = [\n        \":structured_proto\",\n        \"//absl/base:config\",\n        \"//absl/strings:string_view\",\n        \"//absl/types:span\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"test_actions\",\n    testonly = True,\n    srcs = [\"test_actions.cc\"],\n    hdrs = [\"test_actions.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log:log_entry\",\n        \"//absl/strings\",\n        \"//absl/time\",\n    ] + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"//conditions:default\": [\n        ],\n    }),\n)\n\ncc_library(\n    name = \"test_helpers\",\n    testonly = True,\n    srcs = [\"test_helpers.cc\"],\n    hdrs = [\"test_helpers.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \":internal_users\",\n        \":structured_proto_users\",\n    ],\n    deps = [\n        \":globals\",\n        \"//absl/base:config\",\n        \"//absl/base:log_severity\",\n        \"//absl/log:globals\",\n        \"//absl/log:initialize\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"test_matchers\",\n    testonly = True,\n    srcs = [\"test_matchers.cc\"],\n    hdrs = [\"test_matchers.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \":internal_users\",\n        \":structured_proto_users\",\n    ],\n    deps = [\n        \":test_helpers\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log:log_entry\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n    ] + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"//conditions:default\": [\n        ],\n    }),\n)\n\ncc_library(\n    name = \"voidify\",\n    hdrs = [\"voidify.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_library(\n    name = \"proto\",\n    srcs = [\"proto.cc\"],\n    hdrs = [\"proto.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/strings\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"fnmatch\",\n    srcs = [\"fnmatch.cc\"],\n    hdrs = [\"fnmatch.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"vlog_config\",\n    srcs = [\"vlog_config.cc\"],\n    hdrs = [\"vlog_config.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//absl/log:__subpackages__\",\n    ],\n    deps = [\n        \":fnmatch\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:nullability\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_binary(\n    name = \"vlog_config_benchmark\",\n    testonly = True,\n    srcs = [\"vlog_config_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"benchmark\",\n    ],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":vlog_config\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:layout\",\n        \"//absl/memory\",\n        \"//absl/random:distributions\",\n        \"//absl/strings\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\n# Test targets\ncc_test(\n    name = \"stderr_log_sink_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"stderr_log_sink_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test:os:android\",\n        \"no_test:os:ios\",\n        \"no_test_android\",\n        \"no_test_darwin_arm64\",\n        \"no_test_darwin_x86_64\",\n        \"no_test_fuchsia_x64\",\n        \"no_test_ios\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":test_helpers\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:log_severity\",\n        \"//absl/log\",\n        \"//absl/log:globals\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"fnmatch_test\",\n    srcs = [\"fnmatch_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fnmatch\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"fnmatch_benchmark\",\n    srcs = [\"fnmatch_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":fnmatch\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"container\",\n    hdrs = [\"container.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/meta:requires\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_test(\n    name = \"container_test\",\n    srcs = [\"container_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":container\",\n        \"//absl/base:config\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/log/internal/append_truncated.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_\n#define ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_\n\n#include <cstddef>\n#include <cstring>\n#include <string_view>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/utf8.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n// Copies into `dst` as many bytes of `src` as will fit, then truncates the\n// copied bytes from the front of `dst` and returns the number of bytes written.\ninline size_t AppendTruncated(absl::string_view src, absl::Span<char> &dst) {\n  if (src.size() > dst.size()) src = src.substr(0, dst.size());\n  memcpy(dst.data(), src.data(), src.size());\n  dst.remove_prefix(src.size());\n  return src.size();\n}\n// Likewise, but it also takes a wide character string and transforms it into a\n// UTF-8 encoded byte string regardless of the current locale.\n// - On platforms where `wchar_t` is 2 bytes (e.g., Windows), the input is\n//   treated as UTF-16.\n// - On platforms where `wchar_t` is 4 bytes (e.g., Linux, macOS), the input\n//   is treated as UTF-32.\ninline size_t AppendTruncated(std::wstring_view src, absl::Span<char> &dst) {\n  absl::strings_internal::ShiftState state;\n  size_t total_bytes_written = 0;\n  for (const wchar_t wc : src) {\n    // If the destination buffer might not be large enough to write the next\n    // character, stop.\n    if (dst.size() < absl::strings_internal::kMaxEncodedUTF8Size) break;\n    size_t bytes_written =\n        absl::strings_internal::WideToUtf8(wc, dst.data(), state);\n    if (bytes_written == static_cast<size_t>(-1)) {\n      // Invalid character. Encode REPLACEMENT CHARACTER (U+FFFD) instead.\n      constexpr wchar_t kReplacementCharacter = L'\\uFFFD';\n      bytes_written = absl::strings_internal::WideToUtf8(kReplacementCharacter,\n                                                         dst.data(), state);\n    }\n    dst.remove_prefix(bytes_written);\n    total_bytes_written += bytes_written;\n  }\n  return total_bytes_written;\n}\n// Likewise, but `n` copies of `c`.\ninline size_t AppendTruncated(char c, size_t n, absl::Span<char> &dst) {\n  if (n > dst.size()) n = dst.size();\n  memset(dst.data(), c, n);\n  dst.remove_prefix(n);\n  return n;\n}\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_\n"
  },
  {
    "path": "absl/log/internal/check_impl.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_LOG_INTERNAL_CHECK_IMPL_H_\n#define ABSL_LOG_INTERNAL_CHECK_IMPL_H_\n\n#include \"absl/base/optimization.h\"\n#include \"absl/log/internal/check_op.h\"\n#include \"absl/log/internal/conditions.h\"\n#include \"absl/log/internal/strip.h\"\n\n// CHECK\n#define ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text)       \\\n  ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS,                        \\\n                                    ABSL_PREDICT_FALSE(!(condition))) \\\n  ABSL_LOG_INTERNAL_CHECK(condition_text).InternalStream()\n\n#define ABSL_LOG_INTERNAL_QCHECK_IMPL(condition, condition_text)       \\\n  ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS,                        \\\n                                     ABSL_PREDICT_FALSE(!(condition))) \\\n  ABSL_LOG_INTERNAL_QCHECK(condition_text).InternalStream()\n\n#define ABSL_LOG_INTERNAL_PCHECK_IMPL(condition, condition_text) \\\n  ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text).WithPerror()\n\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DCHECK_IMPL(condition, condition_text) \\\n  ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text)\n#else\n#define ABSL_LOG_INTERNAL_DCHECK_IMPL(condition, condition_text) \\\n  ABSL_LOG_INTERNAL_CHECK_IMPL(true || (condition), \"true\")\n#endif\n\n// CHECK_EQ\n#define ABSL_LOG_INTERNAL_CHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OP(Check_EQ, ==, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_CHECK_NE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OP(Check_NE, !=, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_CHECK_LE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OP(Check_LE, <=, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_CHECK_LT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OP(Check_LT, <, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_CHECK_GE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OP(Check_GE, >=, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_CHECK_GT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OP(Check_GT, >, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OP(Check_EQ, ==, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OP(Check_NE, !=, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OP(Check_LE, <=, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OP(Check_LT, <, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OP(Check_GE, >=, val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OP(Check_GT, >, val1, val1_text, val2, val2_text)\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_EQ_IMPL(val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_NE_IMPL(val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_LE_IMPL(val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_LT_IMPL(val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_GE_IMPL(val1, val1_text, val2, val2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_GT_IMPL(val1, val1_text, val2, val2_text)\n#else  // ndef NDEBUG\n#define ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)\n#define ABSL_LOG_INTERNAL_DCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)\n#define ABSL_LOG_INTERNAL_DCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)\n#define ABSL_LOG_INTERNAL_DCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)\n#define ABSL_LOG_INTERNAL_DCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)\n#define ABSL_LOG_INTERNAL_DCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)\n#endif  // def NDEBUG\n\n// CHECK_OK\n#define ABSL_LOG_INTERNAL_CHECK_OK_IMPL(status, status_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OK(status, status_text)\n#define ABSL_LOG_INTERNAL_QCHECK_OK_IMPL(status, status_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_OK(status, status_text)\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DCHECK_OK_IMPL(status, status_text) \\\n  ABSL_LOG_INTERNAL_CHECK_OK(status, status_text)\n#else\n#define ABSL_LOG_INTERNAL_DCHECK_OK_IMPL(status, status_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(status, nullptr)\n#endif\n\n// CHECK_STREQ\n#define ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, ==, true, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, !=, false, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, ==, true, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, !=, false, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, ==, true, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, !=, false, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, ==, true, s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, !=, false, s1, s1_text, s2,  \\\n                                 s2_text)\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL(s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL(s1, s1_text, s2, s2_text)\n#define ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text)\n#else  // ndef NDEBUG\n#define ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)\n#define ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)\n#define ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)\n#define ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \\\n  ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)\n#endif  // def NDEBUG\n\n#endif  // ABSL_LOG_INTERNAL_CHECK_IMPL_H_\n"
  },
  {
    "path": "absl/log/internal/check_op.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/check_op.h\"\n\n#include <cstring>\n#include <ostream>\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/debugging/leak_check.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef _MSC_VER\n#define strcasecmp _stricmp\n#else\n#include <strings.h>  // for strcasecmp, but msvc does not have this header\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \\\n  template const char* absl_nonnull MakeCheckOpString(   \\\n      x, x, const char* absl_nonnull)\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(float);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(double);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(char);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(unsigned char);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const std::string&);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const absl::string_view&);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const char*);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const signed char*);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*);\n#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING\n\nCheckOpMessageBuilder::CheckOpMessageBuilder(\n    const char* absl_nonnull exprtext) {\n  stream_ << exprtext << \" (\";\n}\n\nstd::ostream& CheckOpMessageBuilder::ForVar2() {\n  stream_ << \" vs. \";\n  return stream_;\n}\n\nconst char* absl_nonnull CheckOpMessageBuilder::NewString() {\n  stream_ << \")\";\n  // There's no need to free this string since the process is crashing.\n  return absl::IgnoreLeak(new std::string(std::move(stream_).str()))->c_str();\n}\n\nvoid MakeCheckOpValueString(std::ostream& os, const char v) {\n  if (v >= 32 && v <= 126) {\n    os << \"'\" << v << \"'\";\n  } else {\n    os << \"char value \" << int{v};\n  }\n}\n\nvoid MakeCheckOpValueString(std::ostream& os, const signed char v) {\n  if (v >= 32 && v <= 126) {\n    os << \"'\" << v << \"'\";\n  } else {\n    os << \"signed char value \" << int{v};\n  }\n}\n\nvoid MakeCheckOpValueString(std::ostream& os, const unsigned char v) {\n  if (v >= 32 && v <= 126) {\n    os << \"'\" << v << \"'\";\n  } else {\n    os << \"unsigned char value \" << int{v};\n  }\n}\n\nvoid MakeCheckOpValueString(std::ostream& os, const void* p) {\n  if (p == nullptr) {\n    os << \"(null)\";\n  } else {\n    os << p;\n  }\n}\n\nstd::ostream& operator<<(std::ostream& os, UnprintableWrapper) {\n  return os << \"UNPRINTABLE\";\n}\n\n// Helper functions for string comparisons.\n#define DEFINE_CHECK_STROP_IMPL(name, func, expected)                          \\\n  const char* absl_nullable Check##func##expected##Impl(                       \\\n      const char* absl_nullable s1, const char* absl_nullable s2,              \\\n      const char* absl_nonnull exprtext) {                                     \\\n    bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2));                      \\\n    if (equal == expected) {                                                   \\\n      return nullptr;                                                          \\\n    } else {                                                                   \\\n      /* There's no need to free this string since the process is crashing. */ \\\n      return absl::IgnoreLeak(new std::string(absl::StrCat(exprtext, \" (\", s1, \\\n                                                           \" vs. \", s2, \")\"))) \\\n          ->c_str();                                                           \\\n    }                                                                          \\\n  }\nDEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)\nDEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)\nDEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)\nDEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)\n#undef DEFINE_CHECK_STROP_IMPL\n\nnamespace detect_specialization {\n\nStringifySink::StringifySink(std::ostream& os) : os_(os) {}\n\nvoid StringifySink::Append(absl::string_view text) { os_ << text; }\n\nvoid StringifySink::Append(size_t length, char ch) {\n  for (size_t i = 0; i < length; ++i) os_.put(ch);\n}\n\nvoid AbslFormatFlush(StringifySink* sink, absl::string_view text) {\n  sink->Append(text);\n}\n\n}  // namespace detect_specialization\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/check_op.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/check_op.h\n// -----------------------------------------------------------------------------\n//\n// This file declares helpers routines and macros used to implement `CHECK`\n// macros.\n\n#ifndef ABSL_LOG_INTERNAL_CHECK_OP_H_\n#define ABSL_LOG_INTERNAL_CHECK_OP_H_\n\n#include <stdint.h>\n\n#include <cstddef>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/log/internal/nullguard.h\"\n#include \"absl/log/internal/nullstream.h\"\n#include \"absl/log/internal/strip.h\"\n#include \"absl/strings/has_absl_stringify.h\"\n#include \"absl/strings/has_ostream_operator.h\"\n#include \"absl/strings/string_view.h\"\n\n// `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that\n// should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.\n#ifdef ABSL_MIN_LOG_LEVEL\n#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal)                \\\n  (::absl::LogSeverity::kFatal >=                                      \\\n           static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL) \\\n       ? (literal)                                                     \\\n       : \"\")\n#else\n#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)\n#endif\n\n#ifdef NDEBUG\n// `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing.  However, we\n// still want the compiler to parse `x` and `y`, because we don't want to lose\n// potentially useful errors and warnings.\n#define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y)   \\\n  while (false && ((void)(x), (void)(y), 0)) \\\n  ::absl::log_internal::NullStream().InternalStream()\n#endif\n\n#define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \\\n  while (const char* absl_nullable absl_log_internal_check_op_result           \\\n         [[maybe_unused]] = ::absl::log_internal::name##Impl(                  \\\n             ::absl::log_internal::GetReferenceableValue(val1),                \\\n             ::absl::log_internal::GetReferenceableValue(val2),                \\\n             ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val1_text \" \" #op          \\\n                                                              \" \" val2_text))) \\\n    ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \\\n  ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>(     \\\n                              absl_log_internal_check_op_result))              \\\n      .InternalStream()\n#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2,        \\\n                                    val2_text)                              \\\n  while (const char* absl_nullable absl_log_internal_qcheck_op_result =     \\\n             ::absl::log_internal::name##Impl(                              \\\n                 ::absl::log_internal::GetReferenceableValue(val1),         \\\n                 ::absl::log_internal::GetReferenceableValue(val2),         \\\n                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(                    \\\n                     val1_text \" \" #op \" \" val2_text)))                     \\\n    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                     \\\n  ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \\\n                               absl_log_internal_qcheck_op_result))         \\\n      .InternalStream()\n#define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2,     \\\n                                      s2_text)                                 \\\n  while (const char* absl_nullable absl_log_internal_check_strop_result =      \\\n             ::absl::log_internal::Check##func##expected##Impl(                \\\n                 (s1), (s2),                                                   \\\n                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text \" \" #op        \\\n                                                                \" \" s2_text))) \\\n    ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \\\n  ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>(     \\\n                              absl_log_internal_check_strop_result))           \\\n      .InternalStream()\n#define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2,    \\\n                                       s2_text)                                \\\n  while (const char* absl_nullable absl_log_internal_qcheck_strop_result =     \\\n             ::absl::log_internal::Check##func##expected##Impl(                \\\n                 (s1), (s2),                                                   \\\n                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text \" \" #op        \\\n                                                                \" \" s2_text))) \\\n    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                        \\\n  ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>(    \\\n                               absl_log_internal_qcheck_strop_result))         \\\n      .InternalStream()\n\n// This one is tricky:\n// * We must evaluate `val` exactly once, yet we need to do two things with it:\n//   evaluate `.ok()` and (sometimes) `.ToString()`.\n// * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.\n// * `val` might be e.g. `ATemporary().GetStatus()`, which may return a\n//   reference to a member of `ATemporary` that is only valid until the end of\n//   the full expression.\n// * We don't want this file to depend on `absl::Status` `#include`s or linkage,\n//   nor do we want to move the definition to status and introduce a dependency\n//   in the other direction.  We can be assured that callers must already have a\n//   `Status` and the necessary `#include`s and linkage.\n// * Callsites should be small and fast (at least when `val.ok()`): one branch,\n//   minimal stack footprint.\n//   * In particular, the string concat stuff should be out-of-line and emitted\n//     in only one TU to save linker input size\n// * We want the `val.ok()` check inline so static analyzers and optimizers can\n//   see it.\n// * As usual, no braces so we can stream into the expansion with `operator<<`.\n// * Also as usual, it must expand to a single (partial) statement with no\n//   ambiguous-else problems.\n// * When stripped by `ABSL_MIN_LOG_LEVEL`, we must discard the `<expr> is OK`\n//   string literal and abort without doing any streaming.  We don't need to\n//   strip the call to stringify the non-ok `Status` as long as we don't log it;\n//   dropping the `Status`'s message text is out of scope.\n#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text)                         \\\n  for (::std::pair<const ::absl::Status* absl_nonnull,                    \\\n                   const char* absl_nonnull>                              \\\n           absl_log_internal_check_ok_goo;                                \\\n       absl_log_internal_check_ok_goo.first =                             \\\n           ::absl::log_internal::AsStatus(val),                           \\\n       absl_log_internal_check_ok_goo.second =                            \\\n           ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())  \\\n               ? \"\" /* Don't use nullptr, to keep the annotation happy */ \\\n               : ::absl::status_internal::MakeCheckFailString(            \\\n                     absl_log_internal_check_ok_goo.first,                \\\n                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text      \\\n                                                            \" is OK\")),   \\\n       !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)   \\\n    ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                    \\\n  ABSL_LOG_INTERNAL_CHECK(absl_log_internal_check_ok_goo.second)          \\\n      .InternalStream()\n#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text)                        \\\n  for (::std::pair<const ::absl::Status* absl_nonnull,                    \\\n                   const char* absl_nonnull>                              \\\n           absl_log_internal_qcheck_ok_goo;                               \\\n       absl_log_internal_qcheck_ok_goo.first =                            \\\n           ::absl::log_internal::AsStatus(val),                           \\\n       absl_log_internal_qcheck_ok_goo.second =                           \\\n           ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok()) \\\n               ? \"\" /* Don't use nullptr, to keep the annotation happy */ \\\n               : ::absl::status_internal::MakeCheckFailString(            \\\n                     absl_log_internal_qcheck_ok_goo.first,               \\\n                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text      \\\n                                                            \" is OK\")),   \\\n       !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());)  \\\n    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                   \\\n  ABSL_LOG_INTERNAL_QCHECK(absl_log_internal_qcheck_ok_goo.second)        \\\n      .InternalStream()\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass Status;\ntemplate <typename T>\nclass StatusOr;\n\nnamespace status_internal {\nABSL_ATTRIBUTE_PURE_FUNCTION const char* absl_nonnull MakeCheckFailString(\n    const absl::Status* absl_nonnull status, const char* absl_nonnull prefix);\n}  // namespace status_internal\n\nnamespace log_internal {\n\n// Convert a Status or a StatusOr to its underlying status value.\n//\n// (This implementation does not require a dep on absl::Status to work.)\ninline const absl::Status* absl_nonnull AsStatus(const absl::Status& s) {\n  return &s;\n}\ntemplate <typename T>\nconst absl::Status* absl_nonnull AsStatus(const absl::StatusOr<T>& s) {\n  return &s.status();\n}\n\n// A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.\n// See `MakeCheckOpString` for sample usage.\nclass CheckOpMessageBuilder final {\n public:\n  // Inserts `exprtext` and ` (` to the stream.\n  explicit CheckOpMessageBuilder(const char* absl_nonnull exprtext);\n  ~CheckOpMessageBuilder() = default;\n  // For inserting the first variable.\n  std::ostream& ForVar1() { return stream_; }\n  // For inserting the second variable (adds an intermediate ` vs. `).\n  std::ostream& ForVar2();\n  // Get the result (inserts the closing `)`).\n  const char* absl_nonnull NewString();\n\n private:\n  std::ostringstream stream_;\n};\n\n// This formats a value for a failing `CHECK_XX` statement.  Ordinarily, it uses\n// the definition for `operator<<`, with a few special cases below.\ntemplate <typename T>\ninline void MakeCheckOpValueString(std::ostream& os, const T& v) {\n  os << log_internal::NullGuard<T>::Guard(v);\n}\n\n// Overloads for char types provide readable values for unprintable characters.\nvoid MakeCheckOpValueString(std::ostream& os, char v);\nvoid MakeCheckOpValueString(std::ostream& os, signed char v);\nvoid MakeCheckOpValueString(std::ostream& os, unsigned char v);\nvoid MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p);\n\n// A wrapper for types that have no operator<<.\nstruct UnprintableWrapper {\n  template <typename T>\n  explicit UnprintableWrapper(const T&) {}\n\n  friend std::ostream& operator<<(std::ostream& os, UnprintableWrapper);\n};\n\nnamespace detect_specialization {\n\n// MakeCheckOpString is being specialized for every T and U pair that is being\n// passed to the CHECK_op macros. However, there is a lot of redundancy in these\n// specializations that creates unnecessary library and binary bloat.\n// The number of instantiations tends to be O(n^2) because we have two\n// independent inputs. This technique works by reducing `n`.\n//\n// Most user-defined types being passed to CHECK_op end up being printed as a\n// builtin type. For example, enums tend to be implicitly converted to its\n// underlying type when calling operator<<, and pointers are printed with the\n// `const void*` overload.\n// To reduce the number of instantiations we coerce these values before calling\n// MakeCheckOpString instead of inside it.\n//\n// To detect if this coercion is needed, we duplicate all the relevant\n// operator<< overloads as specified in the standard, just in a different\n// namespace. If the call to `stream << value` becomes ambiguous, it means that\n// one of these overloads is the one selected by overload resolution. We then\n// do overload resolution again just with our overload set to see which one gets\n// selected. That tells us which type to coerce to.\n// If the augmented call was not ambiguous, it means that none of these were\n// selected and we can't coerce the input.\n//\n// As a secondary step to reduce code duplication, we promote integral types to\n// their 64-bit variant. This does not change the printed value, but reduces the\n// number of instantiations even further. Promoting an integer is very cheap at\n// the call site.\nint64_t operator<<(std::ostream&, short value);           // NOLINT\nint64_t operator<<(std::ostream&, unsigned short value);  // NOLINT\nint64_t operator<<(std::ostream&, int value);\nint64_t operator<<(std::ostream&, unsigned int value);\nint64_t operator<<(std::ostream&, long value);                 // NOLINT\nuint64_t operator<<(std::ostream&, unsigned long value);       // NOLINT\nint64_t operator<<(std::ostream&, long long value);            // NOLINT\nuint64_t operator<<(std::ostream&, unsigned long long value);  // NOLINT\nfloat operator<<(std::ostream&, float value);\ndouble operator<<(std::ostream&, double value);\nlong double operator<<(std::ostream&, long double value);\nbool operator<<(std::ostream&, bool value);\nconst void* absl_nullable operator<<(std::ostream&,\n                                     const void* absl_nullable value);\nconst void* absl_nullable operator<<(std::ostream&, std::nullptr_t);\n\n// These `char` overloads are specified like this in the standard, so we have to\n// write them exactly the same to ensure the call is ambiguous.\n// If we wrote it in a different way (eg taking std::ostream instead of the\n// template) then one call might have a higher rank than the other and it would\n// not be ambiguous.\ntemplate <typename Traits>\nchar operator<<(std::basic_ostream<char, Traits>&, char);\ntemplate <typename Traits>\nsigned char operator<<(std::basic_ostream<char, Traits>&, signed char);\ntemplate <typename Traits>\nunsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);\ntemplate <typename Traits>\nconst char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,\n                                    const char* absl_nonnull);\ntemplate <typename Traits>\nconst signed char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,\n                                           const signed char* absl_nonnull);\ntemplate <typename Traits>\nconst unsigned char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,\n                                             const unsigned char* absl_nonnull);\n\n// This overload triggers when the call is not ambiguous.\n// It means that T is being printed with some overload not on this list.\n// We keep the value as `const T&`.\ntemplate <typename T, typename = decltype(std::declval<std::ostream&>()\n                                          << std::declval<const T&>())>\nconst T& Detect(int);\n\n// This overload triggers when the call is ambiguous.\n// It means that T is either one from this list or printed as one from this\n// list. Eg an unscoped enum that decays to `int` for printing.\n// We ask the overload set to give us the type we want to convert it to.\ntemplate <typename T>\ndecltype(detect_specialization::operator<<(\n    std::declval<std::ostream&>(), std::declval<const T&>())) Detect(char);\n\n// A sink for AbslStringify which redirects everything to a std::ostream.\nclass StringifySink {\n public:\n  explicit StringifySink(std::ostream& os ABSL_ATTRIBUTE_LIFETIME_BOUND);\n\n  void Append(absl::string_view text);\n  void Append(size_t length, char ch);\n  friend void AbslFormatFlush(StringifySink* absl_nonnull sink,\n                              absl::string_view text);\n\n private:\n  std::ostream& os_;\n};\n\n// Wraps a type implementing AbslStringify, and implements operator<<.\ntemplate <typename T>\nclass StringifyToStreamWrapper {\n public:\n  explicit StringifyToStreamWrapper(const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : v_(v) {}\n\n  friend std::ostream& operator<<(std::ostream& os,\n                                  const StringifyToStreamWrapper& wrapper) {\n    StringifySink sink(os);\n    AbslStringify(sink, wrapper.v_);\n    return os;\n  }\n\n private:\n  const T& v_;\n};\n\n// This overload triggers when T implements AbslStringify.\n// StringifyToStreamWrapper is used to allow MakeCheckOpString to use\n// operator<<.\ntemplate <typename T>\nstd::enable_if_t<HasAbslStringify<T>::value,\n                 StringifyToStreamWrapper<T>>\nDetect(...);  // Ellipsis has lowest preference when int passed.\n\n// This overload triggers when T is neither possible to print nor an enum.\ntemplate <typename T>\nstd::enable_if_t<std::negation_v<std::disjunction<\n                     std::is_convertible<T, int>, std::is_enum<T>,\n                     std::is_pointer<T>, std::is_same<T, std::nullptr_t>,\n                     HasOstreamOperator<T>, HasAbslStringify<T>>>,\n                 UnprintableWrapper>\nDetect(...);\n\n// Equivalent to the updated std::underlying_type from C++20, which is no\n// longer undefined behavior for non-enum types.\ntemplate <typename T, typename EnableT = void>\nstruct UnderlyingType {};\n\ntemplate <typename T>\nstruct UnderlyingType<T, std::enable_if_t<std::is_enum_v<T>>> {\n  using type = std::underlying_type_t<T>;\n};\ntemplate <typename T>\nusing UnderlyingTypeT = typename UnderlyingType<T>::type;\n\n// This overload triggers when T is a scoped enum that has not defined an output\n// stream operator (operator<<) or AbslStringify. It causes the enum value to be\n// converted to a type that can be streamed. For consistency with other enums, a\n// scoped enum backed by a bool or char is converted to its underlying type, and\n// one backed by another integer is converted to (u)int64_t.\ntemplate <typename T>\nstd::enable_if_t<\n    std::conjunction_v<std::is_enum<T>,\n                       std::negation<std::is_convertible<T, int>>,\n                       std::negation<HasOstreamOperator<T>>,\n                       std::negation<HasAbslStringify<T>>>,\n    std::conditional_t<std::is_same_v<UnderlyingTypeT<T>, bool> ||\n                           std::is_same_v<UnderlyingTypeT<T>, char> ||\n                           std::is_same_v<UnderlyingTypeT<T>, signed char> ||\n                           std::is_same_v<UnderlyingTypeT<T>, unsigned char>,\n                       UnderlyingTypeT<T>,\n                       std::conditional_t<std::is_signed_v<UnderlyingTypeT<T>>,\n                                          int64_t, uint64_t>>>\nDetect(...);\n\ntemplate <typename T>\nusing Detected = decltype(Detect<T>(0));\n}  // namespace detect_specialization\n\n// If the comparison will happen as pointers, decay `char*` arguments to `void*`\n// when printing them. There is no evidence that they are a NULL terminated\n// C-String so printing them as such could lead to UB, and more importantly we\n// compared pointers so showing the pointers is a better result.\ntemplate <typename T>\nconstexpr bool IsCharStarOrVoidStar() {\n  if constexpr (std::is_reference_v<T>) {\n    return IsCharStarOrVoidStar<std::remove_reference_t<T>>();\n  } else if constexpr (std::is_array_v<T>) {\n    return IsCharStarOrVoidStar<std::decay_t<T>>();\n  } else {\n    using U = std::remove_const_t<std::remove_pointer_t<T>>;\n    return std::is_pointer_v<T> &&\n        (std::is_same_v<char, U> || std::is_same_v<unsigned char, U> ||\n         std::is_same_v<signed char, U> || std::is_void_v<U>);\n  }\n}\n\ntemplate <typename T1, typename T2,\n          typename U1 = detect_specialization::Detected<T1>,\n          typename U2 = detect_specialization::Detected<T2>>\nusing CheckOpStreamType =\n    std::conditional_t<IsCharStarOrVoidStar<U1>() && IsCharStarOrVoidStar<U2>(),\n                       const void*, U1>;\n\n// Build the error message string.  Specify no inlining for code size.\ntemplate <typename T1, typename T2>\nABSL_ATTRIBUTE_RETURNS_NONNULL const char* absl_nonnull MakeCheckOpString(\n    T1 v1, T2 v2, const char* absl_nonnull exprtext) ABSL_ATTRIBUTE_NOINLINE;\n\ntemplate <typename T1, typename T2>\nconst char* absl_nonnull MakeCheckOpString(T1 v1, T2 v2,\n                                           const char* absl_nonnull exprtext) {\n  if constexpr (std::is_same_v<CheckOpStreamType<T1, T2>, UnprintableWrapper> &&\n                std::is_same_v<CheckOpStreamType<T2, T1>, UnprintableWrapper>) {\n    // No sense printing \" (UNPRINTABLE vs. UNPRINTABLE)\"\n    return exprtext;\n  } else {\n    CheckOpMessageBuilder comb(exprtext);\n    MakeCheckOpValueString(comb.ForVar1(), v1);\n    MakeCheckOpValueString(comb.ForVar2(), v2);\n    return comb.NewString();\n  }\n}\n\n// Add a few commonly used instantiations as extern to reduce size of objects\n// files.\n#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \\\n  extern template const char* absl_nonnull MakeCheckOpString(   \\\n      x, x, const char* absl_nonnull)\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char* absl_nonnull);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(\n    const signed char* absl_nonnull);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(\n    const unsigned char* absl_nonnull);\nABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void* absl_nonnull);\n#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN\n\n// `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result\n// string iff `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`, instead returning an empty\n// string.\n#ifdef ABSL_MIN_LOG_LEVEL\n#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \\\n  ((::absl::LogSeverity::kFatal >=                                       \\\n    static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL))         \\\n       ? MakeCheckOpString<U1, U2>(v1, v2, exprtext)                     \\\n       : \"\")\n#else\n#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \\\n  MakeCheckOpString<U1, U2>(v1, v2, exprtext)\n#endif\n\n// Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family.  The\n// `(int, int)` override works around the issue that the compiler will not\n// instantiate the template version of the function on values of unnamed enum\n// type.\n#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op)                          \\\n  template <typename T1, typename T2>                                      \\\n  inline constexpr const char* absl_nullable name##Impl(                   \\\n      const T1& v1, const T2& v2, const char* absl_nonnull exprtext) {     \\\n    using U1 = CheckOpStreamType<T1, T2>;                                  \\\n    using U2 = CheckOpStreamType<T2, T1>;                                  \\\n    return ABSL_PREDICT_TRUE(v1 op v2)                                     \\\n               ? nullptr                                                   \\\n               : ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, U1(v1),    \\\n                                                        U2(v2), exprtext); \\\n  }                                                                        \\\n  inline constexpr const char* absl_nullable name##Impl(                   \\\n      int v1, int v2, const char* absl_nonnull exprtext) {                 \\\n    return name##Impl<int, int>(v1, v2, exprtext);                         \\\n  }\n\nABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)\nABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)\nABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)\nABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)\nABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)\nABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)\n#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT\n#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL\n\nconst char* absl_nullable CheckstrcmptrueImpl(\n    const char* absl_nullable s1, const char* absl_nullable s2,\n    const char* absl_nonnull exprtext);\nconst char* absl_nullable CheckstrcmpfalseImpl(\n    const char* absl_nullable s1, const char* absl_nullable s2,\n    const char* absl_nonnull exprtext);\nconst char* absl_nullable CheckstrcasecmptrueImpl(\n    const char* absl_nullable s1, const char* absl_nullable s2,\n    const char* absl_nonnull exprtext);\nconst char* absl_nullable CheckstrcasecmpfalseImpl(\n    const char* absl_nullable s1, const char* absl_nullable s2,\n    const char* absl_nonnull exprtext);\n\n// `CHECK_EQ` and friends want to pass their arguments by reference, however\n// this winds up exposing lots of cases where people have defined and\n// initialized static const data members but never declared them (i.e. in a .cc\n// file), meaning they are not referenceable.  This function avoids that problem\n// for integers (the most common cases) by overloading for every primitive\n// integer type, even the ones we discourage, and returning them by value.\n// NOLINTBEGIN(runtime/int)\n// NOLINTBEGIN(google-runtime-int)\ntemplate <typename T>\ninline constexpr const T& GetReferenceableValue(const T& t) {\n  return t;\n}\ninline constexpr char GetReferenceableValue(char t) { return t; }\ninline constexpr unsigned char GetReferenceableValue(unsigned char t) {\n  return t;\n}\ninline constexpr signed char GetReferenceableValue(signed char t) { return t; }\ninline constexpr short GetReferenceableValue(short t) { return t; }\ninline constexpr unsigned short GetReferenceableValue(unsigned short t) {\n  return t;\n}\ninline constexpr int GetReferenceableValue(int t) { return t; }\ninline constexpr unsigned int GetReferenceableValue(unsigned int t) {\n  return t;\n}\ninline constexpr long GetReferenceableValue(long t) { return t; }\ninline constexpr unsigned long GetReferenceableValue(unsigned long t) {\n  return t;\n}\ninline constexpr long long GetReferenceableValue(long long t) { return t; }\ninline constexpr unsigned long long GetReferenceableValue(\n    unsigned long long t) {\n  return t;\n}\n// NOLINTEND(google-runtime-int)\n// NOLINTEND(runtime/int)\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_CHECK_OP_H_\n"
  },
  {
    "path": "absl/log/internal/conditions.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/conditions.h\"\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/cycleclock.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\n\n// The following code behaves like AtomicStatsCounter::LossyAdd() for\n// speed since it is fine to lose occasional updates.\n// Returns old value of *counter.\nuint32_t LossyIncrement(std::atomic<uint32_t>* counter) {\n  const uint32_t value = counter->load(std::memory_order_relaxed);\n  counter->store(value + 1, std::memory_order_relaxed);\n  return value;\n}\n\n}  // namespace\n\nbool LogEveryNState::ShouldLog(int n) {\n  return n > 0 && (LossyIncrement(&counter_) % static_cast<uint32_t>(n)) == 0;\n}\n\nbool LogFirstNState::ShouldLog(int n) {\n  const uint32_t counter_value = counter_.load(std::memory_order_relaxed);\n  if (static_cast<int64_t>(counter_value) < n) {\n    counter_.store(counter_value + 1, std::memory_order_relaxed);\n    return true;\n  }\n  return false;\n}\n\nbool LogEveryPow2State::ShouldLog() {\n  const uint32_t new_value = LossyIncrement(&counter_) + 1;\n  return (new_value & (new_value - 1)) == 0;\n}\n\nbool LogEveryNSecState::ShouldLog(double seconds) {\n  using absl::base_internal::CycleClock;\n  LossyIncrement(&counter_);\n  const int64_t now_cycles = CycleClock::Now();\n  int64_t next_cycles = next_log_time_cycles_.load(std::memory_order_relaxed);\n#if defined(__myriad2__)\n  // myriad2 does not have 8-byte compare and exchange.  Use a racy version that\n  // is \"good enough\" but will over-log in the face of concurrent logging.\n  if (now_cycles > next_cycles) {\n    next_log_time_cycles_.store(\n        static_cast<int64_t>(now_cycles + seconds * CycleClock::Frequency()),\n        std::memory_order_relaxed);\n    return true;\n  }\n  return false;\n#else\n  do {\n    if (now_cycles <= next_cycles) return false;\n  } while (!next_log_time_cycles_.compare_exchange_weak(\n      next_cycles,\n      static_cast<int64_t>(now_cycles + seconds * CycleClock::Frequency()),\n      std::memory_order_relaxed, std::memory_order_relaxed));\n  return true;\n#endif\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/conditions.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/conditions.h\n// -----------------------------------------------------------------------------\n//\n// This file contains implementation of conditional log statements, like LOG_IF\n// including all the ABSL_LOG_INTERNAL_..._CONDITION_... macros and\n// various condition classes like LogEveryNState.\n\n#ifndef ABSL_LOG_INTERNAL_CONDITIONS_H_\n#define ABSL_LOG_INTERNAL_CONDITIONS_H_\n\n#if defined(_WIN32) || defined(__hexagon__)\n#include <cstdlib>\n#else\n#include <unistd.h>\n#endif\n#include <stdlib.h>\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/voidify.h\"\n\n// `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a\n// temporary `LogMessage` instantiation followed by zero or more streamed\n// expressions.  This definition is tricky to read correctly.  It evaluates to\n// either\n//\n//   (void)0;\n//\n// or\n//\n//   ::absl::log_internal::Voidify() &&\n//       ::absl::log_internal::LogMessage(...) << \"the user's message\";\n//\n// If the condition is evaluable at compile time, as is often the case, it\n// compiles away to just one side or the other.\n//\n// Although this is not used anywhere a statement (e.g. `if`) could not go,\n// the ternary expression does a better job avoiding spurious diagnostics\n// (dangling else, missing switch case) and preserving noreturn semantics (e.g.\n// on `LOG(FATAL)`) without requiring braces.\n//\n// The `switch` ensures that this expansion is the beginning of a statement (as\n// opposed to an expression) and prevents shenanigans like\n// `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`.  The apparently-redundant\n// `default` case makes the condition more amenable to Clang dataflow analysis.\n#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \\\n  switch (0)                                             \\\n  case 0:                                                \\\n  default:                                               \\\n    !(condition) ? (void)0 : ::absl::log_internal::Voidify() &&\n\n// `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like\n// `ABSL_LOG_INTERNAL_STATELESS_CONDITION` but adds to that a series of variable\n// declarations, including a local static object which stores the state needed\n// to implement the stateful macros like `LOG_EVERY_N`.\n//\n// `for`-loops are used to declare scoped variables without braces (to permit\n// streaming into the macro's expansion) and without the dangling-`else`\n// problems/diagnostics that come with `if`.\n//\n// Two more variables are declared in separate `for`-loops:\n//\n// * `COUNTER` implements a streamable token whose value when streamed is the\n//   number of times execution has passed through the macro.\n// * A boolean flag is used to prevent any of the `for`-loops from ever actually\n//   looping.\n#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition)             \\\n  for (bool absl_log_internal_stateful_condition_do_log(condition); \\\n       absl_log_internal_stateful_condition_do_log;                 \\\n       absl_log_internal_stateful_condition_do_log = false)         \\\n  ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL\n#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...)              \\\n  for (static ::absl::log_internal::Log##kind##State                      \\\n           absl_log_internal_stateful_condition_state;                    \\\n       absl_log_internal_stateful_condition_do_log &&                     \\\n       absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \\\n       absl_log_internal_stateful_condition_do_log = false)               \\\n    for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED =                   \\\n             absl_log_internal_stateful_condition_state.counter();        \\\n         absl_log_internal_stateful_condition_do_log;                     \\\n         absl_log_internal_stateful_condition_do_log = false)             \\\n  ::absl::log_internal::Voidify() &&\n\n// `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the\n// macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.\n// `ABSL_MIN_LOG_LEVEL`) into a single boolean expression.  We could chain\n// ternary operators instead, however some versions of Clang sometimes issue\n// spurious diagnostics after such expressions due to a control flow analysis\n// bug.\n#ifdef ABSL_MIN_LOG_LEVEL\n#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                   \\\n      (condition) &&                                      \\\n      ::absl::LogSeverity::kInfo >=                       \\\n          static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL))\n#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                      \\\n      (condition) &&                                         \\\n      ::absl::LogSeverity::kWarning >=                       \\\n          static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL))\n#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                    \\\n      (condition) &&                                       \\\n      ::absl::LogSeverity::kError >=                       \\\n          static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL))\n#define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \\\n  ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition)\n// NOTE: Use ternary operators instead of short-circuiting to mitigate\n// https://bugs.llvm.org/show_bug.cgi?id=51928.\n#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition)                 \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                                    \\\n      ((condition) ? (::absl::LogSeverity::kFatal >=                       \\\n                              static_cast<::absl::LogSeverityAtLeast>(     \\\n                                  ABSL_MIN_LOG_LEVEL)                      \\\n                          ? true                                           \\\n                          : (::absl::log_internal::AbortQuietly(), false)) \\\n                   : false))\n// NOTE: Use ternary operators instead of short-circuiting to mitigate\n// https://bugs.llvm.org/show_bug.cgi?id=51928.\n#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition)               \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                                   \\\n      ((condition) ? (::absl::LogSeverity::kFatal >=                      \\\n                              static_cast<::absl::LogSeverityAtLeast>(    \\\n                                  ABSL_MIN_LOG_LEVEL)                     \\\n                          ? true                                          \\\n                          : (::absl::log_internal::ExitQuietly(), false)) \\\n                   : false))\n#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition)                    \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                                        \\\n      (ABSL_ASSUME(absl::kLogDebugFatal == absl::LogSeverity::kError ||        \\\n                   absl::kLogDebugFatal == absl::LogSeverity::kFatal),         \\\n       (condition) &&                                                          \\\n           (::absl::kLogDebugFatal >=                                          \\\n                static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL) || \\\n            (::absl::kLogDebugFatal == ::absl::LogSeverity::kFatal &&          \\\n             (::absl::log_internal::AbortQuietly(), false)))))\n\n#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity)                            \\\n  for (int absl_log_internal_severity_loop = 1;                                \\\n       absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0)   \\\n    for (const absl::LogSeverity absl_log_internal_severity =                  \\\n             ::absl::NormalizeLogSeverity(severity);                           \\\n         absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \\\n  ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL\n#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition)            \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(                                    \\\n      ((condition) &&                                                      \\\n       (absl_log_internal_severity >=                                      \\\n            static_cast<::absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL) || \\\n        (absl_log_internal_severity == ::absl::LogSeverity::kFatal &&      \\\n         (::absl::log_internal::AbortQuietly(), false)))))\n#else  // ndef ABSL_MIN_LOG_LEVEL\n#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \\\n  ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition)\n#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity)                            \\\n  for (int absl_log_internal_severity_loop = 1;                                \\\n       absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0)   \\\n    for (const absl::LogSeverity absl_log_internal_severity =                  \\\n             ::absl::NormalizeLogSeverity(severity);                           \\\n         absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \\\n  ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL\n#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \\\n  ABSL_LOG_INTERNAL_##type##_CONDITION(condition)\n#endif  // ndef ABSL_MIN_LOG_LEVEL\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// Stateful condition class name should be \"Log\" + name + \"State\".\nclass LogEveryNState final {\n public:\n  bool ShouldLog(int n);\n  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }\n\n private:\n  std::atomic<uint32_t> counter_{0};\n};\n\nclass LogFirstNState final {\n public:\n  bool ShouldLog(int n);\n  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }\n\n private:\n  std::atomic<uint32_t> counter_{0};\n};\n\nclass LogEveryPow2State final {\n public:\n  bool ShouldLog();\n  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }\n\n private:\n  std::atomic<uint32_t> counter_{0};\n};\n\nclass LogEveryNSecState final {\n public:\n  bool ShouldLog(double seconds);\n  uint32_t counter() { return counter_.load(std::memory_order_relaxed); }\n\n private:\n  std::atomic<uint32_t> counter_{0};\n  // Cycle count according to CycleClock that we should next log at.\n  std::atomic<int64_t> next_log_time_cycles_{0};\n};\n\n// Helper routines to abort the application quietly\n\n[[noreturn]] inline void AbortQuietly() { abort(); }\n[[noreturn]] inline void ExitQuietly() { _exit(1); }\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_CONDITIONS_H_\n"
  },
  {
    "path": "absl/log/internal/config.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/config.h\n// -----------------------------------------------------------------------------\n//\n\n#ifndef ABSL_LOG_INTERNAL_CONFIG_H_\n#define ABSL_LOG_INTERNAL_CONFIG_H_\n\n#include \"absl/base/config.h\"\n\n#ifdef _WIN32\n#include <cstdint>\n#else\n#include <sys/types.h>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n#ifdef _WIN32\nusing Tid = uint32_t;\n#else\nusing Tid = pid_t;\n#endif\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_CONFIG_H_\n"
  },
  {
    "path": "absl/log/internal/container.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// The typical use looks like this:\n//\n//   LOG(INFO) << LogContainer(container);\n//\n// By default, LogContainer() uses the LogShortUpTo100 policy: comma-space\n// separation, no newlines, and with limit of 100 items.\n//\n// Policies can be specified:\n//\n//   LOG(INFO) << LogContainer(container, LogMultiline());\n//\n// The above example will print the container using newlines between elements,\n// enclosed in [] braces.\n//\n// See below for further details on policies.\n\n#ifndef ABSL_LOG_INTERNAL_CONTAINER_H_\n#define ABSL_LOG_INTERNAL_CONTAINER_H_\n\n#include <cstdint>\n#include <limits>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/internal/requires.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// Several policy classes below determine how LogRangeToStream will\n// format a range of items.  A Policy class should have these methods:\n//\n// Called to print an individual container element.\n//   void Log(ostream &out, const ElementT &element) const;\n//\n// Called before printing the set of elements:\n//   void LogOpening(ostream &out) const;\n//\n// Called after printing the set of elements:\n//   void LogClosing(ostream &out) const;\n//\n// Called before printing the first element:\n//   void LogFirstSeparator(ostream &out) const;\n//\n// Called before printing the remaining elements:\n//   void LogSeparator(ostream &out) const;\n//\n// Returns the maximum number of elements to print:\n//   int64 MaxElements() const;\n//\n// Called to print an indication that MaximumElements() was reached:\n//   void LogEllipsis(ostream &out) const;\n\nnamespace internal {\n\nstruct LogBase {\n  template <typename ElementT>\n  void Log(std::ostream &out, const ElementT &element) const {  // NOLINT\n    // Fallback to `AbslStringify` if the type does not have `operator<<`.\n    if constexpr (meta_internal::Requires<std::ostream, ElementT>(\n                      [](auto&& x, auto&& y) -> decltype(x << y) {})) {\n      out << element;\n    } else {\n      out << absl::StrCat(element);\n    }\n  }\n  void LogEllipsis(std::ostream &out) const {  // NOLINT\n    out << \"...\";\n  }\n};\n\nstruct LogShortBase : public LogBase {\n  void LogOpening(std::ostream &out) const { out << \"[\"; }        // NOLINT\n  void LogClosing(std::ostream &out) const { out << \"]\"; }        // NOLINT\n  void LogFirstSeparator(std::ostream &out) const { out << \"\"; }  // NOLINT\n  void LogSeparator(std::ostream &out) const { out << \", \"; }     // NOLINT\n};\n\nstruct LogMultilineBase : public LogBase {\n  void LogOpening(std::ostream &out) const { out << \"[\"; }          // NOLINT\n  void LogClosing(std::ostream &out) const { out << \"\\n]\"; }        // NOLINT\n  void LogFirstSeparator(std::ostream &out) const { out << \"\\n\"; }  // NOLINT\n  void LogSeparator(std::ostream &out) const { out << \"\\n\"; }       // NOLINT\n};\n\nstruct LogLegacyBase : public LogBase {\n  void LogOpening(std::ostream &out) const { out << \"\"; }         // NOLINT\n  void LogClosing(std::ostream &out) const { out << \"\"; }         // NOLINT\n  void LogFirstSeparator(std::ostream &out) const { out << \"\"; }  // NOLINT\n  void LogSeparator(std::ostream &out) const { out << \" \"; }      // NOLINT\n};\n\n}  // namespace internal\n\n// LogShort uses [] braces and separates items with comma-spaces.  For\n// example \"[1, 2, 3]\".\nstruct LogShort : public internal::LogShortBase {\n  int64_t MaxElements() const { return (std::numeric_limits<int64_t>::max)(); }\n};\n\n// LogShortUpToN(max_elements) formats the same as LogShort but prints no more\n// than the max_elements elements.\nclass LogShortUpToN : public internal::LogShortBase {\n public:\n  explicit LogShortUpToN(int64_t max_elements) : max_elements_(max_elements) {}\n  int64_t MaxElements() const { return max_elements_; }\n\n private:\n  int64_t max_elements_;\n};\n\n// LogShortUpTo100 formats the same as LogShort but prints no more\n// than 100 elements.\nstruct LogShortUpTo100 : public LogShortUpToN {\n  LogShortUpTo100() : LogShortUpToN(100) {}\n};\n\n// LogMultiline uses [] braces and separates items with\n// newlines.  For example \"[\n// 1\n// 2\n// 3\n// ]\".\nstruct LogMultiline : public internal::LogMultilineBase {\n  int64_t MaxElements() const { return (std::numeric_limits<int64_t>::max)(); }\n};\n\n// LogMultilineUpToN(max_elements) formats the same as LogMultiline but\n// prints no more than max_elements elements.\nclass LogMultilineUpToN : public internal::LogMultilineBase {\n public:\n  explicit LogMultilineUpToN(int64_t max_elements)\n      : max_elements_(max_elements) {}\n  int64_t MaxElements() const { return max_elements_; }\n\n private:\n  int64_t max_elements_;\n};\n\n// LogMultilineUpTo100 formats the same as LogMultiline but\n// prints no more than 100 elements.\nstruct LogMultilineUpTo100 : public LogMultilineUpToN {\n  LogMultilineUpTo100() : LogMultilineUpToN(100) {}\n};\n\n// The legacy behavior of LogSequence() does not use braces and\n// separates items with spaces.  For example \"1 2 3\".\nstruct LogLegacyUpTo100 : public internal::LogLegacyBase {\n  int64_t MaxElements() const { return 100; }\n};\nstruct LogLegacy : public internal::LogLegacyBase {\n  int64_t MaxElements() const { return (std::numeric_limits<int64_t>::max)(); }\n};\n\n// The default policy for new code.\ntypedef LogShortUpTo100 LogDefault;\n\n// LogRangeToStream should be used to define operator<< for\n// STL and STL-like containers.  For example, see stl_logging.h.\ntemplate <typename IteratorT, typename PolicyT>\ninline void LogRangeToStream(std::ostream &out,  // NOLINT\n                             IteratorT begin, IteratorT end,\n                             const PolicyT &policy) {\n  policy.LogOpening(out);\n  for (int64_t i = 0; begin != end && i < policy.MaxElements(); ++i, ++begin) {\n    if (i == 0) {\n      policy.LogFirstSeparator(out);\n    } else {\n      policy.LogSeparator(out);\n    }\n    policy.Log(out, *begin);\n  }\n  if (begin != end) {\n    policy.LogSeparator(out);\n    policy.LogEllipsis(out);\n  }\n  policy.LogClosing(out);\n}\n\nnamespace detail {\n\n// RangeLogger is a helper class for LogRange and LogContainer; do not use it\n// directly.  This object captures iterators into the argument of the LogRange\n// and LogContainer functions, so its lifetime should be confined to a single\n// logging statement.  Objects of this type should not be assigned to local\n// variables.\ntemplate <typename IteratorT, typename PolicyT>\nclass RangeLogger {\n public:\n  RangeLogger(const IteratorT &begin, const IteratorT &end,\n              const PolicyT &policy)\n      : begin_(begin), end_(end), policy_(policy) {}\n\n  friend std::ostream &operator<<(std::ostream &out, const RangeLogger &range) {\n    LogRangeToStream<IteratorT, PolicyT>(out, range.begin_, range.end_,\n                                         range.policy_);\n    return out;\n  }\n\n  // operator<< above is generally recommended. However, some situations may\n  // require a string, so a convenience str() method is provided as well.\n  std::string str() const {\n    std::stringstream ss;\n    ss << *this;\n    return ss.str();\n  }\n\n private:\n  IteratorT begin_;\n  IteratorT end_;\n  PolicyT policy_;\n};\n\ntemplate <typename E>\nclass EnumLogger {\n public:\n  explicit EnumLogger(E e) : e_(e) {}\n\n  friend std::ostream &operator<<(std::ostream &out, const EnumLogger &v) {\n    using I = typename std::underlying_type<E>::type;\n    return out << static_cast<I>(v.e_);\n  }\n\n private:\n  E e_;\n};\n\n}  // namespace detail\n\n// Log a range using \"policy\".  For example:\n//\n//   LOG(INFO) << LogRange(start_pos, end_pos, LogMultiline());\n//\n// The above example will print the range using newlines between\n// elements, enclosed in [] braces.\ntemplate <typename IteratorT, typename PolicyT>\ndetail::RangeLogger<IteratorT, PolicyT> LogRange(const IteratorT &begin,\n                                                 const IteratorT &end,\n                                                 const PolicyT &policy) {\n  return detail::RangeLogger<IteratorT, PolicyT>(begin, end, policy);\n}\n\n// Log a range.  For example:\n//\n//   LOG(INFO) << LogRange(start_pos, end_pos);\n//\n// By default, Range() uses the LogShortUpTo100 policy: comma-space\n// separation, no newlines, and with limit of 100 items.\ntemplate <typename IteratorT>\ndetail::RangeLogger<IteratorT, LogDefault> LogRange(const IteratorT &begin,\n                                                    const IteratorT &end) {\n  return LogRange(begin, end, LogDefault());\n}\n\n// Log a container using \"policy\".  For example:\n//\n//   LOG(INFO) << LogContainer(container, LogMultiline());\n//\n// The above example will print the container using newlines between\n// elements, enclosed in [] braces.\ntemplate <typename ContainerT, typename PolicyT>\nauto LogContainer(const ContainerT& container, const PolicyT& policy)\n    -> decltype(LogRange(container.begin(), container.end(), policy)) {\n  return LogRange(container.begin(), container.end(), policy);\n}\n\n// Log a container.  For example:\n//\n//   LOG(INFO) << LogContainer(container);\n//\n// By default, Container() uses the LogShortUpTo100 policy: comma-space\n// separation, no newlines, and with limit of 100 items.\ntemplate <typename ContainerT>\nauto LogContainer(const ContainerT& container)\n    -> decltype(LogContainer(container, LogDefault())) {\n  return LogContainer(container, LogDefault());\n}\n\n// Log a (possibly scoped) enum.  For example:\n//\n//   enum class Color { kRed, kGreen, kBlue };\n//   LOG(INFO) << LogEnum(kRed);\ntemplate <typename E>\ndetail::EnumLogger<E> LogEnum(E e) {\n  static_assert(std::is_enum<E>::value, \"must be an enum\");\n  return detail::EnumLogger<E>(e);\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_CONTAINER_H_\n"
  },
  {
    "path": "absl/log/internal/container_test.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/container.h\"\n\n#include <cstdint>\n#include <map>\n#include <memory>\n#include <ostream>\n#include <set>\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_join.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\n\nclass ContainerLoggingTest : public ::testing::Test {\n protected:\n  ContainerLoggingTest() : stream_(new std::stringstream) {}\n  std::ostream& stream() { return *stream_; }\n  std::string logged() {\n    std::string r = stream_->str();\n    stream_ = std::make_unique<std::stringstream>();\n    return r;\n  }\n\n private:\n  std::unique_ptr<std::stringstream> stream_;\n};\n\nTEST_F(ContainerLoggingTest, ShortRange) {\n  std::vector<std::string> words = {\"hi\", \"hello\"};\n  LogRangeToStream(stream(), words.begin(), words.end(), LogMultiline());\n  EXPECT_EQ(\"[\\nhi\\nhello\\n]\", logged());\n}\n\nTEST_F(ContainerLoggingTest, LegacyRange) {\n  std::vector<int> lengths = {1, 2};\n  LogRangeToStream(stream(), lengths.begin(), lengths.end(),\n                   LogLegacyUpTo100());\n  EXPECT_EQ(\"1 2\", logged());\n}\n\nTEST_F(ContainerLoggingTest, ToString) {\n  std::vector<int> lengths = {1, 2, 3, 4, 5};\n  EXPECT_EQ(LogContainer(lengths).str(), \"[1, 2, 3, 4, 5]\");\n}\n\nclass UserDefFriend {\n public:\n  explicit UserDefFriend(int i) : i_(i) {}\n\n private:\n  friend std::ostream& operator<<(std::ostream& str, const UserDefFriend& i) {\n    return str << i.i_;\n  }\n  int i_;\n};\n\nTEST_F(ContainerLoggingTest, RangeOfUserDefined) {\n  std::vector<UserDefFriend> ints = {UserDefFriend(1), UserDefFriend(2),\n                                     UserDefFriend(3)};\n  LogRangeToStream(stream(), ints.begin(), ints.begin() + 1, LogDefault());\n  LogRangeToStream(stream(), ints.begin() + 1, ints.begin() + 2,\n                   LogMultiline());\n  LogRangeToStream(stream(), ints.begin() + 2, ints.begin() + 3, LogDefault());\n  LogRangeToStream(stream(), ints.begin(), ints.begin(), LogMultiline());\n\n  EXPECT_EQ(\"[1][\\n2\\n][3][\\n]\", logged());\n}\n\nTEST_F(ContainerLoggingTest, FullContainer) {\n  std::vector<int> ints;\n  std::vector<int> ints100;\n  std::vector<int> ints123;\n  int64_t max_elements = 123;\n  std::string expected1;\n  std::string expected2;\n  std::string expected3;\n  std::string expected4;\n  std::string expected5;\n  std::string expected6;\n  std::string expected7;\n  std::string expected8;\n  std::string expected9;\n  for (int i = 0; i < 1000; ++i) {\n    ints.push_back(i);\n    if (i < 100) {\n      ints100.push_back(i);\n    }\n    if (i < max_elements) {\n      ints123.push_back(i);\n    }\n  }\n  expected1 = \"[\\n\" + absl::StrJoin(ints, \"\\n\") + \"\\n]\";\n  expected2 = \"[\" + absl::StrJoin(ints, \", \") + \"]\";\n  expected3 = \"[\\n\" + absl::StrJoin(ints100, \"\\n\") + \"\\n...\\n]\";\n  expected4 = \"[\" + absl::StrJoin(ints100, \", \") + \", ...]\";\n  expected5 = absl::StrJoin(ints100, \" \") + \" ...\";\n  expected6 = \"[\\n\" + absl::StrJoin(ints, \"\\n\") + \"\\n]\";\n  expected7 = \"[\\n\" + absl::StrJoin(ints123, \"\\n\") + \"\\n...\\n]\";\n  expected8 = \"[\" + absl::StrJoin(ints, \", \") + \"]\";\n  expected9 = \"[\" + absl::StrJoin(ints123, \", \") + \", ...]\";\n\n  LogRangeToStream(stream(), ints.begin(), ints.end(), LogMultiline());\n  EXPECT_EQ(expected1, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(), LogShort());\n  EXPECT_EQ(expected2, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(), LogMultilineUpTo100());\n  EXPECT_EQ(expected3, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(), LogShortUpTo100());\n  EXPECT_EQ(expected4, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(), LogLegacyUpTo100());\n  EXPECT_EQ(expected5, logged());\n\n  LogRangeToStream(stream(), ints.begin(), ints.end(),\n                   LogMultilineUpToN(ints.size()));\n  EXPECT_EQ(expected6, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(),\n                   LogMultilineUpToN(max_elements));\n  EXPECT_EQ(expected7, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(),\n                   LogShortUpToN(ints.size()));\n  EXPECT_EQ(expected8, logged());\n  LogRangeToStream(stream(), ints.begin(), ints.end(),\n                   LogShortUpToN(max_elements));\n  EXPECT_EQ(expected9, logged());\n}\n\nTEST_F(ContainerLoggingTest, LogContainer) {\n  std::set<int> ints = {1, 2, 3};\n  stream() << LogContainer(ints, LogMultiline());\n  EXPECT_EQ(\"[\\n1\\n2\\n3\\n]\", logged());\n\n  stream() << LogContainer(ints);\n  EXPECT_EQ(\"[1, 2, 3]\", logged());\n\n  stream() << LogContainer(std::vector<int>(ints.begin(), ints.end()),\n                           LogLegacyUpTo100());\n  EXPECT_EQ(\"1 2 3\", logged());\n}\n\nTEST_F(ContainerLoggingTest, LogMutableSpan) {\n  std::vector<int> ints = {1, 2, 3};\n  absl::Span<int> int_span(ints);\n  stream() << LogContainer(int_span);\n  EXPECT_EQ(\"[1, 2, 3]\", logged());\n}\n\nTEST_F(ContainerLoggingTest, LogRange) {\n  std::set<int> ints = {1, 2, 3};\n  stream() << LogRange(ints.begin(), ints.end(), LogMultiline());\n  EXPECT_EQ(\"[\\n1\\n2\\n3\\n]\", logged());\n\n  stream() << LogRange(ints.begin(), ints.end());\n  EXPECT_EQ(\"[1, 2, 3]\", logged());\n}\n\n// Some class with a custom Stringify\nclass C {\n public:\n  explicit C(int x) : x_(x) {}\n\n private:\n  // This is intentionally made private for the purposes of the test;\n  //` AbslStringify` isn't meant to be called directly, and instead invoked\n  // via `StrCat` and friends.\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const C& p) {\n    absl::Format(&sink, \"C(%d)\", p.x_);\n  }\n\n  int x_;\n};\n\nTEST_F(ContainerLoggingTest, LogContainerWithCustomStringify) {\n  std::vector<C> c = {C(1), C(2), C(3)};\n  stream() << LogContainer(c);\n  EXPECT_EQ(\"[C(1), C(2), C(3)]\", logged());\n}\n\nclass LogEnumTest : public ContainerLoggingTest {\n protected:\n  enum Unscoped { kUnscoped0, kUnscoped1, kUnscoped2 };\n\n  enum StreamableUnscoped {\n    kStreamableUnscoped0,\n    kStreamableUnscoped1,\n    kStreamableUnscoped2\n  };\n\n  enum class Scoped { k0, k1, k2 };\n\n  enum class StreamableScoped { k0, k1, k2 };\n\n  friend std::ostream& operator<<(std::ostream& os, StreamableUnscoped v) {\n    return os << LogEnum(v);\n  }\n\n  friend std::ostream& operator<<(std::ostream& os, StreamableScoped v) {\n    return os << LogEnum(v);\n  }\n};\n\nTEST_F(LogEnumTest, Unscoped) {\n  stream() << LogEnum(kUnscoped0) << \",\" << LogEnum(kUnscoped1) << \",\"\n           << LogEnum(kUnscoped2);\n  EXPECT_EQ(\"0,1,2\", logged());\n}\n\nTEST_F(LogEnumTest, StreamableUnscoped) {\n  stream() << kStreamableUnscoped0 << \",\" << kStreamableUnscoped1 << \",\"\n           << kStreamableUnscoped2;\n  EXPECT_EQ(\"0,1,2\", logged());\n}\n\nTEST_F(LogEnumTest, Scoped) {\n  stream() << LogEnum(Scoped::k0) << \",\" << LogEnum(Scoped::k1) << \",\"\n           << LogEnum(Scoped::k2);\n  EXPECT_EQ(\"0,1,2\", logged());\n}\n\nTEST_F(LogEnumTest, StreamableScoped) {\n  // Test using LogEnum to implement an operator<<.\n  stream() << StreamableScoped::k0 << \",\" << StreamableScoped::k1 << \",\"\n           << StreamableScoped::k2;\n  EXPECT_EQ(\"0,1,2\", logged());\n}\n\n}  // namespace\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/flags.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/log_flags.h\n// -----------------------------------------------------------------------------\n//\n// This header declares set of flags which can be used to configure Abseil\n// Logging library behaviour at runtime.\n\n#ifndef ABSL_LOG_INTERNAL_FLAGS_H_\n#define ABSL_LOG_INTERNAL_FLAGS_H_\n\n#include <string>\n\n#include \"absl/flags/declare.h\"\n\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n// These flags should not be used in C++ code to access logging library\n// configuration knobs. Use interfaces defined in absl/log/globals.h\n// instead. It is still ok to use these flags on a command line.\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n// Log messages at this severity or above are sent to stderr in *addition* to\n// `LogSink`s.  Defaults to `ERROR`.  See log_severity.h for numeric values of\n// severity levels.\nABSL_DECLARE_FLAG(int, stderrthreshold);\n\n// Log messages at this severity or above are logged; others are discarded.\n// Defaults to `INFO`, i.e. log all severities.  See log_severity.h for numeric\n// values of severity levels.\nABSL_DECLARE_FLAG(int, minloglevel);\n\n// If specified in the form file:linenum, any messages logged from a matching\n// location will also include a backtrace.\nABSL_DECLARE_FLAG(std::string, log_backtrace_at);\n\n// If true, the log prefix (severity, date, time, PID, etc.) is prepended to\n// each message logged. Defaults to true.\nABSL_DECLARE_FLAG(bool, log_prefix);\n\n// Global log verbosity level. Default is 0.\nABSL_DECLARE_FLAG(int, v);\n\n// Per-module log verbosity level. By default is empty and is unused.\nABSL_DECLARE_FLAG(std::string, vmodule);\n\n#endif  // ABSL_LOG_INTERNAL_FLAGS_H_\n"
  },
  {
    "path": "absl/log/internal/fnmatch.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/fnmatch.h\"\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nbool FNMatch(absl::string_view pattern, absl::string_view str) {\n  bool in_wildcard_match = false;\n  while (true) {\n    if (pattern.empty()) {\n      // `pattern` is exhausted; succeed if all of `str` was consumed matching\n      // it.\n      return in_wildcard_match || str.empty();\n    }\n    if (str.empty()) {\n      // `str` is exhausted; succeed if `pattern` is empty or all '*'s.\n      return pattern.find_first_not_of('*') == pattern.npos;\n    }\n    switch (pattern.front()) {\n      case '*':\n        pattern.remove_prefix(1);\n        in_wildcard_match = true;\n        break;\n      case '?':\n        pattern.remove_prefix(1);\n        str.remove_prefix(1);\n        break;\n      default:\n        if (in_wildcard_match) {\n          absl::string_view fixed_portion = pattern;\n          const size_t end = fixed_portion.find_first_of(\"*?\");\n          if (end != fixed_portion.npos) {\n            fixed_portion = fixed_portion.substr(0, end);\n          }\n          const size_t match = str.find(fixed_portion);\n          if (match == str.npos) {\n            return false;\n          }\n          pattern.remove_prefix(fixed_portion.size());\n          str.remove_prefix(match + fixed_portion.size());\n          in_wildcard_match = false;\n        } else {\n          if (pattern.front() != str.front()) {\n            return false;\n          }\n          pattern.remove_prefix(1);\n          str.remove_prefix(1);\n        }\n        break;\n    }\n  }\n}\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/fnmatch.h",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_LOG_INTERNAL_FNMATCH_H_\n#define ABSL_LOG_INTERNAL_FNMATCH_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n// Like POSIX `fnmatch`, but:\n// * accepts `string_view`\n// * does not allocate any dynamic memory\n// * only supports * and ? wildcards and not bracket expressions [...]\n// * wildcards may match /\n// * no backslash-escaping\nbool FNMatch(absl::string_view pattern, absl::string_view str);\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_FNMATCH_H_\n"
  },
  {
    "path": "absl/log/internal/fnmatch_benchmark.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/fnmatch.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\nvoid BM_FNMatch(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    bool ret =\n        absl::log_internal::FNMatch(\"*?*asdf*?*we???asdf**asdf*we\",\n                                    \"QWERFASVWERASDFWEDFASDasdfQWERGFWASDERREWF\"\n                                    \"weHOOasdf@#$%TW#ZSERasdfQW#REGTZSERERwe\");\n    benchmark::DoNotOptimize(ret);\n  }\n}\nBENCHMARK(BM_FNMatch);\n}  // namespace\n"
  },
  {
    "path": "absl/log/internal/fnmatch_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/fnmatch.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nnamespace {\nusing ::testing::IsFalse;\nusing ::testing::IsTrue;\n\nTEST(FNMatchTest, Works) {\n  using absl::log_internal::FNMatch;\n  EXPECT_THAT(FNMatch(\"foo\", \"foo\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"foo\", \"bar\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"foo\", \"fo\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"foo\", \"foo2\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"foo/*\", \"foo/1/2/3/4\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"bar/foo.ext\", \"bar/foo.ext\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"*ba*r/fo*o.ext*\", \"bar/foo.ext\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"bar/foo.ext\", \"bar/baz.ext\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"bar/foo.ext\", \"bar/foo\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"bar/foo.ext\", \"bar/foo.ext.zip\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"ba?/*.ext\", \"bar/foo.ext\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"ba?/*.ext\", \"baZ/FOO.ext\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"ba?/*.ext\", \"barr/foo.ext\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"ba?/*.ext\", \"bar/foo.ext2\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"ba?/*\", \"bar/foo.ext2\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"ba?/*\", \"bar/\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"ba?/?\", \"bar/\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"ba?/*\", \"bar\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"?x\", \"zx\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"*b\", \"aab\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"a*b\", \"aXb\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"\", \"\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"\", \"a\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"ab*\", \"ab\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"ab**\", \"ab\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"ab*?\", \"ab\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"*\", \"bbb\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"*\", \"\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"?\", \"\"), IsFalse());\n  EXPECT_THAT(FNMatch(\"***\", \"**p\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"**\", \"*\"), IsTrue());\n  EXPECT_THAT(FNMatch(\"*?\", \"*\"), IsTrue());\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/internal/globals.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/globals.h\"\n\n#include <atomic>\n#include <cstdio>\n\n#if defined(__EMSCRIPTEN__)\n#include <emscripten/console.h>\n#endif\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nnamespace {\n// Keeps track of whether Logging initialization is finalized.\n// Log messages generated before that will go to stderr.\nABSL_CONST_INIT std::atomic<bool> logging_initialized(false);\n\n// The TimeZone used for logging. This may only be set once.\nABSL_CONST_INIT std::atomic<absl::TimeZone*> timezone_ptr{nullptr};\n\n// If true, the logging library will symbolize stack in fatal messages\nABSL_CONST_INIT std::atomic<bool> symbolize_stack_trace(true);\n\n// Specifies maximum number of stack frames to report in fatal messages.\nABSL_CONST_INIT std::atomic<int> max_frames_in_stack_trace(64);\n\nABSL_CONST_INIT std::atomic<bool> exit_on_dfatal(true);\nABSL_CONST_INIT std::atomic<bool> suppress_sigabort_trace(false);\n}  // namespace\n\nbool IsInitialized() {\n  return logging_initialized.load(std::memory_order_acquire);\n}\n\nvoid SetInitialized() {\n  logging_initialized.store(true, std::memory_order_release);\n}\n\nvoid WriteToStderr(absl::string_view message, absl::LogSeverity severity) {\n  if (message.empty()) return;\n#if defined(__EMSCRIPTEN__)\n  // In WebAssembly, bypass filesystem emulation via fwrite.\n  // Skip a trailing newline character as emscripten_errn adds one itself.\n  const auto message_minus_newline = absl::StripSuffix(message, \"\\n\");\n  // emscripten_errn was introduced in 3.1.41 but broken in standalone mode\n  // until 3.1.43.\n#if ABSL_INTERNAL_EMSCRIPTEN_VERSION >= 3001043\n  emscripten_errn(message_minus_newline.data(), message_minus_newline.size());\n#else\n  std::string null_terminated_message(message_minus_newline);\n  _emscripten_err(null_terminated_message.c_str());\n#endif\n#else\n  // Avoid using std::cerr from this module since we may get called during\n  // exit code, and cerr may be partially or fully destroyed by then.\n  std::fwrite(message.data(), message.size(), 1, stderr);\n#endif\n\n#if defined(_WIN64) || defined(_WIN32) || defined(_WIN16)\n  // C99 requires stderr to not be fully-buffered by default (7.19.3.7), but\n  // MS CRT buffers it anyway, so we must `fflush` to ensure the string hits\n  // the console/file before the program dies (and takes the libc buffers\n  // with it).\n  // https://docs.microsoft.com/en-us/cpp/c-runtime-library/stream-i-o\n  if (severity >= absl::LogSeverity::kWarning) {\n    std::fflush(stderr);\n  }\n#else\n  // Avoid unused parameter warning in this branch.\n  (void)severity;\n#endif\n}\n\nvoid SetTimeZone(absl::TimeZone tz) {\n  absl::TimeZone* expected = nullptr;\n  absl::TimeZone* new_tz = new absl::TimeZone(tz);\n  // timezone_ptr can only be set once, otherwise new_tz is leaked.\n  if (!timezone_ptr.compare_exchange_strong(expected, new_tz,\n                                            std::memory_order_release,\n                                            std::memory_order_relaxed)) {\n    ABSL_RAW_LOG(FATAL,\n                 \"absl::log_internal::SetTimeZone() has already been called\");\n  }\n}\n\nconst absl::TimeZone* TimeZone() {\n  return timezone_ptr.load(std::memory_order_acquire);\n}\n\nbool ShouldSymbolizeLogStackTrace() {\n  return symbolize_stack_trace.load(std::memory_order_acquire);\n}\n\nvoid EnableSymbolizeLogStackTrace(bool on_off) {\n  symbolize_stack_trace.store(on_off, std::memory_order_release);\n}\n\nint MaxFramesInLogStackTrace() {\n  return max_frames_in_stack_trace.load(std::memory_order_acquire);\n}\n\nvoid SetMaxFramesInLogStackTrace(int max_num_frames) {\n  max_frames_in_stack_trace.store(max_num_frames, std::memory_order_release);\n}\n\nbool ExitOnDFatal() { return exit_on_dfatal.load(std::memory_order_acquire); }\n\nvoid SetExitOnDFatal(bool on_off) {\n  exit_on_dfatal.store(on_off, std::memory_order_release);\n}\n\nbool SuppressSigabortTrace() {\n  return suppress_sigabort_trace.load(std::memory_order_acquire);\n}\n\nbool SetSuppressSigabortTrace(bool on_off) {\n  return suppress_sigabort_trace.exchange(on_off);\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/globals.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/globals.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains various global objects and static helper routines\n// use in logging implementation.\n\n#ifndef ABSL_LOG_INTERNAL_GLOBALS_H_\n#define ABSL_LOG_INTERNAL_GLOBALS_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// IsInitialized returns true if the logging library is initialized.\n// This function is async-signal-safe\nbool IsInitialized();\n\n// SetLoggingInitialized is called once after logging initialization is done.\nvoid SetInitialized();\n\n// Unconditionally write a `message` to stderr. If `severity` exceeds kInfo\n// we also flush the stderr stream.\nvoid WriteToStderr(absl::string_view message, absl::LogSeverity severity);\n\n// Set the TimeZone used for human-friendly times (for example, the log message\n// prefix) printed by the logging library. This may only be called once.\nvoid SetTimeZone(absl::TimeZone tz);\n\n// Returns the TimeZone used for human-friendly times (for example, the log\n// message prefix) printed by the logging library Returns nullptr prior to\n// initialization.\nconst absl::TimeZone* TimeZone();\n\n// Returns true if stack traces emitted by the logging library should be\n// symbolized. This function is async-signal-safe.\nbool ShouldSymbolizeLogStackTrace();\n\n// Enables or disables symbolization of stack traces emitted by the\n// logging library. This function is async-signal-safe.\nvoid EnableSymbolizeLogStackTrace(bool on_off);\n\n// Returns the maximum number of frames that appear in stack traces\n// emitted by the logging library. This function is async-signal-safe.\nint MaxFramesInLogStackTrace();\n\n// Sets the maximum number of frames that appear in stack traces emitted by\n// the logging library. This function is async-signal-safe.\nvoid SetMaxFramesInLogStackTrace(int max_num_frames);\n\n// Determines whether we exit the program for a LOG(DFATAL) message in\n// debug mode.  It does this by skipping the call to Fail/FailQuietly.\n// This is intended for testing only.\n//\n// This can have some effects on LOG(FATAL) as well. Failure messages\n// are always allocated (rather than sharing a buffer), the crash\n// reason is not recorded, the \"gwq\" status message is not updated,\n// and the stack trace is not recorded.  The LOG(FATAL) *will* still\n// exit the program. Since this function is used only in testing,\n// these differences are acceptable.\n//\n// Additionally, LOG(LEVEL(FATAL)) is indistinguishable from LOG(DFATAL) and\n// will not terminate the program if SetExitOnDFatal(false) has been called.\nbool ExitOnDFatal();\n\n// SetExitOnDFatal() sets the ExitOnDFatal() status\nvoid SetExitOnDFatal(bool on_off);\n\n// Determines if the logging library should suppress logging of stacktraces in\n// the `SIGABRT` handler, typically because we just logged a stacktrace as part\n// of `LOG(FATAL)` and are about to send ourselves a `SIGABRT` to end the\n// program.\nbool SuppressSigabortTrace();\n\n// Sets the SuppressSigabortTrace() status and returns the previous state.\nbool SetSuppressSigabortTrace(bool on_off);\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_GLOBALS_H_\n"
  },
  {
    "path": "absl/log/internal/log_format.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/log_format.h\"\n\n#include <string.h>\n\n#ifdef _MSC_VER\n#include <winsock2.h>  // For timeval\n#else\n#include <sys/time.h>\n#endif\n\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/log/internal/append_truncated.h\"\n#include \"absl/log/internal/config.h\"\n#include \"absl/log/internal/globals.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/civil_time.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\n\n// This templated function avoids compiler warnings about tautological\n// comparisons when log_internal::Tid is unsigned. It can be replaced with a\n// constexpr if once the minimum C++ version Abseil supports is C++17.\ntemplate <typename T>\ninline std::enable_if_t<!std::is_signed<T>::value>\nPutLeadingWhitespace(T tid, char*& p) {\n  if (tid < 10) *p++ = ' ';\n  if (tid < 100) *p++ = ' ';\n  if (tid < 1000) *p++ = ' ';\n  if (tid < 10000) *p++ = ' ';\n  if (tid < 100000) *p++ = ' ';\n  if (tid < 1000000) *p++ = ' ';\n}\n\ntemplate <typename T>\ninline std::enable_if_t<std::is_signed<T>::value>\nPutLeadingWhitespace(T tid, char*& p) {\n  if (tid >= 0 && tid < 10) *p++ = ' ';\n  if (tid > -10 && tid < 100) *p++ = ' ';\n  if (tid > -100 && tid < 1000) *p++ = ' ';\n  if (tid > -1000 && tid < 10000) *p++ = ' ';\n  if (tid > -10000 && tid < 100000) *p++ = ' ';\n  if (tid > -100000 && tid < 1000000) *p++ = ' ';\n}\n\n// The fields before the filename are all fixed-width except for the thread ID,\n// which is of bounded width.\nsize_t FormatBoundedFields(absl::LogSeverity severity, absl::Time timestamp,\n                           log_internal::Tid tid, absl::Span<char>& buf) {\n  constexpr size_t kBoundedFieldsMaxLen =\n      sizeof(\"SMMDD HH:MM:SS.NNNNNN  \") +\n      (1 + std::numeric_limits<log_internal::Tid>::digits10 + 1) - sizeof(\"\");\n  if (ABSL_PREDICT_FALSE(buf.size() < kBoundedFieldsMaxLen)) {\n    // We don't bother trying to truncate these fields if the buffer is too\n    // short (or almost too short) because it would require doing a lot more\n    // length checking (slow) and it should never happen.  A 15kB buffer should\n    // be enough for anyone.  Instead we mark `buf` full without writing\n    // anything.\n    buf.remove_suffix(buf.size());\n    return 0;\n  }\n\n  // We can't call absl::LocalTime(), localtime_r(), or anything else here that\n  // isn't async-signal-safe. We can only use the time zone if it has already\n  // been loaded.\n  const absl::TimeZone* tz = absl::log_internal::TimeZone();\n  if (ABSL_PREDICT_FALSE(tz == nullptr)) {\n    // If a time zone hasn't been set yet because we are logging before the\n    // logging library has been initialized, we fallback to a simpler, slower\n    // method. Just report the raw Unix time in seconds. We cram this into the\n    // normal time format for the benefit of parsers.\n    auto tv = absl::ToTimeval(timestamp);\n    int snprintf_result = absl::SNPrintF(\n        buf.data(), buf.size(), \"%c0000 00:00:%02d.%06d %7d \",\n        absl::LogSeverityName(severity)[0], static_cast<int>(tv.tv_sec),\n        static_cast<int>(tv.tv_usec), static_cast<int>(tid));\n    if (snprintf_result >= 0) {\n      buf.remove_prefix(static_cast<size_t>(snprintf_result));\n      return static_cast<size_t>(snprintf_result);\n    }\n    return 0;\n  }\n\n  char* p = buf.data();\n  *p++ = absl::LogSeverityName(severity)[0];\n  const absl::TimeZone::CivilInfo ci = tz->At(timestamp);\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.month()), p);\n  p += 2;\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.day()), p);\n  p += 2;\n  *p++ = ' ';\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.hour()), p);\n  p += 2;\n  *p++ = ':';\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.minute()),\n                                       p);\n  p += 2;\n  *p++ = ':';\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.second()),\n                                       p);\n  p += 2;\n  *p++ = '.';\n  const int64_t usecs = absl::ToInt64Microseconds(ci.subsecond);\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs / 10000), p);\n  p += 2;\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs / 100 % 100),\n                                       p);\n  p += 2;\n  absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs % 100), p);\n  p += 2;\n  *p++ = ' ';\n  PutLeadingWhitespace(tid, p);\n  p = absl::numbers_internal::FastIntToBuffer(tid, p);\n  *p++ = ' ';\n  const size_t bytes_formatted = static_cast<size_t>(p - buf.data());\n  buf.remove_prefix(bytes_formatted);\n  return bytes_formatted;\n}\n\nsize_t FormatLineNumber(int line, absl::Span<char>& buf) {\n  constexpr size_t kLineFieldMaxLen =\n      sizeof(\":] \") + (1 + std::numeric_limits<int>::digits10 + 1) - sizeof(\"\");\n  if (ABSL_PREDICT_FALSE(buf.size() < kLineFieldMaxLen)) {\n    // As above, we don't bother trying to truncate this if the buffer is too\n    // short and it should never happen.\n    buf.remove_suffix(buf.size());\n    return 0;\n  }\n  char* p = buf.data();\n  *p++ = ':';\n  p = absl::numbers_internal::FastIntToBuffer(line, p);\n  *p++ = ']';\n  *p++ = ' ';\n  const size_t bytes_formatted = static_cast<size_t>(p - buf.data());\n  buf.remove_prefix(bytes_formatted);\n  return bytes_formatted;\n}\n\n}  // namespace\n\nstd::string FormatLogMessage(absl::LogSeverity severity,\n                             absl::CivilSecond civil_second,\n                             absl::Duration subsecond, log_internal::Tid tid,\n                             absl::string_view basename, int line,\n                             PrefixFormat format, absl::string_view message) {\n  return absl::StrFormat(\n      \"%c%02d%02d %02d:%02d:%02d.%06d %7d %s:%d] %s%s\",\n      absl::LogSeverityName(severity)[0], civil_second.month(),\n      civil_second.day(), civil_second.hour(), civil_second.minute(),\n      civil_second.second(), absl::ToInt64Microseconds(subsecond), tid,\n      basename, line, format == PrefixFormat::kRaw ? \"RAW: \" : \"\", message);\n}\n\n// This method is fairly hot, and the library always passes a huge `buf`, so we\n// save some bounds-checking cycles by not trying to do precise truncation.\n// Truncating at a field boundary is probably a better UX anyway.\n//\n// The prefix is written in three parts, each of which does a single\n// bounds-check and truncation:\n// 1. severity, timestamp, and thread ID\n// 2. filename\n// 3. line number and bracket\nsize_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,\n                       log_internal::Tid tid, absl::string_view basename,\n                       int line, PrefixFormat format, absl::Span<char>& buf) {\n  auto prefix_size = FormatBoundedFields(severity, timestamp, tid, buf);\n  prefix_size += log_internal::AppendTruncated(basename, buf);\n  prefix_size += FormatLineNumber(line, buf);\n  if (format == PrefixFormat::kRaw)\n    prefix_size += log_internal::AppendTruncated(\"RAW: \", buf);\n  return prefix_size;\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/log_format.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/log_format.h\n// -----------------------------------------------------------------------------\n//\n// This file declares routines implementing formatting of log message and log\n// prefix.\n\n#ifndef ABSL_LOG_INTERNAL_LOG_FORMAT_H_\n#define ABSL_LOG_INTERNAL_LOG_FORMAT_H_\n\n#include <stddef.h>\n\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/config.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/civil_time.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nenum class PrefixFormat {\n  kNotRaw,\n  kRaw,\n};\n\n// Formats log message based on provided data.\nstd::string FormatLogMessage(absl::LogSeverity severity,\n                             absl::CivilSecond civil_second,\n                             absl::Duration subsecond, log_internal::Tid tid,\n                             absl::string_view basename, int line,\n                             PrefixFormat format, absl::string_view message);\n\n// Formats various entry metadata into a text string meant for use as a\n// prefix on a log message string.  Writes into `buf`, advances `buf` to point\n// at the remainder of the buffer (i.e. past any written bytes), and returns the\n// number of bytes written.\n//\n// In addition to calling `buf->remove_prefix()` (or the equivalent), this\n// function may also do `buf->remove_suffix(buf->size())` in cases where no more\n// bytes (i.e. no message data) should be written into the buffer.  For example,\n// if the prefix ought to be:\n//   I0926 09:00:00.000000 1234567 foo.cc:123]\n// `buf` is too small, the function might fill the whole buffer:\n//   I0926 09:00:00.000000 1234\n// (note the apparrently incorrect thread ID), or it might write less:\n//   I0926 09:00:00.000000\n// In this case, it might also empty `buf` prior to returning to prevent\n// message data from being written into the space where a reader would expect to\n// see a thread ID.\nsize_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,\n                       log_internal::Tid tid, absl::string_view basename,\n                       int line, PrefixFormat format, absl::Span<char>& buf);\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_LOG_FORMAT_H_\n"
  },
  {
    "path": "absl/log/internal/log_impl.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_LOG_INTERNAL_LOG_IMPL_H_\n#define ABSL_LOG_INTERNAL_LOG_IMPL_H_\n\n#include \"absl/log/absl_vlog_is_on.h\"\n#include \"absl/log/internal/conditions.h\"\n#include \"absl/log/internal/log_message.h\"\n#include \"absl/log/internal/strip.h\"\n\n// ABSL_LOG()\n#define ABSL_LOG_INTERNAL_LOG_IMPL(severity)             \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n// ABSL_PLOG()\n#define ABSL_LOG_INTERNAL_PLOG_IMPL(severity)            \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()   \\\n          .WithPerror()\n\n// ABSL_DLOG()\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DLOG_IMPL(severity)            \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n#else\n#define ABSL_LOG_INTERNAL_DLOG_IMPL(severity)             \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n#endif\n\n// The `switch` ensures that this expansion is the beginning of a statement (as\n// opposed to an expression). The use of both `case 0` and `default` is to\n// suppress a compiler warning.\n#define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level)                     \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level)) \\\n  case 0:                                                              \\\n  default:                                                             \\\n    ABSL_LOG_INTERNAL_LOG_IF_IMPL(                                     \\\n        _INFO, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level))       \\\n        .WithVerbosity(absl_log_internal_verbose_level)\n\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level)                    \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level)) \\\n  case 0:                                                              \\\n  default:                                                             \\\n    ABSL_LOG_INTERNAL_DLOG_IF_IMPL(                                    \\\n        _INFO, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level))       \\\n        .WithVerbosity(absl_log_internal_verbose_level)\n#else\n#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level)                       \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level))    \\\n  case 0:                                                                 \\\n  default:                                                                \\\n    ABSL_LOG_INTERNAL_DLOG_IF_IMPL(                                       \\\n        _INFO, false && ABSL_VLOG_IS_ON(absl_log_internal_verbose_level)) \\\n        .WithVerbosity(absl_log_internal_verbose_level)\n#endif\n\n#define ABSL_LOG_INTERNAL_LOG_IF_IMPL(severity, condition)    \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n#define ABSL_LOG_INTERNAL_PLOG_IF_IMPL(severity, condition)   \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()        \\\n          .WithPerror()\n\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition)   \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n#else\n#define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition)              \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false && (condition)) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n#endif\n\n// ABSL_LOG_EVERY_N\n#define ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(severity, n)            \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n// ABSL_LOG_FIRST_N\n#define ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(severity, n)            \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n// ABSL_LOG_EVERY_POW_2\n#define ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(severity)           \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n// ABSL_LOG_EVERY_N_SEC\n#define ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(severity, n_seconds)           \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(severity, n)           \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()             \\\n          .WithPerror()\n\n#define ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(severity, n)           \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()             \\\n          .WithPerror()\n\n#define ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(severity)          \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()             \\\n          .WithPerror()\n\n#define ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(severity, n_seconds)          \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()                        \\\n          .WithPerror()\n\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)       \\\n  (EveryN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)       \\\n  (FirstN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)        \\\n  (EveryPow2) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true)                   \\\n  (EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#else  // def NDEBUG\n#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)      \\\n  (EveryN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)      \\\n  (FirstN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)       \\\n  (EveryPow2) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false)                  \\\n  (EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n#endif  // def NDEBUG\n\n#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n)            \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level))   \\\n  case 0:                                                                \\\n  default:                                                               \\\n    ABSL_LOG_INTERNAL_CONDITION_INFO(                                    \\\n        STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level))      \\\n  (EveryN, n) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \\\n      absl_log_internal_verbose_level)\n\n#define ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n)            \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level))   \\\n  case 0:                                                                \\\n  default:                                                               \\\n    ABSL_LOG_INTERNAL_CONDITION_INFO(                                    \\\n        STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level))      \\\n  (FirstN, n) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \\\n      absl_log_internal_verbose_level)\n\n#define ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level)           \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level))   \\\n  case 0:                                                                \\\n  default:                                                               \\\n    ABSL_LOG_INTERNAL_CONDITION_INFO(                                    \\\n        STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level))      \\\n  (EveryPow2) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \\\n      absl_log_internal_verbose_level)\n\n#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n_seconds) \\\n  switch (const int absl_log_internal_verbose_level = (verbose_level))    \\\n  case 0:                                                                 \\\n  default:                                                                \\\n    ABSL_LOG_INTERNAL_CONDITION_INFO(                                     \\\n        STATEFUL, ABSL_VLOG_IS_ON(absl_log_internal_verbose_level))       \\\n  (EveryNSec, n_seconds) ABSL_LOG_INTERNAL_LOG_INFO.InternalStream()      \\\n      .WithVerbosity(absl_log_internal_verbose_level)\n\n#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(severity, condition, n)   \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(severity, condition, n)   \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(severity, condition)  \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(severity, condition, \\\n                                                  n_seconds)           \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(          \\\n      EveryNSec, n_seconds) ABSL_LOG_INTERNAL_LOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(severity, condition, n)  \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()                  \\\n          .WithPerror()\n\n#define ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(severity, condition, n)  \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()                  \\\n          .WithPerror()\n\n#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(severity, condition) \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \\\n      ABSL_LOG_INTERNAL_LOG##severity.InternalStream()                  \\\n          .WithPerror()\n\n#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(severity, condition,      \\\n                                                   n_seconds)                \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(                \\\n      EveryNSec, n_seconds) ABSL_LOG_INTERNAL_LOG##severity.InternalStream() \\\n      .WithPerror()\n\n#ifndef NDEBUG\n#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n)  \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n)  \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \\\n      ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \\\n                                                   n_seconds)           \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(           \\\n      EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#else  // def NDEBUG\n#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n)   \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \\\n      EveryN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n)   \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \\\n      FirstN, n) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition)  \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \\\n      EveryPow2) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n\n#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition,  \\\n                                                   n_seconds)            \\\n  ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \\\n      EveryNSec, n_seconds) ABSL_LOG_INTERNAL_DLOG##severity.InternalStream()\n#endif  // def NDEBUG\n\n#endif  // ABSL_LOG_INTERNAL_LOG_IMPL_H_\n"
  },
  {
    "path": "absl/log/internal/log_message.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/log_message.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifndef _WIN32\n#include <unistd.h>\n#endif\n\n#include <algorithm>\n#include <array>\n#include <atomic>\n#include <ios>\n#include <memory>\n#include <ostream>\n#include <string>\n#include <string_view>\n#include <tuple>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/strerror.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/debugging/internal/examine_stack.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/append_truncated.h\"\n#include \"absl/log/internal/globals.h\"\n#include \"absl/log/internal/log_format.h\"\n#include \"absl/log/internal/log_sink_set.h\"\n#include \"absl/log/internal/nullguard.h\"\n#include \"absl/log/internal/proto.h\"\n#include \"absl/log/internal/structured_proto.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/log/log_sink_registry.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/internal/utf8.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nextern \"C\" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(\n    AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {\n  // Default - Do nothing\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nnamespace {\n// message `logging.proto.Event`\nenum EventTag : uint8_t {\n  kFileName = 2,\n  kFileLine = 3,\n  kTimeNsecs = 4,\n  kSeverity = 5,\n  kThreadId = 6,\n  kValue = 7,\n  kSequenceNumber = 9,\n  kThreadName = 10,\n};\n\n// message `logging.proto.Value`\nenum ValueTag : uint8_t {\n  kString = 1,\n  kStringLiteral = 6,\n};\n\n// Decodes a `logging.proto.Value` from `buf` and writes a string representation\n// into `dst`.  The string representation will be truncated if `dst` is not\n// large enough to hold it.  Returns false if `dst` has size zero or one (i.e.\n// sufficient only for a nul-terminator) and no decoded data could be written.\n// This function may or may not write a nul-terminator into `dst`, and it may or\n// may not truncate the data it writes in order to do make space for that nul\n// terminator.  In any case, `dst` will be advanced to point at the byte where\n// subsequent writes should begin.\nbool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {\n  if (dst.size() <= 1) return false;\n  ProtoField field;\n  while (field.DecodeFrom(&buf)) {\n    switch (field.tag()) {\n      case ValueTag::kString:\n      case ValueTag::kStringLiteral:\n        if (field.type() == WireType::kLengthDelimited)\n          if (log_internal::AppendTruncated(field.string_value(), dst) <\n              field.string_value().size())\n            return false;\n    }\n  }\n  return true;\n}\n\n// See `logging.proto.Severity`\nint32_t ProtoSeverity(absl::LogSeverity severity, int verbose_level) {\n  switch (severity) {\n    case absl::LogSeverity::kInfo:\n      if (verbose_level == absl::LogEntry::kNoVerbosityLevel) return 800;\n      return 600 - verbose_level;\n    case absl::LogSeverity::kWarning:\n      return 900;\n    case absl::LogSeverity::kError:\n      return 950;\n    case absl::LogSeverity::kFatal:\n      return 1100;\n    default:\n      return 800;\n  }\n}\n\nabsl::string_view Basename(absl::string_view filepath) {\n#ifdef _WIN32\n  size_t path = filepath.find_last_of(\"/\\\\\");\n#else\n  size_t path = filepath.find_last_of('/');\n#endif\n  if (path != filepath.npos) filepath.remove_prefix(path + 1);\n  return filepath;\n}\n\nvoid WriteToString(const char* data, void* str) {\n  reinterpret_cast<std::string*>(str)->append(data);\n}\nvoid WriteToStream(const char* data, void* os) {\n  auto* cast_os = static_cast<std::ostream*>(os);\n  *cast_os << data;\n}\n}  // namespace\n\nstruct LogMessage::LogMessageData final {\n  LogMessageData(absl::string_view file, int line,\n                 absl::LogSeverity severity, absl::Time timestamp);\n  LogMessageData(const LogMessageData&) = delete;\n  LogMessageData& operator=(const LogMessageData&) = delete;\n\n  // `LogEntry` sent to `LogSink`s; contains metadata.\n  absl::LogEntry entry;\n\n  // true => this was first fatal msg\n  bool first_fatal;\n  // true => all failures should be quiet\n  bool fail_quietly;\n  // true => PLOG was requested\n  bool is_perror;\n\n  // Extra `LogSink`s to log to, in addition to `global_sinks`.\n  absl::InlinedVector<absl::LogSink* absl_nonnull, 16> extra_sinks;\n  // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded\n  // non-sink targets (e.g. stderr, log files).\n  bool extra_sinks_only;\n\n  std::ostream manipulated;  // ostream with IO manipulators applied\n\n  // A `logging.proto.Event` proto message is built into `encoded_buf`.\n  std::array<char, kLogMessageBufferSize> encoded_buf;\n  // `encoded_remaining()` is the suffix of `encoded_buf` that has not been\n  // filled yet.  If a datum to be encoded does not fit into\n  // `encoded_remaining()` and cannot be truncated to fit, the size of\n  // `encoded_remaining()` will be zeroed to prevent encoding of any further\n  // data.  Note that in this case its `data()` pointer will not point past the\n  // end of `encoded_buf`.\n  // The first use of `encoded_remaining()` is our chance to record metadata\n  // after any modifications (e.g. by `AtLocation()`) but before any data have\n  // been recorded.  We want to record metadata before data so that data are\n  // preferentially truncated if we run out of buffer.\n  absl::Span<char>& encoded_remaining() {\n    if (encoded_remaining_actual_do_not_use_directly.data() == nullptr) {\n      encoded_remaining_actual_do_not_use_directly =\n          absl::MakeSpan(encoded_buf);\n      InitializeEncodingAndFormat();\n    }\n    return encoded_remaining_actual_do_not_use_directly;\n  }\n  absl::Span<char> encoded_remaining_actual_do_not_use_directly;\n\n  // A formatted string message is built in `string_buf`.\n  std::array<char, kLogMessageBufferSize> string_buf;\n\n  void InitializeEncodingAndFormat();\n  void FinalizeEncodingAndFormat();\n};\n\nLogMessage::LogMessageData::LogMessageData(absl::string_view file,\n                                           int line, absl::LogSeverity severity,\n                                           absl::Time timestamp)\n    : extra_sinks_only(false), manipulated(nullptr) {\n  // Legacy defaults for LOG's ostream:\n  manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);\n  entry.full_filename_ = file;\n  entry.base_filename_ = Basename(file);\n  entry.line_ = line;\n  entry.prefix_ = absl::ShouldPrependLogPrefix();\n  entry.severity_ = absl::NormalizeLogSeverity(severity);\n  entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;\n  entry.timestamp_ = timestamp;\n  entry.tid_ = absl::base_internal::GetCachedTID();\n}\n\nvoid LogMessage::LogMessageData::InitializeEncodingAndFormat() {\n  EncodeStringTruncate(EventTag::kFileName, entry.source_filename(),\n                       &encoded_remaining());\n  EncodeVarint(EventTag::kFileLine, entry.source_line(), &encoded_remaining());\n  EncodeVarint(EventTag::kTimeNsecs, absl::ToUnixNanos(entry.timestamp()),\n               &encoded_remaining());\n  EncodeVarint(EventTag::kSeverity,\n               ProtoSeverity(entry.log_severity(), entry.verbosity()),\n               &encoded_remaining());\n  EncodeVarint(EventTag::kThreadId, static_cast<uint64_t>(entry.tid()),\n               &encoded_remaining());\n}\n\nvoid LogMessage::LogMessageData::FinalizeEncodingAndFormat() {\n  // Note that `encoded_remaining()` may have zero size without pointing past\n  // the end of `encoded_buf`, so the difference between `data()` pointers is\n  // used to compute the size of `encoded_data`.\n  absl::Span<const char> encoded_data(\n      encoded_buf.data(),\n      static_cast<size_t>(encoded_remaining().data() - encoded_buf.data()));\n  // `string_remaining` is the suffix of `string_buf` that has not been filled\n  // yet.\n  absl::Span<char> string_remaining(string_buf);\n  // We may need to write a newline and nul-terminator at the end of the decoded\n  // string data.  Rather than worry about whether those should overwrite the\n  // end of the string (if the buffer is full) or be appended, we avoid writing\n  // into the last two bytes so we always have space to append.\n  string_remaining.remove_suffix(2);\n  entry.prefix_len_ =\n      entry.prefix() ? log_internal::FormatLogPrefix(\n                           entry.log_severity(), entry.timestamp(), entry.tid(),\n                           entry.source_basename(), entry.source_line(),\n                           log_internal::ThreadIsLoggingToLogSink()\n                               ? PrefixFormat::kRaw\n                               : PrefixFormat::kNotRaw,\n                           string_remaining)\n                     : 0;\n  // Decode data from `encoded_buf` until we run out of data or we run out of\n  // `string_remaining`.\n  ProtoField field;\n  while (field.DecodeFrom(&encoded_data)) {\n    switch (field.tag()) {\n      case EventTag::kValue:\n        if (field.type() != WireType::kLengthDelimited) continue;\n        if (PrintValue(string_remaining, field.bytes_value())) continue;\n        break;\n    }\n  }\n  auto chars_written =\n      static_cast<size_t>(string_remaining.data() - string_buf.data());\n    string_buf[chars_written++] = '\\n';\n  string_buf[chars_written++] = '\\0';\n  entry.text_message_with_prefix_and_newline_and_nul_ =\n      absl::MakeSpan(string_buf).subspan(0, chars_written);\n}\n\nLogMessage::LogMessage(const char* absl_nonnull file, int line,\n                       absl::LogSeverity severity)\n  : LogMessage(absl::string_view(file), line, severity) {}\nLogMessage::LogMessage(absl::string_view file, int line,\n                       absl::LogSeverity severity)\n    : data_(absl::make_unique<LogMessageData>(file, line, severity,\n                                              absl::Now())) {\n  data_->first_fatal = false;\n  data_->is_perror = false;\n  data_->fail_quietly = false;\n\n  // This logs a backtrace even if the location is subsequently changed using\n  // AtLocation.  This quirk, and the behavior when AtLocation is called twice,\n  // are fixable but probably not worth fixing.\n  LogBacktraceIfNeeded();\n}\n\nLogMessage::LogMessage(const char* absl_nonnull file, int line, InfoTag)\n    : LogMessage(file, line, absl::LogSeverity::kInfo) {}\nLogMessage::LogMessage(const char* absl_nonnull file, int line, WarningTag)\n    : LogMessage(file, line, absl::LogSeverity::kWarning) {}\nLogMessage::LogMessage(const char* absl_nonnull file, int line, ErrorTag)\n    : LogMessage(file, line, absl::LogSeverity::kError) {}\n\n// This cannot go in the header since LogMessageData is defined in this file.\nLogMessage::~LogMessage() = default;\n\nLogMessage& LogMessage::AtLocation(absl::string_view file, int line) {\n  data_->entry.full_filename_ = file;\n  data_->entry.base_filename_ = Basename(file);\n  data_->entry.line_ = line;\n  LogBacktraceIfNeeded();\n  return *this;\n}\n\nLogMessage& LogMessage::NoPrefix() {\n  data_->entry.prefix_ = false;\n  return *this;\n}\n\nLogMessage& LogMessage::WithVerbosity(int verbose_level) {\n  if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {\n    data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;\n  } else {\n    data_->entry.verbose_level_ = std::max(0, verbose_level);\n  }\n  return *this;\n}\n\nLogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {\n  data_->entry.timestamp_ = timestamp;\n  return *this;\n}\n\nLogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {\n  data_->entry.tid_ = tid;\n  return *this;\n}\n\nLogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {\n  data_->entry.full_filename_ = entry.full_filename_;\n  data_->entry.base_filename_ = entry.base_filename_;\n  data_->entry.line_ = entry.line_;\n  data_->entry.prefix_ = entry.prefix_;\n  data_->entry.severity_ = entry.severity_;\n  data_->entry.verbose_level_ = entry.verbose_level_;\n  data_->entry.timestamp_ = entry.timestamp_;\n  data_->entry.tid_ = entry.tid_;\n  return *this;\n}\n\nLogMessage& LogMessage::WithPerror() {\n  data_->is_perror = true;\n  return *this;\n}\n\nLogMessage& LogMessage::ToSinkAlso(absl::LogSink* absl_nonnull sink) {\n  ABSL_INTERNAL_CHECK(sink, \"null LogSink*\");\n  data_->extra_sinks.push_back(sink);\n  return *this;\n}\n\nLogMessage& LogMessage::ToSinkOnly(absl::LogSink* absl_nonnull sink) {\n  ABSL_INTERNAL_CHECK(sink, \"null LogSink*\");\n  data_->extra_sinks.clear();\n  data_->extra_sinks.push_back(sink);\n  data_->extra_sinks_only = true;\n  return *this;\n}\n\n#ifdef __ELF__\nextern \"C\" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;\nextern \"C\" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;\n#endif\n\nvoid LogMessage::FailWithoutStackTrace() {\n  // Now suppress repeated trace logging:\n  log_internal::SetSuppressSigabortTrace(true);\n#if defined _DEBUG && defined COMPILER_MSVC\n  // When debugging on windows, avoid the obnoxious dialog.\n  __debugbreak();\n#endif\n\n#ifdef __ELF__\n  // For b/8737634, flush coverage if we are in coverage mode.\n  if (&__gcov_dump != nullptr) {\n    __gcov_dump();\n  } else if (&__gcov_flush != nullptr) {\n    __gcov_flush();\n  }\n#endif\n\n  abort();\n}\n\nvoid LogMessage::FailQuietly() {\n  // _exit. Calling abort() would trigger all sorts of death signal handlers\n  // and a detailed stack trace. Calling exit() would trigger the onexit\n  // handlers, including the heap-leak checker, which is guaranteed to fail in\n  // this case: we probably just new'ed the std::string that we logged.\n  // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out\n  // of the program quickly, and it doesn't make much sense for FailQuietly to\n  // offer different guarantees about exit behavior than Fail does. (And as a\n  // consequence for QCHECK and CHECK to offer different exit behaviors)\n  _exit(1);\n}\n\nLogMessage& LogMessage::operator<<(const std::string& v) {\n  CopyToEncodedBuffer<StringType::kNotLiteral>(v);\n  return *this;\n}\n\nLogMessage& LogMessage::operator<<(absl::string_view v) {\n  CopyToEncodedBuffer<StringType::kNotLiteral>(v);\n  return *this;\n}\n\nLogMessage& LogMessage::operator<<(const std::wstring& v) {\n  CopyToEncodedBuffer<StringType::kNotLiteral>(v);\n  return *this;\n}\n\nLogMessage& LogMessage::operator<<(std::wstring_view v) {\n  CopyToEncodedBuffer<StringType::kNotLiteral>(v);\n  return *this;\n}\n\ntemplate <>\nLogMessage& LogMessage::operator<< <const wchar_t*>(\n    const wchar_t* absl_nullable const& v) {\n  if (v == nullptr) {\n    CopyToEncodedBuffer<StringType::kNotLiteral>(\n        absl::string_view(kCharNull.data(), kCharNull.size() - 1));\n  } else {\n    CopyToEncodedBuffer<StringType::kNotLiteral>(v);\n  }\n  return *this;\n}\n\nLogMessage& LogMessage::operator<<(wchar_t v) {\n  CopyToEncodedBuffer<StringType::kNotLiteral>(std::wstring_view(&v, 1));\n  return *this;\n}\n\nLogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {\n  OstreamView view(*data_);\n  data_->manipulated << m;\n  return *this;\n}\nLogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {\n  OstreamView view(*data_);\n  data_->manipulated << m;\n  return *this;\n}\n// NOLINTBEGIN(runtime/int)\n// NOLINTBEGIN(google-runtime-int)\ntemplate LogMessage& LogMessage::operator<<(const char& v);\ntemplate LogMessage& LogMessage::operator<<(const signed char& v);\ntemplate LogMessage& LogMessage::operator<<(const unsigned char& v);\ntemplate LogMessage& LogMessage::operator<<(const short& v);\ntemplate LogMessage& LogMessage::operator<<(const unsigned short& v);\ntemplate LogMessage& LogMessage::operator<<(const int& v);\ntemplate LogMessage& LogMessage::operator<<(const unsigned int& v);\ntemplate LogMessage& LogMessage::operator<<(const long& v);\ntemplate LogMessage& LogMessage::operator<<(const unsigned long& v);\ntemplate LogMessage& LogMessage::operator<<(const long long& v);\ntemplate LogMessage& LogMessage::operator<<(const unsigned long long& v);\ntemplate LogMessage& LogMessage::operator<<(void* const& v);\ntemplate LogMessage& LogMessage::operator<<(const void* const& v);\ntemplate LogMessage& LogMessage::operator<<(const float& v);\ntemplate LogMessage& LogMessage::operator<<(const double& v);\ntemplate LogMessage& LogMessage::operator<<(const bool& v);\n// NOLINTEND(google-runtime-int)\n// NOLINTEND(runtime/int)\n\nvoid LogMessage::Flush() {\n  if (data_->entry.log_severity() < absl::MinLogLevel()) return;\n\n  if (data_->is_perror) {\n    InternalStream() << \": \" << absl::base_internal::StrError(errno_saver_())\n                     << \" [\" << errno_saver_() << \"]\";\n  }\n\n  // Have we already seen a fatal message?\n  ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);\n  if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&\n      absl::log_internal::ExitOnDFatal()) {\n    // Exactly one LOG(FATAL) message is responsible for aborting the process,\n    // even if multiple threads LOG(FATAL) concurrently.\n    bool expected_seen_fatal = false;\n    if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,\n                                           std::memory_order_relaxed)) {\n      data_->first_fatal = true;\n    }\n  }\n\n  data_->FinalizeEncodingAndFormat();\n  data_->entry.encoding_ =\n      absl::string_view(data_->encoded_buf.data(),\n                        static_cast<size_t>(data_->encoded_remaining().data() -\n                                            data_->encoded_buf.data()));\n  SendToLog();\n}\n\nvoid LogMessage::SetFailQuietly() { data_->fail_quietly = true; }\n\nLogMessage::OstreamView::OstreamView(LogMessageData& message_data)\n    : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining()) {\n  // This constructor sets the `streambuf` up so that streaming into an attached\n  // ostream encodes string data in-place.  To do that, we write appropriate\n  // headers into the buffer using a copy of the buffer view so that we can\n  // decide not to keep them later if nothing is ever streamed in.  We don't\n  // know how much data we'll get, but we can use the size of the remaining\n  // buffer as an upper bound and fill in the right size once we know it.\n  message_start_ =\n      EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),\n                         &encoded_remaining_copy_);\n  string_start_ =\n      EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),\n                         &encoded_remaining_copy_);\n  setp(encoded_remaining_copy_.data(),\n       encoded_remaining_copy_.data() + encoded_remaining_copy_.size());\n  data_.manipulated.rdbuf(this);\n}\n\nLogMessage::OstreamView::~OstreamView() {\n  data_.manipulated.rdbuf(nullptr);\n  if (!string_start_.data()) {\n    // The second field header didn't fit.  Whether the first one did or not, we\n    // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the\n    // size of `data_->encoded_remaining()` so that no more data are encoded.\n    data_.encoded_remaining().remove_suffix(data_.encoded_remaining().size());\n    return;\n  }\n  const absl::Span<const char> contents(pbase(),\n                                        static_cast<size_t>(pptr() - pbase()));\n  if (contents.empty()) return;\n  encoded_remaining_copy_.remove_prefix(contents.size());\n  EncodeMessageLength(string_start_, &encoded_remaining_copy_);\n  EncodeMessageLength(message_start_, &encoded_remaining_copy_);\n  data_.encoded_remaining() = encoded_remaining_copy_;\n}\n\nstd::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }\n\nbool LogMessage::IsFatal() const {\n  return data_->entry.log_severity() == absl::LogSeverity::kFatal &&\n         absl::log_internal::ExitOnDFatal();\n}\n\nvoid LogMessage::PrepareToDie() {\n  // If we log a FATAL message, flush all the log destinations, then toss\n  // a signal for others to catch. We leave the logs in a state that\n  // someone else can use them (as long as they flush afterwards)\n  if (data_->first_fatal) {\n    // Notify observers about the upcoming fatal error.\n    ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);\n  }\n\n  if (!data_->fail_quietly) {\n    // Log the message first before we start collecting stack trace.\n    log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),\n                             data_->extra_sinks_only);\n\n    // `DumpStackTrace` generates an empty string under MSVC.\n    // Adding the constant prefix here simplifies testing.\n    data_->entry.stacktrace_ = \"*** Check failure stack trace: ***\\n\";\n    debugging_internal::DumpStackTrace(\n        0, log_internal::MaxFramesInLogStackTrace(),\n        log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,\n        &data_->entry.stacktrace_);\n  }\n}\n\nvoid LogMessage::Die() {\n  absl::FlushLogSinks();\n\n  if (data_->fail_quietly) {\n    FailQuietly();\n  } else {\n    FailWithoutStackTrace();\n  }\n}\n\nvoid LogMessage::SendToLog() {\n  if (IsFatal()) PrepareToDie();\n  // Also log to all registered sinks, even if OnlyLogToStderr() is set.\n  log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),\n                           data_->extra_sinks_only);\n  if (IsFatal()) Die();\n}\n\nvoid LogMessage::LogBacktraceIfNeeded() {\n  if (!absl::log_internal::IsInitialized()) return;\n\n  if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),\n                                                data_->entry.source_line()))\n    return;\n  OstreamView view(*data_);\n  view.stream() << \" (stacktrace:\\n\";\n  debugging_internal::DumpStackTrace(\n      1, log_internal::MaxFramesInLogStackTrace(),\n      log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,\n      &view.stream());\n  view.stream() << \") \";\n}\n\n// Encodes into `data_->encoded_remaining()` a partial `logging.proto.Event`\n// containing the specified string data using a `Value` field appropriate to\n// `str_type`.  Truncates `str` if necessary, but emits nothing and marks the\n// buffer full if  even the field headers do not fit.\ntemplate <LogMessage::StringType str_type>\nvoid LogMessage::CopyToEncodedBuffer(absl::string_view str) {\n  auto encoded_remaining_copy = data_->encoded_remaining();\n  constexpr uint8_t tag_value = str_type == StringType::kLiteral\n                                    ? ValueTag::kStringLiteral\n                                    : ValueTag::kString;\n  auto start = EncodeMessageStart(\n      EventTag::kValue,\n      BufferSizeFor(tag_value, WireType::kLengthDelimited) + str.size(),\n      &encoded_remaining_copy);\n  // If the `logging.proto.Event.value` field header did not fit,\n  // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and\n  // `EncodeStringTruncate` will fail too.\n  if (EncodeStringTruncate(tag_value, str, &encoded_remaining_copy)) {\n    // The string may have been truncated, but the field header fit.\n    EncodeMessageLength(start, &encoded_remaining_copy);\n    data_->encoded_remaining() = encoded_remaining_copy;\n  } else {\n    // The field header(s) did not fit; zero `encoded_remaining()` so we don't\n    // write anything else later.\n    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());\n  }\n}\ntemplate void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(\n    absl::string_view str);\ntemplate void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kNotLiteral>(absl::string_view str);\ntemplate <LogMessage::StringType str_type>\nvoid LogMessage::CopyToEncodedBuffer(char ch, size_t num) {\n  auto encoded_remaining_copy = data_->encoded_remaining();\n  constexpr uint8_t tag_value = str_type == StringType::kLiteral\n                                    ? ValueTag::kStringLiteral\n                                    : ValueTag::kString;\n  auto value_start = EncodeMessageStart(\n      EventTag::kValue,\n      BufferSizeFor(tag_value, WireType::kLengthDelimited) + num,\n      &encoded_remaining_copy);\n  auto str_start = EncodeMessageStart(tag_value, num, &encoded_remaining_copy);\n  if (str_start.data()) {\n    // The field headers fit.\n    log_internal::AppendTruncated(ch, num, encoded_remaining_copy);\n    EncodeMessageLength(str_start, &encoded_remaining_copy);\n    EncodeMessageLength(value_start, &encoded_remaining_copy);\n    data_->encoded_remaining() = encoded_remaining_copy;\n  } else {\n    // The field header(s) did not fit; zero `encoded_remaining()` so we don't\n    // write anything else later.\n    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());\n  }\n}\ntemplate void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(\n    char ch, size_t num);\ntemplate void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kNotLiteral>(char ch, size_t num);\n\ntemplate <LogMessage::StringType str_type>\nvoid LogMessage::CopyToEncodedBuffer(std::wstring_view str) {\n  auto encoded_remaining_copy = data_->encoded_remaining();\n  constexpr uint8_t tag_value = str_type == StringType::kLiteral\n                                    ? ValueTag::kStringLiteral\n                                    : ValueTag::kString;\n  size_t max_str_byte_length =\n      absl::strings_internal::kMaxEncodedUTF8Size * str.length();\n  auto value_start =\n      EncodeMessageStart(EventTag::kValue,\n                         BufferSizeFor(tag_value, WireType::kLengthDelimited) +\n                             max_str_byte_length,\n                         &encoded_remaining_copy);\n  auto str_start = EncodeMessageStart(tag_value, max_str_byte_length,\n                                      &encoded_remaining_copy);\n  if (str_start.data()) {\n    log_internal::AppendTruncated(str, encoded_remaining_copy);\n    EncodeMessageLength(str_start, &encoded_remaining_copy);\n    EncodeMessageLength(value_start, &encoded_remaining_copy);\n    data_->encoded_remaining() = encoded_remaining_copy;\n  } else {\n    // The field header(s) did not fit; zero `encoded_remaining()` so we don't\n    // write anything else later.\n    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());\n  }\n}\ntemplate void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(\n    std::wstring_view str);\ntemplate void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kNotLiteral>(std::wstring_view str);\n\ntemplate void LogMessage::CopyToEncodedBufferWithStructuredProtoField<\n    LogMessage::StringType::kLiteral>(StructuredProtoField field,\n                                      absl::string_view str);\ntemplate void LogMessage::CopyToEncodedBufferWithStructuredProtoField<\n    LogMessage::StringType::kNotLiteral>(StructuredProtoField field,\n                                         absl::string_view str);\n\ntemplate <LogMessage::StringType str_type>\nvoid LogMessage::CopyToEncodedBufferWithStructuredProtoField(\n    StructuredProtoField field, absl::string_view str) {\n  auto encoded_remaining_copy = data_->encoded_remaining();\n  size_t encoded_field_size = BufferSizeForStructuredProtoField(field);\n  constexpr uint8_t tag_value = str_type == StringType::kLiteral\n                                    ? ValueTag::kStringLiteral\n                                    : ValueTag::kString;\n  auto start = EncodeMessageStart(\n      EventTag::kValue,\n      encoded_field_size +\n          BufferSizeFor(tag_value, WireType::kLengthDelimited) + str.size(),\n      &encoded_remaining_copy);\n\n  // Write the encoded proto field.\n  if (!EncodeStructuredProtoField(field, encoded_remaining_copy)) {\n    // The header / field will not fit; zero `encoded_remaining()` so we\n    // don't write anything else later.\n    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());\n    return;\n  }\n\n  // Write the string, truncating if necessary.\n  if (!EncodeStringTruncate(ValueTag::kString, str, &encoded_remaining_copy)) {\n    // The length of the string itself did not fit; zero `encoded_remaining()`\n    // so the value is not encoded at all.\n    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());\n    return;\n  }\n\n  EncodeMessageLength(start, &encoded_remaining_copy);\n  data_->encoded_remaining() = encoded_remaining_copy;\n}\n\n// We intentionally don't return from these destructors. Disable MSVC's warning\n// about the destructor never returning as we do so intentionally here.\n#if defined(_MSC_VER) && !defined(__clang__)\n#pragma warning(push)\n#pragma warning(disable : 4722)\n#endif\n\nLogMessageFatal::LogMessageFatal(const char* absl_nonnull file, int line)\n    : LogMessage(file, line, absl::LogSeverity::kFatal) {}\n\nLogMessageFatal::LogMessageFatal(const char* absl_nonnull file, int line,\n                                 const char* absl_nonnull failure_msg)\n    : LogMessage(file, line, absl::LogSeverity::kFatal) {\n  *this << \"Check failed: \" << failure_msg << \" \";\n}\n\nLogMessageFatal::~LogMessageFatal() { FailWithoutStackTrace(); }\n\nLogMessageDebugFatal::LogMessageDebugFatal(const char* absl_nonnull file,\n                                           int line)\n    : LogMessage(file, line, absl::LogSeverity::kFatal) {}\n\nLogMessageDebugFatal::~LogMessageDebugFatal() { FailWithoutStackTrace(); }\n\nLogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal(\n    const char* absl_nonnull file, int line)\n    : LogMessage(file, line, absl::LogSeverity::kFatal) {\n  SetFailQuietly();\n}\n\nLogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() { FailQuietly(); }\n\nLogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* absl_nonnull file,\n                                               int line)\n    : LogMessage(file, line, absl::LogSeverity::kFatal) {\n  SetFailQuietly();\n}\n\nLogMessageQuietlyFatal::LogMessageQuietlyFatal(\n    const char* absl_nonnull file, int line,\n    const char* absl_nonnull failure_msg)\n    : LogMessageQuietlyFatal(file, line) {\n  *this << \"Check failed: \" << failure_msg << \" \";\n}\n\nLogMessageQuietlyFatal::~LogMessageQuietlyFatal() { FailQuietly(); }\n#if defined(_MSC_VER) && !defined(__clang__)\n#pragma warning(pop)\n#endif\n\n}  // namespace log_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/log_message.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/log_message.h\n// -----------------------------------------------------------------------------\n//\n// This file declares `class absl::log_internal::LogMessage`. This class more or\n// less represents a particular log message. LOG/CHECK macros create a temporary\n// instance of `LogMessage` and then stream values to it.  At the end of the\n// LOG/CHECK statement, the LogMessage is voidified by operator&&, and `Flush()`\n// directs the message to the registered log sinks.  Heap-allocation of\n// `LogMessage` is unsupported.  Construction outside of a `LOG` macro is\n// unsupported.\n\n#ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_\n#define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_\n\n#include <wchar.h>\n\n#include <cstddef>\n#include <ios>\n#include <memory>\n#include <ostream>\n#include <streambuf>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/errno_saver.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/log/internal/nullguard.h\"\n#include \"absl/log/internal/structured_proto.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/strings/has_absl_stringify.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nconstexpr int kLogMessageBufferSize = 15000;\n\nenum class StructuredStringType;\n\nclass LogMessage {\n public:\n  struct InfoTag {};\n  struct WarningTag {};\n  struct ErrorTag {};\n\n  // Used for `LOG`.  Taking `const char *` instead of `string_view` keeps\n  // callsites a little bit smaller at the cost of doing `strlen` at runtime.\n  LogMessage(const char* absl_nonnull file, int line,\n             absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;\n  // Used for FFI integrations that don't have a NUL-terminated string.\n  LogMessage(absl::string_view file, int line,\n             absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;\n  // These constructors are slightly smaller/faster to call; the severity is\n  // curried into the function pointer.\n  LogMessage(const char* absl_nonnull file, int line,\n             InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;\n  LogMessage(const char* absl_nonnull file, int line,\n             WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;\n  LogMessage(const char* absl_nonnull file, int line,\n             ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;\n  LogMessage(const LogMessage&) = delete;\n  LogMessage& operator=(const LogMessage&) = delete;\n  ~LogMessage() ABSL_ATTRIBUTE_COLD;\n\n  // Overrides the location inferred from the callsite.  The string pointed to\n  // by `file` must be valid until the end of the statement.\n  LogMessage& AtLocation(absl::string_view file, int line);\n  // `loc` doesn't default to `absl::SourceLocation::current()` here since the\n  // callsite is already the default location for `LOG` statements.\n  LogMessage& AtLocation(absl::SourceLocation loc) {\n    return AtLocation(loc.file_name(), static_cast<int>(loc.line()));\n  }\n  // Omits the prefix from this line.  The prefix includes metadata about the\n  // logged data such as source code location and timestamp.\n  LogMessage& NoPrefix();\n  // Sets the verbosity field of the logged message as if it was logged by\n  // `VLOG(verbose_level)`.  Unlike `VLOG`, this method does not affect\n  // evaluation of the statement when the specified `verbose_level` has been\n  // disabled.  The only effect is on `absl::LogSink` implementations which\n  // make use of the `absl::LogSink::verbosity()` value.  The value\n  // `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message\n  // not verbose.\n  LogMessage& WithVerbosity(int verbose_level);\n  // Uses the specified timestamp instead of one collected in the constructor.\n  LogMessage& WithTimestamp(absl::Time timestamp);\n  // Uses the specified thread ID instead of one collected in the constructor.\n  LogMessage& WithThreadID(absl::LogEntry::tid_t tid);\n  // Copies all metadata (but no data) from the specified `absl::LogEntry`.\n  LogMessage& WithMetadataFrom(const absl::LogEntry& entry);\n  // Appends to the logged message a colon, a space, a textual description of\n  // the current value of `errno` (as by strerror(3)), and the numerical value\n  // of `errno`.\n  LogMessage& WithPerror();\n  // Sends this message to `*sink` in addition to whatever other sinks it would\n  // otherwise have been sent to.\n  LogMessage& ToSinkAlso(absl::LogSink* absl_nonnull sink);\n  // Sends this message to `*sink` and no others.\n  LogMessage& ToSinkOnly(absl::LogSink* absl_nonnull sink);\n\n  // Don't call this method from outside this library.\n  LogMessage& InternalStream() { return *this; }\n\n  // By-value overloads for small, common types let us overlook common failures\n  // to define globals and static data members (i.e. in a .cc file).\n  // NOLINTBEGIN(runtime/int)\n  // NOLINTBEGIN(google-runtime-int)\n  // clang-format off:  The CUDA toolchain cannot handle these <<<'s\n  LogMessage& operator<<(char v) { return operator<< <char>(v); }\n  LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }\n  LogMessage& operator<<(unsigned char v) {\n    return operator<< <unsigned char>(v);\n  }\n  LogMessage& operator<<(signed short v) {\n    return operator<< <signed short>(v);\n  }\n  LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }\n  LogMessage& operator<<(signed long v) {\n    return operator<< <signed long>(v);\n  }\n  LogMessage& operator<<(signed long long v) {\n    return operator<< <signed long long>(v);\n  }\n  LogMessage& operator<<(unsigned short v) {\n    return operator<< <unsigned short>(v);\n  }\n  LogMessage& operator<<(unsigned int v) {\n    return operator<< <unsigned int>(v);\n  }\n  LogMessage& operator<<(unsigned long v) {\n    return operator<< <unsigned long>(v);\n  }\n  LogMessage& operator<<(unsigned long long v) {\n    return operator<< <unsigned long long>(v);\n  }\n  LogMessage& operator<<(void* absl_nullable  v) {\n    return operator<< <void*>(v);\n  }\n  LogMessage& operator<<(const void* absl_nullable  v) {\n    return operator<< <const void*>(v);\n  }\n  LogMessage& operator<<(float v) { return operator<< <float>(v); }\n  LogMessage& operator<<(double v) { return operator<< <double>(v); }\n  LogMessage& operator<<(bool v) { return operator<< <bool>(v); }\n  // clang-format on\n  // NOLINTEND(google-runtime-int)\n  // NOLINTEND(runtime/int)\n\n  // These overloads are more efficient since no `ostream` is involved.\n  LogMessage& operator<<(const std::string& v);\n  LogMessage& operator<<(absl::string_view v);\n\n  // Wide string overloads (since std::ostream does not provide them).\n  LogMessage& operator<<(const std::wstring& v);\n  LogMessage& operator<<(std::wstring_view v);\n  // `const wchar_t*` is handled by `operator<< <const wchar_t*>`.\n  LogMessage& operator<<(wchar_t* absl_nullable v);\n  LogMessage& operator<<(wchar_t v);\n\n  // Handle stream manipulators e.g. std::endl.\n  LogMessage& operator<<(std::ostream& (*absl_nonnull m)(std::ostream& os));\n  LogMessage& operator<<(std::ios_base& (*absl_nonnull m)(std::ios_base& os));\n\n  // Literal strings.  This allows us to record C string literals as literals in\n  // the logging.proto.Value.\n  //\n  // Allow this overload to be inlined to prevent generating instantiations of\n  // this template for every value of `SIZE` encountered in each source code\n  // file. That significantly increases linker input sizes. Inlining is cheap\n  // because the argument to this overload is almost always a string literal so\n  // the call to `strlen` can be replaced at compile time. The overloads for\n  // `char[]`/`wchar_t[]` below should not be inlined. The compiler typically\n  // does not have the string at compile time and cannot replace the call to\n  // `strlen` so inlining it increases the binary size. See the discussion on\n  // cl/107527369.\n  template <int SIZE>\n  LogMessage& operator<<(const char (&buf)[SIZE]);\n  template <int SIZE>\n  LogMessage& operator<<(const wchar_t (&buf)[SIZE]);\n\n  // This prevents non-const `char[]` arrays from looking like literals.\n  template <int SIZE>\n  LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;\n  // `wchar_t[SIZE]` is handled by `operator<< <const wchar_t*>`.\n\n  // Types that support `AbslStringify()` are serialized that way.\n  // Types that don't support `AbslStringify()` but do support streaming into a\n  // `std::ostream&` are serialized that way.\n  template <typename T>\n  LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;\n\n  // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.\n  void Flush();\n\n  // Note: We explicitly do not support `operator<<` for non-const references\n  // because it breaks logging of non-integer bitfield types (i.e., enums).\n\n protected:\n  // Call `abort()` or similar to perform `LOG(FATAL)` crash.  It is assumed\n  // that the caller has already generated and written the trace as appropriate.\n  [[noreturn]] static void FailWithoutStackTrace();\n\n  // Similar to `FailWithoutStackTrace()`, but without `abort()`.  Terminates\n  // the process with an error exit code.\n  [[noreturn]] static void FailQuietly();\n\n  // After this is called, failures are done as quiet as possible for this log\n  // message.\n  void SetFailQuietly();\n\n private:\n  struct LogMessageData;  // Opaque type containing message state\n  friend class AsLiteralImpl;\n  friend class StringifySink;\n  template <StructuredStringType str_type>\n  friend class AsStructuredStringTypeImpl;\n  template <typename T>\n  friend class AsStructuredValueImpl;\n\n  // This streambuf writes directly into the structured logging buffer so that\n  // arbitrary types can be encoded as string data (using\n  // `operator<<(std::ostream &, ...)` without any extra allocation or copying.\n  // Space is reserved before the data to store the length field, which is\n  // filled in by `~OstreamView`.\n  class OstreamView final : public std::streambuf {\n   public:\n    explicit OstreamView(LogMessageData& message_data);\n    ~OstreamView() override;\n    OstreamView(const OstreamView&) = delete;\n    OstreamView& operator=(const OstreamView&) = delete;\n    std::ostream& stream();\n\n   private:\n    LogMessageData& data_;\n    absl::Span<char> encoded_remaining_copy_;\n    absl::Span<char> message_start_;\n    absl::Span<char> string_start_;\n  };\n\n  enum class StringType {\n    kLiteral,\n    kNotLiteral,\n  };\n  template <StringType str_type>\n  void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE;\n  template <StringType str_type>\n  void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE;\n  template <StringType str_type>\n  void CopyToEncodedBuffer(std::wstring_view str) ABSL_ATTRIBUTE_NOINLINE;\n\n  // Copies `field` to the encoded buffer, then appends `str` after it\n  // (truncating `str` if necessary to fit).\n  template <StringType str_type>\n  void CopyToEncodedBufferWithStructuredProtoField(StructuredProtoField field,\n                                                   absl::string_view str)\n      ABSL_ATTRIBUTE_NOINLINE;\n\n  // Returns `true` if the message is fatal or enabled debug-fatal.\n  bool IsFatal() const;\n\n  // Records some tombstone-type data in anticipation of `Die`.\n  void PrepareToDie();\n  void Die();\n\n  void SendToLog();\n\n  // Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.\n  void LogBacktraceIfNeeded();\n\n  // This should be the first data member so that its initializer captures errno\n  // before any other initializers alter it (e.g. with calls to new) and so that\n  // no other destructors run afterward an alter it (e.g. with calls to delete).\n  absl::base_internal::ErrnoSaver errno_saver_;\n\n  // We keep the data in a separate struct so that each instance of `LogMessage`\n  // uses less stack space.\n  absl_nonnull std::unique_ptr<LogMessageData> data_;\n};\n\n// Explicitly specializes the generic operator<< for `const wchar_t*`\n// arguments.\n//\n// This method is used instead of a non-template `const wchar_t*` overload,\n// as the latter was found to take precedence over the array template\n// (`operator<<(const wchar_t(&)[SIZE])`) when handling string literals.\n// This specialization ensures the array template now correctly processes\n// literals.\ntemplate <>\nLogMessage& LogMessage::operator<< <const wchar_t*>(\n    const wchar_t* absl_nullable const& v);\n\ninline LogMessage& LogMessage::operator<<(wchar_t* absl_nullable v) {\n  return operator<<(const_cast<const wchar_t*>(v));\n}\n\n// Helper class so that `AbslStringify()` can modify the LogMessage.\nclass StringifySink final {\n public:\n  explicit StringifySink(LogMessage& message) : message_(message) {}\n\n  void Append(size_t count, char ch) {\n    message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(ch,\n                                                                      count);\n  }\n\n  void Append(absl::string_view v) {\n    message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(v);\n  }\n\n  // For types that implement `AbslStringify` using `absl::Format()`.\n  friend void AbslFormatFlush(StringifySink* absl_nonnull sink,\n                              absl::string_view v) {\n    sink->Append(v);\n  }\n\n private:\n  LogMessage& message_;\n};\n\n// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`\ntemplate <typename T>\nLogMessage& LogMessage::operator<<(const T& v) {\n  if constexpr (absl::HasAbslStringify<T>::value) {\n    StringifySink sink(*this);\n    // Replace with public API.\n    AbslStringify(sink, v);\n  } else {\n    OstreamView view(*data_);\n    view.stream() << log_internal::NullGuard<T>().Guard(v);\n  }\n  return *this;\n}\n\ntemplate <int SIZE>\nLogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {\n  CopyToEncodedBuffer<StringType::kLiteral>(buf);\n  return *this;\n}\n\ntemplate <int SIZE>\nLogMessage& LogMessage::operator<<(const wchar_t (&buf)[SIZE]) {\n  CopyToEncodedBuffer<StringType::kLiteral>(buf);\n  return *this;\n}\n\n// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`\ntemplate <int SIZE>\nLogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {\n  CopyToEncodedBuffer<StringType::kNotLiteral>(buf);\n  return *this;\n}\n// We instantiate these specializations in the library's TU to save space in\n// other TUs.  Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be\n// emitting a function call either way.\n// NOLINTBEGIN(runtime/int)\n// NOLINTBEGIN(google-runtime-int)\nextern template LogMessage& LogMessage::operator<<(const char& v);\nextern template LogMessage& LogMessage::operator<<(const signed char& v);\nextern template LogMessage& LogMessage::operator<<(const unsigned char& v);\nextern template LogMessage& LogMessage::operator<<(const short& v);\nextern template LogMessage& LogMessage::operator<<(const unsigned short& v);\nextern template LogMessage& LogMessage::operator<<(const int& v);\nextern template LogMessage& LogMessage::operator<<(const unsigned int& v);\nextern template LogMessage& LogMessage::operator<<(const long& v);\nextern template LogMessage& LogMessage::operator<<(const unsigned long& v);\nextern template LogMessage& LogMessage::operator<<(const long long& v);\nextern template LogMessage& LogMessage::operator<<(const unsigned long long& v);\nextern template LogMessage& LogMessage::operator<<(\n    void* absl_nullable const& v);\nextern template LogMessage& LogMessage::operator<<(\n    const void* absl_nullable const& v);\nextern template LogMessage& LogMessage::operator<<(const float& v);\nextern template LogMessage& LogMessage::operator<<(const double& v);\nextern template LogMessage& LogMessage::operator<<(const bool& v);\n// NOLINTEND(google-runtime-int)\n// NOLINTEND(runtime/int)\n\nextern template void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kLiteral>(absl::string_view str);\nextern template void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kNotLiteral>(absl::string_view str);\nextern template void\nLogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(char ch,\n                                                                  size_t num);\nextern template void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kNotLiteral>(char ch, size_t num);\nextern template void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kLiteral>(std::wstring_view str);\nextern template void LogMessage::CopyToEncodedBuffer<\n    LogMessage::StringType::kNotLiteral>(std::wstring_view str);\n\n// `LogMessageFatal` ensures the process will exit in failure after logging this\n// message.\nclass LogMessageFatal final : public LogMessage {\n public:\n  LogMessageFatal(const char* absl_nonnull file, int line) ABSL_ATTRIBUTE_COLD;\n  LogMessageFatal(const char* absl_nonnull file, int line,\n                  const char* absl_nonnull failure_msg) ABSL_ATTRIBUTE_COLD;\n  [[noreturn]] ~LogMessageFatal();\n};\n\n// `LogMessageDebugFatal` ensures the process will exit in failure after logging\n// this message. It matches LogMessageFatal but is not [[noreturn]] as it's used\n// for DLOG(FATAL) variants.\nclass LogMessageDebugFatal final : public LogMessage {\n public:\n  LogMessageDebugFatal(const char* absl_nonnull file,\n                       int line) ABSL_ATTRIBUTE_COLD;\n  ~LogMessageDebugFatal();\n};\n\nclass LogMessageQuietlyDebugFatal final : public LogMessage {\n public:\n  // DLOG(QFATAL) calls this instead of LogMessageQuietlyFatal to make sure the\n  // destructor is not [[noreturn]] even if this is always FATAL as this is only\n  // invoked when DLOG() is enabled.\n  LogMessageQuietlyDebugFatal(const char* absl_nonnull file,\n                              int line) ABSL_ATTRIBUTE_COLD;\n  ~LogMessageQuietlyDebugFatal();\n};\n\n// Used for LOG(QFATAL) to make sure it's properly understood as [[noreturn]].\nclass LogMessageQuietlyFatal final : public LogMessage {\n public:\n  LogMessageQuietlyFatal(const char* absl_nonnull file,\n                         int line) ABSL_ATTRIBUTE_COLD;\n  LogMessageQuietlyFatal(const char* absl_nonnull file, int line,\n                         const char* absl_nonnull failure_msg)\n      ABSL_ATTRIBUTE_COLD;\n  [[noreturn]] ~LogMessageQuietlyFatal();\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nextern \"C\" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(\n    AbslInternalOnFatalLogMessage)(const absl::LogEntry&);\n\n#endif  // ABSL_LOG_INTERNAL_LOG_MESSAGE_H_\n"
  },
  {
    "path": "absl/log/internal/log_sink_set.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/log_sink_set.h\"\n\n#ifndef ABSL_HAVE_THREAD_LOCAL\n#include <pthread.h>\n#endif\n\n#ifdef __ANDROID__\n#include <android/log.h>\n#endif\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#include <algorithm>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/cleanup/cleanup.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/config.h\"\n#include \"absl/log/internal/globals.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\n\n// Returns a mutable reference to a thread-local variable that should be true if\n// a globally-registered `LogSink`'s `Send()` is currently being invoked on this\n// thread.\nbool& ThreadIsLoggingStatus() {\n#ifdef ABSL_HAVE_THREAD_LOCAL\n  ABSL_CONST_INIT thread_local bool thread_is_logging = false;\n  return thread_is_logging;\n#else\n  ABSL_CONST_INIT static pthread_key_t thread_is_logging_key;\n  static const bool unused = [] {\n    if (pthread_key_create(&thread_is_logging_key, [](void* data) {\n          delete reinterpret_cast<bool*>(data);\n        })) {\n      perror(\"pthread_key_create failed!\");\n      abort();\n    }\n    return true;\n  }();\n  (void)unused;  // Fixes -wunused-variable warning\n  bool* thread_is_logging_ptr =\n      reinterpret_cast<bool*>(pthread_getspecific(thread_is_logging_key));\n\n  if (ABSL_PREDICT_FALSE(!thread_is_logging_ptr)) {\n    thread_is_logging_ptr = new bool{false};\n    if (pthread_setspecific(thread_is_logging_key, thread_is_logging_ptr)) {\n      perror(\"pthread_setspecific failed\");\n      abort();\n    }\n  }\n  return *thread_is_logging_ptr;\n#endif\n}\n\nclass StderrLogSink final : public LogSink {\n public:\n  ~StderrLogSink() override = default;\n\n  void Send(const absl::LogEntry& entry) override {\n    if (entry.log_severity() < absl::StderrThreshold() &&\n        absl::log_internal::IsInitialized()) {\n      return;\n    }\n\n    ABSL_CONST_INIT static absl::once_flag warn_if_not_initialized;\n    absl::call_once(warn_if_not_initialized, []() {\n      if (absl::log_internal::IsInitialized()) return;\n      const char w[] =\n          \"WARNING: All log messages before absl::InitializeLog() is called\"\n          \" are written to STDERR\\n\";\n      absl::log_internal::WriteToStderr(w, absl::LogSeverity::kWarning);\n    });\n\n    if (!entry.stacktrace().empty()) {\n      absl::log_internal::WriteToStderr(entry.stacktrace(),\n                                        entry.log_severity());\n    } else {\n      // TODO(b/226937039): do this outside else condition once we avoid\n      // ReprintFatalMessage\n      absl::log_internal::WriteToStderr(\n          entry.text_message_with_prefix_and_newline(), entry.log_severity());\n    }\n  }\n};\n\n#if defined(__ANDROID__)\nclass AndroidLogSink final : public LogSink {\n public:\n  ~AndroidLogSink() override = default;\n\n  void Send(const absl::LogEntry& entry) override {\n    const int level = AndroidLogLevel(entry);\n    const char* const tag = GetAndroidNativeTag();\n    __android_log_write(level, tag,\n                        entry.text_message_with_prefix_and_newline_c_str());\n    if (entry.log_severity() == absl::LogSeverity::kFatal)\n      __android_log_write(ANDROID_LOG_FATAL, tag, \"terminating.\\n\");\n  }\n\n private:\n  static int AndroidLogLevel(const absl::LogEntry& entry) {\n    switch (entry.log_severity()) {\n      case absl::LogSeverity::kFatal:\n        return ANDROID_LOG_FATAL;\n      case absl::LogSeverity::kError:\n        return ANDROID_LOG_ERROR;\n      case absl::LogSeverity::kWarning:\n        return ANDROID_LOG_WARN;\n      default:\n        if (entry.verbosity() >= 2) return ANDROID_LOG_VERBOSE;\n        if (entry.verbosity() == 1) return ANDROID_LOG_DEBUG;\n        return ANDROID_LOG_INFO;\n    }\n  }\n};\n#endif  // !defined(__ANDROID__)\n\n#if defined(_WIN32)\nclass WindowsDebuggerLogSink final : public LogSink {\n public:\n  ~WindowsDebuggerLogSink() override = default;\n\n  void Send(const absl::LogEntry& entry) override {\n    if (entry.log_severity() < absl::StderrThreshold() &&\n        absl::log_internal::IsInitialized()) {\n      return;\n    }\n    ::OutputDebugStringA(entry.text_message_with_prefix_and_newline_c_str());\n  }\n};\n#endif  // !defined(_WIN32)\n\nclass GlobalLogSinkSet final {\n public:\n  GlobalLogSinkSet() {\n#if defined(__myriad2__) || defined(__Fuchsia__)\n    // myriad2 and Fuchsia do not log to stderr by default.\n#else\n    static absl::NoDestructor<StderrLogSink> stderr_log_sink;\n    AddLogSink(stderr_log_sink.get());\n#endif\n#ifdef __ANDROID__\n    static absl::NoDestructor<AndroidLogSink> android_log_sink;\n    AddLogSink(android_log_sink.get());\n#endif\n#if defined(_WIN32)\n    static absl::NoDestructor<WindowsDebuggerLogSink> debugger_log_sink;\n    AddLogSink(debugger_log_sink.get());\n#endif  // !defined(_WIN32)\n  }\n\n  void LogToSinks(const absl::LogEntry& entry,\n                  absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only)\n      ABSL_LOCKS_EXCLUDED(guard_) {\n    SendToSinks(entry, extra_sinks);\n\n    if (!extra_sinks_only) {\n      if (ThreadIsLoggingToLogSink()) {\n        absl::log_internal::WriteToStderr(\n            entry.text_message_with_prefix_and_newline(), entry.log_severity());\n      } else {\n        absl::ReaderMutexLock global_sinks_lock(guard_);\n        ThreadIsLoggingStatus() = true;\n        // Ensure the \"thread is logging\" status is reverted upon leaving the\n        // scope even in case of exceptions.\n        auto status_cleanup =\n            absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });\n        SendToSinks(entry, absl::MakeSpan(sinks_));\n      }\n    }\n  }\n\n  void AddLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {\n    {\n      absl::WriterMutexLock global_sinks_lock(guard_);\n      auto pos = std::find(sinks_.begin(), sinks_.end(), sink);\n      if (pos == sinks_.end()) {\n        sinks_.push_back(sink);\n        return;\n      }\n    }\n    ABSL_INTERNAL_LOG(FATAL, \"Duplicate log sinks are not supported\");\n  }\n\n  void RemoveLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {\n    {\n      absl::WriterMutexLock global_sinks_lock(guard_);\n      auto pos = std::find(sinks_.begin(), sinks_.end(), sink);\n      if (pos != sinks_.end()) {\n        sinks_.erase(pos);\n        return;\n      }\n    }\n    ABSL_INTERNAL_LOG(FATAL, \"Mismatched log sink being removed\");\n  }\n\n  void FlushLogSinks() ABSL_LOCKS_EXCLUDED(guard_) {\n    if (ThreadIsLoggingToLogSink()) {\n      // The thread_local condition demonstrates that we're already holding the\n      // lock in order to iterate over `sinks_` for dispatch.  The thread-safety\n      // annotations don't know this, so we use `ABSL_NO_THREAD_SAFETY_ANALYSIS`\n      guard_.AssertReaderHeld();\n      FlushLogSinksLocked();\n    } else {\n      absl::ReaderMutexLock global_sinks_lock(guard_);\n      // In case if LogSink::Flush overload decides to log\n      ThreadIsLoggingStatus() = true;\n      // Ensure the \"thread is logging\" status is reverted upon leaving the\n      // scope even in case of exceptions.\n      auto status_cleanup =\n          absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });\n      FlushLogSinksLocked();\n    }\n  }\n\n private:\n  void FlushLogSinksLocked() ABSL_SHARED_LOCKS_REQUIRED(guard_) {\n    for (absl::LogSink* sink : sinks_) {\n      sink->Flush();\n    }\n  }\n\n  // Helper routine for LogToSinks.\n  static void SendToSinks(const absl::LogEntry& entry,\n                          absl::Span<absl::LogSink*> sinks) {\n    for (absl::LogSink* sink : sinks) {\n      sink->Send(entry);\n    }\n  }\n\n  using LogSinksSet = std::vector<absl::LogSink*>;\n  absl::Mutex guard_;\n  LogSinksSet sinks_ ABSL_GUARDED_BY(guard_);\n};\n\n// Returns reference to the global LogSinks set.\nGlobalLogSinkSet& GlobalSinks() {\n  static absl::NoDestructor<GlobalLogSinkSet> global_sinks;\n  return *global_sinks;\n}\n\n}  // namespace\n\nbool ThreadIsLoggingToLogSink() { return ThreadIsLoggingStatus(); }\n\nvoid LogToSinks(const absl::LogEntry& entry,\n                absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only) {\n  log_internal::GlobalSinks().LogToSinks(entry, extra_sinks, extra_sinks_only);\n}\n\nvoid AddLogSink(absl::LogSink* sink) {\n  log_internal::GlobalSinks().AddLogSink(sink);\n}\n\nvoid RemoveLogSink(absl::LogSink* sink) {\n  log_internal::GlobalSinks().RemoveLogSink(sink);\n}\n\nvoid FlushLogSinks() { log_internal::GlobalSinks().FlushLogSinks(); }\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/log_sink_set.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/log_sink_set.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_LOG_INTERNAL_LOG_SINK_SET_H_\n#define ABSL_LOG_INTERNAL_LOG_SINK_SET_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// Returns true if a globally-registered `LogSink`'s `Send()` is currently\n// being invoked on this thread.\nbool ThreadIsLoggingToLogSink();\n\n// This function may log to two sets of sinks:\n//\n// * If `extra_sinks_only` is true, it will dispatch only to `extra_sinks`.\n//   `LogMessage::ToSinkAlso` and `LogMessage::ToSinkOnly` are used to attach\n//    extra sinks to the entry.\n// * Otherwise it will also log to the global sinks set. This set is managed\n//   by `absl::AddLogSink` and `absl::RemoveLogSink`.\nvoid LogToSinks(const absl::LogEntry& entry,\n                absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only);\n\n// Implementation for operations with log sink set.\nvoid AddLogSink(absl::LogSink* sink);\nvoid RemoveLogSink(absl::LogSink* sink);\nvoid FlushLogSinks();\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_LOG_SINK_SET_H_\n"
  },
  {
    "path": "absl/log/internal/nullguard.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/nullguard.h\"\n\n#include <array>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nABSL_CONST_INIT ABSL_DLL const std::array<char, 7> kCharNull{\n    {'(', 'n', 'u', 'l', 'l', ')', '\\0'}};\nABSL_CONST_INIT ABSL_DLL const std::array<signed char, 7> kSignedCharNull{\n    {'(', 'n', 'u', 'l', 'l', ')', '\\0'}};\nABSL_CONST_INIT ABSL_DLL const std::array<unsigned char, 7> kUnsignedCharNull{\n    {'(', 'n', 'u', 'l', 'l', ')', '\\0'}};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/nullguard.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/nullguard.h\n// -----------------------------------------------------------------------------\n//\n// NullGuard exists such that NullGuard<T>::Guard(v) returns v, unless passed a\n// nullptr_t, or a null char* or const char*, in which case it returns \"(null)\".\n// This allows streaming NullGuard<T>::Guard(v) to an output stream without\n// hitting undefined behavior for null values.\n\n#ifndef ABSL_LOG_INTERNAL_NULLGUARD_H_\n#define ABSL_LOG_INTERNAL_NULLGUARD_H_\n\n#include <array>\n#include <cstddef>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nABSL_CONST_INIT ABSL_DLL extern const std::array<char, 7> kCharNull;\nABSL_CONST_INIT ABSL_DLL extern const std::array<signed char, 7>\n    kSignedCharNull;\nABSL_CONST_INIT ABSL_DLL extern const std::array<unsigned char, 7>\n    kUnsignedCharNull;\n\ntemplate <typename T>\nstruct NullGuard final {\n  static const T& Guard(const T& v) { return v; }\n};\ntemplate <>\nstruct NullGuard<char*> final {\n  static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }\n};\ntemplate <>\nstruct NullGuard<const char*> final {\n  static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }\n};\ntemplate <>\nstruct NullGuard<signed char*> final {\n  static const signed char* Guard(const signed char* v) {\n    return v ? v : kSignedCharNull.data();\n  }\n};\ntemplate <>\nstruct NullGuard<const signed char*> final {\n  static const signed char* Guard(const signed char* v) {\n    return v ? v : kSignedCharNull.data();\n  }\n};\ntemplate <>\nstruct NullGuard<unsigned char*> final {\n  static const unsigned char* Guard(const unsigned char* v) {\n    return v ? v : kUnsignedCharNull.data();\n  }\n};\ntemplate <>\nstruct NullGuard<const unsigned char*> final {\n  static const unsigned char* Guard(const unsigned char* v) {\n    return v ? v : kUnsignedCharNull.data();\n  }\n};\ntemplate <>\nstruct NullGuard<std::nullptr_t> final {\n  static const char* Guard(const std::nullptr_t&) { return kCharNull.data(); }\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_NULLGUARD_H_\n"
  },
  {
    "path": "absl/log/internal/nullstream.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/nullstream.h\n// -----------------------------------------------------------------------------\n//\n// Classes `NullStream`, `NullStreamMaybeFatal ` and `NullStreamFatal`\n// implement a subset of the `LogMessage` API and are used instead when logging\n// of messages has been disabled.\n\n#ifndef ABSL_LOG_INTERNAL_NULLSTREAM_H_\n#define ABSL_LOG_INTERNAL_NULLSTREAM_H_\n\n#ifdef _WIN32\n#include <cstdlib>\n#else\n#include <unistd.h>\n#endif\n#include <ios>\n#include <ostream>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// A `NullStream` implements the API of `LogMessage` (a few methods and\n// `operator<<`) but does nothing.  All methods are defined inline so the\n// compiler can eliminate the whole instance and discard anything that's\n// streamed in.\nclass NullStream {\n public:\n  NullStream& AtLocation(absl::string_view, int) { return *this; }\n  template <typename SourceLocationType>\n  NullStream& AtLocation(SourceLocationType) {\n    return *this;\n  }\n  NullStream& NoPrefix() { return *this; }\n  NullStream& WithVerbosity(int) { return *this; }\n  template <typename TimeType>\n  NullStream& WithTimestamp(TimeType) {\n    return *this;\n  }\n  template <typename Tid>\n  NullStream& WithThreadID(Tid) {\n    return *this;\n  }\n  template <typename LogEntryType>\n  NullStream& WithMetadataFrom(const LogEntryType&) {\n    return *this;\n  }\n  NullStream& WithPerror() { return *this; }\n  template <typename LogSinkType>\n  NullStream& ToSinkAlso(LogSinkType*) {\n    return *this;\n  }\n  template <typename LogSinkType>\n  NullStream& ToSinkOnly(LogSinkType*) {\n    return *this;\n  }\n  template <typename LogSinkType>\n  NullStream& OutputToSink(LogSinkType*, bool) {\n    return *this;\n  }\n  NullStream& InternalStream() { return *this; }\n  void Flush() {}\n};\ntemplate <typename T>\ninline NullStream& operator<<(NullStream& str, const T&) {\n  return str;\n}\ninline NullStream& operator<<(NullStream& str,\n                              std::ostream& (*)(std::ostream& os)) {\n  return str;\n}\ninline NullStream& operator<<(NullStream& str,\n                              std::ios_base& (*)(std::ios_base& os)) {\n  return str;\n}\n\n// `NullStreamMaybeFatal` implements the process termination semantics of\n// `LogMessage`, which is used for `DFATAL` severity and expression-defined\n// severity e.g. `LOG(LEVEL(HowBadIsIt()))`.  Like `LogMessage`, it terminates\n// the process when destroyed if the passed-in severity equals `FATAL`.\nclass NullStreamMaybeFatal final : public NullStream {\n public:\n  explicit NullStreamMaybeFatal(absl::LogSeverity severity)\n      : fatal_(severity == absl::LogSeverity::kFatal) {}\n  ~NullStreamMaybeFatal() {\n    if (fatal_) {\n      _exit(1);\n    }\n  }\n\n private:\n  bool fatal_;\n};\n\n// `NullStreamFatal` implements the process termination semantics of\n// `LogMessageFatal`, which means it always terminates the process.  `DFATAL`\n// and expression-defined severity use `NullStreamMaybeFatal` above.\nclass NullStreamFatal final : public NullStream {\n public:\n  NullStreamFatal() = default;\n  [[noreturn]] ~NullStreamFatal() { _exit(1); }\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_GLOBALS_H_\n"
  },
  {
    "path": "absl/log/internal/proto.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/proto.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\nvoid EncodeRawVarint(uint64_t value, size_t size, absl::Span<char> *buf) {\n  for (size_t s = 0; s < size; s++) {\n    (*buf)[s] = static_cast<char>((value & 0x7f) | (s + 1 == size ? 0 : 0x80));\n    value >>= 7;\n  }\n  buf->remove_prefix(size);\n}\n}  // namespace\n\nbool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) {\n  const uint64_t tag_type = MakeTagType(tag, WireType::kVarint);\n  const size_t tag_type_size = VarintSize(tag_type);\n  const size_t value_size = VarintSize(value);\n  if (tag_type_size + value_size > buf->size()) {\n    buf->remove_suffix(buf->size());\n    return false;\n  }\n  EncodeRawVarint(tag_type, tag_type_size, buf);\n  EncodeRawVarint(value, value_size, buf);\n  return true;\n}\n\nbool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf) {\n  const uint64_t tag_type = MakeTagType(tag, WireType::k64Bit);\n  const size_t tag_type_size = VarintSize(tag_type);\n  if (tag_type_size + sizeof(value) > buf->size()) {\n    buf->remove_suffix(buf->size());\n    return false;\n  }\n  EncodeRawVarint(tag_type, tag_type_size, buf);\n  for (size_t s = 0; s < sizeof(value); s++) {\n    (*buf)[s] = static_cast<char>(value & 0xff);\n    value >>= 8;\n  }\n  buf->remove_prefix(sizeof(value));\n  return true;\n}\n\nbool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {\n  const uint64_t tag_type = MakeTagType(tag, WireType::k32Bit);\n  const size_t tag_type_size = VarintSize(tag_type);\n  if (tag_type_size + sizeof(value) > buf->size()) {\n    buf->remove_suffix(buf->size());\n    return false;\n  }\n  EncodeRawVarint(tag_type, tag_type_size, buf);\n  for (size_t s = 0; s < sizeof(value); s++) {\n    (*buf)[s] = static_cast<char>(value & 0xff);\n    value >>= 8;\n  }\n  buf->remove_prefix(sizeof(value));\n  return true;\n}\n\nbool EncodeBytes(uint64_t tag, absl::Span<const char> value,\n                 absl::Span<char> *buf) {\n  const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);\n  const size_t tag_type_size = VarintSize(tag_type);\n  uint64_t length = value.size();\n  const size_t length_size = VarintSize(length);\n  if (tag_type_size + length_size + value.size() > buf->size()) {\n    buf->remove_suffix(buf->size());\n    return false;\n  }\n  EncodeRawVarint(tag_type, tag_type_size, buf);\n  EncodeRawVarint(length, length_size, buf);\n  memcpy(buf->data(), value.data(), value.size());\n  buf->remove_prefix(value.size());\n  return true;\n}\n\nbool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,\n                         absl::Span<char> *buf) {\n  const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);\n  const size_t tag_type_size = VarintSize(tag_type);\n  uint64_t length = value.size();\n  const size_t length_size =\n      VarintSize(std::min<uint64_t>(length, buf->size()));\n  if (tag_type_size + length_size <= buf->size() &&\n      tag_type_size + length_size + value.size() > buf->size()) {\n    value.remove_suffix(tag_type_size + length_size + value.size() -\n                        buf->size());\n    length = value.size();\n  }\n  if (tag_type_size + length_size + value.size() > buf->size()) {\n    buf->remove_suffix(buf->size());\n    return false;\n  }\n  EncodeRawVarint(tag_type, tag_type_size, buf);\n  EncodeRawVarint(length, length_size, buf);\n  memcpy(buf->data(), value.data(), value.size());\n  buf->remove_prefix(value.size());\n  return true;\n}\n\n[[nodiscard]] absl::Span<char> EncodeMessageStart(uint64_t tag,\n                                                  uint64_t max_size,\n                                                  absl::Span<char> *buf) {\n  const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);\n  const size_t tag_type_size = VarintSize(tag_type);\n  max_size = std::min<uint64_t>(max_size, buf->size());\n  const size_t length_size = VarintSize(max_size);\n  if (tag_type_size + length_size > buf->size()) {\n    buf->remove_suffix(buf->size());\n    return absl::Span<char>();\n  }\n  EncodeRawVarint(tag_type, tag_type_size, buf);\n  const absl::Span<char> ret = buf->subspan(0, length_size);\n  EncodeRawVarint(0, length_size, buf);\n  return ret;\n}\n\nvoid EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf) {\n  if (!msg.data()) return;\n  assert(buf->data() >= msg.data());\n  if (buf->data() < msg.data()) return;\n  EncodeRawVarint(\n      static_cast<uint64_t>(buf->data() - (msg.data() + msg.size())),\n      msg.size(), &msg);\n}\n\nnamespace {\nuint64_t DecodeVarint(absl::Span<const char> *buf) {\n  uint64_t value = 0;\n  size_t s = 0;\n  while (s < buf->size()) {\n    value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]) & 0x7f)\n             << 7 * s;\n    if (!((*buf)[s++] & 0x80)) break;\n  }\n  buf->remove_prefix(s);\n  return value;\n}\n\nuint64_t Decode64Bit(absl::Span<const char> *buf) {\n  uint64_t value = 0;\n  size_t s = 0;\n  while (s < buf->size()) {\n    value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]))\n             << 8 * s;\n    if (++s == sizeof(value)) break;\n  }\n  buf->remove_prefix(s);\n  return value;\n}\n\nuint32_t Decode32Bit(absl::Span<const char> *buf) {\n  uint32_t value = 0;\n  size_t s = 0;\n  while (s < buf->size()) {\n    value |= static_cast<uint32_t>(static_cast<unsigned char>((*buf)[s]))\n             << 8 * s;\n    if (++s == sizeof(value)) break;\n  }\n  buf->remove_prefix(s);\n  return value;\n}\n}  // namespace\n\nbool ProtoField::DecodeFrom(absl::Span<const char> *data) {\n  if (data->empty()) return false;\n  const uint64_t tag_type = DecodeVarint(data);\n  tag_ = tag_type >> 3;\n  type_ = static_cast<WireType>(tag_type & 0x07);\n  switch (type_) {\n    case WireType::kVarint:\n      value_ = DecodeVarint(data);\n      break;\n    case WireType::k64Bit:\n      value_ = Decode64Bit(data);\n      break;\n    case WireType::kLengthDelimited: {\n      value_ = DecodeVarint(data);\n      data_ = data->subspan(\n          0, static_cast<size_t>(std::min<uint64_t>(value_, data->size())));\n      data->remove_prefix(data_.size());\n      break;\n    }\n    case WireType::k32Bit:\n      value_ = Decode32Bit(data);\n      break;\n  }\n  return true;\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/proto.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// -----------------------------------------------------------------------------\n// File: internal/proto.h\n// -----------------------------------------------------------------------------\n//\n// Declares functions for serializing and deserializing data to and from memory\n// buffers in protocol buffer wire format.  This library takes no steps to\n// ensure that the encoded data matches with any message specification.\n\n#ifndef ABSL_LOG_INTERNAL_PROTO_H_\n#define ABSL_LOG_INTERNAL_PROTO_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// absl::Span<char> represents a view into the available space in a mutable\n// buffer during encoding.  Encoding functions shrink the span as they go so\n// that the same view can be passed to a series of Encode functions.  If the\n// data do not fit, nothing is encoded, the view is set to size zero (so that\n// all subsequent encode calls fail), and false is returned.  Otherwise true is\n// returned.\n\n// In particular, attempting to encode a series of data into an insufficient\n// buffer has consistent and efficient behavior without any caller-side error\n// checking.  Individual values will be encoded in their entirety or not at all\n// (unless one of the `Truncate` functions is used).  Once a value is omitted\n// because it does not fit, no subsequent values will be encoded to preserve\n// ordering; the decoded sequence will be a prefix of the original sequence.\n\n// There are two ways to encode a message-typed field:\n//\n// * Construct its contents in a separate buffer and use `EncodeBytes` to copy\n//   it into the primary buffer with type, tag, and length.\n// * Use `EncodeMessageStart` to write type and tag fields and reserve space for\n//   the length field, then encode the contents directly into the buffer, then\n//   use `EncodeMessageLength` to write the actual length into the reserved\n//   bytes.  This works fine if the actual length takes fewer bytes to encode\n//   than were reserved, although you don't get your extra bytes back.\n//   This approach will always produce a valid encoding, but your protocol may\n//   require that the whole message field by omitted if the buffer is too small\n//   to contain all desired subfields.  In this case, operate on a copy of the\n//   buffer view and assign back only if everything fit, i.e. if the last\n//   `Encode` call returned true.\n\n// Encodes the specified integer as a varint field and returns true if it fits.\n// Used for int32_t, int64_t, uint32_t, uint64_t, bool, and enum field types.\n// Consumes up to kMaxVarintSize * 2 bytes (20).\nbool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf);\ninline bool EncodeVarint(uint64_t tag, int64_t value, absl::Span<char> *buf) {\n  return EncodeVarint(tag, static_cast<uint64_t>(value), buf);\n}\ninline bool EncodeVarint(uint64_t tag, uint32_t value, absl::Span<char> *buf) {\n  return EncodeVarint(tag, static_cast<uint64_t>(value), buf);\n}\ninline bool EncodeVarint(uint64_t tag, int32_t value, absl::Span<char> *buf) {\n  return EncodeVarint(tag, static_cast<uint64_t>(value), buf);\n}\n\n// Encodes the specified integer as a varint field using ZigZag encoding and\n// returns true if it fits.\n// Used for sint32 and sint64 field types.\n// Consumes up to kMaxVarintSize * 2 bytes (20).\ninline bool EncodeVarintZigZag(uint64_t tag, int64_t value,\n                               absl::Span<char> *buf) {\n  if (value < 0)\n    return EncodeVarint(tag, 2 * static_cast<uint64_t>(-(value + 1)) + 1, buf);\n  return EncodeVarint(tag, 2 * static_cast<uint64_t>(value), buf);\n}\n\n// Encodes the specified integer as a 64-bit field and returns true if it fits.\n// Used for fixed64 and sfixed64 field types.\n// Consumes up to kMaxVarintSize + 8 bytes (18).\nbool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf);\ninline bool Encode64Bit(uint64_t tag, int64_t value, absl::Span<char> *buf) {\n  return Encode64Bit(tag, static_cast<uint64_t>(value), buf);\n}\ninline bool Encode64Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {\n  return Encode64Bit(tag, static_cast<uint64_t>(value), buf);\n}\ninline bool Encode64Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {\n  return Encode64Bit(tag, static_cast<uint64_t>(value), buf);\n}\n\n// Encodes the specified double as a 64-bit field and returns true if it fits.\n// Used for double field type.\n// Consumes up to kMaxVarintSize + 8 bytes (18).\ninline bool EncodeDouble(uint64_t tag, double value, absl::Span<char> *buf) {\n  return Encode64Bit(tag, absl::bit_cast<uint64_t>(value), buf);\n}\n\n// Encodes the specified integer as a 32-bit field and returns true if it fits.\n// Used for fixed32 and sfixed32 field types.\n// Consumes up to kMaxVarintSize + 4 bytes (14).\nbool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf);\ninline bool Encode32Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {\n  return Encode32Bit(tag, static_cast<uint32_t>(value), buf);\n}\n\n// Encodes the specified float as a 32-bit field and returns true if it fits.\n// Used for float field type.\n// Consumes up to kMaxVarintSize + 4 bytes (14).\ninline bool EncodeFloat(uint64_t tag, float value, absl::Span<char> *buf) {\n  return Encode32Bit(tag, absl::bit_cast<uint32_t>(value), buf);\n}\n\n// Encodes the specified bytes as a length-delimited field and returns true if\n// they fit.\n// Used for string, bytes, message, and packed-repeated field type.\n// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).\nbool EncodeBytes(uint64_t tag, absl::Span<const char> value,\n                 absl::Span<char> *buf);\n\n// Encodes as many of the specified bytes as will fit as a length-delimited\n// field and returns true as long as the field header (`tag_type` and `length`)\n// fits.\n// Used for string, bytes, message, and packed-repeated field type.\n// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).\nbool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,\n                         absl::Span<char> *buf);\n\n// Encodes the specified string as a length-delimited field and returns true if\n// it fits.\n// Used for string, bytes, message, and packed-repeated field type.\n// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).\ninline bool EncodeString(uint64_t tag, absl::string_view value,\n                         absl::Span<char> *buf) {\n  return EncodeBytes(tag, value, buf);\n}\n\n// Encodes as much of the specified string as will fit as a length-delimited\n// field and returns true as long as the field header (`tag_type` and `length`)\n// fits.\n// Used for string, bytes, message, and packed-repeated field type.\n// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).\ninline bool EncodeStringTruncate(uint64_t tag, absl::string_view value,\n                                 absl::Span<char> *buf) {\n  return EncodeBytesTruncate(tag, value, buf);\n}\n\n// Encodes the header for a length-delimited field containing up to `max_size`\n// bytes or the number remaining in the buffer, whichever is less.  If the\n// header fits, a non-nullptr `Span` is returned; this must be passed to\n// `EncodeMessageLength` after all contents are encoded to finalize the length\n// field.  If the header does not fit, a nullptr `Span` is returned which is\n// safe to pass to `EncodeMessageLength` but need not be.\n// Used for string, bytes, message, and packed-repeated field type.\n// Consumes up to kMaxVarintSize * 2 bytes (20).\n[[nodiscard]] absl::Span<char> EncodeMessageStart(uint64_t tag,\n                                                  uint64_t max_size,\n                                                  absl::Span<char> *buf);\n\n// Finalizes the length field in `msg` so that it encompasses all data encoded\n// since the call to `EncodeMessageStart` which returned `msg`.  Does nothing if\n// `msg` is a `nullptr` `Span`.\nvoid EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf);\n\nenum class WireType : uint64_t {\n  kVarint = 0,\n  k64Bit = 1,\n  kLengthDelimited = 2,\n  k32Bit = 5,\n};\n\nconstexpr size_t VarintSize(uint64_t value) {\n  return value < 128 ? 1 : 1 + VarintSize(value >> 7);\n}\nconstexpr size_t MinVarintSize() {\n  return VarintSize((std::numeric_limits<uint64_t>::min)());\n}\nconstexpr size_t MaxVarintSize() {\n  return VarintSize((std::numeric_limits<uint64_t>::max)());\n}\n\nconstexpr uint64_t MaxVarintForSize(size_t size) {\n  return size >= 10 ? (std::numeric_limits<uint64_t>::max)()\n                    : (static_cast<uint64_t>(1) << size * 7) - 1;\n}\nconstexpr uint64_t MakeTagType(uint64_t tag, WireType type) {\n  return tag << 3 | static_cast<uint64_t>(type);\n}\n\n// `BufferSizeFor` returns a number of bytes guaranteed to be sufficient to\n// store encoded fields as `(tag, WireType)`, regardless of data values.  This\n// only makes sense for `WireType::kLengthDelimited` if you add in the length of\n// the contents yourself, e.g. for string and bytes fields by adding the lengths\n// of any encoded strings to the return value or for submessage fields by\n// enumerating the fields you may encode into their contents.\nconstexpr size_t BufferSizeFor(uint64_t tag, WireType type) {\n  size_t buffer_size = VarintSize(MakeTagType(tag, type));\n  switch (type) {\n    case WireType::kVarint:\n      buffer_size += MaxVarintSize();\n      break;\n    case WireType::k64Bit:\n      buffer_size += size_t{8};\n      break;\n    case WireType::kLengthDelimited:\n      buffer_size += MaxVarintSize();\n      break;\n    case WireType::k32Bit:\n      buffer_size += size_t{4};\n      break;\n  }\n  return buffer_size;\n}\n\n// absl::Span<const char> represents a view into the un-processed space in a\n// buffer during decoding.  Decoding functions shrink the span as they go so\n// that the same view can be decoded iteratively until all data are processed.\n// In general, if the buffer is exhausted but additional bytes are expected by\n// the decoder, it will return values as if the additional bytes were zeros.\n// Length-delimited fields are an exception - if the encoded length field\n// indicates more data bytes than are available in the buffer, the `bytes_value`\n// and `string_value` accessors will return truncated views.\n\nclass ProtoField final {\n public:\n  // Consumes bytes from `data` and returns true if there were any bytes to\n  // decode.\n  bool DecodeFrom(absl::Span<const char> *data);\n  uint64_t tag() const { return tag_; }\n  WireType type() const { return type_; }\n\n  // These value accessors will return nonsense if the data were not encoded in\n  // the corresponding wiretype from the corresponding C++ (or other language)\n  // type.\n\n  double double_value() const { return absl::bit_cast<double>(value_); }\n  float float_value() const {\n    return absl::bit_cast<float>(static_cast<uint32_t>(value_));\n  }\n  int32_t int32_value() const { return static_cast<int32_t>(value_); }\n  int64_t int64_value() const { return static_cast<int64_t>(value_); }\n  int32_t sint32_value() const {\n    if (value_ % 2) return static_cast<int32_t>(0 - ((value_ - 1) / 2) - 1);\n    return static_cast<int32_t>(value_ / 2);\n  }\n  int64_t sint64_value() const {\n    if (value_ % 2) return 0 - ((value_ - 1) / 2) - 1;\n    return value_ / 2;\n  }\n  uint32_t uint32_value() const { return static_cast<uint32_t>(value_); }\n  uint64_t uint64_value() const { return value_; }\n  bool bool_value() const { return value_ != 0; }\n  // To decode an enum, call int32_value() and cast to the appropriate type.\n  // Note that the official C++ proto compiler treats enum fields with values\n  // that do not correspond to a defined enumerator as unknown fields.\n\n  // To decode fields within a submessage field, call\n  // `DecodeNextField(field.BytesValue())`.\n  absl::Span<const char> bytes_value() const { return data_; }\n  absl::string_view string_value() const {\n    const auto data = bytes_value();\n    return absl::string_view(data.data(), data.size());\n  }\n  // Returns the encoded length of a length-delimited field.  This equals\n  // `bytes_value().size()` except when the latter has been truncated due to\n  // buffer underrun.\n  uint64_t encoded_length() const { return value_; }\n\n private:\n  uint64_t tag_;\n  WireType type_;\n  // For `kTypeVarint`, `kType64Bit`, and `kType32Bit`, holds the decoded value.\n  // For `kTypeLengthDelimited`, holds the decoded length.\n  uint64_t value_;\n  absl::Span<const char> data_;\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_PROTO_H_\n"
  },
  {
    "path": "absl/log/internal/stderr_log_sink_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <stdlib.h>\n\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/log.h\"\n\nnamespace {\nusing ::testing::AllOf;\nusing ::testing::HasSubstr;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\nMATCHER_P2(HasSubstrTimes, substr, expected_count, \"\") {\n  int count = 0;\n  std::string::size_type pos = 0;\n  std::string needle(substr);\n  while ((pos = arg.find(needle, pos)) != std::string::npos) {\n    ++count;\n    pos += needle.size();\n  }\n\n  return count == expected_count;\n}\n\nTEST(StderrLogSinkDeathTest, InfoMessagesInStderr) {\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);\n        LOG(INFO) << \"INFO message\";\n        exit(1);\n      },\n      \"INFO message\");\n}\n\nTEST(StderrLogSinkDeathTest, WarningMessagesInStderr) {\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);\n        LOG(WARNING) << \"WARNING message\";\n        exit(1);\n      },\n      \"WARNING message\");\n}\n\nTEST(StderrLogSinkDeathTest, ErrorMessagesInStderr) {\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);\n        LOG(ERROR) << \"ERROR message\";\n        exit(1);\n      },\n      \"ERROR message\");\n}\n\nTEST(StderrLogSinkDeathTest, FatalMessagesInStderr) {\n  char message[] = \"FATAL message\";\n  char stacktrace[] = \"*** Check failure stack trace: ***\";\n\n  int expected_count = 1;\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);\n        LOG(FATAL) << message;\n      },\n      AllOf(HasSubstrTimes(message, expected_count), HasSubstr(stacktrace)));\n}\n\nTEST(StderrLogSinkDeathTest, SecondaryFatalMessagesInStderr) {\n  auto MessageGen = []() -> std::string {\n    LOG(FATAL) << \"Internal failure\";\n    return \"External failure\";\n  };\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);\n        LOG(FATAL) << MessageGen();\n      },\n      \"Internal failure\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/internal/strip.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/strip.h\n// -----------------------------------------------------------------------------\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_LOG_INTERNAL_STRIP_H_\n#define ABSL_LOG_INTERNAL_STRIP_H_\n\n#include \"absl/base/attributes.h\"  // IWYU pragma: keep\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/log_message.h\"\n#include \"absl/log/internal/nullstream.h\"\n\n// `ABSL_LOG_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or\n// to a related object with a compatible API but different behavior.  This set\n// of defines comes in three flavors: vanilla, plus two variants that strip some\n// logging in subtly different ways for subtly different reasons (see below).\n#if defined(STRIP_LOG) && STRIP_LOG\n\n#define ABSL_LOG_INTERNAL_LOG_INFO ::absl::log_internal::NullStream()\n#define ABSL_LOG_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream()\n#define ABSL_LOG_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream()\n#define ABSL_LOG_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal()\n#define ABSL_LOG_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal()\n#define ABSL_LOG_INTERNAL_LOG_DFATAL \\\n  ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal)\n#define ABSL_LOG_INTERNAL_LOG_LEVEL(severity) \\\n  ::absl::log_internal::NullStreamMaybeFatal(absl_log_internal_severity)\n\n// Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`.\n#define ABSL_LOG_INTERNAL_DLOG_FATAL \\\n  ::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal)\n#define ABSL_LOG_INTERNAL_DLOG_QFATAL \\\n  ::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal)\n\n#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOG_INTERNAL_LOG_FATAL\n#define ABSL_LOG_INTERNAL_QCHECK(failure_message) ABSL_LOG_INTERNAL_LOG_QFATAL\n\n#else  // !defined(STRIP_LOG) || !STRIP_LOG\n\n#define ABSL_LOG_INTERNAL_LOG_INFO  \\\n  ::absl::log_internal::LogMessage( \\\n      __FILE__, __LINE__, ::absl::log_internal::LogMessage::InfoTag{})\n#define ABSL_LOG_INTERNAL_LOG_WARNING \\\n  ::absl::log_internal::LogMessage(   \\\n      __FILE__, __LINE__, ::absl::log_internal::LogMessage::WarningTag{})\n#define ABSL_LOG_INTERNAL_LOG_ERROR \\\n  ::absl::log_internal::LogMessage( \\\n      __FILE__, __LINE__, ::absl::log_internal::LogMessage::ErrorTag{})\n#define ABSL_LOG_INTERNAL_LOG_FATAL \\\n  ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__)\n#define ABSL_LOG_INTERNAL_LOG_QFATAL \\\n  ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__)\n#define ABSL_LOG_INTERNAL_LOG_DFATAL \\\n  ::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal)\n#define ABSL_LOG_INTERNAL_LOG_LEVEL(severity)          \\\n  ::absl::log_internal::LogMessage(__FILE__, __LINE__, \\\n                                   absl_log_internal_severity)\n\n// Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`.\n#define ABSL_LOG_INTERNAL_DLOG_FATAL \\\n  ::absl::log_internal::LogMessageDebugFatal(__FILE__, __LINE__)\n#define ABSL_LOG_INTERNAL_DLOG_QFATAL \\\n  ::absl::log_internal::LogMessageQuietlyDebugFatal(__FILE__, __LINE__)\n\n// These special cases dispatch to special-case constructors that allow us to\n// avoid an extra function call and shrink non-LTO binaries by a percent or so.\n#define ABSL_LOG_INTERNAL_CHECK(failure_message) \\\n  ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__, failure_message)\n#define ABSL_LOG_INTERNAL_QCHECK(failure_message)                  \\\n  ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__, \\\n                                               failure_message)\n#endif  // !defined(STRIP_LOG) || !STRIP_LOG\n\n// This part of a non-fatal `DLOG`s expands the same as `LOG`.\n#define ABSL_LOG_INTERNAL_DLOG_INFO ABSL_LOG_INTERNAL_LOG_INFO\n#define ABSL_LOG_INTERNAL_DLOG_WARNING ABSL_LOG_INTERNAL_LOG_WARNING\n#define ABSL_LOG_INTERNAL_DLOG_ERROR ABSL_LOG_INTERNAL_LOG_ERROR\n#define ABSL_LOG_INTERNAL_DLOG_DFATAL ABSL_LOG_INTERNAL_LOG_DFATAL\n#define ABSL_LOG_INTERNAL_DLOG_LEVEL ABSL_LOG_INTERNAL_LOG_LEVEL\n\n#define ABSL_LOG_INTERNAL_LOG_DO_NOT_SUBMIT ABSL_LOG_INTERNAL_LOG_ERROR\n\n#endif  // ABSL_LOG_INTERNAL_STRIP_H_\n"
  },
  {
    "path": "absl/log/internal/structured.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/structured.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_LOG_INTERNAL_STRUCTURED_H_\n#define ABSL_LOG_INTERNAL_STRUCTURED_H_\n\n#include <ostream>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/functional/any_invocable.h\"\n#include \"absl/log/internal/log_message.h\"\n#include \"absl/log/internal/structured_proto.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nclass [[nodiscard]] AsLiteralImpl final {\n public:\n  explicit AsLiteralImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : str_(str) {}\n  AsLiteralImpl(const AsLiteralImpl&) = default;\n  AsLiteralImpl& operator=(const AsLiteralImpl&) = default;\n\n private:\n  absl::string_view str_;\n\n  friend std::ostream& operator<<(std::ostream& os,\n                                  AsLiteralImpl&& as_literal) {\n    return os << as_literal.str_;\n  }\n  void AddToMessage(log_internal::LogMessage& m) {\n    m.CopyToEncodedBuffer<log_internal::LogMessage::StringType::kLiteral>(str_);\n  }\n  friend log_internal::LogMessage& operator<<(log_internal::LogMessage& m,\n                                              AsLiteralImpl as_literal) {\n    as_literal.AddToMessage(m);\n    return m;\n  }\n};\n\nenum class StructuredStringType {\n  kLiteral,\n  kNotLiteral,\n};\n\n// Structured log data for a string and associated structured proto field,\n// both of which must outlive this object.\ntemplate <StructuredStringType str_type>\nclass [[nodiscard]] AsStructuredStringTypeImpl final {\n public:\n  constexpr AsStructuredStringTypeImpl(\n      absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : str_(str), field_(field) {}\n\n private:\n  absl::string_view str_;\n  StructuredProtoField field_;\n\n  friend std::ostream& operator<<(std::ostream& os,\n                                  const AsStructuredStringTypeImpl& impl) {\n    return os << impl.str_;\n  }\n  void AddToMessage(LogMessage& m) const {\n    if (str_type == StructuredStringType::kLiteral) {\n      return m.CopyToEncodedBufferWithStructuredProtoField<\n          log_internal::LogMessage::StringType::kLiteral>(field_, str_);\n    } else {\n      return m.CopyToEncodedBufferWithStructuredProtoField<\n          log_internal::LogMessage::StringType::kNotLiteral>(field_, str_);\n    }\n  }\n  friend LogMessage& operator<<(LogMessage& m,\n                                const AsStructuredStringTypeImpl& impl) {\n    impl.AddToMessage(m);\n    return m;\n  }\n};\n\nusing AsStructuredLiteralImpl =\n    AsStructuredStringTypeImpl<StructuredStringType::kLiteral>;\nusing AsStructuredNotLiteralImpl =\n    AsStructuredStringTypeImpl<StructuredStringType::kNotLiteral>;\n\n// Structured log data for a stringifyable type T and associated structured\n// proto field, both of which must outlive this object.\ntemplate <typename T>\nclass [[nodiscard]] AsStructuredValueImpl final {\n public:\n  using ValueFormatter = absl::AnyInvocable<std::string(T) const>;\n\n  constexpr AsStructuredValueImpl(\n      T value ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      ValueFormatter value_formatter =\n          [](T value) { return absl::StrCat(value); })\n      : value_(value),\n        field_(field),\n        value_formatter_(std::move(value_formatter)) {}\n\n private:\n  T value_;\n  StructuredProtoField field_;\n  ValueFormatter value_formatter_;\n\n  friend std::ostream& operator<<(std::ostream& os,\n                                  const AsStructuredValueImpl& impl) {\n    return os << impl.value_formatter_(impl.value_);\n  }\n  void AddToMessage(LogMessage& m) const {\n    m.CopyToEncodedBufferWithStructuredProtoField<\n        log_internal::LogMessage::StringType::kNotLiteral>(\n        field_, value_formatter_(value_));\n  }\n  friend LogMessage& operator<<(LogMessage& m,\n                                const AsStructuredValueImpl& impl) {\n    impl.AddToMessage(m);\n    return m;\n  }\n};\n\n// Template deduction guide so `AsStructuredValueImpl(42, data)` works\n// without specifying the template type.\ntemplate <typename T>\nAsStructuredValueImpl(T value, StructuredProtoField field)\n    -> AsStructuredValueImpl<T>;\n\n// Template deduction guide so `AsStructuredValueImpl(42, data, formatter)`\n// works without specifying the template type.\ntemplate <typename T>\nAsStructuredValueImpl(\n    T value, StructuredProtoField field,\n    typename AsStructuredValueImpl<T>::ValueFormatter value_formatter)\n    -> AsStructuredValueImpl<T>;\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_STRUCTURED_H_\n"
  },
  {
    "path": "absl/log/internal/structured_proto.cc",
    "content": "//\n// Copyright 2024 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/structured_proto.h\"\n\n#include <cstdint>\n#include <variant>\n\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/proto.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nnamespace {\n\n// Handles protobuf-encoding a type contained inside\n// `StructuredProtoField::Varint`.\nstruct VarintEncoderVisitor final {\n  template <typename T>\n  bool operator()(T value) const {\n    return EncodeVarint(field_number, value, &buf);\n  }\n\n  uint64_t field_number;\n  absl::Span<char>& buf;\n};\n\n// Handles protobuf-encoding a type contained inside\n// `StructuredProtoField::I64`.\nstruct I64EncoderVisitor final {\n  bool operator()(uint64_t value) const {\n    return Encode64Bit(field_number, value, &buf);\n  }\n\n  bool operator()(int64_t value) const {\n    return Encode64Bit(field_number, value, &buf);\n  }\n\n  bool operator()(double value) const {\n    return EncodeDouble(field_number, value, &buf);\n  }\n\n  uint64_t field_number;\n  absl::Span<char>& buf;\n};\n\n// Handles protobuf-encoding a type contained inside\n// `StructuredProtoField::I32`.\nstruct I32EncoderVisitor final {\n  bool operator()(uint32_t value) const {\n    return Encode32Bit(field_number, value, &buf);\n  }\n\n  bool operator()(int32_t value) const {\n    return Encode32Bit(field_number, value, &buf);\n  }\n\n  bool operator()(float value) const {\n    return EncodeFloat(field_number, value, &buf);\n  }\n\n  uint64_t field_number;\n  absl::Span<char>& buf;\n};\n\n// Handles protobuf-encoding a type contained inside `StructuredProtoField`.\nstruct EncoderVisitor final {\n  bool operator()(StructuredProtoField::Varint varint) {\n    return std::visit(VarintEncoderVisitor{field_number, buf}, varint);\n  }\n\n  bool operator()(StructuredProtoField::I64 i64) {\n    return std::visit(I64EncoderVisitor{field_number, buf}, i64);\n  }\n\n  bool operator()(StructuredProtoField::LengthDelimited length_delimited) {\n    // No need for a visitor, since `StructuredProtoField::LengthDelimited` is\n    // just `absl::Span<const char>`.\n    return EncodeBytes(field_number, length_delimited, &buf);\n  }\n\n  bool operator()(StructuredProtoField::I32 i32) {\n    return std::visit(I32EncoderVisitor{field_number, buf}, i32);\n  }\n\n  uint64_t field_number;\n  absl::Span<char>& buf;\n};\n\n}  // namespace\n\nbool EncodeStructuredProtoField(StructuredProtoField field,\n                                absl::Span<char>& buf) {\n  return std::visit(EncoderVisitor{field.field_number, buf}, field.value);\n}\n\n}  // namespace log_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/structured_proto.h",
    "content": "// Copyright 2024 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/structured_proto.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_\n#define ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <variant>\n\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/proto.h\"\n#include \"absl/types/span.h\"\n#include \"absl/types/variant.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// Sum type holding a single valid protobuf field suitable for encoding.\nstruct StructuredProtoField final {\n  // Numeric type encoded with varint encoding:\n  // https://protobuf.dev/programming-guides/encoding/#varints\n  using Varint = std::variant<uint64_t, int64_t, uint32_t, int32_t, bool>;\n\n  // Fixed-length 64-bit integer encoding:\n  // https://protobuf.dev/programming-guides/encoding/#non-varints\n  using I64 = std::variant<uint64_t, int64_t, double>;\n\n  // Length-delimited record type (string, sub-message):\n  // https://protobuf.dev/programming-guides/encoding/#length-types\n  using LengthDelimited = absl::Span<const char>;\n\n  // Fixed-length 32-bit integer encoding:\n  // https://protobuf.dev/programming-guides/encoding/#non-varints\n  using I32 = std::variant<uint32_t, int32_t, float>;\n\n  // Valid record type:\n  // https://protobuf.dev/programming-guides/encoding/#structure\n  using Value = std::variant<Varint, I64, LengthDelimited, I32>;\n\n  // Field number for the protobuf value.\n  uint64_t field_number;\n\n  // Value to encode.\n  Value value;\n};\n\n// Estimates the number of bytes needed to encode `field` using\n// protobuf encoding.\n//\n// The returned value might be larger than the actual number of bytes needed.\ninline size_t BufferSizeForStructuredProtoField(StructuredProtoField field) {\n  // Visitor to estimate the number of bytes of one of the types contained\n  // inside `StructuredProtoField`.\n  struct BufferSizeVisitor final {\n    size_t operator()(StructuredProtoField::Varint /*unused*/) {\n      return BufferSizeFor(field_number, WireType::kVarint);\n    }\n\n    size_t operator()(StructuredProtoField::I64 /*unused*/) {\n      return BufferSizeFor(field_number, WireType::k64Bit);\n    }\n\n    size_t operator()(StructuredProtoField::LengthDelimited length_delimited) {\n      return BufferSizeFor(field_number, WireType::kLengthDelimited) +\n             length_delimited.size();\n    }\n\n    size_t operator()(StructuredProtoField::I32 /*unused*/) {\n      return BufferSizeFor(field_number, WireType::k32Bit);\n    }\n\n    uint64_t field_number;\n  };\n\n  return std::visit(BufferSizeVisitor{field.field_number}, field.value);\n}\n\n// Encodes `field` into `buf` using protobuf encoding.\n//\n// On success, returns `true` and advances `buf` to the end of\n// the bytes consumed.\n//\n// On failure (if `buf` was too small), returns `false`.\nbool EncodeStructuredProtoField(StructuredProtoField field,\n                                absl::Span<char>& buf);\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_\n"
  },
  {
    "path": "absl/log/internal/structured_proto_test.cc",
    "content": "//\n// Copyright 2024 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/structured_proto.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\n\nusing ::testing::TestWithParam;\n\nstruct StructuredProtoTestCase {\n  std::string test_name;\n  StructuredProtoField field;\n  std::vector<char> expected_encoded_field;\n};\n\nusing StructuredProtoTest = TestWithParam<StructuredProtoTestCase>;\n\nTEST_P(StructuredProtoTest, Encoding) {\n  const StructuredProtoTestCase& test_case = GetParam();\n\n  // Greater than or equal to since BufferSizeForStructuredProtoField() is just\n  // an estimate of the data size and not an exact measurement.\n  ASSERT_GE(BufferSizeForStructuredProtoField(test_case.field),\n            test_case.expected_encoded_field.size());\n\n  std::vector<char> buf;\n  buf.resize(1024);\n\n  absl::Span<char> buf_span(buf);\n  EXPECT_TRUE(EncodeStructuredProtoField(test_case.field, buf_span));\n  size_t encoded_field_size = buf.size() - buf_span.size();\n\n  ASSERT_EQ(encoded_field_size, test_case.expected_encoded_field.size());\n  buf.resize(encoded_field_size);\n  EXPECT_EQ(buf, test_case.expected_encoded_field);\n}\n\nINSTANTIATE_TEST_SUITE_P(\n    StructuredProtoTestSuiteInstantiation,\n    StructuredProtoTest,  // This is the name of your parameterized test\n    testing::ValuesIn<StructuredProtoTestCase>({\n        {\n            \"Varint\",\n            {\n                42,\n                StructuredProtoField::Value{\n                    absl::in_place_type<StructuredProtoField::Varint>,\n                    int32_t{23},\n                },\n            },\n            {'\\xD0', '\\x02', '\\x17'},\n        },\n        {\n            \"I64\",\n            {\n                42,\n                StructuredProtoField::Value{\n                    absl::in_place_type<StructuredProtoField::I64>,\n                    int64_t{23},\n                },\n            },\n            {'\\xD1', '\\x02', '\\x17', '\\x00', '\\x00', '\\x00', '\\x00', '\\x00',\n             '\\x00', '\\x00'},\n        },\n        {\n            \"LengthDelimited\",\n            {\n                42,\n                // Use a string_view so the terminating NUL is excluded.\n                absl::string_view(\"Hello\"),\n            },\n            {'\\xD2', '\\x02', '\\x05', 'H', 'e', 'l', 'l', 'o'},\n        },\n        {\n            \"I32\",\n            {\n                42,\n                StructuredProtoField::Value{\n                    absl::in_place_type<StructuredProtoField::I32>,\n                    int32_t{23},\n                },\n            },\n            {'\\xD5', '\\x02', '\\x17', '\\x00', '\\x00', '\\x00'},\n        },\n    }),\n    [](const testing::TestParamInfo<StructuredProtoTest::ParamType>& info) {\n      return info.param.test_name;\n    });\n\n}  // namespace\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/test_actions.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/test_actions.h\"\n\n#include <cassert>\n#include <iostream>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nvoid WriteToStderrWithFilename::operator()(const absl::LogEntry& entry) const {\n  std::cerr << message << \" (file: \" << entry.source_filename() << \")\\n\";\n}\n\nvoid WriteEntryToStderr::operator()(const absl::LogEntry& entry) const {\n  if (!message.empty()) std::cerr << message << \"\\n\";\n\n  const std::string source_filename = absl::CHexEscape(entry.source_filename());\n  const std::string source_basename = absl::CHexEscape(entry.source_basename());\n  const std::string text_message = absl::CHexEscape(entry.text_message());\n  const std::string encoded_message = absl::CHexEscape(entry.encoded_message());\n  std::string encoded_message_str;\n  std::cerr << \"LogEntry{\\n\"                                               //\n            << \"  source_filename: \\\"\" << source_filename << \"\\\"\\n\"        //\n            << \"  source_basename: \\\"\" << source_basename << \"\\\"\\n\"        //\n            << \"  source_line: \" << entry.source_line() << \"\\n\"            //\n            << \"  prefix: \" << (entry.prefix() ? \"true\\n\" : \"false\\n\")     //\n            << \"  log_severity: \" << entry.log_severity() << \"\\n\"          //\n            << \"  timestamp: \" << entry.timestamp() << \"\\n\"                //\n            << \"  text_message: \\\"\" << text_message << \"\\\"\\n\"              //\n            << \"  verbosity: \" << entry.verbosity() << \"\\n\"                //\n            << \"  encoded_message (raw): \\\"\" << encoded_message << \"\\\"\\n\"  //\n            << encoded_message_str                                         //\n            << \"}\\n\";\n}\n\nvoid WriteEntryToStderr::operator()(absl::LogSeverity severity,\n                                    absl::string_view filename,\n                                    absl::string_view log_message) const {\n  if (!message.empty()) std::cerr << message << \"\\n\";\n  const std::string source_filename = absl::CHexEscape(filename);\n  const std::string text_message = absl::CHexEscape(log_message);\n  std::cerr << \"LogEntry{\\n\"                                         //\n            << \"  source_filename: \\\"\" << source_filename << \"\\\"\\n\"  //\n            << \"  log_severity: \" << severity << \"\\n\"                //\n            << \"  text_message: \\\"\" << text_message << \"\\\"\\n\"        //\n            << \"}\\n\";\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/test_actions.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/test_actions.h\n// -----------------------------------------------------------------------------\n//\n// This file declares Googletest's actions used in the Abseil Logging library\n// unit tests.\n\n#ifndef ABSL_LOG_INTERNAL_TEST_ACTIONS_H_\n#define ABSL_LOG_INTERNAL_TEST_ACTIONS_H_\n\n#include <iostream>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// These actions are used by the child process in a death test.\n//\n// Expectations set in the child cannot cause test failure in the parent\n// directly.  Instead, the child can use these actions with\n// `EXPECT_CALL`/`WillOnce` and `ON_CALL`/`WillByDefault` (for unexpected calls)\n// to write messages to stderr that the parent can match against.\nstruct WriteToStderr final {\n  explicit WriteToStderr(absl::string_view m) : message(m) {}\n  std::string message;\n\n  template <typename... Args>\n  void operator()(const Args&...) const {\n    std::cerr << message << std::endl;\n  }\n};\n\nstruct WriteToStderrWithFilename final {\n  explicit WriteToStderrWithFilename(absl::string_view m) : message(m) {}\n\n  std::string message;\n\n  void operator()(const absl::LogEntry& entry) const;\n};\n\nstruct WriteEntryToStderr final {\n  explicit WriteEntryToStderr(absl::string_view m) : message(m) {}\n\n  std::string message = \"\";\n\n  void operator()(const absl::LogEntry& entry) const;\n  void operator()(absl::LogSeverity, absl::string_view,\n                  absl::string_view) const;\n};\n\n// See the documentation for `DeathTestValidateExpectations` above.\n// `DeathTestExpectedLogging` should be used once in a given death test, and the\n// applicable severity level is the one that should be passed to\n// `DeathTestValidateExpectations`.\ninline WriteEntryToStderr DeathTestExpectedLogging() {\n  return WriteEntryToStderr{\"Mock received expected entry:\"};\n}\n\n// `DeathTestUnexpectedLogging` should be used zero or more times to mark\n// messages that should not hit the logs as the process dies.\ninline WriteEntryToStderr DeathTestUnexpectedLogging() {\n  return WriteEntryToStderr{\"Mock received unexpected entry:\"};\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_TEST_ACTIONS_H_\n"
  },
  {
    "path": "absl/log/internal/test_helpers.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#include \"absl/log/internal/test_helpers.h\"\n\n#ifdef __Fuchsia__\n#include <zircon/syscalls.h>\n#endif\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/initialize.h\"\n#include \"absl/log/internal/globals.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// Returns false if the specified severity level is disabled by\n// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.\nbool LoggingEnabledAt(absl::LogSeverity severity) {\n  return severity >= kAbslMinLogLevel && severity >= absl::MinLogLevel();\n}\n\n// -----------------------------------------------------------------------------\n// Googletest Death Test Predicates\n// -----------------------------------------------------------------------------\n\n#if GTEST_HAS_DEATH_TEST\n\nbool DiedOfFatal(int exit_status) {\n#if defined(_WIN32)\n  // Depending on NDEBUG and (configuration?) MSVC's abort either results\n  // in error code 3 (SIGABRT) or error code 0x80000003 (breakpoint\n  // triggered).\n  return ::testing::ExitedWithCode(3)(exit_status & 0x7fffffff);\n#elif defined(__Fuchsia__)\n  // The Fuchsia death test implementation kill()'s the process when it detects\n  // an exception, so it should exit with the corresponding code. See\n  // FuchsiaDeathTest::Wait().\n  return ::testing::ExitedWithCode(ZX_TASK_RETCODE_SYSCALL_KILL)(exit_status);\n#elif defined(__ANDROID__) && defined(__aarch64__)\n  // These are all run under a qemu config that eats died-due-to-signal exit\n  // statuses.\n  return true;\n#else\n  return ::testing::KilledBySignal(SIGABRT)(exit_status);\n#endif\n}\n\nbool DiedOfQFatal(int exit_status) {\n  return ::testing::ExitedWithCode(1)(exit_status);\n}\n\n#endif\n\n// -----------------------------------------------------------------------------\n// Helper for Log initialization in test\n// -----------------------------------------------------------------------------\n\nvoid LogTestEnvironment::SetUp() {\n  if (!absl::log_internal::IsInitialized()) {\n    absl::InitializeLog();\n  }\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/test_helpers.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/test_helpers.h\n// -----------------------------------------------------------------------------\n//\n// This file declares testing helpers for the logging library.\n\n#ifndef ABSL_LOG_INTERNAL_TEST_HELPERS_H_\n#define ABSL_LOG_INTERNAL_TEST_HELPERS_H_\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/globals.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\n// `ABSL_MIN_LOG_LEVEL` can't be used directly since it is not always defined.\nconstexpr auto kAbslMinLogLevel =\n#ifdef ABSL_MIN_LOG_LEVEL\n    static_cast<absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL);\n#else\n    absl::LogSeverityAtLeast::kInfo;\n#endif\n\n// Returns false if the specified severity level is disabled by\n// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.\nbool LoggingEnabledAt(absl::LogSeverity severity);\n\n// -----------------------------------------------------------------------------\n// Googletest Death Test Predicates\n// -----------------------------------------------------------------------------\n\n#if GTEST_HAS_DEATH_TEST\n\nbool DiedOfFatal(int exit_status);\nbool DiedOfQFatal(int exit_status);\n\n#endif\n\n// -----------------------------------------------------------------------------\n// Helper for Log initialization in test\n// -----------------------------------------------------------------------------\n\nclass LogTestEnvironment : public ::testing::Environment {\n public:\n  ~LogTestEnvironment() override = default;\n\n  void SetUp() override;\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_TEST_HELPERS_H_\n"
  },
  {
    "path": "absl/log/internal/test_matchers.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/test_matchers.h\"\n\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\nnamespace {\nusing ::testing::_;\nusing ::testing::AllOf;\nusing ::testing::Ge;\nusing ::testing::HasSubstr;\nusing ::testing::MakeMatcher;\nusing ::testing::Matcher;\nusing ::testing::MatcherInterface;\nusing ::testing::MatchResultListener;\nusing ::testing::Not;\nusing ::testing::Property;\nusing ::testing::ResultOf;\nusing ::testing::Truly;\n\nclass AsStringImpl final\n    : public MatcherInterface<absl::string_view> {\n public:\n  explicit AsStringImpl(\n      const Matcher<const std::string&>& str_matcher)\n      : str_matcher_(str_matcher) {}\n  bool MatchAndExplain(\n      absl::string_view actual,\n      MatchResultListener* listener) const override {\n    return str_matcher_.MatchAndExplain(std::string(actual), listener);\n  }\n  void DescribeTo(std::ostream* os) const override {\n    return str_matcher_.DescribeTo(os);\n  }\n\n  void DescribeNegationTo(std::ostream* os) const override {\n    return str_matcher_.DescribeNegationTo(os);\n  }\n\n private:\n  const Matcher<const std::string&> str_matcher_;\n};\n\nclass MatchesOstreamImpl final\n    : public MatcherInterface<absl::string_view> {\n public:\n  explicit MatchesOstreamImpl(std::string expected)\n      : expected_(std::move(expected)) {}\n  bool MatchAndExplain(absl::string_view actual,\n                       MatchResultListener*) const override {\n    return actual == expected_;\n  }\n  void DescribeTo(std::ostream* os) const override {\n    *os << \"matches the contents of the ostringstream, which are \\\"\"\n        << expected_ << \"\\\"\";\n  }\n\n  void DescribeNegationTo(std::ostream* os) const override {\n    *os << \"does not match the contents of the ostringstream, which are \\\"\"\n        << expected_ << \"\\\"\";\n  }\n\n private:\n  const std::string expected_;\n};\n}  // namespace\n\nMatcher<absl::string_view> AsString(\n    const Matcher<const std::string&>& str_matcher) {\n  return MakeMatcher(new AsStringImpl(str_matcher));\n}\n\nMatcher<const absl::LogEntry&> SourceFilename(\n    const Matcher<absl::string_view>& source_filename) {\n  return Property(\"source_filename\", &absl::LogEntry::source_filename,\n                  source_filename);\n}\n\nMatcher<const absl::LogEntry&> SourceBasename(\n    const Matcher<absl::string_view>& source_basename) {\n  return Property(\"source_basename\", &absl::LogEntry::source_basename,\n                  source_basename);\n}\n\nMatcher<const absl::LogEntry&> SourceLine(\n    const Matcher<int>& source_line) {\n  return Property(\"source_line\", &absl::LogEntry::source_line, source_line);\n}\n\nMatcher<const absl::LogEntry&> Prefix(\n    const Matcher<bool>& prefix) {\n  return Property(\"prefix\", &absl::LogEntry::prefix, prefix);\n}\n\nMatcher<const absl::LogEntry&> LogSeverity(\n    const Matcher<absl::LogSeverity>& log_severity) {\n  return Property(\"log_severity\", &absl::LogEntry::log_severity, log_severity);\n}\n\nMatcher<const absl::LogEntry&> Timestamp(\n    const Matcher<absl::Time>& timestamp) {\n  return Property(\"timestamp\", &absl::LogEntry::timestamp, timestamp);\n}\n\nMatcher<absl::Time> InMatchWindow() {\n  return AllOf(Ge(absl::Now()),\n               Truly([](absl::Time arg) { return arg <= absl::Now(); }));\n}\n\nMatcher<const absl::LogEntry&> ThreadID(\n    const Matcher<absl::LogEntry::tid_t>& tid) {\n  return Property(\"tid\", &absl::LogEntry::tid, tid);\n}\n\nMatcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(\n    const Matcher<absl::string_view>&\n        text_message_with_prefix_and_newline) {\n  return Property(\"text_message_with_prefix_and_newline\",\n                  &absl::LogEntry::text_message_with_prefix_and_newline,\n                  text_message_with_prefix_and_newline);\n}\n\nMatcher<const absl::LogEntry&> TextMessageWithPrefix(\n    const Matcher<absl::string_view>& text_message_with_prefix) {\n  return Property(\"text_message_with_prefix\",\n                  &absl::LogEntry::text_message_with_prefix,\n                  text_message_with_prefix);\n}\n\nMatcher<const absl::LogEntry&> TextMessage(\n    const Matcher<absl::string_view>& text_message) {\n  return Property(\"text_message\", &absl::LogEntry::text_message, text_message);\n}\n\nMatcher<const absl::LogEntry&> TextPrefix(\n    const Matcher<absl::string_view>& text_prefix) {\n  return ResultOf(\n      [](const absl::LogEntry& entry) {\n        absl::string_view msg = entry.text_message_with_prefix();\n        msg.remove_suffix(entry.text_message().size());\n        return msg;\n      },\n      text_prefix);\n}\nMatcher<const absl::LogEntry&> RawEncodedMessage(\n    const Matcher<absl::string_view>& raw_encoded_message) {\n  return Property(\"encoded_message\", &absl::LogEntry::encoded_message,\n                  raw_encoded_message);\n}\n\nMatcher<const absl::LogEntry&> Verbosity(\n    const Matcher<int>& verbosity) {\n  return Property(\"verbosity\", &absl::LogEntry::verbosity, verbosity);\n}\n\nMatcher<const absl::LogEntry&> Stacktrace(\n    const Matcher<absl::string_view>& stacktrace) {\n  return Property(\"stacktrace\", &absl::LogEntry::stacktrace, stacktrace);\n}\n\nMatcher<absl::string_view> MatchesOstream(\n    const std::ostringstream& stream) {\n  return MakeMatcher(new MatchesOstreamImpl(stream.str()));\n}\n\n// We need to validate what is and isn't logged as the process dies due to\n// `FATAL`, `QFATAL`, `CHECK`, etc., but assertions inside a death test\n// subprocess don't directly affect the pass/fail status of the parent process.\n// Instead, we use the mock actions `DeathTestExpectedLogging` and\n// `DeathTestUnexpectedLogging` to write specific phrases to `stderr` that we\n// can validate in the parent process using this matcher.\nMatcher<const std::string&> DeathTestValidateExpectations() {\n  if (log_internal::LoggingEnabledAt(absl::LogSeverity::kFatal)) {\n    return Matcher<const std::string&>(\n        AllOf(HasSubstr(\"Mock received expected entry\"),\n              Not(HasSubstr(\"Mock received unexpected entry\"))));\n  }\n  // If `FATAL` logging is disabled, neither message should have been written.\n  return Matcher<const std::string&>(\n      AllOf(Not(HasSubstr(\"Mock received expected entry\")),\n            Not(HasSubstr(\"Mock received unexpected entry\"))));\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/test_matchers.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/test_matchers.h\n// -----------------------------------------------------------------------------\n//\n// This file declares Googletest's matchers used in the Abseil Logging library\n// unit tests.\n\n#ifndef ABSL_LOG_INTERNAL_TEST_MATCHERS_H_\n#define ABSL_LOG_INTERNAL_TEST_MATCHERS_H_\n\n#include <iosfwd>\n#include <sstream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n// In some configurations, Googletest's string matchers (e.g.\n// `::testing::EndsWith`) need help to match `absl::string_view`.\n::testing::Matcher<absl::string_view> AsString(\n    const ::testing::Matcher<const std::string&>& str_matcher);\n\n// These matchers correspond to the components of `absl::LogEntry`.\n::testing::Matcher<const absl::LogEntry&> SourceFilename(\n    const ::testing::Matcher<absl::string_view>& source_filename);\n::testing::Matcher<const absl::LogEntry&> SourceBasename(\n    const ::testing::Matcher<absl::string_view>& source_basename);\n// Be careful with this one; multi-line statements using `__LINE__` evaluate\n// differently on different platforms.  In particular, the MSVC implementation\n// of `EXPECT_DEATH` returns the line number of the macro expansion to all lines\n// within the code block that's expected to die.\n::testing::Matcher<const absl::LogEntry&> SourceLine(\n    const ::testing::Matcher<int>& source_line);\n::testing::Matcher<const absl::LogEntry&> Prefix(\n    const ::testing::Matcher<bool>& prefix);\n::testing::Matcher<const absl::LogEntry&> LogSeverity(\n    const ::testing::Matcher<absl::LogSeverity>& log_severity);\n::testing::Matcher<const absl::LogEntry&> Timestamp(\n    const ::testing::Matcher<absl::Time>& timestamp);\n// Matches if the `LogEntry`'s timestamp falls after the instantiation of this\n// matcher and before its execution, as is normal when used with EXPECT_CALL.\n::testing::Matcher<absl::Time> InMatchWindow();\n::testing::Matcher<const absl::LogEntry&> ThreadID(\n    const ::testing::Matcher<absl::LogEntry::tid_t>&);\n::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(\n    const ::testing::Matcher<absl::string_view>&\n        text_message_with_prefix_and_newline);\n::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefix(\n    const ::testing::Matcher<absl::string_view>& text_message_with_prefix);\n::testing::Matcher<const absl::LogEntry&> TextMessage(\n    const ::testing::Matcher<absl::string_view>& text_message);\n::testing::Matcher<const absl::LogEntry&> TextPrefix(\n    const ::testing::Matcher<absl::string_view>& text_prefix);\n::testing::Matcher<const absl::LogEntry&> Verbosity(\n    const ::testing::Matcher<int>& verbosity);\n::testing::Matcher<const absl::LogEntry&> Stacktrace(\n    const ::testing::Matcher<absl::string_view>& stacktrace);\n// Behaves as `Eq(stream.str())`, but produces better failure messages.\n::testing::Matcher<absl::string_view> MatchesOstream(\n    const std::ostringstream& stream);\n::testing::Matcher<const std::string&> DeathTestValidateExpectations();\n\n::testing::Matcher<const absl::LogEntry&> RawEncodedMessage(\n    const ::testing::Matcher<absl::string_view>& raw_encoded_message);\n#define ENCODED_MESSAGE(message_matcher) ::testing::_\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_TEST_MATCHERS_H_\n"
  },
  {
    "path": "absl/log/internal/vlog_config.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/internal/vlog_config.h\"\n\n#include <stddef.h>\n\n#include <algorithm>\n#include <atomic>\n#include <functional>\n#include <memory>\n#include <optional>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/log/internal/fnmatch.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nnamespace {\n\n#ifdef _WIN32\nconstexpr char kPathSeparators[] = \"/\\\\\";\n#else\nconstexpr char kPathSeparators[] = \"/\";\n#endif\n\nbool ModuleIsPath(absl::string_view module_pattern) {\n  return module_pattern.find_first_of(kPathSeparators) != module_pattern.npos;\n}\n\nabsl::string_view Basename(absl::string_view file) {\n  auto sep = file.find_last_of(kPathSeparators);\n  if (sep != file.npos) {\n    file.remove_prefix(sep + 1);\n  }\n  return file;\n}\n\n}  // namespace\n\nbool VLogSite::SlowIsEnabled(int stale_v, int level) {\n  if (ABSL_PREDICT_TRUE(stale_v != kUninitialized)) {\n    // Because of the prerequisites to this function, we know that stale_v is\n    // either uninitialized or >= level. If it's not uninitialized, that means\n    // it must be >= level, thus we should log.\n    return true;\n  }\n  stale_v = log_internal::RegisterAndInitialize(this);\n  return ABSL_PREDICT_FALSE(stale_v >= level);\n}\n\nbool VLogSite::SlowIsEnabled0(int stale_v) { return SlowIsEnabled(stale_v, 0); }\nbool VLogSite::SlowIsEnabled1(int stale_v) { return SlowIsEnabled(stale_v, 1); }\nbool VLogSite::SlowIsEnabled2(int stale_v) { return SlowIsEnabled(stale_v, 2); }\nbool VLogSite::SlowIsEnabled3(int stale_v) { return SlowIsEnabled(stale_v, 3); }\nbool VLogSite::SlowIsEnabled4(int stale_v) { return SlowIsEnabled(stale_v, 4); }\nbool VLogSite::SlowIsEnabled5(int stale_v) { return SlowIsEnabled(stale_v, 5); }\n\nnamespace {\nstruct VModuleInfo final {\n  std::string module_pattern;\n  bool module_is_path;  // i.e. it contains a path separator.\n  int vlog_level;\n\n  // Allocates memory.\n  VModuleInfo(absl::string_view module_pattern_arg, bool module_is_path_arg,\n              int vlog_level_arg)\n      : module_pattern(std::string(module_pattern_arg)),\n        module_is_path(module_is_path_arg),\n        vlog_level(vlog_level_arg) {}\n};\n\n// `mutex` guards all of the data structures that aren't lock-free.\n// To avoid problems with the heap checker which calls into `VLOG`, `mutex` must\n// be a `SpinLock` that prevents fiber scheduling instead of a `Mutex`.\nABSL_CONST_INIT absl::base_internal::SpinLock mutex(\n    absl::base_internal::SCHEDULE_KERNEL_ONLY);\n\n// `GetUpdateSitesMutex()` serializes updates to all of the sites (i.e. those in\n// `site_list_head`) themselves.\nabsl::Mutex& GetUpdateSitesMutex() {\n  // Chromium requires no global destructors, so we can't use the\n  // absl::kConstInit idiom since absl::Mutex as a non-trivial destructor.\n  static absl::NoDestructor<absl::Mutex> update_sites_mutex ABSL_ACQUIRED_AFTER(\n      mutex);\n  return *update_sites_mutex;\n}\n\nABSL_CONST_INIT int global_v ABSL_GUARDED_BY(mutex) = 0;\n// `site_list_head` is the head of a singly-linked list.  Traversal, insertion,\n// and reads are atomic, so no locks are required, but updates to existing\n// elements are guarded by `GetUpdateSitesMutex()`.\nABSL_CONST_INIT std::atomic<VLogSite*> site_list_head{nullptr};\nABSL_CONST_INIT std::vector<VModuleInfo>* vmodule_info ABSL_GUARDED_BY(mutex)\n    ABSL_PT_GUARDED_BY(mutex){nullptr};\n\n// Only used for lisp.\nABSL_CONST_INIT std::vector<std::function<void()>>* update_callbacks\n    ABSL_GUARDED_BY(GetUpdateSitesMutex())\n        ABSL_PT_GUARDED_BY(GetUpdateSitesMutex()){nullptr};\n\n// Allocates memory.\nstd::vector<VModuleInfo>& get_vmodule_info()\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) {\n  if (!vmodule_info) vmodule_info = new std::vector<VModuleInfo>;\n  return *vmodule_info;\n}\n\n// Does not allocate or take locks.\nint VLogLevel(absl::string_view file, const std::vector<VModuleInfo>* infos,\n              int current_global_v) {\n  // `infos` is null during a call to `VLOG` prior to setting `vmodule` (e.g. by\n  // parsing flags).  We can't allocate in `VLOG`, so we treat null as empty\n  // here and press on.\n  if (!infos || infos->empty()) return current_global_v;\n\n  absl::string_view stem = file;\n  absl::string_view stem_basename = Basename(stem);\n  {\n    const size_t sep = stem_basename.find('.');\n    if (sep != stem_basename.npos) {\n      stem.remove_suffix(stem_basename.size() - sep);\n      stem_basename.remove_suffix(stem_basename.size() - sep);\n    }\n    if (absl::ConsumeSuffix(&stem_basename, \"-inl\")) {\n      stem.remove_suffix(absl::string_view(\"-inl\").size());\n    }\n  }\n  for (const auto& info : *infos) {\n    if (info.module_is_path) {\n      // If there are any slashes in the pattern, try to match the full\n      // name.\n      if (FNMatch(info.module_pattern, stem)) {\n        return info.vlog_level;\n      }\n    } else if (FNMatch(info.module_pattern, stem_basename)) {\n      return info.vlog_level;\n    }\n  }\n\n  return current_global_v;\n}\n\n// Allocates memory.\nint AppendVModuleLocked(absl::string_view module_pattern, int log_level)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) {\n  for (const auto& info : get_vmodule_info()) {\n    if (FNMatch(info.module_pattern, module_pattern)) {\n      // This is a memory optimization to avoid storing patterns that will never\n      // match due to exit early semantics. Primarily optimized for our own unit\n      // tests.\n      return info.vlog_level;\n    }\n  }\n  bool module_is_path = ModuleIsPath(module_pattern);\n  get_vmodule_info().emplace_back(std::string(module_pattern), module_is_path,\n                                  log_level);\n  return global_v;\n}\n\n// Allocates memory.\nint PrependVModuleLocked(absl::string_view module_pattern, int log_level)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) {\n  std::optional<int> old_log_level;\n  for (const auto& info : get_vmodule_info()) {\n    if (FNMatch(info.module_pattern, module_pattern)) {\n      old_log_level = info.vlog_level;\n      break;\n    }\n  }\n  bool module_is_path = ModuleIsPath(module_pattern);\n  auto iter = get_vmodule_info().emplace(get_vmodule_info().cbegin(),\n                                         std::string(module_pattern),\n                                         module_is_path, log_level);\n\n  // This is a memory optimization to avoid storing patterns that will never\n  // match due to exit early semantics. Primarily optimized for our own unit\n  // tests.\n  get_vmodule_info().erase(\n      std::remove_if(++iter, get_vmodule_info().end(),\n                     [module_pattern](const VModuleInfo& info) {\n                       // Remove the previous pattern if it is less generic than\n                       // the new one. For example, if the new pattern\n                       // `module_pattern` is \"foo*\" and the previous pattern\n                       // `info.module_pattern` is \"foo\", we should remove the\n                       // previous pattern. Because the new pattern \"foo*\" will\n                       // match all the files that the previous pattern \"foo\"\n                       // matches.\n                       return FNMatch(module_pattern, info.module_pattern);\n                     }),\n      get_vmodule_info().cend());\n  return old_log_level.value_or(global_v);\n}\n}  // namespace\n\nint VLogLevel(absl::string_view file) ABSL_LOCKS_EXCLUDED(mutex) {\n  absl::base_internal::SpinLockHolder l(mutex);\n  return VLogLevel(file, vmodule_info, global_v);\n}\n\nint RegisterAndInitialize(VLogSite* v) ABSL_LOCKS_EXCLUDED(mutex) {\n  // std::memory_order_seq_cst is overkill in this function, but given that this\n  // path is intended to be slow, it's not worth the brain power to relax that.\n  VLogSite* h = site_list_head.load(std::memory_order_seq_cst);\n\n  VLogSite* old = nullptr;\n  if (v->next_.compare_exchange_strong(old, h, std::memory_order_seq_cst,\n                                       std::memory_order_seq_cst)) {\n    // Multiple threads may attempt to register this site concurrently.\n    // By successfully setting `v->next` this thread commits to being *the*\n    // thread that installs `v` in the list.\n    while (!site_list_head.compare_exchange_weak(\n        h, v, std::memory_order_seq_cst, std::memory_order_seq_cst)) {\n      v->next_.store(h, std::memory_order_seq_cst);\n    }\n  }\n\n  int old_v = VLogSite::kUninitialized;\n  int new_v = VLogLevel(v->file_);\n  // No loop, if someone else set this, we should respect their evaluation of\n  // `VLogLevel`. This may mean we return a stale `v`, but `v` itself will\n  // always arrive at the freshest value.  Otherwise, we could be writing a\n  // stale value and clobbering the fresher one.\n  if (v->v_.compare_exchange_strong(old_v, new_v, std::memory_order_seq_cst,\n                                    std::memory_order_seq_cst)) {\n    return new_v;\n  }\n  return old_v;\n}\n\nvoid UpdateVLogSites() ABSL_UNLOCK_FUNCTION(mutex)\n    ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) {\n  std::vector<VModuleInfo> infos = get_vmodule_info();\n  int current_global_v = global_v;\n  // We need to grab `GetUpdateSitesMutex()` before we release `mutex` to ensure\n  // that updates are not interleaved (resulting in an inconsistent final state)\n  // and to ensure that the final state in the sites matches the final state of\n  // `vmodule_info`. We unlock `mutex` to ensure that uninitialized sites don't\n  // have to wait on all updates in order to acquire `mutex` and initialize\n  // themselves.\n  absl::MutexLock ul(GetUpdateSitesMutex());\n  mutex.unlock();\n  VLogSite* n = site_list_head.load(std::memory_order_seq_cst);\n  // Because sites are added to the list in the order they are executed, there\n  // tend to be clusters of entries with the same file.\n  const char* last_file = nullptr;\n  int last_file_level = 0;\n  while (n != nullptr) {\n    if (n->file_ != last_file) {\n      last_file = n->file_;\n      last_file_level = VLogLevel(n->file_, &infos, current_global_v);\n    }\n    n->v_.store(last_file_level, std::memory_order_seq_cst);\n    n = n->next_.load(std::memory_order_seq_cst);\n  }\n  if (update_callbacks) {\n    for (auto& cb : *update_callbacks) {\n      cb();\n    }\n  }\n}\n\nvoid UpdateVModule(absl::string_view vmodule)\n    ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) {\n  std::vector<std::pair<absl::string_view, int>> glob_levels;\n  for (absl::string_view glob_level : absl::StrSplit(vmodule, ',')) {\n    const size_t eq = glob_level.rfind('=');\n    if (eq == glob_level.npos) continue;\n    const absl::string_view glob = glob_level.substr(0, eq);\n    int level;\n    if (!absl::SimpleAtoi(glob_level.substr(eq + 1), &level)) continue;\n    glob_levels.emplace_back(glob, level);\n  }\n  mutex.lock();  // unlocked by UpdateVLogSites().\n  get_vmodule_info().clear();\n  for (const auto& it : glob_levels) {\n    const absl::string_view glob = it.first;\n    const int level = it.second;\n    AppendVModuleLocked(glob, level);\n  }\n  UpdateVLogSites();\n}\n\nint UpdateGlobalVLogLevel(int v)\n    ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) {\n  mutex.lock();  // unlocked by UpdateVLogSites().\n  const int old_global_v = global_v;\n  if (v == global_v) {\n    mutex.unlock();\n    return old_global_v;\n  }\n  global_v = v;\n  UpdateVLogSites();\n  return old_global_v;\n}\n\nint PrependVModule(absl::string_view module_pattern, int log_level)\n    ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) {\n  mutex.lock();  // unlocked by UpdateVLogSites().\n  int old_v = PrependVModuleLocked(module_pattern, log_level);\n  UpdateVLogSites();\n  return old_v;\n}\n\nvoid OnVLogVerbosityUpdate(std::function<void()> cb)\n    ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) {\n  absl::MutexLock ul(GetUpdateSitesMutex());\n  if (!update_callbacks)\n    update_callbacks = new std::vector<std::function<void()>>;\n  update_callbacks->push_back(std::move(cb));\n}\n\nVLogSite* SetVModuleListHeadForTestOnly(VLogSite* v) {\n  return site_list_head.exchange(v, std::memory_order_seq_cst);\n}\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/vlog_config.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// vlog_config.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines `VLogSite`, a public primitive that represents\n// a callsite for the `VLOG` family of macros and related libraries.\n// It also declares and defines multiple internal utilities used to implement\n// `VLOG`, such as `VLogSiteManager`.\n\n#ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_\n#define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_\n\n// IWYU pragma: private, include \"absl/log/log.h\"\n\n#include <atomic>\n#include <cstdint>\n#include <functional>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nclass SyntheticBinary;\nclass VLogSite;\n\nint RegisterAndInitialize(VLogSite* absl_nonnull v);\nvoid UpdateVLogSites();\n\n// Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call.\n//\n// Libraries that provide `VLOG`-like functionality should use this to\n// efficiently handle --vmodule.\n//\n// VLogSite objects must not be destroyed until the program exits. Doing so will\n// probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The\n// recommendation is to make all such objects function-local statics.\nclass VLogSite final {\n public:\n  // `f` must not be destroyed until the program exits.\n  explicit constexpr VLogSite(const char* absl_nonnull f)\n      : file_(f), v_(kUninitialized), next_(nullptr) {}\n  VLogSite(const VLogSite&) = delete;\n  VLogSite& operator=(const VLogSite&) = delete;\n\n  // Inlining the function yields a ~3x performance improvement at the cost of a\n  // 1.5x code size increase at the call site.\n  // Takes locks but does not allocate memory.\n  ABSL_ATTRIBUTE_ALWAYS_INLINE\n  bool IsEnabled(int level) {\n    int stale_v = v_.load(std::memory_order_relaxed);\n    if (ABSL_PREDICT_TRUE(level > stale_v)) {\n      return false;\n    }\n\n    // We put everything other than the fast path, i.e. vlogging is initialized\n    // but not on, behind an out-of-line function to reduce code size.\n    // \"level\" is almost always a call-site constant, so we can save a bit\n    // of code space by special-casing for a few common levels.\n#if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__)\n    if (__builtin_constant_p(level)) {\n      if (level == 0) return SlowIsEnabled0(stale_v);\n      if (level == 1) return SlowIsEnabled1(stale_v);\n      if (level == 2) return SlowIsEnabled2(stale_v);\n      if (level == 3) return SlowIsEnabled3(stale_v);\n      if (level == 4) return SlowIsEnabled4(stale_v);\n      if (level == 5) return SlowIsEnabled5(stale_v);\n    }\n#endif\n    return SlowIsEnabled(stale_v, level);\n  }\n\n private:\n  friend int log_internal::RegisterAndInitialize(VLogSite* absl_nonnull v);\n  friend void log_internal::UpdateVLogSites();\n  friend class log_internal::SyntheticBinary;\n  static constexpr int kUninitialized = (std::numeric_limits<int>::max)();\n\n  // SlowIsEnabled performs slower checks to determine whether a log site is\n  // enabled. Because it is expected to be called somewhat rarely\n  // (comparatively), it is not inlined to save on code size.\n  //\n  // Prerequisites to calling SlowIsEnabled:\n  //   1) stale_v is uninitialized OR\n  //   2) stale_v is initialized and >= level (meaning we must log).\n  // Takes locks but does not allocate memory.\n  ABSL_ATTRIBUTE_NOINLINE\n  bool SlowIsEnabled(int stale_v, int level);\n  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v);\n  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v);\n  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v);\n  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v);\n  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v);\n  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v);\n\n  // This object is too size-sensitive to use absl::string_view.\n  const char* absl_nonnull const file_;\n  std::atomic<int> v_;\n  std::atomic<VLogSite*> next_;\n};\nstatic_assert(std::is_trivially_destructible<VLogSite>::value,\n              \"VLogSite must be trivially destructible\");\n\n// Returns the current verbose log level of `file`.\n// Does not allocate memory.\nint VLogLevel(absl::string_view file);\n\n// Registers a site `v` to get updated as `vmodule` and `v` change.  Also\n// initializes the site based on their current values, and returns that result.\n// Does not allocate memory.\nint RegisterAndInitialize(VLogSite* absl_nonnull v);\n\n// Allocates memory.\nvoid UpdateVLogSites();\n\n// Completely overwrites the saved value of `vmodule`.\n// Allocates memory.\nvoid UpdateVModule(absl::string_view vmodule);\n\n// Updates the global verbosity level to `v` and returns the prior value.\n// Allocates memory.\nint UpdateGlobalVLogLevel(int v);\n\n// Atomically prepends `module_pattern=log_level` to the start of vmodule.\n// Returns the prior value for `module_pattern` if there was an exact match and\n// `global_v` otherwise.\n// Allocates memory.\nint PrependVModule(absl::string_view module_pattern, int log_level);\n\n// Registers `on_update` to be called whenever `v` or `vmodule` change.\n// Allocates memory.\nvoid OnVLogVerbosityUpdate(std::function<void()> cb);\n\n// Does not allocate memory.\nVLogSite* absl_nullable SetVModuleListHeadForTestOnly(\n    VLogSite* absl_nullable v);\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_\n"
  },
  {
    "path": "absl/log/internal/vlog_config_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <atomic>\n#include <cstddef>\n#include <cstring>\n#include <memory>\n#include <new>\n#include <random>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/layout.h\"\n#include \"absl/log/internal/vlog_config.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n// Performance of `UpdateLogSites` depends upon the number and organization of\n// `VLogSite`s in the program.  We can synthesize some on the heap to mimic\n// their layout and linkage in static data.\nclass SyntheticBinary {\n public:\n  explicit SyntheticBinary(const size_t num_tus,\n                           const size_t max_extra_static_data_bytes_per_tu,\n                           const size_t max_sites_per_tu,\n                           const int num_shuffles) {\n    per_tu_data_.reserve(num_tus);\n    auto sites = absl::make_unique<VLogSite *[]>(num_tus * max_sites_per_tu);\n    for (size_t i = 0; i < num_tus; i++) {\n      const std::string filename =\n          absl::StrCat(\"directory-\", i / 100, \"/subdirectory-\", i % 100 / 10,\n                       \"/file-\", i % 10, \".cc\");\n      container_internal::Layout<char, VLogSite, char> layout(\n          filename.size() + 1,\n          absl::LogUniform<size_t>(bitgen_, 1, max_sites_per_tu),\n          absl::LogUniform<size_t>(bitgen_, 0,\n                                   max_extra_static_data_bytes_per_tu));\n      auto buf = absl::make_unique<char[]>(layout.AllocSize());\n      layout.PoisonPadding(buf.get());\n      memcpy(layout.Pointer<0>(buf.get()), filename.c_str(),\n             filename.size() + 1);\n      for (VLogSite &site : layout.Slice<1>(buf.get())) {\n        sites[num_sites_++] =\n            new (&site) VLogSite(layout.Pointer<0>(buf.get()));\n        // The last one is a dangling pointer but will be fixed below.\n        site.next_.store(&site + 1, std::memory_order_seq_cst);\n      }\n      num_extra_static_data_bytes_ += layout.Size<2>();\n      per_tu_data_.push_back(PerTU{layout, std::move(buf)});\n    }\n    // Now link the files together back-to-front into a circular list.\n    for (size_t i = 0; i < num_tus; i++) {\n      auto &tu = per_tu_data_[i];\n      auto &next_tu = per_tu_data_[(i + 1) % num_tus];\n      tu.layout.Slice<1>(tu.buf.get())\n          .back()\n          .next_.store(next_tu.layout.Pointer<1>(next_tu.buf.get()),\n                       std::memory_order_seq_cst);\n    }\n    // Now do some shufflin'.\n    auto new_sites = absl::make_unique<VLogSite *[]>(num_sites_);\n    for (int shuffle_num = 0; shuffle_num < num_shuffles; shuffle_num++) {\n      // Each shuffle cuts the ring into three pieces and rearranges them.\n      const size_t cut_a = absl::Uniform(bitgen_, size_t{0}, num_sites_);\n      const size_t cut_b = absl::Uniform(bitgen_, size_t{0}, num_sites_);\n      const size_t cut_c = absl::Uniform(bitgen_, size_t{0}, num_sites_);\n      if (cut_a == cut_b || cut_b == cut_c || cut_a == cut_c) continue;\n      // The same cuts, sorted:\n      const size_t cut_1 = std::min({cut_a, cut_b, cut_c});\n      const size_t cut_3 = std::max({cut_a, cut_b, cut_c});\n      const size_t cut_2 = cut_a ^ cut_b ^ cut_c ^ cut_1 ^ cut_3;\n      VLogSite *const tmp = sites[cut_1]->next_.load(std::memory_order_seq_cst);\n      sites[cut_1]->next_.store(\n          sites[cut_2]->next_.load(std::memory_order_seq_cst),\n          std::memory_order_seq_cst);\n      sites[cut_2]->next_.store(\n          sites[cut_3]->next_.load(std::memory_order_seq_cst),\n          std::memory_order_seq_cst);\n      sites[cut_3]->next_.store(tmp, std::memory_order_seq_cst);\n      memcpy(&new_sites[0], &sites[0], sizeof(VLogSite *) * (cut_1 + 1));\n      memcpy(&new_sites[cut_1 + 1], &sites[cut_2 + 1],\n             sizeof(VLogSite *) * (cut_3 - cut_2));\n      memcpy(&new_sites[cut_1 + 1 + cut_3 - cut_2], &sites[cut_1 + 1],\n             sizeof(VLogSite *) * (cut_2 - cut_1));\n      memcpy(&new_sites[cut_3 + 1], &sites[cut_3 + 1],\n             sizeof(VLogSite *) * (num_sites_ - cut_3 - 1));\n      sites.swap(new_sites);\n    }\n    const char *last_file = nullptr;\n    for (size_t i = 0; i < num_sites_; i++) {\n      if (sites[i]->file_ == last_file) continue;\n      last_file = sites[i]->file_;\n      num_new_files_++;\n    }\n    absl::log_internal::SetVModuleListHeadForTestOnly(sites[0]);\n    sites[num_tus - 1]->next_.store(nullptr, std::memory_order_seq_cst);\n  }\n  ~SyntheticBinary() {\n    static_assert(std::is_trivially_destructible<VLogSite>::value, \"\");\n    absl::log_internal::SetVModuleListHeadForTestOnly(nullptr);\n  }\n\n  size_t num_sites() const { return num_sites_; }\n  size_t num_new_files() const { return num_new_files_; }\n  size_t num_extra_static_data_bytes() const {\n    return num_extra_static_data_bytes_;\n  }\n\n private:\n  struct PerTU {\n    container_internal::Layout<char, VLogSite, char> layout;\n    std::unique_ptr<char[]> buf;\n  };\n\n  std::mt19937 bitgen_;\n  std::vector<PerTU> per_tu_data_;\n  size_t num_sites_ = 0;\n  size_t num_new_files_ = 0;\n  size_t num_extra_static_data_bytes_ = 0;\n};\n\nnamespace {\nvoid BM_UpdateVModuleEmpty(benchmark::State& state) {\n  SyntheticBinary bin(static_cast<size_t>(state.range(0)), 10 * 1024 * 1024,\n                      256, state.range(1));\n  for (auto s : state) {\n    absl::log_internal::UpdateVModule(\"\");\n  }\n  state.SetItemsProcessed(static_cast<int>(bin.num_new_files()));\n}\nBENCHMARK(BM_UpdateVModuleEmpty)\n    ->ArgPair(100, 200)\n    ->ArgPair(1000, 2000)\n    ->ArgPair(10000, 20000);\n\nvoid BM_UpdateVModuleShort(benchmark::State& state) {\n  SyntheticBinary bin(static_cast<size_t>(state.range(0)), 10 * 1024 * 1024,\n                      256, state.range(1));\n  for (auto s : state) {\n    absl::log_internal::UpdateVModule(\"directory2/*=4\");\n  }\n  state.SetItemsProcessed(static_cast<int>(bin.num_new_files()));\n}\nBENCHMARK(BM_UpdateVModuleShort)\n    ->ArgPair(100, 200)\n    ->ArgPair(1000, 2000)\n    ->ArgPair(10000, 20000);\n\nvoid BM_UpdateVModuleLong(benchmark::State& state) {\n  SyntheticBinary bin(static_cast<size_t>(state.range(0)), 10 * 1024 * 1024,\n                      256, state.range(1));\n  for (auto s : state) {\n    absl::log_internal::UpdateVModule(\n        \"d?r?c?o?y2/*=4,d?*r?*c?**o?*y1/*=2,d?*rc?**o?*y3/*=2,,\"\n        \"d?*r?*c?**o?*1/*=1,d?*r?**o?*y1/*=2,d?*r???***y1/*=7,\"\n        \"d?*r?**o?*y1/aaa=6\");\n  }\n  state.SetItemsProcessed(static_cast<int>(bin.num_new_files()));\n}\nBENCHMARK(BM_UpdateVModuleLong)\n    ->ArgPair(100, 200)\n    ->ArgPair(1000, 2000)\n    ->ArgPair(10000, 20000);\n}  // namespace\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/internal/voidify.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/internal/voidify.h\n// -----------------------------------------------------------------------------\n//\n// This class does the dispatching of the completed `absl::LogEntry` to\n// applicable `absl::LogSink`s, and is used to explicitly ignore values in the\n// conditional logging macros. This avoids compiler warnings like \"value\n// computed is not used\" and \"statement has no effect\".\n\n#ifndef ABSL_LOG_INTERNAL_VOIDIFY_H_\n#define ABSL_LOG_INTERNAL_VOIDIFY_H_\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nclass Voidify final {\n public:\n  // This has to be an operator with a precedence lower than << but higher than\n  // ?:\n  template <typename T>\n  ABSL_ATTRIBUTE_COLD void operator&&(T&& message) const&& {\n    // The dispatching of the completed `absl::LogEntry` to applicable\n    // `absl::LogSink`s happens here.\n    message.Flush();\n  }\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_INTERNAL_VOIDIFY_H_\n"
  },
  {
    "path": "absl/log/log.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/log.h\n// -----------------------------------------------------------------------------\n//\n// This header declares a family of LOG macros.\n//\n// Basic invocation looks like this:\n//\n//   LOG(INFO) << \"Found \" << num_cookies << \" cookies\";\n//\n// Most `LOG` macros take a severity level argument.  The severity levels are\n// `INFO`, `WARNING`, `ERROR`, and `FATAL`.  They are defined\n// in absl/base/log_severity.h.\n// * The `FATAL` severity level terminates the program with a stack trace after\n//   logging its message.  Error handlers registered with `RunOnFailure`\n//   (process_state.h) are run, but exit handlers registered with `atexit(3)`\n//   are not.\n// * The `QFATAL` pseudo-severity level is equivalent to `FATAL` but triggers\n//   quieter termination messages, e.g. without a full stack trace, and skips\n//   running registered error handlers.\n// * The `DFATAL` pseudo-severity level is defined as `FATAL` in debug mode and\n//   as `ERROR` otherwise.\n// * The `DO_NOT_SUBMIT` pseudo-severity level is an alias for `ERROR`, and is\n//   intended for debugging statements that won't be submitted.  The name is\n//   chosen to be easy to spot in review and with tools in order to ensure that\n//   such statements aren't inadvertently checked in.\n//   The contract is that **it may not be checked in**, meaning that no\n//   in-contract uses will be affected if we decide in the future to remove it\n//   or change what it does.\n// Some preprocessor shenanigans are used to ensure that e.g. `LOG(INFO)` has\n// the same meaning even if a local symbol or preprocessor macro named `INFO` is\n// defined.  To specify a severity level using an expression instead of a\n// literal, use `LEVEL(expr)`.\n// Example:\n//\n//   LOG(LEVEL(stale ? absl::LogSeverity::kWarning : absl::LogSeverity::kInfo))\n//       << \"Cookies are \" << days << \" days old\";\n\n// `LOG` macros evaluate to an unterminated statement.  The value at the end of\n// the statement supports some chainable methods:\n//\n//   * .AtLocation(absl::string_view file, int line)\n//     .AtLocation(absl::SourceLocation loc)\n//     Overrides the location inferred from the callsite.  The string pointed to\n//     by `file` must be valid until the end of the statement.\n//   * .NoPrefix()\n//     Omits the prefix from this line.  The prefix includes metadata about the\n//     logged data such as source code location and timestamp.\n//   * .WithVerbosity(int verbose_level)\n//     Sets the verbosity field of the logged message as if it was logged by\n//     `VLOG(verbose_level)`.  Unlike `VLOG`, this method does not affect\n//     evaluation of the statement when the specified `verbose_level` has been\n//     disabled.  The only effect is on `LogSink` implementations which make use\n//     of the `absl::LogSink::verbosity()` value.  The value\n//     `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message\n//     not verbose.\n//   * .WithTimestamp(absl::Time timestamp)\n//     Uses the specified timestamp instead of one collected at the time of\n//     execution.\n//   * .WithThreadID(absl::LogEntry::tid_t tid)\n//     Uses the specified thread ID instead of one collected at the time of\n//     execution.\n//   * .WithMetadataFrom(const absl::LogEntry &entry)\n//     Copies all metadata (but no data) from the specified `absl::LogEntry`.\n//     This can be used to change the severity of a message, but it has some\n//     limitations:\n//     * `ABSL_MIN_LOG_LEVEL` is evaluated against the severity passed into\n//       `LOG` (or the implicit `FATAL` level of `CHECK`).\n//     * `LOG(FATAL)` and `CHECK` terminate the process unconditionally, even if\n//       the severity is changed later.\n//     `.WithMetadataFrom(entry)` should almost always be used in combination\n//     with `LOG(LEVEL(entry.log_severity()))`.\n//   * .WithPerror()\n//     Appends to the logged message a colon, a space, a textual description of\n//     the current value of `errno` (as by `strerror(3)`), and the numerical\n//     value of `errno`.\n//   * .ToSinkAlso(absl::LogSink* sink)\n//     Sends this message to `*sink` in addition to whatever other sinks it\n//     would otherwise have been sent to.  `sink` must not be null.\n//   * .ToSinkOnly(absl::LogSink* sink)\n//     Sends this message to `*sink` and no others.  `sink` must not be null.\n//\n// No interfaces in this header are async-signal-safe; their use in signal\n// handlers is unsupported and may deadlock your program or eat your lunch.\n//\n// Many logging statements are inherently conditional.  For example,\n// `LOG_IF(INFO, !foo)` does nothing if `foo` is true.  Even seemingly\n// unconditional statements like `LOG(INFO)` might be disabled at\n// compile-time to minimize binary size or for security reasons.\n//\n// * Except for the condition in a `CHECK` or `QCHECK` statement, programs must\n//   not rely on evaluation of expressions anywhere in logging statements for\n//   correctness.  For example, this is ok:\n//\n//     CHECK((fp = fopen(\"config.ini\", \"r\")) != nullptr);\n//\n//   But this is probably not ok:\n//\n//     LOG(INFO) << \"Server status: \" << StartServerAndReturnStatusString();\n//\n//   The example below is bad too; the `i++` in the `LOG_IF` condition might\n//   not be evaluated, resulting in an infinite loop:\n//\n//     for (int i = 0; i < 1000000;)\n//       LOG_IF(INFO, i++ % 1000 == 0) << \"Still working...\";\n//\n// * Except where otherwise noted, conditions which cause a statement not to log\n//   also cause expressions not to be evaluated.  Programs may rely on this for\n//   performance reasons, e.g. by streaming the result of an expensive function\n//   call into a `DLOG` or `LOG_EVERY_N` statement.\n// * Care has been taken to ensure that expressions are parsed by the compiler\n//   even if they are never evaluated.  This means that syntax errors will be\n//   caught and variables will be considered used for the purposes of\n//   unused-variable diagnostics.  For example, this statement won't compile\n//   even if `INFO`-level logging has been compiled out:\n//\n//     int number_of_cakes = 40;\n//     LOG(INFO) << \"Number of cakes: \" << number_of_cake;  // Note the typo!\n//\n//   Similarly, this won't produce unused-variable compiler diagnostics even\n//   if `INFO`-level logging is compiled out:\n//\n//     {\n//       char fox_line1[] = \"Hatee-hatee-hatee-ho!\";\n//       LOG_IF(ERROR, false) << \"The fox says \" << fox_line1;\n//       char fox_line2[] = \"A-oo-oo-oo-ooo!\";\n//       LOG(INFO) << \"The fox also says \" << fox_line2;\n//     }\n//\n//   This error-checking is not perfect; for example, symbols that have been\n//   declared but not defined may not produce link errors if used in logging\n//   statements that compile away.\n//\n// Expressions streamed into these macros are formatted using `operator<<` just\n// as they would be if streamed into a `std::ostream`, however it should be\n// noted that their actual type is unspecified.\n//\n// To implement a custom formatting operator for a type you own, there are two\n// options: `AbslStringify()` or `std::ostream& operator<<(std::ostream&, ...)`.\n// It is recommended that users make their types loggable through\n// `AbslStringify()` as it is a universal stringification extension that also\n// enables `absl::StrFormat` and `absl::StrCat` support. If both\n// `AbslStringify()` and `std::ostream& operator<<(std::ostream&, ...)` are\n// defined, `AbslStringify()` will be used.\n//\n// To use the `AbslStringify()` API, define a friend function template in your\n// type's namespace with the following signature:\n//\n//   template <typename Sink>\n//   void AbslStringify(Sink& sink, const UserDefinedType& value);\n//\n// `Sink` has the same interface as `absl::FormatSink`, but without\n// `PutPaddedString()`.\n//\n// Example:\n//\n//   struct Point {\n//     template <typename Sink>\n//     friend void AbslStringify(Sink& sink, const Point& p) {\n//       absl::Format(&sink, \"(%v, %v)\", p.x, p.y);\n//     }\n//\n//     int x;\n//     int y;\n//   };\n//\n// To use `std::ostream& operator<<(std::ostream&, ...)`, define\n// `std::ostream& operator<<(std::ostream&, ...)` in your type's namespace (for\n// ADL) just as you would to stream it to `std::cout`.\n//\n// Currently `AbslStringify()` ignores output manipulators but this is not\n// guaranteed behavior and may be subject to change in the future. If you would\n// like guaranteed behavior regarding output manipulators, please use\n// `std::ostream& operator<<(std::ostream&, ...)` to make custom types loggable\n// instead.\n//\n// Those macros that support streaming honor output manipulators and `fmtflag`\n// changes that output data (e.g. `std::ends`) or control formatting of data\n// (e.g. `std::hex` and `std::fixed`), however flushing such a stream is\n// ignored.  The message produced by a log statement is sent to registered\n// `absl::LogSink` instances at the end of the statement; those sinks are\n// responsible for their own flushing (e.g. to disk) semantics.\n//\n// Flag settings are not carried over from one `LOG` statement to the next; this\n// is a bit different than e.g. `std::cout`:\n//\n//   LOG(INFO) << std::hex << 0xdeadbeef;  // logs \"0xdeadbeef\"\n//   LOG(INFO) << 0xdeadbeef;              // logs \"3735928559\"\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_LOG_LOG_H_\n#define ABSL_LOG_LOG_H_\n\n#include \"absl/log/internal/log_impl.h\"\n\n// LOG()\n//\n// `LOG` takes a single argument which is a severity level.  Data streamed in\n// comprise the logged message.\n// Example:\n//\n//   LOG(INFO) << \"Found \" << num_cookies << \" cookies\";\n#define LOG(severity) ABSL_LOG_INTERNAL_LOG_IMPL(_##severity)\n\n// PLOG()\n//\n// `PLOG` behaves like `LOG` except that a description of the current state of\n// `errno` is appended to the streamed message.\n#define PLOG(severity) ABSL_LOG_INTERNAL_PLOG_IMPL(_##severity)\n\n// DLOG()\n//\n// `DLOG` behaves like `LOG` in debug mode (i.e. `#ifndef NDEBUG`).  Otherwise\n// it compiles away and does nothing.  Note that `DLOG(FATAL)` does not\n// terminate the program if `NDEBUG` is defined.\n#define DLOG(severity) ABSL_LOG_INTERNAL_DLOG_IMPL(_##severity)\n\n// `VLOG` uses numeric levels to provide verbose logging that can configured at\n// runtime, including at a per-module level.  `VLOG` statements are logged at\n// `INFO` severity if they are logged at all; the numeric levels are on a\n// different scale than the proper severity levels.  Positive levels are\n// disabled by default.  Negative levels should not be used.\n// Example:\n//\n//   VLOG(1) << \"I print when you run the program with --v=1 or higher\";\n//   VLOG(2) << \"I print when you run the program with --v=2 or higher\";\n//\n// See vlog_is_on.h for further documentation, including the usage of the\n// --vmodule flag to log at different levels in different source files.\n//\n// `VLOG` does not produce any output when verbose logging is not enabled.\n// However, simply testing whether verbose logging is enabled can be expensive.\n// If you don't intend to enable verbose logging in non-debug builds, consider\n// using `DVLOG` instead.\n#define VLOG(verbose_level) ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level)\n\n// `DVLOG` behaves like `VLOG` in debug mode (i.e. `#ifndef NDEBUG`).\n// Otherwise, it compiles away and does nothing.\n#define DVLOG(verbose_level) ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level)\n\n// `LOG_IF` and friends add a second argument which specifies a condition.  If\n// the condition is false, nothing is logged.\n// Example:\n//\n//   LOG_IF(INFO, num_cookies > 10) << \"Got lots of cookies\";\n//\n// There is no `VLOG_IF` because the order of evaluation of the arguments is\n// ambiguous and the alternate spelling with an `if`-statement is trivial.\n#define LOG_IF(severity, condition) \\\n  ABSL_LOG_INTERNAL_LOG_IF_IMPL(_##severity, condition)\n#define PLOG_IF(severity, condition) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_IMPL(_##severity, condition)\n#define DLOG_IF(severity, condition) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_IMPL(_##severity, condition)\n\n// LOG_EVERY_N\n// LOG_FIRST_N\n// LOG_EVERY_POW_2\n// LOG_EVERY_N_SEC\n//\n// These \"stateful\" macros log conditionally based on a hidden counter or timer.\n// When the condition is false and no logging is done, streamed operands aren't\n// evaluated either.  Each instance has its own state (i.e. counter, timer)\n// that's independent of other instances of the macros.  The macros in this\n// family are thread-safe in the sense that they are meant to be called\n// concurrently and will not invoke undefined behavior, however their\n// implementation prioritizes efficiency over exactness and may occasionally log\n// more or less often than specified.\n//\n//   * `LOG_EVERY_N` logs the first time and once every `n` times thereafter.\n//   * `LOG_FIRST_N` logs the first `n` times and then stops.\n//   * `LOG_EVERY_POW_2` logs the first, second, fourth, eighth, etc. times.\n//   * `LOG_EVERY_N_SEC` logs the first time and no more than once every `n`\n//     seconds thereafter.  `n` is passed as a floating point value.\n//\n// The `LOG_IF`... variations with an extra condition evaluate the specified\n// condition first and short-circuit if it is false.  For example, an evaluation\n// of `LOG_IF_FIRST_N` does not count against the first `n` if the specified\n// condition is false.  Stateful `VLOG`... variations likewise short-circuit\n// if `VLOG` is disabled.\n//\n// An approximate count of the number of times a particular instance's stateful\n// condition has been evaluated (i.e. excluding those where a specified `LOG_IF`\n// condition was false) can be included in the logged message by streaming the\n// symbol `COUNTER`.\n//\n// The `n` parameter need not be a constant.  Conditional logging following a\n// change to `n` isn't fully specified, but it should converge on the new value\n// within roughly `max(old_n, new_n)` evaluations or seconds.\n//\n// Examples:\n//\n//   LOG_EVERY_N(WARNING, 1000) << \"Got a packet with a bad CRC (\" << COUNTER\n//                              << \" total)\";\n//\n//   LOG_EVERY_N_SEC(INFO, 2.5) << \"Got \" << COUNTER << \" cookies so far\";\n//\n//   LOG_IF_EVERY_N(INFO, (size > 1024), 10) << \"Got the \" << COUNTER\n//                                           << \"th big cookie\";\n#define LOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(_##severity, n)\n#define LOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(_##severity, n)\n#define LOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(_##severity)\n#define LOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)\n\n#define PLOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(_##severity, n)\n#define PLOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(_##severity, n)\n#define PLOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(_##severity)\n#define PLOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)\n\n#define DLOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(_##severity, n)\n#define DLOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(_##severity, n)\n#define DLOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(_##severity)\n#define DLOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)\n\n#define VLOG_EVERY_N(severity, n) \\\n  ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(severity, n)\n#define VLOG_FIRST_N(severity, n) \\\n  ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(severity, n)\n#define VLOG_EVERY_POW_2(severity) \\\n  ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(severity)\n#define VLOG_EVERY_N_SEC(severity, n_seconds) \\\n  ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(severity, n_seconds)\n\n#define LOG_IF_EVERY_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(_##severity, condition, n)\n#define LOG_IF_FIRST_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(_##severity, condition, n)\n#define LOG_IF_EVERY_POW_2(severity, condition) \\\n  ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(_##severity, condition)\n#define LOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \\\n  ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)\n\n#define PLOG_IF_EVERY_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(_##severity, condition, n)\n#define PLOG_IF_FIRST_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(_##severity, condition, n)\n#define PLOG_IF_EVERY_POW_2(severity, condition) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)\n#define PLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \\\n  ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)\n\n#define DLOG_IF_EVERY_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(_##severity, condition, n)\n#define DLOG_IF_FIRST_N(severity, condition, n) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(_##severity, condition, n)\n#define DLOG_IF_EVERY_POW_2(severity, condition) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)\n#define DLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \\\n  ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)\n\n#endif  // ABSL_LOG_LOG_H_\n"
  },
  {
    "path": "absl/log/log_basic_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/log.h\"\n\n#define ABSL_TEST_LOG LOG\n#define ABSL_TEST_DLOG DLOG\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/log_basic_test_impl.inc\"\n"
  },
  {
    "path": "absl/log/log_basic_test_impl.inc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n// The testcases in this file are expected to pass or be skipped with any value\n// of ABSL_MIN_LOG_LEVEL\n\n#ifndef ABSL_LOG_LOG_BASIC_TEST_IMPL_H_\n#define ABSL_LOG_LOG_BASIC_TEST_IMPL_H_\n\n// Verify that both sets of macros behave identically by parameterizing the\n// entire test file.\n#ifndef ABSL_TEST_LOG\n#error ABSL_TEST_LOG must be defined for these tests to work.\n#endif\n\n#ifndef ABSL_TEST_DLOG\n#error ABSL_TEST_DLOG must be defined for these tests to work.\n#endif\n\n#include <cerrno>\n#include <sstream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/globals.h\"\n#include \"absl/log/internal/test_actions.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/scoped_mock_log.h\"\n\nnamespace absl_log_internal {\n#if GTEST_HAS_DEATH_TEST\nusing ::absl::log_internal::DeathTestExpectedLogging;\nusing ::absl::log_internal::DeathTestUnexpectedLogging;\nusing ::absl::log_internal::DeathTestValidateExpectations;\nusing ::absl::log_internal::DiedOfFatal;\nusing ::absl::log_internal::DiedOfQFatal;\n#endif\nusing ::absl::log_internal::InMatchWindow;\nusing ::absl::log_internal::LoggingEnabledAt;\nusing ::absl::log_internal::LogSeverity;\nusing ::absl::log_internal::Prefix;\nusing ::absl::log_internal::SourceBasename;\nusing ::absl::log_internal::SourceFilename;\nusing ::absl::log_internal::SourceLine;\nusing ::absl::log_internal::Stacktrace;\nusing ::absl::log_internal::TextMessage;\nusing ::absl::log_internal::ThreadID;\nusing ::absl::log_internal::Timestamp;\nusing ::absl::log_internal::Verbosity;\nusing ::testing::AnyNumber;\nusing ::testing::Eq;\nusing ::testing::IsEmpty;\nusing ::testing::IsTrue;\n\nclass BasicLogTest : public testing::TestWithParam<absl::LogSeverityAtLeast> {};\n\nstd::string ThresholdName(\n    testing::TestParamInfo<absl::LogSeverityAtLeast> severity) {\n  std::stringstream ostr;\n  ostr << severity.param;\n  return ostr.str().substr(\n      severity.param == absl::LogSeverityAtLeast::kInfinity ? 0 : 2);\n}\n\nINSTANTIATE_TEST_SUITE_P(WithParam, BasicLogTest,\n                         testing::Values(absl::LogSeverityAtLeast::kInfo,\n                                         absl::LogSeverityAtLeast::kWarning,\n                                         absl::LogSeverityAtLeast::kError,\n                                         absl::LogSeverityAtLeast::kFatal,\n                                         absl::LogSeverityAtLeast::kInfinity),\n                         ThresholdName);\n\nTEST_P(BasicLogTest, Info) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(INFO) << \"hello world\"; };\n\n  if (LoggingEnabledAt(absl::LogSeverity::kInfo)) {\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(\n            SourceFilename(Eq(__FILE__)),\n            SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n            SourceLine(Eq(log_line)), Prefix(IsTrue()),\n            LogSeverity(Eq(absl::LogSeverity::kInfo)),\n            Timestamp(InMatchWindow()),\n            ThreadID(Eq(absl::base_internal::GetTID())),\n            TextMessage(Eq(\"hello world\")),\n            Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n            ENCODED_MESSAGE(MatchesEvent(\n                Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()),\n                ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n            Stacktrace(IsEmpty()))));\n  }\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\nTEST_P(BasicLogTest, Warning) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(WARNING) << \"hello world\"; };\n\n  if (LoggingEnabledAt(absl::LogSeverity::kWarning)) {\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(\n            SourceFilename(Eq(__FILE__)),\n            SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n            SourceLine(Eq(log_line)), Prefix(IsTrue()),\n            LogSeverity(Eq(absl::LogSeverity::kWarning)),\n            Timestamp(InMatchWindow()),\n            ThreadID(Eq(absl::base_internal::GetTID())),\n            TextMessage(Eq(\"hello world\")),\n            Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n            ENCODED_MESSAGE(MatchesEvent(\n                Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                Eq(logging::proto::WARNING), Eq(absl::base_internal::GetTID()),\n                ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n            Stacktrace(IsEmpty()))));\n  }\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\nTEST_P(BasicLogTest, Error) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(ERROR) << \"hello world\"; };\n\n  if (LoggingEnabledAt(absl::LogSeverity::kError)) {\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(\n            SourceFilename(Eq(__FILE__)),\n            SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n            SourceLine(Eq(log_line)), Prefix(IsTrue()),\n            LogSeverity(Eq(absl::LogSeverity::kError)),\n            Timestamp(InMatchWindow()),\n            ThreadID(Eq(absl::base_internal::GetTID())),\n            TextMessage(Eq(\"hello world\")),\n            Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n            ENCODED_MESSAGE(MatchesEvent(\n                Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),\n                ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n            Stacktrace(IsEmpty()))));\n  }\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\nTEST_P(BasicLogTest, DoNotSubmit) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(DO_NOT_SUBMIT) << \"hello world\"; };\n\n  if (LoggingEnabledAt(absl::LogSeverity::kError)) {\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(\n            SourceFilename(Eq(__FILE__)),\n            SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n            SourceLine(Eq(log_line)), Prefix(IsTrue()),\n            LogSeverity(Eq(absl::LogSeverity::kError)),\n            Timestamp(InMatchWindow()),\n            ThreadID(Eq(absl::base_internal::GetTID())),\n            TextMessage(Eq(\"hello world\")),\n            Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n            ENCODED_MESSAGE(MatchesEvent(\n                Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),\n                ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n            Stacktrace(IsEmpty()))));\n  }\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\n#if GTEST_HAS_DEATH_TEST\nusing BasicLogDeathTest = BasicLogTest;\n\nINSTANTIATE_TEST_SUITE_P(WithParam, BasicLogDeathTest,\n                         testing::Values(absl::LogSeverityAtLeast::kInfo,\n                                         absl::LogSeverityAtLeast::kFatal,\n                                         absl::LogSeverityAtLeast::kInfinity),\n                         ThresholdName);\n\nTEST_P(BasicLogDeathTest, Fatal) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(FATAL) << \"hello world\"; };\n\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink(\n            absl::MockLogDefault::kDisallowUnexpected);\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        ::testing::InSequence s;\n\n        // Note the logic in DeathTestValidateExpectations() caters for the case\n        // of logging being disabled at FATAL level.\n\n        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {\n          // The first call without the stack trace.\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(IsEmpty()))))\n              .WillOnce(DeathTestExpectedLogging());\n\n          // The second call with the stack trace.\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(Not(IsEmpty())))))\n              .WillOnce(DeathTestExpectedLogging());\n        }\n\n        test_sink.StartCapturingLogs();\n        do_log();\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\nTEST_P(BasicLogDeathTest, QFatal) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(QFATAL) << \"hello world\"; };\n\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink(\n            absl::MockLogDefault::kDisallowUnexpected);\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(IsEmpty()))))\n              .WillOnce(DeathTestExpectedLogging());\n        }\n\n        test_sink.StartCapturingLogs();\n        do_log();\n      },\n      DiedOfQFatal, DeathTestValidateExpectations());\n}\n#endif\n\n#ifdef NDEBUG\nTEST_P(BasicLogTest, DFatal) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(DFATAL) << \"hello world\"; };\n\n  if (LoggingEnabledAt(absl::LogSeverity::kError)) {\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(\n            SourceFilename(Eq(__FILE__)),\n            SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n            SourceLine(Eq(log_line)), Prefix(IsTrue()),\n            LogSeverity(Eq(absl::LogSeverity::kError)),\n            Timestamp(InMatchWindow()),\n            ThreadID(Eq(absl::base_internal::GetTID())),\n            TextMessage(Eq(\"hello world\")),\n            Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n            ENCODED_MESSAGE(MatchesEvent(\n                Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),\n                ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n            Stacktrace(IsEmpty()))));\n  }\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\n#elif GTEST_HAS_DEATH_TEST\nTEST_P(BasicLogDeathTest, DFatal) {\n  // TODO(b/242568884): re-enable once bug is fixed.\n  // absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { ABSL_TEST_LOG(DFATAL) << \"hello world\"; };\n\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink(\n            absl::MockLogDefault::kDisallowUnexpected);\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        ::testing::InSequence s;\n\n        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {\n          // The first call without the stack trace.\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(IsEmpty()))))\n              .WillOnce(DeathTestExpectedLogging());\n\n          // The second call with the stack trace.\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(Not(IsEmpty())))))\n              .WillOnce(DeathTestExpectedLogging());\n        }\n\n        test_sink.StartCapturingLogs();\n        do_log();\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n#endif\n\n#ifndef NDEBUG\nTEST_P(BasicLogTest, DFatalIsCancellable) {\n  // LOG(DFATAL) does not die when DFATAL death is disabled.\n  absl::log_internal::SetExitOnDFatal(false);\n  ABSL_TEST_LOG(DFATAL) << \"hello world\";\n  absl::log_internal::SetExitOnDFatal(true);\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST_P(BasicLogDeathTest, DLogFatalIsNotCancellable) {\n  EXPECT_EXIT(\n      {\n        absl::log_internal::SetExitOnDFatal(false);\n        ABSL_TEST_DLOG(FATAL) << \"hello world\";\n        absl::log_internal::SetExitOnDFatal(true);\n      },\n      DiedOfFatal, \"\");\n}\n#endif\n#endif\n\nTEST_P(BasicLogTest, Level) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  for (auto severity : {absl::LogSeverity::kInfo, absl::LogSeverity::kWarning,\n                        absl::LogSeverity::kError}) {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n\n    const int log_line = __LINE__ + 2;\n    auto do_log = [severity] {\n      ABSL_TEST_LOG(LEVEL(severity)) << \"hello world\";\n    };\n\n    if (LoggingEnabledAt(severity)) {\n      EXPECT_CALL(\n          test_sink,\n          Send(AllOf(\n              SourceFilename(Eq(__FILE__)),\n              SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n              SourceLine(Eq(log_line)), Prefix(IsTrue()),\n              LogSeverity(Eq(severity)), Timestamp(InMatchWindow()),\n              ThreadID(Eq(absl::base_internal::GetTID())),\n              TextMessage(Eq(\"hello world\")),\n              Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n              ENCODED_MESSAGE(MatchesEvent(\n                  Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                  Eq(severity == absl::LogSeverity::kInfo ? logging::proto::INFO\n                     : severity == absl::LogSeverity::kWarning\n                         ? logging::proto::WARNING\n                     : severity == absl::LogSeverity::kError\n                         ? logging::proto::ERROR\n                         : 0),\n                  Eq(absl::base_internal::GetTID()),\n                  ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n              Stacktrace(IsEmpty()))));\n    }\n    test_sink.StartCapturingLogs();\n    do_log();\n  }\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST_P(BasicLogDeathTest, Level) {\n  // TODO(b/242568884): re-enable once bug is fixed.\n  // absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  // Ensure that `severity` is not a compile-time constant to prove that\n  // `LOG(LEVEL(severity))` works regardless:\n  auto volatile severity = absl::LogSeverity::kFatal;\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [severity] { ABSL_TEST_LOG(LEVEL(severity)) << \"hello world\"; };\n\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink(\n            absl::MockLogDefault::kDisallowUnexpected);\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        ::testing::InSequence s;\n\n        if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(IsEmpty()))))\n              .WillOnce(DeathTestExpectedLogging());\n\n          EXPECT_CALL(\n              test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_basic_test_impl.inc\")),\n                         SourceLine(Eq(log_line)), Prefix(IsTrue()),\n                         LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                         Timestamp(InMatchWindow()),\n                         ThreadID(Eq(absl::base_internal::GetTID())),\n                         TextMessage(Eq(\"hello world\")),\n                         Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),\n                         ENCODED_MESSAGE(MatchesEvent(\n                             Eq(__FILE__), Eq(log_line), InMatchWindow(),\n                             Eq(logging::proto::FATAL),\n                             Eq(absl::base_internal::GetTID()),\n                             ElementsAre(ValueWithLiteral(Eq(\"hello world\"))))),\n                         Stacktrace(Not(IsEmpty())))))\n              .WillOnce(DeathTestExpectedLogging());\n        }\n\n        test_sink.StartCapturingLogs();\n        do_log();\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n#endif\n\nTEST_P(BasicLogTest, LevelClampsNegativeValues) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {\n    GTEST_SKIP() << \"This test cases required INFO log to be enabled\";\n    return;\n  }\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kInfo))));\n\n  test_sink.StartCapturingLogs();\n  ABSL_TEST_LOG(LEVEL(-1)) << \"hello world\";\n}\n\nTEST_P(BasicLogTest, LevelClampsLargeValues) {\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());\n\n  if (!LoggingEnabledAt(absl::LogSeverity::kError)) {\n    GTEST_SKIP() << \"This test cases required ERROR log to be enabled\";\n    return;\n  }\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kError))));\n\n  test_sink.StartCapturingLogs();\n  ABSL_TEST_LOG(LEVEL(static_cast<int>(absl::LogSeverity::kFatal) + 1))\n      << \"hello world\";\n}\n\nTEST(ErrnoPreservationTest, InSeverityExpression) {\n  errno = 77;\n  int saved_errno;\n  ABSL_TEST_LOG(LEVEL((saved_errno = errno, absl::LogSeverity::kInfo)));\n  EXPECT_THAT(saved_errno, Eq(77));\n}\n\nTEST(ErrnoPreservationTest, InStreamedExpression) {\n  if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {\n    GTEST_SKIP() << \"This test cases required INFO log to be enabled\";\n    return;\n  }\n\n  errno = 77;\n  int saved_errno = 0;\n  ABSL_TEST_LOG(INFO) << (saved_errno = errno, \"hello world\");\n  EXPECT_THAT(saved_errno, Eq(77));\n}\n\nTEST(ErrnoPreservationTest, AfterStatement) {\n  errno = 77;\n  ABSL_TEST_LOG(INFO);\n  const int saved_errno = errno;\n  EXPECT_THAT(saved_errno, Eq(77));\n}\n\n// Tests that using a variable/parameter in a logging statement suppresses\n// unused-variable/parameter warnings.\n// -----------------------------------------------------------------------\nclass UnusedVariableWarningCompileTest {\n  // These four don't prove anything unless `ABSL_MIN_LOG_LEVEL` is greater than\n  // `kInfo`.\n  static void LoggedVariable() {\n    const int x = 0;\n    ABSL_TEST_LOG(INFO) << x;\n  }\n  static void LoggedParameter(const int x) { ABSL_TEST_LOG(INFO) << x; }\n  static void SeverityVariable() {\n    const int x = 0;\n    ABSL_TEST_LOG(LEVEL(x)) << \"hello world\";\n  }\n  static void SeverityParameter(const int x) {\n    ABSL_TEST_LOG(LEVEL(x)) << \"hello world\";\n  }\n};\n\n}  // namespace absl_log_internal\n\n#endif  // ABSL_LOG_LOG_BASIC_TEST_IMPL_H_\n"
  },
  {
    "path": "absl/log/log_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/flags.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/log/log_sink_registry.h\"\n#include \"absl/log/vlog_is_on.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nclass NullLogSink : public absl::LogSink {\n public:\n  NullLogSink() { absl::AddLogSink(this); }\n\n  ~NullLogSink() override { absl::RemoveLogSink(this); }\n\n  void Send(const absl::LogEntry&) override {}\n};\n\nconstexpr int x = -1;\n\nvoid BM_SuccessfulBinaryCheck(benchmark::State& state) {\n  int n = 0;\n  while (state.KeepRunningBatch(8)) {\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    CHECK_GE(n, x);\n    ++n;\n  }\n  benchmark::DoNotOptimize(n);\n}\nBENCHMARK(BM_SuccessfulBinaryCheck);\n\nstatic void BM_SuccessfulUnaryCheck(benchmark::State& state) {\n  int n = 0;\n  while (state.KeepRunningBatch(8)) {\n    CHECK(n >= x);\n    CHECK(n >= x);\n    CHECK(n >= x);\n    CHECK(n >= x);\n    CHECK(n >= x);\n    CHECK(n >= x);\n    CHECK(n >= x);\n    CHECK(n >= x);\n    ++n;\n  }\n  benchmark::DoNotOptimize(n);\n}\nBENCHMARK(BM_SuccessfulUnaryCheck);\n\nstatic void BM_DisabledLogOverhead(benchmark::State& state) {\n  absl::ScopedStderrThreshold disable_stderr_logging(\n      absl::LogSeverityAtLeast::kInfinity);\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(\n      absl::LogSeverityAtLeast::kInfinity);\n  for (auto _ : state) {\n    LOG(INFO);\n  }\n}\nBENCHMARK(BM_DisabledLogOverhead);\n\nstatic void BM_EnabledLogOverhead(benchmark::State& state) {\n  absl::ScopedStderrThreshold stderr_logging(\n      absl::LogSeverityAtLeast::kInfinity);\n  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(\n      absl::LogSeverityAtLeast::kInfo);\n  ABSL_ATTRIBUTE_UNUSED NullLogSink null_sink;\n  for (auto _ : state) {\n    LOG(INFO);\n  }\n}\nBENCHMARK(BM_EnabledLogOverhead);\n\nstatic void BM_VlogIsOnOverhead(benchmark::State& state) {\n  // It would make sense to do this only when state.thread_index == 0,\n  // but thread_index is an int on some platforms (e.g. Android) and a\n  // function returning an int on others. So we just do it on all threads.\n  // TODO(b/152609127): set only if thread_index == 0.\n  absl::SetFlag(&FLAGS_v, 0);\n\n  while (state.KeepRunningBatch(10)) {\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 1\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 2\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 3\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 4\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 5\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 6\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 7\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 8\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 9\n    benchmark::DoNotOptimize(VLOG_IS_ON(0));  // 10\n  }\n}\nBENCHMARK(BM_VlogIsOnOverhead)->ThreadRange(1, 64);\n\nstatic void BM_VlogIsNotOnOverhead(benchmark::State& state) {\n  // It would make sense to do this only when state.thread_index == 0,\n  // but thread_index is an int on some platforms (e.g. Android) and a\n  // function returning an int on others. So we just do it on all threads.\n  // TODO(b/152609127): set only if thread_index == 0.\n  absl::SetFlag(&FLAGS_v, 0);\n\n  while (state.KeepRunningBatch(10)) {\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 1\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 2\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 3\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 4\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 5\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 6\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 7\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 8\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 9\n    benchmark::DoNotOptimize(VLOG_IS_ON(1));  // 10\n  }\n}\nBENCHMARK(BM_VlogIsNotOnOverhead)->ThreadRange(1, 64);\n\nstatic void BM_LogEveryNOverhead(benchmark::State& state) {\n  absl::ScopedStderrThreshold disable_stderr_logging(\n      absl::LogSeverityAtLeast::kInfinity);\n  absl::SetMinLogLevel(absl::LogSeverityAtLeast::kInfinity);\n  ABSL_ATTRIBUTE_UNUSED NullLogSink null_sink;\n\n  while (state.KeepRunningBatch(10)) {\n    LOG_EVERY_N_SEC(INFO, 10);\n    LOG_EVERY_N_SEC(INFO, 20);\n    LOG_EVERY_N_SEC(INFO, 30);\n    LOG_EVERY_N_SEC(INFO, 40);\n    LOG_EVERY_N_SEC(INFO, 50);\n    LOG_EVERY_N_SEC(INFO, 60);\n    LOG_EVERY_N_SEC(INFO, 70);\n    LOG_EVERY_N_SEC(INFO, 80);\n    LOG_EVERY_N_SEC(INFO, 90);\n    LOG_EVERY_N_SEC(INFO, 100);\n  }\n}\nBENCHMARK(BM_LogEveryNOverhead)->ThreadRange(1, 64);\n\n}  // namespace\n\n"
  },
  {
    "path": "absl/log/log_entry.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/log_entry.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <iomanip>\n#include <ios>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/proto.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n// message `logging.proto.Event`\nenum EventTag : uint8_t {\n  kFileName = 2,\n  kFileLine = 3,\n  kTimeNsecs = 4,\n  kSeverity = 5,\n  kThreadId = 6,\n  kValue = 7,\n  kSequenceNumber = 9,\n  kThreadName = 10,\n};\n\n// message `logging.proto.Value`\nenum ValueTag : uint8_t {\n  kString = 1,\n  kStringLiteral = 6,\n};\n\n// enum `logging.proto.Severity`\nenum Severity : int {\n  FINEST = 300,\n  FINER = 400,\n  FINE = 500,\n  VERBOSE_0 = 600,\n  CONFIG = 700,\n  INFO = 800,\n  NOTICE = 850,\n  WARNING = 900,\n  ERROR = 950,\n  SEVERE = 1000,\n  FATAL = 1100,\n};\n\nvoid PrintEscapedRangeTo(const absl::string_view str,\n                         const absl::string_view substr, std::ostream* os) {\n  const absl::string_view head =\n      str.substr(0, static_cast<size_t>(substr.data() - str.data()));\n  const char old_fill = os->fill();\n  const auto old_flags = os->flags();\n  *os << std::right\n      << std::setw(static_cast<int>(absl::CHexEscape(head).size())) << \"\";\n  switch (substr.size()) {\n    case 0:\n      *os << \"\\\\\";\n      break;\n    case 1:\n      *os << \"^\";\n      break;\n    default:\n      *os << \"[\" << std::setw(static_cast<int>(absl::CHexEscape(substr).size()))\n          << std::setfill('-') << \")\";\n      break;\n  }\n  os->fill(old_fill);\n  os->flags(old_flags);\n}\n}  // namespace\nvoid PrintTo(const LogEntry& entry, std::ostream* os) {\n  auto text_message_with_prefix_and_newline_and_nul = absl::string_view(\n      entry.text_message_with_prefix_and_newline_and_nul_.data(),\n      entry.text_message_with_prefix_and_newline_and_nul_.size());\n  *os << \"LogEntry {\\n\"\n      << \"  source_filename: \\\"\" << absl::CHexEscape(entry.source_filename())\n      << \"\\\"\\n\"\n      << \"  source_basename: \\\"\" << absl::CHexEscape(entry.source_basename())\n      << \"\\\"\\n\"\n      << \"  source_line: \" << entry.source_line() << \"\\n\"\n      << \"  prefix: \" << std::boolalpha << entry.prefix() << \"\\n\"\n      << \"  log_severity: \" << entry.log_severity() << \"\\n\"\n      << \"  verbosity: \" << entry.verbosity();\n  if (entry.verbosity() == absl::LogEntry::kNoVerbosityLevel) {\n    *os << \" (kNoVerbosityLevel)\";\n  }\n  *os << \"\\n\"\n      << \"  timestamp: \" << entry.timestamp() << \"\\n\"\n      << \"  tid: \" << entry.tid() << \"\\n\"\n      << \"  text_message_with_prefix_and_newline_and_nul_: \\\"\"\n      << absl::CHexEscape(text_message_with_prefix_and_newline_and_nul)\n      << \"\\\"\\n\"\n      << \"  text_message_with_prefix_and_newline:           \";\n  PrintEscapedRangeTo(text_message_with_prefix_and_newline_and_nul,\n                      entry.text_message_with_prefix_and_newline(), os);\n  *os << \"\\n\"\n      << \"  text_message_with_prefix:                       \";\n  PrintEscapedRangeTo(text_message_with_prefix_and_newline_and_nul,\n                      entry.text_message_with_prefix(), os);\n  *os << \"\\n\"\n      << \"  text_message_with_newline:                      \";\n  PrintEscapedRangeTo(text_message_with_prefix_and_newline_and_nul,\n                      entry.text_message_with_newline(), os);\n  *os << \"\\n\"\n      << \"  text_message:                                   \";\n  PrintEscapedRangeTo(text_message_with_prefix_and_newline_and_nul,\n                      entry.text_message(), os);\n  *os << \"\\n\"\n      << \"  text_message_with_prefix_and_newline_c_str:     \";\n  PrintEscapedRangeTo(\n      text_message_with_prefix_and_newline_and_nul,\n      // NOLINTNEXTLINE(bugprone-string-constructor)\n      absl::string_view(entry.text_message_with_prefix_and_newline_c_str(), 0),\n      os);\n  *os << \"\\n\"\n      << \"  encoded_message (raw): \\\"\"\n      << absl::CHexEscape(entry.encoded_message()) << \"\\\"\\n\"\n      << \"  encoded_message {\\n\";\n  absl::Span<const char> event = entry.encoded_message();\n  log_internal::ProtoField field;\n  while (field.DecodeFrom(&event)) {\n    switch (field.tag()) {\n      case EventTag::kFileName:\n        *os << \"    file_name: \\\"\" << absl::CHexEscape(field.string_value())\n            << \"\\\"\\n\";\n        break;\n      case EventTag::kFileLine:\n        *os << \"    file_line: \" << field.int32_value() << \"\\n\";\n        break;\n      case EventTag::kTimeNsecs:\n        *os << \"    time_nsecs: \" << field.int64_value() << \" (\"\n            << absl::FromUnixNanos(field.int64_value()) << \")\\n\";\n        break;\n      case EventTag::kSeverity:\n        *os << \"    severity: \" << field.int32_value();\n        switch (field.int32_value()) {\n          case Severity::FINEST:\n            *os << \" (FINEST)\";\n            break;\n          case Severity::FINER:\n            *os << \" (FINER)\";\n            break;\n          case Severity::FINE:\n            *os << \" (FINE)\";\n            break;\n          case Severity::VERBOSE_0:\n            *os << \" (VERBOSE_0)\";\n            break;\n          case Severity::CONFIG:\n            *os << \" (CONFIG)\";\n            break;\n          case Severity::INFO:\n            *os << \" (INFO)\";\n            break;\n          case Severity::NOTICE:\n            *os << \" (NOTICE)\";\n            break;\n          case Severity::WARNING:\n            *os << \" (WARNING)\";\n            break;\n          case Severity::ERROR:\n            *os << \" (ERROR)\";\n            break;\n          case Severity::SEVERE:\n            *os << \" (SEVERE)\";\n            break;\n          case Severity::FATAL:\n            *os << \" (FATAL)\";\n            break;\n        }\n        *os << \"\\n\";\n        break;\n      case EventTag::kThreadId:\n        *os << \"    thread_id: \" << field.int64_value() << \"\\n\";\n        break;\n      case EventTag::kValue: {\n        *os << \"    value {\\n\";\n        auto value = field.bytes_value();\n        while (field.DecodeFrom(&value)) {\n          switch (field.tag()) {\n            case ValueTag::kString:\n              *os << \"      str: \\\"\" << absl::CHexEscape(field.string_value())\n                  << \"\\\"\\n\";\n              break;\n            case ValueTag::kStringLiteral:\n              *os << \"      literal: \\\"\"\n                  << absl::CHexEscape(field.string_value()) << \"\\\"\\n\";\n              break;\n            default:\n              *os << \"      unknown field \" << field.tag();\n              switch (field.type()) {\n                case log_internal::WireType::kVarint:\n                  *os << \" (VARINT): \" << std::hex << std::showbase\n                      << field.uint64_value() << std::dec << \"\\n\";\n                  break;\n                case log_internal::WireType::k64Bit:\n                  *os << \" (I64): \" << std::hex << std::showbase\n                      << field.uint64_value() << std::dec << \"\\n\";\n                  break;\n                case log_internal::WireType::kLengthDelimited:\n                  *os << \" (LEN): \\\"\" << absl::CHexEscape(field.string_value())\n                      << \"\\\"\\n\";\n                  break;\n                case log_internal::WireType::k32Bit:\n                  *os << \" (I32): \" << std::hex << std::showbase\n                      << field.uint32_value() << std::dec << \"\\n\";\n                  break;\n              }\n              break;\n          }\n        }\n        *os << \"    }\\n\";\n        break;\n      }\n      default:\n        *os << \"    unknown field \" << field.tag();\n        switch (field.type()) {\n          case log_internal::WireType::kVarint:\n            *os << \" (VARINT): \" << std::hex << std::showbase\n                << field.uint64_value() << std::dec << \"\\n\";\n            break;\n          case log_internal::WireType::k64Bit:\n            *os << \" (I64): \" << std::hex << std::showbase\n                << field.uint64_value() << std::dec << \"\\n\";\n            break;\n          case log_internal::WireType::kLengthDelimited:\n            *os << \" (LEN): \\\"\" << absl::CHexEscape(field.string_value())\n                << \"\\\"\\n\";\n            break;\n          case log_internal::WireType::k32Bit:\n            *os << \" (I32): \" << std::hex << std::showbase\n                << field.uint32_value() << std::dec << \"\\n\";\n            break;\n        }\n        break;\n    }\n  }\n  *os << \"  }\\n\"\n      << \"  stacktrace: \\\"\" << absl::CHexEscape(entry.stacktrace()) << \"\\\"\\n\"\n      << \"}\";\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/log_entry.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/log_entry.h\n// -----------------------------------------------------------------------------\n//\n// This header declares `class absl::LogEntry`, which represents a log record as\n// passed to `LogSink::Send`. Data returned by pointer or by reference or by\n// `absl::string_view` must be copied if they are needed after the lifetime of\n// the `absl::LogEntry`.\n\n#ifndef ABSL_LOG_LOG_ENTRY_H_\n#define ABSL_LOG_LOG_ENTRY_H_\n\n#include <cstddef>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/config.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace log_internal {\n// Test only friend.\nclass LogEntryTestPeer;\nclass LogMessage;\n}  // namespace log_internal\n\n// LogEntry\n//\n// Represents a single entry in a log, i.e., one `LOG` statement or failed\n// `CHECK`.\n//\n// `LogEntry` is thread-compatible.\nclass LogEntry final {\n public:\n  using tid_t = log_internal::Tid;\n\n  // For non-verbose log entries, `verbosity()` returns `kNoVerbosityLevel`.\n  static constexpr int kNoVerbosityLevel = -1;\n  static constexpr int kNoVerboseLevel = -1;  // TO BE removed\n\n  // Pass `LogEntry` by reference, and do not store it as its state does not\n  // outlive the call to `LogSink::Send()`.\n  LogEntry(const LogEntry&) = delete;\n  LogEntry& operator=(const LogEntry&) = delete;\n\n  // Source file and line where the log message occurred.  Taken from `__FILE__`\n  // and `__LINE__` unless overridden by `LOG(...).AtLocation(...)`.\n  //\n  // Take special care not to use the values returned by `source_filename()` and\n  // `source_basename()` after the lifetime of the entry.  This is always\n  // incorrect, but it will often work in practice because they usually point\n  // into a statically allocated character array obtained from `__FILE__`.\n  // Statements like `LOG(INFO).AtLocation(std::string(...), ...)` will expose\n  // the bug.  If you need the data later, you must copy them.\n  absl::string_view source_filename() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return full_filename_;\n  }\n  absl::string_view source_basename() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return base_filename_;\n  }\n  int source_line() const { return line_; }\n\n  // LogEntry::prefix()\n  //\n  // True unless the metadata prefix was suppressed once by\n  // `LOG(...).NoPrefix()` or globally by `absl::EnableLogPrefix(false)`.\n  // Implies `text_message_with_prefix() == text_message()`.\n  bool prefix() const { return prefix_; }\n\n  // LogEntry::log_severity()\n  //\n  // Returns this entry's severity.  For `LOG`, taken from the first argument;\n  // for `CHECK`, always `absl::LogSeverity::kFatal`.\n  absl::LogSeverity log_severity() const { return severity_; }\n\n  // LogEntry::verbosity()\n  //\n  // Returns this entry's verbosity, or `kNoVerbosityLevel` for a non-verbose\n  // entry. Taken from the argument to `VLOG` or from\n  // `LOG(...).WithVerbosity(...)`.\n  int verbosity() const { return verbose_level_; }\n\n  // LogEntry::timestamp()\n  //\n  // Returns the time at which this entry was written.  Captured during\n  // evaluation of `LOG`, but can be overridden by\n  // `LOG(...).WithTimestamp(...)`.\n  //\n  // Take care not to rely on timestamps increasing monotonically, or even to\n  // rely on timestamps having any particular relationship with reality (since\n  // they can be overridden).\n  absl::Time timestamp() const { return timestamp_; }\n\n  // LogEntry::tid()\n  //\n  // Returns the ID of the thread that wrote this entry.  Captured during\n  // evaluation of `LOG`, but can be overridden by `LOG(...).WithThreadID(...)`.\n  //\n  // Take care not to *rely* on reported thread IDs as they can be overridden as\n  // specified above.\n  tid_t tid() const { return tid_; }\n\n  // Text-formatted version of the log message.  An underlying buffer holds\n  // these contiguous data:\n  //\n  // * A prefix formed by formatting metadata (timestamp, filename, line number,\n  //   etc.)\n  //   The prefix may be empty - see `LogEntry::prefix()` - and may rarely be\n  //   truncated if the metadata are very long.\n  // * The streamed data\n  //   The data may be empty if nothing was streamed, or may be truncated to fit\n  //   the buffer.\n  // * A newline\n  // * A nul terminator\n  //\n  // The newline and nul terminator will be present even if the prefix and/or\n  // data are truncated.\n  //\n  // These methods give access to the most commonly useful substrings of the\n  // buffer's contents.  Other combinations can be obtained with substring\n  // arithmetic.\n  //\n  // The buffer does not outlive the entry; if you need the data later, you must\n  // copy them.\n  absl::string_view text_message_with_prefix_and_newline() const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return absl::string_view(\n        text_message_with_prefix_and_newline_and_nul_.data(),\n        text_message_with_prefix_and_newline_and_nul_.size() - 1);\n  }\n  absl::string_view text_message_with_prefix() const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return absl::string_view(\n        text_message_with_prefix_and_newline_and_nul_.data(),\n        text_message_with_prefix_and_newline_and_nul_.size() - 2);\n  }\n  absl::string_view text_message_with_newline() const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return absl::string_view(\n        text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,\n        text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 1);\n  }\n  absl::string_view text_message() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return absl::string_view(\n        text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,\n        text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 2);\n  }\n  const char* text_message_with_prefix_and_newline_c_str() const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return text_message_with_prefix_and_newline_and_nul_.data();\n  }\n\n  // Returns a serialized protobuf holding the operands streamed into this\n  // log message.  The message definition is not yet published.\n  //\n  // The buffer does not outlive the entry; if you need the data later, you must\n  // copy them.\n  absl::string_view encoded_message() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return encoding_;\n  }\n\n  // LogEntry::stacktrace()\n  //\n  // Optional stacktrace, e.g. for `FATAL` logs and failed `CHECK`s.\n  //\n  // Fatal entries are dispatched to each sink twice: first with all data and\n  // metadata but no stacktrace, and then with the stacktrace.  This is done\n  // because stacktrace collection is sometimes slow and fallible, and it's\n  // critical to log enough information to diagnose the failure even if the\n  // stacktrace collection hangs.\n  //\n  // The buffer does not outlive the entry; if you need the data later, you must\n  // copy them.\n  absl::string_view stacktrace() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return stacktrace_;\n  }\n\n private:\n  LogEntry() = default;\n\n  absl::string_view full_filename_;\n  absl::string_view base_filename_;\n  int line_;\n  bool prefix_;\n  absl::LogSeverity severity_;\n  int verbose_level_;  // >=0 for `VLOG`, etc.; otherwise `kNoVerbosityLevel`.\n  absl::Time timestamp_;\n  tid_t tid_;\n  absl::Span<const char> text_message_with_prefix_and_newline_and_nul_;\n  size_t prefix_len_;\n  absl::string_view encoding_;\n  std::string stacktrace_;\n\n  friend class log_internal::LogEntryTestPeer;\n  friend class log_internal::LogMessage;\n  friend void PrintTo(const absl::LogEntry& entry, std::ostream* os);\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_LOG_ENTRY_H_\n"
  },
  {
    "path": "absl/log/log_entry_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/log_entry.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <cstring>\n#include <limits>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/append_truncated.h\"\n#include \"absl/log/internal/log_format.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/civil_time.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nnamespace {\nusing ::absl::log_internal::LogEntryTestPeer;\nusing ::testing::Eq;\nusing ::testing::IsTrue;\nusing ::testing::StartsWith;\nusing ::testing::StrEq;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n}  // namespace\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace log_internal {\n\nclass LogEntryTestPeer {\n public:\n  LogEntryTestPeer(absl::string_view base_filename, int line, bool prefix,\n                   absl::LogSeverity severity, absl::string_view timestamp,\n                   absl::LogEntry::tid_t tid, PrefixFormat format,\n                   absl::string_view text_message)\n      : format_{format}, buf_(15000, '\\0') {\n    entry_.base_filename_ = base_filename;\n    entry_.line_ = line;\n    entry_.prefix_ = prefix;\n    entry_.severity_ = severity;\n    std::string time_err;\n    EXPECT_THAT(\n        absl::ParseTime(\"%Y-%m-%d%ET%H:%M:%E*S\", timestamp,\n                        absl::LocalTimeZone(), &entry_.timestamp_, &time_err),\n        IsTrue())\n        << \"Failed to parse time \" << timestamp << \": \" << time_err;\n    entry_.tid_ = tid;\n    std::pair<absl::string_view, std::string> timestamp_bits =\n        absl::StrSplit(timestamp, absl::ByChar('.'));\n    EXPECT_THAT(absl::ParseCivilTime(timestamp_bits.first, &ci_.cs), IsTrue())\n        << \"Failed to parse time \" << timestamp_bits.first;\n    timestamp_bits.second.resize(9, '0');\n    int64_t nanos = 0;\n    EXPECT_THAT(absl::SimpleAtoi(timestamp_bits.second, &nanos), IsTrue())\n        << \"Failed to parse time \" << timestamp_bits.first;\n    ci_.subsecond = absl::Nanoseconds(nanos);\n\n    absl::Span<char> view = absl::MakeSpan(buf_);\n    view.remove_suffix(2);\n    entry_.prefix_len_ =\n        entry_.prefix_\n            ? log_internal::FormatLogPrefix(\n                  entry_.log_severity(), entry_.timestamp(), entry_.tid(),\n                  entry_.source_basename(), entry_.source_line(), format_, view)\n            : 0;\n\n    EXPECT_THAT(entry_.prefix_len_,\n                Eq(static_cast<size_t>(view.data() - buf_.data())));\n    log_internal::AppendTruncated(text_message, view);\n    view = absl::Span<char>(view.data(), view.size() + 2);\n    view[0] = '\\n';\n    view[1] = '\\0';\n    view.remove_prefix(2);\n    buf_.resize(static_cast<size_t>(view.data() - buf_.data()));\n    entry_.text_message_with_prefix_and_newline_and_nul_ = absl::MakeSpan(buf_);\n  }\n  LogEntryTestPeer(const LogEntryTestPeer&) = delete;\n  LogEntryTestPeer& operator=(const LogEntryTestPeer&) = delete;\n\n  std::string FormatLogMessage() const {\n    return log_internal::FormatLogMessage(\n        entry_.log_severity(), ci_.cs, ci_.subsecond, entry_.tid(),\n        entry_.source_basename(), entry_.source_line(), format_,\n        entry_.text_message());\n  }\n  std::string FormatPrefixIntoSizedBuffer(size_t sz) {\n    std::string str(sz, '\\0');\n    absl::Span<char> buf(&str[0], str.size());\n    const size_t prefix_size = log_internal::FormatLogPrefix(\n        entry_.log_severity(), entry_.timestamp(), entry_.tid(),\n        entry_.source_basename(), entry_.source_line(), format_, buf);\n    EXPECT_THAT(prefix_size, Eq(static_cast<size_t>(buf.data() - str.data())));\n    str.resize(prefix_size);\n    return str;\n  }\n  const absl::LogEntry& entry() const { return entry_; }\n\n private:\n  absl::LogEntry entry_;\n  PrefixFormat format_;\n  absl::TimeZone::CivilInfo ci_;\n  std::vector<char> buf_;\n};\n\n}  // namespace log_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nnamespace {\nconstexpr bool kUsePrefix = true, kNoPrefix = false;\n\nTEST(LogEntryTest, Baseline) {\n  LogEntryTestPeer entry(\"foo.cc\", 1234, kUsePrefix, absl::LogSeverity::kInfo,\n                         \"2020-01-02T03:04:05.6789\", 451,\n                         absl::log_internal::PrefixFormat::kNotRaw,\n                         \"hello world\");\n  EXPECT_THAT(entry.FormatLogMessage(),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] hello world\"));\n  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] \"));\n  for (size_t sz = strlen(\"I0102 03:04:05.678900     451 foo.cc:1234] \") + 20;\n       sz != std::numeric_limits<size_t>::max(); sz--)\n    EXPECT_THAT(\"I0102 03:04:05.678900     451 foo.cc:1234] \",\n                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] hello world\\n\"));\n  EXPECT_THAT(\n      entry.entry().text_message_with_prefix_and_newline_c_str(),\n      StrEq(\"I0102 03:04:05.678900     451 foo.cc:1234] hello world\\n\"));\n  EXPECT_THAT(entry.entry().text_message_with_prefix(),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] hello world\"));\n  EXPECT_THAT(entry.entry().text_message(), Eq(\"hello world\"));\n}\n\nTEST(LogEntryTest, NoPrefix) {\n  LogEntryTestPeer entry(\"foo.cc\", 1234, kNoPrefix, absl::LogSeverity::kInfo,\n                         \"2020-01-02T03:04:05.6789\", 451,\n                         absl::log_internal::PrefixFormat::kNotRaw,\n                         \"hello world\");\n  EXPECT_THAT(entry.FormatLogMessage(),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] hello world\"));\n  // These methods are not responsible for honoring `prefix()`.\n  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] \"));\n  for (size_t sz = strlen(\"I0102 03:04:05.678900     451 foo.cc:1234] \") + 20;\n       sz != std::numeric_limits<size_t>::max(); sz--)\n    EXPECT_THAT(\"I0102 03:04:05.678900     451 foo.cc:1234] \",\n                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),\n              Eq(\"hello world\\n\"));\n  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline_c_str(),\n              StrEq(\"hello world\\n\"));\n  EXPECT_THAT(entry.entry().text_message_with_prefix(), Eq(\"hello world\"));\n  EXPECT_THAT(entry.entry().text_message(), Eq(\"hello world\"));\n}\n\nTEST(LogEntryTest, EmptyFields) {\n  LogEntryTestPeer entry(\"\", 0, kUsePrefix, absl::LogSeverity::kInfo,\n                         \"2020-01-02T03:04:05\", 0,\n                         absl::log_internal::PrefixFormat::kNotRaw, \"\");\n  const std::string format_message = entry.FormatLogMessage();\n  EXPECT_THAT(format_message, Eq(\"I0102 03:04:05.000000       0 :0] \"));\n  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), Eq(format_message));\n  for (size_t sz = format_message.size() + 20;\n       sz != std::numeric_limits<size_t>::max(); sz--)\n    EXPECT_THAT(format_message,\n                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),\n              Eq(\"I0102 03:04:05.000000       0 :0] \\n\"));\n  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline_c_str(),\n              StrEq(\"I0102 03:04:05.000000       0 :0] \\n\"));\n  EXPECT_THAT(entry.entry().text_message_with_prefix(),\n              Eq(\"I0102 03:04:05.000000       0 :0] \"));\n  EXPECT_THAT(entry.entry().text_message(), Eq(\"\"));\n}\n\nTEST(LogEntryTest, NegativeFields) {\n  // When Abseil's minimum C++ version is C++17, this conditional can be\n  // converted to a constexpr if and the static_cast below removed.\n  if (std::is_signed<absl::LogEntry::tid_t>::value) {\n    LogEntryTestPeer entry(\n        \"foo.cc\", -1234, kUsePrefix, absl::LogSeverity::kInfo,\n        \"2020-01-02T03:04:05.6789\", static_cast<absl::LogEntry::tid_t>(-451),\n        absl::log_internal::PrefixFormat::kNotRaw, \"hello world\");\n    EXPECT_THAT(entry.FormatLogMessage(),\n                Eq(\"I0102 03:04:05.678900    -451 foo.cc:-1234] hello world\"));\n    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n                Eq(\"I0102 03:04:05.678900    -451 foo.cc:-1234] \"));\n    for (size_t sz =\n             strlen(\"I0102 03:04:05.678900    -451 foo.cc:-1234] \") + 20;\n         sz != std::numeric_limits<size_t>::max(); sz--)\n      EXPECT_THAT(\"I0102 03:04:05.678900    -451 foo.cc:-1234] \",\n                  StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline(),\n        Eq(\"I0102 03:04:05.678900    -451 foo.cc:-1234] hello world\\n\"));\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline_c_str(),\n        StrEq(\"I0102 03:04:05.678900    -451 foo.cc:-1234] hello world\\n\"));\n    EXPECT_THAT(entry.entry().text_message_with_prefix(),\n                Eq(\"I0102 03:04:05.678900    -451 foo.cc:-1234] hello world\"));\n    EXPECT_THAT(entry.entry().text_message(), Eq(\"hello world\"));\n  } else {\n    LogEntryTestPeer entry(\"foo.cc\", -1234, kUsePrefix,\n                           absl::LogSeverity::kInfo, \"2020-01-02T03:04:05.6789\",\n                           451, absl::log_internal::PrefixFormat::kNotRaw,\n                           \"hello world\");\n    EXPECT_THAT(entry.FormatLogMessage(),\n                Eq(\"I0102 03:04:05.678900     451 foo.cc:-1234] hello world\"));\n    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n                Eq(\"I0102 03:04:05.678900     451 foo.cc:-1234] \"));\n    for (size_t sz =\n             strlen(\"I0102 03:04:05.678900     451 foo.cc:-1234] \") + 20;\n         sz != std::numeric_limits<size_t>::max(); sz--)\n      EXPECT_THAT(\"I0102 03:04:05.678900     451 foo.cc:-1234] \",\n                  StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline(),\n        Eq(\"I0102 03:04:05.678900     451 foo.cc:-1234] hello world\\n\"));\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline_c_str(),\n        StrEq(\"I0102 03:04:05.678900     451 foo.cc:-1234] hello world\\n\"));\n    EXPECT_THAT(entry.entry().text_message_with_prefix(),\n                Eq(\"I0102 03:04:05.678900     451 foo.cc:-1234] hello world\"));\n    EXPECT_THAT(entry.entry().text_message(), Eq(\"hello world\"));\n  }\n}\n\nTEST(LogEntryTest, LongFields) {\n  LogEntryTestPeer entry(\n      \"I am the very model of a modern Major-General / \"\n      \"I've information vegetable, animal, and mineral.\",\n      2147483647, kUsePrefix, absl::LogSeverity::kInfo,\n      \"2020-01-02T03:04:05.678967896789\", 2147483647,\n      absl::log_internal::PrefixFormat::kNotRaw,\n      \"I know the kings of England, and I quote the fights historical / \"\n      \"From Marathon to Waterloo, in order categorical.\");\n  EXPECT_THAT(entry.FormatLogMessage(),\n              Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                 \"modern Major-General / I've information vegetable, animal, \"\n                 \"and mineral.:2147483647] I know the kings of England, and I \"\n                 \"quote the fights historical / From Marathon to Waterloo, in \"\n                 \"order categorical.\"));\n  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n              Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                 \"modern Major-General / I've information vegetable, animal, \"\n                 \"and mineral.:2147483647] \"));\n  for (size_t sz =\n           strlen(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                  \"modern Major-General / I've information vegetable, animal, \"\n                  \"and mineral.:2147483647] \") +\n           20;\n       sz != std::numeric_limits<size_t>::max(); sz--)\n    EXPECT_THAT(\n        \"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n        \"modern Major-General / I've information vegetable, animal, \"\n        \"and mineral.:2147483647] \",\n        StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n  EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(),\n              Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                 \"modern Major-General / I've information vegetable, animal, \"\n                 \"and mineral.:2147483647] I know the kings of England, and I \"\n                 \"quote the fights historical / From Marathon to Waterloo, in \"\n                 \"order categorical.\\n\"));\n  EXPECT_THAT(\n      entry.entry().text_message_with_prefix_and_newline_c_str(),\n      StrEq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n            \"modern Major-General / I've information vegetable, animal, \"\n            \"and mineral.:2147483647] I know the kings of England, and I \"\n            \"quote the fights historical / From Marathon to Waterloo, in \"\n            \"order categorical.\\n\"));\n  EXPECT_THAT(entry.entry().text_message_with_prefix(),\n              Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                 \"modern Major-General / I've information vegetable, animal, \"\n                 \"and mineral.:2147483647] I know the kings of England, and I \"\n                 \"quote the fights historical / From Marathon to Waterloo, in \"\n                 \"order categorical.\"));\n  EXPECT_THAT(\n      entry.entry().text_message(),\n      Eq(\"I know the kings of England, and I quote the fights historical / \"\n         \"From Marathon to Waterloo, in order categorical.\"));\n}\n\nTEST(LogEntryTest, LongNegativeFields) {\n  // When Abseil's minimum C++ version is C++17, this conditional can be\n  // converted to a constexpr if and the static_cast below removed.\n  if (std::is_signed<absl::LogEntry::tid_t>::value) {\n    LogEntryTestPeer entry(\n        \"I am the very model of a modern Major-General / \"\n        \"I've information vegetable, animal, and mineral.\",\n        -2147483647, kUsePrefix, absl::LogSeverity::kInfo,\n        \"2020-01-02T03:04:05.678967896789\",\n        static_cast<absl::LogEntry::tid_t>(-2147483647),\n        absl::log_internal::PrefixFormat::kNotRaw,\n        \"I know the kings of England, and I quote the fights historical / \"\n        \"From Marathon to Waterloo, in order categorical.\");\n    EXPECT_THAT(\n        entry.FormatLogMessage(),\n        Eq(\"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n           \"modern Major-General / I've information vegetable, animal, \"\n           \"and mineral.:-2147483647] I know the kings of England, and I \"\n           \"quote the fights historical / From Marathon to Waterloo, in \"\n           \"order categorical.\"));\n    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n                Eq(\"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n                   \"modern Major-General / I've information vegetable, animal, \"\n                   \"and mineral.:-2147483647] \"));\n    for (size_t sz =\n             strlen(\n                 \"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n                 \"modern Major-General / I've information vegetable, animal, \"\n                 \"and mineral.:-2147483647] \") +\n             20;\n         sz != std::numeric_limits<size_t>::max(); sz--)\n      EXPECT_THAT(\n          \"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n          \"modern Major-General / I've information vegetable, animal, \"\n          \"and mineral.:-2147483647] \",\n          StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline(),\n        Eq(\"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n           \"modern Major-General / I've information vegetable, animal, \"\n           \"and mineral.:-2147483647] I know the kings of England, and I \"\n           \"quote the fights historical / From Marathon to Waterloo, in \"\n           \"order categorical.\\n\"));\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline_c_str(),\n        StrEq(\"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n              \"modern Major-General / I've information vegetable, animal, \"\n              \"and mineral.:-2147483647] I know the kings of England, and I \"\n              \"quote the fights historical / From Marathon to Waterloo, in \"\n              \"order categorical.\\n\"));\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix(),\n        Eq(\"I0102 03:04:05.678967 -2147483647 I am the very model of a \"\n           \"modern Major-General / I've information vegetable, animal, \"\n           \"and mineral.:-2147483647] I know the kings of England, and I \"\n           \"quote the fights historical / From Marathon to Waterloo, in \"\n           \"order categorical.\"));\n    EXPECT_THAT(\n        entry.entry().text_message(),\n        Eq(\"I know the kings of England, and I quote the fights historical / \"\n           \"From Marathon to Waterloo, in order categorical.\"));\n  } else {\n    LogEntryTestPeer entry(\n        \"I am the very model of a modern Major-General / \"\n        \"I've information vegetable, animal, and mineral.\",\n        -2147483647, kUsePrefix, absl::LogSeverity::kInfo,\n        \"2020-01-02T03:04:05.678967896789\", 2147483647,\n        absl::log_internal::PrefixFormat::kNotRaw,\n        \"I know the kings of England, and I quote the fights historical / \"\n        \"From Marathon to Waterloo, in order categorical.\");\n    EXPECT_THAT(\n        entry.FormatLogMessage(),\n        Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n           \"modern Major-General / I've information vegetable, animal, \"\n           \"and mineral.:-2147483647] I know the kings of England, and I \"\n           \"quote the fights historical / From Marathon to Waterloo, in \"\n           \"order categorical.\"));\n    EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n                Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                   \"modern Major-General / I've information vegetable, animal, \"\n                   \"and mineral.:-2147483647] \"));\n    for (size_t sz =\n             strlen(\n                 \"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n                 \"modern Major-General / I've information vegetable, animal, \"\n                 \"and mineral.:-2147483647] \") +\n             20;\n         sz != std::numeric_limits<size_t>::max(); sz--)\n      EXPECT_THAT(\n          \"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n          \"modern Major-General / I've information vegetable, animal, \"\n          \"and mineral.:-2147483647] \",\n          StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline(),\n        Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n           \"modern Major-General / I've information vegetable, animal, \"\n           \"and mineral.:-2147483647] I know the kings of England, and I \"\n           \"quote the fights historical / From Marathon to Waterloo, in \"\n           \"order categorical.\\n\"));\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix_and_newline_c_str(),\n        StrEq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n              \"modern Major-General / I've information vegetable, animal, \"\n              \"and mineral.:-2147483647] I know the kings of England, and I \"\n              \"quote the fights historical / From Marathon to Waterloo, in \"\n              \"order categorical.\\n\"));\n    EXPECT_THAT(\n        entry.entry().text_message_with_prefix(),\n        Eq(\"I0102 03:04:05.678967 2147483647 I am the very model of a \"\n           \"modern Major-General / I've information vegetable, animal, \"\n           \"and mineral.:-2147483647] I know the kings of England, and I \"\n           \"quote the fights historical / From Marathon to Waterloo, in \"\n           \"order categorical.\"));\n    EXPECT_THAT(\n        entry.entry().text_message(),\n        Eq(\"I know the kings of England, and I quote the fights historical / \"\n           \"From Marathon to Waterloo, in order categorical.\"));\n  }\n}\n\nTEST(LogEntryTest, Raw) {\n  LogEntryTestPeer entry(\"foo.cc\", 1234, kUsePrefix, absl::LogSeverity::kInfo,\n                         \"2020-01-02T03:04:05.6789\", 451,\n                         absl::log_internal::PrefixFormat::kRaw, \"hello world\");\n  EXPECT_THAT(\n      entry.FormatLogMessage(),\n      Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: hello world\"));\n  EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000),\n              Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: \"));\n  for (size_t sz =\n           strlen(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: \") + 20;\n       sz != std::numeric_limits<size_t>::max(); sz--)\n    EXPECT_THAT(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: \",\n                StartsWith(entry.FormatPrefixIntoSizedBuffer(sz)));\n\n  EXPECT_THAT(\n      entry.entry().text_message_with_prefix_and_newline(),\n      Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: hello world\\n\"));\n  EXPECT_THAT(\n      entry.entry().text_message_with_prefix_and_newline_c_str(),\n      StrEq(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: hello world\\n\"));\n  EXPECT_THAT(\n      entry.entry().text_message_with_prefix(),\n      Eq(\"I0102 03:04:05.678900     451 foo.cc:1234] RAW: hello world\"));\n  EXPECT_THAT(entry.entry().text_message(), Eq(\"hello world\"));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/log_format_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <math.h>\n\n#include <cstring>\n#include <iomanip>\n#include <ios>\n#include <limits>\n#include <optional>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#ifdef __ANDROID__\n#include <android/api-level.h>\n#endif\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\nusing ::absl::log_internal::AsString;\nusing ::absl::log_internal::MatchesOstream;\nusing ::absl::log_internal::RawEncodedMessage;\nusing ::absl::log_internal::TextMessage;\nusing ::absl::log_internal::TextPrefix;\nusing ::testing::_;\nusing ::testing::AllOf;\nusing ::testing::AnyOf;\nusing ::testing::Each;\nusing ::testing::EndsWith;\nusing ::testing::Eq;\nusing ::testing::Ge;\nusing ::testing::IsEmpty;\nusing ::testing::Le;\nusing ::testing::SizeIs;\nusing ::testing::Types;\n\n// Some aspects of formatting streamed data (e.g. pointer handling) are\n// implementation-defined.  Others are buggy in supported implementations.\n// These tests validate that the formatting matches that performed by a\n// `std::ostream` and also that the result is one of a list of expected formats.\n\nstd::ostringstream ComparisonStream() {\n  std::ostringstream str;\n  str.setf(std::ios_base::showbase | std::ios_base::boolalpha |\n           std::ios_base::internal);\n  return str;\n}\n\nTEST(LogFormatTest, NoMessage) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  auto do_log = [] { LOG(INFO); };\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(ComparisonStream())),\n                         TextPrefix(AsString(EndsWith(absl::StrCat(\n                             \" log_format_test.cc:\", log_line, \"] \")))),\n                         TextMessage(IsEmpty()),\n                         ENCODED_MESSAGE(HasValues(IsEmpty())))));\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\ntemplate <typename T>\nclass CharLogFormatTest : public testing::Test {};\nusing CharTypes = Types<char, signed char, unsigned char>;\nTYPED_TEST_SUITE(CharLogFormatTest, CharTypes);\n\nTYPED_TEST(CharLogFormatTest, Printable) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = 'x';\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"x\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"x\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(CharLogFormatTest, Unprintable) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  constexpr auto value = static_cast<TypeParam>(0xeeu);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"\\xee\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"\\xee\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(WideCharLogFormatTest, Printable) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"€\")),\n                                    ENCODED_MESSAGE(HasValues(\n                                        ElementsAre(ValueWithStr(Eq(\"€\"))))))));\n\n  test_sink.StartCapturingLogs();\n  const wchar_t value = L'\\u20AC';\n  LOG(INFO) << value;\n}\n\nTEST(WideCharLogFormatTest, Unprintable) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  // Using NEL (Next Line) Unicode character (U+0085).\n  // It is encoded as \"\\xC2\\x85\" in UTF-8.\n  constexpr wchar_t wide_value = L'\\u0085';\n  constexpr char value[] = \"\\xC2\\x85\";\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << wide_value;\n}\n\ntemplate <typename T>\nclass UnsignedIntLogFormatTest : public testing::Test {};\nusing UnsignedIntTypes = Types<unsigned short, unsigned int,        // NOLINT\n                               unsigned long, unsigned long long>;  // NOLINT\nTYPED_TEST_SUITE(UnsignedIntLogFormatTest, UnsignedIntTypes);\n\nTYPED_TEST(UnsignedIntLogFormatTest, Positive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = 224;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"224\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"224\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(UnsignedIntLogFormatTest, BitfieldPositive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const struct {\n    TypeParam bits : 6;\n  } value{42};\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value.bits;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"42\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"42\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value.bits;\n}\n\ntemplate <typename T>\nclass SignedIntLogFormatTest : public testing::Test {};\nusing SignedIntTypes =\n    Types<signed short, signed int, signed long, signed long long>;  // NOLINT\nTYPED_TEST_SUITE(SignedIntLogFormatTest, SignedIntTypes);\n\nTYPED_TEST(SignedIntLogFormatTest, Positive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = 224;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"224\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"224\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(SignedIntLogFormatTest, Negative) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = -112;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"-112\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"-112\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(SignedIntLogFormatTest, BitfieldPositive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const struct {\n    TypeParam bits : 6;\n  } value{21};\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value.bits;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"21\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"21\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value.bits;\n}\n\nTYPED_TEST(SignedIntLogFormatTest, BitfieldNegative) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const struct {\n    TypeParam bits : 6;\n  } value{-21};\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value.bits;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"-21\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"-21\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value.bits;\n}\n\n// Ignore these test cases on GCC due to \"is too small to hold all values ...\"\n// warning.\n#if !defined(__GNUC__) || defined(__clang__)\n// The implementation may choose a signed or unsigned integer type to represent\n// this enum, so it may be tested by either `UnsignedEnumLogFormatTest` or\n// `SignedEnumLogFormatTest`.\nenum MyUnsignedEnum {\n  MyUnsignedEnum_ZERO = 0,\n  MyUnsignedEnum_FORTY_TWO = 42,\n  MyUnsignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224,\n};\nenum MyUnsignedIntEnum : unsigned int {\n  MyUnsignedIntEnum_ZERO = 0,\n  MyUnsignedIntEnum_FORTY_TWO = 42,\n  MyUnsignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224,\n};\n\ntemplate <typename T>\nclass UnsignedEnumLogFormatTest : public testing::Test {};\nusing UnsignedEnumTypes = std::conditional<\n    std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value,\n    Types<MyUnsignedIntEnum>, Types<MyUnsignedEnum, MyUnsignedIntEnum>>::type;\nTYPED_TEST_SUITE(UnsignedEnumLogFormatTest, UnsignedEnumTypes);\n\nTYPED_TEST(UnsignedEnumLogFormatTest, Positive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = static_cast<TypeParam>(224);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"224\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"224\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(UnsignedEnumLogFormatTest, BitfieldPositive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const struct {\n    TypeParam bits : 6;\n  } value{static_cast<TypeParam>(42)};\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value.bits;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"42\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"42\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value.bits;\n}\n\nenum MySignedEnum {\n  MySignedEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112,\n  MySignedEnum_NEGATIVE_TWENTY_ONE = -21,\n  MySignedEnum_ZERO = 0,\n  MySignedEnum_TWENTY_ONE = 21,\n  MySignedEnum_TWO_HUNDRED_TWENTY_FOUR = 224,\n};\nenum MySignedIntEnum : signed int {\n  MySignedIntEnum_NEGATIVE_ONE_HUNDRED_TWELVE = -112,\n  MySignedIntEnum_NEGATIVE_TWENTY_ONE = -21,\n  MySignedIntEnum_ZERO = 0,\n  MySignedIntEnum_TWENTY_ONE = 21,\n  MySignedIntEnum_TWO_HUNDRED_TWENTY_FOUR = 224,\n};\n\ntemplate <typename T>\nclass SignedEnumLogFormatTest : public testing::Test {};\nusing SignedEnumTypes = std::conditional<\n    std::is_signed<std::underlying_type<MyUnsignedEnum>::type>::value,\n    Types<MyUnsignedEnum, MySignedEnum, MySignedIntEnum>,\n    Types<MySignedEnum, MySignedIntEnum>>::type;\nTYPED_TEST_SUITE(SignedEnumLogFormatTest, SignedEnumTypes);\n\nTYPED_TEST(SignedEnumLogFormatTest, Positive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = static_cast<TypeParam>(224);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"224\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"224\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(SignedEnumLogFormatTest, Negative) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = static_cast<TypeParam>(-112);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"-112\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"-112\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(SignedEnumLogFormatTest, BitfieldPositive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const struct {\n    TypeParam bits : 6;\n  } value{static_cast<TypeParam>(21)};\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value.bits;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"21\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"21\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value.bits;\n}\n\nTYPED_TEST(SignedEnumLogFormatTest, BitfieldNegative) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const struct {\n    TypeParam bits : 6;\n  } value{static_cast<TypeParam>(-21)};\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value.bits;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"-21\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"-21\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value.bits;\n}\n#endif\n\nTEST(FloatLogFormatTest, Positive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const float value = 6.02e23f;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"6.02e+23\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"6.02e+23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(FloatLogFormatTest, Negative) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const float value = -6.02e23f;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"-6.02e+23\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"-6.02e+23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(FloatLogFormatTest, NegativeExponent) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const float value = 6.02e-23f;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"6.02e-23\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"6.02e-23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(DoubleLogFormatTest, Positive) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 6.02e23;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"6.02e+23\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"6.02e+23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(DoubleLogFormatTest, Negative) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = -6.02e23;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"-6.02e+23\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"-6.02e+23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(DoubleLogFormatTest, NegativeExponent) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 6.02e-23;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"6.02e-23\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"6.02e-23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\ntemplate <typename T>\nclass FloatingPointLogFormatTest : public testing::Test {};\nusing FloatingPointTypes = Types<float, double>;\nTYPED_TEST_SUITE(FloatingPointLogFormatTest, FloatingPointTypes);\n\nTYPED_TEST(FloatingPointLogFormatTest, Zero) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = 0.0;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"0\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"0\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(FloatingPointLogFormatTest, Integer) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = 1.0;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"1\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"1\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(FloatingPointLogFormatTest, Infinity) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = std::numeric_limits<TypeParam>::infinity();\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(AnyOf(Eq(\"inf\"), Eq(\"Inf\"))),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"inf\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(FloatingPointLogFormatTest, NegativeInfinity) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = -std::numeric_limits<TypeParam>::infinity();\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(AnyOf(Eq(\"-inf\"), Eq(\"-Inf\"))),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"-inf\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(FloatingPointLogFormatTest, NaN) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = std::numeric_limits<TypeParam>::quiet_NaN();\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(AnyOf(Eq(\"nan\"), Eq(\"NaN\"))),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"nan\"))))))));\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(FloatingPointLogFormatTest, NegativeNaN) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value =\n      std::copysign(std::numeric_limits<TypeParam>::quiet_NaN(), -1.0);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  // On RISC-V, don't expect that formatting -NaN produces the same string as\n  // streaming it. #ifdefing out just the relevant line breaks the MSVC build,\n  // so duplicate the entire EXPECT_CALL.\n#ifdef __riscv\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(AnyOf(Eq(\"-nan\"), Eq(\"nan\"), Eq(\"NaN\"),\n                                           Eq(\"-nan(ind)\"))),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(\n                             ValueWithStr(Eq(\"-nan\")), ValueWithStr(Eq(\"nan\")),\n                             ValueWithStr(Eq(\"-nan(ind)\")))))))));\n#else\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(AnyOf(Eq(\"-nan\"), Eq(\"nan\"), Eq(\"NaN\"),\n                                           Eq(\"-nan(ind)\"))),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(\n                             ValueWithStr(Eq(\"-nan\")), ValueWithStr(Eq(\"nan\")),\n                             ValueWithStr(Eq(\"-nan(ind)\")))))))));\n#endif\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\ntemplate <typename T>\nclass VoidPtrLogFormatTest : public testing::Test {};\nusing VoidPtrTypes = Types<void*, const void*>;\nTYPED_TEST_SUITE(VoidPtrLogFormatTest, VoidPtrTypes);\n\nTYPED_TEST(VoidPtrLogFormatTest, Null) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = nullptr;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(AnyOf(Eq(\"(nil)\"), Eq(\"0\"), Eq(\"0x0\"),\n                                   Eq(\"00000000\"), Eq(\"0000000000000000\"))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(VoidPtrLogFormatTest, NonNull) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefULL);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(AnyOf(Eq(\"0xdeadbeef\"), Eq(\"DEADBEEF\"),\n                                           Eq(\"00000000DEADBEEF\"))),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             AnyOf(ValueWithStr(Eq(\"0xdeadbeef\")),\n                                   ValueWithStr(Eq(\"00000000DEADBEEF\")))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\ntemplate <typename T>\nclass VolatilePtrLogFormatTest : public testing::Test {};\nusing VolatilePtrTypes = Types<\n    volatile void*, const volatile void*, volatile char*, const volatile char*,\n    volatile signed char*, const volatile signed char*, volatile unsigned char*,\n    const volatile unsigned char*, volatile wchar_t*, const volatile wchar_t*>;\nTYPED_TEST_SUITE(VolatilePtrLogFormatTest, VolatilePtrTypes);\n\nTYPED_TEST(VolatilePtrLogFormatTest, Null) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = nullptr;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1147r1.html\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202302L\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(AnyOf(Eq(\"(nil)\"), Eq(\"0\"), Eq(\"0x0\"),\n                                   Eq(\"00000000\"), Eq(\"0000000000000000\"))))));\n#else\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"false\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"false\"))))))));\n#endif\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(VolatilePtrLogFormatTest, NonNull) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const TypeParam value = reinterpret_cast<TypeParam>(0xdeadbeefLL);\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1147r1.html\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202302L\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(AnyOf(Eq(\"0xdeadbeef\"), Eq(\"DEADBEEF\"),\n                                           Eq(\"00000000DEADBEEF\"))),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             AnyOf(ValueWithStr(Eq(\"0xdeadbeef\")),\n                                   ValueWithStr(Eq(\"00000000DEADBEEF\")))))))));\n#else\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"true\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"true\"))))))));\n#endif\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\ntemplate <typename T>\nclass CharPtrLogFormatTest : public testing::Test {};\nusing CharPtrTypes = Types<char, const char, signed char, const signed char,\n                           unsigned char, const unsigned char>;\nTYPED_TEST_SUITE(CharPtrLogFormatTest, CharPtrTypes);\n\nTYPED_TEST(CharPtrLogFormatTest, Null) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  // Streaming `([cv] char *)nullptr` into a `std::ostream` is UB, and some C++\n  // standard library implementations choose to crash.  We take measures to log\n  // something useful instead of crashing, even when that differs from the\n  // standard library in use (and thus the behavior of `std::ostream`).\n  TypeParam* const value = nullptr;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          // `MatchesOstream` deliberately omitted since we deliberately differ.\n          TextMessage(Eq(\"(null)\")), ENCODED_MESSAGE(HasValues(ElementsAre(\n                                         ValueWithStr(Eq(\"(null)\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(CharPtrLogFormatTest, NonNull) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam data[] = {'v', 'a', 'l', 'u', 'e', '\\0'};\n  TypeParam* const value = data;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"value\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"value\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\ntemplate <typename T>\nclass WideCharPtrLogFormatTest : public testing::Test {};\nusing WideCharPtrTypes = Types<wchar_t, const wchar_t>;\nTYPED_TEST_SUITE(WideCharPtrLogFormatTest, WideCharPtrTypes);\n\nTYPED_TEST(WideCharPtrLogFormatTest, Null) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam* const value = nullptr;\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"(null)\")),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(\"(null)\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(WideCharPtrLogFormatTest, NonNull) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam data[] = {'v', 'a', 'l', 'u', 'e', '\\0'};\n  TypeParam* const value = data;\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"value\")),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(\"value\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(BoolLogFormatTest, True) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const bool value = true;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"true\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"true\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(BoolLogFormatTest, False) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const bool value = false;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"false\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"false\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(LogFormatTest, StringLiteral) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << \"value\";\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"value\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithLiteral(Eq(\"value\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << \"value\";\n}\n\nTEST(LogFormatTest, WideStringLiteral) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"value\")),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithLiteral(Eq(\"value\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << L\"value\";\n}\n\nTEST(LogFormatTest, CharArray) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  char value[] = \"value\";\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"value\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"value\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(LogFormatTest, WideCharArray) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  wchar_t value[] = L\"value\";\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"value\")),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(\"value\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\n// Comprehensive test string for validating wchar_t to UTF-8 conversion.\n// See details in absl/strings/internal/utf8_test.cc.\n//\n// clang-format off\n#define ABSL_LOG_INTERNAL_WIDE_LITERAL L\"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中\"\n#define ABSL_LOG_INTERNAL_UTF8_LITERAL u8\"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中\"\n// clang-format on\n\nabsl::string_view GetUtf8TestString() {\n  // `u8\"\"` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn)\n  // without it. However, the resulting character type differs between pre-C++20\n  // (`char`) and C++20 (`char8_t`). So we reinterpret_cast to `char*` and wrap\n  // it in a `string_view`.\n  static const absl::string_view kUtf8TestString(\n      reinterpret_cast<const char*>(ABSL_LOG_INTERNAL_UTF8_LITERAL),\n      sizeof(ABSL_LOG_INTERNAL_UTF8_LITERAL) - 1);\n  return kUtf8TestString;\n}\n\ntemplate <typename T>\nclass WideStringLogFormatTest : public testing::Test {};\nusing StringTypes =\n    Types<std::wstring, const std::wstring, wchar_t[], const wchar_t*>;\nTYPED_TEST_SUITE(WideStringLogFormatTest, StringTypes);\n\nTYPED_TEST(WideStringLogFormatTest, NonLiterals) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = ABSL_LOG_INTERNAL_WIDE_LITERAL;\n  absl::string_view utf8_value = GetUtf8TestString();\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(WideStringLogFormatTest, StringView) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  std::wstring_view value = ABSL_LOG_INTERNAL_WIDE_LITERAL;\n  absl::string_view utf8_value = GetUtf8TestString();\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(WideStringLogFormatTest, Literal) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  absl::string_view utf8_value = GetUtf8TestString();\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithLiteral(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << ABSL_LOG_INTERNAL_WIDE_LITERAL;\n}\n\n#undef ABSL_LOG_INTERNAL_WIDE_LITERAL\n#undef ABSL_LOG_INTERNAL_UTF8_LITERAL\n\nTYPED_TEST(WideStringLogFormatTest, IsolatedLowSurrogatesAreReplaced) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = L\"AAA \\xDC00 BBB\";\n  // NOLINTNEXTLINE(readability/utf8)\n  absl::string_view utf8_value = \"AAA � BBB\";\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(WideStringLogFormatTest,\n           DISABLED_IsolatedHighSurrogatesAreReplaced) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = L\"AAA \\xD800 BBB\";\n  // NOLINTNEXTLINE(readability/utf8)\n  absl::string_view utf8_value = \"AAA � BBB\";\n  // Currently, this is \"AAA \\xF0\\x90 BBB\".\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(WideStringLogFormatTest,\n           DISABLED_ConsecutiveHighSurrogatesAreReplaced) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = L\"AAA \\xD800\\xD800 BBB\";\n  // NOLINTNEXTLINE(readability/utf8)\n  absl::string_view utf8_value = \"AAA �� BBB\";\n  // Currently, this is \"AAA \\xF0\\x90\\xF0\\x90 BBB\".\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(WideStringLogFormatTest,\n           DISABLED_HighHighLowSurrogateSequencesAreReplaced) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = L\"AAA \\xD800\\xD800\\xDC00 BBB\";\n  // NOLINTNEXTLINE(readability/utf8)\n  absl::string_view utf8_value = \"AAA �𐀀 BBB\";\n  // Currently, this is \"AAA \\xF0\\x90𐀀 BBB\".\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(WideStringLogFormatTest,\n           DISABLED_TrailingHighSurrogatesAreReplaced) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = L\"AAA \\xD800\";\n  // NOLINTNEXTLINE(readability/utf8)\n  absl::string_view utf8_value = \"AAA �\";\n  // Currently, this is \"AAA \\xF0\\x90\".\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),\n                                    ENCODED_MESSAGE(HasValues(ElementsAre(\n                                        ValueWithStr(Eq(utf8_value))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTYPED_TEST(WideStringLogFormatTest, EmptyWideString) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  TypeParam value = L\"\";\n\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"\")),\n                                    ENCODED_MESSAGE(HasValues(\n                                        ElementsAre(ValueWithStr(Eq(\"\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nTEST(WideStringLogFormatTest, MixedNarrowAndWideStrings) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(_, _, \"1234\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << \"1\" << L\"2\" << \"3\" << L\"4\";\n}\n\nclass CustomClass {};\nstd::ostream& operator<<(std::ostream& os, const CustomClass&) {\n  return os << \"CustomClass{}\";\n}\n\nTEST(LogFormatTest, Custom) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  CustomClass value;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"CustomClass{}\")),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(\"CustomClass{}\"))))))));\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nclass CustomClassNonCopyable {\n public:\n  CustomClassNonCopyable() = default;\n  CustomClassNonCopyable(const CustomClassNonCopyable&) = delete;\n  CustomClassNonCopyable& operator=(const CustomClassNonCopyable&) = delete;\n};\nstd::ostream& operator<<(std::ostream& os, const CustomClassNonCopyable&) {\n  return os << \"CustomClassNonCopyable{}\";\n}\n\nTEST(LogFormatTest, CustomNonCopyable) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  CustomClassNonCopyable value;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"CustomClassNonCopyable{}\")),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(\"CustomClassNonCopyable{}\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value;\n}\n\nstruct Point {\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const Point& p) {\n    absl::Format(&sink, \"(%d, %d)\", p.x, p.y);\n  }\n\n  int x = 10;\n  int y = 20;\n};\n\nTEST(LogFormatTest, AbslStringifyExample) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  Point p;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(Eq(\"(10, 20)\")), TextMessage(Eq(absl::StrCat(p))),\n                 ENCODED_MESSAGE(\n                     HasValues(ElementsAre(ValueWithStr(Eq(\"(10, 20)\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << p;\n}\n\nstruct PointWithAbslStringifiyAndOstream {\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink,\n                            const PointWithAbslStringifiyAndOstream& p) {\n    absl::Format(&sink, \"(%d, %d)\", p.x, p.y);\n  }\n\n  int x = 10;\n  int y = 20;\n};\n\nABSL_ATTRIBUTE_UNUSED std::ostream& operator<<(\n    std::ostream& os, const PointWithAbslStringifiyAndOstream&) {\n  return os << \"Default to AbslStringify()\";\n}\n\nTEST(LogFormatTest, CustomWithAbslStringifyAndOstream) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  PointWithAbslStringifiyAndOstream p;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(Eq(\"(10, 20)\")), TextMessage(Eq(absl::StrCat(p))),\n                 ENCODED_MESSAGE(\n                     HasValues(ElementsAre(ValueWithStr(Eq(\"(10, 20)\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << p;\n}\n\nstruct PointStreamsNothing {\n  template <typename Sink>\n  friend void AbslStringify(Sink&, const PointStreamsNothing&) {}\n\n  int x = 10;\n  int y = 20;\n};\n\nTEST(LogFormatTest, AbslStringifyStreamsNothing) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  PointStreamsNothing p;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(Eq(\"77\")), TextMessage(Eq(absl::StrCat(p, 77))),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << p << 77;\n}\n\nstruct PointMultipleAppend {\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const PointMultipleAppend& p) {\n    sink.Append(\"(\");\n    sink.Append(absl::StrCat(p.x, \", \", p.y, \")\"));\n  }\n\n  int x = 10;\n  int y = 20;\n};\n\nTEST(LogFormatTest, AbslStringifyMultipleAppend) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  PointMultipleAppend p;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(Eq(\"(10, 20)\")), TextMessage(Eq(absl::StrCat(p))),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"(\")), ValueWithStr(Eq(\"10, 20)\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << p;\n}\n\nTEST(ManipulatorLogFormatTest, BoolAlphaTrue) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const bool value = true;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::noboolalpha << value << \" \"  //\n                    << std::boolalpha << value << \" \"    //\n                    << std::noboolalpha << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"1 true 1\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"1\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"true\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"1\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::noboolalpha << value << \" \"  //\n            << std::boolalpha << value << \" \"    //\n            << std::noboolalpha << value;\n}\n\nTEST(ManipulatorLogFormatTest, BoolAlphaFalse) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const bool value = false;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::noboolalpha << value << \" \"  //\n                    << std::boolalpha << value << \" \"    //\n                    << std::noboolalpha << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"0 false 0\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"0\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"false\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"0\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::noboolalpha << value << \" \"  //\n            << std::boolalpha << value << \" \"    //\n            << std::noboolalpha << value;\n}\n\nTEST(ManipulatorLogFormatTest, ShowPoint) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 77.0;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::noshowpoint << value << \" \"  //\n                    << std::showpoint << value << \" \"    //\n                    << std::noshowpoint << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"77 77.0000 77\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"77\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"77.0000\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::noshowpoint << value << \" \"  //\n            << std::showpoint << value << \" \"    //\n            << std::noshowpoint << value;\n}\n\nTEST(ManipulatorLogFormatTest, ShowPos) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::noshowpos << value << \" \"  //\n                    << std::showpos << value << \" \"    //\n                    << std::noshowpos << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"77 +77 77\")),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(\"77\")), ValueWithLiteral(Eq(\" \")),\n                             ValueWithStr(Eq(\"+77\")), ValueWithLiteral(Eq(\" \")),\n                             ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::noshowpos << value << \" \"  //\n            << std::showpos << value << \" \"    //\n            << std::noshowpos << value;\n}\n\nTEST(ManipulatorLogFormatTest, UppercaseFloat) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 7.7e7;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::nouppercase << value << \" \"  //\n                    << std::uppercase << value << \" \"    //\n                    << std::nouppercase << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"7.7e+07 7.7E+07 7.7e+07\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"7.7e+07\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"7.7E+07\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"7.7e+07\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::nouppercase << value << \" \"  //\n            << std::uppercase << value << \" \"    //\n            << std::nouppercase << value;\n}\n\nTEST(ManipulatorLogFormatTest, Hex) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 0x77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::hex << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"0x77\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"0x77\"))))))));\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hex << value;\n}\n\nTEST(ManipulatorLogFormatTest, Oct) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 077;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::oct << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"077\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"077\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::oct << value;\n}\n\nTEST(ManipulatorLogFormatTest, Dec) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::hex << std::dec << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"77\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hex << std::dec << value;\n}\n\nTEST(ManipulatorLogFormatTest, ShowbaseHex) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 0x77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::hex                         //\n                    << std::noshowbase << value << \" \"  //\n                    << std::showbase << value << \" \"    //\n                    << std::noshowbase << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"77 0x77 77\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"77\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"0x77\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hex                         //\n            << std::noshowbase << value << \" \"  //\n            << std::showbase << value << \" \"    //\n            << std::noshowbase << value;\n}\n\nTEST(ManipulatorLogFormatTest, ShowbaseOct) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 077;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::oct                         //\n                    << std::noshowbase << value << \" \"  //\n                    << std::showbase << value << \" \"    //\n                    << std::noshowbase << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"77 077 77\")),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(\"77\")), ValueWithLiteral(Eq(\" \")),\n                             ValueWithStr(Eq(\"077\")), ValueWithLiteral(Eq(\" \")),\n                             ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::oct                         //\n            << std::noshowbase << value << \" \"  //\n            << std::showbase << value << \" \"    //\n            << std::noshowbase << value;\n}\n\nTEST(ManipulatorLogFormatTest, UppercaseHex) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 0xbeef;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream                        //\n      << std::hex                          //\n      << std::nouppercase << value << \" \"  //\n      << std::uppercase << value << \" \"    //\n      << std::nouppercase << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"0xbeef 0XBEEF 0xbeef\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"0xbeef\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"0XBEEF\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"0xbeef\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hex                          //\n            << std::nouppercase << value << \" \"  //\n            << std::uppercase << value << \" \"    //\n            << std::nouppercase << value;\n}\n\nTEST(ManipulatorLogFormatTest, FixedFloat) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 7.7e7;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::fixed << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"77000000.000000\")),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(\"77000000.000000\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::fixed << value;\n}\n\nTEST(ManipulatorLogFormatTest, ScientificFloat) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 7.7e7;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::scientific << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"7.700000e+07\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"7.700000e+07\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::scientific << value;\n}\n\n#if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22)\n// Bionic doesn't support `%a` until API 22, so this prints 'a' even if the\n// C++ standard library implements it correctly (by forwarding to printf).\n#elif defined(__GLIBCXX__) && __cplusplus < 201402L\n// libstdc++ shipped C++11 support without `std::hexfloat`.\n#else\nTEST(ManipulatorLogFormatTest, FixedAndScientificFloat) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 7.7e7;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::setiosflags(std::ios_base::scientific |\n                                        std::ios_base::fixed)\n                    << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(AnyOf(Eq(\"0x1.25bb50p+26\"), Eq(\"0x1.25bb5p+26\"),\n                                   Eq(\"0x1.25bb500000000p+26\"))),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     AnyOf(ValueWithStr(Eq(\"0x1.25bb5p+26\")),\n                           ValueWithStr(Eq(\"0x1.25bb500000000p+26\")))))))));\n\n  test_sink.StartCapturingLogs();\n\n  // This combination should mean the same thing as `std::hexfloat`.\n  LOG(INFO) << std::setiosflags(std::ios_base::scientific |\n                                std::ios_base::fixed)\n            << value;\n}\n#endif\n\n#if defined(__BIONIC__) && (!defined(__ANDROID_API__) || __ANDROID_API__ < 22)\n// Bionic doesn't support `%a` until API 22, so this prints 'a' even if the C++\n// standard library supports `std::hexfloat` (by forwarding to printf).\n#elif defined(__GLIBCXX__) && __cplusplus < 201402L\n// libstdc++ shipped C++11 support without `std::hexfloat`.\n#else\nTEST(ManipulatorLogFormatTest, HexfloatFloat) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 7.7e7;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::hexfloat << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(AnyOf(Eq(\"0x1.25bb50p+26\"), Eq(\"0x1.25bb5p+26\"),\n                                   Eq(\"0x1.25bb500000000p+26\"))),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     AnyOf(ValueWithStr(Eq(\"0x1.25bb5p+26\")),\n                           ValueWithStr(Eq(\"0x1.25bb500000000p+26\")))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hexfloat << value;\n}\n#endif\n\nTEST(ManipulatorLogFormatTest, DefaultFloatFloat) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 7.7e7;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::hexfloat << std::defaultfloat << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"7.7e+07\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"7.7e+07\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hexfloat << std::defaultfloat << value;\n}\n\nTEST(ManipulatorLogFormatTest, Ends) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::ends;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(absl::string_view(\"\\0\", 1))),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(absl::string_view(\"\\0\", 1)))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::ends;\n}\n\nTEST(ManipulatorLogFormatTest, Endl) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::endl;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"\\n\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"\\n\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::endl;\n}\n\nTEST(ManipulatorLogFormatTest, SetIosFlags) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 0x77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::resetiosflags(std::ios_base::basefield)\n                    << std::setiosflags(std::ios_base::hex) << value << \" \"  //\n                    << std::resetiosflags(std::ios_base::basefield)\n                    << std::setiosflags(std::ios_base::dec) << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)),\n          TextMessage(Eq(\"0x77 119\")),\n          // `std::setiosflags` and `std::resetiosflags` aren't manipulators.\n          // We're unable to distinguish their return type(s) from arbitrary\n          // user-defined types and thus don't suppress the empty str value.\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"0x77\")),\n                                                ValueWithLiteral(Eq(\" \")),\n                                                ValueWithStr(Eq(\"119\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::resetiosflags(std::ios_base::basefield)\n            << std::setiosflags(std::ios_base::hex) << value << \" \"  //\n            << std::resetiosflags(std::ios_base::basefield)\n            << std::setiosflags(std::ios_base::dec) << value;\n}\n\nTEST(ManipulatorLogFormatTest, SetBase) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 0x77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::setbase(16) << value << \" \"  //\n                    << std::setbase(0) << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"0x77 119\")),\n                 // `std::setbase` isn't a manipulator.  We're unable to\n                 // distinguish its return type from arbitrary user-defined\n                 // types and thus don't suppress the empty str value.\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"0x77\")), ValueWithLiteral(Eq(\" \")),\n                     ValueWithStr(Eq(\"119\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::setbase(16) << value << \" \"  //\n            << std::setbase(0) << value;\n}\n\nTEST(ManipulatorLogFormatTest, SetPrecision) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 6.022140857e23;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::setprecision(4) << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"6.022e+23\")),\n                 // `std::setprecision` isn't a manipulator.  We're unable to\n                 // distinguish its return type from arbitrary user-defined\n                 // types and thus don't suppress the empty str value.\n                 ENCODED_MESSAGE(\n                     HasValues(ElementsAre(ValueWithStr(Eq(\"6.022e+23\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::setprecision(4) << value;\n}\n\nTEST(ManipulatorLogFormatTest, SetPrecisionOverflow) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const double value = 6.022140857e23;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::setprecision(200) << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"602214085700000015187968\")),\n                         ENCODED_MESSAGE(HasValues(ElementsAre(\n                             ValueWithStr(Eq(\"602214085700000015187968\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::setprecision(200) << value;\n}\n\nTEST(ManipulatorLogFormatTest, SetW) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::setw(8) << value;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"      77\")),\n                 // `std::setw` isn't a manipulator.  We're unable to\n                 // distinguish its return type from arbitrary user-defined\n                 // types and thus don't suppress the empty str value.\n                 ENCODED_MESSAGE(\n                     HasValues(ElementsAre(ValueWithStr(Eq(\"      77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::setw(8) << value;\n}\n\nTEST(ManipulatorLogFormatTest, Left) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = -77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::left << std::setw(8) << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"-77     \")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"-77     \"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::left << std::setw(8) << value;\n}\n\nTEST(ManipulatorLogFormatTest, Right) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = -77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::right << std::setw(8) << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"     -77\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"     -77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::right << std::setw(8) << value;\n}\n\nTEST(ManipulatorLogFormatTest, Internal) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = -77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::internal << std::setw(8) << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"-     77\")),\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"-     77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::internal << std::setw(8) << value;\n}\n\nTEST(ManipulatorLogFormatTest, SetFill) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int value = 77;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << std::setfill('0') << std::setw(8) << value;\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                         TextMessage(Eq(\"00000077\")),\n                         // `std::setfill` isn't a manipulator.  We're\n                         // unable to distinguish its return\n                         // type from arbitrary user-defined types and\n                         // thus don't suppress the empty str value.\n                         ENCODED_MESSAGE(HasValues(\n                             ElementsAre(ValueWithStr(Eq(\"00000077\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::setfill('0') << std::setw(8) << value;\n}\n\nclass FromCustomClass {};\nstd::ostream& operator<<(std::ostream& os, const FromCustomClass&) {\n  return os << \"FromCustomClass{}\" << std::hex;\n}\n\nTEST(ManipulatorLogFormatTest, FromCustom) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  FromCustomClass value;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value << \" \" << 0x77;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),\n                 TextMessage(Eq(\"FromCustomClass{} 0x77\")),\n                 ENCODED_MESSAGE(HasValues(ElementsAre(\n                     ValueWithStr(Eq(\"FromCustomClass{}\")),\n                     ValueWithLiteral(Eq(\" \")), ValueWithStr(Eq(\"0x77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value << \" \" << 0x77;\n}\n\nclass StreamsNothing {};\nstd::ostream& operator<<(std::ostream& os, const StreamsNothing&) { return os; }\n\nTEST(ManipulatorLogFormatTest, CustomClassStreamsNothing) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  StreamsNothing value;\n  auto comparison_stream = ComparisonStream();\n  comparison_stream << value << 77;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq(\"77\")),\n          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq(\"77\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << value << 77;\n}\n\nstruct PointPercentV {\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const PointPercentV& p) {\n    absl::Format(&sink, \"(%v, %v)\", p.x, p.y);\n  }\n\n  int x = 10;\n  int y = 20;\n};\n\nTEST(ManipulatorLogFormatTest, IOManipsDoNotAffectAbslStringify) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  PointPercentV p;\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(TextMessage(Eq(\"(10, 20)\")), TextMessage(Eq(absl::StrCat(p))),\n                 ENCODED_MESSAGE(\n                     HasValues(ElementsAre(ValueWithStr(Eq(\"(10, 20)\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::hex << p;\n}\n\nTEST(StructuredLoggingOverflowTest, TruncatesStrings) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  // This message is too long and should be truncated to some unspecified size\n  // no greater than the buffer size but not too much less either.  It should be\n  // truncated rather than discarded.\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(AllOf(\n              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),\n                           Le(absl::log_internal::kLogMessageBufferSize))),\n              Each(Eq('x')))),\n          ENCODED_MESSAGE(HasOneStrThat(AllOf(\n              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),\n                           Le(absl::log_internal::kLogMessageBufferSize))),\n              Each(Eq('x'))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x');\n}\n\nTEST(StructuredLoggingOverflowTest, TruncatesWideStrings) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  // This message is too long and should be truncated to some unspecified size\n  // no greater than the buffer size but not too much less either.  It should be\n  // truncated rather than discarded.\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(AllOf(\n              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),\n                           Le(absl::log_internal::kLogMessageBufferSize))),\n              Each(Eq('x')))),\n          ENCODED_MESSAGE(HasOneStrThat(AllOf(\n              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),\n                           Le(absl::log_internal::kLogMessageBufferSize))),\n              Each(Eq('x'))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << std::wstring(2 * absl::log_internal::kLogMessageBufferSize,\n                            L'x');\n}\n\nstruct StringLike {\n  absl::string_view data;\n};\nstd::ostream& operator<<(std::ostream& os, StringLike str) {\n  return os << str.data;\n}\n\nTEST(StructuredLoggingOverflowTest, TruncatesInsertionOperators) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  // This message is too long and should be truncated to some unspecified size\n  // no greater than the buffer size but not too much less either.  It should be\n  // truncated rather than discarded.\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(AllOf(\n              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),\n                           Le(absl::log_internal::kLogMessageBufferSize))),\n              Each(Eq('x')))),\n          ENCODED_MESSAGE(HasOneStrThat(AllOf(\n              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),\n                           Le(absl::log_internal::kLogMessageBufferSize))),\n              Each(Eq('x'))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << StringLike{\n      std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x')};\n}\n\n// Returns the size of the largest string that will fit in a `LOG` message\n// buffer with no prefix.\nsize_t MaxLogFieldLengthNoPrefix() {\n  class StringLengthExtractorSink : public absl::LogSink {\n   public:\n    void Send(const absl::LogEntry& entry) override {\n      CHECK(!size_.has_value());\n      CHECK_EQ(entry.text_message().find_first_not_of('x'),\n               absl::string_view::npos);\n      size_.emplace(entry.text_message().size());\n    }\n    size_t size() const {\n      CHECK(size_.has_value());\n      return *size_;\n    }\n\n   private:\n    std::optional<size_t> size_;\n  } extractor_sink;\n  LOG(INFO).NoPrefix().ToSinkOnly(&extractor_sink)\n      << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x');\n  return extractor_sink.size();\n}\n\nTEST(StructuredLoggingOverflowTest, TruncatesStringsCleanly) {\n  const size_t longest_fit = MaxLogFieldLengthNoPrefix();\n  // To log a second value field, we need four bytes: two tag/type bytes and two\n  // sizes.  To put any data in the field we need a fifth byte.\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits exactly, no part of y fits.\n    LOG(INFO).NoPrefix() << std::string(longest_fit, 'x') << \"y\";\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 1), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, one byte from y's header fits but shouldn't be visible.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 1, 'x') << \"y\";\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 2), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, two bytes from y's header fit but shouldn't be visible.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 2, 'x') << \"y\";\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 3), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, three bytes from y's header fit but shouldn't be visible.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 3, 'x') << \"y\";\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrAndOneLiteralThat(\n                               AllOf(SizeIs(longest_fit - 4), Each(Eq('x'))),\n                               IsEmpty())),\n                           RawEncodedMessage(Not(AsString(EndsWith(\"x\")))))));\n    test_sink.StartCapturingLogs();\n    // x fits, all four bytes from y's header fit but no data bytes do, so we\n    // encode an empty string.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 4, 'x') << \"y\";\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(ENCODED_MESSAGE(HasOneStrAndOneLiteralThat(\n                       AllOf(SizeIs(longest_fit - 5), Each(Eq('x'))), Eq(\"y\"))),\n                   RawEncodedMessage(AsString(EndsWith(\"y\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, y fits exactly.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 5, 'x') << \"y\";\n  }\n}\n\nTEST(StructuredLoggingOverflowTest, TruncatesInsertionOperatorsCleanly) {\n  const size_t longest_fit = MaxLogFieldLengthNoPrefix();\n  // To log a second value field, we need four bytes: two tag/type bytes and two\n  // sizes.  To put any data in the field we need a fifth byte.\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits exactly, no part of y fits.\n    LOG(INFO).NoPrefix() << std::string(longest_fit, 'x') << StringLike{\"y\"};\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 1), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, one byte from y's header fits but shouldn't be visible.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 1, 'x')\n                         << StringLike{\"y\"};\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 2), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, two bytes from y's header fit but shouldn't be visible.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 2, 'x')\n                         << StringLike{\"y\"};\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 3), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, three bytes from y's header fit but shouldn't be visible.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 3, 'x')\n                         << StringLike{\"y\"};\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(test_sink,\n                Send(AllOf(ENCODED_MESSAGE(HasOneStrThat(\n                               AllOf(SizeIs(longest_fit - 4), Each(Eq('x'))))),\n                           RawEncodedMessage(AsString(EndsWith(\"x\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, all four bytes from y's header fit but no data bytes do.  We\n    // don't encode an empty string here because every I/O manipulator hits this\n    // codepath and those shouldn't leave empty strings behind.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 4, 'x')\n                         << StringLike{\"y\"};\n  }\n  {\n    absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n    EXPECT_CALL(test_sink, Send).Times(0);\n    EXPECT_CALL(\n        test_sink,\n        Send(AllOf(ENCODED_MESSAGE(HasTwoStrsThat(\n                       AllOf(SizeIs(longest_fit - 5), Each(Eq('x'))), Eq(\"y\"))),\n                   RawEncodedMessage(AsString(EndsWith(\"y\"))))));\n    test_sink.StartCapturingLogs();\n    // x fits, y fits exactly.\n    LOG(INFO).NoPrefix() << std::string(longest_fit - 5, 'x')\n                         << StringLike{\"y\"};\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/log_macro_hygiene_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n\nnamespace {\nusing ::testing::_;\nusing ::testing::Eq;\n\nnamespace not_absl {\n\nclass Dummy {\n public:\n  Dummy() {}\n\n private:\n  Dummy(const Dummy&) = delete;\n  Dummy& operator=(const Dummy&) = delete;\n};\n\n// This line tests that local definitions of INFO, WARNING, ERROR, and\n// etc don't shadow the global ones used by the logging macros.  If\n// they do, the LOG() calls in the tests won't compile, catching the\n// bug.\nconst Dummy INFO, WARNING, ERROR, FATAL, NUM_SEVERITIES;\n\n// These makes sure that the uses of same-named types in the\n// implementation of the logging macros are fully qualified.\nclass string {};\nclass vector {};\nclass LogMessage {};\nclass LogMessageFatal {};\nclass LogMessageQuietlyFatal {};\nclass LogMessageVoidify {};\nclass LogSink {};\nclass NullStream {};\nclass NullStreamFatal {};\n\n}  // namespace not_absl\n\nusing namespace not_absl;  // NOLINT\n\n// Tests for LOG(LEVEL(()).\n\nTEST(LogHygieneTest, WorksForQualifiedSeverity) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  ::testing::InSequence seq;\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"To INFO\"));\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, \"To WARNING\"));\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, \"To ERROR\"));\n\n  test_sink.StartCapturingLogs();\n  // Note that LOG(LEVEL()) expects the severity as a run-time\n  // expression (as opposed to a compile-time constant).  Hence we\n  // test that :: is allowed before INFO, etc.\n  LOG(LEVEL(absl::LogSeverity::kInfo)) << \"To INFO\";\n  LOG(LEVEL(absl::LogSeverity::kWarning)) << \"To WARNING\";\n  LOG(LEVEL(absl::LogSeverity::kError)) << \"To ERROR\";\n}\n\nTEST(LogHygieneTest, WorksWithAlternativeINFOSymbol) {\n  const double INFO ABSL_ATTRIBUTE_UNUSED = 7.77;\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"Hello world\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << \"Hello world\";\n}\n\nTEST(LogHygieneTest, WorksWithAlternativeWARNINGSymbol) {\n  const double WARNING ABSL_ATTRIBUTE_UNUSED = 7.77;\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, \"Hello world\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(WARNING) << \"Hello world\";\n}\n\nTEST(LogHygieneTest, WorksWithAlternativeERRORSymbol) {\n  const double ERROR ABSL_ATTRIBUTE_UNUSED = 7.77;\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, \"Hello world\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(ERROR) << \"Hello world\";\n}\n\nTEST(LogHygieneTest, WorksWithAlternativeLEVELSymbol) {\n  const double LEVEL ABSL_ATTRIBUTE_UNUSED = 7.77;\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, \"Hello world\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(LEVEL(absl::LogSeverity::kError)) << \"Hello world\";\n}\n\n#define INFO Bogus\n#ifdef NDEBUG\nconstexpr bool IsOptimized = false;\n#else\nconstexpr bool IsOptimized = true;\n#endif\n\nTEST(LogHygieneTest, WorksWithINFODefined) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"Hello world\"))\n      .Times(2 + (IsOptimized ? 2 : 0));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << \"Hello world\";\n  LOG_IF(INFO, true) << \"Hello world\";\n\n  DLOG(INFO) << \"Hello world\";\n  DLOG_IF(INFO, true) << \"Hello world\";\n}\n\n#undef INFO\n\n#define _INFO Bogus\nTEST(LogHygieneTest, WorksWithUnderscoreINFODefined) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"Hello world\"))\n      .Times(2 + (IsOptimized ? 2 : 0));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << \"Hello world\";\n  LOG_IF(INFO, true) << \"Hello world\";\n\n  DLOG(INFO) << \"Hello world\";\n  DLOG_IF(INFO, true) << \"Hello world\";\n}\n#undef _INFO\n\nTEST(LogHygieneTest, ExpressionEvaluationInLEVELSeverity) {\n  auto i = static_cast<int>(absl::LogSeverity::kInfo);\n  LOG(LEVEL(++i)) << \"hello world\";  // NOLINT\n  EXPECT_THAT(i, Eq(static_cast<int>(absl::LogSeverity::kInfo) + 1));\n}\n\nTEST(LogHygieneTest, ExpressionEvaluationInStreamedMessage) {\n  int i = 0;\n  LOG(INFO) << ++i;\n  EXPECT_THAT(i, 1);\n  LOG_IF(INFO, false) << ++i;\n  EXPECT_THAT(i, 1);\n}\n\n// Tests that macros are usable in unbraced switch statements.\n// -----------------------------------------------------------\n\nclass UnbracedSwitchCompileTest {\n  static void Log() {\n    switch (0) {\n      case 0:\n        LOG(INFO);\n        break;\n      default:\n        break;\n    }\n  }\n};\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/log_modifier_methods_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <errno.h>\n\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/internal/test_actions.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/log/scoped_mock_log.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/source_location.h\"\n\nnamespace {\n#if GTEST_HAS_DEATH_TEST\nusing ::absl::log_internal::DeathTestExpectedLogging;\nusing ::absl::log_internal::DeathTestUnexpectedLogging;\nusing ::absl::log_internal::DeathTestValidateExpectations;\nusing ::absl::log_internal::DiedOfQFatal;\n#endif\nusing ::absl::log_internal::LogSeverity;\nusing ::absl::log_internal::Prefix;\nusing ::absl::log_internal::SourceBasename;\nusing ::absl::log_internal::SourceFilename;\nusing ::absl::log_internal::SourceLine;\nusing ::absl::log_internal::Stacktrace;\nusing ::absl::log_internal::TextMessage;\nusing ::absl::log_internal::TextMessageWithPrefix;\nusing ::absl::log_internal::TextMessageWithPrefixAndNewline;\nusing ::absl::log_internal::TextPrefix;\nusing ::absl::log_internal::ThreadID;\nusing ::absl::log_internal::Timestamp;\nusing ::absl::log_internal::Verbosity;\n\nusing ::testing::AllOf;\nusing ::testing::AnyNumber;\nusing ::testing::AnyOf;\nusing ::testing::Eq;\nusing ::testing::IsEmpty;\nusing ::testing::IsFalse;\nusing ::testing::Truly;\n\nTEST(TailCallsModifiesTest, AtLocationFileLine) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          // The metadata should change:\n          SourceFilename(Eq(\"/my/very/very/very_long_source_file.cc\")),\n          SourceBasename(Eq(\"very_long_source_file.cc\")), SourceLine(Eq(777)),\n          // The logged line should change too, even though the prefix must\n          // grow to fit the new metadata.\n          TextMessageWithPrefix(Truly([](absl::string_view msg) {\n            return absl::EndsWith(msg,\n                                  \" very_long_source_file.cc:777] hello world\");\n          })))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).AtLocation(\"/my/very/very/very_long_source_file.cc\", 777)\n      << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, AtLocationFileLineLifetime) {\n  // The macro takes care to not use this temporary after its lifetime.\n  // The only salient expectation is \"no sanitizer diagnostics\".\n  LOG(INFO).AtLocation(std::string(\"/my/very/very/very_long_source_file.cc\"),\n                       777)\n      << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, AtLocationSourceLocation) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  const int log_line = __LINE__ + 1;\n  constexpr absl::SourceLocation loc = absl::SourceLocation::current();\n  auto do_log = [loc] { LOG(INFO).AtLocation(loc) << \"hello world\"; };\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(SourceFilename(Eq(__FILE__)),\n                         SourceBasename(Eq(\"log_modifier_methods_test.cc\")),\n                         SourceLine(Eq(log_line)))));\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\nTEST(TailCallsModifiesTest, NoPrefix) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(AllOf(Prefix(IsFalse()), TextPrefix(IsEmpty()),\n                                    TextMessageWithPrefix(Eq(\"hello world\")))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).NoPrefix() << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, NoPrefixNoMessageNoShirtNoShoesNoService) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(Prefix(IsFalse()), TextPrefix(IsEmpty()),\n                         TextMessageWithPrefix(IsEmpty()),\n                         TextMessageWithPrefixAndNewline(Eq(\"\\n\")))));\n  test_sink.StartCapturingLogs();\n  LOG(INFO).NoPrefix();\n}\n\nTEST(TailCallsModifiesTest, WithVerbosity) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(Verbosity(Eq(2))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).WithVerbosity(2) << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, WithVerbosityNoVerbosity) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink,\n              Send(Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).WithVerbosity(2).WithVerbosity(absl::LogEntry::kNoVerbosityLevel)\n      << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, WithTimestamp) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(Timestamp(Eq(absl::UnixEpoch()))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).WithTimestamp(absl::UnixEpoch()) << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, WithThreadID) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(ThreadID(Eq(absl::LogEntry::tid_t{1234})))));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).WithThreadID(1234) << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, WithMetadataFrom) {\n  class ForwardingLogSink : public absl::LogSink {\n   public:\n    void Send(const absl::LogEntry &entry) override {\n      LOG(LEVEL(entry.log_severity())).WithMetadataFrom(entry)\n          << \"forwarded: \" << entry.text_message();\n    }\n  } forwarding_sink;\n\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(SourceFilename(Eq(\"fake/file\")), SourceBasename(Eq(\"file\")),\n                 SourceLine(Eq(123)), Prefix(IsFalse()),\n                 LogSeverity(Eq(absl::LogSeverity::kWarning)),\n                 Timestamp(Eq(absl::UnixEpoch())),\n                 ThreadID(Eq(absl::LogEntry::tid_t{456})),\n                 TextMessage(Eq(\"forwarded: hello world\")), Verbosity(Eq(7)),\n                 ENCODED_MESSAGE(MatchesEvent(\n                     Eq(\"fake/file\"), Eq(123), Eq(absl::UnixEpoch()),\n                     Eq(logging::proto::WARNING), Eq(456),\n                     ElementsAre(ValueWithLiteral(Eq(\"forwarded: \")),\n                                 ValueWithStr(Eq(\"hello world\"))))))));\n\n  test_sink.StartCapturingLogs();\n  LOG(WARNING)\n          .AtLocation(\"fake/file\", 123)\n          .NoPrefix()\n          .WithTimestamp(absl::UnixEpoch())\n          .WithThreadID(456)\n          .WithVerbosity(7)\n          .ToSinkOnly(&forwarding_sink)\n      << \"hello world\";\n}\n\nTEST(TailCallsModifiesTest, WithPerror) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          TextMessage(AnyOf(Eq(\"hello world: Bad file number [9]\"),\n                            Eq(\"hello world: Bad file descriptor [9]\"),\n                            Eq(\"hello world: Bad file descriptor [8]\"))),\n          ENCODED_MESSAGE(HasValues(ElementsAre(\n              ValueWithLiteral(Eq(\"hello world\")), ValueWithLiteral(Eq(\": \")),\n              AnyOf(ValueWithStr(Eq(\"Bad file number\")),\n                    ValueWithStr(Eq(\"Bad file descriptor\"))),\n              ValueWithLiteral(Eq(\" [\")),\n              AnyOf(ValueWithStr(Eq(\"8\")), ValueWithStr(Eq(\"9\"))),\n              ValueWithLiteral(Eq(\"]\"))))))));\n\n  test_sink.StartCapturingLogs();\n  errno = EBADF;\n  LOG(INFO).WithPerror() << \"hello world\";\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(ModifierMethodDeathTest, ToSinkOnlyQFatal) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink(\n            absl::MockLogDefault::kDisallowUnexpected);\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        auto do_log = [&test_sink] {\n          LOG(QFATAL).ToSinkOnly(&test_sink.UseAsLocalSink()) << \"hello world\";\n        };\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"hello world\")),\n                                          Stacktrace(IsEmpty()))))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        do_log();\n      },\n      DiedOfQFatal, DeathTestValidateExpectations());\n}\n#endif\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/log_sink.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/log_sink.h\"\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nvoid LogSink::KeyFunction() const {}\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/log_sink.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/log_sink.h\n// -----------------------------------------------------------------------------\n//\n// This header declares the interface class `absl::LogSink`.\n\n#ifndef ABSL_LOG_LOG_SINK_H_\n#define ABSL_LOG_LOG_SINK_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/log/log_entry.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::LogSink\n//\n// `absl::LogSink` is an interface which can be extended to intercept and\n// process particular messages (with `LOG.ToSinkOnly()` or\n// `LOG.ToSinkAlso()`) or all messages (if registered with\n// `absl::AddLogSink`).  Implementations must not take any locks that might be\n// held by the `LOG` caller.\nclass LogSink {\n public:\n  virtual ~LogSink() = default;\n\n  // LogSink::Send()\n  //\n  // `Send` is called synchronously during the log statement.  `Send` must be\n  // thread-safe.\n  //\n  // It is safe to use `LOG` within an implementation of `Send`.  `ToSinkOnly`\n  // and `ToSinkAlso` are safe in general but can be used to create an infinite\n  // loop if you try.\n  virtual void Send(const absl::LogEntry& entry) = 0;\n\n  // LogSink::Flush()\n  //\n  // Sinks that buffer messages should override this method to flush the buffer\n  // and return.  `Flush` must be thread-safe.\n  virtual void Flush() {}\n\n protected:\n  LogSink() = default;\n  // Implementations may be copyable and/or movable.\n  LogSink(const LogSink&) = default;\n  LogSink& operator=(const LogSink&) = default;\n\n private:\n  // https://lld.llvm.org/missingkeyfunction.html#missing-key-function\n  virtual void KeyFunction() const final;  // NOLINT(readability/inheritance)\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_LOG_SINK_H_\n"
  },
  {
    "path": "absl/log/log_sink_registry.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/log_sink_registry.h\n// -----------------------------------------------------------------------------\n//\n// This header declares APIs to operate on global set of registered log sinks.\n\n#ifndef ABSL_LOG_LOG_SINK_REGISTRY_H_\n#define ABSL_LOG_LOG_SINK_REGISTRY_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/log/internal/log_sink_set.h\"\n#include \"absl/log/log_sink.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// AddLogSink(), RemoveLogSink()\n//\n// Adds or removes a `absl::LogSink` as a consumer of logging data.\n//\n// These functions are thread-safe.\n//\n// It is an error to attempt to add a sink that's already registered or to\n// attempt to remove one that isn't.\n//\n// To avoid unbounded recursion, dispatch to registered `absl::LogSink`s is\n// disabled per-thread while running the `Send()` method of registered\n// `absl::LogSink`s.  Affected messages are dispatched to a special internal\n// sink instead which writes them to `stderr`.\n//\n// Do not call these inside `absl::LogSink::Send`.\ninline void AddLogSink(absl::LogSink* absl_nonnull sink) {\n  log_internal::AddLogSink(sink);\n}\ninline void RemoveLogSink(absl::LogSink* absl_nonnull sink) {\n  log_internal::RemoveLogSink(sink);\n}\n\n// FlushLogSinks()\n//\n// Calls `absl::LogSink::Flush` on all registered sinks.\n//\n// Do not call this inside `absl::LogSink::Send`.\ninline void FlushLogSinks() { log_internal::FlushLogSinks(); }\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_LOG_SINK_REGISTRY_H_\n"
  },
  {
    "path": "absl/log/log_sink_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/log_sink.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/log/internal/test_actions.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/log_sink_registry.h\"\n#include \"absl/log/scoped_mock_log.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nusing ::absl::log_internal::DeathTestExpectedLogging;\nusing ::absl::log_internal::DeathTestUnexpectedLogging;\nusing ::absl::log_internal::DeathTestValidateExpectations;\nusing ::absl::log_internal::DiedOfFatal;\nusing ::testing::_;\nusing ::testing::AnyNumber;\nusing ::testing::HasSubstr;\nusing ::testing::InSequence;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\n// Tests for global log sink registration.\n// ---------------------------------------\n\nTEST(LogSinkRegistryTest, AddLogSink) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  InSequence s;\n  EXPECT_CALL(test_sink, Log(_, _, \"hello world\")).Times(0);\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, __FILE__, \"Test : 42\"));\n  EXPECT_CALL(test_sink,\n              Log(absl::LogSeverity::kWarning, __FILE__, \"Danger ahead\"));\n  EXPECT_CALL(test_sink,\n              Log(absl::LogSeverity::kError, __FILE__, \"This is an error\"));\n\n  LOG(INFO) << \"hello world\";\n  test_sink.StartCapturingLogs();\n\n  LOG(INFO) << \"Test : \" << 42;\n  LOG(WARNING) << \"Danger\" << ' ' << \"ahead\";\n  LOG(ERROR) << \"This is an error\";\n\n  test_sink.StopCapturingLogs();\n  LOG(INFO) << \"Goodby world\";\n}\n\nTEST(LogSinkRegistryTest, MultipleLogSinks) {\n  absl::ScopedMockLog test_sink1(absl::MockLogDefault::kDisallowUnexpected);\n  absl::ScopedMockLog test_sink2(absl::MockLogDefault::kDisallowUnexpected);\n\n  ::testing::InSequence seq;\n  EXPECT_CALL(test_sink1, Log(absl::LogSeverity::kInfo, _, \"First\")).Times(1);\n  EXPECT_CALL(test_sink2, Log(absl::LogSeverity::kInfo, _, \"First\")).Times(0);\n\n  EXPECT_CALL(test_sink1, Log(absl::LogSeverity::kInfo, _, \"Second\")).Times(1);\n  EXPECT_CALL(test_sink2, Log(absl::LogSeverity::kInfo, _, \"Second\")).Times(1);\n\n  EXPECT_CALL(test_sink1, Log(absl::LogSeverity::kInfo, _, \"Third\")).Times(0);\n  EXPECT_CALL(test_sink2, Log(absl::LogSeverity::kInfo, _, \"Third\")).Times(1);\n\n  LOG(INFO) << \"Before first\";\n\n  test_sink1.StartCapturingLogs();\n  LOG(INFO) << \"First\";\n\n  test_sink2.StartCapturingLogs();\n  LOG(INFO) << \"Second\";\n\n  test_sink1.StopCapturingLogs();\n  LOG(INFO) << \"Third\";\n\n  test_sink2.StopCapturingLogs();\n  LOG(INFO) << \"Fourth\";\n}\n\nTEST(LogSinkRegistrationDeathTest, DuplicateSinkRegistration) {\n  ASSERT_DEATH_IF_SUPPORTED(\n      {\n        absl::ScopedMockLog sink;\n        sink.StartCapturingLogs();\n        absl::AddLogSink(&sink.UseAsLocalSink());\n      },\n      HasSubstr(\"Duplicate log sinks\"));\n}\n\nTEST(LogSinkRegistrationDeathTest, MismatchSinkRemoval) {\n  ASSERT_DEATH_IF_SUPPORTED(\n      {\n        absl::ScopedMockLog sink;\n        absl::RemoveLogSink(&sink.UseAsLocalSink());\n      },\n      HasSubstr(\"Mismatched log sink\"));\n}\n\n// Tests for log sink semantic.\n// ---------------------------------------\n\nTEST(LogSinkTest, FlushSinks) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(test_sink, Flush()).Times(2);\n\n  test_sink.StartCapturingLogs();\n\n  absl::FlushLogSinks();\n  absl::FlushLogSinks();\n}\n\nTEST(LogSinkDeathTest, DeathInSend) {\n  class FatalSendSink : public absl::LogSink {\n   public:\n    void Send(const absl::LogEntry&) override { LOG(FATAL) << \"goodbye world\"; }\n  };\n\n  FatalSendSink sink;\n  EXPECT_EXIT({ LOG(INFO).ToSinkAlso(&sink) << \"hello world\"; }, DiedOfFatal,\n              _);\n}\n\n// Tests for explicit log sink redirection.\n// ---------------------------------------\n\nTEST(LogSinkTest, ToSinkAlso) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  absl::ScopedMockLog another_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Log(_, _, \"hello world\"));\n  EXPECT_CALL(another_sink, Log(_, _, \"hello world\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).ToSinkAlso(&another_sink.UseAsLocalSink()) << \"hello world\";\n}\n\nTEST(LogSinkTest, ToSinkOnly) {\n  absl::ScopedMockLog another_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(another_sink, Log(_, _, \"hello world\"));\n  LOG(INFO).ToSinkOnly(&another_sink.UseAsLocalSink()) << \"hello world\";\n}\n\nTEST(LogSinkTest, ToManySinks) {\n  absl::ScopedMockLog sink1(absl::MockLogDefault::kDisallowUnexpected);\n  absl::ScopedMockLog sink2(absl::MockLogDefault::kDisallowUnexpected);\n  absl::ScopedMockLog sink3(absl::MockLogDefault::kDisallowUnexpected);\n  absl::ScopedMockLog sink4(absl::MockLogDefault::kDisallowUnexpected);\n  absl::ScopedMockLog sink5(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(sink3, Log(_, _, \"hello world\"));\n  EXPECT_CALL(sink4, Log(_, _, \"hello world\"));\n  EXPECT_CALL(sink5, Log(_, _, \"hello world\"));\n\n  LOG(INFO)\n          .ToSinkAlso(&sink1.UseAsLocalSink())\n          .ToSinkAlso(&sink2.UseAsLocalSink())\n          .ToSinkOnly(&sink3.UseAsLocalSink())\n          .ToSinkAlso(&sink4.UseAsLocalSink())\n          .ToSinkAlso(&sink5.UseAsLocalSink())\n      << \"hello world\";\n}\n\nclass ReentrancyTest : public ::testing::Test {\n protected:\n  ReentrancyTest() = default;\n  enum class LogMode : int { kNormal, kToSinkAlso, kToSinkOnly };\n\n  class ReentrantSendLogSink : public absl::LogSink {\n   public:\n    explicit ReentrantSendLogSink(absl::LogSeverity severity,\n                                  absl::LogSink* sink, LogMode mode)\n        : severity_(severity), sink_(sink), mode_(mode) {}\n    explicit ReentrantSendLogSink(absl::LogSeverity severity)\n        : ReentrantSendLogSink(severity, nullptr, LogMode::kNormal) {}\n\n    void Send(const absl::LogEntry&) override {\n      switch (mode_) {\n        case LogMode::kNormal:\n          LOG(LEVEL(severity_)) << \"The log is coming from *inside the sink*.\";\n          break;\n        case LogMode::kToSinkAlso:\n          LOG(LEVEL(severity_)).ToSinkAlso(sink_)\n              << \"The log is coming from *inside the sink*.\";\n          break;\n        case LogMode::kToSinkOnly:\n          LOG(LEVEL(severity_)).ToSinkOnly(sink_)\n              << \"The log is coming from *inside the sink*.\";\n          break;\n        default:\n          LOG(FATAL) << \"Invalid mode \" << static_cast<int>(mode_);\n      }\n    }\n\n   private:\n    absl::LogSeverity severity_;\n    absl::LogSink* sink_;\n    LogMode mode_;\n  };\n\n  static absl::string_view LogAndReturn(absl::LogSeverity severity,\n                                        absl::string_view to_log,\n                                        absl::string_view to_return) {\n    LOG(LEVEL(severity)) << to_log;\n    return to_return;\n  }\n};\n\nTEST_F(ReentrancyTest, LogFunctionThatLogs) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n\n  InSequence seq;\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"hello\"));\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"world\"));\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, \"danger\"));\n  EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, \"here\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO) << LogAndReturn(absl::LogSeverity::kInfo, \"hello\", \"world\");\n  LOG(INFO) << LogAndReturn(absl::LogSeverity::kWarning, \"danger\", \"here\");\n}\n\nTEST_F(ReentrancyTest, RegisteredLogSinkThatLogsInSend) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  ReentrantSendLogSink renentrant_sink(absl::LogSeverity::kInfo);\n  EXPECT_CALL(test_sink, Log(_, _, \"hello world\"));\n\n  test_sink.StartCapturingLogs();\n  absl::AddLogSink(&renentrant_sink);\n  LOG(INFO) << \"hello world\";\n  absl::RemoveLogSink(&renentrant_sink);\n}\n\nTEST_F(ReentrancyTest, AlsoLogSinkThatLogsInSend) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);\n  EXPECT_CALL(test_sink, Log(_, _, \"hello world\"));\n  EXPECT_CALL(test_sink,\n              Log(_, _, \"The log is coming from *inside the sink*.\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).ToSinkAlso(&reentrant_sink) << \"hello world\";\n}\n\nTEST_F(ReentrancyTest, RegisteredAlsoLogSinkThatLogsInSend) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);\n  EXPECT_CALL(test_sink, Log(_, _, \"hello world\"));\n  // We only call into the test_log sink once with this message, since the\n  // second time log statement is run we are in \"ThreadIsLogging\" mode and all\n  // the log statements are redirected into stderr.\n  EXPECT_CALL(test_sink,\n              Log(_, _, \"The log is coming from *inside the sink*.\"));\n\n  test_sink.StartCapturingLogs();\n  absl::AddLogSink(&reentrant_sink);\n  LOG(INFO).ToSinkAlso(&reentrant_sink) << \"hello world\";\n  absl::RemoveLogSink(&reentrant_sink);\n}\n\nTEST_F(ReentrancyTest, OnlyLogSinkThatLogsInSend) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);\n  EXPECT_CALL(test_sink,\n              Log(_, _, \"The log is coming from *inside the sink*.\"));\n\n  test_sink.StartCapturingLogs();\n  LOG(INFO).ToSinkOnly(&reentrant_sink) << \"hello world\";\n}\n\nTEST_F(ReentrancyTest, RegisteredOnlyLogSinkThatLogsInSend) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kInfo);\n  EXPECT_CALL(test_sink,\n              Log(_, _, \"The log is coming from *inside the sink*.\"));\n\n  test_sink.StartCapturingLogs();\n  absl::AddLogSink(&reentrant_sink);\n  LOG(INFO).ToSinkOnly(&reentrant_sink) << \"hello world\";\n  absl::RemoveLogSink(&reentrant_sink);\n}\n\nusing ReentrancyDeathTest = ReentrancyTest;\n\nTEST_F(ReentrancyDeathTest, LogFunctionThatLogsFatal) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n\n        EXPECT_CALL(test_sink, Log)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n        EXPECT_CALL(test_sink, Log(_, _, \"hello\"))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        LOG(INFO) << LogAndReturn(absl::LogSeverity::kFatal, \"hello\", \"world\");\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\nTEST_F(ReentrancyDeathTest, RegisteredLogSinkThatLogsFatalInSend) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);\n        EXPECT_CALL(test_sink, Log)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n        EXPECT_CALL(test_sink, Log(_, _, \"hello world\"))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        absl::AddLogSink(&reentrant_sink);\n        LOG(INFO) << \"hello world\";\n        // No need to call RemoveLogSink - process is dead at this point.\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\nTEST_F(ReentrancyDeathTest, AlsoLogSinkThatLogsFatalInSend) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);\n\n        EXPECT_CALL(test_sink, Log)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n        EXPECT_CALL(test_sink, Log(_, _, \"hello world\"))\n            .WillOnce(DeathTestExpectedLogging());\n        EXPECT_CALL(test_sink,\n                    Log(_, _, \"The log is coming from *inside the sink*.\"))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        LOG(INFO).ToSinkAlso(&reentrant_sink) << \"hello world\";\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\nTEST_F(ReentrancyDeathTest, RegisteredAlsoLogSinkThatLogsFatalInSend) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);\n        EXPECT_CALL(test_sink, Log)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n        EXPECT_CALL(test_sink, Log(_, _, \"hello world\"))\n            .WillOnce(DeathTestExpectedLogging());\n        EXPECT_CALL(test_sink,\n                    Log(_, _, \"The log is coming from *inside the sink*.\"))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        absl::AddLogSink(&reentrant_sink);\n        LOG(INFO).ToSinkAlso(&reentrant_sink) << \"hello world\";\n        // No need to call RemoveLogSink - process is dead at this point.\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\nTEST_F(ReentrancyDeathTest, OnlyLogSinkThatLogsFatalInSend) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);\n        EXPECT_CALL(test_sink, Log)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n        EXPECT_CALL(test_sink,\n                    Log(_, _, \"The log is coming from *inside the sink*.\"))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        LOG(INFO).ToSinkOnly(&reentrant_sink) << \"hello world\";\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\nTEST_F(ReentrancyDeathTest, RegisteredOnlyLogSinkThatLogsFatalInSend) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        ReentrantSendLogSink reentrant_sink(absl::LogSeverity::kFatal);\n        EXPECT_CALL(test_sink, Log)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n        EXPECT_CALL(test_sink,\n                    Log(_, _, \"The log is coming from *inside the sink*.\"))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        absl::AddLogSink(&reentrant_sink);\n        LOG(INFO).ToSinkOnly(&reentrant_sink) << \"hello world\";\n        // No need to call RemoveLogSink - process is dead at this point.\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/log_streamer.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/log_streamer.h\n// -----------------------------------------------------------------------------\n//\n// This header declares the class `LogStreamer` and convenience functions to\n// construct LogStreamer objects with different associated log severity levels.\n\n#ifndef ABSL_LOG_LOG_STREAMER_H_\n#define ABSL_LOG_LOG_STREAMER_H_\n\n#include <ios>\n#include <memory>\n#include <optional>\n#include <ostream>\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/absl_log.h\"\n#include \"absl/strings/internal/ostringstream.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// LogStreamer\n//\n// Although you can stream into `LOG(INFO)`, you can't pass it into a function\n// that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a\n// `std::ostream` that buffers everything that's streamed in.  The buffer's\n// contents are logged as if by `LOG` when the `LogStreamer` is destroyed.\n// If nothing is streamed in, an empty message is logged.  If the specified\n// severity is `absl::LogSeverity::kFatal`, the program will be terminated when\n// the `LogStreamer` is destroyed regardless of whether any data were streamed\n// in.\n//\n// Factory functions corresponding to the `absl::LogSeverity` enumerators\n// are provided for convenience; if the desired severity is variable, invoke the\n// constructor directly.\n//\n// LogStreamer is movable, but not copyable.\n//\n// Examples:\n//\n//   ShaveYakAndWriteToStream(\n//       yak, absl::LogInfoStreamer(__FILE__, __LINE__).stream());\n//\n//   {\n//     // This logs a single line containing data streamed by all three function\n//     // calls.\n//     absl::LogStreamer streamer(absl::LogSeverity::kInfo, __FILE__, __LINE__);\n//     ShaveYakAndWriteToStream(yak1, streamer.stream());\n//     streamer.stream() << \" \";\n//     ShaveYakAndWriteToStream(yak2, streamer.stream());\n//     streamer.stream() << \" \";\n//     ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());\n//   }\nclass LogStreamer final {\n public:\n  // LogStreamer::LogStreamer()\n  //\n  // Creates a LogStreamer with a given `severity` that will log a message\n  // attributed to the given `file` and `line`.\n  explicit LogStreamer(absl::LogSeverity severity, absl::string_view file,\n                       int line)\n      : severity_(severity),\n        line_(line),\n        file_(file),\n        stream_(absl::in_place, &buf_) {\n    // To match `LOG`'s defaults:\n    stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);\n  }\n  explicit LogStreamer(\n      absl::LogSeverity severity,\n      absl::SourceLocation loc = absl::SourceLocation::current())\n      : LogStreamer(severity, loc.file_name(), static_cast<int>(loc.line())) {}\n\n  // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,\n  // and a program that streams into one has undefined behavior.\n  LogStreamer(LogStreamer&& that) noexcept\n      : severity_(that.severity_),\n        line_(that.line_),\n        file_(std::move(that.file_)),\n        buf_(std::move(that.buf_)),\n        stream_(std::move(that.stream_)) {\n    if (stream_.has_value()) stream_->str(&buf_);\n    that.stream_.reset();\n  }\n  LogStreamer& operator=(LogStreamer&& that) {\n    ABSL_LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;\n    severity_ = that.severity_;\n    file_ = std::move(that.file_);\n    line_ = that.line_;\n    buf_ = std::move(that.buf_);\n    stream_ = std::move(that.stream_);\n    if (stream_.has_value()) stream_->str(&buf_);\n    that.stream_.reset();\n    return *this;\n  }\n\n  // LogStreamer::~LogStreamer()\n  //\n  // Logs this LogStreamer's buffered content as if by LOG.\n  ~LogStreamer() {\n    ABSL_LOG_IF(LEVEL(severity_), stream_.has_value()).AtLocation(file_, line_)\n        << buf_;\n  }\n\n  // LogStreamer::stream()\n  //\n  // Returns the `std::ostream` to use to write into this LogStreamer' internal\n  // buffer.\n  std::ostream& stream() { return *stream_; }\n\n private:\n  absl::LogSeverity severity_;\n  int line_;\n  std::string file_;\n  std::string buf_;\n  // A disengaged `stream_` indicates a moved-from `LogStreamer` that should not\n  // `LOG` upon destruction.\n  std::optional<absl::strings_internal::OStringStream> stream_;\n};\n\n// LogInfoStreamer()\n//\n// Returns a LogStreamer that writes at level LogSeverity::kInfo.\ninline LogStreamer LogInfoStreamer(absl::string_view file, int line) {\n  return absl::LogStreamer(absl::LogSeverity::kInfo, file, line);\n}\n\n// LogWarningStreamer()\n//\n// Returns a LogStreamer that writes at level LogSeverity::kWarning.\ninline LogStreamer LogWarningStreamer(absl::string_view file, int line) {\n  return absl::LogStreamer(absl::LogSeverity::kWarning, file, line);\n}\n\n// LogErrorStreamer()\n//\n// Returns a LogStreamer that writes at level LogSeverity::kError.\ninline LogStreamer LogErrorStreamer(absl::string_view file, int line) {\n  return absl::LogStreamer(absl::LogSeverity::kError, file, line);\n}\n\n// LogFatalStreamer()\n//\n// Returns a LogStreamer that writes at level LogSeverity::kFatal.\n//\n// The program will be terminated when this `LogStreamer` is destroyed,\n// regardless of whether any data were streamed in.\ninline LogStreamer LogFatalStreamer(absl::string_view file, int line) {\n  return absl::LogStreamer(absl::LogSeverity::kFatal, file, line);\n}\n\n// LogDebugFatalStreamer()\n//\n// Returns a LogStreamer that writes at level LogSeverity::kLogDebugFatal.\n//\n// In debug mode, the program will be terminated when this `LogStreamer` is\n// destroyed, regardless of whether any data were streamed in.\ninline LogStreamer LogDebugFatalStreamer(absl::string_view file, int line) {\n  return absl::LogStreamer(absl::kLogDebugFatal, file, line);\n}\n\ninline LogStreamer LogInfoStreamer(\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  return absl::LogStreamer(absl::LogSeverity::kInfo, loc);\n}\ninline LogStreamer LogWarningStreamer(\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  return absl::LogStreamer(absl::LogSeverity::kWarning, loc);\n}\ninline LogStreamer LogErrorStreamer(\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  return absl::LogStreamer(absl::LogSeverity::kError, loc);\n}\ninline LogStreamer LogFatalStreamer(\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  return absl::LogStreamer(absl::LogSeverity::kFatal, loc);\n}\ninline LogStreamer LogDebugFatalStreamer(\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  return absl::LogStreamer(absl::kLogDebugFatal, loc);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_LOG_STREAMER_H_\n"
  },
  {
    "path": "absl/log/log_streamer_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/log_streamer.h\"\n\n#include <ios>\n#include <iostream>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/internal/test_actions.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/source_location.h\"\n\nnamespace {\nusing ::absl::log_internal::DeathTestExpectedLogging;\nusing ::absl::log_internal::DeathTestUnexpectedLogging;\nusing ::absl::log_internal::DeathTestValidateExpectations;\n#if GTEST_HAS_DEATH_TEST\nusing ::absl::log_internal::DiedOfFatal;\n#endif\nusing ::absl::log_internal::InMatchWindow;\nusing ::absl::log_internal::LogSeverity;\nusing ::absl::log_internal::Prefix;\nusing ::absl::log_internal::SourceFilename;\nusing ::absl::log_internal::SourceLine;\nusing ::absl::log_internal::Stacktrace;\nusing ::absl::log_internal::TextMessage;\nusing ::absl::log_internal::ThreadID;\nusing ::absl::log_internal::Timestamp;\nusing ::testing::_;\nusing ::testing::AnyNumber;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing ::testing::IsEmpty;\nusing ::testing::IsTrue;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\nvoid WriteToStream(absl::string_view data, std::ostream* os) {\n  *os << \"WriteToStream: \" << data;\n}\nvoid WriteToStreamRef(absl::string_view data, std::ostream& os) {\n  os << \"WriteToStreamRef: \" << data;\n}\n\nTEST(LogStreamerTest, LogInfoStreamer) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(\n          AllOf(SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kInfo)),\n                Timestamp(InMatchWindow()),\n                ThreadID(Eq(absl::base_internal::GetTID())),\n                TextMessage(Eq(\"WriteToStream: foo\")),\n                ENCODED_MESSAGE(MatchesEvent(\n                    Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n                    Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()),\n                    ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))),\n                Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  WriteToStream(\"foo\", &absl::LogInfoStreamer(\"path/file.cc\", 1234).stream());\n}\n\nTEST(LogStreamerTest, LogWarningStreamer) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n          Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kWarning)),\n          Timestamp(InMatchWindow()),\n          ThreadID(Eq(absl::base_internal::GetTID())),\n          TextMessage(Eq(\"WriteToStream: foo\")),\n          ENCODED_MESSAGE(MatchesEvent(\n              Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n              Eq(logging::proto::WARNING), Eq(absl::base_internal::GetTID()),\n              ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))),\n          Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  WriteToStream(\"foo\",\n                &absl::LogWarningStreamer(\"path/file.cc\", 1234).stream());\n}\n\nTEST(LogStreamerTest, LogErrorStreamer) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n          Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),\n          Timestamp(InMatchWindow()),\n          ThreadID(Eq(absl::base_internal::GetTID())),\n          TextMessage(Eq(\"WriteToStream: foo\")),\n          ENCODED_MESSAGE(MatchesEvent(\n              Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n              Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),\n              ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))),\n          Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  WriteToStream(\"foo\", &absl::LogErrorStreamer(\"path/file.cc\", 1234).stream());\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(LogStreamerDeathTest, LogFatalStreamer) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        EXPECT_CALL(\n            test_sink,\n            Send(AllOf(\n                SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                Timestamp(InMatchWindow()),\n                ThreadID(Eq(absl::base_internal::GetTID())),\n                TextMessage(Eq(\"WriteToStream: foo\")),\n                ENCODED_MESSAGE(MatchesEvent(\n                    Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n                    Eq(logging::proto::FATAL),\n                    Eq(absl::base_internal::GetTID()),\n                    ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))))))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        WriteToStream(\"foo\",\n                      &absl::LogFatalStreamer(\"path/file.cc\", 1234).stream());\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n#endif\n\n#ifdef NDEBUG\nTEST(LogStreamerTest, LogDebugFatalStreamer) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n          Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),\n          Timestamp(InMatchWindow()),\n          ThreadID(Eq(absl::base_internal::GetTID())),\n          TextMessage(Eq(\"WriteToStream: foo\")),\n          ENCODED_MESSAGE(MatchesEvent(\n              Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n              Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),\n              ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))),\n          Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  WriteToStream(\"foo\",\n                &absl::LogDebugFatalStreamer(\"path/file.cc\", 1234).stream());\n}\n#elif GTEST_HAS_DEATH_TEST\nTEST(LogStreamerDeathTest, LogDebugFatalStreamer) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        EXPECT_CALL(\n            test_sink,\n            Send(AllOf(\n                SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                Timestamp(InMatchWindow()),\n                ThreadID(Eq(absl::base_internal::GetTID())),\n                TextMessage(Eq(\"WriteToStream: foo\")),\n                ENCODED_MESSAGE(MatchesEvent(\n                    Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n                    Eq(logging::proto::FATAL),\n                    Eq(absl::base_internal::GetTID()),\n                    ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))))))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        WriteToStream(\n            \"foo\", &absl::LogDebugFatalStreamer(\"path/file.cc\", 1234).stream());\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n#endif\n\nTEST(LogStreamerTest, LogStreamer) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n          Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),\n          Timestamp(InMatchWindow()),\n          ThreadID(Eq(absl::base_internal::GetTID())),\n          TextMessage(Eq(\"WriteToStream: foo\")),\n          ENCODED_MESSAGE(MatchesEvent(\n              Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n              Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),\n              ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))),\n          Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  WriteToStream(\n      \"foo\", &absl::LogStreamer(absl::LogSeverity::kError, \"path/file.cc\", 1234)\n                  .stream());\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(LogStreamerDeathTest, LogStreamer) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        EXPECT_CALL(test_sink, Send).Times(0);\n\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        EXPECT_CALL(\n            test_sink,\n            Send(AllOf(\n                SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),\n                Timestamp(InMatchWindow()),\n                ThreadID(Eq(absl::base_internal::GetTID())),\n                TextMessage(Eq(\"WriteToStream: foo\")),\n                ENCODED_MESSAGE(MatchesEvent(\n                    Eq(\"path/file.cc\"), Eq(1234), InMatchWindow(),\n                    Eq(logging::proto::FATAL),\n                    Eq(absl::base_internal::GetTID()),\n                    ElementsAre(ValueWithStr(Eq(\"WriteToStream: foo\"))))))))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        WriteToStream(\"foo\", &absl::LogStreamer(absl::LogSeverity::kFatal,\n                                                \"path/file.cc\", 1234)\n                                  .stream());\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n#endif\n\nTEST(LogStreamerTest, PassedByReference) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                 TextMessage(Eq(\"WriteToStreamRef: foo\")),\n                 ENCODED_MESSAGE(MatchesEvent(\n                     Eq(\"path/file.cc\"), Eq(1234), _, _, _,\n                     ElementsAre(ValueWithStr(Eq(\"WriteToStreamRef: foo\"))))),\n                 Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  WriteToStreamRef(\"foo\", absl::LogInfoStreamer(\"path/file.cc\", 1234).stream());\n}\n\nTEST(LogStreamerTest, StoredAsLocal) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  auto streamer = absl::LogInfoStreamer(\"path/file.cc\", 1234);\n  WriteToStream(\"foo\", &streamer.stream());\n  streamer.stream() << \" \";\n  WriteToStreamRef(\"bar\", streamer.stream());\n\n  // The call should happen when `streamer` goes out of scope; if it\n  // happened before this `EXPECT_CALL` the call would be unexpected and the\n  // test would fail.\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                 TextMessage(Eq(\"WriteToStream: foo WriteToStreamRef: bar\")),\n                 ENCODED_MESSAGE(MatchesEvent(\n                     Eq(\"path/file.cc\"), Eq(1234), _, _, _,\n                     ElementsAre(ValueWithStr(\n                         Eq(\"WriteToStream: foo WriteToStreamRef: bar\"))))),\n                 Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(LogStreamerDeathTest, StoredAsLocal) {\n  EXPECT_EXIT(\n      {\n        // This is fatal when it goes out of scope, but not until then:\n        auto streamer = absl::LogFatalStreamer(\"path/file.cc\", 1234);\n        std::cerr << \"I'm still alive\" << std::endl;\n        WriteToStream(\"foo\", &streamer.stream());\n      },\n      DiedOfFatal, HasSubstr(\"I'm still alive\"));\n}\n#endif\n\nTEST(LogStreamerTest, LogsEmptyLine) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink, Send(AllOf(SourceFilename(Eq(\"path/file.cc\")),\n                                    SourceLine(Eq(1234)), TextMessage(Eq(\"\")),\n                                    ENCODED_MESSAGE(MatchesEvent(\n                                        Eq(\"path/file.cc\"), Eq(1234), _, _, _,\n                                        ElementsAre(ValueWithStr(Eq(\"\"))))),\n                                    Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  absl::LogInfoStreamer(\"path/file.cc\", 1234);\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(LogStreamerDeathTest, LogsEmptyLine) {\n  EXPECT_EXIT(\n      {\n        absl::ScopedMockLog test_sink;\n        EXPECT_CALL(test_sink, Send)\n            .Times(AnyNumber())\n            .WillRepeatedly(DeathTestUnexpectedLogging());\n\n        EXPECT_CALL(\n            test_sink,\n            Send(AllOf(SourceFilename(Eq(\"path/file.cc\")), TextMessage(Eq(\"\")),\n                       ENCODED_MESSAGE(\n                           MatchesEvent(Eq(\"path/file.cc\"), _, _, _, _,\n                                        ElementsAre(ValueWithStr(Eq(\"\"))))))))\n            .WillOnce(DeathTestExpectedLogging());\n\n        test_sink.StartCapturingLogs();\n        // This is fatal even though it's never used:\n        auto streamer = absl::LogFatalStreamer(\"path/file.cc\", 1234);\n      },\n      DiedOfFatal, DeathTestValidateExpectations());\n}\n#endif\n\nTEST(LogStreamerTest, MoveConstruction) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(\n      test_sink,\n      Send(\n          AllOf(SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                LogSeverity(Eq(absl::LogSeverity::kInfo)),\n                TextMessage(Eq(\"hello 0x10 world 0x10\")),\n                ENCODED_MESSAGE(MatchesEvent(\n                    Eq(\"path/file.cc\"), Eq(1234), _, Eq(logging::proto::INFO),\n                    _, ElementsAre(ValueWithStr(Eq(\"hello 0x10 world 0x10\"))))),\n                Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  auto streamer1 = absl::LogInfoStreamer(\"path/file.cc\", 1234);\n  streamer1.stream() << \"hello \" << std::hex << 16;\n  absl::LogStreamer streamer2(std::move(streamer1));\n  streamer2.stream() << \" world \" << 16;\n}\n\nTEST(LogStreamerTest, MoveAssignment) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  testing::InSequence seq;\n  EXPECT_CALL(\n      test_sink,\n      Send(AllOf(\n          SourceFilename(Eq(\"path/file2.cc\")), SourceLine(Eq(5678)),\n          LogSeverity(Eq(absl::LogSeverity::kWarning)),\n          TextMessage(Eq(\"something else\")),\n          ENCODED_MESSAGE(MatchesEvent(\n              Eq(\"path/file2.cc\"), Eq(5678), _, Eq(logging::proto::WARNING), _,\n              ElementsAre(ValueWithStr(Eq(\"something else\"))))),\n          Stacktrace(IsEmpty()))));\n  EXPECT_CALL(\n      test_sink,\n      Send(\n          AllOf(SourceFilename(Eq(\"path/file.cc\")), SourceLine(Eq(1234)),\n                LogSeverity(Eq(absl::LogSeverity::kInfo)),\n                TextMessage(Eq(\"hello 0x10 world 0x10\")),\n                ENCODED_MESSAGE(MatchesEvent(\n                    Eq(\"path/file.cc\"), Eq(1234), _, Eq(logging::proto::INFO),\n                    _, ElementsAre(ValueWithStr(Eq(\"hello 0x10 world 0x10\"))))),\n                Stacktrace(IsEmpty()))));\n\n  test_sink.StartCapturingLogs();\n  auto streamer1 = absl::LogInfoStreamer(\"path/file.cc\", 1234);\n  streamer1.stream() << \"hello \" << std::hex << 16;\n  auto streamer2 = absl::LogWarningStreamer(\"path/file2.cc\", 5678);\n  streamer2.stream() << \"something else\";\n  streamer2 = std::move(streamer1);\n  streamer2.stream() << \" world \" << 16;\n}\n\nTEST(LogStreamerTest, CorrectDefaultFlags) {\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  // The `boolalpha` and `showbase` flags should be set by default, to match\n  // `LOG`.\n  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(\"false0xdeadbeef\")))))\n      .Times(2);\n\n  test_sink.StartCapturingLogs();\n  absl::LogInfoStreamer(\"path/file.cc\", 1234).stream()\n      << false << std::hex << 0xdeadbeef;\n  LOG(INFO) << false << std::hex << 0xdeadbeef;\n}\n\nTEST(LogStreamerTest, AtSourceLocation) {\n  const int log_line = __LINE__ + 2;\n  auto do_log = [] {\n    WriteToStream(\"foo\", &absl::LogInfoStreamer().stream());  //\n  };\n  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);\n  EXPECT_CALL(test_sink, Send).Times(0);\n\n  EXPECT_CALL(test_sink,\n              Send(AllOf(SourceFilename(\n                             Eq(absl::SourceLocation::current().file_name())),\n                         SourceLine(Eq(log_line)))));\n\n  test_sink.StartCapturingLogs();\n  do_log();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/scoped_mock_log.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/scoped_mock_log.h\"\n\n#include <atomic>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n#include \"absl/log/log_sink_registry.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nScopedMockLog::ScopedMockLog(MockLogDefault default_exp)\n    : sink_(this), is_capturing_logs_(false), is_triggered_(false) {\n  if (default_exp == MockLogDefault::kIgnoreUnexpected) {\n    // Ignore all calls to Log we did not set expectations for.\n    EXPECT_CALL(*this, Log).Times(::testing::AnyNumber());\n  } else {\n    // Disallow all calls to Log we did not set expectations for.\n    EXPECT_CALL(*this, Log).Times(0);\n  }\n  // By default Send mock forwards to Log mock.\n  EXPECT_CALL(*this, Send)\n      .Times(::testing::AnyNumber())\n      .WillRepeatedly([this](const absl::LogEntry& entry) {\n        is_triggered_.store(true, std::memory_order_relaxed);\n        Log(entry.log_severity(), std::string(entry.source_filename()),\n            std::string(entry.text_message()));\n      });\n\n  // By default We ignore all Flush calls.\n  EXPECT_CALL(*this, Flush).Times(::testing::AnyNumber());\n}\n\nScopedMockLog::~ScopedMockLog() {\n  ABSL_RAW_CHECK(is_triggered_.load(std::memory_order_relaxed),\n                 \"Did you forget to call StartCapturingLogs()?\");\n\n  if (is_capturing_logs_) StopCapturingLogs();\n}\n\nvoid ScopedMockLog::StartCapturingLogs() {\n  ABSL_RAW_CHECK(!is_capturing_logs_,\n                 \"StartCapturingLogs() can be called only when the \"\n                 \"absl::ScopedMockLog object is not capturing logs.\");\n\n  is_capturing_logs_ = true;\n  is_triggered_.store(true, std::memory_order_relaxed);\n  absl::AddLogSink(&sink_);\n}\n\nvoid ScopedMockLog::StopCapturingLogs() {\n  ABSL_RAW_CHECK(is_capturing_logs_,\n                 \"StopCapturingLogs() can be called only when the \"\n                 \"absl::ScopedMockLog object is capturing logs.\");\n\n  is_capturing_logs_ = false;\n  absl::RemoveLogSink(&sink_);\n}\n\nabsl::LogSink& ScopedMockLog::UseAsLocalSink() {\n  is_triggered_.store(true, std::memory_order_relaxed);\n  return sink_;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/log/scoped_mock_log.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/scoped_mock_log.h\n// -----------------------------------------------------------------------------\n//\n// This header declares `class absl::ScopedMockLog`, for use in testing.\n\n#ifndef ABSL_LOG_SCOPED_MOCK_LOG_H_\n#define ABSL_LOG_SCOPED_MOCK_LOG_H_\n\n#include <atomic>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/log_entry.h\"\n#include \"absl/log/log_sink.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// MockLogDefault\n//\n// Controls how ScopedMockLog responds to unexpected calls by default.\nenum class MockLogDefault { kIgnoreUnexpected, kDisallowUnexpected };\n\n// ScopedMockLog\n//\n// ScopedMockLog is a LogSink that intercepts LOG() messages issued by all\n// threads when active.\n//\n// Using this together with GoogleTest, it's easy to test how a piece of code\n// calls LOG(). The typical usage, noting the distinction between\n// \"uninteresting\" and \"unexpected\", looks like this:\n//\n//   using ::testing::_;\n//   using ::testing::AnyNumber;\n//   using ::testing::EndsWith;\n//   using ::testing::kDoNotCaptureLogsYet;\n//   using ::testing::Lt;\n//\n//   TEST(FooTest, LogsCorrectly) {\n//     // Simple robust setup, ignores unexpected logs.\n//     absl::ScopedMockLog log;\n//\n//     // We expect the WARNING \"Something bad!\" exactly twice.\n//     EXPECT_CALL(log, Log(absl::LogSeverity::kWarning, _, \"Something bad!\"))\n//         .Times(2);\n//\n//     // But we want no messages from foo.cc.\n//     EXPECT_CALL(log, Log(_, EndsWith(\"/foo.cc\"), _)).Times(0);\n//\n//     log.StartCapturingLogs();  // Call this after done setting expectations.\n//     Foo();  // Exercises the code under test.\n//   }\n//\n//   TEST(BarTest, LogsExactlyCorrectly) {\n//     // Strict checking, fails for unexpected logs.\n//     absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n//\n//     // ... but ignore low severity messages\n//     EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kWarning), _, _))\n//         .Times(AnyNumber());\n//\n//     // We expect the ERROR \"Something bad!\" exactly once.\n//     EXPECT_CALL(log, Log(absl::LogSeverity::kError, EndsWith(\"/foo.cc\"),\n//                 \"Something bad!\"))\n//         .Times(1);\n//\n//     log.StartCapturingLogs();  // Call this after done setting expectations.\n//     Bar();  // Exercises the code under test.\n//    }\n//\n// Note that in a multi-threaded environment, all LOG() messages from a single\n// thread will be handled in sequence, but that cannot be guaranteed for\n// messages from different threads. In fact, if the same or multiple\n// expectations are matched on two threads concurrently, their actions will be\n// executed concurrently as well and may interleave.\nclass ScopedMockLog final {\n public:\n  // ScopedMockLog::ScopedMockLog()\n  //\n  // Sets up the log and adds default expectations.\n  explicit ScopedMockLog(\n      MockLogDefault default_exp = MockLogDefault::kIgnoreUnexpected);\n  ScopedMockLog(const ScopedMockLog&) = delete;\n  ScopedMockLog& operator=(const ScopedMockLog&) = delete;\n\n  // ScopedMockLog::~ScopedMockLog()\n  //\n  // Stops intercepting logs and destroys this ScopedMockLog.\n  ~ScopedMockLog();\n\n  // ScopedMockLog::StartCapturingLogs()\n  //\n  // Starts log capturing if the object isn't already doing so. Otherwise\n  // crashes.\n  //\n  // Usually this method is called in the same thread that created this\n  // ScopedMockLog. It is the user's responsibility to not call this method if\n  // another thread may be calling it or StopCapturingLogs() at the same time.\n  // It is undefined behavior to add expectations while capturing logs is\n  // enabled.\n  void StartCapturingLogs();\n\n  // ScopedMockLog::StopCapturingLogs()\n  //\n  // Stops log capturing if the object is capturing logs. Otherwise crashes.\n  //\n  // Usually this method is called in the same thread that created this object.\n  // It is the user's responsibility to not call this method if another thread\n  // may be calling it or StartCapturingLogs() at the same time.\n  //\n  // It is UB to add expectations, while capturing logs is enabled.\n  void StopCapturingLogs();\n\n  // ScopedMockLog::UseAsLocalSink()\n  //\n  // Each `ScopedMockLog` is implemented with an `absl::LogSink`; this method\n  // returns a reference to that sink (e.g. for use with\n  // `LOG(...).ToSinkOnly()`) and marks the `ScopedMockLog` as having been used\n  // even if `StartCapturingLogs` is never called.\n  absl::LogSink& UseAsLocalSink();\n\n  // Implements the mock method:\n  //\n  //   void Log(LogSeverity severity, absl::string_view file_path,\n  //            absl::string_view message);\n  //\n  // The second argument to Log() is the full path of the source file in\n  // which the LOG() was issued.\n  //\n  // This is a shorthand form, which should be used by most users. Use the\n  // `Send` mock only if you want to add expectations for other log message\n  // attributes.\n  MOCK_METHOD(void, Log,\n              (absl::LogSeverity severity, const std::string& file_path,\n               const std::string& message));\n\n  // Implements the mock method:\n  //\n  //   void Send(const absl::LogEntry& entry);\n  //\n  // This is the most generic form of mock that can be specified. Use this mock\n  // only if you want to add expectations for log message attributes different\n  // from the log message text, log message path and log message severity.\n  //\n  // If no expectations are specified for this mock, the default action is to\n  // forward the call to the `Log` mock.  Tests using `Send` are advised to call\n  //\n  //   `EXPECT_CALL(sink, Send).Times(0);`\n  //\n  // prior to specifying other expectations to suppress forwarding to `Log`.\n  // That way, unexpected calls show up as calls to `Send` with complete data\n  // and metadata for easier debugging.\n  MOCK_METHOD(void, Send, (const absl::LogEntry&));\n\n  // Implements the mock method:\n  //\n  //   void Flush();\n  //\n  // Use this mock only if you want to add expectations for log flush calls.\n  MOCK_METHOD(void, Flush, ());\n\n private:\n  class ForwardingSink final : public absl::LogSink {\n   public:\n    explicit ForwardingSink(ScopedMockLog* sml) : sml_(sml) {}\n    ForwardingSink(const ForwardingSink&) = delete;\n    ForwardingSink& operator=(const ForwardingSink&) = delete;\n    void Send(const absl::LogEntry& entry) override { sml_->Send(entry); }\n    void Flush() override { sml_->Flush(); }\n\n   private:\n    ScopedMockLog* sml_;\n  };\n\n  ForwardingSink sink_;\n  bool is_capturing_logs_;\n  // Until C++20, the default constructor leaves the underlying value wrapped in\n  // std::atomic uninitialized, so all constructors should be sure to initialize\n  // is_triggered_.\n  std::atomic<bool> is_triggered_;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_SCOPED_MOCK_LOG_H_\n"
  },
  {
    "path": "absl/log/scoped_mock_log_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/scoped_mock_log.h\"\n\n#include <memory>\n#include <thread>  // NOLINT(build/c++11)\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest-spi.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/synchronization/barrier.h\"\n#include \"absl/synchronization/notification.h\"\n\nnamespace {\n\nusing ::testing::_;\nusing ::testing::AnyNumber;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing ::testing::InSequence;\nusing ::testing::Lt;\nusing ::testing::Truly;\nusing absl::log_internal::SourceBasename;\nusing absl::log_internal::SourceFilename;\nusing absl::log_internal::SourceLine;\nusing absl::log_internal::TextMessageWithPrefix;\nusing absl::log_internal::ThreadID;\n\nauto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\n#if GTEST_HAS_DEATH_TEST\nTEST(ScopedMockLogDeathTest,\n     StartCapturingLogsCannotBeCalledWhenAlreadyCapturing) {\n  EXPECT_DEATH(\n      {\n        absl::ScopedMockLog log;\n        log.StartCapturingLogs();\n        log.StartCapturingLogs();\n      },\n      \"StartCapturingLogs\");\n}\n\nTEST(ScopedMockLogDeathTest, StopCapturingLogsCannotBeCalledWhenNotCapturing) {\n  EXPECT_DEATH(\n      {\n        absl::ScopedMockLog log;\n        log.StopCapturingLogs();\n      },\n      \"StopCapturingLogs\");\n}\n\nTEST(ScopedMockLogDeathTest, FailsCheckIfStartCapturingLogsIsNeverCalled) {\n  EXPECT_DEATH({ absl::ScopedMockLog log; },\n               \"Did you forget to call StartCapturingLogs\");\n}\n#endif\n\n// Tests that ScopedMockLog intercepts LOG()s when it's alive.\nTEST(ScopedMockLogTest, LogMockCatchAndMatchStrictExpectations) {\n  absl::ScopedMockLog log;\n\n  // The following expectations must match in the order they appear.\n  InSequence s;\n  EXPECT_CALL(log,\n              Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), \"Danger.\"));\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"Working...\")).Times(2);\n  EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, \"Bad!!\"));\n\n  log.StartCapturingLogs();\n  LOG(WARNING) << \"Danger.\";\n  LOG(INFO) << \"Working...\";\n  LOG(INFO) << \"Working...\";\n  LOG(ERROR) << \"Bad!!\";\n}\n\nTEST(ScopedMockLogTest, LogMockCatchAndMatchSendExpectations) {\n  absl::ScopedMockLog log;\n\n  EXPECT_CALL(\n      log,\n      Send(AllOf(SourceFilename(Eq(\"/my/very/very/very_long_source_file.cc\")),\n                 SourceBasename(Eq(\"very_long_source_file.cc\")),\n                 SourceLine(Eq(777)), ThreadID(Eq(absl::LogEntry::tid_t{1234})),\n                 TextMessageWithPrefix(Truly([](absl::string_view msg) {\n                   return absl::EndsWith(\n                       msg, \" very_long_source_file.cc:777] Info message\");\n                 })))));\n\n  log.StartCapturingLogs();\n  LOG(INFO)\n          .AtLocation(\"/my/very/very/very_long_source_file.cc\", 777)\n          .WithThreadID(1234)\n      << \"Info message\";\n}\n\nTEST(ScopedMockLogTest, ScopedMockLogCanBeNice) {\n  absl::ScopedMockLog log;\n\n  InSequence s;\n  EXPECT_CALL(log,\n              Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), \"Danger.\"));\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"Working...\")).Times(2);\n  EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, \"Bad!!\"));\n\n  log.StartCapturingLogs();\n\n  // Any number of these are OK.\n  LOG(INFO) << \"Info message.\";\n  // Any number of these are OK.\n  LOG(WARNING).AtLocation(\"SomeOtherFile.cc\", 100) << \"Danger \";\n\n  LOG(WARNING) << \"Danger.\";\n\n  // Any number of these are OK.\n  LOG(INFO) << \"Info message.\";\n  // Any number of these are OK.\n  LOG(WARNING).AtLocation(\"SomeOtherFile.cc\", 100) << \"Danger \";\n\n  LOG(INFO) << \"Working...\";\n\n  // Any number of these are OK.\n  LOG(INFO) << \"Info message.\";\n  // Any number of these are OK.\n  LOG(WARNING).AtLocation(\"SomeOtherFile.cc\", 100) << \"Danger \";\n\n  LOG(INFO) << \"Working...\";\n\n  // Any number of these are OK.\n  LOG(INFO) << \"Info message.\";\n  // Any number of these are OK.\n  LOG(WARNING).AtLocation(\"SomeOtherFile.cc\", 100) << \"Danger \";\n\n  LOG(ERROR) << \"Bad!!\";\n\n  // Any number of these are OK.\n  LOG(INFO) << \"Info message.\";\n  // Any number of these are OK.\n  LOG(WARNING).AtLocation(\"SomeOtherFile.cc\", 100) << \"Danger \";\n}\n\n// Tests that ScopedMockLog generates a test failure if a message is logged\n// that is not expected (here, that means ERROR or FATAL).\nTEST(ScopedMockLogTest, RejectsUnexpectedLogs) {\n  EXPECT_NONFATAL_FAILURE(\n      {\n        absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n        // Any INFO and WARNING messages are permitted.\n        EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kError), _, _))\n            .Times(AnyNumber());\n        log.StartCapturingLogs();\n        LOG(INFO) << \"Ignored\";\n        LOG(WARNING) << \"Ignored\";\n        LOG(ERROR) << \"Should not be ignored\";\n      },\n      \"Should not be ignored\");\n}\n\nTEST(ScopedMockLogTest, CapturesLogsAfterStartCapturingLogs) {\n  absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfinity);\n  absl::ScopedMockLog log;\n\n  // The ScopedMockLog object shouldn't see these LOGs, as it hasn't\n  // started capturing LOGs yet.\n  LOG(INFO) << \"Ignored info\";\n  LOG(WARNING) << \"Ignored warning\";\n  LOG(ERROR) << \"Ignored error\";\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"Expected info\"));\n  log.StartCapturingLogs();\n\n  // Only this LOG will be seen by the ScopedMockLog.\n  LOG(INFO) << \"Expected info\";\n}\n\nTEST(ScopedMockLogTest, DoesNotCaptureLogsAfterStopCapturingLogs) {\n  absl::ScopedMockLog log;\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"Expected info\"));\n\n  log.StartCapturingLogs();\n\n  // This LOG should be seen by the ScopedMockLog.\n  LOG(INFO) << \"Expected info\";\n\n  log.StopCapturingLogs();\n\n  // The ScopedMockLog object shouldn't see these LOGs, as it has\n  // stopped capturing LOGs.\n  LOG(INFO) << \"Ignored info\";\n  LOG(WARNING) << \"Ignored warning\";\n  LOG(ERROR) << \"Ignored error\";\n}\n\n// Tests that all messages are intercepted regardless of issuing thread. The\n// purpose of this test is NOT to exercise thread-safety.\nTEST(ScopedMockLogTest, LogFromMultipleThreads) {\n  absl::ScopedMockLog log;\n\n  // We don't establish an order to expectations here, since the threads may\n  // execute their log statements in different order.\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, \"Thread 1\"));\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, \"Thread 2\"));\n\n  log.StartCapturingLogs();\n\n  absl::Barrier barrier(2);\n  std::thread thread1([&barrier]() {\n    barrier.Block();\n    LOG(INFO) << \"Thread 1\";\n  });\n  std::thread thread2([&barrier]() {\n    barrier.Block();\n    LOG(INFO) << \"Thread 2\";\n  });\n\n  thread1.join();\n  thread2.join();\n}\n\n// Tests that no sequence will be imposed on two LOG message expectations from\n// different threads. This test would actually deadlock if replaced to two LOG\n// statements from the same thread.\nTEST(ScopedMockLogTest, NoSequenceWithMultipleThreads) {\n  absl::ScopedMockLog log;\n\n  absl::Barrier barrier(2);\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, _))\n      .Times(2)\n      .WillRepeatedly([&barrier]() { barrier.Block(); });\n\n  log.StartCapturingLogs();\n\n  std::thread thread1([]() { LOG(INFO) << \"Thread 1\"; });\n  std::thread thread2([]() { LOG(INFO) << \"Thread 2\"; });\n\n  thread1.join();\n  thread2.join();\n}\n\nTEST(ScopedMockLogTsanTest,\n     ScopedMockLogCanBeDeletedWhenAnotherThreadIsLogging) {\n  auto log = absl::make_unique<absl::ScopedMockLog>();\n  EXPECT_CALL(*log, Log(absl::LogSeverity::kInfo, __FILE__, \"Thread log\"))\n      .Times(AnyNumber());\n\n  log->StartCapturingLogs();\n\n  absl::Notification logging_started;\n\n  std::thread thread([&logging_started]() {\n    for (int i = 0; i < 100; ++i) {\n      if (i == 50) logging_started.Notify();\n      LOG(INFO) << \"Thread log\";\n    }\n  });\n\n  logging_started.WaitForNotification();\n  log.reset();\n  thread.join();\n}\n\nTEST(ScopedMockLogTest, AsLocalSink) {\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(_, _, \"two\"));\n  EXPECT_CALL(log, Log(_, _, \"three\"));\n\n  LOG(INFO) << \"one\";\n  LOG(INFO).ToSinkOnly(&log.UseAsLocalSink()) << \"two\";\n  LOG(INFO).ToSinkAlso(&log.UseAsLocalSink()) << \"three\";\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/stripping_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Tests for stripping of literal strings.\n// ---------------------------------------\n//\n// When a `LOG` statement can be trivially proved at compile time to never fire,\n// e.g. due to `ABSL_MIN_LOG_LEVEL`, `NDEBUG`, or some explicit condition, data\n// streamed in can be dropped from the compiled program completely if they are\n// not used elsewhere.  This most commonly affects string literals, which users\n// often want to strip to reduce binary size and/or redact information about\n// their program's internals (e.g. in a release build).\n//\n// These tests log strings and then validate whether they appear in the compiled\n// binary.  This is done by opening the file corresponding to the running test\n// and running a simple string search on its contents.  The strings to be logged\n// and searched for must be unique, and we must take care not to emit them into\n// the binary in any other place, e.g. when searching for them.  The latter is\n// accomplished by computing them using base64; the source string appears in the\n// binary but the target string is computed at runtime.\n\n#include <stdio.h>\n\n#if defined(__MACH__)\n#include <mach-o/dyld.h>\n#elif defined(_WIN32)\n#include <Windows.h>\n#include <tchar.h>\n#endif\n\n#include <algorithm>\n#include <functional>\n#include <memory>\n#include <ostream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/strerror.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/flags/internal/program_name.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/status/status.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\n// Set a flag that controls whether we actually execute fatal statements, but\n// prevent the compiler from optimizing it out.\nstatic volatile bool kReallyDie = false;\n\nnamespace {\nusing ::testing::_;\nusing ::testing::Eq;\nusing ::testing::NotNull;\n\nusing absl::log_internal::kAbslMinLogLevel;\n\nstd::string Base64UnescapeOrDie(absl::string_view data) {\n  std::string decoded;\n  CHECK(absl::Base64Unescape(data, &decoded));\n  return decoded;\n}\n\n// -----------------------------------------------------------------------------\n// A Googletest matcher which searches the running binary for a given string\n// -----------------------------------------------------------------------------\n\n// This matcher is used to validate that literal strings streamed into\n// `LOG` statements that ought to be compiled out (e.g. `LOG_IF(INFO, false)`)\n// do not appear in the binary.\n//\n// Note that passing the string to be sought directly to `FileHasSubstr()` all\n// but forces its inclusion in the binary regardless of the logging library's\n// behavior. For example:\n//\n//   LOG_IF(INFO, false) << \"you're the man now dog\";\n//   // This will always pass:\n//   // EXPECT_THAT(fp, FileHasSubstr(\"you're the man now dog\"));\n//   // So use this instead:\n//   EXPECT_THAT(fp, FileHasSubstr(\n//       Base64UnescapeOrDie(\"eW91J3JlIHRoZSBtYW4gbm93IGRvZw==\")));\n\nclass FileHasSubstrMatcher final : public ::testing::MatcherInterface<FILE*> {\n public:\n  explicit FileHasSubstrMatcher(absl::string_view needle) : needle_(needle) {}\n\n  bool MatchAndExplain(\n      FILE* fp, ::testing::MatchResultListener* listener) const override {\n    std::string buf(\n        std::max<std::string::size_type>(needle_.size() * 2, 163840000), '\\0');\n    size_t buf_start_offset = 0;  // The file offset of the byte at `buf[0]`.\n    size_t buf_data_size = 0;     // The number of bytes of `buf` which contain\n                                  // data.\n\n    ::fseek(fp, 0, SEEK_SET);\n    while (true) {\n      // Fill the buffer to capacity or EOF:\n      while (buf_data_size < buf.size()) {\n        const size_t ret = fread(&buf[buf_data_size], sizeof(char),\n                                 buf.size() - buf_data_size, fp);\n        if (ret == 0) break;\n        buf_data_size += ret;\n      }\n      if (ferror(fp)) {\n        *listener << \"error reading file\";\n        return false;\n      }\n      const absl::string_view haystack(&buf[0], buf_data_size);\n      const auto off = haystack.find(needle_);\n      if (off != haystack.npos) {\n        *listener << \"string found at offset \" << buf_start_offset + off;\n        return true;\n      }\n      if (feof(fp)) {\n        *listener << \"string not found\";\n        return false;\n      }\n      // Copy the end of `buf` to the beginning so we catch matches that span\n      // buffer boundaries.  `buf` and `buf_data_size` are always large enough\n      // that these ranges don't overlap.\n      memcpy(&buf[0], &buf[buf_data_size - needle_.size()], needle_.size());\n      buf_start_offset += buf_data_size - needle_.size();\n      buf_data_size = needle_.size();\n    }\n  }\n  void DescribeTo(std::ostream* os) const override {\n    *os << \"contains the string \\\"\" << needle_ << \"\\\" (base64(\\\"\"\n        << Base64UnescapeOrDie(needle_) << \"\\\"))\";\n  }\n\n  void DescribeNegationTo(std::ostream* os) const override {\n    *os << \"does not \";\n    DescribeTo(os);\n  }\n\n private:\n  std::string needle_;\n};\n\nclass StrippingTest : public ::testing::Test {\n protected:\n  void SetUp() override {\n#ifndef NDEBUG\n    // Non-optimized builds don't necessarily eliminate dead code at all, so we\n    // don't attempt to validate stripping against such builds.\n    GTEST_SKIP() << \"StrippingTests skipped since this build is not optimized\";\n#elif defined(__EMSCRIPTEN__)\n    // These tests require a way to examine the running binary and look for\n    // strings; there's no portable way to do that.\n    GTEST_SKIP()\n        << \"StrippingTests skipped since this platform is not optimized\";\n#endif\n  }\n\n  // Opens this program's executable file.  Returns `nullptr` and writes to\n  // `stderr` on failure.\n  std::unique_ptr<FILE, std::function<void(FILE*)>> OpenTestExecutable() {\n#if defined(__linux__)\n    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(\n        fopen(\"/proc/self/exe\", \"rb\"), [](FILE* fp) { fclose(fp); });\n    if (!fp) {\n      const std::string err = absl::base_internal::StrError(errno);\n      absl::FPrintF(stderr, \"Failed to open /proc/self/exe: %s\\n\", err);\n    }\n    return fp;\n#elif defined(__Fuchsia__)\n    // TODO(b/242579714): We need to restore the test coverage on this platform.\n    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(\n        fopen(absl::StrCat(\"/pkg/bin/\",\n                           absl::flags_internal::ShortProgramInvocationName())\n                  .c_str(),\n              \"rb\"),\n        [](FILE* fp) { fclose(fp); });\n    if (!fp) {\n      const std::string err = absl::base_internal::StrError(errno);\n      absl::FPrintF(stderr, \"Failed to open /pkg/bin/<binary name>: %s\\n\", err);\n    }\n    return fp;\n#elif defined(__MACH__)\n    uint32_t size = 0;\n    int ret = _NSGetExecutablePath(nullptr, &size);\n    if (ret != -1) {\n      absl::FPrintF(stderr,\n                    \"Failed to get executable path: \"\n                    \"_NSGetExecutablePath(nullptr) returned %d\\n\",\n                    ret);\n      return nullptr;\n    }\n    std::string path(size, '\\0');\n    ret = _NSGetExecutablePath(&path[0], &size);\n    if (ret != 0) {\n      absl::FPrintF(\n          stderr,\n          \"Failed to get executable path: _NSGetExecutablePath(buffer) \"\n          \"returned %d\\n\",\n          ret);\n      return nullptr;\n    }\n    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(\n        fopen(path.c_str(), \"rb\"), [](FILE* fp) { fclose(fp); });\n    if (!fp) {\n      const std::string err = absl::base_internal::StrError(errno);\n      absl::FPrintF(stderr, \"Failed to open executable at %s: %s\\n\", path, err);\n    }\n    return fp;\n#elif defined(_WIN32)\n    std::basic_string<TCHAR> path(4096, _T('\\0'));\n    while (true) {\n      const uint32_t ret = ::GetModuleFileName(nullptr, &path[0],\n                                               static_cast<DWORD>(path.size()));\n      if (ret == 0) {\n        absl::FPrintF(\n            stderr,\n            \"Failed to get executable path: GetModuleFileName(buffer) \"\n            \"returned 0\\n\");\n        return nullptr;\n      }\n      if (ret < path.size()) break;\n      path.resize(path.size() * 2, _T('\\0'));\n    }\n    std::unique_ptr<FILE, std::function<void(FILE*)>> fp(\n        _tfopen(path.c_str(), _T(\"rb\")), [](FILE* fp) { fclose(fp); });\n    if (!fp) absl::FPrintF(stderr, \"Failed to open executable\\n\");\n    return fp;\n#else\n    absl::FPrintF(stderr,\n                  \"OpenTestExecutable() unimplemented on this platform\\n\");\n    return nullptr;\n#endif\n  }\n\n  ::testing::Matcher<FILE*> FileHasSubstr(absl::string_view needle) {\n    return MakeMatcher(new FileHasSubstrMatcher(needle));\n  }\n};\n\n// This tests whether out methodology for testing stripping works on this\n// platform by looking for one string that definitely ought to be there and one\n// that definitely ought not to.  If this fails, none of the `StrippingTest`s\n// are going to produce meaningful results.\nTEST_F(StrippingTest, Control) {\n  constexpr char kEncodedPositiveControl[] =\n      \"U3RyaXBwaW5nVGVzdC5Qb3NpdGl2ZUNvbnRyb2w=\";\n  const std::string encoded_negative_control =\n      absl::Base64Escape(\"StrippingTest.NegativeControl\");\n\n  // Verify this mainly so we can encode other strings and know definitely they\n  // won't encode to `kEncodedPositiveControl`.\n  EXPECT_THAT(Base64UnescapeOrDie(\"U3RyaXBwaW5nVGVzdC5Qb3NpdGl2ZUNvbnRyb2w=\"),\n              Eq(\"StrippingTest.PositiveControl\"));\n\n  auto exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  EXPECT_THAT(exe.get(), FileHasSubstr(kEncodedPositiveControl));\n  EXPECT_THAT(exe.get(), Not(FileHasSubstr(encoded_negative_control)));\n}\n\nTEST_F(StrippingTest, Literal) {\n  // We need to load a copy of the needle string into memory (so we can search\n  // for it) without leaving it lying around in plaintext in the executable file\n  // as would happen if we used a literal.  We might (or might not) leave it\n  // lying around later; that's what the tests are for!\n  const std::string needle = absl::Base64Escape(\"StrippingTest.Literal\");\n  LOG(INFO) << \"U3RyaXBwaW5nVGVzdC5MaXRlcmFs\";\n  auto exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  if (absl::LogSeverity::kInfo >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));\n  }\n}\n\nTEST_F(StrippingTest, LiteralInExpression) {\n  // We need to load a copy of the needle string into memory (so we can search\n  // for it) without leaving it lying around in plaintext in the executable file\n  // as would happen if we used a literal.  We might (or might not) leave it\n  // lying around later; that's what the tests are for!\n  const std::string needle =\n      absl::Base64Escape(\"StrippingTest.LiteralInExpression\");\n  LOG(INFO) << absl::StrCat(\"secret: \",\n                            \"U3RyaXBwaW5nVGVzdC5MaXRlcmFsSW5FeHByZXNzaW9u\");\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  if (absl::LogSeverity::kInfo >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));\n  }\n}\n\nTEST_F(StrippingTest, Fatal) {\n  // We need to load a copy of the needle string into memory (so we can search\n  // for it) without leaving it lying around in plaintext in the executable file\n  // as would happen if we used a literal.  We might (or might not) leave it\n  // lying around later; that's what the tests are for!\n  const std::string needle = absl::Base64Escape(\"StrippingTest.Fatal\");\n  // We don't care if the LOG statement is actually executed, we're just\n  // checking that it's stripped.\n  if (kReallyDie) LOG(FATAL) << \"U3RyaXBwaW5nVGVzdC5GYXRhbA==\";\n\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));\n  }\n}\n\nTEST_F(StrippingTest, DFatal) {\n  // We need to load a copy of the needle string into memory (so we can search\n  // for it) without leaving it lying around in plaintext in the executable file\n  // as would happen if we used a literal.  We might (or might not) leave it\n  // lying around later; that's what the tests are for!\n  const std::string needle = absl::Base64Escape(\"StrippingTest.DFatal\");\n  // We don't care if the LOG statement is actually executed, we're just\n  // checking that it's stripped.\n  if (kReallyDie) LOG(DFATAL) << \"U3RyaXBwaW5nVGVzdC5ERmF0YWw=\";\n\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  // `DFATAL` can be `ERROR` or `FATAL`, and a compile-time optimizer doesn't\n  // know which, because `absl::kLogDebugFatal` is declared `extern` and defined\n  // in another TU.  Link-time optimization might do better.  We have six cases:\n  // |         `AMLL` is-> | `<=ERROR` | `FATAL` | `>FATAL` |\n  // | ------------------- | --------- | ------- | -------- |\n  // | `DFATAL` is `ERROR` |   present |       ? | stripped |\n  // | `DFATAL` is `FATAL` |   present | present | stripped |\n\n  // These constexpr variables are used to suppress unreachable code warnings\n  // in the if-else statements below.\n\n  // \"present\" in the table above: `DFATAL` exceeds `ABSL_MIN_LOG_LEVEL`, so\n  // `DFATAL` statements should not be stripped (and they should be logged\n  // when executed, but that's a different testsuite).\n  constexpr bool kExpectPresent = absl::kLogDebugFatal >= kAbslMinLogLevel;\n\n  // \"stripped\" in the table above: even though the compiler may not know\n  // which value `DFATAL` has, it should be able to strip it since both\n  // possible values ought to be stripped.\n  constexpr bool kExpectStripped = kAbslMinLogLevel > absl::LogSeverity::kFatal;\n\n  if (kExpectPresent) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(needle));\n  } else if (kExpectStripped) {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));\n  } else {\n    // \"?\" in the table above; may or may not be stripped depending on whether\n    // any link-time optimization is done.  Either outcome is ok.\n  }\n}\n\nTEST_F(StrippingTest, Level) {\n  const std::string needle = absl::Base64Escape(\"StrippingTest.Level\");\n  volatile auto severity = absl::LogSeverity::kWarning;\n  // Ensure that `severity` is not a compile-time constant to prove that\n  // stripping works regardless:\n  LOG(LEVEL(severity)) << \"U3RyaXBwaW5nVGVzdC5MZXZlbA==\";\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {\n    // This can't be stripped at compile-time because it might evaluate to a\n    // level that shouldn't be stripped.\n    EXPECT_THAT(exe.get(), FileHasSubstr(needle));\n  } else {\n#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__APPLE__)\n    // Dead code elimination misses this case.\n#else\n    // All levels should be stripped, so it doesn't matter what the severity\n    // winds up being.\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle)));\n#endif\n  }\n}\n\nTEST_F(StrippingTest, Check) {\n  // Here we also need a variable name with enough entropy that it's unlikely to\n  // appear in the binary by chance.  `volatile` keeps the tautological\n  // comparison (and the rest of the `CHECK`) from being optimized away.\n  const std::string var_needle = absl::Base64Escape(\"StrippingTestCheckVar\");\n  const std::string msg_needle = absl::Base64Escape(\"StrippingTest.Check\");\n  volatile int U3RyaXBwaW5nVGVzdENoZWNrVmFy = 0xCAFE;\n  // We don't care if the CHECK is actually executed, just that stripping works.\n  // Hiding it behind `kReallyDie` works around some overly aggressive\n  // optimizations in older versions of MSVC.\n  if (kReallyDie) {\n    CHECK(U3RyaXBwaW5nVGVzdENoZWNrVmFy != U3RyaXBwaW5nVGVzdENoZWNrVmFy)\n        << \"U3RyaXBwaW5nVGVzdC5DaGVjaw==\";\n  }\n\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(var_needle));\n    EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle)));\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle)));\n  }\n}\n\nTEST_F(StrippingTest, CheckOp) {\n  // See `StrippingTest.Check` for some hairy implementation notes.\n  const std::string var_needle1 =\n      absl::Base64Escape(\"StrippingTestCheckOpVar1\");\n  const std::string var_needle2 =\n      absl::Base64Escape(\"StrippingTestCheckOpVar2\");\n  const std::string msg_needle = absl::Base64Escape(\"StrippingTest.CheckOp\");\n  volatile int U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIx = 0xFEED;\n  volatile int U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIy = 0xCAFE;\n  if (kReallyDie) {\n    CHECK_EQ(U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIx, U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIy)\n        << \"U3RyaXBwaW5nVGVzdC5DaGVja09w\";\n  }\n\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n\n  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(var_needle1));\n    EXPECT_THAT(exe.get(), FileHasSubstr(var_needle2));\n    EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle1)));\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle2)));\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle)));\n  }\n}\n\nTEST_F(StrippingTest, CheckStrOp) {\n  // See `StrippingTest.Check` for some hairy implementation notes.\n  const std::string var_needle1 =\n      absl::Base64Escape(\"StrippingTestCheckStrOpVar1\");\n  const std::string var_needle2 =\n      absl::Base64Escape(\"StrippingTestCheckStrOpVar2\");\n  const std::string msg_needle = absl::Base64Escape(\"StrippingTest.CheckStrOp\");\n  const char *volatile U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIx = \"FEED\";\n  const char *volatile U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIy = \"CAFE\";\n  if (kReallyDie) {\n    CHECK_STREQ(U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIx,\n                U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIy)\n        << \"U3RyaXBwaW5nVGVzdC5DaGVja1N0ck9w\";\n  }\n\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n\n  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(var_needle1));\n    EXPECT_THAT(exe.get(), FileHasSubstr(var_needle2));\n    EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle1)));\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle2)));\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle)));\n  }\n}\n\nTEST_F(StrippingTest, CheckOk) {\n  // See `StrippingTest.Check` for some hairy implementation notes.\n  const std::string var_needle = absl::Base64Escape(\"StrippingTestCheckOkVar1\");\n  const std::string msg_needle = absl::Base64Escape(\"StrippingTest.CheckOk\");\n  volatile bool x = false;\n  auto U3RyaXBwaW5nVGVzdENoZWNrT2tWYXIx = absl::OkStatus();\n  if (x) {\n    U3RyaXBwaW5nVGVzdENoZWNrT2tWYXIx =\n        absl::InvalidArgumentError(\"Stripping this is not my job!\");\n  }\n  if (kReallyDie) {\n    CHECK_OK(U3RyaXBwaW5nVGVzdENoZWNrT2tWYXIx)\n        << \"U3RyaXBwaW5nVGVzdC5DaGVja09r\";\n  }\n\n  std::unique_ptr<FILE, std::function<void(FILE*)>> exe = OpenTestExecutable();\n  ASSERT_THAT(exe, NotNull());\n\n  if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) {\n    EXPECT_THAT(exe.get(), FileHasSubstr(var_needle));\n    EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle));\n  } else {\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle)));\n    EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle)));\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/structured.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/structured.h\n// -----------------------------------------------------------------------------\n//\n// This header declares APIs supporting structured logging, allowing log\n// statements to be more easily parsed, especially by automated processes.\n//\n// When structured logging is in use, data streamed into a `LOG` statement are\n// encoded as `Value` fields in a `logging.proto.Event` protocol buffer message.\n// The individual data are exposed programmatically to `LogSink`s and to the\n// user via some log reading tools which are able to query the structured data\n// more usefully than would be possible if each message was a single opaque\n// string.  These helpers allow user code to add additional structure to the\n// data they stream.\n\n#ifndef ABSL_LOG_STRUCTURED_H_\n#define ABSL_LOG_STRUCTURED_H_\n\n#include <ostream>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/structured.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// LogAsLiteral()\n//\n// Annotates its argument as a string literal so that structured logging\n// captures it as a `literal` field instead of a `str` field (the default).\n// This does not affect the text representation, only the structure.\n//\n// Streaming `LogAsLiteral(s)` into a `std::ostream` behaves just like streaming\n// `s` directly.\n//\n// Using `LogAsLiteral()` is occasionally appropriate and useful when proxying\n// data logged from another system or another language.  For example:\n//\n//   void Logger::LogString(absl::string_view str, absl::LogSeverity severity,\n//                          const char *file, int line) {\n//     LOG(LEVEL(severity)).AtLocation(file, line) << str;\n//   }\n//   void Logger::LogStringLiteral(absl::string_view str,\n//                                 absl::LogSeverity severity, const char *file,\n//                                 int line) {\n//     LOG(LEVEL(severity)).AtLocation(file, line) << absl::LogAsLiteral(str);\n//   }\n//\n// `LogAsLiteral` should only be used as a streaming operand and not, for\n// example, as a local variable initializer.\ninline log_internal::AsLiteralImpl LogAsLiteral(\n    absl::string_view s ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return log_internal::AsLiteralImpl(s);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOG_STRUCTURED_H_\n"
  },
  {
    "path": "absl/log/structured_test.cc",
    "content": "//\n// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/structured.h\"\n\n#include <ios>\n#include <sstream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/log/internal/test_helpers.h\"\n#include \"absl/log/internal/test_matchers.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n\nnamespace {\nusing ::absl::log_internal::MatchesOstream;\nusing ::absl::log_internal::TextMessage;\nusing ::testing::ElementsAre;\nusing ::testing::Eq;\n\nauto *test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(\n    new absl::log_internal::LogTestEnvironment);\n\n// Abseil Logging library uses these by default, so we set them on the\n// `std::ostream` we compare against too.\nstd::ios &LoggingDefaults(std::ios &str) {\n  str.setf(std::ios_base::showbase | std::ios_base::boolalpha |\n           std::ios_base::internal);\n  return str;\n}\n\nTEST(StreamingFormatTest, LogAsLiteral) {\n  std::ostringstream stream;\n  const std::string not_a_literal(\"hello world\");\n  stream << LoggingDefaults << absl::LogAsLiteral(not_a_literal);\n\n  absl::ScopedMockLog sink;\n  EXPECT_CALL(sink, Send).Times(0);\n\n  EXPECT_CALL(sink, Send(AllOf(TextMessage(MatchesOstream(stream)),\n                               TextMessage(Eq(\"hello world\")),\n                               ENCODED_MESSAGE(HasValues(ElementsAre(\n                                   ValueWithLiteral(Eq(\"hello world\"))))))));\n\n  sink.StartCapturingLogs();\n  LOG(INFO) << absl::LogAsLiteral(not_a_literal);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/log/vlog_is_on.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: log/vlog_is_on.h\n// -----------------------------------------------------------------------------\n//\n// This header defines the `VLOG_IS_ON()` macro that controls the\n// variable-verbosity conditional logging.\n//\n// It's used by `VLOG` in log.h, or it can also be used directly like this:\n//\n//   if (VLOG_IS_ON(2)) {\n//     foo_server.RecomputeStatisticsExpensive();\n//     LOG(INFO) << foo_server.LastStatisticsAsString();\n//   }\n//\n// Each source file has an effective verbosity level that's a non-negative\n// integer computed from the `--vmodule` and `--v` flags.\n// `VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity\n// level is greater than or equal to `n`.\n//\n// `--vmodule` takes a comma-delimited list of key=value pairs.  Each key is a\n// pattern matched against filenames, and the values give the effective severity\n// level applied to matching files.  '?' and '*' characters in patterns are\n// interpreted as single-character and zero-or-more-character wildcards.\n// Patterns including a slash character are matched against full pathnames,\n// while those without are matched against basenames only.  One suffix (i.e. the\n// last . and everything after it) is stripped from each filename prior to\n// matching, as is the special suffix \"-inl\".\n//\n// Example: --vmodule=module_a=1,module_b=2\n//\n// Files are matched against globs in `--vmodule` in order, and the first match\n// determines the verbosity level.\n//\n// Files which do not match any pattern in `--vmodule` use the value of `--v` as\n// their effective verbosity level.  The default is 0.\n//\n// SetVLogLevel helper function is provided to do limited dynamic control over\n// V-logging by appending to `--vmodule`. Because these go at the beginning of\n// the list, they take priority over any globs previously added.\n//\n// Resetting --vmodule will override all previous modifications to `--vmodule`,\n// including via SetVLogLevel.\n\n#ifndef ABSL_LOG_VLOG_IS_ON_H_\n#define ABSL_LOG_VLOG_IS_ON_H_\n\n#include \"absl/log/absl_vlog_is_on.h\"  // IWYU pragma: export\n\n// IWYU pragma: private, include \"absl/log/log.h\"\n\n// Each VLOG_IS_ON call site gets its own VLogSite that registers with the\n// global linked list of sites to asynchronously update its verbosity level on\n// changes to --v or --vmodule. The verbosity can also be set by manually\n// calling SetVLogLevel.\n//\n// VLOG_IS_ON is not async signal safe, but it is guaranteed not to allocate\n// new memory.\n#define VLOG_IS_ON(verbose_level) ABSL_VLOG_IS_ON(verbose_level)\n\n#endif  // ABSL_LOG_VLOG_IS_ON_H_\n"
  },
  {
    "path": "absl/log/vlog_is_on_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/log/vlog_is_on.h\"\n\n#include <optional>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/log_severity.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/log/flags.h\"\n#include \"absl/log/globals.h\"\n#include \"absl/log/log.h\"\n#include \"absl/log/scoped_mock_log.h\"\n\nnamespace {\n\nusing ::testing::_;\n\nstd::optional<int> MaxLogVerbosity() {\n#ifdef ABSL_MAX_VLOG_VERBOSITY\n  return ABSL_MAX_VLOG_VERBOSITY;\n#else\n  return std::nullopt;\n#endif\n}\n\nstd::optional<int> MinLogLevel() {\n#ifdef ABSL_MIN_LOG_LEVEL\n  return static_cast<int>(ABSL_MIN_LOG_LEVEL);\n#else\n  return std::nullopt;\n#endif\n}\n\n// This fixture is used to reset the VLOG levels to their default values before\n// each test.\nclass VLogIsOnTest : public ::testing::Test {\n protected:\n  void SetUp() override { ResetVLogLevels(); }\n\n private:\n  // Resets the VLOG levels to their default values.\n  // It is supposed to be called in the SetUp() method of the test fixture to\n  // eliminate any side effects from other tests.\n  static void ResetVLogLevels() {\n    absl::log_internal::UpdateVModule(\"\");\n    absl::SetGlobalVLogLevel(0);\n  }\n};\n\nTEST_F(VLogIsOnTest, GlobalWorksWithoutMaxVerbosityAndMinLogLevel) {\n  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {\n    GTEST_SKIP();\n  }\n\n  absl::SetGlobalVLogLevel(3);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"important\"));\n\n  log.StartCapturingLogs();\n  VLOG(3) << \"important\";\n  VLOG(4) << \"spam\";\n}\n\nTEST_F(VLogIsOnTest, FileWorksWithoutMaxVerbosityAndMinLogLevel) {\n  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {\n    GTEST_SKIP();\n  }\n\n  absl::SetVLogLevel(\"vlog_is_on_test\", 3);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"important\"));\n\n  log.StartCapturingLogs();\n  VLOG(3) << \"important\";\n  VLOG(4) << \"spam\";\n}\n\nTEST_F(VLogIsOnTest, PatternWorksWithoutMaxVerbosityAndMinLogLevel) {\n  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {\n    GTEST_SKIP();\n  }\n\n  absl::SetVLogLevel(\"vlog_is_on*\", 3);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"important\"));\n\n  log.StartCapturingLogs();\n  VLOG(3) << \"important\";\n  VLOG(4) << \"spam\";\n}\n\nTEST_F(VLogIsOnTest,\n       PatternOverridesLessGenericOneWithoutMaxVerbosityAndMinLogLevel) {\n  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {\n    GTEST_SKIP();\n  }\n\n  // This should disable logging in this file\n  absl::SetVLogLevel(\"vlog_is_on*\", -1);\n  // This overrides the previous setting, because \"vlog*\" is more generic than\n  // \"vlog_is_on*\". This should enable VLOG level 3 in this file.\n  absl::SetVLogLevel(\"vlog*\", 3);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"important\"));\n\n  log.StartCapturingLogs();\n  VLOG(3) << \"important\";\n  VLOG(4) << \"spam\";\n}\n\nTEST_F(VLogIsOnTest,\n       PatternDoesNotOverridesMoreGenericOneWithoutMaxVerbosityAndMinLogLevel) {\n  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {\n    GTEST_SKIP();\n  }\n\n  // This should enable VLOG level 3 in this file.\n  absl::SetVLogLevel(\"vlog*\", 3);\n  // This should not change the VLOG level in this file. The pattern does not\n  // match this file and it is less generic than the previous patter \"vlog*\".\n  // Therefore, it does not disable VLOG level 3 in this file.\n  absl::SetVLogLevel(\"vlog_is_on_some_other_test*\", -1);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"important\"));\n\n  log.StartCapturingLogs();\n  VLOG(3) << \"important\";\n  VLOG(5) << \"spam\";\n}\n\nTEST_F(VLogIsOnTest, GlobalDoesNotFilterBelowMaxVerbosity) {\n  if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() < 2) {\n    GTEST_SKIP();\n  }\n\n  // Set an arbitrary high value to avoid filtering VLOGs in tests by default.\n  absl::SetGlobalVLogLevel(1000);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"asdf\"));\n\n  log.StartCapturingLogs();\n  VLOG(2) << \"asdf\";\n}\n\nTEST_F(VLogIsOnTest, FileDoesNotFilterBelowMaxVerbosity) {\n  if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() < 2) {\n    GTEST_SKIP();\n  }\n\n  // Set an arbitrary high value to avoid filtering VLOGs in tests by default.\n  absl::SetVLogLevel(\"vlog_is_on_test\", 1000);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"asdf\"));\n\n  log.StartCapturingLogs();\n  VLOG(2) << \"asdf\";\n}\n\nTEST_F(VLogIsOnTest, PatternDoesNotFilterBelowMaxVerbosity) {\n  if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() < 2) {\n    GTEST_SKIP();\n  }\n\n  // Set an arbitrary high value to avoid filtering VLOGs in tests by default.\n  absl::SetVLogLevel(\"vlog_is_on*\", 1000);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, \"asdf\"));\n\n  log.StartCapturingLogs();\n  VLOG(2) << \"asdf\";\n}\n\nTEST_F(VLogIsOnTest, GlobalFiltersAboveMaxVerbosity) {\n  if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() >= 4) {\n    GTEST_SKIP();\n  }\n\n  // Set an arbitrary high value to avoid filtering VLOGs in tests by default.\n  absl::SetGlobalVLogLevel(1000);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  log.StartCapturingLogs();\n  VLOG(4) << \"dfgh\";\n}\n\nTEST_F(VLogIsOnTest, FileFiltersAboveMaxVerbosity) {\n  if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() >= 4) {\n    GTEST_SKIP();\n  }\n\n  // Set an arbitrary high value to avoid filtering VLOGs in tests by default.\n  absl::SetVLogLevel(\"vlog_is_on_test\", 1000);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  log.StartCapturingLogs();\n  VLOG(4) << \"dfgh\";\n}\n\nTEST_F(VLogIsOnTest, PatternFiltersAboveMaxVerbosity) {\n  if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() >= 4) {\n    GTEST_SKIP();\n  }\n\n  // Set an arbitrary high value to avoid filtering VLOGs in tests by default.\n  absl::SetVLogLevel(\"vlog_is_on*\", 1000);\n  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);\n\n  log.StartCapturingLogs();\n  VLOG(4) << \"dfgh\";\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/memory/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"memory\",\n    hdrs = [\"memory.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    defines = select({\n        \"//conditions:default\": [],\n    }),\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"memory_test\",\n    srcs = [\"memory_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":memory\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/memory/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    memory\n  HDRS\n    \"memory.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::core_headers\n    absl::meta\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    memory_test\n  SRCS\n    \"memory_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::memory\n    absl::core_headers\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/memory/memory.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: memory.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains utility functions for managing the creation and\n// conversion of smart pointers. This file is an extension to the C++\n// standard <memory> library header file.\n\n#ifndef ABSL_MEMORY_MEMORY_H_\n#define ABSL_MEMORY_MEMORY_H_\n\n#include <cstddef>\n#include <limits>\n#include <memory>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/macros.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// Function Template: WrapUnique()\n// -----------------------------------------------------------------------------\n//\n// Adopts ownership from a raw pointer and transfers it to the returned\n// `std::unique_ptr`, whose type is deduced. Because of this deduction, *do not*\n// specify the template type `T` when calling `WrapUnique`.\n//\n// Example:\n//   X* NewX(int, int);\n//   auto x = WrapUnique(NewX(1, 2));  // 'x' is std::unique_ptr<X>.\n//\n// Do not call WrapUnique with an explicit type, as in\n// `WrapUnique<X>(NewX(1, 2))`.  The purpose of WrapUnique is to automatically\n// deduce the pointer type. If you wish to make the type explicit, just use\n// `std::unique_ptr` directly.\n//\n//   auto x = std::unique_ptr<X>(NewX(1, 2));\n//                  - or -\n//   std::unique_ptr<X> x(NewX(1, 2));\n//\n// While `absl::WrapUnique` is useful for capturing the output of a raw\n// pointer factory, prefer 'absl::make_unique<T>(args...)' over\n// 'absl::WrapUnique(new T(args...))'.\n//\n//   auto x = WrapUnique(new X(1, 2));  // works, but nonideal.\n//   auto x = make_unique<X>(1, 2);     // safer, standard, avoids raw 'new'.\n//\n// Note that `absl::WrapUnique(p)` is valid only if `delete p` is a valid\n// expression. In particular, `absl::WrapUnique()` cannot wrap pointers to\n// arrays, functions or void, and it must not be used to capture pointers\n// obtained from array-new expressions (even though that would compile!).\ntemplate <typename T>\nstd::unique_ptr<T> WrapUnique(T* ptr) {\n  static_assert(!std::is_array<T>::value, \"array types are unsupported\");\n  static_assert(std::is_object<T>::value, \"non-object types are unsupported\");\n  return std::unique_ptr<T>(ptr);\n}\n\n// -----------------------------------------------------------------------------\n// Function Template: make_unique<T>()\n// -----------------------------------------------------------------------------\n//\n// Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries\n// during the construction process. `absl::make_unique<>` also avoids redundant\n// type declarations, by avoiding the need to explicitly use the `new` operator.\n//\n// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique\n//\n// For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic,\n// see Herb Sutter's explanation on\n// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/].\n// (In general, reviewers should treat `new T(a,b)` with scrutiny.)\n//\n// Historical note: Abseil once provided a C++11 compatible implementation of\n// the C++14's `std::make_unique`. Now that C++11 support has been sunsetted,\n// `absl::make_unique` simply uses the STL-provided implementation. New code\n// should use `std::make_unique`.\nusing std::make_unique;\n\nnamespace memory_internal {\n\n// Traits to select proper overload and return type for\n// `absl::make_unique_for_overwrite<>`.\ntemplate <typename T>\nstruct MakeUniqueResult {\n  using scalar = std::unique_ptr<T>;\n};\ntemplate <typename T>\nstruct MakeUniqueResult<T[]> {\n  using array = std::unique_ptr<T[]>;\n};\ntemplate <typename T, size_t N>\nstruct MakeUniqueResult<T[N]> {\n  using invalid = void;\n};\n\n}  // namespace memory_internal\n\n// These are make_unique_for_overwrite variants modeled after\n// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1973r1.pdf\n// Unlike absl::make_unique, values are default initialized rather than value\n// initialized.\n//\n// `absl::make_unique_for_overwrite` overload for non-array types.\ntemplate <typename T>\ntypename memory_internal::MakeUniqueResult<T>::scalar\n    make_unique_for_overwrite() {\n  return std::unique_ptr<T>(new T);\n}\n\n// `absl::make_unique_for_overwrite` overload for an array T[] of unknown\n// bounds. The array allocation needs to use the `new T[size]` form and cannot\n// take element constructor arguments. The `std::unique_ptr` will manage\n// destructing these array elements.\ntemplate <typename T>\ntypename memory_internal::MakeUniqueResult<T>::array\n    make_unique_for_overwrite(size_t n) {\n  return std::unique_ptr<T>(new typename absl::remove_extent_t<T>[n]);\n}\n\n// `absl::make_unique_for_overwrite` overload for an array T[N] of known bounds.\n// This construction will be rejected.\ntemplate <typename T, typename... Args>\ntypename memory_internal::MakeUniqueResult<T>::invalid\n    make_unique_for_overwrite(Args&&... /* args */) = delete;\n\n// -----------------------------------------------------------------------------\n// Function Template: RawPtr()\n// -----------------------------------------------------------------------------\n//\n// Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is\n// useful within templates that need to handle a complement of raw pointers,\n// `std::nullptr_t`, and smart pointers.\ntemplate <typename T>\nauto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) {\n  // ptr is a forwarding reference to support Ts with non-const operators.\n  return (ptr != nullptr) ? std::addressof(*ptr) : nullptr;\n}\ninline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }\n\n// -----------------------------------------------------------------------------\n// Function Template: ShareUniquePtr()\n// -----------------------------------------------------------------------------\n//\n// Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced\n// type. Ownership (if any) of the held value is transferred to the returned\n// shared pointer.\n//\n// Example:\n//\n//     auto up = absl::make_unique<int>(10);\n//     auto sp = absl::ShareUniquePtr(std::move(up));  // shared_ptr<int>\n//     CHECK_EQ(*sp, 10);\n//     CHECK(up == nullptr);\n//\n// Note that this conversion is correct even when T is an array type, and more\n// generally it works for *any* deleter of the `unique_ptr` (single-object\n// deleter, array deleter, or any custom deleter), since the deleter is adopted\n// by the shared pointer as well. The deleter is copied (unless it is a\n// reference).\n//\n// Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a\n// null shared pointer does not attempt to call the deleter.\ntemplate <typename T, typename D>\nstd::shared_ptr<T> ShareUniquePtr(std::unique_ptr<T, D>&& ptr) {\n  return ptr ? std::shared_ptr<T>(std::move(ptr)) : std::shared_ptr<T>();\n}\n\n// -----------------------------------------------------------------------------\n// Function Template: WeakenPtr()\n// -----------------------------------------------------------------------------\n//\n// Creates a weak pointer associated with a given shared pointer. The returned\n// value is a `std::weak_ptr` of deduced type.\n//\n// Example:\n//\n//    auto sp = std::make_shared<int>(10);\n//    auto wp = absl::WeakenPtr(sp);\n//    CHECK_EQ(sp.get(), wp.lock().get());\n//    sp.reset();\n//    CHECK(wp.lock() == nullptr);\n//\ntemplate <typename T>\nstd::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) {\n  return std::weak_ptr<T>(ptr);\n}\n\n// -----------------------------------------------------------------------------\n// Class Template: pointer_traits\n// -----------------------------------------------------------------------------\n//\n// Historical note: Abseil once provided an implementation of\n// `std::pointer_traits` for platforms that had not yet provided it. Those\n// platforms are no longer supported. New code should simply use\n// `std::pointer_traits`.\nusing std::pointer_traits;\n\n// -----------------------------------------------------------------------------\n// Class Template: allocator_traits\n// -----------------------------------------------------------------------------\n//\n// Historical note: Abseil once provided an implementation of\n// `std::allocator_traits` for platforms that had not yet provided it. Those\n// platforms are no longer supported. New code should simply use\n// `std::allocator_traits`.\nusing std::allocator_traits;\n\nnamespace memory_internal {\n\n// ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D.\ntemplate <template <typename> class Extract, typename Obj, typename Default,\n          typename>\nstruct ExtractOr {\n  using type = Default;\n};\n\ntemplate <template <typename> class Extract, typename Obj, typename Default>\nstruct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> {\n  using type = Extract<Obj>;\n};\n\ntemplate <template <typename> class Extract, typename Obj, typename Default>\nusing ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type;\n\n// This template alias transforms Alloc::is_nothrow into a metafunction with\n// Alloc as a parameter so it can be used with ExtractOrT<>.\ntemplate <typename Alloc>\nusing GetIsNothrow = typename Alloc::is_nothrow;\n\n}  // namespace memory_internal\n\n// ABSL_ALLOCATOR_NOTHROW is a build time configuration macro for user to\n// specify whether the default allocation function can throw or never throws.\n// If the allocation function never throws, user should define it to a non-zero\n// value (e.g. via `-DABSL_ALLOCATOR_NOTHROW`).\n// If the allocation function can throw, user should leave it undefined or\n// define it to zero.\n//\n// allocator_is_nothrow<Alloc> is a traits class that derives from\n// Alloc::is_nothrow if present, otherwise std::false_type. It's specialized\n// for Alloc = std::allocator<T> for any type T according to the state of\n// ABSL_ALLOCATOR_NOTHROW.\n//\n// default_allocator_is_nothrow is a class that derives from std::true_type\n// when the default allocator (global operator new) never throws, and\n// std::false_type when it can throw. It is a convenience shorthand for writing\n// allocator_is_nothrow<std::allocator<T>> (T can be any type).\n// NOTE: allocator_is_nothrow<std::allocator<T>> is guaranteed to derive from\n// the same type for all T, because users should specialize neither\n// allocator_is_nothrow nor std::allocator.\ntemplate <typename Alloc>\nstruct allocator_is_nothrow\n    : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,\n                                  std::false_type> {};\n\n#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW\ntemplate <typename T>\nstruct allocator_is_nothrow<std::allocator<T>> : std::true_type {};\nstruct default_allocator_is_nothrow : std::true_type {};\n#else\nstruct default_allocator_is_nothrow : std::false_type {};\n#endif\n\nnamespace memory_internal {\ntemplate <typename Allocator, typename Iterator, typename... Args>\nvoid ConstructRange(Allocator& alloc, Iterator first, Iterator last,\n                    const Args&... args) {\n  for (Iterator cur = first; cur != last; ++cur) {\n    ABSL_INTERNAL_TRY {\n      std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),\n                                                  args...);\n    }\n    ABSL_INTERNAL_CATCH_ANY {\n      while (cur != first) {\n        --cur;\n        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));\n      }\n      ABSL_INTERNAL_RETHROW;\n    }\n  }\n}\n\ntemplate <typename Allocator, typename Iterator, typename InputIterator>\nvoid CopyRange(Allocator& alloc, Iterator destination, InputIterator first,\n               InputIterator last) {\n  for (Iterator cur = destination; first != last;\n       static_cast<void>(++cur), static_cast<void>(++first)) {\n    ABSL_INTERNAL_TRY {\n      std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),\n                                                  *first);\n    }\n    ABSL_INTERNAL_CATCH_ANY {\n      while (cur != destination) {\n        --cur;\n        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));\n      }\n      ABSL_INTERNAL_RETHROW;\n    }\n  }\n}\n}  // namespace memory_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_MEMORY_MEMORY_H_\n"
  },
  {
    "path": "absl/memory/memory_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Tests for pointer utilities.\n\n#include \"absl/memory/memory.h\"\n\n#include <sys/types.h>\n\n#include <cstddef>\n#include <memory>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::Return;\n\n// This class creates observable behavior to verify that a destructor has\n// been called, via the instance_count variable.\nclass DestructorVerifier {\n public:\n  DestructorVerifier() { ++instance_count_; }\n  DestructorVerifier(const DestructorVerifier&) = delete;\n  DestructorVerifier& operator=(const DestructorVerifier&) = delete;\n  ~DestructorVerifier() { --instance_count_; }\n\n  // The number of instances of this class currently active.\n  static int instance_count() { return instance_count_; }\n\n private:\n  // The number of instances of this class currently active.\n  static int instance_count_;\n};\n\nint DestructorVerifier::instance_count_ = 0;\n\nTEST(WrapUniqueTest, WrapUnique) {\n  // Test that the unique_ptr is constructed properly by verifying that the\n  // destructor for its payload gets called at the proper time.\n  {\n    auto dv = new DestructorVerifier;\n    EXPECT_EQ(1, DestructorVerifier::instance_count());\n    std::unique_ptr<DestructorVerifier> ptr = absl::WrapUnique(dv);\n    EXPECT_EQ(1, DestructorVerifier::instance_count());\n  }\n  EXPECT_EQ(0, DestructorVerifier::instance_count());\n}\n\nTEST(MakeUniqueForOverwriteTest, Basic) {\n  std::unique_ptr<int> p = absl::make_unique_for_overwrite<int>();\n  p = absl::make_unique_for_overwrite<int>();\n}\n\n// InitializationVerifier fills in a pattern when allocated so we can\n// distinguish between its default and value initialized states (without\n// accessing truly uninitialized memory).\nstruct InitializationVerifier {\n  static constexpr int kDefaultScalar = 0x43;\n  static constexpr int kDefaultArray = 0x4B;\n\n  static void* operator new(size_t n) {\n    void* ret = ::operator new(n);\n    memset(ret, kDefaultScalar, n);\n    return ret;\n  }\n\n  static void* operator new[](size_t n) {\n    void* ret = ::operator new[](n);\n    memset(ret, kDefaultArray, n);\n    return ret;\n  }\n\n  int a;\n  int b;\n};\n\nTEST(Initialization, MakeUniqueForOverwrite) {\n  auto p = absl::make_unique_for_overwrite<InitializationVerifier>();\n\n  int pattern;\n  memset(&pattern, InitializationVerifier::kDefaultScalar, sizeof(pattern));\n\n  EXPECT_EQ(pattern, p->a);\n  EXPECT_EQ(pattern, p->b);\n}\n\nTEST(Initialization, MakeUniqueForOverwriteArray) {\n  auto p = absl::make_unique_for_overwrite<InitializationVerifier[]>(2);\n\n  int pattern;\n  memset(&pattern, InitializationVerifier::kDefaultArray, sizeof(pattern));\n\n  EXPECT_EQ(pattern, p[0].a);\n  EXPECT_EQ(pattern, p[0].b);\n  EXPECT_EQ(pattern, p[1].a);\n  EXPECT_EQ(pattern, p[1].b);\n}\n\nstruct ArrayWatch {\n  void* operator new[](size_t n) {\n    allocs().push_back(n);\n    return ::operator new[](n);\n  }\n  void operator delete[](void* p) { return ::operator delete[](p); }\n  static std::vector<size_t>& allocs() {\n    static auto& v = *new std::vector<size_t>;\n    return v;\n  }\n};\n\nTEST(MakeUniqueForOverwriteTest, Array) {\n  // Ensure state is clean before we start so that these tests\n  // are order-agnostic.\n  ArrayWatch::allocs().clear();\n\n  auto p = absl::make_unique_for_overwrite<ArrayWatch[]>(5);\n  static_assert(std::is_same<decltype(p), std::unique_ptr<ArrayWatch[]>>::value,\n                \"unexpected return type\");\n  EXPECT_THAT(ArrayWatch::allocs(), ElementsAre(5 * sizeof(ArrayWatch)));\n}\n\nTEST(RawPtrTest, RawPointer) {\n  int i = 5;\n  EXPECT_EQ(&i, absl::RawPtr(&i));\n}\n\nTEST(RawPtrTest, SmartPointer) {\n  int* o = new int(5);\n  std::unique_ptr<int> p(o);\n  EXPECT_EQ(o, absl::RawPtr(p));\n}\n\nclass IntPointerNonConstDeref {\n public:\n  explicit IntPointerNonConstDeref(int* p) : p_(p) {}\n  friend bool operator!=(const IntPointerNonConstDeref& a, std::nullptr_t) {\n    return a.p_ != nullptr;\n  }\n  int& operator*() { return *p_; }\n\n private:\n  std::unique_ptr<int> p_;\n};\n\nTEST(RawPtrTest, SmartPointerNonConstDereference) {\n  int* o = new int(5);\n  IntPointerNonConstDeref p(o);\n  EXPECT_EQ(o, absl::RawPtr(p));\n}\n\nTEST(RawPtrTest, NullValuedRawPointer) {\n  int* p = nullptr;\n  EXPECT_EQ(nullptr, absl::RawPtr(p));\n}\n\nTEST(RawPtrTest, NullValuedSmartPointer) {\n  std::unique_ptr<int> p;\n  EXPECT_EQ(nullptr, absl::RawPtr(p));\n}\n\nTEST(RawPtrTest, Nullptr) {\n  auto p = absl::RawPtr(nullptr);\n  EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value));\n  EXPECT_EQ(nullptr, p);\n}\n\nTEST(RawPtrTest, Null) {\n  auto p = absl::RawPtr(nullptr);\n  EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value));\n  EXPECT_EQ(nullptr, p);\n}\n\nTEST(RawPtrTest, Zero) {\n  auto p = absl::RawPtr(nullptr);\n  EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value));\n  EXPECT_EQ(nullptr, p);\n}\n\nTEST(ShareUniquePtrTest, Share) {\n  auto up = absl::make_unique<int>();\n  int* rp = up.get();\n  auto sp = absl::ShareUniquePtr(std::move(up));\n  EXPECT_EQ(sp.get(), rp);\n}\n\nTEST(ShareUniquePtrTest, ShareNull) {\n  struct NeverDie {\n    using pointer = void*;\n    void operator()(pointer) {\n      ASSERT_TRUE(false) << \"Deleter should not have been called.\";\n    }\n  };\n\n  std::unique_ptr<void, NeverDie> up;\n  auto sp = absl::ShareUniquePtr(std::move(up));\n}\n\nTEST(WeakenPtrTest, Weak) {\n  auto sp = std::make_shared<int>();\n  auto wp = absl::WeakenPtr(sp);\n  EXPECT_EQ(sp.get(), wp.lock().get());\n  sp.reset();\n  EXPECT_TRUE(wp.expired());\n}\n\n// Should not compile.\n/*\nTEST(RawPtrTest, NotAPointer) {\n  absl::RawPtr(1.5);\n}\n*/\n\nTEST(AllocatorNoThrowTest, DefaultAllocator) {\n#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW\n  EXPECT_TRUE(absl::default_allocator_is_nothrow::value);\n#else\n  EXPECT_FALSE(absl::default_allocator_is_nothrow::value);\n#endif\n}\n\nTEST(AllocatorNoThrowTest, StdAllocator) {\n#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW\n  EXPECT_TRUE(absl::allocator_is_nothrow<std::allocator<int>>::value);\n#else\n  EXPECT_FALSE(absl::allocator_is_nothrow<std::allocator<int>>::value);\n#endif\n}\n\nTEST(AllocatorNoThrowTest, CustomAllocator) {\n  struct NoThrowAllocator {\n    using is_nothrow = std::true_type;\n  };\n  struct CanThrowAllocator {\n    using is_nothrow = std::false_type;\n  };\n  struct UnspecifiedAllocator {};\n  EXPECT_TRUE(absl::allocator_is_nothrow<NoThrowAllocator>::value);\n  EXPECT_FALSE(absl::allocator_is_nothrow<CanThrowAllocator>::value);\n  EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/meta/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"constexpr_testing\",\n    testonly = 1,\n    hdrs = [\"internal/constexpr_testing.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"constexpr_testing_test\",\n    srcs = [\"internal/constexpr_testing_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":constexpr_testing\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"requires\",\n    hdrs = [\"internal/requires.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"requires_test\",\n    srcs = [\"internal/requires_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":requires\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"type_traits\",\n    hdrs = [\"type_traits.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"type_traits_test\",\n    srcs = [\"type_traits_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":type_traits\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/meta/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    constexpr_testing_internal\n  HDRS\n    \"internal/constexpr_testing.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    constexpr_testing_test\n  SRCS\n    \"internal/constexpr_testing_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::constexpr_testing_internal\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    requires_internal\n  HDRS\n    \"internal/requires.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    requires_test\n  SRCS\n    \"internal/requires_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::requires_internal\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    type_traits\n  HDRS\n    \"type_traits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    type_traits_test\n  SRCS\n    \"type_traits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::time\n    absl::core_headers\n    absl::type_traits\n    GTest::gmock_main\n)\n\n# component target\nabsl_cc_library(\n  NAME\n    meta\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::type_traits\n  PUBLIC\n)\n"
  },
  {
    "path": "absl/meta/internal/constexpr_testing.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_\n#define ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_\n\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace meta_internal {\n\n// HasConstexprEvaluation([] { ... }) will evaluate to `true` if the\n// lambda can be evaluated in a constant expression and `false`\n// otherwise.\n// The return type of the lambda is not relevant, as long as the whole\n// evaluation works in a constant expression.\ntemplate <typename F>\nconstexpr bool HasConstexprEvaluation(F f);\n\n/// Implementation details below ///\n\nnamespace internal_constexpr_evaluation {\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wuninitialized\"\n#endif\n// This will give a constexpr instance of `F`.\n// This works for captureless lambdas because they have no state and the copy\n// constructor does not look at the input reference.\ntemplate <typename F>\nconstexpr F default_instance = default_instance<F>;\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\ntemplate <typename F>\nconstexpr std::integral_constant<bool, (default_instance<F>(), true)> Tester(\n    int) {\n  return {};\n}\n\ntemplate <typename S>\nconstexpr std::false_type Tester(char) {\n  return {};\n}\n\n}  // namespace internal_constexpr_evaluation\n\ntemplate <typename F>\nconstexpr bool HasConstexprEvaluation(F) {\n  return internal_constexpr_evaluation::Tester<F>(0);\n}\n\n}  // namespace meta_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_META_INTERNAL_CONSTEXPR_TESTING_H_\n"
  },
  {
    "path": "absl/meta/internal/constexpr_testing_test.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/meta/internal/constexpr_testing.h\"\n\n#include <map>\n#include <string_view>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nTEST(ConstexprTesting, Basic) {\n  using absl::meta_internal::HasConstexprEvaluation;\n\n  EXPECT_TRUE(HasConstexprEvaluation([] {}));\n  static constexpr int const_global = 7;\n  EXPECT_TRUE(HasConstexprEvaluation([] { return const_global; }));\n  EXPECT_TRUE(HasConstexprEvaluation([] { return 0; }));\n  EXPECT_TRUE(HasConstexprEvaluation([] { return std::string_view{}; }));\n\n  static int nonconst_global;\n  EXPECT_FALSE(HasConstexprEvaluation([] { return nonconst_global; }));\n  EXPECT_FALSE(HasConstexprEvaluation([] { std::abort(); }));\n  EXPECT_FALSE(HasConstexprEvaluation([] { return std::map<int, int>(); }));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/meta/internal/requires.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_META_INTERNAL_REQUIRES_H_\n#define ABSL_META_INTERNAL_REQUIRES_H_\n\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace meta_internal {\n\n// C++17 port of the C++20 `requires` expressions.\n// It allows easy inline test of properties of types in template code.\n// https://en.cppreference.com/w/cpp/language/constraints#Requires_expressions\n//\n// Example usage:\n//\n// if constexpr (Requires<T>([](auto&& x) -> decltype(x.foo()) {})) {\n//   // T has foo()\n//   return t.foo();\n// } else if constexpr (Requires<T>([](auto&& x) -> decltype(Bar(x)) {})) {\n//   // Can call Bar with T\n//   return Bar(t);\n// } else if constexpr (Requires<T, U>(\n//     // Can test expression with multiple inputs\n//     [](auto&& x, auto&& y) -> decltype(x + y) {})) {\n//   return t + t2;\n// }\n//\n// The `Requires` function takes a list of types and a generic lambda where all\n// arguments are of type `auto&&`. The lambda is never actually invoked and the\n// body must be empty.\n// When used this way, `Requires` returns whether the expression inside\n// `decltype` is well-formed, when the lambda parameters have the types that\n// are specified by the corresponding template arguments.\n//\n// NOTE: C++17 does not allow lambdas in template parameters, which means that\n// code like the following is _not_ valid in C++17:\n//\n//  template <typename T,\n//            typename = std::enable_if_t<Requires<T>(\n//              [] (auto&& v) -> decltype(<expr>) {})>>\n//\ntemplate <typename... T, typename F>\nconstexpr bool Requires(F) {\n  return std::is_invocable_v<F, T...>;\n}\n\n}  // namespace meta_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_META_INTERNAL_REQUIRES_H_\n"
  },
  {
    "path": "absl/meta/internal/requires_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/meta/internal/requires.h\"\n\n#include <string>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nTEST(RequiresTest, SimpleLambdasWork) {\n  static_assert(absl::meta_internal::Requires([] {}));\n  static_assert(absl::meta_internal::Requires<int>([](auto&&) {}));\n  static_assert(\n      absl::meta_internal::Requires<int, char>([](auto&&, auto&&) {}));\n}\n\ntemplate <typename T>\ninline constexpr bool has_cstr =\n    absl::meta_internal::Requires<T>([](auto&& x) -> decltype(x.c_str()) {});\n\ntemplate <typename T, typename U>\ninline constexpr bool have_plus = absl::meta_internal::Requires<T, U>(\n    [](auto&& x, auto&& y) -> decltype(x + y) {});\n\nTEST(RequiresTest, CanTestProperties) {\n  static_assert(has_cstr<std::string>);\n  static_assert(!has_cstr<std::vector<int>>);\n\n  static_assert(have_plus<int, double>);\n  static_assert(have_plus<std::string, std::string>);\n  static_assert(!have_plus<std::string, double>);\n}\n\nTEST(RequiresTest, WorksWithUnmovableTypes) {\n  struct S {\n    S(const S&) = delete;\n    int foo() { return 0; }\n  };\n  static_assert(\n      absl::meta_internal::Requires<S>([](auto&& x) -> decltype(x.foo()) {}));\n  static_assert(\n      !absl::meta_internal::Requires<S>([](auto&& x) -> decltype(x.bar()) {}));\n}\n\nTEST(RequiresTest, WorksWithArrays) {\n  static_assert(\n      absl::meta_internal::Requires<int[2]>([](auto&& x) -> decltype(x[1]) {}));\n  static_assert(\n      !absl::meta_internal::Requires<int[2]>([](auto&& x) -> decltype(-x) {}));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/meta/type_traits.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// type_traits.h\n// -----------------------------------------------------------------------------\n//\n// This file contains C++11-compatible versions of standard <type_traits> API\n// functions for determining the characteristics of types. Such traits can\n// support type inference, classification, and transformation, as well as\n// make it easier to write templates based on generic type behavior.\n//\n// See https://en.cppreference.com/w/cpp/header/type_traits\n//\n// WARNING: use of many of the constructs in this header will count as \"complex\n// template metaprogramming\", so before proceeding, please carefully consider\n// https://google.github.io/styleguide/cppguide.html#Template_metaprogramming\n//\n// WARNING: using template metaprogramming to detect or depend on API\n// features is brittle and not guaranteed. Neither the standard library nor\n// Abseil provides any guarantee that APIs are stable in the face of template\n// metaprogramming. Use with caution.\n#ifndef ABSL_META_TYPE_TRAITS_H_\n#define ABSL_META_TYPE_TRAITS_H_\n\n#include <cstddef>\n#include <functional>\n#include <string>\n#include <string_view>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n#ifdef __cpp_lib_span\n#include <span>  // NOLINT(build/c++20)\n#endif\n\n// Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17\n// feature.\n#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)\n#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__\n#else  // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)\n#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)\n#endif  // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace type_traits_internal {\n\ntemplate <typename... Ts>\nstruct VoidTImpl {\n  using type = void;\n};\n\n////////////////////////////////\n// Library Fundamentals V2 TS //\n////////////////////////////////\n\n// NOTE: The `is_detected` family of templates here differ from the library\n// fundamentals specification in that for library fundamentals, `Op<Args...>` is\n// evaluated as soon as the type `is_detected<Op, Args...>` undergoes\n// substitution, regardless of whether or not the `::value` is accessed. That\n// is inconsistent with all other standard traits and prevents lazy evaluation\n// in larger contexts (such as if the `is_detected` check is a trailing argument\n// of a `conjunction`. This implementation opts to instead be lazy in the same\n// way that the standard traits are (this \"defect\" of the detection idiom\n// specifications has been reported).\n\ntemplate <class Enabler, template <class...> class Op, class... Args>\nstruct is_detected_impl {\n  using type = std::false_type;\n};\n\ntemplate <template <class...> class Op, class... Args>\nstruct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {\n  using type = std::true_type;\n};\n\ntemplate <template <class...> class Op, class... Args>\nstruct is_detected : is_detected_impl<void, Op, Args...>::type {};\n\n}  // namespace type_traits_internal\n\n// void_t()\n//\n// Ignores the type of any its arguments and returns `void`. In general, this\n// metafunction allows you to create a general case that maps to `void` while\n// allowing specializations that map to specific types.\n//\n// This metafunction is not 100% compatible with the C++17 `std::void_t`\n// metafunction. It has slightly different behavior, such as when ordering\n// partial specializations. It is recommended to use `std::void_t` instead.\ntemplate <typename... Ts>\nusing void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;\n\n// Historical note: Abseil once provided implementations of these type traits\n// for platforms that lacked full support. New code should prefer to use the\n// std variants.\n//\n// See the documentation for the STL <type_traits> header for more information:\n// https://en.cppreference.com/w/cpp/header/type_traits\nusing std::add_const_t;\nusing std::add_cv_t;\nusing std::add_lvalue_reference_t;\nusing std::add_pointer_t;\nusing std::add_rvalue_reference_t;\nusing std::add_volatile_t;\nusing std::common_type_t;\nusing std::conditional_t;\nusing std::conjunction;\nusing std::decay_t;\nusing std::enable_if_t;\nusing std::disjunction;\nusing std::is_copy_assignable;\nusing std::is_function;\nusing std::is_move_assignable;\nusing std::is_trivially_copy_assignable;\nusing std::is_trivially_copy_constructible;\nusing std::is_trivially_default_constructible;\nusing std::is_trivially_destructible;\nusing std::is_trivially_move_assignable;\nusing std::is_trivially_move_constructible;\nusing std::make_signed_t;\nusing std::make_unsigned_t;\nusing std::negation;\nusing std::remove_all_extents_t;\nusing std::remove_const_t;\nusing std::remove_cv_t;\nusing std::remove_extent_t;\nusing std::remove_pointer_t;\nusing std::remove_reference_t;\nusing std::remove_volatile_t;\nusing std::underlying_type_t;\n\n#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L\ntemplate <typename T>\nusing remove_cvref = std::remove_cvref<T>;\n\ntemplate <typename T>\nusing remove_cvref_t = typename std::remove_cvref<T>::type;\n#else\n// remove_cvref()\n//\n// C++11 compatible implementation of std::remove_cvref which was added in\n// C++20.\ntemplate <typename T>\nstruct remove_cvref {\n  using type =\n      typename std::remove_cv<typename std::remove_reference<T>::type>::type;\n};\n\ntemplate <typename T>\nusing remove_cvref_t = typename remove_cvref<T>::type;\n#endif\n\n#if defined(__cpp_lib_type_identity) && __cpp_lib_type_identity >= 201806L\ntemplate <typename T>\nusing type_identity = std::type_identity<T>;\n\ntemplate <typename T>\nusing type_identity_t = std::type_identity_t<T>;\n#else\n// type_identity\n//\n// Back-fill of C++20's `std::type_identity`.\ntemplate <typename T>\nstruct type_identity {\n  typedef T type;\n};\n\n// type_identity_t\n//\n// Back-fill of C++20's `std::type_identity_t`.\ntemplate <typename T>\nusing type_identity_t = typename type_identity<T>::type;\n#endif\n\nnamespace type_traits_internal {\n\n#if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \\\n    (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)\n// std::result_of is deprecated (C++17) or removed (C++20)\ntemplate <typename>\nstruct result_of;\ntemplate <typename F, typename... Args>\nstruct result_of<F(Args...)> : std::invoke_result<F, Args...> {};\n#else\ntemplate <typename F>\nusing result_of = std::result_of<F>;\n#endif\n\n}  // namespace type_traits_internal\n\ntemplate <typename F>\nusing result_of_t = typename type_traits_internal::result_of<F>::type;\n\nnamespace type_traits_internal {\n\ntemplate <typename Key, typename = void>\nstruct IsHashable : std::false_type {};\n\ntemplate <typename Key>\nstruct IsHashable<\n    Key,\n    absl::enable_if_t<std::is_convertible<\n        decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),\n        std::size_t>::value>> : std::true_type {};\n\nstruct AssertHashEnabledHelper {\n private:\n  static void Sink(...) {}\n  struct NAT {};\n\n  template <class Key>\n  static auto GetReturnType(int)\n      -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));\n  template <class Key>\n  static NAT GetReturnType(...);\n\n  template <class Key>\n  static std::nullptr_t DoIt() {\n    static_assert(IsHashable<Key>::value,\n                  \"std::hash<Key> does not provide a call operator\");\n    static_assert(\n        std::is_default_constructible<std::hash<Key>>::value,\n        \"std::hash<Key> must be default constructible when it is enabled\");\n    static_assert(\n        std::is_copy_constructible<std::hash<Key>>::value,\n        \"std::hash<Key> must be copy constructible when it is enabled\");\n    static_assert(absl::is_copy_assignable<std::hash<Key>>::value,\n                  \"std::hash<Key> must be copy assignable when it is enabled\");\n    // is_destructible is unchecked as it's implied by each of the\n    // is_constructible checks.\n    using ReturnType = decltype(GetReturnType<Key>(0));\n    static_assert(std::is_same<ReturnType, NAT>::value ||\n                      std::is_same<ReturnType, size_t>::value,\n                  \"std::hash<Key> must return size_t\");\n    return nullptr;\n  }\n\n  template <class... Ts>\n  friend void AssertHashEnabled();\n};\n\ntemplate <class... Ts>\ninline void AssertHashEnabled() {\n  using Helper = AssertHashEnabledHelper;\n  Helper::Sink(Helper::DoIt<Ts>()...);\n}\n\n}  // namespace type_traits_internal\n\n// An internal namespace that is required to implement the C++17 swap traits.\n// It is not further nested in type_traits_internal to avoid long symbol names.\nnamespace swap_internal {\n\n// Necessary for the traits.\nusing std::swap;\n\n// This declaration prevents global `swap` and `absl::swap` overloads from being\n// considered unless ADL picks them up.\nvoid swap();\n\ntemplate <class T>\nusing IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));\n\n// NOTE: This dance with the default template parameter is for MSVC.\ntemplate <class T,\n          class IsNoexcept = std::integral_constant<\n              bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>\nusing IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;\n\n// IsSwappable\n//\n// Determines whether the standard swap idiom is a valid expression for\n// arguments of type `T`.\ntemplate <class T>\nstruct IsSwappable\n    : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};\n\n// IsNothrowSwappable\n//\n// Determines whether the standard swap idiom is a valid expression for\n// arguments of type `T` and is noexcept.\ntemplate <class T>\nstruct IsNothrowSwappable\n    : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};\n\n// Swap()\n//\n// Performs the swap idiom from a namespace where valid candidates may only be\n// found in `std` or via ADL.\ntemplate <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>\nvoid Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {\n  swap(lhs, rhs);\n}\n\n// StdSwapIsUnconstrained\n//\n// Some standard library implementations are broken in that they do not\n// constrain `std::swap`. This will effectively tell us if we are dealing with\n// one of those implementations.\nusing StdSwapIsUnconstrained = IsSwappable<void()>;\n\n}  // namespace swap_internal\n\nnamespace type_traits_internal {\n\n// Make the swap-related traits/function accessible from this namespace.\nusing swap_internal::IsNothrowSwappable;\nusing swap_internal::IsSwappable;\nusing swap_internal::StdSwapIsUnconstrained;\nusing swap_internal::Swap;\n\n}  // namespace type_traits_internal\n\n// absl::is_trivially_relocatable<T>\n//\n// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2786r11.html\n//\n// Detects whether a type is known to be \"trivially relocatable\" -- meaning it\n// can be relocated from one place to another as if by memcpy/memmove.\n// This implies that its object representation doesn't depend on its address,\n// and also none of its special member functions do anything strange.\n//\n// Note that when relocating the caller code should ensure that if the object is\n// polymorphic, the dynamic type is of the most derived type. Padding bytes\n// should not be copied.\n//\n// This trait is conservative. If it's true then the type is definitely\n// trivially relocatable, but if it's false then the type may or may not be. For\n// example, std::vector<int> is trivially relocatable on every known STL\n// implementation, but absl::is_trivially_relocatable<std::vector<int>> remains\n// false.\n//\n// Example:\n//\n// if constexpr (absl::is_trivially_relocatable<T>::value) {\n//   memcpy(new_location, old_location, sizeof(T));\n// } else {\n//   new(new_location) T(std::move(*old_location));\n//   old_location->~T();\n// }\n//\n// Upstream documentation:\n//\n// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__builtin_is_cpp_trivially_relocatable\n//\n// Clang on Windows has the builtin, but it falsely claims types with a\n// user-provided destructor are trivial (http://b/275003464). So we opt out\n// there.\n//\n// TODO(b/275003464): remove the opt-out once the bug is fixed.\n//\n// Starting with Xcode 15, the Apple compiler will falsely say a type\n// with a user-provided move constructor is trivially relocatable\n// (b/324278148). We will opt out without a version check, due to\n// the fluidity of Apple versions.\n//\n// TODO(b/324278148): If all versions we use have the bug fixed, then\n// remove the condition.\n//\n// Clang on all platforms fails to detect that a type with a user-provided\n// move-assignment operator is not trivially relocatable so we also check for\n// is_trivially_move_assignable for Clang.\n//\n// TODO(b/325479096): Remove the Clang is_trivially_move_assignable version once\n// Clang's behavior is fixed.\n//\n// According to https://github.com/abseil/abseil-cpp/issues/1479, this does not\n// work with NVCC either.\n#if ABSL_HAVE_BUILTIN(__builtin_is_cpp_trivially_relocatable)\n// https://github.com/llvm/llvm-project/pull/127636#pullrequestreview-2637005293\n// In the current implementation, __builtin_is_cpp_trivially_relocatable will\n// only return true for types that are trivially relocatable according to the\n// standard. Notably, this means that marking a type [[clang::trivial_abi]] aka\n// ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI will have no effect on this trait.\ntemplate <class T>\nstruct is_trivially_relocatable\n    : std::integral_constant<bool, __builtin_is_cpp_trivially_relocatable(T)> {\n};\n#elif ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && defined(__clang__) && \\\n    !(defined(_WIN32) || defined(_WIN64)) && !defined(__APPLE__) &&          \\\n    !defined(__NVCC__)\n// https://github.com/llvm/llvm-project/pull/139061\n//  __is_trivially_relocatable is deprecated.\n// TODO(b/325479096): Remove this case.\ntemplate <class T>\nstruct is_trivially_relocatable\n    : std::integral_constant<\n          bool, std::is_trivially_copyable<T>::value ||\n                    (__is_trivially_relocatable(T) &&\n                     std::is_trivially_move_assignable<T>::value)> {};\n#else\n// Otherwise we use a fallback that detects only those types we can feasibly\n// detect. Any type that is trivially copyable is by definition trivially\n// relocatable.\ntemplate <class T>\nstruct is_trivially_relocatable : std::is_trivially_copyable<T> {};\n#endif\n\n// absl::is_constant_evaluated()\n//\n// Detects whether the function call occurs within a constant-evaluated context.\n// Returns true if the evaluation of the call occurs within the evaluation of an\n// expression or conversion that is manifestly constant-evaluated; otherwise\n// returns false.\n//\n// This function is implemented in terms of `std::is_constant_evaluated` for\n// c++20 and up. For older c++ versions, the function is implemented in terms\n// of `__builtin_is_constant_evaluated` if available, otherwise the function\n// will fail to compile.\n//\n// Applications can inspect `ABSL_HAVE_CONSTANT_EVALUATED` at compile time\n// to check if this function is supported.\n//\n// Example:\n//\n// constexpr MyClass::MyClass(int param) {\n// #ifdef ABSL_HAVE_CONSTANT_EVALUATED\n//   if (!absl::is_constant_evaluated()) {\n//     ABSL_LOG(INFO) << \"MyClass(\" << param << \")\";\n//   }\n// #endif  // ABSL_HAVE_CONSTANT_EVALUATED\n// }\n//\n// Upstream documentation:\n//\n// http://en.cppreference.com/w/cpp/types/is_constant_evaluated\n// http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#:~:text=__builtin_is_constant_evaluated\n//\n#if defined(ABSL_HAVE_CONSTANT_EVALUATED)\nconstexpr bool is_constant_evaluated() noexcept {\n#ifdef __cpp_lib_is_constant_evaluated\n  return std::is_constant_evaluated();\n#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)\n  return __builtin_is_constant_evaluated();\n#endif\n}\n#endif  // ABSL_HAVE_CONSTANT_EVALUATED\n\nnamespace type_traits_internal {\n\n// Detects if a class's definition has declared itself to be an owner by\n// declaring\n//   using absl_internal_is_view = std::false_type;\n// as a member.\n// Types that don't want either must either omit this declaration entirely, or\n// (if e.g. inheriting from a base class) define the member to something that\n// isn't a Boolean trait class, such as `void`.\n// Do not specialize or use this directly. It's an implementation detail.\ntemplate <typename T, typename = void>\nstruct IsOwnerImpl : std::false_type {\n  static_assert(std::is_same<T, absl::remove_cvref_t<T>>::value,\n                \"type must lack qualifiers\");\n};\n\ntemplate <typename T>\nstruct IsOwnerImpl<\n    T,\n    std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>\n    : absl::negation<typename T::absl_internal_is_view> {};\n\n// A trait to determine whether a type is an owner.\n// Do *not* depend on the correctness of this trait for correct code behavior.\n// It is only a safety feature and its value may change in the future.\n// Do not specialize this; instead, define the member trait inside your type so\n// that it can be auto-detected, and to prevent ODR violations.\n// If it ever becomes possible to detect [[gsl::Owner]], we should leverage it:\n// https://wg21.link/p1179\ntemplate <typename T>\nstruct IsOwner : IsOwnerImpl<T> {};\n\n// This allows incomplete types to be used for associative containers, and also\n// expands the set of types we can handle to include std::pair.\ntemplate <typename T1, typename T2>\nstruct IsOwner<std::pair<T1, T2>>\n    : std::integral_constant<\n          bool, std::conditional_t<std::is_reference_v<T1>, std::false_type,\n                                   IsOwner<std::remove_cv_t<T1>>>::value &&\n                    std::conditional_t<std::is_reference_v<T2>, std::false_type,\n                                       IsOwner<std::remove_cv_t<T2>>>::value> {\n};\n\ntemplate <typename T, typename Traits, typename Alloc>\nstruct IsOwner<std::basic_string<T, Traits, Alloc>> : std::true_type {};\n\ntemplate <typename T, typename Alloc>\nstruct IsOwner<std::vector<T, Alloc>> : std::true_type {};\n\n// Detects if a class's definition has declared itself to be a view by declaring\n//   using absl_internal_is_view = std::true_type;\n// as a member.\n// Do not specialize or use this directly.\ntemplate <typename T, typename = void>\nstruct IsViewImpl : std::false_type {\n  static_assert(std::is_same<T, absl::remove_cvref_t<T>>::value,\n                \"type must lack qualifiers\");\n};\n\ntemplate <typename T>\nstruct IsViewImpl<\n    T,\n    std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>\n    : T::absl_internal_is_view {};\n\n// A trait to determine whether a type is a view.\n// Do *not* depend on the correctness of this trait for correct code behavior.\n// It is only a safety feature, and its value may change in the future.\n// Do not specialize this trait. Instead, define the member\n//   using absl_internal_is_view = std::true_type;\n// in your class to allow its detection while preventing ODR violations.\n// If it ever becomes possible to detect [[gsl::Pointer]], we should leverage\n// it: https://wg21.link/p1179\ntemplate <typename T>\nstruct IsView : std::integral_constant<bool, std::is_pointer<T>::value ||\n                                                 IsViewImpl<T>::value> {};\n\n// This allows incomplete types to be used for associative containers, and also\n// expands the set of types we can handle to include std::pair.\ntemplate <typename T1, typename T2>\nstruct IsView<std::pair<T1, T2>>\n    : std::integral_constant<bool, IsView<std::remove_cv_t<T1>>::value &&\n                                       IsView<std::remove_cv_t<T2>>::value> {};\n\ntemplate <typename Char, typename Traits>\nstruct IsView<std::basic_string_view<Char, Traits>> : std::true_type {};\n\n#ifdef __cpp_lib_span\ntemplate <typename T>\nstruct IsView<std::span<T>> : std::true_type {};\n#endif\n\n// Determines whether the assignment of the given types is lifetime-bound.\n// Do *not* depend on the correctness of this trait for correct code behavior.\n// It is only a safety feature and its value may change in the future.\n// If it ever becomes possible to detect [[clang::lifetimebound]] directly,\n// we should change the implementation to leverage that.\n// Until then, we consider an assignment from an \"owner\" (such as std::string)\n// to a \"view\" (such as std::string_view) to be a lifetime-bound assignment.\ntemplate <typename T, typename U>\nusing IsLifetimeBoundAssignment = absl::conjunction<\n    std::integral_constant<bool, !std::is_lvalue_reference<U>::value>,\n    IsOwner<absl::remove_cvref_t<U>>, IsView<absl::remove_cvref_t<T>>>;\n\n}  // namespace type_traits_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_META_TYPE_TRAITS_H_\n"
  },
  {
    "path": "absl/meta/type_traits_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/meta/type_traits.h\"\n\n#include <cstdint>\n#include <string>\n#include <string_view>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace {\n\nusing ::testing::StaticAssertTypeEq;\n\ntemplate <typename T>\nusing IsOwnerAndNotView =\n    absl::conjunction<absl::type_traits_internal::IsOwner<T>,\n                      absl::negation<absl::type_traits_internal::IsView<T>>>;\n\nstatic_assert(\n    IsOwnerAndNotView<std::pair<std::vector<int>, std::string>>::value,\n    \"pair of owners is an owner, not a view\");\nstatic_assert(IsOwnerAndNotView<std::vector<int>>::value,\n              \"vector is an owner, not a view\");\nstatic_assert(IsOwnerAndNotView<std::string>::value,\n              \"string is an owner, not a view\");\nstatic_assert(IsOwnerAndNotView<std::wstring>::value,\n              \"wstring is an owner, not a view\");\nstatic_assert(!IsOwnerAndNotView<std::string_view>::value,\n              \"string_view is a view, not an owner\");\nstatic_assert(!IsOwnerAndNotView<std::wstring_view>::value,\n              \"wstring_view is a view, not an owner\");\n\ntemplate <class T, class U>\nstruct simple_pair {\n  T first;\n  U second;\n};\n\nstruct Dummy {};\n\nstruct ReturnType {};\nstruct ConvertibleToReturnType {\n  operator ReturnType() const;  // NOLINT\n};\n\n// Unique types used as parameter types for testing the detection idiom.\nstruct StructA {};\nstruct StructB {};\nstruct StructC {};\n\nstruct TypeWithBarFunction {\n  template <class T,\n            absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>\n  ReturnType bar(T&&, const StructB&, StructC&&) &&;  // NOLINT\n};\n\nstruct TypeWithBarFunctionAndConvertibleReturnType {\n  template <class T,\n            absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>\n  ConvertibleToReturnType bar(T&&, const StructB&, StructC&&) &&;  // NOLINT\n};\n\ntemplate <class Class, class... Ts>\nusing BarIsCallableImpl =\n    decltype(std::declval<Class>().bar(std::declval<Ts>()...));\n\ntemplate <class Class, class... T>\nusing BarIsCallable =\n    absl::type_traits_internal::is_detected<BarIsCallableImpl, Class, T...>;\n\n// NOTE: Test of detail type_traits_internal::is_detected.\nTEST(IsDetectedTest, BasicUsage) {\n  EXPECT_TRUE((BarIsCallable<TypeWithBarFunction, StructA&, const StructB&,\n                             StructC>::value));\n  EXPECT_TRUE(\n      (BarIsCallable<TypeWithBarFunction, StructA&, StructB&, StructC>::value));\n  EXPECT_TRUE(\n      (BarIsCallable<TypeWithBarFunction, StructA&, StructB, StructC>::value));\n\n  EXPECT_FALSE((BarIsCallable<int, StructA&, const StructB&, StructC>::value));\n  EXPECT_FALSE((BarIsCallable<TypeWithBarFunction&, StructA&, const StructB&,\n                              StructC>::value));\n  EXPECT_FALSE((BarIsCallable<TypeWithBarFunction, StructA, const StructB&,\n                              StructC>::value));\n}\n\nTEST(VoidTTest, BasicUsage) {\n  StaticAssertTypeEq<void, absl::void_t<Dummy>>();\n  StaticAssertTypeEq<void, absl::void_t<Dummy, Dummy, Dummy>>();\n}\n\nTEST(TypeTraitsTest, TestRemoveCVRef) {\n  EXPECT_TRUE(\n      (std::is_same<typename absl::remove_cvref<int>::type, int>::value));\n  EXPECT_TRUE(\n      (std::is_same<typename absl::remove_cvref<int&>::type, int>::value));\n  EXPECT_TRUE(\n      (std::is_same<typename absl::remove_cvref<int&&>::type, int>::value));\n  EXPECT_TRUE((\n      std::is_same<typename absl::remove_cvref<const int&>::type, int>::value));\n  EXPECT_TRUE(\n      (std::is_same<typename absl::remove_cvref<int*>::type, int*>::value));\n  // Does not remove const in this case.\n  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int*>::type,\n                            const int*>::value));\n  EXPECT_TRUE(\n      (std::is_same<typename absl::remove_cvref<int[2]>::type, int[2]>::value));\n  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int(&)[2]>::type,\n                            int[2]>::value));\n  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int(&&)[2]>::type,\n                            int[2]>::value));\n  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int[2]>::type,\n                            int[2]>::value));\n  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int(&)[2]>::type,\n                            int[2]>::value));\n  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int(&&)[2]>::type,\n                            int[2]>::value));\n}\n\nTEST(TypeTraitsTest, TestTypeIdentity) {\n  EXPECT_TRUE((std::is_same_v<typename absl::type_identity<int>::type, int>));\n  EXPECT_TRUE((std::is_same_v<absl::type_identity_t<int>, int>));\n  EXPECT_TRUE((std::is_same_v<typename absl::type_identity<int&>::type, int&>));\n  EXPECT_TRUE((std::is_same_v<absl::type_identity_t<int&>, int&>));\n\n  EXPECT_FALSE(\n      (std::is_same_v<typename absl::type_identity<int64_t>::type, int32_t>));\n  EXPECT_FALSE((std::is_same_v<absl::type_identity_t<int64_t>, int32_t>));\n}\n\nstruct TypeA {};\nstruct TypeB {};\nstruct TypeC {};\nstruct TypeD {};\n\ntemplate <typename T>\nstruct Wrap {};\n\nenum class TypeEnum { A, B, C, D };\n\nstruct GetTypeT {\n  template <typename T,\n            absl::enable_if_t<std::is_same<T, TypeA>::value, int> = 0>\n  TypeEnum operator()(Wrap<T>) const {\n    return TypeEnum::A;\n  }\n\n  template <typename T,\n            absl::enable_if_t<std::is_same<T, TypeB>::value, int> = 0>\n  TypeEnum operator()(Wrap<T>) const {\n    return TypeEnum::B;\n  }\n\n  template <typename T,\n            absl::enable_if_t<std::is_same<T, TypeC>::value, int> = 0>\n  TypeEnum operator()(Wrap<T>) const {\n    return TypeEnum::C;\n  }\n\n  // NOTE: TypeD is intentionally not handled\n} constexpr GetType = {};\n\nstruct GetTypeExtT {\n  template <typename T>\n  absl::result_of_t<const GetTypeT&(T)> operator()(T&& arg) const {\n    return GetType(std::forward<T>(arg));\n  }\n\n  TypeEnum operator()(Wrap<TypeD>) const { return TypeEnum::D; }\n} constexpr GetTypeExt = {};\n\nTEST(TypeTraitsTest, TestResultOf) {\n  EXPECT_EQ(TypeEnum::A, GetTypeExt(Wrap<TypeA>()));\n  EXPECT_EQ(TypeEnum::B, GetTypeExt(Wrap<TypeB>()));\n  EXPECT_EQ(TypeEnum::C, GetTypeExt(Wrap<TypeC>()));\n  EXPECT_EQ(TypeEnum::D, GetTypeExt(Wrap<TypeD>()));\n}\n\nnamespace adl_namespace {\n\nstruct DeletedSwap {};\n\nvoid swap(DeletedSwap&, DeletedSwap&) = delete;\n\nstruct SpecialNoexceptSwap {\n  SpecialNoexceptSwap(SpecialNoexceptSwap&&) {}\n  SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; }\n  ~SpecialNoexceptSwap() = default;\n};\n\nvoid swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {}\n\n}  // namespace adl_namespace\n\nTEST(TypeTraitsTest, IsSwappable) {\n  using absl::type_traits_internal::IsSwappable;\n  using absl::type_traits_internal::StdSwapIsUnconstrained;\n\n  EXPECT_TRUE(IsSwappable<int>::value);\n\n  struct S {};\n  EXPECT_TRUE(IsSwappable<S>::value);\n\n  struct NoConstruct {\n    NoConstruct(NoConstruct&&) = delete;\n    NoConstruct& operator=(NoConstruct&&) { return *this; }\n    ~NoConstruct() = default;\n  };\n\n  EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value);\n  struct NoAssign {\n    NoAssign(NoAssign&&) {}\n    NoAssign& operator=(NoAssign&&) = delete;\n    ~NoAssign() = default;\n  };\n\n  EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value);\n\n  EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value);\n\n  EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value);\n}\n\nTEST(TypeTraitsTest, IsNothrowSwappable) {\n  using absl::type_traits_internal::IsNothrowSwappable;\n  using absl::type_traits_internal::StdSwapIsUnconstrained;\n\n  EXPECT_TRUE(IsNothrowSwappable<int>::value);\n\n  struct NonNoexceptMoves {\n    NonNoexceptMoves(NonNoexceptMoves&&) {}\n    NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; }\n    ~NonNoexceptMoves() = default;\n  };\n\n  EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value);\n\n  struct NoConstruct {\n    NoConstruct(NoConstruct&&) = delete;\n    NoConstruct& operator=(NoConstruct&&) { return *this; }\n    ~NoConstruct() = default;\n  };\n\n  EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value);\n\n  struct NoAssign {\n    NoAssign(NoAssign&&) {}\n    NoAssign& operator=(NoAssign&&) = delete;\n    ~NoAssign() = default;\n  };\n\n  EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value);\n\n  EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value);\n\n  EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);\n}\n\nTEST(TriviallyRelocatable, PrimitiveTypes) {\n  static_assert(absl::is_trivially_relocatable<int>::value, \"\");\n  static_assert(absl::is_trivially_relocatable<char>::value, \"\");\n  static_assert(absl::is_trivially_relocatable<void*>::value, \"\");\n}\n\n// User-defined types can be trivially relocatable as long as they don't have a\n// user-provided move constructor or destructor.\nTEST(TriviallyRelocatable, UserDefinedTriviallyRelocatable) {\n  struct S {\n    int x;\n    int y;\n  };\n\n  static_assert(absl::is_trivially_relocatable<S>::value, \"\");\n}\n\n// A user-provided move constructor disqualifies a type from being trivially\n// relocatable.\nTEST(TriviallyRelocatable, UserProvidedMoveConstructor) {\n  struct S {\n    S(S&&) {}  // NOLINT(modernize-use-equals-default)\n  };\n\n  static_assert(!absl::is_trivially_relocatable<S>::value, \"\");\n}\n\n// A user-provided copy constructor disqualifies a type from being trivially\n// relocatable.\nTEST(TriviallyRelocatable, UserProvidedCopyConstructor) {\n  struct S {\n    S(const S&) {}  // NOLINT(modernize-use-equals-default)\n  };\n\n  static_assert(!absl::is_trivially_relocatable<S>::value, \"\");\n}\n\n// A user-provided copy assignment operator disqualifies a type from\n// being trivially relocatable.\nTEST(TriviallyRelocatable, UserProvidedCopyAssignment) {\n  struct S {\n    S(const S&) = default;\n    S& operator=(const S&) {  // NOLINT(modernize-use-equals-default)\n      return *this;\n    }\n  };\n\n  static_assert(!absl::is_trivially_relocatable<S>::value, \"\");\n}\n\n// A user-provided move assignment operator disqualifies a type from\n// being trivially relocatable.\nTEST(TriviallyRelocatable, UserProvidedMoveAssignment) {\n  struct S {\n    S(S&&) = default;\n    S& operator=(S&&) { return *this; }  // NOLINT(modernize-use-equals-default)\n  };\n\n  static_assert(!absl::is_trivially_relocatable<S>::value, \"\");\n}\n\n// A user-provided destructor disqualifies a type from being trivially\n// relocatable.\nTEST(TriviallyRelocatable, UserProvidedDestructor) {\n  struct S {\n    ~S() {}  // NOLINT(modernize-use-equals-default)\n  };\n\n  static_assert(!absl::is_trivially_relocatable<S>::value, \"\");\n}\n\n#ifdef ABSL_HAVE_CONSTANT_EVALUATED\n\nconstexpr int64_t NegateIfConstantEvaluated(int64_t i) {\n  if (absl::is_constant_evaluated()) {\n    return -i;\n  } else {\n    return i;\n  }\n}\n\n#endif  // ABSL_HAVE_CONSTANT_EVALUATED\n\nTEST(IsConstantEvaluated, is_constant_evaluated) {\n#ifdef ABSL_HAVE_CONSTANT_EVALUATED\n  constexpr int64_t constant = NegateIfConstantEvaluated(42);\n  EXPECT_EQ(constant, -42);\n\n  int64_t now = absl::ToUnixSeconds(absl::Now());\n  int64_t not_constant = NegateIfConstantEvaluated(now);\n  EXPECT_EQ(not_constant, now);\n\n  static int64_t const_init = NegateIfConstantEvaluated(42);\n  EXPECT_EQ(const_init, -42);\n#else\n  GTEST_SKIP() << \"absl::is_constant_evaluated is not defined\";\n#endif  // ABSL_HAVE_CONSTANT_EVALUATED\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/numeric/BUILD.bazel",
    "content": "# Copyright 2018 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"bits\",\n    hdrs = [\n        \"bits.h\",\n        \"internal/bits.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n    ],\n)\n\ncc_binary(\n    name = \"bits_benchmark\",\n    testonly = True,\n    srcs = [\"bits_benchmark.cc\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bits\",\n        \"//absl/base:core_headers\",\n        \"//absl/random\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"bits_test\",\n    size = \"small\",\n    srcs = [\n        \"bits_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bits\",\n        \"//absl/random\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"int128\",\n    srcs = [\n        \"int128.cc\",\n        \"int128_have_intrinsic.inc\",\n        \"int128_no_intrinsic.inc\",\n    ],\n    hdrs = [\"int128.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bits\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/types:compare\",\n    ],\n)\n\ncc_test(\n    name = \"int128_test\",\n    size = \"small\",\n    srcs = [\n        \"int128_stream_test.cc\",\n        \"int128_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":int128\",\n        \"//absl/base\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/types:compare\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"int128_benchmark\",\n    testonly = True,\n    srcs = [\"int128_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":int128\",\n        \"//absl/base:config\",\n        \"//absl/random\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"representation\",\n    hdrs = [\n        \"internal/representation.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n"
  },
  {
    "path": "absl/numeric/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    bits\n  HDRS\n    \"bits.h\"\n    \"internal/bits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::endian\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    bits_test\n  SRCS\n    \"bits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::bits\n    absl::core_headers\n    absl::random_random\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    int128\n  HDRS\n    \"int128.h\"\n  SRCS\n    \"int128.cc\"\n    \"int128_have_intrinsic.inc\"\n    \"int128_no_intrinsic.inc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::compare\n    absl::config\n    absl::core_headers\n    absl::bits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    int128_test\n  SRCS\n    \"int128_stream_test.cc\"\n    \"int128_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::int128\n    absl::base\n    absl::compare\n    absl::hash_testing\n    absl::type_traits\n    absl::strings\n    GTest::gmock_main\n)\n\n# component target\nabsl_cc_library(\n  NAME\n    numeric\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::int128\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    numeric_representation\n  HDRS\n    \"internal/representation.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n"
  },
  {
    "path": "absl/numeric/bits.h",
    "content": "// Copyright 2020 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: bits.h\n// -----------------------------------------------------------------------------\n//\n// This file contains implementations of C++20's bitwise math functions, as\n// defined by:\n//\n// P0553R4:\n//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html\n// P0556R3:\n//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html\n// P1355R2:\n//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html\n// P1956R1:\n//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf\n// P0463R1\n//  https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0463r1.html\n// P1272R4\n//  https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1272r4.html\n//\n// When using a standard library that implements these functions, we use the\n// standard library's implementation.\n\n#ifndef ABSL_NUMERIC_BITS_H_\n#define ABSL_NUMERIC_BITS_H_\n\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <bit>\n#endif\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/numeric/internal/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// https://github.com/llvm/llvm-project/issues/64544\n// libc++ had the wrong signature for std::rotl and std::rotr\n// prior to libc++ 18.0.\n//\n#if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) &&     \\\n    (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 180000)\nusing std::rotl;\nusing std::rotr;\n\n#else\n\n// Rotating functions\ntemplate <class T>\n[[nodiscard]] constexpr\n    typename std::enable_if<std::is_unsigned<T>::value, T>::type\n    rotl(T x, int s) noexcept {\n  return numeric_internal::RotateLeft(x, s);\n}\n\ntemplate <class T>\n[[nodiscard]] constexpr\n    typename std::enable_if<std::is_unsigned<T>::value, T>::type\n    rotr(T x, int s) noexcept {\n  return numeric_internal::RotateRight(x, s);\n}\n\n#endif\n\n// https://github.com/llvm/llvm-project/issues/64544\n// libc++ had the wrong signature for std::rotl and std::rotr\n// prior to libc++ 18.0.\n//\n#if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)\n\nusing std::countl_one;\nusing std::countl_zero;\nusing std::countr_one;\nusing std::countr_zero;\nusing std::popcount;\n\n#else\n\n// Counting functions\n//\n// While these functions are typically constexpr, on some platforms, they may\n// not be marked as constexpr due to constraints of the compiler/available\n// intrinsics.\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, int>::type\n    countl_zero(T x) noexcept {\n  return numeric_internal::CountLeadingZeroes(x);\n}\n\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, int>::type\n    countl_one(T x) noexcept {\n  // Avoid integer promotion to a wider type\n  return countl_zero(static_cast<T>(~x));\n}\n\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CTZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, int>::type\n    countr_zero(T x) noexcept {\n  return numeric_internal::CountTrailingZeroes(x);\n}\n\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CTZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, int>::type\n    countr_one(T x) noexcept {\n  // Avoid integer promotion to a wider type\n  return countr_zero(static_cast<T>(~x));\n}\n\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_POPCOUNT inline\n    typename std::enable_if<std::is_unsigned<T>::value, int>::type\n    popcount(T x) noexcept {\n  return numeric_internal::Popcount(x);\n}\n\n#endif\n\n#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L)\n\nusing std::bit_ceil;\nusing std::bit_floor;\nusing std::bit_width;\nusing std::has_single_bit;\n\n#else\n\n// Returns: true if x is an integral power of two; false otherwise.\ntemplate <class T>\nconstexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type\nhas_single_bit(T x) noexcept {\n  return x != 0 && (x & (x - 1)) == 0;\n}\n\n// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any\n// fractional part discarded.\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, int>::type\n    bit_width(T x) noexcept {\n  return std::numeric_limits<T>::digits - countl_zero(x);\n}\n\n// Returns: If x == 0, 0; otherwise the maximal value y such that\n// has_single_bit(y) is true and y <= x.\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, T>::type\n    bit_floor(T x) noexcept {\n  return x == 0 ? 0 : T{1} << (bit_width(x) - 1);\n}\n\n// Returns: N, where N is the smallest power of 2 greater than or equal to x.\n//\n// Preconditions: N is representable as a value of type T.\ntemplate <class T>\nABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, T>::type\n    bit_ceil(T x) {\n  // If T is narrower than unsigned, T{1} << bit_width will be promoted.  We\n  // want to force it to wraparound so that bit_ceil of an invalid value are not\n  // core constant expressions.\n  //\n  // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would\n  // undergo promotion to unsigned but not fit the result into T without\n  // truncation.\n  return has_single_bit(x) ? T{1} << (bit_width(x) - 1)\n                           : numeric_internal::BitCeilNonPowerOf2(x);\n}\n\n#endif\n\n#if defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L\n\n// https://en.cppreference.com/w/cpp/types/endian\n//\n// Indicates the endianness of all scalar types:\n//   * If all scalar types are little-endian, `absl::endian::native` equals\n//     absl::endian::little.\n//   * If all scalar types are big-endian, `absl::endian::native` equals\n//     `absl::endian::big`.\n//   * Platforms that use anything else are unsupported.\nusing std::endian;\n\n#else\n\nenum class endian {\n  little,\n  big,\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n  native = little\n#elif defined(ABSL_IS_BIG_ENDIAN)\n  native = big\n#else\n#error \"Endian detection needs to be set up for this platform\"\n#endif\n};\n\n#endif  // defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L\n\n#if defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L\n\n// https://en.cppreference.com/w/cpp/numeric/byteswap\n//\n// Reverses the bytes in the given integer value `x`.\n//\n// `absl::byteswap` participates in overload resolution only if `T` satisfies\n// integral, i.e., `T` is an integer type. The program is ill-formed if `T` has\n// padding bits.\nusing std::byteswap;\n\n#else\n\ntemplate <class T>\n[[nodiscard]] constexpr T byteswap(T x) noexcept {\n  static_assert(std::is_integral_v<T>,\n                \"byteswap requires an integral argument\");\n  static_assert(\n      sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,\n      \"byteswap works only with 8, 16, 32, or 64-bit integers\");\n  if constexpr (sizeof(T) == 1) {\n    return x;\n  } else if constexpr (sizeof(T) == 2) {\n    return static_cast<T>(gbswap_16(static_cast<uint16_t>(x)));\n  } else if constexpr (sizeof(T) == 4) {\n    return static_cast<T>(gbswap_32(static_cast<uint32_t>(x)));\n  } else if constexpr (sizeof(T) == 8) {\n    return static_cast<T>(gbswap_64(static_cast<uint64_t>(x)));\n  }\n}\n\n#endif  // defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_NUMERIC_BITS_H_\n"
  },
  {
    "path": "absl/numeric/bits_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n#include <vector>\n\n#include \"absl/base/optimization.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/random/random.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nnamespace {\n\ntemplate <typename T>\nstatic void BM_bit_width(benchmark::State& state) {\n  const auto count = static_cast<size_t>(state.range(0));\n\n  absl::BitGen rng;\n  std::vector<T> values;\n  values.reserve(count);\n  for (size_t i = 0; i < count; ++i) {\n    values.push_back(absl::Uniform<T>(rng, 0, std::numeric_limits<T>::max()));\n  }\n\n  while (state.KeepRunningBatch(static_cast<int64_t>(count))) {\n    for (size_t i = 0; i < count; ++i) {\n      benchmark::DoNotOptimize(absl::bit_width(values[i]));\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_bit_width, uint8_t)->Range(1, 1 << 20);\nBENCHMARK_TEMPLATE(BM_bit_width, uint16_t)->Range(1, 1 << 20);\nBENCHMARK_TEMPLATE(BM_bit_width, uint32_t)->Range(1, 1 << 20);\nBENCHMARK_TEMPLATE(BM_bit_width, uint64_t)->Range(1, 1 << 20);\n\ntemplate <typename T>\nstatic void BM_bit_width_nonzero(benchmark::State& state) {\n  const auto count = static_cast<size_t>(state.range(0));\n\n  absl::BitGen rng;\n  std::vector<T> values;\n  values.reserve(count);\n  for (size_t i = 0; i < count; ++i) {\n    values.push_back(absl::Uniform<T>(rng, 1, std::numeric_limits<T>::max()));\n  }\n\n  while (state.KeepRunningBatch(static_cast<int64_t>(count))) {\n    for (size_t i = 0; i < count; ++i) {\n      const T value = values[i];\n      ABSL_ASSUME(value > 0);\n      benchmark::DoNotOptimize(absl::bit_width(value));\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_bit_width_nonzero, uint8_t)->Range(1, 1 << 20);\nBENCHMARK_TEMPLATE(BM_bit_width_nonzero, uint16_t)->Range(1, 1 << 20);\nBENCHMARK_TEMPLATE(BM_bit_width_nonzero, uint32_t)->Range(1, 1 << 20);\nBENCHMARK_TEMPLATE(BM_bit_width_nonzero, uint64_t)->Range(1, 1 << 20);\n\n}  // namespace\n}  // namespace absl\n"
  },
  {
    "path": "absl/numeric/bits_test.cc",
    "content": "// Copyright 2020 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/numeric/bits.h\"\n\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/random.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\ntemplate <typename IntT>\nclass UnsignedIntegerTypesTest : public ::testing::Test {};\ntemplate <typename IntT>\nclass IntegerTypesTest : public ::testing::Test {};\n\nusing UnsignedIntegerTypes =\n    ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>;\nusing OneByteIntegerTypes = ::testing::Types<\n    unsigned char,\n    uint8_t\n    >;\n\nTYPED_TEST_SUITE(UnsignedIntegerTypesTest, UnsignedIntegerTypes);\nTYPED_TEST_SUITE(IntegerTypesTest, OneByteIntegerTypes);\n\nTYPED_TEST(UnsignedIntegerTypesTest, ReturnTypes) {\n  using UIntType = TypeParam;\n\n  static_assert(std::is_same_v<decltype(byteswap(UIntType{0})), UIntType>);\n  static_assert(std::is_same_v<decltype(rotl(UIntType{0}, 0)), UIntType>);\n  static_assert(std::is_same_v<decltype(rotr(UIntType{0}, 0)), UIntType>);\n  static_assert(std::is_same_v<decltype(countl_zero(UIntType{0})), int>);\n  static_assert(std::is_same_v<decltype(countl_one(UIntType{0})), int>);\n  static_assert(std::is_same_v<decltype(countr_zero(UIntType{0})), int>);\n  static_assert(std::is_same_v<decltype(countr_one(UIntType{0})), int>);\n  static_assert(std::is_same_v<decltype(popcount(UIntType{0})), int>);\n  static_assert(std::is_same_v<decltype(bit_ceil(UIntType{0})), UIntType>);\n  static_assert(std::is_same_v<decltype(bit_floor(UIntType{0})), UIntType>);\n  static_assert(std::is_same_v<decltype(bit_width(UIntType{0})), int>);\n}\n\nTYPED_TEST(IntegerTypesTest, HandlesTypes) {\n  using UIntType = TypeParam;\n\n  EXPECT_EQ(rotl(UIntType{0x12}, 0), uint8_t{0x12});\n  EXPECT_EQ(rotr(UIntType{0x12}, -4), uint8_t{0x21});\n  static_assert(rotl(UIntType{0x12}, 0) == uint8_t{0x12}, \"\");\n\n  static_assert(rotr(UIntType{0x12}, 0) == uint8_t{0x12}, \"\");\n  EXPECT_EQ(rotr(UIntType{0x12}, 0), uint8_t{0x12});\n\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ\n  static_assert(countl_zero(UIntType{}) == 8, \"\");\n  static_assert(countl_zero(static_cast<UIntType>(-1)) == 0, \"\");\n\n  static_assert(countl_one(UIntType{}) == 0, \"\");\n  static_assert(countl_one(static_cast<UIntType>(-1)) == 8, \"\");\n\n  static_assert(countr_zero(UIntType{}) == 8, \"\");\n  static_assert(countr_zero(static_cast<UIntType>(-1)) == 0, \"\");\n\n  static_assert(countr_one(UIntType{}) == 0, \"\");\n  static_assert(countr_one(static_cast<UIntType>(-1)) == 8, \"\");\n\n  static_assert(popcount(UIntType{}) == 0, \"\");\n  static_assert(popcount(UIntType{1}) == 1, \"\");\n  static_assert(popcount(static_cast<UIntType>(-1)) == 8, \"\");\n\n  static_assert(bit_width(UIntType{}) == 0, \"\");\n  static_assert(bit_width(UIntType{1}) == 1, \"\");\n  static_assert(bit_width(UIntType{3}) == 2, \"\");\n  static_assert(bit_width(static_cast<UIntType>(-1)) == 8, \"\");\n#endif\n\n  EXPECT_EQ(countl_zero(UIntType{}), 8);\n  EXPECT_EQ(countl_zero(static_cast<UIntType>(-1)), 0);\n\n  EXPECT_EQ(countl_one(UIntType{}), 0);\n  EXPECT_EQ(countl_one(static_cast<UIntType>(-1)), 8);\n\n  EXPECT_EQ(countr_zero(UIntType{}), 8);\n  EXPECT_EQ(countr_zero(static_cast<UIntType>(-1)), 0);\n\n  EXPECT_EQ(countr_one(UIntType{}), 0);\n  EXPECT_EQ(countr_one(static_cast<UIntType>(-1)), 8);\n\n  EXPECT_EQ(popcount(UIntType{}), 0);\n  EXPECT_EQ(popcount(UIntType{1}), 1);\n\n  EXPECT_FALSE(has_single_bit(UIntType{}));\n  EXPECT_FALSE(has_single_bit(static_cast<UIntType>(-1)));\n\n  EXPECT_EQ(bit_width(UIntType{}), 0);\n  EXPECT_EQ(bit_width(UIntType{1}), 1);\n  EXPECT_EQ(bit_width(UIntType{3}), 2);\n  EXPECT_EQ(bit_width(static_cast<UIntType>(-1)), 8);\n}\n\nTEST(Rotate, Left) {\n  static_assert(rotl(uint8_t{0x12}, 0) == uint8_t{0x12}, \"\");\n  static_assert(rotl(uint16_t{0x1234}, 0) == uint16_t{0x1234}, \"\");\n  static_assert(rotl(uint32_t{0x12345678UL}, 0) == uint32_t{0x12345678UL}, \"\");\n  static_assert(rotl(uint64_t{0x12345678ABCDEF01ULL}, 0) ==\n                    uint64_t{0x12345678ABCDEF01ULL},\n                \"\");\n\n  EXPECT_EQ(rotl(uint8_t{0x12}, 0), uint8_t{0x12});\n  EXPECT_EQ(rotl(uint16_t{0x1234}, 0), uint16_t{0x1234});\n  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 0), uint32_t{0x12345678UL});\n  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 0),\n            uint64_t{0x12345678ABCDEF01ULL});\n\n  EXPECT_EQ(rotl(uint8_t{0x12}, 8), uint8_t{0x12});\n  EXPECT_EQ(rotl(uint16_t{0x1234}, 16), uint16_t{0x1234});\n  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 32), uint32_t{0x12345678UL});\n  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 64),\n            uint64_t{0x12345678ABCDEF01ULL});\n\n  EXPECT_EQ(rotl(uint8_t{0x12}, -8), uint8_t{0x12});\n  EXPECT_EQ(rotl(uint16_t{0x1234}, -16), uint16_t{0x1234});\n  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, -32), uint32_t{0x12345678UL});\n  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, -64),\n            uint64_t{0x12345678ABCDEF01ULL});\n\n  EXPECT_EQ(rotl(uint8_t{0x12}, 4), uint8_t{0x21});\n  EXPECT_EQ(rotl(uint16_t{0x1234}, 4), uint16_t{0x2341});\n  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 4), uint32_t{0x23456781UL});\n  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 4),\n            uint64_t{0x2345678ABCDEF011ULL});\n\n  EXPECT_EQ(rotl(uint8_t{0x12}, -4), uint8_t{0x21});\n  EXPECT_EQ(rotl(uint16_t{0x1234}, -4), uint16_t{0x4123});\n  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, -4), uint32_t{0x81234567UL});\n  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, -4),\n            uint64_t{0x112345678ABCDEF0ULL});\n\n  EXPECT_EQ(rotl(uint32_t{1234}, std::numeric_limits<int>::min()),\n            uint32_t{1234});\n}\n\nTEST(Rotate, Right) {\n  static_assert(rotr(uint8_t{0x12}, 0) == uint8_t{0x12}, \"\");\n  static_assert(rotr(uint16_t{0x1234}, 0) == uint16_t{0x1234}, \"\");\n  static_assert(rotr(uint32_t{0x12345678UL}, 0) == uint32_t{0x12345678UL}, \"\");\n  static_assert(rotr(uint64_t{0x12345678ABCDEF01ULL}, 0) ==\n                    uint64_t{0x12345678ABCDEF01ULL},\n                \"\");\n\n  EXPECT_EQ(rotr(uint8_t{0x12}, 0), uint8_t{0x12});\n  EXPECT_EQ(rotr(uint16_t{0x1234}, 0), uint16_t{0x1234});\n  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 0), uint32_t{0x12345678UL});\n  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 0),\n            uint64_t{0x12345678ABCDEF01ULL});\n\n  EXPECT_EQ(rotr(uint8_t{0x12}, 8), uint8_t{0x12});\n  EXPECT_EQ(rotr(uint16_t{0x1234}, 16), uint16_t{0x1234});\n  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 32), uint32_t{0x12345678UL});\n  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 64),\n            uint64_t{0x12345678ABCDEF01ULL});\n\n  EXPECT_EQ(rotr(uint8_t{0x12}, -8), uint8_t{0x12});\n  EXPECT_EQ(rotr(uint16_t{0x1234}, -16), uint16_t{0x1234});\n  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, -32), uint32_t{0x12345678UL});\n  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, -64),\n            uint64_t{0x12345678ABCDEF01ULL});\n\n  EXPECT_EQ(rotr(uint8_t{0x12}, 4), uint8_t{0x21});\n  EXPECT_EQ(rotr(uint16_t{0x1234}, 4), uint16_t{0x4123});\n  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 4), uint32_t{0x81234567UL});\n  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 4),\n            uint64_t{0x112345678ABCDEF0ULL});\n\n  EXPECT_EQ(rotr(uint8_t{0x12}, -4), uint8_t{0x21});\n  EXPECT_EQ(rotr(uint16_t{0x1234}, -4), uint16_t{0x2341});\n  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, -4), uint32_t{0x23456781UL});\n  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, -4),\n            uint64_t{0x2345678ABCDEF011ULL});\n\n  EXPECT_EQ(rotl(uint32_t{1234}, std::numeric_limits<int>::min()),\n            uint32_t{1234});\n}\n\nTEST(Rotate, Symmetry) {\n  // rotr(x, s) is equivalent to rotl(x, -s)\n  absl::BitGen rng;\n  constexpr int kTrials = 100;\n\n  for (int i = 0; i < kTrials; ++i) {\n    uint8_t value = absl::Uniform(rng, std::numeric_limits<uint8_t>::min(),\n                                  std::numeric_limits<uint8_t>::max());\n    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint8_t>::digits,\n                              2 * std::numeric_limits<uint8_t>::digits);\n\n    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));\n  }\n\n  for (int i = 0; i < kTrials; ++i) {\n    uint16_t value = absl::Uniform(rng, std::numeric_limits<uint16_t>::min(),\n                                   std::numeric_limits<uint16_t>::max());\n    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint16_t>::digits,\n                              2 * std::numeric_limits<uint16_t>::digits);\n\n    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));\n  }\n\n  for (int i = 0; i < kTrials; ++i) {\n    uint32_t value = absl::Uniform(rng, std::numeric_limits<uint32_t>::min(),\n                                   std::numeric_limits<uint32_t>::max());\n    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint32_t>::digits,\n                              2 * std::numeric_limits<uint32_t>::digits);\n\n    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));\n  }\n\n  for (int i = 0; i < kTrials; ++i) {\n    uint64_t value = absl::Uniform(rng, std::numeric_limits<uint64_t>::min(),\n                                   std::numeric_limits<uint64_t>::max());\n    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint64_t>::digits,\n                              2 * std::numeric_limits<uint64_t>::digits);\n\n    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));\n  }\n}\n\nTEST(Counting, LeadingZeroes) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ\n  static_assert(countl_zero(uint8_t{}) == 8, \"\");\n  static_assert(countl_zero(static_cast<uint8_t>(-1)) == 0, \"\");\n  static_assert(countl_zero(uint16_t{}) == 16, \"\");\n  static_assert(countl_zero(static_cast<uint16_t>(-1)) == 0, \"\");\n  static_assert(countl_zero(uint32_t{}) == 32, \"\");\n  static_assert(countl_zero(~uint32_t{}) == 0, \"\");\n  static_assert(countl_zero(uint64_t{}) == 64, \"\");\n  static_assert(countl_zero(~uint64_t{}) == 0, \"\");\n#endif\n\n  EXPECT_EQ(countl_zero(uint8_t{}), 8);\n  EXPECT_EQ(countl_zero(static_cast<uint8_t>(-1)), 0);\n  EXPECT_EQ(countl_zero(uint16_t{}), 16);\n  EXPECT_EQ(countl_zero(static_cast<uint16_t>(-1)), 0);\n  EXPECT_EQ(countl_zero(uint32_t{}), 32);\n  EXPECT_EQ(countl_zero(~uint32_t{}), 0);\n  EXPECT_EQ(countl_zero(uint64_t{}), 64);\n  EXPECT_EQ(countl_zero(~uint64_t{}), 0);\n\n  for (int i = 0; i < 8; i++) {\n    EXPECT_EQ(countl_zero(static_cast<uint8_t>(1u << i)), 7 - i);\n  }\n\n  for (int i = 0; i < 16; i++) {\n    EXPECT_EQ(countl_zero(static_cast<uint16_t>(1u << i)), 15 - i);\n  }\n\n  for (int i = 0; i < 32; i++) {\n    EXPECT_EQ(countl_zero(uint32_t{1} << i), 31 - i);\n  }\n\n  for (int i = 0; i < 64; i++) {\n    EXPECT_EQ(countl_zero(uint64_t{1} << i), 63 - i);\n  }\n}\n\nTEST(Counting, LeadingOnes) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ\n  static_assert(countl_one(uint8_t{}) == 0, \"\");\n  static_assert(countl_one(static_cast<uint8_t>(-1)) == 8, \"\");\n  static_assert(countl_one(uint16_t{}) == 0, \"\");\n  static_assert(countl_one(static_cast<uint16_t>(-1)) == 16, \"\");\n  static_assert(countl_one(uint32_t{}) == 0, \"\");\n  static_assert(countl_one(~uint32_t{}) == 32, \"\");\n  static_assert(countl_one(uint64_t{}) == 0, \"\");\n  static_assert(countl_one(~uint64_t{}) == 64, \"\");\n#endif\n\n  EXPECT_EQ(countl_one(uint8_t{}), 0);\n  EXPECT_EQ(countl_one(static_cast<uint8_t>(-1)), 8);\n  EXPECT_EQ(countl_one(uint16_t{}), 0);\n  EXPECT_EQ(countl_one(static_cast<uint16_t>(-1)), 16);\n  EXPECT_EQ(countl_one(uint32_t{}), 0);\n  EXPECT_EQ(countl_one(~uint32_t{}), 32);\n  EXPECT_EQ(countl_one(uint64_t{}), 0);\n  EXPECT_EQ(countl_one(~uint64_t{}), 64);\n}\n\nTEST(Counting, TrailingZeroes) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CTZ\n  static_assert(countr_zero(uint8_t{}) == 8, \"\");\n  static_assert(countr_zero(static_cast<uint8_t>(-1)) == 0, \"\");\n  static_assert(countr_zero(uint16_t{}) == 16, \"\");\n  static_assert(countr_zero(static_cast<uint16_t>(-1)) == 0, \"\");\n  static_assert(countr_zero(uint32_t{}) == 32, \"\");\n  static_assert(countr_zero(~uint32_t{}) == 0, \"\");\n  static_assert(countr_zero(uint64_t{}) == 64, \"\");\n  static_assert(countr_zero(~uint64_t{}) == 0, \"\");\n#endif\n\n  EXPECT_EQ(countr_zero(uint8_t{}), 8);\n  EXPECT_EQ(countr_zero(static_cast<uint8_t>(-1)), 0);\n  EXPECT_EQ(countr_zero(uint16_t{}), 16);\n  EXPECT_EQ(countr_zero(static_cast<uint16_t>(-1)), 0);\n  EXPECT_EQ(countr_zero(uint32_t{}), 32);\n  EXPECT_EQ(countr_zero(~uint32_t{}), 0);\n  EXPECT_EQ(countr_zero(uint64_t{}), 64);\n  EXPECT_EQ(countr_zero(~uint64_t{}), 0);\n}\n\nTEST(Counting, TrailingOnes) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CTZ\n  static_assert(countr_one(uint8_t{}) == 0, \"\");\n  static_assert(countr_one(static_cast<uint8_t>(-1)) == 8, \"\");\n  static_assert(countr_one(uint16_t{}) == 0, \"\");\n  static_assert(countr_one(static_cast<uint16_t>(-1)) == 16, \"\");\n  static_assert(countr_one(uint32_t{}) == 0, \"\");\n  static_assert(countr_one(~uint32_t{}) == 32, \"\");\n  static_assert(countr_one(uint64_t{}) == 0, \"\");\n  static_assert(countr_one(~uint64_t{}) == 64, \"\");\n#endif\n\n  EXPECT_EQ(countr_one(uint8_t{}), 0);\n  EXPECT_EQ(countr_one(static_cast<uint8_t>(-1)), 8);\n  EXPECT_EQ(countr_one(uint16_t{}), 0);\n  EXPECT_EQ(countr_one(static_cast<uint16_t>(-1)), 16);\n  EXPECT_EQ(countr_one(uint32_t{}), 0);\n  EXPECT_EQ(countr_one(~uint32_t{}), 32);\n  EXPECT_EQ(countr_one(uint64_t{}), 0);\n  EXPECT_EQ(countr_one(~uint64_t{}), 64);\n}\n\nTEST(Counting, Popcount) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT\n  static_assert(popcount(uint8_t{}) == 0, \"\");\n  static_assert(popcount(uint8_t{1}) == 1, \"\");\n  static_assert(popcount(static_cast<uint8_t>(-1)) == 8, \"\");\n  static_assert(popcount(uint16_t{}) == 0, \"\");\n  static_assert(popcount(uint16_t{1}) == 1, \"\");\n  static_assert(popcount(static_cast<uint16_t>(-1)) == 16, \"\");\n  static_assert(popcount(uint32_t{}) == 0, \"\");\n  static_assert(popcount(uint32_t{1}) == 1, \"\");\n  static_assert(popcount(~uint32_t{}) == 32, \"\");\n  static_assert(popcount(uint64_t{}) == 0, \"\");\n  static_assert(popcount(uint64_t{1}) == 1, \"\");\n  static_assert(popcount(~uint64_t{}) == 64, \"\");\n#endif  // ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT\n\n  EXPECT_EQ(popcount(uint8_t{}), 0);\n  EXPECT_EQ(popcount(uint8_t{1}), 1);\n  EXPECT_EQ(popcount(static_cast<uint8_t>(-1)), 8);\n  EXPECT_EQ(popcount(uint16_t{}), 0);\n  EXPECT_EQ(popcount(uint16_t{1}), 1);\n  EXPECT_EQ(popcount(static_cast<uint16_t>(-1)), 16);\n  EXPECT_EQ(popcount(uint32_t{}), 0);\n  EXPECT_EQ(popcount(uint32_t{1}), 1);\n  EXPECT_EQ(popcount(~uint32_t{}), 32);\n  EXPECT_EQ(popcount(uint64_t{}), 0);\n  EXPECT_EQ(popcount(uint64_t{1}), 1);\n  EXPECT_EQ(popcount(~uint64_t{}), 64);\n\n  for (int i = 0; i < 8; i++) {\n    EXPECT_EQ(popcount(static_cast<uint8_t>(uint8_t{1} << i)), 1);\n    EXPECT_EQ(popcount(static_cast<uint8_t>(static_cast<uint8_t>(-1) ^\n                                            (uint8_t{1} << i))),\n              7);\n  }\n\n  for (int i = 0; i < 16; i++) {\n    EXPECT_EQ(popcount(static_cast<uint16_t>(uint16_t{1} << i)), 1);\n    EXPECT_EQ(popcount(static_cast<uint16_t>(static_cast<uint16_t>(-1) ^\n                                             (uint16_t{1} << i))),\n              15);\n  }\n\n  for (int i = 0; i < 32; i++) {\n    EXPECT_EQ(popcount(uint32_t{1} << i), 1);\n    EXPECT_EQ(popcount(static_cast<uint32_t>(-1) ^ (uint32_t{1} << i)), 31);\n  }\n\n  for (int i = 0; i < 64; i++) {\n    EXPECT_EQ(popcount(uint64_t{1} << i), 1);\n    EXPECT_EQ(popcount(static_cast<uint64_t>(-1) ^ (uint64_t{1} << i)), 63);\n  }\n}\n\ntemplate <typename T>\nstruct PopcountInput {\n  T value = 0;\n  int expected = 0;\n};\n\ntemplate <typename T>\nPopcountInput<T> GeneratePopcountInput(absl::BitGen& gen) {\n  PopcountInput<T> ret;\n  for (int i = 0; i < std::numeric_limits<T>::digits; i++) {\n    bool coin = absl::Bernoulli(gen, 0.2);\n    if (coin) {\n      ret.value |= T{1} << i;\n      ret.expected++;\n    }\n  }\n  return ret;\n}\n\nTEST(Counting, PopcountFuzz) {\n  absl::BitGen rng;\n  constexpr int kTrials = 100;\n\n  for (int i = 0; i < kTrials; ++i) {\n    auto input = GeneratePopcountInput<uint8_t>(rng);\n    EXPECT_EQ(popcount(input.value), input.expected);\n  }\n\n  for (int i = 0; i < kTrials; ++i) {\n    auto input = GeneratePopcountInput<uint16_t>(rng);\n    EXPECT_EQ(popcount(input.value), input.expected);\n  }\n\n  for (int i = 0; i < kTrials; ++i) {\n    auto input = GeneratePopcountInput<uint32_t>(rng);\n    EXPECT_EQ(popcount(input.value), input.expected);\n  }\n\n  for (int i = 0; i < kTrials; ++i) {\n    auto input = GeneratePopcountInput<uint64_t>(rng);\n    EXPECT_EQ(popcount(input.value), input.expected);\n  }\n}\n\nTEST(IntegralPowersOfTwo, SingleBit) {\n  EXPECT_FALSE(has_single_bit(uint8_t{}));\n  EXPECT_FALSE(has_single_bit(static_cast<uint8_t>(-1)));\n  EXPECT_FALSE(has_single_bit(uint16_t{}));\n  EXPECT_FALSE(has_single_bit(static_cast<uint16_t>(-1)));\n  EXPECT_FALSE(has_single_bit(uint32_t{}));\n  EXPECT_FALSE(has_single_bit(~uint32_t{}));\n  EXPECT_FALSE(has_single_bit(uint64_t{}));\n  EXPECT_FALSE(has_single_bit(~uint64_t{}));\n\n  static_assert(!has_single_bit(0u), \"\");\n  static_assert(has_single_bit(1u), \"\");\n  static_assert(has_single_bit(2u), \"\");\n  static_assert(!has_single_bit(3u), \"\");\n  static_assert(has_single_bit(4u), \"\");\n  static_assert(!has_single_bit(1337u), \"\");\n  static_assert(has_single_bit(65536u), \"\");\n  static_assert(has_single_bit(uint32_t{1} << 30), \"\");\n  static_assert(has_single_bit(uint64_t{1} << 42), \"\");\n\n  EXPECT_FALSE(has_single_bit(0u));\n  EXPECT_TRUE(has_single_bit(1u));\n  EXPECT_TRUE(has_single_bit(2u));\n  EXPECT_FALSE(has_single_bit(3u));\n  EXPECT_TRUE(has_single_bit(4u));\n  EXPECT_FALSE(has_single_bit(1337u));\n  EXPECT_TRUE(has_single_bit(65536u));\n  EXPECT_TRUE(has_single_bit(uint32_t{1} << 30));\n  EXPECT_TRUE(has_single_bit(uint64_t{1} << 42));\n\n  EXPECT_TRUE(has_single_bit(\n      static_cast<uint8_t>(std::numeric_limits<uint8_t>::max() / 2 + 1)));\n  EXPECT_TRUE(has_single_bit(\n      static_cast<uint16_t>(std::numeric_limits<uint16_t>::max() / 2 + 1)));\n  EXPECT_TRUE(has_single_bit(\n      static_cast<uint32_t>(std::numeric_limits<uint32_t>::max() / 2 + 1)));\n  EXPECT_TRUE(has_single_bit(\n      static_cast<uint64_t>(std::numeric_limits<uint64_t>::max() / 2 + 1)));\n}\n\ntemplate <typename T, T arg, T = bit_ceil(arg)>\nbool IsBitCeilConstantExpression(int) {\n  return true;\n}\ntemplate <typename T, T arg>\nbool IsBitCeilConstantExpression(char) {\n  return false;\n}\n\nTEST(IntegralPowersOfTwo, Ceiling) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ\n  static_assert(bit_ceil(0u) == 1, \"\");\n  static_assert(bit_ceil(1u) == 1, \"\");\n  static_assert(bit_ceil(2u) == 2, \"\");\n  static_assert(bit_ceil(3u) == 4, \"\");\n  static_assert(bit_ceil(4u) == 4, \"\");\n  static_assert(bit_ceil(1337u) == 2048, \"\");\n  static_assert(bit_ceil(65536u) == 65536, \"\");\n  static_assert(bit_ceil(65536u - 1337u) == 65536, \"\");\n  static_assert(bit_ceil(uint32_t{0x80000000}) == uint32_t{0x80000000}, \"\");\n  static_assert(bit_ceil(uint64_t{0x40000000000}) == uint64_t{0x40000000000},\n                \"\");\n  static_assert(\n      bit_ceil(uint64_t{0x8000000000000000}) == uint64_t{0x8000000000000000},\n      \"\");\n\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x0}>(0)));\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x80}>(0)));\n  EXPECT_FALSE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x81}>(0)));\n  EXPECT_FALSE((IsBitCeilConstantExpression<uint8_t, uint8_t{0xff}>(0)));\n\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x0}>(0)));\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x8000}>(0)));\n  EXPECT_FALSE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x8001}>(0)));\n  EXPECT_FALSE((IsBitCeilConstantExpression<uint16_t, uint16_t{0xffff}>(0)));\n\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint32_t, uint32_t{0x0}>(0)));\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint32_t, uint32_t{0x80000000}>(0)));\n  EXPECT_FALSE(\n      (IsBitCeilConstantExpression<uint32_t, uint32_t{0x80000001}>(0)));\n  EXPECT_FALSE(\n      (IsBitCeilConstantExpression<uint32_t, uint32_t{0xffffffff}>(0)));\n\n  EXPECT_TRUE((IsBitCeilConstantExpression<uint64_t, uint64_t{0x0}>(0)));\n  EXPECT_TRUE(\n      (IsBitCeilConstantExpression<uint64_t, uint64_t{0x8000000000000000}>(0)));\n  EXPECT_FALSE(\n      (IsBitCeilConstantExpression<uint64_t, uint64_t{0x8000000000000001}>(0)));\n  EXPECT_FALSE(\n      (IsBitCeilConstantExpression<uint64_t, uint64_t{0xffffffffffffffff}>(0)));\n#endif\n\n  EXPECT_EQ(bit_ceil(0u), 1);\n  EXPECT_EQ(bit_ceil(1u), 1);\n  EXPECT_EQ(bit_ceil(2u), 2);\n  EXPECT_EQ(bit_ceil(3u), 4);\n  EXPECT_EQ(bit_ceil(4u), 4);\n  EXPECT_EQ(bit_ceil(1337u), 2048);\n  EXPECT_EQ(bit_ceil(65536u), 65536);\n  EXPECT_EQ(bit_ceil(65536u - 1337u), 65536);\n  EXPECT_EQ(bit_ceil(uint64_t{0x40000000000}), uint64_t{0x40000000000});\n}\n\nTEST(IntegralPowersOfTwo, Floor) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ\n  static_assert(bit_floor(0u) == 0, \"\");\n  static_assert(bit_floor(1u) == 1, \"\");\n  static_assert(bit_floor(2u) == 2, \"\");\n  static_assert(bit_floor(3u) == 2, \"\");\n  static_assert(bit_floor(4u) == 4, \"\");\n  static_assert(bit_floor(1337u) == 1024, \"\");\n  static_assert(bit_floor(65536u) == 65536, \"\");\n  static_assert(bit_floor(65536u - 1337u) == 32768, \"\");\n  static_assert(bit_floor(uint64_t{0x40000000000}) == uint64_t{0x40000000000},\n                \"\");\n#endif\n\n  EXPECT_EQ(bit_floor(0u), 0);\n  EXPECT_EQ(bit_floor(1u), 1);\n  EXPECT_EQ(bit_floor(2u), 2);\n  EXPECT_EQ(bit_floor(3u), 2);\n  EXPECT_EQ(bit_floor(4u), 4);\n  EXPECT_EQ(bit_floor(1337u), 1024);\n  EXPECT_EQ(bit_floor(65536u), 65536);\n  EXPECT_EQ(bit_floor(65536u - 1337u), 32768);\n  EXPECT_EQ(bit_floor(uint64_t{0x40000000000}), uint64_t{0x40000000000});\n\n  for (int i = 0; i < 8; i++) {\n    uint8_t input = uint8_t{1} << i;\n    EXPECT_EQ(bit_floor(input), input);\n    if (i > 0) {\n      EXPECT_EQ(bit_floor(static_cast<uint8_t>(input + 1)), input);\n    }\n  }\n\n  for (int i = 0; i < 16; i++) {\n    uint16_t input = uint16_t{1} << i;\n    EXPECT_EQ(bit_floor(input), input);\n    if (i > 0) {\n      EXPECT_EQ(bit_floor(static_cast<uint16_t>(input + 1)), input);\n    }\n  }\n\n  for (int i = 0; i < 32; i++) {\n    uint32_t input = uint32_t{1} << i;\n    EXPECT_EQ(bit_floor(input), input);\n    if (i > 0) {\n      EXPECT_EQ(bit_floor(input + 1), input);\n    }\n  }\n\n  for (int i = 0; i < 64; i++) {\n    uint64_t input = uint64_t{1} << i;\n    EXPECT_EQ(bit_floor(input), input);\n    if (i > 0) {\n      EXPECT_EQ(bit_floor(input + 1), input);\n    }\n  }\n}\n\nTEST(IntegralPowersOfTwo, Width) {\n#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ\n  static_assert(bit_width(uint8_t{}) == 0, \"\");\n  static_assert(bit_width(uint8_t{1}) == 1, \"\");\n  static_assert(bit_width(uint8_t{3}) == 2, \"\");\n  static_assert(bit_width(static_cast<uint8_t>(-1)) == 8, \"\");\n  static_assert(bit_width(uint16_t{}) == 0, \"\");\n  static_assert(bit_width(uint16_t{1}) == 1, \"\");\n  static_assert(bit_width(uint16_t{3}) == 2, \"\");\n  static_assert(bit_width(static_cast<uint16_t>(-1)) == 16, \"\");\n  static_assert(bit_width(uint32_t{}) == 0, \"\");\n  static_assert(bit_width(uint32_t{1}) == 1, \"\");\n  static_assert(bit_width(uint32_t{3}) == 2, \"\");\n  static_assert(bit_width(~uint32_t{}) == 32, \"\");\n  static_assert(bit_width(uint64_t{}) == 0, \"\");\n  static_assert(bit_width(uint64_t{1}) == 1, \"\");\n  static_assert(bit_width(uint64_t{3}) == 2, \"\");\n  static_assert(bit_width(~uint64_t{}) == 64, \"\");\n#endif\n\n  EXPECT_EQ(bit_width(uint8_t{}), 0);\n  EXPECT_EQ(bit_width(uint8_t{1}), 1);\n  EXPECT_EQ(bit_width(uint8_t{3}), 2);\n  EXPECT_EQ(bit_width(static_cast<uint8_t>(-1)), 8);\n  EXPECT_EQ(bit_width(uint16_t{}), 0);\n  EXPECT_EQ(bit_width(uint16_t{1}), 1);\n  EXPECT_EQ(bit_width(uint16_t{3}), 2);\n  EXPECT_EQ(bit_width(static_cast<uint16_t>(-1)), 16);\n  EXPECT_EQ(bit_width(uint32_t{}), 0);\n  EXPECT_EQ(bit_width(uint32_t{1}), 1);\n  EXPECT_EQ(bit_width(uint32_t{3}), 2);\n  EXPECT_EQ(bit_width(~uint32_t{}), 32);\n  EXPECT_EQ(bit_width(uint64_t{}), 0);\n  EXPECT_EQ(bit_width(uint64_t{1}), 1);\n  EXPECT_EQ(bit_width(uint64_t{3}), 2);\n  EXPECT_EQ(bit_width(~uint64_t{}), 64);\n\n  for (int i = 0; i < 8; i++) {\n    EXPECT_EQ(bit_width(static_cast<uint8_t>(uint8_t{1} << i)), i + 1);\n  }\n\n  for (int i = 0; i < 16; i++) {\n    EXPECT_EQ(bit_width(static_cast<uint16_t>(uint16_t{1} << i)), i + 1);\n  }\n\n  for (int i = 0; i < 32; i++) {\n    EXPECT_EQ(bit_width(uint32_t{1} << i), i + 1);\n  }\n\n  for (int i = 0; i < 64; i++) {\n    EXPECT_EQ(bit_width(uint64_t{1} << i), i + 1);\n  }\n}\n\n// On GCC and Clang, anticiapte that implementations will be constexpr\n#if defined(__GNUC__)\nstatic_assert(ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT,\n              \"popcount should be constexpr\");\nstatic_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CLZ, \"clz should be constexpr\");\nstatic_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CTZ, \"ctz should be constexpr\");\n#endif\n\nTEST(Endian, Comparison) {\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n  static_assert(absl::endian::native == absl::endian::little);\n  static_assert(absl::endian::native != absl::endian::big);\n#endif\n#if defined(ABSL_IS_BIG_ENDIAN)\n  static_assert(absl::endian::native != absl::endian::little);\n  static_assert(absl::endian::native == absl::endian::big);\n#endif\n}\n\nTEST(Byteswap, Constexpr) {\n  static_assert(absl::byteswap<int8_t>(0x12) == 0x12);\n  static_assert(absl::byteswap<int16_t>(0x1234) == 0x3412);\n  static_assert(absl::byteswap<int32_t>(0x12345678) == 0x78563412);\n  static_assert(absl::byteswap<int64_t>(0x123456789abcdef0) ==\n                static_cast<int64_t>(0xf0debc9a78563412));\n  static_assert(absl::byteswap<uint8_t>(0x21) == 0x21);\n  static_assert(absl::byteswap<uint16_t>(0x4321) == 0x2143);\n  static_assert(absl::byteswap<uint32_t>(0x87654321) == 0x21436587);\n  static_assert(absl::byteswap<uint64_t>(0xfedcba9876543210) ==\n                static_cast<uint64_t>(0x1032547698badcfe));\n  static_assert(absl::byteswap<int32_t>(static_cast<int32_t>(0xdeadbeef)) ==\n                static_cast<int32_t>(0xefbeadde));\n}\n\nTEST(Byteswap, NotConstexpr) {\n  int8_t a = 0x12;\n  int16_t b = 0x1234;\n  int32_t c = 0x12345678;\n  int64_t d = 0x123456789abcdef0;\n  uint8_t e = 0x21;\n  uint16_t f = 0x4321;\n  uint32_t g = 0x87654321;\n  uint64_t h = 0xfedcba9876543210;\n  EXPECT_EQ(absl::byteswap<int8_t>(a), 0x12);\n  EXPECT_EQ(absl::byteswap<int16_t>(b), 0x3412);\n  EXPECT_EQ(absl::byteswap(c), 0x78563412);\n  EXPECT_EQ(absl::byteswap(d), 0xf0debc9a78563412);\n  EXPECT_EQ(absl::byteswap<uint8_t>(e), 0x21);\n  EXPECT_EQ(absl::byteswap<uint16_t>(f), 0x2143);\n  EXPECT_EQ(absl::byteswap(g), 0x21436587);\n  EXPECT_EQ(absl::byteswap(h), 0x1032547698badcfe);\n  EXPECT_EQ(absl::byteswap(absl::byteswap<int8_t>(a)), a);\n  EXPECT_EQ(absl::byteswap(absl::byteswap<int16_t>(b)), b);\n  EXPECT_EQ(absl::byteswap(absl::byteswap(c)), c);\n  EXPECT_EQ(absl::byteswap(absl::byteswap(d)), d);\n  EXPECT_EQ(absl::byteswap(absl::byteswap<uint8_t>(e)), e);\n  EXPECT_EQ(absl::byteswap(absl::byteswap<uint16_t>(f)), f);\n  EXPECT_EQ(absl::byteswap(absl::byteswap(g)), g);\n  EXPECT_EQ(absl::byteswap(absl::byteswap(h)), h);\n  EXPECT_EQ(absl::byteswap<uint32_t>(0xdeadbeef), 0xefbeadde);\n  EXPECT_EQ(absl::byteswap<const uint32_t>(0xdeadbeef), 0xefbeadde);\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/numeric/int128.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/numeric/int128.h\"\n\n#include <stddef.h>\n\n#include <cassert>\n#include <iomanip>\n#include <ostream>  // NOLINT(readability/streams)\n#include <sstream>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/optimization.h\"\n#include \"absl/numeric/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\n// Returns the 0-based position of the last set bit (i.e., most significant bit)\n// in the given uint128. The argument is not 0.\n//\n// For example:\n//   Given: 5 (decimal) == 101 (binary)\n//   Returns: 2\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) {\n  if (uint64_t hi = Uint128High64(n)) {\n    ABSL_ASSUME(hi != 0);\n    return 127 - countl_zero(hi);\n  }\n  const uint64_t low = Uint128Low64(n);\n  ABSL_ASSUME(low != 0);\n  return 63 - countl_zero(low);\n}\n\n// Long division/modulo for uint128 implemented using the shift-subtract\n// division algorithm adapted from:\n// https://stackoverflow.com/questions/5386377/division-without-using\ninline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,\n                       uint128* remainder_ret) {\n  assert(divisor != 0);\n\n  if (divisor > dividend) {\n    *quotient_ret = 0;\n    *remainder_ret = dividend;\n    return;\n  }\n\n  if (divisor == dividend) {\n    *quotient_ret = 1;\n    *remainder_ret = 0;\n    return;\n  }\n\n  uint128 denominator = divisor;\n  uint128 quotient = 0;\n\n  // Left aligns the MSB of the denominator and the dividend.\n  const int shift = Fls128(dividend) - Fls128(denominator);\n  denominator <<= shift;\n\n  // Uses shift-subtract algorithm to divide dividend by denominator. The\n  // remainder will be left in dividend.\n  for (int i = 0; i <= shift; ++i) {\n    quotient <<= 1;\n    if (dividend >= denominator) {\n      dividend -= denominator;\n      quotient |= 1;\n    }\n    denominator >>= 1;\n  }\n\n  *quotient_ret = quotient;\n  *remainder_ret = dividend;\n}\n\ntemplate <typename T>\nuint128 MakeUint128FromFloat(T v) {\n  static_assert(std::is_floating_point<T>::value, \"\");\n\n  // Rounding behavior is towards zero, same as for built-in types.\n\n  // Undefined behavior if v is NaN or cannot fit into uint128.\n  assert(std::isfinite(v) && v > -1 &&\n         (std::numeric_limits<T>::max_exponent <= 128 ||\n          v < std::ldexp(static_cast<T>(1), 128)));\n\n  if (v >= std::ldexp(static_cast<T>(1), 64)) {\n    uint64_t hi = static_cast<uint64_t>(std::ldexp(v, -64));\n    uint64_t lo = static_cast<uint64_t>(v - std::ldexp(static_cast<T>(hi), 64));\n    return MakeUint128(hi, lo);\n  }\n\n  return MakeUint128(0, static_cast<uint64_t>(v));\n}\n\n#if defined(__clang__) && (__clang_major__ < 9) && !defined(__SSE3__)\n// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289\n// Casting from long double to uint64_t is miscompiled and drops bits.\n// It is more work, so only use when we need the workaround.\nuint128 MakeUint128FromFloat(long double v) {\n  // Go 50 bits at a time, that fits in a double\n  static_assert(std::numeric_limits<double>::digits >= 50, \"\");\n  static_assert(std::numeric_limits<long double>::digits <= 150, \"\");\n  // Undefined behavior if v is not finite or cannot fit into uint128.\n  assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));\n\n  v = std::ldexp(v, -100);\n  uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));\n  v = std::ldexp(v - static_cast<double>(w0), 50);\n  uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));\n  v = std::ldexp(v - static_cast<double>(w1), 50);\n  uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));\n  return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |\n         static_cast<uint128>(w2);\n}\n#endif  // __clang__ && (__clang_major__ < 9) && !__SSE3__\n}  // namespace\n\nuint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}\nuint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {}\nuint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {}\n\n#if !defined(ABSL_HAVE_INTRINSIC_INT128)\nuint128 operator/(uint128 lhs, uint128 rhs) {\n  uint128 quotient = 0;\n  uint128 remainder = 0;\n  DivModImpl(lhs, rhs, &quotient, &remainder);\n  return quotient;\n}\n\nuint128 operator%(uint128 lhs, uint128 rhs) {\n  uint128 quotient = 0;\n  uint128 remainder = 0;\n  DivModImpl(lhs, rhs, &quotient, &remainder);\n  return remainder;\n}\n#endif  // !defined(ABSL_HAVE_INTRINSIC_INT128)\n\nnamespace {\n\nstd::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) {\n  // Select a divisor which is the largest power of the base < 2^64.\n  uint128 div;\n  int div_base_log;\n  switch (flags & std::ios::basefield) {\n    case std::ios::hex:\n      div = 0x1000000000000000;  // 16^15\n      div_base_log = 15;\n      break;\n    case std::ios::oct:\n      div = 01000000000000000000000;  // 8^21\n      div_base_log = 21;\n      break;\n    default:  // std::ios::dec\n      div = 10000000000000000000u;  // 10^19\n      div_base_log = 19;\n      break;\n  }\n\n  // Now piece together the uint128 representation from three chunks of the\n  // original value, each less than \"div\" and therefore representable as a\n  // uint64_t.\n  std::ostringstream os;\n  std::ios_base::fmtflags copy_mask =\n      std::ios::basefield | std::ios::showbase | std::ios::uppercase;\n  os.setf(flags & copy_mask, copy_mask);\n  uint128 high = v;\n  uint128 low;\n  DivModImpl(high, div, &high, &low);\n  uint128 mid;\n  DivModImpl(high, div, &high, &mid);\n  if (Uint128Low64(high) != 0) {\n    os << Uint128Low64(high);\n    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);\n    os << Uint128Low64(mid);\n    os << std::setw(div_base_log);\n  } else if (Uint128Low64(mid) != 0) {\n    os << Uint128Low64(mid);\n    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);\n  }\n  os << Uint128Low64(low);\n  return os.str();\n}\n\n}  // namespace\n\nstd::string uint128::ToString() const {\n  return Uint128ToFormattedString(*this, std::ios_base::dec);\n}\n\nstd::ostream& operator<<(std::ostream& os, uint128 v) {\n  std::ios_base::fmtflags flags = os.flags();\n  std::string rep = Uint128ToFormattedString(v, flags);\n\n  // Add the requisite padding.\n  std::streamsize width = os.width(0);\n  if (static_cast<size_t>(width) > rep.size()) {\n    const size_t count = static_cast<size_t>(width) - rep.size();\n    std::ios::fmtflags adjustfield = flags & std::ios::adjustfield;\n    if (adjustfield == std::ios::left) {\n      rep.append(count, os.fill());\n    } else if (adjustfield == std::ios::internal &&\n               (flags & std::ios::showbase) &&\n               (flags & std::ios::basefield) == std::ios::hex && v != 0) {\n      rep.insert(size_t{2}, count, os.fill());\n    } else {\n      rep.insert(size_t{0}, count, os.fill());\n    }\n  }\n\n  return os << rep;\n}\n\nnamespace {\n\nuint128 UnsignedAbsoluteValue(int128 v) {\n  // Cast to uint128 before possibly negating because -Int128Min() is undefined.\n  return Int128High64(v) < 0 ? -uint128(v) : uint128(v);\n}\n\n}  // namespace\n\n#if !defined(ABSL_HAVE_INTRINSIC_INT128)\nnamespace {\n\ntemplate <typename T>\nint128 MakeInt128FromFloat(T v) {\n  // Conversion when v is NaN or cannot fit into int128 would be undefined\n  // behavior if using an intrinsic 128-bit integer.\n  assert(std::isfinite(v) && (std::numeric_limits<T>::max_exponent <= 127 ||\n                              (v >= -std::ldexp(static_cast<T>(1), 127) &&\n                               v < std::ldexp(static_cast<T>(1), 127))));\n\n  // We must convert the absolute value and then negate as needed, because\n  // floating point types are typically sign-magnitude. Otherwise, the\n  // difference between the high and low 64 bits when interpreted as two's\n  // complement overwhelms the precision of the mantissa.\n  uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v);\n  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),\n                    Uint128Low64(result));\n}\n\n}  // namespace\n\nint128::int128(float v) : int128(MakeInt128FromFloat(v)) {}\nint128::int128(double v) : int128(MakeInt128FromFloat(v)) {}\nint128::int128(long double v) : int128(MakeInt128FromFloat(v)) {}\n\nint128 operator/(int128 lhs, int128 rhs) {\n  assert(lhs != Int128Min() || rhs != -1);  // UB on two's complement.\n\n  uint128 quotient = 0;\n  uint128 remainder = 0;\n  DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),\n             &quotient, &remainder);\n  if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient;\n  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)),\n                    Uint128Low64(quotient));\n}\n\nint128 operator%(int128 lhs, int128 rhs) {\n  assert(lhs != Int128Min() || rhs != -1);  // UB on two's complement.\n\n  uint128 quotient = 0;\n  uint128 remainder = 0;\n  DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),\n             &quotient, &remainder);\n  if (Int128High64(lhs) < 0) remainder = -remainder;\n  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)),\n                    Uint128Low64(remainder));\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nstd::string int128::ToString() const {\n  std::string rep;\n  if (Int128High64(*this) < 0) rep = \"-\";\n  rep.append(Uint128ToFormattedString(UnsignedAbsoluteValue(*this),\n                                      std::ios_base::dec));\n  return rep;\n}\n\nstd::ostream& operator<<(std::ostream& os, int128 v) {\n  std::ios_base::fmtflags flags = os.flags();\n  std::string rep;\n\n  // Add the sign if needed.\n  bool print_as_decimal =\n      (flags & std::ios::basefield) == std::ios::dec ||\n      (flags & std::ios::basefield) == std::ios_base::fmtflags();\n  if (print_as_decimal) {\n    if (Int128High64(v) < 0) {\n      rep = \"-\";\n    } else if (flags & std::ios::showpos) {\n      rep = \"+\";\n    }\n  }\n\n  rep.append(Uint128ToFormattedString(\n      print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags()));\n\n  // Add the requisite padding.\n  std::streamsize width = os.width(0);\n  if (static_cast<size_t>(width) > rep.size()) {\n    const size_t count = static_cast<size_t>(width) - rep.size();\n    switch (flags & std::ios::adjustfield) {\n      case std::ios::left:\n        rep.append(count, os.fill());\n        break;\n      case std::ios::internal:\n        if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) {\n          rep.insert(size_t{1}, count, os.fill());\n        } else if ((flags & std::ios::basefield) == std::ios::hex &&\n                   (flags & std::ios::showbase) && v != 0) {\n          rep.insert(size_t{2}, count, os.fill());\n        } else {\n          rep.insert(size_t{0}, count, os.fill());\n        }\n        break;\n      default:  // std::ios::right\n        rep.insert(size_t{0}, count, os.fill());\n        break;\n    }\n  }\n\n  return os << rep;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/numeric/int128.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: int128.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines 128-bit integer types, `uint128` and `int128`.\n//\n// TODO(absl-team): This module is inconsistent as many inline `uint128` methods\n// are defined in this file, while many inline `int128` methods are defined in\n// the `int128_*_intrinsic.inc` files.\n\n#ifndef ABSL_NUMERIC_INT128_H_\n#define ABSL_NUMERIC_INT128_H_\n\n#include <cassert>\n#include <cmath>\n#include <cstdint>\n#include <cstring>\n#include <iosfwd>\n#include <limits>\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/port.h\"\n#include \"absl/types/compare.h\"\n\n#if defined(_MSC_VER)\n// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is\n// a typedef for unsigned short.  Otherwise wchar_t is mapped to the __wchar_t\n// builtin type.  We need to make sure not to define operator wchar_t()\n// alongside operator unsigned short() in these instances.\n#define ABSL_INTERNAL_WCHAR_T __wchar_t\n#if defined(_M_X64) && !defined(_M_ARM64EC)\n#include <intrin.h>\n#pragma intrinsic(_umul128)\n#endif  // defined(_M_X64)\n#else   // defined(_MSC_VER)\n#define ABSL_INTERNAL_WCHAR_T wchar_t\n#endif  // defined(_MSC_VER)\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass int128;\n\n// uint128\n//\n// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type\n// as closely as is practical, including exhibiting undefined behavior in\n// analogous cases (e.g. division by zero). This type is intended to be a\n// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when\n// that occurs, existing well-behaved uses of `uint128` will continue to work\n// using that new type.\n//\n// Note: code written with this type will continue to compile once `uint128_t`\n// is introduced, provided the replacement helper functions\n// `Uint128(Low|High)64()` and `MakeUint128()` are made.\n//\n// A `uint128` supports the following:\n//\n//   * Implicit construction from integral types\n//   * Explicit conversion to integral types\n//\n// Additionally, if your compiler supports `__int128`, `uint128` is\n// interoperable with that type. (Abseil checks for this compatibility through\n// the `ABSL_HAVE_INTRINSIC_INT128` macro.)\n//\n// However, a `uint128` differs from intrinsic integral types in the following\n// ways:\n//\n//   * Errors on implicit conversions that do not preserve value (such as\n//     loss of precision when converting to float values).\n//   * Requires explicit construction from and conversion to floating point\n//     types.\n//   * Conversion to integral types requires an explicit static_cast() to\n//     mimic use of the `-Wnarrowing` compiler flag.\n//   * The alignment requirement of `uint128` may differ from that of an\n//     intrinsic 128-bit integer type depending on platform and build\n//     configuration.\n//\n// Example:\n//\n//     float y = absl::Uint128Max();  // Error. uint128 cannot be implicitly\n//                                    // converted to float.\n//\n//     absl::uint128 v;\n//     uint64_t i = v;                         // Error\n//     uint64_t i = static_cast<uint64_t>(v);  // OK\n//\nclass\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n    alignas(unsigned __int128)\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n        uint128 {\n public:\n  uint128() = default;\n\n  // Constructors from arithmetic types\n  constexpr uint128(int v);                 // NOLINT(runtime/explicit)\n  constexpr uint128(unsigned int v);        // NOLINT(runtime/explicit)\n  constexpr uint128(long v);                // NOLINT(runtime/int)\n  constexpr uint128(unsigned long v);       // NOLINT(runtime/int)\n  constexpr uint128(long long v);           // NOLINT(runtime/int)\n  constexpr uint128(unsigned long long v);  // NOLINT(runtime/int)\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  constexpr uint128(__int128 v);           // NOLINT(runtime/explicit)\n  constexpr uint128(unsigned __int128 v);  // NOLINT(runtime/explicit)\n#endif                                     // ABSL_HAVE_INTRINSIC_INT128\n  constexpr uint128(int128 v);             // NOLINT(runtime/explicit)\n  explicit uint128(float v);\n  explicit uint128(double v);\n  explicit uint128(long double v);\n\n  // Assignment operators from arithmetic types\n  uint128& operator=(int v);\n  uint128& operator=(unsigned int v);\n  uint128& operator=(long v);                // NOLINT(runtime/int)\n  uint128& operator=(unsigned long v);       // NOLINT(runtime/int)\n  uint128& operator=(long long v);           // NOLINT(runtime/int)\n  uint128& operator=(unsigned long long v);  // NOLINT(runtime/int)\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  uint128& operator=(__int128 v);\n  uint128& operator=(unsigned __int128 v);\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n  uint128& operator=(int128 v);\n\n  // Conversion operators to other arithmetic types\n  constexpr explicit operator bool() const;\n  constexpr explicit operator char() const;\n  constexpr explicit operator signed char() const;\n  constexpr explicit operator unsigned char() const;\n  constexpr explicit operator char16_t() const;\n  constexpr explicit operator char32_t() const;\n  constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;\n  constexpr explicit operator short() const;  // NOLINT(runtime/int)\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator unsigned short() const;\n  constexpr explicit operator int() const;\n  constexpr explicit operator unsigned int() const;\n  constexpr explicit operator long() const;  // NOLINT(runtime/int)\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator unsigned long() const;\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator long long() const;\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator unsigned long long() const;\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  constexpr explicit operator __int128() const;\n  constexpr explicit operator unsigned __int128() const;\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n  constexpr explicit operator float() const;\n  constexpr explicit operator double() const;\n  constexpr explicit operator long double() const;\n\n  // Trivial copy constructor, assignment operator and destructor.\n\n  // Arithmetic operators.\n  uint128& operator+=(uint128 other);\n  uint128& operator-=(uint128 other);\n  uint128& operator*=(uint128 other);\n  // Long division/modulo for uint128.\n  uint128& operator/=(uint128 other);\n  uint128& operator%=(uint128 other);\n  uint128 operator++(int);\n  uint128 operator--(int);\n  uint128& operator<<=(int);\n  uint128& operator>>=(int);\n  uint128& operator&=(uint128 other);\n  uint128& operator|=(uint128 other);\n  uint128& operator^=(uint128 other);\n  uint128& operator++();\n  uint128& operator--();\n\n  // Uint128Low64()\n  //\n  // Returns the lower 64-bit value of a `uint128` value.\n  friend constexpr uint64_t Uint128Low64(uint128 v);\n\n  // Uint128High64()\n  //\n  // Returns the higher 64-bit value of a `uint128` value.\n  friend constexpr uint64_t Uint128High64(uint128 v);\n\n  // MakeUInt128()\n  //\n  // Constructs a `uint128` numeric value from two 64-bit unsigned integers.\n  // Note that this factory function is the only way to construct a `uint128`\n  // from integer values greater than 2^64.\n  //\n  // Example:\n  //\n  //   absl::uint128 big = absl::MakeUint128(1, 0);\n  friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);\n\n  // Uint128Max()\n  //\n  // Returns the highest value for a 128-bit unsigned integer.\n  friend constexpr uint128 Uint128Max();\n\n  // Support for absl::Hash.\n  template <typename H>\n  friend H AbslHashValue(H h, uint128 v) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n    return H::combine(std::move(h), static_cast<unsigned __int128>(v));\n#else\n    return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));\n#endif\n  }\n\n  // Support for absl::StrCat() etc.\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, uint128 v) {\n    sink.Append(v.ToString());\n  }\n\n private:\n  constexpr uint128(uint64_t high, uint64_t low);\n\n  std::string ToString() const;\n\n  // TODO(strel) Update implementation to use __int128 once all users of\n  // uint128 are fixed to not depend on alignof(uint128) == 8. Also add\n  // alignas(16) to class definition to keep alignment consistent across\n  // platforms.\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n  uint64_t lo_;\n  uint64_t hi_;\n#elif defined(ABSL_IS_BIG_ENDIAN)\n  uint64_t hi_;\n  uint64_t lo_;\n#else  // byte order\n#error \"Unsupported byte order: must be little-endian or big-endian.\"\n#endif  // byte order\n};\n\n// allow uint128 to be logged\nstd::ostream& operator<<(std::ostream& os, uint128 v);\n\n// TODO(strel) add operator>>(std::istream&, uint128)\n\nconstexpr uint128 Uint128Max() {\n  return uint128((std::numeric_limits<uint64_t>::max)(),\n                 (std::numeric_limits<uint64_t>::max)());\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// Specialized numeric_limits for uint128.\nnamespace std {\ntemplate <>\nclass numeric_limits<absl::uint128> {\n public:\n  static constexpr bool is_specialized = true;\n  static constexpr bool is_signed = false;\n  static constexpr bool is_integer = true;\n  static constexpr bool is_exact = true;\n  static constexpr bool has_infinity = false;\n  static constexpr bool has_quiet_NaN = false;\n  static constexpr bool has_signaling_NaN = false;\n  ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\n  static constexpr float_denorm_style has_denorm = denorm_absent;\n  ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n  static constexpr bool has_denorm_loss = false;\n  static constexpr float_round_style round_style = round_toward_zero;\n  static constexpr bool is_iec559 = false;\n  static constexpr bool is_bounded = true;\n  static constexpr bool is_modulo = true;\n  static constexpr int digits = 128;\n  static constexpr int digits10 = 38;\n  static constexpr int max_digits10 = 0;\n  static constexpr int radix = 2;\n  static constexpr int min_exponent = 0;\n  static constexpr int min_exponent10 = 0;\n  static constexpr int max_exponent = 0;\n  static constexpr int max_exponent10 = 0;\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  static constexpr bool traps = numeric_limits<unsigned __int128>::traps;\n#else   // ABSL_HAVE_INTRINSIC_INT128\n  static constexpr bool traps = numeric_limits<uint64_t>::traps;\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n  static constexpr bool tinyness_before = false;\n\n  static constexpr absl::uint128(min)() { return 0; }\n  static constexpr absl::uint128 lowest() { return 0; }\n  static constexpr absl::uint128(max)() { return absl::Uint128Max(); }\n  static constexpr absl::uint128 epsilon() { return 0; }\n  static constexpr absl::uint128 round_error() { return 0; }\n  static constexpr absl::uint128 infinity() { return 0; }\n  static constexpr absl::uint128 quiet_NaN() { return 0; }\n  static constexpr absl::uint128 signaling_NaN() { return 0; }\n  static constexpr absl::uint128 denorm_min() { return 0; }\n};\n}  // namespace std\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// int128\n//\n// A signed 128-bit integer type. The API is meant to mimic an intrinsic\n// integral type as closely as is practical, including exhibiting undefined\n// behavior in analogous cases (e.g. division by zero).\n//\n// An `int128` supports the following:\n//\n//   * Implicit construction from integral types\n//   * Explicit conversion to integral types\n//\n// However, an `int128` differs from intrinsic integral types in the following\n// ways:\n//\n//   * It is not implicitly convertible to other integral types.\n//   * Requires explicit construction from and conversion to floating point\n//     types.\n\n// Additionally, if your compiler supports `__int128`, `int128` is\n// interoperable with that type. (Abseil checks for this compatibility through\n// the `ABSL_HAVE_INTRINSIC_INT128` macro.)\n//\n// The design goal for `int128` is that it will be compatible with a future\n// `int128_t`, if that type becomes a part of the standard.\n//\n// Example:\n//\n//     float y = absl::int128(17);  // Error. int128 cannot be implicitly\n//                                  // converted to float.\n//\n//     absl::int128 v;\n//     int64_t i = v;                        // Error\n//     int64_t i = static_cast<int64_t>(v);  // OK\n//\nclass int128 {\n public:\n  int128() = default;\n\n  // Constructors from arithmetic types\n  constexpr int128(int v);                 // NOLINT(runtime/explicit)\n  constexpr int128(unsigned int v);        // NOLINT(runtime/explicit)\n  constexpr int128(long v);                // NOLINT(runtime/int)\n  constexpr int128(unsigned long v);       // NOLINT(runtime/int)\n  constexpr int128(long long v);           // NOLINT(runtime/int)\n  constexpr int128(unsigned long long v);  // NOLINT(runtime/int)\n  constexpr explicit int128(uint128 v);\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  constexpr int128(__int128 v);  // NOLINT(runtime/explicit)\n  constexpr explicit int128(unsigned __int128 v);\n  constexpr explicit int128(float v);\n  constexpr explicit int128(double v);\n  constexpr explicit int128(long double v);\n#else\n  explicit int128(float v);\n  explicit int128(double v);\n  explicit int128(long double v);\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n  // Assignment operators from arithmetic types\n  int128& operator=(int v);\n  int128& operator=(unsigned int v);\n  int128& operator=(long v);                // NOLINT(runtime/int)\n  int128& operator=(unsigned long v);       // NOLINT(runtime/int)\n  int128& operator=(long long v);           // NOLINT(runtime/int)\n  int128& operator=(unsigned long long v);  // NOLINT(runtime/int)\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  int128& operator=(__int128 v);\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n  // Conversion operators to other arithmetic types\n  constexpr explicit operator bool() const;\n  constexpr explicit operator char() const;\n  constexpr explicit operator signed char() const;\n  constexpr explicit operator unsigned char() const;\n  constexpr explicit operator char16_t() const;\n  constexpr explicit operator char32_t() const;\n  constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;\n  constexpr explicit operator short() const;  // NOLINT(runtime/int)\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator unsigned short() const;\n  constexpr explicit operator int() const;\n  constexpr explicit operator unsigned int() const;\n  constexpr explicit operator long() const;  // NOLINT(runtime/int)\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator unsigned long() const;\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator long long() const;\n  // NOLINTNEXTLINE(runtime/int)\n  constexpr explicit operator unsigned long long() const;\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  constexpr explicit operator __int128() const;\n  constexpr explicit operator unsigned __int128() const;\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n  constexpr explicit operator float() const;\n  constexpr explicit operator double() const;\n  constexpr explicit operator long double() const;\n\n  // Trivial copy constructor, assignment operator and destructor.\n\n  // Arithmetic operators\n  int128& operator+=(int128 other);\n  int128& operator-=(int128 other);\n  int128& operator*=(int128 other);\n  int128& operator/=(int128 other);\n  int128& operator%=(int128 other);\n  int128 operator++(int);  // postfix increment: i++\n  int128 operator--(int);  // postfix decrement: i--\n  int128& operator++();    // prefix increment:  ++i\n  int128& operator--();    // prefix decrement:  --i\n  int128& operator&=(int128 other);\n  int128& operator|=(int128 other);\n  int128& operator^=(int128 other);\n  int128& operator<<=(int amount);\n  int128& operator>>=(int amount);\n\n  // Int128Low64()\n  //\n  // Returns the lower 64-bit value of a `int128` value.\n  friend constexpr uint64_t Int128Low64(int128 v);\n\n  // Int128High64()\n  //\n  // Returns the higher 64-bit value of a `int128` value.\n  friend constexpr int64_t Int128High64(int128 v);\n\n  // MakeInt128()\n  //\n  // Constructs a `int128` numeric value from two 64-bit integers. Note that\n  // signedness is conveyed in the upper `high` value.\n  //\n  //   (absl::int128(1) << 64) * high + low\n  //\n  // Note that this factory function is the only way to construct a `int128`\n  // from integer values greater than 2^64 or less than -2^64.\n  //\n  // Example:\n  //\n  //   absl::int128 big = absl::MakeInt128(1, 0);\n  //   absl::int128 big_n = absl::MakeInt128(-1, 0);\n  friend constexpr int128 MakeInt128(int64_t high, uint64_t low);\n\n  // Int128Max()\n  //\n  // Returns the maximum value for a 128-bit signed integer.\n  friend constexpr int128 Int128Max();\n\n  // Int128Min()\n  //\n  // Returns the minimum value for a 128-bit signed integer.\n  friend constexpr int128 Int128Min();\n\n  // Support for absl::Hash.\n  template <typename H>\n  friend H AbslHashValue(H h, int128 v) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n    return H::combine(std::move(h), v.v_);\n#else\n    return H::combine(std::move(h), Int128High64(v), Int128Low64(v));\n#endif\n  }\n\n  // Support for absl::StrCat() etc.\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, int128 v) {\n    sink.Append(v.ToString());\n  }\n\n private:\n  constexpr int128(int64_t high, uint64_t low);\n\n  std::string ToString() const;\n\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  __int128 v_;\n#else  // ABSL_HAVE_INTRINSIC_INT128\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n  uint64_t lo_;\n  int64_t hi_;\n#elif defined(ABSL_IS_BIG_ENDIAN)\n  int64_t hi_;\n  uint64_t lo_;\n#else  // byte order\n#error \"Unsupported byte order: must be little-endian or big-endian.\"\n#endif  // byte order\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n};\n\nstd::ostream& operator<<(std::ostream& os, int128 v);\n\n// TODO(absl-team) add operator>>(std::istream&, int128)\n\nconstexpr int128 Int128Max() {\n  return int128((std::numeric_limits<int64_t>::max)(),\n                (std::numeric_limits<uint64_t>::max)());\n}\n\nconstexpr int128 Int128Min() {\n  return int128((std::numeric_limits<int64_t>::min)(), 0);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// Specialized numeric_limits for int128.\nnamespace std {\ntemplate <>\nclass numeric_limits<absl::int128> {\n public:\n  static constexpr bool is_specialized = true;\n  static constexpr bool is_signed = true;\n  static constexpr bool is_integer = true;\n  static constexpr bool is_exact = true;\n  static constexpr bool has_infinity = false;\n  static constexpr bool has_quiet_NaN = false;\n  static constexpr bool has_signaling_NaN = false;\n  ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\n  static constexpr float_denorm_style has_denorm = denorm_absent;\n  ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n  static constexpr bool has_denorm_loss = false;\n  static constexpr float_round_style round_style = round_toward_zero;\n  static constexpr bool is_iec559 = false;\n  static constexpr bool is_bounded = true;\n  static constexpr bool is_modulo = false;\n  static constexpr int digits = 127;\n  static constexpr int digits10 = 38;\n  static constexpr int max_digits10 = 0;\n  static constexpr int radix = 2;\n  static constexpr int min_exponent = 0;\n  static constexpr int min_exponent10 = 0;\n  static constexpr int max_exponent = 0;\n  static constexpr int max_exponent10 = 0;\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  static constexpr bool traps = numeric_limits<__int128>::traps;\n#else   // ABSL_HAVE_INTRINSIC_INT128\n  static constexpr bool traps = numeric_limits<uint64_t>::traps;\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n  static constexpr bool tinyness_before = false;\n\n  static constexpr absl::int128(min)() { return absl::Int128Min(); }\n  static constexpr absl::int128 lowest() { return absl::Int128Min(); }\n  static constexpr absl::int128(max)() { return absl::Int128Max(); }\n  static constexpr absl::int128 epsilon() { return 0; }\n  static constexpr absl::int128 round_error() { return 0; }\n  static constexpr absl::int128 infinity() { return 0; }\n  static constexpr absl::int128 quiet_NaN() { return 0; }\n  static constexpr absl::int128 signaling_NaN() { return 0; }\n  static constexpr absl::int128 denorm_min() { return 0; }\n};\n}  // namespace std\n\n// --------------------------------------------------------------------------\n//                      Implementation details follow\n// --------------------------------------------------------------------------\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nconstexpr uint128 MakeUint128(uint64_t high, uint64_t low) {\n  return uint128(high, low);\n}\n\n// Assignment from integer types.\n\ninline uint128& uint128::operator=(int v) { return *this = uint128(v); }\n\ninline uint128& uint128::operator=(unsigned int v) {\n  return *this = uint128(v);\n}\n\ninline uint128& uint128::operator=(long v) {  // NOLINT(runtime/int)\n  return *this = uint128(v);\n}\n\n// NOLINTNEXTLINE(runtime/int)\ninline uint128& uint128::operator=(unsigned long v) {\n  return *this = uint128(v);\n}\n\n// NOLINTNEXTLINE(runtime/int)\ninline uint128& uint128::operator=(long long v) { return *this = uint128(v); }\n\n// NOLINTNEXTLINE(runtime/int)\ninline uint128& uint128::operator=(unsigned long long v) {\n  return *this = uint128(v);\n}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\ninline uint128& uint128::operator=(__int128 v) { return *this = uint128(v); }\n\ninline uint128& uint128::operator=(unsigned __int128 v) {\n  return *this = uint128(v);\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\ninline uint128& uint128::operator=(int128 v) { return *this = uint128(v); }\n\n// Arithmetic operators.\n\nconstexpr uint128 operator<<(uint128 lhs, int amount);\nconstexpr uint128 operator>>(uint128 lhs, int amount);\nconstexpr uint128 operator+(uint128 lhs, uint128 rhs);\nconstexpr uint128 operator-(uint128 lhs, uint128 rhs);\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\nconstexpr uint128 operator*(uint128 lhs, uint128 rhs);\nconstexpr uint128 operator/(uint128 lhs, uint128 rhs);\nconstexpr uint128 operator%(uint128 lhs, uint128 rhs);\n#else   // ABSL_HAVE_INTRINSIC_INT128\nuint128 operator*(uint128 lhs, uint128 rhs);\nuint128 operator/(uint128 lhs, uint128 rhs);\nuint128 operator%(uint128 lhs, uint128 rhs);\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\ninline uint128& uint128::operator<<=(int amount) {\n  *this = *this << amount;\n  return *this;\n}\n\ninline uint128& uint128::operator>>=(int amount) {\n  *this = *this >> amount;\n  return *this;\n}\n\ninline uint128& uint128::operator+=(uint128 other) {\n  *this = *this + other;\n  return *this;\n}\n\ninline uint128& uint128::operator-=(uint128 other) {\n  *this = *this - other;\n  return *this;\n}\n\ninline uint128& uint128::operator*=(uint128 other) {\n  *this = *this * other;\n  return *this;\n}\n\ninline uint128& uint128::operator/=(uint128 other) {\n  *this = *this / other;\n  return *this;\n}\n\ninline uint128& uint128::operator%=(uint128 other) {\n  *this = *this % other;\n  return *this;\n}\n\nconstexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }\n\nconstexpr uint64_t Uint128High64(uint128 v) { return v.hi_; }\n\n// Constructors from integer types.\n\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n\nconstexpr uint128::uint128(uint64_t high, uint64_t low) : lo_{low}, hi_{high} {}\n\nconstexpr uint128::uint128(int v)\n    : lo_{static_cast<uint64_t>(v)},\n      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}\nconstexpr uint128::uint128(long v)  // NOLINT(runtime/int)\n    : lo_{static_cast<uint64_t>(v)},\n      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}\nconstexpr uint128::uint128(long long v)  // NOLINT(runtime/int)\n    : lo_{static_cast<uint64_t>(v)},\n      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}\n\nconstexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\nconstexpr uint128::uint128(__int128 v)\n    : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},\n      hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}\nconstexpr uint128::uint128(unsigned __int128 v)\n    : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},\n      hi_{static_cast<uint64_t>(v >> 64)} {}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nconstexpr uint128::uint128(int128 v)\n    : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {}\n\n#elif defined(ABSL_IS_BIG_ENDIAN)\n\nconstexpr uint128::uint128(uint64_t high, uint64_t low) : hi_{high}, lo_{low} {}\n\nconstexpr uint128::uint128(int v)\n    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},\n      lo_{static_cast<uint64_t>(v)} {}\nconstexpr uint128::uint128(long v)  // NOLINT(runtime/int)\n    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},\n      lo_{static_cast<uint64_t>(v)} {}\nconstexpr uint128::uint128(long long v)  // NOLINT(runtime/int)\n    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},\n      lo_{static_cast<uint64_t>(v)} {}\n\nconstexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\nconstexpr uint128::uint128(__int128 v)\n    : hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},\n      lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}\nconstexpr uint128::uint128(unsigned __int128 v)\n    : hi_{static_cast<uint64_t>(v >> 64)},\n      lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nconstexpr uint128::uint128(int128 v)\n    : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {}\n\n#else  // byte order\n#error \"Unsupported byte order: must be little-endian or big-endian.\"\n#endif  // byte order\n\n// Conversion operators to integer types.\n\nconstexpr uint128::operator bool() const { return lo_ || hi_; }\n\nconstexpr uint128::operator char() const { return static_cast<char>(lo_); }\n\nconstexpr uint128::operator signed char() const {\n  return static_cast<signed char>(lo_);\n}\n\nconstexpr uint128::operator unsigned char() const {\n  return static_cast<unsigned char>(lo_);\n}\n\nconstexpr uint128::operator char16_t() const {\n  return static_cast<char16_t>(lo_);\n}\n\nconstexpr uint128::operator char32_t() const {\n  return static_cast<char32_t>(lo_);\n}\n\nconstexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {\n  return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);\n}\n\n// NOLINTNEXTLINE(runtime/int)\nconstexpr uint128::operator short() const { return static_cast<short>(lo_); }\n\nconstexpr uint128::operator unsigned short() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned short>(lo_);            // NOLINT(runtime/int)\n}\n\nconstexpr uint128::operator int() const { return static_cast<int>(lo_); }\n\nconstexpr uint128::operator unsigned int() const {\n  return static_cast<unsigned int>(lo_);\n}\n\n// NOLINTNEXTLINE(runtime/int)\nconstexpr uint128::operator long() const { return static_cast<long>(lo_); }\n\nconstexpr uint128::operator unsigned long() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned long>(lo_);            // NOLINT(runtime/int)\n}\n\nconstexpr uint128::operator long long() const {  // NOLINT(runtime/int)\n  return static_cast<long long>(lo_);            // NOLINT(runtime/int)\n}\n\nconstexpr uint128::operator unsigned long long() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned long long>(lo_);            // NOLINT(runtime/int)\n}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\nconstexpr uint128::operator __int128() const {\n  return (static_cast<__int128>(hi_) << 64) + lo_;\n}\n\nconstexpr uint128::operator unsigned __int128() const {\n  return (static_cast<unsigned __int128>(hi_) << 64) + lo_;\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n// Conversion operators to floating point types.\n\nconstexpr uint128::operator float() const {\n  // Note: This method might return Inf.\n  constexpr float pow_2_64 = 18446744073709551616.0f;\n  return static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64;\n}\n\nconstexpr uint128::operator double() const {\n  constexpr double pow_2_64 = 18446744073709551616.0;\n  return static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64;\n}\n\nconstexpr uint128::operator long double() const {\n  constexpr long double pow_2_64 = 18446744073709551616.0L;\n  return static_cast<long double>(lo_) +\n         static_cast<long double>(hi_) * pow_2_64;\n}\n\n// Comparison operators.\n\nconstexpr bool operator==(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return static_cast<unsigned __int128>(lhs) ==\n         static_cast<unsigned __int128>(rhs);\n#else\n  return (Uint128Low64(lhs) == Uint128Low64(rhs) &&\n          Uint128High64(lhs) == Uint128High64(rhs));\n#endif\n}\n\nconstexpr bool operator!=(uint128 lhs, uint128 rhs) { return !(lhs == rhs); }\n\nconstexpr bool operator<(uint128 lhs, uint128 rhs) {\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  return static_cast<unsigned __int128>(lhs) <\n         static_cast<unsigned __int128>(rhs);\n#else\n  return (Uint128High64(lhs) == Uint128High64(rhs))\n             ? (Uint128Low64(lhs) < Uint128Low64(rhs))\n             : (Uint128High64(lhs) < Uint128High64(rhs));\n#endif\n}\n\nconstexpr bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }\n\nconstexpr bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }\n\nconstexpr bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }\n\n#ifdef __cpp_impl_three_way_comparison\nconstexpr absl::strong_ordering operator<=>(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  if (auto lhs_128 = static_cast<unsigned __int128>(lhs),\n      rhs_128 = static_cast<unsigned __int128>(rhs);\n      lhs_128 < rhs_128) {\n    return absl::strong_ordering::less;\n  } else if (lhs_128 > rhs_128) {\n    return absl::strong_ordering::greater;\n  } else {\n    return absl::strong_ordering::equal;\n  }\n#else\n  if (uint64_t lhs_high = Uint128High64(lhs), rhs_high = Uint128High64(rhs);\n      lhs_high < rhs_high) {\n    return absl::strong_ordering::less;\n  } else if (lhs_high > rhs_high) {\n    return absl::strong_ordering::greater;\n  } else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs);\n             lhs_low < rhs_low) {\n    return absl::strong_ordering::less;\n  } else if (lhs_low > rhs_low) {\n    return absl::strong_ordering::greater;\n  } else {\n    return absl::strong_ordering::equal;\n  }\n#endif\n}\n#endif\n\n// Unary operators.\n\nconstexpr inline uint128 operator+(uint128 val) { return val; }\n\nconstexpr inline int128 operator+(int128 val) { return val; }\n\nconstexpr uint128 operator-(uint128 val) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return -static_cast<unsigned __int128>(val);\n#else\n  return MakeUint128(\n      ~Uint128High64(val) + static_cast<unsigned long>(Uint128Low64(val) == 0),\n      ~Uint128Low64(val) + 1);\n#endif\n}\n\nconstexpr inline bool operator!(uint128 val) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return !static_cast<unsigned __int128>(val);\n#else\n  return !Uint128High64(val) && !Uint128Low64(val);\n#endif\n}\n\n// Logical operators.\n\nconstexpr inline uint128 operator~(uint128 val) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return ~static_cast<unsigned __int128>(val);\n#else\n  return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));\n#endif\n}\n\nconstexpr inline uint128 operator|(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return static_cast<unsigned __int128>(lhs) |\n         static_cast<unsigned __int128>(rhs);\n#else\n  return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),\n                     Uint128Low64(lhs) | Uint128Low64(rhs));\n#endif\n}\n\nconstexpr inline uint128 operator&(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return static_cast<unsigned __int128>(lhs) &\n         static_cast<unsigned __int128>(rhs);\n#else\n  return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),\n                     Uint128Low64(lhs) & Uint128Low64(rhs));\n#endif\n}\n\nconstexpr inline uint128 operator^(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return static_cast<unsigned __int128>(lhs) ^\n         static_cast<unsigned __int128>(rhs);\n#else\n  return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),\n                     Uint128Low64(lhs) ^ Uint128Low64(rhs));\n#endif\n}\n\ninline uint128& uint128::operator|=(uint128 other) {\n  *this = *this | other;\n  return *this;\n}\n\ninline uint128& uint128::operator&=(uint128 other) {\n  *this = *this & other;\n  return *this;\n}\n\ninline uint128& uint128::operator^=(uint128 other) {\n  *this = *this ^ other;\n  return *this;\n}\n\n// Arithmetic operators.\n\nconstexpr uint128 operator<<(uint128 lhs, int amount) {\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  return static_cast<unsigned __int128>(lhs) << amount;\n#else\n  // uint64_t shifts of >= 64 are undefined, so we will need some\n  // special-casing.\n  return amount >= 64  ? MakeUint128(Uint128Low64(lhs) << (amount - 64), 0)\n         : amount == 0 ? lhs\n                       : MakeUint128((Uint128High64(lhs) << amount) |\n                                         (Uint128Low64(lhs) >> (64 - amount)),\n                                     Uint128Low64(lhs) << amount);\n#endif\n}\n\nconstexpr uint128 operator>>(uint128 lhs, int amount) {\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  return static_cast<unsigned __int128>(lhs) >> amount;\n#else\n  // uint64_t shifts of >= 64 are undefined, so we will need some\n  // special-casing.\n  return amount >= 64  ? MakeUint128(0, Uint128High64(lhs) >> (amount - 64))\n         : amount == 0 ? lhs\n                       : MakeUint128(Uint128High64(lhs) >> amount,\n                                     (Uint128Low64(lhs) >> amount) |\n                                         (Uint128High64(lhs) << (64 - amount)));\n#endif\n}\n\n#if !defined(ABSL_HAVE_INTRINSIC_INT128)\nnamespace int128_internal {\nconstexpr uint128 AddResult(uint128 result, uint128 lhs) {\n  // check for carry\n  return (Uint128Low64(result) < Uint128Low64(lhs))\n             ? MakeUint128(Uint128High64(result) + 1, Uint128Low64(result))\n             : result;\n}\n}  // namespace int128_internal\n#endif\n\nconstexpr uint128 operator+(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return static_cast<unsigned __int128>(lhs) +\n         static_cast<unsigned __int128>(rhs);\n#else\n  return int128_internal::AddResult(\n      MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),\n                  Uint128Low64(lhs) + Uint128Low64(rhs)),\n      lhs);\n#endif\n}\n\n#if !defined(ABSL_HAVE_INTRINSIC_INT128)\nnamespace int128_internal {\nconstexpr uint128 SubstructResult(uint128 result, uint128 lhs, uint128 rhs) {\n  // check for carry\n  return (Uint128Low64(lhs) < Uint128Low64(rhs))\n             ? MakeUint128(Uint128High64(result) - 1, Uint128Low64(result))\n             : result;\n}\n}  // namespace int128_internal\n#endif\n\nconstexpr uint128 operator-(uint128 lhs, uint128 rhs) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  return static_cast<unsigned __int128>(lhs) -\n         static_cast<unsigned __int128>(rhs);\n#else\n  return int128_internal::SubstructResult(\n      MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),\n                  Uint128Low64(lhs) - Uint128Low64(rhs)),\n      lhs, rhs);\n#endif\n}\n\n#if !defined(ABSL_HAVE_INTRINSIC_INT128)\ninline uint128 operator*(uint128 lhs, uint128 rhs) {\n#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)\n  uint64_t carry;\n  uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);\n  return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +\n                         Uint128High64(lhs) * Uint128Low64(rhs) + carry,\n                     low);\n#else   // _MSC_VER\n  uint64_t a32 = Uint128Low64(lhs) >> 32;\n  uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;\n  uint64_t b32 = Uint128Low64(rhs) >> 32;\n  uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;\n  uint128 result =\n      MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +\n                      Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,\n                  a00 * b00);\n  result += uint128(a32 * b00) << 32;\n  result += uint128(a00 * b32) << 32;\n  return result;\n#endif  // _MSC_VER\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\nconstexpr uint128 operator*(uint128 lhs, uint128 rhs) {\n  // TODO(strel) Remove once alignment issues are resolved and unsigned __int128\n  // can be used for uint128 storage.\n  return static_cast<unsigned __int128>(lhs) *\n         static_cast<unsigned __int128>(rhs);\n}\n\nconstexpr uint128 operator/(uint128 lhs, uint128 rhs) {\n  return static_cast<unsigned __int128>(lhs) /\n         static_cast<unsigned __int128>(rhs);\n}\n\nconstexpr uint128 operator%(uint128 lhs, uint128 rhs) {\n  return static_cast<unsigned __int128>(lhs) %\n         static_cast<unsigned __int128>(rhs);\n}\n#endif\n\n// Increment/decrement operators.\n\ninline uint128 uint128::operator++(int) {\n  uint128 tmp(*this);\n  *this += 1;\n  return tmp;\n}\n\ninline uint128 uint128::operator--(int) {\n  uint128 tmp(*this);\n  *this -= 1;\n  return tmp;\n}\n\ninline uint128& uint128::operator++() {\n  *this += 1;\n  return *this;\n}\n\ninline uint128& uint128::operator--() {\n  *this -= 1;\n  return *this;\n}\n\nconstexpr int128 MakeInt128(int64_t high, uint64_t low) {\n  return int128(high, low);\n}\n\n// Assignment from integer types.\ninline int128& int128::operator=(int v) { return *this = int128(v); }\n\ninline int128& int128::operator=(unsigned int v) { return *this = int128(v); }\n\ninline int128& int128::operator=(long v) {  // NOLINT(runtime/int)\n  return *this = int128(v);\n}\n\n// NOLINTNEXTLINE(runtime/int)\ninline int128& int128::operator=(unsigned long v) { return *this = int128(v); }\n\n// NOLINTNEXTLINE(runtime/int)\ninline int128& int128::operator=(long long v) { return *this = int128(v); }\n\n// NOLINTNEXTLINE(runtime/int)\ninline int128& int128::operator=(unsigned long long v) {\n  return *this = int128(v);\n}\n\n// Arithmetic operators.\nconstexpr int128 operator-(int128 v);\nconstexpr int128 operator+(int128 lhs, int128 rhs);\nconstexpr int128 operator-(int128 lhs, int128 rhs);\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\nconstexpr int128 operator*(int128 lhs, int128 rhs);\nconstexpr int128 operator/(int128 lhs, int128 rhs);\nconstexpr int128 operator%(int128 lhs, int128 rhs);\n#else\nint128 operator*(int128 lhs, int128 rhs);\nint128 operator/(int128 lhs, int128 rhs);\nint128 operator%(int128 lhs, int128 rhs);\n#endif  // ABSL_HAVE_INTRINSIC_INT128\nconstexpr int128 operator|(int128 lhs, int128 rhs);\nconstexpr int128 operator&(int128 lhs, int128 rhs);\nconstexpr int128 operator^(int128 lhs, int128 rhs);\nconstexpr int128 operator<<(int128 lhs, int amount);\nconstexpr int128 operator>>(int128 lhs, int amount);\n\ninline int128& int128::operator+=(int128 other) {\n  *this = *this + other;\n  return *this;\n}\n\ninline int128& int128::operator-=(int128 other) {\n  *this = *this - other;\n  return *this;\n}\n\ninline int128& int128::operator*=(int128 other) {\n  *this = *this * other;\n  return *this;\n}\n\ninline int128& int128::operator/=(int128 other) {\n  *this = *this / other;\n  return *this;\n}\n\ninline int128& int128::operator%=(int128 other) {\n  *this = *this % other;\n  return *this;\n}\n\ninline int128& int128::operator|=(int128 other) {\n  *this = *this | other;\n  return *this;\n}\n\ninline int128& int128::operator&=(int128 other) {\n  *this = *this & other;\n  return *this;\n}\n\ninline int128& int128::operator^=(int128 other) {\n  *this = *this ^ other;\n  return *this;\n}\n\ninline int128& int128::operator<<=(int amount) {\n  *this = *this << amount;\n  return *this;\n}\n\ninline int128& int128::operator>>=(int amount) {\n  *this = *this >> amount;\n  return *this;\n}\n\n// Forward declaration for comparison operators.\nconstexpr bool operator!=(int128 lhs, int128 rhs);\n\nnamespace int128_internal {\n\n// Casts from unsigned to signed while preserving the underlying binary\n// representation.\nconstexpr int64_t BitCastToSigned(uint64_t v) {\n  // Casting an unsigned integer to a signed integer of the same\n  // width is implementation defined behavior if the source value would not fit\n  // in the destination type. We step around it with a roundtrip bitwise not\n  // operation to make sure this function remains constexpr. Clang, GCC, and\n  // MSVC optimize this to a no-op on x86-64.\n  return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v)\n                                 : static_cast<int64_t>(v);\n}\n\n}  // namespace int128_internal\n\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n#include \"absl/numeric/int128_have_intrinsic.inc\"  // IWYU pragma: export\n#else  // ABSL_HAVE_INTRINSIC_INT128\n#include \"absl/numeric/int128_no_intrinsic.inc\"  // IWYU pragma: export\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_INTERNAL_WCHAR_T\n\n#endif  // ABSL_NUMERIC_INT128_H_\n"
  },
  {
    "path": "absl/numeric/int128_benchmark.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <random>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/random.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nconstexpr size_t kSampleSize = 1000000;\n\ntemplate <typename T,\n          typename H = typename std::conditional<\n              std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>\nstd::vector<std::pair<T, T>> GetRandomClass128SampleUniformDivisor() {\n  std::vector<std::pair<T, T>> values;\n  absl::InsecureBitGen random;\n  std::uniform_int_distribution<H> uniform_h;\n  values.reserve(kSampleSize);\n  for (size_t i = 0; i < kSampleSize; ++i) {\n    T a{absl::MakeUint128(uniform_h(random), uniform_h(random))};\n    T b{absl::MakeUint128(uniform_h(random), uniform_h(random))};\n    values.emplace_back(std::max(a, b), std::max(T(2), std::min(a, b)));\n  }\n  return values;\n}\n\ntemplate <typename T>\nvoid BM_DivideClass128UniformDivisor(benchmark::State& state) {\n  auto values = GetRandomClass128SampleUniformDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first / pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_DivideClass128UniformDivisor, absl::uint128);\nBENCHMARK_TEMPLATE(BM_DivideClass128UniformDivisor, absl::int128);\n\ntemplate <typename T>\nvoid BM_RemainderClass128UniformDivisor(benchmark::State& state) {\n  auto values = GetRandomClass128SampleUniformDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first % pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_RemainderClass128UniformDivisor, absl::uint128);\nBENCHMARK_TEMPLATE(BM_RemainderClass128UniformDivisor, absl::int128);\n\ntemplate <typename T,\n          typename H = typename std::conditional<\n              std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>\nstd::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() {\n  std::vector<std::pair<T, H>> values;\n  absl::InsecureBitGen random;\n  std::uniform_int_distribution<H> uniform_h;\n  values.reserve(kSampleSize);\n  for (size_t i = 0; i < kSampleSize; ++i) {\n    T a{absl::MakeUint128(uniform_h(random), uniform_h(random))};\n    H b{std::max(H{2}, uniform_h(random))};\n    values.emplace_back(std::max(a, T(b)), b);\n  }\n  return values;\n}\n\ntemplate <typename T>\nvoid BM_DivideClass128SmallDivisor(benchmark::State& state) {\n  auto values = GetRandomClass128SampleSmallDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first / pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::uint128);\nBENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::int128);\n\ntemplate <typename T>\nvoid BM_RemainderClass128SmallDivisor(benchmark::State& state) {\n  auto values = GetRandomClass128SampleSmallDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first % pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::uint128);\nBENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::int128);\n\nstd::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {\n  std::vector<std::pair<absl::uint128, absl::uint128>> values;\n  absl::InsecureBitGen random;\n  std::uniform_int_distribution<uint64_t> uniform_uint64;\n  values.reserve(kSampleSize);\n  for (size_t i = 0; i < kSampleSize; ++i) {\n    values.emplace_back(\n        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)),\n        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random)));\n  }\n  return values;\n}\n\nvoid BM_MultiplyClass128(benchmark::State& state) {\n  auto values = GetRandomClass128Sample();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first * pair.second);\n    }\n  }\n}\nBENCHMARK(BM_MultiplyClass128);\n\nvoid BM_AddClass128(benchmark::State& state) {\n  auto values = GetRandomClass128Sample();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first + pair.second);\n    }\n  }\n}\nBENCHMARK(BM_AddClass128);\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n\n// Some implementations of <random> do not support __int128 when it is\n// available, so we make our own uniform_int_distribution-like type.\ntemplate <typename T,\n          typename H = typename std::conditional<\n              std::is_same<T, __int128>::value, int64_t, uint64_t>::type>\nclass UniformIntDistribution128 {\n public:\n  // NOLINTNEXTLINE: mimicking std::uniform_int_distribution API\n  template <class URBG>\n  T operator()(URBG& generator) {\n    return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator);\n  }\n\n private:\n  std::uniform_int_distribution<H> dist64_;\n};\n\ntemplate <typename T,\n          typename H = typename std::conditional<\n              std::is_same<T, __int128>::value, int64_t, uint64_t>::type>\nstd::vector<std::pair<T, T>> GetRandomIntrinsic128SampleUniformDivisor() {\n  std::vector<std::pair<T, T>> values;\n  absl::InsecureBitGen random;\n  UniformIntDistribution128<T> uniform_128;\n  values.reserve(kSampleSize);\n  for (size_t i = 0; i < kSampleSize; ++i) {\n    T a = uniform_128(random);\n    T b = uniform_128(random);\n    values.emplace_back(std::max(a, b),\n                        std::max(static_cast<T>(2), std::min(a, b)));\n  }\n  return values;\n}\n\ntemplate <typename T>\nvoid BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) {\n  auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first / pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, unsigned __int128);\nBENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, __int128);\n\ntemplate <typename T>\nvoid BM_RemainderIntrinsic128UniformDivisor(benchmark::State& state) {\n  auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first % pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, unsigned __int128);\nBENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, __int128);\n\ntemplate <typename T,\n          typename H = typename std::conditional<\n              std::is_same<T, __int128>::value, int64_t, uint64_t>::type>\nstd::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() {\n  std::vector<std::pair<T, H>> values;\n  absl::InsecureBitGen random;\n  UniformIntDistribution128<T> uniform_int128;\n  std::uniform_int_distribution<H> uniform_int64;\n  values.reserve(kSampleSize);\n  for (size_t i = 0; i < kSampleSize; ++i) {\n    T a = uniform_int128(random);\n    H b = std::max(H{2}, uniform_int64(random));\n    values.emplace_back(std::max(a, static_cast<T>(b)), b);\n  }\n  return values;\n}\n\ntemplate <typename T>\nvoid BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) {\n  auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first / pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, unsigned __int128);\nBENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __int128);\n\ntemplate <typename T>\nvoid BM_RemainderIntrinsic128SmallDivisor(benchmark::State& state) {\n  auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first % pair.second);\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, unsigned __int128);\nBENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128);\n\nstd::vector<std::pair<unsigned __int128, unsigned __int128>>\nGetRandomIntrinsic128Sample() {\n  std::vector<std::pair<unsigned __int128, unsigned __int128>> values;\n  absl::InsecureBitGen random;\n  UniformIntDistribution128<unsigned __int128> uniform_uint128;\n  values.reserve(kSampleSize);\n  for (size_t i = 0; i < kSampleSize; ++i) {\n    values.emplace_back(uniform_uint128(random), uniform_uint128(random));\n  }\n  return values;\n}\n\nvoid BM_MultiplyIntrinsic128(benchmark::State& state) {\n  auto values = GetRandomIntrinsic128Sample();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first * pair.second);\n    }\n  }\n}\nBENCHMARK(BM_MultiplyIntrinsic128);\n\nvoid BM_AddIntrinsic128(benchmark::State& state) {\n  auto values = GetRandomIntrinsic128Sample();\n  while (state.KeepRunningBatch(values.size())) {\n    for (const auto& pair : values) {\n      benchmark::DoNotOptimize(pair.first + pair.second);\n    }\n  }\n}\nBENCHMARK(BM_AddIntrinsic128);\n\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n}  // namespace\n"
  },
  {
    "path": "absl/numeric/int128_have_intrinsic.inc",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file contains :int128 implementation details that depend on internal\n// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is\n// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.\n\nnamespace int128_internal {\n\n// Casts from unsigned to signed while preserving the underlying binary\n// representation.\nconstexpr __int128 BitCastToSigned(unsigned __int128 v) {\n  // Casting an unsigned integer to a signed integer of the same\n  // width is implementation defined behavior if the source value would not fit\n  // in the destination type. We step around it with a roundtrip bitwise not\n  // operation to make sure this function remains constexpr. Clang and GCC\n  // optimize this to a no-op on x86-64.\n  return v & (static_cast<unsigned __int128>(1) << 127)\n             ? ~static_cast<__int128>(~v)\n             : static_cast<__int128>(v);\n}\n\n}  // namespace int128_internal\n\ninline int128& int128::operator=(__int128 v) {\n  v_ = v;\n  return *this;\n}\n\nconstexpr uint64_t Int128Low64(int128 v) {\n  return static_cast<uint64_t>(v.v_ & ~uint64_t{0});\n}\n\nconstexpr int64_t Int128High64(int128 v) {\n  // Initially cast to unsigned to prevent a right shift on a negative value.\n  return int128_internal::BitCastToSigned(\n      static_cast<uint64_t>(static_cast<unsigned __int128>(v.v_) >> 64));\n}\n\nconstexpr int128::int128(int64_t high, uint64_t low)\n    // Initially cast to unsigned to prevent a left shift that overflows.\n    : v_(int128_internal::BitCastToSigned(static_cast<unsigned __int128>(high)\n                                           << 64) |\n         low) {}\n\n\nconstexpr int128::int128(int v) : v_{v} {}\n\nconstexpr int128::int128(long v) : v_{v} {}       // NOLINT(runtime/int)\n\nconstexpr int128::int128(long long v) : v_{v} {}  // NOLINT(runtime/int)\n\nconstexpr int128::int128(__int128 v) : v_{v} {}\n\nconstexpr int128::int128(unsigned int v) : v_{v} {}\n\nconstexpr int128::int128(unsigned long v) : v_{v} {}  // NOLINT(runtime/int)\n\n// NOLINTNEXTLINE(runtime/int)\nconstexpr int128::int128(unsigned long long v) : v_{v} {}\n\nconstexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {}\n\nconstexpr int128::int128(float v) : v_{static_cast<__int128>(v)} {}\n\nconstexpr int128::int128(double v) : v_{static_cast<__int128>(v)} {}\n\nconstexpr int128::int128(long double v) : v_{static_cast<__int128>(v)} {}\n\nconstexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {}\n\nconstexpr int128::operator bool() const { return static_cast<bool>(v_); }\n\nconstexpr int128::operator char() const { return static_cast<char>(v_); }\n\nconstexpr int128::operator signed char() const {\n  return static_cast<signed char>(v_);\n}\n\nconstexpr int128::operator unsigned char() const {\n  return static_cast<unsigned char>(v_);\n}\n\nconstexpr int128::operator char16_t() const {\n  return static_cast<char16_t>(v_);\n}\n\nconstexpr int128::operator char32_t() const {\n  return static_cast<char32_t>(v_);\n}\n\nconstexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {\n  return static_cast<ABSL_INTERNAL_WCHAR_T>(v_);\n}\n\nconstexpr int128::operator short() const {  // NOLINT(runtime/int)\n  return static_cast<short>(v_);            // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator unsigned short() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned short>(v_);            // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator int() const { return static_cast<int>(v_); }\n\nconstexpr int128::operator unsigned int() const {\n  return static_cast<unsigned int>(v_);\n}\n\nconstexpr int128::operator long() const {  // NOLINT(runtime/int)\n  return static_cast<long>(v_);            // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator unsigned long() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned long>(v_);            // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator long long() const {  // NOLINT(runtime/int)\n  return static_cast<long long>(v_);            // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator unsigned long long() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned long long>(v_);            // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator __int128() const { return v_; }\n\nconstexpr int128::operator unsigned __int128() const {\n  return static_cast<unsigned __int128>(v_);\n}\n\n// Clang on PowerPC sometimes produces incorrect __int128 to floating point\n// conversions. In that case, we do the conversion with a similar implementation\n// to the conversion operators in int128_no_intrinsic.inc.\n#if defined(__clang__) && !defined(__ppc64__)\nconstexpr int128::operator float() const { return static_cast<float>(v_); }\n\nconstexpr int128::operator double() const { return static_cast<double>(v_); }\n\nconstexpr int128::operator long double() const {\n  return static_cast<long double>(v_);\n}\n\n#else   // Clang on PowerPC\n\nconstexpr int128::operator float() const {\n  // We must convert the absolute value and then negate as needed, because\n  // floating point types are typically sign-magnitude. Otherwise, the\n  // difference between the high and low 64 bits when interpreted as two's\n  // complement overwhelms the precision of the mantissa.\n  //\n  // Also check to make sure we don't negate Int128Min()\n  constexpr float pow_2_64 = 18446744073709551616.0f;\n  return v_ < 0 && *this != Int128Min()\n             ? -static_cast<float>(-*this)\n             : static_cast<float>(Int128Low64(*this)) +\n                   static_cast<float>(Int128High64(*this)) * pow_2_64;\n}\n\nconstexpr int128::operator double() const {\n  // See comment in int128::operator float() above.\n  constexpr double pow_2_64 = 18446744073709551616.0;\n  return v_ < 0 && *this != Int128Min()\n             ? -static_cast<double>(-*this)\n             : static_cast<double>(Int128Low64(*this)) +\n                   static_cast<double>(Int128High64(*this)) * pow_2_64;\n}\n\nconstexpr int128::operator long double() const {\n  // See comment in int128::operator float() above.\n  constexpr long double pow_2_64 = 18446744073709551616.0L;\n  return v_ < 0 && *this != Int128Min()\n             ? -static_cast<long double>(-*this)\n             : static_cast<long double>(Int128Low64(*this)) +\n                   static_cast<long double>(Int128High64(*this)) * pow_2_64;\n}\n#endif  // Clang on PowerPC\n\n// Comparison operators.\n\nconstexpr bool operator==(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) == static_cast<__int128>(rhs);\n}\n\nconstexpr bool operator!=(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) != static_cast<__int128>(rhs);\n}\n\nconstexpr bool operator<(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) < static_cast<__int128>(rhs);\n}\n\nconstexpr bool operator>(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) > static_cast<__int128>(rhs);\n}\n\nconstexpr bool operator<=(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs);\n}\n\nconstexpr bool operator>=(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs);\n}\n\n#ifdef __cpp_impl_three_way_comparison\nconstexpr absl::strong_ordering operator<=>(int128 lhs, int128 rhs) {\n  if (auto lhs_128 = static_cast<__int128>(lhs),\n      rhs_128 = static_cast<__int128>(rhs);\n      lhs_128 < rhs_128) {\n    return absl::strong_ordering::less;\n  } else if (lhs_128 > rhs_128) {\n    return absl::strong_ordering::greater;\n  } else {\n    return absl::strong_ordering::equal;\n  }\n}\n#endif\n\n// Unary operators.\n\nconstexpr int128 operator-(int128 v) { return -static_cast<__int128>(v); }\n\nconstexpr bool operator!(int128 v) { return !static_cast<__int128>(v); }\n\nconstexpr int128 operator~(int128 val) { return ~static_cast<__int128>(val); }\n\n// Arithmetic operators.\n\nconstexpr int128 operator+(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) + static_cast<__int128>(rhs);\n}\n\nconstexpr int128 operator-(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) - static_cast<__int128>(rhs);\n}\n\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\nconstexpr int128 operator*(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) * static_cast<__int128>(rhs);\n}\n\nconstexpr int128 operator/(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) / static_cast<__int128>(rhs);\n}\n\nconstexpr int128 operator%(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) % static_cast<__int128>(rhs);\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\ninline int128 int128::operator++(int) {\n  int128 tmp(*this);\n  ++v_;\n  return tmp;\n}\n\ninline int128 int128::operator--(int) {\n  int128 tmp(*this);\n  --v_;\n  return tmp;\n}\n\ninline int128& int128::operator++() {\n  ++v_;\n  return *this;\n}\n\ninline int128& int128::operator--() {\n  --v_;\n  return *this;\n}\n\nconstexpr int128 operator|(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) | static_cast<__int128>(rhs);\n}\n\nconstexpr int128 operator&(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) & static_cast<__int128>(rhs);\n}\n\nconstexpr int128 operator^(int128 lhs, int128 rhs) {\n  return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs);\n}\n\nconstexpr int128 operator<<(int128 lhs, int amount) {\n  return static_cast<__int128>(lhs) << amount;\n}\n\nconstexpr int128 operator>>(int128 lhs, int amount) {\n  return static_cast<__int128>(lhs) >> amount;\n}\n"
  },
  {
    "path": "absl/numeric/int128_no_intrinsic.inc",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file contains :int128 implementation details that depend on internal\n// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file\n// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.\n\nconstexpr uint64_t Int128Low64(int128 v) { return v.lo_; }\n\nconstexpr int64_t Int128High64(int128 v) { return v.hi_; }\n\n#if defined(ABSL_IS_LITTLE_ENDIAN)\n\nconstexpr int128::int128(int64_t high, uint64_t low) : lo_(low), hi_(high) {}\n\nconstexpr int128::int128(int v)\n    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}\nconstexpr int128::int128(long v)  // NOLINT(runtime/int)\n    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}\nconstexpr int128::int128(long long v)  // NOLINT(runtime/int)\n    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}\n\nconstexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {}\n\nconstexpr int128::int128(uint128 v)\n    : lo_{Uint128Low64(v)}, hi_{static_cast<int64_t>(Uint128High64(v))} {}\n\n#elif defined(ABSL_IS_BIG_ENDIAN)\n\nconstexpr int128::int128(int64_t high, uint64_t low) : hi_{high}, lo_{low} {}\n\nconstexpr int128::int128(int v)\n    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}\nconstexpr int128::int128(long v)  // NOLINT(runtime/int)\n    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}\nconstexpr int128::int128(long long v)  // NOLINT(runtime/int)\n    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}\n\nconstexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {}\n// NOLINTNEXTLINE(runtime/int)\nconstexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {}\n\nconstexpr int128::int128(uint128 v)\n    : hi_{static_cast<int64_t>(Uint128High64(v))}, lo_{Uint128Low64(v)} {}\n\n#else  // byte order\n#error \"Unsupported byte order: must be little-endian or big-endian.\"\n#endif  // byte order\n\nconstexpr int128::operator bool() const { return lo_ || hi_; }\n\nconstexpr int128::operator char() const {\n  // NOLINTNEXTLINE(runtime/int)\n  return static_cast<char>(static_cast<long long>(*this));\n}\n\nconstexpr int128::operator signed char() const {\n  // NOLINTNEXTLINE(runtime/int)\n  return static_cast<signed char>(static_cast<long long>(*this));\n}\n\nconstexpr int128::operator unsigned char() const {\n  return static_cast<unsigned char>(lo_);\n}\n\nconstexpr int128::operator char16_t() const {\n  return static_cast<char16_t>(lo_);\n}\n\nconstexpr int128::operator char32_t() const {\n  return static_cast<char32_t>(lo_);\n}\n\nconstexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {\n  // NOLINTNEXTLINE(runtime/int)\n  return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this));\n}\n\nconstexpr int128::operator short() const {  // NOLINT(runtime/int)\n  // NOLINTNEXTLINE(runtime/int)\n  return static_cast<short>(static_cast<long long>(*this));\n}\n\nconstexpr int128::operator unsigned short() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned short>(lo_);           // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator int() const {\n  // NOLINTNEXTLINE(runtime/int)\n  return static_cast<int>(static_cast<long long>(*this));\n}\n\nconstexpr int128::operator unsigned int() const {\n  return static_cast<unsigned int>(lo_);\n}\n\nconstexpr int128::operator long() const {  // NOLINT(runtime/int)\n  // NOLINTNEXTLINE(runtime/int)\n  return static_cast<long>(static_cast<long long>(*this));\n}\n\nconstexpr int128::operator unsigned long() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned long>(lo_);           // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator long long() const {  // NOLINT(runtime/int)\n  // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit\n  // must be set in order for the value to fit into a long long. Conversely, if\n  // lo_'s high bit is set, *this must be < 0 for the value to fit.\n  return int128_internal::BitCastToSigned(lo_);\n}\n\nconstexpr int128::operator unsigned long long() const {  // NOLINT(runtime/int)\n  return static_cast<unsigned long long>(lo_);           // NOLINT(runtime/int)\n}\n\nconstexpr int128::operator float() const {\n  // We must convert the absolute value and then negate as needed, because\n  // floating point types are typically sign-magnitude. Otherwise, the\n  // difference between the high and low 64 bits when interpreted as two's\n  // complement overwhelms the precision of the mantissa.\n  //\n  // Also check to make sure we don't negate Int128Min()\n  constexpr float pow_2_64 = 18446744073709551616.0f;\n  return hi_ < 0 && *this != Int128Min()\n             ? -static_cast<float>(-*this)\n             : static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64;\n}\n\nconstexpr int128::operator double() const {\n  // See comment in int128::operator float() above.\n  constexpr double pow_2_64 = 18446744073709551616.0;\n  return hi_ < 0 && *this != Int128Min()\n             ? -static_cast<double>(-*this)\n             : static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64;\n}\n\nconstexpr int128::operator long double() const {\n  // See comment in int128::operator float() above.\n  constexpr long double pow_2_64 = 18446744073709551616.0L;\n  return hi_ < 0 && *this != Int128Min()\n             ? -static_cast<long double>(-*this)\n             : static_cast<long double>(lo_) +\n                   static_cast<long double>(hi_) * pow_2_64;\n}\n\n// Comparison operators.\n\nconstexpr bool operator==(int128 lhs, int128 rhs) {\n  return (Int128Low64(lhs) == Int128Low64(rhs) &&\n          Int128High64(lhs) == Int128High64(rhs));\n}\n\nconstexpr bool operator!=(int128 lhs, int128 rhs) { return !(lhs == rhs); }\n\nconstexpr bool operator<(int128 lhs, int128 rhs) {\n  return (Int128High64(lhs) == Int128High64(rhs))\n             ? (Int128Low64(lhs) < Int128Low64(rhs))\n             : (Int128High64(lhs) < Int128High64(rhs));\n}\n\nconstexpr bool operator>(int128 lhs, int128 rhs) {\n  return (Int128High64(lhs) == Int128High64(rhs))\n             ? (Int128Low64(lhs) > Int128Low64(rhs))\n             : (Int128High64(lhs) > Int128High64(rhs));\n}\n\nconstexpr bool operator<=(int128 lhs, int128 rhs) { return !(lhs > rhs); }\n\nconstexpr bool operator>=(int128 lhs, int128 rhs) { return !(lhs < rhs); }\n\n#ifdef __cpp_impl_three_way_comparison\nconstexpr absl::strong_ordering operator<=>(int128 lhs, int128 rhs) {\n  if (int64_t lhs_high = Int128High64(lhs), rhs_high = Int128High64(rhs);\n      lhs_high < rhs_high) {\n    return absl::strong_ordering::less;\n  } else if (lhs_high > rhs_high) {\n    return absl::strong_ordering::greater;\n  } else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs);\n             lhs_low < rhs_low) {\n    return absl::strong_ordering::less;\n  } else if (lhs_low > rhs_low) {\n    return absl::strong_ordering::greater;\n  } else {\n    return absl::strong_ordering::equal;\n  }\n}\n#endif\n\n// Unary operators.\n\nconstexpr int128 operator-(int128 v) {\n  return MakeInt128(~Int128High64(v) + (Int128Low64(v) == 0),\n                    ~Int128Low64(v) + 1);\n}\n\nconstexpr bool operator!(int128 v) {\n  return !Int128Low64(v) && !Int128High64(v);\n}\n\nconstexpr int128 operator~(int128 val) {\n  return MakeInt128(~Int128High64(val), ~Int128Low64(val));\n}\n\n// Arithmetic operators.\n\nnamespace int128_internal {\nconstexpr int128 SignedAddResult(int128 result, int128 lhs) {\n  // check for carry\n  return (Int128Low64(result) < Int128Low64(lhs))\n             ? MakeInt128(Int128High64(result) + 1, Int128Low64(result))\n             : result;\n}\n}  // namespace int128_internal\nconstexpr int128 operator+(int128 lhs, int128 rhs) {\n  return int128_internal::SignedAddResult(\n      MakeInt128(Int128High64(lhs) + Int128High64(rhs),\n                 Int128Low64(lhs) + Int128Low64(rhs)),\n      lhs);\n}\n\nnamespace int128_internal {\nconstexpr int128 SignedSubstructResult(int128 result, int128 lhs, int128 rhs) {\n  // check for carry\n  return (Int128Low64(lhs) < Int128Low64(rhs))\n             ? MakeInt128(Int128High64(result) - 1, Int128Low64(result))\n             : result;\n}\n}  // namespace int128_internal\nconstexpr int128 operator-(int128 lhs, int128 rhs) {\n  return int128_internal::SignedSubstructResult(\n      MakeInt128(Int128High64(lhs) - Int128High64(rhs),\n                 Int128Low64(lhs) - Int128Low64(rhs)),\n      lhs, rhs);\n}\n\ninline int128 operator*(int128 lhs, int128 rhs) {\n  return MakeInt128(\n      int128_internal::BitCastToSigned(Uint128High64(uint128(lhs) * rhs)),\n      Uint128Low64(uint128(lhs) * rhs));\n}\n\ninline int128 int128::operator++(int) {\n  int128 tmp(*this);\n  *this += 1;\n  return tmp;\n}\n\ninline int128 int128::operator--(int) {\n  int128 tmp(*this);\n  *this -= 1;\n  return tmp;\n}\n\ninline int128& int128::operator++() {\n  *this += 1;\n  return *this;\n}\n\ninline int128& int128::operator--() {\n  *this -= 1;\n  return *this;\n}\n\nconstexpr int128 operator|(int128 lhs, int128 rhs) {\n  return MakeInt128(Int128High64(lhs) | Int128High64(rhs),\n                    Int128Low64(lhs) | Int128Low64(rhs));\n}\n\nconstexpr int128 operator&(int128 lhs, int128 rhs) {\n  return MakeInt128(Int128High64(lhs) & Int128High64(rhs),\n                    Int128Low64(lhs) & Int128Low64(rhs));\n}\n\nconstexpr int128 operator^(int128 lhs, int128 rhs) {\n  return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs),\n                    Int128Low64(lhs) ^ Int128Low64(rhs));\n}\n\nconstexpr int128 operator<<(int128 lhs, int amount) {\n  // int64_t shifts of >= 63 are undefined, so we need some special-casing.\n  assert(amount >= 0 && amount < 127);\n  if (amount <= 0) {\n    return lhs;\n  } else if (amount < 63) {\n    return MakeInt128(\n        (Int128High64(lhs) << amount) |\n            static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)),\n        Int128Low64(lhs) << amount);\n  } else if (amount == 63) {\n    return MakeInt128(((Int128High64(lhs) << 32) << 31) |\n                          static_cast<int64_t>(Int128Low64(lhs) >> 1),\n                      (Int128Low64(lhs) << 32) << 31);\n  } else if (amount == 127) {\n    return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << 63), 0);\n  } else if (amount > 127) {\n    return MakeInt128(0, 0);\n  } else {\n    // amount >= 64 && amount < 127\n    return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)),\n                      0);\n  }\n}\n\nconstexpr int128 operator>>(int128 lhs, int amount) {\n  // int64_t shifts of >= 63 are undefined, so we need some special-casing.\n  assert(amount >= 0 && amount < 127);\n  if (amount <= 0) {\n    return lhs;\n  } else if (amount < 63) {\n    return MakeInt128(\n        Int128High64(lhs) >> amount,\n        Int128Low64(lhs) >> amount | static_cast<uint64_t>(Int128High64(lhs))\n                                         << (64 - amount));\n  } else if (amount == 63) {\n    return MakeInt128((Int128High64(lhs) >> 32) >> 31,\n                      static_cast<uint64_t>(Int128High64(lhs) << 1) |\n                          (Int128Low64(lhs) >> 32) >> 31);\n\n  } else if (amount >= 127) {\n    return MakeInt128((Int128High64(lhs) >> 32) >> 31,\n                      static_cast<uint64_t>((Int128High64(lhs) >> 32) >> 31));\n  } else {\n    // amount >= 64 && amount < 127\n    return MakeInt128(\n        (Int128High64(lhs) >> 32) >> 31,\n        static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)));\n  }\n}\n"
  },
  {
    "path": "absl/numeric/int128_stream_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/numeric/int128.h\"\n\n#include <sstream>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\n\nstruct Uint128TestCase {\n  absl::uint128 value;\n  std::ios_base::fmtflags flags;\n  std::streamsize width;\n  const char* expected;\n};\n\nconstexpr char kFill = '_';\n\nstd::string StreamFormatToString(std::ios_base::fmtflags flags,\n                                 std::streamsize width) {\n  std::vector<const char*> flagstr;\n  switch (flags & std::ios::basefield) {\n    case std::ios::dec:\n      flagstr.push_back(\"std::ios::dec\");\n      break;\n    case std::ios::oct:\n      flagstr.push_back(\"std::ios::oct\");\n      break;\n    case std::ios::hex:\n      flagstr.push_back(\"std::ios::hex\");\n      break;\n    default:  // basefield not specified\n      break;\n  }\n  switch (flags & std::ios::adjustfield) {\n    case std::ios::left:\n      flagstr.push_back(\"std::ios::left\");\n      break;\n    case std::ios::internal:\n      flagstr.push_back(\"std::ios::internal\");\n      break;\n    case std::ios::right:\n      flagstr.push_back(\"std::ios::right\");\n      break;\n    default:  // adjustfield not specified\n      break;\n  }\n  if (flags & std::ios::uppercase) flagstr.push_back(\"std::ios::uppercase\");\n  if (flags & std::ios::showbase) flagstr.push_back(\"std::ios::showbase\");\n  if (flags & std::ios::showpos) flagstr.push_back(\"std::ios::showpos\");\n\n  std::ostringstream msg;\n  msg << \"\\n  StreamFormatToString(test_case.flags, test_case.width)\\n    \"\n         \"flags: \";\n  if (!flagstr.empty()) {\n    for (size_t i = 0; i < flagstr.size() - 1; ++i) msg << flagstr[i] << \" | \";\n    msg << flagstr.back();\n  } else {\n    msg << \"(default)\";\n  }\n  msg << \"\\n    width: \" << width << \"\\n    fill: '\" << kFill << \"'\";\n  return msg.str();\n}\n\nconstexpr std::ios::fmtflags kDec = std::ios::dec;\nconstexpr std::ios::fmtflags kOct = std::ios::oct;\nconstexpr std::ios::fmtflags kHex = std::ios::hex;\nconstexpr std::ios::fmtflags kLeft = std::ios::left;\nconstexpr std::ios::fmtflags kInt = std::ios::internal;\nconstexpr std::ios::fmtflags kRight = std::ios::right;\nconstexpr std::ios::fmtflags kUpper = std::ios::uppercase;\nconstexpr std::ios::fmtflags kBase = std::ios::showbase;\nconstexpr std::ios::fmtflags kPos = std::ios::showpos;\n\nvoid CheckUint128Case(const Uint128TestCase& test_case) {\n  if (test_case.flags == kDec && test_case.width == 0) {\n    EXPECT_EQ(absl::StrCat(test_case.value), test_case.expected);\n  }\n  std::ostringstream os;\n  os.flags(test_case.flags);\n  os.width(test_case.width);\n  os.fill(kFill);\n  os << test_case.value;\n  SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width));\n  EXPECT_EQ(os.str(), test_case.expected);\n}\n\nTEST(Uint128, OStreamValueTest) {\n  CheckUint128Case({1, kDec, /*width = */ 0, \"1\"});\n  CheckUint128Case({1, kOct, /*width = */ 0, \"1\"});\n  CheckUint128Case({1, kHex, /*width = */ 0, \"1\"});\n  CheckUint128Case({9, kDec, /*width = */ 0, \"9\"});\n  CheckUint128Case({9, kOct, /*width = */ 0, \"11\"});\n  CheckUint128Case({9, kHex, /*width = */ 0, \"9\"});\n  CheckUint128Case({12345, kDec, /*width = */ 0, \"12345\"});\n  CheckUint128Case({12345, kOct, /*width = */ 0, \"30071\"});\n  CheckUint128Case({12345, kHex, /*width = */ 0, \"3039\"});\n  CheckUint128Case(\n      {0x8000000000000000, kDec, /*width = */ 0, \"9223372036854775808\"});\n  CheckUint128Case(\n      {0x8000000000000000, kOct, /*width = */ 0, \"1000000000000000000000\"});\n  CheckUint128Case(\n      {0x8000000000000000, kHex, /*width = */ 0, \"8000000000000000\"});\n  CheckUint128Case({std::numeric_limits<uint64_t>::max(), kDec,\n                    /*width = */ 0, \"18446744073709551615\"});\n  CheckUint128Case({std::numeric_limits<uint64_t>::max(), kOct,\n                    /*width = */ 0, \"1777777777777777777777\"});\n  CheckUint128Case({std::numeric_limits<uint64_t>::max(), kHex,\n                    /*width = */ 0, \"ffffffffffffffff\"});\n  CheckUint128Case(\n      {absl::MakeUint128(1, 0), kDec, /*width = */ 0, \"18446744073709551616\"});\n  CheckUint128Case({absl::MakeUint128(1, 0), kOct, /*width = */ 0,\n                    \"2000000000000000000000\"});\n  CheckUint128Case(\n      {absl::MakeUint128(1, 0), kHex, /*width = */ 0, \"10000000000000000\"});\n  CheckUint128Case({absl::MakeUint128(0x8000000000000000, 0), kDec,\n                    /*width = */ 0, \"170141183460469231731687303715884105728\"});\n  CheckUint128Case({absl::MakeUint128(0x8000000000000000, 0), kOct,\n                    /*width = */ 0,\n                    \"2000000000000000000000000000000000000000000\"});\n  CheckUint128Case({absl::MakeUint128(0x8000000000000000, 0), kHex,\n                    /*width = */ 0, \"80000000000000000000000000000000\"});\n  CheckUint128Case({absl::Uint128Max(), kDec, /*width = */ 0,\n                    \"340282366920938463463374607431768211455\"});\n  CheckUint128Case({absl::Uint128Max(), kOct, /*width = */ 0,\n                    \"3777777777777777777777777777777777777777777\"});\n  CheckUint128Case({absl::Uint128Max(), kHex, /*width = */ 0,\n                    \"ffffffffffffffffffffffffffffffff\"});\n}\n\nstd::vector<Uint128TestCase> GetUint128FormatCases();\n\nTEST(Uint128, OStreamFormatTest) {\n  for (const Uint128TestCase& test_case : GetUint128FormatCases()) {\n    CheckUint128Case(test_case);\n  }\n}\n\nstruct Int128TestCase {\n  absl::int128 value;\n  std::ios_base::fmtflags flags;\n  std::streamsize width;\n  const char* expected;\n};\n\nvoid CheckInt128Case(const Int128TestCase& test_case) {\n  if (test_case.flags == kDec && test_case.width == 0) {\n    EXPECT_EQ(absl::StrCat(test_case.value), test_case.expected);\n  }\n  std::ostringstream os;\n  os.flags(test_case.flags);\n  os.width(test_case.width);\n  os.fill(kFill);\n  os << test_case.value;\n  SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width));\n  EXPECT_EQ(os.str(), test_case.expected);\n}\n\nTEST(Int128, OStreamValueTest) {\n  CheckInt128Case({1, kDec, /*width = */ 0, \"1\"});\n  CheckInt128Case({1, kOct, /*width = */ 0, \"1\"});\n  CheckInt128Case({1, kHex, /*width = */ 0, \"1\"});\n  CheckInt128Case({9, kDec, /*width = */ 0, \"9\"});\n  CheckInt128Case({9, kOct, /*width = */ 0, \"11\"});\n  CheckInt128Case({9, kHex, /*width = */ 0, \"9\"});\n  CheckInt128Case({12345, kDec, /*width = */ 0, \"12345\"});\n  CheckInt128Case({12345, kOct, /*width = */ 0, \"30071\"});\n  CheckInt128Case({12345, kHex, /*width = */ 0, \"3039\"});\n  CheckInt128Case(\n      {0x8000000000000000, kDec, /*width = */ 0, \"9223372036854775808\"});\n  CheckInt128Case(\n      {0x8000000000000000, kOct, /*width = */ 0, \"1000000000000000000000\"});\n  CheckInt128Case(\n      {0x8000000000000000, kHex, /*width = */ 0, \"8000000000000000\"});\n  CheckInt128Case({std::numeric_limits<uint64_t>::max(), kDec,\n                   /*width = */ 0, \"18446744073709551615\"});\n  CheckInt128Case({std::numeric_limits<uint64_t>::max(), kOct,\n                   /*width = */ 0, \"1777777777777777777777\"});\n  CheckInt128Case({std::numeric_limits<uint64_t>::max(), kHex,\n                   /*width = */ 0, \"ffffffffffffffff\"});\n  CheckInt128Case(\n      {absl::MakeInt128(1, 0), kDec, /*width = */ 0, \"18446744073709551616\"});\n  CheckInt128Case(\n      {absl::MakeInt128(1, 0), kOct, /*width = */ 0, \"2000000000000000000000\"});\n  CheckInt128Case(\n      {absl::MakeInt128(1, 0), kHex, /*width = */ 0, \"10000000000000000\"});\n  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),\n                                    std::numeric_limits<uint64_t>::max()),\n                   kDec, /*width = */ 0,\n                   \"170141183460469231731687303715884105727\"});\n  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),\n                                    std::numeric_limits<uint64_t>::max()),\n                   kOct, /*width = */ 0,\n                   \"1777777777777777777777777777777777777777777\"});\n  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),\n                                    std::numeric_limits<uint64_t>::max()),\n                   kHex, /*width = */ 0, \"7fffffffffffffffffffffffffffffff\"});\n  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),\n                   kDec, /*width = */ 0,\n                   \"-170141183460469231731687303715884105728\"});\n  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),\n                   kOct, /*width = */ 0,\n                   \"2000000000000000000000000000000000000000000\"});\n  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),\n                   kHex, /*width = */ 0, \"80000000000000000000000000000000\"});\n  CheckInt128Case({-1, kDec, /*width = */ 0, \"-1\"});\n  CheckInt128Case({-1, kOct, /*width = */ 0,\n                   \"3777777777777777777777777777777777777777777\"});\n  CheckInt128Case(\n      {-1, kHex, /*width = */ 0, \"ffffffffffffffffffffffffffffffff\"});\n  CheckInt128Case({-12345, kDec, /*width = */ 0, \"-12345\"});\n  CheckInt128Case({-12345, kOct, /*width = */ 0,\n                   \"3777777777777777777777777777777777777747707\"});\n  CheckInt128Case(\n      {-12345, kHex, /*width = */ 0, \"ffffffffffffffffffffffffffffcfc7\"});\n}\n\nstd::vector<Int128TestCase> GetInt128FormatCases();\nTEST(Int128, OStreamFormatTest) {\n  for (const Int128TestCase& test_case : GetInt128FormatCases()) {\n    CheckInt128Case(test_case);\n  }\n}\n\nstd::vector<Int128TestCase> GetInt128FormatCases() {\n  return {\n      {0, std::ios_base::fmtflags(), /*width = */ 0, \"0\"},\n      {0, std::ios_base::fmtflags(), /*width = */ 6, \"_____0\"},\n      {0, kPos, /*width = */ 0, \"+0\"},\n      {0, kPos, /*width = */ 6, \"____+0\"},\n      {0, kBase, /*width = */ 0, \"0\"},\n      {0, kBase, /*width = */ 6, \"_____0\"},\n      {0, kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kUpper, /*width = */ 0, \"0\"},\n      {0, kUpper, /*width = */ 6, \"_____0\"},\n      {0, kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kUpper | kPos, /*width = */ 6, \"____+0\"},\n      {0, kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kUpper | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kLeft, /*width = */ 0, \"0\"},\n      {0, kLeft, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kPos, /*width = */ 0, \"+0\"},\n      {0, kLeft | kPos, /*width = */ 6, \"+0____\"},\n      {0, kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kLeft | kBase | kPos, /*width = */ 6, \"+0____\"},\n      {0, kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kLeft | kUpper | kPos, /*width = */ 6, \"+0____\"},\n      {0, kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, \"+0____\"},\n      {0, kInt, /*width = */ 0, \"0\"},\n      {0, kInt, /*width = */ 6, \"_____0\"},\n      {0, kInt | kPos, /*width = */ 0, \"+0\"},\n      {0, kInt | kPos, /*width = */ 6, \"+____0\"},\n      {0, kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kInt | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kInt | kBase | kPos, /*width = */ 6, \"+____0\"},\n      {0, kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kInt | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kInt | kUpper | kPos, /*width = */ 6, \"+____0\"},\n      {0, kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kInt | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kInt | kUpper | kBase | kPos, /*width = */ 6, \"+____0\"},\n      {0, kRight, /*width = */ 0, \"0\"},\n      {0, kRight, /*width = */ 6, \"_____0\"},\n      {0, kRight | kPos, /*width = */ 0, \"+0\"},\n      {0, kRight | kPos, /*width = */ 6, \"____+0\"},\n      {0, kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kRight | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kRight | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kRight | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kRight | kUpper | kPos, /*width = */ 6, \"____+0\"},\n      {0, kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kRight | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kRight | kUpper | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec, /*width = */ 0, \"0\"},\n      {0, kDec, /*width = */ 6, \"_____0\"},\n      {0, kDec | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kDec | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kUpper | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kUpper | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kLeft, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kLeft | kPos, /*width = */ 6, \"+0____\"},\n      {0, kDec | kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kLeft | kBase | kPos, /*width = */ 6, \"+0____\"},\n      {0, kDec | kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, \"+0____\"},\n      {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"+0____\"},\n      {0, kDec | kInt, /*width = */ 0, \"0\"},\n      {0, kDec | kInt, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kInt | kPos, /*width = */ 6, \"+____0\"},\n      {0, kDec | kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kInt | kBase | kPos, /*width = */ 6, \"+____0\"},\n      {0, kDec | kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kInt | kUpper | kPos, /*width = */ 6, \"+____0\"},\n      {0, kDec | kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, \"+____0\"},\n      {0, kDec | kRight, /*width = */ 0, \"0\"},\n      {0, kDec | kRight, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kRight | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kRight | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kUpper | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kRight | kUpper | kPos, /*width = */ 6, \"____+0\"},\n      {0, kDec | kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, \"+0\"},\n      {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, \"____+0\"},\n      {0, kOct, /*width = */ 0, \"0\"},\n      {0, kOct, /*width = */ 6, \"_____0\"},\n      {0, kOct | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kLeft, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kInt, /*width = */ 0, \"0\"},\n      {0, kOct | kInt, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight, /*width = */ 0, \"0\"},\n      {0, kOct | kRight, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex, /*width = */ 0, \"0\"},\n      {0, kHex, /*width = */ 6, \"_____0\"},\n      {0, kHex | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kLeft, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kInt, /*width = */ 0, \"0\"},\n      {0, kHex | kInt, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight, /*width = */ 0, \"0\"},\n      {0, kHex | kRight, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {42, std::ios_base::fmtflags(), /*width = */ 0, \"42\"},\n      {42, std::ios_base::fmtflags(), /*width = */ 6, \"____42\"},\n      {42, kPos, /*width = */ 0, \"+42\"},\n      {42, kPos, /*width = */ 6, \"___+42\"},\n      {42, kBase, /*width = */ 0, \"42\"},\n      {42, kBase, /*width = */ 6, \"____42\"},\n      {42, kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kUpper, /*width = */ 0, \"42\"},\n      {42, kUpper, /*width = */ 6, \"____42\"},\n      {42, kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kUpper | kPos, /*width = */ 6, \"___+42\"},\n      {42, kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kUpper | kBase, /*width = */ 6, \"____42\"},\n      {42, kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kUpper | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kLeft, /*width = */ 0, \"42\"},\n      {42, kLeft, /*width = */ 6, \"42____\"},\n      {42, kLeft | kPos, /*width = */ 0, \"+42\"},\n      {42, kLeft | kPos, /*width = */ 6, \"+42___\"},\n      {42, kLeft | kBase, /*width = */ 0, \"42\"},\n      {42, kLeft | kBase, /*width = */ 6, \"42____\"},\n      {42, kLeft | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kLeft | kBase | kPos, /*width = */ 6, \"+42___\"},\n      {42, kLeft | kUpper, /*width = */ 0, \"42\"},\n      {42, kLeft | kUpper, /*width = */ 6, \"42____\"},\n      {42, kLeft | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kLeft | kUpper | kPos, /*width = */ 6, \"+42___\"},\n      {42, kLeft | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kLeft | kUpper | kBase, /*width = */ 6, \"42____\"},\n      {42, kLeft | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kLeft | kUpper | kBase | kPos, /*width = */ 6, \"+42___\"},\n      {42, kInt, /*width = */ 0, \"42\"},\n      {42, kInt, /*width = */ 6, \"____42\"},\n      {42, kInt | kPos, /*width = */ 0, \"+42\"},\n      {42, kInt | kPos, /*width = */ 6, \"+___42\"},\n      {42, kInt | kBase, /*width = */ 0, \"42\"},\n      {42, kInt | kBase, /*width = */ 6, \"____42\"},\n      {42, kInt | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kInt | kBase | kPos, /*width = */ 6, \"+___42\"},\n      {42, kInt | kUpper, /*width = */ 0, \"42\"},\n      {42, kInt | kUpper, /*width = */ 6, \"____42\"},\n      {42, kInt | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kInt | kUpper | kPos, /*width = */ 6, \"+___42\"},\n      {42, kInt | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kInt | kUpper | kBase, /*width = */ 6, \"____42\"},\n      {42, kInt | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kInt | kUpper | kBase | kPos, /*width = */ 6, \"+___42\"},\n      {42, kRight, /*width = */ 0, \"42\"},\n      {42, kRight, /*width = */ 6, \"____42\"},\n      {42, kRight | kPos, /*width = */ 0, \"+42\"},\n      {42, kRight | kPos, /*width = */ 6, \"___+42\"},\n      {42, kRight | kBase, /*width = */ 0, \"42\"},\n      {42, kRight | kBase, /*width = */ 6, \"____42\"},\n      {42, kRight | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kRight | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kRight | kUpper, /*width = */ 0, \"42\"},\n      {42, kRight | kUpper, /*width = */ 6, \"____42\"},\n      {42, kRight | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kRight | kUpper | kPos, /*width = */ 6, \"___+42\"},\n      {42, kRight | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kRight | kUpper | kBase, /*width = */ 6, \"____42\"},\n      {42, kRight | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kRight | kUpper | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec, /*width = */ 0, \"42\"},\n      {42, kDec, /*width = */ 6, \"____42\"},\n      {42, kDec | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kBase, /*width = */ 6, \"____42\"},\n      {42, kDec | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kUpper, /*width = */ 0, \"42\"},\n      {42, kDec | kUpper, /*width = */ 6, \"____42\"},\n      {42, kDec | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kUpper | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kUpper | kBase, /*width = */ 6, \"____42\"},\n      {42, kDec | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kUpper | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kLeft, /*width = */ 0, \"42\"},\n      {42, kDec | kLeft, /*width = */ 6, \"42____\"},\n      {42, kDec | kLeft | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kLeft | kPos, /*width = */ 6, \"+42___\"},\n      {42, kDec | kLeft | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kLeft | kBase, /*width = */ 6, \"42____\"},\n      {42, kDec | kLeft | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kLeft | kBase | kPos, /*width = */ 6, \"+42___\"},\n      {42, kDec | kLeft | kUpper, /*width = */ 0, \"42\"},\n      {42, kDec | kLeft | kUpper, /*width = */ 6, \"42____\"},\n      {42, kDec | kLeft | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kLeft | kUpper | kPos, /*width = */ 6, \"+42___\"},\n      {42, kDec | kLeft | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kLeft | kUpper | kBase, /*width = */ 6, \"42____\"},\n      {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"+42___\"},\n      {42, kDec | kInt, /*width = */ 0, \"42\"},\n      {42, kDec | kInt, /*width = */ 6, \"____42\"},\n      {42, kDec | kInt | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kInt | kPos, /*width = */ 6, \"+___42\"},\n      {42, kDec | kInt | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kInt | kBase, /*width = */ 6, \"____42\"},\n      {42, kDec | kInt | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kInt | kBase | kPos, /*width = */ 6, \"+___42\"},\n      {42, kDec | kInt | kUpper, /*width = */ 0, \"42\"},\n      {42, kDec | kInt | kUpper, /*width = */ 6, \"____42\"},\n      {42, kDec | kInt | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kInt | kUpper | kPos, /*width = */ 6, \"+___42\"},\n      {42, kDec | kInt | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kInt | kUpper | kBase, /*width = */ 6, \"____42\"},\n      {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, \"+___42\"},\n      {42, kDec | kRight, /*width = */ 0, \"42\"},\n      {42, kDec | kRight, /*width = */ 6, \"____42\"},\n      {42, kDec | kRight | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kRight | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kRight | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kRight | kBase, /*width = */ 6, \"____42\"},\n      {42, kDec | kRight | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kRight | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kRight | kUpper, /*width = */ 0, \"42\"},\n      {42, kDec | kRight | kUpper, /*width = */ 6, \"____42\"},\n      {42, kDec | kRight | kUpper | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kRight | kUpper | kPos, /*width = */ 6, \"___+42\"},\n      {42, kDec | kRight | kUpper | kBase, /*width = */ 0, \"42\"},\n      {42, kDec | kRight | kUpper | kBase, /*width = */ 6, \"____42\"},\n      {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, \"+42\"},\n      {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, \"___+42\"},\n      {42, kOct, /*width = */ 0, \"52\"},\n      {42, kOct, /*width = */ 6, \"____52\"},\n      {42, kOct | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kPos, /*width = */ 6, \"____52\"},\n      {42, kOct | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kBase, /*width = */ 6, \"___052\"},\n      {42, kOct | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kBase | kPos, /*width = */ 6, \"___052\"},\n      {42, kOct | kUpper, /*width = */ 0, \"52\"},\n      {42, kOct | kUpper, /*width = */ 6, \"____52\"},\n      {42, kOct | kUpper | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kUpper | kPos, /*width = */ 6, \"____52\"},\n      {42, kOct | kUpper | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kUpper | kBase, /*width = */ 6, \"___052\"},\n      {42, kOct | kUpper | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kUpper | kBase | kPos, /*width = */ 6, \"___052\"},\n      {42, kOct | kLeft, /*width = */ 0, \"52\"},\n      {42, kOct | kLeft, /*width = */ 6, \"52____\"},\n      {42, kOct | kLeft | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kLeft | kPos, /*width = */ 6, \"52____\"},\n      {42, kOct | kLeft | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kLeft | kBase, /*width = */ 6, \"052___\"},\n      {42, kOct | kLeft | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kLeft | kBase | kPos, /*width = */ 6, \"052___\"},\n      {42, kOct | kLeft | kUpper, /*width = */ 0, \"52\"},\n      {42, kOct | kLeft | kUpper, /*width = */ 6, \"52____\"},\n      {42, kOct | kLeft | kUpper | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kLeft | kUpper | kPos, /*width = */ 6, \"52____\"},\n      {42, kOct | kLeft | kUpper | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kLeft | kUpper | kBase, /*width = */ 6, \"052___\"},\n      {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"052___\"},\n      {42, kOct | kInt, /*width = */ 0, \"52\"},\n      {42, kOct | kInt, /*width = */ 6, \"____52\"},\n      {42, kOct | kInt | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kInt | kPos, /*width = */ 6, \"____52\"},\n      {42, kOct | kInt | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kInt | kBase, /*width = */ 6, \"___052\"},\n      {42, kOct | kInt | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kInt | kBase | kPos, /*width = */ 6, \"___052\"},\n      {42, kOct | kInt | kUpper, /*width = */ 0, \"52\"},\n      {42, kOct | kInt | kUpper, /*width = */ 6, \"____52\"},\n      {42, kOct | kInt | kUpper | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kInt | kUpper | kPos, /*width = */ 6, \"____52\"},\n      {42, kOct | kInt | kUpper | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kInt | kUpper | kBase, /*width = */ 6, \"___052\"},\n      {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, \"___052\"},\n      {42, kOct | kRight, /*width = */ 0, \"52\"},\n      {42, kOct | kRight, /*width = */ 6, \"____52\"},\n      {42, kOct | kRight | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kRight | kPos, /*width = */ 6, \"____52\"},\n      {42, kOct | kRight | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kRight | kBase, /*width = */ 6, \"___052\"},\n      {42, kOct | kRight | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kRight | kBase | kPos, /*width = */ 6, \"___052\"},\n      {42, kOct | kRight | kUpper, /*width = */ 0, \"52\"},\n      {42, kOct | kRight | kUpper, /*width = */ 6, \"____52\"},\n      {42, kOct | kRight | kUpper | kPos, /*width = */ 0, \"52\"},\n      {42, kOct | kRight | kUpper | kPos, /*width = */ 6, \"____52\"},\n      {42, kOct | kRight | kUpper | kBase, /*width = */ 0, \"052\"},\n      {42, kOct | kRight | kUpper | kBase, /*width = */ 6, \"___052\"},\n      {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, \"052\"},\n      {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, \"___052\"},\n      {42, kHex, /*width = */ 0, \"2a\"},\n      {42, kHex, /*width = */ 6, \"____2a\"},\n      {42, kHex | kPos, /*width = */ 0, \"2a\"},\n      {42, kHex | kPos, /*width = */ 6, \"____2a\"},\n      {42, kHex | kBase, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kBase, /*width = */ 6, \"__0x2a\"},\n      {42, kHex | kBase | kPos, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kBase | kPos, /*width = */ 6, \"__0x2a\"},\n      {42, kHex | kUpper, /*width = */ 0, \"2A\"},\n      {42, kHex | kUpper, /*width = */ 6, \"____2A\"},\n      {42, kHex | kUpper | kPos, /*width = */ 0, \"2A\"},\n      {42, kHex | kUpper | kPos, /*width = */ 6, \"____2A\"},\n      {42, kHex | kUpper | kBase, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kUpper | kBase, /*width = */ 6, \"__0X2A\"},\n      {42, kHex | kUpper | kBase | kPos, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kUpper | kBase | kPos, /*width = */ 6, \"__0X2A\"},\n      {42, kHex | kLeft, /*width = */ 0, \"2a\"},\n      {42, kHex | kLeft, /*width = */ 6, \"2a____\"},\n      {42, kHex | kLeft | kPos, /*width = */ 0, \"2a\"},\n      {42, kHex | kLeft | kPos, /*width = */ 6, \"2a____\"},\n      {42, kHex | kLeft | kBase, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kLeft | kBase, /*width = */ 6, \"0x2a__\"},\n      {42, kHex | kLeft | kBase | kPos, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kLeft | kBase | kPos, /*width = */ 6, \"0x2a__\"},\n      {42, kHex | kLeft | kUpper, /*width = */ 0, \"2A\"},\n      {42, kHex | kLeft | kUpper, /*width = */ 6, \"2A____\"},\n      {42, kHex | kLeft | kUpper | kPos, /*width = */ 0, \"2A\"},\n      {42, kHex | kLeft | kUpper | kPos, /*width = */ 6, \"2A____\"},\n      {42, kHex | kLeft | kUpper | kBase, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kLeft | kUpper | kBase, /*width = */ 6, \"0X2A__\"},\n      {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0X2A__\"},\n      {42, kHex | kInt, /*width = */ 0, \"2a\"},\n      {42, kHex | kInt, /*width = */ 6, \"____2a\"},\n      {42, kHex | kInt | kPos, /*width = */ 0, \"2a\"},\n      {42, kHex | kInt | kPos, /*width = */ 6, \"____2a\"},\n      {42, kHex | kInt | kBase, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kInt | kBase, /*width = */ 6, \"0x__2a\"},\n      {42, kHex | kInt | kBase | kPos, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kInt | kBase | kPos, /*width = */ 6, \"0x__2a\"},\n      {42, kHex | kInt | kUpper, /*width = */ 0, \"2A\"},\n      {42, kHex | kInt | kUpper, /*width = */ 6, \"____2A\"},\n      {42, kHex | kInt | kUpper | kPos, /*width = */ 0, \"2A\"},\n      {42, kHex | kInt | kUpper | kPos, /*width = */ 6, \"____2A\"},\n      {42, kHex | kInt | kUpper | kBase, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kInt | kUpper | kBase, /*width = */ 6, \"0X__2A\"},\n      {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, \"0X__2A\"},\n      {42, kHex | kRight, /*width = */ 0, \"2a\"},\n      {42, kHex | kRight, /*width = */ 6, \"____2a\"},\n      {42, kHex | kRight | kPos, /*width = */ 0, \"2a\"},\n      {42, kHex | kRight | kPos, /*width = */ 6, \"____2a\"},\n      {42, kHex | kRight | kBase, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kRight | kBase, /*width = */ 6, \"__0x2a\"},\n      {42, kHex | kRight | kBase | kPos, /*width = */ 0, \"0x2a\"},\n      {42, kHex | kRight | kBase | kPos, /*width = */ 6, \"__0x2a\"},\n      {42, kHex | kRight | kUpper, /*width = */ 0, \"2A\"},\n      {42, kHex | kRight | kUpper, /*width = */ 6, \"____2A\"},\n      {42, kHex | kRight | kUpper | kPos, /*width = */ 0, \"2A\"},\n      {42, kHex | kRight | kUpper | kPos, /*width = */ 6, \"____2A\"},\n      {42, kHex | kRight | kUpper | kBase, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kRight | kUpper | kBase, /*width = */ 6, \"__0X2A\"},\n      {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0X2A\"},\n      {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, \"__0X2A\"},\n      {-321, std::ios_base::fmtflags(), /*width = */ 0, \"-321\"},\n      {-321, std::ios_base::fmtflags(), /*width = */ 6, \"__-321\"},\n      {-321, kPos, /*width = */ 0, \"-321\"},\n      {-321, kPos, /*width = */ 6, \"__-321\"},\n      {-321, kBase, /*width = */ 0, \"-321\"},\n      {-321, kBase, /*width = */ 6, \"__-321\"},\n      {-321, kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kUpper, /*width = */ 0, \"-321\"},\n      {-321, kUpper, /*width = */ 6, \"__-321\"},\n      {-321, kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kUpper | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kUpper | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kUpper | kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kLeft, /*width = */ 0, \"-321\"},\n      {-321, kLeft, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kPos, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kBase, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kBase, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kBase | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kUpper, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kUpper | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kUpper | kBase, /*width = */ 6, \"-321__\"},\n      {-321, kLeft | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kLeft | kUpper | kBase | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kInt, /*width = */ 0, \"-321\"},\n      {-321, kInt, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kPos, /*width = */ 0, \"-321\"},\n      {-321, kInt | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kBase, /*width = */ 0, \"-321\"},\n      {-321, kInt | kBase, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kInt | kBase | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kInt | kUpper, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kInt | kUpper | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kInt | kUpper | kBase, /*width = */ 6, \"-__321\"},\n      {-321, kInt | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kInt | kUpper | kBase | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kRight, /*width = */ 0, \"-321\"},\n      {-321, kRight, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kPos, /*width = */ 0, \"-321\"},\n      {-321, kRight | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kBase, /*width = */ 0, \"-321\"},\n      {-321, kRight | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kRight | kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kRight | kUpper, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kRight | kUpper | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kRight | kUpper | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kRight | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kRight | kUpper | kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec, /*width = */ 0, \"-321\"},\n      {-321, kDec, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kDec | kUpper, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kUpper | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kUpper | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kUpper | kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kLeft, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kBase, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kBase | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kUpper, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kUpper | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kUpper | kBase, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"-321__\"},\n      {-321, kDec | kInt, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kBase, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kBase | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kUpper, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kUpper | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kUpper | kBase, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, \"-__321\"},\n      {-321, kDec | kRight, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kBase | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kUpper, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kUpper, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kUpper | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kUpper | kPos, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kUpper | kBase, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kUpper | kBase, /*width = */ 6, \"__-321\"},\n      {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, \"-321\"},\n      {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, \"__-321\"}};\n}\n\nstd::vector<Uint128TestCase> GetUint128FormatCases() {\n  return {\n      {0, std::ios_base::fmtflags(), /*width = */ 0, \"0\"},\n      {0, std::ios_base::fmtflags(), /*width = */ 6, \"_____0\"},\n      {0, kPos, /*width = */ 0, \"0\"},\n      {0, kPos, /*width = */ 6, \"_____0\"},\n      {0, kBase, /*width = */ 0, \"0\"},\n      {0, kBase, /*width = */ 6, \"_____0\"},\n      {0, kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kUpper, /*width = */ 0, \"0\"},\n      {0, kUpper, /*width = */ 6, \"_____0\"},\n      {0, kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kLeft, /*width = */ 0, \"0\"},\n      {0, kLeft, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kPos, /*width = */ 0, \"0\"},\n      {0, kLeft | kPos, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kLeft | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kLeft | kUpper | kPos, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kInt, /*width = */ 0, \"0\"},\n      {0, kInt, /*width = */ 6, \"_____0\"},\n      {0, kInt | kPos, /*width = */ 0, \"0\"},\n      {0, kInt | kPos, /*width = */ 6, \"_____0\"},\n      {0, kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kInt | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kInt | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kInt | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kInt | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kInt | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kInt | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kRight, /*width = */ 0, \"0\"},\n      {0, kRight, /*width = */ 6, \"_____0\"},\n      {0, kRight | kPos, /*width = */ 0, \"0\"},\n      {0, kRight | kPos, /*width = */ 6, \"_____0\"},\n      {0, kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kRight | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kRight | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kRight | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kRight | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kRight | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kRight | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec, /*width = */ 0, \"0\"},\n      {0, kDec, /*width = */ 6, \"_____0\"},\n      {0, kDec | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kDec | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kLeft, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kPos, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kDec | kInt, /*width = */ 0, \"0\"},\n      {0, kDec | kInt, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight, /*width = */ 0, \"0\"},\n      {0, kDec | kRight, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct, /*width = */ 0, \"0\"},\n      {0, kOct, /*width = */ 6, \"_____0\"},\n      {0, kOct | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kLeft, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kOct | kInt, /*width = */ 0, \"0\"},\n      {0, kOct | kInt, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight, /*width = */ 0, \"0\"},\n      {0, kOct | kRight, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex, /*width = */ 0, \"0\"},\n      {0, kHex, /*width = */ 6, \"_____0\"},\n      {0, kHex | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kLeft, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kBase, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, \"0_____\"},\n      {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0_____\"},\n      {0, kHex | kInt, /*width = */ 0, \"0\"},\n      {0, kHex | kInt, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight, /*width = */ 0, \"0\"},\n      {0, kHex | kRight, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper | kPos, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper | kBase, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper | kBase, /*width = */ 6, \"_____0\"},\n      {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0\"},\n      {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, \"_____0\"},\n      {37, std::ios_base::fmtflags(), /*width = */ 0, \"37\"},\n      {37, std::ios_base::fmtflags(), /*width = */ 6, \"____37\"},\n      {37, kPos, /*width = */ 0, \"37\"},\n      {37, kPos, /*width = */ 6, \"____37\"},\n      {37, kBase, /*width = */ 0, \"37\"},\n      {37, kBase, /*width = */ 6, \"____37\"},\n      {37, kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kUpper, /*width = */ 0, \"37\"},\n      {37, kUpper, /*width = */ 6, \"____37\"},\n      {37, kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kUpper | kPos, /*width = */ 6, \"____37\"},\n      {37, kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kUpper | kBase, /*width = */ 6, \"____37\"},\n      {37, kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kUpper | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kLeft, /*width = */ 0, \"37\"},\n      {37, kLeft, /*width = */ 6, \"37____\"},\n      {37, kLeft | kPos, /*width = */ 0, \"37\"},\n      {37, kLeft | kPos, /*width = */ 6, \"37____\"},\n      {37, kLeft | kBase, /*width = */ 0, \"37\"},\n      {37, kLeft | kBase, /*width = */ 6, \"37____\"},\n      {37, kLeft | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kLeft | kBase | kPos, /*width = */ 6, \"37____\"},\n      {37, kLeft | kUpper, /*width = */ 0, \"37\"},\n      {37, kLeft | kUpper, /*width = */ 6, \"37____\"},\n      {37, kLeft | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kLeft | kUpper | kPos, /*width = */ 6, \"37____\"},\n      {37, kLeft | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kLeft | kUpper | kBase, /*width = */ 6, \"37____\"},\n      {37, kLeft | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kLeft | kUpper | kBase | kPos, /*width = */ 6, \"37____\"},\n      {37, kInt, /*width = */ 0, \"37\"},\n      {37, kInt, /*width = */ 6, \"____37\"},\n      {37, kInt | kPos, /*width = */ 0, \"37\"},\n      {37, kInt | kPos, /*width = */ 6, \"____37\"},\n      {37, kInt | kBase, /*width = */ 0, \"37\"},\n      {37, kInt | kBase, /*width = */ 6, \"____37\"},\n      {37, kInt | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kInt | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kInt | kUpper, /*width = */ 0, \"37\"},\n      {37, kInt | kUpper, /*width = */ 6, \"____37\"},\n      {37, kInt | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kInt | kUpper | kPos, /*width = */ 6, \"____37\"},\n      {37, kInt | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kInt | kUpper | kBase, /*width = */ 6, \"____37\"},\n      {37, kInt | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kInt | kUpper | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kRight, /*width = */ 0, \"37\"},\n      {37, kRight, /*width = */ 6, \"____37\"},\n      {37, kRight | kPos, /*width = */ 0, \"37\"},\n      {37, kRight | kPos, /*width = */ 6, \"____37\"},\n      {37, kRight | kBase, /*width = */ 0, \"37\"},\n      {37, kRight | kBase, /*width = */ 6, \"____37\"},\n      {37, kRight | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kRight | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kRight | kUpper, /*width = */ 0, \"37\"},\n      {37, kRight | kUpper, /*width = */ 6, \"____37\"},\n      {37, kRight | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kRight | kUpper | kPos, /*width = */ 6, \"____37\"},\n      {37, kRight | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kRight | kUpper | kBase, /*width = */ 6, \"____37\"},\n      {37, kRight | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kRight | kUpper | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec, /*width = */ 0, \"37\"},\n      {37, kDec, /*width = */ 6, \"____37\"},\n      {37, kDec | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kBase, /*width = */ 6, \"____37\"},\n      {37, kDec | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kUpper, /*width = */ 0, \"37\"},\n      {37, kDec | kUpper, /*width = */ 6, \"____37\"},\n      {37, kDec | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kUpper | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kUpper | kBase, /*width = */ 6, \"____37\"},\n      {37, kDec | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kUpper | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kLeft, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kPos, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kBase, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kBase | kPos, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kUpper, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kUpper, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kUpper | kPos, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kUpper | kBase, /*width = */ 6, \"37____\"},\n      {37, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"37____\"},\n      {37, kDec | kInt, /*width = */ 0, \"37\"},\n      {37, kDec | kInt, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kBase, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kUpper, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kUpper, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kUpper | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kUpper | kBase, /*width = */ 6, \"____37\"},\n      {37, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight, /*width = */ 0, \"37\"},\n      {37, kDec | kRight, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kBase, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kUpper, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kUpper, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kUpper | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kUpper | kPos, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kUpper | kBase, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kUpper | kBase, /*width = */ 6, \"____37\"},\n      {37, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, \"37\"},\n      {37, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, \"____37\"},\n      {37, kOct, /*width = */ 0, \"45\"},\n      {37, kOct, /*width = */ 6, \"____45\"},\n      {37, kOct | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kPos, /*width = */ 6, \"____45\"},\n      {37, kOct | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kBase, /*width = */ 6, \"___045\"},\n      {37, kOct | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kBase | kPos, /*width = */ 6, \"___045\"},\n      {37, kOct | kUpper, /*width = */ 0, \"45\"},\n      {37, kOct | kUpper, /*width = */ 6, \"____45\"},\n      {37, kOct | kUpper | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kUpper | kPos, /*width = */ 6, \"____45\"},\n      {37, kOct | kUpper | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kUpper | kBase, /*width = */ 6, \"___045\"},\n      {37, kOct | kUpper | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kUpper | kBase | kPos, /*width = */ 6, \"___045\"},\n      {37, kOct | kLeft, /*width = */ 0, \"45\"},\n      {37, kOct | kLeft, /*width = */ 6, \"45____\"},\n      {37, kOct | kLeft | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kLeft | kPos, /*width = */ 6, \"45____\"},\n      {37, kOct | kLeft | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kLeft | kBase, /*width = */ 6, \"045___\"},\n      {37, kOct | kLeft | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kLeft | kBase | kPos, /*width = */ 6, \"045___\"},\n      {37, kOct | kLeft | kUpper, /*width = */ 0, \"45\"},\n      {37, kOct | kLeft | kUpper, /*width = */ 6, \"45____\"},\n      {37, kOct | kLeft | kUpper | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kLeft | kUpper | kPos, /*width = */ 6, \"45____\"},\n      {37, kOct | kLeft | kUpper | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kLeft | kUpper | kBase, /*width = */ 6, \"045___\"},\n      {37, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"045___\"},\n      {37, kOct | kInt, /*width = */ 0, \"45\"},\n      {37, kOct | kInt, /*width = */ 6, \"____45\"},\n      {37, kOct | kInt | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kInt | kPos, /*width = */ 6, \"____45\"},\n      {37, kOct | kInt | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kInt | kBase, /*width = */ 6, \"___045\"},\n      {37, kOct | kInt | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kInt | kBase | kPos, /*width = */ 6, \"___045\"},\n      {37, kOct | kInt | kUpper, /*width = */ 0, \"45\"},\n      {37, kOct | kInt | kUpper, /*width = */ 6, \"____45\"},\n      {37, kOct | kInt | kUpper | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kInt | kUpper | kPos, /*width = */ 6, \"____45\"},\n      {37, kOct | kInt | kUpper | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kInt | kUpper | kBase, /*width = */ 6, \"___045\"},\n      {37, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, \"___045\"},\n      {37, kOct | kRight, /*width = */ 0, \"45\"},\n      {37, kOct | kRight, /*width = */ 6, \"____45\"},\n      {37, kOct | kRight | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kRight | kPos, /*width = */ 6, \"____45\"},\n      {37, kOct | kRight | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kRight | kBase, /*width = */ 6, \"___045\"},\n      {37, kOct | kRight | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kRight | kBase | kPos, /*width = */ 6, \"___045\"},\n      {37, kOct | kRight | kUpper, /*width = */ 0, \"45\"},\n      {37, kOct | kRight | kUpper, /*width = */ 6, \"____45\"},\n      {37, kOct | kRight | kUpper | kPos, /*width = */ 0, \"45\"},\n      {37, kOct | kRight | kUpper | kPos, /*width = */ 6, \"____45\"},\n      {37, kOct | kRight | kUpper | kBase, /*width = */ 0, \"045\"},\n      {37, kOct | kRight | kUpper | kBase, /*width = */ 6, \"___045\"},\n      {37, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, \"045\"},\n      {37, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, \"___045\"},\n      {37, kHex, /*width = */ 0, \"25\"},\n      {37, kHex, /*width = */ 6, \"____25\"},\n      {37, kHex | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kPos, /*width = */ 6, \"____25\"},\n      {37, kHex | kBase, /*width = */ 0, \"0x25\"},\n      {37, kHex | kBase, /*width = */ 6, \"__0x25\"},\n      {37, kHex | kBase | kPos, /*width = */ 0, \"0x25\"},\n      {37, kHex | kBase | kPos, /*width = */ 6, \"__0x25\"},\n      {37, kHex | kUpper, /*width = */ 0, \"25\"},\n      {37, kHex | kUpper, /*width = */ 6, \"____25\"},\n      {37, kHex | kUpper | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kUpper | kPos, /*width = */ 6, \"____25\"},\n      {37, kHex | kUpper | kBase, /*width = */ 0, \"0X25\"},\n      {37, kHex | kUpper | kBase, /*width = */ 6, \"__0X25\"},\n      {37, kHex | kUpper | kBase | kPos, /*width = */ 0, \"0X25\"},\n      {37, kHex | kUpper | kBase | kPos, /*width = */ 6, \"__0X25\"},\n      {37, kHex | kLeft, /*width = */ 0, \"25\"},\n      {37, kHex | kLeft, /*width = */ 6, \"25____\"},\n      {37, kHex | kLeft | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kLeft | kPos, /*width = */ 6, \"25____\"},\n      {37, kHex | kLeft | kBase, /*width = */ 0, \"0x25\"},\n      {37, kHex | kLeft | kBase, /*width = */ 6, \"0x25__\"},\n      {37, kHex | kLeft | kBase | kPos, /*width = */ 0, \"0x25\"},\n      {37, kHex | kLeft | kBase | kPos, /*width = */ 6, \"0x25__\"},\n      {37, kHex | kLeft | kUpper, /*width = */ 0, \"25\"},\n      {37, kHex | kLeft | kUpper, /*width = */ 6, \"25____\"},\n      {37, kHex | kLeft | kUpper | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kLeft | kUpper | kPos, /*width = */ 6, \"25____\"},\n      {37, kHex | kLeft | kUpper | kBase, /*width = */ 0, \"0X25\"},\n      {37, kHex | kLeft | kUpper | kBase, /*width = */ 6, \"0X25__\"},\n      {37, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, \"0X25\"},\n      {37, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, \"0X25__\"},\n      {37, kHex | kInt, /*width = */ 0, \"25\"},\n      {37, kHex | kInt, /*width = */ 6, \"____25\"},\n      {37, kHex | kInt | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kInt | kPos, /*width = */ 6, \"____25\"},\n      {37, kHex | kInt | kBase, /*width = */ 0, \"0x25\"},\n      {37, kHex | kInt | kBase, /*width = */ 6, \"0x__25\"},\n      {37, kHex | kInt | kBase | kPos, /*width = */ 0, \"0x25\"},\n      {37, kHex | kInt | kBase | kPos, /*width = */ 6, \"0x__25\"},\n      {37, kHex | kInt | kUpper, /*width = */ 0, \"25\"},\n      {37, kHex | kInt | kUpper, /*width = */ 6, \"____25\"},\n      {37, kHex | kInt | kUpper | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kInt | kUpper | kPos, /*width = */ 6, \"____25\"},\n      {37, kHex | kInt | kUpper | kBase, /*width = */ 0, \"0X25\"},\n      {37, kHex | kInt | kUpper | kBase, /*width = */ 6, \"0X__25\"},\n      {37, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, \"0X25\"},\n      {37, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, \"0X__25\"},\n      {37, kHex | kRight, /*width = */ 0, \"25\"},\n      {37, kHex | kRight, /*width = */ 6, \"____25\"},\n      {37, kHex | kRight | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kRight | kPos, /*width = */ 6, \"____25\"},\n      {37, kHex | kRight | kBase, /*width = */ 0, \"0x25\"},\n      {37, kHex | kRight | kBase, /*width = */ 6, \"__0x25\"},\n      {37, kHex | kRight | kBase | kPos, /*width = */ 0, \"0x25\"},\n      {37, kHex | kRight | kBase | kPos, /*width = */ 6, \"__0x25\"},\n      {37, kHex | kRight | kUpper, /*width = */ 0, \"25\"},\n      {37, kHex | kRight | kUpper, /*width = */ 6, \"____25\"},\n      {37, kHex | kRight | kUpper | kPos, /*width = */ 0, \"25\"},\n      {37, kHex | kRight | kUpper | kPos, /*width = */ 6, \"____25\"},\n      {37, kHex | kRight | kUpper | kBase, /*width = */ 0, \"0X25\"},\n      {37, kHex | kRight | kUpper | kBase, /*width = */ 6, \"__0X25\"},\n      {37, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, \"0X25\"},\n      {37, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, \"__0X25\"}};\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/numeric/int128_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/numeric/int128.h\"\n\n#include <algorithm>\n#include <limits>\n#include <random>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/internal/cycleclock.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/types/compare.h\"\n\n#define MAKE_INT128(HI, LO) absl::MakeInt128(static_cast<int64_t>(HI), LO)\n\nnamespace {\n\ntemplate <typename T>\nclass Uint128IntegerTraitsTest : public ::testing::Test {};\ntypedef ::testing::Types<bool, char, signed char, unsigned char, char16_t,\n                         char32_t, wchar_t,\n                         short,           // NOLINT(runtime/int)\n                         unsigned short,  // NOLINT(runtime/int)\n                         int, unsigned int,\n                         long,                // NOLINT(runtime/int)\n                         unsigned long,       // NOLINT(runtime/int)\n                         long long,           // NOLINT(runtime/int)\n                         unsigned long long>  // NOLINT(runtime/int)\n    IntegerTypes;\n\ntemplate <typename T>\nclass Uint128FloatTraitsTest : public ::testing::Test {};\ntypedef ::testing::Types<float, double, long double> FloatingPointTypes;\n\nTYPED_TEST_SUITE(Uint128IntegerTraitsTest, IntegerTypes);\n\nTYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) {\n  static_assert(std::is_constructible<absl::uint128, TypeParam>::value,\n                \"absl::uint128 must be constructible from TypeParam\");\n  static_assert(std::is_assignable<absl::uint128&, TypeParam>::value,\n                \"absl::uint128 must be assignable from TypeParam\");\n  static_assert(!std::is_assignable<TypeParam&, absl::uint128>::value,\n                \"TypeParam must not be assignable from absl::uint128\");\n}\n\nTYPED_TEST_SUITE(Uint128FloatTraitsTest, FloatingPointTypes);\n\nTYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) {\n  static_assert(std::is_constructible<absl::uint128, TypeParam>::value,\n                \"absl::uint128 must be constructible from TypeParam\");\n  static_assert(!std::is_assignable<absl::uint128&, TypeParam>::value,\n                \"absl::uint128 must not be assignable from TypeParam\");\n  static_assert(!std::is_assignable<TypeParam&, absl::uint128>::value,\n                \"TypeParam must not be assignable from absl::uint128\");\n}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n// These type traits done separately as TYPED_TEST requires typeinfo, and not\n// all platforms have this for __int128 even though they define the type.\nTEST(Uint128, IntrinsicTypeTraitsTest) {\n  static_assert(std::is_constructible<absl::uint128, __int128>::value,\n                \"absl::uint128 must be constructible from __int128\");\n  static_assert(std::is_assignable<absl::uint128&, __int128>::value,\n                \"absl::uint128 must be assignable from __int128\");\n  static_assert(!std::is_assignable<__int128&, absl::uint128>::value,\n                \"__int128 must not be assignable from absl::uint128\");\n\n  static_assert(std::is_constructible<absl::uint128, unsigned __int128>::value,\n                \"absl::uint128 must be constructible from unsigned __int128\");\n  static_assert(std::is_assignable<absl::uint128&, unsigned __int128>::value,\n                \"absl::uint128 must be assignable from unsigned __int128\");\n  static_assert(!std::is_assignable<unsigned __int128&, absl::uint128>::value,\n                \"unsigned __int128 must not be assignable from absl::uint128\");\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nTEST(Uint128, TrivialTraitsTest) {\n  static_assert(absl::is_trivially_default_constructible<absl::uint128>::value,\n                \"\");\n  static_assert(absl::is_trivially_copy_constructible<absl::uint128>::value,\n                \"\");\n  static_assert(absl::is_trivially_copy_assignable<absl::uint128>::value, \"\");\n  static_assert(std::is_trivially_destructible<absl::uint128>::value, \"\");\n}\n\nTEST(Uint128, AllTests) {\n  absl::uint128 zero = 0;\n  absl::uint128 one = 1;\n  absl::uint128 one_2arg = absl::MakeUint128(0, 1);\n  absl::uint128 two = 2;\n  absl::uint128 three = 3;\n  absl::uint128 big = absl::MakeUint128(2000, 2);\n  absl::uint128 big_minus_one = absl::MakeUint128(2000, 1);\n  absl::uint128 bigger = absl::MakeUint128(2001, 1);\n  absl::uint128 biggest = absl::Uint128Max();\n  absl::uint128 high_low = absl::MakeUint128(1, 0);\n  absl::uint128 low_high =\n      absl::MakeUint128(0, std::numeric_limits<uint64_t>::max());\n  EXPECT_LT(one, two);\n  EXPECT_GT(two, one);\n  EXPECT_LT(one, big);\n  EXPECT_LT(one, big);\n  EXPECT_EQ(one, one_2arg);\n  EXPECT_NE(one, two);\n  EXPECT_GT(big, one);\n  EXPECT_GE(big, two);\n  EXPECT_GE(big, big_minus_one);\n  EXPECT_GT(big, big_minus_one);\n  EXPECT_LT(big_minus_one, big);\n  EXPECT_LE(big_minus_one, big);\n  EXPECT_NE(big_minus_one, big);\n  EXPECT_LT(big, biggest);\n  EXPECT_LE(big, biggest);\n  EXPECT_GT(biggest, big);\n  EXPECT_GE(biggest, big);\n  EXPECT_EQ(big, ~~big);\n  EXPECT_EQ(one, one | one);\n  EXPECT_EQ(big, big | big);\n  EXPECT_EQ(one, one | zero);\n  EXPECT_EQ(one, one & one);\n  EXPECT_EQ(big, big & big);\n  EXPECT_EQ(zero, one & zero);\n  EXPECT_EQ(zero, big & ~big);\n  EXPECT_EQ(zero, one ^ one);\n  EXPECT_EQ(zero, big ^ big);\n  EXPECT_EQ(one, one ^ zero);\n\n  // Shift operators.\n  EXPECT_EQ(big, big << 0);\n  EXPECT_EQ(big, big >> 0);\n  EXPECT_GT(big << 1, big);\n  EXPECT_LT(big >> 1, big);\n  EXPECT_EQ(big, (big << 10) >> 10);\n  EXPECT_EQ(big, (big >> 1) << 1);\n  EXPECT_EQ(one, (one << 80) >> 80);\n  EXPECT_EQ(zero, (one >> 80) << 80);\n\n  // Shift assignments.\n  absl::uint128 big_copy = big;\n  EXPECT_EQ(big << 0, big_copy <<= 0);\n  big_copy = big;\n  EXPECT_EQ(big >> 0, big_copy >>= 0);\n  big_copy = big;\n  EXPECT_EQ(big << 1, big_copy <<= 1);\n  big_copy = big;\n  EXPECT_EQ(big >> 1, big_copy >>= 1);\n  big_copy = big;\n  EXPECT_EQ(big << 10, big_copy <<= 10);\n  big_copy = big;\n  EXPECT_EQ(big >> 10, big_copy >>= 10);\n  big_copy = big;\n  EXPECT_EQ(big << 64, big_copy <<= 64);\n  big_copy = big;\n  EXPECT_EQ(big >> 64, big_copy >>= 64);\n  big_copy = big;\n  EXPECT_EQ(big << 73, big_copy <<= 73);\n  big_copy = big;\n  EXPECT_EQ(big >> 73, big_copy >>= 73);\n\n  EXPECT_EQ(absl::Uint128High64(biggest), std::numeric_limits<uint64_t>::max());\n  EXPECT_EQ(absl::Uint128Low64(biggest), std::numeric_limits<uint64_t>::max());\n  EXPECT_EQ(zero + one, one);\n  EXPECT_EQ(one + one, two);\n  EXPECT_EQ(big_minus_one + one, big);\n  EXPECT_EQ(one - one, zero);\n  EXPECT_EQ(one - zero, one);\n  EXPECT_EQ(zero - one, biggest);\n  EXPECT_EQ(big - big, zero);\n  EXPECT_EQ(big - one, big_minus_one);\n  EXPECT_EQ(big + std::numeric_limits<uint64_t>::max(), bigger);\n  EXPECT_EQ(biggest + 1, zero);\n  EXPECT_EQ(zero - 1, biggest);\n  EXPECT_EQ(high_low - one, low_high);\n  EXPECT_EQ(low_high + one, high_low);\n  EXPECT_EQ(absl::Uint128High64((absl::uint128(1) << 64) - 1), 0);\n  EXPECT_EQ(absl::Uint128Low64((absl::uint128(1) << 64) - 1),\n            std::numeric_limits<uint64_t>::max());\n  EXPECT_TRUE(!!one);\n  EXPECT_TRUE(!!high_low);\n  EXPECT_FALSE(!!zero);\n  EXPECT_FALSE(!one);\n  EXPECT_FALSE(!high_low);\n  EXPECT_TRUE(!zero);\n  EXPECT_TRUE(zero == 0);       // NOLINT(readability/check)\n  EXPECT_FALSE(zero != 0);      // NOLINT(readability/check)\n  EXPECT_FALSE(one == 0);       // NOLINT(readability/check)\n  EXPECT_TRUE(one != 0);        // NOLINT(readability/check)\n  EXPECT_FALSE(high_low == 0);  // NOLINT(readability/check)\n  EXPECT_TRUE(high_low != 0);   // NOLINT(readability/check)\n\n  absl::uint128 test = zero;\n  EXPECT_EQ(++test, one);\n  EXPECT_EQ(test, one);\n  EXPECT_EQ(test++, one);\n  EXPECT_EQ(test, two);\n  EXPECT_EQ(test -= 2, zero);\n  EXPECT_EQ(test, zero);\n  EXPECT_EQ(test += 2, two);\n  EXPECT_EQ(test, two);\n  EXPECT_EQ(--test, one);\n  EXPECT_EQ(test, one);\n  EXPECT_EQ(test--, one);\n  EXPECT_EQ(test, zero);\n  EXPECT_EQ(test |= three, three);\n  EXPECT_EQ(test &= one, one);\n  EXPECT_EQ(test ^= three, two);\n  EXPECT_EQ(test >>= 1, one);\n  EXPECT_EQ(test <<= 1, two);\n\n  EXPECT_EQ(big, +big);\n  EXPECT_EQ(two, +two);\n  EXPECT_EQ(absl::Uint128Max(), +absl::Uint128Max());\n  EXPECT_EQ(zero, +zero);\n\n  EXPECT_EQ(big, -(-big));\n  EXPECT_EQ(two, -((-one) - 1));\n  EXPECT_EQ(absl::Uint128Max(), -one);\n  EXPECT_EQ(zero, -zero);\n}\n\nTEST(Int128, RightShiftOfNegativeNumbers) {\n  absl::int128 minus_six = -6;\n  absl::int128 minus_three = -3;\n  absl::int128 minus_two = -2;\n  absl::int128 minus_one = -1;\n  if ((-6 >> 1) == -3) {\n    // Right shift is arithmetic (sign propagates)\n    EXPECT_EQ(minus_six >> 1, minus_three);\n    EXPECT_EQ(minus_six >> 2, minus_two);\n    EXPECT_EQ(minus_six >> 65, minus_one);\n  } else {\n    // Right shift is logical (zeros shifted in at MSB)\n    EXPECT_EQ(minus_six >> 1, absl::int128(absl::uint128(minus_six) >> 1));\n    EXPECT_EQ(minus_six >> 2, absl::int128(absl::uint128(minus_six) >> 2));\n    EXPECT_EQ(minus_six >> 65, absl::int128(absl::uint128(minus_six) >> 65));\n  }\n}\n\nTEST(Uint128, ConversionTests) {\n  EXPECT_TRUE(absl::MakeUint128(1, 0));\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  unsigned __int128 intrinsic =\n      (static_cast<unsigned __int128>(0x3a5b76c209de76f6) << 64) +\n      0x1f25e1d63a2b46c5;\n  absl::uint128 custom =\n      absl::MakeUint128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5);\n\n  EXPECT_EQ(custom, absl::uint128(intrinsic));\n  EXPECT_EQ(custom, absl::uint128(static_cast<__int128>(intrinsic)));\n  EXPECT_EQ(intrinsic, static_cast<unsigned __int128>(custom));\n  EXPECT_EQ(intrinsic, static_cast<__int128>(custom));\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\n  // verify that an integer greater than 2**64 that can be stored precisely\n  // inside a double is converted to a absl::uint128 without loss of\n  // information.\n  double precise_double = 0x530e * std::pow(2.0, 64.0) + 0xda74000000000000;\n  absl::uint128 from_precise_double(precise_double);\n  absl::uint128 from_precise_ints =\n      absl::MakeUint128(0x530e, 0xda74000000000000);\n  EXPECT_EQ(from_precise_double, from_precise_ints);\n  EXPECT_DOUBLE_EQ(static_cast<double>(from_precise_ints), precise_double);\n\n  double approx_double =\n      static_cast<double>(0xffffeeeeddddcccc) * std::pow(2.0, 64.0) +\n      static_cast<double>(0xbbbbaaaa99998888);\n  absl::uint128 from_approx_double(approx_double);\n  EXPECT_DOUBLE_EQ(static_cast<double>(from_approx_double), approx_double);\n\n  double round_to_zero = 0.7;\n  double round_to_five = 5.8;\n  double round_to_nine = 9.3;\n  EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);\n  EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);\n  EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);\n\n  absl::uint128 highest_precision_in_long_double =\n      ~absl::uint128{} >> (128 - std::numeric_limits<long double>::digits);\n  EXPECT_EQ(highest_precision_in_long_double,\n            static_cast<absl::uint128>(\n                static_cast<long double>(highest_precision_in_long_double)));\n  // Apply a mask just to make sure all the bits are the right place.\n  const absl::uint128 arbitrary_mask =\n      absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468);\n  EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask,\n            static_cast<absl::uint128>(static_cast<long double>(\n                highest_precision_in_long_double & arbitrary_mask)));\n\n  EXPECT_EQ(static_cast<absl::uint128>(-0.1L), 0);\n}\n\nTEST(Uint128, OperatorAssignReturnRef) {\n  absl::uint128 v(1);\n  (v += 4) -= 3;\n  EXPECT_EQ(2, v);\n}\n\nTEST(Uint128, Multiply) {\n  absl::uint128 a, b, c;\n\n  // Zero test.\n  a = 0;\n  b = 0;\n  c = a * b;\n  EXPECT_EQ(0, c);\n\n  // Max carries.\n  a = absl::uint128(0) - 1;\n  b = absl::uint128(0) - 1;\n  c = a * b;\n  EXPECT_EQ(1, c);\n\n  // Self-operation with max carries.\n  c = absl::uint128(0) - 1;\n  c *= c;\n  EXPECT_EQ(1, c);\n\n  // 1-bit x 1-bit.\n  for (int i = 0; i < 64; ++i) {\n    for (int j = 0; j < 64; ++j) {\n      a = absl::uint128(1) << i;\n      b = absl::uint128(1) << j;\n      c = a * b;\n      EXPECT_EQ(absl::uint128(1) << (i + j), c);\n    }\n  }\n\n  // Verified with dc.\n  a = absl::MakeUint128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888);\n  b = absl::MakeUint128(0x7777666655554444, 0x3333222211110000);\n  c = a * b;\n  EXPECT_EQ(absl::MakeUint128(0x530EDA741C71D4C3, 0xBF25975319080000), c);\n  EXPECT_EQ(0, c - b * a);\n  EXPECT_EQ(a * a - b * b, (a + b) * (a - b));\n\n  // Verified with dc.\n  a = absl::MakeUint128(0x0123456789abcdef, 0xfedcba9876543210);\n  b = absl::MakeUint128(0x02468ace13579bdf, 0xfdb97531eca86420);\n  c = a * b;\n  EXPECT_EQ(absl::MakeUint128(0x97a87f4f261ba3f2, 0x342d0bbf48948200), c);\n  EXPECT_EQ(0, c - b * a);\n  EXPECT_EQ(a * a - b * b, (a + b) * (a - b));\n}\n\nTEST(Uint128, AliasTests) {\n  absl::uint128 x1 = absl::MakeUint128(1, 2);\n  absl::uint128 x2 = absl::MakeUint128(2, 4);\n  x1 += x1;\n  EXPECT_EQ(x2, x1);\n\n  absl::uint128 x3 = absl::MakeUint128(1, static_cast<uint64_t>(1) << 63);\n  absl::uint128 x4 = absl::MakeUint128(3, 0);\n  x3 += x3;\n  EXPECT_EQ(x4, x3);\n}\n\nTEST(Uint128, DivideAndMod) {\n  using std::swap;\n\n  // a := q * b + r\n  absl::uint128 a, b, q, r;\n\n  // Zero test.\n  a = 0;\n  b = 123;\n  q = a / b;\n  r = a % b;\n  EXPECT_EQ(0, q);\n  EXPECT_EQ(0, r);\n\n  a = absl::MakeUint128(0x530eda741c71d4c3, 0xbf25975319080000);\n  q = absl::MakeUint128(0x4de2cab081, 0x14c34ab4676e4bab);\n  b = absl::uint128(0x1110001);\n  r = absl::uint128(0x3eb455);\n  ASSERT_EQ(a, q * b + r);  // Sanity-check.\n\n  absl::uint128 result_q, result_r;\n  result_q = a / b;\n  result_r = a % b;\n  EXPECT_EQ(q, result_q);\n  EXPECT_EQ(r, result_r);\n\n  // Try the other way around.\n  swap(q, b);\n  result_q = a / b;\n  result_r = a % b;\n  EXPECT_EQ(q, result_q);\n  EXPECT_EQ(r, result_r);\n  // Restore.\n  swap(b, q);\n\n  // Dividend < divisor; result should be q:0 r:<dividend>.\n  swap(a, b);\n  result_q = a / b;\n  result_r = a % b;\n  EXPECT_EQ(0, result_q);\n  EXPECT_EQ(a, result_r);\n  // Try the other way around.\n  swap(a, q);\n  result_q = a / b;\n  result_r = a % b;\n  EXPECT_EQ(0, result_q);\n  EXPECT_EQ(a, result_r);\n  // Restore.\n  swap(q, a);\n  swap(b, a);\n\n  // Try a large remainder.\n  b = a / 2 + 1;\n  absl::uint128 expected_r =\n      absl::MakeUint128(0x29876d3a0e38ea61, 0xdf92cba98c83ffff);\n  // Sanity checks.\n  ASSERT_EQ(a / 2 - 1, expected_r);\n  ASSERT_EQ(a, b + expected_r);\n  result_q = a / b;\n  result_r = a % b;\n  EXPECT_EQ(1, result_q);\n  EXPECT_EQ(expected_r, result_r);\n}\n\nTEST(Uint128, DivideAndModRandomInputs) {\n  const int kNumIters = 1 << 18;\n  std::minstd_rand random(testing::UnitTest::GetInstance()->random_seed());\n  std::uniform_int_distribution<uint64_t> uniform_uint64;\n  for (int i = 0; i < kNumIters; ++i) {\n    const absl::uint128 a =\n        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));\n    const absl::uint128 b =\n        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));\n    if (b == 0) {\n      continue;  // Avoid a div-by-zero.\n    }\n    const absl::uint128 q = a / b;\n    const absl::uint128 r = a % b;\n    ASSERT_EQ(a, b * q + r);\n  }\n}\n\nTEST(Uint128, ConstexprTest) {\n  constexpr absl::uint128 zero = absl::uint128();\n  constexpr absl::uint128 one = 1;\n  constexpr absl::uint128 minus_two = -2;\n  EXPECT_EQ(zero, absl::uint128(0));\n  EXPECT_EQ(one, absl::uint128(1));\n  EXPECT_EQ(minus_two, absl::MakeUint128(-1, -2));\n\n  constexpr double f = static_cast<float>(absl::uint128(123));\n  EXPECT_EQ(f, 123.0f);\n\n  constexpr double d = static_cast<double>(absl::uint128(123));\n  EXPECT_EQ(d, 123.0);\n\n  constexpr long double ld = static_cast<long double>(absl::uint128(123));\n  EXPECT_EQ(ld, 123.0);\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  constexpr absl::uint128 division = absl::uint128(10) / absl::uint128(2);\n  EXPECT_EQ(division, absl::uint128(5));\n\n  constexpr absl::uint128 modulus = absl::int128(10) % absl::int128(3);\n  EXPECT_EQ(modulus, absl::uint128(1));\n\n  constexpr absl::uint128 multiplication = absl::uint128(10) * absl::uint128(3);\n  EXPECT_EQ(multiplication, absl::uint128(30));\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n}\n\nTEST(Uint128, NumericLimitsTest) {\n  static_assert(std::numeric_limits<absl::uint128>::is_specialized, \"\");\n  static_assert(!std::numeric_limits<absl::uint128>::is_signed, \"\");\n  static_assert(std::numeric_limits<absl::uint128>::is_integer, \"\");\n  EXPECT_EQ(static_cast<int>(128 * std::log10(2)),\n            std::numeric_limits<absl::uint128>::digits10);\n  EXPECT_EQ(0, std::numeric_limits<absl::uint128>::min());\n  EXPECT_EQ(0, std::numeric_limits<absl::uint128>::lowest());\n  EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max());\n}\n\n// Some arbitrary constant to test hashing. The first hex digits of pi.\nconstexpr absl::uint128 kPi = (absl::uint128(0x3243f6a8885a308d) << 64) |\n                              absl::uint128(0x313198a2e0370734);\n\nTEST(Uint128, Hash) {\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  using Ext128 = unsigned __int128;\n#endif\n  // Make the tuple outside the EXPECT_TRUE because putting the #if inside the\n  // macro argument is not ok.\n  const auto values = std::make_tuple(\n      // Some simple values\n      absl::uint128{0}, absl::uint128{1}, ~absl::uint128{},\n      // 64 bit limits\n      absl::uint128{std::numeric_limits<int64_t>::max()},\n      absl::uint128{std::numeric_limits<uint64_t>::max()} + 0,\n      absl::uint128{std::numeric_limits<uint64_t>::max()} + 1,\n      absl::uint128{std::numeric_limits<uint64_t>::max()} + 2,\n      // Keeping high same\n      absl::uint128{1} << 62, absl::uint128{1} << 63,\n      // Keeping low same\n      absl::uint128{1} << 64, absl::uint128{1} << 65,\n      // 128 bit limits\n      std::numeric_limits<absl::uint128>::max(),\n      std::numeric_limits<absl::uint128>::max() - 1,\n      std::numeric_limits<absl::uint128>::min() + 1,\n      std::numeric_limits<absl::uint128>::min(),\n      // arbitrary constant\n      kPi\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n      // Same but with the intrinsic to verify that they match\n      ,\n      Ext128{0}, Ext128{1}, ~Ext128{},\n      Ext128{std::numeric_limits<int64_t>::max()},\n      Ext128{std::numeric_limits<uint64_t>::max()} + 0,\n      Ext128{std::numeric_limits<uint64_t>::max()} + 1,\n      Ext128{std::numeric_limits<uint64_t>::max()} + 2, Ext128{1} << 62,\n      Ext128{1} << 63, Ext128{1} << 64, Ext128{1} << 65,\n      std::numeric_limits<Ext128>::max(),\n      std::numeric_limits<Ext128>::max() - 1,\n      std::numeric_limits<Ext128>::min() + 1,\n      std::numeric_limits<Ext128>::min(), static_cast<Ext128>(kPi)\n#endif\n  );\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(values));\n}\n\nTEST(Int128Uint128, ConversionTest) {\n  absl::int128 nonnegative_signed_values[] = {\n      0,\n      1,\n      0xffeeddccbbaa9988,\n      absl::MakeInt128(0x7766554433221100, 0),\n      absl::MakeInt128(0x1234567890abcdef, 0xfedcba0987654321),\n      absl::Int128Max()};\n  for (absl::int128 value : nonnegative_signed_values) {\n    EXPECT_EQ(value, absl::int128(absl::uint128(value)));\n\n    absl::uint128 assigned_value;\n    assigned_value = value;\n    EXPECT_EQ(value, absl::int128(assigned_value));\n  }\n\n  absl::int128 negative_values[] = {\n      -1, -0x1234567890abcdef, absl::MakeInt128(-0x5544332211ffeedd, 0),\n      -absl::MakeInt128(0x76543210fedcba98, 0xabcdef0123456789)};\n  for (absl::int128 value : negative_values) {\n    EXPECT_EQ(absl::uint128(-value), -absl::uint128(value));\n\n    absl::uint128 assigned_value;\n    assigned_value = value;\n    EXPECT_EQ(absl::uint128(-value), -assigned_value);\n  }\n}\n\ntemplate <typename T>\nclass Int128IntegerTraitsTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE(Int128IntegerTraitsTest, IntegerTypes);\n\nTYPED_TEST(Int128IntegerTraitsTest, ConstructAssignTest) {\n  static_assert(std::is_constructible<absl::int128, TypeParam>::value,\n                \"absl::int128 must be constructible from TypeParam\");\n  static_assert(std::is_assignable<absl::int128&, TypeParam>::value,\n                \"absl::int128 must be assignable from TypeParam\");\n  static_assert(!std::is_assignable<TypeParam&, absl::int128>::value,\n                \"TypeParam must not be assignable from absl::int128\");\n}\n\ntemplate <typename T>\nclass Int128FloatTraitsTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE(Int128FloatTraitsTest, FloatingPointTypes);\n\nTYPED_TEST(Int128FloatTraitsTest, ConstructAssignTest) {\n  static_assert(std::is_constructible<absl::int128, TypeParam>::value,\n                \"absl::int128 must be constructible from TypeParam\");\n  static_assert(!std::is_assignable<absl::int128&, TypeParam>::value,\n                \"absl::int128 must not be assignable from TypeParam\");\n  static_assert(!std::is_assignable<TypeParam&, absl::int128>::value,\n                \"TypeParam must not be assignable from absl::int128\");\n}\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n// These type traits done separately as TYPED_TEST requires typeinfo, and not\n// all platforms have this for __int128 even though they define the type.\nTEST(Int128, IntrinsicTypeTraitsTest) {\n  static_assert(std::is_constructible<absl::int128, __int128>::value,\n                \"absl::int128 must be constructible from __int128\");\n  static_assert(std::is_assignable<absl::int128&, __int128>::value,\n                \"absl::int128 must be assignable from __int128\");\n  static_assert(!std::is_assignable<__int128&, absl::int128>::value,\n                \"__int128 must not be assignable from absl::int128\");\n\n  static_assert(std::is_constructible<absl::int128, unsigned __int128>::value,\n                \"absl::int128 must be constructible from unsigned __int128\");\n  static_assert(!std::is_assignable<absl::int128&, unsigned __int128>::value,\n                \"absl::int128 must be assignable from unsigned __int128\");\n  static_assert(!std::is_assignable<unsigned __int128&, absl::int128>::value,\n                \"unsigned __int128 must not be assignable from absl::int128\");\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nTEST(Int128, TrivialTraitsTest) {\n  static_assert(absl::is_trivially_default_constructible<absl::int128>::value,\n                \"\");\n  static_assert(absl::is_trivially_copy_constructible<absl::int128>::value, \"\");\n  static_assert(absl::is_trivially_copy_assignable<absl::int128>::value, \"\");\n  static_assert(std::is_trivially_destructible<absl::int128>::value, \"\");\n}\n\nTEST(Int128, BoolConversionTest) {\n  EXPECT_FALSE(absl::int128(0));\n  for (int i = 0; i < 64; ++i) {\n    EXPECT_TRUE(absl::MakeInt128(0, uint64_t{1} << i));\n  }\n  for (int i = 0; i < 63; ++i) {\n    EXPECT_TRUE(absl::MakeInt128(int64_t{1} << i, 0));\n  }\n  EXPECT_TRUE(absl::Int128Min());\n\n  EXPECT_EQ(absl::int128(1), absl::int128(true));\n  EXPECT_EQ(absl::int128(0), absl::int128(false));\n}\n\ntemplate <typename T>\nclass Int128IntegerConversionTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE(Int128IntegerConversionTest, IntegerTypes);\n\nTYPED_TEST(Int128IntegerConversionTest, RoundTripTest) {\n  EXPECT_EQ(TypeParam{0}, static_cast<TypeParam>(absl::int128(0)));\n  EXPECT_EQ(std::numeric_limits<TypeParam>::min(),\n            static_cast<TypeParam>(\n                absl::int128(std::numeric_limits<TypeParam>::min())));\n  EXPECT_EQ(std::numeric_limits<TypeParam>::max(),\n            static_cast<TypeParam>(\n                absl::int128(std::numeric_limits<TypeParam>::max())));\n}\n\ntemplate <typename T>\nclass Int128FloatConversionTest : public ::testing::Test {};\n\nTYPED_TEST_SUITE(Int128FloatConversionTest, FloatingPointTypes);\n\nTYPED_TEST(Int128FloatConversionTest, ConstructAndCastTest) {\n  // Conversions where the floating point values should be exactly the same.\n  // 0x9f5b is a randomly chosen small value.\n  for (int i = 0; i < 110; ++i) {  // 110 = 126 - #bits in 0x9f5b\n    SCOPED_TRACE(::testing::Message() << \"i = \" << i);\n\n    TypeParam float_value = std::ldexp(static_cast<TypeParam>(0x9f5b), i);\n    absl::int128 int_value = absl::int128(0x9f5b) << i;\n\n    EXPECT_EQ(float_value, static_cast<TypeParam>(int_value));\n    EXPECT_EQ(-float_value, static_cast<TypeParam>(-int_value));\n    EXPECT_EQ(int_value, absl::int128(float_value));\n    EXPECT_EQ(-int_value, absl::int128(-float_value));\n  }\n\n  // Round trip conversions with a small sample of randomly generated uint64_t\n  // values (less than int64_t max so that value * 2^64 fits into int128).\n  uint64_t values[] = {0x6d4492c24fb86199, 0x26ead65e4cb359b5,\n                       0x2c43407433ba3fd1, 0x3b574ec668df6b55,\n                       0x1c750e55a29f4f0f};\n  for (uint64_t value : values) {\n    for (int i = 0; i <= 64; ++i) {\n      SCOPED_TRACE(::testing::Message()\n                   << \"value = \" << value << \"; i = \" << i);\n\n      TypeParam fvalue = std::ldexp(static_cast<TypeParam>(value), i);\n      EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(absl::int128(fvalue)));\n      EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(-absl::int128(fvalue)));\n      EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(absl::int128(-fvalue)));\n      EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(-absl::int128(-fvalue)));\n    }\n  }\n\n  // Round trip conversions with a small sample of random large positive values.\n  absl::int128 large_values[] = {\n      absl::MakeInt128(0x5b0640d96c7b3d9f, 0xb7a7189e51d18622),\n      absl::MakeInt128(0x34bed042c6f65270, 0x73b236570669a089),\n      absl::MakeInt128(0x43deba9e6da12724, 0xf7f0f83da686797d),\n      absl::MakeInt128(0x71e8d383be4e5589, 0x75c3f96fb00752b6)};\n  for (absl::int128 value : large_values) {\n    // Make value have as many significant bits as can be represented by\n    // the mantissa, also making sure the highest and lowest bit in the range\n    // are set.\n    value >>= (127 - std::numeric_limits<TypeParam>::digits);\n    value |= absl::int128(1) << (std::numeric_limits<TypeParam>::digits - 1);\n    value |= 1;\n    for (int i = 0; i < 127 - std::numeric_limits<TypeParam>::digits; ++i) {\n      absl::int128 int_value = value << i;\n      EXPECT_EQ(int_value,\n                static_cast<absl::int128>(static_cast<TypeParam>(int_value)));\n      EXPECT_EQ(-int_value,\n                static_cast<absl::int128>(static_cast<TypeParam>(-int_value)));\n    }\n  }\n\n  // Small sample of checks that rounding is toward zero\n  EXPECT_EQ(0, absl::int128(TypeParam(0.1)));\n  EXPECT_EQ(17, absl::int128(TypeParam(17.8)));\n  EXPECT_EQ(0, absl::int128(TypeParam(-0.8)));\n  EXPECT_EQ(-53, absl::int128(TypeParam(-53.1)));\n  EXPECT_EQ(0, absl::int128(TypeParam(0.5)));\n  EXPECT_EQ(0, absl::int128(TypeParam(-0.5)));\n  TypeParam just_lt_one = std::nexttoward(TypeParam(1), TypeParam(0));\n  EXPECT_EQ(0, absl::int128(just_lt_one));\n  TypeParam just_gt_minus_one = std::nexttoward(TypeParam(-1), TypeParam(0));\n  EXPECT_EQ(0, absl::int128(just_gt_minus_one));\n\n  // Check limits\n  EXPECT_DOUBLE_EQ(std::ldexp(static_cast<TypeParam>(1), 127),\n                   static_cast<TypeParam>(absl::Int128Max()));\n  EXPECT_DOUBLE_EQ(-std::ldexp(static_cast<TypeParam>(1), 127),\n                   static_cast<TypeParam>(absl::Int128Min()));\n}\n\nTEST(Int128, FactoryTest) {\n  EXPECT_EQ(absl::int128(-1), absl::MakeInt128(-1, -1));\n  EXPECT_EQ(absl::int128(-31), absl::MakeInt128(-1, -31));\n  EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::min()),\n            absl::MakeInt128(-1, std::numeric_limits<int64_t>::min()));\n  EXPECT_EQ(absl::int128(0), absl::MakeInt128(0, 0));\n  EXPECT_EQ(absl::int128(1), absl::MakeInt128(0, 1));\n  EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::max()),\n            absl::MakeInt128(0, std::numeric_limits<int64_t>::max()));\n}\n\nTEST(Int128, HighLowTest) {\n  struct HighLowPair {\n    int64_t high;\n    uint64_t low;\n  };\n  HighLowPair values[]{{0, 0}, {0, 1}, {1, 0}, {123, 456}, {-654, 321}};\n  for (const HighLowPair& pair : values) {\n    absl::int128 value = absl::MakeInt128(pair.high, pair.low);\n    EXPECT_EQ(pair.low, absl::Int128Low64(value));\n    EXPECT_EQ(pair.high, absl::Int128High64(value));\n  }\n}\n\nTEST(Int128, LimitsTest) {\n  EXPECT_EQ(absl::MakeInt128(0x7fffffffffffffff, 0xffffffffffffffff),\n            absl::Int128Max());\n  EXPECT_EQ(absl::Int128Max(), ~absl::Int128Min());\n}\n\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\nTEST(Int128, IntrinsicConversionTest) {\n  __int128 intrinsic =\n      (static_cast<__int128>(0x3a5b76c209de76f6) << 64) + 0x1f25e1d63a2b46c5;\n  absl::int128 custom =\n      absl::MakeInt128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5);\n\n  EXPECT_EQ(custom, absl::int128(intrinsic));\n  EXPECT_EQ(intrinsic, static_cast<__int128>(custom));\n}\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n\nTEST(Int128, ConstexprTest) {\n  constexpr absl::int128 zero = absl::int128();\n  constexpr absl::int128 one = 1;\n  constexpr absl::int128 minus_two = -2;\n  constexpr absl::int128 min = absl::Int128Min();\n  constexpr absl::int128 max = absl::Int128Max();\n  EXPECT_EQ(zero, absl::int128(0));\n  EXPECT_EQ(one, absl::int128(1));\n  EXPECT_EQ(minus_two, absl::MakeInt128(-1, -2));\n  EXPECT_GT(max, one);\n  EXPECT_LT(min, minus_two);\n\n  constexpr double f = static_cast<float>(absl::int128(123));\n  EXPECT_EQ(f, 123.0f);\n\n  constexpr double d = static_cast<double>(absl::int128(123));\n  EXPECT_EQ(d, 123.0);\n\n  constexpr long double ld = static_cast<long double>(absl::int128(123));\n  EXPECT_EQ(ld, 123.0);\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\n  constexpr absl::int128 f_int128(static_cast<float>(123.0));\n  EXPECT_EQ(f_int128, absl::int128(123));\n\n  constexpr absl::int128 d_int128(static_cast<double>(123.0));\n  EXPECT_EQ(d_int128, absl::int128(123));\n\n  constexpr absl::int128 ld_int128(static_cast<long double>(123.0));\n  EXPECT_EQ(ld_int128, absl::int128(123));\n\n  constexpr absl::int128 division = absl::int128(10) / absl::int128(2);\n  EXPECT_EQ(division, absl::int128(5));\n\n  constexpr absl::int128 modulus = absl::int128(10) % absl::int128(3);\n  EXPECT_EQ(modulus, absl::int128(1));\n\n  constexpr absl::int128 multiplication = absl::int128(10) * absl::int128(3);\n  EXPECT_EQ(multiplication, absl::int128(30));\n#endif  // ABSL_HAVE_INTRINSIC_INT128\n}\n\nTEST(Int128, ComparisonTest) {\n  struct TestCase {\n    absl::int128 smaller;\n    absl::int128 larger;\n  };\n  TestCase cases[] = {\n      {absl::int128(0), absl::int128(123)},\n      {absl::MakeInt128(-12, 34), absl::MakeInt128(12, 34)},\n      {absl::MakeInt128(1, 1000), absl::MakeInt128(1000, 1)},\n      {absl::MakeInt128(-1000, 1000), absl::MakeInt128(-1, 1)},\n  };\n  for (const TestCase& pair : cases) {\n    SCOPED_TRACE(::testing::Message() << \"pair.smaller = \" << pair.smaller\n                                      << \"; pair.larger = \" << pair.larger);\n\n    EXPECT_TRUE(pair.smaller == pair.smaller);  // NOLINT(readability/check)\n    EXPECT_TRUE(pair.larger == pair.larger);    // NOLINT(readability/check)\n    EXPECT_FALSE(pair.smaller == pair.larger);  // NOLINT(readability/check)\n\n    EXPECT_TRUE(pair.smaller != pair.larger);    // NOLINT(readability/check)\n    EXPECT_FALSE(pair.smaller != pair.smaller);  // NOLINT(readability/check)\n    EXPECT_FALSE(pair.larger != pair.larger);    // NOLINT(readability/check)\n\n    EXPECT_TRUE(pair.smaller < pair.larger);   // NOLINT(readability/check)\n    EXPECT_FALSE(pair.larger < pair.smaller);  // NOLINT(readability/check)\n\n    EXPECT_TRUE(pair.larger > pair.smaller);   // NOLINT(readability/check)\n    EXPECT_FALSE(pair.smaller > pair.larger);  // NOLINT(readability/check)\n\n    EXPECT_TRUE(pair.smaller <= pair.larger);   // NOLINT(readability/check)\n    EXPECT_FALSE(pair.larger <= pair.smaller);  // NOLINT(readability/check)\n    EXPECT_TRUE(pair.smaller <= pair.smaller);  // NOLINT(readability/check)\n    EXPECT_TRUE(pair.larger <= pair.larger);    // NOLINT(readability/check)\n\n    EXPECT_TRUE(pair.larger >= pair.smaller);   // NOLINT(readability/check)\n    EXPECT_FALSE(pair.smaller >= pair.larger);  // NOLINT(readability/check)\n    EXPECT_TRUE(pair.smaller >= pair.smaller);  // NOLINT(readability/check)\n    EXPECT_TRUE(pair.larger >= pair.larger);    // NOLINT(readability/check)\n\n#ifdef __cpp_impl_three_way_comparison\n    EXPECT_EQ(pair.smaller <=> pair.larger, absl::strong_ordering::less);\n    EXPECT_EQ(pair.larger <=> pair.smaller, absl::strong_ordering::greater);\n    EXPECT_EQ(pair.smaller <=> pair.smaller, absl::strong_ordering::equal);\n    EXPECT_EQ(pair.larger <=> pair.larger, absl::strong_ordering::equal);\n#endif\n  }\n}\n\nTEST(Int128, UnaryPlusTest) {\n  int64_t values64[] = {0, 1, 12345, 0x4000000000000000,\n                        std::numeric_limits<int64_t>::max()};\n  for (int64_t value : values64) {\n    SCOPED_TRACE(::testing::Message() << \"value = \" << value);\n\n    EXPECT_EQ(absl::int128(value), +absl::int128(value));\n    EXPECT_EQ(absl::int128(-value), +absl::int128(-value));\n    EXPECT_EQ(absl::MakeInt128(value, 0), +absl::MakeInt128(value, 0));\n    EXPECT_EQ(absl::MakeInt128(-value, 0), +absl::MakeInt128(-value, 0));\n  }\n}\n\nTEST(Int128, UnaryNegationTest) {\n  int64_t values64[] = {0, 1, 12345, 0x4000000000000000,\n                        std::numeric_limits<int64_t>::max()};\n  for (int64_t value : values64) {\n    SCOPED_TRACE(::testing::Message() << \"value = \" << value);\n\n    EXPECT_EQ(absl::int128(-value), -absl::int128(value));\n    EXPECT_EQ(absl::int128(value), -absl::int128(-value));\n    EXPECT_EQ(absl::MakeInt128(-value, 0), -absl::MakeInt128(value, 0));\n    EXPECT_EQ(absl::MakeInt128(value, 0), -absl::MakeInt128(-value, 0));\n  }\n}\n\nTEST(Int128, LogicalNotTest) {\n  EXPECT_TRUE(!absl::int128(0));\n  for (int i = 0; i < 64; ++i) {\n    EXPECT_FALSE(!absl::MakeInt128(0, uint64_t{1} << i));\n  }\n  for (int i = 0; i < 63; ++i) {\n    EXPECT_FALSE(!absl::MakeInt128(int64_t{1} << i, 0));\n  }\n}\n\nTEST(Int128, AdditionSubtractionTest) {\n  // 64 bit pairs that will not cause overflow / underflow. These test negative\n  // carry; positive carry must be checked separately.\n  std::pair<int64_t, int64_t> cases[]{\n      {0, 0},                              // 0, 0\n      {0, 2945781290834},                  // 0, +\n      {1908357619234, 0},                  // +, 0\n      {0, -1204895918245},                 // 0, -\n      {-2957928523560, 0},                 // -, 0\n      {89023982312461, 98346012567134},    // +, +\n      {-63454234568239, -23456235230773},  // -, -\n      {98263457263502, -21428561935925},   // +, -\n      {-88235237438467, 15923659234573},   // -, +\n  };\n  for (const auto& pair : cases) {\n    SCOPED_TRACE(::testing::Message()\n                 << \"pair = {\" << pair.first << \", \" << pair.second << '}');\n\n    EXPECT_EQ(absl::int128(pair.first + pair.second),\n              absl::int128(pair.first) + absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.second + pair.first),\n              absl::int128(pair.second) += absl::int128(pair.first));\n\n    EXPECT_EQ(absl::int128(pair.first - pair.second),\n              absl::int128(pair.first) - absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.second - pair.first),\n              absl::int128(pair.second) -= absl::int128(pair.first));\n\n    EXPECT_EQ(\n        absl::MakeInt128(pair.second + pair.first, 0),\n        absl::MakeInt128(pair.second, 0) + absl::MakeInt128(pair.first, 0));\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first + pair.second, 0),\n        absl::MakeInt128(pair.first, 0) += absl::MakeInt128(pair.second, 0));\n\n    EXPECT_EQ(\n        absl::MakeInt128(pair.second - pair.first, 0),\n        absl::MakeInt128(pair.second, 0) - absl::MakeInt128(pair.first, 0));\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first - pair.second, 0),\n        absl::MakeInt128(pair.first, 0) -= absl::MakeInt128(pair.second, 0));\n  }\n\n  // check positive carry\n  EXPECT_EQ(absl::MakeInt128(31, 0),\n            absl::MakeInt128(20, 1) +\n                absl::MakeInt128(10, std::numeric_limits<uint64_t>::max()));\n}\n\nTEST(Int128, IncrementDecrementTest) {\n  absl::int128 value = 0;\n  EXPECT_EQ(0, value++);\n  EXPECT_EQ(1, value);\n  EXPECT_EQ(1, value--);\n  EXPECT_EQ(0, value);\n  EXPECT_EQ(-1, --value);\n  EXPECT_EQ(-1, value);\n  EXPECT_EQ(0, ++value);\n  EXPECT_EQ(0, value);\n}\n\nTEST(Int128, MultiplicationTest) {\n  // 1 bit x 1 bit, and negative combinations\n  for (int i = 0; i < 64; ++i) {\n    for (int j = 0; j < 127 - i; ++j) {\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      absl::int128 a = absl::int128(1) << i;\n      absl::int128 b = absl::int128(1) << j;\n      absl::int128 c = absl::int128(1) << (i + j);\n\n      EXPECT_EQ(c, a * b);\n      EXPECT_EQ(-c, -a * b);\n      EXPECT_EQ(-c, a * -b);\n      EXPECT_EQ(c, -a * -b);\n\n      EXPECT_EQ(c, absl::int128(a) *= b);\n      EXPECT_EQ(-c, absl::int128(-a) *= b);\n      EXPECT_EQ(-c, absl::int128(a) *= -b);\n      EXPECT_EQ(c, absl::int128(-a) *= -b);\n    }\n  }\n\n  // Pairs of random values that will not overflow signed 64-bit multiplication\n  std::pair<int64_t, int64_t> small_values[] = {\n      {0x5e61, 0xf29f79ca14b4},    // +, +\n      {0x3e033b, -0x612c0ee549},   // +, -\n      {-0x052ce7e8, 0x7c728f0f},   // -, +\n      {-0x3af7054626, -0xfb1e1d},  // -, -\n  };\n  for (const std::pair<int64_t, int64_t>& pair : small_values) {\n    SCOPED_TRACE(::testing::Message()\n                 << \"pair = {\" << pair.first << \", \" << pair.second << '}');\n\n    EXPECT_EQ(absl::int128(pair.first * pair.second),\n              absl::int128(pair.first) * absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.first * pair.second),\n              absl::int128(pair.first) *= absl::int128(pair.second));\n\n    EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0),\n              absl::MakeInt128(pair.first, 0) * absl::int128(pair.second));\n    EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0),\n              absl::MakeInt128(pair.first, 0) *= absl::int128(pair.second));\n  }\n\n  // Pairs of positive random values that will not overflow 64-bit\n  // multiplication and can be left shifted by 32 without overflow\n  std::pair<int64_t, int64_t> small_values2[] = {\n      {0x1bb0a110, 0x31487671},\n      {0x4792784e, 0x28add7d7},\n      {0x7b66553a, 0x11dff8ef},\n  };\n  for (const std::pair<int64_t, int64_t>& pair : small_values2) {\n    SCOPED_TRACE(::testing::Message()\n                 << \"pair = {\" << pair.first << \", \" << pair.second << '}');\n\n    absl::int128 a = absl::int128(pair.first << 32);\n    absl::int128 b = absl::int128(pair.second << 32);\n    absl::int128 c = absl::MakeInt128(pair.first * pair.second, 0);\n\n    EXPECT_EQ(c, a * b);\n    EXPECT_EQ(-c, -a * b);\n    EXPECT_EQ(-c, a * -b);\n    EXPECT_EQ(c, -a * -b);\n\n    EXPECT_EQ(c, absl::int128(a) *= b);\n    EXPECT_EQ(-c, absl::int128(-a) *= b);\n    EXPECT_EQ(-c, absl::int128(a) *= -b);\n    EXPECT_EQ(c, absl::int128(-a) *= -b);\n  }\n\n  // check 0, 1, and -1 behavior with large values\n  absl::int128 large_values[] = {\n      {absl::MakeInt128(0xd66f061af02d0408, 0x727d2846cb475b53)},\n      {absl::MakeInt128(0x27b8d5ed6104452d, 0x03f8a33b0ee1df4f)},\n      {-absl::MakeInt128(0x621b6626b9e8d042, 0x27311ac99df00938)},\n      {-absl::MakeInt128(0x34e0656f1e95fb60, 0x4281cfd731257a47)},\n  };\n  for (absl::int128 value : large_values) {\n    EXPECT_EQ(0, 0 * value);\n    EXPECT_EQ(0, value * 0);\n    EXPECT_EQ(0, absl::int128(0) *= value);\n    EXPECT_EQ(0, value *= 0);\n\n    EXPECT_EQ(value, 1 * value);\n    EXPECT_EQ(value, value * 1);\n    EXPECT_EQ(value, absl::int128(1) *= value);\n    EXPECT_EQ(value, value *= 1);\n\n    EXPECT_EQ(-value, -1 * value);\n    EXPECT_EQ(-value, value * -1);\n    EXPECT_EQ(-value, absl::int128(-1) *= value);\n    EXPECT_EQ(-value, value *= -1);\n  }\n\n  // Manually calculated random large value cases\n  EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1),\n            absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) * 0x1a6037537b);\n  EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e),\n            -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) * 0xe5a434cd14866e);\n  EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4),\n            0xa9b98a8ddf66bc * -absl::MakeInt128(0x81, 0x672e58231e2469d7));\n  EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4),\n            -0x3e39341147 * -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c));\n\n  EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1),\n            absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) *= 0x1a6037537b);\n  EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e),\n            -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) *= 0xe5a434cd14866e);\n  EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4),\n            absl::int128(0xa9b98a8ddf66bc) *=\n            -absl::MakeInt128(0x81, 0x672e58231e2469d7));\n  EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4),\n            absl::int128(-0x3e39341147) *=\n            -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c));\n}\n\nTEST(Int128, DivisionAndModuloTest) {\n  // Check against 64 bit division and modulo operators with a sample of\n  // randomly generated pairs.\n  std::pair<int64_t, int64_t> small_pairs[] = {\n      {0x15f2a64138, 0x67da05},    {0x5e56d194af43045f, 0xcf1543fb99},\n      {0x15e61ed052036a, -0xc8e6}, {0x88125a341e85, -0xd23fb77683},\n      {-0xc06e20, 0x5a},           {-0x4f100219aea3e85d, 0xdcc56cb4efe993},\n      {-0x168d629105, -0xa7},      {-0x7b44e92f03ab2375, -0x6516},\n  };\n  for (const std::pair<int64_t, int64_t>& pair : small_pairs) {\n    SCOPED_TRACE(::testing::Message()\n                 << \"pair = {\" << pair.first << \", \" << pair.second << '}');\n\n    absl::int128 dividend = pair.first;\n    absl::int128 divisor = pair.second;\n    int64_t quotient = pair.first / pair.second;\n    int64_t remainder = pair.first % pair.second;\n\n    EXPECT_EQ(quotient, dividend / divisor);\n    EXPECT_EQ(quotient, absl::int128(dividend) /= divisor);\n    EXPECT_EQ(remainder, dividend % divisor);\n    EXPECT_EQ(remainder, absl::int128(dividend) %= divisor);\n  }\n\n  // Test behavior with 0, 1, and -1 with a sample of randomly generated large\n  // values.\n  absl::int128 values[] = {\n      absl::MakeInt128(0x63d26ee688a962b2, 0x9e1411abda5c1d70),\n      absl::MakeInt128(0x152f385159d6f986, 0xbf8d48ef63da395d),\n      -absl::MakeInt128(0x3098d7567030038c, 0x14e7a8a098dc2164),\n      -absl::MakeInt128(0x49a037aca35c809f, 0xa6a87525480ef330),\n  };\n  for (absl::int128 value : values) {\n    SCOPED_TRACE(::testing::Message() << \"value = \" << value);\n\n    EXPECT_EQ(0, 0 / value);\n    EXPECT_EQ(0, absl::int128(0) /= value);\n    EXPECT_EQ(0, 0 % value);\n    EXPECT_EQ(0, absl::int128(0) %= value);\n\n    EXPECT_EQ(value, value / 1);\n    EXPECT_EQ(value, absl::int128(value) /= 1);\n    EXPECT_EQ(0, value % 1);\n    EXPECT_EQ(0, absl::int128(value) %= 1);\n\n    EXPECT_EQ(-value, value / -1);\n    EXPECT_EQ(-value, absl::int128(value) /= -1);\n    EXPECT_EQ(0, value % -1);\n    EXPECT_EQ(0, absl::int128(value) %= -1);\n  }\n\n  // Min and max values\n  EXPECT_EQ(0, absl::Int128Max() / absl::Int128Min());\n  EXPECT_EQ(absl::Int128Max(), absl::Int128Max() % absl::Int128Min());\n  EXPECT_EQ(-1, absl::Int128Min() / absl::Int128Max());\n  EXPECT_EQ(-1, absl::Int128Min() % absl::Int128Max());\n\n  // Power of two division and modulo of random large dividends\n  absl::int128 positive_values[] = {\n      absl::MakeInt128(0x21e1a1cc69574620, 0xe7ac447fab2fc869),\n      absl::MakeInt128(0x32c2ff3ab89e66e8, 0x03379a613fd1ce74),\n      absl::MakeInt128(0x6f32ca786184dcaf, 0x046f9c9ecb3a9ce1),\n      absl::MakeInt128(0x1aeb469dd990e0ee, 0xda2740f243cd37eb),\n  };\n  for (absl::int128 value : positive_values) {\n    for (int i = 0; i < 127; ++i) {\n      SCOPED_TRACE(::testing::Message()\n                   << \"value = \" << value << \"; i = \" << i);\n      absl::int128 power_of_two = absl::int128(1) << i;\n\n      EXPECT_EQ(value >> i, value / power_of_two);\n      EXPECT_EQ(value >> i, absl::int128(value) /= power_of_two);\n      EXPECT_EQ(value & (power_of_two - 1), value % power_of_two);\n      EXPECT_EQ(value & (power_of_two - 1),\n                absl::int128(value) %= power_of_two);\n    }\n  }\n\n  // Manually calculated cases with random large dividends\n  struct DivisionModCase {\n    absl::int128 dividend;\n    absl::int128 divisor;\n    absl::int128 quotient;\n    absl::int128 remainder;\n  };\n  DivisionModCase manual_cases[] = {\n      {absl::MakeInt128(0x6ada48d489007966, 0x3c9c5c98150d5d69),\n       absl::MakeInt128(0x8bc308fb, 0x8cb9cc9a3b803344), 0xc3b87e08,\n       absl::MakeInt128(0x1b7db5e1, 0xd9eca34b7af04b49)},\n      {absl::MakeInt128(0xd6946511b5b, 0x4886c5c96546bf5f),\n       -absl::MakeInt128(0x263b, 0xfd516279efcfe2dc), -0x59cbabf0,\n       absl::MakeInt128(0x622, 0xf462909155651d1f)},\n      {-absl::MakeInt128(0x33db734f9e8d1399, 0x8447ac92482bca4d), 0x37495078240,\n       -absl::MakeInt128(0xf01f1, 0xbc0368bf9a77eae8), -0x21a508f404d},\n      {-absl::MakeInt128(0x13f837b409a07e7d, 0x7fc8e248a7d73560), -0x1b9f,\n       absl::MakeInt128(0xb9157556d724, 0xb14f635714d7563e), -0x1ade},\n  };\n  for (const DivisionModCase test_case : manual_cases) {\n    EXPECT_EQ(test_case.quotient, test_case.dividend / test_case.divisor);\n    EXPECT_EQ(test_case.quotient,\n              absl::int128(test_case.dividend) /= test_case.divisor);\n    EXPECT_EQ(test_case.remainder, test_case.dividend % test_case.divisor);\n    EXPECT_EQ(test_case.remainder,\n              absl::int128(test_case.dividend) %= test_case.divisor);\n  }\n}\n\nTEST(Int128, BitwiseLogicTest) {\n  EXPECT_EQ(absl::int128(-1), ~absl::int128(0));\n\n  absl::int128 values[]{\n      0, -1, 0xde400bee05c3ff6b, absl::MakeInt128(0x7f32178dd81d634a, 0),\n      absl::MakeInt128(0xaf539057055613a9, 0x7d104d7d946c2e4d)};\n  for (absl::int128 value : values) {\n    EXPECT_EQ(value, ~~value);\n\n    EXPECT_EQ(value, value | value);\n    EXPECT_EQ(value, value & value);\n    EXPECT_EQ(0, value ^ value);\n\n    EXPECT_EQ(value, absl::int128(value) |= value);\n    EXPECT_EQ(value, absl::int128(value) &= value);\n    EXPECT_EQ(0, absl::int128(value) ^= value);\n\n    EXPECT_EQ(value, value | 0);\n    EXPECT_EQ(0, value & 0);\n    EXPECT_EQ(value, value ^ 0);\n\n    EXPECT_EQ(absl::int128(-1), value | absl::int128(-1));\n    EXPECT_EQ(value, value & absl::int128(-1));\n    EXPECT_EQ(~value, value ^ absl::int128(-1));\n  }\n\n  // small sample of randomly generated int64_t's\n  std::pair<int64_t, int64_t> pairs64[]{\n      {0x7f86797f5e991af4, 0x1ee30494fb007c97},\n      {0x0b278282bacf01af, 0x58780e0a57a49e86},\n      {0x059f266ccb93a666, 0x3d5b731bae9286f5},\n      {0x63c0c4820f12108c, 0x58166713c12e1c3a},\n      {0x381488bb2ed2a66e, 0x2220a3eb76a3698c},\n      {0x2a0a0dfb81e06f21, 0x4b60585927f5523c},\n      {0x555b1c3a03698537, 0x25478cd19d8e53cb},\n      {0x4750f6f27d779225, 0x16397553c6ff05fc},\n  };\n  for (const std::pair<int64_t, int64_t>& pair : pairs64) {\n    SCOPED_TRACE(::testing::Message()\n                 << \"pair = {\" << pair.first << \", \" << pair.second << '}');\n\n    EXPECT_EQ(absl::MakeInt128(~pair.first, ~pair.second),\n              ~absl::MakeInt128(pair.first, pair.second));\n\n    EXPECT_EQ(absl::int128(pair.first & pair.second),\n              absl::int128(pair.first) & absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.first | pair.second),\n              absl::int128(pair.first) | absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.first ^ pair.second),\n              absl::int128(pair.first) ^ absl::int128(pair.second));\n\n    EXPECT_EQ(absl::int128(pair.first & pair.second),\n              absl::int128(pair.first) &= absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.first | pair.second),\n              absl::int128(pair.first) |= absl::int128(pair.second));\n    EXPECT_EQ(absl::int128(pair.first ^ pair.second),\n              absl::int128(pair.first) ^= absl::int128(pair.second));\n\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first & pair.second, 0),\n        absl::MakeInt128(pair.first, 0) & absl::MakeInt128(pair.second, 0));\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first | pair.second, 0),\n        absl::MakeInt128(pair.first, 0) | absl::MakeInt128(pair.second, 0));\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first ^ pair.second, 0),\n        absl::MakeInt128(pair.first, 0) ^ absl::MakeInt128(pair.second, 0));\n\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first & pair.second, 0),\n        absl::MakeInt128(pair.first, 0) &= absl::MakeInt128(pair.second, 0));\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first | pair.second, 0),\n        absl::MakeInt128(pair.first, 0) |= absl::MakeInt128(pair.second, 0));\n    EXPECT_EQ(\n        absl::MakeInt128(pair.first ^ pair.second, 0),\n        absl::MakeInt128(pair.first, 0) ^= absl::MakeInt128(pair.second, 0));\n  }\n}\n\nTEST(Int128, BitwiseShiftTest) {\n  for (int i = 0; i < 64; ++i) {\n    for (int j = 0; j <= i; ++j) {\n      // Left shift from j-th bit to i-th bit.\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) << (i - j));\n      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) <<= (i - j));\n    }\n  }\n  for (int i = 0; i < 63; ++i) {\n    for (int j = 0; j < 64; ++j) {\n      // Left shift from j-th bit to (i + 64)-th bit.\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),\n                absl::int128(uint64_t{1} << j) << (i + 64 - j));\n      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),\n                absl::int128(uint64_t{1} << j) <<= (i + 64 - j));\n    }\n    for (int j = 0; j <= i; ++j) {\n      // Left shift from (j + 64)-th bit to (i + 64)-th bit.\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),\n                absl::MakeInt128(uint64_t{1} << j, 0) << (i - j));\n      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),\n                absl::MakeInt128(uint64_t{1} << j, 0) <<= (i - j));\n    }\n  }\n\n  for (int i = 0; i < 64; ++i) {\n    for (int j = i; j < 64; ++j) {\n      // Right shift from j-th bit to i-th bit.\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >> (j - i));\n      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >>= (j - i));\n    }\n    for (int j = 0; j < 63; ++j) {\n      // Right shift from (j + 64)-th bit to i-th bit.\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      EXPECT_EQ(uint64_t{1} << i,\n                absl::MakeInt128(uint64_t{1} << j, 0) >> (j + 64 - i));\n      EXPECT_EQ(uint64_t{1} << i,\n                absl::MakeInt128(uint64_t{1} << j, 0) >>= (j + 64 - i));\n    }\n  }\n  for (int i = 0; i < 63; ++i) {\n    for (int j = i; j < 63; ++j) {\n      // Right shift from (j + 64)-th bit to (i + 64)-th bit.\n      SCOPED_TRACE(::testing::Message() << \"i = \" << i << \"; j = \" << j);\n      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),\n                absl::MakeInt128(uint64_t{1} << j, 0) >> (j - i));\n      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),\n                absl::MakeInt128(uint64_t{1} << j, 0) >>= (j - i));\n    }\n  }\n\n  // Signed integer overflow is undefined behavior, so in these cases enough\n  // high bits must be zero to avoid over-shifting.\n  EXPECT_EQ(MAKE_INT128(0x0, 0x123456789abcdef0) << 63,\n            MAKE_INT128(0x91a2b3c4d5e6f78, 0x0));\n  EXPECT_EQ(MAKE_INT128(0x0, 0x123456789abcdef0) << 64,\n            MAKE_INT128(0x123456789abcdef0, 0x0));\n  EXPECT_EQ(MAKE_INT128(0x1, 0xfedcba0987654321) << 63,\n            MAKE_INT128(0xff6e5d04c3b2a190, 0x8000000000000000));\n  EXPECT_EQ(MAKE_INT128(0x0, 0xfedcba0987654321) << 64,\n            MAKE_INT128(0xfedcba0987654321, 0x0));\n  EXPECT_EQ(MAKE_INT128(0x0, 0x0) << 126, MAKE_INT128(0x0, 0x0));\n  EXPECT_EQ(MAKE_INT128(0x0, 0x1) << 126, MAKE_INT128(0x4000000000000000, 0x0));\n\n  // Manually calculated cases with shift count for positive (val1) and negative\n  // (val2) values\n  absl::int128 val1 = MAKE_INT128(0x123456789abcdef0, 0x123456789abcdef0);\n  absl::int128 val2 = MAKE_INT128(0xfedcba0987654321, 0xfedcba0987654321);\n\n  EXPECT_EQ(val1 >> 63, MAKE_INT128(0x0, 0x2468acf13579bde0));\n  EXPECT_EQ(val1 >> 64, MAKE_INT128(0x0, 0x123456789abcdef0));\n  EXPECT_EQ(val2 >> 63, MAKE_INT128(0xffffffffffffffff, 0xfdb974130eca8643));\n  EXPECT_EQ(val2 >> 64, MAKE_INT128(0xffffffffffffffff, 0xfedcba0987654321));\n\n  EXPECT_EQ(val1 >> 126, MAKE_INT128(0x0, 0x0));\n  EXPECT_EQ(val2 >> 126, MAKE_INT128(0xffffffffffffffff, 0xffffffffffffffff));\n}\n\nTEST(Int128, NumericLimitsTest) {\n  static_assert(std::numeric_limits<absl::int128>::is_specialized, \"\");\n  static_assert(std::numeric_limits<absl::int128>::is_signed, \"\");\n  static_assert(std::numeric_limits<absl::int128>::is_integer, \"\");\n  EXPECT_EQ(static_cast<int>(127 * std::log10(2)),\n            std::numeric_limits<absl::int128>::digits10);\n  EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::min());\n  EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::lowest());\n  EXPECT_EQ(absl::Int128Max(), std::numeric_limits<absl::int128>::max());\n}\n\nTEST(Int128, BitCastable) {\n  // NOTE: This test is not intended to be an example that demonstrate usages of\n  // `static_cast` and `std::bit_cast`, rather it is here simply to verify\n  // behavior. When deciding whether you should use `static_cast` or\n  // `std::bit_cast` when converting between `absl::int128` and `absl::uint128`,\n  // use your best judgement. As a rule of thumb, use the same cast that you\n  // would use when converting between the signed and unsigned counterparts of a\n  // builtin integral type.\n\n  // Verify bit casting between signed and unsigned works with regards to two's\n  // complement. This verifies we exhibit the same behavior as a theoretical\n  // builtin int128_t and uint128_t in C++20 onwards.\n  EXPECT_EQ(absl::bit_cast<absl::uint128>(absl::int128(-1)),\n            std::numeric_limits<absl::uint128>::max());\n  EXPECT_EQ(\n      absl::bit_cast<absl::int128>(std::numeric_limits<absl::uint128>::max()),\n      absl::int128(-1));\n  EXPECT_EQ(\n      absl::bit_cast<absl::uint128>(std::numeric_limits<absl::int128>::min()),\n      absl::uint128(1) << 127);\n  EXPECT_EQ(absl::bit_cast<absl::int128>(absl::uint128(1) << 127),\n            std::numeric_limits<absl::int128>::min());\n  EXPECT_EQ(\n      absl::bit_cast<absl::uint128>(std::numeric_limits<absl::int128>::max()),\n      (absl::uint128(1) << 127) - 1);\n  EXPECT_EQ(absl::bit_cast<absl::int128>((absl::uint128(1) << 127) - 1),\n            std::numeric_limits<absl::int128>::max());\n\n  // Also verify static casting has the same behavior as bit casting.\n  EXPECT_EQ(static_cast<absl::uint128>(absl::int128(-1)),\n            std::numeric_limits<absl::uint128>::max());\n  EXPECT_EQ(\n      static_cast<absl::int128>(std::numeric_limits<absl::uint128>::max()),\n      absl::int128(-1));\n  EXPECT_EQ(\n      static_cast<absl::uint128>(std::numeric_limits<absl::int128>::min()),\n      absl::uint128(1) << 127);\n  EXPECT_EQ(static_cast<absl::int128>(absl::uint128(1) << 127),\n            std::numeric_limits<absl::int128>::min());\n  EXPECT_EQ(\n      static_cast<absl::uint128>(std::numeric_limits<absl::int128>::max()),\n      (absl::uint128(1) << 127) - 1);\n  EXPECT_EQ(static_cast<absl::int128>((absl::uint128(1) << 127) - 1),\n            std::numeric_limits<absl::int128>::max());\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/numeric/internal/bits.h",
    "content": "// Copyright 2020 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_\n#define ABSL_NUMERIC_INTERNAL_BITS_H_\n\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n\n// Clang on Windows has __builtin_clzll; otherwise we need to use the\n// windows intrinsic functions.\n#if defined(_MSC_VER) && !defined(__clang__)\n#include <intrin.h>\n#endif\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n\n#if defined(__GNUC__) && !defined(__clang__)\n// GCC\n#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1\n#else\n#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x)\n#endif\n\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \\\n    ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)\n#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr\n#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1\n#else\n#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT\n#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0\n#endif\n\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \\\n    ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)\n#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr\n#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1\n#else\n#define ABSL_INTERNAL_CONSTEXPR_CLZ\n#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0\n#endif\n\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \\\n    ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)\n#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr\n#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1\n#else\n#define ABSL_INTERNAL_CONSTEXPR_CTZ\n#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace numeric_internal {\n\nconstexpr bool IsPowerOf2(unsigned int x) noexcept {\n  return x != 0 && (x & (x - 1)) == 0;\n}\n\ntemplate <class T>\n[[nodiscard]] ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(\n    T x, int s) noexcept {\n  static_assert(std::is_unsigned<T>::value, \"T must be unsigned\");\n  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),\n                \"T must have a power-of-2 size\");\n\n  // Rotate by s mod the number of digits to avoid unnecessary rotations.\n  //\n  // A negative s represents a left rotation instead of a right rotation.\n  // We compute it as an equivalent complementary right rotation by leveraging\n  // its two's complement representation.\n  //\n  // For example, suppose we rotate a 3-bit number by -2.\n  // In that case:\n  //   * s = 0b11111111111111111111111111111110\n  //   * n = 8\n  //   * r = (0b11111111111111111111111111111110 & 0b111) = 0b110\n  //\n  // Instead of rotating by 2 to the left, we rotate by 6 to the right, which\n  // is equivalent.\n  const int n = std::numeric_limits<T>::digits;\n  const int r = s & (n - 1);\n\n  if (r == 0) {\n    return x;\n  } else {\n    return (x >> r) | (x << (n - r));\n  }\n}\n\ntemplate <class T>\n[[nodiscard]] ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(\n    T x, int s) noexcept {\n  static_assert(std::is_unsigned<T>::value, \"T must be unsigned\");\n  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),\n                \"T must have a power-of-2 size\");\n\n  // Rotate by s mod the number of digits to avoid unnecessary rotations.\n  // See comment in RotateRight for a detailed explanation of the logic below.\n  const int n = std::numeric_limits<T>::digits;\n  const int r = s & (n - 1);\n\n  if (r == 0) {\n    return x;\n  } else {\n    return (x << r) | (x >> (n - r));\n  }\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int\nPopcount32(uint32_t x) noexcept {\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount)\n  static_assert(sizeof(unsigned int) == sizeof(x),\n                \"__builtin_popcount does not take 32-bit arg\");\n  return __builtin_popcount(x);\n#else\n  x -= ((x >> 1) & 0x55555555);\n  x = ((x >> 2) & 0x33333333) + (x & 0x33333333);\n  return static_cast<int>((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);\n#endif\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int\nPopcount64(uint64_t x) noexcept {\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)\n  static_assert(sizeof(unsigned long long) == sizeof(x),  // NOLINT(runtime/int)\n                \"__builtin_popcount does not take 64-bit arg\");\n  return __builtin_popcountll(x);\n#else\n  x -= (x >> 1) & 0x5555555555555555ULL;\n  x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL);\n  return static_cast<int>(\n      (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);\n#endif\n}\n\ntemplate <class T>\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int\nPopcount(T x) noexcept {\n  static_assert(std::is_unsigned<T>::value, \"T must be unsigned\");\n  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),\n                \"T must have a power-of-2 size\");\n  static_assert(sizeof(x) <= sizeof(uint64_t), \"T is too large\");\n  if constexpr (sizeof(x) <= sizeof(uint32_t)) {\n    return Popcount32(x);\n  } else {\n    return Popcount64(x);\n  }\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int\nCountLeadingZeroes32(uint32_t x) {\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz)\n  // Use __builtin_clz, which uses the following instructions:\n  //  x86: bsr, lzcnt\n  //  ARM64: clz\n  //  PPC: cntlzd\n\n  static_assert(sizeof(unsigned int) == sizeof(x),\n                \"__builtin_clz does not take 32-bit arg\");\n  // Handle 0 as a special case because __builtin_clz(0) is undefined.\n  return x == 0 ? 32 : __builtin_clz(x);\n#elif defined(_MSC_VER) && !defined(__clang__)\n  unsigned long result = 0;  // NOLINT(runtime/int)\n  if (_BitScanReverse(&result, x)) {\n    return 31 - result;\n  }\n  return 32;\n#else\n  int zeroes = 28;\n  if (x >> 16) {\n    zeroes -= 16;\n    x >>= 16;\n  }\n  if (x >> 8) {\n    zeroes -= 8;\n    x >>= 8;\n  }\n  if (x >> 4) {\n    zeroes -= 4;\n    x >>= 4;\n  }\n  return \"\\4\\3\\2\\2\\1\\1\\1\\1\\0\\0\\0\\0\\0\\0\\0\"[x] + zeroes;\n#endif\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int\nCountLeadingZeroes16(uint16_t x) {\n#if ABSL_HAVE_BUILTIN(__builtin_clzg)\n  return x == 0 ? 16 : __builtin_clzg(x);\n#elif ABSL_HAVE_BUILTIN(__builtin_clzs)\n  static_assert(sizeof(unsigned short) == sizeof(x),  // NOLINT(runtime/int)\n                \"__builtin_clzs does not take 16-bit arg\");\n  return x == 0 ? 16 : __builtin_clzs(x);\n#else\n  return CountLeadingZeroes32(x) - 16;\n#endif\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int\nCountLeadingZeroes64(uint64_t x) {\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)\n  // Use __builtin_clzll, which uses the following instructions:\n  //  x86: bsr, lzcnt\n  //  ARM64: clz\n  //  PPC: cntlzd\n  static_assert(sizeof(unsigned long long) == sizeof(x),  // NOLINT(runtime/int)\n                \"__builtin_clzll does not take 64-bit arg\");\n\n  // Handle 0 as a special case because __builtin_clzll(0) is undefined.\n  return x == 0 ? 64 : __builtin_clzll(x);\n#elif defined(_MSC_VER) && !defined(__clang__) && \\\n    (defined(_M_X64) || defined(_M_ARM64))\n  // MSVC does not have __buitin_clzll. Use _BitScanReverse64.\n  unsigned long result = 0;  // NOLINT(runtime/int)\n  if (_BitScanReverse64(&result, x)) {\n    return 63 - result;\n  }\n  return 64;\n#elif defined(_MSC_VER) && !defined(__clang__)\n  // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse\n  unsigned long result = 0;  // NOLINT(runtime/int)\n  if ((x >> 32) &&\n      _BitScanReverse(&result, static_cast<unsigned long>(x >> 32))) {\n    return 31 - result;\n  }\n  if (_BitScanReverse(&result, static_cast<unsigned long>(x))) {\n    return 63 - result;\n  }\n  return 64;\n#else\n  int zeroes = 60;\n  if (x >> 32) {\n    zeroes -= 32;\n    x >>= 32;\n  }\n  if (x >> 16) {\n    zeroes -= 16;\n    x >>= 16;\n  }\n  if (x >> 8) {\n    zeroes -= 8;\n    x >>= 8;\n  }\n  if (x >> 4) {\n    zeroes -= 4;\n    x >>= 4;\n  }\n  return \"\\4\\3\\2\\2\\1\\1\\1\\1\\0\\0\\0\\0\\0\\0\\0\"[x] + zeroes;\n#endif\n}\n\ntemplate <typename T>\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int\nCountLeadingZeroes(T x) {\n  static_assert(std::is_unsigned<T>::value, \"T must be unsigned\");\n  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),\n                \"T must have a power-of-2 size\");\n  static_assert(sizeof(T) <= sizeof(uint64_t), \"T too large\");\n  return sizeof(T) <= sizeof(uint16_t)\n             ? CountLeadingZeroes16(static_cast<uint16_t>(x)) -\n                   (std::numeric_limits<uint16_t>::digits -\n                    std::numeric_limits<T>::digits)\n             : (sizeof(T) <= sizeof(uint32_t)\n                    ? CountLeadingZeroes32(static_cast<uint32_t>(x)) -\n                          (std::numeric_limits<uint32_t>::digits -\n                           std::numeric_limits<T>::digits)\n                    : CountLeadingZeroes64(x));\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int\nCountTrailingZeroesNonzero32(uint32_t x) {\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz)\n  static_assert(sizeof(unsigned int) == sizeof(x),\n                \"__builtin_ctz does not take 32-bit arg\");\n  return __builtin_ctz(x);\n#elif defined(_MSC_VER) && !defined(__clang__)\n  unsigned long result = 0;  // NOLINT(runtime/int)\n  _BitScanForward(&result, x);\n  return result;\n#else\n  int c = 31;\n  x &= ~x + 1;\n  if (x & 0x0000FFFF) c -= 16;\n  if (x & 0x00FF00FF) c -= 8;\n  if (x & 0x0F0F0F0F) c -= 4;\n  if (x & 0x33333333) c -= 2;\n  if (x & 0x55555555) c -= 1;\n  return c;\n#endif\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int\nCountTrailingZeroesNonzero64(uint64_t x) {\n#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)\n  static_assert(sizeof(unsigned long long) == sizeof(x),  // NOLINT(runtime/int)\n                \"__builtin_ctzll does not take 64-bit arg\");\n  return __builtin_ctzll(x);\n#elif defined(_MSC_VER) && !defined(__clang__) && \\\n    (defined(_M_X64) || defined(_M_ARM64))\n  unsigned long result = 0;  // NOLINT(runtime/int)\n  _BitScanForward64(&result, x);\n  return result;\n#elif defined(_MSC_VER) && !defined(__clang__)\n  unsigned long result = 0;  // NOLINT(runtime/int)\n  if (static_cast<uint32_t>(x) == 0) {\n    _BitScanForward(&result, static_cast<unsigned long>(x >> 32));\n    return result + 32;\n  }\n  _BitScanForward(&result, static_cast<unsigned long>(x));\n  return result;\n#else\n  int c = 63;\n  x &= ~x + 1;\n  if (x & 0x00000000FFFFFFFF) c -= 32;\n  if (x & 0x0000FFFF0000FFFF) c -= 16;\n  if (x & 0x00FF00FF00FF00FF) c -= 8;\n  if (x & 0x0F0F0F0F0F0F0F0F) c -= 4;\n  if (x & 0x3333333333333333) c -= 2;\n  if (x & 0x5555555555555555) c -= 1;\n  return c;\n#endif\n}\n\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int\nCountTrailingZeroesNonzero16(uint16_t x) {\n#if ABSL_HAVE_BUILTIN(__builtin_ctzg)\n  return __builtin_ctzg(x);\n#elif ABSL_HAVE_BUILTIN(__builtin_ctzs)\n  static_assert(sizeof(unsigned short) == sizeof(x),  // NOLINT(runtime/int)\n                \"__builtin_ctzs does not take 16-bit arg\");\n  return __builtin_ctzs(x);\n#else\n  return CountTrailingZeroesNonzero32(x);\n#endif\n}\n\ntemplate <class T>\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int\nCountTrailingZeroes(T x) noexcept {\n  static_assert(std::is_unsigned<T>::value, \"T must be unsigned\");\n  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),\n                \"T must have a power-of-2 size\");\n  static_assert(sizeof(T) <= sizeof(uint64_t), \"T too large\");\n  return x == 0 ? std::numeric_limits<T>::digits\n                : (sizeof(T) <= sizeof(uint16_t)\n                       ? CountTrailingZeroesNonzero16(static_cast<uint16_t>(x))\n                       : (sizeof(T) <= sizeof(uint32_t)\n                              ? CountTrailingZeroesNonzero32(\n                                    static_cast<uint32_t>(x))\n                              : CountTrailingZeroesNonzero64(x)));\n}\n\n// If T is narrower than unsigned, T{1} << bit_width will be promoted.  We\n// want to force it to wraparound so that bit_ceil of an invalid value are not\n// core constant expressions.\ntemplate <class T>\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, T>::type\n    BitCeilPromotionHelper(T x, T promotion) {\n  return (T{1} << (x + promotion)) >> promotion;\n}\n\ntemplate <class T>\nABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline\n    typename std::enable_if<std::is_unsigned<T>::value, T>::type\n    BitCeilNonPowerOf2(T x) {\n  // If T is narrower than unsigned, it undergoes promotion to unsigned when we\n  // shift.  We calculate the number of bits added by the wider type.\n  return BitCeilPromotionHelper(\n      static_cast<T>(std::numeric_limits<T>::digits - CountLeadingZeroes(x)),\n      T{sizeof(T) >= sizeof(unsigned) ? 0\n                                      : std::numeric_limits<unsigned>::digits -\n                                            std::numeric_limits<T>::digits});\n}\n\n}  // namespace numeric_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_NUMERIC_INTERNAL_BITS_H_\n"
  },
  {
    "path": "absl/numeric/internal/representation.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_\n#define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_\n\n#include <limits>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace numeric_internal {\n\n// Returns true iff long double is represented as a pair of doubles added\n// together.\ninline constexpr bool IsDoubleDouble() {\n  // A double-double value always has exactly twice the precision of a double\n  // value--one double carries the high digits and one double carries the low\n  // digits. This property is not shared with any other common floating-point\n  // representation, so this test won't trigger false positives. For reference,\n  // this table gives the number of bits of precision of each common\n  // floating-point representation:\n  //\n  //                type     precision\n  //         IEEE single          24 b\n  //         IEEE double          53\n  //     x86 long double          64\n  //       double-double         106\n  //      IEEE quadruple         113\n  //\n  // Note in particular that a quadruple-precision float has greater precision\n  // than a double-double float despite taking up the same amount of memory; the\n  // quad has more of its bits allocated to the mantissa than the double-double\n  // has.\n  return std::numeric_limits<long double>::digits ==\n         2 * std::numeric_limits<double>::digits;\n}\n\n}  // namespace numeric_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_\n"
  },
  {
    "path": "absl/profiling/BUILD.bazel",
    "content": "# Copyright 2021 The Abseil Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:private\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"sample_recorder\",\n    hdrs = [\"internal/sample_recorder.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/synchronization\",\n        \"//absl/time\",\n    ],\n)\n\ncc_test(\n    name = \"sample_recorder_test\",\n    srcs = [\"internal/sample_recorder_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":sample_recorder\",\n        \"//absl/base:core_headers\",\n        \"//absl/random\",\n        \"//absl/synchronization\",\n        \"//absl/synchronization:thread_pool\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"exponential_biased\",\n    srcs = [\"internal/exponential_biased.cc\"],\n    hdrs = [\"internal/exponential_biased.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"exponential_biased_test\",\n    size = \"small\",\n    srcs = [\"internal/exponential_biased_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":exponential_biased\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"periodic_sampler\",\n    srcs = [\"internal/periodic_sampler.cc\"],\n    hdrs = [\"internal/periodic_sampler.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":exponential_biased\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"periodic_sampler_test\",\n    size = \"small\",\n    srcs = [\"internal/periodic_sampler_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":periodic_sampler\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"periodic_sampler_benchmark\",\n    testonly = True,\n    srcs = [\"internal/periodic_sampler_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":periodic_sampler\",\n        \"//absl/base:core_headers\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"profile_builder\",\n    srcs = [\"internal/profile_builder.cc\"],\n    hdrs = [\"internal/profile_builder.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/container:btree\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"hashtable\",\n    srcs = [\"hashtable.cc\"],\n    hdrs = [\"hashtable.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":profile_builder\",\n        \"//absl/base:config\",\n        \"//absl/container:hashtablez_sampler\",\n        \"//absl/status:statusor\",\n        \"//absl/strings\",\n        \"//absl/strings:string_view\",\n        \"//absl/time\",\n        \"//absl/types:span\",\n    ],\n)\n"
  },
  {
    "path": "absl/profiling/CMakeLists.txt",
    "content": "# Copyright 2021 The Abseil Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nabsl_cc_library(\n  NAME\n    sample_recorder\n  HDRS\n    \"internal/sample_recorder.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::synchronization\n)\n\nabsl_cc_test(\n  NAME\n    sample_recorder_test\n  SRCS\n    \"internal/sample_recorder_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::random_random\n    absl::sample_recorder\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    exponential_biased\n  SRCS\n    \"internal/exponential_biased.cc\"\n  HDRS\n    \"internal/exponential_biased.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n)\n\nabsl_cc_test(\n  NAME\n    exponential_biased_test\n  SRCS\n    \"internal/exponential_biased_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::exponential_biased\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    periodic_sampler\n  SRCS\n    \"internal/periodic_sampler.cc\"\n  HDRS\n    \"internal/periodic_sampler.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::core_headers\n    absl::exponential_biased\n)\n\nabsl_cc_test(\n  NAME\n    periodic_sampler_test\n  SRCS\n    \"internal/periodic_sampler_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::core_headers\n    absl::periodic_sampler\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly\nabsl_cc_library(\n  NAME\n    profile_builder\n  HDRS\n    \"internal/profile_builder.h\"\n  SRCS\n    \"internal/profile_builder.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::flat_hash_map\n    absl::btree\n    absl::strings\n    absl::str_format\n    absl::span\n)\n\nabsl_cc_library(\n  NAME\n    hashtable_profiler\n  HDRS\n    \"hashtable.h\"\n  SRCS\n    \"hashtable.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::profile_builder\n    absl::config\n    absl::core_headers\n    absl::strings\n    absl::span\n    absl::hashtablez_sampler\n)\n"
  },
  {
    "path": "absl/profiling/hashtable.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may\n// obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/hashtable.h\"\n\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/internal/hashtablez_sampler.h\"\n#include \"absl/profiling/internal/profile_builder.h\"\n#include \"absl/status/statusor.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nStatusOr<std::string> MarshalHashtableProfile() {\n  return debugging_internal::MarshalHashtableProfile(\n      container_internal::GlobalHashtablezSampler(), Now());\n}\n\nnamespace debugging_internal {\n\nstatic void DroppedHashtableSample() {}\n\nStatusOr<std::string> MarshalHashtableProfile(\n    container_internal::HashtablezSampler& sampler, Time now) {\n  static constexpr absl::string_view kDropFrames =\n      \"(::)?absl::container_internal::.*|\"\n      \"(::)?absl::(flat|node)_hash_(map|set).*\";\n\n  ProfileBuilder builder;\n  StringId drop_frames_id = builder.InternString(kDropFrames);\n  builder.set_drop_frames_id(drop_frames_id);\n  builder.AddSampleType(builder.InternString(\"capacity\"),\n                        builder.InternString(\"count\"));\n  builder.set_default_sample_type_id(builder.InternString(\"capacity\"));\n\n  const auto capacity_id = builder.InternString(\"capacity\");\n  const auto size_id = builder.InternString(\"size\");\n  const auto num_erases_id = builder.InternString(\"num_erases\");\n  const auto num_rehashes_id = builder.InternString(\"num_rehashes\");\n  const auto max_probe_length_id = builder.InternString(\"max_probe_length\");\n  const auto total_probe_length_id = builder.InternString(\"total_probe_length\");\n  const auto stuck_bits_id = builder.InternString(\"stuck_bits\");\n  const auto inline_element_size_id =\n      builder.InternString(\"inline_element_size\");\n  const auto key_size_id = builder.InternString(\"key_size\");\n  const auto value_size_id = builder.InternString(\"value_size\");\n  const auto soo_capacity_id = builder.InternString(\"soo_capacity\");\n  const auto table_age_id = builder.InternString(\"table_age\");\n  const auto max_reserve_id = builder.InternString(\"max_reserve\");\n\n  size_t dropped =\n      sampler.Iterate([&](const container_internal::HashtablezInfo& info) {\n        const size_t capacity = info.capacity.load(std::memory_order_relaxed);\n        std::vector<std::pair<StringId, int64_t>> labels;\n\n        auto add_label = [&](StringId tag, uint64_t value) {\n          if (value == 0) {\n            return;\n          }\n          labels.emplace_back(tag, static_cast<int64_t>(value));\n        };\n\n        add_label(capacity_id, capacity);\n        add_label(size_id, info.size.load(std::memory_order_relaxed));\n        add_label(num_erases_id,\n                  info.num_erases.load(std::memory_order_relaxed));\n        add_label(num_rehashes_id,\n                  info.num_rehashes.load(std::memory_order_relaxed));\n        add_label(max_probe_length_id,\n                  info.max_probe_length.load(std::memory_order_relaxed));\n        add_label(total_probe_length_id,\n                  info.total_probe_length.load(std::memory_order_relaxed));\n        add_label(stuck_bits_id,\n                  (info.hashes_bitwise_and.load(std::memory_order_relaxed) |\n                   ~info.hashes_bitwise_or.load(std::memory_order_relaxed)));\n        add_label(inline_element_size_id, info.inline_element_size);\n        add_label(key_size_id, info.key_size);\n        add_label(value_size_id, info.value_size);\n        add_label(soo_capacity_id, info.soo_capacity);\n        add_label(\n            table_age_id,\n            static_cast<uint64_t>(ToInt64Microseconds(now - info.create_time)));\n        add_label(max_reserve_id,\n                  info.max_reserve.load(std::memory_order_relaxed));\n        builder.AddSample(static_cast<int64_t>(capacity) * info.weight,\n                          MakeSpan(info.stack, info.depth), labels);\n      });\n\n  if (dropped > 0) {\n    // If we dropped samples, we don't have information for them, including\n    // their sizes.  The non-zero weight allows it to be noticed in the profile\n    // and examined more closely.\n    //\n    // We compensate for the fixup done by AddSample by adjusting the address\n    // here.\n    const void* kFakeStack[] = {\n      absl::bit_cast<void*>(\n          reinterpret_cast<uintptr_t>(&DroppedHashtableSample)+1)};\n    builder.AddSample(static_cast<int64_t>(dropped), kFakeStack, {});\n  }\n  builder.AddCurrentMappings();\n  return std::move(builder).Emit();\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/hashtable.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_PROFILING_HASHTABLE_H_\n#define ABSL_PROFILING_HASHTABLE_H_\n\n#include <cstdint>\n#include <string>\n\n#include \"absl/container/internal/hashtablez_sampler.h\"\n#include \"absl/status/statusor.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nabsl::StatusOr<std::string> MarshalHashtableProfile();\n\nnamespace debugging_internal {\n\nabsl::StatusOr<std::string> MarshalHashtableProfile(\n    container_internal::HashtablezSampler& sampler, absl::Time now);\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_PROFILING_HASHTABLE_H_\n"
  },
  {
    "path": "absl/profiling/internal/exponential_biased.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/exponential_biased.h\"\n\n#include <stdint.h>\n\n#include <algorithm>\n#include <atomic>\n#include <cmath>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/optimization.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\n\n// The algorithm generates a random number between 0 and 1 and applies the\n// inverse cumulative distribution function for an exponential. Specifically:\n// Let m be the inverse of the sample period, then the probability\n// distribution function is m*exp(-mx) so the CDF is\n// p = 1 - exp(-mx), so\n// q = 1 - p = exp(-mx)\n// log_e(q) = -mx\n// -log_e(q)/m = x\n// log_2(q) * (-log_e(2) * 1/m) = x\n// In the code, q is actually in the range 1 to 2**26, hence the -26 below\nint64_t ExponentialBiased::GetSkipCount(int64_t mean) {\n  if (ABSL_PREDICT_FALSE(!initialized_)) {\n    Initialize();\n  }\n\n  uint64_t rng = NextRandom(rng_);\n  rng_ = rng;\n\n  // Take the top 26 bits as the random number\n  // (This plus the 1<<58 sampling bound give a max possible step of\n  // 5194297183973780480 bytes.)\n  // The uint32_t cast is to prevent a (hard-to-reproduce) NAN\n  // under piii debug for some binaries.\n  double q = static_cast<uint32_t>(rng >> (kPrngNumBits - 26)) + 1.0;\n  // Put the computed p-value through the CDF of a geometric.\n  double interval = bias_ + (std::log2(q) - 26) * (-std::log(2.0) * mean);\n  // Very large values of interval overflow int64_t. To avoid that, we will\n  // cheat and clamp any huge values to (int64_t max)/2. This is a potential\n  // source of bias, but the mean would need to be such a large value that it's\n  // not likely to come up. For example, with a mean of 1e18, the probability of\n  // hitting this condition is about 1/1000. For a mean of 1e17, standard\n  // calculators claim that this event won't happen.\n  if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {\n    // Assume huge values are bias neutral, retain bias for next call.\n    return std::numeric_limits<int64_t>::max() / 2;\n  }\n  double value = std::rint(interval);\n  bias_ = interval - value;\n  return static_cast<int64_t>(value);\n}\n\nint64_t ExponentialBiased::GetStride(int64_t mean) {\n  return GetSkipCount(mean - 1) + 1;\n}\n\nvoid ExponentialBiased::Initialize() {\n  // We don't get well distributed numbers from `this` so we call NextRandom() a\n  // bunch to mush the bits around. We use a global_rand to handle the case\n  // where the same thread (by memory address) gets created and destroyed\n  // repeatedly.\n  ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);\n  uint64_t r = reinterpret_cast<uint64_t>(this) +\n               global_rand.fetch_add(1, std::memory_order_relaxed);\n  for (int i = 0; i < 20; ++i) {\n    r = NextRandom(r);\n  }\n  rng_ = r;\n  initialized_ = true;\n}\n\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/internal/exponential_biased.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_PROFILING_INTERNAL_EXPONENTIAL_BIASED_H_\n#define ABSL_PROFILING_INTERNAL_EXPONENTIAL_BIASED_H_\n\n#include <stdint.h>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\n\n// ExponentialBiased provides a small and fast random number generator for a\n// rounded exponential distribution. This generator manages very little state,\n// and imposes no synchronization overhead. This makes it useful in specialized\n// scenarios requiring minimum overhead, such as stride based periodic sampling.\n//\n// ExponentialBiased provides two closely related functions, GetSkipCount() and\n// GetStride(), both returning a rounded integer defining a number of events\n// required before some event with a given mean probability occurs.\n//\n// The distribution is useful to generate a random wait time or some periodic\n// event with a given mean probability. For example, if an action is supposed to\n// happen on average once every 'N' events, then we can get a random 'stride'\n// counting down how long before the event to happen. For example, if we'd want\n// to sample one in every 1000 'Frobber' calls, our code could look like this:\n//\n//   Frobber::Frobber() {\n//     stride_ = exponential_biased_.GetStride(1000);\n//   }\n//\n//   void Frobber::Frob(int arg) {\n//     if (--stride == 0) {\n//       SampleFrob(arg);\n//       stride_ = exponential_biased_.GetStride(1000);\n//     }\n//     ...\n//   }\n//\n// The rounding of the return value creates a bias, especially for smaller means\n// where the distribution of the fraction is not evenly distributed. We correct\n// this bias by tracking the fraction we rounded up or down on each iteration,\n// effectively tracking the distance between the cumulative value, and the\n// rounded cumulative value. For example, given a mean of 2:\n//\n//   raw = 1.63076, cumulative = 1.63076, rounded = 2, bias = -0.36923\n//   raw = 0.14624, cumulative = 1.77701, rounded = 2, bias =  0.14624\n//   raw = 4.93194, cumulative = 6.70895, rounded = 7, bias = -0.06805\n//   raw = 0.24206, cumulative = 6.95101, rounded = 7, bias =  0.24206\n//   etc...\n//\n// Adjusting with rounding bias is relatively trivial:\n//\n//    double value = bias_ + exponential_distribution(mean)();\n//    double rounded_value = std::rint(value);\n//    bias_ = value - rounded_value;\n//    return rounded_value;\n//\n// This class is thread-compatible.\nclass ExponentialBiased {\n public:\n  // The number of bits set by NextRandom.\n  static constexpr int kPrngNumBits = 48;\n\n  // `GetSkipCount()` returns the number of events to skip before some chosen\n  // event happens. For example, randomly tossing a coin, we will on average\n  // throw heads once before we get tails. We can simulate random coin tosses\n  // using GetSkipCount() as:\n  //\n  //   ExponentialBiased eb;\n  //   for (...) {\n  //     int number_of_heads_before_tail = eb.GetSkipCount(1);\n  //     for (int flips = 0; flips < number_of_heads_before_tail; ++flips) {\n  //       printf(\"head...\");\n  //     }\n  //     printf(\"tail\\n\");\n  //   }\n  //\n  int64_t GetSkipCount(int64_t mean);\n\n  // GetStride() returns the number of events required for a specific event to\n  // happen. See the class comments for a usage example. `GetStride()` is\n  // equivalent to `GetSkipCount(mean - 1) + 1`. When to use `GetStride()` or\n  // `GetSkipCount()` depends mostly on what best fits the use case.\n  int64_t GetStride(int64_t mean);\n\n  // Computes a random number in the range [0, 1<<(kPrngNumBits+1) - 1]\n  //\n  // This is public to enable testing.\n  static uint64_t NextRandom(uint64_t rnd);\n\n private:\n  void Initialize();\n\n  uint64_t rng_{0};\n  double bias_{0};\n  bool initialized_{false};\n};\n\n// Returns the next prng value.\n// pRNG is: aX+b mod c with a = 0x5DEECE66D, b =  0xB, c = 1<<48\n// This is the lrand64 generator.\ninline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) {\n  const uint64_t prng_mult = uint64_t{0x5DEECE66D};\n  const uint64_t prng_add = 0xB;\n  const uint64_t prng_mod_power = 48;\n  const uint64_t prng_mod_mask =\n      ~((~static_cast<uint64_t>(0)) << prng_mod_power);\n  return (prng_mult * rnd + prng_add) & prng_mod_mask;\n}\n\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_PROFILING_INTERNAL_EXPONENTIAL_BIASED_H_\n"
  },
  {
    "path": "absl/profiling/internal/exponential_biased_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/exponential_biased.h\"\n\n#include <stddef.h>\n\n#include <cmath>\n#include <cstdint>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_cat.h\"\n\nusing ::testing::Ge;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\nnamespace {\n\nMATCHER_P2(IsBetween, a, b,\n           absl::StrCat(std::string(negation ? \"isn't\" : \"is\"), \" between \", a,\n                        \" and \", b)) {\n  return a <= arg && arg <= b;\n}\n\n// Tests of the quality of the random numbers generated\n// This uses the Anderson Darling test for uniformity.\n// See \"Evaluating the Anderson-Darling Distribution\" by Marsaglia\n// for details.\n\n// Short cut version of ADinf(z), z>0 (from Marsaglia)\n// This returns the p-value for Anderson Darling statistic in\n// the limit as n-> infinity. For finite n, apply the error fix below.\ndouble AndersonDarlingInf(double z) {\n  if (z < 2) {\n    return exp(-1.2337141 / z) / sqrt(z) *\n           (2.00012 +\n            (0.247105 -\n             (0.0649821 - (0.0347962 - (0.011672 - 0.00168691 * z) * z) * z) *\n                 z) *\n                z);\n  }\n  return exp(\n      -exp(1.0776 -\n           (2.30695 -\n            (0.43424 - (0.082433 - (0.008056 - 0.0003146 * z) * z) * z) * z) *\n               z));\n}\n\n// Corrects the approximation error in AndersonDarlingInf for small values of n\n// Add this to AndersonDarlingInf to get a better approximation\n// (from Marsaglia)\ndouble AndersonDarlingErrFix(int n, double x) {\n  if (x > 0.8) {\n    return (-130.2137 +\n            (745.2337 -\n             (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) *\n                x) /\n           n;\n  }\n  double cutoff = 0.01265 + 0.1757 / n;\n  if (x < cutoff) {\n    double t = x / cutoff;\n    t = sqrt(t) * (1 - t) * (49 * t - 102);\n    return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n;\n  } else {\n    double t = (x - cutoff) / (0.8 - cutoff);\n    t = -0.00022633 +\n        (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * t) * t) * t) * t) *\n            t;\n    return t * (0.04213 + 0.01365 / n) / n;\n  }\n}\n\n// Returns the AndersonDarling p-value given n and the value of the statistic\ndouble AndersonDarlingPValue(int n, double z) {\n  double ad = AndersonDarlingInf(z);\n  double errfix = AndersonDarlingErrFix(n, ad);\n  return ad + errfix;\n}\n\ndouble AndersonDarlingStatistic(const std::vector<double>& random_sample) {\n  size_t n = random_sample.size();\n  double ad_sum = 0;\n  for (size_t i = 0; i < n; i++) {\n    ad_sum += (2 * i + 1) *\n              std::log(random_sample[i] * (1 - random_sample[n - 1 - i]));\n  }\n  const auto n_as_double = static_cast<double>(n);\n  double ad_statistic = -n_as_double - 1 / n_as_double * ad_sum;\n  return ad_statistic;\n}\n\n// Tests if the array of doubles is uniformly distributed.\n// Returns the p-value of the Anderson Darling Statistic\n// for the given set of sorted random doubles\n// See \"Evaluating the Anderson-Darling Distribution\" by\n// Marsaglia and Marsaglia for details.\ndouble AndersonDarlingTest(const std::vector<double>& random_sample) {\n  double ad_statistic = AndersonDarlingStatistic(random_sample);\n  double p = AndersonDarlingPValue(static_cast<int>(random_sample.size()),\n                                   ad_statistic);\n  return p;\n}\n\nTEST(ExponentialBiasedTest, CoinTossDemoWithGetSkipCount) {\n  ExponentialBiased eb;\n  for (int runs = 0; runs < 10; ++runs) {\n    for (int64_t flips = eb.GetSkipCount(1); flips > 0; --flips) {\n      printf(\"head...\");\n    }\n    printf(\"tail\\n\");\n  }\n  int heads = 0;\n  for (int i = 0; i < 10000000; i += 1 + eb.GetSkipCount(1)) {\n    ++heads;\n  }\n  printf(\"Heads = %d (%f%%)\\n\", heads, 100.0 * heads / 10000000);\n}\n\nTEST(ExponentialBiasedTest, SampleDemoWithStride) {\n  ExponentialBiased eb;\n  int64_t stride = eb.GetStride(10);\n  int samples = 0;\n  for (int i = 0; i < 10000000; ++i) {\n    if (--stride == 0) {\n      ++samples;\n      stride = eb.GetStride(10);\n    }\n  }\n  printf(\"Samples = %d (%f%%)\\n\", samples, 100.0 * samples / 10000000);\n}\n\n\n// Testing that NextRandom generates uniform random numbers. Applies the\n// Anderson-Darling test for uniformity\nTEST(ExponentialBiasedTest, TestNextRandom) {\n  for (auto n : std::vector<size_t>({\n           10,  // Check short-range correlation\n           100, 1000,\n           10000  // Make sure there's no systemic error\n       })) {\n    uint64_t x = 1;\n    // This assumes that the prng returns 48 bit numbers\n    uint64_t max_prng_value = static_cast<uint64_t>(1) << 48;\n    // Initialize.\n    for (int i = 1; i <= 20; i++) {\n      x = ExponentialBiased::NextRandom(x);\n    }\n    std::vector<uint64_t> int_random_sample(n);\n    // Collect samples\n    for (size_t i = 0; i < n; i++) {\n      int_random_sample[i] = x;\n      x = ExponentialBiased::NextRandom(x);\n    }\n    // First sort them...\n    std::sort(int_random_sample.begin(), int_random_sample.end());\n    std::vector<double> random_sample(n);\n    // Convert them to uniform randoms (in the range [0,1])\n    for (size_t i = 0; i < n; i++) {\n      random_sample[i] =\n          static_cast<double>(int_random_sample[i]) / max_prng_value;\n    }\n    // Now compute the Anderson-Darling statistic\n    double ad_pvalue = AndersonDarlingTest(random_sample);\n    EXPECT_GT(std::min(ad_pvalue, 1 - ad_pvalue), 0.0001)\n        << \"prng is not uniform: n = \" << n << \" p = \" << ad_pvalue;\n  }\n}\n\n// The generator needs to be available as a thread_local and as a static\n// variable.\nTEST(ExponentialBiasedTest, InitializationModes) {\n  ABSL_CONST_INIT static ExponentialBiased eb_static;\n  EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));\n\n#ifdef ABSL_HAVE_THREAD_LOCAL\n  thread_local ExponentialBiased eb_thread;\n  EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));\n#endif\n\n  ExponentialBiased eb_stack;\n  EXPECT_THAT(eb_stack.GetSkipCount(2), Ge(0));\n}\n\n}  // namespace\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/internal/periodic_sampler.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/periodic_sampler.h\"\n\n#include <atomic>\n\n#include \"absl/profiling/internal/exponential_biased.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\n\nint64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept {\n  return rng_.GetStride(period);\n}\n\nbool PeriodicSamplerBase::SubtleConfirmSample() noexcept {\n  int current_period = period();\n\n  // Deal with period case 0 (always off) and 1 (always on)\n  if (ABSL_PREDICT_FALSE(current_period < 2)) {\n    stride_ = 0;\n    return current_period == 1;\n  }\n\n  // Check if this is the first call to Sample()\n  if (ABSL_PREDICT_FALSE(stride_ == 1)) {\n    stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));\n    if (static_cast<int64_t>(stride_) < -1) {\n      ++stride_;\n      return false;\n    }\n  }\n\n  stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));\n  return true;\n}\n\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/internal/periodic_sampler.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_\n#define ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_\n\n#include <stdint.h>\n\n#include <atomic>\n\n#include \"absl/base/optimization.h\"\n#include \"absl/profiling/internal/exponential_biased.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\n\n// PeriodicSamplerBase provides the basic period sampler implementation.\n//\n// This is the base class for the templated PeriodicSampler class, which holds\n// a global std::atomic value identified by a user defined tag, such that\n// each specific PeriodSampler implementation holds its own global period.\n//\n// PeriodicSamplerBase is thread-compatible except where stated otherwise.\nclass PeriodicSamplerBase {\n public:\n  // PeriodicSamplerBase is trivial / copyable / movable / destructible.\n  PeriodicSamplerBase() = default;\n  PeriodicSamplerBase(PeriodicSamplerBase&&) = default;\n  PeriodicSamplerBase(const PeriodicSamplerBase&) = default;\n\n  // Returns true roughly once every `period` calls. This is established by a\n  // randomly picked `stride` that is counted down on each call to `Sample`.\n  // This stride is picked such that the probability of `Sample()` returning\n  // true is 1 in `period`.\n  inline bool Sample() noexcept;\n\n  // The below methods are intended for optimized use cases where the\n  // size of the inlined fast path code is highly important. Applications\n  // should use the `Sample()` method unless they have proof that their\n  // specific use case requires the optimizations offered by these methods.\n  //\n  // An example of such a use case is SwissTable sampling. All sampling checks\n  // are in inlined SwissTable methods, and the number of call sites is huge.\n  // In this case, the inlined code size added to each translation unit calling\n  // SwissTable methods is non-trivial.\n  //\n  // The `SubtleMaybeSample()` function spuriously returns true even if the\n  // function should not be sampled, applications MUST match each call to\n  // 'SubtleMaybeSample()' returning true with a `SubtleConfirmSample()` call,\n  // and use the result of the latter as the sampling decision.\n  // In other words: the code should logically be equivalent to:\n  //\n  //    if (SubtleMaybeSample() && SubtleConfirmSample()) {\n  //      // Sample this call\n  //    }\n  //\n  // In the 'inline-size' optimized case, the `SubtleConfirmSample()` call can\n  // be placed out of line, for example, the typical use case looks as follows:\n  //\n  //   // --- frobber.h -----------\n  //   void FrobberSampled();\n  //\n  //   inline void FrobberImpl() {\n  //     // ...\n  //   }\n  //\n  //   inline void Frobber() {\n  //     if (ABSL_PREDICT_FALSE(sampler.SubtleMaybeSample())) {\n  //       FrobberSampled();\n  //     } else {\n  //       FrobberImpl();\n  //     }\n  //   }\n  //\n  //   // --- frobber.cc -----------\n  //   void FrobberSampled() {\n  //     if (!sampler.SubtleConfirmSample())) {\n  //       // Spurious false positive\n  //       FrobberImpl();\n  //       return;\n  //     }\n  //\n  //     // Sampled execution\n  //     // ...\n  //   }\n  inline bool SubtleMaybeSample() noexcept;\n  bool SubtleConfirmSample() noexcept;\n\n protected:\n  // We explicitly don't use a virtual destructor as this class is never\n  // virtually destroyed, and it keeps the class trivial, which avoids TLS\n  // prologue and epilogue code for our TLS instances.\n  ~PeriodicSamplerBase() = default;\n\n  // Returns the next stride for our sampler.\n  // This function is virtual for testing purposes only.\n  virtual int64_t GetExponentialBiased(int period) noexcept;\n\n private:\n  // Returns the current period of this sampler. Thread-safe.\n  virtual int period() const noexcept = 0;\n\n  // Keep and decrement stride_ as an unsigned integer, but compare the value\n  // to zero casted as a signed int. clang and msvc do not create optimum code\n  // if we use signed for the combined decrement and sign comparison.\n  //\n  // Below 3 alternative options, all compiles generate the best code\n  // using the unsigned increment <---> signed int comparison option.\n  //\n  // Option 1:\n  //   int64_t stride_;\n  //   if (ABSL_PREDICT_TRUE(++stride_ < 0)) { ... }\n  //\n  //   GCC   x64 (OK) : https://gcc.godbolt.org/z/R5MzzA\n  //   GCC   ppc (OK) : https://gcc.godbolt.org/z/z7NZAt\n  //   Clang x64 (BAD): https://gcc.godbolt.org/z/t4gPsd\n  //   ICC   x64 (OK) : https://gcc.godbolt.org/z/rE6s8W\n  //   MSVC  x64 (OK) : https://gcc.godbolt.org/z/ARMXqS\n  //\n  // Option 2:\n  //   int64_t stride_ = 0;\n  //   if (ABSL_PREDICT_TRUE(--stride_ >= 0)) { ... }\n  //\n  //   GCC   x64 (OK) : https://gcc.godbolt.org/z/jSQxYK\n  //   GCC   ppc (OK) : https://gcc.godbolt.org/z/VJdYaA\n  //   Clang x64 (BAD): https://gcc.godbolt.org/z/Xm4NjX\n  //   ICC   x64 (OK) : https://gcc.godbolt.org/z/4snaFd\n  //   MSVC  x64 (BAD): https://gcc.godbolt.org/z/BgnEKE\n  //\n  // Option 3:\n  //   uint64_t stride_;\n  //   if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) { ... }\n  //\n  //   GCC   x64 (OK) : https://gcc.godbolt.org/z/bFbfPy\n  //   GCC   ppc (OK) : https://gcc.godbolt.org/z/S9KkUE\n  //   Clang x64 (OK) : https://gcc.godbolt.org/z/UYzRb4\n  //   ICC   x64 (OK) : https://gcc.godbolt.org/z/ptTNfD\n  //   MSVC  x64 (OK) : https://gcc.godbolt.org/z/76j4-5\n  uint64_t stride_ = 0;\n  absl::profiling_internal::ExponentialBiased rng_;\n};\n\ninline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept {\n  // See comments on `stride_` for the unsigned increment / signed compare.\n  if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) {\n    return false;\n  }\n  return true;\n}\n\ninline bool PeriodicSamplerBase::Sample() noexcept {\n  return ABSL_PREDICT_FALSE(SubtleMaybeSample()) ? SubtleConfirmSample()\n                                                 : false;\n}\n\n// PeriodicSampler is a concreted periodic sampler implementation.\n// The user provided Tag identifies the implementation, and is required to\n// isolate the global state of this instance from other instances.\n//\n// Typical use case:\n//\n//   struct HashTablezTag {};\n//   thread_local PeriodicSampler<HashTablezTag, 100> sampler;\n//\n//   void HashTableSamplingLogic(...) {\n//     if (sampler.Sample()) {\n//       HashTableSlowSamplePath(...);\n//     }\n//   }\n//\ntemplate <typename Tag, int default_period = 0>\nclass PeriodicSampler final : public PeriodicSamplerBase {\n public:\n  ~PeriodicSampler() = default;\n\n  int period() const noexcept final {\n    return period_.load(std::memory_order_relaxed);\n  }\n\n  // Sets the global period for this sampler. Thread-safe.\n  // Setting a period of 0 disables the sampler, i.e., every call to Sample()\n  // will return false. Setting a period of 1 puts the sampler in 'always on'\n  // mode, i.e., every call to Sample() returns true.\n  static void SetGlobalPeriod(int period) {\n    period_.store(period, std::memory_order_relaxed);\n  }\n\n private:\n  static std::atomic<int> period_;\n};\n\ntemplate <typename Tag, int default_period>\nstd::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period);\n\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_\n"
  },
  {
    "path": "absl/profiling/internal/periodic_sampler_benchmark.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/periodic_sampler.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\nnamespace {\n\ntemplate <typename Sampler>\nvoid BM_Sample(Sampler* sampler, benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(sampler);\n    benchmark::DoNotOptimize(sampler->Sample());\n  }\n}\n\ntemplate <typename Sampler>\nvoid BM_SampleMinunumInlined(Sampler* sampler, benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(sampler);\n    if (ABSL_PREDICT_FALSE(sampler->SubtleMaybeSample())) {\n      benchmark::DoNotOptimize(sampler->SubtleConfirmSample());\n    }\n  }\n}\n\nvoid BM_PeriodicSampler_TinySample(benchmark::State& state) {\n  struct Tag {};\n  PeriodicSampler<Tag, 10> sampler;\n  BM_Sample(&sampler, state);\n}\nBENCHMARK(BM_PeriodicSampler_TinySample);\n\nvoid BM_PeriodicSampler_ShortSample(benchmark::State& state) {\n  struct Tag {};\n  PeriodicSampler<Tag, 1024> sampler;\n  BM_Sample(&sampler, state);\n}\nBENCHMARK(BM_PeriodicSampler_ShortSample);\n\nvoid BM_PeriodicSampler_LongSample(benchmark::State& state) {\n  struct Tag {};\n  PeriodicSampler<Tag, 1024 * 1024> sampler;\n  BM_Sample(&sampler, state);\n}\nBENCHMARK(BM_PeriodicSampler_LongSample);\n\nvoid BM_PeriodicSampler_LongSampleMinunumInlined(benchmark::State& state) {\n  struct Tag {};\n  PeriodicSampler<Tag, 1024 * 1024> sampler;\n  BM_SampleMinunumInlined(&sampler, state);\n}\nBENCHMARK(BM_PeriodicSampler_LongSampleMinunumInlined);\n\nvoid BM_PeriodicSampler_Disabled(benchmark::State& state) {\n  struct Tag {};\n  PeriodicSampler<Tag, 0> sampler;\n  BM_Sample(&sampler, state);\n}\nBENCHMARK(BM_PeriodicSampler_Disabled);\n\n}  // namespace\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/internal/periodic_sampler_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/periodic_sampler.h\"\n\n#include <thread>  // NOLINT(build/c++11)\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\nnamespace {\n\nusing testing::Eq;\nusing testing::Return;\nusing testing::StrictMock;\n\nclass MockPeriodicSampler : public PeriodicSamplerBase {\n public:\n  virtual ~MockPeriodicSampler() = default;\n\n  MOCK_METHOD(int, period, (), (const, noexcept));\n  MOCK_METHOD(int64_t, GetExponentialBiased, (int), (noexcept));\n};\n\nTEST(PeriodicSamplerBaseTest, Sample) {\n  StrictMock<MockPeriodicSampler> sampler;\n\n  EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(16));\n  EXPECT_CALL(sampler, GetExponentialBiased(16))\n      .WillOnce(Return(2))\n      .WillOnce(Return(3))\n      .WillOnce(Return(4));\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_TRUE(sampler.Sample());\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_TRUE(sampler.Sample());\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n}\n\nTEST(PeriodicSamplerBaseTest, ImmediatelySample) {\n  StrictMock<MockPeriodicSampler> sampler;\n\n  EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));\n  EXPECT_CALL(sampler, GetExponentialBiased(16))\n      .WillOnce(Return(1))\n      .WillOnce(Return(2))\n      .WillOnce(Return(3));\n\n  EXPECT_TRUE(sampler.Sample());\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_TRUE(sampler.Sample());\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n}\n\nTEST(PeriodicSamplerBaseTest, Disabled) {\n  StrictMock<MockPeriodicSampler> sampler;\n\n  EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(0));\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n}\n\nTEST(PeriodicSamplerBaseTest, AlwaysOn) {\n  StrictMock<MockPeriodicSampler> sampler;\n\n  EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(1));\n\n  EXPECT_TRUE(sampler.Sample());\n  EXPECT_TRUE(sampler.Sample());\n  EXPECT_TRUE(sampler.Sample());\n}\n\nTEST(PeriodicSamplerBaseTest, Disable) {\n  StrictMock<MockPeriodicSampler> sampler;\n\n  EXPECT_CALL(sampler, period()).WillOnce(Return(16));\n  EXPECT_CALL(sampler, GetExponentialBiased(16)).WillOnce(Return(3));\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n\n  EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(0));\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n}\n\nTEST(PeriodicSamplerBaseTest, Enable) {\n  StrictMock<MockPeriodicSampler> sampler;\n\n  EXPECT_CALL(sampler, period()).WillOnce(Return(0));\n  EXPECT_FALSE(sampler.Sample());\n\n  EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));\n  EXPECT_CALL(sampler, GetExponentialBiased(16))\n      .Times(2)\n      .WillRepeatedly(Return(3));\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_TRUE(sampler.Sample());\n\n  EXPECT_FALSE(sampler.Sample());\n  EXPECT_FALSE(sampler.Sample());\n}\n\nTEST(PeriodicSamplerTest, ConstructConstInit) {\n  struct Tag {};\n  ABSL_CONST_INIT static PeriodicSampler<Tag> sampler;\n  (void)sampler;\n}\n\nTEST(PeriodicSamplerTest, DefaultPeriod0) {\n  struct Tag {};\n  PeriodicSampler<Tag> sampler;\n  EXPECT_THAT(sampler.period(), Eq(0));\n}\n\nTEST(PeriodicSamplerTest, DefaultPeriod) {\n  struct Tag {};\n  PeriodicSampler<Tag, 100> sampler;\n  EXPECT_THAT(sampler.period(), Eq(100));\n}\n\nTEST(PeriodicSamplerTest, SetGlobalPeriod) {\n  struct Tag1 {};\n  struct Tag2 {};\n  PeriodicSampler<Tag1, 25> sampler1;\n  PeriodicSampler<Tag2, 50> sampler2;\n\n  EXPECT_THAT(sampler1.period(), Eq(25));\n  EXPECT_THAT(sampler2.period(), Eq(50));\n\n  std::thread thread([] {\n    PeriodicSampler<Tag1, 25> sampler1;\n    PeriodicSampler<Tag2, 50> sampler2;\n    EXPECT_THAT(sampler1.period(), Eq(25));\n    EXPECT_THAT(sampler2.period(), Eq(50));\n    sampler1.SetGlobalPeriod(10);\n    sampler2.SetGlobalPeriod(20);\n  });\n  thread.join();\n\n  EXPECT_THAT(sampler1.period(), Eq(10));\n  EXPECT_THAT(sampler2.period(), Eq(20));\n}\n\n}  // namespace\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/internal/profile_builder.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may\n// obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/profile_builder.h\"\n\n#ifdef __linux__\n#include <elf.h>\n#include <link.h>\n#endif  // __linux__\n\n#include <cassert>\n#include <cstdint>\n#include <cstring>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\nnamespace {\n\n// This file contains a simplified implementation of the pprof profile builder,\n// which avoids a dependency on protobuf.\n//\n// The canonical profile proto definition is at\n// https://github.com/google/pprof/blob/master/proto/profile.proto\n//\n// Wire-format encoding is a simple sequence of (tag, value) pairs. The tag\n// is a varint-encoded integer, where the low 3 bits are the wire type, and the\n// high bits are the field number.\n//\n// For the fields we care about, we'll be using the following wire types:\n//\n// Wire Type 0: Varint-encoded integer.\n// Wire Type 2: Length-delimited. Used for strings and sub-messages.\nenum class WireType {\n  kVarint = 0,\n  kLengthDelimited = 2,\n};\n\n#ifdef __linux__\n// Returns the Phdr of the first segment of the given type.\nconst ElfW(Phdr) * GetFirstSegment(const dl_phdr_info* const info,\n                                   const ElfW(Word) segment_type) {\n  for (int i = 0; i < info->dlpi_phnum; ++i) {\n    if (info->dlpi_phdr[i].p_type == segment_type) {\n      return &info->dlpi_phdr[i];\n    }\n  }\n  return nullptr;\n}\n\n// Return DT_SONAME for the given image.  If there is no PT_DYNAMIC or if\n// PT_DYNAMIC does not contain DT_SONAME, return nullptr.\nstatic const char* GetSoName(const dl_phdr_info* const info) {\n  const ElfW(Phdr)* const pt_dynamic = GetFirstSegment(info, PT_DYNAMIC);\n  if (pt_dynamic == nullptr) {\n    return nullptr;\n  }\n  const ElfW(Dyn)* dyn =\n      reinterpret_cast<ElfW(Dyn)*>(info->dlpi_addr + pt_dynamic->p_vaddr);\n  const ElfW(Dyn)* dt_strtab = nullptr;\n  const ElfW(Dyn)* dt_strsz = nullptr;\n  const ElfW(Dyn)* dt_soname = nullptr;\n  for (; dyn->d_tag != DT_NULL; ++dyn) {\n    if (dyn->d_tag == DT_SONAME) {\n      dt_soname = dyn;\n    } else if (dyn->d_tag == DT_STRTAB) {\n      dt_strtab = dyn;\n    } else if (dyn->d_tag == DT_STRSZ) {\n      dt_strsz = dyn;\n    }\n  }\n  if (dt_soname == nullptr) {\n    return nullptr;\n  }\n  ABSL_RAW_CHECK(dt_strtab != nullptr, \"Unexpected nullptr\");\n  ABSL_RAW_CHECK(dt_strsz != nullptr, \"Unexpected nullptr\");\n  const char* const strtab = reinterpret_cast<char*>(\n      info->dlpi_addr + static_cast<ElfW(Word)>(dt_strtab->d_un.d_val));\n  ABSL_RAW_CHECK(dt_soname->d_un.d_val < dt_strsz->d_un.d_val,\n                 \"Unexpected order\");\n  return strtab + dt_soname->d_un.d_val;\n}\n\n// Helper function to get the build ID of a shared object.\nstd::string GetBuildId(const dl_phdr_info* const info) {\n  std::string result;\n\n  // pt_note contains entries (of type ElfW(Nhdr)) starting at\n  //   info->dlpi_addr + pt_note->p_vaddr\n  // with length\n  //   pt_note->p_memsz\n  //\n  // The length of each entry is given by\n  //   Align(sizeof(ElfW(Nhdr)) + nhdr->n_namesz) + Align(nhdr->n_descsz)\n  for (int i = 0; i < info->dlpi_phnum; ++i) {\n    const ElfW(Phdr)* pt_note = &info->dlpi_phdr[i];\n    if (pt_note->p_type != PT_NOTE) continue;\n\n    const char* note =\n        reinterpret_cast<char*>(info->dlpi_addr + pt_note->p_vaddr);\n    const char* const last = note + pt_note->p_filesz;\n    const ElfW(Xword) align = pt_note->p_align;\n    while (note < last) {\n      const ElfW(Nhdr)* const nhdr = reinterpret_cast<const ElfW(Nhdr)*>(note);\n      if (note + sizeof(*nhdr) > last) {\n        // Corrupt PT_NOTE\n        break;\n      }\n\n      // Both the start and end of the descriptor are aligned by sh_addralign\n      // (= p_align).\n      const ElfW(Xword) desc_start =\n          (sizeof(*nhdr) + nhdr->n_namesz + align - 1) & -align;\n      const ElfW(Xword) size =\n          desc_start + ((nhdr->n_descsz + align - 1) & -align);\n\n      // Beware of wrap-around.\n      if (nhdr->n_namesz >= static_cast<ElfW(Word)>(-align) ||\n          nhdr->n_descsz >= static_cast<ElfW(Word)>(-align) ||\n          desc_start < sizeof(*nhdr) || size < desc_start ||\n          size > static_cast<ElfW(Xword)>(last - note)) {\n        // Corrupt PT_NOTE\n        break;\n      }\n\n      if (nhdr->n_type == NT_GNU_BUILD_ID) {\n        const char* const note_name = note + sizeof(*nhdr);\n        // n_namesz is the length of note_name.\n        if (nhdr->n_namesz == 4 && memcmp(note_name, \"GNU\\0\", 4) == 0) {\n          if (!result.empty()) {\n            // Repeated build-ids.  Ignore them.\n            return \"\";\n          }\n          result = absl::BytesToHexString(\n              absl::string_view(note + desc_start, nhdr->n_descsz));\n        }\n      }\n      note += size;\n    }\n  }\n\n  return result;\n}\n#endif  // __linux__\n\n// A varint-encoded integer.\nstruct Varint {\n  explicit Varint(uint64_t v) : value(v) {}\n  explicit Varint(StringId v) : value(static_cast<uint64_t>(v)) {}\n  explicit Varint(LocationId v) : value(static_cast<uint64_t>(v)) {}\n  explicit Varint(MappingId v) : value(static_cast<uint64_t>(v)) {}\n\n  uint64_t value;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const Varint& v) {\n    char buf[10];\n    char* p = buf;\n    uint64_t u = v.value;\n    while (u >= 0x80) {\n      *p++ = static_cast<char>((u & 0x7f) | 0x80);\n      u >>= 7;\n    }\n    *p++ = static_cast<char>(u);\n    sink.Append(absl::string_view(buf, static_cast<size_t>(p - buf)));\n  }\n};\n\nstruct Tag {\n  int field_number;\n  WireType wire_type;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const Tag& t) {\n    absl::Format(&sink, \"%v\",\n                 Varint((static_cast<uint64_t>(t.field_number) << 3) |\n                        static_cast<uint64_t>(t.wire_type)));\n  }\n};\n\nstruct LengthDelimited {\n  int field_number;\n  absl::string_view value;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const LengthDelimited& ld) {\n    absl::Format(&sink, \"%v%v%v\",\n                 Tag{ld.field_number, WireType::kLengthDelimited},\n                 Varint(ld.value.size()), ld.value);\n  }\n};\n\nstruct VarintField {\n  int field_number;\n  Varint value;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const VarintField& vf) {\n    absl::Format(&sink, \"%v%v\", Tag{vf.field_number, WireType::kVarint},\n                 vf.value);\n  }\n};\n\n}  // namespace\n\nStringId ProfileBuilder::InternString(absl::string_view str) {\n  if (str.empty()) return StringId(0);\n  return string_table_.emplace(str, StringId(string_table_.size()))\n      .first->second;\n}\n\nLocationId ProfileBuilder::InternLocation(const void* address) {\n  return location_table_\n      .emplace(absl::bit_cast<uintptr_t>(address),\n               LocationId(location_table_.size() + 1))\n      .first->second;\n}\n\nvoid ProfileBuilder::AddSample(\n    int64_t value, absl::Span<const void* const> stack,\n    absl::Span<const std::pair<StringId, int64_t>> labels) {\n  std::string sample_proto;\n  absl::StrAppend(\n      &sample_proto,\n      VarintField{SampleProto::kValue, Varint(static_cast<uint64_t>(value))});\n\n  for (const void* addr : stack) {\n    // Profile addresses are raw stack unwind addresses, so they should be\n    // adjusted by -1 to land inside the call instruction (although potentially\n    // misaligned).\n    absl::StrAppend(\n        &sample_proto,\n        VarintField{SampleProto::kLocationId,\n                    Varint(InternLocation(absl::bit_cast<const void*>(\n                        absl::bit_cast<uintptr_t>(addr) - 1)))});\n  }\n\n  for (const auto& label : labels) {\n    std::string label_proto =\n        absl::StrCat(VarintField{LabelProto::kKey, Varint(label.first)},\n                     VarintField{LabelProto::kNum,\n                                 Varint(static_cast<uint64_t>(label.second))});\n    absl::StrAppend(&sample_proto,\n                    LengthDelimited{SampleProto::kLabel, label_proto});\n  }\n  samples_.push_back(std::move(sample_proto));\n}\n\nvoid ProfileBuilder::AddSampleType(StringId type, StringId unit) {\n  std::string sample_type_proto =\n      absl::StrCat(VarintField{ValueTypeProto::kType, Varint(type)},\n                   VarintField{ValueTypeProto::kUnit, Varint(unit)});\n  sample_types_.push_back(std::move(sample_type_proto));\n}\n\nMappingId ProfileBuilder::AddMapping(uintptr_t memory_start,\n                                     uintptr_t memory_limit,\n                                     uintptr_t file_offset,\n                                     absl::string_view filename,\n                                     absl::string_view build_id) {\n  size_t index = mappings_.size() + 1;\n  auto [it, inserted] = mapping_table_.emplace(memory_start, index);\n  if (!inserted) {\n    return static_cast<MappingId>(it->second);\n  }\n\n  Mapping m;\n  m.start = memory_start;\n  m.limit = memory_limit;\n  m.offset = file_offset;\n  m.filename = std::string(filename);\n  m.build_id = std::string(build_id);\n\n  mappings_.push_back(std::move(m));\n  return static_cast<MappingId>(index);\n}\n\nstd::string ProfileBuilder::Emit() && {\n  std::string profile_proto;\n  for (const auto& sample_type : sample_types_) {\n    absl::StrAppend(&profile_proto,\n                    LengthDelimited{ProfileProto::kSampleType, sample_type});\n  }\n  for (const auto& sample : samples_) {\n    absl::StrAppend(&profile_proto,\n                    LengthDelimited{ProfileProto::kSample, sample});\n  }\n\n  // Build mapping table.\n  for (size_t i = 0, n = mappings_.size(); i < n; ++i) {\n    const auto& mapping = mappings_[i];\n    std::string mapping_proto = absl::StrCat(\n        VarintField{MappingProto::kId, Varint(static_cast<uint64_t>(i + 1))},\n        VarintField{MappingProto::kMemoryStart, Varint(mapping.start)},\n        VarintField{MappingProto::kMemoryLimit, Varint(mapping.limit)},\n        VarintField{MappingProto::kFileOffset, Varint(mapping.offset)},\n        VarintField{MappingProto::kFilename,\n                    Varint(InternString(mapping.filename))},\n        VarintField{MappingProto::kBuildId,\n                    Varint(InternString(mapping.build_id))});\n\n    absl::StrAppend(&profile_proto,\n                    LengthDelimited{ProfileProto::kMapping, mapping_proto});\n  }\n\n  // Build location table.\n  for (const auto& [address, id] : location_table_) {\n    std::string location =\n        absl::StrCat(VarintField{LocationProto::kId, Varint(id)},\n                     VarintField{LocationProto::kAddress, Varint(address)});\n\n    if (!mappings_.empty()) {\n      // Find the mapping ID.\n      auto it = mapping_table_.upper_bound(address);\n      if (it != mapping_table_.begin()) {\n        --it;\n      }\n\n      // If *it contains address, add mapping to location.\n      const size_t mapping_index = it->second;\n      const Mapping& mapping = mappings_[mapping_index - 1];\n\n      if (it->first <= address && address < mapping.limit) {\n        absl::StrAppend(\n            &location,\n            VarintField{LocationProto::kMappingId,\n                        Varint(static_cast<uint64_t>(mapping_index))});\n      }\n    }\n\n    absl::StrAppend(&profile_proto,\n                    LengthDelimited{ProfileProto::kLocation, location});\n  }\n\n  std::string string_table_proto;\n  std::vector<absl::string_view> sorted_strings(string_table_.size());\n  for (const auto& p : string_table_) {\n    sorted_strings[static_cast<size_t>(p.second)] = p.first;\n  }\n  for (const auto& s : sorted_strings) {\n    absl::StrAppend(&string_table_proto,\n                    LengthDelimited{ProfileProto::kStringTable, s});\n  }\n  absl::StrAppend(&profile_proto, VarintField{ProfileProto::kDropFrames,\n                                              Varint(drop_frames_id_)});\n  absl::StrAppend(&profile_proto,\n                  VarintField{ProfileProto::kComment, Varint(comment_id_)});\n  absl::StrAppend(&profile_proto, VarintField{ProfileProto::kDefaultSampleType,\n                                              Varint(default_sample_type_id_)});\n  return absl::StrCat(string_table_proto, profile_proto);\n}\n\nvoid ProfileBuilder::set_drop_frames_id(StringId drop_frames_id) {\n  drop_frames_id_ = drop_frames_id;\n}\n\nvoid ProfileBuilder::set_comment_id(StringId comment_id) {\n  comment_id_ = comment_id;\n}\n\nvoid ProfileBuilder::set_default_sample_type_id(\n    StringId default_sample_type_id) {\n  default_sample_type_id_ = default_sample_type_id;\n}\n\nvoid ProfileBuilder::AddCurrentMappings() {\n#ifdef __linux__\n  dl_iterate_phdr(\n      +[](dl_phdr_info* info, size_t, void* data) {\n        auto& builder = *reinterpret_cast<ProfileBuilder*>(data);\n\n        // Skip dummy entry introduced since glibc 2.18.\n        if (info->dlpi_phdr == nullptr && info->dlpi_phnum == 0) {\n          return 0;\n        }\n\n        const bool is_main_executable = builder.mappings_.empty();\n\n        // Storage for path to executable as dlpi_name isn't populated for the\n        // main executable.  +1 to allow for the null terminator that readlink\n        // does not add.\n        char self_filename[PATH_MAX + 1];\n        const char* filename = info->dlpi_name;\n        if (filename == nullptr || filename[0] == '\\0') {\n          // This is either the main executable or the VDSO.  The main\n          // executable is always the first entry processed by callbacks.\n          if (is_main_executable) {\n            // This is the main executable.\n            ssize_t ret = readlink(\"/proc/self/exe\", self_filename,\n                                   sizeof(self_filename) - 1);\n            if (ret >= 0 && static_cast<size_t>(ret) < sizeof(self_filename)) {\n              self_filename[ret] = '\\0';\n              filename = self_filename;\n            }\n          } else {\n            // This is the VDSO.\n            filename = GetSoName(info);\n          }\n        }\n\n        char resolved_path[PATH_MAX];\n        absl::string_view resolved_filename;\n        if (realpath(filename, resolved_path)) {\n          resolved_filename = resolved_path;\n        } else {\n          resolved_filename = filename;\n        }\n\n        const std::string build_id = GetBuildId(info);\n\n        // Evaluate all the loadable segments.\n        for (int i = 0; i < info->dlpi_phnum; ++i) {\n          if (info->dlpi_phdr[i].p_type != PT_LOAD) {\n            continue;\n          }\n          const ElfW(Phdr)* pt_load = &info->dlpi_phdr[i];\n\n          ABSL_RAW_CHECK(pt_load != nullptr, \"Unexpected nullptr\");\n\n          // Extract data.\n          const size_t memory_start = info->dlpi_addr + pt_load->p_vaddr;\n          const size_t memory_limit = memory_start + pt_load->p_memsz;\n          const size_t file_offset = pt_load->p_offset;\n\n          // Add to profile.\n          builder.AddMapping(memory_start, memory_limit, file_offset,\n                             resolved_filename, build_id);\n        }\n        // Keep going.\n        return 0;\n      },\n      this);\n#endif  // __linux__\n}\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/profiling/internal/profile_builder.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may\n// obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_\n#define ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <string>\n#include <vector>\n\n#include \"absl/container/btree_map.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace debugging_internal {\n\n// Field numbers for perftools.profiles.Profile.\n// https://github.com/google/pprof/blob/master/proto/profile.proto\nstruct ProfileProto {\n  static constexpr int kSampleType = 1;\n  static constexpr int kSample = 2;\n  static constexpr int kMapping = 3;\n  static constexpr int kLocation = 4;\n  static constexpr int kStringTable = 6;\n  static constexpr int kDropFrames = 7;\n  static constexpr int kComment = 13;\n  static constexpr int kDefaultSampleType = 14;\n};\n\nstruct ValueTypeProto {\n  static constexpr int kType = 1;\n  static constexpr int kUnit = 2;\n};\n\nstruct SampleProto {\n  static constexpr int kLocationId = 1;\n  static constexpr int kValue = 2;\n  static constexpr int kLabel = 3;\n};\n\nstruct LabelProto {\n  static constexpr int kKey = 1;\n  static constexpr int kStr = 2;\n  static constexpr int kNum = 3;\n  static constexpr int kNumUnit = 4;\n};\n\nstruct MappingProto {\n  static constexpr int kId = 1;\n  static constexpr int kMemoryStart = 2;\n  static constexpr int kMemoryLimit = 3;\n  static constexpr int kFileOffset = 4;\n  static constexpr int kFilename = 5;\n  static constexpr int kBuildId = 6;\n};\n\nstruct LocationProto {\n  static constexpr int kId = 1;\n  static constexpr int kMappingId = 2;\n  static constexpr int kAddress = 3;\n};\n\nenum class StringId : size_t {};\nenum class LocationId : size_t {};\nenum class MappingId : size_t {};\n\n// A helper class to build a profile protocol buffer.\nclass ProfileBuilder {\n public:\n  struct Mapping {\n    uint64_t start;\n    uint64_t limit;\n    uint64_t offset;\n    std::string filename;\n    std::string build_id;\n  };\n\n  StringId InternString(absl::string_view str);\n\n  LocationId InternLocation(const void* address);\n\n  void AddSample(int64_t value, absl::Span<const void* const> stack,\n                 absl::Span<const std::pair<StringId, int64_t>> labels);\n\n  void AddSampleType(StringId type, StringId unit);\n\n  // Adds the current process mappings to the profile.\n  void AddCurrentMappings();\n\n  // Adds a single mapping to the profile and to lookup cache and returns the\n  // resulting ID.\n  MappingId AddMapping(uintptr_t memory_start, uintptr_t memory_limit,\n                       uintptr_t file_offset, absl::string_view filename,\n                       absl::string_view build_id);\n\n  std::string Emit() &&;\n\n  void set_drop_frames_id(StringId drop_frames_id);\n  void set_comment_id(StringId comment_id);\n  void set_default_sample_type_id(StringId default_sample_type_id);\n\n private:\n  // We turn off hashtable profiling for the ProfileBuilder's own tables.\n  //\n  // This is necessary since we use this class to construct hashtable profiles,\n  // which entails walking the hashtable profiling data and we don't want to\n  // encounter it reentrantly.\n  template <typename T>\n  struct HashtablezBarrier : std::allocator<T> {\n    HashtablezBarrier() = default;\n\n    template <typename U>\n    HashtablezBarrier(const HashtablezBarrier<U>&) {}\n\n    template <class U>\n    struct rebind {\n      using other = HashtablezBarrier<U>;\n    };\n  };\n\n  template <typename K, typename V>\n  using UnprofiledHashMap = absl::flat_hash_map<\n      K, V, DefaultHashContainerHash<K>, DefaultHashContainerEq<K>,\n      HashtablezBarrier<std::pair<const K, V>>>;\n\n  UnprofiledHashMap<std::string, StringId> string_table_{{\"\", StringId(0)}};\n  UnprofiledHashMap<uintptr_t, LocationId> location_table_;\n  // mapping_table_ stores the start address of each mapping in mapping_\n  // to its index.\n  absl::btree_map<uintptr_t, size_t> mapping_table_;\n  std::vector<Mapping> mappings_;\n\n  std::vector<std::string> sample_types_;\n  std::vector<std::string> samples_;\n\n  StringId drop_frames_id_{};\n  StringId comment_id_{};\n  StringId default_sample_type_id_{};\n};\n\n}  // namespace debugging_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_\n"
  },
  {
    "path": "absl/profiling/internal/sample_recorder.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: sample_recorder.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a lock-free linked list for recording samples\n// collected from a random/stochastic process.\n//\n// This utility is internal-only. Use at your own risk.\n\n#ifndef ABSL_PROFILING_INTERNAL_SAMPLE_RECORDER_H_\n#define ABSL_PROFILING_INTERNAL_SAMPLE_RECORDER_H_\n\n#include <atomic>\n#include <cstddef>\n#include <functional>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\n\n// Sample<T> that has members required for linking samples in the linked list of\n// samples maintained by the SampleRecorder.  Type T defines the sampled data.\ntemplate <typename T>\nstruct Sample {\n  // Guards the ability to restore the sample to a pristine state.  This\n  // prevents races with sampling and resurrecting an object.\n  absl::Mutex init_mu;\n  T* next = nullptr;\n  T* dead ABSL_GUARDED_BY(init_mu) = nullptr;\n  int64_t weight;  // How many sampling events were required to sample this one.\n};\n\n// Holds samples and their associated stack traces with a soft limit of\n// `SetHashtablezMaxSamples()`.\n//\n// Thread safe.\ntemplate <typename T>\nclass SampleRecorder {\n public:\n  SampleRecorder();\n  ~SampleRecorder();\n\n  // Registers for sampling.  Returns an opaque registration info.\n  template <typename... Targs>\n  T* Register(Targs&&... args);\n\n  // Unregisters the sample.\n  void Unregister(T* sample);\n\n  // The dispose callback will be called on all samples the moment they are\n  // being unregistered. Only affects samples that are unregistered after the\n  // callback has been set.\n  // Returns the previous callback.\n  using DisposeCallback = void (*)(const T&);\n  DisposeCallback SetDisposeCallback(DisposeCallback f);\n\n  // Iterates over all the registered `StackInfo`s.  Returning the number of\n  // samples that have been dropped.\n  size_t Iterate(const std::function<void(const T& stack)>& f);\n\n  size_t GetMaxSamples() const;\n  void SetMaxSamples(size_t max);\n\n private:\n  void PushNew(T* sample);\n  void PushDead(T* sample);\n  template <typename... Targs>\n  T* PopDead(Targs... args);\n\n  std::atomic<size_t> dropped_samples_;\n  std::atomic<size_t> size_estimate_;\n  std::atomic<size_t> max_samples_{1 << 20};\n\n  // Intrusive lock free linked lists for tracking samples.\n  //\n  // `all_` records all samples (they are never removed from this list) and is\n  // terminated with a `nullptr`.\n  //\n  // `graveyard_.dead` is a circular linked list.  When it is empty,\n  // `graveyard_.dead == &graveyard`.  The list is circular so that\n  // every item on it (even the last) has a non-null dead pointer.  This allows\n  // `Iterate` to determine if a given sample is live or dead using only\n  // information on the sample itself.\n  //\n  // For example, nodes [A, B, C, D, E] with [A, C, E] alive and [B, D] dead\n  // looks like this (G is the Graveyard):\n  //\n  //           +---+    +---+    +---+    +---+    +---+\n  //    all -->| A |--->| B |--->| C |--->| D |--->| E |\n  //           |   |    |   |    |   |    |   |    |   |\n  //   +---+   |   | +->|   |-+  |   | +->|   |-+  |   |\n  //   | G |   +---+ |  +---+ |  +---+ |  +---+ |  +---+\n  //   |   |         |        |        |        |\n  //   |   | --------+        +--------+        |\n  //   +---+                                    |\n  //     ^                                      |\n  //     +--------------------------------------+\n  //\n  std::atomic<T*> all_;\n  T graveyard_;\n\n  std::atomic<DisposeCallback> dispose_;\n};\n\ntemplate <typename T>\ntypename SampleRecorder<T>::DisposeCallback\nSampleRecorder<T>::SetDisposeCallback(DisposeCallback f) {\n  return dispose_.exchange(f, std::memory_order_relaxed);\n}\n\ntemplate <typename T>\nSampleRecorder<T>::SampleRecorder()\n    : dropped_samples_(0), size_estimate_(0), all_(nullptr), dispose_(nullptr) {\n  absl::MutexLock l(graveyard_.init_mu);\n  graveyard_.dead = &graveyard_;\n}\n\ntemplate <typename T>\nSampleRecorder<T>::~SampleRecorder() {\n  T* s = all_.load(std::memory_order_acquire);\n  while (s != nullptr) {\n    T* next = s->next;\n    delete s;\n    s = next;\n  }\n}\n\ntemplate <typename T>\nvoid SampleRecorder<T>::PushNew(T* sample) {\n  sample->next = all_.load(std::memory_order_relaxed);\n  while (!all_.compare_exchange_weak(sample->next, sample,\n                                     std::memory_order_release,\n                                     std::memory_order_relaxed)) {\n  }\n}\n\ntemplate <typename T>\nvoid SampleRecorder<T>::PushDead(T* sample) {\n  if (auto* dispose = dispose_.load(std::memory_order_relaxed)) {\n    dispose(*sample);\n  }\n\n  absl::MutexLock graveyard_lock(graveyard_.init_mu);\n  absl::MutexLock sample_lock(sample->init_mu);\n  sample->dead = graveyard_.dead;\n  graveyard_.dead = sample;\n}\n\ntemplate <typename T>\ntemplate <typename... Targs>\nT* SampleRecorder<T>::PopDead(Targs... args) {\n  absl::MutexLock graveyard_lock(graveyard_.init_mu);\n\n  // The list is circular, so eventually it collapses down to\n  //   graveyard_.dead == &graveyard_\n  // when it is empty.\n  T* sample = graveyard_.dead;\n  if (sample == &graveyard_) return nullptr;\n\n  absl::MutexLock sample_lock(sample->init_mu);\n  graveyard_.dead = sample->dead;\n  sample->dead = nullptr;\n  sample->PrepareForSampling(std::forward<Targs>(args)...);\n  return sample;\n}\n\ntemplate <typename T>\ntemplate <typename... Targs>\nT* SampleRecorder<T>::Register(Targs&&... args) {\n  size_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);\n  if (size > max_samples_.load(std::memory_order_relaxed)) {\n    size_estimate_.fetch_sub(1, std::memory_order_relaxed);\n    dropped_samples_.fetch_add(1, std::memory_order_relaxed);\n    return nullptr;\n  }\n\n  T* sample = PopDead(args...);\n  if (sample == nullptr) {\n    // Resurrection failed.  Hire a new warlock.\n    sample = new T();\n    {\n      absl::MutexLock sample_lock(sample->init_mu);\n      // If flag initialization happens to occur (perhaps in another thread)\n      // while in this block, it will lock `graveyard_` which is usually always\n      // locked before any sample. This will appear as a lock inversion.\n      // However, this code is run exactly once per sample, and this sample\n      // cannot be accessed until after it is returned from this method.  This\n      // means that this lock state can never be recreated, so we can safely\n      // inform the deadlock detector to ignore it.\n      sample->init_mu.ForgetDeadlockInfo();\n      sample->PrepareForSampling(std::forward<Targs>(args)...);\n    }\n    PushNew(sample);\n  }\n\n  return sample;\n}\n\ntemplate <typename T>\nvoid SampleRecorder<T>::Unregister(T* sample) {\n  PushDead(sample);\n  size_estimate_.fetch_sub(1, std::memory_order_relaxed);\n}\n\ntemplate <typename T>\nsize_t SampleRecorder<T>::Iterate(\n    const std::function<void(const T& stack)>& f) {\n  T* s = all_.load(std::memory_order_acquire);\n  while (s != nullptr) {\n    absl::MutexLock l(s->init_mu);\n    if (s->dead == nullptr) {\n      f(*s);\n    }\n    s = s->next;\n  }\n\n  return dropped_samples_.load(std::memory_order_relaxed);\n}\n\ntemplate <typename T>\nvoid SampleRecorder<T>::SetMaxSamples(size_t max) {\n  max_samples_.store(max, std::memory_order_release);\n}\n\ntemplate <typename T>\nsize_t SampleRecorder<T>::GetMaxSamples() const {\n  return max_samples_.load(std::memory_order_acquire);\n}\n\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_PROFILING_INTERNAL_SAMPLE_RECORDER_H_\n"
  },
  {
    "path": "absl/profiling/internal/sample_recorder_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/profiling/internal/sample_recorder.h\"\n\n#include <atomic>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <random>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/random/random.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/synchronization/notification.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace profiling_internal {\n\nnamespace {\nusing ::absl::synchronization_internal::ThreadPool;\nusing ::testing::IsEmpty;\nusing ::testing::UnorderedElementsAre;\n\nstruct Info : public Sample<Info> {\n public:\n  void PrepareForSampling(int64_t w) { weight = w; }\n  std::atomic<size_t> size;\n  absl::Time create_time;\n};\n\nstd::vector<size_t> GetSizes(SampleRecorder<Info>* s) {\n  std::vector<size_t> res;\n  s->Iterate([&](const Info& info) {\n    res.push_back(info.size.load(std::memory_order_acquire));\n  });\n  return res;\n}\n\nstd::vector<int64_t> GetWeights(SampleRecorder<Info>* s) {\n  std::vector<int64_t> res;\n  s->Iterate([&](const Info& info) { res.push_back(info.weight); });\n  return res;\n}\n\nInfo* Register(SampleRecorder<Info>* s, int64_t weight, size_t size) {\n  auto* info = s->Register(weight);\n  assert(info != nullptr);\n  info->size.store(size);\n  return info;\n}\n\nTEST(SampleRecorderTest, Registration) {\n  SampleRecorder<Info> sampler;\n  auto* info1 = Register(&sampler, 31, 1);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1));\n  EXPECT_THAT(GetWeights(&sampler), UnorderedElementsAre(31));\n\n  auto* info2 = Register(&sampler, 32, 2);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1, 2));\n  info1->size.store(3);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(3, 2));\n  EXPECT_THAT(GetWeights(&sampler), UnorderedElementsAre(31, 32));\n\n  sampler.Unregister(info1);\n  sampler.Unregister(info2);\n}\n\nTEST(SampleRecorderTest, Unregistration) {\n  SampleRecorder<Info> sampler;\n  std::vector<Info*> infos;\n  for (size_t i = 0; i < 3; ++i) {\n    infos.push_back(Register(&sampler, 33 + i, i));\n  }\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 1, 2));\n  EXPECT_THAT(GetWeights(&sampler), UnorderedElementsAre(33, 34, 35));\n\n  sampler.Unregister(infos[1]);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2));\n  EXPECT_THAT(GetWeights(&sampler), UnorderedElementsAre(33, 35));\n\n  infos.push_back(Register(&sampler, 36, 3));\n  infos.push_back(Register(&sampler, 37, 4));\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 3, 4));\n  EXPECT_THAT(GetWeights(&sampler), UnorderedElementsAre(33, 35, 36, 37));\n  sampler.Unregister(infos[3]);\n  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 4));\n  EXPECT_THAT(GetWeights(&sampler), UnorderedElementsAre(33, 35, 37));\n\n  sampler.Unregister(infos[0]);\n  sampler.Unregister(infos[2]);\n  sampler.Unregister(infos[4]);\n  EXPECT_THAT(GetSizes(&sampler), IsEmpty());\n}\n\nTEST(SampleRecorderTest, MultiThreaded) {\n  SampleRecorder<Info> sampler;\n  Notification stop;\n  ThreadPool pool(10);\n\n  for (int i = 0; i < 10; ++i) {\n    pool.Schedule([&sampler, &stop, i]() {\n      absl::InsecureBitGen gen;\n      std::vector<Info*> infoz;\n      while (!stop.HasBeenNotified()) {\n        if (infoz.empty()) {\n          infoz.push_back(sampler.Register(i));\n        }\n        switch (std::uniform_int_distribution<>(0, 2)(gen)) {\n          case 0: {\n            infoz.push_back(sampler.Register(i));\n            break;\n          }\n          case 1: {\n            size_t p =\n                std::uniform_int_distribution<>(0, infoz.size() - 1)(gen);\n            Info* info = infoz[p];\n            infoz[p] = infoz.back();\n            infoz.pop_back();\n            EXPECT_EQ(info->weight, i);\n            sampler.Unregister(info);\n            break;\n          }\n          case 2: {\n            absl::Duration oldest = absl::ZeroDuration();\n            sampler.Iterate([&](const Info& info) {\n              oldest = std::max(oldest, absl::Now() - info.create_time);\n            });\n            ASSERT_GE(oldest, absl::ZeroDuration());\n            break;\n          }\n        }\n      }\n    });\n  }\n  // The threads will hammer away.  Give it a little bit of time for tsan to\n  // spot errors.\n  absl::SleepFor(absl::Seconds(3));\n  stop.Notify();\n}\n\nTEST(SampleRecorderTest, Callback) {\n  SampleRecorder<Info> sampler;\n\n  auto* info1 = Register(&sampler, 39, 1);\n  auto* info2 = Register(&sampler, 40, 2);\n\n  static const Info* expected;\n\n  auto callback = [](const Info& info) {\n    // We can't use `info` outside of this callback because the object will be\n    // disposed as soon as we return from here.\n    EXPECT_EQ(&info, expected);\n  };\n\n  // Set the callback.\n  EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr);\n  expected = info1;\n  sampler.Unregister(info1);\n\n  // Unset the callback.\n  EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr));\n  expected = nullptr;  // no more calls.\n  sampler.Unregister(info2);\n}\n\n}  // namespace\n}  // namespace profiling_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# ABSL random-number generation libraries.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"random\",\n    hdrs = [\"random.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":seed_sequences\",\n        \"//absl/base:config\",\n        \"//absl/random/internal:nonsecure_base\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:randen_engine\",\n    ],\n)\n\ncc_library(\n    name = \"distributions\",\n    srcs = [\n        \"discrete_distribution.cc\",\n        \"gaussian_distribution.cc\",\n    ],\n    hdrs = [\n        \"bernoulli_distribution.h\",\n        \"beta_distribution.h\",\n        \"discrete_distribution.h\",\n        \"distributions.h\",\n        \"exponential_distribution.h\",\n        \"gaussian_distribution.h\",\n        \"log_uniform_int_distribution.h\",\n        \"poisson_distribution.h\",\n        \"uniform_int_distribution.h\",\n        \"uniform_real_distribution.h\",\n        \"zipf_distribution.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:base_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n        \"//absl/random/internal:distribution_caller\",\n        \"//absl/random/internal:fast_uniform_bits\",\n        \"//absl/random/internal:fastmath\",\n        \"//absl/random/internal:generate_real\",\n        \"//absl/random/internal:iostream_state_saver\",\n        \"//absl/random/internal:traits\",\n        \"//absl/random/internal:uniform_helper\",\n        \"//absl/random/internal:wide_multiply\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_library(\n    name = \"seed_gen_exception\",\n    srcs = [\"seed_gen_exception.cc\"],\n    hdrs = [\"seed_gen_exception.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"seed_sequences\",\n    srcs = [\"seed_sequences.cc\"],\n    hdrs = [\n        \"seed_sequences.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":seed_gen_exception\",\n        \"//absl/base:config\",\n        \"//absl/base:nullability\",\n        \"//absl/random/internal:entropy_pool\",\n        \"//absl/random/internal:salted_seed_seq\",\n        \"//absl/random/internal:seed_material\",\n        \"//absl/strings:string_view\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"bit_gen_ref\",\n    hdrs = [\"bit_gen_ref.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":random\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/meta:type_traits\",\n        \"//absl/random/internal:distribution_caller\",\n        \"//absl/random/internal:fast_uniform_bits\",\n    ],\n)\n\ncc_library(\n    name = \"mock_distributions\",\n    testonly = True,\n    hdrs = [\"mock_distributions.h\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":mocking_bit_gen\",\n        \"//absl/base:config\",\n        \"//absl/random/internal:mock_overload_set\",\n        \"//absl/random/internal:mock_validators\",\n    ],\n)\n\ncc_library(\n    name = \"mocking_bit_gen\",\n    testonly = True,\n    hdrs = [\n        \"mocking_bit_gen.h\",\n    ],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":random\",\n        \"//absl/base:config\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/meta:type_traits\",\n        \"//absl/random/internal:mock_helpers\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"bernoulli_distribution_test\",\n    size = \"small\",\n    timeout = \"eternal\",  # Android can take a very long time\n    srcs = [\"bernoulli_distribution_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"beta_distribution_test\",\n    size = \"small\",\n    timeout = \"eternal\",  # Android can take a very long time\n    srcs = [\"beta_distribution_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/log\",\n        \"//absl/numeric:representation\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"distributions_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\n        \"distributions_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:int128\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"generators_test\",\n    size = \"small\",\n    srcs = [\"generators_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"log_uniform_int_distribution_test\",\n    size = \"medium\",\n    srcs = [\n        \"log_uniform_int_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",  # Does not converge on WASM.\n    ],\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/log\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"discrete_distribution_test\",\n    size = \"medium\",\n    srcs = [\n        \"discrete_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/log\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"poisson_distribution_test\",\n    size = \"small\",\n    timeout = \"eternal\",  # Android can take a very long time\n    srcs = [\n        \"poisson_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        # Too Slow.\n        \"no_test_android_arm\",\n        \"no_test_loonix\",\n    ],\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/log\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"exponential_distribution_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"exponential_distribution_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/base:core_headers\",\n        \"//absl/log\",\n        \"//absl/numeric:representation\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"gaussian_distribution_test\",\n    size = \"small\",\n    timeout = \"eternal\",  # Android can take a very long time\n    srcs = [\n        \"gaussian_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/base:core_headers\",\n        \"//absl/log\",\n        \"//absl/numeric:representation\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"uniform_int_distribution_test\",\n    size = \"medium\",\n    timeout = \"long\",\n    srcs = [\n        \"uniform_int_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/log\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"uniform_real_distribution_test\",\n    size = \"medium\",\n    srcs = [\n        \"uniform_real_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_android_arm\",\n        \"no_test_android_arm64\",\n        \"no_test_android_x86\",\n    ],\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/log\",\n        \"//absl/numeric:representation\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"zipf_distribution_test\",\n    size = \"medium\",\n    srcs = [\n        \"zipf_distribution_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/log\",\n        \"//absl/random/internal:distribution_test_util\",\n        \"//absl/random/internal:pcg_engine\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"bit_gen_ref_test\",\n    size = \"small\",\n    srcs = [\"bit_gen_ref_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":bit_gen_ref\",\n        \":random\",\n        \"//absl/base:config\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/random/internal:sequence_urbg\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"mocking_bit_gen_test\",\n    size = \"small\",\n    srcs = [\"mocking_bit_gen_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":bit_gen_ref\",\n        \":mock_distributions\",\n        \":mocking_bit_gen\",\n        \":random\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"mock_distributions_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"mock_distributions_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":distributions\",\n        \":mock_distributions\",\n        \":mocking_bit_gen\",\n        \":random\",\n        \"//absl/numeric:int128\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"examples_test\",\n    size = \"small\",\n    srcs = [\"examples_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":random\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"seed_sequences_test\",\n    size = \"small\",\n    srcs = [\"seed_sequences_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":random\",\n        \":seed_sequences\",\n        \"//absl/random/internal:nonsecure_base\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\n# Benchmarks for various methods / test utilities\ncc_binary(\n    name = \"benchmarks\",\n    testonly = True,\n    srcs = [\n        \"benchmarks.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":distributions\",\n        \":random\",\n        \"//absl/base:core_headers\",\n        \"//absl/random/internal:fast_uniform_bits\",\n        \"//absl/random/internal:randen_engine\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/random/CMakeLists.txt",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    random_random\n  HDRS\n    \"random.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::random_distributions\n    absl::random_internal_nonsecure_base\n    absl::random_internal_pcg_engine\n    absl::random_internal_randen_engine\n    absl::random_seed_sequences\n)\n\nabsl_cc_library(\n  NAME\n    random_bit_gen_ref\n  HDRS\n    \"bit_gen_ref.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::random_internal_distribution_caller\n    absl::random_internal_fast_uniform_bits\n    absl::type_traits\n)\n\nabsl_cc_test(\n  NAME\n    random_bit_gen_ref_test\n  SRCS\n    \"bit_gen_ref_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::random_bit_gen_ref\n    absl::random_random\n    absl::random_internal_sequence_urbg\n    absl::fast_type_id\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_mock_helpers\n  HDRS\n    \"internal/mock_helpers.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::fast_type_id\n    absl::optional\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_mock_overload_set\n  HDRS\n    \"internal/mock_overload_set.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::random_mocking_bit_gen\n    absl::random_internal_mock_helpers\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    random_mocking_bit_gen\n  HDRS\n    \"mock_distributions.h\"\n    \"mocking_bit_gen.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::fast_type_id\n    absl::flat_hash_map\n    absl::raw_logging_internal\n    absl::random_internal_mock_helpers\n    absl::random_random\n    absl::type_traits\n    absl::utility\n    GTest::gmock\n    GTest::gtest\n  PUBLIC\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    random_mock_distributions_test\n  SRCS\n    \"mock_distributions_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_distributions\n    absl::random_mocking_bit_gen\n    absl::random_random\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_mocking_bit_gen_test\n  SRCS\n    \"mocking_bit_gen_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_bit_gen_ref\n    absl::random_mocking_bit_gen\n    absl::random_random\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_library(\n  NAME\n    random_distributions\n  SRCS\n    \"discrete_distribution.cc\"\n    \"gaussian_distribution.cc\"\n  HDRS\n    \"bernoulli_distribution.h\"\n    \"beta_distribution.h\"\n    \"discrete_distribution.h\"\n    \"distributions.h\"\n    \"exponential_distribution.h\"\n    \"gaussian_distribution.h\"\n    \"log_uniform_int_distribution.h\"\n    \"poisson_distribution.h\"\n    \"uniform_int_distribution.h\"\n    \"uniform_real_distribution.h\"\n    \"zipf_distribution.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base_internal\n    absl::config\n    absl::core_headers\n    absl::random_internal_generate_real\n    absl::random_internal_distribution_caller\n    absl::random_internal_fast_uniform_bits\n    absl::random_internal_fastmath\n    absl::random_internal_iostream_state_saver\n    absl::random_internal_traits\n    absl::random_internal_uniform_helper\n    absl::random_internal_wide_multiply\n    absl::strings\n    absl::type_traits\n)\n\nabsl_cc_library(\n  NAME\n    random_seed_gen_exception\n  SRCS\n    \"seed_gen_exception.cc\"\n  HDRS\n    \"seed_gen_exception.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::raw_logging_internal\n)\n\nabsl_cc_library(\n  NAME\n    random_seed_sequences\n  SRCS\n    \"seed_sequences.cc\"\n  HDRS\n    \"seed_sequences.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::inlined_vector\n    absl::nullability\n    absl::random_internal_entropy_pool\n    absl::random_internal_salted_seed_seq\n    absl::random_internal_seed_material\n    absl::random_seed_gen_exception\n    absl::span\n    absl::string_view\n)\n\nabsl_cc_test(\n  NAME\n    random_bernoulli_distribution_test\n  SRCS\n    \"bernoulli_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_distributions\n    absl::random_random\n    absl::random_internal_sequence_urbg\n    absl::random_internal_pcg_engine\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_beta_distribution_test\n  SRCS\n    \"beta_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::numeric_representation\n    absl::random_distributions\n    absl::random_random\n    absl::random_internal_distribution_test_util\n    absl::random_internal_sequence_urbg\n    absl::random_internal_pcg_engine\n    absl::strings\n    absl::str_format\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_distributions_test\n  SRCS\n    \"distributions_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_distributions\n    absl::random_random\n    absl::type_traits\n    absl::int128\n    absl::random_internal_distribution_test_util\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_generators_test\n  SRCS\n    \"generators_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_distributions\n    absl::random_random\n    absl::raw_logging_internal\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_log_uniform_int_distribution_test\n  SRCS\n    \"log_uniform_int_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    absl::str_format\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_discrete_distribution_test\n  SRCS\n    \"discrete_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_poisson_distribution_test\n  SRCS\n    \"poisson_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_distributions\n    absl::random_random\n    absl::core_headers\n    absl::flat_hash_map\n    absl::log\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::strings\n    absl::str_format\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_exponential_distribution_test\n  SRCS\n    \"exponential_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::numeric_representation\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    absl::str_format\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_gaussian_distribution_test\n  SRCS\n    \"gaussian_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::log\n    absl::numeric_representation\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    absl::str_format\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_uniform_int_distribution_test\n  SRCS\n    \"uniform_int_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_uniform_real_distribution_test\n  SRCS\n    \"uniform_real_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::numeric_representation\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_zipf_distribution_test\n  SRCS\n    \"zipf_distribution_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::random_distributions\n    absl::random_internal_distribution_test_util\n    absl::random_internal_pcg_engine\n    absl::random_internal_sequence_urbg\n    absl::random_random\n    absl::strings\n    GTest::gmock\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_examples_test\n  SRCS\n    \"examples_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_random\n    GTest::gtest_main\n)\n\nabsl_cc_test(\n  NAME\n    random_seed_sequences_test\n  SRCS\n    \"seed_sequences_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_seed_sequences\n    absl::random_internal_nonsecure_base\n    absl::random_random\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_traits\n  HDRS\n    \"internal/traits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_distribution_caller\n  HDRS\n    \"internal/distribution_caller.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::utility\n    absl::fast_type_id\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_fast_uniform_bits\n  HDRS\n    \"internal/fast_uniform_bits.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_seed_material\n  SRCS\n    \"internal/seed_material.cc\"\n  HDRS\n    \"internal/seed_material.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n    $<$<BOOL:${MINGW}>:-lbcrypt>\n  DEPS\n    absl::config\n    absl::optional\n    absl::random_internal_fast_uniform_bits\n    absl::raw_logging_internal\n    absl::span\n    absl::strings\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_entropy_pool\n  SRCS\n    \"internal/entropy_pool.cc\"\n  HDRS\n    \"internal/entropy_pool.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::random_internal_platform\n    absl::random_internal_randen\n    absl::random_internal_seed_material\n    absl::random_seed_gen_exception\n    absl::span\n    absl::synchronization\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_explicit_seed_seq\n  HDRS\n      \"internal/random_internal_explicit_seed_seq.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::endian\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_sequence_urbg\n  HDRS\n    \"internal/sequence_urbg.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_salted_seed_seq\n  HDRS\n    \"internal/salted_seed_seq.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::inlined_vector\n    absl::optional\n    absl::span\n    absl::random_internal_seed_material\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_iostream_state_saver\n  HDRS\n    \"internal/iostream_state_saver.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::int128\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_generate_real\n  HDRS\n    \"internal/generate_real.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::bits\n    absl::random_internal_fastmath\n    absl::random_internal_traits\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_wide_multiply\n  HDRS\n    \"internal/wide_multiply.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::bits\n    absl::config\n    absl::int128\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_fastmath\n  HDRS\n    \"internal/fastmath.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::bits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_nonsecure_base\n  HDRS\n    \"internal/nonsecure_base.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::inlined_vector\n    absl::random_internal_entropy_pool\n    absl::random_internal_salted_seed_seq\n    absl::random_internal_seed_material\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_pcg_engine\n  HDRS\n    \"internal/pcg_engine.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::int128\n    absl::random_internal_fastmath\n    absl::random_internal_iostream_state_saver\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_randen_engine\n  HDRS\n    \"internal/randen_engine.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::endian\n    absl::random_internal_iostream_state_saver\n    absl::random_internal_randen\n    absl::raw_logging_internal\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_platform\n  HDRS\n    \"internal/randen_traits.h\"\n    \"internal/platform.h\"\n  SRCS\n    \"internal/randen_round_keys.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_randen\n  SRCS\n    \"internal/randen.cc\"\n  HDRS\n    \"internal/randen.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_platform\n    absl::random_internal_randen_hwaes\n    absl::random_internal_randen_slow\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_randen_slow\n  SRCS\n    \"internal/randen_slow.cc\"\n  HDRS\n    \"internal/randen_slow.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_platform\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_randen_hwaes\n  SRCS\n    \"internal/randen_detect.cc\"\n  HDRS\n    \"internal/randen_detect.h\"\n    \"internal/randen_hwaes.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n    ${ABSL_RANDOM_RANDEN_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_platform\n    absl::random_internal_randen_hwaes_impl\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_randen_hwaes_impl\n  SRCS\n    \"internal/randen_hwaes.cc\"\n    \"internal/randen_hwaes.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n    ${ABSL_RANDOM_RANDEN_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_platform\n    absl::config\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_distribution_test_util\n  SRCS\n    \"internal/chi_square.cc\"\n    \"internal/distribution_test_util.cc\"\n  HDRS\n    \"internal/chi_square.h\"\n    \"internal/distribution_test_util.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::strings\n    absl::str_format\n    absl::span\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_traits_test\n  SRCS\n    \"internal/traits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_traits\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_generate_real_test\n  SRCS\n    \"internal/generate_real_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::bits\n    absl::flags\n    absl::random_internal_generate_real\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_distribution_test_util_test\n  SRCS\n    \"internal/distribution_test_util_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_distribution_test_util\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_fastmath_test\n  SRCS\n    \"internal/fastmath_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_fastmath\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_explicit_seed_seq_test\n  SRCS\n    \"internal/explicit_seed_seq_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_explicit_seed_seq\n    absl::random_seed_sequences\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_salted_seed_seq_test\n  SRCS\n    \"internal/salted_seed_seq_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_salted_seed_seq\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_chi_square_test\n  SRCS\n    \"internal/chi_square_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::core_headers\n    absl::random_internal_distribution_test_util\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_fast_uniform_bits_test\n  SRCS\n    \"internal/fast_uniform_bits_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_fast_uniform_bits\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_nonsecure_base_test\n  SRCS\n    \"internal/nonsecure_base_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::flat_hash_map\n    absl::random_distributions\n    absl::random_internal_nonsecure_base\n    absl::random_random\n    absl::synchronization\n    absl::type_traits\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_seed_material_test\n  SRCS\n    \"internal/seed_material_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_seed_material\n    absl::span\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_entropy_pool_test\n  SRCS\n    \"internal/entropy_pool_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::flat_hash_map\n    absl::random_internal_entropy_pool\n    absl::synchronization\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_pcg_engine_test\n  SRCS\n    \"internal/pcg_engine_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_explicit_seed_seq\n    absl::random_internal_pcg_engine\n    absl::time\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_randen_engine_test\n  SRCS\n    \"internal/randen_engine_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::random_internal_explicit_seed_seq\n    absl::random_internal_randen_engine\n    absl::strings\n    absl::time\n    GTest::gmock\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_randen_test\n  SRCS\n    \"internal/randen_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_randen\n    absl::type_traits\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_randen_slow_test\n  SRCS\n    \"internal/randen_slow_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::endian\n    absl::random_internal_randen_slow\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_randen_hwaes_test\n  SRCS\n    \"internal/randen_hwaes_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::log\n    absl::random_internal_platform\n    absl::random_internal_randen_hwaes\n    absl::random_internal_randen_hwaes_impl\n    absl::str_format\n    GTest::gmock\n    GTest::gtest\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_uniform_helper\n  HDRS\n    \"internal/uniform_helper.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::config\n    absl::random_internal_traits\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    random_internal_mock_validators\n  HDRS\n    \"internal/mock_validators.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_iostream_state_saver\n    absl::random_internal_uniform_helper\n    absl::config\n    absl::raw_logging_internal\n    absl::strings\n    absl::string_view\n  TESTONLY\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_uniform_helper_test\n  SRCS\n    \"internal/uniform_helper_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_uniform_helper\n    GTest::gtest_main\n    absl::int128\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_iostream_state_saver_test\n  SRCS\n    \"internal/iostream_state_saver_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_iostream_state_saver\n    GTest::gtest_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_test(\n  NAME\n    random_internal_wide_multiply_test\n  SRCS\n      internal/wide_multiply_test.cc\n  COPTS\n    ${ABSL_TEST_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::random_internal_wide_multiply\n    absl::int128\n    GTest::gmock\n    GTest::gtest_main\n)\n"
  },
  {
    "path": "absl/random/benchmarks.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Benchmarks for absl random distributions as well as a selection of the\n// C++ standard library random distributions.\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <initializer_list>\n#include <iterator>\n#include <limits>\n#include <random>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/macros.h\"\n#include \"absl/random/bernoulli_distribution.h\"\n#include \"absl/random/beta_distribution.h\"\n#include \"absl/random/exponential_distribution.h\"\n#include \"absl/random/gaussian_distribution.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/randen_engine.h\"\n#include \"absl/random/log_uniform_int_distribution.h\"\n#include \"absl/random/poisson_distribution.h\"\n#include \"absl/random/random.h\"\n#include \"absl/random/uniform_int_distribution.h\"\n#include \"absl/random/uniform_real_distribution.h\"\n#include \"absl/random/zipf_distribution.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\n// Seed data to avoid reading random_device() for benchmarks.\nuint32_t kSeedData[] = {\n    0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,\n    0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6,\n    0xFF34052E, 0xC5855664, 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,\n    0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D,\n    0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A18FF, 0x5664526C, 0xC2B19EE1,\n    0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65,\n    0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,\n    0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9,\n    0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0x13198A2E, 0x03707344,\n};\n\n// PrecompiledSeedSeq provides kSeedData to a conforming\n// random engine to speed initialization in the benchmarks.\nclass PrecompiledSeedSeq {\n public:\n  using result_type = uint32_t;\n\n  PrecompiledSeedSeq() = default;\n\n  template <typename Iterator>\n  PrecompiledSeedSeq(Iterator, Iterator) {}\n\n  template <typename T>\n  PrecompiledSeedSeq(std::initializer_list<T>) {}\n\n  template <typename OutIterator>\n  void generate(OutIterator begin, OutIterator end) {\n    static size_t idx = 0;\n    for (; begin != end; begin++) {\n      *begin = kSeedData[idx++];\n      if (idx >= ABSL_ARRAYSIZE(kSeedData)) {\n        idx = 0;\n      }\n    }\n  }\n\n  size_t size() const { return ABSL_ARRAYSIZE(kSeedData); }\n\n  template <typename OutIterator>\n  void param(OutIterator out) const {\n    std::copy(std::begin(kSeedData), std::end(kSeedData), out);\n  }\n};\n\n// Triggers default constructor initialization.\nclass DefaultConstructorSeedSeq {};\n\n// make_engine<T, SSeq> returns a random_engine which is initialized,\n// either via the default constructor, when use_default_initialization<T>\n// is true, or via the indicated seed sequence, SSeq.\ntemplate <typename Engine, typename SSeq = DefaultConstructorSeedSeq>\nEngine make_engine() {\n  constexpr bool use_default_initialization =\n      std::is_same_v<SSeq, DefaultConstructorSeedSeq>;\n  if constexpr (use_default_initialization) {\n    return Engine();\n  } else {\n    // Otherwise, use the provided seed sequence.\n    SSeq seq(std::begin(kSeedData), std::end(kSeedData));\n    return Engine(seq);\n  }\n}\n\ntemplate <typename Engine, typename SSeq>\nvoid BM_Construct(benchmark::State& state) {\n  for (auto _ : state) {\n    auto rng = make_engine<Engine, SSeq>();\n    benchmark::DoNotOptimize(rng());\n  }\n}\n\ntemplate <typename Engine>\nvoid BM_Direct(benchmark::State& state) {\n  using value_type = typename Engine::result_type;\n  // Direct use of the URBG.\n  auto rng = make_engine<Engine>();\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(rng());\n  }\n  state.SetBytesProcessed(sizeof(value_type) * state.iterations());\n}\n\ntemplate <typename Engine>\nvoid BM_Generate(benchmark::State& state) {\n  // std::generate makes a copy of the RNG; thus this tests the\n  // copy-constructor efficiency.\n  using value_type = typename Engine::result_type;\n  std::vector<value_type> v(64);\n  auto rng = make_engine<Engine>();\n  while (state.KeepRunningBatch(64)) {\n    std::generate(std::begin(v), std::end(v), rng);\n  }\n}\n\ntemplate <typename Engine, size_t elems>\nvoid BM_Shuffle(benchmark::State& state) {\n  // Direct use of the Engine.\n  std::vector<uint32_t> v(elems);\n  while (state.KeepRunningBatch(elems)) {\n    auto rng = make_engine<Engine>();\n    std::shuffle(std::begin(v), std::end(v), rng);\n  }\n}\n\ntemplate <typename Engine, size_t elems>\nvoid BM_ShuffleReuse(benchmark::State& state) {\n  // Direct use of the Engine.\n  std::vector<uint32_t> v(elems);\n  auto rng = make_engine<Engine>();\n  while (state.KeepRunningBatch(elems)) {\n    std::shuffle(std::begin(v), std::end(v), rng);\n  }\n}\n\ntemplate <typename Engine, typename Dist, typename... Args>\nvoid BM_Dist(benchmark::State& state, Args&&... args) {\n  using value_type = typename Dist::result_type;\n  auto rng = make_engine<Engine>();\n  Dist dis{std::forward<Args>(args)...};\n  // Compare the following loop performance:\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(dis(rng));\n  }\n  state.SetBytesProcessed(sizeof(value_type) * state.iterations());\n}\n\ntemplate <typename Engine, typename Dist>\nvoid BM_Large(benchmark::State& state) {\n  using value_type = typename Dist::result_type;\n  volatile value_type kMin = 0;\n  volatile value_type kMax = std::numeric_limits<value_type>::max() / 2 + 1;\n  BM_Dist<Engine, Dist>(state, kMin, kMax);\n}\n\ntemplate <typename Engine, typename Dist>\nvoid BM_Small(benchmark::State& state) {\n  using value_type = typename Dist::result_type;\n  volatile value_type kMin = 0;\n  volatile value_type kMax = std::numeric_limits<value_type>::max() / 64 + 1;\n  BM_Dist<Engine, Dist>(state, kMin, kMax);\n}\n\ntemplate <typename Engine, typename Dist, int A>\nvoid BM_Bernoulli(benchmark::State& state) {\n  volatile double a = static_cast<double>(A) / 1000000;\n  BM_Dist<Engine, Dist>(state, a);\n}\n\ntemplate <typename Engine, typename Dist, int A, int B>\nvoid BM_Beta(benchmark::State& state) {\n  using value_type = typename Dist::result_type;\n  volatile value_type a = static_cast<value_type>(A) / 100;\n  volatile value_type b = static_cast<value_type>(B) / 100;\n  BM_Dist<Engine, Dist>(state, a, b);\n}\n\ntemplate <typename Engine, typename Dist, int A>\nvoid BM_Gamma(benchmark::State& state) {\n  using value_type = typename Dist::result_type;\n  volatile value_type a = static_cast<value_type>(A) / 100;\n  BM_Dist<Engine, Dist>(state, a);\n}\n\ntemplate <typename Engine, typename Dist, int A = 100>\nvoid BM_Poisson(benchmark::State& state) {\n  volatile double a = static_cast<double>(A) / 100;\n  BM_Dist<Engine, Dist>(state, a);\n}\n\ntemplate <typename Engine, typename Dist, int Q = 2, int V = 1>\nvoid BM_Zipf(benchmark::State& state) {\n  using value_type = typename Dist::result_type;\n  volatile double q = Q;\n  volatile double v = V;\n  BM_Dist<Engine, Dist>(state, std::numeric_limits<value_type>::max(), q, v);\n}\n\ntemplate <typename Engine, typename Dist>\nvoid BM_Thread(benchmark::State& state) {\n  using value_type = typename Dist::result_type;\n  auto rng = make_engine<Engine>();\n  Dist dis{};\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(dis(rng));\n  }\n  state.SetBytesProcessed(sizeof(value_type) * state.iterations());\n}\n\n// NOTES:\n//\n// std::geometric_distribution is similar to the zipf distributions.\n// The algorithm for the geometric_distribution is, basically,\n// floor(log(1-X) / log(1-p))\n\n// Normal benchmark suite\n#define BM_BASIC(Engine)                                                       \\\n  BENCHMARK_TEMPLATE(BM_Construct, Engine, DefaultConstructorSeedSeq);         \\\n  BENCHMARK_TEMPLATE(BM_Construct, Engine, PrecompiledSeedSeq);                \\\n  BENCHMARK_TEMPLATE(BM_Construct, Engine, std::seed_seq);                     \\\n  BENCHMARK_TEMPLATE(BM_Direct, Engine);                                       \\\n  BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 10);                                  \\\n  BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 100);                                 \\\n  BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 1000);                                \\\n  BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 100);                            \\\n  BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 1000);                           \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine,                                          \\\n                     absl::random_internal::FastUniformBits<uint32_t>);        \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine,                                          \\\n                     absl::random_internal::FastUniformBits<uint64_t>);        \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_int_distribution<int32_t>); \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_int_distribution<int64_t>); \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine,                                          \\\n                     absl::uniform_int_distribution<int32_t>);                 \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine,                                          \\\n                     absl::uniform_int_distribution<int64_t>);                 \\\n  BENCHMARK_TEMPLATE(BM_Large, Engine,                                         \\\n                     std::uniform_int_distribution<int32_t>);                  \\\n  BENCHMARK_TEMPLATE(BM_Large, Engine,                                         \\\n                     std::uniform_int_distribution<int64_t>);                  \\\n  BENCHMARK_TEMPLATE(BM_Large, Engine,                                         \\\n                     absl::uniform_int_distribution<int32_t>);                 \\\n  BENCHMARK_TEMPLATE(BM_Large, Engine,                                         \\\n                     absl::uniform_int_distribution<int64_t>);                 \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_real_distribution<float>);  \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_real_distribution<double>); \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::uniform_real_distribution<float>); \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::uniform_real_distribution<double>)\n\n#define BM_COPY(Engine) BENCHMARK_TEMPLATE(BM_Generate, Engine)\n\n#define BM_THREAD(Engine)                                           \\\n  BENCHMARK_TEMPLATE(BM_Thread, Engine,                             \\\n                     absl::uniform_int_distribution<int64_t>)       \\\n      ->ThreadPerCpu();                                             \\\n  BENCHMARK_TEMPLATE(BM_Thread, Engine,                             \\\n                     absl::uniform_real_distribution<double>)       \\\n      ->ThreadPerCpu();                                             \\\n  BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 100)->ThreadPerCpu();      \\\n  BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 1000)->ThreadPerCpu();     \\\n  BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 100)->ThreadPerCpu(); \\\n  BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 1000)->ThreadPerCpu()\n\n#define BM_EXTENDED(Engine)                                                    \\\n  /* -------------- Extended Uniform -----------------------*/                 \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     std::uniform_int_distribution<int32_t>);                  \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     std::uniform_int_distribution<int64_t>);                  \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     absl::uniform_int_distribution<int32_t>);                 \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     absl::uniform_int_distribution<int64_t>);                 \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine, std::uniform_real_distribution<float>); \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     std::uniform_real_distribution<double>);                  \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     absl::uniform_real_distribution<float>);                  \\\n  BENCHMARK_TEMPLATE(BM_Small, Engine,                                         \\\n                     absl::uniform_real_distribution<double>);                 \\\n  /* -------------- Other -----------------------*/                            \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::normal_distribution<double>);       \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::gaussian_distribution<double>);    \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::exponential_distribution<double>);  \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::exponential_distribution<double>); \\\n  BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>,   \\\n                     100);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>,  \\\n                     100);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>,   \\\n                     10 * 100);                                                \\\n  BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>,  \\\n                     10 * 100);                                                \\\n  BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>,   \\\n                     13 * 100);                                                \\\n  BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>,  \\\n                     13 * 100);                                                \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine,                                          \\\n                     absl::log_uniform_int_distribution<int32_t>);             \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine,                                          \\\n                     absl::log_uniform_int_distribution<int64_t>);             \\\n  BENCHMARK_TEMPLATE(BM_Dist, Engine, std::geometric_distribution<int64_t>);   \\\n  BENCHMARK_TEMPLATE(BM_Zipf, Engine, absl::zipf_distribution<uint64_t>);      \\\n  BENCHMARK_TEMPLATE(BM_Zipf, Engine, absl::zipf_distribution<uint64_t>, 2,    \\\n                     3);                                                       \\\n  BENCHMARK_TEMPLATE(BM_Bernoulli, Engine, std::bernoulli_distribution,        \\\n                     257305);                                                  \\\n  BENCHMARK_TEMPLATE(BM_Bernoulli, Engine, absl::bernoulli_distribution,       \\\n                     257305);                                                  \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 65,     \\\n                     41);                                                      \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 99,     \\\n                     330);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 150,    \\\n                     150);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 410,    \\\n                     580);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 65, 41); \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 99,      \\\n                     330);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 150,     \\\n                     150);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 410,     \\\n                     580);                                                     \\\n  BENCHMARK_TEMPLATE(BM_Gamma, Engine, std::gamma_distribution<float>, 199);   \\\n  BENCHMARK_TEMPLATE(BM_Gamma, Engine, std::gamma_distribution<double>, 199)\n\n// ABSL Recommended interfaces.\nBM_BASIC(absl::InsecureBitGen);  // === pcg64_2018_engine\nBM_BASIC(absl::BitGen);          // === randen_engine<uint64_t>.\nBM_THREAD(absl::BitGen);\nBM_EXTENDED(absl::BitGen);\n\n// Instantiate benchmarks for multiple engines.\nusing randen_engine_64 = absl::random_internal::randen_engine<uint64_t>;\nusing randen_engine_32 = absl::random_internal::randen_engine<uint32_t>;\n\n// Comparison interfaces.\nBM_BASIC(std::mt19937_64);\nBM_COPY(std::mt19937_64);\nBM_EXTENDED(std::mt19937_64);\nBM_BASIC(randen_engine_64);\nBM_COPY(randen_engine_64);\nBM_EXTENDED(randen_engine_64);\n\nBM_BASIC(std::mt19937);\nBM_COPY(std::mt19937);\nBM_BASIC(randen_engine_32);\nBM_COPY(randen_engine_32);\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/bernoulli_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_\n#define ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cstdint>\n#include <istream>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::bernoulli_distribution is a drop in replacement for\n// std::bernoulli_distribution. It guarantees that (given a perfect\n// UniformRandomBitGenerator) the acceptance probability is *exactly* equal to\n// the given double.\n//\n// The implementation assumes that double is IEEE754\nclass bernoulli_distribution {\n public:\n  using result_type = bool;\n\n  class param_type {\n   public:\n    using distribution_type = bernoulli_distribution;\n\n    explicit param_type(double p = 0.5) : prob_(p) {\n      assert(p >= 0.0 && p <= 1.0);\n    }\n\n    double p() const { return prob_; }\n\n    friend bool operator==(const param_type& p1, const param_type& p2) {\n      return p1.p() == p2.p();\n    }\n    friend bool operator!=(const param_type& p1, const param_type& p2) {\n      return p1.p() != p2.p();\n    }\n\n   private:\n    double prob_;\n  };\n\n  bernoulli_distribution() : bernoulli_distribution(0.5) {}\n\n  explicit bernoulli_distribution(double p) : param_(p) {}\n\n  explicit bernoulli_distribution(param_type p) : param_(p) {}\n\n  // no-op\n  void reset() {}\n\n  template <typename URBG>\n  bool operator()(URBG& g) {  // NOLINT(runtime/references)\n    return Generate(param_.p(), g);\n  }\n\n  template <typename URBG>\n  bool operator()(URBG& g,  // NOLINT(runtime/references)\n                  const param_type& param) {\n    return Generate(param.p(), g);\n  }\n\n  param_type param() const { return param_; }\n  void param(const param_type& param) { param_ = param; }\n\n  double p() const { return param_.p(); }\n\n  result_type(min)() const { return false; }\n  result_type(max)() const { return true; }\n\n  friend bool operator==(const bernoulli_distribution& d1,\n                         const bernoulli_distribution& d2) {\n    return d1.param_ == d2.param_;\n  }\n\n  friend bool operator!=(const bernoulli_distribution& d1,\n                         const bernoulli_distribution& d2) {\n    return d1.param_ != d2.param_;\n  }\n\n private:\n  static constexpr uint64_t kP32 = static_cast<uint64_t>(1) << 32;\n\n  template <typename URBG>\n  static bool Generate(double p, URBG& g);  // NOLINT(runtime/references)\n\n  param_type param_;\n};\n\ntemplate <typename CharT, typename Traits>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const bernoulli_distribution& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<double>::kPrecision);\n  os << x.p();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    bernoulli_distribution& x) {            // NOLINT(runtime/references)\n  auto saver = random_internal::make_istream_state_saver(is);\n  auto p = random_internal::read_floating_point<double>(is);\n  if (!is.fail()) {\n    x.param(bernoulli_distribution::param_type(p));\n  }\n  return is;\n}\n\ntemplate <typename URBG>\nbool bernoulli_distribution::Generate(double p,\n                                      URBG& g) {  // NOLINT(runtime/references)\n  random_internal::FastUniformBits<uint32_t> fast_u32;\n\n  while (true) {\n    // There are two aspects of the definition of `c` below that are worth\n    // commenting on.  First, because `p` is in the range [0, 1], `c` is in the\n    // range [0, 2^32] which does not fit in a uint32_t and therefore requires\n    // 64 bits.\n    //\n    // Second, `c` is constructed by first casting explicitly to a signed\n    // integer and then casting explicitly to an unsigned integer of the same\n    // size.  This is done because the hardware conversion instructions produce\n    // signed integers from double; if taken as a uint64_t the conversion would\n    // be wrong for doubles greater than 2^63 (not relevant in this use-case).\n    // If converted directly to an unsigned integer, the compiler would end up\n    // emitting code to handle such large values that are not relevant due to\n    // the known bounds on `c`.  To avoid these extra instructions this\n    // implementation converts first to the signed type and then convert to\n    // unsigned (which is a no-op).\n    const uint64_t c = static_cast<uint64_t>(static_cast<int64_t>(p * kP32));\n    const uint32_t v = fast_u32(g);\n    // FAST PATH: this path fails with probability 1/2^32.  Note that simply\n    // returning v <= c would approximate P very well (up to an absolute error\n    // of 1/2^32); the slow path (taken in that range of possible error, in the\n    // case of equality) eliminates the remaining error.\n    if (ABSL_PREDICT_TRUE(v != c)) return v < c;\n\n    // It is guaranteed that `q` is strictly less than 1, because if `q` were\n    // greater than or equal to 1, the same would be true for `p`. Certainly `p`\n    // cannot be greater than 1, and if `p == 1`, then the fast path would\n    // necessary have been taken already.\n    const double q = static_cast<double>(c) / kP32;\n\n    // The probability of acceptance on the fast path is `q` and so the\n    // probability of acceptance here should be `p - q`.\n    //\n    // Note that `q` is obtained from `p` via some shifts and conversions, the\n    // upshot of which is that `q` is simply `p` with some of the\n    // least-significant bits of its mantissa set to zero. This means that the\n    // difference `p - q` will not have any rounding errors. To see why, pretend\n    // that double has 10 bits of resolution and q is obtained from `p` in such\n    // a way that the 4 least-significant bits of its mantissa are set to zero.\n    // For example:\n    //   p   = 1.1100111011 * 2^-1\n    //   q   = 1.1100110000 * 2^-1\n    // p - q = 1.011        * 2^-8\n    // The difference `p - q` has exactly the nonzero mantissa bits that were\n    // \"lost\" in `q` producing a number which is certainly representable in a\n    // double.\n    const double left = p - q;\n\n    // By construction, the probability of being on this slow path is 1/2^32, so\n    // P(accept in slow path) = P(accept| in slow path) * P(slow path),\n    // which means the probability of acceptance here is `1 / (left * kP32)`:\n    const double here = left * kP32;\n\n    // The simplest way to compute the result of this trial is to repeat the\n    // whole algorithm with the new probability. This terminates because even\n    // given  arbitrarily unfriendly \"random\" bits, each iteration either\n    // multiplies a tiny probability by 2^32 (if c == 0) or strips off some\n    // number of nonzero mantissa bits. That process is bounded.\n    if (here == 0) return false;\n    p = here;\n  }\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/bernoulli_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/bernoulli_distribution.h\"\n\n#include <cmath>\n#include <cstddef>\n#include <random>\n#include <sstream>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n\nnamespace {\n\nclass BernoulliTest : public testing::TestWithParam<std::pair<double, size_t>> {\n};\n\nTEST_P(BernoulliTest, Serialize) {\n  const double d = GetParam().first;\n  absl::bernoulli_distribution before(d);\n\n  {\n    absl::bernoulli_distribution via_param{\n        absl::bernoulli_distribution::param_type(d)};\n    EXPECT_EQ(via_param, before);\n  }\n\n  std::stringstream ss;\n  ss << before;\n  absl::bernoulli_distribution after(0.6789);\n\n  EXPECT_NE(before.p(), after.p());\n  EXPECT_NE(before.param(), after.param());\n  EXPECT_NE(before, after);\n\n  ss >> after;\n\n  EXPECT_EQ(before.p(), after.p());\n  EXPECT_EQ(before.param(), after.param());\n  EXPECT_EQ(before, after);\n}\n\nTEST_P(BernoulliTest, Accuracy) {\n  // Sadly, the claim to fame for this implementation is precise accuracy, which\n  // is very, very hard to measure, the improvements come as trials approach the\n  // limit of double accuracy; thus the outcome differs from the\n  // std::bernoulli_distribution with a probability of approximately 1 in 2^-53.\n  const std::pair<double, size_t> para = GetParam();\n  size_t trials = para.second;\n  double p = para.first;\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);\n\n  size_t yes = 0;\n  absl::bernoulli_distribution dist(p);\n  for (size_t i = 0; i < trials; ++i) {\n    if (dist(rng)) yes++;\n  }\n\n  // Compute the distribution parameters for a binomial test, using a normal\n  // approximation for the confidence interval, as there are a sufficiently\n  // large number of trials that the central limit theorem applies.\n  const double stddev_p = std::sqrt((p * (1.0 - p)) / trials);\n  const double expected = trials * p;\n  const double stddev = trials * stddev_p;\n\n  // 5 sigma, approved by Richard Feynman\n  EXPECT_NEAR(yes, expected, 5 * stddev)\n      << \"@\" << p << \", \"\n      << std::abs(static_cast<double>(yes) - expected) / stddev << \" stddev\";\n}\n\n// There must be many more trials to make the mean approximately normal for `p`\n// closes to 0 or 1.\nINSTANTIATE_TEST_SUITE_P(\n    All, BernoulliTest,\n    ::testing::Values(\n        // Typical values.\n        std::make_pair(0, 30000), std::make_pair(1e-3, 30000000),\n        std::make_pair(0.1, 3000000), std::make_pair(0.5, 3000000),\n        std::make_pair(0.9, 30000000), std::make_pair(0.999, 30000000),\n        std::make_pair(1, 30000),\n        // Boundary cases.\n        std::make_pair(std::nextafter(1.0, 0.0), 1),  // ~1 - epsilon\n        std::make_pair(std::numeric_limits<double>::epsilon(), 1),\n        std::make_pair(std::nextafter(std::numeric_limits<double>::min(),\n                                      1.0),  // min + epsilon\n                       1),\n        std::make_pair(std::numeric_limits<double>::min(),  // smallest normal\n                       1),\n        std::make_pair(\n            std::numeric_limits<double>::denorm_min(),  // smallest denorm\n            1),\n        std::make_pair(std::numeric_limits<double>::min() / 2, 1),  // denorm\n        std::make_pair(std::nextafter(std::numeric_limits<double>::min(),\n                                      0.0),  // denorm_max\n                       1)));\n\n// NOTE: absl::bernoulli_distribution is not guaranteed to be stable.\nTEST(BernoulliTest, StabilityTest) {\n  // absl::bernoulli_distribution stability relies on FastUniformBits and\n  // integer arithmetic.\n  absl::random_internal::sequence_urbg urbg({\n      0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n      0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n      0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n      0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull,\n      0x4864f22c059bf29eull, 0x247856d8b862665cull, 0xe46e86e9a1337e10ull,\n      0xd8c8541f3519b133ull, 0xe75b5162c567b9e4ull, 0xf732e5ded7009c5bull,\n      0xb170b98353121eacull, 0x1ec2e8986d2362caull, 0x814c8e35fe9a961aull,\n      0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, 0x1224e62c978bbc7full,\n      0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, 0x1bbc23cfa8fac721ull,\n      0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, 0x836d794457c08849ull,\n      0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, 0xb12d74fdd718c8c5ull,\n      0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, 0x5738341045ba0d85ull,\n      0xe3fd722dc65ad09eull, 0x5a14fd21ea2a5705ull, 0x14e6ea4d6edb0c73ull,\n      0x275b0dc7e0a18acfull, 0x36cebe0d2653682eull, 0x0361e9b23861596bull,\n  });\n\n  // Generate a string of '0' and '1' for the distribution output.\n  auto generate = [&urbg](absl::bernoulli_distribution& dist) {\n    std::string output;\n    output.reserve(36);\n    urbg.reset();\n    for (int i = 0; i < 35; i++) {\n      output.append(dist(urbg) ? \"1\" : \"0\");\n    }\n    return output;\n  };\n\n  const double kP = 0.0331289862362;\n  {\n    absl::bernoulli_distribution dist(kP);\n    auto v = generate(dist);\n    EXPECT_EQ(35, urbg.invocations());\n    EXPECT_EQ(v, \"00000000000010000000000010000000000\") << dist;\n  }\n  {\n    absl::bernoulli_distribution dist(kP * 10.0);\n    auto v = generate(dist);\n    EXPECT_EQ(35, urbg.invocations());\n    EXPECT_EQ(v, \"00000100010010010010000011000011010\") << dist;\n  }\n  {\n    absl::bernoulli_distribution dist(kP * 20.0);\n    auto v = generate(dist);\n    EXPECT_EQ(35, urbg.invocations());\n    EXPECT_EQ(v, \"00011110010110110011011111110111011\") << dist;\n  }\n  {\n    absl::bernoulli_distribution dist(1.0 - kP);\n    auto v = generate(dist);\n    EXPECT_EQ(35, urbg.invocations());\n    EXPECT_EQ(v, \"11111111111111111111011111111111111\") << dist;\n  }\n}\n\nTEST(BernoulliTest, StabilityTest2) {\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  // Generate a string of '0' and '1' for the distribution output.\n  auto generate = [&urbg](absl::bernoulli_distribution& dist) {\n    std::string output;\n    output.reserve(13);\n    urbg.reset();\n    for (int i = 0; i < 12; i++) {\n      output.append(dist(urbg) ? \"1\" : \"0\");\n    }\n    return output;\n  };\n\n  constexpr double b0 = 1.0 / 13.0 / 0.2;\n  constexpr double b1 = 2.0 / 13.0 / 0.2;\n  constexpr double b3 = (5.0 / 13.0 / 0.2) - ((1 - b0) + (1 - b1) + (1 - b1));\n  {\n    absl::bernoulli_distribution dist(b0);\n    auto v = generate(dist);\n    EXPECT_EQ(12, urbg.invocations());\n    EXPECT_EQ(v, \"000011100101\") << dist;\n  }\n  {\n    absl::bernoulli_distribution dist(b1);\n    auto v = generate(dist);\n    EXPECT_EQ(12, urbg.invocations());\n    EXPECT_EQ(v, \"001111101101\") << dist;\n  }\n  {\n    absl::bernoulli_distribution dist(b3);\n    auto v = generate(dist);\n    EXPECT_EQ(12, urbg.invocations());\n    EXPECT_EQ(v, \"001111101111\") << dist;\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/beta_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_BETA_DISTRIBUTION_H_\n#define ABSL_RANDOM_BETA_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cmath>\n#include <cstdint>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/generate_real.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::beta_distribution:\n// Generate a floating-point variate conforming to a Beta distribution:\n//   pdf(x) \\propto x^(alpha-1) * (1-x)^(beta-1),\n// where the params alpha and beta are both strictly positive real values.\n//\n// The support is the open interval (0, 1), but the return value might be equal\n// to 0 or 1, due to numerical errors when alpha and beta are very different.\n//\n// Usage note: One usage is that alpha and beta are counts of number of\n// successes and failures. When the total number of trials are large, consider\n// approximating a beta distribution with a Gaussian distribution with the same\n// mean and variance. One could use the skewness, which depends only on the\n// smaller of alpha and beta when the number of trials are sufficiently large,\n// to quantify how far a beta distribution is from the normal distribution.\ntemplate <typename RealType = double>\nclass beta_distribution {\n public:\n  using result_type = RealType;\n\n  class param_type {\n   public:\n    using distribution_type = beta_distribution;\n\n    explicit param_type(result_type alpha, result_type beta)\n        : alpha_(alpha), beta_(beta) {\n      assert(alpha >= 0);\n      assert(beta >= 0);\n      assert(alpha <= (std::numeric_limits<result_type>::max)());\n      assert(beta <= (std::numeric_limits<result_type>::max)());\n      if (alpha == 0 || beta == 0) {\n        method_ = DEGENERATE_SMALL;\n        x_ = (alpha >= beta) ? 1 : 0;\n        return;\n      }\n      // a_ = min(beta, alpha), b_ = max(beta, alpha).\n      if (beta < alpha) {\n        inverted_ = true;\n        a_ = beta;\n        b_ = alpha;\n      } else {\n        inverted_ = false;\n        a_ = alpha;\n        b_ = beta;\n      }\n      if (a_ <= 1 && b_ >= ThresholdForLargeA()) {\n        method_ = DEGENERATE_SMALL;\n        x_ = inverted_ ? result_type(1) : result_type(0);\n        return;\n      }\n      // For threshold values, see also:\n      // Evaluation of Beta Generation Algorithms, Ying-Chao Hung, et. al.\n      // February, 2009.\n      if ((b_ < 1.0 && a_ + b_ <= 1.2) || a_ <= ThresholdForSmallA()) {\n        // Choose Joehnk over Cheng when it's faster or when Cheng encounters\n        // numerical issues.\n        method_ = JOEHNK;\n        a_ = result_type(1) / alpha_;\n        b_ = result_type(1) / beta_;\n        if (std::isinf(a_) || std::isinf(b_)) {\n          method_ = DEGENERATE_SMALL;\n          x_ = inverted_ ? result_type(1) : result_type(0);\n        }\n        return;\n      }\n      if (a_ >= ThresholdForLargeA()) {\n        method_ = DEGENERATE_LARGE;\n        // Note: on PPC for long double, evaluating\n        // `std::numeric_limits::max() / ThresholdForLargeA` results in NaN.\n        result_type r = a_ / b_;\n        x_ = (inverted_ ? result_type(1) : r) / (1 + r);\n        return;\n      }\n      x_ = a_ + b_;\n      log_x_ = std::log(x_);\n      if (a_ <= 1) {\n        method_ = CHENG_BA;\n        y_ = result_type(1) / a_;\n        gamma_ = a_ + a_;\n        return;\n      }\n      method_ = CHENG_BB;\n      result_type r = (a_ - 1) / (b_ - 1);\n      y_ = std::sqrt((1 + r) / (b_ * r * 2 - r + 1));\n      gamma_ = a_ + result_type(1) / y_;\n    }\n\n    result_type alpha() const { return alpha_; }\n    result_type beta() const { return beta_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.alpha_ == b.alpha_ && a.beta_ == b.beta_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class beta_distribution;\n\n#ifdef _MSC_VER\n    // MSVC does not have constexpr implementations for std::log and std::exp\n    // so they are computed at runtime.\n#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR\n#else\n#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR constexpr\n#endif\n\n    // The threshold for whether std::exp(1/a) is finite.\n    // Note that this value is quite large, and a smaller a_ is NOT abnormal.\n    static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type\n    ThresholdForSmallA() {\n      return result_type(1) /\n             std::log((std::numeric_limits<result_type>::max)());\n    }\n\n    // The threshold for whether a * std::log(a) is finite.\n    static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type\n    ThresholdForLargeA() {\n      return std::exp(\n          std::log((std::numeric_limits<result_type>::max)()) -\n          std::log(std::log((std::numeric_limits<result_type>::max)())) -\n          ThresholdPadding());\n    }\n\n#undef ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR\n\n    // Pad the threshold for large A for long double on PPC. This is done via a\n    // template specialization below.\n    static constexpr result_type ThresholdPadding() { return 0; }\n\n    enum Method {\n      JOEHNK,    // Uses algorithm Joehnk\n      CHENG_BA,  // Uses algorithm BA in Cheng\n      CHENG_BB,  // Uses algorithm BB in Cheng\n\n      // Note: See also:\n      //   Hung et al. Evaluation of beta generation algorithms. Communications\n      //   in Statistics-Simulation and Computation 38.4 (2009): 750-770.\n      // especially:\n      //   Zechner, Heinz, and Ernst Stadlober. Generating beta variates via\n      //   patchwork rejection. Computing 50.1 (1993): 1-18.\n\n      DEGENERATE_SMALL,  // a_ is abnormally small.\n      DEGENERATE_LARGE,  // a_ is abnormally large.\n    };\n\n    result_type alpha_;\n    result_type beta_;\n\n    result_type a_{};  // the smaller of {alpha, beta}, or 1.0/alpha_ in JOEHNK\n    result_type b_{};  // the larger of {alpha, beta}, or 1.0/beta_ in JOEHNK\n    result_type x_{};  // alpha + beta, or the result in degenerate cases\n    result_type log_x_{};  // log(x_)\n    result_type y_{};      // \"beta\" in Cheng\n    result_type gamma_{};  // \"gamma\" in Cheng\n\n    Method method_{};\n\n    // Placing this last for optimal alignment.\n    // Whether alpha_ != a_, i.e. true iff alpha_ > beta_.\n    bool inverted_{};\n\n    static_assert(std::is_floating_point<RealType>::value,\n                  \"Class-template absl::beta_distribution<> must be \"\n                  \"parameterized using a floating-point type.\");\n  };\n\n  beta_distribution() : beta_distribution(1) {}\n\n  explicit beta_distribution(result_type alpha, result_type beta = 1)\n      : param_(alpha, beta) {}\n\n  explicit beta_distribution(const param_type& p) : param_(p) {}\n\n  void reset() {}\n\n  // Generating functions\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  param_type param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  result_type(min)() const { return 0; }\n  result_type(max)() const { return 1; }\n\n  result_type alpha() const { return param_.alpha(); }\n  result_type beta() const { return param_.beta(); }\n\n  friend bool operator==(const beta_distribution& a,\n                         const beta_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const beta_distribution& a,\n                         const beta_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  template <typename URBG>\n  result_type AlgorithmJoehnk(URBG& g,  // NOLINT(runtime/references)\n                              const param_type& p);\n\n  template <typename URBG>\n  result_type AlgorithmCheng(URBG& g,  // NOLINT(runtime/references)\n                             const param_type& p);\n\n  template <typename URBG>\n  result_type DegenerateCase(URBG& g,  // NOLINT(runtime/references)\n                             const param_type& p) {\n    if (p.method_ == param_type::DEGENERATE_SMALL && p.alpha_ == p.beta_) {\n      // Returns 0 or 1 with equal probability.\n      random_internal::FastUniformBits<uint8_t> fast_u8;\n      return static_cast<result_type>((fast_u8(g) & 0x10) !=\n                                      0);  // pick any single bit.\n    }\n    return p.x_;\n  }\n\n  param_type param_;\n  random_internal::FastUniformBits<uint64_t> fast_u64_;\n};\n\n#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \\\n    defined(__ppc__) || defined(__PPC__)\n// PPC needs a more stringent boundary for long double.\ntemplate <>\nconstexpr long double\nbeta_distribution<long double>::param_type::ThresholdPadding() {\n  return 10;\n}\n#endif\n\ntemplate <typename RealType>\ntemplate <typename URBG>\ntypename beta_distribution<RealType>::result_type\nbeta_distribution<RealType>::AlgorithmJoehnk(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  using random_internal::GeneratePositiveTag;\n  using random_internal::GenerateRealFromBits;\n  using real_type =\n      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;\n\n  // Based on Joehnk, M. D. Erzeugung von betaverteilten und gammaverteilten\n  // Zufallszahlen. Metrika 8.1 (1964): 5-15.\n  // This method is described in Knuth, Vol 2 (Third Edition), pp 134.\n\n  result_type u, v, x, y, z;\n  for (;;) {\n    u = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(\n        fast_u64_(g));\n    v = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(\n        fast_u64_(g));\n\n    // Direct method. std::pow is slow for float, so rely on the optimizer to\n    // remove the std::pow() path for that case.\n    if (!std::is_same<float, result_type>::value) {\n      x = std::pow(u, p.a_);\n      y = std::pow(v, p.b_);\n      z = x + y;\n      if (z > 1) {\n        // Reject if and only if `x + y > 1.0`\n        continue;\n      }\n      if (z > 0) {\n        // When both alpha and beta are small, x and y are both close to 0, so\n        // divide by (x+y) directly may result in nan.\n        return x / z;\n      }\n    }\n\n    // Log transform.\n    // x = log( pow(u, p.a_) ), y = log( pow(v, p.b_) )\n    // since u, v <= 1.0,  x, y < 0.\n    x = std::log(u) * p.a_;\n    y = std::log(v) * p.b_;\n    if (!std::isfinite(x) || !std::isfinite(y)) {\n      continue;\n    }\n    // z = log( pow(u, a) + pow(v, b) )\n    z = x > y ? (x + std::log(1 + std::exp(y - x)))\n              : (y + std::log(1 + std::exp(x - y)));\n    // Reject iff log(x+y) > 0.\n    if (z > 0) {\n      continue;\n    }\n    return std::exp(x - z);\n  }\n}\n\ntemplate <typename RealType>\ntemplate <typename URBG>\ntypename beta_distribution<RealType>::result_type\nbeta_distribution<RealType>::AlgorithmCheng(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  using random_internal::GeneratePositiveTag;\n  using random_internal::GenerateRealFromBits;\n  using real_type =\n      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;\n\n  // Based on Cheng, Russell CH. Generating beta variates with nonintegral\n  // shape parameters. Communications of the ACM 21.4 (1978): 317-322.\n  // (https://dl.acm.org/citation.cfm?id=359482).\n  static constexpr result_type kLogFour =\n      result_type(1.3862943611198906188344642429163531361);  // log(4)\n  static constexpr result_type kS =\n      result_type(2.6094379124341003746007593332261876);  // 1+log(5)\n\n  const bool use_algorithm_ba = (p.method_ == param_type::CHENG_BA);\n  result_type u1, u2, v, w, z, r, s, t, bw_inv, lhs;\n  for (;;) {\n    u1 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(\n        fast_u64_(g));\n    u2 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(\n        fast_u64_(g));\n    v = p.y_ * std::log(u1 / (1 - u1));\n    w = p.a_ * std::exp(v);\n    bw_inv = result_type(1) / (p.b_ + w);\n    r = p.gamma_ * v - kLogFour;\n    s = p.a_ + r - w;\n    z = u1 * u1 * u2;\n    if (!use_algorithm_ba && s + kS >= 5 * z) {\n      break;\n    }\n    t = std::log(z);\n    if (!use_algorithm_ba && s >= t) {\n      break;\n    }\n    lhs = p.x_ * (p.log_x_ + std::log(bw_inv)) + r;\n    if (lhs >= t) {\n      break;\n    }\n  }\n  return p.inverted_ ? (1 - w * bw_inv) : w * bw_inv;\n}\n\ntemplate <typename RealType>\ntemplate <typename URBG>\ntypename beta_distribution<RealType>::result_type\nbeta_distribution<RealType>::operator()(URBG& g,  // NOLINT(runtime/references)\n                                        const param_type& p) {\n  switch (p.method_) {\n    case param_type::JOEHNK:\n      return AlgorithmJoehnk(g, p);\n    case param_type::CHENG_BA:\n      ABSL_FALLTHROUGH_INTENDED;\n    case param_type::CHENG_BB:\n      return AlgorithmCheng(g, p);\n    default:\n      return DegenerateCase(g, p);\n  }\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const beta_distribution<RealType>& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);\n  os << x.alpha() << os.fill() << x.beta();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    beta_distribution<RealType>& x) {       // NOLINT(runtime/references)\n  using result_type = typename beta_distribution<RealType>::result_type;\n  using param_type = typename beta_distribution<RealType>::param_type;\n  result_type alpha, beta;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  alpha = random_internal::read_floating_point<result_type>(is);\n  if (is.fail()) return is;\n  beta = random_internal::read_floating_point<result_type>(is);\n  if (!is.fail()) {\n    x.param(param_type(alpha, beta));\n  }\n  return is;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_BETA_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/beta_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/beta_distribution.h\"\n\n#include <algorithm>\n#include <cfloat>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <unordered_map>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/numeric/internal/representation.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\ntemplate <typename IntType>\nclass BetaDistributionInterfaceTest : public ::testing::Test {};\n\nconstexpr bool ShouldExerciseLongDoubleTests() {\n  // long double arithmetic is not supported well by either GCC or Clang on\n  // most platforms specifically not when implemented in terms of double-double;\n  // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,\n  // https://bugs.llvm.org/show_bug.cgi?id=49131, and\n  // https://bugs.llvm.org/show_bug.cgi?id=49132.\n  // So a conservative choice here is to disable long-double tests pretty much\n  // everywhere except on x64 but only if long double is not implemented as\n  // double-double.\n#if defined(__i686__) && defined(__x86_64__)\n  return !absl::numeric_internal::IsDoubleDouble();\n#else\n  return false;\n#endif\n}\n\nusing RealTypes = std::conditional<ShouldExerciseLongDoubleTests(),\n                                   ::testing::Types<float, double, long double>,\n                                   ::testing::Types<float, double>>::type;\nTYPED_TEST_SUITE(BetaDistributionInterfaceTest, RealTypes);\n\nTYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {\n  // The threshold for whether std::exp(1/a) is finite.\n  const TypeParam kSmallA =\n      1.0f / std::log((std::numeric_limits<TypeParam>::max)());\n  // The threshold for whether a * std::log(a) is finite.\n  const TypeParam kLargeA =\n      std::exp(std::log((std::numeric_limits<TypeParam>::max)()) -\n               std::log(std::log((std::numeric_limits<TypeParam>::max)())));\n  using param_type = typename absl::beta_distribution<TypeParam>::param_type;\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n  const TypeParam kValues[] = {\n      TypeParam(1e-20), TypeParam(1e-12), TypeParam(1e-8), TypeParam(1e-4),\n      TypeParam(1e-3), TypeParam(0.1), TypeParam(0.25),\n      std::nextafter(TypeParam(0.5), TypeParam(0)),  // 0.5 - epsilon\n      std::nextafter(TypeParam(0.5), TypeParam(1)),  // 0.5 + epsilon\n      TypeParam(0.5), TypeParam(1.0),                //\n      std::nextafter(TypeParam(1), TypeParam(0)),    // 1 - epsilon\n      std::nextafter(TypeParam(1), TypeParam(2)),    // 1 + epsilon\n      TypeParam(12.5), TypeParam(1e2), TypeParam(1e8), TypeParam(1e12),\n      TypeParam(1e20),                        //\n      kSmallA,                                //\n      std::nextafter(kSmallA, TypeParam(0)),  //\n      std::nextafter(kSmallA, TypeParam(1)),  //\n      kLargeA,                                //\n      std::nextafter(kLargeA, TypeParam(0)),  //\n      std::nextafter(kLargeA, std::numeric_limits<TypeParam>::max()),\n      // Boundary cases.\n      std::numeric_limits<TypeParam>::max(),\n      std::numeric_limits<TypeParam>::epsilon(),\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(1)),                  // min + epsilon\n      std::numeric_limits<TypeParam>::min(),         // smallest normal\n      std::numeric_limits<TypeParam>::denorm_min(),  // smallest denorm\n      std::numeric_limits<TypeParam>::min() / 2,     // denorm\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(0)),  // denorm_max\n  };\n  for (TypeParam alpha : kValues) {\n    for (TypeParam beta : kValues) {\n      LOG(INFO) << absl::StreamFormat(\"Smoke test for Beta(%a, %a)\", alpha,\n                                      beta);\n\n      param_type param(alpha, beta);\n      absl::beta_distribution<TypeParam> before(alpha, beta);\n      EXPECT_EQ(before.alpha(), param.alpha());\n      EXPECT_EQ(before.beta(), param.beta());\n\n      {\n        absl::beta_distribution<TypeParam> via_param(param);\n        EXPECT_EQ(via_param, before);\n        EXPECT_EQ(via_param.param(), before.param());\n      }\n\n      // Smoke test.\n      for (int i = 0; i < kCount; ++i) {\n        auto sample = before(gen);\n        EXPECT_TRUE(std::isfinite(sample));\n        EXPECT_GE(sample, before.min());\n        EXPECT_LE(sample, before.max());\n      }\n\n      // Validate stream serialization.\n      std::stringstream ss;\n      ss << before;\n      absl::beta_distribution<TypeParam> after(3.8f, 1.43f);\n      EXPECT_NE(before.alpha(), after.alpha());\n      EXPECT_NE(before.beta(), after.beta());\n      EXPECT_NE(before.param(), after.param());\n      EXPECT_NE(before, after);\n\n      ss >> after;\n\n      EXPECT_EQ(before.alpha(), after.alpha());\n      EXPECT_EQ(before.beta(), after.beta());\n      EXPECT_EQ(before, after)           //\n          << ss.str() << \" \"             //\n          << (ss.good() ? \"good \" : \"\")  //\n          << (ss.bad() ? \"bad \" : \"\")    //\n          << (ss.eof() ? \"eof \" : \"\")    //\n          << (ss.fail() ? \"fail \" : \"\");\n    }\n  }\n}\n\nTYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);\n\n  // Extreme cases when the params are abnormal.\n  constexpr int kCount = 1000;\n  const TypeParam kSmallValues[] = {\n      std::numeric_limits<TypeParam>::min(),\n      std::numeric_limits<TypeParam>::denorm_min(),\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(0)),  // denorm_max\n      std::numeric_limits<TypeParam>::epsilon(),\n  };\n  const TypeParam kLargeValues[] = {\n      std::numeric_limits<TypeParam>::max() * static_cast<TypeParam>(0.9999),\n      std::numeric_limits<TypeParam>::max() - 1,\n      std::numeric_limits<TypeParam>::max(),\n  };\n  {\n    // Small alpha and beta.\n    // Useful WolframAlpha plots:\n    //   * plot InverseBetaRegularized[x, 0.0001, 0.0001] from 0.495 to 0.505\n    //   * Beta[1.0, 0.0000001, 0.0000001]\n    //   * Beta[0.9999, 0.0000001, 0.0000001]\n    for (TypeParam alpha : kSmallValues) {\n      for (TypeParam beta : kSmallValues) {\n        int zeros = 0;\n        int ones = 0;\n        absl::beta_distribution<TypeParam> d(alpha, beta);\n        for (int i = 0; i < kCount; ++i) {\n          TypeParam x = d(rng);\n          if (x == 0.0) {\n            zeros++;\n          } else if (x == 1.0) {\n            ones++;\n          }\n        }\n        EXPECT_EQ(ones + zeros, kCount);\n        if (alpha == beta) {\n          EXPECT_NE(ones, 0);\n          EXPECT_NE(zeros, 0);\n        }\n      }\n    }\n  }\n  {\n    // Small alpha, large beta.\n    // Useful WolframAlpha plots:\n    //   * plot InverseBetaRegularized[x, 0.0001, 10000] from 0.995 to 1\n    //   * Beta[0, 0.0000001, 1000000]\n    //   * Beta[0.001, 0.0000001, 1000000]\n    //   * Beta[1, 0.0000001, 1000000]\n    for (TypeParam alpha : kSmallValues) {\n      for (TypeParam beta : kLargeValues) {\n        absl::beta_distribution<TypeParam> d(alpha, beta);\n        for (int i = 0; i < kCount; ++i) {\n          EXPECT_EQ(d(rng), 0.0);\n        }\n      }\n    }\n  }\n  {\n    // Large alpha, small beta.\n    // Useful WolframAlpha plots:\n    //   * plot InverseBetaRegularized[x, 10000, 0.0001] from 0 to 0.001\n    //   * Beta[0.99, 1000000, 0.0000001]\n    //   * Beta[1, 1000000, 0.0000001]\n    for (TypeParam alpha : kLargeValues) {\n      for (TypeParam beta : kSmallValues) {\n        absl::beta_distribution<TypeParam> d(alpha, beta);\n        for (int i = 0; i < kCount; ++i) {\n          EXPECT_EQ(d(rng), 1.0);\n        }\n      }\n    }\n  }\n  {\n    // Large alpha and beta.\n    absl::beta_distribution<TypeParam> d(std::numeric_limits<TypeParam>::max(),\n                                         std::numeric_limits<TypeParam>::max());\n    for (int i = 0; i < kCount; ++i) {\n      EXPECT_EQ(d(rng), 0.5);\n    }\n  }\n  {\n    // Large alpha and beta but unequal.\n    absl::beta_distribution<TypeParam> d(\n        std::numeric_limits<TypeParam>::max(),\n        std::numeric_limits<TypeParam>::max() * 0.9999);\n    for (int i = 0; i < kCount; ++i) {\n      TypeParam x = d(rng);\n      EXPECT_NE(x, 0.5f);\n      EXPECT_FLOAT_EQ(x, 0.500025f);\n    }\n  }\n}\n\nclass BetaDistributionModel {\n public:\n  explicit BetaDistributionModel(::testing::tuple<double, double> p)\n      : alpha_(::testing::get<0>(p)), beta_(::testing::get<1>(p)) {}\n\n  double Mean() const { return alpha_ / (alpha_ + beta_); }\n\n  double Variance() const {\n    return alpha_ * beta_ / (alpha_ + beta_ + 1) / (alpha_ + beta_) /\n           (alpha_ + beta_);\n  }\n\n  double Kurtosis() const {\n    return 3 + 6 *\n                   ((alpha_ - beta_) * (alpha_ - beta_) * (alpha_ + beta_ + 1) -\n                    alpha_ * beta_ * (2 + alpha_ + beta_)) /\n                   alpha_ / beta_ / (alpha_ + beta_ + 2) / (alpha_ + beta_ + 3);\n  }\n\n protected:\n  const double alpha_;\n  const double beta_;\n};\n\nclass BetaDistributionTest\n    : public ::testing::TestWithParam<::testing::tuple<double, double>>,\n      public BetaDistributionModel {\n public:\n  BetaDistributionTest() : BetaDistributionModel(GetParam()) {}\n\n protected:\n  template <class D>\n  bool SingleZTestOnMeanAndVariance(double p, size_t samples);\n\n  template <class D>\n  bool SingleChiSquaredTest(double p, size_t samples, size_t buckets);\n\n  absl::InsecureBitGen rng_;\n};\n\ntemplate <class D>\nbool BetaDistributionTest::SingleZTestOnMeanAndVariance(double p,\n                                                        size_t samples) {\n  D dis(alpha_, beta_);\n\n  std::vector<double> data;\n  data.reserve(samples);\n  for (size_t i = 0; i < samples; i++) {\n    const double variate = dis(rng_);\n    EXPECT_FALSE(std::isnan(variate));\n    // Note that equality is allowed on both sides.\n    EXPECT_GE(variate, 0.0);\n    EXPECT_LE(variate, 1.0);\n    data.push_back(variate);\n  }\n\n  // We validate that the sample mean and sample variance are indeed from a\n  // Beta distribution with the given shape parameters.\n  const auto m = absl::random_internal::ComputeDistributionMoments(data);\n\n  // The variance of the sample mean is variance / n.\n  const double mean_stddev = std::sqrt(Variance() / static_cast<double>(m.n));\n\n  // The variance of the sample variance is (approximately):\n  //   (kurtosis - 1) * variance^2 / n\n  const double variance_stddev = std::sqrt(\n      (Kurtosis() - 1) * Variance() * Variance() / static_cast<double>(m.n));\n  // z score for the sample variance.\n  const double z_variance = (m.variance - Variance()) / variance_stddev;\n\n  const double max_err = absl::random_internal::MaxErrorTolerance(p);\n  const double z_mean = absl::random_internal::ZScore(Mean(), m);\n  const bool pass =\n      absl::random_internal::Near(\"z\", z_mean, 0.0, max_err) &&\n      absl::random_internal::Near(\"z_variance\", z_variance, 0.0, max_err);\n  if (!pass) {\n    LOG(INFO) << \"Beta(\" << alpha_ << \", \" << beta_ << \"), mean: sample \"\n              << m.mean << \", expect \" << Mean() << \", which is \"\n              << std::abs(m.mean - Mean()) / mean_stddev\n              << \" stddevs away, variance: sample \" << m.variance << \", expect \"\n              << Variance() << \", which is \"\n              << std::abs(m.variance - Variance()) / variance_stddev\n              << \" stddevs away.\";\n  }\n  return pass;\n}\n\ntemplate <class D>\nbool BetaDistributionTest::SingleChiSquaredTest(double p, size_t samples,\n                                                size_t buckets) {\n  constexpr double kErr = 1e-7;\n  std::vector<double> cutoffs, expected;\n  const double bucket_width = 1.0 / static_cast<double>(buckets);\n  int i = 1;\n  int unmerged_buckets = 0;\n  for (; i < buckets; ++i) {\n    const double p = bucket_width * static_cast<double>(i);\n    const double boundary =\n        absl::random_internal::BetaIncompleteInv(alpha_, beta_, p);\n    // The intention is to add `boundary` to the list of `cutoffs`. It becomes\n    // problematic, however, when the boundary values are not monotone, due to\n    // numerical issues when computing the inverse regularized incomplete\n    // Beta function. In these cases, we merge that bucket with its previous\n    // neighbor and merge their expected counts.\n    if ((cutoffs.empty() && boundary < kErr) ||\n        (!cutoffs.empty() && boundary <= cutoffs.back())) {\n      unmerged_buckets++;\n      continue;\n    }\n    if (boundary >= 1.0 - 1e-10) {\n      break;\n    }\n    cutoffs.push_back(boundary);\n    expected.push_back(static_cast<double>(1 + unmerged_buckets) *\n                       bucket_width * static_cast<double>(samples));\n    unmerged_buckets = 0;\n  }\n  cutoffs.push_back(std::numeric_limits<double>::infinity());\n  // Merge all remaining buckets.\n  expected.push_back(static_cast<double>(buckets - i + 1) * bucket_width *\n                     static_cast<double>(samples));\n  // Make sure that we don't merge all the buckets, making this test\n  // meaningless.\n  EXPECT_GE(cutoffs.size(), 3) << alpha_ << \", \" << beta_;\n\n  D dis(alpha_, beta_);\n\n  std::vector<int32_t> counts(cutoffs.size(), 0);\n  for (int i = 0; i < samples; i++) {\n    const double x = dis(rng_);\n    auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);\n    counts[std::distance(cutoffs.begin(), it)]++;\n  }\n\n  // Null-hypothesis is that the distribution is beta distributed with the\n  // provided alpha, beta params (not estimated from the data).\n  const int dof = cutoffs.size() - 1;\n\n  const double chi_square = absl::random_internal::ChiSquare(\n      counts.begin(), counts.end(), expected.begin(), expected.end());\n  const bool pass =\n      (absl::random_internal::ChiSquarePValue(chi_square, dof) >= p);\n  if (!pass) {\n    for (size_t i = 0; i < cutoffs.size(); i++) {\n      LOG(INFO) << \"cutoff[\" << i << \"] = \" << cutoffs[i] << \", actual count \"\n                << counts[i] << \", expected \" << static_cast<int>(expected[i]);\n    }\n\n    LOG(INFO) << \"Beta(\" << alpha_ << \", \" << beta_ << \") \"\n              << absl::random_internal::kChiSquared << \" \" << chi_square\n              << \", p = \"\n              << absl::random_internal::ChiSquarePValue(chi_square, dof);\n  }\n  return pass;\n}\n\nTEST_P(BetaDistributionTest, TestSampleStatistics) {\n  static constexpr int kRuns = 20;\n  static constexpr double kPFail = 0.02;\n  const double p =\n      absl::random_internal::RequiredSuccessProbability(kPFail, kRuns);\n  static constexpr int kSampleCount = 10000;\n  static constexpr int kBucketCount = 100;\n  int failed = 0;\n  for (int i = 0; i < kRuns; ++i) {\n    if (!SingleZTestOnMeanAndVariance<absl::beta_distribution<double>>(\n            p, kSampleCount)) {\n      failed++;\n    }\n    if (!SingleChiSquaredTest<absl::beta_distribution<double>>(\n            0.005, kSampleCount, kBucketCount)) {\n      failed++;\n    }\n  }\n  // Set so that the test is not flaky at --runs_per_test=10000\n  EXPECT_LE(failed, 5);\n}\n\nstd::string ParamName(\n    const ::testing::TestParamInfo<::testing::tuple<double, double>>& info) {\n  std::string name = absl::StrCat(\"alpha_\", ::testing::get<0>(info.param),\n                                  \"__beta_\", ::testing::get<1>(info.param));\n  return absl::StrReplaceAll(name, {{\"+\", \"_\"}, {\"-\", \"_\"}, {\".\", \"_\"}});\n}\n\nINSTANTIATE_TEST_SUITE_P(\n    TestSampleStatisticsCombinations, BetaDistributionTest,\n    ::testing::Combine(::testing::Values(0.1, 0.2, 0.9, 1.1, 2.5, 10.0, 123.4),\n                       ::testing::Values(0.1, 0.2, 0.9, 1.1, 2.5, 10.0, 123.4)),\n    ParamName);\n\nINSTANTIATE_TEST_SUITE_P(\n    TestSampleStatistics_SelectedPairs, BetaDistributionTest,\n    ::testing::Values(std::make_pair(0.5, 1000), std::make_pair(1000, 0.5),\n                      std::make_pair(900, 1000), std::make_pair(10000, 20000),\n                      std::make_pair(4e5, 2e7), std::make_pair(1e7, 1e5)),\n    ParamName);\n\n// NOTE: absl::beta_distribution is not guaranteed to be stable.\nTEST(BetaDistributionTest, StabilityTest) {\n  // absl::beta_distribution stability relies on the stability of\n  // absl::random_interna::RandU64ToDouble, std::exp, std::log, std::pow,\n  // and std::sqrt.\n  //\n  // This test also depends on the stability of std::frexp.\n  using testing::ElementsAre;\n  absl::random_internal::sequence_urbg urbg({\n      0xffff00000000e6c8ull, 0xffff0000000006c8ull, 0x800003766295CFA9ull,\n      0x11C819684E734A41ull, 0x832603766295CFA9ull, 0x7fbe76c8b4395800ull,\n      0xB3472DCA7B14A94Aull, 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull,\n      0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, 0x00035C904C70A239ull,\n      0x00009E0BCBAADE14ull, 0x0000000000622CA7ull, 0x4864f22c059bf29eull,\n      0x247856d8b862665cull, 0xe46e86e9a1337e10ull, 0xd8c8541f3519b133ull,\n      0xffe75b52c567b9e4ull, 0xfffff732e5709c5bull, 0xff1f7f0b983532acull,\n      0x1ec2e8986d2362caull, 0xC332DDEFBE6C5AA5ull, 0x6558218568AB9702ull,\n      0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, 0xECDD4775619F1510ull,\n      0x814c8e35fe9a961aull, 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull,\n      0x1224e62c978bbc7full, 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull,\n      0x1bbc23cfa8fac721ull, 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull,\n      0x836d794457c08849ull, 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull,\n      0xb12d74fdd718c8c5ull, 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull,\n      0x5738341045ba0d85ull, 0xf3fd722dc65ad09eull, 0xfa14fd21ea2a5705ull,\n      0xffe6ea4d6edb0c73ull, 0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull,\n      0xEAAD8E716B93D5A0ull, 0xD08ED1D0AFC725E0ull, 0x8E3C5B2F8E7594B7ull,\n      0x8FF6E2FBF2122B64ull, 0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull,\n      0xD1CFF191B3A8C1ADull, 0x2F2F2218BE0E1777ull, 0xEA752DFE8B021FA1ull,\n  });\n\n  // Convert the real-valued result into a unit64 where we compare\n  // 5 (float) or 10 (double) decimal digits plus the base-2 exponent.\n  auto float_to_u64 = [](float d) {\n    int exp = 0;\n    auto f = std::frexp(d, &exp);\n    return (static_cast<uint64_t>(1e5 * f) * 10000) + std::abs(exp);\n  };\n  auto double_to_u64 = [](double d) {\n    int exp = 0;\n    auto f = std::frexp(d, &exp);\n    return (static_cast<uint64_t>(1e10 * f) * 10000) + std::abs(exp);\n  };\n\n  std::vector<uint64_t> output(20);\n  {\n    // Algorithm Joehnk (float)\n    absl::beta_distribution<float> dist(0.1f, 0.2f);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return float_to_u64(dist(urbg)); });\n    EXPECT_EQ(44, urbg.invocations());\n    EXPECT_THAT(output,  //\n                testing::ElementsAre(\n                    998340000, 619030004, 500000001, 999990000, 996280000,\n                    500000001, 844740004, 847210001, 999970000, 872320000,\n                    585480007, 933280000, 869080042, 647670031, 528240004,\n                    969980004, 626050008, 915930002, 833440033, 878040015));\n  }\n\n  urbg.reset();\n  {\n    // Algorithm Joehnk (double)\n    absl::beta_distribution<double> dist(0.1, 0.2);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return double_to_u64(dist(urbg)); });\n    EXPECT_EQ(44, urbg.invocations());\n    EXPECT_THAT(\n        output,  //\n        testing::ElementsAre(\n            99834713000000, 61903356870004, 50000000000001, 99999721170000,\n            99628374770000, 99999999990000, 84474397860004, 84721276240001,\n            99997407490000, 87232528120000, 58548364780007, 93328932910000,\n            86908237770042, 64767917930031, 52824581970004, 96998544140004,\n            62605946270008, 91593604380002, 83345031740033, 87804397230015));\n  }\n\n  urbg.reset();\n  {\n    // Algorithm Cheng 1\n    absl::beta_distribution<double> dist(0.9, 2.0);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return double_to_u64(dist(urbg)); });\n    EXPECT_EQ(62, urbg.invocations());\n    EXPECT_THAT(\n        output,  //\n        testing::ElementsAre(\n            62069004780001, 64433204450001, 53607416560000, 89644295430008,\n            61434586310019, 55172615890002, 62187161490000, 56433684810003,\n            80454622050005, 86418558710003, 92920514700001, 64645184680001,\n            58549183380000, 84881283650005, 71078728590002, 69949694970000,\n            73157461710001, 68592191300001, 70747623900000, 78584696930005));\n  }\n\n  urbg.reset();\n  {\n    // Algorithm Cheng 2\n    absl::beta_distribution<double> dist(1.5, 2.5);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return double_to_u64(dist(urbg)); });\n    EXPECT_EQ(54, urbg.invocations());\n    EXPECT_THAT(\n        output,  //\n        testing::ElementsAre(\n            75000029250001, 76751482860001, 53264575220000, 69193133650005,\n            78028324470013, 91573587560002, 59167523770000, 60658618560002,\n            80075870540000, 94141320460004, 63196592770003, 78883906300002,\n            96797992590001, 76907587800001, 56645167560000, 65408302280003,\n            53401156320001, 64731238570000, 83065573750001, 79788333820001));\n  }\n}\n\n// This is an implementation-specific test. If any part of the implementation\n// changes, then it is likely that this test will change as well.  Also, if\n// dependencies of the distribution change, such as RandU64ToDouble, then this\n// is also likely to change.\nTEST(BetaDistributionTest, AlgorithmBounds) {\n#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0\n  // We're using an x87-compatible FPU, and intermediate operations are\n  // performed with 80-bit floats. This produces slightly different results from\n  // what we expect below.\n  GTEST_SKIP()\n      << \"Skipping the test because we detected x87 floating-point semantics\";\n#endif\n\n  {\n    absl::random_internal::sequence_urbg urbg(\n        {0x7fbe76c8b4395800ull, 0x8000000000000000ull});\n    // u=0.499, v=0.5\n    absl::beta_distribution<double> dist(1e-4, 1e-4);\n    double a = dist(urbg);\n    EXPECT_EQ(a, 2.0202860861567108529e-09);\n    EXPECT_EQ(2, urbg.invocations());\n  }\n\n  // Test that both the float & double algorithms appropriately reject the\n  // initial draw.\n  {\n    // 1/alpha = 1/beta = 2.\n    absl::beta_distribution<float> dist(0.5, 0.5);\n\n    // first two outputs are close to 1.0 - epsilon,\n    // thus:  (u ^ 2 + v ^ 2) > 1.0\n    absl::random_internal::sequence_urbg urbg(\n        {0xffff00000006e6c8ull, 0xffff00000007c7c8ull, 0x800003766295CFA9ull,\n         0x11C819684E734A41ull});\n    {\n      double y = absl::beta_distribution<double>(0.5, 0.5)(urbg);\n      EXPECT_EQ(4, urbg.invocations());\n      EXPECT_EQ(y, 0.9810668952633862) << y;\n    }\n\n    // ...and:  log(u) * a ~= log(v) * b ~= -0.02\n    // thus z ~= -0.02 + log(1 + e(~0))\n    //        ~= -0.02 + 0.69\n    // thus z > 0\n    urbg.reset();\n    {\n      float x = absl::beta_distribution<float>(0.5, 0.5)(urbg);\n      EXPECT_EQ(4, urbg.invocations());\n      EXPECT_NEAR(0.98106688261032104, x, 0.0000005) << x << \"f\";\n    }\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/bit_gen_ref.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: bit_gen_ref.h\n// -----------------------------------------------------------------------------\n//\n// This header defines a bit generator \"reference\" class, for use in interfaces\n// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g.\n// `std::mt19937`) bit generators.\n\n#ifndef ABSL_RANDOM_BIT_GEN_REF_H_\n#define ABSL_RANDOM_BIT_GEN_REF_H_\n\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/distribution_caller.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\ntemplate <typename URBG, typename = void, typename = void, typename = void>\nstruct is_urbg : std::false_type {};\n\ntemplate <typename URBG>\nstruct is_urbg<\n    URBG,\n    absl::enable_if_t<std::is_same<\n        typename URBG::result_type,\n        typename std::decay<decltype((URBG::min)())>::type>::value>,\n    absl::enable_if_t<std::is_same<\n        typename URBG::result_type,\n        typename std::decay<decltype((URBG::max)())>::type>::value>,\n    absl::enable_if_t<std::is_same<\n        typename URBG::result_type,\n        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>\n    : std::true_type {};\n\ntemplate <typename>\nstruct DistributionCaller;\nclass MockHelpers;\n\n}  // namespace random_internal\n\n// -----------------------------------------------------------------------------\n// absl::BitGenRef\n// -----------------------------------------------------------------------------\n//\n// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic\n// non-owning \"reference\" interface for use in place of any specific uniform\n// random bit generator (URBG). This class may be used for both Abseil\n// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g\n// `std::mt19937`, `std::minstd_rand`) bit generators.\n//\n// Like other reference classes, `absl::BitGenRef` does not own the\n// underlying bit generator, and the underlying instance must outlive the\n// `absl::BitGenRef`.\n//\n// `absl::BitGenRef` is particularly useful when used with an\n// `absl::MockingBitGen` to test specific paths in functions which use random\n// values.\n//\n// Example:\n//    void TakesBitGenRef(absl::BitGenRef gen) {\n//      int x = absl::Uniform<int>(gen, 0, 1000);\n//    }\n//\nclass BitGenRef {\n  // SFINAE to detect whether the URBG type includes a member matching\n  // bool InvokeMock(key_id, args_tuple*, result*).\n  //\n  // These live inside BitGenRef so that they have friend access\n  // to MockingBitGen. (see similar methods in DistributionCaller).\n  template <template <class...> class Trait, class AlwaysVoid, class... Args>\n  struct detector : std::false_type {};\n  template <template <class...> class Trait, class... Args>\n  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>\n      : std::true_type {};\n\n  template <class T>\n  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(\n      std::declval<FastTypeIdType>(), std::declval<void*>(),\n      std::declval<void*>()));\n\n  template <typename T>\n  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;\n\n public:\n  BitGenRef(const BitGenRef&) = default;\n  BitGenRef(BitGenRef&&) = default;\n  BitGenRef& operator=(const BitGenRef&) = default;\n  BitGenRef& operator=(BitGenRef&&) = default;\n\n  template <\n      typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,\n      typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&\n                                  random_internal::is_urbg<URBG>::value &&\n                                  !HasInvokeMock<URBG>::value)>* = nullptr>\n  BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT\n      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),\n        mock_call_(NotAMock),\n        generate_impl_fn_(ImplFn<URBG>) {}\n\n  template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,\n            typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&\n                                        random_internal::is_urbg<URBG>::value &&\n                                        HasInvokeMock<URBG>::value)>* = nullptr>\n  BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT\n      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),\n        mock_call_(&MockCall<URBG>),\n        generate_impl_fn_(ImplFn<URBG>) {}\n\n  using result_type = uint64_t;\n\n  static constexpr result_type(min)() {\n    return (std::numeric_limits<result_type>::min)();\n  }\n\n  static constexpr result_type(max)() {\n    return (std::numeric_limits<result_type>::max)();\n  }\n\n  result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }\n\n private:\n  using impl_fn = result_type (*)(uintptr_t);\n  using mock_call_fn = bool (*)(uintptr_t, FastTypeIdType, void*, void*);\n\n  template <typename URBG>\n  static result_type ImplFn(uintptr_t ptr) {\n    // Ensure that the return values from operator() fill the entire\n    // range promised by result_type, min() and max().\n    absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;\n    return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));\n  }\n\n  // Get a type-erased InvokeMock pointer.\n  template <typename URBG>\n  static bool MockCall(uintptr_t gen_ptr, FastTypeIdType key_id, void* result,\n                       void* arg_tuple) {\n    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(key_id, result,\n                                                        arg_tuple);\n  }\n  static bool NotAMock(uintptr_t, FastTypeIdType, void*, void*) {\n    return false;\n  }\n\n  inline bool InvokeMock(FastTypeIdType key_id, void* args_tuple,\n                         void* result) {\n    if (mock_call_ == NotAMock) return false;  // avoids an indirect call.\n    return mock_call_(t_erased_gen_ptr_, key_id, args_tuple, result);\n  }\n\n  uintptr_t t_erased_gen_ptr_;\n  mock_call_fn mock_call_;\n  impl_fn generate_impl_fn_;\n\n  template <typename>\n  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock\n  friend class ::absl::random_internal::MockHelpers;          // for InvokeMock\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_BIT_GEN_REF_H_\n"
  },
  {
    "path": "absl/random/bit_gen_ref_test.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#include \"absl/random/bit_gen_ref.h\"\n\n#include <cstdint>\n#include <random>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass ConstBitGen {\n public:\n  // URBG interface\n  using result_type = absl::BitGen::result_type;\n\n  static constexpr result_type(min)() { return (absl::BitGen::min)(); }\n  static constexpr result_type(max)() { return (absl::BitGen::max)(); }\n  result_type operator()() { return 1; }\n\n  // InvokeMock method\n  bool InvokeMock(FastTypeIdType, void*, void* result) {\n    *static_cast<int*>(result) = 42;\n    return true;\n  }\n};\n\nnamespace {\n\nint FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }\n\ntemplate <typename T>\nclass BitGenRefTest : public testing::Test {};\n\nusing BitGenTypes =\n    ::testing::Types<absl::BitGen, absl::InsecureBitGen, std::mt19937,\n                     std::mt19937_64, std::minstd_rand>;\nTYPED_TEST_SUITE(BitGenRefTest, BitGenTypes);\n\nTYPED_TEST(BitGenRefTest, BasicTest) {\n  TypeParam gen;\n  auto x = FnTest(gen);\n  EXPECT_NEAR(x, 4, 3);\n}\n\nTYPED_TEST(BitGenRefTest, Copyable) {\n  TypeParam gen;\n  absl::BitGenRef gen_ref(gen);\n  FnTest(gen_ref);  // Copy\n}\n\nTEST(BitGenRefTest, PassThroughEquivalence) {\n  // sequence_urbg returns 64-bit results.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<uint64_t> output(12);\n\n  {\n    absl::BitGenRef view(urbg);\n    for (auto& v : output) {\n      v = view();\n    }\n  }\n\n  std::vector<uint64_t> expected(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  EXPECT_THAT(output, testing::Eq(expected));\n}\n\nTEST(BitGenRefTest, MockingBitGenBaseOverrides) {\n  ConstBitGen const_gen;\n  EXPECT_EQ(FnTest(const_gen), 42);\n\n  absl::BitGenRef gen_ref(const_gen);\n  EXPECT_EQ(FnTest(gen_ref), 42);  // Copy\n}\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/discrete_distribution.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/discrete_distribution.h\"\n\n#include <cassert>\n#include <cmath>\n#include <cstddef>\n#include <iterator>\n#include <numeric>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// Initializes the distribution table for Walker's Aliasing algorithm, described\n// in Knuth, Vol 2. as well as in https://en.wikipedia.org/wiki/Alias_method\nstd::vector<std::pair<double, size_t>> InitDiscreteDistribution(\n    std::vector<double>* probabilities) {\n  // The empty-case should already be handled by the constructor.\n  assert(probabilities);\n  assert(!probabilities->empty());\n\n  // Step 1. Normalize the input probabilities to 1.0.\n  double sum = std::accumulate(std::begin(*probabilities),\n                               std::end(*probabilities), 0.0);\n  if (std::fabs(sum - 1.0) > 1e-6) {\n    // Scale `probabilities` only when the sum is too far from 1.0.  Scaling\n    // unconditionally will alter the probabilities slightly.\n    for (double& item : *probabilities) {\n      item = item / sum;\n    }\n  }\n\n  // Step 2. At this point `probabilities` is set to the conditional\n  // probabilities of each element which sum to 1.0, to within reasonable error.\n  // These values are used to construct the proportional probability tables for\n  // the selection phases of Walker's Aliasing algorithm.\n  //\n  // To construct the table, pick an element which is under-full (i.e., an\n  // element for which `(*probabilities)[i] < 1.0/n`), and pair it with an\n  // element which is over-full (i.e., an element for which\n  // `(*probabilities)[i] > 1.0/n`). The smaller value can always be retired.\n  // The larger may still be greater than 1.0/n, or may now be less than 1.0/n,\n  // and put back onto the appropriate collection.\n  const size_t n = probabilities->size();\n  std::vector<std::pair<double, size_t>> q;\n  q.reserve(n);\n\n  std::vector<size_t> over;\n  std::vector<size_t> under;\n  size_t idx = 0;\n  for (const double item : *probabilities) {\n    assert(item >= 0);\n    const double v = item * n;\n    q.emplace_back(v, 0);\n    if (v < 1.0) {\n      under.push_back(idx++);\n    } else {\n      over.push_back(idx++);\n    }\n  }\n  while (!over.empty() && !under.empty()) {\n    auto lo = under.back();\n    under.pop_back();\n    auto hi = over.back();\n    over.pop_back();\n\n    q[lo].second = hi;\n    const double r = q[hi].first - (1.0 - q[lo].first);\n    q[hi].first = r;\n    if (r < 1.0) {\n      under.push_back(hi);\n    } else {\n      over.push_back(hi);\n    }\n  }\n\n  // Due to rounding errors, there may be un-paired elements in either\n  // collection; these should all be values near 1.0.  For these values, set `q`\n  // to 1.0 and set the alternate to the identity.\n  for (auto i : over) {\n    q[i] = {1.0, i};\n  }\n  for (auto i : under) {\n    q[i] = {1.0, i};\n  }\n  return q;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/discrete_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_\n#define ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/bernoulli_distribution.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/uniform_int_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::discrete_distribution\n//\n// A discrete distribution produces random integers i, where 0 <= i < n\n// distributed according to the discrete probability function:\n//\n//     P(i|p0,...,pn−1)=pi\n//\n// This class is an implementation of discrete_distribution (see\n// [rand.dist.samp.discrete]).\n//\n// The algorithm used is Walker's Aliasing algorithm, described in Knuth, Vol 2.\n// absl::discrete_distribution takes O(N) time to precompute the probabilities\n// (where N is the number of possible outcomes in the distribution) at\n// construction, and then takes O(1) time for each variate generation.  Many\n// other implementations also take O(N) time to construct an ordered sequence of\n// partial sums, plus O(log N) time per variate to binary search.\n//\ntemplate <typename IntType = int>\nclass discrete_distribution {\n public:\n  using result_type = IntType;\n\n  class param_type {\n   public:\n    using distribution_type = discrete_distribution;\n\n    param_type() { init(); }\n\n    template <typename InputIterator>\n    explicit param_type(InputIterator begin, InputIterator end)\n        : p_(begin, end) {\n      init();\n    }\n\n    explicit param_type(std::initializer_list<double> weights) : p_(weights) {\n      init();\n    }\n\n    template <class UnaryOperation>\n    explicit param_type(size_t nw, double xmin, double xmax,\n                        UnaryOperation fw) {\n      if (nw > 0) {\n        p_.reserve(nw);\n        double delta = (xmax - xmin) / static_cast<double>(nw);\n        assert(delta > 0);\n        double t = delta * 0.5;\n        for (size_t i = 0; i < nw; ++i) {\n          p_.push_back(fw(xmin + i * delta + t));\n        }\n      }\n      init();\n    }\n\n    const std::vector<double>& probabilities() const { return p_; }\n    size_t n() const { return p_.size() - 1; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.probabilities() == b.probabilities();\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class discrete_distribution;\n\n    void init();\n\n    std::vector<double> p_;                     // normalized probabilities\n    std::vector<std::pair<double, size_t>> q_;  // (acceptance, alternate) pairs\n\n    static_assert(std::is_integral<result_type>::value,\n                  \"Class-template absl::discrete_distribution<> must be \"\n                  \"parameterized using an integral type.\");\n  };\n\n  discrete_distribution() : param_() {}\n\n  explicit discrete_distribution(const param_type& p) : param_(p) {}\n\n  template <typename InputIterator>\n  explicit discrete_distribution(InputIterator begin, InputIterator end)\n      : param_(begin, end) {}\n\n  explicit discrete_distribution(std::initializer_list<double> weights)\n      : param_(weights) {}\n\n  template <class UnaryOperation>\n  explicit discrete_distribution(size_t nw, double xmin, double xmax,\n                                 UnaryOperation fw)\n      : param_(nw, xmin, xmax, std::move(fw)) {}\n\n  void reset() {}\n\n  // generating functions\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  const param_type& param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  result_type(min)() const { return 0; }\n  result_type(max)() const {\n    return static_cast<result_type>(param_.n());\n  }  // inclusive\n\n  // NOTE [rand.dist.sample.discrete] returns a std::vector<double> not a\n  // const std::vector<double>&.\n  const std::vector<double>& probabilities() const {\n    return param_.probabilities();\n  }\n\n  friend bool operator==(const discrete_distribution& a,\n                         const discrete_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const discrete_distribution& a,\n                         const discrete_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  param_type param_;\n};\n\n// --------------------------------------------------------------------------\n// Implementation details only below\n// --------------------------------------------------------------------------\n\nnamespace random_internal {\n\n// Using the vector `*probabilities`, whose values are the weights or\n// probabilities of an element being selected, constructs the proportional\n// probabilities used by the discrete distribution.  `*probabilities` will be\n// scaled, if necessary, so that its entries sum to a value sufficiently close\n// to 1.0.\nstd::vector<std::pair<double, size_t>> InitDiscreteDistribution(\n    std::vector<double>* probabilities);\n\n}  // namespace random_internal\n\ntemplate <typename IntType>\nvoid discrete_distribution<IntType>::param_type::init() {\n  if (p_.empty()) {\n    p_.push_back(1.0);\n    q_.emplace_back(1.0, 0);\n  } else {\n    assert(n() <= (std::numeric_limits<IntType>::max)());\n    q_ = random_internal::InitDiscreteDistribution(&p_);\n  }\n}\n\ntemplate <typename IntType>\ntemplate <typename URBG>\ntypename discrete_distribution<IntType>::result_type\ndiscrete_distribution<IntType>::operator()(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  const auto idx = absl::uniform_int_distribution<result_type>(0, p.n())(g);\n  const auto& q = p.q_[idx];\n  const bool selected = absl::bernoulli_distribution(q.first)(g);\n  return selected ? idx : static_cast<result_type>(q.second);\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const discrete_distribution<IntType>& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  const auto& probabilities = x.param().probabilities();\n  os << probabilities.size();\n\n  os.precision(random_internal::stream_precision_helper<double>::kPrecision);\n  for (const auto& p : probabilities) {\n    os << os.fill() << p;\n  }\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    discrete_distribution<IntType>& x) {    // NOLINT(runtime/references)\n  using param_type = typename discrete_distribution<IntType>::param_type;\n  auto saver = random_internal::make_istream_state_saver(is);\n\n  size_t n;\n  std::vector<double> p;\n\n  is >> n;\n  if (is.fail()) return is;\n  if (n > 0) {\n    p.reserve(n);\n    for (IntType i = 0; i < n && !is.fail(); ++i) {\n      auto tmp = random_internal::read_floating_point<double>(is);\n      if (is.fail()) return is;\n      p.push_back(tmp);\n    }\n  }\n  x.param(param_type(p.begin(), p.end()));\n  return is;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/discrete_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/discrete_distribution.h\"\n\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <numeric>\n#include <random>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\ntemplate <typename IntType>\nclass DiscreteDistributionTypeTest : public ::testing::Test {};\n\nusing IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t,\n                                  uint32_t, int64_t, uint64_t>;\nTYPED_TEST_SUITE(DiscreteDistributionTypeTest, IntTypes);\n\nTYPED_TEST(DiscreteDistributionTypeTest, ParamSerializeTest) {\n  using param_type =\n      typename absl::discrete_distribution<TypeParam>::param_type;\n\n  absl::discrete_distribution<TypeParam> empty;\n  EXPECT_THAT(empty.probabilities(), testing::ElementsAre(1.0));\n\n  absl::discrete_distribution<TypeParam> before({1.0, 2.0, 1.0});\n\n  // Validate that the probabilities sum to 1.0. We picked values which\n  // can be represented exactly to avoid floating-point roundoff error.\n  double s = 0;\n  for (const auto& x : before.probabilities()) {\n    s += x;\n  }\n  EXPECT_EQ(s, 1.0);\n  EXPECT_THAT(before.probabilities(), testing::ElementsAre(0.25, 0.5, 0.25));\n\n  // Validate the same data via an initializer list.\n  {\n    std::vector<double> data({1.0, 2.0, 1.0});\n\n    absl::discrete_distribution<TypeParam> via_param{\n        param_type(std::begin(data), std::end(data))};\n\n    EXPECT_EQ(via_param, before);\n  }\n\n  std::stringstream ss;\n  ss << before;\n  absl::discrete_distribution<TypeParam> after;\n\n  EXPECT_NE(before, after);\n\n  ss >> after;\n\n  EXPECT_EQ(before, after);\n}\n\nTYPED_TEST(DiscreteDistributionTypeTest, Constructor) {\n  auto fn = [](double x) { return x; };\n  {\n    absl::discrete_distribution<int> unary(0, 1.0, 9.0, fn);\n    EXPECT_THAT(unary.probabilities(), testing::ElementsAre(1.0));\n  }\n\n  {\n    absl::discrete_distribution<int> unary(2, 1.0, 9.0, fn);\n    // => fn(1.0 + 0 * 4 + 2) => 3\n    // => fn(1.0 + 1 * 4 + 2) => 7\n    EXPECT_THAT(unary.probabilities(), testing::ElementsAre(0.3, 0.7));\n  }\n}\n\nTEST(DiscreteDistributionTest, InitDiscreteDistribution) {\n  using testing::_;\n  using testing::Pair;\n\n  {\n    std::vector<double> p({1.0, 2.0, 3.0});\n    std::vector<std::pair<double, size_t>> q =\n        absl::random_internal::InitDiscreteDistribution(&p);\n\n    EXPECT_THAT(p, testing::ElementsAre(1 / 6.0, 2 / 6.0, 3 / 6.0));\n\n    // Each bucket is p=1/3, so bucket 0 will send half it's traffic\n    // to bucket 2, while the rest will retain all of their traffic.\n    EXPECT_THAT(q, testing::ElementsAre(Pair(0.5, 2),  //\n                                        Pair(1.0, _),  //\n                                        Pair(1.0, _)));\n  }\n\n  {\n    std::vector<double> p({1.0, 2.0, 3.0, 5.0, 2.0});\n\n    std::vector<std::pair<double, size_t>> q =\n        absl::random_internal::InitDiscreteDistribution(&p);\n\n    EXPECT_THAT(p, testing::ElementsAre(1 / 13.0, 2 / 13.0, 3 / 13.0, 5 / 13.0,\n                                        2 / 13.0));\n\n    // A more complex bucketing solution: Each bucket has p=0.2\n    // So buckets 0, 1, 4 will send their alternate traffic elsewhere, which\n    // happens to be bucket 3.\n    // However, summing up that alternate traffic gives bucket 3 too much\n    // traffic, so it will send some traffic to bucket 2.\n    constexpr double b0 = 1.0 / 13.0 / 0.2;\n    constexpr double b1 = 2.0 / 13.0 / 0.2;\n    constexpr double b3 = (5.0 / 13.0 / 0.2) - ((1 - b0) + (1 - b1) + (1 - b1));\n\n    EXPECT_THAT(q, testing::ElementsAre(Pair(b0, 3),   //\n                                        Pair(b1, 3),   //\n                                        Pair(1.0, _),  //\n                                        Pair(b3, 2),   //\n                                        Pair(b1, 3)));\n  }\n}\n\nTEST(DiscreteDistributionTest, ChiSquaredTest50) {\n  using absl::random_internal::kChiSquared;\n\n  constexpr size_t kTrials = 10000;\n  constexpr int kBuckets = 50;  // inclusive, so actually +1\n\n  // 1-in-100000 threshold, but remember, there are about 8 tests\n  // in this file. And the test could fail for other reasons.\n  // Empirically validated with --runs_per_test=10000.\n  const int kThreshold =\n      absl::random_internal::ChiSquareValue(kBuckets, 0.99999);\n\n  std::vector<double> weights(kBuckets, 0);\n  std::iota(std::begin(weights), std::end(weights), 1);\n  absl::discrete_distribution<int> dist(std::begin(weights), std::end(weights));\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);\n\n  std::vector<int32_t> counts(kBuckets, 0);\n  for (size_t i = 0; i < kTrials; i++) {\n    auto x = dist(rng);\n    counts[x]++;\n  }\n\n  // Scale weights.\n  double sum = 0;\n  for (double x : weights) {\n    sum += x;\n  }\n  for (double& x : weights) {\n    x = kTrials * (x / sum);\n  }\n\n  double chi_square =\n      absl::random_internal::ChiSquare(std::begin(counts), std::end(counts),\n                                       std::begin(weights), std::end(weights));\n\n  if (chi_square > kThreshold) {\n    double p_value =\n        absl::random_internal::ChiSquarePValue(chi_square, kBuckets);\n\n    // Chi-squared test failed. Output does not appear to be uniform.\n    std::string msg;\n    for (size_t i = 0; i < counts.size(); i++) {\n      absl::StrAppend(&msg, i, \": \", counts[i], \" vs \", weights[i], \"\\n\");\n    }\n    absl::StrAppend(&msg, kChiSquared, \" p-value \", p_value, \"\\n\");\n    absl::StrAppend(&msg, \"High \", kChiSquared, \" value: \", chi_square, \" > \",\n                    kThreshold);\n    LOG(INFO) << msg;\n    FAIL() << msg;\n  }\n}\n\nTEST(DiscreteDistributionTest, StabilityTest) {\n  // absl::discrete_distribution stability relies on\n  // absl::uniform_int_distribution and absl::bernoulli_distribution.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(6);\n\n  {\n    absl::discrete_distribution<int32_t> dist({1.0, 2.0, 3.0, 5.0, 2.0});\n    EXPECT_EQ(0, dist.min());\n    EXPECT_EQ(4, dist.max());\n    for (auto& v : output) {\n      v = dist(urbg);\n    }\n    EXPECT_EQ(12, urbg.invocations());\n  }\n\n  // With 12 calls to urbg, each call into discrete_distribution consumes\n  // precisely 2 values: one for the uniform call, and a second for the\n  // bernoulli.\n  //\n  // Given the alt mapping: 0=>3, 1=>3, 2=>2, 3=>2, 4=>3, we can\n  //\n  // uniform:      443210143131\n  // bernoulli: b0 000011100101\n  // bernoulli: b1 001111101101\n  // bernoulli: b2 111111111111\n  // bernoulli: b3 001111101111\n  // bernoulli: b4 001111101101\n  // ...\n  EXPECT_THAT(output, testing::ElementsAre(3, 3, 1, 3, 3, 3));\n\n  {\n    urbg.reset();\n    absl::discrete_distribution<int64_t> dist({1.0, 2.0, 3.0, 5.0, 2.0});\n    EXPECT_EQ(0, dist.min());\n    EXPECT_EQ(4, dist.max());\n    for (auto& v : output) {\n      v = dist(urbg);\n    }\n    EXPECT_EQ(12, urbg.invocations());\n  }\n  EXPECT_THAT(output, testing::ElementsAre(3, 3, 0, 3, 0, 4));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/distributions.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: distributions.h\n// -----------------------------------------------------------------------------\n//\n// This header defines functions representing distributions, which you use in\n// combination with an Abseil random bit generator to produce random values\n// according to the rules of that distribution.\n//\n// The Abseil random library defines the following distributions within this\n// file:\n//\n//   * `absl::Uniform` for uniform (constant) distributions having constant\n//     probability\n//   * `absl::Bernoulli` for discrete distributions having exactly two outcomes\n//   * `absl::Beta` for continuous distributions parameterized through two\n//     free parameters\n//   * `absl::Exponential` for discrete distributions of events occurring\n//     continuously and independently at a constant average rate\n//   * `absl::Gaussian` (also known as \"normal distributions\") for continuous\n//     distributions using an associated quadratic function\n//   * `absl::LogUniform` for discrete distributions where the log to the given\n//     base of all values is uniform\n//   * `absl::Poisson` for discrete probability distributions that express the\n//     probability of a given number of events occurring within a fixed interval\n//   * `absl::Zipf` for discrete probability distributions commonly used for\n//     modelling of rare events\n//\n// Prefer use of these distribution function classes over manual construction of\n// your own distribution classes, as it allows library maintainers greater\n// flexibility to change the underlying implementation in the future.\n\n#ifndef ABSL_RANDOM_DISTRIBUTIONS_H_\n#define ABSL_RANDOM_DISTRIBUTIONS_H_\n\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/bernoulli_distribution.h\"\n#include \"absl/random/beta_distribution.h\"\n#include \"absl/random/exponential_distribution.h\"\n#include \"absl/random/gaussian_distribution.h\"\n#include \"absl/random/internal/distribution_caller.h\"  // IWYU pragma: export\n#include \"absl/random/internal/traits.h\"\n#include \"absl/random/internal/uniform_helper.h\"  // IWYU pragma: export\n#include \"absl/random/log_uniform_int_distribution.h\"\n#include \"absl/random/poisson_distribution.h\"\n#include \"absl/random/uniform_int_distribution.h\"  // IWYU pragma: export\n#include \"absl/random/uniform_real_distribution.h\"  // IWYU pragma: export\n#include \"absl/random/zipf_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ninline constexpr IntervalClosedClosedTag IntervalClosedClosed = {};\ninline constexpr IntervalClosedClosedTag IntervalClosed = {};\ninline constexpr IntervalClosedOpenTag IntervalClosedOpen = {};\ninline constexpr IntervalOpenOpenTag IntervalOpenOpen = {};\ninline constexpr IntervalOpenOpenTag IntervalOpen = {};\ninline constexpr IntervalOpenClosedTag IntervalOpenClosed = {};\n\n// -----------------------------------------------------------------------------\n// absl::Uniform<T>(tag, bitgen, lo, hi)\n// -----------------------------------------------------------------------------\n//\n// `absl::Uniform()` produces random values of type `T` uniformly distributed in\n// a defined interval {lo, hi}. The interval `tag` defines the type of interval\n// which should be one of the following possible values:\n//\n//   * `absl::IntervalOpenOpen`\n//   * `absl::IntervalOpenClosed`\n//   * `absl::IntervalClosedOpen`\n//   * `absl::IntervalClosedClosed`\n//\n// where \"open\" refers to an exclusive value (excluded) from the output, while\n// \"closed\" refers to an inclusive value (included) from the output.\n//\n// In the absence of an explicit return type `T`, `absl::Uniform()` will deduce\n// the return type based on the provided endpoint arguments {A lo, B hi}.\n// Given these endpoints, one of {A, B} will be chosen as the return type, if\n// a type can be implicitly converted into the other in a lossless way. The\n// lack of any such implicit conversion between {A, B} will produce a\n// compile-time error\n//\n// See https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//\n//   // Produce a random float value between 0.0 and 1.0, inclusive\n//   auto x = absl::Uniform(absl::IntervalClosedClosed, bitgen, 0.0f, 1.0f);\n//\n//   // The most common interval of `absl::IntervalClosedOpen` is available by\n//   // default:\n//\n//   auto x = absl::Uniform(bitgen, 0.0f, 1.0f);\n//\n//   // Return-types are typically inferred from the arguments, however callers\n//   // can optionally provide an explicit return-type to the template.\n//\n//   auto x = absl::Uniform<float>(bitgen, 0, 1);\n//\ntemplate <typename R = void, typename TagType, typename URBG>\ntypename absl::enable_if_t<!std::is_same<R, void>::value, R>  //\nUniform(TagType tag,\n        URBG&& urbg,  // NOLINT(runtime/references)\n        R lo, R hi) {\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = random_internal::UniformDistributionWrapper<R>;\n\n  auto a = random_internal::uniform_lower_bound(tag, lo, hi);\n  auto b = random_internal::uniform_upper_bound(tag, lo, hi);\n  if (!random_internal::is_uniform_range_valid(a, b)) return lo;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, tag, lo, hi);\n}\n\n// absl::Uniform<T>(bitgen, lo, hi)\n//\n// Overload of `Uniform()` using the default closed-open interval of [lo, hi),\n// and returning values of type `T`\ntemplate <typename R = void, typename URBG>\ntypename absl::enable_if_t<!std::is_same<R, void>::value, R>  //\nUniform(URBG&& urbg,  // NOLINT(runtime/references)\n        R lo, R hi) {\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = random_internal::UniformDistributionWrapper<R>;\n  constexpr auto tag = absl::IntervalClosedOpen;\n\n  auto a = random_internal::uniform_lower_bound(tag, lo, hi);\n  auto b = random_internal::uniform_upper_bound(tag, lo, hi);\n  if (!random_internal::is_uniform_range_valid(a, b)) return lo;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, lo, hi);\n}\n\n// absl::Uniform(tag, bitgen, lo, hi)\n//\n// Overload of `Uniform()` using different (but compatible) lo, hi types. Note\n// that a compile-error will result if the return type cannot be deduced\n// correctly from the passed types.\ntemplate <typename R = void, typename TagType, typename URBG, typename A,\n          typename B>\ntypename absl::enable_if_t<std::is_same<R, void>::value,\n                           random_internal::uniform_inferred_return_t<A, B>>\nUniform(TagType tag,\n        URBG&& urbg,  // NOLINT(runtime/references)\n        A lo, B hi) {\n  using gen_t = absl::decay_t<URBG>;\n  using return_t = typename random_internal::uniform_inferred_return_t<A, B>;\n  using distribution_t = random_internal::UniformDistributionWrapper<return_t>;\n\n  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);\n  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);\n  if (!random_internal::is_uniform_range_valid(a, b)) return lo;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, tag, static_cast<return_t>(lo),\n                      static_cast<return_t>(hi));\n}\n\n// absl::Uniform(bitgen, lo, hi)\n//\n// Overload of `Uniform()` using different (but compatible) lo, hi types and the\n// default closed-open interval of [lo, hi). Note that a compile-error will\n// result if the return type cannot be deduced correctly from the passed types.\ntemplate <typename R = void, typename URBG, typename A, typename B>\ntypename absl::enable_if_t<std::is_same<R, void>::value,\n                           random_internal::uniform_inferred_return_t<A, B>>\nUniform(URBG&& urbg,  // NOLINT(runtime/references)\n        A lo, B hi) {\n  using gen_t = absl::decay_t<URBG>;\n  using return_t = typename random_internal::uniform_inferred_return_t<A, B>;\n  using distribution_t = random_internal::UniformDistributionWrapper<return_t>;\n\n  constexpr auto tag = absl::IntervalClosedOpen;\n  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);\n  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);\n  if (!random_internal::is_uniform_range_valid(a, b)) return lo;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, static_cast<return_t>(lo),\n                      static_cast<return_t>(hi));\n}\n\n// absl::Uniform<unsigned T>(bitgen)\n//\n// Overload of Uniform() using the minimum and maximum values of a given type\n// `T` (which must be unsigned), returning a value of type `unsigned T`\ntemplate <typename R, typename URBG>\ntypename absl::enable_if_t<!std::numeric_limits<R>::is_signed, R>  //\nUniform(URBG&& urbg) {  // NOLINT(runtime/references)\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = random_internal::UniformDistributionWrapper<R>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg);\n}\n\n// -----------------------------------------------------------------------------\n// absl::Bernoulli(bitgen, p)\n// -----------------------------------------------------------------------------\n//\n// `absl::Bernoulli` produces a random boolean value, with probability `p`\n// (where 0.0 <= p <= 1.0) equaling `true`.\n//\n// Prefer `absl::Bernoulli` to produce boolean values over other alternatives\n// such as comparing an `absl::Uniform()` value to a specific output.\n//\n// See https://en.wikipedia.org/wiki/Bernoulli_distribution\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   if (absl::Bernoulli(bitgen, 1.0/3721.0)) {\n//     std::cout << \"Asteroid field navigation successful.\";\n//   }\n//\ntemplate <typename URBG>\nbool Bernoulli(URBG&& urbg,  // NOLINT(runtime/references)\n               double p) {\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = absl::bernoulli_distribution;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, p);\n}\n\n// -----------------------------------------------------------------------------\n// absl::Beta<T>(bitgen, alpha, beta)\n// -----------------------------------------------------------------------------\n//\n// `absl::Beta` produces a floating point number distributed in the closed\n// interval [0,1] and parameterized by two values `alpha` and `beta` as per a\n// Beta distribution. `T` must be a floating point type, but may be inferred\n// from the types of `alpha` and `beta`.\n//\n// See https://en.wikipedia.org/wiki/Beta_distribution.\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   double sample = absl::Beta(bitgen, 3.0, 2.0);\n//\ntemplate <typename RealType, typename URBG>\nRealType Beta(URBG&& urbg,  // NOLINT(runtime/references)\n              RealType alpha, RealType beta) {\n  static_assert(\n      std::is_floating_point<RealType>::value,\n      \"Template-argument 'RealType' must be a floating-point type, in \"\n      \"absl::Beta<RealType, URBG>(...)\");\n\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = typename absl::beta_distribution<RealType>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, alpha, beta);\n}\n\n// -----------------------------------------------------------------------------\n// absl::Exponential<T>(bitgen, lambda = 1)\n// -----------------------------------------------------------------------------\n//\n// `absl::Exponential` produces a floating point number representing the\n// distance (time) between two consecutive events in a point process of events\n// occurring continuously and independently at a constant average rate. `T` must\n// be a floating point type, but may be inferred from the type of `lambda`.\n//\n// See https://en.wikipedia.org/wiki/Exponential_distribution.\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   double call_length = absl::Exponential(bitgen, 7.0);\n//\ntemplate <typename RealType, typename URBG>\nRealType Exponential(URBG&& urbg,  // NOLINT(runtime/references)\n                     RealType lambda = 1) {\n  static_assert(\n      std::is_floating_point<RealType>::value,\n      \"Template-argument 'RealType' must be a floating-point type, in \"\n      \"absl::Exponential<RealType, URBG>(...)\");\n\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = typename absl::exponential_distribution<RealType>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, lambda);\n}\n\n// -----------------------------------------------------------------------------\n// absl::Gaussian<T>(bitgen, mean = 0, stddev = 1)\n// -----------------------------------------------------------------------------\n//\n// `absl::Gaussian` produces a floating point number selected from the Gaussian\n// (ie. \"Normal\") distribution. `T` must be a floating point type, but may be\n// inferred from the types of `mean` and `stddev`.\n//\n// See https://en.wikipedia.org/wiki/Normal_distribution\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   double giraffe_height = absl::Gaussian(bitgen, 16.3, 3.3);\n//\ntemplate <typename RealType, typename URBG>\nRealType Gaussian(URBG&& urbg,  // NOLINT(runtime/references)\n                  RealType mean = 0, RealType stddev = 1) {\n  static_assert(\n      std::is_floating_point<RealType>::value,\n      \"Template-argument 'RealType' must be a floating-point type, in \"\n      \"absl::Gaussian<RealType, URBG>(...)\");\n\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = typename absl::gaussian_distribution<RealType>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, mean, stddev);\n}\n\n// -----------------------------------------------------------------------------\n// absl::LogUniform<T>(bitgen, lo, hi, base = 2)\n// -----------------------------------------------------------------------------\n//\n// `absl::LogUniform` produces random values distributed where the log to a\n// given base of all values is uniform in a closed interval [lo, hi]. `T` must\n// be an integral type, but may be inferred from the types of `lo` and `hi`.\n//\n// I.e., `LogUniform(0, n, b)` is uniformly distributed across buckets\n// [0], [1, b-1], [b, b^2-1] .. [b^(k-1), (b^k)-1] .. [b^floor(log(n, b)), n]\n// and is uniformly distributed within each bucket.\n//\n// The resulting probability density is inversely related to bucket size, though\n// values in the final bucket may be more likely than previous values. (In the\n// extreme case where n = b^i the final value will be tied with zero as the most\n// probable result.\n//\n// If `lo` is nonzero then this distribution is shifted to the desired interval,\n// so LogUniform(lo, hi, b) is equivalent to LogUniform(0, hi-lo, b)+lo.\n//\n// See https://en.wikipedia.org/wiki/Reciprocal_distribution\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   int v = absl::LogUniform(bitgen, 0, 1000);\n//\ntemplate <typename IntType, typename URBG>\nIntType LogUniform(URBG&& urbg,  // NOLINT(runtime/references)\n                   IntType lo, IntType hi, IntType base = 2) {\n  static_assert(random_internal::IsIntegral<IntType>::value,\n                \"Template-argument 'IntType' must be an integral type, in \"\n                \"absl::LogUniform<IntType, URBG>(...)\");\n\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = typename absl::log_uniform_int_distribution<IntType>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, lo, hi, base);\n}\n\n// -----------------------------------------------------------------------------\n// absl::Poisson<T>(bitgen, mean = 1)\n// -----------------------------------------------------------------------------\n//\n// `absl::Poisson` produces discrete probabilities for a given number of events\n// occurring within a fixed interval within the closed interval [0, max]. `T`\n// must be an integral type.\n//\n// See https://en.wikipedia.org/wiki/Poisson_distribution\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   int requests_per_minute = absl::Poisson<int>(bitgen, 3.2);\n//\ntemplate <typename IntType, typename URBG>\nIntType Poisson(URBG&& urbg,  // NOLINT(runtime/references)\n                double mean = 1.0) {\n  static_assert(random_internal::IsIntegral<IntType>::value,\n                \"Template-argument 'IntType' must be an integral type, in \"\n                \"absl::Poisson<IntType, URBG>(...)\");\n\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = typename absl::poisson_distribution<IntType>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, mean);\n}\n\n// -----------------------------------------------------------------------------\n// absl::Zipf<T>(bitgen, hi = max, q = 2, v = 1)\n// -----------------------------------------------------------------------------\n//\n// `absl::Zipf` produces discrete probabilities commonly used for modelling of\n// rare events over the closed interval [0, hi]. The parameters `v` and `q`\n// determine the skew of the distribution. `T`  must be an integral type, but\n// may be inferred from the type of `hi`.\n//\n// See http://mathworld.wolfram.com/ZipfDistribution.html\n//\n// Example:\n//\n//   absl::BitGen bitgen;\n//   ...\n//   int term_rank = absl::Zipf<int>(bitgen);\n//\ntemplate <typename IntType, typename URBG>\nIntType Zipf(URBG&& urbg,  // NOLINT(runtime/references)\n             IntType hi = (std::numeric_limits<IntType>::max)(), double q = 2.0,\n             double v = 1.0) {\n  static_assert(random_internal::IsIntegral<IntType>::value,\n                \"Template-argument 'IntType' must be an integral type, in \"\n                \"absl::Zipf<IntType, URBG>(...)\");\n\n  using gen_t = absl::decay_t<URBG>;\n  using distribution_t = typename absl::zipf_distribution<IntType>;\n\n  return random_internal::DistributionCaller<gen_t>::template Call<\n      distribution_t>(&urbg, hi, q, v);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_DISTRIBUTIONS_H_\n"
  },
  {
    "path": "absl/random/distributions_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/distributions.h\"\n\n#include <cfloat>\n#include <cmath>\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/random.h\"\n\nnamespace {\n\nconstexpr int kSize = 400000;\n\nclass RandomDistributionsTest : public testing::Test {};\n\nstruct Invalid {};\n\ntemplate <typename A, typename B>\nauto InferredUniformReturnT(int)\n    -> decltype(absl::Uniform(std::declval<absl::InsecureBitGen&>(),\n                              std::declval<A>(), std::declval<B>()));\n\ntemplate <typename, typename>\nInvalid InferredUniformReturnT(...);\n\ntemplate <typename TagType, typename A, typename B>\nauto InferredTaggedUniformReturnT(int)\n    -> decltype(absl::Uniform(std::declval<TagType>(),\n                              std::declval<absl::InsecureBitGen&>(),\n                              std::declval<A>(), std::declval<B>()));\n\ntemplate <typename, typename, typename>\nInvalid InferredTaggedUniformReturnT(...);\n\n// Given types <A, B, Expect>, CheckArgsInferType() verifies that\n//\n//   absl::Uniform(gen, A{}, B{})\n//\n// returns the type \"Expect\".\n//\n// This interface can also be used to assert that a given absl::Uniform()\n// overload does not exist / will not compile. Given types <A, B>, the\n// expression\n//\n//   decltype(absl::Uniform(..., std::declval<A>(), std::declval<B>()))\n//\n// will not compile, leaving the definition of InferredUniformReturnT<A, B> to\n// resolve (via SFINAE) to the overload which returns type \"Invalid\". This\n// allows tests to assert that an invocation such as\n//\n//   absl::Uniform(gen, 1.23f, std::numeric_limits<int>::max() - 1)\n//\n// should not compile, since neither type, float nor int, can precisely\n// represent both endpoint-values. Writing:\n//\n//   CheckArgsInferType<float, int, Invalid>()\n//\n// will assert that this overload does not exist.\ntemplate <typename A, typename B, typename Expect>\nvoid CheckArgsInferType() {\n  static_assert(\n      absl::conjunction<\n          std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,\n          std::is_same<Expect,\n                       decltype(InferredUniformReturnT<B, A>(0))>>::value,\n      \"\");\n  static_assert(\n      absl::conjunction<\n          std::is_same<Expect, decltype(InferredTaggedUniformReturnT<\n                                        absl::IntervalOpenOpenTag, A, B>(0))>,\n          std::is_same<Expect,\n                       decltype(InferredTaggedUniformReturnT<\n                                absl::IntervalOpenOpenTag, B, A>(0))>>::value,\n      \"\");\n}\n\ntemplate <typename A, typename B, typename ExplicitRet>\nauto ExplicitUniformReturnT(int) -> decltype(absl::Uniform<ExplicitRet>(\n    std::declval<absl::InsecureBitGen&>(), std::declval<A>(),\n    std::declval<B>()));\n\ntemplate <typename, typename, typename ExplicitRet>\nInvalid ExplicitUniformReturnT(...);\n\ntemplate <typename TagType, typename A, typename B, typename ExplicitRet>\nauto ExplicitTaggedUniformReturnT(int) -> decltype(absl::Uniform<ExplicitRet>(\n    std::declval<TagType>(), std::declval<absl::InsecureBitGen&>(),\n    std::declval<A>(), std::declval<B>()));\n\ntemplate <typename, typename, typename, typename ExplicitRet>\nInvalid ExplicitTaggedUniformReturnT(...);\n\n// Given types <A, B, Expect>, CheckArgsReturnExpectedType() verifies that\n//\n//   absl::Uniform<Expect>(gen, A{}, B{})\n//\n// returns the type \"Expect\", and that the function-overload has the signature\n//\n//   Expect(URBG&, Expect, Expect)\ntemplate <typename A, typename B, typename Expect>\nvoid CheckArgsReturnExpectedType() {\n  static_assert(\n      absl::conjunction<\n          std::is_same<Expect,\n                       decltype(ExplicitUniformReturnT<A, B, Expect>(0))>,\n          std::is_same<Expect, decltype(ExplicitUniformReturnT<B, A, Expect>(\n                                   0))>>::value,\n      \"\");\n  static_assert(\n      absl::conjunction<\n          std::is_same<Expect,\n                       decltype(ExplicitTaggedUniformReturnT<\n                                absl::IntervalOpenOpenTag, A, B, Expect>(0))>,\n          std::is_same<Expect, decltype(ExplicitTaggedUniformReturnT<\n                                        absl::IntervalOpenOpenTag, B, A,\n                                        Expect>(0))>>::value,\n      \"\");\n}\n\n// Takes the type of `absl::Uniform<R>(gen)` if valid or `Invalid` otherwise.\ntemplate <typename R>\nauto UniformNoBoundsReturnT(int)\n    -> decltype(absl::Uniform<R>(std::declval<absl::InsecureBitGen&>()));\n\ntemplate <typename>\nInvalid UniformNoBoundsReturnT(...);\n\nTEST_F(RandomDistributionsTest, UniformTypeInference) {\n  // Infers common types.\n  CheckArgsInferType<uint16_t, uint16_t, uint16_t>();\n  CheckArgsInferType<uint32_t, uint32_t, uint32_t>();\n  CheckArgsInferType<uint64_t, uint64_t, uint64_t>();\n  CheckArgsInferType<int16_t, int16_t, int16_t>();\n  CheckArgsInferType<int32_t, int32_t, int32_t>();\n  CheckArgsInferType<int64_t, int64_t, int64_t>();\n  CheckArgsInferType<float, float, float>();\n  CheckArgsInferType<double, double, double>();\n\n  // Explicitly-specified return-values override inferences.\n  CheckArgsReturnExpectedType<int16_t, int16_t, int32_t>();\n  CheckArgsReturnExpectedType<uint16_t, uint16_t, int32_t>();\n  CheckArgsReturnExpectedType<int16_t, int16_t, int64_t>();\n  CheckArgsReturnExpectedType<int16_t, int32_t, int64_t>();\n  CheckArgsReturnExpectedType<int16_t, int32_t, double>();\n  CheckArgsReturnExpectedType<float, float, double>();\n  CheckArgsReturnExpectedType<int, int, int16_t>();\n\n  // Properly promotes uint16_t.\n  CheckArgsInferType<uint16_t, uint32_t, uint32_t>();\n  CheckArgsInferType<uint16_t, uint64_t, uint64_t>();\n  CheckArgsInferType<uint16_t, int32_t, int32_t>();\n  CheckArgsInferType<uint16_t, int64_t, int64_t>();\n  CheckArgsInferType<uint16_t, float, float>();\n  CheckArgsInferType<uint16_t, double, double>();\n\n  // Properly promotes int16_t.\n  CheckArgsInferType<int16_t, int32_t, int32_t>();\n  CheckArgsInferType<int16_t, int64_t, int64_t>();\n  CheckArgsInferType<int16_t, float, float>();\n  CheckArgsInferType<int16_t, double, double>();\n\n  // Invalid (u)int16_t-pairings do not compile.\n  // See \"CheckArgsInferType\" comments above, for how this is achieved.\n  CheckArgsInferType<uint16_t, int16_t, Invalid>();\n  CheckArgsInferType<int16_t, uint32_t, Invalid>();\n  CheckArgsInferType<int16_t, uint64_t, Invalid>();\n\n  // Properly promotes uint32_t.\n  CheckArgsInferType<uint32_t, uint64_t, uint64_t>();\n  CheckArgsInferType<uint32_t, int64_t, int64_t>();\n  CheckArgsInferType<uint32_t, double, double>();\n\n  // Properly promotes int32_t.\n  CheckArgsInferType<int32_t, int64_t, int64_t>();\n  CheckArgsInferType<int32_t, double, double>();\n\n  // Invalid (u)int32_t-pairings do not compile.\n  CheckArgsInferType<uint32_t, int32_t, Invalid>();\n  CheckArgsInferType<int32_t, uint64_t, Invalid>();\n  CheckArgsInferType<int32_t, float, Invalid>();\n  CheckArgsInferType<uint32_t, float, Invalid>();\n\n  // Invalid (u)int64_t-pairings do not compile.\n  CheckArgsInferType<uint64_t, int64_t, Invalid>();\n  CheckArgsInferType<int64_t, float, Invalid>();\n  CheckArgsInferType<int64_t, double, Invalid>();\n\n  // Properly promotes float.\n  CheckArgsInferType<float, double, double>();\n}\n\nTEST_F(RandomDistributionsTest, UniformExamples) {\n  // Examples.\n  absl::InsecureBitGen gen;\n  EXPECT_NE(1, absl::Uniform(gen, static_cast<uint16_t>(0), 1.0f));\n  EXPECT_NE(1, absl::Uniform(gen, 0, 1.0));\n  EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen,\n                             static_cast<uint16_t>(0), 1.0f));\n  EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, 0, 1.0));\n  EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, -1, 1.0));\n  EXPECT_NE(1, absl::Uniform<double>(absl::IntervalOpenOpen, gen, -1, 1));\n  EXPECT_NE(1, absl::Uniform<float>(absl::IntervalOpenOpen, gen, 0, 1));\n  EXPECT_NE(1, absl::Uniform<float>(gen, 0, 1));\n}\n\nTEST_F(RandomDistributionsTest, UniformNoBounds) {\n  absl::InsecureBitGen gen;\n\n  absl::Uniform<uint8_t>(gen);\n  absl::Uniform<uint16_t>(gen);\n  absl::Uniform<uint32_t>(gen);\n  absl::Uniform<uint64_t>(gen);\n  absl::Uniform<absl::uint128>(gen);\n\n  // Compile-time validity tests.\n\n  // Allows unsigned ints.\n  testing::StaticAssertTypeEq<uint8_t,\n                              decltype(UniformNoBoundsReturnT<uint8_t>(0))>();\n  testing::StaticAssertTypeEq<uint16_t,\n                              decltype(UniformNoBoundsReturnT<uint16_t>(0))>();\n  testing::StaticAssertTypeEq<uint32_t,\n                              decltype(UniformNoBoundsReturnT<uint32_t>(0))>();\n  testing::StaticAssertTypeEq<uint64_t,\n                              decltype(UniformNoBoundsReturnT<uint64_t>(0))>();\n  testing::StaticAssertTypeEq<\n      absl::uint128, decltype(UniformNoBoundsReturnT<absl::uint128>(0))>();\n\n  // Disallows signed ints.\n  testing::StaticAssertTypeEq<Invalid,\n                              decltype(UniformNoBoundsReturnT<int8_t>(0))>();\n  testing::StaticAssertTypeEq<Invalid,\n                              decltype(UniformNoBoundsReturnT<int16_t>(0))>();\n  testing::StaticAssertTypeEq<Invalid,\n                              decltype(UniformNoBoundsReturnT<int32_t>(0))>();\n  testing::StaticAssertTypeEq<Invalid,\n                              decltype(UniformNoBoundsReturnT<int64_t>(0))>();\n  testing::StaticAssertTypeEq<\n      Invalid, decltype(UniformNoBoundsReturnT<absl::int128>(0))>();\n\n  // Disallows float types.\n  testing::StaticAssertTypeEq<Invalid,\n                              decltype(UniformNoBoundsReturnT<float>(0))>();\n  testing::StaticAssertTypeEq<Invalid,\n                              decltype(UniformNoBoundsReturnT<double>(0))>();\n}\n\nTEST_F(RandomDistributionsTest, UniformNonsenseRanges) {\n  // The ranges used in this test are undefined behavior.\n  // The results are arbitrary and subject to future changes.\n\n#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0\n  // We're using an x87-compatible FPU, and intermediate operations can be\n  // performed with 80-bit floats. This produces slightly different results from\n  // what we expect below.\n  GTEST_SKIP()\n      << \"Skipping the test because we detected x87 floating-point semantics\";\n#endif\n\n  absl::InsecureBitGen gen;\n\n  // <uint>\n  EXPECT_EQ(0, absl::Uniform<uint64_t>(gen, 0, 0));\n  EXPECT_EQ(1, absl::Uniform<uint64_t>(gen, 1, 0));\n  EXPECT_EQ(0, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 0, 0));\n  EXPECT_EQ(1, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 1, 0));\n\n  constexpr auto m = (std::numeric_limits<uint64_t>::max)();\n\n  EXPECT_EQ(m, absl::Uniform(gen, m, m));\n  EXPECT_EQ(m, absl::Uniform(gen, m, m - 1));\n  EXPECT_EQ(m - 1, absl::Uniform(gen, m - 1, m));\n  EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m));\n  EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m - 1));\n  EXPECT_EQ(m - 1, absl::Uniform(absl::IntervalOpenOpen, gen, m - 1, m));\n\n  // <int>\n  EXPECT_EQ(0, absl::Uniform<int64_t>(gen, 0, 0));\n  EXPECT_EQ(1, absl::Uniform<int64_t>(gen, 1, 0));\n  EXPECT_EQ(0, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 0, 0));\n  EXPECT_EQ(1, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 1, 0));\n\n  constexpr auto l = (std::numeric_limits<int64_t>::min)();\n  constexpr auto r = (std::numeric_limits<int64_t>::max)();\n\n  EXPECT_EQ(l, absl::Uniform(gen, l, l));\n  EXPECT_EQ(r, absl::Uniform(gen, r, r));\n  EXPECT_EQ(r, absl::Uniform(gen, r, r - 1));\n  EXPECT_EQ(r - 1, absl::Uniform(gen, r - 1, r));\n  EXPECT_EQ(l, absl::Uniform(absl::IntervalOpenOpen, gen, l, l));\n  EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r));\n  EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r - 1));\n  EXPECT_EQ(r - 1, absl::Uniform(absl::IntervalOpenOpen, gen, r - 1, r));\n\n  // <double>\n  const double e = std::nextafter(1.0, 2.0);  // 1 + epsilon\n  const double f = std::nextafter(1.0, 0.0);  // 1 - epsilon\n  const double g = std::numeric_limits<double>::denorm_min();\n\n  EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, e));\n  EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, f));\n  EXPECT_EQ(0.0, absl::Uniform(gen, 0.0, g));\n\n  EXPECT_EQ(e, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, e));\n  EXPECT_EQ(f, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, f));\n  EXPECT_EQ(g, absl::Uniform(absl::IntervalOpenOpen, gen, 0.0, g));\n}\n\n// TODO(lar): Validate properties of non-default interval-semantics.\nTEST_F(RandomDistributionsTest, UniformReal) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Uniform(gen, 0, 1.0);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(0.5, moments.mean, 0.02);\n  EXPECT_NEAR(1 / 12.0, moments.variance, 0.02);\n  EXPECT_NEAR(0.0, moments.skewness, 0.02);\n  EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.02);\n}\n\nTEST_F(RandomDistributionsTest, UniformInt) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    const int64_t kMax = 1000000000000ll;\n    int64_t j = absl::Uniform(absl::IntervalClosedClosed, gen, 0, kMax);\n    // convert to double.\n    values[i] = static_cast<double>(j) / static_cast<double>(kMax);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(0.5, moments.mean, 0.02);\n  EXPECT_NEAR(1 / 12.0, moments.variance, 0.02);\n  EXPECT_NEAR(0.0, moments.skewness, 0.02);\n  EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.02);\n\n  /*\n  // NOTE: These are not supported by absl::Uniform, which is specialized\n  // on integer and real valued types.\n\n  enum E { E0, E1 };    // enum\n  enum S : int { S0, S1 };    // signed enum\n  enum U : unsigned int { U0, U1 };  // unsigned enum\n\n  absl::Uniform(gen, E0, E1);\n  absl::Uniform(gen, S0, S1);\n  absl::Uniform(gen, U0, U1);\n  */\n}\n\nTEST_F(RandomDistributionsTest, Exponential) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Exponential<double>(gen);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(1.0, moments.mean, 0.02);\n  EXPECT_NEAR(1.0, moments.variance, 0.025);\n  EXPECT_NEAR(2.0, moments.skewness, 0.1);\n  EXPECT_LT(5.0, moments.kurtosis);\n}\n\nTEST_F(RandomDistributionsTest, PoissonDefault) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Poisson<int64_t>(gen);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(1.0, moments.mean, 0.02);\n  EXPECT_NEAR(1.0, moments.variance, 0.02);\n  EXPECT_NEAR(1.0, moments.skewness, 0.025);\n  EXPECT_LT(2.0, moments.kurtosis);\n}\n\nTEST_F(RandomDistributionsTest, PoissonLarge) {\n  constexpr double kMean = 100000000.0;\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Poisson<int64_t>(gen, kMean);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(kMean, moments.mean, kMean * 0.015);\n  EXPECT_NEAR(kMean, moments.variance, kMean * 0.015);\n  EXPECT_NEAR(std::sqrt(kMean), moments.skewness, kMean * 0.02);\n  EXPECT_LT(2.0, moments.kurtosis);\n}\n\nTEST_F(RandomDistributionsTest, Bernoulli) {\n  constexpr double kP = 0.5151515151;\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Bernoulli(gen, kP);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(kP, moments.mean, 0.01);\n}\n\nTEST_F(RandomDistributionsTest, Beta) {\n  constexpr double kAlpha = 2.0;\n  constexpr double kBeta = 3.0;\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Beta(gen, kAlpha, kBeta);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(0.4, moments.mean, 0.01);\n}\n\nTEST_F(RandomDistributionsTest, Zipf) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Zipf<int64_t>(gen, 100);\n  }\n\n  // The mean of a zipf distribution is: H(N, s-1) / H(N,s).\n  // Given the parameter v = 1, this gives the following function:\n  // (Hn(100, 1) - Hn(1,1)) / (Hn(100,2) - Hn(1,2)) = 6.5944\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(6.5944, moments.mean, 2000) << moments;\n}\n\nTEST_F(RandomDistributionsTest, ZipfWithZeroMax) {\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(0, absl::Zipf(gen, 0));\n  }\n}\n\nTEST_F(RandomDistributionsTest, Gaussian) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::Gaussian<double>(gen);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(0.0, moments.mean, 0.02);\n  EXPECT_NEAR(1.0, moments.variance, 0.04);\n  EXPECT_NEAR(0, moments.skewness, 0.2);\n  EXPECT_NEAR(3.0, moments.kurtosis, 0.5);\n}\n\nTEST_F(RandomDistributionsTest, LogUniform) {\n  std::vector<double> values(kSize);\n\n  absl::InsecureBitGen gen;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = absl::LogUniform<int64_t>(gen, 0, (1 << 10) - 1);\n  }\n\n  // The mean is the sum of the fractional means of the uniform distributions:\n  // [0..0][1..1][2..3][4..7][8..15][16..31][32..63]\n  // [64..127][128..255][256..511][512..1023]\n  const double mean = (0 + 1 + 1 + 2 + 3 + 4 + 7 + 8 + 15 + 16 + 31 + 32 + 63 +\n                       64 + 127 + 128 + 255 + 256 + 511 + 512 + 1023) /\n                      (2.0 * 11.0);\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(mean, moments.mean, 2) << moments;\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/examples_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cinttypes>\n#include <random>\n#include <sstream>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/random/random.h\"\n\ntemplate <typename T>\nvoid Use(T) {}\n\nTEST(Examples, Basic) {\n  absl::BitGen gen;\n  std::vector<int> objs = {10, 20, 30, 40, 50};\n\n  // Choose an element from a set.\n  auto elem = objs[absl::Uniform(gen, 0u, objs.size())];\n  Use(elem);\n\n  // Generate a uniform value between 1 and 6.\n  auto dice_roll = absl::Uniform<int>(absl::IntervalClosedClosed, gen, 1, 6);\n  Use(dice_roll);\n\n  // Generate a random byte.\n  auto byte = absl::Uniform<uint8_t>(gen);\n  Use(byte);\n\n  // Generate a fractional value from [0f, 1f).\n  auto fraction = absl::Uniform<float>(gen, 0, 1);\n  Use(fraction);\n\n  // Toss a fair coin; 50/50 probability.\n  bool coin_toss = absl::Bernoulli(gen, 0.5);\n  Use(coin_toss);\n\n  // Select a file size between 1k and 10MB, biased towards smaller file sizes.\n  auto file_size = absl::LogUniform<size_t>(gen, 1000, 10 * 1000 * 1000);\n  Use(file_size);\n\n  // Randomize (shuffle) a collection.\n  std::shuffle(std::begin(objs), std::end(objs), gen);\n}\n\nTEST(Examples, CreateingCorrelatedVariateSequences) {\n  // Unexpected PRNG correlation is often a source of bugs,\n  // so when using absl::BitGen it must be an intentional choice.\n  // NOTE: All of these only exhibit process-level stability.\n\n  // Create a correlated sequence from system entropy.\n  {\n    auto my_seed = absl::MakeSeedSeq();\n\n    absl::BitGen gen_1(my_seed);\n    absl::BitGen gen_2(my_seed);  // Produces same variates as gen_1.\n\n    EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5));\n    EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));\n  }\n\n  // Create a correlated sequence from an existing URBG.\n  {\n    absl::BitGen gen;\n\n    auto my_seed = absl::CreateSeedSeqFrom(&gen);\n    absl::BitGen gen_1(my_seed);\n    absl::BitGen gen_2(my_seed);\n\n    EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5));\n    EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));\n  }\n\n  // An alternate construction which uses user-supplied data\n  // instead of a random seed.\n  {\n    const char kData[] = \"A simple seed string\";\n    std::seed_seq my_seed(std::begin(kData), std::end(kData));\n\n    absl::BitGen gen_1(my_seed);\n    absl::BitGen gen_2(my_seed);\n\n    EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5));\n    EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));\n  }\n}\n"
  },
  {
    "path": "absl/random/exponential_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_\n#define ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cmath>\n#include <istream>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/generate_real.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::exponential_distribution:\n// Generates a number conforming to an exponential distribution and is\n// equivalent to the standard [rand.dist.pois.exp] distribution.\ntemplate <typename RealType = double>\nclass exponential_distribution {\n public:\n  using result_type = RealType;\n\n  class param_type {\n   public:\n    using distribution_type = exponential_distribution;\n\n    explicit param_type(result_type lambda = 1) : lambda_(lambda) {\n      assert(lambda > 0);\n      neg_inv_lambda_ = -result_type(1) / lambda_;\n    }\n\n    result_type lambda() const { return lambda_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.lambda_ == b.lambda_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class exponential_distribution;\n\n    result_type lambda_;\n    result_type neg_inv_lambda_;\n\n    static_assert(\n        std::is_floating_point<RealType>::value,\n        \"Class-template absl::exponential_distribution<> must be parameterized \"\n        \"using a floating-point type.\");\n  };\n\n  exponential_distribution() : exponential_distribution(1) {}\n\n  explicit exponential_distribution(result_type lambda) : param_(lambda) {}\n\n  explicit exponential_distribution(const param_type& p) : param_(p) {}\n\n  void reset() {}\n\n  // Generating functions\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  param_type param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  result_type(min)() const { return 0; }\n  result_type(max)() const {\n    return std::numeric_limits<result_type>::infinity();\n  }\n\n  result_type lambda() const { return param_.lambda(); }\n\n  friend bool operator==(const exponential_distribution& a,\n                         const exponential_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const exponential_distribution& a,\n                         const exponential_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  param_type param_;\n  random_internal::FastUniformBits<uint64_t> fast_u64_;\n};\n\n// --------------------------------------------------------------------------\n// Implementation details follow\n// --------------------------------------------------------------------------\n\ntemplate <typename RealType>\ntemplate <typename URBG>\ntypename exponential_distribution<RealType>::result_type\nexponential_distribution<RealType>::operator()(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  using random_internal::GenerateNegativeTag;\n  using random_internal::GenerateRealFromBits;\n  using real_type =\n      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;\n\n  const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag,\n                                             false>(fast_u64_(g));  // U(-1, 0)\n\n  // log1p(-x) is mathematically equivalent to log(1 - x) but has more\n  // accuracy for x near zero.\n  return p.neg_inv_lambda_ * std::log1p(u);\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const exponential_distribution<RealType>& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);\n  os << x.lambda();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,    // NOLINT(runtime/references)\n    exponential_distribution<RealType>& x) {  // NOLINT(runtime/references)\n  using result_type = typename exponential_distribution<RealType>::result_type;\n  using param_type = typename exponential_distribution<RealType>::param_type;\n  result_type lambda;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  lambda = random_internal::read_floating_point<result_type>(is);\n  if (!is.fail()) {\n    x.param(param_type(lambda));\n  }\n  return is;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/exponential_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/exponential_distribution.h\"\n\n#include <algorithm>\n#include <cfloat>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <limits>\n#include <random>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/log/log.h\"\n#include \"absl/numeric/internal/representation.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\nusing absl::random_internal::kChiSquared;\n\ntemplate <typename RealType>\nclass ExponentialDistributionTypedTest : public ::testing::Test {};\n\n// double-double arithmetic is not supported well by either GCC or Clang; see\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,\n// https://bugs.llvm.org/show_bug.cgi?id=49131, and\n// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests\n// with double doubles until compiler support is better.\nusing RealTypes =\n    std::conditional<absl::numeric_internal::IsDoubleDouble(),\n                     ::testing::Types<float, double>,\n                     ::testing::Types<float, double, long double>>::type;\nTYPED_TEST_SUITE(ExponentialDistributionTypedTest, RealTypes);\n\nTYPED_TEST(ExponentialDistributionTypedTest, SerializeTest) {\n  using param_type =\n      typename absl::exponential_distribution<TypeParam>::param_type;\n\n  const TypeParam kParams[] = {\n      // Cases around 1.\n      1,                                           //\n      std::nextafter(TypeParam(1), TypeParam(0)),  // 1 - epsilon\n      std::nextafter(TypeParam(1), TypeParam(2)),  // 1 + epsilon\n      // Typical cases.\n      TypeParam(1e-8), TypeParam(1e-4), TypeParam(1), TypeParam(2),\n      TypeParam(1e4), TypeParam(1e8), TypeParam(1e20), TypeParam(2.5),\n      // Boundary cases.\n      std::numeric_limits<TypeParam>::max(),\n      std::numeric_limits<TypeParam>::epsilon(),\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(1)),           // min + epsilon\n      std::numeric_limits<TypeParam>::min(),  // smallest normal\n      // There are some errors dealing with denorms on apple platforms.\n      std::numeric_limits<TypeParam>::denorm_min(),  // smallest denorm\n      std::numeric_limits<TypeParam>::min() / 2,     // denorm\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(0)),  // denorm_max\n  };\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n\n  for (const TypeParam lambda : kParams) {\n    // Some values may be invalid; skip those.\n    if (!std::isfinite(lambda)) continue;\n    ABSL_ASSERT(lambda > 0);\n\n    const param_type param(lambda);\n\n    absl::exponential_distribution<TypeParam> before(lambda);\n    EXPECT_EQ(before.lambda(), param.lambda());\n\n    {\n      absl::exponential_distribution<TypeParam> via_param(param);\n      EXPECT_EQ(via_param, before);\n      EXPECT_EQ(via_param.param(), before.param());\n    }\n\n    // Smoke test.\n    auto sample_min = before.max();\n    auto sample_max = before.min();\n    for (int i = 0; i < kCount; i++) {\n      auto sample = before(gen);\n      EXPECT_GE(sample, before.min()) << before;\n      EXPECT_LE(sample, before.max()) << before;\n      if (sample > sample_max) sample_max = sample;\n      if (sample < sample_min) sample_min = sample;\n    }\n    if (!std::is_same<TypeParam, long double>::value) {\n      LOG(INFO) << \"Range {\" << lambda << \"}: \" << sample_min << \", \"\n                << sample_max << \", lambda=\" << lambda;\n    }\n\n    std::stringstream ss;\n    ss << before;\n\n    if (!std::isfinite(lambda)) {\n      // Streams do not deserialize inf/nan correctly.\n      continue;\n    }\n    // Validate stream serialization.\n    absl::exponential_distribution<TypeParam> after(34.56f);\n\n    EXPECT_NE(before.lambda(), after.lambda());\n    EXPECT_NE(before.param(), after.param());\n    EXPECT_NE(before, after);\n\n    ss >> after;\n\n    EXPECT_EQ(before.lambda(), after.lambda())  //\n        << ss.str() << \" \"                      //\n        << (ss.good() ? \"good \" : \"\")           //\n        << (ss.bad() ? \"bad \" : \"\")             //\n        << (ss.eof() ? \"eof \" : \"\")             //\n        << (ss.fail() ? \"fail \" : \"\");\n  }\n}\n\n// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm\n\nclass ExponentialModel {\n public:\n  explicit ExponentialModel(double lambda)\n      : lambda_(lambda), beta_(1.0 / lambda) {}\n\n  double lambda() const { return lambda_; }\n\n  double mean() const { return beta_; }\n  double variance() const { return beta_ * beta_; }\n  double stddev() const { return std::sqrt(variance()); }\n  double skew() const { return 2; }\n  double kurtosis() const { return 6.0; }\n\n  double CDF(double x) { return 1.0 - std::exp(-lambda_ * x); }\n\n  // The inverse CDF, or PercentPoint function of the distribution\n  double InverseCDF(double p) {\n    ABSL_ASSERT(p >= 0.0);\n    ABSL_ASSERT(p < 1.0);\n    return -beta_ * std::log(1.0 - p);\n  }\n\n private:\n  const double lambda_;\n  const double beta_;\n};\n\nstruct Param {\n  double lambda;\n  double p_fail;\n  int trials;\n};\n\nclass ExponentialDistributionTests : public testing::TestWithParam<Param>,\n                                     public ExponentialModel {\n public:\n  ExponentialDistributionTests() : ExponentialModel(GetParam().lambda) {}\n\n  // SingleZTest provides a basic z-squared test of the mean vs. expected\n  // mean for data generated by the poisson distribution.\n  template <typename D>\n  bool SingleZTest(const double p, const size_t samples);\n\n  // SingleChiSquaredTest provides a basic chi-squared test of the normal\n  // distribution.\n  template <typename D>\n  double SingleChiSquaredTest();\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};\n};\n\ntemplate <typename D>\nbool ExponentialDistributionTests::SingleZTest(const double p,\n                                               const size_t samples) {\n  D dis(lambda());\n\n  std::vector<double> data;\n  data.reserve(samples);\n  for (size_t i = 0; i < samples; i++) {\n    const double x = dis(rng_);\n    data.push_back(x);\n  }\n\n  const auto m = absl::random_internal::ComputeDistributionMoments(data);\n  const double max_err = absl::random_internal::MaxErrorTolerance(p);\n  const double z = absl::random_internal::ZScore(mean(), m);\n  const bool pass = absl::random_internal::Near(\"z\", z, 0.0, max_err);\n\n  if (!pass) {\n    // clang-format off\n    LOG(INFO)\n        << \"p=\" << p << \" max_err=\" << max_err << \"\\n\"\n           \" lambda=\" << lambda() << \"\\n\"\n           \" mean=\" << m.mean << \" vs. \" << mean() << \"\\n\"\n           \" stddev=\" << std::sqrt(m.variance) << \" vs. \" << stddev() << \"\\n\"\n           \" skewness=\" << m.skewness << \" vs. \" << skew() << \"\\n\"\n           \" kurtosis=\" << m.kurtosis << \" vs. \" << kurtosis() << \"\\n\"\n           \" z=\" << z << \" vs. 0\";\n    // clang-format on\n  }\n  return pass;\n}\n\ntemplate <typename D>\ndouble ExponentialDistributionTests::SingleChiSquaredTest() {\n  const size_t kSamples = 10000;\n  const int kBuckets = 50;\n\n  // The InverseCDF is the percent point function of the distribution, and can\n  // be used to assign buckets roughly uniformly.\n  std::vector<double> cutoffs;\n  const double kInc = 1.0 / static_cast<double>(kBuckets);\n  for (double p = kInc; p < 1.0; p += kInc) {\n    cutoffs.push_back(InverseCDF(p));\n  }\n  if (cutoffs.back() != std::numeric_limits<double>::infinity()) {\n    cutoffs.push_back(std::numeric_limits<double>::infinity());\n  }\n\n  D dis(lambda());\n\n  std::vector<int32_t> counts(cutoffs.size(), 0);\n  for (int j = 0; j < kSamples; j++) {\n    const double x = dis(rng_);\n    auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);\n    counts[std::distance(cutoffs.begin(), it)]++;\n  }\n\n  // Null-hypothesis is that the distribution is exponentially distributed\n  // with the provided lambda (not estimated from the data).\n  const int dof = static_cast<int>(counts.size()) - 1;\n\n  // Our threshold for logging is 1-in-50.\n  const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);\n\n  const double expected =\n      static_cast<double>(kSamples) / static_cast<double>(counts.size());\n\n  double chi_square = absl::random_internal::ChiSquareWithExpected(\n      std::begin(counts), std::end(counts), expected);\n  double p = absl::random_internal::ChiSquarePValue(chi_square, dof);\n\n  if (chi_square > threshold) {\n    for (size_t i = 0; i < cutoffs.size(); i++) {\n      LOG(INFO) << i << \" : (\" << cutoffs[i] << \") = \" << counts[i];\n    }\n\n    // clang-format off\n    LOG(INFO) << \"lambda \" << lambda() << \"\\n\"\n                 \" expected \" << expected << \"\\n\"\n              << kChiSquared << \" \" << chi_square << \" (\" << p << \")\\n\"\n              << kChiSquared << \" @ 0.98 = \" << threshold;\n    // clang-format on\n  }\n  return p;\n}\n\nTEST_P(ExponentialDistributionTests, ZTest) {\n  const size_t kSamples = 10000;\n  const auto& param = GetParam();\n  const int expected_failures =\n      std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));\n  const double p = absl::random_internal::RequiredSuccessProbability(\n      param.p_fail, param.trials);\n\n  int failures = 0;\n  for (int i = 0; i < param.trials; i++) {\n    failures += SingleZTest<absl::exponential_distribution<double>>(p, kSamples)\n                    ? 0\n                    : 1;\n  }\n  EXPECT_LE(failures, expected_failures);\n}\n\nTEST_P(ExponentialDistributionTests, ChiSquaredTest) {\n  const int kTrials = 20;\n  int failures = 0;\n\n  for (int i = 0; i < kTrials; i++) {\n    double p_value =\n        SingleChiSquaredTest<absl::exponential_distribution<double>>();\n    if (p_value < 0.005) {  // 1/200\n      failures++;\n    }\n  }\n\n  // There is a 0.10% chance of producing at least one failure, so raise the\n  // failure threshold high enough to allow for a flake rate < 10,000.\n  EXPECT_LE(failures, 4);\n}\n\nstd::vector<Param> GenParams() {\n  return {\n      Param{1.0, 0.02, 100},\n      Param{2.5, 0.02, 100},\n      Param{10, 0.02, 100},\n      // large\n      Param{1e4, 0.02, 100},\n      Param{1e9, 0.02, 100},\n      // small\n      Param{0.1, 0.02, 100},\n      Param{1e-3, 0.02, 100},\n      Param{1e-5, 0.02, 100},\n  };\n}\n\nstd::string ParamName(const ::testing::TestParamInfo<Param>& info) {\n  const auto& p = info.param;\n  std::string name = absl::StrCat(\"lambda_\", absl::SixDigits(p.lambda));\n  return absl::StrReplaceAll(name, {{\"+\", \"_\"}, {\"-\", \"_\"}, {\".\", \"_\"}});\n}\n\nINSTANTIATE_TEST_SUITE_P(All, ExponentialDistributionTests,\n                         ::testing::ValuesIn(GenParams()), ParamName);\n\n// NOTE: absl::exponential_distribution is not guaranteed to be stable.\nTEST(ExponentialDistributionTest, StabilityTest) {\n  // absl::exponential_distribution stability relies on std::log1p and\n  // absl::uniform_real_distribution.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(14);\n\n  {\n    absl::exponential_distribution<double> dist;\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return static_cast<int>(10000.0 * dist(urbg)); });\n\n    EXPECT_EQ(14, urbg.invocations());\n    EXPECT_THAT(output,\n                testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936,\n                                     804, 126, 12337, 17984, 27002, 0, 71913));\n  }\n\n  urbg.reset();\n  {\n    absl::exponential_distribution<float> dist;\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return static_cast<int>(10000.0f * dist(urbg)); });\n\n    EXPECT_EQ(14, urbg.invocations());\n    EXPECT_THAT(output,\n                testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936,\n                                     804, 126, 12337, 17984, 27002, 0, 71913));\n  }\n}\n\nTEST(ExponentialDistributionTest, AlgorithmBounds) {\n  // Relies on absl::uniform_real_distribution, so some of these comments\n  // reference that.\n\n#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0\n  // We're using an x87-compatible FPU, and intermediate operations can be\n  // performed with 80-bit floats. This produces slightly different results from\n  // what we expect below.\n  GTEST_SKIP()\n      << \"Skipping the test because we detected x87 floating-point semantics\";\n#endif\n\n  absl::exponential_distribution<double> dist;\n\n  {\n    // This returns the smallest value >0 from absl::uniform_real_distribution.\n    absl::random_internal::sequence_urbg urbg({0x0000000000000001ull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 5.42101086242752217004e-20);\n  }\n\n  {\n    // This returns a value very near 0.5 from absl::uniform_real_distribution.\n    absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 0.693147180559945175204);\n  }\n\n  {\n    // This returns the largest value <1 from absl::uniform_real_distribution.\n    // WolframAlpha: ~39.1439465808987766283058547296341915292187253\n    absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFeFull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 36.7368005696771007251);\n  }\n  {\n    // This *ALSO* returns the largest value <1.\n    absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 36.7368005696771007251);\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/gaussian_distribution.cc",
    "content": "// BEGIN GENERATED CODE; DO NOT EDIT\n// clang-format off\n\n#include \"absl/random/gaussian_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\nconst gaussian_distribution_base::Tables\n    gaussian_distribution_base::zg_ = {\n    {3.7130862467425505, 3.442619855899000214, 3.223084984581141565,\n     3.083228858216868318, 2.978696252647779819, 2.894344007021528942,\n     2.82312535054891045, 2.761169372387176857, 2.706113573121819549,\n     2.656406411261359679, 2.610972248431847387, 2.56903362592493778,\n     2.530009672388827457, 2.493454522095372106, 2.459018177411830486,\n     2.426420645533749809, 2.395434278011062457, 2.365871370117638595,\n     2.337575241339236776, 2.310413683698762988, 2.284274059677471769,\n     2.25905957386919809, 2.234686395590979036, 2.21108140887870297,\n     2.188180432076048731, 2.165926793748921497, 2.144270182360394905,\n     2.123165708673976138, 2.102573135189237608, 2.082456237992015957,\n     2.062782274508307978, 2.043521536655067194, 2.02464697337738464,\n     2.006133869963471206, 1.987959574127619033, 1.970103260854325633,\n     1.952545729553555764, 1.935269228296621957, 1.918257300864508963,\n     1.901494653105150423, 1.884967035707758143, 1.868661140994487768,\n     1.852564511728090002, 1.836665460258444904, 1.820952996596124418,\n     1.805416764219227366, 1.790046982599857506, 1.77483439558606837,\n     1.759770224899592339, 1.744846128113799244, 1.730054160563729182,\n     1.71538674071366648, 1.700836618569915748, 1.686396846779167014,\n     1.6720607540975998, 1.657821920954023254, 1.643674156862867441,\n     1.629611479470633562, 1.615628095043159629, 1.601718380221376581,\n     1.587876864890574558, 1.574098216022999264, 1.560377222366167382,\n     1.546708779859908844, 1.533087877674041755, 1.519509584765938559,\n     1.505969036863201937, 1.492461423781352714, 1.478981976989922842,\n     1.465525957342709296, 1.452088642889222792, 1.438665316684561546,\n     1.425251254514058319, 1.411841712447055919, 1.398431914131003539,\n     1.385017037732650058, 1.371592202427340812, 1.358152454330141534,\n     1.34469275175354519, 1.331207949665625279, 1.317692783209412299,\n     1.304141850128615054, 1.290549591926194894, 1.27691027356015363,\n     1.263217961454619287, 1.249466499573066436, 1.23564948326336066,\n     1.221760230539994385, 1.207791750415947662, 1.193736707833126465,\n     1.17958738466398616, 1.165335636164750222, 1.150972842148865416,\n     1.136489852013158774, 1.121876922582540237, 1.107123647534034028,\n     1.092218876907275371, 1.077150624892893482, 1.061905963694822042,\n     1.046470900764042922, 1.030830236068192907, 1.014967395251327842,\n     0.9988642334929808131, 0.9825008035154263464, 0.9658550794011470098,\n     0.9489026255113034436, 0.9316161966151479401, 0.9139652510230292792,\n     0.8959153525809346874, 0.8774274291129204872, 0.8584568431938099931,\n     0.8389522142975741614, 0.8188539067003538507, 0.7980920606440534693,\n     0.7765839878947563557, 0.7542306644540520688, 0.7309119106424850631,\n     0.7064796113354325779, 0.6807479186691505202, 0.6534786387399710295,\n     0.6243585973360461505, 0.5929629424714434327, 0.5586921784081798625,\n     0.5206560387620546848, 0.4774378372966830431, 0.4265479863554152429,\n     0.3628714310970211909, 0.2723208648139477384, 0},\n    {0.001014352564120377413, 0.002669629083880922793, 0.005548995220771345792,\n     0.008624484412859888607, 0.01183947865788486861, 0.01516729801054656976,\n     0.01859210273701129151, 0.02210330461592709475, 0.02569329193593428151,\n     0.02935631744000685023, 0.03308788614622575758, 0.03688438878665621645,\n     0.04074286807444417458, 0.04466086220049143157, 0.04863629585986780496,\n     0.05266740190305100461, 0.05675266348104984759, 0.06089077034804041277,\n     0.06508058521306804567, 0.06932111739357792179, 0.07361150188411341722,\n     0.07795098251397346301, 0.08233889824223575293, 0.08677467189478028919,\n     0.09125780082683036809, 0.095787849121731522, 0.1003644410286559929,\n     0.1049872554094214289, 0.1096560210148404546, 0.1143705124488661323,\n     0.1191305467076509556, 0.1239359802028679736, 0.1287867061959434012,\n     0.1336826525834396151, 0.1386237799845948804, 0.1436100800906280339,\n     0.1486415742423425057, 0.1537183122081819397, 0.1588403711394795748,\n     0.1640078546834206341, 0.1692208922373653057, 0.1744796383307898324,\n     0.1797842721232958407, 0.1851349970089926078, 0.1905320403191375633,\n     0.1959756531162781534, 0.2014661100743140865, 0.2070037094399269362,\n     0.2125887730717307134, 0.2182216465543058426, 0.2239026993850088965,\n     0.229632325232116602, 0.2354109422634795556, 0.2412389935454402889,\n     0.2471169475123218551, 0.2530452985073261551, 0.2590245673962052742,\n     0.2650553022555897087, 0.271138079138385224, 0.2772735029191887857,\n     0.2834622082232336471, 0.2897048604429605656, 0.2960021568469337061,\n     0.3023548277864842593, 0.3087636380061818397, 0.3152293880650116065,\n     0.3217529158759855901, 0.3283350983728509642, 0.3349768533135899506,\n     0.3416791412315512977, 0.3484429675463274756, 0.355269384847918035,\n     0.3621594953693184626, 0.3691144536644731522, 0.376135469510563536,\n     0.3832238110559021416, 0.3903808082373155797, 0.3976078564938743676,\n     0.404906420807223999, 0.4122780401026620578, 0.4197243320495753771,\n     0.4272469983049970721, 0.4348478302499918513, 0.4425287152754694975,\n     0.4502916436820402768, 0.458138716267873114, 0.4660721526894572309,\n     0.4740943006930180559, 0.4822076463294863724, 0.4904148252838453348,\n     0.4987186354709807201, 0.5071220510755701794, 0.5156282382440030565,\n     0.5242405726729852944, 0.5329626593838373561, 0.5417983550254266145,\n     0.5507517931146057588, 0.5598274127040882009, 0.5690299910679523787,\n     0.5783646811197646898, 0.5878370544347081283, 0.5974531509445183408,\n     0.6072195366251219584, 0.6171433708188825973, 0.6272324852499290282,\n     0.6374954773350440806, 0.6479418211102242475, 0.6585820000500898219,\n     0.6694276673488921414, 0.6804918409973358395, 0.6917891434366769676,\n     0.7033360990161600101, 0.7151515074105005976, 0.7272569183441868201,\n     0.7396772436726493094, 0.7524415591746134169, 0.7655841738977066102,\n     0.7791460859296898134, 0.7931770117713072832, 0.8077382946829627652,\n     0.8229072113814113187, 0.8387836052959920519, 0.8555006078694531446,\n     0.873243048910072206, 0.8922816507840289901, 0.9130436479717434217,\n     0.9362826816850632339, 0.9635996931270905952, 1}};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// clang-format on\n// END GENERATED CODE\n"
  },
  {
    "path": "absl/random/gaussian_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_\n#define ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_\n\n// absl::gaussian_distribution implements the Ziggurat algorithm\n// for generating random gaussian numbers.\n//\n// Implementation based on \"The Ziggurat Method for Generating Random Variables\"\n// by George Marsaglia and Wai Wan Tsang: http://www.jstatsoft.org/v05/i08/\n//\n\n#include <cmath>\n#include <cstdint>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/generate_real.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// absl::gaussian_distribution_base implements the underlying ziggurat algorithm\n// using the ziggurat tables generated by the gaussian_distribution_gentables\n// binary.\n//\n// The specific algorithm has some of the improvements suggested by the\n// 2005 paper, \"An Improved Ziggurat Method to Generate Normal Random Samples\",\n// Jurgen A Doornik.  (https://www.doornik.com/research/ziggurat.pdf)\nclass ABSL_DLL gaussian_distribution_base {\n public:\n  template <typename URBG>\n  inline double zignor(URBG& g);  // NOLINT(runtime/references)\n\n private:\n  friend class TableGenerator;\n\n  template <typename URBG>\n  inline double zignor_fallback(URBG& g,  // NOLINT(runtime/references)\n                                bool neg);\n\n  // Constants used for the gaussian distribution.\n  static constexpr double kR = 3.442619855899;          // Start of the tail.\n  static constexpr double kRInv = 0.29047645161474317;  // ~= (1.0 / kR) .\n  static constexpr double kV = 9.91256303526217e-3;\n  static constexpr uint64_t kMask = 0x07f;\n\n  // The ziggurat tables store the pdf(f) and inverse-pdf(x) for equal-area\n  // points on one-half of the normal distribution, where the pdf function,\n  // pdf = e ^ (-1/2 *x^2), assumes that the mean = 0 & stddev = 1.\n  //\n  // These tables are just over 2kb in size; larger tables might improve the\n  // distributions, but also lead to more cache pollution.\n  //\n  // x = {3.71308, 3.44261, 3.22308, ..., 0}\n  // f = {0.00101, 0.00266, 0.00554, ..., 1}\n  struct Tables {\n    double x[kMask + 2];\n    double f[kMask + 2];\n  };\n  static const Tables zg_;\n  random_internal::FastUniformBits<uint64_t> fast_u64_;\n};\n\n}  // namespace random_internal\n\n// absl::gaussian_distribution:\n// Generates a number conforming to a Gaussian distribution.\ntemplate <typename RealType = double>\nclass gaussian_distribution : random_internal::gaussian_distribution_base {\n public:\n  using result_type = RealType;\n\n  class param_type {\n   public:\n    using distribution_type = gaussian_distribution;\n\n    explicit param_type(result_type mean = 0, result_type stddev = 1)\n        : mean_(mean), stddev_(stddev) {}\n\n    // Returns the mean distribution parameter.  The mean specifies the location\n    // of the peak.  The default value is 0.0.\n    result_type mean() const { return mean_; }\n\n    // Returns the deviation distribution parameter.  The default value is 1.0.\n    result_type stddev() const { return stddev_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.mean_ == b.mean_ && a.stddev_ == b.stddev_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    result_type mean_;\n    result_type stddev_;\n\n    static_assert(\n        std::is_floating_point<RealType>::value,\n        \"Class-template absl::gaussian_distribution<> must be parameterized \"\n        \"using a floating-point type.\");\n  };\n\n  gaussian_distribution() : gaussian_distribution(0) {}\n\n  explicit gaussian_distribution(result_type mean, result_type stddev = 1)\n      : param_(mean, stddev) {}\n\n  explicit gaussian_distribution(const param_type& p) : param_(p) {}\n\n  void reset() {}\n\n  // Generating functions\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  param_type param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  result_type(min)() const {\n    return -std::numeric_limits<result_type>::infinity();\n  }\n  result_type(max)() const {\n    return std::numeric_limits<result_type>::infinity();\n  }\n\n  result_type mean() const { return param_.mean(); }\n  result_type stddev() const { return param_.stddev(); }\n\n  friend bool operator==(const gaussian_distribution& a,\n                         const gaussian_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const gaussian_distribution& a,\n                         const gaussian_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  param_type param_;\n};\n\n// --------------------------------------------------------------------------\n// Implementation details only below\n// --------------------------------------------------------------------------\n\ntemplate <typename RealType>\ntemplate <typename URBG>\ntypename gaussian_distribution<RealType>::result_type\ngaussian_distribution<RealType>::operator()(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  return p.mean() + p.stddev() * static_cast<result_type>(zignor(g));\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const gaussian_distribution<RealType>& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);\n  os << x.mean() << os.fill() << x.stddev();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    gaussian_distribution<RealType>& x) {   // NOLINT(runtime/references)\n  using result_type = typename gaussian_distribution<RealType>::result_type;\n  using param_type = typename gaussian_distribution<RealType>::param_type;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  auto mean = random_internal::read_floating_point<result_type>(is);\n  if (is.fail()) return is;\n  auto stddev = random_internal::read_floating_point<result_type>(is);\n  if (!is.fail()) {\n    x.param(param_type(mean, stddev));\n  }\n  return is;\n}\n\nnamespace random_internal {\n\ntemplate <typename URBG>\ninline double gaussian_distribution_base::zignor_fallback(URBG& g, bool neg) {\n  using random_internal::GeneratePositiveTag;\n  using random_internal::GenerateRealFromBits;\n\n  // This fallback path happens approximately 0.05% of the time.\n  double x, y;\n  do {\n    // kRInv = 1/r, U(0, 1)\n    x = kRInv *\n        std::log(GenerateRealFromBits<double, GeneratePositiveTag, false>(\n            fast_u64_(g)));\n    y = -std::log(\n        GenerateRealFromBits<double, GeneratePositiveTag, false>(fast_u64_(g)));\n  } while ((y + y) < (x * x));\n  return neg ? (x - kR) : (kR - x);\n}\n\ntemplate <typename URBG>\ninline double gaussian_distribution_base::zignor(\n    URBG& g) {  // NOLINT(runtime/references)\n  using random_internal::GeneratePositiveTag;\n  using random_internal::GenerateRealFromBits;\n  using random_internal::GenerateSignedTag;\n\n  while (true) {\n    // We use a single uint64_t to generate both a double and a strip.\n    // These bits are unused when the generated double is > 1/2^5.\n    // This may introduce some bias from the duplicated low bits of small\n    // values (those smaller than 1/2^5, which all end up on the left tail).\n    uint64_t bits = fast_u64_(g);\n    int i = static_cast<int>(bits & kMask);  // pick a random strip\n    double j = GenerateRealFromBits<double, GenerateSignedTag, false>(\n        bits);  // U(-1, 1)\n    const double x = j * zg_.x[i];\n\n    // Rectangular box. Handles >97% of all cases.\n    // For any given box, this handles between 75% and 99% of values.\n    // Equivalent to U(01) < (x[i+1] / x[i]), and when i == 0, ~93.5%\n    if (std::abs(x) < zg_.x[i + 1]) {\n      return x;\n    }\n\n    // i == 0: Base box. Sample using a ratio of uniforms.\n    if (i == 0) {\n      // This path happens about 0.05% of the time.\n      return zignor_fallback(g, j < 0);\n    }\n\n    // i > 0: Wedge samples using precomputed values.\n    double v = GenerateRealFromBits<double, GeneratePositiveTag, false>(\n        fast_u64_(g));  // U(0, 1)\n    if ((zg_.f[i + 1] + v * (zg_.f[i] - zg_.f[i + 1])) <\n        std::exp(-0.5 * x * x)) {\n      return x;\n    }\n\n    // The wedge was missed; reject the value and try again.\n  }\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/gaussian_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/gaussian_distribution.h\"\n\n#include <algorithm>\n#include <cmath>\n#include <cstddef>\n#include <ios>\n#include <iterator>\n#include <random>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/log/log.h\"\n#include \"absl/numeric/internal/representation.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\nusing absl::random_internal::kChiSquared;\n\ntemplate <typename RealType>\nclass GaussianDistributionInterfaceTest : public ::testing::Test {};\n\n// double-double arithmetic is not supported well by either GCC or Clang; see\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,\n// https://bugs.llvm.org/show_bug.cgi?id=49131, and\n// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests\n// with double doubles until compiler support is better.\nusing RealTypes =\n    std::conditional<absl::numeric_internal::IsDoubleDouble(),\n                     ::testing::Types<float, double>,\n                     ::testing::Types<float, double, long double>>::type;\nTYPED_TEST_SUITE(GaussianDistributionInterfaceTest, RealTypes);\n\nTYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) {\n  using param_type =\n      typename absl::gaussian_distribution<TypeParam>::param_type;\n\n  const TypeParam kParams[] = {\n      // Cases around 1.\n      1,                                           //\n      std::nextafter(TypeParam(1), TypeParam(0)),  // 1 - epsilon\n      std::nextafter(TypeParam(1), TypeParam(2)),  // 1 + epsilon\n      // Arbitrary values.\n      TypeParam(1e-8), TypeParam(1e-4), TypeParam(2), TypeParam(1e4),\n      TypeParam(1e8), TypeParam(1e20), TypeParam(2.5),\n      // Boundary cases.\n      std::numeric_limits<TypeParam>::infinity(),\n      std::numeric_limits<TypeParam>::max(),\n      std::numeric_limits<TypeParam>::epsilon(),\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(1)),           // min + epsilon\n      std::numeric_limits<TypeParam>::min(),  // smallest normal\n      // There are some errors dealing with denorms on apple platforms.\n      std::numeric_limits<TypeParam>::denorm_min(),  // smallest denorm\n      std::numeric_limits<TypeParam>::min() / 2,\n      std::nextafter(std::numeric_limits<TypeParam>::min(),\n                     TypeParam(0)),  // denorm_max\n  };\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n\n  // Use a loop to generate the combinations of {+/-x, +/-y}, and assign x, y to\n  // all values in kParams,\n  for (const auto mod : {0, 1, 2, 3}) {\n    for (const auto x : kParams) {\n      if (!std::isfinite(x)) continue;\n      for (const auto y : kParams) {\n        const TypeParam mean = (mod & 0x1) ? -x : x;\n        const TypeParam stddev = (mod & 0x2) ? -y : y;\n        const param_type param(mean, stddev);\n\n        absl::gaussian_distribution<TypeParam> before(mean, stddev);\n        EXPECT_EQ(before.mean(), param.mean());\n        EXPECT_EQ(before.stddev(), param.stddev());\n\n        {\n          absl::gaussian_distribution<TypeParam> via_param(param);\n          EXPECT_EQ(via_param, before);\n          EXPECT_EQ(via_param.param(), before.param());\n        }\n\n        // Smoke test.\n        auto sample_min = before.max();\n        auto sample_max = before.min();\n        for (int i = 0; i < kCount; i++) {\n          auto sample = before(gen);\n          if (sample > sample_max) sample_max = sample;\n          if (sample < sample_min) sample_min = sample;\n          EXPECT_GE(sample, before.min()) << before;\n          EXPECT_LE(sample, before.max()) << before;\n        }\n        if (!std::is_same<TypeParam, long double>::value) {\n          LOG(INFO) << \"Range{\" << mean << \", \" << stddev << \"}: \" << sample_min\n                    << \", \" << sample_max;\n        }\n\n        std::stringstream ss;\n        ss << before;\n\n        if (!std::isfinite(mean) || !std::isfinite(stddev)) {\n          // Streams do not parse inf/nan.\n          continue;\n        }\n\n        // Validate stream serialization.\n        absl::gaussian_distribution<TypeParam> after(-0.53f, 2.3456f);\n\n        EXPECT_NE(before.mean(), after.mean());\n        EXPECT_NE(before.stddev(), after.stddev());\n        EXPECT_NE(before.param(), after.param());\n        EXPECT_NE(before, after);\n\n        ss >> after;\n\n        EXPECT_EQ(before.mean(), after.mean());\n        EXPECT_EQ(before.stddev(), after.stddev())  //\n            << ss.str() << \" \"                      //\n            << (ss.good() ? \"good \" : \"\")           //\n            << (ss.bad() ? \"bad \" : \"\")             //\n            << (ss.eof() ? \"eof \" : \"\")             //\n            << (ss.fail() ? \"fail \" : \"\");\n      }\n    }\n  }\n}\n\n// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm\n\nclass GaussianModel {\n public:\n  GaussianModel(double mean, double stddev) : mean_(mean), stddev_(stddev) {}\n\n  double mean() const { return mean_; }\n  double variance() const { return stddev() * stddev(); }\n  double stddev() const { return stddev_; }\n  double skew() const { return 0; }\n  double kurtosis() const { return 3.0; }\n\n  // The inverse CDF, or PercentPoint function.\n  double InverseCDF(double p) {\n    ABSL_ASSERT(p >= 0.0);\n    ABSL_ASSERT(p < 1.0);\n    return mean() + stddev() * -absl::random_internal::InverseNormalSurvival(p);\n  }\n\n private:\n  const double mean_;\n  const double stddev_;\n};\n\nstruct Param {\n  double mean;\n  double stddev;\n  double p_fail;  // Z-Test probability of failure.\n  int trials;     // Z-Test trials.\n};\n\n// GaussianDistributionTests implements a z-test for the gaussian\n// distribution.\nclass GaussianDistributionTests : public testing::TestWithParam<Param>,\n                                  public GaussianModel {\n public:\n  GaussianDistributionTests()\n      : GaussianModel(GetParam().mean, GetParam().stddev) {}\n\n  // SingleZTest provides a basic z-squared test of the mean vs. expected\n  // mean for data generated by the poisson distribution.\n  template <typename D>\n  bool SingleZTest(const double p, const size_t samples);\n\n  // SingleChiSquaredTest provides a basic chi-squared test of the normal\n  // distribution.\n  template <typename D>\n  double SingleChiSquaredTest();\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};\n};\n\ntemplate <typename D>\nbool GaussianDistributionTests::SingleZTest(const double p,\n                                            const size_t samples) {\n  D dis(mean(), stddev());\n\n  std::vector<double> data;\n  data.reserve(samples);\n  for (size_t i = 0; i < samples; i++) {\n    const double x = dis(rng_);\n    data.push_back(x);\n  }\n\n  const double max_err = absl::random_internal::MaxErrorTolerance(p);\n  const auto m = absl::random_internal::ComputeDistributionMoments(data);\n  const double z = absl::random_internal::ZScore(mean(), m);\n  const bool pass = absl::random_internal::Near(\"z\", z, 0.0, max_err);\n\n  // NOTE: Informational statistical test:\n  //\n  // Compute the Jarque-Bera test statistic given the excess skewness\n  // and kurtosis. The statistic is drawn from a chi-square(2) distribution.\n  // https://en.wikipedia.org/wiki/Jarque%E2%80%93Bera_test\n  //\n  // The null-hypothesis (normal distribution) is rejected when\n  // (p = 0.05 => jb > 5.99)\n  // (p = 0.01 => jb > 9.21)\n  // NOTE: JB has a large type-I error rate, so it will reject the\n  // null-hypothesis even when it is true more often than the z-test.\n  //\n  const double jb =\n      static_cast<double>(m.n) / 6.0 *\n      (std::pow(m.skewness, 2.0) + std::pow(m.kurtosis - 3.0, 2.0) / 4.0);\n\n  if (!pass || jb > 9.21) {\n    // clang-format off\n    LOG(INFO)\n        << \"p=\" << p << \" max_err=\" << max_err << \"\\n\"\n           \" mean=\" << m.mean << \" vs. \" << mean() << \"\\n\"\n           \" stddev=\" << std::sqrt(m.variance) << \" vs. \" << stddev() << \"\\n\"\n           \" skewness=\" << m.skewness << \" vs. \" << skew() << \"\\n\"\n           \" kurtosis=\" << m.kurtosis << \" vs. \" << kurtosis() << \"\\n\"\n           \" z=\" << z << \" vs. 0\\n\"\n           \" jb=\" << jb << \" vs. 9.21\";\n    // clang-format on\n  }\n  return pass;\n}\n\ntemplate <typename D>\ndouble GaussianDistributionTests::SingleChiSquaredTest() {\n  const size_t kSamples = 10000;\n  const int kBuckets = 50;\n\n  // The InverseCDF is the percent point function of the\n  // distribution, and can be used to assign buckets\n  // roughly uniformly.\n  std::vector<double> cutoffs;\n  const double kInc = 1.0 / static_cast<double>(kBuckets);\n  for (double p = kInc; p < 1.0; p += kInc) {\n    cutoffs.push_back(InverseCDF(p));\n  }\n  if (cutoffs.back() != std::numeric_limits<double>::infinity()) {\n    cutoffs.push_back(std::numeric_limits<double>::infinity());\n  }\n\n  D dis(mean(), stddev());\n\n  std::vector<int32_t> counts(cutoffs.size(), 0);\n  for (int j = 0; j < kSamples; j++) {\n    const double x = dis(rng_);\n    auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);\n    counts[std::distance(cutoffs.begin(), it)]++;\n  }\n\n  // Null-hypothesis is that the distribution is a gaussian distribution\n  // with the provided mean and stddev (not estimated from the data).\n  const int dof = static_cast<int>(counts.size()) - 1;\n\n  // Our threshold for logging is 1-in-50.\n  const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);\n\n  const double expected =\n      static_cast<double>(kSamples) / static_cast<double>(counts.size());\n\n  double chi_square = absl::random_internal::ChiSquareWithExpected(\n      std::begin(counts), std::end(counts), expected);\n  double p = absl::random_internal::ChiSquarePValue(chi_square, dof);\n\n  // Log if the chi_square value is above the threshold.\n  if (chi_square > threshold) {\n    for (size_t i = 0; i < cutoffs.size(); i++) {\n      LOG(INFO) << i << \" : (\" << cutoffs[i] << \") = \" << counts[i];\n    }\n\n    // clang-format off\n    LOG(INFO) << \"mean=\" << mean() << \" stddev=\" << stddev() << \"\\n\"\n                 \" expected \" << expected << \"\\n\"\n              << kChiSquared << \" \" << chi_square << \" (\" << p << \")\\n\"\n              << kChiSquared << \" @ 0.98 = \" << threshold;\n    // clang-format on\n  }\n  return p;\n}\n\nTEST_P(GaussianDistributionTests, ZTest) {\n  // TODO(absl-team): Run these tests against std::normal_distribution<double>\n  // to validate outcomes are similar.\n  const size_t kSamples = 10000;\n  const auto& param = GetParam();\n  const int expected_failures =\n      std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));\n  const double p = absl::random_internal::RequiredSuccessProbability(\n      param.p_fail, param.trials);\n\n  int failures = 0;\n  for (int i = 0; i < param.trials; i++) {\n    failures +=\n        SingleZTest<absl::gaussian_distribution<double>>(p, kSamples) ? 0 : 1;\n  }\n  EXPECT_LE(failures, expected_failures);\n}\n\nTEST_P(GaussianDistributionTests, ChiSquaredTest) {\n  const int kTrials = 20;\n  int failures = 0;\n\n  for (int i = 0; i < kTrials; i++) {\n    double p_value =\n        SingleChiSquaredTest<absl::gaussian_distribution<double>>();\n    if (p_value < 0.0025) {  // 1/400\n      failures++;\n    }\n  }\n  // There is a 0.05% chance of producing at least one failure, so raise the\n  // failure threshold high enough to allow for a flake rate of less than one in\n  // 10,000.\n  EXPECT_LE(failures, 4);\n}\n\nstd::vector<Param> GenParams() {\n  return {\n      // Mean around 0.\n      Param{0.0, 1.0, 0.01, 100},\n      Param{0.0, 1e2, 0.01, 100},\n      Param{0.0, 1e4, 0.01, 100},\n      Param{0.0, 1e8, 0.01, 100},\n      Param{0.0, 1e16, 0.01, 100},\n      Param{0.0, 1e-3, 0.01, 100},\n      Param{0.0, 1e-5, 0.01, 100},\n      Param{0.0, 1e-9, 0.01, 100},\n      Param{0.0, 1e-17, 0.01, 100},\n\n      // Mean around 1.\n      Param{1.0, 1.0, 0.01, 100},\n      Param{1.0, 1e2, 0.01, 100},\n      Param{1.0, 1e-2, 0.01, 100},\n\n      // Mean around 100 / -100\n      Param{1e2, 1.0, 0.01, 100},\n      Param{-1e2, 1.0, 0.01, 100},\n      Param{1e2, 1e6, 0.01, 100},\n      Param{-1e2, 1e6, 0.01, 100},\n\n      // More extreme\n      Param{1e4, 1e4, 0.01, 100},\n      Param{1e8, 1e4, 0.01, 100},\n      Param{1e12, 1e4, 0.01, 100},\n  };\n}\n\nstd::string ParamName(const ::testing::TestParamInfo<Param>& info) {\n  const auto& p = info.param;\n  std::string name = absl::StrCat(\"mean_\", absl::SixDigits(p.mean), \"__stddev_\",\n                                  absl::SixDigits(p.stddev));\n  return absl::StrReplaceAll(name, {{\"+\", \"_\"}, {\"-\", \"_\"}, {\".\", \"_\"}});\n}\n\nINSTANTIATE_TEST_SUITE_P(All, GaussianDistributionTests,\n                         ::testing::ValuesIn(GenParams()), ParamName);\n\n// NOTE: absl::gaussian_distribution is not guaranteed to be stable.\nTEST(GaussianDistributionTest, StabilityTest) {\n  // absl::gaussian_distribution stability relies on the underlying zignor\n  // data, absl::random_interna::RandU64ToDouble, std::exp, std::log, and\n  // std::abs.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(11);\n\n  {\n    absl::gaussian_distribution<double> dist;\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return static_cast<int>(10000000.0 * dist(urbg)); });\n\n    EXPECT_EQ(13, urbg.invocations());\n    EXPECT_THAT(output,  //\n                testing::ElementsAre(1494, 25518841, 9991550, 1351856,\n                                     -20373238, 3456682, 333530, -6804981,\n                                     -15279580, -16459654, 1494));\n  }\n\n  urbg.reset();\n  {\n    absl::gaussian_distribution<float> dist;\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return static_cast<int>(1000000.0f * dist(urbg)); });\n\n    EXPECT_EQ(13, urbg.invocations());\n    EXPECT_THAT(\n        output,  //\n        testing::ElementsAre(149, 2551884, 999155, 135185, -2037323, 345668,\n                             33353, -680498, -1527958, -1645965, 149));\n  }\n}\n\n// This is an implementation-specific test. If any part of the implementation\n// changes, then it is likely that this test will change as well.\n// Also, if dependencies of the distribution change, such as RandU64ToDouble,\n// then this is also likely to change.\nTEST(GaussianDistributionTest, AlgorithmBounds) {\n  absl::gaussian_distribution<double> dist;\n\n  // In ~95% of cases, a single value is used to generate the output.\n  // for all inputs where |x| < 0.750461021389 this should be the case.\n  //\n  // The exact constraints are based on the ziggurat tables, and any\n  // changes to the ziggurat tables may require adjusting these bounds.\n  //\n  // for i in range(0, len(X)-1):\n  //   print i, X[i+1]/X[i], (X[i+1]/X[i] > 0.984375)\n  //\n  // 0.125 <= |values| <= 0.75\n  const uint64_t kValues[] = {\n      0x1000000000000100ull, 0x2000000000000100ull, 0x3000000000000100ull,\n      0x4000000000000100ull, 0x5000000000000100ull, 0x6000000000000100ull,\n      // negative values\n      0x9000000000000100ull, 0xa000000000000100ull, 0xb000000000000100ull,\n      0xc000000000000100ull, 0xd000000000000100ull, 0xe000000000000100ull};\n\n  // 0.875 <= |values| <= 0.984375\n  const uint64_t kExtraValues[] = {\n      0x7000000000000100ull, 0x7800000000000100ull,  //\n      0x7c00000000000100ull, 0x7e00000000000100ull,  //\n      // negative values\n      0xf000000000000100ull, 0xf800000000000100ull,  //\n      0xfc00000000000100ull, 0xfe00000000000100ull};\n\n  auto make_box = [](uint64_t v, uint64_t box) {\n    return (v & 0xffffffffffffff80ull) | box;\n  };\n\n  // The box is the lower 7 bits of the value. When the box == 0, then\n  // the algorithm uses an escape hatch to select the result for large\n  // outputs.\n  for (uint64_t box = 0; box < 0x7f; box++) {\n    for (const uint64_t v : kValues) {\n      // Extra values are added to the sequence to attempt to avoid\n      // infinite loops from rejection sampling on bugs/errors.\n      absl::random_internal::sequence_urbg urbg(\n          {make_box(v, box), 0x0003eb76f6f7f755ull, 0x5FCEA50FDB2F953Bull});\n\n      auto a = dist(urbg);\n      EXPECT_EQ(1, urbg.invocations()) << box << \" \" << std::hex << v;\n      if (v & 0x8000000000000000ull) {\n        EXPECT_LT(a, 0.0) << box << \" \" << std::hex << v;\n      } else {\n        EXPECT_GT(a, 0.0) << box << \" \" << std::hex << v;\n      }\n    }\n    if (box > 10 && box < 100) {\n      // The center boxes use the fast algorithm for more\n      // than 98.4375% of values.\n      for (const uint64_t v : kExtraValues) {\n        absl::random_internal::sequence_urbg urbg(\n            {make_box(v, box), 0x0003eb76f6f7f755ull, 0x5FCEA50FDB2F953Bull});\n\n        auto a = dist(urbg);\n        EXPECT_EQ(1, urbg.invocations()) << box << \" \" << std::hex << v;\n        if (v & 0x8000000000000000ull) {\n          EXPECT_LT(a, 0.0) << box << \" \" << std::hex << v;\n        } else {\n          EXPECT_GT(a, 0.0) << box << \" \" << std::hex << v;\n        }\n      }\n    }\n  }\n\n  // When the box == 0, the fallback algorithm uses a ratio of uniforms,\n  // which consumes 2 additional values from the urbg.\n  // Fallback also requires that the initial value be > 0.9271586026096681.\n  auto make_fallback = [](uint64_t v) { return (v & 0xffffffffffffff80ull); };\n\n  double tail[2];\n  {\n    // 0.9375\n    absl::random_internal::sequence_urbg urbg(\n        {make_fallback(0x7800000000000000ull), 0x13CCA830EB61BD96ull,\n         0x00000076f6f7f755ull});\n    tail[0] = dist(urbg);\n    EXPECT_EQ(3, urbg.invocations());\n    EXPECT_GT(tail[0], 0);\n  }\n  {\n    // -0.9375\n    absl::random_internal::sequence_urbg urbg(\n        {make_fallback(0xf800000000000000ull), 0x13CCA830EB61BD96ull,\n         0x00000076f6f7f755ull});\n    tail[1] = dist(urbg);\n    EXPECT_EQ(3, urbg.invocations());\n    EXPECT_LT(tail[1], 0);\n  }\n  EXPECT_EQ(tail[0], -tail[1]);\n  EXPECT_EQ(418610, static_cast<int64_t>(tail[0] * 100000.0));\n\n  // When the box != 0, the fallback algorithm computes a wedge function.\n  // Depending on the box, the threshold for varies as high as\n  // 0.991522480228.\n  {\n    // 0.9921875, 0.875\n    absl::random_internal::sequence_urbg urbg(\n        {make_box(0x7f00000000000000ull, 120), 0xe000000000000001ull,\n         0x13CCA830EB61BD96ull});\n    tail[0] = dist(urbg);\n    EXPECT_EQ(2, urbg.invocations());\n    EXPECT_GT(tail[0], 0);\n  }\n  {\n    // -0.9921875, 0.875\n    absl::random_internal::sequence_urbg urbg(\n        {make_box(0xff00000000000000ull, 120), 0xe000000000000001ull,\n         0x13CCA830EB61BD96ull});\n    tail[1] = dist(urbg);\n    EXPECT_EQ(2, urbg.invocations());\n    EXPECT_LT(tail[1], 0);\n  }\n  EXPECT_EQ(tail[0], -tail[1]);\n  EXPECT_EQ(61948, static_cast<int64_t>(tail[0] * 100000.0));\n\n  // Fallback rejected, try again.\n  {\n    // -0.9921875, 0.0625\n    absl::random_internal::sequence_urbg urbg(\n        {make_box(0xff00000000000000ull, 120), 0x1000000000000001,\n         make_box(0x1000000000000100ull, 50), 0x13CCA830EB61BD96ull});\n    dist(urbg);\n    EXPECT_EQ(3, urbg.invocations());\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/generators_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstdint>\n#include <random>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/random.h\"\n\nnamespace {\n\ntemplate <typename URBG>\nvoid TestUniform(URBG* gen) {\n  // [a, b) default-semantics, inferred types.\n  absl::Uniform(*gen, 0, 100);     // int\n  absl::Uniform(*gen, 0, 1.0);     // Promoted to double\n  absl::Uniform(*gen, 0.0f, 1.0);  // Promoted to double\n  absl::Uniform(*gen, 0.0, 1.0);   // double\n  absl::Uniform(*gen, -1, 1L);     // Promoted to long\n\n  // Roll a die.\n  absl::Uniform(absl::IntervalClosedClosed, *gen, 1, 6);\n\n  // Get a fraction.\n  absl::Uniform(absl::IntervalOpenOpen, *gen, 0.0, 1.0);\n\n  // Assign a value to a random element.\n  std::vector<int> elems = {10, 20, 30, 40, 50};\n  elems[absl::Uniform(*gen, 0u, elems.size())] = 5;\n  elems[absl::Uniform<size_t>(*gen, 0, elems.size())] = 3;\n\n  // Choose some epsilon around zero.\n  absl::Uniform(absl::IntervalOpenOpen, *gen, -1.0, 1.0);\n\n  // (a, b) semantics, inferred types.\n  absl::Uniform(absl::IntervalOpenOpen, *gen, 0, 1.0);  // Promoted to double\n\n  // Explicit overriding of types.\n  absl::Uniform<int>(*gen, 0, 100);\n  absl::Uniform<int8_t>(*gen, 0, 100);\n  absl::Uniform<int16_t>(*gen, 0, 100);\n  absl::Uniform<uint16_t>(*gen, 0, 100);\n  absl::Uniform<int32_t>(*gen, 0, 1 << 10);\n  absl::Uniform<uint32_t>(*gen, 0, 1 << 10);\n  absl::Uniform<int64_t>(*gen, 0, 1 << 10);\n  absl::Uniform<uint64_t>(*gen, 0, 1 << 10);\n\n  absl::Uniform<float>(*gen, 0.0, 1.0);\n  absl::Uniform<float>(*gen, 0, 1);\n  absl::Uniform<float>(*gen, -1, 1);\n  absl::Uniform<double>(*gen, 0.0, 1.0);\n\n  absl::Uniform<float>(*gen, -1.0, 0);\n  absl::Uniform<double>(*gen, -1.0, 0);\n\n  // Tagged\n  absl::Uniform<double>(absl::IntervalClosedClosed, *gen, 0, 1);\n  absl::Uniform<double>(absl::IntervalClosedOpen, *gen, 0, 1);\n  absl::Uniform<double>(absl::IntervalOpenOpen, *gen, 0, 1);\n  absl::Uniform<double>(absl::IntervalOpenClosed, *gen, 0, 1);\n  absl::Uniform<double>(absl::IntervalClosedClosed, *gen, 0, 1);\n  absl::Uniform<double>(absl::IntervalOpenOpen, *gen, 0, 1);\n\n  absl::Uniform<int>(absl::IntervalClosedClosed, *gen, 0, 100);\n  absl::Uniform<int>(absl::IntervalClosedOpen, *gen, 0, 100);\n  absl::Uniform<int>(absl::IntervalOpenOpen, *gen, 0, 100);\n  absl::Uniform<int>(absl::IntervalOpenClosed, *gen, 0, 100);\n  absl::Uniform<int>(absl::IntervalClosedClosed, *gen, 0, 100);\n  absl::Uniform<int>(absl::IntervalOpenOpen, *gen, 0, 100);\n\n  // With *generator as an R-value reference.\n  absl::Uniform<int>(URBG(), 0, 100);\n  absl::Uniform<double>(URBG(), 0.0, 1.0);\n}\n\ntemplate <typename URBG>\nvoid TestExponential(URBG* gen) {\n  absl::Exponential<float>(*gen);\n  absl::Exponential<double>(*gen);\n  absl::Exponential<double>(URBG());\n}\n\ntemplate <typename URBG>\nvoid TestPoisson(URBG* gen) {\n  // [rand.dist.pois] Indicates that the std::poisson_distribution\n  // is parameterized by IntType, however MSVC does not allow 8-bit\n  // types.\n  absl::Poisson<int>(*gen);\n  absl::Poisson<int16_t>(*gen);\n  absl::Poisson<uint16_t>(*gen);\n  absl::Poisson<int32_t>(*gen);\n  absl::Poisson<uint32_t>(*gen);\n  absl::Poisson<int64_t>(*gen);\n  absl::Poisson<uint64_t>(*gen);\n  absl::Poisson<uint64_t>(URBG());\n  absl::Poisson<absl::int128>(*gen);\n  absl::Poisson<absl::uint128>(*gen);\n}\n\ntemplate <typename URBG>\nvoid TestBernoulli(URBG* gen) {\n  absl::Bernoulli(*gen, 0.5);\n  absl::Bernoulli(*gen, 0.5);\n}\n\ntemplate <typename URBG>\nvoid TestZipf(URBG* gen) {\n  absl::Zipf<int>(*gen, 100);\n  absl::Zipf<int8_t>(*gen, 100);\n  absl::Zipf<int16_t>(*gen, 100);\n  absl::Zipf<uint16_t>(*gen, 100);\n  absl::Zipf<int32_t>(*gen, 1 << 10);\n  absl::Zipf<uint32_t>(*gen, 1 << 10);\n  absl::Zipf<int64_t>(*gen, 1 << 10);\n  absl::Zipf<uint64_t>(*gen, 1 << 10);\n  absl::Zipf<uint64_t>(URBG(), 1 << 10);\n  absl::Zipf<absl::int128>(*gen, 1 << 10);\n  absl::Zipf<absl::uint128>(*gen, 1 << 10);\n}\n\ntemplate <typename URBG>\nvoid TestGaussian(URBG* gen) {\n  absl::Gaussian<float>(*gen, 1.0, 1.0);\n  absl::Gaussian<double>(*gen, 1.0, 1.0);\n  absl::Gaussian<double>(URBG(), 1.0, 1.0);\n}\n\ntemplate <typename URBG>\nvoid TestLogNormal(URBG* gen) {\n  absl::LogUniform<int>(*gen, 0, 100);\n  absl::LogUniform<int8_t>(*gen, 0, 100);\n  absl::LogUniform<int16_t>(*gen, 0, 100);\n  absl::LogUniform<uint16_t>(*gen, 0, 100);\n  absl::LogUniform<int32_t>(*gen, 0, 1 << 10);\n  absl::LogUniform<uint32_t>(*gen, 0, 1 << 10);\n  absl::LogUniform<int64_t>(*gen, 0, 1 << 10);\n  absl::LogUniform<uint64_t>(*gen, 0, 1 << 10);\n  absl::LogUniform<uint64_t>(URBG(), 0, 1 << 10);\n  absl::LogUniform<absl::int128>(*gen, 0, 1 << 10);\n  absl::LogUniform<absl::uint128>(*gen, 0, 1 << 10);\n}\n\ntemplate <typename URBG>\nvoid CompatibilityTest() {\n  URBG gen;\n\n  TestUniform(&gen);\n  TestExponential(&gen);\n  TestPoisson(&gen);\n  TestBernoulli(&gen);\n  TestZipf(&gen);\n  TestGaussian(&gen);\n  TestLogNormal(&gen);\n}\n\nTEST(std_mt19937_64, Compatibility) {\n  // Validate with std::mt19937_64\n  CompatibilityTest<std::mt19937_64>();\n}\n\nTEST(BitGen, Compatibility) {\n  // Validate with absl::BitGen\n  CompatibilityTest<absl::BitGen>();\n}\n\nTEST(InsecureBitGen, Compatibility) {\n  // Validate with absl::InsecureBitGen\n  CompatibilityTest<absl::InsecureBitGen>();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\n\n# Internal-only implementation classes for Abseil Random\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\ndefault_package_visibility = [\n    \"//absl/random:__pkg__\",\n    \"//absl:friends\",\n]\n\npackage(\n    default_visibility = default_package_visibility,\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\n# Used to select on compilers that support GCC-compatible options\n# (e.g. \"-maes\").\nselects.config_setting_group(\n    name = \"gcc_compatible\",\n    match_any = [\n        \"@rules_cc//cc/compiler:clang\",\n        \"@rules_cc//cc/compiler:gcc\",\n    ],\n)\n\nselects.config_setting_group(\n    name = \"gcc_compatible-aarch32\",\n    match_all = [\n        \":gcc_compatible\",\n        \"@platforms//cpu:aarch32\",\n    ],\n)\n\nselects.config_setting_group(\n    name = \"gcc_compatible-aarch64\",\n    match_all = [\n        \":gcc_compatible\",\n        \"@platforms//cpu:aarch64\",\n    ],\n)\n\nselects.config_setting_group(\n    name = \"ppc_crypto\",\n    match_any = [\n        \"@platforms//cpu:ppc\",\n        \"@platforms//cpu:ppc32\",\n        \"@platforms//cpu:ppc64le\",\n    ],\n)\n\nselects.config_setting_group(\n    name = \"gcc_compatible-ppc_crypto\",\n    match_all = [\n        \":gcc_compatible\",\n        \":ppc_crypto\",\n    ],\n)\n\nselects.config_setting_group(\n    name = \"gcc_compatible-x86_64\",\n    match_all = [\n        \":gcc_compatible\",\n        \"@platforms//cpu:x86_64\",\n    ],\n)\n\n# Some libraries are compiled with options to generate AES-NI\n# instructions, and runtime dispatch is used to determine if the host\n# microarchitecture supports AES-NI or if a portable fallback library\n# should be called.\nABSL_RANDOM_RANDEN_COPTS = select({\n    \":gcc_compatible-aarch32\": [\"-mfpu=neon\"],\n    \":gcc_compatible-aarch64\": [\"-march=armv8-a+crypto\"],\n    \":gcc_compatible-ppc_crypto\": [\"-mcrypto\"],\n    \":gcc_compatible-x86_64\": [\n        \"-maes\",\n        \"-msse4.1\",\n    ],\n    \"//conditions:default\": [],\n})\n\ncc_library(\n    name = \"traits\",\n    hdrs = [\"traits.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/numeric:bits\",\n        \"//absl/numeric:int128\",\n    ],\n)\n\ncc_library(\n    name = \"distribution_caller\",\n    hdrs = [\"distribution_caller.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/meta:type_traits\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"fast_uniform_bits\",\n    hdrs = [\n        \"fast_uniform_bits.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":traits\",\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"seed_material\",\n    srcs = [\n        \"seed_material.cc\",\n    ],\n    hdrs = [\n        \"seed_material.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [\"-DEFAULTLIB:bcrypt.lib\"],\n        \"@rules_cc//cc/compiler:clang-cl\": [\"-DEFAULTLIB:bcrypt.lib\"],\n        \"//absl:mingw_compiler\": [\n            \"-DEFAULTLIB:bcrypt.lib\",\n            \"-lbcrypt\",\n        ],\n        \"//conditions:default\": [],\n    }),\n    deps = [\n        \":fast_uniform_bits\",\n        \"//absl/base:config\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"//absl/types:optional\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"entropy_pool\",\n    srcs = [\"entropy_pool.cc\"],\n    hdrs = [\"entropy_pool.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"@rules_cc//cc/compiler:clang-cl\": [],\n        \"@rules_cc//cc/compiler:emscripten\": [],\n        \"//conditions:default\": [\"-pthread\"],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":platform\",\n        \":randen\",\n        \":seed_material\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/random:seed_gen_exception\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"explicit_seed_seq\",\n    testonly = True,\n    hdrs = [\n        \"explicit_seed_seq.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:endian\",\n    ],\n)\n\ncc_library(\n    name = \"sequence_urbg\",\n    testonly = True,\n    hdrs = [\n        \"sequence_urbg.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\"//absl/base:config\"],\n)\n\ncc_library(\n    name = \"salted_seed_seq\",\n    hdrs = [\n        \"salted_seed_seq.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":seed_material\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/meta:type_traits\",\n        \"//absl/types:optional\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"iostream_state_saver\",\n    hdrs = [\"iostream_state_saver.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:int128\",\n    ],\n)\n\ncc_library(\n    name = \"generate_real\",\n    hdrs = [\n        \"generate_real.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fastmath\",\n        \":traits\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n    ],\n)\n\ncc_library(\n    name = \"fastmath\",\n    hdrs = [\n        \"fastmath.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\"//absl/numeric:bits\"],\n)\n\ncc_library(\n    name = \"wide_multiply\",\n    hdrs = [\"wide_multiply.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":traits\",\n        \"//absl/base:config\",\n        \"//absl/numeric:bits\",\n        \"//absl/numeric:int128\",\n    ],\n)\n\ncc_library(\n    name = \"nonsecure_base\",\n    hdrs = [\"nonsecure_base.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":entropy_pool\",\n        \":salted_seed_seq\",\n        \":seed_material\",\n        \"//absl/base:config\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"pcg_engine\",\n    hdrs = [\"pcg_engine.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fastmath\",\n        \":iostream_state_saver\",\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/numeric:int128\",\n    ],\n)\n\ncc_library(\n    name = \"randen_engine\",\n    hdrs = [\"randen_engine.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = default_package_visibility + [\n    ],\n    deps = [\n        \":iostream_state_saver\",\n        \":randen\",\n        \"//absl/base:endian\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"platform\",\n    srcs = [\n        \"randen_round_keys.cc\",\n    ],\n    hdrs = [\n        \"randen_traits.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    textual_hdrs = [\n        \"platform.h\",\n    ],\n    deps = [\"//absl/base:config\"],\n)\n\ncc_library(\n    name = \"randen\",\n    srcs = [\n        \"randen.cc\",\n    ],\n    hdrs = [\n        \"randen.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":platform\",\n        \":randen_hwaes\",\n        \":randen_slow\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"randen_slow\",\n    srcs = [\"randen_slow.cc\"],\n    hdrs = [\"randen_slow.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":platform\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/numeric:int128\",\n    ],\n)\n\ncc_library(\n    name = \"randen_hwaes\",\n    srcs = [\n        \"randen_detect.cc\",\n    ],\n    hdrs = [\n        \"randen_detect.h\",\n        \"randen_hwaes.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":platform\",\n        \":randen_hwaes_impl\",\n        \"//absl/base:config\",\n    ],\n)\n\n# build with --save_temps to see assembly language output.\ncc_library(\n    name = \"randen_hwaes_impl\",\n    srcs = [\n        \"randen_hwaes.cc\",\n        \"randen_hwaes.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS + ABSL_RANDOM_RANDEN_COPTS + select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"@rules_cc//cc/compiler:clang-cl\": [],\n        \"//conditions:default\": [\"-Wno-pass-failed\"],\n    }),\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":platform\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/numeric:int128\",\n    ],\n)\n\ncc_binary(\n    name = \"gaussian_distribution_gentables\",\n    srcs = [\n        \"gaussian_distribution_gentables.cc\",\n    ],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:core_headers\",\n        \"//absl/random:distributions\",\n    ],\n)\n\ncc_library(\n    name = \"distribution_test_util\",\n    testonly = True,\n    srcs = [\n        \"chi_square.cc\",\n        \"distribution_test_util.cc\",\n    ],\n    hdrs = [\n        \"chi_square.h\",\n        \"distribution_test_util.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:span\",\n    ],\n)\n\n# Common tags for tests, etc.\nABSL_RANDOM_NONPORTABLE_TAGS = [\n    \"no_test_android_arm\",\n    \"no_test_android_arm64\",\n    \"no_test_android_x86\",\n    \"no_test_darwin_x86_64\",\n    \"no_test_ios_x86_64\",\n    \"no_test_loonix\",\n    \"no_test_lexan\",\n    \"no_test_wasm\",\n]\n\ncc_test(\n    name = \"traits_test\",\n    size = \"small\",\n    srcs = [\"traits_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"generate_real_test\",\n    size = \"small\",\n    srcs = [\n        \"generate_real_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":generate_real\",\n        \"//absl/flags:flag\",\n        \"//absl/numeric:bits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"distribution_test_util_test\",\n    size = \"small\",\n    srcs = [\"distribution_test_util_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distribution_test_util\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"fastmath_test\",\n    size = \"small\",\n    srcs = [\"fastmath_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fastmath\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"explicit_seed_seq_test\",\n    size = \"small\",\n    srcs = [\"explicit_seed_seq_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":explicit_seed_seq\",\n        \"//absl/random:seed_sequences\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"salted_seed_seq_test\",\n    size = \"small\",\n    srcs = [\"salted_seed_seq_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":salted_seed_seq\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"chi_square_test\",\n    size = \"small\",\n    srcs = [\n        \"chi_square_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":distribution_test_util\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"fast_uniform_bits_test\",\n    size = \"small\",\n    srcs = [\n        \"fast_uniform_bits_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":fast_uniform_bits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"mock_helpers\",\n    hdrs = [\"mock_helpers.h\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:fast_type_id\",\n        \"//absl/types:optional\",\n    ],\n)\n\ncc_library(\n    name = \"mock_overload_set\",\n    testonly = True,\n    hdrs = [\"mock_overload_set.h\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":mock_helpers\",\n        \"//absl/base:config\",\n        \"//absl/random:mocking_bit_gen\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"nonsecure_base_test\",\n    size = \"small\",\n    srcs = [\n        \"nonsecure_base_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":nonsecure_base\",\n        \"//absl/container:flat_hash_set\",\n        \"//absl/meta:type_traits\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"seed_material_test\",\n    size = \"small\",\n    srcs = [\"seed_material_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":seed_material\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"entropy_pool_test\",\n    size = \"small\",\n    srcs = [\n        \"entropy_pool_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":entropy_pool\",\n        \"//absl/container:flat_hash_set\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"pcg_engine_test\",\n    size = \"medium\",  # Trying to measure accuracy.\n    srcs = [\"pcg_engine_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":explicit_seed_seq\",\n        \":pcg_engine\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"randen_engine_test\",\n    size = \"medium\",\n    srcs = [\n        \"randen_engine_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":explicit_seed_seq\",\n        \":randen_engine\",\n        \"//absl/log\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"randen_test\",\n    size = \"small\",\n    srcs = [\"randen_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":randen\",\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"randen_slow_test\",\n    size = \"small\",\n    srcs = [\"randen_slow_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":platform\",\n        \":randen_slow\",\n        \"//absl/base:endian\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"randen_hwaes_test\",\n    size = \"small\",\n    srcs = [\"randen_hwaes_test.cc\"],\n    copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = ABSL_RANDOM_NONPORTABLE_TAGS,\n    deps = [\n        \":platform\",\n        \":randen_hwaes\",\n        \":randen_hwaes_impl\",  # build_cleaner: keep\n        \"//absl/log\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"wide_multiply_test\",\n    size = \"small\",\n    srcs = [\"wide_multiply_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":wide_multiply\",\n        \"//absl/numeric:int128\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"nanobenchmark\",\n    srcs = [\"nanobenchmark.cc\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    textual_hdrs = [\"nanobenchmark.h\"],\n    deps = [\n        \":platform\",\n        \":randen_engine\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"uniform_helper\",\n    hdrs = [\"uniform_helper.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":traits\",\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"mock_validators\",\n    hdrs = [\"mock_validators.h\"],\n    deps = [\n        \":iostream_state_saver\",\n        \":uniform_helper\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n        \"//absl/strings:string_view\",\n    ],\n)\n\ncc_test(\n    name = \"nanobenchmark_test\",\n    size = \"small\",\n    srcs = [\"nanobenchmark_test.cc\"],\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"benchmark\",\n        \"no_test_ios_sim_arm64\",\n        \"no_test_ios_x86_64\",\n        \"no_test_loonix\",  # Crashing.\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":nanobenchmark\",\n        \"//absl/log\",\n        \"//absl/log:check\",\n        \"//absl/strings\",\n        \"//absl/strings:str_format\",\n    ],\n)\n\ncc_test(\n    name = \"randen_benchmarks\",\n    size = \"medium\",\n    timeout = \"long\",\n    srcs = [\"randen_benchmarks.cc\"],\n    copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = ABSL_RANDOM_NONPORTABLE_TAGS + [\"benchmark\"],\n    deps = [\n        \":nanobenchmark\",\n        \":platform\",\n        \":randen\",\n        \":randen_engine\",\n        \":randen_hwaes\",\n        \":randen_hwaes_impl\",\n        \":randen_slow\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/strings\",\n    ],\n)\n\ncc_test(\n    name = \"iostream_state_saver_test\",\n    srcs = [\"iostream_state_saver_test.cc\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":iostream_state_saver\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"uniform_helper_test\",\n    size = \"small\",\n    srcs = [\"uniform_helper_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":uniform_helper\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/random/internal/chi_square.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/chi_square.h\"\n\n#include <cmath>\n\n#include \"absl/random/internal/distribution_test_util.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\n#if defined(__EMSCRIPTEN__)\n// Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found.\ninline double fma(double x, double y, double z) { return (x * y) + z; }\n#endif\n\n// Use Horner's method to evaluate a polynomial.\ntemplate <typename T, unsigned N>\ninline T EvaluatePolynomial(T x, const T (&poly)[N]) {\n#if !defined(__EMSCRIPTEN__)\n  using std::fma;\n#endif\n  T p = poly[N - 1];\n  for (unsigned i = 2; i <= N; i++) {\n    p = fma(p, x, poly[N - i]);\n  }\n  return p;\n}\n\nstatic constexpr int kLargeDOF = 150;\n\n// Returns the probability of a normal z-value.\n//\n// Adapted from the POZ function in:\n//     Ibbetson D, Algorithm 209\n//     Collected Algorithms of the CACM 1963 p. 616\n//\ndouble POZ(double z) {\n  static constexpr double kP1[] = {\n      0.797884560593,  -0.531923007300, 0.319152932694,\n      -0.151968751364, 0.059054035642,  -0.019198292004,\n      0.005198775019,  -0.001075204047, 0.000124818987,\n  };\n  static constexpr double kP2[] = {\n      0.999936657524,  0.000535310849,  -0.002141268741, 0.005353579108,\n      -0.009279453341, 0.011630447319,  -0.010557625006, 0.006549791214,\n      -0.002034254874, -0.000794620820, 0.001390604284,  -0.000676904986,\n      -0.000019538132, 0.000152529290,  -0.000045255659,\n  };\n\n  const double kZMax = 6.0;  // Maximum meaningful z-value.\n  if (z == 0.0) {\n    return 0.5;\n  }\n  double x;\n  double y = 0.5 * std::fabs(z);\n  if (y >= (kZMax * 0.5)) {\n    x = 1.0;\n  } else if (y < 1.0) {\n    double w = y * y;\n    x = EvaluatePolynomial(w, kP1) * y * 2.0;\n  } else {\n    y -= 2.0;\n    x = EvaluatePolynomial(y, kP2);\n  }\n  return z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5);\n}\n\n// Approximates the survival function of the normal distribution.\n//\n// Algorithm 26.2.18, from:\n// [Abramowitz and Stegun, Handbook of Mathematical Functions,p.932]\n// http://people.math.sfu.ca/~cbm/aands/abramowitz_and_stegun.pdf\n//\ndouble normal_survival(double z) {\n  // Maybe replace with the alternate formulation.\n  // 0.5 * erfc((x - mean)/(sqrt(2) * sigma))\n  static constexpr double kR[] = {\n      1.0, 0.196854, 0.115194, 0.000344, 0.019527,\n  };\n  double r = EvaluatePolynomial(z, kR);\n  r *= r;\n  return 0.5 / (r * r);\n}\n\n}  // namespace\n\n// Calculates the critical chi-square value given degrees-of-freedom and a\n// p-value, usually using bisection. Also known by the name CRITCHI.\ndouble ChiSquareValue(int dof, double p) {\n  static constexpr double kChiEpsilon =\n      0.000001;                               // Accuracy of the approximation.\n  static constexpr double kChiMax = 99999.0;  // Maximum chi-squared value.\n\n  const double p_value = 1.0 - p;\n  if (dof < 1 || p_value > 1.0) {\n    return 0.0;\n  }\n\n  if (dof > kLargeDOF) {\n    // For large degrees of freedom, use the normal approximation by\n    //     Wilson, E. B. and Hilferty, M. M. (1931)\n    //                     chi^2 - mean\n    //                Z = --------------\n    //                        stddev\n    const double z = InverseNormalSurvival(p_value);\n    const double mean = 1 - 2.0 / (9 * dof);\n    const double variance = 2.0 / (9 * dof);\n    // Cannot use this method if the variance is 0.\n    if (variance != 0) {\n      double term = z * std::sqrt(variance) + mean;\n      return dof * (term * term * term);\n    }\n  }\n\n  if (p_value <= 0.0) return kChiMax;\n\n  // Otherwise search for the p value by bisection\n  double min_chisq = 0.0;\n  double max_chisq = kChiMax;\n  double current = dof / std::sqrt(p_value);\n  while ((max_chisq - min_chisq) > kChiEpsilon) {\n    if (ChiSquarePValue(current, dof) < p_value) {\n      max_chisq = current;\n    } else {\n      min_chisq = current;\n    }\n    current = (max_chisq + min_chisq) * 0.5;\n  }\n  return current;\n}\n\n// Calculates the p-value (probability) of a given chi-square value\n// and degrees of freedom.\n//\n// Adapted from the POCHISQ function from:\n//     Hill, I. D. and Pike, M. C.  Algorithm 299\n//     Collected Algorithms of the CACM 1963 p. 243\n//\ndouble ChiSquarePValue(double chi_square, int dof) {\n  static constexpr double kLogSqrtPi =\n      0.5723649429247000870717135;  // Log[Sqrt[Pi]]\n  static constexpr double kInverseSqrtPi =\n      0.5641895835477562869480795;  // 1/(Sqrt[Pi])\n\n  // For large degrees of freedom, use the normal approximation by\n  //     Wilson, E. B. and Hilferty, M. M. (1931)\n  // Via Wikipedia:\n  //   By the Central Limit Theorem, because the chi-square distribution is the\n  //   sum of k independent random variables with finite mean and variance, it\n  //   converges to a normal distribution for large k.\n  if (dof > kLargeDOF) {\n    // Re-scale everything.\n    const double chi_square_scaled = std::pow(chi_square / dof, 1.0 / 3);\n    const double mean = 1 - 2.0 / (9 * dof);\n    const double variance = 2.0 / (9 * dof);\n    // If variance is 0, this method cannot be used.\n    if (variance != 0) {\n      const double z = (chi_square_scaled - mean) / std::sqrt(variance);\n      if (z > 0) {\n        return normal_survival(z);\n      } else if (z < 0) {\n        return 1.0 - normal_survival(-z);\n      } else {\n        return 0.5;\n      }\n    }\n  }\n\n  // The chi square function is >= 0 for any degrees of freedom.\n  // In other words, probability that the chi square function >= 0 is 1.\n  if (chi_square <= 0.0) return 1.0;\n\n  // If the degrees of freedom is zero, the chi square function is always 0 by\n  // definition. In other words, the probability that the chi square function\n  // is > 0 is zero (chi square values <= 0 have been filtered above).\n  if (dof < 1) return 0;\n\n  auto capped_exp = [](double x) { return x < -20 ? 0.0 : std::exp(x); };\n  static constexpr double kBigX = 20;\n\n  double a = 0.5 * chi_square;\n  const bool even = !(dof & 1);  // True if dof is an even number.\n  const double y = capped_exp(-a);\n  double s = even ? y : (2.0 * POZ(-std::sqrt(chi_square)));\n\n  if (dof <= 2) {\n    return s;\n  }\n\n  chi_square = 0.5 * (dof - 1.0);\n  double z = (even ? 1.0 : 0.5);\n  if (a > kBigX) {\n    double e = (even ? 0.0 : kLogSqrtPi);\n    double c = std::log(a);\n    while (z <= chi_square) {\n      e = std::log(z) + e;\n      s += capped_exp(c * z - a - e);\n      z += 1.0;\n    }\n    return s;\n  }\n\n  double e = (even ? 1.0 : (kInverseSqrtPi / std::sqrt(a)));\n  double c = 0.0;\n  while (z <= chi_square) {\n    e = e * (a / z);\n    c = c + e;\n    z += 1.0;\n  }\n  return c * y + s;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/chi_square.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_\n#define ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_\n\n// The chi-square statistic.\n//\n// Useful for evaluating if `D` independent random variables are behaving as\n// expected, or if two distributions are similar.  (`D` is the degrees of\n// freedom).\n//\n// Each bucket should have an expected count of 10 or more for the chi square to\n// be meaningful.\n\n#include <cassert>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\nconstexpr const char kChiSquared[] = \"chi-squared\";\n\n// Returns the measured chi square value, using a single expected value.  This\n// assumes that the values in [begin, end) are uniformly distributed.\ntemplate <typename Iterator>\ndouble ChiSquareWithExpected(Iterator begin, Iterator end, double expected) {\n  // Compute the sum and the number of buckets.\n  assert(expected >= 10);  // require at least 10 samples per bucket.\n  double chi_square = 0;\n  for (auto it = begin; it != end; it++) {\n    double d = static_cast<double>(*it) - expected;\n    chi_square += d * d;\n  }\n  chi_square = chi_square / expected;\n  return chi_square;\n}\n\n// Returns the measured chi square value, taking the actual value of each bucket\n// from the first set of iterators, and the expected value of each bucket from\n// the second set of iterators.\ntemplate <typename Iterator, typename Expected>\ndouble ChiSquare(Iterator it, Iterator end, Expected eit, Expected eend) {\n  double chi_square = 0;\n  for (; it != end && eit != eend; ++it, ++eit) {\n    if (*it > 0) {\n      assert(*eit > 0);\n    }\n    double e = static_cast<double>(*eit);\n    double d = static_cast<double>(*it - *eit);\n    if (d != 0) {\n      assert(e > 0);\n      chi_square += (d * d) / e;\n    }\n  }\n  assert(it == end && eit == eend);\n  return chi_square;\n}\n\n// ======================================================================\n// The following methods can be used for an arbitrary significance level.\n//\n\n// Calculates critical chi-square values to produce the given p-value using a\n// bisection search for a value within epsilon, relying on the monotonicity of\n// ChiSquarePValue().\ndouble ChiSquareValue(int dof, double p);\n\n// Calculates the p-value (probability) of a given chi-square value.\ndouble ChiSquarePValue(double chi_square, int dof);\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_\n"
  },
  {
    "path": "absl/random/internal/chi_square_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/chi_square.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <numeric>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n\nusing absl::random_internal::ChiSquare;\nusing absl::random_internal::ChiSquarePValue;\nusing absl::random_internal::ChiSquareValue;\nusing absl::random_internal::ChiSquareWithExpected;\n\nnamespace {\n\nTEST(ChiSquare, Value) {\n  struct {\n    int line;\n    double chi_square;\n    int df;\n    double confidence;\n  } const specs[] = {\n      // Testing lookup at 1% confidence\n      {__LINE__, 0, 0, 0.01},\n      {__LINE__, 0.00016, 1, 0.01},\n      {__LINE__, 1.64650, 8, 0.01},\n      {__LINE__, 5.81221, 16, 0.01},\n      {__LINE__, 156.4319, 200, 0.01},\n      {__LINE__, 1121.3784, 1234, 0.01},\n      {__LINE__, 53557.1629, 54321, 0.01},\n      {__LINE__, 651662.6647, 654321, 0.01},\n\n      // Testing lookup at 99% confidence\n      {__LINE__, 0, 0, 0.99},\n      {__LINE__, 6.635, 1, 0.99},\n      {__LINE__, 20.090, 8, 0.99},\n      {__LINE__, 32.000, 16, 0.99},\n      {__LINE__, 249.4456, 200, 0.99},\n      {__LINE__, 1131.1573, 1023, 0.99},\n      {__LINE__, 1352.5038, 1234, 0.99},\n      {__LINE__, 55090.7356, 54321, 0.99},\n      {__LINE__, 656985.1514, 654321, 0.99},\n\n      // Testing lookup at 99.9% confidence\n      {__LINE__, 16.2659, 3, 0.999},\n      {__LINE__, 22.4580, 6, 0.999},\n      {__LINE__, 267.5409, 200, 0.999},\n      {__LINE__, 1168.5033, 1023, 0.999},\n      {__LINE__, 55345.1741, 54321, 0.999},\n      {__LINE__, 657861.7284, 654321, 0.999},\n      {__LINE__, 51.1772, 24, 0.999},\n      {__LINE__, 59.7003, 30, 0.999},\n      {__LINE__, 37.6984, 15, 0.999},\n      {__LINE__, 29.5898, 10, 0.999},\n      {__LINE__, 27.8776, 9, 0.999},\n\n      // Testing lookup at random confidences\n      {__LINE__, 0.000157088, 1, 0.01},\n      {__LINE__, 5.31852, 2, 0.93},\n      {__LINE__, 1.92256, 4, 0.25},\n      {__LINE__, 10.7709, 13, 0.37},\n      {__LINE__, 26.2514, 17, 0.93},\n      {__LINE__, 36.4799, 29, 0.84},\n      {__LINE__, 25.818, 31, 0.27},\n      {__LINE__, 63.3346, 64, 0.50},\n      {__LINE__, 196.211, 128, 0.9999},\n      {__LINE__, 215.21, 243, 0.10},\n      {__LINE__, 285.393, 256, 0.90},\n      {__LINE__, 984.504, 1024, 0.1923},\n      {__LINE__, 2043.85, 2048, 0.4783},\n      {__LINE__, 48004.6, 48273, 0.194},\n  };\n  for (const auto& spec : specs) {\n    SCOPED_TRACE(spec.line);\n    // Verify all values are have at most a 1% relative error.\n    const double val = ChiSquareValue(spec.df, spec.confidence);\n    const double err = std::max(5e-6, spec.chi_square / 5e3);  // 1 part in 5000\n    EXPECT_NEAR(spec.chi_square, val, err) << spec.line;\n  }\n\n  // Relaxed test for extreme values, from\n  //  http://www.ciphersbyritter.com/JAVASCRP/NORMCHIK.HTM#ChiSquare\n  EXPECT_NEAR(49.2680, ChiSquareValue(100, 1e-6), 5);  // 0.000'005 mark\n  EXPECT_NEAR(123.499, ChiSquareValue(200, 1e-6), 5);  // 0.000'005 mark\n\n  EXPECT_NEAR(149.449, ChiSquareValue(100, 0.999), 0.01);\n  EXPECT_NEAR(161.318, ChiSquareValue(100, 0.9999), 0.01);\n  EXPECT_NEAR(172.098, ChiSquareValue(100, 0.99999), 0.01);\n\n  EXPECT_NEAR(381.426, ChiSquareValue(300, 0.999), 0.05);\n  EXPECT_NEAR(399.756, ChiSquareValue(300, 0.9999), 0.1);\n  EXPECT_NEAR(416.126, ChiSquareValue(300, 0.99999), 0.2);\n}\n\nTEST(ChiSquareTest, PValue) {\n  struct {\n    int line;\n    double pval;\n    double chi_square;\n    int df;\n  } static const specs[] = {\n      {__LINE__, 1, 0, 0},\n      {__LINE__, 0, 0.001, 0},\n      {__LINE__, 1.000, 0, 453},\n      {__LINE__, 0.134471, 7972.52, 7834},\n      {__LINE__, 0.203922, 28.32, 23},\n      {__LINE__, 0.737171, 48274, 48472},\n      {__LINE__, 0.444146, 583.1234, 579},\n      {__LINE__, 0.294814, 138.2, 130},\n      {__LINE__, 0.0816532, 12.63, 7},\n      {__LINE__, 0, 682.32, 67},\n      {__LINE__, 0.49405, 999, 999},\n      {__LINE__, 1.000, 0, 9999},\n      {__LINE__, 0.997477, 0.00001, 1},\n      {__LINE__, 0, 5823.21, 5040},\n  };\n  for (const auto& spec : specs) {\n    SCOPED_TRACE(spec.line);\n    const double pval = ChiSquarePValue(spec.chi_square, spec.df);\n    EXPECT_NEAR(spec.pval, pval, 1e-3);\n  }\n}\n\nTEST(ChiSquareTest, CalcChiSquare) {\n  struct {\n    int line;\n    std::vector<int> expected;\n    std::vector<int> actual;\n  } const specs[] = {\n      {__LINE__,\n       {56, 234, 76, 1, 546, 1, 87, 345, 1, 234},\n       {2, 132, 4, 43, 234, 8, 345, 8, 236, 56}},\n      {__LINE__,\n       {123, 36, 234, 367, 345, 2, 456, 567, 234, 567},\n       {123, 56, 2345, 8, 345, 8, 2345, 23, 48, 267}},\n      {__LINE__,\n       {123, 234, 345, 456, 567, 678, 789, 890, 98, 76},\n       {123, 234, 345, 456, 567, 678, 789, 890, 98, 76}},\n      {__LINE__, {3, 675, 23, 86, 2, 8, 2}, {456, 675, 23, 86, 23, 65, 2}},\n      {__LINE__, {1}, {23}},\n  };\n  for (const auto& spec : specs) {\n    SCOPED_TRACE(spec.line);\n    double chi_square = 0;\n    for (int i = 0; i < spec.expected.size(); ++i) {\n      const double diff = spec.actual[i] - spec.expected[i];\n      chi_square += (diff * diff) / spec.expected[i];\n    }\n    EXPECT_NEAR(chi_square,\n                ChiSquare(std::begin(spec.actual), std::end(spec.actual),\n                          std::begin(spec.expected), std::end(spec.expected)),\n                1e-5);\n  }\n}\n\nTEST(ChiSquareTest, CalcChiSquareInt64) {\n  const int64_t data[3] = {910293487, 910292491, 910216780};\n  // $ python -c \"import scipy.stats\n  // > print scipy.stats.chisquare([910293487, 910292491, 910216780])[0]\"\n  // 4.25410123524\n  double sum = std::accumulate(std::begin(data), std::end(data), double{0});\n  size_t n = std::distance(std::begin(data), std::end(data));\n  double a = ChiSquareWithExpected(std::begin(data), std::end(data), sum / n);\n  EXPECT_NEAR(4.254101, a, 1e-6);\n\n  // ... Or with known values.\n  double b =\n      ChiSquareWithExpected(std::begin(data), std::end(data), 910267586.0);\n  EXPECT_NEAR(4.254101, b, 1e-6);\n}\n\nTEST(ChiSquareTest, TableData) {\n  // Test data from\n  // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm\n  //    0.90      0.95     0.975      0.99     0.999\n  const double data[100][5] = {\n      /* 1*/ {2.706, 3.841, 5.024, 6.635, 10.828},\n      /* 2*/ {4.605, 5.991, 7.378, 9.210, 13.816},\n      /* 3*/ {6.251, 7.815, 9.348, 11.345, 16.266},\n      /* 4*/ {7.779, 9.488, 11.143, 13.277, 18.467},\n      /* 5*/ {9.236, 11.070, 12.833, 15.086, 20.515},\n      /* 6*/ {10.645, 12.592, 14.449, 16.812, 22.458},\n      /* 7*/ {12.017, 14.067, 16.013, 18.475, 24.322},\n      /* 8*/ {13.362, 15.507, 17.535, 20.090, 26.125},\n      /* 9*/ {14.684, 16.919, 19.023, 21.666, 27.877},\n      /*10*/ {15.987, 18.307, 20.483, 23.209, 29.588},\n      /*11*/ {17.275, 19.675, 21.920, 24.725, 31.264},\n      /*12*/ {18.549, 21.026, 23.337, 26.217, 32.910},\n      /*13*/ {19.812, 22.362, 24.736, 27.688, 34.528},\n      /*14*/ {21.064, 23.685, 26.119, 29.141, 36.123},\n      /*15*/ {22.307, 24.996, 27.488, 30.578, 37.697},\n      /*16*/ {23.542, 26.296, 28.845, 32.000, 39.252},\n      /*17*/ {24.769, 27.587, 30.191, 33.409, 40.790},\n      /*18*/ {25.989, 28.869, 31.526, 34.805, 42.312},\n      /*19*/ {27.204, 30.144, 32.852, 36.191, 43.820},\n      /*20*/ {28.412, 31.410, 34.170, 37.566, 45.315},\n      /*21*/ {29.615, 32.671, 35.479, 38.932, 46.797},\n      /*22*/ {30.813, 33.924, 36.781, 40.289, 48.268},\n      /*23*/ {32.007, 35.172, 38.076, 41.638, 49.728},\n      /*24*/ {33.196, 36.415, 39.364, 42.980, 51.179},\n      /*25*/ {34.382, 37.652, 40.646, 44.314, 52.620},\n      /*26*/ {35.563, 38.885, 41.923, 45.642, 54.052},\n      /*27*/ {36.741, 40.113, 43.195, 46.963, 55.476},\n      /*28*/ {37.916, 41.337, 44.461, 48.278, 56.892},\n      /*29*/ {39.087, 42.557, 45.722, 49.588, 58.301},\n      /*30*/ {40.256, 43.773, 46.979, 50.892, 59.703},\n      /*31*/ {41.422, 44.985, 48.232, 52.191, 61.098},\n      /*32*/ {42.585, 46.194, 49.480, 53.486, 62.487},\n      /*33*/ {43.745, 47.400, 50.725, 54.776, 63.870},\n      /*34*/ {44.903, 48.602, 51.966, 56.061, 65.247},\n      /*35*/ {46.059, 49.802, 53.203, 57.342, 66.619},\n      /*36*/ {47.212, 50.998, 54.437, 58.619, 67.985},\n      /*37*/ {48.363, 52.192, 55.668, 59.893, 69.347},\n      /*38*/ {49.513, 53.384, 56.896, 61.162, 70.703},\n      /*39*/ {50.660, 54.572, 58.120, 62.428, 72.055},\n      /*40*/ {51.805, 55.758, 59.342, 63.691, 73.402},\n      /*41*/ {52.949, 56.942, 60.561, 64.950, 74.745},\n      /*42*/ {54.090, 58.124, 61.777, 66.206, 76.084},\n      /*43*/ {55.230, 59.304, 62.990, 67.459, 77.419},\n      /*44*/ {56.369, 60.481, 64.201, 68.710, 78.750},\n      /*45*/ {57.505, 61.656, 65.410, 69.957, 80.077},\n      /*46*/ {58.641, 62.830, 66.617, 71.201, 81.400},\n      /*47*/ {59.774, 64.001, 67.821, 72.443, 82.720},\n      /*48*/ {60.907, 65.171, 69.023, 73.683, 84.037},\n      /*49*/ {62.038, 66.339, 70.222, 74.919, 85.351},\n      /*50*/ {63.167, 67.505, 71.420, 76.154, 86.661},\n      /*51*/ {64.295, 68.669, 72.616, 77.386, 87.968},\n      /*52*/ {65.422, 69.832, 73.810, 78.616, 89.272},\n      /*53*/ {66.548, 70.993, 75.002, 79.843, 90.573},\n      /*54*/ {67.673, 72.153, 76.192, 81.069, 91.872},\n      /*55*/ {68.796, 73.311, 77.380, 82.292, 93.168},\n      /*56*/ {69.919, 74.468, 78.567, 83.513, 94.461},\n      /*57*/ {71.040, 75.624, 79.752, 84.733, 95.751},\n      /*58*/ {72.160, 76.778, 80.936, 85.950, 97.039},\n      /*59*/ {73.279, 77.931, 82.117, 87.166, 98.324},\n      /*60*/ {74.397, 79.082, 83.298, 88.379, 99.607},\n      /*61*/ {75.514, 80.232, 84.476, 89.591, 100.888},\n      /*62*/ {76.630, 81.381, 85.654, 90.802, 102.166},\n      /*63*/ {77.745, 82.529, 86.830, 92.010, 103.442},\n      /*64*/ {78.860, 83.675, 88.004, 93.217, 104.716},\n      /*65*/ {79.973, 84.821, 89.177, 94.422, 105.988},\n      /*66*/ {81.085, 85.965, 90.349, 95.626, 107.258},\n      /*67*/ {82.197, 87.108, 91.519, 96.828, 108.526},\n      /*68*/ {83.308, 88.250, 92.689, 98.028, 109.791},\n      /*69*/ {84.418, 89.391, 93.856, 99.228, 111.055},\n      /*70*/ {85.527, 90.531, 95.023, 100.425, 112.317},\n      /*71*/ {86.635, 91.670, 96.189, 101.621, 113.577},\n      /*72*/ {87.743, 92.808, 97.353, 102.816, 114.835},\n      /*73*/ {88.850, 93.945, 98.516, 104.010, 116.092},\n      /*74*/ {89.956, 95.081, 99.678, 105.202, 117.346},\n      /*75*/ {91.061, 96.217, 100.839, 106.393, 118.599},\n      /*76*/ {92.166, 97.351, 101.999, 107.583, 119.850},\n      /*77*/ {93.270, 98.484, 103.158, 108.771, 121.100},\n      /*78*/ {94.374, 99.617, 104.316, 109.958, 122.348},\n      /*79*/ {95.476, 100.749, 105.473, 111.144, 123.594},\n      /*80*/ {96.578, 101.879, 106.629, 112.329, 124.839},\n      /*81*/ {97.680, 103.010, 107.783, 113.512, 126.083},\n      /*82*/ {98.780, 104.139, 108.937, 114.695, 127.324},\n      /*83*/ {99.880, 105.267, 110.090, 115.876, 128.565},\n      /*84*/ {100.980, 106.395, 111.242, 117.057, 129.804},\n      /*85*/ {102.079, 107.522, 112.393, 118.236, 131.041},\n      /*86*/ {103.177, 108.648, 113.544, 119.414, 132.277},\n      /*87*/ {104.275, 109.773, 114.693, 120.591, 133.512},\n      /*88*/ {105.372, 110.898, 115.841, 121.767, 134.746},\n      /*89*/ {106.469, 112.022, 116.989, 122.942, 135.978},\n      /*90*/ {107.565, 113.145, 118.136, 124.116, 137.208},\n      /*91*/ {108.661, 114.268, 119.282, 125.289, 138.438},\n      /*92*/ {109.756, 115.390, 120.427, 126.462, 139.666},\n      /*93*/ {110.850, 116.511, 121.571, 127.633, 140.893},\n      /*94*/ {111.944, 117.632, 122.715, 128.803, 142.119},\n      /*95*/ {113.038, 118.752, 123.858, 129.973, 143.344},\n      /*96*/ {114.131, 119.871, 125.000, 131.141, 144.567},\n      /*97*/ {115.223, 120.990, 126.141, 132.309, 145.789},\n      /*98*/ {116.315, 122.108, 127.282, 133.476, 147.010},\n      /*99*/ {117.407, 123.225, 128.422, 134.642, 148.230},\n      /*100*/ {118.498, 124.342, 129.561, 135.807, 149.449} /**/};\n\n  //    0.90      0.95     0.975      0.99     0.999\n  for (int i = 0; i < ABSL_ARRAYSIZE(data); i++) {\n    const double E = 0.0001;\n    EXPECT_NEAR(ChiSquarePValue(data[i][0], i + 1), 0.10, E)\n        << i << \" \" << data[i][0];\n    EXPECT_NEAR(ChiSquarePValue(data[i][1], i + 1), 0.05, E)\n        << i << \" \" << data[i][1];\n    EXPECT_NEAR(ChiSquarePValue(data[i][2], i + 1), 0.025, E)\n        << i << \" \" << data[i][2];\n    EXPECT_NEAR(ChiSquarePValue(data[i][3], i + 1), 0.01, E)\n        << i << \" \" << data[i][3];\n    EXPECT_NEAR(ChiSquarePValue(data[i][4], i + 1), 0.001, E)\n        << i << \" \" << data[i][4];\n\n    const double F = 0.1;\n    EXPECT_NEAR(ChiSquareValue(i + 1, 0.90), data[i][0], F) << i;\n    EXPECT_NEAR(ChiSquareValue(i + 1, 0.95), data[i][1], F) << i;\n    EXPECT_NEAR(ChiSquareValue(i + 1, 0.975), data[i][2], F) << i;\n    EXPECT_NEAR(ChiSquareValue(i + 1, 0.99), data[i][3], F) << i;\n    EXPECT_NEAR(ChiSquareValue(i + 1, 0.999), data[i][4], F) << i;\n  }\n}\n\nTEST(ChiSquareTest, ChiSquareTwoIterator) {\n  // Test data from http://www.stat.yale.edu/Courses/1997-98/101/chigf.htm\n  // Null-hypothesis: This data is normally distributed.\n  const int counts[10] = {6, 6, 18, 33, 38, 38, 28, 21, 9, 3};\n  const double expected[10] = {4.6,  8.8,  18.4, 30.0, 38.2,\n                               38.2, 30.0, 18.4, 8.8,  4.6};\n  double chi_square = ChiSquare(std::begin(counts), std::end(counts),\n                                std::begin(expected), std::end(expected));\n  EXPECT_NEAR(chi_square, 2.69, 0.001);\n\n  // Degrees of freedom: 10 bins. two estimated parameters. = 10 - 2 - 1.\n  const int dof = 7;\n  // The critical value of 7, 95% => 14.067 (see above test)\n  double p_value_05 = ChiSquarePValue(14.067, dof);\n  EXPECT_NEAR(p_value_05, 0.05, 0.001);  // 95%-ile p-value\n\n  double p_actual = ChiSquarePValue(chi_square, dof);\n  EXPECT_GT(p_actual, 0.05);  // Accept the null hypothesis.\n}\n\nTEST(ChiSquareTest, DiceRolls) {\n  // Assume we are testing 102 fair dice rolls.\n  // Null-hypothesis: This data is fairly distributed.\n  //\n  // The dof value of 4, @95% = 9.488 (see above test)\n  // The dof value of 5, @95% = 11.070\n  const int rolls[6] = {22, 11, 17, 14, 20, 18};\n  double sum = std::accumulate(std::begin(rolls), std::end(rolls), double{0});\n  size_t n = std::distance(std::begin(rolls), std::end(rolls));\n\n  double a = ChiSquareWithExpected(std::begin(rolls), std::end(rolls), sum / n);\n  EXPECT_NEAR(a, 4.70588, 1e-5);\n  EXPECT_LT(a, ChiSquareValue(4, 0.95));\n\n  double p_a = ChiSquarePValue(a, 4);\n  EXPECT_NEAR(p_a, 0.318828, 1e-5);  // Accept the null hypothesis.\n\n  double b = ChiSquareWithExpected(std::begin(rolls), std::end(rolls), 17.0);\n  EXPECT_NEAR(b, 4.70588, 1e-5);\n  EXPECT_LT(b, ChiSquareValue(5, 0.95));\n\n  double p_b = ChiSquarePValue(b, 5);\n  EXPECT_NEAR(p_b, 0.4528180, 1e-5);  // Accept the null hypothesis.\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/distribution_caller.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_\n#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_\n\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// DistributionCaller provides an opportunity to overload the general\n// mechanism for calling a distribution, allowing for mock-RNG classes\n// to intercept such calls.\ntemplate <typename URBG>\nstruct DistributionCaller {\n  static_assert(!std::is_pointer<URBG>::value,\n                \"You must pass a reference, not a pointer.\");\n  // SFINAE to detect whether the URBG type includes a member matching\n  // bool InvokeMock(key_id, args_tuple*, result*).\n  //\n  // These live inside BitGenRef so that they have friend access\n  // to MockingBitGen. (see similar methods in DistributionCaller).\n  template <template <class...> class Trait, class AlwaysVoid, class... Args>\n  struct detector : std::false_type {};\n  template <template <class...> class Trait, class... Args>\n  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>\n      : std::true_type {};\n\n  template <class T>\n  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(\n      std::declval<FastTypeIdType>(), std::declval<void*>(),\n      std::declval<void*>()));\n\n  using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;\n\n  // Default implementation of distribution caller.\n  template <typename DistrT, typename... Args>\n  static typename DistrT::result_type Impl(std::false_type, URBG* urbg,\n                                           Args&&... args) {\n    DistrT dist(std::forward<Args>(args)...);\n    return dist(*urbg);\n  }\n\n  // Mock implementation of distribution caller.\n  // The underlying KeyT must match the KeyT constructed by MockOverloadSet.\n  template <typename DistrT, typename... Args>\n  static typename DistrT::result_type Impl(std::true_type, URBG* urbg,\n                                           Args&&... args) {\n    using ResultT = typename DistrT::result_type;\n    using ArgTupleT = std::tuple<absl::decay_t<Args>...>;\n    using KeyT = ResultT(DistrT, ArgTupleT);\n\n    ArgTupleT arg_tuple(std::forward<Args>(args)...);\n    ResultT result;\n    if (!urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {\n      auto dist = absl::make_from_tuple<DistrT>(arg_tuple);\n      result = dist(*urbg);\n    }\n    return result;\n  }\n\n  // Default implementation of distribution caller.\n  template <typename DistrT, typename... Args>\n  static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {\n    return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,\n                                 std::forward<Args>(args)...);\n  }\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_\n"
  },
  {
    "path": "absl/random/internal/distribution_test_util.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/distribution_test_util.h\"\n\n#include <cassert>\n#include <cmath>\n#include <string>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\n#if defined(__EMSCRIPTEN__)\n// Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found.\ninline double fma(double x, double y, double z) { return (x * y) + z; }\n#endif\n\n}  // namespace\n\nDistributionMoments ComputeDistributionMoments(\n    absl::Span<const double> data_points) {\n  DistributionMoments result;\n\n  // Compute m1\n  for (double x : data_points) {\n    result.n++;\n    result.mean += x;\n  }\n  result.mean /= static_cast<double>(result.n);\n\n  // Compute m2, m3, m4\n  for (double x : data_points) {\n    double v = x - result.mean;\n    result.variance += v * v;\n    result.skewness += v * v * v;\n    result.kurtosis += v * v * v * v;\n  }\n  result.variance /= static_cast<double>(result.n - 1);\n\n  result.skewness /= static_cast<double>(result.n);\n  result.skewness /= std::pow(result.variance, 1.5);\n\n  result.kurtosis /= static_cast<double>(result.n);\n  result.kurtosis /= std::pow(result.variance, 2.0);\n  return result;\n\n  // When validating the min/max count, the following confidence intervals may\n  // be of use:\n  // 3.291 * stddev = 99.9% CI\n  // 2.576 * stddev = 99% CI\n  // 1.96 * stddev  = 95% CI\n  // 1.65 * stddev  = 90% CI\n}\n\nstd::ostream& operator<<(std::ostream& os, const DistributionMoments& moments) {\n  return os << absl::StrFormat(\"mean=%f, stddev=%f, skewness=%f, kurtosis=%f\",\n                               moments.mean, std::sqrt(moments.variance),\n                               moments.skewness, moments.kurtosis);\n}\n\ndouble InverseNormalSurvival(double x) {\n  // inv_sf(u) = -sqrt(2) * erfinv(2u-1)\n  static constexpr double kSqrt2 = 1.4142135623730950488;\n  return -kSqrt2 * absl::random_internal::erfinv(2 * x - 1.0);\n}\n\nbool Near(absl::string_view msg, double actual, double expected, double bound) {\n  assert(bound > 0.0);\n  double delta = fabs(expected - actual);\n  if (delta < bound) {\n    return true;\n  }\n\n  std::string formatted = absl::StrCat(\n      msg, \" actual=\", actual, \" expected=\", expected, \" err=\", delta / bound);\n  ABSL_RAW_LOG(INFO, \"%s\", formatted.c_str());\n  return false;\n}\n\n// TODO(absl-team): Replace with an \"ABSL_HAVE_SPECIAL_MATH\" and try\n// to use std::beta().  As of this writing P0226R1 is not implemented\n// in libc++: http://libcxx.llvm.org/cxx1z_status.html\ndouble beta(double p, double q) {\n  // Beta(x, y) = Gamma(x) * Gamma(y) / Gamma(x+y)\n  double lbeta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q);\n  return std::exp(lbeta);\n}\n\n// Approximation to inverse of the Error Function in double precision.\n// (http://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf)\ndouble erfinv(double x) {\n#if !defined(__EMSCRIPTEN__)\n  using std::fma;\n#endif\n\n  double w = 0.0;\n  double p = 0.0;\n  w = -std::log((1.0 - x) * (1.0 + x));\n  if (w < 6.250000) {\n    w = w - 3.125000;\n    p = -3.6444120640178196996e-21;\n    p = fma(p, w, -1.685059138182016589e-19);\n    p = fma(p, w, 1.2858480715256400167e-18);\n    p = fma(p, w, 1.115787767802518096e-17);\n    p = fma(p, w, -1.333171662854620906e-16);\n    p = fma(p, w, 2.0972767875968561637e-17);\n    p = fma(p, w, 6.6376381343583238325e-15);\n    p = fma(p, w, -4.0545662729752068639e-14);\n    p = fma(p, w, -8.1519341976054721522e-14);\n    p = fma(p, w, 2.6335093153082322977e-12);\n    p = fma(p, w, -1.2975133253453532498e-11);\n    p = fma(p, w, -5.4154120542946279317e-11);\n    p = fma(p, w, 1.051212273321532285e-09);\n    p = fma(p, w, -4.1126339803469836976e-09);\n    p = fma(p, w, -2.9070369957882005086e-08);\n    p = fma(p, w, 4.2347877827932403518e-07);\n    p = fma(p, w, -1.3654692000834678645e-06);\n    p = fma(p, w, -1.3882523362786468719e-05);\n    p = fma(p, w, 0.0001867342080340571352);\n    p = fma(p, w, -0.00074070253416626697512);\n    p = fma(p, w, -0.0060336708714301490533);\n    p = fma(p, w, 0.24015818242558961693);\n    p = fma(p, w, 1.6536545626831027356);\n  } else if (w < 16.000000) {\n    w = std::sqrt(w) - 3.250000;\n    p = 2.2137376921775787049e-09;\n    p = fma(p, w, 9.0756561938885390979e-08);\n    p = fma(p, w, -2.7517406297064545428e-07);\n    p = fma(p, w, 1.8239629214389227755e-08);\n    p = fma(p, w, 1.5027403968909827627e-06);\n    p = fma(p, w, -4.013867526981545969e-06);\n    p = fma(p, w, 2.9234449089955446044e-06);\n    p = fma(p, w, 1.2475304481671778723e-05);\n    p = fma(p, w, -4.7318229009055733981e-05);\n    p = fma(p, w, 6.8284851459573175448e-05);\n    p = fma(p, w, 2.4031110387097893999e-05);\n    p = fma(p, w, -0.0003550375203628474796);\n    p = fma(p, w, 0.00095328937973738049703);\n    p = fma(p, w, -0.0016882755560235047313);\n    p = fma(p, w, 0.0024914420961078508066);\n    p = fma(p, w, -0.0037512085075692412107);\n    p = fma(p, w, 0.005370914553590063617);\n    p = fma(p, w, 1.0052589676941592334);\n    p = fma(p, w, 3.0838856104922207635);\n  } else {\n    w = std::sqrt(w) - 5.000000;\n    p = -2.7109920616438573243e-11;\n    p = fma(p, w, -2.5556418169965252055e-10);\n    p = fma(p, w, 1.5076572693500548083e-09);\n    p = fma(p, w, -3.7894654401267369937e-09);\n    p = fma(p, w, 7.6157012080783393804e-09);\n    p = fma(p, w, -1.4960026627149240478e-08);\n    p = fma(p, w, 2.9147953450901080826e-08);\n    p = fma(p, w, -6.7711997758452339498e-08);\n    p = fma(p, w, 2.2900482228026654717e-07);\n    p = fma(p, w, -9.9298272942317002539e-07);\n    p = fma(p, w, 4.5260625972231537039e-06);\n    p = fma(p, w, -1.9681778105531670567e-05);\n    p = fma(p, w, 7.5995277030017761139e-05);\n    p = fma(p, w, -0.00021503011930044477347);\n    p = fma(p, w, -0.00013871931833623122026);\n    p = fma(p, w, 1.0103004648645343977);\n    p = fma(p, w, 4.8499064014085844221);\n  }\n  return p * x;\n}\n\nnamespace {\n\n// Direct implementation of AS63, BETAIN()\n// https://www.jstor.org/stable/2346797?seq=3#page_scan_tab_contents.\n//\n// BETAIN(x, p, q, beta)\n//  x:     the value of the upper limit x.\n//  p:     the value of the parameter p.\n//  q:     the value of the parameter q.\n//  beta:  the value of ln B(p, q)\n//\ndouble BetaIncompleteImpl(const double x, const double p, const double q,\n                          const double beta) {\n  if (p < (p + q) * x) {\n    // Incomplete beta function is symmetrical, so return the complement.\n    return 1. - BetaIncompleteImpl(1.0 - x, q, p, beta);\n  }\n\n  double psq = p + q;\n  const double kErr = 1e-14;\n  const double xc = 1. - x;\n  const double pre =\n      std::exp(p * std::log(x) + (q - 1.) * std::log(xc) - beta) / p;\n\n  double term = 1.;\n  double ai = 1.;\n  double result = 1.;\n  int ns = static_cast<int>(q + xc * psq);\n\n  // Use the soper reduction formula.\n  double rx = (ns == 0) ? x : x / xc;\n  double temp = q - ai;\n  for (;;) {\n    term = term * temp * rx / (p + ai);\n    result = result + term;\n    temp = std::fabs(term);\n    if (temp < kErr && temp < kErr * result) {\n      return result * pre;\n    }\n    ai = ai + 1.;\n    --ns;\n    if (ns >= 0) {\n      temp = q - ai;\n      if (ns == 0) {\n        rx = x;\n      }\n    } else {\n      temp = psq;\n      psq = psq + 1.;\n    }\n  }\n\n  // NOTE: See also TOMS Algorithm 708.\n  // http://www.netlib.org/toms/index.html\n  //\n  // NOTE: The NWSC library also includes BRATIO / ISUBX (p87)\n  // https://archive.org/details/DTIC_ADA261511/page/n75\n}\n\n// Direct implementation of AS109, XINBTA(p, q, beta, alpha)\n// https://www.jstor.org/stable/2346798?read-now=1&seq=4#page_scan_tab_contents\n// https://www.jstor.org/stable/2346887?seq=1#page_scan_tab_contents\n//\n// XINBTA(p, q, beta, alpha)\n//  p:     the value of the parameter p.\n//  q:     the value of the parameter q.\n//  beta:  the value of ln B(p, q)\n//  alpha: the value of the lower tail area.\n//\ndouble BetaIncompleteInvImpl(const double p, const double q, const double beta,\n                             const double alpha) {\n  if (alpha < 0.5) {\n    // Inverse Incomplete beta function is symmetrical, return the complement.\n    return 1. - BetaIncompleteInvImpl(q, p, beta, 1. - alpha);\n  }\n  const double kErr = 1e-14;\n  double value = kErr;\n\n  // Compute the initial estimate.\n  {\n    double r = std::sqrt(-std::log(alpha * alpha));\n    double y =\n        r - fma(r, 0.27061, 2.30753) / fma(r, fma(r, 0.04481, 0.99229), 1.0);\n    if (p > 1. && q > 1.) {\n      r = (y * y - 3.) / 6.;\n      double s = 1. / (p + p - 1.);\n      double t = 1. / (q + q - 1.);\n      double h = 2. / s + t;\n      double w =\n          y * std::sqrt(h + r) / h - (t - s) * (r + 5. / 6. - t / (3. * h));\n      value = p / (p + q * std::exp(w + w));\n    } else {\n      r = q + q;\n      double t = 1.0 / (9. * q);\n      double u = 1.0 - t + y * std::sqrt(t);\n      t = r * (u * u * u);\n      if (t <= 0) {\n        value = 1.0 - std::exp((std::log((1.0 - alpha) * q) + beta) / q);\n      } else {\n        t = (4.0 * p + r - 2.0) / t;\n        if (t <= 1) {\n          value = std::exp((std::log(alpha * p) + beta) / p);\n        } else {\n          value = 1.0 - 2.0 / (t + 1.0);\n        }\n      }\n    }\n  }\n\n  // Solve for x using a modified newton-raphson method using the function\n  // BetaIncomplete.\n  {\n    value = std::max(value, kErr);\n    value = std::min(value, 1.0 - kErr);\n\n    const double r = 1.0 - p;\n    const double t = 1.0 - q;\n    double y;\n    double yprev = 0;\n    double sq = 1;\n    double prev = 1;\n    for (;;) {\n      if (value < 0 || value > 1.0) {\n        // Error case; value went infinite.\n        return std::numeric_limits<double>::infinity();\n      } else if (value == 0 || value == 1) {\n        y = value;\n      } else {\n        y = BetaIncompleteImpl(value, p, q, beta);\n        if (!std::isfinite(y)) {\n          return y;\n        }\n      }\n      y = (y - alpha) *\n          std::exp(beta + r * std::log(value) + t * std::log(1.0 - value));\n      if (y * yprev <= 0) {\n        prev = std::max(sq, std::numeric_limits<double>::min());\n      }\n      double g = 1.0;\n      for (;;) {\n        const double adj = g * y;\n        const double adj_sq = adj * adj;\n        if (adj_sq >= prev) {\n          g = g / 3.0;\n          continue;\n        }\n        const double tx = value - adj;\n        if (tx < 0 || tx > 1) {\n          g = g / 3.0;\n          continue;\n        }\n        if (prev < kErr) {\n          return value;\n        }\n        if (y * y < kErr) {\n          return value;\n        }\n        if (tx == value) {\n          return value;\n        }\n        if (tx == 0 || tx == 1) {\n          g = g / 3.0;\n          continue;\n        }\n        value = tx;\n        yprev = y;\n        break;\n      }\n    }\n  }\n\n  // NOTES: See also: Asymptotic inversion of the incomplete beta function.\n  // https://core.ac.uk/download/pdf/82140723.pdf\n  //\n  // NOTE: See the Boost library documentation as well:\n  // https://www.boost.org/doc/libs/1_52_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_beta/ibeta_function.html\n}\n\n}  // namespace\n\ndouble BetaIncomplete(const double x, const double p, const double q) {\n  // Error cases.\n  if (p < 0 || q < 0 || x < 0 || x > 1.0) {\n    return std::numeric_limits<double>::infinity();\n  }\n  if (x == 0 || x == 1) {\n    return x;\n  }\n  // ln(Beta(p, q))\n  double beta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q);\n  return BetaIncompleteImpl(x, p, q, beta);\n}\n\ndouble BetaIncompleteInv(const double p, const double q, const double alpha) {\n  // Error cases.\n  if (p < 0 || q < 0 || alpha < 0 || alpha > 1.0) {\n    return std::numeric_limits<double>::infinity();\n  }\n  if (alpha == 0 || alpha == 1) {\n    return alpha;\n  }\n  // ln(Beta(p, q))\n  double beta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q);\n  return BetaIncompleteInvImpl(p, q, beta, alpha);\n}\n\n// Given `num_trials` trials each with probability `p` of success, the\n// probability of no failures is `p^k`. To ensure the probability of a failure\n// is no more than `p_fail`, it must be that `p^k == 1 - p_fail`. This function\n// computes `p` from that equation.\ndouble RequiredSuccessProbability(const double p_fail, const int num_trials) {\n  double p = std::exp(std::log(1.0 - p_fail) / static_cast<double>(num_trials));\n  ABSL_ASSERT(p > 0);\n  return p;\n}\n\ndouble ZScore(double expected_mean, const DistributionMoments& moments) {\n  return (moments.mean - expected_mean) /\n         (std::sqrt(moments.variance) /\n          std::sqrt(static_cast<double>(moments.n)));\n}\n\ndouble MaxErrorTolerance(double acceptance_probability) {\n  double one_sided_pvalue = 0.5 * (1.0 - acceptance_probability);\n  const double max_err = InverseNormalSurvival(one_sided_pvalue);\n  ABSL_ASSERT(max_err > 0);\n  return max_err;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/distribution_test_util.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_\n#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_\n\n#include <cstddef>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\n// NOTE: The functions in this file are test only, and are should not be used in\n// non-test code.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// http://webspace.ship.edu/pgmarr/Geo441/Lectures/Lec%205%20-%20Normality%20Testing.pdf\n\n// Compute the 1st to 4th standard moments:\n// mean, variance, skewness, and kurtosis.\n// http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm\nstruct DistributionMoments {\n  size_t n = 0;\n  double mean = 0.0;\n  double variance = 0.0;\n  double skewness = 0.0;\n  double kurtosis = 0.0;\n};\nDistributionMoments ComputeDistributionMoments(\n    absl::Span<const double> data_points);\n\nstd::ostream& operator<<(std::ostream& os, const DistributionMoments& moments);\n\n// Computes the Z-score for a set of data with the given distribution moments\n// compared against `expected_mean`.\ndouble ZScore(double expected_mean, const DistributionMoments& moments);\n\n// Returns the probability of success required for a single trial to ensure that\n// after `num_trials` trials, the probability of at least one failure is no more\n// than `p_fail`.\ndouble RequiredSuccessProbability(double p_fail, int num_trials);\n\n// Computes the maximum distance from the mean tolerable, for Z-Tests that are\n// expected to pass with `acceptance_probability`. Will terminate if the\n// resulting tolerance is zero (due to passing in 0.0 for\n// `acceptance_probability` or rounding errors).\n//\n// For example,\n// MaxErrorTolerance(0.001) = 0.0\n// MaxErrorTolerance(0.5) = ~0.47\n// MaxErrorTolerance(1.0) = inf\ndouble MaxErrorTolerance(double acceptance_probability);\n\n// Approximation to inverse of the Error Function in double precision.\n// (http://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf)\ndouble erfinv(double x);\n\n// Beta(p, q) = Gamma(p) * Gamma(q) / Gamma(p+q)\ndouble beta(double p, double q);\n\n// The inverse of the normal survival function.\ndouble InverseNormalSurvival(double x);\n\n// Returns whether actual is \"near\" expected, based on the bound.\nbool Near(absl::string_view msg, double actual, double expected, double bound);\n\n// Implements the incomplete regularized beta function, AS63, BETAIN.\n//    https://www.jstor.org/stable/2346797\n//\n// BetaIncomplete(x, p, q), where\n//   `x` is the value of the upper limit\n//   `p` is beta parameter p, `q` is beta parameter q.\n//\n// NOTE: This is a test-only function which is only accurate to within, at most,\n// 1e-13 of the actual value.\n//\ndouble BetaIncomplete(double x, double p, double q);\n\n// Implements the inverse of the incomplete regularized beta function, AS109,\n// XINBTA.\n//   https://www.jstor.org/stable/2346798\n//   https://www.jstor.org/stable/2346887\n//\n// BetaIncompleteInv(p, q, beta, alpha)\n//   `p` is beta parameter p, `q` is beta parameter q.\n//   `alpha` is the value of the lower tail area.\n//\n// NOTE: This is a test-only function and, when successful, is only accurate to\n// within ~1e-6 of the actual value; there are some cases where it diverges from\n// the actual value by much more than that.  The function uses Newton's method,\n// and thus the runtime is highly variable.\ndouble BetaIncompleteInv(double p, double q, double alpha);\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_\n"
  },
  {
    "path": "absl/random/internal/distribution_test_util_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/distribution_test_util.h\"\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nTEST(TestUtil, InverseErf) {\n  const struct {\n    const double z;\n    const double value;\n  } kErfInvTable[] = {\n      {0.0000001, 8.86227e-8},\n      {0.00001, 8.86227e-6},\n      {0.5, 0.4769362762044},\n      {0.6, 0.5951160814499},\n      {0.99999, 3.1234132743},\n      {0.9999999, 3.7665625816},\n      {0.999999944, 3.8403850690566985},  // = log((1-x) * (1+x)) =~ 16.004\n      {0.999999999, 4.3200053849134452},\n  };\n\n  for (const auto& data : kErfInvTable) {\n    auto value = absl::random_internal::erfinv(data.z);\n\n    // Log using the Wolfram-alpha function name & parameters.\n    EXPECT_NEAR(value, data.value, 1e-8)\n        << \" InverseErf[\" << data.z << \"]  (expected=\" << data.value << \")  -> \"\n        << value;\n  }\n}\n\nconst struct {\n  const double p;\n  const double q;\n  const double x;\n  const double alpha;\n} kBetaTable[] = {\n    {0.5, 0.5, 0.01, 0.06376856085851985},\n    {0.5, 0.5, 0.1, 0.2048327646991335},\n    {0.5, 0.5, 1, 1},\n    {1, 0.5, 0, 0},\n    {1, 0.5, 0.01, 0.005012562893380045},\n    {1, 0.5, 0.1, 0.0513167019494862},\n    {1, 0.5, 0.5, 0.2928932188134525},\n    {1, 1, 0.5, 0.5},\n    {2, 2, 0.1, 0.028},\n    {2, 2, 0.2, 0.104},\n    {2, 2, 0.3, 0.216},\n    {2, 2, 0.4, 0.352},\n    {2, 2, 0.5, 0.5},\n    {2, 2, 0.6, 0.648},\n    {2, 2, 0.7, 0.784},\n    {2, 2, 0.8, 0.896},\n    {2, 2, 0.9, 0.972},\n    {5.5, 5, 0.5, 0.4361908850559777},\n    {10, 0.5, 0.9, 0.1516409096346979},\n    {10, 5, 0.5, 0.08978271484375},\n    {10, 5, 1, 1},\n    {10, 10, 0.5, 0.5},\n    {20, 5, 0.8, 0.4598773297575791},\n    {20, 10, 0.6, 0.2146816102371739},\n    {20, 10, 0.8, 0.9507364826957875},\n    {20, 20, 0.5, 0.5},\n    {20, 20, 0.6, 0.8979413687105918},\n    {30, 10, 0.7, 0.2241297491808366},\n    {30, 10, 0.8, 0.7586405487192086},\n    {40, 20, 0.7, 0.7001783247477069},\n    {1, 0.5, 0.1, 0.0513167019494862},\n    {1, 0.5, 0.2, 0.1055728090000841},\n    {1, 0.5, 0.3, 0.1633399734659245},\n    {1, 0.5, 0.4, 0.2254033307585166},\n    {1, 2, 0.2, 0.36},\n    {1, 3, 0.2, 0.488},\n    {1, 4, 0.2, 0.5904},\n    {1, 5, 0.2, 0.67232},\n    {2, 2, 0.3, 0.216},\n    {3, 2, 0.3, 0.0837},\n    {4, 2, 0.3, 0.03078},\n    {5, 2, 0.3, 0.010935},\n\n    // These values test small & large points along the range of the Beta\n    // function.\n    //\n    // When selecting test points, remember that if BetaIncomplete(x, p, q)\n    // returns the same value to within the limits of precision over a large\n    // domain of the input, x, then BetaIncompleteInv(alpha, p, q) may return an\n    // essentially arbitrary value where BetaIncomplete(x, p, q) =~ alpha.\n\n    // BetaRegularized[x, 0.00001, 0.00001],\n    // For x in {~0.001 ... ~0.999}, => ~0.5\n    {1e-5, 1e-5, 1e-5, 0.4999424388184638311},\n    {1e-5, 1e-5, (1.0 - 1e-8), 0.5000920948389232964},\n\n    // BetaRegularized[x, 0.00001, 10000].\n    // For x in {~epsilon ... 1.0}, => ~1\n    {1e-5, 1e5, 1e-6, 0.9999817708130066936},\n    {1e-5, 1e5, (1.0 - 1e-7), 1.0},\n\n    // BetaRegularized[x, 10000, 0.00001].\n    // For x in {0 .. 1-epsilon}, => ~0\n    {1e5, 1e-5, 1e-6, 0},\n    {1e5, 1e-5, (1.0 - 1e-6), 1.8229186993306369e-5},\n};\n\nTEST(BetaTest, BetaIncomplete) {\n  for (const auto& data : kBetaTable) {\n    auto value = absl::random_internal::BetaIncomplete(data.x, data.p, data.q);\n\n    // Log using the Wolfram-alpha function name & parameters.\n    EXPECT_NEAR(value, data.alpha, 1e-12)\n        << \" BetaRegularized[\" << data.x << \", \" << data.p << \", \" << data.q\n        << \"]  (expected=\" << data.alpha << \")  -> \" << value;\n  }\n}\n\nTEST(BetaTest, BetaIncompleteInv) {\n  for (const auto& data : kBetaTable) {\n    auto value =\n        absl::random_internal::BetaIncompleteInv(data.p, data.q, data.alpha);\n\n    // Log using the Wolfram-alpha function name & parameters.\n    EXPECT_NEAR(value, data.x, 1e-6)\n        << \" InverseBetaRegularized[\" << data.alpha << \", \" << data.p << \", \"\n        << data.q << \"]  (expected=\" << data.x << \")  -> \" << value;\n  }\n}\n\nTEST(MaxErrorTolerance, MaxErrorTolerance) {\n  std::vector<std::pair<double, double>> cases = {\n      {0.0000001, 8.86227e-8 * 1.41421356237},\n      {0.00001, 8.86227e-6 * 1.41421356237},\n      {0.5, 0.4769362762044 * 1.41421356237},\n      {0.6, 0.5951160814499 * 1.41421356237},\n      {0.99999, 3.1234132743 * 1.41421356237},\n      {0.9999999, 3.7665625816 * 1.41421356237},\n      {0.999999944, 3.8403850690566985 * 1.41421356237},\n      {0.999999999, 4.3200053849134452 * 1.41421356237}};\n  for (auto entry : cases) {\n    EXPECT_NEAR(absl::random_internal::MaxErrorTolerance(entry.first),\n                entry.second, 1e-8);\n  }\n}\n\nTEST(ZScore, WithSameMean) {\n  absl::random_internal::DistributionMoments m;\n  m.n = 100;\n  m.mean = 5;\n  m.variance = 1;\n  EXPECT_NEAR(absl::random_internal::ZScore(5, m), 0, 1e-12);\n\n  m.n = 1;\n  m.mean = 0;\n  m.variance = 1;\n  EXPECT_NEAR(absl::random_internal::ZScore(0, m), 0, 1e-12);\n\n  m.n = 10000;\n  m.mean = -5;\n  m.variance = 100;\n  EXPECT_NEAR(absl::random_internal::ZScore(-5, m), 0, 1e-12);\n}\n\nTEST(ZScore, DifferentMean) {\n  absl::random_internal::DistributionMoments m;\n  m.n = 100;\n  m.mean = 5;\n  m.variance = 1;\n  EXPECT_NEAR(absl::random_internal::ZScore(4, m), 10, 1e-12);\n\n  m.n = 1;\n  m.mean = 0;\n  m.variance = 1;\n  EXPECT_NEAR(absl::random_internal::ZScore(-1, m), 1, 1e-12);\n\n  m.n = 10000;\n  m.mean = -5;\n  m.variance = 100;\n  EXPECT_NEAR(absl::random_internal::ZScore(-4, m), -10, 1e-12);\n}\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/entropy_pool.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/entropy_pool.h\"\n\n#include <algorithm>\n#include <atomic>\n#include <cstdint>\n#include <cstring>\n#include <iterator>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/random/internal/randen.h\"\n#include \"absl/random/internal/randen_traits.h\"\n#include \"absl/random/internal/seed_material.h\"\n#include \"absl/random/seed_gen_exception.h\"\n#include \"absl/types/span.h\"\n\nusing absl::base_internal::SpinLock;\nusing absl::base_internal::SpinLockHolder;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\n// RandenPoolEntry is a thread-safe pseudorandom bit generator, implementing a\n// single generator within a RandenPool<T>. It is an internal implementation\n// detail, and does not aim to conform to [rand.req.urng].\n//\n// At least 32-byte alignment is required for the state_ array on some ARM\n// platforms.  We also want this aligned to a cacheline to eliminate false\n// sharing.\nclass alignas(std::max(size_t{ABSL_CACHELINE_SIZE}, size_t{32}))\n    RandenPoolEntry {\n public:\n  static constexpr size_t kState = RandenTraits::kStateBytes / sizeof(uint32_t);\n  static constexpr size_t kCapacity =\n      RandenTraits::kCapacityBytes / sizeof(uint32_t);\n\n  void Init(absl::Span<const uint32_t> data) {\n    SpinLockHolder l(mu_);  // Always uncontested.\n    std::copy(data.begin(), data.end(), std::begin(state_));\n    next_ = kState;\n  }\n\n  // Copy bytes into out.\n  void Fill(uint8_t* out, size_t bytes) ABSL_LOCKS_EXCLUDED(mu_);\n\n  inline void MaybeRefill() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {\n    if (next_ >= kState) {\n      next_ = kCapacity;\n      impl_.Generate(state_);\n    }\n  }\n\n  inline size_t available() const ABSL_SHARED_LOCKS_REQUIRED(mu_) {\n    return kState - next_;\n  }\n\n private:\n  // Randen URBG state.\n  // At least 32-byte alignment is required by ARM platform code.\n  alignas(32) uint32_t state_[kState] ABSL_GUARDED_BY(mu_);\n  SpinLock mu_;\n  const Randen impl_;\n  size_t next_ ABSL_GUARDED_BY(mu_);\n};\n\nvoid RandenPoolEntry::Fill(uint8_t* out, size_t bytes) {\n  SpinLockHolder l(mu_);\n  while (bytes > 0) {\n    MaybeRefill();\n    size_t remaining = available() * sizeof(state_[0]);\n    size_t to_copy = std::min(bytes, remaining);\n    std::memcpy(out, &state_[next_], to_copy);\n    out += to_copy;\n    bytes -= to_copy;\n    next_ += (to_copy + sizeof(state_[0]) - 1) / sizeof(state_[0]);\n  }\n}\n\n// Number of pooled urbg entries.\nstatic constexpr size_t kPoolSize = 8;\n\n// Shared pool entries.\nstatic absl::once_flag pool_once;\nABSL_CACHELINE_ALIGNED static RandenPoolEntry* shared_pools[kPoolSize];\n\n// Returns an id in the range [0 ... kPoolSize), which indexes into the\n// pool of random engines.\n//\n// Each thread to access the pool is assigned a sequential ID (without reuse)\n// from the pool-id space; the id is cached in a thread_local variable.\n// This id is assigned based on the arrival-order of the thread to the\n// GetPoolID call; this has no binary, CL, or runtime stability because\n// on subsequent runs the order within the same program may be significantly\n// different. However, as other thread IDs are not assigned sequentially,\n// this is not expected to matter.\nsize_t GetPoolID() {\n  static_assert(kPoolSize >= 1,\n                \"At least one urbg instance is required for PoolURBG\");\n\n  ABSL_CONST_INIT static std::atomic<uint64_t> sequence{0};\n\n#ifdef ABSL_HAVE_THREAD_LOCAL\n  static thread_local size_t my_pool_id = kPoolSize;\n  if (ABSL_PREDICT_FALSE(my_pool_id == kPoolSize)) {\n    my_pool_id = (sequence++ % kPoolSize);\n  }\n  return my_pool_id;\n#else\n  static pthread_key_t tid_key = [] {\n    pthread_key_t tmp_key;\n    int err = pthread_key_create(&tmp_key, nullptr);\n    if (err) {\n      ABSL_RAW_LOG(FATAL, \"pthread_key_create failed with %d\", err);\n    }\n    return tmp_key;\n  }();\n\n  // Store the value in the pthread_{get/set}specific. However an uninitialized\n  // value is 0, so add +1 to distinguish from the null value.\n  uintptr_t my_pool_id =\n      reinterpret_cast<uintptr_t>(pthread_getspecific(tid_key));\n  if (ABSL_PREDICT_FALSE(my_pool_id == 0)) {\n    // No allocated ID, allocate the next value, cache it, and return.\n    my_pool_id = (sequence++ % kPoolSize) + 1;\n    int err = pthread_setspecific(tid_key, reinterpret_cast<void*>(my_pool_id));\n    if (err) {\n      ABSL_RAW_LOG(FATAL, \"pthread_setspecific failed with %d\", err);\n    }\n  }\n  return my_pool_id - 1;\n#endif\n}\n\n// Allocate and initialize kPoolSize objects of type RandenPoolEntry.\nvoid InitPoolURBG() {\n  static constexpr size_t kSeedSize =\n      RandenTraits::kStateBytes / sizeof(uint32_t);\n  // Read OS entropy once, and use it to initialize each pool entry.\n  uint32_t seed_material[kPoolSize * kSeedSize];\n  if (!ReadSeedMaterialFromOSEntropy(absl::MakeSpan(seed_material))) {\n    ThrowSeedGenException();\n  }\n  for (size_t i = 0; i < kPoolSize; i++) {\n    shared_pools[i] = new RandenPoolEntry();\n    shared_pools[i]->Init(\n        absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize));\n  }\n}\n\n// Returns the pool entry for the current thread.\nRandenPoolEntry* GetPoolForCurrentThread() {\n  absl::call_once(pool_once, InitPoolURBG);\n  return shared_pools[GetPoolID()];\n}\n\n}  // namespace\n\nvoid GetEntropyFromRandenPool(void* dest, size_t bytes) {\n  auto* pool = GetPoolForCurrentThread();\n  pool->Fill(reinterpret_cast<uint8_t*>(dest), bytes);\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/entropy_pool.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_ENTROPY_POOL_H_\n#define ABSL_RANDOM_INTERNAL_ENTROPY_POOL_H_\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// GetEntropyFromRandenPool() is a helper function that fills a memory region\n// with random bytes from the RandenPool.  This is used by the absl::BitGen\n// implementation to fill the internal buffer.\nvoid GetEntropyFromRandenPool(void* dest, size_t bytes);\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_ENTROPY_POOL_H_\n"
  },
  {
    "path": "absl/random/internal/entropy_pool_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/entropy_pool.h\"\n\n#include <bitset>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <thread>  // NOLINT\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace {\n\nusing ::absl::random_internal::GetEntropyFromRandenPool;\n\nTEST(EntropyPoolTest, DistinctSequencesPerThread) {\n  using result_type = uint32_t;\n  constexpr int kNumThreads = 12;\n  constexpr size_t kValuesPerThread = 32;\n\n  // Acquire entropy from multiple threads.\n  std::vector<std::vector<result_type>> data;\n  {\n    absl::Mutex mu;\n    std::vector<std::thread> threads;\n    for (int i = 0; i < kNumThreads; i++) {\n      threads.emplace_back([&]() {\n        std::vector<result_type> v(kValuesPerThread);\n        GetEntropyFromRandenPool(v.data(), sizeof(result_type) * v.size());\n        absl::MutexLock l(mu);\n        data.push_back(std::move(v));\n      });\n    }\n    for (auto& t : threads) t.join();\n  }\n\n  EXPECT_EQ(data.size(), kNumThreads);\n\n  // There should be essentially no duplicates in the sequences.\n  size_t expected_size = 0;\n  absl::flat_hash_set<result_type> seen;\n  for (const auto& v : data) {\n    expected_size += v.size();\n    for (result_type x : v) seen.insert(x);\n  }\n  EXPECT_GE(seen.size(), expected_size - 1);\n}\n\n// This validates that sequences are independent.\nTEST(EntropyPoolTest, ValidateDistribution) {\n  using result_type = uint32_t;\n  constexpr int kNumOutputs = 16;\n  std::vector<result_type> a(kNumOutputs);\n  std::vector<result_type> b(kNumOutputs);\n\n  GetEntropyFromRandenPool(a.data(), sizeof(a[0]) * a.size());\n  GetEntropyFromRandenPool(b.data(), sizeof(b[0]) * b.size());\n\n  // Compare the two sequences, counting the number of bits that are different,\n  // then verify using a normal-approximation of the binomial distribution.\n  size_t changed_bits = 0;\n  size_t total_set = 0;\n  size_t equal_count = 0;\n  size_t zero_count = 0;\n  for (size_t i = 0; i < a.size(); ++i) {\n    std::bitset<sizeof(result_type) * 8> changed_set(a[i] ^ b[i]);\n    changed_bits += changed_set.count();\n\n    std::bitset<sizeof(result_type) * 8> a_set(a[i]);\n    std::bitset<sizeof(result_type) * 8> b_set(b[i]);\n    total_set += a_set.count() + b_set.count();\n\n    equal_count += (a[i] == b[i]) ? 1 : 0;\n\n    zero_count += (a[i] == 0) ? 1 : 0;\n    zero_count += (b[i] == 0) ? 1 : 0;\n  }\n\n  constexpr size_t kNBits = kNumOutputs * sizeof(result_type) * 8;\n\n  // This should be a binomial distribution with:\n  //    p = 0.5\n  //    n = kNBits\n  //    sigma =~ 11.3 (sqrt(n * 0.5 * 0.5))\n  // So we expect the number of changed bits to be within 5 standard deviations\n  // of the mean; this should fail less than one in 3 million times.\n  EXPECT_NEAR(changed_bits, kNBits * 0.5, 5 * std::sqrt(kNBits))\n      << \"@\" << changed_bits / static_cast<double>(kNBits);\n\n  // Verify that the number of set bits is also within the expected range;\n  // Note that this is summed over the two sequences, so the number of trials\n  // is twice the number of bits.\n  EXPECT_NEAR(total_set, kNBits, 5 * std::sqrt(2 * kNBits))\n      << \"@\" << total_set / static_cast<double>(2 * kNBits);\n\n  // A[i] == B[i] with probability ~= 16 * 1/2^32; certainly less than 1.\n  EXPECT_LE(equal_count, 1);\n\n  // Zeros values must be rare; 32 / 2^32 is certainly less than 1.\n  EXPECT_LE(zero_count, 1);\n}\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/explicit_seed_seq.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_\n#define ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <initializer_list>\n#include <iterator>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// This class conforms to the C++ Standard \"Seed Sequence\" concept\n// [rand.req.seedseq].\n//\n// An \"ExplicitSeedSeq\" is meant to provide a conformant interface for\n// forwarding pre-computed seed material to the constructor of a class\n// conforming to the \"Uniform Random Bit Generator\" concept. This class makes no\n// attempt to mutate the state provided by its constructor, and returns it\n// directly via ExplicitSeedSeq::generate().\n//\n// If this class is asked to generate more seed material than was provided to\n// the constructor, then the remaining bytes will be filled with deterministic,\n// nonrandom data.\nclass ExplicitSeedSeq {\n public:\n  using result_type = uint32_t;\n\n  ExplicitSeedSeq() : state_() {}\n\n  // Copy and move both allowed.\n  ExplicitSeedSeq(const ExplicitSeedSeq& other) = default;\n  ExplicitSeedSeq& operator=(const ExplicitSeedSeq& other) = default;\n  ExplicitSeedSeq(ExplicitSeedSeq&& other) = default;\n  ExplicitSeedSeq& operator=(ExplicitSeedSeq&& other) = default;\n\n  template <typename Iterator>\n  ExplicitSeedSeq(Iterator begin, Iterator end) {\n    for (auto it = begin; it != end; it++) {\n      state_.push_back(*it & 0xffffffff);\n    }\n  }\n\n  template <typename T>\n  ExplicitSeedSeq(std::initializer_list<T> il)\n      : ExplicitSeedSeq(il.begin(), il.end()) {}\n\n  size_t size() const { return state_.size(); }\n\n  template <typename OutIterator>\n  void param(OutIterator out) const {\n    std::copy(std::begin(state_), std::end(state_), out);\n  }\n\n  template <typename OutIterator>\n  void generate(OutIterator begin, OutIterator end) {\n    for (size_t index = 0; begin != end; begin++) {\n      *begin = state_.empty() ? 0 : state_[index++];\n      if (index >= state_.size()) {\n        index = 0;\n      }\n    }\n  }\n\n protected:\n  std::vector<uint32_t> state_;\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_\n"
  },
  {
    "path": "absl/random/internal/explicit_seed_seq_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/explicit_seed_seq.h\"\n\n#include <iterator>\n#include <random>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/seed_sequences.h\"\n\nnamespace {\n\nusing ::absl::random_internal::ExplicitSeedSeq;\n\ntemplate <typename Sseq>\nbool ConformsToInterface() {\n  // Check that the SeedSequence can be default-constructed.\n  {\n    Sseq default_constructed_seq;\n  }\n  // Check that the SeedSequence can be constructed with two iterators.\n  {\n    uint32_t init_array[] = {1, 3, 5, 7, 9};\n    Sseq iterator_constructed_seq(init_array, &init_array[5]);\n  }\n  // Check that the SeedSequence can be std::initializer_list-constructed.\n  {\n    Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13};\n  }\n  // Check that param() and size() return state provided to constructor.\n  {\n    uint32_t init_array[] = {1, 2, 3, 4, 5};\n    Sseq seq(init_array, &init_array[ABSL_ARRAYSIZE(init_array)]);\n    EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array));\n\n    uint32_t state_array[ABSL_ARRAYSIZE(init_array)];\n    seq.param(state_array);\n\n    for (int i = 0; i < ABSL_ARRAYSIZE(state_array); i++) {\n      EXPECT_EQ(state_array[i], i + 1);\n    }\n  }\n  // Check for presence of generate() method.\n  {\n    Sseq seq;\n    uint32_t seeds[5];\n\n    seq.generate(seeds, &seeds[ABSL_ARRAYSIZE(seeds)]);\n  }\n  return true;\n}\n}  // namespace\n\nTEST(SeedSequences, CheckInterfaces) {\n  // Control case\n  EXPECT_TRUE(ConformsToInterface<std::seed_seq>());\n\n  // Abseil classes\n  EXPECT_TRUE(ConformsToInterface<ExplicitSeedSeq>());\n}\n\nTEST(ExplicitSeedSeq, DefaultConstructorGeneratesZeros) {\n  const size_t kNumBlocks = 128;\n\n  uint32_t outputs[kNumBlocks];\n  ExplicitSeedSeq seq;\n  seq.generate(outputs, &outputs[kNumBlocks]);\n\n  for (uint32_t& seed : outputs) {\n    EXPECT_EQ(seed, 0);\n  }\n}\n\nTEST(ExplicitSeeqSeq, SeedMaterialIsForwardedIdentically) {\n  const size_t kNumBlocks = 128;\n\n  uint32_t seed_material[kNumBlocks];\n  std::random_device urandom{\"/dev/urandom\"};\n  for (uint32_t& seed : seed_material) {\n    seed = urandom();\n  }\n  ExplicitSeedSeq seq(seed_material, &seed_material[kNumBlocks]);\n\n  // Check that output is same as seed-material provided to constructor.\n  {\n    const size_t kNumGenerated = kNumBlocks / 2;\n    uint32_t outputs[kNumGenerated];\n    seq.generate(outputs, &outputs[kNumGenerated]);\n    for (size_t i = 0; i < kNumGenerated; i++) {\n      EXPECT_EQ(outputs[i], seed_material[i]);\n    }\n  }\n  // Check that SeedSequence is stateless between invocations: Despite the last\n  // invocation of generate() only consuming half of the input-entropy, the same\n  // entropy will be recycled for the next invocation.\n  {\n    const size_t kNumGenerated = kNumBlocks;\n    uint32_t outputs[kNumGenerated];\n    seq.generate(outputs, &outputs[kNumGenerated]);\n    for (size_t i = 0; i < kNumGenerated; i++) {\n      EXPECT_EQ(outputs[i], seed_material[i]);\n    }\n  }\n  // Check that when more seed-material is asked for than is provided, nonzero\n  // values are still written.\n  {\n    const size_t kNumGenerated = kNumBlocks * 2;\n    uint32_t outputs[kNumGenerated];\n    seq.generate(outputs, &outputs[kNumGenerated]);\n    for (size_t i = 0; i < kNumGenerated; i++) {\n      EXPECT_EQ(outputs[i], seed_material[i % kNumBlocks]);\n    }\n  }\n}\n\nTEST(ExplicitSeedSeq, CopyAndMoveConstructors) {\n  using testing::Each;\n  using testing::Eq;\n  using testing::Not;\n  using testing::Pointwise;\n\n  uint32_t entropy[4];\n  std::random_device urandom(\"/dev/urandom\");\n  for (uint32_t& entry : entropy) {\n    entry = urandom();\n  }\n  ExplicitSeedSeq seq_from_entropy(std::begin(entropy), std::end(entropy));\n  // Copy constructor.\n  {\n    ExplicitSeedSeq seq_copy(seq_from_entropy);\n    EXPECT_EQ(seq_copy.size(), seq_from_entropy.size());\n\n    std::vector<uint32_t> seeds_1(1000, 0);\n    std::vector<uint32_t> seeds_2(1000, 1);\n\n    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());\n    seq_copy.generate(seeds_2.begin(), seeds_2.end());\n\n    EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));\n  }\n  // Assignment operator.\n  {\n    for (uint32_t& entry : entropy) {\n      entry = urandom();\n    }\n    ExplicitSeedSeq another_seq(std::begin(entropy), std::end(entropy));\n\n    std::vector<uint32_t> seeds_1(1000, 0);\n    std::vector<uint32_t> seeds_2(1000, 0);\n\n    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());\n    another_seq.generate(seeds_2.begin(), seeds_2.end());\n\n    // Assert precondition: Sequences generated by seed-sequences are not equal.\n    EXPECT_THAT(seeds_1, Not(Pointwise(Eq(), seeds_2)));\n\n    // Apply the assignment-operator.\n    // GCC 12 has a false-positive -Wstringop-overflow warning here.\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n#endif\n    another_seq = seq_from_entropy;\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic pop\n#endif\n\n    // Re-generate seeds.\n    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());\n    another_seq.generate(seeds_2.begin(), seeds_2.end());\n\n    // Seeds generated by seed-sequences should now be equal.\n    EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));\n  }\n  // Move constructor.\n  {\n    // Get seeds from seed-sequence constructed from entropy.\n    std::vector<uint32_t> seeds_1(1000, 0);\n    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());\n\n    // Apply move-constructor move the sequence to another instance.\n    absl::random_internal::ExplicitSeedSeq moved_seq(\n        std::move(seq_from_entropy));\n    std::vector<uint32_t> seeds_2(1000, 1);\n    moved_seq.generate(seeds_2.begin(), seeds_2.end());\n    // Verify that seeds produced by moved-instance are the same as original.\n    EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));\n\n    // Verify that the moved-from instance now behaves like a\n    // default-constructed instance.\n    EXPECT_EQ(seq_from_entropy.size(), 0);\n    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());\n    EXPECT_THAT(seeds_1, Each(Eq(0)));\n  }\n}\n\nTEST(ExplicitSeedSeq, StdURBGGoldenTests) {\n  // Verify that for std::- URBG instances the results are stable across\n  // platforms (these should have deterministic output).\n  {\n    ExplicitSeedSeq seed_sequence{12, 34, 56};\n    std::minstd_rand rng(seed_sequence);\n\n    std::minstd_rand::result_type values[4] = {rng(), rng(), rng(), rng()};\n    EXPECT_THAT(values,\n                testing::ElementsAre(579252, 43785881, 464353103, 1501811174));\n  }\n\n  {\n    ExplicitSeedSeq seed_sequence{12, 34, 56};\n    std::mt19937 rng(seed_sequence);\n\n    std::mt19937::result_type values[4] = {rng(), rng(), rng(), rng()};\n    EXPECT_THAT(values, testing::ElementsAre(138416803, 151130212, 33817739,\n                                             138416803));\n  }\n\n  {\n    ExplicitSeedSeq seed_sequence{12, 34, 56};\n    std::mt19937_64 rng(seed_sequence);\n\n    std::mt19937_64::result_type values[4] = {rng(), rng(), rng(), rng()};\n    EXPECT_THAT(values,\n                testing::ElementsAre(19738651785169348, 1464811352364190456,\n                                     18054685302720800, 19738651785169348));\n  }\n}\n"
  },
  {
    "path": "absl/random/internal/fast_uniform_bits.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_\n#define ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n// Returns true if the input value is zero or a power of two. Useful for\n// determining if the range of output values in a URBG\ntemplate <typename UIntType>\nconstexpr bool IsPowerOfTwoOrZero(UIntType n) {\n  return (n == 0) || ((n & (n - 1)) == 0);\n}\n\n// Computes the length of the range of values producible by the URBG, or returns\n// zero if that would encompass the entire range of representable values in\n// URBG::result_type.\ntemplate <typename URBG>\nconstexpr typename URBG::result_type RangeSize() {\n  using result_type = typename URBG::result_type;\n  static_assert((URBG::max)() != (URBG::min)(), \"URBG range cannot be 0.\");\n  return ((URBG::max)() == (std::numeric_limits<result_type>::max)() &&\n          (URBG::min)() == std::numeric_limits<result_type>::lowest())\n             ? result_type{0}\n             : ((URBG::max)() - (URBG::min)() + result_type{1});\n}\n\n// Computes the floor of the log. (i.e., std::floor(std::log2(N));\ntemplate <typename UIntType>\nconstexpr UIntType IntegerLog2(UIntType n) {\n  return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1);\n}\n\n// Returns the number of bits of randomness returned through\n// `PowerOfTwoVariate(urbg)`.\ntemplate <typename URBG>\nconstexpr size_t NumBits() {\n  return static_cast<size_t>(\n      RangeSize<URBG>() == 0\n          ? std::numeric_limits<typename URBG::result_type>::digits\n          : IntegerLog2(RangeSize<URBG>()));\n}\n\n// Given a shift value `n`, constructs a mask with exactly the low `n` bits set.\n// If `n == 0`, all bits are set.\ntemplate <typename UIntType>\nconstexpr UIntType MaskFromShift(size_t n) {\n  return ((n % std::numeric_limits<UIntType>::digits) == 0)\n             ? ~UIntType{0}\n             : (UIntType{1} << n) - UIntType{1};\n}\n\n// Tags used to dispatch FastUniformBits::generate to the simple or more complex\n// entropy extraction algorithm.\nstruct SimplifiedLoopTag {};\nstruct RejectionLoopTag {};\n\n// FastUniformBits implements a fast path to acquire uniform independent bits\n// from a type which conforms to the [rand.req.urbg] concept.\n// Parameterized by:\n//  `UIntType`: the result (output) type\n//\n// The std::independent_bits_engine [rand.adapt.ibits] adaptor can be\n// instantiated from an existing generator through a copy or a move. It does\n// not, however, facilitate the production of pseudorandom bits from an un-owned\n// generator that will outlive the std::independent_bits_engine instance.\ntemplate <typename UIntType = uint64_t>\nclass FastUniformBits {\n public:\n  using result_type = UIntType;\n\n  static constexpr result_type(min)() { return 0; }\n  static constexpr result_type(max)() {\n    return (std::numeric_limits<result_type>::max)();\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g);  // NOLINT(runtime/references)\n\n private:\n  static_assert(IsUnsigned<UIntType>::value,\n                \"Class-template FastUniformBits<> must be parameterized using \"\n                \"an unsigned type.\");\n\n  // Generate() generates a random value, dispatched on whether\n  // the underlying URBG must use rejection sampling to generate a value,\n  // or whether a simplified loop will suffice.\n  template <typename URBG>\n  result_type Generate(URBG& g,  // NOLINT(runtime/references)\n                       SimplifiedLoopTag);\n\n  template <typename URBG>\n  result_type Generate(URBG& g,  // NOLINT(runtime/references)\n                       RejectionLoopTag);\n};\n\ntemplate <typename UIntType>\ntemplate <typename URBG>\ntypename FastUniformBits<UIntType>::result_type\nFastUniformBits<UIntType>::operator()(URBG& g) {  // NOLINT(runtime/references)\n  // kRangeMask is the mask used when sampling variates from the URBG when the\n  // width of the URBG range is not a power of 2.\n  // Y = (2 ^ kRange) - 1\n  static_assert((URBG::max)() > (URBG::min)(),\n                \"URBG::max and URBG::min may not be equal.\");\n\n  using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),\n                                  SimplifiedLoopTag, RejectionLoopTag>;\n  return Generate(g, tag{});\n}\n\ntemplate <typename UIntType>\ntemplate <typename URBG>\ntypename FastUniformBits<UIntType>::result_type\nFastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)\n                                    SimplifiedLoopTag) {\n  // The simplified version of FastUniformBits works only on URBGs that have\n  // a range that is a power of 2. In this case we simply loop and shift without\n  // attempting to balance the bits across calls.\n  static_assert(IsPowerOfTwoOrZero(RangeSize<URBG>()),\n                \"incorrect Generate tag for URBG instance\");\n\n  static constexpr size_t kResultBits =\n      std::numeric_limits<result_type>::digits;\n  static constexpr size_t kUrbgBits = NumBits<URBG>();\n  static constexpr size_t kIters =\n      (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0);\n  static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits;\n  static constexpr auto kMin = (URBG::min)();\n\n  result_type r = static_cast<result_type>(g() - kMin);\n  for (size_t n = 1; n < kIters; ++n) {\n    r = static_cast<result_type>(r << kShift) +\n        static_cast<result_type>(g() - kMin);\n  }\n  return r;\n}\n\ntemplate <typename UIntType>\ntemplate <typename URBG>\ntypename FastUniformBits<UIntType>::result_type\nFastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)\n                                    RejectionLoopTag) {\n  static_assert(!IsPowerOfTwoOrZero(RangeSize<URBG>()),\n                \"incorrect Generate tag for URBG instance\");\n  using urbg_result_type = typename URBG::result_type;\n\n  // See [rand.adapt.ibits] for more details on the constants calculated below.\n  //\n  // It is preferable to use roughly the same number of bits from each generator\n  // call, however this is only possible when the number of bits provided by the\n  // URBG is a divisor of the number of bits in `result_type`. In all other\n  // cases, the number of bits used cannot always be the same, but it can be\n  // guaranteed to be off by at most 1. Thus we run two loops, one with a\n  // smaller bit-width size (`kSmallWidth`) and one with a larger width size\n  // (satisfying `kLargeWidth == kSmallWidth + 1`). The loops are run\n  // `kSmallIters` and `kLargeIters` times respectively such\n  // that\n  //\n  //    `kResultBits == kSmallIters * kSmallBits\n  //                    + kLargeIters * kLargeBits`\n  //\n  // where `kResultBits` is the total number of bits in `result_type`.\n  //\n  static constexpr size_t kResultBits =\n      std::numeric_limits<result_type>::digits;                      // w\n  static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>();  // R\n  static constexpr size_t kUrbgBits = NumBits<URBG>();               // m\n\n  // compute the initial estimate of the bits used.\n  // [rand.adapt.ibits] 2 (c)\n  static constexpr size_t kA =  // ceil(w/m)\n      (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0);  // n'\n\n  static constexpr size_t kABits = kResultBits / kA;  // w0'\n  static constexpr urbg_result_type kARejection =\n      ((kUrbgRange >> kABits) << kABits);  // y0'\n\n  // refine the selection to reduce the rejection frequency.\n  static constexpr size_t kTotalIters =\n      ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1);  // n\n\n  // [rand.adapt.ibits] 2 (b)\n  static constexpr size_t kSmallIters =\n      kTotalIters - (kResultBits % kTotalIters);                   // n0\n  static constexpr size_t kSmallBits = kResultBits / kTotalIters;  // w0\n  static constexpr urbg_result_type kSmallRejection =\n      ((kUrbgRange >> kSmallBits) << kSmallBits);  // y0\n\n  static constexpr size_t kLargeBits = kSmallBits + 1;  // w0+1\n  static constexpr urbg_result_type kLargeRejection =\n      ((kUrbgRange >> kLargeBits) << kLargeBits);  // y1\n\n  //\n  // Because `kLargeBits == kSmallBits + 1`, it follows that\n  //\n  //     `kResultBits == kSmallIters * kSmallBits + kLargeIters`\n  //\n  // and therefore\n  //\n  //     `kLargeIters == kTotalWidth % kSmallWidth`\n  //\n  // Intuitively, each iteration with the large width accounts for one unit\n  // of the remainder when `kTotalWidth` is divided by `kSmallWidth`. As\n  // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then\n  // there would be no need for any large iterations (i.e., one loop would\n  // suffice), and indeed, in this case, `kLargeIters` would be zero.\n  static_assert(kResultBits == kSmallIters * kSmallBits +\n                                   (kTotalIters - kSmallIters) * kLargeBits,\n                \"Error in looping constant calculations.\");\n\n  // The small shift is essentially small bits, but due to the potential\n  // of generating a smaller result_type from a larger urbg type, the actual\n  // shift might be 0.\n  static constexpr size_t kSmallShift = kSmallBits % kResultBits;\n  static constexpr auto kSmallMask =\n      MaskFromShift<urbg_result_type>(kSmallShift);\n  static constexpr size_t kLargeShift = kLargeBits % kResultBits;\n  static constexpr auto kLargeMask =\n      MaskFromShift<urbg_result_type>(kLargeShift);\n\n  static constexpr auto kMin = (URBG::min)();\n\n  result_type s = 0;\n  for (size_t n = 0; n < kSmallIters; ++n) {\n    urbg_result_type v;\n    do {\n      v = g() - kMin;\n    } while (v >= kSmallRejection);\n\n    s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask);\n  }\n\n  for (size_t n = kSmallIters; n < kTotalIters; ++n) {\n    urbg_result_type v;\n    do {\n      v = g() - kMin;\n    } while (v >= kLargeRejection);\n\n    s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask);\n  }\n  return s;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_\n"
  },
  {
    "path": "absl/random/internal/fast_uniform_bits_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/fast_uniform_bits.h\"\n\n#include <random>\n\n#include \"gtest/gtest.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\ntemplate <typename IntType>\nclass FastUniformBitsTypedTest : public ::testing::Test {};\n\nusing IntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>;\n\nTYPED_TEST_SUITE(FastUniformBitsTypedTest, IntTypes);\n\nTYPED_TEST(FastUniformBitsTypedTest, BasicTest) {\n  using Limits = std::numeric_limits<TypeParam>;\n  using FastBits = FastUniformBits<TypeParam>;\n\n  EXPECT_EQ(0, (FastBits::min)());\n  EXPECT_EQ((Limits::max)(), (FastBits::max)());\n\n  constexpr int kIters = 10000;\n  std::random_device rd;\n  std::mt19937 gen(rd());\n  FastBits fast;\n  for (int i = 0; i < kIters; i++) {\n    const auto v = fast(gen);\n    EXPECT_LE(v, (FastBits::max)());\n    EXPECT_GE(v, (FastBits::min)());\n  }\n}\n\ntemplate <typename UIntType, UIntType Lo, UIntType Hi, UIntType Val = Lo>\nstruct FakeUrbg {\n  using result_type = UIntType;\n\n  FakeUrbg() = default;\n  explicit FakeUrbg(bool r) : reject(r) {}\n\n  static constexpr result_type(max)() { return Hi; }\n  static constexpr result_type(min)() { return Lo; }\n  result_type operator()() {\n    // when reject is set, return Hi half the time.\n    return ((++calls % 2) == 1 && reject) ? Hi : Val;\n  }\n\n  bool reject = false;\n  size_t calls = 0;\n};\n\nTEST(FastUniformBitsTest, IsPowerOfTwoOrZero) {\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{0}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{1}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{2}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{3}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{4}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{16}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{17}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint8_t>::max)()));\n\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{0}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{1}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{2}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{3}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{4}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{16}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{17}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint16_t>::max)()));\n\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{0}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{1}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{2}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint32_t{3}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{32}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint32_t{17}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint32_t>::max)()));\n\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{0}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{1}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{2}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{3}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{4}));\n  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{64}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{17}));\n  EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint64_t>::max)()));\n}\n\nTEST(FastUniformBitsTest, IntegerLog2) {\n  EXPECT_EQ(0, IntegerLog2(uint16_t{0}));\n  EXPECT_EQ(0, IntegerLog2(uint16_t{1}));\n  EXPECT_EQ(1, IntegerLog2(uint16_t{2}));\n  EXPECT_EQ(1, IntegerLog2(uint16_t{3}));\n  EXPECT_EQ(2, IntegerLog2(uint16_t{4}));\n  EXPECT_EQ(2, IntegerLog2(uint16_t{5}));\n  EXPECT_EQ(2, IntegerLog2(uint16_t{7}));\n  EXPECT_EQ(3, IntegerLog2(uint16_t{8}));\n  EXPECT_EQ(63, IntegerLog2((std::numeric_limits<uint64_t>::max)()));\n}\n\nTEST(FastUniformBitsTest, RangeSize) {\n  EXPECT_EQ(2, (RangeSize<FakeUrbg<uint8_t, 0, 1>>()));\n  EXPECT_EQ(3, (RangeSize<FakeUrbg<uint8_t, 0, 2>>()));\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 0, 3>>()));\n  //  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint8_t, 2, 2>>()));\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 2, 5>>()));\n  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint8_t, 2, 6>>()));\n  EXPECT_EQ(9, (RangeSize<FakeUrbg<uint8_t, 2, 10>>()));\n  EXPECT_EQ(\n      0, (RangeSize<\n             FakeUrbg<uint8_t, 0, (std::numeric_limits<uint8_t>::max)()>>()));\n\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 0, 3>>()));\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 2, 5>>()));\n  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint16_t, 2, 6>>()));\n  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()));\n  EXPECT_EQ(\n      0, (RangeSize<\n             FakeUrbg<uint16_t, 0, (std::numeric_limits<uint16_t>::max)()>>()));\n\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 0, 3>>()));\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 2, 5>>()));\n  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint32_t, 2, 6>>()));\n  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()));\n  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()));\n  EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()));\n  EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()));\n  EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()));\n  EXPECT_EQ(\n      0, (RangeSize<\n             FakeUrbg<uint32_t, 0, (std::numeric_limits<uint32_t>::max)()>>()));\n\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 0, 3>>()));\n  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 2, 5>>()));\n  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint64_t, 2, 6>>()));\n  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()));\n  EXPECT_EQ(0x100000000, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()));\n  EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()));\n  EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()));\n  EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()));\n  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffff>>()));\n  EXPECT_EQ(0xffffffffffffffff,\n            (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffff>>()));\n  EXPECT_EQ(0xfffffffffffffffe,\n            (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffe>>()));\n  EXPECT_EQ(0xfffffffffffffffd,\n            (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffe>>()));\n  EXPECT_EQ(\n      0, (RangeSize<\n             FakeUrbg<uint64_t, 0, (std::numeric_limits<uint64_t>::max)()>>()));\n}\n\n// The constants need to be chosen so that an infinite rejection loop doesn't\n// happen...\nusing Urng1_5bit = FakeUrbg<uint8_t, 0, 2, 0>;  // ~1.5 bits (range 3)\nusing Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;\nusing Urng22bits = FakeUrbg<uint32_t, 0, 0x3fffff, 0x301020>;\nusing Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>;  // ~31.9 bits\nusing Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;\nusing Urng33bits =\n    FakeUrbg<uint64_t, 1, 0x1ffffffff, 0x013301033>;  // ~32.9 bits\nusing Urng63bits = FakeUrbg<uint64_t, 1, 0xfffffffffffffffe,\n                            0xfedcba9012345678>;  // ~63.9 bits\nusing Urng64bits =\n    FakeUrbg<uint64_t, 0, 0xffffffffffffffff, 0x123456780fedcba9>;\n\nTEST(FastUniformBitsTest, OutputsUpTo32Bits) {\n  // Tests that how values are composed; the single-bit deltas should be spread\n  // across each invocation.\n  Urng1_5bit urng1_5;\n  Urng4bits urng4;\n  Urng22bits urng22;\n  Urng31bits urng31;\n  Urng32bits urng32;\n  Urng33bits urng33;\n  Urng63bits urng63;\n  Urng64bits urng64;\n\n  // 8-bit types\n  {\n    FastUniformBits<uint8_t> fast8;\n    EXPECT_EQ(0x0, fast8(urng1_5));\n    EXPECT_EQ(0x11, fast8(urng4));\n    EXPECT_EQ(0x20, fast8(urng22));\n    EXPECT_EQ(0x2, fast8(urng31));\n    EXPECT_EQ(0x1, fast8(urng32));\n    EXPECT_EQ(0x32, fast8(urng33));\n    EXPECT_EQ(0x77, fast8(urng63));\n    EXPECT_EQ(0xa9, fast8(urng64));\n  }\n\n  // 16-bit types\n  {\n    FastUniformBits<uint16_t> fast16;\n    EXPECT_EQ(0x0, fast16(urng1_5));\n    EXPECT_EQ(0x1111, fast16(urng4));\n    EXPECT_EQ(0x1020, fast16(urng22));\n    EXPECT_EQ(0x0f02, fast16(urng31));\n    EXPECT_EQ(0x0f01, fast16(urng32));\n    EXPECT_EQ(0x1032, fast16(urng33));\n    EXPECT_EQ(0x5677, fast16(urng63));\n    EXPECT_EQ(0xcba9, fast16(urng64));\n  }\n\n  // 32-bit types\n  {\n    FastUniformBits<uint32_t> fast32;\n    EXPECT_EQ(0x0, fast32(urng1_5));\n    EXPECT_EQ(0x11111111, fast32(urng4));\n    EXPECT_EQ(0x08301020, fast32(urng22));\n    EXPECT_EQ(0x0f020f02, fast32(urng31));\n    EXPECT_EQ(0x74010f01, fast32(urng32));\n    EXPECT_EQ(0x13301032, fast32(urng33));\n    EXPECT_EQ(0x12345677, fast32(urng63));\n    EXPECT_EQ(0x0fedcba9, fast32(urng64));\n  }\n}\n\nTEST(FastUniformBitsTest, Outputs64Bits) {\n  // Tests that how values are composed; the single-bit deltas should be spread\n  // across each invocation.\n  FastUniformBits<uint64_t> fast64;\n\n  {\n    FakeUrbg<uint8_t, 0, 1, 0> urng0;\n    FakeUrbg<uint8_t, 0, 1, 1> urng1;\n    Urng4bits urng4;\n    Urng22bits urng22;\n    Urng31bits urng31;\n    Urng32bits urng32;\n    Urng33bits urng33;\n    Urng63bits urng63;\n    Urng64bits urng64;\n\n    // somewhat degenerate cases only create a single bit.\n    EXPECT_EQ(0x0, fast64(urng0));\n    EXPECT_EQ(64, urng0.calls);\n    EXPECT_EQ(0xffffffffffffffff, fast64(urng1));\n    EXPECT_EQ(64, urng1.calls);\n\n    // less degenerate cases.\n    EXPECT_EQ(0x1111111111111111, fast64(urng4));\n    EXPECT_EQ(16, urng4.calls);\n    EXPECT_EQ(0x01020c0408301020, fast64(urng22));\n    EXPECT_EQ(3, urng22.calls);\n    EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));\n    EXPECT_EQ(3, urng31.calls);\n    EXPECT_EQ(0x74010f0174010f01, fast64(urng32));\n    EXPECT_EQ(2, urng32.calls);\n    EXPECT_EQ(0x808194040cb01032, fast64(urng33));\n    EXPECT_EQ(3, urng33.calls);\n    EXPECT_EQ(0x1234567712345677, fast64(urng63));\n    EXPECT_EQ(2, urng63.calls);\n    EXPECT_EQ(0x123456780fedcba9, fast64(urng64));\n    EXPECT_EQ(1, urng64.calls);\n  }\n\n  // The 1.5 bit case is somewhat interesting in that the algorithm refinement\n  // causes one extra small sample. Comments here reference the names used in\n  // [rand.adapt.ibits] that correspond to this case.\n  {\n    Urng1_5bit urng1_5;\n\n    // w = 64\n    // R = 3\n    // m = 1\n    // n' = 64\n    // w0' = 1\n    // y0' = 2\n    // n = (1 <= 0) > 64 : 65 = 65\n    // n0 = 65 - (64%65) = 1\n    // n1 = 64\n    // w0 = 0\n    // y0 = 3\n    // w1 = 1\n    // y1 = 2\n    EXPECT_EQ(0x0, fast64(urng1_5));\n    EXPECT_EQ(65, urng1_5.calls);\n  }\n\n  // Validate rejections for non-power-of-2 cases.\n  {\n    Urng1_5bit urng1_5(true);\n    Urng31bits urng31(true);\n    Urng33bits urng33(true);\n    Urng63bits urng63(true);\n\n    // For 1.5 bits, there would be 1+2*64, except the first\n    // value was accepted and shifted off the end.\n    EXPECT_EQ(0, fast64(urng1_5));\n    EXPECT_EQ(128, urng1_5.calls);\n    EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));\n    EXPECT_EQ(6, urng31.calls);\n    EXPECT_EQ(0x808194040cb01032, fast64(urng33));\n    EXPECT_EQ(6, urng33.calls);\n    EXPECT_EQ(0x1234567712345677, fast64(urng63));\n    EXPECT_EQ(4, urng63.calls);\n  }\n}\n\nTEST(FastUniformBitsTest, URBG32bitRegression) {\n  // Validate with deterministic 32-bit std::minstd_rand\n  // to ensure that operator() performs as expected.\n\n  EXPECT_EQ(2147483646, RangeSize<std::minstd_rand>());\n  EXPECT_EQ(30, IntegerLog2(RangeSize<std::minstd_rand>()));\n\n  std::minstd_rand gen(1);\n  FastUniformBits<uint64_t> fast64;\n\n  EXPECT_EQ(0x05e47095f8791f45, fast64(gen));\n  EXPECT_EQ(0x028be17e3c07c122, fast64(gen));\n  EXPECT_EQ(0x55d2847c1626e8c2, fast64(gen));\n}\n\n}  // namespace\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/fastmath.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_FASTMATH_H_\n#define ABSL_RANDOM_INTERNAL_FASTMATH_H_\n\n// This file contains fast math functions (bitwise ops as well as some others)\n// which are implementation details of various absl random number distributions.\n\n#include <cassert>\n#include <cmath>\n#include <cstdint>\n\n#include \"absl/numeric/bits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// Compute log2(n) using integer operations.\n// While std::log2 is more accurate than std::log(n) / std::log(2), for\n// very large numbers--those close to std::numeric_limits<uint64_t>::max() - 2,\n// for instance--std::log2 rounds up rather than down, which introduces\n// definite skew in the results.\ninline int IntLog2Floor(uint64_t n) {\n  return (n <= 1) ? 0 : (63 - countl_zero(n));\n}\ninline int IntLog2Ceil(uint64_t n) {\n  return (n <= 1) ? 0 : (64 - countl_zero(n - 1));\n}\n\ninline double StirlingLogFactorial(double n) {\n  assert(n >= 1);\n  // Using Stirling's approximation.\n  constexpr double kLog2PI = 1.83787706640934548356;\n  const double logn = std::log(n);\n  const double ninv = 1.0 / static_cast<double>(n);\n  return n * logn - n + 0.5 * (kLog2PI + logn) + (1.0 / 12.0) * ninv -\n         (1.0 / 360.0) * ninv * ninv * ninv;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_FASTMATH_H_\n"
  },
  {
    "path": "absl/random/internal/fastmath_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/fastmath.h\"\n\n#include \"gtest/gtest.h\"\n\n#if defined(__EMSCRIPTEN__)\n// Emscripten has a less accurate implementation of std::log2 than most of\n// the other platforms. For some values which should have integral results,\n// sometimes Emscripten returns slightly larger values.\n#define ABSL_RANDOM_INACCURATE_LOG2\n#endif\n\nnamespace {\n\nTEST(FastMathTest, IntLog2FloorTest) {\n  using absl::random_internal::IntLog2Floor;\n  constexpr uint64_t kZero = 0;\n  EXPECT_EQ(0, IntLog2Floor(0));  // boundary. return 0.\n  EXPECT_EQ(0, IntLog2Floor(1));\n  EXPECT_EQ(1, IntLog2Floor(2));\n  EXPECT_EQ(63, IntLog2Floor(~kZero));\n\n  // A boundary case: Converting 0xffffffffffffffff requires > 53\n  // bits of precision, so the conversion to double rounds up,\n  // and the result of std::log2(x) > IntLog2Floor(x).\n  EXPECT_LT(IntLog2Floor(~kZero), static_cast<int>(std::log2(~kZero)));\n\n  for (int i = 0; i < 64; i++) {\n    const uint64_t i_pow_2 = static_cast<uint64_t>(1) << i;\n    EXPECT_EQ(i, IntLog2Floor(i_pow_2));\n    EXPECT_EQ(i, static_cast<int>(std::log2(i_pow_2)));\n\n    uint64_t y = i_pow_2;\n    for (int j = i - 1; j > 0; --j) {\n      y = y | (i_pow_2 >> j);\n      EXPECT_EQ(i, IntLog2Floor(y));\n    }\n  }\n}\n\nTEST(FastMathTest, IntLog2CeilTest) {\n  using absl::random_internal::IntLog2Ceil;\n  constexpr uint64_t kZero = 0;\n  EXPECT_EQ(0, IntLog2Ceil(0));  // boundary. return 0.\n  EXPECT_EQ(0, IntLog2Ceil(1));\n  EXPECT_EQ(1, IntLog2Ceil(2));\n  EXPECT_EQ(64, IntLog2Ceil(~kZero));\n\n  // A boundary case: Converting 0xffffffffffffffff requires > 53\n  // bits of precision, so the conversion to double rounds up,\n  // and the result of std::log2(x) > IntLog2Floor(x).\n  EXPECT_LE(IntLog2Ceil(~kZero), static_cast<int>(std::log2(~kZero)));\n\n  for (int i = 0; i < 64; i++) {\n    const uint64_t i_pow_2 = static_cast<uint64_t>(1) << i;\n    EXPECT_EQ(i, IntLog2Ceil(i_pow_2));\n#ifndef ABSL_RANDOM_INACCURATE_LOG2\n    EXPECT_EQ(i, static_cast<int>(std::ceil(std::log2(i_pow_2))));\n#endif\n\n    uint64_t y = i_pow_2;\n    for (int j = i - 1; j > 0; --j) {\n      y = y | (i_pow_2 >> j);\n      EXPECT_EQ(i + 1, IntLog2Ceil(y));\n    }\n  }\n}\n\nTEST(FastMathTest, StirlingLogFactorial) {\n  using absl::random_internal::StirlingLogFactorial;\n\n  EXPECT_NEAR(StirlingLogFactorial(1.0), 0, 1e-3);\n  EXPECT_NEAR(StirlingLogFactorial(1.50), 0.284683, 1e-3);\n  EXPECT_NEAR(StirlingLogFactorial(2.0), 0.69314718056, 1e-4);\n\n  for (int i = 2; i < 50; i++) {\n    double d = static_cast<double>(i);\n    EXPECT_NEAR(StirlingLogFactorial(d), std::lgamma(d + 1), 3e-5);\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/gaussian_distribution_gentables.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Generates gaussian_distribution.cc\n//\n// $ blaze run :gaussian_distribution_gentables > gaussian_distribution.cc\n//\n#include <cmath>\n#include <cstddef>\n#include <iostream>\n#include <limits>\n#include <string>\n\n#include \"absl/base/macros.h\"\n#include \"absl/random/gaussian_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\ntemplate <typename T, size_t N>\nvoid FormatArrayContents(std::ostream* os, T (&data)[N]) {\n  if (!std::numeric_limits<T>::is_exact) {\n    // Note: T is either an integer or a float.\n    // float requires higher precision to ensure that values are\n    // reproduced exactly.\n    // Trivia: C99 has hexadecimal floating point literals, but C++11 does not.\n    // Using them would remove all concern of precision loss.\n    os->precision(std::numeric_limits<T>::max_digits10 + 2);\n  }\n  *os << \"    {\";\n  std::string separator = \"\";\n  for (size_t i = 0; i < N; ++i) {\n    *os << separator << data[i];\n    if ((i + 1) % 3 != 0) {\n      separator = \", \";\n    } else {\n      separator = \",\\n     \";\n    }\n  }\n  *os << \"}\";\n}\n\n}  // namespace\n\nclass TableGenerator : public gaussian_distribution_base {\n public:\n  TableGenerator();\n  void Print(std::ostream* os);\n\n  using gaussian_distribution_base::kMask;\n  using gaussian_distribution_base::kR;\n  using gaussian_distribution_base::kV;\n\n private:\n  Tables tables_;\n};\n\n// Ziggurat gaussian initialization.  For an explanation of the algorithm, see\n// the Marsaglia paper, \"The Ziggurat Method for Generating Random Variables\".\n//   http://www.jstatsoft.org/v05/i08/\n//\n// Further details are available in the Doornik paper\n//   https://www.doornik.com/research/ziggurat.pdf\n//\nTableGenerator::TableGenerator() {\n  // The constants here should match the values in gaussian_distribution.h\n  static constexpr int kC = kMask + 1;\n\n  static_assert((ABSL_ARRAYSIZE(tables_.x) == kC + 1),\n                \"xArray must be length kMask + 2\");\n\n  static_assert((ABSL_ARRAYSIZE(tables_.x) == ABSL_ARRAYSIZE(tables_.f)),\n                \"fx and x arrays must be identical length\");\n\n  auto f = [](double x) { return std::exp(-0.5 * x * x); };\n  auto f_inv = [](double x) { return std::sqrt(-2.0 * std::log(x)); };\n\n  tables_.x[0] = kV / f(kR);\n  tables_.f[0] = f(tables_.x[0]);\n\n  tables_.x[1] = kR;\n  tables_.f[1] = f(tables_.x[1]);\n\n  tables_.x[kC] = 0.0;\n  tables_.f[kC] = f(tables_.x[kC]);  // 1.0\n\n  for (int i = 2; i < kC; i++) {\n    double v = (kV / tables_.x[i - 1]) + tables_.f[i - 1];\n    tables_.x[i] = f_inv(v);\n    tables_.f[i] = v;\n  }\n}\n\nvoid TableGenerator::Print(std::ostream* os) {\n  *os << \"// BEGIN GENERATED CODE; DO NOT EDIT\\n\"\n         \"// clang-format off\\n\"\n         \"\\n\"\n         \"#include \\\"absl/random/gaussian_distribution.h\\\"\\n\"\n         \"\\n\"\n         \"namespace absl {\\n\"\n         \"ABSL_NAMESPACE_BEGIN\\n\"\n         \"namespace random_internal {\\n\"\n         \"\\n\"\n         \"const gaussian_distribution_base::Tables\\n\"\n         \"    gaussian_distribution_base::zg_ = {\\n\";\n  FormatArrayContents(os, tables_.x);\n  *os << \",\\n\";\n  FormatArrayContents(os, tables_.f);\n  *os << \"};\\n\"\n         \"\\n\"\n         \"}  // namespace random_internal\\n\"\n         \"ABSL_NAMESPACE_END\\n\"\n         \"}  // namespace absl\\n\"\n         \"\\n\"\n         \"// clang-format on\\n\"\n         \"// END GENERATED CODE\";\n  *os << std::endl;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nint main(int, char**) {\n  std::cerr << \"\\nCopy the output to gaussian_distribution.cc\" << std::endl;\n  absl::random_internal::TableGenerator generator;\n  generator.Print(&std::cout);\n  return 0;\n}\n"
  },
  {
    "path": "absl/random/internal/generate_real.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_\n#define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_\n\n// This file contains some implementation details which are used by one or more\n// of the absl random number distributions.\n\n#include <cstdint>\n#include <cstring>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/random/internal/fastmath.h\"\n#include \"absl/random/internal/traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// Tristate tag types controlling the output of GenerateRealFromBits.\nstruct GeneratePositiveTag {};\nstruct GenerateNegativeTag {};\nstruct GenerateSignedTag {};\n\n// GenerateRealFromBits generates a single real value from a single 64-bit\n// `bits` with template fields controlling the output.\n//\n// The `SignedTag` parameter controls whether positive, negative,\n// or either signed/unsigned may be returned.\n//   When SignedTag == GeneratePositiveTag, range is U(0, 1)\n//   When SignedTag == GenerateNegativeTag, range is U(-1, 0)\n//   When SignedTag == GenerateSignedTag, range is U(-1, 1)\n//\n// When the `IncludeZero` parameter is true, the function may return 0 for some\n// inputs, otherwise it never returns 0.\n//\n// When a value in U(0,1) is required, use:\n//   GenerateRealFromBits<double, PositiveValueT, true>;\n//\n// When a value in U(-1,1) is required, use:\n//   GenerateRealFromBits<double, SignedValueT, false>;\n//\n//   This generates more distinct values than the mathematical equivalent\n//   `U(0, 1) * 2.0 - 1.0`.\n//\n// Scaling the result by powers of 2 (and avoiding a multiply) is also possible:\n//   GenerateRealFromBits<double>(..., -1);  => U(0, 0.5)\n//   GenerateRealFromBits<double>(..., 1);   => U(0, 2)\n//\ntemplate <typename RealType,  // Real type, either float or double.\n          typename SignedTag = GeneratePositiveTag,  // Whether a positive,\n                                                     // negative, or signed\n                                                     // value is generated.\n          bool IncludeZero = true>\ninline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) {\n  using real_type = RealType;\n  using uint_type = absl::conditional_t<std::is_same<real_type, float>::value,\n                                        uint32_t, uint64_t>;\n\n  static_assert(\n      (std::is_same<double, real_type>::value ||\n       std::is_same<float, real_type>::value),\n      \"GenerateRealFromBits must be parameterized by either float or double.\");\n\n  static_assert(sizeof(uint_type) == sizeof(real_type),\n                \"Mismatched unsigned and real types.\");\n\n  static_assert((std::numeric_limits<real_type>::is_iec559 &&\n                 std::numeric_limits<real_type>::radix == 2),\n                \"RealType representation is not IEEE 754 binary.\");\n\n  static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value ||\n                 std::is_same<SignedTag, GenerateNegativeTag>::value ||\n                 std::is_same<SignedTag, GenerateSignedTag>::value),\n                \"\");\n\n  static constexpr int kExp = std::numeric_limits<real_type>::digits - 1;\n  static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u;\n  static constexpr int kUintBits = sizeof(uint_type) * 8;\n\n  int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2};\n\n  // Determine the sign bit.\n  // Depending on the SignedTag, this may use the left-most bit\n  // or it may be a constant value.\n  uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value\n                       ? (static_cast<uint_type>(1) << (kUintBits - 1))\n                       : 0;\n  if (std::is_same<SignedTag, GenerateSignedTag>::value) {\n    if (std::is_same<uint_type, uint64_t>::value) {\n      sign = bits & uint64_t{0x8000000000000000};\n    }\n    if (std::is_same<uint_type, uint32_t>::value) {\n      const uint64_t tmp = bits & uint64_t{0x8000000000000000};\n      sign = static_cast<uint32_t>(tmp >> 32);\n    }\n    // adjust the bits and the exponent to account for removing\n    // the leading bit.\n    bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF};\n    exp++;\n  }\n  if (IncludeZero) {\n    if (bits == 0u) return 0;\n  }\n\n  // Number of leading zeros is mapped to the exponent: 2^-clz\n  // bits is 0..01xxxxxx. After shifting, we're left with 1xxx...0..0\n  int clz = countl_zero(bits);\n  bits <<= (IncludeZero ? clz : (clz & 63));  // remove 0-bits.\n  exp -= clz;                                 // set the exponent.\n  bits >>= (63 - kExp);\n\n  // Construct the 32-bit or 64-bit IEEE 754 floating-point value from\n  // the individual fields: sign, exp, mantissa(bits).\n  uint_type val = sign | (static_cast<uint_type>(exp) << kExp) |\n                  (static_cast<uint_type>(bits) & kMask);\n\n  // bit_cast to the output-type\n  real_type result;\n  memcpy(static_cast<void*>(&result), static_cast<const void*>(&val),\n         sizeof(result));\n  return result;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_\n"
  },
  {
    "path": "absl/random/internal/generate_real_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/generate_real.h\"\n\n#include <cfloat>\n#include <cstddef>\n#include <cstdint>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/numeric/bits.h\"\n\nABSL_FLAG(int64_t, absl_random_test_trials, 50000,\n          \"Number of trials for the probability tests.\");\n\nusing absl::random_internal::GenerateNegativeTag;\nusing absl::random_internal::GeneratePositiveTag;\nusing absl::random_internal::GenerateRealFromBits;\nusing absl::random_internal::GenerateSignedTag;\n\nnamespace {\n\nTEST(GenerateRealTest, U64ToFloat_Positive_NoZero_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GeneratePositiveTag, false>(a);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), 2.710505431e-20f);\n  EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), 0.5);\n  EXPECT_EQ(ToFloat(0x8000000000000001), 0.5);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloat_Positive_Zero_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), 0.0);\n  EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), 0.5);\n  EXPECT_EQ(ToFloat(0x8000000000000001), 0.5);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloat_Negative_NoZero_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GenerateNegativeTag, false>(a);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), -2.710505431e-20f);\n  EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), -0.5);\n  EXPECT_EQ(ToFloat(0x8000000000000001), -0.5);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloat_Negative_Zero_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GenerateNegativeTag, true>(a);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), 0.0);\n  EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), -0.5);\n  EXPECT_EQ(ToFloat(0x8000000000000001), -0.5);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloat_Signed_NoZero_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GenerateSignedTag, false>(a);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), 5.421010862e-20f);\n  EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f);\n  EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 0.9999999404f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), -5.421010862e-20f);\n  EXPECT_EQ(ToFloat(0x8000000000000001), -1.084202172e-19f);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloat_Signed_Zero_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GenerateSignedTag, true>(a);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), 0);\n  EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f);\n  EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 0.9999999404f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), 0);\n  EXPECT_EQ(ToFloat(0x8000000000000001), -1.084202172e-19f);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloat_Signed_Bias_Test) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GenerateSignedTag, true>(a, 1);\n  };\n  EXPECT_EQ(ToFloat(0x0000000000000000), 0);\n  EXPECT_EQ(ToFloat(0x0000000000000001), 2 * 1.084202172e-19f);\n  EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 2 * 0.9999999404f);\n  EXPECT_EQ(ToFloat(0x8000000000000000), 0);\n  EXPECT_EQ(ToFloat(0x8000000000000001), 2 * -1.084202172e-19f);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 2 * -0.9999999404f);\n}\n\nTEST(GenerateRealTest, U64ToFloatTest) {\n  auto ToFloat = [](uint64_t a) -> float {\n    return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);\n  };\n\n  EXPECT_EQ(ToFloat(0x0000000000000000), 0.0f);\n\n  EXPECT_EQ(ToFloat(0x8000000000000000), 0.5f);\n  EXPECT_EQ(ToFloat(0x8000000000000001), 0.5f);\n  EXPECT_EQ(ToFloat(0x800000FFFFFFFFFF), 0.5f);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);\n\n  EXPECT_GT(ToFloat(0x0000000000000001), 0.0f);\n\n  EXPECT_NE(ToFloat(0x7FFFFF0000000000), ToFloat(0x7FFFFEFFFFFFFFFF));\n\n  EXPECT_LT(ToFloat(0xFFFFFFFFFFFFFFFF), 1.0f);\n  int32_t two_to_24 = 1 << 24;\n  EXPECT_EQ(static_cast<int32_t>(ToFloat(0xFFFFFFFFFFFFFFFF) * two_to_24),\n            two_to_24 - 1);\n  EXPECT_NE(static_cast<int32_t>(ToFloat(0xFFFFFFFFFFFFFFFF) * two_to_24 * 2),\n            two_to_24 * 2 - 1);\n  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), ToFloat(0xFFFFFF0000000000));\n  EXPECT_NE(ToFloat(0xFFFFFFFFFFFFFFFF), ToFloat(0xFFFFFEFFFFFFFFFF));\n  EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), ToFloat(0x7FFFFF8000000000));\n  EXPECT_NE(ToFloat(0x7FFFFFFFFFFFFFFF), ToFloat(0x7FFFFF7FFFFFFFFF));\n  EXPECT_EQ(ToFloat(0x3FFFFFFFFFFFFFFF), ToFloat(0x3FFFFFC000000000));\n  EXPECT_NE(ToFloat(0x3FFFFFFFFFFFFFFF), ToFloat(0x3FFFFFBFFFFFFFFF));\n\n  // For values where every bit counts, the values scale as multiples of the\n  // input.\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(i * ToFloat(0x0000000000000001), ToFloat(i));\n  }\n\n  // For each i: value generated from (1 << i).\n  float exp_values[64];\n  exp_values[63] = 0.5f;\n  for (int i = 62; i >= 0; --i) exp_values[i] = 0.5f * exp_values[i + 1];\n  constexpr uint64_t one = 1;\n  for (int i = 0; i < 64; ++i) {\n    EXPECT_EQ(ToFloat(one << i), exp_values[i]);\n    for (int j = 1; j < FLT_MANT_DIG && i - j >= 0; ++j) {\n      EXPECT_NE(exp_values[i] + exp_values[i - j], exp_values[i]);\n      EXPECT_EQ(ToFloat((one << i) + (one << (i - j))),\n                exp_values[i] + exp_values[i - j]);\n    }\n    for (int j = FLT_MANT_DIG; i - j >= 0; ++j) {\n      EXPECT_EQ(exp_values[i] + exp_values[i - j], exp_values[i]);\n      EXPECT_EQ(ToFloat((one << i) + (one << (i - j))), exp_values[i]);\n    }\n  }\n}\n\nTEST(GenerateRealTest, U64ToDouble_Positive_NoZero_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GeneratePositiveTag, false>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), 2.710505431213761085e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000002), 1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);\n  EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);\n}\n\nTEST(GenerateRealTest, U64ToDouble_Positive_Zero_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GeneratePositiveTag, true>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);\n  EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);\n  EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);\n}\n\nTEST(GenerateRealTest, U64ToDouble_Negative_NoZero_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GenerateNegativeTag, false>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), -2.710505431213761085e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0x8000000000000000), -0.5);\n  EXPECT_EQ(ToDouble(0x8000000000000001), -0.5);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);\n}\n\nTEST(GenerateRealTest, U64ToDouble_Negative_Zero_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GenerateNegativeTag, true>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);\n  EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0x8000000000000000), -0.5);\n  EXPECT_EQ(ToDouble(0x8000000000000001), -0.5);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);\n}\n\nTEST(GenerateRealTest, U64ToDouble_Signed_NoZero_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GenerateSignedTag, false>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978);\n  EXPECT_EQ(ToDouble(0x8000000000000000), -5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);\n}\n\nTEST(GenerateRealTest, U64ToDouble_Signed_Zero_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GenerateSignedTag, true>(a);\n  };\n  EXPECT_EQ(ToDouble(0x0000000000000000), 0);\n  EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978);\n  EXPECT_EQ(ToDouble(0x8000000000000000), 0);\n  EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);\n}\n\nTEST(GenerateRealTest, U64ToDouble_GenerateSignedTag_Bias_Test) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GenerateSignedTag, true>(a, -1);\n  };\n  EXPECT_EQ(ToDouble(0x0000000000000000), 0);\n  EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19 / 2);\n  EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978 / 2);\n  EXPECT_EQ(ToDouble(0x8000000000000000), 0);\n  EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19 / 2);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978 / 2);\n}\n\nTEST(GenerateRealTest, U64ToDoubleTest) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GeneratePositiveTag, true>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);\n  EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);\n\n  EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x7fffffffffffffef), 0.499999999999999944489);\n  EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);\n\n  // For values > 0.5, RandU64ToDouble discards up to 11 bits. (64-53).\n  EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);\n  EXPECT_EQ(ToDouble(0x80000000000007FF), 0.5);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);\n  EXPECT_NE(ToDouble(0x7FFFFFFFFFFFF800), ToDouble(0x7FFFFFFFFFFFF7FF));\n\n  EXPECT_LT(ToDouble(0xFFFFFFFFFFFFFFFF), 1.0);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), ToDouble(0xFFFFFFFFFFFFF800));\n  EXPECT_NE(ToDouble(0xFFFFFFFFFFFFFFFF), ToDouble(0xFFFFFFFFFFFFF7FF));\n  EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFC00));\n  EXPECT_NE(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFBFF));\n  EXPECT_EQ(ToDouble(0x3FFFFFFFFFFFFFFF), ToDouble(0x3FFFFFFFFFFFFE00));\n  EXPECT_NE(ToDouble(0x3FFFFFFFFFFFFFFF), ToDouble(0x3FFFFFFFFFFFFDFF));\n\n  EXPECT_EQ(ToDouble(0x1000000000000001), 0.0625);\n  EXPECT_EQ(ToDouble(0x2000000000000001), 0.125);\n  EXPECT_EQ(ToDouble(0x3000000000000001), 0.1875);\n  EXPECT_EQ(ToDouble(0x4000000000000001), 0.25);\n  EXPECT_EQ(ToDouble(0x5000000000000001), 0.3125);\n  EXPECT_EQ(ToDouble(0x6000000000000001), 0.375);\n  EXPECT_EQ(ToDouble(0x7000000000000001), 0.4375);\n  EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);\n  EXPECT_EQ(ToDouble(0x9000000000000001), 0.5625);\n  EXPECT_EQ(ToDouble(0xa000000000000001), 0.625);\n  EXPECT_EQ(ToDouble(0xb000000000000001), 0.6875);\n  EXPECT_EQ(ToDouble(0xc000000000000001), 0.75);\n  EXPECT_EQ(ToDouble(0xd000000000000001), 0.8125);\n  EXPECT_EQ(ToDouble(0xe000000000000001), 0.875);\n  EXPECT_EQ(ToDouble(0xf000000000000001), 0.9375);\n\n  // Large powers of 2.\n  int64_t two_to_53 = int64_t{1} << 53;\n  EXPECT_EQ(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53),\n            two_to_53 - 1);\n  EXPECT_NE(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53 * 2),\n            two_to_53 * 2 - 1);\n\n  // For values where every bit counts, the values scale as multiples of the\n  // input.\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(i * ToDouble(0x0000000000000001), ToDouble(i));\n  }\n\n  // For each i: value generated from (1 << i).\n  double exp_values[64];\n  exp_values[63] = 0.5;\n  for (int i = 62; i >= 0; --i) exp_values[i] = 0.5 * exp_values[i + 1];\n  constexpr uint64_t one = 1;\n  for (int i = 0; i < 64; ++i) {\n    EXPECT_EQ(ToDouble(one << i), exp_values[i]);\n    for (int j = 1; j < DBL_MANT_DIG && i - j >= 0; ++j) {\n      EXPECT_NE(exp_values[i] + exp_values[i - j], exp_values[i]);\n      EXPECT_EQ(ToDouble((one << i) + (one << (i - j))),\n                exp_values[i] + exp_values[i - j]);\n    }\n    for (int j = DBL_MANT_DIG; i - j >= 0; ++j) {\n      EXPECT_EQ(exp_values[i] + exp_values[i - j], exp_values[i]);\n      EXPECT_EQ(ToDouble((one << i) + (one << (i - j))), exp_values[i]);\n    }\n  }\n}\n\nTEST(GenerateRealTest, U64ToDoubleSignedTest) {\n  auto ToDouble = [](uint64_t a) {\n    return GenerateRealFromBits<double, GenerateSignedTag, false>(a);\n  };\n\n  EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);\n\n  EXPECT_EQ(ToDouble(0x8000000000000000), -5.42101086242752217004e-20);\n  EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19);\n\n  const double e_plus = ToDouble(0x0000000000000001);\n  const double e_minus = ToDouble(0x8000000000000001);\n  EXPECT_EQ(e_plus, 1.084202172485504434e-19);\n  EXPECT_EQ(e_minus, -1.084202172485504434e-19);\n\n  EXPECT_EQ(ToDouble(0x3fffffffffffffef), 0.499999999999999944489);\n  EXPECT_EQ(ToDouble(0xbfffffffffffffef), -0.499999999999999944489);\n\n  // For values > 0.5, RandU64ToDouble discards up to 10 bits. (63-53).\n  EXPECT_EQ(ToDouble(0x4000000000000000), 0.5);\n  EXPECT_EQ(ToDouble(0x4000000000000001), 0.5);\n  EXPECT_EQ(ToDouble(0x40000000000003FF), 0.5);\n\n  EXPECT_EQ(ToDouble(0xC000000000000000), -0.5);\n  EXPECT_EQ(ToDouble(0xC000000000000001), -0.5);\n  EXPECT_EQ(ToDouble(0xC0000000000003FF), -0.5);\n\n  EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFe), 0.999999999999999888978);\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFe), -0.999999999999999888978);\n\n  EXPECT_NE(ToDouble(0x7FFFFFFFFFFFF800), ToDouble(0x7FFFFFFFFFFFF7FF));\n\n  EXPECT_LT(ToDouble(0x7FFFFFFFFFFFFFFF), 1.0);\n  EXPECT_GT(ToDouble(0x7FFFFFFFFFFFFFFF), 0.9999999999);\n\n  EXPECT_GT(ToDouble(0xFFFFFFFFFFFFFFFe), -1.0);\n  EXPECT_LT(ToDouble(0xFFFFFFFFFFFFFFFe), -0.999999999);\n\n  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFe), ToDouble(0xFFFFFFFFFFFFFC00));\n  EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFC00));\n  EXPECT_NE(ToDouble(0xFFFFFFFFFFFFFFFe), ToDouble(0xFFFFFFFFFFFFF3FF));\n  EXPECT_NE(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFF3FF));\n\n  EXPECT_EQ(ToDouble(0x1000000000000001), 0.125);\n  EXPECT_EQ(ToDouble(0x2000000000000001), 0.25);\n  EXPECT_EQ(ToDouble(0x3000000000000001), 0.375);\n  EXPECT_EQ(ToDouble(0x4000000000000001), 0.5);\n  EXPECT_EQ(ToDouble(0x5000000000000001), 0.625);\n  EXPECT_EQ(ToDouble(0x6000000000000001), 0.75);\n  EXPECT_EQ(ToDouble(0x7000000000000001), 0.875);\n  EXPECT_EQ(ToDouble(0x7800000000000001), 0.9375);\n  EXPECT_EQ(ToDouble(0x7c00000000000001), 0.96875);\n  EXPECT_EQ(ToDouble(0x7e00000000000001), 0.984375);\n  EXPECT_EQ(ToDouble(0x7f00000000000001), 0.9921875);\n\n  // 0x8000000000000000 ~= 0\n  EXPECT_EQ(ToDouble(0x9000000000000001), -0.125);\n  EXPECT_EQ(ToDouble(0xa000000000000001), -0.25);\n  EXPECT_EQ(ToDouble(0xb000000000000001), -0.375);\n  EXPECT_EQ(ToDouble(0xc000000000000001), -0.5);\n  EXPECT_EQ(ToDouble(0xd000000000000001), -0.625);\n  EXPECT_EQ(ToDouble(0xe000000000000001), -0.75);\n  EXPECT_EQ(ToDouble(0xf000000000000001), -0.875);\n\n  // Large powers of 2.\n  int64_t two_to_53 = int64_t{1} << 53;\n  EXPECT_EQ(static_cast<int64_t>(ToDouble(0x7FFFFFFFFFFFFFFF) * two_to_53),\n            two_to_53 - 1);\n  EXPECT_EQ(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53),\n            -(two_to_53 - 1));\n\n  EXPECT_NE(static_cast<int64_t>(ToDouble(0x7FFFFFFFFFFFFFFF) * two_to_53 * 2),\n            two_to_53 * 2 - 1);\n\n  // For values where every bit counts, the values scale as multiples of the\n  // input.\n  for (int i = 1; i < 100; ++i) {\n    EXPECT_EQ(i * e_plus, ToDouble(i)) << i;\n    EXPECT_EQ(i * e_minus, ToDouble(0x8000000000000000 | i)) << i;\n  }\n}\n\nTEST(GenerateRealTest, ExhaustiveFloat) {\n  auto ToFloat = [](uint64_t a) {\n    return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);\n  };\n\n  // Rely on RandU64ToFloat generating values from greatest to least when\n  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).\n  // Thus, this algorithm stores the previous value, and if the new value is at\n  // greater than or equal to the previous value, then there is a collision in\n  // the generation algorithm.\n  //\n  // Use the computation below to convert the random value into a result:\n  //   double res = a() * (1.0f - sample) + b() * sample;\n  float last_f = 1.0, last_g = 2.0;\n  uint64_t f_collisions = 0, g_collisions = 0;\n  uint64_t f_unique = 0, g_unique = 0;\n  uint64_t total = 0;\n  auto count = [&](const float r) {\n    total++;\n    // `f` is mapped to the range [0, 1) (default)\n    const float f = 0.0f * (1.0f - r) + 1.0f * r;\n    if (f >= last_f) {\n      f_collisions++;\n    } else {\n      f_unique++;\n      last_f = f;\n    }\n    // `g` is mapped to the range [1, 2)\n    const float g = 1.0f * (1.0f - r) + 2.0f * r;\n    if (g >= last_g) {\n      g_collisions++;\n    } else {\n      g_unique++;\n      last_g = g;\n    }\n  };\n\n  size_t limit = absl::GetFlag(FLAGS_absl_random_test_trials);\n\n  // Generate all uint64_t which have unique floating point values.\n  // Counting down from 0xFFFFFFFFFFFFFFFFu ... 0x0u\n  uint64_t x = ~uint64_t(0);\n  for (; x != 0 && limit > 0;) {\n    constexpr int kDig = (64 - FLT_MANT_DIG);\n    // Set a decrement value & the next point at which to change\n    // the decrement value. By default these are 1, 0.\n    uint64_t dec = 1;\n    uint64_t chk = 0;\n\n    // Adjust decrement and check value based on how many leading 0\n    // bits are set in the current value.\n    const int clz = absl::countl_zero(x);\n    if (clz < kDig) {\n      dec <<= (kDig - clz);\n      chk = (~uint64_t(0)) >> (clz + 1);\n    }\n    for (; x > chk && limit > 0; x -= dec) {\n      count(ToFloat(x));\n      --limit;\n    }\n  }\n\n  static_assert(FLT_MANT_DIG == 24,\n                \"The float type is expected to have a 24 bit mantissa.\");\n\n  if (limit != 0) {\n    // There are between 2^28 and 2^29 unique values in the range [0, 1).  For\n    // the low values of x, there are 2^24 -1 unique values.  Once x > 2^24,\n    // there are 40 * 2^24 unique values. Thus:\n    // (2 + 4 + 8 ... + 2^23) + 40 * 2^23\n    EXPECT_LT(1 << 28, f_unique);\n    EXPECT_EQ((1 << 24) + 40 * (1 << 23) - 1, f_unique);\n    EXPECT_EQ(total, f_unique);\n    EXPECT_EQ(0, f_collisions);\n\n    // Expect at least 2^23 unique values for the range [1, 2)\n    EXPECT_LE(1 << 23, g_unique);\n    EXPECT_EQ(total - g_unique, g_collisions);\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/iostream_state_saver.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_\n#define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_\n\n#include <cmath>\n#include <cstdint>\n#include <ios>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/int128.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// The null_state_saver does nothing.\ntemplate <typename T>\nclass null_state_saver {\n public:\n  using stream_type = T;\n  using flags_type = std::ios_base::fmtflags;\n\n  null_state_saver(T&, flags_type) {}\n  ~null_state_saver() {}\n};\n\n// ostream_state_saver is a RAII object to save and restore the common\n// basic_ostream flags used when implementing `operator <<()` on any of\n// the absl random distributions.\ntemplate <typename OStream>\nclass ostream_state_saver {\n public:\n  using ostream_type = OStream;\n  using flags_type = std::ios_base::fmtflags;\n  using fill_type = typename ostream_type::char_type;\n  using precision_type = std::streamsize;\n\n  ostream_state_saver(ostream_type& os,  // NOLINT(runtime/references)\n                      flags_type flags, fill_type fill)\n      : os_(os),\n        flags_(os.flags(flags)),\n        fill_(os.fill(fill)),\n        precision_(os.precision()) {\n    // Save state in initialized variables.\n  }\n\n  ~ostream_state_saver() {\n    // Restore saved state.\n    os_.precision(precision_);\n    os_.fill(fill_);\n    os_.flags(flags_);\n  }\n\n private:\n  ostream_type& os_;\n  const flags_type flags_;\n  const fill_type fill_;\n  const precision_type precision_;\n};\n\n#if defined(__NDK_MAJOR__) && __NDK_MAJOR__ < 16\n#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 1\n#else\n#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 0\n#endif\n\ntemplate <typename CharT, typename Traits>\nostream_state_saver<std::basic_ostream<CharT, Traits>> make_ostream_state_saver(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    std::ios_base::fmtflags flags = std::ios_base::dec | std::ios_base::left |\n#if ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT\n                                    std::ios_base::fixed |\n#endif\n                                    std::ios_base::scientific) {\n  using result_type = ostream_state_saver<std::basic_ostream<CharT, Traits>>;\n  return result_type(os, flags, os.widen(' '));\n}\n\ntemplate <typename T>\ntypename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,\n                           null_state_saver<T>>\nmake_ostream_state_saver(T& is,  // NOLINT(runtime/references)\n                         std::ios_base::fmtflags flags = std::ios_base::dec) {\n  using result_type = null_state_saver<T>;\n  return result_type(is, flags);\n}\n\n// stream_precision_helper<type>::kPrecision returns the base 10 precision\n// required to stream and reconstruct a real type exact binary value through\n// a binary->decimal->binary transition.\ntemplate <typename T>\nstruct stream_precision_helper {\n  // max_digits10 may be 0 on MSVC; if so, use digits10 + 3.\n  static constexpr int kPrecision =\n      (std::numeric_limits<T>::max_digits10 > std::numeric_limits<T>::digits10)\n          ? std::numeric_limits<T>::max_digits10\n          : (std::numeric_limits<T>::digits10 + 3);\n};\n\ntemplate <>\nstruct stream_precision_helper<float> {\n  static constexpr int kPrecision = 9;\n};\ntemplate <>\nstruct stream_precision_helper<double> {\n  static constexpr int kPrecision = 17;\n};\ntemplate <>\nstruct stream_precision_helper<long double> {\n  static constexpr int kPrecision = 36;  // assuming fp128\n};\n\n// istream_state_saver is a RAII object to save and restore the common\n// std::basic_istream<> flags used when implementing `operator >>()` on any of\n// the absl random distributions.\ntemplate <typename IStream>\nclass istream_state_saver {\n public:\n  using istream_type = IStream;\n  using flags_type = std::ios_base::fmtflags;\n\n  istream_state_saver(istream_type& is,  // NOLINT(runtime/references)\n                      flags_type flags)\n      : is_(is), flags_(is.flags(flags)) {}\n\n  ~istream_state_saver() { is_.flags(flags_); }\n\n private:\n  istream_type& is_;\n  flags_type flags_;\n};\n\ntemplate <typename CharT, typename Traits>\nistream_state_saver<std::basic_istream<CharT, Traits>> make_istream_state_saver(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    std::ios_base::fmtflags flags = std::ios_base::dec |\n                                    std::ios_base::scientific |\n                                    std::ios_base::skipws) {\n  using result_type = istream_state_saver<std::basic_istream<CharT, Traits>>;\n  return result_type(is, flags);\n}\n\ntemplate <typename T>\ntypename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,\n                           null_state_saver<T>>\nmake_istream_state_saver(T& is,  // NOLINT(runtime/references)\n                         std::ios_base::fmtflags flags = std::ios_base::dec) {\n  using result_type = null_state_saver<T>;\n  return result_type(is, flags);\n}\n\n// stream_format_type<T> is a helper struct to convert types which\n// basic_iostream cannot output as decimal numbers into types which\n// basic_iostream can output as decimal numbers. Specifically:\n// * signed/unsigned char-width types are converted to int.\n// * TODO(lar): __int128 => uint128, except there is no operator << yet.\n//\ntemplate <typename T>\nstruct stream_format_type\n    : public std::conditional<(sizeof(T) == sizeof(char)), int, T> {};\n\n// stream_u128_helper allows us to write out either absl::uint128 or\n// __uint128_t types in the same way, which enables their use as internal\n// state of PRNG engines.\ntemplate <typename T>\nstruct stream_u128_helper;\n\ntemplate <>\nstruct stream_u128_helper<absl::uint128> {\n  template <typename IStream>\n  inline absl::uint128 read(IStream& in) {\n    uint64_t h = 0;\n    uint64_t l = 0;\n    in >> h >> l;\n    return absl::MakeUint128(h, l);\n  }\n\n  template <typename OStream>\n  inline void write(absl::uint128 val, OStream& out) {\n    uint64_t h = absl::Uint128High64(val);\n    uint64_t l = absl::Uint128Low64(val);\n    out << h << out.fill() << l;\n  }\n};\n\n#ifdef ABSL_HAVE_INTRINSIC_INT128\ntemplate <>\nstruct stream_u128_helper<__uint128_t> {\n  template <typename IStream>\n  inline __uint128_t read(IStream& in) {\n    uint64_t h = 0;\n    uint64_t l = 0;\n    in >> h >> l;\n    return (static_cast<__uint128_t>(h) << 64) | l;\n  }\n\n  template <typename OStream>\n  inline void write(__uint128_t val, OStream& out) {\n    uint64_t h = static_cast<uint64_t>(val >> 64u);\n    uint64_t l = static_cast<uint64_t>(val);\n    out << h << out.fill() << l;\n  }\n};\n#endif\n\ntemplate <typename FloatType, typename IStream>\ninline FloatType read_floating_point(IStream& is) {\n  static_assert(std::is_floating_point<FloatType>::value, \"\");\n  FloatType dest;\n  is >> dest;\n  // Parsing a double value may report a subnormal value as an error\n  // despite being able to represent it.\n  // See https://stackoverflow.com/q/52410931/3286653\n  // It may also report an underflow when parsing DOUBLE_MIN as an\n  // ERANGE error, as the parsed value may be smaller than DOUBLE_MIN\n  // and rounded up.\n  // See: https://stackoverflow.com/q/42005462\n  if (is.fail() &&\n      (std::fabs(dest) == (std::numeric_limits<FloatType>::min)() ||\n       std::fpclassify(dest) == FP_SUBNORMAL)) {\n    is.clear(is.rdstate() & (~std::ios_base::failbit));\n  }\n  return dest;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_\n"
  },
  {
    "path": "absl/random/internal/iostream_state_saver_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/iostream_state_saver.h\"\n\n#include <errno.h>\n#include <stdio.h>\n\n#include <sstream>\n#include <string>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing absl::random_internal::make_istream_state_saver;\nusing absl::random_internal::make_ostream_state_saver;\nusing absl::random_internal::stream_precision_helper;\n\ntemplate <typename T>\ntypename absl::enable_if_t<std::is_integral<T>::value, T>  //\nStreamRoundTrip(T t) {\n  std::stringstream ss;\n  {\n    auto saver = make_ostream_state_saver(ss);\n    ss.precision(stream_precision_helper<T>::kPrecision);\n    ss << t;\n  }\n  T result = 0;\n  {\n    auto saver = make_istream_state_saver(ss);\n    ss >> result;\n  }\n  EXPECT_FALSE(ss.fail())            //\n      << ss.str() << \" \"             //\n      << (ss.good() ? \"good \" : \"\")  //\n      << (ss.bad() ? \"bad \" : \"\")    //\n      << (ss.eof() ? \"eof \" : \"\")    //\n      << (ss.fail() ? \"fail \" : \"\");\n\n  return result;\n}\n\ntemplate <typename T>\ntypename absl::enable_if_t<std::is_floating_point<T>::value, T>  //\nStreamRoundTrip(T t) {\n  std::stringstream ss;\n  {\n    auto saver = make_ostream_state_saver(ss);\n    ss.precision(stream_precision_helper<T>::kPrecision);\n    ss << t;\n  }\n  T result = 0;\n  {\n    auto saver = make_istream_state_saver(ss);\n    result = absl::random_internal::read_floating_point<T>(ss);\n  }\n  EXPECT_FALSE(ss.fail())            //\n      << ss.str() << \" \"             //\n      << (ss.good() ? \"good \" : \"\")  //\n      << (ss.bad() ? \"bad \" : \"\")    //\n      << (ss.eof() ? \"eof \" : \"\")    //\n      << (ss.fail() ? \"fail \" : \"\");\n\n  return result;\n}\n\nTEST(IOStreamStateSaver, BasicSaverState) {\n  std::stringstream ss;\n  ss.precision(2);\n  ss.fill('x');\n  ss.flags(std::ios_base::dec | std::ios_base::right);\n\n  {\n    auto saver = make_ostream_state_saver(ss);\n    ss.precision(10);\n    EXPECT_NE('x', ss.fill());\n    EXPECT_EQ(10, ss.precision());\n    EXPECT_NE(std::ios_base::dec | std::ios_base::right, ss.flags());\n\n    ss << 1.23;\n  }\n\n  EXPECT_EQ('x', ss.fill());\n  EXPECT_EQ(2, ss.precision());\n  EXPECT_EQ(std::ios_base::dec | std::ios_base::right, ss.flags());\n}\n\nTEST(IOStreamStateSaver, RoundTripInts) {\n  const uint64_t kUintValues[] = {\n      0,\n      1,\n      static_cast<uint64_t>(-1),\n      2,\n      static_cast<uint64_t>(-2),\n\n      1 << 7,\n      1 << 8,\n      1 << 16,\n      1ull << 32,\n      1ull << 50,\n      1ull << 62,\n      1ull << 63,\n\n      (1 << 7) - 1,\n      (1 << 8) - 1,\n      (1 << 16) - 1,\n      (1ull << 32) - 1,\n      (1ull << 50) - 1,\n      (1ull << 62) - 1,\n      (1ull << 63) - 1,\n\n      static_cast<uint64_t>(-(1 << 8)),\n      static_cast<uint64_t>(-(1 << 16)),\n      static_cast<uint64_t>(-(1ll << 32)),\n      static_cast<uint64_t>(-(1ll << 50)),\n      static_cast<uint64_t>(-(1ll << 62)),\n\n      static_cast<uint64_t>(-(1 << 8) - 1),\n      static_cast<uint64_t>(-(1 << 16) - 1),\n      static_cast<uint64_t>(-(1ll << 32) - 1),\n      static_cast<uint64_t>(-(1ll << 50) - 1),\n      static_cast<uint64_t>(-(1ll << 62) - 1),\n  };\n\n  for (const uint64_t u : kUintValues) {\n    EXPECT_EQ(u, StreamRoundTrip<uint64_t>(u));\n\n    int64_t x = static_cast<int64_t>(u);\n    EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));\n\n    double d = static_cast<double>(x);\n    EXPECT_EQ(d, StreamRoundTrip<double>(d));\n\n    float f = d;\n    EXPECT_EQ(f, StreamRoundTrip<float>(f));\n  }\n}\n\nTEST(IOStreamStateSaver, RoundTripFloats) {\n  static_assert(\n      stream_precision_helper<float>::kPrecision >= 9,\n      \"stream_precision_helper<float>::kPrecision should be at least 9\");\n\n  const float kValues[] = {\n      1,\n      std::nextafter(1.0f, 0.0f),  // 1 - epsilon\n      std::nextafter(1.0f, 2.0f),  // 1 + epsilon\n\n      1.0e+1f,\n      1.0e-1f,\n      1.0e+2f,\n      1.0e-2f,\n      1.0e+10f,\n      1.0e-10f,\n\n      0.00000051110000111311111111f,\n      -0.00000051110000111211111111f,\n\n      1.234678912345678912345e+6f,\n      1.234678912345678912345e-6f,\n      1.234678912345678912345e+30f,\n      1.234678912345678912345e-30f,\n      1.234678912345678912345e+38f,\n      1.0234678912345678912345e-38f,\n\n      // Boundary cases.\n      std::numeric_limits<float>::max(),\n      std::numeric_limits<float>::lowest(),\n      std::numeric_limits<float>::epsilon(),\n      std::nextafter(std::numeric_limits<float>::min(),\n                     1.0f),               // min + epsilon\n      std::numeric_limits<float>::min(),  // smallest normal\n      // There are some errors dealing with denorms on apple platforms.\n      std::numeric_limits<float>::denorm_min(),  // smallest denorm\n      std::numeric_limits<float>::min() / 2,\n      std::nextafter(std::numeric_limits<float>::min(),\n                     0.0f),  // denorm_max\n      std::nextafter(std::numeric_limits<float>::denorm_min(), 1.0f),\n  };\n\n  for (const float f : kValues) {\n    EXPECT_EQ(f, StreamRoundTrip<float>(f));\n    EXPECT_EQ(-f, StreamRoundTrip<float>(-f));\n\n    double d = f;\n    EXPECT_EQ(d, StreamRoundTrip<double>(d));\n    EXPECT_EQ(-d, StreamRoundTrip<double>(-d));\n\n    // Avoid undefined behavior (overflow/underflow).\n    if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) &&\n        f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) {\n      int64_t x = static_cast<int64_t>(f);\n      EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));\n    }\n  }\n}\n\nTEST(IOStreamStateSaver, RoundTripDoubles) {\n  static_assert(\n      stream_precision_helper<double>::kPrecision >= 17,\n      \"stream_precision_helper<double>::kPrecision should be at least 17\");\n\n  const double kValues[] = {\n      1,\n      std::nextafter(1.0, 0.0),  // 1 - epsilon\n      std::nextafter(1.0, 2.0),  // 1 + epsilon\n\n      1.0e+1,\n      1.0e-1,\n      1.0e+2,\n      1.0e-2,\n      1.0e+10,\n      1.0e-10,\n\n      0.00000051110000111311111111,\n      -0.00000051110000111211111111,\n\n      1.234678912345678912345e+6,\n      1.234678912345678912345e-6,\n      1.234678912345678912345e+30,\n      1.234678912345678912345e-30,\n      1.234678912345678912345e+38,\n      1.0234678912345678912345e-38,\n\n      1.0e+100,\n      1.0e-100,\n      1.234678912345678912345e+308,\n      1.0234678912345678912345e-308,\n      2.22507385850720138e-308,\n\n      // Boundary cases.\n      std::numeric_limits<double>::max(),\n      std::numeric_limits<double>::lowest(),\n      std::numeric_limits<double>::epsilon(),\n      std::nextafter(std::numeric_limits<double>::min(),\n                     1.0),                 // min + epsilon\n      std::numeric_limits<double>::min(),  // smallest normal\n      // There are some errors dealing with denorms on apple platforms.\n      std::numeric_limits<double>::denorm_min(),  // smallest denorm\n      std::numeric_limits<double>::min() / 2,\n      std::nextafter(std::numeric_limits<double>::min(),\n                     0.0),  // denorm_max\n      std::nextafter(std::numeric_limits<double>::denorm_min(), 1.0f),\n  };\n\n  for (const double d : kValues) {\n    EXPECT_EQ(d, StreamRoundTrip<double>(d));\n    EXPECT_EQ(-d, StreamRoundTrip<double>(-d));\n\n    // Avoid undefined behavior (overflow/underflow).\n    if (d <= std::numeric_limits<float>::max() &&\n        d >= std::numeric_limits<float>::lowest()) {\n      float f = static_cast<float>(d);\n      EXPECT_EQ(f, StreamRoundTrip<float>(f));\n    }\n\n    // Avoid undefined behavior (overflow/underflow).\n    if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) &&\n        d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) {\n      int64_t x = static_cast<int64_t>(d);\n      EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));\n    }\n  }\n}\n\nTEST(IOStreamStateSaver, RoundTripLongDoubles) {\n  // Technically, C++ only guarantees that long double is at least as large as a\n  // double.  Practically it varies from 64-bits to 128-bits.\n  //\n  // So it is best to consider long double a best-effort extended precision\n  // type.\n\n  static_assert(\n      stream_precision_helper<long double>::kPrecision >= 36,\n      \"stream_precision_helper<long double>::kPrecision should be at least 36\");\n\n  using real_type = long double;\n  const real_type kValues[] = {\n      1,\n      std::nextafter(1.0, 0.0),  // 1 - epsilon\n      std::nextafter(1.0, 2.0),  // 1 + epsilon\n\n      1.0e+1,\n      1.0e-1,\n      1.0e+2,\n      1.0e-2,\n      1.0e+10,\n      1.0e-10,\n\n      0.00000051110000111311111111,\n      -0.00000051110000111211111111,\n\n      1.2346789123456789123456789123456789e+6,\n      1.2346789123456789123456789123456789e-6,\n      1.2346789123456789123456789123456789e+30,\n      1.2346789123456789123456789123456789e-30,\n      1.2346789123456789123456789123456789e+38,\n      1.2346789123456789123456789123456789e-38,\n      1.2346789123456789123456789123456789e+308,\n      1.2346789123456789123456789123456789e-308,\n\n      1.0e+100,\n      1.0e-100,\n      1.234678912345678912345e+308,\n      1.0234678912345678912345e-308,\n\n      // Boundary cases.\n      std::numeric_limits<real_type>::max(),\n      std::numeric_limits<real_type>::lowest(),\n      std::numeric_limits<real_type>::epsilon(),\n      std::nextafter(std::numeric_limits<real_type>::min(),\n                     real_type(1)),           // min + epsilon\n      std::numeric_limits<real_type>::min(),  // smallest normal\n      // There are some errors dealing with denorms on apple platforms.\n      std::numeric_limits<real_type>::denorm_min(),  // smallest denorm\n      std::numeric_limits<real_type>::min() / 2,\n      std::nextafter(std::numeric_limits<real_type>::min(),\n                     0.0),  // denorm_max\n      std::nextafter(std::numeric_limits<real_type>::denorm_min(), 1.0f),\n  };\n\n  int index = -1;\n  for (const long double dd : kValues) {\n    index++;\n    EXPECT_EQ(dd, StreamRoundTrip<real_type>(dd)) << index;\n    EXPECT_EQ(-dd, StreamRoundTrip<real_type>(-dd)) << index;\n\n    // Avoid undefined behavior (overflow/underflow).\n    if (dd <= std::numeric_limits<double>::max() &&\n        dd >= std::numeric_limits<double>::lowest()) {\n      double d = static_cast<double>(dd);\n      EXPECT_EQ(d, StreamRoundTrip<double>(d));\n    }\n\n    // Avoid undefined behavior (overflow/underflow).\n    if (dd <= static_cast<long double>(std::numeric_limits<int64_t>::max()) &&\n        dd >=\n            static_cast<long double>(std::numeric_limits<int64_t>::lowest())) {\n      int64_t x = static_cast<int64_t>(dd);\n      EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));\n    }\n  }\n}\n\nTEST(StrToDTest, DoubleMin) {\n  const char kV[] = \"2.22507385850720138e-308\";\n  char* end;\n  double x = std::strtod(kV, &end);\n  EXPECT_EQ(std::numeric_limits<double>::min(), x);\n  // errno may equal ERANGE.\n}\n\nTEST(StrToDTest, DoubleDenormMin) {\n  const char kV[] = \"4.94065645841246544e-324\";\n  char* end;\n  double x = std::strtod(kV, &end);\n  EXPECT_EQ(std::numeric_limits<double>::denorm_min(), x);\n  // errno may equal ERANGE.\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/mock_helpers.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_\n#define ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_\n\n#include <optional>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/types/optional.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// A no-op validator meeting the ValidatorT requirements for MockHelpers.\n//\n// Custom validators should follow a similar structure, passing the type to\n// MockHelpers::MockFor<KeyT>(m, CustomValidatorT()).\nstruct NoOpValidator {\n  // Default validation: do nothing.\n  template <typename ResultT, typename... Args>\n  static void Validate(ResultT, Args&&...) {}\n};\n\n// MockHelpers works in conjunction with MockOverloadSet, MockingBitGen, and\n// BitGenRef to enable the mocking capability for absl distribution functions.\n//\n// MockingBitGen registers mocks based on the typeid of a mock signature, KeyT,\n// which is used to generate a unique id.\n//\n// KeyT is a signature of the form:\n//   result_type(discriminator_type, std::tuple<args...>)\n// The mocked function signature will be composed from KeyT as:\n//   result_type(args...)\n//\nclass MockHelpers {\n  using IdType = ::absl::FastTypeIdType;\n\n  // Given a key signature type used to index the mock, extract the components.\n  // KeyT is expected to have the form:\n  //   result_type(discriminator_type, arg_tuple_type)\n  template <typename KeyT>\n  struct KeySignature;\n\n  template <typename ResultT, typename DiscriminatorT, typename ArgTupleT>\n  struct KeySignature<ResultT(DiscriminatorT, ArgTupleT)> {\n    using result_type = ResultT;\n    using discriminator_type = DiscriminatorT;\n    using arg_tuple_type = ArgTupleT;\n  };\n\n  // Detector for InvokeMock.\n  template <class T>\n  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(\n      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));\n\n  // Empty implementation of InvokeMock.\n  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,\n            typename... Args>\n  static std::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {\n    return std::nullopt;\n  }\n\n  // Non-empty implementation of InvokeMock.\n  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,\n            typename = invoke_mock_t<URBG>, typename... Args>\n  static std::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,\n                                               Args&&... args) {\n    ArgTupleT arg_tuple(std::forward<Args>(args)...);\n    ReturnT result;\n    if (urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {\n      return result;\n    }\n    return std::nullopt;\n  }\n\n public:\n  // InvokeMock is private; this provides access for some specialized use cases.\n  template <typename URBG>\n  static inline bool PrivateInvokeMock(URBG* urbg, IdType key_id,\n                                       void* args_tuple, void* result) {\n    return urbg->InvokeMock(key_id, args_tuple, result);\n  }\n\n  // Invoke a mock for the KeyT (may or may not be a signature).\n  //\n  // KeyT is used to generate a typeid-based lookup key for the mock.\n  // KeyT is a signature of the form:\n  //   result_type(discriminator_type, std::tuple<args...>)\n  // The mocked function signature will be composed from KeyT as:\n  //   result_type(args...)\n  //\n  // An instance of arg_tuple_type must be constructable from Args..., since\n  // the underlying mechanism requires a pointer to an argument tuple.\n  template <typename KeyT, typename URBG, typename... Args>\n  static auto MaybeInvokeMock(URBG* urbg, Args&&... args)\n      -> std::optional<typename KeySignature<KeyT>::result_type> {\n    // Use function overloading to dispatch to the implementation since\n    // more modern patterns (e.g. require + constexpr) are not supported in all\n    // compiler configurations.\n    return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,\n                          typename KeySignature<KeyT>::arg_tuple_type, URBG>(\n        0, urbg, std::forward<Args>(args)...);\n  }\n\n  // Acquire a mock for the KeyT (may or may not be a signature), set up to use\n  // the ValidatorT to verify that the result is in the range of the RNG\n  // function.\n  //\n  // KeyT is used to generate a typeid-based lookup for the mock.\n  // KeyT is a signature of the form:\n  //   result_type(discriminator_type, std::tuple<args...>)\n  // The mocked function signature will be composed from KeyT as:\n  //   result_type(args...)\n  // ValidatorT::Validate will be called after the result of the RNG. The\n  //   signature is expected to be of the form:\n  //      ValidatorT::Validate(result, args...)\n  template <typename KeyT, typename ValidatorT, typename MockURBG>\n  static auto MockFor(MockURBG& m, ValidatorT)\n      -> decltype(m.template RegisterMock<\n                  typename KeySignature<KeyT>::result_type,\n                  typename KeySignature<KeyT>::arg_tuple_type>(\n          m, std::declval<IdType>(), ValidatorT())) {\n    return m.template RegisterMock<typename KeySignature<KeyT>::result_type,\n                                   typename KeySignature<KeyT>::arg_tuple_type>(\n        m, ::absl::FastTypeId<KeyT>(), ValidatorT());\n  }\n\n  // Acquire a mock for the KeyT (may or may not be a signature).\n  //\n  // KeyT is used to generate a typeid-based lookup for the mock.\n  // KeyT is a signature of the form:\n  //   result_type(discriminator_type, std::tuple<args...>)\n  // The mocked function signature will be composed from KeyT as:\n  //   result_type(args...)\n  template <typename KeyT, typename MockURBG>\n  static decltype(auto) MockFor(MockURBG& m) {\n    return MockFor<KeyT>(m, NoOpValidator());\n  }\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_\n"
  },
  {
    "path": "absl/random/internal/mock_overload_set.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_\n#define ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_\n\n#include <tuple>\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/mock_helpers.h\"\n#include \"absl/random/mocking_bit_gen.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\ntemplate <typename DistrT, typename ValidatorT, typename Fn>\nstruct MockSingleOverload;\n\n// MockSingleOverload\n//\n// MockSingleOverload hooks in to gMock's `ON_CALL` and `EXPECT_CALL` macros.\n// EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to\n// `mock_single_overload.gmock_Call(...)`. Because expectations are stored on\n// the MockingBitGen (an argument passed inside `Call(...)`), this forwards to\n// arguments to MockingBitGen::Register.\n//\n// The underlying KeyT must match the KeyT constructed by DistributionCaller.\ntemplate <typename DistrT, typename ValidatorT, typename Ret, typename... Args>\nstruct MockSingleOverload<DistrT, ValidatorT, Ret(MockingBitGen&, Args...)> {\n  static_assert(std::is_same<typename DistrT::result_type, Ret>::value,\n                \"Overload signature must have return type matching the \"\n                \"distribution result_type.\");\n  using KeyT = Ret(DistrT, std::tuple<Args...>);\n\n  template <typename MockURBG>\n  auto gmock_Call(MockURBG& gen, const ::testing::Matcher<Args>&... matchers)\n      -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())\n                      .gmock_Call(matchers...)) {\n    static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,\n                  \"Mocking requires an absl::MockingBitGen\");\n    return MockHelpers::MockFor<KeyT>(gen, ValidatorT())\n        .gmock_Call(matchers...);\n  }\n};\n\ntemplate <typename DistrT, typename ValidatorT, typename Ret, typename Arg,\n          typename... Args>\nstruct MockSingleOverload<DistrT, ValidatorT,\n                          Ret(Arg, MockingBitGen&, Args...)> {\n  static_assert(std::is_same<typename DistrT::result_type, Ret>::value,\n                \"Overload signature must have return type matching the \"\n                \"distribution result_type.\");\n  using KeyT = Ret(DistrT, std::tuple<Arg, Args...>);\n\n  template <typename MockURBG>\n  auto gmock_Call(const ::testing::Matcher<Arg>& matcher, MockURBG& gen,\n                  const ::testing::Matcher<Args>&... matchers)\n      -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())\n                      .gmock_Call(matcher, matchers...)) {\n    static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,\n                  \"Mocking requires an absl::MockingBitGen\");\n    return MockHelpers::MockFor<KeyT>(gen, ValidatorT())\n        .gmock_Call(matcher, matchers...);\n  }\n};\n\n// MockOverloadSetWithValidator\n//\n// MockOverloadSetWithValidator is a wrapper around MockOverloadSet which takes\n// an additional Validator parameter, allowing for customization of the mock\n// behavior.\n//\n// `ValidatorT::Validate(result, args...)` will be called after the mock\n// distribution returns a value in `result`, allowing for validation against the\n// args.\ntemplate <typename DistrT, typename ValidatorT, typename... Fns>\nstruct MockOverloadSetWithValidator;\n\ntemplate <typename DistrT, typename ValidatorT, typename Sig>\nstruct MockOverloadSetWithValidator<DistrT, ValidatorT, Sig>\n    : public MockSingleOverload<DistrT, ValidatorT, Sig> {\n  using MockSingleOverload<DistrT, ValidatorT, Sig>::gmock_Call;\n};\n\ntemplate <typename DistrT, typename ValidatorT, typename FirstSig,\n          typename... Rest>\nstruct MockOverloadSetWithValidator<DistrT, ValidatorT, FirstSig, Rest...>\n    : public MockSingleOverload<DistrT, ValidatorT, FirstSig>,\n      public MockOverloadSetWithValidator<DistrT, ValidatorT, Rest...> {\n  using MockSingleOverload<DistrT, ValidatorT, FirstSig>::gmock_Call;\n  using MockOverloadSetWithValidator<DistrT, ValidatorT, Rest...>::gmock_Call;\n};\n\n// MockOverloadSet\n//\n// MockOverloadSet takes a distribution and a collection of signatures and\n// performs overload resolution amongst all the overloads. This makes\n// `EXPECT_CALL(mock_overload_set, Call(...))` expand and do overload resolution\n// correctly.\ntemplate <typename DistrT, typename... Signatures>\nusing MockOverloadSet =\n    MockOverloadSetWithValidator<DistrT, NoOpValidator, Signatures...>;\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_\n"
  },
  {
    "path": "absl/random/internal/mock_validators.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_MOCK_VALIDATORS_H_\n#define ABSL_RANDOM_INTERNAL_MOCK_VALIDATORS_H_\n\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/internal/uniform_helper.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\ntemplate <typename NumType>\nclass UniformDistributionValidator {\n public:\n  // Handle absl::Uniform<NumType>(gen, absl::IntervalTag, lo, hi).\n  template <typename TagType>\n  static void Validate(NumType x, TagType tag, NumType lo, NumType hi) {\n    // For invalid ranges, absl::Uniform() simply returns one of the bounds.\n    if (x == lo && lo == hi) return;\n\n    ValidateImpl(std::is_floating_point<NumType>{}, x, tag, lo, hi);\n  }\n\n  // Handle absl::Uniform<NumType>(gen, lo, hi).\n  static void Validate(NumType x, NumType lo, NumType hi) {\n    Validate(x, IntervalClosedOpenTag(), lo, hi);\n  }\n\n  // Handle absl::Uniform<NumType>(gen).\n  static void Validate(NumType) {\n    // absl::Uniform<NumType>(gen) spans the entire range of `NumType`, so any\n    // value is okay. This overload exists because the validation logic attempts\n    // to call it anyway rather than adding extra SFINAE.\n  }\n\n private:\n  static absl::string_view TagLbBound(IntervalClosedOpenTag) { return \"[\"; }\n  static absl::string_view TagLbBound(IntervalOpenOpenTag) { return \"(\"; }\n  static absl::string_view TagLbBound(IntervalClosedClosedTag) { return \"[\"; }\n  static absl::string_view TagLbBound(IntervalOpenClosedTag) { return \"(\"; }\n  static absl::string_view TagUbBound(IntervalClosedOpenTag) { return \")\"; }\n  static absl::string_view TagUbBound(IntervalOpenOpenTag) { return \")\"; }\n  static absl::string_view TagUbBound(IntervalClosedClosedTag) { return \"]\"; }\n  static absl::string_view TagUbBound(IntervalOpenClosedTag) { return \"]\"; }\n\n  template <typename TagType>\n  static void ValidateImpl(std::true_type /* is_floating_point */, NumType x,\n                           TagType tag, NumType lo, NumType hi) {\n    UniformDistributionWrapper<NumType> dist(tag, lo, hi);\n    NumType lb = dist.a();\n    NumType ub = dist.b();\n    // uniform_real_distribution is always closed-open, so the upper bound is\n    // always non-inclusive.\n    ABSL_INTERNAL_CHECK(lb <= x && x < ub,\n                        absl::StrCat(x, \" is not in \", TagLbBound(tag), lo,\n                                     \", \", hi, TagUbBound(tag)));\n  }\n\n  template <typename TagType>\n  static void ValidateImpl(std::false_type /* is_floating_point */, NumType x,\n                           TagType tag, NumType lo, NumType hi) {\n    using stream_type =\n        typename random_internal::stream_format_type<NumType>::type;\n\n    UniformDistributionWrapper<NumType> dist(tag, lo, hi);\n    NumType lb = dist.a();\n    NumType ub = dist.b();\n    ABSL_INTERNAL_CHECK(\n        lb <= x && x <= ub,\n        absl::StrCat(stream_type{x}, \" is not in \", TagLbBound(tag),\n                     stream_type{lo}, \", \", stream_type{hi}, TagUbBound(tag)));\n  }\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_MOCK_VALIDATORS_H_\n"
  },
  {
    "path": "absl/random/internal/nanobenchmark.cc",
    "content": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/nanobenchmark.h\"\n\n#include <sys/types.h>\n\n#include <algorithm>  // sort\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>  // memcpy\n#include <limits>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/random/internal/platform.h\"\n#include \"absl/random/internal/randen_engine.h\"\n\n// OS\n#if defined(_WIN32) || defined(_WIN64)\n#define ABSL_OS_WIN\n#include <windows.h>  // NOLINT\n\n#elif defined(__ANDROID__)\n#define ABSL_OS_ANDROID\n\n#elif defined(__linux__)\n#define ABSL_OS_LINUX\n#include <sched.h>        // NOLINT\n#include <sys/syscall.h>  // NOLINT\n#endif\n\n#if defined(ABSL_ARCH_X86_64) && !defined(ABSL_OS_WIN)\n#include <cpuid.h>  // NOLINT\n#endif\n\n// __ppc_get_timebase_freq\n#if defined(ABSL_ARCH_PPC)\n#include <sys/platform/ppc.h>  // NOLINT\n#endif\n\n// clock_gettime\n#if defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)\n#include <time.h>  // NOLINT\n#endif\n\n// ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE prevents inlining of the method.\n#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __attribute__((noinline))\n#elif defined(_MSC_VER)\n#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __declspec(noinline)\n#else\n#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal_nanobenchmark {\nnamespace {\n\n// For code folding.\nnamespace platform {\n#if defined(ABSL_ARCH_X86_64)\n\n// TODO(janwas): Merge with the one in randen_hwaes.cc?\nvoid Cpuid(const uint32_t level, const uint32_t count,\n           uint32_t* ABSL_RANDOM_INTERNAL_RESTRICT abcd) {\n#if defined(ABSL_OS_WIN)\n  int regs[4];\n  __cpuidex(regs, level, count);\n  for (int i = 0; i < 4; ++i) {\n    abcd[i] = regs[i];\n  }\n#else\n  uint32_t a, b, c, d;\n  __cpuid_count(level, count, a, b, c, d);\n  abcd[0] = a;\n  abcd[1] = b;\n  abcd[2] = c;\n  abcd[3] = d;\n#endif\n}\n\nstd::string BrandString() {\n  char brand_string[49];\n  uint32_t abcd[4];\n\n  // Check if brand string is supported (it is on all reasonable Intel/AMD)\n  Cpuid(0x80000000U, 0, abcd);\n  if (abcd[0] < 0x80000004U) {\n    return std::string();\n  }\n\n  for (int i = 0; i < 3; ++i) {\n    Cpuid(0x80000002U + i, 0, abcd);\n    memcpy(brand_string + i * 16, &abcd, sizeof(abcd));\n  }\n  brand_string[48] = 0;\n  return brand_string;\n}\n\n// Returns the frequency quoted inside the brand string. This does not\n// account for throttling nor Turbo Boost.\ndouble NominalClockRate() {\n  const std::string& brand_string = BrandString();\n  // Brand strings include the maximum configured frequency. These prefixes are\n  // defined by Intel CPUID documentation.\n  const char* prefixes[3] = {\"MHz\", \"GHz\", \"THz\"};\n  const double multipliers[3] = {1E6, 1E9, 1E12};\n  for (size_t i = 0; i < 3; ++i) {\n    const size_t pos_prefix = brand_string.find(prefixes[i]);\n    if (pos_prefix != std::string::npos) {\n      const size_t pos_space = brand_string.rfind(' ', pos_prefix - 1);\n      if (pos_space != std::string::npos) {\n        const std::string digits =\n            brand_string.substr(pos_space + 1, pos_prefix - pos_space - 1);\n        return std::stod(digits) * multipliers[i];\n      }\n    }\n  }\n\n  return 0.0;\n}\n\n#endif  // ABSL_ARCH_X86_64\n}  // namespace platform\n\n// Prevents the compiler from eliding the computations that led to \"output\".\ntemplate <class T>\ninline void PreventElision(T&& output) {\n#ifndef ABSL_OS_WIN\n  // Works by indicating to the compiler that \"output\" is being read and\n  // modified. The +r constraint avoids unnecessary writes to memory, but only\n  // works for built-in types (typically FuncOutput).\n  asm volatile(\"\" : \"+r\"(output) : : \"memory\");\n#else\n  // MSVC does not support inline assembly anymore (and never supported GCC's\n  // RTL constraints). Self-assignment with #pragma optimize(\"off\") might be\n  // expected to prevent elision, but it does not with MSVC 2015. Type-punning\n  // with volatile pointers generates inefficient code on MSVC 2017.\n  static std::atomic<T> dummy(T{});\n  dummy.store(output, std::memory_order_relaxed);\n#endif\n}\n\nnamespace timer {\n\n// Start/Stop return absolute timestamps and must be placed immediately before\n// and after the region to measure. We provide separate Start/Stop functions\n// because they use different fences.\n//\n// Background: RDTSC is not 'serializing'; earlier instructions may complete\n// after it, and/or later instructions may complete before it. 'Fences' ensure\n// regions' elapsed times are independent of such reordering. The only\n// documented unprivileged serializing instruction is CPUID, which acts as a\n// full fence (no reordering across it in either direction). Unfortunately\n// the latency of CPUID varies wildly (perhaps made worse by not initializing\n// its EAX input). Because it cannot reliably be deducted from the region's\n// elapsed time, it must not be included in the region to measure (i.e.\n// between the two RDTSC).\n//\n// The newer RDTSCP is sometimes described as serializing, but it actually\n// only serves as a half-fence with release semantics. Although all\n// instructions in the region will complete before the final timestamp is\n// captured, subsequent instructions may leak into the region and increase the\n// elapsed time. Inserting another fence after the final RDTSCP would prevent\n// such reordering without affecting the measured region.\n//\n// Fortunately, such a fence exists. The LFENCE instruction is only documented\n// to delay later loads until earlier loads are visible. However, Intel's\n// reference manual says it acts as a full fence (waiting until all earlier\n// instructions have completed, and delaying later instructions until it\n// completes). AMD assigns the same behavior to MFENCE.\n//\n// We need a fence before the initial RDTSC to prevent earlier instructions\n// from leaking into the region, and arguably another after RDTSC to avoid\n// region instructions from completing before the timestamp is recorded.\n// When surrounded by fences, the additional RDTSCP half-fence provides no\n// benefit, so the initial timestamp can be recorded via RDTSC, which has\n// lower overhead than RDTSCP because it does not read TSC_AUX. In summary,\n// we define Start = LFENCE/RDTSC/LFENCE; Stop = RDTSCP/LFENCE.\n//\n// Using Start+Start leads to higher variance and overhead than Stop+Stop.\n// However, Stop+Stop includes an LFENCE in the region measurements, which\n// adds a delay dependent on earlier loads. The combination of Start+Stop\n// is faster than Start+Start and more consistent than Stop+Stop because\n// the first LFENCE already delayed subsequent loads before the measured\n// region. This combination seems not to have been considered in prior work:\n// http://akaros.cs.berkeley.edu/lxr/akaros/kern/arch/x86/rdtsc_test.c\n//\n// Note: performance counters can measure 'exact' instructions-retired or\n// (unhalted) cycle counts. The RDPMC instruction is not serializing and also\n// requires fences. Unfortunately, it is not accessible on all OSes and we\n// prefer to avoid kernel-mode drivers. Performance counters are also affected\n// by several under/over-count errata, so we use the TSC instead.\n\n// Returns a 64-bit timestamp in unit of 'ticks'; to convert to seconds,\n// divide by InvariantTicksPerSecond.\ninline uint64_t Start64() {\n  uint64_t t;\n#if defined(ABSL_ARCH_PPC)\n  asm volatile(\"mfspr %0, %1\" : \"=r\"(t) : \"i\"(268));\n#elif defined(ABSL_ARCH_X86_64)\n#if defined(ABSL_OS_WIN)\n  _ReadWriteBarrier();\n  _mm_lfence();\n  _ReadWriteBarrier();\n  t = __rdtsc();\n  _ReadWriteBarrier();\n  _mm_lfence();\n  _ReadWriteBarrier();\n#else\n  asm volatile(\n      \"lfence\\n\\t\"\n      \"rdtsc\\n\\t\"\n      \"shl $32, %%rdx\\n\\t\"\n      \"or %%rdx, %0\\n\\t\"\n      \"lfence\"\n      : \"=a\"(t)\n      :\n      // \"memory\" avoids reordering. rdx = TSC >> 32.\n      // \"cc\" = flags modified by SHL.\n      : \"rdx\", \"memory\", \"cc\");\n#endif\n#else\n  // Fall back to OS - unsure how to reliably query cntvct_el0 frequency.\n  timespec ts;\n  clock_gettime(CLOCK_REALTIME, &ts);\n  t = ts.tv_sec * 1000000000LL + ts.tv_nsec;\n#endif\n  return t;\n}\n\ninline uint64_t Stop64() {\n  uint64_t t;\n#if defined(ABSL_ARCH_X86_64)\n#if defined(ABSL_OS_WIN)\n  _ReadWriteBarrier();\n  unsigned aux;\n  t = __rdtscp(&aux);\n  _ReadWriteBarrier();\n  _mm_lfence();\n  _ReadWriteBarrier();\n#else\n  // Use inline asm because __rdtscp generates code to store TSC_AUX (ecx).\n  asm volatile(\n      \"rdtscp\\n\\t\"\n      \"shl $32, %%rdx\\n\\t\"\n      \"or %%rdx, %0\\n\\t\"\n      \"lfence\"\n      : \"=a\"(t)\n      :\n      // \"memory\" avoids reordering. rcx = TSC_AUX. rdx = TSC >> 32.\n      // \"cc\" = flags modified by SHL.\n      : \"rcx\", \"rdx\", \"memory\", \"cc\");\n#endif\n#else\n  t = Start64();\n#endif\n  return t;\n}\n\n// Returns a 32-bit timestamp with about 4 cycles less overhead than\n// Start64. Only suitable for measuring very short regions because the\n// timestamp overflows about once a second.\ninline uint32_t Start32() {\n  uint32_t t;\n#if defined(ABSL_ARCH_X86_64)\n#if defined(ABSL_OS_WIN)\n  _ReadWriteBarrier();\n  _mm_lfence();\n  _ReadWriteBarrier();\n  t = static_cast<uint32_t>(__rdtsc());\n  _ReadWriteBarrier();\n  _mm_lfence();\n  _ReadWriteBarrier();\n#else\n  asm volatile(\n      \"lfence\\n\\t\"\n      \"rdtsc\\n\\t\"\n      \"lfence\"\n      : \"=a\"(t)\n      :\n      // \"memory\" avoids reordering. rdx = TSC >> 32.\n      : \"rdx\", \"memory\");\n#endif\n#else\n  t = static_cast<uint32_t>(Start64());\n#endif\n  return t;\n}\n\ninline uint32_t Stop32() {\n  uint32_t t;\n#if defined(ABSL_ARCH_X86_64)\n#if defined(ABSL_OS_WIN)\n  _ReadWriteBarrier();\n  unsigned aux;\n  t = static_cast<uint32_t>(__rdtscp(&aux));\n  _ReadWriteBarrier();\n  _mm_lfence();\n  _ReadWriteBarrier();\n#else\n  // Use inline asm because __rdtscp generates code to store TSC_AUX (ecx).\n  asm volatile(\n      \"rdtscp\\n\\t\"\n      \"lfence\"\n      : \"=a\"(t)\n      :\n      // \"memory\" avoids reordering. rcx = TSC_AUX. rdx = TSC >> 32.\n      : \"rcx\", \"rdx\", \"memory\");\n#endif\n#else\n  t = static_cast<uint32_t>(Stop64());\n#endif\n  return t;\n}\n\n}  // namespace timer\n\nnamespace robust_statistics {\n\n// Sorts integral values in ascending order (e.g. for Mode). About 3x faster\n// than std::sort for input distributions with very few unique values.\ntemplate <class T>\nvoid CountingSort(T* values, size_t num_values) {\n  // Unique values and their frequency (similar to flat_map).\n  using Unique = std::pair<T, int>;\n  std::vector<Unique> unique;\n  for (size_t i = 0; i < num_values; ++i) {\n    const T value = values[i];\n    const auto pos =\n        std::find_if(unique.begin(), unique.end(),\n                     [value](const Unique u) { return u.first == value; });\n    if (pos == unique.end()) {\n      unique.push_back(std::make_pair(value, 1));\n    } else {\n      ++pos->second;\n    }\n  }\n\n  // Sort in ascending order of value (pair.first).\n  std::sort(unique.begin(), unique.end());\n\n  // Write that many copies of each unique value to the array.\n  T* ABSL_RANDOM_INTERNAL_RESTRICT p = values;\n  for (const auto& value_count : unique) {\n    std::fill_n(p, value_count.second, value_count.first);\n    p += value_count.second;\n  }\n  ABSL_RAW_CHECK(p == values + num_values, \"Did not produce enough output\");\n}\n\n// @return i in [idx_begin, idx_begin + half_count) that minimizes\n// sorted[i + half_count] - sorted[i].\ntemplate <typename T>\nsize_t MinRange(const T* const ABSL_RANDOM_INTERNAL_RESTRICT sorted,\n                const size_t idx_begin, const size_t half_count) {\n  T min_range = (std::numeric_limits<T>::max)();\n  size_t min_idx = 0;\n\n  for (size_t idx = idx_begin; idx < idx_begin + half_count; ++idx) {\n    ABSL_RAW_CHECK(sorted[idx] <= sorted[idx + half_count], \"Not sorted\");\n    const T range = sorted[idx + half_count] - sorted[idx];\n    if (range < min_range) {\n      min_range = range;\n      min_idx = idx;\n    }\n  }\n\n  return min_idx;\n}\n\n// Returns an estimate of the mode by calling MinRange on successively\n// halved intervals. \"sorted\" must be in ascending order. This is the\n// Half Sample Mode estimator proposed by Bickel in \"On a fast, robust\n// estimator of the mode\", with complexity O(N log N). The mode is less\n// affected by outliers in highly-skewed distributions than the median.\n// The averaging operation below assumes \"T\" is an unsigned integer type.\ntemplate <typename T>\nT ModeOfSorted(const T* const ABSL_RANDOM_INTERNAL_RESTRICT sorted,\n               const size_t num_values) {\n  size_t idx_begin = 0;\n  size_t half_count = num_values / 2;\n  while (half_count > 1) {\n    idx_begin = MinRange(sorted, idx_begin, half_count);\n    half_count >>= 1;\n  }\n\n  const T x = sorted[idx_begin + 0];\n  if (half_count == 0) {\n    return x;\n  }\n  ABSL_RAW_CHECK(half_count == 1, \"Should stop at half_count=1\");\n  const T average = (x + sorted[idx_begin + 1] + 1) / 2;\n  return average;\n}\n\n// Returns the mode. Side effect: sorts \"values\".\ntemplate <typename T>\nT Mode(T* values, const size_t num_values) {\n  CountingSort(values, num_values);\n  return ModeOfSorted(values, num_values);\n}\n\ntemplate <typename T, size_t N>\nT Mode(T (&values)[N]) {\n  return Mode(&values[0], N);\n}\n\n// Returns the median value. Side effect: sorts \"values\".\ntemplate <typename T>\nT Median(T* values, const size_t num_values) {\n  ABSL_RAW_CHECK(num_values != 0, \"Empty input\");\n  std::sort(values, values + num_values);\n  const size_t half = num_values / 2;\n  // Odd count: return middle\n  if (num_values % 2) {\n    return values[half];\n  }\n  // Even count: return average of middle two.\n  return (values[half] + values[half - 1] + 1) / 2;\n}\n\n// Returns a robust measure of variability.\ntemplate <typename T>\nT MedianAbsoluteDeviation(const T* values, const size_t num_values,\n                          const T median) {\n  ABSL_RAW_CHECK(num_values != 0, \"Empty input\");\n  std::vector<T> abs_deviations;\n  abs_deviations.reserve(num_values);\n  for (size_t i = 0; i < num_values; ++i) {\n    const int64_t abs = std::abs(int64_t(values[i]) - int64_t(median));\n    abs_deviations.push_back(static_cast<T>(abs));\n  }\n  return Median(abs_deviations.data(), num_values);\n}\n\n}  // namespace robust_statistics\n\n// Ticks := platform-specific timer values (CPU cycles on x86). Must be\n// unsigned to guarantee wraparound on overflow. 32 bit timers are faster to\n// read than 64 bit.\nusing Ticks = uint32_t;\n\n// Returns timer overhead / minimum measurable difference.\nTicks TimerResolution() {\n  // Nested loop avoids exceeding stack/L1 capacity.\n  Ticks repetitions[Params::kTimerSamples];\n  for (size_t rep = 0; rep < Params::kTimerSamples; ++rep) {\n    Ticks samples[Params::kTimerSamples];\n    for (size_t i = 0; i < Params::kTimerSamples; ++i) {\n      const Ticks t0 = timer::Start32();\n      const Ticks t1 = timer::Stop32();\n      samples[i] = t1 - t0;\n    }\n    repetitions[rep] = robust_statistics::Mode(samples);\n  }\n  return robust_statistics::Mode(repetitions);\n}\n\nstatic const Ticks timer_resolution = TimerResolution();\n\n// Estimates the expected value of \"lambda\" values with a variable number of\n// samples until the variability \"rel_mad\" is less than \"max_rel_mad\".\ntemplate <class Lambda>\nTicks SampleUntilStable(const double max_rel_mad, double* rel_mad,\n                        const Params& p, const Lambda& lambda) {\n  auto measure_duration = [&lambda]() -> Ticks {\n    const Ticks t0 = timer::Start32();\n    lambda();\n    const Ticks t1 = timer::Stop32();\n    return t1 - t0;\n  };\n\n  // Choose initial samples_per_eval based on a single estimated duration.\n  Ticks est = measure_duration();\n  static const double ticks_per_second = InvariantTicksPerSecond();\n  const size_t ticks_per_eval = ticks_per_second * p.seconds_per_eval;\n  size_t samples_per_eval = ticks_per_eval / est;\n  samples_per_eval = (std::max)(samples_per_eval, p.min_samples_per_eval);\n\n  std::vector<Ticks> samples;\n  samples.reserve(1 + samples_per_eval);\n  samples.push_back(est);\n\n  // Percentage is too strict for tiny differences, so also allow a small\n  // absolute \"median absolute deviation\".\n  const Ticks max_abs_mad = (timer_resolution + 99) / 100;\n  *rel_mad = 0.0;  // ensure initialized\n\n  for (size_t eval = 0; eval < p.max_evals; ++eval, samples_per_eval *= 2) {\n    samples.reserve(samples.size() + samples_per_eval);\n    for (size_t i = 0; i < samples_per_eval; ++i) {\n      const Ticks r = measure_duration();\n      samples.push_back(r);\n    }\n\n    if (samples.size() >= p.min_mode_samples) {\n      est = robust_statistics::Mode(samples.data(), samples.size());\n    } else {\n      // For \"few\" (depends also on the variance) samples, Median is safer.\n      est = robust_statistics::Median(samples.data(), samples.size());\n    }\n    ABSL_RAW_CHECK(est != 0, \"Estimator returned zero duration\");\n\n    // Median absolute deviation (mad) is a robust measure of 'variability'.\n    const Ticks abs_mad = robust_statistics::MedianAbsoluteDeviation(\n        samples.data(), samples.size(), est);\n    *rel_mad = static_cast<double>(static_cast<int>(abs_mad)) / est;\n\n    if (*rel_mad <= max_rel_mad || abs_mad <= max_abs_mad) {\n      if (p.verbose) {\n        ABSL_RAW_LOG(INFO,\n                     \"%6zu samples => %5u (abs_mad=%4u, rel_mad=%4.2f%%)\\n\",\n                     samples.size(), est, abs_mad, *rel_mad * 100.0);\n      }\n      return est;\n    }\n  }\n\n  if (p.verbose) {\n    ABSL_RAW_LOG(WARNING,\n                 \"rel_mad=%4.2f%% still exceeds %4.2f%% after %6zu samples.\\n\",\n                 *rel_mad * 100.0, max_rel_mad * 100.0, samples.size());\n  }\n  return est;\n}\n\nusing InputVec = std::vector<FuncInput>;\n\n// Returns vector of unique input values.\nInputVec UniqueInputs(const FuncInput* inputs, const size_t num_inputs) {\n  InputVec unique(inputs, inputs + num_inputs);\n  std::sort(unique.begin(), unique.end());\n  unique.erase(std::unique(unique.begin(), unique.end()), unique.end());\n  return unique;\n}\n\n// Returns how often we need to call func for sufficient precision, or zero\n// on failure (e.g. the elapsed time is too long for a 32-bit tick count).\nsize_t NumSkip(const Func func, const void* arg, const InputVec& unique,\n               const Params& p) {\n  // Min elapsed ticks for any input.\n  Ticks min_duration = ~0u;\n\n  for (const FuncInput input : unique) {\n    // Make sure a 32-bit timer is sufficient.\n    const uint64_t t0 = timer::Start64();\n    PreventElision(func(arg, input));\n    const uint64_t t1 = timer::Stop64();\n    const uint64_t elapsed = t1 - t0;\n    if (elapsed >= (1ULL << 30)) {\n      ABSL_RAW_LOG(WARNING,\n                   \"Measurement failed: need 64-bit timer for input=%zu\\n\",\n                   static_cast<size_t>(input));\n      return 0;\n    }\n\n    double rel_mad;\n    const Ticks total = SampleUntilStable(\n        p.target_rel_mad, &rel_mad, p,\n        [func, arg, input]() { PreventElision(func(arg, input)); });\n    min_duration = (std::min)(min_duration, total - timer_resolution);\n  }\n\n  // Number of repetitions required to reach the target resolution.\n  const size_t max_skip = p.precision_divisor;\n  // Number of repetitions given the estimated duration.\n  const size_t num_skip =\n      min_duration == 0 ? 0 : (max_skip + min_duration - 1) / min_duration;\n  if (p.verbose) {\n    ABSL_RAW_LOG(INFO, \"res=%u max_skip=%zu min_dur=%u num_skip=%zu\\n\",\n                 timer_resolution, max_skip, min_duration, num_skip);\n  }\n  return num_skip;\n}\n\n// Replicates inputs until we can omit \"num_skip\" occurrences of an input.\nInputVec ReplicateInputs(const FuncInput* inputs, const size_t num_inputs,\n                         const size_t num_unique, const size_t num_skip,\n                         const Params& p) {\n  InputVec full;\n  if (num_unique == 1) {\n    full.assign(p.subset_ratio * num_skip, inputs[0]);\n    return full;\n  }\n\n  full.reserve(p.subset_ratio * num_skip * num_inputs);\n  for (size_t i = 0; i < p.subset_ratio * num_skip; ++i) {\n    full.insert(full.end(), inputs, inputs + num_inputs);\n  }\n  absl::random_internal::randen_engine<uint32_t> rng;\n  std::shuffle(full.begin(), full.end(), rng);\n  return full;\n}\n\n// Copies the \"full\" to \"subset\" in the same order, but with \"num_skip\"\n// randomly selected occurrences of \"input_to_skip\" removed.\nvoid FillSubset(const InputVec& full, const FuncInput input_to_skip,\n                const size_t num_skip, InputVec* subset) {\n  const size_t count = std::count(full.begin(), full.end(), input_to_skip);\n  // Generate num_skip random indices: which occurrence to skip.\n  std::vector<uint32_t> omit;\n  // Replacement for std::iota, not yet available in MSVC builds.\n  omit.reserve(count);\n  for (size_t i = 0; i < count; ++i) {\n    omit.push_back(i);\n  }\n  // omit[] is the same on every call, but that's OK because they identify the\n  // Nth instance of input_to_skip, so the position within full[] differs.\n  absl::random_internal::randen_engine<uint32_t> rng;\n  std::shuffle(omit.begin(), omit.end(), rng);\n  omit.resize(num_skip);\n  std::sort(omit.begin(), omit.end());\n\n  uint32_t occurrence = ~0u;  // 0 after preincrement\n  size_t idx_omit = 0;        // cursor within omit[]\n  size_t idx_subset = 0;      // cursor within *subset\n  for (const FuncInput next : full) {\n    if (next == input_to_skip) {\n      ++occurrence;\n      // Haven't removed enough already\n      if (idx_omit < num_skip) {\n        // This one is up for removal\n        if (occurrence == omit[idx_omit]) {\n          ++idx_omit;\n          continue;\n        }\n      }\n    }\n    if (idx_subset < subset->size()) {\n      (*subset)[idx_subset++] = next;\n    }\n  }\n  ABSL_RAW_CHECK(idx_subset == subset->size(), \"idx_subset not at end\");\n  ABSL_RAW_CHECK(idx_omit == omit.size(), \"idx_omit not at end\");\n  ABSL_RAW_CHECK(occurrence == count - 1, \"occurrence not at end\");\n}\n\n// Returns total ticks elapsed for all inputs.\nTicks TotalDuration(const Func func, const void* arg, const InputVec* inputs,\n                    const Params& p, double* max_rel_mad) {\n  double rel_mad;\n  const Ticks duration =\n      SampleUntilStable(p.target_rel_mad, &rel_mad, p, [func, arg, inputs]() {\n        for (const FuncInput input : *inputs) {\n          PreventElision(func(arg, input));\n        }\n      });\n  *max_rel_mad = (std::max)(*max_rel_mad, rel_mad);\n  return duration;\n}\n\n// (Nearly) empty Func for measuring timer overhead/resolution.\nABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE FuncOutput\nEmptyFunc(const void* arg, const FuncInput input) {\n  return input;\n}\n\n// Returns overhead of accessing inputs[] and calling a function; this will\n// be deducted from future TotalDuration return values.\nTicks Overhead(const void* arg, const InputVec* inputs, const Params& p) {\n  double rel_mad;\n  // Zero tolerance because repeatability is crucial and EmptyFunc is fast.\n  return SampleUntilStable(0.0, &rel_mad, p, [arg, inputs]() {\n    for (const FuncInput input : *inputs) {\n      PreventElision(EmptyFunc(arg, input));\n    }\n  });\n}\n\n}  // namespace\n\nvoid PinThreadToCPU(int cpu) {\n  // We might migrate to another CPU before pinning below, but at least cpu\n  // will be one of the CPUs on which this thread ran.\n#if defined(ABSL_OS_WIN)\n  if (cpu < 0) {\n    cpu = static_cast<int>(GetCurrentProcessorNumber());\n    ABSL_RAW_CHECK(cpu >= 0, \"PinThreadToCPU detect failed\");\n    if (cpu >= 64) {\n      // NOTE: On wine, at least, GetCurrentProcessorNumber() sometimes returns\n      // a value > 64, which is out of range. When this happens, log a message\n      // and don't set a cpu affinity.\n      ABSL_RAW_LOG(ERROR, \"Invalid CPU number: %d\", cpu);\n      return;\n    }\n  } else if (cpu >= 64) {\n    // User specified an explicit CPU affinity > the valid range.\n    ABSL_RAW_LOG(FATAL, \"Invalid CPU number: %d\", cpu);\n  }\n  const DWORD_PTR prev = SetThreadAffinityMask(GetCurrentThread(), 1ULL << cpu);\n  ABSL_RAW_CHECK(prev != 0, \"SetAffinity failed\");\n#elif defined(ABSL_OS_LINUX) && !defined(ABSL_OS_ANDROID)\n  if (cpu < 0) {\n    cpu = sched_getcpu();\n    ABSL_RAW_CHECK(cpu >= 0, \"PinThreadToCPU detect failed\");\n  }\n  const pid_t pid = 0;  // current thread\n  cpu_set_t set;\n  CPU_ZERO(&set);\n  CPU_SET(cpu, &set);\n  const int err = sched_setaffinity(pid, sizeof(set), &set);\n  ABSL_RAW_CHECK(err == 0, \"SetAffinity failed\");\n#endif\n}\n\n// Returns tick rate. Invariant means the tick counter frequency is independent\n// of CPU throttling or sleep. May be expensive, caller should cache the result.\ndouble InvariantTicksPerSecond() {\n#if defined(ABSL_ARCH_PPC)\n  return __ppc_get_timebase_freq();\n#elif defined(ABSL_ARCH_X86_64)\n  // We assume the TSC is invariant; it is on all recent Intel/AMD CPUs.\n  return platform::NominalClockRate();\n#else\n  // Fall back to clock_gettime nanoseconds.\n  return 1E9;\n#endif\n}\n\nsize_t MeasureImpl(const Func func, const void* arg, const size_t num_skip,\n                   const InputVec& unique, const InputVec& full,\n                   const Params& p, Result* results) {\n  const float mul = 1.0f / static_cast<int>(num_skip);\n\n  InputVec subset(full.size() - num_skip);\n  const Ticks overhead = Overhead(arg, &full, p);\n  const Ticks overhead_skip = Overhead(arg, &subset, p);\n  if (overhead < overhead_skip) {\n    ABSL_RAW_LOG(WARNING, \"Measurement failed: overhead %u < %u\\n\", overhead,\n                 overhead_skip);\n    return 0;\n  }\n\n  if (p.verbose) {\n    ABSL_RAW_LOG(INFO, \"#inputs=%5zu,%5zu overhead=%5u,%5u\\n\", full.size(),\n                 subset.size(), overhead, overhead_skip);\n  }\n\n  double max_rel_mad = 0.0;\n  const Ticks total = TotalDuration(func, arg, &full, p, &max_rel_mad);\n\n  for (size_t i = 0; i < unique.size(); ++i) {\n    FillSubset(full, unique[i], num_skip, &subset);\n    const Ticks total_skip = TotalDuration(func, arg, &subset, p, &max_rel_mad);\n\n    if (total < total_skip) {\n      ABSL_RAW_LOG(WARNING, \"Measurement failed: total %u < %u\\n\", total,\n                   total_skip);\n      return 0;\n    }\n\n    const Ticks duration = (total - overhead) - (total_skip - overhead_skip);\n    results[i].input = unique[i];\n    results[i].ticks = duration * mul;\n    results[i].variability = max_rel_mad;\n  }\n\n  return unique.size();\n}\n\nsize_t Measure(const Func func, const void* arg, const FuncInput* inputs,\n               const size_t num_inputs, Result* results, const Params& p) {\n  ABSL_RAW_CHECK(num_inputs != 0, \"No inputs\");\n\n  const InputVec unique = UniqueInputs(inputs, num_inputs);\n  const size_t num_skip = NumSkip(func, arg, unique, p);  // never 0\n  if (num_skip == 0) return 0;  // NumSkip already printed error message\n\n  const InputVec full =\n      ReplicateInputs(inputs, num_inputs, unique.size(), num_skip, p);\n\n  // MeasureImpl may fail up to p.max_measure_retries times.\n  for (size_t i = 0; i < p.max_measure_retries; i++) {\n    auto result = MeasureImpl(func, arg, num_skip, unique, full, p, results);\n    if (result != 0) {\n      return result;\n    }\n  }\n  // All retries failed. (Unusual)\n  return 0;\n}\n\n}  // namespace random_internal_nanobenchmark\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/nanobenchmark.h",
    "content": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_\n#define ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_\n\n// Benchmarks functions of a single integer argument with realistic branch\n// prediction hit rates. Uses a robust estimator to summarize the measurements.\n// The precision is about 0.2%.\n//\n// Examples: see nanobenchmark_test.cc.\n//\n// Background: Microbenchmarks such as http://github.com/google/benchmark\n// can measure elapsed times on the order of a microsecond. Shorter functions\n// are typically measured by repeating them thousands of times and dividing\n// the total elapsed time by this count. Unfortunately, repetition (especially\n// with the same input parameter!) influences the runtime. In time-critical\n// code, it is reasonable to expect warm instruction/data caches and TLBs,\n// but a perfect record of which branches will be taken is unrealistic.\n// Unless the application also repeatedly invokes the measured function with\n// the same parameter, the benchmark is measuring something very different -\n// a best-case result, almost as if the parameter were made a compile-time\n// constant. This may lead to erroneous conclusions about branch-heavy\n// algorithms outperforming branch-free alternatives.\n//\n// Our approach differs in three ways. Adding fences to the timer functions\n// reduces variability due to instruction reordering, improving the timer\n// resolution to about 40 CPU cycles. However, shorter functions must still\n// be invoked repeatedly. For more realistic branch prediction performance,\n// we vary the input parameter according to a user-specified distribution.\n// Thus, instead of VaryInputs(Measure(Repeat(func))), we change the\n// loop nesting to Measure(Repeat(VaryInputs(func))). We also estimate the\n// central tendency of the measurement samples with the \"half sample mode\",\n// which is more robust to outliers and skewed data than the mean or median.\n\n// NOTE: for compatibility with multiple translation units compiled with\n// distinct flags, avoid #including headers that define functions.\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal_nanobenchmark {\n\n// Input influencing the function being measured (e.g. number of bytes to copy).\nusing FuncInput = size_t;\n\n// \"Proof of work\" returned by Func to ensure the compiler does not elide it.\nusing FuncOutput = uint64_t;\n\n// Function to measure: either 1) a captureless lambda or function with two\n// arguments or 2) a lambda with capture, in which case the first argument\n// is reserved for use by MeasureClosure.\nusing Func = FuncOutput (*)(const void*, FuncInput);\n\n// Internal parameters that determine precision/resolution/measuring time.\nstruct Params {\n  // For measuring timer overhead/resolution. Used in a nested loop =>\n  // quadratic time, acceptable because we know timer overhead is \"low\".\n  // constexpr because this is used to define array bounds.\n  static constexpr size_t kTimerSamples = 256;\n\n  // Best-case precision, expressed as a divisor of the timer resolution.\n  // Larger => more calls to Func and higher precision.\n  size_t precision_divisor = 1024;\n\n  // Ratio between full and subset input distribution sizes. Cannot be less\n  // than 2; larger values increase measurement time but more faithfully\n  // model the given input distribution.\n  size_t subset_ratio = 2;\n\n  // Together with the estimated Func duration, determines how many times to\n  // call Func before checking the sample variability. Larger values increase\n  // measurement time, memory/cache use and precision.\n  double seconds_per_eval = 4E-3;\n\n  // The minimum number of samples before estimating the central tendency.\n  size_t min_samples_per_eval = 7;\n\n  // The mode is better than median for estimating the central tendency of\n  // skewed/fat-tailed distributions, but it requires sufficient samples\n  // relative to the width of half-ranges.\n  size_t min_mode_samples = 64;\n\n  // Maximum permissible variability (= median absolute deviation / center).\n  double target_rel_mad = 0.002;\n\n  // Abort after this many evals without reaching target_rel_mad. This\n  // prevents infinite loops.\n  size_t max_evals = 9;\n\n  // Retry the measure loop up to this many times.\n  size_t max_measure_retries = 2;\n\n  // Whether to print additional statistics to stdout.\n  bool verbose = true;\n};\n\n// Measurement result for each unique input.\nstruct Result {\n  FuncInput input;\n\n  // Robust estimate (mode or median) of duration.\n  float ticks;\n\n  // Measure of variability (median absolute deviation relative to \"ticks\").\n  float variability;\n};\n\n// Ensures the thread is running on the specified cpu, and no others.\n// Reduces noise due to desynchronized socket RDTSC and context switches.\n// If \"cpu\" is negative, pin to the currently running core.\nvoid PinThreadToCPU(const int cpu = -1);\n\n// Returns tick rate, useful for converting measurements to seconds. Invariant\n// means the tick counter frequency is independent of CPU throttling or sleep.\n// This call may be expensive, callers should cache the result.\ndouble InvariantTicksPerSecond();\n\n// Precisely measures the number of ticks elapsed when calling \"func\" with the\n// given inputs, shuffled to ensure realistic branch prediction hit rates.\n//\n// \"func\" returns a 'proof of work' to ensure its computations are not elided.\n// \"arg\" is passed to Func, or reserved for internal use by MeasureClosure.\n// \"inputs\" is an array of \"num_inputs\" (not necessarily unique) arguments to\n//   \"func\". The values should be chosen to maximize coverage of \"func\". This\n//   represents a distribution, so a value's frequency should reflect its\n//   probability in the real application. Order does not matter; for example, a\n//   uniform distribution over [0, 4) could be represented as {3,0,2,1}.\n// Returns how many Result were written to \"results\": one per unique input, or\n//   zero if the measurement failed (an error message goes to stderr).\nsize_t Measure(const Func func, const void* arg, const FuncInput* inputs,\n               const size_t num_inputs, Result* results,\n               const Params& p = Params());\n\n// Calls operator() of the given closure (lambda function).\ntemplate <class Closure>\nstatic FuncOutput CallClosure(const void* f, const FuncInput input) {\n  return (*reinterpret_cast<const Closure*>(f))(input);\n}\n\n// Same as Measure, except \"closure\" is typically a lambda function of\n// FuncInput -> FuncOutput with a capture list.\ntemplate <class Closure>\nstatic inline size_t MeasureClosure(const Closure& closure,\n                                    const FuncInput* inputs,\n                                    const size_t num_inputs, Result* results,\n                                    const Params& p = Params()) {\n  return Measure(reinterpret_cast<Func>(&CallClosure<Closure>),\n                 reinterpret_cast<const void*>(&closure), inputs, num_inputs,\n                 results, p);\n}\n\n}  // namespace random_internal_nanobenchmark\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_\n"
  },
  {
    "path": "absl/random/internal/nanobenchmark_test.cc",
    "content": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/nanobenchmark.h\"\n\n#include \"absl/log/check.h\"\n#include \"absl/log/log.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal_nanobenchmark {\nnamespace {\n\nuint64_t Div(const void*, FuncInput in) {\n  // Here we're measuring the throughput because benchmark invocations are\n  // independent.\n  const int64_t d1 = 0xFFFFFFFFFFll / int64_t(in);  // IDIV\n  return d1;\n}\n\ntemplate <size_t N>\nvoid MeasureDiv(const FuncInput (&inputs)[N]) {\n  Result results[N];\n  Params params;\n  params.max_evals = 6;  // avoid test timeout\n  const size_t num_results = Measure(&Div, nullptr, inputs, N, results, params);\n  if (num_results == 0) {\n    LOG(WARNING)\n        << \"WARNING: Measurement failed, should not happen when using \"\n           \"PinThreadToCPU unless the region to measure takes > 1 second.\";\n    return;\n  }\n  for (size_t i = 0; i < num_results; ++i) {\n    LOG(INFO) << absl::StreamFormat(\"%5u: %6.2f ticks; MAD=%4.2f%%\\n\",\n                                    results[i].input, results[i].ticks,\n                                    results[i].variability * 100.0);\n    CHECK_NE(results[i].ticks, 0.0f) << \"Zero duration\";\n  }\n}\n\nvoid RunAll(const int argc, char* argv[]) {\n  // Avoid migrating between cores - important on multi-socket systems.\n  int cpu = -1;\n  if (argc == 2) {\n    if (!absl::SimpleAtoi(argv[1], &cpu)) {\n      LOG(FATAL) << \"The optional argument must be a CPU number >= 0.\";\n    }\n  }\n  PinThreadToCPU(cpu);\n\n  // unpredictable == 1 but the compiler doesn't know that.\n  const FuncInput unpredictable = argc != 999;\n  static const FuncInput inputs[] = {unpredictable * 10, unpredictable * 100};\n\n  MeasureDiv(inputs);\n}\n\n}  // namespace\n}  // namespace random_internal_nanobenchmark\nABSL_NAMESPACE_END\n}  // namespace absl\n\nint main(int argc, char* argv[]) {\n  absl::random_internal_nanobenchmark::RunAll(argc, argv);\n  return 0;\n}\n"
  },
  {
    "path": "absl/random/internal/nonsecure_base.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_\n#define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/entropy_pool.h\"\n#include \"absl/random/internal/salted_seed_seq.h\"\n#include \"absl/random/internal/seed_material.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// RandenPoolSeedSeq is a custom seed sequence type where generate() fills the\n// provided buffer via the RandenPool entropy source.\nclass RandenPoolSeedSeq {\n private:\n  struct ContiguousTag {};\n  struct BufferTag {};\n\n  // Generate random unsigned values directly into the buffer.\n  template <typename Contiguous>\n  void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) {\n    const size_t n = static_cast<size_t>(std::distance(begin, end));\n    auto* a = &(*begin);\n    GetEntropyFromRandenPool(a, sizeof(*a) * n);\n  }\n\n  // Construct a buffer of size n and fill it with values, then copy\n  // those values into the seed iterators.\n  template <typename RandomAccessIterator>\n  void generate_impl(BufferTag, RandomAccessIterator begin,\n                     RandomAccessIterator end) {\n    const size_t n = std::distance(begin, end);\n    absl::InlinedVector<uint32_t, 8> data(n, 0);\n    GetEntropyFromRandenPool(data.begin(), sizeof(data[0]) * n);\n    std::copy(std::begin(data), std::end(data), begin);\n  }\n\n public:\n  using result_type = uint32_t;\n\n  size_t size() { return 0; }\n\n  template <typename OutIterator>\n  void param(OutIterator) const {}\n\n  template <typename RandomAccessIterator>\n  void generate(RandomAccessIterator begin, RandomAccessIterator end) {\n    // RandomAccessIterator must be assignable from uint32_t\n    if (begin != end) {\n      using U = typename std::iterator_traits<RandomAccessIterator>::value_type;\n      // ContiguousTag indicates the common case of a known contiguous buffer,\n      // which allows directly filling the buffer. In C++20,\n      // std::contiguous_iterator_tag provides a mechanism for testing this\n      // capability, however until Abseil's support requirements allow us to\n      // assume C++20, limit checks to a few common cases.\n      using TagType = absl::conditional_t<\n          (std::is_pointer<RandomAccessIterator>::value ||\n           std::is_same<RandomAccessIterator,\n                        typename std::vector<U>::iterator>::value),\n          ContiguousTag, BufferTag>;\n\n      generate_impl(TagType{}, begin, end);\n    }\n  }\n};\n\n// Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced\n// by a thread-unique URBG-instance.\ntemplate <typename URBG, typename Seeder = RandenPoolSeedSeq>\nclass NonsecureURBGBase {\n public:\n  using result_type = typename URBG::result_type;\n\n  // Default constructor\n  NonsecureURBGBase() : urbg_(ConstructURBG()) {}\n\n  // Copy disallowed, move allowed.\n  NonsecureURBGBase(const NonsecureURBGBase&) = delete;\n  NonsecureURBGBase& operator=(const NonsecureURBGBase&) = delete;\n  NonsecureURBGBase(NonsecureURBGBase&&) = default;\n  NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default;\n\n  // Constructor using a seed\n  template <class SSeq, typename = typename absl::enable_if_t<\n                            !std::is_same<SSeq, NonsecureURBGBase>::value>>\n  explicit NonsecureURBGBase(SSeq&& seq)\n      : urbg_(ConstructURBG(std::forward<SSeq>(seq))) {}\n\n  // Note: on MSVC, min() or max() can be interpreted as MIN() or MAX(), so we\n  // enclose min() or max() in parens as (min)() and (max)().\n  // Additionally, clang-format requires no space before this construction.\n\n  // NonsecureURBGBase::min()\n  static constexpr result_type(min)() { return (URBG::min)(); }\n\n  // NonsecureURBGBase::max()\n  static constexpr result_type(max)() { return (URBG::max)(); }\n\n  // NonsecureURBGBase::operator()()\n  result_type operator()() { return urbg_(); }\n\n  // NonsecureURBGBase::discard()\n  void discard(unsigned long long values) {  // NOLINT(runtime/int)\n    urbg_.discard(values);\n  }\n\n  bool operator==(const NonsecureURBGBase& other) const {\n    return urbg_ == other.urbg_;\n  }\n\n  bool operator!=(const NonsecureURBGBase& other) const {\n    return !(urbg_ == other.urbg_);\n  }\n\n private:\n  static URBG ConstructURBG() {\n    Seeder seeder;\n    return URBG(seeder);\n  }\n\n  template <typename SSeq>\n  static URBG ConstructURBG(SSeq&& seq) {  // NOLINT(runtime/references)\n    auto salted_seq =\n        random_internal::MakeSaltedSeedSeq(std::forward<SSeq>(seq));\n    return URBG(salted_seq);\n  }\n\n  URBG urbg_;\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_\n"
  },
  {
    "path": "absl/random/internal/nonsecure_base_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/nonsecure_base.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <thread>  // NOLINT\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/container/flat_hash_set.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/random.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace {\n\nusing ExampleNonsecureURBG =\n    absl::random_internal::NonsecureURBGBase<std::mt19937>;\n\ntemplate <typename T>\nvoid Use(const T&) {}\n\n}  // namespace\n\nTEST(NonsecureURBGBase, DefaultConstructorIsValid) {\n  ExampleNonsecureURBG urbg;\n}\n\n// Ensure that the recommended template-instantiations are valid.\nTEST(RecommendedTemplates, CanBeConstructed) {\n  absl::BitGen default_generator;\n  absl::InsecureBitGen insecure_generator;\n}\n\nTEST(RecommendedTemplates, CanDiscardValues) {\n  absl::BitGen default_generator;\n  absl::InsecureBitGen insecure_generator;\n\n  default_generator.discard(5);\n  insecure_generator.discard(5);\n}\n\nTEST(NonsecureURBGBase, StandardInterface) {\n  // Names after definition of [rand.req.urbg] in C++ standard.\n  // e us a value of E\n  // v is a lvalue of E\n  // x, y are possibly const values of E\n  // s is a value of T\n  // q is a value satisfying requirements of seed_sequence\n  // z is a value of type unsigned long long\n  // os is a some specialization of basic_ostream\n  // is is a some specialization of basic_istream\n\n  using E = absl::random_internal::NonsecureURBGBase<std::minstd_rand>;\n\n  using T = typename E::result_type;\n\n  static_assert(!std::is_copy_constructible<E>::value,\n                \"NonsecureURBGBase should not be copy constructible\");\n\n  static_assert(!absl::is_copy_assignable<E>::value,\n                \"NonsecureURBGBase should not be copy assignable\");\n\n  static_assert(std::is_move_constructible<E>::value,\n                \"NonsecureURBGBase should be move constructible\");\n\n  static_assert(absl::is_move_assignable<E>::value,\n                \"NonsecureURBGBase should be move assignable\");\n\n  static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,\n                \"return type of operator() must be result_type\");\n\n  {\n    const E x, y;\n    Use(x);\n    Use(y);\n\n    static_assert(std::is_same<decltype(x == y), bool>::value,\n                  \"return type of operator== must be bool\");\n\n    static_assert(std::is_same<decltype(x != y), bool>::value,\n                  \"return type of operator== must be bool\");\n  }\n\n  E e;\n  std::seed_seq q{1, 2, 3};\n\n  E{};\n  E{q};\n\n  // Copy constructor not supported.\n  // E{x};\n\n  // result_type seed constructor not supported.\n  // E{T{1}};\n\n  // Move constructors are supported.\n  {\n    E tmp(q);\n    E m = std::move(tmp);\n    E n(std::move(m));\n    EXPECT_TRUE(e != n);\n  }\n\n  // Comparisons work.\n  {\n    // MSVC emits error 2718 when using EXPECT_EQ(e, x)\n    //  * actual parameter with __declspec(align('#')) won't be aligned\n    E a(q);\n    E b(q);\n\n    EXPECT_TRUE(a != e);\n    EXPECT_TRUE(a == b);\n\n    a();\n    EXPECT_TRUE(a != b);\n  }\n\n  // e.seed(s) not supported.\n\n  // [rand.req.eng] specifies the parameter as 'unsigned long long'\n  // e.discard(unsigned long long) is supported.\n  unsigned long long z = 1;  // NOLINT(runtime/int)\n  e.discard(z);\n}\n\nTEST(NonsecureURBGBase, SeedSeqConstructorIsValid) {\n  std::seed_seq seq;\n  ExampleNonsecureURBG rbg(seq);\n}\n\nTEST(NonsecureURBGBase, CompatibleWithDistributionUtils) {\n  ExampleNonsecureURBG rbg;\n\n  absl::Uniform(rbg, 0, 100);\n  absl::Uniform(rbg, 0.5, 0.7);\n  absl::Poisson<uint32_t>(rbg);\n  absl::Exponential<float>(rbg);\n}\n\nTEST(NonsecureURBGBase, CompatibleWithStdDistributions) {\n  ExampleNonsecureURBG rbg;\n\n  // Cast to void to suppress [[nodiscard]] warnings\n  static_cast<void>(std::uniform_int_distribution<uint32_t>(0, 100)(rbg));\n  static_cast<void>(std::uniform_real_distribution<float>()(rbg));\n  static_cast<void>(std::bernoulli_distribution(0.2)(rbg));\n}\n\nTEST(NonsecureURBGBase, ConsecutiveDefaultInstancesYieldUniqueVariates) {\n  const size_t kNumSamples = 128;\n\n  ExampleNonsecureURBG rbg1;\n  ExampleNonsecureURBG rbg2;\n\n  for (size_t i = 0; i < kNumSamples; i++) {\n    EXPECT_NE(rbg1(), rbg2());\n  }\n}\n\nTEST(NonsecureURBGBase, EqualSeedSequencesYieldEqualVariates) {\n  std::seed_seq seq;\n\n  ExampleNonsecureURBG rbg1(seq);\n  ExampleNonsecureURBG rbg2(seq);\n\n  // ExampleNonsecureURBG rbg3({1, 2, 3});  // Should not compile.\n\n  for (uint32_t i = 0; i < 1000; i++) {\n    EXPECT_EQ(rbg1(), rbg2());\n  }\n\n  rbg1.discard(100);\n  rbg2.discard(100);\n\n  // The sequences should continue after discarding\n  for (uint32_t i = 0; i < 1000; i++) {\n    EXPECT_EQ(rbg1(), rbg2());\n  }\n}\n\nTEST(NonsecureURBGBase, DistinctSequencesPerThread) {\n  constexpr int kNumThreads = 12;\n  constexpr size_t kValuesPerThread = 32;\n  using result_type = absl::BitGen::result_type;\n\n  // Acquire initial sequences from multiple threads.\n  std::vector<std::vector<result_type>> data;\n  {\n    absl::Mutex mu;\n    std::vector<std::thread> threads;\n    for (int i = 0; i < kNumThreads; i++) {\n      threads.emplace_back([&]() {\n        absl::BitGen gen;\n\n        std::vector<result_type> v(kValuesPerThread);\n        std::generate(v.begin(), v.end(), [&]() { return gen(); });\n        absl::MutexLock l(mu);\n        data.push_back(std::move(v));\n      });\n    }\n    for (auto& t : threads) t.join();\n  }\n\n  EXPECT_EQ(data.size(), kNumThreads);\n\n  // There should be essentially no duplicates in the sequences.\n  size_t expected_size = 0;\n  absl::flat_hash_set<result_type> seen;\n  for (const auto& v : data) {\n    expected_size += v.size();\n    for (result_type x : v) seen.insert(x);\n  }\n  EXPECT_GE(seen.size(), expected_size - 1);\n}\n\nTEST(RandenPoolSeedSeqTest, SeederWorksForU32) {\n  absl::random_internal::RandenPoolSeedSeq seeder;\n\n  uint32_t state[2] = {0, 0};\n  seeder.generate(std::begin(state), std::end(state));\n  EXPECT_FALSE(state[0] == 0 && state[1] == 0);\n}\n\nTEST(RandenPoolSeedSeqTest, SeederWorksForU64) {\n  absl::random_internal::RandenPoolSeedSeq seeder;\n\n  uint64_t state[2] = {0, 0};\n  seeder.generate(std::begin(state), std::end(state));\n  EXPECT_FALSE(state[0] == 0 && state[1] == 0);\n  EXPECT_FALSE((state[0] >> 32) == 0 && (state[1] >> 32) == 0);\n}\n\nTEST(RandenPoolSeedSeqTest, SeederWorksForS32) {\n  absl::random_internal::RandenPoolSeedSeq seeder;\n\n  int32_t state[2] = {0, 0};\n  seeder.generate(std::begin(state), std::end(state));\n  EXPECT_FALSE(state[0] == 0 && state[1] == 0);\n}\n\nTEST(RandenPoolSeedSeqTest, SeederWorksForVector) {\n  absl::random_internal::RandenPoolSeedSeq seeder;\n\n  std::vector<uint32_t> state(2);\n  seeder.generate(std::begin(state), std::end(state));\n  EXPECT_FALSE(state[0] == 0 && state[1] == 0);\n}\n"
  },
  {
    "path": "absl/random/internal/pcg_engine.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_\n#define ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_\n\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/internal/fastmath.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in\n// C++.  PCG combines a linear congruential generator (LCG) with output state\n// mixing functions to generate each random variate.  pcg_engine supports only a\n// single sequence (oneseq), and does not support streams.\n//\n// pcg_engine is parameterized by two types:\n//   Params, which provides the multiplier and increment values;\n//   Mix, which mixes the state into the result.\n//\ntemplate <typename Params, typename Mix>\nclass pcg_engine {\n  static_assert(std::is_same<typename Params::state_type,\n                             typename Mix::state_type>::value,\n                \"Class-template absl::pcg_engine must be parameterized by \"\n                \"Params and Mix with identical state_type\");\n\n  static_assert(std::is_unsigned<typename Mix::result_type>::value,\n                \"Class-template absl::pcg_engine must be parameterized by \"\n                \"an unsigned Mix::result_type\");\n\n  using params_type = Params;\n  using mix_type = Mix;\n  using state_type = typename Mix::state_type;\n\n public:\n  // C++11 URBG interface:\n  using result_type = typename Mix::result_type;\n\n  static constexpr result_type(min)() {\n    return (std::numeric_limits<result_type>::min)();\n  }\n\n  static constexpr result_type(max)() {\n    return (std::numeric_limits<result_type>::max)();\n  }\n\n  explicit pcg_engine(uint64_t seed_value = 0) { seed(seed_value); }\n\n  template <class SeedSequence,\n            typename = typename absl::enable_if_t<\n                !std::is_same<SeedSequence, pcg_engine>::value>>\n  explicit pcg_engine(SeedSequence&& seq) {\n    seed(seq);\n  }\n\n  pcg_engine(const pcg_engine&) = default;\n  pcg_engine& operator=(const pcg_engine&) = default;\n  pcg_engine(pcg_engine&&) = default;\n  pcg_engine& operator=(pcg_engine&&) = default;\n\n  result_type operator()() {\n    // Advance the LCG state, always using the new value to generate the output.\n    state_ = lcg(state_);\n    return Mix{}(state_);\n  }\n\n  void seed(uint64_t seed_value = 0) {\n    state_type tmp = seed_value;\n    state_ = lcg(tmp + Params::increment());\n  }\n\n  template <class SeedSequence>\n  typename absl::enable_if_t<\n      !std::is_convertible<SeedSequence, uint64_t>::value, void>\n  seed(SeedSequence&& seq) {\n    reseed(seq);\n  }\n\n  void discard(uint64_t count) { state_ = advance(state_, count); }\n\n  bool operator==(const pcg_engine& other) const {\n    return state_ == other.state_;\n  }\n\n  bool operator!=(const pcg_engine& other) const { return !(*this == other); }\n\n  template <class CharT, class Traits>\n  friend typename absl::enable_if_t<(sizeof(state_type) == 16),\n                                    std::basic_ostream<CharT, Traits>&>\n  operator<<(\n      std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n      const pcg_engine& engine) {\n    auto saver = random_internal::make_ostream_state_saver(os);\n    random_internal::stream_u128_helper<state_type> helper;\n    helper.write(pcg_engine::params_type::multiplier(), os);\n    os << os.fill();\n    helper.write(pcg_engine::params_type::increment(), os);\n    os << os.fill();\n    helper.write(engine.state_, os);\n    return os;\n  }\n\n  template <class CharT, class Traits>\n  friend typename absl::enable_if_t<(sizeof(state_type) <= 8),\n                                    std::basic_ostream<CharT, Traits>&>\n  operator<<(\n      std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n      const pcg_engine& engine) {\n    auto saver = random_internal::make_ostream_state_saver(os);\n    os << pcg_engine::params_type::multiplier() << os.fill();\n    os << pcg_engine::params_type::increment() << os.fill();\n    os << engine.state_;\n    return os;\n  }\n\n  template <class CharT, class Traits>\n  friend typename absl::enable_if_t<(sizeof(state_type) == 16),\n                                    std::basic_istream<CharT, Traits>&>\n  operator>>(\n      std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n      pcg_engine& engine) {                   // NOLINT(runtime/references)\n    random_internal::stream_u128_helper<state_type> helper;\n    auto mult = helper.read(is);\n    auto inc = helper.read(is);\n    auto tmp = helper.read(is);\n    if (mult != pcg_engine::params_type::multiplier() ||\n        inc != pcg_engine::params_type::increment()) {\n      // signal failure by setting the failbit.\n      is.setstate(is.rdstate() | std::ios_base::failbit);\n    }\n    if (!is.fail()) {\n      engine.state_ = tmp;\n    }\n    return is;\n  }\n\n  template <class CharT, class Traits>\n  friend typename absl::enable_if_t<(sizeof(state_type) <= 8),\n                                    std::basic_istream<CharT, Traits>&>\n  operator>>(\n      std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n      pcg_engine& engine) {                   // NOLINT(runtime/references)\n    state_type mult{}, inc{}, tmp{};\n    is >> mult >> inc >> tmp;\n    if (mult != pcg_engine::params_type::multiplier() ||\n        inc != pcg_engine::params_type::increment()) {\n      // signal failure by setting the failbit.\n      is.setstate(is.rdstate() | std::ios_base::failbit);\n    }\n    if (!is.fail()) {\n      engine.state_ = tmp;\n    }\n    return is;\n  }\n\n private:\n  state_type state_;\n\n  // Returns the linear-congruential generator next state.\n  static inline constexpr state_type lcg(state_type s) {\n    return s * Params::multiplier() + Params::increment();\n  }\n\n  // Returns the linear-congruential arbitrary seek state.\n  inline state_type advance(state_type s, uint64_t n) const {\n    state_type mult = Params::multiplier();\n    state_type inc = Params::increment();\n    state_type m = 1;\n    state_type i = 0;\n    while (n > 0) {\n      if (n & 1) {\n        m *= mult;\n        i = i * mult + inc;\n      }\n      inc = (mult + 1) * inc;\n      mult *= mult;\n      n >>= 1;\n    }\n    return m * s + i;\n  }\n\n  template <class SeedSequence>\n  void reseed(SeedSequence& seq) {\n    using sequence_result_type = typename SeedSequence::result_type;\n    constexpr size_t kBufferSize =\n        sizeof(state_type) / sizeof(sequence_result_type);\n    sequence_result_type buffer[kBufferSize];\n    seq.generate(std::begin(buffer), std::end(buffer));\n    // Convert the seed output to a single state value.\n    state_type tmp = buffer[0];\n    for (size_t i = 1; i < kBufferSize; i++) {\n      tmp <<= (sizeof(sequence_result_type) * 8);\n      tmp |= buffer[i];\n    }\n    state_ = lcg(tmp + params_type::increment());\n  }\n};\n\n// Parameterized implementation of the PCG 128-bit oneseq state.\n// This provides state_type, multiplier, and increment for pcg_engine.\ntemplate <uint64_t kMultA, uint64_t kMultB, uint64_t kIncA, uint64_t kIncB>\nclass pcg128_params {\n public:\n  using state_type = absl::uint128;\n  static inline constexpr state_type multiplier() {\n    return absl::MakeUint128(kMultA, kMultB);\n  }\n  static inline constexpr state_type increment() {\n    return absl::MakeUint128(kIncA, kIncB);\n  }\n};\n\n// Implementation of the PCG xsl_rr_128_64 128-bit mixing function, which\n// accepts an input of state_type and mixes it into an output of result_type.\nstruct pcg_xsl_rr_128_64 {\n  using state_type = absl::uint128;\n  using result_type = uint64_t;\n\n  inline uint64_t operator()(state_type state) {\n    // This is equivalent to the xsl_rr_128_64 mixing function.\n    uint64_t rotate = static_cast<uint64_t>(state >> 122u);\n    state ^= state >> 64;\n    uint64_t s = static_cast<uint64_t>(state);\n    return rotr(s, static_cast<int>(rotate));\n  }\n};\n\n// Parameterized implementation of the PCG 64-bit oneseq state.\n// This provides state_type, multiplier, and increment for pcg_engine.\ntemplate <uint64_t kMult, uint64_t kInc>\nclass pcg64_params {\n public:\n  using state_type = uint64_t;\n  static inline constexpr state_type multiplier() { return kMult; }\n  static inline constexpr state_type increment() { return kInc; }\n};\n\n// Implementation of the PCG xsh_rr_64_32 64-bit mixing function, which accepts\n// an input of state_type and mixes it into an output of result_type.\nstruct pcg_xsh_rr_64_32 {\n  using state_type = uint64_t;\n  using result_type = uint32_t;\n  inline uint32_t operator()(uint64_t state) {\n    return rotr(static_cast<uint32_t>(((state >> 18) ^ state) >> 27),\n                state >> 59);\n  }\n};\n\n// Stable pcg_engine implementations:\n// This is a 64-bit generator using 128-bits of state.\n// The output sequence is equivalent to Melissa O'Neil's pcg64_oneseq.\nusing pcg64_2018_engine = pcg_engine<\n    random_internal::pcg128_params<0x2360ed051fc65da4ull, 0x4385df649fccf645ull,\n                                   0x5851f42d4c957f2d, 0x14057b7ef767814f>,\n    random_internal::pcg_xsl_rr_128_64>;\n\n// This is a 32-bit generator using 64-bits of state.\n// This is equivalent to Melissa O'Neil's pcg32_oneseq.\nusing pcg32_2018_engine = pcg_engine<\n    random_internal::pcg64_params<0x5851f42d4c957f2dull, 0x14057b7ef767814full>,\n    random_internal::pcg_xsh_rr_64_32>;\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_\n"
  },
  {
    "path": "absl/random/internal/pcg_engine_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/pcg_engine.h\"\n\n#include <algorithm>\n#include <bitset>\n#include <random>\n#include <sstream>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/internal/explicit_seed_seq.h\"\n#include \"absl/time/clock.h\"\n\n#define UPDATE_GOLDEN 0\n\nnamespace {\n\nusing absl::random_internal::ExplicitSeedSeq;\nusing absl::random_internal::pcg32_2018_engine;\nusing absl::random_internal::pcg64_2018_engine;\n\ntemplate <typename EngineType>\nclass PCGEngineTest : public ::testing::Test {};\n\nusing EngineTypes = ::testing::Types<pcg64_2018_engine, pcg32_2018_engine>;\n\nTYPED_TEST_SUITE(PCGEngineTest, EngineTypes);\n\nTYPED_TEST(PCGEngineTest, VerifyReseedChangesAllValues) {\n  using engine_type = TypeParam;\n  using result_type = typename engine_type::result_type;\n\n  const size_t kNumOutputs = 16;\n  engine_type engine;\n\n  // MSVC emits error 2719 without the use of std::ref below.\n  //  * formal parameter with __declspec(align('#')) won't be aligned\n\n  {\n    std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7};\n    engine.seed(seq1);\n  }\n  result_type a[kNumOutputs];\n  std::generate(std::begin(a), std::end(a), std::ref(engine));\n\n  {\n    std::random_device rd;\n    std::seed_seq seq2{rd(), rd(), rd()};\n    engine.seed(seq2);\n  }\n  result_type b[kNumOutputs];\n  std::generate(std::begin(b), std::end(b), std::ref(engine));\n\n  // Verify that two uncorrelated values have ~50% of there bits in common. Use\n  // a 10% margin-of-error to reduce flakiness.\n  size_t changed_bits = 0;\n  size_t unchanged_bits = 0;\n  size_t total_set = 0;\n  size_t total_bits = 0;\n  size_t equal_count = 0;\n  for (size_t i = 0; i < kNumOutputs; ++i) {\n    equal_count += (a[i] == b[i]) ? 1 : 0;\n    std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);\n    changed_bits += bitset.count();\n    unchanged_bits += bitset.size() - bitset.count();\n\n    std::bitset<sizeof(result_type) * 8> a_set(a[i]);\n    std::bitset<sizeof(result_type) * 8> b_set(b[i]);\n    total_set += a_set.count() + b_set.count();\n    total_bits += 2 * 8 * sizeof(result_type);\n  }\n  // On average, half the bits are changed between two calls.\n  EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));\n  EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));\n\n  // verify using a quick normal-approximation to the binomial.\n  EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))\n      << \"@\" << total_set / static_cast<double>(total_bits);\n\n  // Also, A[i] == B[i] with probability (1/range) * N.\n  // Give this a pretty wide latitude, though.\n  const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);\n  EXPECT_LE(equal_count, 1.0 + kExpected);\n}\n\n// Number of values that needs to be consumed to clean two sizes of buffer\n// and trigger third refresh. (slightly overestimates the actual state size).\nconstexpr size_t kTwoBufferValues = 16;\n\nTYPED_TEST(PCGEngineTest, VerifyDiscard) {\n  using engine_type = TypeParam;\n\n  for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) {\n    engine_type engine_used;\n    for (size_t i = 0; i < num_used; ++i) {\n      engine_used();\n    }\n\n    for (size_t num_discard = 0; num_discard < kTwoBufferValues;\n         ++num_discard) {\n      engine_type engine1 = engine_used;\n      engine_type engine2 = engine_used;\n      for (size_t i = 0; i < num_discard; ++i) {\n        engine1();\n      }\n      engine2.discard(num_discard);\n      for (size_t i = 0; i < kTwoBufferValues; ++i) {\n        const auto r1 = engine1();\n        const auto r2 = engine2();\n        ASSERT_EQ(r1, r2) << \"used=\" << num_used << \" discard=\" << num_discard;\n      }\n    }\n  }\n}\n\nTYPED_TEST(PCGEngineTest, StreamOperatorsResult) {\n  using engine_type = TypeParam;\n\n  std::wostringstream os;\n  std::wistringstream is;\n  engine_type engine;\n\n  EXPECT_EQ(&(os << engine), &os);\n  EXPECT_EQ(&(is >> engine), &is);\n}\n\nTYPED_TEST(PCGEngineTest, StreamSerialization) {\n  using engine_type = TypeParam;\n\n  for (size_t discard = 0; discard < kTwoBufferValues; ++discard) {\n    ExplicitSeedSeq seed_sequence{12, 34, 56};\n    engine_type engine(seed_sequence);\n    engine.discard(discard);\n\n    std::stringstream stream;\n    stream << engine;\n\n    engine_type new_engine;\n    stream >> new_engine;\n    for (size_t i = 0; i < 64; ++i) {\n      EXPECT_EQ(engine(), new_engine()) << \" \" << i;\n    }\n  }\n}\n\nconstexpr size_t kNumGoldenOutputs = 127;\n\n// This test is checking if randen_engine is meets interface requirements\n// defined in [rand.req.urbg].\nTYPED_TEST(PCGEngineTest, RandomNumberEngineInterface) {\n  using engine_type = TypeParam;\n\n  using E = engine_type;\n  using T = typename E::result_type;\n\n  static_assert(std::is_copy_constructible<E>::value,\n                \"engine_type must be copy constructible\");\n\n  static_assert(absl::is_copy_assignable<E>::value,\n                \"engine_type must be copy assignable\");\n\n  static_assert(std::is_move_constructible<E>::value,\n                \"engine_type must be move constructible\");\n\n  static_assert(absl::is_move_assignable<E>::value,\n                \"engine_type must be move assignable\");\n\n  static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,\n                \"return type of operator() must be result_type\");\n\n  // Names after definition of [rand.req.urbg] in C++ standard.\n  // e us a value of E\n  // v is a lvalue of E\n  // x, y are possibly const values of E\n  // s is a value of T\n  // q is a value satisfying requirements of seed_sequence\n  // z is a value of type unsigned long long\n  // os is a some specialization of basic_ostream\n  // is is a some specialization of basic_istream\n\n  E e, v;\n  const E x, y;\n  T s = 1;\n  std::seed_seq q{1, 2, 3};\n  unsigned long long z = 1;  // NOLINT(runtime/int)\n  std::wostringstream os;\n  std::wistringstream is;\n\n  E{};\n  E{x};\n  E{s};\n  E{q};\n\n  e.seed();\n\n  // MSVC emits error 2718 when using EXPECT_EQ(e, x)\n  //  * actual parameter with __declspec(align('#')) won't be aligned\n  EXPECT_TRUE(e == x);\n\n  e.seed(q);\n  {\n    E tmp(q);\n    EXPECT_TRUE(e == tmp);\n  }\n\n  e();\n  {\n    E tmp(q);\n    EXPECT_TRUE(e != tmp);\n  }\n\n  e.discard(z);\n\n  static_assert(std::is_same<decltype(x == y), bool>::value,\n                \"return type of operator== must be bool\");\n\n  static_assert(std::is_same<decltype(x != y), bool>::value,\n                \"return type of operator== must be bool\");\n}\n\nTYPED_TEST(PCGEngineTest, RandenEngineSFINAETest) {\n  using engine_type = TypeParam;\n  using result_type = typename engine_type::result_type;\n\n  {\n    engine_type engine(result_type(1));\n    engine.seed(result_type(1));\n  }\n\n  {\n    result_type n = 1;\n    engine_type engine(n);\n    engine.seed(n);\n  }\n\n  {\n    engine_type engine(1);\n    engine.seed(1);\n  }\n\n  {\n    int n = 1;\n    engine_type engine(n);\n    engine.seed(n);\n  }\n\n  {\n    std::seed_seq seed_seq;\n    engine_type engine(seed_seq);\n    engine.seed(seed_seq);\n  }\n\n  {\n    engine_type engine{std::seed_seq()};\n    engine.seed(std::seed_seq());\n  }\n}\n\n// ------------------------------------------------------------------\n// Stability tests for pcg64_2018_engine\n// ------------------------------------------------------------------\nTEST(PCG642018EngineTest, VerifyGolden) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0x01070196e695f8f1, 0x703ec840c59f4493, 0xe54954914b3a44fa,\n      0x96130ff204b9285e, 0x7d9fdef535ceb21a, 0x666feed42e1219a0,\n      0x981f685721c8326f, 0xad80710d6eab4dda, 0xe202c480b037a029,\n      0x5d3390eaedd907e2, 0x0756befb39c6b8aa, 0x1fb44ba6634d62a3,\n      0x8d20423662426642, 0x34ea910167a39fb4, 0x93010b43a80d0ab6,\n      0x663db08a98fc568a, 0x720b0a1335956fae, 0x2c35483e31e1d3ba,\n      0x429f39776337409d, 0xb46d99e638687344, 0x105370b96aedcaee,\n      0x3999e92f811cff71, 0xd230f8bcb591cfc9, 0x0dce3db2ba7bdea5,\n      0xcf2f52c91eec99af, 0x2bc7c24a8b998a39, 0xbd8af1b0d599a19c,\n      0x56bc45abc66059f5, 0x170a46dc170f7f1e, 0xc25daf5277b85fad,\n      0xe629c2e0c948eadb, 0x1720a796915542ed, 0x22fb0caa4f909951,\n      0x7e0c0f4175acd83d, 0xd9fcab37ff2a860c, 0xab2280fb2054bad1,\n      0x58e8a06f37fa9e99, 0xc3a52a30b06528c7, 0x0175f773a13fc1bd,\n      0x731cfc584b00e840, 0x404cc7b2648069cb, 0x5bc29153b0b7f783,\n      0x771310a38cc999d1, 0x766a572f0a71a916, 0x90f450fb4fc48348,\n      0xf080ea3e1c7b1a0d, 0x15471a4507d66a44, 0x7d58e55a78f3df69,\n      0x0130a094576ac99c, 0x46669cb2d04b1d87, 0x17ab5bed20191840,\n      0x95b177d260adff3e, 0x025fb624b6ee4c07, 0xb35de4330154a95f,\n      0xe8510fff67e24c79, 0x132c3cbcd76ed2d3, 0x35e7cc145a093904,\n      0x9f5b5b5f81583b79, 0x3ee749a533966233, 0x4af85886cdeda8cd,\n      0x0ca5380ecb3ef3aa, 0x4f674eb7661d3192, 0x88a29aad00cd7733,\n      0x70b627ca045ffac6, 0x5912b43ea887623d, 0x95dc9fc6f62cf221,\n      0x926081a12a5c905b, 0x9c57d4cd7dfce651, 0x85ab2cbf23e3bb5d,\n      0xc5cd669f63023152, 0x3067be0fad5d898e, 0x12b56f444cb53d05,\n      0xbc2e5a640c3434fc, 0x9280bff0e4613fe1, 0x98819094c528743e,\n      0x999d1c98d829df33, 0x9ff82a012dc89242, 0xf99183ed39c8be94,\n      0xf0f59161cd421c55, 0x3c705730c2f6c48d, 0x66ad85c6e9278a61,\n      0x2a3428e4a428d5d0, 0x79207d68fd04940d, 0xea7f2b402edc8430,\n      0xa06b419ac857f63b, 0xcb1dd0e6fbc47e1c, 0x4f55229200ada6a4,\n      0x9647b5e6359c927f, 0x30bf8f9197c7efe5, 0xa79519529cc384d0,\n      0xbb22c4f339ad6497, 0xd7b9782f59d14175, 0x0dff12fff2ec0118,\n      0xa331ad8305343a7c, 0x48dad7e3f17e0862, 0x324c6fb3fd3c9665,\n      0xf0e4350e7933dfc4, 0x7ccda2f30b8b03b6, 0xa0afc6179005de40,\n      0xee65da6d063b3a30, 0xb9506f42f2bfe87a, 0xc9a2e26b0ef5baa0,\n      0x39fa9d4f495011d6, 0xbecc21a45d023948, 0x6bf484c6593f737f,\n      0x8065e0070cadc3b7, 0x9ef617ed8d419799, 0xac692cf8c233dd15,\n      0xd2ed87583c4ebb98, 0xad95ba1bebfedc62, 0x9b60b160a8264e43,\n      0x0bc8c45f71fcf25b, 0x4a78035cdf1c9931, 0x4602dc106667e029,\n      0xb335a3c250498ac8, 0x0256ebc4df20cab8, 0x0c61efd153f0c8d9,\n      0xe5d0150a4f806f88, 0x99d6521d351e7d87, 0x8d4888c9f80f4325,\n      0x106c5735c1ba868d, 0x73414881b880a878, 0x808a9a58a3064751,\n      0x339a29f3746de3d5, 0x5410d7fa4f873896, 0xd84623c81d7b8a03,\n      0x1f7c7e7a7f47f462,\n  };\n\n  pcg64_2018_engine engine(0);\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%016lx, \", engine());\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed();\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(PCG642018EngineTest, VerifyGoldenSeeded) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0xb03988f1e39691ee, 0xbd2a1eb5ac31e97a, 0x8f00d6d433634d02,\n      0x1823c28d483d5776, 0x000c3ee3e1aeb74a, 0xfa82ef27a4f3df9c,\n      0xc6f382308654e454, 0x414afb1a238996c2, 0x4703a4bc252eb411,\n      0x99d64f62c8f7f654, 0xbb07ebe11a34fa44, 0x79eb06a363c06131,\n      0xf66ad3756f1c6b21, 0x130c01d5e869f457, 0x5ca2b9963aecbc81,\n      0xfef7bebc1de27e6c, 0x1d174faa5ed2cdbf, 0xd75b7a773f2bb889,\n      0xc35c872327a170a5, 0x46da6d88646a42fe, 0x4622985e0442dae2,\n      0xbe3cbd67297f1f9b, 0xe7c37b4a4798bfd1, 0x173d5dfad15a25c3,\n      0x0eb6849ba2961522, 0xb0ff7246e6700d73, 0x88cb9c42d3afa577,\n      0xb609731dbd94d917, 0xd3941cda04b40081, 0x28d140f7409bea3a,\n      0x3c96699a920a124a, 0xdb28be521958b2fd, 0x0a3f44db3d4c5124,\n      0x7ac8e60ba13b70d2, 0x75f03a41ded5195a, 0xaed10ac7c4e4825d,\n      0xb92a3b18aadb7adc, 0xda45e0081f2bca46, 0x74d39ab3753143fc,\n      0xb686038018fac9ca, 0x4cc309fe99542dbb, 0xf3e1a4fcb311097c,\n      0x58763d6fa698d69d, 0xd11c365dbecd8d60, 0x2c15d55725b1dee7,\n      0x89805f254d85658c, 0x2374c44dfc62158b, 0x9a8350fa7995328d,\n      0x198f838970cf91da, 0x96aff569562c0e53, 0xd76c8c52b7ec6e3f,\n      0x23a01cd9ae4baa81, 0x3adb366b6d02a893, 0xb3313e2a4c5b333f,\n      0x04c11230b96a5425, 0x1f7f7af04787d571, 0xaddb019365275ec7,\n      0x5c960468ccb09f42, 0x8438db698c69a44a, 0x492be1e46111637e,\n      0x9c6c01e18100c610, 0xbfe48e75b7d0aceb, 0xb5e0b89ec1ce6a00,\n      0x9d280ecbc2fe8997, 0x290d9e991ba5fcab, 0xeec5bec7d9d2a4f0,\n      0x726e81488f19150e, 0x1a6df7955a7e462c, 0x37a12d174ba46bb5,\n      0x3cdcdffd96b1b5c5, 0x2c5d5ac10661a26e, 0xa742ed18f22e50c4,\n      0x00e0ed88ff0d8a35, 0x3d3c1718cb1efc0b, 0x1d70c51ffbccbf11,\n      0xfbbb895132a4092f, 0x619d27f2fb095f24, 0x69af68200985e5c4,\n      0xbee4885f57373f8d, 0x10b7a6bfe0587e40, 0xa885e6cf2f7e5f0a,\n      0x59f879464f767550, 0x24e805d69056990d, 0x860970b911095891,\n      0xca3189954f84170d, 0x6652a5edd4590134, 0x5e1008cef76174bf,\n      0xcbd417881f2bcfe5, 0xfd49fc9d706ecd17, 0xeebf540221ebd066,\n      0x46af7679464504cb, 0xd4028486946956f1, 0xd4f41864b86c2103,\n      0x7af090e751583372, 0x98cdaa09278cb642, 0xffd42b921215602f,\n      0x1d05bec8466b1740, 0xf036fa78a0132044, 0x787880589d1ecc78,\n      0x5644552cfef33230, 0x0a97e275fe06884b, 0x96d1b13333d470b5,\n      0xc8b3cdad52d3b034, 0x091357b9db7376fd, 0xa5fe4232555edf8c,\n      0x3371bc3b6ada76b5, 0x7deeb2300477c995, 0x6fc6d4244f2849c1,\n      0x750e8cc797ca340a, 0x81728613cd79899f, 0x3467f4ee6f9aeb93,\n      0x5ef0a905f58c640f, 0x432db85e5101c98a, 0x6488e96f46ac80c2,\n      0x22fddb282625048c, 0x15b287a0bc2d4c5d, 0xa7e2343ef1f28bce,\n      0xc87ee1aa89bed09e, 0x220610107812c5e9, 0xcbdab6fcd640f586,\n      0x8d41047970928784, 0x1aa431509ec1ade0, 0xac3f0be53f518ddc,\n      0x16f4428ad81d0cbb, 0x675b13c2736fc4bb, 0x6db073afdd87e32d,\n      0x572f3ca2f1a078c6,\n  };\n\n  ExplicitSeedSeq seed_sequence{12, 34, 56};\n  pcg64_2018_engine engine(seed_sequence);\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%016lx, \", engine());\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed(seed_sequence);\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(PCG642018EngineTest, VerifyGoldenFromDeserializedEngine) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0xdd425b47b4113dea, 0x1b07176479d444b0, 0x6b391027586f2e42,\n      0xa166f2b15f4a2143, 0xffb6dbd7a179ee97, 0xb2c00035365bf0b1,\n      0x8fbb518b45855521, 0xfc789a55ddf87c3b, 0x429531f0f17ff355,\n      0xbe708560d603d283, 0x5bff415175c5cb6b, 0xe813491f4ad45394,\n      0xa853f4506d55880d, 0x7e538453e568172e, 0xe101f1e098ddd0ec,\n      0x6ee31266ee4c766d, 0xa8786d92d66b39d7, 0xfee622a2acf5e5b0,\n      0x5fe8e82c102fa7b3, 0x01f10be4cdb53c9d, 0xbe0545366f857022,\n      0x12e74f010a339bca, 0xb10d85ca40d5ce34, 0xe80d6feba5054875,\n      0x2b7c1ee6d567d4ee, 0x2a9cd043bfd03b66, 0x5cfc531bd239f3f1,\n      0x1c4734e4647d70f5, 0x85a8f60f006b5760, 0x6a4239ce76dca387,\n      0x8da0f86d7339335c, 0xf055b0468551374d, 0x486e8567e9bea9a0,\n      0x4cb531b8405192dd, 0xf813b1ee3157110b, 0x214c2a664a875d8e,\n      0x74531237b29b35f7, 0xa6f0267bb77a771e, 0x64b552bff54184a4,\n      0xa2d6f7af2d75b6fc, 0x460a10018e03b5ab, 0x76fd1fdcb81d0800,\n      0x76f5f81805070d9d, 0x1fb75cb1a70b289a, 0x9dfd25a022c4b27f,\n      0x9a31a14a80528e9e, 0x910dc565ddc25820, 0xd6aef8e2b0936c10,\n      0xe1773c507fe70225, 0xe027fd7aadd632bc, 0xc1fecb427089c8b8,\n      0xb5c74c69fa9dbf26, 0x71bf9b0e4670227d, 0x25f48fad205dcfdd,\n      0x905248ec4d689c56, 0x5c2b7631b0de5c9d, 0x9f2ee0f8f485036c,\n      0xfd6ce4ebb90bf7ea, 0xd435d20046085574, 0x6b7eadcb0625f986,\n      0x679d7d44b48be89e, 0x49683b8e1cdc49de, 0x4366cf76e9a2f4ca,\n      0x54026ec1cdad7bed, 0xa9a04385207f28d3, 0xc8e66de4eba074b2,\n      0x40b08c42de0f4cc0, 0x1d4c5e0e93c5bbc0, 0x19b80792e470ae2d,\n      0x6fcaaeaa4c2a5bd9, 0xa92cb07c4238438e, 0x8bb5c918a007e298,\n      0x7cd671e944874cf4, 0x88166470b1ba3cac, 0xd013d476eaeeade6,\n      0xcee416947189b3c3, 0x5d7c16ab0dce6088, 0xd3578a5c32b13d27,\n      0x3875db5adc9cc973, 0xfbdaba01c5b5dc56, 0xffc4fdd391b231c3,\n      0x2334520ecb164fec, 0x361c115e7b6de1fa, 0xeee58106cc3563d7,\n      0x8b7f35a8db25ebb8, 0xb29d00211e2cafa6, 0x22a39fe4614b646b,\n      0x92ca6de8b998506d, 0x40922fe3d388d1db, 0x9da47f1e540f802a,\n      0x811dceebf16a25db, 0xf6524ae22e0e53a9, 0x52d9e780a16eb99d,\n      0x4f504286bb830207, 0xf6654d4786bd5cc3, 0x00bd98316003a7e1,\n      0xefda054a6ab8f5f3, 0x46cfb0f4c1872827, 0xc22b316965c0f3b2,\n      0xd1a28087c7e7562a, 0xaa4f6a094b7f5cff, 0xfe2bc853a041f7da,\n      0xe9d531402a83c3ba, 0xe545d8663d3ce4dd, 0xfa2dcd7d91a13fa8,\n      0xda1a080e52a127b8, 0x19c98f1f809c3d84, 0x2cef109af4678c88,\n      0x53462accab3b9132, 0x176b13a80415394e, 0xea70047ef6bc178b,\n      0x57bca80506d6dcdf, 0xd853ba09ff09f5c4, 0x75f4df3a7ddd4775,\n      0x209c367ade62f4fe, 0xa9a0bbc74d5f4682, 0x5dfe34bada86c21a,\n      0xc2c05bbcd38566d1, 0x6de8088e348c916a, 0x6a7001c6000c2196,\n      0xd9fb51865fc4a367, 0x12f320e444ece8ff, 0x6d56f7f793d65035,\n      0x138f31b7a865f8aa, 0x58fc68b4026b9adf, 0xcd48954b79fb6436,\n      0x27dfce4a0232af87,\n  };\n\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  std::seed_seq seed_sequence{1, 2, 3};\n  pcg64_2018_engine engine(seed_sequence);\n  std::ostringstream stream;\n  stream << engine;\n  auto str = stream.str();\n  printf(\"%s\\n\\n\", str.c_str());\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%016lx, \", engine());\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  pcg64_2018_engine engine;\n  std::istringstream stream(\n      \"2549297995355413924 4865540595714422341 6364136223846793005 \"\n      \"1442695040888963407 18088519957565336995 4845369368158826708\");\n  stream >> engine;\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\n// ------------------------------------------------------------------\n// Stability tests for pcg32_2018_engine\n// ------------------------------------------------------------------\nTEST(PCG322018EngineTest, VerifyGolden) {\n  constexpr uint32_t kGolden[kNumGoldenOutputs] = {\n      0x7a7ecbd9, 0x89fd6c06, 0xae646aa8, 0xcd3cf945, 0x6204b303, 0x198c8585,\n      0x49fce611, 0xd1e9297a, 0x142d9440, 0xee75f56b, 0x473a9117, 0xe3a45903,\n      0xbce807a1, 0xe54e5f4d, 0x497d6c51, 0x61829166, 0xa740474b, 0x031912a8,\n      0x9de3defa, 0xd266dbf1, 0x0f38bebb, 0xec3c4f65, 0x07c5057d, 0xbbce03c8,\n      0xfd2ac7a8, 0xffcf4773, 0x5b10affb, 0xede1c842, 0xe22b01b7, 0xda133c8c,\n      0xaf89b0f4, 0x25d1b8bc, 0x9f625482, 0x7bfd6882, 0x2e2210c0, 0x2c8fb9a6,\n      0x42cb3b83, 0x40ce0dab, 0x644a3510, 0x36230ef2, 0xe2cb6d43, 0x1012b343,\n      0x746c6c9f, 0x36714cf8, 0xed1f5026, 0x8bbbf83e, 0xe98710f4, 0x8a2afa36,\n      0x09035349, 0x6dc1a487, 0x682b634b, 0xc106794f, 0x7dd78beb, 0x628c262b,\n      0x852fb232, 0xb153ac4c, 0x4f169d1b, 0xa69ab774, 0x4bd4b6f2, 0xdc351dd3,\n      0x93ff3c8c, 0xa30819ab, 0xff07758c, 0x5ab13c62, 0xd16d7fb5, 0xc4950ffa,\n      0xd309ae49, 0xb9677a87, 0x4464e317, 0x90dc44f1, 0xc694c1d4, 0x1d5e1168,\n      0xadf37a2d, 0xda38990d, 0x1ec4bd33, 0x36ca25ce, 0xfa0dc76a, 0x968a9d43,\n      0x6950ac39, 0xdd3276bc, 0x06d5a71e, 0x1f6f282d, 0x5c626c62, 0xdde3fc31,\n      0x152194ce, 0xc35ed14c, 0xb1f7224e, 0x47f76bb8, 0xb34fdd08, 0x7011395e,\n      0x162d2a49, 0x0d1bf09f, 0x9428a952, 0x03c5c344, 0xd3525616, 0x7816fff3,\n      0x6bceb8a8, 0x8345a081, 0x366420fd, 0x182abeda, 0x70f82745, 0xaf15ded8,\n      0xc7f52ca2, 0xa98db9c5, 0x919d99ba, 0x9c376c1c, 0xed8d34c2, 0x716ae9f5,\n      0xef062fa5, 0xee3b6c56, 0x52325658, 0x61afa9c3, 0xfdaf02f0, 0x961cf3ab,\n      0x9f291565, 0x4fbf3045, 0x0590c899, 0xde901385, 0x45005ffb, 0x509db162,\n      0x262fa941, 0x4c421653, 0x4b17c21e, 0xea0d1530, 0xde803845, 0x61bfd515,\n      0x438523ef,\n  };\n\n  pcg32_2018_engine engine(0);\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%08x, \", engine());\n    if (i % 6 == 5) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed();\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(PCG322018EngineTest, VerifyGoldenSeeded) {\n  constexpr uint32_t kGolden[kNumGoldenOutputs] = {\n      0x60b5a64c, 0x978502f9, 0x80a75f60, 0x241f1158, 0xa4cd1dbb, 0xe7284017,\n      0x3b678da5, 0x5223ec99, 0xe4bdd5d9, 0x72190e6d, 0xe6e702c9, 0xff80c768,\n      0xcf126ed3, 0x1fbd20ab, 0x60980489, 0xbc72bf89, 0x407ac6c0, 0x00bf3c51,\n      0xf9087897, 0x172e4eb6, 0xe9e4f443, 0x1a6098bf, 0xbf44f8c2, 0xdd84a0e5,\n      0xd9a52364, 0xc0e2e786, 0x061ae2ba, 0x9facb8e3, 0x6109432d, 0xd4e0a013,\n      0xbd8eb9a6, 0x7e86c3b6, 0x629c0e68, 0x05337430, 0xb495b9f4, 0x11ccd65d,\n      0xb578db25, 0x66f1246d, 0x6ef20a7f, 0x5e429812, 0x11772130, 0xb944b5c2,\n      0x01624128, 0xa2385ab7, 0xd3e10d35, 0xbe570ec3, 0xc951656f, 0xbe8944a0,\n      0x7be41062, 0x5709f919, 0xd745feda, 0x9870b9ae, 0xb44b8168, 0x19e7683b,\n      0xded8017f, 0xc6e4d544, 0x91ae4225, 0xd6745fba, 0xb992f284, 0x65b12b33,\n      0xa9d5fdb4, 0xf105ce1a, 0x35ca1a6e, 0x2ff70dd0, 0xd8335e49, 0xfb71ddf2,\n      0xcaeabb89, 0x5c6f5f84, 0x9a811a7d, 0xbcecbbd1, 0x0f661ba0, 0x9ad93b9d,\n      0xedd23e0b, 0x42062f48, 0xd38dd7e4, 0x6cd63c9c, 0x640b98ae, 0x4bff5653,\n      0x12626371, 0x13266017, 0xe7a698d8, 0x39c74667, 0xe8fdf2e3, 0x52803bf8,\n      0x2af6895b, 0x91335b7b, 0x699e4961, 0x00a40fff, 0x253ff2b6, 0x4a6cf672,\n      0x9584e85f, 0xf2a5000c, 0x4d58aba8, 0xb8513e6a, 0x767fad65, 0x8e326f9e,\n      0x182f15a1, 0x163dab52, 0xdf99c780, 0x047282a1, 0xee4f90dd, 0xd50394ae,\n      0x6c9fd5f0, 0xb06a9194, 0x387e3840, 0x04a9487b, 0xf678a4c2, 0xd0a78810,\n      0xd502c97e, 0xd6a9b12a, 0x4accc5dc, 0x416ed53e, 0x50411536, 0xeeb89c24,\n      0x813a7902, 0x034ebca6, 0xffa52e7c, 0x7ecd3d0e, 0xfa37a0d2, 0xb1fbe2c1,\n      0xb7efc6d1, 0xefa4ccee, 0xf6f80424, 0x2283f3d9, 0x68732284, 0x94f3b5c8,\n      0xbbdeceb9,\n  };\n\n  ExplicitSeedSeq seed_sequence{12, 34, 56};\n  pcg32_2018_engine engine(seed_sequence);\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%08x, \", engine());\n    if (i % 6 == 5) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed(seed_sequence);\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(PCG322018EngineTest, VerifyGoldenFromDeserializedEngine) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0x780f7042, 0xba137215, 0x43ab6f22, 0x0cb55f46, 0x44b2627d, 0x835597af,\n      0xea973ea1, 0x0d2abd35, 0x4fdd601c, 0xac4342fe, 0x7db7e93c, 0xe56ebcaf,\n      0x3596470a, 0x7770a9ad, 0x9b893320, 0x57db3415, 0xb432de54, 0xa02baf71,\n      0xa256aadb, 0x88921fc7, 0xa35fa6b3, 0xde3eca46, 0x605739a7, 0xa890b82b,\n      0xe457b7ad, 0x335fb903, 0xeb06790c, 0xb3c54bf6, 0x6141e442, 0xa599a482,\n      0xb78987cc, 0xc61dfe9d, 0x0f1d6ace, 0x17460594, 0x8f6a5061, 0x083dc354,\n      0xe9c337fb, 0xcfd105f7, 0x926764b6, 0x638d24dc, 0xeaac650a, 0x67d2cb9c,\n      0xd807733c, 0x205fc52e, 0xf5399e2e, 0x6c46ddcc, 0xb603e875, 0xce113a25,\n      0x3c8d4813, 0xfb584db8, 0xf6d255ff, 0xea80954f, 0x42e8be85, 0xb2feee72,\n      0x62bd8d16, 0x1be4a142, 0x97dca1a4, 0xdd6e7333, 0xb2caa20e, 0xa12b1588,\n      0xeb3a5a1a, 0x6fa5ba89, 0x077ea931, 0x8ddb1713, 0x0dd03079, 0x2c2ba965,\n      0xa77fac17, 0xc8325742, 0x8bb893bf, 0xc2315741, 0xeaceee92, 0x81dd2ee2,\n      0xe5214216, 0x1b9b8fb2, 0x01646d03, 0x24facc25, 0xd8c0e0bb, 0xa33fe106,\n      0xf34fe976, 0xb3b4b44e, 0x65618fed, 0x032c6192, 0xa9dd72ce, 0xf391887b,\n      0xf41c6a6e, 0x05c4bd6d, 0x37fa260e, 0x46b05659, 0xb5f6348a, 0x62d26d89,\n      0x39f6452d, 0xb17b30a2, 0xbdd82743, 0x38ecae3b, 0xfe90f0a2, 0xcb2d226d,\n      0xcf8a0b1c, 0x0eed3d4d, 0xa1f69cfc, 0xd7ac3ba5, 0xce9d9a6b, 0x121deb4c,\n      0x4a0d03f3, 0xc1821ed1, 0x59c249ac, 0xc0abb474, 0x28149985, 0xfd9a82ba,\n      0x5960c3b2, 0xeff00cba, 0x6073aa17, 0x25dc0919, 0x9976626e, 0xdd2ccc33,\n      0x39ecb6ec, 0xc6e15d13, 0xfac94cfd, 0x28cfd34f, 0xf2d2c32d, 0x51c23d08,\n      0x4fdb2f48, 0x97baa807, 0xf2c1004c, 0xc4ae8136, 0x71f31c94, 0x8c92d601,\n      0x36caf5cd,\n  };\n\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  std::seed_seq seed_sequence{1, 2, 3};\n  pcg32_2018_engine engine(seed_sequence);\n  std::ostringstream stream;\n  stream << engine;\n  auto str = stream.str();\n  printf(\"%s\\n\\n\", str.c_str());\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%08x, \", engine());\n    if (i % 6 == 5) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n\n  EXPECT_FALSE(true);\n#else\n  pcg32_2018_engine engine;\n  std::istringstream stream(\n      \"6364136223846793005 1442695040888963407 6537028157270659894\");\n  stream >> engine;\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/platform.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_RANDOM_INTERNAL_PLATFORM_H_\n#define ABSL_RANDOM_INTERNAL_PLATFORM_H_\n\n// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate\n// symbols from arbitrary system and other headers, since it may be built\n// with different flags from other targets, using different levels of\n// optimization, potentially introducing ODR violations.\n\n// -----------------------------------------------------------------------------\n// Platform Feature Checks\n// -----------------------------------------------------------------------------\n\n// Currently supported operating systems and associated preprocessor\n// symbols:\n//\n//   Linux and Linux-derived           __linux__\n//   Android                           __ANDROID__ (implies __linux__)\n//   Linux (non-Android)               __linux__ && !__ANDROID__\n//   Darwin (macOS and iOS)            __APPLE__\n//   Akaros (http://akaros.org)        __ros__\n//   Windows                           _WIN32\n//   AsmJS                             __asmjs__\n//   WebAssembly                       __wasm__\n//   Fuchsia                           __Fuchsia__\n//\n// Note that since Android defines both __ANDROID__ and __linux__, one\n// may probe for either Linux or Android by simply testing for __linux__.\n//\n// NOTE: For __APPLE__ platforms, we use #include <TargetConditionals.h>\n// to distinguish os variants.\n//\n// http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system\n\n#if defined(__APPLE__)\n#include <TargetConditionals.h>\n#endif\n\n// -----------------------------------------------------------------------------\n// Architecture Checks\n// -----------------------------------------------------------------------------\n\n// These preprocessor directives are trying to determine CPU architecture,\n// including necessary headers to support hardware AES.\n//\n// ABSL_ARCH_{X86/PPC/ARM} macros determine the platform.\n#if defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || \\\n    defined(_M_X64)\n#define ABSL_ARCH_X86_64\n#elif defined(__i386) || defined(_M_IX86)\n#define ABSL_ARCH_X86_32\n#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)\n#define ABSL_ARCH_AARCH64\n#elif defined(__arm__) || defined(__ARMEL__) || defined(_M_ARM)\n#define ABSL_ARCH_ARM\n#elif defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \\\n    defined(__ppc__) || defined(__PPC__)\n#define ABSL_ARCH_PPC\n#else\n// Unsupported architecture.\n//  * https://sourceforge.net/p/predef/wiki/Architectures/\n//  * https://msdn.microsoft.com/en-us/library/b0084kay.aspx\n//  * for gcc, clang: \"echo | gcc -E -dM -\"\n#endif\n\n// -----------------------------------------------------------------------------\n// Attribute Checks\n// -----------------------------------------------------------------------------\n\n// ABSL_RANDOM_INTERNAL_RESTRICT annotates whether pointers may be considered\n// to be unaliased.\n#if defined(__clang__) || defined(__GNUC__)\n#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict__\n#elif defined(_MSC_VER)\n#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict\n#else\n#define ABSL_RANDOM_INTERNAL_RESTRICT\n#endif\n\n// ABSL_HAVE_ACCELERATED_AES indicates whether the currently active compiler\n// flags (e.g. -maes) allow using hardware accelerated AES instructions, which\n// implies us assuming that the target platform supports them.\n#define ABSL_HAVE_ACCELERATED_AES 0\n\n#if defined(ABSL_ARCH_X86_64)\n\n#if defined(__AES__) || defined(__AVX__)\n#undef ABSL_HAVE_ACCELERATED_AES\n#define ABSL_HAVE_ACCELERATED_AES 1\n#endif\n\n#elif defined(ABSL_ARCH_PPC)\n\n// Rely on VSX and CRYPTO extensions for vcipher on PowerPC.\n#if (defined(__VEC__) || defined(__ALTIVEC__)) && defined(__VSX__) && \\\n    defined(__CRYPTO__)\n#undef ABSL_HAVE_ACCELERATED_AES\n#define ABSL_HAVE_ACCELERATED_AES 1\n#endif\n\n#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)\n\n// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf\n// Rely on NEON+CRYPTO extensions for ARM.\n#if defined(__ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)\n#undef ABSL_HAVE_ACCELERATED_AES\n#define ABSL_HAVE_ACCELERATED_AES 1\n#endif\n\n#endif\n\n// ABSL_RANDOM_INTERNAL_AES_DISPATCH indicates whether the currently active\n// platform has, or should use run-time dispatch for selecting the\n// accelerated Randen implementation.\n#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0\n\n// iOS does not support dispatch, even on x86, since applications\n// should be bundled as fat binaries, with a different build tailored for\n// each specific supported platform/architecture.\n#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \\\n    (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)\n#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH\n#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0\n#elif defined(ABSL_ARCH_X86_64)\n// Dispatch is available on x86_64\n#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH\n#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1\n#elif defined(__linux__) && defined(ABSL_ARCH_PPC)\n// Or when running linux PPC\n#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH\n#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1\n#elif (defined(__linux__) || defined(__APPLE__)) && defined(ABSL_ARCH_AARCH64)\n// Or when running linux or macOS AArch64\n#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH\n#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1\n#elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8)\n// Or when running linux ARM v8 or higher.\n// (This captures a lot of Android configurations.)\n#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH\n#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1\n#endif\n\n#endif  // ABSL_RANDOM_INTERNAL_PLATFORM_H_\n"
  },
  {
    "path": "absl/random/internal/randen.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen.h\"\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/random/internal/randen_detect.h\"\n\n// RANDen = RANDom generator or beetroots in Swiss High German.\n// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random\n// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.\n//\n// High-level summary:\n// 1) Reverie (see \"A Robust and Sponge-Like PRNG with Improved Efficiency\") is\n//    a sponge-like random generator that requires a cryptographic permutation.\n//    It improves upon \"Provably Robust Sponge-Based PRNGs and KDFs\" by\n//    achieving backtracking resistance with only one Permute() per buffer.\n//\n// 2) \"Simpira v2: A Family of Efficient Permutations Using the AES Round\n//    Function\" constructs up to 1024-bit permutations using an improved\n//    Generalized Feistel network with 2-round AES-128 functions. This Feistel\n//    block shuffle achieves diffusion faster and is less vulnerable to\n//    sliced-biclique attacks than the Type-2 cyclic shuffle.\n//\n// 3) \"Improving the Generalized Feistel\" and \"New criterion for diffusion\n//    property\" extends the same kind of improved Feistel block shuffle to 16\n//    branches, which enables a 2048-bit permutation.\n//\n// We combine these three ideas and also change Simpira's subround keys from\n// structured/low-entropy counters to digits of Pi.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\nstruct RandenState {\n  const void* keys;\n  bool has_crypto;\n};\n\nRandenState GetRandenState() {\n  static const RandenState state = []() {\n    RandenState tmp;\n#if ABSL_RANDOM_INTERNAL_AES_DISPATCH\n    // HW AES Dispatch.\n    if (HasRandenHwAesImplementation() && CPUSupportsRandenHwAes()) {\n      tmp.has_crypto = true;\n      tmp.keys = RandenHwAes::GetKeys();\n    } else {\n      tmp.has_crypto = false;\n      tmp.keys = RandenSlow::GetKeys();\n    }\n#elif ABSL_HAVE_ACCELERATED_AES\n    // HW AES is enabled.\n    tmp.has_crypto = true;\n    tmp.keys = RandenHwAes::GetKeys();\n#else\n    // HW AES is disabled.\n    tmp.has_crypto = false;\n    tmp.keys = RandenSlow::GetKeys();\n#endif\n    return tmp;\n  }();\n  return state;\n}\n\n}  // namespace\n\nRanden::Randen() {\n  auto tmp = GetRandenState();\n  keys_ = tmp.keys;\n#if ABSL_RANDOM_INTERNAL_AES_DISPATCH\n  has_crypto_ = tmp.has_crypto;\n#endif\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/randen.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_RANDEN_H_\n#define ABSL_RANDOM_INTERNAL_RANDEN_H_\n\n#include <cstddef>\n\n#include \"absl/random/internal/platform.h\"\n#include \"absl/random/internal/randen_hwaes.h\"\n#include \"absl/random/internal/randen_slow.h\"\n#include \"absl/random/internal/randen_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// RANDen = RANDom generator or beetroots in Swiss High German.\n// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random\n// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.\n//\n// Randen implements the basic state manipulation methods.\nclass Randen {\n public:\n  static constexpr size_t kStateBytes = RandenTraits::kStateBytes;\n  static constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;\n  static constexpr size_t kSeedBytes = RandenTraits::kSeedBytes;\n\n  ~Randen() = default;\n\n  Randen();\n\n  // Generate updates the randen sponge. The outer portion of the sponge\n  // (kCapacityBytes .. kStateBytes) may be consumed as PRNG state.\n  // REQUIRES: state points to kStateBytes of state.\n  inline void Generate(void* state) const {\n#if ABSL_RANDOM_INTERNAL_AES_DISPATCH\n    // HW AES Dispatch.\n    if (has_crypto_) {\n      RandenHwAes::Generate(keys_, state);\n    } else {\n      RandenSlow::Generate(keys_, state);\n    }\n#elif ABSL_HAVE_ACCELERATED_AES\n    // HW AES is enabled.\n    RandenHwAes::Generate(keys_, state);\n#else\n    // HW AES is disabled.\n    RandenSlow::Generate(keys_, state);\n#endif\n  }\n\n  // Absorb incorporates additional seed material into the randen sponge.  After\n  // absorb returns, Generate must be called before the state may be consumed.\n  // REQUIRES: seed points to kSeedBytes of seed.\n  // REQUIRES: state points to kStateBytes of state.\n  inline void Absorb(const void* seed, void* state) const {\n#if ABSL_RANDOM_INTERNAL_AES_DISPATCH\n    // HW AES Dispatch.\n    if (has_crypto_) {\n      RandenHwAes::Absorb(seed, state);\n    } else {\n      RandenSlow::Absorb(seed, state);\n    }\n#elif ABSL_HAVE_ACCELERATED_AES\n    // HW AES is enabled.\n    RandenHwAes::Absorb(seed, state);\n#else\n    // HW AES is disabled.\n    RandenSlow::Absorb(seed, state);\n#endif\n  }\n\n private:\n  const void* keys_;\n#if ABSL_RANDOM_INTERNAL_AES_DISPATCH\n  bool has_crypto_;\n#endif\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_RANDEN_H_\n"
  },
  {
    "path": "absl/random/internal/randen_benchmarks.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#include <cstdint>\n#include <cstdio>\n#include <cstring>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/random/internal/nanobenchmark.h\"\n#include \"absl/random/internal/platform.h\"\n#include \"absl/random/internal/randen.h\"\n#include \"absl/random/internal/randen_detect.h\"\n#include \"absl/random/internal/randen_engine.h\"\n#include \"absl/random/internal/randen_hwaes.h\"\n#include \"absl/random/internal/randen_slow.h\"\n#include \"absl/strings/numbers.h\"\n\nnamespace {\n\nusing absl::random_internal::CPUSupportsRandenHwAes;\nusing absl::random_internal::Randen;\nusing absl::random_internal::RandenHwAes;\nusing absl::random_internal::RandenSlow;\n\nusing absl::random_internal_nanobenchmark::FuncInput;\nusing absl::random_internal_nanobenchmark::FuncOutput;\nusing absl::random_internal_nanobenchmark::InvariantTicksPerSecond;\nusing absl::random_internal_nanobenchmark::MeasureClosure;\nusing absl::random_internal_nanobenchmark::Params;\nusing absl::random_internal_nanobenchmark::PinThreadToCPU;\nusing absl::random_internal_nanobenchmark::Result;\n\n// Local state parameters.\nstatic constexpr size_t kStateSizeT = Randen::kStateBytes / sizeof(uint64_t);\nstatic constexpr size_t kSeedSizeT = Randen::kSeedBytes / sizeof(uint32_t);\n\n// Randen implementation benchmarks.\ntemplate <typename T>\nstruct AbsorbFn : public T {\n  // These are both cast to uint128* in the RandenHwAes implementation, so\n  // ensure they are 16 byte aligned.\n  alignas(16) mutable uint64_t state[kStateSizeT] = {};\n  alignas(16) mutable uint32_t seed[kSeedSizeT] = {};\n\n  static constexpr size_t bytes() { return sizeof(seed); }\n\n  FuncOutput operator()(const FuncInput num_iters) const {\n    for (size_t i = 0; i < num_iters; ++i) {\n      this->Absorb(seed, state);\n    }\n    return state[0];\n  }\n};\n\ntemplate <typename T>\nstruct GenerateFn : public T {\n  mutable uint64_t state[kStateSizeT];\n  GenerateFn() { std::memset(state, 0, sizeof(state)); }\n\n  static constexpr size_t bytes() { return sizeof(state); }\n\n  FuncOutput operator()(const FuncInput num_iters) const {\n    const auto* keys = this->GetKeys();\n    for (size_t i = 0; i < num_iters; ++i) {\n      this->Generate(keys, state);\n    }\n    return state[0];\n  }\n};\n\ntemplate <typename UInt>\nstruct Engine {\n  mutable absl::random_internal::randen_engine<UInt> rng;\n\n  static constexpr size_t bytes() { return sizeof(UInt); }\n\n  FuncOutput operator()(const FuncInput num_iters) const {\n    for (size_t i = 0; i < num_iters - 1; ++i) {\n      rng();\n    }\n    return rng();\n  }\n};\n\ntemplate <size_t N>\nvoid Print(const char* name, const size_t n, const Result (&results)[N],\n           const size_t bytes) {\n  if (n == 0) {\n    ABSL_RAW_LOG(\n        WARNING,\n        \"WARNING: Measurement failed, should not happen when using \"\n        \"PinThreadToCPU unless the region to measure takes > 1 second.\\n\");\n    return;\n  }\n\n  static const double ns_per_tick = 1e9 / InvariantTicksPerSecond();\n  static constexpr const double kNsPerS = 1e9;                 // ns/s\n  static constexpr const double kMBPerByte = 1.0 / 1048576.0;  // Mb / b\n  static auto header = [] {\n    return printf(\"%20s %8s: %12s ticks; %9s  (%9s) %8s\\n\", \"Name\", \"Count\",\n                  \"Total\", \"Variance\", \"Time\", \"bytes/s\");\n  }();\n  (void)header;\n\n  for (size_t i = 0; i < n; ++i) {\n    const double ticks_per_call = results[i].ticks / results[i].input;\n    const double ns_per_call = ns_per_tick * ticks_per_call;\n    const double bytes_per_ns = bytes / ns_per_call;\n    const double mb_per_s = bytes_per_ns * kNsPerS * kMBPerByte;\n    // Output\n    printf(\"%20s %8zu: %12.2f ticks; MAD=%4.2f%%  (%6.1f ns) %8.1f Mb/s\\n\",\n           name, results[i].input, results[i].ticks,\n           results[i].variability * 100.0, ns_per_call, mb_per_s);\n  }\n}\n\n// Fails here\ntemplate <typename Op, size_t N>\nvoid Measure(const char* name, const FuncInput (&inputs)[N]) {\n  Op op;\n\n  Result results[N];\n  Params params;\n  params.verbose = false;\n  params.max_evals = 6;  // avoid test timeout\n  const size_t num_results = MeasureClosure(op, inputs, N, results, params);\n  Print(name, num_results, results, op.bytes());\n}\n\n// unpredictable == 1 but the compiler does not know that.\nvoid RunAll(const int argc, char* argv[]) {\n  if (argc == 2) {\n    int cpu = -1;\n    if (!absl::SimpleAtoi(argv[1], &cpu)) {\n      ABSL_RAW_LOG(FATAL, \"The optional argument must be a CPU number >= 0.\\n\");\n    }\n    PinThreadToCPU(cpu);\n  }\n\n  // The compiler cannot reduce this to a constant.\n  const FuncInput unpredictable = (argc != 999);\n  static const FuncInput inputs[] = {unpredictable * 100, unpredictable * 1000};\n\n  if (CPUSupportsRandenHwAes()) {\n    Measure<AbsorbFn<RandenHwAes>>(\"Absorb (HwAes)\", inputs);\n  }\n  Measure<AbsorbFn<RandenSlow>>(\"Absorb (Slow)\", inputs);\n\n  if (CPUSupportsRandenHwAes()) {\n    Measure<GenerateFn<RandenHwAes>>(\"Generate (HwAes)\", inputs);\n  }\n  Measure<GenerateFn<RandenSlow>>(\"Generate (Slow)\", inputs);\n\n  // Measure the production engine.\n  static const FuncInput inputs1[] = {unpredictable * 1000,\n                                      unpredictable * 10000};\n  Measure<Engine<uint64_t>>(\"randen_engine<uint64_t>\", inputs1);\n  Measure<Engine<uint32_t>>(\"randen_engine<uint32_t>\", inputs1);\n}\n\n}  // namespace\n\nint main(int argc, char* argv[]) {\n  RunAll(argc, argv);\n  return 0;\n}\n"
  },
  {
    "path": "absl/random/internal/randen_detect.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate\n// symbols from arbitrary system and other headers, since it may be built\n// with different flags from other targets, using different levels of\n// optimization, potentially introducing ODR violations.\n\n#include \"absl/random/internal/randen_detect.h\"\n\n#if defined(__APPLE__) && defined(__aarch64__)\n#if defined(__has_include)\n#if __has_include(<arm/cpu_capabilities_public.h>)\n#include <arm/cpu_capabilities_public.h>\n#endif\n#endif\n#include <sys/sysctl.h>\n#include <sys/types.h>\n#endif\n\n#include <cstdint>\n#include <cstring>\n#include <optional>  // IWYU pragma: keep\n\n#include \"absl/random/internal/platform.h\"\n\n#if !defined(__UCLIBC__) && defined(__GLIBC__) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))\n#define ABSL_HAVE_GETAUXVAL\n#endif\n\n#if defined(ABSL_ARCH_X86_64)\n#define ABSL_INTERNAL_USE_X86_CPUID\n#elif defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \\\n    defined(ABSL_ARCH_AARCH64)\n#if defined(__ANDROID__)\n#define ABSL_INTERNAL_USE_ANDROID_GETAUXVAL\n#define ABSL_INTERNAL_USE_GETAUXVAL\n#elif defined(__linux__) && defined(ABSL_HAVE_GETAUXVAL)\n#define ABSL_INTERNAL_USE_LINUX_GETAUXVAL\n#define ABSL_INTERNAL_USE_GETAUXVAL\n#endif\n#endif\n\n#if defined(ABSL_INTERNAL_USE_X86_CPUID)\n#if defined(_WIN32) || defined(_WIN64)\n#include <intrin.h>  // NOLINT(build/include_order)\n#elif ABSL_HAVE_BUILTIN(__cpuid)\n// MSVC-equivalent __cpuid intrinsic declaration for clang-like compilers\n// for non-Windows build environments.\nextern void __cpuid(int[4], int);\n#else\n// MSVC-equivalent __cpuid intrinsic function.\nstatic void __cpuid(int cpu_info[4], int info_type) {\n  __asm__ volatile(\"cpuid \\n\\t\"\n                   : \"=a\"(cpu_info[0]), \"=b\"(cpu_info[1]), \"=c\"(cpu_info[2]),\n                     \"=d\"(cpu_info[3])\n                   : \"a\"(info_type), \"c\"(0));\n}\n#endif\n#endif  // ABSL_INTERNAL_USE_X86_CPUID\n\n// On linux, just use the c-library getauxval call.\n#if defined(ABSL_INTERNAL_USE_LINUX_GETAUXVAL)\n\n#include <sys/auxv.h>\n\nstatic uint32_t GetAuxval(uint32_t hwcap_type) {\n  return static_cast<uint32_t>(getauxval(hwcap_type));\n}\n\n#endif\n\n// On android, probe the system's C library for getauxval().\n// This is the same technique used by the android NDK cpu features library\n// as well as the google open-source cpu_features library.\n//\n// TODO(absl-team): Consider implementing a fallback of directly reading\n// /proc/self/auxval.\n#if defined(ABSL_INTERNAL_USE_ANDROID_GETAUXVAL)\n#include <dlfcn.h>\n\nstatic uint32_t GetAuxval(uint32_t hwcap_type) {\n  // NOLINTNEXTLINE(runtime/int)\n  typedef unsigned long (*getauxval_func_t)(unsigned long);\n\n  dlerror();  // Cleaning error state before calling dlopen.\n  void* libc_handle = dlopen(\"libc.so\", RTLD_NOW);\n  if (!libc_handle) {\n    return 0;\n  }\n  uint32_t result = 0;\n  void* sym = dlsym(libc_handle, \"getauxval\");\n  if (sym) {\n    getauxval_func_t func;\n    memcpy(&func, &sym, sizeof(func));\n    result = static_cast<uint32_t>((*func)(hwcap_type));\n  }\n  dlclose(libc_handle);\n  return result;\n}\n\n#endif\n\n#if defined(__APPLE__) && defined(ABSL_ARCH_AARCH64)\ntemplate <typename T>\nstatic std::optional<T> ReadSysctlByName(const char* name) {\n  T val;\n  size_t val_size = sizeof(T);\n  int ret = sysctlbyname(name, &val, &val_size, nullptr, 0);\n  if (ret == -1) {\n    return std::nullopt;\n  }\n  return val;\n}\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// The default return at the end of the function might be unreachable depending\n// on the configuration. Ignore that warning.\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunreachable-code-return\"\n#endif\n\n// CPUSupportsRandenHwAes returns whether the CPU is a microarchitecture\n// which supports the crpyto/aes instructions or extensions necessary to use the\n// accelerated RandenHwAes implementation.\n//\n// 1. For x86 it is sufficient to use the CPUID instruction to detect whether\n//    the cpu supports AES instructions. Done.\n//\n// Fon non-x86 it is much more complicated.\n//\n// 2. When ABSL_INTERNAL_USE_GETAUXVAL is defined, use getauxval() (either\n//    the direct c-library version, or the android probing version which loads\n//    libc), and read the hardware capability bits.\n//    This is based on the technique used by boringssl uses to detect\n//    cpu capabilities, and should allow us to enable crypto in the android\n//    builds where it is supported.\n//\n// 3. When __APPLE__ is defined on AARCH64, use sysctlbyname().\n//\n// 4. Use the default for the compiler architecture.\n//\n\nbool CPUSupportsRandenHwAes() {\n#if defined(ABSL_INTERNAL_USE_X86_CPUID)\n  // 1. For x86: Use CPUID to detect the required AES instruction set.\n  int regs[4];\n  __cpuid(reinterpret_cast<int*>(regs), 1);\n  return regs[2] & (1 << 25);  // AES\n\n#elif defined(ABSL_INTERNAL_USE_GETAUXVAL)\n  // 2. Use getauxval() to read the hardware bits and determine\n  // cpu capabilities.\n\n#define AT_HWCAP 16\n#define AT_HWCAP2 26\n#if defined(ABSL_ARCH_PPC)\n  // For Power / PPC: Expect that the cpu supports VCRYPTO\n  // See https://members.openpowerfoundation.org/document/dl/576\n  // VCRYPTO should be present in POWER8 >= 2.07.\n  // Uses Linux kernel constants from arch/powerpc/include/uapi/asm/cputable.h\n  static const uint32_t kVCRYPTO = 0x02000000;\n  const uint32_t hwcap = GetAuxval(AT_HWCAP2);\n  return (hwcap & kVCRYPTO) != 0;\n\n#elif defined(ABSL_ARCH_ARM)\n  // For ARM: Require crypto+neon\n  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html\n  // Uses Linux kernel constants from arch/arm64/include/asm/hwcap.h\n  static const uint32_t kNEON = 1 << 12;\n  uint32_t hwcap = GetAuxval(AT_HWCAP);\n  if ((hwcap & kNEON) == 0) {\n    return false;\n  }\n\n  // And use it again to detect AES.\n  static const uint32_t kAES = 1 << 0;\n  const uint32_t hwcap2 = GetAuxval(AT_HWCAP2);\n  return (hwcap2 & kAES) != 0;\n\n#elif defined(ABSL_ARCH_AARCH64)\n  // For AARCH64: Require crypto+neon\n  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html\n  static const uint32_t kNEON = 1 << 1;\n  static const uint32_t kAES = 1 << 3;\n  const uint32_t hwcap = GetAuxval(AT_HWCAP);\n  return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0);\n#endif\n\n#elif defined(__APPLE__) && defined(ABSL_ARCH_AARCH64)\n  // 3. Use sysctlbyname.\n\n  // Newer XNU kernels support querying all capabilities in a single\n  // sysctlbyname.\n#if defined(CAP_BIT_AdvSIMD) && defined(CAP_BIT_FEAT_AES)\n  static const std::optional<uint64_t> caps =\n      ReadSysctlByName<uint64_t>(\"hw.optional.arm.caps\");\n  if (caps.has_value()) {\n    constexpr uint64_t kNeonAndAesCaps =\n        (uint64_t{1} << CAP_BIT_AdvSIMD) | (uint64_t{1} << CAP_BIT_FEAT_AES);\n    return (*caps & kNeonAndAesCaps) == kNeonAndAesCaps;\n  }\n#endif\n\n  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#overview\n  static const std::optional<int> adv_simd =\n      ReadSysctlByName<int>(\"hw.optional.AdvSIMD\");\n  if (adv_simd.value_or(0) == 0) {\n    return false;\n  }\n  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855\n  static const std::optional<int> feat_aes =\n      ReadSysctlByName<int>(\"hw.optional.arm.FEAT_AES\");\n  if (feat_aes.value_or(0) == 0) {\n    return false;\n  }\n  return true;\n#else  // ABSL_INTERNAL_USE_GETAUXVAL\n  // 4. By default, assume that the compiler default.\n  return ABSL_HAVE_ACCELERATED_AES ? true : false;\n\n#endif\n  // NOTE: There are some other techniques that may be worth trying:\n  //\n  // * Use an environment variable: ABSL_RANDOM_USE_HWAES\n  //\n  // * Rely on compiler-generated target-based dispatch.\n  // Using x86/gcc it might look something like this:\n  //\n  // int __attribute__((target(\"aes\"))) HasAes() { return 1; }\n  // int __attribute__((target(\"default\"))) HasAes() { return 0; }\n  //\n  // This does not work on all architecture/compiler combinations.\n  //\n  // * On Linux consider reading /proc/cpuinfo and/or /proc/self/auxv.\n  // These files have lines which are easy to parse; for ARM/AARCH64 it is quite\n  // easy to find the Features: line and extract aes / neon. Likewise for\n  // PPC.\n  //\n  // * Fork a process and test for SIGILL:\n  //\n  // * Many architectures have instructions to read the ISA. Unfortunately\n  //   most of those require that the code is running in ring 0 /\n  //   protected-mode.\n  //\n  //   There are several examples. e.g. Valgrind detects PPC ISA 2.07:\n  //   https://github.com/lu-zero/valgrind/blob/master/none/tests/ppc64/test_isa_2_07_part1.c\n  //\n  //   MRS <Xt>, ID_AA64ISAR0_EL1 ; Read ID_AA64ISAR0_EL1 into Xt\n  //\n  //   uint64_t val;\n  //   __asm __volatile(\"mrs %0, id_aa64isar0_el1\" :\"=&r\" (val));\n  //\n  // * Use a CPUID-style heuristic database.\n}\n\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/randen_detect.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_\n#define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// Returns whether the current CPU supports RandenHwAes implementation.\n// This typically involves supporting cryptographic extensions on whichever\n// platform is currently running.\nbool CPUSupportsRandenHwAes();\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_\n"
  },
  {
    "path": "absl/random/internal/randen_engine.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_\n#define ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_\n\n#include <algorithm>\n#include <cinttypes>\n#include <cstdlib>\n#include <istream>\n#include <iterator>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/internal/endian.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/internal/randen.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// Deterministic pseudorandom byte generator with backtracking resistance\n// (leaking the state does not compromise prior outputs). Based on Reverie\n// (see \"A Robust and Sponge-Like PRNG with Improved Efficiency\") instantiated\n// with an improved Simpira-like permutation.\n// Returns values of type \"T\" (must be a built-in unsigned integer type).\n//\n// RANDen = RANDom generator or beetroots in Swiss High German.\n// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random\n// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.\ntemplate <typename T>\nclass alignas(8) randen_engine {\n public:\n  // C++11 URBG interface:\n  using result_type = T;\n  static_assert(std::is_unsigned<result_type>::value,\n                \"randen_engine template argument must be a built-in unsigned \"\n                \"integer type\");\n\n  static constexpr result_type(min)() {\n    return (std::numeric_limits<result_type>::min)();\n  }\n\n  static constexpr result_type(max)() {\n    return (std::numeric_limits<result_type>::max)();\n  }\n\n  randen_engine() : randen_engine(0) {}\n  explicit randen_engine(result_type seed_value) { seed(seed_value); }\n\n  template <class SeedSequence,\n            typename = typename absl::enable_if_t<\n                !std::is_same<SeedSequence, randen_engine>::value>>\n  explicit randen_engine(SeedSequence&& seq) {\n    seed(seq);\n  }\n\n  // alignment requirements dictate custom copy and move constructors.\n  randen_engine(const randen_engine& other)\n      : next_(other.next_), impl_(other.impl_) {\n    std::memcpy(state(), other.state(), kStateSizeT * sizeof(result_type));\n  }\n  randen_engine& operator=(const randen_engine& other) {\n    next_ = other.next_;\n    impl_ = other.impl_;\n    std::memcpy(state(), other.state(), kStateSizeT * sizeof(result_type));\n    return *this;\n  }\n\n  // Returns random bits from the buffer in units of result_type.\n  result_type operator()() {\n    // Refill the buffer if needed (unlikely).\n    auto* begin = state();\n    if (next_ >= kStateSizeT) {\n      next_ = kCapacityT;\n      impl_.Generate(begin);\n    }\n    return little_endian::ToHost(begin[next_++]);\n  }\n\n  template <class SeedSequence>\n  typename absl::enable_if_t<\n      !std::is_convertible<SeedSequence, result_type>::value>\n  seed(SeedSequence&& seq) {\n    // Zeroes the state.\n    seed();\n    reseed(seq);\n  }\n\n  void seed(result_type seed_value = 0) {\n    next_ = kStateSizeT;\n    // Zeroes the inner state and fills the outer state with seed_value to\n    // mimic the behaviour of reseed\n    auto* begin = state();\n    std::fill(begin, begin + kCapacityT, 0);\n    std::fill(begin + kCapacityT, begin + kStateSizeT, seed_value);\n  }\n\n  // Inserts entropy into (part of) the state. Calling this periodically with\n  // sufficient entropy ensures prediction resistance (attackers cannot predict\n  // future outputs even if state is compromised).\n  template <class SeedSequence>\n  void reseed(SeedSequence& seq) {\n    using sequence_result_type = typename SeedSequence::result_type;\n    static_assert(sizeof(sequence_result_type) == 4,\n                  \"SeedSequence::result_type must be 32-bit\");\n    constexpr size_t kBufferSize =\n        Randen::kSeedBytes / sizeof(sequence_result_type);\n    alignas(16) sequence_result_type buffer[kBufferSize];\n\n    // Randen::Absorb XORs the seed into state, which is then mixed by a call\n    // to Randen::Generate. Seeding with only the provided entropy is preferred\n    // to using an arbitrary generate() call, so use [rand.req.seed_seq]\n    // size as a proxy for the number of entropy units that can be generated\n    // without relying on seed sequence mixing...\n    const size_t entropy_size = seq.size();\n    if (entropy_size < kBufferSize) {\n      // ... and only request that many values, or 256-bits, when unspecified.\n      const size_t requested_entropy = (entropy_size == 0) ? 8u : entropy_size;\n      std::fill(buffer + requested_entropy, buffer + kBufferSize, 0);\n      seq.generate(buffer, buffer + requested_entropy);\n#ifdef ABSL_IS_BIG_ENDIAN\n      // Randen expects the seed buffer to be in Little Endian; reverse it on\n      // Big Endian platforms.\n      for (sequence_result_type& e : buffer) {\n        e = absl::little_endian::FromHost(e);\n      }\n#endif\n      // The Randen paper suggests preferentially initializing even-numbered\n      // 128-bit vectors of the randen state (there are 16 such vectors).\n      // The seed data is merged into the state offset by 128-bits, which\n      // implies preferring seed bytes [16..31, ..., 208..223]. Since the\n      // buffer is 32-bit values, we swap the corresponding buffer positions in\n      // 128-bit chunks.\n      size_t dst = kBufferSize;\n      while (dst > 7) {\n        // leave the odd bucket as-is.\n        dst -= 4;\n        size_t src = dst >> 1;\n        // swap 128-bits into the even bucket\n        std::swap(buffer[--dst], buffer[--src]);\n        std::swap(buffer[--dst], buffer[--src]);\n        std::swap(buffer[--dst], buffer[--src]);\n        std::swap(buffer[--dst], buffer[--src]);\n      }\n    } else {\n      seq.generate(buffer, buffer + kBufferSize);\n    }\n    impl_.Absorb(buffer, state());\n\n    // Generate will be called when operator() is called\n    next_ = kStateSizeT;\n  }\n\n  void discard(uint64_t count) {\n    uint64_t step = std::min<uint64_t>(kStateSizeT - next_, count);\n    count -= step;\n\n    constexpr uint64_t kRateT = kStateSizeT - kCapacityT;\n    auto* begin = state();\n    while (count > 0) {\n      next_ = kCapacityT;\n      impl_.Generate(*reinterpret_cast<result_type(*)[kStateSizeT]>(begin));\n      step = std::min<uint64_t>(kRateT, count);\n      count -= step;\n    }\n    next_ += step;\n  }\n\n  bool operator==(const randen_engine& other) const {\n    const auto* begin = state();\n    return next_ == other.next_ &&\n           std::equal(begin, begin + kStateSizeT, other.state());\n  }\n\n  bool operator!=(const randen_engine& other) const {\n    return !(*this == other);\n  }\n\n  template <class CharT, class Traits>\n  friend std::basic_ostream<CharT, Traits>& operator<<(\n      std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n      const randen_engine<T>& engine) {       // NOLINT(runtime/references)\n    using numeric_type =\n        typename random_internal::stream_format_type<result_type>::type;\n    auto saver = random_internal::make_ostream_state_saver(os);\n    auto* it = engine.state();\n    for (auto* end = it + kStateSizeT; it < end; ++it) {\n      // In the case that `elem` is `uint8_t`, it must be cast to something\n      // larger so that it prints as an integer rather than a character. For\n      // simplicity, apply the cast all circumstances.\n      os << static_cast<numeric_type>(little_endian::FromHost(*it))\n         << os.fill();\n    }\n    os << engine.next_;\n    return os;\n  }\n\n  template <class CharT, class Traits>\n  friend std::basic_istream<CharT, Traits>& operator>>(\n      std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n      randen_engine<T>& engine) {             // NOLINT(runtime/references)\n    using numeric_type =\n        typename random_internal::stream_format_type<result_type>::type;\n    result_type state[kStateSizeT];\n    size_t next;\n    for (auto& elem : state) {\n      // It is not possible to read uint8_t from wide streams, so it is\n      // necessary to read a wider type and then cast it to uint8_t.\n      numeric_type value;\n      is >> value;\n      elem = little_endian::ToHost(static_cast<result_type>(value));\n    }\n    is >> next;\n    if (is.fail()) {\n      return is;\n    }\n    std::memcpy(engine.state(), state, sizeof(state));\n    engine.next_ = next;\n    return is;\n  }\n\n private:\n  static constexpr size_t kStateSizeT =\n      Randen::kStateBytes / sizeof(result_type);\n  static constexpr size_t kCapacityT =\n      Randen::kCapacityBytes / sizeof(result_type);\n\n  // Returns the state array pointer, which is aligned to 16 bytes.\n  // The first kCapacityT are the `inner' sponge; the remainder are available.\n  result_type* state() {\n    return reinterpret_cast<result_type*>(\n        (reinterpret_cast<uintptr_t>(&raw_state_) & 0xf) ? (raw_state_ + 8)\n                                                         : raw_state_);\n  }\n  const result_type* state() const {\n    return const_cast<randen_engine*>(this)->state();\n  }\n\n  // raw state array, manually aligned in state(). This overallocates\n  // by 8 bytes since C++ does not guarantee extended heap alignment.\n  alignas(8) char raw_state_[Randen::kStateBytes + 8];\n  size_t next_;  // index within state()\n  Randen impl_;\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_\n"
  },
  {
    "path": "absl/random/internal/randen_engine_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen_engine.h\"\n\n#include <algorithm>\n#include <bitset>\n#include <random>\n#include <sstream>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/explicit_seed_seq.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/time/clock.h\"\n\n#define UPDATE_GOLDEN 0\n\nusing randen_u64 = absl::random_internal::randen_engine<uint64_t>;\nusing randen_u32 = absl::random_internal::randen_engine<uint32_t>;\nusing absl::random_internal::ExplicitSeedSeq;\n\nnamespace {\n\ntemplate <typename UIntType>\nclass RandenEngineTypedTest : public ::testing::Test {};\n\nusing UIntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>;\n\nTYPED_TEST_SUITE(RandenEngineTypedTest, UIntTypes);\n\nTYPED_TEST(RandenEngineTypedTest, VerifyReseedChangesAllValues) {\n  using randen = typename absl::random_internal::randen_engine<TypeParam>;\n  using result_type = typename randen::result_type;\n\n  const size_t kNumOutputs = (sizeof(randen) * 2 / sizeof(TypeParam)) + 1;\n  randen engine;\n\n  // MSVC emits error 2719 without the use of std::ref below.\n  //  * formal parameter with __declspec(align('#')) won't be aligned\n\n  {\n    std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7};\n    engine.seed(seq1);\n  }\n  result_type a[kNumOutputs];\n  std::generate(std::begin(a), std::end(a), std::ref(engine));\n\n  {\n    std::random_device rd;\n    std::seed_seq seq2{rd(), rd(), rd()};\n    engine.seed(seq2);\n  }\n  result_type b[kNumOutputs];\n  std::generate(std::begin(b), std::end(b), std::ref(engine));\n\n  // Test that generated sequence changed as sequence of bits, i.e. if about\n  // half of the bites were flipped between two non-correlated values.\n  size_t changed_bits = 0;\n  size_t unchanged_bits = 0;\n  size_t total_set = 0;\n  size_t total_bits = 0;\n  size_t equal_count = 0;\n  for (size_t i = 0; i < kNumOutputs; ++i) {\n    equal_count += (a[i] == b[i]) ? 1 : 0;\n    std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);\n    changed_bits += bitset.count();\n    unchanged_bits += bitset.size() - bitset.count();\n\n    std::bitset<sizeof(result_type) * 8> a_set(a[i]);\n    std::bitset<sizeof(result_type) * 8> b_set(b[i]);\n    total_set += a_set.count() + b_set.count();\n    total_bits += 2 * 8 * sizeof(result_type);\n  }\n  // On average, half the bits are changed between two calls.\n  EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));\n  EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));\n\n  // Verify using a quick normal-approximation to the binomial.\n  EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))\n      << \"@\" << total_set / static_cast<double>(total_bits);\n\n  // Also, A[i] == B[i] with probability (1/range) * N.\n  // Give this a pretty wide latitude, though.\n  const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);\n  EXPECT_LE(equal_count, 1.0 + kExpected);\n}\n\n// Number of values that needs to be consumed to clean two sizes of buffer\n// and trigger third refresh. (slightly overestimates the actual state size).\nconstexpr size_t kTwoBufferValues = sizeof(randen_u64) / sizeof(uint16_t) + 1;\n\nTYPED_TEST(RandenEngineTypedTest, VerifyDiscard) {\n  using randen = typename absl::random_internal::randen_engine<TypeParam>;\n\n  for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) {\n    randen engine_used;\n    for (size_t i = 0; i < num_used; ++i) {\n      engine_used();\n    }\n\n    for (size_t num_discard = 0; num_discard < kTwoBufferValues;\n         ++num_discard) {\n      randen engine1 = engine_used;\n      randen engine2 = engine_used;\n      for (size_t i = 0; i < num_discard; ++i) {\n        engine1();\n      }\n      engine2.discard(num_discard);\n      for (size_t i = 0; i < kTwoBufferValues; ++i) {\n        const auto r1 = engine1();\n        const auto r2 = engine2();\n        ASSERT_EQ(r1, r2) << \"used=\" << num_used << \" discard=\" << num_discard;\n      }\n    }\n  }\n}\n\nTYPED_TEST(RandenEngineTypedTest, StreamOperatorsResult) {\n  using randen = typename absl::random_internal::randen_engine<TypeParam>;\n  std::wostringstream os;\n  std::wistringstream is;\n  randen engine;\n\n  EXPECT_EQ(&(os << engine), &os);\n  EXPECT_EQ(&(is >> engine), &is);\n}\n\nTYPED_TEST(RandenEngineTypedTest, StreamSerialization) {\n  using randen = typename absl::random_internal::randen_engine<TypeParam>;\n\n  for (size_t discard = 0; discard < kTwoBufferValues; ++discard) {\n    ExplicitSeedSeq seed_sequence{12, 34, 56};\n    randen engine(seed_sequence);\n    engine.discard(discard);\n\n    std::stringstream stream;\n    stream << engine;\n\n    randen new_engine;\n    stream >> new_engine;\n    for (size_t i = 0; i < 64; ++i) {\n      EXPECT_EQ(engine(), new_engine()) << \" \" << i;\n    }\n  }\n}\n\nconstexpr size_t kNumGoldenOutputs = 127;\n\n// This test is checking if randen_engine is meets interface requirements\n// defined in [rand.req.urbg].\nTYPED_TEST(RandenEngineTypedTest, RandomNumberEngineInterface) {\n  using randen = typename absl::random_internal::randen_engine<TypeParam>;\n\n  using E = randen;\n  using T = typename E::result_type;\n\n  static_assert(std::is_copy_constructible<E>::value,\n                \"randen_engine must be copy constructible\");\n\n  static_assert(absl::is_copy_assignable<E>::value,\n                \"randen_engine must be copy assignable\");\n\n  static_assert(std::is_move_constructible<E>::value,\n                \"randen_engine must be move constructible\");\n\n  static_assert(absl::is_move_assignable<E>::value,\n                \"randen_engine must be move assignable\");\n\n  static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,\n                \"return type of operator() must be result_type\");\n\n  // Names after definition of [rand.req.urbg] in C++ standard.\n  // e us a value of E\n  // v is a lvalue of E\n  // x, y are possibly const values of E\n  // s is a value of T\n  // q is a value satisfying requirements of seed_sequence\n  // z is a value of type unsigned long long\n  // os is a some specialization of basic_ostream\n  // is is a some specialization of basic_istream\n\n  E e, v;\n  const E x, y;\n  T s = 1;\n  std::seed_seq q{1, 2, 3};\n  unsigned long long z = 1;  // NOLINT(runtime/int)\n  std::wostringstream os;\n  std::wistringstream is;\n\n  E{};\n  E{x};\n  E{s};\n  E{q};\n\n  e.seed();\n\n  // MSVC emits error 2718 when using EXPECT_EQ(e, x)\n  //  * actual parameter with __declspec(align('#')) won't be aligned\n  EXPECT_TRUE(e == x);\n\n  e.seed(q);\n  {\n    E tmp(q);\n    EXPECT_TRUE(e == tmp);\n  }\n\n  e();\n  {\n    E tmp(q);\n    EXPECT_TRUE(e != tmp);\n  }\n\n  e.discard(z);\n\n  static_assert(std::is_same<decltype(x == y), bool>::value,\n                \"return type of operator== must be bool\");\n\n  static_assert(std::is_same<decltype(x != y), bool>::value,\n                \"return type of operator== must be bool\");\n}\n\nTYPED_TEST(RandenEngineTypedTest, RandenEngineSFINAETest) {\n  using randen = typename absl::random_internal::randen_engine<TypeParam>;\n  using result_type = typename randen::result_type;\n\n  {\n    randen engine(result_type(1));\n    engine.seed(result_type(1));\n  }\n\n  {\n    result_type n = 1;\n    randen engine(n);\n    engine.seed(n);\n  }\n\n  {\n    randen engine(1);\n    engine.seed(1);\n  }\n\n  {\n    int n = 1;\n    randen engine(n);\n    engine.seed(n);\n  }\n\n  {\n    std::seed_seq seed_seq;\n    randen engine(seed_seq);\n    engine.seed(seed_seq);\n  }\n\n  {\n    randen engine{std::seed_seq()};\n    engine.seed(std::seed_seq());\n  }\n}\n\nTEST(RandenTest, VerifyGoldenRanden64Default) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0xc3c14f134e433977, 0xdda9f47cd90410ee, 0x887bf3087fd8ca10,\n      0xf0b780f545c72912, 0x15dbb1d37696599f, 0x30ec63baff3c6d59,\n      0xb29f73606f7f20a6, 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e,\n      0x9cbf605e3fd9de8a, 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5,\n      0xf4b327fe0fc73c37, 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d,\n      0xd5af05dd3eff9556, 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c,\n      0x58d3575834956d42, 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3,\n      0x497cabf3431154fc, 0x4e24370570029a8b, 0xd88b5749f090e5ea,\n      0xc651a582a970692f, 0x78fcec2cbb6342f5, 0x463cb745612f55db,\n      0x352ee4ad1816afe3, 0x026ff374c101da7e, 0x811ef0821c3de851,\n      0x6f7e616704c4fa59, 0xa0660379992d58fc, 0x04b0a374a3b795c7,\n      0x915f3445685da798, 0x26802a8ac76571ce, 0x4663352533ce1882,\n      0xb9fdefb4a24dc738, 0x5588ba3a4d6e6c51, 0xa2101a42d35f1956,\n      0x607195a5e200f5fd, 0x7e100308f3290764, 0xe1e5e03c759c0709,\n      0x082572cc5da6606f, 0xcbcf585399e432f1, 0xe8a2be4f8335d8f1,\n      0x0904469acbfee8f2, 0xf08bd31b6daecd51, 0x08e8a1f1a69da69a,\n      0x6542a20aad57bff5, 0x2e9705bb053d6b46, 0xda2fc9db0713c391,\n      0x78e3a810213b6ffb, 0xdc16a59cdd85f8a6, 0xc0932718cd55781f,\n      0xb9bfb29c2b20bfe5, 0xb97289c1be0f2f9c, 0xc0a2a0e403a892d4,\n      0x5524bb834771435b, 0x8265da3d39d1a750, 0xff4af3ab8d1b78c5,\n      0xf0ec5f424bcad77f, 0x66e455f627495189, 0xc82d3120b57e3270,\n      0x3424e47dc22596e3, 0xbc0c95129ccedcdd, 0xc191c595afc4dcbf,\n      0x120392bd2bb70939, 0x7f90650ea6cd6ab4, 0x7287491832695ad3,\n      0xa7c8fac5a7917eb0, 0xd088cb9418be0361, 0x7c1bf9839c7c1ce5,\n      0xe2e991fa58e1e79e, 0x78565cdefd28c4ad, 0x7351b9fef98bafad,\n      0x2a9eac28b08c96bf, 0x6c4f179696cb2225, 0x13a685861bab87e0,\n      0x64c6de5aa0501971, 0x30537425cac70991, 0x01590d9dc6c532b7,\n      0x7e05e3aa8ec720dc, 0x74a07d9c54e3e63f, 0x738184388f3bc1d2,\n      0x26ffdc5067be3acb, 0x6bcdf185561f255f, 0xa0eaf2e1cf99b1c6,\n      0x171df81934f68604, 0x7ea5a21665683e5a, 0x5d1cb02075ba1cea,\n      0x957f38cbd2123fdf, 0xba6364eff80de02f, 0x606e0a0e41d452ee,\n      0x892d8317de82f7a2, 0xe707b1db50f7b43e, 0x4eb28826766fcf5b,\n      0x5a362d56e80a0951, 0x6ee217df16527d78, 0xf6737962ba6b23dd,\n      0x443e63857d4076ca, 0x790d9a5f048adfeb, 0xd796b052151ee94d,\n      0x033ed95c12b04a03, 0x8b833ff84893da5d, 0x3d6724b1bb15eab9,\n      0x9877c4225061ca76, 0xd68d6810adf74fb3, 0x42e5352fe30ce989,\n      0x265b565a7431fde7, 0x3cdbf7e358df4b8b, 0x2922a47f6d3e8779,\n      0x52d2242f65b37f88, 0x5d836d6e2958d6b5, 0x29d40f00566d5e26,\n      0x288db0e1124b14a0, 0x6c056608b7d9c1b6, 0x0b9471bdb8f19d32,\n      0x8fb946504faa6c9d, 0x8943a9464540251c, 0xfd1fe27d144a09e0,\n      0xea6ac458da141bda, 0x8048f217633fce36, 0xfeda1384ade74d31,\n      0x4334b8b02ff7612f, 0xdbc8441f5227e216, 0x096d119a3605c85b,\n      0x2b72b31c21b7d7d0};\n\n  randen_u64 engine;\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%016lx, \", engine());\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed();\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(RandenTest, VerifyGoldenRanden64Seeded) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0x83a9e58f94d3dcd5, 0x70bbdff3d97949fb, 0x0438481f7471c1b4,\n      0x34fdc58ee5fb5930, 0xceee4f2d2a937d17, 0xb5a26a68e432aea9,\n      0x8b64774a3fb51740, 0xd89ac1fc74249c74, 0x03910d1d23fc3fdf,\n      0xd38f630878aa897f, 0x0ee8f0f5615f7e44, 0x98f5a53df8279d52,\n      0xb403f52c25938d0e, 0x240072996ea6e838, 0xd3a791246190fa61,\n      0xaaedd3df7a7b4f80, 0xc6eacabe05deaf6e, 0xb7967dd8790edf4d,\n      0x9a0a8e67e049d279, 0x0494f606aebc23e7, 0x598dcd687bc3e0ee,\n      0x010ac81802d452a1, 0x6407c87160aa2842, 0x5a56e276486f93a0,\n      0xc887a399d46a8f02, 0x9e1e6100fe93b740, 0x12d02e330f8901f6,\n      0xc39ca52b47e790b7, 0xb0b0a2fa11e82e61, 0x1542d841a303806a,\n      0x1fe659fd7d6e9d86, 0xb8c90d80746541ac, 0x239d56a5669ddc94,\n      0xd40db57c8123d13c, 0x3abc2414153a0db0, 0x9bad665630cb8d61,\n      0x0bd1fb90ee3f4bbc, 0x8f0b4d7e079b4e42, 0xfa0fb0e0ee59e793,\n      0x51080b283e071100, 0x2c4b9e715081cc15, 0xbe10ed49de4941df,\n      0xf8eaac9d4b1b0d37, 0x4bcce4b54605e139, 0xa64722b76765dda6,\n      0xb9377d738ca28ab5, 0x779fad81a8ccc1af, 0x65cb3ee61ffd3ba7,\n      0xd74e79087862836f, 0xd05b9c584c3f25bf, 0x2ba93a4693579827,\n      0xd81530aff05420ce, 0xec06cea215478621, 0x4b1798a6796d65ad,\n      0xf142f3fb3a6f6fa6, 0x002b7bf7e237b560, 0xf47f2605ef65b4f8,\n      0x9804ec5517effc18, 0xaed3d7f8b7d481cd, 0x5651c24c1ce338d1,\n      0x3e7a38208bf0a3c6, 0x6796a7b614534aed, 0x0d0f3b848358460f,\n      0x0fa5fe7600b19524, 0x2b0cf38253faaedc, 0x10df9188233a9fd6,\n      0x3a10033880138b59, 0x5fb0b0d23948e80f, 0x9e76f7b02fbf5350,\n      0x0816052304b1a985, 0x30c9880db41fd218, 0x14aa399b65e20f28,\n      0xe1454a8cace787b4, 0x325ac971b6c6f0f5, 0x716b1aa2784f3d36,\n      0x3d5ce14accfd144f, 0x6c0c97710f651792, 0xbc5b0f59fb333532,\n      0x2a90a7d2140470bc, 0x8da269f55c1e1c8d, 0xcfc37143895792ca,\n      0xbe21eab1f30b238f, 0x8c47229dee4d65fd, 0x5743614ed1ed7d54,\n      0x351372a99e9c476e, 0x2bd5ea15e5db085f, 0x6925fde46e0af4ca,\n      0xed3eda2bdc1f45bd, 0xdef68c68d460fa6e, 0xe42a0de76253e2b5,\n      0x4e5176dcbc29c305, 0xbfd85fba9f810f6e, 0x76a5a2a9beb815c6,\n      0x01edc4ddceaf414c, 0xa4e98904b4bb3b4b, 0x00bd63ac7d2f1ddd,\n      0xb8491fe6e998ddbb, 0xb386a3463dda6800, 0x0081887688871619,\n      0x33d394b3344e9a38, 0x815dba65a3a8baf9, 0x4232f6ec02c2fd1a,\n      0xb5cff603edd20834, 0x580189243f687663, 0xa8d5a2cbdc27fe99,\n      0x725d881693fa0131, 0xa2be2c13db2c7ac5, 0x7b6a9614b509fd78,\n      0xb6b136d71e717636, 0x660f1a71aff046ea, 0x0ba10ae346c8ec9e,\n      0xe66dde53e3145b41, 0x3b18288c88c26be6, 0x4d9d9d2ff02db933,\n      0x4167da8c70f46e8a, 0xf183beef8c6318b4, 0x4d889e1e71eeeef1,\n      0x7175c71ad6689b6b, 0xfb9e42beacd1b7dd, 0xc33d0e91b29b5e0d,\n      0xd39b83291ce47922, 0xc4d570fb8493d12e, 0x23d5a5724f424ae6,\n      0x5245f161876b6616, 0x38d77dbd21ab578d, 0x9c3423311f4ecbfe,\n      0x76fe31389bacd9d5,\n  };\n\n  ExplicitSeedSeq seed_sequence{12, 34, 56};\n  randen_u64 engine(seed_sequence);\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%016lx, \", engine());\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed(seed_sequence);\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(RandenTest, VerifyGoldenRanden32Default) {\n  constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = {\n      0x4e433977, 0xc3c14f13, 0xd90410ee, 0xdda9f47c, 0x7fd8ca10, 0x887bf308,\n      0x45c72912, 0xf0b780f5, 0x7696599f, 0x15dbb1d3, 0xff3c6d59, 0x30ec63ba,\n      0x6f7f20a6, 0xb29f7360, 0x6f49a54c, 0x02808a31, 0xd5c8e50e, 0x3b8feaf9,\n      0x3fd9de8a, 0x9cbf605e, 0x78183bbb, 0xc970ae1a, 0x56301ed5, 0xd8b2ffd3,\n      0x0fc73c37, 0xf4b327fe, 0xeb8f9a19, 0xcdfd8d76, 0x91420c9d, 0xc3a506eb,\n      0x3eff9556, 0xd5af05dd, 0x8f83c4a1, 0x48db1bb7, 0x0d6bfe8c, 0x7023920e,\n      0x34956d42, 0x58d35758, 0x6b87b840, 0xed1ef4c2, 0x3e0b2df3, 0x8eef32a2,\n      0x431154fc, 0x497cabf3, 0x70029a8b, 0x4e243705, 0xf090e5ea, 0xd88b5749,\n      0xa970692f, 0xc651a582, 0xbb6342f5, 0x78fcec2c, 0x612f55db, 0x463cb745,\n      0x1816afe3, 0x352ee4ad, 0xc101da7e, 0x026ff374, 0x1c3de851, 0x811ef082,\n      0x04c4fa59, 0x6f7e6167, 0x992d58fc, 0xa0660379, 0xa3b795c7, 0x04b0a374,\n      0x685da798, 0x915f3445, 0xc76571ce, 0x26802a8a, 0x33ce1882, 0x46633525,\n      0xa24dc738, 0xb9fdefb4, 0x4d6e6c51, 0x5588ba3a, 0xd35f1956, 0xa2101a42,\n      0xe200f5fd, 0x607195a5, 0xf3290764, 0x7e100308, 0x759c0709, 0xe1e5e03c,\n      0x5da6606f, 0x082572cc, 0x99e432f1, 0xcbcf5853, 0x8335d8f1, 0xe8a2be4f,\n      0xcbfee8f2, 0x0904469a, 0x6daecd51, 0xf08bd31b, 0xa69da69a, 0x08e8a1f1,\n      0xad57bff5, 0x6542a20a, 0x053d6b46, 0x2e9705bb, 0x0713c391, 0xda2fc9db,\n      0x213b6ffb, 0x78e3a810, 0xdd85f8a6, 0xdc16a59c, 0xcd55781f, 0xc0932718,\n      0x2b20bfe5, 0xb9bfb29c, 0xbe0f2f9c, 0xb97289c1, 0x03a892d4, 0xc0a2a0e4,\n      0x4771435b, 0x5524bb83, 0x39d1a750, 0x8265da3d, 0x8d1b78c5, 0xff4af3ab,\n      0x4bcad77f, 0xf0ec5f42, 0x27495189, 0x66e455f6, 0xb57e3270, 0xc82d3120,\n      0xc22596e3, 0x3424e47d, 0x9ccedcdd, 0xbc0c9512, 0xafc4dcbf, 0xc191c595,\n      0x2bb70939, 0x120392bd, 0xa6cd6ab4, 0x7f90650e, 0x32695ad3, 0x72874918,\n      0xa7917eb0, 0xa7c8fac5, 0x18be0361, 0xd088cb94, 0x9c7c1ce5, 0x7c1bf983,\n      0x58e1e79e, 0xe2e991fa, 0xfd28c4ad, 0x78565cde, 0xf98bafad, 0x7351b9fe,\n      0xb08c96bf, 0x2a9eac28, 0x96cb2225, 0x6c4f1796, 0x1bab87e0, 0x13a68586,\n      0xa0501971, 0x64c6de5a, 0xcac70991, 0x30537425, 0xc6c532b7, 0x01590d9d,\n      0x8ec720dc, 0x7e05e3aa, 0x54e3e63f, 0x74a07d9c, 0x8f3bc1d2, 0x73818438,\n      0x67be3acb, 0x26ffdc50, 0x561f255f, 0x6bcdf185, 0xcf99b1c6, 0xa0eaf2e1,\n      0x34f68604, 0x171df819, 0x65683e5a, 0x7ea5a216, 0x75ba1cea, 0x5d1cb020,\n      0xd2123fdf, 0x957f38cb, 0xf80de02f, 0xba6364ef, 0x41d452ee, 0x606e0a0e,\n      0xde82f7a2, 0x892d8317, 0x50f7b43e, 0xe707b1db, 0x766fcf5b, 0x4eb28826,\n      0xe80a0951, 0x5a362d56, 0x16527d78, 0x6ee217df, 0xba6b23dd, 0xf6737962,\n      0x7d4076ca, 0x443e6385, 0x048adfeb, 0x790d9a5f, 0x151ee94d, 0xd796b052,\n      0x12b04a03, 0x033ed95c, 0x4893da5d, 0x8b833ff8, 0xbb15eab9, 0x3d6724b1,\n      0x5061ca76, 0x9877c422, 0xadf74fb3, 0xd68d6810, 0xe30ce989, 0x42e5352f,\n      0x7431fde7, 0x265b565a, 0x58df4b8b, 0x3cdbf7e3, 0x6d3e8779, 0x2922a47f,\n      0x65b37f88, 0x52d2242f, 0x2958d6b5, 0x5d836d6e, 0x566d5e26, 0x29d40f00,\n      0x124b14a0, 0x288db0e1, 0xb7d9c1b6, 0x6c056608, 0xb8f19d32, 0x0b9471bd,\n      0x4faa6c9d, 0x8fb94650, 0x4540251c, 0x8943a946, 0x144a09e0, 0xfd1fe27d,\n      0xda141bda, 0xea6ac458, 0x633fce36, 0x8048f217, 0xade74d31, 0xfeda1384,\n      0x2ff7612f, 0x4334b8b0, 0x5227e216, 0xdbc8441f, 0x3605c85b, 0x096d119a,\n      0x21b7d7d0, 0x2b72b31c};\n\n  randen_u32 engine;\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) {\n    printf(\"0x%08x, \", engine());\n    if (i % 6 == 5) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed();\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(RandenTest, VerifyGoldenRanden32Seeded) {\n  constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = {\n      0x94d3dcd5, 0x83a9e58f, 0xd97949fb, 0x70bbdff3, 0x7471c1b4, 0x0438481f,\n      0xe5fb5930, 0x34fdc58e, 0x2a937d17, 0xceee4f2d, 0xe432aea9, 0xb5a26a68,\n      0x3fb51740, 0x8b64774a, 0x74249c74, 0xd89ac1fc, 0x23fc3fdf, 0x03910d1d,\n      0x78aa897f, 0xd38f6308, 0x615f7e44, 0x0ee8f0f5, 0xf8279d52, 0x98f5a53d,\n      0x25938d0e, 0xb403f52c, 0x6ea6e838, 0x24007299, 0x6190fa61, 0xd3a79124,\n      0x7a7b4f80, 0xaaedd3df, 0x05deaf6e, 0xc6eacabe, 0x790edf4d, 0xb7967dd8,\n      0xe049d279, 0x9a0a8e67, 0xaebc23e7, 0x0494f606, 0x7bc3e0ee, 0x598dcd68,\n      0x02d452a1, 0x010ac818, 0x60aa2842, 0x6407c871, 0x486f93a0, 0x5a56e276,\n      0xd46a8f02, 0xc887a399, 0xfe93b740, 0x9e1e6100, 0x0f8901f6, 0x12d02e33,\n      0x47e790b7, 0xc39ca52b, 0x11e82e61, 0xb0b0a2fa, 0xa303806a, 0x1542d841,\n      0x7d6e9d86, 0x1fe659fd, 0x746541ac, 0xb8c90d80, 0x669ddc94, 0x239d56a5,\n      0x8123d13c, 0xd40db57c, 0x153a0db0, 0x3abc2414, 0x30cb8d61, 0x9bad6656,\n      0xee3f4bbc, 0x0bd1fb90, 0x079b4e42, 0x8f0b4d7e, 0xee59e793, 0xfa0fb0e0,\n      0x3e071100, 0x51080b28, 0x5081cc15, 0x2c4b9e71, 0xde4941df, 0xbe10ed49,\n      0x4b1b0d37, 0xf8eaac9d, 0x4605e139, 0x4bcce4b5, 0x6765dda6, 0xa64722b7,\n      0x8ca28ab5, 0xb9377d73, 0xa8ccc1af, 0x779fad81, 0x1ffd3ba7, 0x65cb3ee6,\n      0x7862836f, 0xd74e7908, 0x4c3f25bf, 0xd05b9c58, 0x93579827, 0x2ba93a46,\n      0xf05420ce, 0xd81530af, 0x15478621, 0xec06cea2, 0x796d65ad, 0x4b1798a6,\n      0x3a6f6fa6, 0xf142f3fb, 0xe237b560, 0x002b7bf7, 0xef65b4f8, 0xf47f2605,\n      0x17effc18, 0x9804ec55, 0xb7d481cd, 0xaed3d7f8, 0x1ce338d1, 0x5651c24c,\n      0x8bf0a3c6, 0x3e7a3820, 0x14534aed, 0x6796a7b6, 0x8358460f, 0x0d0f3b84,\n      0x00b19524, 0x0fa5fe76, 0x53faaedc, 0x2b0cf382, 0x233a9fd6, 0x10df9188,\n      0x80138b59, 0x3a100338, 0x3948e80f, 0x5fb0b0d2, 0x2fbf5350, 0x9e76f7b0,\n      0x04b1a985, 0x08160523, 0xb41fd218, 0x30c9880d, 0x65e20f28, 0x14aa399b,\n      0xace787b4, 0xe1454a8c, 0xb6c6f0f5, 0x325ac971, 0x784f3d36, 0x716b1aa2,\n      0xccfd144f, 0x3d5ce14a, 0x0f651792, 0x6c0c9771, 0xfb333532, 0xbc5b0f59,\n      0x140470bc, 0x2a90a7d2, 0x5c1e1c8d, 0x8da269f5, 0x895792ca, 0xcfc37143,\n      0xf30b238f, 0xbe21eab1, 0xee4d65fd, 0x8c47229d, 0xd1ed7d54, 0x5743614e,\n      0x9e9c476e, 0x351372a9, 0xe5db085f, 0x2bd5ea15, 0x6e0af4ca, 0x6925fde4,\n      0xdc1f45bd, 0xed3eda2b, 0xd460fa6e, 0xdef68c68, 0x6253e2b5, 0xe42a0de7,\n      0xbc29c305, 0x4e5176dc, 0x9f810f6e, 0xbfd85fba, 0xbeb815c6, 0x76a5a2a9,\n      0xceaf414c, 0x01edc4dd, 0xb4bb3b4b, 0xa4e98904, 0x7d2f1ddd, 0x00bd63ac,\n      0xe998ddbb, 0xb8491fe6, 0x3dda6800, 0xb386a346, 0x88871619, 0x00818876,\n      0x344e9a38, 0x33d394b3, 0xa3a8baf9, 0x815dba65, 0x02c2fd1a, 0x4232f6ec,\n      0xedd20834, 0xb5cff603, 0x3f687663, 0x58018924, 0xdc27fe99, 0xa8d5a2cb,\n      0x93fa0131, 0x725d8816, 0xdb2c7ac5, 0xa2be2c13, 0xb509fd78, 0x7b6a9614,\n      0x1e717636, 0xb6b136d7, 0xaff046ea, 0x660f1a71, 0x46c8ec9e, 0x0ba10ae3,\n      0xe3145b41, 0xe66dde53, 0x88c26be6, 0x3b18288c, 0xf02db933, 0x4d9d9d2f,\n      0x70f46e8a, 0x4167da8c, 0x8c6318b4, 0xf183beef, 0x71eeeef1, 0x4d889e1e,\n      0xd6689b6b, 0x7175c71a, 0xacd1b7dd, 0xfb9e42be, 0xb29b5e0d, 0xc33d0e91,\n      0x1ce47922, 0xd39b8329, 0x8493d12e, 0xc4d570fb, 0x4f424ae6, 0x23d5a572,\n      0x876b6616, 0x5245f161, 0x21ab578d, 0x38d77dbd, 0x1f4ecbfe, 0x9c342331,\n      0x9bacd9d5, 0x76fe3138,\n  };\n\n  ExplicitSeedSeq seed_sequence{12, 34, 56};\n  randen_u32 engine(seed_sequence);\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) {\n    printf(\"0x%08x, \", engine());\n    if (i % 6 == 5) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n  engine.seed(seed_sequence);\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(RandenTest, VerifyGoldenFromDeserializedEngine) {\n  constexpr uint64_t kGolden[kNumGoldenOutputs] = {\n      0x067f9f9ab919657a, 0x0534605912988583, 0x8a303f72feaa673f,\n      0x77b7fd747909185c, 0xd9af90403c56d891, 0xd939c6cb204d14b5,\n      0x7fbe6b954a47b483, 0x8b31a47cc34c768d, 0x3a9e546da2701a9c,\n      0x5246539046253e71, 0x417191ffb2a848a1, 0x7b1c7bf5a5001d09,\n      0x9489b15d194f2361, 0xfcebdeea3bcd2461, 0xd643027c854cec97,\n      0x5885397f91e0d21c, 0x53173b0efae30d58, 0x1c9c71168449fac1,\n      0xe358202b711ed8aa, 0x94e3918ed1d8227c, 0x5bb4e251450144cf,\n      0xb5c7a519b489af3b, 0x6f8b560b1f7b3469, 0xfde11dd4a1c74eef,\n      0x33383d2f76457dcf, 0x3060c0ec6db9fce1, 0x18f451fcddeec766,\n      0xe73c5d6b9f26da2a, 0x8d4cc566671b32a4, 0xb8189b73776bc9ff,\n      0x497a70f9caf0bc23, 0x23afcc509791dcea, 0x18af70dc4b27d306,\n      0xd3853f955a0ce5b9, 0x441db6c01a0afb17, 0xd0136c3fb8e1f13f,\n      0x5e4fd6fc2f33783c, 0xe0d24548adb5da51, 0x0f4d8362a7d3485a,\n      0x9f572d68270fa563, 0x6351fbc823024393, 0xa66dbfc61810e9ab,\n      0x0ff17fc14b651af8, 0xd74c55dafb99e623, 0x36303bc1ad85c6c2,\n      0x4920cd6a2af7e897, 0x0b8848addc30fecd, 0x9e1562eda6488e93,\n      0x197553807d607828, 0xbef5eaeda5e21235, 0x18d91d2616aca527,\n      0xb7821937f5c873cd, 0x2cd4ae5650dbeefc, 0xb35a64376f75ffdf,\n      0x9226d414d647fe07, 0x663f3db455bbb35e, 0xa829eead6ae93247,\n      0x7fd69c204dd0d25f, 0xbe1411f891c9acb1, 0xd476f34a506d5f11,\n      0xf423d2831649c5ca, 0x1e503962951abd75, 0xeccc9e8b1e34b537,\n      0xb11a147294044854, 0xc4cf27f0abf4929d, 0xe9193abf6fa24c8c,\n      0xa94a259e3aba8808, 0x21dc414197deffa3, 0xa2ae211d1ff622ae,\n      0xfe3995c46be5a4f4, 0xe9984c284bf11128, 0xcb1ce9d2f0851a80,\n      0x42fee17971d87cd8, 0xac76a98d177adc88, 0xa0973b3dedc4af6f,\n      0xdf56d6bbcb1b8e86, 0xf1e6485f407b11c9, 0x2c63de4deccb15c0,\n      0x6fe69db32ed4fad7, 0xaa51a65f84bca1f1, 0x242f2ee81d608afc,\n      0x8eb88b2b69fc153b, 0x22c20098baf73fd1, 0x57759466f576488c,\n      0x075ca562cea1be9d, 0x9a74814d73d28891, 0x73d1555fc02f4d3d,\n      0xc17f8f210ee89337, 0x46cca7999eaeafd4, 0x5db8d6a327a0d8ac,\n      0xb79b4f93c738d7a1, 0x9994512f0036ded1, 0xd3883026f38747f4,\n      0xf31f7458078d097c, 0x736ce4d480680669, 0x7a496f4c7e1033e3,\n      0xecf85bf297fbc68c, 0x9e37e1d0f24f3c4e, 0x15b6e067ca0746fc,\n      0xdd4a39905c5db81c, 0xb5dfafa7bcfdf7da, 0xca6646fb6f92a276,\n      0x1c6b35f363ef0efd, 0x6a33d06037ad9f76, 0x45544241afd8f80f,\n      0x83f8d83f859c90c5, 0x22aea9c5365e8c19, 0xfac35b11f20b6a6a,\n      0xd1acf49d1a27dd2f, 0xf281cd09c4fed405, 0x076000a42cd38e4f,\n      0x6ace300565070445, 0x463a62781bddc4db, 0x1477126b46b569ac,\n      0x127f2bb15035fbb8, 0xdfa30946049c04a8, 0x89072a586ba8dd3e,\n      0x62c809582bb7e74d, 0x22c0c3641406c28b, 0x9b66e36c47ff004d,\n      0xb9cd2c7519653330, 0x18608d79cd7a598d, 0x92c0bd1323e53e32,\n      0x887ff00de8524aa5, 0xa074410b787abd10, 0x18ab41b8057a2063,\n      0x1560abf26bc5f987};\n\n#if UPDATE_GOLDEN\n  (void)kGolden;  // Silence warning.\n  std::seed_seq seed_sequence{1, 2, 3, 4, 5};\n  randen_u64 engine(seed_sequence);\n  std::ostringstream stream;\n  stream << engine;\n  auto str = stream.str();\n  printf(\"%s\\n\\n\", str.c_str());\n  for (size_t i = 0; i < kNumGoldenOutputs; ++i) {\n    printf(\"0x%016lx, \", engine());\n    if (i % 3 == 2) {\n      printf(\"\\n\");\n    }\n  }\n  printf(\"\\n\\n\\n\");\n#else\n  randen_u64 engine;\n  std::istringstream stream(\n      \"0 0 9824501439887287479 3242284395352394785 243836530774933777 \"\n      \"4047941804708365596 17165468127298385802 949276103645889255 \"\n      \"10659970394998657921 1657570836810929787 11697746266668051452 \"\n      \"9967209969299905230 14140390331161524430 7383014124183271684 \"\n      \"13146719127702337852 13983155220295807171 11121125587542359264 \"\n      \"195757810993252695 17138580243103178492 11326030747260920501 \"\n      \"8585097322474965590 18342582839328350995 15052982824209724634 \"\n      \"7321861343874683609 1806786911778767826 10100850842665572955 \"\n      \"9249328950653985078 13600624835326909759 11137960060943860251 \"\n      \"10208781341792329629 9282723971471525577 16373271619486811032 32\");\n  stream >> engine;\n  for (const auto& elem : kGolden) {\n    EXPECT_EQ(elem, engine());\n  }\n#endif\n}\n\nTEST(RandenTest, IsFastOrSlow) {\n  // randen_engine typically costs ~5ns per value for the optimized code paths,\n  // and the ~1000ns per value for slow code paths.  However when running under\n  // msan, asan, etc. it can take much longer.\n  //\n  // The estimated operation time is something like:\n  //\n  // linux, optimized ~5ns\n  // ppc, optimized ~7ns\n  //\n  // `kCount` is chosen below so that, in debug builds and without hardware\n  // acceleration, the test (assuming ~1us per call) should finish in ~0.1s\n  static constexpr size_t kCount = 100000;\n  randen_u64 engine;\n  randen_u64::result_type sum = 0;\n  auto start = absl::GetCurrentTimeNanos();\n  for (int i = 0; i < kCount; i++) {\n    sum += engine();\n  }\n  auto duration = absl::GetCurrentTimeNanos() - start;\n\n  LOG(INFO) << static_cast<double>(duration) / static_cast<double>(kCount)\n            << \"ns\";\n\n  EXPECT_GT(sum, 0);\n  EXPECT_GE(duration, kCount);  // Should be slower than 1ns per call.\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/randen_hwaes.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate\n// symbols from arbitrary system and other headers, since it may be built\n// with different flags from other targets, using different levels of\n// optimization, potentially introducing ODR violations.\n\n#include \"absl/random/internal/randen_hwaes.h\"\n\n#include <cstdint>\n#include <cstring>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/internal/platform.h\"\n#include \"absl/random/internal/randen_traits.h\"\n\n// ABSL_RANDEN_HWAES_IMPL indicates whether this file will contain\n// a hardware accelerated implementation of randen, or whether it\n// will contain stubs that exit the process.\n#if ABSL_HAVE_ACCELERATED_AES\n// The following platforms have implemented RandenHwAes.\n#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) || \\\n    defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) ||       \\\n    defined(ABSL_ARCH_AARCH64)\n#define ABSL_RANDEN_HWAES_IMPL 1\n#endif\n#endif\n\n#if !defined(ABSL_RANDEN_HWAES_IMPL)\n// No accelerated implementation is supported.\n// The RandenHwAes functions are stubs that print an error and exit.\n\n#include <cstdio>\n#include <cstdlib>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// No accelerated implementation.\nbool HasRandenHwAesImplementation() { return false; }\n\n// NOLINTNEXTLINE\nconst void* RandenHwAes::GetKeys() {\n  // Attempted to dispatch to an unsupported dispatch target.\n  const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;\n  fprintf(stderr, \"AES Hardware detection failed (%d).\\n\", d);\n  exit(1);\n  return nullptr;\n}\n\n// NOLINTNEXTLINE\nvoid RandenHwAes::Absorb(const void*, void*) {\n  // Attempted to dispatch to an unsupported dispatch target.\n  const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;\n  fprintf(stderr, \"AES Hardware detection failed (%d).\\n\", d);\n  exit(1);\n}\n\n// NOLINTNEXTLINE\nvoid RandenHwAes::Generate(const void*, void*) {\n  // Attempted to dispatch to an unsupported dispatch target.\n  const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;\n  fprintf(stderr, \"AES Hardware detection failed (%d).\\n\", d);\n  exit(1);\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#else  // defined(ABSL_RANDEN_HWAES_IMPL)\n//\n// Accelerated implementations are supported.\n// We need the per-architecture includes and defines.\n//\nnamespace {\n\nusing absl::random_internal::RandenTraits;\n\n}  // namespace\n\n// TARGET_CRYPTO defines a crypto attribute for each architecture.\n//\n// NOTE: Evaluate whether we should eliminate ABSL_TARGET_CRYPTO.\n#if (defined(__clang__) || defined(__GNUC__))\n#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)\n#define ABSL_TARGET_CRYPTO __attribute__((target(\"aes\")))\n#elif defined(ABSL_ARCH_PPC)\n#define ABSL_TARGET_CRYPTO __attribute__((target(\"crypto\")))\n#else\n#define ABSL_TARGET_CRYPTO\n#endif\n#else\n#define ABSL_TARGET_CRYPTO\n#endif\n\n#if defined(ABSL_ARCH_PPC)\n// NOTE: Keep in mind that PPC can operate in little-endian or big-endian mode,\n// however the PPC altivec vector registers (and thus the AES instructions)\n// always operate in big-endian mode.\n\n#include <altivec.h>\n// <altivec.h> #defines vector __vector; in C++, this is bad form.\n#undef vector\n#undef bool\n\n// Rely on the PowerPC AltiVec vector operations for accelerated AES\n// instructions. GCC support of the PPC vector types is described in:\n// https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/PowerPC-AltiVec_002fVSX-Built-in-Functions.html\n//\n// Already provides operator^=.\nusing Vector128 = __vector unsigned long long;  // NOLINT(runtime/int)\n\nnamespace {\ninline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(const Vector128& v) {\n  // Reverses the bytes of the vector.\n  const __vector unsigned char perm = {15, 14, 13, 12, 11, 10, 9, 8,\n                                       7,  6,  5,  4,  3,  2,  1, 0};\n  return vec_perm(v, v, perm);\n}\n\n// WARNING: these load/store in native byte order. It is OK to load and then\n// store an unchanged vector, but interpreting the bits as a number or input\n// to AES will have undefined results.\ninline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {\n  return vec_vsx_ld(0, reinterpret_cast<const Vector128*>(from));\n}\n\ninline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {\n  vec_vsx_st(v, 0, reinterpret_cast<Vector128*>(to));\n}\n\n// One round of AES. \"round_key\" is a public constant for breaking the\n// symmetry of AES (ensures previously equal columns differ afterwards).\ninline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,\n                                             const Vector128& round_key) {\n  return Vector128(__builtin_crypto_vcipher(state, round_key));\n}\n\n// Enables native loads in the round loop by pre-swapping.\ninline ABSL_TARGET_CRYPTO void SwapEndian(absl::uint128* state) {\n  for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {\n    Vector128Store(ReverseBytes(Vector128Load(state + block)), state + block);\n  }\n}\n\n}  // namespace\n\n#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)\n\n// Rely on the ARM NEON+Crypto advanced simd types, defined in <arm_neon.h>.\n// uint8x16_t is the user alias for underlying __simd128_uint8_t type.\n// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf\n//\n// <arm_neon> defines the following\n//\n// typedef __attribute__((neon_vector_type(16))) uint8_t uint8x16_t;\n// typedef __attribute__((neon_vector_type(16))) int8_t int8x16_t;\n// typedef __attribute__((neon_polyvector_type(16))) int8_t poly8x16_t;\n//\n// vld1q_v\n// vst1q_v\n// vaeseq_v\n// vaesmcq_v\n#include <arm_neon.h>\n\n// Already provides operator^=.\nusing Vector128 = uint8x16_t;\n\nnamespace {\n\ninline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {\n  return vld1q_u8(reinterpret_cast<const uint8_t*>(from));\n}\n\ninline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {\n  vst1q_u8(reinterpret_cast<uint8_t*>(to), v);\n}\n\n// One round of AES. \"round_key\" is a public constant for breaking the\n// symmetry of AES (ensures previously equal columns differ afterwards).\ninline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,\n                                             const Vector128& round_key) {\n  // It is important to always use the full round function - omitting the\n  // final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf]\n  // and does not help because we never decrypt.\n  //\n  // Note that ARM divides AES instructions differently than x86 / PPC,\n  // And we need to skip the first AddRoundKey step and add an extra\n  // AddRoundKey step to the end. Lucky for us this is just XOR.\n  return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key;\n}\n\ninline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}\n\n}  // namespace\n\n#elif defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)\n// On x86 we rely on the aesni instructions\n#include <immintrin.h>\n\nnamespace {\n\n// Vector128 class is only wrapper for __m128i, benchmark indicates that it's\n// faster than using __m128i directly.\nclass Vector128 {\n public:\n  // Convert from/to intrinsics.\n  inline explicit Vector128(const __m128i& v) : data_(v) {}\n\n  inline __m128i data() const { return data_; }\n\n  inline Vector128& operator^=(const Vector128& other) {\n    data_ = _mm_xor_si128(data_, other.data());\n    return *this;\n  }\n\n private:\n  __m128i data_;\n};\n\ninline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {\n  return Vector128(_mm_load_si128(reinterpret_cast<const __m128i*>(from)));\n}\n\ninline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {\n  _mm_store_si128(reinterpret_cast<__m128i*>(to), v.data());\n}\n\n// One round of AES. \"round_key\" is a public constant for breaking the\n// symmetry of AES (ensures previously equal columns differ afterwards).\ninline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,\n                                             const Vector128& round_key) {\n  // It is important to always use the full round function - omitting the\n  // final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf]\n  // and does not help because we never decrypt.\n  return Vector128(_mm_aesenc_si128(state.data(), round_key.data()));\n}\n\ninline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}\n\n}  // namespace\n\n#endif\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunknown-pragmas\"\n#endif\n\n// At this point, all of the platform-specific features have been defined /\n// implemented.\n//\n// REQUIRES: using Vector128 = ...\n// REQUIRES: Vector128 Vector128Load(void*) {...}\n// REQUIRES: void Vector128Store(Vector128, void*) {...}\n// REQUIRES: Vector128 AesRound(Vector128, Vector128) {...}\n// REQUIRES: void SwapEndian(uint64_t*) {...}\n//\n// PROVIDES: absl::random_internal::RandenHwAes::Absorb\n// PROVIDES: absl::random_internal::RandenHwAes::Generate\nnamespace {\n\n// Block shuffles applies a shuffle to the entire state between AES rounds.\n// Improved odd-even shuffle from \"New criterion for diffusion property\".\ninline ABSL_TARGET_CRYPTO void BlockShuffle(absl::uint128* state) {\n  static_assert(RandenTraits::kFeistelBlocks == 16,\n                \"Expecting 16 FeistelBlocks.\");\n\n  constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {\n      7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};\n\n  const Vector128 v0 = Vector128Load(state + shuffle[0]);\n  const Vector128 v1 = Vector128Load(state + shuffle[1]);\n  const Vector128 v2 = Vector128Load(state + shuffle[2]);\n  const Vector128 v3 = Vector128Load(state + shuffle[3]);\n  const Vector128 v4 = Vector128Load(state + shuffle[4]);\n  const Vector128 v5 = Vector128Load(state + shuffle[5]);\n  const Vector128 v6 = Vector128Load(state + shuffle[6]);\n  const Vector128 v7 = Vector128Load(state + shuffle[7]);\n  const Vector128 w0 = Vector128Load(state + shuffle[8]);\n  const Vector128 w1 = Vector128Load(state + shuffle[9]);\n  const Vector128 w2 = Vector128Load(state + shuffle[10]);\n  const Vector128 w3 = Vector128Load(state + shuffle[11]);\n  const Vector128 w4 = Vector128Load(state + shuffle[12]);\n  const Vector128 w5 = Vector128Load(state + shuffle[13]);\n  const Vector128 w6 = Vector128Load(state + shuffle[14]);\n  const Vector128 w7 = Vector128Load(state + shuffle[15]);\n\n  Vector128Store(v0, state + 0);\n  Vector128Store(v1, state + 1);\n  Vector128Store(v2, state + 2);\n  Vector128Store(v3, state + 3);\n  Vector128Store(v4, state + 4);\n  Vector128Store(v5, state + 5);\n  Vector128Store(v6, state + 6);\n  Vector128Store(v7, state + 7);\n  Vector128Store(w0, state + 8);\n  Vector128Store(w1, state + 9);\n  Vector128Store(w2, state + 10);\n  Vector128Store(w3, state + 11);\n  Vector128Store(w4, state + 12);\n  Vector128Store(w5, state + 13);\n  Vector128Store(w6, state + 14);\n  Vector128Store(w7, state + 15);\n}\n\n// Feistel round function using two AES subrounds. Very similar to F()\n// from Simpira v2, but with independent subround keys. Uses 17 AES rounds\n// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in\n// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel\n// XORs are 'free' (included in the second AES instruction).\ninline ABSL_TARGET_CRYPTO const absl::uint128* FeistelRound(\n    absl::uint128* state,\n    const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {\n  static_assert(RandenTraits::kFeistelBlocks == 16,\n                \"Expecting 16 FeistelBlocks.\");\n\n  // MSVC does a horrible job at unrolling loops.\n  // So we unroll the loop by hand to improve the performance.\n  const Vector128 s0 = Vector128Load(state + 0);\n  const Vector128 s1 = Vector128Load(state + 1);\n  const Vector128 s2 = Vector128Load(state + 2);\n  const Vector128 s3 = Vector128Load(state + 3);\n  const Vector128 s4 = Vector128Load(state + 4);\n  const Vector128 s5 = Vector128Load(state + 5);\n  const Vector128 s6 = Vector128Load(state + 6);\n  const Vector128 s7 = Vector128Load(state + 7);\n  const Vector128 s8 = Vector128Load(state + 8);\n  const Vector128 s9 = Vector128Load(state + 9);\n  const Vector128 s10 = Vector128Load(state + 10);\n  const Vector128 s11 = Vector128Load(state + 11);\n  const Vector128 s12 = Vector128Load(state + 12);\n  const Vector128 s13 = Vector128Load(state + 13);\n  const Vector128 s14 = Vector128Load(state + 14);\n  const Vector128 s15 = Vector128Load(state + 15);\n\n  // Encode even blocks with keys.\n  const Vector128 e0 = AesRound(s0, Vector128Load(keys + 0));\n  const Vector128 e2 = AesRound(s2, Vector128Load(keys + 1));\n  const Vector128 e4 = AesRound(s4, Vector128Load(keys + 2));\n  const Vector128 e6 = AesRound(s6, Vector128Load(keys + 3));\n  const Vector128 e8 = AesRound(s8, Vector128Load(keys + 4));\n  const Vector128 e10 = AesRound(s10, Vector128Load(keys + 5));\n  const Vector128 e12 = AesRound(s12, Vector128Load(keys + 6));\n  const Vector128 e14 = AesRound(s14, Vector128Load(keys + 7));\n\n  // Encode odd blocks with even output from above.\n  const Vector128 o1 = AesRound(e0, s1);\n  const Vector128 o3 = AesRound(e2, s3);\n  const Vector128 o5 = AesRound(e4, s5);\n  const Vector128 o7 = AesRound(e6, s7);\n  const Vector128 o9 = AesRound(e8, s9);\n  const Vector128 o11 = AesRound(e10, s11);\n  const Vector128 o13 = AesRound(e12, s13);\n  const Vector128 o15 = AesRound(e14, s15);\n\n  // Store odd blocks. (These will be shuffled later).\n  Vector128Store(o1, state + 1);\n  Vector128Store(o3, state + 3);\n  Vector128Store(o5, state + 5);\n  Vector128Store(o7, state + 7);\n  Vector128Store(o9, state + 9);\n  Vector128Store(o11, state + 11);\n  Vector128Store(o13, state + 13);\n  Vector128Store(o15, state + 15);\n\n  return keys + 8;\n}\n\n// Cryptographic permutation based via type-2 Generalized Feistel Network.\n// Indistinguishable from ideal by chosen-ciphertext adversaries using less than\n// 2^64 queries if the round function is a PRF. This is similar to the b=8 case\n// of Simpira v2, but more efficient than its generic construction for b=16.\ninline ABSL_TARGET_CRYPTO void Permute(\n    absl::uint128* state,\n    const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {\n  // (Successfully unrolled; the first iteration jumps into the second half)\n#ifdef __clang__\n#pragma clang loop unroll_count(2)\n#endif\n  for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {\n    keys = FeistelRound(state, keys);\n    BlockShuffle(state);\n  }\n}\n\n}  // namespace\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\nbool HasRandenHwAesImplementation() { return true; }\n\nconst void* ABSL_TARGET_CRYPTO RandenHwAes::GetKeys() {\n  // Round keys for one AES per Feistel round and branch.\n  // The canonical implementation uses first digits of Pi.\n#if defined(ABSL_ARCH_PPC)\n  return kRandenRoundKeysBE;\n#else\n  return kRandenRoundKeys;\n#endif\n}\n\n// NOLINTNEXTLINE\nvoid ABSL_TARGET_CRYPTO RandenHwAes::Absorb(const void* seed_void,\n                                            void* state_void) {\n  static_assert(RandenTraits::kCapacityBytes / sizeof(Vector128) == 1,\n                \"Unexpected Randen kCapacityBlocks\");\n  static_assert(RandenTraits::kStateBytes / sizeof(Vector128) == 16,\n                \"Unexpected Randen kStateBlocks\");\n\n  auto* state = reinterpret_cast<absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT>(\n      state_void);\n  const auto* seed =\n      reinterpret_cast<const absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT>(\n          seed_void);\n\n  Vector128 b1 = Vector128Load(state + 1);\n  b1 ^= Vector128Load(seed + 0);\n  Vector128Store(b1, state + 1);\n\n  Vector128 b2 = Vector128Load(state + 2);\n  b2 ^= Vector128Load(seed + 1);\n  Vector128Store(b2, state + 2);\n\n  Vector128 b3 = Vector128Load(state + 3);\n  b3 ^= Vector128Load(seed + 2);\n  Vector128Store(b3, state + 3);\n\n  Vector128 b4 = Vector128Load(state + 4);\n  b4 ^= Vector128Load(seed + 3);\n  Vector128Store(b4, state + 4);\n\n  Vector128 b5 = Vector128Load(state + 5);\n  b5 ^= Vector128Load(seed + 4);\n  Vector128Store(b5, state + 5);\n\n  Vector128 b6 = Vector128Load(state + 6);\n  b6 ^= Vector128Load(seed + 5);\n  Vector128Store(b6, state + 6);\n\n  Vector128 b7 = Vector128Load(state + 7);\n  b7 ^= Vector128Load(seed + 6);\n  Vector128Store(b7, state + 7);\n\n  Vector128 b8 = Vector128Load(state + 8);\n  b8 ^= Vector128Load(seed + 7);\n  Vector128Store(b8, state + 8);\n\n  Vector128 b9 = Vector128Load(state + 9);\n  b9 ^= Vector128Load(seed + 8);\n  Vector128Store(b9, state + 9);\n\n  Vector128 b10 = Vector128Load(state + 10);\n  b10 ^= Vector128Load(seed + 9);\n  Vector128Store(b10, state + 10);\n\n  Vector128 b11 = Vector128Load(state + 11);\n  b11 ^= Vector128Load(seed + 10);\n  Vector128Store(b11, state + 11);\n\n  Vector128 b12 = Vector128Load(state + 12);\n  b12 ^= Vector128Load(seed + 11);\n  Vector128Store(b12, state + 12);\n\n  Vector128 b13 = Vector128Load(state + 13);\n  b13 ^= Vector128Load(seed + 12);\n  Vector128Store(b13, state + 13);\n\n  Vector128 b14 = Vector128Load(state + 14);\n  b14 ^= Vector128Load(seed + 13);\n  Vector128Store(b14, state + 14);\n\n  Vector128 b15 = Vector128Load(state + 15);\n  b15 ^= Vector128Load(seed + 14);\n  Vector128Store(b15, state + 15);\n}\n\n// NOLINTNEXTLINE\nvoid ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys_void,\n                                              void* state_void) {\n  static_assert(RandenTraits::kCapacityBytes == sizeof(Vector128),\n                \"Capacity mismatch\");\n\n  auto* state = reinterpret_cast<absl::uint128*>(state_void);\n  const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);\n\n  const Vector128 prev_inner = Vector128Load(state);\n\n  SwapEndian(state);\n\n  Permute(state, keys);\n\n  SwapEndian(state);\n\n  // Ensure backtracking resistance.\n  Vector128 inner = Vector128Load(state);\n  inner ^= prev_inner;\n  Vector128Store(inner, state);\n}\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // (ABSL_RANDEN_HWAES_IMPL)\n"
  },
  {
    "path": "absl/random/internal/randen_hwaes.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_\n#define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_\n\n#include \"absl/base/config.h\"\n\n// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate\n// symbols from arbitrary system and other headers, since it may be built\n// with different flags from other targets, using different levels of\n// optimization, potentially introducing ODR violations.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// RANDen = RANDom generator or beetroots in Swiss High German.\n// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random\n// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.\n//\n// RandenHwAes implements the basic state manipulation methods.\nclass RandenHwAes {\n public:\n  static void Generate(const void* keys, void* state_void);\n  static void Absorb(const void* seed_void, void* state_void);\n  static const void* GetKeys();\n};\n\n// HasRandenHwAesImplementation returns true when there is an accelerated\n// implementation, and false otherwise.  If there is no implementation,\n// then attempting to use it will abort the program.\nbool HasRandenHwAesImplementation();\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_\n"
  },
  {
    "path": "absl/random/internal/randen_hwaes_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen_hwaes.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/platform.h\"\n#include \"absl/random/internal/randen_detect.h\"\n#include \"absl/random/internal/randen_traits.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace {\n\nusing absl::random_internal::RandenHwAes;\nusing absl::random_internal::RandenTraits;\n\nTEST(RandenHwAesTest, Default) {\n  EXPECT_TRUE(absl::random_internal::CPUSupportsRandenHwAes());\n\n  constexpr uint8_t kGolden[] = {\n      0xee, 0xd3, 0xe6, 0x0e, 0x09, 0x34, 0x65, 0x6c, 0xc6, 0x33, 0x53, 0x9d,\n      0x9b, 0x2b, 0x4e, 0x04, 0x77, 0x39, 0x43, 0x4e, 0x13, 0x4f, 0xc1, 0xc3,\n      0xee, 0x10, 0x04, 0xd9, 0x7c, 0xf4, 0xa9, 0xdd, 0x10, 0xca, 0xd8, 0x7f,\n      0x08, 0xf3, 0x7b, 0x88, 0x12, 0x29, 0xc7, 0x45, 0xf5, 0x80, 0xb7, 0xf0,\n      0x9f, 0x59, 0x96, 0x76, 0xd3, 0xb1, 0xdb, 0x15, 0x59, 0x6d, 0x3c, 0xff,\n      0xba, 0x63, 0xec, 0x30, 0xa6, 0x20, 0x7f, 0x6f, 0x60, 0x73, 0x9f, 0xb2,\n      0x4c, 0xa5, 0x49, 0x6f, 0x31, 0x8a, 0x80, 0x02, 0x0e, 0xe5, 0xc8, 0xd5,\n      0xf9, 0xea, 0x8f, 0x3b, 0x8a, 0xde, 0xd9, 0x3f, 0x5e, 0x60, 0xbf, 0x9c,\n      0xbb, 0x3b, 0x18, 0x78, 0x1a, 0xae, 0x70, 0xc9, 0xd5, 0x1e, 0x30, 0x56,\n      0xd3, 0xff, 0xb2, 0xd8, 0x37, 0x3c, 0xc7, 0x0f, 0xfe, 0x27, 0xb3, 0xf4,\n      0x19, 0x9a, 0x8f, 0xeb, 0x76, 0x8d, 0xfd, 0xcd, 0x9d, 0x0c, 0x42, 0x91,\n      0xeb, 0x06, 0xa5, 0xc3, 0x56, 0x95, 0xff, 0x3e, 0xdd, 0x05, 0xaf, 0xd5,\n      0xa1, 0xc4, 0x83, 0x8f, 0xb7, 0x1b, 0xdb, 0x48, 0x8c, 0xfe, 0x6b, 0x0d,\n      0x0e, 0x92, 0x23, 0x70, 0x42, 0x6d, 0x95, 0x34, 0x58, 0x57, 0xd3, 0x58,\n      0x40, 0xb8, 0x87, 0x6b, 0xc2, 0xf4, 0x1e, 0xed, 0xf3, 0x2d, 0x0b, 0x3e,\n      0xa2, 0x32, 0xef, 0x8e, 0xfc, 0x54, 0x11, 0x43, 0xf3, 0xab, 0x7c, 0x49,\n      0x8b, 0x9a, 0x02, 0x70, 0x05, 0x37, 0x24, 0x4e, 0xea, 0xe5, 0x90, 0xf0,\n      0x49, 0x57, 0x8b, 0xd8, 0x2f, 0x69, 0x70, 0xa9, 0x82, 0xa5, 0x51, 0xc6,\n      0xf5, 0x42, 0x63, 0xbb, 0x2c, 0xec, 0xfc, 0x78, 0xdb, 0x55, 0x2f, 0x61,\n      0x45, 0xb7, 0x3c, 0x46, 0xe3, 0xaf, 0x16, 0x18, 0xad, 0xe4, 0x2e, 0x35,\n      0x7e, 0xda, 0x01, 0xc1, 0x74, 0xf3, 0x6f, 0x02, 0x51, 0xe8, 0x3d, 0x1c,\n      0x82, 0xf0, 0x1e, 0x81,\n  };\n\n  alignas(16) uint8_t state[RandenTraits::kStateBytes];\n  std::memset(state, 0, sizeof(state));\n\n  RandenHwAes::Generate(RandenHwAes::GetKeys(), state);\n  EXPECT_EQ(0, std::memcmp(state, kGolden, sizeof(state)));\n}\n\n}  // namespace\n\nint main(int argc, char* argv[]) {\n  testing::InitGoogleTest(&argc, argv);\n\n  LOG(INFO) << \"ABSL_HAVE_ACCELERATED_AES=\" << ABSL_HAVE_ACCELERATED_AES;\n  LOG(INFO) << \"ABSL_RANDOM_INTERNAL_AES_DISPATCH=\"\n            << ABSL_RANDOM_INTERNAL_AES_DISPATCH;\n\n#if defined(ABSL_ARCH_X86_64)\n  LOG(INFO) << \"ABSL_ARCH_X86_64\";\n#elif defined(ABSL_ARCH_X86_32)\n  LOG(INFO) << \"ABSL_ARCH_X86_32\";\n#elif defined(ABSL_ARCH_AARCH64)\n  LOG(INFO) << \"ABSL_ARCH_AARCH64\";\n#elif defined(ABSL_ARCH_ARM)\n  LOG(INFO) << \"ABSL_ARCH_ARM\";\n#elif defined(ABSL_ARCH_PPC)\n  LOG(INFO) << \"ABSL_ARCH_PPC\";\n#else\n  LOG(INFO) << \"ARCH Unknown\";\n#endif\n\n  int x = absl::random_internal::HasRandenHwAesImplementation();\n  LOG(INFO) << \"HasRandenHwAesImplementation = \" << x;\n\n  int y = absl::random_internal::CPUSupportsRandenHwAes();\n  LOG(INFO) << \"CPUSupportsRandenHwAes = \" << y;\n\n  if (!x || !y) {\n    LOG(INFO) << \"Skipping Randen HWAES tests.\";\n    return 0;\n  }\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "absl/random/internal/randen_round_keys.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen_traits.h\"\n\n// This file contains only the round keys for randen.\n//\n// \"Nothing up my sleeve\" numbers from the first hex digits of Pi, obtained\n// from http://hexpi.sourceforge.net/. The array was generated by following\n// Python script:\n\n/*\npython >tmp.cc << EOF\n\"\"\"Generates Randen round keys array from pi-hex.62500.txt file.\"\"\"\nimport binascii\n\nKEYS = 17 * 8\n\ndef chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i + n]\n\ndef pairwise(t):\n    \"\"\"Transforms sequence into sequence of pairs.\"\"\"\n    it = iter(t)\n    return zip(it,it)\n\ndef digits_from_pi():\n  \"\"\"Reads digits from hexpi.sourceforge.net file.\"\"\"\n  with open(\"pi-hex.62500.txt\") as file:\n    return file.read()\n\ndef digits_from_urandom():\n  \"\"\"Reads digits from /dev/urandom.\"\"\"\n  with open(\"/dev/urandom\") as file:\n    return binascii.hexlify(file.read(KEYS * 16))\n\ndef print_row(b)\n  print(\"  0x{0}, 0x{1}, 0x{2}, 0x{3}, 0x{4}, 0x{5}, 0x{6}, 0x{7}, 0x{8}, 0x{9},\n0x{10}, 0x{11}, 0x{12}, 0x{13}, 0x{14}, 0x{15},\".format(*b))\n\n\ndigits = digits_from_pi()\n#digits = digits_from_urandom()\n\nprint(\"namespace {\")\nprint(\"static constexpr size_t kKeyBytes = {0};\\n\".format(KEYS * 16))\nprint(\"}\")\n\nprint(\"alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {\")\n\nfor i, u16 in zip(range(KEYS), chunks(digits, 32)):\n  b = list(chunks(u16, 2))\n  print_row(b)\n\nprint(\"};\")\n\nprint(\"alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {\")\n\nfor i, u16 in zip(range(KEYS), chunks(digits, 32)):\n  b = list(chunks(u16, 2))\n  b.reverse()\n  print_row(b)\n\nprint(\"};\")\n\nEOF\n\n*/\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\nstatic constexpr size_t kKeyBytes = 2176;\n}\n\nalignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {\n    0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E,\n    0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,\n    0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, 0x45, 0x28, 0x21, 0xE6,\n    0x38, 0xD0, 0x13, 0x77, 0xBE, 0x54, 0x66, 0xCF, 0x34, 0xE9, 0x0C, 0x6C,\n    0xC0, 0xAC, 0x29, 0xB7, 0xC9, 0x7C, 0x50, 0xDD, 0x3F, 0x84, 0xD5, 0xB5,\n    0xB5, 0x47, 0x09, 0x17, 0x92, 0x16, 0xD5, 0xD9, 0x89, 0x79, 0xFB, 0x1B,\n    0xD1, 0x31, 0x0B, 0xA6, 0x98, 0xDF, 0xB5, 0xAC, 0x2F, 0xFD, 0x72, 0xDB,\n    0xD0, 0x1A, 0xDF, 0xB7, 0xB8, 0xE1, 0xAF, 0xED, 0x6A, 0x26, 0x7E, 0x96,\n    0xBA, 0x7C, 0x90, 0x45, 0xF1, 0x2C, 0x7F, 0x99, 0x24, 0xA1, 0x99, 0x47,\n    0xB3, 0x91, 0x6C, 0xF7, 0x08, 0x01, 0xF2, 0xE2, 0x85, 0x8E, 0xFC, 0x16,\n    0x63, 0x69, 0x20, 0xD8, 0x71, 0x57, 0x4E, 0x69, 0xA4, 0x58, 0xFE, 0xA3,\n    0xF4, 0x93, 0x3D, 0x7E, 0x0D, 0x95, 0x74, 0x8F, 0x72, 0x8E, 0xB6, 0x58,\n    0x71, 0x8B, 0xCD, 0x58, 0x82, 0x15, 0x4A, 0xEE, 0x7B, 0x54, 0xA4, 0x1D,\n    0xC2, 0x5A, 0x59, 0xB5, 0x9C, 0x30, 0xD5, 0x39, 0x2A, 0xF2, 0x60, 0x13,\n    0xC5, 0xD1, 0xB0, 0x23, 0x28, 0x60, 0x85, 0xF0, 0xCA, 0x41, 0x79, 0x18,\n    0xB8, 0xDB, 0x38, 0xEF, 0x8E, 0x79, 0xDC, 0xB0, 0x60, 0x3A, 0x18, 0x0E,\n    0x6C, 0x9E, 0x0E, 0x8B, 0xB0, 0x1E, 0x8A, 0x3E, 0xD7, 0x15, 0x77, 0xC1,\n    0xBD, 0x31, 0x4B, 0x27, 0x78, 0xAF, 0x2F, 0xDA, 0x55, 0x60, 0x5C, 0x60,\n    0xE6, 0x55, 0x25, 0xF3, 0xAA, 0x55, 0xAB, 0x94, 0x57, 0x48, 0x98, 0x62,\n    0x63, 0xE8, 0x14, 0x40, 0x55, 0xCA, 0x39, 0x6A, 0x2A, 0xAB, 0x10, 0xB6,\n    0xB4, 0xCC, 0x5C, 0x34, 0x11, 0x41, 0xE8, 0xCE, 0xA1, 0x54, 0x86, 0xAF,\n    0x7C, 0x72, 0xE9, 0x93, 0xB3, 0xEE, 0x14, 0x11, 0x63, 0x6F, 0xBC, 0x2A,\n    0x2B, 0xA9, 0xC5, 0x5D, 0x74, 0x18, 0x31, 0xF6, 0xCE, 0x5C, 0x3E, 0x16,\n    0x9B, 0x87, 0x93, 0x1E, 0xAF, 0xD6, 0xBA, 0x33, 0x6C, 0x24, 0xCF, 0x5C,\n    0x7A, 0x32, 0x53, 0x81, 0x28, 0x95, 0x86, 0x77, 0x3B, 0x8F, 0x48, 0x98,\n    0x6B, 0x4B, 0xB9, 0xAF, 0xC4, 0xBF, 0xE8, 0x1B, 0x66, 0x28, 0x21, 0x93,\n    0x61, 0xD8, 0x09, 0xCC, 0xFB, 0x21, 0xA9, 0x91, 0x48, 0x7C, 0xAC, 0x60,\n    0x5D, 0xEC, 0x80, 0x32, 0xEF, 0x84, 0x5D, 0x5D, 0xE9, 0x85, 0x75, 0xB1,\n    0xDC, 0x26, 0x23, 0x02, 0xEB, 0x65, 0x1B, 0x88, 0x23, 0x89, 0x3E, 0x81,\n    0xD3, 0x96, 0xAC, 0xC5, 0x0F, 0x6D, 0x6F, 0xF3, 0x83, 0xF4, 0x42, 0x39,\n    0x2E, 0x0B, 0x44, 0x82, 0xA4, 0x84, 0x20, 0x04, 0x69, 0xC8, 0xF0, 0x4A,\n    0x9E, 0x1F, 0x9B, 0x5E, 0x21, 0xC6, 0x68, 0x42, 0xF6, 0xE9, 0x6C, 0x9A,\n    0x67, 0x0C, 0x9C, 0x61, 0xAB, 0xD3, 0x88, 0xF0, 0x6A, 0x51, 0xA0, 0xD2,\n    0xD8, 0x54, 0x2F, 0x68, 0x96, 0x0F, 0xA7, 0x28, 0xAB, 0x51, 0x33, 0xA3,\n    0x6E, 0xEF, 0x0B, 0x6C, 0x13, 0x7A, 0x3B, 0xE4, 0xBA, 0x3B, 0xF0, 0x50,\n    0x7E, 0xFB, 0x2A, 0x98, 0xA1, 0xF1, 0x65, 0x1D, 0x39, 0xAF, 0x01, 0x76,\n    0x66, 0xCA, 0x59, 0x3E, 0x82, 0x43, 0x0E, 0x88, 0x8C, 0xEE, 0x86, 0x19,\n    0x45, 0x6F, 0x9F, 0xB4, 0x7D, 0x84, 0xA5, 0xC3, 0x3B, 0x8B, 0x5E, 0xBE,\n    0xE0, 0x6F, 0x75, 0xD8, 0x85, 0xC1, 0x20, 0x73, 0x40, 0x1A, 0x44, 0x9F,\n    0x56, 0xC1, 0x6A, 0xA6, 0x4E, 0xD3, 0xAA, 0x62, 0x36, 0x3F, 0x77, 0x06,\n    0x1B, 0xFE, 0xDF, 0x72, 0x42, 0x9B, 0x02, 0x3D, 0x37, 0xD0, 0xD7, 0x24,\n    0xD0, 0x0A, 0x12, 0x48, 0xDB, 0x0F, 0xEA, 0xD3, 0x49, 0xF1, 0xC0, 0x9B,\n    0x07, 0x53, 0x72, 0xC9, 0x80, 0x99, 0x1B, 0x7B, 0x25, 0xD4, 0x79, 0xD8,\n    0xF6, 0xE8, 0xDE, 0xF7, 0xE3, 0xFE, 0x50, 0x1A, 0xB6, 0x79, 0x4C, 0x3B,\n    0x97, 0x6C, 0xE0, 0xBD, 0x04, 0xC0, 0x06, 0xBA, 0xC1, 0xA9, 0x4F, 0xB6,\n    0x40, 0x9F, 0x60, 0xC4, 0x5E, 0x5C, 0x9E, 0xC2, 0x19, 0x6A, 0x24, 0x63,\n    0x68, 0xFB, 0x6F, 0xAF, 0x3E, 0x6C, 0x53, 0xB5, 0x13, 0x39, 0xB2, 0xEB,\n    0x3B, 0x52, 0xEC, 0x6F, 0x6D, 0xFC, 0x51, 0x1F, 0x9B, 0x30, 0x95, 0x2C,\n    0xCC, 0x81, 0x45, 0x44, 0xAF, 0x5E, 0xBD, 0x09, 0xBE, 0xE3, 0xD0, 0x04,\n    0xDE, 0x33, 0x4A, 0xFD, 0x66, 0x0F, 0x28, 0x07, 0x19, 0x2E, 0x4B, 0xB3,\n    0xC0, 0xCB, 0xA8, 0x57, 0x45, 0xC8, 0x74, 0x0F, 0xD2, 0x0B, 0x5F, 0x39,\n    0xB9, 0xD3, 0xFB, 0xDB, 0x55, 0x79, 0xC0, 0xBD, 0x1A, 0x60, 0x32, 0x0A,\n    0xD6, 0xA1, 0x00, 0xC6, 0x40, 0x2C, 0x72, 0x79, 0x67, 0x9F, 0x25, 0xFE,\n    0xFB, 0x1F, 0xA3, 0xCC, 0x8E, 0xA5, 0xE9, 0xF8, 0xDB, 0x32, 0x22, 0xF8,\n    0x3C, 0x75, 0x16, 0xDF, 0xFD, 0x61, 0x6B, 0x15, 0x2F, 0x50, 0x1E, 0xC8,\n    0xAD, 0x05, 0x52, 0xAB, 0x32, 0x3D, 0xB5, 0xFA, 0xFD, 0x23, 0x87, 0x60,\n    0x53, 0x31, 0x7B, 0x48, 0x3E, 0x00, 0xDF, 0x82, 0x9E, 0x5C, 0x57, 0xBB,\n    0xCA, 0x6F, 0x8C, 0xA0, 0x1A, 0x87, 0x56, 0x2E, 0xDF, 0x17, 0x69, 0xDB,\n    0xD5, 0x42, 0xA8, 0xF6, 0x28, 0x7E, 0xFF, 0xC3, 0xAC, 0x67, 0x32, 0xC6,\n    0x8C, 0x4F, 0x55, 0x73, 0x69, 0x5B, 0x27, 0xB0, 0xBB, 0xCA, 0x58, 0xC8,\n    0xE1, 0xFF, 0xA3, 0x5D, 0xB8, 0xF0, 0x11, 0xA0, 0x10, 0xFA, 0x3D, 0x98,\n    0xFD, 0x21, 0x83, 0xB8, 0x4A, 0xFC, 0xB5, 0x6C, 0x2D, 0xD1, 0xD3, 0x5B,\n    0x9A, 0x53, 0xE4, 0x79, 0xB6, 0xF8, 0x45, 0x65, 0xD2, 0x8E, 0x49, 0xBC,\n    0x4B, 0xFB, 0x97, 0x90, 0xE1, 0xDD, 0xF2, 0xDA, 0xA4, 0xCB, 0x7E, 0x33,\n    0x62, 0xFB, 0x13, 0x41, 0xCE, 0xE4, 0xC6, 0xE8, 0xEF, 0x20, 0xCA, 0xDA,\n    0x36, 0x77, 0x4C, 0x01, 0xD0, 0x7E, 0x9E, 0xFE, 0x2B, 0xF1, 0x1F, 0xB4,\n    0x95, 0xDB, 0xDA, 0x4D, 0xAE, 0x90, 0x91, 0x98, 0xEA, 0xAD, 0x8E, 0x71,\n    0x6B, 0x93, 0xD5, 0xA0, 0xD0, 0x8E, 0xD1, 0xD0, 0xAF, 0xC7, 0x25, 0xE0,\n    0x8E, 0x3C, 0x5B, 0x2F, 0x8E, 0x75, 0x94, 0xB7, 0x8F, 0xF6, 0xE2, 0xFB,\n    0xF2, 0x12, 0x2B, 0x64, 0x88, 0x88, 0xB8, 0x12, 0x90, 0x0D, 0xF0, 0x1C,\n    0x4F, 0xAD, 0x5E, 0xA0, 0x68, 0x8F, 0xC3, 0x1C, 0xD1, 0xCF, 0xF1, 0x91,\n    0xB3, 0xA8, 0xC1, 0xAD, 0x2F, 0x2F, 0x22, 0x18, 0xBE, 0x0E, 0x17, 0x77,\n    0xEA, 0x75, 0x2D, 0xFE, 0x8B, 0x02, 0x1F, 0xA1, 0xE5, 0xA0, 0xCC, 0x0F,\n    0xB5, 0x6F, 0x74, 0xE8, 0x18, 0xAC, 0xF3, 0xD6, 0xCE, 0x89, 0xE2, 0x99,\n    0xB4, 0xA8, 0x4F, 0xE0, 0xFD, 0x13, 0xE0, 0xB7, 0x7C, 0xC4, 0x3B, 0x81,\n    0xD2, 0xAD, 0xA8, 0xD9, 0x16, 0x5F, 0xA2, 0x66, 0x80, 0x95, 0x77, 0x05,\n    0x93, 0xCC, 0x73, 0x14, 0x21, 0x1A, 0x14, 0x77, 0xE6, 0xAD, 0x20, 0x65,\n    0x77, 0xB5, 0xFA, 0x86, 0xC7, 0x54, 0x42, 0xF5, 0xFB, 0x9D, 0x35, 0xCF,\n    0xEB, 0xCD, 0xAF, 0x0C, 0x7B, 0x3E, 0x89, 0xA0, 0xD6, 0x41, 0x1B, 0xD3,\n    0xAE, 0x1E, 0x7E, 0x49, 0x00, 0x25, 0x0E, 0x2D, 0x20, 0x71, 0xB3, 0x5E,\n    0x22, 0x68, 0x00, 0xBB, 0x57, 0xB8, 0xE0, 0xAF, 0x24, 0x64, 0x36, 0x9B,\n    0xF0, 0x09, 0xB9, 0x1E, 0x55, 0x63, 0x91, 0x1D, 0x59, 0xDF, 0xA6, 0xAA,\n    0x78, 0xC1, 0x43, 0x89, 0xD9, 0x5A, 0x53, 0x7F, 0x20, 0x7D, 0x5B, 0xA2,\n    0x02, 0xE5, 0xB9, 0xC5, 0x83, 0x26, 0x03, 0x76, 0x62, 0x95, 0xCF, 0xA9,\n    0x11, 0xC8, 0x19, 0x68, 0x4E, 0x73, 0x4A, 0x41, 0xB3, 0x47, 0x2D, 0xCA,\n    0x7B, 0x14, 0xA9, 0x4A, 0x1B, 0x51, 0x00, 0x52, 0x9A, 0x53, 0x29, 0x15,\n    0xD6, 0x0F, 0x57, 0x3F, 0xBC, 0x9B, 0xC6, 0xE4, 0x2B, 0x60, 0xA4, 0x76,\n    0x81, 0xE6, 0x74, 0x00, 0x08, 0xBA, 0x6F, 0xB5, 0x57, 0x1B, 0xE9, 0x1F,\n    0xF2, 0x96, 0xEC, 0x6B, 0x2A, 0x0D, 0xD9, 0x15, 0xB6, 0x63, 0x65, 0x21,\n    0xE7, 0xB9, 0xF9, 0xB6, 0xFF, 0x34, 0x05, 0x2E, 0xC5, 0x85, 0x56, 0x64,\n    0x53, 0xB0, 0x2D, 0x5D, 0xA9, 0x9F, 0x8F, 0xA1, 0x08, 0xBA, 0x47, 0x99,\n    0x6E, 0x85, 0x07, 0x6A, 0x4B, 0x7A, 0x70, 0xE9, 0xB5, 0xB3, 0x29, 0x44,\n    0xDB, 0x75, 0x09, 0x2E, 0xC4, 0x19, 0x26, 0x23, 0xAD, 0x6E, 0xA6, 0xB0,\n    0x49, 0xA7, 0xDF, 0x7D, 0x9C, 0xEE, 0x60, 0xB8, 0x8F, 0xED, 0xB2, 0x66,\n    0xEC, 0xAA, 0x8C, 0x71, 0x69, 0x9A, 0x18, 0xFF, 0x56, 0x64, 0x52, 0x6C,\n    0xC2, 0xB1, 0x9E, 0xE1, 0x19, 0x36, 0x02, 0xA5, 0x75, 0x09, 0x4C, 0x29,\n    0xA0, 0x59, 0x13, 0x40, 0xE4, 0x18, 0x3A, 0x3E, 0x3F, 0x54, 0x98, 0x9A,\n    0x5B, 0x42, 0x9D, 0x65, 0x6B, 0x8F, 0xE4, 0xD6, 0x99, 0xF7, 0x3F, 0xD6,\n    0xA1, 0xD2, 0x9C, 0x07, 0xEF, 0xE8, 0x30, 0xF5, 0x4D, 0x2D, 0x38, 0xE6,\n    0xF0, 0x25, 0x5D, 0xC1, 0x4C, 0xDD, 0x20, 0x86, 0x84, 0x70, 0xEB, 0x26,\n    0x63, 0x82, 0xE9, 0xC6, 0x02, 0x1E, 0xCC, 0x5E, 0x09, 0x68, 0x6B, 0x3F,\n    0x3E, 0xBA, 0xEF, 0xC9, 0x3C, 0x97, 0x18, 0x14, 0x6B, 0x6A, 0x70, 0xA1,\n    0x68, 0x7F, 0x35, 0x84, 0x52, 0xA0, 0xE2, 0x86, 0xB7, 0x9C, 0x53, 0x05,\n    0xAA, 0x50, 0x07, 0x37, 0x3E, 0x07, 0x84, 0x1C, 0x7F, 0xDE, 0xAE, 0x5C,\n    0x8E, 0x7D, 0x44, 0xEC, 0x57, 0x16, 0xF2, 0xB8, 0xB0, 0x3A, 0xDA, 0x37,\n    0xF0, 0x50, 0x0C, 0x0D, 0xF0, 0x1C, 0x1F, 0x04, 0x02, 0x00, 0xB3, 0xFF,\n    0xAE, 0x0C, 0xF5, 0x1A, 0x3C, 0xB5, 0x74, 0xB2, 0x25, 0x83, 0x7A, 0x58,\n    0xDC, 0x09, 0x21, 0xBD, 0xD1, 0x91, 0x13, 0xF9, 0x7C, 0xA9, 0x2F, 0xF6,\n    0x94, 0x32, 0x47, 0x73, 0x22, 0xF5, 0x47, 0x01, 0x3A, 0xE5, 0xE5, 0x81,\n    0x37, 0xC2, 0xDA, 0xDC, 0xC8, 0xB5, 0x76, 0x34, 0x9A, 0xF3, 0xDD, 0xA7,\n    0xA9, 0x44, 0x61, 0x46, 0x0F, 0xD0, 0x03, 0x0E, 0xEC, 0xC8, 0xC7, 0x3E,\n    0xA4, 0x75, 0x1E, 0x41, 0xE2, 0x38, 0xCD, 0x99, 0x3B, 0xEA, 0x0E, 0x2F,\n    0x32, 0x80, 0xBB, 0xA1, 0x18, 0x3E, 0xB3, 0x31, 0x4E, 0x54, 0x8B, 0x38,\n    0x4F, 0x6D, 0xB9, 0x08, 0x6F, 0x42, 0x0D, 0x03, 0xF6, 0x0A, 0x04, 0xBF,\n    0x2C, 0xB8, 0x12, 0x90, 0x24, 0x97, 0x7C, 0x79, 0x56, 0x79, 0xB0, 0x72,\n    0xBC, 0xAF, 0x89, 0xAF, 0xDE, 0x9A, 0x77, 0x1F, 0xD9, 0x93, 0x08, 0x10,\n    0xB3, 0x8B, 0xAE, 0x12, 0xDC, 0xCF, 0x3F, 0x2E, 0x55, 0x12, 0x72, 0x1F,\n    0x2E, 0x6B, 0x71, 0x24, 0x50, 0x1A, 0xDD, 0xE6, 0x9F, 0x84, 0xCD, 0x87,\n    0x7A, 0x58, 0x47, 0x18, 0x74, 0x08, 0xDA, 0x17, 0xBC, 0x9F, 0x9A, 0xBC,\n    0xE9, 0x4B, 0x7D, 0x8C, 0xEC, 0x7A, 0xEC, 0x3A, 0xDB, 0x85, 0x1D, 0xFA,\n    0x63, 0x09, 0x43, 0x66, 0xC4, 0x64, 0xC3, 0xD2, 0xEF, 0x1C, 0x18, 0x47,\n    0x32, 0x15, 0xD8, 0x08, 0xDD, 0x43, 0x3B, 0x37, 0x24, 0xC2, 0xBA, 0x16,\n    0x12, 0xA1, 0x4D, 0x43, 0x2A, 0x65, 0xC4, 0x51, 0x50, 0x94, 0x00, 0x02,\n    0x13, 0x3A, 0xE4, 0xDD, 0x71, 0xDF, 0xF8, 0x9E, 0x10, 0x31, 0x4E, 0x55,\n    0x81, 0xAC, 0x77, 0xD6, 0x5F, 0x11, 0x19, 0x9B, 0x04, 0x35, 0x56, 0xF1,\n    0xD7, 0xA3, 0xC7, 0x6B, 0x3C, 0x11, 0x18, 0x3B, 0x59, 0x24, 0xA5, 0x09,\n    0xF2, 0x8F, 0xE6, 0xED, 0x97, 0xF1, 0xFB, 0xFA, 0x9E, 0xBA, 0xBF, 0x2C,\n    0x1E, 0x15, 0x3C, 0x6E, 0x86, 0xE3, 0x45, 0x70, 0xEA, 0xE9, 0x6F, 0xB1,\n    0x86, 0x0E, 0x5E, 0x0A, 0x5A, 0x3E, 0x2A, 0xB3, 0x77, 0x1F, 0xE7, 0x1C,\n    0x4E, 0x3D, 0x06, 0xFA, 0x29, 0x65, 0xDC, 0xB9, 0x99, 0xE7, 0x1D, 0x0F,\n    0x80, 0x3E, 0x89, 0xD6, 0x52, 0x66, 0xC8, 0x25, 0x2E, 0x4C, 0xC9, 0x78,\n    0x9C, 0x10, 0xB3, 0x6A, 0xC6, 0x15, 0x0E, 0xBA, 0x94, 0xE2, 0xEA, 0x78,\n    0xA6, 0xFC, 0x3C, 0x53, 0x1E, 0x0A, 0x2D, 0xF4, 0xF2, 0xF7, 0x4E, 0xA7,\n    0x36, 0x1D, 0x2B, 0x3D, 0x19, 0x39, 0x26, 0x0F, 0x19, 0xC2, 0x79, 0x60,\n    0x52, 0x23, 0xA7, 0x08, 0xF7, 0x13, 0x12, 0xB6, 0xEB, 0xAD, 0xFE, 0x6E,\n    0xEA, 0xC3, 0x1F, 0x66, 0xE3, 0xBC, 0x45, 0x95, 0xA6, 0x7B, 0xC8, 0x83,\n    0xB1, 0x7F, 0x37, 0xD1, 0x01, 0x8C, 0xFF, 0x28, 0xC3, 0x32, 0xDD, 0xEF,\n    0xBE, 0x6C, 0x5A, 0xA5, 0x65, 0x58, 0x21, 0x85, 0x68, 0xAB, 0x97, 0x02,\n    0xEE, 0xCE, 0xA5, 0x0F, 0xDB, 0x2F, 0x95, 0x3B, 0x2A, 0xEF, 0x7D, 0xAD,\n    0x5B, 0x6E, 0x2F, 0x84, 0x15, 0x21, 0xB6, 0x28, 0x29, 0x07, 0x61, 0x70,\n    0xEC, 0xDD, 0x47, 0x75, 0x61, 0x9F, 0x15, 0x10, 0x13, 0xCC, 0xA8, 0x30,\n    0xEB, 0x61, 0xBD, 0x96, 0x03, 0x34, 0xFE, 0x1E, 0xAA, 0x03, 0x63, 0xCF,\n    0xB5, 0x73, 0x5C, 0x90, 0x4C, 0x70, 0xA2, 0x39, 0xD5, 0x9E, 0x9E, 0x0B,\n    0xCB, 0xAA, 0xDE, 0x14, 0xEE, 0xCC, 0x86, 0xBC, 0x60, 0x62, 0x2C, 0xA7,\n    0x9C, 0xAB, 0x5C, 0xAB, 0xB2, 0xF3, 0x84, 0x6E, 0x64, 0x8B, 0x1E, 0xAF,\n    0x19, 0xBD, 0xF0, 0xCA, 0xA0, 0x23, 0x69, 0xB9, 0x65, 0x5A, 0xBB, 0x50,\n    0x40, 0x68, 0x5A, 0x32, 0x3C, 0x2A, 0xB4, 0xB3, 0x31, 0x9E, 0xE9, 0xD5,\n    0xC0, 0x21, 0xB8, 0xF7, 0x9B, 0x54, 0x0B, 0x19, 0x87, 0x5F, 0xA0, 0x99,\n    0x95, 0xF7, 0x99, 0x7E, 0x62, 0x3D, 0x7D, 0xA8, 0xF8, 0x37, 0x88, 0x9A,\n    0x97, 0xE3, 0x2D, 0x77, 0x11, 0xED, 0x93, 0x5F, 0x16, 0x68, 0x12, 0x81,\n    0x0E, 0x35, 0x88, 0x29, 0xC7, 0xE6, 0x1F, 0xD6, 0x96, 0xDE, 0xDF, 0xA1,\n    0x78, 0x58, 0xBA, 0x99, 0x57, 0xF5, 0x84, 0xA5, 0x1B, 0x22, 0x72, 0x63,\n    0x9B, 0x83, 0xC3, 0xFF, 0x1A, 0xC2, 0x46, 0x96, 0xCD, 0xB3, 0x0A, 0xEB,\n    0x53, 0x2E, 0x30, 0x54, 0x8F, 0xD9, 0x48, 0xE4, 0x6D, 0xBC, 0x31, 0x28,\n    0x58, 0xEB, 0xF2, 0xEF, 0x34, 0xC6, 0xFF, 0xEA, 0xFE, 0x28, 0xED, 0x61,\n    0xEE, 0x7C, 0x3C, 0x73, 0x5D, 0x4A, 0x14, 0xD9, 0xE8, 0x64, 0xB7, 0xE3,\n    0x42, 0x10, 0x5D, 0x14, 0x20, 0x3E, 0x13, 0xE0, 0x45, 0xEE, 0xE2, 0xB6,\n    0xA3, 0xAA, 0xAB, 0xEA, 0xDB, 0x6C, 0x4F, 0x15, 0xFA, 0xCB, 0x4F, 0xD0,\n    0xC7, 0x42, 0xF4, 0x42, 0xEF, 0x6A, 0xBB, 0xB5, 0x65, 0x4F, 0x3B, 0x1D,\n    0x41, 0xCD, 0x21, 0x05, 0xD8, 0x1E, 0x79, 0x9E, 0x86, 0x85, 0x4D, 0xC7,\n    0xE4, 0x4B, 0x47, 0x6A, 0x3D, 0x81, 0x62, 0x50, 0xCF, 0x62, 0xA1, 0xF2,\n    0x5B, 0x8D, 0x26, 0x46, 0xFC, 0x88, 0x83, 0xA0, 0xC1, 0xC7, 0xB6, 0xA3,\n    0x7F, 0x15, 0x24, 0xC3, 0x69, 0xCB, 0x74, 0x92, 0x47, 0x84, 0x8A, 0x0B,\n    0x56, 0x92, 0xB2, 0x85, 0x09, 0x5B, 0xBF, 0x00, 0xAD, 0x19, 0x48, 0x9D,\n    0x14, 0x62, 0xB1, 0x74, 0x23, 0x82, 0x0D, 0x00, 0x58, 0x42, 0x8D, 0x2A,\n    0x0C, 0x55, 0xF5, 0xEA, 0x1D, 0xAD, 0xF4, 0x3E, 0x23, 0x3F, 0x70, 0x61,\n    0x33, 0x72, 0xF0, 0x92, 0x8D, 0x93, 0x7E, 0x41, 0xD6, 0x5F, 0xEC, 0xF1,\n    0x6C, 0x22, 0x3B, 0xDB, 0x7C, 0xDE, 0x37, 0x59, 0xCB, 0xEE, 0x74, 0x60,\n    0x40, 0x85, 0xF2, 0xA7, 0xCE, 0x77, 0x32, 0x6E, 0xA6, 0x07, 0x80, 0x84,\n    0x19, 0xF8, 0x50, 0x9E, 0xE8, 0xEF, 0xD8, 0x55, 0x61, 0xD9, 0x97, 0x35,\n    0xA9, 0x69, 0xA7, 0xAA, 0xC5, 0x0C, 0x06, 0xC2, 0x5A, 0x04, 0xAB, 0xFC,\n    0x80, 0x0B, 0xCA, 0xDC, 0x9E, 0x44, 0x7A, 0x2E, 0xC3, 0x45, 0x34, 0x84,\n    0xFD, 0xD5, 0x67, 0x05, 0x0E, 0x1E, 0x9E, 0xC9, 0xDB, 0x73, 0xDB, 0xD3,\n    0x10, 0x55, 0x88, 0xCD, 0x67, 0x5F, 0xDA, 0x79, 0xE3, 0x67, 0x43, 0x40,\n    0xC5, 0xC4, 0x34, 0x65, 0x71, 0x3E, 0x38, 0xD8, 0x3D, 0x28, 0xF8, 0x9E,\n    0xF1, 0x6D, 0xFF, 0x20, 0x15, 0x3E, 0x21, 0xE7, 0x8F, 0xB0, 0x3D, 0x4A,\n    0xE6, 0xE3, 0x9F, 0x2B, 0xDB, 0x83, 0xAD, 0xF7, 0xE9, 0x3D, 0x5A, 0x68,\n    0x94, 0x81, 0x40, 0xF7, 0xF6, 0x4C, 0x26, 0x1C, 0x94, 0x69, 0x29, 0x34,\n    0x41, 0x15, 0x20, 0xF7, 0x76, 0x02, 0xD4, 0xF7, 0xBC, 0xF4, 0x6B, 0x2E,\n    0xD4, 0xA1, 0x00, 0x68, 0xD4, 0x08, 0x24, 0x71, 0x33, 0x20, 0xF4, 0x6A,\n    0x43, 0xB7, 0xD4, 0xB7, 0x50, 0x00, 0x61, 0xAF, 0x1E, 0x39, 0xF6, 0x2E,\n    0x97, 0x24, 0x45, 0x46,\n};\n\nalignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {\n    0x44, 0x73, 0x70, 0x03, 0x2E, 0x8A, 0x19, 0x13, 0xD3, 0x08, 0xA3, 0x85,\n    0x88, 0x6A, 0x3F, 0x24, 0x89, 0x6C, 0x4E, 0xEC, 0x98, 0xFA, 0x2E, 0x08,\n    0xD0, 0x31, 0x9F, 0x29, 0x22, 0x38, 0x09, 0xA4, 0x6C, 0x0C, 0xE9, 0x34,\n    0xCF, 0x66, 0x54, 0xBE, 0x77, 0x13, 0xD0, 0x38, 0xE6, 0x21, 0x28, 0x45,\n    0x17, 0x09, 0x47, 0xB5, 0xB5, 0xD5, 0x84, 0x3F, 0xDD, 0x50, 0x7C, 0xC9,\n    0xB7, 0x29, 0xAC, 0xC0, 0xAC, 0xB5, 0xDF, 0x98, 0xA6, 0x0B, 0x31, 0xD1,\n    0x1B, 0xFB, 0x79, 0x89, 0xD9, 0xD5, 0x16, 0x92, 0x96, 0x7E, 0x26, 0x6A,\n    0xED, 0xAF, 0xE1, 0xB8, 0xB7, 0xDF, 0x1A, 0xD0, 0xDB, 0x72, 0xFD, 0x2F,\n    0xF7, 0x6C, 0x91, 0xB3, 0x47, 0x99, 0xA1, 0x24, 0x99, 0x7F, 0x2C, 0xF1,\n    0x45, 0x90, 0x7C, 0xBA, 0x69, 0x4E, 0x57, 0x71, 0xD8, 0x20, 0x69, 0x63,\n    0x16, 0xFC, 0x8E, 0x85, 0xE2, 0xF2, 0x01, 0x08, 0x58, 0xB6, 0x8E, 0x72,\n    0x8F, 0x74, 0x95, 0x0D, 0x7E, 0x3D, 0x93, 0xF4, 0xA3, 0xFE, 0x58, 0xA4,\n    0xB5, 0x59, 0x5A, 0xC2, 0x1D, 0xA4, 0x54, 0x7B, 0xEE, 0x4A, 0x15, 0x82,\n    0x58, 0xCD, 0x8B, 0x71, 0xF0, 0x85, 0x60, 0x28, 0x23, 0xB0, 0xD1, 0xC5,\n    0x13, 0x60, 0xF2, 0x2A, 0x39, 0xD5, 0x30, 0x9C, 0x0E, 0x18, 0x3A, 0x60,\n    0xB0, 0xDC, 0x79, 0x8E, 0xEF, 0x38, 0xDB, 0xB8, 0x18, 0x79, 0x41, 0xCA,\n    0x27, 0x4B, 0x31, 0xBD, 0xC1, 0x77, 0x15, 0xD7, 0x3E, 0x8A, 0x1E, 0xB0,\n    0x8B, 0x0E, 0x9E, 0x6C, 0x94, 0xAB, 0x55, 0xAA, 0xF3, 0x25, 0x55, 0xE6,\n    0x60, 0x5C, 0x60, 0x55, 0xDA, 0x2F, 0xAF, 0x78, 0xB6, 0x10, 0xAB, 0x2A,\n    0x6A, 0x39, 0xCA, 0x55, 0x40, 0x14, 0xE8, 0x63, 0x62, 0x98, 0x48, 0x57,\n    0x93, 0xE9, 0x72, 0x7C, 0xAF, 0x86, 0x54, 0xA1, 0xCE, 0xE8, 0x41, 0x11,\n    0x34, 0x5C, 0xCC, 0xB4, 0xF6, 0x31, 0x18, 0x74, 0x5D, 0xC5, 0xA9, 0x2B,\n    0x2A, 0xBC, 0x6F, 0x63, 0x11, 0x14, 0xEE, 0xB3, 0x5C, 0xCF, 0x24, 0x6C,\n    0x33, 0xBA, 0xD6, 0xAF, 0x1E, 0x93, 0x87, 0x9B, 0x16, 0x3E, 0x5C, 0xCE,\n    0xAF, 0xB9, 0x4B, 0x6B, 0x98, 0x48, 0x8F, 0x3B, 0x77, 0x86, 0x95, 0x28,\n    0x81, 0x53, 0x32, 0x7A, 0x91, 0xA9, 0x21, 0xFB, 0xCC, 0x09, 0xD8, 0x61,\n    0x93, 0x21, 0x28, 0x66, 0x1B, 0xE8, 0xBF, 0xC4, 0xB1, 0x75, 0x85, 0xE9,\n    0x5D, 0x5D, 0x84, 0xEF, 0x32, 0x80, 0xEC, 0x5D, 0x60, 0xAC, 0x7C, 0x48,\n    0xC5, 0xAC, 0x96, 0xD3, 0x81, 0x3E, 0x89, 0x23, 0x88, 0x1B, 0x65, 0xEB,\n    0x02, 0x23, 0x26, 0xDC, 0x04, 0x20, 0x84, 0xA4, 0x82, 0x44, 0x0B, 0x2E,\n    0x39, 0x42, 0xF4, 0x83, 0xF3, 0x6F, 0x6D, 0x0F, 0x9A, 0x6C, 0xE9, 0xF6,\n    0x42, 0x68, 0xC6, 0x21, 0x5E, 0x9B, 0x1F, 0x9E, 0x4A, 0xF0, 0xC8, 0x69,\n    0x68, 0x2F, 0x54, 0xD8, 0xD2, 0xA0, 0x51, 0x6A, 0xF0, 0x88, 0xD3, 0xAB,\n    0x61, 0x9C, 0x0C, 0x67, 0xE4, 0x3B, 0x7A, 0x13, 0x6C, 0x0B, 0xEF, 0x6E,\n    0xA3, 0x33, 0x51, 0xAB, 0x28, 0xA7, 0x0F, 0x96, 0x76, 0x01, 0xAF, 0x39,\n    0x1D, 0x65, 0xF1, 0xA1, 0x98, 0x2A, 0xFB, 0x7E, 0x50, 0xF0, 0x3B, 0xBA,\n    0xB4, 0x9F, 0x6F, 0x45, 0x19, 0x86, 0xEE, 0x8C, 0x88, 0x0E, 0x43, 0x82,\n    0x3E, 0x59, 0xCA, 0x66, 0x73, 0x20, 0xC1, 0x85, 0xD8, 0x75, 0x6F, 0xE0,\n    0xBE, 0x5E, 0x8B, 0x3B, 0xC3, 0xA5, 0x84, 0x7D, 0x06, 0x77, 0x3F, 0x36,\n    0x62, 0xAA, 0xD3, 0x4E, 0xA6, 0x6A, 0xC1, 0x56, 0x9F, 0x44, 0x1A, 0x40,\n    0x48, 0x12, 0x0A, 0xD0, 0x24, 0xD7, 0xD0, 0x37, 0x3D, 0x02, 0x9B, 0x42,\n    0x72, 0xDF, 0xFE, 0x1B, 0x7B, 0x1B, 0x99, 0x80, 0xC9, 0x72, 0x53, 0x07,\n    0x9B, 0xC0, 0xF1, 0x49, 0xD3, 0xEA, 0x0F, 0xDB, 0x3B, 0x4C, 0x79, 0xB6,\n    0x1A, 0x50, 0xFE, 0xE3, 0xF7, 0xDE, 0xE8, 0xF6, 0xD8, 0x79, 0xD4, 0x25,\n    0xC4, 0x60, 0x9F, 0x40, 0xB6, 0x4F, 0xA9, 0xC1, 0xBA, 0x06, 0xC0, 0x04,\n    0xBD, 0xE0, 0x6C, 0x97, 0xB5, 0x53, 0x6C, 0x3E, 0xAF, 0x6F, 0xFB, 0x68,\n    0x63, 0x24, 0x6A, 0x19, 0xC2, 0x9E, 0x5C, 0x5E, 0x2C, 0x95, 0x30, 0x9B,\n    0x1F, 0x51, 0xFC, 0x6D, 0x6F, 0xEC, 0x52, 0x3B, 0xEB, 0xB2, 0x39, 0x13,\n    0xFD, 0x4A, 0x33, 0xDE, 0x04, 0xD0, 0xE3, 0xBE, 0x09, 0xBD, 0x5E, 0xAF,\n    0x44, 0x45, 0x81, 0xCC, 0x0F, 0x74, 0xC8, 0x45, 0x57, 0xA8, 0xCB, 0xC0,\n    0xB3, 0x4B, 0x2E, 0x19, 0x07, 0x28, 0x0F, 0x66, 0x0A, 0x32, 0x60, 0x1A,\n    0xBD, 0xC0, 0x79, 0x55, 0xDB, 0xFB, 0xD3, 0xB9, 0x39, 0x5F, 0x0B, 0xD2,\n    0xCC, 0xA3, 0x1F, 0xFB, 0xFE, 0x25, 0x9F, 0x67, 0x79, 0x72, 0x2C, 0x40,\n    0xC6, 0x00, 0xA1, 0xD6, 0x15, 0x6B, 0x61, 0xFD, 0xDF, 0x16, 0x75, 0x3C,\n    0xF8, 0x22, 0x32, 0xDB, 0xF8, 0xE9, 0xA5, 0x8E, 0x60, 0x87, 0x23, 0xFD,\n    0xFA, 0xB5, 0x3D, 0x32, 0xAB, 0x52, 0x05, 0xAD, 0xC8, 0x1E, 0x50, 0x2F,\n    0xA0, 0x8C, 0x6F, 0xCA, 0xBB, 0x57, 0x5C, 0x9E, 0x82, 0xDF, 0x00, 0x3E,\n    0x48, 0x7B, 0x31, 0x53, 0xC3, 0xFF, 0x7E, 0x28, 0xF6, 0xA8, 0x42, 0xD5,\n    0xDB, 0x69, 0x17, 0xDF, 0x2E, 0x56, 0x87, 0x1A, 0xC8, 0x58, 0xCA, 0xBB,\n    0xB0, 0x27, 0x5B, 0x69, 0x73, 0x55, 0x4F, 0x8C, 0xC6, 0x32, 0x67, 0xAC,\n    0xB8, 0x83, 0x21, 0xFD, 0x98, 0x3D, 0xFA, 0x10, 0xA0, 0x11, 0xF0, 0xB8,\n    0x5D, 0xA3, 0xFF, 0xE1, 0x65, 0x45, 0xF8, 0xB6, 0x79, 0xE4, 0x53, 0x9A,\n    0x5B, 0xD3, 0xD1, 0x2D, 0x6C, 0xB5, 0xFC, 0x4A, 0x33, 0x7E, 0xCB, 0xA4,\n    0xDA, 0xF2, 0xDD, 0xE1, 0x90, 0x97, 0xFB, 0x4B, 0xBC, 0x49, 0x8E, 0xD2,\n    0x01, 0x4C, 0x77, 0x36, 0xDA, 0xCA, 0x20, 0xEF, 0xE8, 0xC6, 0xE4, 0xCE,\n    0x41, 0x13, 0xFB, 0x62, 0x98, 0x91, 0x90, 0xAE, 0x4D, 0xDA, 0xDB, 0x95,\n    0xB4, 0x1F, 0xF1, 0x2B, 0xFE, 0x9E, 0x7E, 0xD0, 0xE0, 0x25, 0xC7, 0xAF,\n    0xD0, 0xD1, 0x8E, 0xD0, 0xA0, 0xD5, 0x93, 0x6B, 0x71, 0x8E, 0xAD, 0xEA,\n    0x64, 0x2B, 0x12, 0xF2, 0xFB, 0xE2, 0xF6, 0x8F, 0xB7, 0x94, 0x75, 0x8E,\n    0x2F, 0x5B, 0x3C, 0x8E, 0x1C, 0xC3, 0x8F, 0x68, 0xA0, 0x5E, 0xAD, 0x4F,\n    0x1C, 0xF0, 0x0D, 0x90, 0x12, 0xB8, 0x88, 0x88, 0x77, 0x17, 0x0E, 0xBE,\n    0x18, 0x22, 0x2F, 0x2F, 0xAD, 0xC1, 0xA8, 0xB3, 0x91, 0xF1, 0xCF, 0xD1,\n    0xE8, 0x74, 0x6F, 0xB5, 0x0F, 0xCC, 0xA0, 0xE5, 0xA1, 0x1F, 0x02, 0x8B,\n    0xFE, 0x2D, 0x75, 0xEA, 0xB7, 0xE0, 0x13, 0xFD, 0xE0, 0x4F, 0xA8, 0xB4,\n    0x99, 0xE2, 0x89, 0xCE, 0xD6, 0xF3, 0xAC, 0x18, 0x05, 0x77, 0x95, 0x80,\n    0x66, 0xA2, 0x5F, 0x16, 0xD9, 0xA8, 0xAD, 0xD2, 0x81, 0x3B, 0xC4, 0x7C,\n    0x86, 0xFA, 0xB5, 0x77, 0x65, 0x20, 0xAD, 0xE6, 0x77, 0x14, 0x1A, 0x21,\n    0x14, 0x73, 0xCC, 0x93, 0xA0, 0x89, 0x3E, 0x7B, 0x0C, 0xAF, 0xCD, 0xEB,\n    0xCF, 0x35, 0x9D, 0xFB, 0xF5, 0x42, 0x54, 0xC7, 0x5E, 0xB3, 0x71, 0x20,\n    0x2D, 0x0E, 0x25, 0x00, 0x49, 0x7E, 0x1E, 0xAE, 0xD3, 0x1B, 0x41, 0xD6,\n    0x1E, 0xB9, 0x09, 0xF0, 0x9B, 0x36, 0x64, 0x24, 0xAF, 0xE0, 0xB8, 0x57,\n    0xBB, 0x00, 0x68, 0x22, 0x7F, 0x53, 0x5A, 0xD9, 0x89, 0x43, 0xC1, 0x78,\n    0xAA, 0xA6, 0xDF, 0x59, 0x1D, 0x91, 0x63, 0x55, 0xA9, 0xCF, 0x95, 0x62,\n    0x76, 0x03, 0x26, 0x83, 0xC5, 0xB9, 0xE5, 0x02, 0xA2, 0x5B, 0x7D, 0x20,\n    0x4A, 0xA9, 0x14, 0x7B, 0xCA, 0x2D, 0x47, 0xB3, 0x41, 0x4A, 0x73, 0x4E,\n    0x68, 0x19, 0xC8, 0x11, 0xE4, 0xC6, 0x9B, 0xBC, 0x3F, 0x57, 0x0F, 0xD6,\n    0x15, 0x29, 0x53, 0x9A, 0x52, 0x00, 0x51, 0x1B, 0x1F, 0xE9, 0x1B, 0x57,\n    0xB5, 0x6F, 0xBA, 0x08, 0x00, 0x74, 0xE6, 0x81, 0x76, 0xA4, 0x60, 0x2B,\n    0xB6, 0xF9, 0xB9, 0xE7, 0x21, 0x65, 0x63, 0xB6, 0x15, 0xD9, 0x0D, 0x2A,\n    0x6B, 0xEC, 0x96, 0xF2, 0xA1, 0x8F, 0x9F, 0xA9, 0x5D, 0x2D, 0xB0, 0x53,\n    0x64, 0x56, 0x85, 0xC5, 0x2E, 0x05, 0x34, 0xFF, 0x44, 0x29, 0xB3, 0xB5,\n    0xE9, 0x70, 0x7A, 0x4B, 0x6A, 0x07, 0x85, 0x6E, 0x99, 0x47, 0xBA, 0x08,\n    0x7D, 0xDF, 0xA7, 0x49, 0xB0, 0xA6, 0x6E, 0xAD, 0x23, 0x26, 0x19, 0xC4,\n    0x2E, 0x09, 0x75, 0xDB, 0xFF, 0x18, 0x9A, 0x69, 0x71, 0x8C, 0xAA, 0xEC,\n    0x66, 0xB2, 0xED, 0x8F, 0xB8, 0x60, 0xEE, 0x9C, 0x29, 0x4C, 0x09, 0x75,\n    0xA5, 0x02, 0x36, 0x19, 0xE1, 0x9E, 0xB1, 0xC2, 0x6C, 0x52, 0x64, 0x56,\n    0x65, 0x9D, 0x42, 0x5B, 0x9A, 0x98, 0x54, 0x3F, 0x3E, 0x3A, 0x18, 0xE4,\n    0x40, 0x13, 0x59, 0xA0, 0xF5, 0x30, 0xE8, 0xEF, 0x07, 0x9C, 0xD2, 0xA1,\n    0xD6, 0x3F, 0xF7, 0x99, 0xD6, 0xE4, 0x8F, 0x6B, 0x26, 0xEB, 0x70, 0x84,\n    0x86, 0x20, 0xDD, 0x4C, 0xC1, 0x5D, 0x25, 0xF0, 0xE6, 0x38, 0x2D, 0x4D,\n    0xC9, 0xEF, 0xBA, 0x3E, 0x3F, 0x6B, 0x68, 0x09, 0x5E, 0xCC, 0x1E, 0x02,\n    0xC6, 0xE9, 0x82, 0x63, 0x86, 0xE2, 0xA0, 0x52, 0x84, 0x35, 0x7F, 0x68,\n    0xA1, 0x70, 0x6A, 0x6B, 0x14, 0x18, 0x97, 0x3C, 0x5C, 0xAE, 0xDE, 0x7F,\n    0x1C, 0x84, 0x07, 0x3E, 0x37, 0x07, 0x50, 0xAA, 0x05, 0x53, 0x9C, 0xB7,\n    0x0D, 0x0C, 0x50, 0xF0, 0x37, 0xDA, 0x3A, 0xB0, 0xB8, 0xF2, 0x16, 0x57,\n    0xEC, 0x44, 0x7D, 0x8E, 0xB2, 0x74, 0xB5, 0x3C, 0x1A, 0xF5, 0x0C, 0xAE,\n    0xFF, 0xB3, 0x00, 0x02, 0x04, 0x1F, 0x1C, 0xF0, 0xF6, 0x2F, 0xA9, 0x7C,\n    0xF9, 0x13, 0x91, 0xD1, 0xBD, 0x21, 0x09, 0xDC, 0x58, 0x7A, 0x83, 0x25,\n    0xDC, 0xDA, 0xC2, 0x37, 0x81, 0xE5, 0xE5, 0x3A, 0x01, 0x47, 0xF5, 0x22,\n    0x73, 0x47, 0x32, 0x94, 0x0E, 0x03, 0xD0, 0x0F, 0x46, 0x61, 0x44, 0xA9,\n    0xA7, 0xDD, 0xF3, 0x9A, 0x34, 0x76, 0xB5, 0xC8, 0x2F, 0x0E, 0xEA, 0x3B,\n    0x99, 0xCD, 0x38, 0xE2, 0x41, 0x1E, 0x75, 0xA4, 0x3E, 0xC7, 0xC8, 0xEC,\n    0x08, 0xB9, 0x6D, 0x4F, 0x38, 0x8B, 0x54, 0x4E, 0x31, 0xB3, 0x3E, 0x18,\n    0xA1, 0xBB, 0x80, 0x32, 0x79, 0x7C, 0x97, 0x24, 0x90, 0x12, 0xB8, 0x2C,\n    0xBF, 0x04, 0x0A, 0xF6, 0x03, 0x0D, 0x42, 0x6F, 0x10, 0x08, 0x93, 0xD9,\n    0x1F, 0x77, 0x9A, 0xDE, 0xAF, 0x89, 0xAF, 0xBC, 0x72, 0xB0, 0x79, 0x56,\n    0x24, 0x71, 0x6B, 0x2E, 0x1F, 0x72, 0x12, 0x55, 0x2E, 0x3F, 0xCF, 0xDC,\n    0x12, 0xAE, 0x8B, 0xB3, 0x17, 0xDA, 0x08, 0x74, 0x18, 0x47, 0x58, 0x7A,\n    0x87, 0xCD, 0x84, 0x9F, 0xE6, 0xDD, 0x1A, 0x50, 0xFA, 0x1D, 0x85, 0xDB,\n    0x3A, 0xEC, 0x7A, 0xEC, 0x8C, 0x7D, 0x4B, 0xE9, 0xBC, 0x9A, 0x9F, 0xBC,\n    0x08, 0xD8, 0x15, 0x32, 0x47, 0x18, 0x1C, 0xEF, 0xD2, 0xC3, 0x64, 0xC4,\n    0x66, 0x43, 0x09, 0x63, 0x51, 0xC4, 0x65, 0x2A, 0x43, 0x4D, 0xA1, 0x12,\n    0x16, 0xBA, 0xC2, 0x24, 0x37, 0x3B, 0x43, 0xDD, 0x55, 0x4E, 0x31, 0x10,\n    0x9E, 0xF8, 0xDF, 0x71, 0xDD, 0xE4, 0x3A, 0x13, 0x02, 0x00, 0x94, 0x50,\n    0x6B, 0xC7, 0xA3, 0xD7, 0xF1, 0x56, 0x35, 0x04, 0x9B, 0x19, 0x11, 0x5F,\n    0xD6, 0x77, 0xAC, 0x81, 0xFA, 0xFB, 0xF1, 0x97, 0xED, 0xE6, 0x8F, 0xF2,\n    0x09, 0xA5, 0x24, 0x59, 0x3B, 0x18, 0x11, 0x3C, 0xB1, 0x6F, 0xE9, 0xEA,\n    0x70, 0x45, 0xE3, 0x86, 0x6E, 0x3C, 0x15, 0x1E, 0x2C, 0xBF, 0xBA, 0x9E,\n    0xFA, 0x06, 0x3D, 0x4E, 0x1C, 0xE7, 0x1F, 0x77, 0xB3, 0x2A, 0x3E, 0x5A,\n    0x0A, 0x5E, 0x0E, 0x86, 0x25, 0xC8, 0x66, 0x52, 0xD6, 0x89, 0x3E, 0x80,\n    0x0F, 0x1D, 0xE7, 0x99, 0xB9, 0xDC, 0x65, 0x29, 0x78, 0xEA, 0xE2, 0x94,\n    0xBA, 0x0E, 0x15, 0xC6, 0x6A, 0xB3, 0x10, 0x9C, 0x78, 0xC9, 0x4C, 0x2E,\n    0x3D, 0x2B, 0x1D, 0x36, 0xA7, 0x4E, 0xF7, 0xF2, 0xF4, 0x2D, 0x0A, 0x1E,\n    0x53, 0x3C, 0xFC, 0xA6, 0xB6, 0x12, 0x13, 0xF7, 0x08, 0xA7, 0x23, 0x52,\n    0x60, 0x79, 0xC2, 0x19, 0x0F, 0x26, 0x39, 0x19, 0x83, 0xC8, 0x7B, 0xA6,\n    0x95, 0x45, 0xBC, 0xE3, 0x66, 0x1F, 0xC3, 0xEA, 0x6E, 0xFE, 0xAD, 0xEB,\n    0xA5, 0x5A, 0x6C, 0xBE, 0xEF, 0xDD, 0x32, 0xC3, 0x28, 0xFF, 0x8C, 0x01,\n    0xD1, 0x37, 0x7F, 0xB1, 0x3B, 0x95, 0x2F, 0xDB, 0x0F, 0xA5, 0xCE, 0xEE,\n    0x02, 0x97, 0xAB, 0x68, 0x85, 0x21, 0x58, 0x65, 0x70, 0x61, 0x07, 0x29,\n    0x28, 0xB6, 0x21, 0x15, 0x84, 0x2F, 0x6E, 0x5B, 0xAD, 0x7D, 0xEF, 0x2A,\n    0x96, 0xBD, 0x61, 0xEB, 0x30, 0xA8, 0xCC, 0x13, 0x10, 0x15, 0x9F, 0x61,\n    0x75, 0x47, 0xDD, 0xEC, 0x39, 0xA2, 0x70, 0x4C, 0x90, 0x5C, 0x73, 0xB5,\n    0xCF, 0x63, 0x03, 0xAA, 0x1E, 0xFE, 0x34, 0x03, 0xA7, 0x2C, 0x62, 0x60,\n    0xBC, 0x86, 0xCC, 0xEE, 0x14, 0xDE, 0xAA, 0xCB, 0x0B, 0x9E, 0x9E, 0xD5,\n    0xCA, 0xF0, 0xBD, 0x19, 0xAF, 0x1E, 0x8B, 0x64, 0x6E, 0x84, 0xF3, 0xB2,\n    0xAB, 0x5C, 0xAB, 0x9C, 0xB3, 0xB4, 0x2A, 0x3C, 0x32, 0x5A, 0x68, 0x40,\n    0x50, 0xBB, 0x5A, 0x65, 0xB9, 0x69, 0x23, 0xA0, 0x99, 0xA0, 0x5F, 0x87,\n    0x19, 0x0B, 0x54, 0x9B, 0xF7, 0xB8, 0x21, 0xC0, 0xD5, 0xE9, 0x9E, 0x31,\n    0x77, 0x2D, 0xE3, 0x97, 0x9A, 0x88, 0x37, 0xF8, 0xA8, 0x7D, 0x3D, 0x62,\n    0x7E, 0x99, 0xF7, 0x95, 0xD6, 0x1F, 0xE6, 0xC7, 0x29, 0x88, 0x35, 0x0E,\n    0x81, 0x12, 0x68, 0x16, 0x5F, 0x93, 0xED, 0x11, 0x63, 0x72, 0x22, 0x1B,\n    0xA5, 0x84, 0xF5, 0x57, 0x99, 0xBA, 0x58, 0x78, 0xA1, 0xDF, 0xDE, 0x96,\n    0x54, 0x30, 0x2E, 0x53, 0xEB, 0x0A, 0xB3, 0xCD, 0x96, 0x46, 0xC2, 0x1A,\n    0xFF, 0xC3, 0x83, 0x9B, 0xEA, 0xFF, 0xC6, 0x34, 0xEF, 0xF2, 0xEB, 0x58,\n    0x28, 0x31, 0xBC, 0x6D, 0xE4, 0x48, 0xD9, 0x8F, 0xE3, 0xB7, 0x64, 0xE8,\n    0xD9, 0x14, 0x4A, 0x5D, 0x73, 0x3C, 0x7C, 0xEE, 0x61, 0xED, 0x28, 0xFE,\n    0xEA, 0xAB, 0xAA, 0xA3, 0xB6, 0xE2, 0xEE, 0x45, 0xE0, 0x13, 0x3E, 0x20,\n    0x14, 0x5D, 0x10, 0x42, 0xB5, 0xBB, 0x6A, 0xEF, 0x42, 0xF4, 0x42, 0xC7,\n    0xD0, 0x4F, 0xCB, 0xFA, 0x15, 0x4F, 0x6C, 0xDB, 0xC7, 0x4D, 0x85, 0x86,\n    0x9E, 0x79, 0x1E, 0xD8, 0x05, 0x21, 0xCD, 0x41, 0x1D, 0x3B, 0x4F, 0x65,\n    0x46, 0x26, 0x8D, 0x5B, 0xF2, 0xA1, 0x62, 0xCF, 0x50, 0x62, 0x81, 0x3D,\n    0x6A, 0x47, 0x4B, 0xE4, 0x92, 0x74, 0xCB, 0x69, 0xC3, 0x24, 0x15, 0x7F,\n    0xA3, 0xB6, 0xC7, 0xC1, 0xA0, 0x83, 0x88, 0xFC, 0x9D, 0x48, 0x19, 0xAD,\n    0x00, 0xBF, 0x5B, 0x09, 0x85, 0xB2, 0x92, 0x56, 0x0B, 0x8A, 0x84, 0x47,\n    0xEA, 0xF5, 0x55, 0x0C, 0x2A, 0x8D, 0x42, 0x58, 0x00, 0x0D, 0x82, 0x23,\n    0x74, 0xB1, 0x62, 0x14, 0x41, 0x7E, 0x93, 0x8D, 0x92, 0xF0, 0x72, 0x33,\n    0x61, 0x70, 0x3F, 0x23, 0x3E, 0xF4, 0xAD, 0x1D, 0x60, 0x74, 0xEE, 0xCB,\n    0x59, 0x37, 0xDE, 0x7C, 0xDB, 0x3B, 0x22, 0x6C, 0xF1, 0xEC, 0x5F, 0xD6,\n    0x9E, 0x50, 0xF8, 0x19, 0x84, 0x80, 0x07, 0xA6, 0x6E, 0x32, 0x77, 0xCE,\n    0xA7, 0xF2, 0x85, 0x40, 0xC2, 0x06, 0x0C, 0xC5, 0xAA, 0xA7, 0x69, 0xA9,\n    0x35, 0x97, 0xD9, 0x61, 0x55, 0xD8, 0xEF, 0xE8, 0x84, 0x34, 0x45, 0xC3,\n    0x2E, 0x7A, 0x44, 0x9E, 0xDC, 0xCA, 0x0B, 0x80, 0xFC, 0xAB, 0x04, 0x5A,\n    0xCD, 0x88, 0x55, 0x10, 0xD3, 0xDB, 0x73, 0xDB, 0xC9, 0x9E, 0x1E, 0x0E,\n    0x05, 0x67, 0xD5, 0xFD, 0xD8, 0x38, 0x3E, 0x71, 0x65, 0x34, 0xC4, 0xC5,\n    0x40, 0x43, 0x67, 0xE3, 0x79, 0xDA, 0x5F, 0x67, 0x4A, 0x3D, 0xB0, 0x8F,\n    0xE7, 0x21, 0x3E, 0x15, 0x20, 0xFF, 0x6D, 0xF1, 0x9E, 0xF8, 0x28, 0x3D,\n    0xF7, 0x40, 0x81, 0x94, 0x68, 0x5A, 0x3D, 0xE9, 0xF7, 0xAD, 0x83, 0xDB,\n    0x2B, 0x9F, 0xE3, 0xE6, 0xF7, 0xD4, 0x02, 0x76, 0xF7, 0x20, 0x15, 0x41,\n    0x34, 0x29, 0x69, 0x94, 0x1C, 0x26, 0x4C, 0xF6, 0x6A, 0xF4, 0x20, 0x33,\n    0x71, 0x24, 0x08, 0xD4, 0x68, 0x00, 0xA1, 0xD4, 0x2E, 0x6B, 0xF4, 0xBC,\n    0x46, 0x45, 0x24, 0x97, 0x2E, 0xF6, 0x39, 0x1E, 0xAF, 0x61, 0x00, 0x50,\n    0xB7, 0xD4, 0xB7, 0x43,\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/randen_slow.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen_slow.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/internal/platform.h\"\n#include \"absl/random/internal/randen_traits.h\"\n\n#if ABSL_HAVE_ATTRIBUTE(always_inline) || \\\n    (defined(__GNUC__) && !defined(__clang__))\n#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \\\n  __attribute__((always_inline))\n#elif defined(_MSC_VER)\n// We can achieve something similar to attribute((always_inline)) with MSVC by\n// using the __forceinline keyword, however this is not perfect. MSVC is\n// much less aggressive about inlining, and even with the __forceinline keyword.\n#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE __forceinline\n#else\n#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE\n#endif\n\nnamespace {\n\n// AES portions based on rijndael-alg-fst.c,\n// https://fastcrypto.org/front/misc/rijndael-alg-fst.c, and modified for\n// platform-endianness.\n//\n// Implementation of\n// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf\nconstexpr uint32_t te0[256] = {\n    0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6,\n    0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,\n    0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,\n    0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,\n    0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,\n    0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,\n    0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,\n    0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,\n    0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,\n    0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,\n    0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,\n    0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,\n    0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,\n    0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,\n    0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,\n    0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,\n    0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,\n    0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,\n    0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,\n    0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,\n    0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,\n    0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,\n    0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,\n    0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,\n    0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,\n    0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,\n    0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,\n    0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,\n    0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,\n    0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,\n    0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,\n    0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,\n    0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,\n    0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,\n    0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,\n    0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,\n    0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,\n    0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,\n    0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,\n    0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,\n    0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,\n    0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,\n    0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c,\n};\n\nconstexpr uint32_t te1[256] = {\n    0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd,\n    0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,\n    0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, 0xcaca8f45, 0x82821f9d,\n    0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,\n    0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,\n    0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,\n    0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4,\n    0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,\n    0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1,\n    0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,\n    0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e,\n    0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,\n    0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e,\n    0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,\n    0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,\n    0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,\n    0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7,\n    0x33336655, 0x85851194, 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,\n    0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe,\n    0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,\n    0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a,\n    0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,\n    0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2,\n    0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,\n    0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,\n    0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,\n    0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, 0xe0e0db3b, 0x32326456,\n    0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,\n    0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4,\n    0xe4e4d337, 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,\n    0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa,\n    0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,\n    0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1,\n    0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,\n    0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,\n    0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,\n    0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958,\n    0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,\n    0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22,\n    0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,\n    0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731,\n    0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,\n    0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a,\n};\n\nconstexpr uint32_t te2[256] = {\n    0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b,\n    0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,\n    0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, 0xca8f45ca, 0x821f9d82,\n    0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,\n    0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,\n    0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,\n    0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5,\n    0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,\n    0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196,\n    0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,\n    0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83,\n    0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,\n    0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3,\n    0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,\n    0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,\n    0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,\n    0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d,\n    0x33665533, 0x85119485, 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,\n    0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3,\n    0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,\n    0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff,\n    0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,\n    0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7,\n    0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,\n    0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,\n    0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,\n    0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, 0xe0db3be0, 0x32645632,\n    0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,\n    0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495,\n    0xe4d337e4, 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,\n    0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56,\n    0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,\n    0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6,\n    0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,\n    0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,\n    0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,\n    0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1,\n    0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,\n    0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e,\n    0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,\n    0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6,\n    0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,\n    0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16,\n};\n\nconstexpr uint32_t te3[256] = {\n    0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b,\n    0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,\n    0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, 0x8f45caca, 0x1f9d8282,\n    0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,\n    0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,\n    0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,\n    0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5,\n    0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,\n    0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696,\n    0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,\n    0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383,\n    0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,\n    0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3,\n    0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,\n    0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,\n    0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,\n    0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d,\n    0x66553333, 0x11948585, 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,\n    0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3,\n    0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,\n    0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff,\n    0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,\n    0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7,\n    0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,\n    0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,\n    0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,\n    0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, 0xdb3be0e0, 0x64563232,\n    0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,\n    0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595,\n    0xd337e4e4, 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,\n    0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656,\n    0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,\n    0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6,\n    0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,\n    0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,\n    0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,\n    0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1,\n    0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,\n    0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e,\n    0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,\n    0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6,\n    0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,\n    0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616,\n};\n\n// Software implementation of the Vector128 class, using uint32_t\n// as an underlying vector register.\nstruct alignas(16) Vector128 {\n  uint32_t s[4];\n};\n\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128\nVector128Load(const void* from) {\n  Vector128 result;\n  std::memcpy(result.s, from, sizeof(Vector128));\n  return result;\n}\n\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Vector128Store(\n    const Vector128& v, void* to) {\n  std::memcpy(to, v.s, sizeof(Vector128));\n}\n\n// One round of AES. \"round_key\" is a public constant for breaking the\n// symmetry of AES (ensures previously equal columns differ afterwards).\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128\nAesRound(const Vector128& state, const Vector128& round_key) {\n  Vector128 result;\n#ifdef ABSL_IS_LITTLE_ENDIAN\n  result.s[0] = round_key.s[0] ^                  //\n                te0[uint8_t(state.s[0])] ^        //\n                te1[uint8_t(state.s[1] >> 8)] ^   //\n                te2[uint8_t(state.s[2] >> 16)] ^  //\n                te3[uint8_t(state.s[3] >> 24)];\n  result.s[1] = round_key.s[1] ^                  //\n                te0[uint8_t(state.s[1])] ^        //\n                te1[uint8_t(state.s[2] >> 8)] ^   //\n                te2[uint8_t(state.s[3] >> 16)] ^  //\n                te3[uint8_t(state.s[0] >> 24)];\n  result.s[2] = round_key.s[2] ^                  //\n                te0[uint8_t(state.s[2])] ^        //\n                te1[uint8_t(state.s[3] >> 8)] ^   //\n                te2[uint8_t(state.s[0] >> 16)] ^  //\n                te3[uint8_t(state.s[1] >> 24)];\n  result.s[3] = round_key.s[3] ^                  //\n                te0[uint8_t(state.s[3])] ^        //\n                te1[uint8_t(state.s[0] >> 8)] ^   //\n                te2[uint8_t(state.s[1] >> 16)] ^  //\n                te3[uint8_t(state.s[2] >> 24)];\n#else\n  result.s[0] = round_key.s[0] ^                  //\n                te0[uint8_t(state.s[0])] ^        //\n                te1[uint8_t(state.s[3] >> 8)] ^   //\n                te2[uint8_t(state.s[2] >> 16)] ^  //\n                te3[uint8_t(state.s[1] >> 24)];\n  result.s[1] = round_key.s[1] ^                  //\n                te0[uint8_t(state.s[1])] ^        //\n                te1[uint8_t(state.s[0] >> 8)] ^   //\n                te2[uint8_t(state.s[3] >> 16)] ^  //\n                te3[uint8_t(state.s[2] >> 24)];\n  result.s[2] = round_key.s[2] ^                  //\n                te0[uint8_t(state.s[2])] ^        //\n                te1[uint8_t(state.s[1] >> 8)] ^   //\n                te2[uint8_t(state.s[0] >> 16)] ^  //\n                te3[uint8_t(state.s[3] >> 24)];\n  result.s[3] = round_key.s[3] ^                  //\n                te0[uint8_t(state.s[3])] ^        //\n                te1[uint8_t(state.s[2] >> 8)] ^   //\n                te2[uint8_t(state.s[1] >> 16)] ^  //\n                te3[uint8_t(state.s[0] >> 24)];\n#endif\n  return result;\n}\n\nusing ::absl::random_internal::RandenTraits;\n\n// The improved Feistel block shuffle function for 16 blocks.\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(\n    absl::uint128* state) {\n  static_assert(RandenTraits::kFeistelBlocks == 16,\n                \"Feistel block shuffle only works for 16 blocks.\");\n\n  constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {\n      7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};\n\n  // The fully unrolled loop without the memcpy improves the speed by about\n  // 30% over the equivalent:\n#if 0\n  absl::uint128 source[RandenTraits::kFeistelBlocks];\n  std::memcpy(source, state, sizeof(source));\n  for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) {\n    const absl::uint128 v0 = source[shuffle[i]];\n    state[i] = v0;\n  }\n  return;\n#endif\n\n  const absl::uint128 v0 = state[shuffle[0]];\n  const absl::uint128 v1 = state[shuffle[1]];\n  const absl::uint128 v2 = state[shuffle[2]];\n  const absl::uint128 v3 = state[shuffle[3]];\n  const absl::uint128 v4 = state[shuffle[4]];\n  const absl::uint128 v5 = state[shuffle[5]];\n  const absl::uint128 v6 = state[shuffle[6]];\n  const absl::uint128 v7 = state[shuffle[7]];\n  const absl::uint128 w0 = state[shuffle[8]];\n  const absl::uint128 w1 = state[shuffle[9]];\n  const absl::uint128 w2 = state[shuffle[10]];\n  const absl::uint128 w3 = state[shuffle[11]];\n  const absl::uint128 w4 = state[shuffle[12]];\n  const absl::uint128 w5 = state[shuffle[13]];\n  const absl::uint128 w6 = state[shuffle[14]];\n  const absl::uint128 w7 = state[shuffle[15]];\n  state[0] = v0;\n  state[1] = v1;\n  state[2] = v2;\n  state[3] = v3;\n  state[4] = v4;\n  state[5] = v5;\n  state[6] = v6;\n  state[7] = v7;\n  state[8] = w0;\n  state[9] = w1;\n  state[10] = w2;\n  state[11] = w3;\n  state[12] = w4;\n  state[13] = w5;\n  state[14] = w6;\n  state[15] = w7;\n}\n\n// Feistel round function using two AES subrounds. Very similar to F()\n// from Simpira v2, but with independent subround keys. Uses 17 AES rounds\n// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in\n// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel\n// XORs are 'free' (included in the second AES instruction).\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const absl::uint128*\nFeistelRound(absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT state,\n             const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {\n  for (size_t branch = 0; branch < RandenTraits::kFeistelBlocks; branch += 4) {\n    const Vector128 s0 = Vector128Load(state + branch);\n    const Vector128 s1 = Vector128Load(state + branch + 1);\n    const Vector128 f0 = AesRound(s0, Vector128Load(keys));\n    keys++;\n    const Vector128 o1 = AesRound(f0, s1);\n    Vector128Store(o1, state + branch + 1);\n\n    // Manually unroll this loop once. about 10% better than not unrolled.\n    const Vector128 s2 = Vector128Load(state + branch + 2);\n    const Vector128 s3 = Vector128Load(state + branch + 3);\n    const Vector128 f2 = AesRound(s2, Vector128Load(keys));\n    keys++;\n    const Vector128 o3 = AesRound(f2, s3);\n    Vector128Store(o3, state + branch + 3);\n  }\n  return keys;\n}\n\n// Cryptographic permutation based via type-2 Generalized Feistel Network.\n// Indistinguishable from ideal by chosen-ciphertext adversaries using less than\n// 2^64 queries if the round function is a PRF. This is similar to the b=8 case\n// of Simpira v2, but more efficient than its generic construction for b=16.\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(\n    absl::uint128* state,\n    const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {\n  for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {\n    keys = FeistelRound(state, keys);\n    BlockShuffle(state);\n  }\n}\n\n// Enables native loads in the round loop by pre-swapping.\ninline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void SwapEndian(\n    absl::uint128* state) {\n#ifdef ABSL_IS_BIG_ENDIAN\n  for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {\n    uint64_t new_lo = absl::little_endian::ToHost64(\n        static_cast<uint64_t>(state[block] >> 64));\n    uint64_t new_hi = absl::little_endian::ToHost64(\n        static_cast<uint64_t>((state[block] << 64) >> 64));\n    state[block] = (static_cast<absl::uint128>(new_hi) << 64) | new_lo;\n  }\n#else\n  // Avoid warning about unused variable.\n  (void)state;\n#endif\n}\n\n}  // namespace\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\nconst void* RandenSlow::GetKeys() {\n  // Round keys for one AES per Feistel round and branch.\n  // The canonical implementation uses first digits of Pi.\n#ifdef ABSL_IS_LITTLE_ENDIAN\n  return kRandenRoundKeys;\n#else\n  return kRandenRoundKeysBE;\n#endif\n}\n\nvoid RandenSlow::Absorb(const void* seed_void, void* state_void) {\n  auto* state =\n      reinterpret_cast<uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);\n  const auto* seed =\n      reinterpret_cast<const uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(\n          seed_void);\n\n  constexpr size_t kCapacityBlocks =\n      RandenTraits::kCapacityBytes / sizeof(uint64_t);\n  static_assert(\n      kCapacityBlocks * sizeof(uint64_t) == RandenTraits::kCapacityBytes,\n      \"Not i*V\");\n\n  for (size_t i = kCapacityBlocks;\n       i < RandenTraits::kStateBytes / sizeof(uint64_t); ++i) {\n    state[i] ^= seed[i - kCapacityBlocks];\n  }\n}\n\nvoid RandenSlow::Generate(const void* keys_void, void* state_void) {\n  static_assert(RandenTraits::kCapacityBytes == sizeof(absl::uint128),\n                \"Capacity mismatch\");\n\n  auto* state = reinterpret_cast<absl::uint128*>(state_void);\n  const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);\n\n  const absl::uint128 prev_inner = state[0];\n\n  SwapEndian(state);\n\n  Permute(state, keys);\n\n  SwapEndian(state);\n\n  // Ensure backtracking resistance.\n  *state ^= prev_inner;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/randen_slow.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_\n#define ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// RANDen = RANDom generator or beetroots in Swiss High German.\n// RandenSlow implements the basic state manipulation methods for\n// architectures lacking AES hardware acceleration intrinsics.\nclass RandenSlow {\n public:\n  static void Generate(const void* keys, void* state_void);\n  static void Absorb(const void* seed_void, void* state_void);\n  static const void* GetKeys();\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_\n"
  },
  {
    "path": "absl/random/internal/randen_slow_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen_slow.h\"\n\n#include <cstring>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/random/internal/randen_traits.h\"\n\nnamespace {\n\nusing absl::random_internal::RandenSlow;\nusing absl::random_internal::RandenTraits;\n\nTEST(RandenSlowTest, Default) {\n  constexpr uint8_t kGolden[] = {\n      0xee, 0xd3, 0xe6, 0x0e, 0x09, 0x34, 0x65, 0x6c, 0xc6, 0x33, 0x53, 0x9d,\n      0x9b, 0x2b, 0x4e, 0x04, 0x77, 0x39, 0x43, 0x4e, 0x13, 0x4f, 0xc1, 0xc3,\n      0xee, 0x10, 0x04, 0xd9, 0x7c, 0xf4, 0xa9, 0xdd, 0x10, 0xca, 0xd8, 0x7f,\n      0x08, 0xf3, 0x7b, 0x88, 0x12, 0x29, 0xc7, 0x45, 0xf5, 0x80, 0xb7, 0xf0,\n      0x9f, 0x59, 0x96, 0x76, 0xd3, 0xb1, 0xdb, 0x15, 0x59, 0x6d, 0x3c, 0xff,\n      0xba, 0x63, 0xec, 0x30, 0xa6, 0x20, 0x7f, 0x6f, 0x60, 0x73, 0x9f, 0xb2,\n      0x4c, 0xa5, 0x49, 0x6f, 0x31, 0x8a, 0x80, 0x02, 0x0e, 0xe5, 0xc8, 0xd5,\n      0xf9, 0xea, 0x8f, 0x3b, 0x8a, 0xde, 0xd9, 0x3f, 0x5e, 0x60, 0xbf, 0x9c,\n      0xbb, 0x3b, 0x18, 0x78, 0x1a, 0xae, 0x70, 0xc9, 0xd5, 0x1e, 0x30, 0x56,\n      0xd3, 0xff, 0xb2, 0xd8, 0x37, 0x3c, 0xc7, 0x0f, 0xfe, 0x27, 0xb3, 0xf4,\n      0x19, 0x9a, 0x8f, 0xeb, 0x76, 0x8d, 0xfd, 0xcd, 0x9d, 0x0c, 0x42, 0x91,\n      0xeb, 0x06, 0xa5, 0xc3, 0x56, 0x95, 0xff, 0x3e, 0xdd, 0x05, 0xaf, 0xd5,\n      0xa1, 0xc4, 0x83, 0x8f, 0xb7, 0x1b, 0xdb, 0x48, 0x8c, 0xfe, 0x6b, 0x0d,\n      0x0e, 0x92, 0x23, 0x70, 0x42, 0x6d, 0x95, 0x34, 0x58, 0x57, 0xd3, 0x58,\n      0x40, 0xb8, 0x87, 0x6b, 0xc2, 0xf4, 0x1e, 0xed, 0xf3, 0x2d, 0x0b, 0x3e,\n      0xa2, 0x32, 0xef, 0x8e, 0xfc, 0x54, 0x11, 0x43, 0xf3, 0xab, 0x7c, 0x49,\n      0x8b, 0x9a, 0x02, 0x70, 0x05, 0x37, 0x24, 0x4e, 0xea, 0xe5, 0x90, 0xf0,\n      0x49, 0x57, 0x8b, 0xd8, 0x2f, 0x69, 0x70, 0xa9, 0x82, 0xa5, 0x51, 0xc6,\n      0xf5, 0x42, 0x63, 0xbb, 0x2c, 0xec, 0xfc, 0x78, 0xdb, 0x55, 0x2f, 0x61,\n      0x45, 0xb7, 0x3c, 0x46, 0xe3, 0xaf, 0x16, 0x18, 0xad, 0xe4, 0x2e, 0x35,\n      0x7e, 0xda, 0x01, 0xc1, 0x74, 0xf3, 0x6f, 0x02, 0x51, 0xe8, 0x3d, 0x1c,\n      0x82, 0xf0, 0x1e, 0x81,\n  };\n\n  alignas(16) uint8_t state[RandenTraits::kStateBytes];\n  std::memset(state, 0, sizeof(state));\n\n  RandenSlow::Generate(RandenSlow::GetKeys(), state);\n  EXPECT_EQ(0, std::memcmp(state, kGolden, sizeof(state)));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/randen_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/randen.h\"\n\n#include <cstring>\n\n#include \"gtest/gtest.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace {\n\nusing absl::random_internal::Randen;\n\nTEST(RandenTest, CopyAndMove) {\n  static_assert(std::is_copy_constructible<Randen>::value,\n                \"Randen must be copy constructible\");\n\n  static_assert(absl::is_copy_assignable<Randen>::value,\n                \"Randen must be copy assignable\");\n\n  static_assert(std::is_move_constructible<Randen>::value,\n                \"Randen must be move constructible\");\n\n  static_assert(absl::is_move_assignable<Randen>::value,\n                \"Randen must be move assignable\");\n}\n\nTEST(RandenTest, Default) {\n  constexpr uint8_t kGolden[] = {\n      0xee, 0xd3, 0xe6, 0x0e, 0x09, 0x34, 0x65, 0x6c, 0xc6, 0x33, 0x53, 0x9d,\n      0x9b, 0x2b, 0x4e, 0x04, 0x77, 0x39, 0x43, 0x4e, 0x13, 0x4f, 0xc1, 0xc3,\n      0xee, 0x10, 0x04, 0xd9, 0x7c, 0xf4, 0xa9, 0xdd, 0x10, 0xca, 0xd8, 0x7f,\n      0x08, 0xf3, 0x7b, 0x88, 0x12, 0x29, 0xc7, 0x45, 0xf5, 0x80, 0xb7, 0xf0,\n      0x9f, 0x59, 0x96, 0x76, 0xd3, 0xb1, 0xdb, 0x15, 0x59, 0x6d, 0x3c, 0xff,\n      0xba, 0x63, 0xec, 0x30, 0xa6, 0x20, 0x7f, 0x6f, 0x60, 0x73, 0x9f, 0xb2,\n      0x4c, 0xa5, 0x49, 0x6f, 0x31, 0x8a, 0x80, 0x02, 0x0e, 0xe5, 0xc8, 0xd5,\n      0xf9, 0xea, 0x8f, 0x3b, 0x8a, 0xde, 0xd9, 0x3f, 0x5e, 0x60, 0xbf, 0x9c,\n      0xbb, 0x3b, 0x18, 0x78, 0x1a, 0xae, 0x70, 0xc9, 0xd5, 0x1e, 0x30, 0x56,\n      0xd3, 0xff, 0xb2, 0xd8, 0x37, 0x3c, 0xc7, 0x0f, 0xfe, 0x27, 0xb3, 0xf4,\n      0x19, 0x9a, 0x8f, 0xeb, 0x76, 0x8d, 0xfd, 0xcd, 0x9d, 0x0c, 0x42, 0x91,\n      0xeb, 0x06, 0xa5, 0xc3, 0x56, 0x95, 0xff, 0x3e, 0xdd, 0x05, 0xaf, 0xd5,\n      0xa1, 0xc4, 0x83, 0x8f, 0xb7, 0x1b, 0xdb, 0x48, 0x8c, 0xfe, 0x6b, 0x0d,\n      0x0e, 0x92, 0x23, 0x70, 0x42, 0x6d, 0x95, 0x34, 0x58, 0x57, 0xd3, 0x58,\n      0x40, 0xb8, 0x87, 0x6b, 0xc2, 0xf4, 0x1e, 0xed, 0xf3, 0x2d, 0x0b, 0x3e,\n      0xa2, 0x32, 0xef, 0x8e, 0xfc, 0x54, 0x11, 0x43, 0xf3, 0xab, 0x7c, 0x49,\n      0x8b, 0x9a, 0x02, 0x70, 0x05, 0x37, 0x24, 0x4e, 0xea, 0xe5, 0x90, 0xf0,\n      0x49, 0x57, 0x8b, 0xd8, 0x2f, 0x69, 0x70, 0xa9, 0x82, 0xa5, 0x51, 0xc6,\n      0xf5, 0x42, 0x63, 0xbb, 0x2c, 0xec, 0xfc, 0x78, 0xdb, 0x55, 0x2f, 0x61,\n      0x45, 0xb7, 0x3c, 0x46, 0xe3, 0xaf, 0x16, 0x18, 0xad, 0xe4, 0x2e, 0x35,\n      0x7e, 0xda, 0x01, 0xc1, 0x74, 0xf3, 0x6f, 0x02, 0x51, 0xe8, 0x3d, 0x1c,\n      0x82, 0xf0, 0x1e, 0x81,\n  };\n\n  alignas(16) uint8_t state[Randen::kStateBytes];\n  std::memset(state, 0, sizeof(state));\n\n  Randen r;\n  r.Generate(state);\n\n  EXPECT_EQ(0, std::memcmp(state, kGolden, sizeof(state)));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/randen_traits.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_\n#define ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_\n\n// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate\n// symbols from arbitrary system and other headers, since it may be built\n// with different flags from other targets, using different levels of\n// optimization, potentially introducing ODR violations.\n\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// RANDen = RANDom generator or beetroots in Swiss High German.\n// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random\n// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.\n//\n// High-level summary:\n// 1) Reverie (see \"A Robust and Sponge-Like PRNG with Improved Efficiency\") is\n//    a sponge-like random generator that requires a cryptographic permutation.\n//    It improves upon \"Provably Robust Sponge-Based PRNGs and KDFs\" by\n//    achieving backtracking resistance with only one Permute() per buffer.\n//\n// 2) \"Simpira v2: A Family of Efficient Permutations Using the AES Round\n//    Function\" constructs up to 1024-bit permutations using an improved\n//    Generalized Feistel network with 2-round AES-128 functions. This Feistel\n//    block shuffle achieves diffusion faster and is less vulnerable to\n//    sliced-biclique attacks than the Type-2 cyclic shuffle.\n//\n// 3) \"Improving the Generalized Feistel\" and \"New criterion for diffusion\n//    property\" extends the same kind of improved Feistel block shuffle to 16\n//    branches, which enables a 2048-bit permutation.\n//\n// Combine these three ideas and also change Simpira's subround keys from\n// structured/low-entropy counters to digits of Pi (or other random source).\n\n// RandenTraits contains the basic algorithm traits, such as the size of the\n// state, seed, sponge, etc.\nstruct RandenTraits {\n  // Size of the entire sponge / state for the randen PRNG.\n  static constexpr size_t kStateBytes = 256;  // 2048-bit\n\n  // Size of the 'inner' (inaccessible) part of the sponge. Larger values would\n  // require more frequent calls to RandenGenerate.\n  static constexpr size_t kCapacityBytes = 16;  // 128-bit\n\n  // Size of the default seed consumed by the sponge.\n  static constexpr size_t kSeedBytes = kStateBytes - kCapacityBytes;\n\n  // Assuming 128-bit blocks, the number of blocks in the state.\n  // Largest size for which security proofs are known.\n  static constexpr size_t kFeistelBlocks = 16;\n\n  // Ensures SPRP security and two full subblock diffusions.\n  // Must be > 4 * log2(kFeistelBlocks).\n  static constexpr size_t kFeistelRounds = 16 + 1;\n\n  // Size of the key. A 128-bit key block is used for every-other\n  // feistel block (Type-2 generalized Feistel network) in each round.\n  static constexpr size_t kKeyBytes = 16 * kFeistelRounds * kFeistelBlocks / 2;\n};\n\n// Randen key arrays. In randen_round_keys.cc\nextern const unsigned char kRandenRoundKeys[RandenTraits::kKeyBytes];\nextern const unsigned char kRandenRoundKeysBE[RandenTraits::kKeyBytes];\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_\n"
  },
  {
    "path": "absl/random/internal/salted_seed_seq.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_\n#define ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_\n\n#include <cstdint>\n#include <cstdlib>\n#include <initializer_list>\n#include <iterator>\n#include <memory>\n#include <optional>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/seed_material.h\"\n#include \"absl/types/optional.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// This class conforms to the C++ Standard \"Seed Sequence\" concept\n// [rand.req.seedseq].\n//\n// A `SaltedSeedSeq` is meant to wrap an existing seed sequence and modify\n// generated sequence by mixing with extra entropy. This entropy may be\n// build-dependent or process-dependent. The implementation may change to be\n// have either or both kinds of entropy. If salt is not available sequence is\n// not modified.\ntemplate <typename SSeq>\nclass SaltedSeedSeq {\n public:\n  using inner_sequence_type = SSeq;\n  using result_type = typename SSeq::result_type;\n\n  SaltedSeedSeq() : seq_(absl::make_unique<SSeq>()) {}\n\n  template <typename Iterator>\n  SaltedSeedSeq(Iterator begin, Iterator end)\n      : seq_(absl::make_unique<SSeq>(begin, end)) {}\n\n  template <typename T>\n  SaltedSeedSeq(std::initializer_list<T> il)\n      : SaltedSeedSeq(il.begin(), il.end()) {}\n\n  SaltedSeedSeq(const SaltedSeedSeq&) = delete;\n  SaltedSeedSeq& operator=(const SaltedSeedSeq&) = delete;\n\n  SaltedSeedSeq(SaltedSeedSeq&&) = default;\n  SaltedSeedSeq& operator=(SaltedSeedSeq&&) = default;\n\n  template <typename RandomAccessIterator>\n  void generate(RandomAccessIterator begin, RandomAccessIterator end) {\n    using U = typename std::iterator_traits<RandomAccessIterator>::value_type;\n\n    // The common case is that generate is called with ContiguousIterators\n    // to uint arrays. Such contiguous memory regions may be optimized,\n    // which we detect here.\n    using TagType = absl::conditional_t<\n        (std::is_same<U, uint32_t>::value &&\n         (std::is_pointer<RandomAccessIterator>::value ||\n          std::is_same<RandomAccessIterator,\n                       typename std::vector<U>::iterator>::value)),\n        ContiguousAndUint32Tag, DefaultTag>;\n    if (begin != end) {\n      generate_impl(TagType{}, begin, end, std::distance(begin, end));\n    }\n  }\n\n  template <typename OutIterator>\n  void param(OutIterator out) const {\n    seq_->param(out);\n  }\n\n  size_t size() const { return seq_->size(); }\n\n private:\n  struct ContiguousAndUint32Tag {};\n  struct DefaultTag {};\n\n  // Generate which requires the iterators are contiguous pointers to uint32_t.\n  // Fills the initial seed buffer the underlying SSeq::generate() call,\n  // then mixes in the salt material.\n  template <typename Contiguous>\n  void generate_impl(ContiguousAndUint32Tag, Contiguous begin, Contiguous end,\n                     size_t n) {\n    seq_->generate(begin, end);\n    const uint32_t salt = absl::random_internal::GetSaltMaterial().value_or(0);\n    auto span = absl::Span<uint32_t>(&*begin, n);\n    MixIntoSeedMaterial(absl::MakeConstSpan(&salt, 1), span);\n  }\n\n  // The uncommon case for generate is that it is called with iterators over\n  // some other buffer type which is assignable from a 32-bit value. In this\n  // case we allocate a temporary 32-bit buffer and then copy-assign back\n  // to the initial inputs.\n  template <typename RandomAccessIterator>\n  void generate_impl(DefaultTag, RandomAccessIterator begin,\n                     RandomAccessIterator, size_t n) {\n    // Allocates a seed buffer of `n` elements, generates the seed, then\n    // copies the result into the `out` iterator.\n    absl::InlinedVector<uint32_t, 8> data(n, 0);\n    generate_impl(ContiguousAndUint32Tag{}, data.begin(), data.end(), n);\n    std::copy(data.begin(), data.end(), begin);\n  }\n\n  // Because [rand.req.seedseq] is not required to be copy-constructible,\n  // copy-assignable nor movable, we wrap it with unique pointer to be able\n  // to move SaltedSeedSeq.\n  std::unique_ptr<SSeq> seq_;\n};\n\n// is_salted_seed_seq indicates whether the type is a SaltedSeedSeq.\ntemplate <typename T, typename = void>\nstruct is_salted_seed_seq : public std::false_type {};\n\ntemplate <typename T>\nstruct is_salted_seed_seq<\n    T, typename std::enable_if<std::is_same<\n           T, SaltedSeedSeq<typename T::inner_sequence_type>>::value>::type>\n    : public std::true_type {};\n\n// MakeSaltedSeedSeq returns a salted variant of the seed sequence.\n// When provided with an existing SaltedSeedSeq, returns the input parameter,\n// otherwise constructs a new SaltedSeedSeq which embodies the original\n// non-salted seed parameters.\ntemplate <\n    typename SSeq,  //\n    typename EnableIf = absl::enable_if_t<is_salted_seed_seq<SSeq>::value>>\nSSeq MakeSaltedSeedSeq(SSeq&& seq) {\n  return SSeq(std::forward<SSeq>(seq));\n}\n\ntemplate <\n    typename SSeq,  //\n    typename EnableIf = absl::enable_if_t<!is_salted_seed_seq<SSeq>::value>>\nSaltedSeedSeq<typename std::decay<SSeq>::type> MakeSaltedSeedSeq(SSeq&& seq) {\n  using sseq_type = typename std::decay<SSeq>::type;\n  using result_type = typename sseq_type::result_type;\n\n  absl::InlinedVector<result_type, 8> data;\n  seq.param(std::back_inserter(data));\n  return SaltedSeedSeq<sseq_type>(data.begin(), data.end());\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_\n"
  },
  {
    "path": "absl/random/internal/salted_seed_seq_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/salted_seed_seq.h\"\n\n#include <iterator>\n#include <random>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nusing absl::random_internal::GetSaltMaterial;\nusing absl::random_internal::MakeSaltedSeedSeq;\nusing absl::random_internal::SaltedSeedSeq;\nusing testing::Eq;\nusing testing::Pointwise;\n\nnamespace {\n\ntemplate <typename Sseq>\nvoid ConformsToInterface() {\n  // Check that the SeedSequence can be default-constructed.\n  {\n    Sseq default_constructed_seq;\n  }\n  // Check that the SeedSequence can be constructed with two iterators.\n  {\n    uint32_t init_array[] = {1, 3, 5, 7, 9};\n    Sseq iterator_constructed_seq(std::begin(init_array), std::end(init_array));\n  }\n  // Check that the SeedSequence can be std::initializer_list-constructed.\n  {\n    Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13};\n  }\n  // Check that param() and size() return state provided to constructor.\n  {\n    uint32_t init_array[] = {1, 2, 3, 4, 5};\n    Sseq seq(std::begin(init_array), std::end(init_array));\n    EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array));\n\n    std::vector<uint32_t> state_vector;\n    seq.param(std::back_inserter(state_vector));\n\n    EXPECT_EQ(state_vector.size(), ABSL_ARRAYSIZE(init_array));\n    for (int i = 0; i < state_vector.size(); i++) {\n      EXPECT_EQ(state_vector[i], i + 1);\n    }\n  }\n  // Check for presence of generate() method.\n  {\n    Sseq seq;\n    uint32_t seeds[5];\n\n    seq.generate(std::begin(seeds), std::end(seeds));\n  }\n}\n\nTEST(SaltedSeedSeq, CheckInterfaces) {\n  // Control case\n  ConformsToInterface<std::seed_seq>();\n\n  // Abseil classes\n  ConformsToInterface<SaltedSeedSeq<std::seed_seq>>();\n}\n\nTEST(SaltedSeedSeq, CheckConstructingFromOtherSequence) {\n  std::vector<uint32_t> seed_values(10, 1);\n  std::seed_seq seq(seed_values.begin(), seed_values.end());\n  auto salted_seq = MakeSaltedSeedSeq(std::move(seq));\n\n  EXPECT_EQ(seq.size(), salted_seq.size());\n\n  std::vector<uint32_t> param_result;\n  seq.param(std::back_inserter(param_result));\n\n  EXPECT_EQ(seed_values, param_result);\n}\n\nTEST(SaltedSeedSeq, SaltedSaltedSeedSeqIsNotDoubleSalted) {\n  uint32_t init[] = {1, 3, 5, 7, 9};\n\n  std::seed_seq seq(std::begin(init), std::end(init));\n\n  // The first salting.\n  SaltedSeedSeq<std::seed_seq> salted_seq = MakeSaltedSeedSeq(std::move(seq));\n  uint32_t a[16];\n  salted_seq.generate(std::begin(a), std::end(a));\n\n  // The second salting.\n  SaltedSeedSeq<std::seed_seq> salted_salted_seq =\n      MakeSaltedSeedSeq(std::move(salted_seq));\n  uint32_t b[16];\n  salted_salted_seq.generate(std::begin(b), std::end(b));\n\n  // ... both should be equal.\n  EXPECT_THAT(b, Pointwise(Eq(), a)) << \"a[0] \" << a[0];\n}\n\nTEST(SaltedSeedSeq, SeedMaterialIsSalted) {\n  const size_t kNumBlocks = 16;\n\n  uint32_t seed_material[kNumBlocks];\n  std::random_device urandom{\"/dev/urandom\"};\n  for (uint32_t& seed : seed_material) {\n    seed = urandom();\n  }\n\n  std::seed_seq seq(std::begin(seed_material), std::end(seed_material));\n  SaltedSeedSeq<std::seed_seq> salted_seq(std::begin(seed_material),\n                                          std::end(seed_material));\n\n  bool salt_is_available = GetSaltMaterial().has_value();\n\n  // If salt is available generated sequence should be different.\n  if (salt_is_available) {\n    uint32_t outputs[kNumBlocks];\n    uint32_t salted_outputs[kNumBlocks];\n\n    seq.generate(std::begin(outputs), std::end(outputs));\n    salted_seq.generate(std::begin(salted_outputs), std::end(salted_outputs));\n\n    EXPECT_THAT(outputs, Pointwise(testing::Ne(), salted_outputs));\n  }\n}\n\nTEST(SaltedSeedSeq, GenerateAcceptsDifferentTypes) {\n  const size_t kNumBlocks = 4;\n\n  SaltedSeedSeq<std::seed_seq> seq({1, 2, 3});\n\n  uint32_t expected[kNumBlocks];\n  seq.generate(std::begin(expected), std::end(expected));\n\n  // 32-bit outputs\n  {\n    unsigned long seed_material[kNumBlocks];  // NOLINT(runtime/int)\n    seq.generate(std::begin(seed_material), std::end(seed_material));\n    EXPECT_THAT(seed_material, Pointwise(Eq(), expected));\n  }\n  {\n    unsigned int seed_material[kNumBlocks];  // NOLINT(runtime/int)\n    seq.generate(std::begin(seed_material), std::end(seed_material));\n    EXPECT_THAT(seed_material, Pointwise(Eq(), expected));\n  }\n\n  // 64-bit outputs.\n  {\n    uint64_t seed_material[kNumBlocks];\n    seq.generate(std::begin(seed_material), std::end(seed_material));\n    EXPECT_THAT(seed_material, Pointwise(Eq(), expected));\n  }\n  {\n    int64_t seed_material[kNumBlocks];\n    seq.generate(std::begin(seed_material), std::end(seed_material));\n    EXPECT_THAT(seed_material, Pointwise(Eq(), expected));\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/seed_material.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/seed_material.h\"\n\n#include <fcntl.h>\n\n#ifndef _WIN32\n#include <unistd.h>\n#else\n#include <io.h>\n#endif\n\n#include <algorithm>\n#include <cassert>\n#include <cerrno>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <optional>\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/types/span.h\"\n\n#if defined(_WIN32)\n\n#include <windows.h>\n#define ABSL_RANDOM_USE_BCRYPT 1\n#pragma comment(lib, \"bcrypt.lib\")\n\n#elif defined(__Fuchsia__)\n#include <zircon/syscalls.h>\n\n#endif\n\n#if defined(__GLIBC__) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))\n// glibc >= 2.25 has getentropy()\n#define ABSL_RANDOM_USE_GET_ENTROPY 1\n#endif\n\n#if defined(__EMSCRIPTEN__)\n#include <sys/random.h>\n// Emscripten has getentropy, but it resides in a different header.\n#define ABSL_RANDOM_USE_GET_ENTROPY 1\n#endif\n\n#if defined(ABSL_RANDOM_USE_BCRYPT)\n#include <bcrypt.h>\n\n#ifndef BCRYPT_SUCCESS\n#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)\n#endif\n// Also link bcrypt; this can be done via linker options or:\n// #pragma comment(lib, \"bcrypt.lib\")\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\nnamespace {\n\n// Read OS Entropy for random number seeds.\n// TODO(absl-team): Possibly place a cap on how much entropy may be read at a\n// time.\n\n#if defined(ABSL_RANDOM_USE_BCRYPT)\n\n// On Windows potentially use the BCRYPT CNG API to read available entropy.\nbool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {\n  BCRYPT_ALG_HANDLE hProvider;\n  NTSTATUS ret;\n  ret = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RNG_ALGORITHM,\n                                    MS_PRIMITIVE_PROVIDER, 0);\n  if (!(BCRYPT_SUCCESS(ret))) {\n    ABSL_RAW_LOG(ERROR, \"Failed to open crypto provider.\");\n    return false;\n  }\n  ret = BCryptGenRandom(\n      hProvider,                                             // provider\n      reinterpret_cast<UCHAR*>(values.data()),               // buffer\n      static_cast<ULONG>(sizeof(uint32_t) * values.size()),  // bytes\n      0);                                                    // flags\n  BCryptCloseAlgorithmProvider(hProvider, 0);\n  return BCRYPT_SUCCESS(ret);\n}\n\n#elif defined(__Fuchsia__)\n\nbool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {\n  auto buffer = reinterpret_cast<uint8_t*>(values.data());\n  size_t buffer_size = sizeof(uint32_t) * values.size();\n  zx_cprng_draw(buffer, buffer_size);\n  return true;\n}\n\n#else\n\n#if defined(ABSL_RANDOM_USE_GET_ENTROPY)\n// On *nix, use getentropy() if supported. Note that libc may support\n// getentropy(), but the kernel may not, in which case this function will return\n// false.\nbool ReadSeedMaterialFromGetEntropy(absl::Span<uint32_t> values) {\n  auto buffer = reinterpret_cast<uint8_t*>(values.data());\n  size_t buffer_size = sizeof(uint32_t) * values.size();\n  while (buffer_size > 0) {\n    // getentropy() has a maximum permitted length of 256.\n    size_t to_read = std::min<size_t>(buffer_size, 256);\n    int result = getentropy(buffer, to_read);\n    if (result < 0) {\n      return false;\n    }\n    // https://github.com/google/sanitizers/issues/1173\n    // MemorySanitizer can't see through getentropy().\n    ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buffer, to_read);\n    buffer += to_read;\n    buffer_size -= to_read;\n  }\n  return true;\n}\n#endif  // defined(ABSL_RANDOM_GETENTROPY)\n\n// On *nix, read entropy from /dev/urandom.\nbool ReadSeedMaterialFromDevURandom(absl::Span<uint32_t> values) {\n  const char kEntropyFile[] = \"/dev/urandom\";\n\n  auto buffer = reinterpret_cast<uint8_t*>(values.data());\n  size_t buffer_size = sizeof(uint32_t) * values.size();\n\n  int dev_urandom = open(kEntropyFile, O_RDONLY);\n  if (dev_urandom < 0) {\n    ABSL_RAW_LOG(ERROR, \"Failed to open /dev/urandom.\");\n    return false;\n  }\n\n  while (buffer_size > 0) {\n    ssize_t bytes_read = read(dev_urandom, buffer, buffer_size);\n    int read_error = errno;\n    if (bytes_read == -1 && read_error == EINTR) {\n      // Interrupted, try again.\n      continue;\n    } else if (bytes_read <= 0) {\n      // EOF, or error.\n      break;\n    }\n    buffer += bytes_read;\n    buffer_size -= static_cast<size_t>(bytes_read);\n  }\n\n  close(dev_urandom);\n  return buffer_size == 0;\n}\n\nbool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {\n#if defined(ABSL_RANDOM_USE_GET_ENTROPY)\n  if (ReadSeedMaterialFromGetEntropy(values)) {\n    return true;\n  }\n#endif\n  // Libc may support getentropy, but the kernel may not, so we still have\n  // to fallback to ReadSeedMaterialFromDevURandom().\n  return ReadSeedMaterialFromDevURandom(values);\n}\n\n#endif\n\n}  // namespace\n\nbool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values) {\n  assert(values.data() != nullptr);\n  if (values.data() == nullptr) {\n    return false;\n  }\n  if (values.empty()) {\n    return true;\n  }\n  return ReadSeedMaterialFromOSEntropyImpl(values);\n}\n\nvoid MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,\n                         absl::Span<uint32_t> seed_material) {\n  // Algorithm is based on code available at\n  // https://gist.github.com/imneme/540829265469e673d045\n  constexpr uint32_t kInitVal = 0x43b0d7e5;\n  constexpr uint32_t kHashMul = 0x931e8875;\n  constexpr uint32_t kMixMulL = 0xca01f9dd;\n  constexpr uint32_t kMixMulR = 0x4973f715;\n  constexpr uint32_t kShiftSize = sizeof(uint32_t) * 8 / 2;\n\n  uint32_t hash_const = kInitVal;\n  auto hash = [&](uint32_t value) {\n    value ^= hash_const;\n    hash_const *= kHashMul;\n    value *= hash_const;\n    value ^= value >> kShiftSize;\n    return value;\n  };\n\n  auto mix = [&](uint32_t x, uint32_t y) {\n    uint32_t result = kMixMulL * x - kMixMulR * y;\n    result ^= result >> kShiftSize;\n    return result;\n  };\n\n  for (const auto& seq_val : sequence) {\n    for (auto& elem : seed_material) {\n      elem = mix(elem, hash(seq_val));\n    }\n  }\n}\n\nstd::optional<uint32_t> GetSaltMaterial() {\n  // Salt must be common for all generators within the same process so read it\n  // only once and store in static variable.\n  static const auto salt_material = []() -> std::optional<uint32_t> {\n    uint32_t salt_value = 0;\n\n    if (ReadSeedMaterialFromOSEntropy(absl::MakeSpan(&salt_value, 1))) {\n      return salt_value;\n    }\n\n    return std::nullopt;\n  }();\n\n  return salt_material;\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/internal/seed_material.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_\n#define ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_\n\n#include <cassert>\n#include <cstdint>\n#include <cstdlib>\n#include <optional>\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/types/optional.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// Returns the number of 32-bit blocks needed to contain the given number of\n// bits.\nconstexpr size_t SeedBitsToBlocks(size_t seed_size) {\n  return (seed_size + 31) / 32;\n}\n\n// Amount of entropy (measured in bits) used to instantiate a Seed Sequence,\n// with which to create a URBG.\nconstexpr size_t kEntropyBitsNeeded = 256;\n\n// Amount of entropy (measured in 32-bit blocks) used to instantiate a Seed\n// Sequence, with which to create a URBG.\nconstexpr size_t kEntropyBlocksNeeded =\n    random_internal::SeedBitsToBlocks(kEntropyBitsNeeded);\n\nstatic_assert(kEntropyBlocksNeeded > 0,\n              \"Entropy used to seed URBGs must be nonzero.\");\n\n// Attempts to fill a span of uint32_t-values using an OS-provided source of\n// true entropy (eg. /dev/urandom) into an array of uint32_t blocks of data. The\n// resulting array may be used to initialize an instance of a class conforming\n// to the C++ Standard \"Seed Sequence\" concept [rand.req.seedseq].\n//\n// If values.data() == nullptr, the behavior is undefined.\n[[nodiscard]]\nbool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values);\n\n// Attempts to fill a span of uint32_t-values using variates generated by an\n// existing instance of a class conforming to the C++ Standard \"Uniform Random\n// Bit Generator\" concept [rand.req.urng]. The resulting data may be used to\n// initialize an instance of a class conforming to the C++ Standard\n// \"Seed Sequence\" concept [rand.req.seedseq].\n//\n// If urbg == nullptr or values.data() == nullptr, the behavior is undefined.\ntemplate <typename URBG>\n[[nodiscard]] bool ReadSeedMaterialFromURBG(URBG* urbg,\n                                            absl::Span<uint32_t> values) {\n  random_internal::FastUniformBits<uint32_t> distr;\n\n  assert(urbg != nullptr && values.data() != nullptr);\n  if (urbg == nullptr || values.data() == nullptr) {\n    return false;\n  }\n\n  for (uint32_t& seed_value : values) {\n    seed_value = distr(*urbg);\n  }\n  return true;\n}\n\n// Mixes given sequence of values with into given sequence of seed material.\n// Time complexity of this function is O(sequence.size() *\n// seed_material.size()).\n//\n// Algorithm is based on code available at\n// https://gist.github.com/imneme/540829265469e673d045\n// by Melissa O'Neill.\nvoid MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,\n                         absl::Span<uint32_t> seed_material);\n\n// Returns salt value.\n//\n// Salt is obtained only once and stored in static variable.\n//\n// May return empty value if obtaining the salt was not possible.\nstd::optional<uint32_t> GetSaltMaterial();\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_\n"
  },
  {
    "path": "absl/random/internal/seed_material_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/seed_material.h\"\n\n#include <bitset>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <random>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/types/span.h\"\n\n#ifdef __ANDROID__\n// Android assert messages only go to system log, so death tests cannot inspect\n// the message for matching.\n#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \\\n  EXPECT_DEATH_IF_SUPPORTED(statement, \".*\")\n#else\n#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \\\n  EXPECT_DEATH_IF_SUPPORTED(statement, regex)\n#endif\n\nnamespace {\n\nusing testing::Each;\nusing testing::ElementsAre;\nusing testing::Eq;\nusing testing::Ne;\nusing testing::Pointwise;\n\nTEST(SeedBitsToBlocks, VerifyCases) {\n  EXPECT_EQ(0, absl::random_internal::SeedBitsToBlocks(0));\n  EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(1));\n  EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(31));\n  EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(32));\n  EXPECT_EQ(2, absl::random_internal::SeedBitsToBlocks(33));\n  EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(127));\n  EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(128));\n  EXPECT_EQ(5, absl::random_internal::SeedBitsToBlocks(129));\n}\n\nTEST(ReadSeedMaterialFromOSEntropy, SuccessiveReadsAreDistinct) {\n  constexpr size_t kSeedMaterialSize = 64;\n  uint32_t seed_material_1[kSeedMaterialSize] = {};\n  uint32_t seed_material_2[kSeedMaterialSize] = {};\n\n  EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(\n      absl::Span<uint32_t>(seed_material_1, kSeedMaterialSize)));\n  EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(\n      absl::Span<uint32_t>(seed_material_2, kSeedMaterialSize)));\n\n  EXPECT_THAT(seed_material_1, Pointwise(Ne(), seed_material_2));\n}\n\nTEST(ReadSeedMaterialFromOSEntropy, ReadZeroBytesIsNoOp) {\n  uint32_t seed_material[32] = {};\n  std::memset(seed_material, 0xAA, sizeof(seed_material));\n  EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(\n      absl::Span<uint32_t>(seed_material, 0)));\n\n  EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA)));\n}\n\nTEST(ReadSeedMaterialFromOSEntropy, NullPtrVectorArgument) {\n#ifdef NDEBUG\n  EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromOSEntropy(\n      absl::Span<uint32_t>(nullptr, 32)));\n#else\n  bool result;\n  ABSL_EXPECT_DEATH_IF_SUPPORTED(\n      result = absl::random_internal::ReadSeedMaterialFromOSEntropy(\n          absl::Span<uint32_t>(nullptr, 32)),\n      \"!= nullptr\");\n  (void)result;  // suppress unused-variable warning\n#endif\n}\n\nTEST(ReadSeedMaterialFromURBG, SeedMaterialEqualsVariateSequence) {\n  // Two default-constructed instances of std::mt19937_64 are guaranteed to\n  // produce equal variate-sequences.\n  std::mt19937 urbg_1;\n  std::mt19937 urbg_2;\n  constexpr size_t kSeedMaterialSize = 1024;\n  uint32_t seed_material[kSeedMaterialSize] = {};\n\n  EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG(\n      &urbg_1, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)));\n  for (uint32_t seed : seed_material) {\n    EXPECT_EQ(seed, urbg_2());\n  }\n}\n\nTEST(ReadSeedMaterialFromURBG, ReadZeroBytesIsNoOp) {\n  std::mt19937_64 urbg;\n  uint32_t seed_material[32];\n  std::memset(seed_material, 0xAA, sizeof(seed_material));\n  EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG(\n      &urbg, absl::Span<uint32_t>(seed_material, 0)));\n\n  EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA)));\n}\n\nTEST(ReadSeedMaterialFromURBG, NullUrbgArgument) {\n  constexpr size_t kSeedMaterialSize = 32;\n  uint32_t seed_material[kSeedMaterialSize];\n#ifdef NDEBUG\n  EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>(\n      nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)));\n#else\n  bool result;\n  ABSL_EXPECT_DEATH_IF_SUPPORTED(\n      result = absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>(\n          nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)),\n      \"!= nullptr\");\n  (void)result;  // suppress unused-variable warning\n#endif\n}\n\nTEST(ReadSeedMaterialFromURBG, NullPtrVectorArgument) {\n  std::mt19937_64 urbg;\n#ifdef NDEBUG\n  EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG(\n      &urbg, absl::Span<uint32_t>(nullptr, 32)));\n#else\n  bool result;\n  ABSL_EXPECT_DEATH_IF_SUPPORTED(\n      result = absl::random_internal::ReadSeedMaterialFromURBG(\n          &urbg, absl::Span<uint32_t>(nullptr, 32)),\n      \"!= nullptr\");\n  (void)result;  // suppress unused-variable warning\n#endif\n}\n\n// The avalanche effect is a desirable cryptographic property of hashes in which\n// changing a single bit in the input causes each bit of the output to be\n// changed with probability near 50%.\n//\n// https://en.wikipedia.org/wiki/Avalanche_effect\n\nTEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitLong) {\n  std::vector<uint32_t> seed_material = {1, 2, 3, 4, 5, 6, 7, 8};\n\n  // For every 32-bit number with exactly one bit set, verify the avalanche\n  // effect holds.  In order to reduce flakiness of tests, accept values\n  // anywhere in the range of 30%-70%.\n  for (uint32_t v = 1; v != 0; v <<= 1) {\n    std::vector<uint32_t> seed_material_copy = seed_material;\n    absl::random_internal::MixIntoSeedMaterial(\n        absl::Span<uint32_t>(&v, 1),\n        absl::Span<uint32_t>(seed_material_copy.data(),\n                             seed_material_copy.size()));\n\n    uint32_t changed_bits = 0;\n    for (size_t i = 0; i < seed_material.size(); i++) {\n      std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^\n                                               seed_material_copy[i]);\n      changed_bits += bitset.count();\n    }\n\n    EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size());\n    EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size());\n  }\n}\n\nTEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitShort) {\n  std::vector<uint32_t> seed_material = {1};\n\n  // For every 32-bit number with exactly one bit set, verify the avalanche\n  // effect holds.  In order to reduce flakiness of tests, accept values\n  // anywhere in the range of 30%-70%.\n  for (uint32_t v = 1; v != 0; v <<= 1) {\n    std::vector<uint32_t> seed_material_copy = seed_material;\n    absl::random_internal::MixIntoSeedMaterial(\n        absl::Span<uint32_t>(&v, 1),\n        absl::Span<uint32_t>(seed_material_copy.data(),\n                             seed_material_copy.size()));\n\n    uint32_t changed_bits = 0;\n    for (size_t i = 0; i < seed_material.size(); i++) {\n      std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^\n                                               seed_material_copy[i]);\n      changed_bits += bitset.count();\n    }\n\n    EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size());\n    EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size());\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/sequence_urbg.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_\n#define ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_\n\n#include <cstdint>\n#include <cstring>\n#include <limits>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// `sequence_urbg` is a simple random number generator which meets the\n// requirements of [rand.req.urbg], and is solely for testing absl\n// distributions.\nclass sequence_urbg {\n public:\n  using result_type = uint64_t;\n\n  static constexpr result_type(min)() {\n    return (std::numeric_limits<result_type>::min)();\n  }\n  static constexpr result_type(max)() {\n    return (std::numeric_limits<result_type>::max)();\n  }\n\n  sequence_urbg(std::initializer_list<result_type> data) : i_(0), data_(data) {}\n  void reset() { i_ = 0; }\n\n  result_type operator()() { return data_[i_++ % data_.size()]; }\n\n  size_t invocations() const { return i_; }\n\n private:\n  size_t i_;\n  std::vector<result_type> data_;\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_\n"
  },
  {
    "path": "absl/random/internal/traits.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_\n#define ABSL_RANDOM_INTERNAL_TRAITS_H_\n\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// random_internal::is_widening_convertible<A, B>\n//\n// Returns whether a type A is widening-convertible to a type B.\n//\n// A is widening-convertible to B means:\n//   A a = <any number>;\n//   B b = a;\n//   A c = b;\n//   EXPECT_EQ(a, c);\ntemplate <typename A, typename B>\nclass is_widening_convertible {\n  // As long as there are enough bits in the exact part of a number:\n  // - unsigned can fit in float, signed, unsigned\n  // - signed can fit in float, signed\n  // - float can fit in float\n  // So we define rank to be:\n  // - rank(float) -> 2\n  // - rank(signed) -> 1\n  // - rank(unsigned) -> 0\n  template <class T>\n  static constexpr int rank() {\n    return !std::numeric_limits<T>::is_integer +\n           std::numeric_limits<T>::is_signed;\n  }\n\n public:\n  // If an arithmetic-type B can represent at least as many digits as a type A,\n  // and B belongs to a rank no lower than A, then A can be safely represented\n  // by B through a widening-conversion.\n  static constexpr bool value =\n      std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&\n      rank<A>() <= rank<B>();\n};\n\ntemplate <typename T>\nstruct IsIntegral : std::is_integral<T> {};\ntemplate <>\nstruct IsIntegral<absl::int128> : std::true_type {};\ntemplate <>\nstruct IsIntegral<absl::uint128> : std::true_type {};\n\ntemplate <typename T>\nstruct MakeUnsigned : std::make_unsigned<T> {};\ntemplate <>\nstruct MakeUnsigned<absl::int128> {\n  using type = absl::uint128;\n};\ntemplate <>\nstruct MakeUnsigned<absl::uint128> {\n  using type = absl::uint128;\n};\n\ntemplate <typename T>\nstruct IsUnsigned : std::is_unsigned<T> {};\ntemplate <>\nstruct IsUnsigned<absl::int128> : std::false_type {};\ntemplate <>\nstruct IsUnsigned<absl::uint128> : std::true_type {};\n\n// unsigned_bits<N>::type returns the unsigned int type with the indicated\n// number of bits.\ntemplate <size_t N>\nstruct unsigned_bits;\n\ntemplate <>\nstruct unsigned_bits<8> {\n  using type = uint8_t;\n};\ntemplate <>\nstruct unsigned_bits<16> {\n  using type = uint16_t;\n};\ntemplate <>\nstruct unsigned_bits<32> {\n  using type = uint32_t;\n};\ntemplate <>\nstruct unsigned_bits<64> {\n  using type = uint64_t;\n};\n\ntemplate <>\nstruct unsigned_bits<128> {\n  using type = absl::uint128;\n};\n\n// 256-bit wrapper for wide multiplications.\nstruct U256 {\n  uint128 hi;\n  uint128 lo;\n};\ntemplate <>\nstruct unsigned_bits<256> {\n  using type = U256;\n};\n\ntemplate <typename IntType>\nstruct make_unsigned_bits {\n  using type = typename unsigned_bits<\n      std::numeric_limits<typename MakeUnsigned<IntType>::type>::digits>::type;\n};\n\ntemplate <typename T>\nint BitWidth(T v) {\n  // Workaround for bit_width not supporting int128.\n  // Don't hardcode `64` to make sure this code does not trigger compiler\n  // warnings in smaller types.\n  constexpr int half_bits = sizeof(T) * 8 / 2;\n  if (sizeof(T) == 16 && (v >> half_bits) != 0) {\n    return bit_width(static_cast<uint64_t>(v >> half_bits)) + half_bits;\n  } else {\n    return bit_width(static_cast<uint64_t>(v));\n  }\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_TRAITS_H_\n"
  },
  {
    "path": "absl/random/internal/traits_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/traits.h\"\n\n#include <cstdint>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing absl::random_internal::is_widening_convertible;\n\n// CheckWideningConvertsToSelf<T1, T2, ...>()\n//\n// For each type T, checks:\n// - T IS widening-convertible to itself.\n//\ntemplate <typename T>\nvoid CheckWideningConvertsToSelf() {\n  static_assert(is_widening_convertible<T, T>::value,\n                \"Type is not convertible to self!\");\n}\n\ntemplate <typename T, typename Next, typename... Args>\nvoid CheckWideningConvertsToSelf() {\n  CheckWideningConvertsToSelf<T>();\n  CheckWideningConvertsToSelf<Next, Args...>();\n}\n\n// CheckNotWideningConvertibleWithSigned<T1, T2, ...>()\n//\n// For each unsigned-type T, checks that:\n// - T is NOT widening-convertible to Signed(T)\n// - Signed(T) is NOT widening-convertible to T\n//\ntemplate <typename T>\nvoid CheckNotWideningConvertibleWithSigned() {\n  using signed_t = typename std::make_signed<T>::type;\n\n  static_assert(!is_widening_convertible<T, signed_t>::value,\n                \"Unsigned type is convertible to same-sized signed-type!\");\n  static_assert(!is_widening_convertible<signed_t, T>::value,\n                \"Signed type is convertible to same-sized unsigned-type!\");\n}\n\ntemplate <typename T, typename Next, typename... Args>\nvoid CheckNotWideningConvertibleWithSigned() {\n  CheckNotWideningConvertibleWithSigned<T>();\n  CheckWideningConvertsToSelf<Next, Args...>();\n}\n\n// CheckWideningConvertsToLargerType<T1, T2, ...>()\n//\n// For each successive unsigned-types {Ti, Ti+1}, checks that:\n// - Ti IS widening-convertible to Ti+1\n// - Ti IS widening-convertible to Signed(Ti+1)\n// - Signed(Ti) is NOT widening-convertible to Ti\n// - Signed(Ti) IS widening-convertible to Ti+1\ntemplate <typename T, typename Higher>\nvoid CheckWideningConvertsToLargerTypes() {\n  using signed_t = typename std::make_signed<T>::type;\n  using higher_t = Higher;\n  using signed_higher_t = typename std::make_signed<Higher>::type;\n\n  static_assert(is_widening_convertible<T, higher_t>::value,\n                \"Type not embeddable into larger type!\");\n  static_assert(is_widening_convertible<T, signed_higher_t>::value,\n                \"Type not embeddable into larger signed type!\");\n  static_assert(!is_widening_convertible<signed_t, higher_t>::value,\n                \"Signed type is embeddable into larger unsigned type!\");\n  static_assert(is_widening_convertible<signed_t, signed_higher_t>::value,\n                \"Signed type not embeddable into larger signed type!\");\n}\n\ntemplate <typename T, typename Higher, typename Next, typename... Args>\nvoid CheckWideningConvertsToLargerTypes() {\n  CheckWideningConvertsToLargerTypes<T, Higher>();\n  CheckWideningConvertsToLargerTypes<Higher, Next, Args...>();\n}\n\n// CheckWideningConvertsTo<T, U, [expect]>\n//\n// Checks that T DOES widening-convert to U.\n// If \"expect\" is false, then asserts that T does NOT widening-convert to U.\ntemplate <typename T, typename U, bool expect = true>\nvoid CheckWideningConvertsTo() {\n  static_assert(is_widening_convertible<T, U>::value == expect,\n                \"Unexpected result for is_widening_convertible<T, U>!\");\n}\n\nTEST(TraitsTest, IsWideningConvertibleTest) {\n  constexpr bool kInvalid = false;\n\n  CheckWideningConvertsToSelf<uint8_t, uint16_t, uint32_t, uint64_t, int8_t,\n                              int16_t, int32_t, int64_t, float, double>();\n  CheckNotWideningConvertibleWithSigned<uint8_t, uint16_t, uint32_t,\n                                        uint64_t>();\n  CheckWideningConvertsToLargerTypes<uint8_t, uint16_t, uint32_t, uint64_t>();\n\n  CheckWideningConvertsTo<float, double>();\n  CheckWideningConvertsTo<uint16_t, float>();\n  CheckWideningConvertsTo<uint32_t, double>();\n  CheckWideningConvertsTo<uint64_t, double, kInvalid>();\n  CheckWideningConvertsTo<double, float, kInvalid>();\n\n  CheckWideningConvertsTo<bool, int>();\n  CheckWideningConvertsTo<bool, float>();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/uniform_helper.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#ifndef ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_\n#define ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_\n\n#include <cmath>\n#include <limits>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename IntType>\nclass uniform_int_distribution;\n\ntemplate <typename RealType>\nclass uniform_real_distribution;\n\n// Interval tag types which specify whether the interval is open or closed\n// on either boundary.\n\nnamespace random_internal {\ntemplate <typename T>\nstruct TagTypeCompare {};\n\ntemplate <typename T>\nconstexpr bool operator==(TagTypeCompare<T>, TagTypeCompare<T>) {\n  // Tags are mono-states. They always compare equal.\n  return true;\n}\ntemplate <typename T>\nconstexpr bool operator!=(TagTypeCompare<T>, TagTypeCompare<T>) {\n  return false;\n}\n\n}  // namespace random_internal\n\nstruct IntervalClosedClosedTag\n    : public random_internal::TagTypeCompare<IntervalClosedClosedTag> {};\nstruct IntervalClosedOpenTag\n    : public random_internal::TagTypeCompare<IntervalClosedOpenTag> {};\nstruct IntervalOpenClosedTag\n    : public random_internal::TagTypeCompare<IntervalOpenClosedTag> {};\nstruct IntervalOpenOpenTag\n    : public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};\n\nnamespace random_internal {\n\n// In the absence of an explicitly provided return-type, the template\n// \"uniform_inferred_return_t<A, B>\" is used to derive a suitable type, based on\n// the data-types of the endpoint-arguments {A lo, B hi}.\n//\n// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the\n// return-type, if one type can be implicitly converted into the other, in a\n// lossless way. The template \"is_widening_convertible\" implements the\n// compile-time logic for deciding if such a conversion is possible.\n//\n// If no such conversion between {A, B} exists, then the overload for\n// absl::Uniform() will be discarded, and the call will be ill-formed.\n// Return-type for absl::Uniform() when the return-type is inferred.\ntemplate <typename A, typename B>\nusing uniform_inferred_return_t =\n    absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,\n                                        is_widening_convertible<B, A>>::value,\n                      typename std::conditional<\n                          is_widening_convertible<A, B>::value, B, A>::type>;\n\n// The functions\n//    uniform_lower_bound(tag, a, b)\n// and\n//    uniform_upper_bound(tag, a, b)\n// are used as implementation-details for absl::Uniform().\n//\n// Conceptually,\n//    [a, b] == [uniform_lower_bound(IntervalClosedClosed, a, b),\n//               uniform_upper_bound(IntervalClosedClosed, a, b)]\n//    (a, b) == [uniform_lower_bound(IntervalOpenOpen, a, b),\n//               uniform_upper_bound(IntervalOpenOpen, a, b)]\n//    [a, b) == [uniform_lower_bound(IntervalClosedOpen, a, b),\n//               uniform_upper_bound(IntervalClosedOpen, a, b)]\n//    (a, b] == [uniform_lower_bound(IntervalOpenClosed, a, b),\n//               uniform_upper_bound(IntervalOpenClosed, a, b)]\n//\ntemplate <typename IntType, typename Tag>\ntypename absl::enable_if_t<\n    absl::conjunction<\n        IsIntegral<IntType>,\n        absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,\n                          std::is_same<Tag, IntervalOpenOpenTag>>>::value,\n    IntType>\nuniform_lower_bound(Tag, IntType a, IntType) {\n  return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a;\n}\n\ntemplate <typename FloatType, typename Tag>\ntypename absl::enable_if_t<\n    absl::conjunction<\n        std::is_floating_point<FloatType>,\n        absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,\n                          std::is_same<Tag, IntervalOpenOpenTag>>>::value,\n    FloatType>\nuniform_lower_bound(Tag, FloatType a, FloatType b) {\n  return std::nextafter(a, b);\n}\n\ntemplate <typename NumType, typename Tag>\ntypename absl::enable_if_t<\n    absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,\n                      std::is_same<Tag, IntervalClosedOpenTag>>::value,\n    NumType>\nuniform_lower_bound(Tag, NumType a, NumType) {\n  return a;\n}\n\ntemplate <typename IntType, typename Tag>\ntypename absl::enable_if_t<\n    absl::conjunction<\n        IsIntegral<IntType>,\n        absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,\n                          std::is_same<Tag, IntervalOpenOpenTag>>>::value,\n    IntType>\nuniform_upper_bound(Tag, IntType, IntType b) {\n  return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b;\n}\n\ntemplate <typename FloatType, typename Tag>\ntypename absl::enable_if_t<\n    absl::conjunction<\n        std::is_floating_point<FloatType>,\n        absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,\n                          std::is_same<Tag, IntervalOpenOpenTag>>>::value,\n    FloatType>\nuniform_upper_bound(Tag, FloatType, FloatType b) {\n  return b;\n}\n\ntemplate <typename IntType, typename Tag>\ntypename absl::enable_if_t<\n    absl::conjunction<\n        IsIntegral<IntType>,\n        absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,\n                          std::is_same<Tag, IntervalOpenClosedTag>>>::value,\n    IntType>\nuniform_upper_bound(Tag, IntType, IntType b) {\n  return b;\n}\n\ntemplate <typename FloatType, typename Tag>\ntypename absl::enable_if_t<\n    absl::conjunction<\n        std::is_floating_point<FloatType>,\n        absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,\n                          std::is_same<Tag, IntervalOpenClosedTag>>>::value,\n    FloatType>\nuniform_upper_bound(Tag, FloatType, FloatType b) {\n  return std::nextafter(b, (std::numeric_limits<FloatType>::max)());\n}\n\n// Returns whether the bounds are valid for the underlying distribution.\n// Inputs must have already been resolved via uniform_*_bound calls.\n//\n// The c++ standard constraints in [rand.dist.uni.int] are listed as:\n//    requires: lo <= hi.\n//\n// In the uniform_int_distrubtion, {lo, hi} are closed, closed. Thus:\n// [0, 0] is legal.\n// [0, 0) is not legal, but [0, 1) is, which translates to [0, 0].\n// (0, 1) is not legal, but (0, 2) is, which translates to [1, 1].\n// (0, 0] is not legal, but (0, 1] is, which translates to [1, 1].\n//\n// The c++ standard constraints in [rand.dist.uni.real] are listed as:\n//    requires: lo <= hi.\n//    requires: (hi - lo) <= numeric_limits<T>::max()\n//\n// In the uniform_real_distribution, {lo, hi} are closed, open, Thus:\n// [0, 0] is legal, which is [0, 0+epsilon).\n// [0, 0) is legal.\n// (0, 0) is not legal, but (0-epsilon, 0+epsilon) is.\n// (0, 0] is not legal, but (0, 0+epsilon] is.\n//\ntemplate <typename FloatType>\nabsl::enable_if_t<std::is_floating_point<FloatType>::value, bool>\nis_uniform_range_valid(FloatType a, FloatType b) {\n  return a <= b && std::isfinite(b - a);\n}\n\ntemplate <typename IntType>\nabsl::enable_if_t<IsIntegral<IntType>::value, bool> is_uniform_range_valid(\n    IntType a, IntType b) {\n  return a <= b;\n}\n\n// UniformDistribution selects either absl::uniform_int_distribution\n// or absl::uniform_real_distribution depending on the NumType parameter.\ntemplate <typename NumType>\nusing UniformDistribution =\n    typename std::conditional<IsIntegral<NumType>::value,\n                              absl::uniform_int_distribution<NumType>,\n                              absl::uniform_real_distribution<NumType>>::type;\n\n// UniformDistributionWrapper is used as the underlying distribution type\n// by the absl::Uniform template function. It selects the proper Abseil\n// uniform distribution and provides constructor overloads that match the\n// expected parameter order as well as adjusting distribution bounds based\n// on the tag.\ntemplate <typename NumType>\nstruct UniformDistributionWrapper : public UniformDistribution<NumType> {\n  template <typename TagType>\n  explicit UniformDistributionWrapper(TagType, NumType lo, NumType hi)\n      : UniformDistribution<NumType>(\n            uniform_lower_bound<NumType>(TagType{}, lo, hi),\n            uniform_upper_bound<NumType>(TagType{}, lo, hi)) {}\n\n  explicit UniformDistributionWrapper(NumType lo, NumType hi)\n      : UniformDistribution<NumType>(\n            uniform_lower_bound<NumType>(IntervalClosedOpenTag(), lo, hi),\n            uniform_upper_bound<NumType>(IntervalClosedOpenTag(), lo, hi)) {}\n\n  explicit UniformDistributionWrapper()\n      : UniformDistribution<NumType>(std::numeric_limits<NumType>::lowest(),\n                                     (std::numeric_limits<NumType>::max)()) {}\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_\n"
  },
  {
    "path": "absl/random/internal/uniform_helper_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/uniform_helper.h\"\n\n#include <cmath>\n#include <cstdint>\n#include <random>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing absl::IntervalClosedClosedTag;\nusing absl::IntervalClosedOpenTag;\nusing absl::IntervalOpenClosedTag;\nusing absl::IntervalOpenOpenTag;\nusing absl::random_internal::uniform_inferred_return_t;\nusing absl::random_internal::uniform_lower_bound;\nusing absl::random_internal::uniform_upper_bound;\n\nclass UniformHelperTest : public testing::Test {};\n\nTEST_F(UniformHelperTest, UniformBoundFunctionsGeneral) {\n  constexpr IntervalClosedClosedTag IntervalClosedClosed;\n  constexpr IntervalClosedOpenTag IntervalClosedOpen;\n  constexpr IntervalOpenClosedTag IntervalOpenClosed;\n  constexpr IntervalOpenOpenTag IntervalOpenOpen;\n\n  // absl::uniform_int_distribution natively assumes IntervalClosedClosed\n  // absl::uniform_real_distribution natively assumes IntervalClosedOpen\n\n  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, 0, 100), 1);\n  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, 0, 100), 1);\n  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, 0, 1.0), 0);\n  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, 0, 1.0), 0);\n  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, 0, 1.0), 0);\n  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, 0, 1.0), 0);\n\n  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, 0, 100), 0);\n  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, 0, 100), 0);\n  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, 0, 1.0), 0);\n  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, 0, 1.0), 0);\n  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, 0, 1.0), 0);\n  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, 0, 1.0), 0);\n\n  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, 0, 100), 99);\n  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, 0, 100), 99);\n  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, 0, 1.0), 1.0);\n  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, 0, 1.0), 1.0);\n  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, 0, 1.0), 1.0);\n  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, 0, 1.0), 1.0);\n\n  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, 0, 100), 100);\n  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0, 100), 100);\n  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, 0, 1.0), 1.0);\n  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, 0, 1.0), 1.0);\n  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, 0, 1.0), 1.0);\n  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, 0, 1.0), 1.0);\n\n  // Negative value tests\n  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, -100, -1), -99);\n  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, -100, -1), -99);\n  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, -2.0, -1.0), -2.0);\n  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, -2.0, -1.0), -2.0);\n  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, -2.0, -1.0), -2.0);\n  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, -2.0, -1.0), -2.0);\n\n  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, -100, -1), -100);\n  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, -100, -1), -100);\n  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, -2.0, -1.0), -2.0);\n  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, -2.0, -1.0), -2.0);\n  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, -2.0, -1.0),\n            -2.0);\n  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, -2.0, -1.0), -2.0);\n\n  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, -100, -1), -2);\n  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, -100, -1), -2);\n  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, -2.0, -1.0), -1.0);\n  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, -2.0, -1.0), -1.0);\n  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, -2.0, -1.0), -1.0);\n  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, -2.0, -1.0), -1.0);\n\n  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, -100, -1), -1);\n  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, -100, -1), -1);\n  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, -2.0, -1.0), -1.0);\n  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, -2.0, -1.0), -1.0);\n  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, -2.0, -1.0), -1.0);\n  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, -2.0, -1.0),\n            -1.0);\n\n  EXPECT_GT(uniform_lower_bound(IntervalOpenClosed, 1.0, 2.0), 1.0);\n  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, +0.0), 1.0);\n  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -0.0), 1.0);\n  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0), 1.0);\n}\n\nTEST_F(UniformHelperTest, UniformBoundFunctionsIntBounds) {\n  // Verifies the saturating nature of uniform_lower_bound and\n  // uniform_upper_bound\n  constexpr IntervalOpenOpenTag IntervalOpenOpen;\n\n  // uint max.\n  constexpr auto m = (std::numeric_limits<uint64_t>::max)();\n\n  EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0u, 0u));\n  EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m, m));\n  EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m - 1, m - 1));\n  EXPECT_EQ(0, uniform_upper_bound(IntervalOpenOpen, 0u, 0u));\n  EXPECT_EQ(m - 1, uniform_upper_bound(IntervalOpenOpen, m, m));\n\n  // int min/max\n  constexpr auto l = (std::numeric_limits<int64_t>::min)();\n  constexpr auto r = (std::numeric_limits<int64_t>::max)();\n  EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0, 0));\n  EXPECT_EQ(l + 1, uniform_lower_bound(IntervalOpenOpen, l, l));\n  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r - 1, r - 1));\n  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r, r));\n  EXPECT_EQ(-1, uniform_upper_bound(IntervalOpenOpen, 0, 0));\n  EXPECT_EQ(l, uniform_upper_bound(IntervalOpenOpen, l, l));\n  EXPECT_EQ(r - 1, uniform_upper_bound(IntervalOpenOpen, r, r));\n}\n\nTEST_F(UniformHelperTest, UniformBoundFunctionsRealBounds) {\n  // absl::uniform_real_distribution natively assumes IntervalClosedOpen;\n  // use the inverse here so each bound has to change.\n  constexpr IntervalOpenClosedTag IntervalOpenClosed;\n\n  // Edge cases: the next value toward itself is itself.\n  EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, 1.0, 1.0));\n  EXPECT_EQ(1.0f, uniform_lower_bound(IntervalOpenClosed, 1.0f, 1.0f));\n\n  // rightmost and leftmost finite values.\n  constexpr auto r = (std::numeric_limits<double>::max)();\n  const auto re = std::nexttoward(r, 0.0);\n  constexpr auto l = -r;\n  const auto le = std::nexttoward(l, 0.0);\n\n  EXPECT_EQ(l, uniform_lower_bound(IntervalOpenClosed, l, l));     // (l,l)\n  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, r, r));     // (r,r)\n  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, r));    // (l,r)\n  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, 0.0));  // (l, 0)\n  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, le));   // (l, le)\n  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, re, r));    // (re, r)\n\n  EXPECT_EQ(le, uniform_upper_bound(IntervalOpenClosed, l, l));   // (l,l)\n  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, r, r));    // (r,r)\n  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, r));    // (l,r)\n  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, re));   // (l,re)\n  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, 0.0, r));  // (0, r)\n  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, re, r));   // (re, r)\n  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, le, re));  // (le, re)\n\n  const double e = std::nextafter(1.0, 2.0);  // 1 + epsilon\n  const double f = std::nextafter(1.0, 0.0);  // 1 - epsilon\n\n  // (1.0, 1.0 + epsilon)\n  EXPECT_EQ(e, uniform_lower_bound(IntervalOpenClosed, 1.0, e));\n  EXPECT_EQ(std::nextafter(e, 2.0),\n            uniform_upper_bound(IntervalOpenClosed, 1.0, e));\n\n  // (1.0-epsilon, 1.0)\n  EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, f, 1.0));\n  EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, f, 1.0));\n\n  // denorm cases.\n  const double g = std::numeric_limits<double>::denorm_min();\n  const double h = std::nextafter(g, 1.0);\n\n  // (0, denorm_min)\n  EXPECT_EQ(g, uniform_lower_bound(IntervalOpenClosed, 0.0, g));\n  EXPECT_EQ(h, uniform_upper_bound(IntervalOpenClosed, 0.0, g));\n\n  // (denorm_min, 1.0)\n  EXPECT_EQ(h, uniform_lower_bound(IntervalOpenClosed, g, 1.0));\n  EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, g, 1.0));\n\n  // Edge cases: invalid bounds.\n  EXPECT_EQ(f, uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0));\n}\n\nstruct Invalid {};\n\ntemplate <typename A, typename B>\nauto InferredUniformReturnT(int) -> uniform_inferred_return_t<A, B>;\n\ntemplate <typename, typename>\nInvalid InferredUniformReturnT(...);\n\n// Given types <A, B, Expect>, CheckArgsInferType() verifies that\n//\n//   uniform_inferred_return_t<A, B> and\n//   uniform_inferred_return_t<B, A>\n//\n// returns the type \"Expect\".\n//\n// This interface can also be used to assert that a given inferred return types\n// are invalid. Writing:\n//\n//   CheckArgsInferType<float, int, Invalid>()\n//\n// will assert that this overload does not exist.\ntemplate <typename A, typename B, typename Expect>\nvoid CheckArgsInferType() {\n  static_assert(\n      absl::conjunction<\n          std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,\n          std::is_same<Expect,\n                       decltype(InferredUniformReturnT<B, A>(0))>>::value,\n      \"\");\n}\n\nTEST_F(UniformHelperTest, UniformTypeInference) {\n  // Infers common types.\n  CheckArgsInferType<uint16_t, uint16_t, uint16_t>();\n  CheckArgsInferType<uint32_t, uint32_t, uint32_t>();\n  CheckArgsInferType<uint64_t, uint64_t, uint64_t>();\n  CheckArgsInferType<int16_t, int16_t, int16_t>();\n  CheckArgsInferType<int32_t, int32_t, int32_t>();\n  CheckArgsInferType<int64_t, int64_t, int64_t>();\n  CheckArgsInferType<float, float, float>();\n  CheckArgsInferType<double, double, double>();\n\n  // Properly promotes uint16_t.\n  CheckArgsInferType<uint16_t, uint32_t, uint32_t>();\n  CheckArgsInferType<uint16_t, uint64_t, uint64_t>();\n  CheckArgsInferType<uint16_t, int32_t, int32_t>();\n  CheckArgsInferType<uint16_t, int64_t, int64_t>();\n  CheckArgsInferType<uint16_t, float, float>();\n  CheckArgsInferType<uint16_t, double, double>();\n\n  // Properly promotes int16_t.\n  CheckArgsInferType<int16_t, int32_t, int32_t>();\n  CheckArgsInferType<int16_t, int64_t, int64_t>();\n  CheckArgsInferType<int16_t, float, float>();\n  CheckArgsInferType<int16_t, double, double>();\n\n  // Invalid (u)int16_t-pairings do not compile.\n  // See \"CheckArgsInferType\" comments above, for how this is achieved.\n  CheckArgsInferType<uint16_t, int16_t, Invalid>();\n  CheckArgsInferType<int16_t, uint32_t, Invalid>();\n  CheckArgsInferType<int16_t, uint64_t, Invalid>();\n\n  // Properly promotes uint32_t.\n  CheckArgsInferType<uint32_t, uint64_t, uint64_t>();\n  CheckArgsInferType<uint32_t, int64_t, int64_t>();\n  CheckArgsInferType<uint32_t, double, double>();\n\n  // Properly promotes int32_t.\n  CheckArgsInferType<int32_t, int64_t, int64_t>();\n  CheckArgsInferType<int32_t, double, double>();\n\n  // Invalid (u)int32_t-pairings do not compile.\n  CheckArgsInferType<uint32_t, int32_t, Invalid>();\n  CheckArgsInferType<int32_t, uint64_t, Invalid>();\n  CheckArgsInferType<int32_t, float, Invalid>();\n  CheckArgsInferType<uint32_t, float, Invalid>();\n\n  // Invalid (u)int64_t-pairings do not compile.\n  CheckArgsInferType<uint64_t, int64_t, Invalid>();\n  CheckArgsInferType<int64_t, float, Invalid>();\n  CheckArgsInferType<int64_t, double, Invalid>();\n\n  // Properly promotes float.\n  CheckArgsInferType<float, double, double>();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/internal/wide_multiply.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_\n#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_\n\n#include <cstdint>\n#include <limits>\n#include <type_traits>\n\n#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)\n#include <intrin.h>  // NOLINT(build/include_order)\n#pragma intrinsic(_umul128)\n#define ABSL_INTERNAL_USE_UMUL128 1\n#endif\n\n#include \"absl/base/config.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/internal/traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace random_internal {\n\n// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.\ntemplate <typename UIntType>\nstruct wide_multiply {\n  static constexpr size_t kN = std::numeric_limits<UIntType>::digits;\n  using input_type = UIntType;\n  using result_type = typename random_internal::unsigned_bits<kN * 2>::type;\n\n  static result_type multiply(input_type a, input_type b) {\n    return static_cast<result_type>(a) * b;\n  }\n\n  static input_type hi(result_type r) {\n    return static_cast<input_type>(r >> kN);\n  }\n  static input_type lo(result_type r) { return static_cast<input_type>(r); }\n\n  static_assert(std::is_unsigned<UIntType>::value,\n                \"Class-template wide_multiply<> argument must be unsigned.\");\n};\n\n// MultiplyU128ToU256 multiplies two 128-bit values to a 256-bit value.\ninline U256 MultiplyU128ToU256(uint128 a, uint128 b) {\n  const uint128 a00 = static_cast<uint64_t>(a);\n  const uint128 a64 = a >> 64;\n  const uint128 b00 = static_cast<uint64_t>(b);\n  const uint128 b64 = b >> 64;\n\n  const uint128 c00 = a00 * b00;\n  const uint128 c64a = a00 * b64;\n  const uint128 c64b = a64 * b00;\n  const uint128 c128 = a64 * b64;\n\n  const uint64_t carry =\n      static_cast<uint64_t>(((c00 >> 64) + static_cast<uint64_t>(c64a) +\n                             static_cast<uint64_t>(c64b)) >>\n                            64);\n\n  return {c128 + (c64a >> 64) + (c64b >> 64) + carry,\n          c00 + (c64a << 64) + (c64b << 64)};\n}\n\ntemplate <>\nstruct wide_multiply<uint128> {\n  using input_type = uint128;\n  using result_type = U256;\n\n  static result_type multiply(input_type a, input_type b) {\n    return MultiplyU128ToU256(a, b);\n  }\n\n  static input_type hi(result_type r) { return r.hi; }\n  static input_type lo(result_type r) { return r.lo; }\n};\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_\n"
  },
  {
    "path": "absl/random/internal/wide_multiply_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/internal/wide_multiply.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/numeric/int128.h\"\n\nusing absl::random_internal::MultiplyU128ToU256;\nusing absl::random_internal::U256;\n\nnamespace {\n\nU256 LeftShift(U256 v, int s) {\n  if (s == 0) {\n    return v;\n  } else if (s < 128) {\n    return {(v.hi << s) | (v.lo >> (128 - s)), v.lo << s};\n  } else {\n    return {v.lo << (s - 128), 0};\n  }\n}\n\nMATCHER_P2(Eq256, hi, lo, \"\") { return arg.hi == hi && arg.lo == lo; }\nMATCHER_P(Eq256, v, \"\") { return arg.hi == v.hi && arg.lo == v.lo; }\n\nTEST(WideMultiplyTest, MultiplyU128ToU256Test) {\n  using absl::uint128;\n  constexpr uint128 k1 = 1;\n  constexpr uint128 kMax = ~static_cast<uint128>(0);\n\n  EXPECT_THAT(MultiplyU128ToU256(0, 0), Eq256(0, 0));\n\n  // Max uin128_t\n  EXPECT_THAT(MultiplyU128ToU256(kMax, kMax), Eq256(kMax << 1, 1));\n  EXPECT_THAT(MultiplyU128ToU256(kMax, 1), Eq256(0, kMax));\n  EXPECT_THAT(MultiplyU128ToU256(1, kMax), Eq256(0, kMax));\n  for (int i = 0; i < 64; ++i) {\n    SCOPED_TRACE(i);\n    EXPECT_THAT(MultiplyU128ToU256(kMax, k1 << i),\n                Eq256(LeftShift({0, kMax}, i)));\n    EXPECT_THAT(MultiplyU128ToU256(k1 << i, kMax),\n                Eq256(LeftShift({0, kMax}, i)));\n  }\n\n  // 1-bit x 1-bit.\n  for (int i = 0; i < 64; ++i) {\n    for (int j = 0; j < 64; ++j) {\n      EXPECT_THAT(MultiplyU128ToU256(k1 << i, k1 << j),\n                  Eq256(LeftShift({0, 1}, i + j)));\n    }\n  }\n\n  // Verified multiplies\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0xc502da0d6ea99fe8, 0xfa3c9141a1f50912),\n                  absl::MakeUint128(0x96bcf1ac37f97bd6, 0x27e2cdeb5fb2299e)),\n              Eq256(absl::MakeUint128(0x740113d838f96a64, 0x22e8cfa4d71f89ea),\n                    absl::MakeUint128(0x19184a345c62e993, 0x237871b630337b1c)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0x6f29e670cee07230, 0xc3d8e6c3e4d86759),\n                  absl::MakeUint128(0x3227d29fa6386db1, 0x231682bb1e4b764f)),\n              Eq256(absl::MakeUint128(0x15c779d9d5d3b07c, 0xd7e6c827f0c81cbe),\n                    absl::MakeUint128(0xf88e3914f7fa287a, 0x15b79975137dea77)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0xafb77107215646e1, 0x3b844cb1ac5769e7),\n                  absl::MakeUint128(0x1ff7b2d888b62479, 0x92f758ae96fcba0b)),\n              Eq256(absl::MakeUint128(0x15f13b70181f6985, 0x2adb36bbabce7d02),\n                    absl::MakeUint128(0x6c470d72e13aad04, 0x63fba3f5841762ed)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0xd85d5558d67ac905, 0xf88c70654dae19b1),\n                  absl::MakeUint128(0x17252c6727db3738, 0x399ff658c511eedc)),\n              Eq256(absl::MakeUint128(0x138fcdaf8b0421ee, 0x1b465ddf2a0d03f6),\n                    absl::MakeUint128(0x8f573ba68296860f, 0xf327d2738741a21c)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0x46f0421a37ff6bee, 0xa61df89f09d140b1),\n                  absl::MakeUint128(0x3d712ec9f37ca2e1, 0x9658a2cba47ef4b1)),\n              Eq256(absl::MakeUint128(0x11069cc48ee7c95d, 0xd35fb1c7aa91c978),\n                    absl::MakeUint128(0xbe2f4a6de874b015, 0xd2f7ac1b76746e61)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0x730d27c72d58fa49, 0x3ebeda7498f8827c),\n                  absl::MakeUint128(0xa2c959eca9f503af, 0x189c687eb842bbd8)),\n              Eq256(absl::MakeUint128(0x4928d0ea356ba022, 0x1546d34a2963393),\n                    absl::MakeUint128(0x7481531e1e0a16d1, 0xdd8025015cf6aca0)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0x6ca41020f856d2f1, 0xb9b0838c04a7f4aa),\n                  absl::MakeUint128(0x9cf41d28a8396f54, 0x1d681695e377ffe6)),\n              Eq256(absl::MakeUint128(0x429b92934d9be6f1, 0xea182877157c1e7),\n                    absl::MakeUint128(0x7135c23f0a4a475, 0xc1adc366f4a126bc)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0x57472833797c332, 0x6c79272fdec4687a),\n                  absl::MakeUint128(0xb5f022ea3838e46b, 0x16face2f003e27a6)),\n              Eq256(absl::MakeUint128(0x3e072e0962b3400, 0x5d9fe8fdc3d0e1f4),\n                    absl::MakeUint128(0x7dc0df47cedafd62, 0xbe6501f1acd2551c)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0xf0fb4198322eb1c2, 0xfe7f5f31f3885938),\n                  absl::MakeUint128(0xd99012b71bb7aa31, 0xac7a6f9eb190789)),\n              Eq256(absl::MakeUint128(0xcccc998cf075ca01, 0x642d144322fb873a),\n                    absl::MakeUint128(0xc79dc12b69d91ed4, 0xa83459132ce046f8)));\n  EXPECT_THAT(MultiplyU128ToU256(\n                  absl::MakeUint128(0xb5c04120848cdb47, 0x8aa62a827bf52635),\n                  absl::MakeUint128(0x8d07a359be2f1380, 0x467bb90d59da0dea)),\n              Eq256(absl::MakeUint128(0x64205019d139a9ce, 0x99425c5fb6e7a977),\n                    absl::MakeUint128(0xd3e99628a9e5fca7, 0x9c7824cb7279d72)));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/log_uniform_int_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_\n#define ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cmath>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/internal/traits.h\"\n#include \"absl/random/uniform_int_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// log_uniform_int_distribution:\n//\n// Returns a random variate R in range [min, max] such that\n// floor(log(R-min, base)) is uniformly distributed.\n// We ensure uniformity by discretization using the\n// boundary sets [0, 1, base, base * base, ... min(base*n, max)]\n//\ntemplate <typename IntType = int>\nclass log_uniform_int_distribution {\n private:\n  using unsigned_type =\n      typename random_internal::make_unsigned_bits<IntType>::type;\n\n public:\n  using result_type = IntType;\n\n  class param_type {\n   public:\n    using distribution_type = log_uniform_int_distribution;\n\n    explicit param_type(\n        result_type min = 0,\n        result_type max = (std::numeric_limits<result_type>::max)(),\n        result_type base = 2)\n        : min_(min),\n          max_(max),\n          base_(base),\n          range_(static_cast<unsigned_type>(max_) -\n                 static_cast<unsigned_type>(min_)),\n          log_range_(0) {\n      assert(max_ >= min_);\n      assert(base_ > 1);\n\n      if (base_ == 2) {\n        // Determine where the first set bit is on range(), giving a log2(range)\n        // value which can be used to construct bounds.\n        log_range_ = (std::min)(random_internal::BitWidth(range()),\n                                std::numeric_limits<unsigned_type>::digits);\n      } else {\n        // NOTE: Computing the logN(x) introduces error from 2 sources:\n        // 1. Conversion of int to double loses precision for values >=\n        // 2^53, which may cause some log() computations to operate on\n        // different values.\n        // 2. The error introduced by the division will cause the result\n        // to differ from the expected value.\n        //\n        // Thus a result which should equal K may equal K +/- epsilon,\n        // which can eliminate some values depending on where the bounds fall.\n        const double inv_log_base = 1.0 / std::log(static_cast<double>(base_));\n        const double log_range = std::log(static_cast<double>(range()) + 0.5);\n        log_range_ = static_cast<int>(std::ceil(inv_log_base * log_range));\n      }\n    }\n\n    result_type(min)() const { return min_; }\n    result_type(max)() const { return max_; }\n    result_type base() const { return base_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.min_ == b.min_ && a.max_ == b.max_ && a.base_ == b.base_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class log_uniform_int_distribution;\n\n    int log_range() const { return log_range_; }\n    unsigned_type range() const { return range_; }\n\n    result_type min_;\n    result_type max_;\n    result_type base_;\n    unsigned_type range_;  // max - min\n    int log_range_;        // ceil(logN(range_))\n\n    static_assert(random_internal::IsIntegral<IntType>::value,\n                  \"Class-template absl::log_uniform_int_distribution<> must be \"\n                  \"parameterized using an integral type.\");\n  };\n\n  log_uniform_int_distribution() : log_uniform_int_distribution(0) {}\n\n  explicit log_uniform_int_distribution(\n      result_type min,\n      result_type max = (std::numeric_limits<result_type>::max)(),\n      result_type base = 2)\n      : param_(min, max, base) {}\n\n  explicit log_uniform_int_distribution(const param_type& p) : param_(p) {}\n\n  void reset() {}\n\n  // generating functions\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p) {\n    return static_cast<result_type>((p.min)() + Generate(g, p));\n  }\n\n  result_type(min)() const { return (param_.min)(); }\n  result_type(max)() const { return (param_.max)(); }\n  result_type base() const { return param_.base(); }\n\n  param_type param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  friend bool operator==(const log_uniform_int_distribution& a,\n                         const log_uniform_int_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const log_uniform_int_distribution& a,\n                         const log_uniform_int_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  // Returns a log-uniform variate in the range [0, p.range()]. The caller\n  // should add min() to shift the result to the correct range.\n  template <typename URNG>\n  unsigned_type Generate(URNG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  param_type param_;\n};\n\ntemplate <typename IntType>\ntemplate <typename URBG>\ntypename log_uniform_int_distribution<IntType>::unsigned_type\nlog_uniform_int_distribution<IntType>::Generate(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  // sample e over [0, log_range]. Map the results of e to this:\n  // 0 => 0\n  // 1 => [1, b-1]\n  // 2 => [b, (b^2)-1]\n  // n => [b^(n-1)..(b^n)-1]\n  const int e = absl::uniform_int_distribution<int>(0, p.log_range())(g);\n  if (e == 0) {\n    return 0;\n  }\n  const int d = e - 1;\n\n  unsigned_type base_e, top_e;\n  if (p.base() == 2) {\n    base_e = static_cast<unsigned_type>(1) << d;\n\n    top_e = (e >= std::numeric_limits<unsigned_type>::digits)\n                ? (std::numeric_limits<unsigned_type>::max)()\n                : (static_cast<unsigned_type>(1) << e) - 1;\n  } else {\n    const double r = std::pow(static_cast<double>(p.base()), d);\n    const double s = (r * static_cast<double>(p.base())) - 1.0;\n\n    base_e =\n        (r > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))\n            ? (std::numeric_limits<unsigned_type>::max)()\n            : static_cast<unsigned_type>(r);\n\n    top_e =\n        (s > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))\n            ? (std::numeric_limits<unsigned_type>::max)()\n            : static_cast<unsigned_type>(s);\n  }\n\n  const unsigned_type lo = (base_e >= p.range()) ? p.range() : base_e;\n  const unsigned_type hi = (top_e >= p.range()) ? p.range() : top_e;\n\n  // choose uniformly over [lo, hi]\n  return absl::uniform_int_distribution<result_type>(\n      static_cast<result_type>(lo), static_cast<result_type>(hi))(g);\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const log_uniform_int_distribution<IntType>& x) {\n  using stream_type =\n      typename random_internal::stream_format_type<IntType>::type;\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os << static_cast<stream_type>((x.min)()) << os.fill()\n     << static_cast<stream_type>((x.max)()) << os.fill()\n     << static_cast<stream_type>(x.base());\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,       // NOLINT(runtime/references)\n    log_uniform_int_distribution<IntType>& x) {  // NOLINT(runtime/references)\n  using param_type = typename log_uniform_int_distribution<IntType>::param_type;\n  using result_type =\n      typename log_uniform_int_distribution<IntType>::result_type;\n  using stream_type =\n      typename random_internal::stream_format_type<IntType>::type;\n\n  stream_type min;\n  stream_type max;\n  stream_type base;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  is >> min >> max >> base;\n  if (!is.fail()) {\n    x.param(param_type(static_cast<result_type>(min),\n                       static_cast<result_type>(max),\n                       static_cast<result_type>(base)));\n  }\n  return is;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/log_uniform_int_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/log_uniform_int_distribution.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\ntemplate <typename IntType>\nclass LogUniformIntDistributionTypeTest : public ::testing::Test {};\n\nusing IntTypes = ::testing::Types<int8_t, int16_t, int32_t, int64_t,  //\n                                  uint8_t, uint16_t, uint32_t, uint64_t>;\nTYPED_TEST_SUITE(LogUniformIntDistributionTypeTest, IntTypes);\n\nTYPED_TEST(LogUniformIntDistributionTypeTest, SerializeTest) {\n  using param_type =\n      typename absl::log_uniform_int_distribution<TypeParam>::param_type;\n  using Limits = std::numeric_limits<TypeParam>;\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n  for (const auto& param : {\n           param_type(0, 1),                             //\n           param_type(0, 2),                             //\n           param_type(0, 2, 10),                         //\n           param_type(9, 32, 4),                         //\n           param_type(1, 101, 10),                       //\n           param_type(1, Limits::max() / 2),             //\n           param_type(0, Limits::max() - 1),             //\n           param_type(0, Limits::max(), 2),              //\n           param_type(0, Limits::max(), 10),             //\n           param_type(Limits::min(), 0),                 //\n           param_type(Limits::lowest(), Limits::max()),  //\n           param_type(Limits::min(), Limits::max()),     //\n       }) {\n    // Validate parameters.\n    const auto min = param.min();\n    const auto max = param.max();\n    const auto base = param.base();\n    absl::log_uniform_int_distribution<TypeParam> before(min, max, base);\n    EXPECT_EQ(before.min(), param.min());\n    EXPECT_EQ(before.max(), param.max());\n    EXPECT_EQ(before.base(), param.base());\n\n    {\n      absl::log_uniform_int_distribution<TypeParam> via_param(param);\n      EXPECT_EQ(via_param, before);\n    }\n\n    // Validate stream serialization.\n    std::stringstream ss;\n    ss << before;\n\n    absl::log_uniform_int_distribution<TypeParam> after(3, 6, 17);\n\n    EXPECT_NE(before.max(), after.max());\n    EXPECT_NE(before.base(), after.base());\n    EXPECT_NE(before.param(), after.param());\n    EXPECT_NE(before, after);\n\n    ss >> after;\n\n    EXPECT_EQ(before.min(), after.min());\n    EXPECT_EQ(before.max(), after.max());\n    EXPECT_EQ(before.base(), after.base());\n    EXPECT_EQ(before.param(), after.param());\n    EXPECT_EQ(before, after);\n\n    // Smoke test.\n    auto sample_min = after.max();\n    auto sample_max = after.min();\n    for (int i = 0; i < kCount; i++) {\n      auto sample = after(gen);\n      EXPECT_GE(sample, after.min());\n      EXPECT_LE(sample, after.max());\n      if (sample > sample_max) sample_max = sample;\n      if (sample < sample_min) sample_min = sample;\n    }\n    LOG(INFO) << \"Range: \" << sample_min << \", \" << sample_max;\n  }\n}\n\nusing log_uniform_i32 = absl::log_uniform_int_distribution<int32_t>;\n\nclass LogUniformIntChiSquaredTest\n    : public testing::TestWithParam<log_uniform_i32::param_type> {\n public:\n  // The ChiSquaredTestImpl provides a chi-squared goodness of fit test for\n  // data generated by the log-uniform-int distribution.\n  double ChiSquaredTestImpl();\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};\n};\n\ndouble LogUniformIntChiSquaredTest::ChiSquaredTestImpl() {\n  using absl::random_internal::kChiSquared;\n\n  const auto& param = GetParam();\n\n  // Check the distribution of L=log(log_uniform_int_distribution, base),\n  // expecting that L is roughly uniformly distributed, that is:\n  //\n  //   P[L=0] ~= P[L=1] ~= ... ~= P[L=log(max)]\n  //\n  // For a total of X entries, each bucket should contain some number of samples\n  // in the interval [X/k - a, X/k + a].\n  //\n  // Where `a` is approximately sqrt(X/k). This is validated by bucketing\n  // according to the log function and using a chi-squared test for uniformity.\n\n  const bool is_2 = (param.base() == 2);\n  const double base_log = 1.0 / std::log(param.base());\n  const auto bucket_index = [base_log, is_2, &param](int32_t x) {\n    uint64_t y = static_cast<uint64_t>(x) - param.min();\n    return (y == 0) ? 0\n           : is_2   ? static_cast<int>(1 + std::log2(y))\n                    : static_cast<int>(1 + std::log(y) * base_log);\n  };\n  const int max_bucket = bucket_index(param.max());  // inclusive\n  const size_t trials = 15 + (max_bucket + 1) * 10;\n\n  log_uniform_i32 dist(param);\n\n  std::vector<int64_t> buckets(max_bucket + 1);\n  for (size_t i = 0; i < trials; ++i) {\n    const auto sample = dist(rng_);\n    // Check the bounds.\n    ABSL_ASSERT(sample <= dist.max());\n    ABSL_ASSERT(sample >= dist.min());\n    // Convert the output of the generator to one of num_bucket buckets.\n    int bucket = bucket_index(sample);\n    ABSL_ASSERT(bucket <= max_bucket);\n    ++buckets[bucket];\n  }\n\n  // The null-hypothesis is that the distribution is uniform with respect to\n  // log-uniform-int bucketization.\n  const int dof = buckets.size() - 1;\n  const double expected = trials / static_cast<double>(buckets.size());\n\n  const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);\n\n  double chi_square = absl::random_internal::ChiSquareWithExpected(\n      std::begin(buckets), std::end(buckets), expected);\n\n  const double p = absl::random_internal::ChiSquarePValue(chi_square, dof);\n\n  if (chi_square > threshold) {\n    LOG(INFO) << \"values\";\n    for (size_t i = 0; i < buckets.size(); i++) {\n      LOG(INFO) << i << \": \" << buckets[i];\n    }\n    LOG(INFO) << \"trials=\" << trials << \"\\n\"\n              << kChiSquared << \"(data, \" << dof << \") = \" << chi_square << \" (\"\n              << p << \")\\n\"\n              << kChiSquared << \" @ 0.98 = \" << threshold;\n  }\n  return p;\n}\n\nTEST_P(LogUniformIntChiSquaredTest, MultiTest) {\n  const int kTrials = 5;\n  int failures = 0;\n  for (int i = 0; i < kTrials; i++) {\n    double p_value = ChiSquaredTestImpl();\n    if (p_value < 0.005) {\n      failures++;\n    }\n  }\n\n  // There is a 0.10% chance of producing at least one failure, so raise the\n  // failure threshold high enough to allow for a flake rate < 10,000.\n  EXPECT_LE(failures, 4);\n}\n\n// Generate the parameters for the test.\nstd::vector<log_uniform_i32::param_type> GenParams() {\n  using Param = log_uniform_i32::param_type;\n  using Limits = std::numeric_limits<int32_t>;\n\n  return std::vector<Param>{\n      Param{0, 1, 2},\n      Param{1, 1, 2},\n      Param{0, 2, 2},\n      Param{0, 3, 2},\n      Param{0, 4, 2},\n      Param{0, 9, 10},\n      Param{0, 10, 10},\n      Param{0, 11, 10},\n      Param{1, 10, 10},\n      Param{0, (1 << 8) - 1, 2},\n      Param{0, (1 << 8), 2},\n      Param{0, (1 << 30) - 1, 2},\n      Param{-1000, 1000, 10},\n      Param{0, Limits::max(), 2},\n      Param{0, Limits::max(), 3},\n      Param{0, Limits::max(), 10},\n      Param{Limits::min(), 0},\n      Param{Limits::min(), Limits::max(), 2},\n  };\n}\n\nstd::string ParamName(\n    const ::testing::TestParamInfo<log_uniform_i32::param_type>& info) {\n  const auto& p = info.param;\n  std::string name =\n      absl::StrCat(\"min_\", p.min(), \"__max_\", p.max(), \"__base_\", p.base());\n  return absl::StrReplaceAll(name, {{\"+\", \"_\"}, {\"-\", \"_\"}, {\".\", \"_\"}});\n}\n\nINSTANTIATE_TEST_SUITE_P(All, LogUniformIntChiSquaredTest,\n                         ::testing::ValuesIn(GenParams()), ParamName);\n\n// NOTE: absl::log_uniform_int_distribution is not guaranteed to be stable.\nTEST(LogUniformIntDistributionTest, StabilityTest) {\n  using testing::ElementsAre;\n  // absl::uniform_int_distribution stability relies on\n  // absl::random_internal::LeadingSetBit, std::log, std::pow.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(6);\n\n  {\n    absl::log_uniform_int_distribution<int32_t> dist(0, 256);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n    EXPECT_THAT(output, ElementsAre(256, 66, 4, 6, 57, 103));\n  }\n  urbg.reset();\n  {\n    absl::log_uniform_int_distribution<int32_t> dist(0, 256, 10);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n    EXPECT_THAT(output, ElementsAre(8, 4, 0, 0, 0, 69));\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/mock_distributions.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: mock_distributions.h\n// -----------------------------------------------------------------------------\n//\n// This file contains mock distribution functions for use alongside an\n// `absl::MockingBitGen` object within the GoogleTest testing framework. Such\n// mocks are useful to provide deterministic values as return values within\n// (otherwise random) Abseil distribution functions.\n//\n// The return type of each function is a mock expectation object which\n// is used to set the match result.\n//\n// More information about the GoogleTest testing framework is available at\n// https://github.com/google/googletest\n//\n// EXPECT_CALL and ON_CALL need to be made within the same DLL component as\n// the call to absl::Uniform and related methods, otherwise mocking will fail\n// since the  underlying implementation creates a type-specific pointer which\n// will be distinct across different DLL boundaries.\n//\n// Example:\n//\n//   absl::MockingBitGen mock;\n//   EXPECT_CALL(absl::MockUniform<int>(), Call(mock, 1, 1000))\n//     .WillRepeatedly(testing::ReturnRoundRobin({20, 40}));\n//\n//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);\n//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);\n//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);\n//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);\n\n#ifndef ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_\n#define ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/random/bernoulli_distribution.h\"\n#include \"absl/random/beta_distribution.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/exponential_distribution.h\"\n#include \"absl/random/gaussian_distribution.h\"\n#include \"absl/random/internal/mock_overload_set.h\"\n#include \"absl/random/internal/mock_validators.h\"\n#include \"absl/random/log_uniform_int_distribution.h\"\n#include \"absl/random/mocking_bit_gen.h\"\n#include \"absl/random/poisson_distribution.h\"\n#include \"absl/random/zipf_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// absl::MockUniform\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Uniform.\n//\n// `absl::MockUniform` is a class template used in conjunction with Googletest's\n// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an\n// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the\n// same way one would define mocks on a Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(mock))\n//     .WillOnce(Return(123456));\n//  auto x = absl::Uniform<uint32_t>(mock);\n//  assert(x == 123456)\n//\ntemplate <typename R>\nusing MockUniform = random_internal::MockOverloadSetWithValidator<\n    random_internal::UniformDistributionWrapper<R>,\n    random_internal::UniformDistributionValidator<R>,\n    R(IntervalClosedOpenTag, MockingBitGen&, R, R),\n    R(IntervalClosedClosedTag, MockingBitGen&, R, R),\n    R(IntervalOpenOpenTag, MockingBitGen&, R, R),\n    R(IntervalOpenClosedTag, MockingBitGen&, R, R), R(MockingBitGen&, R, R),\n    R(MockingBitGen&)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockBernoulli\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Bernoulli.\n//\n// `absl::MockBernoulli` is a class used in conjunction with Googletest's\n// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an\n// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the\n// same way one would define mocks on a Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockBernoulli(), Call(mock, testing::_))\n//     .WillOnce(Return(false));\n//  assert(absl::Bernoulli(mock, 0.5) == false);\n//\nusing MockBernoulli =\n    random_internal::MockOverloadSet<absl::bernoulli_distribution,\n                                     bool(MockingBitGen&, double)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockBeta\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Beta.\n//\n// `absl::MockBeta` is a class used in conjunction with Googletest's `ON_CALL()`\n// and `EXPECT_CALL()` macros. To use it, default-construct an instance of it\n// inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the same way one\n// would define mocks on a Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockBeta(), Call(mock, 3.0, 2.0))\n//     .WillOnce(Return(0.567));\n//  auto x = absl::Beta<double>(mock, 3.0, 2.0);\n//  assert(x == 0.567);\n//\ntemplate <typename RealType>\nusing MockBeta =\n    random_internal::MockOverloadSet<absl::beta_distribution<RealType>,\n                                     RealType(MockingBitGen&, RealType,\n                                              RealType)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockExponential\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Exponential.\n//\n// `absl::MockExponential` is a class template used in conjunction with\n// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,\n// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,\n// and use `Call(...)` the same way one would define mocks on a\n// Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockExponential<double>(), Call(mock, 0.5))\n//     .WillOnce(Return(12.3456789));\n//  auto x = absl::Exponential<double>(mock, 0.5);\n//  assert(x == 12.3456789)\n//\ntemplate <typename RealType>\nusing MockExponential =\n    random_internal::MockOverloadSet<absl::exponential_distribution<RealType>,\n                                     RealType(MockingBitGen&, RealType)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockGaussian\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Gaussian.\n//\n// `absl::MockGaussian` is a class template used in conjunction with\n// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,\n// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,\n// and use `Call(...)` the same way one would define mocks on a\n// Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockGaussian<double>(), Call(mock, 16.3, 3.3))\n//     .WillOnce(Return(12.3456789));\n//  auto x = absl::Gaussian<double>(mock, 16.3, 3.3);\n//  assert(x == 12.3456789)\n//\ntemplate <typename RealType>\nusing MockGaussian =\n    random_internal::MockOverloadSet<absl::gaussian_distribution<RealType>,\n                                     RealType(MockingBitGen&, RealType,\n                                              RealType)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockLogUniform\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::LogUniform.\n//\n// `absl::MockLogUniform` is a class template used in conjunction with\n// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,\n// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,\n// and use `Call(...)` the same way one would define mocks on a\n// Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockLogUniform<int>(), Call(mock, 10, 10000, 10))\n//     .WillOnce(Return(1221));\n//  auto x = absl::LogUniform<int>(mock, 10, 10000, 10);\n//  assert(x == 1221)\n//\ntemplate <typename IntType>\nusing MockLogUniform = random_internal::MockOverloadSet<\n    absl::log_uniform_int_distribution<IntType>,\n    IntType(MockingBitGen&, IntType, IntType, IntType)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockPoisson\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Poisson.\n//\n// `absl::MockPoisson` is a class template used in conjunction with Googletest's\n// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an\n// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the\n// same way one would define mocks on a Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockPoisson<int>(), Call(mock, 2.0))\n//     .WillOnce(Return(1221));\n//  auto x = absl::Poisson<int>(mock, 2.0);\n//  assert(x == 1221)\n//\ntemplate <typename IntType>\nusing MockPoisson =\n    random_internal::MockOverloadSet<absl::poisson_distribution<IntType>,\n                                     IntType(MockingBitGen&, double)>;\n\n// -----------------------------------------------------------------------------\n// absl::MockZipf\n// -----------------------------------------------------------------------------\n//\n// Matches calls to absl::Zipf.\n//\n// `absl::MockZipf` is a class template used in conjunction with Googletest's\n// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an\n// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the\n// same way one would define mocks on a Googletest `MockFunction()`.\n//\n// Example:\n//\n//  absl::MockingBitGen mock;\n//  EXPECT_CALL(absl::MockZipf<int>(), Call(mock, 1000000, 2.0, 1.0))\n//     .WillOnce(Return(1221));\n//  auto x = absl::Zipf<int>(mock, 1000000, 2.0, 1.0);\n//  assert(x == 1221)\n//\ntemplate <typename IntType>\nusing MockZipf =\n    random_internal::MockOverloadSet<absl::zipf_distribution<IntType>,\n                                     IntType(MockingBitGen&, IntType, double,\n                                             double)>;\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_\n"
  },
  {
    "path": "absl/random/mock_distributions_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/mock_distributions.h\"\n\n#include <cmath>\n#include <limits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/mocking_bit_gen.h\"\n#include \"absl/random/random.h\"\n\nnamespace {\nusing ::testing::Return;\n\nTEST(MockDistributions, Examples) {\n  absl::MockingBitGen gen;\n\n  EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);\n  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))\n      .WillOnce(Return(20));\n  EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);\n\n  EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);\n  EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))\n      .WillOnce(Return(5.0));\n  EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);\n\n  EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);\n  EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))\n      .WillOnce(Return(42));\n  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);\n\n  EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);\n  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));\n  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);\n\n  EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);\n  EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))\n      .WillOnce(Return(true));\n  EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);\n\n  EXPECT_NE(absl::Beta<double>(gen, 3.0, 2.0), 0.567);\n  EXPECT_CALL(absl::MockBeta<double>(), Call(gen, 3.0, 2.0))\n      .WillOnce(Return(0.567));\n  EXPECT_EQ(absl::Beta<double>(gen, 3.0, 2.0), 0.567);\n\n  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n  EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))\n      .WillOnce(Return(1221));\n  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n\n  EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);\n  EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))\n      .WillOnce(Return(0.001));\n  EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);\n\n  const int kHigh = (1 << 30) - 1;\n  EXPECT_NE(absl::LogUniform<int>(gen, 0, kHigh, 2), kHigh);\n  EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, kHigh, 2))\n      .WillOnce(Return(kHigh));\n  EXPECT_EQ(absl::LogUniform<int>(gen, 0, kHigh, 2), kHigh);\n}\n\nTEST(MockDistributions, UniformUInt128BoundariesAreAllowed) {\n  absl::MockingBitGen gen;\n\n  EXPECT_CALL(absl::MockUniform<absl::uint128>(), Call(gen))\n      .WillOnce(Return(absl::Uint128Max()));\n  EXPECT_EQ(absl::Uniform<absl::uint128>(gen), absl::Uint128Max());\n}\n\nTEST(MockDistributions, UniformDoubleBoundaryCasesAreAllowed) {\n  absl::MockingBitGen gen;\n\n  EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 1.0, 10.0))\n      .WillOnce(Return(\n          std::nextafter(10.0, -std::numeric_limits<double>::infinity())));\n  EXPECT_EQ(absl::Uniform<double>(gen, 1.0, 10.0),\n            std::nextafter(10.0, -std::numeric_limits<double>::infinity()));\n\n  EXPECT_CALL(absl::MockUniform<double>(),\n              Call(absl::IntervalOpen, gen, 1.0, 10.0))\n      .WillOnce(Return(\n          std::nextafter(10.0, -std::numeric_limits<double>::infinity())));\n  EXPECT_EQ(absl::Uniform<double>(absl::IntervalOpen, gen, 1.0, 10.0),\n            std::nextafter(10.0, -std::numeric_limits<double>::infinity()));\n\n  EXPECT_CALL(absl::MockUniform<double>(),\n              Call(absl::IntervalOpen, gen, 1.0, 10.0))\n      .WillOnce(\n          Return(std::nextafter(1.0, std::numeric_limits<double>::infinity())));\n  EXPECT_EQ(absl::Uniform<double>(absl::IntervalOpen, gen, 1.0, 10.0),\n            std::nextafter(1.0, std::numeric_limits<double>::infinity()));\n}\n\nTEST(MockDistributions, UniformDoubleEmptyRangesAllowTheBoundary) {\n  absl::MockingBitGen gen;\n\n  ON_CALL(absl::MockUniform<double>(), Call(absl::IntervalOpen, gen, 1.0, 1.0))\n      .WillByDefault(Return(1.0));\n  EXPECT_EQ(absl::Uniform<double>(absl::IntervalOpen, gen, 1.0, 1.0), 1.0);\n\n  ON_CALL(absl::MockUniform<double>(),\n          Call(absl::IntervalOpenClosed, gen, 1.0, 1.0))\n      .WillByDefault(Return(1.0));\n  EXPECT_EQ(absl::Uniform<double>(absl::IntervalOpenClosed, gen, 1.0, 1.0),\n            1.0);\n\n  ON_CALL(absl::MockUniform<double>(),\n          Call(absl::IntervalClosedOpen, gen, 1.0, 1.0))\n      .WillByDefault(Return(1.0));\n  EXPECT_EQ(absl::Uniform<double>(absl::IntervalClosedOpen, gen, 1.0, 1.0),\n            1.0);\n}\n\nTEST(MockDistributions, UniformIntEmptyRangeCasesAllowTheBoundary) {\n  absl::MockingBitGen gen;\n\n  ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalOpen, gen, 1, 1))\n      .WillByDefault(Return(1));\n  EXPECT_EQ(absl::Uniform<int>(absl::IntervalOpen, gen, 1, 1), 1);\n\n  ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalOpenClosed, gen, 1, 1))\n      .WillByDefault(Return(1));\n  EXPECT_EQ(absl::Uniform<int>(absl::IntervalOpenClosed, gen, 1, 1), 1);\n\n  ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosedOpen, gen, 1, 1))\n      .WillByDefault(Return(1));\n  EXPECT_EQ(absl::Uniform<int>(absl::IntervalClosedOpen, gen, 1, 1), 1);\n}\n\nTEST(MockUniformDeathTest, OutOfBoundsValuesAreRejected) {\n  absl::MockingBitGen gen;\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 100))\n            .WillOnce(Return(0));\n        absl::Uniform<int>(gen, 1, 100);\n      },\n      \" 0 is not in \\\\[1, 100\\\\)\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 100))\n            .WillOnce(Return(101));\n        absl::Uniform<int>(gen, 1, 100);\n      },\n      \" 101 is not in \\\\[1, 100\\\\)\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 100))\n            .WillOnce(Return(100));\n        absl::Uniform<int>(gen, 1, 100);\n      },\n      \" 100 is not in \\\\[1, 100\\\\)\");\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpen, gen, 1, 100))\n            .WillOnce(Return(1));\n        absl::Uniform<int>(absl::IntervalOpen, gen, 1, 100);\n      },\n      \" 1 is not in \\\\(1, 100\\\\)\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpen, gen, 1, 100))\n            .WillOnce(Return(101));\n        absl::Uniform<int>(absl::IntervalOpen, gen, 1, 100);\n      },\n      \" 101 is not in \\\\(1, 100\\\\)\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpen, gen, 1, 100))\n            .WillOnce(Return(100));\n        absl::Uniform<int>(absl::IntervalOpen, gen, 1, 100);\n      },\n      \" 100 is not in \\\\(1, 100\\\\)\");\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpenClosed, gen, 1, 100))\n            .WillOnce(Return(1));\n        absl::Uniform<int>(absl::IntervalOpenClosed, gen, 1, 100);\n      },\n      \" 1 is not in \\\\(1, 100\\\\]\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpenClosed, gen, 1, 100))\n            .WillOnce(Return(101));\n        absl::Uniform<int>(absl::IntervalOpenClosed, gen, 1, 100);\n      },\n      \" 101 is not in \\\\(1, 100\\\\]\");\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpenClosed, gen, 1, 100))\n            .WillOnce(Return(0));\n        absl::Uniform<int>(absl::IntervalOpenClosed, gen, 1, 100);\n      },\n      \" 0 is not in \\\\(1, 100\\\\]\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalOpenClosed, gen, 1, 100))\n            .WillOnce(Return(101));\n        absl::Uniform<int>(absl::IntervalOpenClosed, gen, 1, 100);\n      },\n      \" 101 is not in \\\\(1, 100\\\\]\");\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalClosed, gen, 1, 100))\n            .WillOnce(Return(0));\n        absl::Uniform<int>(absl::IntervalClosed, gen, 1, 100);\n      },\n      \" 0 is not in \\\\[1, 100\\\\]\");\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<int>(),\n                    Call(absl::IntervalClosed, gen, 1, 100))\n            .WillOnce(Return(101));\n        absl::Uniform<int>(absl::IntervalClosed, gen, 1, 100);\n      },\n      \" 101 is not in \\\\[1, 100\\\\]\");\n}\n\nTEST(MockUniformDeathTest, OutOfBoundsDoublesAreRejected) {\n  absl::MockingBitGen gen;\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 1.0, 10.0))\n            .WillOnce(Return(10.0));\n        EXPECT_EQ(absl::Uniform<double>(gen, 1.0, 10.0), 10.0);\n      },\n      \" 10 is not in \\\\[1, 10\\\\)\");\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<double>(),\n                    Call(absl::IntervalOpen, gen, 1.0, 10.0))\n            .WillOnce(Return(10.0));\n        EXPECT_EQ(absl::Uniform<double>(absl::IntervalOpen, gen, 1.0, 10.0),\n                  10.0);\n      },\n      \" 10 is not in \\\\(1, 10\\\\)\");\n\n  EXPECT_DEATH_IF_SUPPORTED(\n      {\n        EXPECT_CALL(absl::MockUniform<double>(),\n                    Call(absl::IntervalOpen, gen, 1.0, 10.0))\n            .WillOnce(Return(1.0));\n        EXPECT_EQ(absl::Uniform<double>(absl::IntervalOpen, gen, 1.0, 10.0),\n                  1.0);\n      },\n      \" 1 is not in \\\\(1, 10\\\\)\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/mocking_bit_gen.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// mocking_bit_gen.h\n// -----------------------------------------------------------------------------\n//\n// This file includes an `absl::MockingBitGen` class to use as a mock within the\n// GoogleTest testing framework. Such a mock is useful to provide deterministic\n// values as return values within (otherwise random) Abseil distribution\n// functions. Such determinism within a mock is useful within testing frameworks\n// to test otherwise indeterminate APIs.\n//\n// More information about the GoogleTest testing framework is available at\n// https://github.com/google/googletest\n\n#ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_\n#define ABSL_RANDOM_MOCKING_BIT_GEN_H_\n\n#include <memory>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/fast_type_id.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/mock_helpers.h\"\n#include \"absl/random/random.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass BitGenRef;\n\nnamespace random_internal {\ntemplate <typename>\nstruct DistributionCaller;\nclass MockHelpers;\n}  // namespace random_internal\n\n// MockingBitGen\n//\n// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class\n// which can act in place of an `absl::BitGen` URBG within tests using the\n// GoogleTest testing framework.\n//\n// Usage:\n//\n// Use an `absl::MockingBitGen` along with a mock distribution object (within\n// mock_distributions.h) inside Googletest constructs such as ON_CALL(),\n// EXPECT_TRUE(), etc. to produce deterministic results conforming to the\n// distribution's API contract.\n//\n// Example:\n//\n//  // Mock a call to an `absl::Bernoulli` distribution using Googletest\n//   absl::MockingBitGen bitgen;\n//\n//   ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5))\n//       .WillByDefault(testing::Return(true));\n//   EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5));\n//\n//  // Mock a call to an `absl::Uniform` distribution within Googletest\n//  absl::MockingBitGen bitgen;\n//\n//   ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_))\n//       .WillByDefault([] (int low, int high) {\n//           return low + (high - low) / 2;\n//       });\n//\n//   EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5);\n//   EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35);\n//\n// At this time, only mock distributions supplied within the Abseil random\n// library are officially supported.\n//\n// EXPECT_CALL and ON_CALL need to be made within the same DLL component as\n// the call to absl::Uniform and related methods, otherwise mocking will fail\n// since the  underlying implementation creates a type-specific pointer which\n// will be distinct across different DLL boundaries.\n//\nclass MockingBitGen {\n public:\n  MockingBitGen() = default;\n  ~MockingBitGen() = default;\n\n  // URBG interface\n  using result_type = absl::BitGen::result_type;\n\n  static constexpr result_type(min)() { return (absl::BitGen::min)(); }\n  static constexpr result_type(max)() { return (absl::BitGen::max)(); }\n  result_type operator()() { return gen_(); }\n\n private:\n  // GetMockFnType returns the testing::MockFunction for a result and tuple.\n  // This method only exists for type deduction and is otherwise unimplemented.\n  template <typename ResultT, typename... Args>\n  static auto GetMockFnType(ResultT, std::tuple<Args...>)\n      -> ::testing::MockFunction<ResultT(Args...)>;\n\n  // MockFnCaller is a helper method for use with absl::apply to\n  // apply an ArgTupleT to a compatible MockFunction.\n  // NOTE: MockFnCaller is essentially equivalent to the lambda:\n  // [fn](auto... args) { return fn->Call(std::move(args)...)}\n  // however that fails to build on some supported platforms.\n  template <typename MockFnType, typename ValidatorT, typename ResultT,\n            typename Tuple>\n  struct MockFnCaller;\n\n  // specialization for std::tuple.\n  template <typename MockFnType, typename ValidatorT, typename ResultT,\n            typename... Args>\n  struct MockFnCaller<MockFnType, ValidatorT, ResultT, std::tuple<Args...>> {\n    MockFnType* fn;\n    inline ResultT operator()(Args... args) {\n      ResultT result = fn->Call(args...);\n      ValidatorT::Validate(result, args...);\n      return result;\n    }\n  };\n\n  // FunctionHolder owns a particular ::testing::MockFunction associated with\n  // a mocked type signature, and implement the type-erased Apply call, which\n  // applies type-erased arguments to the mock.\n  class FunctionHolder {\n   public:\n    virtual ~FunctionHolder() = default;\n\n    // Call is a dispatch function which converts the\n    // generic type-erased parameters into a specific mock invocation call.\n    virtual void Apply(/*ArgTupleT*/ void* args_tuple,\n                       /*ResultT*/ void* result) = 0;\n  };\n\n  template <typename MockFnType, typename ValidatorT, typename ResultT,\n            typename ArgTupleT>\n  class FunctionHolderImpl final : public FunctionHolder {\n   public:\n    void Apply(void* args_tuple, void* result) final {\n      // Requires tuple_args to point to a ArgTupleT, which is a\n      // std::tuple<Args...> used to invoke the mock function. Requires result\n      // to point to a ResultT, which is the result of the call.\n      *static_cast<ResultT*>(result) = absl::apply(\n          MockFnCaller<MockFnType, ValidatorT, ResultT, ArgTupleT>{&mock_fn_},\n          *static_cast<ArgTupleT*>(args_tuple));\n    }\n\n    MockFnType mock_fn_;\n  };\n\n  // MockingBitGen::RegisterMock\n  //\n  // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension\n  // point for extending the MockingBitGen framework. It provides a mechanism to\n  // install a mock expectation for a function like ResultT(Args...) keyed by\n  // type_idex onto the MockingBitGen context. The key is that the type_index\n  // used to register must match the type index used to call the mock.\n  //\n  // The returned MockFunction<...> type can be used to setup additional\n  // distribution parameters of the expectation.\n  template <typename ResultT, typename ArgTupleT, typename SelfT,\n            typename ValidatorT>\n  auto RegisterMock(SelfT&, FastTypeIdType type, ValidatorT)\n      -> decltype(GetMockFnType(std::declval<ResultT>(),\n                                std::declval<ArgTupleT>()))& {\n    using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),\n                                              std::declval<ArgTupleT>()));\n\n    using WrappedFnType = absl::conditional_t<\n        std::is_same<SelfT, ::testing::NiceMock<MockingBitGen>>::value,\n        ::testing::NiceMock<MockFnType>,\n        absl::conditional_t<\n            std::is_same<SelfT, ::testing::NaggyMock<MockingBitGen>>::value,\n            ::testing::NaggyMock<MockFnType>,\n            absl::conditional_t<\n                std::is_same<SelfT,\n                             ::testing::StrictMock<MockingBitGen>>::value,\n                ::testing::StrictMock<MockFnType>, MockFnType>>>;\n\n    using ImplT =\n        FunctionHolderImpl<WrappedFnType, ValidatorT, ResultT, ArgTupleT>;\n    auto& mock = mocks_[type];\n    if (!mock) {\n      mock = absl::make_unique<ImplT>();\n    }\n    return static_cast<ImplT*>(mock.get())->mock_fn_;\n  }\n\n  // MockingBitGen::InvokeMock\n  //\n  // bool InvokeMock(key_id, args_tuple*, result*) is the entrypoint\n  // for invoking mocks registered on MockingBitGen.\n  //\n  // When no mocks are registered on the provided FastTypeIdType, returns false.\n  // Otherwise attempts to invoke the mock function ResultT(Args...) that\n  // was previously registered via the type_index.\n  // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>\n  // used to invoke the mock function.\n  // Requires result to point to a ResultT, which is the result of the call.\n  inline bool InvokeMock(FastTypeIdType key_id, void* args_tuple,\n                         void* result) {\n    // Trigger a mock, if there exists one that matches `param`.\n    auto it = mocks_.find(key_id);\n    if (it == mocks_.end()) return false;\n    it->second->Apply(args_tuple, result);\n    return true;\n  }\n\n  absl::flat_hash_map<FastTypeIdType, std::unique_ptr<FunctionHolder>> mocks_;\n  absl::BitGen gen_;\n\n  template <typename>\n  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock\n  friend class ::absl::BitGenRef;                             // for InvokeMock\n  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock,\n                                                      // InvokeMock\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_MOCKING_BIT_GEN_H_\n"
  },
  {
    "path": "absl/random/mocking_bit_gen_test.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#include \"absl/random/mocking_bit_gen.h\"\n\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <numeric>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest-spi.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/bit_gen_ref.h\"\n#include \"absl/random/mock_distributions.h\"\n#include \"absl/random/random.h\"\n\nnamespace {\n\nusing ::testing::_;\nusing ::testing::Ne;\nusing ::testing::Return;\n\nTEST(BasicMocking, AllDistributionsAreOverridable) {\n  absl::MockingBitGen gen;\n\n  EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);\n  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))\n      .WillOnce(Return(20));\n  EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);\n\n  EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);\n  EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))\n      .WillOnce(Return(5.0));\n  EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);\n\n  EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);\n  EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))\n      .WillOnce(Return(42));\n  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);\n\n  EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);\n  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));\n  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);\n\n  EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);\n  EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))\n      .WillOnce(Return(true));\n  EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);\n\n  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n  EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))\n      .WillOnce(Return(1221));\n  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n\n  EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);\n  EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))\n      .WillOnce(Return(0.001));\n  EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);\n\n  EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);\n  EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))\n      .WillOnce(Return(500000));\n  EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);\n}\n\nTEST(BasicMocking, OnDistribution) {\n  absl::MockingBitGen gen;\n\n  EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);\n  ON_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))\n      .WillByDefault(Return(20));\n  EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);\n\n  EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);\n  ON_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))\n      .WillByDefault(Return(5.0));\n  EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);\n\n  EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);\n  ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))\n      .WillByDefault(Return(42));\n  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);\n\n  EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);\n  ON_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillByDefault(Return(500));\n  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);\n\n  EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);\n  ON_CALL(absl::MockBernoulli(), Call(gen, 0.000001))\n      .WillByDefault(Return(true));\n  EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);\n\n  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n  ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))\n      .WillByDefault(Return(1221));\n  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n\n  EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);\n  ON_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))\n      .WillByDefault(Return(0.001));\n  EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);\n\n  EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);\n  ON_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))\n      .WillByDefault(Return(2040));\n  EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);\n}\n\nTEST(BasicMocking, GMockMatchers) {\n  absl::MockingBitGen gen;\n\n  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n  ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))\n      .WillByDefault(Return(1221));\n  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);\n}\n\nTEST(BasicMocking, OverridesWithMultipleGMockExpectations) {\n  absl::MockingBitGen gen;\n\n  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 10000))\n      .WillOnce(Return(20))\n      .WillOnce(Return(40))\n      .WillOnce(Return(60));\n  EXPECT_EQ(absl::Uniform(gen, 1, 10000), 20);\n  EXPECT_EQ(absl::Uniform(gen, 1, 10000), 40);\n  EXPECT_EQ(absl::Uniform(gen, 1, 10000), 60);\n}\n\nTEST(BasicMocking, DefaultArgument) {\n  absl::MockingBitGen gen;\n\n  ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))\n      .WillByDefault(Return(200));\n\n  EXPECT_EQ(absl::Exponential<double>(gen), 200);\n  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 200);\n}\n\nTEST(BasicMocking, MultipleGenerators) {\n  auto get_value = [](absl::BitGenRef gen_ref) {\n    return absl::Uniform(gen_ref, 1, 1000000);\n  };\n  absl::MockingBitGen unmocked_generator;\n  absl::MockingBitGen mocked_with_3;\n  absl::MockingBitGen mocked_with_11;\n\n  EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_3, 1, 1000000))\n      .WillOnce(Return(3))\n      .WillRepeatedly(Return(17));\n  EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_11, 1, 1000000))\n      .WillOnce(Return(11))\n      .WillRepeatedly(Return(17));\n\n  // Ensure that unmocked generator generates neither value.\n  int unmocked_value = get_value(unmocked_generator);\n  EXPECT_NE(unmocked_value, 3);\n  EXPECT_NE(unmocked_value, 11);\n  // Mocked generators should generate their mocked values.\n  EXPECT_EQ(get_value(mocked_with_3), 3);\n  EXPECT_EQ(get_value(mocked_with_11), 11);\n  // Ensure that the mocks have expired.\n  EXPECT_NE(get_value(mocked_with_3), 3);\n  EXPECT_NE(get_value(mocked_with_11), 11);\n}\n\nTEST(BasicMocking, MocksNotTriggeredForIncorrectTypes) {\n  absl::MockingBitGen gen;\n  EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen))\n      .WillRepeatedly(Return(42));\n\n  bool uint16_always42 = true;\n  for (int i = 0; i < 10000; i++) {\n    EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42);  // Mock triggered.\n    // uint16_t not mocked.\n    uint16_always42 = uint16_always42 && absl::Uniform<uint16_t>(gen) == 42;\n  }\n  EXPECT_FALSE(uint16_always42);\n}\n\nTEST(BasicMocking, FailsOnUnsatisfiedMocks) {\n  EXPECT_NONFATAL_FAILURE(\n      []() {\n        absl::MockingBitGen gen;\n        EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))\n            .WillOnce(Return(3.0));\n        // Does not call absl::Exponential().\n      }(),\n      \"unsatisfied and active\");\n}\n\nTEST(OnUniform, RespectsUniformIntervalSemantics) {\n  absl::MockingBitGen gen;\n\n  EXPECT_CALL(absl::MockUniform<int>(),\n              Call(absl::IntervalClosed, gen, 1, 1000000))\n      .WillOnce(Return(301));\n  EXPECT_NE(absl::Uniform(gen, 1, 1000000), 301);  // Not mocked\n  EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 1, 1000000), 301);\n}\n\nTEST(OnUniform, RespectsNoArgUnsignedShorthand) {\n  absl::MockingBitGen gen;\n  EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));\n  EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42);\n}\n\nTEST(RepeatedlyModifier, ForceSnakeEyesForManyDice) {\n  auto roll_some_dice = [](absl::BitGenRef gen_ref) {\n    std::vector<int> results(16);\n    for (auto& r : results) {\n      r = absl::Uniform(absl::IntervalClosed, gen_ref, 1, 6);\n    }\n    return results;\n  };\n  std::vector<int> results;\n  absl::MockingBitGen gen;\n\n  // Without any mocked calls, not all dice roll a \"6\".\n  results = roll_some_dice(gen);\n  EXPECT_LT(std::accumulate(std::begin(results), std::end(results), 0),\n            results.size() * 6);\n\n  // Verify that we can force all \"6\"-rolls, with mocking.\n  ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, 1, 6))\n      .WillByDefault(Return(6));\n  results = roll_some_dice(gen);\n  EXPECT_EQ(std::accumulate(std::begin(results), std::end(results), 0),\n            results.size() * 6);\n}\n\nTEST(WillOnce, DistinctCounters) {\n  absl::MockingBitGen gen;\n  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))\n      .Times(3)\n      .WillRepeatedly(Return(1));\n  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1000001, 2000000))\n      .Times(3)\n      .WillRepeatedly(Return(1000001));\n  EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1000001);\n  EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 1);\n  EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1000001);\n  EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 1);\n  EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1000001);\n  EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 1);\n}\n\nTEST(TimesModifier, ModifierSaturatesAndExpires) {\n  EXPECT_NONFATAL_FAILURE(\n      []() {\n        absl::MockingBitGen gen;\n        EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 0, 1000000))\n            .Times(3)\n            .WillRepeatedly(Return(15))\n            .RetiresOnSaturation();\n\n        EXPECT_EQ(absl::Uniform(gen, 0, 1000000), 15);\n        EXPECT_EQ(absl::Uniform(gen, 0, 1000000), 15);\n        EXPECT_EQ(absl::Uniform(gen, 0, 1000000), 15);\n        // Times(3) has expired - Should get a different value now.\n\n        EXPECT_NE(absl::Uniform(gen, 0, 1000000), 15);\n      }(),\n      \"\");\n}\n\nTEST(TimesModifier, Times0) {\n  absl::MockingBitGen gen;\n  EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.0)).Times(0);\n  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).Times(0);\n}\n\nTEST(AnythingMatcher, MatchesAnyArgument) {\n  using testing::_;\n\n  {\n    absl::MockingBitGen gen;\n    ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, _, 1000))\n        .WillByDefault(Return(11));\n    ON_CALL(absl::MockUniform<int>(),\n            Call(absl::IntervalClosed, gen, _, Ne(1000)))\n        .WillByDefault(Return(99));\n\n    EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000000), 99);\n    EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000), 11);\n  }\n\n  {\n    absl::MockingBitGen gen;\n    ON_CALL(absl::MockUniform<int>(), Call(gen, 1, _))\n        .WillByDefault(Return(25));\n    ON_CALL(absl::MockUniform<int>(), Call(gen, Ne(1), _))\n        .WillByDefault(Return(99));\n    EXPECT_EQ(absl::Uniform(gen, 3, 1000000), 99);\n    EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 25);\n  }\n\n  {\n    absl::MockingBitGen gen;\n    ON_CALL(absl::MockUniform<int>(), Call(gen, _, _))\n        .WillByDefault(Return(145));\n    EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);\n    EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145);\n    EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145);\n  }\n}\n\nTEST(AnythingMatcher, WithWillByDefault) {\n  using testing::_;\n  absl::MockingBitGen gen;\n  std::vector<int> values = {11, 22, 33, 44, 55, 66, 77, 88, 99, 1010};\n\n  ON_CALL(absl::MockUniform<size_t>(), Call(gen, 0, _))\n      .WillByDefault(Return(0));\n  for (int i = 0; i < 100; i++) {\n    auto& elem = values[absl::Uniform(gen, 0u, values.size())];\n    EXPECT_EQ(elem, 11);\n  }\n}\n\nTEST(BasicMocking, WillByDefaultWithArgs) {\n  using testing::_;\n\n  absl::MockingBitGen gen;\n  ON_CALL(absl::MockPoisson<int>(), Call(gen, _))\n      .WillByDefault([](double lambda) {\n        return static_cast<int>(std::rint(lambda * 10));\n      });\n  EXPECT_EQ(absl::Poisson<int>(gen, 1.7), 17);\n  EXPECT_EQ(absl::Poisson<int>(gen, 0.03), 0);\n}\n\nTEST(MockingBitGen, InSequenceSucceedsInOrder) {\n  absl::MockingBitGen gen;\n\n  testing::InSequence seq;\n\n  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(3));\n  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 2.0)).WillOnce(Return(4));\n\n  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 3);\n  EXPECT_EQ(absl::Poisson<int>(gen, 2.0), 4);\n}\n\nTEST(MockingBitGen, NiceMock) {\n  ::testing::NiceMock<absl::MockingBitGen> gen;\n  ON_CALL(absl::MockUniform<int>(), Call(gen, _, _)).WillByDefault(Return(145));\n\n  ON_CALL(absl::MockPoisson<int>(), Call(gen, _)).WillByDefault(Return(3));\n\n  EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);\n  EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145);\n  EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145);\n}\n\nTEST(MockingBitGen, NaggyMock) {\n  // This is difficult to test, as only the output matters, so just verify\n  // that ON_CALL can be installed. Anything else requires log inspection.\n  ::testing::NaggyMock<absl::MockingBitGen> gen;\n\n  ON_CALL(absl::MockUniform<int>(), Call(gen, _, _)).WillByDefault(Return(145));\n  ON_CALL(absl::MockPoisson<int>(), Call(gen, _)).WillByDefault(Return(3));\n\n  EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);\n}\n\nTEST(MockingBitGen, StrictMock_NotEnough) {\n  EXPECT_NONFATAL_FAILURE(\n      []() {\n        ::testing::StrictMock<absl::MockingBitGen> gen;\n        EXPECT_CALL(absl::MockUniform<int>(), Call(gen, _, _))\n            .WillOnce(Return(145));\n      }(),\n      \"unsatisfied and active\");\n}\n\nTEST(MockingBitGen, StrictMock_TooMany) {\n  ::testing::StrictMock<absl::MockingBitGen> gen;\n\n  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, _, _)).WillOnce(Return(145));\n  EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);\n\n  EXPECT_NONFATAL_FAILURE(\n      [&]() { EXPECT_EQ(absl::Uniform(gen, 0, 1000), 0); }(),\n      \"over-saturated and active\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/poisson_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_POISSON_DISTRIBUTION_H_\n#define ABSL_RANDOM_POISSON_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cmath>\n#include <cstdint>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/fastmath.h\"\n#include \"absl/random/internal/generate_real.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/internal/traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::poisson_distribution:\n// Generates discrete variates conforming to a Poisson distribution.\n//   p(n) = (mean^n / n!) exp(-mean)\n//\n// Depending on the parameter, the distribution selects one of the following\n// algorithms:\n// * The standard algorithm, attributed to Knuth, extended using a split method\n// for larger values\n// * The \"Ratio of Uniforms as a convenient method for sampling from classical\n// discrete distributions\", Stadlober, 1989.\n// http://www.sciencedirect.com/science/article/pii/0377042790903495\n//\n// NOTE: param_type.mean() is a double, which permits values larger than\n// poisson_distribution<IntType>::max(), however this should be avoided and\n// the distribution results are limited to the max() value.\n//\n// The goals of this implementation are to provide good performance while still\n// being thread-safe: This limits the implementation to not using lgamma\n// provided by <math.h>.\n//\ntemplate <typename IntType = int>\nclass poisson_distribution {\n public:\n  using result_type = IntType;\n\n  class param_type {\n   public:\n    using distribution_type = poisson_distribution;\n    explicit param_type(double mean = 1.0);\n\n    double mean() const { return mean_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.mean_ == b.mean_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class poisson_distribution;\n\n    double mean_;\n    double emu_;  // e ^ -mean_\n    double lmu_;  // ln(mean_)\n    double s_;\n    double log_k_;\n    int split_;\n\n    static_assert(random_internal::IsIntegral<IntType>::value,\n                  \"Class-template absl::poisson_distribution<> must be \"\n                  \"parameterized using an integral type.\");\n  };\n\n  poisson_distribution() : poisson_distribution(1.0) {}\n\n  explicit poisson_distribution(double mean) : param_(mean) {}\n\n  explicit poisson_distribution(const param_type& p) : param_(p) {}\n\n  void reset() {}\n\n  // generating functions\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  param_type param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  result_type(min)() const { return 0; }\n  result_type(max)() const { return (std::numeric_limits<result_type>::max)(); }\n\n  double mean() const { return param_.mean(); }\n\n  friend bool operator==(const poisson_distribution& a,\n                         const poisson_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const poisson_distribution& a,\n                         const poisson_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  param_type param_;\n  random_internal::FastUniformBits<uint64_t> fast_u64_;\n};\n\n// -----------------------------------------------------------------------------\n// Implementation details follow\n// -----------------------------------------------------------------------------\n\ntemplate <typename IntType>\npoisson_distribution<IntType>::param_type::param_type(double mean)\n    : mean_(mean), split_(0) {\n  assert(mean >= 0);\n  assert(mean <=\n         static_cast<double>((std::numeric_limits<result_type>::max)()));\n  // As a defensive measure, avoid large values of the mean.  The rejection\n  // algorithm used does not support very large values well.  It my be worth\n  // changing algorithms to better deal with these cases.\n  assert(mean <= 1e10);\n  if (mean_ < 10) {\n    // For small lambda, use the knuth method.\n    split_ = 1;\n    emu_ = std::exp(-mean_);\n  } else if (mean_ <= 50) {\n    // Use split-knuth method.\n    split_ = 1 + static_cast<int>(mean_ / 10.0);\n    emu_ = std::exp(-mean_ / static_cast<double>(split_));\n  } else {\n    // Use ratio of uniforms method.\n    constexpr double k2E = 0.7357588823428846;\n    constexpr double kSA = 0.4494580810294493;\n\n    lmu_ = std::log(mean_);\n    double a = mean_ + 0.5;\n    s_ = kSA + std::sqrt(k2E * a);\n    const double mode = std::ceil(mean_) - 1;\n    log_k_ = lmu_ * mode - absl::random_internal::StirlingLogFactorial(mode);\n  }\n}\n\ntemplate <typename IntType>\ntemplate <typename URBG>\ntypename poisson_distribution<IntType>::result_type\npoisson_distribution<IntType>::operator()(\n    URBG& g,  // NOLINT(runtime/references)\n    const param_type& p) {\n  using random_internal::GeneratePositiveTag;\n  using random_internal::GenerateRealFromBits;\n  using random_internal::GenerateSignedTag;\n\n  if (p.split_ != 0) {\n    // Use Knuth's algorithm with range splitting to avoid floating-point\n    // errors. Knuth's algorithm is: Ui is a sequence of uniform variates on\n    // (0,1); return the number of variates required for product(Ui) <\n    // exp(-lambda).\n    //\n    // The expected number of variates required for Knuth's method can be\n    // computed as follows:\n    // The expected value of U is 0.5, so solving for 0.5^n < exp(-lambda) gives\n    // the expected number of uniform variates\n    // required for a given lambda, which is:\n    //  lambda = [2, 5,  9, 10, 11, 12, 13, 14, 15, 16, 17]\n    //  n      = [3, 8, 13, 15, 16, 18, 19, 21, 22, 24, 25]\n    //\n    result_type n = 0;\n    for (int split = p.split_; split > 0; --split) {\n      double r = 1.0;\n      do {\n        r *= GenerateRealFromBits<double, GeneratePositiveTag, true>(\n            fast_u64_(g));  // U(-1, 0)\n        ++n;\n      } while (r > p.emu_);\n      --n;\n    }\n    return n;\n  }\n\n  // Use ratio of uniforms method.\n  //\n  // Let u ~ Uniform(0, 1), v ~ Uniform(-1, 1),\n  //     a = lambda + 1/2,\n  //     s = 1.5 - sqrt(3/e) + sqrt(2(lambda + 1/2)/e),\n  //     x = s * v/u + a.\n  // P(floor(x) = k | u^2 < f(floor(x))/k), where\n  // f(m) = lambda^m exp(-lambda)/ m!, for 0 <= m, and f(m) = 0 otherwise,\n  // and k = max(f).\n  const double a = p.mean_ + 0.5;\n  for (;;) {\n    const double u = GenerateRealFromBits<double, GeneratePositiveTag, false>(\n        fast_u64_(g));  // U(0, 1)\n    const double v = GenerateRealFromBits<double, GenerateSignedTag, false>(\n        fast_u64_(g));  // U(-1, 1)\n\n    const double x = std::floor(p.s_ * v / u + a);\n    if (x < 0) continue;  // f(negative) = 0\n    const double rhs = x * p.lmu_;\n    // clang-format off\n    double s = (x <= 1.0) ? 0.0\n             : (x == 2.0) ? 0.693147180559945\n             : absl::random_internal::StirlingLogFactorial(x);\n    // clang-format on\n    const double lhs = 2.0 * std::log(u) + p.log_k_ + s;\n    if (lhs < rhs) {\n      return x > static_cast<double>((max)())\n                 ? (max)()\n                 : static_cast<result_type>(x);  // f(x)/k >= u^2\n    }\n  }\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const poisson_distribution<IntType>& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<double>::kPrecision);\n  os << x.mean();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    poisson_distribution<IntType>& x) {     // NOLINT(runtime/references)\n  using param_type = typename poisson_distribution<IntType>::param_type;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  double mean = random_internal::read_floating_point<double>(is);\n  if (!is.fail()) {\n    x.param(param_type(mean));\n  }\n  return is;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_POISSON_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/poisson_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/poisson_distribution.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/strip.h\"\n\n// Notes about generating poisson variates:\n//\n// It is unlikely that any implementation of std::poisson_distribution\n// will be stable over time and across library implementations. For instance\n// the three different poisson variate generators listed below all differ:\n//\n// https://github.com/ampl/gsl/tree/master/randist/poisson.c\n// * GSL uses a gamma + binomial + knuth method to compute poisson variates.\n//\n// https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/random.tcc\n// * GCC uses the Devroye rejection algorithm, based on\n// Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag,\n// New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!), ~p.511\n//   http://www.nrbook.com/devroye/\n//\n// https://github.com/llvm-mirror/libcxx/blob/master/include/random\n// * CLANG uses a different rejection method, which appears to include a\n// normal-distribution approximation and an exponential distribution to\n// compute the threshold, including a similar factorial approximation to this\n// one, but it is unclear where the algorithm comes from, exactly.\n//\n\nnamespace {\n\nusing absl::random_internal::kChiSquared;\n\n// The PoissonDistributionInterfaceTest provides a basic test that\n// absl::poisson_distribution conforms to the interface and serialization\n// requirements imposed by [rand.req.dist] for the common integer types.\n\ntemplate <typename IntType>\nclass PoissonDistributionInterfaceTest : public ::testing::Test {};\n\nusing IntTypes = ::testing::Types<int, int8_t, int16_t, int32_t, int64_t,\n                                  uint8_t, uint16_t, uint32_t, uint64_t>;\nTYPED_TEST_SUITE(PoissonDistributionInterfaceTest, IntTypes);\n\nTYPED_TEST(PoissonDistributionInterfaceTest, SerializeTest) {\n  using param_type = typename absl::poisson_distribution<TypeParam>::param_type;\n  const double kMax =\n      std::min(1e10 /* assertion limit */,\n               static_cast<double>(std::numeric_limits<TypeParam>::max()));\n\n  const double kParams[] = {\n      // Cases around 1.\n      1,                         //\n      std::nextafter(1.0, 0.0),  // 1 - epsilon\n      std::nextafter(1.0, 2.0),  // 1 + epsilon\n      // Arbitrary values.\n      1e-8, 1e-4,\n      0.0000005,  // ~7.2e-7\n      0.2,        // ~0.2x\n      0.5,        // 0.72\n      2,          // ~2.8\n      20,         // 3x ~9.6\n      100, 1e4, 1e8, 1.5e9, 1e20,\n      // Boundary cases.\n      std::numeric_limits<double>::max(),\n      std::numeric_limits<double>::epsilon(),\n      std::nextafter(std::numeric_limits<double>::min(),\n                     1.0),                        // min + epsilon\n      std::numeric_limits<double>::min(),         // smallest normal\n      std::numeric_limits<double>::denorm_min(),  // smallest denorm\n      std::numeric_limits<double>::min() / 2,     // denorm\n      std::nextafter(std::numeric_limits<double>::min(),\n                     0.0),  // denorm_max\n  };\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n  for (const double m : kParams) {\n    const double mean = std::min(kMax, m);\n    const param_type param(mean);\n\n    // Validate parameters.\n    absl::poisson_distribution<TypeParam> before(mean);\n    EXPECT_EQ(before.mean(), param.mean());\n\n    {\n      absl::poisson_distribution<TypeParam> via_param(param);\n      EXPECT_EQ(via_param, before);\n      EXPECT_EQ(via_param.param(), before.param());\n    }\n\n    // Smoke test.\n    auto sample_min = before.max();\n    auto sample_max = before.min();\n    for (int i = 0; i < kCount; i++) {\n      auto sample = before(gen);\n      EXPECT_GE(sample, before.min());\n      EXPECT_LE(sample, before.max());\n      if (sample > sample_max) sample_max = sample;\n      if (sample < sample_min) sample_min = sample;\n    }\n\n    LOG(INFO) << \"Range {\" << param.mean() << \"}: \" << sample_min << \", \"\n              << sample_max;\n\n    // Validate stream serialization.\n    std::stringstream ss;\n    ss << before;\n\n    absl::poisson_distribution<TypeParam> after(3.8);\n\n    EXPECT_NE(before.mean(), after.mean());\n    EXPECT_NE(before.param(), after.param());\n    EXPECT_NE(before, after);\n\n    ss >> after;\n\n    EXPECT_EQ(before.mean(), after.mean())  //\n        << ss.str() << \" \"                  //\n        << (ss.good() ? \"good \" : \"\")       //\n        << (ss.bad() ? \"bad \" : \"\")         //\n        << (ss.eof() ? \"eof \" : \"\")         //\n        << (ss.fail() ? \"fail \" : \"\");\n  }\n}\n\n// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda366j.htm\n\nclass PoissonModel {\n public:\n  explicit PoissonModel(double mean) : mean_(mean) {}\n\n  double mean() const { return mean_; }\n  double variance() const { return mean_; }\n  double stddev() const { return std::sqrt(variance()); }\n  double skew() const { return 1.0 / mean_; }\n  double kurtosis() const { return 3.0 + 1.0 / mean_; }\n\n  // InitCDF() initializes the CDF for the distribution parameters.\n  void InitCDF();\n\n  // The InverseCDF, or the Percent-point function returns x, P(x) < v.\n  struct CDF {\n    size_t index;\n    double pmf;\n    double cdf;\n  };\n  CDF InverseCDF(double p) {\n    CDF target{0, 0, p};\n    auto it = std::upper_bound(\n        std::begin(cdf_), std::end(cdf_), target,\n        [](const CDF& a, const CDF& b) { return a.cdf < b.cdf; });\n    return *it;\n  }\n\n  void LogCDF() {\n    LOG(INFO) << \"CDF (mean = \" << mean_ << \")\";\n    for (const auto c : cdf_) {\n      LOG(INFO) << c.index << \": pmf=\" << c.pmf << \" cdf=\" << c.cdf;\n    }\n  }\n\n private:\n  const double mean_;\n\n  std::vector<CDF> cdf_;\n};\n\n// The goal is to compute an InverseCDF function, or percent point function for\n// the poisson distribution, and use that to partition our output into equal\n// range buckets.  However there is no closed form solution for the inverse cdf\n// for poisson distributions (the closest is the incomplete gamma function).\n// Instead, `InitCDF` iteratively computes the PMF and the CDF. This enables\n// searching for the bucket points.\nvoid PoissonModel::InitCDF() {\n  if (!cdf_.empty()) {\n    // State already initialized.\n    return;\n  }\n  ABSL_ASSERT(mean_ < 201.0);\n\n  const size_t max_i = 50 * stddev() + mean();\n  const double e_neg_mean = std::exp(-mean());\n  ABSL_ASSERT(e_neg_mean > 0);\n\n  double d = 1;\n  double last_result = e_neg_mean;\n  double cumulative = e_neg_mean;\n  if (e_neg_mean > 1e-10) {\n    cdf_.push_back({0, e_neg_mean, cumulative});\n  }\n  for (size_t i = 1; i < max_i; i++) {\n    d *= (mean() / i);\n    double result = e_neg_mean * d;\n    cumulative += result;\n    if (result < 1e-10 && result < last_result && cumulative > 0.999999) {\n      break;\n    }\n    if (result > 1e-7) {\n      cdf_.push_back({i, result, cumulative});\n    }\n    last_result = result;\n  }\n  ABSL_ASSERT(!cdf_.empty());\n}\n\n// PoissonDistributionZTest implements a z-test for the poisson distribution.\n\nstruct ZParam {\n  double mean;\n  double p_fail;   // Z-Test probability of failure.\n  int trials;      // Z-Test trials.\n  size_t samples;  // Z-Test samples.\n};\n\nclass PoissonDistributionZTest : public testing::TestWithParam<ZParam>,\n                                 public PoissonModel {\n public:\n  PoissonDistributionZTest() : PoissonModel(GetParam().mean) {}\n\n  // ZTestImpl provides a basic z-squared test of the mean vs. expected\n  // mean for data generated by the poisson distribution.\n  template <typename D>\n  bool SingleZTest(const double p, const size_t samples);\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};\n};\n\ntemplate <typename D>\nbool PoissonDistributionZTest::SingleZTest(const double p,\n                                           const size_t samples) {\n  D dis(mean());\n\n  absl::flat_hash_map<int32_t, int> buckets;\n  std::vector<double> data;\n  data.reserve(samples);\n  for (int j = 0; j < samples; j++) {\n    const auto x = dis(rng_);\n    buckets[x]++;\n    data.push_back(x);\n  }\n\n  // The null-hypothesis is that the distribution is a poisson distribution with\n  // the provided mean (not estimated from the data).\n  const auto m = absl::random_internal::ComputeDistributionMoments(data);\n  const double max_err = absl::random_internal::MaxErrorTolerance(p);\n  const double z = absl::random_internal::ZScore(mean(), m);\n  const bool pass = absl::random_internal::Near(\"z\", z, 0.0, max_err);\n\n  if (!pass) {\n    // clang-format off\n    LOG(INFO)\n        << \"p=\" << p << \" max_err=\" << max_err << \"\\n\"\n           \" mean=\" << m.mean << \" vs. \" << mean() << \"\\n\"\n           \" stddev=\" << std::sqrt(m.variance) << \" vs. \" << stddev() << \"\\n\"\n           \" skewness=\" << m.skewness << \" vs. \" << skew() << \"\\n\"\n           \" kurtosis=\" << m.kurtosis << \" vs. \" << kurtosis() << \"\\n\"\n           \" z=\" << z;\n    // clang-format on\n  }\n  return pass;\n}\n\nTEST_P(PoissonDistributionZTest, AbslPoissonDistribution) {\n  const auto& param = GetParam();\n  const int expected_failures =\n      std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));\n  const double p = absl::random_internal::RequiredSuccessProbability(\n      param.p_fail, param.trials);\n\n  int failures = 0;\n  for (int i = 0; i < param.trials; i++) {\n    failures +=\n        SingleZTest<absl::poisson_distribution<int32_t>>(p, param.samples) ? 0\n                                                                           : 1;\n  }\n  EXPECT_LE(failures, expected_failures);\n}\n\nstd::vector<ZParam> GetZParams() {\n  // These values have been adjusted from the \"exact\" computed values to reduce\n  // failure rates.\n  //\n  // It turns out that the actual values are not as close to the expected values\n  // as would be ideal.\n  return std::vector<ZParam>({\n      // Knuth method.\n      ZParam{0.5, 0.01, 100, 1000},\n      ZParam{1.0, 0.01, 100, 1000},\n      ZParam{10.0, 0.01, 100, 5000},\n      // Split-knuth method.\n      ZParam{20.0, 0.01, 100, 10000},\n      ZParam{50.0, 0.01, 100, 10000},\n      // Ratio of gaussians method.\n      ZParam{51.0, 0.01, 100, 10000},\n      ZParam{200.0, 0.05, 10, 100000},\n      ZParam{100000.0, 0.05, 10, 1000000},\n  });\n}\n\nstd::string ZParamName(const ::testing::TestParamInfo<ZParam>& info) {\n  const auto& p = info.param;\n  std::string name = absl::StrCat(\"mean_\", absl::SixDigits(p.mean));\n  return absl::StrReplaceAll(name, {{\"+\", \"_\"}, {\"-\", \"_\"}, {\".\", \"_\"}});\n}\n\nINSTANTIATE_TEST_SUITE_P(All, PoissonDistributionZTest,\n                         ::testing::ValuesIn(GetZParams()), ZParamName);\n\n// The PoissonDistributionChiSquaredTest class provides a basic test framework\n// for variates generated by a conforming poisson_distribution.\nclass PoissonDistributionChiSquaredTest : public testing::TestWithParam<double>,\n                                          public PoissonModel {\n public:\n  PoissonDistributionChiSquaredTest() : PoissonModel(GetParam()) {}\n\n  // The ChiSquaredTestImpl provides a chi-squared goodness of fit test for data\n  // generated by the poisson distribution.\n  template <typename D>\n  double ChiSquaredTestImpl();\n\n private:\n  void InitChiSquaredTest(const double buckets);\n\n  std::vector<size_t> cutoffs_;\n  std::vector<double> expected_;\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};\n};\n\nvoid PoissonDistributionChiSquaredTest::InitChiSquaredTest(\n    const double buckets) {\n  if (!cutoffs_.empty() && !expected_.empty()) {\n    return;\n  }\n  InitCDF();\n\n  // The code below finds cuttoffs that yield approximately equally-sized\n  // buckets to the extent that it is possible. However for poisson\n  // distributions this is particularly challenging for small mean parameters.\n  // Track the expected proportion of items in each bucket.\n  double last_cdf = 0;\n  const double inc = 1.0 / buckets;\n  for (double p = inc; p <= 1.0; p += inc) {\n    auto result = InverseCDF(p);\n    if (!cutoffs_.empty() && cutoffs_.back() == result.index) {\n      continue;\n    }\n    double d = result.cdf - last_cdf;\n    cutoffs_.push_back(result.index);\n    expected_.push_back(d);\n    last_cdf = result.cdf;\n  }\n  cutoffs_.push_back(std::numeric_limits<size_t>::max());\n  expected_.push_back(std::max(0.0, 1.0 - last_cdf));\n}\n\ntemplate <typename D>\ndouble PoissonDistributionChiSquaredTest::ChiSquaredTestImpl() {\n  const int kSamples = 2000;\n  const int kBuckets = 50;\n\n  // The poisson CDF fails for large mean values, since e^-mean exceeds the\n  // machine precision. For these cases, using a normal approximation would be\n  // appropriate.\n  ABSL_ASSERT(mean() <= 200);\n  InitChiSquaredTest(kBuckets);\n\n  D dis(mean());\n\n  std::vector<int32_t> counts(cutoffs_.size(), 0);\n  for (int j = 0; j < kSamples; j++) {\n    const size_t x = dis(rng_);\n    auto it = std::lower_bound(std::begin(cutoffs_), std::end(cutoffs_), x);\n    counts[std::distance(cutoffs_.begin(), it)]++;\n  }\n\n  // Normalize the counts.\n  std::vector<int32_t> e(expected_.size(), 0);\n  for (int i = 0; i < e.size(); i++) {\n    e[i] = kSamples * expected_[i];\n  }\n\n  // The null-hypothesis is that the distribution is a poisson distribution with\n  // the provided mean (not estimated from the data).\n  const int dof = static_cast<int>(counts.size()) - 1;\n\n  // The threshold for logging is 1-in-50.\n  const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);\n\n  const double chi_square = absl::random_internal::ChiSquare(\n      std::begin(counts), std::end(counts), std::begin(e), std::end(e));\n\n  const double p = absl::random_internal::ChiSquarePValue(chi_square, dof);\n\n  // Log if the chi_squared value is above the threshold.\n  if (chi_square > threshold) {\n    LogCDF();\n\n    LOG(INFO) << \"VALUES  buckets=\" << counts.size()\n              << \"  samples=\" << kSamples;\n    for (size_t i = 0; i < counts.size(); i++) {\n      LOG(INFO) << cutoffs_[i] << \": \" << counts[i] << \" vs. E=\" << e[i];\n    }\n\n    LOG(INFO) << kChiSquared << \"(data, dof=\" << dof << \") = \" << chi_square\n              << \" (\" << p << \")\\n\"\n              << \" vs.\\n\"\n              << kChiSquared << \" @ 0.98 = \" << threshold;\n  }\n  return p;\n}\n\nTEST_P(PoissonDistributionChiSquaredTest, AbslPoissonDistribution) {\n  const int kTrials = 20;\n\n  // Large values are not yet supported -- this requires estimating the cdf\n  // using the normal distribution instead of the poisson in this case.\n  ASSERT_LE(mean(), 200.0);\n  if (mean() > 200.0) {\n    return;\n  }\n\n  int failures = 0;\n  for (int i = 0; i < kTrials; i++) {\n    double p_value = ChiSquaredTestImpl<absl::poisson_distribution<int32_t>>();\n    if (p_value < 0.005) {\n      failures++;\n    }\n  }\n  // There is a 0.10% chance of producing at least one failure, so raise the\n  // failure threshold high enough to allow for a flake rate < 10,000.\n  EXPECT_LE(failures, 4);\n}\n\nINSTANTIATE_TEST_SUITE_P(All, PoissonDistributionChiSquaredTest,\n                         ::testing::Values(0.5, 1.0, 2.0, 10.0, 50.0, 51.0,\n                                           200.0));\n\n// NOTE: absl::poisson_distribution is not guaranteed to be stable.\nTEST(PoissonDistributionTest, StabilityTest) {\n  using testing::ElementsAre;\n  // absl::poisson_distribution stability relies on stability of\n  // std::exp, std::log, std::sqrt, std::ceil, std::floor, and\n  // absl::FastUniformBits, absl::StirlingLogFactorial, absl::RandU64ToDouble.\n  absl::random_internal::sequence_urbg urbg({\n      0x035b0dc7e0a18acfull, 0x06cebe0d2653682eull, 0x0061e9b23861596bull,\n      0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n      0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n      0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n      0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull,\n      0x4864f22c059bf29eull, 0x247856d8b862665cull, 0xe46e86e9a1337e10ull,\n      0xd8c8541f3519b133ull, 0xe75b5162c567b9e4ull, 0xf732e5ded7009c5bull,\n      0xb170b98353121eacull, 0x1ec2e8986d2362caull, 0x814c8e35fe9a961aull,\n      0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, 0x1224e62c978bbc7full,\n      0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, 0x1bbc23cfa8fac721ull,\n      0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, 0x836d794457c08849ull,\n      0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, 0xb12d74fdd718c8c5ull,\n      0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, 0x5738341045ba0d85ull,\n      0xf3fd722dc65ad09eull, 0xfa14fd21ea2a5705ull, 0xffe6ea4d6edb0c73ull,\n      0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull, 0xEAAD8E716B93D5A0ull,\n      0xD08ED1D0AFC725E0ull, 0x8E3C5B2F8E7594B7ull, 0x8FF6E2FBF2122B64ull,\n      0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull, 0xD1CFF191B3A8C1ADull,\n      0x2F2F2218BE0E1777ull, 0xEA752DFE8B021FA1ull, 0xE5A0CC0FB56F74E8ull,\n      0x18ACF3D6CE89E299ull, 0xB4A84FE0FD13E0B7ull, 0x7CC43B81D2ADA8D9ull,\n      0x165FA26680957705ull, 0x93CC7314211A1477ull, 0xE6AD206577B5FA86ull,\n      0xC75442F5FB9D35CFull, 0xEBCDAF0C7B3E89A0ull, 0xD6411BD3AE1E7E49ull,\n      0x00250E2D2071B35Eull, 0x226800BB57B8E0AFull, 0x2464369BF009B91Eull,\n      0x5563911D59DFA6AAull, 0x78C14389D95A537Full, 0x207D5BA202E5B9C5ull,\n      0x832603766295CFA9ull, 0x11C819684E734A41ull, 0xB3472DCA7B14A94Aull,\n  });\n\n  std::vector<int> output(10);\n\n  // Method 1.\n  {\n    absl::poisson_distribution<int> dist(5);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n  }\n  EXPECT_THAT(output,  // mean = 4.2\n              ElementsAre(1, 0, 0, 4, 2, 10, 3, 3, 7, 12));\n\n  // Method 2.\n  {\n    urbg.reset();\n    absl::poisson_distribution<int> dist(25);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n  }\n  EXPECT_THAT(output,  // mean = 19.8\n              ElementsAre(9, 35, 18, 10, 35, 18, 10, 35, 18, 10));\n\n  // Method 3.\n  {\n    urbg.reset();\n    absl::poisson_distribution<int> dist(121);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n  }\n  EXPECT_THAT(output,  // mean = 124.1\n              ElementsAre(161, 122, 129, 124, 112, 112, 117, 120, 130, 114));\n}\n\nTEST(PoissonDistributionTest, AlgorithmExpectedValue_1) {\n  // This tests small values of the Knuth method.\n  // The underlying uniform distribution will generate exactly 0.5.\n  absl::random_internal::sequence_urbg urbg({0x8000000000000001ull});\n  absl::poisson_distribution<int> dist(5);\n  EXPECT_EQ(7, dist(urbg));\n}\n\nTEST(PoissonDistributionTest, AlgorithmExpectedValue_2) {\n  // This tests larger values of the Knuth method.\n  // The underlying uniform distribution will generate exactly 0.5.\n  absl::random_internal::sequence_urbg urbg({0x8000000000000001ull});\n  absl::poisson_distribution<int> dist(25);\n  EXPECT_EQ(36, dist(urbg));\n}\n\nTEST(PoissonDistributionTest, AlgorithmExpectedValue_3) {\n  // This variant uses the ratio of uniforms method.\n  absl::random_internal::sequence_urbg urbg(\n      {0x7fffffffffffffffull, 0x8000000000000000ull});\n\n  absl::poisson_distribution<int> dist(121);\n  EXPECT_EQ(121, dist(urbg));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/random.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: random.h\n// -----------------------------------------------------------------------------\n//\n// This header defines the recommended Uniform Random Bit Generator (URBG)\n// types for use within the Abseil Random library. These types are not\n// suitable for security-related use-cases, but should suffice for most other\n// uses of generating random values.\n//\n// The Abseil random library provides the following URBG types:\n//\n//   * BitGen, a good general-purpose bit generator, optimized for generating\n//     random (but not cryptographically secure) values\n//   * InsecureBitGen, a slightly faster, though less random, bit generator, for\n//     cases where the existing BitGen is a drag on performance.\n\n#ifndef ABSL_RANDOM_RANDOM_H_\n#define ABSL_RANDOM_RANDOM_H_\n\n#include <cstdint>\n#include <random>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/distributions.h\"  // IWYU pragma: export\n#include \"absl/random/internal/nonsecure_base.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/randen_engine.h\"\n#include \"absl/random/seed_sequences.h\"  // IWYU pragma: export\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// absl::BitGen\n// -----------------------------------------------------------------------------\n//\n// `absl::BitGen` is a general-purpose random bit generator for generating\n// random values for use within the Abseil random library. Typically, you use a\n// bit generator in combination with a distribution to provide random values.\n//\n// Example:\n//\n//   // Create an absl::BitGen. There is no need to seed this bit generator.\n//   absl::BitGen gen;\n//\n//   // Generate an integer value in the closed interval [1,6]\n//   int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen);\n//\n// `absl::BitGen` is seeded by default with non-deterministic data to produce\n// different sequences of random values across different instances, including\n// different binary invocations. This behavior is different than the standard\n// library bit generators, which use golden values as their seeds. Default\n// construction intentionally provides no stability guarantees, to avoid\n// accidental dependence on such a property.\n//\n// `absl::BitGen` may be constructed with an optional seed sequence type,\n// conforming to [rand.req.seed_seq], which will be mixed with additional\n// non-deterministic data as detailed below.\n//\n// Example:\n//\n//  // Create an absl::BitGen using an std::seed_seq seed sequence\n//  std::seed_seq seq{1,2,3};\n//  absl::BitGen gen_with_seed(seq);\n//\n//  // Generate an integer value in the closed interval [1,6]\n//  int die_roll2 = absl::uniform_int_distribution<int>(1, 6)(gen_with_seed);\n//\n// Constructing two `absl::BitGen`s with the same seed sequence in the same\n// process will produce the same sequence of variates, but need not do so across\n// multiple processes even if they're executing the same binary.\n//\n// `absl::BitGen` meets the requirements of the Uniform Random Bit Generator\n// (URBG) concept as per the C++17 standard [rand.req.urng] though differs\n// slightly with [rand.req.eng]. Like its standard library equivalents (e.g.\n// `std::mersenne_twister_engine`) `absl::BitGen` is not cryptographically\n// secure.\n//\n// This type has been optimized to perform better than Mersenne Twister\n// (https://en.wikipedia.org/wiki/Mersenne_Twister) and many other complex URBG\n// types on modern x86, ARM, and PPC architectures.\n//\n// This type is thread-compatible, but not thread-safe.\nclass BitGen : private random_internal::NonsecureURBGBase<\n                   random_internal::randen_engine<uint64_t>> {\n  using Base = random_internal::NonsecureURBGBase<\n      random_internal::randen_engine<uint64_t>>;\n\n public:\n  using result_type = typename Base::result_type;\n\n  // BitGen()\n  // BitGen(SeedSequence seed_seq)\n  //\n  // Copy disallowed.\n  // Move allowed.\n  using Base::Base;\n  using Base::operator=;\n\n  // BitGen::min()\n  //\n  // Returns the smallest possible value from this bit generator.\n  using Base::min;\n\n  // BitGen::max()\n  //\n  // Returns the largest possible value from this bit generator.\n  using Base::max;\n\n  // BitGen::discard(num)\n  //\n  // Advances the internal state of this bit generator by `num` times, and\n  // discards the intermediate results.\n  using Base::discard;\n\n  // BitGen::operator()()\n  //\n  // Invoke the URBG, returning a generated value.\n  using Base::operator();\n\n  using Base::operator==;\n  using Base::operator!=;\n};\n\n// -----------------------------------------------------------------------------\n// absl::InsecureBitGen\n// -----------------------------------------------------------------------------\n//\n// `absl::InsecureBitGen` is an efficient random bit generator for generating\n// random values, recommended only for performance-sensitive use cases where\n// `absl::BitGen` is not satisfactory when compute-bounded by bit generation\n// costs.\n//\n// Example:\n//\n//   // Create an absl::InsecureBitGen\n//   absl::InsecureBitGen gen;\n//   for (size_t i = 0; i < 1000000; i++) {\n//\n//     // Generate a bunch of random values from some complex distribution\n//     auto my_rnd = some_distribution(gen, 1, 1000);\n//   }\n//\n// Like `absl::BitGen`, `absl::InsecureBitGen` is seeded by default with\n// non-deterministic data to produce different sequences of random values across\n// different instances, including different binary invocations. (This behavior\n// is different than the standard library bit generators, which use golden\n// values as their seeds.)\n//\n// `absl::InsecureBitGen` may be constructed with an optional seed sequence\n// type, conforming to [rand.req.seed_seq], which will be mixed with additional\n// non-deterministic data, as detailed in the `absl::BitGen` comment.\n//\n// `absl::InsecureBitGen` meets the requirements of the Uniform Random Bit\n// Generator (URBG) concept as per the C++17 standard [rand.req.urng] though\n// its implementation differs slightly with [rand.req.eng]. Like its standard\n// library equivalents (e.g. `std::mersenne_twister_engine`)\n// `absl::InsecureBitGen` is not cryptographically secure.\n//\n// Prefer `absl::BitGen` over `absl::InsecureBitGen` as the general type is\n// often fast enough for the vast majority of applications. However, it is\n// reasonable to use `absl::InsecureBitGen` in tests or when using a URBG\n// in small isolated tasks such as in `std::shuffle`.\n//\n// This type is thread-compatible, but not thread-safe.\nclass InsecureBitGen : private random_internal::NonsecureURBGBase<\n                           random_internal::pcg64_2018_engine> {\n  using Base =\n      random_internal::NonsecureURBGBase<random_internal::pcg64_2018_engine>;\n\n public:\n  using result_type = typename Base::result_type;\n\n  // InsecureBitGen()\n  // InsecureBitGen(SeedSequence seed_seq)\n  //\n  // Copy disallowed.\n  // Move allowed.\n  using Base::Base;\n  using Base::operator=;\n\n  // InsecureBitGen::min()\n  //\n  // Returns the smallest possible value from this bit generator.\n  using Base::min;\n\n  // InsecureBitGen::max()\n  //\n  // Returns the largest possible value from this bit generator.\n  using Base::max;\n\n  // InsecureBitGen::discard(num)\n  //\n  // Advances the internal state of this bit generator by `num` times, and\n  // discards the intermediate results.\n  using Base::discard;\n\n  // InsecureBitGen::operator()()\n  //\n  // Invoke the URBG, returning a generated value.\n  using Base::operator();\n\n  using Base::operator==;\n  using Base::operator!=;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_RANDOM_H_\n"
  },
  {
    "path": "absl/random/seed_gen_exception.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/seed_gen_exception.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nstatic constexpr const char kExceptionMessage[] =\n    \"Failed generating seed-material for URBG.\";\n\nSeedGenException::~SeedGenException() = default;\n\nconst char* SeedGenException::what() const noexcept {\n  return kExceptionMessage;\n}\n\nnamespace random_internal {\n\nvoid ThrowSeedGenException() {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw absl::SeedGenException();\n#else\n  ABSL_RAW_LOG(FATAL, \"%s\", kExceptionMessage);\n  std::terminate();\n#endif\n}\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/seed_gen_exception.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: seed_gen_exception.h\n// -----------------------------------------------------------------------------\n//\n// This header defines an exception class which may be thrown if unpredictable\n// events prevent the derivation of suitable seed-material for constructing a\n// bit generator conforming to [rand.req.urng] (eg. entropy cannot be read from\n// /dev/urandom on a Unix-based system).\n//\n// Note: if exceptions are disabled, `std::terminate()` is called instead.\n\n#ifndef ABSL_RANDOM_SEED_GEN_EXCEPTION_H_\n#define ABSL_RANDOM_SEED_GEN_EXCEPTION_H_\n\n#include <exception>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n//------------------------------------------------------------------------------\n// SeedGenException\n//------------------------------------------------------------------------------\nclass SeedGenException : public std::exception {\n public:\n  SeedGenException() = default;\n  ~SeedGenException() override;\n  const char* what() const noexcept override;\n};\n\nnamespace random_internal {\n\n// throw delegator\n[[noreturn]] void ThrowSeedGenException();\n\n}  // namespace random_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_SEED_GEN_EXCEPTION_H_\n"
  },
  {
    "path": "absl/random/seed_sequences.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/seed_sequences.h\"\n\n#include <iterator>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/entropy_pool.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nSeedSeq MakeSeedSeq() {\n  SeedSeq::result_type seed_material[8];\n  random_internal::GetEntropyFromRandenPool(&seed_material[0],\n                                            sizeof(seed_material[0]) * 8);\n  return SeedSeq(std::begin(seed_material), std::end(seed_material));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/random/seed_sequences.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: seed_sequences.h\n// -----------------------------------------------------------------------------\n//\n// This header contains utilities for creating and working with seed sequences\n// conforming to [rand.req.seedseq]. In general, direct construction of seed\n// sequences is discouraged, but use-cases for construction of identical bit\n// generators (using the same seed sequence) may be helpful (e.g. replaying a\n// simulation whose state is derived from variates of a bit generator).\n\n#ifndef ABSL_RANDOM_SEED_SEQUENCES_H_\n#define ABSL_RANDOM_SEED_SEQUENCES_H_\n\n#include <iterator>\n#include <random>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/random/internal/salted_seed_seq.h\"\n#include \"absl/random/internal/seed_material.h\"\n#include \"absl/random/seed_gen_exception.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// absl::SeedSeq\n// -----------------------------------------------------------------------------\n//\n// `absl::SeedSeq` constructs a seed sequence according to [rand.req.seedseq]\n// for use within bit generators. `absl::SeedSeq`, unlike `std::seed_seq`\n// additionally salts the generated seeds with extra implementation-defined\n// entropy. For that reason, you can use `absl::SeedSeq` in combination with\n// standard library bit generators (e.g. `std::mt19937`) to introduce\n// non-determinism in your seeds.\n//\n// Example:\n//\n//   absl::SeedSeq my_seed_seq({a, b, c});\n//   std::mt19937 my_bitgen(my_seed_seq);\n//\nusing SeedSeq = random_internal::SaltedSeedSeq<std::seed_seq>;\n\n// -----------------------------------------------------------------------------\n// absl::CreateSeedSeqFrom(bitgen*)\n// -----------------------------------------------------------------------------\n//\n// Constructs a seed sequence conforming to [rand.req.seedseq] using variates\n// produced by a provided bit generator.\n//\n// You should generally avoid direct construction of seed sequences, but\n// use-cases for reuse of a seed sequence to construct identical bit generators\n// may be helpful (eg. replaying a simulation whose state is derived from bit\n// generator values).\n//\n// If bitgen == nullptr, then behavior is undefined.\n//\n// Example:\n//\n//   absl::BitGen my_bitgen;\n//   auto seed_seq = absl::CreateSeedSeqFrom(&my_bitgen);\n//   absl::BitGen new_engine(seed_seq); // derived from my_bitgen, but not\n//                                      // correlated.\n//\ntemplate <typename URBG>\nSeedSeq CreateSeedSeqFrom(URBG* urbg) {\n  SeedSeq::result_type seed_material[random_internal::kEntropyBlocksNeeded];\n\n  if (!random_internal::ReadSeedMaterialFromURBG(\n          urbg, absl::MakeSpan(seed_material))) {\n    random_internal::ThrowSeedGenException();\n  }\n  return SeedSeq(std::begin(seed_material), std::end(seed_material));\n}\n\n// -----------------------------------------------------------------------------\n// absl::MakeSeedSeq()\n// -----------------------------------------------------------------------------\n//\n// Constructs an `absl::SeedSeq` salting the generated values using\n// implementation-defined entropy. The returned sequence can be used to create\n// equivalent bit generators correlated using this sequence.\n//\n// Example:\n//\n//   auto my_seed_seq = absl::MakeSeedSeq();\n//   std::mt19937 rng1(my_seed_seq);\n//   std::mt19937 rng2(my_seed_seq);\n//   EXPECT_EQ(rng1(), rng2());\n//\nSeedSeq MakeSeedSeq();\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_SEED_SEQUENCES_H_\n"
  },
  {
    "path": "absl/random/seed_sequences_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/seed_sequences.h\"\n\n#include <iterator>\n#include <random>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/internal/nonsecure_base.h\"\n#include \"absl/random/random.h\"\nnamespace {\n\nTEST(SeedSequences, Examples) {\n  {\n    absl::SeedSeq seed_seq({1, 2, 3});\n    absl::BitGen bitgen(seed_seq);\n\n    EXPECT_NE(0, bitgen());\n  }\n  {\n    absl::BitGen engine;\n    auto seed_seq = absl::CreateSeedSeqFrom(&engine);\n    absl::BitGen bitgen(seed_seq);\n\n    EXPECT_NE(engine(), bitgen());\n  }\n  {\n    auto seed_seq = absl::MakeSeedSeq();\n    std::mt19937 random(seed_seq);\n\n    EXPECT_NE(0, random());\n  }\n}\n\nTEST(CreateSeedSeqFrom, CompatibleWithStdTypes) {\n  using ExampleNonsecureURBG =\n      absl::random_internal::NonsecureURBGBase<std::minstd_rand0>;\n\n  // Construct a URBG instance.\n  ExampleNonsecureURBG rng;\n\n  // Construct a Seed Sequence from its variates.\n  auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);\n\n  // Ensure that another URBG can be validly constructed from the Seed Sequence.\n  std::mt19937_64{seq_from_rng};\n}\n\nTEST(CreateSeedSeqFrom, CompatibleWithBitGenerator) {\n  // Construct a URBG instance.\n  absl::BitGen rng;\n\n  // Construct a Seed Sequence from its variates.\n  auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);\n\n  // Ensure that another URBG can be validly constructed from the Seed Sequence.\n  std::mt19937_64{seq_from_rng};\n}\n\nTEST(CreateSeedSeqFrom, CompatibleWithInsecureBitGen) {\n  // Construct a URBG instance.\n  absl::InsecureBitGen rng;\n\n  // Construct a Seed Sequence from its variates.\n  auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);\n\n  // Ensure that another URBG can be validly constructed from the Seed Sequence.\n  std::mt19937_64{seq_from_rng};\n}\n\nTEST(CreateSeedSeqFrom, CompatibleWithRawURBG) {\n  // Construct a URBG instance.\n  std::random_device urandom;\n\n  // Construct a Seed Sequence from its variates, using 64b of seed-material.\n  auto seq_from_rng = absl::CreateSeedSeqFrom(&urandom);\n\n  // Ensure that another URBG can be validly constructed from the Seed Sequence.\n  std::mt19937_64{seq_from_rng};\n}\n\ntemplate <typename URBG>\nvoid TestReproducibleVariateSequencesForNonsecureURBG() {\n  const size_t kNumVariates = 1000;\n\n  URBG rng;\n  // Reused for both RNG instances.\n  auto reusable_seed = absl::CreateSeedSeqFrom(&rng);\n\n  typename URBG::result_type variates[kNumVariates];\n  {\n    URBG child(reusable_seed);\n    for (auto& variate : variates) {\n      variate = child();\n    }\n  }\n  // Ensure that variate-sequence can be \"replayed\" by identical RNG.\n  {\n    URBG child(reusable_seed);\n    for (auto& variate : variates) {\n      ASSERT_EQ(variate, child());\n    }\n  }\n}\n\nTEST(CreateSeedSeqFrom, ReproducesVariateSequencesForInsecureBitGen) {\n  TestReproducibleVariateSequencesForNonsecureURBG<absl::InsecureBitGen>();\n}\n\nTEST(CreateSeedSeqFrom, ReproducesVariateSequencesForBitGenerator) {\n  TestReproducibleVariateSequencesForNonsecureURBG<absl::BitGen>();\n}\n}  // namespace\n"
  },
  {
    "path": "absl/random/uniform_int_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: uniform_int_distribution.h\n// -----------------------------------------------------------------------------\n//\n// This header defines a class for representing a uniform integer distribution\n// over the closed (inclusive) interval [a,b]. You use this distribution in\n// combination with an Abseil random bit generator to produce random values\n// according to the rules of the distribution.\n//\n// `absl::uniform_int_distribution` is a drop-in replacement for the C++11\n// `std::uniform_int_distribution` [rand.dist.uni.int] but is considerably\n// faster than the libstdc++ implementation.\n\n#ifndef ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_\n#define ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_\n\n#include <cassert>\n#include <istream>\n#include <limits>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/internal/traits.h\"\n#include \"absl/random/internal/wide_multiply.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::uniform_int_distribution<T>\n//\n// This distribution produces random integer values uniformly distributed in the\n// closed (inclusive) interval [a, b].\n//\n// Example:\n//\n//   absl::BitGen gen;\n//\n//   // Use the distribution to produce a value between 1 and 6, inclusive.\n//   int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen);\n//\ntemplate <typename IntType = int>\nclass uniform_int_distribution {\n private:\n  using unsigned_type =\n      typename random_internal::make_unsigned_bits<IntType>::type;\n\n public:\n  using result_type = IntType;\n\n  class param_type {\n   public:\n    using distribution_type = uniform_int_distribution;\n\n    explicit param_type(\n        result_type lo = 0,\n        result_type hi = (std::numeric_limits<result_type>::max)())\n        : lo_(lo),\n          range_(static_cast<unsigned_type>(hi) -\n                 static_cast<unsigned_type>(lo)) {\n      // [rand.dist.uni.int] precondition 2\n      assert(lo <= hi);\n    }\n\n    result_type a() const { return lo_; }\n    result_type b() const {\n      return static_cast<result_type>(static_cast<unsigned_type>(lo_) + range_);\n    }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.lo_ == b.lo_ && a.range_ == b.range_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class uniform_int_distribution;\n    unsigned_type range() const { return range_; }\n\n    result_type lo_;\n    unsigned_type range_;\n\n    static_assert(random_internal::IsIntegral<result_type>::value,\n                  \"Class-template absl::uniform_int_distribution<> must be \"\n                  \"parameterized using an integral type.\");\n  };  // param_type\n\n  uniform_int_distribution() : uniform_int_distribution(0) {}\n\n  explicit uniform_int_distribution(\n      result_type lo,\n      result_type hi = (std::numeric_limits<result_type>::max)())\n      : param_(lo, hi) {}\n\n  explicit uniform_int_distribution(const param_type& param) : param_(param) {}\n\n  // uniform_int_distribution<T>::reset()\n  //\n  // Resets the uniform int distribution. Note that this function has no effect\n  // because the distribution already produces independent values.\n  void reset() {}\n\n  template <typename URBG>\n  result_type operator()(URBG& gen) {  // NOLINT(runtime/references)\n    return (*this)(gen, param());\n  }\n\n  template <typename URBG>\n  result_type operator()(\n      URBG& gen, const param_type& param) {  // NOLINT(runtime/references)\n    return static_cast<result_type>(param.a() + Generate(gen, param.range()));\n  }\n\n  result_type a() const { return param_.a(); }\n  result_type b() const { return param_.b(); }\n\n  param_type param() const { return param_; }\n  void param(const param_type& params) { param_ = params; }\n\n  result_type(min)() const { return a(); }\n  result_type(max)() const { return b(); }\n\n  friend bool operator==(const uniform_int_distribution& a,\n                         const uniform_int_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const uniform_int_distribution& a,\n                         const uniform_int_distribution& b) {\n    return !(a == b);\n  }\n\n private:\n  // Generates a value in the *closed* interval [0, R]\n  template <typename URBG>\n  unsigned_type Generate(URBG& g,  // NOLINT(runtime/references)\n                         unsigned_type R);\n  param_type param_;\n};\n\n// -----------------------------------------------------------------------------\n// Implementation details follow\n// -----------------------------------------------------------------------------\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,\n    const uniform_int_distribution<IntType>& x) {\n  using stream_type =\n      typename random_internal::stream_format_type<IntType>::type;\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os << static_cast<stream_type>(x.a()) << os.fill()\n     << static_cast<stream_type>(x.b());\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,\n    uniform_int_distribution<IntType>& x) {\n  using param_type = typename uniform_int_distribution<IntType>::param_type;\n  using result_type = typename uniform_int_distribution<IntType>::result_type;\n  using stream_type =\n      typename random_internal::stream_format_type<IntType>::type;\n\n  stream_type a;\n  stream_type b;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  is >> a >> b;\n  if (!is.fail()) {\n    x.param(\n        param_type(static_cast<result_type>(a), static_cast<result_type>(b)));\n  }\n  return is;\n}\n\ntemplate <typename IntType>\ntemplate <typename URBG>\ntypename random_internal::make_unsigned_bits<IntType>::type\nuniform_int_distribution<IntType>::Generate(\n    URBG& g,  // NOLINT(runtime/references)\n    typename random_internal::make_unsigned_bits<IntType>::type R) {\n  random_internal::FastUniformBits<unsigned_type> fast_bits;\n  unsigned_type bits = fast_bits(g);\n  const unsigned_type Lim = R + 1;\n  if ((R & Lim) == 0) {\n    // If the interval's length is a power of two range, just take the low bits.\n    return bits & R;\n  }\n\n  // Generates a uniform variate on [0, Lim) using fixed-point multiplication.\n  // The above fast-path guarantees that Lim is representable in unsigned_type.\n  //\n  // Algorithm adapted from\n  // http://lemire.me/blog/2016/06/30/fast-random-shuffling/, with added\n  // explanation.\n  //\n  // The algorithm creates a uniform variate `bits` in the interval [0, 2^N),\n  // and treats it as the fractional part of a fixed-point real value in [0, 1),\n  // multiplied by 2^N.  For example, 0.25 would be represented as 2^(N - 2),\n  // because 2^N * 0.25 == 2^(N - 2).\n  //\n  // Next, `bits` and `Lim` are multiplied with a wide-multiply to bring the\n  // value into the range [0, Lim).  The integral part (the high word of the\n  // multiplication result) is then very nearly the desired result.  However,\n  // this is not quite accurate; viewing the multiplication result as one\n  // double-width integer, the resulting values for the sample are mapped as\n  // follows:\n  //\n  // If the result lies in this interval:       Return this value:\n  //        [0, 2^N)                                    0\n  //        [2^N, 2 * 2^N)                              1\n  //        ...                                         ...\n  //        [K * 2^N, (K + 1) * 2^N)                    K\n  //        ...                                         ...\n  //        [(Lim - 1) * 2^N, Lim * 2^N)                Lim - 1\n  //\n  // While all of these intervals have the same size, the result of `bits * Lim`\n  // must be a multiple of `Lim`, and not all of these intervals contain the\n  // same number of multiples of `Lim`.  In particular, some contain\n  // `F = floor(2^N / Lim)` and some contain `F + 1 = ceil(2^N / Lim)`.  This\n  // difference produces a small nonuniformity, which is corrected by applying\n  // rejection sampling to one of the values in the \"larger intervals\" (i.e.,\n  // the intervals containing `F + 1` multiples of `Lim`.\n  //\n  // An interval contains `F + 1` multiples of `Lim` if and only if its smallest\n  // value modulo 2^N is less than `2^N % Lim`.  The unique value satisfying\n  // this property is used as the one for rejection.  That is, a value of\n  // `bits * Lim` is rejected if `(bit * Lim) % 2^N < (2^N % Lim)`.\n\n  using helper = random_internal::wide_multiply<unsigned_type>;\n  auto product = helper::multiply(bits, Lim);\n\n  // Two optimizations here:\n  // * Rejection occurs with some probability less than 1/2, and for reasonable\n  //   ranges considerably less (in particular, less than 1/(F+1)), so\n  //   ABSL_PREDICT_FALSE is apt.\n  // * `Lim` is an overestimate of `threshold`, and doesn't require a divide.\n  if (ABSL_PREDICT_FALSE(helper::lo(product) < Lim)) {\n    // This quantity is exactly equal to `2^N % Lim`, but does not require high\n    // precision calculations: `2^N % Lim` is congruent to `(2^N - Lim) % Lim`.\n    // Ideally this could be expressed simply as `-X` rather than `2^N - X`, but\n    // for types smaller than int, this calculation is incorrect due to integer\n    // promotion rules.\n    const unsigned_type threshold =\n        ((std::numeric_limits<unsigned_type>::max)() - Lim + 1) % Lim;\n    while (helper::lo(product) < threshold) {\n      bits = fast_bits(g);\n      product = helper::multiply(bits, Lim);\n    }\n  }\n\n  return helper::hi(product);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/uniform_int_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/uniform_int_distribution.h\"\n\n#include <cmath>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\n\ntemplate <typename IntType>\nclass UniformIntDistributionTest : public ::testing::Test {};\n\nusing IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t,\n                                  uint32_t, int64_t, uint64_t>;\nTYPED_TEST_SUITE(UniformIntDistributionTest, IntTypes);\n\nTYPED_TEST(UniformIntDistributionTest, ParamSerializeTest) {\n  // This test essentially ensures that the parameters serialize,\n  // not that the values generated cover the full range.\n  using Limits = std::numeric_limits<TypeParam>;\n  using param_type =\n      typename absl::uniform_int_distribution<TypeParam>::param_type;\n  const TypeParam kMin = std::is_unsigned<TypeParam>::value ? 37 : -105;\n  const TypeParam kNegOneOrZero = std::is_unsigned<TypeParam>::value ? 0 : -1;\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n  for (const auto& param : {\n           param_type(),\n           param_type(2, 2),  // Same\n           param_type(9, 32),\n           param_type(kMin, 115),\n           param_type(kNegOneOrZero, Limits::max()),\n           param_type(Limits::min(), Limits::max()),\n           param_type(Limits::lowest(), Limits::max()),\n           param_type(Limits::min() + 1, Limits::max() - 1),\n       }) {\n    const auto a = param.a();\n    const auto b = param.b();\n    absl::uniform_int_distribution<TypeParam> before(a, b);\n    EXPECT_EQ(before.a(), param.a());\n    EXPECT_EQ(before.b(), param.b());\n\n    {\n      // Initialize via param_type\n      absl::uniform_int_distribution<TypeParam> via_param(param);\n      EXPECT_EQ(via_param, before);\n    }\n\n    // Initialize via iostreams\n    std::stringstream ss;\n    ss << before;\n\n    absl::uniform_int_distribution<TypeParam> after(Limits::min() + 3,\n                                                    Limits::max() - 5);\n\n    EXPECT_NE(before.a(), after.a());\n    EXPECT_NE(before.b(), after.b());\n    EXPECT_NE(before.param(), after.param());\n    EXPECT_NE(before, after);\n\n    ss >> after;\n\n    EXPECT_EQ(before.a(), after.a());\n    EXPECT_EQ(before.b(), after.b());\n    EXPECT_EQ(before.param(), after.param());\n    EXPECT_EQ(before, after);\n\n    // Smoke test.\n    auto sample_min = after.max();\n    auto sample_max = after.min();\n    for (int i = 0; i < kCount; i++) {\n      auto sample = after(gen);\n      EXPECT_GE(sample, after.min());\n      EXPECT_LE(sample, after.max());\n      if (sample > sample_max) {\n        sample_max = sample;\n      }\n      if (sample < sample_min) {\n        sample_min = sample;\n      }\n    }\n    LOG(INFO) << \"Range: \" << sample_min << \", \" << sample_max;\n  }\n}\n\nTYPED_TEST(UniformIntDistributionTest, ViolatesPreconditionsDeathTest) {\n#if GTEST_HAS_DEATH_TEST\n  // Hi < Lo\n  EXPECT_DEBUG_DEATH(\n      { absl::uniform_int_distribution<TypeParam> dist(10, 1); }, \"\");\n#endif  // GTEST_HAS_DEATH_TEST\n#if defined(NDEBUG)\n  // opt-mode, for invalid parameters, will generate a garbage value,\n  // but should not enter an infinite loop.\n  absl::InsecureBitGen gen;\n  absl::uniform_int_distribution<TypeParam> dist(10, 1);\n  auto x = dist(gen);\n\n  // Any value will generate a non-empty string.\n  EXPECT_FALSE(absl::StrCat(+x).empty()) << x;\n#endif  // NDEBUG\n}\n\nTYPED_TEST(UniformIntDistributionTest, TestMoments) {\n  constexpr int kSize = 100000;\n  using Limits = std::numeric_limits<TypeParam>;\n  using param_type =\n      typename absl::uniform_int_distribution<TypeParam>::param_type;\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the quality of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};\n\n  std::vector<double> values(kSize);\n  for (const auto& param :\n       {param_type(0, Limits::max()), param_type(13, 127)}) {\n    absl::uniform_int_distribution<TypeParam> dist(param);\n    for (int i = 0; i < kSize; i++) {\n      const auto sample = dist(rng);\n      ASSERT_LE(dist.param().a(), sample);\n      ASSERT_GE(dist.param().b(), sample);\n      values[i] = sample;\n    }\n\n    auto moments = absl::random_internal::ComputeDistributionMoments(values);\n    const double a = dist.param().a();\n    const double b = dist.param().b();\n    const double n = (b - a + 1);\n    const double mean = (a + b) / 2;\n    const double var = ((b - a + 1) * (b - a + 1) - 1) / 12;\n    const double kurtosis = 3 - 6 * (n * n + 1) / (5 * (n * n - 1));\n\n    // TODO(ahh): this is not the right bound\n    // empirically validated with --runs_per_test=10000.\n    EXPECT_NEAR(mean, moments.mean, 0.01 * var);\n    EXPECT_NEAR(var, moments.variance, 0.015 * var);\n    EXPECT_NEAR(0.0, moments.skewness, 0.025);\n    EXPECT_NEAR(kurtosis, moments.kurtosis, 0.02 * kurtosis);\n  }\n}\n\nTYPED_TEST(UniformIntDistributionTest, ChiSquaredTest50) {\n  using absl::random_internal::kChiSquared;\n\n  constexpr size_t kTrials = 1000;\n  constexpr int kBuckets = 50;  // inclusive, so actually +1\n  constexpr double kExpected =\n      static_cast<double>(kTrials) / static_cast<double>(kBuckets);\n\n  // Empirically validated with --runs_per_test=10000.\n  const int kThreshold =\n      absl::random_internal::ChiSquareValue(kBuckets, 0.999999);\n\n  const TypeParam min = std::is_unsigned<TypeParam>::value ? 37 : -37;\n  const TypeParam max = min + kBuckets;\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the quality of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};\n\n  absl::uniform_int_distribution<TypeParam> dist(min, max);\n\n  std::vector<int32_t> counts(kBuckets + 1, 0);\n  for (size_t i = 0; i < kTrials; i++) {\n    auto x = dist(rng);\n    counts[x - min]++;\n  }\n  double chi_square = absl::random_internal::ChiSquareWithExpected(\n      std::begin(counts), std::end(counts), kExpected);\n  if (chi_square > kThreshold) {\n    double p_value =\n        absl::random_internal::ChiSquarePValue(chi_square, kBuckets);\n\n    // Chi-squared test failed. Output does not appear to be uniform.\n    std::string msg;\n    for (const auto& a : counts) {\n      absl::StrAppend(&msg, a, \"\\n\");\n    }\n    absl::StrAppend(&msg, kChiSquared, \" p-value \", p_value, \"\\n\");\n    absl::StrAppend(&msg, \"High \", kChiSquared, \" value: \", chi_square, \" > \",\n                    kThreshold);\n    LOG(INFO) << msg;\n    FAIL() << msg;\n  }\n}\n\nTEST(UniformIntDistributionTest, StabilityTest) {\n  // absl::uniform_int_distribution stability relies only on integer operations.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(12);\n\n  {\n    absl::uniform_int_distribution<int32_t> dist(0, 4);\n    for (auto& v : output) {\n      v = dist(urbg);\n    }\n  }\n  EXPECT_EQ(12, urbg.invocations());\n  EXPECT_THAT(output, testing::ElementsAre(4, 4, 3, 2, 1, 0, 1, 4, 3, 1, 3, 1));\n\n  {\n    urbg.reset();\n    absl::uniform_int_distribution<int32_t> dist(0, 100);\n    for (auto& v : output) {\n      v = dist(urbg);\n    }\n  }\n  EXPECT_EQ(12, urbg.invocations());\n  EXPECT_THAT(output, testing::ElementsAre(97, 86, 75, 41, 36, 16, 38, 92, 67,\n                                           30, 80, 38));\n\n  {\n    urbg.reset();\n    absl::uniform_int_distribution<int32_t> dist(0, 10000);\n    for (auto& v : output) {\n      v = dist(urbg);\n    }\n  }\n  EXPECT_EQ(12, urbg.invocations());\n  EXPECT_THAT(output, testing::ElementsAre(9648, 8562, 7439, 4089, 3571, 1602,\n                                           3813, 9195, 6641, 2986, 7956, 3765));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/uniform_real_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: uniform_real_distribution.h\n// -----------------------------------------------------------------------------\n//\n// This header defines a class for representing a uniform floating-point\n// distribution over a half-open interval [a,b). You use this distribution in\n// combination with an Abseil random bit generator to produce random values\n// according to the rules of the distribution.\n//\n// `absl::uniform_real_distribution` is a drop-in replacement for the C++11\n// `std::uniform_real_distribution` [rand.dist.uni.real] but is considerably\n// faster than the libstdc++ implementation.\n//\n// Note: the standard-library version may occasionally return `1.0` when\n// default-initialized. See https://bugs.llvm.org//show_bug.cgi?id=18767\n// `absl::uniform_real_distribution` does not exhibit this behavior.\n\n#ifndef ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_\n#define ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cmath>\n#include <cstdint>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/random/internal/fast_uniform_bits.h\"\n#include \"absl/random/internal/generate_real.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::uniform_real_distribution<T>\n//\n// This distribution produces random floating-point values uniformly distributed\n// over the half-open interval [a, b).\n//\n// Example:\n//\n//   absl::BitGen gen;\n//\n//   // Use the distribution to produce a value between 0.0 (inclusive)\n//   // and 1.0 (exclusive).\n//   double value = absl::uniform_real_distribution<double>(0, 1)(gen);\n//\ntemplate <typename RealType = double>\nclass uniform_real_distribution {\n public:\n  using result_type = RealType;\n\n  class param_type {\n   public:\n    using distribution_type = uniform_real_distribution;\n\n    explicit param_type(result_type lo = 0, result_type hi = 1)\n        : lo_(lo), hi_(hi), range_(hi - lo) {\n      // [rand.dist.uni.real] preconditions 2 & 3\n      assert(lo <= hi);\n\n      // NOTE: For integral types, we can promote the range to an unsigned type,\n      // which gives full width of the range. However for real (fp) types, this\n      // is not possible, so value generation cannot use the full range of the\n      // real type.\n      assert(range_ <= (std::numeric_limits<result_type>::max)());\n    }\n\n    result_type a() const { return lo_; }\n    result_type b() const { return hi_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.lo_ == b.lo_ && a.hi_ == b.hi_;\n    }\n\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class uniform_real_distribution;\n    result_type lo_, hi_, range_;\n\n    static_assert(std::is_floating_point<RealType>::value,\n                  \"Class-template absl::uniform_real_distribution<> must be \"\n                  \"parameterized using a floating-point type.\");\n  };\n\n  uniform_real_distribution() : uniform_real_distribution(0) {}\n\n  explicit uniform_real_distribution(result_type lo, result_type hi = 1)\n      : param_(lo, hi) {}\n\n  explicit uniform_real_distribution(const param_type& param) : param_(param) {}\n\n  // uniform_real_distribution<T>::reset()\n  //\n  // Resets the uniform real distribution. Note that this function has no effect\n  // because the distribution already produces independent values.\n  void reset() {}\n\n  template <typename URBG>\n  result_type operator()(URBG& gen) {  // NOLINT(runtime/references)\n    return operator()(gen, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& gen,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  result_type a() const { return param_.a(); }\n  result_type b() const { return param_.b(); }\n\n  param_type param() const { return param_; }\n  void param(const param_type& params) { param_ = params; }\n\n  result_type(min)() const { return a(); }\n  result_type(max)() const { return b(); }\n\n  friend bool operator==(const uniform_real_distribution& a,\n                         const uniform_real_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const uniform_real_distribution& a,\n                         const uniform_real_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  param_type param_;\n  random_internal::FastUniformBits<uint64_t> fast_u64_;\n};\n\n// -----------------------------------------------------------------------------\n// Implementation details follow\n// -----------------------------------------------------------------------------\ntemplate <typename RealType>\ntemplate <typename URBG>\ntypename uniform_real_distribution<RealType>::result_type\nuniform_real_distribution<RealType>::operator()(\n    URBG& gen, const param_type& p) {  // NOLINT(runtime/references)\n  using random_internal::GeneratePositiveTag;\n  using random_internal::GenerateRealFromBits;\n  using real_type =\n      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;\n\n  while (true) {\n    const result_type sample =\n        GenerateRealFromBits<real_type, GeneratePositiveTag, true>(\n            fast_u64_(gen));\n    const result_type res = p.a() + (sample * p.range_);\n    if (res < p.b() || p.range_ <= 0 || !std::isfinite(p.range_)) {\n      return res;\n    }\n    // else sample rejected, try again.\n  }\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const uniform_real_distribution<RealType>& x) {\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);\n  os << x.a() << os.fill() << x.b();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename RealType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,     // NOLINT(runtime/references)\n    uniform_real_distribution<RealType>& x) {  // NOLINT(runtime/references)\n  using param_type = typename uniform_real_distribution<RealType>::param_type;\n  using result_type = typename uniform_real_distribution<RealType>::result_type;\n  auto saver = random_internal::make_istream_state_saver(is);\n  auto a = random_internal::read_floating_point<result_type>(is);\n  if (is.fail()) return is;\n  auto b = random_internal::read_floating_point<result_type>(is);\n  if (!is.fail()) {\n    x.param(param_type(a, b));\n  }\n  return is;\n}\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/uniform_real_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/uniform_real_distribution.h\"\n\n#include <cfloat>\n#include <cmath>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/numeric/internal/representation.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/distribution_test_util.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n\n// NOTES:\n// * Some documentation on generating random real values suggests that\n//   it is possible to use std::nextafter(b, DBL_MAX) to generate a value on\n//   the closed range [a, b]. Unfortunately, that technique is not universally\n//   reliable due to floating point quantization.\n//\n// * absl::uniform_real_distribution<float> generates between 2^28 and 2^29\n//   distinct floating point values in the range [0, 1).\n//\n// * absl::uniform_real_distribution<float> generates at least 2^23 distinct\n//   floating point values in the range [1, 2). This should be the same as\n//   any other range covered by a single exponent in IEEE 754.\n//\n// * absl::uniform_real_distribution<double> generates more than 2^52 distinct\n//   values in the range [0, 1), and should generate at least 2^52 distinct\n//   values in the range of [1, 2).\n//\n\nnamespace {\n\ntemplate <typename RealType>\nclass UniformRealDistributionTest : public ::testing::Test {};\n\n// double-double arithmetic is not supported well by either GCC or Clang; see\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,\n// https://bugs.llvm.org/show_bug.cgi?id=49131, and\n// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests\n// with double doubles until compiler support is better.\nusing RealTypes =\n    std::conditional<absl::numeric_internal::IsDoubleDouble(),\n                     ::testing::Types<float, double>,\n                     ::testing::Types<float, double, long double>>::type;\n\nTYPED_TEST_SUITE(UniformRealDistributionTest, RealTypes);\n\nTYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) {\n#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0\n  // We're using an x87-compatible FPU, and intermediate operations are\n  // performed with 80-bit floats. This produces slightly different results from\n  // what we expect below.\n  GTEST_SKIP()\n      << \"Skipping the test because we detected x87 floating-point semantics\";\n#endif\n  using DistributionType = absl::uniform_real_distribution<TypeParam>;\n  using real_type = TypeParam;\n  using param_type = typename DistributionType::param_type;\n\n  constexpr const real_type kMax = std::numeric_limits<real_type>::max();\n  constexpr const real_type kMin = std::numeric_limits<real_type>::min();\n  constexpr const real_type kEpsilon =\n      std::numeric_limits<real_type>::epsilon();\n  constexpr const real_type kLowest =\n      std::numeric_limits<real_type>::lowest();  // -max\n\n  const real_type kDenormMax = std::nextafter(kMin, real_type{0});\n  const real_type kOneMinusE =\n      std::nextafter(real_type{1}, real_type{0});  // 1 - epsilon\n\n  constexpr const real_type kTwo60{1152921504606846976};  // 2^60\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n  for (const auto& param : {\n           param_type(),\n           param_type(real_type{0}, real_type{1}),\n           param_type(real_type(-0.1), real_type(0.1)),\n           param_type(real_type(0.05), real_type(0.12)),\n           param_type(real_type(-0.05), real_type(0.13)),\n           param_type(real_type(-0.05), real_type(-0.02)),\n           // range = 0\n           param_type(real_type(2.0), real_type(2.0)),  // Same\n           // double range = 0\n           // 2^60 , 2^60 + 2^6\n           param_type(kTwo60, real_type(1152921504606847040)),\n           // 2^60 , 2^60 + 2^7\n           param_type(kTwo60, real_type(1152921504606847104)),\n           // double range = 2^8\n           // 2^60 , 2^60 + 2^8\n           param_type(kTwo60, real_type(1152921504606847232)),\n           // float range = 0\n           // 2^60 , 2^60 + 2^36\n           param_type(kTwo60, real_type(1152921573326323712)),\n           // 2^60 , 2^60 + 2^37\n           param_type(kTwo60, real_type(1152921642045800448)),\n           // float range = 2^38\n           // 2^60 , 2^60 + 2^38\n           param_type(kTwo60, real_type(1152921779484753920)),\n           // Limits\n           param_type(0, kMax),\n           param_type(kLowest, 0),\n           param_type(0, kMin),\n           param_type(0, kEpsilon),\n           param_type(-kEpsilon, kEpsilon),\n           param_type(0, kOneMinusE),\n           param_type(0, kDenormMax),\n       }) {\n    // Validate parameters.\n    const auto a = param.a();\n    const auto b = param.b();\n    DistributionType before(a, b);\n    EXPECT_EQ(before.a(), param.a());\n    EXPECT_EQ(before.b(), param.b());\n\n    {\n      DistributionType via_param(param);\n      EXPECT_EQ(via_param, before);\n    }\n\n    std::stringstream ss;\n    ss << before;\n    DistributionType after(real_type(1.0), real_type(3.1));\n\n    EXPECT_NE(before.a(), after.a());\n    EXPECT_NE(before.b(), after.b());\n    EXPECT_NE(before.param(), after.param());\n    EXPECT_NE(before, after);\n\n    ss >> after;\n\n    EXPECT_EQ(before.a(), after.a());\n    EXPECT_EQ(before.b(), after.b());\n    EXPECT_EQ(before.param(), after.param());\n    EXPECT_EQ(before, after);\n\n    // Smoke test.\n    auto sample_min = after.max();\n    auto sample_max = after.min();\n    for (int i = 0; i < kCount; i++) {\n      auto sample = after(gen);\n      // Failure here indicates a bug in uniform_real_distribution::operator(),\n      // or bad parameters--range too large, etc.\n      if (after.min() == after.max()) {\n        EXPECT_EQ(sample, after.min());\n      } else {\n        EXPECT_GE(sample, after.min());\n        EXPECT_LT(sample, after.max());\n      }\n      if (sample > sample_max) {\n        sample_max = sample;\n      }\n      if (sample < sample_min) {\n        sample_min = sample;\n      }\n    }\n\n    if (!std::is_same<real_type, long double>::value) {\n      // static_cast<double>(long double) can overflow.\n      LOG(INFO) << \"Range: \" << static_cast<double>(sample_min) << \", \"\n                << static_cast<double>(sample_max);\n    }\n  }\n}\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4756)  // Constant arithmetic overflow.\n#endif\nTYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) {\n  using DistributionType = absl::uniform_real_distribution<TypeParam>;\n  using real_type = TypeParam;\n\n#if GTEST_HAS_DEATH_TEST\n  // Hi < Lo\n  EXPECT_DEBUG_DEATH({ DistributionType dist(10.0, 1.0); }, \"\");\n\n  // Hi - Lo > numeric_limits<>::max()\n  EXPECT_DEBUG_DEATH(\n      {\n        DistributionType dist(std::numeric_limits<real_type>::lowest(),\n                              std::numeric_limits<real_type>::max());\n      },\n      \"\");\n\n  // kEpsilon guarantees that max + kEpsilon = inf.\n  const auto kEpsilon = std::nexttoward(\n      (std::numeric_limits<real_type>::max() -\n       std::nexttoward(std::numeric_limits<real_type>::max(), 0.0)) /\n          2,\n      std::numeric_limits<real_type>::max());\n  EXPECT_DEBUG_DEATH(\n      {\n        DistributionType dist(-kEpsilon, std::numeric_limits<real_type>::max());\n      },\n      \"\");\n  EXPECT_DEBUG_DEATH(\n      {\n        DistributionType dist(std::numeric_limits<real_type>::lowest(),\n                              kEpsilon);\n      },\n      \"\");\n\n#endif  // GTEST_HAS_DEATH_TEST\n#if defined(NDEBUG)\n  // opt-mode, for invalid parameters, will generate a garbage value,\n  // but should not enter an infinite loop.\n  absl::InsecureBitGen gen;\n  {\n    DistributionType dist(10.0, 1.0);\n    auto x = dist(gen);\n    EXPECT_FALSE(std::isnan(x)) << x;\n  }\n  {\n    DistributionType dist(std::numeric_limits<real_type>::lowest(),\n                          std::numeric_limits<real_type>::max());\n    auto x = dist(gen);\n    // Infinite result.\n    EXPECT_FALSE(std::isfinite(x)) << x;\n  }\n#endif  // NDEBUG\n}\n#ifdef _MSC_VER\n#pragma warning(pop)  // warning(disable:4756)\n#endif\n\nTYPED_TEST(UniformRealDistributionTest, TestMoments) {\n  using DistributionType = absl::uniform_real_distribution<TypeParam>;\n\n  constexpr int kSize = 1000000;\n  std::vector<double> values(kSize);\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};\n\n  DistributionType dist;\n  for (int i = 0; i < kSize; i++) {\n    values[i] = dist(rng);\n  }\n\n  const auto moments =\n      absl::random_internal::ComputeDistributionMoments(values);\n  EXPECT_NEAR(0.5, moments.mean, 0.01);\n  EXPECT_NEAR(1 / 12.0, moments.variance, 0.015);\n  EXPECT_NEAR(0.0, moments.skewness, 0.02);\n  EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.015);\n}\n\nTYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) {\n  using DistributionType = absl::uniform_real_distribution<TypeParam>;\n  using param_type = typename DistributionType::param_type;\n\n  using absl::random_internal::kChiSquared;\n\n  constexpr size_t kTrials = 100000;\n  constexpr int kBuckets = 50;\n  constexpr double kExpected =\n      static_cast<double>(kTrials) / static_cast<double>(kBuckets);\n\n  // 1-in-100000 threshold, but remember, there are about 8 tests\n  // in this file. And the test could fail for other reasons.\n  // Empirically validated with --runs_per_test=10000.\n  const int kThreshold =\n      absl::random_internal::ChiSquareValue(kBuckets - 1, 0.999999);\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};\n\n  for (const auto& param : {param_type(0, 1), param_type(5, 12),\n                            param_type(-5, 13), param_type(-5, -2)}) {\n    const double min_val = param.a();\n    const double max_val = param.b();\n    const double factor = kBuckets / (max_val - min_val);\n\n    std::vector<int32_t> counts(kBuckets, 0);\n    DistributionType dist(param);\n    for (size_t i = 0; i < kTrials; i++) {\n      auto x = dist(rng);\n      auto bucket = static_cast<size_t>((x - min_val) * factor);\n      counts[bucket]++;\n    }\n\n    double chi_square = absl::random_internal::ChiSquareWithExpected(\n        std::begin(counts), std::end(counts), kExpected);\n    if (chi_square > kThreshold) {\n      double p_value =\n          absl::random_internal::ChiSquarePValue(chi_square, kBuckets);\n\n      // Chi-squared test failed. Output does not appear to be uniform.\n      std::string msg;\n      for (const auto& a : counts) {\n        absl::StrAppend(&msg, a, \"\\n\");\n      }\n      absl::StrAppend(&msg, kChiSquared, \" p-value \", p_value, \"\\n\");\n      absl::StrAppend(&msg, \"High \", kChiSquared, \" value: \", chi_square, \" > \",\n                      kThreshold);\n      LOG(INFO) << msg;\n      FAIL() << msg;\n    }\n  }\n}\n\nTYPED_TEST(UniformRealDistributionTest, StabilityTest) {\n  using DistributionType = absl::uniform_real_distribution<TypeParam>;\n  using real_type = TypeParam;\n\n  // absl::uniform_real_distribution stability relies only on\n  // random_internal::GenerateRealFromBits.\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(12);\n\n  DistributionType dist;\n  std::generate(std::begin(output), std::end(output), [&] {\n    return static_cast<int>(real_type(1000000) * dist(urbg));\n  });\n\n  EXPECT_THAT(\n      output,  //\n      testing::ElementsAre(59, 999246, 762494, 395876, 167716, 82545, 925251,\n                           77341, 12527, 708791, 834451, 932808));\n}\n\nTEST(UniformRealDistributionTest, AlgorithmBounds) {\n  absl::uniform_real_distribution<double> dist;\n\n  {\n    // This returns the smallest value >0 from absl::uniform_real_distribution.\n    absl::random_internal::sequence_urbg urbg({0x0000000000000001ull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 5.42101086242752217004e-20);\n  }\n\n  {\n    // This returns a value very near 0.5 from absl::uniform_real_distribution.\n    absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 0.499999999999999944489);\n  }\n  {\n    // This returns a value very near 0.5 from absl::uniform_real_distribution.\n    absl::random_internal::sequence_urbg urbg({0x8000000000000000ull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 0.5);\n  }\n\n  {\n    // This returns the largest value <1 from absl::uniform_real_distribution.\n    absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFEFull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 0.999999999999999888978);\n  }\n  {\n    // This *ALSO* returns the largest value <1.\n    absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull});\n    double a = dist(urbg);\n    EXPECT_EQ(a, 0.999999999999999888978);\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/random/zipf_distribution.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_RANDOM_ZIPF_DISTRIBUTION_H_\n#define ABSL_RANDOM_ZIPF_DISTRIBUTION_H_\n\n#include <cassert>\n#include <cmath>\n#include <istream>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/internal/iostream_state_saver.h\"\n#include \"absl/random/internal/traits.h\"\n#include \"absl/random/uniform_real_distribution.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::zipf_distribution produces random integer-values in the range [0, k],\n// distributed according to the unnormalized discrete probability function:\n//\n//  P(x) = (v + x) ^ -q\n//\n// The parameter `v` must be greater than 0 and the parameter `q` must be\n// greater than 1. If either of these parameters take invalid values then the\n// behavior is undefined.\n//\n// IntType is the result_type generated by the generator. It must be of integral\n// type; a static_assert ensures this is the case.\n//\n// The implementation is based on W.Hormann, G.Derflinger:\n//\n// \"Rejection-Inversion to Generate Variates from Monotone Discrete\n// Distributions\"\n//\n// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz\n//\ntemplate <typename IntType = int>\nclass zipf_distribution {\n public:\n  using result_type = IntType;\n\n  class param_type {\n   public:\n    using distribution_type = zipf_distribution;\n\n    // Preconditions: k >= 0, v > 0, q > 1\n    // The preconditions are validated when NDEBUG is not defined via\n    // a pair of assert() directives.\n    // If NDEBUG is defined and either or both of these parameters take invalid\n    // values, the behavior of the class is undefined.\n    explicit param_type(result_type k = (std::numeric_limits<IntType>::max)(),\n                        double q = 2.0, double v = 1.0);\n\n    result_type k() const { return k_; }\n    double q() const { return q_; }\n    double v() const { return v_; }\n\n    friend bool operator==(const param_type& a, const param_type& b) {\n      return a.k_ == b.k_ && a.q_ == b.q_ && a.v_ == b.v_;\n    }\n    friend bool operator!=(const param_type& a, const param_type& b) {\n      return !(a == b);\n    }\n\n   private:\n    friend class zipf_distribution;\n    inline double h(double x) const;\n    inline double hinv(double x) const;\n    inline double compute_s() const;\n    inline double pow_negative_q(double x) const;\n\n    // Parameters here are exactly the same as the parameters of Algorithm ZRI\n    // in the paper.\n    IntType k_;\n    double q_;\n    double v_;\n\n    double one_minus_q_;  // 1-q\n    double s_;\n    double one_minus_q_inv_;  // 1 / 1-q\n    double hxm_;              // h(k + 0.5)\n    double hx0_minus_hxm_;    // h(x0) - h(k + 0.5)\n\n    static_assert(random_internal::IsIntegral<IntType>::value,\n                  \"Class-template absl::zipf_distribution<> must be \"\n                  \"parameterized using an integral type.\");\n  };\n\n  zipf_distribution()\n      : zipf_distribution((std::numeric_limits<IntType>::max)()) {}\n\n  explicit zipf_distribution(result_type k, double q = 2.0, double v = 1.0)\n      : param_(k, q, v) {}\n\n  explicit zipf_distribution(const param_type& p) : param_(p) {}\n\n  void reset() {}\n\n  template <typename URBG>\n  result_type operator()(URBG& g) {  // NOLINT(runtime/references)\n    return (*this)(g, param_);\n  }\n\n  template <typename URBG>\n  result_type operator()(URBG& g,  // NOLINT(runtime/references)\n                         const param_type& p);\n\n  result_type k() const { return param_.k(); }\n  double q() const { return param_.q(); }\n  double v() const { return param_.v(); }\n\n  param_type param() const { return param_; }\n  void param(const param_type& p) { param_ = p; }\n\n  result_type(min)() const { return 0; }\n  result_type(max)() const { return k(); }\n\n  friend bool operator==(const zipf_distribution& a,\n                         const zipf_distribution& b) {\n    return a.param_ == b.param_;\n  }\n  friend bool operator!=(const zipf_distribution& a,\n                         const zipf_distribution& b) {\n    return a.param_ != b.param_;\n  }\n\n private:\n  param_type param_;\n};\n\n// --------------------------------------------------------------------------\n// Implementation details follow\n// --------------------------------------------------------------------------\n\ntemplate <typename IntType>\nzipf_distribution<IntType>::param_type::param_type(\n    typename zipf_distribution<IntType>::result_type k, double q, double v)\n    : k_(k), q_(q), v_(v), one_minus_q_(1 - q) {\n  assert(q > 1);\n  assert(v > 0);\n  assert(k >= 0);\n  one_minus_q_inv_ = 1 / one_minus_q_;\n\n  // Setup for the ZRI algorithm (pg 17 of the paper).\n  // Compute: h(i max) => h(k + 0.5)\n  constexpr double kMax = 18446744073709549568.0;\n  double kd = static_cast<double>(k);\n  // TODO(absl-team): Determine if this check is needed, and if so, add a test\n  // that fails for k > kMax\n  if (kd > kMax) {\n    // Ensure that our maximum value is capped to a value which will\n    // round-trip back through double.\n    kd = kMax;\n  }\n  hxm_ = h(kd + 0.5);\n\n  // Compute: h(0)\n  const bool use_precomputed = (v == 1.0 && q == 2.0);\n  const double h0x5 = use_precomputed ? (-1.0 / 1.5)  // exp(-log(1.5))\n                                      : h(0.5);\n  const double elogv_q = (v_ == 1.0) ? 1 : pow_negative_q(v_);\n\n  // h(0) = h(0.5) - exp(log(v) * -q)\n  hx0_minus_hxm_ = (h0x5 - elogv_q) - hxm_;\n\n  // And s\n  s_ = use_precomputed ? 0.46153846153846123 : compute_s();\n}\n\ntemplate <typename IntType>\ndouble zipf_distribution<IntType>::param_type::h(double x) const {\n  // std::exp(one_minus_q_ * std::log(v_ + x)) * one_minus_q_inv_;\n  x += v_;\n  return (one_minus_q_ == -1.0)\n             ? (-1.0 / x)  // -exp(-log(x))\n             : (std::exp(std::log(x) * one_minus_q_) * one_minus_q_inv_);\n}\n\ntemplate <typename IntType>\ndouble zipf_distribution<IntType>::param_type::hinv(double x) const {\n  // std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)) - v_;\n  return -v_ + ((one_minus_q_ == -1.0)\n                    ? (-1.0 / x)  // exp(-log(-x))\n                    : std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)));\n}\n\ntemplate <typename IntType>\ndouble zipf_distribution<IntType>::param_type::compute_s() const {\n  // 1 - hinv(h(1.5) - std::exp(std::log(v_ + 1) * -q_));\n  return 1.0 - hinv(h(1.5) - pow_negative_q(v_ + 1.0));\n}\n\ntemplate <typename IntType>\ndouble zipf_distribution<IntType>::param_type::pow_negative_q(double x) const {\n  // std::exp(std::log(x) * -q_);\n  return q_ == 2.0 ? (1.0 / (x * x)) : std::exp(std::log(x) * -q_);\n}\n\ntemplate <typename IntType>\ntemplate <typename URBG>\ntypename zipf_distribution<IntType>::result_type\nzipf_distribution<IntType>::operator()(\n    URBG& g, const param_type& p) {  // NOLINT(runtime/references)\n  absl::uniform_real_distribution<double> uniform_double;\n  double k;\n  for (;;) {\n    const double v = uniform_double(g);\n    const double u = p.hxm_ + v * p.hx0_minus_hxm_;\n    const double x = p.hinv(u);\n    k = rint(x);                                   // std::floor(x + 0.5);\n    if (k > static_cast<double>(p.k())) continue;  // reject k > max_k\n    if (k - x <= p.s_) break;\n    const double h = p.h(k + 0.5);\n    const double r = p.pow_negative_q(p.v_ + k);\n    if (u >= h - r) break;\n  }\n  IntType ki = static_cast<IntType>(k);\n  assert(ki <= p.k_);\n  return ki;\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_ostream<CharT, Traits>& operator<<(\n    std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)\n    const zipf_distribution<IntType>& x) {\n  using stream_type =\n      typename random_internal::stream_format_type<IntType>::type;\n  auto saver = random_internal::make_ostream_state_saver(os);\n  os.precision(random_internal::stream_precision_helper<double>::kPrecision);\n  os << static_cast<stream_type>(x.k()) << os.fill() << x.q() << os.fill()\n     << x.v();\n  return os;\n}\n\ntemplate <typename CharT, typename Traits, typename IntType>\nstd::basic_istream<CharT, Traits>& operator>>(\n    std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)\n    zipf_distribution<IntType>& x) {        // NOLINT(runtime/references)\n  using result_type = typename zipf_distribution<IntType>::result_type;\n  using param_type = typename zipf_distribution<IntType>::param_type;\n  using stream_type =\n      typename random_internal::stream_format_type<IntType>::type;\n  stream_type k;\n  double q;\n  double v;\n\n  auto saver = random_internal::make_istream_state_saver(is);\n  is >> k >> q >> v;\n  if (!is.fail()) {\n    x.param(param_type(static_cast<result_type>(k), q, v));\n  }\n  return is;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_\n"
  },
  {
    "path": "absl/random/zipf_distribution_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/random/zipf_distribution.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <iterator>\n#include <random>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/internal/chi_square.h\"\n#include \"absl/random/internal/pcg_engine.h\"\n#include \"absl/random/internal/sequence_urbg.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace {\n\nusing ::absl::random_internal::kChiSquared;\nusing ::testing::ElementsAre;\n\ntemplate <typename IntType>\nclass ZipfDistributionTypedTest : public ::testing::Test {};\n\nusing IntTypes = ::testing::Types<int, int8_t, int16_t, int32_t, int64_t,\n                                  uint8_t, uint16_t, uint32_t, uint64_t>;\nTYPED_TEST_SUITE(ZipfDistributionTypedTest, IntTypes);\n\nTYPED_TEST(ZipfDistributionTypedTest, SerializeTest) {\n  using param_type = typename absl::zipf_distribution<TypeParam>::param_type;\n\n  constexpr int kCount = 1000;\n  absl::InsecureBitGen gen;\n  for (const auto& param : {\n           param_type(),\n           param_type(32),\n           param_type(100, 3, 2),\n           param_type(std::numeric_limits<TypeParam>::max(), 4, 3),\n           param_type(std::numeric_limits<TypeParam>::max() / 2),\n       }) {\n    // Validate parameters.\n    const auto k = param.k();\n    const auto q = param.q();\n    const auto v = param.v();\n\n    absl::zipf_distribution<TypeParam> before(k, q, v);\n    EXPECT_EQ(before.k(), param.k());\n    EXPECT_EQ(before.q(), param.q());\n    EXPECT_EQ(before.v(), param.v());\n\n    {\n      absl::zipf_distribution<TypeParam> via_param(param);\n      EXPECT_EQ(via_param, before);\n    }\n\n    // Validate stream serialization.\n    std::stringstream ss;\n    ss << before;\n    absl::zipf_distribution<TypeParam> after(4, 5.5, 4.4);\n\n    EXPECT_NE(before.k(), after.k());\n    EXPECT_NE(before.q(), after.q());\n    EXPECT_NE(before.v(), after.v());\n    EXPECT_NE(before.param(), after.param());\n    EXPECT_NE(before, after);\n\n    ss >> after;\n\n    EXPECT_EQ(before.k(), after.k());\n    EXPECT_EQ(before.q(), after.q());\n    EXPECT_EQ(before.v(), after.v());\n    EXPECT_EQ(before.param(), after.param());\n    EXPECT_EQ(before, after);\n\n    // Smoke test.\n    auto sample_min = after.max();\n    auto sample_max = after.min();\n    for (int i = 0; i < kCount; i++) {\n      auto sample = after(gen);\n      EXPECT_GE(sample, after.min());\n      EXPECT_LE(sample, after.max());\n      if (sample > sample_max) sample_max = sample;\n      if (sample < sample_min) sample_min = sample;\n    }\n    LOG(INFO) << \"Range: \" << sample_min << \", \" << sample_max;\n  }\n}\n\nclass ZipfModel {\n public:\n  ZipfModel(size_t k, double q, double v) : k_(k), q_(q), v_(v) {}\n\n  double mean() const { return mean_; }\n\n  // For the other moments of the Zipf distribution, see, for example,\n  // http://mathworld.wolfram.com/ZipfDistribution.html\n\n  // PMF(k) = (1 / k^s) / H(N,s)\n  // Returns the probability that any single invocation returns k.\n  double PMF(size_t i) { return i >= hnq_.size() ? 0.0 : hnq_[i] / sum_hnq_; }\n\n  // CDF = H(k, s) / H(N,s)\n  double CDF(size_t i) {\n    if (i >= hnq_.size()) {\n      return 1.0;\n    }\n    auto it = std::begin(hnq_);\n    double h = 0.0;\n    for (const auto end = it; it != end; it++) {\n      h += *it;\n    }\n    return h / sum_hnq_;\n  }\n\n  // The InverseCDF returns the k values which bound p on the upper and lower\n  // bound. Since there is no closed-form solution, this is implemented as a\n  // bisction of the cdf.\n  std::pair<size_t, size_t> InverseCDF(double p) {\n    size_t min = 0;\n    size_t max = hnq_.size();\n    while (max > min + 1) {\n      size_t target = (max + min) >> 1;\n      double x = CDF(target);\n      if (x > p) {\n        max = target;\n      } else {\n        min = target;\n      }\n    }\n    return {min, max};\n  }\n\n  // Compute the probability totals, which are based on the generalized harmonic\n  // number, H(N,s).\n  //   H(N,s) == SUM(k=1..N, 1 / k^s)\n  //\n  // In the limit, H(N,s) == zetac(s) + 1.\n  //\n  // NOTE: The mean of a zipf distribution could be computed here as well.\n  // Mean :=  H(N, s-1) / H(N,s).\n  // Given the parameter v = 1, this gives the following function:\n  // (Hn(100, 1) - Hn(1,1)) / (Hn(100,2) - Hn(1,2)) = 6.5944\n  //\n  void Init() {\n    if (!hnq_.empty()) {\n      return;\n    }\n    hnq_.clear();\n    hnq_.reserve(std::min(k_, size_t{1000}));\n\n    sum_hnq_ = 0;\n    double qm1 = q_ - 1.0;\n    double sum_hnq_m1 = 0;\n    for (size_t i = 0; i < k_; i++) {\n      // Partial n-th generalized harmonic number\n      const double x = v_ + i;\n\n      // H(n, q-1)\n      const double hnqm1 = (q_ == 2.0)   ? (1.0 / x)\n                           : (q_ == 3.0) ? (1.0 / (x * x))\n                                         : std::pow(x, -qm1);\n      sum_hnq_m1 += hnqm1;\n\n      // H(n, q)\n      const double hnq = (q_ == 2.0)   ? (1.0 / (x * x))\n                         : (q_ == 3.0) ? (1.0 / (x * x * x))\n                                       : std::pow(x, -q_);\n      sum_hnq_ += hnq;\n      hnq_.push_back(hnq);\n      if (i > 1000 && hnq <= 1e-10) {\n        // The harmonic number is too small.\n        break;\n      }\n    }\n    assert(sum_hnq_ > 0);\n    mean_ = sum_hnq_m1 / sum_hnq_;\n  }\n\n private:\n  const size_t k_;\n  const double q_;\n  const double v_;\n\n  double mean_;\n  std::vector<double> hnq_;\n  double sum_hnq_;\n};\n\nusing zipf_u64 = absl::zipf_distribution<uint64_t>;\n\nclass ZipfTest : public testing::TestWithParam<zipf_u64::param_type>,\n                 public ZipfModel {\n public:\n  ZipfTest() : ZipfModel(GetParam().k(), GetParam().q(), GetParam().v()) {}\n\n  // We use a fixed bit generator for distribution accuracy tests.  This allows\n  // these tests to be deterministic, while still testing the qualify of the\n  // implementation.\n  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};\n};\n\nTEST_P(ZipfTest, ChiSquaredTest) {\n  const auto& param = GetParam();\n  Init();\n\n  size_t trials = 10000;\n\n  // Find the split-points for the buckets.\n  std::vector<size_t> points;\n  std::vector<double> expected;\n  {\n    double last_cdf = 0.0;\n    double min_p = 1.0;\n    for (double p = 0.01; p < 1.0; p += 0.01) {\n      auto x = InverseCDF(p);\n      if (points.empty() || points.back() < x.second) {\n        const double p = CDF(x.second);\n        points.push_back(x.second);\n        double q = p - last_cdf;\n        expected.push_back(q);\n        last_cdf = p;\n        if (q < min_p) {\n          min_p = q;\n        }\n      }\n    }\n    if (last_cdf < 0.999) {\n      points.push_back(std::numeric_limits<size_t>::max());\n      double q = 1.0 - last_cdf;\n      expected.push_back(q);\n      if (q < min_p) {\n        min_p = q;\n      }\n    } else {\n      points.back() = std::numeric_limits<size_t>::max();\n      expected.back() += (1.0 - last_cdf);\n    }\n    // The Chi-Squared score is not completely scale-invariant; it works best\n    // when the small values are in the small digits.\n    trials = static_cast<size_t>(8.0 / min_p);\n  }\n  ASSERT_GT(points.size(), 0);\n\n  // Generate n variates and fill the counts vector with the count of their\n  // occurrences.\n  std::vector<int64_t> buckets(points.size(), 0);\n  double avg = 0;\n  {\n    zipf_u64 dis(param);\n    for (size_t i = 0; i < trials; i++) {\n      uint64_t x = dis(rng_);\n      ASSERT_LE(x, dis.max());\n      ASSERT_GE(x, dis.min());\n      avg += static_cast<double>(x);\n      auto it = std::upper_bound(std::begin(points), std::end(points),\n                                 static_cast<size_t>(x));\n      buckets[std::distance(std::begin(points), it)]++;\n    }\n    avg = avg / static_cast<double>(trials);\n  }\n\n  // Validate the output using the Chi-Squared test.\n  for (auto& e : expected) {\n    e *= trials;\n  }\n\n  // The null-hypothesis is that the distribution is a poisson distribution with\n  // the provided mean (not estimated from the data).\n  const int dof = static_cast<int>(expected.size()) - 1;\n\n  // NOTE: This test runs about 15x per invocation, so a value of 0.9995 is\n  // approximately correct for a test suite failure rate of 1 in 100.  In\n  // practice we see failures slightly higher than that.\n  const double threshold = absl::random_internal::ChiSquareValue(dof, 0.9999);\n\n  const double chi_square = absl::random_internal::ChiSquare(\n      std::begin(buckets), std::end(buckets), std::begin(expected),\n      std::end(expected));\n\n  const double p_actual =\n      absl::random_internal::ChiSquarePValue(chi_square, dof);\n\n  // Log if the chi_squared value is above the threshold.\n  if (chi_square > threshold) {\n    LOG(INFO) << \"values\";\n    for (size_t i = 0; i < expected.size(); i++) {\n      LOG(INFO) << points[i] << \": \" << buckets[i] << \" vs. E=\" << expected[i];\n    }\n    LOG(INFO) << \"trials \" << trials;\n    LOG(INFO) << \"mean \" << avg << \" vs. expected \" << mean();\n    LOG(INFO) << kChiSquared << \"(data, \" << dof << \") = \" << chi_square << \" (\"\n              << p_actual << \")\";\n    LOG(INFO) << kChiSquared << \" @ 0.9995 = \" << threshold;\n    FAIL() << kChiSquared << \" value of \" << chi_square\n           << \" is above the threshold.\";\n  }\n}\n\nstd::vector<zipf_u64::param_type> GenParams() {\n  using param = zipf_u64::param_type;\n  const auto k = param().k();\n  const auto q = param().q();\n  const auto v = param().v();\n  const uint64_t k2 = 1 << 10;\n  return std::vector<zipf_u64::param_type>{\n      // Default\n      param(k, q, v),\n      // vary K\n      param(4, q, v), param(1 << 4, q, v), param(k2, q, v),\n      // vary V\n      param(k2, q, 0.5), param(k2, q, 1.5), param(k2, q, 2.5), param(k2, q, 10),\n      // vary Q\n      param(k2, 1.5, v), param(k2, 3, v), param(k2, 5, v), param(k2, 10, v),\n      // Vary V & Q\n      param(k2, 1.5, 0.5), param(k2, 3, 1.5), param(k, 10, 10)};\n}\n\nstd::string ParamName(\n    const ::testing::TestParamInfo<zipf_u64::param_type>& info) {\n  const auto& p = info.param;\n  std::string name = absl::StrCat(\"k_\", p.k(), \"__q_\", absl::SixDigits(p.q()),\n                                  \"__v_\", absl::SixDigits(p.v()));\n  return absl::StrReplaceAll(name, {{\"+\", \"_\"}, {\"-\", \"_\"}, {\".\", \"_\"}});\n}\n\nINSTANTIATE_TEST_SUITE_P(All, ZipfTest, ::testing::ValuesIn(GenParams()),\n                         ParamName);\n\n// NOTE: absl::zipf_distribution is not guaranteed to be stable.\nTEST(ZipfDistributionTest, StabilityTest) {\n  // absl::zipf_distribution stability relies on\n  // absl::uniform_real_distribution, std::log, std::exp, std::log1p\n  absl::random_internal::sequence_urbg urbg(\n      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,\n       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,\n       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,\n       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});\n\n  std::vector<int> output(10);\n\n  {\n    absl::zipf_distribution<int32_t> dist;\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n    EXPECT_THAT(output, ElementsAre(10031, 0, 0, 3, 6, 0, 7, 47, 0, 0));\n  }\n  urbg.reset();\n  {\n    absl::zipf_distribution<int32_t> dist(std::numeric_limits<int32_t>::max(),\n                                          3.3);\n    std::generate(std::begin(output), std::end(output),\n                  [&] { return dist(urbg); });\n    EXPECT_THAT(output, ElementsAre(44, 0, 0, 0, 0, 1, 0, 1, 3, 0));\n  }\n}\n\nTEST(ZipfDistributionTest, AlgorithmBounds) {\n  absl::zipf_distribution<int32_t> dist;\n\n  // Small values from absl::uniform_real_distribution map to larger Zipf\n  // distribution values.\n  const std::pair<uint64_t, int32_t> kInputs[] = {\n      {0xffffffffffffffff, 0x0}, {0x7fffffffffffffff, 0x0},\n      {0x3ffffffffffffffb, 0x1}, {0x1ffffffffffffffd, 0x4},\n      {0xffffffffffffffe, 0x9},  {0x7ffffffffffffff, 0x12},\n      {0x3ffffffffffffff, 0x25}, {0x1ffffffffffffff, 0x4c},\n      {0xffffffffffffff, 0x99},  {0x7fffffffffffff, 0x132},\n      {0x3fffffffffffff, 0x265}, {0x1fffffffffffff, 0x4cc},\n      {0xfffffffffffff, 0x999},  {0x7ffffffffffff, 0x1332},\n      {0x3ffffffffffff, 0x2665}, {0x1ffffffffffff, 0x4ccc},\n      {0xffffffffffff, 0x9998},  {0x7fffffffffff, 0x1332f},\n      {0x3fffffffffff, 0x2665a}, {0x1fffffffffff, 0x4cc9e},\n      {0xfffffffffff, 0x998e0},  {0x7ffffffffff, 0x133051},\n      {0x3ffffffffff, 0x265ae4}, {0x1ffffffffff, 0x4c9ed3},\n      {0xffffffffff, 0x98e223},  {0x7fffffffff, 0x13058c4},\n      {0x3fffffffff, 0x25b178e}, {0x1fffffffff, 0x4a062b2},\n      {0xfffffffff, 0x8ee23b8},  {0x7ffffffff, 0x10b21642},\n      {0x3ffffffff, 0x1d89d89d}, {0x1ffffffff, 0x2fffffff},\n      {0xffffffff, 0x45d1745d},  {0x7fffffff, 0x5a5a5a5a},\n      {0x3fffffff, 0x69ee5846},  {0x1fffffff, 0x73ecade3},\n      {0xfffffff, 0x79a9d260},   {0x7ffffff, 0x7cc0532b},\n      {0x3ffffff, 0x7e5ad146},   {0x1ffffff, 0x7f2c0bec},\n      {0xffffff, 0x7f95adef},    {0x7fffff, 0x7fcac0da},\n      {0x3fffff, 0x7fe55ae2},    {0x1fffff, 0x7ff2ac0e},\n      {0xfffff, 0x7ff955ae},     {0x7ffff, 0x7ffcaac1},\n      {0x3ffff, 0x7ffe555b},     {0x1ffff, 0x7fff2aac},\n      {0xffff, 0x7fff9556},      {0x7fff, 0x7fffcaab},\n      {0x3fff, 0x7fffe555},      {0x1fff, 0x7ffff2ab},\n      {0xfff, 0x7ffff955},       {0x7ff, 0x7ffffcab},\n      {0x3ff, 0x7ffffe55},       {0x1ff, 0x7fffff2b},\n      {0xff, 0x7fffff95},        {0x7f, 0x7fffffcb},\n      {0x3f, 0x7fffffe5},        {0x1f, 0x7ffffff3},\n      {0xf, 0x7ffffff9},         {0x7, 0x7ffffffd},\n      {0x3, 0x7ffffffe},         {0x1, 0x7fffffff},\n  };\n\n  for (const auto& instance : kInputs) {\n    absl::random_internal::sequence_urbg urbg({instance.first});\n    EXPECT_EQ(instance.second, dist(urbg));\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/status/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This package contains `absl::Status`.\n# It will expand later to have utilities around `Status` like `StatusOr`,\n# `StatusBuilder` and macros.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"status\",\n    srcs = [\n        \"internal/status_internal.cc\",\n        \"internal/status_internal.h\",\n        \"status.cc\",\n        \"status_payload_printer.cc\",\n    ],\n    hdrs = [\n        \"status.h\",\n        \"status_payload_printer.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:atomic_hook\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/base:strerror\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/debugging:leak_check\",\n        \"//absl/debugging:stacktrace\",\n        \"//absl/debugging:symbolize\",\n        \"//absl/functional:function_ref\",\n        \"//absl/hash\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:optional\",\n        \"//absl/types:source_location\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_test(\n    name = \"status_test\",\n    srcs = [\"status_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":status\",\n        \"//absl/strings\",\n        \"//absl/strings:cord\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:source_location\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"status_benchmark\",\n    testonly = True,\n    srcs = [\"status_benchmark.cc\"],\n    tags = [\"benchmark\"],\n    deps = [\n        \":status\",\n        \"//absl/types:source_location\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"statusor\",\n    srcs = [\n        \"internal/statusor_internal.h\",\n        \"statusor.cc\",\n    ],\n    hdrs = [\n        \"statusor.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":status\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"//absl/strings:has_ostream_operator\",\n        \"//absl/strings:str_format\",\n        \"//absl/types:source_location\",\n        \"//absl/types:span\",\n        \"//absl/types:variant\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"statusor_test\",\n    size = \"small\",\n    srcs = [\"statusor_test.cc\"],\n    deps = [\n        \":status\",\n        \":status_matchers\",\n        \":statusor\",\n        \"//absl/base\",\n        \"//absl/memory\",\n        \"//absl/strings\",\n        \"//absl/types:any\",\n        \"//absl/types:source_location\",\n        \"//absl/types:variant\",\n        \"//absl/utility\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"statusor_benchmark\",\n    testonly = True,\n    srcs = [\"statusor_benchmark.cc\"],\n    tags = [\"benchmark\"],\n    deps = [\n        \":status\",\n        \":statusor\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"status_matchers\",\n    testonly = 1,\n    srcs = [\n        \"internal/status_matchers.cc\",\n        \"internal/status_matchers.h\",\n    ],\n    hdrs = [\"status_matchers.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":status\",\n        \":statusor\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"status_matchers_test\",\n    size = \"small\",\n    srcs = [\"status_matchers_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":status\",\n        \":status_matchers\",\n        \":statusor\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"status_matchers_with_unqualified_macros_test\",\n    size = \"small\",\n    srcs = [\"status_matchers_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    local_defines = [\"ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\"],\n    deps = [\n        \":status\",\n        \":status_matchers\",\n        \":statusor\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/status/CMakeLists.txt",
    "content": "#\n# Copyright 2020 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nabsl_cc_library(\n  NAME\n    status\n  HDRS\n    \"status.h\"\n  SRCS\n    \"internal/status_internal.h\"\n    \"internal/status_internal.cc\"\n    \"status.cc\"\n    \"status_payload_printer.h\"\n    \"status_payload_printer.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEFINES\n    \"$<$<PLATFORM_ID:AIX>:_LINUX_SOURCE_COMPAT>\"\n  DEPS\n    absl::atomic_hook\n    absl::config\n    absl::cord\n    absl::core_headers\n    absl::function_ref\n    absl::inlined_vector\n    absl::leak_check\n    absl::memory\n    absl::no_destructor\n    absl::nullability\n    absl::optional\n    absl::raw_logging_internal\n    absl::source_location\n    absl::span\n    absl::stacktrace\n    absl::str_format\n    absl::strerror\n    absl::strings\n    absl::symbolize\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    status_test\n  SRCS\n   \"status_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::status\n    absl::source_location\n    absl::str_format\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    statusor\n  HDRS\n    \"statusor.h\"\n  SRCS\n    \"statusor.cc\"\n    \"internal/statusor_internal.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::has_ostream_operator\n    absl::nullability\n    absl::raw_logging_internal\n    absl::status\n    absl::source_location\n    absl::str_format\n    absl::strings\n    absl::type_traits\n    absl::utility\n    absl::variant\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    statusor_test\n  SRCS\n   \"statusor_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::status\n    absl::status_matchers\n    absl::statusor\n    absl::source_location\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    status_matchers\n  HDRS\n    \"status_matchers.h\"\n  SRCS\n    \"internal/status_matchers.h\"\n    \"internal/status_matchers.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  LINKOPTS\n    ${ABSL_DEFAULT_LINKOPTS}\n  DEPS\n    absl::base\n    absl::core_headers\n    absl::status\n    absl::statusor\n    absl::strings\n    GTest::gmock\n    GTest::gtest\n  PUBLIC\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    status_matchers_test\n  SRCS\n   \"status_matchers_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::status\n    absl::statusor\n    absl::status_matchers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    status_matchers_with_unqualified_macros_test\n  SRCS\n   \"status_matchers_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEFINES\n    \"ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\"\n  DEPS\n    absl::status\n    absl::statusor\n    absl::status_matchers\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/status/internal/status_internal.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/status/internal/status_internal.h\"\n\n#include <atomic>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <cstring>\n#include <memory>\n#include <optional>\n#include <string>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/debugging/leak_check.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/symbolize.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/status/status.h\"\n#include \"absl/status/status_payload_printer.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace status_internal {\n\nvoid StatusRep::Unref() const {\n  // Fast path: if ref==1, there is no need for a RefCountDec (since\n  // this is the only reference and therefore no other thread is\n  // allowed to be mucking with r).\n  if (ref_.load(std::memory_order_acquire) == 1 ||\n      ref_.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) {\n    delete this;\n  }\n}\n\nstatic std::optional<size_t> FindPayloadIndexByUrl(const Payloads* payloads,\n                                                   absl::string_view type_url) {\n  if (payloads == nullptr) return std::nullopt;\n\n  for (size_t i = 0; i < payloads->size(); ++i) {\n    if ((*payloads)[i].type_url == type_url) return i;\n  }\n\n  return std::nullopt;\n}\n\nstd::optional<absl::Cord> StatusRep::GetPayload(\n    absl::string_view type_url) const {\n  std::optional<size_t> index =\n      status_internal::FindPayloadIndexByUrl(payloads_.get(), type_url);\n  if (index.has_value()) return (*payloads_)[index.value()].payload;\n\n  return std::nullopt;\n}\n\nvoid StatusRep::SetPayload(absl::string_view type_url, absl::Cord payload) {\n  if (payloads_ == nullptr) {\n    payloads_ = absl::make_unique<status_internal::Payloads>();\n  }\n\n  std::optional<size_t> index =\n      status_internal::FindPayloadIndexByUrl(payloads_.get(), type_url);\n  if (index.has_value()) {\n    (*payloads_)[index.value()].payload = std::move(payload);\n    return;\n  }\n\n  payloads_->push_back({std::string(type_url), std::move(payload)});\n}\n\nStatusRep::EraseResult StatusRep::ErasePayload(absl::string_view type_url) {\n  std::optional<size_t> index =\n      status_internal::FindPayloadIndexByUrl(payloads_.get(), type_url);\n  if (!index.has_value()) return {false, Status::PointerToRep(this)};\n  payloads_->erase(payloads_->begin() + index.value());\n  if (payloads_->empty() && message_.empty()) {\n    // Special case: If this can be represented inlined, it MUST be inlined\n    // (== depends on this behavior).\n    EraseResult result = {true, Status::CodeToInlinedRep(code_)};\n    Unref();\n    return result;\n  }\n  return {true, Status::PointerToRep(this)};\n}\n\nvoid StatusRep::ForEachPayload(\n    absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)\n    const {\n  if (auto* payloads = payloads_.get()) {\n    bool in_reverse =\n        payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;\n\n    for (size_t index = 0; index < payloads->size(); ++index) {\n      const auto& elem =\n          (*payloads)[in_reverse ? payloads->size() - 1 - index : index];\n\n#ifdef NDEBUG\n      visitor(elem.type_url, elem.payload);\n#else\n      // In debug mode invalidate the type url to prevent users from relying on\n      // this string lifetime.\n\n      // NOLINTNEXTLINE intentional extra conversion to force temporary.\n      visitor(std::string(elem.type_url), elem.payload);\n#endif  // NDEBUG\n    }\n  }\n}\n\nabsl::Span<const SourceLocation> StatusRep::GetSourceLocations() const {\n  return absl::MakeSpan(source_locations_);\n}\n\nvoid StatusRep::AddSourceLocation(absl::SourceLocation loc) {\n  source_locations_.push_back(loc);\n}\n\nstd::string StatusRep::ToString(StatusToStringMode mode) const {\n  std::string text;\n  absl::StrAppend(&text, absl::StatusCodeToString(code()), \": \", message());\n\n  const bool with_payload = (mode & StatusToStringMode::kWithPayload) ==\n                            StatusToStringMode::kWithPayload;\n\n  if (with_payload) {\n    status_internal::StatusPayloadPrinter printer =\n        status_internal::GetStatusPayloadPrinter();\n    this->ForEachPayload([&](absl::string_view type_url,\n                             const absl::Cord& payload) {\n      std::optional<std::string> result;\n      if (printer) result = printer(type_url, payload);\n      absl::StrAppend(\n          &text, \" [\", type_url, \"='\",\n          result.has_value() ? *result : absl::CHexEscape(std::string(payload)),\n          \"']\");\n    });\n  }\n  const bool with_source_location =\n      (mode & StatusToStringMode::kWithSourceLocation) ==\n      StatusToStringMode::kWithSourceLocation;\n  if (with_source_location && !source_locations_.empty()) {\n    absl::string_view whitespace = (absl::Hash<int>{}(42) % 2 == 0) ? \"\" : \" \";\n    absl::StrAppend(&text, \"\\n=== Source Location Trace: ===\", whitespace,\n                    \"\\n\");\n    for (const absl::SourceLocation loc : GetSourceLocations()) {\n      absl::StrAppend(&text, loc.file_name(), \":\", loc.line(), \"\\n\");\n    }\n  }\n\n  return text;\n}\n\nbool StatusRep::operator==(const StatusRep& other) const {\n  assert(this != &other);\n  if (code_ != other.code_) return false;\n  if (message_ != other.message_) return false;\n  const status_internal::Payloads* this_payloads = payloads_.get();\n  const status_internal::Payloads* other_payloads = other.payloads_.get();\n\n  const status_internal::Payloads no_payloads;\n  const status_internal::Payloads* larger_payloads =\n      this_payloads ? this_payloads : &no_payloads;\n  const status_internal::Payloads* smaller_payloads =\n      other_payloads ? other_payloads : &no_payloads;\n  if (larger_payloads->size() < smaller_payloads->size()) {\n    std::swap(larger_payloads, smaller_payloads);\n  }\n  if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false;\n  // Payloads can be ordered differently, so we can't just compare payload\n  // vectors.\n  for (const auto& payload : *larger_payloads) {\n\n    bool found = false;\n    for (const auto& other_payload : *smaller_payloads) {\n      if (payload.type_url == other_payload.type_url) {\n        if (payload.payload != other_payload.payload) {\n          return false;\n        }\n        found = true;\n        break;\n      }\n    }\n    if (!found) return false;\n  }\n  return true;\n}\n\nStatusRep* absl_nonnull StatusRep::CloneAndUnref() const {\n  // Optimization: no need to create a clone if we already have a refcount of 1.\n  if (ref_.load(std::memory_order_acquire) == 1) {\n    // All StatusRep instances are heap allocated and mutable, therefore this\n    // const_cast will never cast away const from a stack instance.\n    //\n    // CloneAndUnref is the only method that doesn't involve an external cast to\n    // get a mutable StatusRep* from the uintptr_t rep stored in Status.\n    return const_cast<StatusRep*>(this);\n  }\n  std::unique_ptr<status_internal::Payloads> payloads;\n  if (payloads_) {\n    payloads = absl::make_unique<status_internal::Payloads>(*payloads_);\n  }\n  auto* new_rep = new StatusRep(code_, message_, std::move(payloads));\n  new_rep->source_locations_ = source_locations_;\n  Unref();\n  return new_rep;\n}\n\n// Convert canonical code to a value known to this binary.\nabsl::StatusCode MapToLocalCode(int value) {\n  absl::StatusCode code = static_cast<absl::StatusCode>(value);\n  switch (code) {\n    case absl::StatusCode::kOk:\n    case absl::StatusCode::kCancelled:\n    case absl::StatusCode::kUnknown:\n    case absl::StatusCode::kInvalidArgument:\n    case absl::StatusCode::kDeadlineExceeded:\n    case absl::StatusCode::kNotFound:\n    case absl::StatusCode::kAlreadyExists:\n    case absl::StatusCode::kPermissionDenied:\n    case absl::StatusCode::kResourceExhausted:\n    case absl::StatusCode::kFailedPrecondition:\n    case absl::StatusCode::kAborted:\n    case absl::StatusCode::kOutOfRange:\n    case absl::StatusCode::kUnimplemented:\n    case absl::StatusCode::kInternal:\n    case absl::StatusCode::kUnavailable:\n    case absl::StatusCode::kDataLoss:\n    case absl::StatusCode::kUnauthenticated:\n      return code;\n    default:\n      return absl::StatusCode::kUnknown;\n  }\n}\n\nconst char* absl_nonnull MakeCheckFailString(\n    const absl::Status* absl_nonnull status, const char* absl_nonnull prefix) {\n  // There's no need to free this string since the process is crashing.\n  return absl::IgnoreLeak(\n             new std::string(absl::StrCat(\n                 prefix, \" (\",\n                 status->ToString(StatusToStringMode::kWithEverything), \")\")))\n      ->c_str();\n}\n\n}  // namespace status_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/status/internal/status_internal.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_\n#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_\n\n#include <atomic>\n#include <cstdint>\n#include <memory>\n#include <optional>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/types/span.h\"\n\n#ifndef SWIG\n// Disabled for SWIG as it doesn't parse attributes correctly.\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n// Returned Status objects may not be ignored. Codesearch doesn't handle ifdefs\n// as part of a class definitions (b/6995610), so we use a forward declaration.\n//\n// TODO(b/176172494): ABSL_MUST_USE_RESULT should expand to the more strict\n// [[nodiscard]]. For now, just use [[nodiscard]] directly when it is available.\n#if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard)\nclass [[nodiscard]] ABSL_ATTRIBUTE_TRIVIAL_ABI\n    Status;\n#else\nclass ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI\n    Status;\n#endif\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // !SWIG\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nenum class StatusCode : int;\nenum class StatusToStringMode : int;\n\nnamespace status_internal {\n\n// Container for status payloads.\nstruct Payload {\n  std::string type_url;\n  absl::Cord payload;\n};\n\nusing Payloads = absl::InlinedVector<Payload, 1>;\n\n// Reference-counted representation of Status data.\nclass StatusRep {\n public:\n  StatusRep(absl::StatusCode code_arg, absl::string_view message_arg,\n            std::unique_ptr<status_internal::Payloads> payloads_arg)\n      : ref_(int32_t{1}),\n        code_(code_arg),\n        message_(message_arg),\n        payloads_(std::move(payloads_arg)) {}\n\n  absl::StatusCode code() const { return code_; }\n  const std::string& message() const { return message_; }\n\n  // Ref and unref are const to allow access through a const pointer, and are\n  // used during copying operations.\n  void Ref() const { ref_.fetch_add(1, std::memory_order_relaxed); }\n  void Unref() const;\n\n  // Payload methods correspond to the same methods in absl::Status.\n  std::optional<absl::Cord> GetPayload(absl::string_view type_url) const;\n  void SetPayload(absl::string_view type_url, absl::Cord payload);\n  struct EraseResult {\n    bool erased;\n    uintptr_t new_rep;\n  };\n  EraseResult ErasePayload(absl::string_view type_url);\n  void ForEachPayload(\n      absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)\n      const;\n\n  absl::Span<const SourceLocation> GetSourceLocations() const;\n  void AddSourceLocation(absl::SourceLocation loc);\n\n  std::string ToString(StatusToStringMode mode) const;\n\n  bool operator==(const StatusRep& other) const;\n  bool operator!=(const StatusRep& other) const { return !(*this == other); }\n\n  // Returns an equivalent heap allocated StatusRep with refcount 1.\n  //\n  // `this` is not safe to be used after calling as it may have been deleted.\n  StatusRep* absl_nonnull CloneAndUnref() const;\n\n private:\n  mutable std::atomic<int32_t> ref_;\n  absl::StatusCode code_;\n\n  // As an internal implementation detail, we guarantee that if status.message()\n  // is non-empty, then the resulting string_view is null terminated.\n  // This is required to implement 'StatusMessageAsCStr(...)'\n  std::string message_;\n  absl::InlinedVector<absl::SourceLocation, 1> source_locations_;\n  std::unique_ptr<status_internal::Payloads> payloads_;\n};\n\nabsl::StatusCode MapToLocalCode(int value);\n\n// Returns a pointer to a newly-allocated string with the given `prefix`,\n// suitable for output as an error message in assertion/`CHECK()` failures.\n//\n// This is an internal implementation detail for Abseil logging.\nABSL_ATTRIBUTE_PURE_FUNCTION\nconst char* absl_nonnull MakeCheckFailString(\n    const absl::Status* absl_nonnull status, const char* absl_nonnull prefix);\n\n}  // namespace status_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_\n"
  },
  {
    "path": "absl/status/internal/status_matchers.cc",
    "content": "// Copyright 2024 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: status_matchers.cc\n// -----------------------------------------------------------------------------\n\n#include \"absl/status/internal/status_matchers.h\"\n\n#include <ostream>\n#include <string>\n\n#include \"gmock/gmock.h\"  // gmock_for_status_matchers.h\n#include \"absl/base/config.h\"\n#include \"absl/status/status.h\"\n\nnamespace absl_testing {\nABSL_NAMESPACE_BEGIN\nnamespace status_internal {\n\nvoid StatusIsMatcherCommonImpl::DescribeTo(std::ostream* os) const {\n  *os << \"has a status code that \";\n  code_matcher_.DescribeTo(os);\n  *os << \", and has an error message that \";\n  message_matcher_.DescribeTo(os);\n}\n\nvoid StatusIsMatcherCommonImpl::DescribeNegationTo(std::ostream* os) const {\n  *os << \"either has a status code that \";\n  code_matcher_.DescribeNegationTo(os);\n  *os << \", or has an error message that \";\n  message_matcher_.DescribeNegationTo(os);\n}\n\nbool StatusIsMatcherCommonImpl::MatchAndExplain(\n    const ::absl::Status& status,\n    ::testing::MatchResultListener* result_listener) const {\n  ::testing::StringMatchResultListener inner_listener;\n  if (!code_matcher_.MatchAndExplain(status.code(), &inner_listener)) {\n    *result_listener << (inner_listener.str().empty()\n                             ? status.ok() ? \"which is OK\"\n                                           : \"whose status code is wrong\"\n                             : \"which has a status code \" +\n                                   inner_listener.str());\n    return false;\n  }\n\n  if (!message_matcher_.Matches(std::string(status.message()))) {\n    *result_listener << \"whose error message is wrong\";\n    return false;\n  }\n\n  return true;\n}\n\n}  // namespace status_internal\nABSL_NAMESPACE_END\n}  // namespace absl_testing\n"
  },
  {
    "path": "absl/status/internal/status_matchers.h",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_\n#define ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_\n\n#include <ostream>  // NOLINT\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"  // gmock_for_status_matchers.h\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/status/status.h\"\n#include \"absl/status/statusor.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl_testing {\nABSL_NAMESPACE_BEGIN\nnamespace status_internal {\n\n// TODO(b/323927127): Remove ABSL_REFACTOR_INLINE once callers are cleaned up\n// and move it into a namespace like adl_barrier without types to avoid\n// accidental ADL.\nABSL_REFACTOR_INLINE inline const absl::Status& GetStatus(\n    const absl::Status& status) {\n  return status;\n}\n\n// TODO(b/323927127): Remove ABSL_REFACTOR_INLINE once callers are cleaned up\n// and move it into a namespace like adl_barrier without types to avoid\n// accidental ADL.\ntemplate <typename T>\nABSL_REFACTOR_INLINE const absl::Status& GetStatus(\n    const absl::StatusOr<T>& status) {\n  return status.status();\n}\n\n////////////////////////////////////////////////////////////\n// Implementation of IsOkAndHolds().\n\n// Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a\n// reference to StatusOr<T>.\ntemplate <typename StatusOrType>\nclass IsOkAndHoldsMatcherImpl\n    : public ::testing::MatcherInterface<StatusOrType> {\n public:\n  typedef\n      typename std::remove_reference<StatusOrType>::type::value_type value_type;\n\n  template <typename InnerMatcher>\n  explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)\n      : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(\n            std::forward<InnerMatcher>(inner_matcher))) {}\n\n  void DescribeTo(std::ostream* os) const override {\n    *os << \"is OK and has a value that \";\n    inner_matcher_.DescribeTo(os);\n  }\n\n  void DescribeNegationTo(std::ostream* os) const override {\n    *os << \"isn't OK or has a value that \";\n    inner_matcher_.DescribeNegationTo(os);\n  }\n\n  bool MatchAndExplain(\n      StatusOrType actual_value,\n      ::testing::MatchResultListener* result_listener) const override {\n    if (!actual_value.ok()) {\n      *result_listener << \"which has status \" << actual_value.status();\n      return false;\n    }\n\n    // Call through to the inner matcher.\n    return inner_matcher_.MatchAndExplain(*actual_value, result_listener);\n  }\n\n private:\n  const ::testing::Matcher<const value_type&> inner_matcher_;\n};\n\n// Implements IsOkAndHolds(m) as a polymorphic matcher.\ntemplate <typename InnerMatcher>\nclass IsOkAndHoldsMatcher {\n public:\n  explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)\n      : inner_matcher_(std::forward<InnerMatcher>(inner_matcher)) {}\n\n  // Converts this polymorphic matcher to a monomorphic matcher of the\n  // given type.  StatusOrType can be either StatusOr<T> or a\n  // reference to StatusOr<T>.\n  template <typename StatusOrType>\n  operator ::testing::Matcher<StatusOrType>() const {  // NOLINT\n    return ::testing::Matcher<StatusOrType>(\n        new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));\n  }\n\n private:\n  const InnerMatcher inner_matcher_;\n};\n\n////////////////////////////////////////////////////////////\n// Implementation of StatusIs().\n\n// `StatusCode` is implicitly convertible from `int`, `absl::StatusCode`, and\n//  is explicitly convertible to these types as well.\n//\n// We need this class because `absl::StatusCode` (as a scoped enum) is not\n// implicitly convertible to `int`. In order to handle use cases like\n// ```\n// StatusIs(Anyof(absl::StatusCode::kUnknown, absl::StatusCode::kCancelled))\n// ```\n// which uses polymorphic matchers, we need to unify the interfaces into\n// `Matcher<StatusCode>`.\nclass StatusCode {\n public:\n  /*implicit*/ StatusCode(int code)  // NOLINT\n      : code_(code) {}\n  /*implicit*/ StatusCode(::absl::StatusCode code)  // NOLINT\n      : code_(static_cast<int>(code)) {}\n\n  explicit operator int() const { return static_cast<int>(code_); }\n\n  friend inline void PrintTo(const StatusCode& code, std::ostream* os) {\n    absl::string_view text =\n        absl::StatusCodeToStringView(static_cast<absl::StatusCode>(code.code_));\n    if (!text.empty()) {\n      *os << text;\n    } else {\n      *os << code.code_;\n    }\n  }\n\n private:\n  int code_;\n};\n\n// Relational operators to handle matchers like Eq, Lt, etc..\ninline bool operator==(const StatusCode& lhs, const StatusCode& rhs) {\n  return static_cast<int>(lhs) == static_cast<int>(rhs);\n}\ninline bool operator!=(const StatusCode& lhs, const StatusCode& rhs) {\n  return static_cast<int>(lhs) != static_cast<int>(rhs);\n}\n\n// StatusIs() is a polymorphic matcher.  This class is the common\n// implementation of it shared by all types T where StatusIs() can be\n// used as a Matcher<T>.\nclass StatusIsMatcherCommonImpl {\n public:\n  StatusIsMatcherCommonImpl(\n      ::testing::Matcher<StatusCode> code_matcher,\n      ::testing::Matcher<absl::string_view> message_matcher)\n      : code_matcher_(std::move(code_matcher)),\n        message_matcher_(std::move(message_matcher)) {}\n\n  void DescribeTo(std::ostream* os) const;\n\n  void DescribeNegationTo(std::ostream* os) const;\n\n  bool MatchAndExplain(const absl::Status& status,\n                       ::testing::MatchResultListener* result_listener) const;\n\n private:\n  const ::testing::Matcher<StatusCode> code_matcher_;\n  const ::testing::Matcher<absl::string_view> message_matcher_;\n};\n\n// Monomorphic implementation of matcher StatusIs() for a given type\n// T.  T can be Status, StatusOr<>, or a reference to either of them.\ntemplate <typename T>\nclass MonoStatusIsMatcherImpl : public ::testing::MatcherInterface<T> {\n public:\n  explicit MonoStatusIsMatcherImpl(StatusIsMatcherCommonImpl common_impl)\n      : common_impl_(std::move(common_impl)) {}\n\n  void DescribeTo(std::ostream* os) const override {\n    common_impl_.DescribeTo(os);\n  }\n\n  void DescribeNegationTo(std::ostream* os) const override {\n    common_impl_.DescribeNegationTo(os);\n  }\n\n  bool MatchAndExplain(\n      T actual_value,\n      ::testing::MatchResultListener* result_listener) const override {\n    return common_impl_.MatchAndExplain(GetStatus(actual_value),\n                                        result_listener);\n  }\n\n private:\n  StatusIsMatcherCommonImpl common_impl_;\n};\n\n// Implements StatusIs() as a polymorphic matcher.\nclass StatusIsMatcher {\n public:\n  template <typename StatusCodeMatcher, typename StatusMessageMatcher>\n  StatusIsMatcher(StatusCodeMatcher&& code_matcher,\n                  StatusMessageMatcher&& message_matcher)\n      : common_impl_(::testing::MatcherCast<StatusCode>(\n                         std::forward<StatusCodeMatcher>(code_matcher)),\n                     ::testing::MatcherCast<absl::string_view>(\n                         std::forward<StatusMessageMatcher>(message_matcher))) {\n  }\n\n  // Converts this polymorphic matcher to a monomorphic matcher of the\n  // given type.  T can be StatusOr<>, Status, or a reference to\n  // either of them.\n  template <typename T>\n  /*implicit*/ operator ::testing::Matcher<T>() const {  // NOLINT\n    return ::testing::Matcher<T>(\n        new MonoStatusIsMatcherImpl<const T&>(common_impl_));\n  }\n\n private:\n  const StatusIsMatcherCommonImpl common_impl_;\n};\n\n// Monomorphic implementation of matcher IsOk() for a given type T.\n// T can be Status, StatusOr<>, or a reference to either of them.\ntemplate <typename T>\nclass MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {\n public:\n  void DescribeTo(std::ostream* os) const override { *os << \"is OK\"; }\n  void DescribeNegationTo(std::ostream* os) const override {\n    *os << \"is not OK\";\n  }\n  bool MatchAndExplain(T actual_value,\n                       ::testing::MatchResultListener*) const override {\n    return GetStatus(actual_value).ok();\n  }\n};\n\n// Implements IsOk() as a polymorphic matcher.\nclass IsOkMatcher {\n public:\n  template <typename T>\n  /*implicit*/ operator ::testing::Matcher<T>() const {  // NOLINT\n    return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<const T&>());\n  }\n};\n\n}  // namespace status_internal\nABSL_NAMESPACE_END\n}  // namespace absl_testing\n\n#endif  // ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_\n"
  },
  {
    "path": "absl/status/internal/statusor_internal.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_\n#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_\n\n#include <cstdint>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/status/status.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename T>\nclass ABSL_MUST_USE_RESULT\n    StatusOr;\n\nnamespace internal_statusor {\n\n// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator\n// StatusOr<T>()`.\ntemplate <typename T, typename U, typename = void>\nstruct HasConversionOperatorToStatusOr : std::false_type {};\n\ntemplate <typename T, typename U>\nvoid test(char (*absl_nullable)[sizeof(\n    std::declval<U>().operator absl::StatusOr<T>())]);\n\ntemplate <typename T, typename U>\nstruct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>\n    : std::true_type {};\n\n// Detects whether `T` is equality-comparable.\ntemplate <typename T, typename = void>\nstruct IsEqualityComparable : std::false_type {};\n\ntemplate <typename T>\nstruct IsEqualityComparable<\n    T, std::enable_if_t<std::is_convertible<\n           decltype(std::declval<T>() == std::declval<T>()),\n           bool>::value>> : std::true_type {};\n\n// Detects whether `T` is constructible or convertible from `StatusOr<U>`.\ntemplate <typename T, typename U>\nusing IsConstructibleOrConvertibleFromStatusOr =\n    absl::disjunction<std::is_constructible<T, StatusOr<U>&>,\n                      std::is_constructible<T, const StatusOr<U>&>,\n                      std::is_constructible<T, StatusOr<U>&&>,\n                      std::is_constructible<T, const StatusOr<U>&&>,\n                      std::is_convertible<StatusOr<U>&, T>,\n                      std::is_convertible<const StatusOr<U>&, T>,\n                      std::is_convertible<StatusOr<U>&&, T>,\n                      std::is_convertible<const StatusOr<U>&&, T>>;\n\n// Detects whether `T` is constructible or convertible or assignable from\n// `StatusOr<U>`.\ntemplate <typename T, typename U>\nusing IsConstructibleOrConvertibleOrAssignableFromStatusOr =\n    absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,\n                      std::is_assignable<T&, StatusOr<U>&>,\n                      std::is_assignable<T&, const StatusOr<U>&>,\n                      std::is_assignable<T&, StatusOr<U>&&>,\n                      std::is_assignable<T&, const StatusOr<U>&&>>;\n\n// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.\n// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.\ntemplate <typename T, typename U>\nstruct IsDirectInitializationAmbiguous\n    : public absl::conditional_t<\n          std::is_same<absl::remove_cvref_t<U>, U>::value, std::false_type,\n          IsDirectInitializationAmbiguous<T, absl::remove_cvref_t<U>>> {};\n\ntemplate <typename T, typename V>\nstruct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>\n    : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};\n\n// Checks whether the conversion from U to T can be done without dangling\n// temporaries.\n// REQUIRES: T and U are references.\ntemplate <typename T, typename U>\nusing IsReferenceConversionValid = absl::conjunction<  //\n    std::is_reference<T>, std::is_reference<U>,\n    // The references are convertible. This checks for\n    // lvalue/rvalue compatibility.\n    std::is_convertible<U, T>,\n    // The pointers are convertible. This checks we don't have\n    // a temporary.\n    std::is_convertible<std::remove_reference_t<U>*,\n                        std::remove_reference_t<T>*>>;\n\n// Checks against the constraints of the direction initialization, i.e. when\n// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.\ntemplate <typename T, typename U>\nusing IsDirectInitializationValid = absl::disjunction<\n    // Short circuits if T is basically U.\n    std::is_same<T, absl::remove_cvref_t<U>>,  //\n    std::conditional_t<\n        std::is_reference_v<T>,  //\n        IsReferenceConversionValid<T, U>,\n        absl::negation<absl::disjunction<\n            std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>,\n            std::is_same<absl::Status, absl::remove_cvref_t<U>>,\n            std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>,\n            IsDirectInitializationAmbiguous<T, U>>>>>;\n\n// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which\n// is equivalent to whether all the following conditions are met:\n// 1. `U` is `StatusOr<V>`.\n// 2. `T` is constructible and assignable from `V`.\n// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).\n// For example, the following code is considered ambiguous:\n// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)\n//   StatusOr<bool> s1 = true;  // s1.ok() && s1.ValueOrDie() == true\n//   StatusOr<bool> s2 = false;  // s2.ok() && s2.ValueOrDie() == false\n//   s1 = s2;  // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?\ntemplate <typename T, typename U>\nstruct IsForwardingAssignmentAmbiguous\n    : public absl::conditional_t<\n          std::is_same<absl::remove_cvref_t<U>, U>::value, std::false_type,\n          IsForwardingAssignmentAmbiguous<T, absl::remove_cvref_t<U>>> {};\n\ntemplate <typename T, typename U>\nstruct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>\n    : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};\n\n// Checks against the constraints of the forwarding assignment, i.e. whether\n// `StatusOr<T>::operator(U&&)` should participate in overload resolution.\ntemplate <typename T, typename U>\nusing IsForwardingAssignmentValid = absl::disjunction<\n    // Short circuits if T is basically U.\n    std::is_same<T, absl::remove_cvref_t<U>>,\n    absl::negation<absl::disjunction<\n        std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>,\n        std::is_same<absl::Status, absl::remove_cvref_t<U>>,\n        std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>,\n        IsForwardingAssignmentAmbiguous<T, U>>>>;\n\ntemplate <bool Value, typename T>\nusing Equality = std::conditional_t<Value, T, absl::negation<T>>;\n\ntemplate <bool Explicit, typename T, typename U, bool Lifetimebound>\nusing IsConstructionValid = absl::conjunction<\n    Equality<Lifetimebound,\n             absl::disjunction<\n                 std::is_reference<T>,\n                 type_traits_internal::IsLifetimeBoundAssignment<T, U>>>,\n    IsDirectInitializationValid<T, U&&>, std::is_constructible<T, U&&>,\n    Equality<!Explicit, std::is_convertible<U&&, T>>,\n    absl::disjunction<\n        std::is_same<T, absl::remove_cvref_t<U>>,\n        absl::conjunction<\n            std::conditional_t<\n                Explicit,\n                absl::negation<std::is_constructible<absl::Status, U&&>>,\n                absl::negation<std::is_convertible<U&&, absl::Status>>>,\n            absl::negation<\n                internal_statusor::HasConversionOperatorToStatusOr<T, U&&>>>>>;\n\ntemplate <typename T, typename U, bool Lifetimebound>\nusing IsAssignmentValid = absl::conjunction<\n    Equality<Lifetimebound,\n             absl::disjunction<\n                 std::is_reference<T>,\n                 type_traits_internal::IsLifetimeBoundAssignment<T, U>>>,\n    std::conditional_t<std::is_reference_v<T>,\n                       IsReferenceConversionValid<T, U&&>,\n                       absl::conjunction<std::is_constructible<T, U&&>,\n                                         std::is_assignable<T&, U&&>>>,\n    absl::disjunction<\n        std::is_same<T, absl::remove_cvref_t<U>>,\n        absl::conjunction<\n            absl::negation<std::is_convertible<U&&, absl::Status>>,\n            absl::negation<HasConversionOperatorToStatusOr<T, U&&>>>>,\n    IsForwardingAssignmentValid<T, U&&>>;\n\ntemplate <bool Explicit, typename T, typename U>\nusing IsConstructionFromStatusValid = absl::conjunction<\n    absl::negation<std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>>,\n    absl::negation<std::is_same<T, absl::remove_cvref_t<U>>>,\n    absl::negation<std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>>,\n    Equality<!Explicit, std::is_convertible<U, absl::Status>>,\n    std::is_constructible<absl::Status, U>,\n    absl::negation<HasConversionOperatorToStatusOr<T, U>>>;\n\ntemplate <bool Explicit, typename T, typename U, bool Lifetimebound,\n          typename UQ>\nusing IsConstructionFromStatusOrValid = absl::conjunction<\n    absl::negation<std::is_same<T, U>>,\n    // If `T` is a reference, then U must be a compatible one.\n    absl::disjunction<absl::negation<std::is_reference<T>>,\n                      IsReferenceConversionValid<T, U>>,\n    Equality<Lifetimebound,\n             type_traits_internal::IsLifetimeBoundAssignment<T, U>>,\n    std::is_constructible<T, UQ>,\n    Equality<!Explicit, std::is_convertible<UQ, T>>,\n    absl::negation<IsConstructibleOrConvertibleFromStatusOr<T, U>>>;\n\ntemplate <typename T, typename U, bool Lifetimebound>\nusing IsStatusOrAssignmentValid = absl::conjunction<\n    absl::negation<std::is_same<T, absl::remove_cvref_t<U>>>,\n    Equality<Lifetimebound,\n             type_traits_internal::IsLifetimeBoundAssignment<T, U>>,\n    std::is_constructible<T, U>, std::is_assignable<T, U>,\n    absl::negation<IsConstructibleOrConvertibleOrAssignableFromStatusOr<\n        T, absl::remove_cvref_t<U>>>>;\n\ntemplate <typename T, typename U, bool Lifetimebound>\nusing IsValueOrValid = absl::conjunction<\n    // If `T` is a reference, then U must be a compatible one.\n    absl::disjunction<absl::negation<std::is_reference<T>>,\n                      IsReferenceConversionValid<T, U>>,\n    Equality<Lifetimebound,\n             absl::disjunction<\n                 std::is_reference<T>,\n                 type_traits_internal::IsLifetimeBoundAssignment<T, U>>>>;\n\nclass Helper {\n public:\n  // Move type-agnostic error handling to the .cc.\n  static void HandleInvalidStatusCtorArg(Status* absl_nonnull);\n  [[noreturn]] static void Crash(const absl::Status& status);\n};\n\n// Construct an instance of T in `p` through placement new, passing Args... to\n// the constructor.\n// This abstraction is here mostly for the gcc performance fix.\ntemplate <typename T, typename... Args>\nABSL_ATTRIBUTE_NONNULL(1)\nvoid PlacementNew(void* absl_nonnull p, Args&&... args) {\n  new (p) T(std::forward<Args>(args)...);\n}\n\ntemplate <typename T>\nclass Reference {\n public:\n  constexpr explicit Reference(T ref ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : payload_(std::addressof(ref)) {}\n\n  Reference(const Reference&) = default;\n  Reference& operator=(const Reference&) = default;\n  Reference& operator=(T value) {\n    payload_ = std::addressof(value);\n    return *this;\n  }\n\n  operator T() const { return static_cast<T>(*payload_); }  // NOLINT\n  T get() const { return *this; }\n\n private:\n  std::remove_reference_t<T>* absl_nonnull payload_;\n};\n\n// Helper base class to hold the data and all operations.\n// We move all this to a base class to allow mixing with the appropriate\n// TraitsBase specialization.\ntemplate <typename T>\nclass StatusOrData {\n  template <typename U>\n  friend class StatusOrData;\n\n  decltype(auto) MaybeMoveData() {\n    if constexpr (std::is_reference_v<T>) {\n      return data_.get();\n    } else {\n      return std::move(data_);\n    }\n  }\n\n public:\n  StatusOrData() = delete;\n\n  StatusOrData(const StatusOrData& other) {\n    if (other.ok()) {\n      MakeValue(other.data_);\n      MakeStatus();\n    } else {\n      MakeStatus(other.status_);\n    }\n  }\n\n  StatusOrData(StatusOrData&& other) noexcept {\n    if (other.ok()) {\n      MakeValue(other.MaybeMoveData());\n      MakeStatus();\n    } else {\n      MakeStatus(std::move(other.status_));\n    }\n  }\n\n  template <typename U>\n  explicit StatusOrData(const StatusOrData<U>& other) {\n    if (other.ok()) {\n      MakeValue(other.data_);\n      MakeStatus();\n    } else {\n      MakeStatus(other.status_);\n    }\n  }\n\n  template <typename U>\n  explicit StatusOrData(StatusOrData<U>&& other) {\n    if (other.ok()) {\n      MakeValue(other.MaybeMoveData());\n      MakeStatus();\n    } else {\n      MakeStatus(std::move(other.status_));\n    }\n  }\n\n  template <typename... Args>\n  explicit StatusOrData(absl::in_place_t, Args&&... args)\n      : data_(std::forward<Args>(args)...) {\n    MakeStatus();\n  }\n\n  template <typename U,\n            absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,\n                              int> = 0>\n  explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {\n    EnsureNotOk();\n  }\n\n  StatusOrData& operator=(const StatusOrData& other) {\n    if (this == &other) return *this;\n    if (other.ok())\n      Assign(other.data_);\n    else\n      AssignStatus(other.status_);\n    return *this;\n  }\n\n  StatusOrData& operator=(StatusOrData&& other) {\n    if (this == &other) return *this;\n    if (other.ok())\n      Assign(other.MaybeMoveData());\n    else\n      AssignStatus(std::move(other.status_));\n    return *this;\n  }\n\n  ~StatusOrData() {\n    if (ok()) {\n      status_.~Status();\n      if constexpr (!std::is_trivially_destructible_v<T>) {\n        data_.~T();\n      }\n    } else {\n      status_.~Status();\n    }\n  }\n\n  template <typename U>\n  void Assign(U&& value) {\n    if (ok()) {\n      data_ = std::forward<U>(value);\n    } else {\n      MakeValue(std::forward<U>(value));\n      status_ = OkStatus();\n    }\n  }\n\n  template <typename U>\n  void AssignStatus(U&& v) {\n    Clear();\n    status_ = static_cast<absl::Status>(std::forward<U>(v));\n    EnsureNotOk();\n  }\n\n  bool ok() const { return status_.ok(); }\n\n protected:\n  // status_ will always be active after the constructor.\n  // We make it a union to be able to initialize exactly how we need without\n  // waste.\n  // Eg. in the copy constructor we use the default constructor of Status in\n  // the ok() path to avoid an extra Ref call.\n  union {\n    Status status_;\n  };\n\n  // data_ is active iff status_.ok()==true\n  struct Dummy {};\n  union {\n    // When T is const, we need some non-const object we can cast to void* for\n    // the placement new. dummy_ is that object.\n    Dummy dummy_;\n    std::conditional_t<std::is_reference_v<T>, Reference<T>, T> data_;\n  };\n\n  void Clear() {\n    if constexpr (!std::is_trivially_destructible_v<T>) {\n      if (ok()) data_.~T();\n    }\n  }\n\n  void EnsureOk() const {\n    if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);\n  }\n\n  void EnsureNotOk() {\n    if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);\n  }\n\n  // Construct the value (ie. data_) through placement new with the passed\n  // argument.\n  template <typename... Arg>\n  void MakeValue(Arg&&... arg) {\n    internal_statusor::PlacementNew<decltype(data_)>(&dummy_,\n                                                     std::forward<Arg>(arg)...);\n  }\n\n  // Construct the status (ie. status_) through placement new with the passed\n  // argument.\n  template <typename... Args>\n  void MakeStatus(Args&&... args) {\n    internal_statusor::PlacementNew<Status>(&status_,\n                                            std::forward<Args>(args)...);\n  }\n\n  template <typename U>\n  T ValueOrImpl(U&& default_value) const& {\n    if (ok()) {\n      return data_;\n    }\n    return std::forward<U>(default_value);\n  }\n\n  template <typename U>\n  T ValueOrImpl(U&& default_value) && {\n    if (ok()) {\n      return std::move(data_);\n    }\n    return std::forward<U>(default_value);\n  }\n};\n\n[[noreturn]] void ThrowBadStatusOrAccess(absl::Status status);\n\ntemplate <typename T>\nstruct OperatorBase {\n  auto& self() const { return static_cast<const StatusOr<T>&>(*this); }\n  auto& self() { return static_cast<StatusOr<T>&>(*this); }\n\n  const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    self().EnsureOk();\n    return self().data_;\n  }\n  T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    self().EnsureOk();\n    return self().data_;\n  }\n  const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    self().EnsureOk();\n    return std::move(self().data_);\n  }\n  T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    self().EnsureOk();\n    return std::move(self().data_);\n  }\n\n  const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!self().ok()) internal_statusor::ThrowBadStatusOrAccess(self().status_);\n    return self().data_;\n  }\n  T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!self().ok()) internal_statusor::ThrowBadStatusOrAccess(self().status_);\n    return self().data_;\n  }\n  const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!self().ok()) {\n      internal_statusor::ThrowBadStatusOrAccess(std::move(self().status_));\n    }\n    return std::move(self().data_);\n  }\n  T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (!self().ok()) {\n      internal_statusor::ThrowBadStatusOrAccess(std::move(self().status_));\n    }\n    return std::move(self().data_);\n  }\n\n  const T* absl_nonnull operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return std::addressof(**this);\n  }\n  T* absl_nonnull operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return std::addressof(**this);\n  }\n};\n\ntemplate <typename T>\nstruct OperatorBase<T&> {\n  auto& self() const { return static_cast<const StatusOr<T&>&>(*this); }\n\n  T& operator*() const {\n    self().EnsureOk();\n    return self().data_;\n  }\n\n  T& value() const {\n    if (!self().ok()) internal_statusor::ThrowBadStatusOrAccess(self().status_);\n    return self().data_;\n  }\n\n  T* absl_nonnull operator->() const {\n    return std::addressof(**this);\n  }\n};\n\n// Helper base classes to allow implicitly deleted constructors and assignment\n// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete\n// the copy constructor when T is not copy constructible and `StatusOr` will\n// inherit that behavior implicitly.\ntemplate <typename T, bool = std::is_copy_constructible<T>::value>\nstruct CopyCtorBase {\n  CopyCtorBase() = default;\n  CopyCtorBase(const CopyCtorBase&) = default;\n  CopyCtorBase(CopyCtorBase&&) = default;\n  CopyCtorBase& operator=(const CopyCtorBase&) = default;\n  CopyCtorBase& operator=(CopyCtorBase&&) = default;\n};\n\ntemplate <typename T>\nstruct CopyCtorBase<T, false> {\n  CopyCtorBase() = default;\n  CopyCtorBase(const CopyCtorBase&) = delete;\n  CopyCtorBase(CopyCtorBase&&) = default;\n  CopyCtorBase& operator=(const CopyCtorBase&) = default;\n  CopyCtorBase& operator=(CopyCtorBase&&) = default;\n};\n\ntemplate <typename T, bool = std::is_move_constructible<T>::value>\nstruct MoveCtorBase {\n  MoveCtorBase() = default;\n  MoveCtorBase(const MoveCtorBase&) = default;\n  MoveCtorBase(MoveCtorBase&&) = default;\n  MoveCtorBase& operator=(const MoveCtorBase&) = default;\n  MoveCtorBase& operator=(MoveCtorBase&&) = default;\n};\n\ntemplate <typename T>\nstruct MoveCtorBase<T, false> {\n  MoveCtorBase() = default;\n  MoveCtorBase(const MoveCtorBase&) = default;\n  MoveCtorBase(MoveCtorBase&&) = delete;\n  MoveCtorBase& operator=(const MoveCtorBase&) = default;\n  MoveCtorBase& operator=(MoveCtorBase&&) = default;\n};\n\ntemplate <typename T, bool = (std::is_copy_constructible<T>::value &&\n                              std::is_copy_assignable<T>::value) ||\n                             std::is_reference_v<T>>\nstruct CopyAssignBase {\n  CopyAssignBase() = default;\n  CopyAssignBase(const CopyAssignBase&) = default;\n  CopyAssignBase(CopyAssignBase&&) = default;\n  CopyAssignBase& operator=(const CopyAssignBase&) = default;\n  CopyAssignBase& operator=(CopyAssignBase&&) = default;\n};\n\ntemplate <typename T>\nstruct CopyAssignBase<T, false> {\n  CopyAssignBase() = default;\n  CopyAssignBase(const CopyAssignBase&) = default;\n  CopyAssignBase(CopyAssignBase&&) = default;\n  CopyAssignBase& operator=(const CopyAssignBase&) = delete;\n  CopyAssignBase& operator=(CopyAssignBase&&) = default;\n};\n\ntemplate <typename T, bool = (std::is_move_constructible<T>::value &&\n                              std::is_move_assignable<T>::value) ||\n                             std::is_reference_v<T>>\nstruct MoveAssignBase {\n  MoveAssignBase() = default;\n  MoveAssignBase(const MoveAssignBase&) = default;\n  MoveAssignBase(MoveAssignBase&&) = default;\n  MoveAssignBase& operator=(const MoveAssignBase&) = default;\n  MoveAssignBase& operator=(MoveAssignBase&&) = default;\n};\n\ntemplate <typename T>\nstruct MoveAssignBase<T, false> {\n  MoveAssignBase() = default;\n  MoveAssignBase(const MoveAssignBase&) = default;\n  MoveAssignBase(MoveAssignBase&&) = default;\n  MoveAssignBase& operator=(const MoveAssignBase&) = default;\n  MoveAssignBase& operator=(MoveAssignBase&&) = delete;\n};\n\n// Used to introduce jitter into the output of printing functions for\n// `StatusOr` (i.e. `AbslStringify` and `operator<<`).\nclass StringifyRandom {\n  enum BracesType {\n    kBareParens = 0,\n    kSpaceParens,\n    kBareBrackets,\n    kSpaceBrackets,\n  };\n\n  // Returns a random `BracesType` determined once per binary load.\n  static BracesType RandomBraces() {\n    static const BracesType kRandomBraces = static_cast<BracesType>(\n        (reinterpret_cast<uintptr_t>(&kRandomBraces) >> 4) % 4);\n    return kRandomBraces;\n  }\n\n public:\n  static inline absl::string_view OpenBrackets() {\n    switch (RandomBraces()) {\n      case kBareParens:\n        return \"(\";\n      case kSpaceParens:\n        return \"( \";\n      case kBareBrackets:\n        return \"[\";\n      case kSpaceBrackets:\n        return \"[ \";\n    }\n    return \"(\";\n  }\n\n  static inline absl::string_view CloseBrackets() {\n    switch (RandomBraces()) {\n      case kBareParens:\n        return \")\";\n      case kSpaceParens:\n        return \" )\";\n      case kBareBrackets:\n        return \"]\";\n      case kSpaceBrackets:\n        return \" ]\";\n    }\n    return \")\";\n  }\n};\n\n}  // namespace internal_statusor\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_\n"
  },
  {
    "path": "absl/status/status.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/status/status.h\"\n\n#include <errno.h>\n\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <memory>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/strerror.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/symbolize.h\"\n#include \"absl/status/internal/status_internal.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/source_location.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nstatic_assert(\n    alignof(status_internal::StatusRep) >= 4,\n    \"absl::Status assumes it can use the bottom 2 bits of a StatusRep*.\");\n\nstd::string StatusCodeToString(StatusCode code) {\n  return std::string(absl::StatusCodeToStringView(code));\n}\n\nabsl::string_view StatusCodeToStringView(StatusCode code) {\n  switch (code) {\n    case StatusCode::kOk:\n      return \"OK\";\n    case StatusCode::kCancelled:\n      return \"CANCELLED\";\n    case StatusCode::kUnknown:\n      return \"UNKNOWN\";\n    case StatusCode::kInvalidArgument:\n      return \"INVALID_ARGUMENT\";\n    case StatusCode::kDeadlineExceeded:\n      return \"DEADLINE_EXCEEDED\";\n    case StatusCode::kNotFound:\n      return \"NOT_FOUND\";\n    case StatusCode::kAlreadyExists:\n      return \"ALREADY_EXISTS\";\n    case StatusCode::kPermissionDenied:\n      return \"PERMISSION_DENIED\";\n    case StatusCode::kUnauthenticated:\n      return \"UNAUTHENTICATED\";\n    case StatusCode::kResourceExhausted:\n      return \"RESOURCE_EXHAUSTED\";\n    case StatusCode::kFailedPrecondition:\n      return \"FAILED_PRECONDITION\";\n    case StatusCode::kAborted:\n      return \"ABORTED\";\n    case StatusCode::kOutOfRange:\n      return \"OUT_OF_RANGE\";\n    case StatusCode::kUnimplemented:\n      return \"UNIMPLEMENTED\";\n    case StatusCode::kInternal:\n      return \"INTERNAL\";\n    case StatusCode::kUnavailable:\n      return \"UNAVAILABLE\";\n    case StatusCode::kDataLoss:\n      return \"DATA_LOSS\";\n    default:\n      return \"\";\n  }\n}\n\nstd::ostream& operator<<(std::ostream& os, StatusCode code) {\n  return os << StatusCodeToString(code);\n}\n\nconst std::string* absl_nonnull Status::EmptyString() {\n  static const absl::NoDestructor<std::string> kEmpty;\n  return kEmpty.get();\n}\n\nconst std::string* absl_nonnull Status::MovedFromString() {\n  static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString);\n  return kMovedFrom.get();\n}\n\nuintptr_t Status::MakeRep(uintptr_t inlined_rep, absl::string_view msg,\n                          absl::SourceLocation loc) {\n  bool ok = inlined_rep == CodeToInlinedRep(absl::StatusCode::kOk);\n  if (ok) return inlined_rep;\n  if (msg.empty()\n  ) {\n    return inlined_rep;\n  }\n  auto* rep = new status_internal::StatusRep(InlinedRepToCode(inlined_rep), msg,\n                                             nullptr);\n  if (loc.file_name()[0] != '\\0') {\n    rep->AddSourceLocation(loc);\n  }\n  return PointerToRep(rep);\n}\n\nuintptr_t Status::AddSourceLocationImpl(uintptr_t rep,\n                                        absl::SourceLocation loc) {\n  if (IsInlined(rep)) return rep;\n  if (loc.file_name()[0] == '\\0') return rep;\n  status_internal::StatusRep* rep_ptr = PrepareToModify(rep);\n  rep_ptr->AddSourceLocation(loc);\n  return PointerToRep(rep_ptr);\n}\n\nstatus_internal::StatusRep* absl_nonnull Status::PrepareToModify(\n    uintptr_t rep) {\n  if (IsInlined(rep)) {\n    return new status_internal::StatusRep(InlinedRepToCode(rep),\n                                          absl::string_view(), nullptr);\n  }\n  return RepToPointer(rep)->CloneAndUnref();\n}\n\nstd::string Status::ToStringSlow(uintptr_t rep, StatusToStringMode mode) {\n  if (IsInlined(rep)) {\n    return absl::StrCat(absl::StatusCodeToString(InlinedRepToCode(rep)), \": \");\n  }\n  return RepToPointer(rep)->ToString(mode);\n}\n\nstd::ostream& operator<<(std::ostream& os, const Status& x) {\n  os << x.ToString(StatusToStringMode::kWithEverything);\n  return os;\n}\n\nStatus AbortedError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kAborted, message, loc);\n}\n\nStatus AlreadyExistsError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kAlreadyExists, message, loc);\n}\n\nStatus CancelledError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kCancelled, message, loc);\n}\n\nStatus DataLossError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kDataLoss, message, loc);\n}\n\nStatus DeadlineExceededError(absl::string_view message,\n                             absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kDeadlineExceeded, message, loc);\n}\n\nStatus FailedPreconditionError(absl::string_view message,\n                               absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kFailedPrecondition, message, loc);\n}\n\nStatus InternalError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kInternal, message, loc);\n}\n\nStatus InvalidArgumentError(absl::string_view message,\n                            absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kInvalidArgument, message, loc);\n}\n\nStatus NotFoundError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kNotFound, message, loc);\n}\n\nStatus OutOfRangeError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kOutOfRange, message, loc);\n}\n\nStatus PermissionDeniedError(absl::string_view message,\n                             absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kPermissionDenied, message, loc);\n}\n\nStatus ResourceExhaustedError(absl::string_view message,\n                              absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kResourceExhausted, message, loc);\n}\n\nStatus UnauthenticatedError(absl::string_view message,\n                            absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kUnauthenticated, message, loc);\n}\n\nStatus UnavailableError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kUnavailable, message, loc);\n}\n\nStatus UnimplementedError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kUnimplemented, message, loc);\n}\n\nStatus UnknownError(absl::string_view message, absl::SourceLocation loc) {\n  return Status(absl::StatusCode::kUnknown, message, loc);\n}\n\nbool IsAborted(const Status& status) {\n  return status.code() == absl::StatusCode::kAborted;\n}\n\nbool IsAlreadyExists(const Status& status) {\n  return status.code() == absl::StatusCode::kAlreadyExists;\n}\n\nbool IsCancelled(const Status& status) {\n  return status.code() == absl::StatusCode::kCancelled;\n}\n\nbool IsDataLoss(const Status& status) {\n  return status.code() == absl::StatusCode::kDataLoss;\n}\n\nbool IsDeadlineExceeded(const Status& status) {\n  return status.code() == absl::StatusCode::kDeadlineExceeded;\n}\n\nbool IsFailedPrecondition(const Status& status) {\n  return status.code() == absl::StatusCode::kFailedPrecondition;\n}\n\nbool IsInternal(const Status& status) {\n  return status.code() == absl::StatusCode::kInternal;\n}\n\nbool IsInvalidArgument(const Status& status) {\n  return status.code() == absl::StatusCode::kInvalidArgument;\n}\n\nbool IsNotFound(const Status& status) {\n  return status.code() == absl::StatusCode::kNotFound;\n}\n\nbool IsOutOfRange(const Status& status) {\n  return status.code() == absl::StatusCode::kOutOfRange;\n}\n\nbool IsPermissionDenied(const Status& status) {\n  return status.code() == absl::StatusCode::kPermissionDenied;\n}\n\nbool IsResourceExhausted(const Status& status) {\n  return status.code() == absl::StatusCode::kResourceExhausted;\n}\n\nbool IsUnauthenticated(const Status& status) {\n  return status.code() == absl::StatusCode::kUnauthenticated;\n}\n\nbool IsUnavailable(const Status& status) {\n  return status.code() == absl::StatusCode::kUnavailable;\n}\n\nbool IsUnimplemented(const Status& status) {\n  return status.code() == absl::StatusCode::kUnimplemented;\n}\n\nbool IsUnknown(const Status& status) {\n  return status.code() == absl::StatusCode::kUnknown;\n}\n\nStatusCode ErrnoToStatusCode(int error_number) {\n  switch (error_number) {\n    case 0:\n      return StatusCode::kOk;\n    case EINVAL:        // Invalid argument\n    case ENAMETOOLONG:  // Filename too long\n    case E2BIG:         // Argument list too long\n    case EDESTADDRREQ:  // Destination address required\n    case EDOM:          // Mathematics argument out of domain of function\n    case EFAULT:        // Bad address\n    case EILSEQ:        // Illegal byte sequence\n    case ENOPROTOOPT:   // Protocol not available\n    case ENOTSOCK:      // Not a socket\n    case ENOTTY:        // Inappropriate I/O control operation\n    case EPROTOTYPE:    // Protocol wrong type for socket\n    case ESPIPE:        // Invalid seek\n      return StatusCode::kInvalidArgument;\n    case ETIMEDOUT:  // Connection timed out\n      return StatusCode::kDeadlineExceeded;\n    case ENODEV:  // No such device\n    case ENOENT:  // No such file or directory\n#ifdef ENOMEDIUM\n    case ENOMEDIUM:  // No medium found\n#endif\n    case ENXIO:  // No such device or address\n    case ESRCH:  // No such process\n      return StatusCode::kNotFound;\n    case EEXIST:         // File exists\n    case EADDRNOTAVAIL:  // Address not available\n    case EALREADY:       // Connection already in progress\n#ifdef ENOTUNIQ\n    case ENOTUNIQ:  // Name not unique on network\n#endif\n      return StatusCode::kAlreadyExists;\n    case EPERM:   // Operation not permitted\n    case EACCES:  // Permission denied\n#ifdef ENOKEY\n    case ENOKEY:  // Required key not available\n#endif\n    case EROFS:  // Read only file system\n      return StatusCode::kPermissionDenied;\n    case ENOTEMPTY:   // Directory not empty\n    case EISDIR:      // Is a directory\n    case ENOTDIR:     // Not a directory\n    case EADDRINUSE:  // Address already in use\n    case EBADF:       // Invalid file descriptor\n#ifdef EBADFD\n    case EBADFD:  // File descriptor in bad state\n#endif\n    case EBUSY:    // Device or resource busy\n    case ECHILD:   // No child processes\n    case EISCONN:  // Socket is connected\n#ifdef EISNAM\n    case EISNAM:  // Is a named type file\n#endif\n#ifdef ENOTBLK\n    case ENOTBLK:  // Block device required\n#endif\n    case ENOTCONN:  // The socket is not connected\n    case EPIPE:     // Broken pipe\n#ifdef ESHUTDOWN\n    case ESHUTDOWN:  // Cannot send after transport endpoint shutdown\n#endif\n    case ETXTBSY:  // Text file busy\n#ifdef EUNATCH\n    case EUNATCH:  // Protocol driver not attached\n#endif\n      return StatusCode::kFailedPrecondition;\n    case ENOSPC:  // No space left on device\n#ifdef EDQUOT\n    case EDQUOT:  // Disk quota exceeded\n#endif\n    case EMFILE:   // Too many open files\n    case EMLINK:   // Too many links\n    case ENFILE:   // Too many open files in system\n    case ENOBUFS:  // No buffer space available\n    case ENOMEM:   // Not enough space\n#ifdef EUSERS\n    case EUSERS:  // Too many users\n#endif\n      return StatusCode::kResourceExhausted;\n#ifdef ECHRNG\n    case ECHRNG:  // Channel number out of range\n#endif\n    case EFBIG:      // File too large\n    case EOVERFLOW:  // Value too large to be stored in data type\n    case ERANGE:     // Result too large\n      return StatusCode::kOutOfRange;\n#ifdef ENOPKG\n    case ENOPKG:  // Package not installed\n#endif\n    case ENOSYS:        // Function not implemented\n    case ENOTSUP:       // Operation not supported\n    case EAFNOSUPPORT:  // Address family not supported\n#ifdef EPFNOSUPPORT\n    case EPFNOSUPPORT:  // Protocol family not supported\n#endif\n    case EPROTONOSUPPORT:  // Protocol not supported\n#ifdef ESOCKTNOSUPPORT\n    case ESOCKTNOSUPPORT:  // Socket type not supported\n#endif\n    case EXDEV:  // Improper link\n      return StatusCode::kUnimplemented;\n    case EAGAIN:  // Resource temporarily unavailable\n#ifdef ECOMM\n    case ECOMM:  // Communication error on send\n#endif\n    case ECONNREFUSED:  // Connection refused\n    case ECONNABORTED:  // Connection aborted\n    case ECONNRESET:    // Connection reset\n    case EINTR:         // Interrupted function call\n#ifdef EHOSTDOWN\n    case EHOSTDOWN:  // Host is down\n#endif\n    case EHOSTUNREACH:  // Host is unreachable\n    case ENETDOWN:      // Network is down\n    case ENETRESET:     // Connection aborted by network\n    case ENETUNREACH:   // Network unreachable\n    case ENOLCK:        // No locks available\n    case ENOLINK:       // Link has been severed\n#ifdef ENONET\n    case ENONET:  // Machine is not on the network\n#endif\n      return StatusCode::kUnavailable;\n    case EDEADLK:  // Resource deadlock avoided\n#ifdef ESTALE\n    case ESTALE:  // Stale file handle\n#endif\n      return StatusCode::kAborted;\n    case ECANCELED:  // Operation cancelled\n      return StatusCode::kCancelled;\n    default:\n      return StatusCode::kUnknown;\n  }\n}\n\nnamespace {\nstd::string MessageForErrnoToStatus(int error_number,\n                                    absl::string_view message) {\n  return absl::StrCat(message, \": \",\n                      absl::base_internal::StrError(error_number));\n}\n}  // namespace\n\nStatus ErrnoToStatus(int error_number, absl::string_view message,\n                     absl::SourceLocation loc) {\n  return Status(ErrnoToStatusCode(error_number),\n                MessageForErrnoToStatus(error_number, message), loc);\n}\n\nconst char* absl_nonnull StatusMessageAsCStr(const Status& status) {\n  // As an internal implementation detail, we guarantee that if status.message()\n  // is non-empty, then the resulting string_view is null terminated.\n  auto sv_message = status.message();\n  return sv_message.empty() ? \"\" : sv_message.data();\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/status/status.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: status.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the Abseil `status` library, consisting of:\n//\n//   * An `absl::Status` class for holding error handling information\n//   * A set of canonical `absl::StatusCode` error codes, and associated\n//     utilities for generating and propagating status codes.\n//   * A set of helper functions for creating status codes and checking their\n//     values\n//\n// Within Google, `absl::Status` is the primary mechanism for communicating\n// errors in C++, and is used to represent error state in both in-process\n// library calls as well as RPC calls. Some of these errors may be recoverable,\n// but others may not. Most functions that can produce a recoverable error\n// should be designed to return an `absl::Status` (or `absl::StatusOr`).\n//\n// Example:\n//\n// absl::Status myFunction(absl::string_view fname, ...) {\n//   ...\n//   // encounter error\n//   if (error condition) {\n//     return absl::InvalidArgumentError(\"bad mode\");\n//   }\n//   // else, return OK\n//   return absl::OkStatus();\n// }\n//\n// An `absl::Status` is designed to either return \"OK\" or one of a number of\n// different error codes, corresponding to typical error conditions.\n// In almost all cases, when using `absl::Status` you should use the canonical\n// error codes (of type `absl::StatusCode`) enumerated in this header file.\n// These canonical codes are understood across the codebase and will be\n// accepted across all API and RPC boundaries.\n#ifndef ABSL_STATUS_STATUS_H_\n#define ABSL_STATUS_STATUS_H_\n\n#include <cassert>\n#include <cstdint>\n#include <optional>\n#include <ostream>\n#include <string>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/status/internal/status_internal.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// absl::StatusCode\n//\n// An `absl::StatusCode` is an enumerated type indicating either no error (\"OK\")\n// or an error condition. In most cases, an `absl::Status` indicates a\n// recoverable error, and the purpose of signalling an error is to indicate what\n// action to take in response to that error. These error codes map to the proto\n// RPC error codes indicated in https://cloud.google.com/apis/design/errors.\n//\n// The errors listed below are the canonical errors associated with\n// `absl::Status` and are used throughout the codebase. As a result, these\n// error codes are somewhat generic.\n//\n// In general, try to return the most specific error that applies if more than\n// one error may pertain. For example, prefer `kOutOfRange` over\n// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or\n// `kAlreadyExists` over `kFailedPrecondition`.\n//\n// Because these errors may cross RPC boundaries, these codes are tied to the\n// `google.rpc.Code` definitions within\n// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto\n// The string value of these RPC codes is denoted within each enum below.\n//\n// If your error handling code requires more context, you can attach payloads\n// to your status. See `absl::Status::SetPayload()` and\n// `absl::Status::GetPayload()` below.\nenum class StatusCode : int {\n  // StatusCode::kOk\n  //\n  // kOK (gRPC code \"OK\") does not indicate an error; this value is returned on\n  // success. It is typical to check for this value before proceeding on any\n  // given call across an API or RPC boundary. To check this value, use the\n  // `absl::Status::ok()` member function rather than inspecting the raw code.\n  kOk = 0,\n\n  // StatusCode::kCancelled\n  //\n  // kCancelled (gRPC code \"CANCELLED\") indicates the operation was cancelled,\n  // typically by the caller.\n  kCancelled = 1,\n\n  // StatusCode::kUnknown\n  //\n  // kUnknown (gRPC code \"UNKNOWN\") indicates an unknown error occurred. In\n  // general, more specific errors should be raised, if possible. Errors raised\n  // by APIs that do not return enough error information may be converted to\n  // this error.\n  kUnknown = 2,\n\n  // StatusCode::kInvalidArgument\n  //\n  // kInvalidArgument (gRPC code \"INVALID_ARGUMENT\") indicates the caller\n  // specified an invalid argument, such as a malformed filename. Note that use\n  // of such errors should be narrowly limited to indicate the invalid nature of\n  // the arguments themselves. Errors with validly formed arguments that may\n  // cause errors with the state of the receiving system should be denoted with\n  // `kFailedPrecondition` instead.\n  kInvalidArgument = 3,\n\n  // StatusCode::kDeadlineExceeded\n  //\n  // kDeadlineExceeded (gRPC code \"DEADLINE_EXCEEDED\") indicates a deadline\n  // expired before the operation could complete. For operations that may change\n  // state within a system, this error may be returned even if the operation has\n  // completed successfully. For example, a successful response from a server\n  // could have been delayed long enough for the deadline to expire.\n  kDeadlineExceeded = 4,\n\n  // StatusCode::kNotFound\n  //\n  // kNotFound (gRPC code \"NOT_FOUND\") indicates some requested entity (such as\n  // a file or directory) was not found.\n  //\n  // `kNotFound` is useful if a request should be denied for an entire class of\n  // users, such as during a gradual feature rollout or undocumented allow list.\n  // If a request should be denied for specific sets of users, such as through\n  // user-based access control, use `kPermissionDenied` instead.\n  kNotFound = 5,\n\n  // StatusCode::kAlreadyExists\n  //\n  // kAlreadyExists (gRPC code \"ALREADY_EXISTS\") indicates that the entity a\n  // caller attempted to create (such as a file or directory) is already\n  // present.\n  kAlreadyExists = 6,\n\n  // StatusCode::kPermissionDenied\n  //\n  // kPermissionDenied (gRPC code \"PERMISSION_DENIED\") indicates that the caller\n  // does not have permission to execute the specified operation. Note that this\n  // error is different than an error due to an *un*authenticated user. This\n  // error code does not imply the request is valid or the requested entity\n  // exists or satisfies any other pre-conditions.\n  //\n  // `kPermissionDenied` must not be used for rejections caused by exhausting\n  // some resource. Instead, use `kResourceExhausted` for those errors.\n  // `kPermissionDenied` must not be used if the caller cannot be identified.\n  // Instead, use `kUnauthenticated` for those errors.\n  kPermissionDenied = 7,\n\n  // StatusCode::kResourceExhausted\n  //\n  // kResourceExhausted (gRPC code \"RESOURCE_EXHAUSTED\") indicates some resource\n  // has been exhausted, perhaps a per-user quota, or perhaps the entire file\n  // system is out of space.\n  kResourceExhausted = 8,\n\n  // StatusCode::kFailedPrecondition\n  //\n  // kFailedPrecondition (gRPC code \"FAILED_PRECONDITION\") indicates that the\n  // operation was rejected because the system is not in a state required for\n  // the operation's execution. For example, a directory to be deleted may be\n  // non-empty, an \"rmdir\" operation is applied to a non-directory, etc.\n  //\n  // Some guidelines that may help a service implementer in deciding between\n  // `kFailedPrecondition`, `kAborted`, and `kUnavailable`:\n  //\n  //  (a) Use `kUnavailable` if the client can retry just the failing call.\n  //  (b) Use `kAborted` if the client should retry at a higher transaction\n  //      level (such as when a client-specified test-and-set fails, indicating\n  //      the client should restart a read-modify-write sequence).\n  //  (c) Use `kFailedPrecondition` if the client should not retry until\n  //      the system state has been explicitly fixed. For example, if a \"rmdir\"\n  //      fails because the directory is non-empty, `kFailedPrecondition`\n  //      should be returned since the client should not retry unless\n  //      the files are deleted from the directory.\n  kFailedPrecondition = 9,\n\n  // StatusCode::kAborted\n  //\n  // kAborted (gRPC code \"ABORTED\") indicates the operation was aborted,\n  // typically due to a concurrency issue such as a sequencer check failure or a\n  // failed transaction.\n  //\n  // See the guidelines above for deciding between `kFailedPrecondition`,\n  // `kAborted`, and `kUnavailable`.\n  kAborted = 10,\n\n  // StatusCode::kOutOfRange\n  //\n  // kOutOfRange (gRPC code \"OUT_OF_RANGE\") indicates the operation was\n  // attempted past the valid range, such as seeking or reading past an\n  // end-of-file.\n  //\n  // Unlike `kInvalidArgument`, this error indicates a problem that may\n  // be fixed if the system state changes. For example, a 32-bit file\n  // system will generate `kInvalidArgument` if asked to read at an\n  // offset that is not in the range [0,2^32-1], but it will generate\n  // `kOutOfRange` if asked to read from an offset past the current\n  // file size.\n  //\n  // There is a fair bit of overlap between `kFailedPrecondition` and\n  // `kOutOfRange`.  We recommend using `kOutOfRange` (the more specific\n  // error) when it applies so that callers who are iterating through\n  // a space can easily look for an `kOutOfRange` error to detect when\n  // they are done.\n  kOutOfRange = 11,\n\n  // StatusCode::kUnimplemented\n  //\n  // kUnimplemented (gRPC code \"UNIMPLEMENTED\") indicates the operation is not\n  // implemented or supported in this service. In this case, the operation\n  // should not be re-attempted.\n  kUnimplemented = 12,\n\n  // StatusCode::kInternal\n  //\n  // kInternal (gRPC code \"INTERNAL\") indicates an internal error has occurred\n  // and some invariants expected by the underlying system have not been\n  // satisfied. This error code is reserved for serious errors.\n  kInternal = 13,\n\n  // StatusCode::kUnavailable\n  //\n  // kUnavailable (gRPC code \"UNAVAILABLE\") indicates the service is currently\n  // unavailable and that this is most likely a transient condition. An error\n  // such as this can be corrected by retrying with a backoff scheme. Note that\n  // it is not always safe to retry non-idempotent operations.\n  //\n  // See the guidelines above for deciding between `kFailedPrecondition`,\n  // `kAborted`, and `kUnavailable`.\n  kUnavailable = 14,\n\n  // StatusCode::kDataLoss\n  //\n  // kDataLoss (gRPC code \"DATA_LOSS\") indicates that unrecoverable data loss or\n  // corruption has occurred. As this error is serious, proper alerting should\n  // be attached to errors such as this.\n  kDataLoss = 15,\n\n  // StatusCode::kUnauthenticated\n  //\n  // kUnauthenticated (gRPC code \"UNAUTHENTICATED\") indicates that the request\n  // does not have valid authentication credentials for the operation. Correct\n  // the authentication and try again.\n  kUnauthenticated = 16,\n\n  // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_\n  //\n  // NOTE: this error code entry should not be used and you should not rely on\n  // its value, which may change.\n  //\n  // The purpose of this enumerated value is to force people who handle status\n  // codes with `switch()` statements to *not* simply enumerate all possible\n  // values, but instead provide a \"default:\" case. Providing such a default\n  // case ensures that code will compile when new codes are added.\n  kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20\n};\n\n// StatusCodeToString()\n//\n// Returns the name for the status code, or \"\" if it is an unknown value.\nstd::string StatusCodeToString(StatusCode code);\n\n// StatusCodeToStringView()\n//\n// Same as StatusCodeToString(), but returns a string_view.\nabsl::string_view StatusCodeToStringView(StatusCode code);\n\n// operator<<\n//\n// Streams StatusCodeToString(code) to `os`.\nstd::ostream& operator<<(std::ostream& os, StatusCode code);\n\n// absl::StatusToStringMode\n//\n// An `absl::StatusToStringMode` is an enumerated type indicating how\n// `absl::Status::ToString()` should construct the output string for a non-ok\n// status.\nenum class StatusToStringMode : int {\n  // ToString will not contain any extra data (such as payloads). It will only\n  // contain the error code and message, if any.\n  kWithNoExtraData = 0,\n  // ToString will contain the payloads.\n  kWithPayload = 1 << 0,\n  // ToString will contain the source locations.\n  kWithSourceLocation = 1 << 1,\n  // ToString will include all the extra data this Status has.\n  kWithEverything = ~kWithNoExtraData,\n  // Default mode used by ToString. Its exact value might change in the future.\n  kDefault = kWithPayload,\n};\n\n// absl::StatusToStringMode is specified as a bitmask type, which means the\n// following operations must be provided:\ninline constexpr StatusToStringMode operator&(StatusToStringMode lhs,\n                                              StatusToStringMode rhs) {\n  return static_cast<StatusToStringMode>(static_cast<int>(lhs) &\n                                         static_cast<int>(rhs));\n}\ninline constexpr StatusToStringMode operator|(StatusToStringMode lhs,\n                                              StatusToStringMode rhs) {\n  return static_cast<StatusToStringMode>(static_cast<int>(lhs) |\n                                         static_cast<int>(rhs));\n}\ninline constexpr StatusToStringMode operator^(StatusToStringMode lhs,\n                                              StatusToStringMode rhs) {\n  return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^\n                                         static_cast<int>(rhs));\n}\ninline constexpr StatusToStringMode operator~(StatusToStringMode arg) {\n  return static_cast<StatusToStringMode>(~static_cast<int>(arg));\n}\ninline StatusToStringMode& operator&=(StatusToStringMode& lhs,\n                                      StatusToStringMode rhs) {\n  lhs = lhs & rhs;\n  return lhs;\n}\ninline StatusToStringMode& operator|=(StatusToStringMode& lhs,\n                                      StatusToStringMode rhs) {\n  lhs = lhs | rhs;\n  return lhs;\n}\ninline StatusToStringMode& operator^=(StatusToStringMode& lhs,\n                                      StatusToStringMode rhs) {\n  lhs = lhs ^ rhs;\n  return lhs;\n}\n\n// absl::Status\n//\n// The `absl::Status` class is generally used to gracefully handle errors\n// across API boundaries (and in particular across RPC boundaries). Some of\n// these errors may be recoverable, but others may not. Most\n// functions which can produce a recoverable error should be designed to return\n// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds\n// either an object of type `T` or an error).\n//\n// API developers should construct their functions to return `absl::OkStatus()`\n// upon success, or an `absl::StatusCode` upon another type of error (e.g\n// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience\n// functions to construct each status code.\n//\n// Example:\n//\n// absl::Status myFunction(absl::string_view fname, ...) {\n//   ...\n//   // encounter error\n//   if (error condition) {\n//     // Construct an absl::StatusCode::kInvalidArgument error\n//     return absl::InvalidArgumentError(\"bad mode\");\n//   }\n//   // else, return OK\n//   return absl::OkStatus();\n// }\n//\n// Users handling status error codes should prefer checking for an OK status\n// using the `ok()` member function. Handling multiple error codes may justify\n// use of switch statement, but only check for error codes you know how to\n// handle; do not try to exhaustively match against all canonical error codes.\n// Errors that cannot be handled should be logged and/or propagated for higher\n// levels to deal with. If you do use a switch statement, make sure that you\n// also provide a `default:` switch case, so that code does not break as other\n// canonical codes are added to the API.\n//\n// Example:\n//\n//   absl::Status result = DoSomething();\n//   if (!result.ok()) {\n//     LOG(ERROR) << result;\n//   }\n//\n//   // Provide a default if switching on multiple error codes\n//   switch (result.code()) {\n//     // The user hasn't authenticated. Ask them to reauth\n//     case absl::StatusCode::kUnauthenticated:\n//       DoReAuth();\n//       break;\n//     // The user does not have permission. Log an error.\n//     case absl::StatusCode::kPermissionDenied:\n//       LOG(ERROR) << result;\n//       break;\n//     // Propagate the error otherwise.\n//     default:\n//       return true;\n//   }\n//\n// An `absl::Status` can optionally include a payload with more information\n// about the error. Typically, this payload serves one of several purposes:\n//\n//   * It may provide more fine-grained semantic information about the error to\n//     facilitate actionable remedies.\n//   * It may provide human-readable contextual information that is more\n//     appropriate to display to an end user.\n//\n// Example:\n//\n//   absl::Status result = DoSomething();\n//   // Inform user to retry after 30 seconds\n//   // See more error details in googleapis/google/rpc/error_details.proto\n//   if (absl::IsResourceExhausted(result)) {\n//     google::rpc::RetryInfo info;\n//     info.retry_delay().seconds() = 30;\n//     // Payloads require a unique key (a URL to ensure no collisions with\n//     // other payloads), and an `absl::Cord` to hold the encoded data.\n//     absl::string_view url = \"type.googleapis.com/google.rpc.RetryInfo\";\n//     result.SetPayload(url, info.SerializeAsCord());\n//     return result;\n//   }\n//\n// For documentation see https://abseil.io/docs/cpp/guides/status.\n//\n// Returned Status objects may not be ignored. status_internal.h has a forward\n// declaration of the form\n// class ABSL_MUST_USE_RESULT Status;\nclass ABSL_ATTRIBUTE_TRIVIAL_ABI Status final {\n public:\n  // Constructors\n\n  // This default constructor creates an OK status with no message or payload.\n  // Avoid this constructor and prefer explicit construction of an OK status\n  // with `absl::OkStatus()`.\n  Status();\n\n  // Creates a status in the canonical error space with the specified\n  // `absl::StatusCode` and error message.  If `code == absl::StatusCode::kOk`,\n  // `msg` is ignored and an object identical to an OK status is constructed.\n  //\n  // The `msg` string must be in UTF-8. The implementation may complain (e.g.,\n  // by printing a warning) if it is not.\n  //\n  // The `loc` is the SourceLocation of the callsite. It will be stored in the\n  // Status iff `code != absl::StatusCode::kOk` and `!msg.empty()`.\n  Status(absl::StatusCode code, absl::string_view msg,\n         absl::SourceLocation loc = SourceLocation::current());\n\n  // Create a status from a `base_status` and a `loc`. The `loc` will be\n  // appended to the location chain of the new status, iff the `base_status` is\n  // not ok and has non-empty msg.\n  Status(const Status& base_status, absl::SourceLocation loc)\n      : Status(base_status) {\n    AddSourceLocation(loc);\n  }\n  Status(Status&& base_status, absl::SourceLocation loc)\n      : Status(std::move(base_status)) {\n    AddSourceLocation(loc);\n  }\n\n  Status(const Status&);\n  Status& operator=(const Status& x);\n\n  // Move operators\n\n  // The moved-from state is valid but unspecified.\n  Status(Status&&) noexcept;\n  Status& operator=(Status&&) noexcept;\n\n  ~Status();\n\n  // Status::Update()\n  //\n  // Updates the existing status with `new_status` provided that `this->ok()`.\n  // If the existing status already contains a non-OK error, this update has no\n  // effect and preserves the current data. Note that this behavior may change\n  // in the future to augment a current non-ok status with additional\n  // information about `new_status`.\n  //\n  // `Update()` provides a convenient way of keeping track of the first error\n  // encountered.\n  //\n  // Example:\n  //   // Instead of \"if (overall_status.ok()) overall_status = new_status\"\n  //   overall_status.Update(new_status);\n  //\n  void Update(const Status& new_status);\n  void Update(Status&& new_status);\n\n  // Status::ok()\n  //\n  // Returns `true` if `this->code()` == `absl::StatusCode::kOk`,\n  // indicating the absence of an error.\n  // Prefer checking for an OK status using this member function.\n  ABSL_MUST_USE_RESULT bool ok() const;\n\n  // Status::code()\n  //\n  // Returns the canonical error code of type `absl::StatusCode` of this status.\n  absl::StatusCode code() const;\n\n  // Status::raw_code()\n  //\n  // Returns a raw (canonical) error code corresponding to the enum value of\n  // `google.rpc.Code` definitions within\n  // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto.\n  // These values could be out of the range of canonical `absl::StatusCode`\n  // enum values.\n  //\n  // NOTE: This function should only be called when converting to an associated\n  // wire format. Use `Status::code()` for error handling.\n  int raw_code() const;\n\n  // Status::message()\n  //\n  // Returns the error message associated with this error code, if available.\n  // Note that this message rarely describes the error code.  It is not unusual\n  // for the error message to be the empty string. As a result, prefer\n  // `operator<<` or `Status::ToString()` for debug logging.\n  absl::string_view message() const;\n\n  friend bool operator==(const Status&, const Status&);\n  friend bool operator!=(const Status&, const Status&);\n\n  // Status::ToString()\n  //\n  // Returns a string based on the `mode`. By default, it returns combination of\n  // the error code name, the message and any associated payload messages. This\n  // string is designed simply to be human readable and its exact format should\n  // not be load bearing. Do not depend on the exact format of the result of\n  // `ToString()` which is subject to change.\n  //\n  // The printed code name and the message are generally substrings of the\n  // result, and the payloads to be printed use the status payload printer\n  // mechanism (which is internal).\n  std::string ToString(\n      StatusToStringMode mode = StatusToStringMode::kDefault) const;\n\n  // Support `absl::StrCat`, `absl::StrFormat`, etc.\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const Status& status) {\n    sink.Append(status.ToString(StatusToStringMode::kWithEverything));\n  }\n\n  // Status::IgnoreError()\n  //\n  // Ignores any errors. This method does nothing except potentially suppress\n  // complaints from any tools that are checking that errors are not dropped on\n  // the floor.\n  void IgnoreError() const;\n\n  // swap()\n  //\n  // Swap the contents of one status with another.\n  friend void swap(Status& a, Status& b) noexcept;\n\n  //----------------------------------------------------------------------------\n  // Payload Management APIs\n  //----------------------------------------------------------------------------\n\n  // A payload may be attached to a status to provide additional context to an\n  // error that may not be satisfied by an existing `absl::StatusCode`.\n  // Typically, this payload serves one of several purposes:\n  //\n  //   * It may provide more fine-grained semantic information about the error\n  //     to facilitate actionable remedies.\n  //   * It may provide human-readable contextual information that is more\n  //     appropriate to display to an end user.\n  //\n  // A payload consists of a [key,value] pair, where the key is a string\n  // referring to a unique \"type URL\" and the value is an object of type\n  // `absl::Cord` to hold the contextual data.\n  //\n  // The \"type URL\" should be unique and follow the format of a URL\n  // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some\n  // documentation or schema on how to interpret its associated data. For\n  // example, the default type URL for a protobuf message type is\n  // \"type.googleapis.com/packagename.messagename\". Other custom wire formats\n  // should define the format of type URL in a similar practice so as to\n  // minimize the chance of conflict between type URLs.\n  // Users should ensure that the type URL can be mapped to a concrete\n  // C++ type if they want to deserialize the payload and read it effectively.\n  //\n  // To attach a payload to a status object, call `Status::SetPayload()`,\n  // passing it the type URL and an `absl::Cord` of associated data. Similarly,\n  // to extract the payload from a status, call `Status::GetPayload()`. You\n  // may attach multiple payloads (with differing type URLs) to any given\n  // status object, provided that the status is currently exhibiting an error\n  // code (i.e. is not OK).\n\n  // Status::GetPayload()\n  //\n  // Gets the payload of a status given its unique `type_url` key, if present.\n  std::optional<absl::Cord> GetPayload(absl::string_view type_url) const;\n\n  // Status::SetPayload()\n  //\n  // Sets the payload for a non-ok status using a `type_url` key, overwriting\n  // any existing payload for that `type_url`.\n  //\n  // NOTE: This function does nothing if the Status is ok.\n  void SetPayload(absl::string_view type_url, absl::Cord payload);\n\n  // Status::ErasePayload()\n  //\n  // Erases the payload corresponding to the `type_url` key.  Returns `true` if\n  // the payload was present.\n  bool ErasePayload(absl::string_view type_url);\n\n  // Status::ForEachPayload()\n  //\n  // Iterates over the stored payloads and calls the\n  // `visitor(type_key, payload)` callable for each one.\n  //\n  // NOTE: The order of calls to `visitor()` is not specified and may change at\n  // any time.\n  //\n  // NOTE: Any mutation on the same 'absl::Status' object during visitation is\n  // forbidden and could result in undefined behavior.\n  void ForEachPayload(\n      absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)\n      const;\n\n  absl::Span<const absl::SourceLocation> GetSourceLocations() const {\n    if (IsInlined(rep_)) return {};\n    return RepToPointer(rep_)->GetSourceLocations();\n  }\n  // Appends the `loc` to the current location chain inside the status, iff the\n  // status is non-ok and contains a non-empty message.\n  void AddSourceLocation(\n      absl::SourceLocation loc = absl::SourceLocation::current()) {\n    if (ok()) return;\n    rep_ = AddSourceLocationImpl(rep_, loc);\n    ABSL_ATTRIBUTE_UNUSED bool okay = ok();\n    // This hint tells the optimizer that the status is still not ok after the\n    // AddSourceLocation() call. This is useful when passing a known !ok status\n    // to StatusOr. StatusOr checks for ok() on its constructor and this assume\n    // helps the optimizer remove that check.\n    ABSL_ASSUME(!okay);\n  }\n\n  // Status::WithSourceLocation()\n  //\n  // Returns a copy of the current status, with `loc` appended to its location\n  // chain iff the status is non-ok and contains a non-empty message.\n  //\n  // Example:\n  //\n  //   if (Status status = Foo(); !status.ok()) {\n  //     return status.WithSourceLocation();\n  //   }\n  Status WithSourceLocation(\n      absl::SourceLocation loc = absl::SourceLocation::current()) const& {\n    return Status(*this, loc);\n  }\n\n  // Status::WithSourceLocation()\n  //\n  // Appends the `loc` to the current location chain inside the status iff the\n  // status is non-ok and contains a non-empty message, and returns an rvalue\n  // reference to `*this`.\n  //\n  // Example:\n  //\n  //   Status Finalize(...);\n  //\n  //   Status DoSomething(...) {\n  //     ...\n  //     return Finalize().WithSourceLocation();\n  //   }\n  ABSL_MUST_USE_RESULT Status&& WithSourceLocation(\n      absl::SourceLocation loc = absl::SourceLocation::current()) && {\n    AddSourceLocation(loc);\n    return std::move(*this);\n  }\n\n private:\n  friend Status CancelledError();\n\n  // Creates a status in the canonical error space with the specified\n  // code, and an empty error message.\n  explicit Status(absl::StatusCode code);\n\n  // Delegate factory in header that ensures CodeToInlinedRep is inlined\n  // where possible.\n  static uintptr_t MakeRep(uintptr_t inlined_rep, absl::string_view msg,\n                           absl::SourceLocation loc);\n\n  // Underlying constructor for status from a rep_.\n  explicit Status(uintptr_t rep) : rep_(rep) {}\n\n  // An out-of-line AddSourceLocation that mutates rep directly.\n  static uintptr_t AddSourceLocationImpl(uintptr_t rep,\n                                         absl::SourceLocation loc);\n\n  static void Ref(uintptr_t rep);\n  static void Unref(uintptr_t rep);\n\n  // REQUIRES: !ok()\n  // Ensures rep is not inlined or shared with any other Status.\n  static status_internal::StatusRep* absl_nonnull PrepareToModify(\n      uintptr_t rep);\n\n  // MSVC 14.0 limitation requires the const.\n  static constexpr const char kMovedFromString[] =\n      \"Status accessed after move.\";\n\n  static const std::string* absl_nonnull EmptyString();\n  static const std::string* absl_nonnull MovedFromString();\n\n  // Returns whether rep contains an inlined representation.\n  // See rep_ for details.\n  static constexpr bool IsInlined(uintptr_t rep);\n\n  // Indicates whether this Status was the rhs of a move operation. See rep_\n  // for details.\n  static constexpr bool IsMovedFrom(uintptr_t rep);\n  static constexpr uintptr_t MovedFromRep();\n\n  // Convert between error::Code and the inlined uintptr_t representation used\n  // by rep_. See rep_ for details.\n  static constexpr uintptr_t CodeToInlinedRep(absl::StatusCode code);\n  static constexpr absl::StatusCode InlinedRepToCode(uintptr_t rep);\n\n  // Converts between StatusRep* and the external uintptr_t representation used\n  // by rep_. See rep_ for details.\n  static uintptr_t PointerToRep(status_internal::StatusRep* absl_nonnull r);\n  static const status_internal::StatusRep* absl_nonnull RepToPointer(\n      uintptr_t r);\n\n  static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode);\n\n  // Status supports two different representations.\n  //  - When the low bit is set it is an inlined representation.\n  //    It uses the canonical error space, no message or payload.\n  //    The error code is (rep_ >> 2).\n  //    The (rep_ & 2) bit is the \"moved from\" indicator, used in IsMovedFrom().\n  //  - When the low bit is off it is an external representation.\n  //    In this case all the data comes from a heap allocated Rep object.\n  //    rep_ is a status_internal::StatusRep* pointer to that structure.\n  uintptr_t rep_;\n\n  friend class status_internal::StatusRep;\n};\n\n// OkStatus()\n//\n// Returns an OK status, equivalent to a default constructed instance. Prefer\n// usage of `absl::OkStatus()` when constructing such an OK status.\nStatus OkStatus();\n\n// operator<<()\n//\n// Prints a human-readable representation of `x` to `os`.\nstd::ostream& operator<<(std::ostream& os, const Status& x);\n\n// IsAborted()\n// IsAlreadyExists()\n// IsCancelled()\n// IsDataLoss()\n// IsDeadlineExceeded()\n// IsFailedPrecondition()\n// IsInternal()\n// IsInvalidArgument()\n// IsNotFound()\n// IsOutOfRange()\n// IsPermissionDenied()\n// IsResourceExhausted()\n// IsUnauthenticated()\n// IsUnavailable()\n// IsUnimplemented()\n// IsUnknown()\n//\n// These convenience functions return `true` if a given status matches the\n// `absl::StatusCode` error code of its associated function.\nABSL_MUST_USE_RESULT bool IsAborted(const Status& status);\nABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);\nABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);\nABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);\nABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);\nABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);\nABSL_MUST_USE_RESULT bool IsInternal(const Status& status);\nABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);\nABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);\nABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);\nABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);\nABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);\nABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);\nABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);\nABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);\nABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);\n\n// AbortedError()\n// AlreadyExistsError()\n// CancelledError()\n// DataLossError()\n// DeadlineExceededError()\n// FailedPreconditionError()\n// InternalError()\n// InvalidArgumentError()\n// NotFoundError()\n// OutOfRangeError()\n// PermissionDeniedError()\n// ResourceExhaustedError()\n// UnauthenticatedError()\n// UnavailableError()\n// UnimplementedError()\n// UnknownError()\n//\n// These convenience functions create an `absl::Status` object with an error\n// code as indicated by the associated function name, using the error message\n// passed in `message`.\nStatus AbortedError(absl::string_view message,\n                    absl::SourceLocation loc = SourceLocation::current());\nStatus AlreadyExistsError(absl::string_view message,\n                          absl::SourceLocation loc = SourceLocation::current());\nStatus CancelledError(absl::string_view message,\n                      absl::SourceLocation loc = SourceLocation::current());\nStatus DataLossError(absl::string_view message,\n                     absl::SourceLocation loc = SourceLocation::current());\nStatus DeadlineExceededError(\n    absl::string_view message,\n    absl::SourceLocation loc = SourceLocation::current());\nStatus FailedPreconditionError(\n    absl::string_view message,\n    absl::SourceLocation loc = SourceLocation::current());\nStatus InternalError(absl::string_view message,\n                     absl::SourceLocation loc = SourceLocation::current());\nStatus InvalidArgumentError(\n    absl::string_view message,\n    absl::SourceLocation loc = SourceLocation::current());\nStatus NotFoundError(absl::string_view message,\n                     absl::SourceLocation loc = SourceLocation::current());\nStatus OutOfRangeError(absl::string_view message,\n                       absl::SourceLocation loc = SourceLocation::current());\nStatus PermissionDeniedError(\n    absl::string_view message,\n    absl::SourceLocation loc = SourceLocation::current());\nStatus ResourceExhaustedError(\n    absl::string_view message,\n    absl::SourceLocation loc = SourceLocation::current());\nStatus UnauthenticatedError(\n    absl::string_view message,\n    absl::SourceLocation loc = SourceLocation::current());\nStatus UnavailableError(absl::string_view message,\n                        absl::SourceLocation loc = SourceLocation::current());\nStatus UnimplementedError(absl::string_view message,\n                          absl::SourceLocation loc = SourceLocation::current());\nStatus UnknownError(absl::string_view message,\n                    absl::SourceLocation loc = SourceLocation::current());\n\n// ErrnoToStatusCode()\n//\n// Returns the StatusCode for `error_number`, which should be an `errno` value.\n// See https://en.cppreference.com/w/cpp/error/errno_macros and similar\n// references.\nabsl::StatusCode ErrnoToStatusCode(int error_number);\n\n// ErrnoToStatus()\n//\n// Convenience function that creates a `absl::Status` using an `error_number`,\n// which should be an `errno` value.\nStatus ErrnoToStatus(int error_number, absl::string_view message,\n                     absl::SourceLocation loc = SourceLocation::current());\n\n//------------------------------------------------------------------------------\n// Implementation details follow\n//------------------------------------------------------------------------------\n\ninline Status::Status() : Status(absl::StatusCode::kOk) {}\n\ninline Status::Status(absl::StatusCode code) : Status(CodeToInlinedRep(code)) {}\n\ninline Status::Status(absl::StatusCode code, absl::string_view msg,\n                      absl::SourceLocation loc)\n    : Status(MakeRep(CodeToInlinedRep(code), msg, loc)) {}\n\ninline Status::Status(const Status& x) : Status(x.rep_) { Ref(rep_); }\n\ninline Status& Status::operator=(const Status& x) {\n  uintptr_t old_rep = rep_;\n  if (x.rep_ != old_rep) {\n    Ref(x.rep_);\n    rep_ = x.rep_;\n    Unref(old_rep);\n  }\n  return *this;\n}\n\ninline Status::Status(Status&& x) noexcept : Status(x.rep_) {\n  x.rep_ = MovedFromRep();\n}\n\ninline Status& Status::operator=(Status&& x) noexcept {\n  uintptr_t old_rep = rep_;\n  if (x.rep_ != old_rep) {\n    rep_ = x.rep_;\n    x.rep_ = MovedFromRep();\n    Unref(old_rep);\n  }\n  return *this;\n}\n\ninline void Status::Update(const Status& new_status) {\n  if (ok()) {\n    *this = new_status;\n  }\n}\n\ninline void Status::Update(Status&& new_status) {\n  if (ok()) {\n    *this = std::move(new_status);\n  }\n}\n\ninline Status::~Status() { Unref(rep_); }\n\ninline bool Status::ok() const {\n  return rep_ == CodeToInlinedRep(absl::StatusCode::kOk);\n}\n\ninline absl::StatusCode Status::code() const {\n  return status_internal::MapToLocalCode(raw_code());\n}\n\ninline int Status::raw_code() const {\n  if (IsInlined(rep_)) return static_cast<int>(InlinedRepToCode(rep_));\n  return static_cast<int>(RepToPointer(rep_)->code());\n}\n\ninline absl::string_view Status::message() const {\n  return !IsInlined(rep_)\n             ? RepToPointer(rep_)->message()\n             : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString)\n                                  : absl::string_view());\n}\n\ninline bool operator==(const Status& lhs, const Status& rhs) {\n  if (lhs.rep_ == rhs.rep_) return true;\n  if (Status::IsInlined(lhs.rep_)) return false;\n  if (Status::IsInlined(rhs.rep_)) return false;\n  return *Status::RepToPointer(lhs.rep_) == *Status::RepToPointer(rhs.rep_);\n}\n\ninline bool operator!=(const Status& lhs, const Status& rhs) {\n  return !(lhs == rhs);\n}\n\ninline std::string Status::ToString(StatusToStringMode mode) const {\n  return ok() ? \"OK\" : ToStringSlow(rep_, mode);\n}\n\ninline void Status::IgnoreError() const {\n  // no-op\n}\n\ninline void swap(absl::Status& a, absl::Status& b) noexcept {\n  using std::swap;\n  swap(a.rep_, b.rep_);\n}\n\ninline std::optional<absl::Cord> Status::GetPayload(\n    absl::string_view type_url) const {\n  if (IsInlined(rep_)) return std::nullopt;\n  return RepToPointer(rep_)->GetPayload(type_url);\n}\n\ninline void Status::SetPayload(absl::string_view type_url, absl::Cord payload) {\n  if (ok()) return;\n  status_internal::StatusRep* rep = PrepareToModify(rep_);\n  rep->SetPayload(type_url, std::move(payload));\n  rep_ = PointerToRep(rep);\n}\n\ninline bool Status::ErasePayload(absl::string_view type_url) {\n  if (IsInlined(rep_)) return false;\n  status_internal::StatusRep* rep = PrepareToModify(rep_);\n  auto res = rep->ErasePayload(type_url);\n  rep_ = res.new_rep;\n  return res.erased;\n}\n\ninline void Status::ForEachPayload(\n    absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)\n    const {\n  if (IsInlined(rep_)) return;\n  RepToPointer(rep_)->ForEachPayload(visitor);\n}\n\nconstexpr bool Status::IsInlined(uintptr_t rep) { return (rep & 1) != 0; }\n\nconstexpr bool Status::IsMovedFrom(uintptr_t rep) { return (rep & 2) != 0; }\n\nconstexpr uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) {\n  return (static_cast<uintptr_t>(code) << 2) + 1;\n}\n\nconstexpr absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) {\n  ABSL_ASSERT(IsInlined(rep));\n  return static_cast<absl::StatusCode>(rep >> 2);\n}\n\nconstexpr uintptr_t Status::MovedFromRep() {\n  return CodeToInlinedRep(absl::StatusCode::kInternal) | 2;\n}\n\ninline const status_internal::StatusRep* absl_nonnull Status::RepToPointer(\n    uintptr_t rep) {\n  assert(!IsInlined(rep));\n  return reinterpret_cast<const status_internal::StatusRep*>(rep);\n}\n\ninline uintptr_t Status::PointerToRep(\n    status_internal::StatusRep* absl_nonnull rep) {\n  return reinterpret_cast<uintptr_t>(rep);\n}\n\ninline void Status::Ref(uintptr_t rep) {\n  if (!IsInlined(rep)) RepToPointer(rep)->Ref();\n}\n\ninline void Status::Unref(uintptr_t rep) {\n  if (!IsInlined(rep)) RepToPointer(rep)->Unref();\n}\n\ninline Status OkStatus() { return Status(); }\n\n// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code\n// and an empty message. It is provided only for efficiency, given that\n// message-less kCancelled errors are common in the infrastructure.\ninline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }\n\n// Retrieves a message's status as a null terminated C string. The lifetime of\n// this string is tied to the lifetime of the status object itself.\n//\n// If the status's message is empty, the empty string is returned.\n//\n// StatusMessageAsCStr exists for C support. Use `status.message()` in C++.\nconst char* absl_nonnull StatusMessageAsCStr(\n    const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STATUS_STATUS_H_\n"
  },
  {
    "path": "absl/status/status_benchmark.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <utility>\n\n#include \"absl/status/status.h\"\n#include \"absl/types/source_location.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_CreateOk(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::Status s;  // ok.\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_CreateOk);\n\nvoid BM_CreateBad(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::Status s(absl::StatusCode::kInvalidArgument, \"message\");\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_CreateBad);\n\nvoid BM_AppendSourceLocation(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::Status s(absl::StatusCode::kInvalidArgument, \"message\");\n    benchmark::DoNotOptimize(s);\n    absl::Status s2(std::move(s), absl::SourceLocation::current());\n    benchmark::DoNotOptimize(s2);\n  }\n}\nBENCHMARK(BM_AppendSourceLocation);\n\n}  // namespace\n"
  },
  {
    "path": "absl/status/status_matchers.h",
    "content": "// Copyright 2024 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: status_matchers.h\n// -----------------------------------------------------------------------------\n//\n// Testing utilities for working with `absl::Status` and `absl::StatusOr`.\n//\n// Defines the following utilities:\n//\n//   =================\n//   ABSL_EXPECT_OK(s)\n//\n//   ABSL_ASSERT_OK(s)\n//   =================\n//   Convenience macros for `EXPECT_THAT(s, IsOk())`, where `s` is either\n//   a `Status` or a `StatusOr<T>`.\n//\n//   There are no EXPECT_NOT_OK/ASSERT_NOT_OK macros since they would not\n//   provide much value (when they fail, they would just print the OK status\n//   which conveys no more information than `EXPECT_FALSE(s.ok())`. You can\n//   of course use `EXPECT_THAT(s, Not(IsOk()))` if you prefer _THAT style.\n//\n//   If you want to check for particular errors, better alternatives are:\n//   EXPECT_THAT(s, StatusIs(expected_error));\n//   EXPECT_THAT(s, StatusIs(_, _, HasSubstr(\"expected error\")));\n//\n//\n//   ===============\n//   `IsOkAndHolds(m)`\n//   ===============\n//\n//   This gMock matcher matches a StatusOr<T> value whose status is OK\n//   and whose inner value matches matcher m.  Example:\n//\n//   ```\n//   using ::testing::MatchesRegex;\n//   using ::absl_testing::IsOkAndHolds;\n//   ...\n//   absl::StatusOr<string> maybe_name = ...;\n//   EXPECT_THAT(maybe_name, IsOkAndHolds(MatchesRegex(\"John .*\")));\n//   ```\n//\n//   ===============================\n//   `StatusIs(status_code_matcher)`\n//   ===============================\n//\n//   This is a shorthand for\n//     `StatusIs(status_code_matcher, ::testing::_)`\n//   In other words, it's like the two-argument `StatusIs()`, except that it\n//   ignores error message.\n//\n//   ===============\n//   `IsOk()`\n//   ===============\n//\n//   Matches an `absl::Status` or `absl::StatusOr<T>` value whose status value\n//   is `absl::StatusCode::kOk.`\n//\n//   Equivalent to 'StatusIs(absl::StatusCode::kOk)'.\n//   Example:\n//   ```\n//   using ::absl_testing::IsOk;\n//   ...\n//   absl::StatusOr<string> maybe_name = ...;\n//   EXPECT_THAT(maybe_name, IsOk());\n//   Status s = ...;\n//   EXPECT_THAT(s, IsOk());\n//   ```\n\n#ifndef ABSL_STATUS_STATUS_MATCHERS_H_\n#define ABSL_STATUS_STATUS_MATCHERS_H_\n\n#include <ostream>  // NOLINT\n#include <type_traits>\n#include <utility>\n\n#include \"gmock/gmock.h\"  // gmock_for_status_matchers.h\n#include \"absl/base/config.h\"\n#include \"absl/status/internal/status_matchers.h\"\n\nnamespace absl_testing {\nABSL_NAMESPACE_BEGIN\n\n// Macros for testing the results of functions that return absl::Status or\n// absl::StatusOr<T> (for any type T).\n#define ABSL_EXPECT_OK(expression) \\\n  EXPECT_THAT(expression, ::absl_testing::IsOk())\n#define ABSL_ASSERT_OK(expression) \\\n  ASSERT_THAT(expression, ::absl_testing::IsOk())\n\n// Returns a gMock matcher that matches a StatusOr<> whose status is\n// OK and whose value matches the inner matcher.\ntemplate <typename InnerMatcherT>\nstatus_internal::IsOkAndHoldsMatcher<typename std::decay<InnerMatcherT>::type>\nIsOkAndHolds(InnerMatcherT&& inner_matcher) {\n  return status_internal::IsOkAndHoldsMatcher<\n      typename std::decay<InnerMatcherT>::type>(\n      std::forward<InnerMatcherT>(inner_matcher));\n}\n\n// Returns a gMock matcher that matches a Status or StatusOr<> whose status code\n// matches code_matcher and whose error message matches message_matcher.\n// Typically, code_matcher will be an absl::StatusCode, e.g.\n//\n// StatusIs(absl::StatusCode::kInvalidArgument, \"...\")\ntemplate <typename StatusCodeMatcherT, typename StatusMessageMatcherT>\nstatus_internal::StatusIsMatcher StatusIs(\n    StatusCodeMatcherT&& code_matcher,\n    StatusMessageMatcherT&& message_matcher) {\n  return status_internal::StatusIsMatcher(\n      std::forward<StatusCodeMatcherT>(code_matcher),\n      std::forward<StatusMessageMatcherT>(message_matcher));\n}\n\n// Returns a gMock matcher that matches a Status or StatusOr<> and whose status\n// code matches code_matcher.  See above for details.\ntemplate <typename StatusCodeMatcherT>\nstatus_internal::StatusIsMatcher StatusIs(StatusCodeMatcherT&& code_matcher) {\n  return absl_testing::StatusIs(std::forward<StatusCodeMatcherT>(code_matcher),\n                                ::testing::_);\n}\n\n// Returns a gMock matcher that matches a Status or StatusOr<> which is OK.\ninline status_internal::IsOkMatcher IsOk() {\n  return status_internal::IsOkMatcher();\n}\n\n// By defining ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS, this library also\n// provides unqualified versions of macros\n//\n// Unqualified macro names are likely to collide with those other projects, and\n// so are not recommended.  Further, this is true of any transitive dependency\n// of Abseil; it is impossible to be confident no downstream library will not\n// also define these macros itself nor depend on a different library that also\n// defines them.\n//\n// To enable this, define `ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS`\n// preferably at the command line, e.g.\n// `-DABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS` or\n// `local_defines = [\"ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\"]` if using\n// Bazel.\n//\n// These are turned on by default inside Google's internal codebase where their\n// use is historically ubiquitous.  Other OSS Google projects should use the\n// qualified versions or the `EXPECT_THAT(..., IsOk())` form.\n#ifdef ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\n#define EXPECT_OK(expression) ABSL_EXPECT_OK(expression)\n#define ASSERT_OK(expression) ABSL_ASSERT_OK(expression)\n#endif  // ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\n\nABSL_NAMESPACE_END\n}  // namespace absl_testing\n\n#endif  // ABSL_STATUS_STATUS_MATCHERS_H_\n"
  },
  {
    "path": "absl/status/status_matchers_test.cc",
    "content": "// Copyright 2024 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: status_matchers_test.cc\n// -----------------------------------------------------------------------------\n#include \"absl/status/status_matchers.h\"\n\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest-spi.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/status/status.h\"\n#include \"absl/status/statusor.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nusing ::absl_testing::IsOk;\nusing ::absl_testing::IsOkAndHolds;\nusing ::absl_testing::StatusIs;\nusing ::testing::ElementsAre;\nusing ::testing::Eq;\nusing ::testing::Gt;\nusing ::testing::MatchesRegex;\nusing ::testing::Not;\nusing ::testing::Ref;\n\nTEST(StatusMatcherTest, AbslExpectAssertOk) {\n  ABSL_EXPECT_OK(absl::OkStatus());\n  ABSL_ASSERT_OK(absl::OkStatus());\n  EXPECT_NONFATAL_FAILURE(ABSL_EXPECT_OK(absl::InternalError(\"Smigla error\")),\n                          \"Smigla error\");\n  EXPECT_FATAL_FAILURE(ABSL_ASSERT_OK(absl::InternalError(\"Smigla error\")),\n                       \"Smigla error\");\n}\n\nTEST(StatusMatcherTest, ExpectAssertOk) {\n#ifdef ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\n  EXPECT_OK(absl::OkStatus());\n  ASSERT_OK(absl::OkStatus());\n  EXPECT_NONFATAL_FAILURE(EXPECT_OK(absl::InternalError(\"Smigla error\")),\n                          \"Smigla error\");\n  EXPECT_FATAL_FAILURE(ASSERT_OK(absl::InternalError(\"Smigla error\")),\n                       \"Smigla error\");\n#else\n#ifdef EXPECT_OK\n  static_assert(false, \"EXPECT_OK defined despite being turned off.\");\n#endif  // EXPECT_OK\n#ifdef ASSERT_OK\n  static_assert(false, \"ASSERT_OK defined despite being turned off.\");\n#endif  // ASSERT_OK\n#endif  // ABSL_DEFINE_UNQUALIFIED_STATUS_TESTING_MACROS\n}\n\nTEST(StatusMatcherTest, StatusIsOk) { EXPECT_THAT(absl::OkStatus(), IsOk()); }\n\nTEST(StatusMatcherTest, StatusOrIsOk) {\n  absl::StatusOr<int> ok_int = {0};\n  EXPECT_THAT(ok_int, IsOk());\n}\n\nTEST(StatusMatcherTest, StatusIsNotOk) {\n  absl::Status error = absl::UnknownError(\"Smigla\");\n  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(error, IsOk()), \"Smigla\");\n}\n\nTEST(StatusMatcherTest, StatusOrIsNotOk) {\n  absl::StatusOr<int> error = absl::UnknownError(\"Smigla\");\n  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(error, IsOk()), \"Smigla\");\n}\n\nTEST(StatusMatcherTest, IsOkAndHolds) {\n  absl::StatusOr<int> ok_int = {4};\n  absl::StatusOr<absl::string_view> ok_str = {\"text\"};\n  EXPECT_THAT(ok_int, IsOkAndHolds(4));\n  EXPECT_THAT(ok_int, IsOkAndHolds(Gt(0)));\n  EXPECT_THAT(ok_str, IsOkAndHolds(\"text\"));\n}\n\nTEST(StatusMatcherTest, IsOkAndHoldsFailure) {\n  absl::StatusOr<int> ok_int = {502};\n  absl::StatusOr<int> error = absl::UnknownError(\"Smigla\");\n  absl::StatusOr<absl::string_view> ok_str = {\"actual\"};\n  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(ok_int, IsOkAndHolds(0)), \"502\");\n  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(error, IsOkAndHolds(0)), \"Smigla\");\n  EXPECT_NONFATAL_FAILURE(EXPECT_THAT(ok_str, IsOkAndHolds(\"expected\")),\n                          \"actual\");\n}\n\ntemplate <typename MatcherType, typename Value>\nstd::string Explain(const MatcherType& m, const Value& x) {\n  ::testing::StringMatchResultListener listener;\n  ExplainMatchResult(m, x, &listener);\n  return listener.str();\n}\n\nTEST(StatusMatcherTest, StatusIs) {\n  absl::Status unknown = absl::UnknownError(\"unbekannt\");\n  absl::Status invalid = absl::InvalidArgumentError(\"ungueltig\");\n  EXPECT_THAT(absl::OkStatus(), StatusIs(absl::StatusCode::kOk));\n  EXPECT_THAT(absl::OkStatus(), StatusIs(0));\n  EXPECT_THAT(unknown, StatusIs(absl::StatusCode::kUnknown));\n  EXPECT_THAT(unknown, StatusIs(2));\n  EXPECT_THAT(unknown, StatusIs(absl::StatusCode::kUnknown, \"unbekannt\"));\n  EXPECT_THAT(invalid, StatusIs(absl::StatusCode::kInvalidArgument));\n  EXPECT_THAT(invalid, StatusIs(3));\n  EXPECT_THAT(invalid,\n              StatusIs(absl::StatusCode::kInvalidArgument, \"ungueltig\"));\n\n  auto m = StatusIs(absl::StatusCode::kInternal, \"internal error\");\n  EXPECT_THAT(::testing::DescribeMatcher<absl::Status>(m),\n              MatchesRegex(\"has a status code that is equal to INTERNAL, and \"\n                           \"has an error message that .*\"));\n  EXPECT_THAT(\n      ::testing::DescribeMatcher<absl::Status>(m, /*negation=*/true),\n      MatchesRegex(\n          \"either has a status code that .*, or has an error message that .*\"));\n  EXPECT_THAT(Explain(m, absl::InvalidArgumentError(\"internal error\")),\n              Eq(\"whose status code is wrong\"));\n  EXPECT_THAT(Explain(m, absl::InternalError(\"unexpected error\")),\n              Eq(\"whose error message is wrong\"));\n}\n\nTEST(StatusMatcherTest, StatusOrIs) {\n  absl::StatusOr<int> ok = {42};\n  absl::StatusOr<int> unknown = absl::UnknownError(\"unbekannt\");\n  absl::StatusOr<absl::string_view> invalid =\n      absl::InvalidArgumentError(\"ungueltig\");\n  EXPECT_THAT(ok, StatusIs(absl::StatusCode::kOk));\n  EXPECT_THAT(ok, StatusIs(0));\n  EXPECT_THAT(unknown, StatusIs(absl::StatusCode::kUnknown));\n  EXPECT_THAT(unknown, StatusIs(2));\n  EXPECT_THAT(unknown, StatusIs(absl::StatusCode::kUnknown, \"unbekannt\"));\n  EXPECT_THAT(invalid, StatusIs(absl::StatusCode::kInvalidArgument));\n  EXPECT_THAT(invalid, StatusIs(3));\n  EXPECT_THAT(invalid,\n              StatusIs(absl::StatusCode::kInvalidArgument, \"ungueltig\"));\n\n  auto m = StatusIs(absl::StatusCode::kInternal, \"internal error\");\n  EXPECT_THAT(\n      ::testing::DescribeMatcher<absl::StatusOr<int>>(m),\n      MatchesRegex(\n          \"has a status code that .*, and has an error message that .*\"));\n  EXPECT_THAT(\n      ::testing::DescribeMatcher<absl::StatusOr<int>>(m, /*negation=*/true),\n      MatchesRegex(\n          \"either has a status code that .*, or has an error message that .*\"));\n  EXPECT_THAT(Explain(m, absl::StatusOr<int>(57)), Eq(\"which is OK\"));\n  EXPECT_THAT(Explain(m, absl::StatusOr<int>(\n                             absl::InvalidArgumentError(\"internal error\"))),\n              Eq(\"whose status code is wrong\"));\n  EXPECT_THAT(\n      Explain(m, absl::StatusOr<int>(absl::InternalError(\"unexpected error\"))),\n      Eq(\"whose error message is wrong\"));\n}\n\nTEST(StatusMatcherTest, StatusIsFailure) {\n  absl::Status unknown = absl::UnknownError(\"unbekannt\");\n  absl::Status invalid = absl::InvalidArgumentError(\"ungueltig\");\n  EXPECT_NONFATAL_FAILURE(\n      EXPECT_THAT(absl::OkStatus(),\n                  StatusIs(absl::StatusCode::kInvalidArgument)),\n      \"OK\");\n  EXPECT_NONFATAL_FAILURE(\n      EXPECT_THAT(unknown, StatusIs(absl::StatusCode::kCancelled)), \"UNKNOWN\");\n  EXPECT_NONFATAL_FAILURE(\n      EXPECT_THAT(unknown, StatusIs(absl::StatusCode::kUnknown, \"inconnu\")),\n      \"unbekannt\");\n  EXPECT_NONFATAL_FAILURE(\n      EXPECT_THAT(invalid, StatusIs(absl::StatusCode::kOutOfRange)), \"INVALID\");\n  EXPECT_NONFATAL_FAILURE(\n      EXPECT_THAT(invalid,\n                  StatusIs(absl::StatusCode::kInvalidArgument, \"invalide\")),\n      \"ungueltig\");\n}\n\nTEST(StatusMatcherTest, ReferencesWork) {\n  int i = 17;\n  int j = 19;\n  EXPECT_THAT(absl::StatusOr<int&>(i), IsOkAndHolds(17));\n  EXPECT_THAT(absl::StatusOr<int&>(i), Not(IsOkAndHolds(19)));\n  EXPECT_THAT(absl::StatusOr<const int&>(i), IsOkAndHolds(17));\n\n  // Reference testing works as expected.\n  EXPECT_THAT(absl::StatusOr<int&>(i), IsOkAndHolds(Ref(i)));\n  EXPECT_THAT(absl::StatusOr<int&>(i), Not(IsOkAndHolds(Ref(j))));\n\n  // Try a more complex one.\n  std::vector<std::string> vec = {\"A\", \"B\", \"C\"};\n  EXPECT_THAT(absl::StatusOr<std::vector<std::string>&>(vec),\n              IsOkAndHolds(ElementsAre(\"A\", \"B\", \"C\")));\n  EXPECT_THAT(absl::StatusOr<std::vector<std::string>&>(vec),\n              Not(IsOkAndHolds(ElementsAre(\"A\", \"X\", \"C\"))));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/status/status_payload_printer.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/status/status_payload_printer.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace status_internal {\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\nstatic absl::base_internal::AtomicHook<StatusPayloadPrinter> storage;\n\nvoid SetStatusPayloadPrinter(StatusPayloadPrinter printer) {\n  storage.Store(printer);\n}\n\nStatusPayloadPrinter GetStatusPayloadPrinter() {\n  return storage.Load();\n}\n\n}  // namespace status_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/status/status_payload_printer.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#ifndef ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_\n#define ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_\n\n#include <optional>\n#include <string>\n\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/optional.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace status_internal {\n\n// By default, `Status::ToString` and `operator<<(Status)` print a payload by\n// dumping the type URL and the raw bytes. To help debugging, we provide an\n// extension point, which is a global printer function that can be set by users\n// to specify how to print payloads. The function takes the type URL and the\n// payload as input, and should return a valid human-readable string on success\n// or `std::nullopt` on failure (in which case it falls back to the default\n// approach of printing the raw bytes).\n// NOTE: This is an internal API and the design is subject to change in the\n// future in a non-backward-compatible way. Since it's only meant for debugging\n// purpose, you should not rely on it in any critical logic.\nusing StatusPayloadPrinter = std::optional<std::string> (*absl_nullable)(\n    absl::string_view, const absl::Cord&);\n\n// Sets the global payload printer. Only one printer should be set per process.\n// If multiple printers are set, it's undefined which one will be used.\nvoid SetStatusPayloadPrinter(StatusPayloadPrinter);\n\n// Returns the global payload printer if previously set, otherwise `nullptr`.\nStatusPayloadPrinter GetStatusPayloadPrinter();\n\n}  // namespace status_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_\n"
  },
  {
    "path": "absl/status/status_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/status/status.h\"\n\n#include <errno.h>\n\n#include <array>\n#include <cstddef>\n#include <sstream>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/source_location.h\"\n\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing ::testing::Optional;\nusing ::testing::UnorderedElementsAreArray;\n\nTEST(StatusCode, InsertionOperator) {\n  const absl::StatusCode code = absl::StatusCode::kUnknown;\n  std::ostringstream oss;\n  oss << code;\n  EXPECT_EQ(oss.str(), absl::StatusCodeToString(code));\n  EXPECT_EQ(oss.str(), absl::StatusCodeToStringView(code));\n}\n\n// This structure holds the details for testing a single error code,\n// its creator, and its classifier.\nstruct ErrorTest {\n  absl::StatusCode code;\n  using Creator = absl::Status (*)(absl::string_view, absl::SourceLocation);\n  using Classifier = bool (*)(const absl::Status&);\n  Creator creator;\n  Classifier classifier;\n};\n\nconstexpr ErrorTest kErrorTests[]{\n    {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled},\n    {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown},\n    {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError,\n     absl::IsInvalidArgument},\n    {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError,\n     absl::IsDeadlineExceeded},\n    {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound},\n    {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError,\n     absl::IsAlreadyExists},\n    {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError,\n     absl::IsPermissionDenied},\n    {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError,\n     absl::IsResourceExhausted},\n    {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError,\n     absl::IsFailedPrecondition},\n    {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted},\n    {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange},\n    {absl::StatusCode::kUnimplemented, absl::UnimplementedError,\n     absl::IsUnimplemented},\n    {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal},\n    {absl::StatusCode::kUnavailable, absl::UnavailableError,\n     absl::IsUnavailable},\n    {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss},\n    {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError,\n     absl::IsUnauthenticated},\n};\n\nTEST(Status, CreateAndClassify) {\n  for (const auto& test : kErrorTests) {\n    SCOPED_TRACE(absl::StatusCodeToString(test.code));\n\n    // Ensure that the creator does, in fact, create status objects with the\n    // expected error code and message.\n    std::string message =\n        absl::StrCat(\"error code \", test.code, \" test message\");\n    absl::Status status =\n        test.creator(message, absl::SourceLocation::current());\n    EXPECT_EQ(test.code, status.code());\n    EXPECT_EQ(message, status.message());\n\n    // Ensure that the classifier returns true for a status produced by the\n    // creator.\n    EXPECT_TRUE(test.classifier(status));\n\n    // Ensure that the classifier returns false for status with a different\n    // code.\n    for (const auto& other : kErrorTests) {\n      if (other.code != test.code) {\n        EXPECT_FALSE(test.classifier(absl::Status(other.code, \"\")))\n            << \" other.code = \" << other.code;\n      }\n    }\n  }\n}\n\nTEST(Status, DefaultConstructor) {\n  absl::Status status;\n  EXPECT_TRUE(status.ok());\n  EXPECT_EQ(absl::StatusCode::kOk, status.code());\n  EXPECT_EQ(\"\", status.message());\n}\n\nTEST(Status, OkStatus) {\n  absl::Status status = absl::OkStatus();\n  EXPECT_TRUE(status.ok());\n  EXPECT_EQ(absl::StatusCode::kOk, status.code());\n  EXPECT_EQ(\"\", status.message());\n}\n\nTEST(Status, ConstructorWithCodeMessage) {\n  {\n    absl::Status status(absl::StatusCode::kCancelled, \"\");\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kCancelled, status.code());\n    EXPECT_EQ(\"\", status.message());\n  }\n  {\n    absl::Status status(absl::StatusCode::kInternal, \"message\");\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    EXPECT_EQ(\"message\", status.message());\n  }\n}\n\nTEST(Status, StatusMessageCStringTest) {\n  {\n    absl::Status status = absl::OkStatus();\n    EXPECT_EQ(status.message(), \"\");\n    EXPECT_STREQ(absl::StatusMessageAsCStr(status), \"\");\n    EXPECT_EQ(status.message(), absl::StatusMessageAsCStr(status));\n    EXPECT_NE(absl::StatusMessageAsCStr(status), nullptr);\n  }\n  {\n    absl::Status status;\n    EXPECT_EQ(status.message(), \"\");\n    EXPECT_NE(absl::StatusMessageAsCStr(status), nullptr);\n    EXPECT_STREQ(absl::StatusMessageAsCStr(status), \"\");\n  }\n  {\n    absl::Status status(absl::StatusCode::kInternal, \"message\");\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    EXPECT_EQ(\"message\", status.message());\n    EXPECT_STREQ(\"message\", absl::StatusMessageAsCStr(status));\n  }\n}\n\nTEST(Status, ConstructOutOfRangeCode) {\n  const int kRawCode = 9999;\n  absl::Status status(static_cast<absl::StatusCode>(kRawCode), \"\");\n  EXPECT_EQ(absl::StatusCode::kUnknown, status.code());\n  EXPECT_EQ(kRawCode, status.raw_code());\n}\n\nconstexpr char kUrl1[] = \"url.payload.1\";\nconstexpr char kUrl2[] = \"url.payload.2\";\nconstexpr char kUrl3[] = \"url.payload.3\";\nconstexpr char kUrl4[] = \"url.payload.xx\";\n\nconstexpr char kPayload1[] = \"aaaaa\";\nconstexpr char kPayload2[] = \"bbbbb\";\nconstexpr char kPayload3[] = \"ccccc\";\n\nusing PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>;\n\nTEST(Status, TestGetSetPayload) {\n  absl::Status ok_status = absl::OkStatus();\n  ok_status.SetPayload(kUrl1, absl::Cord(kPayload1));\n  ok_status.SetPayload(kUrl2, absl::Cord(kPayload2));\n\n  EXPECT_FALSE(ok_status.GetPayload(kUrl1));\n  EXPECT_FALSE(ok_status.GetPayload(kUrl2));\n\n  absl::Status bad_status(absl::StatusCode::kInternal, \"fail\");\n  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));\n  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));\n\n  EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1)));\n  EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2)));\n\n  EXPECT_FALSE(bad_status.GetPayload(kUrl3));\n\n  bad_status.SetPayload(kUrl1, absl::Cord(kPayload3));\n  EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3)));\n\n  // Testing dynamically generated type_url\n  bad_status.SetPayload(absl::StrCat(kUrl1, \".1\"), absl::Cord(kPayload1));\n  EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, \".1\")),\n              Optional(Eq(kPayload1)));\n}\n\nTEST(Status, TestErasePayload) {\n  absl::Status bad_status(absl::StatusCode::kInternal, \"fail\");\n  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));\n  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));\n  bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));\n\n  EXPECT_FALSE(bad_status.ErasePayload(kUrl4));\n\n  EXPECT_TRUE(bad_status.GetPayload(kUrl2));\n  EXPECT_TRUE(bad_status.ErasePayload(kUrl2));\n  EXPECT_FALSE(bad_status.GetPayload(kUrl2));\n  EXPECT_FALSE(bad_status.ErasePayload(kUrl2));\n\n  EXPECT_TRUE(bad_status.ErasePayload(kUrl1));\n  EXPECT_TRUE(bad_status.ErasePayload(kUrl3));\n\n  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));\n  EXPECT_TRUE(bad_status.ErasePayload(kUrl1));\n}\n\nTEST(Status, TestComparePayloads) {\n  absl::Status bad_status1(absl::StatusCode::kInternal, \"fail\");\n  bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1));\n  bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2));\n  bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3));\n\n  absl::Status bad_status2(absl::StatusCode::kInternal, \"fail\");\n  bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2));\n  bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3));\n  bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1));\n\n  EXPECT_EQ(bad_status1, bad_status2);\n}\n\nTEST(Status, TestComparePayloadsAfterErase) {\n  absl::Status payload_status(absl::StatusCode::kInternal, \"\");\n  payload_status.SetPayload(kUrl1, absl::Cord(kPayload1));\n  payload_status.SetPayload(kUrl2, absl::Cord(kPayload2));\n\n  absl::Status empty_status(absl::StatusCode::kInternal, \"\");\n\n  // Different payloads, not equal\n  EXPECT_NE(payload_status, empty_status);\n  EXPECT_TRUE(payload_status.ErasePayload(kUrl1));\n\n  // Still Different payloads, still not equal.\n  EXPECT_NE(payload_status, empty_status);\n  EXPECT_TRUE(payload_status.ErasePayload(kUrl2));\n\n  // Both empty payloads, should be equal\n  EXPECT_EQ(payload_status, empty_status);\n}\n\nPayloadsVec AllVisitedPayloads(const absl::Status& s) {\n  PayloadsVec result;\n\n  s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) {\n    result.push_back(std::make_pair(std::string(type_url), payload));\n  });\n\n  return result;\n}\n\nTEST(Status, TestForEachPayload) {\n  absl::Status bad_status(absl::StatusCode::kInternal, \"fail\");\n  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));\n  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));\n  bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));\n\n  int count = 0;\n\n  bad_status.ForEachPayload(\n      [&count](absl::string_view, const absl::Cord&) { ++count; });\n\n  EXPECT_EQ(count, 3);\n\n  PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)},\n                                   {kUrl2, absl::Cord(kPayload2)},\n                                   {kUrl3, absl::Cord(kPayload3)}};\n\n  // Test that we visit all the payloads in the status.\n  PayloadsVec visited_payloads = AllVisitedPayloads(bad_status);\n  EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads));\n\n  // Test that visitation order is not consistent between run.\n  std::vector<absl::Status> scratch;\n  while (true) {\n    scratch.emplace_back(absl::StatusCode::kInternal, \"fail\");\n\n    scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1));\n    scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2));\n    scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3));\n\n    if (AllVisitedPayloads(scratch.back()) != visited_payloads) {\n      break;\n    }\n  }\n}\n\nTEST(Status, ToString) {\n  absl::Status status(absl::StatusCode::kInternal, \"fail\");\n  EXPECT_EQ(\"INTERNAL: fail\", status.ToString());\n  status.SetPayload(\"foo\", absl::Cord(\"bar\"));\n  EXPECT_EQ(\"INTERNAL: fail [foo='bar']\", status.ToString());\n  status.SetPayload(\"bar\", absl::Cord(\"\\377\"));\n  EXPECT_THAT(status.ToString(),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\")));\n}\n\nTEST(Status, ToStringMode) {\n  absl::Status status(absl::StatusCode::kInternal, \"fail\");\n  status.SetPayload(\"foo\", absl::Cord(\"bar\"));\n  status.SetPayload(\"bar\", absl::Cord(\"\\377\"));\n\n  EXPECT_EQ(\"INTERNAL: fail\",\n            status.ToString(absl::StatusToStringMode::kWithNoExtraData));\n\n  EXPECT_THAT(status.ToString(absl::StatusToStringMode::kWithPayload),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\")));\n\n  EXPECT_THAT(status.ToString(absl::StatusToStringMode::kWithEverything),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\")));\n\n  EXPECT_THAT(status.ToString(~absl::StatusToStringMode::kWithPayload),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), Not(HasSubstr(\"[foo='bar']\")),\n                    Not(HasSubstr(\"[bar='\\\\xff']\"))));\n}\n\nTEST(Status, OstreamOperator) {\n  absl::Status status(absl::StatusCode::kInternal, \"fail\");\n  { std::stringstream stream;\n    stream << status;\n    EXPECT_THAT(stream.str(),\n                AllOf(HasSubstr(\"INTERNAL: fail\"),\n                      HasSubstr(\"status_test.cc:\")));\n  }\n  status.SetPayload(\"foo\", absl::Cord(\"bar\"));\n  { std::stringstream stream;\n    stream << status;\n    EXPECT_THAT(stream.str(),\n                AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                      HasSubstr(\"status_test.cc:\")));\n  }\n  status.SetPayload(\"bar\", absl::Cord(\"\\377\"));\n  { std::stringstream stream;\n    stream << status;\n    EXPECT_THAT(stream.str(),\n                AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                      HasSubstr(\"[bar='\\\\xff']\"),\n                      HasSubstr(\"status_test.cc:\")));\n  }\n}\n\nTEST(Status, AbslStringify) {\n  absl::Status status(absl::StatusCode::kInternal, \"fail\");\n  EXPECT_THAT(absl::StrCat(status),\n              AllOf(HasSubstr(\"INTERNAL: fail\"),\n                    HasSubstr(\"status_test.cc:\")));\n  EXPECT_THAT(absl::StrFormat(\"%v\", status),\n              AllOf(HasSubstr(\"INTERNAL: fail\"),\n                    HasSubstr(\"status_test.cc:\")));\n  EXPECT_EQ(absl::StrCat(status), absl::StrFormat(\"%v\", status));\n  status.SetPayload(\"foo\", absl::Cord(\"bar\"));\n  EXPECT_THAT(absl::StrCat(status),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"status_test.cc:\")));\n  status.SetPayload(\"bar\", absl::Cord(\"\\377\"));\n  EXPECT_THAT(absl::StrCat(status),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\"),\n                    HasSubstr(\"status_test.cc:\")));\n}\n\nTEST(Status, OstreamEqStringify) {\n  absl::Status status(absl::StatusCode::kUnknown, \"fail\");\n  status.SetPayload(\"foo\", absl::Cord(\"bar\"));\n  std::stringstream stream;\n  stream << status;\n  EXPECT_EQ(stream.str(), absl::StrCat(status));\n}\n\nabsl::Status EraseAndReturn(const absl::Status& base) {\n  absl::Status copy = base;\n  EXPECT_TRUE(copy.ErasePayload(kUrl1));\n  return copy;\n}\n\nTEST(Status, CopyOnWriteForErasePayload) {\n  {\n    absl::Status base(absl::StatusCode::kInvalidArgument, \"fail\");\n    base.SetPayload(kUrl1, absl::Cord(kPayload1));\n    EXPECT_TRUE(base.GetPayload(kUrl1).has_value());\n    absl::Status copy = EraseAndReturn(base);\n    EXPECT_TRUE(base.GetPayload(kUrl1).has_value());\n    EXPECT_FALSE(copy.GetPayload(kUrl1).has_value());\n  }\n  {\n    absl::Status base(absl::StatusCode::kInvalidArgument, \"fail\");\n    base.SetPayload(kUrl1, absl::Cord(kPayload1));\n    absl::Status copy = base;\n\n    EXPECT_TRUE(base.GetPayload(kUrl1).has_value());\n    EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());\n\n    EXPECT_TRUE(base.ErasePayload(kUrl1));\n\n    EXPECT_FALSE(base.GetPayload(kUrl1).has_value());\n    EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());\n  }\n}\n\nTEST(Status, CopyConstructor) {\n  {\n    absl::Status status;\n    absl::Status copy(status);\n    EXPECT_EQ(copy, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    absl::Status copy(status);\n    EXPECT_EQ(copy, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    status.SetPayload(kUrl1, absl::Cord(kPayload1));\n    absl::Status copy(status);\n    EXPECT_EQ(copy, status);\n  }\n}\n\nTEST(Status, CopyAssignment) {\n  absl::Status assignee;\n  {\n    absl::Status status;\n    assignee = status;\n    EXPECT_EQ(assignee, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    assignee = status;\n    EXPECT_EQ(assignee, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    status.SetPayload(kUrl1, absl::Cord(kPayload1));\n    assignee = status;\n    EXPECT_EQ(assignee, status);\n  }\n}\n\nTEST(Status, CopyAssignmentIsNotRef) {\n  const absl::Status status_orig(absl::StatusCode::kInvalidArgument, \"message\");\n  absl::Status status_copy = status_orig;\n  EXPECT_EQ(status_orig, status_copy);\n  status_copy.SetPayload(kUrl1, absl::Cord(kPayload1));\n  EXPECT_NE(status_orig, status_copy);\n}\n\nTEST(Status, MoveConstructor) {\n  {\n    absl::Status status;\n    absl::Status copy(absl::Status{});\n    EXPECT_EQ(copy, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    absl::Status copy(\n        absl::Status(absl::StatusCode::kInvalidArgument, \"message\"));\n    EXPECT_EQ(copy, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    status.SetPayload(kUrl1, absl::Cord(kPayload1));\n    absl::Status copy1(status);\n    absl::Status copy2(std::move(status));\n    EXPECT_EQ(copy1, copy2);\n  }\n}\n\nTEST(Status, MoveAssignment) {\n  absl::Status assignee;\n  {\n    absl::Status status;\n    assignee = absl::Status();\n    EXPECT_EQ(assignee, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    assignee = absl::Status(absl::StatusCode::kInvalidArgument, \"message\");\n    EXPECT_EQ(assignee, status);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    status.SetPayload(kUrl1, absl::Cord(kPayload1));\n    absl::Status copy(status);\n    assignee = std::move(status);\n    EXPECT_EQ(assignee, copy);\n  }\n  {\n    absl::Status status(absl::StatusCode::kInvalidArgument, \"message\");\n    absl::Status copy(status);\n    assignee = static_cast<absl::Status&&>(status);\n    EXPECT_EQ(assignee, copy);\n  }\n}\n\nTEST(Status, Update) {\n  absl::Status s;\n  s.Update(absl::OkStatus());\n  EXPECT_TRUE(s.ok());\n  const absl::Status a(absl::StatusCode::kCancelled, \"message\");\n  s.Update(a);\n  EXPECT_EQ(s, a);\n  const absl::Status b(absl::StatusCode::kInternal, \"other message\");\n  s.Update(b);\n  EXPECT_EQ(s, a);\n  s.Update(absl::OkStatus());\n  EXPECT_EQ(s, a);\n  EXPECT_FALSE(s.ok());\n}\n\nTEST(Status, Equality) {\n  absl::Status ok;\n  absl::Status no_payload = absl::CancelledError(\"no payload\");\n  absl::Status one_payload = absl::InvalidArgumentError(\"one payload\");\n  one_payload.SetPayload(kUrl1, absl::Cord(kPayload1));\n  absl::Status two_payloads = one_payload;\n  two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2));\n  const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload,\n                                                  two_payloads};\n  for (int i = 0; i < status_arr.size(); i++) {\n    for (int j = 0; j < status_arr.size(); j++) {\n      if (i == j) {\n        EXPECT_TRUE(status_arr[i] == status_arr[j]);\n        EXPECT_FALSE(status_arr[i] != status_arr[j]);\n      } else {\n        EXPECT_TRUE(status_arr[i] != status_arr[j]);\n        EXPECT_FALSE(status_arr[i] == status_arr[j]);\n      }\n    }\n  }\n}\n\nTEST(Status, Swap) {\n  auto test_swap = [](const absl::Status& s1, const absl::Status& s2) {\n    absl::Status copy1 = s1, copy2 = s2;\n    swap(copy1, copy2);\n    EXPECT_EQ(copy1, s2);\n    EXPECT_EQ(copy2, s1);\n  };\n  const absl::Status ok;\n  const absl::Status no_payload(absl::StatusCode::kAlreadyExists, \"no payload\");\n  absl::Status with_payload(absl::StatusCode::kInternal, \"with payload\");\n  with_payload.SetPayload(kUrl1, absl::Cord(kPayload1));\n  test_swap(ok, no_payload);\n  test_swap(no_payload, ok);\n  test_swap(ok, with_payload);\n  test_swap(with_payload, ok);\n  test_swap(no_payload, with_payload);\n  test_swap(with_payload, no_payload);\n}\n\nTEST(StatusErrno, ErrnoToStatusCode) {\n  EXPECT_EQ(absl::ErrnoToStatusCode(0), absl::StatusCode::kOk);\n\n  // Spot-check a few errno values.\n  EXPECT_EQ(absl::ErrnoToStatusCode(EINVAL),\n            absl::StatusCode::kInvalidArgument);\n  EXPECT_EQ(absl::ErrnoToStatusCode(ENOENT), absl::StatusCode::kNotFound);\n\n  // We'll pick a very large number so it hopefully doesn't collide to errno.\n  EXPECT_EQ(absl::ErrnoToStatusCode(19980927), absl::StatusCode::kUnknown);\n}\n\nTEST(StatusErrno, ErrnoToStatus) {\n  absl::Status status = absl::ErrnoToStatus(ENOENT, \"Cannot open 'path'\");\n  EXPECT_EQ(status.code(), absl::StatusCode::kNotFound);\n  EXPECT_EQ(status.message(), \"Cannot open 'path': No such file or directory\");\n}\n\n#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE\n#define GET_SOURCE_LOCATION(offset) __builtin_LINE() - offset\n#else\n#define GET_SOURCE_LOCATION(offset) 1\n#endif\n\nvoid CheckSourceLocation(\n    const absl::Status& status, std::vector<int> lines = {},\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  ASSERT_EQ(status.GetSourceLocations().size(), lines.size())\n      << \"Size check failed at \" << loc.line();\n  for (size_t i = 0; i < lines.size(); ++i) {\n    EXPECT_EQ(absl::string_view(status.GetSourceLocations()[i].file_name()),\n              absl::string_view(loc.file_name()))\n        << \"File name check failed at \" << loc.line();\n    EXPECT_EQ(status.GetSourceLocations()[i].line(), lines[i])\n        << \"Line check failed at \" << loc.line();\n  }\n}\n\nTEST(Status, ConstructorCheckSourceLocation) {\n  {\n    const absl::Status a;\n    const absl::Status b = a;\n    for (const absl::Status& status : {a, b}) {\n      EXPECT_TRUE(status.ok());\n      EXPECT_EQ(absl::StatusCode::kOk, status.code());\n      CheckSourceLocation(status);\n    }\n  }\n  {\n    const absl::Status a(absl::StatusCode::kInternal, \"message\",\n                         absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    const absl::Status b = a;\n    for (const absl::Status& status : {a, b}) {\n      EXPECT_FALSE(status.ok());\n      EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n      CheckSourceLocation(status, {line});\n    }\n  }\n  {\n    const absl::Status a(absl::StatusCode::kInternal, \"message\",\n                         absl::SourceLocation());\n    const absl::Status b = a;\n    for (const absl::Status& status : {a, b}) {\n      EXPECT_FALSE(status.ok());\n      EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n      CheckSourceLocation(status);\n    }\n  }\n  {\n    const absl::Status a(absl::StatusCode::kInternal, \"\",\n                         absl::SourceLocation::current());\n    const absl::Status b = a;\n    for (const absl::Status& status : {a, b}) {\n      EXPECT_FALSE(status.ok());\n      EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n      CheckSourceLocation(status);\n    }\n  }\n  {\n    const absl::Status a(absl::StatusCode::kInternal, \"\",\n                         absl::SourceLocation());\n    const absl::Status b = a;\n    for (const absl::Status& status : {a, b}) {\n      EXPECT_FALSE(status.ok());\n      EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n      CheckSourceLocation(status);\n    }\n  }\n}\n\nTEST(Status, SourceLocationConstructor) {\n  {\n    // OK status doesn't save source locations.\n    const absl::Status original;\n    const absl::Status status(original, absl::SourceLocation());\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kOk, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // OK status doesn't save source locations.\n    const absl::Status original;\n    const absl::Status status(original, absl::SourceLocation::current());\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kOk, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-ok Status with non-empty msg can save source locations with\n    // non-nullptr filename.\n    const absl::Status original(absl::StatusCode::kInternal, \"message\",\n                                absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    // Default absl::SourceLocation cannot be saved into the chain.\n    const absl::Status status(original, absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status, {line});\n  }\n  {\n    const absl::Status original(absl::StatusCode::kInternal, \"message\",\n                                absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n\n    const absl::Status status(original, absl::SourceLocation::current());\n    int line2 = GET_SOURCE_LOCATION(1);\n\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status, {line, line2});\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations.\n    const absl::Status original(absl::StatusCode::kInternal, \"\",\n                                absl::SourceLocation::current());\n    const absl::Status status(original, absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations.\n    const absl::Status original(absl::StatusCode::kInternal, \"\",\n                                absl::SourceLocation::current());\n    const absl::Status status(original, absl::SourceLocation::current());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations from default\n    // constructor.\n    const absl::Status original(absl::StatusCode::kInternal, \"\",\n                                absl::SourceLocation());\n    const absl::Status status(original, absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations.\n    const absl::Status original(absl::StatusCode::kInternal, \"\",\n                                absl::SourceLocation());\n    const absl::Status status(original, absl::SourceLocation::current());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    const absl::Status original(absl::StatusCode::kInternal, \"message\",\n                                absl::SourceLocation());\n    const absl::Status status(original, absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    const absl::Status original(absl::StatusCode::kInternal, \"message\",\n                                absl::SourceLocation());\n    const absl::Status status(original, absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status, {line});\n  }\n}\n\nTEST(Status, SourceLocationWithMoveConstructor) {\n  {\n    // OK status doesn't save source locations.\n    absl::Status original;\n    const absl::Status status(std::move(original), absl::SourceLocation());\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kOk, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // OK status doesn't save source locations.\n    absl::Status original;\n    const absl::Status status(std::move(original),\n                              absl::SourceLocation::current());\n    EXPECT_TRUE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kOk, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-ok Status with non-empty msg can save source locations with\n    // non-nullptr filename.\n    absl::Status original(absl::StatusCode::kInternal, \"message\",\n                          absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    // Default absl::SourceLocation cannot be saved into the chain.\n    const absl::Status status(std::move(original), absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status, {line});\n  }\n  {\n    absl::Status original(absl::StatusCode::kInternal, \"message\",\n                          absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n\n    const absl::Status status(std::move(original),\n                              absl::SourceLocation::current());\n    int line2 = GET_SOURCE_LOCATION(1);\n\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status, {line, line2});\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations.\n    absl::Status original(absl::StatusCode::kInternal, \"\",\n                          absl::SourceLocation::current());\n    const absl::Status status(std::move(original), absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations.\n    absl::Status original(absl::StatusCode::kInternal, \"\",\n                          absl::SourceLocation::current());\n    const absl::Status status(std::move(original),\n                              absl::SourceLocation::current());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations from default\n    // constructor.\n    absl::Status original(absl::StatusCode::kInternal, \"\",\n                          absl::SourceLocation());\n    const absl::Status status(std::move(original), absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    // Non-OK status with empty msg doesn't save source locations.\n    absl::Status original(absl::StatusCode::kInternal, \"\",\n                          absl::SourceLocation());\n    const absl::Status status(std::move(original),\n                              absl::SourceLocation::current());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    absl::Status original(absl::StatusCode::kInternal, \"message\",\n                          absl::SourceLocation());\n    const absl::Status status(std::move(original), absl::SourceLocation());\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status);\n  }\n  {\n    absl::Status original(absl::StatusCode::kInternal, \"message\",\n                          absl::SourceLocation());\n    const absl::Status status(std::move(original),\n                              absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    EXPECT_FALSE(status.ok());\n    EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n    CheckSourceLocation(status, {line});\n  }\n}\n\nTEST(Status, AddSourceLocation) {\n  int max_iter = 10;\n  {\n    // Status that ignores source location.\n    absl::Status status_ignores_source_location[] = {\n        absl::Status(),\n        absl::Status(absl::StatusCode::kInternal, \"\")};\n    for (absl::Status& s : status_ignores_source_location) {\n      for (int i = 0; i < max_iter; ++i) {\n        s.AddSourceLocation(absl::SourceLocation::current());\n        s.AddSourceLocation(absl::SourceLocation());\n      }\n      CheckSourceLocation(s);\n    }\n  }\n  {\n    // Default SourceLocation is not added.\n    absl::Status status(absl::StatusCode::kInternal, \"foo\",\n                        absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    for (int i = 0; i < max_iter; ++i) {\n      status.AddSourceLocation(absl::SourceLocation());\n    }\n    CheckSourceLocation(status, {line});\n  }\n  {\n    // Default SourceLocation is not added.\n    absl::Status status(absl::StatusCode::kInternal, \"foo\",\n                        absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    std::vector<int> lines = {line};\n    lines.reserve(1 + max_iter);\n    for (int i = 0; i < max_iter; ++i) {\n      status.AddSourceLocation(absl::SourceLocation::current());\n      lines.push_back(GET_SOURCE_LOCATION(1));\n    }\n    CheckSourceLocation(status, lines);\n  }\n}\n\nTEST(Status, WithSourceLocationCopy) {\n  absl::Status original(absl::StatusCode::kInternal, \"message\",\n                        absl::SourceLocation::current());\n  int line = GET_SOURCE_LOCATION(1);\n\n  const absl::Status status =\n      original.WithSourceLocation(absl::SourceLocation::current());\n  int line2 = GET_SOURCE_LOCATION(1);\n\n  CheckSourceLocation(original, {line});\n  CheckSourceLocation(status, {line, line2});\n  EXPECT_EQ(original, status);\n}\n\nabsl::Status&& IsRvalueStatus(absl::Status&& s) { return std::move(s); }\n\nTEST(Status, WithSourceLocationMove) {\n  absl::Status original(absl::StatusCode::kInternal, \"message\",\n                        absl::SourceLocation::current());\n  int line = GET_SOURCE_LOCATION(1);\n\n  const absl::Status status = IsRvalueStatus(\n      std::move(original).WithSourceLocation(absl::SourceLocation::current()));\n  int line2 = GET_SOURCE_LOCATION(1);\n\n  CheckSourceLocation(status, {line, line2});\n  EXPECT_FALSE(status.ok());\n  EXPECT_EQ(absl::StatusCode::kInternal, status.code());\n}\n\nTEST(Status, CopyOnWriteSourceLocations) {\n  absl::Status source(absl::StatusCode::kInvalidArgument, \"fail\",\n                      absl::SourceLocation::current());\n  EXPECT_EQ(source.GetSourceLocations().size(), 1);\n  absl::Status copy = source;\n  EXPECT_EQ(copy.GetSourceLocations().size(), 1);\n  copy.AddSourceLocation(absl::SourceLocation::current());  // Copy rep.\n  EXPECT_EQ(copy.GetSourceLocations().size(), 2);\n  EXPECT_EQ(source.GetSourceLocations().size(), 1);\n}\n\nTEST(Status, SourceLocationToStringMode) {\n  absl::Status s(absl::StatusCode::kInternal, \"fail\",\n                 absl::SourceLocation::current());\n  int line = GET_SOURCE_LOCATION(1);\n  std::string source_location_string = \"\\n=== Source Location Trace: ===\";\n  std::string source_location_stack = absl::StrCat(\n      absl::SourceLocation::current().file_name(), \":\", line, \"\\n\");\n\n  s.SetPayload(\"foo\", absl::Cord(\"bar\"));\n\n  EXPECT_EQ(\"INTERNAL: fail\",\n            s.ToString(absl::StatusToStringMode::kWithNoExtraData));\n\n  EXPECT_EQ(\"INTERNAL: fail\",\n            s.ToString(~absl::StatusToStringMode::kWithSourceLocation &\n                       ~absl::StatusToStringMode::kWithPayload));\n  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithSourceLocation |\n                         absl::StatusToStringMode::kWithPayload),\n              AllOf(HasSubstr(\"INTERNAL: fail [foo='bar']\"),\n                    HasSubstr(source_location_string),\n                    HasSubstr(source_location_stack)));\n\n  s.SetPayload(\"bar\", absl::Cord(\"\\377\"));\n\n  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\"),\n                    HasSubstr(source_location_string),\n                    HasSubstr(source_location_stack)));\n  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload |\n                         absl::StatusToStringMode::kWithSourceLocation),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\"),\n                    HasSubstr(source_location_string),\n                    HasSubstr(source_location_stack)));\n  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithSourceLocation),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), Not(HasSubstr(\"[foo='bar']\")),\n                    Not(HasSubstr(\"[bar='\\\\xff']\")),\n                    HasSubstr(source_location_string),\n                    HasSubstr(source_location_stack)));\n  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload),\n              AllOf(HasSubstr(\"INTERNAL: fail\"), HasSubstr(\"[foo='bar']\"),\n                    HasSubstr(\"[bar='\\\\xff']\"),\n                    Not(HasSubstr(source_location_string)),\n                    Not(HasSubstr(source_location_stack))));\n}\n\nTEST(Status, StackTracePayloadOverflow) {\n  // Stack must have the same layout as status_internal::StackTracePayload.\n  struct Stack {\n    size_t size;\n    void* frames[20];\n  } stack;\n  stack.size = 200;  // Overflows frames.\n\n  absl::Status status = absl::CancelledError();\n  status.SetPayload(\"AbslStatusStackTracePayload\",\n                    absl::Cord(absl::string_view(\n                        reinterpret_cast<const char*>(&stack), sizeof(stack))));\n\n  // An unchecked overflow should be detected by ASAN/MSAN on the next line.\n  static_cast<void>(status.ToString(absl::StatusToStringMode::kWithEverything));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/status/statusor.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/status/statusor.h\"\n\n#include <cstdlib>\n#include <utility>\n\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/status/internal/statusor_internal.h\"\n#include \"absl/status/status.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nBadStatusOrAccess::BadStatusOrAccess(absl::Status status)\n    : status_(std::move(status)) {}\n\nBadStatusOrAccess::BadStatusOrAccess(const BadStatusOrAccess& other)\n    : status_(other.status_) {}\n\nBadStatusOrAccess& BadStatusOrAccess::operator=(\n    const BadStatusOrAccess& other) {\n  // Ensure assignment is correct regardless of whether this->InitWhat() has\n  // already been called.\n  other.InitWhat();\n  status_ = other.status_;\n  what_ = other.what_;\n  return *this;\n}\n\nBadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) {\n  // Ensure assignment is correct regardless of whether this->InitWhat() has\n  // already been called.\n  other.InitWhat();\n  status_ = std::move(other.status_);\n  what_ = std::move(other.what_);\n  return *this;\n}\n\nBadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)\n    : status_(std::move(other.status_)) {}\n\nconst char* absl_nonnull BadStatusOrAccess::what() const noexcept {\n  InitWhat();\n  return what_.c_str();\n}\n\nconst absl::Status& BadStatusOrAccess::status() const { return status_; }\n\nvoid BadStatusOrAccess::InitWhat() const {\n  absl::call_once(init_what_, [this] {\n    what_ = absl::StrCat(\"Bad StatusOr access: \", status_.ToString());\n  });\n}\n\nnamespace internal_statusor {\n\nvoid Helper::HandleInvalidStatusCtorArg(absl::Status* absl_nonnull status) {\n  const char* kMessage =\n      \"An OK status is not a valid constructor argument to StatusOr<T>\";\n#ifdef NDEBUG\n  ABSL_INTERNAL_LOG(ERROR, kMessage);\n#else\n  ABSL_INTERNAL_LOG(FATAL, kMessage);\n#endif\n  // In optimized builds, we will fall back to InternalError.\n  *status = absl::InternalError(kMessage);\n}\n\nvoid Helper::Crash(const absl::Status& status) {\n  ABSL_INTERNAL_LOG(\n      FATAL,\n      absl::StrCat(\"Attempting to fetch value instead of handling error \",\n                   status.ToString()));\n}\n\nvoid ThrowBadStatusOrAccess(absl::Status status) {\n#ifdef ABSL_HAVE_EXCEPTIONS\n  throw absl::BadStatusOrAccess(std::move(status));\n#else\n  ABSL_INTERNAL_LOG(\n      FATAL,\n      absl::StrCat(\"Attempting to fetch value instead of handling error \",\n                   status.ToString()));\n  std::abort();\n#endif\n}\n\n}  // namespace internal_statusor\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/status/statusor.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: statusor.h\n// -----------------------------------------------------------------------------\n//\n// An `absl::StatusOr<T>` represents a union of an `absl::Status` object\n// and an object of type `T`. The `absl::StatusOr<T>` will either contain an\n// object of type `T` (indicating a successful operation), or an error (of type\n// `absl::Status`) explaining why such a value is not present.\n//\n// In general, check the success of an operation returning an\n// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()`\n// member function.\n//\n// Example:\n//\n//   StatusOr<Foo> result = Calculation();\n//   if (result.ok()) {\n//     result->DoSomethingCool();\n//   } else {\n//     LOG(ERROR) << result.status();\n//   }\n#ifndef ABSL_STATUS_STATUSOR_H_\n#define ABSL_STATUS_STATUSOR_H_\n\n#include <exception>\n#include <initializer_list>\n#include <new>\n#include <ostream>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <variant>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/status/internal/statusor_internal.h\"\n#include \"absl/status/status.h\"\n#include \"absl/strings/has_absl_stringify.h\"\n#include \"absl/strings/has_ostream_operator.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/types/span.h\"\n#include \"absl/types/variant.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// BadStatusOrAccess\n//\n// This class defines the type of object to throw (if exceptions are enabled),\n// when accessing the value of an `absl::StatusOr<T>` object that does not\n// contain a value. This behavior is analogous to that of\n// `std::bad_optional_access` in the case of accessing an invalid\n// `std::optional` value.\n//\n// Example:\n//\n// try {\n//   absl::StatusOr<int> v = FetchInt();\n//   DoWork(v.value());  // Accessing value() when not \"OK\" may throw\n// } catch (absl::BadStatusOrAccess& ex) {\n//   LOG(ERROR) << ex.status();\n// }\nclass BadStatusOrAccess : public std::exception {\n public:\n  explicit BadStatusOrAccess(absl::Status status);\n  ~BadStatusOrAccess() override = default;\n\n  BadStatusOrAccess(const BadStatusOrAccess& other);\n  BadStatusOrAccess& operator=(const BadStatusOrAccess& other);\n  BadStatusOrAccess(BadStatusOrAccess&& other);\n  BadStatusOrAccess& operator=(BadStatusOrAccess&& other);\n\n  // BadStatusOrAccess::what()\n  //\n  // Returns the associated explanatory string of the `absl::StatusOr<T>`\n  // object's error code. This function contains information about the failing\n  // status, but its exact formatting may change and should not be depended on.\n  //\n  // The pointer of this string is guaranteed to be valid until any non-const\n  // function is invoked on the exception object.\n  const char* absl_nonnull what() const noexcept override;\n\n  // BadStatusOrAccess::status()\n  //\n  // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's\n  // error.\n  const absl::Status& status() const;\n\n private:\n  void InitWhat() const;\n\n  absl::Status status_;\n  mutable absl::once_flag init_what_;\n  mutable std::string what_;\n};\n\n// Returned StatusOr objects may not be ignored.\ntemplate <typename T>\n#if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard)\n// TODO(b/176172494): ABSL_MUST_USE_RESULT should expand to the more strict\n// [[nodiscard]]. For now, just use [[nodiscard]] directly when it is available.\nclass [[nodiscard]] StatusOr;\n#else\nclass ABSL_MUST_USE_RESULT StatusOr;\n#endif  // ABSL_HAVE_CPP_ATTRIBUTE(nodiscard)\n\n// absl::StatusOr<T>\n//\n// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object\n// and an object of type `T`. The `absl::StatusOr<T>` models an object that is\n// either a usable object, or an error (of type `absl::Status`) explaining why\n// such an object is not present. An `absl::StatusOr<T>` is typically the return\n// value of a function which may fail.\n//\n// An `absl::StatusOr<T>` can never hold an \"OK\" status (an\n// `absl::StatusCode::kOk` value); instead, the presence of an object of type\n// `T` indicates success. Instead of checking for a `kOk` value, use the\n// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code\n// readability, that using the `ok()` function is preferred for `absl::Status`\n// as well.)\n//\n// Example:\n//\n//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();\n//   if (result.ok()) {\n//     result->DoSomethingCool();\n//   } else {\n//     LOG(ERROR) << result.status();\n//   }\n//\n// Accessing the object held by an `absl::StatusOr<T>` should be performed via\n// `operator*` or `operator->`, after a call to `ok()` confirms that the\n// `absl::StatusOr<T>` holds an object of type `T`:\n//\n// Example:\n//\n//   absl::StatusOr<int> i = GetCount();\n//   if (i.ok()) {\n//     updated_total += *i;\n//   }\n//\n// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will\n// throw an exception if exceptions are enabled or terminate the process when\n// exceptions are not enabled.\n//\n// Example:\n//\n//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();\n//   const Foo& foo = result.value();    // Crash/exception if no value present\n//   foo.DoSomethingCool();\n//\n// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other\n// pointer value, and the result will be that `ok()` returns `true` and\n// `value()` returns `nullptr`. Checking the value of pointer in an\n// `absl::StatusOr<T*>` generally requires a bit more care, to ensure both that\n// a value is present and that value is not null:\n//\n//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);\n//  if (!result.ok()) {\n//    LOG(ERROR) << result.status();\n//  } else if (*result == nullptr) {\n//    LOG(ERROR) << \"Unexpected null pointer\";\n//  } else {\n//    (*result)->DoSomethingCool();\n//  }\n//\n// Example factory implementation returning StatusOr<T>:\n//\n//  StatusOr<Foo> FooFactory::MakeFoo(int arg) {\n//    if (arg <= 0) {\n//      return absl::Status(absl::StatusCode::kInvalidArgument,\n//                          \"Arg must be positive\");\n//    }\n//    return Foo(arg);\n//  }\ntemplate <typename T>\nclass StatusOr : private internal_statusor::OperatorBase<T>,\n                 private internal_statusor::StatusOrData<T>,\n                 private internal_statusor::CopyCtorBase<T>,\n                 private internal_statusor::MoveCtorBase<T>,\n                 private internal_statusor::CopyAssignBase<T>,\n                 private internal_statusor::MoveAssignBase<T> {\n#ifndef SWIG\n  static_assert(!std::is_rvalue_reference_v<T>,\n                \"rvalue references are not yet supported.\");\n#endif  // SWIG\n\n  template <typename U>\n  friend class StatusOr;\n\n  friend internal_statusor::OperatorBase<T>;\n\n  typedef internal_statusor::StatusOrData<T> Base;\n\n public:\n  // StatusOr<T>::value_type\n  //\n  // This instance data provides a generic `value_type` member for use within\n  // generic programming. This usage is analogous to that of\n  // `optional::value_type` in the case of `std::optional`.\n  typedef T value_type;\n\n  // Constructors\n\n  // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown`\n  // status. This constructor is marked 'explicit' to prevent usages in return\n  // values such as 'return {};', under the misconception that\n  // `absl::StatusOr<std::vector<int>>` will be initialized with an empty\n  // vector, instead of an `absl::StatusCode::kUnknown` error code.\n  explicit StatusOr();\n\n  // `StatusOr<T>` is copy constructible if `T` is copy constructible.\n  StatusOr(const StatusOr&) = default;\n  // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy\n  // assignable.\n  StatusOr& operator=(const StatusOr&) = default;\n\n  // `StatusOr<T>` is move constructible if `T` is move constructible.\n  StatusOr(StatusOr&&) = default;\n  // `StatusOr<T>` is moveAssignable if `T` is move constructible and move\n  // assignable.\n  StatusOr& operator=(StatusOr&&) = default;\n\n  // Converting Constructors\n\n  // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T`\n  // is constructible from `U`. To avoid ambiguity, these constructors are\n  // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor\n  // is explicit if and only if the corresponding construction of `T` from `U`\n  // is explicit. (This constructor inherits its explicitness from the\n  // underlying constructor.)\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                false, T, U, false, const U&>::value,\n                            int> = 0>\n  StatusOr(const StatusOr<U>& other)  // NOLINT\n      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                false, T, U, true, const U&>::value,\n                            int> = 0>\n  StatusOr(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT\n      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                true, T, U, false, const U&>::value,\n                            int> = 0>\n  explicit StatusOr(const StatusOr<U>& other)\n      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                true, T, U, true, const U&>::value,\n                            int> = 0>\n  explicit StatusOr(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}\n\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                false, T, U, false, U&&>::value,\n                            int> = 0>\n  StatusOr(StatusOr<U>&& other)  // NOLINT\n      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                false, T, U, true, U&&>::value,\n                            int> = 0>\n  StatusOr(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT\n      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                true, T, U, false, U&&>::value,\n                            int> = 0>\n  explicit StatusOr(StatusOr<U>&& other)\n      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}\n  template <typename U, absl::enable_if_t<\n                            internal_statusor::IsConstructionFromStatusOrValid<\n                                true, T, U, true, U&&>::value,\n                            int> = 0>\n  explicit StatusOr(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}\n\n  // Converting Assignment Operators\n\n  // Creates an `absl::StatusOr<T>` through assignment from an\n  // `absl::StatusOr<U>` when:\n  //\n  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning\n  //     `U` to `T` directly.\n  //   * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error\n  //      code by destroying `absl::StatusOr<T>`'s value and assigning from\n  //      `absl::StatusOr<U>'\n  //   * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is\n  //      OK by directly initializing `T` from `U`.\n  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error\n  //     code by assigning the `Status` in `absl::StatusOr<U>` to\n  //     `absl::StatusOr<T>`\n  //\n  // These overloads only apply if `absl::StatusOr<T>` is constructible and\n  // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly\n  // assigned from `StatusOr<U>`.\n  template <typename U,\n            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<\n                                  T, const U&, false>::value,\n                              int> = 0>\n  StatusOr& operator=(const StatusOr<U>& other) {\n    this->Assign(other);\n    return *this;\n  }\n  template <typename U,\n            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<\n                                  T, const U&, true>::value,\n                              int> = 0>\n  StatusOr& operator=(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n    this->Assign(other);\n    return *this;\n  }\n  template <typename U,\n            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<\n                                  T, U&&, false>::value,\n                              int> = 0>\n  StatusOr& operator=(StatusOr<U>&& other) {\n    this->Assign(std::move(other));\n    return *this;\n  }\n  template <typename U,\n            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<\n                                  T, U&&, true>::value,\n                              int> = 0>\n  StatusOr& operator=(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n    this->Assign(std::move(other));\n    return *this;\n  }\n\n  // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling\n  // this constructor, `this->ok()` will be `false` and calls to `value()` will\n  // crash, or produce an exception if exceptions are enabled.\n  //\n  // The constructor also takes any type `U` that is convertible to\n  // `absl::Status`. This constructor is explicit if an only if `U` is not of\n  // type `absl::Status` and the conversion from `U` to `Status` is explicit.\n  //\n  // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.\n  // In optimized builds, passing absl::OkStatus() here will have the effect\n  // of passing absl::StatusCode::kInternal as a fallback.\n  template <typename U = absl::Status,\n            absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid<\n                                  false, T, U>::value,\n                              int> = 0>\n  StatusOr(U&& v) : Base(std::forward<U>(v)) {}\n\n  template <typename U = absl::Status,\n            absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid<\n                                  true, T, U>::value,\n                              int> = 0>\n  explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}\n  template <typename U = absl::Status,\n            absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid<\n                                  false, T, U>::value,\n                              int> = 0>\n  StatusOr& operator=(U&& v) {\n    this->AssignStatus(std::forward<U>(v));\n    return *this;\n  }\n\n  // Perfect-forwarding value assignment operator.\n\n  // If `*this` contains a `T` value before the call, the contained value is\n  // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized\n  // from `std::forward<U>(v)`.\n  // This function does not participate in overload unless:\n  // 1. `std::is_constructible_v<T, U>` is true,\n  // 2. `std::is_assignable_v<T&, U>` is true.\n  // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false.\n  // 4. Assigning `U` to `T` is not ambiguous:\n  //  If `U` is `StatusOr<V>` and `T` is constructible and assignable from\n  //  both `StatusOr<V>` and `V`, the assignment is considered bug-prone and\n  //  ambiguous thus will fail to compile. For example:\n  //    StatusOr<bool> s1 = true;  // s1.ok() && *s1 == true\n  //    StatusOr<bool> s2 = false;  // s2.ok() && *s2 == false\n  //    s1 = s2;  // ambiguous, `s1 = *s2` or `s1 = bool(s2)`?\n  template <typename U = T,\n            typename std::enable_if<\n                internal_statusor::IsAssignmentValid<T, U, false>::value,\n                int>::type = 0>\n  StatusOr& operator=(U&& v) {\n    this->Assign(std::forward<U>(v));\n    return *this;\n  }\n  template <typename U = T,\n            typename std::enable_if<\n                internal_statusor::IsAssignmentValid<T, U, true>::value,\n                int>::type = 0>\n  StatusOr& operator=(U&& v ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)) {\n    this->Assign(std::forward<U>(v));\n    return *this;\n  }\n\n  // Constructs the inner value `T` in-place using the provided args, using the\n  // `T(args...)` constructor.\n  template <typename... Args>\n  explicit StatusOr(absl::in_place_t, Args&&... args);\n  template <typename U, typename... Args>\n  explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,\n                    Args&&... args);\n\n  // Constructs the inner value `T` in-place using the provided args, using the\n  // `T(U)` (direct-initialization) constructor. This constructor is only valid\n  // if `T` can be constructed from a `U`. Can accept move or copy constructors.\n  //\n  // This constructor is explicit if `U` is not convertible to `T`. To avoid\n  // ambiguity, this constructor is disabled if `U` is a `StatusOr<J>`, where\n  // `J` is convertible to `T`.\n  template <typename U = T,\n            absl::enable_if_t<internal_statusor::IsConstructionValid<\n                                  false, T, U, false>::value,\n                              int> = 0>\n  StatusOr(U&& u)  // NOLINT\n      : StatusOr(absl::in_place, std::forward<U>(u)) {}\n  template <typename U = T,\n            absl::enable_if_t<internal_statusor::IsConstructionValid<\n                                  false, T, U, true>::value,\n                              int> = 0>\n  StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT\n      : StatusOr(absl::in_place, std::forward<U>(u)) {}\n\n  template <typename U = T,\n            absl::enable_if_t<internal_statusor::IsConstructionValid<\n                                  true, T, U, false>::value,\n                              int> = 0>\n  explicit StatusOr(U&& u)  // NOLINT\n      : StatusOr(absl::in_place, std::forward<U>(u)) {}\n  template <typename U = T,\n            absl::enable_if_t<\n                internal_statusor::IsConstructionValid<true, T, U, true>::value,\n                int> = 0>\n  explicit StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT\n      : StatusOr(absl::in_place, std::forward<U>(u)) {}\n\n  // StatusOr<T>::ok()\n  //\n  // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This\n  // member function is analogous to `absl::Status::ok()` and should be used\n  // similarly to check the status of return values.\n  //\n  // Example:\n  //\n  // StatusOr<Foo> result = DoBigCalculationThatCouldFail();\n  // if (result.ok()) {\n  //    // Handle result\n  // else {\n  //    // Handle error\n  // }\n  ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }\n\n  // StatusOr<T>::status()\n  //\n  // Returns a reference to the current `absl::Status` contained within the\n  // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this\n  // function returns `absl::OkStatus()`.\n  ABSL_MUST_USE_RESULT const Status& status() const&;\n  Status status() &&;\n\n  absl::Span<const absl::SourceLocation> GetSourceLocations() const {\n    return this->status_.GetSourceLocations();\n  }\n  // Appends the `loc` to the current location chain inside the status, iff the\n  // status-or is non-ok and contains a non-empty message.\n  void AddSourceLocation(\n      absl::SourceLocation loc = absl::SourceLocation::current()) {\n    this->status_.AddSourceLocation(loc);\n  }\n\n  // StatusOr<T>::WithSourceLocation()\n  //\n  // Appends the `loc` to the current location chain inside the status iff the\n  // status-or is non-ok and contains a non-empty message, and returns an rvalue\n  // reference to `*this`.\n  //\n  // Example:\n  //\n  //   StatusOr<int> Finalize(...);\n  //\n  //   StatusOr<int> DoSomething(...) {\n  //     ...\n  //     return Finalize().WithSourceLocation();\n  //   }\n  ABSL_MUST_USE_RESULT StatusOr<T>&& WithSourceLocation(\n      absl::SourceLocation loc = absl::SourceLocation::current()) && {\n    AddSourceLocation(loc);\n    return std::move(*this);\n  }\n\n  // StatusOr<T>::value()\n  //\n  // Returns a reference to the held value if `this->ok()`. Otherwise, throws\n  // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to\n  // terminate the process if exceptions are disabled.\n  //\n  // If you have already checked the status using `this->ok()`, you probably\n  // want to use `operator*()` or `operator->()` to access the value instead of\n  // `value`.\n  //\n  // Note: for value types that are cheap to copy, prefer simple code:\n  //\n  //   T value = statusor.value();\n  //\n  // Otherwise, if the value type is expensive to copy, but can be left\n  // in the StatusOr, simply assign to a reference:\n  //\n  //   T& value = statusor.value();  // or `const T&`\n  //\n  // Otherwise, if the value type supports an efficient move, it can be\n  // used as follows:\n  //\n  //   T value = std::move(statusor).value();\n  //\n  // The `std::move` on statusor instead of on the whole expression enables\n  // warnings about possible uses of the statusor object after the move.\n  using StatusOr::OperatorBase::value;\n\n  // StatusOr<T>:: operator*()\n  //\n  // Returns a reference to the current value.\n  //\n  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.\n  //\n  // Use `this->ok()` to verify that there is a current value within the\n  // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a\n  // similar API that guarantees crashing or throwing an exception if there is\n  // no current value.\n  using StatusOr::OperatorBase::operator*;\n\n  // StatusOr<T>::operator->()\n  //\n  // Returns a pointer to the current value.\n  //\n  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.\n  //\n  // Use `this->ok()` to verify that there is a current value.\n  using StatusOr::OperatorBase::operator->;\n\n  // StatusOr<T>::value_or()\n  //\n  // Returns the current value if `this->ok() == true`. Otherwise constructs a\n  // value using the provided `default_value`.\n  //\n  // Unlike `value`, this function returns by value, copying the current value\n  // if necessary. If the value type supports an efficient move, it can be used\n  // as follows:\n  //\n  //   T value = std::move(statusor).value_or(def);\n  //\n  // Unlike with `value`, calling `std::move()` on the result of `value_or` will\n  // still trigger a copy.\n  template <\n      typename U,\n      std::enable_if_t<internal_statusor::IsValueOrValid<T, U&&, false>::value,\n                       int> = 0>\n  T value_or(U&& default_value) const& {\n    return this->ValueOrImpl(std::forward<U>(default_value));\n  }\n  template <\n      typename U,\n      std::enable_if_t<internal_statusor::IsValueOrValid<T, U&&, false>::value,\n                       int> = 0>\n  T value_or(U&& default_value) && {\n    return std::move(*this).ValueOrImpl(std::forward<U>(default_value));\n  }\n  template <\n      typename U,\n      std::enable_if_t<internal_statusor::IsValueOrValid<T, U&&, true>::value,\n                       int> = 0>\n  T value_or(U&& default_value ABSL_ATTRIBUTE_LIFETIME_BOUND) const& {\n    return this->ValueOrImpl(std::forward<U>(default_value));\n  }\n  template <\n      typename U,\n      std::enable_if_t<internal_statusor::IsValueOrValid<T, U&&, true>::value,\n                       int> = 0>\n  T value_or(U&& default_value ABSL_ATTRIBUTE_LIFETIME_BOUND) && {\n    return std::move(*this).ValueOrImpl(std::forward<U>(default_value));\n  }\n\n  // StatusOr<T>::IgnoreError()\n  //\n  // Ignores any errors. This method does nothing except potentially suppress\n  // complaints from any tools that are checking that errors are not dropped on\n  // the floor.\n  void IgnoreError() const;\n\n  // StatusOr<T>::emplace()\n  //\n  // Reconstructs the inner value T in-place using the provided args, using the\n  // T(args...) constructor. Returns reference to the reconstructed `T`.\n  template <typename... Args>\n  T& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ok()) {\n      this->Clear();\n      this->MakeValue(std::forward<Args>(args)...);\n    } else {\n      this->MakeValue(std::forward<Args>(args)...);\n      this->status_ = absl::OkStatus();\n    }\n    return this->data_;\n  }\n\n  template <\n      typename U, typename... Args,\n      absl::enable_if_t<\n          std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,\n          int> = 0>\n  T& emplace(std::initializer_list<U> ilist,\n             Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    if (ok()) {\n      this->Clear();\n      this->MakeValue(ilist, std::forward<Args>(args)...);\n    } else {\n      this->MakeValue(ilist, std::forward<Args>(args)...);\n      this->status_ = absl::OkStatus();\n    }\n    return this->data_;\n  }\n\n  // StatusOr<T>::AssignStatus()\n  //\n  // Sets the status of `absl::StatusOr<T>` to the given non-ok status value.\n  //\n  // NOTE: We recommend using the constructor and `operator=` where possible.\n  // This method is intended for use in generic programming, to enable setting\n  // the status of a `StatusOr<T>` when `T` may be `Status`. In that case, the\n  // constructor and `operator=` would assign into the inner value of type\n  // `Status`, rather than status of the `StatusOr` (b/280392796).\n  //\n  // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.\n  // In optimized builds, passing absl::OkStatus() here will have the effect\n  // of passing absl::StatusCode::kInternal as a fallback.\n  using internal_statusor::StatusOrData<T>::AssignStatus;\n\n private:\n  using internal_statusor::StatusOrData<T>::Assign;\n  template <typename U>\n  void Assign(const absl::StatusOr<U>& other);\n  template <typename U>\n  void Assign(absl::StatusOr<U>&& other);\n};\n\n// operator==()\n//\n// This operator checks the equality of two `absl::StatusOr<T>` objects.\ntemplate <typename T,\n          std::enable_if_t<internal_statusor::IsEqualityComparable<T>::value,\n                           int> = 0>\nbool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {\n  if (lhs.ok() && rhs.ok()) return *lhs == *rhs;\n  return lhs.status() == rhs.status();\n}\n\n// operator!=()\n//\n// This operator checks the inequality of two `absl::StatusOr<T>` objects.\ntemplate <typename T,\n          std::enable_if_t<internal_statusor::IsEqualityComparable<T>::value,\n                           int> = 0>\nbool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {\n  return !(lhs == rhs);\n}\n\n// Prints the `value` or the status in brackets to `os`.\n//\n// Requires `T` supports `operator<<`.  Do not rely on the output format which\n// may change without notice.\ntemplate <typename T, typename std::enable_if<\n                          absl::HasOstreamOperator<T>::value, int>::type = 0>\nstd::ostream& operator<<(std::ostream& os, const StatusOr<T>& status_or) {\n  if (status_or.ok()) {\n    os << status_or.value();\n  } else {\n    os << internal_statusor::StringifyRandom::OpenBrackets()\n       << status_or.status()\n       << internal_statusor::StringifyRandom::CloseBrackets();\n  }\n  return os;\n}\n\n// As above, but supports `StrCat`, `StrFormat`, etc.\n//\n// Requires `T` has `AbslStringify`.  Do not rely on the output format which\n// may change without notice.\ntemplate <\n    typename Sink, typename T,\n    typename std::enable_if<absl::HasAbslStringify<T>::value, int>::type = 0>\nvoid AbslStringify(Sink& sink, const StatusOr<T>& status_or) {\n  if (status_or.ok()) {\n    absl::Format(&sink, \"%v\", status_or.value());\n  } else {\n    absl::Format(&sink, \"%s%v%s\",\n                 internal_statusor::StringifyRandom::OpenBrackets(),\n                 status_or.status(),\n                 internal_statusor::StringifyRandom::CloseBrackets());\n  }\n}\n\n//------------------------------------------------------------------------------\n// Implementation details for StatusOr<T>\n//------------------------------------------------------------------------------\n\n// TODO(sbenza): avoid the string here completely.\ntemplate <typename T>\nStatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, \"\")) {}\n\ntemplate <typename T>\ntemplate <typename U>\ninline void StatusOr<T>::Assign(const StatusOr<U>& other) {\n  if (other.ok()) {\n    this->Assign(*other);\n  } else {\n    this->AssignStatus(other.status());\n  }\n}\n\ntemplate <typename T>\ntemplate <typename U>\ninline void StatusOr<T>::Assign(StatusOr<U>&& other) {\n  if (other.ok()) {\n    this->Assign(*std::move(other));\n  } else {\n    this->AssignStatus(std::move(other).status());\n  }\n}\ntemplate <typename T>\ntemplate <typename... Args>\nStatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)\n    : Base(absl::in_place, std::forward<Args>(args)...) {}\n\ntemplate <typename T>\ntemplate <typename U, typename... Args>\nStatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,\n                      Args&&... args)\n    : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}\n\ntemplate <typename T>\nconst Status& StatusOr<T>::status() const& {\n  return this->status_;\n}\ntemplate <typename T>\nStatus StatusOr<T>::status() && {\n  return ok() ? OkStatus() : std::move(this->status_);\n}\n\ntemplate <typename T>\nvoid StatusOr<T>::IgnoreError() const {\n  // no-op\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STATUS_STATUSOR_H_\n"
  },
  {
    "path": "absl/status/statusor_benchmark.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n\n#include \"absl/status/status.h\"\n#include \"absl/status/statusor.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_StatusOrInt_CtorStatus(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> status(absl::CancelledError());\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_CtorStatus);\n\nvoid BM_StatusOrInt_CtorStatusWithMessage(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_CtorStatusWithMessage);\n\nvoid BM_StatusOrInt_CopyCtor_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_CopyCtor_Error);\n\nvoid BM_StatusOrInt_CopyCtor_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(42);\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_CopyCtor_Ok);\n\nvoid BM_StatusOrInt_MoveCtor_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_MoveCtor_Error);\n\nvoid BM_StatusOrInt_MoveCtor_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(42);\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_MoveCtor_Ok);\n\nvoid BM_StatusOrInt_CopyAssign_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(42);\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_CopyAssign_Error);\n\nvoid BM_StatusOrInt_CopyAssign_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(42);\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(42);\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_CopyAssign_Ok);\n\nvoid BM_StatusOrInt_MoveAssign_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(42);\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_MoveAssign_Error);\n\nvoid BM_StatusOrInt_MoveAssign_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> original(42);\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<int> status(42);\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrInt_MoveAssign_Ok);\n\nvoid BM_StatusOrInt_OkMethod_Error(benchmark::State& state) {\n  absl::StatusOr<int> status(\n      absl::UnknownError(\"This string is 28 characters\"));\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.ok());\n  }\n}\nBENCHMARK(BM_StatusOrInt_OkMethod_Error);\n\nvoid BM_StatusOrInt_OkMethod_Ok(benchmark::State& state) {\n  absl::StatusOr<int> status(42);\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.ok());\n  }\n}\nBENCHMARK(BM_StatusOrInt_OkMethod_Ok);\n\nvoid BM_StatusOrInt_StatusMethod_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.status().ok());\n  }\n}\nBENCHMARK(BM_StatusOrInt_StatusMethod_Error);\n\nvoid BM_StatusOrInt_StatusMethod_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> status(42);\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(std::move(status).status().ok());\n  }\n}\nBENCHMARK(BM_StatusOrInt_StatusMethod_Ok);\n\nvoid BM_StatusOrInt_StatusMethodRvalue_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(std::move(status).status().ok());\n  }\n}\nBENCHMARK(BM_StatusOrInt_StatusMethodRvalue_Error);\n\nvoid BM_StatusOrInt_StatusMethodRvalue_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<int> status(42);\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(std::move(status).status());\n  }\n}\nBENCHMARK(BM_StatusOrInt_StatusMethodRvalue_Ok);\n\nvoid BM_StatusOrString_CtorStatus(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(absl::CancelledError());\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_CtorStatus);\n\nvoid BM_StatusOrString_CtorStatusWithMessage(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_CtorStatusWithMessage);\n\nvoid BM_StatusOrString_CopyCtor_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_CopyCtor_Error);\n\nvoid BM_StatusOrString_CopyCtor_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_CopyCtor_Ok);\n\nvoid BM_StatusOrString_MoveCtor_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_MoveCtor_Error);\n\nvoid BM_StatusOrString_MoveCtor_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_MoveCtor_Ok);\n\nvoid BM_StatusOrString_CopyAssign_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_CopyAssign_Error);\n\nvoid BM_StatusOrString_CopyAssign_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = original);\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_CopyAssign_Ok);\n\nvoid BM_StatusOrString_MoveAssign_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_MoveAssign_Error);\n\nvoid BM_StatusOrString_MoveAssign_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> original(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(original);\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status = std::move(original));\n    benchmark::DoNotOptimize(status);\n  }\n}\nBENCHMARK(BM_StatusOrString_MoveAssign_Ok);\n\nvoid BM_StatusOrString_OkMethod_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.ok());\n  }\n}\nBENCHMARK(BM_StatusOrString_OkMethod_Error);\n\nvoid BM_StatusOrString_OkMethod_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.ok());\n  }\n}\nBENCHMARK(BM_StatusOrString_OkMethod_Ok);\n\nvoid BM_StatusOrString_StatusMethod_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.status().ok());\n  }\n}\nBENCHMARK(BM_StatusOrString_StatusMethod_Error);\n\nvoid BM_StatusOrString_StatusMethod_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(status.status().ok());\n  }\n}\nBENCHMARK(BM_StatusOrString_StatusMethod_Ok);\n\nvoid BM_StatusOrString_StatusMethodRvalue_Error(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\n        absl::UnknownError(\"This string is 28 characters\"));\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(std::move(status).status());\n  }\n}\nBENCHMARK(BM_StatusOrString_StatusMethodRvalue_Error);\n\nvoid BM_StatusOrString_StatusMethodRvalue_Ok(benchmark::State& state) {\n  for (auto _ : state) {\n    absl::StatusOr<std::string> status(\"This string is 28 characters\");\n    benchmark::DoNotOptimize(status);\n    benchmark::DoNotOptimize(std::move(status).status());\n  }\n}\nBENCHMARK(BM_StatusOrString_StatusMethodRvalue_Ok);\n\n// Benchmarks comparing a few alternative ways of structuring an interface\n// for returning an int64 on success or an error.  See (a), (b), (c), (d)\n// below for the variants.\nbool bm_cond = true;\n\nbool SimpleIntInterface(int64_t* v) ABSL_ATTRIBUTE_NOINLINE;\nbool SimpleIntInterfaceWithErrorMessage(int64_t* v, std::string* msg)\n    ABSL_ATTRIBUTE_NOINLINE;\nabsl::Status SimpleIntInterfaceWithErrorStatus(int64_t* v)\n    ABSL_ATTRIBUTE_NOINLINE;\nabsl::StatusOr<int64_t> SimpleIntStatusOrInterface() ABSL_ATTRIBUTE_NOINLINE;\n\n// (a): Just a boolean return value with an out int64* parameter\nbool SimpleIntInterface(int64_t* v) {\n  benchmark::DoNotOptimize(bm_cond);\n  if (bm_cond) {\n    *v = 42;\n    return true;\n  } else {\n    return false;\n  }\n}\n\n// (b): A boolean return value and a string error message filled in on failure\n// and an out int64* parameter filled on success\nbool SimpleIntInterfaceWithErrorMessage(int64_t* v, std::string* msg) {\n  benchmark::DoNotOptimize(bm_cond);\n  if (bm_cond) {\n    *v = 42;\n    return true;\n  } else {\n    *msg = \"This is an error message\";\n    return false;\n  }\n}\n\n// (c): A Status return value with an out int64* parameter on success\nabsl::Status SimpleIntInterfaceWithErrorStatus(int64_t* v) {\n  benchmark::DoNotOptimize(bm_cond);\n  if (bm_cond) {\n    *v = 42;\n    return absl::OkStatus();\n  } else {\n    return absl::UnknownError(\"This is an error message\");\n  }\n}\n\n// (d): A StatusOr<int64> return value\nabsl::StatusOr<int64_t> SimpleIntStatusOrInterface() {\n  benchmark::DoNotOptimize(bm_cond);\n  if (bm_cond) {\n    return 42;\n  } else {\n    return absl::StatusOr<int64_t>(\n        absl::UnknownError(\"This is an error message\"));\n  }\n}\n\nvoid SetCondition(benchmark::State& state) {\n  bm_cond = (state.range(0) == 0);\n  state.SetLabel(bm_cond ? \"Success\" : \"Failure\");\n}\n\nvoid BM_SimpleIntInterface(benchmark::State& state) {\n  SetCondition(state);\n  int64_t sum = 0;\n  for (auto s : state) {\n    int64_t v;\n    if (SimpleIntInterface(&v)) {\n      sum += v;\n    }\n    benchmark::DoNotOptimize(sum);\n  }\n}\n\nvoid BM_SimpleIntInterfaceMsg(benchmark::State& state) {\n  SetCondition(state);\n  int64_t sum = 0;\n  std::string msg;\n  for (auto s : state) {\n    int64_t v;\n    if (SimpleIntInterfaceWithErrorMessage(&v, &msg)) {\n      sum += v;\n    }\n    benchmark::DoNotOptimize(sum);\n    benchmark::DoNotOptimize(msg);\n  }\n}\n\nvoid BM_SimpleIntInterfaceStatus(benchmark::State& state) {\n  SetCondition(state);\n  int64_t sum = 0;\n  for (auto s : state) {\n    int64_t v;\n    auto result = SimpleIntInterfaceWithErrorStatus(&v);\n    if (result.ok()) {\n      sum += v;\n    }\n    benchmark::DoNotOptimize(sum);\n  }\n}\n\nvoid BM_SimpleIntStatusOrInterface(benchmark::State& state) {\n  SetCondition(state);\n  int64_t sum = 0;\n  for (auto s : state) {\n    auto v_s = SimpleIntStatusOrInterface();\n    if (v_s.ok()) {\n      sum += *v_s;\n    }\n    benchmark::DoNotOptimize(sum);\n  }\n}\n\n// Ordered like this so all the success path benchmarks (Arg(0)) show up,\n// then all the failure benchmarks (Arg(1))\nBENCHMARK(BM_SimpleIntInterface)->Arg(0);\nBENCHMARK(BM_SimpleIntInterfaceMsg)->Arg(0);\nBENCHMARK(BM_SimpleIntInterfaceStatus)->Arg(0);\nBENCHMARK(BM_SimpleIntStatusOrInterface)->Arg(0);\nBENCHMARK(BM_SimpleIntInterface)->Arg(1);\nBENCHMARK(BM_SimpleIntInterfaceMsg)->Arg(1);\nBENCHMARK(BM_SimpleIntInterfaceStatus)->Arg(1);\nBENCHMARK(BM_SimpleIntStatusOrInterface)->Arg(1);\n\n}  // namespace\n"
  },
  {
    "path": "absl/status/statusor_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/status/statusor.h\"\n\n#include <any>\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <initializer_list>\n#include <map>\n#include <memory>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <variant>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/status/status.h\"\n#include \"absl/status/status_matchers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/source_location.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace {\n\nusing ::absl_testing::IsOk;\nusing ::absl_testing::IsOkAndHolds;\nusing ::testing::AllOf;\nusing ::testing::AnyOf;\nusing ::testing::AnyWith;\nusing ::testing::ElementsAre;\nusing ::testing::EndsWith;\nusing ::testing::Field;\nusing ::testing::HasSubstr;\nusing ::testing::Ne;\nusing ::testing::Not;\nusing ::testing::Pointee;\nusing ::testing::StartsWith;\nusing ::testing::VariantWith;\n\nstruct CopyDetector {\n  CopyDetector() = default;\n  explicit CopyDetector(int xx) : x(xx) {}\n  CopyDetector(CopyDetector&& d) noexcept\n      : x(d.x), copied(false), moved(true) {}\n  CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}\n  CopyDetector& operator=(const CopyDetector& c) {\n    x = c.x;\n    copied = true;\n    moved = false;\n    return *this;\n  }\n  CopyDetector& operator=(CopyDetector&& c) noexcept {\n    x = c.x;\n    copied = false;\n    moved = true;\n    return *this;\n  }\n  int x = 0;\n  bool copied = false;\n  bool moved = false;\n};\n\ntesting::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) {\n  return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b),\n               Field(&CopyDetector::copied, c));\n}\n\nclass Base1 {\n public:\n  virtual ~Base1() {}\n  int pad;\n};\n\nclass Base2 {\n public:\n  virtual ~Base2() {}\n  int yetotherpad;\n};\n\nclass Derived : public Base1, public Base2 {\n public:\n  virtual ~Derived() {}\n  int evenmorepad;\n};\n\nclass CopyNoAssign {\n public:\n  explicit CopyNoAssign(int value) : foo(value) {}\n  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}\n  int foo;\n\n private:\n  const CopyNoAssign& operator=(const CopyNoAssign&);\n};\n\nabsl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {\n  // Uses implicit constructor from T&&\n  return absl::make_unique<int>(0);\n}\n\nTEST(StatusOr, ElementType) {\n  static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), \"\");\n  static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), \"\");\n}\n\nTEST(StatusOr, TestMoveOnlyInitialization) {\n  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());\n  ASSERT_TRUE(thing.ok());\n  EXPECT_EQ(0, **thing);\n  int* previous = thing->get();\n\n  thing = ReturnUniquePtr();\n  EXPECT_TRUE(thing.ok());\n  EXPECT_EQ(0, **thing);\n  EXPECT_NE(previous, thing->get());\n}\n\nTEST(StatusOr, TestMoveOnlyValueExtraction) {\n  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());\n  ASSERT_TRUE(thing.ok());\n  std::unique_ptr<int> ptr = *std::move(thing);\n  EXPECT_EQ(0, *ptr);\n\n  thing = std::move(ptr);\n  ptr = std::move(*thing);\n  EXPECT_EQ(0, *ptr);\n}\n\nTEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {\n  std::unique_ptr<int> ptr(*ReturnUniquePtr());\n  EXPECT_EQ(0, *ptr);\n}\n\nTEST(StatusOr, TestValueOrDieOverloadForConstTemporary) {\n  static_assert(\n      std::is_same<\n          const int&&,\n          decltype(std::declval<const absl::StatusOr<int>&&>().value())>(),\n      \"value() for const temporaries should return const T&&\");\n}\n\nTEST(StatusOr, TestMoveOnlyConversion) {\n  absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());\n  EXPECT_TRUE(const_thing.ok());\n  EXPECT_EQ(0, **const_thing);\n\n  // Test rvalue converting assignment\n  const int* const_previous = const_thing->get();\n  const_thing = ReturnUniquePtr();\n  EXPECT_TRUE(const_thing.ok());\n  EXPECT_EQ(0, **const_thing);\n  EXPECT_NE(const_previous, const_thing->get());\n}\n\nTEST(StatusOr, TestMoveOnlyVector) {\n  // Sanity check that absl::StatusOr<MoveOnly> works in vector.\n  std::vector<absl::StatusOr<std::unique_ptr<int>>> vec;\n  vec.push_back(ReturnUniquePtr());\n  vec.resize(2);\n  auto another_vec = std::move(vec);\n  EXPECT_EQ(0, **another_vec[0]);\n  EXPECT_EQ(absl::UnknownError(\"\"), another_vec[1].status());\n}\n\nTEST(StatusOr, TestDefaultCtor) {\n  absl::StatusOr<int> thing;\n  EXPECT_FALSE(thing.ok());\n  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);\n}\n\nTEST(StatusOr, StatusCtorForwards) {\n  absl::Status status(absl::StatusCode::kInternal, \"Some error\");\n\n  EXPECT_EQ(absl::StatusOr<int>(status).status().message(), \"Some error\");\n  EXPECT_EQ(status.message(), \"Some error\");\n\n  EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(),\n            \"Some error\");\n  EXPECT_NE(status.message(), \"Some error\");\n}\n\nTEST(BadStatusOrAccessTest, CopyConstructionWhatOk) {\n  absl::Status error =\n      absl::InternalError(\"some arbitrary message too big for the sso buffer\");\n  absl::BadStatusOrAccess e1{error};\n  absl::BadStatusOrAccess e2{e1};\n  EXPECT_THAT(e1.what(), HasSubstr(error.ToString()));\n  EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));\n}\n\nTEST(BadStatusOrAccessTest, CopyAssignmentWhatOk) {\n  absl::Status error =\n      absl::InternalError(\"some arbitrary message too big for the sso buffer\");\n  absl::BadStatusOrAccess e1{error};\n  absl::BadStatusOrAccess e2{absl::InternalError(\"other\")};\n  e2 = e1;\n  EXPECT_THAT(e1.what(), HasSubstr(error.ToString()));\n  EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));\n}\n\nTEST(BadStatusOrAccessTest, MoveConstructionWhatOk) {\n  absl::Status error =\n      absl::InternalError(\"some arbitrary message too big for the sso buffer\");\n  absl::BadStatusOrAccess e1{error};\n  absl::BadStatusOrAccess e2{std::move(e1)};\n  EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));\n}\n\nTEST(BadStatusOrAccessTest, MoveAssignmentWhatOk) {\n  absl::Status error =\n      absl::InternalError(\"some arbitrary message too big for the sso buffer\");\n  absl::BadStatusOrAccess e1{error};\n  absl::BadStatusOrAccess e2{absl::InternalError(\"other\")};\n  e2 = std::move(e1);\n  EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));\n}\n\n// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`,\n// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether\n// exceptions are enabled.\n#ifdef ABSL_HAVE_EXCEPTIONS\n#define EXPECT_DEATH_OR_THROW(statement, status_)                  \\\n  EXPECT_THROW(                                                    \\\n      {                                                            \\\n        try {                                                      \\\n          statement;                                               \\\n        } catch (const absl::BadStatusOrAccess& e) {               \\\n          EXPECT_EQ(e.status(), status_);                          \\\n          EXPECT_THAT(e.what(), HasSubstr(e.status().ToString())); \\\n          throw;                                                   \\\n        }                                                          \\\n      },                                                           \\\n      absl::BadStatusOrAccess);\n#else  // ABSL_HAVE_EXCEPTIONS\n#define EXPECT_DEATH_OR_THROW(statement, status) \\\n  EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString());\n#endif  // ABSL_HAVE_EXCEPTIONS\n\nTEST(StatusOrDeathTest, TestDefaultCtorValue) {\n  absl::StatusOr<int> thing;\n  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(\"\"));\n  const absl::StatusOr<int> thing2;\n  EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError(\"\"));\n}\n\nTEST(StatusOrDeathTest, TestValueNotOk) {\n  absl::StatusOr<int> thing(absl::CancelledError());\n  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());\n}\n\nTEST(StatusOrDeathTest, TestValueNotOkConst) {\n  const absl::StatusOr<int> thing(absl::UnknownError(\"\"));\n  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(\"\"));\n}\n\nTEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {\n  absl::StatusOr<int*> thing;\n  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(\"\"));\n}\n\nTEST(StatusOrDeathTest, TestPointerValueNotOk) {\n  absl::StatusOr<int*> thing(absl::CancelledError());\n  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());\n}\n\nTEST(StatusOrDeathTest, TestPointerValueNotOkConst) {\n  const absl::StatusOr<int*> thing(absl::CancelledError());\n  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(StatusOrDeathTest, TestStatusCtorStatusOk) {\n  EXPECT_DEBUG_DEATH(\n      {\n        // This will DCHECK\n        absl::StatusOr<int> thing(absl::OkStatus());\n        // In optimized mode, we are actually going to get error::INTERNAL for\n        // status here, rather than crashing, so check that.\n        EXPECT_FALSE(thing.ok());\n        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);\n      },\n      \"An OK status is not a valid constructor argument\");\n}\n\nTEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) {\n  EXPECT_DEBUG_DEATH(\n      {\n        absl::StatusOr<int*> thing(absl::OkStatus());\n        // In optimized mode, we are actually going to get error::INTERNAL for\n        // status here, rather than crashing, so check that.\n        EXPECT_FALSE(thing.ok());\n        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);\n      },\n      \"An OK status is not a valid constructor argument\");\n}\n#endif\n\nTEST(StatusOr, ValueAccessor) {\n  const int kIntValue = 110;\n  {\n    absl::StatusOr<int> status_or(kIntValue);\n    EXPECT_EQ(kIntValue, status_or.value());\n    EXPECT_EQ(kIntValue, std::move(status_or).value());\n  }\n  {\n    absl::StatusOr<CopyDetector> status_or(kIntValue);\n    EXPECT_THAT(status_or,\n                IsOkAndHolds(CopyDetectorHas(kIntValue, false, false)));\n    CopyDetector copy_detector = status_or.value();\n    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true));\n    copy_detector = std::move(status_or).value();\n    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false));\n  }\n}\n\nTEST(StatusOr, BadValueAccess) {\n  const absl::Status kError = absl::CancelledError(\"message\");\n  absl::StatusOr<int> status_or(kError);\n  EXPECT_DEATH_OR_THROW(status_or.value(), kError);\n}\n\nTEST(StatusOr, TestStatusCtor) {\n  absl::StatusOr<int> thing(absl::CancelledError());\n  EXPECT_FALSE(thing.ok());\n  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestValueCtor) {\n  const int kI = 4;\n  const absl::StatusOr<int> thing(kI);\n  EXPECT_TRUE(thing.ok());\n  EXPECT_EQ(kI, *thing);\n}\n\nstruct Foo {\n  const int x;\n  explicit Foo(int y) : x(y) {}\n};\n\nTEST(StatusOr, InPlaceConstruction) {\n  EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10),\n              IsOkAndHolds(Field(&Foo::x, 10)));\n}\n\nstruct InPlaceHelper {\n  InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)\n      : x(xs), y(std::move(yy)) {}\n  const std::vector<int> x;\n  std::unique_ptr<int> y;\n};\n\nTEST(StatusOr, InPlaceInitListConstruction) {\n  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},\n                                          absl::make_unique<int>(13));\n  EXPECT_THAT(status_or, IsOkAndHolds(AllOf(\n                             Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)),\n                             Field(&InPlaceHelper::y, Pointee(13)))));\n}\n\nTEST(StatusOr, Emplace) {\n  absl::StatusOr<Foo> status_or_foo(10);\n  status_or_foo.emplace(20);\n  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));\n  status_or_foo = absl::InvalidArgumentError(\"msg\");\n  EXPECT_FALSE(status_or_foo.ok());\n  EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument);\n  EXPECT_EQ(status_or_foo.status().message(), \"msg\");\n  status_or_foo.emplace(20);\n  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));\n}\n\nTEST(StatusOr, EmplaceInitializerList) {\n  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},\n                                          absl::make_unique<int>(13));\n  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));\n  EXPECT_THAT(status_or,\n              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),\n                                 Field(&InPlaceHelper::y, Pointee(4)))));\n  status_or = absl::InvalidArgumentError(\"msg\");\n  EXPECT_FALSE(status_or.ok());\n  EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument);\n  EXPECT_EQ(status_or.status().message(), \"msg\");\n  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));\n  EXPECT_THAT(status_or,\n              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),\n                                 Field(&InPlaceHelper::y, Pointee(4)))));\n}\n\nTEST(StatusOr, TestCopyCtorStatusOk) {\n  const int kI = 4;\n  const absl::StatusOr<int> original(kI);\n  const absl::StatusOr<int> copy(original);\n  EXPECT_THAT(copy.status(), IsOk());\n  EXPECT_EQ(*original, *copy);\n}\n\nTEST(StatusOr, TestCopyCtorStatusNotOk) {\n  absl::StatusOr<int> original(absl::CancelledError());\n  absl::StatusOr<int> copy(original);\n  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestCopyCtorNonAssignable) {\n  const int kI = 4;\n  CopyNoAssign value(kI);\n  absl::StatusOr<CopyNoAssign> original(value);\n  absl::StatusOr<CopyNoAssign> copy(original);\n  EXPECT_THAT(copy.status(), IsOk());\n  EXPECT_EQ(original->foo, copy->foo);\n}\n\nTEST(StatusOr, TestCopyCtorStatusOKConverting) {\n  const int kI = 4;\n  absl::StatusOr<int> original(kI);\n  absl::StatusOr<double> copy(original);\n  EXPECT_THAT(copy.status(), IsOk());\n  EXPECT_DOUBLE_EQ(*original, *copy);\n}\n\nTEST(StatusOr, TestCopyCtorStatusNotOkConverting) {\n  absl::StatusOr<int> original(absl::CancelledError());\n  absl::StatusOr<double> copy(original);\n  EXPECT_EQ(copy.status(), original.status());\n}\n\nTEST(StatusOr, TestAssignmentStatusOk) {\n  // Copy assignmment\n  {\n    const auto p = std::make_shared<int>(17);\n    absl::StatusOr<std::shared_ptr<int>> source(p);\n\n    absl::StatusOr<std::shared_ptr<int>> target;\n    target = source;\n\n    ASSERT_TRUE(target.ok());\n    EXPECT_THAT(target.status(), IsOk());\n    EXPECT_EQ(p, *target);\n\n    ASSERT_TRUE(source.ok());\n    EXPECT_THAT(source.status(), IsOk());\n    EXPECT_EQ(p, *source);\n  }\n\n  // Move assignment\n  {\n    const auto p = std::make_shared<int>(17);\n    absl::StatusOr<std::shared_ptr<int>> source(p);\n\n    absl::StatusOr<std::shared_ptr<int>> target;\n    target = std::move(source);\n\n    ASSERT_TRUE(target.ok());\n    EXPECT_THAT(target.status(), IsOk());\n    EXPECT_EQ(p, *target);\n\n    ASSERT_TRUE(source.ok());\n    EXPECT_THAT(source.status(), IsOk());\n    EXPECT_EQ(nullptr, *source);\n  }\n}\n\nTEST(StatusOr, TestAssignmentStatusNotOk) {\n  // Copy assignment\n  {\n    const absl::Status expected = absl::CancelledError();\n    absl::StatusOr<int> source(expected);\n\n    absl::StatusOr<int> target;\n    target = source;\n\n    EXPECT_FALSE(target.ok());\n    EXPECT_EQ(expected, target.status());\n\n    EXPECT_FALSE(source.ok());\n    EXPECT_EQ(expected, source.status());\n  }\n\n  // Move assignment\n  {\n    const absl::Status expected = absl::CancelledError();\n    absl::StatusOr<int> source(expected);\n\n    absl::StatusOr<int> target;\n    target = std::move(source);\n\n    EXPECT_FALSE(target.ok());\n    EXPECT_EQ(expected, target.status());\n\n    EXPECT_FALSE(source.ok());\n    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);\n  }\n}\n\nTEST(StatusOr, TestAssignmentStatusOKConverting) {\n  // Copy assignment\n  {\n    const int kI = 4;\n    absl::StatusOr<int> source(kI);\n\n    absl::StatusOr<double> target;\n    target = source;\n\n    ASSERT_TRUE(target.ok());\n    EXPECT_THAT(target.status(), IsOk());\n    EXPECT_DOUBLE_EQ(kI, *target);\n\n    ASSERT_TRUE(source.ok());\n    EXPECT_THAT(source.status(), IsOk());\n    EXPECT_DOUBLE_EQ(kI, *source);\n  }\n\n  // Move assignment\n  {\n    const auto p = new int(17);\n    absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p));\n\n    absl::StatusOr<std::shared_ptr<int>> target;\n    target = std::move(source);\n\n    ASSERT_TRUE(target.ok());\n    EXPECT_THAT(target.status(), IsOk());\n    EXPECT_EQ(p, target->get());\n\n    ASSERT_TRUE(source.ok());\n    EXPECT_THAT(source.status(), IsOk());\n    EXPECT_EQ(nullptr, source->get());\n  }\n}\n\nstruct A {\n  int x;\n};\n\nstruct ImplicitConstructibleFromA {\n  int x;\n  bool moved;\n  ImplicitConstructibleFromA(const A& a)  // NOLINT\n      : x(a.x), moved(false) {}\n  ImplicitConstructibleFromA(A&& a)  // NOLINT\n      : x(a.x), moved(true) {}\n};\n\nTEST(StatusOr, ImplicitConvertingConstructor) {\n  EXPECT_THAT(\n      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(\n          absl::StatusOr<A>(A{11})),\n      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11),\n                         Field(&ImplicitConstructibleFromA::moved, true))));\n  absl::StatusOr<A> a(A{12});\n  EXPECT_THAT(\n      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a),\n      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12),\n                         Field(&ImplicitConstructibleFromA::moved, false))));\n}\n\nstruct ExplicitConstructibleFromA {\n  int x;\n  bool moved;\n  explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}\n  explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}\n};\n\nTEST(StatusOr, ExplicitConvertingConstructor) {\n  EXPECT_FALSE(\n      (std::is_convertible<const absl::StatusOr<A>&,\n                           absl::StatusOr<ExplicitConstructibleFromA>>::value));\n  EXPECT_FALSE(\n      (std::is_convertible<absl::StatusOr<A>&&,\n                           absl::StatusOr<ExplicitConstructibleFromA>>::value));\n  EXPECT_THAT(\n      absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})),\n      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11),\n                         Field(&ExplicitConstructibleFromA::moved, true))));\n  absl::StatusOr<A> a(A{12});\n  EXPECT_THAT(\n      absl::StatusOr<ExplicitConstructibleFromA>(a),\n      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12),\n                         Field(&ExplicitConstructibleFromA::moved, false))));\n}\n\nstruct ImplicitConstructibleFromBool {\n  ImplicitConstructibleFromBool(bool y) : x(y) {}  // NOLINT\n  bool x = false;\n};\n\nstruct ConvertibleToBool {\n  explicit ConvertibleToBool(bool y) : x(y) {}\n  operator bool() const { return x; }  // NOLINT\n  bool x = false;\n};\n\nTEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) {\n  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),\n              IsOkAndHolds(true));\n  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),\n              IsOkAndHolds(false));\n  EXPECT_THAT(\n      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>(\n          absl::StatusOr<bool>(false)),\n      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));\n  EXPECT_FALSE((std::is_convertible<\n                absl::StatusOr<ConvertibleToBool>,\n                absl::StatusOr<ImplicitConstructibleFromBool>>::value));\n}\n\nTEST(StatusOr, BooleanConstructionWithImplicitCasts) {\n  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),\n              IsOkAndHolds(true));\n  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),\n              IsOkAndHolds(false));\n  EXPECT_THAT(\n      absl::StatusOr<ImplicitConstructibleFromBool>{\n          absl::StatusOr<bool>(false)},\n      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));\n  EXPECT_THAT(\n      absl::StatusOr<ImplicitConstructibleFromBool>{\n          absl::StatusOr<bool>(absl::InvalidArgumentError(\"\"))},\n      Not(IsOk()));\n\n  EXPECT_THAT(\n      absl::StatusOr<ImplicitConstructibleFromBool>{\n          absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})},\n      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));\n  EXPECT_THAT(\n      absl::StatusOr<ImplicitConstructibleFromBool>{\n          absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(\"\"))},\n      Not(IsOk()));\n}\n\nTEST(StatusOr, ConstImplicitCast) {\n  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(\n                  absl::StatusOr<const bool>(true)),\n              IsOkAndHolds(true));\n  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(\n                  absl::StatusOr<const bool>(false)),\n              IsOkAndHolds(false));\n  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(\n                  absl::StatusOr<bool>(true)),\n              IsOkAndHolds(true));\n  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(\n                  absl::StatusOr<bool>(false)),\n              IsOkAndHolds(false));\n  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>(\n                  absl::StatusOr<std::string>(\"foo\")),\n              IsOkAndHolds(\"foo\"));\n  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>(\n                  absl::StatusOr<const std::string>(\"foo\")),\n              IsOkAndHolds(\"foo\"));\n  EXPECT_THAT(\n      absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>(\n          absl::StatusOr<std::shared_ptr<std::string>>(\n              std::make_shared<std::string>(\"foo\"))),\n      IsOkAndHolds(Pointee(std::string(\"foo\"))));\n}\n\nTEST(StatusOr, ConstExplicitConstruction) {\n  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)),\n              IsOkAndHolds(true));\n  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)),\n              IsOkAndHolds(false));\n  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)),\n              IsOkAndHolds(true));\n  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)),\n              IsOkAndHolds(false));\n}\n\nstruct ExplicitConstructibleFromInt {\n  int x;\n  explicit ExplicitConstructibleFromInt(int y) : x(y) {}\n};\n\nTEST(StatusOr, ExplicitConstruction) {\n  EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10),\n              IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10)));\n}\n\nTEST(StatusOr, ImplicitConstruction) {\n  // Check implicit casting works.\n  auto status_or =\n      absl::implicit_cast<absl::StatusOr<std::variant<int, std::string>>>(10);\n  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));\n}\n\nTEST(StatusOr, ImplicitConstructionFromInitliazerList) {\n  // Note: dropping the explicit std::initializer_list<int> is not supported\n  // by absl::StatusOr or std::optional.\n  auto status_or =\n      absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}});\n  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));\n}\n\nTEST(StatusOr, UniquePtrImplicitConstruction) {\n  auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>(\n      absl::make_unique<Derived>());\n  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));\n}\n\nTEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) {\n  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);\n  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =\n      absl::InvalidArgumentError(\"foo\");\n  EXPECT_THAT(status_or,\n              IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));\n  absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or;\n  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));\n  absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error;\n  EXPECT_THAT(a_err, Not(IsOk()));\n\n  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;\n  absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref;  // NOLINT\n  EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));\n  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;\n  absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err;  // NOLINT\n  EXPECT_THAT(b_err, Not(IsOk()));\n\n  absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or);\n  EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));\n  absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error);\n  EXPECT_THAT(c_err, Not(IsOk()));\n}\n\nTEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) {\n  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);\n  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =\n      absl::InvalidArgumentError(\"foo\");\n  absl::StatusOr<absl::StatusOr<CopyDetector>> a;\n  a = status_or;\n  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));\n  a = status_error;\n  EXPECT_THAT(a, Not(IsOk()));\n\n  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;\n  a = cref;\n  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));\n  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;\n  a = cref_err;\n  EXPECT_THAT(a, Not(IsOk()));\n  a = std::move(status_or);\n  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));\n  a = std::move(status_error);\n  EXPECT_THAT(a, Not(IsOk()));\n}\n\nstruct Copyable {\n  Copyable() {}\n  Copyable(const Copyable&) {}\n  Copyable& operator=(const Copyable&) { return *this; }\n};\n\nstruct MoveOnly {\n  MoveOnly() {}\n  MoveOnly(MoveOnly&&) {}\n  MoveOnly& operator=(MoveOnly&&) { return *this; }\n};\n\nstruct NonMovable {\n  NonMovable() {}\n  NonMovable(const NonMovable&) = delete;\n  NonMovable(NonMovable&&) = delete;\n  NonMovable& operator=(const NonMovable&) = delete;\n  NonMovable& operator=(NonMovable&&) = delete;\n};\n\nTEST(StatusOr, CopyAndMoveAbility) {\n  EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);\n  EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);\n  EXPECT_TRUE(std::is_move_constructible<Copyable>::value);\n  EXPECT_TRUE(std::is_move_assignable<Copyable>::value);\n  EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);\n  EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);\n  EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);\n  EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);\n  EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);\n  EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);\n  EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);\n  EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);\n}\n\nTEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) {\n  absl::StatusOr<std::any> status_or = CopyDetector(10);\n  absl::StatusOr<std::any> status_error = absl::InvalidArgumentError(\"foo\");\n  EXPECT_THAT(\n      status_or,\n      IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));\n  absl::StatusOr<std::any> a = status_or;\n  EXPECT_THAT(\n      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));\n  absl::StatusOr<std::any> a_err = status_error;\n  EXPECT_THAT(a_err, Not(IsOk()));\n\n  const absl::StatusOr<std::any>& cref = status_or;\n  // No lint for no-change copy.\n  absl::StatusOr<std::any> b = cref;  // NOLINT\n  EXPECT_THAT(\n      b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));\n  const absl::StatusOr<std::any>& cref_err = status_error;\n  // No lint for no-change copy.\n  absl::StatusOr<std::any> b_err = cref_err;  // NOLINT\n  EXPECT_THAT(b_err, Not(IsOk()));\n\n  absl::StatusOr<std::any> c = std::move(status_or);\n  EXPECT_THAT(\n      c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));\n  absl::StatusOr<std::any> c_err = std::move(status_error);\n  EXPECT_THAT(c_err, Not(IsOk()));\n}\n\nTEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) {\n  absl::StatusOr<std::any> status_or = CopyDetector(10);\n  absl::StatusOr<std::any> status_error = absl::InvalidArgumentError(\"foo\");\n  absl::StatusOr<std::any> a;\n  a = status_or;\n  EXPECT_THAT(\n      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));\n  a = status_error;\n  EXPECT_THAT(a, Not(IsOk()));\n\n  const absl::StatusOr<std::any>& cref = status_or;\n  a = cref;\n  EXPECT_THAT(\n      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));\n  const absl::StatusOr<std::any>& cref_err = status_error;\n  a = cref_err;\n  EXPECT_THAT(a, Not(IsOk()));\n  a = std::move(status_or);\n  EXPECT_THAT(\n      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));\n  a = std::move(status_error);\n  EXPECT_THAT(a, Not(IsOk()));\n}\n\nTEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) {\n  absl::StatusOr<CopyDetector> status_or(10);\n  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));\n  absl::StatusOr<CopyDetector> a(status_or);\n  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));\n  const absl::StatusOr<CopyDetector>& cref = status_or;\n  absl::StatusOr<CopyDetector> b(cref);  // NOLINT\n  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));\n  absl::StatusOr<CopyDetector> c(std::move(status_or));\n  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));\n}\n\nTEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) {\n  absl::StatusOr<CopyDetector> status_or(10);\n  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));\n  absl::StatusOr<CopyDetector> a;\n  a = status_or;\n  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));\n  const absl::StatusOr<CopyDetector>& cref = status_or;\n  absl::StatusOr<CopyDetector> b;\n  b = cref;\n  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));\n  absl::StatusOr<CopyDetector> c;\n  c = std::move(status_or);\n  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));\n}\n\nTEST(StatusOr, AbslAnyAssignment) {\n  EXPECT_FALSE((std::is_assignable<absl::StatusOr<std::any>,\n                                   absl::StatusOr<int>>::value));\n  absl::StatusOr<std::any> status_or;\n  status_or = absl::InvalidArgumentError(\"foo\");\n  EXPECT_THAT(status_or, Not(IsOk()));\n}\n\nTEST(StatusOr, ImplicitAssignment) {\n  absl::StatusOr<std::variant<int, std::string>> status_or;\n  status_or = 10;\n  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));\n}\n\nTEST(StatusOr, SelfDirectInitAssignment) {\n  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};\n  status_or = *status_or;\n  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));\n}\n\nTEST(StatusOr, ImplicitCastFromInitializerList) {\n  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};\n  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));\n}\n\nTEST(StatusOr, UniquePtrImplicitAssignment) {\n  absl::StatusOr<std::unique_ptr<Base1>> status_or;\n  status_or = absl::make_unique<Derived>();\n  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));\n}\n\nTEST(StatusOr, Pointer) {\n  struct A {};\n  struct B : public A {};\n  struct C : private A {};\n\n  EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value));\n  EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value));\n  EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value));\n  EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value));\n}\n\nTEST(StatusOr, TestAssignmentStatusNotOkConverting) {\n  // Copy assignment\n  {\n    const absl::Status expected = absl::CancelledError();\n    absl::StatusOr<int> source(expected);\n\n    absl::StatusOr<double> target;\n    target = source;\n\n    EXPECT_FALSE(target.ok());\n    EXPECT_EQ(expected, target.status());\n\n    EXPECT_FALSE(source.ok());\n    EXPECT_EQ(expected, source.status());\n  }\n\n  // Move assignment\n  {\n    const absl::Status expected = absl::CancelledError();\n    absl::StatusOr<int> source(expected);\n\n    absl::StatusOr<double> target;\n    target = std::move(source);\n\n    EXPECT_FALSE(target.ok());\n    EXPECT_EQ(expected, target.status());\n\n    EXPECT_FALSE(source.ok());\n    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);\n  }\n}\n\nTEST(StatusOr, SelfAssignment) {\n  // Copy-assignment, status OK\n  {\n    // A string long enough that it's likely to defeat any inline representation\n    // optimization.\n    const std::string long_str(128, 'a');\n\n    absl::StatusOr<std::string> so = long_str;\n    so = *&so;\n\n    ASSERT_TRUE(so.ok());\n    EXPECT_THAT(so.status(), IsOk());\n    EXPECT_EQ(long_str, *so);\n  }\n\n  // Copy-assignment, error status\n  {\n    absl::StatusOr<int> so = absl::NotFoundError(\"taco\");\n    so = *&so;\n\n    EXPECT_FALSE(so.ok());\n    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);\n    EXPECT_EQ(so.status().message(), \"taco\");\n  }\n\n  // Move-assignment with copyable type, status OK\n  {\n    absl::StatusOr<int> so = 17;\n\n    // Fool the compiler, which otherwise complains.\n    auto& same = so;\n    so = std::move(same);\n\n    ASSERT_TRUE(so.ok());\n    EXPECT_THAT(so.status(), IsOk());\n    EXPECT_EQ(17, *so);\n  }\n\n  // Move-assignment with copyable type, error status\n  {\n    absl::StatusOr<int> so = absl::NotFoundError(\"taco\");\n\n    // Fool the compiler, which otherwise complains.\n    auto& same = so;\n    so = std::move(same);\n\n    EXPECT_FALSE(so.ok());\n    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);\n    EXPECT_EQ(so.status().message(), \"taco\");\n  }\n\n  // Move-assignment with non-copyable type, status OK\n  {\n    const auto raw = new int(17);\n    absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw);\n\n    // Fool the compiler, which otherwise complains.\n    auto& same = so;\n    so = std::move(same);\n\n    ASSERT_TRUE(so.ok());\n    EXPECT_THAT(so.status(), IsOk());\n    EXPECT_EQ(raw, so->get());\n  }\n\n  // Move-assignment with non-copyable type, error status\n  {\n    absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError(\"taco\");\n\n    // Fool the compiler, which otherwise complains.\n    auto& same = so;\n    so = std::move(same);\n\n    EXPECT_FALSE(so.ok());\n    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);\n    EXPECT_EQ(so.status().message(), \"taco\");\n  }\n}\n\n// These types form the overload sets of the constructors and the assignment\n// operators of `MockValue`. They distinguish construction from assignment,\n// lvalue from rvalue.\nstruct FromConstructibleAssignableLvalue {};\nstruct FromConstructibleAssignableRvalue {};\nstruct FromImplicitConstructibleOnly {};\nstruct FromAssignableOnly {};\n\n// This class is for testing the forwarding value assignments of `StatusOr`.\n// `from_rvalue` indicates whether the constructor or the assignment taking\n// rvalue reference is called. `from_assignment` indicates whether any\n// assignment is called.\nstruct MockValue {\n  // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.\n  MockValue(const FromConstructibleAssignableLvalue&)  // NOLINT\n      : from_rvalue(false), assigned(false) {}\n  // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.\n  MockValue(FromConstructibleAssignableRvalue&&)  // NOLINT\n      : from_rvalue(true), assigned(false) {}\n  // Constructs `MockValue` from `FromImplicitConstructibleOnly`.\n  // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.\n  MockValue(const FromImplicitConstructibleOnly&)  // NOLINT\n      : from_rvalue(false), assigned(false) {}\n  // Assigns `FromConstructibleAssignableLvalue`.\n  MockValue& operator=(const FromConstructibleAssignableLvalue&) {\n    from_rvalue = false;\n    assigned = true;\n    return *this;\n  }\n  // Assigns `FromConstructibleAssignableRvalue` (rvalue only).\n  MockValue& operator=(FromConstructibleAssignableRvalue&&) {\n    from_rvalue = true;\n    assigned = true;\n    return *this;\n  }\n  // Assigns `FromAssignableOnly`, but not constructible from\n  // `FromAssignableOnly`.\n  MockValue& operator=(const FromAssignableOnly&) {\n    from_rvalue = false;\n    assigned = true;\n    return *this;\n  }\n  bool from_rvalue;\n  bool assigned;\n};\n\n// operator=(U&&)\nTEST(StatusOr, PerfectForwardingAssignment) {\n  // U == T\n  constexpr int kValue1 = 10, kValue2 = 20;\n  absl::StatusOr<CopyDetector> status_or;\n  CopyDetector lvalue(kValue1);\n  status_or = lvalue;\n  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true)));\n  status_or = CopyDetector(kValue2);\n  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false)));\n\n  // U != T\n  EXPECT_TRUE(\n      (std::is_assignable<absl::StatusOr<MockValue>&,\n                          const FromConstructibleAssignableLvalue&>::value));\n  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,\n                                  FromConstructibleAssignableLvalue&&>::value));\n  EXPECT_FALSE(\n      (std::is_assignable<absl::StatusOr<MockValue>&,\n                          const FromConstructibleAssignableRvalue&>::value));\n  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,\n                                  FromConstructibleAssignableRvalue&&>::value));\n  EXPECT_TRUE(\n      (std::is_assignable<absl::StatusOr<MockValue>&,\n                          const FromImplicitConstructibleOnly&>::value));\n  EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&,\n                                   const FromAssignableOnly&>::value));\n\n  absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});\n  EXPECT_FALSE(from_lvalue->from_rvalue);\n  EXPECT_FALSE(from_lvalue->assigned);\n  from_lvalue = FromConstructibleAssignableLvalue{};\n  EXPECT_FALSE(from_lvalue->from_rvalue);\n  EXPECT_TRUE(from_lvalue->assigned);\n\n  absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});\n  EXPECT_TRUE(from_rvalue->from_rvalue);\n  EXPECT_FALSE(from_rvalue->assigned);\n  from_rvalue = FromConstructibleAssignableRvalue{};\n  EXPECT_TRUE(from_rvalue->from_rvalue);\n  EXPECT_TRUE(from_rvalue->assigned);\n\n  absl::StatusOr<MockValue> from_implicit_constructible(\n      FromImplicitConstructibleOnly{});\n  EXPECT_FALSE(from_implicit_constructible->from_rvalue);\n  EXPECT_FALSE(from_implicit_constructible->assigned);\n  // construct a temporary `StatusOr` object and invoke the `StatusOr` move\n  // assignment operator.\n  from_implicit_constructible = FromImplicitConstructibleOnly{};\n  EXPECT_FALSE(from_implicit_constructible->from_rvalue);\n  EXPECT_FALSE(from_implicit_constructible->assigned);\n}\n\nTEST(StatusOr, TestStatus) {\n  absl::StatusOr<int> good(4);\n  EXPECT_TRUE(good.ok());\n  absl::StatusOr<int> bad(absl::CancelledError());\n  EXPECT_FALSE(bad.ok());\n  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, OperatorStarRefQualifiers) {\n  static_assert(\n      std::is_same<const int&,\n                   decltype(*std::declval<const absl::StatusOr<int>&>())>(),\n      \"Unexpected ref-qualifiers\");\n  static_assert(\n      std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(),\n      \"Unexpected ref-qualifiers\");\n  static_assert(\n      std::is_same<const int&&,\n                   decltype(*std::declval<const absl::StatusOr<int>&&>())>(),\n      \"Unexpected ref-qualifiers\");\n  static_assert(\n      std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(),\n      \"Unexpected ref-qualifiers\");\n}\n\nTEST(StatusOr, OperatorStar) {\n  const absl::StatusOr<std::string> const_lvalue(\"hello\");\n  EXPECT_EQ(\"hello\", *const_lvalue);\n\n  absl::StatusOr<std::string> lvalue(\"hello\");\n  EXPECT_EQ(\"hello\", *lvalue);\n\n  // Note: Recall that std::move() is equivalent to a static_cast to an rvalue\n  // reference type.\n  const absl::StatusOr<std::string> const_rvalue(\"hello\");\n  EXPECT_EQ(\"hello\", *std::move(const_rvalue));  // NOLINT\n\n  absl::StatusOr<std::string> rvalue(\"hello\");\n  EXPECT_EQ(\"hello\", *std::move(rvalue));\n}\n\nTEST(StatusOr, OperatorArrowQualifiers) {\n  static_assert(\n      std::is_same<\n          const int*,\n          decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(),\n      \"Unexpected qualifiers\");\n  static_assert(\n      std::is_same<\n          int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(),\n      \"Unexpected qualifiers\");\n  static_assert(\n      std::is_same<\n          const int*,\n          decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(),\n      \"Unexpected qualifiers\");\n  static_assert(\n      std::is_same<\n          int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(),\n      \"Unexpected qualifiers\");\n}\n\nTEST(StatusOr, OperatorArrow) {\n  const absl::StatusOr<std::string> const_lvalue(\"hello\");\n  EXPECT_EQ(std::string(\"hello\"), const_lvalue->c_str());\n\n  absl::StatusOr<std::string> lvalue(\"hello\");\n  EXPECT_EQ(std::string(\"hello\"), lvalue->c_str());\n}\n\nTEST(StatusOr, RValueStatus) {\n  absl::StatusOr<int> so(absl::NotFoundError(\"taco\"));\n  const absl::Status s = std::move(so).status();\n\n  EXPECT_EQ(s.code(), absl::StatusCode::kNotFound);\n  EXPECT_EQ(s.message(), \"taco\");\n\n  // Check that !ok() still implies !status().ok(), even after moving out of the\n  // object. See the note on the rvalue ref-qualified status method.\n  EXPECT_FALSE(so.ok());  // NOLINT\n  EXPECT_FALSE(so.status().ok());\n  EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal);\n  EXPECT_EQ(so.status().message(), \"Status accessed after move.\");\n}\n\nTEST(StatusOr, TestValue) {\n  const int kI = 4;\n  absl::StatusOr<int> thing(kI);\n  EXPECT_EQ(kI, *thing);\n}\n\nTEST(StatusOr, TestValueConst) {\n  const int kI = 4;\n  const absl::StatusOr<int> thing(kI);\n  EXPECT_EQ(kI, *thing);\n}\n\nTEST(StatusOr, TestPointerDefaultCtor) {\n  absl::StatusOr<int*> thing;\n  EXPECT_FALSE(thing.ok());\n  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);\n}\n\nTEST(StatusOr, TestPointerStatusCtor) {\n  absl::StatusOr<int*> thing(absl::CancelledError());\n  EXPECT_FALSE(thing.ok());\n  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestPointerValueCtor) {\n  const int kI = 4;\n\n  // Construction from a non-null pointer\n  {\n    absl::StatusOr<const int*> so(&kI);\n    EXPECT_TRUE(so.ok());\n    EXPECT_THAT(so.status(), IsOk());\n    EXPECT_EQ(&kI, *so);\n  }\n\n  // Construction from a null pointer constant\n  {\n    absl::StatusOr<const int*> so(nullptr);\n    EXPECT_TRUE(so.ok());\n    EXPECT_THAT(so.status(), IsOk());\n    EXPECT_EQ(nullptr, *so);\n  }\n\n  // Construction from a non-literal null pointer\n  {\n    const int* const p = nullptr;\n\n    absl::StatusOr<const int*> so(p);\n    EXPECT_TRUE(so.ok());\n    EXPECT_THAT(so.status(), IsOk());\n    EXPECT_EQ(nullptr, *so);\n  }\n}\n\nTEST(StatusOr, TestPointerCopyCtorStatusOk) {\n  const int kI = 0;\n  absl::StatusOr<const int*> original(&kI);\n  absl::StatusOr<const int*> copy(original);\n  EXPECT_THAT(copy.status(), IsOk());\n  EXPECT_EQ(*original, *copy);\n}\n\nTEST(StatusOr, TestPointerCopyCtorStatusNotOk) {\n  absl::StatusOr<int*> original(absl::CancelledError());\n  absl::StatusOr<int*> copy(original);\n  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {\n  Derived derived;\n  absl::StatusOr<Derived*> original(&derived);\n  absl::StatusOr<Base2*> copy(original);\n  EXPECT_THAT(copy.status(), IsOk());\n  EXPECT_EQ(static_cast<const Base2*>(*original), *copy);\n}\n\nTEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {\n  absl::StatusOr<Derived*> original(absl::CancelledError());\n  absl::StatusOr<Base2*> copy(original);\n  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestPointerAssignmentStatusOk) {\n  const int kI = 0;\n  absl::StatusOr<const int*> source(&kI);\n  absl::StatusOr<const int*> target;\n  target = source;\n  EXPECT_THAT(target.status(), IsOk());\n  EXPECT_EQ(*source, *target);\n}\n\nTEST(StatusOr, TestPointerAssignmentStatusNotOk) {\n  absl::StatusOr<int*> source(absl::CancelledError());\n  absl::StatusOr<int*> target;\n  target = source;\n  EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestPointerAssignmentStatusOKConverting) {\n  Derived derived;\n  absl::StatusOr<Derived*> source(&derived);\n  absl::StatusOr<Base2*> target;\n  target = source;\n  EXPECT_THAT(target.status(), IsOk());\n  EXPECT_EQ(static_cast<const Base2*>(*source), *target);\n}\n\nTEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {\n  absl::StatusOr<Derived*> source(absl::CancelledError());\n  absl::StatusOr<Base2*> target;\n  target = source;\n  EXPECT_EQ(target.status(), source.status());\n}\n\nTEST(StatusOr, TestPointerStatus) {\n  const int kI = 0;\n  absl::StatusOr<const int*> good(&kI);\n  EXPECT_TRUE(good.ok());\n  absl::StatusOr<const int*> bad(absl::CancelledError());\n  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);\n}\n\nTEST(StatusOr, TestPointerValue) {\n  const int kI = 0;\n  absl::StatusOr<const int*> thing(&kI);\n  EXPECT_EQ(&kI, *thing);\n}\n\nTEST(StatusOr, TestPointerValueConst) {\n  const int kI = 0;\n  const absl::StatusOr<const int*> thing(&kI);\n  EXPECT_EQ(&kI, *thing);\n}\n\nTEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) {\n  using EvilType = std::vector<std::unique_ptr<int>>;\n  static_assert(std::is_copy_constructible<EvilType>::value, \"\");\n  std::vector<::absl::StatusOr<EvilType>> v(5);\n  v.reserve(v.capacity() + 10);\n  v.resize(v.capacity() + 10);\n}\n\nTEST(StatusOr, ConstPayload) {\n  // A reduced version of a problematic type found in the wild. All of the\n  // operations below should compile.\n  absl::StatusOr<const int> a;\n\n  // Copy-construction\n  absl::StatusOr<const int> b(a);\n\n  // Copy-assignment\n  EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value);\n\n  // Move-construction\n  absl::StatusOr<const int> c(std::move(a));\n\n  // Move-assignment\n  EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value);\n}\n\nTEST(StatusOr, MapToStatusOrUniquePtr) {\n  // A reduced version of a problematic type found in the wild. All of the\n  // operations below should compile.\n  using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>;\n\n  MapType a;\n\n  // Move-construction\n  MapType b(std::move(a));\n\n  // Move-assignment\n  a = std::move(b);\n}\n\nTEST(StatusOr, ValueOrOk) {\n  const absl::StatusOr<int> status_or = 0;\n  EXPECT_EQ(status_or.value_or(-1), 0);\n}\n\nTEST(StatusOr, ValueOrDefault) {\n  const absl::StatusOr<int> status_or = absl::CancelledError();\n  EXPECT_EQ(status_or.value_or(-1), -1);\n}\n\nTEST(StatusOr, MoveOnlyValueOrOk) {\n  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))\n                  .value_or(absl::make_unique<int>(-1)),\n              Pointee(0));\n}\n\nTEST(StatusOr, MoveOnlyValueOrDefault) {\n  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError())\n                  .value_or(absl::make_unique<int>(-1)),\n              Pointee(-1));\n}\n\nstatic absl::StatusOr<int> MakeStatus() { return 100; }\n\nTEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); }\n\nTEST(StatusOr, EqualityOperator) {\n  constexpr size_t kNumCases = 4;\n  std::array<absl::StatusOr<int>, kNumCases> group1 = {\n      absl::StatusOr<int>(1), absl::StatusOr<int>(2),\n      absl::StatusOr<int>(absl::InvalidArgumentError(\"msg\")),\n      absl::StatusOr<int>(absl::InternalError(\"msg\"))};\n  std::array<absl::StatusOr<int>, kNumCases> group2 = {\n      absl::StatusOr<int>(1), absl::StatusOr<int>(2),\n      absl::StatusOr<int>(absl::InvalidArgumentError(\"msg\")),\n      absl::StatusOr<int>(absl::InternalError(\"msg\"))};\n  for (size_t i = 0; i < kNumCases; ++i) {\n    for (size_t j = 0; j < kNumCases; ++j) {\n      if (i == j) {\n        EXPECT_TRUE(group1[i] == group2[j]);\n        EXPECT_FALSE(group1[i] != group2[j]);\n      } else {\n        EXPECT_FALSE(group1[i] == group2[j]);\n        EXPECT_TRUE(group1[i] != group2[j]);\n      }\n    }\n  }\n}\n\nstruct MyType {\n  bool operator==(const MyType&) const { return true; }\n};\n\nenum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };\n\n// This class has conversion operator to `StatusOr<T>` based on value of\n// `conv_traits`.\ntemplate <typename T, ConvTraits conv_traits = ConvTraits::kNone>\nstruct StatusOrConversionBase {};\n\ntemplate <typename T>\nstruct StatusOrConversionBase<T, ConvTraits::kImplicit> {\n  operator absl::StatusOr<T>() const& {  // NOLINT\n    return absl::InvalidArgumentError(\"conversion to absl::StatusOr\");\n  }\n  operator absl::StatusOr<T>() && {  // NOLINT\n    return absl::InvalidArgumentError(\"conversion to absl::StatusOr\");\n  }\n};\n\ntemplate <typename T>\nstruct StatusOrConversionBase<T, ConvTraits::kExplicit> {\n  explicit operator absl::StatusOr<T>() const& {\n    return absl::InvalidArgumentError(\"conversion to absl::StatusOr\");\n  }\n  explicit operator absl::StatusOr<T>() && {\n    return absl::InvalidArgumentError(\"conversion to absl::StatusOr\");\n  }\n};\n\n// This class has conversion operator to `T` based on the value of\n// `conv_traits`.\ntemplate <typename T, ConvTraits conv_traits = ConvTraits::kNone>\nstruct ConversionBase {};\n\ntemplate <typename T>\nstruct ConversionBase<T, ConvTraits::kImplicit> {\n  operator T() const& { return t; }         // NOLINT\n  operator T() && { return std::move(t); }  // NOLINT\n  T t;\n};\n\ntemplate <typename T>\nstruct ConversionBase<T, ConvTraits::kExplicit> {\n  explicit operator T() const& { return t; }\n  explicit operator T() && { return std::move(t); }\n  T t;\n};\n\n// This class has conversion operator to `absl::Status` based on the value of\n// `conv_traits`.\ntemplate <ConvTraits conv_traits = ConvTraits::kNone>\nstruct StatusConversionBase {};\n\ntemplate <>\nstruct StatusConversionBase<ConvTraits::kImplicit> {\n  operator absl::Status() const& {  // NOLINT\n    return absl::InternalError(\"conversion to Status\");\n  }\n  operator absl::Status() && {  // NOLINT\n    return absl::InternalError(\"conversion to Status\");\n  }\n};\n\ntemplate <>\nstruct StatusConversionBase<ConvTraits::kExplicit> {\n  explicit operator absl::Status() const& {  // NOLINT\n    return absl::InternalError(\"conversion to Status\");\n  }\n  explicit operator absl::Status() && {  // NOLINT\n    return absl::InternalError(\"conversion to Status\");\n  }\n};\n\nstatic constexpr int kConvToStatus = 1;\nstatic constexpr int kConvToStatusOr = 2;\nstatic constexpr int kConvToT = 4;\nstatic constexpr int kConvExplicit = 8;\n\nconstexpr ConvTraits GetConvTraits(int bit, int config) {\n  return (config & bit) == 0\n             ? ConvTraits::kNone\n             : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit\n                                              : ConvTraits::kExplicit);\n}\n\n// This class conditionally has conversion operator to `absl::Status`, `T`,\n// `StatusOr<T>`, based on values of the template parameters.\ntemplate <typename T, int config>\nstruct CustomType\n    : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>,\n      ConversionBase<T, GetConvTraits(kConvToT, config)>,\n      StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};\n\nstruct ConvertibleToAnyStatusOr {\n  template <typename T>\n  operator absl::StatusOr<T>() const {  // NOLINT\n    return absl::InvalidArgumentError(\"Conversion to absl::StatusOr\");\n  }\n};\n\n// Test the rank of overload resolution for `StatusOr<T>` constructor and\n// assignment, from highest to lowest:\n// 1. T/Status\n// 2. U that has conversion operator to absl::StatusOr<T>\n// 3. U that is convertible to Status\n// 4. U that is convertible to T\nTEST(StatusOr, ConstructionFromT) {\n  // Construct absl::StatusOr<T> from T when T is convertible to\n  // absl::StatusOr<T>\n  {\n    ConvertibleToAnyStatusOr v;\n    absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v);\n    EXPECT_TRUE(statusor.ok());\n  }\n  {\n    ConvertibleToAnyStatusOr v;\n    absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v;\n    EXPECT_TRUE(statusor.ok());\n  }\n  // Construct absl::StatusOr<T> from T when T is explicitly convertible to\n  // Status\n  {\n    CustomType<MyType, kConvToStatus | kConvExplicit> v;\n    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(\n        v);\n    EXPECT_TRUE(statusor.ok());\n  }\n  {\n    CustomType<MyType, kConvToStatus | kConvExplicit> v;\n    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor =\n        v;\n    EXPECT_TRUE(statusor.ok());\n  }\n}\n\n// Construct absl::StatusOr<T> from U when U is explicitly convertible to T\nTEST(StatusOr, ConstructionFromTypeConvertibleToT) {\n  {\n    CustomType<MyType, kConvToT | kConvExplicit> v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_TRUE(statusor.ok());\n  }\n  {\n    CustomType<MyType, kConvToT> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_TRUE(statusor.ok());\n  }\n}\n\n// Construct absl::StatusOr<T> from U when U has explicit conversion operator to\n// absl::StatusOr<T>\nTEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) {\n  {\n    CustomType<MyType, kConvToStatusOr | kConvExplicit> v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType,\n               kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit>\n        v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToStatusOr> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatusOr> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n}\n\nTEST(StatusOr, ConstructionFromTypeConvertibleToStatus) {\n  // Construction fails because conversion to `Status` is explicit.\n  {\n    CustomType<MyType, kConvToStatus | kConvExplicit> v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_FALSE(statusor.ok());\n    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;\n    absl::StatusOr<MyType> statusor(v);\n    EXPECT_FALSE(statusor.ok());\n    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n  }\n  {\n    CustomType<MyType, kConvToStatus> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_FALSE(statusor.ok());\n    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatus> v;\n    absl::StatusOr<MyType> statusor = v;\n    EXPECT_FALSE(statusor.ok());\n    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n  }\n}\n\nTEST(StatusOr, AssignmentFromT) {\n  // Assign to absl::StatusOr<T> from T when T is convertible to\n  // absl::StatusOr<T>\n  {\n    ConvertibleToAnyStatusOr v;\n    absl::StatusOr<ConvertibleToAnyStatusOr> statusor;\n    statusor = v;\n    EXPECT_TRUE(statusor.ok());\n  }\n  // Assign to absl::StatusOr<T> from T when T is convertible to Status\n  {\n    CustomType<MyType, kConvToStatus> v;\n    absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor;\n    statusor = v;\n    EXPECT_TRUE(statusor.ok());\n  }\n}\n\nTEST(StatusOr, AssignmentFromTypeConvertibleToT) {\n  // Assign to absl::StatusOr<T> from U when U is convertible to T\n  {\n    CustomType<MyType, kConvToT> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_TRUE(statusor.ok());\n  }\n}\n\nTEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) {\n  // Assign to absl::StatusOr<T> from U when U has conversion operator to\n  // absl::StatusOr<T>\n  {\n    CustomType<MyType, kConvToStatusOr> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatusOr> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());\n  }\n}\n\nTEST(StatusOr, AssignmentFromTypeConvertibleToStatus) {\n  // Assign to absl::StatusOr<T> from U when U is convertible to Status\n  {\n    CustomType<MyType, kConvToStatus> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_FALSE(statusor.ok());\n    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n  }\n  {\n    CustomType<MyType, kConvToT | kConvToStatus> v;\n    absl::StatusOr<MyType> statusor;\n    statusor = v;\n    EXPECT_FALSE(statusor.ok());\n    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n  }\n}\n\nTEST(StatusOr, StatusAssignmentFromStatusError) {\n  absl::StatusOr<absl::Status> statusor;\n  statusor.AssignStatus(absl::CancelledError());\n\n  EXPECT_FALSE(statusor.ok());\n  EXPECT_EQ(statusor.status(), absl::CancelledError());\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(StatusOr, StatusAssignmentFromStatusOk) {\n  EXPECT_DEBUG_DEATH(\n      {\n        absl::StatusOr<absl::Status> statusor;\n        // This will DCHECK.\n        statusor.AssignStatus(absl::OkStatus());\n        // In optimized mode, we are actually going to get error::INTERNAL for\n        // status here, rather than crashing, so check that.\n        EXPECT_FALSE(statusor.ok());\n        EXPECT_EQ(statusor.status().code(), absl::StatusCode::kInternal);\n      },\n      \"An OK status is not a valid constructor argument to StatusOr<T>\");\n}\n#endif\n\nTEST(StatusOr, StatusAssignmentFromTypeConvertibleToStatus) {\n  CustomType<MyType, kConvToStatus> v;\n  absl::StatusOr<MyType> statusor;\n  statusor.AssignStatus(v);\n\n  EXPECT_FALSE(statusor.ok());\n  EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));\n}\n\nstruct PrintTestStruct {\n  friend std::ostream& operator<<(std::ostream& os, const PrintTestStruct&) {\n    return os << \"ostream\";\n  }\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const PrintTestStruct&) {\n    sink.Append(\"stringify\");\n  }\n};\n\nTEST(StatusOr, OkPrinting) {\n  absl::StatusOr<PrintTestStruct> print_me = PrintTestStruct{};\n  std::stringstream stream;\n  stream << print_me;\n  EXPECT_EQ(stream.str(), \"ostream\");\n  EXPECT_EQ(absl::StrCat(print_me), \"stringify\");\n}\n\nTEST(StatusOr, ErrorPrinting) {\n  absl::StatusOr<PrintTestStruct> print_me = absl::UnknownError(\"error\");\n  std::stringstream stream;\n  stream << print_me;\n  const auto error_matcher =\n      AllOf(HasSubstr(\"UNKNOWN\"), HasSubstr(\"error\"),\n            AnyOf(AllOf(StartsWith(\"(\"), EndsWith(\")\")),\n                  AllOf(StartsWith(\"[\"), EndsWith(\"]\"))));\n  EXPECT_THAT(stream.str(), error_matcher);\n  EXPECT_THAT(absl::StrCat(print_me), error_matcher);\n}\n\n#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE\n#define GET_SOURCE_LOCATION(offset) __builtin_LINE() - offset\n#else\n#define GET_SOURCE_LOCATION(offset) 1\n#endif\n\ntemplate <typename T>\nvoid CheckSourceLocation(\n    const absl::StatusOr<T>& status_or, std::vector<int> lines = {},\n    absl::SourceLocation loc = absl::SourceLocation::current()) {\n  ASSERT_EQ(status_or.GetSourceLocations().size(), lines.size())\n      << \"Size check failed at \" << loc.line();\n  for (size_t i = 0; i < lines.size(); ++i) {\n    EXPECT_EQ(absl::string_view(status_or.GetSourceLocations()[i].file_name()),\n              absl::string_view(loc.file_name()))\n        << \"File name check failed at \" << loc.line();\n    EXPECT_EQ(status_or.GetSourceLocations()[i].line(), lines[i])\n        << \"Line check failed at \" << loc.line();\n  }\n}\n\nTEST(StatusOr, AddSourceLocation) {\n  constexpr int kMaxIter = 10;\n  {\n    // Status that ignores source location.\n    absl::StatusOr<int> status_ignores_source_location[] = {\n        123, absl::Status(absl::StatusCode::kInternal, \"\")};\n    for (absl::StatusOr<int>& s : status_ignores_source_location) {\n      for (int i = 0; i < kMaxIter; ++i) {\n        s.AddSourceLocation(absl::SourceLocation::current());\n        s.AddSourceLocation(absl::SourceLocation());\n      }\n      CheckSourceLocation(s);\n    }\n  }\n  {\n    // Default SourceLocation is not added.\n    absl::StatusOr<int> status = absl::Status(\n        absl::StatusCode::kInternal, \"foo\", absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    for (int i = 0; i < kMaxIter; ++i) {\n      status.AddSourceLocation(absl::SourceLocation());\n    }\n    CheckSourceLocation(status, {line});\n  }\n  {\n    // Default SourceLocation is not added.\n    absl::StatusOr<int> status = absl::Status(\n        absl::StatusCode::kInternal, \"foo\", absl::SourceLocation::current());\n    int line = GET_SOURCE_LOCATION(1);\n    std::vector<int> lines = {line};\n    lines.reserve(1 + kMaxIter);\n    for (int i = 0; i < kMaxIter; ++i) {\n      status.AddSourceLocation(absl::SourceLocation::current());\n      lines.push_back(GET_SOURCE_LOCATION(1));\n    }\n    CheckSourceLocation(status, lines);\n  }\n}\n\nabsl::StatusOr<int>&& IsRvalueStatus(absl::StatusOr<int>&& s) {\n  return std::move(s);\n}\n\nTEST(StatusOr, WithSourceLocationMove) {\n  absl::StatusOr<int> original = absl::Status(\n      absl::StatusCode::kInternal, \"message\", absl::SourceLocation::current());\n  int line = GET_SOURCE_LOCATION(1);\n\n  const absl::StatusOr<int> status_or = IsRvalueStatus(\n      std::move(original).WithSourceLocation(absl::SourceLocation::current()));\n  int line2 = GET_SOURCE_LOCATION(1);\n\n  CheckSourceLocation(status_or, {line, line2});\n  EXPECT_FALSE(status_or.ok());\n}\n\nTEST(StatusOr, WithSourceLocationReturn) {\n  absl::SourceLocation loc1 = absl::SourceLocation::current();\n  int line1 = GET_SOURCE_LOCATION(1);\n  absl::SourceLocation loc2 = absl::SourceLocation::current();\n  int line2 = GET_SOURCE_LOCATION(1);\n\n  const auto return_error = [&loc1]() -> absl::StatusOr<int> {\n    return absl::InvalidArgumentError(\"I am error\", loc1);\n  };\n  const auto return_error_with_source_location =\n      [&return_error, &loc2]() -> absl::StatusOr<int> {\n    return return_error().WithSourceLocation(loc2);\n  };\n\n  absl::StatusOr<int> status_or = return_error_with_source_location();\n  CheckSourceLocation(status_or, {line1, line2});\n  EXPECT_FALSE(status_or.ok());\n}\n\nTEST(StatusOr, SupportsReferenceTypes) {\n  int i = 1;\n  absl::StatusOr<int&> s = i;\n  EXPECT_EQ(&i, &*s);\n  *s = 10;\n  EXPECT_EQ(i, 10);\n}\n\nTEST(StatusOr, ReferenceFromStatus) {\n  int i = 10;\n  absl::StatusOr<int&> s = i;\n  s = absl::InternalError(\"foo\");\n  EXPECT_EQ(s.status().message(), \"foo\");\n\n  absl::StatusOr<int&> s2 = absl::InternalError(\"foo2\");\n  EXPECT_EQ(s2.status().message(), \"foo2\");\n}\n\nTEST(StatusOr, SupportReferenceValueConstructor) {\n  int i = 1;\n  absl::StatusOr<int&> s = i;\n  absl::StatusOr<const int&> cs = i;\n  absl::StatusOr<const int&> cs2 = std::move(i);  // `T&&` to `const T&` is ok.\n\n  EXPECT_EQ(&i, &*s);\n  EXPECT_EQ(&i, &*cs);\n\n  Derived d;\n  absl::StatusOr<const Base1&> b = d;\n  EXPECT_EQ(&d, &*b);\n\n  // We disallow constructions that cause temporaries.\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<const int&>, double>));\n  EXPECT_FALSE(\n      (std::is_constructible_v<absl::StatusOr<const int&>, const double&>));\n  EXPECT_FALSE(\n      (std::is_constructible_v<absl::StatusOr<const absl::string_view&>,\n                               std::string>));\n\n  // We disallow constructions with wrong reference.\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<int&>, int&&>));\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<int&>, const int&>));\n}\n\nTEST(StatusOr, SupportReferenceConvertingConstructor) {\n  int i = 1;\n  absl::StatusOr<int&> s = i;\n  absl::StatusOr<const int&> cs = s;\n\n  EXPECT_EQ(&i, &*s);\n  EXPECT_EQ(&i, &*cs);\n\n  // The other direction is not allowed.\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<int&>,\n                                        absl::StatusOr<const int&>>));\n\n  Derived d;\n  absl::StatusOr<const Base1&> b = absl::StatusOr<const Derived&>(d);\n  EXPECT_EQ(&d, &*b);\n\n  // The other direction is not allowed.\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<const Derived&>,\n                                        absl::StatusOr<const Base1&>>));\n\n  // We disallow conversions that cause temporaries.\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<const int&>,\n                                        absl::StatusOr<int>>));\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<const int&>,\n                                        absl::StatusOr<double>>));\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<const int&>,\n                                        absl::StatusOr<const double&>>));\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<const double&>,\n                                        absl::StatusOr<const int&>>));\n  EXPECT_FALSE(\n      (std::is_constructible_v<absl::StatusOr<const absl::string_view&>,\n                               absl::StatusOr<std::string>>));\n\n  // We disallow constructions with wrong reference.\n  EXPECT_FALSE((std::is_constructible_v<absl::StatusOr<int&>,\n                                        absl::StatusOr<const int&>>));\n}\n\nTEST(StatusOr, SupportReferenceValueAssignment) {\n  int i = 1;\n  absl::StatusOr<int&> s = i;\n  absl::StatusOr<const int&> cs;\n  cs = i;\n  absl::StatusOr<const int&> cs2;\n  cs2 = std::move(i);  // `T&&` to `const T&` is ok.\n\n  EXPECT_EQ(&i, &*s);\n  EXPECT_EQ(&i, &*cs);\n\n  Derived d;\n  absl::StatusOr<const Base1&> b;\n  b = d;\n  EXPECT_EQ(&d, &*b);\n\n  // We disallow constructions that cause temporaries.\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<const int&>, double>));\n  EXPECT_FALSE(\n      (std::is_assignable_v<absl::StatusOr<const int&>, const double&>));\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<const absl::string_view&>,\n                                     std::string>));\n\n  // We disallow constructions with wrong reference.\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<int&>, int&&>));\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<int&>, const int&>));\n}\n\nTEST(StatusOr, SupportReferenceConvertingAssignment) {\n  int i = 1;\n  absl::StatusOr<int&> s;\n  s = i;\n  absl::StatusOr<const int&> cs;\n  cs = s;\n\n  EXPECT_EQ(&i, &*s);\n  EXPECT_EQ(&i, &*cs);\n\n  // The other direction is not allowed.\n  EXPECT_FALSE(\n      (std::is_assignable_v<absl::StatusOr<int&>, absl::StatusOr<const int&>>));\n\n  Derived d;\n  absl::StatusOr<const Base1&> b;\n  b = absl::StatusOr<const Derived&>(d);\n  EXPECT_EQ(&d, &*b);\n\n  // The other direction is not allowed.\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<const Derived&>,\n                                     absl::StatusOr<const Base1&>>));\n\n  // We disallow conversions that cause temporaries.\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<const int&>,\n                                     absl::StatusOr<const double&>>));\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<const int&>,\n                                     absl::StatusOr<double>>));\n  EXPECT_FALSE((std::is_assignable_v<absl::StatusOr<const absl::string_view&>,\n                                     absl::StatusOr<std::string>>));\n\n  // We disallow constructions with wrong reference.\n  EXPECT_FALSE(\n      (std::is_assignable_v<absl::StatusOr<int&>, absl::StatusOr<const int&>>));\n}\n\nTEST(StatusOr, SupportReferenceToNonReferenceConversions) {\n  int i = 17;\n  absl::StatusOr<int&> si = i;\n  absl::StatusOr<float> sf = si;\n  EXPECT_THAT(sf, IsOkAndHolds(17.));\n\n  i = 20;\n  sf = si;\n  EXPECT_THAT(sf, IsOkAndHolds(20.));\n\n  EXPECT_THAT(absl::StatusOr<int64_t>(absl::StatusOr<int&>(i)),\n              IsOkAndHolds(20));\n  EXPECT_THAT(absl::StatusOr<int64_t>(absl::StatusOr<const int&>(i)),\n              IsOkAndHolds(20));\n\n  std::string str = \"str\";\n  absl::StatusOr<std::string> sos = absl::StatusOr<std::string&>(str);\n  EXPECT_THAT(sos, IsOkAndHolds(\"str\"));\n  str = \"str2\";\n  EXPECT_THAT(sos, IsOkAndHolds(\"str\"));\n  sos = absl::StatusOr<std::string&>(str);\n  EXPECT_THAT(sos, IsOkAndHolds(\"str2\"));\n\n  absl::StatusOr<absl::string_view> sosv = absl::StatusOr<std::string&>(str);\n  EXPECT_THAT(sosv, IsOkAndHolds(\"str2\"));\n  str = \"str3\";\n  sosv = absl::StatusOr<std::string&>(str);\n  EXPECT_THAT(sosv, IsOkAndHolds(\"str3\"));\n\n  absl::string_view view = \"view\";\n  // This way it is constructible, but not convertible because\n  // string_view->string is explicit\n  EXPECT_THAT(\n      absl::StatusOr<std::string>(absl::StatusOr<absl::string_view&>(view)),\n      IsOkAndHolds(\"view\"));\n#if defined(ABSL_USES_STD_STRING_VIEW)\n  // The assignment doesn't work with normal absl::string_view because\n  // std::string doesn't know about it.\n  sos = absl::StatusOr<absl::string_view&>(view);\n  EXPECT_THAT(sos, IsOkAndHolds(\"view\"));\n#endif\n\n  EXPECT_FALSE((std::is_convertible_v<absl::StatusOr<absl::string_view&>,\n                                      absl::StatusOr<std::string>>));\n}\n\nTEST(StatusOr, ReferenceOperatorStarAndArrow) {\n  std::string str = \"Foo\";\n  absl::StatusOr<std::string&> s = str;\n  s->assign(\"Bar\");\n  EXPECT_EQ(str, \"Bar\");\n\n  *s = \"Baz\";\n  EXPECT_EQ(str, \"Baz\");\n\n  const absl::StatusOr<std::string&> cs = str;\n  // Even if the StatusOr is const, the reference it gives is non-const so we\n  // can still assign.\n  *cs = \"Finally\";\n  EXPECT_EQ(str, \"Finally\");\n\n  cs->clear();\n  EXPECT_EQ(cs.value(), str);\n  EXPECT_EQ(str, \"\");\n}\n\nTEST(StatusOr, ReferenceValueOr) {\n  int i = 17;\n  absl::StatusOr<int&> si = i;\n\n  int other = 20;\n  EXPECT_EQ(&i, &si.value_or(other));\n\n  si = absl::UnknownError(\"\");\n  EXPECT_EQ(&other, &si.value_or(other));\n\n  absl::StatusOr<const int&> csi = i;\n  EXPECT_EQ(&i, &csi.value_or(1));\n\n  const auto value_or_call = [](auto&& sor, auto&& v)\n      -> decltype(std::forward<decltype(sor)>(sor).value_or(\n          std::forward<decltype(v)>(v))) {};\n  using Probe = decltype(value_or_call);\n  // Just to verify that Probe works as expected in the good cases.\n  EXPECT_TRUE((std::is_invocable_v<Probe, absl::StatusOr<const int&>, int&&>));\n  // Causes temporary conversion.\n  EXPECT_FALSE(\n      (std::is_invocable_v<Probe, absl::StatusOr<const int&>, double&&>));\n  // Const invalid.\n  EXPECT_FALSE((std::is_invocable_v<Probe, absl::StatusOr<int&>, const int&>));\n}\n\nTEST(StatusOr, ReferenceAssignmentFromStatusOr) {\n  std::vector<int> v = {1, 2, 3};\n  absl::StatusOr<int&> si = v[0];\n  absl::StatusOr<int&> si2 = v[1];\n\n  EXPECT_THAT(v, ElementsAre(1, 2, 3));\n  EXPECT_THAT(si, IsOkAndHolds(1));\n  EXPECT_THAT(si2, IsOkAndHolds(2));\n\n  // This rebinds the reference.\n  si = si2;\n  EXPECT_THAT(v, ElementsAre(1, 2, 3));\n  EXPECT_THAT(si, IsOkAndHolds(2));\n  EXPECT_THAT(si2, IsOkAndHolds(2));\n  EXPECT_EQ(&*si, &*si2);\n}\n\nTEST(StatusOr, ReferenceAssignFromReference) {\n  std::vector<int> v = {1, 2, 3};\n  absl::StatusOr<int&> si = v[0];\n\n  EXPECT_THAT(v, ElementsAre(1, 2, 3));\n  EXPECT_THAT(si, IsOkAndHolds(1));\n\n  // This rebinds the reference.\n  si = v[2];\n  EXPECT_THAT(v, ElementsAre(1, 2, 3));\n  EXPECT_THAT(si, IsOkAndHolds(3));\n  EXPECT_EQ(&*si, &v[2]);\n}\n\nTEST(StatusOr, ReferenceIsNotLifetimeBoundForStarValue) {\n  int i = 0;\n\n  // op*/value should not be LIFETIME_BOUND because the ref is not limited to\n  // the lifetime of the StatusOr.\n  int& r = *absl::StatusOr<int&>(i);\n  EXPECT_EQ(&r, &i);\n  int& r2 = absl::StatusOr<int&>(i).value();\n  EXPECT_EQ(&r2, &i);\n\n  struct S {\n    int i;\n  };\n  S s;\n  // op-> should also not be LIFETIME_BOUND for refs.\n  int& r3 = absl::StatusOr<S&>(s)->i;\n  EXPECT_EQ(&r3, &s.i);\n}\n\ntemplate <typename Expected, typename T>\nvoid TestReferenceDeref() {\n  static_assert(std::is_same_v<Expected, decltype(*std::declval<T>())>);\n  static_assert(std::is_same_v<Expected, decltype(std::declval<T>().value())>);\n}\n\nTEST(StatusOr, ReferenceTypeIsMaintainedOnDeref) {\n  TestReferenceDeref<int&, absl::StatusOr<int&>&>();\n  TestReferenceDeref<int&, absl::StatusOr<int&>&&>();\n  TestReferenceDeref<int&, const absl::StatusOr<int&>&>();\n  TestReferenceDeref<int&, const absl::StatusOr<int&>&&>();\n\n  TestReferenceDeref<const int&, absl::StatusOr<const int&>&>();\n  TestReferenceDeref<const int&, absl::StatusOr<const int&>&&>();\n  TestReferenceDeref<const int&, const absl::StatusOr<const int&>&>();\n  TestReferenceDeref<const int&, const absl::StatusOr<const int&>&&>();\n\n  struct Struct {\n    int value;\n  };\n  EXPECT_TRUE(\n      (std::is_same_v<\n          int&, decltype((std::declval<absl::StatusOr<Struct&>>()->value))>));\n  EXPECT_TRUE(\n      (std::is_same_v<\n          int&,\n          decltype((std::declval<const absl::StatusOr<Struct&>>()->value))>));\n  EXPECT_TRUE(\n      (std::is_same_v<\n          const int&,\n          decltype((std::declval<absl::StatusOr<const Struct&>>()->value))>));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"string_view\",\n    hdrs = [\"string_view.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n    ],\n)\n\ncc_library(\n    name = \"strings\",\n    srcs = [\n        \"ascii.cc\",\n        \"charconv.cc\",\n        \"escaping.cc\",\n        \"internal/charconv_bigint.cc\",\n        \"internal/charconv_bigint.h\",\n        \"internal/charconv_parse.cc\",\n        \"internal/charconv_parse.h\",\n        \"internal/damerau_levenshtein_distance.cc\",\n        \"internal/memutil.cc\",\n        \"internal/memutil.h\",\n        \"internal/stl_type_traits.h\",\n        \"internal/str_join_internal.h\",\n        \"internal/str_split_internal.h\",\n        \"internal/stringify_sink.cc\",\n        \"internal/stringify_sink.h\",\n        \"match.cc\",\n        \"numbers.cc\",\n        \"str_cat.cc\",\n        \"str_replace.cc\",\n        \"str_split.cc\",\n        \"substitute.cc\",\n    ],\n    hdrs = [\n        \"ascii.h\",\n        \"charconv.h\",\n        \"escaping.h\",\n        \"has_absl_stringify.h\",\n        \"internal/damerau_levenshtein_distance.h\",\n        \"internal/string_constant.h\",\n        \"match.h\",\n        \"numbers.h\",\n        \"str_cat.h\",\n        \"str_join.h\",\n        \"str_replace.h\",\n        \"str_split.h\",\n        \"string_view.h\",\n        \"strip.h\",\n        \"substitute.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    textual_hdrs = [\n        # string_view.h was once part of :strings, so string_view.h is\n        # re-exported for backwards compatibility.\n        # New code should directly depend on :string_view.\n        \"string_view.h\",\n    ],\n    deps = [\n        \":append_and_overwrite\",\n        \":charset\",\n        \":internal\",\n        \":resize_and_overwrite\",\n        \":string_view\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:iterator_traits_internal\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/memory\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/numeric:int128\",\n        \"//absl/types:source_location\",\n    ],\n)\n\ncc_library(\n    name = \"internal\",\n    srcs = [\n        \"internal/escaping.cc\",\n        \"internal/ostringstream.cc\",\n        \"internal/utf8.cc\",\n    ],\n    hdrs = [\n        \"internal/escaping.h\",\n        \"internal/ostringstream.h\",\n        \"internal/resize_uninitialized.h\",\n        \"internal/utf8.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":resize_and_overwrite\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_library(\n    name = \"resize_and_overwrite\",\n    hdrs = [\"resize_and_overwrite.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:throw_delegate\",\n    ],\n)\n\ncc_test(\n    name = \"resize_and_overwrite_test\",\n    srcs = [\"resize_and_overwrite_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":resize_and_overwrite\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/log:absl_check\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"append_and_overwrite\",\n    hdrs = [\"internal/append_and_overwrite.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":resize_and_overwrite\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:throw_delegate\",\n    ],\n)\n\ncc_test(\n    name = \"append_and_overwrite_test\",\n    srcs = [\"internal/append_and_overwrite_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":append_and_overwrite\",\n        \"//absl/log:absl_check\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"match_test\",\n    size = \"small\",\n    srcs = [\"match_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"escaping_test\",\n    size = \"small\",\n    srcs = [\n        \"escaping_test.cc\",\n        \"internal/escaping_test_common.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"no_test_chromiumos_x86_64\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:fixed_array\",\n        \"//absl/log:check\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"escaping_benchmark\",\n    testonly = True,\n    srcs = [\n        \"escaping_benchmark.cc\",\n        \"internal/escaping_test_common.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:raw_logging_internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"has_absl_stringify_test\",\n    size = \"small\",\n    srcs = [\"has_absl_stringify_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"has_ostream_operator\",\n    hdrs = [\"has_ostream_operator.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"has_ostream_operator_test\",\n    size = \"small\",\n    srcs = [\"has_ostream_operator_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":has_ostream_operator\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"ascii_test\",\n    size = \"small\",\n    srcs = [\"ascii_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"ascii_benchmark\",\n    testonly = True,\n    srcs = [\"ascii_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/random\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"damerau_levenshtein_distance_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/damerau_levenshtein_distance_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"damerau_levenshtein_distance_benchmark\",\n    testonly = True,\n    srcs = [\n        \"internal/damerau_levenshtein_distance_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_binary(\n    name = \"memutil_benchmark\",\n    testonly = True,\n    srcs = [\n        \"internal/memutil.h\",\n        \"internal/memutil_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"memutil_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/memutil.h\",\n        \"internal/memutil_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"utf8_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/utf8_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":internal\",\n        \":string_view\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"string_constant_test\",\n    size = \"small\",\n    srcs = [\"internal/string_constant_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"string_view_test\",\n    size = \"small\",\n    srcs = [\"string_view_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":string_view\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"stringify_stream\",\n    hdrs = [\"internal/stringify_stream.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n        \"//visibility:private\",\n    ],\n    deps = [\n        \":string_view\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"stringify_stream_test\",\n    srcs = [\"internal/stringify_stream_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":string_view\",\n        \":stringify_stream\",\n        \"//absl/base:config\",\n        \"//absl/strings:str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"charset_benchmark\",\n    testonly = True,\n    srcs = [\n        \"charset_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    tags = [\n        \"benchmark\",\n    ],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":charset\",\n        \"//absl/log:check\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"charset\",\n    hdrs = [\n        \"charset.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":string_view\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"charset_test\",\n    size = \"small\",\n    srcs = [\"charset_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":charset\",\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"cord_internal\",\n    srcs = [\n        \"internal/cord_internal.cc\",\n        \"internal/cord_rep_btree.cc\",\n        \"internal/cord_rep_btree_navigator.cc\",\n        \"internal/cord_rep_btree_reader.cc\",\n        \"internal/cord_rep_consume.cc\",\n        \"internal/cord_rep_crc.cc\",\n    ],\n    hdrs = [\n        \"internal/cord_data_edge.h\",\n        \"internal/cord_internal.h\",\n        \"internal/cord_rep_btree.h\",\n        \"internal/cord_rep_btree_navigator.h\",\n        \"internal/cord_rep_btree_reader.h\",\n        \"internal/cord_rep_consume.h\",\n        \"internal/cord_rep_crc.h\",\n        \"internal/cord_rep_flat.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//visibility:private\",\n    ],\n    deps = [\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/container:compressed_tuple\",\n        \"//absl/container:container_memory\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/crc:crc_cord_state\",\n        \"//absl/functional:function_ref\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_test(\n    name = \"cord_data_edge_test\",\n    size = \"small\",\n    srcs = [\"internal/cord_data_edge_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord_internal\",\n        \":cord_rep_test_util\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cord_rep_btree_test\",\n    size = \"medium\",\n    timeout = \"long\",\n    srcs = [\"internal/cord_rep_btree_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord_internal\",\n        \":cord_rep_test_util\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/cleanup\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cord_rep_btree_navigator_test\",\n    size = \"medium\",\n    srcs = [\"internal/cord_rep_btree_navigator_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord_internal\",\n        \":cord_rep_test_util\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cord_rep_btree_reader_test\",\n    size = \"medium\",\n    srcs = [\"internal/cord_rep_btree_reader_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":cord_rep_test_util\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cord_rep_crc_test\",\n    size = \"small\",\n    srcs = [\"internal/cord_rep_crc_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord_internal\",\n        \":cord_rep_test_util\",\n        \"//absl/base:config\",\n        \"//absl/crc:crc_cord_state\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_update_tracker\",\n    hdrs = [\"internal/cordz_update_tracker.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\"//absl/base:config\"],\n)\n\ncc_test(\n    name = \"cordz_update_tracker_test\",\n    srcs = [\"internal/cordz_update_tracker_test.cc\"],\n    deps = [\n        \":cordz_update_tracker\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"cord\",\n    srcs = [\n        \"cord.cc\",\n        \"cord_analysis.cc\",\n        \"cord_analysis.h\",\n    ],\n    hdrs = [\n        \"cord.h\",\n        \"cord_buffer.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":append_and_overwrite\",\n        \":cord_internal\",\n        \":cordz_info\",\n        \":cordz_update_scope\",\n        \":cordz_update_tracker\",\n        \":internal\",\n        \":resize_and_overwrite\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/crc:crc32c\",\n        \"//absl/crc:crc_cord_state\",\n        \"//absl/functional:function_ref\",\n        \"//absl/hash:weakly_mixed_integer\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/types:compare\",\n        \"//absl/types:optional\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_handle\",\n    srcs = [\"internal/cordz_handle.cc\"],\n    hdrs = [\"internal/cordz_handle.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//absl:__subpackages__\"],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_info\",\n    srcs = [\"internal/cordz_info.cc\"],\n    hdrs = [\"internal/cordz_info.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":cord_internal\",\n        \":cordz_functions\",\n        \":cordz_handle\",\n        \":cordz_statistics\",\n        \":cordz_update_tracker\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/debugging:stacktrace\",\n        \"//absl/synchronization\",\n        \"//absl/time\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_update_scope\",\n    hdrs = [\"internal/cordz_update_scope.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//absl:__subpackages__\"],\n    deps = [\n        \":cord_internal\",\n        \":cordz_info\",\n        \":cordz_update_tracker\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_update_scope_test\",\n    srcs = [\"internal/cordz_update_scope_test.cc\"],\n    copts = ABSL_DEFAULT_COPTS,\n    deps = [\n        \":cord_internal\",\n        \":cordz_info\",\n        \":cordz_test_helpers\",\n        \":cordz_update_scope\",\n        \":cordz_update_tracker\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_sample_token\",\n    srcs = [\"internal/cordz_sample_token.cc\"],\n    hdrs = [\"internal/cordz_sample_token.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":cordz_handle\",\n        \":cordz_info\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_functions\",\n    srcs = [\"internal/cordz_functions.cc\"],\n    hdrs = [\"internal/cordz_functions.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/profiling:exponential_biased\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_statistics\",\n    hdrs = [\"internal/cordz_statistics.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":cordz_update_tracker\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_functions_test\",\n    srcs = [\n        \"internal/cordz_functions_test.cc\",\n    ],\n    deps = [\n        \":cordz_functions\",\n        \":cordz_test_helpers\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_handle_test\",\n    srcs = [\n        \"internal/cordz_handle_test.cc\",\n    ],\n    deps = [\n        \":cordz_handle\",\n        \"//absl/base:config\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"//absl/synchronization\",\n        \"//absl/synchronization:thread_pool\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_info_test\",\n    srcs = [\n        \"internal/cordz_info_test.cc\",\n    ],\n    deps = [\n        \":cord_internal\",\n        \":cordz_handle\",\n        \":cordz_info\",\n        \":cordz_statistics\",\n        \":cordz_test_helpers\",\n        \":cordz_update_tracker\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/debugging:stacktrace\",\n        \"//absl/debugging:symbolize\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_info_statistics_test\",\n    srcs = [\n        \"internal/cordz_info_statistics_test.cc\",\n    ],\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":cordz_info\",\n        \":cordz_sample_token\",\n        \":cordz_statistics\",\n        \":cordz_update_scope\",\n        \":cordz_update_tracker\",\n        \"//absl/base:config\",\n        \"//absl/crc:crc_cord_state\",\n        \"//absl/synchronization\",\n        \"//absl/synchronization:thread_pool\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_sample_token_test\",\n    srcs = [\n        \"internal/cordz_sample_token_test.cc\",\n    ],\n    deps = [\n        \":cord_internal\",\n        \":cordz_handle\",\n        \":cordz_info\",\n        \":cordz_sample_token\",\n        \":cordz_test_helpers\",\n        \"//absl/base:config\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/synchronization\",\n        \"//absl/synchronization:thread_pool\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"cord_test_helpers\",\n    testonly = True,\n    hdrs = [\n        \"cord_test_helpers.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":strings\",\n        \"//absl/base:config\",\n    ],\n)\n\ncc_library(\n    name = \"cord_rep_test_util\",\n    testonly = True,\n    hdrs = [\"internal/cord_rep_test_util.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":cord_internal\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"cordz_test_helpers\",\n    testonly = True,\n    hdrs = [\"cordz_test_helpers.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":cordz_info\",\n        \":cordz_sample_token\",\n        \":cordz_statistics\",\n        \":cordz_update_tracker\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"cord_buffer_test\",\n    size = \"small\",\n    srcs = [\"cord_buffer_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":cord_rep_test_util\",\n        \":string_view\",\n        \"//absl/base:config\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cord_test\",\n    size = \"medium\",\n    timeout = \"long\",\n    srcs = [\"cord_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":cord_test_helpers\",\n        \":cordz_functions\",\n        \":cordz_statistics\",\n        \":cordz_test_helpers\",\n        \":cordz_update_tracker\",\n        \":str_format\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:endian\",\n        \"//absl/base:no_destructor\",\n        \"//absl/container:fixed_array\",\n        \"//absl/functional:function_ref\",\n        \"//absl/hash\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/log\",\n        \"//absl/log:check\",\n        \"//absl/random\",\n        \"//absl/types:compare\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"cordz_test\",\n    size = \"medium\",\n    srcs = [\"cordz_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\n        \"no_test_android_arm\",\n        \"no_test_android_arm64\",\n        \"no_test_android_x86\",\n        \"no_test_ios_x86_64\",\n        \"no_test_lexan\",\n        \"no_test_loonix\",\n    ],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":cord_internal\",\n        \":cord_test_helpers\",\n        \":cordz_functions\",\n        \":cordz_info\",\n        \":cordz_sample_token\",\n        \":cordz_statistics\",\n        \":cordz_test_helpers\",\n        \":cordz_update_tracker\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"substitute_test\",\n    size = \"small\",\n    srcs = [\"substitute_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"substitute_benchmark\",\n    testonly = True,\n    srcs = [\"substitute_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\n        \"benchmark\",\n    ],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_binary(\n    name = \"str_replace_benchmark\",\n    testonly = True,\n    srcs = [\"str_replace_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:raw_logging_internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_replace_test\",\n    size = \"small\",\n    srcs = [\"str_replace_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_split_test\",\n    srcs = [\"str_split_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/container:btree\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/container:node_hash_map\",\n        \"//absl/hash\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"str_split_benchmark\",\n    testonly = True,\n    srcs = [\"str_split_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:raw_logging_internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"ostringstream_test\",\n    size = \"small\",\n    srcs = [\"internal/ostringstream_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"ostringstream_benchmark\",\n    testonly = True,\n    srcs = [\"internal/ostringstream_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"resize_uninitialized_test\",\n    size = \"small\",\n    srcs = [\n        \"internal/resize_uninitialized_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":internal\",\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_join_test\",\n    size = \"small\",\n    srcs = [\"str_join_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:core_headers\",\n        \"//absl/memory\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"str_join_benchmark\",\n    testonly = True,\n    srcs = [\"str_join_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_cat_test\",\n    size = \"small\",\n    srcs = [\"str_cat_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"str_cat_benchmark\",\n    testonly = True,\n    srcs = [\"str_cat_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \":strings\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"numbers_test\",\n    size = \"medium\",\n    srcs = [\n        \"internal/numbers_test_common.h\",\n        \"numbers_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":internal\",\n        \":pow10_helper\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/log\",\n        \"//absl/numeric:int128\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"numbers_benchmark\",\n    testonly = True,\n    srcs = [\"numbers_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    tags = [\"benchmark\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/random\",\n        \"//absl/random:distributions\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"strip_test\",\n    size = \"small\",\n    srcs = [\"strip_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"charconv_test\",\n    srcs = [\"charconv_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":pow10_helper\",\n        \":str_format\",\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"charconv_parse_test\",\n    srcs = [\n        \"internal/charconv_parse.h\",\n        \"internal/charconv_parse_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/log:check\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"charconv_bigint_test\",\n    srcs = [\n        \"internal/charconv_bigint.h\",\n        \"internal/charconv_bigint_test.cc\",\n        \"internal/charconv_parse.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":strings\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"charconv_benchmark\",\n    testonly = True,\n    srcs = [\n        \"charconv_benchmark.cc\",\n    ],\n    tags = [\n        \"benchmark\",\n    ],\n    deps = [\n        \":strings\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"str_format\",\n    hdrs = [\n        \"str_format.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":str_format_internal\",\n        \":string_view\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/types:span\",\n    ],\n)\n\ncc_library(\n    name = \"str_format_internal\",\n    srcs = [\n        \"internal/str_format/arg.cc\",\n        \"internal/str_format/bind.cc\",\n        \"internal/str_format/extension.cc\",\n        \"internal/str_format/float_conversion.cc\",\n        \"internal/str_format/output.cc\",\n        \"internal/str_format/parser.cc\",\n    ],\n    hdrs = [\n        \"internal/str_format/arg.h\",\n        \"internal/str_format/bind.h\",\n        \"internal/str_format/checker.h\",\n        \"internal/str_format/constexpr_parser.h\",\n        \"internal/str_format/extension.h\",\n        \"internal/str_format/float_conversion.h\",\n        \"internal/str_format/output.h\",\n        \"internal/str_format/parser.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":internal\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:fixed_array\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/functional:function_ref\",\n        \"//absl/meta:type_traits\",\n        \"//absl/numeric:bits\",\n        \"//absl/numeric:int128\",\n        \"//absl/numeric:representation\",\n        \"//absl/types:span\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_test\",\n    srcs = [\"str_format_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":str_format\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_extension_test\",\n    srcs = [\n        \"internal/str_format/extension_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \":str_format_internal\",\n        \":strings\",\n        \"//absl/random\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_arg_test\",\n    srcs = [\"internal/str_format/arg_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \":str_format_internal\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_bind_test\",\n    srcs = [\"internal/str_format/bind_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_checker_test\",\n    srcs = [\"internal/str_format/checker_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_convert_test\",\n    size = \"medium\",\n    timeout = \"long\",\n    srcs = [\"internal/str_format/convert_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \":str_format_internal\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/log\",\n        \"//absl/numeric:int128\",\n        \"//absl/types:span\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_output_test\",\n    srcs = [\"internal/str_format/output_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":cord\",\n        \":str_format_internal\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"str_format_parser_test\",\n    srcs = [\"internal/str_format/parser_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format_internal\",\n        \":string_view\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"pow10_helper\",\n    testonly = True,\n    srcs = [\"internal/pow10_helper.cc\"],\n    hdrs = [\"internal/pow10_helper.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\"//absl/base:config\"],\n)\n\ncc_test(\n    name = \"pow10_helper_test\",\n    srcs = [\"internal/pow10_helper_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":pow10_helper\",\n        \":str_format\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"atod_manual_test\",\n    testonly = True,\n    srcs = [\"atod_manual_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":str_format\",\n        \":strings\",\n        \"//absl/base\",\n    ],\n)\n\ncc_test(\n    name = \"char_formatting_test\",\n    srcs = [\n        \"char_formatting_test.cc\",\n    ],\n    deps = [\n        \":str_format\",\n        \":strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"generic_printer\",\n    srcs = [\n        \"internal/generic_printer.cc\",\n        \"internal/generic_printer_internal.h\",\n    ],\n    hdrs = [\"internal/generic_printer.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":str_format\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/log/internal:container\",\n        \"//absl/meta:requires\",\n    ],\n)\n\ncc_test(\n    name = \"generic_printer_test\",\n    srcs = [\"internal/generic_printer_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":generic_printer\",\n        \":strings\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/container:flat_hash_map\",\n        \"//absl/log\",\n        \"//absl/status\",\n        \"//absl/status:statusor\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/strings/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    string_view\n  HDRS\n    \"string_view.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::nullability\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    strings\n  HDRS\n    \"ascii.h\"\n    \"charconv.h\"\n    \"escaping.h\"\n    \"has_absl_stringify.h\"\n    \"internal/damerau_levenshtein_distance.h\"\n    \"internal/string_constant.h\"\n    \"match.h\"\n    \"numbers.h\"\n    \"str_cat.h\"\n    \"str_join.h\"\n    \"str_replace.h\"\n    \"str_split.h\"\n    \"strip.h\"\n    \"substitute.h\"\n  SRCS\n    \"ascii.cc\"\n    \"charconv.cc\"\n    \"escaping.cc\"\n    \"internal/charconv_bigint.cc\"\n    \"internal/charconv_bigint.h\"\n    \"internal/charconv_parse.cc\"\n    \"internal/charconv_parse.h\"\n    \"internal/damerau_levenshtein_distance.cc\"\n    \"internal/memutil.cc\"\n    \"internal/memutil.h\"\n    \"internal/stringify_sink.h\"\n    \"internal/stringify_sink.cc\"\n    \"internal/stl_type_traits.h\"\n    \"internal/str_join_internal.h\"\n    \"internal/str_split_internal.h\"\n    \"match.cc\"\n    \"numbers.cc\"\n    \"str_cat.cc\"\n    \"str_replace.cc\"\n    \"str_split.cc\"\n    \"substitute.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::string_view\n    absl::strings_append_and_overwrite\n    absl::strings_internal\n    absl::strings_resize_and_overwrite\n    absl::base\n    absl::bits\n    absl::charset\n    absl::config\n    absl::core_headers\n    absl::endian\n    absl::int128\n    absl::iterator_traits_internal\n    absl::memory\n    absl::nullability\n    absl::raw_logging_internal\n    absl::source_location\n    absl::strings\n    absl::throw_delegate\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    charset\n  HDRS\n    charset.h\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::string_view\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    has_ostream_operator\n  HDRS\n    \"has_ostream_operator.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    stringify_stream\n  HDRS\n    \"internal/stringify_stream.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::string_view\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    stringify_stream_test\n  SRCS\n    \"internal/stringify_stream_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::string_view\n    absl::stringify_stream\n    absl::str_format\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    strings_internal\n  HDRS\n    \"internal/escaping.cc\"\n    \"internal/escaping.h\"\n    \"internal/ostringstream.h\"\n    \"internal/resize_uninitialized.h\"\n    \"internal/utf8.h\"\n  SRCS\n    \"internal/ostringstream.cc\"\n    \"internal/utf8.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::endian\n    absl::raw_logging_internal\n    absl::strings_resize_and_overwrite\n    absl::type_traits\n)\n\nabsl_cc_library(\n  NAME\n    strings_resize_and_overwrite\n  HDRS\n    \"resize_and_overwrite.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::throw_delegate\n)\n\nabsl_cc_test(\n  NAME\n    strings_resize_and_overwrite_test\n  SRCS\n    \"resize_and_overwrite_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings_resize_and_overwrite\n    absl::absl_check\n    absl::dynamic_annotations\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    strings_append_and_overwrite\n  HDRS\n    \"internal/append_and_overwrite.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::strings_resize_and_overwrite\n    absl::throw_delegate\n)\n\nabsl_cc_test(\n  NAME\n    strings_append_and_overwrite_test\n  SRCS\n    \"internal/append_and_overwrite_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings_resize_and_overwrite\n    absl::absl_check\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    match_test\n  SRCS\n    \"match_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::base\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    escaping_test\n  SRCS\n    \"escaping_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::core_headers\n    absl::fixed_array\n    GTest::gmock_main\n    absl::check\n)\n\nabsl_cc_test(\n  NAME\n    has_absl_stringify_test\n  SRCS\n    \"has_absl_stringify_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    has_ostream_operator_test\n  SRCS\n    \"has_ostream_operator_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::has_ostream_operator\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    ascii_test\n  SRCS\n    \"ascii_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    damerau_levenshtein_distance_test\n  SRCS\n    \"internal/damerau_levenshtein_distance_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::base\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    memutil_test\n  SRCS\n    \"internal/memutil.h\"\n    \"internal/memutil_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    utf8_test\n  SRCS\n    \"internal/utf8_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::string_view\n    absl::strings_internal\n    absl::base\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    string_constant_test\n  SRCS\n    \"internal/string_constant_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::type_traits\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    string_view_test\n  SRCS\n    \"string_view_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::type_traits\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    substitute_test\n  SRCS\n    \"substitute_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_replace_test\n  SRCS\n    \"str_replace_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_split_test\n  SRCS\n    \"str_split_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::btree\n    absl::flat_hash_map\n    absl::hash\n    absl::node_hash_map\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    ostringstream_test\n  SRCS\n    \"internal/ostringstream_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings_internal\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    resize_uninitialized_test\n  SRCS\n    \"internal/resize_uninitialized_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings_internal\n    absl::base\n    absl::core_headers\n    absl::type_traits\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_join_test\n  SRCS\n    \"str_join_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::base\n    absl::core_headers\n    absl::memory\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_cat_test\n  SRCS\n    \"str_cat_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::str_format\n    absl::config\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    numbers_test\n  SRCS\n    \"internal/numbers_test_common.h\"\n    \"numbers_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::int128\n    absl::log\n    absl::pow10_helper\n    absl::random_distributions\n    absl::random_random\n    absl::strings\n    absl::strings_internal\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    strip_test\n  SRCS\n    \"strip_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::base\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    charset_test\n  SRCS\n    \"charset_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    charconv_test\n  SRCS\n    \"charconv_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::str_format\n    absl::pow10_helper\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    charconv_parse_test\n  SRCS\n    \"internal/charconv_parse.h\"\n    \"internal/charconv_parse_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::check\n    absl::config\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    charconv_bigint_test\n  SRCS\n    \"internal/charconv_bigint.h\"\n    \"internal/charconv_bigint_test.cc\"\n    \"internal/charconv_parse.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::strings\n    absl::config\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    str_format\n  HDRS\n    \"str_format.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::nullability\n    absl::span\n    absl::str_format_internal\n    absl::string_view\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    str_format_internal\n  HDRS\n    \"internal/str_format/arg.h\"\n    \"internal/str_format/bind.h\"\n    \"internal/str_format/checker.h\"\n    \"internal/str_format/constexpr_parser.h\"\n    \"internal/str_format/extension.h\"\n    \"internal/str_format/float_conversion.h\"\n    \"internal/str_format/output.h\"\n    \"internal/str_format/parser.h\"\n  SRCS\n    \"internal/str_format/arg.cc\"\n    \"internal/str_format/bind.cc\"\n    \"internal/str_format/extension.cc\"\n    \"internal/str_format/float_conversion.cc\"\n    \"internal/str_format/output.cc\"\n    \"internal/str_format/parser.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::bits\n    absl::strings\n    absl::config\n    absl::core_headers\n    absl::fixed_array\n    absl::inlined_vector\n    absl::numeric_representation\n    absl::type_traits\n    absl::utility\n    absl::int128\n    absl::span\n    absl::strings_internal\n)\n\nabsl_cc_test(\n  NAME\n    str_format_test\n  SRCS\n    \"str_format_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord\n    absl::core_headers\n    absl::span\n    absl::str_format\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_extension_test\n  SRCS\n    \"internal/str_format/extension_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::random_random\n    absl::str_format\n    absl::str_format_internal\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_arg_test\n  SRCS\n    \"internal/str_format/arg_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::str_format\n    absl::str_format_internal\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_bind_test\n  SRCS\n    \"internal/str_format/bind_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::str_format_internal\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_checker_test\n  SRCS\n    \"internal/str_format/checker_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::str_format\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_convert_test\n  SRCS\n    \"internal/str_format/convert_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::int128\n    absl::log\n    absl::raw_logging_internal\n    absl::span\n    absl::str_format\n    absl::str_format_internal\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_output_test\n  SRCS\n    \"internal/str_format/output_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::str_format_internal\n    absl::cord\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    str_format_parser_test\n  SRCS\n    \"internal/str_format/parser_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::str_format_internal\n    absl::string_view\n    absl::config\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    char_formatting_test\n  SRCS\n    \"char_formatting_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::str_format\n    absl::strings\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    pow10_helper\n  HDRS\n    \"internal/pow10_helper.h\"\n  SRCS\n    \"internal/pow10_helper.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    pow10_helper_test\n  SRCS\n    \"internal/pow10_helper_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::pow10_helper\n    absl::str_format\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cord_internal\n  HDRS\n    \"internal/cord_data_edge.h\"\n    \"internal/cord_internal.h\"\n    \"internal/cord_rep_btree.h\"\n    \"internal/cord_rep_btree_navigator.h\"\n    \"internal/cord_rep_btree_reader.h\"\n    \"internal/cord_rep_crc.h\"\n    \"internal/cord_rep_consume.h\"\n    \"internal/cord_rep_flat.h\"\n  SRCS\n    \"internal/cord_internal.cc\"\n    \"internal/cord_rep_btree.cc\"\n    \"internal/cord_rep_btree_navigator.cc\"\n    \"internal/cord_rep_btree_reader.cc\"\n    \"internal/cord_rep_crc.cc\"\n    \"internal/cord_rep_consume.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::compressed_tuple\n    absl::config\n    absl::container_memory\n    absl::compare\n    absl::core_headers\n    absl::crc_cord_state\n    absl::endian\n    absl::inlined_vector\n    absl::layout\n    absl::raw_logging_internal\n    absl::strings\n    absl::throw_delegate\n    absl::type_traits\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_update_tracker\n  HDRS\n    \"internal/cordz_update_tracker.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n)\n\nabsl_cc_test(\n  NAME\n    cordz_update_tracker_test\n  SRCS\n    \"internal/cordz_update_tracker_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cordz_update_tracker\n    absl::core_headers\n    absl::synchronization\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_functions\n  HDRS\n    \"internal/cordz_functions.h\"\n  SRCS\n    \"internal/cordz_functions.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::exponential_biased\n    absl::raw_logging_internal\n)\n\nabsl_cc_test(\n  NAME\n    cordz_functions_test\n  SRCS\n    \"internal/cordz_functions_test.cc\"\n  DEPS\n    absl::config\n    absl::cordz_functions\n    absl::cordz_test_helpers\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_statistics\n  HDRS\n    \"internal/cordz_statistics.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::cordz_update_tracker\n    absl::synchronization\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_handle\n  HDRS\n    \"internal/cordz_handle.h\"\n  SRCS\n    \"internal/cordz_handle.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::no_destructor\n    absl::raw_logging_internal\n    absl::synchronization\n)\n\nabsl_cc_test(\n  NAME\n    cordz_handle_test\n  SRCS\n    \"internal/cordz_handle_test.cc\"\n  DEPS\n    absl::config\n    absl::cordz_handle\n    absl::cordz_test_helpers\n    absl::memory\n    absl::random_random\n    absl::random_distributions\n    absl::synchronization\n    absl::time\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_info\n  HDRS\n    \"internal/cordz_info.h\"\n  SRCS\n    \"internal/cordz_info.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::cord_internal\n    absl::cordz_functions\n    absl::cordz_handle\n    absl::cordz_statistics\n    absl::cordz_update_tracker\n    absl::core_headers\n    absl::no_destructor\n    absl::inlined_vector\n    absl::span\n    absl::raw_logging_internal\n    absl::stacktrace\n    absl::synchronization\n    absl::time\n)\n\nabsl_cc_test(\n  NAME\n    cordz_info_test\n  SRCS\n    \"internal/cordz_info_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord_internal\n    absl::cordz_test_helpers\n    absl::cordz_handle\n    absl::cordz_info\n    absl::cordz_statistics\n    absl::cordz_test_helpers\n    absl::cordz_update_tracker\n    absl::span\n    absl::stacktrace\n    absl::symbolize\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cordz_info_statistics_test\n  SRCS\n    \"internal/cordz_info_statistics_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord\n    absl::cord_internal\n    absl::cordz_info\n    absl::cordz_sample_token\n    absl::cordz_statistics\n    absl::cordz_update_scope\n    absl::cordz_update_tracker\n    absl::crc_cord_state\n    absl::thread_pool\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_sample_token\n  HDRS\n    \"internal/cordz_sample_token.h\"\n  SRCS\n    \"internal/cordz_sample_token.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::cordz_handle\n    absl::cordz_info\n)\n\nabsl_cc_test(\n  NAME\n    cordz_sample_token_test\n  SRCS\n    \"internal/cordz_sample_token_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord_internal\n    absl::cordz_handle\n    absl::cordz_info\n    absl::cordz_info\n    absl::cordz_sample_token\n    absl::cordz_test_helpers\n    absl::memory\n    absl::random_random\n    absl::synchronization\n    absl::thread_pool\n    absl::time\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_update_scope\n  HDRS\n    \"internal/cordz_update_scope.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::cord_internal\n    absl::cordz_info\n    absl::cordz_update_tracker\n    absl::core_headers\n)\n\nabsl_cc_test(\n  NAME\n    cordz_update_scope_test\n  SRCS\n    \"internal/cordz_update_scope_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord_internal\n    absl::cordz_info\n    absl::cordz_test_helpers\n    absl::cordz_update_scope\n    absl::cordz_update_tracker\n    absl::core_headers\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    cord\n  HDRS\n    \"cord.h\"\n    \"cord_buffer.h\"\n  SRCS\n    \"cord.cc\"\n    \"cord_analysis.cc\"\n    \"cord_analysis.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::cord_internal\n    absl::cordz_functions\n    absl::cordz_info\n    absl::cordz_update_scope\n    absl::cordz_update_tracker\n    absl::core_headers\n    absl::crc32c\n    absl::crc_cord_state\n    absl::endian\n    absl::function_ref\n    absl::inlined_vector\n    absl::nullability\n    absl::optional\n    absl::raw_logging_internal\n    absl::span\n    absl::strings\n    absl::strings_append_and_overwrite\n    absl::strings_resize_and_overwrite\n    absl::type_traits\n    absl::weakly_mixed_integer\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cord_rep_test_util\n  HDRS\n    \"internal/cord_rep_test_util.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord_internal\n    absl::raw_logging_internal\n    absl::strings\n  TESTONLY\n)\n\nabsl_cc_library(\n  NAME\n    cord_test_helpers\n  HDRS\n    \"cord_test_helpers.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord\n    absl::cord_internal\n    absl::strings\n  TESTONLY\n  PUBLIC\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    cordz_test_helpers\n  HDRS\n    \"cordz_test_helpers.h\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord\n    absl::cord_internal\n    absl::cordz_info\n    absl::cordz_sample_token\n    absl::cordz_statistics\n    absl::cordz_update_tracker\n    absl::core_headers\n    absl::nullability\n    absl::strings\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    cord_test\n  SRCS\n    \"cord_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::check\n    absl::config\n    absl::cord\n    absl::cord_test_helpers\n    absl::cordz_test_helpers\n    absl::core_headers\n    absl::endian\n    absl::fixed_array\n    absl::function_ref\n    absl::hash\n    absl::hash_testing\n    absl::no_destructor\n    absl::log\n    absl::random_random\n    absl::str_format\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cord_data_edge_test\n  SRCS\n    \"internal/cord_data_edge_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::cord_internal\n    absl::cord_rep_test_util\n    absl::core_headers\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cord_rep_btree_test\n  SRCS\n    \"internal/cord_rep_btree_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::cleanup\n    absl::config\n    absl::cord_internal\n    absl::cord_rep_test_util\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cord_rep_btree_navigator_test\n  SRCS\n    \"internal/cord_rep_btree_navigator_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::cord_internal\n    absl::cord_rep_test_util\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cord_rep_btree_reader_test\n  SRCS\n    \"internal/cord_rep_btree_reader_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::cord_internal\n    absl::cord_rep_test_util\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cord_rep_crc_test\n  SRCS\n    \"internal/cord_rep_crc_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::cord_internal\n    absl::cord_rep_test_util\n    absl::crc_cord_state\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    cordz_test\n  SRCS\n    \"cordz_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::cord\n    absl::cord_internal\n    absl::cord_test_helpers\n    absl::cordz_test_helpers\n    absl::cordz_functions\n    absl::cordz_info\n    absl::cordz_sample_token\n    absl::cordz_statistics\n    absl::cordz_update_tracker\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    generic_printer_internal\n  SRCS\n    \"internal/generic_printer.cc\"\n    \"internal/generic_printer_internal.h\"\n  HDRS\n    \"internal/generic_printer.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::strings\n    absl::str_format\n    absl::log_internal_container\n    absl::requires_internal\n)\n\nabsl_cc_test(\n  NAME\n    generic_printer_test\n  SRCS\n    \"internal/generic_printer_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::flat_hash_map\n    absl::generic_printer_internal\n    absl::log\n    absl::status\n    absl::statusor\n    absl::strings\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/strings/ascii.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/ascii.h\"\n\n#include <climits>\n#include <cstddef>\n#include <cstring>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace ascii_internal {\n\n// # Table generated by this Python code (bit 0x02 is currently unused):\n// TODO(mbar) Move Python code for generation of table to BUILD and link here.\n\n// NOTE: The kAsciiPropertyBits table used within this code was generated by\n// Python code of the following form. (Bit 0x02 is currently unused and\n// available.)\n//\n// def Hex2(n):\n//   return '0x' + hex(n/16)[2:] + hex(n%16)[2:]\n// def IsPunct(ch):\n//   return (ord(ch) >= 32 and ord(ch) < 127 and\n//           not ch.isspace() and not ch.isalnum())\n// def IsBlank(ch):\n//   return ch in ' \\t'\n// def IsCntrl(ch):\n//   return ord(ch) < 32 or ord(ch) == 127\n// def IsXDigit(ch):\n//   return ch.isdigit() or ch.lower() in 'abcdef'\n// for i in range(128):\n//   ch = chr(i)\n//   mask = ((ch.isalpha() and 0x01 or 0) |\n//           (ch.isalnum() and 0x04 or 0) |\n//           (ch.isspace() and 0x08 or 0) |\n//           (IsPunct(ch) and 0x10 or 0) |\n//           (IsBlank(ch) and 0x20 or 0) |\n//           (IsCntrl(ch) and 0x40 or 0) |\n//           (IsXDigit(ch) and 0x80 or 0))\n//   print Hex2(mask) + ',',\n//   if i % 16 == 7:\n//     print ' //', Hex2(i & 0x78)\n//   elif i % 16 == 15:\n//     print\n\n// clang-format off\n// Array of bitfields holding character information. Each bit value corresponds\n// to a particular character feature. For readability, and because the value\n// of these bits is tightly coupled to this implementation, the individual bits\n// are not named. Note that bitfields for all characters above ASCII 127 are\n// zero-initialized.\nABSL_DLL const unsigned char kPropertyBits[256] = {\n    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x00\n    0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,\n    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x10\n    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\n    0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  // 0x20\n    0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,  // 0x30\n    0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\n    0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05,  // 0x40\n    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,  // 0x50\n    0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,\n    0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05,  // 0x60\n    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n    0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,  // 0x70\n    0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,\n};\n\n// Array of characters for the ascii_tolower() function. For values 'A'\n// through 'Z', return the lower-case character; otherwise, return the\n// identity of the passed character.\nABSL_DLL const char kToLower[256] = {\n  '\\x00', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\x07',\n  '\\x08', '\\x09', '\\x0a', '\\x0b', '\\x0c', '\\x0d', '\\x0e', '\\x0f',\n  '\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17',\n  '\\x18', '\\x19', '\\x1a', '\\x1b', '\\x1c', '\\x1d', '\\x1e', '\\x1f',\n  '\\x20', '\\x21', '\\x22', '\\x23', '\\x24', '\\x25', '\\x26', '\\x27',\n  '\\x28', '\\x29', '\\x2a', '\\x2b', '\\x2c', '\\x2d', '\\x2e', '\\x2f',\n  '\\x30', '\\x31', '\\x32', '\\x33', '\\x34', '\\x35', '\\x36', '\\x37',\n  '\\x38', '\\x39', '\\x3a', '\\x3b', '\\x3c', '\\x3d', '\\x3e', '\\x3f',\n  '\\x40',    'a',    'b',    'c',    'd',    'e',    'f',    'g',\n     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',\n     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',\n     'x',    'y',    'z', '\\x5b', '\\x5c', '\\x5d', '\\x5e', '\\x5f',\n  '\\x60', '\\x61', '\\x62', '\\x63', '\\x64', '\\x65', '\\x66', '\\x67',\n  '\\x68', '\\x69', '\\x6a', '\\x6b', '\\x6c', '\\x6d', '\\x6e', '\\x6f',\n  '\\x70', '\\x71', '\\x72', '\\x73', '\\x74', '\\x75', '\\x76', '\\x77',\n  '\\x78', '\\x79', '\\x7a', '\\x7b', '\\x7c', '\\x7d', '\\x7e', '\\x7f',\n  '\\x80', '\\x81', '\\x82', '\\x83', '\\x84', '\\x85', '\\x86', '\\x87',\n  '\\x88', '\\x89', '\\x8a', '\\x8b', '\\x8c', '\\x8d', '\\x8e', '\\x8f',\n  '\\x90', '\\x91', '\\x92', '\\x93', '\\x94', '\\x95', '\\x96', '\\x97',\n  '\\x98', '\\x99', '\\x9a', '\\x9b', '\\x9c', '\\x9d', '\\x9e', '\\x9f',\n  '\\xa0', '\\xa1', '\\xa2', '\\xa3', '\\xa4', '\\xa5', '\\xa6', '\\xa7',\n  '\\xa8', '\\xa9', '\\xaa', '\\xab', '\\xac', '\\xad', '\\xae', '\\xaf',\n  '\\xb0', '\\xb1', '\\xb2', '\\xb3', '\\xb4', '\\xb5', '\\xb6', '\\xb7',\n  '\\xb8', '\\xb9', '\\xba', '\\xbb', '\\xbc', '\\xbd', '\\xbe', '\\xbf',\n  '\\xc0', '\\xc1', '\\xc2', '\\xc3', '\\xc4', '\\xc5', '\\xc6', '\\xc7',\n  '\\xc8', '\\xc9', '\\xca', '\\xcb', '\\xcc', '\\xcd', '\\xce', '\\xcf',\n  '\\xd0', '\\xd1', '\\xd2', '\\xd3', '\\xd4', '\\xd5', '\\xd6', '\\xd7',\n  '\\xd8', '\\xd9', '\\xda', '\\xdb', '\\xdc', '\\xdd', '\\xde', '\\xdf',\n  '\\xe0', '\\xe1', '\\xe2', '\\xe3', '\\xe4', '\\xe5', '\\xe6', '\\xe7',\n  '\\xe8', '\\xe9', '\\xea', '\\xeb', '\\xec', '\\xed', '\\xee', '\\xef',\n  '\\xf0', '\\xf1', '\\xf2', '\\xf3', '\\xf4', '\\xf5', '\\xf6', '\\xf7',\n  '\\xf8', '\\xf9', '\\xfa', '\\xfb', '\\xfc', '\\xfd', '\\xfe', '\\xff',\n};\n\n// Array of characters for the ascii_toupper() function. For values 'a'\n// through 'z', return the upper-case character; otherwise, return the\n// identity of the passed character.\nABSL_DLL const char kToUpper[256] = {\n  '\\x00', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\x07',\n  '\\x08', '\\x09', '\\x0a', '\\x0b', '\\x0c', '\\x0d', '\\x0e', '\\x0f',\n  '\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17',\n  '\\x18', '\\x19', '\\x1a', '\\x1b', '\\x1c', '\\x1d', '\\x1e', '\\x1f',\n  '\\x20', '\\x21', '\\x22', '\\x23', '\\x24', '\\x25', '\\x26', '\\x27',\n  '\\x28', '\\x29', '\\x2a', '\\x2b', '\\x2c', '\\x2d', '\\x2e', '\\x2f',\n  '\\x30', '\\x31', '\\x32', '\\x33', '\\x34', '\\x35', '\\x36', '\\x37',\n  '\\x38', '\\x39', '\\x3a', '\\x3b', '\\x3c', '\\x3d', '\\x3e', '\\x3f',\n  '\\x40', '\\x41', '\\x42', '\\x43', '\\x44', '\\x45', '\\x46', '\\x47',\n  '\\x48', '\\x49', '\\x4a', '\\x4b', '\\x4c', '\\x4d', '\\x4e', '\\x4f',\n  '\\x50', '\\x51', '\\x52', '\\x53', '\\x54', '\\x55', '\\x56', '\\x57',\n  '\\x58', '\\x59', '\\x5a', '\\x5b', '\\x5c', '\\x5d', '\\x5e', '\\x5f',\n  '\\x60',    'A',    'B',    'C',    'D',    'E',    'F',    'G',\n     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',\n     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',\n     'X',    'Y',    'Z', '\\x7b', '\\x7c', '\\x7d', '\\x7e', '\\x7f',\n  '\\x80', '\\x81', '\\x82', '\\x83', '\\x84', '\\x85', '\\x86', '\\x87',\n  '\\x88', '\\x89', '\\x8a', '\\x8b', '\\x8c', '\\x8d', '\\x8e', '\\x8f',\n  '\\x90', '\\x91', '\\x92', '\\x93', '\\x94', '\\x95', '\\x96', '\\x97',\n  '\\x98', '\\x99', '\\x9a', '\\x9b', '\\x9c', '\\x9d', '\\x9e', '\\x9f',\n  '\\xa0', '\\xa1', '\\xa2', '\\xa3', '\\xa4', '\\xa5', '\\xa6', '\\xa7',\n  '\\xa8', '\\xa9', '\\xaa', '\\xab', '\\xac', '\\xad', '\\xae', '\\xaf',\n  '\\xb0', '\\xb1', '\\xb2', '\\xb3', '\\xb4', '\\xb5', '\\xb6', '\\xb7',\n  '\\xb8', '\\xb9', '\\xba', '\\xbb', '\\xbc', '\\xbd', '\\xbe', '\\xbf',\n  '\\xc0', '\\xc1', '\\xc2', '\\xc3', '\\xc4', '\\xc5', '\\xc6', '\\xc7',\n  '\\xc8', '\\xc9', '\\xca', '\\xcb', '\\xcc', '\\xcd', '\\xce', '\\xcf',\n  '\\xd0', '\\xd1', '\\xd2', '\\xd3', '\\xd4', '\\xd5', '\\xd6', '\\xd7',\n  '\\xd8', '\\xd9', '\\xda', '\\xdb', '\\xdc', '\\xdd', '\\xde', '\\xdf',\n  '\\xe0', '\\xe1', '\\xe2', '\\xe3', '\\xe4', '\\xe5', '\\xe6', '\\xe7',\n  '\\xe8', '\\xe9', '\\xea', '\\xeb', '\\xec', '\\xed', '\\xee', '\\xef',\n  '\\xf0', '\\xf1', '\\xf2', '\\xf3', '\\xf4', '\\xf5', '\\xf6', '\\xf7',\n  '\\xf8', '\\xf9', '\\xfa', '\\xfb', '\\xfc', '\\xfd', '\\xfe', '\\xff',\n};\n// clang-format on\n\n// Returns whether `c` is in the a-z/A-Z range (w.r.t. `ToUpper`).\n// Implemented by:\n//  1. Pushing the a-z/A-Z range to [SCHAR_MIN, SCHAR_MIN + 26).\n//  2. Comparing to SCHAR_MIN + 26.\ntemplate <bool ToUpper>\nconstexpr bool AsciiInAZRange(unsigned char c) {\n  constexpr unsigned char sub = (ToUpper ? 'a' : 'A') - SCHAR_MIN;\n  constexpr signed char threshold = SCHAR_MIN + 26;  // 26 = alphabet size.\n  // Using unsigned arithmetic as overflows/underflows are well defined.\n  unsigned char u = c - sub;\n  // Using signed cmp, as SIMD unsigned cmp isn't available in many platforms.\n  return static_cast<signed char>(u) < threshold;\n}\n\ntemplate <bool ToUpper>\nconstexpr bool AsciiInAZRangeNaive(unsigned char c) {\n  constexpr unsigned char a = (ToUpper ? 'a' : 'A');\n  constexpr unsigned char z = (ToUpper ? 'z' : 'Z');\n  return a <= c && c <= z;\n}\n\ntemplate <bool ToUpper, bool Naive>\nconstexpr void AsciiStrCaseFoldImpl(char* absl_nonnull dst,\n                                    const char* absl_nullable src,\n                                    size_t size) {\n  // The upper- and lowercase versions of ASCII characters differ by only 1 bit.\n  // When we need to flip the case, we can xor with this bit to achieve the\n  // desired result. Note that the choice of 'a' and 'A' here is arbitrary. We\n  // could have chosen 'z' and 'Z', or any other pair of characters as they all\n  // have the same single bit difference.\n  constexpr unsigned char kAsciiCaseBitFlip = 'a' ^ 'A';\n\n  for (size_t i = 0; i < size; ++i) {\n    unsigned char v = static_cast<unsigned char>(src[i]);\n    if ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 (Naive) {\n      v ^= AsciiInAZRangeNaive<ToUpper>(v) ? kAsciiCaseBitFlip : 0;\n    } else {\n      v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0;\n    }\n    dst[i] = static_cast<char>(v);\n  }\n}\n\n// Splitting to short and long strings to allow vectorization decisions\n// to be made separately in the long and short cases.\n// Using slightly different implementations so the compiler won't optimize them\n// into the same code (the non-naive version is needed for SIMD, so for short\n// strings it's not important).\n// `src` may be null iff `size` is zero.\ntemplate <bool ToUpper>\nconstexpr void AsciiStrCaseFold(char* absl_nonnull dst,\n                                const char* absl_nullable src, size_t size) {\n  size < 16 ? AsciiStrCaseFoldImpl<ToUpper, /*Naive=*/true>(dst, src, size)\n            : AsciiStrCaseFoldImpl<ToUpper, /*Naive=*/false>(dst, src, size);\n}\n\nvoid AsciiStrToLower(char* absl_nonnull dst, const char* absl_nullable src,\n                     size_t n) {\n  return AsciiStrCaseFold<false>(dst, src, n);\n}\n\nvoid AsciiStrToUpper(char* absl_nonnull dst, const char* absl_nullable src,\n                     size_t n) {\n  return AsciiStrCaseFold<true>(dst, src, n);\n}\n\nstatic constexpr size_t ValidateAsciiCasefold() {\n  constexpr size_t num_chars = 1 + CHAR_MAX - CHAR_MIN;\n  size_t incorrect_index = 0;\n  char lowered[num_chars] = {};\n  char uppered[num_chars] = {};\n  for (unsigned int i = 0; i < num_chars; ++i) {\n    uppered[i] = lowered[i] = static_cast<char>(i);\n  }\n  AsciiStrCaseFold<false>(&lowered[0], &lowered[0], num_chars);\n  AsciiStrCaseFold<true>(&uppered[0], &uppered[0], num_chars);\n  for (size_t i = 0; i < num_chars; ++i) {\n    const char ch = static_cast<char>(i),\n               ch_upper = ('a' <= ch && ch <= 'z' ? 'A' + (ch - 'a') : ch),\n               ch_lower = ('A' <= ch && ch <= 'Z' ? 'a' + (ch - 'A') : ch);\n    if (uppered[i] != ch_upper || lowered[i] != ch_lower) {\n      incorrect_index = i > 0 ? i : num_chars;\n      break;\n    }\n  }\n  return incorrect_index;\n}\n\nstatic_assert(ValidateAsciiCasefold() == 0, \"error in case conversion\");\n\n}  // namespace ascii_internal\n\nvoid AsciiStrToLower(std::string* absl_nonnull s) {\n  char* p = &(*s)[0];\n  return ascii_internal::AsciiStrCaseFold<false>(p, p, s->size());\n}\n\nvoid AsciiStrToUpper(std::string* absl_nonnull s) {\n  char* p = &(*s)[0];\n  return ascii_internal::AsciiStrCaseFold<true>(p, p, s->size());\n}\n\nvoid RemoveExtraAsciiWhitespace(std::string* absl_nonnull str) {\n  auto stripped = StripAsciiWhitespace(*str);\n\n  if (stripped.empty()) {\n    str->clear();\n    return;\n  }\n\n  auto input_it = stripped.begin();\n  auto input_end = stripped.end();\n  auto output_it = &(*str)[0];\n  bool is_ws = false;\n\n  for (; input_it < input_end; ++input_it) {\n    if (is_ws) {\n      // Consecutive whitespace?  Keep only the last.\n      is_ws = absl::ascii_isspace(static_cast<unsigned char>(*input_it));\n      if (is_ws) --output_it;\n    } else {\n      is_ws = absl::ascii_isspace(static_cast<unsigned char>(*input_it));\n    }\n\n    *output_it = *input_it;\n    ++output_it;\n  }\n\n  str->erase(static_cast<size_t>(output_it - &(*str)[0]));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/ascii.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: ascii.h\n// -----------------------------------------------------------------------------\n//\n// This package contains functions operating on characters and strings\n// restricted to standard ASCII. These include character classification\n// functions analogous to those found in the ANSI C Standard Library <ctype.h>\n// header file.\n//\n// C++ implementations provide <ctype.h> functionality based on their\n// C environment locale. In general, reliance on such a locale is not ideal, as\n// the locale standard is problematic (and may not return invariant information\n// for the same character set, for example). These `ascii_*()` functions are\n// hard-wired for standard ASCII, much faster, and guaranteed to behave\n// consistently.  They will never be overloaded, nor will their function\n// signature change.\n//\n// `ascii_isalnum()`, `ascii_isalpha()`, `ascii_isascii()`, `ascii_isblank()`,\n// `ascii_iscntrl()`, `ascii_isdigit()`, `ascii_isgraph()`, `ascii_islower()`,\n// `ascii_isprint()`, `ascii_ispunct()`, `ascii_isspace()`, `ascii_isupper()`,\n// `ascii_isxdigit()`\n//   Analogous to the <ctype.h> functions with similar names, these\n//   functions take an unsigned char and return a bool, based on whether the\n//   character matches the condition specified.\n//\n//   If the input character has a numerical value greater than 127, these\n//   functions return `false`.\n//\n// `ascii_tolower()`, `ascii_toupper()`\n//   Analogous to the <ctype.h> functions with similar names, these functions\n//   take an unsigned char and return a char.\n//\n//   If the input character is not an ASCII {lower,upper}-case letter (including\n//   numerical values greater than 127) then the functions return the same value\n//   as the input character.\n\n#ifndef ABSL_STRINGS_ASCII_H_\n#define ABSL_STRINGS_ASCII_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <string>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace ascii_internal {\n\n// Declaration for an array of bitfields holding character information.\nABSL_DLL extern const unsigned char kPropertyBits[256];\n\n// Declaration for the array of characters to upper-case characters.\nABSL_DLL extern const char kToUpper[256];\n\n// Declaration for the array of characters to lower-case characters.\nABSL_DLL extern const char kToLower[256];\n\nvoid AsciiStrToLower(char* absl_nonnull dst, const char* absl_nullable src,\n                     size_t n);\n\nvoid AsciiStrToUpper(char* absl_nonnull dst, const char* absl_nullable src,\n                     size_t n);\n\n}  // namespace ascii_internal\n\n// ascii_isalpha()\n//\n// Determines whether the given character is an alphabetic character.\ninline bool ascii_isalpha(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x01) != 0;\n}\n\n// ascii_isalnum()\n//\n// Determines whether the given character is an alphanumeric character.\ninline bool ascii_isalnum(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x04) != 0;\n}\n\n// ascii_isspace()\n//\n// Determines whether the given character is a whitespace character (space,\n// tab, vertical tab, formfeed, linefeed, or carriage return).\ninline bool ascii_isspace(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x08) != 0;\n}\n\n// ascii_ispunct()\n//\n// Determines whether the given character is a punctuation character.\ninline bool ascii_ispunct(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x10) != 0;\n}\n\n// ascii_isblank()\n//\n// Determines whether the given character is a blank character (tab or space).\ninline bool ascii_isblank(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x20) != 0;\n}\n\n// ascii_iscntrl()\n//\n// Determines whether the given character is a control character.\ninline bool ascii_iscntrl(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x40) != 0;\n}\n\n// ascii_isxdigit()\n//\n// Determines whether the given character can be represented as a hexadecimal\n// digit character (i.e. {0-9} or {A-F} or {a-f}).\ninline bool ascii_isxdigit(unsigned char c) {\n  return (ascii_internal::kPropertyBits[c] & 0x80) != 0;\n}\n\n// ascii_isdigit()\n//\n// Determines whether the given character can be represented as a decimal\n// digit character (i.e. {0-9}).\ninline constexpr bool ascii_isdigit(unsigned char c) {\n  return c >= '0' && c <= '9';\n}\n\n// ascii_isprint()\n//\n// Determines whether the given character is printable, including spaces.\ninline constexpr bool ascii_isprint(unsigned char c) {\n  return c >= 32 && c < 127;\n}\n\n// ascii_isgraph()\n//\n// Determines whether the given character has a graphical representation.\ninline constexpr bool ascii_isgraph(unsigned char c) {\n  return c > 32 && c < 127;\n}\n\n// ascii_isupper()\n//\n// Determines whether the given character is uppercase.\ninline constexpr bool ascii_isupper(unsigned char c) {\n  return c >= 'A' && c <= 'Z';\n}\n\n// ascii_islower()\n//\n// Determines whether the given character is lowercase.\ninline constexpr bool ascii_islower(unsigned char c) {\n  return c >= 'a' && c <= 'z';\n}\n\n// ascii_isascii()\n//\n// Determines whether the given character is ASCII.\ninline constexpr bool ascii_isascii(unsigned char c) { return c < 128; }\n\n// ascii_tolower()\n//\n// Returns an ASCII character, converting to lowercase if uppercase is\n// passed. Note that character values > 127 are simply returned.\ninline char ascii_tolower(unsigned char c) {\n  return ascii_internal::kToLower[c];\n}\n\n// Converts the characters in `s` to lowercase, changing the contents of `s`.\nvoid AsciiStrToLower(std::string* absl_nonnull s);\n\n// Creates a lowercase string from a given absl::string_view.\n[[nodiscard]] inline std::string AsciiStrToLower(absl::string_view s) {\n  std::string result;\n  StringResizeAndOverwrite(result, s.size(), [s](char* buf, size_t buf_size) {\n    ascii_internal::AsciiStrToLower(buf, s.data(), s.size());\n    return buf_size;\n  });\n  return result;\n}\n\n// Creates a lowercase string from a given std::string&&.\n//\n// (Template is used to lower priority of this overload.)\ntemplate <int&... DoNotSpecify>\n[[nodiscard]] inline std::string AsciiStrToLower(std::string&& s) {\n  std::string result = std::move(s);\n  absl::AsciiStrToLower(&result);\n  return result;\n}\n\n// ascii_toupper()\n//\n// Returns the ASCII character, converting to upper-case if lower-case is\n// passed. Note that characters values > 127 are simply returned.\ninline char ascii_toupper(unsigned char c) {\n  return ascii_internal::kToUpper[c];\n}\n\n// Converts the characters in `s` to uppercase, changing the contents of `s`.\nvoid AsciiStrToUpper(std::string* absl_nonnull s);\n\n// Creates an uppercase string from a given absl::string_view.\n[[nodiscard]] inline std::string AsciiStrToUpper(absl::string_view s) {\n  std::string result;\n  StringResizeAndOverwrite(result, s.size(), [s](char* buf, size_t buf_size) {\n    ascii_internal::AsciiStrToUpper(buf, s.data(), s.size());\n    return buf_size;\n  });\n  return result;\n}\n\n// Creates an uppercase string from a given std::string&&.\n//\n// (Template is used to lower priority of this overload.)\ntemplate <int&... DoNotSpecify>\n[[nodiscard]] inline std::string AsciiStrToUpper(std::string&& s) {\n  std::string result = std::move(s);\n  absl::AsciiStrToUpper(&result);\n  return result;\n}\n\n// Returns absl::string_view with whitespace stripped from the beginning of the\n// given string_view.\n[[nodiscard]] inline absl::string_view StripLeadingAsciiWhitespace(\n    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  auto it = std::find_if_not(str.begin(), str.end(), absl::ascii_isspace);\n  return str.substr(static_cast<size_t>(it - str.begin()));\n}\n\n// Strips in place whitespace from the beginning of the given string.\ninline void StripLeadingAsciiWhitespace(std::string* absl_nonnull str) {\n  auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace);\n  str->erase(str->begin(), it);\n}\n\n// Returns absl::string_view with whitespace stripped from the end of the given\n// string_view.\n[[nodiscard]] inline absl::string_view StripTrailingAsciiWhitespace(\n    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  auto it = std::find_if_not(str.rbegin(), str.rend(), absl::ascii_isspace);\n  return str.substr(0, static_cast<size_t>(str.rend() - it));\n}\n\n// Strips in place whitespace from the end of the given string\ninline void StripTrailingAsciiWhitespace(std::string* absl_nonnull str) {\n  auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace);\n  str->erase(static_cast<size_t>(str->rend() - it));\n}\n\n// Returns absl::string_view with whitespace stripped from both ends of the\n// given string_view.\n[[nodiscard]] inline absl::string_view StripAsciiWhitespace(\n    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return StripTrailingAsciiWhitespace(StripLeadingAsciiWhitespace(str));\n}\n\n// Strips in place whitespace from both ends of the given string\ninline void StripAsciiWhitespace(std::string* absl_nonnull str) {\n  StripTrailingAsciiWhitespace(str);\n  StripLeadingAsciiWhitespace(str);\n}\n\n// Removes leading, trailing, and consecutive internal whitespace.\nvoid RemoveExtraAsciiWhitespace(std::string* absl_nonnull str);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_ASCII_H_\n"
  },
  {
    "path": "absl/strings/ascii_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <array>\n#include <cctype>\n#include <cstddef>\n#include <string>\n\n#include \"absl/random/random.h\"\n#include \"absl/strings/ascii.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nstd::array<unsigned char, 256> MakeShuffledBytes() {\n  std::array<unsigned char, 256> bytes;\n  for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i);\n  absl::InsecureBitGen gen;\n  std::shuffle(bytes.begin(), bytes.end(), gen);\n  return bytes;\n}\n\ntemplate <typename Function>\nvoid AsciiBenchmark(benchmark::State& state, Function f) {\n  std::array<unsigned char, 256> bytes = MakeShuffledBytes();\n  size_t sum = 0;\n  for (auto _ : state) {\n    for (unsigned char b : bytes) sum += f(b) ? 1 : 0;\n  }\n  // Make a copy of `sum` before calling `DoNotOptimize` to make sure that `sum`\n  // can be put in a CPU register and not degrade performance in the loop above.\n  size_t sum2 = sum;\n  benchmark::DoNotOptimize(sum2);\n  state.SetBytesProcessed(state.iterations() * bytes.size());\n}\n\nusing StdAsciiFunction = int (*)(int);\ntemplate <StdAsciiFunction f>\nvoid BM_Ascii(benchmark::State& state) {\n  AsciiBenchmark(state, f);\n}\n\nusing AbslAsciiIsFunction = bool (*)(unsigned char);\ntemplate <AbslAsciiIsFunction f>\nvoid BM_Ascii(benchmark::State& state) {\n  AsciiBenchmark(state, f);\n}\n\nusing AbslAsciiToFunction = char (*)(unsigned char);\ntemplate <AbslAsciiToFunction f>\nvoid BM_Ascii(benchmark::State& state) {\n  AsciiBenchmark(state, f);\n}\n\ninline char Noop(unsigned char b) { return static_cast<char>(b); }\n\nBENCHMARK_TEMPLATE(BM_Ascii, Noop);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isalpha);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalpha);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isdigit);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isdigit);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isalnum);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalnum);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isspace);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isspace);\nBENCHMARK_TEMPLATE(BM_Ascii, std::ispunct);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_ispunct);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isblank);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isblank);\nBENCHMARK_TEMPLATE(BM_Ascii, std::iscntrl);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_iscntrl);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isxdigit);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isxdigit);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isprint);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isprint);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isgraph);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isgraph);\nBENCHMARK_TEMPLATE(BM_Ascii, std::isupper);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isupper);\nBENCHMARK_TEMPLATE(BM_Ascii, std::islower);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_islower);\nBENCHMARK_TEMPLATE(BM_Ascii, isascii);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isascii);\nBENCHMARK_TEMPLATE(BM_Ascii, std::tolower);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_tolower);\nBENCHMARK_TEMPLATE(BM_Ascii, std::toupper);\nBENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper);\n\nstatic void BM_StrToLower(benchmark::State& state) {\n  const size_t size = static_cast<size_t>(state.range(0));\n  std::string s(size, 'X');\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(s);\n    std::string res = absl::AsciiStrToLower(s);\n    benchmark::DoNotOptimize(res);\n  }\n}\nBENCHMARK(BM_StrToLower)\n    ->DenseRange(0, 32)\n    ->RangeMultiplier(2)\n    ->Range(64, 1 << 26);\n\nstatic void BM_StrToUpper(benchmark::State& state) {\n  const size_t size = static_cast<size_t>(state.range(0));\n  std::string s(size, 'x');\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(s);\n    std::string res = absl::AsciiStrToUpper(s);\n    benchmark::DoNotOptimize(res);\n  }\n}\nBENCHMARK(BM_StrToUpper)\n    ->DenseRange(0, 32)\n    ->RangeMultiplier(2)\n    ->Range(64, 1 << 26);\n\nstatic void BM_StrToUpperFromRvalref(benchmark::State& state) {\n  const size_t size = static_cast<size_t>(state.range(0));\n  std::string s(size, 'X');\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(s);\n    std::string res = absl::AsciiStrToUpper(std::string(s));\n    benchmark::DoNotOptimize(res);\n  }\n}\nBENCHMARK(BM_StrToUpperFromRvalref)\n    ->DenseRange(0, 32)\n    ->RangeMultiplier(2)\n    ->Range(64, 1 << 26);\n\nstatic void BM_StrToLowerFromRvalref(benchmark::State& state) {\n  const size_t size = static_cast<size_t>(state.range(0));\n  std::string s(size, 'x');\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(s);\n    std::string res = absl::AsciiStrToLower(std::string(s));\n    benchmark::DoNotOptimize(res);\n  }\n}\nBENCHMARK(BM_StrToLowerFromRvalref)\n    ->DenseRange(0, 32)\n    ->RangeMultiplier(2)\n    ->Range(64, 1 << 26);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/ascii_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/ascii.h\"\n\n#include <algorithm>\n#include <cctype>\n#include <clocale>\n#include <cstring>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nTEST(AsciiIsFoo, All) {\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))\n      EXPECT_TRUE(absl::ascii_isalpha(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isalpha(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if ((c >= '0' && c <= '9'))\n      EXPECT_TRUE(absl::ascii_isdigit(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isdigit(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (absl::ascii_isalpha(c) || absl::ascii_isdigit(c))\n      EXPECT_TRUE(absl::ascii_isalnum(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isalnum(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i != '\\0' && strchr(\" \\r\\n\\t\\v\\f\", i))\n      EXPECT_TRUE(absl::ascii_isspace(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isspace(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i >= 32 && i < 127)\n      EXPECT_TRUE(absl::ascii_isprint(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isprint(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (absl::ascii_isprint(c) && !absl::ascii_isspace(c) &&\n        !absl::ascii_isalnum(c)) {\n      EXPECT_TRUE(absl::ascii_ispunct(c)) << \": failed on \" << c;\n    } else {\n      EXPECT_TRUE(!absl::ascii_ispunct(c)) << \": failed on \" << c;\n    }\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i == ' ' || i == '\\t')\n      EXPECT_TRUE(absl::ascii_isblank(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isblank(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i < 32 || i == 127)\n      EXPECT_TRUE(absl::ascii_iscntrl(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_iscntrl(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (absl::ascii_isdigit(c) || (i >= 'A' && i <= 'F') ||\n        (i >= 'a' && i <= 'f')) {\n      EXPECT_TRUE(absl::ascii_isxdigit(c)) << \": failed on \" << c;\n    } else {\n      EXPECT_TRUE(!absl::ascii_isxdigit(c)) << \": failed on \" << c;\n    }\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i > 32 && i < 127)\n      EXPECT_TRUE(absl::ascii_isgraph(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isgraph(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i >= 'A' && i <= 'Z')\n      EXPECT_TRUE(absl::ascii_isupper(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_isupper(c)) << \": failed on \" << c;\n  }\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (i >= 'a' && i <= 'z')\n      EXPECT_TRUE(absl::ascii_islower(c)) << \": failed on \" << c;\n    else\n      EXPECT_TRUE(!absl::ascii_islower(c)) << \": failed on \" << c;\n  }\n  for (unsigned char c = 0; c < 128; c++) {\n    EXPECT_TRUE(absl::ascii_isascii(c)) << \": failed on \" << c;\n  }\n  for (int i = 128; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    EXPECT_TRUE(!absl::ascii_isascii(c)) << \": failed on \" << c;\n  }\n}\n\n// Checks that absl::ascii_isfoo returns the same value as isfoo in the C\n// locale.\nTEST(AsciiIsFoo, SameAsIsFoo) {\n#ifndef __ANDROID__\n  // temporarily change locale to C. It should already be C, but just for safety\n  const char* old_locale = setlocale(LC_CTYPE, \"C\");\n  ASSERT_TRUE(old_locale != nullptr);\n#endif\n\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    EXPECT_EQ(isalpha(c) != 0, absl::ascii_isalpha(c)) << c;\n    EXPECT_EQ(isdigit(c) != 0, absl::ascii_isdigit(c)) << c;\n    EXPECT_EQ(isalnum(c) != 0, absl::ascii_isalnum(c)) << c;\n    EXPECT_EQ(isspace(c) != 0, absl::ascii_isspace(c)) << c;\n    EXPECT_EQ(ispunct(c) != 0, absl::ascii_ispunct(c)) << c;\n    EXPECT_EQ(isblank(c) != 0, absl::ascii_isblank(c)) << c;\n    EXPECT_EQ(iscntrl(c) != 0, absl::ascii_iscntrl(c)) << c;\n    EXPECT_EQ(isxdigit(c) != 0, absl::ascii_isxdigit(c)) << c;\n    EXPECT_EQ(isprint(c) != 0, absl::ascii_isprint(c)) << c;\n    EXPECT_EQ(isgraph(c) != 0, absl::ascii_isgraph(c)) << c;\n    EXPECT_EQ(isupper(c) != 0, absl::ascii_isupper(c)) << c;\n    EXPECT_EQ(islower(c) != 0, absl::ascii_islower(c)) << c;\n    EXPECT_EQ(isascii(c) != 0, absl::ascii_isascii(c)) << c;\n  }\n\n#ifndef __ANDROID__\n  // restore the old locale.\n  ASSERT_TRUE(setlocale(LC_CTYPE, old_locale));\n#endif\n}\n\nTEST(AsciiToFoo, All) {\n#ifndef __ANDROID__\n  // temporarily change locale to C. It should already be C, but just for safety\n  const char* old_locale = setlocale(LC_CTYPE, \"C\");\n  ASSERT_TRUE(old_locale != nullptr);\n#endif\n\n  for (int i = 0; i < 256; i++) {\n    const auto c = static_cast<unsigned char>(i);\n    if (absl::ascii_islower(c))\n      EXPECT_EQ(absl::ascii_toupper(c), 'A' + (i - 'a')) << c;\n    else\n      EXPECT_EQ(absl::ascii_toupper(c), static_cast<char>(i)) << c;\n\n    if (absl::ascii_isupper(c))\n      EXPECT_EQ(absl::ascii_tolower(c), 'a' + (i - 'A')) << c;\n    else\n      EXPECT_EQ(absl::ascii_tolower(c), static_cast<char>(i)) << c;\n\n    // These CHECKs only hold in a C locale.\n    EXPECT_EQ(static_cast<char>(tolower(i)), absl::ascii_tolower(c)) << c;\n    EXPECT_EQ(static_cast<char>(toupper(i)), absl::ascii_toupper(c)) << c;\n  }\n#ifndef __ANDROID__\n  // restore the old locale.\n  ASSERT_TRUE(setlocale(LC_CTYPE, old_locale));\n#endif\n}\n\nTEST(AsciiStrTo, Lower) {\n  const char buf[] = \"ABCDEF\";\n  const std::string str(\"GHIJKL\");\n  const std::string str2(\"MNOPQR\");\n  const absl::string_view sp(str2);\n  const std::string long_str(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ1!a\");\n  std::string mutable_str(\"_`?@[{AMNOPQRSTUVWXYZ\");\n  auto fun = []() -> std::string { return \"PQRSTU\"; };\n\n  EXPECT_EQ(\"abcdef\", absl::AsciiStrToLower(buf));\n  EXPECT_EQ(\"ghijkl\", absl::AsciiStrToLower(str));\n  EXPECT_EQ(\"mnopqr\", absl::AsciiStrToLower(sp));\n  EXPECT_EQ(\"abcdefghijklmnopqrstuvwxyz1!a\", absl::AsciiStrToLower(long_str));\n  EXPECT_EQ(\"pqrstu\", absl::AsciiStrToLower(fun()));\n\n  // An empty `string_view` specifically exercises the case where a null data\n  // pointer is passed to internal functions.\n  EXPECT_EQ(\"\", absl::AsciiStrToLower(absl::string_view()));\n\n  absl::AsciiStrToLower(&mutable_str);\n  EXPECT_EQ(\"_`?@[{amnopqrstuvwxyz\", mutable_str);\n\n  char mutable_buf[] = \"Mutable\";\n  std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),\n                 mutable_buf, absl::ascii_tolower);\n  EXPECT_STREQ(\"mutable\", mutable_buf);\n}\n\nTEST(AsciiStrTo, Upper) {\n  const char buf[] = \"abcdef\";\n  const std::string str(\"ghijkl\");\n  const std::string str2(\"_`?@[{amnopqrstuvwxyz\");\n  const absl::string_view sp(str2);\n  const std::string long_str(\"abcdefghijklmnopqrstuvwxyz1!A\");\n  auto fun = []() -> std::string { return \"pqrstu\"; };\n\n  EXPECT_EQ(\"ABCDEF\", absl::AsciiStrToUpper(buf));\n  EXPECT_EQ(\"GHIJKL\", absl::AsciiStrToUpper(str));\n  EXPECT_EQ(\"_`?@[{AMNOPQRSTUVWXYZ\", absl::AsciiStrToUpper(sp));\n  EXPECT_EQ(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ1!A\", absl::AsciiStrToUpper(long_str));\n  EXPECT_EQ(\"PQRSTU\", absl::AsciiStrToUpper(fun()));\n\n  // An empty `string_view` specifically exercises the case where a null data\n  // pointer is passed to internal functions.\n  EXPECT_EQ(\"\", absl::AsciiStrToUpper(absl::string_view()));\n\n  char mutable_buf[] = \"Mutable\";\n  std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),\n                 mutable_buf, absl::ascii_toupper);\n  EXPECT_STREQ(\"MUTABLE\", mutable_buf);\n}\n\nTEST(StripLeadingAsciiWhitespace, FromStringView) {\n  EXPECT_EQ(absl::string_view{},\n            absl::StripLeadingAsciiWhitespace(absl::string_view{}));\n  EXPECT_EQ(\"foo\", absl::StripLeadingAsciiWhitespace({\"foo\"}));\n  EXPECT_EQ(\"foo\", absl::StripLeadingAsciiWhitespace({\"\\t  \\n\\f\\r\\n\\vfoo\"}));\n  EXPECT_EQ(\"foo foo\\n \",\n            absl::StripLeadingAsciiWhitespace({\"\\t  \\n\\f\\r\\n\\vfoo foo\\n \"}));\n  EXPECT_EQ(absl::string_view{}, absl::StripLeadingAsciiWhitespace(\n                                     {\"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\"}));\n}\n\nTEST(StripLeadingAsciiWhitespace, InPlace) {\n  std::string str;\n\n  absl::StripLeadingAsciiWhitespace(&str);\n  EXPECT_EQ(\"\", str);\n\n  str = \"foo\";\n  absl::StripLeadingAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo\", str);\n\n  str = \"\\t  \\n\\f\\r\\n\\vfoo\";\n  absl::StripLeadingAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo\", str);\n\n  str = \"\\t  \\n\\f\\r\\n\\vfoo foo\\n \";\n  absl::StripLeadingAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo foo\\n \", str);\n\n  str = \"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\";\n  absl::StripLeadingAsciiWhitespace(&str);\n  EXPECT_EQ(absl::string_view{}, str);\n}\n\nTEST(StripTrailingAsciiWhitespace, FromStringView) {\n  EXPECT_EQ(absl::string_view{},\n            absl::StripTrailingAsciiWhitespace(absl::string_view{}));\n  EXPECT_EQ(\"foo\", absl::StripTrailingAsciiWhitespace({\"foo\"}));\n  EXPECT_EQ(\"foo\", absl::StripTrailingAsciiWhitespace({\"foo\\t  \\n\\f\\r\\n\\v\"}));\n  EXPECT_EQ(\" \\nfoo foo\",\n            absl::StripTrailingAsciiWhitespace({\" \\nfoo foo\\t  \\n\\f\\r\\n\\v\"}));\n  EXPECT_EQ(absl::string_view{}, absl::StripTrailingAsciiWhitespace(\n                                     {\"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\"}));\n}\n\nTEST(StripTrailingAsciiWhitespace, InPlace) {\n  std::string str;\n\n  absl::StripTrailingAsciiWhitespace(&str);\n  EXPECT_EQ(\"\", str);\n\n  str = \"foo\";\n  absl::StripTrailingAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo\", str);\n\n  str = \"foo\\t  \\n\\f\\r\\n\\v\";\n  absl::StripTrailingAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo\", str);\n\n  str = \" \\nfoo foo\\t  \\n\\f\\r\\n\\v\";\n  absl::StripTrailingAsciiWhitespace(&str);\n  EXPECT_EQ(\" \\nfoo foo\", str);\n\n  str = \"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\";\n  absl::StripTrailingAsciiWhitespace(&str);\n  EXPECT_EQ(absl::string_view{}, str);\n}\n\nTEST(StripAsciiWhitespace, FromStringView) {\n  EXPECT_EQ(absl::string_view{},\n            absl::StripAsciiWhitespace(absl::string_view{}));\n  EXPECT_EQ(\"foo\", absl::StripAsciiWhitespace({\"foo\"}));\n  EXPECT_EQ(\"foo\",\n            absl::StripAsciiWhitespace({\"\\t  \\n\\f\\r\\n\\vfoo\\t  \\n\\f\\r\\n\\v\"}));\n  EXPECT_EQ(\"foo foo\", absl::StripAsciiWhitespace(\n                           {\"\\t  \\n\\f\\r\\n\\vfoo foo\\t  \\n\\f\\r\\n\\v\"}));\n  EXPECT_EQ(absl::string_view{},\n            absl::StripAsciiWhitespace({\"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\"}));\n}\n\nTEST(StripAsciiWhitespace, InPlace) {\n  std::string str;\n\n  absl::StripAsciiWhitespace(&str);\n  EXPECT_EQ(\"\", str);\n\n  str = \"foo\";\n  absl::StripAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo\", str);\n\n  str = \"\\t  \\n\\f\\r\\n\\vfoo\\t  \\n\\f\\r\\n\\v\";\n  absl::StripAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo\", str);\n\n  str = \"\\t  \\n\\f\\r\\n\\vfoo foo\\t  \\n\\f\\r\\n\\v\";\n  absl::StripAsciiWhitespace(&str);\n  EXPECT_EQ(\"foo foo\", str);\n\n  str = \"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\";\n  absl::StripAsciiWhitespace(&str);\n  EXPECT_EQ(absl::string_view{}, str);\n}\n\nTEST(RemoveExtraAsciiWhitespace, InPlace) {\n  const char* inputs[] = {\"No extra space\",\n                          \"  Leading whitespace\",\n                          \"Trailing whitespace  \",\n                          \"  Leading and trailing  \",\n                          \" Whitespace \\t  in\\v   middle  \",\n                          \"'Eeeeep!  \\n Newlines!\\n\",\n                          \"nospaces\",\n                          \"\",\n                          \"\\n\\t a\\t\\n\\nb \\t\\n\"};\n\n  const char* outputs[] = {\n      \"No extra space\",\n      \"Leading whitespace\",\n      \"Trailing whitespace\",\n      \"Leading and trailing\",\n      \"Whitespace in middle\",\n      \"'Eeeeep! Newlines!\",\n      \"nospaces\",\n      \"\",\n      \"a\\nb\",\n  };\n  const int NUM_TESTS = ABSL_ARRAYSIZE(inputs);\n\n  for (int i = 0; i < NUM_TESTS; i++) {\n    std::string s(inputs[i]);\n    absl::RemoveExtraAsciiWhitespace(&s);\n    EXPECT_EQ(outputs[i], s);\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/atod_manual_test.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This program tests the absl::SimpleAtod and absl::SimpleAtof functions. Run\n// it as \"atod_manual_test pnftd/data/*.txt\" where the pnftd directory is a\n// local checkout of the https://github.com/nigeltao/parse-number-fxx-test-data\n// repository. The test suite lives in a separate repository because its more\n// than 5 million test cases weigh over several hundred megabytes and because\n// the test cases are also useful to other software projects, not just Abseil.\n// Its data/*.txt files contain one test case per line, like:\n//\n// 3C00 3F800000 3FF0000000000000 1\n// 3D00 3FA00000 3FF4000000000000 1.25\n// 3D9A 3FB33333 3FF6666666666666 1.4\n// 57B7 42F6E979 405EDD2F1A9FBE77 123.456\n// 622A 44454000 4088A80000000000 789\n// 7C00 7F800000 7FF0000000000000 123.456e789\n//\n// For each line (and using 0-based column indexes), columns [5..13] and\n// [14..30] contain the 32-bit float and 64-bit double result of parsing\n// columns [31..].\n//\n// For example, parsing \"1.4\" as a float gives the bits 0x3FB33333.\n//\n// In this 6-line example, the final line's float and double values are all\n// infinity. The largest finite float and double values are approximately\n// 3.40e+38 and 1.80e+308.\n\n#include <cstdint>\n#include <cstdio>\n#include <optional>\n#include <string>\n\n#include \"absl/base/casts.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\nstatic constexpr uint8_t kUnhex[256] = {\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,  // '0' ..= '7'\n    0x8, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  // '8' ..= '9'\n\n    0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0,  // 'A' ..= 'F'\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  //\n};\n\nstatic std::optional<std::string> ReadFileToString(const char* filename) {\n  FILE* f = fopen(filename, \"rb\");\n  if (!f) {\n    return std::nullopt;\n  }\n  fseek(f, 0, SEEK_END);\n  size_t size = ftell(f);\n  fseek(f, 0, SEEK_SET);\n  std::string s(size, '\\x00');\n  size_t n = fread(&s[0], 1, size, f);\n  fclose(f);\n  if (n != size) {\n    return std::nullopt;\n  }\n  return s;\n}\n\nstatic bool ProcessOneTestFile(const char* filename) {\n  std::optional<std::string> contents = ReadFileToString(filename);\n  if (!contents) {\n    absl::FPrintF(stderr, \"Invalid file: %s\\n\", filename);\n    return false;\n  }\n\n  int num_cases = 0;\n  for (absl::string_view v(*contents); !v.empty();) {\n    size_t new_line = v.find('\\n');\n    if ((new_line == absl::string_view::npos) || (new_line < 32)) {\n      break;\n    }\n    absl::string_view input = v.substr(31, new_line - 31);\n\n    // Test absl::SimpleAtof.\n    {\n      float f;\n      if (!absl::SimpleAtof(input, &f)) {\n        absl::FPrintF(stderr, \"Could not parse \\\"%s\\\" in %s\\n\", input,\n                      filename);\n        return false;\n      }\n      uint32_t have32 = absl::bit_cast<uint32_t>(f);\n\n      uint32_t want32 = 0;\n      for (int i = 0; i < 8; i++) {\n        want32 = (want32 << 4) | kUnhex[static_cast<unsigned char>(v[5 + i])];\n      }\n\n      if (have32 != want32) {\n        absl::FPrintF(stderr,\n                      \"absl::SimpleAtof failed parsing \\\"%s\\\" in %s\\n  have  \"\n                      \"%08X\\n  want  %08X\\n\",\n                      input, filename, have32, want32);\n        return false;\n      }\n    }\n\n    // Test absl::SimpleAtod.\n    {\n      double d;\n      if (!absl::SimpleAtod(input, &d)) {\n        absl::FPrintF(stderr, \"Could not parse \\\"%s\\\" in %s\\n\", input,\n                      filename);\n        return false;\n      }\n      uint64_t have64 = absl::bit_cast<uint64_t>(d);\n\n      uint64_t want64 = 0;\n      for (int i = 0; i < 16; i++) {\n        want64 = (want64 << 4) | kUnhex[static_cast<unsigned char>(v[14 + i])];\n      }\n\n      if (have64 != want64) {\n        absl::FPrintF(stderr,\n                      \"absl::SimpleAtod failed parsing \\\"%s\\\" in %s\\n  have  \"\n                      \"%016X\\n  want  %016X\\n\",\n                      input, filename, have64, want64);\n        return false;\n      }\n    }\n\n    num_cases++;\n    v = v.substr(new_line + 1);\n  }\n  printf(\"%8d OK in %s\\n\", num_cases, filename);\n  return true;\n}\n\nint main(int argc, char** argv) {\n  if (argc < 2) {\n    absl::FPrintF(\n        stderr,\n        \"Usage: %s pnftd/data/*.txt\\nwhere the pnftd directory is a local \"\n        \"checkout of \"\n        \"the\\nhttps://github.com/nigeltao/parse-number-fxx-test-data \"\n        \"repository.\\n\",\n        argv[0]);\n    return 1;\n  }\n\n  for (int i = 1; i < argc; i++) {\n    if (!ProcessOneTestFile(argv[i])) {\n      return 1;\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "absl/strings/char_formatting_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/substitute.h\"\n\nnamespace {\n\nTEST(CharFormatting, Char) {\n  const char v = 'A';\n\n  // Desired behavior: does not compile:\n  // EXPECT_EQ(absl::StrCat(v, \"B\"), \"AB\");\n  // EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"AB\");\n\n  // Legacy behavior: format as char:\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"AB\");\n}\n\nenum CharEnum : char {};\nTEST(CharFormatting, CharEnum) {\n  auto v = static_cast<CharEnum>('A');\n\n  // Desired behavior: format as decimal\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n\n  // Legacy behavior: format as character:\n\n  // Some older versions of gcc behave differently in this one case\n#if !defined(__GNUC__) || defined(__clang__)\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"AB\");\n#endif\n}\n\nenum class CharEnumClass: char {};\nTEST(CharFormatting, CharEnumClass) {\n  auto v = static_cast<CharEnumClass>('A');\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n\n  // Legacy behavior: format as character:\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"AB\");\n}\n\nTEST(CharFormatting, UnsignedChar) {\n  const unsigned char v = 'A';\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n\n  // Signedness check\n  const unsigned char w = 255;\n  EXPECT_EQ(absl::StrCat(w, \"B\"), \"255B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", w), \"255B\");\n  // EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"255B\");\n}\n\nTEST(CharFormatting, SignedChar) {\n  const signed char v = 'A';\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n\n  // Signedness check\n  const signed char w = -128;\n  EXPECT_EQ(absl::StrCat(w, \"B\"), \"-128B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", w), \"-128B\");\n}\n\nenum UnsignedCharEnum : unsigned char {};\nTEST(CharFormatting, UnsignedCharEnum) {\n  auto v = static_cast<UnsignedCharEnum>('A');\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n\n  // Signedness check\n  auto w = static_cast<UnsignedCharEnum>(255);\n  EXPECT_EQ(absl::StrCat(w, \"B\"), \"255B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", w), \"255B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", w), \"255B\");\n}\n\nenum SignedCharEnum : signed char {};\nTEST(CharFormatting, SignedCharEnum) {\n  auto v = static_cast<SignedCharEnum>('A');\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n\n  // Signedness check\n  auto w = static_cast<SignedCharEnum>(-128);\n  EXPECT_EQ(absl::StrCat(w, \"B\"), \"-128B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", w), \"-128B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", w), \"-128B\");\n}\n\nenum class UnsignedCharEnumClass : unsigned char {};\nTEST(CharFormatting, UnsignedCharEnumClass) {\n  auto v = static_cast<UnsignedCharEnumClass>('A');\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n\n  // Signedness check\n  auto w = static_cast<UnsignedCharEnumClass>(255);\n  EXPECT_EQ(absl::StrCat(w, \"B\"), \"255B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", w), \"255B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", w), \"255B\");\n}\n\nenum SignedCharEnumClass : signed char {};\nTEST(CharFormatting, SignedCharEnumClass) {\n  auto v = static_cast<SignedCharEnumClass>('A');\n\n  // Desired behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n\n  // Signedness check\n  auto w = static_cast<SignedCharEnumClass>(-128);\n  EXPECT_EQ(absl::StrCat(w, \"B\"), \"-128B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", w), \"-128B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", w), \"-128B\");\n}\n\n#ifdef __cpp_lib_byte\nTEST(CharFormatting, StdByte) {\n  auto v = static_cast<std::byte>('A');\n  // Desired behavior: format as 0xff\n  // (No APIs do this today.)\n\n  // Legacy behavior: format as decimal:\n  EXPECT_EQ(absl::StrCat(v, \"B\"), \"65B\");\n  EXPECT_EQ(absl::Substitute(\"$0B\", v), \"65B\");\n  EXPECT_EQ(absl::StrFormat(\"%vB\", v), \"65B\");\n}\n#endif  // _cpp_lib_byte\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/charconv.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/charconv.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <system_error>  // NOLINT(build/c++11)\n\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/internal/charconv_bigint.h\"\n#include \"absl/strings/internal/charconv_parse.h\"\n\n// The macro ABSL_BIT_PACK_FLOATS is defined on x86-64, where IEEE floating\n// point numbers have the same endianness in memory as a bitfield struct\n// containing the corresponding parts.\n//\n// When set, we replace calls to ldexp() with manual bit packing, which is\n// faster and is unaffected by floating point environment.\n#ifdef ABSL_BIT_PACK_FLOATS\n#error ABSL_BIT_PACK_FLOATS cannot be directly set\n#elif defined(__x86_64__) || defined(_M_X64)\n#define ABSL_BIT_PACK_FLOATS 1\n#endif\n\n// A note about subnormals:\n//\n// The code below talks about \"normals\" and \"subnormals\".  A normal IEEE float\n// has a fixed-width mantissa and power of two exponent.  For example, a normal\n// `double` has a 53-bit mantissa.  Because the high bit is always 1, it is not\n// stored in the representation.  The implicit bit buys an extra bit of\n// resolution in the datatype.\n//\n// The downside of this scheme is that there is a large gap between DBL_MIN and\n// zero.  (Large, at least, relative to the different between DBL_MIN and the\n// next representable number).  This gap is softened by the \"subnormal\" numbers,\n// which have the same power-of-two exponent as DBL_MIN, but no implicit 53rd\n// bit.  An all-bits-zero exponent in the encoding represents subnormals.  (Zero\n// is represented as a subnormal with an all-bits-zero mantissa.)\n//\n// The code below, in calculations, represents the mantissa as a uint64_t.  The\n// end result normally has the 53rd bit set.  It represents subnormals by using\n// narrower mantissas.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\ntemplate <typename FloatType>\nstruct FloatTraits;\n\ntemplate <>\nstruct FloatTraits<double> {\n  using mantissa_t = uint64_t;\n\n  // The number of bits in the given float type.\n  static constexpr int kTargetBits = 64;\n\n  // The number of exponent bits in the given float type.\n  static constexpr int kTargetExponentBits = 11;\n\n  // The number of mantissa bits in the given float type.  This includes the\n  // implied high bit.\n  static constexpr int kTargetMantissaBits = 53;\n\n  // The largest supported IEEE exponent, in our integral mantissa\n  // representation.\n  //\n  // If `m` is the largest possible int kTargetMantissaBits bits wide, then\n  // m * 2**kMaxExponent is exactly equal to DBL_MAX.\n  static constexpr int kMaxExponent = 971;\n\n  // The smallest supported IEEE normal exponent, in our integral mantissa\n  // representation.\n  //\n  // If `m` is the smallest possible int kTargetMantissaBits bits wide, then\n  // m * 2**kMinNormalExponent is exactly equal to DBL_MIN.\n  static constexpr int kMinNormalExponent = -1074;\n\n  // The IEEE exponent bias.  It equals ((1 << (kTargetExponentBits - 1)) - 1).\n  static constexpr int kExponentBias = 1023;\n\n  // The Eisel-Lemire \"Shifting to 54/25 Bits\" adjustment.  It equals (63 - 1 -\n  // kTargetMantissaBits).\n  static constexpr int kEiselLemireShift = 9;\n\n  // The Eisel-Lemire high64_mask.  It equals ((1 << kEiselLemireShift) - 1).\n  static constexpr uint64_t kEiselLemireMask = uint64_t{0x1FF};\n\n  // The smallest negative integer N (smallest negative means furthest from\n  // zero) such that parsing 9999999999999999999eN, with 19 nines, is still\n  // positive. Parsing a smaller (more negative) N will produce zero.\n  //\n  // Adjusting the decimal point and exponent, without adjusting the value,\n  // 9999999999999999999eN equals 9.999999999999999999eM where M = N + 18.\n  //\n  // 9999999999999999999, with 19 nines but no decimal point, is the largest\n  // \"repeated nines\" integer that fits in a uint64_t.\n  static constexpr int kEiselLemireMinInclusiveExp10 = -324 - 18;\n\n  // The smallest positive integer N such that parsing 1eN produces infinity.\n  // Parsing a smaller N will produce something finite.\n  static constexpr int kEiselLemireMaxExclusiveExp10 = 309;\n\n  static double MakeNan(const char* absl_nonnull tagp) {\n#if ABSL_HAVE_BUILTIN(__builtin_nan)\n    // Use __builtin_nan() if available since it has a fix for\n    // https://bugs.llvm.org/show_bug.cgi?id=37778\n    // std::nan may use the glibc implementation.\n    return __builtin_nan(tagp);\n#else\n    // Support nan no matter which namespace it's in.  Some platforms\n    // incorrectly don't put it in namespace std.\n    using namespace std;  // NOLINT\n    return nan(tagp);\n#endif\n  }\n\n  // Builds a nonzero floating point number out of the provided parts.\n  //\n  // This is intended to do the same operation as ldexp(mantissa, exponent),\n  // but using purely integer math, to avoid -ffastmath and floating\n  // point environment issues.  Using type punning is also faster. We fall back\n  // to ldexp on a per-platform basis for portability.\n  //\n  // `exponent` must be between kMinNormalExponent and kMaxExponent.\n  //\n  // `mantissa` must either be exactly kTargetMantissaBits wide, in which case\n  // a normal value is made, or it must be less narrow than that, in which case\n  // `exponent` must be exactly kMinNormalExponent, and a subnormal value is\n  // made.\n  static double Make(mantissa_t mantissa, int exponent, bool sign) {\n#ifndef ABSL_BIT_PACK_FLOATS\n    // Support ldexp no matter which namespace it's in.  Some platforms\n    // incorrectly don't put it in namespace std.\n    using namespace std;  // NOLINT\n    return sign ? -ldexp(mantissa, exponent) : ldexp(mantissa, exponent);\n#else\n    constexpr uint64_t kMantissaMask =\n        (uint64_t{1} << (kTargetMantissaBits - 1)) - 1;\n    uint64_t dbl = static_cast<uint64_t>(sign) << 63;\n    if (mantissa > kMantissaMask) {\n      // Normal value.\n      // Adjust by 1023 for the exponent representation bias, and an additional\n      // 52 due to the implied decimal point in the IEEE mantissa\n      // representation.\n      dbl += static_cast<uint64_t>(exponent + 1023 + kTargetMantissaBits - 1)\n             << 52;\n      mantissa &= kMantissaMask;\n    } else {\n      // subnormal value\n      assert(exponent == kMinNormalExponent);\n    }\n    dbl += mantissa;\n    return absl::bit_cast<double>(dbl);\n#endif  // ABSL_BIT_PACK_FLOATS\n  }\n};\n\n// Specialization of floating point traits for the `float` type.  See the\n// FloatTraits<double> specialization above for meaning of each of the following\n// members and methods.\ntemplate <>\nstruct FloatTraits<float> {\n  using mantissa_t = uint32_t;\n\n  static constexpr int kTargetBits = 32;\n  static constexpr int kTargetExponentBits = 8;\n  static constexpr int kTargetMantissaBits = 24;\n  static constexpr int kMaxExponent = 104;\n  static constexpr int kMinNormalExponent = -149;\n  static constexpr int kExponentBias = 127;\n  static constexpr int kEiselLemireShift = 38;\n  static constexpr uint64_t kEiselLemireMask = uint64_t{0x3FFFFFFFFF};\n  static constexpr int kEiselLemireMinInclusiveExp10 = -46 - 18;\n  static constexpr int kEiselLemireMaxExclusiveExp10 = 39;\n\n  static float MakeNan(const char* absl_nonnull tagp) {\n#if ABSL_HAVE_BUILTIN(__builtin_nanf)\n    // Use __builtin_nanf() if available since it has a fix for\n    // https://bugs.llvm.org/show_bug.cgi?id=37778\n    // std::nanf may use the glibc implementation.\n    return __builtin_nanf(tagp);\n#else\n    // Support nanf no matter which namespace it's in.  Some platforms\n    // incorrectly don't put it in namespace std.\n    using namespace std;  // NOLINT\n    return std::nanf(tagp);\n#endif\n  }\n\n  static float Make(mantissa_t mantissa, int exponent, bool sign) {\n#ifndef ABSL_BIT_PACK_FLOATS\n    // Support ldexpf no matter which namespace it's in.  Some platforms\n    // incorrectly don't put it in namespace std.\n    using namespace std;  // NOLINT\n    return sign ? -ldexpf(mantissa, exponent) : ldexpf(mantissa, exponent);\n#else\n    constexpr uint32_t kMantissaMask =\n        (uint32_t{1} << (kTargetMantissaBits - 1)) - 1;\n    uint32_t flt = static_cast<uint32_t>(sign) << 31;\n    if (mantissa > kMantissaMask) {\n      // Normal value.\n      // Adjust by 127 for the exponent representation bias, and an additional\n      // 23 due to the implied decimal point in the IEEE mantissa\n      // representation.\n      flt += static_cast<uint32_t>(exponent + 127 + kTargetMantissaBits - 1)\n             << 23;\n      mantissa &= kMantissaMask;\n    } else {\n      // subnormal value\n      assert(exponent == kMinNormalExponent);\n    }\n    flt += mantissa;\n    return absl::bit_cast<float>(flt);\n#endif  // ABSL_BIT_PACK_FLOATS\n  }\n};\n\n// Decimal-to-binary conversions require coercing powers of 10 into a mantissa\n// and a power of 2.  The two helper functions Power10Mantissa(n) and\n// Power10Exponent(n) perform this task.  Together, these represent a hand-\n// rolled floating point value which is equal to or just less than 10**n.\n//\n// The return values satisfy two range guarantees:\n//\n//   Power10Mantissa(n) * 2**Power10Exponent(n) <= 10**n\n//     < (Power10Mantissa(n) + 1) * 2**Power10Exponent(n)\n//\n//   2**63 <= Power10Mantissa(n) < 2**64.\n//\n// See the \"Table of powers of 10\" comment below for a \"1e60\" example.\n//\n// Lookups into the power-of-10 table must first check the Power10Overflow() and\n// Power10Underflow() functions, to avoid out-of-bounds table access.\n//\n// Indexes into these tables are biased by -kPower10TableMinInclusive. Valid\n// indexes range from kPower10TableMinInclusive to kPower10TableMaxExclusive.\nextern const uint64_t kPower10MantissaHighTable[];  // High 64 of 128 bits.\nextern const uint64_t kPower10MantissaLowTable[];   // Low  64 of 128 bits.\n\n// The smallest (inclusive) allowed value for use with the Power10Mantissa()\n// and Power10Exponent() functions below.  (If a smaller exponent is needed in\n// calculations, the end result is guaranteed to underflow.)\nconstexpr int kPower10TableMinInclusive = -342;\n\n// The largest (exclusive) allowed value for use with the Power10Mantissa() and\n// Power10Exponent() functions below.  (If a larger-or-equal exponent is needed\n// in calculations, the end result is guaranteed to overflow.)\nconstexpr int kPower10TableMaxExclusive = 309;\n\nuint64_t Power10Mantissa(int n) {\n  return kPower10MantissaHighTable[n - kPower10TableMinInclusive];\n}\n\nint Power10Exponent(int n) {\n  // The 217706 etc magic numbers encode the results as a formula instead of a\n  // table. Their equivalence (over the kPower10TableMinInclusive ..\n  // kPower10TableMaxExclusive range) is confirmed by\n  // https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go\n  return (217706 * n >> 16) - 63;\n}\n\n// Returns true if n is large enough that 10**n always results in an IEEE\n// overflow.\nbool Power10Overflow(int n) { return n >= kPower10TableMaxExclusive; }\n\n// Returns true if n is small enough that 10**n times a ParsedFloat mantissa\n// always results in an IEEE underflow.\nbool Power10Underflow(int n) { return n < kPower10TableMinInclusive; }\n\n// Returns true if Power10Mantissa(n) * 2**Power10Exponent(n) is exactly equal\n// to 10**n numerically.  Put another way, this returns true if there is no\n// truncation error in Power10Mantissa(n).\nbool Power10Exact(int n) { return n >= 0 && n <= 27; }\n\n// Sentinel exponent values for representing numbers too large or too close to\n// zero to represent in a double.\nconstexpr int kOverflow = 99999;\nconstexpr int kUnderflow = -99999;\n\n// Struct representing the calculated conversion result of a positive (nonzero)\n// floating point number.\n//\n// The calculated number is mantissa * 2**exponent (mantissa is treated as an\n// integer.)  `mantissa` is chosen to be the correct width for the IEEE float\n// representation being calculated.  (`mantissa` will always have the same bit\n// width for normal values, and narrower bit widths for subnormals.)\n//\n// If the result of conversion was an underflow or overflow, exponent is set\n// to kUnderflow or kOverflow.\nstruct CalculatedFloat {\n  uint64_t mantissa = 0;\n  int exponent = 0;\n};\n\n// Returns the bit width of the given uint128.  (Equivalently, returns 128\n// minus the number of leading zero bits.)\nint BitWidth(uint128 value) {\n  if (Uint128High64(value) == 0) {\n    // This static_cast is only needed when using a std::bit_width()\n    // implementation that does not have the fix for LWG 3656 applied.\n    return static_cast<int>(bit_width(Uint128Low64(value)));\n  }\n  return 128 - countl_zero(Uint128High64(value));\n}\n\n// Calculates how far to the right a mantissa needs to be shifted to create a\n// properly adjusted mantissa for an IEEE floating point number.\n//\n// `mantissa_width` is the bit width of the mantissa to be shifted, and\n// `binary_exponent` is the exponent of the number before the shift.\n//\n// This accounts for subnormal values, and will return a larger-than-normal\n// shift if binary_exponent would otherwise be too low.\ntemplate <typename FloatType>\nint NormalizedShiftSize(int mantissa_width, int binary_exponent) {\n  const int normal_shift =\n      mantissa_width - FloatTraits<FloatType>::kTargetMantissaBits;\n  const int minimum_shift =\n      FloatTraits<FloatType>::kMinNormalExponent - binary_exponent;\n  return std::max(normal_shift, minimum_shift);\n}\n\n// Right shifts a uint128 so that it has the requested bit width.  (The\n// resulting value will have 128 - bit_width leading zeroes.)  The initial\n// `value` must be wider than the requested bit width.\n//\n// Returns the number of bits shifted.\nint TruncateToBitWidth(int bit_width, uint128* absl_nonnull value) {\n  const int current_bit_width = BitWidth(*value);\n  const int shift = current_bit_width - bit_width;\n  *value >>= shift;\n  return shift;\n}\n\n// Checks if the given ParsedFloat represents one of the edge cases that are\n// not dependent on number base: zero, infinity, or NaN.  If so, sets *value\n// the appropriate double, and returns true.\ntemplate <typename FloatType>\nbool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,\n                    FloatType* absl_nonnull value) {\n  if (input.type == strings_internal::FloatType::kNan) {\n    // A bug in gcc would cause the compiler to optimize away the buffer we are\n    // building below.  Declaring the buffer volatile avoids the issue, and has\n    // no measurable performance impact in microbenchmarks.\n    //\n    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113\n    constexpr ptrdiff_t kNanBufferSize = 128;\n#if (defined(__GNUC__) && !defined(__clang__))\n    volatile char n_char_sequence[kNanBufferSize];\n#else\n    char n_char_sequence[kNanBufferSize];\n#endif\n    if (input.subrange_begin == nullptr) {\n      n_char_sequence[0] = '\\0';\n    } else {\n      ptrdiff_t nan_size = input.subrange_end - input.subrange_begin;\n      nan_size = std::min(nan_size, kNanBufferSize - 1);\n      std::copy_n(input.subrange_begin, nan_size, n_char_sequence);\n      n_char_sequence[nan_size] = '\\0';\n    }\n    char* nan_argument = const_cast<char*>(n_char_sequence);\n    *value = negative ? -FloatTraits<FloatType>::MakeNan(nan_argument)\n                      : FloatTraits<FloatType>::MakeNan(nan_argument);\n    return true;\n  }\n  if (input.type == strings_internal::FloatType::kInfinity) {\n    *value = negative ? -std::numeric_limits<FloatType>::infinity()\n                      : std::numeric_limits<FloatType>::infinity();\n    return true;\n  }\n  if (input.mantissa == 0) {\n    *value = negative ? -0.0f : 0.0f;\n    return true;\n  }\n  return false;\n}\n\n// Given a CalculatedFloat result of a from_chars conversion, generate the\n// correct output values.\n//\n// CalculatedFloat can represent an underflow or overflow, in which case the\n// error code in *result is set.  Otherwise, the calculated floating point\n// number is stored in *value.\ntemplate <typename FloatType>\nvoid EncodeResult(const CalculatedFloat& calculated, bool negative,\n                  absl::from_chars_result* absl_nonnull result,\n                  FloatType* absl_nonnull value) {\n  if (calculated.exponent == kOverflow) {\n    result->ec = std::errc::result_out_of_range;\n    *value = negative ? -std::numeric_limits<FloatType>::max()\n                      : std::numeric_limits<FloatType>::max();\n    return;\n  } else if (calculated.mantissa == 0 || calculated.exponent == kUnderflow) {\n    result->ec = std::errc::result_out_of_range;\n    *value = negative ? -0.0f : 0.0f;\n    return;\n  }\n  *value = FloatTraits<FloatType>::Make(\n      static_cast<typename FloatTraits<FloatType>::mantissa_t>(\n          calculated.mantissa),\n      calculated.exponent, negative);\n}\n\n// Returns the given uint128 shifted to the right by `shift` bits, and rounds\n// the remaining bits using round_to_nearest logic.  The value is returned as a\n// uint64_t, since this is the type used by this library for storing calculated\n// floating point mantissas.\n//\n// It is expected that the width of the input value shifted by `shift` will\n// be the correct bit-width for the target mantissa, which is strictly narrower\n// than a uint64_t.\n//\n// If `input_exact` is false, then a nonzero error epsilon is assumed.  For\n// rounding purposes, the true value being rounded is strictly greater than the\n// input value.  The error may represent a single lost carry bit.\n//\n// When input_exact, shifted bits of the form 1000000... represent a tie, which\n// is broken by rounding to even -- the rounding direction is chosen so the low\n// bit of the returned value is 0.\n//\n// When !input_exact, shifted bits of the form 10000000... represent a value\n// strictly greater than one half (due to the error epsilon), and so ties are\n// always broken by rounding up.\n//\n// When !input_exact, shifted bits of the form 01111111... are uncertain;\n// the true value may or may not be greater than 10000000..., due to the\n// possible lost carry bit.  The correct rounding direction is unknown.  In this\n// case, the result is rounded down, and `output_exact` is set to false.\n//\n// Zero and negative values of `shift` are accepted, in which case the word is\n// shifted left, as necessary.\nuint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact,\n                            bool* absl_nonnull output_exact) {\n  if (shift <= 0) {\n    *output_exact = input_exact;\n    return static_cast<uint64_t>(value << -shift);\n  }\n  if (shift >= 128) {\n    // Exponent is so small that we are shifting away all significant bits.\n    // Answer will not be representable, even as a subnormal, so return a zero\n    // mantissa (which represents underflow).\n    *output_exact = true;\n    return 0;\n  }\n\n  *output_exact = true;\n  const uint128 shift_mask = (uint128(1) << shift) - 1;\n  const uint128 halfway_point = uint128(1) << (shift - 1);\n\n  const uint128 shifted_bits = value & shift_mask;\n  value >>= shift;\n  if (shifted_bits > halfway_point) {\n    // Shifted bits greater than 10000... require rounding up.\n    return static_cast<uint64_t>(value + 1);\n  }\n  if (shifted_bits == halfway_point) {\n    // In exact mode, shifted bits of 10000... mean we're exactly halfway\n    // between two numbers, and we must round to even.  So only round up if\n    // the low bit of `value` is set.\n    //\n    // In inexact mode, the nonzero error means the actual value is greater\n    // than the halfway point and we must always round up.\n    if ((value & 1) == 1 || !input_exact) {\n      ++value;\n    }\n    return static_cast<uint64_t>(value);\n  }\n  if (!input_exact && shifted_bits == halfway_point - 1) {\n    // Rounding direction is unclear, due to error.\n    *output_exact = false;\n  }\n  // Otherwise, round down.\n  return static_cast<uint64_t>(value);\n}\n\n// Checks if a floating point guess needs to be rounded up, using high precision\n// math.\n//\n// `guess_mantissa` and `guess_exponent` represent a candidate guess for the\n// number represented by `parsed_decimal`.\n//\n// The exact number represented by `parsed_decimal` must lie between the two\n// numbers:\n//   A = `guess_mantissa * 2**guess_exponent`\n//   B = `(guess_mantissa + 1) * 2**guess_exponent`\n//\n// This function returns false if `A` is the better guess, and true if `B` is\n// the better guess, with rounding ties broken by rounding to even.\nbool MustRoundUp(uint64_t guess_mantissa, int guess_exponent,\n                 const strings_internal::ParsedFloat& parsed_decimal) {\n  // 768 is the number of digits needed in the worst case.  We could determine a\n  // better limit dynamically based on the value of parsed_decimal.exponent.\n  // This would optimize pathological input cases only.  (Sane inputs won't have\n  // hundreds of digits of mantissa.)\n  absl::strings_internal::BigUnsigned<84> exact_mantissa;\n  int exact_exponent = exact_mantissa.ReadFloatMantissa(parsed_decimal, 768);\n\n  // Adjust the `guess` arguments to be halfway between A and B.\n  guess_mantissa = guess_mantissa * 2 + 1;\n  guess_exponent -= 1;\n\n  // In our comparison:\n  // lhs = exact = exact_mantissa * 10**exact_exponent\n  //             = exact_mantissa * 5**exact_exponent * 2**exact_exponent\n  // rhs = guess = guess_mantissa * 2**guess_exponent\n  //\n  // Because we are doing integer math, we can't directly deal with negative\n  // exponents.  We instead move these to the other side of the inequality.\n  absl::strings_internal::BigUnsigned<84>& lhs = exact_mantissa;\n  int comparison;\n  if (exact_exponent >= 0) {\n    lhs.MultiplyByFiveToTheNth(exact_exponent);\n    absl::strings_internal::BigUnsigned<84> rhs(guess_mantissa);\n    // There are powers of 2 on both sides of the inequality; reduce this to\n    // a single bit-shift.\n    if (exact_exponent > guess_exponent) {\n      lhs.ShiftLeft(exact_exponent - guess_exponent);\n    } else {\n      rhs.ShiftLeft(guess_exponent - exact_exponent);\n    }\n    comparison = Compare(lhs, rhs);\n  } else {\n    // Move the power of 5 to the other side of the equation, giving us:\n    // lhs = exact_mantissa * 2**exact_exponent\n    // rhs = guess_mantissa * 5**(-exact_exponent) * 2**guess_exponent\n    absl::strings_internal::BigUnsigned<84> rhs =\n        absl::strings_internal::BigUnsigned<84>::FiveToTheNth(-exact_exponent);\n    rhs.MultiplyBy(guess_mantissa);\n    if (exact_exponent > guess_exponent) {\n      lhs.ShiftLeft(exact_exponent - guess_exponent);\n    } else {\n      rhs.ShiftLeft(guess_exponent - exact_exponent);\n    }\n    comparison = Compare(lhs, rhs);\n  }\n  if (comparison < 0) {\n    return false;\n  } else if (comparison > 0) {\n    return true;\n  } else {\n    // When lhs == rhs, the decimal input is exactly between A and B.\n    // Round towards even -- round up only if the low bit of the initial\n    // `guess_mantissa` was a 1.  We shifted guess_mantissa left 1 bit at\n    // the beginning of this function, so test the 2nd bit here.\n    return (guess_mantissa & 2) == 2;\n  }\n}\n\n// Constructs a CalculatedFloat from a given mantissa and exponent, but\n// with the following normalizations applied:\n//\n// If rounding has caused mantissa to increase just past the allowed bit\n// width, shift and adjust exponent.\n//\n// If exponent is too high, sets kOverflow.\n//\n// If mantissa is zero (representing a non-zero value not representable, even\n// as a subnormal), sets kUnderflow.\ntemplate <typename FloatType>\nCalculatedFloat CalculatedFloatFromRawValues(uint64_t mantissa, int exponent) {\n  CalculatedFloat result;\n  if (mantissa == uint64_t{1} << FloatTraits<FloatType>::kTargetMantissaBits) {\n    mantissa >>= 1;\n    exponent += 1;\n  }\n  if (exponent > FloatTraits<FloatType>::kMaxExponent) {\n    result.exponent = kOverflow;\n  } else if (mantissa == 0) {\n    result.exponent = kUnderflow;\n  } else {\n    result.exponent = exponent;\n    result.mantissa = mantissa;\n  }\n  return result;\n}\n\ntemplate <typename FloatType>\nCalculatedFloat CalculateFromParsedHexadecimal(\n    const strings_internal::ParsedFloat& parsed_hex) {\n  uint64_t mantissa = parsed_hex.mantissa;\n  int exponent = parsed_hex.exponent;\n  // This static_cast is only needed when using a std::bit_width()\n  // implementation that does not have the fix for LWG 3656 applied.\n  int mantissa_width = static_cast<int>(bit_width(mantissa));\n  const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);\n  bool result_exact;\n  exponent += shift;\n  mantissa = ShiftRightAndRound(mantissa, shift,\n                                /* input exact= */ true, &result_exact);\n  // ParseFloat handles rounding in the hexadecimal case, so we don't have to\n  // check `result_exact` here.\n  return CalculatedFloatFromRawValues<FloatType>(mantissa, exponent);\n}\n\ntemplate <typename FloatType>\nCalculatedFloat CalculateFromParsedDecimal(\n    const strings_internal::ParsedFloat& parsed_decimal) {\n  CalculatedFloat result;\n\n  // Large or small enough decimal exponents will always result in overflow\n  // or underflow.\n  if (Power10Underflow(parsed_decimal.exponent)) {\n    result.exponent = kUnderflow;\n    return result;\n  } else if (Power10Overflow(parsed_decimal.exponent)) {\n    result.exponent = kOverflow;\n    return result;\n  }\n\n  // Otherwise convert our power of 10 into a power of 2 times an integer\n  // mantissa, and multiply this by our parsed decimal mantissa.\n  uint128 wide_binary_mantissa = parsed_decimal.mantissa;\n  wide_binary_mantissa *= Power10Mantissa(parsed_decimal.exponent);\n  int binary_exponent = Power10Exponent(parsed_decimal.exponent);\n\n  // Discard bits that are inaccurate due to truncation error.  The magic\n  // `mantissa_width` constants below are justified in\n  // https://abseil.io/about/design/charconv. They represent the number of bits\n  // in `wide_binary_mantissa` that are guaranteed to be unaffected by error\n  // propagation.\n  bool mantissa_exact;\n  int mantissa_width;\n  if (parsed_decimal.subrange_begin) {\n    // Truncated mantissa\n    mantissa_width = 58;\n    mantissa_exact = false;\n    binary_exponent +=\n        TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);\n  } else if (!Power10Exact(parsed_decimal.exponent)) {\n    // Exact mantissa, truncated power of ten\n    mantissa_width = 63;\n    mantissa_exact = false;\n    binary_exponent +=\n        TruncateToBitWidth(mantissa_width, &wide_binary_mantissa);\n  } else {\n    // Product is exact\n    mantissa_width = BitWidth(wide_binary_mantissa);\n    mantissa_exact = true;\n  }\n\n  // Shift into an FloatType-sized mantissa, and round to nearest.\n  const int shift =\n      NormalizedShiftSize<FloatType>(mantissa_width, binary_exponent);\n  bool result_exact;\n  binary_exponent += shift;\n  uint64_t binary_mantissa = ShiftRightAndRound(wide_binary_mantissa, shift,\n                                                mantissa_exact, &result_exact);\n  if (!result_exact) {\n    // We could not determine the rounding direction using int128 math.  Use\n    // full resolution math instead.\n    if (MustRoundUp(binary_mantissa, binary_exponent, parsed_decimal)) {\n      binary_mantissa += 1;\n    }\n  }\n\n  return CalculatedFloatFromRawValues<FloatType>(binary_mantissa,\n                                                 binary_exponent);\n}\n\n// As discussed in https://nigeltao.github.io/blog/2020/eisel-lemire.html the\n// primary goal of the Eisel-Lemire algorithm is speed, for 99+% of the cases,\n// not 100% coverage. As long as Eisel-Lemire doesn’t claim false positives,\n// the combined approach (falling back to an alternative implementation when\n// this function returns false) is both fast and correct.\ntemplate <typename FloatType>\nbool EiselLemire(const strings_internal::ParsedFloat& input, bool negative,\n                 FloatType* absl_nonnull value, std::errc* absl_nonnull ec) {\n  uint64_t man = input.mantissa;\n  int exp10 = input.exponent;\n  if (exp10 < FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10) {\n    *value = negative ? -0.0f : 0.0f;\n    *ec = std::errc::result_out_of_range;\n    return true;\n  } else if (exp10 >= FloatTraits<FloatType>::kEiselLemireMaxExclusiveExp10) {\n    // Return max (a finite value) consistent with from_chars and DR 3081. For\n    // SimpleAtod and SimpleAtof, post-processing will return infinity.\n    *value = negative ? -std::numeric_limits<FloatType>::max()\n                      : std::numeric_limits<FloatType>::max();\n    *ec = std::errc::result_out_of_range;\n    return true;\n  }\n\n  // Assert kPower10TableMinInclusive <= exp10 < kPower10TableMaxExclusive.\n  // Equivalently, !Power10Underflow(exp10) and !Power10Overflow(exp10).\n  static_assert(\n      FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10 >=\n          kPower10TableMinInclusive,\n      \"(exp10-kPower10TableMinInclusive) in kPower10MantissaHighTable bounds\");\n  static_assert(\n      FloatTraits<FloatType>::kEiselLemireMaxExclusiveExp10 <=\n          kPower10TableMaxExclusive,\n      \"(exp10-kPower10TableMinInclusive) in kPower10MantissaHighTable bounds\");\n\n  // The terse (+) comments in this function body refer to sections of the\n  // https://nigeltao.github.io/blog/2020/eisel-lemire.html blog post.\n  //\n  // That blog post discusses double precision (11 exponent bits with a -1023\n  // bias, 52 mantissa bits), but the same approach applies to single precision\n  // (8 exponent bits with a -127 bias, 23 mantissa bits). Either way, the\n  // computation here happens with 64-bit values (e.g. man) or 128-bit values\n  // (e.g. x) before finally converting to 64- or 32-bit floating point.\n  //\n  // See also \"Number Parsing at a Gigabyte per Second, Software: Practice and\n  // Experience 51 (8), 2021\" (https://arxiv.org/abs/2101.11408) for detail.\n\n  // (+) Normalization.\n  int clz = countl_zero(man);\n  man <<= static_cast<unsigned int>(clz);\n  // The 217706 etc magic numbers are from the Power10Exponent function.\n  uint64_t ret_exp2 =\n      static_cast<uint64_t>((217706 * exp10 >> 16) + 64 +\n                            FloatTraits<FloatType>::kExponentBias - clz);\n\n  // (+) Multiplication.\n  uint128 x = static_cast<uint128>(man) *\n              static_cast<uint128>(\n                  kPower10MantissaHighTable[exp10 - kPower10TableMinInclusive]);\n\n  // (+) Wider Approximation.\n  static constexpr uint64_t high64_mask =\n      FloatTraits<FloatType>::kEiselLemireMask;\n  if (((Uint128High64(x) & high64_mask) == high64_mask) &&\n      (man > (std::numeric_limits<uint64_t>::max() - Uint128Low64(x)))) {\n    uint128 y =\n        static_cast<uint128>(man) *\n        static_cast<uint128>(\n            kPower10MantissaLowTable[exp10 - kPower10TableMinInclusive]);\n    x += Uint128High64(y);\n    // For example, parsing \"4503599627370497.5\" will take the if-true\n    // branch here (for double precision), since:\n    //  - x   = 0x8000000000000BFF_FFFFFFFFFFFFFFFF\n    //  - y   = 0x8000000000000BFF_7FFFFFFFFFFFF400\n    //  - man = 0xA000000000000F00\n    // Likewise, when parsing \"0.0625\" for single precision:\n    //  - x   = 0x7FFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF\n    //  - y   = 0x813FFFFFFFFFFFFF_8A00000000000000\n    //  - man = 0x9C40000000000000\n    if (((Uint128High64(x) & high64_mask) == high64_mask) &&\n        ((Uint128Low64(x) + 1) == 0) &&\n        (man > (std::numeric_limits<uint64_t>::max() - Uint128Low64(y)))) {\n      return false;\n    }\n  }\n\n  // (+) Shifting to 54 Bits (or for single precision, to 25 bits).\n  uint64_t msb = Uint128High64(x) >> 63;\n  uint64_t ret_man =\n      Uint128High64(x) >> (msb + FloatTraits<FloatType>::kEiselLemireShift);\n  ret_exp2 -= 1 ^ msb;\n\n  // (+) Half-way Ambiguity.\n  //\n  // For example, parsing \"1e+23\" will take the if-true branch here (for double\n  // precision), since:\n  //  - x       = 0x54B40B1F852BDA00_0000000000000000\n  //  - ret_man = 0x002A5A058FC295ED\n  // Likewise, when parsing \"20040229.0\" for single precision:\n  //  - x       = 0x4C72894000000000_0000000000000000\n  //  - ret_man = 0x000000000131CA25\n  if ((Uint128Low64(x) == 0) && ((Uint128High64(x) & high64_mask) == 0) &&\n      ((ret_man & 3) == 1)) {\n    return false;\n  }\n\n  // (+) From 54 to 53 Bits (or for single precision, from 25 to 24 bits).\n  ret_man += ret_man & 1;  // Line From54a.\n  ret_man >>= 1;           // Line From54b.\n  // Incrementing ret_man (at line From54a) may have overflowed 54 bits (53\n  // bits after the right shift by 1 at line From54b), so adjust for that.\n  //\n  // For example, parsing \"9223372036854775807\" will take the if-true branch\n  // here (for double precision), since:\n  //  - ret_man = 0x0020000000000000 = (1 << 53)\n  // Likewise, when parsing \"2147483647.0\" for single precision:\n  //  - ret_man = 0x0000000001000000 = (1 << 24)\n  if ((ret_man >> FloatTraits<FloatType>::kTargetMantissaBits) > 0) {\n    ret_exp2 += 1;\n    // Conceptually, we need a \"ret_man >>= 1\" in this if-block to balance\n    // incrementing ret_exp2 in the line immediately above. However, we only\n    // get here when line From54a overflowed (after adding a 1), so ret_man\n    // here is (1 << 53). Its low 53 bits are therefore all zeroes. The only\n    // remaining use of ret_man is to mask it with ((1 << 52) - 1), so only its\n    // low 52 bits matter. A \"ret_man >>= 1\" would have no effect in practice.\n    //\n    // We omit the \"ret_man >>= 1\", even if it is cheap (and this if-branch is\n    // rarely taken) and technically 'more correct', so that mutation tests\n    // that would otherwise modify or omit that \"ret_man >>= 1\" don't complain\n    // that such code mutations have no observable effect.\n  }\n\n  // ret_exp2 is a uint64_t. Zero or underflow means that we're in subnormal\n  // space. max_exp2 (0x7FF for double precision, 0xFF for single precision) or\n  // above means that we're in Inf/NaN space.\n  //\n  // The if block is equivalent to (but has fewer branches than):\n  //   if ((ret_exp2 <= 0) || (ret_exp2 >= max_exp2)) { etc }\n  //\n  // For example, parsing \"4.9406564584124654e-324\" will take the if-true\n  // branch here, since ret_exp2 = -51.\n  static constexpr uint64_t max_exp2 =\n      (1 << FloatTraits<FloatType>::kTargetExponentBits) - 1;\n  if ((ret_exp2 - 1) >= (max_exp2 - 1)) {\n    return false;\n  }\n\n#ifndef ABSL_BIT_PACK_FLOATS\n  if (FloatTraits<FloatType>::kTargetBits == 64) {\n    *value = FloatTraits<FloatType>::Make(\n        (ret_man & 0x000FFFFFFFFFFFFFu) | 0x0010000000000000u,\n        static_cast<int>(ret_exp2) - 1023 - 52, negative);\n    return true;\n  } else if (FloatTraits<FloatType>::kTargetBits == 32) {\n    *value = FloatTraits<FloatType>::Make(\n        (static_cast<uint32_t>(ret_man) & 0x007FFFFFu) | 0x00800000u,\n        static_cast<int>(ret_exp2) - 127 - 23, negative);\n    return true;\n  }\n#else\n  if (FloatTraits<FloatType>::kTargetBits == 64) {\n    uint64_t ret_bits = (ret_exp2 << 52) | (ret_man & 0x000FFFFFFFFFFFFFu);\n    if (negative) {\n      ret_bits |= 0x8000000000000000u;\n    }\n    *value = static_cast<FloatType>(absl::bit_cast<double>(ret_bits));\n    return true;\n  } else if (FloatTraits<FloatType>::kTargetBits == 32) {\n    uint32_t ret_bits = (static_cast<uint32_t>(ret_exp2) << 23) |\n                        (static_cast<uint32_t>(ret_man) & 0x007FFFFFu);\n    if (negative) {\n      ret_bits |= 0x80000000u;\n    }\n    *value = static_cast<FloatType>(absl::bit_cast<float>(ret_bits));\n    return true;\n  }\n#endif  // ABSL_BIT_PACK_FLOATS\n  return false;\n}\n\ntemplate <typename FloatType>\nfrom_chars_result FromCharsImpl(const char* absl_nonnull first,\n                                const char* absl_nonnull last, FloatType& value,\n                                chars_format fmt_flags) {\n  from_chars_result result;\n  result.ptr = first;  // overwritten on successful parse\n  result.ec = std::errc();\n\n  bool negative = false;\n  if (first != last && *first == '-') {\n    ++first;\n    negative = true;\n  }\n  // If the `hex` flag is *not* set, then we will accept a 0x prefix and try\n  // to parse a hexadecimal float.\n  if ((fmt_flags & chars_format::hex) == chars_format{} && last - first >= 2 &&\n      *first == '0' && (first[1] == 'x' || first[1] == 'X')) {\n    const char* hex_first = first + 2;\n    strings_internal::ParsedFloat hex_parse =\n        strings_internal::ParseFloat<16>(hex_first, last, fmt_flags);\n    if (hex_parse.end == nullptr ||\n        hex_parse.type != strings_internal::FloatType::kNumber) {\n      // Either we failed to parse a hex float after the \"0x\", or we read\n      // \"0xinf\" or \"0xnan\" which we don't want to match.\n      //\n      // However, a string that begins with \"0x\" also begins with \"0\", which\n      // is normally a valid match for the number zero.  So we want these\n      // strings to match zero unless fmt_flags is `scientific`.  (This flag\n      // means an exponent is required, which the string \"0\" does not have.)\n      if (fmt_flags == chars_format::scientific) {\n        result.ec = std::errc::invalid_argument;\n      } else {\n        result.ptr = first + 1;\n        value = negative ? -0.0f : 0.0f;\n      }\n      return result;\n    }\n    // We matched a value.\n    result.ptr = hex_parse.end;\n    if (HandleEdgeCase(hex_parse, negative, &value)) {\n      return result;\n    }\n    CalculatedFloat calculated =\n        CalculateFromParsedHexadecimal<FloatType>(hex_parse);\n    EncodeResult(calculated, negative, &result, &value);\n    return result;\n  }\n  // Otherwise, we choose the number base based on the flags.\n  if ((fmt_flags & chars_format::hex) == chars_format::hex) {\n    strings_internal::ParsedFloat hex_parse =\n        strings_internal::ParseFloat<16>(first, last, fmt_flags);\n    if (hex_parse.end == nullptr) {\n      result.ec = std::errc::invalid_argument;\n      return result;\n    }\n    result.ptr = hex_parse.end;\n    if (HandleEdgeCase(hex_parse, negative, &value)) {\n      return result;\n    }\n    CalculatedFloat calculated =\n        CalculateFromParsedHexadecimal<FloatType>(hex_parse);\n    EncodeResult(calculated, negative, &result, &value);\n    return result;\n  } else {\n    strings_internal::ParsedFloat decimal_parse =\n        strings_internal::ParseFloat<10>(first, last, fmt_flags);\n    if (decimal_parse.end == nullptr) {\n      result.ec = std::errc::invalid_argument;\n      return result;\n    }\n    result.ptr = decimal_parse.end;\n    if (HandleEdgeCase(decimal_parse, negative, &value)) {\n      return result;\n    }\n    // A nullptr subrange_begin means that the decimal_parse.mantissa is exact\n    // (not truncated), a precondition of the Eisel-Lemire algorithm.\n    if ((decimal_parse.subrange_begin == nullptr) &&\n        EiselLemire<FloatType>(decimal_parse, negative, &value, &result.ec)) {\n      return result;\n    }\n    CalculatedFloat calculated =\n        CalculateFromParsedDecimal<FloatType>(decimal_parse);\n    EncodeResult(calculated, negative, &result, &value);\n    return result;\n  }\n}\n}  // namespace\n\nfrom_chars_result from_chars(const char* absl_nonnull first,\n                             const char* absl_nonnull last, double& value,\n                             chars_format fmt) {\n  return FromCharsImpl(first, last, value, fmt);\n}\n\nfrom_chars_result from_chars(const char* absl_nonnull first,\n                             const char* absl_nonnull last, float& value,\n                             chars_format fmt) {\n  return FromCharsImpl(first, last, value, fmt);\n}\n\nnamespace {\n\n// Table of powers of 10, from kPower10TableMinInclusive to\n// kPower10TableMaxExclusive.\n//\n// kPower10MantissaHighTable[i - kPower10TableMinInclusive] stores the 64-bit\n// mantissa. The high bit is always on.\n//\n// kPower10MantissaLowTable extends that 64-bit mantissa to 128 bits.\n//\n// Power10Exponent(i) calculates the power-of-two exponent.\n//\n// For a number i, this gives the unique mantissaHigh and exponent such that\n// (mantissaHigh * 2**exponent) <= 10**i < ((mantissaHigh + 1) * 2**exponent).\n//\n// For example, Python can confirm that the exact hexadecimal value of 1e60 is:\n//    >>> a = 1000000000000000000000000000000000000000000000000000000000000\n//    >>> hex(a)\n//    '0x9f4f2726179a224501d762422c946590d91000000000000000'\n// Adding underscores at every 8th hex digit shows 50 hex digits:\n//    '0x9f4f2726_179a2245_01d76242_2c946590_d9100000_00000000_00'.\n// In this case, the high bit of the first hex digit, 9, is coincidentally set,\n// so we do not have to do further shifting to deduce the 128-bit mantissa:\n//   - kPower10MantissaHighTable[60 - kP10TMI] = 0x9f4f2726179a2245U\n//   - kPower10MantissaLowTable[ 60 - kP10TMI] = 0x01d762422c946590U\n// where kP10TMI is kPower10TableMinInclusive. The low 18 of those 50 hex\n// digits are truncated.\n//\n// 50 hex digits (with the high bit set) is 200 bits and mantissaHigh holds 64\n// bits, so Power10Exponent(60) = 200 - 64 = 136. Again, Python can confirm:\n//    >>> b = 0x9f4f2726179a2245\n//    >>> ((b+0)<<136) <= a\n//    True\n//    >>> ((b+1)<<136) <= a\n//    False\n//\n// The tables were generated by\n// https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go\n// after re-formatting its output into two arrays of N uint64_t values (instead\n// of an N element array of uint64_t pairs).\n\nconst uint64_t kPower10MantissaHighTable[] = {\n    0xeef453d6923bd65aU, 0x9558b4661b6565f8U, 0xbaaee17fa23ebf76U,\n    0xe95a99df8ace6f53U, 0x91d8a02bb6c10594U, 0xb64ec836a47146f9U,\n    0xe3e27a444d8d98b7U, 0x8e6d8c6ab0787f72U, 0xb208ef855c969f4fU,\n    0xde8b2b66b3bc4723U, 0x8b16fb203055ac76U, 0xaddcb9e83c6b1793U,\n    0xd953e8624b85dd78U, 0x87d4713d6f33aa6bU, 0xa9c98d8ccb009506U,\n    0xd43bf0effdc0ba48U, 0x84a57695fe98746dU, 0xa5ced43b7e3e9188U,\n    0xcf42894a5dce35eaU, 0x818995ce7aa0e1b2U, 0xa1ebfb4219491a1fU,\n    0xca66fa129f9b60a6U, 0xfd00b897478238d0U, 0x9e20735e8cb16382U,\n    0xc5a890362fddbc62U, 0xf712b443bbd52b7bU, 0x9a6bb0aa55653b2dU,\n    0xc1069cd4eabe89f8U, 0xf148440a256e2c76U, 0x96cd2a865764dbcaU,\n    0xbc807527ed3e12bcU, 0xeba09271e88d976bU, 0x93445b8731587ea3U,\n    0xb8157268fdae9e4cU, 0xe61acf033d1a45dfU, 0x8fd0c16206306babU,\n    0xb3c4f1ba87bc8696U, 0xe0b62e2929aba83cU, 0x8c71dcd9ba0b4925U,\n    0xaf8e5410288e1b6fU, 0xdb71e91432b1a24aU, 0x892731ac9faf056eU,\n    0xab70fe17c79ac6caU, 0xd64d3d9db981787dU, 0x85f0468293f0eb4eU,\n    0xa76c582338ed2621U, 0xd1476e2c07286faaU, 0x82cca4db847945caU,\n    0xa37fce126597973cU, 0xcc5fc196fefd7d0cU, 0xff77b1fcbebcdc4fU,\n    0x9faacf3df73609b1U, 0xc795830d75038c1dU, 0xf97ae3d0d2446f25U,\n    0x9becce62836ac577U, 0xc2e801fb244576d5U, 0xf3a20279ed56d48aU,\n    0x9845418c345644d6U, 0xbe5691ef416bd60cU, 0xedec366b11c6cb8fU,\n    0x94b3a202eb1c3f39U, 0xb9e08a83a5e34f07U, 0xe858ad248f5c22c9U,\n    0x91376c36d99995beU, 0xb58547448ffffb2dU, 0xe2e69915b3fff9f9U,\n    0x8dd01fad907ffc3bU, 0xb1442798f49ffb4aU, 0xdd95317f31c7fa1dU,\n    0x8a7d3eef7f1cfc52U, 0xad1c8eab5ee43b66U, 0xd863b256369d4a40U,\n    0x873e4f75e2224e68U, 0xa90de3535aaae202U, 0xd3515c2831559a83U,\n    0x8412d9991ed58091U, 0xa5178fff668ae0b6U, 0xce5d73ff402d98e3U,\n    0x80fa687f881c7f8eU, 0xa139029f6a239f72U, 0xc987434744ac874eU,\n    0xfbe9141915d7a922U, 0x9d71ac8fada6c9b5U, 0xc4ce17b399107c22U,\n    0xf6019da07f549b2bU, 0x99c102844f94e0fbU, 0xc0314325637a1939U,\n    0xf03d93eebc589f88U, 0x96267c7535b763b5U, 0xbbb01b9283253ca2U,\n    0xea9c227723ee8bcbU, 0x92a1958a7675175fU, 0xb749faed14125d36U,\n    0xe51c79a85916f484U, 0x8f31cc0937ae58d2U, 0xb2fe3f0b8599ef07U,\n    0xdfbdcece67006ac9U, 0x8bd6a141006042bdU, 0xaecc49914078536dU,\n    0xda7f5bf590966848U, 0x888f99797a5e012dU, 0xaab37fd7d8f58178U,\n    0xd5605fcdcf32e1d6U, 0x855c3be0a17fcd26U, 0xa6b34ad8c9dfc06fU,\n    0xd0601d8efc57b08bU, 0x823c12795db6ce57U, 0xa2cb1717b52481edU,\n    0xcb7ddcdda26da268U, 0xfe5d54150b090b02U, 0x9efa548d26e5a6e1U,\n    0xc6b8e9b0709f109aU, 0xf867241c8cc6d4c0U, 0x9b407691d7fc44f8U,\n    0xc21094364dfb5636U, 0xf294b943e17a2bc4U, 0x979cf3ca6cec5b5aU,\n    0xbd8430bd08277231U, 0xece53cec4a314ebdU, 0x940f4613ae5ed136U,\n    0xb913179899f68584U, 0xe757dd7ec07426e5U, 0x9096ea6f3848984fU,\n    0xb4bca50b065abe63U, 0xe1ebce4dc7f16dfbU, 0x8d3360f09cf6e4bdU,\n    0xb080392cc4349decU, 0xdca04777f541c567U, 0x89e42caaf9491b60U,\n    0xac5d37d5b79b6239U, 0xd77485cb25823ac7U, 0x86a8d39ef77164bcU,\n    0xa8530886b54dbdebU, 0xd267caa862a12d66U, 0x8380dea93da4bc60U,\n    0xa46116538d0deb78U, 0xcd795be870516656U, 0x806bd9714632dff6U,\n    0xa086cfcd97bf97f3U, 0xc8a883c0fdaf7df0U, 0xfad2a4b13d1b5d6cU,\n    0x9cc3a6eec6311a63U, 0xc3f490aa77bd60fcU, 0xf4f1b4d515acb93bU,\n    0x991711052d8bf3c5U, 0xbf5cd54678eef0b6U, 0xef340a98172aace4U,\n    0x9580869f0e7aac0eU, 0xbae0a846d2195712U, 0xe998d258869facd7U,\n    0x91ff83775423cc06U, 0xb67f6455292cbf08U, 0xe41f3d6a7377eecaU,\n    0x8e938662882af53eU, 0xb23867fb2a35b28dU, 0xdec681f9f4c31f31U,\n    0x8b3c113c38f9f37eU, 0xae0b158b4738705eU, 0xd98ddaee19068c76U,\n    0x87f8a8d4cfa417c9U, 0xa9f6d30a038d1dbcU, 0xd47487cc8470652bU,\n    0x84c8d4dfd2c63f3bU, 0xa5fb0a17c777cf09U, 0xcf79cc9db955c2ccU,\n    0x81ac1fe293d599bfU, 0xa21727db38cb002fU, 0xca9cf1d206fdc03bU,\n    0xfd442e4688bd304aU, 0x9e4a9cec15763e2eU, 0xc5dd44271ad3cdbaU,\n    0xf7549530e188c128U, 0x9a94dd3e8cf578b9U, 0xc13a148e3032d6e7U,\n    0xf18899b1bc3f8ca1U, 0x96f5600f15a7b7e5U, 0xbcb2b812db11a5deU,\n    0xebdf661791d60f56U, 0x936b9fcebb25c995U, 0xb84687c269ef3bfbU,\n    0xe65829b3046b0afaU, 0x8ff71a0fe2c2e6dcU, 0xb3f4e093db73a093U,\n    0xe0f218b8d25088b8U, 0x8c974f7383725573U, 0xafbd2350644eeacfU,\n    0xdbac6c247d62a583U, 0x894bc396ce5da772U, 0xab9eb47c81f5114fU,\n    0xd686619ba27255a2U, 0x8613fd0145877585U, 0xa798fc4196e952e7U,\n    0xd17f3b51fca3a7a0U, 0x82ef85133de648c4U, 0xa3ab66580d5fdaf5U,\n    0xcc963fee10b7d1b3U, 0xffbbcfe994e5c61fU, 0x9fd561f1fd0f9bd3U,\n    0xc7caba6e7c5382c8U, 0xf9bd690a1b68637bU, 0x9c1661a651213e2dU,\n    0xc31bfa0fe5698db8U, 0xf3e2f893dec3f126U, 0x986ddb5c6b3a76b7U,\n    0xbe89523386091465U, 0xee2ba6c0678b597fU, 0x94db483840b717efU,\n    0xba121a4650e4ddebU, 0xe896a0d7e51e1566U, 0x915e2486ef32cd60U,\n    0xb5b5ada8aaff80b8U, 0xe3231912d5bf60e6U, 0x8df5efabc5979c8fU,\n    0xb1736b96b6fd83b3U, 0xddd0467c64bce4a0U, 0x8aa22c0dbef60ee4U,\n    0xad4ab7112eb3929dU, 0xd89d64d57a607744U, 0x87625f056c7c4a8bU,\n    0xa93af6c6c79b5d2dU, 0xd389b47879823479U, 0x843610cb4bf160cbU,\n    0xa54394fe1eedb8feU, 0xce947a3da6a9273eU, 0x811ccc668829b887U,\n    0xa163ff802a3426a8U, 0xc9bcff6034c13052U, 0xfc2c3f3841f17c67U,\n    0x9d9ba7832936edc0U, 0xc5029163f384a931U, 0xf64335bcf065d37dU,\n    0x99ea0196163fa42eU, 0xc06481fb9bcf8d39U, 0xf07da27a82c37088U,\n    0x964e858c91ba2655U, 0xbbe226efb628afeaU, 0xeadab0aba3b2dbe5U,\n    0x92c8ae6b464fc96fU, 0xb77ada0617e3bbcbU, 0xe55990879ddcaabdU,\n    0x8f57fa54c2a9eab6U, 0xb32df8e9f3546564U, 0xdff9772470297ebdU,\n    0x8bfbea76c619ef36U, 0xaefae51477a06b03U, 0xdab99e59958885c4U,\n    0x88b402f7fd75539bU, 0xaae103b5fcd2a881U, 0xd59944a37c0752a2U,\n    0x857fcae62d8493a5U, 0xa6dfbd9fb8e5b88eU, 0xd097ad07a71f26b2U,\n    0x825ecc24c873782fU, 0xa2f67f2dfa90563bU, 0xcbb41ef979346bcaU,\n    0xfea126b7d78186bcU, 0x9f24b832e6b0f436U, 0xc6ede63fa05d3143U,\n    0xf8a95fcf88747d94U, 0x9b69dbe1b548ce7cU, 0xc24452da229b021bU,\n    0xf2d56790ab41c2a2U, 0x97c560ba6b0919a5U, 0xbdb6b8e905cb600fU,\n    0xed246723473e3813U, 0x9436c0760c86e30bU, 0xb94470938fa89bceU,\n    0xe7958cb87392c2c2U, 0x90bd77f3483bb9b9U, 0xb4ecd5f01a4aa828U,\n    0xe2280b6c20dd5232U, 0x8d590723948a535fU, 0xb0af48ec79ace837U,\n    0xdcdb1b2798182244U, 0x8a08f0f8bf0f156bU, 0xac8b2d36eed2dac5U,\n    0xd7adf884aa879177U, 0x86ccbb52ea94baeaU, 0xa87fea27a539e9a5U,\n    0xd29fe4b18e88640eU, 0x83a3eeeef9153e89U, 0xa48ceaaab75a8e2bU,\n    0xcdb02555653131b6U, 0x808e17555f3ebf11U, 0xa0b19d2ab70e6ed6U,\n    0xc8de047564d20a8bU, 0xfb158592be068d2eU, 0x9ced737bb6c4183dU,\n    0xc428d05aa4751e4cU, 0xf53304714d9265dfU, 0x993fe2c6d07b7fabU,\n    0xbf8fdb78849a5f96U, 0xef73d256a5c0f77cU, 0x95a8637627989aadU,\n    0xbb127c53b17ec159U, 0xe9d71b689dde71afU, 0x9226712162ab070dU,\n    0xb6b00d69bb55c8d1U, 0xe45c10c42a2b3b05U, 0x8eb98a7a9a5b04e3U,\n    0xb267ed1940f1c61cU, 0xdf01e85f912e37a3U, 0x8b61313bbabce2c6U,\n    0xae397d8aa96c1b77U, 0xd9c7dced53c72255U, 0x881cea14545c7575U,\n    0xaa242499697392d2U, 0xd4ad2dbfc3d07787U, 0x84ec3c97da624ab4U,\n    0xa6274bbdd0fadd61U, 0xcfb11ead453994baU, 0x81ceb32c4b43fcf4U,\n    0xa2425ff75e14fc31U, 0xcad2f7f5359a3b3eU, 0xfd87b5f28300ca0dU,\n    0x9e74d1b791e07e48U, 0xc612062576589ddaU, 0xf79687aed3eec551U,\n    0x9abe14cd44753b52U, 0xc16d9a0095928a27U, 0xf1c90080baf72cb1U,\n    0x971da05074da7beeU, 0xbce5086492111aeaU, 0xec1e4a7db69561a5U,\n    0x9392ee8e921d5d07U, 0xb877aa3236a4b449U, 0xe69594bec44de15bU,\n    0x901d7cf73ab0acd9U, 0xb424dc35095cd80fU, 0xe12e13424bb40e13U,\n    0x8cbccc096f5088cbU, 0xafebff0bcb24aafeU, 0xdbe6fecebdedd5beU,\n    0x89705f4136b4a597U, 0xabcc77118461cefcU, 0xd6bf94d5e57a42bcU,\n    0x8637bd05af6c69b5U, 0xa7c5ac471b478423U, 0xd1b71758e219652bU,\n    0x83126e978d4fdf3bU, 0xa3d70a3d70a3d70aU, 0xccccccccccccccccU,\n    0x8000000000000000U, 0xa000000000000000U, 0xc800000000000000U,\n    0xfa00000000000000U, 0x9c40000000000000U, 0xc350000000000000U,\n    0xf424000000000000U, 0x9896800000000000U, 0xbebc200000000000U,\n    0xee6b280000000000U, 0x9502f90000000000U, 0xba43b74000000000U,\n    0xe8d4a51000000000U, 0x9184e72a00000000U, 0xb5e620f480000000U,\n    0xe35fa931a0000000U, 0x8e1bc9bf04000000U, 0xb1a2bc2ec5000000U,\n    0xde0b6b3a76400000U, 0x8ac7230489e80000U, 0xad78ebc5ac620000U,\n    0xd8d726b7177a8000U, 0x878678326eac9000U, 0xa968163f0a57b400U,\n    0xd3c21bcecceda100U, 0x84595161401484a0U, 0xa56fa5b99019a5c8U,\n    0xcecb8f27f4200f3aU, 0x813f3978f8940984U, 0xa18f07d736b90be5U,\n    0xc9f2c9cd04674edeU, 0xfc6f7c4045812296U, 0x9dc5ada82b70b59dU,\n    0xc5371912364ce305U, 0xf684df56c3e01bc6U, 0x9a130b963a6c115cU,\n    0xc097ce7bc90715b3U, 0xf0bdc21abb48db20U, 0x96769950b50d88f4U,\n    0xbc143fa4e250eb31U, 0xeb194f8e1ae525fdU, 0x92efd1b8d0cf37beU,\n    0xb7abc627050305adU, 0xe596b7b0c643c719U, 0x8f7e32ce7bea5c6fU,\n    0xb35dbf821ae4f38bU, 0xe0352f62a19e306eU, 0x8c213d9da502de45U,\n    0xaf298d050e4395d6U, 0xdaf3f04651d47b4cU, 0x88d8762bf324cd0fU,\n    0xab0e93b6efee0053U, 0xd5d238a4abe98068U, 0x85a36366eb71f041U,\n    0xa70c3c40a64e6c51U, 0xd0cf4b50cfe20765U, 0x82818f1281ed449fU,\n    0xa321f2d7226895c7U, 0xcbea6f8ceb02bb39U, 0xfee50b7025c36a08U,\n    0x9f4f2726179a2245U, 0xc722f0ef9d80aad6U, 0xf8ebad2b84e0d58bU,\n    0x9b934c3b330c8577U, 0xc2781f49ffcfa6d5U, 0xf316271c7fc3908aU,\n    0x97edd871cfda3a56U, 0xbde94e8e43d0c8ecU, 0xed63a231d4c4fb27U,\n    0x945e455f24fb1cf8U, 0xb975d6b6ee39e436U, 0xe7d34c64a9c85d44U,\n    0x90e40fbeea1d3a4aU, 0xb51d13aea4a488ddU, 0xe264589a4dcdab14U,\n    0x8d7eb76070a08aecU, 0xb0de65388cc8ada8U, 0xdd15fe86affad912U,\n    0x8a2dbf142dfcc7abU, 0xacb92ed9397bf996U, 0xd7e77a8f87daf7fbU,\n    0x86f0ac99b4e8dafdU, 0xa8acd7c0222311bcU, 0xd2d80db02aabd62bU,\n    0x83c7088e1aab65dbU, 0xa4b8cab1a1563f52U, 0xcde6fd5e09abcf26U,\n    0x80b05e5ac60b6178U, 0xa0dc75f1778e39d6U, 0xc913936dd571c84cU,\n    0xfb5878494ace3a5fU, 0x9d174b2dcec0e47bU, 0xc45d1df942711d9aU,\n    0xf5746577930d6500U, 0x9968bf6abbe85f20U, 0xbfc2ef456ae276e8U,\n    0xefb3ab16c59b14a2U, 0x95d04aee3b80ece5U, 0xbb445da9ca61281fU,\n    0xea1575143cf97226U, 0x924d692ca61be758U, 0xb6e0c377cfa2e12eU,\n    0xe498f455c38b997aU, 0x8edf98b59a373fecU, 0xb2977ee300c50fe7U,\n    0xdf3d5e9bc0f653e1U, 0x8b865b215899f46cU, 0xae67f1e9aec07187U,\n    0xda01ee641a708de9U, 0x884134fe908658b2U, 0xaa51823e34a7eedeU,\n    0xd4e5e2cdc1d1ea96U, 0x850fadc09923329eU, 0xa6539930bf6bff45U,\n    0xcfe87f7cef46ff16U, 0x81f14fae158c5f6eU, 0xa26da3999aef7749U,\n    0xcb090c8001ab551cU, 0xfdcb4fa002162a63U, 0x9e9f11c4014dda7eU,\n    0xc646d63501a1511dU, 0xf7d88bc24209a565U, 0x9ae757596946075fU,\n    0xc1a12d2fc3978937U, 0xf209787bb47d6b84U, 0x9745eb4d50ce6332U,\n    0xbd176620a501fbffU, 0xec5d3fa8ce427affU, 0x93ba47c980e98cdfU,\n    0xb8a8d9bbe123f017U, 0xe6d3102ad96cec1dU, 0x9043ea1ac7e41392U,\n    0xb454e4a179dd1877U, 0xe16a1dc9d8545e94U, 0x8ce2529e2734bb1dU,\n    0xb01ae745b101e9e4U, 0xdc21a1171d42645dU, 0x899504ae72497ebaU,\n    0xabfa45da0edbde69U, 0xd6f8d7509292d603U, 0x865b86925b9bc5c2U,\n    0xa7f26836f282b732U, 0xd1ef0244af2364ffU, 0x8335616aed761f1fU,\n    0xa402b9c5a8d3a6e7U, 0xcd036837130890a1U, 0x802221226be55a64U,\n    0xa02aa96b06deb0fdU, 0xc83553c5c8965d3dU, 0xfa42a8b73abbf48cU,\n    0x9c69a97284b578d7U, 0xc38413cf25e2d70dU, 0xf46518c2ef5b8cd1U,\n    0x98bf2f79d5993802U, 0xbeeefb584aff8603U, 0xeeaaba2e5dbf6784U,\n    0x952ab45cfa97a0b2U, 0xba756174393d88dfU, 0xe912b9d1478ceb17U,\n    0x91abb422ccb812eeU, 0xb616a12b7fe617aaU, 0xe39c49765fdf9d94U,\n    0x8e41ade9fbebc27dU, 0xb1d219647ae6b31cU, 0xde469fbd99a05fe3U,\n    0x8aec23d680043beeU, 0xada72ccc20054ae9U, 0xd910f7ff28069da4U,\n    0x87aa9aff79042286U, 0xa99541bf57452b28U, 0xd3fa922f2d1675f2U,\n    0x847c9b5d7c2e09b7U, 0xa59bc234db398c25U, 0xcf02b2c21207ef2eU,\n    0x8161afb94b44f57dU, 0xa1ba1ba79e1632dcU, 0xca28a291859bbf93U,\n    0xfcb2cb35e702af78U, 0x9defbf01b061adabU, 0xc56baec21c7a1916U,\n    0xf6c69a72a3989f5bU, 0x9a3c2087a63f6399U, 0xc0cb28a98fcf3c7fU,\n    0xf0fdf2d3f3c30b9fU, 0x969eb7c47859e743U, 0xbc4665b596706114U,\n    0xeb57ff22fc0c7959U, 0x9316ff75dd87cbd8U, 0xb7dcbf5354e9beceU,\n    0xe5d3ef282a242e81U, 0x8fa475791a569d10U, 0xb38d92d760ec4455U,\n    0xe070f78d3927556aU, 0x8c469ab843b89562U, 0xaf58416654a6babbU,\n    0xdb2e51bfe9d0696aU, 0x88fcf317f22241e2U, 0xab3c2fddeeaad25aU,\n    0xd60b3bd56a5586f1U, 0x85c7056562757456U, 0xa738c6bebb12d16cU,\n    0xd106f86e69d785c7U, 0x82a45b450226b39cU, 0xa34d721642b06084U,\n    0xcc20ce9bd35c78a5U, 0xff290242c83396ceU, 0x9f79a169bd203e41U,\n    0xc75809c42c684dd1U, 0xf92e0c3537826145U, 0x9bbcc7a142b17ccbU,\n    0xc2abf989935ddbfeU, 0xf356f7ebf83552feU, 0x98165af37b2153deU,\n    0xbe1bf1b059e9a8d6U, 0xeda2ee1c7064130cU, 0x9485d4d1c63e8be7U,\n    0xb9a74a0637ce2ee1U, 0xe8111c87c5c1ba99U, 0x910ab1d4db9914a0U,\n    0xb54d5e4a127f59c8U, 0xe2a0b5dc971f303aU, 0x8da471a9de737e24U,\n    0xb10d8e1456105dadU, 0xdd50f1996b947518U, 0x8a5296ffe33cc92fU,\n    0xace73cbfdc0bfb7bU, 0xd8210befd30efa5aU, 0x8714a775e3e95c78U,\n    0xa8d9d1535ce3b396U, 0xd31045a8341ca07cU, 0x83ea2b892091e44dU,\n    0xa4e4b66b68b65d60U, 0xce1de40642e3f4b9U, 0x80d2ae83e9ce78f3U,\n    0xa1075a24e4421730U, 0xc94930ae1d529cfcU, 0xfb9b7cd9a4a7443cU,\n    0x9d412e0806e88aa5U, 0xc491798a08a2ad4eU, 0xf5b5d7ec8acb58a2U,\n    0x9991a6f3d6bf1765U, 0xbff610b0cc6edd3fU, 0xeff394dcff8a948eU,\n    0x95f83d0a1fb69cd9U, 0xbb764c4ca7a4440fU, 0xea53df5fd18d5513U,\n    0x92746b9be2f8552cU, 0xb7118682dbb66a77U, 0xe4d5e82392a40515U,\n    0x8f05b1163ba6832dU, 0xb2c71d5bca9023f8U, 0xdf78e4b2bd342cf6U,\n    0x8bab8eefb6409c1aU, 0xae9672aba3d0c320U, 0xda3c0f568cc4f3e8U,\n    0x8865899617fb1871U, 0xaa7eebfb9df9de8dU, 0xd51ea6fa85785631U,\n    0x8533285c936b35deU, 0xa67ff273b8460356U, 0xd01fef10a657842cU,\n    0x8213f56a67f6b29bU, 0xa298f2c501f45f42U, 0xcb3f2f7642717713U,\n    0xfe0efb53d30dd4d7U, 0x9ec95d1463e8a506U, 0xc67bb4597ce2ce48U,\n    0xf81aa16fdc1b81daU, 0x9b10a4e5e9913128U, 0xc1d4ce1f63f57d72U,\n    0xf24a01a73cf2dccfU, 0x976e41088617ca01U, 0xbd49d14aa79dbc82U,\n    0xec9c459d51852ba2U, 0x93e1ab8252f33b45U, 0xb8da1662e7b00a17U,\n    0xe7109bfba19c0c9dU, 0x906a617d450187e2U, 0xb484f9dc9641e9daU,\n    0xe1a63853bbd26451U, 0x8d07e33455637eb2U, 0xb049dc016abc5e5fU,\n    0xdc5c5301c56b75f7U, 0x89b9b3e11b6329baU, 0xac2820d9623bf429U,\n    0xd732290fbacaf133U, 0x867f59a9d4bed6c0U, 0xa81f301449ee8c70U,\n    0xd226fc195c6a2f8cU, 0x83585d8fd9c25db7U, 0xa42e74f3d032f525U,\n    0xcd3a1230c43fb26fU, 0x80444b5e7aa7cf85U, 0xa0555e361951c366U,\n    0xc86ab5c39fa63440U, 0xfa856334878fc150U, 0x9c935e00d4b9d8d2U,\n    0xc3b8358109e84f07U, 0xf4a642e14c6262c8U, 0x98e7e9cccfbd7dbdU,\n    0xbf21e44003acdd2cU, 0xeeea5d5004981478U, 0x95527a5202df0ccbU,\n    0xbaa718e68396cffdU, 0xe950df20247c83fdU, 0x91d28b7416cdd27eU,\n    0xb6472e511c81471dU, 0xe3d8f9e563a198e5U, 0x8e679c2f5e44ff8fU,\n};\n\nconst uint64_t kPower10MantissaLowTable[] = {\n    0x113faa2906a13b3fU, 0x4ac7ca59a424c507U, 0x5d79bcf00d2df649U,\n    0xf4d82c2c107973dcU, 0x79071b9b8a4be869U, 0x9748e2826cdee284U,\n    0xfd1b1b2308169b25U, 0xfe30f0f5e50e20f7U, 0xbdbd2d335e51a935U,\n    0xad2c788035e61382U, 0x4c3bcb5021afcc31U, 0xdf4abe242a1bbf3dU,\n    0xd71d6dad34a2af0dU, 0x8672648c40e5ad68U, 0x680efdaf511f18c2U,\n    0x0212bd1b2566def2U, 0x014bb630f7604b57U, 0x419ea3bd35385e2dU,\n    0x52064cac828675b9U, 0x7343efebd1940993U, 0x1014ebe6c5f90bf8U,\n    0xd41a26e077774ef6U, 0x8920b098955522b4U, 0x55b46e5f5d5535b0U,\n    0xeb2189f734aa831dU, 0xa5e9ec7501d523e4U, 0x47b233c92125366eU,\n    0x999ec0bb696e840aU, 0xc00670ea43ca250dU, 0x380406926a5e5728U,\n    0xc605083704f5ecf2U, 0xf7864a44c633682eU, 0x7ab3ee6afbe0211dU,\n    0x5960ea05bad82964U, 0x6fb92487298e33bdU, 0xa5d3b6d479f8e056U,\n    0x8f48a4899877186cU, 0x331acdabfe94de87U, 0x9ff0c08b7f1d0b14U,\n    0x07ecf0ae5ee44dd9U, 0xc9e82cd9f69d6150U, 0xbe311c083a225cd2U,\n    0x6dbd630a48aaf406U, 0x092cbbccdad5b108U, 0x25bbf56008c58ea5U,\n    0xaf2af2b80af6f24eU, 0x1af5af660db4aee1U, 0x50d98d9fc890ed4dU,\n    0xe50ff107bab528a0U, 0x1e53ed49a96272c8U, 0x25e8e89c13bb0f7aU,\n    0x77b191618c54e9acU, 0xd59df5b9ef6a2417U, 0x4b0573286b44ad1dU,\n    0x4ee367f9430aec32U, 0x229c41f793cda73fU, 0x6b43527578c1110fU,\n    0x830a13896b78aaa9U, 0x23cc986bc656d553U, 0x2cbfbe86b7ec8aa8U,\n    0x7bf7d71432f3d6a9U, 0xdaf5ccd93fb0cc53U, 0xd1b3400f8f9cff68U,\n    0x23100809b9c21fa1U, 0xabd40a0c2832a78aU, 0x16c90c8f323f516cU,\n    0xae3da7d97f6792e3U, 0x99cd11cfdf41779cU, 0x40405643d711d583U,\n    0x482835ea666b2572U, 0xda3243650005eecfU, 0x90bed43e40076a82U,\n    0x5a7744a6e804a291U, 0x711515d0a205cb36U, 0x0d5a5b44ca873e03U,\n    0xe858790afe9486c2U, 0x626e974dbe39a872U, 0xfb0a3d212dc8128fU,\n    0x7ce66634bc9d0b99U, 0x1c1fffc1ebc44e80U, 0xa327ffb266b56220U,\n    0x4bf1ff9f0062baa8U, 0x6f773fc3603db4a9U, 0xcb550fb4384d21d3U,\n    0x7e2a53a146606a48U, 0x2eda7444cbfc426dU, 0xfa911155fefb5308U,\n    0x793555ab7eba27caU, 0x4bc1558b2f3458deU, 0x9eb1aaedfb016f16U,\n    0x465e15a979c1cadcU, 0x0bfacd89ec191ec9U, 0xcef980ec671f667bU,\n    0x82b7e12780e7401aU, 0xd1b2ecb8b0908810U, 0x861fa7e6dcb4aa15U,\n    0x67a791e093e1d49aU, 0xe0c8bb2c5c6d24e0U, 0x58fae9f773886e18U,\n    0xaf39a475506a899eU, 0x6d8406c952429603U, 0xc8e5087ba6d33b83U,\n    0xfb1e4a9a90880a64U, 0x5cf2eea09a55067fU, 0xf42faa48c0ea481eU,\n    0xf13b94daf124da26U, 0x76c53d08d6b70858U, 0x54768c4b0c64ca6eU,\n    0xa9942f5dcf7dfd09U, 0xd3f93b35435d7c4cU, 0xc47bc5014a1a6dafU,\n    0x359ab6419ca1091bU, 0xc30163d203c94b62U, 0x79e0de63425dcf1dU,\n    0x985915fc12f542e4U, 0x3e6f5b7b17b2939dU, 0xa705992ceecf9c42U,\n    0x50c6ff782a838353U, 0xa4f8bf5635246428U, 0x871b7795e136be99U,\n    0x28e2557b59846e3fU, 0x331aeada2fe589cfU, 0x3ff0d2c85def7621U,\n    0x0fed077a756b53a9U, 0xd3e8495912c62894U, 0x64712dd7abbbd95cU,\n    0xbd8d794d96aacfb3U, 0xecf0d7a0fc5583a0U, 0xf41686c49db57244U,\n    0x311c2875c522ced5U, 0x7d633293366b828bU, 0xae5dff9c02033197U,\n    0xd9f57f830283fdfcU, 0xd072df63c324fd7bU, 0x4247cb9e59f71e6dU,\n    0x52d9be85f074e608U, 0x67902e276c921f8bU, 0x00ba1cd8a3db53b6U,\n    0x80e8a40eccd228a4U, 0x6122cd128006b2cdU, 0x796b805720085f81U,\n    0xcbe3303674053bb0U, 0xbedbfc4411068a9cU, 0xee92fb5515482d44U,\n    0x751bdd152d4d1c4aU, 0xd262d45a78a0635dU, 0x86fb897116c87c34U,\n    0xd45d35e6ae3d4da0U, 0x8974836059cca109U, 0x2bd1a438703fc94bU,\n    0x7b6306a34627ddcfU, 0x1a3bc84c17b1d542U, 0x20caba5f1d9e4a93U,\n    0x547eb47b7282ee9cU, 0xe99e619a4f23aa43U, 0x6405fa00e2ec94d4U,\n    0xde83bc408dd3dd04U, 0x9624ab50b148d445U, 0x3badd624dd9b0957U,\n    0xe54ca5d70a80e5d6U, 0x5e9fcf4ccd211f4cU, 0x7647c3200069671fU,\n    0x29ecd9f40041e073U, 0xf468107100525890U, 0x7182148d4066eeb4U,\n    0xc6f14cd848405530U, 0xb8ada00e5a506a7cU, 0xa6d90811f0e4851cU,\n    0x908f4a166d1da663U, 0x9a598e4e043287feU, 0x40eff1e1853f29fdU,\n    0xd12bee59e68ef47cU, 0x82bb74f8301958ceU, 0xe36a52363c1faf01U,\n    0xdc44e6c3cb279ac1U, 0x29ab103a5ef8c0b9U, 0x7415d448f6b6f0e7U,\n    0x111b495b3464ad21U, 0xcab10dd900beec34U, 0x3d5d514f40eea742U,\n    0x0cb4a5a3112a5112U, 0x47f0e785eaba72abU, 0x59ed216765690f56U,\n    0x306869c13ec3532cU, 0x1e414218c73a13fbU, 0xe5d1929ef90898faU,\n    0xdf45f746b74abf39U, 0x6b8bba8c328eb783U, 0x066ea92f3f326564U,\n    0xc80a537b0efefebdU, 0xbd06742ce95f5f36U, 0x2c48113823b73704U,\n    0xf75a15862ca504c5U, 0x9a984d73dbe722fbU, 0xc13e60d0d2e0ebbaU,\n    0x318df905079926a8U, 0xfdf17746497f7052U, 0xfeb6ea8bedefa633U,\n    0xfe64a52ee96b8fc0U, 0x3dfdce7aa3c673b0U, 0x06bea10ca65c084eU,\n    0x486e494fcff30a62U, 0x5a89dba3c3efccfaU, 0xf89629465a75e01cU,\n    0xf6bbb397f1135823U, 0x746aa07ded582e2cU, 0xa8c2a44eb4571cdcU,\n    0x92f34d62616ce413U, 0x77b020baf9c81d17U, 0x0ace1474dc1d122eU,\n    0x0d819992132456baU, 0x10e1fff697ed6c69U, 0xca8d3ffa1ef463c1U,\n    0xbd308ff8a6b17cb2U, 0xac7cb3f6d05ddbdeU, 0x6bcdf07a423aa96bU,\n    0x86c16c98d2c953c6U, 0xe871c7bf077ba8b7U, 0x11471cd764ad4972U,\n    0xd598e40d3dd89bcfU, 0x4aff1d108d4ec2c3U, 0xcedf722a585139baU,\n    0xc2974eb4ee658828U, 0x733d226229feea32U, 0x0806357d5a3f525fU,\n    0xca07c2dcb0cf26f7U, 0xfc89b393dd02f0b5U, 0xbbac2078d443ace2U,\n    0xd54b944b84aa4c0dU, 0x0a9e795e65d4df11U, 0x4d4617b5ff4a16d5U,\n    0x504bced1bf8e4e45U, 0xe45ec2862f71e1d6U, 0x5d767327bb4e5a4cU,\n    0x3a6a07f8d510f86fU, 0x890489f70a55368bU, 0x2b45ac74ccea842eU,\n    0x3b0b8bc90012929dU, 0x09ce6ebb40173744U, 0xcc420a6a101d0515U,\n    0x9fa946824a12232dU, 0x47939822dc96abf9U, 0x59787e2b93bc56f7U,\n    0x57eb4edb3c55b65aU, 0xede622920b6b23f1U, 0xe95fab368e45ecedU,\n    0x11dbcb0218ebb414U, 0xd652bdc29f26a119U, 0x4be76d3346f0495fU,\n    0x6f70a4400c562ddbU, 0xcb4ccd500f6bb952U, 0x7e2000a41346a7a7U,\n    0x8ed400668c0c28c8U, 0x728900802f0f32faU, 0x4f2b40a03ad2ffb9U,\n    0xe2f610c84987bfa8U, 0x0dd9ca7d2df4d7c9U, 0x91503d1c79720dbbU,\n    0x75a44c6397ce912aU, 0xc986afbe3ee11abaU, 0xfbe85badce996168U,\n    0xfae27299423fb9c3U, 0xdccd879fc967d41aU, 0x5400e987bbc1c920U,\n    0x290123e9aab23b68U, 0xf9a0b6720aaf6521U, 0xf808e40e8d5b3e69U,\n    0xb60b1d1230b20e04U, 0xb1c6f22b5e6f48c2U, 0x1e38aeb6360b1af3U,\n    0x25c6da63c38de1b0U, 0x579c487e5a38ad0eU, 0x2d835a9df0c6d851U,\n    0xf8e431456cf88e65U, 0x1b8e9ecb641b58ffU, 0xe272467e3d222f3fU,\n    0x5b0ed81dcc6abb0fU, 0x98e947129fc2b4e9U, 0x3f2398d747b36224U,\n    0x8eec7f0d19a03aadU, 0x1953cf68300424acU, 0x5fa8c3423c052dd7U,\n    0x3792f412cb06794dU, 0xe2bbd88bbee40bd0U, 0x5b6aceaeae9d0ec4U,\n    0xf245825a5a445275U, 0xeed6e2f0f0d56712U, 0x55464dd69685606bU,\n    0xaa97e14c3c26b886U, 0xd53dd99f4b3066a8U, 0xe546a8038efe4029U,\n    0xde98520472bdd033U, 0x963e66858f6d4440U, 0xdde7001379a44aa8U,\n    0x5560c018580d5d52U, 0xaab8f01e6e10b4a6U, 0xcab3961304ca70e8U,\n    0x3d607b97c5fd0d22U, 0x8cb89a7db77c506aU, 0x77f3608e92adb242U,\n    0x55f038b237591ed3U, 0x6b6c46dec52f6688U, 0x2323ac4b3b3da015U,\n    0xabec975e0a0d081aU, 0x96e7bd358c904a21U, 0x7e50d64177da2e54U,\n    0xdde50bd1d5d0b9e9U, 0x955e4ec64b44e864U, 0xbd5af13bef0b113eU,\n    0xecb1ad8aeacdd58eU, 0x67de18eda5814af2U, 0x80eacf948770ced7U,\n    0xa1258379a94d028dU, 0x096ee45813a04330U, 0x8bca9d6e188853fcU,\n    0x775ea264cf55347dU, 0x95364afe032a819dU, 0x3a83ddbd83f52204U,\n    0xc4926a9672793542U, 0x75b7053c0f178293U, 0x5324c68b12dd6338U,\n    0xd3f6fc16ebca5e03U, 0x88f4bb1ca6bcf584U, 0x2b31e9e3d06c32e5U,\n    0x3aff322e62439fcfU, 0x09befeb9fad487c2U, 0x4c2ebe687989a9b3U,\n    0x0f9d37014bf60a10U, 0x538484c19ef38c94U, 0x2865a5f206b06fb9U,\n    0xf93f87b7442e45d3U, 0xf78f69a51539d748U, 0xb573440e5a884d1bU,\n    0x31680a88f8953030U, 0xfdc20d2b36ba7c3dU, 0x3d32907604691b4cU,\n    0xa63f9a49c2c1b10fU, 0x0fcf80dc33721d53U, 0xd3c36113404ea4a8U,\n    0x645a1cac083126e9U, 0x3d70a3d70a3d70a3U, 0xccccccccccccccccU,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,\n    0x0000000000000000U, 0x4000000000000000U, 0x5000000000000000U,\n    0xa400000000000000U, 0x4d00000000000000U, 0xf020000000000000U,\n    0x6c28000000000000U, 0xc732000000000000U, 0x3c7f400000000000U,\n    0x4b9f100000000000U, 0x1e86d40000000000U, 0x1314448000000000U,\n    0x17d955a000000000U, 0x5dcfab0800000000U, 0x5aa1cae500000000U,\n    0xf14a3d9e40000000U, 0x6d9ccd05d0000000U, 0xe4820023a2000000U,\n    0xdda2802c8a800000U, 0xd50b2037ad200000U, 0x4526f422cc340000U,\n    0x9670b12b7f410000U, 0x3c0cdd765f114000U, 0xa5880a69fb6ac800U,\n    0x8eea0d047a457a00U, 0x72a4904598d6d880U, 0x47a6da2b7f864750U,\n    0x999090b65f67d924U, 0xfff4b4e3f741cf6dU, 0xbff8f10e7a8921a4U,\n    0xaff72d52192b6a0dU, 0x9bf4f8a69f764490U, 0x02f236d04753d5b4U,\n    0x01d762422c946590U, 0x424d3ad2b7b97ef5U, 0xd2e0898765a7deb2U,\n    0x63cc55f49f88eb2fU, 0x3cbf6b71c76b25fbU, 0x8bef464e3945ef7aU,\n    0x97758bf0e3cbb5acU, 0x3d52eeed1cbea317U, 0x4ca7aaa863ee4bddU,\n    0x8fe8caa93e74ef6aU, 0xb3e2fd538e122b44U, 0x60dbbca87196b616U,\n    0xbc8955e946fe31cdU, 0x6babab6398bdbe41U, 0xc696963c7eed2dd1U,\n    0xfc1e1de5cf543ca2U, 0x3b25a55f43294bcbU, 0x49ef0eb713f39ebeU,\n    0x6e3569326c784337U, 0x49c2c37f07965404U, 0xdc33745ec97be906U,\n    0x69a028bb3ded71a3U, 0xc40832ea0d68ce0cU, 0xf50a3fa490c30190U,\n    0x792667c6da79e0faU, 0x577001b891185938U, 0xed4c0226b55e6f86U,\n    0x544f8158315b05b4U, 0x696361ae3db1c721U, 0x03bc3a19cd1e38e9U,\n    0x04ab48a04065c723U, 0x62eb0d64283f9c76U, 0x3ba5d0bd324f8394U,\n    0xca8f44ec7ee36479U, 0x7e998b13cf4e1ecbU, 0x9e3fedd8c321a67eU,\n    0xc5cfe94ef3ea101eU, 0xbba1f1d158724a12U, 0x2a8a6e45ae8edc97U,\n    0xf52d09d71a3293bdU, 0x593c2626705f9c56U, 0x6f8b2fb00c77836cU,\n    0x0b6dfb9c0f956447U, 0x4724bd4189bd5eacU, 0x58edec91ec2cb657U,\n    0x2f2967b66737e3edU, 0xbd79e0d20082ee74U, 0xecd8590680a3aa11U,\n    0xe80e6f4820cc9495U, 0x3109058d147fdcddU, 0xbd4b46f0599fd415U,\n    0x6c9e18ac7007c91aU, 0x03e2cf6bc604ddb0U, 0x84db8346b786151cU,\n    0xe612641865679a63U, 0x4fcb7e8f3f60c07eU, 0xe3be5e330f38f09dU,\n    0x5cadf5bfd3072cc5U, 0x73d9732fc7c8f7f6U, 0x2867e7fddcdd9afaU,\n    0xb281e1fd541501b8U, 0x1f225a7ca91a4226U, 0x3375788de9b06958U,\n    0x0052d6b1641c83aeU, 0xc0678c5dbd23a49aU, 0xf840b7ba963646e0U,\n    0xb650e5a93bc3d898U, 0xa3e51f138ab4cebeU, 0xc66f336c36b10137U,\n    0xb80b0047445d4184U, 0xa60dc059157491e5U, 0x87c89837ad68db2fU,\n    0x29babe4598c311fbU, 0xf4296dd6fef3d67aU, 0x1899e4a65f58660cU,\n    0x5ec05dcff72e7f8fU, 0x76707543f4fa1f73U, 0x6a06494a791c53a8U,\n    0x0487db9d17636892U, 0x45a9d2845d3c42b6U, 0x0b8a2392ba45a9b2U,\n    0x8e6cac7768d7141eU, 0x3207d795430cd926U, 0x7f44e6bd49e807b8U,\n    0x5f16206c9c6209a6U, 0x36dba887c37a8c0fU, 0xc2494954da2c9789U,\n    0xf2db9baa10b7bd6cU, 0x6f92829494e5acc7U, 0xcb772339ba1f17f9U,\n    0xff2a760414536efbU, 0xfef5138519684abaU, 0x7eb258665fc25d69U,\n    0xef2f773ffbd97a61U, 0xaafb550ffacfd8faU, 0x95ba2a53f983cf38U,\n    0xdd945a747bf26183U, 0x94f971119aeef9e4U, 0x7a37cd5601aab85dU,\n    0xac62e055c10ab33aU, 0x577b986b314d6009U, 0xed5a7e85fda0b80bU,\n    0x14588f13be847307U, 0x596eb2d8ae258fc8U, 0x6fca5f8ed9aef3bbU,\n    0x25de7bb9480d5854U, 0xaf561aa79a10ae6aU, 0x1b2ba1518094da04U,\n    0x90fb44d2f05d0842U, 0x353a1607ac744a53U, 0x42889b8997915ce8U,\n    0x69956135febada11U, 0x43fab9837e699095U, 0x94f967e45e03f4bbU,\n    0x1d1be0eebac278f5U, 0x6462d92a69731732U, 0x7d7b8f7503cfdcfeU,\n    0x5cda735244c3d43eU, 0x3a0888136afa64a7U, 0x088aaa1845b8fdd0U,\n    0x8aad549e57273d45U, 0x36ac54e2f678864bU, 0x84576a1bb416a7ddU,\n    0x656d44a2a11c51d5U, 0x9f644ae5a4b1b325U, 0x873d5d9f0dde1feeU,\n    0xa90cb506d155a7eaU, 0x09a7f12442d588f2U, 0x0c11ed6d538aeb2fU,\n    0x8f1668c8a86da5faU, 0xf96e017d694487bcU, 0x37c981dcc395a9acU,\n    0x85bbe253f47b1417U, 0x93956d7478ccec8eU, 0x387ac8d1970027b2U,\n    0x06997b05fcc0319eU, 0x441fece3bdf81f03U, 0xd527e81cad7626c3U,\n    0x8a71e223d8d3b074U, 0xf6872d5667844e49U, 0xb428f8ac016561dbU,\n    0xe13336d701beba52U, 0xecc0024661173473U, 0x27f002d7f95d0190U,\n    0x31ec038df7b441f4U, 0x7e67047175a15271U, 0x0f0062c6e984d386U,\n    0x52c07b78a3e60868U, 0xa7709a56ccdf8a82U, 0x88a66076400bb691U,\n    0x6acff893d00ea435U, 0x0583f6b8c4124d43U, 0xc3727a337a8b704aU,\n    0x744f18c0592e4c5cU, 0x1162def06f79df73U, 0x8addcb5645ac2ba8U,\n    0x6d953e2bd7173692U, 0xc8fa8db6ccdd0437U, 0x1d9c9892400a22a2U,\n    0x2503beb6d00cab4bU, 0x2e44ae64840fd61dU, 0x5ceaecfed289e5d2U,\n    0x7425a83e872c5f47U, 0xd12f124e28f77719U, 0x82bd6b70d99aaa6fU,\n    0x636cc64d1001550bU, 0x3c47f7e05401aa4eU, 0x65acfaec34810a71U,\n    0x7f1839a741a14d0dU, 0x1ede48111209a050U, 0x934aed0aab460432U,\n    0xf81da84d5617853fU, 0x36251260ab9d668eU, 0xc1d72b7c6b426019U,\n    0xb24cf65b8612f81fU, 0xdee033f26797b627U, 0x169840ef017da3b1U,\n    0x8e1f289560ee864eU, 0xf1a6f2bab92a27e2U, 0xae10af696774b1dbU,\n    0xacca6da1e0a8ef29U, 0x17fd090a58d32af3U, 0xddfc4b4cef07f5b0U,\n    0x4abdaf101564f98eU, 0x9d6d1ad41abe37f1U, 0x84c86189216dc5edU,\n    0x32fd3cf5b4e49bb4U, 0x3fbc8c33221dc2a1U, 0x0fabaf3feaa5334aU,\n    0x29cb4d87f2a7400eU, 0x743e20e9ef511012U, 0x914da9246b255416U,\n    0x1ad089b6c2f7548eU, 0xa184ac2473b529b1U, 0xc9e5d72d90a2741eU,\n    0x7e2fa67c7a658892U, 0xddbb901b98feeab7U, 0x552a74227f3ea565U,\n    0xd53a88958f87275fU, 0x8a892abaf368f137U, 0x2d2b7569b0432d85U,\n    0x9c3b29620e29fc73U, 0x8349f3ba91b47b8fU, 0x241c70a936219a73U,\n    0xed238cd383aa0110U, 0xf4363804324a40aaU, 0xb143c6053edcd0d5U,\n    0xdd94b7868e94050aU, 0xca7cf2b4191c8326U, 0xfd1c2f611f63a3f0U,\n    0xbc633b39673c8cecU, 0xd5be0503e085d813U, 0x4b2d8644d8a74e18U,\n    0xddf8e7d60ed1219eU, 0xcabb90e5c942b503U, 0x3d6a751f3b936243U,\n    0x0cc512670a783ad4U, 0x27fb2b80668b24c5U, 0xb1f9f660802dedf6U,\n    0x5e7873f8a0396973U, 0xdb0b487b6423e1e8U, 0x91ce1a9a3d2cda62U,\n    0x7641a140cc7810fbU, 0xa9e904c87fcb0a9dU, 0x546345fa9fbdcd44U,\n    0xa97c177947ad4095U, 0x49ed8eabcccc485dU, 0x5c68f256bfff5a74U,\n    0x73832eec6fff3111U, 0xc831fd53c5ff7eabU, 0xba3e7ca8b77f5e55U,\n    0x28ce1bd2e55f35ebU, 0x7980d163cf5b81b3U, 0xd7e105bcc332621fU,\n    0x8dd9472bf3fefaa7U, 0xb14f98f6f0feb951U, 0x6ed1bf9a569f33d3U,\n    0x0a862f80ec4700c8U, 0xcd27bb612758c0faU, 0x8038d51cb897789cU,\n    0xe0470a63e6bd56c3U, 0x1858ccfce06cac74U, 0x0f37801e0c43ebc8U,\n    0xd30560258f54e6baU, 0x47c6b82ef32a2069U, 0x4cdc331d57fa5441U,\n    0xe0133fe4adf8e952U, 0x58180fddd97723a6U, 0x570f09eaa7ea7648U,\n};\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/charconv.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_CHARCONV_H_\n#define ABSL_STRINGS_CHARCONV_H_\n\n#include <system_error>  // NOLINT(build/c++11)\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Workalike compatibility version of std::chars_format from C++17.\n//\n// This is an bitfield enumerator which can be passed to absl::from_chars to\n// configure the string-to-float conversion.\nenum class chars_format {\n  scientific = 1,\n  fixed = 2,\n  hex = 4,\n  general = fixed | scientific,\n};\n\n// The return result of a string-to-number conversion.\n//\n// `ec` will be set to `invalid_argument` if a well-formed number was not found\n// at the start of the input range, `result_out_of_range` if a well-formed\n// number was found, but it was out of the representable range of the requested\n// type, or to std::errc() otherwise.\n//\n// If a well-formed number was found, `ptr` is set to one past the sequence of\n// characters that were successfully parsed.  If none was found, `ptr` is set\n// to the `first` argument to from_chars.\nstruct from_chars_result {\n  const char* absl_nonnull ptr;\n  std::errc ec;\n};\n\n// Workalike compatibility version of std::from_chars from C++17.  Currently\n// this only supports the `double` and `float` types.\n//\n// This interface incorporates the proposed resolutions for library issues\n// DR 3080 and DR 3081.  If these are adopted with different wording,\n// Abseil's behavior will change to match the standard.  (The behavior most\n// likely to change is for DR 3081, which says what `value` will be set to in\n// the case of overflow and underflow.  Code that wants to avoid possible\n// breaking changes in this area should not depend on `value` when the returned\n// from_chars_result indicates a range error.)\n//\n// Searches the range [first, last) for the longest matching pattern beginning\n// at `first` that represents a floating point number.  If one is found, store\n// the result in `value`.\n//\n// The matching pattern format is almost the same as that of strtod(), except\n// that (1) C locale is not respected, (2) an initial '+' character in the\n// input range will never be matched, and (3) leading whitespaces are not\n// ignored.\n//\n// If `fmt` is set, it must be one of the enumerator values of the chars_format.\n// (This is despite the fact that chars_format is a bitmask type.)  If set to\n// `scientific`, a matching number must contain an exponent.  If set to `fixed`,\n// then an exponent will never match.  (For example, the string \"1e5\" will be\n// parsed as \"1\".)  If set to `hex`, then a hexadecimal float is parsed in the\n// format that strtod() accepts, except that a \"0x\" prefix is NOT matched.\n// (In particular, in `hex` mode, the input \"0xff\" results in the largest\n// matching pattern \"0\".)\nabsl::from_chars_result from_chars(const char* absl_nonnull first,\n                                   const char* absl_nonnull last,\n                                   double& value,  // NOLINT\n                                   chars_format fmt = chars_format::general);\n\nabsl::from_chars_result from_chars(const char* absl_nonnull first,\n                                   const char* absl_nonnull last,\n                                   float& value,  // NOLINT\n                                   chars_format fmt = chars_format::general);\n\n// std::chars_format is specified as a bitmask type, which means the following\n// operations must be provided:\ninline constexpr chars_format operator&(chars_format lhs, chars_format rhs) {\n  return static_cast<chars_format>(static_cast<int>(lhs) &\n                                   static_cast<int>(rhs));\n}\ninline constexpr chars_format operator|(chars_format lhs, chars_format rhs) {\n  return static_cast<chars_format>(static_cast<int>(lhs) |\n                                   static_cast<int>(rhs));\n}\ninline constexpr chars_format operator^(chars_format lhs, chars_format rhs) {\n  return static_cast<chars_format>(static_cast<int>(lhs) ^\n                                   static_cast<int>(rhs));\n}\ninline constexpr chars_format operator~(chars_format arg) {\n  return static_cast<chars_format>(~static_cast<int>(arg));\n}\ninline chars_format& operator&=(chars_format& lhs, chars_format rhs) {\n  lhs = lhs & rhs;\n  return lhs;\n}\ninline chars_format& operator|=(chars_format& lhs, chars_format rhs) {\n  lhs = lhs | rhs;\n  return lhs;\n}\ninline chars_format& operator^=(chars_format& lhs, chars_format rhs) {\n  lhs = lhs ^ rhs;\n  return lhs;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_CHARCONV_H_\n"
  },
  {
    "path": "absl/strings/charconv_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdlib>\n#include <cstring>\n#include <string>\n\n#include \"absl/strings/charconv.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_Strtod_Pi(benchmark::State& state) {\n  const char* pi = \"3.14159\";\n  for (auto s : state) {\n    benchmark::DoNotOptimize(pi);\n    benchmark::DoNotOptimize(strtod(pi, nullptr));\n  }\n}\nBENCHMARK(BM_Strtod_Pi);\n\nvoid BM_Absl_Pi(benchmark::State& state) {\n  const char* pi = \"3.14159\";\n  const char* pi_end = pi + strlen(pi);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(pi);\n    double v;\n    absl::from_chars(pi, pi_end, v);\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_Absl_Pi);\n\nvoid BM_Strtod_Pi_float(benchmark::State& state) {\n  const char* pi = \"3.14159\";\n  for (auto s : state) {\n    benchmark::DoNotOptimize(pi);\n    benchmark::DoNotOptimize(strtof(pi, nullptr));\n  }\n}\nBENCHMARK(BM_Strtod_Pi_float);\n\nvoid BM_Absl_Pi_float(benchmark::State& state) {\n  const char* pi = \"3.14159\";\n  const char* pi_end = pi + strlen(pi);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(pi);\n    float v;\n    absl::from_chars(pi, pi_end, v);\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_Absl_Pi_float);\n\nvoid BM_Strtod_HardLarge(benchmark::State& state) {\n  const char* num = \"272104041512242479.e200\";\n  for (auto s : state) {\n    benchmark::DoNotOptimize(num);\n    benchmark::DoNotOptimize(strtod(num, nullptr));\n  }\n}\nBENCHMARK(BM_Strtod_HardLarge);\n\nvoid BM_Absl_HardLarge(benchmark::State& state) {\n  const char* numstr = \"272104041512242479.e200\";\n  const char* numstr_end = numstr + strlen(numstr);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(numstr);\n    double v;\n    absl::from_chars(numstr, numstr_end, v);\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_Absl_HardLarge);\n\nvoid BM_Strtod_HardSmall(benchmark::State& state) {\n  const char* num = \"94080055902682397.e-242\";\n  for (auto s : state) {\n    benchmark::DoNotOptimize(num);\n    benchmark::DoNotOptimize(strtod(num, nullptr));\n  }\n}\nBENCHMARK(BM_Strtod_HardSmall);\n\nvoid BM_Absl_HardSmall(benchmark::State& state) {\n  const char* numstr = \"94080055902682397.e-242\";\n  const char* numstr_end = numstr + strlen(numstr);\n  for (auto s : state) {\n    benchmark::DoNotOptimize(numstr);\n    double v;\n    absl::from_chars(numstr, numstr_end, v);\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_Absl_HardSmall);\n\nvoid BM_Strtod_HugeMantissa(benchmark::State& state) {\n  std::string huge(200, '3');\n  const char* num = huge.c_str();\n  for (auto s : state) {\n    benchmark::DoNotOptimize(num);\n    benchmark::DoNotOptimize(strtod(num, nullptr));\n  }\n}\nBENCHMARK(BM_Strtod_HugeMantissa);\n\nvoid BM_Absl_HugeMantissa(benchmark::State& state) {\n  std::string huge(200, '3');\n  const char* num = huge.c_str();\n  const char* num_end = num + 200;\n  for (auto s : state) {\n    benchmark::DoNotOptimize(num);\n    double v;\n    absl::from_chars(num, num_end, v);\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_Absl_HugeMantissa);\n\nstd::string MakeHardCase(int length) {\n  // The number 1.1521...e-297 is exactly halfway between 12345 * 2**-1000 and\n  // the next larger representable number.  The digits of this number are in\n  // the string below.\n  const std::string digits =\n      \"1.\"\n      \"152113937042223790993097181572444900347587985074226836242307364987727724\"\n      \"831384300183638649152607195040591791364113930628852279348613864894524591\"\n      \"272746490313676832900762939595690019745859128071117417798540258114233761\"\n      \"012939937017879509401007964861774960297319002612457273148497158989073482\"\n      \"171377406078223015359818300988676687994537274548940612510414856761641652\"\n      \"513434981938564294004070500716200446656421722229202383105446378511678258\"\n      \"370570631774499359748259931676320916632111681001853983492795053244971606\"\n      \"922718923011680846577744433974087653954904214152517799883551075537146316\"\n      \"168973685866425605046988661997658648354773076621610279716804960009043764\"\n      \"038392994055171112475093876476783502487512538082706095923790634572014823\"\n      \"78877699375152587890625\" +\n      std::string(5000, '0');\n  // generate the hard cases on either side for the given length.\n  // Lengths between 3 and 1000 are reasonable.\n  return digits.substr(0, length) + \"1e-297\";\n}\n\nvoid BM_Strtod_Big_And_Difficult(benchmark::State& state) {\n  std::string testcase = MakeHardCase(state.range(0));\n  const char* begin = testcase.c_str();\n  for (auto s : state) {\n    benchmark::DoNotOptimize(begin);\n    benchmark::DoNotOptimize(strtod(begin, nullptr));\n  }\n}\nBENCHMARK(BM_Strtod_Big_And_Difficult)->Range(3, 5000);\n\nvoid BM_Absl_Big_And_Difficult(benchmark::State& state) {\n  std::string testcase = MakeHardCase(state.range(0));\n  const char* begin = testcase.c_str();\n  const char* end = begin + testcase.size();\n  for (auto s : state) {\n    benchmark::DoNotOptimize(begin);\n    double v;\n    absl::from_chars(begin, end, v);\n    benchmark::DoNotOptimize(v);\n  }\n}\nBENCHMARK(BM_Absl_Big_And_Difficult)->Range(3, 5000);\n\n}  // namespace\n\n// ------------------------------------------------------------------------\n// Benchmark                                 Time           CPU Iterations\n// ------------------------------------------------------------------------\n// BM_Strtod_Pi                             96 ns         96 ns    6337454\n// BM_Absl_Pi                               35 ns         35 ns   20031996\n// BM_Strtod_Pi_float                       91 ns         91 ns    7745851\n// BM_Absl_Pi_float                         35 ns         35 ns   20430298\n// BM_Strtod_HardLarge                     133 ns        133 ns    5288341\n// BM_Absl_HardLarge                       181 ns        181 ns    3855615\n// BM_Strtod_HardSmall                     279 ns        279 ns    2517243\n// BM_Absl_HardSmall                       287 ns        287 ns    2458744\n// BM_Strtod_HugeMantissa                  433 ns        433 ns    1604293\n// BM_Absl_HugeMantissa                    160 ns        160 ns    4403671\n// BM_Strtod_Big_And_Difficult/3           236 ns        236 ns    2942496\n// BM_Strtod_Big_And_Difficult/8           232 ns        232 ns    2983796\n// BM_Strtod_Big_And_Difficult/64          437 ns        437 ns    1591951\n// BM_Strtod_Big_And_Difficult/512        1738 ns       1738 ns     402519\n// BM_Strtod_Big_And_Difficult/4096       3943 ns       3943 ns     176128\n// BM_Strtod_Big_And_Difficult/5000       4397 ns       4397 ns     157878\n// BM_Absl_Big_And_Difficult/3              39 ns         39 ns   17799583\n// BM_Absl_Big_And_Difficult/8              43 ns         43 ns   16096859\n// BM_Absl_Big_And_Difficult/64            550 ns        550 ns    1259717\n// BM_Absl_Big_And_Difficult/512          4167 ns       4167 ns     171414\n// BM_Absl_Big_And_Difficult/4096         9160 ns       9159 ns      76297\n// BM_Absl_Big_And_Difficult/5000         9738 ns       9738 ns      70140\n"
  },
  {
    "path": "absl/strings/charconv_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/charconv.h\"\n\n#include <cfloat>\n#include <cmath>\n#include <cstdlib>\n#include <functional>\n#include <limits>\n#include <string>\n#include <system_error>  // NOLINT(build/c++11)\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/internal/pow10_helper.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef _MSC_FULL_VER\n#define ABSL_COMPILER_DOES_EXACT_ROUNDING 0\n#define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 0\n#else\n#define ABSL_COMPILER_DOES_EXACT_ROUNDING 1\n#define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 1\n#endif\n\nnamespace {\n\nusing absl::strings_internal::Pow10;\n\n#if ABSL_COMPILER_DOES_EXACT_ROUNDING\n\n// Tests that the given string is accepted by absl::from_chars, and that it\n// converts exactly equal to the given number.\nvoid TestDoubleParse(absl::string_view str, double expected_number) {\n  SCOPED_TRACE(str);\n  double actual_number = 0.0;\n  absl::from_chars_result result =\n      absl::from_chars(str.data(), str.data() + str.length(), actual_number);\n  EXPECT_EQ(result.ec, std::errc());\n  EXPECT_EQ(result.ptr, str.data() + str.length());\n  EXPECT_EQ(actual_number, expected_number);\n}\n\nvoid TestFloatParse(absl::string_view str, float expected_number) {\n  SCOPED_TRACE(str);\n  float actual_number = 0.0;\n  absl::from_chars_result result =\n      absl::from_chars(str.data(), str.data() + str.length(), actual_number);\n  EXPECT_EQ(result.ec, std::errc());\n  EXPECT_EQ(result.ptr, str.data() + str.length());\n  EXPECT_EQ(actual_number, expected_number);\n}\n\n// Tests that the given double or single precision floating point literal is\n// parsed correctly by absl::from_chars.\n//\n// These convenience macros assume that the C++ compiler being used also does\n// fully correct decimal-to-binary conversions.\n#define FROM_CHARS_TEST_DOUBLE(number)     \\\n  {                                        \\\n    TestDoubleParse(#number, number);      \\\n    TestDoubleParse(\"-\" #number, -number); \\\n  }\n\n#define FROM_CHARS_TEST_FLOAT(number)        \\\n  {                                          \\\n    TestFloatParse(#number, number##f);      \\\n    TestFloatParse(\"-\" #number, -number##f); \\\n  }\n\nTEST(FromChars, NearRoundingCases) {\n  // Cases from \"A Program for Testing IEEE Decimal-Binary Conversion\"\n  // by Vern Paxson.\n\n  // Forms that should round towards zero.  (These are the hardest cases for\n  // each decimal mantissa size.)\n  FROM_CHARS_TEST_DOUBLE(5.e125);\n  FROM_CHARS_TEST_DOUBLE(69.e267);\n  FROM_CHARS_TEST_DOUBLE(999.e-026);\n  FROM_CHARS_TEST_DOUBLE(7861.e-034);\n  FROM_CHARS_TEST_DOUBLE(75569.e-254);\n  FROM_CHARS_TEST_DOUBLE(928609.e-261);\n  FROM_CHARS_TEST_DOUBLE(9210917.e080);\n  FROM_CHARS_TEST_DOUBLE(84863171.e114);\n  FROM_CHARS_TEST_DOUBLE(653777767.e273);\n  FROM_CHARS_TEST_DOUBLE(5232604057.e-298);\n  FROM_CHARS_TEST_DOUBLE(27235667517.e-109);\n  FROM_CHARS_TEST_DOUBLE(653532977297.e-123);\n  FROM_CHARS_TEST_DOUBLE(3142213164987.e-294);\n  FROM_CHARS_TEST_DOUBLE(46202199371337.e-072);\n  FROM_CHARS_TEST_DOUBLE(231010996856685.e-073);\n  FROM_CHARS_TEST_DOUBLE(9324754620109615.e212);\n  FROM_CHARS_TEST_DOUBLE(78459735791271921.e049);\n  FROM_CHARS_TEST_DOUBLE(272104041512242479.e200);\n  FROM_CHARS_TEST_DOUBLE(6802601037806061975.e198);\n  FROM_CHARS_TEST_DOUBLE(20505426358836677347.e-221);\n  FROM_CHARS_TEST_DOUBLE(836168422905420598437.e-234);\n  FROM_CHARS_TEST_DOUBLE(4891559871276714924261.e222);\n  FROM_CHARS_TEST_FLOAT(5.e-20);\n  FROM_CHARS_TEST_FLOAT(67.e14);\n  FROM_CHARS_TEST_FLOAT(985.e15);\n  FROM_CHARS_TEST_FLOAT(7693.e-42);\n  FROM_CHARS_TEST_FLOAT(55895.e-16);\n  FROM_CHARS_TEST_FLOAT(996622.e-44);\n  FROM_CHARS_TEST_FLOAT(7038531.e-32);\n  FROM_CHARS_TEST_FLOAT(60419369.e-46);\n  FROM_CHARS_TEST_FLOAT(702990899.e-20);\n  FROM_CHARS_TEST_FLOAT(6930161142.e-48);\n  FROM_CHARS_TEST_FLOAT(25933168707.e-13);\n  FROM_CHARS_TEST_FLOAT(596428896559.e20);\n\n  // Similarly, forms that should round away from zero.\n  FROM_CHARS_TEST_DOUBLE(9.e-265);\n  FROM_CHARS_TEST_DOUBLE(85.e-037);\n  FROM_CHARS_TEST_DOUBLE(623.e100);\n  FROM_CHARS_TEST_DOUBLE(3571.e263);\n  FROM_CHARS_TEST_DOUBLE(81661.e153);\n  FROM_CHARS_TEST_DOUBLE(920657.e-023);\n  FROM_CHARS_TEST_DOUBLE(4603285.e-024);\n  FROM_CHARS_TEST_DOUBLE(87575437.e-309);\n  FROM_CHARS_TEST_DOUBLE(245540327.e122);\n  FROM_CHARS_TEST_DOUBLE(6138508175.e120);\n  FROM_CHARS_TEST_DOUBLE(83356057653.e193);\n  FROM_CHARS_TEST_DOUBLE(619534293513.e124);\n  FROM_CHARS_TEST_DOUBLE(2335141086879.e218);\n  FROM_CHARS_TEST_DOUBLE(36167929443327.e-159);\n  FROM_CHARS_TEST_DOUBLE(609610927149051.e-255);\n  FROM_CHARS_TEST_DOUBLE(3743626360493413.e-165);\n  FROM_CHARS_TEST_DOUBLE(94080055902682397.e-242);\n  FROM_CHARS_TEST_DOUBLE(899810892172646163.e283);\n  FROM_CHARS_TEST_DOUBLE(7120190517612959703.e120);\n  FROM_CHARS_TEST_DOUBLE(25188282901709339043.e-252);\n  FROM_CHARS_TEST_DOUBLE(308984926168550152811.e-052);\n  FROM_CHARS_TEST_DOUBLE(6372891218502368041059.e064);\n  FROM_CHARS_TEST_FLOAT(3.e-23);\n  FROM_CHARS_TEST_FLOAT(57.e18);\n  FROM_CHARS_TEST_FLOAT(789.e-35);\n  FROM_CHARS_TEST_FLOAT(2539.e-18);\n  FROM_CHARS_TEST_FLOAT(76173.e28);\n  FROM_CHARS_TEST_FLOAT(887745.e-11);\n  FROM_CHARS_TEST_FLOAT(5382571.e-37);\n  FROM_CHARS_TEST_FLOAT(82381273.e-35);\n  FROM_CHARS_TEST_FLOAT(750486563.e-38);\n  FROM_CHARS_TEST_FLOAT(3752432815.e-39);\n  FROM_CHARS_TEST_FLOAT(75224575729.e-45);\n  FROM_CHARS_TEST_FLOAT(459926601011.e15);\n}\n\n#undef FROM_CHARS_TEST_DOUBLE\n#undef FROM_CHARS_TEST_FLOAT\n#endif\n\nfloat ToFloat(absl::string_view s) {\n  float f;\n  absl::from_chars(s.data(), s.data() + s.size(), f);\n  return f;\n}\n\ndouble ToDouble(absl::string_view s) {\n  double d;\n  absl::from_chars(s.data(), s.data() + s.size(), d);\n  return d;\n}\n\n// A duplication of the test cases in \"NearRoundingCases\" above, but with\n// expected values expressed with integers, using ldexp/ldexpf.  These test\n// cases will work even on compilers that do not accurately round floating point\n// literals.\nTEST(FromChars, NearRoundingCasesExplicit) {\n  EXPECT_EQ(ToDouble(\"5.e125\"), ldexp(6653062250012735, 365));\n  EXPECT_EQ(ToDouble(\"69.e267\"), ldexp(4705683757438170, 841));\n  EXPECT_EQ(ToDouble(\"999.e-026\"), ldexp(6798841691080350, -129));\n  EXPECT_EQ(ToDouble(\"7861.e-034\"), ldexp(8975675289889240, -153));\n  EXPECT_EQ(ToDouble(\"75569.e-254\"), ldexp(6091718967192243, -880));\n  EXPECT_EQ(ToDouble(\"928609.e-261\"), ldexp(7849264900213743, -900));\n  EXPECT_EQ(ToDouble(\"9210917.e080\"), ldexp(8341110837370930, 236));\n  EXPECT_EQ(ToDouble(\"84863171.e114\"), ldexp(4625202867375927, 353));\n  EXPECT_EQ(ToDouble(\"653777767.e273\"), ldexp(5068902999763073, 884));\n  EXPECT_EQ(ToDouble(\"5232604057.e-298\"), ldexp(5741343011915040, -1010));\n  EXPECT_EQ(ToDouble(\"27235667517.e-109\"), ldexp(6707124626673586, -380));\n  EXPECT_EQ(ToDouble(\"653532977297.e-123\"), ldexp(7078246407265384, -422));\n  EXPECT_EQ(ToDouble(\"3142213164987.e-294\"), ldexp(8219991337640559, -988));\n  EXPECT_EQ(ToDouble(\"46202199371337.e-072\"), ldexp(5224462102115359, -246));\n  EXPECT_EQ(ToDouble(\"231010996856685.e-073\"), ldexp(5224462102115359, -247));\n  EXPECT_EQ(ToDouble(\"9324754620109615.e212\"), ldexp(5539753864394442, 705));\n  EXPECT_EQ(ToDouble(\"78459735791271921.e049\"), ldexp(8388176519442766, 166));\n  EXPECT_EQ(ToDouble(\"272104041512242479.e200\"), ldexp(5554409530847367, 670));\n  EXPECT_EQ(ToDouble(\"6802601037806061975.e198\"), ldexp(5554409530847367, 668));\n  EXPECT_EQ(ToDouble(\"20505426358836677347.e-221\"),\n            ldexp(4524032052079546, -722));\n  EXPECT_EQ(ToDouble(\"836168422905420598437.e-234\"),\n            ldexp(5070963299887562, -760));\n  EXPECT_EQ(ToDouble(\"4891559871276714924261.e222\"),\n            ldexp(6452687840519111, 757));\n  EXPECT_EQ(ToFloat(\"5.e-20\"), ldexpf(15474250, -88));\n  EXPECT_EQ(ToFloat(\"67.e14\"), ldexpf(12479722, 29));\n  EXPECT_EQ(ToFloat(\"985.e15\"), ldexpf(14333636, 36));\n  EXPECT_EQ(ToFloat(\"7693.e-42\"), ldexpf(10979816, -150));\n  EXPECT_EQ(ToFloat(\"55895.e-16\"), ldexpf(12888509, -61));\n  EXPECT_EQ(ToFloat(\"996622.e-44\"), ldexpf(14224264, -150));\n  EXPECT_EQ(ToFloat(\"7038531.e-32\"), ldexpf(11420669, -107));\n  EXPECT_EQ(ToFloat(\"60419369.e-46\"), ldexpf(8623340, -150));\n  EXPECT_EQ(ToFloat(\"702990899.e-20\"), ldexpf(16209866, -61));\n  EXPECT_EQ(ToFloat(\"6930161142.e-48\"), ldexpf(9891056, -150));\n  EXPECT_EQ(ToFloat(\"25933168707.e-13\"), ldexpf(11138211, -32));\n  EXPECT_EQ(ToFloat(\"596428896559.e20\"), ldexpf(12333860, 82));\n\n\n  EXPECT_EQ(ToDouble(\"9.e-265\"), ldexp(8168427841980010, -930));\n  EXPECT_EQ(ToDouble(\"85.e-037\"), ldexp(6360455125664090, -169));\n  EXPECT_EQ(ToDouble(\"623.e100\"), ldexp(6263531988747231, 289));\n  EXPECT_EQ(ToDouble(\"3571.e263\"), ldexp(6234526311072170, 833));\n  EXPECT_EQ(ToDouble(\"81661.e153\"), ldexp(6696636728760206, 472));\n  EXPECT_EQ(ToDouble(\"920657.e-023\"), ldexp(5975405561110124, -109));\n  EXPECT_EQ(ToDouble(\"4603285.e-024\"), ldexp(5975405561110124, -110));\n  EXPECT_EQ(ToDouble(\"87575437.e-309\"), ldexp(8452160731874668, -1053));\n  EXPECT_EQ(ToDouble(\"245540327.e122\"), ldexp(4985336549131723, 381));\n  EXPECT_EQ(ToDouble(\"6138508175.e120\"), ldexp(4985336549131723, 379));\n  EXPECT_EQ(ToDouble(\"83356057653.e193\"), ldexp(5986732817132056, 625));\n  EXPECT_EQ(ToDouble(\"619534293513.e124\"), ldexp(4798406992060657, 399));\n  EXPECT_EQ(ToDouble(\"2335141086879.e218\"), ldexp(5419088166961646, 713));\n  EXPECT_EQ(ToDouble(\"36167929443327.e-159\"), ldexp(8135819834632444, -536));\n  EXPECT_EQ(ToDouble(\"609610927149051.e-255\"), ldexp(4576664294594737, -850));\n  EXPECT_EQ(ToDouble(\"3743626360493413.e-165\"), ldexp(6898586531774201, -549));\n  EXPECT_EQ(ToDouble(\"94080055902682397.e-242\"), ldexp(6273271706052298, -800));\n  EXPECT_EQ(ToDouble(\"899810892172646163.e283\"), ldexp(7563892574477827, 947));\n  EXPECT_EQ(ToDouble(\"7120190517612959703.e120\"), ldexp(5385467232557565, 409));\n  EXPECT_EQ(ToDouble(\"25188282901709339043.e-252\"),\n            ldexp(5635662608542340, -825));\n  EXPECT_EQ(ToDouble(\"308984926168550152811.e-052\"),\n            ldexp(5644774693823803, -157));\n  EXPECT_EQ(ToDouble(\"6372891218502368041059.e064\"),\n            ldexp(4616868614322430, 233));\n\n  EXPECT_EQ(ToFloat(\"3.e-23\"), ldexpf(9507380, -98));\n  EXPECT_EQ(ToFloat(\"57.e18\"), ldexpf(12960300, 42));\n  EXPECT_EQ(ToFloat(\"789.e-35\"), ldexpf(10739312, -130));\n  EXPECT_EQ(ToFloat(\"2539.e-18\"), ldexpf(11990089, -72));\n  EXPECT_EQ(ToFloat(\"76173.e28\"), ldexpf(9845130, 86));\n  EXPECT_EQ(ToFloat(\"887745.e-11\"), ldexpf(9760860, -40));\n  EXPECT_EQ(ToFloat(\"5382571.e-37\"), ldexpf(11447463, -124));\n  EXPECT_EQ(ToFloat(\"82381273.e-35\"), ldexpf(8554961, -113));\n  EXPECT_EQ(ToFloat(\"750486563.e-38\"), ldexpf(9975678, -120));\n  EXPECT_EQ(ToFloat(\"3752432815.e-39\"), ldexpf(9975678, -121));\n  EXPECT_EQ(ToFloat(\"75224575729.e-45\"), ldexpf(13105970, -137));\n  EXPECT_EQ(ToFloat(\"459926601011.e15\"), ldexpf(12466336, 65));\n}\n\n// Common test logic for converting a string which lies exactly halfway between\n// two target floats.\n//\n// mantissa and exponent represent the precise value between two floating point\n// numbers, `expected_low` and `expected_high`.  The floating point\n// representation to parse in `StrCat(mantissa, \"e\", exponent)`.\n//\n// This function checks that an input just slightly less than the exact value\n// is rounded down to `expected_low`, and an input just slightly greater than\n// the exact value is rounded up to `expected_high`.\n//\n// The exact value should round to `expected_half`, which must be either\n// `expected_low` or `expected_high`.\ntemplate <typename FloatType>\nvoid TestHalfwayValue(const std::string& mantissa, int exponent,\n                      FloatType expected_low, FloatType expected_high,\n                      FloatType expected_half) {\n  std::string low_rep = mantissa;\n  low_rep[low_rep.size() - 1] -= 1;\n  absl::StrAppend(&low_rep, std::string(1000, '9'), \"e\", exponent);\n\n  FloatType actual_low = 0;\n  absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low);\n  EXPECT_EQ(expected_low, actual_low);\n\n  std::string high_rep =\n      absl::StrCat(mantissa, std::string(1000, '0'), \"1e\", exponent);\n  FloatType actual_high = 0;\n  absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(),\n                   actual_high);\n  EXPECT_EQ(expected_high, actual_high);\n\n  std::string halfway_rep = absl::StrCat(mantissa, \"e\", exponent);\n  FloatType actual_half = 0;\n  absl::from_chars(halfway_rep.data(), halfway_rep.data() + halfway_rep.size(),\n                   actual_half);\n  EXPECT_EQ(expected_half, actual_half);\n}\n\nTEST(FromChars, DoubleRounding) {\n  const double zero = 0.0;\n  const double first_subnormal = nextafter(zero, 1.0);\n  const double second_subnormal = nextafter(first_subnormal, 1.0);\n\n  const double first_normal = DBL_MIN;\n  const double last_subnormal = nextafter(first_normal, 0.0);\n  const double second_normal = nextafter(first_normal, 1.0);\n\n  const double last_normal = DBL_MAX;\n  const double penultimate_normal = nextafter(last_normal, 0.0);\n\n  // Various test cases for numbers between two representable floats.  Each\n  // call to TestHalfwayValue tests a number just below and just above the\n  // halfway point, as well as the number exactly between them.\n\n  // Test between zero and first_subnormal.  Round-to-even tie rounds down.\n  TestHalfwayValue(\n      \"2.\"\n      \"470328229206232720882843964341106861825299013071623822127928412503377536\"\n      \"351043759326499181808179961898982823477228588654633283551779698981993873\"\n      \"980053909390631503565951557022639229085839244910518443593180284993653615\"\n      \"250031937045767824921936562366986365848075700158576926990370631192827955\"\n      \"855133292783433840935197801553124659726357957462276646527282722005637400\"\n      \"648549997709659947045402082816622623785739345073633900796776193057750674\"\n      \"017632467360096895134053553745851666113422376667860416215968046191446729\"\n      \"184030053005753084904876539171138659164623952491262365388187963623937328\"\n      \"042389101867234849766823508986338858792562830275599565752445550725518931\"\n      \"369083625477918694866799496832404970582102851318545139621383772282614543\"\n      \"7693412532098591327667236328125\",\n      -324, zero, first_subnormal, zero);\n\n  // first_subnormal and second_subnormal.  Round-to-even tie rounds up.\n  TestHalfwayValue(\n      \"7.\"\n      \"410984687618698162648531893023320585475897039214871466383785237510132609\"\n      \"053131277979497545424539885696948470431685765963899850655339096945981621\"\n      \"940161728171894510697854671067917687257517734731555330779540854980960845\"\n      \"750095811137303474765809687100959097544227100475730780971111893578483867\"\n      \"565399878350301522805593404659373979179073872386829939581848166016912201\"\n      \"945649993128979841136206248449867871357218035220901702390328579173252022\"\n      \"052897402080290685402160661237554998340267130003581248647904138574340187\"\n      \"552090159017259254714629617513415977493871857473787096164563890871811984\"\n      \"127167305601704549300470526959016576377688490826798697257336652176556794\"\n      \"107250876433756084600398490497214911746308553955635418864151316847843631\"\n      \"3080237596295773983001708984375\",\n      -324, first_subnormal, second_subnormal, second_subnormal);\n\n  // last_subnormal and first_normal.  Round-to-even tie rounds up.\n  TestHalfwayValue(\n      \"2.\"\n      \"225073858507201136057409796709131975934819546351645648023426109724822222\"\n      \"021076945516529523908135087914149158913039621106870086438694594645527657\"\n      \"207407820621743379988141063267329253552286881372149012981122451451889849\"\n      \"057222307285255133155755015914397476397983411801999323962548289017107081\"\n      \"850690630666655994938275772572015763062690663332647565300009245888316433\"\n      \"037779791869612049497390377829704905051080609940730262937128958950003583\"\n      \"799967207254304360284078895771796150945516748243471030702609144621572289\"\n      \"880258182545180325707018860872113128079512233426288368622321503775666622\"\n      \"503982534335974568884423900265498198385487948292206894721689831099698365\"\n      \"846814022854243330660339850886445804001034933970427567186443383770486037\"\n      \"86162277173854562306587467901408672332763671875\",\n      -308, last_subnormal, first_normal, first_normal);\n\n  // first_normal and second_normal.  Round-to-even tie rounds down.\n  TestHalfwayValue(\n      \"2.\"\n      \"225073858507201630123055637955676152503612414573018013083228724049586647\"\n      \"606759446192036794116886953213985520549032000903434781884412325572184367\"\n      \"563347617020518175998922941393629966742598285899994830148971433555578567\"\n      \"693279306015978183162142425067962460785295885199272493577688320732492479\"\n      \"924816869232247165964934329258783950102250973957579510571600738343645738\"\n      \"494324192997092179207389919761694314131497173265255020084997973676783743\"\n      \"155205818804439163810572367791175177756227497413804253387084478193655533\"\n      \"073867420834526162513029462022730109054820067654020201547112002028139700\"\n      \"141575259123440177362244273712468151750189745559978653234255886219611516\"\n      \"335924167958029604477064946470184777360934300451421683607013647479513962\"\n      \"13837722826145437693412532098591327667236328125\",\n      -308, first_normal, second_normal, first_normal);\n\n  // penultimate_normal and last_normal.  Round-to-even rounds down.\n  TestHalfwayValue(\n      \"1.\"\n      \"797693134862315608353258760581052985162070023416521662616611746258695532\"\n      \"672923265745300992879465492467506314903358770175220871059269879629062776\"\n      \"047355692132901909191523941804762171253349609463563872612866401980290377\"\n      \"995141836029815117562837277714038305214839639239356331336428021390916694\"\n      \"57927874464075218944\",\n      308, penultimate_normal, last_normal, penultimate_normal);\n}\n\n// Same test cases as DoubleRounding, now with new and improved Much Smaller\n// Precision!\nTEST(FromChars, FloatRounding) {\n  const float zero = 0.0;\n  const float first_subnormal = nextafterf(zero, 1.0);\n  const float second_subnormal = nextafterf(first_subnormal, 1.0);\n\n  const float first_normal = FLT_MIN;\n  const float last_subnormal = nextafterf(first_normal, 0.0);\n  const float second_normal = nextafterf(first_normal, 1.0);\n\n  const float last_normal = FLT_MAX;\n  const float penultimate_normal = nextafterf(last_normal, 0.0);\n\n  // Test between zero and first_subnormal.  Round-to-even tie rounds down.\n  TestHalfwayValue(\n      \"7.\"\n      \"006492321624085354618647916449580656401309709382578858785341419448955413\"\n      \"42930300743319094181060791015625\",\n      -46, zero, first_subnormal, zero);\n\n  // first_subnormal and second_subnormal.  Round-to-even tie rounds up.\n  TestHalfwayValue(\n      \"2.\"\n      \"101947696487225606385594374934874196920392912814773657635602425834686624\"\n      \"028790902229957282543182373046875\",\n      -45, first_subnormal, second_subnormal, second_subnormal);\n\n  // last_subnormal and first_normal.  Round-to-even tie rounds up.\n  TestHalfwayValue(\n      \"1.\"\n      \"175494280757364291727882991035766513322858992758990427682963118425003064\"\n      \"9651730385585324256680905818939208984375\",\n      -38, last_subnormal, first_normal, first_normal);\n\n  // first_normal and second_normal.  Round-to-even tie rounds down.\n  TestHalfwayValue(\n      \"1.\"\n      \"175494420887210724209590083408724842314472120785184615334540294131831453\"\n      \"9442813071445925743319094181060791015625\",\n      -38, first_normal, second_normal, first_normal);\n\n  // penultimate_normal and last_normal.  Round-to-even rounds down.\n  TestHalfwayValue(\"3.40282336497324057985868971510891282432\", 38,\n                   penultimate_normal, last_normal, penultimate_normal);\n}\n\nTEST(FromChars, Underflow) {\n  // Check that underflow is handled correctly, according to the specification\n  // in DR 3081.\n  double d;\n  float f;\n  absl::from_chars_result result;\n\n  std::string negative_underflow = \"-1e-1000\";\n  const char* begin = negative_underflow.data();\n  const char* end = begin + negative_underflow.size();\n  d = 100.0;\n  result = absl::from_chars(begin, end, d);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_TRUE(std::signbit(d));  // negative\n  EXPECT_GE(d, -std::numeric_limits<double>::min());\n  f = 100.0;\n  result = absl::from_chars(begin, end, f);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_TRUE(std::signbit(f));  // negative\n  EXPECT_GE(f, -std::numeric_limits<float>::min());\n\n  std::string positive_underflow = \"1e-1000\";\n  begin = positive_underflow.data();\n  end = begin + positive_underflow.size();\n  d = -100.0;\n  result = absl::from_chars(begin, end, d);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_FALSE(std::signbit(d));  // positive\n  EXPECT_LE(d, std::numeric_limits<double>::min());\n  f = -100.0;\n  result = absl::from_chars(begin, end, f);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_FALSE(std::signbit(f));  // positive\n  EXPECT_LE(f, std::numeric_limits<float>::min());\n}\n\nTEST(FromChars, Overflow) {\n  // Check that overflow is handled correctly, according to the specification\n  // in DR 3081.\n  double d;\n  float f;\n  absl::from_chars_result result;\n\n  std::string negative_overflow = \"-1e1000\";\n  const char* begin = negative_overflow.data();\n  const char* end = begin + negative_overflow.size();\n  d = 100.0;\n  result = absl::from_chars(begin, end, d);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_TRUE(std::signbit(d));  // negative\n  EXPECT_EQ(d, -std::numeric_limits<double>::max());\n  f = 100.0;\n  result = absl::from_chars(begin, end, f);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_TRUE(std::signbit(f));  // negative\n  EXPECT_EQ(f, -std::numeric_limits<float>::max());\n\n  std::string positive_overflow = \"1e1000\";\n  begin = positive_overflow.data();\n  end = begin + positive_overflow.size();\n  d = -100.0;\n  result = absl::from_chars(begin, end, d);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_FALSE(std::signbit(d));  // positive\n  EXPECT_EQ(d, std::numeric_limits<double>::max());\n  f = -100.0;\n  result = absl::from_chars(begin, end, f);\n  EXPECT_EQ(result.ptr, end);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_FALSE(std::signbit(f));  // positive\n  EXPECT_EQ(f, std::numeric_limits<float>::max());\n}\n\nTEST(FromChars, RegressionTestsFromFuzzer) {\n  absl::string_view src = \"0x21900000p00000000099\";\n  float f;\n  auto result = absl::from_chars(src.data(), src.data() + src.size(), f);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n}\n\nTEST(FromChars, ReturnValuePtr) {\n  // Check that `ptr` points one past the number scanned, even if that number\n  // is not representable.\n  double d;\n  absl::from_chars_result result;\n\n  std::string normal = \"3.14@#$%@#$%\";\n  result = absl::from_chars(normal.data(), normal.data() + normal.size(), d);\n  EXPECT_EQ(result.ec, std::errc());\n  EXPECT_EQ(result.ptr - normal.data(), 4);\n\n  std::string overflow = \"1e1000@#$%@#$%\";\n  result = absl::from_chars(overflow.data(),\n                            overflow.data() + overflow.size(), d);\n  EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n  EXPECT_EQ(result.ptr - overflow.data(), 6);\n\n  std::string garbage = \"#$%@#$%\";\n  result = absl::from_chars(garbage.data(),\n                            garbage.data() + garbage.size(), d);\n  EXPECT_EQ(result.ec, std::errc::invalid_argument);\n  EXPECT_EQ(result.ptr - garbage.data(), 0);\n}\n\n// Check for a wide range of inputs that strtod() and absl::from_chars() exactly\n// agree on the conversion amount.\n//\n// This test assumes the platform's strtod() uses perfect round_to_nearest\n// rounding.\nTEST(FromChars, TestVersusStrtod) {\n  for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) {\n    for (int exponent = -300; exponent < 300; ++exponent) {\n      std::string candidate = absl::StrCat(mantissa, \"e\", exponent);\n      double strtod_value = strtod(candidate.c_str(), nullptr);\n      double absl_value = 0;\n      absl::from_chars(candidate.data(), candidate.data() + candidate.size(),\n                       absl_value);\n      ASSERT_EQ(strtod_value, absl_value) << candidate;\n    }\n  }\n}\n\n// Check for a wide range of inputs that strtof() and absl::from_chars() exactly\n// agree on the conversion amount.\n//\n// This test assumes the platform's strtof() uses perfect round_to_nearest\n// rounding.\nTEST(FromChars, TestVersusStrtof) {\n  for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) {\n    for (int exponent = -43; exponent < 32; ++exponent) {\n      std::string candidate = absl::StrCat(mantissa, \"e\", exponent);\n      float strtod_value = strtof(candidate.c_str(), nullptr);\n      float absl_value = 0;\n      absl::from_chars(candidate.data(), candidate.data() + candidate.size(),\n                       absl_value);\n      ASSERT_EQ(strtod_value, absl_value) << candidate;\n    }\n  }\n}\n\n// Tests if two floating point values have identical bit layouts.  (EXPECT_EQ\n// is not suitable for NaN testing, since NaNs are never equal.)\ntemplate <typename Float>\nbool Identical(Float a, Float b) {\n  return 0 == memcmp(&a, &b, sizeof(Float));\n}\n\n// Check that NaNs are parsed correctly.  The spec requires that\n// std::from_chars on \"NaN(123abc)\" return the same value as std::nan(\"123abc\").\n// How such an n-char-sequence affects the generated NaN is unspecified, so we\n// just test for symmetry with std::nan and strtod here.\n//\n// (In Linux, this parses the value as a number and stuffs that number into the\n// free bits of a quiet NaN.)\nTEST(FromChars, NaNDoubles) {\n  for (std::string n_char_sequence :\n       {\"\", \"1\", \"2\", \"3\", \"fff\", \"FFF\", \"200000\", \"400000\", \"4000000000000\",\n        \"8000000000000\", \"abc123\", \"legal_but_unexpected\",\n        \"99999999999999999999999\", \"_\"}) {\n    std::string input = absl::StrCat(\"nan(\", n_char_sequence, \")\");\n    SCOPED_TRACE(input);\n    double from_chars_double;\n    absl::from_chars(input.data(), input.data() + input.size(),\n                     from_chars_double);\n    double std_nan_double = std::nan(n_char_sequence.c_str());\n    EXPECT_TRUE(Identical(from_chars_double, std_nan_double));\n\n    // Also check that we match strtod()'s behavior.  This test assumes that the\n    // platform has a compliant strtod().\n#if ABSL_STRTOD_HANDLES_NAN_CORRECTLY\n    double strtod_double = strtod(input.c_str(), nullptr);\n    EXPECT_TRUE(Identical(from_chars_double, strtod_double));\n#endif  // ABSL_STRTOD_HANDLES_NAN_CORRECTLY\n\n    // Check that we can parse a negative NaN\n    std::string negative_input = \"-\" + input;\n    double negative_from_chars_double;\n    absl::from_chars(negative_input.data(),\n                     negative_input.data() + negative_input.size(),\n                     negative_from_chars_double);\n    EXPECT_TRUE(std::signbit(negative_from_chars_double));\n    EXPECT_FALSE(Identical(negative_from_chars_double, from_chars_double));\n    from_chars_double = std::copysign(from_chars_double, -1.0);\n    EXPECT_TRUE(Identical(negative_from_chars_double, from_chars_double));\n  }\n}\n\nTEST(FromChars, NaNFloats) {\n  for (std::string n_char_sequence :\n       {\"\", \"1\", \"2\", \"3\", \"fff\", \"FFF\", \"200000\", \"400000\", \"4000000000000\",\n        \"8000000000000\", \"abc123\", \"legal_but_unexpected\",\n        \"99999999999999999999999\", \"_\"}) {\n    std::string input = absl::StrCat(\"nan(\", n_char_sequence, \")\");\n    SCOPED_TRACE(input);\n    float from_chars_float;\n    absl::from_chars(input.data(), input.data() + input.size(),\n                     from_chars_float);\n    float std_nan_float = std::nanf(n_char_sequence.c_str());\n    EXPECT_TRUE(Identical(from_chars_float, std_nan_float));\n\n    // Also check that we match strtof()'s behavior.  This test assumes that the\n    // platform has a compliant strtof().\n#if ABSL_STRTOD_HANDLES_NAN_CORRECTLY\n    float strtof_float = strtof(input.c_str(), nullptr);\n    EXPECT_TRUE(Identical(from_chars_float, strtof_float));\n#endif  // ABSL_STRTOD_HANDLES_NAN_CORRECTLY\n\n    // Check that we can parse a negative NaN\n    std::string negative_input = \"-\" + input;\n    float negative_from_chars_float;\n    absl::from_chars(negative_input.data(),\n                     negative_input.data() + negative_input.size(),\n                     negative_from_chars_float);\n    EXPECT_TRUE(std::signbit(negative_from_chars_float));\n    EXPECT_FALSE(Identical(negative_from_chars_float, from_chars_float));\n    // Use the (float, float) overload of std::copysign to prevent narrowing;\n    // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98251.\n    from_chars_float = std::copysign(from_chars_float, -1.0f);\n    EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float));\n  }\n}\n\n// Returns an integer larger than step.  The values grow exponentially.\nint NextStep(int step) {\n  return step + (step >> 2) + 1;\n}\n\n// Test a conversion on a family of input strings, checking that the calculation\n// is correct for in-bounds values, and that overflow and underflow are done\n// correctly for out-of-bounds values.\n//\n// input_generator maps from an integer index to a string to test.\n// expected_generator maps from an integer index to an expected Float value.\n// from_chars conversion of input_generator(i) should result in\n// expected_generator(i).\n//\n// lower_bound and upper_bound denote the smallest and largest values for which\n// the conversion is expected to succeed.\ntemplate <typename Float>\nvoid TestOverflowAndUnderflow(\n    const std::function<std::string(int)>& input_generator,\n    const std::function<Float(int)>& expected_generator, int lower_bound,\n    int upper_bound) {\n  // test legal values near lower_bound\n  int index, step;\n  for (index = lower_bound, step = 1; index < upper_bound;\n       index += step, step = NextStep(step)) {\n    std::string input = input_generator(index);\n    SCOPED_TRACE(input);\n    Float expected = expected_generator(index);\n    Float actual;\n    auto result =\n        absl::from_chars(input.data(), input.data() + input.size(), actual);\n    EXPECT_EQ(result.ec, std::errc());\n    EXPECT_EQ(expected, actual)\n        << absl::StrFormat(\"%a vs %a\", expected, actual);\n  }\n  // test legal values near upper_bound\n  for (index = upper_bound, step = 1; index > lower_bound;\n       index -= step, step = NextStep(step)) {\n    std::string input = input_generator(index);\n    SCOPED_TRACE(input);\n    Float expected = expected_generator(index);\n    Float actual;\n    auto result =\n        absl::from_chars(input.data(), input.data() + input.size(), actual);\n    EXPECT_EQ(result.ec, std::errc());\n    EXPECT_EQ(expected, actual)\n        << absl::StrFormat(\"%a vs %a\", expected, actual);\n  }\n  // Test underflow values below lower_bound\n  for (index = lower_bound - 1, step = 1; index > -1000000;\n       index -= step, step = NextStep(step)) {\n    std::string input = input_generator(index);\n    SCOPED_TRACE(input);\n    Float actual;\n    auto result =\n        absl::from_chars(input.data(), input.data() + input.size(), actual);\n    EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n    EXPECT_LT(actual, 1.0);  // check for underflow\n  }\n  // Test overflow values above upper_bound\n  for (index = upper_bound + 1, step = 1; index < 1000000;\n       index += step, step = NextStep(step)) {\n    std::string input = input_generator(index);\n    SCOPED_TRACE(input);\n    Float actual;\n    auto result =\n        absl::from_chars(input.data(), input.data() + input.size(), actual);\n    EXPECT_EQ(result.ec, std::errc::result_out_of_range);\n    EXPECT_GT(actual, 1.0);  // check for overflow\n  }\n}\n\n// Check that overflow and underflow are caught correctly for hex doubles.\n//\n// The largest representable double is 0x1.fffffffffffffp+1023, and the\n// smallest representable subnormal is 0x0.0000000000001p-1022, which equals\n// 0x1p-1074.  Therefore 1023 and -1074 are the limits of acceptable exponents\n// in this test.\nTEST(FromChars, HexdecimalDoubleLimits) {\n  auto input_gen = [](int index) { return absl::StrCat(\"0x1.0p\", index); };\n  auto expected_gen = [](int index) { return std::ldexp(1.0, index); };\n  TestOverflowAndUnderflow<double>(input_gen, expected_gen, -1074, 1023);\n}\n\n// Check that overflow and underflow are caught correctly for hex floats.\n//\n// The largest representable float is 0x1.fffffep+127, and the smallest\n// representable subnormal is 0x0.000002p-126, which equals 0x1p-149.\n// Therefore 127 and -149 are the limits of acceptable exponents in this test.\nTEST(FromChars, HexdecimalFloatLimits) {\n  auto input_gen = [](int index) { return absl::StrCat(\"0x1.0p\", index); };\n  auto expected_gen = [](int index) { return std::ldexp(1.0f, index); };\n  TestOverflowAndUnderflow<float>(input_gen, expected_gen, -149, 127);\n}\n\n// Check that overflow and underflow are caught correctly for decimal doubles.\n//\n// The largest representable double is about 1.8e308, and the smallest\n// representable subnormal is about 5e-324.  '1e-324' therefore rounds away from\n// the smallest representable positive value.  -323 and 308 are the limits of\n// acceptable exponents in this test.\nTEST(FromChars, DecimalDoubleLimits) {\n  auto input_gen = [](int index) { return absl::StrCat(\"1.0e\", index); };\n  auto expected_gen = [](int index) { return Pow10(index); };\n  TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308);\n}\n\n// Check that overflow and underflow are caught correctly for decimal floats.\n//\n// The largest representable float is about 3.4e38, and the smallest\n// representable subnormal is about 1.45e-45.  '1e-45' therefore rounds towards\n// the smallest representable positive value.  -45 and 38 are the limits of\n// acceptable exponents in this test.\nTEST(FromChars, DecimalFloatLimits) {\n  auto input_gen = [](int index) { return absl::StrCat(\"1.0e\", index); };\n  auto expected_gen = [](int index) { return Pow10(index); };\n  TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/charset.h",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: charset.h\n// -----------------------------------------------------------------------------\n//\n// This file contains absl::CharSet, a fast, bit-vector set of 8-bit unsigned\n// characters.\n//\n// Instances can be initialized as constexpr constants. For example:\n//\n//   constexpr absl::CharSet kJustX = absl::CharSet::Char('x');\n//   constexpr absl::CharSet kMySymbols = absl::CharSet(\"$@!\");\n//   constexpr absl::CharSet kLetters = absl::CharSet::Range('a', 'z');\n//\n// Multiple instances can be combined that still forms a constexpr expression.\n// For example:\n//\n//   constexpr absl::CharSet kLettersAndNumbers =\n//       absl::CharSet::Range('a', 'z') | absl::CharSet::Range('0', '9');\n//\n// Several pre-defined character classes are available that mirror the methods\n// from <cctype>. For example:\n//\n//   constexpr absl::CharSet kLettersAndWhitespace =\n//       absl::CharSet::AsciiAlphabet() | absl::CharSet::AsciiWhitespace();\n//\n// To check membership, use the .contains method, e.g.\n//\n//   absl::CharSet hex_letters(\"abcdef\");\n//   hex_letters.contains('a');  // true\n//   hex_letters.contains('g');  // false\n\n#ifndef ABSL_STRINGS_CHARSET_H_\n#define ABSL_STRINGS_CHARSET_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass CharSet {\n public:\n  constexpr CharSet() : m_() {}\n\n  // Initializes with a given string_view.\n  constexpr explicit CharSet(absl::string_view str) : m_() {\n    for (char c : str) {\n      SetChar(static_cast<unsigned char>(c));\n    }\n  }\n\n  constexpr bool contains(char c) const {\n    return ((m_[static_cast<unsigned char>(c) / 64] >>\n             (static_cast<unsigned char>(c) % 64)) &\n            0x1) == 0x1;\n  }\n\n  constexpr bool empty() const {\n    for (uint64_t c : m_) {\n      if (c != 0) return false;\n    }\n    return true;\n  }\n\n  // Containing only a single specified char.\n  static constexpr CharSet Char(char x) {\n    return CharSet(CharMaskForWord(x, 0), CharMaskForWord(x, 1),\n                   CharMaskForWord(x, 2), CharMaskForWord(x, 3));\n  }\n\n  // Containing all the chars in the closed interval [lo,hi].\n  static constexpr CharSet Range(char lo, char hi) {\n    return CharSet(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1),\n                   RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3));\n  }\n\n  friend constexpr CharSet operator&(const CharSet& a, const CharSet& b) {\n    return CharSet(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2],\n                   a.m_[3] & b.m_[3]);\n  }\n\n  friend constexpr CharSet operator|(const CharSet& a, const CharSet& b) {\n    return CharSet(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2],\n                   a.m_[3] | b.m_[3]);\n  }\n\n  friend constexpr CharSet operator~(const CharSet& a) {\n    return CharSet(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]);\n  }\n\n  // Mirrors the char-classifying predicates in <cctype>.\n  static constexpr CharSet AsciiUppercase() { return CharSet::Range('A', 'Z'); }\n  static constexpr CharSet AsciiLowercase() { return CharSet::Range('a', 'z'); }\n  static constexpr CharSet AsciiDigits() { return CharSet::Range('0', '9'); }\n  static constexpr CharSet AsciiAlphabet() {\n    return AsciiLowercase() | AsciiUppercase();\n  }\n  static constexpr CharSet AsciiAlphanumerics() {\n    return AsciiDigits() | AsciiAlphabet();\n  }\n  static constexpr CharSet AsciiHexDigits() {\n    return AsciiDigits() | CharSet::Range('A', 'F') | CharSet::Range('a', 'f');\n  }\n  static constexpr CharSet AsciiPrintable() {\n    return CharSet::Range(0x20, 0x7e);\n  }\n  static constexpr CharSet AsciiWhitespace() { return CharSet(\"\\t\\n\\v\\f\\r \"); }\n  static constexpr CharSet AsciiPunctuation() {\n    return AsciiPrintable() & ~AsciiWhitespace() & ~AsciiAlphanumerics();\n  }\n\n private:\n  constexpr CharSet(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3)\n      : m_{b0, b1, b2, b3} {}\n\n  static constexpr uint64_t RangeForWord(char lo, char hi, uint64_t word) {\n    return OpenRangeFromZeroForWord(static_cast<unsigned char>(hi) + 1, word) &\n           ~OpenRangeFromZeroForWord(static_cast<unsigned char>(lo), word);\n  }\n\n  // All the chars in the specified word of the range [0, upper).\n  static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper,\n                                                     uint64_t word) {\n    return (upper <= 64 * word) ? 0\n           : (upper >= 64 * (word + 1))\n               ? ~static_cast<uint64_t>(0)\n               : (~static_cast<uint64_t>(0) >> (64 - upper % 64));\n  }\n\n  static constexpr uint64_t CharMaskForWord(char x, uint64_t word) {\n    return (static_cast<unsigned char>(x) / 64 == word)\n               ? (static_cast<uint64_t>(1)\n                  << (static_cast<unsigned char>(x) % 64))\n               : 0;\n  }\n\n  constexpr void SetChar(unsigned char c) {\n    m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64);\n  }\n\n  uint64_t m_[4];\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_CHARSET_H_\n"
  },
  {
    "path": "absl/strings/charset_benchmark.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n\n#include \"absl/log/check.h\"\n#include \"absl/strings/charset.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nabsl::CharSet MakeBenchmarkMap() {\n  absl::CharSet m;\n  uint32_t x[] = {0x0, 0x1, 0x2, 0x3, 0xf, 0xe, 0xd, 0xc};\n  for (uint32_t& t : x) t *= static_cast<uint32_t>(0x11111111UL);\n  for (uint32_t i = 0; i < 256; ++i) {\n    if ((x[i / 32] >> (i % 32)) & 1) m = m | absl::CharSet::Char(i);\n  }\n  return m;\n}\n\n// Micro-benchmark for Charmap::contains.\nstatic void BM_Contains(benchmark::State& state) {\n  // Loop-body replicated 10 times to increase time per iteration.\n  // Argument continuously changed to avoid generating common subexpressions.\n  // Final CHECK used to discourage unwanted optimization.\n  const absl::CharSet benchmark_map = MakeBenchmarkMap();\n  unsigned char c = 0;\n  int ops = 0;\n  for (auto _ : state) {\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n    ops += benchmark_map.contains(c++);\n  }\n  CHECK_NE(ops, -1);\n}\nBENCHMARK(BM_Contains);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/charset_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/charset.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#include <string>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nconstexpr absl::CharSet everything_map = ~absl::CharSet();\nconstexpr absl::CharSet nothing_map = absl::CharSet();\n\nTEST(Charmap, AllTests) {\n  const absl::CharSet also_nothing_map(\"\");\n  EXPECT_TRUE(everything_map.contains('\\0'));\n  EXPECT_FALSE(nothing_map.contains('\\0'));\n  EXPECT_FALSE(also_nothing_map.contains('\\0'));\n  for (unsigned char ch = 1; ch != 0; ++ch) {\n    SCOPED_TRACE(ch);\n    EXPECT_TRUE(everything_map.contains(ch));\n    EXPECT_FALSE(nothing_map.contains(ch));\n    EXPECT_FALSE(also_nothing_map.contains(ch));\n  }\n\n  const absl::CharSet symbols(absl::string_view(\"&@#@^!@?\", 5));\n  EXPECT_TRUE(symbols.contains('&'));\n  EXPECT_TRUE(symbols.contains('@'));\n  EXPECT_TRUE(symbols.contains('#'));\n  EXPECT_TRUE(symbols.contains('^'));\n  EXPECT_FALSE(symbols.contains('!'));\n  EXPECT_FALSE(symbols.contains('?'));\n  int cnt = 0;\n  for (unsigned char ch = 1; ch != 0; ++ch) cnt += symbols.contains(ch);\n  EXPECT_EQ(cnt, 4);\n\n  const absl::CharSet lets(absl::string_view(\"^abcde\", 3));\n  const absl::CharSet lets2(absl::string_view(\"fghij\\0klmnop\", 10));\n  const absl::CharSet lets3(\"fghij\\0klmnop\");\n  EXPECT_TRUE(lets2.contains('k'));\n  EXPECT_FALSE(lets3.contains('k'));\n\n  EXPECT_FALSE((symbols & lets).empty());\n  EXPECT_TRUE((lets2 & lets).empty());\n  EXPECT_FALSE((lets & symbols).empty());\n  EXPECT_TRUE((lets & lets2).empty());\n\n  EXPECT_TRUE(nothing_map.empty());\n  EXPECT_FALSE(lets.empty());\n}\n\nstd::string Members(const absl::CharSet& m) {\n  std::string r;\n  for (size_t i = 0; i < 256; ++i)\n    if (m.contains(i)) r.push_back(i);\n  return r;\n}\n\nstd::string ClosedRangeString(unsigned char lo, unsigned char hi) {\n  // Don't depend on lo<hi. Just increment until lo==hi.\n  std::string s;\n  while (true) {\n    s.push_back(lo);\n    if (lo == hi) break;\n    ++lo;\n  }\n  return s;\n}\n\nTEST(Charmap, Constexpr) {\n  constexpr absl::CharSet kEmpty = absl::CharSet();\n  EXPECT_EQ(Members(kEmpty), \"\");\n  constexpr absl::CharSet kA = absl::CharSet::Char('A');\n  EXPECT_EQ(Members(kA), \"A\");\n  constexpr absl::CharSet kAZ = absl::CharSet::Range('A', 'Z');\n  EXPECT_EQ(Members(kAZ), \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n  constexpr absl::CharSet kIdentifier =\n      absl::CharSet::Range('0', '9') | absl::CharSet::Range('A', 'Z') |\n      absl::CharSet::Range('a', 'z') | absl::CharSet::Char('_');\n  EXPECT_EQ(Members(kIdentifier),\n            \"0123456789\"\n            \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n            \"_\"\n            \"abcdefghijklmnopqrstuvwxyz\");\n  constexpr absl::CharSet kAll = ~absl::CharSet();\n  for (size_t i = 0; i < 256; ++i) {\n    SCOPED_TRACE(i);\n    EXPECT_TRUE(kAll.contains(i));\n  }\n  constexpr absl::CharSet kHello = absl::CharSet(\"Hello, world!\");\n  EXPECT_EQ(Members(kHello), \" !,Hdelorw\");\n\n  // test negation and intersection\n  constexpr absl::CharSet kABC =\n      absl::CharSet::Range('A', 'Z') & ~absl::CharSet::Range('D', 'Z');\n  EXPECT_EQ(Members(kABC), \"ABC\");\n\n  // contains\n  constexpr bool kContainsA = absl::CharSet(\"abc\").contains('a');\n  EXPECT_TRUE(kContainsA);\n  constexpr bool kContainsD = absl::CharSet(\"abc\").contains('d');\n  EXPECT_FALSE(kContainsD);\n\n  // empty\n  constexpr bool kEmptyIsEmpty = absl::CharSet().empty();\n  EXPECT_TRUE(kEmptyIsEmpty);\n  constexpr bool kNotEmptyIsEmpty = absl::CharSet(\"abc\").empty();\n  EXPECT_FALSE(kNotEmptyIsEmpty);\n}\n\nTEST(Charmap, Range) {\n  // Exhaustive testing takes too long, so test some of the boundaries that\n  // are perhaps going to cause trouble.\n  std::vector<size_t> poi = {0,   1,   2,   3,   4,   7,   8,   9,  15,\n                             16,  17,  30,  31,  32,  33,  63,  64, 65,\n                             127, 128, 129, 223, 224, 225, 254, 255};\n  for (auto lo = poi.begin(); lo != poi.end(); ++lo) {\n    SCOPED_TRACE(*lo);\n    for (auto hi = lo; hi != poi.end(); ++hi) {\n      SCOPED_TRACE(*hi);\n      EXPECT_EQ(Members(absl::CharSet::Range(*lo, *hi)),\n                ClosedRangeString(*lo, *hi));\n    }\n  }\n}\n\nTEST(Charmap, NullByteWithStringView) {\n  char characters[5] = {'a', 'b', '\\0', 'd', 'x'};\n  absl::string_view view(characters, 5);\n  absl::CharSet tester(view);\n  EXPECT_TRUE(tester.contains('a'));\n  EXPECT_TRUE(tester.contains('b'));\n  EXPECT_TRUE(tester.contains('\\0'));\n  EXPECT_TRUE(tester.contains('d'));\n  EXPECT_TRUE(tester.contains('x'));\n  EXPECT_FALSE(tester.contains('c'));\n}\n\nTEST(CharmapCtype, Match) {\n  for (int c = 0; c < 256; ++c) {\n    SCOPED_TRACE(c);\n    SCOPED_TRACE(static_cast<char>(c));\n    EXPECT_EQ(absl::ascii_isupper(c),\n              absl::CharSet::AsciiUppercase().contains(c));\n    EXPECT_EQ(absl::ascii_islower(c),\n              absl::CharSet::AsciiLowercase().contains(c));\n    EXPECT_EQ(absl::ascii_isdigit(c), absl::CharSet::AsciiDigits().contains(c));\n    EXPECT_EQ(absl::ascii_isalpha(c),\n              absl::CharSet::AsciiAlphabet().contains(c));\n    EXPECT_EQ(absl::ascii_isalnum(c),\n              absl::CharSet::AsciiAlphanumerics().contains(c));\n    EXPECT_EQ(absl::ascii_isxdigit(c),\n              absl::CharSet::AsciiHexDigits().contains(c));\n    EXPECT_EQ(absl::ascii_isprint(c),\n              absl::CharSet::AsciiPrintable().contains(c));\n    EXPECT_EQ(absl::ascii_isspace(c),\n              absl::CharSet::AsciiWhitespace().contains(c));\n    EXPECT_EQ(absl::ascii_ispunct(c),\n              absl::CharSet::AsciiPunctuation().contains(c));\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/cord.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/cord.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <iomanip>\n#include <ios>\n#include <iostream>\n#include <limits>\n#include <memory>\n#include <optional>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/crc/crc32c.h\"\n#include \"absl/crc/internal/crc_cord_state.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/strings/cord_buffer.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/internal/append_and_overwrite.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nusing ::absl::cord_internal::CordRep;\nusing ::absl::cord_internal::CordRepBtree;\nusing ::absl::cord_internal::CordRepCrc;\nusing ::absl::cord_internal::CordRepExternal;\nusing ::absl::cord_internal::CordRepFlat;\nusing ::absl::cord_internal::CordRepSubstring;\nusing ::absl::cord_internal::CordzUpdateTracker;\nusing ::absl::cord_internal::InlineData;\nusing ::absl::cord_internal::kMaxFlatLength;\nusing ::absl::cord_internal::kMinFlatLength;\n\nusing ::absl::cord_internal::kInlinedVectorSize;\nusing ::absl::cord_internal::kMaxBytesToCopy;\n\nstatic void DumpNode(CordRep* absl_nonnull nonnull_rep, bool include_data,\n                     std::ostream* absl_nonnull os, int indent = 0);\nstatic bool VerifyNode(CordRep* absl_nonnull root,\n                       CordRep* absl_nonnull start_node);\n\nstatic inline CordRep* absl_nullable VerifyTree(CordRep* absl_nullable node) {\n  assert(node == nullptr || VerifyNode(node, node));\n  static_cast<void>(&VerifyNode);\n  return node;\n}\n\nstatic CordRepFlat* absl_nonnull CreateFlat(const char* absl_nonnull data,\n                                            size_t length, size_t alloc_hint) {\n  CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);\n  flat->length = length;\n  memcpy(flat->Data(), data, length);\n  return flat;\n}\n\n// Creates a new flat or Btree out of the specified array.\n// The returned node has a refcount of 1.\nstatic CordRep* absl_nonnull NewBtree(const char* absl_nonnull data,\n                                      size_t length, size_t alloc_hint) {\n  if (length <= kMaxFlatLength) {\n    return CreateFlat(data, length, alloc_hint);\n  }\n  CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);\n  data += kMaxFlatLength;\n  length -= kMaxFlatLength;\n  auto* root = CordRepBtree::Create(flat);\n  return CordRepBtree::Append(root, {data, length}, alloc_hint);\n}\n\n// Create a new tree out of the specified array.\n// The returned node has a refcount of 1.\nstatic CordRep* absl_nullable NewTree(const char* absl_nullable data,\n                                      size_t length, size_t alloc_hint) {\n  if (length == 0) return nullptr;\n  return NewBtree(data, length, alloc_hint);\n}\n\nnamespace cord_internal {\n\nvoid InitializeCordRepExternal(absl::string_view data,\n                               CordRepExternal* absl_nonnull rep) {\n  assert(!data.empty());\n  rep->length = data.size();\n  rep->tag = EXTERNAL;\n  rep->base = data.data();\n  VerifyTree(rep);\n}\n\n}  // namespace cord_internal\n\n// Creates a CordRep from the provided string. If the string is large enough,\n// and not wasteful, we move the string into an external cord rep, preserving\n// the already allocated string contents.\n// Requires the provided string length to be larger than `kMaxInline`.\nstatic CordRep* absl_nonnull CordRepFromString(std::string&& src) {\n  assert(src.length() > cord_internal::kMaxInline);\n  if (\n      // String is short: copy data to avoid external block overhead.\n      src.size() <= kMaxBytesToCopy ||\n      // String is wasteful: copy data to avoid pinning too much unused memory.\n      src.size() < src.capacity() / 2\n  ) {\n    return NewTree(src.data(), src.size(), 0);\n  }\n\n  struct StringReleaser {\n    void operator()(absl::string_view /* data */) {}\n    std::string data;\n  };\n  const absl::string_view original_data = src;\n  auto* rep =\n      static_cast<::absl::cord_internal::CordRepExternalImpl<StringReleaser>*>(\n          absl::cord_internal::NewExternalRep(original_data,\n                                              StringReleaser{std::move(src)}));\n  // Moving src may have invalidated its data pointer, so adjust it.\n  rep->base = rep->template get<0>().data.data();\n  return rep;\n}\n\n// --------------------------------------------------------------------\n// Cord::InlineRep functions\n\ninline void Cord::InlineRep::set_data(const char* absl_nullable data,\n                                      size_t n) {\n  static_assert(kMaxInline == 15, \"set_data is hard-coded for a length of 15\");\n  assert(data != nullptr || n == 0);\n  data_.set_inline_data(data, n);\n}\n\ninline char* absl_nonnull Cord::InlineRep::set_data(size_t n) {\n  assert(n <= kMaxInline);\n  ResetToEmpty();\n  set_inline_size(n);\n  return data_.as_chars();\n}\n\ninline void Cord::InlineRep::reduce_size(size_t n) {\n  size_t tag = inline_size();\n  assert(tag <= kMaxInline);\n  assert(tag >= n);\n  tag -= n;\n  memset(data_.as_chars() + tag, 0, n);\n  set_inline_size(tag);\n}\n\ninline void Cord::InlineRep::remove_prefix(size_t n) {\n  cord_internal::SmallMemmove(data_.as_chars(), data_.as_chars() + n,\n                              inline_size() - n);\n  reduce_size(n);\n}\n\n// Returns `rep` converted into a CordRepBtree.\n// Directly returns `rep` if `rep` is already a CordRepBtree.\nstatic CordRepBtree* absl_nonnull ForceBtree(CordRep* rep) {\n  return rep->IsBtree()\n             ? rep->btree()\n             : CordRepBtree::Create(cord_internal::RemoveCrcNode(rep));\n}\n\nvoid Cord::InlineRep::AppendTreeToInlined(CordRep* absl_nonnull tree,\n                                          MethodIdentifier method) {\n  assert(!is_tree());\n  if (!data_.is_empty()) {\n    CordRepFlat* flat = MakeFlatWithExtraCapacity(0);\n    tree = CordRepBtree::Append(CordRepBtree::Create(flat), tree);\n  }\n  EmplaceTree(tree, method);\n}\n\nvoid Cord::InlineRep::AppendTreeToTree(CordRep* absl_nonnull tree,\n                                       MethodIdentifier method) {\n  assert(is_tree());\n  const CordzUpdateScope scope(data_.cordz_info(), method);\n  tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree);\n  SetTree(tree, scope);\n}\n\nvoid Cord::InlineRep::AppendTree(CordRep* absl_nonnull tree,\n                                 MethodIdentifier method) {\n  assert(tree != nullptr);\n  assert(tree->length != 0);\n  assert(!tree->IsCrc());\n  if (data_.is_tree()) {\n    AppendTreeToTree(tree, method);\n  } else {\n    AppendTreeToInlined(tree, method);\n  }\n}\n\nvoid Cord::InlineRep::PrependTreeToInlined(CordRep* absl_nonnull tree,\n                                           MethodIdentifier method) {\n  assert(!is_tree());\n  if (!data_.is_empty()) {\n    CordRepFlat* flat = MakeFlatWithExtraCapacity(0);\n    tree = CordRepBtree::Prepend(CordRepBtree::Create(flat), tree);\n  }\n  EmplaceTree(tree, method);\n}\n\nvoid Cord::InlineRep::PrependTreeToTree(CordRep* absl_nonnull tree,\n                                        MethodIdentifier method) {\n  assert(is_tree());\n  const CordzUpdateScope scope(data_.cordz_info(), method);\n  tree = CordRepBtree::Prepend(ForceBtree(data_.as_tree()), tree);\n  SetTree(tree, scope);\n}\n\nvoid Cord::InlineRep::PrependTree(CordRep* absl_nonnull tree,\n                                  MethodIdentifier method) {\n  assert(tree != nullptr);\n  assert(tree->length != 0);\n  assert(!tree->IsCrc());\n  if (data_.is_tree()) {\n    PrependTreeToTree(tree, method);\n  } else {\n    PrependTreeToInlined(tree, method);\n  }\n}\n\n// Searches for a non-full flat node at the rightmost leaf of the tree. If a\n// suitable leaf is found, the function will update the length field for all\n// nodes to account for the size increase. The append region address will be\n// written to region and the actual size increase will be written to size.\nstatic inline bool PrepareAppendRegion(CordRep* absl_nonnull root,\n                                       char* absl_nullable* absl_nonnull region,\n                                       size_t* absl_nonnull size,\n                                       size_t max_length) {\n  if (root->IsBtree() && root->refcount.IsOne()) {\n    Span<char> span = root->btree()->GetAppendBuffer(max_length);\n    if (!span.empty()) {\n      *region = span.data();\n      *size = span.size();\n      return true;\n    }\n  }\n\n  CordRep* dst = root;\n  if (!dst->IsFlat() || !dst->refcount.IsOne()) {\n    *region = nullptr;\n    *size = 0;\n    return false;\n  }\n\n  const size_t in_use = dst->length;\n  const size_t capacity = dst->flat()->Capacity();\n  if (in_use == capacity) {\n    *region = nullptr;\n    *size = 0;\n    return false;\n  }\n\n  const size_t size_increase = std::min(capacity - in_use, max_length);\n  dst->length += size_increase;\n\n  *region = dst->flat()->Data() + in_use;\n  *size = size_increase;\n  return true;\n}\n\nvoid Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {\n  assert(&src != this);\n  assert(is_tree() || src.is_tree());\n  auto constexpr method = CordzUpdateTracker::kAssignCord;\n  if (ABSL_PREDICT_TRUE(!is_tree())) {\n    EmplaceTree(CordRep::Ref(src.as_tree()), src.data_, method);\n    return;\n  }\n\n  CordRep* tree = as_tree();\n  if (CordRep* src_tree = src.tree()) {\n    // Leave any existing `cordz_info` in place, and let MaybeTrackCord()\n    // decide if this cord should be (or remains to be) sampled or not.\n    data_.set_tree(CordRep::Ref(src_tree));\n    CordzInfo::MaybeTrackCord(data_, src.data_, method);\n  } else {\n    CordzInfo::MaybeUntrackCord(data_.cordz_info());\n    data_ = src.data_;\n  }\n  CordRep::Unref(tree);\n}\n\nvoid Cord::InlineRep::UnrefTree() {\n  if (is_tree()) {\n    CordzInfo::MaybeUntrackCord(data_.cordz_info());\n    CordRep::Unref(tree());\n  }\n}\n\n// --------------------------------------------------------------------\n// Constructors and destructors\n\nCord::Cord(absl::string_view src, MethodIdentifier method)\n    : contents_(InlineData::kDefaultInit) {\n  const size_t n = src.size();\n  if (n <= InlineRep::kMaxInline) {\n    contents_.set_data(src.data(), n);\n  } else {\n    CordRep* rep = NewTree(src.data(), n, 0);\n    contents_.EmplaceTree(rep, method);\n  }\n}\n\ntemplate <typename T, Cord::EnableIfString<T>>\nCord::Cord(T&& src) : contents_(InlineData::kDefaultInit) {\n  if (src.size() <= InlineRep::kMaxInline) {\n    contents_.set_data(src.data(), src.size());\n  } else {\n    CordRep* rep = CordRepFromString(std::forward<T>(src));\n    contents_.EmplaceTree(rep, CordzUpdateTracker::kConstructorString);\n  }\n}\n\ntemplate Cord::Cord(std::string&& src);\n\n// The destruction code is separate so that the compiler can determine\n// that it does not need to call the destructor on a moved-from Cord.\nvoid Cord::DestroyCordSlow() {\n  assert(contents_.is_tree());\n  CordzInfo::MaybeUntrackCord(contents_.cordz_info());\n  CordRep::Unref(VerifyTree(contents_.as_tree()));\n}\n\n// --------------------------------------------------------------------\n// Mutators\n\nvoid Cord::Clear() {\n  if (CordRep* tree = contents_.clear()) {\n    CordRep::Unref(tree);\n  }\n}\n\nCord& Cord::AssignLargeString(std::string&& src) {\n  auto constexpr method = CordzUpdateTracker::kAssignString;\n  assert(src.size() > kMaxBytesToCopy);\n  CordRep* rep = CordRepFromString(std::move(src));\n  if (CordRep* tree = contents_.tree()) {\n    CordzUpdateScope scope(contents_.cordz_info(), method);\n    contents_.SetTree(rep, scope);\n    CordRep::Unref(tree);\n  } else {\n    contents_.EmplaceTree(rep, method);\n  }\n  return *this;\n}\n\nCord& Cord::operator=(absl::string_view src) {\n  auto constexpr method = CordzUpdateTracker::kAssignString;\n  const char* data = src.data();\n  size_t length = src.size();\n  CordRep* tree = contents_.tree();\n  if (length <= InlineRep::kMaxInline) {\n    // Embed into this->contents_, which is somewhat subtle:\n    // - MaybeUntrackCord must be called before Unref(tree).\n    // - MaybeUntrackCord must be called before set_data() clobbers cordz_info.\n    // - set_data() must be called before Unref(tree) as it may reference tree.\n    if (tree != nullptr) CordzInfo::MaybeUntrackCord(contents_.cordz_info());\n    contents_.set_data(data, length);\n    if (tree != nullptr) CordRep::Unref(tree);\n    return *this;\n  }\n  if (tree != nullptr) {\n    CordzUpdateScope scope(contents_.cordz_info(), method);\n    if (tree->IsFlat() && tree->flat()->Capacity() >= length &&\n        tree->refcount.IsOne()) {\n      // Copy in place if the existing FLAT node is reusable.\n      memmove(tree->flat()->Data(), data, length);\n      tree->length = length;\n      VerifyTree(tree);\n      return *this;\n    }\n    contents_.SetTree(NewTree(data, length, 0), scope);\n    CordRep::Unref(tree);\n  } else {\n    contents_.EmplaceTree(NewTree(data, length, 0), method);\n  }\n  return *this;\n}\n\n// TODO(sanjay): Move to Cord::InlineRep section of file.  For now,\n// we keep it here to make diffs easier.\nvoid Cord::InlineRep::AppendArray(absl::string_view src,\n                                  MethodIdentifier method) {\n  if (src.empty()) return;  // memcpy(_, nullptr, 0) is undefined.\n  MaybeRemoveEmptyCrcNode();\n\n  size_t appended = 0;\n  CordRep* rep = tree();\n  const CordRep* const root = rep;\n  CordzUpdateScope scope(root ? cordz_info() : nullptr, method);\n  if (root != nullptr) {\n    rep = cord_internal::RemoveCrcNode(rep);\n    char* region;\n    if (PrepareAppendRegion(rep, &region, &appended, src.size())) {\n      memcpy(region, src.data(), appended);\n    }\n  } else {\n    // Try to fit in the inline buffer if possible.\n    size_t inline_length = inline_size();\n    if (src.size() <= kMaxInline - inline_length) {\n      // Append new data to embedded array\n      set_inline_size(inline_length + src.size());\n      memcpy(data_.as_chars() + inline_length, src.data(), src.size());\n      return;\n    }\n\n    // Allocate flat to be a perfect fit on first append exceeding inlined size.\n    // Subsequent growth will use amortized growth until we reach maximum flat\n    // size.\n    rep = CordRepFlat::New(inline_length + src.size());\n    appended = std::min(src.size(), rep->flat()->Capacity() - inline_length);\n    memcpy(rep->flat()->Data(), data_.as_chars(), inline_length);\n    memcpy(rep->flat()->Data() + inline_length, src.data(), appended);\n    rep->length = inline_length + appended;\n  }\n\n  src.remove_prefix(appended);\n  if (src.empty()) {\n    CommitTree(root, rep, scope, method);\n    return;\n  }\n\n  // TODO(b/192061034): keep legacy 10% growth rate: consider other rates.\n  rep = ForceBtree(rep);\n  const size_t min_growth = std::max<size_t>(rep->length / 10, src.size());\n  rep = CordRepBtree::Append(rep->btree(), src, min_growth - src.size());\n\n  CommitTree(root, rep, scope, method);\n}\n\ninline CordRep* absl_nonnull Cord::TakeRep() const& {\n  return CordRep::Ref(contents_.tree());\n}\n\ninline CordRep* absl_nonnull Cord::TakeRep() && {\n  CordRep* rep = contents_.tree();\n  contents_.clear();\n  return rep;\n}\n\ntemplate <typename C>\ninline void Cord::AppendImpl(C&& src) {\n  auto constexpr method = CordzUpdateTracker::kAppendCord;\n\n  contents_.MaybeRemoveEmptyCrcNode();\n  if (src.empty()) return;\n\n  if (empty()) {\n    // Since destination is empty, we can avoid allocating a node,\n    if (src.contents_.is_tree()) {\n      // by taking the tree directly\n      CordRep* rep =\n          cord_internal::RemoveCrcNode(std::forward<C>(src).TakeRep());\n      contents_.EmplaceTree(rep, method);\n    } else {\n      // or copying over inline data\n      contents_.data_ = src.contents_.data_;\n    }\n    return;\n  }\n\n  // For short cords, it is faster to copy data if there is room in dst.\n  const size_t src_size = src.contents_.size();\n  if (src_size <= kMaxBytesToCopy) {\n    CordRep* src_tree = src.contents_.tree();\n    if (src_tree == nullptr) {\n      // src has embedded data.\n      contents_.AppendArray({src.contents_.data(), src_size}, method);\n      return;\n    }\n    if (src_tree->IsFlat()) {\n      // src tree just has one flat node.\n      contents_.AppendArray({src_tree->flat()->Data(), src_size}, method);\n      return;\n    }\n    if (&src == this) {\n      // ChunkIterator below assumes that src is not modified during traversal.\n      Append(Cord(src));\n      return;\n    }\n    // TODO(mec): Should we only do this if \"dst\" has space?\n    for (absl::string_view chunk : src.Chunks()) {\n      Append(chunk);\n    }\n    return;\n  }\n\n  // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)\n  CordRep* rep = cord_internal::RemoveCrcNode(std::forward<C>(src).TakeRep());\n  contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);\n}\n\nstatic CordRep::ExtractResult ExtractAppendBuffer(CordRep* absl_nonnull rep,\n                                                  size_t min_capacity) {\n  switch (rep->tag) {\n    case cord_internal::BTREE:\n      return CordRepBtree::ExtractAppendBuffer(rep->btree(), min_capacity);\n    default:\n      if (rep->IsFlat() && rep->refcount.IsOne() &&\n          rep->flat()->Capacity() - rep->length >= min_capacity) {\n        return {nullptr, rep};\n      }\n      return {rep, nullptr};\n  }\n}\n\nstatic CordBuffer CreateAppendBuffer(InlineData& data, size_t block_size,\n                                     size_t capacity) {\n  // Watch out for overflow, people can ask for size_t::max().\n  const size_t size = data.inline_size();\n  const size_t max_capacity = std::numeric_limits<size_t>::max() - size;\n  capacity = (std::min)(max_capacity, capacity) + size;\n  CordBuffer buffer =\n      block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)\n                 : CordBuffer::CreateWithDefaultLimit(capacity);\n  cord_internal::SmallMemmove(buffer.data(), data.as_chars(), size);\n  buffer.SetLength(size);\n  data = {};\n  return buffer;\n}\n\nCordBuffer Cord::GetAppendBufferSlowPath(size_t block_size, size_t capacity,\n                                         size_t min_capacity) {\n  auto constexpr method = CordzUpdateTracker::kGetAppendBuffer;\n  CordRep* tree = contents_.tree();\n  if (tree != nullptr) {\n    CordzUpdateScope scope(contents_.cordz_info(), method);\n    CordRep::ExtractResult result = ExtractAppendBuffer(tree, min_capacity);\n    if (result.extracted != nullptr) {\n      contents_.SetTreeOrEmpty(result.tree, scope);\n      return CordBuffer(result.extracted->flat());\n    }\n    return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)\n                      : CordBuffer::CreateWithDefaultLimit(capacity);\n  }\n  return CreateAppendBuffer(contents_.data_, block_size, capacity);\n}\n\nvoid Cord::Append(const Cord& src) { AppendImpl(src); }\n\nvoid Cord::Append(Cord&& src) { AppendImpl(std::move(src)); }\n\ntemplate <typename T, Cord::EnableIfString<T>>\nvoid Cord::Append(T&& src) {\n  if (src.size() <= kMaxBytesToCopy) {\n    Append(absl::string_view(src));\n  } else {\n    CordRep* rep = CordRepFromString(std::forward<T>(src));\n    contents_.AppendTree(rep, CordzUpdateTracker::kAppendString);\n  }\n}\n\ntemplate void Cord::Append(std::string&& src);\n\nvoid Cord::Prepend(const Cord& src) {\n  contents_.MaybeRemoveEmptyCrcNode();\n  if (src.empty()) return;\n\n  CordRep* src_tree = src.contents_.tree();\n  if (src_tree != nullptr) {\n    CordRep::Ref(src_tree);\n    contents_.PrependTree(cord_internal::RemoveCrcNode(src_tree),\n                          CordzUpdateTracker::kPrependCord);\n    return;\n  }\n\n  // `src` cord is inlined.\n  absl::string_view src_contents(src.contents_.data(), src.contents_.size());\n  return Prepend(src_contents);\n}\n\nvoid Cord::PrependArray(absl::string_view src, MethodIdentifier method) {\n  contents_.MaybeRemoveEmptyCrcNode();\n  if (src.empty()) return;  // memcpy(_, nullptr, 0) is undefined.\n\n  if (!contents_.is_tree()) {\n    size_t cur_size = contents_.inline_size();\n    if (cur_size + src.size() <= InlineRep::kMaxInline) {\n      // Use embedded storage.\n      InlineData data;\n      data.set_inline_size(cur_size + src.size());\n      memcpy(data.as_chars(), src.data(), src.size());\n      memcpy(data.as_chars() + src.size(), contents_.data(), cur_size);\n      contents_.data_ = data;\n      return;\n    }\n  }\n  CordRep* rep = NewTree(src.data(), src.size(), 0);\n  contents_.PrependTree(rep, method);\n}\n\nvoid Cord::AppendPrecise(absl::string_view src, MethodIdentifier method) {\n  assert(!src.empty());\n  assert(src.size() <= cord_internal::kMaxFlatLength);\n  if (contents_.remaining_inline_capacity() >= src.size()) {\n    const size_t inline_length = contents_.inline_size();\n    contents_.set_inline_size(inline_length + src.size());\n    memcpy(contents_.data_.as_chars() + inline_length, src.data(), src.size());\n  } else {\n    contents_.AppendTree(CordRepFlat::Create(src), method);\n  }\n}\n\nvoid Cord::PrependPrecise(absl::string_view src, MethodIdentifier method) {\n  assert(!src.empty());\n  assert(src.size() <= cord_internal::kMaxFlatLength);\n  if (contents_.remaining_inline_capacity() >= src.size()) {\n    const size_t cur_size = contents_.inline_size();\n    InlineData data;\n    data.set_inline_size(cur_size + src.size());\n    memcpy(data.as_chars(), src.data(), src.size());\n    memcpy(data.as_chars() + src.size(), contents_.data(), cur_size);\n    contents_.data_ = data;\n  } else {\n    contents_.PrependTree(CordRepFlat::Create(src), method);\n  }\n}\n\ntemplate <typename T, Cord::EnableIfString<T>>\ninline void Cord::Prepend(T&& src) {\n  if (src.size() <= kMaxBytesToCopy) {\n    Prepend(absl::string_view(src));\n  } else {\n    CordRep* rep = CordRepFromString(std::forward<T>(src));\n    contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);\n  }\n}\n\ntemplate void Cord::Prepend(std::string&& src);\n\nvoid Cord::RemovePrefix(size_t n) {\n  ABSL_INTERNAL_CHECK(n <= size(),\n                      absl::StrCat(\"Requested prefix size \", n,\n                                   \" exceeds Cord's size \", size()));\n  contents_.MaybeRemoveEmptyCrcNode();\n  CordRep* tree = contents_.tree();\n  if (tree == nullptr) {\n    contents_.remove_prefix(n);\n  } else {\n    auto constexpr method = CordzUpdateTracker::kRemovePrefix;\n    CordzUpdateScope scope(contents_.cordz_info(), method);\n    tree = cord_internal::RemoveCrcNode(tree);\n    if (n >= tree->length) {\n      CordRep::Unref(tree);\n      tree = nullptr;\n    } else if (tree->IsBtree()) {\n      CordRep* old = tree;\n      tree = tree->btree()->SubTree(n, tree->length - n);\n      CordRep::Unref(old);\n    } else if (tree->IsSubstring() && tree->refcount.IsOne()) {\n      tree->substring()->start += n;\n      tree->length -= n;\n    } else {\n      CordRep* rep = CordRepSubstring::Substring(tree, n, tree->length - n);\n      CordRep::Unref(tree);\n      tree = rep;\n    }\n    contents_.SetTreeOrEmpty(tree, scope);\n  }\n}\n\nvoid Cord::RemoveSuffix(size_t n) {\n  ABSL_INTERNAL_CHECK(n <= size(),\n                      absl::StrCat(\"Requested suffix size \", n,\n                                   \" exceeds Cord's size \", size()));\n  contents_.MaybeRemoveEmptyCrcNode();\n  CordRep* tree = contents_.tree();\n  if (tree == nullptr) {\n    contents_.reduce_size(n);\n  } else {\n    auto constexpr method = CordzUpdateTracker::kRemoveSuffix;\n    CordzUpdateScope scope(contents_.cordz_info(), method);\n    tree = cord_internal::RemoveCrcNode(tree);\n    if (n >= tree->length) {\n      CordRep::Unref(tree);\n      tree = nullptr;\n    } else if (tree->IsBtree()) {\n      tree = CordRepBtree::RemoveSuffix(tree->btree(), n);\n    } else if (!tree->IsExternal() && tree->refcount.IsOne()) {\n      assert(tree->IsFlat() || tree->IsSubstring());\n      tree->length -= n;\n    } else {\n      CordRep* rep = CordRepSubstring::Substring(tree, 0, tree->length - n);\n      CordRep::Unref(tree);\n      tree = rep;\n    }\n    contents_.SetTreeOrEmpty(tree, scope);\n  }\n}\n\nCord Cord::Subcord(size_t pos, size_t new_size) const {\n  Cord sub_cord;\n  size_t length = size();\n  if (pos > length) pos = length;\n  if (new_size > length - pos) new_size = length - pos;\n  if (new_size == 0) return sub_cord;\n\n  CordRep* tree = contents_.tree();\n  if (tree == nullptr) {\n    sub_cord.contents_.set_data(contents_.data() + pos, new_size);\n    return sub_cord;\n  }\n\n  if (new_size <= InlineRep::kMaxInline) {\n    sub_cord.contents_.set_inline_size(new_size);\n    char* dest = sub_cord.contents_.data_.as_chars();\n    Cord::ChunkIterator it = chunk_begin();\n    it.AdvanceBytes(pos);\n    size_t remaining_size = new_size;\n    while (remaining_size > it->size()) {\n      cord_internal::SmallMemmove(dest, it->data(), it->size());\n      remaining_size -= it->size();\n      dest += it->size();\n      ++it;\n    }\n    cord_internal::SmallMemmove(dest, it->data(), remaining_size);\n    return sub_cord;\n  }\n\n  tree = cord_internal::SkipCrcNode(tree);\n  if (tree->IsBtree()) {\n    tree = tree->btree()->SubTree(pos, new_size);\n  } else {\n    tree = CordRepSubstring::Substring(tree, pos, new_size);\n  }\n  sub_cord.contents_.EmplaceTree(tree, contents_.data_,\n                                 CordzUpdateTracker::kSubCord);\n  return sub_cord;\n}\n\n// --------------------------------------------------------------------\n// Comparators\n\nnamespace {\n\nint ClampResult(int memcmp_res) {\n  return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);\n}\n\nint CompareChunks(absl::string_view* absl_nonnull lhs,\n                  absl::string_view* absl_nonnull rhs,\n                  size_t* absl_nonnull size_to_compare) {\n  size_t compared_size = std::min(lhs->size(), rhs->size());\n  assert(*size_to_compare >= compared_size);\n  *size_to_compare -= compared_size;\n\n  int memcmp_res = ::memcmp(lhs->data(), rhs->data(), compared_size);\n  if (memcmp_res != 0) return memcmp_res;\n\n  lhs->remove_prefix(compared_size);\n  rhs->remove_prefix(compared_size);\n\n  return 0;\n}\n\n// This overload set computes comparison results from memcmp result. This\n// interface is used inside GenericCompare below. Different implementations\n// are specialized for int and bool. For int we clamp result to {-1, 0, 1}\n// set. For bool we just interested in \"value == 0\".\ntemplate <typename ResultType>\nResultType ComputeCompareResult(int memcmp_res) {\n  return ClampResult(memcmp_res);\n}\ntemplate <>\nbool ComputeCompareResult<bool>(int memcmp_res) {\n  return memcmp_res == 0;\n}\n\n}  // namespace\n\n// Helper routine. Locates the first flat or external chunk of the Cord without\n// initializing the iterator, and returns a string_view referencing the data.\ninline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {\n  if (!is_tree()) {\n    return absl::string_view(data_.as_chars(), data_.inline_size());\n  }\n\n  CordRep* node = cord_internal::SkipCrcNode(tree());\n  if (node->IsFlat()) {\n    return absl::string_view(node->flat()->Data(), node->length);\n  }\n\n  if (node->IsExternal()) {\n    return absl::string_view(node->external()->base, node->length);\n  }\n\n  if (node->IsBtree()) {\n    CordRepBtree* tree = node->btree();\n    int height = tree->height();\n    while (--height >= 0) {\n      tree = tree->Edge(CordRepBtree::kFront)->btree();\n    }\n    return tree->Data(tree->begin());\n  }\n\n  // Get the child node if we encounter a SUBSTRING.\n  size_t offset = 0;\n  size_t length = node->length;\n  assert(length != 0);\n\n  if (node->IsSubstring()) {\n    offset = node->substring()->start;\n    node = node->substring()->child;\n  }\n\n  if (node->IsFlat()) {\n    return absl::string_view(node->flat()->Data() + offset, length);\n  }\n\n  assert(node->IsExternal() && \"Expect FLAT or EXTERNAL node here\");\n\n  return absl::string_view(node->external()->base + offset, length);\n}\n\nvoid Cord::SetCrcCordState(crc_internal::CrcCordState state) {\n  auto constexpr method = CordzUpdateTracker::kSetExpectedChecksum;\n  if (empty()) {\n    contents_.MaybeRemoveEmptyCrcNode();\n    CordRep* rep = CordRepCrc::New(nullptr, std::move(state));\n    contents_.EmplaceTree(rep, method);\n  } else if (!contents_.is_tree()) {\n    CordRep* rep = contents_.MakeFlatWithExtraCapacity(0);\n    rep = CordRepCrc::New(rep, std::move(state));\n    contents_.EmplaceTree(rep, method);\n  } else {\n    const CordzUpdateScope scope(contents_.data_.cordz_info(), method);\n    CordRep* rep = CordRepCrc::New(contents_.data_.as_tree(), std::move(state));\n    contents_.SetTree(rep, scope);\n  }\n}\n\nvoid Cord::SetExpectedChecksum(uint32_t crc) {\n  // Construct a CrcCordState with a single chunk.\n  crc_internal::CrcCordState state;\n  state.mutable_rep()->prefix_crc.push_back(\n      crc_internal::CrcCordState::PrefixCrc(size(), absl::crc32c_t{crc}));\n  SetCrcCordState(std::move(state));\n}\n\nconst crc_internal::CrcCordState* absl_nullable Cord::MaybeGetCrcCordState()\n    const {\n  if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {\n    return nullptr;\n  }\n  return &contents_.tree()->crc()->crc_cord_state;\n}\n\nstd::optional<uint32_t> Cord::ExpectedChecksum() const {\n  if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {\n    return std::nullopt;\n  }\n  return static_cast<uint32_t>(\n      contents_.tree()->crc()->crc_cord_state.Checksum());\n}\n\ninline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,\n                                 size_t size_to_compare) const {\n  auto advance = [](Cord::ChunkIterator* absl_nonnull it,\n                    absl::string_view* absl_nonnull chunk) {\n    if (!chunk->empty()) return true;\n    ++*it;\n    if (it->bytes_remaining_ == 0) return false;\n    *chunk = **it;\n    return true;\n  };\n\n  Cord::ChunkIterator lhs_it = chunk_begin();\n\n  // compared_size is inside first chunk.\n  absl::string_view lhs_chunk =\n      (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();\n  assert(compared_size <= lhs_chunk.size());\n  assert(compared_size <= rhs.size());\n  lhs_chunk.remove_prefix(compared_size);\n  rhs.remove_prefix(compared_size);\n  size_to_compare -= compared_size;  // skip already compared size.\n\n  while (advance(&lhs_it, &lhs_chunk) && !rhs.empty()) {\n    int comparison_result = CompareChunks(&lhs_chunk, &rhs, &size_to_compare);\n    if (comparison_result != 0) return comparison_result;\n    if (size_to_compare == 0) return 0;\n  }\n\n  return static_cast<int>(rhs.empty()) - static_cast<int>(lhs_chunk.empty());\n}\n\ninline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,\n                                 size_t size_to_compare) const {\n  auto advance = [](Cord::ChunkIterator* absl_nonnull it,\n                    absl::string_view* absl_nonnull chunk) {\n    if (!chunk->empty()) return true;\n    ++*it;\n    if (it->bytes_remaining_ == 0) return false;\n    *chunk = **it;\n    return true;\n  };\n\n  Cord::ChunkIterator lhs_it = chunk_begin();\n  Cord::ChunkIterator rhs_it = rhs.chunk_begin();\n\n  // compared_size is inside both first chunks.\n  absl::string_view lhs_chunk =\n      (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();\n  absl::string_view rhs_chunk =\n      (rhs_it.bytes_remaining_ != 0) ? *rhs_it : absl::string_view();\n  assert(compared_size <= lhs_chunk.size());\n  assert(compared_size <= rhs_chunk.size());\n  lhs_chunk.remove_prefix(compared_size);\n  rhs_chunk.remove_prefix(compared_size);\n  size_to_compare -= compared_size;  // skip already compared size.\n\n  while (advance(&lhs_it, &lhs_chunk) && advance(&rhs_it, &rhs_chunk)) {\n    int memcmp_res = CompareChunks(&lhs_chunk, &rhs_chunk, &size_to_compare);\n    if (memcmp_res != 0) return memcmp_res;\n    if (size_to_compare == 0) return 0;\n  }\n\n  return static_cast<int>(rhs_chunk.empty()) -\n         static_cast<int>(lhs_chunk.empty());\n}\n\ninline absl::string_view Cord::GetFirstChunk(const Cord& c) {\n  if (c.empty()) return {};\n  return c.contents_.FindFlatStartPiece();\n}\ninline absl::string_view Cord::GetFirstChunk(absl::string_view sv) {\n  return sv;\n}\n\n// Compares up to 'size_to_compare' bytes of 'lhs' with 'rhs'. It is assumed\n// that 'size_to_compare' is greater that size of smallest of first chunks.\ntemplate <typename ResultType, typename RHS>\nResultType GenericCompare(const Cord& lhs, const RHS& rhs,\n                          size_t size_to_compare) {\n  absl::string_view lhs_chunk = Cord::GetFirstChunk(lhs);\n  absl::string_view rhs_chunk = Cord::GetFirstChunk(rhs);\n\n  size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size());\n  assert(size_to_compare >= compared_size);\n  int memcmp_res = compared_size > 0 ? ::memcmp(lhs_chunk.data(),\n                                                rhs_chunk.data(), compared_size)\n                                     : 0;\n  if (compared_size == size_to_compare || memcmp_res != 0) {\n    return ComputeCompareResult<ResultType>(memcmp_res);\n  }\n\n  return ComputeCompareResult<ResultType>(\n      lhs.CompareSlowPath(rhs, compared_size, size_to_compare));\n}\n\nbool Cord::EqualsImpl(absl::string_view rhs, size_t size_to_compare) const {\n  return GenericCompare<bool>(*this, rhs, size_to_compare);\n}\n\nbool Cord::EqualsImpl(const Cord& rhs, size_t size_to_compare) const {\n  return GenericCompare<bool>(*this, rhs, size_to_compare);\n}\n\ntemplate <typename RHS>\ninline int SharedCompareImpl(const Cord& lhs, const RHS& rhs) {\n  size_t lhs_size = lhs.size();\n  size_t rhs_size = rhs.size();\n  if (lhs_size == rhs_size) {\n    return GenericCompare<int>(lhs, rhs, lhs_size);\n  }\n  if (lhs_size < rhs_size) {\n    auto data_comp_res = GenericCompare<int>(lhs, rhs, lhs_size);\n    return data_comp_res == 0 ? -1 : data_comp_res;\n  }\n\n  auto data_comp_res = GenericCompare<int>(lhs, rhs, rhs_size);\n  return data_comp_res == 0 ? +1 : data_comp_res;\n}\n\nint Cord::Compare(absl::string_view rhs) const {\n  return SharedCompareImpl(*this, rhs);\n}\n\nint Cord::CompareImpl(const Cord& rhs) const {\n  return SharedCompareImpl(*this, rhs);\n}\n\nbool Cord::EndsWith(absl::string_view rhs) const {\n  size_t my_size = size();\n  size_t rhs_size = rhs.size();\n\n  if (my_size < rhs_size) return false;\n\n  Cord tmp(*this);\n  tmp.RemovePrefix(my_size - rhs_size);\n  return tmp.EqualsImpl(rhs, rhs_size);\n}\n\nbool Cord::EndsWith(const Cord& rhs) const {\n  size_t my_size = size();\n  size_t rhs_size = rhs.size();\n\n  if (my_size < rhs_size) return false;\n\n  Cord tmp(*this);\n  tmp.RemovePrefix(my_size - rhs_size);\n  return tmp.EqualsImpl(rhs, rhs_size);\n}\n\n// --------------------------------------------------------------------\n// Misc.\n\nCord::operator std::string() const {\n  std::string s;\n  absl::CopyCordToString(*this, &s);\n  return s;\n}\n\nvoid CopyCordToString(const Cord& src, std::string* absl_nonnull dst) {\n  if (!src.contents_.is_tree()) {\n    src.contents_.CopyTo(dst);\n  } else {\n    StringResizeAndOverwrite(*dst, src.size(),\n                             [&src](char* buf, size_t buf_size) {\n                               src.CopyToArraySlowPath(buf);\n                               return buf_size;\n                             });\n  }\n}\n\nvoid AppendCordToString(const Cord& src, std::string* absl_nonnull dst) {\n  strings_internal::StringAppendAndOverwrite(\n      *dst, src.size(), [&src](char* buf, size_t buf_size) {\n        src.CopyToArrayImpl(buf);\n        return buf_size;\n      });\n}\n\nvoid Cord::CopyToArraySlowPath(char* absl_nonnull dst) const {\n  assert(contents_.is_tree());\n  absl::string_view fragment;\n  if (GetFlatAux(contents_.tree(), &fragment) && !fragment.empty()) {\n    memcpy(dst, fragment.data(), fragment.size());\n    return;\n  }\n  for (absl::string_view chunk : Chunks()) {\n    memcpy(dst, chunk.data(), chunk.size());\n    dst += chunk.size();\n  }\n}\n\nCord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {\n  ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&\n                        \"Attempted to iterate past `end()`\");\n  Cord subcord;\n  auto constexpr method = CordzUpdateTracker::kCordReader;\n\n  if (n <= InlineRep::kMaxInline) {\n    // Range to read fits in inline data. Flatten it.\n    char* data = subcord.contents_.set_data(n);\n    while (n > current_chunk_.size()) {\n      memcpy(data, current_chunk_.data(), current_chunk_.size());\n      data += current_chunk_.size();\n      n -= current_chunk_.size();\n      ++*this;\n    }\n    memcpy(data, current_chunk_.data(), n);\n    if (n < current_chunk_.size()) {\n      RemoveChunkPrefix(n);\n    } else if (n > 0) {\n      ++*this;\n    }\n    return subcord;\n  }\n\n  if (btree_reader_) {\n    size_t chunk_size = current_chunk_.size();\n    if (n <= chunk_size && n <= kMaxBytesToCopy) {\n      subcord = Cord(current_chunk_.substr(0, n), method);\n      if (n < chunk_size) {\n        current_chunk_.remove_prefix(n);\n      } else {\n        current_chunk_ = btree_reader_.Next();\n      }\n    } else {\n      CordRep* rep;\n      current_chunk_ = btree_reader_.Read(n, chunk_size, rep);\n      subcord.contents_.EmplaceTree(rep, method);\n    }\n    bytes_remaining_ -= n;\n    return subcord;\n  }\n\n  // Short circuit if reading the entire data edge.\n  assert(current_leaf_ != nullptr);\n  if (n == current_leaf_->length) {\n    bytes_remaining_ = 0;\n    current_chunk_ = {};\n    CordRep* tree = CordRep::Ref(current_leaf_);\n    subcord.contents_.EmplaceTree(VerifyTree(tree), method);\n    return subcord;\n  }\n\n  // From this point on, we need a partial substring node.\n  // Get pointer to the underlying flat or external data payload and\n  // compute data pointer and offset into current flat or external.\n  CordRep* payload = current_leaf_->IsSubstring()\n                         ? current_leaf_->substring()->child\n                         : current_leaf_;\n  const char* data = payload->IsExternal() ? payload->external()->base\n                                           : payload->flat()->Data();\n  const size_t offset = static_cast<size_t>(current_chunk_.data() - data);\n\n  auto* tree = CordRepSubstring::Substring(payload, offset, n);\n  subcord.contents_.EmplaceTree(VerifyTree(tree), method);\n  bytes_remaining_ -= n;\n  current_chunk_.remove_prefix(n);\n  return subcord;\n}\n\nchar Cord::operator[](size_t i) const {\n  ABSL_HARDENING_ASSERT(i < size());\n  size_t offset = i;\n  const CordRep* rep = contents_.tree();\n  if (rep == nullptr) {\n    return contents_.data()[i];\n  }\n  rep = cord_internal::SkipCrcNode(rep);\n  while (true) {\n    assert(rep != nullptr);\n    assert(offset < rep->length);\n    if (rep->IsFlat()) {\n      // Get the \"i\"th character directly from the flat array.\n      return rep->flat()->Data()[offset];\n    } else if (rep->IsBtree()) {\n      return rep->btree()->GetCharacter(offset);\n    } else if (rep->IsExternal()) {\n      // Get the \"i\"th character from the external array.\n      return rep->external()->base[offset];\n    } else {\n      // This must be a substring a node, so bypass it to get to the child.\n      assert(rep->IsSubstring());\n      offset += rep->substring()->start;\n      rep = rep->substring()->child;\n    }\n  }\n}\n\nnamespace {\n\n// Tests whether the sequence of chunks beginning at `position` starts with\n// `needle`.\n//\n// REQUIRES: remaining `absl::Cord` starting at `position` is greater than or\n// equal to `needle.size()`.\nbool IsSubstringInCordAt(absl::Cord::CharIterator position,\n                         absl::string_view needle) {\n  auto haystack_chunk = absl::Cord::ChunkRemaining(position);\n  while (true) {\n    // Precondition is that `absl::Cord::ChunkRemaining(position)` is not\n    // empty. This assert will trigger if that is not true.\n    assert(!haystack_chunk.empty());\n    auto min_length = std::min(haystack_chunk.size(), needle.size());\n    if (!absl::ConsumePrefix(&needle, haystack_chunk.substr(0, min_length))) {\n      return false;\n    }\n    if (needle.empty()) {\n      return true;\n    }\n    absl::Cord::Advance(&position, min_length);\n    haystack_chunk = absl::Cord::ChunkRemaining(position);\n  }\n}\n\n}  // namespace\n\n// A few options how this could be implemented:\n// (a) Flatten the Cord and find, i.e.\n//       haystack.Flatten().find(needle)\n//     For large 'haystack' (where Cord makes sense to be used), this copies\n//     the whole 'haystack' and can be slow.\n// (b) Use std::search, i.e.\n//       std::search(haystack.char_begin(), haystack.char_end(),\n//                   needle.begin(), needle.end())\n//     This avoids the copy, but compares one byte at a time, and branches a\n//     lot every time it has to advance. It is also not possible to use\n//     std::search as is, because CharIterator is only an input iterator, not a\n//     forward iterator.\n// (c) Use string_view::find in each fragment, and specifically handle fragment\n//     boundaries.\n//\n// This currently implements option (b).\nabsl::Cord::CharIterator absl::Cord::FindImpl(CharIterator it,\n                                              absl::string_view needle) const {\n  // Ensure preconditions are met by callers first.\n\n  // Needle must not be empty.\n  assert(!needle.empty());\n  // Haystack must be at least as large as needle.\n  assert(it.chunk_iterator_.bytes_remaining_ >= needle.size());\n\n  // Cord is a sequence of chunks. To find `needle` we go chunk by chunk looking\n  // for the first char of needle, up until we have advanced `N` defined as\n  // `haystack.size() - needle.size()`. If we find the first char of needle at\n  // `P` and `P` is less than `N`, we then call `IsSubstringInCordAt` to\n  // see if this is the needle. If not, we advance to `P + 1` and try again.\n  while (it.chunk_iterator_.bytes_remaining_ >= needle.size()) {\n    auto haystack_chunk = Cord::ChunkRemaining(it);\n    assert(!haystack_chunk.empty());\n    // Look for the first char of `needle` in the current chunk.\n    auto idx = haystack_chunk.find(needle.front());\n    if (idx == absl::string_view::npos) {\n      // No potential match in this chunk, advance past it.\n      Cord::Advance(&it, haystack_chunk.size());\n      continue;\n    }\n    // We found the start of a potential match in the chunk. Advance the\n    // iterator and haystack chunk to the match the position.\n    Cord::Advance(&it, idx);\n    // Check if there is enough haystack remaining to actually have a match.\n    if (it.chunk_iterator_.bytes_remaining_ < needle.size()) {\n      break;\n    }\n    // Check if this is `needle`.\n    if (IsSubstringInCordAt(it, needle)) {\n      return it;\n    }\n    // No match, increment the iterator for the next attempt.\n    Cord::Advance(&it, 1);\n  }\n  // If we got here, we did not find `needle`.\n  return char_end();\n}\n\nabsl::Cord::CharIterator absl::Cord::Find(absl::string_view needle) const {\n  if (needle.empty()) {\n    return char_begin();\n  }\n  if (needle.size() > size()) {\n    return char_end();\n  }\n  if (needle.size() == size()) {\n    return *this == needle ? char_begin() : char_end();\n  }\n  return FindImpl(char_begin(), needle);\n}\n\nnamespace {\n\n// Tests whether the sequence of chunks beginning at `haystack` starts with the\n// sequence of chunks beginning at `needle_begin` and extending to `needle_end`.\n//\n// REQUIRES: remaining `absl::Cord` starting at `position` is greater than or\n// equal to `needle_end - needle_begin` and `advance`.\nbool IsSubcordInCordAt(absl::Cord::CharIterator haystack,\n                       absl::Cord::CharIterator needle_begin,\n                       absl::Cord::CharIterator needle_end) {\n  while (needle_begin != needle_end) {\n    auto haystack_chunk = absl::Cord::ChunkRemaining(haystack);\n    assert(!haystack_chunk.empty());\n    auto needle_chunk = absl::Cord::ChunkRemaining(needle_begin);\n    auto min_length = std::min(haystack_chunk.size(), needle_chunk.size());\n    if (haystack_chunk.substr(0, min_length) !=\n        needle_chunk.substr(0, min_length)) {\n      return false;\n    }\n    absl::Cord::Advance(&haystack, min_length);\n    absl::Cord::Advance(&needle_begin, min_length);\n  }\n  return true;\n}\n\n// Tests whether the sequence of chunks beginning at `position` starts with the\n// cord `needle`.\n//\n// REQUIRES: remaining `absl::Cord` starting at `position` is greater than or\n// equal to `needle.size()`.\nbool IsSubcordInCordAt(absl::Cord::CharIterator position,\n                       const absl::Cord& needle) {\n  return IsSubcordInCordAt(position, needle.char_begin(), needle.char_end());\n}\n\n}  // namespace\n\nabsl::Cord::CharIterator absl::Cord::Find(const absl::Cord& needle) const {\n  if (needle.empty()) {\n    return char_begin();\n  }\n  const auto needle_size = needle.size();\n  if (needle_size > size()) {\n    return char_end();\n  }\n  if (needle_size == size()) {\n    return *this == needle ? char_begin() : char_end();\n  }\n  const auto needle_chunk = Cord::ChunkRemaining(needle.char_begin());\n  auto haystack_it = char_begin();\n  while (true) {\n    haystack_it = FindImpl(haystack_it, needle_chunk);\n    if (haystack_it == char_end() ||\n        haystack_it.chunk_iterator_.bytes_remaining_ < needle_size) {\n      break;\n    }\n    // We found the first chunk of `needle` at `haystack_it` but not the entire\n    // subcord. Advance past the first chunk and check for the remainder.\n    auto haystack_advanced_it = haystack_it;\n    auto needle_it = needle.char_begin();\n    Cord::Advance(&haystack_advanced_it, needle_chunk.size());\n    Cord::Advance(&needle_it, needle_chunk.size());\n    if (IsSubcordInCordAt(haystack_advanced_it, needle_it, needle.char_end())) {\n      return haystack_it;\n    }\n    Cord::Advance(&haystack_it, 1);\n    if (haystack_it.chunk_iterator_.bytes_remaining_ < needle_size) {\n      break;\n    }\n    if (haystack_it.chunk_iterator_.bytes_remaining_ == needle_size) {\n      // Special case, if there is exactly `needle_size` bytes remaining, the\n      // subcord is either at `haystack_it` or not at all.\n      if (IsSubcordInCordAt(haystack_it, needle)) {\n        return haystack_it;\n      }\n      break;\n    }\n  }\n  return char_end();\n}\n\nbool Cord::Contains(absl::string_view rhs) const {\n  return rhs.empty() || Find(rhs) != char_end();\n}\n\nbool Cord::Contains(const absl::Cord& rhs) const {\n  return rhs.empty() || Find(rhs) != char_end();\n}\n\nabsl::string_view Cord::FlattenSlowPath() {\n  assert(contents_.is_tree());\n  size_t total_size = size();\n  CordRep* new_rep;\n  char* new_buffer;\n\n  // Try to put the contents into a new flat rep. If they won't fit in the\n  // biggest possible flat node, use an external rep instead.\n  if (total_size <= kMaxFlatLength) {\n    new_rep = CordRepFlat::New(total_size);\n    new_rep->length = total_size;\n    new_buffer = new_rep->flat()->Data();\n    CopyToArraySlowPath(new_buffer);\n  } else {\n    new_buffer = std::allocator<char>().allocate(total_size);\n    CopyToArraySlowPath(new_buffer);\n    new_rep = absl::cord_internal::NewExternalRep(\n        absl::string_view(new_buffer, total_size), [](absl::string_view s) {\n          std::allocator<char>().deallocate(const_cast<char*>(s.data()),\n                                            s.size());\n        });\n  }\n  CordzUpdateScope scope(contents_.cordz_info(), CordzUpdateTracker::kFlatten);\n  CordRep::Unref(contents_.as_tree());\n  contents_.SetTree(new_rep, scope);\n  return absl::string_view(new_buffer, total_size);\n}\n\n/* static */ bool Cord::GetFlatAux(CordRep* absl_nonnull rep,\n                                   absl::string_view* absl_nonnull fragment) {\n  assert(rep != nullptr);\n  if (rep->length == 0) {\n    *fragment = absl::string_view();\n    return true;\n  }\n  rep = cord_internal::SkipCrcNode(rep);\n  if (rep->IsFlat()) {\n    *fragment = absl::string_view(rep->flat()->Data(), rep->length);\n    return true;\n  } else if (rep->IsExternal()) {\n    *fragment = absl::string_view(rep->external()->base, rep->length);\n    return true;\n  } else if (rep->IsBtree()) {\n    return rep->btree()->IsFlat(fragment);\n  } else if (rep->IsSubstring()) {\n    CordRep* child = rep->substring()->child;\n    if (child->IsFlat()) {\n      *fragment = absl::string_view(\n          child->flat()->Data() + rep->substring()->start, rep->length);\n      return true;\n    } else if (child->IsExternal()) {\n      *fragment = absl::string_view(\n          child->external()->base + rep->substring()->start, rep->length);\n      return true;\n    } else if (child->IsBtree()) {\n      return child->btree()->IsFlat(rep->substring()->start, rep->length,\n                                    fragment);\n    }\n  }\n  return false;\n}\n\n/* static */ void Cord::ForEachChunkAux(\n    absl::cord_internal::CordRep* absl_nonnull rep,\n    absl::FunctionRef<void(absl::string_view)> callback) {\n  assert(rep != nullptr);\n  if (rep->length == 0) return;\n  rep = cord_internal::SkipCrcNode(rep);\n\n  if (rep->IsBtree()) {\n    ChunkIterator it(rep), end;\n    while (it != end) {\n      callback(*it);\n      ++it;\n    }\n    return;\n  }\n\n  // This is a leaf node, so invoke our callback.\n  absl::cord_internal::CordRep* current_node = cord_internal::SkipCrcNode(rep);\n  absl::string_view chunk;\n  bool success = GetFlatAux(current_node, &chunk);\n  assert(success);\n  if (success) {\n    callback(chunk);\n  }\n}\n\nstatic void DumpNode(CordRep* absl_nonnull nonnull_rep, bool include_data,\n                     std::ostream* absl_nonnull os, int indent) {\n  CordRep* rep = nonnull_rep;\n  const int kIndentStep = 1;\n  for (;;) {\n    *os << std::setw(3) << (rep == nullptr ? 0 : rep->refcount.Get());\n    *os << \" \" << std::setw(7) << (rep == nullptr ? 0 : rep->length);\n    *os << \" [\";\n    if (include_data) *os << static_cast<void*>(rep);\n    *os << \"]\";\n    *os << \" \" << std::setw(indent) << \"\";\n    bool leaf = false;\n    if (rep == nullptr) {\n      *os << \"NULL\\n\";\n      leaf = true;\n    } else if (rep->IsCrc()) {\n      *os << \"CRC crc=\" << rep->crc()->crc_cord_state.Checksum() << \"\\n\";\n      indent += kIndentStep;\n      rep = rep->crc()->child;\n    } else if (rep->IsSubstring()) {\n      *os << \"SUBSTRING @ \" << rep->substring()->start << \"\\n\";\n      indent += kIndentStep;\n      rep = rep->substring()->child;\n    } else {  // Leaf or ring\n      leaf = true;\n      if (rep->IsExternal()) {\n        *os << \"EXTERNAL [\";\n        if (include_data)\n          *os << absl::CEscape(\n              absl::string_view(rep->external()->base, rep->length));\n        *os << \"]\\n\";\n      } else if (rep->IsFlat()) {\n        *os << \"FLAT cap=\" << rep->flat()->Capacity() << \" [\";\n        if (include_data)\n          *os << absl::CEscape(\n              absl::string_view(rep->flat()->Data(), rep->length));\n        *os << \"]\\n\";\n      } else {\n        CordRepBtree::Dump(rep, /*label=*/\"\", include_data, *os);\n      }\n    }\n    if (leaf) {\n      break;\n    }\n  }\n}\n\nstatic std::string ReportError(CordRep* absl_nonnull root,\n                               CordRep* absl_nonnull node) {\n  std::ostringstream buf;\n  buf << \"Error at node \" << node << \" in:\";\n  DumpNode(root, true, &buf);\n  return buf.str();\n}\n\nstatic bool VerifyNode(CordRep* absl_nonnull root,\n                       CordRep* absl_nonnull start_node) {\n  absl::InlinedVector<CordRep* absl_nonnull, 2> worklist;\n  worklist.push_back(start_node);\n  do {\n    CordRep* node = worklist.back();\n    worklist.pop_back();\n\n    ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node));\n    if (node != root) {\n      ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));\n      ABSL_INTERNAL_CHECK(!node->IsCrc(), ReportError(root, node));\n    }\n\n    if (node->IsFlat()) {\n      ABSL_INTERNAL_CHECK(node->length <= node->flat()->Capacity(),\n                          ReportError(root, node));\n    } else if (node->IsExternal()) {\n      ABSL_INTERNAL_CHECK(node->external()->base != nullptr,\n                          ReportError(root, node));\n    } else if (node->IsSubstring()) {\n      ABSL_INTERNAL_CHECK(\n          node->substring()->start < node->substring()->child->length,\n          ReportError(root, node));\n      ABSL_INTERNAL_CHECK(node->substring()->start + node->length <=\n                              node->substring()->child->length,\n                          ReportError(root, node));\n    } else if (node->IsCrc()) {\n      ABSL_INTERNAL_CHECK(\n          node->crc()->child != nullptr || node->crc()->length == 0,\n          ReportError(root, node));\n      if (node->crc()->child != nullptr) {\n        ABSL_INTERNAL_CHECK(node->crc()->length == node->crc()->child->length,\n                            ReportError(root, node));\n        worklist.push_back(node->crc()->child);\n      }\n    }\n  } while (!worklist.empty());\n  return true;\n}\n\nstd::ostream& operator<<(std::ostream& out, const Cord& cord) {\n  for (absl::string_view chunk : cord.Chunks()) {\n    out.write(chunk.data(), static_cast<std::streamsize>(chunk.size()));\n  }\n  return out;\n}\n\nnamespace strings_internal {\nsize_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }\nsize_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }\nsize_t CordTestAccess::FlatTagToLength(uint8_t tag) {\n  return cord_internal::TagToLength(tag);\n}\nuint8_t CordTestAccess::LengthToTag(size_t s) {\n  ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat(\"Invalid length \", s));\n  return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);\n}\nsize_t CordTestAccess::SizeofCordRepExternal() {\n  return sizeof(CordRepExternal);\n}\nsize_t CordTestAccess::SizeofCordRepSubstring() {\n  return sizeof(CordRepSubstring);\n}\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/cord.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: cord.h\n// -----------------------------------------------------------------------------\n//\n// This file defines the `absl::Cord` data structure and operations on that data\n// structure. A Cord is a string-like sequence of characters optimized for\n// specific use cases. Unlike a `std::string`, which stores an array of\n// contiguous characters, Cord data is stored in a structure consisting of\n// separate, reference-counted \"chunks.\"\n//\n// Because a Cord consists of these chunks, data can be added to or removed from\n// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a\n// `std::string`, a Cord can therefore accommodate data that changes over its\n// lifetime, though it's not quite \"mutable\"; it can change only in the\n// attachment, detachment, or rearrangement of chunks of its constituent data.\n//\n// A Cord provides some benefit over `std::string` under the following (albeit\n// narrow) circumstances:\n//\n//   * Cord data is designed to grow and shrink over a Cord's lifetime. Cord\n//     provides efficient insertions and deletions at the start and end of the\n//     character sequences, avoiding copies in those cases. Static data should\n//     generally be stored as strings.\n//   * External memory consisting of string-like data can be directly added to\n//     a Cord without requiring copies or allocations.\n//   * Cord data may be shared and copied cheaply. Cord provides a copy-on-write\n//     implementation and cheap sub-Cord operations. Copying a Cord is an O(1)\n//     operation.\n//\n// As a consequence to the above, Cord data is generally large. Small data\n// should generally use strings, as construction of a Cord requires some\n// overhead. Small Cords (<= 15 bytes) are represented inline, but most small\n// Cords are expected to grow over their lifetimes.\n//\n// Note that because a Cord is made up of separate chunked data, random access\n// to character data within a Cord is slower than within a `std::string`.\n//\n// Thread Safety\n//\n// Cord has the same thread-safety properties as many other types like\n// std::string, std::vector<>, int, etc -- it is thread-compatible. In\n// particular, if threads do not call non-const methods, then it is safe to call\n// const methods without synchronization. Copying a Cord produces a new instance\n// that can be used concurrently with the original in arbitrary ways.\n\n#ifndef ABSL_STRINGS_CORD_H_\n#define ABSL_STRINGS_CORD_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <iosfwd>\n#include <iterator>\n#include <optional>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/crc/internal/crc_cord_state.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/cord_analysis.h\"\n#include \"absl/strings/cord_buffer.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_btree_reader.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/strings/internal/cordz_update_scope.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/strings/internal/string_constant.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/compare.h\"\n#include \"absl/types/optional.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nclass Cord;\nclass CordTestPeer;\ntemplate <typename Releaser>\nCord MakeCordFromExternal(absl::string_view, Releaser&&);\nvoid CopyCordToString(const Cord& src, std::string* absl_nonnull dst);\nvoid AppendCordToString(const Cord& src, std::string* absl_nonnull dst);\n\n// Cord memory accounting modes\nenum class CordMemoryAccounting {\n  // Counts the *approximate* number of bytes held in full or in part by this\n  // Cord (which may not remain the same between invocations). Cords that share\n  // memory could each be \"charged\" independently for the same shared memory.\n  // See also comment on `kTotalMorePrecise` on internally shared memory.\n  kTotal,\n\n  // Counts the *approximate* number of bytes held in full or in part by this\n  // Cord for the distinct memory held by this cord. This option is similar\n  // to `kTotal`, except that if the cord has multiple references to the same\n  // memory, that memory is only counted once.\n  //\n  // For example:\n  //   absl::Cord cord;\n  //   cord.Append(some_other_cord);\n  //   cord.Append(some_other_cord);\n  //   // Counts `some_other_cord` twice:\n  //   cord.EstimatedMemoryUsage(kTotal);\n  //   // Counts `some_other_cord` once:\n  //   cord.EstimatedMemoryUsage(kTotalMorePrecise);\n  //\n  // The `kTotalMorePrecise` number is more expensive to compute as it requires\n  // deduplicating all memory references. Applications should prefer to use\n  // `kFairShare` or `kTotal` unless they really need a more precise estimate\n  // on \"how much memory is potentially held / kept alive by this cord?\"\n  kTotalMorePrecise,\n\n  // Counts the *approximate* number of bytes held in full or in part by this\n  // Cord weighted by the sharing ratio of that data. For example, if some data\n  // edge is shared by 4 different Cords, then each cord is attributed 1/4th of\n  // the total memory usage as a 'fair share' of the total memory usage.\n  kFairShare,\n};\n\n// Cord\n//\n// A Cord is a sequence of characters, designed to be more efficient than a\n// `std::string` in certain circumstances: namely, large string data that needs\n// to change over its lifetime or shared, especially when such data is shared\n// across API boundaries.\n//\n// A Cord stores its character data in a structure that allows efficient prepend\n// and append operations. This makes a Cord useful for large string data sent\n// over in a wire format that may need to be prepended or appended at some point\n// during the data exchange (e.g. HTTP, protocol buffers). For example, a\n// Cord is useful for storing an HTTP request, and prepending an HTTP header to\n// such a request.\n//\n// Cords should not be used for storing general string data, however. They\n// require overhead to construct and are slower than strings for random access.\n//\n// The Cord API provides the following common API operations:\n//\n// * Create or assign Cords out of existing string data, memory, or other Cords\n// * Append and prepend data to an existing Cord\n// * Create new Sub-Cords from existing Cord data\n// * Swap Cord data and compare Cord equality\n// * Write out Cord data by constructing a `std::string`\n//\n// Additionally, the API provides iterator utilities to iterate through Cord\n// data via chunks or character bytes.\n//\nclass Cord {\n private:\n  template <typename T>\n  using EnableIfString =\n      absl::enable_if_t<std::is_same<T, std::string>::value, int>;\n\n public:\n  // Cord::Cord() Constructors.\n\n  // Creates an empty Cord.\n  constexpr Cord() noexcept;\n\n  // Creates a Cord from an existing Cord. Cord is copyable and efficiently\n  // movable. The moved-from state is valid but unspecified.\n  Cord(const Cord& src);\n  Cord(Cord&& src) noexcept;\n  Cord& operator=(const Cord& x);\n  Cord& operator=(Cord&& x) noexcept;\n\n  // Creates a Cord from a `src` string. This constructor is marked explicit to\n  // prevent implicit Cord constructions from arguments convertible to an\n  // `absl::string_view`.\n  explicit Cord(absl::string_view src);\n  Cord& operator=(absl::string_view src);\n\n  // Creates a Cord from a `std::string&&` rvalue. These constructors are\n  // templated to avoid ambiguities for types that are convertible to both\n  // `absl::string_view` and `std::string`, such as `const char*`.\n  template <typename T, EnableIfString<T> = 0>\n  explicit Cord(T&& src);\n  template <typename T, EnableIfString<T> = 0>\n  Cord& operator=(T&& src);\n\n  // Cord::~Cord()\n  //\n  // Destructs the Cord.\n  ~Cord() {\n    if (contents_.is_tree()) DestroyCordSlow();\n  }\n\n  // MakeCordFromExternal()\n  //\n  // Creates a Cord that takes ownership of external string memory. The\n  // contents of `data` are not copied to the Cord; instead, the external\n  // memory is added to the Cord and reference-counted. This data may not be\n  // changed for the life of the Cord, though it may be prepended or appended\n  // to.\n  //\n  // `MakeCordFromExternal()` takes a callable \"releaser\" that is invoked when\n  // the reference count for `data` reaches zero. As noted above, this data must\n  // remain live until the releaser is invoked. The callable releaser also must:\n  //\n  //   * be move constructible\n  //   * support `void operator()(absl::string_view)` or `void operator()()`\n  //\n  // Example:\n  //\n  // Cord MakeCord(BlockPool* pool) {\n  //   Block* block = pool->NewBlock();\n  //   FillBlock(block);\n  //   return absl::MakeCordFromExternal(\n  //       block->ToStringView(),\n  //       [pool, block](absl::string_view v) {\n  //         pool->FreeBlock(block, v);\n  //       });\n  // }\n  //\n  // WARNING: Because a Cord can be reference-counted, it's likely a bug if your\n  // releaser doesn't do anything. For example, consider the following:\n  //\n  // void Foo(const char* buffer, int len) {\n  //   auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),\n  //                                       [](absl::string_view) {});\n  //\n  //   // BUG: If Bar() copies its cord for any reason, including keeping a\n  //   // substring of it, the lifetime of buffer might be extended beyond\n  //   // when Foo() returns.\n  //   Bar(c);\n  // }\n  template <typename Releaser>\n  friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);\n\n  // Cord::Clear()\n  //\n  // Releases the Cord data. Any nodes that share data with other Cords, if\n  // applicable, will have their reference counts reduced by 1.\n  ABSL_ATTRIBUTE_REINITIALIZES void Clear();\n\n  // Cord::Append()\n  //\n  // Appends data to the Cord, which may come from another Cord or other string\n  // data.\n  void Append(const Cord& src);\n  void Append(Cord&& src);\n  void Append(absl::string_view src);\n  template <typename T, EnableIfString<T> = 0>\n  void Append(T&& src);\n\n  // Appends `buffer` to this cord, unless `buffer` has a zero length in which\n  // case this method has no effect on this cord instance.\n  // This method is guaranteed to consume `buffer`.\n  void Append(CordBuffer buffer);\n\n  // Returns a CordBuffer, re-using potential existing capacity in this cord.\n  //\n  // Cord instances may have additional unused capacity in the last (or first)\n  // nodes of the underlying tree to facilitate amortized growth. This method\n  // allows applications to explicitly use this spare capacity if available,\n  // or create a new CordBuffer instance otherwise.\n  // If this cord has a final non-shared node with at least `min_capacity`\n  // available, then this method will return that buffer including its data\n  // contents. I.e.; the returned buffer will have a non-zero length, and\n  // a capacity of at least `buffer.length + min_capacity`. Otherwise, this\n  // method will return `CordBuffer::CreateWithDefaultLimit(capacity)`.\n  //\n  // Below an example of using GetAppendBuffer. Notice that in this example we\n  // use `GetAppendBuffer()` only on the first iteration. As we know nothing\n  // about any initial extra capacity in `cord`, we may be able to use the extra\n  // capacity. But as we add new buffers with fully utilized contents after that\n  // we avoid calling `GetAppendBuffer()` on subsequent iterations: while this\n  // works fine, it results in an unnecessary inspection of cord contents:\n  //\n  //   void AppendRandomDataToCord(absl::Cord &cord, size_t n) {\n  //     bool first = true;\n  //     while (n > 0) {\n  //       CordBuffer buffer = first ? cord.GetAppendBuffer(n)\n  //                                 : CordBuffer::CreateWithDefaultLimit(n);\n  //       absl::Span<char> data = buffer.available_up_to(n);\n  //       FillRandomValues(data.data(), data.size());\n  //       buffer.IncreaseLengthBy(data.size());\n  //       cord.Append(std::move(buffer));\n  //       n -= data.size();\n  //       first = false;\n  //     }\n  //   }\n  CordBuffer GetAppendBuffer(size_t capacity, size_t min_capacity = 16);\n\n  // Returns a CordBuffer, re-using potential existing capacity in this cord.\n  //\n  // This function is identical to `GetAppendBuffer`, except that in the case\n  // where a new `CordBuffer` is allocated, it is allocated using the provided\n  // custom limit instead of the default limit. `GetAppendBuffer` will default\n  // to `CordBuffer::CreateWithDefaultLimit(capacity)` whereas this method\n  // will default to `CordBuffer::CreateWithCustomLimit(block_size, capacity)`.\n  // This method is equivalent to `GetAppendBuffer` if `block_size` is zero.\n  // See the documentation for `CreateWithCustomLimit` for more details on the\n  // restrictions and legal values for `block_size`.\n  CordBuffer GetCustomAppendBuffer(size_t block_size, size_t capacity,\n                                   size_t min_capacity = 16);\n\n  // Cord::Prepend()\n  //\n  // Prepends data to the Cord, which may come from another Cord or other string\n  // data.\n  void Prepend(const Cord& src);\n  void Prepend(absl::string_view src);\n  template <typename T, EnableIfString<T> = 0>\n  void Prepend(T&& src);\n\n  // Prepends `buffer` to this cord, unless `buffer` has a zero length in which\n  // case this method has no effect on this cord instance.\n  // This method is guaranteed to consume `buffer`.\n  void Prepend(CordBuffer buffer);\n\n  // Cord::RemovePrefix()\n  //\n  // Removes the first `n` bytes of a Cord.\n  void RemovePrefix(size_t n);\n  void RemoveSuffix(size_t n);\n\n  // Cord::Subcord()\n  //\n  // Returns a new Cord representing the subrange [pos, pos + new_size) of\n  // *this. If pos >= size(), the result is empty(). If\n  // (pos + new_size) >= size(), the result is the subrange [pos, size()).\n  Cord Subcord(size_t pos, size_t new_size) const;\n\n  // Cord::swap()\n  //\n  // Swaps the contents of the Cord with `other`.\n  void swap(Cord& other) noexcept;\n\n  // swap()\n  //\n  // Swaps the contents of two Cords.\n  friend void swap(Cord& x, Cord& y) noexcept { x.swap(y); }\n\n  // Cord::size()\n  //\n  // Returns the size of the Cord.\n  size_t size() const;\n\n  // Cord::empty()\n  //\n  // Determines whether the given Cord is empty, returning `true` if so.\n  bool empty() const;\n\n  // Cord::EstimatedMemoryUsage()\n  //\n  // Returns the *approximate* number of bytes held by this cord.\n  // See CordMemoryAccounting for more information on the accounting method.\n  size_t EstimatedMemoryUsage(CordMemoryAccounting accounting_method =\n                                  CordMemoryAccounting::kTotal) const;\n\n  // Cord::Compare()\n  //\n  // Compares 'this' Cord with rhs. This function and its relatives treat Cords\n  // as sequences of unsigned bytes. The comparison is a straightforward\n  // lexicographic comparison. `Cord::Compare()` returns values as follows:\n  //\n  //   -1  'this' Cord is smaller\n  //    0  two Cords are equal\n  //    1  'this' Cord is larger\n  int Compare(absl::string_view rhs) const;\n  int Compare(const Cord& rhs) const;\n\n  // Cord::StartsWith()\n  //\n  // Determines whether the Cord starts with the passed string data `rhs`.\n  bool StartsWith(const Cord& rhs) const;\n  bool StartsWith(absl::string_view rhs) const;\n\n  // Cord::EndsWith()\n  //\n  // Determines whether the Cord ends with the passed string data `rhs`.\n  bool EndsWith(absl::string_view rhs) const;\n  bool EndsWith(const Cord& rhs) const;\n\n  // Cord::Contains()\n  //\n  // Determines whether the Cord contains the passed string data `rhs`.\n  bool Contains(absl::string_view rhs) const;\n  bool Contains(const Cord& rhs) const;\n\n  // Cord::operator std::string()\n  //\n  // Converts a Cord into a `std::string()`. This operator is marked explicit to\n  // prevent unintended Cord usage in functions that take a string.\n  explicit operator std::string() const;\n\n  // CopyCordToString()\n  //\n  // Copies the contents of a `src` Cord into a `*dst` string.\n  //\n  // This function optimizes the case of reusing the destination string since it\n  // can reuse previously allocated capacity. However, this function does not\n  // guarantee that pointers previously returned by `dst->data()` remain valid\n  // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new\n  // object, prefer to simply use the conversion operator to `std::string`.\n  friend void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);\n\n  // AppendCordToString()\n  //\n  // Appends the contents of a `src` Cord to a `*dst` string.\n  //\n  // This function optimizes the case of appending to a non-empty destination\n  // string. If `*dst` already has capacity to store the contents of the cord,\n  // this function does not invalidate pointers previously returned by\n  // `dst->data()`. If `*dst` is a new object, prefer to simply use the\n  // conversion operator to `std::string`.\n  friend void AppendCordToString(const Cord& src,\n                                 std::string* absl_nonnull dst);\n\n  class CharIterator;\n\n  //----------------------------------------------------------------------------\n  // Cord::ChunkIterator\n  //----------------------------------------------------------------------------\n  //\n  // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its\n  // Cord. Such iteration allows you to perform non-const operations on the data\n  // of a Cord without modifying it.\n  //\n  // Generally, you do not instantiate a `Cord::ChunkIterator` directly;\n  // instead, you create one implicitly through use of the `Cord::Chunks()`\n  // member function.\n  //\n  // The `Cord::ChunkIterator` has the following properties:\n  //\n  //   * The iterator is invalidated after any non-const operation on the\n  //     Cord object over which it iterates.\n  //   * The `string_view` returned by dereferencing a valid, non-`end()`\n  //     iterator is guaranteed to be non-empty.\n  //   * Two `ChunkIterator` objects can be compared equal if and only if they\n  //     remain valid and iterate over the same Cord.\n  //   * The iterator in this case is a proxy iterator; the `string_view`\n  //     returned by the iterator does not live inside the Cord, and its\n  //     lifetime is limited to the lifetime of the iterator itself. To help\n  //     prevent lifetime issues, `ChunkIterator::reference` is not a true\n  //     reference type and is equivalent to `value_type`.\n  //   * The iterator keeps state that can grow for Cords that contain many\n  //     nodes and are imbalanced due to sharing. Prefer to pass this type by\n  //     const reference instead of by value.\n  class ChunkIterator {\n   public:\n    using iterator_category = std::input_iterator_tag;\n    using value_type = absl::string_view;\n    using difference_type = ptrdiff_t;\n    using pointer = const value_type* absl_nonnull;\n    using reference = value_type;\n\n    ChunkIterator() = default;\n\n    ChunkIterator& operator++();\n    ChunkIterator operator++(int);\n    bool operator==(const ChunkIterator& other) const;\n    bool operator!=(const ChunkIterator& other) const;\n    reference operator*() const;\n    pointer operator->() const;\n\n    friend class Cord;\n    friend class CharIterator;\n\n   private:\n    using CordRep = absl::cord_internal::CordRep;\n    using CordRepBtree = absl::cord_internal::CordRepBtree;\n    using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;\n\n    // Constructs a `begin()` iterator from `tree`.\n    explicit ChunkIterator(cord_internal::CordRep* absl_nonnull tree);\n\n    // Constructs a `begin()` iterator from `cord`.\n    explicit ChunkIterator(const Cord* absl_nonnull cord);\n\n    // Initializes this instance from a tree. Invoked by constructors.\n    void InitTree(cord_internal::CordRep* absl_nonnull tree);\n\n    // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than\n    // `current_chunk_.size()`.\n    void RemoveChunkPrefix(size_t n);\n    Cord AdvanceAndReadBytes(size_t n);\n    void AdvanceBytes(size_t n);\n\n    // Btree specific operator++\n    ChunkIterator& AdvanceBtree();\n    void AdvanceBytesBtree(size_t n);\n\n    // A view into bytes of the current `CordRep`. It may only be a view to a\n    // suffix of bytes if this is being used by `CharIterator`.\n    absl::string_view current_chunk_;\n    // The current leaf, or `nullptr` if the iterator points to short data.\n    // If the current chunk is a substring node, current_leaf_ points to the\n    // underlying flat or external node.\n    absl::cord_internal::CordRep* absl_nullable current_leaf_ = nullptr;\n    // The number of bytes left in the `Cord` over which we are iterating.\n    size_t bytes_remaining_ = 0;\n\n    // Cord reader for cord btrees. Empty if not traversing a btree.\n    CordRepBtreeReader btree_reader_;\n  };\n\n  // Cord::chunk_begin()\n  //\n  // Returns an iterator to the first chunk of the `Cord`.\n  //\n  // Generally, prefer using `Cord::Chunks()` within a range-based for loop for\n  // iterating over the chunks of a Cord. This method may be useful for getting\n  // a `ChunkIterator` where range-based for-loops are not useful.\n  //\n  // Example:\n  //\n  //   absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,\n  //                                         absl::string_view s) {\n  //     return std::find(c.chunk_begin(), c.chunk_end(), s);\n  //   }\n  ChunkIterator chunk_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  // Cord::chunk_end()\n  //\n  // Returns an iterator one increment past the last chunk of the `Cord`.\n  //\n  // Generally, prefer using `Cord::Chunks()` within a range-based for loop for\n  // iterating over the chunks of a Cord. This method may be useful for getting\n  // a `ChunkIterator` where range-based for-loops may not be available.\n  ChunkIterator chunk_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  //----------------------------------------------------------------------------\n  // Cord::ChunkRange\n  //----------------------------------------------------------------------------\n  //\n  // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,\n  // producing an iterator which can be used within a range-based for loop.\n  // Construction of a `ChunkRange` will return an iterator pointing to the\n  // first chunk of the Cord. Generally, do not construct a `ChunkRange`\n  // directly; instead, prefer to use the `Cord::Chunks()` method.\n  //\n  // Implementation note: `ChunkRange` is simply a convenience wrapper over\n  // `Cord::chunk_begin()` and `Cord::chunk_end()`.\n  class ChunkRange {\n   public:\n    // Fulfill minimum c++ container requirements [container.requirements]\n    // These (partial) container type definitions allow ChunkRange to be used\n    // in various utilities expecting a subset of [container.requirements].\n    // For example, the below enables using `::testing::ElementsAre(...)`\n    using value_type = absl::string_view;\n    using reference = value_type&;\n    using const_reference = const value_type&;\n    using iterator = ChunkIterator;\n    using const_iterator = ChunkIterator;\n\n    explicit ChunkRange(const Cord* absl_nonnull cord) : cord_(cord) {}\n\n    ChunkIterator begin() const;\n    ChunkIterator end() const;\n\n   private:\n    const Cord* absl_nonnull cord_;\n  };\n\n  // Cord::Chunks()\n  //\n  // Returns a `Cord::ChunkRange` for iterating over the chunks of a `Cord` with\n  // a range-based for-loop. For most iteration tasks on a Cord, use\n  // `Cord::Chunks()` to retrieve this iterator.\n  //\n  // Example:\n  //\n  //   void ProcessChunks(const Cord& cord) {\n  //     for (absl::string_view chunk : cord.Chunks()) { ... }\n  //   }\n  //\n  // Note that the ordinary caveats of temporary lifetime extension apply:\n  //\n  //   void Process() {\n  //     for (absl::string_view chunk : CordFactory().Chunks()) {\n  //       // The temporary Cord returned by CordFactory has been destroyed!\n  //     }\n  //   }\n  ChunkRange Chunks() const ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  //----------------------------------------------------------------------------\n  // Cord::CharIterator\n  //----------------------------------------------------------------------------\n  //\n  // A `Cord::CharIterator` allows iteration over the constituent characters of\n  // a `Cord`.\n  //\n  // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,\n  // you create one implicitly through use of the `Cord::Chars()` member\n  // function.\n  //\n  // A `Cord::CharIterator` has the following properties:\n  //\n  //   * The iterator is invalidated after any non-const operation on the\n  //     Cord object over which it iterates.\n  //   * Two `CharIterator` objects can be compared equal if and only if they\n  //     remain valid and iterate over the same Cord.\n  //   * The iterator keeps state that can grow for Cords that contain many\n  //     nodes and are imbalanced due to sharing. Prefer to pass this type by\n  //     const reference instead of by value.\n  //   * This type cannot act as a forward iterator because a `Cord` can reuse\n  //     sections of memory. This fact violates the requirement for forward\n  //     iterators to compare equal if dereferencing them returns the same\n  //     object.\n  class CharIterator {\n   public:\n    using iterator_category = std::input_iterator_tag;\n    using value_type = char;\n    using difference_type = ptrdiff_t;\n    using pointer = const char* absl_nonnull;\n    using reference = const char&;\n\n    CharIterator() = default;\n\n    CharIterator& operator++();\n    CharIterator operator++(int);\n    bool operator==(const CharIterator& other) const;\n    bool operator!=(const CharIterator& other) const;\n    reference operator*() const;\n\n    friend Cord;\n\n   private:\n    explicit CharIterator(const Cord* absl_nonnull cord)\n        : chunk_iterator_(cord) {}\n\n    ChunkIterator chunk_iterator_;\n  };\n\n  // Cord::AdvanceAndRead()\n  //\n  // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes\n  // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the\n  // number of bytes within the Cord; otherwise, behavior is undefined. It is\n  // valid to pass `char_end()` and `0`.\n  static Cord AdvanceAndRead(CharIterator* absl_nonnull it, size_t n_bytes);\n\n  // Cord::Advance()\n  //\n  // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than\n  // or equal to the number of bytes remaining within the Cord; otherwise,\n  // behavior is undefined. It is valid to pass `char_end()` and `0`.\n  static void Advance(CharIterator* absl_nonnull it, size_t n_bytes);\n\n  // Cord::ChunkRemaining()\n  //\n  // Returns the longest contiguous view starting at the iterator's position.\n  //\n  // `it` must be dereferenceable.\n  static absl::string_view ChunkRemaining(const CharIterator& it);\n\n  // Cord::Distance()\n  //\n  // Returns the distance between `first` and `last`, as if\n  // `std::distance(first, last)` was called.\n  static ptrdiff_t Distance(const CharIterator& first,\n                            const CharIterator& last);\n\n  // Cord::char_begin()\n  //\n  // Returns an iterator to the first character of the `Cord`.\n  //\n  // Generally, prefer using `Cord::Chars()` within a range-based for loop for\n  // iterating over the chunks of a Cord. This method may be useful for getting\n  // a `CharIterator` where range-based for-loops may not be available.\n  CharIterator char_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  // Cord::char_end()\n  //\n  // Returns an iterator to one past the last character of the `Cord`.\n  //\n  // Generally, prefer using `Cord::Chars()` within a range-based for loop for\n  // iterating over the chunks of a Cord. This method may be useful for getting\n  // a `CharIterator` where range-based for-loops are not useful.\n  CharIterator char_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  // Cord::CharRange\n  //\n  // `CharRange` is a helper class for iterating over the characters of a\n  // producing an iterator which can be used within a range-based for loop.\n  // Construction of a `CharRange` will return an iterator pointing to the first\n  // character of the Cord. Generally, do not construct a `CharRange` directly;\n  // instead, prefer to use the `Cord::Chars()` method shown below.\n  //\n  // Implementation note: `CharRange` is simply a convenience wrapper over\n  // `Cord::char_begin()` and `Cord::char_end()`.\n  class CharRange {\n   public:\n    // Fulfill minimum c++ container requirements [container.requirements]\n    // These (partial) container type definitions allow CharRange to be used\n    // in various utilities expecting a subset of [container.requirements].\n    // For example, the below enables using `::testing::ElementsAre(...)`\n    using value_type = char;\n    using reference = value_type&;\n    using const_reference = const value_type&;\n    using iterator = CharIterator;\n    using const_iterator = CharIterator;\n\n    explicit CharRange(const Cord* absl_nonnull cord) : cord_(cord) {}\n\n    CharIterator begin() const;\n    CharIterator end() const;\n\n   private:\n    const Cord* absl_nonnull cord_;\n  };\n\n  // Cord::Chars()\n  //\n  // Returns a `Cord::CharRange` for iterating over the characters of a `Cord`\n  // with a range-based for-loop. For most character-based iteration tasks on a\n  // Cord, use `Cord::Chars()` to retrieve this iterator.\n  //\n  // Example:\n  //\n  //   void ProcessCord(const Cord& cord) {\n  //     for (char c : cord.Chars()) { ... }\n  //   }\n  //\n  // Note that the ordinary caveats of temporary lifetime extension apply:\n  //\n  //   void Process() {\n  //     for (char c : CordFactory().Chars()) {\n  //       // The temporary Cord returned by CordFactory has been destroyed!\n  //     }\n  //   }\n  CharRange Chars() const ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  // Cord::operator[]\n  //\n  // Gets the \"i\"th character of the Cord and returns it, provided that\n  // 0 <= i < Cord.size().\n  //\n  // NOTE: This routine is reasonably efficient. It is roughly\n  // logarithmic based on the number of chunks that make up the cord. Still,\n  // if you need to iterate over the contents of a cord, you should\n  // use a CharIterator/ChunkIterator rather than call operator[]\n  // repeatedly in a loop.\n  char operator[](size_t i) const;\n\n  // Cord::TryFlat()\n  //\n  // If this cord's representation is a single flat array, returns a\n  // string_view referencing that array.  Otherwise returns nullopt.\n  std::optional<absl::string_view> TryFlat() const\n      ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  // Cord::Flatten()\n  //\n  // Flattens the cord into a single array and returns a view of the data.\n  //\n  // If the cord was already flat, the contents are not modified.\n  absl::string_view Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND;\n\n  // Cord::Find()\n  //\n  // Returns an iterator to the first occurrence of the substring `needle`.\n  //\n  // If the substring `needle` does not occur, `Cord::char_end()` is returned.\n  CharIterator Find(absl::string_view needle) const;\n  CharIterator Find(const absl::Cord& needle) const;\n\n  // Supports absl::Cord as a sink object for absl::Format().\n  friend void AbslFormatFlush(absl::Cord* absl_nonnull cord,\n                              absl::string_view part) {\n    cord->Append(part);\n  }\n\n  // Support automatic stringification with absl::StrCat and absl::StrFormat.\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const absl::Cord& cord) {\n    for (absl::string_view chunk : cord.Chunks()) {\n      sink.Append(chunk);\n    }\n  }\n\n  // Cord::SetExpectedChecksum()\n  //\n  // Stores a checksum value with this non-empty cord instance, for later\n  // retrieval.\n  //\n  // The expected checksum is a number stored out-of-band, alongside the data.\n  // It is preserved across copies and assignments, but any mutations to a cord\n  // will cause it to lose its expected checksum.\n  //\n  // The expected checksum is not part of a Cord's value, and does not affect\n  // operations such as equality or hashing.\n  //\n  // This field is intended to store a CRC32C checksum for later validation, to\n  // help support end-to-end checksum workflows.  However, the Cord API itself\n  // does no CRC validation, and assigns no meaning to this number.\n  //\n  // This call has no effect if this cord is empty.\n  void SetExpectedChecksum(uint32_t crc);\n\n  // Returns this cord's expected checksum, if it has one.  Otherwise, returns\n  // nullopt.\n  std::optional<uint32_t> ExpectedChecksum() const;\n\n  template <typename H>\n  friend H AbslHashValue(H hash_state, const absl::Cord& c) {\n    std::optional<absl::string_view> maybe_flat = c.TryFlat();\n    if (maybe_flat.has_value()) {\n      return H::combine(std::move(hash_state), *maybe_flat);\n    }\n    return c.HashFragmented(std::move(hash_state));\n  }\n\n  // Create a Cord with the contents of StringConstant<T>::value.\n  // No allocations will be done and no data will be copied.\n  // This is an INTERNAL API and subject to change or removal. This API can only\n  // be used by spelling absl::strings_internal::MakeStringConstant, which is\n  // also an internal API.\n  template <typename T>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  constexpr Cord(strings_internal::StringConstant<T>);\n\n private:\n  using CordRep = absl::cord_internal::CordRep;\n  using CordRepFlat = absl::cord_internal::CordRepFlat;\n  using CordzInfo = cord_internal::CordzInfo;\n  using CordzUpdateScope = cord_internal::CordzUpdateScope;\n  using CordzUpdateTracker = cord_internal::CordzUpdateTracker;\n  using InlineData = cord_internal::InlineData;\n  using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;\n\n  // Creates a cord instance with `method` representing the originating\n  // public API call causing the cord to be created.\n  explicit Cord(absl::string_view src, MethodIdentifier method);\n\n  friend class CordTestPeer;\n  friend bool operator==(const Cord& lhs, const Cord& rhs);\n  friend bool operator==(const Cord& lhs, absl::string_view rhs);\n\n#ifdef __cpp_impl_three_way_comparison\n\n  // Cords support comparison with other Cords and string_views via operator<\n  // and others; here we provide a wrapper for the C++20 three-way comparison\n  // <=> operator.\n\n  static inline std::strong_ordering ConvertCompareResultToStrongOrdering(\n      int c) {\n    if (c == 0) {\n      return std::strong_ordering::equal;\n    } else if (c < 0) {\n      return std::strong_ordering::less;\n    } else {\n      return std::strong_ordering::greater;\n    }\n  }\n\n  friend inline std::strong_ordering operator<=>(const Cord& x, const Cord& y) {\n    return ConvertCompareResultToStrongOrdering(x.Compare(y));\n  }\n\n  friend inline std::strong_ordering operator<=>(const Cord& lhs,\n                                                 absl::string_view rhs) {\n    return ConvertCompareResultToStrongOrdering(lhs.Compare(rhs));\n  }\n\n  friend inline std::strong_ordering operator<=>(absl::string_view lhs,\n                                                 const Cord& rhs) {\n    return ConvertCompareResultToStrongOrdering(-rhs.Compare(lhs));\n  }\n#endif\n\n  friend const CordzInfo* absl_nullable GetCordzInfoForTesting(\n      const Cord& cord);\n\n  // Calls the provided function once for each cord chunk, in order.  Unlike\n  // Chunks(), this API will not allocate memory.\n  void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;\n\n  // Allocates new contiguous storage for the contents of the cord. This is\n  // called by Flatten() when the cord was not already flat.\n  absl::string_view FlattenSlowPath();\n\n  // Actual cord contents are hidden inside the following simple\n  // class so that we can isolate the bulk of cord.cc from changes\n  // to the representation.\n  //\n  // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.\n  class InlineRep {\n   public:\n    static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;\n    static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), \"\");\n\n    constexpr InlineRep() : data_() {}\n    explicit InlineRep(InlineData::DefaultInitType init) : data_(init) {}\n    InlineRep(const InlineRep& src);\n    InlineRep(InlineRep&& src);\n    InlineRep& operator=(const InlineRep& src);\n    InlineRep& operator=(InlineRep&& src) noexcept;\n\n    explicit constexpr InlineRep(absl::string_view sv,\n                                 CordRep* absl_nullable rep);\n\n    void Swap(InlineRep* absl_nonnull rhs);\n    size_t size() const;\n    // Returns nullptr if holding pointer\n    const char* absl_nullable data() const;\n    // Discards pointer, if any\n    void set_data(const char* absl_nullable data, size_t n);\n    char* absl_nonnull set_data(size_t n);  // Write data to the result\n    // Returns nullptr if holding bytes\n    absl::cord_internal::CordRep* absl_nullable tree() const;\n    absl::cord_internal::CordRep* absl_nonnull as_tree() const;\n    const char* absl_nonnull as_chars() const;\n    // Returns non-null iff was holding a pointer\n    absl::cord_internal::CordRep* absl_nullable clear();\n    // Converts to pointer if necessary.\n    void reduce_size(size_t n);    // REQUIRES: holding data\n    void remove_prefix(size_t n);  // REQUIRES: holding data\n    void AppendArray(absl::string_view src, MethodIdentifier method);\n    absl::string_view FindFlatStartPiece() const;\n\n    // Creates a CordRepFlat instance from the current inlined data with `extra'\n    // bytes of desired additional capacity.\n    CordRepFlat* absl_nonnull MakeFlatWithExtraCapacity(size_t extra);\n\n    // Sets the tree value for this instance. `rep` must not be null.\n    // Requires the current instance to hold a tree, and a lock to be held on\n    // any CordzInfo referenced by this instance. The latter is enforced through\n    // the CordzUpdateScope argument. If the current instance is sampled, then\n    // the CordzInfo instance is updated to reference the new `rep` value.\n    void SetTree(CordRep* absl_nonnull rep, const CordzUpdateScope& scope);\n\n    // Identical to SetTree(), except that `rep` is allowed to be null, in\n    // which case the current instance is reset to an empty value.\n    void SetTreeOrEmpty(CordRep* absl_nullable rep,\n                        const CordzUpdateScope& scope);\n\n    // Sets the tree value for this instance, and randomly samples this cord.\n    // This function disregards existing contents in `data_`, and should be\n    // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'\n    // value to a non-inlined (tree / ring) value.\n    void EmplaceTree(CordRep* absl_nonnull rep, MethodIdentifier method);\n\n    // Identical to EmplaceTree, except that it copies the parent stack from\n    // the provided `parent` data if the parent is sampled.\n    void EmplaceTree(CordRep* absl_nonnull rep, const InlineData& parent,\n                     MethodIdentifier method);\n\n    // Commits the change of a newly created, or updated `rep` root value into\n    // this cord. `old_rep` indicates the old (inlined or tree) value of the\n    // cord, and determines if the commit invokes SetTree() or EmplaceTree().\n    void CommitTree(const CordRep* absl_nullable old_rep,\n                    CordRep* absl_nonnull rep, const CordzUpdateScope& scope,\n                    MethodIdentifier method);\n\n    void AppendTreeToInlined(CordRep* absl_nonnull tree,\n                             MethodIdentifier method);\n    void AppendTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);\n    void AppendTree(CordRep* absl_nonnull tree, MethodIdentifier method);\n    void PrependTreeToInlined(CordRep* absl_nonnull tree,\n                              MethodIdentifier method);\n    void PrependTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);\n    void PrependTree(CordRep* absl_nonnull tree, MethodIdentifier method);\n\n    bool IsSame(const InlineRep& other) const { return data_ == other.data_; }\n\n    // Copies the inline contents into `dst`. Assumes the cord is not empty.\n    void CopyTo(std::string* absl_nonnull dst) const {\n      data_.CopyInlineToString(dst);\n    }\n\n    // Copies the inline contents into `dst`. Assumes the cord is not empty.\n    void CopyToArray(char* absl_nonnull dst) const;\n\n    bool is_tree() const { return data_.is_tree(); }\n\n    // Returns true if the Cord is being profiled by cordz.\n    bool is_profiled() const { return data_.is_tree() && data_.is_profiled(); }\n\n    // Returns the available inlined capacity, or 0 if is_tree() == true.\n    size_t remaining_inline_capacity() const {\n      return data_.is_tree() ? 0 : kMaxInline - data_.inline_size();\n    }\n\n    // Returns the profiled CordzInfo, or nullptr if not sampled.\n    absl::cord_internal::CordzInfo* absl_nullable cordz_info() const {\n      return data_.cordz_info();\n    }\n\n    // Sets the profiled CordzInfo.\n    void set_cordz_info(cord_internal::CordzInfo* absl_nonnull cordz_info) {\n      assert(cordz_info != nullptr);\n      data_.set_cordz_info(cordz_info);\n    }\n\n    // Resets the current cordz_info to null / empty.\n    void clear_cordz_info() { data_.clear_cordz_info(); }\n\n   private:\n    friend class Cord;\n\n    void AssignSlow(const InlineRep& src);\n    // Unrefs the tree and stops profiling.\n    void UnrefTree();\n\n    void ResetToEmpty() { data_ = {}; }\n\n    void set_inline_size(size_t size) { data_.set_inline_size(size); }\n    size_t inline_size() const { return data_.inline_size(); }\n\n    // Empty cords that carry a checksum have a CordRepCrc node with a null\n    // child node. The code can avoid lots of special cases where it would\n    // otherwise transition from tree to inline storage if we just remove the\n    // CordRepCrc node before mutations. Must never be called inside a\n    // CordzUpdateScope since it untracks the cordz info.\n    void MaybeRemoveEmptyCrcNode();\n\n    cord_internal::InlineData data_;\n  };\n  InlineRep contents_;\n\n  // Helper for GetFlat() and TryFlat().\n  static bool GetFlatAux(absl::cord_internal::CordRep* absl_nonnull rep,\n                         absl::string_view* absl_nonnull fragment);\n\n  // Helper for ForEachChunk().\n  static void ForEachChunkAux(\n      absl::cord_internal::CordRep* absl_nonnull rep,\n      absl::FunctionRef<void(absl::string_view)> callback);\n\n  // The destructor for non-empty Cords.\n  void DestroyCordSlow();\n\n  // Out-of-line implementation of slower parts of logic.\n  void CopyToArraySlowPath(char* absl_nonnull dst) const;\n  int CompareSlowPath(absl::string_view rhs, size_t compared_size,\n                      size_t size_to_compare) const;\n  int CompareSlowPath(const Cord& rhs, size_t compared_size,\n                      size_t size_to_compare) const;\n  bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;\n  bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;\n  int CompareImpl(const Cord& rhs) const;\n\n  template <typename ResultType, typename RHS>\n  friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,\n                                   size_t size_to_compare);\n  static absl::string_view GetFirstChunk(const Cord& c);\n  static absl::string_view GetFirstChunk(absl::string_view sv);\n\n  // Returns a new reference to contents_.tree(), or steals an existing\n  // reference if called on an rvalue.\n  absl::cord_internal::CordRep* absl_nonnull TakeRep() const&;\n  absl::cord_internal::CordRep* absl_nonnull TakeRep() &&;\n\n  // Helper for Append().\n  template <typename C>\n  void AppendImpl(C&& src);\n\n  // Appends / Prepends `src` to this instance, using precise sizing.\n  // This method does explicitly not attempt to use any spare capacity\n  // in any pending last added private owned flat.\n  // Requires `src` to be <= kMaxFlatLength.\n  void AppendPrecise(absl::string_view src, MethodIdentifier method);\n  void PrependPrecise(absl::string_view src, MethodIdentifier method);\n\n  CordBuffer GetAppendBufferSlowPath(size_t block_size, size_t capacity,\n                                     size_t min_capacity);\n\n  // Prepends the provided data to this instance. `method` contains the public\n  // API method for this action which is tracked for Cordz sampling purposes.\n  void PrependArray(absl::string_view src, MethodIdentifier method);\n\n  // Assigns the value in 'src' to this instance, 'stealing' its contents.\n  // Requires src.length() > kMaxBytesToCopy.\n  Cord& AssignLargeString(std::string&& src);\n\n  // Helper for AbslHashValue().\n  template <typename H>\n  H HashFragmented(H hash_state) const {\n    typename H::AbslInternalPiecewiseCombiner combiner;\n    ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {\n      hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),\n                                       chunk.size());\n    });\n    return combiner.finalize(std::move(hash_state));\n  }\n\n  friend class CrcCord;\n  void SetCrcCordState(crc_internal::CrcCordState state);\n  const crc_internal::CrcCordState* absl_nullable MaybeGetCrcCordState() const;\n\n  CharIterator FindImpl(CharIterator it, absl::string_view needle) const;\n\n  void CopyToArrayImpl(char* absl_nonnull dst) const;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// allow a Cord to be logged\nextern std::ostream& operator<<(std::ostream& out, const Cord& cord);\n\n// ------------------------------------------------------------------\n// Internal details follow.  Clients should ignore.\n\nnamespace cord_internal {\n\n// Does non-template-specific `CordRepExternal` initialization.\n// Requires `data` to be non-empty.\nvoid InitializeCordRepExternal(absl::string_view data,\n                               CordRepExternal* absl_nonnull rep);\n\n// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer\n// to it. Requires `data` to be non-empty.\ntemplate <typename Releaser>\n// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.\nCordRep* absl_nonnull NewExternalRep(absl::string_view data,\n                                     Releaser&& releaser) {\n  assert(!data.empty());\n  using ReleaserType = absl::decay_t<Releaser>;\n  CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(\n      std::forward<Releaser>(releaser), 0);\n  InitializeCordRepExternal(data, rep);\n  return rep;\n}\n\n// Overload for function reference types that dispatches using a function\n// pointer because there are no `alignof()` or `sizeof()` a function reference.\n// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.\ninline CordRep* absl_nonnull NewExternalRep(\n    absl::string_view data, void (&releaser)(absl::string_view)) {\n  return NewExternalRep(data, &releaser);\n}\n\n}  // namespace cord_internal\n\ntemplate <typename Releaser>\nCord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {\n  Cord cord;\n  if (ABSL_PREDICT_TRUE(!data.empty())) {\n    cord.contents_.EmplaceTree(::absl::cord_internal::NewExternalRep(\n                                   data, std::forward<Releaser>(releaser)),\n                               Cord::MethodIdentifier::kMakeCordFromExternal);\n  } else {\n    using ReleaserType = absl::decay_t<Releaser>;\n    cord_internal::InvokeReleaser(\n        cord_internal::Rank1{}, ReleaserType(std::forward<Releaser>(releaser)),\n        data);\n  }\n  return cord;\n}\n\nconstexpr Cord::InlineRep::InlineRep(absl::string_view sv,\n                                     CordRep* absl_nullable rep)\n    : data_(sv, rep) {}\n\ninline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)\n    : data_(InlineData::kDefaultInit) {\n  if (CordRep* tree = src.tree()) {\n    EmplaceTree(CordRep::Ref(tree), src.data_,\n                CordzUpdateTracker::kConstructorCord);\n  } else {\n    data_ = src.data_;\n  }\n}\n\ninline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) {\n  src.ResetToEmpty();\n}\n\ninline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {\n  if (this == &src) {\n    return *this;\n  }\n  if (!is_tree() && !src.is_tree()) {\n    data_ = src.data_;\n    return *this;\n  }\n  AssignSlow(src);\n  return *this;\n}\n\ninline Cord::InlineRep& Cord::InlineRep::operator=(\n    Cord::InlineRep&& src) noexcept {\n  if (is_tree()) {\n    UnrefTree();\n  }\n  data_ = src.data_;\n  src.ResetToEmpty();\n  return *this;\n}\n\ninline void Cord::InlineRep::Swap(Cord::InlineRep* absl_nonnull rhs) {\n  if (rhs == this) {\n    return;\n  }\n  using std::swap;\n  swap(data_, rhs->data_);\n}\n\ninline const char* absl_nullable Cord::InlineRep::data() const {\n  return is_tree() ? nullptr : data_.as_chars();\n}\n\ninline const char* absl_nonnull Cord::InlineRep::as_chars() const {\n  assert(!data_.is_tree());\n  return data_.as_chars();\n}\n\ninline absl::cord_internal::CordRep* absl_nonnull Cord::InlineRep::as_tree()\n    const {\n  assert(data_.is_tree());\n  return data_.as_tree();\n}\n\ninline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::tree()\n    const {\n  if (is_tree()) {\n    return as_tree();\n  } else {\n    return nullptr;\n  }\n}\n\ninline size_t Cord::InlineRep::size() const {\n  return is_tree() ? as_tree()->length : inline_size();\n}\n\ninline cord_internal::CordRepFlat* absl_nonnull\nCord::InlineRep::MakeFlatWithExtraCapacity(size_t extra) {\n  static_assert(cord_internal::kMinFlatLength >= sizeof(data_), \"\");\n  size_t len = data_.inline_size();\n  auto* result = CordRepFlat::New(len + extra);\n  result->length = len;\n  data_.copy_max_inline_to(result->Data());\n  return result;\n}\n\ninline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,\n                                         MethodIdentifier method) {\n  assert(rep);\n  data_.make_tree(rep);\n  CordzInfo::MaybeTrackCord(data_, method);\n}\n\ninline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,\n                                         const InlineData& parent,\n                                         MethodIdentifier method) {\n  data_.make_tree(rep);\n  CordzInfo::MaybeTrackCord(data_, parent, method);\n}\n\ninline void Cord::InlineRep::SetTree(CordRep* absl_nonnull rep,\n                                     const CordzUpdateScope& scope) {\n  assert(rep);\n  assert(data_.is_tree());\n  data_.set_tree(rep);\n  scope.SetCordRep(rep);\n}\n\ninline void Cord::InlineRep::SetTreeOrEmpty(CordRep* absl_nullable rep,\n                                            const CordzUpdateScope& scope) {\n  assert(data_.is_tree());\n  if (rep) {\n    data_.set_tree(rep);\n  } else {\n    data_ = {};\n  }\n  scope.SetCordRep(rep);\n}\n\ninline void Cord::InlineRep::CommitTree(const CordRep* absl_nullable old_rep,\n                                        CordRep* absl_nonnull rep,\n                                        const CordzUpdateScope& scope,\n                                        MethodIdentifier method) {\n  if (old_rep) {\n    SetTree(rep, scope);\n  } else {\n    EmplaceTree(rep, method);\n  }\n}\n\ninline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::clear() {\n  if (is_tree()) {\n    CordzInfo::MaybeUntrackCord(cordz_info());\n  }\n  absl::cord_internal::CordRep* result = tree();\n  ResetToEmpty();\n  return result;\n}\n\ninline void Cord::InlineRep::CopyToArray(char* absl_nonnull dst) const {\n  assert(!is_tree());\n  size_t n = inline_size();\n  assert(n != 0);\n  cord_internal::SmallMemmove(dst, data_.as_chars(), n);\n}\n\ninline void Cord::InlineRep::MaybeRemoveEmptyCrcNode() {\n  CordRep* rep = tree();\n  if (rep == nullptr || ABSL_PREDICT_TRUE(rep->length > 0)) {\n    return;\n  }\n  assert(rep->IsCrc());\n  assert(rep->crc()->child == nullptr);\n  CordzInfo::MaybeUntrackCord(cordz_info());\n  CordRep::Unref(rep);\n  ResetToEmpty();\n}\n\nconstexpr inline Cord::Cord() noexcept {}\n\ninline Cord::Cord(absl::string_view src)\n    : Cord(src, CordzUpdateTracker::kConstructorString) {}\n\ntemplate <typename T>\nconstexpr Cord::Cord(strings_internal::StringConstant<T>)\n    : contents_(strings_internal::StringConstant<T>::value,\n                strings_internal::StringConstant<T>::value.size() <=\n                        cord_internal::kMaxInline\n                    ? nullptr\n                    : &cord_internal::ConstInitExternalStorage<\n                          strings_internal::StringConstant<T>>::value) {}\n\ninline Cord& Cord::operator=(const Cord& x) {\n  contents_ = x.contents_;\n  return *this;\n}\n\ntemplate <typename T, Cord::EnableIfString<T>>\nCord& Cord::operator=(T&& src) {\n  if (src.size() <= cord_internal::kMaxBytesToCopy) {\n    return operator=(absl::string_view(src));\n  } else {\n    return AssignLargeString(std::forward<T>(src));\n  }\n}\n\ninline Cord::Cord(const Cord& src) : contents_(src.contents_) {}\n\ninline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}\n\ninline void Cord::swap(Cord& other) noexcept {\n  contents_.Swap(&other.contents_);\n}\n\ninline Cord& Cord::operator=(Cord&& x) noexcept {\n  contents_ = std::move(x.contents_);\n  return *this;\n}\n\nextern template Cord::Cord(std::string&& src);\n\ninline size_t Cord::size() const {\n  // Length is 1st field in str.rep_\n  return contents_.size();\n}\n\ninline bool Cord::empty() const { return size() == 0; }\n\ninline size_t Cord::EstimatedMemoryUsage(\n    CordMemoryAccounting accounting_method) const {\n  size_t result = sizeof(Cord);\n  if (const absl::cord_internal::CordRep* rep = contents_.tree()) {\n    switch (accounting_method) {\n      case CordMemoryAccounting::kFairShare:\n        result += cord_internal::GetEstimatedFairShareMemoryUsage(rep);\n        break;\n      case CordMemoryAccounting::kTotalMorePrecise:\n        result += cord_internal::GetMorePreciseMemoryUsage(rep);\n        break;\n      case CordMemoryAccounting::kTotal:\n        result += cord_internal::GetEstimatedMemoryUsage(rep);\n        break;\n    }\n  }\n  return result;\n}\n\ninline std::optional<absl::string_view> Cord::TryFlat() const\n    ABSL_ATTRIBUTE_LIFETIME_BOUND {\n  absl::cord_internal::CordRep* rep = contents_.tree();\n  if (rep == nullptr) {\n    return absl::string_view(contents_.data(), contents_.size());\n  }\n  absl::string_view fragment;\n  if (GetFlatAux(rep, &fragment)) {\n    return fragment;\n  }\n  return std::nullopt;\n}\n\ninline absl::string_view Cord::Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND {\n  absl::cord_internal::CordRep* rep = contents_.tree();\n  if (rep == nullptr) {\n    return absl::string_view(contents_.data(), contents_.size());\n  } else {\n    absl::string_view already_flat_contents;\n    if (GetFlatAux(rep, &already_flat_contents)) {\n      return already_flat_contents;\n    }\n  }\n  return FlattenSlowPath();\n}\n\ninline void Cord::Append(absl::string_view src) {\n  contents_.AppendArray(src, CordzUpdateTracker::kAppendString);\n}\n\ninline void Cord::Prepend(absl::string_view src) {\n  PrependArray(src, CordzUpdateTracker::kPrependString);\n}\n\ninline void Cord::Append(CordBuffer buffer) {\n  if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;\n  contents_.MaybeRemoveEmptyCrcNode();\n  absl::string_view short_value;\n  if (CordRep* rep = buffer.ConsumeValue(short_value)) {\n    contents_.AppendTree(rep, CordzUpdateTracker::kAppendCordBuffer);\n  } else {\n    AppendPrecise(short_value, CordzUpdateTracker::kAppendCordBuffer);\n  }\n}\n\ninline void Cord::Prepend(CordBuffer buffer) {\n  if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;\n  contents_.MaybeRemoveEmptyCrcNode();\n  absl::string_view short_value;\n  if (CordRep* rep = buffer.ConsumeValue(short_value)) {\n    contents_.PrependTree(rep, CordzUpdateTracker::kPrependCordBuffer);\n  } else {\n    PrependPrecise(short_value, CordzUpdateTracker::kPrependCordBuffer);\n  }\n}\n\ninline CordBuffer Cord::GetAppendBuffer(size_t capacity, size_t min_capacity) {\n  if (empty()) return CordBuffer::CreateWithDefaultLimit(capacity);\n  return GetAppendBufferSlowPath(0, capacity, min_capacity);\n}\n\ninline CordBuffer Cord::GetCustomAppendBuffer(size_t block_size,\n                                              size_t capacity,\n                                              size_t min_capacity) {\n  if (empty()) {\n    return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)\n                      : CordBuffer::CreateWithDefaultLimit(capacity);\n  }\n  return GetAppendBufferSlowPath(block_size, capacity, min_capacity);\n}\n\nextern template void Cord::Append(std::string&& src);\nextern template void Cord::Prepend(std::string&& src);\n\ninline int Cord::Compare(const Cord& rhs) const {\n  if (!contents_.is_tree() && !rhs.contents_.is_tree()) {\n    return contents_.data_.Compare(rhs.contents_.data_);\n  }\n\n  return CompareImpl(rhs);\n}\n\n// Does 'this' cord start/end with rhs\ninline bool Cord::StartsWith(const Cord& rhs) const {\n  if (contents_.IsSame(rhs.contents_)) return true;\n  size_t rhs_size = rhs.size();\n  if (size() < rhs_size) return false;\n  return EqualsImpl(rhs, rhs_size);\n}\n\ninline bool Cord::StartsWith(absl::string_view rhs) const {\n  size_t rhs_size = rhs.size();\n  if (size() < rhs_size) return false;\n  return EqualsImpl(rhs, rhs_size);\n}\n\ninline void Cord::CopyToArrayImpl(char* absl_nonnull dst) const {\n  if (!contents_.is_tree()) {\n    if (!empty()) contents_.CopyToArray(dst);\n  } else {\n    CopyToArraySlowPath(dst);\n  }\n}\n\ninline void Cord::ChunkIterator::InitTree(\n    cord_internal::CordRep* absl_nonnull tree) {\n  tree = cord_internal::SkipCrcNode(tree);\n  if (tree->tag == cord_internal::BTREE) {\n    current_chunk_ = btree_reader_.Init(tree->btree());\n  } else {\n    current_leaf_ = tree;\n    current_chunk_ = cord_internal::EdgeData(tree);\n  }\n}\n\ninline Cord::ChunkIterator::ChunkIterator(\n    cord_internal::CordRep* absl_nonnull tree) {\n  bytes_remaining_ = tree->length;\n  InitTree(tree);\n}\n\ninline Cord::ChunkIterator::ChunkIterator(const Cord* absl_nonnull cord) {\n  if (CordRep* tree = cord->contents_.tree()) {\n    bytes_remaining_ = tree->length;\n    if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) {\n      InitTree(tree);\n    } else {\n      current_chunk_ = {};\n    }\n  } else {\n    bytes_remaining_ = cord->contents_.inline_size();\n    current_chunk_ = {cord->contents_.data(), bytes_remaining_};\n  }\n}\n\ninline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() {\n  current_chunk_ = btree_reader_.Next();\n  return *this;\n}\n\ninline void Cord::ChunkIterator::AdvanceBytesBtree(size_t n) {\n  assert(n >= current_chunk_.size());\n  bytes_remaining_ -= n;\n  if (bytes_remaining_) {\n    if (n == current_chunk_.size()) {\n      current_chunk_ = btree_reader_.Next();\n    } else {\n      size_t offset = btree_reader_.length() - bytes_remaining_;\n      current_chunk_ = btree_reader_.Seek(offset);\n    }\n  } else {\n    current_chunk_ = {};\n  }\n}\n\ninline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {\n  ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&\n                        \"Attempted to iterate past `end()`\");\n  assert(bytes_remaining_ >= current_chunk_.size());\n  bytes_remaining_ -= current_chunk_.size();\n  if (bytes_remaining_ > 0) {\n    if (btree_reader_) {\n      return AdvanceBtree();\n    } else {\n      assert(!current_chunk_.empty());  // Called on invalid iterator.\n    }\n    current_chunk_ = {};\n  }\n  return *this;\n}\n\ninline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {\n  ChunkIterator tmp(*this);\n  operator++();\n  return tmp;\n}\n\ninline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {\n  return bytes_remaining_ == other.bytes_remaining_;\n}\n\ninline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {\n  return !(*this == other);\n}\n\ninline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {\n  ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);\n  return current_chunk_;\n}\n\ninline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {\n  ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);\n  return &current_chunk_;\n}\n\ninline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {\n  assert(n < current_chunk_.size());\n  current_chunk_.remove_prefix(n);\n  bytes_remaining_ -= n;\n}\n\ninline void Cord::ChunkIterator::AdvanceBytes(size_t n) {\n  assert(bytes_remaining_ >= n);\n  if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {\n    RemoveChunkPrefix(n);\n  } else if (n != 0) {\n    if (btree_reader_) {\n      AdvanceBytesBtree(n);\n    } else {\n      bytes_remaining_ = 0;\n    }\n  }\n}\n\ninline Cord::ChunkIterator Cord::chunk_begin() const {\n  return ChunkIterator(this);\n}\n\ninline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }\n\ninline Cord::ChunkIterator Cord::ChunkRange::begin() const {\n  return cord_->chunk_begin();\n}\n\ninline Cord::ChunkIterator Cord::ChunkRange::end() const {\n  return cord_->chunk_end();\n}\n\ninline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }\n\ninline Cord::CharIterator& Cord::CharIterator::operator++() {\n  if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {\n    chunk_iterator_.RemoveChunkPrefix(1);\n  } else {\n    ++chunk_iterator_;\n  }\n  return *this;\n}\n\ninline Cord::CharIterator Cord::CharIterator::operator++(int) {\n  CharIterator tmp(*this);\n  operator++();\n  return tmp;\n}\n\ninline bool Cord::CharIterator::operator==(const CharIterator& other) const {\n  return chunk_iterator_ == other.chunk_iterator_;\n}\n\ninline bool Cord::CharIterator::operator!=(const CharIterator& other) const {\n  return !(*this == other);\n}\n\ninline Cord::CharIterator::reference Cord::CharIterator::operator*() const {\n  return *chunk_iterator_->data();\n}\n\ninline Cord Cord::AdvanceAndRead(CharIterator* absl_nonnull it,\n                                 size_t n_bytes) {\n  assert(it != nullptr);\n  return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);\n}\n\ninline void Cord::Advance(CharIterator* absl_nonnull it, size_t n_bytes) {\n  assert(it != nullptr);\n  it->chunk_iterator_.AdvanceBytes(n_bytes);\n}\n\ninline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {\n  return *it.chunk_iterator_;\n}\n\ninline ptrdiff_t Cord::Distance(const CharIterator& first,\n                                const CharIterator& last) {\n  return static_cast<ptrdiff_t>(first.chunk_iterator_.bytes_remaining_ -\n                                last.chunk_iterator_.bytes_remaining_);\n}\n\ninline Cord::CharIterator Cord::char_begin() const {\n  return CharIterator(this);\n}\n\ninline Cord::CharIterator Cord::char_end() const { return CharIterator(); }\n\ninline Cord::CharIterator Cord::CharRange::begin() const {\n  return cord_->char_begin();\n}\n\ninline Cord::CharIterator Cord::CharRange::end() const {\n  return cord_->char_end();\n}\n\ninline Cord::CharRange Cord::Chars() const { return CharRange(this); }\n\ninline void Cord::ForEachChunk(\n    absl::FunctionRef<void(absl::string_view)> callback) const {\n  absl::cord_internal::CordRep* rep = contents_.tree();\n  if (rep == nullptr) {\n    callback(absl::string_view(contents_.data(), contents_.size()));\n  } else {\n    ForEachChunkAux(rep, callback);\n  }\n}\n\n// Nonmember Cord-to-Cord relational operators.\ninline bool operator==(const Cord& lhs, const Cord& rhs) {\n  if (lhs.contents_.IsSame(rhs.contents_)) return true;\n  size_t rhs_size = rhs.size();\n  if (lhs.size() != rhs_size) return false;\n  return lhs.EqualsImpl(rhs, rhs_size);\n}\n\ninline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }\ninline bool operator<(const Cord& x, const Cord& y) { return x.Compare(y) < 0; }\ninline bool operator>(const Cord& x, const Cord& y) { return x.Compare(y) > 0; }\ninline bool operator<=(const Cord& x, const Cord& y) {\n  return x.Compare(y) <= 0;\n}\ninline bool operator>=(const Cord& x, const Cord& y) {\n  return x.Compare(y) >= 0;\n}\n\n// Nonmember Cord-to-absl::string_view relational operators.\n//\n// Due to implicit conversions, these also enable comparisons of Cord with\n// std::string and const char*.\ninline bool operator==(const Cord& lhs, absl::string_view rhs) {\n  size_t lhs_size = lhs.size();\n  size_t rhs_size = rhs.size();\n  if (lhs_size != rhs_size) return false;\n  return lhs.EqualsImpl(rhs, rhs_size);\n}\n\ninline bool operator==(absl::string_view x, const Cord& y) { return y == x; }\ninline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }\ninline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }\ninline bool operator<(const Cord& x, absl::string_view y) {\n  return x.Compare(y) < 0;\n}\ninline bool operator<(absl::string_view x, const Cord& y) {\n  return y.Compare(x) > 0;\n}\ninline bool operator>(const Cord& x, absl::string_view y) { return y < x; }\ninline bool operator>(absl::string_view x, const Cord& y) { return y < x; }\ninline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }\ninline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }\ninline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }\ninline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }\n\n// Some internals exposed to test code.\nnamespace strings_internal {\nclass CordTestAccess {\n public:\n  static size_t FlatOverhead();\n  static size_t MaxFlatLength();\n  static size_t SizeofCordRepExternal();\n  static size_t SizeofCordRepSubstring();\n  static size_t FlatTagToLength(uint8_t tag);\n  static uint8_t LengthToTag(size_t s);\n};\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_CORD_H_\n"
  },
  {
    "path": "absl/strings/cord_analysis.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/cord_analysis.h\"\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <unordered_set>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\n// Accounting mode for analyzing memory usage.\nenum class Mode { kFairShare, kTotal, kTotalMorePrecise };\n\n// CordRepRef holds a `const CordRep*` reference in rep, and depending on mode,\n// holds a 'fraction' representing a cumulative inverse refcount weight.\ntemplate <Mode mode>\nstruct CordRepRef {\n  // Instantiates a CordRepRef instance.\n  explicit CordRepRef(const CordRep* absl_nonnull r) : rep(r) {}\n\n  // Creates a child reference holding the provided child.\n  // Overloaded to add cumulative reference count for kFairShare.\n  CordRepRef Child(const CordRep* absl_nonnull child) const {\n    return CordRepRef(child);\n  }\n\n  const CordRep* absl_nonnull rep;\n};\n\n// RawUsage holds the computed total number of bytes.\ntemplate <Mode mode>\nstruct RawUsage {\n  size_t total = 0;\n\n  // Add 'size' to total, ignoring the CordRepRef argument.\n  void Add(size_t size, CordRepRef<mode>) { total += size; }\n};\n\n// Overloaded representation of RawUsage that tracks the set of objects\n// counted, and avoids double-counting objects referenced more than once\n// by the same Cord.\ntemplate <>\nstruct RawUsage<Mode::kTotalMorePrecise> {\n  size_t total = 0;\n  // TODO(b/289250880): Replace this with a flat_hash_set.\n  std::unordered_set<const CordRep* absl_nonnull> counted;\n\n  void Add(size_t size, CordRepRef<Mode::kTotalMorePrecise> repref) {\n    if (counted.insert(repref.rep).second) {\n      total += size;\n    }\n  }\n};\n\n// Returns n / refcount avoiding a div for the common refcount == 1.\ntemplate <typename refcount_t>\ndouble MaybeDiv(double d, refcount_t refcount) {\n  return refcount == 1 ? d : d / refcount;\n}\n\n// Overloaded 'kFairShare' specialization for CordRepRef. This class holds a\n// `fraction` value which represents a cumulative inverse refcount weight.\n// For example, a top node with a reference count of 2 will have a fraction\n// value of 1/2 = 0.5, representing the 'fair share' of memory it references.\n// A node below such a node with a reference count of 5 then has a fraction of\n// 0.5 / 5 = 0.1 representing the fair share of memory below that node, etc.\ntemplate <>\nstruct CordRepRef<Mode::kFairShare> {\n  // Creates a CordRepRef with the provided rep and top (parent) fraction.\n  explicit CordRepRef(const CordRep* absl_nonnull r, double frac = 1.0)\n      : rep(r), fraction(MaybeDiv(frac, r->refcount.Get())) {}\n\n  // Returns a CordRepRef with a fraction of `this->fraction / child.refcount`\n  CordRepRef Child(const CordRep* absl_nonnull child) const {\n    return CordRepRef(child, fraction);\n  }\n\n  const CordRep* absl_nonnull rep;\n  double fraction;\n};\n\n// Overloaded 'kFairShare' specialization for RawUsage\ntemplate <>\nstruct RawUsage<Mode::kFairShare> {\n  double total = 0;\n\n  // Adds `size` multiplied by `rep.fraction` to the total size.\n  void Add(size_t size, CordRepRef<Mode::kFairShare> rep) {\n    total += static_cast<double>(size) * rep.fraction;\n  }\n};\n\n// Computes the estimated memory size of the provided data edge.\n// External reps are assumed 'heap allocated at their exact size'.\ntemplate <Mode mode>\nvoid AnalyzeDataEdge(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) {\n  assert(IsDataEdge(rep.rep));\n\n  // Consume all substrings\n  if (rep.rep->tag == SUBSTRING) {\n    raw_usage.Add(sizeof(CordRepSubstring), rep);\n    rep = rep.Child(rep.rep->substring()->child);\n  }\n\n  // Consume FLAT / EXTERNAL\n  const size_t size =\n      rep.rep->tag >= FLAT\n          ? rep.rep->flat()->AllocatedSize()\n          : rep.rep->length + sizeof(CordRepExternalImpl<intptr_t>);\n  raw_usage.Add(size, rep);\n}\n\n// Computes the memory size of the provided Btree tree.\ntemplate <Mode mode>\nvoid AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) {\n  raw_usage.Add(sizeof(CordRepBtree), rep);\n  const CordRepBtree* tree = rep.rep->btree();\n  if (tree->height() > 0) {\n    for (CordRep* edge : tree->Edges()) {\n      AnalyzeBtree(rep.Child(edge), raw_usage);\n    }\n  } else {\n    for (CordRep* edge : tree->Edges()) {\n      AnalyzeDataEdge(rep.Child(edge), raw_usage);\n    }\n  }\n}\n\ntemplate <Mode mode>\nsize_t GetEstimatedUsage(const CordRep* absl_nonnull rep) {\n  // Zero initialized memory usage totals.\n  RawUsage<mode> raw_usage;\n\n  // Capture top level node and refcount into a CordRepRef.\n  CordRepRef<mode> repref(rep);\n\n  // Consume the top level CRC node if present.\n  if (repref.rep->tag == CRC) {\n    raw_usage.Add(sizeof(CordRepCrc), repref);\n    if (repref.rep->crc()->child == nullptr) {\n      return static_cast<size_t>(raw_usage.total);\n    }\n    repref = repref.Child(repref.rep->crc()->child);\n  }\n\n  if (IsDataEdge(repref.rep)) {\n    AnalyzeDataEdge(repref, raw_usage);\n  } else if (repref.rep->tag == BTREE) {\n    AnalyzeBtree(repref, raw_usage);\n  } else {\n    assert(false);\n  }\n\n  return static_cast<size_t>(raw_usage.total);\n}\n\n}  // namespace\n\nsize_t GetEstimatedMemoryUsage(const CordRep* absl_nonnull rep) {\n  return GetEstimatedUsage<Mode::kTotal>(rep);\n}\n\nsize_t GetEstimatedFairShareMemoryUsage(const CordRep* absl_nonnull rep) {\n  return GetEstimatedUsage<Mode::kFairShare>(rep);\n}\n\nsize_t GetMorePreciseMemoryUsage(const CordRep* absl_nonnull rep) {\n  return GetEstimatedUsage<Mode::kTotalMorePrecise>(rep);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/cord_analysis.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_CORD_ANALYSIS_H_\n#define ABSL_STRINGS_CORD_ANALYSIS_H_\n\n#include <cstddef>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// Returns the *approximate* number of bytes held in full or in part by this\n// Cord (which may not remain the same between invocations). Cords that share\n// memory could each be \"charged\" independently for the same shared memory.\nsize_t GetEstimatedMemoryUsage(const CordRep* absl_nonnull rep);\n\n// Returns the *approximate* number of bytes held in full or in part by this\n// Cord for the distinct memory held by this cord. This is similar to\n// `GetEstimatedMemoryUsage()`, except that if the cord has multiple references\n// to the same memory, that memory is only counted once.\n//\n// For example:\n//   absl::Cord cord;\n//   cord.append(some_other_cord);\n//   cord.append(some_other_cord);\n//    // Calls GetEstimatedMemoryUsage() and counts `other_cord` twice:\n//   cord.EstimatedMemoryUsage(kTotal);\n//    // Calls GetMorePreciseMemoryUsage() and counts `other_cord` once:\n//   cord.EstimatedMemoryUsage(kTotalMorePrecise);\n//\n// This is more expensive than `GetEstimatedMemoryUsage()` as it requires\n// deduplicating all memory references.\nsize_t GetMorePreciseMemoryUsage(const CordRep* absl_nonnull rep);\n\n// Returns the *approximate* number of bytes held in full or in part by this\n// CordRep weighted by the sharing ratio of that data. For example, if some data\n// edge is shared by 4 different Cords, then each cord is attribute 1/4th of\n// the total memory usage as a 'fair share' of the total memory usage.\nsize_t GetEstimatedFairShareMemoryUsage(const CordRep* absl_nonnull rep);\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n\n#endif  // ABSL_STRINGS_CORD_ANALYSIS_H_\n"
  },
  {
    "path": "absl/strings/cord_buffer.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: cord_buffer.h\n// -----------------------------------------------------------------------------\n//\n// This file defines an `absl::CordBuffer` data structure to hold data for\n// eventual inclusion within an existing `Cord` data structure. Cord buffers are\n// useful for building large Cords that may require custom allocation of its\n// associated memory.\n//\n#ifndef ABSL_STRINGS_CORD_BUFFER_H_\n#define ABSL_STRINGS_CORD_BUFFER_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass Cord;\nclass CordBufferTestPeer;\n\n// CordBuffer\n//\n// CordBuffer manages memory buffers for purposes such as zero-copy APIs as well\n// as applications building cords with large data requiring granular control\n// over the allocation and size of cord data. For example, a function creating\n// a cord of random data could use a CordBuffer as follows:\n//\n//   absl::Cord CreateRandomCord(size_t length) {\n//     absl::Cord cord;\n//     while (length > 0) {\n//       CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(length);\n//       absl::Span<char> data = buffer.available_up_to(length);\n//       FillRandomValues(data.data(), data.size());\n//       buffer.IncreaseLengthBy(data.size());\n//       cord.Append(std::move(buffer));\n//       length -= data.size();\n//     }\n//     return cord;\n//   }\n//\n// CordBuffer instances are by default limited to a capacity of `kDefaultLimit`\n// bytes. `kDefaultLimit` is currently just under 4KiB, but this default may\n// change in the future and/or for specific architectures. The default limit is\n// aimed to provide a good trade-off between performance and memory overhead.\n// Smaller buffers typically incur more compute cost while larger buffers are\n// more CPU efficient but create significant memory overhead because of such\n// allocations being less granular. Using larger buffers may also increase the\n// risk of memory fragmentation.\n//\n// Applications create a buffer using one of the `CreateWithDefaultLimit()` or\n// `CreateWithCustomLimit()` methods. The returned instance will have a non-zero\n// capacity and a zero length. Applications use the `data()` method to set the\n// contents of the managed memory, and once done filling the buffer, use the\n// `IncreaseLengthBy()` or 'SetLength()' method to specify the length of the\n// initialized data before adding the buffer to a Cord.\n//\n// The `CreateWithCustomLimit()` method is intended for applications needing\n// larger buffers than the default memory limit, allowing the allocation of up\n// to a capacity of `kCustomLimit` bytes minus some minimum internal overhead.\n// The usage of `CreateWithCustomLimit()` should be limited to only those use\n// cases where the distribution of the input is relatively well known, and/or\n// where the trade-off between the efficiency gains outweigh the risk of memory\n// fragmentation. See the documentation for `CreateWithCustomLimit()` for more\n// information on using larger custom limits.\n//\n// The capacity of a `CordBuffer` returned by one of the `Create` methods may\n// be larger than the requested capacity due to rounding, alignment and\n// granularity of the memory allocator. Applications should use the `capacity`\n// method to obtain the effective capacity of the returned instance as\n// demonstrated in the provided example above.\n//\n// CordBuffer is a move-only class. All references into the managed memory are\n// invalidated when an instance is moved into either another CordBuffer instance\n// or a Cord. Writing to a location obtained by a previous call to `data()`\n// after an instance was moved will lead to undefined behavior.\n//\n// A `moved from` CordBuffer instance will have a valid, but empty state.\n// CordBuffer is thread compatible.\nclass CordBuffer {\n public:\n  // kDefaultLimit\n  //\n  // Default capacity limits of allocated CordBuffers.\n  // See the class comments for more information on allocation limits.\n  static constexpr size_t kDefaultLimit = cord_internal::kMaxFlatLength;\n\n  // kCustomLimit\n  //\n  // Maximum size for CreateWithCustomLimit() allocated buffers.\n  // Note that the effective capacity may be slightly less\n  // because of internal overhead of internal cord buffers.\n  static constexpr size_t kCustomLimit = 64U << 10;\n\n  // Constructors, Destructors and Assignment Operators\n\n  // Creates an empty CordBuffer.\n  CordBuffer() = default;\n\n  // Destroys this CordBuffer instance and, if not empty, releases any memory\n  // managed by this instance, invalidating previously returned references.\n  ~CordBuffer();\n\n  // CordBuffer is move-only\n  CordBuffer(CordBuffer&& rhs) noexcept;\n  CordBuffer& operator=(CordBuffer&&) noexcept;\n  CordBuffer(const CordBuffer&) = delete;\n  CordBuffer& operator=(const CordBuffer&) = delete;\n\n  // CordBuffer::MaximumPayload()\n  //\n  // Returns the guaranteed maximum payload for a CordBuffer returned by the\n  // `CreateWithDefaultLimit()` method. While small, each internal buffer inside\n  // a Cord incurs an overhead to manage the length, type and reference count\n  // for the buffer managed inside the cord tree. Applications can use this\n  // method to get approximate number of buffers required for a given byte\n  // size, etc.\n  //\n  // For example:\n  //   const size_t payload = absl::CordBuffer::MaximumPayload();\n  //   const size_t buffer_count = (total_size + payload - 1) / payload;\n  //   buffers.reserve(buffer_count);\n  static constexpr size_t MaximumPayload();\n\n  // Overload to the above `MaximumPayload()` except that it returns the\n  // maximum payload for a CordBuffer returned by the `CreateWithCustomLimit()`\n  // method given the provided `block_size`.\n  static constexpr size_t MaximumPayload(size_t block_size);\n\n  // CordBuffer::CreateWithDefaultLimit()\n  //\n  // Creates a CordBuffer instance of the desired `capacity`, capped at the\n  // default limit `kDefaultLimit`. The returned buffer has a guaranteed\n  // capacity of at least `min(kDefaultLimit, capacity)`. See the class comments\n  // for more information on buffer capacities and intended usage.\n  static CordBuffer CreateWithDefaultLimit(size_t capacity);\n\n  // CordBuffer::CreateWithCustomLimit()\n  //\n  // Creates a CordBuffer instance of the desired `capacity` rounded to an\n  // appropriate power of 2 size less than, or equal to `block_size`.\n  // Requires `block_size` to be a power of 2.\n  //\n  // If `capacity` is less than or equal to `kDefaultLimit`, then this method\n  // behaves identical to `CreateWithDefaultLimit`, which means that the caller\n  // is guaranteed to get a buffer of at least the requested capacity.\n  //\n  // If `capacity` is greater than or equal to `block_size`, then this method\n  // returns a buffer with an `allocated size` of `block_size` bytes. Otherwise,\n  // this methods returns a buffer with a suitable smaller power of 2 block size\n  // to satisfy the request. The actual size depends on a number of factors, and\n  // is typically (but not necessarily) the highest or second highest power of 2\n  // value less than or equal to `capacity`.\n  //\n  // The 'allocated size' includes a small amount of overhead required for\n  // internal state, which is currently 13 bytes on 64-bit platforms. For\n  // example: a buffer created with `block_size` and `capacity' set to 8KiB\n  // will have an allocated size of 8KiB, and an effective internal `capacity`\n  // of 8KiB - 13 = 8179 bytes.\n  //\n  // To demonstrate this in practice, let's assume we want to read data from\n  // somewhat larger files using approximately 64KiB buffers:\n  //\n  //   absl::Cord ReadFromFile(int fd, size_t n) {\n  //     absl::Cord cord;\n  //     while (n > 0) {\n  //       CordBuffer buffer = CordBuffer::CreateWithCustomLimit(64 << 10, n);\n  //       absl::Span<char> data = buffer.available_up_to(n);\n  //       ReadFileDataOrDie(fd, data.data(), data.size());\n  //       buffer.IncreaseLengthBy(data.size());\n  //       cord.Append(std::move(buffer));\n  //       n -= data.size();\n  //     }\n  //     return cord;\n  //   }\n  //\n  // If we'd use this function to read a file of 659KiB, we may get the\n  // following pattern of allocated cord buffer sizes:\n  //\n  //   CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)\n  //   CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)\n  //   ...\n  //   CreateWithCustomLimit(64KiB,  19586) --> ~16KiB (16371)\n  //   CreateWithCustomLimit(64KiB,   3215) -->   3215 (at least 3215)\n  //\n  // The reason the method returns a 16K buffer instead of a roughly 19K buffer\n  // is to reduce memory overhead and fragmentation risks. Using carefully\n  // chosen power of 2 values reduces the entropy of allocated memory sizes.\n  //\n  // Additionally, let's assume we'd use the above function on files that are\n  // generally smaller than 64K. If we'd use 'precise' sized buffers for such\n  // files, than we'd get a very wide distribution of allocated memory sizes\n  // rounded to 4K page sizes, and we'd end up with a lot of unused capacity.\n  //\n  // In general, application should only use custom sizes if the data they are\n  // consuming or storing is expected to be many times the chosen block size,\n  // and be based on objective data and performance metrics. For example, a\n  // compress function may work faster and consume less CPU when using larger\n  // buffers. Such an application should pick a size offering a reasonable\n  // trade-off between expected data size, compute savings with larger buffers,\n  // and the cost or fragmentation effect of larger buffers.\n  // Applications must pick a reasonable spot on that curve, and make sure their\n  // data meets their expectations in size distributions such as \"mostly large\".\n  static CordBuffer CreateWithCustomLimit(size_t block_size, size_t capacity);\n\n  // CordBuffer::available()\n  //\n  // Returns the span delineating the available capacity in this buffer\n  // which is defined as `{ data() + length(), capacity() - length() }`.\n  absl::Span<char> available();\n\n  // CordBuffer::available_up_to()\n  //\n  // Returns the span delineating the available capacity in this buffer limited\n  // to `size` bytes. This is equivalent to `available().subspan(0, size)`.\n  absl::Span<char> available_up_to(size_t size);\n\n  // CordBuffer::data()\n  //\n  // Returns a non-null reference to the data managed by this instance.\n  // Applications are allowed to write up to `capacity` bytes of instance data.\n  // CordBuffer data is uninitialized by default. Reading data from an instance\n  // that has not yet been initialized will lead to undefined behavior.\n  char* data();\n  const char* data() const;\n\n  // CordBuffer::length()\n  //\n  // Returns the length of this instance. The default length of a CordBuffer is\n  // 0, indicating an 'empty' CordBuffer. Applications must specify the length\n  // of the data in a CordBuffer before adding it to a Cord.\n  size_t length() const;\n\n  // CordBuffer::capacity()\n  //\n  // Returns the capacity of this instance. All instances have a non-zero\n  // capacity: default and `moved from` instances have a small internal buffer.\n  size_t capacity() const;\n\n  // CordBuffer::IncreaseLengthBy()\n  //\n  // Increases the length of this buffer by the specified 'n' bytes.\n  // Applications must make sure all data in this buffer up to the new length\n  // has been initialized before adding a CordBuffer to a Cord: failure to do so\n  // will lead to undefined behavior.  Requires `length() + n <= capacity()`.\n  // Typically, applications will use 'available_up_to()` to get a span of the\n  // desired capacity, and use `span.size()` to increase the length as in:\n  //   absl::Span<char> span = buffer.available_up_to(desired);\n  //   buffer.IncreaseLengthBy(span.size());\n  //   memcpy(span.data(), src, span.size());\n  //   etc...\n  void IncreaseLengthBy(size_t n);\n\n  // CordBuffer::SetLength()\n  //\n  // Sets the data length of this instance. Applications must make sure all data\n  // of the specified length has been initialized before adding a CordBuffer to\n  // a Cord: failure to do so will lead to undefined behavior.\n  // Setting the length to a small value or zero does not release any memory\n  // held by this CordBuffer instance. Requires `length <= capacity()`.\n  // Applications should preferably use the `IncreaseLengthBy()` method above\n  // in combination with the 'available()` or `available_up_to()` methods.\n  void SetLength(size_t length);\n\n private:\n  // Make sure we don't accidentally over promise.\n  static_assert(kCustomLimit <= cord_internal::kMaxLargeFlatSize, \"\");\n\n  // Assume the cost of an 'uprounded' allocation to CeilPow2(size) versus\n  // the cost of allocating at least 1 extra flat <= 4KB:\n  // - Flat overhead = 13 bytes\n  // - Btree amortized cost / node =~ 13 bytes\n  // - 64 byte granularity of tcmalloc at 4K =~ 32 byte average\n  // CPU cost and efficiency requires we should at least 'save' something by\n  // splitting, as a poor man's measure, we say the slop needs to be\n  // at least double the cost offset to make it worth splitting: ~128 bytes.\n  static constexpr size_t kMaxPageSlop = 128;\n\n  // Overhead for allocation a flat.\n  static constexpr size_t kOverhead = cord_internal::kFlatOverhead;\n\n  using CordRepFlat = cord_internal::CordRepFlat;\n\n  // `Rep` is the internal data representation of a CordBuffer. The internal\n  // representation has an internal small size optimization similar to\n  // std::string (SSO).\n  struct Rep {\n    // Inline SSO size of a CordBuffer\n    static constexpr size_t kInlineCapacity = sizeof(intptr_t) * 2 - 1;\n\n    // Creates a default instance with kInlineCapacity.\n    Rep() : short_rep{} {}\n\n    // Creates an instance managing an allocated non zero CordRep.\n    explicit Rep(cord_internal::CordRepFlat* rep) : long_rep{rep} {\n      assert(rep != nullptr);\n    }\n\n    // Returns true if this instance manages the SSO internal buffer.\n    bool is_short() const {\n      constexpr size_t offset = offsetof(Short, raw_size);\n      return (reinterpret_cast<const char*>(this)[offset] & 1) != 0;\n    }\n\n    // Returns the available area of the internal SSO data\n    absl::Span<char> short_available() {\n      const size_t length = short_length();\n      return absl::Span<char>(short_rep.data + length,\n                              kInlineCapacity - length);\n    }\n\n    // Returns the available area of the internal SSO data\n    absl::Span<char> long_available() const {\n      assert(!is_short());\n      const size_t length = long_rep.rep->length;\n      return absl::Span<char>(long_rep.rep->Data() + length,\n                              long_rep.rep->Capacity() - length);\n    }\n\n    // Returns the length of the internal SSO data.\n    size_t short_length() const {\n      assert(is_short());\n      return static_cast<size_t>(short_rep.raw_size >> 1);\n    }\n\n    // Sets the length of the internal SSO data.\n    // Disregards any previously set CordRep instance.\n    void set_short_length(size_t length) {\n      short_rep.raw_size = static_cast<char>((length << 1) + 1);\n    }\n\n    // Adds `n` to the current short length.\n    void add_short_length(size_t n) {\n      assert(is_short());\n      short_rep.raw_size += static_cast<char>(n << 1);\n    }\n\n    // Returns reference to the internal SSO data buffer.\n    char* data() {\n      assert(is_short());\n      return short_rep.data;\n    }\n    const char* data() const {\n      assert(is_short());\n      return short_rep.data;\n    }\n\n    // Returns a pointer the external CordRep managed by this instance.\n    cord_internal::CordRepFlat* rep() const {\n      assert(!is_short());\n      return long_rep.rep;\n    }\n\n    // The internal representation takes advantage of the fact that allocated\n    // memory is always on an even address, and uses the least significant bit\n    // of the first or last byte (depending on endianness) as the inline size\n    // indicator overlapping with the least significant byte of the CordRep*.\n#if defined(ABSL_IS_BIG_ENDIAN)\n    struct Long {\n      explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}\n      void* padding;\n      cord_internal::CordRepFlat* rep;\n    };\n    struct Short {\n      char data[sizeof(Long) - 1];\n      char raw_size = 1;\n    };\n#else\n    struct Long {\n      explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}\n      cord_internal::CordRepFlat* rep;\n      void* padding;\n    };\n    struct Short {\n      char raw_size = 1;\n      char data[sizeof(Long) - 1];\n    };\n#endif\n\n    union {\n      Long long_rep;\n      Short short_rep;\n    };\n  };\n\n  // Power2 functions\n  static bool IsPow2(size_t size) { return absl::has_single_bit(size); }\n  static size_t Log2Floor(size_t size) {\n    return static_cast<size_t>(absl::bit_width(size) - 1);\n  }\n  static size_t Log2Ceil(size_t size) {\n    return static_cast<size_t>(absl::bit_width(size - 1));\n  }\n\n  // Implementation of `CreateWithCustomLimit()`.\n  // This implementation allows for future memory allocation hints to\n  // be passed down into the CordRepFlat allocation function.\n  template <typename... AllocationHints>\n  static CordBuffer CreateWithCustomLimitImpl(size_t block_size,\n                                              size_t capacity,\n                                              AllocationHints... hints);\n\n  // Consumes the value contained in this instance and resets the instance.\n  // This method returns a non-null Cordrep* if the current instances manages a\n  // CordRep*, and resets the instance to an empty SSO instance. If the current\n  // instance is an SSO instance, then this method returns nullptr and sets\n  // `short_value` to the inlined data value. In either case, the current\n  // instance length is reset to zero.\n  // This method is intended to be used by Cord internal functions only.\n  cord_internal::CordRep* ConsumeValue(absl::string_view& short_value) {\n    cord_internal::CordRep* rep = nullptr;\n    if (rep_.is_short()) {\n      short_value = absl::string_view(rep_.data(), rep_.short_length());\n    } else {\n      rep = rep_.rep();\n    }\n    rep_.set_short_length(0);\n    return rep;\n  }\n\n  // Internal constructor.\n  explicit CordBuffer(cord_internal::CordRepFlat* rep) : rep_(rep) {\n    assert(rep != nullptr);\n  }\n\n  Rep rep_;\n\n  friend class Cord;\n  friend class CordBufferTestPeer;\n};\n\ninline constexpr size_t CordBuffer::MaximumPayload() {\n  return cord_internal::kMaxFlatLength;\n}\n\ninline constexpr size_t CordBuffer::MaximumPayload(size_t block_size) {\n  return (std::min)(kCustomLimit, block_size) - cord_internal::kFlatOverhead;\n}\n\ninline CordBuffer CordBuffer::CreateWithDefaultLimit(size_t capacity) {\n  if (capacity > Rep::kInlineCapacity) {\n    auto* rep = cord_internal::CordRepFlat::New(capacity);\n    rep->length = 0;\n    return CordBuffer(rep);\n  }\n  return CordBuffer();\n}\n\ntemplate <typename... AllocationHints>\ninline CordBuffer CordBuffer::CreateWithCustomLimitImpl(\n    size_t block_size, size_t capacity, AllocationHints... hints) {\n  assert(IsPow2(block_size));\n  capacity = (std::min)(capacity, kCustomLimit);\n  block_size = (std::min)(block_size, kCustomLimit);\n  if (capacity + kOverhead >= block_size) {\n    capacity = block_size;\n  } else if (capacity <= kDefaultLimit) {\n    capacity = capacity + kOverhead;\n  } else if (!IsPow2(capacity)) {\n    // Check if rounded up to next power 2 is a good enough fit\n    // with limited waste making it an acceptable direct fit.\n    const size_t rounded_up = size_t{1} << Log2Ceil(capacity);\n    const size_t slop = rounded_up - capacity;\n    if (slop >= kOverhead && slop <= kMaxPageSlop + kOverhead) {\n      capacity = rounded_up;\n    } else {\n      // Round down to highest power of 2 <= capacity.\n      // Consider a more aggressive step down if that may reduce the\n      // risk of fragmentation where 'people are holding it wrong'.\n      const size_t rounded_down = size_t{1} << Log2Floor(capacity);\n      capacity = rounded_down;\n    }\n  }\n  const size_t length = capacity - kOverhead;\n  auto* rep = CordRepFlat::New(CordRepFlat::Large(), length, hints...);\n  rep->length = 0;\n  return CordBuffer(rep);\n}\n\ninline CordBuffer CordBuffer::CreateWithCustomLimit(size_t block_size,\n                                                    size_t capacity) {\n  return CreateWithCustomLimitImpl(block_size, capacity);\n}\n\ninline CordBuffer::~CordBuffer() {\n  if (!rep_.is_short()) {\n    cord_internal::CordRepFlat::Delete(rep_.rep());\n  }\n}\n\ninline CordBuffer::CordBuffer(CordBuffer&& rhs) noexcept : rep_(rhs.rep_) {\n  rhs.rep_.set_short_length(0);\n}\n\ninline CordBuffer& CordBuffer::operator=(CordBuffer&& rhs) noexcept {\n  if (!rep_.is_short()) cord_internal::CordRepFlat::Delete(rep_.rep());\n  rep_ = rhs.rep_;\n  rhs.rep_.set_short_length(0);\n  return *this;\n}\n\ninline absl::Span<char> CordBuffer::available() {\n  return rep_.is_short() ? rep_.short_available() : rep_.long_available();\n}\n\ninline absl::Span<char> CordBuffer::available_up_to(size_t size) {\n  return available().subspan(0, size);\n}\n\ninline char* CordBuffer::data() {\n  return rep_.is_short() ? rep_.data() : rep_.rep()->Data();\n}\n\ninline const char* CordBuffer::data() const {\n  return rep_.is_short() ? rep_.data() : rep_.rep()->Data();\n}\n\ninline size_t CordBuffer::capacity() const {\n  return rep_.is_short() ? Rep::kInlineCapacity : rep_.rep()->Capacity();\n}\n\ninline size_t CordBuffer::length() const {\n  return rep_.is_short() ? rep_.short_length() : rep_.rep()->length;\n}\n\ninline void CordBuffer::SetLength(size_t length) {\n  ABSL_HARDENING_ASSERT(length <= capacity());\n  if (rep_.is_short()) {\n    rep_.set_short_length(length);\n  } else {\n    rep_.rep()->length = length;\n  }\n}\n\ninline void CordBuffer::IncreaseLengthBy(size_t n) {\n  ABSL_HARDENING_ASSERT(n <= capacity() && length() + n <= capacity());\n  if (rep_.is_short()) {\n    rep_.add_short_length(n);\n  } else {\n    rep_.rep()->length += n;\n  }\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_CORD_BUFFER_H_\n"
  },
  {
    "path": "absl/strings/cord_buffer_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/cord_buffer.h\"\n\n\n#include <algorithm>\n#include <cstring>\n#include <limits>\n#include <string>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cord_rep_test_util.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nusing testing::Eq;\nusing testing::Ge;\nusing testing::Le;\nusing testing::Ne;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass CordBufferTestPeer {\n public:\n  static cord_internal::CordRep* ConsumeValue(CordBuffer& buffer,\n                                              absl::string_view& short_value) {\n    return buffer.ConsumeValue(short_value);\n  }\n};\n\nnamespace {\n\nusing ::absl::cordrep_testing::CordToString;\n\nconstexpr size_t kInlinedSize = sizeof(CordBuffer) - 1;\nconstexpr size_t kDefaultLimit = CordBuffer::kDefaultLimit;\nconstexpr size_t kCustomLimit = CordBuffer::kCustomLimit;\nconstexpr size_t kMaxFlatSize = cord_internal::kMaxFlatSize;\nconstexpr size_t kMaxFlatLength = cord_internal::kMaxFlatLength;\nconstexpr size_t kFlatOverhead = cord_internal::kFlatOverhead;\n\nconstexpr size_t k8KiB = 8 << 10;\nconstexpr size_t k16KiB = 16 << 10;\nconstexpr size_t k64KiB = 64 << 10;\nconstexpr size_t k1MB = 1 << 20;\n\nclass CordBufferTest : public testing::TestWithParam<size_t> {};\n\nINSTANTIATE_TEST_SUITE_P(MediumSize, CordBufferTest,\n                         testing::Values(1, kInlinedSize - 1, kInlinedSize,\n                                         kInlinedSize + 1, kDefaultLimit - 1,\n                                         kDefaultLimit));\n\nTEST_P(CordBufferTest, MaximumPayload) {\n  EXPECT_THAT(CordBuffer::MaximumPayload(), Eq(kMaxFlatLength));\n  EXPECT_THAT(CordBuffer::MaximumPayload(512), Eq(512 - kFlatOverhead));\n  EXPECT_THAT(CordBuffer::MaximumPayload(k64KiB), Eq(k64KiB - kFlatOverhead));\n  EXPECT_THAT(CordBuffer::MaximumPayload(k1MB), Eq(k64KiB - kFlatOverhead));\n}\n\nTEST(CordBufferTest, ConstructDefault) {\n  CordBuffer buffer;\n  EXPECT_THAT(buffer.capacity(), Eq(sizeof(CordBuffer) - 1));\n  EXPECT_THAT(buffer.length(), Eq(0));\n  EXPECT_THAT(buffer.data(), Ne(nullptr));\n  EXPECT_THAT(buffer.available().data(), Eq(buffer.data()));\n  EXPECT_THAT(buffer.available().size(), Eq(buffer.capacity()));\n  memset(buffer.data(), 0xCD, buffer.capacity());\n}\n\nTEST(CordBufferTest, CreateSsoWithDefaultLimit) {\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(3);\n  EXPECT_THAT(buffer.capacity(), Ge(3));\n  EXPECT_THAT(buffer.capacity(), Le(sizeof(CordBuffer)));\n  EXPECT_THAT(buffer.length(), Eq(0));\n  memset(buffer.data(), 0xCD, buffer.capacity());\n\n  memcpy(buffer.data(), \"Abc\", 3);\n  buffer.SetLength(3);\n  EXPECT_THAT(buffer.length(), Eq(3));\n  absl::string_view short_value;\n  EXPECT_THAT(CordBufferTestPeer::ConsumeValue(buffer, short_value),\n              Eq(nullptr));\n  EXPECT_THAT(absl::string_view(buffer.data(), 3), Eq(\"Abc\"));\n  EXPECT_THAT(short_value, Eq(\"Abc\"));\n}\n\nTEST_P(CordBufferTest, Available) {\n  const size_t requested = GetParam();\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(requested);\n  EXPECT_THAT(buffer.available().data(), Eq(buffer.data()));\n  EXPECT_THAT(buffer.available().size(), Eq(buffer.capacity()));\n\n  buffer.SetLength(2);\n  EXPECT_THAT(buffer.available().data(), Eq(buffer.data() + 2));\n  EXPECT_THAT(buffer.available().size(), Eq(buffer.capacity() - 2));\n}\n\nTEST_P(CordBufferTest, IncreaseLengthBy) {\n  const size_t requested = GetParam();\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(requested);\n  buffer.IncreaseLengthBy(2);\n  EXPECT_THAT(buffer.length(), Eq(2));\n  buffer.IncreaseLengthBy(5);\n  EXPECT_THAT(buffer.length(), Eq(7));\n}\n\nTEST_P(CordBufferTest, AvailableUpTo) {\n  const size_t requested = GetParam();\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(requested);\n  size_t expected_up_to = std::min<size_t>(3, buffer.capacity());\n  EXPECT_THAT(buffer.available_up_to(3).data(), Eq(buffer.data()));\n  EXPECT_THAT(buffer.available_up_to(3).size(), Eq(expected_up_to));\n\n  buffer.SetLength(2);\n  expected_up_to = std::min<size_t>(3, buffer.capacity() - 2);\n  EXPECT_THAT(buffer.available_up_to(3).data(), Eq(buffer.data() + 2));\n  EXPECT_THAT(buffer.available_up_to(3).size(), Eq(expected_up_to));\n}\n\n// Returns the maximum capacity for a given block_size and requested size.\nsize_t MaxCapacityFor(size_t block_size, size_t requested) {\n  requested = (std::min)(requested, cord_internal::kMaxLargeFlatSize);\n  // Maximum returned size is always capped at block_size - kFlatOverhead.\n  return block_size - kFlatOverhead;\n}\n\nTEST_P(CordBufferTest, CreateWithDefaultLimit) {\n  const size_t requested = GetParam();\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(requested);\n  EXPECT_THAT(buffer.capacity(), Ge(requested));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(kMaxFlatSize, requested)));\n  EXPECT_THAT(buffer.length(), Eq(0));\n\n  memset(buffer.data(), 0xCD, buffer.capacity());\n\n  std::string data(requested - 1, 'x');\n  memcpy(buffer.data(), data.c_str(), requested);\n  buffer.SetLength(requested);\n\n  EXPECT_THAT(buffer.length(), Eq(requested));\n  EXPECT_THAT(absl::string_view(buffer.data()), Eq(data));\n}\n\nTEST(CordBufferTest, CreateWithDefaultLimitAskingFor2GB) {\n  constexpr size_t k2GiB = 1U << 31;\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(k2GiB);\n  // Expect to never be awarded more than a reasonable memory size, even in\n  // cases where a (debug) memory allocator may grant us somewhat more memory\n  // than `kDefaultLimit` which should be no more than `2 * kDefaultLimit`\n  EXPECT_THAT(buffer.capacity(), Le(2 * CordBuffer::kDefaultLimit));\n  EXPECT_THAT(buffer.length(), Eq(0));\n  EXPECT_THAT(buffer.data(), Ne(nullptr));\n  memset(buffer.data(), 0xCD, buffer.capacity());\n}\n\nTEST_P(CordBufferTest, MoveConstruct) {\n  const size_t requested = GetParam();\n  CordBuffer from = CordBuffer::CreateWithDefaultLimit(requested);\n  const size_t capacity = from.capacity();\n  memcpy(from.data(), \"Abc\", 4);\n  from.SetLength(4);\n\n  CordBuffer to(std::move(from));\n  EXPECT_THAT(to.capacity(), Eq(capacity));\n  EXPECT_THAT(to.length(), Eq(4));\n  EXPECT_THAT(absl::string_view(to.data()), Eq(\"Abc\"));\n\n  EXPECT_THAT(from.length(), Eq(0));  // NOLINT\n}\n\nTEST_P(CordBufferTest, MoveAssign) {\n  const size_t requested = GetParam();\n  CordBuffer from = CordBuffer::CreateWithDefaultLimit(requested);\n  const size_t capacity = from.capacity();\n  memcpy(from.data(), \"Abc\", 4);\n  from.SetLength(4);\n\n  CordBuffer to;\n  to = std::move(from);\n  EXPECT_THAT(to.capacity(), Eq(capacity));\n  EXPECT_THAT(to.length(), Eq(4));\n  EXPECT_THAT(absl::string_view(to.data()), Eq(\"Abc\"));\n\n  EXPECT_THAT(from.length(), Eq(0));  // NOLINT\n}\n\nTEST_P(CordBufferTest, ConsumeValue) {\n  const size_t requested = GetParam();\n  CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(requested);\n  memcpy(buffer.data(), \"Abc\", 4);\n  buffer.SetLength(3);\n\n  absl::string_view short_value;\n  if (cord_internal::CordRep* rep =\n          CordBufferTestPeer::ConsumeValue(buffer, short_value)) {\n    EXPECT_THAT(CordToString(rep), Eq(\"Abc\"));\n    cord_internal::CordRep::Unref(rep);\n  } else {\n    EXPECT_THAT(short_value, Eq(\"Abc\"));\n  }\n  EXPECT_THAT(buffer.length(), Eq(0));\n}\n\nTEST_P(CordBufferTest, CreateWithCustomLimitWithinDefaultLimit) {\n  const size_t requested = GetParam();\n  CordBuffer buffer =\n      CordBuffer::CreateWithCustomLimit(kMaxFlatSize, requested);\n  EXPECT_THAT(buffer.capacity(), Ge(requested));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(kMaxFlatSize, requested)));\n  EXPECT_THAT(buffer.length(), Eq(0));\n\n  memset(buffer.data(), 0xCD, buffer.capacity());\n\n  std::string data(requested - 1, 'x');\n  memcpy(buffer.data(), data.c_str(), requested);\n  buffer.SetLength(requested);\n\n  EXPECT_THAT(buffer.length(), Eq(requested));\n  EXPECT_THAT(absl::string_view(buffer.data()), Eq(data));\n}\n\nTEST(CordLargeBufferTest, CreateAtOrBelowDefaultLimit) {\n  CordBuffer buffer = CordBuffer::CreateWithCustomLimit(k64KiB, kDefaultLimit);\n  EXPECT_THAT(buffer.capacity(), Ge(kDefaultLimit));\n  EXPECT_THAT(buffer.capacity(),\n              Le(MaxCapacityFor(kMaxFlatSize, kDefaultLimit)));\n\n  buffer = CordBuffer::CreateWithCustomLimit(k64KiB, 3178);\n  EXPECT_THAT(buffer.capacity(), Ge(3178));\n}\n\nTEST(CordLargeBufferTest, CreateWithCustomLimit) {\n  ASSERT_THAT((kMaxFlatSize & (kMaxFlatSize - 1)) == 0, \"Must be power of 2\");\n\n  for (size_t size = kMaxFlatSize; size <= kCustomLimit; size *= 2) {\n    CordBuffer buffer = CordBuffer::CreateWithCustomLimit(size, size);\n    size_t expected = size - kFlatOverhead;\n    ASSERT_THAT(buffer.capacity(), Ge(expected));\n    EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(size, expected)));\n  }\n}\n\nTEST(CordLargeBufferTest, CreateWithTooLargeLimit) {\n  CordBuffer buffer = CordBuffer::CreateWithCustomLimit(k64KiB, k1MB);\n  ASSERT_THAT(buffer.capacity(), Ge(k64KiB - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(k64KiB, k1MB)));\n}\n\nTEST(CordLargeBufferTest, CreateWithHugeValueForOverFlowHardening) {\n  for (size_t dist_from_max = 0; dist_from_max <= 32; ++dist_from_max) {\n    size_t capacity = std::numeric_limits<size_t>::max() - dist_from_max;\n\n    CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(capacity);\n    ASSERT_THAT(buffer.capacity(), Ge(kDefaultLimit));\n    EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(kMaxFlatSize, capacity)));\n\n    for (size_t limit = kMaxFlatSize; limit <= kCustomLimit; limit *= 2) {\n      CordBuffer buffer = CordBuffer::CreateWithCustomLimit(limit, capacity);\n      ASSERT_THAT(buffer.capacity(), Ge(limit - kFlatOverhead));\n      EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(limit, capacity)));\n    }\n  }\n}\n\nTEST(CordLargeBufferTest, CreateWithSmallLimit) {\n  CordBuffer buffer = CordBuffer::CreateWithCustomLimit(512, 1024);\n  ASSERT_THAT(buffer.capacity(), Ge(512 - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(512, 1024)));\n\n  // Ask for precise block size, should return size - kOverhead\n  buffer = CordBuffer::CreateWithCustomLimit(512, 512);\n  ASSERT_THAT(buffer.capacity(), Ge(512 - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(512, 512)));\n\n  // Corner case: 511 < block_size, but 511 + kOverhead is above\n  buffer = CordBuffer::CreateWithCustomLimit(512, 511);\n  ASSERT_THAT(buffer.capacity(), Ge(512 - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(512, 511)));\n\n  // Corner case: 498 + kOverhead < block_size\n  buffer = CordBuffer::CreateWithCustomLimit(512, 498);\n  ASSERT_THAT(buffer.capacity(), Ge(512 - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(512, 498)));\n}\n\nTEST(CordLargeBufferTest, CreateWasteFull) {\n  // 15 KiB gets rounded down to next pow2 value.\n  const size_t requested = (15 << 10);\n  CordBuffer buffer = CordBuffer::CreateWithCustomLimit(k16KiB, requested);\n  ASSERT_THAT(buffer.capacity(), Ge(k8KiB - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(k8KiB, requested)));\n}\n\nTEST(CordLargeBufferTest, CreateSmallSlop) {\n  const size_t requested = k16KiB - 2 * kFlatOverhead;\n  CordBuffer buffer = CordBuffer::CreateWithCustomLimit(k16KiB, requested);\n  ASSERT_THAT(buffer.capacity(), Ge(k16KiB - kFlatOverhead));\n  EXPECT_THAT(buffer.capacity(), Le(MaxCapacityFor(k16KiB, requested)));\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/cord_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/cord.h\"\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <cstring>\n#include <iostream>\n#include <iterator>\n#include <limits>\n#include <optional>\n#include <random>\n#include <set>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/base/options.h\"\n#include \"absl/container/fixed_array.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/log.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/cord_buffer.h\"\n#include \"absl/strings/cord_test_helpers.h\"\n#include \"absl/strings/cordz_test_helpers.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/strings/internal/string_constant.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/compare.h\"\n\n// convenience local constants\nstatic constexpr auto FLAT = absl::cord_internal::FLAT;\nstatic constexpr auto MAX_FLAT_TAG = absl::cord_internal::MAX_FLAT_TAG;\n\ntypedef std::mt19937_64 RandomEngine;\n\nusing absl::cord_internal::CordRep;\nusing absl::cord_internal::CordRepBtree;\nusing absl::cord_internal::CordRepConcat;\nusing absl::cord_internal::CordRepCrc;\nusing absl::cord_internal::CordRepExternal;\nusing absl::cord_internal::CordRepFlat;\nusing absl::cord_internal::CordRepSubstring;\nusing absl::cord_internal::CordzUpdateTracker;\nusing absl::cord_internal::kFlatOverhead;\nusing absl::cord_internal::kMaxFlatLength;\nusing ::testing::ElementsAre;\nusing ::testing::Le;\n\nstatic std::string RandomLowercaseString(RandomEngine* rng);\nstatic std::string RandomLowercaseString(RandomEngine* rng, size_t length);\n\nstatic int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) {\n  if (upper_bound > 0) {\n    std::uniform_int_distribution<int> uniform(0, upper_bound - 1);\n    return uniform(*rng);\n  } else {\n    return 0;\n  }\n}\n\nstatic size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) {\n  if (upper_bound > 0) {\n    std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1);\n    return uniform(*rng);\n  } else {\n    return 0;\n  }\n}\n\nstatic int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) {\n  const uint32_t base = (*rng)() % (max_log + 1);\n  const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;\n  return (*rng)() & mask;\n}\n\nstatic std::string RandomLowercaseString(RandomEngine* rng) {\n  int length;\n  std::bernoulli_distribution one_in_1k(0.001);\n  std::bernoulli_distribution one_in_10k(0.0001);\n  // With low probability, make a large fragment\n  if (one_in_10k(*rng)) {\n    length = GetUniformRandomUpTo(rng, 1048576);\n  } else if (one_in_1k(*rng)) {\n    length = GetUniformRandomUpTo(rng, 10000);\n  } else {\n    length = GenerateSkewedRandom(rng, 10);\n  }\n  return RandomLowercaseString(rng, length);\n}\n\nstatic std::string RandomLowercaseString(RandomEngine* rng, size_t length) {\n  std::string result(length, '\\0');\n  std::uniform_int_distribution<int> chars('a', 'z');\n  std::generate(result.begin(), result.end(),\n                [&]() { return static_cast<char>(chars(*rng)); });\n  return result;\n}\n\nstatic void DoNothing(absl::string_view /* data */, void* /* arg */) {}\n\nstatic void DeleteExternalString(absl::string_view data, void* arg) {\n  std::string* s = reinterpret_cast<std::string*>(arg);\n  EXPECT_EQ(data, *s);\n  delete s;\n}\n\n// Add \"s\" to *dst via `MakeCordFromExternal`\nstatic void AddExternalMemory(absl::string_view s, absl::Cord* dst) {\n  std::string* str = new std::string(s.data(), s.size());\n  dst->Append(absl::MakeCordFromExternal(*str, [str](absl::string_view data) {\n    DeleteExternalString(data, str);\n  }));\n}\n\nstatic void DumpGrowth() {\n  absl::Cord str;\n  for (int i = 0; i < 1000; i++) {\n    char c = 'a' + i % 26;\n    str.Append(absl::string_view(&c, 1));\n  }\n}\n\n// Make a Cord with some number of fragments.  Return the size (in bytes)\n// of the smallest fragment.\nstatic size_t AppendWithFragments(const std::string& s, RandomEngine* rng,\n                                  absl::Cord* cord) {\n  size_t j = 0;\n  const size_t max_size = s.size() / 5;  // Make approx. 10 fragments\n  size_t min_size = max_size;            // size of smallest fragment\n  while (j < s.size()) {\n    size_t N = 1 + GetUniformRandomUpTo(rng, max_size);\n    if (N > (s.size() - j)) {\n      N = s.size() - j;\n    }\n    if (N < min_size) {\n      min_size = N;\n    }\n\n    std::bernoulli_distribution coin_flip(0.5);\n    if (coin_flip(*rng)) {\n      // Grow by adding an external-memory.\n      AddExternalMemory(absl::string_view(s.data() + j, N), cord);\n    } else {\n      cord->Append(absl::string_view(s.data() + j, N));\n    }\n    j += N;\n  }\n  return min_size;\n}\n\n// Add an external memory that contains the specified std::string to cord\nstatic void AddNewStringBlock(const std::string& str, absl::Cord* dst) {\n  char* data = new char[str.size()];\n  memcpy(data, str.data(), str.size());\n  dst->Append(absl::MakeCordFromExternal(\n      absl::string_view(data, str.size()),\n      [](absl::string_view s) { delete[] s.data(); }));\n}\n\n// Make a Cord out of many different types of nodes.\nstatic absl::Cord MakeComposite() {\n  absl::Cord cord;\n  cord.Append(\"the\");\n  AddExternalMemory(\" quick brown\", &cord);\n  AddExternalMemory(\" fox jumped\", &cord);\n\n  absl::Cord full(\" over\");\n  AddExternalMemory(\" the lazy\", &full);\n  AddNewStringBlock(\" dog slept the whole day away\", &full);\n  absl::Cord substring = full.Subcord(0, 18);\n\n  // Make substring long enough to defeat the copying fast path in Append.\n  substring.Append(std::string(1000, '.'));\n  cord.Append(substring);\n  cord = cord.Subcord(0, cord.size() - 998);  // Remove most of extra junk\n\n  return cord;\n}\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass CordTestPeer {\n public:\n  static void ForEachChunk(\n      const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {\n    c.ForEachChunk(callback);\n  }\n\n  static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }\n  static CordRep* Tree(const Cord& c) { return c.contents_.tree(); }\n\n  static cord_internal::CordzInfo* GetCordzInfo(const Cord& c) {\n    return c.contents_.cordz_info();\n  }\n\n  static Cord MakeSubstring(Cord src, size_t offset, size_t length) {\n    CHECK(src.contents_.is_tree()) << \"Can not be inlined\";\n    CHECK(!src.ExpectedChecksum().has_value()) << \"Can not be hardened\";\n    Cord cord;\n    auto* tree = cord_internal::SkipCrcNode(src.contents_.tree());\n    auto* rep = CordRepSubstring::Create(CordRep::Ref(tree), offset, length);\n    cord.contents_.EmplaceTree(rep, CordzUpdateTracker::kSubCord);\n    return cord;\n  }\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n\n\n// The CordTest fixture runs all tests with and without expected CRCs being set\n// on the subject Cords.\nclass CordTest : public testing::TestWithParam<bool /*useCrc*/> {\n public:\n  // Returns true if test is running with Crc enabled.\n  bool UseCrc() const { return GetParam(); }\n  void MaybeHarden(absl::Cord& c) {\n    if (UseCrc()) {\n      c.SetExpectedChecksum(1);\n    }\n  }\n  absl::Cord MaybeHardened(absl::Cord c) {\n    MaybeHarden(c);\n    return c;\n  }\n\n  // Returns human readable string representation of the test parameter.\n  static std::string ToString(testing::TestParamInfo<bool> useCrc) {\n    if (useCrc.param) {\n      return \"BtreeHardened\";\n    } else {\n      return \"Btree\";\n    }\n  }\n};\n\nINSTANTIATE_TEST_SUITE_P(WithParam, CordTest, testing::Bool(),\n                         CordTest::ToString);\n\nTEST(CordRepFlat, AllFlatCapacities) {\n  // Explicitly and redundantly assert built-in min/max limits\n  static_assert(absl::cord_internal::kFlatOverhead < 32, \"\");\n  static_assert(absl::cord_internal::kMinFlatSize == 32, \"\");\n  static_assert(absl::cord_internal::kMaxLargeFlatSize == 256 << 10, \"\");\n  EXPECT_EQ(absl::cord_internal::TagToAllocatedSize(FLAT), 32);\n  EXPECT_EQ(absl::cord_internal::TagToAllocatedSize(MAX_FLAT_TAG), 256 << 10);\n\n  // Verify all tags to map perfectly back and forth, and\n  // that sizes are monotonically increasing.\n  size_t last_size = 0;\n  for (int tag = FLAT; tag <= MAX_FLAT_TAG; ++tag) {\n    size_t size = absl::cord_internal::TagToAllocatedSize(tag);\n    ASSERT_GT(size, last_size);\n    ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);\n    last_size = size;\n  }\n\n  // All flat size from 32 - 512 are 8 byte granularity\n  for (size_t size = 32; size <= 512; size += 8) {\n    ASSERT_EQ(absl::cord_internal::RoundUpForTag(size), size);\n    uint8_t tag = absl::cord_internal::AllocatedSizeToTag(size);\n    ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);\n  }\n\n  // All flat sizes from 512 - 8192 are 64 byte granularity\n  for (size_t size = 512; size <= 8192; size += 64) {\n    ASSERT_EQ(absl::cord_internal::RoundUpForTag(size), size);\n    uint8_t tag = absl::cord_internal::AllocatedSizeToTag(size);\n    ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);\n  }\n\n  // All flat sizes from 8KB to 256KB are 4KB granularity\n  for (size_t size = 8192; size <= 256 * 1024; size += 4 * 1024) {\n    ASSERT_EQ(absl::cord_internal::RoundUpForTag(size), size);\n    uint8_t tag = absl::cord_internal::AllocatedSizeToTag(size);\n    ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);\n  }\n}\n\nTEST(CordRepFlat, MaxFlatSize) {\n  CordRepFlat* flat = CordRepFlat::New(kMaxFlatLength);\n  EXPECT_EQ(flat->Capacity(), kMaxFlatLength);\n  CordRep::Unref(flat);\n\n  flat = CordRepFlat::New(kMaxFlatLength * 4);\n  EXPECT_EQ(flat->Capacity(), kMaxFlatLength);\n  CordRep::Unref(flat);\n}\n\nTEST(CordRepFlat, MaxLargeFlatSize) {\n  const size_t size = 256 * 1024 - kFlatOverhead;\n  CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), size);\n  EXPECT_GE(flat->Capacity(), size);\n  CordRep::Unref(flat);\n}\n\nTEST(CordRepFlat, AllFlatSizes) {\n  const size_t kMaxSize = 256 * 1024;\n  for (size_t size = 32; size <= kMaxSize; size *=2) {\n    const size_t length = size - kFlatOverhead - 1;\n    CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), length);\n    EXPECT_GE(flat->Capacity(), length);\n    memset(flat->Data(), 0xCD, flat->Capacity());\n    CordRep::Unref(flat);\n  }\n}\n\nTEST_P(CordTest, AllFlatSizes) {\n  using absl::strings_internal::CordTestAccess;\n\n  for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {\n    // Make a string of length s.\n    std::string src;\n    while (src.size() < s) {\n      src.push_back('a' + (src.size() % 26));\n    }\n\n    absl::Cord dst(src);\n    MaybeHarden(dst);\n    EXPECT_EQ(std::string(dst), src) << s;\n  }\n}\n\n// We create a Cord at least 128GB in size using the fact that Cords can\n// internally reference-count; thus the Cord is enormous without actually\n// consuming very much memory.\nTEST_P(CordTest, GigabyteCordFromExternal) {\n  const size_t one_gig = 1024U * 1024U * 1024U;\n  size_t max_size = 2 * one_gig;\n  if (sizeof(max_size) > 4) max_size = 128 * one_gig;\n\n  size_t length = 128 * 1024;\n  char* data = new char[length];\n  absl::Cord from = absl::MakeCordFromExternal(\n      absl::string_view(data, length),\n      [](absl::string_view sv) { delete[] sv.data(); });\n\n  // This loop may seem odd due to its combination of exponential doubling of\n  // size and incremental size increases.  We do it incrementally to be sure the\n  // Cord will need rebalancing and will exercise code that, in the past, has\n  // caused crashes in production.  We grow exponentially so that the code will\n  // execute in a reasonable amount of time.\n  absl::Cord c;\n  c.Append(from);\n  while (c.size() < max_size) {\n    c.Append(c);\n    c.Append(from);\n    c.Append(from);\n    c.Append(from);\n    c.Append(from);\n    MaybeHarden(c);\n  }\n\n  for (int i = 0; i < 1024; ++i) {\n    c.Append(from);\n  }\n  LOG(INFO) << \"Made a Cord with \" << c.size() << \" bytes!\";\n  // Note: on a 32-bit build, this comes out to   2,818,048,000 bytes.\n  // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes.\n}\n\nstatic absl::Cord MakeExternalCord(int size) {\n  char* buffer = new char[size];\n  memset(buffer, 'x', size);\n  absl::Cord cord;\n  cord.Append(absl::MakeCordFromExternal(\n      absl::string_view(buffer, size),\n      [](absl::string_view s) { delete[] s.data(); }));\n  return cord;\n}\n\n// Extern to fool clang that this is not constant. Needed to suppress\n// a warning of unsafe code we want to test.\nextern bool my_unique_true_boolean;\nbool my_unique_true_boolean = true;\n\nTEST_P(CordTest, Assignment) {\n  absl::Cord x(absl::string_view(\"hi there\"));\n  absl::Cord y(x);\n  MaybeHarden(y);\n  ASSERT_EQ(x.ExpectedChecksum(), std::nullopt);\n  ASSERT_EQ(std::string(x), \"hi there\");\n  ASSERT_EQ(std::string(y), \"hi there\");\n  ASSERT_TRUE(x == y);\n  ASSERT_TRUE(x <= y);\n  ASSERT_TRUE(y <= x);\n\n  x = absl::string_view(\"foo\");\n  ASSERT_EQ(std::string(x), \"foo\");\n  ASSERT_EQ(std::string(y), \"hi there\");\n  ASSERT_TRUE(x < y);\n  ASSERT_TRUE(y > x);\n  ASSERT_TRUE(x != y);\n  ASSERT_TRUE(x <= y);\n  ASSERT_TRUE(y >= x);\n\n  x = \"foo\";\n  ASSERT_EQ(x, \"foo\");\n\n  // Test that going from inline rep to tree we don't leak memory.\n  std::vector<std::pair<absl::string_view, absl::string_view>>\n      test_string_pairs = {{\"hi there\", \"foo\"},\n                           {\"loooooong coooooord\", \"short cord\"},\n                           {\"short cord\", \"loooooong coooooord\"},\n                           {\"loooooong coooooord1\", \"loooooong coooooord2\"}};\n  for (std::pair<absl::string_view, absl::string_view> test_strings :\n       test_string_pairs) {\n    absl::Cord tmp(test_strings.first);\n    absl::Cord z(std::move(tmp));\n    ASSERT_EQ(std::string(z), test_strings.first);\n    tmp = test_strings.second;\n    z = std::move(tmp);\n    ASSERT_EQ(std::string(z), test_strings.second);\n  }\n  {\n    // Test that self-move assignment doesn't crash/leak.\n    // Do not write such code!\n    absl::Cord my_small_cord(\"foo\");\n    absl::Cord my_big_cord(\"loooooong coooooord\");\n    // Bypass clang's warning on self move-assignment.\n    absl::Cord* my_small_alias =\n        my_unique_true_boolean ? &my_small_cord : &my_big_cord;\n    absl::Cord* my_big_alias =\n        !my_unique_true_boolean ? &my_small_cord : &my_big_cord;\n\n    *my_small_alias = std::move(my_small_cord);\n    *my_big_alias = std::move(my_big_cord);\n    // my_small_cord and my_big_cord are in an unspecified but valid\n    // state, and will be correctly destroyed here.\n  }\n}\n\nTEST_P(CordTest, StartsEndsWith) {\n  absl::Cord x(absl::string_view(\"abcde\"));\n  MaybeHarden(x);\n  absl::Cord empty(\"\");\n\n  ASSERT_TRUE(x.StartsWith(absl::Cord(\"abcde\")));\n  ASSERT_TRUE(x.StartsWith(absl::Cord(\"abc\")));\n  ASSERT_TRUE(x.StartsWith(absl::Cord(\"\")));\n  ASSERT_TRUE(empty.StartsWith(absl::Cord(\"\")));\n  ASSERT_TRUE(x.EndsWith(absl::Cord(\"abcde\")));\n  ASSERT_TRUE(x.EndsWith(absl::Cord(\"cde\")));\n  ASSERT_TRUE(x.EndsWith(absl::Cord(\"\")));\n  ASSERT_TRUE(empty.EndsWith(absl::Cord(\"\")));\n\n  ASSERT_TRUE(!x.StartsWith(absl::Cord(\"xyz\")));\n  ASSERT_TRUE(!empty.StartsWith(absl::Cord(\"xyz\")));\n  ASSERT_TRUE(!x.EndsWith(absl::Cord(\"xyz\")));\n  ASSERT_TRUE(!empty.EndsWith(absl::Cord(\"xyz\")));\n\n  ASSERT_TRUE(x.StartsWith(\"abcde\"));\n  ASSERT_TRUE(x.StartsWith(\"abc\"));\n  ASSERT_TRUE(x.StartsWith(\"\"));\n  ASSERT_TRUE(empty.StartsWith(\"\"));\n  ASSERT_TRUE(x.EndsWith(\"abcde\"));\n  ASSERT_TRUE(x.EndsWith(\"cde\"));\n  ASSERT_TRUE(x.EndsWith(\"\"));\n  ASSERT_TRUE(empty.EndsWith(\"\"));\n\n  ASSERT_TRUE(!x.StartsWith(\"xyz\"));\n  ASSERT_TRUE(!empty.StartsWith(\"xyz\"));\n  ASSERT_TRUE(!x.EndsWith(\"xyz\"));\n  ASSERT_TRUE(!empty.EndsWith(\"xyz\"));\n}\n\nTEST_P(CordTest, Contains) {\n  auto flat_haystack = absl::Cord(\"this is a flat cord\");\n  auto fragmented_haystack = absl::MakeFragmentedCord(\n      {\"this\", \" \", \"is\", \" \", \"a\", \" \", \"fragmented\", \" \", \"cord\"});\n\n  EXPECT_TRUE(flat_haystack.Contains(\"\"));\n  EXPECT_TRUE(fragmented_haystack.Contains(\"\"));\n  EXPECT_TRUE(flat_haystack.Contains(absl::Cord(\"\")));\n  EXPECT_TRUE(fragmented_haystack.Contains(absl::Cord(\"\")));\n  EXPECT_TRUE(absl::Cord(\"\").Contains(\"\"));\n  EXPECT_TRUE(absl::Cord(\"\").Contains(absl::Cord(\"\")));\n  EXPECT_FALSE(absl::Cord(\"\").Contains(flat_haystack));\n  EXPECT_FALSE(absl::Cord(\"\").Contains(fragmented_haystack));\n\n  EXPECT_FALSE(flat_haystack.Contains(\"z\"));\n  EXPECT_FALSE(fragmented_haystack.Contains(\"z\"));\n  EXPECT_FALSE(flat_haystack.Contains(absl::Cord(\"z\")));\n  EXPECT_FALSE(fragmented_haystack.Contains(absl::Cord(\"z\")));\n\n  EXPECT_FALSE(flat_haystack.Contains(\"is an\"));\n  EXPECT_FALSE(fragmented_haystack.Contains(\"is an\"));\n  EXPECT_FALSE(flat_haystack.Contains(absl::Cord(\"is an\")));\n  EXPECT_FALSE(fragmented_haystack.Contains(absl::Cord(\"is an\")));\n  EXPECT_FALSE(\n      flat_haystack.Contains(absl::MakeFragmentedCord({\"is\", \" \", \"an\"})));\n  EXPECT_FALSE(fragmented_haystack.Contains(\n      absl::MakeFragmentedCord({\"is\", \" \", \"an\"})));\n\n  EXPECT_TRUE(flat_haystack.Contains(\"is a\"));\n  EXPECT_TRUE(fragmented_haystack.Contains(\"is a\"));\n  EXPECT_TRUE(flat_haystack.Contains(absl::Cord(\"is a\")));\n  EXPECT_TRUE(fragmented_haystack.Contains(absl::Cord(\"is a\")));\n  EXPECT_TRUE(\n      flat_haystack.Contains(absl::MakeFragmentedCord({\"is\", \" \", \"a\"})));\n  EXPECT_TRUE(\n      fragmented_haystack.Contains(absl::MakeFragmentedCord({\"is\", \" \", \"a\"})));\n}\n\nTEST_P(CordTest, Find) {\n  auto flat_haystack = absl::Cord(\"this is a flat cord\");\n  auto fragmented_haystack = absl::MakeFragmentedCord(\n      {\"this\", \" \", \"is\", \" \", \"a\", \" \", \"fragmented\", \" \", \"cord\"});\n  auto empty_haystack = absl::Cord(\"\");\n\n  EXPECT_EQ(flat_haystack.Find(\"\"), flat_haystack.char_begin());\n  EXPECT_EQ(fragmented_haystack.Find(\"\"), fragmented_haystack.char_begin());\n  EXPECT_EQ(flat_haystack.Find(absl::Cord(\"\")), flat_haystack.char_begin());\n  EXPECT_EQ(fragmented_haystack.Find(absl::Cord(\"\")),\n            fragmented_haystack.char_begin());\n  EXPECT_EQ(empty_haystack.Find(\"\"), empty_haystack.char_begin());\n  EXPECT_EQ(empty_haystack.Find(absl::Cord(\"\")), empty_haystack.char_begin());\n  EXPECT_EQ(empty_haystack.Find(flat_haystack), empty_haystack.char_end());\n  EXPECT_EQ(empty_haystack.Find(fragmented_haystack),\n            empty_haystack.char_end());\n\n  EXPECT_EQ(flat_haystack.Find(\"z\"), flat_haystack.char_end());\n  EXPECT_EQ(fragmented_haystack.Find(\"z\"), fragmented_haystack.char_end());\n  EXPECT_EQ(flat_haystack.Find(absl::Cord(\"z\")), flat_haystack.char_end());\n  EXPECT_EQ(fragmented_haystack.Find(absl::Cord(\"z\")),\n            fragmented_haystack.char_end());\n\n  EXPECT_EQ(flat_haystack.Find(\"is an\"), flat_haystack.char_end());\n  EXPECT_EQ(fragmented_haystack.Find(\"is an\"), fragmented_haystack.char_end());\n  EXPECT_EQ(flat_haystack.Find(absl::Cord(\"is an\")), flat_haystack.char_end());\n  EXPECT_EQ(fragmented_haystack.Find(absl::Cord(\"is an\")),\n            fragmented_haystack.char_end());\n  EXPECT_EQ(flat_haystack.Find(absl::MakeFragmentedCord({\"is\", \" \", \"an\"})),\n            flat_haystack.char_end());\n  EXPECT_EQ(\n      fragmented_haystack.Find(absl::MakeFragmentedCord({\"is\", \" \", \"an\"})),\n      fragmented_haystack.char_end());\n\n  EXPECT_EQ(flat_haystack.Find(\"is a\"),\n            std::next(flat_haystack.char_begin(), 5));\n  EXPECT_EQ(fragmented_haystack.Find(\"is a\"),\n            std::next(fragmented_haystack.char_begin(), 5));\n  EXPECT_EQ(flat_haystack.Find(absl::Cord(\"is a\")),\n            std::next(flat_haystack.char_begin(), 5));\n  EXPECT_EQ(fragmented_haystack.Find(absl::Cord(\"is a\")),\n            std::next(fragmented_haystack.char_begin(), 5));\n  EXPECT_EQ(flat_haystack.Find(absl::MakeFragmentedCord({\"is\", \" \", \"a\"})),\n            std::next(flat_haystack.char_begin(), 5));\n  EXPECT_EQ(\n      fragmented_haystack.Find(absl::MakeFragmentedCord({\"is\", \" \", \"a\"})),\n      std::next(fragmented_haystack.char_begin(), 5));\n}\n\nTEST_P(CordTest, Subcord) {\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  const std::string s = RandomLowercaseString(&rng, 1024);\n\n  absl::Cord a;\n  AppendWithFragments(s, &rng, &a);\n  MaybeHarden(a);\n  ASSERT_EQ(s, std::string(a));\n\n  // Check subcords of a, from a variety of interesting points.\n  std::set<size_t> positions;\n  for (int i = 0; i <= 32; ++i) {\n    positions.insert(i);\n    positions.insert(i * 32 - 1);\n    positions.insert(i * 32);\n    positions.insert(i * 32 + 1);\n    positions.insert(a.size() - i);\n  }\n  positions.insert(237);\n  positions.insert(732);\n  for (size_t pos : positions) {\n    if (pos > a.size()) continue;\n    for (size_t end_pos : positions) {\n      if (end_pos < pos || end_pos > a.size()) continue;\n      absl::Cord sa = a.Subcord(pos, end_pos - pos);\n      ASSERT_EQ(absl::string_view(s).substr(pos, end_pos - pos),\n                std::string(sa))\n          << a;\n      if (pos != 0 || end_pos != a.size()) {\n        ASSERT_EQ(sa.ExpectedChecksum(), std::nullopt);\n      }\n    }\n  }\n\n  // Do the same thing for an inline cord.\n  const std::string sh = \"short\";\n  absl::Cord c(sh);\n  for (size_t pos = 0; pos <= sh.size(); ++pos) {\n    for (size_t n = 0; n <= sh.size() - pos; ++n) {\n      absl::Cord sc = c.Subcord(pos, n);\n      ASSERT_EQ(sh.substr(pos, n), std::string(sc)) << c;\n    }\n  }\n\n  // Check subcords of subcords.\n  absl::Cord sa = a.Subcord(0, a.size());\n  std::string ss = s.substr(0, s.size());\n  while (sa.size() > 1) {\n    sa = sa.Subcord(1, sa.size() - 2);\n    ss = ss.substr(1, ss.size() - 2);\n    ASSERT_EQ(ss, std::string(sa)) << a;\n    if (HasFailure()) break;  // halt cascade\n  }\n\n  // It is OK to ask for too much.\n  sa = a.Subcord(0, a.size() + 1);\n  EXPECT_EQ(s, std::string(sa));\n\n  // It is OK to ask for something beyond the end.\n  sa = a.Subcord(a.size() + 1, 0);\n  EXPECT_TRUE(sa.empty());\n  sa = a.Subcord(a.size() + 1, 1);\n  EXPECT_TRUE(sa.empty());\n}\n\nTEST_P(CordTest, Swap) {\n  absl::string_view a(\"Dexter\");\n  absl::string_view b(\"Mandark\");\n  absl::Cord x(a);\n  absl::Cord y(b);\n  MaybeHarden(x);\n  swap(x, y);\n  if (UseCrc()) {\n    ASSERT_EQ(x.ExpectedChecksum(), std::nullopt);\n    ASSERT_EQ(y.ExpectedChecksum(), 1);\n  }\n  ASSERT_EQ(x, absl::Cord(b));\n  ASSERT_EQ(y, absl::Cord(a));\n  x.swap(y);\n  if (UseCrc()) {\n    ASSERT_EQ(x.ExpectedChecksum(), 1);\n    ASSERT_EQ(y.ExpectedChecksum(), std::nullopt);\n  }\n  ASSERT_EQ(x, absl::Cord(a));\n  ASSERT_EQ(y, absl::Cord(b));\n}\n\nstatic void VerifyCopyToString(const absl::Cord& cord) {\n  std::string initially_empty;\n  absl::CopyCordToString(cord, &initially_empty);\n  EXPECT_EQ(initially_empty, cord);\n\n  constexpr size_t kInitialLength = 1024;\n  std::string has_initial_contents(kInitialLength, 'x');\n  const char* address_before_copy = has_initial_contents.data();\n  absl::CopyCordToString(cord, &has_initial_contents);\n  EXPECT_EQ(has_initial_contents, cord);\n\n  if (cord.size() <= kInitialLength) {\n    EXPECT_EQ(has_initial_contents.data(), address_before_copy)\n        << \"CopyCordToString allocated new string storage; \"\n           \"has_initial_contents = \\\"\"\n        << has_initial_contents << \"\\\"\";\n  }\n}\n\nTEST_P(CordTest, CopyToString) {\n  VerifyCopyToString(absl::Cord());  // empty cords cannot carry CRCs\n  VerifyCopyToString(MaybeHardened(absl::Cord(\"small cord\")));\n  VerifyCopyToString(MaybeHardened(\n      absl::MakeFragmentedCord({\"fragmented \", \"cord \", \"to \", \"test \",\n                                \"copying \", \"to \", \"a \", \"string.\"})));\n}\n\nstatic void VerifyAppendCordToString(const absl::Cord& cord) {\n  std::string initially_empty;\n  absl::AppendCordToString(cord, &initially_empty);\n  EXPECT_EQ(initially_empty, cord);\n\n  const absl::string_view kInitialContents = \"initial contents.\";\n  std::string expected_after_append =\n      absl::StrCat(kInitialContents, std::string(cord));\n\n  std::string no_reserve(kInitialContents);\n  absl::AppendCordToString(cord, &no_reserve);\n  EXPECT_EQ(no_reserve, expected_after_append);\n\n  std::string has_reserved_capacity(kInitialContents);\n  has_reserved_capacity.reserve(has_reserved_capacity.size() + cord.size());\n  const char* address_before_copy = has_reserved_capacity.data();\n  absl::AppendCordToString(cord, &has_reserved_capacity);\n  EXPECT_EQ(has_reserved_capacity, expected_after_append);\n  EXPECT_EQ(has_reserved_capacity.data(), address_before_copy)\n      << \"AppendCordToString allocated new string storage; \"\n         \"has_reserved_capacity = \\\"\"\n      << has_reserved_capacity << \"\\\"\";\n}\n\nTEST_P(CordTest, AppendToString) {\n  VerifyAppendCordToString(absl::Cord());  // empty cords cannot carry CRCs\n  VerifyAppendCordToString(MaybeHardened(absl::Cord(\"small cord\")));\n  VerifyAppendCordToString(MaybeHardened(\n      absl::MakeFragmentedCord({\"fragmented \", \"cord \", \"to \", \"test \",\n                                \"appending \", \"to \", \"a \", \"string.\"})));\n}\n\nTEST_P(CordTest, AppendEmptyBuffer) {\n  absl::Cord cord;\n  cord.Append(absl::CordBuffer());\n  cord.Append(absl::CordBuffer::CreateWithDefaultLimit(2000));\n}\n\nTEST_P(CordTest, AppendEmptyBufferToFlat) {\n  absl::Cord cord(std::string(2000, 'x'));\n  cord.Append(absl::CordBuffer());\n  cord.Append(absl::CordBuffer::CreateWithDefaultLimit(2000));\n}\n\nTEST_P(CordTest, AppendEmptyBufferToTree) {\n  absl::Cord cord(std::string(2000, 'x'));\n  cord.Append(std::string(2000, 'y'));\n  cord.Append(absl::CordBuffer());\n  cord.Append(absl::CordBuffer::CreateWithDefaultLimit(2000));\n}\n\nTEST_P(CordTest, AppendSmallBuffer) {\n  absl::Cord cord;\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(3);\n  ASSERT_THAT(buffer.capacity(), Le(15));\n  memcpy(buffer.data(), \"Abc\", 3);\n  buffer.SetLength(3);\n  cord.Append(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  buffer = absl::CordBuffer::CreateWithDefaultLimit(3);\n  memcpy(buffer.data(), \"defgh\", 5);\n  buffer.SetLength(5);\n  cord.Append(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  EXPECT_THAT(cord.Chunks(), ElementsAre(\"Abcdefgh\"));\n}\n\nTEST_P(CordTest, AppendAndPrependBufferArePrecise) {\n  // Create a cord large enough to force 40KB flats.\n  std::string test_data(absl::cord_internal::kMaxFlatLength * 10, 'x');\n  absl::Cord cord1(test_data);\n  absl::Cord cord2(test_data);\n  const size_t size1 = cord1.EstimatedMemoryUsage();\n  const size_t size2 = cord2.EstimatedMemoryUsage();\n\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(3);\n  memcpy(buffer.data(), \"Abc\", 3);\n  buffer.SetLength(3);\n  cord1.Append(std::move(buffer));\n\n  buffer = absl::CordBuffer::CreateWithDefaultLimit(3);\n  memcpy(buffer.data(), \"Abc\", 3);\n  buffer.SetLength(3);\n  cord2.Prepend(std::move(buffer));\n\n#ifndef NDEBUG\n  // Allow 32 bytes new CordRepFlat, and 128 bytes for 'glue nodes'\n  constexpr size_t kMaxDelta = 128 + 32;\n#else\n  // Allow 256 bytes extra for 'allocation debug overhead'\n  constexpr size_t kMaxDelta = 128 + 32 + 256;\n#endif\n\n  EXPECT_LE(cord1.EstimatedMemoryUsage() - size1, kMaxDelta);\n  EXPECT_LE(cord2.EstimatedMemoryUsage() - size2, kMaxDelta);\n\n  EXPECT_EQ(cord1, absl::StrCat(test_data, \"Abc\"));\n  EXPECT_EQ(cord2, absl::StrCat(\"Abc\", test_data));\n}\n\nTEST_P(CordTest, PrependSmallBuffer) {\n  absl::Cord cord;\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(3);\n  ASSERT_THAT(buffer.capacity(), Le(15));\n  memcpy(buffer.data(), \"Abc\", 3);\n  buffer.SetLength(3);\n  cord.Prepend(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  buffer = absl::CordBuffer::CreateWithDefaultLimit(3);\n  memcpy(buffer.data(), \"defgh\", 5);\n  buffer.SetLength(5);\n  cord.Prepend(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  EXPECT_THAT(cord.Chunks(), ElementsAre(\"defghAbc\"));\n}\n\nTEST_P(CordTest, AppendLargeBuffer) {\n  absl::Cord cord;\n\n  std::string s1(700, '1');\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(s1.size());\n  memcpy(buffer.data(), s1.data(), s1.size());\n  buffer.SetLength(s1.size());\n  cord.Append(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  std::string s2(1000, '2');\n  buffer = absl::CordBuffer::CreateWithDefaultLimit(s2.size());\n  memcpy(buffer.data(), s2.data(), s2.size());\n  buffer.SetLength(s2.size());\n  cord.Append(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  EXPECT_THAT(cord.Chunks(), ElementsAre(s1, s2));\n}\n\nTEST_P(CordTest, PrependLargeBuffer) {\n  absl::Cord cord;\n\n  std::string s1(700, '1');\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(s1.size());\n  memcpy(buffer.data(), s1.data(), s1.size());\n  buffer.SetLength(s1.size());\n  cord.Prepend(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  std::string s2(1000, '2');\n  buffer = absl::CordBuffer::CreateWithDefaultLimit(s2.size());\n  memcpy(buffer.data(), s2.data(), s2.size());\n  buffer.SetLength(s2.size());\n  cord.Prepend(std::move(buffer));\n  EXPECT_EQ(buffer.length(), 0);    // NOLINT\n  EXPECT_GT(buffer.capacity(), 0);  // NOLINT\n\n  EXPECT_THAT(cord.Chunks(), ElementsAre(s2, s1));\n}\n\nclass CordAppendBufferTest : public testing::TestWithParam<bool> {\n public:\n  size_t is_default() const { return GetParam(); }\n\n  // Returns human readable string representation of the test parameter.\n  static std::string ToString(testing::TestParamInfo<bool> param) {\n    return param.param ? \"DefaultLimit\" : \"CustomLimit\";\n  }\n\n  size_t limit() const {\n    return is_default() ? absl::CordBuffer::kDefaultLimit\n                        : absl::CordBuffer::kCustomLimit;\n  }\n\n  size_t maximum_payload() const {\n    return is_default() ? absl::CordBuffer::MaximumPayload()\n                        : absl::CordBuffer::MaximumPayload(limit());\n  }\n\n  absl::CordBuffer GetAppendBuffer(absl::Cord& cord, size_t capacity,\n                                   size_t min_capacity = 16) {\n    return is_default()\n               ? cord.GetAppendBuffer(capacity, min_capacity)\n               : cord.GetCustomAppendBuffer(limit(), capacity, min_capacity);\n  }\n};\n\nINSTANTIATE_TEST_SUITE_P(WithParam, CordAppendBufferTest, testing::Bool(),\n                         CordAppendBufferTest::ToString);\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnEmptyCord) {\n  absl::Cord cord;\n  absl::CordBuffer buffer = GetAppendBuffer(cord, 1000);\n  EXPECT_GE(buffer.capacity(), 1000);\n  EXPECT_EQ(buffer.length(), 0);\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnInlinedCord) {\n  static constexpr int kInlinedSize = sizeof(absl::CordBuffer) - 1;\n  for (int size : {6, kInlinedSize - 3, kInlinedSize - 2, 1000}) {\n    absl::Cord cord(\"Abc\");\n    absl::CordBuffer buffer = GetAppendBuffer(cord, size, 1);\n    EXPECT_GE(buffer.capacity(), 3 + size);\n    EXPECT_EQ(buffer.length(), 3);\n    EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), \"Abc\");\n    EXPECT_TRUE(cord.empty());\n  }\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnInlinedCordCapacityCloseToMax) {\n  // Cover the use case where we have a non empty inlined cord with some size\n  // 'n', and ask for something like 'uint64_max - k', assuming internal logic\n  // could overflow on 'uint64_max - k + size', and return a valid, but\n  // inefficiently smaller buffer if it would provide is the max allowed size.\n  for (size_t dist_from_max = 0; dist_from_max <= 4; ++dist_from_max) {\n    absl::Cord cord(\"Abc\");\n    size_t size = std::numeric_limits<size_t>::max() - dist_from_max;\n    absl::CordBuffer buffer = GetAppendBuffer(cord, size, 1);\n    EXPECT_GE(buffer.capacity(), maximum_payload());\n    EXPECT_EQ(buffer.length(), 3);\n    EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), \"Abc\");\n    EXPECT_TRUE(cord.empty());\n  }\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnFlat) {\n  // Create a cord with a single flat and extra capacity\n  absl::Cord cord;\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n  const size_t expected_capacity = buffer.capacity();\n  buffer.SetLength(3);\n  memcpy(buffer.data(), \"Abc\", 3);\n  cord.Append(std::move(buffer));\n\n  buffer = GetAppendBuffer(cord, 6);\n  EXPECT_EQ(buffer.capacity(), expected_capacity);\n  EXPECT_EQ(buffer.length(), 3);\n  EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), \"Abc\");\n  EXPECT_TRUE(cord.empty());\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnFlatWithoutMinCapacity) {\n  // Create a cord with a single flat and extra capacity\n  absl::Cord cord;\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n  buffer.SetLength(30);\n  memset(buffer.data(), 'x', 30);\n  cord.Append(std::move(buffer));\n\n  buffer = GetAppendBuffer(cord, 1000, 900);\n  EXPECT_GE(buffer.capacity(), 1000);\n  EXPECT_EQ(buffer.length(), 0);\n  EXPECT_EQ(cord, std::string(30, 'x'));\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnTree) {\n  RandomEngine rng;\n  for (int num_flats : {2, 3, 100}) {\n    // Create a cord with `num_flats` flats and extra capacity\n    absl::Cord cord;\n    std::string prefix;\n    std::string last;\n    for (int i = 0; i < num_flats - 1; ++i) {\n      prefix += last;\n      last = RandomLowercaseString(&rng, 10);\n      absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n      buffer.SetLength(10);\n      memcpy(buffer.data(), last.data(), 10);\n      cord.Append(std::move(buffer));\n    }\n    absl::CordBuffer buffer = GetAppendBuffer(cord, 6);\n    EXPECT_GE(buffer.capacity(), 500);\n    EXPECT_EQ(buffer.length(), 10);\n    EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), last);\n    EXPECT_EQ(cord, prefix);\n  }\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnTreeWithoutMinCapacity) {\n  absl::Cord cord;\n  for (int i = 0; i < 2; ++i) {\n    absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n    buffer.SetLength(3);\n    memcpy(buffer.data(), i ? \"def\" : \"Abc\", 3);\n    cord.Append(std::move(buffer));\n  }\n  absl::CordBuffer buffer = GetAppendBuffer(cord, 1000, 900);\n  EXPECT_GE(buffer.capacity(), 1000);\n  EXPECT_EQ(buffer.length(), 0);\n  EXPECT_EQ(cord, \"Abcdef\");\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnSubstring) {\n  // Create a large cord with a single flat and some extra capacity\n  absl::Cord cord;\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n  buffer.SetLength(450);\n  memset(buffer.data(), 'x', 450);\n  cord.Append(std::move(buffer));\n  cord.RemovePrefix(1);\n\n  // Deny on substring\n  buffer = GetAppendBuffer(cord, 6);\n  EXPECT_EQ(buffer.length(), 0);\n  EXPECT_EQ(cord, std::string(449, 'x'));\n}\n\nTEST_P(CordAppendBufferTest, GetAppendBufferOnSharedCord) {\n  // Create a shared cord with a single flat and extra capacity\n  absl::Cord cord;\n  absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n  buffer.SetLength(3);\n  memcpy(buffer.data(), \"Abc\", 3);\n  cord.Append(std::move(buffer));\n  absl::Cord shared_cord = cord;\n\n  // Deny on flat\n  buffer = GetAppendBuffer(cord, 6);\n  EXPECT_EQ(buffer.length(), 0);\n  EXPECT_EQ(cord, \"Abc\");\n\n  buffer = absl::CordBuffer::CreateWithDefaultLimit(500);\n  buffer.SetLength(3);\n  memcpy(buffer.data(), \"def\", 3);\n  cord.Append(std::move(buffer));\n  shared_cord = cord;\n\n  // Deny on tree\n  buffer = GetAppendBuffer(cord, 6);\n  EXPECT_EQ(buffer.length(), 0);\n  EXPECT_EQ(cord, \"Abcdef\");\n}\n\nTEST_P(CordTest, TryFlatEmpty) {\n  absl::Cord c;\n  EXPECT_EQ(c.TryFlat(), \"\");\n}\n\nTEST_P(CordTest, TryFlatFlat) {\n  absl::Cord c(\"hello\");\n  MaybeHarden(c);\n  EXPECT_EQ(c.TryFlat(), \"hello\");\n}\n\nTEST_P(CordTest, TryFlatSubstrInlined) {\n  absl::Cord c(\"hello\");\n  c.RemovePrefix(1);\n  MaybeHarden(c);\n  EXPECT_EQ(c.TryFlat(), \"ello\");\n}\n\nTEST_P(CordTest, TryFlatSubstrFlat) {\n  absl::Cord c(\"longer than 15 bytes\");\n  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);\n  MaybeHarden(sub);\n  EXPECT_EQ(sub.TryFlat(), \"onger than 15 bytes\");\n}\n\nTEST_P(CordTest, TryFlatConcat) {\n  absl::Cord c = absl::MakeFragmentedCord({\"hel\", \"lo\"});\n  MaybeHarden(c);\n  EXPECT_EQ(c.TryFlat(), std::nullopt);\n}\n\nTEST_P(CordTest, TryFlatExternal) {\n  absl::Cord c = absl::MakeCordFromExternal(\"hell\", [](absl::string_view) {});\n  MaybeHarden(c);\n  EXPECT_EQ(c.TryFlat(), \"hell\");\n}\n\nTEST_P(CordTest, TryFlatSubstrExternal) {\n  absl::Cord c = absl::MakeCordFromExternal(\"hell\", [](absl::string_view) {});\n  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);\n  MaybeHarden(sub);\n  EXPECT_EQ(sub.TryFlat(), \"ell\");\n}\n\nTEST_P(CordTest, TryFlatCommonlyAssumedInvariants) {\n  // The behavior tested below is not part of the API contract of Cord, but it's\n  // something we intend to be true in our current implementation.  This test\n  // exists to detect and prevent accidental breakage of the implementation.\n  absl::string_view fragments[] = {\"A fragmented test\",\n                                   \" cord\",\n                                   \" to test subcords\",\n                                   \" of \",\n                                   \"a\",\n                                   \" cord for\",\n                                   \" each chunk \"\n                                   \"returned by the \",\n                                   \"iterator\"};\n  absl::Cord c = absl::MakeFragmentedCord(fragments);\n  MaybeHarden(c);\n  int fragment = 0;\n  int offset = 0;\n  absl::Cord::CharIterator itc = c.char_begin();\n  for (absl::string_view sv : c.Chunks()) {\n    absl::string_view expected = fragments[fragment];\n    absl::Cord subcord1 = c.Subcord(offset, sv.length());\n    absl::Cord subcord2 = absl::Cord::AdvanceAndRead(&itc, sv.size());\n    EXPECT_EQ(subcord1.TryFlat(), expected);\n    EXPECT_EQ(subcord2.TryFlat(), expected);\n    ++fragment;\n    offset += sv.length();\n  }\n}\n\nstatic bool IsFlat(const absl::Cord& c) {\n  return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();\n}\n\nstatic void VerifyFlatten(absl::Cord c) {\n  std::string old_contents(c);\n  absl::string_view old_flat;\n  bool already_flat_and_non_empty = IsFlat(c) && !c.empty();\n  if (already_flat_and_non_empty) {\n    old_flat = *c.chunk_begin();\n  }\n  absl::string_view new_flat = c.Flatten();\n\n  // Verify that the contents of the flattened Cord are correct.\n  EXPECT_EQ(new_flat, old_contents);\n  EXPECT_EQ(std::string(c), old_contents);\n\n  // If the Cord contained data and was already flat, verify that the data\n  // wasn't copied.\n  if (already_flat_and_non_empty) {\n    EXPECT_EQ(old_flat.data(), new_flat.data())\n        << \"Allocated new memory even though the Cord was already flat.\";\n  }\n\n  // Verify that the flattened Cord is in fact flat.\n  EXPECT_TRUE(IsFlat(c));\n}\n\nTEST_P(CordTest, Flatten) {\n  VerifyFlatten(absl::Cord());\n  VerifyFlatten(MaybeHardened(absl::Cord(\"small cord\")));\n  VerifyFlatten(\n      MaybeHardened(absl::Cord(\"larger than small buffer optimization\")));\n  VerifyFlatten(MaybeHardened(\n      absl::MakeFragmentedCord({\"small \", \"fragmented \", \"cord\"})));\n\n  // Test with a cord that is longer than the largest flat buffer\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  VerifyFlatten(MaybeHardened(absl::Cord(RandomLowercaseString(&rng, 8192))));\n}\n\n// Test data\nnamespace {\nclass TestData {\n private:\n  std::vector<std::string> data_;\n\n  // Return a std::string of the specified length.\n  static std::string MakeString(int length) {\n    std::string result;\n    char buf[30];\n    snprintf(buf, sizeof(buf), \"(%d)\", length);\n    while (result.size() < length) {\n      result += buf;\n    }\n    result.resize(length);\n    return result;\n  }\n\n public:\n  TestData() {\n    // short strings increasing in length by one\n    for (int i = 0; i < 30; i++) {\n      data_.push_back(MakeString(i));\n    }\n\n    // strings around half kMaxFlatLength\n    static const int kMaxFlatLength = 4096 - 9;\n    static const int kHalf = kMaxFlatLength / 2;\n\n    for (int i = -10; i <= +10; i++) {\n      data_.push_back(MakeString(kHalf + i));\n    }\n\n    for (int i = -10; i <= +10; i++) {\n      data_.push_back(MakeString(kMaxFlatLength + i));\n    }\n  }\n\n  size_t size() const { return data_.size(); }\n  const std::string& data(size_t i) const { return data_[i]; }\n};\n}  // namespace\n\nTEST_P(CordTest, MultipleLengths) {\n  TestData d;\n  for (size_t i = 0; i < d.size(); i++) {\n    std::string a = d.data(i);\n\n    {  // Construct from Cord\n      absl::Cord tmp(a);\n      absl::Cord x(tmp);\n      MaybeHarden(x);\n      EXPECT_EQ(a, std::string(x)) << \"'\" << a << \"'\";\n    }\n\n    {  // Construct from absl::string_view\n      absl::Cord x(a);\n      MaybeHarden(x);\n      EXPECT_EQ(a, std::string(x)) << \"'\" << a << \"'\";\n    }\n\n    {  // Append cord to self\n      absl::Cord self(a);\n      MaybeHarden(self);\n      self.Append(self);\n      EXPECT_EQ(a + a, std::string(self)) << \"'\" << a << \"' + '\" << a << \"'\";\n    }\n\n    {  // Prepend cord to self\n      absl::Cord self(a);\n      MaybeHarden(self);\n      self.Prepend(self);\n      EXPECT_EQ(a + a, std::string(self)) << \"'\" << a << \"' + '\" << a << \"'\";\n    }\n\n    // Try to append/prepend others\n    for (size_t j = 0; j < d.size(); j++) {\n      std::string b = d.data(j);\n\n      {  // CopyFrom Cord\n        absl::Cord x(a);\n        absl::Cord y(b);\n        MaybeHarden(x);\n        x = y;\n        EXPECT_EQ(b, std::string(x)) << \"'\" << a << \"' + '\" << b << \"'\";\n      }\n\n      {  // CopyFrom absl::string_view\n        absl::Cord x(a);\n        MaybeHarden(x);\n        x = b;\n        EXPECT_EQ(b, std::string(x)) << \"'\" << a << \"' + '\" << b << \"'\";\n      }\n\n      {  // Cord::Append(Cord)\n        absl::Cord x(a);\n        absl::Cord y(b);\n        MaybeHarden(x);\n        x.Append(y);\n        EXPECT_EQ(a + b, std::string(x)) << \"'\" << a << \"' + '\" << b << \"'\";\n      }\n\n      {  // Cord::Append(absl::string_view)\n        absl::Cord x(a);\n        MaybeHarden(x);\n        x.Append(b);\n        EXPECT_EQ(a + b, std::string(x)) << \"'\" << a << \"' + '\" << b << \"'\";\n      }\n\n      {  // Cord::Prepend(Cord)\n        absl::Cord x(a);\n        absl::Cord y(b);\n        MaybeHarden(x);\n        x.Prepend(y);\n        EXPECT_EQ(b + a, std::string(x)) << \"'\" << b << \"' + '\" << a << \"'\";\n      }\n\n      {  // Cord::Prepend(absl::string_view)\n        absl::Cord x(a);\n        MaybeHarden(x);\n        x.Prepend(b);\n        EXPECT_EQ(b + a, std::string(x)) << \"'\" << b << \"' + '\" << a << \"'\";\n      }\n    }\n  }\n}\n\nnamespace {\n\nTEST_P(CordTest, RemoveSuffixWithExternalOrSubstring) {\n  absl::Cord cord = absl::MakeCordFromExternal(\n      \"foo bar baz\", [](absl::string_view s) { DoNothing(s, nullptr); });\n  EXPECT_EQ(\"foo bar baz\", std::string(cord));\n\n  MaybeHarden(cord);\n\n  // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node.\n  cord.RemoveSuffix(4);\n  EXPECT_EQ(\"foo bar\", std::string(cord));\n\n  MaybeHarden(cord);\n\n  // This RemoveSuffix() will adjust the SUBSTRING node in-place.\n  cord.RemoveSuffix(4);\n  EXPECT_EQ(\"foo\", std::string(cord));\n}\n\nTEST_P(CordTest, RemoveSuffixMakesZeroLengthNode) {\n  absl::Cord c;\n  c.Append(absl::Cord(std::string(100, 'x')));\n  absl::Cord other_ref = c;  // Prevent inplace appends\n  EXPECT_THAT(other_ref, testing::Eq(c));\n  MaybeHarden(c);\n  c.Append(absl::Cord(std::string(200, 'y')));\n  c.RemoveSuffix(200);\n  EXPECT_EQ(std::string(100, 'x'), std::string(c));\n}\n\n}  // namespace\n\n// CordSpliceTest contributed by hendrie.\nnamespace {\n\n// Create a cord with an external memory block filled with 'z'\nabsl::Cord CordWithZedBlock(size_t size) {\n  char* data = new char[size];\n  if (size > 0) {\n    memset(data, 'z', size);\n  }\n  absl::Cord cord = absl::MakeCordFromExternal(\n      absl::string_view(data, size),\n      [](absl::string_view s) { delete[] s.data(); });\n  return cord;\n}\n\n// Establish that ZedBlock does what we think it does.\nTEST_P(CordTest, CordSpliceTestZedBlock) {\n  absl::Cord blob = CordWithZedBlock(10);\n  MaybeHarden(blob);\n  EXPECT_EQ(10, blob.size());\n  std::string s;\n  absl::CopyCordToString(blob, &s);\n  EXPECT_EQ(\"zzzzzzzzzz\", s);\n}\n\nTEST_P(CordTest, CordSpliceTestZedBlock0) {\n  absl::Cord blob = CordWithZedBlock(0);\n  MaybeHarden(blob);\n  EXPECT_EQ(0, blob.size());\n  std::string s;\n  absl::CopyCordToString(blob, &s);\n  EXPECT_EQ(\"\", s);\n}\n\nTEST_P(CordTest, CordSpliceTestZedBlockSuffix1) {\n  absl::Cord blob = CordWithZedBlock(10);\n  MaybeHarden(blob);\n  EXPECT_EQ(10, blob.size());\n  absl::Cord suffix(blob);\n  suffix.RemovePrefix(9);\n  EXPECT_EQ(1, suffix.size());\n  std::string s;\n  absl::CopyCordToString(suffix, &s);\n  EXPECT_EQ(\"z\", s);\n}\n\n// Remove all of a prefix block\nTEST_P(CordTest, CordSpliceTestZedBlockSuffix0) {\n  absl::Cord blob = CordWithZedBlock(10);\n  MaybeHarden(blob);\n  EXPECT_EQ(10, blob.size());\n  absl::Cord suffix(blob);\n  suffix.RemovePrefix(10);\n  EXPECT_EQ(0, suffix.size());\n  std::string s;\n  absl::CopyCordToString(suffix, &s);\n  EXPECT_EQ(\"\", s);\n}\n\nabsl::Cord BigCord(size_t len, char v) {\n  std::string s(len, v);\n  return absl::Cord(s);\n}\n\n// Splice block into cord.\nabsl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,\n                      const absl::Cord& block) {\n  CHECK_GE(offset, 0);\n  CHECK_LE(static_cast<size_t>(offset) + block.size(), blob.size());\n  absl::Cord result(blob);\n  result.RemoveSuffix(blob.size() - offset);\n  result.Append(block);\n  absl::Cord suffix(blob);\n  suffix.RemovePrefix(offset + block.size());\n  result.Append(suffix);\n  CHECK_EQ(blob.size(), result.size());\n  return result;\n}\n\n// Taking an empty suffix of a block breaks appending.\nTEST_P(CordTest, CordSpliceTestRemoveEntireBlock1) {\n  absl::Cord zero = CordWithZedBlock(10);\n  MaybeHarden(zero);\n  absl::Cord suffix(zero);\n  suffix.RemovePrefix(10);\n  absl::Cord result;\n  result.Append(suffix);\n}\n\nTEST_P(CordTest, CordSpliceTestRemoveEntireBlock2) {\n  absl::Cord zero = CordWithZedBlock(10);\n  MaybeHarden(zero);\n  absl::Cord prefix(zero);\n  prefix.RemoveSuffix(10);\n  absl::Cord suffix(zero);\n  suffix.RemovePrefix(10);\n  absl::Cord result(prefix);\n  result.Append(suffix);\n}\n\nTEST_P(CordTest, CordSpliceTestRemoveEntireBlock3) {\n  absl::Cord blob = CordWithZedBlock(10);\n  absl::Cord block = BigCord(10, 'b');\n  MaybeHarden(blob);\n  MaybeHarden(block);\n  blob = SpliceCord(blob, 0, block);\n}\n\nstruct CordCompareTestCase {\n  template <typename LHS, typename RHS>\n  CordCompareTestCase(const LHS& lhs, const RHS& rhs, bool use_crc)\n      : lhs_cord(lhs), rhs_cord(rhs) {\n    if (use_crc) {\n      lhs_cord.SetExpectedChecksum(1);\n    }\n  }\n\n  absl::Cord lhs_cord;\n  absl::Cord rhs_cord;\n};\n\nconst auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); };\n\nvoid VerifyComparison(const CordCompareTestCase& test_case) {\n  std::string lhs_string(test_case.lhs_cord);\n  std::string rhs_string(test_case.rhs_cord);\n  int expected = sign(lhs_string.compare(rhs_string));\n  EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord))\n      << \"LHS=\" << lhs_string << \"; RHS=\" << rhs_string;\n  EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string))\n      << \"LHS=\" << lhs_string << \"; RHS=\" << rhs_string;\n  EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord))\n      << \"LHS=\" << rhs_string << \"; RHS=\" << lhs_string;\n  EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string))\n      << \"LHS=\" << rhs_string << \"; RHS=\" << lhs_string;\n}\n\nTEST_P(CordTest, Compare) {\n  absl::Cord subcord(\"aaaaaBBBBBcccccDDDDD\");\n  subcord = subcord.Subcord(3, 10);\n\n  absl::Cord tmp(\"aaaaaaaaaaaaaaaa\");\n  tmp.Append(\"BBBBBBBBBBBBBBBB\");\n  absl::Cord concat = absl::Cord(\"cccccccccccccccc\");\n  concat.Append(\"DDDDDDDDDDDDDDDD\");\n  concat.Prepend(tmp);\n\n  absl::Cord concat2(\"aaaaaaaaaaaaa\");\n  concat2.Append(\"aaaBBBBBBBBBBBBBBBBccccc\");\n  concat2.Append(\"cccccccccccDDDDDDDDDDDDDD\");\n  concat2.Append(\"DD\");\n\n  const bool use_crc = UseCrc();\n\n  std::vector<CordCompareTestCase> test_cases = {{\n      // Inline cords\n      {\"abcdef\", \"abcdef\", use_crc},\n      {\"abcdef\", \"abcdee\", use_crc},\n      {\"abcdef\", \"abcdeg\", use_crc},\n      {\"bbcdef\", \"abcdef\", use_crc},\n      {\"bbcdef\", \"abcdeg\", use_crc},\n      {\"abcdefa\", \"abcdef\", use_crc},\n      {\"abcdef\", \"abcdefa\", use_crc},\n\n      // Small flat cords\n      {\"aaaaaBBBBBcccccDDDDD\", \"aaaaaBBBBBcccccDDDDD\", use_crc},\n      {\"aaaaaBBBBBcccccDDDDD\", \"aaaaaBBBBBxccccDDDDD\", use_crc},\n      {\"aaaaaBBBBBcxcccDDDDD\", \"aaaaaBBBBBcccccDDDDD\", use_crc},\n      {\"aaaaaBBBBBxccccDDDDD\", \"aaaaaBBBBBcccccDDDDX\", use_crc},\n      {\"aaaaaBBBBBcccccDDDDDa\", \"aaaaaBBBBBcccccDDDDD\", use_crc},\n      {\"aaaaaBBBBBcccccDDDDD\", \"aaaaaBBBBBcccccDDDDDa\", use_crc},\n\n      // Subcords\n      {subcord, subcord, use_crc},\n      {subcord, \"aaBBBBBccc\", use_crc},\n      {subcord, \"aaBBBBBccd\", use_crc},\n      {subcord, \"aaBBBBBccb\", use_crc},\n      {subcord, \"aaBBBBBxcb\", use_crc},\n      {subcord, \"aaBBBBBccca\", use_crc},\n      {subcord, \"aaBBBBBcc\", use_crc},\n\n      // Concats\n      {concat, concat, use_crc},\n      {concat,\n       \"aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD\",\n       use_crc},\n      {concat,\n       \"aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD\",\n       use_crc},\n      {concat,\n       \"aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD\",\n       use_crc},\n      {concat,\n       \"aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD\",\n       use_crc},\n      {concat,\n       \"aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe\",\n       use_crc},\n\n      {concat, concat2, use_crc},\n  }};\n\n  for (const auto& tc : test_cases) {\n    VerifyComparison(tc);\n  }\n}\n\nTEST_P(CordTest, CompareAfterAssign) {\n  absl::Cord a(\"aaaaaa1111111\");\n  absl::Cord b(\"aaaaaa2222222\");\n  MaybeHarden(a);\n  a = \"cccccc\";\n  b = \"cccccc\";\n  EXPECT_EQ(a, b);\n  EXPECT_FALSE(a < b);\n\n  a = \"aaaa\";\n  b = \"bbbbb\";\n  a = \"\";\n  b = \"\";\n  EXPECT_EQ(a, b);\n  EXPECT_FALSE(a < b);\n}\n\n// Test CompareTo() and ComparePrefix() against string and substring\n// comparison methods from basic_string.\nstatic void TestCompare(const absl::Cord& c, const absl::Cord& d,\n                        RandomEngine* rng) {\n  // char_traits<char>::lt is guaranteed to do an unsigned comparison:\n  // https://en.cppreference.com/w/cpp/string/char_traits/cmp. We also expect\n  // Cord comparisons to be based on unsigned byte comparisons regardless of\n  // whether char is signed.\n  int expected = sign(std::string(c).compare(std::string(d)));\n  EXPECT_EQ(expected, sign(c.Compare(d))) << c << \", \" << d;\n}\n\nTEST_P(CordTest, CompareComparisonIsUnsigned) {\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255);\n  char x = static_cast<char>(uniform_uint8(rng));\n  TestCompare(\n      absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x)),\n      absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);\n}\n\nTEST_P(CordTest, CompareRandomComparisons) {\n  const int kIters = 5000;\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n\n  int n = GetUniformRandomUpTo(&rng, 5000);\n  absl::Cord a[] = {MakeExternalCord(n),\n                    absl::Cord(\"ant\"),\n                    absl::Cord(\"elephant\"),\n                    absl::Cord(\"giraffe\"),\n                    absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100),\n                                           GetUniformRandomUpTo(&rng, 100))),\n                    absl::Cord(\"\"),\n                    absl::Cord(\"x\"),\n                    absl::Cord(\"A\"),\n                    absl::Cord(\"B\"),\n                    absl::Cord(\"C\")};\n  for (int i = 0; i < kIters; i++) {\n    absl::Cord c, d;\n    for (int j = 0; j < (i % 7) + 1; j++) {\n      c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);\n      d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);\n    }\n    std::bernoulli_distribution coin_flip(0.5);\n    MaybeHarden(c);\n    MaybeHarden(d);\n    TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)),\n                coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng);\n  }\n}\n\ntemplate <typename T1, typename T2>\nvoid CompareOperators() {\n  const T1 a(\"a\");\n  const T2 b(\"b\");\n\n  EXPECT_TRUE(a == a);\n  // For pointer type (i.e. `const char*`), operator== compares the address\n  // instead of the string, so `a == const char*(\"a\")` isn't necessarily true.\n  EXPECT_TRUE(std::is_pointer<T1>::value || a == T1(\"a\"));\n  EXPECT_TRUE(std::is_pointer<T2>::value || a == T2(\"a\"));\n  EXPECT_FALSE(a == b);\n\n  EXPECT_TRUE(a != b);\n  EXPECT_FALSE(a != a);\n\n  EXPECT_TRUE(a < b);\n  EXPECT_FALSE(b < a);\n\n  EXPECT_TRUE(b > a);\n  EXPECT_FALSE(a > b);\n\n  EXPECT_TRUE(a >= a);\n  EXPECT_TRUE(b >= a);\n  EXPECT_FALSE(a >= b);\n\n  EXPECT_TRUE(a <= a);\n  EXPECT_TRUE(a <= b);\n  EXPECT_FALSE(b <= a);\n}\n\nTEST_P(CordTest, ComparisonOperators_Cord_Cord) {\n  CompareOperators<absl::Cord, absl::Cord>();\n}\n\nTEST_P(CordTest, ComparisonOperators_Cord_StringPiece) {\n  CompareOperators<absl::Cord, absl::string_view>();\n}\n\nTEST_P(CordTest, ComparisonOperators_StringPiece_Cord) {\n  CompareOperators<absl::string_view, absl::Cord>();\n}\n\nTEST_P(CordTest, ComparisonOperators_Cord_string) {\n  CompareOperators<absl::Cord, std::string>();\n}\n\nTEST_P(CordTest, ComparisonOperators_string_Cord) {\n  CompareOperators<std::string, absl::Cord>();\n}\n\nTEST_P(CordTest, ComparisonOperators_stdstring_Cord) {\n  CompareOperators<std::string, absl::Cord>();\n}\n\nTEST_P(CordTest, ComparisonOperators_Cord_stdstring) {\n  CompareOperators<absl::Cord, std::string>();\n}\n\nTEST_P(CordTest, ComparisonOperators_charstar_Cord) {\n  CompareOperators<const char*, absl::Cord>();\n}\n\nTEST_P(CordTest, ComparisonOperators_Cord_charstar) {\n  CompareOperators<absl::Cord, const char*>();\n}\n\nTEST_P(CordTest, ConstructFromExternalReleaserInvoked) {\n  // Empty external memory means the releaser should be called immediately.\n  {\n    bool invoked = false;\n    auto releaser = [&invoked](absl::string_view) { invoked = true; };\n    {\n      auto c = absl::MakeCordFromExternal(\"\", releaser);\n      EXPECT_THAT(c, testing::Eq(\"\"));\n      EXPECT_TRUE(invoked);\n    }\n  }\n\n  // If the size of the data is small enough, a future constructor\n  // implementation may copy the bytes and immediately invoke the releaser\n  // instead of creating an external node. We make a large dummy std::string to\n  // make this test independent of such an optimization.\n  std::string large_dummy(2048, 'c');\n  {\n    bool invoked = false;\n    auto releaser = [&invoked](absl::string_view) { invoked = true; };\n    {\n      auto c = absl::MakeCordFromExternal(large_dummy, releaser);\n      EXPECT_THAT(c, testing::Eq(large_dummy));\n      EXPECT_FALSE(invoked);\n    }\n    EXPECT_TRUE(invoked);\n  }\n\n  {\n    bool invoked = false;\n    auto releaser = [&invoked](absl::string_view) { invoked = true; };\n    {\n      absl::Cord copy;\n      {\n        auto c = absl::MakeCordFromExternal(large_dummy, releaser);\n        copy = c;\n        EXPECT_FALSE(invoked);\n      }\n      EXPECT_FALSE(invoked);\n    }\n    EXPECT_TRUE(invoked);\n  }\n}\n\nTEST_P(CordTest, ConstructFromExternalCompareContents) {\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n\n  for (int length = 1; length <= 2048; length *= 2) {\n    std::string data = RandomLowercaseString(&rng, length);\n    auto* external = new std::string(data);\n    auto cord =\n        absl::MakeCordFromExternal(*external, [external](absl::string_view sv) {\n          EXPECT_EQ(external->data(), sv.data());\n          EXPECT_EQ(external->size(), sv.size());\n          delete external;\n        });\n    MaybeHarden(cord);\n    EXPECT_EQ(data, cord);\n  }\n}\n\nTEST_P(CordTest, ConstructFromExternalLargeReleaser) {\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  constexpr size_t kLength = 256;\n  std::string data = RandomLowercaseString(&rng, kLength);\n  std::array<char, kLength> data_array;\n  for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i];\n  bool invoked = false;\n  auto releaser = [data_array, &invoked](absl::string_view data) {\n    EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size()));\n    invoked = true;\n  };\n  (void)MaybeHardened(absl::MakeCordFromExternal(data, releaser));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalFunctionPointerReleaser) {\n  static absl::string_view data(\"hello world\");\n  static bool invoked;\n  auto* releaser =\n      static_cast<void (*)(absl::string_view)>([](absl::string_view sv) {\n        EXPECT_EQ(data, sv);\n        invoked = true;\n      });\n  invoked = false;\n  (void)MaybeHardened(absl::MakeCordFromExternal(data, releaser));\n  EXPECT_TRUE(invoked);\n\n  invoked = false;\n  (void)MaybeHardened(absl::MakeCordFromExternal(data, *releaser));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalMoveOnlyReleaser) {\n  struct Releaser {\n    explicit Releaser(bool* invoked) : invoked(invoked) {}\n    Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}\n    void operator()(absl::string_view) const { *invoked = true; }\n\n    bool* invoked;\n  };\n\n  bool invoked = false;\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"dummy\", Releaser(&invoked)));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalNonConstReleaser) {\n  struct Releaser {\n    explicit Releaser(bool* invoked) : invoked(invoked) {}\n    // Non const method.\n    void operator()(absl::string_view) { *invoked = true; }\n\n    bool* invoked;\n  };\n\n  bool invoked = false;\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"dummy\", Releaser(&invoked)));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalNonConstNoArgReleaser) {\n  struct Releaser {\n    explicit Releaser(bool* invoked) : invoked(invoked) {}\n    // Non const method.\n    void operator()() { *invoked = true; }\n\n    bool* invoked;\n  };\n\n  bool invoked = false;\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"dummy\", Releaser(&invoked)));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalNoArgLambda) {\n  bool invoked = false;\n  (void)MaybeHardened(\n      absl::MakeCordFromExternal(\"dummy\", [&invoked]() { invoked = true; }));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalStringViewArgLambda) {\n  bool invoked = false;\n  (void)MaybeHardened(absl::MakeCordFromExternal(\n      \"dummy\", [&invoked](absl::string_view) { invoked = true; }));\n  EXPECT_TRUE(invoked);\n}\n\nTEST_P(CordTest, ConstructFromExternalNonTrivialReleaserDestructor) {\n  struct Releaser {\n    explicit Releaser(bool* destroyed) : destroyed(destroyed) {}\n    ~Releaser() { *destroyed = true; }\n    void operator()(absl::string_view) const {}\n\n    bool* destroyed;\n  };\n\n  bool destroyed = false;\n  Releaser releaser(&destroyed);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"dummy\", releaser));\n  EXPECT_TRUE(destroyed);\n}\n\nTEST_P(CordTest, ConstructFromExternalReferenceQualifierOverloads) {\n  enum InvokedAs { kMissing, kLValue, kRValue };\n  enum CopiedAs { kNone, kMove, kCopy };\n  struct Tracker {\n    CopiedAs copied_as = kNone;\n    InvokedAs invoked_as = kMissing;\n\n    void Record(InvokedAs rhs) {\n      ASSERT_EQ(invoked_as, kMissing);\n      invoked_as = rhs;\n    }\n\n    void Record(CopiedAs rhs) {\n      if (copied_as == kNone || rhs == kCopy) copied_as = rhs;\n    }\n  } tracker;\n\n  class Releaser {\n   public:\n    explicit Releaser(Tracker* tracker) : tr_(tracker) { *tracker = Tracker(); }\n    Releaser(Releaser&& rhs) : tr_(rhs.tr_) { tr_->Record(kMove); }\n    Releaser(const Releaser& rhs) : tr_(rhs.tr_) { tr_->Record(kCopy); }\n\n    void operator()(absl::string_view) & { tr_->Record(kLValue); }\n    void operator()(absl::string_view) && { tr_->Record(kRValue); }\n\n   private:\n    Tracker* tr_;\n  };\n\n  const Releaser releaser1(&tracker);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"\", releaser1));\n  EXPECT_EQ(tracker.copied_as, kCopy);\n  EXPECT_EQ(tracker.invoked_as, kRValue);\n\n  const Releaser releaser2(&tracker);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"\", releaser2));\n  EXPECT_EQ(tracker.copied_as, kCopy);\n  EXPECT_EQ(tracker.invoked_as, kRValue);\n\n  Releaser releaser3(&tracker);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"\", std::move(releaser3)));\n  EXPECT_EQ(tracker.copied_as, kMove);\n  EXPECT_EQ(tracker.invoked_as, kRValue);\n\n  Releaser releaser4(&tracker);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"dummy\", releaser4));\n  EXPECT_EQ(tracker.copied_as, kCopy);\n  EXPECT_EQ(tracker.invoked_as, kRValue);\n\n  const Releaser releaser5(&tracker);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"dummy\", releaser5));\n  EXPECT_EQ(tracker.copied_as, kCopy);\n  EXPECT_EQ(tracker.invoked_as, kRValue);\n\n  Releaser releaser6(&tracker);\n  (void)MaybeHardened(absl::MakeCordFromExternal(\"foo\", std::move(releaser6)));\n  EXPECT_EQ(tracker.copied_as, kMove);\n  EXPECT_EQ(tracker.invoked_as, kRValue);\n}\n\nTEST_P(CordTest, ExternalMemoryBasicUsage) {\n  static const char* strings[] = {\"\", \"hello\", \"there\"};\n  for (const char* str : strings) {\n    absl::Cord dst(\"(prefix)\");\n    MaybeHarden(dst);\n    AddExternalMemory(str, &dst);\n    MaybeHarden(dst);\n    dst.Append(\"(suffix)\");\n    EXPECT_EQ((std::string(\"(prefix)\") + str + std::string(\"(suffix)\")),\n              std::string(dst));\n  }\n}\n\nTEST_P(CordTest, ExternalMemoryRemovePrefixSuffix) {\n  // Exhaustively try all sub-strings.\n  absl::Cord cord = MakeComposite();\n  std::string s = std::string(cord);\n  for (int offset = 0; offset <= s.size(); offset++) {\n    for (int length = 0; length <= s.size() - offset; length++) {\n      absl::Cord result(cord);\n      MaybeHarden(result);\n      result.RemovePrefix(offset);\n      MaybeHarden(result);\n      result.RemoveSuffix(result.size() - length);\n      EXPECT_EQ(s.substr(offset, length), std::string(result))\n          << offset << \" \" << length;\n    }\n  }\n}\n\nTEST_P(CordTest, ExternalMemoryGet) {\n  absl::Cord cord(\"hello\");\n  AddExternalMemory(\" world!\", &cord);\n  MaybeHarden(cord);\n  AddExternalMemory(\" how are \", &cord);\n  cord.Append(\" you?\");\n  MaybeHarden(cord);\n  std::string s = std::string(cord);\n  for (int i = 0; i < s.size(); i++) {\n    EXPECT_EQ(s[i], cord[i]);\n  }\n}\n\n// CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage()\n// We use whiteboxed expectations based on our knowledge of the layout and size\n// of empty and inlined cords, and flat nodes.\n\nconstexpr auto kFairShare = absl::CordMemoryAccounting::kFairShare;\nconstexpr auto kTotalMorePrecise =\n    absl::CordMemoryAccounting::kTotalMorePrecise;\n\n// Creates a cord of `n` `c` values, making sure no string stealing occurs.\nabsl::Cord MakeCord(size_t n, char c) {\n  const std::string s(n, c);\n  return absl::Cord(s);\n}\n\nTEST(CordTest, CordMemoryUsageEmpty) {\n  absl::Cord cord;\n  EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage());\n  EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage(kFairShare));\n  EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage(kTotalMorePrecise));\n}\n\nTEST(CordTest, CordMemoryUsageInlined) {\n  absl::Cord a(\"hello\");\n  EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));\n  EXPECT_EQ(a.EstimatedMemoryUsage(kFairShare), sizeof(absl::Cord));\n  EXPECT_EQ(a.EstimatedMemoryUsage(kTotalMorePrecise), sizeof(absl::Cord));\n}\n\nTEST(CordTest, CordMemoryUsageExternalMemory) {\n  absl::Cord cord;\n  AddExternalMemory(std::string(1000, 'x'), &cord);\n  const size_t expected =\n      sizeof(absl::Cord) + 1000 + sizeof(CordRepExternal) + sizeof(intptr_t);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(), expected);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare), expected);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise), expected);\n}\n\nTEST(CordTest, CordMemoryUsageFlat) {\n  absl::Cord cord = MakeCord(1000, 'a');\n  const size_t flat_size =\n      absl::CordTestPeer::Tree(cord)->flat()->AllocatedSize();\n  EXPECT_EQ(cord.EstimatedMemoryUsage(), sizeof(absl::Cord) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + flat_size);\n}\n\nTEST(CordTest, CordMemoryUsageSubStringSharedFlat) {\n  absl::Cord flat = MakeCord(2000, 'a');\n  const size_t flat_size =\n      absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();\n  absl::Cord cord = flat.Subcord(500, 1000);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(),\n            sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size / 2);\n}\n\nTEST(CordTest, CordMemoryUsageFlatShared) {\n  absl::Cord shared = MakeCord(1000, 'a');\n  absl::Cord cord(shared);\n  const size_t flat_size =\n      absl::CordTestPeer::Tree(cord)->flat()->AllocatedSize();\n  EXPECT_EQ(cord.EstimatedMemoryUsage(), sizeof(absl::Cord) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + flat_size / 2);\n}\n\nTEST(CordTest, CordMemoryUsageFlatHardenedAndShared) {\n  absl::Cord shared = MakeCord(1000, 'a');\n  absl::Cord cord(shared);\n  const size_t flat_size =\n      absl::CordTestPeer::Tree(cord)->flat()->AllocatedSize();\n  cord.SetExpectedChecksum(1);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(),\n            sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size / 2);\n\n  absl::Cord cord2(cord);\n  EXPECT_EQ(cord2.EstimatedMemoryUsage(),\n            sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);\n  EXPECT_EQ(cord2.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);\n  EXPECT_EQ(cord2.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + (sizeof(CordRepCrc) + flat_size / 2) / 2);\n}\n\nTEST(CordTest, CordMemoryUsageBTree) {\n  absl::Cord cord1;\n  size_t flats1_size = 0;\n  absl::Cord flats1[4] = {MakeCord(1000, 'a'), MakeCord(1100, 'a'),\n                          MakeCord(1200, 'a'), MakeCord(1300, 'a')};\n  for (absl::Cord flat : flats1) {\n    flats1_size += absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();\n    cord1.Append(std::move(flat));\n  }\n\n  // Make sure the created cord is a BTREE tree. Under some builds such as\n  // windows DLL, we may have ODR like effects on the flag, meaning the DLL\n  // code will run with the picked up default.\n  if (!absl::CordTestPeer::Tree(cord1)->IsBtree()) {\n    LOG(WARNING) << \"Cord library code not respecting btree flag\";\n    return;\n  }\n\n  size_t rep1_size = sizeof(CordRepBtree) + flats1_size;\n  size_t rep1_shared_size = sizeof(CordRepBtree) + flats1_size / 2;\n\n  EXPECT_EQ(cord1.EstimatedMemoryUsage(), sizeof(absl::Cord) + rep1_size);\n  EXPECT_EQ(cord1.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + rep1_size);\n  EXPECT_EQ(cord1.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + rep1_shared_size);\n\n  absl::Cord cord2;\n  size_t flats2_size = 0;\n  absl::Cord flats2[4] = {MakeCord(600, 'a'), MakeCord(700, 'a'),\n                          MakeCord(800, 'a'), MakeCord(900, 'a')};\n  for (absl::Cord& flat : flats2) {\n    flats2_size += absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();\n    cord2.Append(std::move(flat));\n  }\n  size_t rep2_size = sizeof(CordRepBtree) + flats2_size;\n\n  EXPECT_EQ(cord2.EstimatedMemoryUsage(), sizeof(absl::Cord) + rep2_size);\n  EXPECT_EQ(cord2.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + rep2_size);\n  EXPECT_EQ(cord2.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + rep2_size);\n\n  absl::Cord cord(cord1);\n  cord.Append(std::move(cord2));\n\n  EXPECT_EQ(cord.EstimatedMemoryUsage(),\n            sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_size + rep2_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_size + rep2_size);\n  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),\n            sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_shared_size / 2 +\n                rep2_size);\n}\n\nTEST(CordTest, TestHashFragmentation) {\n  // Make sure we hit these boundary cases precisely.\n  EXPECT_EQ(1024, absl::hash_internal::PiecewiseChunkSize());\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::Cord(),\n      absl::MakeFragmentedCord({std::string(600, 'a'), std::string(600, 'a')}),\n      absl::MakeFragmentedCord({std::string(1200, 'a')}),\n      absl::MakeFragmentedCord({std::string(900, 'b'), std::string(900, 'b')}),\n      absl::MakeFragmentedCord({std::string(1800, 'b')}),\n      absl::MakeFragmentedCord(\n          {std::string(2000, 'c'), std::string(2000, 'c')}),\n      absl::MakeFragmentedCord({std::string(4000, 'c')}),\n      absl::MakeFragmentedCord({std::string(1024, 'd')}),\n      absl::MakeFragmentedCord({std::string(1023, 'd'), \"d\"}),\n      absl::MakeFragmentedCord({std::string(1025, 'e')}),\n      absl::MakeFragmentedCord({std::string(1024, 'e'), \"e\"}),\n      absl::MakeFragmentedCord({std::string(1023, 'e'), \"e\", \"e\"}),\n  }));\n}\n\n// Regtest for a change that had to be rolled back because it expanded out\n// of the InlineRep too soon, which was observable through MemoryUsage().\nTEST_P(CordTest, CordMemoryUsageInlineRep) {\n  constexpr size_t kMaxInline = 15;  // Cord::InlineRep::N\n  const std::string small_string(kMaxInline, 'x');\n  absl::Cord c1(small_string);\n\n  absl::Cord c2;\n  c2.Append(small_string);\n  EXPECT_EQ(c1, c2);\n  EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage());\n}\n\nTEST_P(CordTest, CordMemoryUsageTotalMorePreciseMode) {\n  constexpr size_t kChunkSize = 2000;\n  std::string tmp_str(kChunkSize, 'x');\n  const absl::Cord flat(std::move(tmp_str));\n\n  // Construct `fragmented` with two references into the same\n  // underlying buffer shared with `flat`:\n  absl::Cord fragmented(flat);\n  fragmented.Append(flat);\n\n  // Memory usage of `flat`, minus the top-level Cord object:\n  const size_t flat_internal_usage =\n      flat.EstimatedMemoryUsage() - sizeof(absl::Cord);\n\n  // `fragmented` holds a Cord and a CordRepBtree. That tree points to two\n  // copies of flat's internals, which we expect to dedup:\n  EXPECT_EQ(fragmented.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) +\n            sizeof(CordRepBtree) +\n            flat_internal_usage);\n\n  // This is a case where kTotal produces an overestimate:\n  EXPECT_EQ(fragmented.EstimatedMemoryUsage(),\n            sizeof(absl::Cord) +\n            sizeof(CordRepBtree) +\n            2 * flat_internal_usage);\n}\n\nTEST_P(CordTest, CordMemoryUsageTotalMorePreciseModeWithSubstring) {\n  constexpr size_t kChunkSize = 2000;\n  std::string tmp_str(kChunkSize, 'x');\n  const absl::Cord flat(std::move(tmp_str));\n\n  // Construct `fragmented` with two references into the same\n  // underlying buffer shared with `flat`.\n  //\n  // This time, each reference is through a Subcord():\n  absl::Cord fragmented;\n  fragmented.Append(flat.Subcord(1, kChunkSize - 2));\n  fragmented.Append(flat.Subcord(1, kChunkSize - 2));\n\n  // Memory usage of `flat`, minus the top-level Cord object:\n  const size_t flat_internal_usage =\n      flat.EstimatedMemoryUsage() - sizeof(absl::Cord);\n\n  // `fragmented` holds a Cord and a CordRepBtree. That tree points to two\n  // CordRepSubstrings, each pointing at flat's internals.\n  EXPECT_EQ(fragmented.EstimatedMemoryUsage(kTotalMorePrecise),\n            sizeof(absl::Cord) +\n            sizeof(CordRepBtree) +\n            2 * sizeof(CordRepSubstring) +\n            flat_internal_usage);\n\n  // This is a case where kTotal produces an overestimate:\n  EXPECT_EQ(fragmented.EstimatedMemoryUsage(),\n            sizeof(absl::Cord) +\n            sizeof(CordRepBtree) +\n            2 * sizeof(CordRepSubstring) +\n            2 * flat_internal_usage);\n}\n}  // namespace\n\n// Regtest for 7510292 (fix a bug introduced by 7465150)\nTEST_P(CordTest, Concat_Append) {\n  // Create a rep of type CONCAT\n  absl::Cord s1(\"foobarbarbarbarbar\");\n  MaybeHarden(s1);\n  s1.Append(\"abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg\");\n  size_t size = s1.size();\n\n  // Create a copy of s1 and append to it.\n  absl::Cord s2 = s1;\n  MaybeHarden(s2);\n  s2.Append(\"x\");\n\n  // 7465150 modifies s1 when it shouldn't.\n  EXPECT_EQ(s1.size(), size);\n  EXPECT_EQ(s2.size(), size + 1);\n}\n\nTEST_P(CordTest, DiabolicalGrowth) {\n  // This test exercises a diabolical Append(<one char>) on a cord, making the\n  // cord shared before each Append call resulting in a terribly fragmented\n  // resulting cord.\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  const std::string expected = RandomLowercaseString(&rng, 5000);\n  absl::Cord cord;\n  for (char c : expected) {\n    absl::Cord shared(cord);\n    EXPECT_THAT(cord, testing::Eq(shared));\n    cord.Append(absl::string_view(&c, 1));\n    MaybeHarden(cord);\n  }\n  std::string value;\n  absl::CopyCordToString(cord, &value);\n  EXPECT_EQ(value, expected);\n  LOG(INFO) << \"Diabolical size allocated = \" << cord.EstimatedMemoryUsage();\n}\n\n// The following tests check support for >4GB cords in 64-bit binaries, and\n// 2GB-4GB cords in 32-bit binaries.  This function returns the large cord size\n// that's appropriate for the binary.\n\n// Construct a huge cord with the specified valid prefix.\nstatic absl::Cord MakeHuge(absl::string_view prefix) {\n  absl::Cord cord;\n  if (sizeof(size_t) > 4) {\n    // In 64-bit binaries, test 64-bit Cord support.\n    const size_t size =\n        static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 314;\n    cord.Append(absl::MakeCordFromExternal(\n        absl::string_view(prefix.data(), size),\n        [](absl::string_view s) { DoNothing(s, nullptr); }));\n  } else {\n    // Cords are limited to 32-bit lengths in 32-bit binaries.  The following\n    // tests check for use of \"signed int\" to represent Cord length/offset.\n    // However absl::string_view does not allow lengths >= (1u<<31), so we need\n    // to append in two parts;\n    const size_t s1 = (1u << 31) - 1;\n    // For shorter cord, `Append` copies the data rather than allocating a new\n    // node. The threshold is currently set to 511, so `s2` needs to be bigger\n    // to not trigger the copy.\n    const size_t s2 = 600;\n    cord.Append(absl::MakeCordFromExternal(\n        absl::string_view(prefix.data(), s1),\n        [](absl::string_view s) { DoNothing(s, nullptr); }));\n    cord.Append(absl::MakeCordFromExternal(\n        absl::string_view(\"\", s2),\n        [](absl::string_view s) { DoNothing(s, nullptr); }));\n  }\n  return cord;\n}\n\nTEST_P(CordTest, HugeCord) {\n  absl::Cord cord = MakeHuge(\"huge cord\");\n  MaybeHarden(cord);\n\n  const size_t acceptable_delta =\n      100 + (UseCrc() ? sizeof(absl::cord_internal::CordRepCrc) : 0);\n  EXPECT_LE(cord.size(), cord.EstimatedMemoryUsage());\n  EXPECT_GE(cord.size() + acceptable_delta, cord.EstimatedMemoryUsage());\n}\n\n// Tests that Append() works ok when handed a self reference\nTEST_P(CordTest, AppendSelf) {\n  // Test the empty case.\n  absl::Cord empty;\n  MaybeHarden(empty);\n  empty.Append(empty);\n  ASSERT_EQ(empty, \"\");\n\n  // We run the test until data is ~16K\n  // This guarantees it covers small, medium and large data.\n  std::string control_data = \"Abc\";\n  absl::Cord data(control_data);\n  while (control_data.length() < 0x4000) {\n    MaybeHarden(data);\n    data.Append(data);\n    control_data.append(control_data);\n    ASSERT_EQ(control_data, data);\n  }\n}\n\nTEST_P(CordTest, MakeFragmentedCordFromInitializerList) {\n  absl::Cord fragmented =\n      absl::MakeFragmentedCord({\"A \", \"fragmented \", \"Cord\"});\n\n  MaybeHarden(fragmented);\n\n  EXPECT_EQ(\"A fragmented Cord\", fragmented);\n\n  auto chunk_it = fragmented.chunk_begin();\n\n  ASSERT_TRUE(chunk_it != fragmented.chunk_end());\n  EXPECT_EQ(\"A \", *chunk_it);\n\n  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());\n  EXPECT_EQ(\"fragmented \", *chunk_it);\n\n  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());\n  EXPECT_EQ(\"Cord\", *chunk_it);\n\n  ASSERT_TRUE(++chunk_it == fragmented.chunk_end());\n}\n\nTEST_P(CordTest, MakeFragmentedCordFromVector) {\n  std::vector<absl::string_view> chunks = {\"A \", \"fragmented \", \"Cord\"};\n  absl::Cord fragmented = absl::MakeFragmentedCord(chunks);\n\n  MaybeHarden(fragmented);\n\n  EXPECT_EQ(\"A fragmented Cord\", fragmented);\n\n  auto chunk_it = fragmented.chunk_begin();\n\n  ASSERT_TRUE(chunk_it != fragmented.chunk_end());\n  EXPECT_EQ(\"A \", *chunk_it);\n\n  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());\n  EXPECT_EQ(\"fragmented \", *chunk_it);\n\n  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());\n  EXPECT_EQ(\"Cord\", *chunk_it);\n\n  ASSERT_TRUE(++chunk_it == fragmented.chunk_end());\n}\n\nTEST_P(CordTest, CordChunkIteratorTraits) {\n  static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value,\n                \"\");\n  static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, \"\");\n\n  // Move semantics to satisfy swappable via std::swap\n  static_assert(std::is_move_constructible<absl::Cord::ChunkIterator>::value,\n                \"\");\n  static_assert(std::is_move_assignable<absl::Cord::ChunkIterator>::value, \"\");\n\n  static_assert(\n      std::is_same<\n          std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category,\n          std::input_iterator_tag>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::value_type,\n                   absl::string_view>::value,\n      \"\");\n  static_assert(\n      std::is_same<\n          std::iterator_traits<absl::Cord::ChunkIterator>::difference_type,\n          ptrdiff_t>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer,\n                   const absl::string_view*>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference,\n                   absl::string_view>::value,\n      \"\");\n}\n\nstatic void VerifyChunkIterator(const absl::Cord& cord,\n                                size_t expected_chunks) {\n  EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord;\n  EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty());\n\n  absl::Cord::ChunkRange range = cord.Chunks();\n  EXPECT_EQ(range.begin() == range.end(), cord.empty());\n  EXPECT_EQ(range.begin() != range.end(), !cord.empty());\n\n  std::string content(cord);\n  size_t pos = 0;\n  auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin();\n  size_t n_chunks = 0;\n  while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) {\n    EXPECT_FALSE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==\n    EXPECT_FALSE(post_iter == cord.chunk_end());  // NOLINT\n\n    EXPECT_EQ(pre_iter, post_iter);\n    EXPECT_EQ(*pre_iter, *post_iter);\n\n    EXPECT_EQ(pre_iter->data(), (*pre_iter).data());\n    EXPECT_EQ(pre_iter->size(), (*pre_iter).size());\n\n    absl::string_view chunk = *pre_iter;\n    EXPECT_FALSE(chunk.empty());\n    EXPECT_LE(pos + chunk.size(), content.size());\n    EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk);\n\n    int n_equal_iterators = 0;\n    for (absl::Cord::ChunkIterator it = range.begin(); it != range.end();\n         ++it) {\n      n_equal_iterators += static_cast<int>(it == pre_iter);\n    }\n    EXPECT_EQ(n_equal_iterators, 1);\n\n    ++pre_iter;\n    EXPECT_EQ(*post_iter++, chunk);\n\n    pos += chunk.size();\n    ++n_chunks;\n  }\n  EXPECT_EQ(expected_chunks, n_chunks);\n  EXPECT_EQ(pos, content.size());\n  EXPECT_TRUE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==\n  EXPECT_TRUE(post_iter == cord.chunk_end());  // NOLINT\n}\n\nTEST_P(CordTest, CordChunkIteratorOperations) {\n  absl::Cord empty_cord;\n  VerifyChunkIterator(empty_cord, 0);\n\n  absl::Cord small_buffer_cord(\"small cord\");\n  MaybeHarden(small_buffer_cord);\n  VerifyChunkIterator(small_buffer_cord, 1);\n\n  absl::Cord flat_node_cord(\"larger than small buffer optimization\");\n  MaybeHarden(flat_node_cord);\n  VerifyChunkIterator(flat_node_cord, 1);\n\n  VerifyChunkIterator(MaybeHardened(absl::MakeFragmentedCord(\n                          {\"a \", \"small \", \"fragmented \", \"cord \", \"for \",\n                           \"testing \", \"chunk \", \"iterations.\"})),\n                      8);\n\n  absl::Cord reused_nodes_cord(std::string(40, 'c'));\n  reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b')));\n  MaybeHarden(reused_nodes_cord);\n  reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a')));\n  size_t expected_chunks = 3;\n  for (int i = 0; i < 8; ++i) {\n    reused_nodes_cord.Prepend(reused_nodes_cord);\n    MaybeHarden(reused_nodes_cord);\n    expected_chunks *= 2;\n    VerifyChunkIterator(reused_nodes_cord, expected_chunks);\n  }\n\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  absl::Cord flat_cord(RandomLowercaseString(&rng, 256));\n  absl::Cord subcords;\n  for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128));\n  VerifyChunkIterator(subcords, 128);\n}\n\n\nTEST_P(CordTest, AdvanceAndReadOnDataEdge) {\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  const std::string data = RandomLowercaseString(&rng, 2000);\n  for (bool as_flat : {true, false}) {\n    SCOPED_TRACE(as_flat ? \"Flat\" : \"External\");\n\n    absl::Cord cord =\n        as_flat ? absl::Cord(data)\n                : absl::MakeCordFromExternal(data, [](absl::string_view) {});\n    auto it = cord.Chars().begin();\n#if !defined(NDEBUG) || ABSL_OPTION_HARDENED\n    EXPECT_DEATH_IF_SUPPORTED(cord.AdvanceAndRead(&it, 2001), \".*\");\n#endif\n\n    it = cord.Chars().begin();\n    absl::Cord frag = cord.AdvanceAndRead(&it, 2000);\n    EXPECT_EQ(frag, data);\n    EXPECT_TRUE(it == cord.Chars().end());\n\n    it = cord.Chars().begin();\n    frag = cord.AdvanceAndRead(&it, 200);\n    EXPECT_EQ(frag, data.substr(0, 200));\n    EXPECT_FALSE(it == cord.Chars().end());\n\n    frag = cord.AdvanceAndRead(&it, 1500);\n    EXPECT_EQ(frag, data.substr(200, 1500));\n    EXPECT_FALSE(it == cord.Chars().end());\n\n    frag = cord.AdvanceAndRead(&it, 300);\n    EXPECT_EQ(frag, data.substr(1700, 300));\n    EXPECT_TRUE(it == cord.Chars().end());\n  }\n}\n\nTEST_P(CordTest, AdvanceAndReadOnSubstringDataEdge) {\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  const std::string data = RandomLowercaseString(&rng, 2500);\n  for (bool as_flat : {true, false}) {\n    SCOPED_TRACE(as_flat ? \"Flat\" : \"External\");\n\n    absl::Cord cord =\n        as_flat ? absl::Cord(data)\n                : absl::MakeCordFromExternal(data, [](absl::string_view) {});\n    cord = cord.Subcord(200, 2000);\n    const std::string substr = data.substr(200, 2000);\n\n    auto it = cord.Chars().begin();\n#if !defined(NDEBUG) || ABSL_OPTION_HARDENED\n    EXPECT_DEATH_IF_SUPPORTED(cord.AdvanceAndRead(&it, 2001), \".*\");\n#endif\n\n    it = cord.Chars().begin();\n    absl::Cord frag = cord.AdvanceAndRead(&it, 2000);\n    EXPECT_EQ(frag, substr);\n    EXPECT_TRUE(it == cord.Chars().end());\n\n    it = cord.Chars().begin();\n    frag = cord.AdvanceAndRead(&it, 200);\n    EXPECT_EQ(frag, substr.substr(0, 200));\n    EXPECT_FALSE(it == cord.Chars().end());\n\n    frag = cord.AdvanceAndRead(&it, 1500);\n    EXPECT_EQ(frag, substr.substr(200, 1500));\n    EXPECT_FALSE(it == cord.Chars().end());\n\n    frag = cord.AdvanceAndRead(&it, 300);\n    EXPECT_EQ(frag, substr.substr(1700, 300));\n    EXPECT_TRUE(it == cord.Chars().end());\n  }\n}\n\nTEST_P(CordTest, CharIteratorTraits) {\n  static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value,\n                \"\");\n  static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, \"\");\n\n  // Move semantics to satisfy swappable via std::swap\n  static_assert(std::is_move_constructible<absl::Cord::CharIterator>::value,\n                \"\");\n  static_assert(std::is_move_assignable<absl::Cord::CharIterator>::value, \"\");\n\n  static_assert(\n      std::is_same<\n          std::iterator_traits<absl::Cord::CharIterator>::iterator_category,\n          std::input_iterator_tag>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<absl::Cord::CharIterator>::value_type,\n                   char>::value,\n      \"\");\n  static_assert(\n      std::is_same<\n          std::iterator_traits<absl::Cord::CharIterator>::difference_type,\n          ptrdiff_t>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer,\n                   const char*>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference,\n                   const char&>::value,\n      \"\");\n}\n\nstatic void VerifyCharIterator(const absl::Cord& cord) {\n  EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty());\n  EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty());\n\n  absl::Cord::CharRange range = cord.Chars();\n  EXPECT_EQ(range.begin() == range.end(), cord.empty());\n  EXPECT_EQ(range.begin() != range.end(), !cord.empty());\n  EXPECT_EQ(absl::Cord::Distance(range.begin(), range.end()),\n            static_cast<ptrdiff_t>(cord.size()));\n  EXPECT_EQ(absl::Cord::Distance(range.end(), range.begin()),\n            -static_cast<ptrdiff_t>(cord.size()));\n\n  size_t i = 0;\n  absl::Cord::CharIterator pre_iter = cord.char_begin();\n  absl::Cord::CharIterator post_iter = cord.char_begin();\n  std::string content(cord);\n  while (pre_iter != cord.char_end() && post_iter != cord.char_end()) {\n    EXPECT_FALSE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==\n    EXPECT_FALSE(post_iter == cord.char_end());  // NOLINT\n\n    EXPECT_LT(i, cord.size());\n    EXPECT_EQ(content[i], *pre_iter);\n\n    EXPECT_EQ(pre_iter, post_iter);\n    EXPECT_EQ(*pre_iter, *post_iter);\n    EXPECT_EQ(&*pre_iter, &*post_iter);\n\n    const char* character_address = &*pre_iter;\n    absl::Cord::CharIterator copy = pre_iter;\n    ++copy;\n    EXPECT_EQ(character_address, &*pre_iter);\n\n    int n_equal_iterators = 0;\n    for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) {\n      n_equal_iterators += static_cast<int>(it == pre_iter);\n    }\n    EXPECT_EQ(n_equal_iterators, 1);\n\n    absl::Cord::CharIterator advance_iter = range.begin();\n    absl::Cord::Advance(&advance_iter, i);\n    EXPECT_EQ(pre_iter, advance_iter);\n    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),\n              static_cast<ptrdiff_t>(i));\n\n    advance_iter = range.begin();\n    EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));\n    EXPECT_EQ(pre_iter, advance_iter);\n    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),\n              static_cast<ptrdiff_t>(i));\n\n    advance_iter = pre_iter;\n    absl::Cord::Advance(&advance_iter, cord.size() - i);\n    EXPECT_EQ(range.end(), advance_iter);\n    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),\n              static_cast<ptrdiff_t>(cord.size()));\n    EXPECT_EQ(absl::Cord::Distance(advance_iter, range.end()), 0);\n\n    advance_iter = pre_iter;\n    EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),\n              cord.Subcord(i, cord.size() - i));\n    EXPECT_EQ(range.end(), advance_iter);\n    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),\n              static_cast<ptrdiff_t>(cord.size()));\n    EXPECT_EQ(absl::Cord::Distance(advance_iter, range.end()), 0);\n\n    ++i;\n    ++pre_iter;\n    post_iter++;\n  }\n  EXPECT_EQ(i, cord.size());\n  EXPECT_TRUE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==\n  EXPECT_TRUE(post_iter == cord.char_end());  // NOLINT\n\n  absl::Cord::CharIterator zero_advanced_end = cord.char_end();\n  absl::Cord::Advance(&zero_advanced_end, 0);\n  EXPECT_EQ(zero_advanced_end, cord.char_end());\n\n  absl::Cord::CharIterator it = cord.char_begin();\n  for (absl::string_view chunk : cord.Chunks()) {\n    while (!chunk.empty()) {\n      EXPECT_EQ(absl::Cord::ChunkRemaining(it), chunk);\n      chunk.remove_prefix(1);\n      ++it;\n    }\n  }\n}\n\nTEST_P(CordTest, CharIteratorOperations) {\n  absl::Cord empty_cord;\n  VerifyCharIterator(empty_cord);\n\n  absl::Cord small_buffer_cord(\"small cord\");\n  MaybeHarden(small_buffer_cord);\n  VerifyCharIterator(small_buffer_cord);\n\n  absl::Cord flat_node_cord(\"larger than small buffer optimization\");\n  MaybeHarden(flat_node_cord);\n  VerifyCharIterator(flat_node_cord);\n\n  VerifyCharIterator(MaybeHardened(\n      absl::MakeFragmentedCord({\"a \", \"small \", \"fragmented \", \"cord \", \"for \",\n                                \"testing \", \"character \", \"iteration.\"})));\n\n  absl::Cord reused_nodes_cord(\"ghi\");\n  reused_nodes_cord.Prepend(absl::Cord(\"def\"));\n  reused_nodes_cord.Prepend(absl::Cord(\"abc\"));\n  for (int i = 0; i < 4; ++i) {\n    reused_nodes_cord.Prepend(reused_nodes_cord);\n    MaybeHarden(reused_nodes_cord);\n    VerifyCharIterator(reused_nodes_cord);\n  }\n\n  RandomEngine rng(GTEST_FLAG_GET(random_seed));\n  absl::Cord flat_cord(RandomLowercaseString(&rng, 256));\n  absl::Cord subcords;\n  for (int i = 0; i < 4; ++i) {\n    subcords.Prepend(flat_cord.Subcord(16 * i, 128));\n    MaybeHarden(subcords);\n  }\n  VerifyCharIterator(subcords);\n}\n\nTEST_P(CordTest, CharIteratorAdvanceAndRead) {\n  // Create a Cord holding 6 flats of 2500 bytes each, and then iterate over it\n  // reading 150, 1500, 2500 and 3000 bytes. This will result in all possible\n  // partial, full and straddled read combinations including reads below\n  // kMaxBytesToCopy. b/197776822 surfaced a bug for a specific partial, small\n  // read 'at end' on Cord which caused a failure on attempting to read past the\n  // end in CordRepBtreeReader which was not covered by any existing test.\n  constexpr int kBlocks = 6;\n  constexpr size_t kBlockSize = 2500;\n  constexpr size_t kChunkSize1 = 1500;\n  constexpr size_t kChunkSize2 = 2500;\n  constexpr size_t kChunkSize3 = 3000;\n  constexpr size_t kChunkSize4 = 150;\n  RandomEngine rng;\n  std::string data = RandomLowercaseString(&rng, kBlocks * kBlockSize);\n  absl::Cord cord;\n  for (int i = 0; i < kBlocks; ++i) {\n    const std::string block = data.substr(i * kBlockSize, kBlockSize);\n    cord.Append(absl::Cord(block));\n  }\n\n  MaybeHarden(cord);\n\n\n  for (size_t chunk_size :\n       {kChunkSize1, kChunkSize2, kChunkSize3, kChunkSize4}) {\n    absl::Cord::CharIterator it = cord.char_begin();\n    size_t it_remaining = cord.size();\n    size_t it_advanced = 0;\n    size_t offset = 0;\n    while (offset < data.length()) {\n      EXPECT_EQ(absl::Cord::Distance(it, cord.char_end()), it_remaining);\n      EXPECT_EQ(absl::Cord::Distance(cord.char_begin(), it), it_advanced);\n      const size_t n = std::min<size_t>(data.length() - offset, chunk_size);\n      absl::Cord chunk = cord.AdvanceAndRead(&it, n);\n      ASSERT_EQ(chunk.size(), n);\n      ASSERT_EQ(chunk.Compare(data.substr(offset, n)), 0);\n      offset += n;\n      it_remaining -= n;\n      it_advanced += n;\n      EXPECT_EQ(absl::Cord::Distance(it, cord.char_end()), it_remaining);\n      EXPECT_EQ(absl::Cord::Distance(cord.char_begin(), it), it_advanced);\n    }\n  }\n}\n\nTEST_P(CordTest, StreamingOutput) {\n  absl::Cord c =\n      absl::MakeFragmentedCord({\"A \", \"small \", \"fragmented \", \"Cord\", \".\"});\n  MaybeHarden(c);\n  std::stringstream output;\n  output << c;\n  EXPECT_EQ(\"A small fragmented Cord.\", output.str());\n}\n\nTEST_P(CordTest, ForEachChunk) {\n  for (int num_elements : {1, 10, 200}) {\n    SCOPED_TRACE(num_elements);\n    std::vector<std::string> cord_chunks;\n    for (int i = 0; i < num_elements; ++i) {\n      cord_chunks.push_back(absl::StrCat(\"[\", i, \"]\"));\n    }\n    absl::Cord c = absl::MakeFragmentedCord(cord_chunks);\n    MaybeHarden(c);\n\n    std::vector<std::string> iterated_chunks;\n    absl::CordTestPeer::ForEachChunk(c,\n                                     [&iterated_chunks](absl::string_view sv) {\n                                       iterated_chunks.emplace_back(sv);\n                                     });\n    EXPECT_EQ(iterated_chunks, cord_chunks);\n  }\n}\n\nTEST_P(CordTest, SmallBufferAssignFromOwnData) {\n  constexpr size_t kMaxInline = 15;\n  std::string contents = \"small buff cord\";\n  EXPECT_EQ(contents.size(), kMaxInline);\n  for (size_t pos = 0; pos < contents.size(); ++pos) {\n    for (size_t count = contents.size() - pos; count > 0; --count) {\n      absl::Cord c(contents);\n      MaybeHarden(c);\n      absl::string_view flat = c.Flatten();\n      c = flat.substr(pos, count);\n      EXPECT_EQ(c, contents.substr(pos, count))\n          << \"pos = \" << pos << \"; count = \" << count;\n    }\n  }\n}\n\nTEST_P(CordTest, Format) {\n  absl::Cord c;\n  absl::Format(&c, \"There were %04d little %s.\", 3, \"pigs\");\n  EXPECT_EQ(c, \"There were 0003 little pigs.\");\n  MaybeHarden(c);\n  absl::Format(&c, \"And %-3llx bad wolf!\", 1);\n  MaybeHarden(c);\n  EXPECT_EQ(c, \"There were 0003 little pigs.And 1   bad wolf!\");\n}\n\nTEST_P(CordTest, Stringify) {\n  absl::Cord c =\n      absl::MakeFragmentedCord({\"A \", \"small \", \"fragmented \", \"Cord\", \".\"});\n  MaybeHarden(c);\n  EXPECT_EQ(absl::StrCat(c), \"A small fragmented Cord.\");\n}\n\nTEST_P(CordTest, Hardening) {\n  absl::Cord cord(\"hello\");\n  MaybeHarden(cord);\n\n  // These statement should abort the program in all builds modes.\n  EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(cord.RemoveSuffix(6), \"\");\n\n  bool test_hardening = false;\n  ABSL_HARDENING_ASSERT([&]() {\n    // This only runs when ABSL_HARDENING_ASSERT is active.\n    test_hardening = true;\n    return true;\n  }());\n  if (!test_hardening) return;\n\n  EXPECT_DEATH_IF_SUPPORTED(cord[5], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), \"\");\n  EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), \"\");\n}\n\n// This test mimics a specific (and rare) application repeatedly splitting a\n// cord, inserting (overwriting) a string value, and composing a new cord from\n// the three pieces. This is hostile towards a Btree implementation: A split of\n// a node at any level is likely to have the right-most edge of the left split,\n// and the left-most edge of the right split shared. For example, splitting a\n// leaf node with 6 edges will result likely in a 1-6, 2-5, 3-4, etc. split,\n// sharing the 'split node'. When recomposing such nodes, we 'injected' an edge\n// in that node. As this happens with some probability on each level of the\n// tree, this will quickly grow the tree until it reaches maximum height.\nTEST_P(CordTest, BtreeHostileSplitInsertJoin) {\n  absl::BitGen bitgen;\n\n  // Start with about 1GB of data\n  std::string data(1 << 10, 'x');\n  absl::Cord buffer(data);\n  absl::Cord cord;\n  for (int i = 0; i < 1000000; ++i) {\n    cord.Append(buffer);\n  }\n\n  for (int j = 0; j < 1000; ++j) {\n    MaybeHarden(cord);\n    size_t offset = absl::Uniform(bitgen, 0u, cord.size());\n    size_t length = absl::Uniform(bitgen, 100u, data.size());\n    if (cord.size() == offset) {\n      cord.Append(absl::string_view(data.data(), length));\n    } else {\n      absl::Cord suffix;\n      if (offset + length < cord.size()) {\n        suffix = cord;\n        suffix.RemovePrefix(offset + length);\n      }\n      if (cord.size() > offset) {\n        cord.RemoveSuffix(cord.size() - offset);\n      }\n      cord.Append(absl::string_view(data.data(), length));\n      if (!suffix.empty()) {\n        cord.Append(suffix);\n      }\n    }\n  }\n}\n\nclass AfterExitCordTester {\n public:\n  bool Set(absl::Cord* cord, absl::string_view expected) {\n    cord_ = cord;\n    expected_ = expected;\n    return true;\n  }\n\n  ~AfterExitCordTester() {\n    EXPECT_EQ(*cord_, expected_);\n  }\n private:\n  absl::Cord* cord_;\n  absl::string_view expected_;\n};\n\ntemplate <typename Str>\nvoid TestAfterExit(Str) {\n  const auto expected = Str::value;\n  // Defined before `cord` to be destroyed after it.\n  static AfterExitCordTester exit_tester;  // NOLINT\n  static absl::NoDestructor<absl::Cord> cord_leaker(Str{});\n  // cord_leaker is static, so this reference will remain valid through the end\n  // of program execution.\n  static absl::Cord& cord = *cord_leaker;\n  static bool init_exit_tester = exit_tester.Set(&cord, expected);\n  (void)init_exit_tester;\n\n  EXPECT_EQ(cord, expected);\n  // Copy the object and test the copy, and the original.\n  {\n    absl::Cord copy = cord;\n    EXPECT_EQ(copy, expected);\n  }\n  // The original still works\n  EXPECT_EQ(cord, expected);\n\n  // Try making adding more structure to the tree.\n  {\n    absl::Cord copy = cord;\n    std::string expected_copy(expected);\n    for (int i = 0; i < 10; ++i) {\n      copy.Append(cord);\n      absl::StrAppend(&expected_copy, expected);\n      EXPECT_EQ(copy, expected_copy);\n    }\n  }\n\n  // Make sure we are using the right branch during constant evaluation.\n  EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);\n\n  for (int i = 0; i < 10; ++i) {\n    // Make a few more Cords from the same global rep.\n    // This tests what happens when the refcount for it gets below 1.\n    EXPECT_EQ(expected, absl::Cord(Str{}));\n  }\n}\n\nconstexpr int SimpleStrlen(const char* p) {\n  return *p ? 1 + SimpleStrlen(p + 1) : 0;\n}\n\nstruct ShortView {\n  constexpr absl::string_view operator()() const {\n    return absl::string_view(\"SSO string\", SimpleStrlen(\"SSO string\"));\n  }\n};\n\nstruct LongView {\n  constexpr absl::string_view operator()() const {\n    return absl::string_view(\"String that does not fit SSO.\",\n                             SimpleStrlen(\"String that does not fit SSO.\"));\n  }\n};\n\n\nTEST_P(CordTest, AfterExit) {\n  TestAfterExit(absl::strings_internal::MakeStringConstant(ShortView{}));\n  TestAfterExit(absl::strings_internal::MakeStringConstant(LongView{}));\n}\n\nnamespace {\n\n// Test helper that generates a populated cord for future manipulation.\n//\n// By test convention, all generated cords begin with the characters \"abcde\" at\n// the start of the first chunk.\nclass PopulatedCordFactory {\n public:\n  constexpr PopulatedCordFactory(absl::string_view name,\n                                 absl::Cord (*generator)())\n      : name_(name), generator_(generator) {}\n\n  absl::string_view Name() const { return name_; }\n  absl::Cord Generate() const { return generator_(); }\n\n private:\n  absl::string_view name_;\n  absl::Cord (*generator_)();\n};\n\n// clang-format off\n// This array is constant-initialized in conformant compilers.\nPopulatedCordFactory cord_factories[] = {\n  {\"sso\", [] { return absl::Cord(\"abcde\"); }},\n  {\"flat\", [] {\n    // Too large to live in SSO space, but small enough to be a simple FLAT.\n    absl::Cord flat(absl::StrCat(\"abcde\", std::string(1000, 'x')));\n    flat.Flatten();\n    return flat;\n  }},\n  {\"external\", [] {\n    // A cheat: we are using a string literal as the external storage, so a\n    // no-op releaser is correct here.\n    return absl::MakeCordFromExternal(\"abcde External!\", []{});\n  }},\n  {\"external substring\", [] {\n    // A cheat: we are using a string literal as the external storage, so a\n    // no-op releaser is correct here.\n    absl::Cord ext = absl::MakeCordFromExternal(\"-abcde External!\", []{});\n    return absl::CordTestPeer::MakeSubstring(ext, 1, ext.size() - 1);\n  }},\n  {\"substring\", [] {\n    absl::Cord flat(absl::StrCat(\"-abcde\", std::string(1000, 'x')));\n    flat.Flatten();\n    return flat.Subcord(1, 998);\n  }},\n  {\"fragmented\", [] {\n    std::string fragment = absl::StrCat(\"abcde\", std::string(195, 'x'));\n    std::vector<std::string> fragments(200, fragment);\n    absl::Cord cord = absl::MakeFragmentedCord(fragments);\n    assert(cord.size() == 40000);\n    return cord;\n  }},\n};\n// clang-format on\n\n// Test helper that can mutate a cord, and possibly undo the mutation, for\n// testing.\nclass CordMutator {\n public:\n  constexpr CordMutator(absl::string_view name, void (*mutate)(absl::Cord&),\n                        void (*undo)(absl::Cord&) = nullptr)\n      : name_(name), mutate_(mutate), undo_(undo) {}\n\n  absl::string_view Name() const { return name_; }\n  void Mutate(absl::Cord& cord) const { mutate_(cord); }\n  bool CanUndo() const { return undo_ != nullptr; }\n  void Undo(absl::Cord& cord) const { undo_(cord); }\n\n private:\n  absl::string_view name_;\n  void (*mutate_)(absl::Cord&);\n  void (*undo_)(absl::Cord&);\n};\n\n// clang-format off\n// This array is constant-initialized in conformant compilers.\nCordMutator cord_mutators[] = {\n  {\"clear\", [](absl::Cord& c) { c.Clear(); }},\n  {\"overwrite\", [](absl::Cord& c) { c = \"overwritten\"; }},\n  {\n    \"append string\",\n    [](absl::Cord& c) { c.Append(\"0123456789\"); },\n    [](absl::Cord& c) { c.RemoveSuffix(10); }\n  },\n  {\n    \"append cord\",\n    [](absl::Cord& c) {\n      c.Append(absl::MakeFragmentedCord({\"12345\", \"67890\"}));\n    },\n    [](absl::Cord& c) { c.RemoveSuffix(10); }\n  },\n  {\n    \"append checksummed cord\",\n    [](absl::Cord& c) {\n      absl::Cord to_append = absl::MakeFragmentedCord({\"12345\", \"67890\"});\n      to_append.SetExpectedChecksum(999);\n      c.Append(to_append);\n    },\n    [](absl::Cord& c) { c.RemoveSuffix(10); }\n  },\n  {\n    \"append self\",\n    [](absl::Cord& c) { c.Append(c); },\n    [](absl::Cord& c) { c.RemoveSuffix(c.size() / 2); }\n  },\n  {\n    \"append empty string\",\n    [](absl::Cord& c) { c.Append(\"\"); },\n    [](absl::Cord& c) { }\n  },\n  {\n    \"append empty cord\",\n    [](absl::Cord& c) { c.Append(absl::Cord()); },\n    [](absl::Cord& c) { }\n  },\n  {\n    \"append empty checksummed cord\",\n    [](absl::Cord& c) {\n      absl::Cord to_append;\n      to_append.SetExpectedChecksum(999);\n      c.Append(to_append);\n    },\n    [](absl::Cord& c) { }\n  },\n  {\n    \"prepend string\",\n    [](absl::Cord& c) { c.Prepend(\"9876543210\"); },\n    [](absl::Cord& c) { c.RemovePrefix(10); }\n  },\n  {\n    \"prepend cord\",\n    [](absl::Cord& c) {\n      c.Prepend(absl::MakeFragmentedCord({\"98765\", \"43210\"}));\n    },\n    [](absl::Cord& c) { c.RemovePrefix(10); }\n  },\n  {\n    \"prepend checksummed cord\",\n    [](absl::Cord& c) {\n      absl::Cord to_prepend = absl::MakeFragmentedCord({\"98765\", \"43210\"});\n      to_prepend.SetExpectedChecksum(999);\n      c.Prepend(to_prepend);\n    },\n    [](absl::Cord& c) { c.RemovePrefix(10); }\n  },\n  {\n    \"prepend empty string\",\n    [](absl::Cord& c) { c.Prepend(\"\"); },\n    [](absl::Cord& c) { }\n  },\n  {\n    \"prepend empty cord\",\n    [](absl::Cord& c) { c.Prepend(absl::Cord()); },\n    [](absl::Cord& c) { }\n  },\n  {\n    \"prepend empty checksummed cord\",\n    [](absl::Cord& c) {\n      absl::Cord to_prepend;\n      to_prepend.SetExpectedChecksum(999);\n      c.Prepend(to_prepend);\n    },\n    [](absl::Cord& c) { }\n  },\n  {\n    \"prepend self\",\n    [](absl::Cord& c) { c.Prepend(c); },\n    [](absl::Cord& c) { c.RemovePrefix(c.size() / 2); }\n  },\n  {\"remove prefix\", [](absl::Cord& c) { c.RemovePrefix(c.size() / 2); }},\n  {\"remove suffix\", [](absl::Cord& c) { c.RemoveSuffix(c.size() / 2); }},\n  {\"remove 0-prefix\", [](absl::Cord& c) { c.RemovePrefix(0); }},\n  {\"remove 0-suffix\", [](absl::Cord& c) { c.RemoveSuffix(0); }},\n  {\"subcord\", [](absl::Cord& c) { c = c.Subcord(1, c.size() - 2); }},\n  {\n    \"swap inline\",\n    [](absl::Cord& c) {\n      absl::Cord other(\"swap\");\n      c.swap(other);\n    }\n  },\n  {\n    \"swap tree\",\n    [](absl::Cord& c) {\n      absl::Cord other(std::string(10000, 'x'));\n      c.swap(other);\n    }\n  },\n};\n// clang-format on\n}  // namespace\n\nTEST_P(CordTest, ExpectedChecksum) {\n  for (const PopulatedCordFactory& factory : cord_factories) {\n    SCOPED_TRACE(factory.Name());\n    for (bool shared : {false, true}) {\n      SCOPED_TRACE(shared);\n\n      absl::Cord shared_cord_source = factory.Generate();\n      auto make_instance = [=] {\n        return shared ? shared_cord_source : factory.Generate();\n      };\n\n      const absl::Cord base_value = factory.Generate();\n      const std::string base_value_as_string(factory.Generate().Flatten());\n\n      absl::Cord c1 = make_instance();\n      EXPECT_FALSE(c1.ExpectedChecksum().has_value());\n\n      // Setting an expected checksum works, and retains the cord's bytes\n      c1.SetExpectedChecksum(12345);\n      EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);\n      EXPECT_EQ(c1, base_value);\n\n      // Test that setting an expected checksum again doesn't crash or leak\n      // memory.\n      c1.SetExpectedChecksum(12345);\n      EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);\n      EXPECT_EQ(c1, base_value);\n\n      // CRC persists through copies, assignments, and moves:\n      absl::Cord c1_copy_construct = c1;\n      EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);\n\n      absl::Cord c1_copy_assign;\n      c1_copy_assign = c1;\n      EXPECT_EQ(c1_copy_assign.ExpectedChecksum().value_or(0), 12345);\n\n      absl::Cord c1_move(std::move(c1_copy_assign));\n      EXPECT_EQ(c1_move.ExpectedChecksum().value_or(0), 12345);\n\n      EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);\n\n      // A CRC Cord compares equal to its non-CRC value.\n      EXPECT_EQ(c1, make_instance());\n\n      for (const CordMutator& mutator : cord_mutators) {\n        SCOPED_TRACE(mutator.Name());\n\n        // Test that mutating a cord removes its stored checksum\n        absl::Cord c2 = make_instance();\n        c2.SetExpectedChecksum(24680);\n\n        mutator.Mutate(c2);\n\n        if (c1 == c2) {\n          // Not a mutation (for example, appending the empty string).\n          // Whether the checksum is removed is not defined.\n          continue;\n        }\n\n        EXPECT_EQ(c2.ExpectedChecksum(), std::nullopt);\n\n        if (mutator.CanUndo()) {\n          // Undoing an operation should not restore the checksum\n          mutator.Undo(c2);\n          EXPECT_EQ(c2, base_value);\n          EXPECT_EQ(c2.ExpectedChecksum(), std::nullopt);\n        }\n      }\n\n      absl::Cord c3 = make_instance();\n      c3.SetExpectedChecksum(999);\n      const absl::Cord& cc3 = c3;\n\n      // Test that all cord reading operations function in the face of an\n      // expected checksum.\n\n      // Test data precondition\n      ASSERT_TRUE(cc3.StartsWith(\"abcde\"));\n\n      EXPECT_EQ(cc3.size(), base_value_as_string.size());\n      EXPECT_FALSE(cc3.empty());\n      EXPECT_EQ(cc3.Compare(base_value), 0);\n      EXPECT_EQ(cc3.Compare(base_value_as_string), 0);\n      EXPECT_EQ(cc3.Compare(\"wxyz\"), -1);\n      EXPECT_EQ(cc3.Compare(absl::Cord(\"wxyz\")), -1);\n      EXPECT_EQ(cc3.Compare(\"aaaa\"), 1);\n      EXPECT_EQ(cc3.Compare(absl::Cord(\"aaaa\")), 1);\n      EXPECT_EQ(absl::Cord(\"wxyz\").Compare(cc3), 1);\n      EXPECT_EQ(absl::Cord(\"aaaa\").Compare(cc3), -1);\n      EXPECT_TRUE(cc3.StartsWith(\"abcd\"));\n      EXPECT_EQ(std::string(cc3), base_value_as_string);\n\n      std::string dest;\n      absl::CopyCordToString(cc3, &dest);\n      EXPECT_EQ(dest, base_value_as_string);\n\n      bool first_pass = true;\n      for (absl::string_view chunk : cc3.Chunks()) {\n        if (first_pass) {\n          EXPECT_TRUE(absl::StartsWith(chunk, \"abcde\"));\n        }\n        first_pass = false;\n      }\n      first_pass = true;\n      for (char ch : cc3.Chars()) {\n        if (first_pass) {\n          EXPECT_EQ(ch, 'a');\n        }\n        first_pass = false;\n      }\n      EXPECT_TRUE(absl::StartsWith(*cc3.chunk_begin(), \"abcde\"));\n      EXPECT_EQ(*cc3.char_begin(), 'a');\n\n      auto char_it = cc3.char_begin();\n      absl::Cord::Advance(&char_it, 2);\n      EXPECT_EQ(absl::Cord::AdvanceAndRead(&char_it, 2), \"cd\");\n      EXPECT_EQ(*char_it, 'e');\n      char_it = cc3.char_begin();\n      absl::Cord::Advance(&char_it, 2);\n      EXPECT_TRUE(absl::StartsWith(absl::Cord::ChunkRemaining(char_it), \"cde\"));\n\n      EXPECT_EQ(cc3[0], 'a');\n      EXPECT_EQ(cc3[4], 'e');\n      EXPECT_EQ(absl::HashOf(cc3), absl::HashOf(base_value));\n      EXPECT_EQ(absl::HashOf(cc3), absl::HashOf(base_value_as_string));\n    }\n  }\n}\n\n// Test the special cases encountered with an empty checksummed cord.\nTEST_P(CordTest, ChecksummedEmptyCord) {\n  absl::Cord c1;\n  EXPECT_FALSE(c1.ExpectedChecksum().has_value());\n\n  // Setting an expected checksum works.\n  c1.SetExpectedChecksum(12345);\n  EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);\n  EXPECT_EQ(c1, \"\");\n  EXPECT_TRUE(c1.empty());\n\n  // Test that setting an expected checksum again doesn't crash or leak memory.\n  c1.SetExpectedChecksum(12345);\n  EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);\n  EXPECT_EQ(c1, \"\");\n  EXPECT_TRUE(c1.empty());\n\n  // CRC persists through copies, assignments, and moves:\n  absl::Cord c1_copy_construct = c1;\n  EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);\n\n  absl::Cord c1_copy_assign;\n  c1_copy_assign = c1;\n  EXPECT_EQ(c1_copy_assign.ExpectedChecksum().value_or(0), 12345);\n\n  absl::Cord c1_move(std::move(c1_copy_assign));\n  EXPECT_EQ(c1_move.ExpectedChecksum().value_or(0), 12345);\n\n  EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);\n\n  // A CRC Cord compares equal to its non-CRC value.\n  EXPECT_EQ(c1, absl::Cord());\n\n  for (const CordMutator& mutator : cord_mutators) {\n    SCOPED_TRACE(mutator.Name());\n\n    // Exercise mutating an empty checksummed cord to catch crashes and exercise\n    // memory sanitizers.\n    absl::Cord c2;\n    c2.SetExpectedChecksum(24680);\n    mutator.Mutate(c2);\n\n    if (c2.empty()) {\n      // Not a mutation\n      continue;\n    }\n    EXPECT_EQ(c2.ExpectedChecksum(), std::nullopt);\n\n    if (mutator.CanUndo()) {\n      mutator.Undo(c2);\n    }\n  }\n\n  absl::Cord c3;\n  c3.SetExpectedChecksum(999);\n  const absl::Cord& cc3 = c3;\n\n  // Test that all cord reading operations function in the face of an\n  // expected checksum.\n  EXPECT_TRUE(cc3.StartsWith(\"\"));\n  EXPECT_TRUE(cc3.EndsWith(\"\"));\n  EXPECT_TRUE(cc3.empty());\n  EXPECT_EQ(cc3, \"\");\n  EXPECT_EQ(cc3, absl::Cord());\n  EXPECT_EQ(cc3.size(), 0);\n  EXPECT_EQ(cc3.Compare(absl::Cord()), 0);\n  EXPECT_EQ(cc3.Compare(c1), 0);\n  EXPECT_EQ(cc3.Compare(cc3), 0);\n  EXPECT_EQ(cc3.Compare(\"\"), 0);\n  EXPECT_EQ(cc3.Compare(\"wxyz\"), -1);\n  EXPECT_EQ(cc3.Compare(absl::Cord(\"wxyz\")), -1);\n  EXPECT_EQ(absl::Cord(\"wxyz\").Compare(cc3), 1);\n  EXPECT_EQ(std::string(cc3), \"\");\n\n  std::string dest;\n  absl::CopyCordToString(cc3, &dest);\n  EXPECT_EQ(dest, \"\");\n\n  for (absl::string_view chunk : cc3.Chunks()) {  // NOLINT(unreachable loop)\n    static_cast<void>(chunk);\n    GTEST_FAIL() << \"no chunks expected\";\n  }\n  EXPECT_TRUE(cc3.chunk_begin() == cc3.chunk_end());\n\n  for (char ch : cc3.Chars()) {  // NOLINT(unreachable loop)\n    static_cast<void>(ch);\n    GTEST_FAIL() << \"no chars expected\";\n  }\n  EXPECT_TRUE(cc3.char_begin() == cc3.char_end());\n\n  EXPECT_EQ(cc3.TryFlat(), \"\");\n  EXPECT_EQ(absl::HashOf(c3), absl::HashOf(absl::Cord()));\n  EXPECT_EQ(absl::HashOf(c3), absl::HashOf(absl::string_view()));\n}\n\n// This must not be static to avoid aggressive optimizations.\nABSL_ATTRIBUTE_WEAK\nsize_t FalseReport(const absl::Cord& a, bool f);\n\nABSL_ATTRIBUTE_NOINLINE\nsize_t FalseReport(const absl::Cord& a, bool f) {\n  absl::Cord b;\n  const absl::Cord& ref = f ? b : a;\n  // Test that sanitizers report nothing here. Without\n  // InlineData::Rep::annotated_this() compiler can unconditionally load\n  // poisoned parts, assuming that local variable is fully accessible.\n  return ref.size();\n}\n\nTEST(CordSanitizerTest, SanitizesCordFalseReport) {\n  absl::Cord c;\n  for (int i = 0; i < 1000; ++i) c.Append(\"a\");\n  FalseReport(c, false);\n}\n\nTEST(CrcCordTest, ChecksummedEmptyCordEstimateMemoryUsage) {\n  absl::Cord cord;\n  cord.SetExpectedChecksum(0);\n  EXPECT_NE(cord.EstimatedMemoryUsage(), 0);\n}\n\nTEST(CordThreeWayComparisonTest, CompareCords) {\n#ifndef __cpp_impl_three_way_comparison\n  GTEST_SKIP() << \"C++20 three-way <=> comparison not supported\";\n#else\n  EXPECT_EQ(absl::Cord(\"a\") <=> absl::Cord(\"a\"), std::strong_ordering::equal);\n  EXPECT_EQ(absl::Cord(\"aaaa\") <=> absl::Cord(\"aaab\"),\n            std::strong_ordering::less);\n  EXPECT_EQ(absl::Cord(\"baaa\") <=> absl::Cord(\"a\"),\n            std::strong_ordering::greater);\n#endif\n}\n\nTEST(CordThreeWayComparisonTest, CompareCordsAndStringViews) {\n#ifndef __cpp_impl_three_way_comparison\n  GTEST_SKIP() << \"C++20 three-way <=> comparison not supported\";\n#else\n  EXPECT_EQ(absl::string_view(\"a\") <=> absl::Cord(\"a\"),\n            std::strong_ordering::equal);\n  EXPECT_EQ(absl::Cord(\"a\") <=> absl::string_view(\"b\"),\n            std::strong_ordering::less);\n  EXPECT_EQ(absl::string_view(\"b\") <=> absl::Cord(\"a\"),\n            std::strong_ordering::greater);\n#endif\n}\n\n#if defined(GTEST_HAS_DEATH_TEST) && defined(ABSL_INTERNAL_CORD_HAVE_SANITIZER)\n\n// Returns an expected poison / uninitialized death message expression.\nconst char* MASanDeathExpr() {\n  return \"(use-after-poison|use-of-uninitialized-value)\";\n}\n\nTEST(CordSanitizerTest, SanitizesEmptyCord) {\n  absl::Cord cord;\n  const char* data = cord.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[0], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesSmallCord) {\n  absl::Cord cord(\"Hello\");\n  const char* data = cord.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesCordOnSetSSOValue) {\n  absl::Cord cord(\"String that is too big to be an SSO value\");\n  cord = \"Hello\";\n  const char* data = cord.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesCordOnCopyCtor) {\n  absl::Cord src(\"hello\");\n  absl::Cord dst(src);\n  const char* data = dst.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesCordOnMoveCtor) {\n  absl::Cord src(\"hello\");\n  absl::Cord dst(std::move(src));\n  const char* data = dst.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesCordOnAssign) {\n  absl::Cord src(\"hello\");\n  absl::Cord dst;\n  dst = src;\n  const char* data = dst.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesCordOnMoveAssign) {\n  absl::Cord src(\"hello\");\n  absl::Cord dst;\n  dst = std::move(src);\n  const char* data = dst.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\nTEST(CordSanitizerTest, SanitizesCordOnSsoAssign) {\n  absl::Cord src(\"hello\");\n  absl::Cord dst(\"String that is too big to be an SSO value\");\n  dst = src;\n  const char* data = dst.Flatten().data();\n  EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());\n}\n\n#endif  // GTEST_HAS_DEATH_TEST && ABSL_INTERNAL_CORD_HAVE_SANITIZER\n"
  },
  {
    "path": "absl/strings/cord_test_helpers.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_\n#define ABSL_STRINGS_CORD_TEST_HELPERS_H_\n\n#include <cstdint>\n#include <iostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Cord sizes relevant for testing\nenum class TestCordSize {\n  // An empty value\n  kEmpty = 0,\n\n  // An inlined string value\n  kInlined = cord_internal::kMaxInline / 2 + 1,\n\n  // 'Well known' SSO lengths (excluding terminating zero).\n  // libstdcxx has a maximum SSO of 15, libc++ has a maximum SSO of 22.\n  kStringSso1 = 15,\n  kStringSso2 = 22,\n\n  // A string value which is too large to fit in inlined data, but small enough\n  // such that Cord prefers copying the value if possible, i.e.: not stealing\n  // std::string inputs, or referencing existing CordReps on Append, etc.\n  kSmall = cord_internal::kMaxBytesToCopy / 2 + 1,\n\n  // A string value large enough that Cord prefers to reference or steal from\n  // existing inputs rather than copying contents of the input.\n  kMedium = cord_internal::kMaxFlatLength / 2 + 1,\n\n  // A string value large enough to cause it to be stored in multiple flats.\n  kLarge = cord_internal::kMaxFlatLength * 4\n};\n\n// To string helper\ninline absl::string_view ToString(TestCordSize size) {\n  switch (size) {\n    case TestCordSize::kEmpty:\n      return \"Empty\";\n    case TestCordSize::kInlined:\n      return \"Inlined\";\n    case TestCordSize::kSmall:\n      return \"Small\";\n    case TestCordSize::kStringSso1:\n      return \"StringSso1\";\n    case TestCordSize::kStringSso2:\n      return \"StringSso2\";\n    case TestCordSize::kMedium:\n      return \"Medium\";\n    case TestCordSize::kLarge:\n      return \"Large\";\n  }\n  return \"???\";\n}\n\n// Returns the length matching the specified size\ninline size_t Length(TestCordSize size) { return static_cast<size_t>(size); }\n\n// Stream output helper\ninline std::ostream& operator<<(std::ostream& stream, TestCordSize size) {\n  return stream << ToString(size);\n}\n\n// Creates a multi-segment Cord from an iterable container of strings.  The\n// resulting Cord is guaranteed to have one segment for every string in the\n// container.  This allows code to be unit tested with multi-segment Cord\n// inputs.\n//\n// Example:\n//\n//   absl::Cord c = absl::MakeFragmentedCord({\"A \", \"fragmented \", \"Cord\"});\n//   EXPECT_FALSE(c.GetFlat(&unused));\n//\n// The mechanism by which this Cord is created is an implementation detail.  Any\n// implementation that produces a multi-segment Cord may produce a flat Cord in\n// the future as new optimizations are added to the Cord class.\n// MakeFragmentedCord will, however, always be updated to return a multi-segment\n// Cord.\ntemplate <typename Container>\nCord MakeFragmentedCord(const Container& c) {\n  Cord result;\n  for (const auto& s : c) {\n    auto* external = new std::string(s);\n    Cord tmp = absl::MakeCordFromExternal(\n        *external, [external](absl::string_view) { delete external; });\n    tmp.Prepend(result);\n    result = tmp;\n  }\n  return result;\n}\n\ninline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) {\n  return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_CORD_TEST_HELPERS_H_\n"
  },
  {
    "path": "absl/strings/cordz_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstring>\n#include <ostream>\n#include <string>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/cord_buffer.h\"\n#include \"absl/strings/cord_test_helpers.h\"\n#include \"absl/strings/cordz_test_helpers.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/strings/internal/cordz_sample_token.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef ABSL_INTERNAL_CORDZ_ENABLED\n\nusing testing::Eq;\nusing testing::AnyOf;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nusing cord_internal::CordzInfo;\nusing cord_internal::CordzSampleToken;\nusing cord_internal::CordzStatistics;\nusing cord_internal::CordzUpdateTracker;\nusing Method = CordzUpdateTracker::MethodIdentifier;\n\n// Do not print cord contents, we only care about 'size' perhaps.\n// Note that this method must be inside the named namespace.\ninline void PrintTo(const Cord& cord, std::ostream* s) {\n  if (s) *s << \"Cord[\" << cord.size() << \"]\";\n}\n\nnamespace {\n\nauto constexpr kMaxInline = cord_internal::kMaxInline;\n\n// Returns a string_view value of the specified length\n// We do this to avoid 'consuming' large strings in Cord by default.\nabsl::string_view MakeString(size_t size) {\n  thread_local std::string str;\n  str = std::string(size, '.');\n  return str;\n}\n\nabsl::string_view MakeString(TestCordSize size) {\n  return MakeString(Length(size));\n}\n\n// Returns a cord with a sampled method of kAppendString.\nabsl::Cord MakeAppendStringCord(TestCordSize size) {\n  CordzSamplingIntervalHelper always(1);\n  absl::Cord cord;\n  cord.Append(MakeString(size));\n  return cord;\n}\n\nstd::string TestParamToString(::testing::TestParamInfo<TestCordSize> size) {\n  return absl::StrCat(\"On\", ToString(size.param), \"Cord\");\n}\n\nclass CordzUpdateTest : public testing::TestWithParam<TestCordSize> {\n public:\n  Cord& cord() { return cord_; }\n\n  Method InitialOr(Method method) const {\n    return (GetParam() > TestCordSize::kInlined) ? Method::kConstructorString\n                                                 : method;\n  }\n\n private:\n  CordzSamplingIntervalHelper sample_every_{1};\n  Cord cord_{MakeString(GetParam())};\n};\n\ntemplate <typename T>\nstd::string ParamToString(::testing::TestParamInfo<T> param) {\n  return std::string(ToString(param.param));\n}\n\nINSTANTIATE_TEST_SUITE_P(WithParam, CordzUpdateTest,\n                         testing::Values(TestCordSize::kEmpty,\n                                         TestCordSize::kInlined,\n                                         TestCordSize::kLarge),\n                         TestParamToString);\n\nclass CordzStringTest : public testing::TestWithParam<TestCordSize> {\n private:\n  CordzSamplingIntervalHelper sample_every_{1};\n};\n\nINSTANTIATE_TEST_SUITE_P(WithParam, CordzStringTest,\n                         testing::Values(TestCordSize::kInlined,\n                                         TestCordSize::kStringSso1,\n                                         TestCordSize::kStringSso2,\n                                         TestCordSize::kSmall,\n                                         TestCordSize::kLarge),\n                         ParamToString<TestCordSize>);\n\nTEST(CordzTest, ConstructSmallArray) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord(MakeString(TestCordSize::kSmall));\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n}\n\nTEST(CordzTest, ConstructLargeArray) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord(MakeString(TestCordSize::kLarge));\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n}\n\nTEST_P(CordzStringTest, ConstructString) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord(std::string(Length(GetParam()), '.'));\n  if (Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  }\n}\n\nTEST(CordzTest, CopyConstructFromUnsampled) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  Cord cord(src);\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n}\n\nTEST(CordzTest, CopyConstructFromSampled) {\n  CordzSamplingIntervalHelper sample_never{99999};\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  Cord cord(src);\n  ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n}\n\nTEST(CordzTest, MoveConstruct) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord src(MakeString(TestCordSize::kLarge));\n  Cord cord(std::move(src));\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n}\n\nTEST_P(CordzUpdateTest, AssignUnsampledCord) {\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  const CordzInfo* info = GetCordzInfoForTesting(cord());\n  cord() = src;\n  EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));\n  EXPECT_FALSE(CordzInfoIsListed(info));\n}\n\nTEST_P(CordzUpdateTest, AssignSampledCord) {\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  cord() = src;\n  ASSERT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord())->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));\n}\n\nTEST(CordzUpdateTest, AssignSampledCordToInlined) {\n  CordzSamplingIntervalHelper sample_never{99999};\n  Cord cord;\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  cord = src;\n  ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));\n}\n\nTEST(CordzUpdateTest, AssignSampledCordToUnsampledCord) {\n  CordzSamplingIntervalHelper sample_never{99999};\n  Cord cord = UnsampledCord(MakeString(TestCordSize::kLarge));\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  cord = src;\n  ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));\n}\n\nTEST(CordzUpdateTest, AssignUnsampledCordToSampledCordWithoutSampling) {\n  CordzSamplingIntervalHelper sample_never{99999};\n  Cord cord = MakeAppendStringCord(TestCordSize::kLarge);\n  const CordzInfo* info = GetCordzInfoForTesting(cord);\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  cord = src;\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n  EXPECT_FALSE(CordzInfoIsListed(info));\n}\n\nTEST(CordzUpdateTest, AssignUnsampledCordToSampledCordWithSampling) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord = MakeAppendStringCord(TestCordSize::kLarge);\n  const CordzInfo* info = GetCordzInfoForTesting(cord);\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  cord = src;\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n  EXPECT_FALSE(CordzInfoIsListed(info));\n}\n\nTEST(CordzUpdateTest, AssignSampledCordToSampledCord) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  Cord cord(MakeString(TestCordSize::kLarge));\n  cord = src;\n  ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));\n}\n\nTEST(CordzUpdateTest, AssignUnsampledCordToSampledCord) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  Cord cord(MakeString(TestCordSize::kLarge));\n  cord = src;\n  ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));\n}\n\nTEST(CordzTest, AssignInlinedCordToSampledCord) {\n  CordzSampleToken token;\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord(MakeString(TestCordSize::kLarge));\n  const CordzInfo* info = GetCordzInfoForTesting(cord);\n  Cord src = UnsampledCord(MakeString(TestCordSize::kInlined));\n  cord = src;\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n  EXPECT_FALSE(CordzInfoIsListed(info));\n}\n\nTEST(CordzUpdateTest, MoveAssignCord) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord;\n  Cord src(MakeString(TestCordSize::kLarge));\n  cord = std::move(src);\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n}\n\nTEST_P(CordzUpdateTest, AssignLargeArray) {\n  cord() = MakeString(TestCordSize::kSmall);\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignString));\n}\n\nTEST_P(CordzUpdateTest, AssignSmallArray) {\n  cord() = MakeString(TestCordSize::kSmall);\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignString));\n}\n\nTEST_P(CordzUpdateTest, AssignInlinedArray) {\n  cord() = MakeString(TestCordSize::kInlined);\n  EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));\n}\n\nTEST_P(CordzStringTest, AssignStringToInlined) {\n  Cord cord;\n  cord = std::string(Length(GetParam()), '.');\n  if (Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAssignString));\n  }\n}\n\nTEST_P(CordzStringTest, AssignStringToCord) {\n  Cord cord(MakeString(TestCordSize::kLarge));\n  cord = std::string(Length(GetParam()), '.');\n  if (Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n    EXPECT_THAT(cord, CordzMethodCountEq(Method::kAssignString, 1));\n  }\n}\n\nTEST_P(CordzUpdateTest, AssignInlinedString) {\n  cord() = std::string(Length(TestCordSize::kInlined), '.');\n  EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));\n}\n\nTEST_P(CordzUpdateTest, AppendCord) {\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  cord().Append(src);\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendCord)));\n}\n\nTEST_P(CordzUpdateTest, MoveAppendCord) {\n  cord().Append(UnsampledCord(MakeString(TestCordSize::kLarge)));\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendCord)));\n}\n\nTEST_P(CordzUpdateTest, AppendSmallArray) {\n  cord().Append(MakeString(TestCordSize::kSmall));\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendString)));\n}\n\nTEST_P(CordzUpdateTest, AppendLargeArray) {\n  cord().Append(MakeString(TestCordSize::kLarge));\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendString)));\n}\n\nTEST_P(CordzStringTest, AppendStringToEmpty) {\n  Cord cord;\n  cord.Append(std::string(Length(GetParam()), '.'));\n  if (Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendString));\n  }\n}\n\nTEST_P(CordzStringTest, AppendStringToInlined) {\n  Cord cord(MakeString(TestCordSize::kInlined));\n  cord.Append(std::string(Length(GetParam()), '.'));\n  if (Length(TestCordSize::kInlined) + Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendString));\n  }\n}\n\nTEST_P(CordzStringTest, AppendStringToCord) {\n  Cord cord(MakeString(TestCordSize::kLarge));\n  cord.Append(std::string(Length(GetParam()), '.'));\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  EXPECT_THAT(cord, CordzMethodCountEq(Method::kAppendString, 1));\n}\n\nTEST(CordzTest, MakeCordFromExternal) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord = MakeCordFromExternal(\"Hello world\", [](absl::string_view) {});\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kMakeCordFromExternal));\n}\n\nTEST(CordzTest, MakeCordFromEmptyExternal) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord cord = MakeCordFromExternal({}, [](absl::string_view) {});\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n}\n\nTEST_P(CordzUpdateTest, PrependCord) {\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  cord().Prepend(src);\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependCord)));\n}\n\nTEST_P(CordzUpdateTest, PrependSmallArray) {\n  cord().Prepend(MakeString(TestCordSize::kSmall));\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependString)));\n}\n\nTEST_P(CordzUpdateTest, PrependLargeArray) {\n  cord().Prepend(MakeString(TestCordSize::kLarge));\n  EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependString)));\n}\n\nTEST_P(CordzStringTest, PrependStringToEmpty) {\n  Cord cord;\n  cord.Prepend(std::string(Length(GetParam()), '.'));\n  if (Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kPrependString));\n  }\n}\n\nTEST_P(CordzStringTest, PrependStringToInlined) {\n  Cord cord(MakeString(TestCordSize::kInlined));\n  cord.Prepend(std::string(Length(GetParam()), '.'));\n  if (Length(TestCordSize::kInlined) + Length(GetParam()) > kMaxInline) {\n    EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kPrependString));\n  }\n}\n\nTEST_P(CordzStringTest, PrependStringToCord) {\n  Cord cord(MakeString(TestCordSize::kLarge));\n  cord.Prepend(std::string(Length(GetParam()), '.'));\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  EXPECT_THAT(cord, CordzMethodCountEq(Method::kPrependString, 1));\n}\n\nTEST(CordzTest, RemovePrefix) {\n  CordzSamplingIntervalHelper sample_every(1);\n  Cord cord(MakeString(TestCordSize::kLarge));\n\n  // Half the cord\n  cord.RemovePrefix(cord.size() / 2);\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemovePrefix, 1));\n\n  // TODO(mvels): RemovePrefix does not reset to inlined, except if empty?\n  cord.RemovePrefix(cord.size() - kMaxInline);\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemovePrefix, 2));\n\n  cord.RemovePrefix(cord.size());\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n}\n\nTEST(CordzTest, RemoveSuffix) {\n  CordzSamplingIntervalHelper sample_every(1);\n  Cord cord(MakeString(TestCordSize::kLarge));\n\n  // Half the cord\n  cord.RemoveSuffix(cord.size() / 2);\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemoveSuffix, 1));\n\n  // TODO(mvels): RemoveSuffix does not reset to inlined, except if empty?\n  cord.RemoveSuffix(cord.size() - kMaxInline);\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));\n  EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemoveSuffix, 2));\n\n  cord.RemoveSuffix(cord.size());\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n}\n\nTEST(CordzTest, SubCordFromUnsampledCord) {\n  CordzSamplingIntervalHelper sample_every{1};\n  Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));\n  Cord cord = src.Subcord(10, src.size() / 2);\n  EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));\n}\n\nTEST(CordzTest, SubCordFromSampledCord) {\n  CordzSamplingIntervalHelper sample_never{99999};\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  Cord cord = src.Subcord(10, src.size() / 2);\n  ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kSubCord));\n  CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();\n  EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));\n  EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));\n}\n\nTEST(CordzTest, SmallSubCord) {\n  CordzSamplingIntervalHelper sample_never{99999};\n  Cord src = MakeAppendStringCord(TestCordSize::kLarge);\n  Cord cord = src.Subcord(10, kMaxInline + 1);\n  EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kSubCord));\n}\n\n}  // namespace\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_CORDZ_ENABLED\n"
  },
  {
    "path": "absl/strings/cordz_test_helpers.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_CORDZ_TEST_HELPERS_H_\n#define ABSL_STRINGS_CORDZ_TEST_HELPERS_H_\n\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/strings/internal/cordz_sample_token.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Returns the CordzInfo for the cord, or nullptr if the cord is not sampled.\ninline const cord_internal::CordzInfo* GetCordzInfoForTesting(\n    const Cord& cord) {\n  if (!cord.contents_.is_tree()) return nullptr;\n  return cord.contents_.cordz_info();\n}\n\n// Returns true if the provided cordz_info is in the list of sampled cords.\ninline bool CordzInfoIsListed(const cord_internal::CordzInfo* cordz_info,\n                              cord_internal::CordzSampleToken token = {}) {\n  for (const cord_internal::CordzInfo& info : token) {\n    if (cordz_info == &info) return true;\n  }\n  return false;\n}\n\n// Matcher on Cord that verifies all of:\n// - the cord is sampled\n// - the CordzInfo of the cord is listed / discoverable.\n// - the reported CordzStatistics match the cord's actual properties\n// - the cord has an (initial) UpdateTracker count of 1 for `method`\nMATCHER_P(HasValidCordzInfoOf, method, \"CordzInfo matches cord\") {\n  const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg);\n  if (cord_info == nullptr) {\n    *result_listener << \"cord is not sampled\";\n    return false;\n  }\n  if (!CordzInfoIsListed(cord_info)) {\n    *result_listener << \"cord is sampled, but not listed\";\n    return false;\n  }\n  cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics();\n  if (stat.size != arg.size()) {\n    *result_listener << \"cordz size \" << stat.size\n                     << \" does not match cord size \" << arg.size();\n    return false;\n  }\n  if (stat.update_tracker.Value(method) != 1) {\n    *result_listener << \"Expected method count 1 for \" << method << \", found \"\n                     << stat.update_tracker.Value(method);\n    return false;\n  }\n  return true;\n}\n\n// Matcher on Cord that verifies that the cord is sampled and that the CordzInfo\n// update tracker has 'method' with a call count of 'n'\nMATCHER_P2(CordzMethodCountEq, method, n,\n           absl::StrCat(\"CordzInfo method count equals \", n)) {\n  const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg);\n  if (cord_info == nullptr) {\n    *result_listener << \"cord is not sampled\";\n    return false;\n  }\n  cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics();\n  if (stat.update_tracker.Value(method) != n) {\n    *result_listener << \"Expected method count \" << n << \" for \" << method\n                     << \", found \" << stat.update_tracker.Value(method);\n    return false;\n  }\n  return true;\n}\n\n// Cordz will only update with a new rate once the previously scheduled event\n// has fired. When we disable Cordz, a long delay takes place where we won't\n// consider profiling new Cords. CordzSampleIntervalHelper will burn through\n// that interval and allow for testing that assumes that the average sampling\n// interval is a particular value.\nclass CordzSamplingIntervalHelper {\n public:\n  explicit CordzSamplingIntervalHelper(int32_t interval)\n      : orig_mean_interval_(absl::cord_internal::get_cordz_mean_interval()) {\n    absl::cord_internal::set_cordz_mean_interval(interval);\n    absl::cord_internal::cordz_set_next_sample_for_testing(interval);\n  }\n\n  ~CordzSamplingIntervalHelper() {\n    absl::cord_internal::set_cordz_mean_interval(orig_mean_interval_);\n    absl::cord_internal::cordz_set_next_sample_for_testing(orig_mean_interval_);\n  }\n\n private:\n  int32_t orig_mean_interval_;\n};\n\n// Wrapper struct managing a small CordRep `rep`\nstruct TestCordRep {\n  cord_internal::CordRepFlat* rep;\n\n  TestCordRep() {\n    rep = cord_internal::CordRepFlat::New(100);\n    rep->length = 100;\n    memset(rep->Data(), 1, 100);\n  }\n  ~TestCordRep() { cord_internal::CordRep::Unref(rep); }\n};\n\n// Wrapper struct managing a small CordRep `rep`, and\n// an InlineData `data` initialized with that CordRep.\nstruct TestCordData {\n  TestCordRep rep;\n  cord_internal::InlineData data{rep.rep};\n};\n\n// Creates a Cord that is not sampled\ntemplate <typename... Args>\nCord UnsampledCord(Args... args) {\n  CordzSamplingIntervalHelper never(9999);\n  Cord cord(std::forward<Args>(args)...);\n  ABSL_ASSERT(GetCordzInfoForTesting(cord) == nullptr);\n  return cord;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_CORDZ_TEST_HELPERS_H_\n"
  },
  {
    "path": "absl/strings/escaping.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/escaping.h\"\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <limits>\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/unaligned_access.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/charset.h\"\n#include \"absl/strings/internal/append_and_overwrite.h\"\n#include \"absl/strings/internal/escaping.h\"\n#include \"absl/strings/internal/utf8.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\n// These are used for the leave_nulls_escaped argument to CUnescapeInternal().\nconstexpr bool kUnescapeNulls = false;\n\ninline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); }\n\ninline unsigned int hex_digit_to_int(char c) {\n  static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61,\n                \"Character set must be ASCII.\");\n  assert(absl::ascii_isxdigit(static_cast<unsigned char>(c)));\n  unsigned int x = static_cast<unsigned char>(c);\n  if (x > '9') {\n    x += 9;\n  }\n  return x & 0xf;\n}\n\ninline bool IsSurrogate(char32_t c, absl::string_view src,\n                        std::string* absl_nullable error) {\n  if (c >= 0xD800 && c <= 0xDFFF) {\n    if (error) {\n      *error = absl::StrCat(\"invalid surrogate character (0xD800-DFFF): \\\\\",\n                            src);\n    }\n    return true;\n  }\n  return false;\n}\n\n// ----------------------------------------------------------------------\n// CUnescapeInternal()\n//    Implements both CUnescape() and CUnescapeForNullTerminatedString().\n//\n//    Unescapes C escape sequences and is the reverse of CEscape().\n//\n//    If `src` is valid, stores the unescaped string in `dst` and the length of\n//    unescaped string in `dst_size`, and returns true. Otherwise returns false\n//    and optionally stores the error description in `error`. Set `error` to\n//    nullptr to disable error reporting.\n//\n//    `src` and `dst` may use the same underlying buffer (but keep in mind\n//    that if this returns an error, it will leave both `src` and `dst` in\n//    an unspecified state because they are using the same underlying buffer.)\n//    `dst` must have at least as much space as `src`.\n// ----------------------------------------------------------------------\n\nbool CUnescapeInternal(absl::string_view src, bool leave_nulls_escaped,\n                       char* absl_nonnull dst, size_t* absl_nonnull dst_size,\n                       std::string* absl_nullable error) {\n  absl::string_view::size_type p = 0;  // Current src position.\n  size_t d = 0;                        // Current dst position.\n\n  // When unescaping in-place, skip any prefix that does not have escaping.\n  if (src.data() == dst) {\n    while (p < src.size() && src[p] != '\\\\') p++, d++;\n  }\n\n  while (p < src.size()) {\n    if (src[p] != '\\\\') {\n      dst[d++] = src[p++];\n    } else {\n      if (++p >= src.size()) {  // skip past the '\\\\'\n        if (error != nullptr) {\n          *error = \"String cannot end with \\\\\";\n        }\n        return false;\n      }\n      switch (src[p]) {\n          // clang-format off\n        case 'a':  dst[d++] = '\\a';  break;\n        case 'b':  dst[d++] = '\\b';  break;\n        case 'f':  dst[d++] = '\\f';  break;\n        case 'n':  dst[d++] = '\\n';  break;\n        case 'r':  dst[d++] = '\\r';  break;\n        case 't':  dst[d++] = '\\t';  break;\n        case 'v':  dst[d++] = '\\v';  break;\n        case '\\\\': dst[d++] = '\\\\';  break;\n        case '?':  dst[d++] = '\\?';  break;\n        case '\\'': dst[d++] = '\\'';  break;\n        case '\"':  dst[d++] = '\\\"';  break;\n        // clang-format on\n        case '0':\n        case '1':\n        case '2':\n        case '3':\n        case '4':\n        case '5':\n        case '6':\n        case '7': {\n          // octal digit: 1 to 3 digits\n          auto octal_start = p;\n          unsigned int ch = static_cast<unsigned int>(src[p] - '0');  // digit 1\n          if (p + 1 < src.size() && is_octal_digit(src[p + 1]))\n            ch = ch * 8 + static_cast<unsigned int>(src[++p] - '0');  // digit 2\n          if (p + 1 < src.size() && is_octal_digit(src[p + 1]))\n            ch = ch * 8 + static_cast<unsigned int>(src[++p] - '0');  // digit 3\n          if (ch > 0xff) {\n            if (error != nullptr) {\n              *error =\n                  \"Value of \\\\\" +\n                  std::string(src.substr(octal_start, p + 1 - octal_start)) +\n                  \" exceeds 0xff\";\n            }\n            return false;\n          }\n          if ((ch == 0) && leave_nulls_escaped) {\n            // Copy the escape sequence for the null character\n            dst[d++] = '\\\\';\n            while (octal_start <= p) {\n              dst[d++] = src[octal_start++];\n            }\n            break;\n          }\n          dst[d++] = static_cast<char>(ch);\n          break;\n        }\n        case 'x':\n        case 'X': {\n          if (p + 1 >= src.size()) {\n            if (error != nullptr) {\n              *error = \"String cannot end with \\\\x\";\n            }\n            return false;\n          } else if (!absl::ascii_isxdigit(\n              static_cast<unsigned char>(src[p + 1]))) {\n            if (error != nullptr) {\n              *error = \"\\\\x cannot be followed by a non-hex digit\";\n            }\n            return false;\n          }\n          unsigned int ch = 0;\n          auto hex_start = p;\n          while (p + 1 < src.size() &&\n                 absl::ascii_isxdigit(static_cast<unsigned char>(src[p + 1]))) {\n            // Arbitrarily many hex digits\n            ch = (ch << 4) + hex_digit_to_int(src[++p]);\n            // If ch was 0xFF at the start of this loop, the most can it can be\n            // here is (0xFF << 4) + 0xF, which is 4095, thus ch cannot overflow\n            // 32-bits here. The check below is sufficient.\n            if (ch > 0xFF) {\n              if (error != nullptr) {\n                *error = \"Value of \\\\\" +\n                         std::string(src.substr(hex_start, p + 1 - hex_start)) +\n                         \" exceeds 0xff\";\n              }\n              return false;\n            }\n          }\n          if ((ch == 0) && leave_nulls_escaped) {\n            // Copy the escape sequence for the null character\n            dst[d++] = '\\\\';\n            while (hex_start <= p) {\n              dst[d++] = src[hex_start++];\n            }\n            break;\n          }\n          dst[d++] = static_cast<char>(ch);\n          break;\n        }\n        case 'u': {\n          // \\uhhhh => convert 4 hex digits to UTF-8\n          char32_t rune = 0;\n          auto hex_start = p;\n          if (p + 4 >= src.size()) {\n            if (error != nullptr) {\n              *error = \"\\\\u must be followed by 4 hex digits\";\n            }\n            return false;\n          }\n          for (int i = 0; i < 4; ++i) {\n            // Look one char ahead.\n            if (absl::ascii_isxdigit(static_cast<unsigned char>(src[p + 1]))) {\n              rune = (rune << 4) + hex_digit_to_int(src[++p]);\n            } else {\n              if (error != nullptr) {\n                *error = \"\\\\u must be followed by 4 hex digits: \\\\\" +\n                         std::string(src.substr(hex_start, p + 1 - hex_start));\n              }\n              return false;\n            }\n          }\n          if ((rune == 0) && leave_nulls_escaped) {\n            // Copy the escape sequence for the null character\n            dst[d++] = '\\\\';\n            while (hex_start <= p) {\n              dst[d++] = src[hex_start++];\n            }\n            break;\n          }\n          if (IsSurrogate(rune, src.substr(hex_start, 5), error)) {\n            return false;\n          }\n          d += strings_internal::EncodeUTF8Char(dst + d, rune);\n          break;\n        }\n        case 'U': {\n          // \\Uhhhhhhhh => convert 8 hex digits to UTF-8\n          char32_t rune = 0;\n          auto hex_start = p;\n          if (p + 8 >= src.size()) {\n            if (error != nullptr) {\n              *error = \"\\\\U must be followed by 8 hex digits\";\n            }\n            return false;\n          }\n          for (int i = 0; i < 8; ++i) {\n            // Look one char ahead.\n            if (absl::ascii_isxdigit(static_cast<unsigned char>(src[p + 1]))) {\n              // Don't change rune until we're sure this\n              // is within the Unicode limit, but do advance p.\n              uint32_t newrune = (rune << 4) + hex_digit_to_int(src[++p]);\n              if (newrune > 0x10FFFF) {\n                if (error != nullptr) {\n                  *error =\n                      \"Value of \\\\\" +\n                      std::string(src.substr(hex_start, p + 1 - hex_start)) +\n                      \" exceeds Unicode limit (0x10FFFF)\";\n                }\n                return false;\n              } else {\n                rune = newrune;\n              }\n            } else {\n              if (error != nullptr) {\n                *error = \"\\\\U must be followed by 8 hex digits: \\\\\" +\n                         std::string(src.substr(hex_start, p + 1 - hex_start));\n              }\n              return false;\n            }\n          }\n          if ((rune == 0) && leave_nulls_escaped) {\n            // Copy the escape sequence for the null character\n            dst[d++] = '\\\\';\n            // U00000000\n            while (hex_start <= p) {\n              dst[d++] = src[hex_start++];\n            }\n            break;\n          }\n          if (IsSurrogate(rune, src.substr(hex_start, 9), error)) {\n            return false;\n          }\n          d += strings_internal::EncodeUTF8Char(dst + d, rune);\n          break;\n        }\n        default: {\n          if (error != nullptr) {\n            *error = std::string(\"Unknown escape sequence: \\\\\") + src[p];\n          }\n          return false;\n        }\n      }\n      p++;  // Read past letter we escaped.\n    }\n  }\n\n  *dst_size = d;\n  return true;\n}\n\n// ----------------------------------------------------------------------\n// CEscape()\n// CHexEscape()\n// Utf8SafeCEscape()\n// Utf8SafeCHexEscape()\n//    Escapes 'src' using C-style escape sequences.  This is useful for\n//    preparing query flags.  The 'Hex' version uses hexadecimal rather than\n//    octal sequences.  The 'Utf8Safe' version does not touch UTF-8 bytes.\n//\n//    Escaped chars: \\n, \\r, \\t, \", ', \\, and !absl::ascii_isprint().\n// ----------------------------------------------------------------------\nstd::string CEscapeInternal(absl::string_view src, bool use_hex,\n                            bool utf8_safe) {\n  std::string dest;\n  bool last_hex_escape = false;  // true if last output char was \\xNN.\n\n  for (char c : src) {\n    bool is_hex_escape = false;\n    switch (c) {\n      case '\\n': dest.append(\"\\\\\" \"n\"); break;\n      case '\\r': dest.append(\"\\\\\" \"r\"); break;\n      case '\\t': dest.append(\"\\\\\" \"t\"); break;\n      case '\\\"': dest.append(\"\\\\\" \"\\\"\"); break;\n      case '\\'': dest.append(\"\\\\\" \"'\"); break;\n      case '\\\\': dest.append(\"\\\\\" \"\\\\\"); break;\n      default: {\n        // Note that if we emit \\xNN and the src character after that is a hex\n        // digit then that digit must be escaped too to prevent it being\n        // interpreted as part of the character code by C.\n        const unsigned char uc = static_cast<unsigned char>(c);\n        if ((!utf8_safe || uc < 0x80) &&\n            (!absl::ascii_isprint(uc) ||\n             (last_hex_escape && absl::ascii_isxdigit(uc)))) {\n          if (use_hex) {\n            dest.append(\"\\\\\" \"x\");\n            dest.push_back(numbers_internal::kHexChar[uc / 16]);\n            dest.push_back(numbers_internal::kHexChar[uc % 16]);\n            is_hex_escape = true;\n          } else {\n            dest.append(\"\\\\\");\n            dest.push_back(numbers_internal::kHexChar[uc / 64]);\n            dest.push_back(numbers_internal::kHexChar[(uc % 64) / 8]);\n            dest.push_back(numbers_internal::kHexChar[uc % 8]);\n          }\n        } else {\n          dest.push_back(c);\n          break;\n        }\n      }\n    }\n    last_hex_escape = is_hex_escape;\n  }\n\n  return dest;\n}\n\n/* clang-format off */\nconstexpr std::array<unsigned char, 256> kCEscapedLen = {\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \\t, \\n, \\r\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,  // \", '\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // '0'..'9'\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'A'..'O'\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,  // 'P'..'Z', '\\'\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'a'..'o'\n    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,  // 'p'..'z', DEL\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n};\n/* clang-format on */\n\nconstexpr uint32_t MakeCEscapedLittleEndianUint32(size_t c) {\n  size_t char_len = kCEscapedLen[c];\n  if (char_len == 1) {\n    return static_cast<uint32_t>(c);\n  }\n  if (char_len == 2) {\n    switch (c) {\n      case '\\n':\n        return '\\\\' | (static_cast<uint32_t>('n') << 8);\n      case '\\r':\n        return '\\\\' | (static_cast<uint32_t>('r') << 8);\n      case '\\t':\n        return '\\\\' | (static_cast<uint32_t>('t') << 8);\n      case '\\\"':\n        return '\\\\' | (static_cast<uint32_t>('\\\"') << 8);\n      case '\\'':\n        return '\\\\' | (static_cast<uint32_t>('\\'') << 8);\n      case '\\\\':\n        return '\\\\' | (static_cast<uint32_t>('\\\\') << 8);\n    }\n  }\n  return static_cast<uint32_t>('\\\\' | (('0' + (c / 64)) << 8) |\n                               (('0' + ((c % 64) / 8)) << 16) |\n                               (('0' + (c % 8)) << 24));\n}\n\ntemplate <size_t... indexes>\ninline constexpr std::array<uint32_t, sizeof...(indexes)>\nMakeCEscapedLittleEndianUint32Array(std::index_sequence<indexes...>) {\n  return {MakeCEscapedLittleEndianUint32(indexes)...};\n}\nconstexpr std::array<uint32_t, 256> kCEscapedLittleEndianUint32Array =\n    MakeCEscapedLittleEndianUint32Array(std::make_index_sequence<256>());\n\n// Calculates the length of the C-style escaped version of 'src'.\n// Assumes that non-printable characters are escaped using octal sequences, and\n// that UTF-8 bytes are not handled specially.\ninline size_t CEscapedLength(absl::string_view src) {\n  size_t escaped_len = 0;\n  // The maximum value of kCEscapedLen[x] is 4, so we can escape any string of\n  // length size_t_max/4 without checking for overflow.\n  size_t unchecked_limit =\n      std::min<size_t>(src.size(), std::numeric_limits<size_t>::max() / 4);\n  size_t i = 0;\n  while (i < unchecked_limit) {\n    // Common case: No need to check for overflow.\n    escaped_len += kCEscapedLen[static_cast<unsigned char>(src[i++])];\n  }\n  while (i < src.size()) {\n    // Beyond unchecked_limit we need to check for overflow before adding.\n    size_t char_len = kCEscapedLen[static_cast<unsigned char>(src[i++])];\n    ABSL_INTERNAL_CHECK(\n        escaped_len <= std::numeric_limits<size_t>::max() - char_len,\n        \"escaped_len overflow\");\n    escaped_len += char_len;\n  }\n  return escaped_len;\n}\n\nvoid CEscapeAndAppendInternal(absl::string_view src,\n                              std::string* absl_nonnull dest) {\n  size_t escaped_len = CEscapedLength(src);\n  if (escaped_len == src.size()) {\n    dest->append(src.data(), src.size());\n    return;\n  }\n\n  // We keep 3 slop bytes so that we can call `little_endian::Store32`\n  // invariably regardless of the length of the escaped character.\n  constexpr size_t kSlopBytes = 3;\n  size_t cur_dest_len = dest->size();\n  size_t append_buf_len = cur_dest_len + escaped_len + kSlopBytes;\n  ABSL_INTERNAL_CHECK(append_buf_len > cur_dest_len,\n                      \"std::string size overflow\");\n  strings_internal::StringAppendAndOverwrite(\n      *dest, append_buf_len, [src, escaped_len](char* append_ptr, size_t) {\n        for (char c : src) {\n          unsigned char uc = static_cast<unsigned char>(c);\n          size_t char_len = kCEscapedLen[uc];\n          uint32_t little_endian_uint32 = kCEscapedLittleEndianUint32Array[uc];\n          little_endian::Store32(append_ptr, little_endian_uint32);\n          append_ptr += char_len;\n        }\n        return escaped_len;\n      });\n}\n\n// Reverses the mapping in Base64EscapeInternal; see that method's\n// documentation for details of the mapping.\nbool Base64UnescapeInternal(const char* absl_nullable src_param, size_t szsrc,\n                            char* absl_nullable dest, size_t szdest,\n                            const std::array<signed char, 256>& unbase64,\n                            size_t* absl_nonnull len) {\n  static const char kPad64Equals = '=';\n  static const char kPad64Dot = '.';\n\n  size_t destidx = 0;\n  int decode = 0;\n  int state = 0;\n  unsigned char ch = 0;\n  unsigned int temp = 0;\n\n  // If \"char\" is signed by default, using *src as an array index results in\n  // accessing negative array elements. Treat the input as a pointer to\n  // unsigned char to avoid this.\n  const unsigned char* src = reinterpret_cast<const unsigned char*>(src_param);\n\n  // The GET_INPUT macro gets the next input character, skipping\n  // over any whitespace, and stopping when we reach the end of the\n  // string or when we read any non-data character.  The arguments are\n  // an arbitrary identifier (used as a label for goto) and the number\n  // of data bytes that must remain in the input to avoid aborting the\n  // loop.\n#define GET_INPUT(label, remain)                                \\\n  label:                                                        \\\n  --szsrc;                                                      \\\n  ch = *src++;                                                  \\\n  decode = unbase64[ch];                                        \\\n  if (decode < 0) {                                             \\\n    if (absl::ascii_isspace(ch) && szsrc >= remain) goto label; \\\n    state = 4 - remain;                                         \\\n    break;                                                      \\\n  }\n\n  // if dest is null, we're just checking to see if it's legal input\n  // rather than producing output.  (I suspect this could just be done\n  // with a regexp...).  We duplicate the loop so this test can be\n  // outside it instead of in every iteration.\n\n  if (dest) {\n    // This loop consumes 4 input bytes and produces 3 output bytes\n    // per iteration.  We can't know at the start that there is enough\n    // data left in the string for a full iteration, so the loop may\n    // break out in the middle; if so 'state' will be set to the\n    // number of input bytes read.\n\n    while (szsrc >= 4) {\n      // We'll start by optimistically assuming that the next four\n      // bytes of the string (src[0..3]) are four good data bytes\n      // (that is, no nulls, whitespace, padding chars, or illegal\n      // chars).  We need to test src[0..2] for nulls individually\n      // before constructing temp to preserve the property that we\n      // never read past a null in the string (no matter how long\n      // szsrc claims the string is).\n\n      if (!src[0] || !src[1] || !src[2] ||\n          ((temp = ((unsigned(unbase64[src[0]]) << 18) |\n                    (unsigned(unbase64[src[1]]) << 12) |\n                    (unsigned(unbase64[src[2]]) << 6) |\n                    (unsigned(unbase64[src[3]])))) &\n           0x80000000)) {\n        // Iff any of those four characters was bad (null, illegal,\n        // whitespace, padding), then temp's high bit will be set\n        // (because unbase64[] is -1 for all bad characters).\n        //\n        // We'll back up and resort to the slower decoder, which knows\n        // how to handle those cases.\n\n        GET_INPUT(first, 4);\n        temp = static_cast<unsigned char>(decode);\n        GET_INPUT(second, 3);\n        temp = (temp << 6) | static_cast<unsigned char>(decode);\n        GET_INPUT(third, 2);\n        temp = (temp << 6) | static_cast<unsigned char>(decode);\n        GET_INPUT(fourth, 1);\n        temp = (temp << 6) | static_cast<unsigned char>(decode);\n      } else {\n        // We really did have four good data bytes, so advance four\n        // characters in the string.\n\n        szsrc -= 4;\n        src += 4;\n      }\n\n      // temp has 24 bits of input, so write that out as three bytes.\n\n      if (destidx + 3 > szdest) return false;\n      dest[destidx + 2] = static_cast<char>(temp);\n      temp >>= 8;\n      dest[destidx + 1] = static_cast<char>(temp);\n      temp >>= 8;\n      dest[destidx] = static_cast<char>(temp);\n      destidx += 3;\n    }\n  } else {\n    while (szsrc >= 4) {\n      if (!src[0] || !src[1] || !src[2] ||\n          ((temp = ((unsigned(unbase64[src[0]]) << 18) |\n                    (unsigned(unbase64[src[1]]) << 12) |\n                    (unsigned(unbase64[src[2]]) << 6) |\n                    (unsigned(unbase64[src[3]])))) &\n           0x80000000)) {\n        GET_INPUT(first_no_dest, 4);\n        GET_INPUT(second_no_dest, 3);\n        GET_INPUT(third_no_dest, 2);\n        GET_INPUT(fourth_no_dest, 1);\n      } else {\n        szsrc -= 4;\n        src += 4;\n      }\n      destidx += 3;\n    }\n  }\n\n#undef GET_INPUT\n\n  // if the loop terminated because we read a bad character, return\n  // now.\n  if (decode < 0 && ch != kPad64Equals && ch != kPad64Dot &&\n      !absl::ascii_isspace(ch))\n    return false;\n\n  if (ch == kPad64Equals || ch == kPad64Dot) {\n    // if we stopped by hitting an '=' or '.', un-read that character -- we'll\n    // look at it again when we count to check for the proper number of\n    // equals signs at the end.\n    ++szsrc;\n    --src;\n  } else {\n    // This loop consumes 1 input byte per iteration.  It's used to\n    // clean up the 0-3 input bytes remaining when the first, faster\n    // loop finishes.  'temp' contains the data from 'state' input\n    // characters read by the first loop.\n    while (szsrc > 0) {\n      --szsrc;\n      ch = *src++;\n      decode = unbase64[ch];\n      if (decode < 0) {\n        if (absl::ascii_isspace(ch)) {\n          continue;\n        } else if (ch == kPad64Equals || ch == kPad64Dot) {\n          // back up one character; we'll read it again when we check\n          // for the correct number of pad characters at the end.\n          ++szsrc;\n          --src;\n          break;\n        } else {\n          return false;\n        }\n      }\n\n      // Each input character gives us six bits of output.\n      temp = (temp << 6) | static_cast<unsigned char>(decode);\n      ++state;\n      if (state == 4) {\n        // If we've accumulated 24 bits of output, write that out as\n        // three bytes.\n        if (dest) {\n          if (destidx + 3 > szdest) return false;\n          dest[destidx + 2] = static_cast<char>(temp);\n          temp >>= 8;\n          dest[destidx + 1] = static_cast<char>(temp);\n          temp >>= 8;\n          dest[destidx] = static_cast<char>(temp);\n        }\n        destidx += 3;\n        state = 0;\n        temp = 0;\n      }\n    }\n  }\n\n  // Process the leftover data contained in 'temp' at the end of the input.\n  int expected_equals = 0;\n  switch (state) {\n    case 0:\n      // Nothing left over; output is a multiple of 3 bytes.\n      break;\n\n    case 1:\n      // Bad input; we have 6 bits left over.\n      return false;\n\n    case 2:\n      // Produce one more output byte from the 12 input bits we have left.\n      if (dest) {\n        if (destidx + 1 > szdest) return false;\n        temp >>= 4;\n        dest[destidx] = static_cast<char>(temp);\n      }\n      ++destidx;\n      expected_equals = 2;\n      break;\n\n    case 3:\n      // Produce two more output bytes from the 18 input bits we have left.\n      if (dest) {\n        if (destidx + 2 > szdest) return false;\n        temp >>= 2;\n        dest[destidx + 1] = static_cast<char>(temp);\n        temp >>= 8;\n        dest[destidx] = static_cast<char>(temp);\n      }\n      destidx += 2;\n      expected_equals = 1;\n      break;\n\n    default:\n      // state should have no other values at this point.\n      ABSL_RAW_LOG(FATAL, \"This can't happen; base64 decoder state = %d\",\n                   state);\n  }\n\n  // The remainder of the string should be all whitespace, mixed with\n  // exactly 0 equals signs, or exactly 'expected_equals' equals\n  // signs.  (Always accepting 0 equals signs is an Abseil extension\n  // not covered in the RFC, as is accepting dot as the pad character.)\n\n  int equals = 0;\n  while (szsrc > 0) {\n    if (*src == kPad64Equals || *src == kPad64Dot)\n      ++equals;\n    else if (!absl::ascii_isspace(*src))\n      return false;\n    --szsrc;\n    ++src;\n  }\n\n  const bool ok = (equals == 0 || equals == expected_equals);\n  if (ok) *len = destidx;\n  return ok;\n}\n\n// The arrays below map base64-escaped characters back to their original values.\n// For the inverse case, see k(WebSafe)Base64Chars in the internal\n// escaping.cc.\n// These arrays were generated by the following inversion code:\n// #include <sys/time.h>\n// #include <stdlib.h>\n// #include <string.h>\n// main()\n// {\n//   static const char Base64[] =\n//     \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n//   char* pos;\n//   int idx, i, j;\n//   printf(\"    \");\n//   for (i = 0; i < 255; i += 8) {\n//     for (j = i; j < i + 8; j++) {\n//       pos = strchr(Base64, j);\n//       if ((pos == nullptr) || (j == 0))\n//         idx = -1;\n//       else\n//         idx = pos - Base64;\n//       if (idx == -1)\n//         printf(\" %2d,     \", idx);\n//       else\n//         printf(\" %2d/*%c*/,\", idx, j);\n//     }\n//     printf(\"\\n    \");\n//   }\n// }\n//\n// where the value of \"Base64[]\" was replaced by one of k(WebSafe)Base64Chars\n// in the internal escaping.cc.\n/* clang-format off */\nconstexpr std::array<signed char, 256> kUnBase64 = {\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,\n    52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,\n    60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,\n    -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,\n    07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,\n    15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,\n    23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,\n    -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,\n    33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,\n    41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,\n    49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1\n};\n\nconstexpr std::array<signed char, 256> kUnWebSafeBase64 = {\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      62/*-*/, -1,      -1,\n    52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,\n    60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,\n    -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,\n    07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,\n    15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,\n    23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      63/*_*/,\n    -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,\n    33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,\n    41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,\n    49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,\n    -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1\n};\n/* clang-format on */\n\ntemplate <typename String>\nbool Base64UnescapeInternal(const char* absl_nullable src, size_t slen,\n                            String* absl_nonnull dest,\n                            const std::array<signed char, 256>& unbase64) {\n  // Determine the size of the output string.  Base64 encodes every 3 bytes into\n  // 4 characters.  Any leftover chars are added directly for good measure.\n  const size_t dest_len = 3 * (slen / 4) + (slen % 4);\n\n  bool ok;\n  StringResizeAndOverwrite(\n      *dest, dest_len, [src, slen, unbase64, &ok](char* buf, size_t buf_size) {\n        size_t len;\n        ok = Base64UnescapeInternal(src, slen, buf, buf_size, unbase64, &len);\n        if (!ok) {\n          len = 0;\n        }\n        assert(len <= buf_size);  // Could be shorter if there was padding.\n        return len;\n      });\n  return ok;\n}\n\n/* clang-format off */\nconstexpr std::array<uint8_t, 256> kHexValueLenient = {\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  1,  2,  3,  4,  5,  6, 7, 8, 9, 0, 0, 0, 0, 0, 0,  // '0'..'9'\n    0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'A'..'F'\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'a'..'f'\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\n\nconstexpr std::array<int8_t, 256> kHexValueStrict = {\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  // '0'..'9'\n    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  // 'A'..'F'\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  // 'a'..'f'\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n};\n/* clang-format on */\n\n// This is a templated function so that T can be either a char*\n// or a string.  This works because we use the [] operator to access\n// individual characters at a time.\ntemplate <typename T>\nvoid HexStringToBytesInternal(const char* absl_nullable from, T to,\n                              size_t num) {\n  for (size_t i = 0; i < num; i++) {\n    to[i] = static_cast<char>(kHexValueLenient[from[i * 2] & 0xFF] << 4) +\n            static_cast<char>(kHexValueLenient[from[i * 2 + 1] & 0xFF]);\n  }\n}\n\nvoid BytesToHexStringInternal(const unsigned char* absl_nullable src,\n                              char* dest, size_t num) {\n  for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest += 2) {\n    const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];\n    std::copy(hex_p, hex_p + 2, dest);\n  }\n}\n\n}  // namespace\n\n// ----------------------------------------------------------------------\n// CUnescape()\n//\n// See CUnescapeInternal() for implementation details.\n// ----------------------------------------------------------------------\n\nbool CUnescape(absl::string_view source, std::string* absl_nonnull dest,\n               std::string* absl_nullable error) {\n  bool success;\n\n  // `CUnescape()` allows for in-place unescaping, which means `source` may\n  // alias `*dest`.  However, absl::StringResizeAndOverwrite() invalidates all\n  // iterators, pointers, and references into the string, regardless whether\n  // reallocation occurs. Therefore we need to avoid calling\n  // absl::StringResizeAndOverwrite() when `source.data() ==\n  // dest->data()`. Comparing the sizes is sufficient to cover this case.\n  if (dest->size() >= source.size()) {\n    size_t dest_size = 0;\n    success = CUnescapeInternal(source, kUnescapeNulls, dest->data(),\n                                &dest_size, error);\n    ABSL_ASSERT(dest_size <= dest->size());\n    dest->erase(dest_size);\n  } else {\n    StringResizeAndOverwrite(\n        *dest, source.size(),\n        [source, error, &success](char* buf, size_t buf_size) {\n          size_t dest_size = 0;\n          success =\n              CUnescapeInternal(source, kUnescapeNulls, buf, &dest_size, error);\n          ABSL_ASSERT(dest_size <= buf_size);\n          return dest_size;\n        });\n  }\n  return success;\n}\n\nstd::string CEscape(absl::string_view src) {\n  std::string dest;\n  CEscapeAndAppendInternal(src, &dest);\n  return dest;\n}\n\nstd::string CHexEscape(absl::string_view src) {\n  return CEscapeInternal(src, true, false);\n}\n\nstd::string Utf8SafeCEscape(absl::string_view src) {\n  return CEscapeInternal(src, false, true);\n}\n\nstd::string Utf8SafeCHexEscape(absl::string_view src) {\n  return CEscapeInternal(src, true, true);\n}\n\nbool Base64Unescape(absl::string_view src, std::string* absl_nonnull dest) {\n  return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);\n}\n\nbool WebSafeBase64Unescape(absl::string_view src,\n                           std::string* absl_nonnull dest) {\n  return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);\n}\n\nstd::string Base64Escape(absl::string_view src) {\n  std::string dest;\n  strings_internal::Base64EscapeInternal(\n      reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,\n      true, strings_internal::kBase64Chars);\n  return dest;\n}\n\nstd::string WebSafeBase64Escape(absl::string_view src) {\n  std::string dest;\n  strings_internal::Base64EscapeInternal(\n      reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,\n      false, strings_internal::kWebSafeBase64Chars);\n  return dest;\n}\n\nbool HexStringToBytes(absl::string_view hex, std::string* absl_nonnull bytes) {\n  std::string output;\n\n  size_t num_bytes = hex.size() / 2;\n  if (hex.size() != num_bytes * 2) {\n    return false;\n  }\n\n  StringResizeAndOverwrite(\n      output, num_bytes, [hex](char* buf, size_t buf_size) {\n        auto hex_p = hex.cbegin();\n        for (size_t i = 0; i < buf_size; ++i) {\n          int h1 = absl::kHexValueStrict[static_cast<size_t>(\n              static_cast<uint8_t>(*hex_p++))];\n          int h2 = absl::kHexValueStrict[static_cast<size_t>(\n              static_cast<uint8_t>(*hex_p++))];\n          if (h1 == -1 || h2 == -1) {\n            return size_t{0};\n          }\n          buf[i] = static_cast<char>((h1 << 4) + h2);\n        }\n        return buf_size;\n      });\n\n  if (output.size() != num_bytes) {\n    return false;\n  }\n  *bytes = std::move(output);\n  return true;\n}\n\nstd::string HexStringToBytes(absl::string_view from) {\n  std::string result;\n  const auto num = from.size() / 2;\n  StringResizeAndOverwrite(result, num, [from](char* buf, size_t buf_size) {\n    absl::HexStringToBytesInternal<char*>(from.data(), buf, buf_size);\n    return buf_size;\n  });\n  return result;\n}\n\nstd::string BytesToHexString(absl::string_view from) {\n  std::string result;\n  StringResizeAndOverwrite(\n      result, 2 * from.size(), [from](char* buf, size_t buf_size) {\n        absl::BytesToHexStringInternal(\n            reinterpret_cast<const unsigned char*>(from.data()), buf,\n            from.size());\n        return buf_size;\n      });\n  return result;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/escaping.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: escaping.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains string utilities involved in escaping and\n// unescaping strings in various ways.\n\n#ifndef ABSL_STRINGS_ESCAPING_H_\n#define ABSL_STRINGS_ESCAPING_H_\n\n#include <cstddef>\n#include <string>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/str_join.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// CUnescape()\n//\n// Unescapes a `source` string and copies it into `dest`, rewriting C-style\n// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into\n// their proper code point equivalents, returning `true` if successful.\n//\n// The following unescape sequences can be handled:\n//\n//   * ASCII escape sequences ('\\n','\\r','\\\\', etc.) to their ASCII equivalents\n//   * Octal escape sequences ('\\nnn') to byte nnn. The unescaped value must\n//     resolve to a single byte or an error will occur. E.g. values greater than\n//     0xff will produce an error.\n//   * Hexadecimal escape sequences ('\\xnn') to byte nn. While an arbitrary\n//     number of following digits are allowed, the unescaped value must resolve\n//     to a single byte or an error will occur. E.g. '\\x0045' is equivalent to\n//     '\\x45', but '\\x1234' will produce an error.\n//   * Unicode escape sequences ('\\unnnn' for exactly four hex digits or\n//     '\\Unnnnnnnn' for exactly eight hex digits, which will be encoded in\n//     UTF-8. (E.g., `\\u2019` unescapes to the three bytes 0xE2, 0x80, and\n//     0x99).\n//\n// If any errors are encountered, this function returns `false`, leaving the\n// `dest` output parameter in an unspecified state, and stores the first\n// encountered error in `error`. To disable error reporting, set `error` to\n// `nullptr` or use the overload with no error reporting below.\n//\n// Example:\n//\n//   std::string s = \"foo\\\\rbar\\\\nbaz\\\\t\";\n//   std::string unescaped_s;\n//   if (!absl::CUnescape(s, &unescaped_s)) {\n//     ...\n//   }\n//   EXPECT_EQ(unescaped_s, \"foo\\rbar\\nbaz\\t\");\nbool CUnescape(absl::string_view source, std::string* absl_nonnull dest,\n               std::string* absl_nullable error);\n\n// Overload of `CUnescape()` with no error reporting.\ninline bool CUnescape(absl::string_view source,\n                      std::string* absl_nonnull dest) {\n  return CUnescape(source, dest, nullptr);\n}\n\n// CEscape()\n//\n// Escapes a 'src' string using C-style escapes sequences\n// (https://en.cppreference.com/w/cpp/language/escape), escaping other\n// non-printable/non-whitespace bytes as octal sequences (e.g. \"\\377\").\n//\n// Example:\n//\n//   std::string s = \"foo\\rbar\\tbaz\\010\\011\\012\\013\\014\\x0d\\n\";\n//   std::string escaped_s = absl::CEscape(s);\n//   EXPECT_EQ(escaped_s, \"foo\\\\rbar\\\\tbaz\\\\010\\\\t\\\\n\\\\013\\\\014\\\\r\\\\n\");\nstd::string CEscape(absl::string_view src);\n\n// CHexEscape()\n//\n// Escapes a 'src' string using C-style escape sequences, escaping\n// other non-printable/non-whitespace bytes as hexadecimal sequences (e.g.\n// \"\\xFF\").\n//\n// Example:\n//\n//   std::string s = \"foo\\rbar\\tbaz\\010\\011\\012\\013\\014\\x0d\\n\";\n//   std::string escaped_s = absl::CHexEscape(s);\n//   EXPECT_EQ(escaped_s, \"foo\\\\rbar\\\\tbaz\\\\x08\\\\t\\\\n\\\\x0b\\\\x0c\\\\r\\\\n\");\nstd::string CHexEscape(absl::string_view src);\n\n// Utf8SafeCEscape()\n//\n// Escapes a 'src' string using C-style escape sequences, escaping bytes as\n// octal sequences, and passing through UTF-8 characters without conversion.\n// I.e., when encountering any bytes with their high bit set, this function\n// will not escape those values, whether or not they are valid UTF-8.\nstd::string Utf8SafeCEscape(absl::string_view src);\n\n// Utf8SafeCHexEscape()\n//\n// Escapes a 'src' string using C-style escape sequences, escaping bytes as\n// hexadecimal sequences, and passing through UTF-8 characters without\n// conversion.\nstd::string Utf8SafeCHexEscape(absl::string_view src);\n\n// Base64Escape()\n//\n// Encodes a `src` string into a base64-encoded 'dest' string with padding\n// characters. This function conforms with RFC 4648 section 4 (base64) and RFC\n// 2045.\nstd::string Base64Escape(absl::string_view src);\n[[deprecated(\n    \"Use the string-returning version of \"\n    \"Base64Escape()\")]] ABSL_REFACTOR_INLINE inline void\nBase64Escape(absl::string_view src, std::string* absl_nonnull dest) {\n  *dest = Base64Escape(src);\n}\n\n// WebSafeBase64Escape()\n//\n// Encodes a `src` string into a base64 string, like Base64Escape() does, but\n// outputs '-' instead of '+' and '_' instead of '/', and does not pad 'dest'.\n// This function conforms with RFC 4648 section 5 (base64url).\nstd::string WebSafeBase64Escape(absl::string_view src);\n[[deprecated(\n    \"Use the string-returning version of \"\n    \"WebSafeBase64Escape()\")]] ABSL_REFACTOR_INLINE inline void\nWebSafeBase64Escape(absl::string_view src, std::string* absl_nonnull dest) {\n  *dest = WebSafeBase64Escape(src);\n}\n\n// Base64Unescape()\n//\n// Converts a `src` string encoded in Base64 (RFC 4648 section 4) to its binary\n// equivalent, writing it to a `dest` buffer, returning `true` on success. If\n// `src` contains invalid characters, `dest` is cleared and returns `false`.\n// If padding is included (note that `Base64Escape()` does produce it), it must\n// be correct. In the padding, '=' and '.' are treated identically.\nbool Base64Unescape(absl::string_view src, std::string* absl_nonnull dest);\n\n// WebSafeBase64Unescape()\n//\n// Converts a `src` string encoded in \"web safe\" Base64 (RFC 4648 section 5) to\n// its binary equivalent, writing it to a `dest` buffer. If `src` contains\n// invalid characters, `dest` is cleared and returns `false`. If padding is\n// included (note that `WebSafeBase64Escape()` does not produce it), it must be\n// correct. In the padding, '=' and '.' are treated identically.\nbool WebSafeBase64Unescape(absl::string_view src,\n                           std::string* absl_nonnull dest);\n\n// HexStringToBytes()\n//\n// Converts the hexadecimal encoded data in `hex` into raw bytes in the `bytes`\n// output string.  If `hex` does not consist of valid hexadecimal data, this\n// function returns false and leaves `bytes` in an unspecified state. Returns\n// true on success.\n[[nodiscard]] bool HexStringToBytes(absl::string_view hex,\n                                    std::string* absl_nonnull bytes);\n\n// HexStringToBytes()\n//\n// Converts an ASCII hex string into bytes, returning binary data of length\n// `from.size()/2`. The input must be valid hexadecimal data, otherwise the\n// return value is unspecified.\nABSL_DEPRECATED(\"Use the HexStringToBytes() that returns a bool\")\nstd::string HexStringToBytes(absl::string_view from);\n\n// BytesToHexString()\n//\n// Converts binary data into an ASCII text string, returning a string of size\n// `2*from.size()`.\nstd::string BytesToHexString(absl::string_view from);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_ESCAPING_H_\n"
  },
  {
    "path": "absl/strings/escaping_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n#include <memory>\n#include <random>\n#include <string>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/internal/escaping_test_common.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_CUnescapeHexString(benchmark::State& state) {\n  std::string src;\n  for (int i = 0; i < 50; i++) {\n    src += \"\\\\x55\";\n  }\n  for (auto _ : state) {\n    std::string dest;\n    benchmark::DoNotOptimize(src);\n    bool result = absl::CUnescape(src, &dest);\n    benchmark::DoNotOptimize(result);\n    benchmark::DoNotOptimize(dest);\n  }\n}\nBENCHMARK(BM_CUnescapeHexString);\n\nvoid BM_WebSafeBase64Escape_string(benchmark::State& state) {\n  std::string raw;\n  for (int i = 0; i < 10; ++i) {\n    for (const auto& test_set : absl::strings_internal::base64_strings()) {\n      raw += std::string(test_set.plaintext);\n    }\n  }\n  for (auto _ : state) {\n    std::string escaped = absl::WebSafeBase64Escape(raw);\n    benchmark::DoNotOptimize(escaped);\n  }\n}\nBENCHMARK(BM_WebSafeBase64Escape_string);\n\nvoid BM_HexStringToBytes(benchmark::State& state) {\n  const int size = state.range(0);\n  std::string input, output;\n  for (int i = 0; i < size; ++i) input += \"1c\";\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(input);\n    bool result = absl::HexStringToBytes(input, &output);\n    benchmark::DoNotOptimize(result);\n    benchmark::DoNotOptimize(output);\n  }\n}\nBENCHMARK(BM_HexStringToBytes)->Range(1, 1 << 8);\n\nvoid BM_HexStringToBytes_Fail(benchmark::State& state) {\n  std::string binary;\n  absl::string_view hex_input1 = \"1c2f003\";\n  absl::string_view hex_input2 = \"1c2f0032f40123456789abcdef**\";\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(hex_input1);\n    bool result1 = absl::HexStringToBytes(hex_input1, &binary);\n    benchmark::DoNotOptimize(result1);\n    benchmark::DoNotOptimize(binary);\n    benchmark::DoNotOptimize(hex_input2);\n    bool result2 = absl::HexStringToBytes(hex_input2, &binary);\n    benchmark::DoNotOptimize(result2);\n    benchmark::DoNotOptimize(binary);\n  }\n}\nBENCHMARK(BM_HexStringToBytes_Fail);\n\n// Used for the CEscape benchmarks\nconst char kStringValueNoEscape[] = \"1234567890\";\nconst char kStringValueSomeEscaped[] = \"123\\n56789\\xA1\";\nconst char kStringValueMostEscaped[] = \"\\xA1\\xA2\\ny\\xA4\\xA5\\xA6z\\b\\r\";\n\nvoid CEscapeBenchmarkHelper(benchmark::State& state, const char* string_value,\n                            int max_len) {\n  std::string src;\n  while (src.size() < max_len) {\n    absl::StrAppend(&src, string_value);\n  }\n\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(src);\n    std::string result = absl::CEscape(src);\n    benchmark::DoNotOptimize(result);\n  }\n}\n\nvoid BM_CEscape_NoEscape(benchmark::State& state) {\n  CEscapeBenchmarkHelper(state, kStringValueNoEscape, state.range(0));\n}\nBENCHMARK(BM_CEscape_NoEscape)->Range(1, 1 << 14);\n\nvoid BM_CEscape_SomeEscaped(benchmark::State& state) {\n  CEscapeBenchmarkHelper(state, kStringValueSomeEscaped, state.range(0));\n}\nBENCHMARK(BM_CEscape_SomeEscaped)->Range(1, 1 << 14);\n\nvoid BM_CEscape_MostEscaped(benchmark::State& state) {\n  CEscapeBenchmarkHelper(state, kStringValueMostEscaped, state.range(0));\n}\nBENCHMARK(BM_CEscape_MostEscaped)->Range(1, 1 << 14);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/escaping_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/escaping.h\"\n\n#include <array>\n#include <cstddef>\n#include <cstdio>\n#include <cstring>\n#include <initializer_list>\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/check.h\"\n#include \"absl/strings/str_cat.h\"\n\n#include \"absl/strings/internal/escaping_test_common.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nstruct epair {\n  std::string escaped;\n  std::string unescaped;\n};\n\nTEST(CEscape, EscapeAndUnescape) {\n  const std::string inputs[] = {\n      std::string(\"foo\\nxx\\r\\b\\0023\"),\n      std::string(\"\"),\n      std::string(\"abc\"),\n      std::string(\"\\1chad_rules\"),\n      std::string(\"\\1arnar_drools\"),\n      std::string(\"xxxx\\r\\t'\\\"\\\\\"),\n      std::string(\"\\0xx\\0\", 4),\n      std::string(\"\\x01\\x31\"),\n      std::string(\"abc\\xb\\x42\\141bc\"),\n      std::string(\"123\\1\\x31\\x32\\x33\"),\n      std::string(\"\\xc1\\xca\\x1b\\x62\\x19o\\xcc\\x04\"),\n      std::string(\n          \"\\\\\\\"\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\\\\\\" is Google\\\\\\'s Chinese name\"),\n  };\n  // Do this twice, once for octal escapes and once for hex escapes.\n  for (int kind = 0; kind < 4; kind++) {\n    for (const std::string& original : inputs) {\n      std::string escaped;\n      switch (kind) {\n        case 0:\n          escaped = absl::CEscape(original);\n          break;\n        case 1:\n          escaped = absl::CHexEscape(original);\n          break;\n        case 2:\n          escaped = absl::Utf8SafeCEscape(original);\n          break;\n        case 3:\n          escaped = absl::Utf8SafeCHexEscape(original);\n          break;\n      }\n      std::string unescaped_str;\n      EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str));\n      EXPECT_EQ(unescaped_str, original);\n\n      unescaped_str.erase();\n      std::string error;\n      EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str, &error));\n      EXPECT_EQ(error, \"\");\n\n      // Check in-place unescaping\n      std::string s = escaped;\n      EXPECT_TRUE(absl::CUnescape(s, &s));\n      ASSERT_EQ(s, original);\n    }\n  }\n  // Check that all possible two character strings can be escaped then\n  // unescaped successfully.\n  for (int char0 = 0; char0 < 256; char0++) {\n    for (int char1 = 0; char1 < 256; char1++) {\n      char chars[2];\n      chars[0] = char0;\n      chars[1] = char1;\n      std::string s(chars, 2);\n      std::string escaped = absl::CHexEscape(s);\n      std::string unescaped;\n      EXPECT_TRUE(absl::CUnescape(escaped, &unescaped));\n      EXPECT_EQ(s, unescaped);\n    }\n  }\n}\n\nTEST(CEscape, BasicEscaping) {\n  epair oct_values[] = {\n      {\"foo\\\\rbar\\\\nbaz\\\\t\", \"foo\\rbar\\nbaz\\t\"},\n      {\"\\\\'full of \\\\\\\"sound\\\\\\\" and \\\\\\\"fury\\\\\\\"\\\\'\",\n       \"'full of \\\"sound\\\" and \\\"fury\\\"'\"},\n      {\"signi\\\\\\\\fying\\\\\\\\ nothing\\\\\\\\\", \"signi\\\\fying\\\\ nothing\\\\\"},\n      {\"\\\\010\\\\t\\\\n\\\\013\\\\014\\\\r\", \"\\010\\011\\012\\013\\014\\015\"}\n  };\n  epair hex_values[] = {\n      {\"ubik\\\\rubik\\\\nubik\\\\t\", \"ubik\\rubik\\nubik\\t\"},\n      {\"I\\\\\\'ve just seen a \\\\\\\"face\\\\\\\"\",\n       \"I've just seen a \\\"face\\\"\"},\n      {\"hel\\\\\\\\ter\\\\\\\\skel\\\\\\\\ter\\\\\\\\\", \"hel\\\\ter\\\\skel\\\\ter\\\\\"},\n      {\"\\\\x08\\\\t\\\\n\\\\x0b\\\\x0c\\\\r\", \"\\010\\011\\012\\013\\014\\015\"}\n  };\n  epair utf8_oct_values[] = {\n      {\"\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\\\r\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\\\nbaz\\\\t\",\n       \"\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\r\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\nbaz\\t\"},\n      {\"\\\\\\\"\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\\\\\\" is Google\\\\\\'s Chinese name\",\n       \"\\\"\\xe8\\xb0\\xb7\\xe6\\xad\\x8c\\\" is Google\\'s Chinese name\"},\n      {\"\\xe3\\x83\\xa1\\xe3\\x83\\xbc\\xe3\\x83\\xab\\\\\\\\are\\\\\\\\Japanese\\\\\\\\chars\\\\\\\\\",\n       \"\\xe3\\x83\\xa1\\xe3\\x83\\xbc\\xe3\\x83\\xab\\\\are\\\\Japanese\\\\chars\\\\\"},\n      {\"\\xed\\x81\\xac\\xeb\\xa1\\xac\\\\010\\\\t\\\\n\\\\013\\\\014\\\\r\",\n       \"\\xed\\x81\\xac\\xeb\\xa1\\xac\\010\\011\\012\\013\\014\\015\"}\n  };\n  epair utf8_hex_values[] = {\n      {\"\\x20\\xe4\\xbd\\xa0\\\\t\\xe5\\xa5\\xbd,\\\\r!\\\\n\",\n       \"\\x20\\xe4\\xbd\\xa0\\t\\xe5\\xa5\\xbd,\\r!\\n\"},\n      {\"\\xe8\\xa9\\xa6\\xe9\\xa8\\x93\\\\\\' means \\\\\\\"test\\\\\\\"\",\n       \"\\xe8\\xa9\\xa6\\xe9\\xa8\\x93\\' means \\\"test\\\"\"},\n      {\"\\\\\\\\\\xe6\\x88\\x91\\\\\\\\:\\\\\\\\\\xe6\\x9d\\xa8\\xe6\\xac\\xa2\\\\\\\\\",\n       \"\\\\\\xe6\\x88\\x91\\\\:\\\\\\xe6\\x9d\\xa8\\xe6\\xac\\xa2\\\\\"},\n      {\"\\xed\\x81\\xac\\xeb\\xa1\\xac\\\\x08\\\\t\\\\n\\\\x0b\\\\x0c\\\\r\",\n       \"\\xed\\x81\\xac\\xeb\\xa1\\xac\\010\\011\\012\\013\\014\\015\"}\n  };\n\n  for (const epair& val : oct_values) {\n    std::string escaped = absl::CEscape(val.unescaped);\n    EXPECT_EQ(escaped, val.escaped);\n  }\n  for (const epair& val : hex_values) {\n    std::string escaped = absl::CHexEscape(val.unescaped);\n    EXPECT_EQ(escaped, val.escaped);\n  }\n  for (const epair& val : utf8_oct_values) {\n    std::string escaped = absl::Utf8SafeCEscape(val.unescaped);\n    EXPECT_EQ(escaped, val.escaped);\n  }\n  for (const epair& val : utf8_hex_values) {\n    std::string escaped = absl::Utf8SafeCHexEscape(val.unescaped);\n    EXPECT_EQ(escaped, val.escaped);\n  }\n}\n\nTEST(Unescape, BasicFunction) {\n  epair tests[] =\n    {{\"\", \"\"},\n     {\"\\\\u0030\", \"0\"},\n     {\"\\\\u00A3\", \"\\xC2\\xA3\"},\n     {\"\\\\u22FD\", \"\\xE2\\x8B\\xBD\"},\n     {\"\\\\U00010000\", \"\\xF0\\x90\\x80\\x80\"},\n     {\"\\\\U0010FFFD\", \"\\xF4\\x8F\\xBF\\xBD\"}};\n  for (const epair& val : tests) {\n    std::string out;\n    EXPECT_TRUE(absl::CUnescape(val.escaped, &out));\n    EXPECT_EQ(out, val.unescaped);\n  }\n  constexpr absl::string_view bad[] = {\n      \"\\\\u1\",          // too short\n      \"\\\\U1\",          // too short\n      \"\\\\Uffffff\",     // exceeds 0x10ffff (largest Unicode)\n      \"\\\\U00110000\",   // exceeds 0x10ffff (largest Unicode)\n      \"\\\\uD835\",       // surrogate character (D800-DFFF)\n      \"\\\\U0000DD04\",   // surrogate character (D800-DFFF)\n      \"\\\\777\",         // exceeds 0xff\n      \"\\\\xABCD\",       // exceeds 0xff\n      \"\\\\x100000041\",  // overflows uint32_t\n      \"endswith\\\\\",    // ends with \"\\\"\n      \"endswith\\\\x\",   // ends with \"\\x\"\n      \"endswith\\\\X\",   // ends with \"\\X\"\n      \"\\\\x.2345678\",   // non-hex follows \"\\x\"\n      \"\\\\X.2345678\",   // non-hex follows \"\\X\"\n      \"\\\\u.2345678\",   // non-hex follows \"\\U\"\n      \"\\\\U.2345678\",   // non-hex follows \"\\U\"\n      \"\\\\.unknown\",    // unknown escape sequence\n  };\n  for (const auto e : bad) {\n    std::string error;\n    std::string out;\n    EXPECT_FALSE(absl::CUnescape(e, &out, &error));\n    EXPECT_FALSE(error.empty());\n\n    out.erase();\n    EXPECT_FALSE(absl::CUnescape(e, &out));\n  }\n}\n\nclass CUnescapeTest : public testing::Test {\n protected:\n  static const char kStringWithMultipleOctalNulls[];\n  static const char kStringWithMultipleHexNulls[];\n  static const char kStringWithMultipleUnicodeNulls[];\n\n  std::string result_string_;\n};\n\nconst char CUnescapeTest::kStringWithMultipleOctalNulls[] =\n    \"\\\\0\\\\n\"    // null escape \\0 plus newline\n    \"0\\\\n\"      // just a number 0 (not a null escape) plus newline\n    \"\\\\00\\\\12\"  // null escape \\00 plus octal newline code\n    \"\\\\000\";    // null escape \\000\n\n// This has the same ingredients as kStringWithMultipleOctalNulls\n// but with \\x hex escapes instead of octal escapes.\nconst char CUnescapeTest::kStringWithMultipleHexNulls[] =\n    \"\\\\x0\\\\n\"\n    \"0\\\\n\"\n    \"\\\\x00\\\\xa\"\n    \"\\\\x000\";\n\nconst char CUnescapeTest::kStringWithMultipleUnicodeNulls[] =\n    \"\\\\u0000\\\\n\"    // short-form (4-digit) null escape plus newline\n    \"0\\\\n\"          // just a number 0 (not a null escape) plus newline\n    \"\\\\U00000000\";  // long-form (8-digit) null escape\n\nTEST_F(CUnescapeTest, Unescapes1CharOctalNull) {\n  std::string original_string = \"\\\\0\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes2CharOctalNull) {\n  std::string original_string = \"\\\\00\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes3CharOctalNull) {\n  std::string original_string = \"\\\\000\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes1CharHexNull) {\n  std::string original_string = \"\\\\x0\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes2CharHexNull) {\n  std::string original_string = \"\\\\x00\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes3CharHexNull) {\n  std::string original_string = \"\\\\x000\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes4CharUnicodeNull) {\n  std::string original_string = \"\\\\u0000\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, Unescapes8CharUnicodeNull) {\n  std::string original_string = \"\\\\U00000000\";\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\", 1), result_string_);\n}\n\nTEST_F(CUnescapeTest, UnescapesMultipleOctalNulls) {\n  std::string original_string(kStringWithMultipleOctalNulls);\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  // All escapes, including newlines and null escapes, should have been\n  // converted to the equivalent characters.\n  EXPECT_EQ(std::string(\"\\0\\n\"\n                        \"0\\n\"\n                        \"\\0\\n\"\n                        \"\\0\",\n                        7),\n            result_string_);\n}\n\n\nTEST_F(CUnescapeTest, UnescapesMultipleHexNulls) {\n  std::string original_string(kStringWithMultipleHexNulls);\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\\n\"\n                        \"0\\n\"\n                        \"\\0\\n\"\n                        \"\\0\",\n                        7),\n            result_string_);\n}\n\nTEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) {\n  std::string original_string(kStringWithMultipleUnicodeNulls);\n  EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));\n  EXPECT_EQ(std::string(\"\\0\\n\"\n                        \"0\\n\"\n                        \"\\0\",\n                        5),\n            result_string_);\n}\n\nstatic struct {\n  absl::string_view plaintext;\n  absl::string_view cyphertext;\n} const base64_tests[] = {\n    // Empty string.\n    {{\"\", 0}, {\"\", 0}},\n    {{nullptr, 0},\n     {\"\", 0}},  // if length is zero, plaintext ptr must be ignored!\n\n    // Basic bit patterns;\n    // values obtained with \"echo -n '...' | uuencode -m test\"\n\n    {{\"\\000\", 1}, \"AA==\"},\n    {{\"\\001\", 1}, \"AQ==\"},\n    {{\"\\002\", 1}, \"Ag==\"},\n    {{\"\\004\", 1}, \"BA==\"},\n    {{\"\\010\", 1}, \"CA==\"},\n    {{\"\\020\", 1}, \"EA==\"},\n    {{\"\\040\", 1}, \"IA==\"},\n    {{\"\\100\", 1}, \"QA==\"},\n    {{\"\\200\", 1}, \"gA==\"},\n\n    {{\"\\377\", 1}, \"/w==\"},\n    {{\"\\376\", 1}, \"/g==\"},\n    {{\"\\375\", 1}, \"/Q==\"},\n    {{\"\\373\", 1}, \"+w==\"},\n    {{\"\\367\", 1}, \"9w==\"},\n    {{\"\\357\", 1}, \"7w==\"},\n    {{\"\\337\", 1}, \"3w==\"},\n    {{\"\\277\", 1}, \"vw==\"},\n    {{\"\\177\", 1}, \"fw==\"},\n    {{\"\\000\\000\", 2}, \"AAA=\"},\n    {{\"\\000\\001\", 2}, \"AAE=\"},\n    {{\"\\000\\002\", 2}, \"AAI=\"},\n    {{\"\\000\\004\", 2}, \"AAQ=\"},\n    {{\"\\000\\010\", 2}, \"AAg=\"},\n    {{\"\\000\\020\", 2}, \"ABA=\"},\n    {{\"\\000\\040\", 2}, \"ACA=\"},\n    {{\"\\000\\100\", 2}, \"AEA=\"},\n    {{\"\\000\\200\", 2}, \"AIA=\"},\n    {{\"\\001\\000\", 2}, \"AQA=\"},\n    {{\"\\002\\000\", 2}, \"AgA=\"},\n    {{\"\\004\\000\", 2}, \"BAA=\"},\n    {{\"\\010\\000\", 2}, \"CAA=\"},\n    {{\"\\020\\000\", 2}, \"EAA=\"},\n    {{\"\\040\\000\", 2}, \"IAA=\"},\n    {{\"\\100\\000\", 2}, \"QAA=\"},\n    {{\"\\200\\000\", 2}, \"gAA=\"},\n\n    {{\"\\377\\377\", 2}, \"//8=\"},\n    {{\"\\377\\376\", 2}, \"//4=\"},\n    {{\"\\377\\375\", 2}, \"//0=\"},\n    {{\"\\377\\373\", 2}, \"//s=\"},\n    {{\"\\377\\367\", 2}, \"//c=\"},\n    {{\"\\377\\357\", 2}, \"/+8=\"},\n    {{\"\\377\\337\", 2}, \"/98=\"},\n    {{\"\\377\\277\", 2}, \"/78=\"},\n    {{\"\\377\\177\", 2}, \"/38=\"},\n    {{\"\\376\\377\", 2}, \"/v8=\"},\n    {{\"\\375\\377\", 2}, \"/f8=\"},\n    {{\"\\373\\377\", 2}, \"+/8=\"},\n    {{\"\\367\\377\", 2}, \"9/8=\"},\n    {{\"\\357\\377\", 2}, \"7/8=\"},\n    {{\"\\337\\377\", 2}, \"3/8=\"},\n    {{\"\\277\\377\", 2}, \"v/8=\"},\n    {{\"\\177\\377\", 2}, \"f/8=\"},\n\n    {{\"\\000\\000\\000\", 3}, \"AAAA\"},\n    {{\"\\000\\000\\001\", 3}, \"AAAB\"},\n    {{\"\\000\\000\\002\", 3}, \"AAAC\"},\n    {{\"\\000\\000\\004\", 3}, \"AAAE\"},\n    {{\"\\000\\000\\010\", 3}, \"AAAI\"},\n    {{\"\\000\\000\\020\", 3}, \"AAAQ\"},\n    {{\"\\000\\000\\040\", 3}, \"AAAg\"},\n    {{\"\\000\\000\\100\", 3}, \"AABA\"},\n    {{\"\\000\\000\\200\", 3}, \"AACA\"},\n    {{\"\\000\\001\\000\", 3}, \"AAEA\"},\n    {{\"\\000\\002\\000\", 3}, \"AAIA\"},\n    {{\"\\000\\004\\000\", 3}, \"AAQA\"},\n    {{\"\\000\\010\\000\", 3}, \"AAgA\"},\n    {{\"\\000\\020\\000\", 3}, \"ABAA\"},\n    {{\"\\000\\040\\000\", 3}, \"ACAA\"},\n    {{\"\\000\\100\\000\", 3}, \"AEAA\"},\n    {{\"\\000\\200\\000\", 3}, \"AIAA\"},\n    {{\"\\001\\000\\000\", 3}, \"AQAA\"},\n    {{\"\\002\\000\\000\", 3}, \"AgAA\"},\n    {{\"\\004\\000\\000\", 3}, \"BAAA\"},\n    {{\"\\010\\000\\000\", 3}, \"CAAA\"},\n    {{\"\\020\\000\\000\", 3}, \"EAAA\"},\n    {{\"\\040\\000\\000\", 3}, \"IAAA\"},\n    {{\"\\100\\000\\000\", 3}, \"QAAA\"},\n    {{\"\\200\\000\\000\", 3}, \"gAAA\"},\n\n    {{\"\\377\\377\\377\", 3}, \"////\"},\n    {{\"\\377\\377\\376\", 3}, \"///+\"},\n    {{\"\\377\\377\\375\", 3}, \"///9\"},\n    {{\"\\377\\377\\373\", 3}, \"///7\"},\n    {{\"\\377\\377\\367\", 3}, \"///3\"},\n    {{\"\\377\\377\\357\", 3}, \"///v\"},\n    {{\"\\377\\377\\337\", 3}, \"///f\"},\n    {{\"\\377\\377\\277\", 3}, \"//+/\"},\n    {{\"\\377\\377\\177\", 3}, \"//9/\"},\n    {{\"\\377\\376\\377\", 3}, \"//7/\"},\n    {{\"\\377\\375\\377\", 3}, \"//3/\"},\n    {{\"\\377\\373\\377\", 3}, \"//v/\"},\n    {{\"\\377\\367\\377\", 3}, \"//f/\"},\n    {{\"\\377\\357\\377\", 3}, \"/+//\"},\n    {{\"\\377\\337\\377\", 3}, \"/9//\"},\n    {{\"\\377\\277\\377\", 3}, \"/7//\"},\n    {{\"\\377\\177\\377\", 3}, \"/3//\"},\n    {{\"\\376\\377\\377\", 3}, \"/v//\"},\n    {{\"\\375\\377\\377\", 3}, \"/f//\"},\n    {{\"\\373\\377\\377\", 3}, \"+///\"},\n    {{\"\\367\\377\\377\", 3}, \"9///\"},\n    {{\"\\357\\377\\377\", 3}, \"7///\"},\n    {{\"\\337\\377\\377\", 3}, \"3///\"},\n    {{\"\\277\\377\\377\", 3}, \"v///\"},\n    {{\"\\177\\377\\377\", 3}, \"f///\"},\n\n    // Random numbers: values obtained with\n    //\n    //  #! /bin/bash\n    //  dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random\n    //  od -N $1 -t o1 /tmp/bar.random\n    //  uuencode -m test < /tmp/bar.random\n    //\n    // where $1 is the number of bytes (2, 3)\n\n    {{\"\\243\\361\", 2}, \"o/E=\"},\n    {{\"\\024\\167\", 2}, \"FHc=\"},\n    {{\"\\313\\252\", 2}, \"y6o=\"},\n    {{\"\\046\\041\", 2}, \"JiE=\"},\n    {{\"\\145\\236\", 2}, \"ZZ4=\"},\n    {{\"\\254\\325\", 2}, \"rNU=\"},\n    {{\"\\061\\330\", 2}, \"Mdg=\"},\n    {{\"\\245\\032\", 2}, \"pRo=\"},\n    {{\"\\006\\000\", 2}, \"BgA=\"},\n    {{\"\\375\\131\", 2}, \"/Vk=\"},\n    {{\"\\303\\210\", 2}, \"w4g=\"},\n    {{\"\\040\\037\", 2}, \"IB8=\"},\n    {{\"\\261\\372\", 2}, \"sfo=\"},\n    {{\"\\335\\014\", 2}, \"3Qw=\"},\n    {{\"\\233\\217\", 2}, \"m48=\"},\n    {{\"\\373\\056\", 2}, \"+y4=\"},\n    {{\"\\247\\232\", 2}, \"p5o=\"},\n    {{\"\\107\\053\", 2}, \"Rys=\"},\n    {{\"\\204\\077\", 2}, \"hD8=\"},\n    {{\"\\276\\211\", 2}, \"vok=\"},\n    {{\"\\313\\110\", 2}, \"y0g=\"},\n    {{\"\\363\\376\", 2}, \"8/4=\"},\n    {{\"\\251\\234\", 2}, \"qZw=\"},\n    {{\"\\103\\262\", 2}, \"Q7I=\"},\n    {{\"\\142\\312\", 2}, \"Yso=\"},\n    {{\"\\067\\211\", 2}, \"N4k=\"},\n    {{\"\\220\\001\", 2}, \"kAE=\"},\n    {{\"\\152\\240\", 2}, \"aqA=\"},\n    {{\"\\367\\061\", 2}, \"9zE=\"},\n    {{\"\\133\\255\", 2}, \"W60=\"},\n    {{\"\\176\\035\", 2}, \"fh0=\"},\n    {{\"\\032\\231\", 2}, \"Gpk=\"},\n\n    {{\"\\013\\007\\144\", 3}, \"Cwdk\"},\n    {{\"\\030\\112\\106\", 3}, \"GEpG\"},\n    {{\"\\047\\325\\046\", 3}, \"J9Um\"},\n    {{\"\\310\\160\\022\", 3}, \"yHAS\"},\n    {{\"\\131\\100\\237\", 3}, \"WUCf\"},\n    {{\"\\064\\342\\134\", 3}, \"NOJc\"},\n    {{\"\\010\\177\\004\", 3}, \"CH8E\"},\n    {{\"\\345\\147\\205\", 3}, \"5WeF\"},\n    {{\"\\300\\343\\360\", 3}, \"wOPw\"},\n    {{\"\\061\\240\\201\", 3}, \"MaCB\"},\n    {{\"\\225\\333\\044\", 3}, \"ldsk\"},\n    {{\"\\215\\137\\352\", 3}, \"jV/q\"},\n    {{\"\\371\\147\\160\", 3}, \"+Wdw\"},\n    {{\"\\030\\320\\051\", 3}, \"GNAp\"},\n    {{\"\\044\\174\\241\", 3}, \"JHyh\"},\n    {{\"\\260\\127\\037\", 3}, \"sFcf\"},\n    {{\"\\111\\045\\033\", 3}, \"SSUb\"},\n    {{\"\\202\\114\\107\", 3}, \"gkxH\"},\n    {{\"\\057\\371\\042\", 3}, \"L/ki\"},\n    {{\"\\223\\247\\244\", 3}, \"k6ek\"},\n    {{\"\\047\\216\\144\", 3}, \"J45k\"},\n    {{\"\\203\\070\\327\", 3}, \"gzjX\"},\n    {{\"\\247\\140\\072\", 3}, \"p2A6\"},\n    {{\"\\124\\115\\116\", 3}, \"VE1O\"},\n    {{\"\\157\\162\\050\", 3}, \"b3Io\"},\n    {{\"\\357\\223\\004\", 3}, \"75ME\"},\n    {{\"\\052\\117\\156\", 3}, \"Kk9u\"},\n    {{\"\\347\\154\\000\", 3}, \"52wA\"},\n    {{\"\\303\\012\\142\", 3}, \"wwpi\"},\n    {{\"\\060\\035\\362\", 3}, \"MB3y\"},\n    {{\"\\130\\226\\361\", 3}, \"WJbx\"},\n    {{\"\\173\\013\\071\", 3}, \"ews5\"},\n    {{\"\\336\\004\\027\", 3}, \"3gQX\"},\n    {{\"\\357\\366\\234\", 3}, \"7/ac\"},\n    {{\"\\353\\304\\111\", 3}, \"68RJ\"},\n    {{\"\\024\\264\\131\", 3}, \"FLRZ\"},\n    {{\"\\075\\114\\251\", 3}, \"PUyp\"},\n    {{\"\\315\\031\\225\", 3}, \"zRmV\"},\n    {{\"\\154\\201\\276\", 3}, \"bIG+\"},\n    {{\"\\200\\066\\072\", 3}, \"gDY6\"},\n    {{\"\\142\\350\\267\", 3}, \"Yui3\"},\n    {{\"\\033\\000\\166\", 3}, \"GwB2\"},\n    {{\"\\210\\055\\077\", 3}, \"iC0/\"},\n    {{\"\\341\\037\\124\", 3}, \"4R9U\"},\n    {{\"\\161\\103\\152\", 3}, \"cUNq\"},\n    {{\"\\270\\142\\131\", 3}, \"uGJZ\"},\n    {{\"\\337\\076\\074\", 3}, \"3z48\"},\n    {{\"\\375\\106\\362\", 3}, \"/Uby\"},\n    {{\"\\227\\301\\127\", 3}, \"l8FX\"},\n    {{\"\\340\\002\\234\", 3}, \"4AKc\"},\n    {{\"\\121\\064\\033\", 3}, \"UTQb\"},\n    {{\"\\157\\134\\143\", 3}, \"b1xj\"},\n    {{\"\\247\\055\\327\", 3}, \"py3X\"},\n    {{\"\\340\\142\\005\", 3}, \"4GIF\"},\n    {{\"\\060\\260\\143\", 3}, \"MLBj\"},\n    {{\"\\075\\203\\170\", 3}, \"PYN4\"},\n    {{\"\\143\\160\\016\", 3}, \"Y3AO\"},\n    {{\"\\313\\013\\063\", 3}, \"ywsz\"},\n    {{\"\\174\\236\\135\", 3}, \"fJ5d\"},\n    {{\"\\103\\047\\026\", 3}, \"QycW\"},\n    {{\"\\365\\005\\343\", 3}, \"9QXj\"},\n    {{\"\\271\\160\\223\", 3}, \"uXCT\"},\n    {{\"\\362\\255\\172\", 3}, \"8q16\"},\n    {{\"\\113\\012\\015\", 3}, \"SwoN\"},\n\n    // various lengths, generated by this python script:\n    //\n    // from std::string import lowercase as lc\n    // for i in range(27):\n    //   print '{ %2d, \"%s\",%s \"%s\" },' % (i, lc[:i], ' ' * (26-i),\n    //                                     lc[:i].encode('base64').strip())\n\n    {{\"\", 0}, {\"\", 0}},\n    {\"a\", \"YQ==\"},\n    {\"ab\", \"YWI=\"},\n    {\"abc\", \"YWJj\"},\n    {\"abcd\", \"YWJjZA==\"},\n    {\"abcde\", \"YWJjZGU=\"},\n    {\"abcdef\", \"YWJjZGVm\"},\n    {\"abcdefg\", \"YWJjZGVmZw==\"},\n    {\"abcdefgh\", \"YWJjZGVmZ2g=\"},\n    {\"abcdefghi\", \"YWJjZGVmZ2hp\"},\n    {\"abcdefghij\", \"YWJjZGVmZ2hpag==\"},\n    {\"abcdefghijk\", \"YWJjZGVmZ2hpams=\"},\n    {\"abcdefghijkl\", \"YWJjZGVmZ2hpamts\"},\n    {\"abcdefghijklm\", \"YWJjZGVmZ2hpamtsbQ==\"},\n    {\"abcdefghijklmn\", \"YWJjZGVmZ2hpamtsbW4=\"},\n    {\"abcdefghijklmno\", \"YWJjZGVmZ2hpamtsbW5v\"},\n    {\"abcdefghijklmnop\", \"YWJjZGVmZ2hpamtsbW5vcA==\"},\n    {\"abcdefghijklmnopq\", \"YWJjZGVmZ2hpamtsbW5vcHE=\"},\n    {\"abcdefghijklmnopqr\", \"YWJjZGVmZ2hpamtsbW5vcHFy\"},\n    {\"abcdefghijklmnopqrs\", \"YWJjZGVmZ2hpamtsbW5vcHFycw==\"},\n    {\"abcdefghijklmnopqrst\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3Q=\"},\n    {\"abcdefghijklmnopqrstu\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1\"},\n    {\"abcdefghijklmnopqrstuv\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg==\"},\n    {\"abcdefghijklmnopqrstuvw\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc=\"},\n    {\"abcdefghijklmnopqrstuvwx\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4\"},\n    {\"abcdefghijklmnopqrstuvwxy\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ==\"},\n    {\"abcdefghijklmnopqrstuvwxyz\", \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=\"},\n};\n\ntemplate <typename StringType>\nvoid TestEscapeAndUnescape() {\n  // Check the short strings; this tests the math (and boundaries)\n  for (const auto& tc : base64_tests) {\n    // Test plain base64.\n    StringType encoded(\"this junk should be ignored\");\n    absl::Base64Escape(tc.plaintext, &encoded);\n    EXPECT_EQ(encoded, tc.cyphertext);\n    EXPECT_EQ(absl::Base64Escape(tc.plaintext), tc.cyphertext);\n\n    StringType decoded(\"this junk should be ignored\");\n    EXPECT_TRUE(absl::Base64Unescape(encoded, &decoded));\n    EXPECT_EQ(decoded, tc.plaintext);\n\n    StringType websafe_with_padding(tc.cyphertext);\n    for (unsigned int c = 0; c < websafe_with_padding.size(); ++c) {\n      if ('+' == websafe_with_padding[c]) websafe_with_padding[c] = '-';\n      if ('/' == websafe_with_padding[c]) websafe_with_padding[c] = '_';\n      // Intentionally keeping padding aka '='.\n    }\n\n    // Test plain websafe (aka without padding).\n    StringType websafe(websafe_with_padding);\n    for (unsigned int c = 0; c < websafe.size(); ++c) {\n      if ('=' == websafe[c]) {\n        websafe.resize(c);\n        break;\n      }\n    }\n    encoded = \"this junk should be ignored\";\n    absl::WebSafeBase64Escape(tc.plaintext, &encoded);\n    EXPECT_EQ(encoded, websafe);\n    EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe);\n\n    decoded = \"this junk should be ignored\";\n    EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded));\n    EXPECT_EQ(decoded, tc.plaintext);\n  }\n\n  // Now try the long strings, this tests the streaming\n  for (const auto& tc : absl::strings_internal::base64_strings()) {\n    StringType buffer;\n    absl::WebSafeBase64Escape(tc.plaintext, &buffer);\n    EXPECT_EQ(tc.cyphertext, buffer);\n    EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), tc.cyphertext);\n  }\n\n  // Verify the behavior when decoding bad data\n  {\n    absl::string_view data_set[] = {\"ab-/\", absl::string_view(\"\\0bcd\", 4),\n                                    absl::string_view(\"abc.\\0\", 5)};\n    for (absl::string_view bad_data : data_set) {\n      StringType buf;\n      EXPECT_FALSE(absl::Base64Unescape(bad_data, &buf));\n      EXPECT_FALSE(absl::WebSafeBase64Unescape(bad_data, &buf));\n      EXPECT_TRUE(buf.empty());\n    }\n  }\n}\n\nTEST(Base64, EscapeAndUnescape) {\n  TestEscapeAndUnescape<std::string>();\n}\n\nTEST(Base64, Padding) {\n  // Padding is optional.\n  // '.' is an acceptable padding character, just like '='.\n  std::initializer_list<absl::string_view> good_padding = {\n    \"YQ\",\n    \"YQ==\",\n    \"YQ=.\",\n    \"YQ.=\",\n    \"YQ..\",\n  };\n  for (absl::string_view b64 : good_padding) {\n    std::string decoded;\n    EXPECT_TRUE(absl::Base64Unescape(b64, &decoded));\n    EXPECT_EQ(decoded, \"a\");\n    std::string websafe_decoded;\n    EXPECT_TRUE(absl::WebSafeBase64Unescape(b64, &websafe_decoded));\n    EXPECT_EQ(websafe_decoded, \"a\");\n  }\n  std::initializer_list<absl::string_view> bad_padding = {\n    \"YQ=\",\n    \"YQ.\",\n    \"YQ===\",\n    \"YQ==.\",\n    \"YQ=.=\",\n    \"YQ=..\",\n    \"YQ.==\",\n    \"YQ.=.\",\n    \"YQ..=\",\n    \"YQ...\",\n    \"YQ====\",\n    \"YQ....\",\n    \"YQ=====\",\n    \"YQ.....\",\n  };\n  for (absl::string_view b64 : bad_padding) {\n    std::string decoded;\n    EXPECT_FALSE(absl::Base64Unescape(b64, &decoded));\n    std::string websafe_decoded;\n    EXPECT_FALSE(absl::WebSafeBase64Unescape(b64, &websafe_decoded));\n  }\n}\n\nTEST(Base64, DISABLED_HugeData) {\n  const size_t kSize = size_t(3) * 1000 * 1000 * 1000;\n  static_assert(kSize % 3 == 0, \"kSize must be divisible by 3\");\n  const std::string huge(kSize, 'x');\n\n  std::string escaped = absl::Base64Escape(huge);\n\n  // Generates the string that should match a base64 encoded \"xxx...\" string.\n  // \"xxx\" in base64 is \"eHh4\".\n  std::string expected_encoding;\n  expected_encoding.reserve(kSize / 3 * 4);\n  for (size_t i = 0; i < kSize / 3; ++i) {\n    expected_encoding.append(\"eHh4\");\n  }\n  EXPECT_EQ(expected_encoding, escaped);\n\n  std::string unescaped;\n  EXPECT_TRUE(absl::Base64Unescape(escaped, &unescaped));\n  EXPECT_EQ(huge, unescaped);\n}\n\nTEST(Escaping, HexStringToBytesBackToHex) {\n  std::string bytes, hex;\n\n  constexpr absl::string_view kTestHexLower =  \"1c2f0032f40123456789abcdef\";\n  constexpr absl::string_view kTestHexUpper =  \"1C2F0032F40123456789ABCDEF\";\n  constexpr absl::string_view kTestBytes = absl::string_view(\n      \"\\x1c\\x2f\\x00\\x32\\xf4\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\", 13);\n\n  EXPECT_TRUE(absl::HexStringToBytes(kTestHexLower, &bytes));\n  EXPECT_EQ(bytes, kTestBytes);\n\n  EXPECT_TRUE(absl::HexStringToBytes(kTestHexUpper, &bytes));\n  EXPECT_EQ(bytes, kTestBytes);\n\n  hex = absl::BytesToHexString(kTestBytes);\n  EXPECT_EQ(hex, kTestHexLower);\n\n  // Same buffer.\n  // We do not care if this works since we do not promise it in the contract.\n  // The purpose of this test is to to see if the program will crash or if\n  // sanitizers will catch anything.\n  bytes = std::string(kTestHexUpper);\n  (void)absl::HexStringToBytes(bytes, &bytes);\n\n  // Length not a multiple of two.\n  EXPECT_FALSE(absl::HexStringToBytes(\"1c2f003\", &bytes));\n\n  // Not hex.\n  EXPECT_FALSE(absl::HexStringToBytes(\"1c2f00ft\", &bytes));\n\n  // Empty input.\n  bytes = \"abc\";\n  EXPECT_TRUE(absl::HexStringToBytes(\"\", &bytes));\n  EXPECT_EQ(\"\", bytes);  // Results in empty output.\n\n  // Ensure there is no sign extension bug on a signed char.\n  hex.assign(\"\\xC8\" \"b\", 2);\n  EXPECT_FALSE(absl::HexStringToBytes(hex, &bytes));\n}\n\nTEST(HexAndBack, HexStringToBytes_and_BytesToHexString) {\n  std::string hex_mixed = \"0123456789abcdefABCDEF\";\n  std::string bytes_expected = \"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\\xAB\\xCD\\xEF\";\n  std::string hex_only_lower = \"0123456789abcdefabcdef\";\n\n  std::string bytes_result = absl::HexStringToBytes(hex_mixed);\n  EXPECT_EQ(bytes_expected, bytes_result);\n\n  std::string prefix_valid = hex_mixed + \"?\";\n  std::string prefix_valid_result = absl::HexStringToBytes(\n      absl::string_view(prefix_valid.data(), prefix_valid.size() - 1));\n  EXPECT_EQ(bytes_expected, prefix_valid_result);\n\n  std::string infix_valid = \"?\" + hex_mixed + \"???\";\n  std::string infix_valid_result = absl::HexStringToBytes(\n      absl::string_view(infix_valid.data() + 1, hex_mixed.size()));\n  EXPECT_EQ(bytes_expected, infix_valid_result);\n\n  std::string hex_result = absl::BytesToHexString(bytes_expected);\n  EXPECT_EQ(hex_only_lower, hex_result);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/has_absl_stringify.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_\n#define ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_\n\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace strings_internal {\n\n// This is an empty class not intended to be used. It exists so that\n// `HasAbslStringify` can reference a universal class rather than needing to be\n// copied for each new sink.\nclass UnimplementedSink {\n public:\n  void Append(size_t count, char ch);\n\n  void Append(string_view v);\n\n  // Support `absl::Format(&sink, format, args...)`.\n  friend void AbslFormatFlush(UnimplementedSink* sink, absl::string_view v);\n};\n\n}  // namespace strings_internal\n\n// `HasAbslStringify<T>` detects if type `T` supports the `AbslStringify()`\n// customization point (see\n// https://abseil.io/docs/cpp/guides/format#abslstringify for the\n// documentation).\n//\n// Note that there are types that can be `StrCat`-ed that do not use the\n// `AbslStringify` customization point (for example, `int`).\n\ntemplate <typename T, typename = void>\nstruct HasAbslStringify : std::false_type {};\n\ntemplate <typename T>\nstruct HasAbslStringify<\n    T, std::enable_if_t<std::is_void<decltype(AbslStringify(\n           std::declval<strings_internal::UnimplementedSink&>(),\n           std::declval<const T&>()))>::value>> : std::true_type {};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_\n"
  },
  {
    "path": "absl/strings/has_absl_stringify_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/has_absl_stringify.h\"\n\n#include <optional>\n#include <string>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nstruct TypeWithoutAbslStringify {};\n\nstruct TypeWithAbslStringify {\n  template <typename Sink>\n  friend void AbslStringify(Sink&, const TypeWithAbslStringify&) {}\n};\n\nTEST(HasAbslStringifyTest, Works) {\n  EXPECT_FALSE(absl::HasAbslStringify<int>::value);\n  EXPECT_FALSE(absl::HasAbslStringify<std::string>::value);\n  EXPECT_FALSE(absl::HasAbslStringify<TypeWithoutAbslStringify>::value);\n  EXPECT_TRUE(absl::HasAbslStringify<TypeWithAbslStringify>::value);\n  EXPECT_FALSE(\n      absl::HasAbslStringify<std::optional<TypeWithAbslStringify>>::value);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/has_ostream_operator.h",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_\n#define ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_\n\n#include <ostream>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Detects if type `T` supports streaming to `std::ostream`s with `operator<<`.\n\ntemplate <typename T, typename = void>\nstruct HasOstreamOperator : std::false_type {};\n\ntemplate <typename T>\nstruct HasOstreamOperator<\n    T, std::enable_if_t<std::is_same<\n           std::ostream&, decltype(std::declval<std::ostream&>()\n                                   << std::declval<const T&>())>::value>>\n    : std::true_type {};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_\n"
  },
  {
    "path": "absl/strings/has_ostream_operator_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/has_ostream_operator.h\"\n\n#include <optional>\n#include <ostream>\n#include <string>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nstruct TypeWithoutOstreamOp {};\n\nstruct TypeWithOstreamOp {\n  friend std::ostream& operator<<(std::ostream& os, const TypeWithOstreamOp&) {\n    return os;\n  }\n};\n\nTEST(HasOstreamOperatorTest, Works) {\n  EXPECT_TRUE(absl::HasOstreamOperator<int>::value);\n  EXPECT_TRUE(absl::HasOstreamOperator<std::string>::value);\n  EXPECT_FALSE(absl::HasOstreamOperator<std::optional<int>>::value);\n  EXPECT_FALSE(absl::HasOstreamOperator<TypeWithoutOstreamOp>::value);\n  EXPECT_TRUE(absl::HasOstreamOperator<TypeWithOstreamOp>::value);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/append_and_overwrite.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_\n#define ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// An internal-only variant similar to `absl::StringResizeAndOverwrite()`\n// optimized for repeated appends to a string that uses exponential growth so\n// that the amortized complexity of increasing the string size by a small amount\n// is O(1), in contrast to O(str.size()) in the case of precise growth. Use of\n// this function is subtle; see https://reviews.llvm.org/D102727 to understand\n// the tradeoffs.\n//\n// Appends at most `append_n` characters to `str`, using the user-provided\n// operation `append_op` to modify the possibly indeterminate\n// contents. `append_op` must return the length of the buffer appended to `str`.\n//\n// Invalidates all iterators, pointers, and references into `str`, regardless\n// of whether reallocation occurs.\n//\n// `append_op(value_type* buf, size_t buf_size)` is allowed to write\n// `value_type{}` to `buf[buf_size]`, which facilitiates interoperation with\n// functions that write a trailing NUL.\ntemplate <typename T, typename Op>\nvoid StringAppendAndOverwrite(T& str, typename T::size_type append_n,\n                              Op append_op) {\n  if (ABSL_PREDICT_FALSE(append_n > str.max_size() - str.size())) {\n    ThrowStdLengthError(\"absl::strings_internal::StringAppendAndOverwrite\");\n  }\n\n  auto old_size = str.size();\n  auto resize = old_size + append_n;\n\n  if (resize > str.capacity()) {\n    // Make sure to always grow by at least a factor of 2x.\n    const auto min_growth = str.capacity();\n    if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() - min_growth)) {\n      str.reserve(str.max_size());\n    } else if (resize < str.capacity() + min_growth) {\n      str.reserve(str.capacity() + min_growth);\n    }\n  }\n\n  // Avoid calling StringResizeAndOverwrite() here since it does an MSAN\n  // verification on the entire string. StringResizeAndOverwriteImpl() is\n  // StringResizeAndOverwrite() without the MSAN verification.\n  StringResizeAndOverwriteImpl(\n      str, resize,\n      [old_size, append_n, do_append = std::move(append_op)](\n          typename T::value_type* data_ptr, typename T::size_type) mutable {\n        auto num_appended =\n            std::move(do_append)(data_ptr + old_size, append_n);\n        ABSL_HARDENING_ASSERT(num_appended >= 0 && num_appended <= append_n);\n        return old_size + num_appended;\n      });\n\n#if defined(ABSL_HAVE_MEMORY_SANITIZER)\n  // Only check the region appended to. Checking the entire string would cause\n  // pathological quadratic verfication on repeated small appends.\n  __msan_check_mem_is_initialized(str.data() + old_size, str.size() - old_size);\n#endif\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n\n#endif  // ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_\n"
  },
  {
    "path": "absl/strings/internal/append_and_overwrite_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/append_and_overwrite.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/log/absl_check.h\"\n\nnamespace {\n\nstruct AppendAndOverwriteParam {\n  size_t initial_size;\n  size_t append_capacity;\n  size_t append_size;\n};\n\nusing StringAppendAndOverwriteTest =\n    ::testing::TestWithParam<AppendAndOverwriteParam>;\n\nTEST_P(StringAppendAndOverwriteTest, StringAppendAndOverwrite) {\n  const auto& param = GetParam();\n  std::string s(param.initial_size, 'a');\n  absl::strings_internal::StringAppendAndOverwrite(\n      s, param.append_capacity, [&](char* p, size_t n) {\n        ABSL_CHECK_EQ(n, param.append_capacity);\n        std::fill_n(p, param.append_size, 'b');\n        p[param.append_size] = '\\0';\n        return param.append_size;\n      });\n\n  std::string expected =\n      std::string(param.initial_size, 'a') +\n      std::string(param.append_size,\n                  'b');\n\n  EXPECT_EQ(s, expected);\n  EXPECT_EQ(s.c_str()[s.size()], '\\0');\n}\n\n// clang-format off\nINSTANTIATE_TEST_SUITE_P(StringAppendAndOverwriteTestSuite,\n                         StringAppendAndOverwriteTest,\n                         ::testing::ValuesIn<AppendAndOverwriteParam>({\n                             {0,  10,  5},\n                             {10, 10, 10},\n                             {10, 15, 15},\n                             {10, 20, 15},\n                             {10, 40, 40},\n                             {10, 50, 40},\n                             {30, 35, 35},\n                             {30, 45, 35},\n                             {10, 30, 15},\n                         }));\n// clang-format on\n\nTEST(StringAppendAndOverwrite, AmortizedComplexity) {\n  std::string str;\n  std::string expected;\n  size_t prev_cap = str.capacity();\n  int cap_increase_count = 0;\n  for (int i = 0; i < 1000; ++i) {\n    char c = static_cast<char>('a' + (i % 26));\n    absl::strings_internal::StringAppendAndOverwrite(\n        str, 1, [c](char* buf, size_t buf_size) {\n          ABSL_CHECK_EQ(buf_size, 1);\n          buf[0] = c;\n          return size_t{1};\n        });\n    expected.push_back(c);\n    EXPECT_EQ(str, expected);\n    size_t new_cap = str.capacity();\n    if (new_cap > prev_cap) {\n      ++cap_increase_count;\n    }\n    prev_cap = new_cap;\n  }\n  EXPECT_LT(cap_increase_count, 50);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/charconv_bigint.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/charconv_bigint.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <string>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nnamespace {\n\n// Table containing some large powers of 5, for fast computation.\n\n// Constant step size for entries in the kLargePowersOfFive table.  Each entry\n// is larger than the previous entry by a factor of 5**kLargePowerOfFiveStep\n// (or 5**27).\n//\n// In other words, the Nth entry in the table is 5**(27*N).\n//\n// 5**27 is the largest power of 5 that fits in 64 bits.\nconstexpr int kLargePowerOfFiveStep = 27;\n\n// The largest legal index into the kLargePowersOfFive table.\n//\n// In other words, the largest precomputed power of 5 is 5**(27*20).\nconstexpr int kLargestPowerOfFiveIndex = 20;\n\n// Table of powers of (5**27), up to (5**27)**20 == 5**540.\n//\n// Used to generate large powers of 5 while limiting the number of repeated\n// multiplications required.\n//\n// clang-format off\nconst uint32_t kLargePowersOfFive[] = {\n// 5**27 (i=1), start=0, end=2\n  0xfa10079dU, 0x6765c793U,\n// 5**54 (i=2), start=2, end=6\n  0x97d9f649U, 0x6664242dU, 0x29939b14U, 0x29c30f10U,\n// 5**81 (i=3), start=6, end=12\n  0xc4f809c5U, 0x7bf3f22aU, 0x67bdae34U, 0xad340517U, 0x369d1b5fU, 0x10de1593U,\n// 5**108 (i=4), start=12, end=20\n  0x92b260d1U, 0x9efff7c7U, 0x81de0ec6U, 0xaeba5d56U, 0x410664a4U, 0x4f40737aU,\n  0x20d3846fU, 0x06d00f73U,\n// 5**135 (i=5), start=20, end=30\n  0xff1b172dU, 0x13a1d71cU, 0xefa07617U, 0x7f682d3dU, 0xff8c90c0U, 0x3f0131e7U,\n  0x3fdcb9feU, 0x917b0177U, 0x16c407a7U, 0x02c06b9dU,\n// 5**162 (i=6), start=30, end=42\n  0x960f7199U, 0x056667ecU, 0xe07aefd8U, 0x80f2b9ccU, 0x8273f5e3U, 0xeb9a214aU,\n  0x40b38005U, 0x0e477ad4U, 0x277d08e6U, 0xfa28b11eU, 0xd3f7d784U, 0x011c835bU,\n// 5**189 (i=7), start=42, end=56\n  0xf723d9d5U, 0x3282d3f3U, 0xe00857d1U, 0x69659d25U, 0x2cf117cfU, 0x24da6d07U,\n  0x954d1417U, 0x3e5d8cedU, 0x7a8bb766U, 0xfd785ae6U, 0x645436d2U, 0x40c78b34U,\n  0x94151217U, 0x0072e9f7U,\n// 5**216 (i=8), start=56, end=72\n  0x2b416aa1U, 0x7893c5a7U, 0xe37dc6d4U, 0x2bad2beaU, 0xf0fc846cU, 0x7575ae4bU,\n  0x62587b14U, 0x83b67a34U, 0x02110cdbU, 0xf7992f55U, 0x00deb022U, 0xa4a23becU,\n  0x8af5c5cdU, 0xb85b654fU, 0x818df38bU, 0x002e69d2U,\n// 5**243 (i=9), start=72, end=90\n  0x3518cbbdU, 0x20b0c15fU, 0x38756c2fU, 0xfb5dc3ddU, 0x22ad2d94U, 0xbf35a952U,\n  0xa699192aU, 0x9a613326U, 0xad2a9cedU, 0xd7f48968U, 0xe87dfb54U, 0xc8f05db6U,\n  0x5ef67531U, 0x31c1ab49U, 0xe202ac9fU, 0x9b2957b5U, 0xa143f6d3U, 0x0012bf07U,\n// 5**270 (i=10), start=90, end=110\n  0x8b971de9U, 0x21aba2e1U, 0x63944362U, 0x57172336U, 0xd9544225U, 0xfb534166U,\n  0x08c563eeU, 0x14640ee2U, 0x24e40d31U, 0x02b06537U, 0x03887f14U, 0x0285e533U,\n  0xb744ef26U, 0x8be3a6c4U, 0x266979b4U, 0x6761ece2U, 0xd9cb39e4U, 0xe67de319U,\n  0x0d39e796U, 0x00079250U,\n// 5**297 (i=11), start=110, end=132\n  0x260eb6e5U, 0xf414a796U, 0xee1a7491U, 0xdb9368ebU, 0xf50c105bU, 0x59157750U,\n  0x9ed2fb5cU, 0xf6e56d8bU, 0xeaee8d23U, 0x0f319f75U, 0x2aa134d6U, 0xac2908e9U,\n  0xd4413298U, 0x02f02a55U, 0x989d5a7aU, 0x70dde184U, 0xba8040a7U, 0x03200981U,\n  0xbe03b11cU, 0x3c1c2a18U, 0xd60427a1U, 0x00030ee0U,\n// 5**324 (i=12), start=132, end=156\n  0xce566d71U, 0xf1c4aa25U, 0x4e93ca53U, 0xa72283d0U, 0x551a73eaU, 0x3d0538e2U,\n  0x8da4303fU, 0x6a58de60U, 0x0e660221U, 0x49cf61a6U, 0x8d058fc1U, 0xb9d1a14cU,\n  0x4bab157dU, 0xc85c6932U, 0x518c8b9eU, 0x9b92b8d0U, 0x0d8a0e21U, 0xbd855df9U,\n  0xb3ea59a1U, 0x8da29289U, 0x4584d506U, 0x3752d80fU, 0xb72569c6U, 0x00013c33U,\n// 5**351 (i=13), start=156, end=182\n  0x190f354dU, 0x83695cfeU, 0xe5a4d0c7U, 0xb60fb7e8U, 0xee5bbcc4U, 0xb922054cU,\n  0xbb4f0d85U, 0x48394028U, 0x1d8957dbU, 0x0d7edb14U, 0x4ecc7587U, 0x505e9e02U,\n  0x4c87f36bU, 0x99e66bd6U, 0x44b9ed35U, 0x753037d4U, 0xe5fe5f27U, 0x2742c203U,\n  0x13b2ed2bU, 0xdc525d2cU, 0xe6fde59aU, 0x77ffb18fU, 0x13c5752cU, 0x08a84bccU,\n  0x859a4940U, 0x00007fb6U,\n// 5**378 (i=14), start=182, end=210\n  0x4f98cb39U, 0xa60edbbcU, 0x83b5872eU, 0xa501acffU, 0x9cc76f78U, 0xbadd4c73U,\n  0x43e989faU, 0xca7acf80U, 0x2e0c824fU, 0xb19f4ffcU, 0x092fd81cU, 0xe4eb645bU,\n  0xa1ff84c2U, 0x8a5a83baU, 0xa8a1fae9U, 0x1db43609U, 0xb0fed50bU, 0x0dd7d2bdU,\n  0x7d7accd8U, 0x91fa640fU, 0x37dcc6c5U, 0x1c417fd5U, 0xe4d462adU, 0xe8a43399U,\n  0x131bf9a5U, 0x8df54d29U, 0x36547dc1U, 0x00003395U,\n// 5**405 (i=15), start=210, end=240\n  0x5bd330f5U, 0x77d21967U, 0x1ac481b7U, 0x6be2f7ceU, 0x7f4792a9U, 0xe84c2c52U,\n  0x84592228U, 0x9dcaf829U, 0xdab44ce1U, 0x3d0c311bU, 0x532e297dU, 0x4704e8b4U,\n  0x9cdc32beU, 0x41e64d9dU, 0x7717bea1U, 0xa824c00dU, 0x08f50b27U, 0x0f198d77U,\n  0x49bbfdf0U, 0x025c6c69U, 0xd4e55cd3U, 0xf083602bU, 0xb9f0fecdU, 0xc0864aeaU,\n  0x9cb98681U, 0xaaf620e9U, 0xacb6df30U, 0x4faafe66U, 0x8af13c3bU, 0x000014d5U,\n// 5**432 (i=16), start=240, end=272\n  0x682bb941U, 0x89a9f297U, 0xcba75d7bU, 0x404217b1U, 0xb4e519e9U, 0xa1bc162bU,\n  0xf7f5910aU, 0x98715af5U, 0x2ff53e57U, 0xe3ef118cU, 0x490c4543U, 0xbc9b1734U,\n  0x2affbe4dU, 0x4cedcb4cU, 0xfb14e99eU, 0x35e34212U, 0xece39c24U, 0x07673ab3U,\n  0xe73115ddU, 0xd15d38e7U, 0x093eed3bU, 0xf8e7eac5U, 0x78a8cc80U, 0x25227aacU,\n  0x3f590551U, 0x413da1cbU, 0xdf643a55U, 0xab65ad44U, 0xd70b23d7U, 0xc672cd76U,\n  0x3364ea62U, 0x0000086aU,\n// 5**459 (i=17), start=272, end=306\n  0x22f163ddU, 0x23cf07acU, 0xbe2af6c2U, 0xf412f6f6U, 0xc3ff541eU, 0x6eeaf7deU,\n  0xa47047e0U, 0x408cda92U, 0x0f0eeb08U, 0x56deba9dU, 0xcfc6b090U, 0x8bbbdf04U,\n  0x3933cdb3U, 0x9e7bb67dU, 0x9f297035U, 0x38946244U, 0xee1d37bbU, 0xde898174U,\n  0x63f3559dU, 0x705b72fbU, 0x138d27d9U, 0xf8603a78U, 0x735eec44U, 0xe30987d5U,\n  0xc6d38070U, 0x9cfe548eU, 0x9ff01422U, 0x7c564aa8U, 0x91cc60baU, 0xcbc3565dU,\n  0x7550a50bU, 0x6909aeadU, 0x13234c45U, 0x00000366U,\n// 5**486 (i=18), start=306, end=342\n  0x17954989U, 0x3a7d7709U, 0x98042de5U, 0xa9011443U, 0x45e723c2U, 0x269ffd6fU,\n  0x58852a46U, 0xaaa1042aU, 0x2eee8153U, 0xb2b6c39eU, 0xaf845b65U, 0xf6c365d7U,\n  0xe4cffb2bU, 0xc840e90cU, 0xabea8abbU, 0x5c58f8d2U, 0x5c19fa3aU, 0x4670910aU,\n  0x4449f21cU, 0xefa645b3U, 0xcc427decU, 0x083c3d73U, 0x467cb413U, 0x6fe10ae4U,\n  0x3caffc72U, 0x9f8da55eU, 0x5e5c8ea7U, 0x490594bbU, 0xf0871b0bU, 0xdd89816cU,\n  0x8e931df8U, 0xe85ce1c9U, 0xcca090a5U, 0x575fa16bU, 0x6b9f106cU, 0x0000015fU,\n// 5**513 (i=19), start=342, end=380\n  0xee20d805U, 0x57bc3c07U, 0xcdea624eU, 0xd3f0f52dU, 0x9924b4f4U, 0xcf968640U,\n  0x61d41962U, 0xe87fb464U, 0xeaaf51c7U, 0x564c8b60U, 0xccda4028U, 0x529428bbU,\n  0x313a1fa8U, 0x96bd0f94U, 0x7a82ebaaU, 0xad99e7e9U, 0xf2668cd4U, 0xbe33a45eU,\n  0xfd0db669U, 0x87ee369fU, 0xd3ec20edU, 0x9c4d7db7U, 0xdedcf0d8U, 0x7cd2ca64U,\n  0xe25a6577U, 0x61003fd4U, 0xe56f54ccU, 0x10b7c748U, 0x40526e5eU, 0x7300ae87U,\n  0x5c439261U, 0x2c0ff469U, 0xbf723f12U, 0xb2379b61U, 0xbf59b4f5U, 0xc91b1c3fU,\n  0xf0046d27U, 0x0000008dU,\n// 5**540 (i=20), start=380, end=420\n  0x525c9e11U, 0xf4e0eb41U, 0xebb2895dU, 0x5da512f9U, 0x7d9b29d4U, 0x452f4edcU,\n  0x0b90bc37U, 0x341777cbU, 0x63d269afU, 0x1da77929U, 0x0a5c1826U, 0x77991898U,\n  0x5aeddf86U, 0xf853a877U, 0x538c31ccU, 0xe84896daU, 0xb7a0010bU, 0x17ef4de5U,\n  0xa52a2adeU, 0x029fd81cU, 0x987ce701U, 0x27fefd77U, 0xdb46c66fU, 0x5d301900U,\n  0x496998c0U, 0xbb6598b9U, 0x5eebb607U, 0xe547354aU, 0xdf4a2f7eU, 0xf06c4955U,\n  0x96242ffaU, 0x1775fb27U, 0xbecc58ceU, 0xebf2a53bU, 0x3eaad82aU, 0xf41137baU,\n  0x573e6fbaU, 0xfb4866b8U, 0x54002148U, 0x00000039U,\n};\n// clang-format on\n\n// Returns a pointer to the big integer data for (5**27)**i.  i must be\n// between 1 and 20, inclusive.\nconst uint32_t* LargePowerOfFiveData(int i) {\n  return kLargePowersOfFive + i * (i - 1);\n}\n\n// Returns the size of the big integer data for (5**27)**i, in words.  i must be\n// between 1 and 20, inclusive.\nint LargePowerOfFiveSize(int i) { return 2 * i; }\n}  // namespace\n\nABSL_DLL const uint32_t kFiveToNth[14] = {\n    1,     5,      25,      125,     625,      3125,      15625,\n    78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,\n};\n\nABSL_DLL const uint32_t kTenToNth[10] = {\n    1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,\n};\n\ntemplate <int max_words>\nint BigUnsigned<max_words>::ReadFloatMantissa(const ParsedFloat& fp,\n                                              int significant_digits) {\n  SetToZero();\n  assert(fp.type == FloatType::kNumber);\n\n  if (fp.subrange_begin == nullptr) {\n    // We already exactly parsed the mantissa, so no more work is necessary.\n    words_[0] = fp.mantissa & 0xffffffffu;\n    words_[1] = fp.mantissa >> 32;\n    if (words_[1]) {\n      size_ = 2;\n    } else if (words_[0]) {\n      size_ = 1;\n    }\n    return fp.exponent;\n  }\n  int exponent_adjust =\n      ReadDigits(fp.subrange_begin, fp.subrange_end, significant_digits);\n  return fp.literal_exponent + exponent_adjust;\n}\n\ntemplate <int max_words>\nint BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,\n                                       int significant_digits) {\n  assert(significant_digits <= Digits10() + 1);\n  SetToZero();\n\n  bool after_decimal_point = false;\n  // Discard any leading zeroes before the decimal point\n  while (begin < end && *begin == '0') {\n    ++begin;\n  }\n  int dropped_digits = 0;\n  // Discard any trailing zeroes.  These may or may not be after the decimal\n  // point.\n  while (begin < end && *std::prev(end) == '0') {\n    --end;\n    ++dropped_digits;\n  }\n  if (begin < end && *std::prev(end) == '.') {\n    // If the string ends in '.', either before or after dropping zeroes, then\n    // drop the decimal point and look for more digits to drop.\n    dropped_digits = 0;\n    --end;\n    while (begin < end && *std::prev(end) == '0') {\n      --end;\n      ++dropped_digits;\n    }\n  } else if (dropped_digits) {\n    // We dropped digits, and aren't sure if they're before or after the decimal\n    // point.  Figure that out now.\n    const char* dp = std::find(begin, end, '.');\n    if (dp != end) {\n      // The dropped trailing digits were after the decimal point, so don't\n      // count them.\n      dropped_digits = 0;\n    }\n  }\n  // Any non-fraction digits we dropped need to be accounted for in our exponent\n  // adjustment.\n  int exponent_adjust = dropped_digits;\n\n  uint32_t queued = 0;\n  int digits_queued = 0;\n  for (; begin != end && significant_digits > 0; ++begin) {\n    if (*begin == '.') {\n      after_decimal_point = true;\n      continue;\n    }\n    if (after_decimal_point) {\n      // For each fractional digit we emit in our parsed integer, adjust our\n      // decimal exponent to compensate.\n      --exponent_adjust;\n    }\n    char digit = (*begin - '0');\n    --significant_digits;\n    if (significant_digits == 0 && std::next(begin) != end &&\n        (digit == 0 || digit == 5)) {\n      // If this is the very last significant digit, but insignificant digits\n      // remain, we know that the last of those remaining significant digits is\n      // nonzero.  (If it wasn't, we would have stripped it before we got here.)\n      // So if this final digit is a 0 or 5, adjust it upward by 1.\n      //\n      // This adjustment is what allows incredibly large mantissas ending in\n      // 500000...000000000001 to correctly round up, rather than to nearest.\n      ++digit;\n    }\n    queued = 10 * queued + static_cast<uint32_t>(digit);\n    ++digits_queued;\n    if (digits_queued == kMaxSmallPowerOfTen) {\n      MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]);\n      AddWithCarry(0, queued);\n      queued = digits_queued = 0;\n    }\n  }\n  // Encode any remaining digits.\n  if (digits_queued) {\n    MultiplyBy(kTenToNth[digits_queued]);\n    AddWithCarry(0, queued);\n  }\n\n  // If any insignificant digits remain, we will drop them.  But if we have not\n  // yet read the decimal point, then we have to adjust the exponent to account\n  // for the dropped digits.\n  if (begin < end && !after_decimal_point) {\n    // This call to std::find will result in a pointer either to the decimal\n    // point, or to the end of our buffer if there was none.\n    //\n    // Either way, [begin, decimal_point) will contain the set of dropped digits\n    // that require an exponent adjustment.\n    const char* decimal_point = std::find(begin, end, '.');\n    exponent_adjust += static_cast<int>(decimal_point - begin);\n  }\n  return exponent_adjust;\n}\n\ntemplate <int max_words>\n/* static */ BigUnsigned<max_words> BigUnsigned<max_words>::FiveToTheNth(\n    int n) {\n  BigUnsigned answer(1u);\n\n  // Seed from the table of large powers, if possible.\n  bool first_pass = true;\n  while (n >= kLargePowerOfFiveStep) {\n    int big_power =\n        std::min(n / kLargePowerOfFiveStep, kLargestPowerOfFiveIndex);\n    if (first_pass) {\n      // just copy, rather than multiplying by 1\n      std::copy_n(LargePowerOfFiveData(big_power),\n                  LargePowerOfFiveSize(big_power), answer.words_);\n      answer.size_ = LargePowerOfFiveSize(big_power);\n      first_pass = false;\n    } else {\n      answer.MultiplyBy(LargePowerOfFiveSize(big_power),\n                        LargePowerOfFiveData(big_power));\n    }\n    n -= kLargePowerOfFiveStep * big_power;\n  }\n  answer.MultiplyByFiveToTheNth(n);\n  return answer;\n}\n\ntemplate <int max_words>\nvoid BigUnsigned<max_words>::MultiplyStep(int original_size,\n                                          const uint32_t* other_words,\n                                          int other_size, int step) {\n  int this_i = std::min(original_size - 1, step);\n  int other_i = step - this_i;\n\n  uint64_t this_word = 0;\n  uint64_t carry = 0;\n  for (; this_i >= 0 && other_i < other_size; --this_i, ++other_i) {\n    uint64_t product = words_[this_i];\n    product *= other_words[other_i];\n    this_word += product;\n    carry += (this_word >> 32);\n    this_word &= 0xffffffff;\n  }\n  AddWithCarry(step + 1, carry);\n  words_[step] = this_word & 0xffffffff;\n  if (this_word > 0 && size_ <= step) {\n    size_ = step + 1;\n  }\n}\n\ntemplate <int max_words>\nstd::string BigUnsigned<max_words>::ToString() const {\n  BigUnsigned<max_words> copy = *this;\n  std::string result;\n  // Build result in reverse order\n  while (copy.size() > 0) {\n    uint32_t next_digit = copy.DivMod<10>();\n    result.push_back('0' + static_cast<char>(next_digit));\n  }\n  if (result.empty()) {\n    result.push_back('0');\n  }\n  std::reverse(result.begin(), result.end());\n  return result;\n}\n\ntemplate class BigUnsigned<4>;\ntemplate class BigUnsigned<84>;\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/charconv_bigint.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_\n#define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_\n\n#include <algorithm>\n#include <cstdint>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/internal/charconv_parse.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// The largest power that 5 that can be raised to, and still fit in a uint32_t.\nconstexpr int kMaxSmallPowerOfFive = 13;\n// The largest power that 10 that can be raised to, and still fit in a uint32_t.\nconstexpr int kMaxSmallPowerOfTen = 9;\n\nABSL_DLL extern const uint32_t\n    kFiveToNth[kMaxSmallPowerOfFive + 1];\nABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];\n\n// Large, fixed-width unsigned integer.\n//\n// Exact rounding for decimal-to-binary floating point conversion requires very\n// large integer math, but a design goal of absl::from_chars is to avoid\n// allocating memory.  The integer precision needed for decimal-to-binary\n// conversions is large but bounded, so a huge fixed-width integer class\n// suffices.\n//\n// This is an intentionally limited big integer class.  Only needed operations\n// are implemented.  All storage lives in an array data member, and all\n// arithmetic is done in-place, to avoid requiring separate storage for operand\n// and result.\n//\n// This is an internal class.  Some methods live in the .cc file, and are\n// instantiated only for the values of max_words we need.\ntemplate <int max_words>\nclass BigUnsigned {\n public:\n  static_assert(max_words == 4 || max_words == 84,\n                \"unsupported max_words value\");\n\n  BigUnsigned() : size_(0), words_{} {}\n  explicit constexpr BigUnsigned(uint64_t v)\n      : size_((v >> 32) ? 2 : v ? 1 : 0),\n        words_{static_cast<uint32_t>(v & 0xffffffffu),\n               static_cast<uint32_t>(v >> 32)} {}\n\n  // Constructs a BigUnsigned from the given string_view containing a decimal\n  // value.  If the input string is not a decimal integer, constructs a 0\n  // instead.\n  explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {\n    // Check for valid input, returning a 0 otherwise.  This is reasonable\n    // behavior only because this constructor is for unit tests.\n    if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||\n        sv.empty()) {\n      return;\n    }\n    int exponent_adjust =\n        ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);\n    if (exponent_adjust > 0) {\n      MultiplyByTenToTheNth(exponent_adjust);\n    }\n  }\n\n  // Loads the mantissa value of a previously-parsed float.\n  //\n  // Returns the associated decimal exponent.  The value of the parsed float is\n  // exactly *this * 10**exponent.\n  int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);\n\n  // Returns the number of decimal digits of precision this type provides.  All\n  // numbers with this many decimal digits or fewer are representable by this\n  // type.\n  //\n  // Analogous to std::numeric_limits<BigUnsigned>::digits10.\n  static constexpr int Digits10() {\n    // 9975007/1035508 is very slightly less than log10(2**32).\n    return static_cast<uint64_t>(max_words) * 9975007 / 1035508;\n  }\n\n  // Shifts left by the given number of bits.\n  void ShiftLeft(int count) {\n    if (count > 0) {\n      const int word_shift = count / 32;\n      if (word_shift >= max_words) {\n        SetToZero();\n        return;\n      }\n      size_ = (std::min)(size_ + word_shift, max_words);\n      count %= 32;\n      if (count == 0) {\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=warray-bounds\n// shows a lot of bogus -Warray-bounds warnings under GCC.\n// This is not the only one in Abseil.\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(14, 0)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Warray-bounds\"\n#endif\n        std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(14, 0)\n#pragma GCC diagnostic pop\n#endif\n      } else {\n        for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {\n          words_[i] = (words_[i - word_shift] << count) |\n                      (words_[i - word_shift - 1] >> (32 - count));\n        }\n        words_[word_shift] = words_[0] << count;\n        // Grow size_ if necessary.\n        if (size_ < max_words && words_[size_]) {\n          ++size_;\n        }\n      }\n      std::fill_n(words_, word_shift, 0u);\n    }\n  }\n\n\n  // Multiplies by v in-place.\n  void MultiplyBy(uint32_t v) {\n    if (size_ == 0 || v == 1) {\n      return;\n    }\n    if (v == 0) {\n      SetToZero();\n      return;\n    }\n    const uint64_t factor = v;\n    uint64_t window = 0;\n    for (int i = 0; i < size_; ++i) {\n      window += factor * words_[i];\n      words_[i] = window & 0xffffffff;\n      window >>= 32;\n    }\n    // If carry bits remain and there's space for them, grow size_.\n    if (window && size_ < max_words) {\n      words_[size_] = window & 0xffffffff;\n      ++size_;\n    }\n  }\n\n  void MultiplyBy(uint64_t v) {\n    uint32_t words[2];\n    words[0] = static_cast<uint32_t>(v);\n    words[1] = static_cast<uint32_t>(v >> 32);\n    if (words[1] == 0) {\n      MultiplyBy(words[0]);\n    } else {\n      MultiplyBy(2, words);\n    }\n  }\n\n  // Multiplies in place by 5 to the power of n.  n must be non-negative.\n  void MultiplyByFiveToTheNth(int n) {\n    while (n >= kMaxSmallPowerOfFive) {\n      MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);\n      n -= kMaxSmallPowerOfFive;\n    }\n    if (n > 0) {\n      MultiplyBy(kFiveToNth[n]);\n    }\n  }\n\n  // Multiplies in place by 10 to the power of n.  n must be non-negative.\n  void MultiplyByTenToTheNth(int n) {\n    if (n > kMaxSmallPowerOfTen) {\n      // For large n, raise to a power of 5, then shift left by the same amount.\n      // (10**n == 5**n * 2**n.)  This requires fewer multiplications overall.\n      MultiplyByFiveToTheNth(n);\n      ShiftLeft(n);\n    } else if (n > 0) {\n      // We can do this more quickly for very small N by using a single\n      // multiplication.\n      MultiplyBy(kTenToNth[n]);\n    }\n  }\n\n  // Returns the value of 5**n, for non-negative n.  This implementation uses\n  // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling\n  // MultiplyByFiveToTheNth().\n  static BigUnsigned FiveToTheNth(int n);\n\n  // Multiplies by another BigUnsigned, in-place.\n  template <int M>\n  void MultiplyBy(const BigUnsigned<M>& other) {\n    MultiplyBy(other.size(), other.words());\n  }\n\n  void SetToZero() {\n    std::fill_n(words_, size_, 0u);\n    size_ = 0;\n  }\n\n  // Returns the value of the nth word of this BigUnsigned.  This is\n  // range-checked, and returns 0 on out-of-bounds accesses.\n  uint32_t GetWord(int index) const {\n    if (index < 0 || index >= size_) {\n      return 0;\n    }\n    return words_[index];\n  }\n\n  // Returns this integer as a decimal string.  This is not used in the decimal-\n  // to-binary conversion; it is intended to aid in testing.\n  std::string ToString() const;\n\n  int size() const { return size_; }\n  const uint32_t* words() const { return words_; }\n\n private:\n  // Reads the number between [begin, end), possibly containing a decimal point,\n  // into this BigUnsigned.\n  //\n  // Callers are required to ensure [begin, end) contains a valid number, with\n  // one or more decimal digits and at most one decimal point.  This routine\n  // will behave unpredictably if these preconditions are not met.\n  //\n  // Only the first `significant_digits` digits are read.  Digits beyond this\n  // limit are \"sticky\": If the final significant digit is 0 or 5, and if any\n  // dropped digit is nonzero, then that final significant digit is adjusted up\n  // to 1 or 6.  This adjustment allows for precise rounding.\n  //\n  // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to\n  // account for the decimal point and for dropped significant digits.  After\n  // this function returns,\n  //   actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.\n  int ReadDigits(const char* begin, const char* end, int significant_digits);\n\n  // Performs a step of big integer multiplication.  This computes the full\n  // (64-bit-wide) values that should be added at the given index (step), and\n  // adds to that location in-place.\n  //\n  // Because our math all occurs in place, we must multiply starting from the\n  // highest word working downward.  (This is a bit more expensive due to the\n  // extra carries involved.)\n  //\n  // This must be called in steps, for each word to be calculated, starting from\n  // the high end and working down to 0.  The first value of `step` should be\n  //   `std::min(original_size + other.size_ - 2, max_words - 1)`.\n  // The reason for this expression is that multiplying the i'th word from one\n  // multiplicand and the j'th word of another multiplicand creates a\n  // two-word-wide value to be stored at the (i+j)'th element.  The highest\n  // word indices we will access are `original_size - 1` from this object, and\n  // `other.size_ - 1` from our operand.  Therefore,\n  // `original_size + other.size_ - 2` is the first step we should calculate,\n  // but limited on an upper bound by max_words.\n\n  // Working from high-to-low ensures that we do not overwrite the portions of\n  // the initial value of *this which are still needed for later steps.\n  //\n  // Once called with step == 0, *this contains the result of the\n  // multiplication.\n  //\n  // `original_size` is the size_ of *this before the first call to\n  // MultiplyStep().  `other_words` and `other_size` are the contents of our\n  // operand.  `step` is the step to perform, as described above.\n  void MultiplyStep(int original_size, const uint32_t* other_words,\n                    int other_size, int step);\n\n  void MultiplyBy(int other_size, const uint32_t* other_words) {\n    const int original_size = size_;\n    const int first_step =\n        (std::min)(original_size + other_size - 2, max_words - 1);\n    for (int step = first_step; step >= 0; --step) {\n      MultiplyStep(original_size, other_words, other_size, step);\n    }\n  }\n\n  // Adds a 32-bit value to the index'th word, with carry.\n  void AddWithCarry(int index, uint32_t value) {\n    if (value) {\n      while (index < max_words && value > 0) {\n        words_[index] += value;\n        // carry if we overflowed in this word:\n        if (value > words_[index]) {\n          value = 1;\n          ++index;\n        } else {\n          value = 0;\n        }\n      }\n      size_ = (std::min)(max_words, (std::max)(index + 1, size_));\n    }\n  }\n\n  void AddWithCarry(int index, uint64_t value) {\n    if (value && index < max_words) {\n      uint32_t high = value >> 32;\n      uint32_t low = value & 0xffffffff;\n      words_[index] += low;\n      if (words_[index] < low) {\n        ++high;\n        if (high == 0) {\n          // Carry from the low word caused our high word to overflow.\n          // Short circuit here to do the right thing.\n          AddWithCarry(index + 2, static_cast<uint32_t>(1));\n          return;\n        }\n      }\n      if (high > 0) {\n        AddWithCarry(index + 1, high);\n      } else {\n        // Normally 32-bit AddWithCarry() sets size_, but since we don't call\n        // it when `high` is 0, do it ourselves here.\n        size_ = (std::min)(max_words, (std::max)(index + 1, size_));\n      }\n    }\n  }\n\n  // Divide this in place by a constant divisor.  Returns the remainder of the\n  // division.\n  template <uint32_t divisor>\n  uint32_t DivMod() {\n    uint64_t accumulator = 0;\n    for (int i = size_ - 1; i >= 0; --i) {\n      accumulator <<= 32;\n      accumulator += words_[i];\n      // accumulator / divisor will never overflow an int32_t in this loop\n      words_[i] = static_cast<uint32_t>(accumulator / divisor);\n      accumulator = accumulator % divisor;\n    }\n    while (size_ > 0 && words_[size_ - 1] == 0) {\n      --size_;\n    }\n    return static_cast<uint32_t>(accumulator);\n  }\n\n  // The number of elements in words_ that may carry significant values.\n  // All elements beyond this point are 0.\n  //\n  // When size_ is 0, this BigUnsigned stores the value 0.\n  // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is\n  // nonzero.  This can occur due to overflow truncation.\n  // In particular, x.size_ != y.size_ does *not* imply x != y.\n  int size_;\n  uint32_t words_[max_words];\n};\n\n// Compares two big integer instances.\n//\n// Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.\ntemplate <int N, int M>\nint Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  int limit = (std::max)(lhs.size(), rhs.size());\n  for (int i = limit - 1; i >= 0; --i) {\n    const uint32_t lhs_word = lhs.GetWord(i);\n    const uint32_t rhs_word = rhs.GetWord(i);\n    if (lhs_word < rhs_word) {\n      return -1;\n    } else if (lhs_word > rhs_word) {\n      return 1;\n    }\n  }\n  return 0;\n}\n\ntemplate <int N, int M>\nbool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  int limit = (std::max)(lhs.size(), rhs.size());\n  for (int i = 0; i < limit; ++i) {\n    if (lhs.GetWord(i) != rhs.GetWord(i)) {\n      return false;\n    }\n  }\n  return true;\n}\n\ntemplate <int N, int M>\nbool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  return !(lhs == rhs);\n}\n\ntemplate <int N, int M>\nbool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  return Compare(lhs, rhs) == -1;\n}\n\ntemplate <int N, int M>\nbool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  return rhs < lhs;\n}\ntemplate <int N, int M>\nbool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  return !(rhs < lhs);\n}\ntemplate <int N, int M>\nbool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {\n  return !(lhs < rhs);\n}\n\n// Output operator for BigUnsigned, for testing purposes only.\ntemplate <int N>\nstd::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {\n  return os << num.ToString();\n}\n\n// Explicit instantiation declarations for the sizes of BigUnsigned that we\n// are using.\n//\n// For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is\n// still bigger than an int128, and 84 is a large value we will want to use\n// in the from_chars implementation.\n//\n// Comments justifying the use of 84 belong in the from_chars implementation,\n// and will be added in a follow-up CL.\nextern template class BigUnsigned<4>;\nextern template class BigUnsigned<84>;\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_\n"
  },
  {
    "path": "absl/strings/internal/charconv_bigint_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/charconv_bigint.h\"\n\n#include <string>\n\n#include \"gtest/gtest.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nTEST(BigUnsigned, ShiftLeft) {\n  {\n    // Check that 3 * 2**100 is calculated correctly\n    BigUnsigned<4> num(3u);\n    num.ShiftLeft(100);\n    EXPECT_EQ(num, BigUnsigned<4>(\"3802951800684688204490109616128\"));\n  }\n  {\n    // Test that overflow is truncated properly.\n    // 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint.\n    // Shifting left by 125 bits should truncate off the high bit, so that\n    //   15 << 125 == 7 << 125\n    // after truncation.\n    BigUnsigned<4> a(15u);\n    BigUnsigned<4> b(7u);\n    BigUnsigned<4> c(3u);\n    a.ShiftLeft(125);\n    b.ShiftLeft(125);\n    c.ShiftLeft(125);\n    EXPECT_EQ(a, b);\n    EXPECT_NE(a, c);\n  }\n  {\n    // Same test, larger bigint:\n    BigUnsigned<84> a(15u);\n    BigUnsigned<84> b(7u);\n    BigUnsigned<84> c(3u);\n    a.ShiftLeft(84 * 32 - 3);\n    b.ShiftLeft(84 * 32 - 3);\n    c.ShiftLeft(84 * 32 - 3);\n    EXPECT_EQ(a, b);\n    EXPECT_NE(a, c);\n  }\n  {\n    // Check that incrementally shifting has the same result as doing it all at\n    // once (attempting to capture corner cases.)\n    const std::string seed = \"1234567890123456789012345678901234567890\";\n    BigUnsigned<84> a(seed);\n    for (int i = 1; i <= 84 * 32; ++i) {\n      a.ShiftLeft(1);\n      BigUnsigned<84> b(seed);\n      b.ShiftLeft(i);\n      EXPECT_EQ(a, b);\n    }\n    // And we should have fully rotated all bits off by now:\n    EXPECT_EQ(a, BigUnsigned<84>(0u));\n  }\n  {\n    // Bit shifting large and small numbers by large and small offsets.\n    // Intended to exercise bounds-checking corner on ShiftLeft() (directly\n    // and under asan).\n\n    // 2**(32*84)-1\n    const BigUnsigned<84> all_bits_one(\n        \"1474444211396924248063325089479706787923460402125687709454567433186613\"\n        \"6228083464060749874845919674257665016359189106695900028098437021384227\"\n        \"3285029708032466536084583113729486015826557532750465299832071590813090\"\n        \"2011853039837649252477307070509704043541368002938784757296893793903797\"\n        \"8180292336310543540677175225040919704702800559606097685920595947397024\"\n        \"8303316808753252115729411497720357971050627997031988036134171378490368\"\n        \"6008000778741115399296162550786288457245180872759047016734959330367829\"\n        \"5235612397427686310674725251378116268607113017720538636924549612987647\"\n        \"5767411074510311386444547332882472126067840027882117834454260409440463\"\n        \"9345147252664893456053258463203120637089916304618696601333953616715125\"\n        \"2115882482473279040772264257431663818610405673876655957323083702713344\"\n        \"4201105427930770976052393421467136557055\");\n    const BigUnsigned<84> zero(0u);\n    const BigUnsigned<84> one(1u);\n    // in bounds shifts\n    for (int i = 1; i < 84*32; ++i) {\n      // shifting all_bits_one to the left should result in a smaller number,\n      // since the high bits rotate off and the low bits are replaced with\n      // zeroes.\n      BigUnsigned<84> big_shifted = all_bits_one;\n      big_shifted.ShiftLeft(i);\n      EXPECT_GT(all_bits_one, big_shifted);\n      // Shifting 1 to the left should instead result in a larger number.\n      BigUnsigned<84> small_shifted = one;\n      small_shifted.ShiftLeft(i);\n      EXPECT_LT(one, small_shifted);\n    }\n    // Shifting by zero or a negative number has no effect\n    for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) {\n      BigUnsigned<84> big_shifted = all_bits_one;\n      big_shifted.ShiftLeft(no_op_shift);\n      EXPECT_EQ(all_bits_one, big_shifted);\n      BigUnsigned<84> small_shifted = one;\n      big_shifted.ShiftLeft(no_op_shift);\n      EXPECT_EQ(one, small_shifted);\n    }\n    // Shifting by an amount greater than the number of bits should result in\n    // zero.\n    for (int out_of_bounds_shift :\n         {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) {\n      BigUnsigned<84> big_shifted = all_bits_one;\n      big_shifted.ShiftLeft(out_of_bounds_shift);\n      EXPECT_EQ(zero, big_shifted);\n      BigUnsigned<84> small_shifted = one;\n      small_shifted.ShiftLeft(out_of_bounds_shift);\n      EXPECT_EQ(zero, small_shifted);\n    }\n  }\n}\n\nTEST(BigUnsigned, MultiplyByUint32) {\n  const BigUnsigned<84> factorial_100(\n      \"933262154439441526816992388562667004907159682643816214685929638952175999\"\n      \"932299156089414639761565182862536979208272237582511852109168640000000000\"\n      \"00000000000000\");\n  BigUnsigned<84> a(1u);\n  for (uint32_t i = 1; i <= 100; ++i) {\n    a.MultiplyBy(i);\n  }\n  EXPECT_EQ(a, BigUnsigned<84>(factorial_100));\n}\n\nTEST(BigUnsigned, MultiplyByBigUnsigned) {\n  {\n    // Put the terms of factorial_200 into two bigints, and multiply them\n    // together.\n    const BigUnsigned<84> factorial_200(\n        \"7886578673647905035523632139321850622951359776871732632947425332443594\"\n        \"4996340334292030428401198462390417721213891963883025764279024263710506\"\n        \"1926624952829931113462857270763317237396988943922445621451664240254033\"\n        \"2918641312274282948532775242424075739032403212574055795686602260319041\"\n        \"7032406235170085879617892222278962370389737472000000000000000000000000\"\n        \"0000000000000000000000000\");\n    BigUnsigned<84> evens(1u);\n    BigUnsigned<84> odds(1u);\n    for (uint32_t i = 1; i < 200; i += 2) {\n      odds.MultiplyBy(i);\n      evens.MultiplyBy(i + 1);\n    }\n    evens.MultiplyBy(odds);\n    EXPECT_EQ(evens, factorial_200);\n  }\n  {\n    // Multiply various powers of 10 together.\n    for (int a = 0 ; a < 700; a += 25) {\n      SCOPED_TRACE(a);\n      BigUnsigned<84> a_value(\"3\" + std::string(a, '0'));\n      for (int b = 0; b < (700 - a); b += 25) {\n        SCOPED_TRACE(b);\n        BigUnsigned<84> b_value(\"2\" + std::string(b, '0'));\n        BigUnsigned<84> expected_product(\"6\" + std::string(a + b, '0'));\n        b_value.MultiplyBy(a_value);\n        EXPECT_EQ(b_value, expected_product);\n      }\n    }\n  }\n}\n\nTEST(BigUnsigned, MultiplyByOverflow) {\n  {\n    // Check that multiplication overflow predictably truncates.\n\n    // A big int with all bits on.\n    BigUnsigned<4> all_bits_on(\"340282366920938463463374607431768211455\");\n    // Modulo 2**128, this is equal to -1.  Therefore the square of this,\n    // modulo 2**128, should be 1.\n    all_bits_on.MultiplyBy(all_bits_on);\n    EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u));\n  }\n  {\n    // Try multiplying a large bigint by 2**50, and compare the result to\n    // shifting.\n    BigUnsigned<4> value_1(\"12345678901234567890123456789012345678\");\n    BigUnsigned<4> value_2(\"12345678901234567890123456789012345678\");\n    BigUnsigned<4> two_to_fiftieth(1u);\n    two_to_fiftieth.ShiftLeft(50);\n\n    value_1.ShiftLeft(50);\n    value_2.MultiplyBy(two_to_fiftieth);\n    EXPECT_EQ(value_1, value_2);\n  }\n}\n\nTEST(BigUnsigned, FiveToTheNth) {\n  {\n    // Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to\n    // and including overflow.\n    for (int i = 0; i < 1160; ++i) {\n      SCOPED_TRACE(i);\n      BigUnsigned<84> value_1(123u);\n      BigUnsigned<84> value_2(123u);\n      value_1.MultiplyByFiveToTheNth(i);\n      for (int j = 0; j < i; j++) {\n        value_2.MultiplyBy(5u);\n      }\n      EXPECT_EQ(value_1, value_2);\n    }\n  }\n  {\n    // Check that the faster, table-lookup-based static method returns the same\n    // result that multiplying in-place would return, up to and including\n    // overflow.\n    for (int i = 0; i < 1160; ++i) {\n      SCOPED_TRACE(i);\n      BigUnsigned<84> value_1(1u);\n      value_1.MultiplyByFiveToTheNth(i);\n      BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i);\n      EXPECT_EQ(value_1, value_2);\n    }\n  }\n}\n\nTEST(BigUnsigned, TenToTheNth) {\n  {\n    // Sanity check MultiplyByTenToTheNth.\n    for (int i = 0; i < 800; ++i) {\n      SCOPED_TRACE(i);\n      BigUnsigned<84> value_1(123u);\n      BigUnsigned<84> value_2(123u);\n      value_1.MultiplyByTenToTheNth(i);\n      for (int j = 0; j < i; j++) {\n        value_2.MultiplyBy(10u);\n      }\n      EXPECT_EQ(value_1, value_2);\n    }\n  }\n  {\n    // Alternate testing approach, taking advantage of the decimal parser.\n    for (int i = 0; i < 200; ++i) {\n      SCOPED_TRACE(i);\n      BigUnsigned<84> value_1(135u);\n      value_1.MultiplyByTenToTheNth(i);\n      BigUnsigned<84> value_2(\"135\" + std::string(i, '0'));\n      EXPECT_EQ(value_1, value_2);\n    }\n  }\n}\n\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/charconv_parse.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/charconv_parse.h\"\n#include \"absl/strings/charconv.h\"\n\n#include <cassert>\n#include <cstdint>\n#include <limits>\n\n#include \"absl/strings/internal/memutil.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\n// ParseFloat<10> will read the first 19 significant digits of the mantissa.\n// This number was chosen for multiple reasons.\n//\n// (a) First, for whatever integer type we choose to represent the mantissa, we\n// want to choose the largest possible number of decimal digits for that integer\n// type.  We are using uint64_t, which can express any 19-digit unsigned\n// integer.\n//\n// (b) Second, we need to parse enough digits that the binary value of any\n// mantissa we capture has more bits of resolution than the mantissa\n// representation in the target float.  Our algorithm requires at least 3 bits\n// of headway, but 19 decimal digits give a little more than that.\n//\n// The following static assertions verify the above comments:\nconstexpr int kDecimalMantissaDigitsMax = 19;\n\nstatic_assert(std::numeric_limits<uint64_t>::digits10 ==\n                  kDecimalMantissaDigitsMax,\n              \"(a) above\");\n\n// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa.\nstatic_assert(std::numeric_limits<double>::is_iec559, \"IEEE double assumed\");\nstatic_assert(std::numeric_limits<double>::radix == 2, \"IEEE double fact\");\nstatic_assert(std::numeric_limits<double>::digits == 53, \"IEEE double fact\");\n\n// The lowest valued 19-digit decimal mantissa we can read still contains\n// sufficient information to reconstruct a binary mantissa.\nstatic_assert(1000000000000000000u > (uint64_t{1} << (53 + 3)), \"(b) above\");\n\n// ParseFloat<16> will read the first 15 significant digits of the mantissa.\n//\n// Because a base-16-to-base-2 conversion can be done exactly, we do not need\n// to maximize the number of scanned hex digits to improve our conversion.  What\n// is required is to scan two more bits than the mantissa can represent, so that\n// we always round correctly.\n//\n// (One extra bit does not suffice to perform correct rounding, since a number\n// exactly halfway between two representable floats has unique rounding rules,\n// so we need to differentiate between a \"halfway between\" number and a \"closer\n// to the larger value\" number.)\nconstexpr int kHexadecimalMantissaDigitsMax = 15;\n\n// The minimum number of significant bits that will be read from\n// kHexadecimalMantissaDigitsMax hex digits.  We must subtract by three, since\n// the most significant digit can be a \"1\", which only contributes a single\n// significant bit.\nconstexpr int kGuaranteedHexadecimalMantissaBitPrecision =\n    4 * kHexadecimalMantissaDigitsMax - 3;\n\nstatic_assert(kGuaranteedHexadecimalMantissaBitPrecision >\n                  std::numeric_limits<double>::digits + 2,\n              \"kHexadecimalMantissaDigitsMax too small\");\n\n// We also impose a limit on the number of significant digits we will read from\n// an exponent, to avoid having to deal with integer overflow.  We use 9 for\n// this purpose.\n//\n// If we read a 9 digit exponent, the end result of the conversion will\n// necessarily be infinity or zero, depending on the sign of the exponent.\n// Therefore we can just drop extra digits on the floor without any extra\n// logic.\nconstexpr int kDecimalExponentDigitsMax = 9;\nstatic_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax,\n              \"int type too small\");\n\n// To avoid incredibly large inputs causing integer overflow for our exponent,\n// we impose an arbitrary but very large limit on the number of significant\n// digits we will accept.  The implementation refuses to match a string with\n// more consecutive significant mantissa digits than this.\nconstexpr int kDecimalDigitLimit = 50000000;\n\n// Corresponding limit for hexadecimal digit inputs.  This is one fourth the\n// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires\n// a binary exponent adjustment of 4.\nconstexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4;\n\n// The largest exponent we can read is 999999999 (per\n// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get\n// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these\n// comfortably fits in an integer.\n//\n// We count kDecimalDigitLimit twice because there are independent limits for\n// numbers before and after the decimal point.  (In the case where there are no\n// significant digits before the decimal point, there are independent limits for\n// post-decimal-point leading zeroes and for significant digits.)\nstatic_assert(999999999 + 2 * kDecimalDigitLimit <\n                  std::numeric_limits<int>::max(),\n              \"int type too small\");\nstatic_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) <\n                  std::numeric_limits<int>::max(),\n              \"int type too small\");\n\n// Returns true if the provided bitfield allows parsing an exponent value\n// (e.g., \"1.5e100\").\nbool AllowExponent(chars_format flags) {\n  bool fixed = (flags & chars_format::fixed) == chars_format::fixed;\n  bool scientific =\n      (flags & chars_format::scientific) == chars_format::scientific;\n  return scientific || !fixed;\n}\n\n// Returns true if the provided bitfield requires an exponent value be present.\nbool RequireExponent(chars_format flags) {\n  bool fixed = (flags & chars_format::fixed) == chars_format::fixed;\n  bool scientific =\n      (flags & chars_format::scientific) == chars_format::scientific;\n  return scientific && !fixed;\n}\n\nconst int8_t kAsciiToInt[256] = {\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  1,  2,  3,  4,  5,  6,  7,  8,\n    9,  -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1};\n\n// Returns true if `ch` is a digit in the given base\ntemplate <int base>\nbool IsDigit(char ch);\n\n// Converts a valid `ch` to its digit value in the given base.\ntemplate <int base>\nunsigned ToDigit(char ch);\n\n// Returns true if `ch` is the exponent delimiter for the given base.\ntemplate <int base>\nbool IsExponentCharacter(char ch);\n\n// Returns the maximum number of significant digits we will read for a float\n// in the given base.\ntemplate <int base>\nconstexpr int MantissaDigitsMax();\n\n// Returns the largest consecutive run of digits we will accept when parsing a\n// number in the given base.\ntemplate <int base>\nconstexpr int DigitLimit();\n\n// Returns the amount the exponent must be adjusted by for each dropped digit.\n// (For decimal this is 1, since the digits are in base 10 and the exponent base\n// is also 10, but for hexadecimal this is 4, since the digits are base 16 but\n// the exponent base is 2.)\ntemplate <int base>\nconstexpr int DigitMagnitude();\n\ntemplate <>\nbool IsDigit<10>(char ch) {\n  return ch >= '0' && ch <= '9';\n}\ntemplate <>\nbool IsDigit<16>(char ch) {\n  return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0;\n}\n\ntemplate <>\nunsigned ToDigit<10>(char ch) {\n  return static_cast<unsigned>(ch - '0');\n}\ntemplate <>\nunsigned ToDigit<16>(char ch) {\n  return static_cast<unsigned>(kAsciiToInt[static_cast<unsigned char>(ch)]);\n}\n\ntemplate <>\nbool IsExponentCharacter<10>(char ch) {\n  return ch == 'e' || ch == 'E';\n}\n\ntemplate <>\nbool IsExponentCharacter<16>(char ch) {\n  return ch == 'p' || ch == 'P';\n}\n\ntemplate <>\nconstexpr int MantissaDigitsMax<10>() {\n  return kDecimalMantissaDigitsMax;\n}\ntemplate <>\nconstexpr int MantissaDigitsMax<16>() {\n  return kHexadecimalMantissaDigitsMax;\n}\n\ntemplate <>\nconstexpr int DigitLimit<10>() {\n  return kDecimalDigitLimit;\n}\ntemplate <>\nconstexpr int DigitLimit<16>() {\n  return kHexadecimalDigitLimit;\n}\n\ntemplate <>\nconstexpr int DigitMagnitude<10>() {\n  return 1;\n}\ntemplate <>\nconstexpr int DigitMagnitude<16>() {\n  return 4;\n}\n\n// Reads decimal digits from [begin, end) into *out.  Returns the number of\n// digits consumed.\n//\n// After max_digits has been read, keeps consuming characters, but no longer\n// adjusts *out.  If a nonzero digit is dropped this way, *dropped_nonzero_digit\n// is set; otherwise, it is left unmodified.\n//\n// If no digits are matched, returns 0 and leaves *out unchanged.\n//\n// ConsumeDigits does not protect against overflow on *out; max_digits must\n// be chosen with respect to type T to avoid the possibility of overflow.\ntemplate <int base, typename T>\nint ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,\n                  bool* dropped_nonzero_digit) {\n  if (base == 10) {\n    assert(max_digits <= std::numeric_limits<T>::digits10);\n  } else if (base == 16) {\n    assert(max_digits * 4 <= std::numeric_limits<T>::digits);\n  }\n  const char* const original_begin = begin;\n\n  // Skip leading zeros, but only if *out is zero.\n  // They don't cause an overflow so we don't have to count them for\n  // `max_digits`.\n  while (!*out && end != begin && *begin == '0') ++begin;\n\n  T accumulator = *out;\n  const char* significant_digits_end =\n      (end - begin > max_digits) ? begin + max_digits : end;\n  while (begin < significant_digits_end && IsDigit<base>(*begin)) {\n    // Do not guard against *out overflow; max_digits was chosen to avoid this.\n    // Do assert against it, to detect problems in debug builds.\n    auto digit = static_cast<T>(ToDigit<base>(*begin));\n    assert(accumulator * base >= accumulator);\n    accumulator *= base;\n    assert(accumulator + digit >= accumulator);\n    accumulator += digit;\n    ++begin;\n  }\n  bool dropped_nonzero = false;\n  while (begin < end && IsDigit<base>(*begin)) {\n    dropped_nonzero = dropped_nonzero || (*begin != '0');\n    ++begin;\n  }\n  if (dropped_nonzero && dropped_nonzero_digit != nullptr) {\n    *dropped_nonzero_digit = true;\n  }\n  *out = accumulator;\n  return static_cast<int>(begin - original_begin);\n}\n\n// Returns true if `v` is one of the chars allowed inside parentheses following\n// a NaN.\nbool IsNanChar(char v) {\n  return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') ||\n         (v >= 'A' && v <= 'Z');\n}\n\n// Checks the range [begin, end) for a strtod()-formatted infinity or NaN.  If\n// one is found, sets `out` appropriately and returns true.\nbool ParseInfinityOrNan(const char* begin, const char* end,\n                        strings_internal::ParsedFloat* out) {\n  if (end - begin < 3) {\n    return false;\n  }\n  switch (*begin) {\n    case 'i':\n    case 'I': {\n      // An infinity string consists of the characters \"inf\" or \"infinity\",\n      // case insensitive.\n      if (strings_internal::memcasecmp(begin + 1, \"nf\", 2) != 0) {\n        return false;\n      }\n      out->type = strings_internal::FloatType::kInfinity;\n      if (end - begin >= 8 &&\n          strings_internal::memcasecmp(begin + 3, \"inity\", 5) == 0) {\n        out->end = begin + 8;\n      } else {\n        out->end = begin + 3;\n      }\n      return true;\n    }\n    case 'n':\n    case 'N': {\n      // A NaN consists of the characters \"nan\", case insensitive, optionally\n      // followed by a parenthesized sequence of zero or more alphanumeric\n      // characters and/or underscores.\n      if (strings_internal::memcasecmp(begin + 1, \"an\", 2) != 0) {\n        return false;\n      }\n      out->type = strings_internal::FloatType::kNan;\n      out->end = begin + 3;\n      // NaN is allowed to be followed by a parenthesized string, consisting of\n      // only the characters [a-zA-Z0-9_].  Match that if it's present.\n      begin += 3;\n      if (begin < end && *begin == '(') {\n        const char* nan_begin = begin + 1;\n        while (nan_begin < end && IsNanChar(*nan_begin)) {\n          ++nan_begin;\n        }\n        if (nan_begin < end && *nan_begin == ')') {\n          // We found an extra NaN specifier range\n          out->subrange_begin = begin + 1;\n          out->subrange_end = nan_begin;\n          out->end = nan_begin + 1;\n        }\n      }\n      return true;\n    }\n    default:\n      return false;\n  }\n}\n}  // namespace\n\nnamespace strings_internal {\n\ntemplate <int base>\nstrings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,\n                                         chars_format format_flags) {\n  strings_internal::ParsedFloat result;\n\n  // Exit early if we're given an empty range.\n  if (begin == end) return result;\n\n  // Handle the infinity and NaN cases.\n  if (ParseInfinityOrNan(begin, end, &result)) {\n    return result;\n  }\n\n  const char* const mantissa_begin = begin;\n  while (begin < end && *begin == '0') {\n    ++begin;  // skip leading zeros\n  }\n  uint64_t mantissa = 0;\n\n  int exponent_adjustment = 0;\n  bool mantissa_is_inexact = false;\n  int pre_decimal_digits = ConsumeDigits<base>(\n      begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);\n  begin += pre_decimal_digits;\n  int digits_left;\n  if (pre_decimal_digits >= DigitLimit<base>()) {\n    // refuse to parse pathological inputs\n    return result;\n  } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {\n    // We dropped some non-fraction digits on the floor.  Adjust our exponent\n    // to compensate.\n    exponent_adjustment =\n        static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());\n    digits_left = 0;\n  } else {\n    digits_left =\n        static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);\n  }\n  if (begin < end && *begin == '.') {\n    ++begin;\n    if (mantissa == 0) {\n      // If we haven't seen any nonzero digits yet, keep skipping zeros.  We\n      // have to adjust the exponent to reflect the changed place value.\n      const char* begin_zeros = begin;\n      while (begin < end && *begin == '0') {\n        ++begin;\n      }\n      int zeros_skipped = static_cast<int>(begin - begin_zeros);\n      if (zeros_skipped >= DigitLimit<base>()) {\n        // refuse to parse pathological inputs\n        return result;\n      }\n      exponent_adjustment -= static_cast<int>(zeros_skipped);\n    }\n    int post_decimal_digits = ConsumeDigits<base>(\n        begin, end, digits_left, &mantissa, &mantissa_is_inexact);\n    begin += post_decimal_digits;\n\n    // Since `mantissa` is an integer, each significant digit we read after\n    // the decimal point requires an adjustment to the exponent. \"1.23e0\" will\n    // be stored as `mantissa` == 123 and `exponent` == -2 (that is,\n    // \"123e-2\").\n    if (post_decimal_digits >= DigitLimit<base>()) {\n      // refuse to parse pathological inputs\n      return result;\n    } else if (post_decimal_digits > digits_left) {\n      exponent_adjustment -= digits_left;\n    } else {\n      exponent_adjustment -= post_decimal_digits;\n    }\n  }\n  // If we've found no mantissa whatsoever, this isn't a number.\n  if (mantissa_begin == begin) {\n    return result;\n  }\n  // A bare \".\" doesn't count as a mantissa either.\n  if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {\n    return result;\n  }\n\n  if (mantissa_is_inexact) {\n    // We dropped significant digits on the floor.  Handle this appropriately.\n    if (base == 10) {\n      // If we truncated significant decimal digits, store the full range of the\n      // mantissa for future big integer math for exact rounding.\n      result.subrange_begin = mantissa_begin;\n      result.subrange_end = begin;\n    } else if (base == 16) {\n      // If we truncated hex digits, reflect this fact by setting the low\n      // (\"sticky\") bit.  This allows for correct rounding in all cases.\n      mantissa |= 1;\n    }\n  }\n  result.mantissa = mantissa;\n\n  const char* const exponent_begin = begin;\n  result.literal_exponent = 0;\n  bool found_exponent = false;\n  if (AllowExponent(format_flags) && begin < end &&\n      IsExponentCharacter<base>(*begin)) {\n    bool negative_exponent = false;\n    ++begin;\n    if (begin < end && *begin == '-') {\n      negative_exponent = true;\n      ++begin;\n    } else if (begin < end && *begin == '+') {\n      ++begin;\n    }\n    const char* const exponent_digits_begin = begin;\n    // Exponent is always expressed in decimal, even for hexadecimal floats.\n    begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,\n                               &result.literal_exponent, nullptr);\n    if (begin == exponent_digits_begin) {\n      // there were no digits where we expected an exponent.  We failed to read\n      // an exponent and should not consume the 'e' after all.  Rewind 'begin'.\n      found_exponent = false;\n      begin = exponent_begin;\n    } else {\n      found_exponent = true;\n      if (negative_exponent) {\n        result.literal_exponent = -result.literal_exponent;\n      }\n    }\n  }\n\n  if (!found_exponent && RequireExponent(format_flags)) {\n    // Provided flags required an exponent, but none was found.  This results\n    // in a failure to scan.\n    return result;\n  }\n\n  // Success!\n  result.type = strings_internal::FloatType::kNumber;\n  if (result.mantissa > 0) {\n    result.exponent = result.literal_exponent +\n                      (DigitMagnitude<base>() * exponent_adjustment);\n  } else {\n    result.exponent = 0;\n  }\n  result.end = begin;\n  return result;\n}\n\ntemplate ParsedFloat ParseFloat<10>(const char* begin, const char* end,\n                                    chars_format format_flags);\ntemplate ParsedFloat ParseFloat<16>(const char* begin, const char* end,\n                                    chars_format format_flags);\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/charconv_parse.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_\n#define ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/charconv.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// Enum indicating whether a parsed float is a number or special value.\nenum class FloatType { kNumber, kInfinity, kNan };\n\n// The decomposed parts of a parsed `float` or `double`.\nstruct ParsedFloat {\n  // Representation of the parsed mantissa, with the decimal point adjusted to\n  // make it an integer.\n  //\n  // During decimal scanning, this contains 19 significant digits worth of\n  // mantissa value.  If digits beyond this point are found, they\n  // are truncated, and if any of these dropped digits are nonzero, then\n  // `mantissa` is inexact, and the full mantissa is stored in [subrange_begin,\n  // subrange_end).\n  //\n  // During hexadecimal scanning, this contains 15 significant hex digits worth\n  // of mantissa value.  Digits beyond this point are sticky -- they are\n  // truncated, but if any dropped digits are nonzero, the low bit of mantissa\n  // will be set.  (This allows for precise rounding, and avoids the need\n  // to store the full mantissa in [subrange_begin, subrange_end).)\n  uint64_t mantissa = 0;\n\n  // Floating point expontent.  This reflects any decimal point adjustments and\n  // any truncated digits from the mantissa.  The absolute value of the parsed\n  // number is represented by mantissa * (base ** exponent), where base==10 for\n  // decimal floats, and base==2 for hexadecimal floats.\n  int exponent = 0;\n\n  // The literal exponent value scanned from the input, or 0 if none was\n  // present.  This does not reflect any adjustments applied to mantissa.\n  int literal_exponent = 0;\n\n  // The type of number scanned.\n  FloatType type = FloatType::kNumber;\n\n  // When non-null, [subrange_begin, subrange_end) marks a range of characters\n  // that require further processing.  The meaning is dependent on float type.\n  // If type == kNumber and this is set, this is a \"wide input\": the input\n  // mantissa contained more than 19 digits.  The range contains the full\n  // mantissa.  It plus `literal_exponent` need to be examined to find the best\n  // floating point match.\n  // If type == kNan and this is set, the range marks the contents of a\n  // matched parenthesized character region after the NaN.\n  const char* subrange_begin = nullptr;\n  const char* subrange_end = nullptr;\n\n  // One-past-the-end of the successfully parsed region, or nullptr if no\n  // matching pattern was found.\n  const char* end = nullptr;\n};\n\n// Read the floating point number in the provided range, and populate\n// ParsedFloat accordingly.\n//\n// format_flags is a bitmask value specifying what patterns this API will match.\n// `scientific` and `fixed`  are honored per std::from_chars rules\n// ([utility.from.chars], C++17): if exactly one of these bits is set, then an\n// exponent is required, or dislallowed, respectively.\n//\n// Template parameter `base` must be either 10 or 16.  For base 16, a \"0x\" is\n// *not* consumed.  The `hex` bit from format_flags is ignored by ParseFloat.\ntemplate <int base>\nParsedFloat ParseFloat(const char* begin, const char* end,\n                       absl::chars_format format_flags);\n\nextern template ParsedFloat ParseFloat<10>(const char* begin, const char* end,\n                                           absl::chars_format format_flags);\nextern template ParsedFloat ParseFloat<16>(const char* begin, const char* end,\n                                           absl::chars_format format_flags);\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_\n"
  },
  {
    "path": "absl/strings/internal/charconv_parse_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/charconv_parse.h\"\n\n#include <string>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/check.h\"\n#include \"absl/strings/str_cat.h\"\n\nusing absl::chars_format;\nusing absl::strings_internal::FloatType;\nusing absl::strings_internal::ParsedFloat;\nusing absl::strings_internal::ParseFloat;\n\nnamespace {\n\n// Check that a given string input is parsed to the expected mantissa and\n// exponent.\n//\n// Input string `s` must contain a '$' character.  It marks the end of the\n// characters that should be consumed by the match.  It is stripped from the\n// input to ParseFloat.\n//\n// If input string `s` contains '[' and ']' characters, these mark the region\n// of characters that should be marked as the \"subrange\".  For NaNs, this is\n// the location of the extended NaN string.  For numbers, this is the location\n// of the full, over-large mantissa.\ntemplate <int base>\nvoid ExpectParsedFloat(std::string s, absl::chars_format format_flags,\n                       FloatType expected_type, uint64_t expected_mantissa,\n                       int expected_exponent,\n                       int expected_literal_exponent = -999) {\n  SCOPED_TRACE(s);\n\n  int begin_subrange = -1;\n  int end_subrange = -1;\n  // If s contains '[' and ']', then strip these characters and set the subrange\n  // indices appropriately.\n  std::string::size_type open_bracket_pos = s.find('[');\n  if (open_bracket_pos != std::string::npos) {\n    begin_subrange = static_cast<int>(open_bracket_pos);\n    s.replace(open_bracket_pos, 1, \"\");\n    std::string::size_type close_bracket_pos = s.find(']');\n    CHECK_NE(close_bracket_pos, absl::string_view::npos)\n        << \"Test input contains [ without matching ]\";\n    end_subrange = static_cast<int>(close_bracket_pos);\n    s.replace(close_bracket_pos, 1, \"\");\n  }\n  const std::string::size_type expected_characters_matched = s.find('$');\n  CHECK_NE(expected_characters_matched, std::string::npos)\n      << \"Input string must contain $\";\n  s.replace(expected_characters_matched, 1, \"\");\n\n  ParsedFloat parsed =\n      ParseFloat<base>(s.data(), s.data() + s.size(), format_flags);\n\n  EXPECT_NE(parsed.end, nullptr);\n  if (parsed.end == nullptr) {\n    return;  // The following tests are not useful if we fully failed to parse\n  }\n  EXPECT_EQ(parsed.type, expected_type);\n  if (begin_subrange == -1) {\n    EXPECT_EQ(parsed.subrange_begin, nullptr);\n    EXPECT_EQ(parsed.subrange_end, nullptr);\n  } else {\n    EXPECT_EQ(parsed.subrange_begin, s.data() + begin_subrange);\n    EXPECT_EQ(parsed.subrange_end, s.data() + end_subrange);\n  }\n  if (parsed.type == FloatType::kNumber) {\n    EXPECT_EQ(parsed.mantissa, expected_mantissa);\n    EXPECT_EQ(parsed.exponent, expected_exponent);\n    if (expected_literal_exponent != -999) {\n      EXPECT_EQ(parsed.literal_exponent, expected_literal_exponent);\n    }\n  }\n  auto characters_matched = static_cast<int>(parsed.end - s.data());\n  EXPECT_EQ(characters_matched, expected_characters_matched);\n}\n\n// Check that a given string input is parsed to the expected mantissa and\n// exponent.\n//\n// Input string `s` must contain a '$' character.  It marks the end of the\n// characters that were consumed by the match.\ntemplate <int base>\nvoid ExpectNumber(std::string s, absl::chars_format format_flags,\n                  uint64_t expected_mantissa, int expected_exponent,\n                  int expected_literal_exponent = -999) {\n  ExpectParsedFloat<base>(std::move(s), format_flags, FloatType::kNumber,\n                          expected_mantissa, expected_exponent,\n                          expected_literal_exponent);\n}\n\n// Check that a given string input is parsed to the given special value.\n//\n// This tests against both number bases, since infinities and NaNs have\n// identical representations in both modes.\nvoid ExpectSpecial(const std::string& s, absl::chars_format format_flags,\n                   FloatType type) {\n  ExpectParsedFloat<10>(s, format_flags, type, 0, 0);\n  ExpectParsedFloat<16>(s, format_flags, type, 0, 0);\n}\n\n// Check that a given input string is not matched by Float.\ntemplate <int base>\nvoid ExpectFailedParse(absl::string_view s, absl::chars_format format_flags) {\n  ParsedFloat parsed =\n      ParseFloat<base>(s.data(), s.data() + s.size(), format_flags);\n  EXPECT_EQ(parsed.end, nullptr);\n}\n\nTEST(ParseFloat, SimpleValue) {\n  // Test that various forms of floating point numbers all parse correctly.\n  ExpectNumber<10>(\"1.23456789e5$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789e+5$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789E5$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789e05$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"123.456789e3$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"0.000123456789e9$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"123456.789$\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"123456789e-3$\", chars_format::general, 123456789, -3);\n\n  ExpectNumber<16>(\"1.234abcdefp28$\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"1.234abcdefp+28$\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"1.234ABCDEFp28$\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"1.234AbCdEfP0028$\", chars_format::general, 0x1234abcdef,\n                   -8);\n  ExpectNumber<16>(\"123.4abcdefp20$\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"0.0001234abcdefp44$\", chars_format::general, 0x1234abcdef,\n                   -8);\n  ExpectNumber<16>(\"1234abcd.ef$\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"1234abcdefp-8$\", chars_format::general, 0x1234abcdef, -8);\n\n  // ExpectNumber does not attempt to drop trailing zeroes.\n  ExpectNumber<10>(\"0001.2345678900e005$\", chars_format::general, 12345678900,\n                   -5);\n  ExpectNumber<16>(\"0001.234abcdef000p28$\", chars_format::general,\n                   0x1234abcdef000, -20);\n\n  // Ensure non-matching characters after a number are ignored, even when they\n  // look like potentially matching characters.\n  ExpectNumber<10>(\"1.23456789e5$   \", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789e5$e5e5\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789e5$.25\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789e5$-\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"1.23456789e5$PUPPERS!!!\", chars_format::general, 123456789,\n                   -3);\n  ExpectNumber<10>(\"123456.789$efghij\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"123456.789$e\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"123456.789$p5\", chars_format::general, 123456789, -3);\n  ExpectNumber<10>(\"123456.789$.10\", chars_format::general, 123456789, -3);\n\n  ExpectNumber<16>(\"1.234abcdefp28$   \", chars_format::general, 0x1234abcdef,\n                   -8);\n  ExpectNumber<16>(\"1.234abcdefp28$p28\", chars_format::general, 0x1234abcdef,\n                   -8);\n  ExpectNumber<16>(\"1.234abcdefp28$.125\", chars_format::general, 0x1234abcdef,\n                   -8);\n  ExpectNumber<16>(\"1.234abcdefp28$-\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"1.234abcdefp28$KITTEHS!!!\", chars_format::general,\n                   0x1234abcdef, -8);\n  ExpectNumber<16>(\"1234abcd.ef$ghijk\", chars_format::general, 0x1234abcdef,\n                   -8);\n  ExpectNumber<16>(\"1234abcd.ef$p\", chars_format::general, 0x1234abcdef, -8);\n  ExpectNumber<16>(\"1234abcd.ef$.10\", chars_format::general, 0x1234abcdef, -8);\n\n  // Ensure we can read a full resolution mantissa without overflow.\n  ExpectNumber<10>(\"9999999999999999999$\", chars_format::general,\n                   9999999999999999999u, 0);\n  ExpectNumber<16>(\"fffffffffffffff$\", chars_format::general,\n                   0xfffffffffffffffu, 0);\n\n  // Check that zero is consistently read.\n  ExpectNumber<10>(\"0$\", chars_format::general, 0, 0);\n  ExpectNumber<16>(\"0$\", chars_format::general, 0, 0);\n  ExpectNumber<10>(\"000000000000000000000000000000000000000$\",\n                   chars_format::general, 0, 0);\n  ExpectNumber<16>(\"000000000000000000000000000000000000000$\",\n                   chars_format::general, 0, 0);\n  ExpectNumber<10>(\"0000000000000000000000.000000000000000000$\",\n                   chars_format::general, 0, 0);\n  ExpectNumber<16>(\"0000000000000000000000.000000000000000000$\",\n                   chars_format::general, 0, 0);\n  ExpectNumber<10>(\"0.00000000000000000000000000000000e123456$\",\n                   chars_format::general, 0, 0);\n  ExpectNumber<16>(\"0.00000000000000000000000000000000p123456$\",\n                   chars_format::general, 0, 0);\n}\n\nTEST(ParseFloat, LargeDecimalMantissa) {\n  // After 19 significant decimal digits in the mantissa, ParsedFloat will\n  // truncate additional digits.  We need to test that:\n  //   1) the truncation to 19 digits happens\n  //   2) the returned exponent reflects the dropped significant digits\n  //   3) a correct literal_exponent is set\n  //\n  // If and only if a significant digit is found after 19 digits, then the\n  // entirety of the mantissa in case the exact value is needed to make a\n  // rounding decision.  The [ and ] characters below denote where such a\n  // subregion was marked by by ParseFloat.  They are not part of the input.\n\n  // Mark a capture group only if a dropped digit is significant (nonzero).\n  ExpectNumber<10>(\"100000000000000000000000000$\", chars_format::general,\n                   1000000000000000000,\n                   /* adjusted exponent */ 8);\n\n  ExpectNumber<10>(\"123456789123456789100000000$\", chars_format::general,\n                   1234567891234567891,\n                   /* adjusted exponent */ 8);\n\n  ExpectNumber<10>(\"[123456789123456789123456789]$\", chars_format::general,\n                   1234567891234567891,\n                   /* adjusted exponent */ 8,\n                   /* literal exponent */ 0);\n\n  ExpectNumber<10>(\"[123456789123456789100000009]$\", chars_format::general,\n                   1234567891234567891,\n                   /* adjusted exponent */ 8,\n                   /* literal exponent */ 0);\n\n  ExpectNumber<10>(\"[123456789123456789120000000]$\", chars_format::general,\n                   1234567891234567891,\n                   /* adjusted exponent */ 8,\n                   /* literal exponent */ 0);\n\n  // Leading zeroes should not count towards the 19 significant digit limit\n  ExpectNumber<10>(\"[00000000123456789123456789123456789]$\",\n                   chars_format::general, 1234567891234567891,\n                   /* adjusted exponent */ 8,\n                   /* literal exponent */ 0);\n\n  ExpectNumber<10>(\"00000000123456789123456789100000000$\",\n                   chars_format::general, 1234567891234567891,\n                   /* adjusted exponent */ 8);\n\n  // Truncated digits after the decimal point should not cause a further\n  // exponent adjustment.\n  ExpectNumber<10>(\"1.234567891234567891e123$\", chars_format::general,\n                   1234567891234567891, 105);\n  ExpectNumber<10>(\"[1.23456789123456789123456789]e123$\", chars_format::general,\n                   1234567891234567891,\n                   /* adjusted exponent */ 105,\n                   /* literal exponent */ 123);\n\n  // Ensure we truncate, and not round.  (The from_chars algorithm we use\n  // depends on our guess missing low, if it misses, so we need the rounding\n  // error to be downward.)\n  ExpectNumber<10>(\"[1999999999999999999999]$\", chars_format::general,\n                   1999999999999999999,\n                   /* adjusted exponent */ 3,\n                   /* literal exponent */ 0);\n}\n\nTEST(ParseFloat, LargeHexadecimalMantissa) {\n  // After 15 significant hex digits in the mantissa, ParsedFloat will treat\n  // additional digits as sticky,  We need to test that:\n  //   1) The truncation to 15 digits happens\n  //   2) The returned exponent reflects the dropped significant digits\n  //   3) If a nonzero digit is dropped, the low bit of mantissa is set.\n\n  ExpectNumber<16>(\"123456789abcdef123456789abcdef$\", chars_format::general,\n                   0x123456789abcdef, 60);\n\n  // Leading zeroes should not count towards the 15 significant digit limit\n  ExpectNumber<16>(\"000000123456789abcdef123456789abcdef$\",\n                   chars_format::general, 0x123456789abcdef, 60);\n\n  // Truncated digits after the radix point should not cause a further\n  // exponent adjustment.\n  ExpectNumber<16>(\"1.23456789abcdefp100$\", chars_format::general,\n                   0x123456789abcdef, 44);\n  ExpectNumber<16>(\"1.23456789abcdef123456789abcdefp100$\",\n                   chars_format::general, 0x123456789abcdef, 44);\n\n  // test sticky digit behavior.  The low bit should be set iff any dropped\n  // digit is nonzero.\n  ExpectNumber<16>(\"123456789abcdee123456789abcdee$\", chars_format::general,\n                   0x123456789abcdef, 60);\n  ExpectNumber<16>(\"123456789abcdee000000000000001$\", chars_format::general,\n                   0x123456789abcdef, 60);\n  ExpectNumber<16>(\"123456789abcdee000000000000000$\", chars_format::general,\n                   0x123456789abcdee, 60);\n}\n\nTEST(ParseFloat, ScientificVsFixed) {\n  // In fixed mode, an exponent is never matched (but the remainder of the\n  // number will be matched.)\n  ExpectNumber<10>(\"1.23456789$e5\", chars_format::fixed, 123456789, -8);\n  ExpectNumber<10>(\"123456.789$\", chars_format::fixed, 123456789, -3);\n  ExpectNumber<16>(\"1.234abcdef$p28\", chars_format::fixed, 0x1234abcdef, -36);\n  ExpectNumber<16>(\"1234abcd.ef$\", chars_format::fixed, 0x1234abcdef, -8);\n\n  // In scientific mode, numbers don't match *unless* they have an exponent.\n  ExpectNumber<10>(\"1.23456789e5$\", chars_format::scientific, 123456789, -3);\n  ExpectFailedParse<10>(\"-123456.789$\", chars_format::scientific);\n  ExpectNumber<16>(\"1.234abcdefp28$\", chars_format::scientific, 0x1234abcdef,\n                   -8);\n  ExpectFailedParse<16>(\"1234abcd.ef$\", chars_format::scientific);\n}\n\nTEST(ParseFloat, Infinity) {\n  ExpectFailedParse<10>(\"in\", chars_format::general);\n  ExpectFailedParse<16>(\"in\", chars_format::general);\n  ExpectFailedParse<10>(\"inx\", chars_format::general);\n  ExpectFailedParse<16>(\"inx\", chars_format::general);\n  ExpectSpecial(\"inf$\", chars_format::general, FloatType::kInfinity);\n  ExpectSpecial(\"Inf$\", chars_format::general, FloatType::kInfinity);\n  ExpectSpecial(\"INF$\", chars_format::general, FloatType::kInfinity);\n  ExpectSpecial(\"inf$inite\", chars_format::general, FloatType::kInfinity);\n  ExpectSpecial(\"iNfInItY$\", chars_format::general, FloatType::kInfinity);\n  ExpectSpecial(\"infinity$!!!\", chars_format::general, FloatType::kInfinity);\n}\n\nTEST(ParseFloat, NaN) {\n  ExpectFailedParse<10>(\"na\", chars_format::general);\n  ExpectFailedParse<16>(\"na\", chars_format::general);\n  ExpectFailedParse<10>(\"nah\", chars_format::general);\n  ExpectFailedParse<16>(\"nah\", chars_format::general);\n  ExpectSpecial(\"nan$\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"NaN$\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"nAn$\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"NAN$\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"NaN$aNaNaNaNaBatman!\", chars_format::general, FloatType::kNan);\n\n  // A parenthesized sequence of the characters [a-zA-Z0-9_] is allowed to\n  // appear after an NaN.  Check that this is allowed, and that the correct\n  // characters are grouped.\n  //\n  // (The characters [ and ] in the pattern below delimit the expected matched\n  // subgroup; they are not part of the input passed to ParseFloat.)\n  ExpectSpecial(\"nan([0xabcdef])$\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"nan([0xabcdef])$...\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"nan([0xabcdef])$)...\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"nan([])$\", chars_format::general, FloatType::kNan);\n  ExpectSpecial(\"nan([aAzZ09_])$\", chars_format::general, FloatType::kNan);\n  // If the subgroup contains illegal characters, don't match it at all.\n  ExpectSpecial(\"nan$(bad-char)\", chars_format::general, FloatType::kNan);\n  // Also cope with a missing close paren.\n  ExpectSpecial(\"nan$(0xabcdef\", chars_format::general, FloatType::kNan);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/cord_data_edge.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_DATA_EDGE_H_\n#define ABSL_STRINGS_INTERNAL_CORD_DATA_EDGE_H_\n\n#include <cassert>\n#include <cstddef>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// Returns true if the provided rep is a FLAT, EXTERNAL or a SUBSTRING node\n// holding a FLAT or EXTERNAL child rep. Requires `rep != nullptr`.\ninline bool IsDataEdge(const CordRep* edge) {\n  assert(edge != nullptr);\n\n  // The fast path is that `edge` is an EXTERNAL or FLAT node, making the below\n  // if a single, well predicted branch. We then repeat the FLAT or EXTERNAL\n  // check in the slow path of the SUBSTRING check to optimize for the hot path.\n  if (edge->tag == EXTERNAL || edge->tag >= FLAT) return true;\n  if (edge->tag == SUBSTRING) edge = edge->substring()->child;\n  return edge->tag == EXTERNAL || edge->tag >= FLAT;\n}\n\n// Returns the `absl::string_view` data reference for the provided data edge.\n// Requires 'IsDataEdge(edge) == true`.\ninline absl::string_view EdgeData(const CordRep* edge) {\n  assert(IsDataEdge(edge));\n\n  size_t offset = 0;\n  const size_t length = edge->length;\n  if (edge->IsSubstring()) {\n    offset = edge->substring()->start;\n    edge = edge->substring()->child;\n  }\n  return edge->tag >= FLAT\n             ? absl::string_view{edge->flat()->Data() + offset, length}\n             : absl::string_view{edge->external()->base + offset, length};\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_DATA_EDGE_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_data_edge_test.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_data_edge.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_test_util.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::absl::cordrep_testing::MakeExternal;\nusing ::absl::cordrep_testing::MakeFlat;\nusing ::absl::cordrep_testing::MakeSubstring;\n\nTEST(CordDataEdgeTest, IsDataEdgeOnFlat) {\n  CordRep* rep = MakeFlat(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  EXPECT_TRUE(IsDataEdge(rep));\n  CordRep::Unref(rep);\n}\n\nTEST(CordDataEdgeTest, IsDataEdgeOnExternal) {\n  CordRep* rep = MakeExternal(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  EXPECT_TRUE(IsDataEdge(rep));\n  CordRep::Unref(rep);\n}\n\nTEST(CordDataEdgeTest, IsDataEdgeOnSubstringOfFlat) {\n  CordRep* rep = MakeFlat(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  CordRep* substr = MakeSubstring(1, 20, rep);\n  EXPECT_TRUE(IsDataEdge(substr));\n  CordRep::Unref(substr);\n}\n\nTEST(CordDataEdgeTest, IsDataEdgeOnSubstringOfExternal) {\n  CordRep* rep = MakeExternal(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  CordRep* substr = MakeSubstring(1, 20, rep);\n  EXPECT_TRUE(IsDataEdge(substr));\n  CordRep::Unref(substr);\n}\n\nTEST(CordDataEdgeTest, IsDataEdgeOnBtree) {\n  CordRep* rep = MakeFlat(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  CordRepBtree* tree = CordRepBtree::New(rep);\n  EXPECT_FALSE(IsDataEdge(tree));\n  CordRep::Unref(tree);\n}\n\nTEST(CordDataEdgeTest, IsDataEdgeOnBadSubstr) {\n  CordRep* rep = MakeFlat(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  CordRep* substr = MakeSubstring(1, 18, MakeSubstring(1, 20, rep));\n  EXPECT_FALSE(IsDataEdge(substr));\n  CordRep::Unref(substr);\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnFlat) {\n  absl::string_view value = \"Lorem ipsum dolor sit amet, consectetur ...\";\n  CordRep* rep = MakeFlat(value);\n  EXPECT_EQ(EdgeData(rep), value);\n  CordRep::Unref(rep);\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnExternal) {\n  absl::string_view value = \"Lorem ipsum dolor sit amet, consectetur ...\";\n  CordRep* rep = MakeExternal(value);\n  EXPECT_EQ(EdgeData(rep), value);\n  CordRep::Unref(rep);\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnSubstringOfFlat) {\n  absl::string_view value = \"Lorem ipsum dolor sit amet, consectetur ...\";\n  CordRep* rep = MakeFlat(value);\n  CordRep* substr = MakeSubstring(1, 20, rep);\n  EXPECT_EQ(EdgeData(substr), value.substr(1, 20));\n  CordRep::Unref(substr);\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnSubstringOfExternal) {\n  absl::string_view value = \"Lorem ipsum dolor sit amet, consectetur ...\";\n  CordRep* rep = MakeExternal(value);\n  CordRep* substr = MakeSubstring(1, 20, rep);\n  EXPECT_EQ(EdgeData(substr), value.substr(1, 20));\n  CordRep::Unref(substr);\n}\n\n#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n\nTEST(CordDataEdgeTest, IsDataEdgeOnNullPtr) {\n  EXPECT_DEATH(IsDataEdge(nullptr), \".*\");\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnNullPtr) {\n  EXPECT_DEATH(EdgeData(nullptr), \".*\");\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnBtree) {\n  CordRep* rep = MakeFlat(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  CordRepBtree* tree = CordRepBtree::New(rep);\n  EXPECT_DEATH(EdgeData(tree), \".*\");\n  CordRep::Unref(tree);\n}\n\nTEST(CordDataEdgeTest, EdgeDataOnBadSubstr) {\n  CordRep* rep = MakeFlat(\"Lorem ipsum dolor sit amet, consectetur ...\");\n  CordRep* substr = MakeSubstring(1, 18, MakeSubstring(1, 20, rep));\n  EXPECT_DEATH(EdgeData(substr), \".*\");\n  CordRep::Unref(substr);\n}\n\n#endif  // GTEST_HAS_DEATH_TEST && !NDEBUG\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_internal.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/strings/internal/cord_internal.h\"\n\n#include <atomic>\n#include <cassert>\n#include <memory>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled(\n    kCordShallowSubcordsDefault);\n\nvoid LogFatalNodeType(CordRep* rep) {\n  ABSL_INTERNAL_LOG(FATAL, absl::StrCat(\"Unexpected node type: \",\n                                        static_cast<int>(rep->tag)));\n}\n\nvoid CordRep::Destroy(CordRep* rep) {\n  assert(rep != nullptr);\n\n  while (true) {\n    assert(!rep->refcount.IsImmortal());\n    if (rep->tag == BTREE) {\n      CordRepBtree::Destroy(rep->btree());\n      return;\n    } else if (rep->tag == EXTERNAL) {\n      CordRepExternal::Delete(rep);\n      return;\n    } else if (rep->tag == SUBSTRING) {\n      CordRepSubstring* rep_substring = rep->substring();\n      rep = rep_substring->child;\n      delete rep_substring;\n      if (rep->refcount.Decrement()) {\n        return;\n      }\n    } else if (rep->tag == CRC) {\n      CordRepCrc::Destroy(rep->crc());\n      return;\n    } else {\n      assert(rep->IsFlat());\n      CordRepFlat::Delete(rep);\n      return;\n    }\n  }\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_internal.h",
    "content": "// Copyright 2021 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_\n#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_\n\n#include <atomic>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/container/internal/compressed_tuple.h\"\n#include \"absl/container/internal/container_memory.h\"\n#include \"absl/strings/string_view.h\"\n\n// We can only add poisoning if we can detect consteval executions.\n#if defined(ABSL_HAVE_CONSTANT_EVALUATED) && \\\n    (defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n     defined(ABSL_HAVE_MEMORY_SANITIZER))\n#define ABSL_INTERNAL_CORD_HAVE_SANITIZER 1\n#endif\n\n#define ABSL_CORD_INTERNAL_NO_SANITIZE \\\n  ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// The overhead of a vtable is too much for Cord, so we roll our own subclasses\n// using only a single byte to differentiate classes from each other - the \"tag\"\n// byte.  Define the subclasses first so we can provide downcasting helper\n// functions in the base class.\nstruct CordRep;\nstruct CordRepConcat;\nstruct CordRepExternal;\nstruct CordRepFlat;\nstruct CordRepSubstring;\nstruct CordRepCrc;\nclass CordRepBtree;\n\nclass CordzInfo;\n\n// Default feature enable states for cord ring buffers\nenum CordFeatureDefaults { kCordShallowSubcordsDefault = false };\n\nextern std::atomic<bool> shallow_subcords_enabled;\n\ninline void enable_shallow_subcords(bool enable) {\n  shallow_subcords_enabled.store(enable, std::memory_order_relaxed);\n}\n\nenum Constants {\n  // The inlined size to use with absl::InlinedVector.\n  //\n  // Note: The InlinedVectors in this file (and in cord.h) do not need to use\n  // the same value for their inlined size. The fact that they do is historical.\n  // It may be desirable for each to use a different inlined size optimized for\n  // that InlinedVector's usage.\n  //\n  // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for\n  // the inlined vector size (47 exists for backward compatibility).\n  kInlinedVectorSize = 47,\n\n  // Prefer copying blocks of at most this size, otherwise reference count.\n  kMaxBytesToCopy = 511\n};\n\n// Emits a fatal error \"Unexpected node type: xyz\" and aborts the program.\n[[noreturn]] void LogFatalNodeType(CordRep* rep);\n\n// Fast implementation of memmove for up to 15 bytes. This implementation is\n// safe for overlapping regions. If nullify_tail is true, the destination is\n// padded with '\\0' up to 15 bytes.\ntemplate <bool nullify_tail = false>\ninline void SmallMemmove(char* dst, const char* src, size_t n) {\n  if (n >= 8) {\n    assert(n <= 15);\n    uint64_t buf1;\n    uint64_t buf2;\n    memcpy(&buf1, src, 8);\n    memcpy(&buf2, src + n - 8, 8);\n    if (nullify_tail) {\n      memset(dst + 7, 0, 8);\n    }\n    // GCC 12 has a false-positive -Wstringop-overflow warning here.\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n#endif\n    memcpy(dst, &buf1, 8);\n    memcpy(dst + n - 8, &buf2, 8);\n#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)\n#pragma GCC diagnostic pop\n#endif\n  } else if (n >= 4) {\n    uint32_t buf1;\n    uint32_t buf2;\n    memcpy(&buf1, src, 4);\n    memcpy(&buf2, src + n - 4, 4);\n    if (nullify_tail) {\n      memset(dst + 4, 0, 4);\n      memset(dst + 7, 0, 8);\n    }\n    memcpy(dst, &buf1, 4);\n    memcpy(dst + n - 4, &buf2, 4);\n  } else {\n    if (n != 0) {\n      dst[0] = src[0];\n      dst[n / 2] = src[n / 2];\n      dst[n - 1] = src[n - 1];\n    }\n    if (nullify_tail) {\n      memset(dst + 7, 0, 8);\n      memset(dst + n, 0, 8);\n    }\n  }\n}\n\n// Compact class for tracking the reference count and state flags for CordRep\n// instances.  Data is stored in an atomic int32_t for compactness and speed.\nclass RefcountAndFlags {\n public:\n  constexpr RefcountAndFlags() : count_{kRefIncrement} {}\n  struct Immortal {};\n  explicit constexpr RefcountAndFlags(Immortal) : count_(kImmortalFlag) {}\n\n  // Increments the reference count. Imposes no memory ordering.\n  inline void Increment() {\n    count_.fetch_add(kRefIncrement, std::memory_order_relaxed);\n  }\n\n  // Asserts that the current refcount is greater than 0. If the refcount is\n  // greater than 1, decrements the reference count.\n  //\n  // Returns false if there are no references outstanding; true otherwise.\n  // Inserts barriers to ensure that state written before this method returns\n  // false will be visible to a thread that just observed this method returning\n  // false.  Always returns false when the immortal bit is set.\n  inline bool Decrement() {\n    int32_t refcount = count_.load(std::memory_order_acquire);\n    assert(refcount > 0 || refcount & kImmortalFlag);\n    return refcount != kRefIncrement &&\n           count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=\n               kRefIncrement;\n  }\n\n  // Same as Decrement but expect that refcount is greater than 1.\n  inline bool DecrementExpectHighRefcount() {\n    int32_t refcount =\n        count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);\n    assert(refcount > 0 || refcount & kImmortalFlag);\n    return refcount != kRefIncrement;\n  }\n\n  // Returns the current reference count using acquire semantics.\n  inline size_t Get() const {\n    return static_cast<size_t>(count_.load(std::memory_order_acquire) >>\n                               kNumFlags);\n  }\n\n  // Returns whether the atomic integer is 1.\n  // If the reference count is used in the conventional way, a\n  // reference count of 1 implies that the current thread owns the\n  // reference and no other thread shares it.\n  // This call performs the test for a reference count of one, and\n  // performs the memory barrier needed for the owning thread\n  // to act on the object, knowing that it has exclusive access to the\n  // object. Always returns false when the immortal bit is set.\n  inline bool IsOne() {\n    return count_.load(std::memory_order_acquire) == kRefIncrement;\n  }\n\n  bool IsImmortal() const {\n    return (count_.load(std::memory_order_relaxed) & kImmortalFlag) != 0;\n  }\n\n private:\n  // We reserve the bottom bit for flag.\n  // kImmortalBit indicates that this entity should never be collected; it is\n  // used for the StringConstant constructor to avoid collecting immutable\n  // constant cords.\n  enum Flags {\n    kNumFlags = 1,\n\n    kImmortalFlag = 0x1,\n    kRefIncrement = (1 << kNumFlags),\n  };\n\n  std::atomic<int32_t> count_;\n};\n\n// Various representations that we allow\nenum CordRepKind {\n  UNUSED_0 = 0,\n  SUBSTRING = 1,\n  CRC = 2,\n  BTREE = 3,\n  UNUSED_4 = 4,\n  EXTERNAL = 5,\n\n  // We have different tags for different sized flat arrays,\n  // starting with FLAT, and limited to MAX_FLAT_TAG. The below values map to an\n  // allocated range of 32 bytes to 256 KB. The current granularity is:\n  // - 8 byte granularity for flat sizes in [32 - 512]\n  // - 64 byte granularity for flat sizes in (512 - 8KiB]\n  // - 4KiB byte granularity for flat sizes in (8KiB, 256 KiB]\n  // If a new tag is needed in the future, then 'FLAT' and 'MAX_FLAT_TAG' should\n  // be adjusted as well as the Tag <---> Size mapping logic so that FLAT still\n  // represents the minimum flat allocation size. (32 bytes as of now).\n  FLAT = 6,\n  MAX_FLAT_TAG = 248\n};\n\n// There are various locations where we want to check if some rep is a 'plain'\n// data edge, i.e. an external or flat rep. By having FLAT == EXTERNAL + 1, we\n// can perform this check in a single branch as 'tag >= EXTERNAL'\n// Note that we can leave this optimization to the compiler. The compiler will\n// DTRT when it sees a condition like `tag == EXTERNAL || tag >= FLAT`.\nstatic_assert(FLAT == EXTERNAL + 1, \"EXTERNAL and FLAT not consecutive\");\n\nstruct CordRep {\n  // Result from an `extract edge` operation. Contains the (possibly changed)\n  // tree node as well as the extracted edge, or {tree, nullptr} if no edge\n  // could be extracted.\n  // On success, the returned `tree` value is null if `extracted` was the only\n  // data edge inside the tree, a data edge if there were only two data edges in\n  // the tree, or the (possibly new / smaller) remaining tree with the extracted\n  // data edge removed.\n  struct ExtractResult {\n    CordRep* tree;\n    CordRep* extracted;\n  };\n\n  CordRep() = default;\n  constexpr CordRep(RefcountAndFlags::Immortal immortal, size_t l)\n      : length(l), refcount(immortal), tag(EXTERNAL), storage{} {}\n\n  // The following three fields have to be less than 32 bytes since\n  // that is the smallest supported flat node size. Some code optimizations rely\n  // on the specific layout of these fields. Notably: the non-trivial field\n  // `refcount` being preceded by `length`, and being tailed by POD data\n  // members only.\n  // LINT.IfChange\n  size_t length;\n  RefcountAndFlags refcount;\n  // If tag < FLAT, it represents CordRepKind and indicates the type of node.\n  // Otherwise, the node type is CordRepFlat and the tag is the encoded size.\n  uint8_t tag;\n\n  // `storage` provides two main purposes:\n  // - the starting point for FlatCordRep.Data() [flexible-array-member]\n  // - 3 bytes of additional storage for use by derived classes.\n  // The latter is used by CordrepConcat and CordRepBtree. CordRepConcat stores\n  // a 'depth' value in storage[0], and the (future) CordRepBtree class stores\n  // `height`, `begin` and `end` in the 3 entries. Otherwise we would need to\n  // allocate room for these in the derived class, as not all compilers reuse\n  // padding space from the base class (clang and gcc do, MSVC does not, etc)\n  uint8_t storage[3];\n  // LINT.ThenChange(cord_rep_btree.h:copy_raw)\n\n  // Returns true if this instance's tag matches the requested type.\n  constexpr bool IsSubstring() const { return tag == SUBSTRING; }\n  constexpr bool IsCrc() const { return tag == CRC; }\n  constexpr bool IsExternal() const { return tag == EXTERNAL; }\n  constexpr bool IsFlat() const { return tag >= FLAT; }\n  constexpr bool IsBtree() const { return tag == BTREE; }\n\n  inline CordRepSubstring* substring();\n  inline const CordRepSubstring* substring() const;\n  inline CordRepCrc* crc();\n  inline const CordRepCrc* crc() const;\n  inline CordRepExternal* external();\n  inline const CordRepExternal* external() const;\n  inline CordRepFlat* flat();\n  inline const CordRepFlat* flat() const;\n  inline CordRepBtree* btree();\n  inline const CordRepBtree* btree() const;\n\n  // --------------------------------------------------------------------\n  // Memory management\n\n  // Destroys the provided `rep`.\n  static void Destroy(CordRep* rep);\n\n  // Increments the reference count of `rep`.\n  // Requires `rep` to be a non-null pointer value.\n  static inline CordRep* Ref(CordRep* rep);\n\n  // Decrements the reference count of `rep`. Destroys rep if count reaches\n  // zero. Requires `rep` to be a non-null pointer value.\n  static inline void Unref(CordRep* rep);\n};\n\nstruct CordRepSubstring : public CordRep {\n  size_t start;  // Starting offset of substring in child\n  CordRep* child;\n\n  // Creates a substring on `child`, adopting a reference on `child`.\n  // Requires `child` to be either a flat or external node, and `pos` and `n` to\n  // form a non-empty partial sub range of `'child`, i.e.:\n  // `n > 0 && n < length && n + pos <= length`\n  static inline CordRepSubstring* Create(CordRep* child, size_t pos, size_t n);\n\n  // Creates a substring of `rep`. Does not adopt a reference on `rep`.\n  // Requires `IsDataEdge(rep) && n > 0 && pos + n <= rep->length`.\n  // If `n == rep->length` then this method returns `CordRep::Ref(rep)`\n  // If `rep` is a substring of a flat or external node, then this method will\n  // return a new substring of that flat or external node with `pos` adjusted\n  // with the original `start` position.\n  static inline CordRep* Substring(CordRep* rep, size_t pos, size_t n);\n};\n\n// Type for function pointer that will invoke the releaser function and also\n// delete the `CordRepExternalImpl` corresponding to the passed in\n// `CordRepExternal`.\nusing ExternalReleaserInvoker = void (*)(CordRepExternal*);\n\n// External CordReps are allocated together with a type erased releaser. The\n// releaser is stored in the memory directly following the CordRepExternal.\nstruct CordRepExternal : public CordRep {\n  CordRepExternal() = default;\n  explicit constexpr CordRepExternal(absl::string_view str)\n      : CordRep(RefcountAndFlags::Immortal{}, str.size()),\n        base(str.data()),\n        releaser_invoker(nullptr) {}\n\n  const char* base;\n  // Pointer to function that knows how to call and destroy the releaser.\n  ExternalReleaserInvoker releaser_invoker;\n\n  // Deletes (releases) the external rep.\n  // Requires rep != nullptr and rep->IsExternal()\n  static void Delete(CordRep* rep);\n};\n\n// Use go/ranked-overloads for dispatching.\nstruct Rank0 {};\nstruct Rank1 : Rank0 {};\n\ntemplate <typename Releaser,\n          typename = ::std::invoke_result_t<Releaser, absl::string_view>>\nvoid InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view data) {\n  ::std::invoke(std::forward<Releaser>(releaser), data);\n}\n\ntemplate <typename Releaser, typename = ::std::invoke_result_t<Releaser>>\nvoid InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view) {\n  ::std::invoke(std::forward<Releaser>(releaser));\n}\n\n// We use CompressedTuple so that we can benefit from EBCO.\ntemplate <typename Releaser>\nstruct CordRepExternalImpl\n    : public CordRepExternal,\n      public ::absl::container_internal::CompressedTuple<Releaser> {\n  // The extra int arg is so that we can avoid interfering with copy/move\n  // constructors while still benefitting from perfect forwarding.\n  template <typename T>\n  CordRepExternalImpl(T&& releaser, int)\n      : CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {\n    this->releaser_invoker = &Release;\n  }\n\n  const Releaser* releaser() const { return &this->template get<0>(); }\n\n  ~CordRepExternalImpl() {\n    InvokeReleaser(Rank1{}, std::move(this->template get<0>()),\n                   absl::string_view(base, length));\n  }\n\n  static void Release(CordRepExternal* rep) {\n    delete static_cast<CordRepExternalImpl*>(rep);\n  }\n};\n\ninline CordRepSubstring* CordRepSubstring::Create(CordRep* child, size_t pos,\n                                                  size_t n) {\n  assert(child != nullptr);\n  assert(n > 0);\n  assert(n < child->length);\n  assert(pos < child->length);\n  assert(n <= child->length - pos);\n\n  // Move to strategical places inside the Cord logic and make this an assert.\n  if (ABSL_PREDICT_FALSE(!(child->IsExternal() || child->IsFlat()))) {\n    LogFatalNodeType(child);\n  }\n\n  CordRepSubstring* rep = new CordRepSubstring();\n  rep->length = n;\n  rep->tag = SUBSTRING;\n  rep->start = pos;\n  rep->child = child;\n  return rep;\n}\n\ninline CordRep* CordRepSubstring::Substring(CordRep* rep, size_t pos,\n                                            size_t n) {\n  assert(rep != nullptr);\n  assert(n != 0);\n  assert(pos < rep->length);\n  assert(n <= rep->length - pos);\n  if (n == rep->length) return CordRep::Ref(rep);\n  if (rep->IsSubstring()) {\n    pos += rep->substring()->start;\n    rep = rep->substring()->child;\n  }\n  CordRepSubstring* substr = new CordRepSubstring();\n  substr->length = n;\n  substr->tag = SUBSTRING;\n  substr->start = pos;\n  substr->child = CordRep::Ref(rep);\n  return substr;\n}\n\ninline void CordRepExternal::Delete(CordRep* rep) {\n  assert(rep != nullptr && rep->IsExternal());\n  auto* rep_external = static_cast<CordRepExternal*>(rep);\n  assert(rep_external->releaser_invoker != nullptr);\n  rep_external->releaser_invoker(rep_external);\n}\n\ntemplate <typename Str>\nstruct ConstInitExternalStorage {\n  ABSL_CONST_INIT static CordRepExternal value;\n};\n\ntemplate <typename Str>\nABSL_CONST_INIT CordRepExternal\n    ConstInitExternalStorage<Str>::value(Str::value);\n\nenum {\n  kMaxInline = 15,\n};\n\nconstexpr char GetOrNull(absl::string_view data, size_t pos) {\n  return pos < data.size() ? data[pos] : '\\0';\n}\n\n// We store cordz_info as 64 bit pointer value in little endian format. This\n// guarantees that the least significant byte of cordz_info matches the first\n// byte of the inline data representation in `data`, which holds the inlined\n// size or the 'is_tree' bit.\nusing cordz_info_t = int64_t;\n\n// Assert that the `cordz_info` pointer value perfectly overlaps the last half\n// of `data` and can hold a pointer value.\nstatic_assert(sizeof(cordz_info_t) * 2 == kMaxInline + 1, \"\");\nstatic_assert(sizeof(cordz_info_t) >= sizeof(intptr_t), \"\");\n\n// LittleEndianByte() creates a little endian representation of 'value', i.e.:\n// a little endian value where the first byte in the host's representation\n// holds 'value`, with all other bytes being 0.\nstatic constexpr cordz_info_t LittleEndianByte(unsigned char value) {\n#if defined(ABSL_IS_BIG_ENDIAN)\n  return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);\n#else\n  return value;\n#endif\n}\n\nclass InlineData {\n public:\n  // DefaultInitType forces the use of the default initialization constructor.\n  enum DefaultInitType { kDefaultInit };\n\n  // kNullCordzInfo holds the little endian representation of intptr_t(1)\n  // This is the 'null' / initial value of 'cordz_info'. The null value\n  // is specifically big endian 1 as with 64-bit pointers, the last\n  // byte of cordz_info overlaps with the last byte holding the tag.\n  static constexpr cordz_info_t kNullCordzInfo = LittleEndianByte(1);\n\n  // kTagOffset contains the offset of the control byte / tag. This constant is\n  // intended mostly for debugging purposes: do not remove this constant as it\n  // is actively inspected and used by gdb pretty printing code.\n  static constexpr size_t kTagOffset = 0;\n\n  // Implement `~InlineData()` conditionally: we only need this destructor to\n  // unpoison poisoned instances under *SAN, and it will only compile correctly\n  // if the current compiler supports `absl::is_constant_evaluated()`.\n#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER\n  ~InlineData() noexcept { unpoison(); }\n#endif\n\n  constexpr InlineData() noexcept { poison_this(); }\n\n  explicit InlineData(DefaultInitType) noexcept : rep_(kDefaultInit) {\n    poison_this();\n  }\n\n  explicit InlineData(CordRep* rep) noexcept : rep_(rep) {\n    ABSL_ASSERT(rep != nullptr);\n  }\n\n  // Explicit constexpr constructor to create a constexpr InlineData\n  // value. Creates an inlined SSO value if `rep` is null, otherwise\n  // creates a tree instance value.\n  constexpr InlineData(absl::string_view sv, CordRep* rep) noexcept\n      : rep_(rep ? Rep(rep) : Rep(sv)) {\n    poison();\n  }\n\n  constexpr InlineData(const InlineData& rhs) noexcept;\n  InlineData& operator=(const InlineData& rhs) noexcept;\n  friend void swap(InlineData& lhs, InlineData& rhs) noexcept;\n\n  friend bool operator==(const InlineData& lhs, const InlineData& rhs) {\n#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER\n    const Rep l = lhs.rep_.SanitizerSafeCopy();\n    const Rep r = rhs.rep_.SanitizerSafeCopy();\n    return memcmp(&l, &r, sizeof(l)) == 0;\n#else\n    return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;\n#endif\n  }\n  friend bool operator!=(const InlineData& lhs, const InlineData& rhs) {\n    return !operator==(lhs, rhs);\n  }\n\n  // Poisons the unused inlined SSO data if the current instance\n  // is inlined, else un-poisons the entire instance.\n  constexpr void poison();\n\n  // Un-poisons this instance.\n  constexpr void unpoison();\n\n  // Poisons the current instance. This is used on default initialization.\n  constexpr void poison_this();\n\n  // Returns true if the current instance is empty.\n  // The 'empty value' is an inlined data value of zero length.\n  bool is_empty() const { return rep_.tag() == 0; }\n\n  // Returns true if the current instance holds a tree value.\n  bool is_tree() const { return (rep_.tag() & 1) != 0; }\n\n  // Returns true if the current instance holds a cordz_info value.\n  // Requires the current instance to hold a tree value.\n  bool is_profiled() const {\n    assert(is_tree());\n    return rep_.cordz_info() != kNullCordzInfo;\n  }\n\n  // Returns true if either of the provided instances hold a cordz_info value.\n  // This method is more efficient than the equivalent `data1.is_profiled() ||\n  // data2.is_profiled()`. Requires both arguments to hold a tree.\n  static bool is_either_profiled(const InlineData& data1,\n                                 const InlineData& data2) {\n    assert(data1.is_tree() && data2.is_tree());\n    return (data1.rep_.cordz_info() | data2.rep_.cordz_info()) !=\n           kNullCordzInfo;\n  }\n\n  // Returns the cordz_info sampling instance for this instance, or nullptr\n  // if the current instance is not sampled and does not have CordzInfo data.\n  // Requires the current instance to hold a tree value.\n  CordzInfo* cordz_info() const {\n    assert(is_tree());\n    intptr_t info = static_cast<intptr_t>(absl::little_endian::ToHost64(\n        static_cast<uint64_t>(rep_.cordz_info())));\n    assert(info & 1);\n    return reinterpret_cast<CordzInfo*>(info - 1);\n  }\n\n  // Sets the current cordz_info sampling instance for this instance, or nullptr\n  // if the current instance is not sampled and does not have CordzInfo data.\n  // Requires the current instance to hold a tree value.\n  void set_cordz_info(CordzInfo* cordz_info) {\n    assert(is_tree());\n    uintptr_t info = reinterpret_cast<uintptr_t>(cordz_info) | 1;\n    rep_.set_cordz_info(\n        static_cast<cordz_info_t>(absl::little_endian::FromHost64(info)));\n  }\n\n  // Resets the current cordz_info to null / empty.\n  void clear_cordz_info() {\n    assert(is_tree());\n    rep_.set_cordz_info(kNullCordzInfo);\n  }\n\n  // Returns a read only pointer to the character data inside this instance.\n  // Requires the current instance to hold inline data.\n  const char* as_chars() const {\n    assert(!is_tree());\n    return rep_.as_chars();\n  }\n\n  // Returns a mutable pointer to the character data inside this instance.\n  // Should be used for 'write only' operations setting an inlined value.\n  // Applications can set the value of inlined data either before or after\n  // setting the inlined size, i.e., both of the below are valid:\n  //\n  //   // Set inlined data and inline size\n  //   memcpy(data_.as_chars(), data, size);\n  //   data_.set_inline_size(size);\n  //\n  //   // Set inlined size and inline data\n  //   data_.set_inline_size(size);\n  //   memcpy(data_.as_chars(), data, size);\n  //\n  // It's an error to read from the returned pointer without a preceding write\n  // if the current instance does not hold inline data, i.e.: is_tree() == true.\n  char* as_chars() { return rep_.as_chars(); }\n\n  // Returns the tree value of this value.\n  // Requires the current instance to hold a tree value.\n  CordRep* as_tree() const {\n    assert(is_tree());\n    return rep_.tree();\n  }\n\n  void set_inline_data(const char* data, size_t n) {\n    ABSL_ASSERT(n <= kMaxInline);\n    unpoison();\n    rep_.set_tag(static_cast<int8_t>(n << 1));\n    SmallMemmove<true>(rep_.as_chars(), data, n);\n    poison();\n  }\n\n  void CopyInlineToString(std::string* dst) const {\n    assert(!is_tree());\n    // As Cord can store only 15 bytes it is smaller than std::string's\n    // small string optimization buffer size. Therefore we will always trigger\n    // the fast assign short path.\n    //\n    // Copying with a size equal to the maximum allows more efficient, wider\n    // stores to be used and no branching.\n    dst->assign(rep_.SanitizerSafeCopy().as_chars(), kMaxInline);\n    // After the copy we then change the size and put in a 0 byte.\n    dst->erase(inline_size());\n  }\n\n  void copy_max_inline_to(char* dst) const {\n    assert(!is_tree());\n    memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline);\n  }\n\n  // Initialize this instance to holding the tree value `rep`,\n  // initializing the cordz_info to null, i.e.: 'not profiled'.\n  void make_tree(CordRep* rep) {\n    unpoison();\n    rep_.make_tree(rep);\n  }\n\n  // Set the tree value of this instance to 'rep`.\n  // Requires the current instance to already hold a tree value.\n  // Does not affect the value of cordz_info.\n  void set_tree(CordRep* rep) {\n    assert(is_tree());\n    rep_.set_tree(rep);\n  }\n\n  // Returns the size of the inlined character data inside this instance.\n  // Requires the current instance to hold inline data.\n  size_t inline_size() const { return rep_.inline_size(); }\n\n  // Sets the size of the inlined character data inside this instance.\n  // Requires `size` to be <= kMaxInline.\n  // See the documentation on 'as_chars()' for more information and examples.\n  void set_inline_size(size_t size) {\n    unpoison();\n    rep_.set_inline_size(size);\n    poison();\n  }\n\n  // Compares 'this' inlined data  with rhs. The comparison is a straightforward\n  // lexicographic comparison. `Compare()` returns values as follows:\n  //\n  //   -1  'this' InlineData instance is smaller\n  //    0  the InlineData instances are equal\n  //    1  'this' InlineData instance larger\n  int Compare(const InlineData& rhs) const {\n    return Compare(rep_.SanitizerSafeCopy(), rhs.rep_.SanitizerSafeCopy());\n  }\n\n private:\n  struct Rep {\n    // See cordz_info_t for forced alignment and size of `cordz_info` details.\n    struct AsTree {\n      explicit constexpr AsTree(absl::cord_internal::CordRep* tree)\n          : rep(tree) {}\n      cordz_info_t cordz_info = kNullCordzInfo;\n      absl::cord_internal::CordRep* rep;\n    };\n\n    explicit Rep(DefaultInitType) {}\n    constexpr Rep() : data{0} {}\n    constexpr Rep(const Rep&) = default;\n    constexpr Rep& operator=(const Rep&) = default;\n\n    explicit constexpr Rep(CordRep* rep) : as_tree(rep) {}\n\n    explicit constexpr Rep(absl::string_view chars)\n        : data{static_cast<char>((chars.size() << 1)),\n               GetOrNull(chars, 0),\n               GetOrNull(chars, 1),\n               GetOrNull(chars, 2),\n               GetOrNull(chars, 3),\n               GetOrNull(chars, 4),\n               GetOrNull(chars, 5),\n               GetOrNull(chars, 6),\n               GetOrNull(chars, 7),\n               GetOrNull(chars, 8),\n               GetOrNull(chars, 9),\n               GetOrNull(chars, 10),\n               GetOrNull(chars, 11),\n               GetOrNull(chars, 12),\n               GetOrNull(chars, 13),\n               GetOrNull(chars, 14)} {}\n\n#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER\n    // Break compiler optimization for cases when value is allocated on the\n    // stack. Compiler assumes that the the variable is fully accessible\n    // regardless of our poisoning.\n    // Missing report: https://github.com/llvm/llvm-project/issues/100640\n    const Rep* self() const {\n      const Rep* volatile ptr = this;\n      return ptr;\n    }\n    Rep* self() {\n      Rep* volatile ptr = this;\n      return ptr;\n    }\n#else\n    constexpr const Rep* self() const { return this; }\n    constexpr Rep* self() { return this; }\n#endif\n\n    // Disable sanitizer as we must always be able to read `tag`.\n    ABSL_CORD_INTERNAL_NO_SANITIZE\n    int8_t tag() const { return reinterpret_cast<const int8_t*>(this)[0]; }\n    void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(self())[0] = rhs; }\n\n    char* as_chars() { return self()->data + 1; }\n    const char* as_chars() const { return self()->data + 1; }\n\n    bool is_tree() const { return (self()->tag() & 1) != 0; }\n\n    size_t inline_size() const {\n      ABSL_ASSERT(!self()->is_tree());\n      return static_cast<size_t>(self()->tag()) >> 1;\n    }\n\n    void set_inline_size(size_t size) {\n      ABSL_ASSERT(size <= kMaxInline);\n      self()->set_tag(static_cast<int8_t>(size << 1));\n    }\n\n    CordRep* tree() const { return self()->as_tree.rep; }\n    void set_tree(CordRep* rhs) { self()->as_tree.rep = rhs; }\n\n    cordz_info_t cordz_info() const { return self()->as_tree.cordz_info; }\n    void set_cordz_info(cordz_info_t rhs) { self()->as_tree.cordz_info = rhs; }\n\n    void make_tree(CordRep* tree) {\n      self()->as_tree.rep = tree;\n      self()->as_tree.cordz_info = kNullCordzInfo;\n    }\n\n#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER\n    constexpr Rep SanitizerSafeCopy() const {\n      if (!absl::is_constant_evaluated()) {\n        Rep res;\n        if (is_tree()) {\n          res = *this;\n        } else {\n          res.set_tag(tag());\n          memcpy(res.as_chars(), as_chars(), inline_size());\n        }\n        return res;\n      } else {\n        return *this;\n      }\n    }\n#else\n    constexpr const Rep& SanitizerSafeCopy() const { return *this; }\n#endif\n\n    // If the data has length <= kMaxInline, we store it in `data`, and\n    // store the size in the first char of `data` shifted left + 1.\n    // Else we store it in a tree and store a pointer to that tree in\n    // `as_tree.rep` with a tagged pointer to make `tag() & 1` non zero.\n    union {\n      char data[kMaxInline + 1];\n      AsTree as_tree;\n    };\n\n    // TODO(b/145829486): see swap(InlineData, InlineData) for more info.\n    inline void SwapValue(Rep rhs, Rep& refrhs) {\n      memcpy(&refrhs, this, sizeof(*this));\n      memcpy(this, &rhs, sizeof(*this));\n    }\n  };\n\n  // Private implementation of `Compare()`\n  static inline int Compare(const Rep& lhs, const Rep& rhs) {\n    uint64_t x, y;\n    memcpy(&x, lhs.as_chars(), sizeof(x));\n    memcpy(&y, rhs.as_chars(), sizeof(y));\n    if (x == y) {\n      memcpy(&x, lhs.as_chars() + 7, sizeof(x));\n      memcpy(&y, rhs.as_chars() + 7, sizeof(y));\n      if (x == y) {\n        if (lhs.inline_size() == rhs.inline_size()) return 0;\n        return lhs.inline_size() < rhs.inline_size() ? -1 : 1;\n      }\n    }\n    x = absl::big_endian::FromHost64(x);\n    y = absl::big_endian::FromHost64(y);\n    return x < y ? -1 : 1;\n  }\n\n  Rep rep_;\n};\n\nstatic_assert(sizeof(InlineData) == kMaxInline + 1, \"\");\n\n#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER\n\nconstexpr InlineData::InlineData(const InlineData& rhs) noexcept\n    : rep_(rhs.rep_.SanitizerSafeCopy()) {\n  poison();\n}\n\ninline InlineData& InlineData::operator=(const InlineData& rhs) noexcept {\n  unpoison();\n  rep_ = rhs.rep_.SanitizerSafeCopy();\n  poison();\n  return *this;\n}\n\nconstexpr void InlineData::poison_this() {\n  if (!absl::is_constant_evaluated()) {\n    container_internal::SanitizerPoisonObject(this);\n  }\n}\n\nconstexpr void InlineData::unpoison() {\n  if (!absl::is_constant_evaluated()) {\n    container_internal::SanitizerUnpoisonObject(this);\n  }\n}\n\nconstexpr void InlineData::poison() {\n  if (!absl::is_constant_evaluated()) {\n    if (is_tree()) {\n      container_internal::SanitizerUnpoisonObject(this);\n    } else if (const size_t size = inline_size()) {\n      if (size < kMaxInline) {\n        const char* end = rep_.as_chars() + size;\n        container_internal::SanitizerPoisonMemoryRegion(end, kMaxInline - size);\n      }\n    } else {\n      container_internal::SanitizerPoisonObject(this);\n    }\n  }\n}\n\n#else  // ABSL_INTERNAL_CORD_HAVE_SANITIZER\n\nconstexpr InlineData::InlineData(const InlineData&) noexcept = default;\ninline InlineData& InlineData::operator=(const InlineData&) noexcept = default;\n\nconstexpr void InlineData::poison_this() {}\nconstexpr void InlineData::unpoison() {}\nconstexpr void InlineData::poison() {}\n\n#endif  // ABSL_INTERNAL_CORD_HAVE_SANITIZER\n\ninline CordRepSubstring* CordRep::substring() {\n  assert(IsSubstring());\n  return static_cast<CordRepSubstring*>(this);\n}\n\ninline const CordRepSubstring* CordRep::substring() const {\n  assert(IsSubstring());\n  return static_cast<const CordRepSubstring*>(this);\n}\n\ninline CordRepExternal* CordRep::external() {\n  assert(IsExternal());\n  return static_cast<CordRepExternal*>(this);\n}\n\ninline const CordRepExternal* CordRep::external() const {\n  assert(IsExternal());\n  return static_cast<const CordRepExternal*>(this);\n}\n\ninline CordRep* CordRep::Ref(CordRep* rep) {\n  // ABSL_ASSUME is a workaround for\n  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105585\n  ABSL_ASSUME(rep != nullptr);\n  rep->refcount.Increment();\n  return rep;\n}\n\ninline void CordRep::Unref(CordRep* rep) {\n  assert(rep != nullptr);\n  if (ABSL_PREDICT_FALSE(!rep->refcount.DecrementExpectHighRefcount())) {\n    Destroy(rep);\n  }\n}\n\ninline void swap(InlineData& lhs, InlineData& rhs) noexcept {\n  lhs.unpoison();\n  rhs.unpoison();\n  // TODO(b/145829486): `std::swap(lhs.rep_, rhs.rep_)` results in bad codegen\n  // on clang, spilling the temporary swap value on the stack. Since `Rep` is\n  // trivial, we can make clang DTRT by calling a hand-rolled `SwapValue` where\n  // we pass `rhs` both by value (register allocated) and by reference. The IR\n  // then folds and inlines correctly into an optimized swap without spill.\n  lhs.rep_.SwapValue(rhs.rep_, rhs.rep_);\n  rhs.poison();\n  lhs.poison();\n}\n\n}  // namespace cord_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_btree.h\"\n\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n#include <iostream>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_consume.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nnamespace {\n\nusing NodeStack = CordRepBtree * [CordRepBtree::kMaxDepth];\nusing EdgeType = CordRepBtree::EdgeType;\nusing OpResult = CordRepBtree::OpResult;\nusing CopyResult = CordRepBtree::CopyResult;\n\nconstexpr auto kFront = CordRepBtree::kFront;\nconstexpr auto kBack = CordRepBtree::kBack;\n\nABSL_CONST_INIT std::atomic<bool> cord_btree_exhaustive_validation(false);\n\n// Implementation of the various 'Dump' functions.\n// Prints the entire tree structure or 'rep'. External callers should\n// not specify 'depth' and leave it to its default (0) value.\n// Rep may be a CordRepBtree tree, or a SUBSTRING / EXTERNAL / FLAT node.\nvoid DumpAll(const CordRep* rep,\n             bool include_contents,\n             std::ostream& stream,\n             size_t depth = 0) {\n  // Allow for full height trees + substring -> flat / external nodes.\n  assert(depth <= CordRepBtree::kMaxDepth + 2);\n  std::string sharing = const_cast<CordRep*>(rep)->refcount.IsOne()\n                            ? std::string(\"Private\")\n                            : absl::StrCat(\"Shared(\", rep->refcount.Get(), \")\");\n  std::string sptr = absl::StrCat(\"0x\", absl::Hex(rep));\n\n  // Dumps the data contents of `rep` if `include_contents` is true.\n  // Always emits a new line character.\n  auto maybe_dump_data = [&stream, include_contents](const CordRep* r) {\n    if (include_contents) {\n      // Allow for up to 60 wide display of content data, which with some\n      // indentation and prefix / labels keeps us within roughly 80-100 wide.\n      constexpr size_t kMaxDataLength = 60;\n      stream << \", data = \\\"\"\n             << EdgeData(r).substr(0, kMaxDataLength)\n             << (r->length > kMaxDataLength ? \"\\\"...\" : \"\\\"\");\n    }\n    stream << '\\n';\n  };\n\n  // For each level, we print the 'shared/private' state and the rep pointer,\n  // indented by two spaces per recursive depth.\n  stream << std::string(depth * 2, ' ') << sharing << \" (\" << sptr << \") \";\n\n  if (rep->IsBtree()) {\n    const CordRepBtree* node = rep->btree();\n    std::string label =\n        node->height() ? absl::StrCat(\"Node(\", node->height(), \")\") : \"Leaf\";\n    stream << label << \", len = \" << node->length\n           << \", begin = \" << node->begin() << \", end = \" << node->end()\n           << \"\\n\";\n    for (CordRep* edge : node->Edges()) {\n      DumpAll(edge, include_contents, stream, depth + 1);\n    }\n  } else if (rep->tag == SUBSTRING) {\n    const CordRepSubstring* substring = rep->substring();\n    stream << \"Substring, len = \" << rep->length\n           << \", start = \" << substring->start;\n    maybe_dump_data(rep);\n    DumpAll(substring->child, include_contents, stream, depth + 1);\n  } else if (rep->tag >= FLAT) {\n    stream << \"Flat, len = \" << rep->length\n           << \", cap = \" << rep->flat()->Capacity();\n    maybe_dump_data(rep);\n  } else if (rep->tag == EXTERNAL) {\n    stream << \"Extn, len = \" << rep->length;\n    maybe_dump_data(rep);\n  }\n}\n\n// TODO(b/192061034): add 'bytes to copy' logic to avoid large slop on substring\n// small data out of large reps, and general efficiency of 'always copy small\n// data'. Consider making this a cord rep internal library function.\nCordRepSubstring* CreateSubstring(CordRep* rep, size_t offset, size_t n) {\n  assert(n != 0);\n  assert(offset + n <= rep->length);\n  assert(offset != 0 || n != rep->length);\n\n  if (rep->tag == SUBSTRING) {\n    CordRepSubstring* substring = rep->substring();\n    offset += substring->start;\n    rep = CordRep::Ref(substring->child);\n    CordRep::Unref(substring);\n  }\n  assert(rep->IsExternal() || rep->IsFlat());\n  CordRepSubstring* substring = new CordRepSubstring();\n  substring->length = n;\n  substring->tag = SUBSTRING;\n  substring->start = offset;\n  substring->child = rep;\n  return substring;\n}\n\n// TODO(b/192061034): consider making this a cord rep library function.\ninline CordRep* MakeSubstring(CordRep* rep, size_t offset, size_t n) {\n  if (n == rep->length) return rep;\n  if (n == 0) return CordRep::Unref(rep), nullptr;\n  return CreateSubstring(rep, offset, n);\n}\n\n// TODO(b/192061034): consider making this a cord rep library function.\ninline CordRep* MakeSubstring(CordRep* rep, size_t offset) {\n  if (offset == 0) return rep;\n  return CreateSubstring(rep, offset, rep->length - offset);\n}\n\n// Resizes `edge` to the provided `length`. Adopts a reference on `edge`.\n// This method directly returns `edge` if `length` equals `edge->length`.\n// If `is_mutable` is set to true, this function may return `edge` with\n// `edge->length` set to the new length depending on the type and size of\n// `edge`. Otherwise, this function returns a new CordRepSubstring value.\n// Requires `length > 0 && length <= edge->length`.\nCordRep* ResizeEdge(CordRep* edge, size_t length, bool is_mutable) {\n  assert(length > 0);\n  assert(length <= edge->length);\n  assert(IsDataEdge(edge));\n  if (length >= edge->length) return edge;\n\n  if (is_mutable && (edge->tag >= FLAT || edge->tag == SUBSTRING)) {\n    edge->length = length;\n    return edge;\n  }\n\n  return CreateSubstring(edge, 0, length);\n}\n\ntemplate <EdgeType edge_type>\ninline absl::string_view Consume(absl::string_view s, size_t n) {\n  return edge_type == kBack ? s.substr(n) : s.substr(0, s.size() - n);\n}\n\ntemplate <EdgeType edge_type>\ninline absl::string_view Consume(char* dst, absl::string_view s, size_t n) {\n  if (edge_type == kBack) {\n    memcpy(dst, s.data(), n);\n    return s.substr(n);\n  } else {\n    const size_t offset = s.size() - n;\n    memcpy(dst, s.data() + offset, n);\n    return s.substr(0, offset);\n  }\n}\n\n// Known issue / optimization weirdness: the store associated with the\n// decrement introduces traffic between cpus (even if the result of that\n// traffic does nothing), making this faster than a single call to\n// refcount.Decrement() checking the zero refcount condition.\ntemplate <typename R, typename Fn>\ninline void FastUnref(R* r, Fn&& fn) {\n  if (r->refcount.IsOne()) {\n    fn(r);\n  } else if (!r->refcount.DecrementExpectHighRefcount()) {\n    fn(r);\n  }\n}\n\n\nvoid DeleteSubstring(CordRepSubstring* substring) {\n  CordRep* rep = substring->child;\n  if (!rep->refcount.Decrement()) {\n    if (rep->tag >= FLAT) {\n      CordRepFlat::Delete(rep->flat());\n    } else {\n      assert(rep->tag == EXTERNAL);\n      CordRepExternal::Delete(rep->external());\n    }\n  }\n  delete substring;\n}\n\n// Deletes a leaf node data edge. Requires `IsDataEdge(rep)`.\nvoid DeleteLeafEdge(CordRep* rep) {\n  assert(IsDataEdge(rep));\n  if (rep->tag >= FLAT) {\n    CordRepFlat::Delete(rep->flat());\n  } else if (rep->tag == EXTERNAL) {\n    CordRepExternal::Delete(rep->external());\n  } else {\n    DeleteSubstring(rep->substring());\n  }\n}\n\n// StackOperations contains the logic to build a left-most or right-most stack\n// (leg) down to the leaf level of a btree, and 'unwind' / 'Finalize' methods to\n// propagate node changes up the stack.\ntemplate <EdgeType edge_type>\nstruct StackOperations {\n  // Returns true if the node at 'depth' is not shared, i.e. has a refcount\n  // of one and all of its parent nodes have a refcount of one.\n  inline bool owned(int depth) const { return depth < share_depth; }\n\n  // Returns the node at 'depth'.\n  inline CordRepBtree* node(int depth) const { return stack[depth]; }\n\n  // Builds a `depth` levels deep stack starting at `tree` recording which nodes\n  // are private in the form of the 'share depth' where nodes are shared.\n  inline CordRepBtree* BuildStack(CordRepBtree* tree, int depth) {\n    assert(depth <= tree->height());\n    int current_depth = 0;\n    while (current_depth < depth && tree->refcount.IsOne()) {\n      stack[current_depth++] = tree;\n      tree = tree->Edge(edge_type)->btree();\n    }\n    share_depth = current_depth + (tree->refcount.IsOne() ? 1 : 0);\n    while (current_depth < depth) {\n      stack[current_depth++] = tree;\n      tree = tree->Edge(edge_type)->btree();\n    }\n    return tree;\n  }\n\n  // Builds a stack with the invariant that all nodes are private owned / not\n  // shared. This is used in iterative updates where a previous propagation\n  // guaranteed all nodes are owned / private.\n  inline void BuildOwnedStack(CordRepBtree* tree, int height) {\n    assert(height <= CordRepBtree::kMaxHeight);\n    int depth = 0;\n    while (depth < height) {\n      assert(tree->refcount.IsOne());\n      stack[depth++] = tree;\n      tree = tree->Edge(edge_type)->btree();\n    }\n    assert(tree->refcount.IsOne());\n    share_depth = depth + 1;\n  }\n\n  // Processes the final 'top level' result action for the tree.\n  // See the 'Action' enum for the various action implications.\n  static inline CordRepBtree* Finalize(CordRepBtree* tree, OpResult result) {\n    switch (result.action) {\n      case CordRepBtree::kPopped:\n        tree = edge_type == kBack ? CordRepBtree::New(tree, result.tree)\n                                  : CordRepBtree::New(result.tree, tree);\n        if (ABSL_PREDICT_FALSE(tree->height() > CordRepBtree::kMaxHeight)) {\n          tree = CordRepBtree::Rebuild(tree);\n          ABSL_RAW_CHECK(tree->height() <= CordRepBtree::kMaxHeight,\n                         \"Max height exceeded\");\n        }\n        return tree;\n      case CordRepBtree::kCopied:\n        CordRep::Unref(tree);\n        ABSL_FALLTHROUGH_INTENDED;\n      case CordRepBtree::kSelf:\n        return result.tree;\n    }\n    ABSL_UNREACHABLE();\n    return result.tree;\n  }\n\n  // Propagate the action result in 'result' up into all nodes of the stack\n  // starting at depth 'depth'. 'length' contains the extra length of data that\n  // was added at the lowest level, and is updated into all nodes of the stack.\n  // See the 'Action' enum for the various action implications.\n  // If 'propagate' is true, then any copied node values are updated into the\n  // stack, which is used for iterative processing on the same stack.\n  template <bool propagate = false>\n  inline CordRepBtree* Unwind(CordRepBtree* tree, int depth, size_t length,\n                              OpResult result) {\n    // TODO(mvels): revisit the below code to check if 3 loops with 3\n    // (incremental) conditions is faster than 1 loop with a switch.\n    // Benchmarking and perf recordings indicate the loop with switch is\n    // fastest, likely because of indirect jumps on the tight case values and\n    // dense branches. But it's worth considering 3 loops, as the `action`\n    // transitions are mono directional. E.g.:\n    //   while (action == kPopped) {\n    //     ...\n    //   }\n    //   while (action == kCopied) {\n    //     ...\n    //   }\n    //   ...\n    // We also  found that an \"if () do {}\" loop here seems faster, possibly\n    // because it allows the branch predictor more granular heuristics on\n    // 'single leaf' (`depth` == 0) and 'single depth' (`depth` == 1) cases\n    // which appear to be the most common use cases.\n    if (depth != 0) {\n      do {\n        CordRepBtree* node = stack[--depth];\n        const bool owned = depth < share_depth;\n        switch (result.action) {\n          case CordRepBtree::kPopped:\n            assert(!propagate);\n            result = node->AddEdge<edge_type>(owned, result.tree, length);\n            break;\n          case CordRepBtree::kCopied:\n            result = node->SetEdge<edge_type>(owned, result.tree, length);\n            if (propagate) stack[depth] = result.tree;\n            break;\n          case CordRepBtree::kSelf:\n            node->length += length;\n            while (depth > 0) {\n              node = stack[--depth];\n              node->length += length;\n            }\n            return node;\n        }\n      } while (depth > 0);\n    }\n    return Finalize(tree, result);\n  }\n\n  // Invokes `Unwind` with `propagate=true` to update the stack node values.\n  inline CordRepBtree* Propagate(CordRepBtree* tree, int depth, size_t length,\n                                 OpResult result) {\n    return Unwind</*propagate=*/true>(tree, depth, length, result);\n  }\n\n  // `share_depth` contains the depth at which the nodes in the stack become\n  // shared. I.e., if the top most level is shared (i.e.: `!refcount.IsOne()`),\n  // then `share_depth` is 0. If the 2nd node is shared (and implicitly all\n  // nodes below that) then `share_depth` is 1, etc. A `share_depth` greater\n  // than the depth of the stack indicates that none of the nodes in the stack\n  // are shared.\n  int share_depth;\n\n  NodeStack stack;\n};\n\n}  // namespace\n\nvoid SetCordBtreeExhaustiveValidation(bool do_exaustive_validation) {\n  cord_btree_exhaustive_validation.store(do_exaustive_validation,\n                                         std::memory_order_relaxed);\n}\n\nbool IsCordBtreeExhaustiveValidationEnabled() {\n  return cord_btree_exhaustive_validation.load(std::memory_order_relaxed);\n}\n\nvoid CordRepBtree::Dump(const CordRep* rep, absl::string_view label,\n                        bool include_contents, std::ostream& stream) {\n  stream << \"===================================\\n\";\n  if (!label.empty()) {\n    stream << label << '\\n';\n    stream << \"-----------------------------------\\n\";\n  }\n  if (rep) {\n    DumpAll(rep, include_contents, stream);\n  } else {\n    stream << \"NULL\\n\";\n  }\n}\n\nvoid CordRepBtree::Dump(const CordRep* rep, absl::string_view label,\n                        std::ostream& stream) {\n  Dump(rep, label, false, stream);\n}\n\nvoid CordRepBtree::Dump(const CordRep* rep, std::ostream& stream) {\n  Dump(rep, absl::string_view(), false, stream);\n}\n\ntemplate <size_t size>\nstatic void DestroyTree(CordRepBtree* tree) {\n  for (CordRep* node : tree->Edges()) {\n    if (node->refcount.Decrement()) continue;\n    for (CordRep* edge : node->btree()->Edges()) {\n      if (edge->refcount.Decrement()) continue;\n      if (size == 1) {\n        DeleteLeafEdge(edge);\n      } else {\n        CordRepBtree::Destroy(edge->btree());\n      }\n    }\n    CordRepBtree::Delete(node->btree());\n  }\n  CordRepBtree::Delete(tree);\n}\n\nvoid CordRepBtree::Destroy(CordRepBtree* tree) {\n  switch (tree->height()) {\n    case 0:\n      for (CordRep* edge : tree->Edges()) {\n        if (!edge->refcount.Decrement()) {\n          DeleteLeafEdge(edge);\n        }\n      }\n      return CordRepBtree::Delete(tree);\n    case 1:\n      return DestroyTree<1>(tree);\n    default:\n      return DestroyTree<2>(tree);\n  }\n}\n\nbool CordRepBtree::IsValid(const CordRepBtree* tree, bool shallow) {\n#define NODE_CHECK_VALID(x)                                           \\\n  if (!(x)) {                                                         \\\n    ABSL_RAW_LOG(ERROR, \"CordRepBtree::CheckValid() FAILED: %s\", #x); \\\n    return false;                                                     \\\n  }\n#define NODE_CHECK_EQ(x, y)                                                    \\\n  if ((x) != (y)) {                                                            \\\n    ABSL_RAW_LOG(ERROR,                                                        \\\n                 \"CordRepBtree::CheckValid() FAILED: %s != %s (%s vs %s)\", #x, \\\n                 #y, absl::StrCat(x).c_str(), absl::StrCat(y).c_str());        \\\n    return false;                                                              \\\n  }\n\n  NODE_CHECK_VALID(tree != nullptr);\n  NODE_CHECK_VALID(tree->IsBtree());\n  NODE_CHECK_VALID(tree->height() <= kMaxHeight);\n  NODE_CHECK_VALID(tree->begin() < tree->capacity());\n  NODE_CHECK_VALID(tree->end() <= tree->capacity());\n  NODE_CHECK_VALID(tree->begin() <= tree->end());\n  size_t child_length = 0;\n  for (CordRep* edge : tree->Edges()) {\n    NODE_CHECK_VALID(edge != nullptr);\n    if (tree->height() > 0) {\n      NODE_CHECK_VALID(edge->IsBtree());\n      NODE_CHECK_VALID(edge->btree()->height() == tree->height() - 1);\n    } else {\n      NODE_CHECK_VALID(IsDataEdge(edge));\n    }\n    child_length += edge->length;\n  }\n  NODE_CHECK_EQ(child_length, tree->length);\n  if ((!shallow || IsCordBtreeExhaustiveValidationEnabled()) &&\n      tree->height() > 0) {\n    for (CordRep* edge : tree->Edges()) {\n      if (!IsValid(edge->btree(), shallow)) return false;\n    }\n  }\n  return true;\n\n#undef NODE_CHECK_VALID\n#undef NODE_CHECK_EQ\n}\n\n#ifndef NDEBUG\n\nCordRepBtree* CordRepBtree::AssertValid(CordRepBtree* tree, bool shallow) {\n  if (!IsValid(tree, shallow)) {\n    Dump(tree, \"CordRepBtree validation failed:\", false, std::cout);\n    ABSL_RAW_LOG(FATAL, \"CordRepBtree::CheckValid() FAILED\");\n  }\n  return tree;\n}\n\nconst CordRepBtree* CordRepBtree::AssertValid(const CordRepBtree* tree,\n                                              bool shallow) {\n  if (!IsValid(tree, shallow)) {\n    Dump(tree, \"CordRepBtree validation failed:\", false, std::cout);\n    ABSL_RAW_LOG(FATAL, \"CordRepBtree::CheckValid() FAILED\");\n  }\n  return tree;\n}\n\n#endif  // NDEBUG\n\ntemplate <EdgeType edge_type>\ninline OpResult CordRepBtree::AddEdge(bool owned, CordRep* edge, size_t delta) {\n  if (size() >= kMaxCapacity) return {New(edge), kPopped};\n  OpResult result = ToOpResult(owned);\n  result.tree->Add<edge_type>(edge);\n  result.tree->length += delta;\n  return result;\n}\n\ntemplate <EdgeType edge_type>\nOpResult CordRepBtree::SetEdge(bool owned, CordRep* edge, size_t delta) {\n  OpResult result;\n  const size_t idx = index(edge_type);\n  if (owned) {\n    result = {this, kSelf};\n    CordRep::Unref(edges_[idx]);\n  } else {\n    // Create a copy containing all unchanged edges. Unchanged edges are the\n    // open interval [begin, back) or [begin + 1, end) depending on `edge_type`.\n    // We conveniently cover both case using a constexpr `shift` being 0 or 1\n    // as `end :== back + 1`.\n    result = {CopyRaw(length), kCopied};\n    constexpr int shift = edge_type == kFront ? 1 : 0;\n    for (CordRep* r : Edges(begin() + shift, back() + shift)) {\n      CordRep::Ref(r);\n    }\n  }\n  result.tree->edges_[idx] = edge;\n  result.tree->length += delta;\n  return result;\n}\n\ntemplate <EdgeType edge_type>\nCordRepBtree* CordRepBtree::AddCordRep(CordRepBtree* tree, CordRep* rep) {\n  const int depth = tree->height();\n  const size_t length = rep->length;\n  StackOperations<edge_type> ops;\n  CordRepBtree* leaf = ops.BuildStack(tree, depth);\n  const OpResult result =\n      leaf->AddEdge<edge_type>(ops.owned(depth), rep, length);\n  return ops.Unwind(tree, depth, length, result);\n}\n\ntemplate <>\nCordRepBtree* CordRepBtree::NewLeaf<kBack>(absl::string_view data,\n                                           size_t extra) {\n  CordRepBtree* leaf = CordRepBtree::New(0);\n  size_t length = 0;\n  size_t end = 0;\n  const size_t cap = leaf->capacity();\n  while (!data.empty() && end != cap) {\n    auto* flat = CordRepFlat::New(data.length() + extra);\n    flat->length = (std::min)(data.length(), flat->Capacity());\n    length += flat->length;\n    leaf->edges_[end++] = flat;\n    data = Consume<kBack>(flat->Data(), data, flat->length);\n  }\n  leaf->length = length;\n  leaf->set_end(end);\n  return leaf;\n}\n\ntemplate <>\nCordRepBtree* CordRepBtree::NewLeaf<kFront>(absl::string_view data,\n                                            size_t extra) {\n  CordRepBtree* leaf = CordRepBtree::New(0);\n  size_t length = 0;\n  size_t begin = leaf->capacity();\n  leaf->set_end(leaf->capacity());\n  while (!data.empty() && begin != 0) {\n    auto* flat = CordRepFlat::New(data.length() + extra);\n    flat->length = (std::min)(data.length(), flat->Capacity());\n    length += flat->length;\n    leaf->edges_[--begin] = flat;\n    data = Consume<kFront>(flat->Data(), data, flat->length);\n  }\n  leaf->length = length;\n  leaf->set_begin(begin);\n  return leaf;\n}\n\ntemplate <>\nabsl::string_view CordRepBtree::AddData<kBack>(absl::string_view data,\n                                               size_t extra) {\n  assert(!data.empty());\n  assert(size() < capacity());\n  AlignBegin();\n  const size_t cap = capacity();\n  do {\n    CordRepFlat* flat = CordRepFlat::New(data.length() + extra);\n    const size_t n = (std::min)(data.length(), flat->Capacity());\n    flat->length = n;\n    edges_[fetch_add_end(1)] = flat;\n    data = Consume<kBack>(flat->Data(), data, n);\n  } while (!data.empty() && end() != cap);\n  return data;\n}\n\ntemplate <>\nabsl::string_view CordRepBtree::AddData<kFront>(absl::string_view data,\n                                                size_t extra) {\n  assert(!data.empty());\n  assert(size() < capacity());\n  AlignEnd();\n  do {\n    CordRepFlat* flat = CordRepFlat::New(data.length() + extra);\n    const size_t n = (std::min)(data.length(), flat->Capacity());\n    flat->length = n;\n    edges_[sub_fetch_begin(1)] = flat;\n    data = Consume<kFront>(flat->Data(), data, n);\n  } while (!data.empty() && begin() != 0);\n  return data;\n}\n\ntemplate <EdgeType edge_type>\nCordRepBtree* CordRepBtree::AddData(CordRepBtree* tree, absl::string_view data,\n                                    size_t extra) {\n  if (ABSL_PREDICT_FALSE(data.empty())) return tree;\n\n  const size_t original_data_size = data.size();\n  int depth = tree->height();\n  StackOperations<edge_type> ops;\n  CordRepBtree* leaf = ops.BuildStack(tree, depth);\n\n  // If there is capacity in the last edge, append as much data\n  // as possible into this last edge.\n  if (leaf->size() < leaf->capacity()) {\n    OpResult result = leaf->ToOpResult(ops.owned(depth));\n    data = result.tree->AddData<edge_type>(data, extra);\n    if (data.empty()) {\n      result.tree->length += original_data_size;\n      return ops.Unwind(tree, depth, original_data_size, result);\n    }\n\n    // We added some data into this leaf, but not all. Propagate the added\n    // length to the top most node, and rebuild the stack with any newly copied\n    // or updated nodes. From this point on, the path (leg) from the top most\n    // node to the right-most node towards the leaf node is privately owned.\n    size_t delta = original_data_size - data.size();\n    assert(delta > 0);\n    result.tree->length += delta;\n    tree = ops.Propagate(tree, depth, delta, result);\n    ops.share_depth = depth + 1;\n  }\n\n  // We were unable to append all data into the existing right-most leaf node.\n  // This means all remaining data must be put into (a) new leaf node(s) which\n  // we append to the tree. To make this efficient, we iteratively build full\n  // leaf nodes from `data` until the created leaf contains all remaining data.\n  // We utilize the `Unwind` method to merge the created leaf into the first\n  // level towards root that has capacity. On each iteration with remaining\n  // data, we rebuild the stack in the knowledge that right-most nodes are\n  // privately owned after the first `Unwind` completes.\n  for (;;) {\n    OpResult result = {CordRepBtree::NewLeaf<edge_type>(data, extra), kPopped};\n    if (result.tree->length == data.size()) {\n      return ops.Unwind(tree, depth, result.tree->length, result);\n    }\n    data = Consume<edge_type>(data, result.tree->length);\n    tree = ops.Unwind(tree, depth, result.tree->length, result);\n    depth = tree->height();\n    ops.BuildOwnedStack(tree, depth);\n  }\n}\n\ntemplate <EdgeType edge_type>\nCordRepBtree* CordRepBtree::Merge(CordRepBtree* dst, CordRepBtree* src) {\n  assert(dst->height() >= src->height());\n\n  // Capture source length as we may consume / destroy `src`.\n  const size_t length = src->length;\n\n  // We attempt to merge `src` at its corresponding height in `dst`.\n  const int depth = dst->height() - src->height();\n  StackOperations<edge_type> ops;\n  CordRepBtree* merge_node = ops.BuildStack(dst, depth);\n\n  // If there is enough space in `merge_node` for all edges from `src`, add all\n  // edges to this node, making a fresh copy as needed if not privately owned.\n  // If `merge_node` does not have capacity for `src`, we rely on `Unwind` and\n  // `Finalize` to merge `src` into the first level towards `root` where there\n  // is capacity for another edge, or create a new top level node.\n  OpResult result;\n  if (merge_node->size() + src->size() <= kMaxCapacity) {\n    result = merge_node->ToOpResult(ops.owned(depth));\n    result.tree->Add<edge_type>(src->Edges());\n    result.tree->length += src->length;\n    if (src->refcount.IsOne()) {\n      Delete(src);\n    } else {\n      for (CordRep* edge : src->Edges()) CordRep::Ref(edge);\n      CordRepBtree::Unref(src);\n    }\n  } else {\n    result = {src, kPopped};\n  }\n\n  // Unless we merged at the top level (i.e.: src and dst are equal height),\n  // unwind the result towards the top level, and finalize the result.\n  if (depth) {\n    return ops.Unwind(dst, depth, length, result);\n  }\n  return ops.Finalize(dst, result);\n}\n\nCopyResult CordRepBtree::CopySuffix(size_t offset) {\n  assert(offset < this->length);\n\n  // As long as `offset` starts inside the last edge, we can 'drop' the current\n  // depth. For the most extreme example: if offset references the last data\n  // edge in the tree, there is only a single edge / path from the top of the\n  // tree to that last edge, so we can drop all the nodes except that edge.\n  // The fast path check for this is `back->length >= length - offset`.\n  int height = this->height();\n  CordRepBtree* node = this;\n  size_t len = node->length - offset;\n  CordRep* back = node->Edge(kBack);\n  while (back->length >= len) {\n    offset = back->length - len;\n    if (--height < 0) {\n      return {MakeSubstring(CordRep::Ref(back), offset), height};\n    }\n    node = back->btree();\n    back = node->Edge(kBack);\n  }\n  if (offset == 0) return {CordRep::Ref(node), height};\n\n  // Offset does not point into the last edge, so we span at least two edges.\n  // Find the index of offset with `IndexBeyond` which provides us the edge\n  // 'beyond' the offset if offset is not a clean starting point of an edge.\n  Position pos = node->IndexBeyond(offset);\n  CordRepBtree* sub = node->CopyToEndFrom(pos.index, len);\n  const CopyResult result = {sub, height};\n\n  // `pos.n` contains a non zero value if the offset is not an exact starting\n  // point of an edge. In this case, `pos.n` contains the 'trailing' amount of\n  // bytes of the edge preceding that in `pos.index`. We need to iteratively\n  // adjust the preceding edge with the 'broken' offset until we have a perfect\n  // start of the edge.\n  while (pos.n != 0) {\n    assert(pos.index >= 1);\n    const size_t begin = pos.index - 1;\n    sub->set_begin(begin);\n    CordRep* const edge = node->Edge(begin);\n\n    len = pos.n;\n    offset = edge->length - len;\n\n    if (--height < 0) {\n      sub->edges_[begin] = MakeSubstring(CordRep::Ref(edge), offset, len);\n      return result;\n    }\n\n    node = edge->btree();\n    pos = node->IndexBeyond(offset);\n\n    CordRepBtree* nsub = node->CopyToEndFrom(pos.index, len);\n    sub->edges_[begin] = nsub;\n    sub = nsub;\n  }\n  sub->set_begin(pos.index);\n  return result;\n}\n\nCopyResult CordRepBtree::CopyPrefix(size_t n, bool allow_folding) {\n  assert(n > 0);\n  assert(n <= this->length);\n\n  // As long as `n` does not exceed the length of the first edge, we can 'drop'\n  // the current depth. For the most extreme example: if we'd copy a 1 byte\n  // prefix from a tree, there is only a single edge / path from the top of the\n  // tree to the single data edge containing this byte, so we can drop all the\n  // nodes except the data node.\n  int height = this->height();\n  CordRepBtree* node = this;\n  CordRep* front = node->Edge(kFront);\n  if (allow_folding) {\n    while (front->length >= n) {\n      if (--height < 0) return {MakeSubstring(CordRep::Ref(front), 0, n), -1};\n      node = front->btree();\n      front = node->Edge(kFront);\n    }\n  }\n  if (node->length == n) return {CordRep::Ref(node), height};\n\n  // `n` spans at least two nodes, find the end point of the span.\n  Position pos = node->IndexOf(n);\n\n  // Create a partial copy of the node up to `pos.index`, with a defined length\n  // of `n`. Any 'partial last edge' is added further below as needed.\n  CordRepBtree* sub = node->CopyBeginTo(pos.index, n);\n  const CopyResult result = {sub, height};\n\n  // `pos.n` contains the 'offset inside the edge for IndexOf(n)'. As long as\n  // this is not zero, we don't have a 'clean cut', so we need to make a\n  // (partial) copy of that last edge, and repeat this until pos.n is zero.\n  while (pos.n != 0) {\n    size_t end = pos.index;\n    n = pos.n;\n\n    CordRep* edge = node->Edge(pos.index);\n    if (--height < 0) {\n      sub->edges_[end++] = MakeSubstring(CordRep::Ref(edge), 0, n);\n      sub->set_end(end);\n      AssertValid(result.edge->btree());\n      return result;\n    }\n\n    node = edge->btree();\n    pos = node->IndexOf(n);\n    CordRepBtree* nsub = node->CopyBeginTo(pos.index, n);\n    sub->edges_[end++] = nsub;\n    sub->set_end(end);\n    sub = nsub;\n  }\n  sub->set_end(pos.index);\n  AssertValid(result.edge->btree());\n  return result;\n}\n\nCordRep* CordRepBtree::ExtractFront(CordRepBtree* tree) {\n  CordRep* front = tree->Edge(tree->begin());\n  if (tree->refcount.IsOne()) {\n    Unref(tree->Edges(tree->begin() + 1, tree->end()));\n    CordRepBtree::Delete(tree);\n  } else {\n    CordRep::Ref(front);\n    CordRep::Unref(tree);\n  }\n  return front;\n}\n\nCordRepBtree* CordRepBtree::ConsumeBeginTo(CordRepBtree* tree, size_t end,\n                                           size_t new_length) {\n  assert(end <= tree->end());\n  if (tree->refcount.IsOne()) {\n    Unref(tree->Edges(end, tree->end()));\n    tree->set_end(end);\n    tree->length = new_length;\n  } else {\n    CordRepBtree* old = tree;\n    tree = tree->CopyBeginTo(end, new_length);\n    CordRep::Unref(old);\n  }\n  return tree;\n}\n\nCordRep* CordRepBtree::RemoveSuffix(CordRepBtree* tree, size_t n) {\n  // Check input and deal with trivial cases 'Remove all/none'\n  assert(tree != nullptr);\n  assert(n <= tree->length);\n  const size_t len = tree->length;\n  if (ABSL_PREDICT_FALSE(n == 0)) {\n    return tree;\n  }\n  if (ABSL_PREDICT_FALSE(n >= len)) {\n    CordRepBtree::Unref(tree);\n    return nullptr;\n  }\n\n  size_t length = len - n;\n  int height = tree->height();\n  bool is_mutable = tree->refcount.IsOne();\n\n  // Extract all top nodes which are reduced to size = 1\n  Position pos = tree->IndexOfLength(length);\n  while (pos.index == tree->begin()) {\n    CordRep* edge = ExtractFront(tree);\n    is_mutable &= edge->refcount.IsOne();\n    if (height-- == 0) return ResizeEdge(edge, length, is_mutable);\n    tree = edge->btree();\n    pos = tree->IndexOfLength(length);\n  }\n\n  // Repeat the following sequence traversing down the tree:\n  // - Crop the top node to the 'last remaining edge' adjusting length.\n  // - Set the length for down edges to the partial length in that last edge.\n  // - Repeat this until the last edge is 'included in full'\n  // - If we hit the data edge level, resize and return the last data edge\n  CordRepBtree* top = tree = ConsumeBeginTo(tree, pos.index + 1, length);\n  CordRep* edge = tree->Edge(pos.index);\n  length = pos.n;\n  while (length != edge->length) {\n    // ConsumeBeginTo guarantees `tree` is a clean, privately owned copy.\n    assert(tree->refcount.IsOne());\n    const bool edge_is_mutable = edge->refcount.IsOne();\n\n    if (height-- == 0) {\n      tree->edges_[pos.index] = ResizeEdge(edge, length, edge_is_mutable);\n      return AssertValid(top);\n    }\n\n    if (!edge_is_mutable) {\n      // We can't 'in place' remove any suffixes down this edge.\n      // Replace this edge with a prefix copy instead.\n      tree->edges_[pos.index] = edge->btree()->CopyPrefix(length, false).edge;\n      CordRep::Unref(edge);\n      return AssertValid(top);\n    }\n\n    // Move down one level, rinse repeat.\n    tree = edge->btree();\n    pos = tree->IndexOfLength(length);\n    tree = ConsumeBeginTo(edge->btree(), pos.index + 1, length);\n    edge = tree->Edge(pos.index);\n    length = pos.n;\n  }\n\n  return AssertValid(top);\n}\n\nCordRep* CordRepBtree::SubTree(size_t offset, size_t n) {\n  assert(n <= this->length);\n  assert(offset <= this->length - n);\n  if (ABSL_PREDICT_FALSE(n == 0)) return nullptr;\n\n  CordRepBtree* node = this;\n  int height = node->height();\n  Position front = node->IndexOf(offset);\n  CordRep* left = node->edges_[front.index];\n  while (front.n + n <= left->length) {\n    if (--height < 0) return MakeSubstring(CordRep::Ref(left), front.n, n);\n    node = left->btree();\n    front = node->IndexOf(front.n);\n    left = node->edges_[front.index];\n  }\n\n  const Position back = node->IndexBefore(front, n);\n  CordRep* const right = node->edges_[back.index];\n  assert(back.index > front.index);\n\n  // Get partial suffix and prefix entries.\n  CopyResult prefix;\n  CopyResult suffix;\n  if (height > 0) {\n    // Copy prefix and suffix of the boundary nodes.\n    prefix = left->btree()->CopySuffix(front.n);\n    suffix = right->btree()->CopyPrefix(back.n);\n\n    // If there is an edge between the prefix and suffix edges, then the tree\n    // must remain at its previous (full) height. If we have no edges between\n    // prefix and suffix edges, then the tree must be as high as either the\n    // suffix or prefix edges (which are collapsed to their minimum heights).\n    if (front.index + 1 == back.index) {\n      height = (std::max)(prefix.height, suffix.height) + 1;\n    }\n\n    // Raise prefix and suffixes to the new tree height.\n    for (int h = prefix.height + 1; h < height; ++h) {\n      prefix.edge = CordRepBtree::New(prefix.edge);\n    }\n    for (int h = suffix.height + 1; h < height; ++h) {\n      suffix.edge = CordRepBtree::New(suffix.edge);\n    }\n  } else {\n    // Leaf node, simply take substrings for prefix and suffix.\n    prefix = CopyResult{MakeSubstring(CordRep::Ref(left), front.n), -1};\n    suffix = CopyResult{MakeSubstring(CordRep::Ref(right), 0, back.n), -1};\n  }\n\n  // Compose resulting tree.\n  CordRepBtree* sub = CordRepBtree::New(height);\n  size_t end = 0;\n  sub->edges_[end++] = prefix.edge;\n  for (CordRep* r : node->Edges(front.index + 1, back.index)) {\n    sub->edges_[end++] = CordRep::Ref(r);\n  }\n  sub->edges_[end++] = suffix.edge;\n  sub->set_end(end);\n  sub->length = n;\n  return AssertValid(sub);\n}\n\nCordRepBtree* CordRepBtree::MergeTrees(CordRepBtree* left,\n                                       CordRepBtree* right) {\n  return left->height() >= right->height() ? Merge<kBack>(left, right)\n                                           : Merge<kFront>(right, left);\n}\n\nbool CordRepBtree::IsFlat(absl::string_view* fragment) const {\n  if (height() == 0 && size() == 1) {\n    if (fragment) *fragment = Data(begin());\n    return true;\n  }\n  return false;\n}\n\nbool CordRepBtree::IsFlat(size_t offset, const size_t n,\n                          absl::string_view* fragment) const {\n  assert(n <= this->length);\n  assert(offset <= this->length - n);\n  if (ABSL_PREDICT_FALSE(n == 0)) return false;\n  int height = this->height();\n  const CordRepBtree* node = this;\n  for (;;) {\n    const Position front = node->IndexOf(offset);\n    const CordRep* edge = node->Edge(front.index);\n    if (edge->length < front.n + n) return false;\n    if (--height < 0) {\n      if (fragment) *fragment = EdgeData(edge).substr(front.n, n);\n      return true;\n    }\n    offset = front.n;\n    node = node->Edge(front.index)->btree();\n  }\n}\n\nchar CordRepBtree::GetCharacter(size_t offset) const {\n  assert(offset < length);\n  const CordRepBtree* node = this;\n  int height = node->height();\n  for (;;) {\n    Position front = node->IndexOf(offset);\n    if (--height < 0) return node->Data(front.index)[front.n];\n    offset = front.n;\n    node = node->Edge(front.index)->btree();\n  }\n}\n\nSpan<char> CordRepBtree::GetAppendBufferSlow(size_t size) {\n  // The inlined version in `GetAppendBuffer()` deals with all heights <= 3.\n  assert(height() >= 4);\n  assert(refcount.IsOne());\n\n  // Build a stack of nodes we may potentially need to update if we find a\n  // non-shared FLAT with capacity at the leaf level.\n  const int depth = height();\n  CordRepBtree* node = this;\n  CordRepBtree* stack[kMaxDepth];\n  for (int i = 0; i < depth; ++i) {\n    node = node->Edge(kBack)->btree();\n    if (!node->refcount.IsOne()) return {};\n    stack[i] = node;\n  }\n\n  // Must be a privately owned, mutable flat.\n  CordRep* const edge = node->Edge(kBack);\n  if (!edge->refcount.IsOne() || edge->tag < FLAT) return {};\n\n  // Must have capacity.\n  const size_t avail = edge->flat()->Capacity() - edge->length;\n  if (avail == 0) return {};\n\n  // Build span on remaining capacity.\n  size_t delta = (std::min)(size, avail);\n  Span<char> span = {edge->flat()->Data() + edge->length, delta};\n  edge->length += delta;\n  this->length += delta;\n  for (int i = 0; i < depth; ++i) {\n    stack[i]->length += delta;\n  }\n  return span;\n}\n\nCordRepBtree* CordRepBtree::CreateSlow(CordRep* rep) {\n  if (rep->IsBtree()) return rep->btree();\n\n  CordRepBtree* node = nullptr;\n  auto consume = [&node](CordRep* r, size_t offset, size_t length) {\n    r = MakeSubstring(r, offset, length);\n    if (node == nullptr) {\n      node = New(r);\n    } else {\n      node = CordRepBtree::AddCordRep<kBack>(node, r);\n    }\n  };\n  Consume(rep, consume);\n  return node;\n}\n\nCordRepBtree* CordRepBtree::AppendSlow(CordRepBtree* tree, CordRep* rep) {\n  if (ABSL_PREDICT_TRUE(rep->IsBtree())) {\n    return MergeTrees(tree, rep->btree());\n  }\n  auto consume = [&tree](CordRep* r, size_t offset, size_t length) {\n    r = MakeSubstring(r, offset, length);\n    tree = CordRepBtree::AddCordRep<kBack>(tree, r);\n  };\n  Consume(rep, consume);\n  return tree;\n}\n\nCordRepBtree* CordRepBtree::PrependSlow(CordRepBtree* tree, CordRep* rep) {\n  if (ABSL_PREDICT_TRUE(rep->IsBtree())) {\n    return MergeTrees(rep->btree(), tree);\n  }\n  auto consume = [&tree](CordRep* r, size_t offset, size_t length) {\n    r = MakeSubstring(r, offset, length);\n    tree = CordRepBtree::AddCordRep<kFront>(tree, r);\n  };\n  ReverseConsume(rep, consume);\n  return tree;\n}\n\nCordRepBtree* CordRepBtree::Append(CordRepBtree* tree, absl::string_view data,\n                                   size_t extra) {\n  return CordRepBtree::AddData<kBack>(tree, data, extra);\n}\n\nCordRepBtree* CordRepBtree::Prepend(CordRepBtree* tree, absl::string_view data,\n                                    size_t extra) {\n  return CordRepBtree::AddData<kFront>(tree, data, extra);\n}\n\ntemplate CordRepBtree* CordRepBtree::AddCordRep<kFront>(CordRepBtree* tree,\n                                                        CordRep* rep);\ntemplate CordRepBtree* CordRepBtree::AddCordRep<kBack>(CordRepBtree* tree,\n                                                       CordRep* rep);\ntemplate CordRepBtree* CordRepBtree::AddData<kFront>(CordRepBtree* tree,\n                                                     absl::string_view data,\n                                                     size_t extra);\ntemplate CordRepBtree* CordRepBtree::AddData<kBack>(CordRepBtree* tree,\n                                                    absl::string_view data,\n                                                    size_t extra);\n\nvoid CordRepBtree::Rebuild(CordRepBtree** stack, CordRepBtree* tree,\n                           bool consume) {\n  bool owned = consume && tree->refcount.IsOne();\n  if (tree->height() == 0) {\n    for (CordRep* edge : tree->Edges()) {\n      if (!owned) edge = CordRep::Ref(edge);\n      size_t height = 0;\n      size_t length = edge->length;\n      CordRepBtree* node = stack[0];\n      OpResult result = node->AddEdge<kBack>(true, edge, length);\n      while (result.action == CordRepBtree::kPopped) {\n        stack[height] = result.tree;\n        if (stack[++height] == nullptr) {\n          result.action = CordRepBtree::kSelf;\n          stack[height] = CordRepBtree::New(node, result.tree);\n        } else {\n          node = stack[height];\n          result = node->AddEdge<kBack>(true, result.tree, length);\n        }\n      }\n      while (stack[++height] != nullptr) {\n        stack[height]->length += length;\n      }\n    }\n  } else {\n    for (CordRep* rep : tree->Edges()) {\n      Rebuild(stack, rep->btree(), owned);\n    }\n  }\n  if (consume) {\n    if (owned) {\n      CordRepBtree::Delete(tree);\n    } else {\n      CordRepBtree::Unref(tree);\n    }\n  }\n}\n\nCordRepBtree* CordRepBtree::Rebuild(CordRepBtree* tree) {\n  // Set up initial stack with empty leaf node.\n  CordRepBtree* node = CordRepBtree::New();\n  CordRepBtree* stack[CordRepBtree::kMaxDepth + 1] = {node};\n\n  // Recursively build the tree, consuming the input tree.\n  Rebuild(stack, tree, /* consume reference */ true);\n\n  // Return top most node\n  for (CordRepBtree* parent : stack) {\n    if (parent == nullptr) return node;\n    node = parent;\n  }\n\n  // Unreachable\n  assert(false);\n  return nullptr;\n}\n\nCordRepBtree::ExtractResult CordRepBtree::ExtractAppendBuffer(\n    CordRepBtree* tree, size_t extra_capacity) {\n  int depth = 0;\n  NodeStack stack;\n\n  // Set up default 'no success' result which is {tree, nullptr}.\n  ExtractResult result;\n  result.tree = tree;\n  result.extracted = nullptr;\n\n  // Dive down the right side of the tree, making sure no edges are shared.\n  while (tree->height() > 0) {\n    if (!tree->refcount.IsOne()) return result;\n    stack[depth++] = tree;\n    tree = tree->Edge(kBack)->btree();\n  }\n  if (!tree->refcount.IsOne()) return result;\n\n  // Validate we ended on a non shared flat.\n  CordRep* rep = tree->Edge(kBack);\n  if (!(rep->IsFlat() && rep->refcount.IsOne())) return result;\n\n  // Verify it has at least the requested extra capacity.\n  CordRepFlat* flat = rep->flat();\n  const size_t length = flat->length;\n  const size_t avail = flat->Capacity() - flat->length;\n  if (extra_capacity > avail) return result;\n\n  // Set the extracted flat in the result.\n  result.extracted = flat;\n\n  // Cascading delete all nodes that become empty.\n  while (tree->size() == 1) {\n    CordRepBtree::Delete(tree);\n    if (--depth < 0) {\n      // We consumed the entire tree: return nullptr for new tree.\n      result.tree = nullptr;\n      return result;\n    }\n    rep = tree;\n    tree = stack[depth];\n  }\n\n  // Remove the edge or cascaded up parent node.\n  tree->set_end(tree->end() - 1);\n  tree->length -= length;\n\n  // Adjust lengths up the tree.\n  while (depth > 0) {\n    tree = stack[--depth];\n    tree->length -= length;\n  }\n\n  // Remove unnecessary top nodes with size = 1. This may iterate all the way\n  // down to the leaf node in which case we simply return the remaining last\n  // edge in that node and the extracted flat.\n  while (tree->size() == 1) {\n    int height = tree->height();\n    rep = tree->Edge(kBack);\n    Delete(tree);\n    if (height == 0) {\n      // We consumed the leaf: return the sole data edge as the new tree.\n      result.tree = rep;\n      return result;\n    }\n    tree = rep->btree();\n  }\n\n  // Done: return the (new) top level node and extracted flat.\n  result.tree = tree;\n  return result;\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_\n\n#include <cassert>\n#include <cstdint>\n#include <iosfwd>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// `SetCordBtreeExhaustiveValidation()` can be set to force exhaustive\n// validation in debug assertions, and code that calls `IsValid()`\n// explicitly. By default, assertions should be relatively cheap and\n// AssertValid() can easily lead to O(n^2) complexity as recursive / full tree\n// validation is O(n).\nvoid SetCordBtreeExhaustiveValidation(bool do_exaustive_validation);\nbool IsCordBtreeExhaustiveValidationEnabled();\n\nclass CordRepBtreeNavigator;\n\n// CordRepBtree is as the name implies a btree implementation of a Cordrep tree.\n// Data is stored at the leaf level only, non leaf nodes contain down pointers\n// only. Allowed types of data edges are FLAT, EXTERNAL and SUBSTRINGs of FLAT\n// or EXTERNAL nodes. The implementation allows for data to be added to either\n// end of the tree only, it does not provide any 'insert' logic. This has the\n// benefit that we can expect good fill ratios: all nodes except the outer\n// 'legs' will have 100% fill ratios for trees built using Append/Prepend\n// methods. Merged trees will typically have a fill ratio well above 50% as in a\n// similar fashion, one side of the merged tree will typically have a 100% fill\n// ratio, and the 'open' end will average 50%. All operations are O(log(n)) or\n// better, and the tree never needs balancing.\n//\n// All methods accepting a CordRep* or CordRepBtree* adopt a reference on that\n// input unless explicitly stated otherwise. All functions returning a CordRep*\n// or CordRepBtree* instance transfer a reference back to the caller.\n// Simplified, callers both 'donate' and 'consume' a reference count on each\n// call, simplifying the API. An example of building a tree:\n//\n//   CordRepBtree* tree = CordRepBtree::Create(MakeFlat(\"Hello\"));\n//   tree = CordRepBtree::Append(tree, MakeFlat(\"world\"));\n//\n// In the above example, all inputs are consumed, making each call affecting\n// `tree` reference count neutral. The returned `tree` value can be different\n// from the input if the input is shared with other threads, or if the tree\n// grows in height, but callers typically never have to concern themselves with\n// that and trust that all methods DTRT at all times.\nclass CordRepBtree : public CordRep {\n public:\n  // EdgeType identifies `front` and `back` enum values.\n  // Various implementations in CordRepBtree such as `Add` and `Edge` are\n  // generic and templated on operating on either of the boundary edges.\n  // For more information on the possible edges contained in a CordRepBtree\n  // instance see the documentation for `edges_`.\n  enum class EdgeType { kFront, kBack };\n\n  // Convenience constants into `EdgeType`\n  static constexpr EdgeType kFront = EdgeType::kFront;\n  static constexpr EdgeType kBack = EdgeType::kBack;\n\n  // Maximum number of edges: based on experiments and performance data, we can\n  // pick suitable values resulting in optimum cacheline aligned values. The\n  // preferred values are based on 64-bit systems where we aim to align this\n  // class onto 64 bytes, i.e.:  6 = 64 bytes, 14 = 128 bytes, etc.\n  // TODO(b/192061034): experiment with alternative sizes.\n  static constexpr size_t kMaxCapacity = 6;\n\n  // Reasonable maximum height of the btree. We can expect a fill ratio of at\n  // least 50%: trees are always expanded at the front or back. Concatenating\n  // trees will then typically fold at the top most node, where the lower nodes\n  // are at least at capacity on one side of joined inputs. At a lower fill\n  // rate of 4 edges per node, we have capacity for ~16 million leaf nodes.\n  // We will fail / abort if an application ever exceeds this height, which\n  // should be extremely rare (near impossible) and be an indication of an\n  // application error: we do not assume it reasonable for any application to\n  // operate correctly with such monster trees.\n  // Another compelling reason for the number `12` is that any contextual stack\n  // required for navigation or insertion requires 12 words and 12 bytes, which\n  // fits inside 2 cache lines with some room to spare, and is reasonable as a\n  // local stack variable compared to Cord's current near 400 bytes stack use.\n  // The maximum `height` value of a node is then `kMaxDepth - 1` as node height\n  // values start with a value of 0 for leaf nodes.\n  static constexpr size_t kMaxDepth = 12;\n  // See comments on height() for why this is an int and not a size_t.\n  static constexpr int kMaxHeight = static_cast<int>(kMaxDepth - 1);\n\n  // `Action` defines the action for unwinding changes done at the btree's leaf\n  // level that need to be propagated up to the parent node(s). Each operation\n  // on a node has an effect / action defined as follows:\n  // - kSelf\n  //   The operation (add / update, etc) was performed directly on the node as\n  //   the node is private to the current thread (i.e.: not shared directly or\n  //   indirectly through a refcount > 1). Changes can be propagated directly to\n  //   all parent nodes as all parent nodes are also then private to the current\n  //   thread.\n  // - kCopied\n  //   The operation (add / update, etc) was performed on a copy of the original\n  //   node, as the node is (potentially) directly or indirectly shared with\n  //   other threads. Changes need to be propagated into the parent nodes where\n  //   the old down pointer must be unreffed and replaced with this new copy.\n  //   Such changes to parent nodes may themselves require a copy if the parent\n  //   node is also shared. A kCopied action can propagate all the way to the\n  //   top node where we then must unref the `tree` input provided by the\n  //   caller, and return the new copy.\n  // - kPopped\n  //   The operation (typically add) could not be satisfied due to insufficient\n  //   capacity in the targeted node, and a new 'leg' was created that needs to\n  //   be added into the parent node. For example, adding a FLAT inside a leaf\n  //   node that is at capacity will create a new leaf node containing that\n  //   FLAT, that needs to be 'popped' up the btree. Such 'pop' actions can\n  //   cascade up the tree if parent nodes are also at capacity. A 'Popped'\n  //   action propagating all the way to the top of the tree will result in\n  //   the tree becoming one level higher than the current tree through a final\n  //   `CordRepBtree::New(tree, popped)` call, resulting in a new top node\n  //   referencing the old tree and the new (fully popped upwards) 'leg'.\n  enum Action { kSelf, kCopied, kPopped };\n\n  // Result of an operation on a node. See the `Action` enum for details.\n  struct OpResult {\n    CordRepBtree* tree;\n    Action action;\n  };\n\n  // Return value of the CopyPrefix and CopySuffix methods which can\n  // return a node or data edge at any height inside the tree.\n  // A height of 0 defines the lowest (leaf) node, a height of -1 identifies\n  // `edge` as being a plain data node: EXTERNAL / FLAT or SUBSTRING thereof.\n  struct CopyResult {\n    CordRep* edge;\n    int height;\n  };\n\n  // Logical position inside a node:\n  // - index: index of the edge.\n  // - n: size or offset value depending on context.\n  struct Position {\n    size_t index;\n    size_t n;\n  };\n\n  // Creates a btree from the given input. Adopts a ref of `rep`.\n  // If the input `rep` is itself a btree, i.e., `IsBtree()`, then this\n  // function immediately returns `rep->btree()`. If the input is a valid data\n  // edge (see IsDataEdge()), then a new leaf node is returned containing `rep`\n  // as the sole data edge. Else, the input is assumed to be a (legacy) concat\n  // tree, and the input is consumed and transformed into a btree().\n  static CordRepBtree* Create(CordRep* rep);\n\n  // Destroys the provided tree. Should only be called by cord internal API's,\n  // typically after a ref_count.Decrement() on the last reference count.\n  static void Destroy(CordRepBtree* tree);\n\n  // Destruction\n  static void Delete(CordRepBtree* tree) { delete tree; }\n\n  // Use CordRep::Unref() as we overload for absl::Span<CordRep* const>.\n  using CordRep::Unref;\n\n  // Unrefs all edges in `edges` which are assumed to be 'likely one'.\n  static void Unref(absl::Span<CordRep* const> edges);\n\n  // Appends / Prepends an existing CordRep instance to this tree.\n  // The below methods accept three types of input:\n  // 1) `rep` is a data node (See `IsDataNode` for valid data edges).\n  // `rep` is appended or prepended to this tree 'as is'.\n  // 2) `rep` is a BTREE.\n  // `rep` is merged into `tree` respecting the Append/Prepend order.\n  // 3) `rep` is some other (legacy) type.\n  // `rep` is converted in place and added to `tree`\n  // Requires `tree` and `rep` to be not null.\n  static CordRepBtree* Append(CordRepBtree* tree, CordRep* rep);\n  static CordRepBtree* Prepend(CordRepBtree* tree, CordRep* rep);\n\n  // Append/Prepend the data in `data` to this tree.\n  // The `extra` parameter defines how much extra capacity should be allocated\n  // for any additional FLAT being allocated. This is an optimization hint from\n  // the caller. For example, a caller may need to add 2 string_views of data\n  // \"abc\" and \"defghi\" which are not consecutive. The caller can in this case\n  // invoke `AddData(tree, \"abc\", 6)`, and any newly added flat is allocated\n  // where possible with at least 6 bytes of extra capacity beyond `length`.\n  // This helps avoiding data getting fragmented over multiple flats.\n  // There is no limit on the size of `data`. If `data` can not be stored inside\n  // a single flat, then the function will iteratively add flats until all data\n  // has been consumed and appended or prepended to the tree.\n  static CordRepBtree* Append(CordRepBtree* tree, string_view data,\n                              size_t extra = 0);\n  static CordRepBtree* Prepend(CordRepBtree* tree, string_view data,\n                               size_t extra = 0);\n\n  // Returns a new tree, containing `n` bytes of data from this instance\n  // starting at offset `offset`. Where possible, the returned tree shares\n  // (re-uses) data edges and nodes with this instance to minimize the\n  // combined memory footprint of both trees.\n  // Requires `offset + n <= length`. Returns `nullptr` if `n` is zero.\n  CordRep* SubTree(size_t offset, size_t n);\n\n  // Removes `n` trailing bytes from `tree`, and returns the resulting tree\n  // or data edge. Returns `tree` if n is zero, and nullptr if n == length.\n  // This function is logically identical to:\n  //   result = tree->SubTree(0, tree->length - n);\n  //   Unref(tree);\n  //   return result;\n  // However, the actual implementation will as much as possible perform 'in\n  // place' modifications on the tree on all nodes and edges that are mutable.\n  // For example, in a fully privately owned tree with the last edge being a\n  // flat of length 12, RemoveSuffix(1) will simply set the length of that data\n  // edge to 11, and reduce the length of all nodes on the edge path by 1.\n  static CordRep* RemoveSuffix(CordRepBtree* tree, size_t n);\n\n  // Returns the character at the given offset.\n  char GetCharacter(size_t offset) const;\n\n  // Returns true if this node holds a single data edge, and if so, sets\n  // `fragment` to reference the contained data. `fragment` is an optional\n  // output parameter and allowed to be null.\n  bool IsFlat(absl::string_view* fragment) const;\n\n  // Returns true if the data of `n` bytes starting at offset `offset`\n  // is contained in a single data edge, and if so, sets fragment to reference\n  // the contained data. `fragment` is an optional output parameter and allowed\n  // to be null.\n  bool IsFlat(size_t offset, size_t n, absl::string_view* fragment) const;\n\n  // Returns a span (mutable range of bytes) of up to `size` bytes into the\n  // last FLAT data edge inside this tree under the following conditions:\n  // - none of the nodes down into the FLAT node are shared.\n  // - the last data edge in this tree is a non-shared FLAT.\n  // - the referenced FLAT has additional capacity available.\n  // If all these conditions are met, a non-empty span is returned, and the\n  // length of the flat node and involved tree nodes have been increased by\n  // `span.length()`. The caller is responsible for immediately assigning values\n  // to all uninitialized data reference by the returned span.\n  // Requires `this->refcount.IsOne()`: this function forces the caller to do\n  // this fast path check on the top level node, as this is the most commonly\n  // shared node of a cord tree.\n  Span<char> GetAppendBuffer(size_t size);\n\n  // Extracts the right-most data edge from this tree iff:\n  // - the tree and all internal edges to the right-most node are not shared.\n  // - the right-most node is a FLAT node and not shared.\n  // - the right-most node has at least the desired extra capacity.\n  //\n  // Returns {tree, nullptr} if any of the above conditions are not met.\n  // This method effectively removes data from the tree. The intent of this\n  // method is to allow applications appending small string data to use\n  // pre-existing capacity, and add the modified rep back to the tree.\n  //\n  // Simplified such code would look similar to this:\n  //   void MyTreeBuilder::Append(string_view data) {\n  //     ExtractResult result = CordRepBtree::ExtractAppendBuffer(tree_, 1);\n  //     if (CordRep* rep = result.extracted) {\n  //       size_t available = rep->Capacity() - rep->length;\n  //       size_t n = std::min(data.size(), n);\n  //       memcpy(rep->Data(), data.data(), n);\n  //       rep->length += n;\n  //       data.remove_prefix(n);\n  //       if (!result.tree->IsBtree()) {\n  //         tree_ = CordRepBtree::Create(result.tree);\n  //       }\n  //       tree_ = CordRepBtree::Append(tree_, rep);\n  //     }\n  //     ...\n  //     // Remaining edge in `result.tree`.\n  //   }\n  static ExtractResult ExtractAppendBuffer(CordRepBtree* tree,\n                                           size_t extra_capacity = 1);\n\n  // Returns the `height` of the tree. The height of a tree is limited to\n  // kMaxHeight. `height` is implemented as an `int` as in some places we\n  // use negative (-1) values for 'data edges'.\n  int height() const { return static_cast<int>(storage[0]); }\n\n  // Properties: begin, back, end, front/back boundary indexes.\n  size_t begin() const { return static_cast<size_t>(storage[1]); }\n  size_t back() const { return static_cast<size_t>(storage[2]) - 1; }\n  size_t end() const { return static_cast<size_t>(storage[2]); }\n  size_t index(EdgeType edge) const {\n    return edge == kFront ? begin() : back();\n  }\n\n  // Properties: size and capacity.\n  // `capacity` contains the current capacity of this instance, where\n  // `kMaxCapacity` contains the maximum capacity of a btree node.\n  // For now, `capacity` and `kMaxCapacity` return the same value, but this may\n  // change in the future if we see benefit in dynamically sizing 'small' nodes\n  // to 'large' nodes for large data trees.\n  size_t size() const { return end() - begin(); }\n  size_t capacity() const { return kMaxCapacity; }\n\n  // Edge access\n  inline CordRep* Edge(size_t index) const;\n  inline CordRep* Edge(EdgeType edge_type) const;\n  inline absl::Span<CordRep* const> Edges() const;\n  inline absl::Span<CordRep* const> Edges(size_t begin, size_t end) const;\n\n  // Returns reference to the data edge at `index`.\n  // Requires this instance to be a leaf node, and `index` to be valid index.\n  inline absl::string_view Data(size_t index) const;\n\n  // Diagnostics: returns true if `tree` is valid and internally consistent.\n  // If `shallow` is false, then the provided top level node and all child nodes\n  // below it are recursively checked. If `shallow` is true, only the provided\n  // node in `tree` and the cumulative length, type and height of the direct\n  // child nodes of `tree` are checked. The value of `shallow` is ignored if the\n  // internal `cord_btree_exhaustive_validation` diagnostics variable is true,\n  // in which case the performed validations works as if `shallow` were false.\n  // This function is intended for debugging and testing purposes only.\n  static bool IsValid(const CordRepBtree* tree, bool shallow = false);\n\n  // Diagnostics: asserts that the provided tree is valid.\n  // `AssertValid()` performs a shallow validation by default. `shallow` can be\n  // set to false in which case an exhaustive validation is performed. This\n  // function is implemented in terms of calling `IsValid()` and asserting the\n  // return value to be true. See `IsValid()` for more information.\n  // This function is intended for debugging and testing purposes only.\n  static CordRepBtree* AssertValid(CordRepBtree* tree, bool shallow = true);\n  static const CordRepBtree* AssertValid(const CordRepBtree* tree,\n                                         bool shallow = true);\n\n  // Diagnostics: dump the contents of this tree to `stream`.\n  // This function is intended for debugging and testing purposes only.\n  static void Dump(const CordRep* rep, std::ostream& stream);\n  static void Dump(const CordRep* rep, absl::string_view label,\n                   std::ostream& stream);\n  static void Dump(const CordRep* rep, absl::string_view label,\n                   bool include_contents, std::ostream& stream);\n\n  // Adds the edge `edge` to this node if possible. `owned` indicates if the\n  // current node is potentially shared or not with other threads. Returns:\n  // - {kSelf, <this>}\n  //   The edge was directly added to this node.\n  // - {kCopied, <node>}\n  //   The edge was added to a copy of this node.\n  // - {kPopped, New(edge, height())}\n  //   A new leg with the edge was created as this node has no extra capacity.\n  template <EdgeType edge_type>\n  inline OpResult AddEdge(bool owned, CordRep* edge, size_t delta);\n\n  // Replaces the front or back edge with the provided new edge. Returns:\n  // - {kSelf, <this>}\n  //   The edge was directly set in this node. The old edge is unreffed.\n  // - {kCopied, <node>}\n  //   A copy of this node was created with the new edge value.\n  // In both cases, the function adopts a reference on `edge`.\n  template <EdgeType edge_type>\n  OpResult SetEdge(bool owned, CordRep* edge, size_t delta);\n\n  // Creates a new empty node at the specified height.\n  static CordRepBtree* New(int height = 0);\n\n  // Creates a new node containing `rep`, with the height being computed\n  // automatically based on the type of `rep`.\n  static CordRepBtree* New(CordRep* rep);\n\n  // Creates a new node containing both `front` and `back` at height\n  // `front.height() + 1`. Requires `back.height() == front.height()`.\n  static CordRepBtree* New(CordRepBtree* front, CordRepBtree* back);\n\n  // Creates a fully balanced tree from the provided tree by rebuilding a new\n  // tree from all data edges in the input. This function is automatically\n  // invoked internally when the tree exceeds the maximum height.\n  static CordRepBtree* Rebuild(CordRepBtree* tree);\n\n private:\n  CordRepBtree() = default;\n  ~CordRepBtree() = default;\n\n  // Initializes the main properties `tag`, `begin`, `end`, `height`.\n  inline void InitInstance(int height, size_t begin = 0, size_t end = 0);\n\n  // Direct property access begin / end\n  void set_begin(size_t begin) { storage[1] = static_cast<uint8_t>(begin); }\n  void set_end(size_t end) { storage[2] = static_cast<uint8_t>(end); }\n\n  // Decreases the value of `begin` by `n`, and returns the new value. Notice\n  // how this returns the new value unlike atomic::fetch_add which returns the\n  // old value. This is because this is used to prepend edges at 'begin - 1'.\n  size_t sub_fetch_begin(size_t n) {\n    storage[1] -= static_cast<uint8_t>(n);\n    return storage[1];\n  }\n\n  // Increases the value of `end` by `n`, and returns the previous value. This\n  // function is typically used to append edges at 'end'.\n  size_t fetch_add_end(size_t n) {\n    const uint8_t current = storage[2];\n    storage[2] = static_cast<uint8_t>(current + n);\n    return current;\n  }\n\n  // Returns the index of the last edge starting on, or before `offset`, with\n  // `n` containing the relative offset of `offset` inside that edge.\n  // Requires `offset` < length.\n  Position IndexOf(size_t offset) const;\n\n  // Returns the index of the last edge starting before `offset`, with `n`\n  // containing the relative offset of `offset` inside that edge.\n  // This function is useful to find the edges for some span of bytes ending at\n  // `offset` (i.e., `n` bytes). For example:\n  //\n  //   Position pos = IndexBefore(n)\n  //   edges = Edges(begin(), pos.index)     // All full edges (may be empty)\n  //   last = Sub(Edge(pos.index), 0, pos.n) // Last partial edge (may be empty)\n  //\n  // Requires 0 < `offset` <= length.\n  Position IndexBefore(size_t offset) const;\n\n  // Returns the index of the edge ending at (or on) length `length`, and the\n  // number of bytes inside that edge up to `length`. For example, if we have a\n  // Node with 2 edges, one of 10 and one of 20 long, then IndexOfLength(27)\n  // will return {1, 17}, and IndexOfLength(10) will return {0, 10}.\n  Position IndexOfLength(size_t n) const;\n\n  // Identical to the above function except starting from the position `front`.\n  // This function is equivalent to `IndexBefore(front.n + offset)`, with\n  // the difference that this function is optimized to start at `front.index`.\n  Position IndexBefore(Position front, size_t offset) const;\n\n  // Returns the index of the edge directly beyond the edge containing offset\n  // `offset`, with `n` containing the distance of that edge from `offset`.\n  // This function is useful for iteratively finding suffix nodes and remaining\n  // partial bytes in left-most suffix nodes as for example in CopySuffix.\n  // Requires `offset` < length.\n  Position IndexBeyond(size_t offset) const;\n\n  // Creates a new leaf node containing as much data as possible from `data`.\n  // The data is added either forwards or reversed depending on `edge_type`.\n  // Callers must check the length of the returned node to determine if all data\n  // was copied or not.\n  // See the `Append/Prepend` function for the meaning and purpose of `extra`.\n  template <EdgeType edge_type>\n  static CordRepBtree* NewLeaf(absl::string_view data, size_t extra);\n\n  // Creates a raw copy of this Btree node with the specified length, copying\n  // all properties, but without adding any references to existing edges.\n  CordRepBtree* CopyRaw(size_t new_length) const;\n\n  // Creates a full copy of this Btree node, adding a reference on all edges.\n  CordRepBtree* Copy() const;\n\n  // Creates a partial copy of this Btree node, copying all edges up to `end`,\n  // adding a reference on each copied edge, and sets the length of the newly\n  // created copy to `new_length`.\n  CordRepBtree* CopyBeginTo(size_t end, size_t new_length) const;\n\n  // Returns a tree containing the edges [tree->begin(), end) and length\n  // of `new_length`. This method consumes a reference on the provided\n  // tree, and logically performs the following operation:\n  //   result = tree->CopyBeginTo(end, new_length);\n  //   CordRep::Unref(tree);\n  //   return result;\n  static CordRepBtree* ConsumeBeginTo(CordRepBtree* tree, size_t end,\n                                      size_t new_length);\n\n  // Creates a partial copy of this Btree node, copying all edges starting at\n  // `begin`, adding a reference on each copied edge, and sets the length of\n  // the newly created copy to `new_length`.\n  CordRepBtree* CopyToEndFrom(size_t begin, size_t new_length) const;\n\n  // Extracts and returns the front edge from the provided tree.\n  // This method consumes a reference on the provided tree, and logically\n  // performs the following operation:\n  //   edge = CordRep::Ref(tree->Edge(kFront));\n  //   CordRep::Unref(tree);\n  //   return edge;\n  static CordRep* ExtractFront(CordRepBtree* tree);\n\n  // Returns a tree containing the result of appending `right` to `left`.\n  static CordRepBtree* MergeTrees(CordRepBtree* left, CordRepBtree* right);\n\n  // Fallback functions for `Create()`, `Append()` and `Prepend()` which\n  // deal with legacy / non conforming input, i.e.: CONCAT trees.\n  static CordRepBtree* CreateSlow(CordRep* rep);\n  static CordRepBtree* AppendSlow(CordRepBtree*, CordRep* rep);\n  static CordRepBtree* PrependSlow(CordRepBtree*, CordRep* rep);\n\n  // Recursively rebuilds `tree` into `stack`. If 'consume` is set to true, the\n  // function will consume a reference on `tree`. `stack` is a null terminated\n  // array containing the new tree's state, with the current leaf node at\n  // stack[0], and parent nodes above that, or null for 'top of tree'.\n  static void Rebuild(CordRepBtree** stack, CordRepBtree* tree, bool consume);\n\n  // Aligns existing edges to start at index 0, to allow for a new edge to be\n  // added to the back of the current edges.\n  inline void AlignBegin();\n\n  // Aligns existing edges to end at `capacity`, to allow for a new edge to be\n  // added in front of the current edges.\n  inline void AlignEnd();\n\n  // Adds the provided edge to this node.\n  // Requires this node to have capacity for the edge. Realigns / moves\n  // existing edges as needed to prepend or append the new edge.\n  template <EdgeType edge_type>\n  inline void Add(CordRep* rep);\n\n  // Adds the provided edges to this node.\n  // Requires this node to have capacity for the edges. Realigns / moves\n  // existing edges as needed to prepend or append the new edges.\n  template <EdgeType edge_type>\n  inline void Add(absl::Span<CordRep* const>);\n\n  // Adds data from `data` to this node until either all data has been consumed,\n  // or there is no more capacity for additional flat nodes inside this node.\n  // Requires the current node to be a leaf node, data to be non empty, and the\n  // current node to have capacity for at least one more data edge.\n  // Returns any remaining data from `data` that was not added, which is\n  // depending on the edge type (front / back) either the remaining prefix of\n  // suffix of the input.\n  // See the `Append/Prepend` function for the meaning and purpose of `extra`.\n  template <EdgeType edge_type>\n  absl::string_view AddData(absl::string_view data, size_t extra);\n\n  // Replace the front or back edge with the provided value.\n  // Adopts a reference on `edge` and unrefs the old edge.\n  template <EdgeType edge_type>\n  inline void SetEdge(CordRep* edge);\n\n  // Returns a partial copy of the current tree containing the first `n` bytes\n  // of data. `CopyResult` contains both the resulting edge and its height. The\n  // resulting tree may be less high than the current tree, or even be a single\n  // matching data edge if `allow_folding` is set to true.\n  // For example, if `n == 1`, then the result will be the single data edge, and\n  // height will be set to -1 (one below the owning leaf node). If n == 0, this\n  // function returns null. Requires `n <= length`\n  CopyResult CopyPrefix(size_t n, bool allow_folding = true);\n\n  // Returns a partial copy of the current tree containing all data starting\n  // after `offset`. `CopyResult` contains both the resulting edge and its\n  // height. The resulting tree may be less high than the current tree, or even\n  // be a single matching data edge. For example, if `n == length - 1`, then the\n  // result will be a single data edge, and height will be set to -1 (one below\n  // the owning leaf node).\n  // Requires `offset < length`\n  CopyResult CopySuffix(size_t offset);\n\n  // Returns a OpResult value of {this, kSelf} or {Copy(), kCopied}\n  // depending on the value of `owned`.\n  inline OpResult ToOpResult(bool owned);\n\n  // Adds `rep` to the specified tree, returning the modified tree.\n  template <EdgeType edge_type>\n  static CordRepBtree* AddCordRep(CordRepBtree* tree, CordRep* rep);\n\n  // Adds `data` to the specified tree, returning the modified tree.\n  // See the `Append/Prepend` function for the meaning and purpose of `extra`.\n  template <EdgeType edge_type>\n  static CordRepBtree* AddData(CordRepBtree* tree, absl::string_view data,\n                               size_t extra = 0);\n\n  // Merges `src` into `dst` with `src` being added either before (kFront) or\n  // after (kBack) `dst`. Requires the height of `dst` to be greater than or\n  // equal to the height of `src`.\n  template <EdgeType edge_type>\n  static CordRepBtree* Merge(CordRepBtree* dst, CordRepBtree* src);\n\n  // Fallback version of GetAppendBuffer for large trees: GetAppendBuffer()\n  // implements an inlined version for trees of limited height (3 levels),\n  // GetAppendBufferSlow implements the logic for large trees.\n  Span<char> GetAppendBufferSlow(size_t size);\n\n  // `edges_` contains all edges starting from this instance.\n  // These are explicitly `child` edges only, a cord btree (or any cord tree in\n  // that respect) does not store `parent` pointers anywhere: multiple trees /\n  // parents can reference the same shared child edge. The type of these edges\n  // depends on the height of the node. `Leaf nodes` (height == 0) contain `data\n  // edges` (external or flat nodes, or sub-strings thereof). All other nodes\n  // (height > 0) contain pointers to BTREE nodes with a height of `height - 1`.\n  CordRep* edges_[kMaxCapacity];\n\n  friend class CordRepBtreeTestPeer;\n  friend class CordRepBtreeNavigator;\n};\n\ninline CordRepBtree* CordRep::btree() {\n  assert(IsBtree());\n  return static_cast<CordRepBtree*>(this);\n}\n\ninline const CordRepBtree* CordRep::btree() const {\n  assert(IsBtree());\n  return static_cast<const CordRepBtree*>(this);\n}\n\ninline void CordRepBtree::InitInstance(int height, size_t begin, size_t end) {\n  tag = BTREE;\n  storage[0] = static_cast<uint8_t>(height);\n  storage[1] = static_cast<uint8_t>(begin);\n  storage[2] = static_cast<uint8_t>(end);\n}\n\ninline CordRep* CordRepBtree::Edge(size_t index) const {\n  assert(index >= begin());\n  assert(index < end());\n  return edges_[index];\n}\n\ninline CordRep* CordRepBtree::Edge(EdgeType edge_type) const {\n  return edges_[edge_type == kFront ? begin() : back()];\n}\n\ninline absl::Span<CordRep* const> CordRepBtree::Edges() const {\n  return {edges_ + begin(), size()};\n}\n\ninline absl::Span<CordRep* const> CordRepBtree::Edges(size_t begin,\n                                                      size_t end) const {\n  assert(begin <= end);\n  assert(begin >= this->begin());\n  assert(end <= this->end());\n  return {edges_ + begin, static_cast<size_t>(end - begin)};\n}\n\ninline absl::string_view CordRepBtree::Data(size_t index) const {\n  assert(height() == 0);\n  return EdgeData(Edge(index));\n}\n\ninline CordRepBtree* CordRepBtree::New(int height) {\n  CordRepBtree* tree = new CordRepBtree;\n  tree->length = 0;\n  tree->InitInstance(height);\n  return tree;\n}\n\ninline CordRepBtree* CordRepBtree::New(CordRep* rep) {\n  CordRepBtree* tree = new CordRepBtree;\n  int height = rep->IsBtree() ? rep->btree()->height() + 1 : 0;\n  tree->length = rep->length;\n  tree->InitInstance(height, /*begin=*/0, /*end=*/1);\n  tree->edges_[0] = rep;\n  return tree;\n}\n\ninline CordRepBtree* CordRepBtree::New(CordRepBtree* front,\n                                       CordRepBtree* back) {\n  assert(front->height() == back->height());\n  CordRepBtree* tree = new CordRepBtree;\n  tree->length = front->length + back->length;\n  tree->InitInstance(front->height() + 1, /*begin=*/0, /*end=*/2);\n  tree->edges_[0] = front;\n  tree->edges_[1] = back;\n  return tree;\n}\n\ninline void CordRepBtree::Unref(absl::Span<CordRep* const> edges) {\n  for (CordRep* edge : edges) {\n    if (ABSL_PREDICT_FALSE(!edge->refcount.Decrement())) {\n      CordRep::Destroy(edge);\n    }\n  }\n}\n\ninline CordRepBtree* CordRepBtree::CopyRaw(size_t new_length) const {\n  CordRepBtree* tree = new CordRepBtree;\n\n  // `length` and `refcount` are the first members of `CordRepBtree`.\n  // We initialize `length` using the given length, have `refcount` be set to\n  // ref = 1 through its default constructor, and copy all data beyond\n  // 'refcount' which starts with `tag` using a single memcpy: all contents\n  // except `refcount` is trivially copyable, and the compiler does not\n  // efficiently coalesce member-wise copy of these members.\n  // See https://gcc.godbolt.org/z/qY8zsca6z\n  // LINT.IfChange(copy_raw)\n  tree->length = new_length;\n  uint8_t* dst = &tree->tag;\n  const uint8_t* src = &tag;\n  const ptrdiff_t offset = src - reinterpret_cast<const uint8_t*>(this);\n  memcpy(dst, src, sizeof(CordRepBtree) - static_cast<size_t>(offset));\n  return tree;\n  // LINT.ThenChange()\n}\n\ninline CordRepBtree* CordRepBtree::Copy() const {\n  CordRepBtree* tree = CopyRaw(length);\n  for (CordRep* rep : Edges()) CordRep::Ref(rep);\n  return tree;\n}\n\ninline CordRepBtree* CordRepBtree::CopyToEndFrom(size_t begin,\n                                                 size_t new_length) const {\n  assert(begin >= this->begin());\n  assert(begin <= this->end());\n  CordRepBtree* tree = CopyRaw(new_length);\n  tree->set_begin(begin);\n  for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);\n  return tree;\n}\n\ninline CordRepBtree* CordRepBtree::CopyBeginTo(size_t end,\n                                               size_t new_length) const {\n  assert(end <= capacity());\n  assert(end >= this->begin());\n  CordRepBtree* tree = CopyRaw(new_length);\n  tree->set_end(end);\n  for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);\n  return tree;\n}\n\ninline void CordRepBtree::AlignBegin() {\n  // The below code itself does not need to be fast as typically we have\n  // mono-directional append/prepend calls, and `begin` / `end` are typically\n  // adjusted no more than once. But we want to avoid potential register clobber\n  // effects, making the compiler emit register save/store/spills, and minimize\n  // the size of code.\n  const size_t delta = begin();\n  if (ABSL_PREDICT_FALSE(delta != 0)) {\n    const size_t new_end = end() - delta;\n    set_begin(0);\n    set_end(new_end);\n    // TODO(mvels): we can write this using 2 loads / 2 stores depending on\n    // total size for the kMaxCapacity = 6 case. I.e., we can branch (switch) on\n    // size, and then do overlapping load/store of up to 4 pointers (inlined as\n    // XMM, YMM or ZMM load/store) and up to 2 pointers (XMM / YMM), which is a)\n    // compact and b) not clobbering any registers.\n    ABSL_ASSUME(new_end <= kMaxCapacity);\n#ifdef __clang__\n#pragma unroll 1\n#endif\n    for (size_t i = 0; i < new_end; ++i) {\n      edges_[i] = edges_[i + delta];\n    }\n  }\n}\n\ninline void CordRepBtree::AlignEnd() {\n  // See comments in `AlignBegin` for motivation on the hand-rolled for loops.\n  const size_t delta = capacity() - end();\n  if (delta != 0) {\n    const size_t new_begin = begin() + delta;\n    const size_t new_end = end() + delta;\n    set_begin(new_begin);\n    set_end(new_end);\n    ABSL_ASSUME(new_end <= kMaxCapacity);\n#ifdef __clang__\n#pragma unroll 1\n#endif\n    for (size_t i = new_end - 1; i >= new_begin; --i) {\n      edges_[i] = edges_[i - delta];\n    }\n  }\n}\n\ntemplate <>\ninline void CordRepBtree::Add<CordRepBtree::kBack>(CordRep* rep) {\n  AlignBegin();\n  edges_[fetch_add_end(1)] = rep;\n}\n\ntemplate <>\ninline void CordRepBtree::Add<CordRepBtree::kBack>(\n    absl::Span<CordRep* const> edges) {\n  AlignBegin();\n  size_t new_end = end();\n  for (CordRep* edge : edges) edges_[new_end++] = edge;\n  set_end(new_end);\n}\n\ntemplate <>\ninline void CordRepBtree::Add<CordRepBtree::kFront>(CordRep* rep) {\n  AlignEnd();\n  edges_[sub_fetch_begin(1)] = rep;\n}\n\ntemplate <>\ninline void CordRepBtree::Add<CordRepBtree::kFront>(\n    absl::Span<CordRep* const> edges) {\n  AlignEnd();\n  size_t new_begin = begin() - edges.size();\n  set_begin(new_begin);\n  for (CordRep* edge : edges) edges_[new_begin++] = edge;\n}\n\ntemplate <CordRepBtree::EdgeType edge_type>\ninline void CordRepBtree::SetEdge(CordRep* edge) {\n  const int idx = edge_type == kFront ? begin() : back();\n  CordRep::Unref(edges_[idx]);\n  edges_[idx] = edge;\n}\n\ninline CordRepBtree::OpResult CordRepBtree::ToOpResult(bool owned) {\n  return owned ? OpResult{this, kSelf} : OpResult{Copy(), kCopied};\n}\n\ninline CordRepBtree::Position CordRepBtree::IndexOf(size_t offset) const {\n  assert(offset < length);\n  size_t index = begin();\n  while (offset >= edges_[index]->length) offset -= edges_[index++]->length;\n  return {index, offset};\n}\n\ninline CordRepBtree::Position CordRepBtree::IndexBefore(size_t offset) const {\n  assert(offset > 0);\n  assert(offset <= length);\n  size_t index = begin();\n  while (offset > edges_[index]->length) offset -= edges_[index++]->length;\n  return {index, offset};\n}\n\ninline CordRepBtree::Position CordRepBtree::IndexBefore(Position front,\n                                                        size_t offset) const {\n  size_t index = front.index;\n  offset = offset + front.n;\n  while (offset > edges_[index]->length) offset -= edges_[index++]->length;\n  return {index, offset};\n}\n\ninline CordRepBtree::Position CordRepBtree::IndexOfLength(size_t n) const {\n  assert(n <= length);\n  size_t index = back();\n  size_t strip = length - n;\n  while (strip >= edges_[index]->length) strip -= edges_[index--]->length;\n  return {index, edges_[index]->length - strip};\n}\n\ninline CordRepBtree::Position CordRepBtree::IndexBeyond(\n    const size_t offset) const {\n  // We need to find the edge which `starting offset` is beyond (>=)`offset`.\n  // For this we can't use the `offset -= length` logic of IndexOf. Instead, we\n  // track the offset of the `current edge` in `off`, which we increase as we\n  // iterate over the edges until we find the matching edge.\n  size_t off = 0;\n  size_t index = begin();\n  while (offset > off) off += edges_[index++]->length;\n  return {index, off - offset};\n}\n\ninline CordRepBtree* CordRepBtree::Create(CordRep* rep) {\n  if (IsDataEdge(rep)) return New(rep);\n  return CreateSlow(rep);\n}\n\ninline Span<char> CordRepBtree::GetAppendBuffer(size_t size) {\n  assert(refcount.IsOne());\n  CordRepBtree* tree = this;\n  const int height = this->height();\n  CordRepBtree* n1 = tree;\n  CordRepBtree* n2 = tree;\n  CordRepBtree* n3 = tree;\n  switch (height) {\n    case 3:\n      tree = tree->Edge(kBack)->btree();\n      if (!tree->refcount.IsOne()) return {};\n      n2 = tree;\n      ABSL_FALLTHROUGH_INTENDED;\n    case 2:\n      tree = tree->Edge(kBack)->btree();\n      if (!tree->refcount.IsOne()) return {};\n      n1 = tree;\n      ABSL_FALLTHROUGH_INTENDED;\n    case 1:\n      tree = tree->Edge(kBack)->btree();\n      if (!tree->refcount.IsOne()) return {};\n      ABSL_FALLTHROUGH_INTENDED;\n    case 0:\n      CordRep* edge = tree->Edge(kBack);\n      if (!edge->refcount.IsOne()) return {};\n      if (edge->tag < FLAT) return {};\n      size_t avail = edge->flat()->Capacity() - edge->length;\n      if (avail == 0) return {};\n      size_t delta = (std::min)(size, avail);\n      Span<char> span = {edge->flat()->Data() + edge->length, delta};\n      edge->length += delta;\n      switch (height) {\n        case 3:\n          n3->length += delta;\n          ABSL_FALLTHROUGH_INTENDED;\n        case 2:\n          n2->length += delta;\n          ABSL_FALLTHROUGH_INTENDED;\n        case 1:\n          n1->length += delta;\n          ABSL_FALLTHROUGH_INTENDED;\n        case 0:\n          tree->length += delta;\n          return span;\n      }\n      break;\n  }\n  return GetAppendBufferSlow(size);\n}\n\nextern template CordRepBtree* CordRepBtree::AddCordRep<CordRepBtree::kBack>(\n    CordRepBtree* tree, CordRep* rep);\n\nextern template CordRepBtree* CordRepBtree::AddCordRep<CordRepBtree::kFront>(\n    CordRepBtree* tree, CordRep* rep);\n\ninline CordRepBtree* CordRepBtree::Append(CordRepBtree* tree, CordRep* rep) {\n  if (ABSL_PREDICT_TRUE(IsDataEdge(rep))) {\n    return CordRepBtree::AddCordRep<kBack>(tree, rep);\n  }\n  return AppendSlow(tree, rep);\n}\n\ninline CordRepBtree* CordRepBtree::Prepend(CordRepBtree* tree, CordRep* rep) {\n  if (ABSL_PREDICT_TRUE(IsDataEdge(rep))) {\n    return CordRepBtree::AddCordRep<kFront>(tree, rep);\n  }\n  return PrependSlow(tree, rep);\n}\n\n#ifdef NDEBUG\n\ninline CordRepBtree* CordRepBtree::AssertValid(CordRepBtree* tree,\n                                               bool /* shallow */) {\n  return tree;\n}\n\ninline const CordRepBtree* CordRepBtree::AssertValid(const CordRepBtree* tree,\n                                                     bool /* shallow */) {\n  return tree;\n}\n\n#endif\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_navigator.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_btree_navigator.h\"\n\n#include <cassert>\n\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nusing ReadResult = CordRepBtreeNavigator::ReadResult;\n\nnamespace {\n\n// Returns a `CordRepSubstring` from `rep` starting at `offset` of size `n`.\n// If `rep` is already a `CordRepSubstring` instance, an adjusted instance is\n// created based on the old offset and new offset.\n// Adopts a reference on `rep`. Rep must be a valid data edge. Returns\n// nullptr if `n == 0`, `rep` if `n == rep->length`.\n// Requires `offset < rep->length` and `offset + n <= rep->length`.\n// TODO(192061034): move to utility library in internal and optimize for small\n// substrings of larger reps.\ninline CordRep* Substring(CordRep* rep, size_t offset, size_t n) {\n  assert(n <= rep->length);\n  assert(offset < rep->length);\n  assert(offset <= rep->length - n);\n  assert(IsDataEdge(rep));\n\n  if (n == 0) return nullptr;\n  if (n == rep->length) return CordRep::Ref(rep);\n\n  if (rep->tag == SUBSTRING) {\n    offset += rep->substring()->start;\n    rep = rep->substring()->child;\n  }\n\n  assert(rep->IsExternal() || rep->IsFlat());\n  CordRepSubstring* substring = new CordRepSubstring();\n  substring->length = n;\n  substring->tag = SUBSTRING;\n  substring->start = offset;\n  substring->child = CordRep::Ref(rep);\n  return substring;\n}\n\ninline CordRep* Substring(CordRep* rep, size_t offset) {\n  return Substring(rep, offset, rep->length - offset);\n}\n\n}  // namespace\n\nCordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {\n  int height = 0;\n  size_t index = index_[0];\n  CordRepBtree* node = node_[0];\n  CordRep* edge = node->Edge(index);\n\n  // Overall logic: Find an edge of at least the length we need to skip.\n  // We consume all edges which are smaller (i.e., must be 100% skipped).\n  // If we exhausted all edges on the current level, we move one level\n  // up the tree, and repeat until we either find the edge, or until we hit\n  // the top of the tree meaning the skip exceeds tree->length.\n  while (n >= edge->length) {\n    n -= edge->length;\n    while (++index == node->end()) {\n      if (++height > height_) return {nullptr, n};\n      node = node_[height];\n      index = index_[height];\n    }\n    edge = node->Edge(index);\n  }\n\n  // If we moved up the tree, descend down to the leaf level, consuming all\n  // edges that must be skipped.\n  while (height > 0) {\n    node = edge->btree();\n    index_[height] = static_cast<uint8_t>(index);\n    node_[--height] = node;\n    index = node->begin();\n    edge = node->Edge(index);\n    while (n >= edge->length) {\n      n -= edge->length;\n      ++index;\n      assert(index != node->end());\n      edge = node->Edge(index);\n    }\n  }\n  index_[0] = static_cast<uint8_t>(index);\n  return {edge, n};\n}\n\nReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {\n  int height = 0;\n  size_t length = edge_offset + n;\n  size_t index = index_[0];\n  CordRepBtree* node = node_[0];\n  CordRep* edge = node->Edge(index);\n  assert(edge_offset < edge->length);\n\n  if (length < edge->length) {\n    return {Substring(edge, edge_offset, n), length};\n  }\n\n  // Similar to 'Skip', we consume all edges that are inside the 'length' of\n  // data that needs to be read. If we exhaust the current level, we move one\n  // level up the tree and repeat until we hit the final edge that must be\n  // (partially) read. We consume all edges into `subtree`.\n  CordRepBtree* subtree = CordRepBtree::New(Substring(edge, edge_offset));\n  size_t subtree_end = 1;\n  do {\n    length -= edge->length;\n    while (++index == node->end()) {\n      index_[height] = static_cast<uint8_t>(index);\n      if (++height > height_) {\n        subtree->set_end(subtree_end);\n        if (length == 0) return {subtree, 0};\n        CordRep::Unref(subtree);\n        return {nullptr, length};\n      }\n      if (length != 0) {\n        subtree->set_end(subtree_end);\n        subtree = CordRepBtree::New(subtree);\n        subtree_end = 1;\n      }\n      node = node_[height];\n      index = index_[height];\n    }\n    edge = node->Edge(index);\n    if (length >= edge->length) {\n      subtree->length += edge->length;\n      subtree->edges_[subtree_end++] = CordRep::Ref(edge);\n    }\n  } while (length >= edge->length);\n  CordRepBtree* tree = subtree;\n  subtree->length += length;\n\n  // If we moved up the tree, descend down to the leaf level, consuming all\n  // edges that must be read, adding 'down' nodes to `subtree`.\n  while (height > 0) {\n    node = edge->btree();\n    index_[height] = static_cast<uint8_t>(index);\n    node_[--height] = node;\n    index = node->begin();\n    edge = node->Edge(index);\n\n    if (length != 0) {\n      CordRepBtree* right = CordRepBtree::New(height);\n      right->length = length;\n      subtree->edges_[subtree_end++] = right;\n      subtree->set_end(subtree_end);\n      subtree = right;\n      subtree_end = 0;\n      while (length >= edge->length) {\n        subtree->edges_[subtree_end++] = CordRep::Ref(edge);\n        length -= edge->length;\n        edge = node->Edge(++index);\n      }\n    }\n  }\n  // Add any (partial) edge still remaining at the leaf level.\n  if (length != 0) {\n    subtree->edges_[subtree_end++] = Substring(edge, 0, length);\n  }\n  subtree->set_end(subtree_end);\n  index_[0] = static_cast<uint8_t>(index);\n  return {tree, length};\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_navigator.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_\n\n#include <cassert>\n#include <iostream>\n\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordRepBtreeNavigator is a bi-directional navigator allowing callers to\n// navigate all the (leaf) data edges in a CordRepBtree instance.\n//\n// A CordRepBtreeNavigator instance is by default empty. Callers initialize a\n// navigator instance by calling one of `InitFirst()`, `InitLast()` or\n// `InitOffset()`, which establishes a current position. Callers can then\n// navigate using the `Next`, `Previous`, `Skip` and `Seek` methods.\n//\n// The navigator instance does not take or adopt a reference on the provided\n// `tree` on any of the initialization calls. Callers are responsible for\n// guaranteeing the lifecycle of the provided tree. A navigator instance can\n// be reset to the empty state by calling `Reset`.\n//\n// A navigator only keeps positional state on the 'current data edge', it does\n// explicitly not keep any 'offset' state. The class does accept and return\n// offsets in the `Read()`, `Skip()` and 'Seek()` methods as these would\n// otherwise put a big burden on callers. Callers are expected to maintain\n// (returned) offset info if they require such granular state.\nclass CordRepBtreeNavigator {\n public:\n  // The logical position as returned by the Seek() and Skip() functions.\n  // Returns the current leaf edge for the desired seek or skip position and\n  // the offset of that position inside that edge.\n  struct Position {\n    CordRep* edge;\n    size_t offset;\n  };\n\n  // The read result as returned by the Read() function.\n  // `tree` contains the resulting tree which is identical to the result\n  // of calling CordRepBtree::SubTree(...) on the tree being navigated.\n  // `n` contains the number of bytes used from the last navigated to\n  // edge of the tree.\n  struct ReadResult {\n    CordRep* tree;\n    size_t n;\n  };\n\n  // Returns true if this instance is not empty.\n  explicit operator bool() const;\n\n  // Returns the tree for this instance or nullptr if empty.\n  CordRepBtree* btree() const;\n\n  // Returns the data edge of the current position.\n  // Requires this instance to not be empty.\n  CordRep* Current() const;\n\n  // Resets this navigator to `tree`, returning the first data edge in the tree.\n  CordRep* InitFirst(CordRepBtree* tree);\n\n  // Resets this navigator to `tree`, returning the last data edge in the tree.\n  CordRep* InitLast(CordRepBtree* tree);\n\n  // Resets this navigator to `tree` returning the data edge at position\n  // `offset` and the relative offset of `offset` into that data edge.\n  // Returns `Position.edge = nullptr` if the provided offset is greater\n  // than or equal to the length of the tree, in which case the state of\n  // the navigator instance remains unchanged.\n  Position InitOffset(CordRepBtree* tree, size_t offset);\n\n  // Navigates to the next data edge.\n  // Returns the next data edge or nullptr if there is no next data edge, in\n  // which case the current position remains unchanged.\n  CordRep* Next();\n\n  // Navigates to the previous data edge.\n  // Returns the previous data edge or nullptr if there is no previous data\n  // edge, in which case the current position remains unchanged.\n  CordRep* Previous();\n\n  // Navigates to the data edge at position `offset`. Returns the navigated to\n  // data edge in `Position.edge` and the relative offset of `offset` into that\n  // data edge in `Position.offset`. Returns `Position.edge = nullptr` if the\n  // provide offset is greater than or equal to the tree's length.\n  Position Seek(size_t offset);\n\n  // Reads `n` bytes of data starting at offset `edge_offset` of the current\n  // data edge, and returns the result in `ReadResult.tree`. `ReadResult.n`\n  // contains the 'bytes used` from the last / current data edge in the tree.\n  // This allows users that mix regular navigation (using string views) and\n  // 'read into cord' navigation to keep track of the current state, and which\n  // bytes have been consumed from a navigator.\n  // This function returns `ReadResult.tree = nullptr` if the requested length\n  // exceeds the length of the tree starting at the current data edge.\n  ReadResult Read(size_t edge_offset, size_t n);\n\n  // Skips `n` bytes forward from the current data edge, returning the navigated\n  // to data edge in `Position.edge` and `Position.offset` containing the offset\n  // inside that data edge. Note that the state of the navigator is left\n  // unchanged if `n` is smaller than the length of the current data edge.\n  Position Skip(size_t n);\n\n  // Resets this instance to the default / empty state.\n  void Reset();\n\n private:\n  // Slow path for Next() if Next() reached the end of a leaf node. Backtracks\n  // up the stack until it finds a node that has a 'next' position available,\n  // and then does a 'front dive' towards the next leaf node.\n  CordRep* NextUp();\n\n  // Slow path for Previous() if Previous() reached the beginning of a leaf\n  // node. Backtracks up the stack until it finds a node that has a 'previous'\n  // position available, and then does a 'back dive' towards the previous leaf\n  // node.\n  CordRep* PreviousUp();\n\n  // Generic implementation of InitFirst() and InitLast().\n  template <CordRepBtree::EdgeType edge_type>\n  CordRep* Init(CordRepBtree* tree);\n\n  // `height_` contains the height of the current tree, or -1 if empty.\n  int height_ = -1;\n\n  // `index_` and `node_` contain the navigation state as the 'path' to the\n  // current data edge which is at `node_[0]->Edge(index_[0])`. The contents\n  // of these are undefined until the instance is initialized (`height_ >= 0`).\n  uint8_t index_[CordRepBtree::kMaxDepth];\n  CordRepBtree* node_[CordRepBtree::kMaxDepth];\n};\n\n// Returns true if this instance is not empty.\ninline CordRepBtreeNavigator::operator bool() const { return height_ >= 0; }\n\ninline CordRepBtree* CordRepBtreeNavigator::btree() const {\n  return height_ >= 0 ? node_[height_] : nullptr;\n}\n\ninline CordRep* CordRepBtreeNavigator::Current() const {\n  assert(height_ >= 0);\n  return node_[0]->Edge(index_[0]);\n}\n\ninline void CordRepBtreeNavigator::Reset() { height_ = -1; }\n\ninline CordRep* CordRepBtreeNavigator::InitFirst(CordRepBtree* tree) {\n  return Init<CordRepBtree::kFront>(tree);\n}\n\ninline CordRep* CordRepBtreeNavigator::InitLast(CordRepBtree* tree) {\n  return Init<CordRepBtree::kBack>(tree);\n}\n\ntemplate <CordRepBtree::EdgeType edge_type>\ninline CordRep* CordRepBtreeNavigator::Init(CordRepBtree* tree) {\n  assert(tree != nullptr);\n  assert(tree->size() > 0);\n  assert(tree->height() <= CordRepBtree::kMaxHeight);\n  int height = height_ = tree->height();\n  size_t index = tree->index(edge_type);\n  node_[height] = tree;\n  index_[height] = static_cast<uint8_t>(index);\n  while (--height >= 0) {\n    tree = tree->Edge(index)->btree();\n    node_[height] = tree;\n    index = tree->index(edge_type);\n    index_[height] = static_cast<uint8_t>(index);\n  }\n  return node_[0]->Edge(index);\n}\n\ninline CordRepBtreeNavigator::Position CordRepBtreeNavigator::Seek(\n    size_t offset) {\n  assert(btree() != nullptr);\n  int height = height_;\n  CordRepBtree* edge = node_[height];\n  if (ABSL_PREDICT_FALSE(offset >= edge->length)) return {nullptr, 0};\n  CordRepBtree::Position index = edge->IndexOf(offset);\n  index_[height] = static_cast<uint8_t>(index.index);\n  while (--height >= 0) {\n    edge = edge->Edge(index.index)->btree();\n    node_[height] = edge;\n    index = edge->IndexOf(index.n);\n    index_[height] = static_cast<uint8_t>(index.index);\n  }\n  return {edge->Edge(index.index), index.n};\n}\n\ninline CordRepBtreeNavigator::Position CordRepBtreeNavigator::InitOffset(\n    CordRepBtree* tree, size_t offset) {\n  assert(tree != nullptr);\n  assert(tree->height() <= CordRepBtree::kMaxHeight);\n  if (ABSL_PREDICT_FALSE(offset >= tree->length)) return {nullptr, 0};\n  height_ = tree->height();\n  node_[height_] = tree;\n  return Seek(offset);\n}\n\ninline CordRep* CordRepBtreeNavigator::Next() {\n  CordRepBtree* edge = node_[0];\n  return index_[0] == edge->back() ? NextUp() : edge->Edge(++index_[0]);\n}\n\ninline CordRep* CordRepBtreeNavigator::Previous() {\n  CordRepBtree* edge = node_[0];\n  return index_[0] == edge->begin() ? PreviousUp() : edge->Edge(--index_[0]);\n}\n\ninline CordRep* CordRepBtreeNavigator::NextUp() {\n  assert(index_[0] == node_[0]->back());\n  CordRepBtree* edge;\n  size_t index;\n  int height = 0;\n  do {\n    if (++height > height_) return nullptr;\n    edge = node_[height];\n    index = index_[height] + 1;\n  } while (index == edge->end());\n  index_[height] = static_cast<uint8_t>(index);\n  do {\n    node_[--height] = edge = edge->Edge(index)->btree();\n    index_[height] = static_cast<uint8_t>(index = edge->begin());\n  } while (height > 0);\n  return edge->Edge(index);\n}\n\ninline CordRep* CordRepBtreeNavigator::PreviousUp() {\n  assert(index_[0] == node_[0]->begin());\n  CordRepBtree* edge;\n  size_t index;\n  int height = 0;\n  do {\n    if (++height > height_) return nullptr;\n    edge = node_[height];\n    index = index_[height];\n  } while (index == edge->begin());\n  index_[height] = static_cast<uint8_t>(--index);\n  do {\n    node_[--height] = edge = edge->Edge(index)->btree();\n    index_[height] = static_cast<uint8_t>(index = edge->back());\n  } while (height > 0);\n  return edge->Edge(index);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_navigator_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_btree_navigator.h\"\n\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_test_util.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::Ne;\n\nusing ::absl::cordrep_testing::CordRepBtreeFromFlats;\nusing ::absl::cordrep_testing::CordToString;\nusing ::absl::cordrep_testing::CreateFlatsFromString;\nusing ::absl::cordrep_testing::CreateRandomString;\nusing ::absl::cordrep_testing::MakeFlat;\nusing ::absl::cordrep_testing::MakeSubstring;\n\nusing ReadResult = CordRepBtreeNavigator::ReadResult;\nusing Position = CordRepBtreeNavigator::Position;\n\n// CordRepBtreeNavigatorTest is a test fixture which automatically creates a\n// tree to test navigation logic on. The parameter `count' defines the number of\n// data edges in the test tree.\nclass CordRepBtreeNavigatorTest : public testing::TestWithParam<size_t> {\n public:\n  using Flats = std::vector<CordRep*>;\n  static constexpr size_t kCharsPerFlat = 3;\n\n  CordRepBtreeNavigatorTest() {\n    data_ = CreateRandomString(count() * kCharsPerFlat);\n    flats_ = CreateFlatsFromString(data_, kCharsPerFlat);\n\n    // Turn flat 0 or 1 into a substring to cover partial reads on substrings.\n    if (count() > 1) {\n      CordRep::Unref(flats_[1]);\n      flats_[1] = MakeSubstring(kCharsPerFlat, kCharsPerFlat, MakeFlat(data_));\n    } else {\n      CordRep::Unref(flats_[0]);\n      flats_[0] = MakeSubstring(0, kCharsPerFlat, MakeFlat(data_));\n    }\n\n    tree_ = CordRepBtreeFromFlats(flats_);\n  }\n\n  ~CordRepBtreeNavigatorTest() override { CordRep::Unref(tree_); }\n\n  size_t count() const { return GetParam(); }\n  CordRepBtree* tree() { return tree_; }\n  const std::string& data() const { return data_; }\n  const std::vector<CordRep*>& flats() const { return flats_; }\n\n  static std::string ToString(testing::TestParamInfo<size_t> param) {\n    return absl::StrCat(param.param, \"_Flats\");\n  }\n\n private:\n  std::string data_;\n  Flats flats_;\n  CordRepBtree* tree_;\n};\n\nINSTANTIATE_TEST_SUITE_P(\n    WithParam, CordRepBtreeNavigatorTest,\n    testing::Values(1, CordRepBtree::kMaxCapacity - 1,\n                    CordRepBtree::kMaxCapacity,\n                    CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity - 1,\n                    CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity,\n                    CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity + 1,\n                    CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity * 2 +\n                        17),\n    CordRepBtreeNavigatorTest::ToString);\n\nTEST(CordRepBtreeNavigatorTest, Uninitialized) {\n  CordRepBtreeNavigator nav;\n  EXPECT_FALSE(nav);\n  EXPECT_THAT(nav.btree(), Eq(nullptr));\n#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n  EXPECT_DEATH(nav.Current(), \".*\");\n#endif\n}\n\nTEST_P(CordRepBtreeNavigatorTest, InitFirst) {\n  CordRepBtreeNavigator nav;\n  CordRep* edge = nav.InitFirst(tree());\n  EXPECT_TRUE(nav);\n  EXPECT_THAT(nav.btree(), Eq(tree()));\n  EXPECT_THAT(nav.Current(), Eq(flats().front()));\n  EXPECT_THAT(edge, Eq(flats().front()));\n}\n\nTEST_P(CordRepBtreeNavigatorTest, InitLast) {\n  CordRepBtreeNavigator nav;\n  CordRep* edge = nav.InitLast(tree());\n  EXPECT_TRUE(nav);\n  EXPECT_THAT(nav.btree(), Eq(tree()));\n  EXPECT_THAT(nav.Current(), Eq(flats().back()));\n  EXPECT_THAT(edge, Eq(flats().back()));\n}\n\nTEST_P(CordRepBtreeNavigatorTest, NextPrev) {\n  CordRepBtreeNavigator nav;\n  nav.InitFirst(tree());\n  const Flats& flats = this->flats();\n\n  EXPECT_THAT(nav.Previous(), Eq(nullptr));\n  EXPECT_THAT(nav.Current(), Eq(flats.front()));\n  for (size_t i = 1; i < flats.size(); ++i) {\n    ASSERT_THAT(nav.Next(), Eq(flats[i]));\n    EXPECT_THAT(nav.Current(), Eq(flats[i]));\n  }\n  EXPECT_THAT(nav.Next(), Eq(nullptr));\n  EXPECT_THAT(nav.Current(), Eq(flats.back()));\n  for (size_t i = flats.size() - 1; i > 0; --i) {\n    ASSERT_THAT(nav.Previous(), Eq(flats[i - 1]));\n    EXPECT_THAT(nav.Current(), Eq(flats[i - 1]));\n  }\n  EXPECT_THAT(nav.Previous(), Eq(nullptr));\n  EXPECT_THAT(nav.Current(), Eq(flats.front()));\n}\n\nTEST_P(CordRepBtreeNavigatorTest, PrevNext) {\n  CordRepBtreeNavigator nav;\n  nav.InitLast(tree());\n  const Flats& flats = this->flats();\n\n  EXPECT_THAT(nav.Next(), Eq(nullptr));\n  EXPECT_THAT(nav.Current(), Eq(flats.back()));\n  for (size_t i = flats.size() - 1; i > 0; --i) {\n    ASSERT_THAT(nav.Previous(), Eq(flats[i - 1]));\n    EXPECT_THAT(nav.Current(), Eq(flats[i - 1]));\n  }\n  EXPECT_THAT(nav.Previous(), Eq(nullptr));\n  EXPECT_THAT(nav.Current(), Eq(flats.front()));\n  for (size_t i = 1; i < flats.size(); ++i) {\n    ASSERT_THAT(nav.Next(), Eq(flats[i]));\n    EXPECT_THAT(nav.Current(), Eq(flats[i]));\n  }\n  EXPECT_THAT(nav.Next(), Eq(nullptr));\n  EXPECT_THAT(nav.Current(), Eq(flats.back()));\n}\n\nTEST(CordRepBtreeNavigatorTest, Reset) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeFlat(\"abc\"));\n  CordRepBtreeNavigator nav;\n  nav.InitFirst(tree);\n  nav.Reset();\n  EXPECT_FALSE(nav);\n  EXPECT_THAT(nav.btree(), Eq(nullptr));\n#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n  EXPECT_DEATH(nav.Current(), \".*\");\n#endif\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeNavigatorTest, Skip) {\n  size_t count = this->count();\n  const Flats& flats = this->flats();\n  CordRepBtreeNavigator nav;\n  nav.InitFirst(tree());\n\n  for (size_t char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {\n    Position pos = nav.Skip(char_offset);\n    EXPECT_THAT(pos.edge, Eq(nav.Current()));\n    EXPECT_THAT(pos.edge, Eq(flats[0]));\n    EXPECT_THAT(pos.offset, Eq(char_offset));\n  }\n\n  for (size_t index1 = 0; index1 < count; ++index1) {\n    for (size_t index2 = index1; index2 < count; ++index2) {\n      for (size_t char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {\n        CordRepBtreeNavigator nav;\n        nav.InitFirst(tree());\n\n        size_t length1 = index1 * kCharsPerFlat;\n        Position pos1 = nav.Skip(length1 + char_offset);\n        ASSERT_THAT(pos1.edge, Eq(flats[index1]));\n        ASSERT_THAT(pos1.edge, Eq(nav.Current()));\n        ASSERT_THAT(pos1.offset, Eq(char_offset));\n\n        size_t length2 = index2 * kCharsPerFlat;\n        Position pos2 = nav.Skip(length2 - length1 + char_offset);\n        ASSERT_THAT(pos2.edge, Eq(flats[index2]));\n        ASSERT_THAT(pos2.edge, Eq(nav.Current()));\n        ASSERT_THAT(pos2.offset, Eq(char_offset));\n      }\n    }\n  }\n}\n\nTEST_P(CordRepBtreeNavigatorTest, Seek) {\n  size_t count = this->count();\n  const Flats& flats = this->flats();\n  CordRepBtreeNavigator nav;\n  nav.InitFirst(tree());\n\n  for (size_t char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {\n    Position pos = nav.Seek(char_offset);\n    EXPECT_THAT(pos.edge, Eq(nav.Current()));\n    EXPECT_THAT(pos.edge, Eq(flats[0]));\n    EXPECT_THAT(pos.offset, Eq(char_offset));\n  }\n\n  for (size_t index = 0; index < count; ++index) {\n    for (size_t char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {\n      size_t offset = index * kCharsPerFlat + char_offset;\n      Position pos1 = nav.Seek(offset);\n      ASSERT_THAT(pos1.edge, Eq(flats[index]));\n      ASSERT_THAT(pos1.edge, Eq(nav.Current()));\n      ASSERT_THAT(pos1.offset, Eq(char_offset));\n    }\n  }\n}\n\nTEST(CordRepBtreeNavigatorTest, InitOffset) {\n  // Whitebox: InitOffset() is implemented in terms of Seek() which is\n  // exhaustively tested. Only test it initializes / forwards properly..\n  CordRepBtree* tree = CordRepBtree::Create(MakeFlat(\"abc\"));\n  tree = CordRepBtree::Append(tree, MakeFlat(\"def\"));\n  CordRepBtreeNavigator nav;\n  Position pos = nav.InitOffset(tree, 5);\n  EXPECT_TRUE(nav);\n  EXPECT_THAT(nav.btree(), Eq(tree));\n  EXPECT_THAT(pos.edge, Eq(tree->Edges()[1]));\n  EXPECT_THAT(pos.edge, Eq(nav.Current()));\n  EXPECT_THAT(pos.offset, Eq(2u));\n  CordRep::Unref(tree);\n}\n\nTEST(CordRepBtreeNavigatorTest, InitOffsetAndSeekBeyondLength) {\n  CordRepBtree* tree1 = CordRepBtree::Create(MakeFlat(\"abc\"));\n  CordRepBtree* tree2 = CordRepBtree::Create(MakeFlat(\"def\"));\n\n  CordRepBtreeNavigator nav;\n  nav.InitFirst(tree1);\n  EXPECT_THAT(nav.Seek(3).edge, Eq(nullptr));\n  EXPECT_THAT(nav.Seek(100).edge, Eq(nullptr));\n  EXPECT_THAT(nav.btree(), Eq(tree1));\n  EXPECT_THAT(nav.Current(), Eq(tree1->Edges().front()));\n\n  EXPECT_THAT(nav.InitOffset(tree2, 3).edge, Eq(nullptr));\n  EXPECT_THAT(nav.InitOffset(tree2, 100).edge, Eq(nullptr));\n  EXPECT_THAT(nav.btree(), Eq(tree1));\n  EXPECT_THAT(nav.Current(), Eq(tree1->Edges().front()));\n\n  CordRep::Unref(tree1);\n  CordRep::Unref(tree2);\n}\n\nTEST_P(CordRepBtreeNavigatorTest, Read) {\n  const Flats& flats = this->flats();\n  const std::string& data = this->data();\n\n  for (size_t offset = 0; offset < data.size(); ++offset) {\n    for (size_t length = 1; length <= data.size() - offset; ++length) {\n      CordRepBtreeNavigator nav;\n      nav.InitFirst(tree());\n\n      // Skip towards edge holding offset\n      size_t edge_offset = nav.Skip(offset).offset;\n\n      // Read node\n      ReadResult result = nav.Read(edge_offset, length);\n      ASSERT_THAT(result.tree, Ne(nullptr));\n      EXPECT_THAT(result.tree->length, Eq(length));\n      if (result.tree->tag == BTREE) {\n        ASSERT_TRUE(CordRepBtree::IsValid(result.tree->btree()));\n      }\n\n      // Verify contents\n      std::string value = CordToString(result.tree);\n      EXPECT_THAT(value, Eq(data.substr(offset, length)));\n\n      // Verify 'partial last edge' reads.\n      size_t partial = (offset + length) % kCharsPerFlat;\n      ASSERT_THAT(result.n, Eq(partial));\n\n      // Verify ending position if not EOF\n      if (offset + length < data.size()) {\n        size_t index = (offset + length) / kCharsPerFlat;\n        EXPECT_THAT(nav.Current(), Eq(flats[index]));\n      }\n\n      CordRep::Unref(result.tree);\n    }\n  }\n}\n\nTEST_P(CordRepBtreeNavigatorTest, ReadBeyondLengthOfTree) {\n  CordRepBtreeNavigator nav;\n  nav.InitFirst(tree());\n  ReadResult result = nav.Read(2, tree()->length);\n  ASSERT_THAT(result.tree, Eq(nullptr));\n}\n\nTEST(CordRepBtreeNavigatorTest, NavigateMaximumTreeDepth) {\n  CordRepFlat* flat1 = MakeFlat(\"Hello world\");\n  CordRepFlat* flat2 = MakeFlat(\"World Hello\");\n\n  CordRepBtree* node = CordRepBtree::Create(flat1);\n  node = CordRepBtree::Append(node, flat2);\n  while (node->height() < CordRepBtree::kMaxHeight) {\n    node = CordRepBtree::New(node);\n  }\n\n  CordRepBtreeNavigator nav;\n  CordRep* edge = nav.InitFirst(node);\n  EXPECT_THAT(edge, Eq(flat1));\n  EXPECT_THAT(nav.Next(), Eq(flat2));\n  EXPECT_THAT(nav.Next(), Eq(nullptr));\n  EXPECT_THAT(nav.Previous(), Eq(flat1));\n  EXPECT_THAT(nav.Previous(), Eq(nullptr));\n\n  CordRep::Unref(node);\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_reader.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_btree_reader.h\"\n\n#include <cassert>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_btree_navigator.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nabsl::string_view CordRepBtreeReader::Read(size_t n, size_t chunk_size,\n                                           CordRep*& tree) {\n  assert(chunk_size <= navigator_.Current()->length);\n\n  // If chunk_size is non-zero, we need to start inside last returned edge.\n  // Else we start reading at the next data edge of the tree.\n  CordRep* edge = chunk_size ? navigator_.Current() : navigator_.Next();\n  const size_t offset = chunk_size ? edge->length - chunk_size : 0;\n\n  // Read the sub tree and verify we got what we wanted.\n  ReadResult result = navigator_.Read(offset, n);\n  tree = result.tree;\n\n  // If the data returned in `tree` was covered entirely by `chunk_size`, i.e.,\n  // read from the 'previous' edge, we did not consume any additional data, and\n  // can directly return the substring into the current data edge as the next\n  // chunk. We can easily establish from the above code that `navigator_.Next()`\n  // has not been called as that requires `chunk_size` to be zero.\n  if (n < chunk_size) return EdgeData(edge).substr(result.n);\n\n  // The amount of data taken from the last edge is `chunk_size` and `result.n`\n  // contains the offset into the current edge trailing the read data (which can\n  // be 0). As the call to `navigator_.Read()` could have consumed all remaining\n  // data, calling `navigator_.Current()` is not safe before checking if we\n  // already consumed all remaining data.\n  const size_t consumed_by_read = n - chunk_size - result.n;\n  if (consumed_by_read >= remaining_) {\n    remaining_ = 0;\n    return {};\n  }\n\n  // We did not read all data, return remaining data from current edge.\n  edge = navigator_.Current();\n  remaining_ -= consumed_by_read + edge->length;\n  return EdgeData(edge).substr(result.n);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_reader.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_\n\n#include <cassert>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_btree_navigator.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordRepBtreeReader implements logic to iterate over cord btrees.\n// References to the underlying data are returned as absl::string_view values.\n// The most typical use case is a forward only iteration over tree data.\n// The class also provides `Skip()`, `Seek()` and `Read()` methods similar to\n// CordRepBtreeNavigator that allow more advanced navigation.\n//\n// Example: iterate over all data inside a cord btree:\n//\n//   CordRepBtreeReader reader;\n//   for (string_view sv = reader.Init(tree); !sv.Empty(); sv = sv.Next()) {\n//     DoSomethingWithDataIn(sv);\n//   }\n//\n// All navigation methods always return the next 'chunk' of data. The class\n// assumes that all data is directly 'consumed' by the caller. For example:\n// invoking `Skip()` will skip the desired number of bytes, and directly\n// read and return the next chunk of data directly after the skipped bytes.\n//\n// Example: iterate over all data inside a btree skipping the first 100 bytes:\n//\n//   CordRepBtreeReader reader;\n//   absl::string_view sv = reader.Init(tree);\n//   if (sv.length() > 100) {\n//     sv.RemovePrefix(100);\n//   } else {\n//     sv = reader.Skip(100 - sv.length());\n//   }\n//   while (!sv.empty()) {\n//     DoSomethingWithDataIn(sv);\n//     absl::string_view sv = reader.Next();\n//   }\n//\n// It is important to notice that `remaining` is based on the end position of\n// the last data edge returned to the caller, not the cumulative data returned\n// to the caller which can be less in cases of skipping or seeking over data.\n//\n// For example, consider a cord btree with five data edges: \"abc\", \"def\", \"ghi\",\n// \"jkl\" and \"mno\":\n//\n//   absl::string_view sv;\n//   CordRepBtreeReader reader;\n//\n//   sv = reader.Init(tree); // sv = \"abc\", remaining = 12\n//   sv = reader.Skip(4);    // sv = \"hi\",  remaining = 6\n//   sv = reader.Skip(2);    // sv = \"l\",   remaining = 3\n//   sv = reader.Next();     // sv = \"mno\", remaining = 0\n//   sv = reader.Seek(1);    // sv = \"bc\", remaining = 12\n//\nclass CordRepBtreeReader {\n public:\n  using ReadResult = CordRepBtreeNavigator::ReadResult;\n  using Position = CordRepBtreeNavigator::Position;\n\n  // Returns true if this instance is not empty.\n  explicit operator bool() const { return navigator_.btree() != nullptr; }\n\n  // Returns the tree referenced by this instance or nullptr if empty.\n  CordRepBtree* btree() const { return navigator_.btree(); }\n\n  // Returns the current data edge inside the referenced btree.\n  // Requires that the current instance is not empty.\n  CordRep* node() const { return navigator_.Current(); }\n\n  // Returns the length of the referenced tree.\n  // Requires that the current instance is not empty.\n  size_t length() const;\n\n  // Returns the number of remaining bytes available for iteration, which is the\n  // number of bytes directly following the end of the last chunk returned.\n  // This value will be zero if we iterated over the last edge in the bound\n  // tree, in which case any call to Next() or Skip() will return an empty\n  // string_view reflecting the EOF state.\n  // Note that a call to `Seek()` resets `remaining` to a value based on the\n  // end position of the chunk returned by that call.\n  size_t remaining() const { return remaining_; }\n\n  // Resets this instance to an empty value.\n  void Reset() { navigator_.Reset(); }\n\n  // Initializes this instance with `tree`. `tree` must not be null.\n  // Returns a reference to the first data edge of the provided tree.\n  absl::string_view Init(CordRepBtree* tree);\n\n  // Navigates to and returns the next data edge of the referenced tree.\n  // Returns an empty string_view if an attempt is made to read beyond the end\n  // of the tree, i.e.: if `remaining()` is zero indicating an EOF condition.\n  // Requires that the current instance is not empty.\n  absl::string_view Next();\n\n  // Skips the provided amount of bytes and returns a reference to the data\n  // directly following the skipped bytes.\n  absl::string_view Skip(size_t skip);\n\n  // Reads `n` bytes into `tree`.\n  // If `chunk_size` is zero, starts reading at the next data edge. If\n  // `chunk_size` is non zero, the read starts at the last `chunk_size` bytes of\n  // the last returned data edge. Effectively, this means that the read starts\n  // at offset `consumed() - chunk_size`.\n  // Requires that `chunk_size` is less than or equal to the length of the\n  // last returned data edge. The purpose of `chunk_size` is to simplify code\n  // partially consuming a returned chunk and wanting to include the remaining\n  // bytes in the Read call. For example, the below code will read 1000 bytes of\n  // data into a cord tree if the first chunk starts with \"big:\":\n  //\n  //   CordRepBtreeReader reader;\n  //   absl::string_view sv = reader.Init(tree);\n  //   if (absl::StartsWith(sv, \"big:\")) {\n  //     CordRepBtree tree;\n  //     sv = reader.Read(1000, sv.size() - 4 /* \"big:\" */, &tree);\n  //   }\n  //\n  // This method will return an empty string view if all remaining data was\n  // read. If `n` exceeded the amount of remaining data this function will\n  // return an empty string view and `tree` will be set to nullptr.\n  // In both cases, `consumed` will be set to `length`.\n  absl::string_view Read(size_t n, size_t chunk_size, CordRep*& tree);\n\n  // Navigates to the chunk at offset `offset`.\n  // Returns a reference into the navigated to chunk, adjusted for the relative\n  // position of `offset` into that chunk. For example, calling `Seek(13)` on a\n  // cord tree containing 2 chunks of 10 and 20 bytes respectively will return\n  // a string view into the second chunk starting at offset 3 with a size of 17.\n  // Returns an empty string view if `offset` is equal to or greater than the\n  // length of the referenced tree.\n  absl::string_view Seek(size_t offset);\n\n private:\n  size_t remaining_ = 0;\n  CordRepBtreeNavigator navigator_;\n};\n\ninline size_t CordRepBtreeReader::length() const {\n  assert(btree() != nullptr);\n  return btree()->length;\n}\n\ninline absl::string_view CordRepBtreeReader::Init(CordRepBtree* tree) {\n  assert(tree != nullptr);\n  const CordRep* edge = navigator_.InitFirst(tree);\n  remaining_ = tree->length - edge->length;\n  return EdgeData(edge);\n}\n\ninline absl::string_view CordRepBtreeReader::Next() {\n  if (remaining_ == 0) return {};\n  const CordRep* edge = navigator_.Next();\n  assert(edge != nullptr);\n  remaining_ -= edge->length;\n  return EdgeData(edge);\n}\n\ninline absl::string_view CordRepBtreeReader::Skip(size_t skip) {\n  // As we are always positioned on the last 'consumed' edge, we\n  // need to skip the current edge as well as `skip`.\n  const size_t edge_length = navigator_.Current()->length;\n  CordRepBtreeNavigator::Position pos = navigator_.Skip(skip + edge_length);\n  if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {\n    remaining_ = 0;\n    return {};\n  }\n  // The combined length of all edges skipped before `pos.edge` is `skip -\n  // pos.offset`, all of which are 'consumed', as well as the current edge.\n  remaining_ -= skip - pos.offset + pos.edge->length;\n  return EdgeData(pos.edge).substr(pos.offset);\n}\n\ninline absl::string_view CordRepBtreeReader::Seek(size_t offset) {\n  const CordRepBtreeNavigator::Position pos = navigator_.Seek(offset);\n  if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {\n    remaining_ = 0;\n    return {};\n  }\n  absl::string_view chunk = EdgeData(pos.edge).substr(pos.offset);\n  remaining_ = length() - offset - chunk.length();\n  return chunk;\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_reader_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_btree_reader.h\"\n\n#include <iostream>\n#include <random>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_test_util.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::IsEmpty;\nusing ::testing::Ne;\nusing ::testing::Not;\n\nusing ::absl::cordrep_testing::CordRepBtreeFromFlats;\nusing ::absl::cordrep_testing::MakeFlat;\nusing ::absl::cordrep_testing::CordToString;\nusing ::absl::cordrep_testing::CreateFlatsFromString;\nusing ::absl::cordrep_testing::CreateRandomString;\n\nusing ReadResult = CordRepBtreeReader::ReadResult;\n\nTEST(CordRepBtreeReaderTest, Next) {\n  constexpr size_t kChars = 3;\n  const size_t cap = CordRepBtree::kMaxCapacity;\n  size_t counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};\n\n  for (size_t count : counts) {\n    std::string data = CreateRandomString(count * kChars);\n    std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);\n    CordRepBtree* node = CordRepBtreeFromFlats(flats);\n\n    CordRepBtreeReader reader;\n    size_t remaining = data.length();\n    absl::string_view chunk = reader.Init(node);\n    EXPECT_THAT(chunk, Eq(data.substr(0, chunk.length())));\n\n    remaining -= chunk.length();\n    EXPECT_THAT(reader.remaining(), Eq(remaining));\n\n    while (remaining > 0) {\n      const size_t offset = data.length() - remaining;\n      chunk = reader.Next();\n      EXPECT_THAT(chunk, Eq(data.substr(offset, chunk.length())));\n\n      remaining -= chunk.length();\n      EXPECT_THAT(reader.remaining(), Eq(remaining));\n    }\n\n    EXPECT_THAT(reader.remaining(), Eq(0u));\n\n    // Verify trying to read beyond EOF returns empty string_view\n    EXPECT_THAT(reader.Next(), testing::IsEmpty());\n\n    CordRep::Unref(node);\n  }\n}\n\nTEST(CordRepBtreeReaderTest, Skip) {\n  constexpr size_t kChars = 3;\n  const size_t cap = CordRepBtree::kMaxCapacity;\n  size_t counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};\n\n  for (size_t count : counts) {\n    std::string data = CreateRandomString(count * kChars);\n    std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);\n    CordRepBtree* node = CordRepBtreeFromFlats(flats);\n\n    for (size_t skip1 = 0; skip1 < data.length() - kChars; ++skip1) {\n      for (size_t skip2 = 0; skip2 < data.length() - kChars; ++skip2) {\n        CordRepBtreeReader reader;\n        size_t remaining = data.length();\n        absl::string_view chunk = reader.Init(node);\n        remaining -= chunk.length();\n\n        chunk = reader.Skip(skip1);\n        size_t offset = data.length() - remaining;\n        ASSERT_THAT(chunk, Eq(data.substr(offset + skip1, chunk.length())));\n        remaining -= chunk.length() + skip1;\n        ASSERT_THAT(reader.remaining(), Eq(remaining));\n\n        if (remaining == 0) continue;\n\n        size_t skip = std::min(remaining - 1, skip2);\n        chunk = reader.Skip(skip);\n        offset = data.length() - remaining;\n        ASSERT_THAT(chunk, Eq(data.substr(offset + skip, chunk.length())));\n      }\n    }\n\n    CordRep::Unref(node);\n  }\n}\n\nTEST(CordRepBtreeReaderTest, SkipBeyondLength) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeFlat(\"abc\"));\n  tree = CordRepBtree::Append(tree, MakeFlat(\"def\"));\n  CordRepBtreeReader reader;\n  reader.Init(tree);\n  EXPECT_THAT(reader.Skip(100), IsEmpty());\n  EXPECT_THAT(reader.remaining(), Eq(0u));\n  CordRep::Unref(tree);\n}\n\nTEST(CordRepBtreeReaderTest, Seek) {\n  constexpr size_t kChars = 3;\n  const size_t cap = CordRepBtree::kMaxCapacity;\n  size_t counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};\n\n  for (size_t count : counts) {\n    std::string data = CreateRandomString(count * kChars);\n    std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);\n    CordRepBtree* node = CordRepBtreeFromFlats(flats);\n\n    for (size_t seek = 0; seek < data.length() - 1; ++seek) {\n      CordRepBtreeReader reader;\n      reader.Init(node);\n      absl::string_view chunk = reader.Seek(seek);\n      ASSERT_THAT(chunk, Not(IsEmpty()));\n      ASSERT_THAT(chunk, Eq(data.substr(seek, chunk.length())));\n      ASSERT_THAT(reader.remaining(),\n                  Eq(data.length() - seek - chunk.length()));\n    }\n\n    CordRep::Unref(node);\n  }\n}\n\nTEST(CordRepBtreeReaderTest, SeekBeyondLength) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeFlat(\"abc\"));\n  tree = CordRepBtree::Append(tree, MakeFlat(\"def\"));\n  CordRepBtreeReader reader;\n  reader.Init(tree);\n  EXPECT_THAT(reader.Seek(6), IsEmpty());\n  EXPECT_THAT(reader.remaining(), Eq(0u));\n  EXPECT_THAT(reader.Seek(100), IsEmpty());\n  EXPECT_THAT(reader.remaining(), Eq(0u));\n  CordRep::Unref(tree);\n}\n\nTEST(CordRepBtreeReaderTest, Read) {\n  std::string data = \"abcdefghijklmno\";\n  std::vector<CordRep*> flats = CreateFlatsFromString(data, 5);\n  CordRepBtree* node = CordRepBtreeFromFlats(flats);\n\n  CordRep* tree;\n  CordRepBtreeReader reader;\n  absl::string_view chunk;\n\n  // Read zero bytes\n  chunk = reader.Init(node);\n  chunk = reader.Read(0, chunk.length(), tree);\n  EXPECT_THAT(tree, Eq(nullptr));\n  EXPECT_THAT(chunk, Eq(\"abcde\"));\n  EXPECT_THAT(reader.remaining(), Eq(10u));\n  EXPECT_THAT(reader.Next(), Eq(\"fghij\"));\n\n  // Read in full\n  chunk = reader.Init(node);\n  chunk = reader.Read(15, chunk.length(), tree);\n  EXPECT_THAT(tree, Ne(nullptr));\n  EXPECT_THAT(CordToString(tree), Eq(\"abcdefghijklmno\"));\n  EXPECT_THAT(chunk, Eq(\"\"));\n  EXPECT_THAT(reader.remaining(), Eq(0u));\n  CordRep::Unref(tree);\n\n  // Read < chunk bytes\n  chunk = reader.Init(node);\n  chunk = reader.Read(3, chunk.length(), tree);\n  ASSERT_THAT(tree, Ne(nullptr));\n  EXPECT_THAT(CordToString(tree), Eq(\"abc\"));\n  EXPECT_THAT(chunk, Eq(\"de\"));\n  EXPECT_THAT(reader.remaining(), Eq(10u));\n  EXPECT_THAT(reader.Next(), Eq(\"fghij\"));\n  CordRep::Unref(tree);\n\n  // Read < chunk bytes at offset\n  chunk = reader.Init(node);\n  chunk = reader.Read(2, chunk.length() - 2, tree);\n  ASSERT_THAT(tree, Ne(nullptr));\n  EXPECT_THAT(CordToString(tree), Eq(\"cd\"));\n  EXPECT_THAT(chunk, Eq(\"e\"));\n  EXPECT_THAT(reader.remaining(), Eq(10u));\n  EXPECT_THAT(reader.Next(), Eq(\"fghij\"));\n  CordRep::Unref(tree);\n\n  // Read from consumed chunk\n  chunk = reader.Init(node);\n  chunk = reader.Read(3, 0, tree);\n  ASSERT_THAT(tree, Ne(nullptr));\n  EXPECT_THAT(CordToString(tree), Eq(\"fgh\"));\n  EXPECT_THAT(chunk, Eq(\"ij\"));\n  EXPECT_THAT(reader.remaining(), Eq(5u));\n  EXPECT_THAT(reader.Next(), Eq(\"klmno\"));\n  CordRep::Unref(tree);\n\n  // Read across chunks\n  chunk = reader.Init(node);\n  chunk = reader.Read(12, chunk.length() - 2, tree);\n  ASSERT_THAT(tree, Ne(nullptr));\n  EXPECT_THAT(CordToString(tree), Eq(\"cdefghijklmn\"));\n  EXPECT_THAT(chunk, Eq(\"o\"));\n  EXPECT_THAT(reader.remaining(), Eq(0u));\n  CordRep::Unref(tree);\n\n  // Read across chunks landing on exact edge boundary\n  chunk = reader.Init(node);\n  chunk = reader.Read(10 - 2, chunk.length() - 2, tree);\n  ASSERT_THAT(tree, Ne(nullptr));\n  EXPECT_THAT(CordToString(tree), Eq(\"cdefghij\"));\n  EXPECT_THAT(chunk, Eq(\"klmno\"));\n  EXPECT_THAT(reader.remaining(), Eq(0u));\n  CordRep::Unref(tree);\n\n  CordRep::Unref(node);\n}\n\nTEST(CordRepBtreeReaderTest, ReadExhaustive) {\n  constexpr size_t kChars = 3;\n  const size_t cap = CordRepBtree::kMaxCapacity;\n  size_t counts[] = {1, 2, cap, cap * cap + 1, cap * cap * cap * 2 + 17};\n\n  for (size_t count : counts) {\n    std::string data = CreateRandomString(count * kChars);\n    std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);\n    CordRepBtree* node = CordRepBtreeFromFlats(flats);\n\n    for (size_t read_size : {kChars - 1, kChars, kChars + 7, cap * cap}) {\n      CordRepBtreeReader reader;\n      absl::string_view chunk = reader.Init(node);\n\n      // `consumed` tracks the end of last consumed chunk which is the start of\n      // the next chunk: we always read with `chunk_size = chunk.length()`.\n      size_t consumed = 0;\n      size_t remaining = data.length();\n      while (remaining > 0) {\n        CordRep* tree;\n        size_t n = (std::min)(remaining, read_size);\n        chunk = reader.Read(n, chunk.length(), tree);\n        EXPECT_THAT(tree, Ne(nullptr));\n        if (tree) {\n          EXPECT_THAT(CordToString(tree), Eq(data.substr(consumed, n)));\n          CordRep::Unref(tree);\n        }\n\n        consumed += n;\n        remaining -= n;\n        EXPECT_THAT(reader.remaining(), Eq(remaining - chunk.length()));\n\n        if (remaining > 0) {\n          ASSERT_FALSE(chunk.empty());\n          ASSERT_THAT(chunk, Eq(data.substr(consumed, chunk.length())));\n        } else {\n          ASSERT_TRUE(chunk.empty()) << chunk;\n        }\n      }\n    }\n\n    CordRep::Unref(node);\n  }\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_btree_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_btree.h\"\n\n#include <cmath>\n#include <deque>\n#include <iostream>\n#include <string>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/cleanup/cleanup.h\"\n#include \"absl/strings/internal/cord_data_edge.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_test_util.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nclass CordRepBtreeTestPeer {\n public:\n  static void SetEdge(CordRepBtree* node, size_t idx, CordRep* edge) {\n    node->edges_[idx] = edge;\n  }\n  static void AddEdge(CordRepBtree* node, CordRep* edge) {\n    node->edges_[node->fetch_add_end(1)] = edge;\n  }\n};\n\nnamespace {\n\nusing ::absl::cordrep_testing::AutoUnref;\nusing ::absl::cordrep_testing::CordCollectRepsIf;\nusing ::absl::cordrep_testing::CordToString;\nusing ::absl::cordrep_testing::CordVisitReps;\nusing ::absl::cordrep_testing::CreateFlatsFromString;\nusing ::absl::cordrep_testing::CreateRandomString;\nusing ::absl::cordrep_testing::MakeExternal;\nusing ::absl::cordrep_testing::MakeFlat;\nusing ::absl::cordrep_testing::MakeSubstring;\nusing ::testing::_;\nusing ::testing::AllOf;\nusing ::testing::AnyOf;\nusing ::testing::Conditional;\nusing ::testing::ElementsAre;\nusing ::testing::ElementsAreArray;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing ::testing::Le;\nusing ::testing::Ne;\nusing ::testing::Not;\nusing ::testing::SizeIs;\nusing ::testing::TypedEq;\n\nMATCHER_P(EqFlatHolding, data, \"Equals flat holding data\") {\n  if (arg->tag < FLAT) {\n    *result_listener << \"Expected FLAT, got tag \" << static_cast<int>(arg->tag);\n    return false;\n  }\n  std::string actual = CordToString(arg);\n  if (actual != data) {\n    *result_listener << \"Expected flat holding \\\"\" << data\n                     << \"\\\", got flat holding \\\"\" << actual << \"\\\"\";\n    return false;\n  }\n  return true;\n}\n\nMATCHER_P(IsNode, height, absl::StrCat(\"Is a valid node of height \", height)) {\n  if (arg == nullptr) {\n    *result_listener << \"Expected NODE, got nullptr\";\n    return false;\n  }\n  if (arg->tag != BTREE) {\n    *result_listener << \"Expected NODE, got \" << static_cast<int>(arg->tag);\n    return false;\n  }\n  if (!CordRepBtree::IsValid(arg->btree())) {\n    CordRepBtree::Dump(arg->btree(), \"Expected valid NODE, got:\", false,\n                       *result_listener->stream());\n    return false;\n  }\n  if (arg->btree()->height() != height) {\n    *result_listener << \"Expected NODE of height \" << height << \", got \"\n                     << arg->btree()->height();\n    return false;\n  }\n  return true;\n}\n\nMATCHER_P2(IsSubstring, start, length,\n           absl::StrCat(\"Is a substring(start = \", start, \", length = \", length,\n                        \")\")) {\n  if (arg == nullptr) {\n    *result_listener << \"Expected substring, got nullptr\";\n    return false;\n  }\n  if (arg->tag != SUBSTRING) {\n    *result_listener << \"Expected SUBSTRING, got \"\n                     << static_cast<int>(arg->tag);\n    return false;\n  }\n  const CordRepSubstring* const substr = arg->substring();\n  if (substr->start != start || substr->length != length) {\n    *result_listener << \"Expected substring(\" << start << \", \" << length\n                     << \"), got substring(\" << substr->start << \", \"\n                     << substr->length << \")\";\n    return false;\n  }\n  return true;\n}\n\nMATCHER_P2(EqExtractResult, tree, rep, \"Equals ExtractResult\") {\n  if (arg.tree != tree || arg.extracted != rep) {\n    *result_listener << \"Expected {\" << static_cast<const void*>(tree) << \", \"\n                     << static_cast<const void*>(rep) << \"}, got {\" << arg.tree\n                     << \", \" << arg.extracted << \"}\";\n    return false;\n  }\n  return true;\n}\n\n// DataConsumer is a simple helper class used by tests to 'consume' string\n// fragments from the provided input in forward or backward direction.\nclass DataConsumer {\n public:\n  // Starts consumption of `data`. Caller must make sure `data` outlives this\n  // instance. Consumes data starting at the front if `forward` is true, else\n  // consumes data from the back.\n  DataConsumer(absl::string_view data, bool forward)\n      : data_(data), forward_(forward) {}\n\n  // Return the next `n` bytes from referenced data.\n  absl::string_view Next(size_t n) {\n    assert(n <= data_.size() - consumed_);\n    consumed_ += n;\n    return data_.substr(forward_ ? consumed_ - n : data_.size() - consumed_, n);\n  }\n\n  // Returns all data consumed so far.\n  absl::string_view Consumed() const {\n    return forward_ ? data_.substr(0, consumed_)\n                    : data_.substr(data_.size() - consumed_);\n  }\n\n private:\n  absl::string_view data_;\n  size_t consumed_ = 0;\n  bool forward_;\n};\n\n// BtreeAdd returns either CordRepBtree::Append or CordRepBtree::Prepend.\nCordRepBtree* BtreeAdd(CordRepBtree* node, bool append,\n                       absl::string_view data) {\n  return append ? CordRepBtree::Append(node, data)\n                : CordRepBtree::Prepend(node, data);\n}\n\n// Recursively collects all leaf edges from `tree` and appends them to `edges`.\nvoid GetLeafEdges(const CordRepBtree* tree, std::vector<CordRep*>& edges) {\n  if (tree->height() == 0) {\n    for (CordRep* edge : tree->Edges()) {\n      edges.push_back(edge);\n    }\n  } else {\n    for (CordRep* edge : tree->Edges()) {\n      GetLeafEdges(edge->btree(), edges);\n    }\n  }\n}\n\n// Recursively collects and returns all leaf edges from `tree`.\nstd::vector<CordRep*> GetLeafEdges(const CordRepBtree* tree) {\n  std::vector<CordRep*> edges;\n  GetLeafEdges(tree, edges);\n  return edges;\n}\n\n// Creates a flat containing the hexadecimal value of `i` zero padded\n// to at least 4 digits prefixed with \"0x\", e.g.: \"0x04AC\".\nCordRepFlat* MakeHexFlat(size_t i) {\n  return MakeFlat(absl::StrCat(\"0x\", absl::Hex(i, absl::kZeroPad4)));\n}\n\nCordRepBtree* MakeLeaf(size_t size = CordRepBtree::kMaxCapacity) {\n  assert(size <= CordRepBtree::kMaxCapacity);\n  CordRepBtree* leaf = CordRepBtree::Create(MakeHexFlat(0));\n  for (size_t i = 1; i < size; ++i) {\n    leaf = CordRepBtree::Append(leaf, MakeHexFlat(i));\n  }\n  return leaf;\n}\n\nCordRepBtree* MakeTree(size_t size, bool append = true) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeHexFlat(0));\n  for (size_t i = 1; i < size; ++i) {\n    tree = append ? CordRepBtree::Append(tree, MakeHexFlat(i))\n                  : CordRepBtree::Prepend(tree, MakeHexFlat(i));\n  }\n  return tree;\n}\n\nCordRepBtree* CreateTree(absl::Span<CordRep* const> reps) {\n  auto it = reps.begin();\n  CordRepBtree* tree = CordRepBtree::Create(*it);\n  while (++it != reps.end()) tree = CordRepBtree::Append(tree, *it);\n  return tree;\n}\n\nCordRepBtree* CreateTree(absl::string_view data, size_t chunk_size) {\n  return CreateTree(CreateFlatsFromString(data, chunk_size));\n}\n\nCordRepBtree* CreateTreeReverse(absl::string_view data, size_t chunk_size) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(data, chunk_size);\n  auto rit = flats.rbegin();\n  CordRepBtree* tree = CordRepBtree::Create(*rit);\n  while (++rit != flats.rend()) tree = CordRepBtree::Prepend(tree, *rit);\n  return tree;\n}\n\nclass CordRepBtreeTest : public testing::TestWithParam<bool> {\n public:\n  bool shared() const { return GetParam(); }\n\n  static std::string ToString(testing::TestParamInfo<bool> param) {\n    return param.param ? \"Shared\" : \"Private\";\n  }\n};\n\nINSTANTIATE_TEST_SUITE_P(WithParam, CordRepBtreeTest, testing::Bool(),\n                         CordRepBtreeTest::ToString);\n\nclass CordRepBtreeHeightTest : public testing::TestWithParam<int> {\n public:\n  int height() const { return GetParam(); }\n\n  static std::string ToString(testing::TestParamInfo<int> param) {\n    return absl::StrCat(param.param);\n  }\n};\n\nINSTANTIATE_TEST_SUITE_P(WithHeights, CordRepBtreeHeightTest,\n                         testing::Range(0, CordRepBtree::kMaxHeight),\n                         CordRepBtreeHeightTest::ToString);\n\nusing TwoBools = testing::tuple<bool, bool>;\n\nclass CordRepBtreeDualTest : public testing::TestWithParam<TwoBools> {\n public:\n  bool first_shared() const { return std::get<0>(GetParam()); }\n  bool second_shared() const { return std::get<1>(GetParam()); }\n\n  static std::string ToString(testing::TestParamInfo<TwoBools> param) {\n    if (std::get<0>(param.param)) {\n      return std::get<1>(param.param) ? \"BothShared\" : \"FirstShared\";\n    }\n    return std::get<1>(param.param) ? \"SecondShared\" : \"Private\";\n  }\n};\n\nINSTANTIATE_TEST_SUITE_P(WithParam, CordRepBtreeDualTest,\n                         testing::Combine(testing::Bool(), testing::Bool()),\n                         CordRepBtreeDualTest::ToString);\n\nTEST(CordRepBtreeTest, SizeIsMultipleOf64) {\n  // Only enforce for fully 64-bit platforms.\n  if (sizeof(size_t) == 8 && sizeof(void*) == 8) {\n    EXPECT_THAT(sizeof(CordRepBtree) % 64, Eq(0u))\n        << \"Should be multiple of 64\";\n  }\n}\n\nTEST(CordRepBtreeTest, NewDestroyEmptyTree) {\n  auto* tree = CordRepBtree::New();\n  EXPECT_THAT(tree->size(), Eq(0u));\n  EXPECT_THAT(tree->height(), Eq(0));\n  EXPECT_THAT(tree->Edges(), ElementsAre());\n  CordRepBtree::Destroy(tree);\n}\n\nTEST(CordRepBtreeTest, NewDestroyEmptyTreeAtHeight) {\n  auto* tree = CordRepBtree::New(3);\n  EXPECT_THAT(tree->size(), Eq(0u));\n  EXPECT_THAT(tree->height(), Eq(3));\n  EXPECT_THAT(tree->Edges(), ElementsAre());\n  CordRepBtree::Destroy(tree);\n}\n\nTEST(CordRepBtreeTest, Btree) {\n  CordRep* rep = CordRepBtree::New();\n  EXPECT_THAT(rep->btree(), Eq(rep));\n  EXPECT_THAT(static_cast<const CordRep*>(rep)->btree(), Eq(rep));\n  CordRep::Unref(rep);\n#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n  rep = MakeFlat(\"Hello world\");\n  EXPECT_DEATH(rep->btree(), \".*\");\n  EXPECT_DEATH(static_cast<const CordRep*>(rep)->btree(), \".*\");\n  CordRep::Unref(rep);\n#endif\n}\n\nTEST(CordRepBtreeTest, EdgeData) {\n  CordRepFlat* flat = MakeFlat(\"Hello world\");\n  CordRepExternal* external = MakeExternal(\"Hello external\");\n  CordRep* substr1 = MakeSubstring(1, 6, CordRep::Ref(flat));\n  CordRep* substr2 = MakeSubstring(1, 6, CordRep::Ref(external));\n  CordRep* bad_substr = MakeSubstring(1, 2, CordRep::Ref(substr1));\n\n  EXPECT_TRUE(IsDataEdge(flat));\n  EXPECT_THAT(EdgeData(flat).data(), TypedEq<const void*>(flat->Data()));\n  EXPECT_THAT(EdgeData(flat), Eq(\"Hello world\"));\n\n  EXPECT_TRUE(IsDataEdge(external));\n  EXPECT_THAT(EdgeData(external).data(), TypedEq<const void*>(external->base));\n  EXPECT_THAT(EdgeData(external), Eq(\"Hello external\"));\n\n  EXPECT_TRUE(IsDataEdge(substr1));\n  EXPECT_THAT(EdgeData(substr1).data(), TypedEq<const void*>(flat->Data() + 1));\n  EXPECT_THAT(EdgeData(substr1), Eq(\"ello w\"));\n\n  EXPECT_TRUE(IsDataEdge(substr2));\n  EXPECT_THAT(EdgeData(substr2).data(),\n              TypedEq<const void*>(external->base + 1));\n  EXPECT_THAT(EdgeData(substr2), Eq(\"ello e\"));\n\n  EXPECT_FALSE(IsDataEdge(bad_substr));\n#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n  EXPECT_DEATH(EdgeData(bad_substr), \".*\");\n#endif\n\n  CordRep::Unref(bad_substr);\n  CordRep::Unref(substr2);\n  CordRep::Unref(substr1);\n  CordRep::Unref(external);\n  CordRep::Unref(flat);\n}\n\nTEST(CordRepBtreeTest, CreateUnrefLeaf) {\n  auto* flat = MakeFlat(\"a\");\n  auto* leaf = CordRepBtree::Create(flat);\n  EXPECT_THAT(leaf->size(), Eq(1u));\n  EXPECT_THAT(leaf->height(), Eq(0));\n  EXPECT_THAT(leaf->Edges(), ElementsAre(flat));\n  CordRepBtree::Unref(leaf);\n}\n\nTEST(CordRepBtreeTest, NewUnrefNode) {\n  auto* leaf = CordRepBtree::Create(MakeFlat(\"a\"));\n  CordRepBtree* tree = CordRepBtree::New(leaf);\n  EXPECT_THAT(tree->size(), Eq(1u));\n  EXPECT_THAT(tree->height(), Eq(1));\n  EXPECT_THAT(tree->Edges(), ElementsAre(leaf));\n  CordRepBtree::Unref(tree);\n}\n\nTEST_P(CordRepBtreeTest, AppendToLeafToCapacity) {\n  AutoUnref refs;\n  std::vector<CordRep*> flats;\n  flats.push_back(MakeHexFlat(0));\n  auto* leaf = CordRepBtree::Create(flats.back());\n\n  for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {\n    refs.RefIf(shared(), leaf);\n    flats.push_back(MakeHexFlat(i));\n    auto* result = CordRepBtree::Append(leaf, flats.back());\n    EXPECT_THAT(result->height(), Eq(0));\n    EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));\n    EXPECT_THAT(result->Edges(), ElementsAreArray(flats));\n    leaf = result;\n  }\n  CordRep::Unref(leaf);\n}\n\nTEST_P(CordRepBtreeTest, PrependToLeafToCapacity) {\n  AutoUnref refs;\n  std::deque<CordRep*> flats;\n  flats.push_front(MakeHexFlat(0));\n  auto* leaf = CordRepBtree::Create(flats.front());\n\n  for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {\n    refs.RefIf(shared(), leaf);\n    flats.push_front(MakeHexFlat(i));\n    auto* result = CordRepBtree::Prepend(leaf, flats.front());\n    EXPECT_THAT(result->height(), Eq(0));\n    EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));\n    EXPECT_THAT(result->Edges(), ElementsAreArray(flats));\n    leaf = result;\n  }\n  CordRep::Unref(leaf);\n}\n\n// This test specifically aims at code aligning data at either the front or the\n// back of the contained `edges[]` array, alternating Append and Prepend will\n// move `begin()` and `end()` values as needed for each added value.\nTEST_P(CordRepBtreeTest, AppendPrependToLeafToCapacity) {\n  AutoUnref refs;\n  std::deque<CordRep*> flats;\n  flats.push_front(MakeHexFlat(0));\n  auto* leaf = CordRepBtree::Create(flats.front());\n\n  for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {\n    refs.RefIf(shared(), leaf);\n    CordRepBtree* result;\n    if (i % 2 != 0) {\n      flats.push_front(MakeHexFlat(i));\n      result = CordRepBtree::Prepend(leaf, flats.front());\n    } else {\n      flats.push_back(MakeHexFlat(i));\n      result = CordRepBtree::Append(leaf, flats.back());\n    }\n    EXPECT_THAT(result->height(), Eq(0));\n    EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));\n    EXPECT_THAT(result->Edges(), ElementsAreArray(flats));\n    leaf = result;\n  }\n  CordRep::Unref(leaf);\n}\n\nTEST_P(CordRepBtreeTest, AppendToLeafBeyondCapacity) {\n  AutoUnref refs;\n  auto* leaf = MakeLeaf();\n  refs.RefIf(shared(), leaf);\n  CordRep* flat = MakeFlat(\"abc\");\n  auto* result = CordRepBtree::Append(leaf, flat);\n  ASSERT_THAT(result, IsNode(1));\n  EXPECT_THAT(result, Ne(leaf));\n  absl::Span<CordRep* const> edges = result->Edges();\n  ASSERT_THAT(edges, ElementsAre(leaf, IsNode(0)));\n  EXPECT_THAT(edges[1]->btree()->Edges(), ElementsAre(flat));\n  CordRep::Unref(result);\n}\n\nTEST_P(CordRepBtreeTest, PrependToLeafBeyondCapacity) {\n  AutoUnref refs;\n  auto* leaf = MakeLeaf();\n  refs.RefIf(shared(), leaf);\n  CordRep* flat = MakeFlat(\"abc\");\n  auto* result = CordRepBtree::Prepend(leaf, flat);\n  ASSERT_THAT(result, IsNode(1));\n  EXPECT_THAT(result, Ne(leaf));\n  absl::Span<CordRep* const> edges = result->Edges();\n  ASSERT_THAT(edges, ElementsAre(IsNode(0), leaf));\n  EXPECT_THAT(edges[0]->btree()->Edges(), ElementsAre(flat));\n  CordRep::Unref(result);\n}\n\nTEST_P(CordRepBtreeTest, AppendToTreeOneDeep) {\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  AutoUnref refs;\n  std::vector<CordRep*> flats;\n  flats.push_back(MakeHexFlat(0));\n  CordRepBtree* tree = CordRepBtree::Create(flats.back());\n  for (size_t i = 1; i <= max_cap; ++i) {\n    flats.push_back(MakeHexFlat(i));\n    tree = CordRepBtree::Append(tree, flats.back());\n  }\n  ASSERT_THAT(tree, IsNode(1));\n\n  for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {\n    // Ref top level tree based on param.\n    // Ref leaf node once every 4 iterations, which should not have an\n    // observable effect other than that the leaf itself is copied.\n    refs.RefIf(shared(), tree);\n    refs.RefIf(i % 4 == 0, tree->Edges().back());\n\n    flats.push_back(MakeHexFlat(i));\n    CordRepBtree* result = CordRepBtree::Append(tree, flats.back());\n    ASSERT_THAT(result, IsNode(1));\n    ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n    std::vector<CordRep*> edges = GetLeafEdges(result);\n    ASSERT_THAT(edges, ElementsAreArray(flats));\n    tree = result;\n  }\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeTest, AppendToTreeTwoDeep) {\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  AutoUnref refs;\n  std::vector<CordRep*> flats;\n  flats.push_back(MakeHexFlat(0));\n  CordRepBtree* tree = CordRepBtree::Create(flats.back());\n  for (size_t i = 1; i <= max_cap * max_cap; ++i) {\n    flats.push_back(MakeHexFlat(i));\n    tree = CordRepBtree::Append(tree, flats.back());\n  }\n  ASSERT_THAT(tree, IsNode(2));\n  for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap; ++i) {\n    // Ref top level tree based on param.\n    // Ref child node once every 16 iterations, and leaf node every 4\n    // iterations which  which should not have an observable effect other than\n    //  the node and/or the leaf below it being copied.\n    refs.RefIf(shared(), tree);\n    refs.RefIf(i % 16 == 0, tree->Edges().back());\n    refs.RefIf(i % 4 == 0, tree->Edges().back()->btree()->Edges().back());\n\n    flats.push_back(MakeHexFlat(i));\n    CordRepBtree* result = CordRepBtree::Append(tree, flats.back());\n    ASSERT_THAT(result, IsNode(2));\n    ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n    std::vector<CordRep*> edges = GetLeafEdges(result);\n    ASSERT_THAT(edges, ElementsAreArray(flats));\n    tree = result;\n  }\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeTest, PrependToTreeOneDeep) {\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  AutoUnref refs;\n  std::deque<CordRep*> flats;\n  flats.push_back(MakeHexFlat(0));\n  CordRepBtree* tree = CordRepBtree::Create(flats.back());\n  for (size_t i = 1; i <= max_cap; ++i) {\n    flats.push_front(MakeHexFlat(i));\n    tree = CordRepBtree::Prepend(tree, flats.front());\n  }\n  ASSERT_THAT(tree, IsNode(1));\n\n  for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {\n    // Ref top level tree based on param.\n    // Ref leaf node once every 4 iterations which should not have an observable\n    // effect other than than the leaf itself is copied.\n    refs.RefIf(shared(), tree);\n    refs.RefIf(i % 4 == 0, tree->Edges().back());\n\n    flats.push_front(MakeHexFlat(i));\n    CordRepBtree* result = CordRepBtree::Prepend(tree, flats.front());\n    ASSERT_THAT(result, IsNode(1));\n    ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n    std::vector<CordRep*> edges = GetLeafEdges(result);\n    ASSERT_THAT(edges, ElementsAreArray(flats));\n    tree = result;\n  }\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeTest, PrependToTreeTwoDeep) {\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  AutoUnref refs;\n  std::deque<CordRep*> flats;\n  flats.push_back(MakeHexFlat(0));\n  CordRepBtree* tree = CordRepBtree::Create(flats.back());\n  for (size_t i = 1; i <= max_cap * max_cap; ++i) {\n    flats.push_front(MakeHexFlat(i));\n    tree = CordRepBtree::Prepend(tree, flats.front());\n  }\n  ASSERT_THAT(tree, IsNode(2));\n  for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap; ++i) {\n    // Ref top level tree based on param.\n    // Ref child node once every 16 iterations, and leaf node every 4\n    // iterations which  which should not have an observable effect other than\n    //  the node and/or the leaf below it being copied.\n    refs.RefIf(shared(), tree);\n    refs.RefIf(i % 16 == 0, tree->Edges().back());\n    refs.RefIf(i % 4 == 0, tree->Edges().back()->btree()->Edges().back());\n\n    flats.push_front(MakeHexFlat(i));\n    CordRepBtree* result = CordRepBtree::Prepend(tree, flats.front());\n    ASSERT_THAT(result, IsNode(2));\n    ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n    std::vector<CordRep*> edges = GetLeafEdges(result);\n    ASSERT_THAT(edges, ElementsAreArray(flats));\n    tree = result;\n  }\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeDualTest, MergeLeafsNotExceedingCapacity) {\n  for (bool use_append : {false, true}) {\n    SCOPED_TRACE(use_append ? \"Using Append\" : \"Using Prepend\");\n\n    AutoUnref refs;\n    std::vector<CordRep*> flats;\n\n    // Build `left` side leaf appending all contained flats to `flats`\n    CordRepBtree* left = MakeLeaf(3);\n    GetLeafEdges(left, flats);\n    refs.RefIf(first_shared(), left);\n\n    // Build `right` side leaf appending all contained flats to `flats`\n    CordRepBtree* right = MakeLeaf(2);\n    GetLeafEdges(right, flats);\n    refs.RefIf(second_shared(), right);\n\n    CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)\n                                    : CordRepBtree::Prepend(right, left);\n    EXPECT_THAT(tree, IsNode(0));\n\n    // `tree` contains all flats originally belonging to `left` and `right`.\n    EXPECT_THAT(tree->Edges(), ElementsAreArray(flats));\n    CordRepBtree::Unref(tree);\n  }\n}\n\nTEST_P(CordRepBtreeDualTest, MergeLeafsExceedingCapacity) {\n  for (bool use_append : {false, true}) {\n    SCOPED_TRACE(use_append ? \"Using Append\" : \"Using Prepend\");\n\n    AutoUnref refs;\n\n    // Build `left` side tree appending all contained flats to `flats`\n    CordRepBtree* left = MakeLeaf(CordRepBtree::kMaxCapacity - 2);\n    refs.RefIf(first_shared(), left);\n\n    // Build `right` side tree appending all contained flats to `flats`\n    CordRepBtree* right = MakeLeaf(CordRepBtree::kMaxCapacity - 1);\n    refs.RefIf(second_shared(), right);\n\n    CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)\n                                    : CordRepBtree::Prepend(right, left);\n    EXPECT_THAT(tree, IsNode(1));\n    EXPECT_THAT(tree->Edges(), ElementsAre(left, right));\n    CordRepBtree::Unref(tree);\n  }\n}\n\nTEST_P(CordRepBtreeDualTest, MergeEqualHeightTrees) {\n  for (bool use_append : {false, true}) {\n    SCOPED_TRACE(use_append ? \"Using Append\" : \"Using Prepend\");\n\n    AutoUnref refs;\n    std::vector<CordRep*> flats;\n\n    // Build `left` side tree appending all contained flats to `flats`\n    CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 3);\n    GetLeafEdges(left, flats);\n    refs.RefIf(first_shared(), left);\n\n    // Build `right` side tree appending all contained flats to `flats`\n    CordRepBtree* right = MakeTree(CordRepBtree::kMaxCapacity * 2);\n    GetLeafEdges(right, flats);\n    refs.RefIf(second_shared(), right);\n\n    CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)\n                                    : CordRepBtree::Prepend(right, left);\n    EXPECT_THAT(tree, IsNode(1));\n    EXPECT_THAT(tree->Edges(), SizeIs(5u));\n\n    // `tree` contains all flats originally belonging to `left` and `right`.\n    EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));\n    CordRepBtree::Unref(tree);\n  }\n}\n\nTEST_P(CordRepBtreeDualTest, MergeLeafWithTreeNotExceedingLeafCapacity) {\n  for (bool use_append : {false, true}) {\n    SCOPED_TRACE(use_append ? \"Using Append\" : \"Using Prepend\");\n\n    AutoUnref refs;\n    std::vector<CordRep*> flats;\n\n    // Build `left` side tree appending all added flats to `flats`\n    CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 2 + 2);\n    GetLeafEdges(left, flats);\n    refs.RefIf(first_shared(), left);\n\n    // Build `right` side tree appending all added flats to `flats`\n    CordRepBtree* right = MakeTree(3);\n    GetLeafEdges(right, flats);\n    refs.RefIf(second_shared(), right);\n\n    CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)\n                                    : CordRepBtree::Prepend(right, left);\n    EXPECT_THAT(tree, IsNode(1));\n    EXPECT_THAT(tree->Edges(), SizeIs(3u));\n\n    // `tree` contains all flats originally belonging to `left` and `right`.\n    EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));\n    CordRepBtree::Unref(tree);\n  }\n}\n\nTEST_P(CordRepBtreeDualTest, MergeLeafWithTreeExceedingLeafCapacity) {\n  for (bool use_append : {false, true}) {\n    SCOPED_TRACE(use_append ? \"Using Append\" : \"Using Prepend\");\n\n    AutoUnref refs;\n    std::vector<CordRep*> flats;\n\n    // Build `left` side tree appending all added flats to `flats`\n    CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 3 - 2);\n    GetLeafEdges(left, flats);\n    refs.RefIf(first_shared(), left);\n\n    // Build `right` side tree appending all added flats to `flats`\n    CordRepBtree* right = MakeTree(3);\n    GetLeafEdges(right, flats);\n    refs.RefIf(second_shared(), right);\n\n    CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)\n                                    : CordRepBtree::Prepend(right, left);\n    EXPECT_THAT(tree, IsNode(1));\n    EXPECT_THAT(tree->Edges(), SizeIs(4u));\n\n    // `tree` contains all flats originally belonging to `left` and `right`.\n    EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));\n    CordRepBtree::Unref(tree);\n  }\n}\n\nvoid RefEdgesAt(size_t depth, AutoUnref& refs, CordRepBtree* tree) {\n  absl::Span<CordRep* const> edges = tree->Edges();\n  if (depth == 0) {\n    refs.Ref(edges.front());\n    refs.Ref(edges.back());\n  } else {\n    assert(tree->height() > 0);\n    RefEdgesAt(depth - 1, refs, edges.front()->btree());\n    RefEdgesAt(depth - 1, refs, edges.back()->btree());\n  }\n}\n\nTEST(CordRepBtreeTest, MergeFuzzTest) {\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  std::minstd_rand rnd;\n  std::uniform_int_distribution<int> coin_flip(0, 1);\n  std::uniform_int_distribution<int> dice_throw(1, 6);\n\n  auto random_leaf_count = [&]() {\n    std::uniform_int_distribution<int> dist_height(0, 3);\n    std::uniform_int_distribution<int> dist_leaf(0, max_cap - 1);\n    const int height = dist_height(rnd);\n    return (height ? pow(max_cap, height) : 0) + dist_leaf(rnd);\n  };\n\n  for (int i = 0; i < 10000; ++i) {\n    AutoUnref refs;\n    std::vector<CordRep*> flats;\n\n    CordRepBtree* left = MakeTree(random_leaf_count(), coin_flip(rnd));\n    GetLeafEdges(left, flats);\n    if (dice_throw(rnd) == 1) {\n      std::uniform_int_distribution<size_t> dist(\n          0, static_cast<size_t>(left->height()));\n      RefEdgesAt(dist(rnd), refs, left);\n    }\n\n    CordRepBtree* right = MakeTree(random_leaf_count(), coin_flip(rnd));\n    GetLeafEdges(right, flats);\n    if (dice_throw(rnd) == 1) {\n      std::uniform_int_distribution<size_t> dist(\n          0, static_cast<size_t>(right->height()));\n      RefEdgesAt(dist(rnd), refs, right);\n    }\n\n    CordRepBtree* tree = CordRepBtree::Append(left, right);\n    EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));\n    CordRepBtree::Unref(tree);\n  }\n}\n\nTEST_P(CordRepBtreeTest, RemoveSuffix) {\n  // Create tree of 1, 2 and 3 levels high\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  for (size_t cap : {max_cap - 1, max_cap * 2, max_cap * max_cap * 2}) {\n    const std::string data = CreateRandomString(cap * 512);\n\n    {\n      // Verify RemoveSuffix(<all>)\n      AutoUnref refs;\n      CordRepBtree* node = refs.RefIf(shared(), CreateTree(data, 512));\n      EXPECT_THAT(CordRepBtree::RemoveSuffix(node, data.length()), Eq(nullptr));\n\n      // Verify RemoveSuffix(<none>)\n      node = refs.RefIf(shared(), CreateTree(data, 512));\n      EXPECT_THAT(CordRepBtree::RemoveSuffix(node, 0), Eq(node));\n      CordRep::Unref(node);\n    }\n\n    for (size_t n = 1; n < data.length(); ++n) {\n      AutoUnref refs;\n      auto flats = CreateFlatsFromString(data, 512);\n      CordRepBtree* node = refs.RefIf(shared(), CreateTree(flats));\n      CordRep* rep = refs.Add(CordRepBtree::RemoveSuffix(node, n));\n      EXPECT_THAT(CordToString(rep), Eq(data.substr(0, data.length() - n)));\n\n      // Collect all flats\n      auto is_flat = [](CordRep* rep) { return rep->tag >= FLAT; };\n      std::vector<CordRep*> edges = CordCollectRepsIf(is_flat, rep);\n      ASSERT_THAT(edges.size(), Le(flats.size()));\n\n      // Isolate last edge\n      CordRep* last_edge = edges.back();\n      edges.pop_back();\n      const size_t last_length = rep->length - edges.size() * 512;\n\n      // All flats except the last edge must be kept or copied 'as is'\n      size_t index = 0;\n      for (CordRep* edge : edges) {\n        ASSERT_THAT(edge, Eq(flats[index++]));\n        ASSERT_THAT(edge->length, Eq(512u));\n      }\n\n      // CordRepBtree may optimize small substrings to avoid waste, so only\n      // check for flat sharing / updates where the code should always do this.\n      if (last_length >= 500) {\n        EXPECT_THAT(last_edge, Eq(flats[index++]));\n        if (shared()) {\n          EXPECT_THAT(last_edge->length, Eq(512u));\n        } else {\n          EXPECT_TRUE(last_edge->refcount.IsOne());\n          EXPECT_THAT(last_edge->length, Eq(last_length));\n        }\n      }\n    }\n  }\n}\n\nTEST(CordRepBtreeTest, SubTree) {\n  // Create tree of at least 2 levels high\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  const size_t n = max_cap * max_cap * 2;\n  const std::string data = CreateRandomString(n * 3);\n  std::vector<CordRep*> flats;\n  for (absl::string_view s = data; !s.empty(); s.remove_prefix(3)) {\n    flats.push_back(MakeFlat(s.substr(0, 3)));\n  }\n  CordRepBtree* node = CordRepBtree::Create(CordRep::Ref(flats[0]));\n  for (size_t i = 1; i < flats.size(); ++i) {\n    node = CordRepBtree::Append(node, CordRep::Ref(flats[i]));\n  }\n\n  for (size_t offset = 0; offset < data.length(); ++offset) {\n    for (size_t length = 1; length <= data.length() - offset; ++length) {\n      CordRep* rep = node->SubTree(offset, length);\n      EXPECT_THAT(CordToString(rep), Eq(data.substr(offset, length)));\n      CordRep::Unref(rep);\n    }\n  }\n  CordRepBtree::Unref(node);\n  for (CordRep* rep : flats) {\n    CordRep::Unref(rep);\n  }\n}\n\nTEST(CordRepBtreeTest, SubTreeOnExistingSubstring) {\n  // This test verifies that a SubTree call on a pre-existing (large) substring\n  // adjusts the existing substring if not shared, and else rewrites the\n  // existing substring.\n  AutoUnref refs;\n  std::string data = CreateRandomString(1000);\n  CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(\"abc\"));\n  CordRep* flat = MakeFlat(data);\n  leaf = CordRepBtree::Append(leaf, flat);\n\n  // Setup tree containing substring.\n  CordRep* result = leaf->SubTree(0, 3 + 990);\n  ASSERT_THAT(result->tag, Eq(BTREE));\n  CordRep::Unref(leaf);\n  leaf = result->btree();\n  ASSERT_THAT(leaf->Edges(), ElementsAre(_, IsSubstring(0u, 990u)));\n  EXPECT_THAT(leaf->Edges()[1]->substring()->child, Eq(flat));\n\n  // Verify substring of substring.\n  result = leaf->SubTree(3 + 5, 970);\n  ASSERT_THAT(result, IsSubstring(5u, 970u));\n  EXPECT_THAT(result->substring()->child, Eq(flat));\n  CordRep::Unref(result);\n\n  CordRep::Unref(leaf);\n}\n\nTEST_P(CordRepBtreeTest, AddDataToLeaf) {\n  const size_t n = CordRepBtree::kMaxCapacity;\n  const std::string data = CreateRandomString(n * 3);\n\n  for (bool append : {true, false}) {\n    AutoUnref refs;\n    DataConsumer consumer(data, append);\n    SCOPED_TRACE(append ? \"Append\" : \"Prepend\");\n\n    CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(consumer.Next(3)));\n    for (size_t i = 1; i < n; ++i) {\n      refs.RefIf(shared(), leaf);\n      CordRepBtree* result = BtreeAdd(leaf, append, consumer.Next(3));\n      EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));\n      EXPECT_THAT(CordToString(result), Eq(consumer.Consumed()));\n      leaf = result;\n    }\n    CordRep::Unref(leaf);\n  }\n}\n\nTEST_P(CordRepBtreeTest, AppendDataToTree) {\n  AutoUnref refs;\n  size_t n = CordRepBtree::kMaxCapacity + CordRepBtree::kMaxCapacity / 2;\n  std::string data = CreateRandomString(n * 3);\n  CordRepBtree* tree = refs.RefIf(shared(), CreateTree(data, 3));\n  CordRepBtree* leaf0 = tree->Edges()[0]->btree();\n  CordRepBtree* leaf1 = tree->Edges()[1]->btree();\n  CordRepBtree* result = CordRepBtree::Append(tree, \"123456789\");\n  EXPECT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n  EXPECT_THAT(result->Edges(),\n              ElementsAre(leaf0, Conditional(shared(), Ne(leaf1), Eq(leaf1))));\n  EXPECT_THAT(CordToString(result), Eq(data + \"123456789\"));\n  CordRep::Unref(result);\n}\n\nTEST_P(CordRepBtreeTest, PrependDataToTree) {\n  AutoUnref refs;\n  size_t n = CordRepBtree::kMaxCapacity + CordRepBtree::kMaxCapacity / 2;\n  std::string data = CreateRandomString(n * 3);\n  CordRepBtree* tree = refs.RefIf(shared(), CreateTreeReverse(data, 3));\n  CordRepBtree* leaf0 = tree->Edges()[0]->btree();\n  CordRepBtree* leaf1 = tree->Edges()[1]->btree();\n  CordRepBtree* result = CordRepBtree::Prepend(tree, \"123456789\");\n  EXPECT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n  EXPECT_THAT(result->Edges(),\n              ElementsAre(Conditional(shared(), Ne(leaf0), Eq(leaf0)), leaf1));\n  EXPECT_THAT(CordToString(result), Eq(\"123456789\" + data));\n  CordRep::Unref(result);\n}\n\nTEST_P(CordRepBtreeTest, AddDataToTreeThreeLevelsDeep) {\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  const size_t n = max_cap * max_cap * max_cap;\n  const std::string data = CreateRandomString(n * 3);\n\n  for (bool append : {true, false}) {\n    AutoUnref refs;\n    DataConsumer consumer(data, append);\n    SCOPED_TRACE(append ? \"Append\" : \"Prepend\");\n\n    // Fill leaf\n    CordRepBtree* tree = CordRepBtree::Create(MakeFlat(consumer.Next(3)));\n    for (size_t i = 1; i < max_cap; ++i) {\n      tree = BtreeAdd(tree, append, consumer.Next(3));\n    }\n    ASSERT_THAT(CordToString(tree), Eq(consumer.Consumed()));\n\n    // Fill to maximum at one deep\n    refs.RefIf(shared(), tree);\n    CordRepBtree* result = BtreeAdd(tree, append, consumer.Next(3));\n    ASSERT_THAT(result, IsNode(1));\n    ASSERT_THAT(result, Ne(tree));\n    ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));\n    tree = result;\n    for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {\n      refs.RefIf(shared(), tree);\n      result = BtreeAdd(tree, append, consumer.Next(3));\n      ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n      ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));\n      tree = result;\n    }\n\n    // Fill to maximum at two deep\n    refs.RefIf(shared(), tree);\n    result = BtreeAdd(tree, append, consumer.Next(3));\n    ASSERT_THAT(result, IsNode(2));\n    ASSERT_THAT(result, Ne(tree));\n    ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));\n    tree = result;\n    for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap;\n         ++i) {\n      refs.RefIf(shared(), tree);\n      result = BtreeAdd(tree, append, consumer.Next(3));\n      ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));\n      ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));\n      tree = result;\n    }\n\n    CordRep::Unref(tree);\n  }\n}\n\nTEST_P(CordRepBtreeTest, AddLargeDataToLeaf) {\n  const size_t max_cap = CordRepBtree::kMaxCapacity;\n  const size_t n = max_cap * max_cap * max_cap * 3 + 2;\n  const std::string data = CreateRandomString(n * kMaxFlatLength);\n\n  for (bool append : {true, false}) {\n    AutoUnref refs;\n    SCOPED_TRACE(append ? \"Append\" : \"Prepend\");\n\n    CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(\"abc\"));\n    refs.RefIf(shared(), leaf);\n    CordRepBtree* result = BtreeAdd(leaf, append, data);\n    EXPECT_THAT(CordToString(result), Eq(append ? \"abc\" + data : data + \"abc\"));\n    CordRep::Unref(result);\n  }\n}\n\nTEST_P(CordRepBtreeTest, CreateFromTreeReturnsTree) {\n  AutoUnref refs;\n  CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(\"Hello world\"));\n  refs.RefIf(shared(), leaf);\n  CordRepBtree* result = CordRepBtree::Create(leaf);\n  EXPECT_THAT(result, Eq(leaf));\n  CordRep::Unref(result);\n}\n\nTEST(CordRepBtreeTest, GetCharacter) {\n  size_t n = CordRepBtree::kMaxCapacity * CordRepBtree::kMaxCapacity + 2;\n  std::string data = CreateRandomString(n * 3);\n  CordRepBtree* tree = CreateTree(data, 3);\n  // Add a substring node for good measure.\n  tree = tree->Append(tree, MakeSubstring(4, 5, MakeFlat(\"abcdefghijklm\")));\n  data += \"efghi\";\n  for (size_t i = 0; i < data.length(); ++i) {\n    ASSERT_THAT(tree->GetCharacter(i), Eq(data[i]));\n  }\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeTest, IsFlatSingleFlat) {\n  CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(\"Hello world\"));\n\n  absl::string_view fragment;\n  EXPECT_TRUE(leaf->IsFlat(nullptr));\n  EXPECT_TRUE(leaf->IsFlat(&fragment));\n  EXPECT_THAT(fragment, Eq(\"Hello world\"));\n  fragment = \"\";\n  EXPECT_TRUE(leaf->IsFlat(0, 11, nullptr));\n  EXPECT_TRUE(leaf->IsFlat(0, 11, &fragment));\n  EXPECT_THAT(fragment, Eq(\"Hello world\"));\n\n  // Arbitrary ranges must check true as well.\n  EXPECT_TRUE(leaf->IsFlat(1, 4, &fragment));\n  EXPECT_THAT(fragment, Eq(\"ello\"));\n  EXPECT_TRUE(leaf->IsFlat(6, 5, &fragment));\n  EXPECT_THAT(fragment, Eq(\"world\"));\n\n  CordRep::Unref(leaf);\n}\n\nTEST(CordRepBtreeTest, IsFlatMultiFlat) {\n  size_t n = CordRepBtree::kMaxCapacity * CordRepBtree::kMaxCapacity + 2;\n  std::string data = CreateRandomString(n * 3);\n  CordRepBtree* tree = CreateTree(data, 3);\n  // Add substring nodes for good measure.\n  tree = tree->Append(tree, MakeSubstring(4, 3, MakeFlat(\"abcdefghijklm\")));\n  tree = tree->Append(tree, MakeSubstring(8, 3, MakeFlat(\"abcdefghijklm\")));\n  data += \"efgijk\";\n\n  EXPECT_FALSE(tree->IsFlat(nullptr));\n  absl::string_view fragment = \"Can't touch this\";\n  EXPECT_FALSE(tree->IsFlat(&fragment));\n  EXPECT_THAT(fragment, Eq(\"Can't touch this\"));\n\n  for (size_t offset = 0; offset < data.size(); offset += 3) {\n    EXPECT_TRUE(tree->IsFlat(offset, 3, nullptr));\n    EXPECT_TRUE(tree->IsFlat(offset, 3, &fragment));\n    EXPECT_THAT(fragment, Eq(data.substr(offset, 3)));\n\n    fragment = \"Can't touch this\";\n    if (offset > 0) {\n      EXPECT_FALSE(tree->IsFlat(offset - 1, 4, nullptr));\n      EXPECT_FALSE(tree->IsFlat(offset - 1, 4, &fragment));\n      EXPECT_THAT(fragment, Eq(\"Can't touch this\"));\n    }\n    if (offset < data.size() - 4) {\n      EXPECT_FALSE(tree->IsFlat(offset, 4, nullptr));\n      EXPECT_FALSE(tree->IsFlat(offset, 4, &fragment));\n      EXPECT_THAT(fragment, Eq(\"Can't touch this\"));\n    }\n  }\n\n  CordRep::Unref(tree);\n}\n\n#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n\nTEST_P(CordRepBtreeHeightTest, GetAppendBufferNotPrivate) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeExternal(\"Foo\"));\n  CordRepBtree::Ref(tree);\n  EXPECT_DEATH(tree->GetAppendBuffer(1), \".*\");\n  CordRepBtree::Unref(tree);\n  CordRepBtree::Unref(tree);\n}\n\n#endif  // defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)\n\nTEST_P(CordRepBtreeHeightTest, GetAppendBufferNotFlat) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeExternal(\"Foo\"));\n  for (int i = 1; i <= height(); ++i) {\n    tree = CordRepBtree::New(tree);\n  }\n  EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));\n  CordRepBtree::Unref(tree);\n}\n\nTEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatNotPrivate) {\n  CordRepFlat* flat = MakeFlat(\"abc\");\n  CordRepBtree* tree = CordRepBtree::Create(CordRep::Ref(flat));\n  for (int i = 1; i <= height(); ++i) {\n    tree = CordRepBtree::New(tree);\n  }\n  EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));\n  CordRepBtree::Unref(tree);\n  CordRep::Unref(flat);\n}\n\nTEST_P(CordRepBtreeHeightTest, GetAppendBufferTreeNotPrivate) {\n  if (height() == 0) return;\n  AutoUnref refs;\n  CordRepFlat* flat = MakeFlat(\"abc\");\n  CordRepBtree* tree = CordRepBtree::Create(CordRep::Ref(flat));\n  for (int i = 1; i <= height(); ++i) {\n    if (i == (height() + 1) / 2) refs.Ref(tree);\n    tree = CordRepBtree::New(tree);\n  }\n  EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));\n  CordRepBtree::Unref(tree);\n  CordRep::Unref(flat);\n}\n\nTEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatNoCapacity) {\n  CordRepFlat* flat = MakeFlat(\"abc\");\n  flat->length = flat->Capacity();\n  CordRepBtree* tree = CordRepBtree::Create(flat);\n  for (int i = 1; i <= height(); ++i) {\n    tree = CordRepBtree::New(tree);\n  }\n  EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));\n  CordRepBtree::Unref(tree);\n}\n\nTEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatWithCapacity) {\n  CordRepFlat* flat = MakeFlat(\"abc\");\n  CordRepBtree* tree = CordRepBtree::Create(flat);\n  for (int i = 1; i <= height(); ++i) {\n    tree = CordRepBtree::New(tree);\n  }\n  absl::Span<char> span = tree->GetAppendBuffer(2);\n  EXPECT_THAT(span, SizeIs(2u));\n  EXPECT_THAT(span.data(), TypedEq<void*>(flat->Data() + 3));\n  EXPECT_THAT(tree->length, Eq(5u));\n\n  size_t avail = flat->Capacity() - 5;\n  span = tree->GetAppendBuffer(avail + 100);\n  EXPECT_THAT(span, SizeIs(avail));\n  EXPECT_THAT(span.data(), TypedEq<void*>(flat->Data() + 5));\n  EXPECT_THAT(tree->length, Eq(5 + avail));\n\n  CordRepBtree::Unref(tree);\n}\n\nTEST(CordRepBtreeTest, Dump) {\n  // Handles nullptr\n  std::stringstream ss;\n  CordRepBtree::Dump(nullptr, ss);\n  CordRepBtree::Dump(nullptr, \"Once upon a label\", ss);\n  CordRepBtree::Dump(nullptr, \"Once upon a label\", false, ss);\n  CordRepBtree::Dump(nullptr, \"Once upon a label\", true, ss);\n\n  // Cover legal edges\n  CordRepFlat* flat = MakeFlat(\"Hello world\");\n  CordRepExternal* external = MakeExternal(\"Hello external\");\n  CordRep* substr_flat = MakeSubstring(1, 6, CordRep::Ref(flat));\n  CordRep* substr_external = MakeSubstring(2, 7, CordRep::Ref(external));\n\n  // Build tree\n  CordRepBtree* tree = CordRepBtree::Create(flat);\n  tree = CordRepBtree::Append(tree, external);\n  tree = CordRepBtree::Append(tree, substr_flat);\n  tree = CordRepBtree::Append(tree, substr_external);\n\n  // Repeat until we have a tree\n  while (tree->height() == 0) {\n    tree = CordRepBtree::Append(tree, CordRep::Ref(flat));\n    tree = CordRepBtree::Append(tree, CordRep::Ref(external));\n    tree = CordRepBtree::Append(tree, CordRep::Ref(substr_flat));\n    tree = CordRepBtree::Append(tree, CordRep::Ref(substr_external));\n  }\n\n  for (int api = 0; api <= 3; ++api) {\n    absl::string_view api_scope;\n    std::stringstream ss;\n    switch (api) {\n      case 0:\n        api_scope = \"Bare\";\n        CordRepBtree::Dump(tree, ss);\n        break;\n      case 1:\n        api_scope = \"Label only\";\n        CordRepBtree::Dump(tree, \"Once upon a label\", ss);\n        break;\n      case 2:\n        api_scope = \"Label no content\";\n        CordRepBtree::Dump(tree, \"Once upon a label\", false, ss);\n        break;\n      default:\n        api_scope = \"Label and content\";\n        CordRepBtree::Dump(tree, \"Once upon a label\", true, ss);\n        break;\n    }\n    SCOPED_TRACE(api_scope);\n    std::string str = ss.str();\n\n    // Contains Node(depth) / Leaf and private / shared indicators\n    EXPECT_THAT(str, AllOf(HasSubstr(\"Node(1)\"), HasSubstr(\"Leaf\"),\n                           HasSubstr(\"Private\"), HasSubstr(\"Shared\")));\n\n    // Contains length and start offset of all data edges\n    EXPECT_THAT(str, AllOf(HasSubstr(\"len = 11\"), HasSubstr(\"len = 14\"),\n                           HasSubstr(\"len = 6\"), HasSubstr(\"len = 7\"),\n                           HasSubstr(\"start = 1\"), HasSubstr(\"start = 2\")));\n\n    // Contains address of all data edges\n    EXPECT_THAT(\n        str, AllOf(HasSubstr(absl::StrCat(\"0x\", absl::Hex(flat))),\n                   HasSubstr(absl::StrCat(\"0x\", absl::Hex(external))),\n                   HasSubstr(absl::StrCat(\"0x\", absl::Hex(substr_flat))),\n                   HasSubstr(absl::StrCat(\"0x\", absl::Hex(substr_external)))));\n\n    if (api != 0) {\n      // Contains label\n      EXPECT_THAT(str, HasSubstr(\"Once upon a label\"));\n    }\n\n    if (api != 3) {\n      // Does not contain contents\n      EXPECT_THAT(str, Not(AnyOf(HasSubstr(\"data = \\\"Hello world\\\"\"),\n                                 HasSubstr(\"data = \\\"Hello external\\\"\"),\n                                 HasSubstr(\"data = \\\"ello w\\\"\"),\n                                 HasSubstr(\"data = \\\"llo ext\\\"\"))));\n    } else {\n      // Contains contents\n      EXPECT_THAT(str, AllOf(HasSubstr(\"data = \\\"Hello world\\\"\"),\n                             HasSubstr(\"data = \\\"Hello external\\\"\"),\n                             HasSubstr(\"data = \\\"ello w\\\"\"),\n                             HasSubstr(\"data = \\\"llo ext\\\"\")));\n    }\n  }\n\n  CordRep::Unref(tree);\n}\n\nTEST(CordRepBtreeTest, IsValid) {\n  EXPECT_FALSE(CordRepBtree::IsValid(nullptr));\n\n  CordRepBtree* empty = CordRepBtree::New(0);\n  EXPECT_TRUE(CordRepBtree::IsValid(empty));\n  CordRep::Unref(empty);\n\n  for (bool as_tree : {false, true}) {\n    CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(\"abc\"));\n    CordRepBtree* tree = as_tree ? CordRepBtree::New(leaf) : nullptr;\n    CordRepBtree* check = as_tree ? tree : leaf;\n\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    leaf->length--;\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->length++;\n\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    leaf->tag--;\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->tag++;\n\n    // Height\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    leaf->storage[0] = static_cast<uint8_t>(CordRepBtree::kMaxHeight + 1);\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->storage[0] = 1;\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->storage[0] = 0;\n\n    // Begin\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    const uint8_t begin = leaf->storage[1];\n    leaf->storage[1] = static_cast<uint8_t>(CordRepBtree::kMaxCapacity);\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->storage[1] = 2;\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->storage[1] = begin;\n\n    // End\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    const uint8_t end = leaf->storage[2];\n    leaf->storage[2] = static_cast<uint8_t>(CordRepBtree::kMaxCapacity + 1);\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    leaf->storage[2] = end;\n\n    // DataEdge tag and value\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    CordRep* const edge = leaf->Edges()[0];\n    const uint8_t tag = edge->tag;\n    CordRepBtreeTestPeer::SetEdge(leaf, begin, nullptr);\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    CordRepBtreeTestPeer::SetEdge(leaf, begin, edge);\n    edge->tag = BTREE;\n    EXPECT_FALSE(CordRepBtree::IsValid(check));\n    edge->tag = tag;\n\n    if (as_tree) {\n      ASSERT_TRUE(CordRepBtree::IsValid(check));\n      leaf->length--;\n      EXPECT_FALSE(CordRepBtree::IsValid(check));\n      leaf->length++;\n\n      // Height\n      ASSERT_TRUE(CordRepBtree::IsValid(check));\n      tree->storage[0] = static_cast<uint8_t>(2);\n      EXPECT_FALSE(CordRepBtree::IsValid(check));\n      tree->storage[0] = 1;\n\n      // Btree edge\n      ASSERT_TRUE(CordRepBtree::IsValid(check));\n      CordRep* const edge = tree->Edges()[0];\n      const uint8_t tag = edge->tag;\n      edge->tag = FLAT;\n      EXPECT_FALSE(CordRepBtree::IsValid(check));\n      edge->tag = tag;\n    }\n\n    ASSERT_TRUE(CordRepBtree::IsValid(check));\n    CordRep::Unref(check);\n  }\n}\n\nTEST(CordRepBtreeTest, AssertValid) {\n  CordRepBtree* tree = CordRepBtree::Create(MakeFlat(\"abc\"));\n  const CordRepBtree* ctree = tree;\n  EXPECT_THAT(CordRepBtree::AssertValid(tree), Eq(tree));\n  EXPECT_THAT(CordRepBtree::AssertValid(ctree), Eq(ctree));\n\n#if defined(GTEST_HAS_DEATH_TEST)\n  CordRepBtree* nulltree = nullptr;\n  const CordRepBtree* cnulltree = nullptr;\n  EXPECT_DEBUG_DEATH(\n      EXPECT_THAT(CordRepBtree::AssertValid(nulltree), Eq(nulltree)), \".*\");\n  EXPECT_DEBUG_DEATH(\n      EXPECT_THAT(CordRepBtree::AssertValid(cnulltree), Eq(cnulltree)), \".*\");\n\n  tree->length--;\n  EXPECT_DEBUG_DEATH(EXPECT_THAT(CordRepBtree::AssertValid(tree), Eq(tree)),\n                     \".*\");\n  EXPECT_DEBUG_DEATH(EXPECT_THAT(CordRepBtree::AssertValid(ctree), Eq(ctree)),\n                     \".*\");\n  tree->length++;\n#endif\n  CordRep::Unref(tree);\n}\n\nTEST(CordRepBtreeTest, CheckAssertValidShallowVsDeep) {\n  // Restore exhaustive validation on any exit.\n  const bool exhaustive_validation = IsCordBtreeExhaustiveValidationEnabled();\n  auto cleanup = absl::MakeCleanup([exhaustive_validation] {\n    SetCordBtreeExhaustiveValidation(exhaustive_validation);\n  });\n\n  // Create a tree of at least 2 levels, and mess with the original flat, which\n  // should go undetected in shallow mode as the flat is too far away, but\n  // should be detected in forced non-shallow mode.\n  CordRep* flat = MakeFlat(\"abc\");\n  CordRepBtree* tree = CordRepBtree::Create(flat);\n  constexpr size_t max_cap = CordRepBtree::kMaxCapacity;\n  const size_t n = max_cap * max_cap * 2;\n  for (size_t i = 0; i < n; ++i) {\n    tree = CordRepBtree::Append(tree, MakeFlat(\"Hello world\"));\n  }\n  flat->length = 100;\n\n  SetCordBtreeExhaustiveValidation(false);\n  EXPECT_FALSE(CordRepBtree::IsValid(tree));\n  EXPECT_TRUE(CordRepBtree::IsValid(tree, true));\n  EXPECT_FALSE(CordRepBtree::IsValid(tree, false));\n  CordRepBtree::AssertValid(tree);\n  CordRepBtree::AssertValid(tree, true);\n#if defined(GTEST_HAS_DEATH_TEST)\n  EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree, false), \".*\");\n#endif\n\n  SetCordBtreeExhaustiveValidation(true);\n  EXPECT_FALSE(CordRepBtree::IsValid(tree));\n  EXPECT_FALSE(CordRepBtree::IsValid(tree, true));\n  EXPECT_FALSE(CordRepBtree::IsValid(tree, false));\n#if defined(GTEST_HAS_DEATH_TEST)\n  EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree), \".*\");\n  EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree, true), \".*\");\n#endif\n\n  flat->length = 3;\n  CordRep::Unref(tree);\n}\n\nTEST_P(CordRepBtreeTest, Rebuild) {\n  for (size_t size : {3u, 8u, 100u, 10000u, 1000000u}) {\n    SCOPED_TRACE(absl::StrCat(\"Rebuild @\", size));\n\n    std::vector<CordRepFlat*> flats;\n    for (size_t i = 0; i < size; ++i) {\n      flats.push_back(CordRepFlat::New(2));\n      flats.back()->Data()[0] = 'x';\n      flats.back()->length = 1;\n    }\n\n    // Build the tree into 'right', and each so many 'split_limit' edges,\n    // combine 'left' + 'right' into a new 'left', and start a new 'right'.\n    // This guarantees we get a reasonable amount of chaos in the tree.\n    size_t split_count = 0;\n    size_t split_limit = 3;\n    auto it = flats.begin();\n    CordRepBtree* left = nullptr;\n    CordRepBtree* right = CordRepBtree::New(*it);\n    while (++it != flats.end()) {\n      if (++split_count >= split_limit) {\n        split_limit += split_limit / 16;\n        left = left ? CordRepBtree::Append(left, right) : right;\n        right = CordRepBtree::New(*it);\n      } else {\n        right = CordRepBtree::Append(right, *it);\n      }\n    }\n\n    // Finalize tree\n    left = left ? CordRepBtree::Append(left, right) : right;\n\n    // Rebuild\n    AutoUnref ref;\n    left = ref.Add(CordRepBtree::Rebuild(ref.RefIf(shared(), left)));\n    ASSERT_TRUE(CordRepBtree::IsValid(left));\n\n    // Verify we have the exact same edges in the exact same order.\n    bool ok = true;\n    it = flats.begin();\n    CordVisitReps(left, [&](CordRep* edge) {\n      if (edge->tag < FLAT) return;\n      ok = ok && (it != flats.end() && *it++ == edge);\n    });\n    EXPECT_TRUE(ok && it == flats.end()) << \"Rebuild edges mismatch\";\n  }\n}\n\n// Convenience helper for CordRepBtree::ExtractAppendBuffer\nCordRepBtree::ExtractResult ExtractLast(CordRepBtree* input, size_t cap = 1) {\n  return CordRepBtree::ExtractAppendBuffer(input, cap);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferLeafSingleFlat) {\n  CordRep* flat = MakeFlat(\"Abc\");\n  CordRepBtree* leaf = CordRepBtree::Create(flat);\n  EXPECT_THAT(ExtractLast(leaf), EqExtractResult(nullptr, flat));\n  CordRep::Unref(flat);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNodeSingleFlat) {\n  CordRep* flat = MakeFlat(\"Abc\");\n  CordRepBtree* leaf = CordRepBtree::Create(flat);\n  CordRepBtree* node = CordRepBtree::New(leaf);\n  EXPECT_THAT(ExtractLast(node), EqExtractResult(nullptr, flat));\n  CordRep::Unref(flat);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferLeafTwoFlats) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdef\", 3);\n  CordRepBtree* leaf = CreateTree(flats);\n  EXPECT_THAT(ExtractLast(leaf), EqExtractResult(flats[0], flats[1]));\n  CordRep::Unref(flats[0]);\n  CordRep::Unref(flats[1]);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNodeTwoFlats) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdef\", 3);\n  CordRepBtree* leaf = CreateTree(flats);\n  CordRepBtree* node = CordRepBtree::New(leaf);\n  EXPECT_THAT(ExtractLast(node), EqExtractResult(flats[0], flats[1]));\n  CordRep::Unref(flats[0]);\n  CordRep::Unref(flats[1]);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNodeTwoFlatsInTwoLeafs) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdef\", 3);\n  CordRepBtree* leaf1 = CordRepBtree::Create(flats[0]);\n  CordRepBtree* leaf2 = CordRepBtree::Create(flats[1]);\n  CordRepBtree* node = CordRepBtree::New(leaf1, leaf2);\n  EXPECT_THAT(ExtractLast(node), EqExtractResult(flats[0], flats[1]));\n  CordRep::Unref(flats[0]);\n  CordRep::Unref(flats[1]);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferLeafThreeFlats) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdefghi\", 3);\n  CordRepBtree* leaf = CreateTree(flats);\n  EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, flats[2]));\n  CordRep::Unref(flats[2]);\n  CordRep::Unref(leaf);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNodeThreeFlatsRightNoFolding) {\n  CordRep* flat = MakeFlat(\"Abc\");\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"defghi\", 3);\n  CordRepBtree* leaf1 = CordRepBtree::Create(flat);\n  CordRepBtree* leaf2 = CreateTree(flats);\n  CordRepBtree* node = CordRepBtree::New(leaf1, leaf2);\n  EXPECT_THAT(ExtractLast(node), EqExtractResult(node, flats[1]));\n  EXPECT_THAT(node->Edges(), ElementsAre(leaf1, leaf2));\n  EXPECT_THAT(leaf1->Edges(), ElementsAre(flat));\n  EXPECT_THAT(leaf2->Edges(), ElementsAre(flats[0]));\n  CordRep::Unref(node);\n  CordRep::Unref(flats[1]);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNodeThreeFlatsRightLeafFolding) {\n  CordRep* flat = MakeFlat(\"Abc\");\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"defghi\", 3);\n  CordRepBtree* leaf1 = CreateTree(flats);\n  CordRepBtree* leaf2 = CordRepBtree::Create(flat);\n  CordRepBtree* node = CordRepBtree::New(leaf1, leaf2);\n  EXPECT_THAT(ExtractLast(node), EqExtractResult(leaf1, flat));\n  EXPECT_THAT(leaf1->Edges(), ElementsAreArray(flats));\n  CordRep::Unref(leaf1);\n  CordRep::Unref(flat);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNoCapacity) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdef\", 3);\n  CordRepBtree* leaf = CreateTree(flats);\n  size_t avail = flats[1]->flat()->Capacity() - flats[1]->length;\n  EXPECT_THAT(ExtractLast(leaf, avail + 1), EqExtractResult(leaf, nullptr));\n  EXPECT_THAT(ExtractLast(leaf, avail), EqExtractResult(flats[0], flats[1]));\n  CordRep::Unref(flats[0]);\n  CordRep::Unref(flats[1]);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferNotFlat) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdef\", 3);\n  auto substr = MakeSubstring(1, 2, flats[1]);\n  CordRepBtree* leaf = CreateTree({flats[0], substr});\n  EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, nullptr));\n  CordRep::Unref(leaf);\n}\n\nTEST(CordRepBtreeTest, ExtractAppendBufferShared) {\n  std::vector<CordRep*> flats = CreateFlatsFromString(\"abcdef\", 3);\n  CordRepBtree* leaf = CreateTree(flats);\n\n  CordRep::Ref(flats[1]);\n  EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, nullptr));\n  CordRep::Unref(flats[1]);\n\n  CordRep::Ref(leaf);\n  EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, nullptr));\n  CordRep::Unref(leaf);\n\n  CordRepBtree* node = CordRepBtree::New(leaf);\n  CordRep::Ref(node);\n  EXPECT_THAT(ExtractLast(node), EqExtractResult(node, nullptr));\n  CordRep::Unref(node);\n\n  CordRep::Unref(node);\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_consume.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_consume.h\"\n\n#include <array>\n#include <utility>\n\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nnamespace {\n\n// Unrefs the provided `substring`, and returns `substring->child`\n// Adds or assumes a reference on `substring->child`\nCordRep* ClipSubstring(CordRepSubstring* substring) {\n  CordRep* child = substring->child;\n  if (substring->refcount.IsOne()) {\n    delete substring;\n  } else {\n    CordRep::Ref(child);\n    CordRep::Unref(substring);\n  }\n  return child;\n}\n\n}  // namespace\n\nvoid Consume(CordRep* rep,\n             FunctionRef<void(CordRep*, size_t, size_t)> consume_fn) {\n  size_t offset = 0;\n  size_t length = rep->length;\n\n  if (rep->tag == SUBSTRING) {\n    offset += rep->substring()->start;\n    rep = ClipSubstring(rep->substring());\n  }\n  consume_fn(rep, offset, length);\n}\n\nvoid ReverseConsume(CordRep* rep,\n                    FunctionRef<void(CordRep*, size_t, size_t)> consume_fn) {\n  return Consume(rep, consume_fn);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_consume.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_\n\n#include <functional>\n\n#include \"absl/functional/function_ref.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// Consume() and ReverseConsume() consume CONCAT based trees and invoke the\n// provided functor with the contained nodes in the proper forward or reverse\n// order, which is used to convert CONCAT trees into other tree or cord data.\n// All CONCAT and SUBSTRING nodes are processed internally. The 'offset`\n// parameter of the functor is non-zero for any nodes below SUBSTRING nodes.\n// It's up to the caller to form these back into SUBSTRING nodes or otherwise\n// store offset / prefix information. These functions are intended to be used\n// only for migration / transitional code where due to factors such as ODR\n// violations, we can not 100% guarantee that all code respects 'new format'\n// settings and flags, so we need to be able to parse old data on the fly until\n// all old code is deprecated / no longer the default format.\nvoid Consume(CordRep* rep,\n             FunctionRef<void(CordRep*, size_t, size_t)> consume_fn);\nvoid ReverseConsume(CordRep* rep,\n                    FunctionRef<void(CordRep*, size_t, size_t)> consume_fn);\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_crc.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_crc.h\"\n\n#include <cassert>\n#include <cstdint>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nCordRepCrc* CordRepCrc::New(CordRep* child, crc_internal::CrcCordState state) {\n  if (child != nullptr && child->IsCrc()) {\n    if (child->refcount.IsOne()) {\n      child->crc()->crc_cord_state = std::move(state);\n      return child->crc();\n    }\n    CordRep* old = child;\n    child = old->crc()->child;\n    CordRep::Ref(child);\n    CordRep::Unref(old);\n  }\n  auto* new_cordrep = new CordRepCrc;\n  new_cordrep->length = child != nullptr ? child->length : 0;\n  new_cordrep->tag = cord_internal::CRC;\n  new_cordrep->child = child;\n  new_cordrep->crc_cord_state = std::move(state);\n  return new_cordrep;\n}\n\nvoid CordRepCrc::Destroy(CordRepCrc* node) {\n  if (node->child != nullptr) {\n    CordRep::Unref(node->child);\n  }\n  delete node;\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_crc.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_\n\n#include <cassert>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/crc/internal/crc_cord_state.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordRepCrc is a CordRep node intended only to appear at the top level of a\n// cord tree.  It associates an \"expected CRC\" with the contained data, to allow\n// for easy passage of checksum data in Cord data flows.\n//\n// From Cord's perspective, the crc value has no semantics; any validation of\n// the contained checksum is the user's responsibility.\nstruct CordRepCrc : public CordRep {\n  CordRep* child;\n  absl::crc_internal::CrcCordState crc_cord_state;\n\n  // Consumes `child` and returns a CordRepCrc prefixed tree containing `child`.\n  // If the specified `child` is itself a CordRepCrc node, then this method\n  // either replaces the existing node, or directly updates the crc state in it\n  // depending on the node being shared or not, i.e.: refcount.IsOne().\n  // `child` must only be null if the Cord is empty. Never returns null.\n  static CordRepCrc* New(CordRep* child, crc_internal::CrcCordState state);\n\n  // Destroys (deletes) the provided node. `node` must not be null.\n  static void Destroy(CordRepCrc* node);\n};\n\n// Consumes `rep` and returns a CordRep* with any outer CordRepCrc wrapper\n// removed.  This is usually a no-op (returning `rep`), but this will remove and\n// unref an outer CordRepCrc node.\ninline CordRep* RemoveCrcNode(CordRep* rep) {\n  assert(rep != nullptr);\n  if (ABSL_PREDICT_FALSE(rep->IsCrc())) {\n    CordRep* child = rep->crc()->child;\n    if (rep->refcount.IsOne()) {\n      delete rep->crc();\n    } else {\n      CordRep::Ref(child);\n      CordRep::Unref(rep);\n    }\n    return child;\n  }\n  return rep;\n}\n\n// Returns `rep` if it is not a CordRepCrc node, or its child if it is.\n// Does not consume or create a reference on `rep` or the returned value.\ninline CordRep* SkipCrcNode(CordRep* rep) {\n  assert(rep != nullptr);\n  if (ABSL_PREDICT_FALSE(rep->IsCrc())) {\n    return rep->crc()->child;\n  } else {\n    return rep;\n  }\n}\n\ninline const CordRep* SkipCrcNode(const CordRep* rep) {\n  assert(rep != nullptr);\n  if (ABSL_PREDICT_FALSE(rep->IsCrc())) {\n    return rep->crc()->child;\n  } else {\n    return rep;\n  }\n}\n\ninline CordRepCrc* CordRep::crc() {\n  assert(IsCrc());\n  return static_cast<CordRepCrc*>(this);\n}\n\ninline const CordRepCrc* CordRep::crc() const {\n  assert(IsCrc());\n  return static_cast<const CordRepCrc*>(this);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_crc_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cord_rep_crc.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/crc/internal/crc_cord_state.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_test_util.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::absl::cordrep_testing::MakeFlat;\nusing ::testing::Eq;\nusing ::testing::IsNull;\nusing ::testing::Ne;\n\n#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST\n\nTEST(CordRepCrc, RemoveCrcWithNullptr) {\n  EXPECT_DEATH(RemoveCrcNode(nullptr), \"\");\n}\n\n#endif  // !NDEBUG && GTEST_HAS_DEATH_TEST\n\nabsl::crc_internal::CrcCordState MakeCrcCordState(uint32_t crc) {\n  crc_internal::CrcCordState state;\n  state.mutable_rep()->prefix_crc.push_back(\n      crc_internal::CrcCordState::PrefixCrc(42, crc32c_t{crc}));\n  return state;\n}\n\nTEST(CordRepCrc, NewDestroy) {\n  CordRep* rep = cordrep_testing::MakeFlat(\"Hello world\");\n  CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345));\n  EXPECT_TRUE(crc->refcount.IsOne());\n  EXPECT_THAT(crc->child, Eq(rep));\n  EXPECT_THAT(crc->crc_cord_state.Checksum(), Eq(crc32c_t{12345u}));\n  EXPECT_TRUE(rep->refcount.IsOne());\n  CordRepCrc::Destroy(crc);\n}\n\nTEST(CordRepCrc, NewExistingCrcNotShared) {\n  CordRep* rep = cordrep_testing::MakeFlat(\"Hello world\");\n  CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345));\n  CordRepCrc* new_crc = CordRepCrc::New(crc, MakeCrcCordState(54321));\n  EXPECT_THAT(new_crc, Eq(crc));\n  EXPECT_TRUE(new_crc->refcount.IsOne());\n  EXPECT_THAT(new_crc->child, Eq(rep));\n  EXPECT_THAT(new_crc->crc_cord_state.Checksum(), Eq(crc32c_t{54321u}));\n  EXPECT_TRUE(rep->refcount.IsOne());\n  CordRepCrc::Destroy(new_crc);\n}\n\nTEST(CordRepCrc, NewExistingCrcShared) {\n  CordRep* rep = cordrep_testing::MakeFlat(\"Hello world\");\n  CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345));\n  CordRep::Ref(crc);\n  CordRepCrc* new_crc = CordRepCrc::New(crc, MakeCrcCordState(54321));\n\n  EXPECT_THAT(new_crc, Ne(crc));\n  EXPECT_TRUE(new_crc->refcount.IsOne());\n  EXPECT_TRUE(crc->refcount.IsOne());\n  EXPECT_FALSE(rep->refcount.IsOne());\n  EXPECT_THAT(crc->child, Eq(rep));\n  EXPECT_THAT(new_crc->child, Eq(rep));\n  EXPECT_THAT(crc->crc_cord_state.Checksum(), Eq(crc32c_t{12345u}));\n  EXPECT_THAT(new_crc->crc_cord_state.Checksum(), Eq(crc32c_t{54321u}));\n\n  CordRep::Unref(crc);\n  CordRep::Unref(new_crc);\n}\n\nTEST(CordRepCrc, NewEmpty) {\n  CordRepCrc* crc = CordRepCrc::New(nullptr, MakeCrcCordState(12345));\n  EXPECT_TRUE(crc->refcount.IsOne());\n  EXPECT_THAT(crc->child, IsNull());\n  EXPECT_THAT(crc->length, Eq(0u));\n  EXPECT_THAT(crc->crc_cord_state.Checksum(), Eq(crc32c_t{12345u}));\n  EXPECT_TRUE(crc->refcount.IsOne());\n  CordRepCrc::Destroy(crc);\n}\n\nTEST(CordRepCrc, RemoveCrcNotCrc) {\n  CordRep* rep = cordrep_testing::MakeFlat(\"Hello world\");\n  CordRep* nocrc = RemoveCrcNode(rep);\n  EXPECT_THAT(nocrc, Eq(rep));\n  CordRep::Unref(nocrc);\n}\n\nTEST(CordRepCrc, RemoveCrcNotShared) {\n  CordRep* rep = cordrep_testing::MakeFlat(\"Hello world\");\n  CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345));\n  CordRep* nocrc = RemoveCrcNode(crc);\n  EXPECT_THAT(nocrc, Eq(rep));\n  EXPECT_TRUE(rep->refcount.IsOne());\n  CordRep::Unref(nocrc);\n}\n\nTEST(CordRepCrc, RemoveCrcShared) {\n  CordRep* rep = cordrep_testing::MakeFlat(\"Hello world\");\n  CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345));\n  CordRep::Ref(crc);\n  CordRep* nocrc = RemoveCrcNode(crc);\n  EXPECT_THAT(nocrc, Eq(rep));\n  EXPECT_FALSE(rep->refcount.IsOne());\n  CordRep::Unref(nocrc);\n  CordRep::Unref(crc);\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_flat.h",
    "content": "// Copyright 2020 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_\n\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// Note: all constants below are never ODR used and internal to cord, we define\n// these as static constexpr to avoid 'in struct' definition and usage clutter.\n\n// Largest and smallest flat node lengths we are willing to allocate\n// Flat allocation size is stored in tag, which currently can encode sizes up\n// to 4K, encoded as multiple of either 8 or 32 bytes.\n// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.\n// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and\n// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.\n// kMaxFlatSize is bounded by the size resulting in a computed tag no greater\n// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.\nstatic constexpr size_t kFlatOverhead = offsetof(CordRep, storage);\nstatic constexpr size_t kMinFlatSize = 32;\nstatic constexpr size_t kMaxFlatSize = 4096;\nstatic constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;\nstatic constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;\nstatic constexpr size_t kMaxLargeFlatSize = 256 * 1024;\nstatic constexpr size_t kMaxLargeFlatLength = kMaxLargeFlatSize - kFlatOverhead;\n\n// kTagBase should make the Size <--> Tag computation resilient\n// against changes to the value of FLAT when we add a new tag..\nstatic constexpr uint8_t kTagBase = FLAT - 4;\n\n// Converts the provided rounded size to the corresponding tag\nconstexpr uint8_t AllocatedSizeToTagUnchecked(size_t size) {\n  return static_cast<uint8_t>(size <= 512 ? kTagBase + size / 8\n                              : size <= 8192\n                                  ? kTagBase + 512 / 8 + size / 64 - 512 / 64\n                                  : kTagBase + 512 / 8 + ((8192 - 512) / 64) +\n                                        size / 4096 - 8192 / 4096);\n}\n\n// Converts the provided tag to the corresponding allocated size\nconstexpr size_t TagToAllocatedSize(uint8_t tag) {\n  return (tag <= kTagBase + 512 / 8) ? tag * 8 - kTagBase * 8\n         : (tag <= kTagBase + (512 / 8) + ((8192 - 512) / 64))\n             ? 512 + tag * 64 - kTagBase * 64 - 512 / 8 * 64\n             : 8192 + tag * 4096 - kTagBase * 4096 -\n                   ((512 / 8) + ((8192 - 512) / 64)) * 4096;\n}\n\nstatic_assert(AllocatedSizeToTagUnchecked(kMinFlatSize) == FLAT, \"\");\nstatic_assert(AllocatedSizeToTagUnchecked(kMaxLargeFlatSize) == MAX_FLAT_TAG,\n              \"\");\n\n// RoundUp logically performs `((n + m - 1) / m) * m` to round up to the nearest\n// multiple of `m`, optimized for the invariant that `m` is a power of 2.\nconstexpr size_t RoundUp(size_t n, size_t m) {\n  return (n + m - 1) & (0 - m);\n}\n\n// Returns the size to the nearest equal or larger value that can be\n// expressed exactly as a tag value.\ninline size_t RoundUpForTag(size_t size) {\n  return RoundUp(size, (size <= 512) ? 8 : (size <= 8192 ? 64 : 4096));\n}\n\n// Converts the allocated size to a tag, rounding down if the size\n// does not exactly match a 'tag expressible' size value. The result is\n// undefined if the size exceeds the maximum size that can be encoded in\n// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).\ninline uint8_t AllocatedSizeToTag(size_t size) {\n  const uint8_t tag = AllocatedSizeToTagUnchecked(size);\n  assert(tag <= MAX_FLAT_TAG);\n  return tag;\n}\n\n// Converts the provided tag to the corresponding available data length\nconstexpr size_t TagToLength(uint8_t tag) {\n  return TagToAllocatedSize(tag) - kFlatOverhead;\n}\n\n// Enforce that kMaxFlatSize maps to a well-known exact tag value.\nstatic_assert(TagToAllocatedSize(MAX_FLAT_TAG) == kMaxLargeFlatSize,\n              \"Bad tag logic\");\n\nstruct CordRepFlat : public CordRep {\n  // Tag for explicit 'large flat' allocation\n  struct Large {};\n\n  // Creates a new flat node.\n  template <size_t max_flat_size, typename... Args>\n  static CordRepFlat* NewImpl(size_t len, Args... args ABSL_ATTRIBUTE_UNUSED) {\n    if (len <= kMinFlatLength) {\n      len = kMinFlatLength;\n    } else if (len > max_flat_size - kFlatOverhead) {\n      len = max_flat_size - kFlatOverhead;\n    }\n\n    // Round size up so it matches a size we can exactly express in a tag.\n    const size_t size = RoundUpForTag(len + kFlatOverhead);\n    void* const raw_rep = ::operator new(size);\n    // GCC 13 has a false-positive -Wstringop-overflow warning here.\n    #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(13, 0)\n    #pragma GCC diagnostic push\n    #pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n    #endif\n    CordRepFlat* rep = new (raw_rep) CordRepFlat();\n    rep->tag = AllocatedSizeToTag(size);\n    #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(13, 0)\n    #pragma GCC diagnostic pop\n    #endif\n    return rep;\n  }\n\n  static CordRepFlat* New(size_t len) { return NewImpl<kMaxFlatSize>(len); }\n\n  static CordRepFlat* New(Large, size_t len) {\n    return NewImpl<kMaxLargeFlatSize>(len);\n  }\n\n  // Deletes a CordRepFlat instance created previously through a call to New().\n  // Flat CordReps are allocated and constructed with raw ::operator new and\n  // placement new, and must be destructed and deallocated accordingly.\n  static void Delete(CordRep*rep) {\n    assert(rep->tag >= FLAT && rep->tag <= MAX_FLAT_TAG);\n\n#if defined(__cpp_sized_deallocation)\n    size_t size = TagToAllocatedSize(rep->tag);\n    rep->~CordRep();\n    ::operator delete(rep, size);\n#else\n    rep->~CordRep();\n    ::operator delete(rep);\n#endif\n  }\n\n  // Create a CordRepFlat containing `data`, with an optional additional\n  // extra capacity of up to `extra` bytes. Requires that `data.size()`\n  // is less than kMaxFlatLength.\n  static CordRepFlat* Create(absl::string_view data, size_t extra = 0) {\n    assert(data.size() <= kMaxFlatLength);\n    CordRepFlat* flat = New(data.size() + (std::min)(extra, kMaxFlatLength));\n    memcpy(flat->Data(), data.data(), data.size());\n    flat->length = data.size();\n    return flat;\n  }\n\n  // Returns a pointer to the data inside this flat rep.\n  char* Data() { return reinterpret_cast<char*>(storage); }\n  const char* Data() const { return reinterpret_cast<const char*>(storage); }\n\n  // Returns the maximum capacity (payload size) of this instance.\n  size_t Capacity() const { return TagToLength(tag); }\n\n  // Returns the allocated size (payload + overhead) of this instance.\n  size_t AllocatedSize() const { return TagToAllocatedSize(tag); }\n};\n\n// Now that CordRepFlat is defined, we can define CordRep's helper casts:\ninline CordRepFlat* CordRep::flat() {\n  assert(tag >= FLAT && tag <= MAX_FLAT_TAG);\n  return reinterpret_cast<CordRepFlat*>(this);\n}\n\ninline const CordRepFlat* CordRep::flat() const {\n  assert(tag >= FLAT && tag <= MAX_FLAT_TAG);\n  return reinterpret_cast<const CordRepFlat*>(this);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_\n"
  },
  {
    "path": "absl/strings/internal/cord_rep_test_util.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_\n#define ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_\n\n#include <cassert>\n#include <memory>\n#include <random>\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cordrep_testing {\n\ninline cord_internal::CordRepSubstring* MakeSubstring(\n    size_t start, size_t len, cord_internal::CordRep* rep) {\n  auto* sub = new cord_internal::CordRepSubstring;\n  sub->tag = cord_internal::SUBSTRING;\n  sub->start = start;\n  sub->length = len <= 0 ? rep->length - start + len : len;\n  sub->child = rep;\n  return sub;\n}\n\ninline cord_internal::CordRepFlat* MakeFlat(absl::string_view value) {\n  assert(value.length() <= cord_internal::kMaxFlatLength);\n  auto* flat = cord_internal::CordRepFlat::New(value.length());\n  flat->length = value.length();\n  memcpy(flat->Data(), value.data(), value.length());\n  return flat;\n}\n\n// Creates an external node for testing\ninline cord_internal::CordRepExternal* MakeExternal(absl::string_view s) {\n  struct Rep : public cord_internal::CordRepExternal {\n    std::string s;\n    explicit Rep(absl::string_view sv) : s(sv) {\n      this->tag = cord_internal::EXTERNAL;\n      this->base = s.data();\n      this->length = s.length();\n      this->releaser_invoker = [](cord_internal::CordRepExternal* self) {\n        delete static_cast<Rep*>(self);\n      };\n    }\n  };\n  return new Rep(s);\n}\n\ninline std::string CreateRandomString(size_t n) {\n  absl::string_view data =\n      \"abcdefghijklmnopqrstuvwxyz\"\n      \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n      \"0123456789~!@#$%^&*()_+=-<>?:\\\"{}[]|\";\n  std::minstd_rand rnd;\n  std::uniform_int_distribution<size_t> dist(0, data.size() - 1);\n  std::string s(n, ' ');\n  for (size_t i = 0; i < n; ++i) {\n    s[i] = data[dist(rnd)];\n  }\n  return s;\n}\n\n// Creates an array of flats from the provided string, chopping\n// the provided string up into flats of size `chunk_size` characters\n// resulting in roughly `data.size() / chunk_size` total flats.\ninline std::vector<cord_internal::CordRep*> CreateFlatsFromString(\n    absl::string_view data, size_t chunk_size) {\n  assert(chunk_size > 0);\n  std::vector<cord_internal::CordRep*> flats;\n  for (absl::string_view s = data; !s.empty(); s.remove_prefix(chunk_size)) {\n    flats.push_back(MakeFlat(s.substr(0, chunk_size)));\n  }\n  return flats;\n}\n\ninline cord_internal::CordRepBtree* CordRepBtreeFromFlats(\n    absl::Span<cord_internal::CordRep* const> flats) {\n  assert(!flats.empty());\n  auto* node = cord_internal::CordRepBtree::Create(flats[0]);\n  for (size_t i = 1; i < flats.size(); ++i) {\n    node = cord_internal::CordRepBtree::Append(node, flats[i]);\n  }\n  return node;\n}\n\ntemplate <typename Fn>\ninline void CordVisitReps(cord_internal::CordRep* rep, Fn&& fn) {\n  fn(rep);\n  while (rep->tag == cord_internal::SUBSTRING) {\n    rep = rep->substring()->child;\n    fn(rep);\n  }\n  if (rep->tag == cord_internal::BTREE) {\n    for (cord_internal::CordRep* edge : rep->btree()->Edges()) {\n      CordVisitReps(edge, fn);\n    }\n  }\n}\n\ntemplate <typename Predicate>\ninline std::vector<cord_internal::CordRep*> CordCollectRepsIf(\n    Predicate&& predicate, cord_internal::CordRep* rep) {\n  std::vector<cord_internal::CordRep*> reps;\n  CordVisitReps(rep, [&reps, &predicate](cord_internal::CordRep* rep) {\n    if (predicate(rep)) reps.push_back(rep);\n  });\n  return reps;\n}\n\ninline std::vector<cord_internal::CordRep*> CordCollectReps(\n    cord_internal::CordRep* rep) {\n  std::vector<cord_internal::CordRep*> reps;\n  auto fn = [&reps](cord_internal::CordRep* rep) { reps.push_back(rep); };\n  CordVisitReps(rep, fn);\n  return reps;\n}\n\ninline void CordToString(cord_internal::CordRep* rep, std::string& s) {\n  size_t offset = 0;\n  size_t length = rep->length;\n  while (rep->tag == cord_internal::SUBSTRING) {\n    offset += rep->substring()->start;\n    rep = rep->substring()->child;\n  }\n  if (rep->tag == cord_internal::BTREE) {\n    for (cord_internal::CordRep* edge : rep->btree()->Edges()) {\n      CordToString(edge, s);\n    }\n  } else if (rep->tag >= cord_internal::FLAT) {\n    s.append(rep->flat()->Data() + offset, length);\n  } else if (rep->tag == cord_internal::EXTERNAL) {\n    s.append(rep->external()->base + offset, length);\n  } else {\n    ABSL_RAW_LOG(FATAL, \"Unsupported tag %d\", rep->tag);\n  }\n}\n\ninline std::string CordToString(cord_internal::CordRep* rep) {\n  std::string s;\n  s.reserve(rep->length);\n  CordToString(rep, s);\n  return s;\n}\n\n// RAII Helper class to automatically unref reps on destruction.\nclass AutoUnref {\n public:\n  ~AutoUnref() {\n    for (CordRep* rep : unrefs_) CordRep::Unref(rep);\n  }\n\n  // Adds `rep` to the list of reps to be unreffed at destruction.\n  template <typename CordRepType>\n  CordRepType* Add(CordRepType* rep) {\n    unrefs_.push_back(rep);\n    return rep;\n  }\n\n  // Increments the reference count of `rep` by one, and adds it to\n  // the list of reps to be unreffed at destruction.\n  template <typename CordRepType>\n  CordRepType* Ref(CordRepType* rep) {\n    unrefs_.push_back(CordRep::Ref(rep));\n    return rep;\n  }\n\n  // Increments the reference count of `rep` by one if `condition` is true,\n  // and adds it to the list of reps to be unreffed at destruction.\n  template <typename CordRepType>\n  CordRepType* RefIf(bool condition, CordRepType* rep) {\n    if (condition) unrefs_.push_back(CordRep::Ref(rep));\n    return rep;\n  }\n\n private:\n  using CordRep = absl::cord_internal::CordRep;\n\n  std::vector<CordRep*> unrefs_;\n};\n\n}  // namespace cordrep_testing\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_functions.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_functions.h\"\n\n#include <atomic>\n#include <cmath>\n#include <limits>\n#include <random>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/profiling/internal/exponential_biased.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\n// The average interval until the next sample. A value of 0 disables profiling\n// while a value of 1 will profile all Cords.\nstd::atomic<int> g_cordz_mean_interval(50000);\n\n}  // namespace\n\n#ifdef ABSL_INTERNAL_CORDZ_ENABLED\n\n// Special negative 'not initialized' per thread value for cordz_next_sample.\nstatic constexpr int64_t kInitCordzNextSample = -1;\n\nABSL_CONST_INIT thread_local SamplingState cordz_next_sample = {\n    kInitCordzNextSample, 1};\n\n// kIntervalIfDisabled is the number of profile-eligible events need to occur\n// before the code will confirm that cordz is still disabled.\nconstexpr int64_t kIntervalIfDisabled = 1 << 16;\n\nABSL_ATTRIBUTE_NOINLINE int64_t\ncordz_should_profile_slow(SamplingState& state) {\n\n  thread_local absl::profiling_internal::ExponentialBiased\n      exponential_biased_generator;\n  int32_t mean_interval = get_cordz_mean_interval();\n\n  // Check if we disabled profiling. If so, set the next sample to a \"large\"\n  // number to minimize the overhead of the should_profile codepath.\n  if (mean_interval <= 0) {\n    state = {kIntervalIfDisabled, kIntervalIfDisabled};\n    return 0;\n  }\n\n  // Check if we're always sampling.\n  if (mean_interval == 1) {\n    state = {1, 1};\n    return 1;\n  }\n\n  if (cordz_next_sample.next_sample <= 0) {\n    // If first check on current thread, check cordz_should_profile()\n    // again using the created (initial) stride in cordz_next_sample.\n    const bool initialized =\n        cordz_next_sample.next_sample != kInitCordzNextSample;\n    auto old_stride = state.sample_stride;\n    auto stride = exponential_biased_generator.GetStride(mean_interval);\n    state = {stride, stride};\n    bool should_sample = initialized || cordz_should_profile() > 0;\n    return should_sample ? old_stride : 0;\n  }\n\n  --state.next_sample;\n  return 0;\n}\n\nvoid cordz_set_next_sample_for_testing(int64_t next_sample) {\n  cordz_next_sample = {next_sample, next_sample};\n}\n\n#endif  // ABSL_INTERNAL_CORDZ_ENABLED\n\nint32_t get_cordz_mean_interval() {\n  return g_cordz_mean_interval.load(std::memory_order_acquire);\n}\n\nvoid set_cordz_mean_interval(int32_t mean_interval) {\n  g_cordz_mean_interval.store(mean_interval, std::memory_order_release);\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_functions.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_\n\n#include <stdint.h>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// Returns the current sample rate. This represents the average interval\n// between samples.\nint32_t get_cordz_mean_interval();\n\n// Sets the sample rate with the average interval between samples.\nvoid set_cordz_mean_interval(int32_t mean_interval);\n\n// Cordz is only enabled on Linux with thread_local support.\n#if defined(ABSL_INTERNAL_CORDZ_ENABLED)\n#error ABSL_INTERNAL_CORDZ_ENABLED cannot be set directly\n#elif defined(__linux__) && defined(ABSL_HAVE_THREAD_LOCAL)\n#define ABSL_INTERNAL_CORDZ_ENABLED 1\n#endif\n\n#ifdef ABSL_INTERNAL_CORDZ_ENABLED\n\nstruct SamplingState {\n  int64_t next_sample;\n  int64_t sample_stride;\n};\n\n// cordz_next_sample is the number of events until the next sample event. If\n// the value is 1 or less, the code will check on the next event if cordz is\n// enabled, and if so, will sample the Cord. cordz is only enabled when we can\n// use thread locals.\nABSL_CONST_INIT extern thread_local SamplingState cordz_next_sample;\n\n// Determines if the next sample should be profiled.\n// Returns:\n//   0: Do not sample\n//  >0: Sample with the stride of the last sampling period\nint64_t cordz_should_profile_slow(SamplingState& state);\n\n// Determines if the next sample should be profiled.\n// Returns:\n//   0: Do not sample\n//  >0: Sample with the stride of the last sampling period\ninline int64_t cordz_should_profile() {\n  if (ABSL_PREDICT_TRUE(cordz_next_sample.next_sample > 1)) {\n    cordz_next_sample.next_sample--;\n    return 0;\n  }\n  return cordz_should_profile_slow(cordz_next_sample);\n}\n\n// Sets the interval until the next sample (for testing only)\nvoid cordz_set_next_sample_for_testing(int64_t next_sample);\n\n#else  // ABSL_INTERNAL_CORDZ_ENABLED\n\ninline int64_t cordz_should_profile() { return 0; }\ninline void cordz_set_next_sample_for_testing(int64_t) {}\n\n#endif  // ABSL_INTERNAL_CORDZ_ENABLED\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_functions_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_functions.h\"\n\n#include <thread>  // NOLINT we need real clean new threads\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::Ge;\nusing ::testing::Le;\n\nTEST(CordzFunctionsTest, SampleRate) {\n  int32_t orig_sample_rate = get_cordz_mean_interval();\n  int32_t expected_sample_rate = 123;\n  set_cordz_mean_interval(expected_sample_rate);\n  EXPECT_THAT(get_cordz_mean_interval(), Eq(expected_sample_rate));\n  set_cordz_mean_interval(orig_sample_rate);\n}\n\n// Cordz is disabled when we don't have thread_local. All calls to\n// should_profile will return false when cordz is disabled, so we might want to\n// avoid those tests.\n#ifdef ABSL_INTERNAL_CORDZ_ENABLED\n\nTEST(CordzFunctionsTest, ShouldProfileDisable) {\n  int32_t orig_sample_rate = get_cordz_mean_interval();\n\n  set_cordz_mean_interval(0);\n  cordz_set_next_sample_for_testing(0);\n  EXPECT_EQ(cordz_should_profile(), 0);\n  // 1 << 16 is from kIntervalIfDisabled in cordz_functions.cc.\n  EXPECT_THAT(cordz_next_sample.next_sample, Eq(1 << 16));\n\n  set_cordz_mean_interval(orig_sample_rate);\n}\n\nTEST(CordzFunctionsTest, ShouldProfileAlways) {\n  int32_t orig_sample_rate = get_cordz_mean_interval();\n\n  set_cordz_mean_interval(1);\n  cordz_set_next_sample_for_testing(1);\n  EXPECT_GT(cordz_should_profile(), 0);\n  EXPECT_THAT(cordz_next_sample.next_sample, Le(1));\n\n  set_cordz_mean_interval(orig_sample_rate);\n}\n\nTEST(CordzFunctionsTest, DoesNotAlwaysSampleFirstCord) {\n  // Set large enough interval such that the chance of 'tons' of threads\n  // randomly sampling the first call is infinitely small.\n  set_cordz_mean_interval(10000);\n  int tries = 0;\n  bool sampled = false;\n  do {\n    ++tries;\n    ASSERT_THAT(tries, Le(1000));\n    std::thread thread([&sampled] { sampled = cordz_should_profile() > 0; });\n    thread.join();\n  } while (sampled);\n}\n\nTEST(CordzFunctionsTest, ShouldProfileRate) {\n  static constexpr int kDesiredMeanInterval = 1000;\n  static constexpr int kSamples = 10000;\n  int32_t orig_sample_rate = get_cordz_mean_interval();\n\n  set_cordz_mean_interval(kDesiredMeanInterval);\n\n  int64_t sum_of_intervals = 0;\n  for (int i = 0; i < kSamples; i++) {\n    // Setting next_sample to 0 will force cordz_should_profile to generate a\n    // new value for next_sample each iteration.\n    cordz_set_next_sample_for_testing(0);\n    cordz_should_profile();\n    sum_of_intervals += cordz_next_sample.next_sample;\n  }\n\n  // The sum of independent exponential variables is an Erlang distribution,\n  // which is a gamma distribution where the shape parameter is equal to the\n  // number of summands. The distribution used for cordz_should_profile is\n  // actually floor(Exponential(1/mean)) which introduces bias. However, we can\n  // apply the squint-really-hard correction factor. That is, when mean is\n  // large, then if we squint really hard the shape of the distribution between\n  // N and N+1 looks like a uniform distribution. On average, each value for\n  // next_sample will be about 0.5 lower than we would expect from an\n  // exponential distribution. This squint-really-hard correction approach won't\n  // work when mean is smaller than about 10 but works fine when mean is 1000.\n  //\n  // We can use R to calculate a confidence interval. This\n  // shows how to generate a confidence interval with a false positive rate of\n  // one in a billion.\n  //\n  // $ R -q\n  // > mean = 1000\n  // > kSamples = 10000\n  // > errorRate = 1e-9\n  // > correction = -kSamples / 2\n  // > low = qgamma(errorRate/2, kSamples, 1/mean) + correction\n  // > high = qgamma(1 - errorRate/2, kSamples, 1/mean) + correction\n  // > low\n  // [1] 9396115\n  // > high\n  // [1] 10618100\n  EXPECT_THAT(sum_of_intervals, Ge(9396115));\n  EXPECT_THAT(sum_of_intervals, Le(10618100));\n\n  set_cordz_mean_interval(orig_sample_rate);\n}\n\n#else  // ABSL_INTERNAL_CORDZ_ENABLED\n\nTEST(CordzFunctionsTest, ShouldProfileDisabled) {\n  int32_t orig_sample_rate = get_cordz_mean_interval();\n\n  set_cordz_mean_interval(1);\n  cordz_set_next_sample_for_testing(0);\n  EXPECT_FALSE(cordz_should_profile());\n\n  set_cordz_mean_interval(orig_sample_rate);\n}\n\n#endif  // ABSL_INTERNAL_CORDZ_ENABLED\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_handle.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/strings/internal/cordz_handle.h\"\n\n#include <atomic>\n\n#include \"absl/base/internal/raw_logging.h\"  // For ABSL_RAW_CHECK\n#include \"absl/base/no_destructor.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nnamespace {\n\nstruct Queue {\n  Queue() = default;\n\n  absl::Mutex mutex;\n  std::atomic<CordzHandle*> dq_tail ABSL_GUARDED_BY(mutex){nullptr};\n\n  // Returns true if this delete queue is empty. This method does not acquire\n  // the lock, but does a 'load acquire' observation on the delete queue tail.\n  // It is used inside Delete() to check for the presence of a delete queue\n  // without holding the lock. The assumption is that the caller is in the\n  // state of 'being deleted', and can not be newly discovered by a concurrent\n  // 'being constructed' snapshot instance. Practically, this means that any\n  // such discovery (`find`, 'first' or 'next', etc) must have proper 'happens\n  // before / after' semantics and atomic fences.\n  bool IsEmpty() const ABSL_NO_THREAD_SAFETY_ANALYSIS {\n    return dq_tail.load(std::memory_order_acquire) == nullptr;\n  }\n};\n\nstatic Queue& GlobalQueue() {\n  static absl::NoDestructor<Queue> global_queue;\n  return *global_queue;\n}\n\n}  // namespace\n\nCordzHandle::CordzHandle(bool is_snapshot) : is_snapshot_(is_snapshot) {\n  Queue& global_queue = GlobalQueue();\n  if (is_snapshot) {\n    MutexLock lock(global_queue.mutex);\n    CordzHandle* dq_tail = global_queue.dq_tail.load(std::memory_order_acquire);\n    if (dq_tail != nullptr) {\n      dq_prev_ = dq_tail;\n      dq_tail->dq_next_ = this;\n    }\n    global_queue.dq_tail.store(this, std::memory_order_release);\n  }\n}\n\nCordzHandle::~CordzHandle() {\n  Queue& global_queue = GlobalQueue();\n  if (is_snapshot_) {\n    std::vector<CordzHandle*> to_delete;\n    {\n      MutexLock lock(global_queue.mutex);\n      CordzHandle* next = dq_next_;\n      if (dq_prev_ == nullptr) {\n        // We were head of the queue, delete every CordzHandle until we reach\n        // either the end of the list, or a snapshot handle.\n        while (next && !next->is_snapshot_) {\n          to_delete.push_back(next);\n          next = next->dq_next_;\n        }\n      } else {\n        // Another CordzHandle existed before this one, don't delete anything.\n        dq_prev_->dq_next_ = next;\n      }\n      if (next) {\n        next->dq_prev_ = dq_prev_;\n      } else {\n        global_queue.dq_tail.store(dq_prev_, std::memory_order_release);\n      }\n    }\n    for (CordzHandle* handle : to_delete) {\n      delete handle;\n    }\n  }\n}\n\nbool CordzHandle::SafeToDelete() const {\n  return is_snapshot_ || GlobalQueue().IsEmpty();\n}\n\nvoid CordzHandle::Delete(CordzHandle* handle) {\n  assert(handle);\n  if (handle) {\n    Queue& queue = GlobalQueue();\n    if (!handle->SafeToDelete()) {\n      MutexLock lock(queue.mutex);\n      CordzHandle* dq_tail = queue.dq_tail.load(std::memory_order_acquire);\n      if (dq_tail != nullptr) {\n        handle->dq_prev_ = dq_tail;\n        dq_tail->dq_next_ = handle;\n        queue.dq_tail.store(handle, std::memory_order_release);\n        return;\n      }\n    }\n    delete handle;\n  }\n}\n\nstd::vector<const CordzHandle*> CordzHandle::DiagnosticsGetDeleteQueue() {\n  std::vector<const CordzHandle*> handles;\n  Queue& global_queue = GlobalQueue();\n  MutexLock lock(global_queue.mutex);\n  CordzHandle* dq_tail = global_queue.dq_tail.load(std::memory_order_acquire);\n  for (const CordzHandle* p = dq_tail; p; p = p->dq_prev_) {\n    handles.push_back(p);\n  }\n  return handles;\n}\n\nbool CordzHandle::DiagnosticsHandleIsSafeToInspect(\n    const CordzHandle* handle) const {\n  if (!is_snapshot_) return false;\n  if (handle == nullptr) return true;\n  if (handle->is_snapshot_) return false;\n  bool snapshot_found = false;\n  Queue& global_queue = GlobalQueue();\n  MutexLock lock(global_queue.mutex);\n  for (const CordzHandle* p = global_queue.dq_tail; p; p = p->dq_prev_) {\n    if (p == handle) return !snapshot_found;\n    if (p == this) snapshot_found = true;\n  }\n  ABSL_ASSERT(snapshot_found);  // Assert that 'this' is in delete queue.\n  return true;\n}\n\nstd::vector<const CordzHandle*>\nCordzHandle::DiagnosticsGetSafeToInspectDeletedHandles() {\n  std::vector<const CordzHandle*> handles;\n  if (!is_snapshot()) {\n    return handles;\n  }\n\n  Queue& global_queue = GlobalQueue();\n  MutexLock lock(global_queue.mutex);\n  for (const CordzHandle* p = dq_next_; p != nullptr; p = p->dq_next_) {\n    if (!p->is_snapshot()) {\n      handles.push_back(p);\n    }\n  }\n  return handles;\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_handle.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_\n\n#include <atomic>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// This base class allows multiple types of object (CordzInfo and\n// CordzSampleToken) to exist simultaneously on the delete queue (pointed to by\n// global_dq_tail and traversed using dq_prev_ and dq_next_). The\n// delete queue guarantees that once a profiler creates a CordzSampleToken and\n// has gained visibility into a CordzInfo object, that CordzInfo object will not\n// be deleted prematurely. This allows the profiler to inspect all CordzInfo\n// objects that are alive without needing to hold a global lock.\nclass ABSL_DLL CordzHandle {\n public:\n  CordzHandle() : CordzHandle(false) {}\n\n  bool is_snapshot() const { return is_snapshot_; }\n\n  // Returns true if this instance is safe to be deleted because it is either a\n  // snapshot, which is always safe to delete, or not included in the global\n  // delete queue and thus not included in any snapshot.\n  // Callers are responsible for making sure this instance can not be newly\n  // discovered by other threads. For example, CordzInfo instances first de-list\n  // themselves from the global CordzInfo list before determining if they are\n  // safe to be deleted directly.\n  // If SafeToDelete returns false, callers MUST use the Delete() method to\n  // safely queue CordzHandle instances for deletion.\n  bool SafeToDelete() const;\n\n  // Deletes the provided instance, or puts it on the delete queue to be deleted\n  // once there are no more sample tokens (snapshot) instances potentially\n  // referencing the instance. `handle` should not be null.\n  static void Delete(CordzHandle* handle);\n\n  // Returns the current entries in the delete queue in LIFO order.\n  static std::vector<const CordzHandle*> DiagnosticsGetDeleteQueue();\n\n  // Returns true if the provided handle is nullptr or guarded by this handle.\n  // Since the CordzSnapshot token is itself a CordzHandle, this method will\n  // allow tests to check if that token is keeping an arbitrary CordzHandle\n  // alive.\n  bool DiagnosticsHandleIsSafeToInspect(const CordzHandle* handle) const;\n\n  // Returns the current entries in the delete queue, in LIFO order, that are\n  // protected by this. CordzHandle objects are only placed on the delete queue\n  // after CordzHandle::Delete is called with them as an argument. Only\n  // CordzHandle objects that are not also CordzSnapshot objects will be\n  // included in the return vector. For each of the handles in the return\n  // vector, the earliest that their memory can be freed is when this\n  // CordzSnapshot object is deleted.\n  std::vector<const CordzHandle*> DiagnosticsGetSafeToInspectDeletedHandles();\n\n protected:\n  explicit CordzHandle(bool is_snapshot);\n  virtual ~CordzHandle();\n\n private:\n  const bool is_snapshot_;\n\n  // dq_prev_ and dq_next_ require the global queue mutex to be held.\n  // Unfortunately we can't use thread annotations such that the thread safety\n  // analysis understands that queue_ and global_queue_ are one and the same.\n  CordzHandle* dq_prev_  = nullptr;\n  CordzHandle* dq_next_ = nullptr;\n};\n\nclass CordzSnapshot : public CordzHandle {\n public:\n  CordzSnapshot() : CordzHandle(true) {}\n};\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_handle_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#include \"absl/strings/internal/cordz_handle.h\"\n\n#include <random>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/notification.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::Gt;\nusing ::testing::IsEmpty;\nusing ::testing::SizeIs;\n\n// Local less verbose helper\nstd::vector<const CordzHandle*> DeleteQueue() {\n  return CordzHandle::DiagnosticsGetDeleteQueue();\n}\n\nstruct CordzHandleDeleteTracker : public CordzHandle {\n  bool* deleted;\n  explicit CordzHandleDeleteTracker(bool* deleted) : deleted(deleted) {}\n  ~CordzHandleDeleteTracker() override { *deleted = true; }\n};\n\nTEST(CordzHandleTest, DeleteQueueIsEmpty) {\n  EXPECT_THAT(DeleteQueue(), SizeIs(0));\n}\n\nTEST(CordzHandleTest, CordzHandleCreateDelete) {\n  bool deleted = false;\n  auto* handle = new CordzHandleDeleteTracker(&deleted);\n  EXPECT_FALSE(handle->is_snapshot());\n  EXPECT_TRUE(handle->SafeToDelete());\n  EXPECT_THAT(DeleteQueue(), SizeIs(0));\n\n  CordzHandle::Delete(handle);\n  EXPECT_THAT(DeleteQueue(), SizeIs(0));\n  EXPECT_TRUE(deleted);\n}\n\nTEST(CordzHandleTest, CordzSnapshotCreateDelete) {\n  auto* snapshot = new CordzSnapshot();\n  EXPECT_TRUE(snapshot->is_snapshot());\n  EXPECT_TRUE(snapshot->SafeToDelete());\n  EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot));\n  delete snapshot;\n  EXPECT_THAT(DeleteQueue(), SizeIs(0));\n}\n\nTEST(CordzHandleTest, CordzHandleCreateDeleteWithSnapshot) {\n  bool deleted = false;\n  auto* snapshot = new CordzSnapshot();\n  auto* handle = new CordzHandleDeleteTracker(&deleted);\n  EXPECT_FALSE(handle->SafeToDelete());\n\n  CordzHandle::Delete(handle);\n  EXPECT_THAT(DeleteQueue(), ElementsAre(handle, snapshot));\n  EXPECT_FALSE(deleted);\n  EXPECT_FALSE(handle->SafeToDelete());\n\n  delete snapshot;\n  EXPECT_THAT(DeleteQueue(), SizeIs(0));\n  EXPECT_TRUE(deleted);\n}\n\nTEST(CordzHandleTest, MultiSnapshot) {\n  bool deleted[3] = {false, false, false};\n\n  CordzSnapshot* snapshot[3];\n  CordzHandleDeleteTracker* handle[3];\n  for (int i = 0; i < 3; ++i) {\n    snapshot[i] = new CordzSnapshot();\n    handle[i] = new CordzHandleDeleteTracker(&deleted[i]);\n    CordzHandle::Delete(handle[i]);\n  }\n\n  EXPECT_THAT(DeleteQueue(), ElementsAre(handle[2], snapshot[2], handle[1],\n                                         snapshot[1], handle[0], snapshot[0]));\n  EXPECT_THAT(deleted, ElementsAre(false, false, false));\n\n  delete snapshot[1];\n  EXPECT_THAT(DeleteQueue(), ElementsAre(handle[2], snapshot[2], handle[1],\n                                         handle[0], snapshot[0]));\n  EXPECT_THAT(deleted, ElementsAre(false, false, false));\n\n  delete snapshot[0];\n  EXPECT_THAT(DeleteQueue(), ElementsAre(handle[2], snapshot[2]));\n  EXPECT_THAT(deleted, ElementsAre(true, true, false));\n\n  delete snapshot[2];\n  EXPECT_THAT(DeleteQueue(), SizeIs(0));\n  EXPECT_THAT(deleted, ElementsAre(true, true, deleted));\n}\n\nTEST(CordzHandleTest, DiagnosticsHandleIsSafeToInspect) {\n  CordzSnapshot snapshot1;\n  EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(nullptr));\n\n  auto* handle1 = new CordzHandle();\n  EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));\n\n  CordzHandle::Delete(handle1);\n  EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));\n\n  CordzSnapshot snapshot2;\n  auto* handle2 = new CordzHandle();\n  EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));\n  EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle2));\n  EXPECT_FALSE(snapshot2.DiagnosticsHandleIsSafeToInspect(handle1));\n  EXPECT_TRUE(snapshot2.DiagnosticsHandleIsSafeToInspect(handle2));\n\n  CordzHandle::Delete(handle2);\n  EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));\n}\n\nTEST(CordzHandleTest, DiagnosticsGetSafeToInspectDeletedHandles) {\n  EXPECT_THAT(DeleteQueue(), IsEmpty());\n\n  auto* handle = new CordzHandle();\n  auto* snapshot1 = new CordzSnapshot();\n\n  // snapshot1 should be able to see handle.\n  EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot1));\n  EXPECT_TRUE(snapshot1->DiagnosticsHandleIsSafeToInspect(handle));\n  EXPECT_THAT(snapshot1->DiagnosticsGetSafeToInspectDeletedHandles(),\n              IsEmpty());\n\n  // This handle will be safe to inspect as long as snapshot1 is alive. However,\n  // since only snapshot1 can prove that it's alive, it will be hidden from\n  // snapshot2.\n  CordzHandle::Delete(handle);\n\n  // This snapshot shouldn't be able to see handle because handle was already\n  // sent to Delete.\n  auto* snapshot2 = new CordzSnapshot();\n\n  // DeleteQueue elements are LIFO order.\n  EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot2, handle, snapshot1));\n\n  EXPECT_TRUE(snapshot1->DiagnosticsHandleIsSafeToInspect(handle));\n  EXPECT_FALSE(snapshot2->DiagnosticsHandleIsSafeToInspect(handle));\n\n  EXPECT_THAT(snapshot1->DiagnosticsGetSafeToInspectDeletedHandles(),\n              ElementsAre(handle));\n  EXPECT_THAT(snapshot2->DiagnosticsGetSafeToInspectDeletedHandles(),\n              IsEmpty());\n\n  CordzHandle::Delete(snapshot1);\n  EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot2));\n\n  CordzHandle::Delete(snapshot2);\n  EXPECT_THAT(DeleteQueue(), IsEmpty());\n}\n\n// Create and delete CordzHandle and CordzSnapshot objects in multiple threads\n// so that tsan has some time to chew on it and look for memory problems.\nTEST(CordzHandleTest, MultiThreaded) {\n  Notification stop;\n  static constexpr int kNumThreads = 4;\n  // Keep the number of handles relatively small so that the test will naturally\n  // transition to an empty delete queue during the test. If there are, say, 100\n  // handles, that will virtually never happen. With 10 handles and around 50k\n  // iterations in each of 4 threads, the delete queue appears to become empty\n  // around 200 times.\n  static constexpr int kNumHandles = 10;\n\n  // Each thread is going to pick a random index and atomically swap its\n  // CordzHandle with one in handles. This way, each thread can avoid\n  // manipulating a CordzHandle that might be operated upon in another thread.\n  std::vector<std::atomic<CordzHandle*>> handles(kNumHandles);\n\n  // global bool which is set when any thread did get some 'safe to inspect'\n  // handles. On some platforms and OSS tests, we might risk that some pool\n  // threads are starved, stalled, or just got a few unlikely random 'handle'\n  // coin tosses, so we satisfy this test with simply observing 'some' thread\n  // did something meaningful, which should minimize the potential for flakes.\n  std::atomic<bool> found_safe_to_inspect(false);\n\n  {\n    absl::synchronization_internal::ThreadPool pool(kNumThreads);\n    for (int i = 0; i < kNumThreads; ++i) {\n      pool.Schedule([&stop, &handles, &found_safe_to_inspect]() {\n        std::minstd_rand gen;\n        std::uniform_int_distribution<int> dist_type(0, 2);\n        std::uniform_int_distribution<int> dist_handle(0, kNumHandles - 1);\n\n        while (!stop.HasBeenNotified()) {\n          CordzHandle* handle;\n          switch (dist_type(gen)) {\n            case 0:\n              handle = new CordzHandle();\n              break;\n            case 1:\n              handle = new CordzSnapshot();\n              break;\n            default:\n              handle = nullptr;\n              break;\n          }\n          CordzHandle* old_handle = handles[dist_handle(gen)].exchange(handle);\n          if (old_handle != nullptr) {\n            std::vector<const CordzHandle*> safe_to_inspect =\n                old_handle->DiagnosticsGetSafeToInspectDeletedHandles();\n            for (const CordzHandle* handle : safe_to_inspect) {\n              // We're in a tight loop, so don't generate too many error\n              // messages.\n              ASSERT_FALSE(handle->is_snapshot());\n            }\n            if (!safe_to_inspect.empty()) {\n              found_safe_to_inspect.store(true);\n            }\n            CordzHandle::Delete(old_handle);\n          }\n        }\n\n        // Have each thread attempt to clean up everything. Some thread will be\n        // the last to reach this cleanup code, and it will be guaranteed to\n        // clean up everything because nothing remains to create new handles.\n        for (auto& h : handles) {\n          if (CordzHandle* handle = h.exchange(nullptr)) {\n            CordzHandle::Delete(handle);\n          }\n        }\n      });\n    }\n\n    // The threads will hammer away.  Give it a little bit of time for tsan to\n    // spot errors.\n    absl::SleepFor(absl::Seconds(3));\n    stop.Notify();\n  }\n\n  // Confirm that the test did *something*. This check will be satisfied as\n  // long as any thread has deleted a CordzSnapshot object and a non-snapshot\n  // CordzHandle was deleted after the CordzSnapshot was created.\n  // See also comments on `found_safe_to_inspect`\n  EXPECT_TRUE(found_safe_to_inspect.load());\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_info.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_info.h\"\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n#include \"absl/strings/internal/cordz_handle.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nnamespace {\n\n// CordRepAnalyzer performs the analysis of a cord.\n//\n// It computes absolute node counts and total memory usage, and an 'estimated\n// fair share memory usage` statistic.\n// Conceptually, it divides the 'memory usage' at each location in the 'cord\n// graph' by the cumulative reference count of that location. The cumulative\n// reference count is the factored total of all edges leading into that node.\n//\n// The top level node is treated specially: we assume the current thread\n// (typically called from the CordzHandler) to hold a reference purely to\n// perform a safe analysis, and not being part of the application. So we\n// subtract 1 from the reference count of the top node to compute the\n// 'application fair share' excluding the reference of the current thread.\n//\n// An example of fair sharing, and why we multiply reference counts:\n// Assume we have 2 CordReps, both being a Substring referencing a Flat:\n//   CordSubstring A (refcount = 5) --> child Flat C (refcount = 2)\n//   CordSubstring B (refcount = 9) --> child Flat C (refcount = 2)\n//\n// Flat C has 2 incoming edges from the 2 substrings (refcount = 2) and is not\n// referenced directly anywhere else. Translated into a 'fair share', we then\n// attribute 50% of the memory (memory / refcount = 2) to each incoming edge.\n// Rep A has a refcount of 5, so we attribute each incoming edge 1 / 5th of the\n// memory cost below it, i.e.: the fair share of Rep A of the memory used by C\n// is then 'memory C / (refcount C * refcount A) + (memory A / refcount A)'.\n// It is also easy to see how all incoming edges add up to 100%.\nclass CordRepAnalyzer {\n public:\n  // Creates an analyzer instance binding to `statistics`.\n  explicit CordRepAnalyzer(CordzStatistics& statistics)\n      : statistics_(statistics) {}\n\n  // Analyzes the memory statistics and node counts for the provided `rep`, and\n  // adds the results to `statistics`. Note that node counts and memory sizes\n  // are not initialized, computed values are added to any existing values.\n  void AnalyzeCordRep(const CordRep* rep) {\n    ABSL_ASSERT(rep != nullptr);\n\n    // Process all linear nodes.\n    // As per the class comments, use refcout - 1 on the top level node, as the\n    // top level node is assumed to be referenced only for analysis purposes.\n    size_t refcount = rep->refcount.Get();\n    RepRef repref{rep, (refcount > 1) ? refcount - 1 : 1};\n\n    // Process the top level CRC node, if present.\n    if (repref.tag() == CRC) {\n      statistics_.node_count++;\n      statistics_.node_counts.crc++;\n      memory_usage_.Add(sizeof(CordRepCrc), repref.refcount);\n      repref = repref.Child(repref.rep->crc()->child);\n    }\n\n    // Process all top level linear nodes (substrings and flats).\n    repref = CountLinearReps(repref, memory_usage_);\n\n    switch (repref.tag()) {\n      case CordRepKind::BTREE:\n        AnalyzeBtree(repref);\n        break;\n      default:\n        // We should have a btree node if not null.\n        ABSL_ASSERT(repref.tag() == CordRepKind::UNUSED_0);\n        break;\n    }\n\n    // Adds values to output\n    statistics_.estimated_memory_usage += memory_usage_.total;\n    statistics_.estimated_fair_share_memory_usage +=\n        static_cast<size_t>(memory_usage_.fair_share);\n  }\n\n private:\n  // RepRef identifies a CordRep* inside the Cord tree with its cumulative\n  // refcount including itself. For example, a tree consisting of a substring\n  // with a refcount of 3 and a child flat with a refcount of 4 will have RepRef\n  // refcounts of 3 and 12 respectively.\n  struct RepRef {\n    const CordRep* rep;\n    size_t refcount;\n\n    // Returns a 'child' RepRef which contains the cumulative reference count\n    // of this instance multiplied by the child's reference count. Returns a\n    // nullptr RepRef value with a refcount of 0 if `child` is nullptr.\n    RepRef Child(const CordRep* child) const {\n      if (child == nullptr) return RepRef{nullptr, 0};\n      return RepRef{child, refcount * child->refcount.Get()};\n    }\n\n    // Returns the tag of this rep, or UNUSED_0 if this instance is null\n    constexpr CordRepKind tag() const {\n      ABSL_ASSERT(rep == nullptr || rep->tag != CordRepKind::UNUSED_0);\n      return rep ? static_cast<CordRepKind>(rep->tag) : CordRepKind::UNUSED_0;\n    }\n  };\n\n  // Memory usage values\n  struct MemoryUsage {\n    size_t total = 0;\n    double fair_share = 0.0;\n\n    // Adds 'size` memory usage to this class, with a cumulative (recursive)\n    // reference count of `refcount`\n    void Add(size_t size, size_t refcount) {\n      total += size;\n      fair_share += static_cast<double>(size) / refcount;\n    }\n  };\n\n  // Counts a flat of the provide allocated size\n  void CountFlat(size_t size) {\n    statistics_.node_count++;\n    statistics_.node_counts.flat++;\n    if (size <= 64) {\n      statistics_.node_counts.flat_64++;\n    } else if (size <= 128) {\n      statistics_.node_counts.flat_128++;\n    } else if (size <= 256) {\n      statistics_.node_counts.flat_256++;\n    } else if (size <= 512) {\n      statistics_.node_counts.flat_512++;\n    } else if (size <= 1024) {\n      statistics_.node_counts.flat_1k++;\n    }\n  }\n\n  // Processes 'linear' reps (substring, flat, external) not requiring iteration\n  // or recursion. Returns RefRep{null} if all reps were processed, else returns\n  // the top-most non-linear concat or ring cordrep.\n  // Node counts are updated into `statistics_`, memory usage is update into\n  // `memory_usage`, which typically references `memory_usage_` except for ring\n  // buffers where we count children unrounded.\n  RepRef CountLinearReps(RepRef rep, MemoryUsage& memory_usage) {\n    // Consume all substrings\n    while (rep.tag() == SUBSTRING) {\n      statistics_.node_count++;\n      statistics_.node_counts.substring++;\n      memory_usage.Add(sizeof(CordRepSubstring), rep.refcount);\n      rep = rep.Child(rep.rep->substring()->child);\n    }\n\n    // Consume possible FLAT\n    if (rep.tag() >= FLAT) {\n      size_t size = rep.rep->flat()->AllocatedSize();\n      CountFlat(size);\n      memory_usage.Add(size, rep.refcount);\n      return RepRef{nullptr, 0};\n    }\n\n    // Consume possible external\n    if (rep.tag() == EXTERNAL) {\n      statistics_.node_count++;\n      statistics_.node_counts.external++;\n      size_t size = rep.rep->length + sizeof(CordRepExternalImpl<intptr_t>);\n      memory_usage.Add(size, rep.refcount);\n      return RepRef{nullptr, 0};\n    }\n\n    return rep;\n  }\n\n  // Analyzes the provided btree.\n  void AnalyzeBtree(RepRef rep) {\n    statistics_.node_count++;\n    statistics_.node_counts.btree++;\n    memory_usage_.Add(sizeof(CordRepBtree), rep.refcount);\n    const CordRepBtree* tree = rep.rep->btree();\n    if (tree->height() > 0) {\n      for (CordRep* edge : tree->Edges()) {\n        AnalyzeBtree(rep.Child(edge));\n      }\n    } else {\n      for (CordRep* edge : tree->Edges()) {\n        CountLinearReps(rep.Child(edge), memory_usage_);\n      }\n    }\n  }\n\n  CordzStatistics& statistics_;\n  MemoryUsage memory_usage_;\n};\n\n}  // namespace\n\nCordzInfo::List* CordzInfo::GlobalList() {\n  static absl::NoDestructor<CordzInfo::List> list;\n  return list.get();\n}\n\nCordzInfo* CordzInfo::Head(const CordzSnapshot& snapshot) {\n  ABSL_ASSERT(snapshot.is_snapshot());\n\n  // We obtain the lock here as we must synchronize the first call into the list\n  // with any concurrent 'Untrack()` operation to avoid any read in the list to\n  // reorder before the observation of the thread 'untracking a cord' of the\n  // delete queue being empty or not. After this all next observations are safe\n  // as we have established all subsequent untracks will be queued for delete.\n  // We do enforce in DEBUG builds that the 'head' value is present in the\n  // delete queue: ODR violations may lead to 'snapshot' and 'global_list'\n  // being in different libraries / modules.\n  auto global_list = GlobalList();\n  absl::MutexLock l(global_list->mutex);\n  ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(global_list->head));\n  return global_list->head;\n}\n\nCordzInfo* CordzInfo::Next(const CordzSnapshot& snapshot) const {\n  ABSL_ASSERT(snapshot.is_snapshot());\n\n  // We do not need a lock here. See also comments in Head().\n  CordzInfo* next = ci_next_.load(std::memory_order_acquire);\n  ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(this));\n  ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(next));\n  return next;\n}\n\nvoid CordzInfo::TrackCord(InlineData& cord, MethodIdentifier method,\n                          int64_t sampling_stride) {\n  assert(cord.is_tree());\n  assert(!cord.is_profiled());\n  CordzInfo* cordz_info =\n      new CordzInfo(cord.as_tree(), nullptr, method, sampling_stride);\n  cord.set_cordz_info(cordz_info);\n  cordz_info->Track();\n}\n\nvoid CordzInfo::TrackCord(InlineData& cord, const InlineData& src,\n                          MethodIdentifier method) {\n  assert(cord.is_tree());\n  assert(src.is_tree());\n\n  // Unsample current as we the current cord is being replaced with 'src',\n  // so any method history is no longer relevant.\n  CordzInfo* cordz_info = cord.cordz_info();\n  if (cordz_info != nullptr) cordz_info->Untrack();\n\n  // Start new cord sample\n  cordz_info = new CordzInfo(cord.as_tree(), src.cordz_info(), method,\n                             src.cordz_info()->sampling_stride());\n  cord.set_cordz_info(cordz_info);\n  cordz_info->Track();\n}\n\nvoid CordzInfo::MaybeTrackCordImpl(InlineData& cord, const InlineData& src,\n                                   MethodIdentifier method) {\n  if (src.is_profiled()) {\n    TrackCord(cord, src, method);\n  } else if (cord.is_profiled()) {\n    cord.cordz_info()->Untrack();\n    cord.clear_cordz_info();\n  }\n}\n\nCordzInfo::MethodIdentifier CordzInfo::GetParentMethod(const CordzInfo* src) {\n  if (src == nullptr) return MethodIdentifier::kUnknown;\n  return src->parent_method_ != MethodIdentifier::kUnknown ? src->parent_method_\n                                                           : src->method_;\n}\n\nsize_t CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {\n  assert(stack);\n  if (src == nullptr) return 0;\n  if (src->parent_stack_depth_) {\n    memcpy(stack, src->parent_stack_, src->parent_stack_depth_ * sizeof(void*));\n    return src->parent_stack_depth_;\n  }\n  memcpy(stack, src->stack_, src->stack_depth_ * sizeof(void*));\n  return src->stack_depth_;\n}\n\nCordzInfo::CordzInfo(CordRep* rep, const CordzInfo* src,\n                     MethodIdentifier method, int64_t sampling_stride)\n    : rep_(rep),\n      stack_depth_(\n          static_cast<size_t>(absl::GetStackTrace(stack_,\n                                                  /*max_depth=*/kMaxStackDepth,\n                                                  /*skip_count=*/1))),\n      parent_stack_depth_(FillParentStack(src, parent_stack_)),\n      method_(method),\n      parent_method_(GetParentMethod(src)),\n      create_time_(absl::Now()),\n      sampling_stride_(sampling_stride) {\n  update_tracker_.LossyAdd(method);\n  if (src) {\n    // Copy parent counters.\n    update_tracker_.LossyAdd(src->update_tracker_);\n  }\n}\n\nCordzInfo::~CordzInfo() {\n  // `rep_` is potentially kept alive if CordzInfo is included\n  // in a collection snapshot (which should be rare).\n  if (ABSL_PREDICT_FALSE(rep_)) {\n    CordRep::Unref(rep_);\n  }\n}\n\nvoid CordzInfo::Track() {\n  absl::MutexLock l(list_->mutex);\n  CordzInfo* const head = list_->head;\n  if (head != nullptr) {\n    head->ci_prev_.store(this, std::memory_order_release);\n  }\n  ci_next_.store(head, std::memory_order_release);\n  list_->head = this;\n}\n\nvoid CordzInfo::Untrack() {\n  ODRCheck();\n  {\n    absl::MutexLock l(list_->mutex);\n\n    CordzInfo* const head = list_->head;\n    CordzInfo* const next = ci_next_.load(std::memory_order_acquire);\n    CordzInfo* const prev = ci_prev_.load(std::memory_order_acquire);\n\n    if (next) {\n      ABSL_ASSERT(next->ci_prev_.load(std::memory_order_acquire) == this);\n      next->ci_prev_.store(prev, std::memory_order_release);\n    }\n    if (prev) {\n      ABSL_ASSERT(head != this);\n      ABSL_ASSERT(prev->ci_next_.load(std::memory_order_acquire) == this);\n      prev->ci_next_.store(next, std::memory_order_release);\n    } else {\n      ABSL_ASSERT(head == this);\n      list_->head = next;\n    }\n  }\n\n  // We can no longer be discovered: perform a fast path check if we are not\n  // listed on any delete queue, so we can directly delete this instance.\n  if (SafeToDelete()) {\n    UnsafeSetCordRep(nullptr);\n    delete this;\n    return;\n  }\n\n  // We are likely part of a snapshot, extend the life of the CordRep\n  {\n    absl::MutexLock lock(mutex_);\n    if (rep_) CordRep::Ref(rep_);\n  }\n  CordzHandle::Delete(this);\n}\n\nvoid CordzInfo::Lock(MethodIdentifier method)\n    ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex_) {\n  mutex_.lock();\n  update_tracker_.LossyAdd(method);\n  assert(rep_);\n}\n\nvoid CordzInfo::Unlock() ABSL_UNLOCK_FUNCTION(mutex_) {\n  bool tracked = rep_ != nullptr;\n  mutex_.unlock();\n  if (!tracked) {\n    Untrack();\n  }\n}\n\nabsl::Span<void* const> CordzInfo::GetStack() const {\n  return absl::MakeConstSpan(stack_, stack_depth_);\n}\n\nabsl::Span<void* const> CordzInfo::GetParentStack() const {\n  return absl::MakeConstSpan(parent_stack_, parent_stack_depth_);\n}\n\nCordzStatistics CordzInfo::GetCordzStatistics() const {\n  CordzStatistics stats;\n  stats.method = method_;\n  stats.parent_method = parent_method_;\n  stats.update_tracker = update_tracker_;\n  if (CordRep* rep = RefCordRep()) {\n    stats.size = rep->length;\n    CordRepAnalyzer analyzer(stats);\n    analyzer.AnalyzeCordRep(rep);\n    CordRep::Unref(rep);\n  }\n  return stats;\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_info.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_\n\n#include <atomic>\n#include <cstdint>\n#include <functional>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cordz_functions.h\"\n#include \"absl/strings/internal/cordz_handle.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordzInfo tracks a profiled Cord. Each of these objects can be in two places.\n// If a Cord is alive, the CordzInfo will be in the global_cordz_infos map, and\n// can also be retrieved via the linked list starting with\n// global_cordz_infos_head and continued via the cordz_info_next() method. When\n// a Cord has reached the end of its lifespan, the CordzInfo object will be\n// migrated out of the global_cordz_infos list and the global_cordz_infos_map,\n// and will either be deleted or appended to the global_delete_queue. If it is\n// placed on the global_delete_queue, the CordzInfo object will be cleaned in\n// the destructor of a CordzSampleToken object.\nclass ABSL_LOCKABLE CordzInfo : public CordzHandle {\n public:\n  using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;\n\n  // TrackCord creates a CordzInfo instance which tracks important metrics of\n  // a sampled cord, and stores the created CordzInfo instance into `cord'. All\n  // CordzInfo instances are placed in a global list which is used to discover\n  // and snapshot all actively tracked cords. Callers are responsible for\n  // calling UntrackCord() before the tracked Cord instance is deleted, or to\n  // stop tracking the sampled Cord. Callers are also responsible for guarding\n  // changes to the 'tree' value of a Cord (InlineData.tree) through the Lock()\n  // and Unlock() calls. Any change resulting in a new tree value for the cord\n  // requires a call to SetCordRep() before the old tree has been unreffed\n  // and/or deleted. `method` identifies the Cord public API method initiating\n  // the cord to be sampled.\n  // Requires `cord` to hold a tree, and `cord.cordz_info()` to be null.\n  static void TrackCord(InlineData& cord, MethodIdentifier method,\n                        int64_t sampling_stride);\n\n  // Identical to TrackCord(), except that this function fills the\n  // `parent_stack` and `parent_method` properties of the returned CordzInfo\n  // instance from the provided `src` instance if `src` is sampled.\n  // This function should be used for sampling 'copy constructed' and 'copy\n  // assigned' cords. This function allows 'cord` to be already sampled, in\n  // which case the CordzInfo will be newly created from `src`.\n  static void TrackCord(InlineData& cord, const InlineData& src,\n                        MethodIdentifier method);\n\n  // Maybe sample the cord identified by 'cord' for method 'method'.\n  // Uses `cordz_should_profile` to randomly pick cords to be sampled, and if\n  // so, invokes `TrackCord` to start sampling `cord`.\n  static void MaybeTrackCord(InlineData& cord, MethodIdentifier method);\n\n  // Maybe sample the cord identified by 'cord' for method 'method'.\n  // `src` identifies a 'parent' cord which is assigned to `cord`, typically the\n  // input cord for a copy constructor, or an assign method such as `operator=`\n  // `cord` will be sampled if (and only if) `src` is sampled.\n  // If `cord` is currently being sampled and `src` is not being sampled, then\n  // this function will stop sampling the cord and reset the cord's cordz_info.\n  //\n  // Previously this function defined that `cord` will be sampled if either\n  // `src` is sampled, or if `cord` is randomly picked for sampling. However,\n  // this can cause issues, as there may be paths where some cord is assigned an\n  // indirect copy of it's own value. As such a 'string of copies' would then\n  // remain sampled (`src.is_profiled`), then assigning such a cord back to\n  // 'itself' creates a cycle where the cord will converge to 'always sampled`.\n  //\n  // For example:\n  //\n  //   Cord x;\n  //   for (...) {\n  //     // Copy ctor --> y.is_profiled := x.is_profiled | random(...)\n  //     Cord y = x;\n  //     ...\n  //     // Assign x = y --> x.is_profiled = y.is_profiled | random(...)\n  //     //              ==> x.is_profiled |= random(...)\n  //     //              ==> x converges to 'always profiled'\n  //     x = y;\n  //   }\n  static void MaybeTrackCord(InlineData& cord, const InlineData& src,\n                             MethodIdentifier method);\n\n  // Stops tracking changes for a sampled cord, and deletes the provided info.\n  // This function must be called before the sampled cord instance is deleted,\n  // and before the root cordrep of the sampled cord is unreffed.\n  // This function may extend the lifetime of the cordrep in cases where the\n  // CordInfo instance is being held by a concurrent collection thread.\n  void Untrack();\n\n  // Invokes UntrackCord() on `info` if `info` is not null.\n  static void MaybeUntrackCord(CordzInfo* info);\n\n  CordzInfo() = delete;\n  CordzInfo(const CordzInfo&) = delete;\n  CordzInfo& operator=(const CordzInfo&) = delete;\n\n  // Retrieves the oldest existing CordzInfo.\n  static CordzInfo* Head(const CordzSnapshot& snapshot);\n\n  // Retrieves the next oldest existing CordzInfo older than 'this' instance.\n  CordzInfo* Next(const CordzSnapshot& snapshot) const;\n\n  // Locks this instance for the update identified by `method`.\n  // Increases the count for `method` in `update_tracker`.\n  void Lock(MethodIdentifier method) ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex_);\n\n  // Unlocks this instance. If the contained `rep` has been set to null\n  // indicating the Cord has been cleared or is otherwise no longer sampled,\n  // then this method will delete this CordzInfo instance.\n  void Unlock() ABSL_UNLOCK_FUNCTION(mutex_);\n\n  // Asserts that this CordzInfo instance is locked.\n  void AssertHeld() ABSL_ASSERT_EXCLUSIVE_LOCK(mutex_);\n\n  // Updates the `rep` property of this instance. This methods is invoked by\n  // Cord logic each time the root node of a sampled Cord changes, and before\n  // the old root reference count is deleted. This guarantees that collection\n  // code can always safely take a reference on the tracked cord.\n  // Requires a lock to be held through the `Lock()` method.\n  // TODO(b/117940323): annotate with ABSL_EXCLUSIVE_LOCKS_REQUIRED once all\n  // Cord code is in a state where this can be proven true by the compiler.\n  void SetCordRep(CordRep* rep);\n\n  // Returns the current `rep` property of this instance with a reference\n  // added, or null if this instance represents a cord that has since been\n  // deleted or untracked.\n  CordRep* RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_);\n\n  // Returns the current value of `rep_` for testing purposes only.\n  CordRep* GetCordRepForTesting() const ABSL_NO_THREAD_SAFETY_ANALYSIS {\n    return rep_;\n  }\n\n  // Sets the current value of `rep_` for testing purposes only.\n  void SetCordRepForTesting(CordRep* rep) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n    rep_ = rep;\n  }\n\n  // Returns the stack trace for where the cord was first sampled. Cords are\n  // potentially sampled when they promote from an inlined cord to a tree or\n  // ring representation, which is not necessarily the location where the cord\n  // was first created. Some cords are created as inlined cords, and only as\n  // data is added do they become a non-inlined cord. However, typically the\n  // location represents reasonably well where the cord is 'created'.\n  absl::Span<void* const> GetStack() const;\n\n  // Returns the stack trace for a sampled cord's 'parent stack trace'. This\n  // value may be set if the cord is sampled (promoted) after being created\n  // from, or being assigned the value of an existing (sampled) cord.\n  absl::Span<void* const> GetParentStack() const;\n\n  // Retrieves the CordzStatistics associated with this Cord. The statistics\n  // are only updated when a Cord goes through a mutation, such as an Append\n  // or RemovePrefix.\n  CordzStatistics GetCordzStatistics() const;\n\n  int64_t sampling_stride() const { return sampling_stride_; }\n\n private:\n  // Global cordz info list. CordzInfo stores a pointer to the global list\n  // instance to harden against ODR violations.\n  struct List {\n    absl::Mutex mutex;\n    CordzInfo* head ABSL_GUARDED_BY(mutex){nullptr};\n  };\n\n  static List* GlobalList();\n\n  static constexpr size_t kMaxStackDepth = 64;\n\n  explicit CordzInfo(CordRep* rep, const CordzInfo* src,\n                     MethodIdentifier method, int64_t weight);\n  ~CordzInfo() override;\n\n  // Sets `rep_` without holding a lock.\n  void UnsafeSetCordRep(CordRep* rep) ABSL_NO_THREAD_SAFETY_ANALYSIS;\n\n  void Track();\n\n  // Returns the parent method from `src`, which is either `parent_method_` or\n  // `method_` depending on `parent_method_` being kUnknown.\n  // Returns kUnknown if `src` is null.\n  static MethodIdentifier GetParentMethod(const CordzInfo* src);\n\n  // Fills the provided stack from `src`, copying either `parent_stack_` or\n  // `stack_` depending on `parent_stack_` being empty, returning the size of\n  // the parent stack.\n  // Returns 0 if `src` is null.\n  static size_t FillParentStack(const CordzInfo* src, void** stack);\n\n  void ODRCheck() const {\n#ifndef NDEBUG\n    ABSL_RAW_CHECK(list_ == GlobalList(), \"ODR violation in Cord\");\n#endif\n  }\n\n  // Non-inlined implementation of `MaybeTrackCord`, which is executed if\n  // either `src` is sampled or `cord` is sampled, and either untracks or\n  // tracks `cord` as documented per `MaybeTrackCord`.\n  static void MaybeTrackCordImpl(InlineData& cord, const InlineData& src,\n                                 MethodIdentifier method);\n\n  List* const list_ = GlobalList();\n\n  // ci_prev_ and ci_next_ require the global list mutex to be held.\n  // Unfortunately we can't use thread annotations such that the thread safety\n  // analysis understands that list_ and GlobalList() are one and the same.\n  std::atomic<CordzInfo*> ci_prev_{nullptr};\n  std::atomic<CordzInfo*> ci_next_{nullptr};\n\n  mutable absl::Mutex mutex_;\n  CordRep* rep_ ABSL_GUARDED_BY(mutex_);\n\n  void* stack_[kMaxStackDepth];\n  void* parent_stack_[kMaxStackDepth];\n  const size_t stack_depth_;\n  const size_t parent_stack_depth_;\n  const MethodIdentifier method_;\n  const MethodIdentifier parent_method_;\n  CordzUpdateTracker update_tracker_;\n  const absl::Time create_time_;\n  const int64_t sampling_stride_;\n};\n\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeTrackCord(\n    InlineData& cord, MethodIdentifier method) {\n  auto stride = cordz_should_profile();\n  if (ABSL_PREDICT_FALSE(stride > 0)) {\n    TrackCord(cord, method, stride);\n  }\n}\n\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeTrackCord(\n    InlineData& cord, const InlineData& src, MethodIdentifier method) {\n  if (ABSL_PREDICT_FALSE(InlineData::is_either_profiled(cord, src))) {\n    MaybeTrackCordImpl(cord, src, method);\n  }\n}\n\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeUntrackCord(\n    CordzInfo* info) {\n  if (ABSL_PREDICT_FALSE(info)) {\n    info->Untrack();\n  }\n}\n\ninline void CordzInfo::AssertHeld() ABSL_ASSERT_EXCLUSIVE_LOCK(mutex_) {\n#ifndef NDEBUG\n  mutex_.AssertHeld();\n#endif\n}\n\ninline void CordzInfo::SetCordRep(CordRep* rep) {\n  AssertHeld();\n  rep_ = rep;\n}\n\ninline void CordzInfo::UnsafeSetCordRep(CordRep* rep) { rep_ = rep; }\n\ninline CordRep* CordzInfo::RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_) {\n  MutexLock lock(mutex_);\n  return rep_ ? CordRep::Ref(rep_) : nullptr;\n}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_info_statistics_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <iostream>\n#include <random>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/crc/internal/crc_cord_state.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cord_rep_btree.h\"\n#include \"absl/strings/internal/cord_rep_crc.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/strings/internal/cordz_sample_token.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_scope.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/notification.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// Do not print statistics contents, the matcher prints them as needed.\ninline void PrintTo(const CordzStatistics& stats, std::ostream* s) {\n  if (s) *s << \"CordzStatistics{...}\";\n}\n\nnamespace {\n\nusing ::testing::Ge;\n\n// Creates a flat of the specified allocated size\nCordRepFlat* Flat(size_t size) {\n  // Round up to a tag size, as we are going to poke an exact tag size back into\n  // the allocated flat. 'size returning allocators' could grant us more than we\n  // wanted, but we are ok to poke the 'requested' size in the tag, even in the\n  // presence of sized deletes, so we need to make sure the size rounds\n  // perfectly to a tag value.\n  assert(size >= kMinFlatSize);\n  size = RoundUpForTag(size);\n  CordRepFlat* flat = CordRepFlat::New(size - kFlatOverhead);\n  flat->tag = AllocatedSizeToTag(size);\n  flat->length = size - kFlatOverhead;\n  return flat;\n}\n\n// Creates an external of the specified length\nCordRepExternal* External(size_t length = 512) {\n  return static_cast<CordRepExternal*>(\n      NewExternalRep(absl::string_view(\"\", length), [](absl::string_view) {}));\n}\n\n// Creates a substring on the provided rep of length - 1\nCordRepSubstring* Substring(CordRep* rep) {\n  auto* substring = new CordRepSubstring;\n  substring->length = rep->length - 1;\n  substring->tag = SUBSTRING;\n  substring->child = rep;\n  return substring;\n}\n\n// Reference count helper\nstruct RefHelper {\n  std::vector<CordRep*> refs;\n\n  ~RefHelper() {\n    for (CordRep* rep : refs) {\n      CordRep::Unref(rep);\n    }\n  }\n\n  // Invokes CordRep::Unref() on `rep` when this instance is destroyed.\n  template <typename T>\n  T* NeedsUnref(T* rep) {\n    refs.push_back(rep);\n    return rep;\n  }\n\n  // Adds `n` reference counts to `rep` which will be unreffed when this\n  // instance is destroyed.\n  template <typename T>\n  T* Ref(T* rep, size_t n = 1) {\n    while (n--) {\n      NeedsUnref(CordRep::Ref(rep));\n    }\n    return rep;\n  }\n};\n\n// Sizeof helper. Returns the allocated size of `p`, excluding any child\n// elements for substring, concat and ring cord reps.\ntemplate <typename T>\nsize_t SizeOf(const T* rep) {\n  return sizeof(T);\n}\n\ntemplate <>\nsize_t SizeOf(const CordRepFlat* rep) {\n  return rep->AllocatedSize();\n}\n\ntemplate <>\nsize_t SizeOf(const CordRepExternal* rep) {\n  // See cord.cc\n  return sizeof(CordRepExternalImpl<intptr_t>) + rep->length;\n}\n\n// Computes fair share memory used in a naive 'we dare to recurse' way.\ndouble FairShareImpl(CordRep* rep, size_t ref) {\n  double self = 0.0, children = 0.0;\n  ref *= rep->refcount.Get();\n  if (rep->tag >= FLAT) {\n    self = SizeOf(rep->flat());\n  } else if (rep->tag == EXTERNAL) {\n    self = SizeOf(rep->external());\n  } else if (rep->tag == SUBSTRING) {\n    self = SizeOf(rep->substring());\n    children = FairShareImpl(rep->substring()->child, ref);\n  } else if (rep->tag == BTREE) {\n    self = SizeOf(rep->btree());\n    for (CordRep*edge : rep->btree()->Edges()) {\n      children += FairShareImpl(edge, ref);\n    }\n  } else {\n    assert(false);\n  }\n  return self / ref + children;\n}\n\n// Returns the fair share memory size from `ShareFhareImpl()` as a size_t.\nsize_t FairShare(CordRep* rep, size_t ref = 1) {\n  return static_cast<size_t>(FairShareImpl(rep, ref));\n}\n\n// Samples the cord and returns CordzInfo::GetStatistics()\nCordzStatistics SampleCord(CordRep* rep) {\n  InlineData cord(rep);\n  CordzInfo::TrackCord(cord, CordzUpdateTracker::kUnknown, 1);\n  CordzStatistics stats = cord.cordz_info()->GetCordzStatistics();\n  cord.cordz_info()->Untrack();\n  return stats;\n}\n\nMATCHER_P(EqStatistics, stats, \"Statistics equal expected values\") {\n  bool ok = true;\n\n#define STATS_MATCHER_EXPECT_EQ(member)                              \\\n  if (stats.member != arg.member) {                                  \\\n    *result_listener << \"\\n    stats.\" << #member                    \\\n                     << \": actual = \" << arg.member << \", expected \" \\\n                     << stats.member;                                \\\n    ok = false;                                                      \\\n  }\n\n  STATS_MATCHER_EXPECT_EQ(size);\n  STATS_MATCHER_EXPECT_EQ(node_count);\n  STATS_MATCHER_EXPECT_EQ(node_counts.flat);\n  STATS_MATCHER_EXPECT_EQ(node_counts.flat_64);\n  STATS_MATCHER_EXPECT_EQ(node_counts.flat_128);\n  STATS_MATCHER_EXPECT_EQ(node_counts.flat_256);\n  STATS_MATCHER_EXPECT_EQ(node_counts.flat_512);\n  STATS_MATCHER_EXPECT_EQ(node_counts.flat_1k);\n  STATS_MATCHER_EXPECT_EQ(node_counts.external);\n  STATS_MATCHER_EXPECT_EQ(node_counts.concat);\n  STATS_MATCHER_EXPECT_EQ(node_counts.substring);\n  STATS_MATCHER_EXPECT_EQ(node_counts.ring);\n  STATS_MATCHER_EXPECT_EQ(node_counts.btree);\n  STATS_MATCHER_EXPECT_EQ(estimated_memory_usage);\n  STATS_MATCHER_EXPECT_EQ(estimated_fair_share_memory_usage);\n\n#undef STATS_MATCHER_EXPECT_EQ\n\n  return ok;\n}\n\nTEST(CordzInfoStatisticsTest, Flat) {\n  RefHelper ref;\n  auto* flat = ref.NeedsUnref(Flat(512));\n\n  CordzStatistics expected;\n  expected.size = flat->length;\n  expected.estimated_memory_usage = SizeOf(flat);\n  expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;\n  expected.node_count = 1;\n  expected.node_counts.flat = 1;\n  expected.node_counts.flat_512 = 1;\n\n  EXPECT_THAT(SampleCord(flat), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, SharedFlat) {\n  RefHelper ref;\n  auto* flat = ref.Ref(ref.NeedsUnref(Flat(64)));\n\n  CordzStatistics expected;\n  expected.size = flat->length;\n  expected.estimated_memory_usage = SizeOf(flat);\n  expected.estimated_fair_share_memory_usage = SizeOf(flat) / 2;\n  expected.node_count = 1;\n  expected.node_counts.flat = 1;\n  expected.node_counts.flat_64 = 1;\n\n  EXPECT_THAT(SampleCord(flat), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, External) {\n  RefHelper ref;\n  auto* external = ref.NeedsUnref(External());\n\n  CordzStatistics expected;\n  expected.size = external->length;\n  expected.estimated_memory_usage = SizeOf(external);\n  expected.estimated_fair_share_memory_usage = SizeOf(external);\n  expected.node_count = 1;\n  expected.node_counts.external = 1;\n\n  EXPECT_THAT(SampleCord(external), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, SharedExternal) {\n  RefHelper ref;\n  auto* external = ref.Ref(ref.NeedsUnref(External()));\n\n  CordzStatistics expected;\n  expected.size = external->length;\n  expected.estimated_memory_usage = SizeOf(external);\n  expected.estimated_fair_share_memory_usage = SizeOf(external) / 2;\n  expected.node_count = 1;\n  expected.node_counts.external = 1;\n\n  EXPECT_THAT(SampleCord(external), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, Substring) {\n  RefHelper ref;\n  auto* flat = Flat(1024);\n  auto* substring = ref.NeedsUnref(Substring(flat));\n\n  CordzStatistics expected;\n  expected.size = substring->length;\n  expected.estimated_memory_usage = SizeOf(substring) + SizeOf(flat);\n  expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;\n  expected.node_count = 2;\n  expected.node_counts.flat = 1;\n  expected.node_counts.flat_1k = 1;\n  expected.node_counts.substring = 1;\n\n  EXPECT_THAT(SampleCord(substring), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, SharedSubstring) {\n  RefHelper ref;\n  auto* flat = ref.Ref(Flat(511), 2);\n  auto* substring = ref.Ref(ref.NeedsUnref(Substring(flat)));\n\n  CordzStatistics expected;\n  expected.size = substring->length;\n  expected.estimated_memory_usage = SizeOf(flat) + SizeOf(substring);\n  expected.estimated_fair_share_memory_usage =\n      SizeOf(substring) / 2 + SizeOf(flat) / 6;\n  expected.node_count = 2;\n  expected.node_counts.flat = 1;\n  expected.node_counts.flat_512 = 1;\n  expected.node_counts.substring = 1;\n\n  EXPECT_THAT(SampleCord(substring), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, BtreeLeaf) {\n  ASSERT_THAT(CordRepBtree::kMaxCapacity, Ge(3u));\n  RefHelper ref;\n  auto* flat1 = Flat(2000);\n  auto* flat2 = Flat(200);\n  auto* substr = Substring(flat2);\n  auto* external = External(3000);\n\n  CordRepBtree* tree = CordRepBtree::Create(flat1);\n  tree = CordRepBtree::Append(tree, substr);\n  tree = CordRepBtree::Append(tree, external);\n  size_t flat3_count = CordRepBtree::kMaxCapacity - 3;\n  size_t flat3_size = 0;\n  for (size_t i = 0; i < flat3_count; ++i) {\n    auto* flat3 = Flat(70);\n    flat3_size += SizeOf(flat3);\n    tree = CordRepBtree::Append(tree, flat3);\n  }\n  ref.NeedsUnref(tree);\n\n  CordzStatistics expected;\n  expected.size = tree->length;\n  expected.estimated_memory_usage = SizeOf(tree) + SizeOf(flat1) +\n                                    SizeOf(flat2) + SizeOf(substr) +\n                                    flat3_size + SizeOf(external);\n  expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;\n  expected.node_count = 1 + 3 + 1 + flat3_count;\n  expected.node_counts.flat = 2 + flat3_count;\n  expected.node_counts.flat_128 = flat3_count;\n  expected.node_counts.flat_256 = 1;\n  expected.node_counts.external = 1;\n  expected.node_counts.substring = 1;\n  expected.node_counts.btree = 1;\n\n  EXPECT_THAT(SampleCord(tree), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, BtreeNodeShared) {\n  RefHelper ref;\n  static constexpr int leaf_count = 3;\n  const size_t flat3_count = CordRepBtree::kMaxCapacity - 3;\n  ASSERT_THAT(flat3_count, Ge(0u));\n\n  CordRepBtree* tree = nullptr;\n  size_t mem_size = 0;\n  for (int i = 0; i < leaf_count; ++i) {\n    auto* flat1 = ref.Ref(Flat(2000), 9);\n    mem_size += SizeOf(flat1);\n    if (i == 0) {\n      tree = CordRepBtree::Create(flat1);\n    } else {\n      tree = CordRepBtree::Append(tree, flat1);\n    }\n\n    auto* flat2 = Flat(200);\n    auto* substr = Substring(flat2);\n    mem_size += SizeOf(flat2) + SizeOf(substr);\n    tree = CordRepBtree::Append(tree, substr);\n\n    auto* external = External(30);\n    mem_size += SizeOf(external);\n    tree = CordRepBtree::Append(tree, external);\n\n    for (size_t i = 0; i < flat3_count; ++i) {\n      auto* flat3 = Flat(70);\n      mem_size += SizeOf(flat3);\n      tree = CordRepBtree::Append(tree, flat3);\n    }\n\n    if (i == 0) {\n      mem_size += SizeOf(tree);\n    } else {\n      mem_size += SizeOf(tree->Edges().back()->btree());\n    }\n  }\n  ref.NeedsUnref(tree);\n\n  // Ref count: 2 for top (add 1), 5 for leaf 0 (add 4).\n  ref.Ref(tree, 1);\n  ref.Ref(tree->Edges().front(), 4);\n\n  CordzStatistics expected;\n  expected.size = tree->length;\n  expected.estimated_memory_usage = SizeOf(tree) + mem_size;\n  expected.estimated_fair_share_memory_usage = FairShare(tree);\n\n  expected.node_count = 1 + leaf_count * (1 + 3 + 1 + flat3_count);\n  expected.node_counts.flat = leaf_count * (2 + flat3_count);\n  expected.node_counts.flat_128 = leaf_count * flat3_count;\n  expected.node_counts.flat_256 = leaf_count;\n  expected.node_counts.external = leaf_count;\n  expected.node_counts.substring = leaf_count;\n  expected.node_counts.btree = 1 + leaf_count;\n\n  EXPECT_THAT(SampleCord(tree), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, Crc) {\n  RefHelper ref;\n  auto* left = Flat(1000);\n  auto* crc = ref.NeedsUnref(CordRepCrc::New(left, {}));\n\n  CordzStatistics expected;\n  expected.size = left->length;\n  expected.estimated_memory_usage = SizeOf(crc) + SizeOf(left);\n  expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;\n  expected.node_count = 2;\n  expected.node_counts.flat = 1;\n  expected.node_counts.flat_1k = 1;\n  expected.node_counts.crc = 1;\n\n  EXPECT_THAT(SampleCord(crc), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, EmptyCrc) {\n  RefHelper ref;\n  auto* crc = ref.NeedsUnref(CordRepCrc::New(nullptr, {}));\n\n  CordzStatistics expected;\n  expected.size = 0;\n  expected.estimated_memory_usage = SizeOf(crc);\n  expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;\n  expected.node_count = 1;\n  expected.node_counts.crc = 1;\n\n  EXPECT_THAT(SampleCord(crc), EqStatistics(expected));\n}\n\nTEST(CordzInfoStatisticsTest, ThreadSafety) {\n  Notification stop;\n  static constexpr int kNumThreads = 8;\n  int64_t sampled_node_count = 0;\n\n  {\n    absl::synchronization_internal::ThreadPool pool(kNumThreads);\n\n    // Run analyzer thread emulating a CordzHandler collection.\n    pool.Schedule([&]() {\n      while (!stop.HasBeenNotified()) {\n        // Run every 10us (about 100K total collections).\n        absl::SleepFor(absl::Microseconds(10));\n        CordzSampleToken token;\n        for (const CordzInfo& cord_info : token) {\n          CordzStatistics stats = cord_info.GetCordzStatistics();\n          sampled_node_count += stats.node_count;\n        }\n      }\n    });\n\n    // Run 'application threads'\n    for (int i = 0; i < kNumThreads; ++i) {\n      pool.Schedule([&]() {\n        // Track 0 - 2 cordz infos at a time, providing permutations of 0, 1\n        // and 2 CordzHandle and CordzInfo queues being active, with plenty of\n        // 'empty to non empty' transitions.\n        InlineData cords[2];\n        std::minstd_rand gen;\n        std::uniform_int_distribution<int> coin_toss(0, 1);\n        std::uniform_int_distribution<int> dice_roll(1, 6);\n\n        while (!stop.HasBeenNotified()) {\n          for (InlineData& cord : cords) {\n            // 50/50 flip the state of the cord\n            if (coin_toss(gen) != 0) {\n              if (cord.is_tree()) {\n                // 50/50 simulate delete (untrack) or 'edit to empty'\n                if (coin_toss(gen) != 0) {\n                  CordzInfo::MaybeUntrackCord(cord.cordz_info());\n                } else {\n                  CordzUpdateScope scope(cord.cordz_info(),\n                                         CordzUpdateTracker::kUnknown);\n                  scope.SetCordRep(nullptr);\n                }\n                CordRep::Unref(cord.as_tree());\n                cord.set_inline_size(0);\n              } else {\n                // Coin toss to 50% btree, and 50% flat.\n                CordRep* rep = Flat(256);\n                if (coin_toss(gen) != 0) {\n                  rep = CordRepBtree::Create(rep);\n                }\n\n                // Maybe CRC this cord\n                if (dice_roll(gen) == 6) {\n                  if (dice_roll(gen) == 6) {\n                    // Empty CRC rep\n                    CordRep::Unref(rep);\n                    rep = CordRepCrc::New(nullptr, {});\n                  } else {\n                    // Regular CRC rep\n                    rep = CordRepCrc::New(rep, {});\n                  }\n                }\n                cord.make_tree(rep);\n\n                // 50/50 sample\n                if (coin_toss(gen) != 0) {\n                  CordzInfo::TrackCord(cord, CordzUpdateTracker::kUnknown, 1);\n                }\n              }\n            }\n          }\n        }\n        for (InlineData& cord : cords) {\n          if (cord.is_tree()) {\n            CordzInfo::MaybeUntrackCord(cord.cordz_info());\n            CordRep::Unref(cord.as_tree());\n          }\n        }\n      });\n    }\n\n    // Run for 1 second to give memory and thread safety analyzers plenty of\n    // time to detect any mishaps or undefined behaviors.\n    absl::SleepFor(absl::Seconds(1));\n    stop.Notify();\n  }\n\n  std::cout << \"Sampled \" << sampled_node_count << \" nodes\\n\";\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_info_test.cc",
    "content": "// Copyright 2019 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_info.h\"\n\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/symbolize.h\"\n#include \"absl/strings/cordz_test_helpers.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_handle.h\"\n#include \"absl/strings/internal/cordz_statistics.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing ::testing::Ne;\nusing ::testing::SizeIs;\n\n// Used test values\nauto constexpr kUnknownMethod = CordzUpdateTracker::kUnknown;\nauto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;\nauto constexpr kChildMethod = CordzUpdateTracker::kConstructorCord;\nauto constexpr kUpdateMethod = CordzUpdateTracker::kAppendString;\n\n// Local less verbose helper\nstd::vector<const CordzHandle*> DeleteQueue() {\n  return CordzHandle::DiagnosticsGetDeleteQueue();\n}\n\nstd::string FormatStack(absl::Span<void* const> raw_stack) {\n  static constexpr size_t buf_size = 1 << 14;\n  std::unique_ptr<char[]> buf(new char[buf_size]);\n  std::string output;\n  for (void* stackp : raw_stack) {\n    if (absl::Symbolize(stackp, buf.get(), buf_size)) {\n      absl::StrAppend(&output, \"    \", buf.get(), \"\\n\");\n    }\n  }\n  return output;\n}\n\nTEST(CordzInfoTest, TrackCord) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n  ASSERT_THAT(info, Ne(nullptr));\n  EXPECT_FALSE(info->is_snapshot());\n  EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(info));\n  EXPECT_THAT(info->GetCordRepForTesting(), Eq(data.rep.rep));\n  info->Untrack();\n}\n\nTEST(CordzInfoTest, MaybeTrackChildCordWithoutSampling) {\n  CordzSamplingIntervalHelper sample_none(99999);\n  TestCordData parent, child;\n  CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);\n  EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, MaybeTrackChildCordWithSampling) {\n  CordzSamplingIntervalHelper sample_all(1);\n  TestCordData parent, child;\n  CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);\n  EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, MaybeTrackChildCordWithoutSamplingParentSampled) {\n  CordzSamplingIntervalHelper sample_none(99999);\n  TestCordData parent, child;\n  CordzInfo::TrackCord(parent.data, kTrackCordMethod, 1);\n  CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);\n  CordzInfo* parent_info = parent.data.cordz_info();\n  CordzInfo* child_info = child.data.cordz_info();\n  ASSERT_THAT(child_info, Ne(nullptr));\n  EXPECT_THAT(child_info->GetCordRepForTesting(), Eq(child.rep.rep));\n  EXPECT_THAT(child_info->GetParentStack(), parent_info->GetStack());\n  parent_info->Untrack();\n  child_info->Untrack();\n}\n\nTEST(CordzInfoTest, MaybeTrackChildCordWithoutSamplingChildSampled) {\n  CordzSamplingIntervalHelper sample_none(99999);\n  TestCordData parent, child;\n  CordzInfo::TrackCord(child.data, kTrackCordMethod, 1);\n  CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);\n  EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, MaybeTrackChildCordWithSamplingChildSampled) {\n  CordzSamplingIntervalHelper sample_all(1);\n  TestCordData parent, child;\n  CordzInfo::TrackCord(child.data, kTrackCordMethod, 1);\n  CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);\n  EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, UntrackCord) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n\n  info->Untrack();\n  EXPECT_THAT(DeleteQueue(), SizeIs(0u));\n}\n\nTEST(CordzInfoTest, UntrackCordWithSnapshot) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n\n  CordzSnapshot snapshot;\n  info->Untrack();\n  EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(nullptr));\n  EXPECT_THAT(info->GetCordRepForTesting(), Eq(data.rep.rep));\n  EXPECT_THAT(DeleteQueue(), ElementsAre(info, &snapshot));\n}\n\nTEST(CordzInfoTest, SetCordRep) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n\n  TestCordRep rep;\n  info->Lock(CordzUpdateTracker::kAppendCord);\n  info->SetCordRep(rep.rep);\n  info->Unlock();\n  EXPECT_THAT(info->GetCordRepForTesting(), Eq(rep.rep));\n\n  info->Untrack();\n}\n\nTEST(CordzInfoTest, SetCordRepNullUntracksCordOnUnlock) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n\n  info->Lock(CordzUpdateTracker::kAppendString);\n  info->SetCordRep(nullptr);\n  EXPECT_THAT(info->GetCordRepForTesting(), Eq(nullptr));\n  EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(info));\n\n  info->Unlock();\n  EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, RefCordRep) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n\n  size_t refcount = data.rep.rep->refcount.Get();\n  EXPECT_THAT(info->RefCordRep(), Eq(data.rep.rep));\n  EXPECT_THAT(data.rep.rep->refcount.Get(), Eq(refcount + 1));\n  CordRep::Unref(data.rep.rep);\n  info->Untrack();\n}\n\n#if GTEST_HAS_DEATH_TEST\n\nTEST(CordzInfoTest, SetCordRepRequiresMutex) {\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n  TestCordRep rep;\n  EXPECT_DEBUG_DEATH(info->SetCordRep(rep.rep), \".*\");\n  info->Untrack();\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\nTEST(CordzInfoTest, TrackUntrackHeadFirstV2) {\n  CordzSnapshot snapshot;\n  EXPECT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));\n\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info1 = data.data.cordz_info();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info1));\n  EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));\n\n  TestCordData data2;\n  CordzInfo::TrackCord(data2.data, kTrackCordMethod, 1);\n  CordzInfo* info2 = data2.data.cordz_info();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info2));\n  EXPECT_THAT(info2->Next(snapshot), Eq(info1));\n  EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));\n\n  info2->Untrack();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info1));\n  EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));\n\n  info1->Untrack();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, TrackUntrackTailFirstV2) {\n  CordzSnapshot snapshot;\n  EXPECT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));\n\n  TestCordData data;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info1 = data.data.cordz_info();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info1));\n  EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));\n\n  TestCordData data2;\n  CordzInfo::TrackCord(data2.data, kTrackCordMethod, 1);\n  CordzInfo* info2 = data2.data.cordz_info();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info2));\n  EXPECT_THAT(info2->Next(snapshot), Eq(info1));\n  EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));\n\n  info1->Untrack();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info2));\n  EXPECT_THAT(info2->Next(snapshot), Eq(nullptr));\n\n  info2->Untrack();\n  ASSERT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));\n}\n\nTEST(CordzInfoTest, StackV2) {\n  TestCordData data;\n  // kMaxStackDepth is intentionally less than 64 (which is the max depth that\n  // Cordz will record) because if the actual stack depth is over 64\n  // (which it is on Apple platforms) then the expected_stack will end up\n  // catching a few frames at the end that the actual_stack didn't get and\n  // it will no longer be subset. At the time of this writing 58 is the max\n  // that will allow this test to pass (with a minimum os version of iOS 9), so\n  // rounded down to 50 to hopefully not run into this in the future if Apple\n  // makes small modifications to its testing stack. 50 is sufficient to prove\n  // that we got a decent stack.\n  static constexpr int kMaxStackDepth = 50;\n  CordzInfo::TrackCord(data.data, kTrackCordMethod, 1);\n  CordzInfo* info = data.data.cordz_info();\n  std::vector<void*> local_stack;\n  local_stack.resize(kMaxStackDepth);\n  // In some environments we don't get stack traces. For example in Android\n  // absl::GetStackTrace will return 0 indicating it didn't find any stack. The\n  // resultant formatted stack will be \"\", but that still equals the stack\n  // recorded in CordzInfo, which is also empty. The skip_count is 1 so that the\n  // line number of the current stack isn't included in the HasSubstr check.\n  local_stack.resize(static_cast<size_t>(\n      absl::GetStackTrace(local_stack.data(), kMaxStackDepth,\n                          /*skip_count=*/1)));\n\n  std::string got_stack = FormatStack(info->GetStack());\n  std::string expected_stack = FormatStack(local_stack);\n  // If TrackCord is inlined, got_stack should match expected_stack. If it isn't\n  // inlined, got_stack should include an additional frame not present in\n  // expected_stack. Either way, expected_stack should be a substring of\n  // got_stack.\n  EXPECT_THAT(got_stack, HasSubstr(expected_stack));\n\n  info->Untrack();\n}\n\n// Local helper functions to get different stacks for child and parent.\nCordzInfo* TrackChildCord(InlineData& data, const InlineData& parent) {\n  CordzInfo::TrackCord(data, parent, kChildMethod);\n  return data.cordz_info();\n}\nCordzInfo* TrackParentCord(InlineData& data) {\n  CordzInfo::TrackCord(data, kTrackCordMethod, 1);\n  return data.cordz_info();\n}\n\nTEST(CordzInfoTest, GetStatistics) {\n  TestCordData data;\n  CordzInfo* info = TrackParentCord(data.data);\n\n  CordzStatistics statistics = info->GetCordzStatistics();\n  EXPECT_THAT(statistics.size, Eq(data.rep.rep->length));\n  EXPECT_THAT(statistics.method, Eq(kTrackCordMethod));\n  EXPECT_THAT(statistics.parent_method, Eq(kUnknownMethod));\n  EXPECT_THAT(statistics.update_tracker.Value(kTrackCordMethod), Eq(1));\n\n  info->Untrack();\n}\n\nTEST(CordzInfoTest, LockCountsMethod) {\n  TestCordData data;\n  CordzInfo* info = TrackParentCord(data.data);\n\n  info->Lock(kUpdateMethod);\n  info->Unlock();\n  info->Lock(kUpdateMethod);\n  info->Unlock();\n\n  CordzStatistics statistics = info->GetCordzStatistics();\n  EXPECT_THAT(statistics.update_tracker.Value(kUpdateMethod), Eq(2));\n\n  info->Untrack();\n}\n\nTEST(CordzInfoTest, FromParent) {\n  TestCordData parent;\n  TestCordData child;\n  CordzInfo* info_parent = TrackParentCord(parent.data);\n  CordzInfo* info_child = TrackChildCord(child.data, parent.data);\n\n  std::string stack = FormatStack(info_parent->GetStack());\n  std::string parent_stack = FormatStack(info_child->GetParentStack());\n  EXPECT_THAT(stack, Eq(parent_stack));\n\n  CordzStatistics statistics = info_child->GetCordzStatistics();\n  EXPECT_THAT(statistics.size, Eq(child.rep.rep->length));\n  EXPECT_THAT(statistics.method, Eq(kChildMethod));\n  EXPECT_THAT(statistics.parent_method, Eq(kTrackCordMethod));\n  EXPECT_THAT(statistics.update_tracker.Value(kChildMethod), Eq(1));\n\n  info_parent->Untrack();\n  info_child->Untrack();\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_sample_token.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_sample_token.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cordz_handle.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nCordzSampleToken::Iterator& CordzSampleToken::Iterator::operator++() {\n  if (current_) {\n    current_ = current_->Next(*token_);\n  }\n  return *this;\n}\n\nCordzSampleToken::Iterator CordzSampleToken::Iterator::operator++(int) {\n  Iterator it(*this);\n  operator++();\n  return it;\n}\n\nbool operator==(const CordzSampleToken::Iterator& lhs,\n                const CordzSampleToken::Iterator& rhs) {\n  return lhs.current_ == rhs.current_ &&\n         (lhs.current_ == nullptr || lhs.token_ == rhs.token_);\n}\n\nbool operator!=(const CordzSampleToken::Iterator& lhs,\n                const CordzSampleToken::Iterator& rhs) {\n  return !(lhs == rhs);\n}\n\nCordzSampleToken::Iterator::reference CordzSampleToken::Iterator::operator*()\n    const {\n  return *current_;\n}\n\nCordzSampleToken::Iterator::pointer CordzSampleToken::Iterator::operator->()\n    const {\n  return current_;\n}\n\nCordzSampleToken::Iterator::Iterator(const CordzSampleToken* token)\n    : token_(token), current_(CordzInfo::Head(*token)) {}\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_sample_token.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cordz_handle.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// The existence of a CordzSampleToken guarantees that a reader can traverse the\n// global_cordz_infos_head linked-list without needing to hold a mutex. When a\n// CordzSampleToken exists, all CordzInfo objects that would be destroyed are\n// instead appended to a deletion queue. When the CordzSampleToken is destroyed,\n// it will also clean up any of these CordzInfo objects.\n//\n// E.g., ST are CordzSampleToken objects and CH are CordzHandle objects.\n//   ST1 <- CH1 <- CH2 <- ST2 <- CH3 <- global_delete_queue_tail\n//\n// This list tracks that CH1 and CH2 were created after ST1, so the thread\n// holding ST1 might have a reference to CH1, CH2, ST2, and CH3. However, ST2\n// was created later, so the thread holding the ST2 token cannot have a\n// reference to ST1, CH1, or CH2. If ST1 is cleaned up first, that thread will\n// delete ST1, CH1, and CH2. If instead ST2 is cleaned up first, that thread\n// will only delete ST2.\n//\n// If ST1 is cleaned up first, the new list will be:\n//   ST2 <- CH3 <- global_delete_queue_tail\n//\n// If ST2 is cleaned up first, the new list will be:\n//   ST1 <- CH1 <- CH2 <- CH3 <- global_delete_queue_tail\n//\n// All new CordzHandle objects are appended to the list, so if a new thread\n// comes along before either ST1 or ST2 are cleaned up, the new list will be:\n//   ST1 <- CH1 <- CH2 <- ST2 <- CH3 <- ST3 <- global_delete_queue_tail\n//\n// A thread must hold the global_delete_queue_mu mutex whenever it's altering\n// this list.\n//\n// It is safe for thread that holds a CordzSampleToken to read\n// global_cordz_infos at any time since the objects it is able to retrieve will\n// not be deleted while the CordzSampleToken exists.\nclass CordzSampleToken : public CordzSnapshot {\n public:\n  class Iterator {\n   public:\n    using iterator_category = std::input_iterator_tag;\n    using value_type = const CordzInfo&;\n    using difference_type = ptrdiff_t;\n    using pointer = const CordzInfo*;\n    using reference = value_type;\n\n    Iterator() = default;\n\n    Iterator& operator++();\n    Iterator operator++(int);\n    friend bool operator==(const Iterator& lhs, const Iterator& rhs);\n    friend bool operator!=(const Iterator& lhs, const Iterator& rhs);\n    reference operator*() const;\n    pointer operator->() const;\n\n   private:\n    friend class CordzSampleToken;\n    explicit Iterator(const CordzSampleToken* token);\n\n    const CordzSampleToken* token_ = nullptr;\n    pointer current_ = nullptr;\n  };\n\n  CordzSampleToken() = default;\n  CordzSampleToken(const CordzSampleToken&) = delete;\n  CordzSampleToken& operator=(const CordzSampleToken&) = delete;\n\n  Iterator begin() { return Iterator(this); }\n  Iterator end() { return Iterator(); }\n};\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_sample_token_test.cc",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_sample_token.h\"\n\n#include <memory>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/cordz_test_helpers.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_handle.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/notification.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::Eq;\nusing ::testing::Ne;\n\n// Used test values\nauto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;\n\nTEST(CordzSampleTokenTest, IteratorTraits) {\n  static_assert(std::is_copy_constructible<CordzSampleToken::Iterator>::value,\n                \"\");\n  static_assert(std::is_copy_assignable<CordzSampleToken::Iterator>::value, \"\");\n  static_assert(std::is_move_constructible<CordzSampleToken::Iterator>::value,\n                \"\");\n  static_assert(std::is_move_assignable<CordzSampleToken::Iterator>::value, \"\");\n  static_assert(\n      std::is_same<\n          std::iterator_traits<CordzSampleToken::Iterator>::iterator_category,\n          std::input_iterator_tag>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::value_type,\n                   const CordzInfo&>::value,\n      \"\");\n  static_assert(\n      std::is_same<\n          std::iterator_traits<CordzSampleToken::Iterator>::difference_type,\n          ptrdiff_t>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::pointer,\n                   const CordzInfo*>::value,\n      \"\");\n  static_assert(\n      std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::reference,\n                   const CordzInfo&>::value,\n      \"\");\n}\n\nTEST(CordzSampleTokenTest, IteratorEmpty) {\n  CordzSampleToken token;\n  EXPECT_THAT(token.begin(), Eq(token.end()));\n}\n\nTEST(CordzSampleTokenTest, Iterator) {\n  TestCordData cord1, cord2, cord3;\n  CordzInfo::TrackCord(cord1.data, kTrackCordMethod, 1);\n  CordzInfo* info1 = cord1.data.cordz_info();\n  CordzInfo::TrackCord(cord2.data, kTrackCordMethod, 1);\n  CordzInfo* info2 = cord2.data.cordz_info();\n  CordzInfo::TrackCord(cord3.data, kTrackCordMethod, 1);\n  CordzInfo* info3 = cord3.data.cordz_info();\n\n  CordzSampleToken token;\n  std::vector<const CordzInfo*> found;\n  for (const CordzInfo& cord_info : token) {\n    found.push_back(&cord_info);\n  }\n\n  EXPECT_THAT(found, ElementsAre(info3, info2, info1));\n\n  info1->Untrack();\n  info2->Untrack();\n  info3->Untrack();\n}\n\nTEST(CordzSampleTokenTest, IteratorEquality) {\n  TestCordData cord1;\n  TestCordData cord2;\n  TestCordData cord3;\n  CordzInfo::TrackCord(cord1.data, kTrackCordMethod, 1);\n  CordzInfo* info1 = cord1.data.cordz_info();\n\n  CordzSampleToken token1;\n  // lhs starts with the CordzInfo corresponding to cord1 at the head.\n  CordzSampleToken::Iterator lhs = token1.begin();\n\n  CordzInfo::TrackCord(cord2.data, kTrackCordMethod, 1);\n  CordzInfo* info2 = cord2.data.cordz_info();\n\n  CordzSampleToken token2;\n  // rhs starts with the CordzInfo corresponding to cord2 at the head.\n  CordzSampleToken::Iterator rhs = token2.begin();\n\n  CordzInfo::TrackCord(cord3.data, kTrackCordMethod, 1);\n  CordzInfo* info3 = cord3.data.cordz_info();\n\n  // lhs is on cord1 while rhs is on cord2.\n  EXPECT_THAT(lhs, Ne(rhs));\n\n  rhs++;\n  // lhs and rhs are both on cord1, but they didn't come from the same\n  // CordzSampleToken.\n  EXPECT_THAT(lhs, Ne(rhs));\n\n  lhs++;\n  rhs++;\n  // Both lhs and rhs are done, so they are on nullptr.\n  EXPECT_THAT(lhs, Eq(rhs));\n\n  info1->Untrack();\n  info2->Untrack();\n  info3->Untrack();\n}\n\nTEST(CordzSampleTokenTest, MultiThreaded) {\n  Notification stop;\n  static constexpr int kNumThreads = 4;\n  static constexpr int kNumCords = 3;\n  static constexpr int kNumTokens = 3;\n  absl::synchronization_internal::ThreadPool pool(kNumThreads);\n\n  for (int i = 0; i < kNumThreads; ++i) {\n    pool.Schedule([&stop]() {\n      absl::BitGen gen;\n      TestCordData cords[kNumCords];\n      std::unique_ptr<CordzSampleToken> tokens[kNumTokens];\n\n      while (!stop.HasBeenNotified()) {\n        // Randomly perform one of five actions:\n        //   1) Untrack\n        //   2) Track\n        //   3) Iterate over Cords visible to a token.\n        //   4) Unsample\n        //   5) Sample\n        int index = absl::Uniform(gen, 0, kNumCords);\n        if (absl::Bernoulli(gen, 0.5)) {\n          TestCordData& cord = cords[index];\n          // Track/untrack.\n          if (cord.data.is_profiled()) {\n            // 1) Untrack\n            cord.data.cordz_info()->Untrack();\n            cord.data.clear_cordz_info();\n          } else {\n            // 2) Track\n            CordzInfo::TrackCord(cord.data, kTrackCordMethod, 1);\n          }\n        } else {\n          std::unique_ptr<CordzSampleToken>& token = tokens[index];\n          if (token) {\n            if (absl::Bernoulli(gen, 0.5)) {\n              // 3) Iterate over Cords visible to a token.\n              for (const CordzInfo& info : *token) {\n                // This is trivial work to allow us to compile the loop.\n                EXPECT_THAT(info.Next(*token), Ne(&info));\n              }\n            } else {\n              // 4) Unsample\n              token = nullptr;\n            }\n          } else {\n            // 5) Sample\n            token = absl::make_unique<CordzSampleToken>();\n          }\n        }\n      }\n      for (TestCordData& cord : cords) {\n        CordzInfo::MaybeUntrackCord(cord.data.cordz_info());\n      }\n    });\n  }\n  // The threads will hammer away.  Give it a little bit of time for tsan to\n  // spot errors.\n  absl::SleepFor(absl::Seconds(3));\n  stop.Notify();\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_statistics.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordzStatistics captures some meta information about a Cord's shape.\nstruct CordzStatistics {\n  using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;\n\n  // Node counts information\n  struct NodeCounts {\n    size_t flat = 0;       // #flats\n    size_t flat_64 = 0;    // #flats up to 64 bytes\n    size_t flat_128 = 0;   // #flats up to 128 bytes\n    size_t flat_256 = 0;   // #flats up to 256 bytes\n    size_t flat_512 = 0;   // #flats up to 512 bytes\n    size_t flat_1k = 0;    // #flats up to 1K bytes\n    size_t external = 0;   // #external reps\n    size_t substring = 0;  // #substring reps\n    size_t concat = 0;     // #concat reps\n    size_t ring = 0;       // #ring buffer reps\n    size_t btree = 0;      // #btree reps\n    size_t crc = 0;        // #crc reps\n  };\n\n  // The size of the cord in bytes. This matches the result of Cord::size().\n  size_t size = 0;\n\n  // The estimated memory used by the sampled cord. This value matches the\n  // value as reported by Cord::EstimatedMemoryUsage().\n  // A value of 0 implies the property has not been recorded.\n  size_t estimated_memory_usage = 0;\n\n  // The effective memory used by the sampled cord, inversely weighted by the\n  // effective indegree of each allocated node. This is a representation of the\n  // fair share of memory usage that should be attributed to the sampled cord.\n  // This value is more useful for cases where one or more nodes are referenced\n  // by multiple Cord instances, and for cases where a Cord includes the same\n  // node multiple times (either directly or indirectly).\n  // A value of 0 implies the property has not been recorded.\n  size_t estimated_fair_share_memory_usage = 0;\n\n  // The total number of nodes referenced by this cord.\n  // For ring buffer Cords, this includes the 'ring buffer' node.\n  // For btree Cords, this includes all 'CordRepBtree' tree nodes as well as all\n  // the substring, flat and external nodes referenced by the tree.\n  // A value of 0 implies the property has not been recorded.\n  size_t node_count = 0;\n\n  // Detailed node counts per type\n  NodeCounts node_counts;\n\n  // The cord method responsible for sampling the cord.\n  MethodIdentifier method = MethodIdentifier::kUnknown;\n\n  // The cord method responsible for sampling the parent cord if applicable.\n  MethodIdentifier parent_method = MethodIdentifier::kUnknown;\n\n  // Update tracker tracking invocation count per cord method.\n  CordzUpdateTracker update_tracker;\n};\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_update_scope.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/strings/internal/cord_internal.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordzUpdateScope scopes an update to the provided CordzInfo.\n// The class invokes `info->Lock(method)` and `info->Unlock()` to guard\n// cordrep updates. This class does nothing if `info` is null.\n// See also the 'Lock`, `Unlock` and `SetCordRep` methods in `CordzInfo`.\nclass ABSL_SCOPED_LOCKABLE CordzUpdateScope {\n public:\n  CordzUpdateScope(CordzInfo* info, CordzUpdateTracker::MethodIdentifier method)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(info)\n      : info_(info) {\n    if (ABSL_PREDICT_FALSE(info_)) {\n      info->Lock(method);\n    }\n  }\n\n  // CordzUpdateScope can not be copied or assigned to.\n  CordzUpdateScope(CordzUpdateScope&& rhs) = delete;\n  CordzUpdateScope(const CordzUpdateScope&) = delete;\n  CordzUpdateScope& operator=(CordzUpdateScope&& rhs) = delete;\n  CordzUpdateScope& operator=(const CordzUpdateScope&) = delete;\n\n  ~CordzUpdateScope() ABSL_UNLOCK_FUNCTION() {\n    if (ABSL_PREDICT_FALSE(info_)) {\n      info_->Unlock();\n    }\n  }\n\n  void SetCordRep(CordRep* rep) const {\n    if (ABSL_PREDICT_FALSE(info_)) {\n      info_->SetCordRep(rep);\n    }\n  }\n\n  CordzInfo* info() const { return info_; }\n\n private:\n  CordzInfo* info_;\n};\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_update_scope_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_update_scope.h\"\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/cordz_test_helpers.h\"\n#include \"absl/strings/internal/cord_rep_flat.h\"\n#include \"absl/strings/internal/cordz_info.h\"\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\nnamespace {\n\n// Used test values\nauto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;\n\nTEST(CordzUpdateScopeTest, ScopeNullptr) {\n  CordzUpdateScope scope(nullptr, kTrackCordMethod);\n}\n\nTEST(CordzUpdateScopeTest, ScopeSampledCord) {\n  TestCordData cord;\n  CordzInfo::TrackCord(cord.data, kTrackCordMethod, 1);\n  CordzUpdateScope scope(cord.data.cordz_info(), kTrackCordMethod);\n  cord.data.cordz_info()->SetCordRep(nullptr);\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace cord_internal\n\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/cordz_update_tracker.h",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_\n#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\n\n// CordzUpdateTracker tracks counters for Cord update methods.\n//\n// The purpose of CordzUpdateTracker is to track the number of calls to methods\n// updating Cord data for sampled cords. The class internally uses 'lossy'\n// atomic operations: Cord is thread-compatible, so there is no need to\n// synchronize updates. However, Cordz collection threads may call 'Value()' at\n// any point, so the class needs to provide thread safe access.\n//\n// This class is thread-safe. But as per above comments, all non-const methods\n// should be used single-threaded only: updates are thread-safe but lossy.\nclass CordzUpdateTracker {\n public:\n  // Tracked update methods.\n  enum MethodIdentifier {\n    kUnknown,\n    kAppendCord,\n    kAppendCordBuffer,\n    kAppendExternalMemory,\n    kAppendString,\n    kAssignCord,\n    kAssignString,\n    kClear,\n    kConstructorCord,\n    kConstructorString,\n    kCordReader,\n    kFlatten,\n    kGetAppendBuffer,\n    kGetAppendRegion,\n    kMakeCordFromExternal,\n    kMoveAppendCord,\n    kMoveAssignCord,\n    kMovePrependCord,\n    kPrependCord,\n    kPrependCordBuffer,\n    kPrependString,\n    kRemovePrefix,\n    kRemoveSuffix,\n    kSetExpectedChecksum,\n    kSubCord,\n\n    // kNumMethods defines the number of entries: must be the last entry.\n    kNumMethods,\n  };\n\n  // Constructs a new instance. All counters are zero-initialized.\n  constexpr CordzUpdateTracker() noexcept : values_{} {}\n\n  // Copy constructs a new instance.\n  CordzUpdateTracker(const CordzUpdateTracker& rhs) noexcept { *this = rhs; }\n\n  // Assigns the provided value to this instance.\n  CordzUpdateTracker& operator=(const CordzUpdateTracker& rhs) noexcept {\n    for (int i = 0; i < kNumMethods; ++i) {\n      values_[i].store(rhs.values_[i].load(std::memory_order_relaxed),\n                       std::memory_order_relaxed);\n    }\n    return *this;\n  }\n\n  // Returns the value for the specified method.\n  int64_t Value(MethodIdentifier method) const {\n    return values_[method].load(std::memory_order_relaxed);\n  }\n\n  // Increases the value for the specified method by `n`\n  void LossyAdd(MethodIdentifier method, int64_t n = 1) {\n    auto& value = values_[method];\n    value.store(value.load(std::memory_order_relaxed) + n,\n                std::memory_order_relaxed);\n  }\n\n  // Adds all the values from `src` to this instance\n  void LossyAdd(const CordzUpdateTracker& src) {\n    for (int i = 0; i < kNumMethods; ++i) {\n      MethodIdentifier method = static_cast<MethodIdentifier>(i);\n      if (int64_t value = src.Value(method)) {\n        LossyAdd(method, value);\n      }\n    }\n  }\n\n private:\n  // Until C++20 std::atomic is not constexpr default-constructible, so we need\n  // a wrapper for this class to be constexpr constructible.\n  class Counter : public std::atomic<int64_t> {\n   public:\n    constexpr Counter() noexcept : std::atomic<int64_t>(0) {}\n  };\n\n  Counter values_[kNumMethods];\n};\n\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_\n"
  },
  {
    "path": "absl/strings/internal/cordz_update_tracker_test.cc",
    "content": "// Copyright 2021 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/cordz_update_tracker.h\"\n\n#include <array>\n#include <thread>  // NOLINT\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/synchronization/notification.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace cord_internal {\nnamespace {\n\nusing ::testing::AnyOf;\nusing ::testing::Eq;\n\nusing Method = CordzUpdateTracker::MethodIdentifier;\nusing Methods = std::array<Method, Method::kNumMethods>;\n\n// Returns an array of all methods defined in `MethodIdentifier`\nMethods AllMethods() {\n  return Methods{Method::kUnknown,\n                 Method::kAppendCord,\n                 Method::kAppendCordBuffer,\n                 Method::kAppendExternalMemory,\n                 Method::kAppendString,\n                 Method::kAssignCord,\n                 Method::kAssignString,\n                 Method::kClear,\n                 Method::kConstructorCord,\n                 Method::kConstructorString,\n                 Method::kCordReader,\n                 Method::kFlatten,\n                 Method::kGetAppendBuffer,\n                 Method::kGetAppendRegion,\n                 Method::kMakeCordFromExternal,\n                 Method::kMoveAppendCord,\n                 Method::kMoveAssignCord,\n                 Method::kMovePrependCord,\n                 Method::kPrependCord,\n                 Method::kPrependCordBuffer,\n                 Method::kPrependString,\n                 Method::kRemovePrefix,\n                 Method::kRemoveSuffix,\n                 Method::kSetExpectedChecksum,\n                 Method::kSubCord};\n}\n\nTEST(CordzUpdateTracker, IsConstExprAndInitializesToZero) {\n  constexpr CordzUpdateTracker tracker;\n  for (Method method : AllMethods()) {\n    ASSERT_THAT(tracker.Value(method), Eq(0));\n  }\n}\n\nTEST(CordzUpdateTracker, LossyAdd) {\n  int64_t n = 1;\n  CordzUpdateTracker tracker;\n  for (Method method : AllMethods()) {\n    tracker.LossyAdd(method, n);\n    EXPECT_THAT(tracker.Value(method), Eq(n));\n    n += 2;\n  }\n}\n\nTEST(CordzUpdateTracker, CopyConstructor) {\n  int64_t n = 1;\n  CordzUpdateTracker src;\n  for (Method method : AllMethods()) {\n    src.LossyAdd(method, n);\n    n += 2;\n  }\n\n  n = 1;\n  CordzUpdateTracker tracker(src);\n  for (Method method : AllMethods()) {\n    EXPECT_THAT(tracker.Value(method), Eq(n));\n    n += 2;\n  }\n}\n\nTEST(CordzUpdateTracker, OperatorAssign) {\n  int64_t n = 1;\n  CordzUpdateTracker src;\n  CordzUpdateTracker tracker;\n  for (Method method : AllMethods()) {\n    src.LossyAdd(method, n);\n    n += 2;\n  }\n\n  n = 1;\n  tracker = src;\n  for (Method method : AllMethods()) {\n    EXPECT_THAT(tracker.Value(method), Eq(n));\n    n += 2;\n  }\n}\n\nTEST(CordzUpdateTracker, ThreadSanitizedValueCheck) {\n  absl::Notification done;\n  CordzUpdateTracker tracker;\n\n  std::thread reader([&done, &tracker] {\n    while (!done.HasBeenNotified()) {\n      int n = 1;\n      for (Method method : AllMethods()) {\n        EXPECT_THAT(tracker.Value(method), AnyOf(Eq(n), Eq(0)));\n        n += 2;\n      }\n    }\n    int n = 1;\n    for (Method method : AllMethods()) {\n      EXPECT_THAT(tracker.Value(method), Eq(n));\n      n += 2;\n    }\n  });\n\n  int64_t n = 1;\n  for (Method method : AllMethods()) {\n    tracker.LossyAdd(method, n);\n    n += 2;\n  }\n  done.Notify();\n  reader.join();\n}\n\n}  // namespace\n}  // namespace cord_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/damerau_levenshtein_distance.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/damerau_levenshtein_distance.h\"\n\n#include <algorithm>\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <numeric>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n// Calculate DamerauLevenshtein (adjacent transpositions) distance\n// between two strings,\n// https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance. The\n// algorithm follows the condition that no substring is edited more than once.\n// While this can reduce is larger distance, it's a) a much simpler algorithm\n// and b) more realistic for the case that typographic mistakes should be\n// detected.\n// When the distance is larger than cutoff, or one of the strings has more\n// than MAX_SIZE=100 characters, the code returns min(MAX_SIZE, cutoff) + 1.\nuint8_t CappedDamerauLevenshteinDistance(absl::string_view s1,\n                                         absl::string_view s2, uint8_t cutoff) {\n  const uint8_t MAX_SIZE = 100;\n  const uint8_t _cutoff = std::min(MAX_SIZE, cutoff);\n  const uint8_t cutoff_plus_1 = static_cast<uint8_t>(_cutoff + 1);\n\n  if (s1.size() > s2.size()) std::swap(s1, s2);\n  if (s1.size() + _cutoff < s2.size() || s2.size() > MAX_SIZE)\n    return cutoff_plus_1;\n\n  if (s1.empty())\n    return static_cast<uint8_t>(s2.size());\n\n  // Lower diagonal bound: y = x - lower_diag\n  const uint8_t lower_diag =\n      _cutoff - static_cast<uint8_t>(s2.size() - s1.size());\n  // Upper diagonal bound: y = x + upper_diag\n  const uint8_t upper_diag = _cutoff;\n\n  // d[i][j] is the number of edits required to convert s1[0, i] to s2[0, j]\n  std::array<std::array<uint8_t, MAX_SIZE + 2>, MAX_SIZE + 2> d;\n  std::iota(d[0].begin(), d[0].begin() + upper_diag + 1, 0);\n  d[0][cutoff_plus_1] = cutoff_plus_1;\n  for (size_t i = 1; i <= s1.size(); ++i) {\n    // Deduce begin of relevant window.\n    size_t j_begin = 1;\n    if (i > lower_diag) {\n      j_begin = i - lower_diag;\n      d[i][j_begin - 1] = cutoff_plus_1;\n    } else {\n      d[i][0] = static_cast<uint8_t>(i);\n    }\n\n    // Deduce end of relevant window.\n    size_t j_end = i + upper_diag;\n    if (j_end > s2.size()) {\n      j_end = s2.size();\n    } else {\n      d[i][j_end + 1] = cutoff_plus_1;\n    }\n\n    for (size_t j = j_begin; j <= j_end; ++j) {\n      const uint8_t deletion_distance = d[i - 1][j] + 1;\n      const uint8_t insertion_distance = d[i][j - 1] + 1;\n      const uint8_t mismatched_tail_cost = s1[i - 1] == s2[j - 1] ? 0 : 1;\n      const uint8_t mismatch_distance = d[i - 1][j - 1] + mismatched_tail_cost;\n      uint8_t transposition_distance = _cutoff + 1;\n      if (i > 1 && j > 1 && s1[i - 1] == s2[j - 2] && s1[i - 2] == s2[j - 1])\n        transposition_distance = d[i - 2][j - 2] + 1;\n      d[i][j] = std::min({cutoff_plus_1, deletion_distance, insertion_distance,\n                          mismatch_distance, transposition_distance});\n    }\n  }\n  return d[s1.size()][s2.size()];\n}\n\n}  // namespace strings_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/damerau_levenshtein_distance.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_DAMERAU_LEVENSHTEIN_DISTANCE_H_\n#define ABSL_STRINGS_INTERNAL_DAMERAU_LEVENSHTEIN_DISTANCE_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n// Calculate DamerauLevenshtein distance between two strings.\n// When the distance is larger than cutoff, the code just returns cutoff + 1.\nuint8_t CappedDamerauLevenshteinDistance(absl::string_view s1,\n                                         absl::string_view s2, uint8_t cutoff);\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_DAMERAU_LEVENSHTEIN_DISTANCE_H_\n"
  },
  {
    "path": "absl/strings/internal/damerau_levenshtein_distance_benchmark.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n\n#include \"absl/strings/internal/damerau_levenshtein_distance.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nstd::string MakeTestString(int desired_length, int num_edits) {\n  std::string test(desired_length, 'x');\n  for (int i = 0; (i < num_edits) && (i * 8 < desired_length); ++i) {\n    test[i * 8] = 'y';\n  }\n  return test;\n}\n\nvoid BenchmarkArgs(benchmark::internal::Benchmark* benchmark) {\n  // Each column is 8 bytes.\n  const auto string_size = {1, 8, 64, 100};\n  const auto num_edits = {1, 2, 16, 16, 64, 80};\n  const auto distance_cap = {1, 2, 3, 16, 64, 80};\n  for (const int s : string_size) {\n    for (const int n : num_edits) {\n      for (const int d : distance_cap) {\n        if (n > s) continue;\n        benchmark->Args({s, n, d});\n      }\n    }\n  }\n}\n\nusing absl::strings_internal::CappedDamerauLevenshteinDistance;\nvoid BM_Distance(benchmark::State& state) {\n  std::string s1 = MakeTestString(state.range(0), 0);\n  std::string s2 = MakeTestString(state.range(0), state.range(1));\n  const size_t cap = state.range(2);\n  for (auto _ : state) {\n    CappedDamerauLevenshteinDistance(s1, s2, cap);\n  }\n}\nBENCHMARK(BM_Distance)->Apply(BenchmarkArgs);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/damerau_levenshtein_distance_test.cc",
    "content": "// Copyright 2022 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/damerau_levenshtein_distance.h\"\n\n#include <cstdint>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing absl::strings_internal::CappedDamerauLevenshteinDistance;\n\nTEST(Distance, TestDistances) {\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"ab\", \"ab\", 6), uint8_t{0});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"a\", \"b\", 6), uint8_t{1});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"ca\", \"abc\", 6), uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcd\", \"ad\", 6), uint8_t{2});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcd\", \"cadb\", 6), uint8_t{4});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcd\", \"bdac\", 6), uint8_t{4});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"ab\", \"ab\", 0), uint8_t{0});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"\", \"\", 0), uint8_t{0});\n  // combinations for 3-character strings:\n  // 1, 2, 3 removals, insertions or replacements and transpositions\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abc\", \"abc\", 6), uint8_t{0});\n  for (auto res :\n       {\"\", \"ca\", \"efg\", \"ea\", \"ce\", \"ceb\", \"eca\", \"cae\", \"cea\", \"bea\"}) {\n    EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abc\", res, 6), uint8_t{3});\n    EXPECT_THAT(CappedDamerauLevenshteinDistance(res, \"abc\", 6), uint8_t{3});\n  }\n  for (auto res :\n       {\"a\",   \"b\",   \"c\",   \"ba\",  \"cb\",  \"bca\", \"cab\", \"cba\", \"ace\",\n        \"efc\", \"ebf\", \"aef\", \"ae\",  \"be\",  \"eb\",  \"ec\",  \"ecb\", \"bec\",\n        \"bce\", \"cbe\", \"ace\", \"eac\", \"aeb\", \"bae\", \"eab\", \"eba\"}) {\n    EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abc\", res, 6), uint8_t{2});\n    EXPECT_THAT(CappedDamerauLevenshteinDistance(res, \"abc\", 6), uint8_t{2});\n  }\n  for (auto res : {\"ab\", \"ac\", \"bc\", \"acb\", \"bac\", \"ebc\", \"aec\", \"abe\"}) {\n    EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abc\", res, 6), uint8_t{1});\n    EXPECT_THAT(CappedDamerauLevenshteinDistance(res, \"abc\", 6), uint8_t{1});\n  }\n}\n\nTEST(Distance, TestCutoff) {\n  // Returning cutoff + 1 if the value is larger than cutoff or string longer\n  // than MAX_SIZE.\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcd\", \"a\", 3), uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcd\", \"a\", 2), uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcd\", \"a\", 1), uint8_t{2});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"abcdefg\", \"a\", 2), uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(\"a\", \"abcde\", 2), uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(102, 'a'),\n                                               std::string(102, 'a'), 105),\n              uint8_t{101});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(100, 'a'),\n                                               std::string(100, 'a'), 100),\n              uint8_t{0});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(100, 'a'),\n                                               std::string(100, 'b'), 100),\n              uint8_t{100});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(100, 'a'),\n                                               std::string(99, 'a'), 2),\n              uint8_t{1});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(100, 'a'),\n                                               std::string(101, 'a'), 2),\n              uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(100, 'a'),\n                                               std::string(101, 'a'), 2),\n              uint8_t{3});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(UINT8_MAX + 1, 'a'),\n                                               std::string(UINT8_MAX + 1, 'b'),\n                                               UINT8_MAX),\n              uint8_t{101});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(UINT8_MAX - 1, 'a'),\n                                               std::string(UINT8_MAX - 1, 'b'),\n                                               UINT8_MAX),\n              uint8_t{101});\n  EXPECT_THAT(\n      CappedDamerauLevenshteinDistance(std::string(UINT8_MAX, 'a'),\n                                       std::string(UINT8_MAX, 'b'), UINT8_MAX),\n      uint8_t{101});\n  EXPECT_THAT(CappedDamerauLevenshteinDistance(std::string(UINT8_MAX - 1, 'a'),\n                                               std::string(UINT8_MAX - 1, 'a'),\n                                               UINT8_MAX),\n              uint8_t{101});\n}\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/escaping.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/escaping.h\"\n\n#include <limits>\n\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// The two strings below provide maps from normal 6-bit characters to their\n// base64-escaped equivalent.\n// For the inverse case, see kUn(WebSafe)Base64 in the external\n// escaping.cc.\nABSL_CONST_INIT const char kBase64Chars[] =\n    \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nABSL_CONST_INIT const char kWebSafeBase64Chars[] =\n    \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\nsize_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {\n  // Base64 encodes three bytes of input at a time. If the input is not\n  // divisible by three, we pad as appropriate.\n  //\n  // Base64 encodes each three bytes of input into four bytes of output.\n  constexpr size_t kMaxSize = (std::numeric_limits<size_t>::max() - 1) / 4 * 3;\n  ABSL_INTERNAL_CHECK(input_len <= kMaxSize,\n                      \"CalculateBase64EscapedLenInternal() overflow\");\n  size_t len = (input_len / 3) * 4;\n\n  // Since all base 64 input is an integral number of octets, only the following\n  // cases can arise:\n  if (input_len % 3 == 0) {\n    // (from https://tools.ietf.org/html/rfc3548)\n    // (1) the final quantum of encoding input is an integral multiple of 24\n    // bits; here, the final unit of encoded output will be an integral\n    // multiple of 4 characters with no \"=\" padding,\n  } else if (input_len % 3 == 1) {\n    // (from https://tools.ietf.org/html/rfc3548)\n    // (2) the final quantum of encoding input is exactly 8 bits; here, the\n    // final unit of encoded output will be two characters followed by two\n    // \"=\" padding characters, or\n    len += 2;\n    if (do_padding) {\n      len += 2;\n    }\n  } else {  // (input_len % 3 == 2)\n    // (from https://tools.ietf.org/html/rfc3548)\n    // (3) the final quantum of encoding input is exactly 16 bits; here, the\n    // final unit of encoded output will be three characters followed by one\n    // \"=\" padding character.\n    len += 3;\n    if (do_padding) {\n      len += 1;\n    }\n  }\n\n  return len;\n}\n\n// ----------------------------------------------------------------------\n//   Take the input in groups of 4 characters and turn each\n//   character into a code 0 to 63 thus:\n//           A-Z map to 0 to 25\n//           a-z map to 26 to 51\n//           0-9 map to 52 to 61\n//           +(- for WebSafe) maps to 62\n//           /(_ for WebSafe) maps to 63\n//   There will be four numbers, all less than 64 which can be represented\n//   by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).\n//   Arrange the 6 digit binary numbers into three bytes as such:\n//   aaaaaabb bbbbcccc ccdddddd\n//   Equals signs (one or two) are used at the end of the encoded block to\n//   indicate that the text was not an integer multiple of three bytes long.\n// ----------------------------------------------------------------------\nsize_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,\n                            size_t szdest, const char* base64,\n                            bool do_padding) {\n  static const char kPad64 = '=';\n\n  if (szsrc * 4 > szdest * 3) return 0;\n\n  char* cur_dest = dest;\n  const unsigned char* cur_src = src;\n\n  char* const limit_dest = dest + szdest;\n  const unsigned char* const limit_src = src + szsrc;\n\n  // (from https://tools.ietf.org/html/rfc3548)\n  // Special processing is performed if fewer than 24 bits are available\n  // at the end of the data being encoded.  A full encoding quantum is\n  // always completed at the end of a quantity.  When fewer than 24 input\n  // bits are available in an input group, zero bits are added (on the\n  // right) to form an integral number of 6-bit groups.\n  //\n  // If do_padding is true, padding at the end of the data is performed. This\n  // output padding uses the '=' character.\n\n  // Three bytes of data encodes to four characters of cyphertext.\n  // So we can pump through three-byte chunks atomically.\n  if (szsrc >= 3) {                    // \"limit_src - 3\" is UB if szsrc < 3.\n    while (cur_src < limit_src - 3) {  // While we have >= 32 bits.\n      uint32_t in = absl::big_endian::Load32(cur_src) >> 8;\n\n      cur_dest[0] = base64[in >> 18];\n      in &= 0x3FFFF;\n      cur_dest[1] = base64[in >> 12];\n      in &= 0xFFF;\n      cur_dest[2] = base64[in >> 6];\n      in &= 0x3F;\n      cur_dest[3] = base64[in];\n\n      cur_dest += 4;\n      cur_src += 3;\n    }\n  }\n  // To save time, we didn't update szdest or szsrc in the loop.  So do it now.\n  szdest = static_cast<size_t>(limit_dest - cur_dest);\n  szsrc = static_cast<size_t>(limit_src - cur_src);\n\n  /* now deal with the tail (<=3 bytes) */\n  switch (szsrc) {\n    case 0:\n      // Nothing left; nothing more to do.\n      break;\n    case 1: {\n      // One byte left: this encodes to two characters, and (optionally)\n      // two pad characters to round out the four-character cypherblock.\n      if (szdest < 2) return 0;\n      uint32_t in = cur_src[0];\n      cur_dest[0] = base64[in >> 2];\n      in &= 0x3;\n      cur_dest[1] = base64[in << 4];\n      cur_dest += 2;\n      szdest -= 2;\n      if (do_padding) {\n        if (szdest < 2) return 0;\n        cur_dest[0] = kPad64;\n        cur_dest[1] = kPad64;\n        cur_dest += 2;\n        szdest -= 2;\n      }\n      break;\n    }\n    case 2: {\n      // Two bytes left: this encodes to three characters, and (optionally)\n      // one pad character to round out the four-character cypherblock.\n      if (szdest < 3) return 0;\n      uint32_t in = absl::big_endian::Load16(cur_src);\n      cur_dest[0] = base64[in >> 10];\n      in &= 0x3FF;\n      cur_dest[1] = base64[in >> 4];\n      in &= 0x00F;\n      cur_dest[2] = base64[in << 2];\n      cur_dest += 3;\n      szdest -= 3;\n      if (do_padding) {\n        if (szdest < 1) return 0;\n        cur_dest[0] = kPad64;\n        cur_dest += 1;\n        szdest -= 1;\n      }\n      break;\n    }\n    case 3: {\n      // Three bytes left: same as in the big loop above.  We can't do this in\n      // the loop because the loop above always reads 4 bytes, and the fourth\n      // byte is past the end of the input.\n      if (szdest < 4) return 0;\n      uint32_t in =\n          (uint32_t{cur_src[0]} << 16) + absl::big_endian::Load16(cur_src + 1);\n      cur_dest[0] = base64[in >> 18];\n      in &= 0x3FFFF;\n      cur_dest[1] = base64[in >> 12];\n      in &= 0xFFF;\n      cur_dest[2] = base64[in >> 6];\n      in &= 0x3F;\n      cur_dest[3] = base64[in];\n      cur_dest += 4;\n      szdest -= 4;\n      break;\n    }\n    default:\n      // Should not be reached: blocks of 4 bytes are handled\n      // in the while loop before this switch statement.\n      ABSL_RAW_LOG(FATAL, \"Logic problem? szsrc = %zu\", szsrc);\n      break;\n  }\n  return static_cast<size_t>(cur_dest - dest);\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/escaping.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_H_\n#define ABSL_STRINGS_INTERNAL_ESCAPING_H_\n\n#include <cassert>\n\n#include \"absl/strings/resize_and_overwrite.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nABSL_CONST_INIT extern const char kBase64Chars[];\nABSL_CONST_INIT extern const char kWebSafeBase64Chars[];\n\n// Calculates the length of a Base64 encoding (RFC 4648) of a string of length\n// `input_len`, with or without padding per `do_padding`. Note that 'web-safe'\n// encoding (section 5 of the RFC) does not change this length.\nsize_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding);\n\n// Base64-encodes `src` using the alphabet provided in `base64` (which\n// determines whether to do web-safe encoding or not) and writes the result to\n// `dest`. If `do_padding` is true, `dest` is padded with '=' chars until its\n// length is a multiple of 3. Returns the length of `dest`.\nsize_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,\n                            size_t szdest, const char* base64, bool do_padding);\ntemplate <typename String>\nvoid Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,\n                          bool do_padding, const char* base64_chars) {\n  const size_t calc_escaped_size =\n      CalculateBase64EscapedLenInternal(szsrc, do_padding);\n  StringResizeAndOverwrite(\n      *dest, calc_escaped_size,\n      [src, szsrc, base64_chars, do_padding](char* buf, size_t buf_size) {\n        const size_t escaped_len = Base64EscapeInternal(\n            src, szsrc, buf, buf_size, base64_chars, do_padding);\n        assert(escaped_len == buf_size);\n        return escaped_len;\n      });\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_ESCAPING_H_\n"
  },
  {
    "path": "absl/strings/internal/escaping_test_common.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This test contains common things needed by both escaping_test.cc and\n// escaping_benchmark.cc.\n\n#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_\n#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_\n\n#include <array>\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nstruct base64_testcase {\n  absl::string_view plaintext;\n  absl::string_view cyphertext;\n};\n\ninline const std::array<base64_testcase, 5>& base64_strings() {\n  static const std::array<base64_testcase, 5> testcase{{\n      // Some google quotes\n      // Cyphertext created with \"uuencode (GNU sharutils) 4.6.3\"\n      // (Note that we're testing the websafe encoding, though, so if\n      // you add messages, be sure to run \"tr -- '+/' '-_'\" on the output)\n      { \"I was always good at math and science, and I never realized \"\n        \"that was unusual or somehow undesirable. So one of the things \"\n        \"I care a lot about is helping to remove that stigma, \"\n        \"to show girls that you can be feminine, you can like the things \"\n        \"that girls like, but you can also be really good at technology. \"\n        \"You can be really good at building things.\"\n        \" - Marissa Meyer, Newsweek, 2010-12-22\" \"\\n\",\n\n        \"SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg\"\n        \"bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu\"\n        \"ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg\"\n        \"YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo\"\n        \"b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp\"\n        \"a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs\"\n        \"c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy\"\n        \"ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll\"\n        \"ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK\" },\n\n      { \"Typical first year for a new cluster: \"\n        \"~0.5 overheating \"\n        \"~1 PDU failure \"\n        \"~1 rack-move \"\n        \"~1 network rewiring \"\n        \"~20 rack failures \"\n        \"~5 racks go wonky \"\n        \"~8 network maintenances \"\n        \"~12 router reloads \"\n        \"~3 router failures \"\n        \"~dozens of minor 30-second blips for dns \"\n        \"~1000 individual machine failures \"\n        \"~thousands of hard drive failures \"\n        \"slow disks, bad memory, misconfigured machines, flaky machines, etc.\"\n        \" - Jeff Dean, The Joys of Real Hardware\" \"\\n\",\n\n        \"VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92\"\n        \"ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3\"\n        \"b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv\"\n        \"bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk\"\n        \"cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv\"\n        \"bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp\"\n        \"bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg\"\n        \"ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs\"\n        \"YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS\"\n        \"ZWFsIEhhcmR3YXJlCg\" },\n\n      { \"I'm the head of the webspam team at Google.  \"\n        \"That means that if you type your name into Google and get porn back, \"\n        \"it's my fault. Unless you're a porn star, in which case porn is a \"\n        \"completely reasonable response.\"\n        \" - Matt Cutts, Google Plus\" \"\\n\",\n\n        \"SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg\"\n        \"VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv\"\n        \"b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz\"\n        \"IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg\"\n        \"Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs\"\n        \"IEdvb2dsZSBQbHVzCg\" },\n\n      { \"It will still be a long time before machines approach human \"\n        \"intelligence. \"\n        \"But luckily, machines don't actually have to be intelligent; \"\n        \"they just have to fake it. Access to a wealth of information, \"\n        \"combined with a rudimentary decision-making capacity, \"\n        \"can often be almost as useful. Of course, the results are better yet \"\n        \"when coupled with intelligence. A reference librarian with access to \"\n        \"a good search engine is a formidable tool.\"\n        \" - Craig Silverstein, Siemens Pictures of the Future, Spring 2004\"\n        \"\\n\",\n\n        \"SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg\"\n        \"YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj\"\n        \"aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg\"\n        \"dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo\"\n        \"IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg\"\n        \"ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0\"\n        \"IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy\"\n        \"IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl\"\n        \"bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu\"\n        \"Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp\"\n        \"biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw\"\n        \"NAo\" },\n\n      // Degenerate edge case\n      { \"\",\n        \"\" },\n  }};\n\n  return testcase;\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_\n"
  },
  {
    "path": "absl/strings/internal/generic_printer.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/generic_printer.h\"\n\n#include <cstddef>\n#include <cstdlib>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace internal_generic_printer {\n\n// Out-of-line helper for PrintAsStringWithEscaping.\nstd::ostream& PrintEscapedString(std::ostream& os, absl::string_view v) {\n  return os << \"\\\"\" << absl::CHexEscape(v) << \"\\\"\";\n}\n\n// Retuns a string representation of 'v', shortened if possible.\ntemplate <class T, class F>\nstd::string TryShorten(T v, F strtox) {\n  std::string printed =\n      absl::StrFormat(\"%.*g\", std::numeric_limits<T>::max_digits10 / 2, v);\n  T parsed = strtox(printed.data());\n  if (parsed != v) {\n    printed =\n        absl::StrFormat(\"%.*g\", std::numeric_limits<T>::max_digits10 + 1, v);\n  }\n  return printed;\n}\n\n// Out-of-line helpers for floating point values. These don't necessarily\n// ensure that values are precise, but rather that they are wide enough to\n// represent distinct values. go/c++17std/numeric.limits.members.html\nstd::ostream& PrintPreciseFP(std::ostream& os, float v) {\n  return os << TryShorten(v, [](const char* buf) {\n           char* unused;\n           return std::strtof(buf, &unused);\n         }) << \"f\";\n}\nstd::ostream& PrintPreciseFP(std::ostream& os, double v) {\n  return os << TryShorten(v, [](const char* buf) {\n           char* unused;\n           return std::strtod(buf, &unused);\n         });\n}\nstd::ostream& PrintPreciseFP(std::ostream& os, long double v) {\n  return os << TryShorten(v, [](const char* buf) {\n           char* unused;\n           return std::strtold(buf, &unused);\n         }) << \"L\";\n}\n\n// Prints a nibble of 'v' in hexadecimal.\ninline char hexnib(int v) {\n  return static_cast<char>((v < 10 ? '0' : ('a' - 10)) + v);\n}\n\ntemplate <typename T>\nstatic std::ostream& PrintCharImpl(std::ostream& os, T v) {\n  // Specialization for chars: print as 'c' if printable, otherwise\n  // hex-escaped.\n  return (absl::ascii_isprint(static_cast<unsigned char>(v))\n              ? (os << (v == '\\'' ? \"'\\\\\" : \"'\") << v)\n              : (os << \"'\\\\x\" << hexnib((v >> 4) & 0xf) << hexnib(v & 0xf)))\n         << \"' (0x\" << hexnib((v >> 4) & 0xf) << hexnib(v & 0xf) << \" \"\n         << static_cast<int>(v) << \")\";\n}\n\nstd::ostream& PrintChar(std::ostream& os, char c) {\n  return PrintCharImpl(os, c);\n}\n\nstd::ostream& PrintChar(std::ostream& os, signed char c) {\n  return PrintCharImpl(os, c);\n}\n\nstd::ostream& PrintChar(std::ostream& os, unsigned char c) {\n  return PrintCharImpl(os, c);\n}\n\nstd::ostream& PrintByte(std::ostream& os, std::byte b) {\n  auto v = std::to_integer<int>(b);\n  os << \"0x\" << hexnib((v >> 4) & 0xf) << hexnib(v & 0xf);\n  return os;\n}\n\n}  // namespace internal_generic_printer\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/generic_printer.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_GENERIC_PRINTER_H_\n#define ABSL_STRINGS_INTERNAL_GENERIC_PRINTER_H_\n\n#include \"absl/strings/internal/generic_printer_internal.h\"  // IWYU pragma: export\n\n// Helpers for printing objects in generic code.\n//\n// These functions help with streaming in generic code. It may be desirable, for\n// example, to log values from generic functions; however, operator<< may not be\n// overloaded for all types.\n//\n// The helpers in this library use, in order of precedence:\n//\n//  1. std::string and std::string_view are quoted and escaped. (The specific\n//     format is not guaranteed to be stable.)\n//  2. A defined AbslStringify() method.\n//  3. absl::log_internal::LogContainer, if the object is a STL container.\n//  4. For std::tuple, std::pair, and std::optional, recursively calls\n//     GenericPrint for each element.\n//  5. Floating point values are printed with enough precision for round-trip.\n//  6. char values are quoted, with non-printable values escaped, and the\n//     char's numeric value is included.\n//  7. A defined operator<< overload (which should be found by ADL).\n//  8. A defined DebugString() const method.\n//  9. A fallback value with basic information otherwise.\n//\n// Note that the fallback value means that if no formatting conversion is\n// defined, you will not see a compile-time error. This also means that\n// GenericPrint() can safely be used in generic template contexts, and can\n// format any types needed (even though the output will vary).\n//\n// Example usage:\n//\n//   // All values after GenericPrint() are formatted:\n//   LOG(INFO) << GenericPrint()\n//             << int_var         // <- printed normally\n//             << float_var       // <- sufficient precision for round-trip\n//             << \" unchanged literal text \";\n//\n//   // Just one value is formatted:\n//   LOG(INFO) << GenericPrint(string(\"this is quoted and escaped\\t\\n\"))\n//             << GenericPrint(\"but not this, \");\n//             << string(\"and not this.\");\n//\n// To make a type loggable with GenericPrint, prefer defining operator<< as a\n// friend function. For example:\n//\n//   class TypeToLog {\n//    public:\n//     string ToString() const;  // Many types already implement this.\n//                               // Define out-of-line if it is complex.\n//     friend std::ostream& operator<<(std::ostream& os, const TypeToLog& v) {\n//       return os << v.ToString();  // OK to define in-line instead, if simple.\n//     }\n//   };\n//\n// (Defining operator<< as an inline friend free function allows it to be found\n// by Argument-Dependent Lookup, or ADL, which is the mechanism typically used\n// for operator overload resolution. An inline friend function is the tightest\n// scope possible for overloading the left-hand side of an operator.)\n\n#include <ostream>\n#include <utility>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// Helper for logging values in generic code.\n//\n// Example usage:\n//\n//   template <typename T>\n//   void GenericFunction() {\n//     T v1, v2;\n//     VLOG(1) << GenericPrint() << v1 << v2;  // GenericPrint everything\n//     VLOG(1) << GenericPrint(v1) << v2;  // GenericPrint just v1\n//   }\n//\ninline constexpr internal_generic_printer::GenericPrintAdapterFactory\n    GenericPrint{};\n\n// Generic printer type: this class can be used, for example, as a template\n// argument to allow users to provide alternative printing strategies.\n//\n// For example, to allow callers to provide a custom strategy:\n//\n//   template <typename T, typename PrinterT = GenericPrinter<T>>\n//   void GenericFunction() {\n//     T value;\n//     VLOG(1) << PrinterT{value};\n//   }\n//\ntemplate <typename T>\nusing GenericPrinter = internal_generic_printer::GenericPrinter<T>;\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_GENERIC_PRINTER_H_\n"
  },
  {
    "path": "absl/strings/internal/generic_printer_internal.h",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_GENERIC_PRINTER_INTERNAL_H_\n#define ABSL_STRINGS_INTERNAL_GENERIC_PRINTER_INTERNAL_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <optional>\n#include <ostream>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <variant>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/log/internal/container.h\"\n#include \"absl/meta/internal/requires.h\"\n#include \"absl/strings/has_absl_stringify.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\n// NOTE: we do not want to expand the dependencies of this library. All\n// compatibility detection must be done in a generic way, without having to\n// include the headers of other libraries.\n\n// Internal implementation details: see generic_printer.h.\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace internal_generic_printer {\n\ntemplate <typename T>\nstd::ostream& GenericPrintImpl(std::ostream& os, const T& v);\n\n// Scope blocker: we must always use ADL in our predicates below.\nstruct Anonymous;\nstd::ostream& operator<<(const Anonymous&, const Anonymous&) = delete;\n\n// Logging policy for LogContainer. Our SFINAE overload will not fail\n// if the contained type cannot be printed, so make sure to circle back to\n// GenericPrinter.\nstruct ContainerLogPolicy {\n  void LogOpening(std::ostream& os) const { os << \"[\"; }\n  void LogClosing(std::ostream& os) const { os << \"]\"; }\n  void LogFirstSeparator(std::ostream& os) const { os << \"\"; }\n  void LogSeparator(std::ostream& os) const { os << \", \"; }\n  int64_t MaxElements() const { return 15; }\n  template <typename T>\n  void Log(std::ostream& os, const T& element) const {\n    internal_generic_printer::GenericPrintImpl(os, element);\n  }\n  void LogEllipsis(std::ostream& os) const { os << \"...\"; }\n};\n\n// Out-of-line helper for PrintAsStringWithEscaping.\nstd::ostream& PrintEscapedString(std::ostream& os, absl::string_view v);\n\n// Trait to recognize a string, possibly with a custom allocator.\ntemplate <class T>\ninline constexpr bool is_any_string = false;\ntemplate <class A>\ninline constexpr bool\n    is_any_string<std::basic_string<char, std::char_traits<char>, A>> = true;\n\n// Trait to recognize a supported pointer. Below are documented reasons why\n// raw pointers and std::shared_ptr are not currently supported.\n// See also http://b/239459272#comment9 and the discussion in the comment\n// threads of cl/485200996.\n//\n// The tl;dr:\n// 1. Pointers that logically represent an object (or nullptr) are safe to print\n//    out.\n// 2. Pointers that may represent some other concept (delineating memory bounds,\n//    overridden managed-memory deleters to mimic RAII, ...) may be unsafe to\n//    print out.\n//\n// raw pointers:\n//  - A pointer one-past the last element of an array\n//  - Non-null but non-dereferenceable: https://gcc.godbolt.org/z/sqsqGvKbP\n//\n// `std::shared_ptr`:\n//  - \"Aliasing\" / similar to raw pointers: https://gcc.godbolt.org/z/YbWPzvhae\ntemplate <class T, class = void>\ninline constexpr bool is_supported_ptr = false;\n// `std::unique_ptr` has the same theoretical risks as raw pointers, but those\n// risks are far less likely (typically requiring a custom deleter), and the\n// benefits of supporting unique_ptr outweigh the costs.\n//  - Note: `std::unique_ptr<T[]>` cannot safely be and is not dereferenced.\ntemplate <class A, class... Deleter>\ninline constexpr bool is_supported_ptr<std::unique_ptr<A, Deleter...>> = true;\n// `ArenaSafeUniquePtr` is at least as safe as `std::unique_ptr`.\ntemplate <class T>\ninline constexpr bool is_supported_ptr<\n    T,\n    // Check for `ArenaSafeUniquePtr` without having to include its header here.\n    // This does match any type named `ArenaSafeUniquePtr`, regardless of the\n    // namespace it is defined in, but it's pretty plausible that any such type\n    // would be a fork.\n    decltype(T().~ArenaSafeUniquePtr())> = true;\n\n// `proto2::Arena::UniquePtr` is at least as safe as `std::unique_ptr`.\ntemplate <class T>\ninline constexpr bool is_supported_ptr<\n    T,\n    // Check for `proto2::Arena::UniquePtr` without having to include its\n    // header here. This does match any type named `UniquePtr`, regardless\n    // of the scope it is defined in, but we try to restrict by probing some\n    // methods.\n    std::void_t<decltype(\n        // Check the class name using the destructor.\n        T().~UniquePtr(),\n        // Check some other members, to try to duck type into the right class.\n        T().get(), T().reset(), T().try_heap_release(),\n        T().GetOwningArena()\n            ->template MakeUnique<int>(nullptr)\n            .~UniquePtr())>> = true;\n\n// Specialization for floats: print floating point types using their\n// max_digits10 precision. This ensures each distinct underlying values\n// can be represented uniquely, even though it's not (strictly speaking)\n// the most precise representation.\nstd::ostream& PrintPreciseFP(std::ostream& os, float v);\nstd::ostream& PrintPreciseFP(std::ostream& os, double v);\nstd::ostream& PrintPreciseFP(std::ostream& os, long double v);\n\nstd::ostream& PrintChar(std::ostream& os, char c);\nstd::ostream& PrintChar(std::ostream& os, signed char c);\nstd::ostream& PrintChar(std::ostream& os, unsigned char c);\n\nstd::ostream& PrintByte(std::ostream& os, std::byte b);\n\ntemplate <class... Ts>\nstd::ostream& PrintTuple(std::ostream& os, const std::tuple<Ts...>& tuple) {\n  absl::string_view sep = \"\";\n  const auto print_one = [&](const auto& v) {\n    os << sep;\n    (GenericPrintImpl)(os, v);\n    sep = \", \";\n  };\n  os << \"<\";\n  std::apply([&](const auto&... v) { (print_one(v), ...); }, tuple);\n  os << \">\";\n  return os;\n}\n\ntemplate <typename T, typename U>\nstd::ostream& PrintPair(std::ostream& os, const std::pair<T, U>& p) {\n  os << \"<\";\n  (GenericPrintImpl)(os, p.first);\n  os << \", \";\n  (GenericPrintImpl)(os, p.second);\n  os << \">\";\n  return os;\n}\n\ntemplate <typename T>\nstd::ostream& PrintOptionalLike(std::ostream& os, const T& v) {\n  if (v.has_value()) {\n    os << \"<\";\n    (GenericPrintImpl)(os, *v);\n    os << \">\";\n  } else {\n    (GenericPrintImpl)(os, std::nullopt);\n  }\n  return os;\n}\n\ntemplate <typename... Ts>\nstd::ostream& PrintVariant(std::ostream& os, const std::variant<Ts...>& v) {\n  os << \"(\";\n  os << \"'(index = \" << v.index() << \")' \";\n\n  // NOTE(derekbailey): This may throw a std::bad_variant_access if the variant\n  // is \"valueless\", which only occurs if exceptions are thrown. This is\n  // non-relevant when not using exceptions, but it is worth mentioning if that\n  // invariant is ever changed.\n  std::visit([&](const auto& arg) { (GenericPrintImpl)(os, arg); }, v);\n  os << \")\";\n  return os;\n}\n\ntemplate <typename StatusOrLike>\nstd::ostream& PrintStatusOrLike(std::ostream& os, const StatusOrLike& v) {\n  os << \"<\";\n  if (v.ok()) {\n    os << \"OK: \";\n    (GenericPrintImpl)(os, *v);\n  } else {\n    (GenericPrintImpl)(os, v.status());\n  }\n  os << \">\";\n  return os;\n}\n\ntemplate <typename SmartPointer>\nstd::ostream& PrintSmartPointerContents(std::ostream& os,\n                                        const SmartPointer& v) {\n  os << \"<\";\n  if (v == nullptr) {\n    (GenericPrintImpl)(os, nullptr);\n  } else {\n    // Cast to void* so that every type (e.g. `char*`) is printed as an address.\n    os << absl::implicit_cast<const void*>(v.get()) << \" pointing to \";\n\n    if constexpr (meta_internal::Requires<SmartPointer>(\n                      [](auto&& p) -> decltype(p[0]) {})) {\n      // e.g. std::unique_ptr<int[]>, which only has operator[]\n      os << \"an array\";\n    } else if constexpr (std::is_object_v<\n                             typename SmartPointer::element_type>) {\n      (GenericPrintImpl)(os, *v);\n    } else {\n      // e.g. std::unique_ptr<void, MyCustomDeleter>\n      os << \"a non-object type\";\n    }\n  }\n  os << \">\";\n  return os;\n}\n\ntemplate <typename T>\nstd::ostream& GenericPrintImpl(std::ostream& os, const T& v) {\n  if constexpr (is_any_string<T> || std::is_same_v<T, absl::string_view>) {\n    // Specialization for strings: prints with plausible quoting and escaping.\n    return PrintEscapedString(os, v);\n  } else if constexpr (is_supported_ptr<T>) {\n    return (PrintSmartPointerContents)(os, v);\n  } else if constexpr (absl::HasAbslStringify<T>::value) {\n    // If someone has specified `AbslStringify`, we should prefer that.\n    return os << absl::StrCat(v);\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype((\n                                   PrintTuple)(std::declval<std::ostream&>(),\n                                               w)) {})) {\n    // For tuples, use `< elem0, ..., elemN >`.\n    return (PrintTuple)(os, v);\n\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype((\n                                   PrintPair)(std::declval<std::ostream&>(),\n                                              w)) {})) {\n    // For pairs, use `< first, second >`.\n    return (PrintPair)(os, v);\n\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype((\n                                   PrintVariant)(std::declval<std::ostream&>(),\n                                                 w)) {})) {\n    // For std::variant, use `std::visit(v)`\n    return (PrintVariant)(os, v);\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w) -> decltype(w.ok(), w.status(), *w) {\n                           })) {\n    return (PrintStatusOrLike)(os, v);\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w) -> decltype(w.has_value(), *w) {})) {\n    return (PrintOptionalLike)(os, v);\n  } else if constexpr (std::is_same_v<T, std::nullopt_t>) {\n    // Specialization for nullopt.\n    return os << \"nullopt\";\n\n  } else if constexpr (std::is_same_v<T, std::nullptr_t>) {\n    // Specialization for nullptr.\n    return os << \"nullptr\";\n\n  } else if constexpr (std::is_floating_point_v<T>) {\n    // For floating point print with enough precision for a roundtrip.\n    return PrintPreciseFP(os, v);\n\n  } else if constexpr (std::is_same_v<T, char> ||\n                       std::is_same_v<T, signed char> ||\n                       std::is_same_v<T, unsigned char>) {\n    // Chars are printed as the char (if a printable char) and the integral\n    // representation in hex and decimal.\n    return PrintChar(os, v);\n\n  } else if constexpr (std::is_same_v<T, std::byte>) {\n    return PrintByte(os, v);\n\n  } else if constexpr (std::is_same_v<T, bool> ||\n                       std::is_same_v<T,\n                                      typename std::vector<bool>::reference> ||\n                       std::is_same_v<\n                           T, typename std::vector<bool>::const_reference>) {\n    return os << (v ? \"true\" : \"false\");\n\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype(ProtobufInternalGetEnumDescriptor(\n                                   w)) {})) {\n    os << static_cast<std::underlying_type_t<T>>(v);\n    if (auto* desc =\n            ProtobufInternalGetEnumDescriptor(T{})->FindValueByNumber(v)) {\n      os << \"(\" << desc->name() << \")\";\n    }\n    return os;\n  } else if constexpr (!std::is_enum_v<T> &&\n                       meta_internal::Requires<const T>(\n                           [&](auto&& w) -> decltype(absl::StrCat(w)) {})) {\n    return os << absl::StrCat(v);\n\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype(std::declval<std::ostream&>()\n                                           << log_internal::LogContainer(w)) {\n                           })) {\n    // For containers, use `[ elem0, ..., elemN ]` with a max of 15.\n    return os << log_internal::LogContainer(v, ContainerLogPolicy());\n\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype(std::declval<std::ostream&>() << w) {\n                           })) {\n    // Streaming\n    return os << v;\n\n  } else if constexpr (meta_internal::Requires<const T>(\n                           [&](auto&& w)\n                               -> decltype(std::declval<std::ostream&>()\n                                           << w.DebugString()) {})) {\n    // DebugString\n    return os << v.DebugString();\n\n  } else if constexpr (std::is_enum_v<T>) {\n    // In case the underlying type is some kind of char, we have to recurse.\n    return GenericPrintImpl(os, static_cast<std::underlying_type_t<T>>(v));\n\n  } else {\n    // Default: we don't have anything to stream the value.\n    return os << \"[unprintable value of size \" << sizeof(T) << \" @\" << &v\n              << \"]\";\n  }\n}\n\n// GenericPrinter always has a valid operator<<. It defers to the disjuction\n// above.\ntemplate <typename T>\nclass GenericPrinter {\n public:\n  explicit GenericPrinter(const T& value) : value_(value) {}\n\n private:\n  friend std::ostream& operator<<(std::ostream& os, const GenericPrinter& gp) {\n    return internal_generic_printer::GenericPrintImpl(os, gp.value_);\n  }\n  const T& value_;\n};\n\nstruct GenericPrintStreamAdapter {\n  template <class StreamT>\n  struct Impl {\n    // Stream operator: this object will adapt to the underlying stream type,\n    // but only if the Impl is an rvalue. For example, this works:\n    //   std::cout << GenericPrint() << foo;\n    // but not:\n    //   auto adapter = (std::cout << GenericPrint());\n    //   adapter << foo;\n    template <typename T>\n    Impl&& operator<<(const T& value) && {\n      os << internal_generic_printer::GenericPrinter<T>(value);\n      return std::move(*this);\n    }\n\n    // Inhibit using a stack variable for the adapter:\n    template <typename T>\n    Impl& operator<<(const T& value) & = delete;\n\n    // Detects a Flush() method, for LogMessage compatibility.\n    template <typename T>\n    class HasFlushMethod {\n     private:\n      template <typename C>\n      static std::true_type Test(decltype(&C::Flush));\n      template <typename C>\n      static std::false_type Test(...);\n\n     public:\n      static constexpr bool value = decltype(Test<T>(nullptr))::value;\n    };\n\n    // LogMessage compatibility requires a Flush() method.\n    void Flush() {\n      if constexpr (HasFlushMethod<StreamT>::value) {\n        os.Flush();\n      }\n    }\n\n    StreamT& os;\n  };\n\n  // If Impl is evaluated on the RHS of an 'operator&&', and 'lhs && Impl.os'\n  // implicitly converts to void, then it's fine for Impl to do so, too. This\n  // will create precisely as many objects as 'lhs && Impl.os', so we should\n  // both observe any side effects, and avoid observing multiple side\n  // effects. (See absl::log_internal::Voidify for an example of why this might\n  // be useful.)\n  template <typename LHS, typename RHS>\n  friend auto operator&&(LHS&& lhs, Impl<RHS>&& rhs)\n      -> decltype(lhs && rhs.os) {\n    return lhs && rhs.os;\n  }\n\n  template <class StreamT>\n  friend Impl<StreamT> operator<<(StreamT& os, GenericPrintStreamAdapter&&) {\n    return Impl<StreamT>{os};\n  }\n};\n\nstruct GenericPrintAdapterFactory {\n  internal_generic_printer::GenericPrintStreamAdapter operator()() const {\n    return internal_generic_printer::GenericPrintStreamAdapter{};\n  }\n  template <typename T>\n  internal_generic_printer::GenericPrinter<T> operator()(const T& value) const {\n    return internal_generic_printer::GenericPrinter<T>{value};\n  }\n};\n\n}  // namespace internal_generic_printer\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_GENERIC_PRINTER_INTERNAL_H_\n"
  },
  {
    "path": "absl/strings/internal/generic_printer_test.cc",
    "content": "// Copyright 2025 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/generic_printer.h\"\n\n#include <array>\n#include <cstdint>\n#include <limits>\n#include <map>\n#include <memory>\n#include <optional>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <variant>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/status/status.h\"\n#include \"absl/status/statusor.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/substitute.h\"\n\nnamespace generic_logging_test {\nstruct NotStreamable {};\n}  // namespace generic_logging_test\n\nstatic std::ostream& operator<<(std::ostream& os,\n                                const generic_logging_test::NotStreamable&) {\n  return os << \"This overload should NOT be found by GenericPrint.\";\n}\n\n// Types to test selection logic for streamable and non-streamable types.\nnamespace generic_logging_test {\nstruct Streamable {\n  int x;\n  friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {\n    return os << \"Streamable{\" << l.x << \"}\";\n  }\n};\n}  // namespace generic_logging_test\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\nnamespace {\n\nusing ::testing::AllOf;\nusing ::testing::AnyOf;\nusing ::testing::ContainsRegex;\nusing ::testing::EndsWith;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing ::testing::MatchesRegex;\n\nstruct AbslStringifiable {\n  template <typename S>\n  friend void AbslStringify(S& sink, const AbslStringifiable&) {\n    sink.Append(\"AbslStringifiable!\");\n  }\n};\n\nauto IsUnprintable() {\n#ifdef GTEST_USES_SIMPLE_RE\n  return HasSubstr(\"unprintable value of size\");\n#else\n  return ContainsRegex(\n      \"\\\\[unprintable value of size [0-9]+ @(0x)?[0-9a-fA-F]+\\\\]\");\n#endif\n}\n\nauto HasExactlyNInstancesOf(int n, absl::string_view me) {\n#ifdef GTEST_USES_SIMPLE_RE\n  (void)n;\n  return HasSubstr(me);\n#else\n  absl::string_view value_m_times = \"(.*$0){$1}.*\";\n\n  return AllOf(MatchesRegex(absl::Substitute(value_m_times, me, n)),\n               Not(MatchesRegex(absl::Substitute(value_m_times, me, n + 1))));\n#endif\n}\n\ntemplate <typename T>\nstd::string GenericPrintToString(const T& v) {\n  std::stringstream ss;\n  ss << GenericPrint(v);\n  {\n    std::stringstream ss2;\n    ss2 << GenericPrint() << v;\n    EXPECT_EQ(ss.str(), ss2.str());\n  }\n  return ss.str();\n}\n\nTEST(GenericPrinterTest, Bool) {\n  EXPECT_EQ(\"true\", GenericPrintToString(true));\n  EXPECT_EQ(\"false\", GenericPrintToString(false));\n}\n\nTEST(GenericPrinterTest, VectorOfBool) {\n  std::vector<bool> v{true, false, true};\n  const auto& cv = v;\n  EXPECT_EQ(\"[true, false, true]\", GenericPrintToString(v));\n  EXPECT_EQ(\"true\", GenericPrintToString(v[0]));\n  EXPECT_EQ(\"true\", GenericPrintToString(cv[0]));\n}\n\nTEST(GenericPrinterTest, CharLiterals) {\n  EXPECT_EQ(R\"(a\"\\b)\", GenericPrintToString(R\"(a\"\\b)\"));\n}\n\nTEST(GenericPrinterTest, Builtin) {\n  EXPECT_EQ(\"123\", GenericPrintToString(123));\n}\n\nTEST(GenericPrinterTest, AbslStringifiable) {\n  EXPECT_EQ(\"AbslStringifiable!\", GenericPrintToString(AbslStringifiable{}));\n}\n\nTEST(GenericPrinterTest, Nullptr) {\n  EXPECT_EQ(\"nullptr\", GenericPrintToString(nullptr));\n}\n\nTEST(GenericPrinterTest, Chars) {\n  EXPECT_EQ(R\"('\\x0a' (0x0a 10))\", GenericPrintToString('\\x0a'));\n  EXPECT_EQ(R\"(' ' (0x20 32))\", GenericPrintToString(' '));\n  EXPECT_EQ(R\"('~' (0x7e 126))\", GenericPrintToString('~'));\n  EXPECT_EQ(R\"('\\'' (0x27 39))\", GenericPrintToString('\\''));\n}\n\nTEST(GenericPrinterTest, SignedChars) {\n  EXPECT_EQ(R\"('\\x0a' (0x0a 10))\",\n            GenericPrintToString(static_cast<signed char>('\\x0a')));\n  EXPECT_EQ(R\"(' ' (0x20 32))\",\n            GenericPrintToString(static_cast<signed char>(' ')));\n  EXPECT_EQ(R\"('~' (0x7e 126))\",\n            GenericPrintToString(static_cast<signed char>('~')));\n  EXPECT_EQ(R\"('\\'' (0x27 39))\",\n            GenericPrintToString(static_cast<signed char>('\\'')));\n}\n\nTEST(GenericPrinterTest, UnsignedChars) {\n  EXPECT_EQ(R\"('\\x0a' (0x0a 10))\",\n            GenericPrintToString(static_cast<unsigned char>('\\x0a')));\n  EXPECT_EQ(R\"(' ' (0x20 32))\",\n            GenericPrintToString(static_cast<unsigned char>(' ')));\n  EXPECT_EQ(R\"('~' (0x7e 126))\",\n            GenericPrintToString(static_cast<unsigned char>('~')));\n  EXPECT_EQ(R\"('\\'' (0x27 39))\",\n            GenericPrintToString(static_cast<unsigned char>('\\'')));\n}\n\nTEST(GenericPrinterTest, Bytes) {\n  EXPECT_EQ(\"0x00\", GenericPrintToString(static_cast<std::byte>(0)));\n  EXPECT_EQ(\"0x7f\", GenericPrintToString(static_cast<std::byte>(0x7F)));\n  EXPECT_EQ(\"0xff\", GenericPrintToString(static_cast<std::byte>(0xFF)));\n}\n\nTEST(GenericPrinterTest, Strings) {\n  const std::string expected_quotes = R\"(\"a\\\"\\\\b\")\";\n  EXPECT_EQ(expected_quotes, GenericPrintToString(std::string(R\"(a\"\\b)\")));\n  const std::string expected_nonprintable = R\"(\"\\x00\\xcd\\n\\xab\")\";\n  EXPECT_EQ(expected_nonprintable,\n            GenericPrintToString(absl::string_view(\"\\0\\315\\n\\xAB\", 4)));\n}\n\nTEST(GenericPrinterTest, PreciseFloat) {\n  // Instead of testing exactly how the values are formatted, just check that\n  // they are distinct.\n\n  // Ensure concise output for exact values:\n  EXPECT_EQ(\"1f\", GenericPrintToString(1.f));\n  EXPECT_EQ(\"1.1f\", GenericPrintToString(1.1f));\n\n  // Plausible real-world values:\n  float f = 10.0000095f;\n  EXPECT_NE(GenericPrintToString(f), GenericPrintToString(10.0000105f));\n  // Smallest increment for a real-world value:\n  EXPECT_NE(GenericPrintToString(f),\n            GenericPrintToString(std::nextafter(f, 11)));\n  // The two smallest (finite) values possible:\n  EXPECT_NE(GenericPrintToString(std::numeric_limits<float>::lowest()),\n            GenericPrintToString(\n                std::nextafter(std::numeric_limits<float>::lowest(), 1)));\n  // Ensure the value has the correct type suffix:\n  EXPECT_THAT(GenericPrintToString(0.f), EndsWith(\"f\"));\n}\n\nTEST(GenericPrinterTest, PreciseDouble) {\n  EXPECT_EQ(\"1\", GenericPrintToString(1.));\n  EXPECT_EQ(\"1.1\", GenericPrintToString(1.1));\n  double d = 10.000000000000002;\n  EXPECT_NE(GenericPrintToString(d), GenericPrintToString(10.000000000000004));\n  EXPECT_NE(GenericPrintToString(d),\n            GenericPrintToString(std::nextafter(d, 11)));\n  EXPECT_NE(GenericPrintToString(std::numeric_limits<double>::lowest()),\n            GenericPrintToString(\n                std::nextafter(std::numeric_limits<double>::lowest(), 1)));\n  EXPECT_THAT(GenericPrintToString(0.), EndsWith(\"0\"));\n}\n\nTEST(GenericPrinterTest, PreciseLongDouble) {\n  EXPECT_EQ(\"1L\", GenericPrintToString(1.L));\n  EXPECT_EQ(\"1.1L\", GenericPrintToString(1.1L));\n  long double ld = 10.0000000000000000000000000000002;\n  EXPECT_NE(GenericPrintToString(ld),\n            GenericPrintToString(10.0000000000000000000000000000004));\n  EXPECT_NE(GenericPrintToString(ld),\n            GenericPrintToString(std::nextafter(ld, 11)));\n  EXPECT_NE(GenericPrintToString(std::numeric_limits<long double>::lowest()),\n            GenericPrintToString(\n                std::nextafter(std::numeric_limits<long double>::lowest(), 1)));\n  EXPECT_THAT(GenericPrintToString(0.L), EndsWith(\"L\"));\n}\n\nTEST(GenericPrinterTest, StreamableLvalue) {\n  generic_logging_test::Streamable x{234};\n  EXPECT_EQ(\"Streamable{234}\", GenericPrintToString(x));\n}\n\nTEST(GenericPrinterTest, StreamableXvalue) {\n  EXPECT_EQ(\"Streamable{345}\",\n            GenericPrintToString(generic_logging_test::Streamable{345}));\n}\n\nTEST(GenericPrinterTest, NotStreamableWithoutGenericPrint) {\n  ::generic_logging_test::NotStreamable x;\n  std::stringstream ss;\n  ::operator<<(ss, x);\n  EXPECT_EQ(ss.str(), \"This overload should NOT be found by GenericPrint.\");\n}\n\nTEST(GenericPrinterTest, NotStreamableLvalue) {\n  generic_logging_test::NotStreamable x;\n  EXPECT_THAT(GenericPrintToString(x), IsUnprintable());\n}\n\nTEST(GenericPrinterTest, NotStreamableXvalue) {\n  EXPECT_THAT(GenericPrintToString(generic_logging_test::NotStreamable{}),\n              IsUnprintable());\n}\n\nTEST(GenericPrinterTest, DebugString) {\n  struct WithDebugString {\n    std::string val;\n    std::string DebugString() const {\n      return absl::StrCat(\"WithDebugString{\", val, \"}\");\n    }\n  };\n  EXPECT_EQ(\"WithDebugString{foo}\",\n            GenericPrintToString(WithDebugString{\"foo\"}));\n}\n\nTEST(GenericPrinterTest, Vector) {\n  std::vector<int> v = {4, 5, 6};\n  EXPECT_THAT(GenericPrintToString(v), MatchesRegex(\".*4,? 5,? 6.*\"));\n}\n\nTEST(GenericPrinterTest, StreamableVector) {\n  std::vector<generic_logging_test::Streamable> v = {{7}, {8}, {9}};\n  EXPECT_THAT(GenericPrintToString(v),\n              MatchesRegex(\".*Streamable.7.,? Streamable.8.,? Streamable.9.*\"));\n}\n\nTEST(GenericPrinterTest, Map) {\n  absl::flat_hash_map<\n      std::string, absl::flat_hash_map<std::string, std::pair<double, double>>>\n      v = {{\"A\", {{\"B\", {.5, .25}}}}};\n\n  EXPECT_THAT(GenericPrintToString(v), R\"([<\"A\", [<\"B\", <0.5, 0.25>>]>])\");\n\n  std::map<std::string, std::map<std::string, std::pair<double, double>>> v2 = {\n      {\"A\", {{\"B\", {.5, .25}}}}};\n\n  EXPECT_THAT(GenericPrintToString(v2), R\"([<\"A\", [<\"B\", <0.5, 0.25>>]>])\");\n}\n\nTEST(GenericPrinterTest, StreamAdapter) {\n  std::stringstream ss;\n  static_assert(\n      std::is_same<\n          typename std::remove_reference<decltype(ss << GenericPrint())>::type,\n          internal_generic_printer::GenericPrintStreamAdapter::Impl<\n              std::stringstream>>::value,\n      \"expected ostream << GenericPrint() to yield adapter impl\");\n\n  ss << GenericPrint() << \"again, \" << \"back-up, \" << \"cue, \"\n     << \"double-u, \" << \"eye, \"\n     << \"four: \" << generic_logging_test::NotStreamable{};\n  EXPECT_THAT(\n      ss.str(),\n      MatchesRegex(\n          \"again, back-up, cue, double-u, eye, four: .unprintable value.*\"));\n}\n\nTEST(GenericPrinterTest, NotStreamableVector) {\n  std::vector<generic_logging_test::NotStreamable> v = {{}, {}, {}};\n#ifdef GTEST_USES_SIMPLE_RE\n  EXPECT_THAT(GenericPrintToString(v), HasSubstr(\"unprintable\"));\n#else\n  EXPECT_THAT(GenericPrintToString(v), MatchesRegex(\".*(unprintable.*){3}.*\"));\n#endif\n}\n\nstruct CustomContainer : public std::array<int, 4> {\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const CustomContainer& c) {\n    absl::Format(&sink, \"%d %d\", c[0], c[1]);\n  }\n};\n\n// Checks that AbslStringify (go/totw/215) is respected for container-like\n// types.\nTEST(GenericPrinterTest, ContainerLikeCustomLogging) {\n  CustomContainer c = {1, 2, 3, 4};\n  EXPECT_EQ(GenericPrintToString(c), \"1 2\");\n}\n\n// Test helper: this function demonstrates customizable printing logic:\n// 'GenericPrinter<T>' can be nominated as a default template argument.\ntemplate <typename T, typename Printer = GenericPrinter<T>>\nstd::string SpecializablePrint(const T& v) {\n  std::stringstream ss;\n  ss << Printer{v};\n  return ss.str();\n}\n\nTEST(GenericPrinterTest, DefaultPrinter) {\n  EXPECT_EQ(\"123\", SpecializablePrint(123));\n}\n\n// Example of custom printing logic. This doesn't actually test anything in\n// GenericPrinter, but it's a working example of customizing printing logic (as\n// opposed to the comments in generic_printer.h).\nstruct CustomPrinter {\n  explicit CustomPrinter(int) {}\n  friend std::ostream& operator<<(std::ostream& os, CustomPrinter&&) {\n    return os << \"custom printer\";\n  }\n};\n\nTEST(GenericPrinterTest, CustomPrinter) {\n  EXPECT_EQ(\"custom printer\", (SpecializablePrint<int, CustomPrinter>(123)));\n}\n\nTEST(GenricPrinterTest, Nullopt) {\n  EXPECT_EQ(\"nullopt\", GenericPrintToString(std::nullopt));\n}\n\nTEST(GenericPrinterTest, Optional) {\n  EXPECT_EQ(\"nullopt\", GenericPrintToString(std::optional<int>()));\n  EXPECT_EQ(\"nullopt\", GenericPrintToString(std::optional<int>(std::nullopt)));\n  EXPECT_EQ(\"<3>\", GenericPrintToString(std::make_optional(3)));\n  EXPECT_EQ(\"<Streamable{3}>\", GenericPrintToString(std::make_optional(\n                                   generic_logging_test::Streamable{3})));\n}\n\nTEST(GenericPrinterTest, Tuple) {\n  EXPECT_EQ(\"<1, two, 3>\", GenericPrintToString(std::make_tuple(1, \"two\", 3)));\n}\n\nTEST(GenericPrinterTest, EmptyTuple) {\n  EXPECT_EQ(\"<>\", GenericPrintToString(std::make_tuple()));\n}\n\nTEST(GenericPrinterTest, TupleWithStreamableMember) {\n  EXPECT_EQ(\"<1, two, Streamable{3}>\",\n            GenericPrintToString(std::make_tuple(\n                1, \"two\", generic_logging_test::Streamable{3})));\n}\n\nTEST(GenericPrinterTest, Variant) {\n  EXPECT_EQ(R\"(('(index = 0)' \"cow\"))\",\n            GenericPrintToString(std::variant<std::string, float>(\"cow\")));\n\n  EXPECT_EQ(\"('(index = 1)' 1.1f)\",\n            GenericPrintToString(std::variant<std::string, float>(1.1F)));\n}\n\nTEST(GenericPrinterTest, VariantMonostate) {\n  EXPECT_THAT(GenericPrintToString(std::variant<std::monostate, std::string>()),\n              IsUnprintable());\n}\n\nTEST(GenericPrinterTest, VariantNonStreamable) {\n  EXPECT_EQ(R\"(('(index = 0)' \"cow\"))\",\n            GenericPrintToString(\n                std::variant<std::string, generic_logging_test::NotStreamable>(\n                    \"cow\")));\n\n  EXPECT_THAT(\n      GenericPrintToString(\n          std::variant<std::string, generic_logging_test::NotStreamable>(\n              generic_logging_test::NotStreamable{})),\n      IsUnprintable());\n}\n\nTEST(GenericPrinterTest, VariantNestedVariant) {\n  EXPECT_EQ(\n      \"('(index = 1)' ('(index = 1)' 1.1f))\",\n      GenericPrintToString(std::variant<std::string, std::variant<int, float>>(\n          std::variant<int, float>(1.1F))));\n}\n\nTEST(GenericPrinterTest, VariantInPlace) {\n  EXPECT_EQ(\"('(index = 0)' 17)\", GenericPrintToString(std::variant<int, int>(\n                                      std::in_place_index<0>, 17)));\n\n  EXPECT_EQ(\"('(index = 1)' 17)\", GenericPrintToString(std::variant<int, int>(\n                                      std::in_place_index<1>, 17)));\n}\n\nTEST(GenericPrinterTest, StatusOrLikeOkPrintsValue) {\n  EXPECT_EQ(R\"(<OK: \"cow\">)\",\n            GenericPrintToString(absl::StatusOr<std::string>(\"cow\")));\n\n  EXPECT_EQ(R\"(<OK: 1.1f>)\", GenericPrintToString(absl::StatusOr<float>(1.1F)));\n}\n\nTEST(GenericPrinterTest, StatusOrLikeNonOkPrintsStatus) {\n  EXPECT_THAT(\n      GenericPrintToString(absl::StatusOr<float>(\n          absl::InvalidArgumentError(\"my error message\"))),\n      AllOf(HasSubstr(\"my error message\"), HasSubstr(\"INVALID_ARGUMENT\")));\n\n  EXPECT_THAT(GenericPrintToString(\n                  absl::StatusOr<int>(absl::AbortedError(\"other message\"))),\n              AllOf(HasSubstr(\"other message\"), HasSubstr(\"ABORTED\")));\n}\n\nTEST(GenericPrinterTest, StatusOrLikeNonStreamableValueUnprintable) {\n  EXPECT_THAT(\n      GenericPrintToString(absl::StatusOr<generic_logging_test::NotStreamable>(\n          generic_logging_test::NotStreamable{})),\n      IsUnprintable());\n}\n\nTEST(GenericPrinterTest, StatusOrLikeNonStreamableErrorStillPrintable) {\n  EXPECT_THAT(\n      GenericPrintToString(absl::StatusOr<generic_logging_test::NotStreamable>(\n          absl::AbortedError(\"other message\"))),\n      AllOf(HasSubstr(\"other message\"), HasSubstr(\"ABORTED\")));\n}\n\nTEST(GenericPrinterTest, IsSupportedPointer) {\n  using internal_generic_printer::is_supported_ptr;\n\n  EXPECT_TRUE(is_supported_ptr<std::unique_ptr<std::string>>);\n  EXPECT_TRUE(is_supported_ptr<std::unique_ptr<int[]>>);\n  EXPECT_TRUE((is_supported_ptr<std::unique_ptr<void, void (*)(void*)>>));\n\n  EXPECT_FALSE(is_supported_ptr<int*>);\n  EXPECT_FALSE(is_supported_ptr<std::shared_ptr<int>>);\n  EXPECT_FALSE(is_supported_ptr<std::weak_ptr<int>>);\n}\n\nTEST(GenericPrinterTest, SmartPointerPrintsNullptrForAllNullptrs) {\n  std::unique_ptr<std::string> up;\n\n  EXPECT_EQ(\"<nullptr>\", GenericPrintToString(up));\n}\n\nTEST(GenericPrinterTest, SmartPointerPrintsValueIfNonNull) {\n  EXPECT_THAT(GenericPrintToString(std::make_unique<int>(5)),\n              HasSubstr(\"pointing to 5\"));\n}\n\nTEST(GenericPrinterTest, SmartPointerPrintsAddressOfPointee) {\n  auto i = std::make_unique<int>(5);\n  auto c = std::make_unique<char>('z');\n  char memory[] = \"abcdefg\";\n  auto cp = std::make_unique<char*>(memory);\n\n  EXPECT_THAT(GenericPrintToString(i),\n              AnyOf(Eq(absl::StrFormat(\"<%016X pointing to 5>\",\n                                       reinterpret_cast<intptr_t>(&*i))),\n                    Eq(absl::StrFormat(\"<%#x pointing to 5>\",\n                                       reinterpret_cast<intptr_t>(&*i)))));\n\n  EXPECT_THAT(\n      GenericPrintToString(c),\n      AnyOf(HasSubstr(absl::StrFormat(\"<%016X pointing to 'z'\",\n                                      reinterpret_cast<intptr_t>(&*c))),\n            HasSubstr(absl::StrFormat(\"<%#x pointing to 'z'\",\n                                      reinterpret_cast<intptr_t>(&*c)))));\n\n  EXPECT_THAT(GenericPrintToString(cp),\n              AnyOf(Eq(absl::StrFormat(\"<%016X pointing to abcdefg>\",\n                                       reinterpret_cast<intptr_t>(&*cp))),\n                    Eq(absl::StrFormat(\"<%#x pointing to abcdefg>\",\n                                       reinterpret_cast<intptr_t>(&*cp)))));\n}\n\nTEST(GenericPrinterTest, SmartPointerToArrayOnlyPrintsAddressAndHelpText) {\n  auto empty = std::make_unique<int[]>(0);\n  auto nonempty = std::make_unique<int[]>(5);\n  nonempty[0] = 12345;\n  nonempty[4] = 54321;\n  // NOTE: ArenaSafeUniquePtr is not meant to support array-type template\n  // parameters, so we skip testing that here.\n  // http://g/c-users/J-AEFrFHssY/UMMFzCkdBAAJ, b/265984185.\n\n  EXPECT_THAT(\n      GenericPrintToString(nonempty),\n      AllOf(AnyOf(HasSubstr(absl::StrFormat(\n                      \"%016X\", reinterpret_cast<intptr_t>(nonempty.get()))),\n                  HasSubstr(absl::StrFormat(\n                      \"%#x\", reinterpret_cast<intptr_t>(nonempty.get())))),\n            HasSubstr(\"array\"), Not(HasSubstr(\"to 54321\")),\n            Not(HasSubstr(\"to 12345\"))));\n\n  EXPECT_THAT(\n      GenericPrintToString(empty),\n      AllOf(AnyOf(HasSubstr(absl::StrFormat(\n                      \"%016X\", reinterpret_cast<intptr_t>(empty.get()))),\n                  HasSubstr(absl::StrFormat(\n                      \"%#x\", reinterpret_cast<intptr_t>(empty.get())))),\n            HasSubstr(\"array\")));\n}\n\nTEST(GenericPrinterTest, SmartPointerToNonObjectType) {\n  auto int_ptr_deleter = [](void* data) {\n    int* p = static_cast<int*>(data);\n    delete p;\n  };\n\n  std::unique_ptr<void, decltype(int_ptr_deleter)> void_ptr(new int(959),\n                                                            int_ptr_deleter);\n\n  EXPECT_THAT(GenericPrintToString(void_ptr),\n              HasSubstr(\"pointing to a non-object type\"));\n}\n\nTEST(GenericPrinterTest, PrintsCustomDeleterSmartPointer) {\n  // Delete `p` (if not nullptr) only on the 4th time the deleter is used.\n  auto four_deleter = [](std::string* p) {\n    static int counter = 0;\n    if (p == nullptr) return;  // skip calls to moved-from destructors.\n    if (++counter >= 4) delete p;\n  };\n\n  // Have four `unique_ptr`s \"manage\" the same string-pointer, with only the\n  // final (4th) call to the deleter deleting the string pointer.\n  auto* unique_string = new std::string(\"unique string\");\n  std::vector<std::unique_ptr<std::string, decltype(four_deleter)>> test_ptrs;\n  for (int i = 0; i < 4; ++i) {\n    test_ptrs.emplace_back(unique_string, four_deleter);\n  }\n\n  EXPECT_THAT(GenericPrintToString(test_ptrs),\n              HasExactlyNInstancesOf(4, \"unique string\"));\n}\n\n// Ensure that GenericPrint is robust to recursion when a type's operator<<\n// calls into GenericPrint internally.\nstruct CustomRecursive {\n  std::unique_ptr<CustomRecursive> next;\n  int val = 0;\n\n  friend std::ostream& operator<<(std::ostream& os, const CustomRecursive& cr) {\n    return os << \"custom print: next = \" << GenericPrintToString(cr.next);\n  }\n};\n\nTEST(GenericPrinterTest, DISABLED_CustomPrintOverloadRecursionDetected) {\n  auto r1 = std::make_unique<CustomRecursive>();\n  r1->val = 1;\n  auto& r2 = r1->next = std::make_unique<CustomRecursive>();\n  r2->val = 2;\n  r2->next = std::move(r1);\n\n  EXPECT_THAT(GenericPrintToString(*r2),\n              AllOf(HasExactlyNInstancesOf(2, \"custom print\"),\n                    HasExactlyNInstancesOf(1, \"<recursive>\")));\n\n  r2->next = nullptr;  // break the cycle\n}\n// <end DISABLED_ test section>\n\nenum CStyleEnum { kValue0, kValue1 };\nTEST(GenericPrinterTest, Enum) {\n  EXPECT_EQ(\"1\", GenericPrintToString(kValue1));\n}\n\nenum class CppStyleEnum { kValue0, kValue1, kValue2 };\nTEST(GenericPrinterTest, EnumClass) {\n  EXPECT_EQ(\"2\", GenericPrintToString(CppStyleEnum::kValue2));\n}\n\nenum class CharBasedEnum : char { kValueA = 'A', kValue1 = '\\x01' };\nTEST(GenericPrinterTest, CharBasedEnum) {\n  EXPECT_EQ(\"'A' (0x41 65)\", GenericPrintToString(CharBasedEnum::kValueA));\n  EXPECT_EQ(\"'\\\\x01' (0x01 1)\", GenericPrintToString(CharBasedEnum::kValue1));\n}\n\nenum class WideBasedEnum : uint64_t {\n  kValue = std::numeric_limits<uint64_t>::max()\n};\nTEST(GenericPrinterTest, WideBasedEnum) {\n  EXPECT_EQ(absl::StrCat(std::numeric_limits<uint64_t>::max()),\n            GenericPrintToString(WideBasedEnum::kValue));\n}\n\nenum CStyleEnumWithStringify { kValueA = 0, kValueB = 2 };\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CStyleEnumWithStringify e) {\n  switch (e) {\n    case CStyleEnumWithStringify::kValueA:\n      sink.Append(\"A\");\n      return;\n    case CStyleEnumWithStringify::kValueB:\n      sink.Append(\"B\");\n      return;\n  }\n  sink.Append(\"??\");\n}\nTEST(GenericPrinterTest, CStyleEnumWithStringify) {\n  EXPECT_EQ(\"A\", GenericPrintToString(CStyleEnumWithStringify::kValueA));\n  EXPECT_EQ(\"??\",\n            GenericPrintToString(static_cast<CStyleEnumWithStringify>(1)));\n}\n\nenum class CppStyleEnumWithStringify { kValueA, kValueB, kValueC };\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CppStyleEnumWithStringify e) {\n  switch (e) {\n    case CppStyleEnumWithStringify::kValueA:\n      sink.Append(\"A\");\n      return;\n    case CppStyleEnumWithStringify::kValueB:\n      sink.Append(\"B\");\n      return;\n    case CppStyleEnumWithStringify::kValueC:\n      sink.Append(\"C\");\n      return;\n  }\n  sink.Append(\"??\");\n}\nTEST(GenericPrinterTest, CppStyleEnumWithStringify) {\n  EXPECT_EQ(\"A\", GenericPrintToString(CppStyleEnumWithStringify::kValueA));\n  EXPECT_EQ(\"??\",\n            GenericPrintToString(static_cast<CppStyleEnumWithStringify>(17)));\n}\n\nenum class CharBasedEnumWithStringify : char { kValueA = 'A', kValueB = 'B' };\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CharBasedEnumWithStringify e) {\n  switch (e) {\n    case CharBasedEnumWithStringify::kValueA:\n      sink.Append(\"charA\");\n      return;\n    case CharBasedEnumWithStringify::kValueB:\n      sink.Append(\"charB\");\n      return;\n  }\n  sink.Append(\"??\");\n}\nTEST(GenericPrinterTest, CharBasedEnumWithStringify) {\n  EXPECT_EQ(\"charA\", GenericPrintToString(CharBasedEnumWithStringify::kValueA));\n  EXPECT_EQ(\"??\",\n            GenericPrintToString(static_cast<CharBasedEnumWithStringify>('W')));\n}\n\n}  // namespace\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/memutil.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/memutil.h\"\n\n#include <cstdlib>\n\n#include \"absl/strings/ascii.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nint memcasecmp(const char* s1, const char* s2, size_t len) {\n  const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1);\n  const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2);\n\n  for (size_t i = 0; i < len; i++) {\n    unsigned char c1 = us1[i];\n    unsigned char c2 = us2[i];\n    // If bytes are the same, they will be the same when converted to lower.\n    // So we only need to convert if bytes are not equal.\n    // NOTE(b/308193381): We do not use `absl::ascii_tolower` here in order\n    // to avoid its lookup table and improve performance.\n    if (c1 != c2) {\n      c1 = c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1;\n      c2 = c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2;\n      const int diff = int{c1} - int{c2};\n      if (diff != 0) return diff;\n    }\n  }\n  return 0;\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/memutil.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_STRINGS_INTERNAL_MEMUTIL_H_\n#define ABSL_STRINGS_INTERNAL_MEMUTIL_H_\n\n#include <cstddef>\n#include <cstring>\n\n#include \"absl/base/port.h\"  // disable some warnings on Windows\n#include \"absl/strings/ascii.h\"  // for absl::ascii_tolower\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// Performs a byte-by-byte comparison of `len` bytes of the strings `s1` and\n// `s2`, ignoring the case of the characters. It returns an integer less than,\n// equal to, or greater than zero if `s1` is found, respectively, to be less\n// than, to match, or be greater than `s2`.\nint memcasecmp(const char* s1, const char* s2, size_t len);\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_MEMUTIL_H_\n"
  },
  {
    "path": "absl/strings/internal/memutil_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <cstdlib>\n\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/internal/memutil.h\"\n#include \"benchmark/benchmark.h\"\n\n// We fill the haystack with aaaaaaaaaaaaaaaaaa...aaaab.\n// That gives us:\n// - an easy search: 'b'\n// - a medium search: 'ab'.  That means every letter is a possible match.\n// - a pathological search: 'aaaaaa.......aaaaab' (half as many a's as haytack)\n\nnamespace {\n\nconstexpr int kHaystackSize = 10000;\nconstexpr int64_t kHaystackSize64 = kHaystackSize;\nconst char* MakeHaystack() {\n  char* haystack = new char[kHaystackSize];\n  for (int i = 0; i < kHaystackSize - 1; ++i) haystack[i] = 'a';\n  haystack[kHaystackSize - 1] = 'b';\n  return haystack;\n}\nconst char* const kHaystack = MakeHaystack();\n\nbool case_eq(const char a, const char b) {\n  return absl::ascii_tolower(a) == absl::ascii_tolower(b);\n}\n\nvoid BM_Searchcase(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize,\n                                         kHaystack + kHaystackSize - 1,\n                                         kHaystack + kHaystackSize, case_eq));\n  }\n  state.SetBytesProcessed(kHaystackSize64 * state.iterations());\n}\nBENCHMARK(BM_Searchcase);\n\nvoid BM_SearchcaseMedium(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize,\n                                         kHaystack + kHaystackSize - 2,\n                                         kHaystack + kHaystackSize, case_eq));\n  }\n  state.SetBytesProcessed(kHaystackSize64 * state.iterations());\n}\nBENCHMARK(BM_SearchcaseMedium);\n\nvoid BM_SearchcasePathological(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize,\n                                         kHaystack + kHaystackSize / 2,\n                                         kHaystack + kHaystackSize, case_eq));\n  }\n  state.SetBytesProcessed(kHaystackSize64 * state.iterations());\n}\nBENCHMARK(BM_SearchcasePathological);\n\nchar* memcasechr(const char* s, int c, size_t slen) {\n  c = absl::ascii_tolower(c);\n  for (; slen; ++s, --slen) {\n    if (absl::ascii_tolower(*s) == c) return const_cast<char*>(s);\n  }\n  return nullptr;\n}\n\nconst char* memcasematch(const char* phaystack, size_t haylen,\n                         const char* pneedle, size_t neelen) {\n  if (0 == neelen) {\n    return phaystack;  // even if haylen is 0\n  }\n  if (haylen < neelen) return nullptr;\n\n  const char* match;\n  const char* hayend = phaystack + haylen - neelen + 1;\n  while ((match = static_cast<char*>(\n              memcasechr(phaystack, pneedle[0], hayend - phaystack)))) {\n    if (absl::strings_internal::memcasecmp(match, pneedle, neelen) == 0)\n      return match;\n    else\n      phaystack = match + 1;\n  }\n  return nullptr;\n}\n\nvoid BM_Memcasematch(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, \"b\", 1));\n  }\n  state.SetBytesProcessed(kHaystackSize64 * state.iterations());\n}\nBENCHMARK(BM_Memcasematch);\n\nvoid BM_MemcasematchMedium(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, \"ab\", 2));\n  }\n  state.SetBytesProcessed(kHaystackSize64 * state.iterations());\n}\nBENCHMARK(BM_MemcasematchMedium);\n\nvoid BM_MemcasematchPathological(benchmark::State& state) {\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize,\n                                          kHaystack + kHaystackSize / 2,\n                                          kHaystackSize - kHaystackSize / 2));\n  }\n  state.SetBytesProcessed(kHaystackSize64 * state.iterations());\n}\nBENCHMARK(BM_MemcasematchPathological);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/memutil_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Unit test for memutil.cc\n\n#include \"absl/strings/internal/memutil.h\"\n\n#include <cstdlib>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nTEST(MemUtil, memcasecmp) {\n  // check memutil functions\n  const char a[] = \"hello there\";\n\n  EXPECT_EQ(absl::strings_internal::memcasecmp(a, \"heLLO there\",\n                                               sizeof(\"hello there\") - 1),\n            0);\n  EXPECT_EQ(absl::strings_internal::memcasecmp(a, \"heLLO therf\",\n                                               sizeof(\"hello there\") - 1),\n            -1);\n  EXPECT_EQ(absl::strings_internal::memcasecmp(a, \"heLLO therf\",\n                                               sizeof(\"hello there\") - 2),\n            0);\n  EXPECT_EQ(absl::strings_internal::memcasecmp(a, \"whatever\", 0), 0);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/numbers_test_common.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This file contains common things needed by numbers_test.cc,\n// numbers_legacy_test.cc and numbers_benchmark.cc.\n\n#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_\n#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_\n\n#include <array>\n#include <cstdint>\n#include <limits>\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\ntemplate <typename IntType>\ninline bool Itoa(IntType value, int base, std::string* destination) {\n  destination->clear();\n  if (base <= 1 || base > 36) {\n    return false;\n  }\n\n  if (value == 0) {\n    destination->push_back('0');\n    return true;\n  }\n\n  bool negative = value < 0;\n  while (value != 0) {\n    const IntType next_value = value / base;\n    // Can't use std::abs here because of problems when IntType is unsigned.\n    int remainder =\n        static_cast<int>(value > next_value * base ? value - next_value * base\n                                                   : next_value * base - value);\n    char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;\n    destination->insert(0, 1, c);\n    value = next_value;\n  }\n\n  if (negative) {\n    destination->insert(0, 1, '-');\n  }\n  return true;\n}\n\nstruct uint32_test_case {\n  const char* str;\n  bool expect_ok;\n  int base;  // base to pass to the conversion function\n  uint32_t expected;\n};\n\ninline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {\n  static const std::array<uint32_test_case, 27> test_cases{{\n      {\"0xffffffff\", true, 16, (std::numeric_limits<uint32_t>::max)()},\n      {\"0x34234324\", true, 16, 0x34234324},\n      {\"34234324\", true, 16, 0x34234324},\n      {\"0\", true, 16, 0},\n      {\" \\t\\n 0xffffffff\", true, 16, (std::numeric_limits<uint32_t>::max)()},\n      {\" \\f\\v 46\", true, 10, 46},  // must accept weird whitespace\n      {\" \\t\\n 72717222\", true, 8, 072717222},\n      {\" \\t\\n 072717222\", true, 8, 072717222},\n      {\" \\t\\n 072717228\", false, 8, 07271722},\n      {\"0\", true, 0, 0},\n\n      // Base-10 version.\n      {\"34234324\", true, 0, 34234324},\n      {\"4294967295\", true, 0, (std::numeric_limits<uint32_t>::max)()},\n      {\"34234324 \\n\\t\", true, 10, 34234324},\n\n      // Unusual base\n      {\"0\", true, 3, 0},\n      {\"2\", true, 3, 2},\n      {\"11\", true, 3, 4},\n\n      // Invalid uints.\n      {\"\", false, 0, 0},\n      {\"  \", false, 0, 0},\n      {\"abc\", false, 0, 0},  // would be valid hex, but prefix is missing\n      {\"34234324a\", false, 0, 34234324},\n      {\"34234.3\", false, 0, 34234},\n      {\"-1\", false, 0, 0},\n      {\"   -123\", false, 0, 0},\n      {\" \\t\\n -123\", false, 0, 0},\n\n      // Out of bounds.\n      {\"4294967296\", false, 0, (std::numeric_limits<uint32_t>::max)()},\n      {\"0x100000000\", false, 0, (std::numeric_limits<uint32_t>::max)()},\n      {nullptr, false, 0, 0},\n  }};\n  return test_cases;\n}\n\nstruct uint64_test_case {\n  const char* str;\n  bool expect_ok;\n  int base;\n  uint64_t expected;\n};\n\ninline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {\n  static const std::array<uint64_test_case, 34> test_cases{{\n      {\"0x3423432448783446\", true, 16, int64_t{0x3423432448783446}},\n      {\"3423432448783446\", true, 16, int64_t{0x3423432448783446}},\n\n      {\"0\", true, 16, 0},\n      {\"000\", true, 0, 0},\n      {\"0\", true, 0, 0},\n      {\" \\t\\n 0xffffffffffffffff\", true, 16,\n       (std::numeric_limits<uint64_t>::max)()},\n\n      {\"012345670123456701234\", true, 8, int64_t{012345670123456701234}},\n      {\"12345670123456701234\", true, 8, int64_t{012345670123456701234}},\n\n      {\"12845670123456701234\", false, 8, 0},\n\n      // Base-10 version.\n      {\"34234324487834466\", true, 0, int64_t{34234324487834466}},\n\n      {\" \\t\\n 18446744073709551615\", true, 0,\n       (std::numeric_limits<uint64_t>::max)()},\n\n      {\"34234324487834466 \\n\\t \", true, 0, int64_t{34234324487834466}},\n\n      {\" \\f\\v 46\", true, 10, 46},  // must accept weird whitespace\n\n      // Unusual base\n      {\"0\", true, 3, 0},\n      {\"2\", true, 3, 2},\n      {\"11\", true, 3, 4},\n\n      {\"0\", true, 0, 0},\n\n      // Invalid uints.\n      {\"\", false, 0, 0},\n      {\"  \", false, 0, 0},\n      {\"abc\", false, 0, 0},\n      {\"34234324487834466a\", false, 0, 0},\n      {\"34234487834466.3\", false, 0, 0},\n      {\"-1\", false, 0, 0},\n      {\"   -123\", false, 0, 0},\n      {\" \\t\\n -123\", false, 0, 0},\n\n      // Out of bounds.\n      {\"18446744073709551616\", false, 10, 0},\n      {\"18446744073709551616\", false, 0, 0},\n      {\"0x10000000000000000\", false, 16,\n       (std::numeric_limits<uint64_t>::max)()},\n      {\"0X10000000000000000\", false, 16,\n       (std::numeric_limits<uint64_t>::max)()},  // 0X versus 0x.\n      {\"0x10000000000000000\", false, 0, (std::numeric_limits<uint64_t>::max)()},\n      {\"0X10000000000000000\", false, 0,\n       (std::numeric_limits<uint64_t>::max)()},  // 0X versus 0x.\n\n      {\"0x1234\", true, 16, 0x1234},\n\n      // Base-10 string version.\n      {\"1234\", true, 0, 1234},\n      {nullptr, false, 0, 0},\n  }};\n  return test_cases;\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_\n"
  },
  {
    "path": "absl/strings/internal/ostringstream.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/ostringstream.h\"\n\n#include <cassert>\n#include <cstddef>\n#include <ios>\n#include <streambuf>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nOStringStream::Streambuf::int_type OStringStream::Streambuf::overflow(int c) {\n  assert(str_);\n  if (!std::streambuf::traits_type::eq_int_type(\n          c, std::streambuf::traits_type::eof()))\n    str_->push_back(static_cast<char>(c));\n  return 1;\n}\n\nstd::streamsize OStringStream::Streambuf::xsputn(const char* s,\n                                                 std::streamsize n) {\n  assert(str_);\n  str_->append(s, static_cast<size_t>(n));\n  return n;\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/ostringstream.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_\n#define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_\n\n#include <cassert>\n#include <ios>\n#include <ostream>\n#include <streambuf>\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// The same as std::ostringstream but appends to a user-specified std::string,\n// and is faster. It is ~70% faster to create, ~50% faster to write to, and\n// completely free to extract the result std::string.\n//\n//   std::string s;\n//   OStringStream strm(&s);\n//   strm << 42 << ' ' << 3.14;  // appends to `s`\n//\n// The stream object doesn't have to be named. Starting from C++11 operator<<\n// works with rvalues of std::ostream.\n//\n//   std::string s;\n//   OStringStream(&s) << 42 << ' ' << 3.14;  // appends to `s`\n//\n// OStringStream is faster to create than std::ostringstream but it's still\n// relatively slow. Avoid creating multiple streams where a single stream will\n// do.\n//\n// Creates unnecessary instances of OStringStream: slow.\n//\n//   std::string s;\n//   OStringStream(&s) << 42;\n//   OStringStream(&s) << ' ';\n//   OStringStream(&s) << 3.14;\n//\n// Creates a single instance of OStringStream and reuses it: fast.\n//\n//   std::string s;\n//   OStringStream strm(&s);\n//   strm << 42;\n//   strm << ' ';\n//   strm << 3.14;\n//\n// Note: flush() has no effect. No reason to call it.\nclass OStringStream final : public std::ostream {\n public:\n  // The argument can be null, in which case you'll need to call str(p) with a\n  // non-null argument before you can write to the stream.\n  //\n  // The destructor of OStringStream doesn't use the std::string. It's OK to\n  // destroy the std::string before the stream.\n  explicit OStringStream(std::string* str)\n      : std::ostream(&buf_), buf_(str) {}\n  OStringStream(OStringStream&& that)\n      : std::ostream(std::move(static_cast<std::ostream&>(that))),\n        buf_(that.buf_) {\n    rdbuf(&buf_);\n  }\n  OStringStream& operator=(OStringStream&& that) {\n    std::ostream::operator=(std::move(static_cast<std::ostream&>(that)));\n    buf_ = that.buf_;\n    rdbuf(&buf_);\n    return *this;\n  }\n\n  std::string* str() { return buf_.str(); }\n  const std::string* str() const { return buf_.str(); }\n  void str(std::string* str) { buf_.str(str); }\n\n private:\n  class Streambuf final : public std::streambuf {\n   public:\n    explicit Streambuf(std::string* str) : str_(str) {}\n    Streambuf(const Streambuf&) = default;\n    Streambuf& operator=(const Streambuf&) = default;\n\n    std::string* str() { return str_; }\n    const std::string* str() const { return str_; }\n    void str(std::string* str) { str_ = str; }\n\n   protected:\n    int_type overflow(int c) override;\n    std::streamsize xsputn(const char* s, std::streamsize n) override;\n\n   private:\n    std::string* str_;\n  } buf_;\n};\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_\n"
  },
  {
    "path": "absl/strings/internal/ostringstream_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <sstream>\n#include <string>\n\n#include \"absl/strings/internal/ostringstream.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nenum StringType {\n  kNone,\n  kStdString,\n};\n\n// Benchmarks for std::ostringstream.\ntemplate <StringType kOutput>\nvoid BM_StdStream(benchmark::State& state) {\n  const int num_writes = state.range(0);\n  const int bytes_per_write = state.range(1);\n  const std::string payload(bytes_per_write, 'x');\n  for (auto _ : state) {\n    std::ostringstream strm;\n    benchmark::DoNotOptimize(strm);\n    for (int i = 0; i != num_writes; ++i) {\n      strm << payload;\n    }\n    switch (kOutput) {\n      case kNone: {\n        break;\n      }\n      case kStdString: {\n        std::string s = strm.str();\n        benchmark::DoNotOptimize(s);\n        break;\n      }\n    }\n  }\n}\n\n// Create the stream, optionally write to it, then destroy it.\nBENCHMARK_TEMPLATE(BM_StdStream, kNone)\n    ->ArgPair(0, 0)\n    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO\n    ->ArgPair(1, 256)  // 256 bytes requires heap allocation\n    ->ArgPair(1024, 256);\n// Create the stream, write to it, get std::string out, then destroy.\nBENCHMARK_TEMPLATE(BM_StdStream, kStdString)\n    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO\n    ->ArgPair(1, 256)  // 256 bytes requires heap allocation\n    ->ArgPair(1024, 256);\n\n// Benchmarks for OStringStream.\ntemplate <StringType kOutput>\nvoid BM_CustomStream(benchmark::State& state) {\n  const int num_writes = state.range(0);\n  const int bytes_per_write = state.range(1);\n  const std::string payload(bytes_per_write, 'x');\n  for (auto _ : state) {\n    std::string out;\n    absl::strings_internal::OStringStream strm(&out);\n    benchmark::DoNotOptimize(strm);\n    for (int i = 0; i != num_writes; ++i) {\n      strm << payload;\n    }\n    switch (kOutput) {\n      case kNone: {\n        break;\n      }\n      case kStdString: {\n        std::string s = out;\n        benchmark::DoNotOptimize(s);\n        break;\n      }\n    }\n  }\n}\n\n// Create the stream, optionally write to it, then destroy it.\nBENCHMARK_TEMPLATE(BM_CustomStream, kNone)\n    ->ArgPair(0, 0)\n    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO\n    ->ArgPair(1, 256)  // 256 bytes requires heap allocation\n    ->ArgPair(1024, 256);\n// Create the stream, write to it, get std::string out, then destroy.\n// It's not useful in practice to extract std::string from OStringStream; we\n// measure it for completeness.\nBENCHMARK_TEMPLATE(BM_CustomStream, kStdString)\n    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO\n    ->ArgPair(1, 256)  // 256 bytes requires heap allocation\n    ->ArgPair(1024, 256);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/ostringstream_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/ostringstream.h\"\n\n#include <ios>\n#include <memory>\n#include <ostream>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nTEST(OStringStream, IsOStream) {\n  static_assert(\n      std::is_base_of<std::ostream, absl::strings_internal::OStringStream>(),\n      \"\");\n}\n\nTEST(OStringStream, ConstructNullptr) {\n  absl::strings_internal::OStringStream strm(nullptr);\n  EXPECT_EQ(nullptr, strm.str());\n}\n\nTEST(OStringStream, ConstructStr) {\n  std::string s = \"abc\";\n  {\n    absl::strings_internal::OStringStream strm(&s);\n    EXPECT_EQ(&s, strm.str());\n  }\n  EXPECT_EQ(\"abc\", s);\n}\n\nTEST(OStringStream, Destroy) {\n  std::unique_ptr<std::string> s(new std::string);\n  absl::strings_internal::OStringStream strm(s.get());\n  s.reset();\n}\n\nTEST(OStringStream, MoveConstruct) {\n  std::string s = \"abc\";\n  {\n    absl::strings_internal::OStringStream strm1(&s);\n    strm1 << std::hex << 16;\n    EXPECT_EQ(&s, strm1.str());\n    absl::strings_internal::OStringStream strm2(std::move(strm1));\n    strm2 << 16;  // We should still be in base 16.\n    EXPECT_EQ(&s, strm2.str());\n  }\n  EXPECT_EQ(\"abc1010\", s);\n}\n\nTEST(OStringStream, MoveAssign) {\n  std::string s = \"abc\";\n  {\n    absl::strings_internal::OStringStream strm1(&s);\n    strm1 << std::hex << 16;\n    EXPECT_EQ(&s, strm1.str());\n    absl::strings_internal::OStringStream strm2(nullptr);\n    strm2 = std::move(strm1);\n    strm2 << 16;  // We should still be in base 16.\n    EXPECT_EQ(&s, strm2.str());\n  }\n  EXPECT_EQ(\"abc1010\", s);\n}\n\nTEST(OStringStream, Str) {\n  std::string s1;\n  absl::strings_internal::OStringStream strm(&s1);\n  const absl::strings_internal::OStringStream& c_strm(strm);\n\n  static_assert(std::is_same<decltype(strm.str()), std::string*>(), \"\");\n  static_assert(std::is_same<decltype(c_strm.str()), const std::string*>(), \"\");\n\n  EXPECT_EQ(&s1, strm.str());\n  EXPECT_EQ(&s1, c_strm.str());\n\n  strm.str(&s1);\n  EXPECT_EQ(&s1, strm.str());\n  EXPECT_EQ(&s1, c_strm.str());\n\n  std::string s2;\n  strm.str(&s2);\n  EXPECT_EQ(&s2, strm.str());\n  EXPECT_EQ(&s2, c_strm.str());\n\n  strm.str(nullptr);\n  EXPECT_EQ(nullptr, strm.str());\n  EXPECT_EQ(nullptr, c_strm.str());\n}\n\nTEST(OStreamStream, WriteToLValue) {\n  std::string s = \"abc\";\n  {\n    absl::strings_internal::OStringStream strm(&s);\n    EXPECT_EQ(\"abc\", s);\n    strm << \"\";\n    EXPECT_EQ(\"abc\", s);\n    strm << 42;\n    EXPECT_EQ(\"abc42\", s);\n    strm << 'x' << 'y';\n    EXPECT_EQ(\"abc42xy\", s);\n  }\n  EXPECT_EQ(\"abc42xy\", s);\n}\n\nTEST(OStreamStream, WriteToRValue) {\n  std::string s = \"abc\";\n  absl::strings_internal::OStringStream(&s) << \"\";\n  EXPECT_EQ(\"abc\", s);\n  absl::strings_internal::OStringStream(&s) << 42;\n  EXPECT_EQ(\"abc42\", s);\n  absl::strings_internal::OStringStream(&s) << 'x' << 'y';\n  EXPECT_EQ(\"abc42xy\", s);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/pow10_helper.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/pow10_helper.h\"\n\n#include <cmath>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nnamespace {\n\n// The exact value of 1e23 falls precisely halfway between two representable\n// doubles. Furthermore, the rounding rules we prefer (break ties by rounding\n// to the nearest even) dictate in this case that the number should be rounded\n// down, but this is not completely specified for floating-point literals in\n// C++. (It just says to use the default rounding mode of the standard\n// library.) We ensure the result we want by using a number that has an\n// unambiguous correctly rounded answer.\nconstexpr double k1e23 = 9999999999999999e7;\n\nconstexpr double kPowersOfTen[] = {\n    0.0,    1e-323, 1e-322, 1e-321, 1e-320, 1e-319, 1e-318, 1e-317, 1e-316,\n    1e-315, 1e-314, 1e-313, 1e-312, 1e-311, 1e-310, 1e-309, 1e-308, 1e-307,\n    1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299, 1e-298,\n    1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290, 1e-289,\n    1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281, 1e-280,\n    1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,\n    1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262,\n    1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253,\n    1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244,\n    1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235,\n    1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227, 1e-226,\n    1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218, 1e-217,\n    1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209, 1e-208,\n    1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200, 1e-199,\n    1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191, 1e-190,\n    1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,\n    1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172,\n    1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163,\n    1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154,\n    1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145,\n    1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137, 1e-136,\n    1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128, 1e-127,\n    1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119, 1e-118,\n    1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110, 1e-109,\n    1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101, 1e-100,\n    1e-99,  1e-98,  1e-97,  1e-96,  1e-95,  1e-94,  1e-93,  1e-92,  1e-91,\n    1e-90,  1e-89,  1e-88,  1e-87,  1e-86,  1e-85,  1e-84,  1e-83,  1e-82,\n    1e-81,  1e-80,  1e-79,  1e-78,  1e-77,  1e-76,  1e-75,  1e-74,  1e-73,\n    1e-72,  1e-71,  1e-70,  1e-69,  1e-68,  1e-67,  1e-66,  1e-65,  1e-64,\n    1e-63,  1e-62,  1e-61,  1e-60,  1e-59,  1e-58,  1e-57,  1e-56,  1e-55,\n    1e-54,  1e-53,  1e-52,  1e-51,  1e-50,  1e-49,  1e-48,  1e-47,  1e-46,\n    1e-45,  1e-44,  1e-43,  1e-42,  1e-41,  1e-40,  1e-39,  1e-38,  1e-37,\n    1e-36,  1e-35,  1e-34,  1e-33,  1e-32,  1e-31,  1e-30,  1e-29,  1e-28,\n    1e-27,  1e-26,  1e-25,  1e-24,  1e-23,  1e-22,  1e-21,  1e-20,  1e-19,\n    1e-18,  1e-17,  1e-16,  1e-15,  1e-14,  1e-13,  1e-12,  1e-11,  1e-10,\n    1e-9,   1e-8,   1e-7,   1e-6,   1e-5,   1e-4,   1e-3,   1e-2,   1e-1,\n    1e+0,   1e+1,   1e+2,   1e+3,   1e+4,   1e+5,   1e+6,   1e+7,   1e+8,\n    1e+9,   1e+10,  1e+11,  1e+12,  1e+13,  1e+14,  1e+15,  1e+16,  1e+17,\n    1e+18,  1e+19,  1e+20,  1e+21,  1e+22,  k1e23,  1e+24,  1e+25,  1e+26,\n    1e+27,  1e+28,  1e+29,  1e+30,  1e+31,  1e+32,  1e+33,  1e+34,  1e+35,\n    1e+36,  1e+37,  1e+38,  1e+39,  1e+40,  1e+41,  1e+42,  1e+43,  1e+44,\n    1e+45,  1e+46,  1e+47,  1e+48,  1e+49,  1e+50,  1e+51,  1e+52,  1e+53,\n    1e+54,  1e+55,  1e+56,  1e+57,  1e+58,  1e+59,  1e+60,  1e+61,  1e+62,\n    1e+63,  1e+64,  1e+65,  1e+66,  1e+67,  1e+68,  1e+69,  1e+70,  1e+71,\n    1e+72,  1e+73,  1e+74,  1e+75,  1e+76,  1e+77,  1e+78,  1e+79,  1e+80,\n    1e+81,  1e+82,  1e+83,  1e+84,  1e+85,  1e+86,  1e+87,  1e+88,  1e+89,\n    1e+90,  1e+91,  1e+92,  1e+93,  1e+94,  1e+95,  1e+96,  1e+97,  1e+98,\n    1e+99,  1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107,\n    1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116,\n    1e+117, 1e+118, 1e+119, 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125,\n    1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134,\n    1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+141, 1e+142, 1e+143,\n    1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152,\n    1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+161,\n    1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170,\n    1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,\n    1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188,\n    1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197,\n    1e+198, 1e+199, 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206,\n    1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215,\n    1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+221, 1e+222, 1e+223, 1e+224,\n    1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233,\n    1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, 1e+241, 1e+242,\n    1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251,\n    1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260,\n    1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,\n    1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278,\n    1e+279, 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287,\n    1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296,\n    1e+297, 1e+298, 1e+299, 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305,\n    1e+306, 1e+307, 1e+308,\n};\n\n}  // namespace\n\ndouble Pow10(int exp) {\n  if (exp < -324) {\n    return 0.0;\n  } else if (exp > 308) {\n    return INFINITY;\n  } else {\n    return kPowersOfTen[exp + 324];\n  }\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/pow10_helper.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// This test helper library contains a table of powers of 10, to guarantee\n// precise values are computed across the full range of doubles. We can't rely\n// on the pow() function, because not all standard libraries ship a version\n// that is precise.\n#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_\n#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_\n\n#include <vector>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// Computes the precise value of 10^exp. (I.e. the nearest representable\n// double to the exact value, rounding to nearest-even in the (single) case of\n// being exactly halfway between.)\ndouble Pow10(int exp);\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_\n"
  },
  {
    "path": "absl/strings/internal/pow10_helper_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/pow10_helper.h\"\n\n#include <cmath>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nnamespace {\n\nstruct TestCase {\n  int power;           // Testing Pow10(power)\n  uint64_t significand;  // Raw bits of the expected value\n  int radix;           // significand is adjusted by 2^radix\n};\n\nTEST(Pow10HelperTest, Works) {\n  // The logic in pow10_helper.cc is so simple that theoretically we don't even\n  // need a test. However, we're paranoid and believe that there may be\n  // compilers that don't round floating-point literals correctly, even though\n  // it is specified by the standard. We check various edge cases, just to be\n  // sure.\n  constexpr TestCase kTestCases[] = {\n      // Subnormals\n      {-323, 0x2, -1074},\n      {-322, 0x14, -1074},\n      {-321, 0xca, -1074},\n      {-320, 0x7e8, -1074},\n      {-319, 0x4f10, -1074},\n      {-318, 0x316a2, -1074},\n      {-317, 0x1ee257, -1074},\n      {-316, 0x134d761, -1074},\n      {-315, 0xc1069cd, -1074},\n      {-314, 0x78a42205, -1074},\n      {-313, 0x4b6695433, -1074},\n      {-312, 0x2f201d49fb, -1074},\n      {-311, 0x1d74124e3d1, -1074},\n      {-310, 0x12688b70e62b, -1074},\n      {-309, 0xb8157268fdaf, -1074},\n      {-308, 0x730d67819e8d2, -1074},\n      // Values that are very close to rounding the other way.\n      // Comment shows difference of significand from the true value.\n      {-307, 0x11fa182c40c60d, -1072},  // -.4588\n      {-290, 0x18f2b061aea072, -1016},  //  .4854\n      {-276, 0x11BA03F5B21000, -969},   //  .4709\n      {-259, 0x1899C2F6732210, -913},   //  .4830\n      {-252, 0x1D53844EE47DD1, -890},   // -.4743\n      {-227, 0x1E5297287C2F45, -807},   // -.4708\n      {-198, 0x1322E220A5B17E, -710},   // -.4714\n      {-195, 0x12B010D3E1CF56, -700},   //  .4928\n      {-192, 0x123FF06EEA847A, -690},   //  .4968\n      {-163, 0x1708D0F84D3DE7, -594},   // -.4977\n      {-145, 0x13FAAC3E3FA1F3, -534},   // -.4785\n      {-111, 0x133D4032C2C7F5, -421},   //  .4774\n      {-106, 0x1D5B561574765B, -405},   // -.4869\n      {-104, 0x16EF5B40C2FC77, -398},   // -.4741\n      {-88, 0x197683DF2F268D, -345},    // -.4738\n      {-86, 0x13E497065CD61F, -338},    //  .4736\n      {-76, 0x17288E1271F513, -305},    // -.4761\n      {-63, 0x1A53FC9631D10D, -262},    //  .4929\n      {-30, 0x14484BFEEBC2A0, -152},    //  .4758\n      {-21, 0x12E3B40A0E9B4F, -122},    // -.4916\n      {-5, 0x14F8B588E368F1, -69},      //  .4829\n      {23, 0x152D02C7E14AF6, 24},       // -.5000 (exactly, round-to-even)\n      {29, 0x1431E0FAE6D721, 44},       // -.4870\n      {34, 0x1ED09BEAD87C03, 60},       // -.4721\n      {70, 0x172EBAD6DDC73D, 180},      //  .4733\n      {105, 0x1BE7ABD3781ECA, 296},     // -.4850\n      {126, 0x17A2ECC414A03F, 366},     // -.4999\n      {130, 0x1CDA62055B2D9E, 379},     //  .4855\n      {165, 0x115D847AD00087, 496},     // -.4913\n      {172, 0x14B378469B6732, 519},     //  .4818\n      {187, 0x1262DFEEBBB0F9, 569},     // -.4805\n      {210, 0x18557F31326BBB, 645},     // -.4992\n      {212, 0x1302CB5E6F642A, 652},     // -.4838\n      {215, 0x1290BA9A38C7D1, 662},     // -.4881\n      {236, 0x1F736F9B3494E9, 731},     //  .4707\n      {244, 0x176EC98994F489, 758},     //  .4924\n      {250, 0x1658E3AB795204, 778},     // -.4963\n      {252, 0x117571DDF6C814, 785},     //  .4873\n      {254, 0x1B4781EAD1989E, 791},     // -.4887\n      {260, 0x1A03FDE214CAF1, 811},     //  .4784\n      {284, 0x1585041B2C477F, 891},     //  .4798\n      {304, 0x1D2A1BE4048F90, 957},     // -.4987\n      // Out-of-range values\n      {-324, 0x0, 0},\n      {-325, 0x0, 0},\n      {-326, 0x0, 0},\n      {309, 1, 2000},\n      {310, 1, 2000},\n      {311, 1, 2000},\n  };\n  for (const TestCase& test_case : kTestCases) {\n    EXPECT_EQ(Pow10(test_case.power),\n              std::ldexp(test_case.significand, test_case.radix))\n        << absl::StrFormat(\"Failure for Pow10(%d): %a vs %a\", test_case.power,\n                           Pow10(test_case.power),\n                           std::ldexp(test_case.significand, test_case.radix));\n  }\n}\n\n}  // namespace\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/resize_uninitialized.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_\n#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_\n\n#include <algorithm>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"\n#include \"absl/meta/type_traits.h\"  //  for void_t\n#include \"absl/strings/resize_and_overwrite.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// In this type trait, we look for a __resize_default_init member function, and\n// we use it if available, otherwise, we use resize. We provide HasMember to\n// indicate whether __resize_default_init is present.\ntemplate <typename string_type, typename = void>\nstruct ResizeUninitializedTraits {\n  using HasMember = std::false_type;\n  static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }\n};\n\n// __resize_default_init is provided by libc++ >= 8.0\ntemplate <typename string_type>\nstruct ResizeUninitializedTraits<\n    string_type, absl::void_t<decltype(std::declval<string_type&>()\n                                           .__resize_default_init(237))> > {\n  using HasMember = std::true_type;\n  static void Resize(string_type* s, size_t new_size) {\n    s->__resize_default_init(new_size);\n  }\n};\n\n// Returns true if the std::string implementation supports a resize where\n// the new characters added to the std::string are left untouched.\n//\n// (A better name might be \"STLStringSupportsUninitializedResize\", alluding to\n// the previous function.)\ntemplate <typename string_type>\ninline constexpr bool STLStringSupportsNontrashingResize(string_type*) {\n  return ResizeUninitializedTraits<string_type>::HasMember::value;\n}\n\n// Like str->resize(new_size), except any new characters added to \"*str\" as a\n// result of resizing may be left uninitialized, rather than being filled with\n// '0' bytes. Typically used when code is then going to overwrite the backing\n// store of the std::string with known data.\ntemplate <typename string_type, typename = void>\ninline void STLStringResizeUninitialized(string_type* s, size_t new_size) {\n  ResizeUninitializedTraits<string_type>::Resize(s, new_size);\n}\n\n// Like STLStringResizeUninitialized(str, new_size), except guaranteed to use\n// exponential growth so that the amortized complexity of increasing the string\n// size by a small amount is O(1), in contrast to O(str->size()) in the case of\n// precise growth.\n//\n// TODO: b/446221957 - Delete this function.\ntemplate <typename string_type>\n[[deprecated]]\nvoid STLStringResizeUninitializedAmortized(string_type* s, size_t new_size) {\n  if (new_size > s->size()) {\n    if (new_size > s->capacity()) {\n      // Make sure to always grow by at least a factor of 2x. Change min_growth\n      // if you want to experiment with other growth strategies.\n      const auto min_growth = s->capacity();\n      if (ABSL_PREDICT_FALSE(s->capacity() > s->max_size() - min_growth)) {\n        s->reserve(s->max_size());\n      } else if (new_size < s->capacity() + min_growth) {\n        s->reserve(s->capacity() + min_growth);\n      }\n    }\n    // This calls absl::strings_internal::StringResizeAndOverwriteImpl() because\n    // the public API absl::StringResizeAndOverwrite() verifies that the\n    // required range has been initialized. No other code should be calling\n    // absl::strings_internal::StringResizeAndOverwriteImpl(). Instead it should\n    // be implemented correctly with absl::StringResizeAndOverwrite().\n    absl::strings_internal::StringResizeAndOverwriteImpl(\n        *s, new_size, [](typename string_type::value_type*, size_t buf_size) {\n          // TODO: b/446221957 - It is undefined behavior if any character in\n          // the range [0, return_value) is uninitialized, but we rely on this\n          // here to implement the old STLStringResizeUninitializedAmortized()\n          // API.\n          return buf_size;\n        });\n  } else {\n    s->erase(new_size);\n  }\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_\n"
  },
  {
    "path": "absl/strings/internal/resize_uninitialized_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/resize_uninitialized.h\"\n\n#include <cstddef>\n#include <limits>\n\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nint resize_call_count = 0;\n\n// A mock string class whose only purpose is to track how many times its\n// resize() method has been called.\nstruct resizable_string {\n  using value_type = char;\n  using size_type = size_t;\n  size_t size() const { return 0; }\n  size_t capacity() const { return 0; }\n  char* data() { return buffer; }\n  char& operator[](size_t) { return buffer[0]; }\n  void resize(size_t) { resize_call_count += 1; }\n  void reserve(size_t) {}\n  resizable_string& erase(size_t = 0, size_t = 0) { return *this; }\n  size_t max_size() const { return std::numeric_limits<size_t>::max(); }\n  char buffer[1] = {};\n};\n\nint resize_default_init_call_count = 0;\n\n// A mock string class whose only purpose is to track how many times its\n// resize()/__resize_default_init() methods have been called.\nstruct default_init_string {\n  using value_type = char;\n  using size_type = size_t;\n  size_t size() const { return 0; }\n  size_t capacity() const { return 0; }\n  char* data() { return buffer; }\n  char& operator[](size_t) { return buffer[0]; }\n  void resize(size_t) { resize_call_count += 1; }\n  void __resize_default_init(size_t) { resize_default_init_call_count += 1; }\n  void reserve(size_t) {}\n  default_init_string& erase(size_t = 0, size_t = 0) { return *this; }\n  size_t max_size() const { return std::numeric_limits<size_t>::max(); }\n  char buffer[1];\n};\n\nTEST(ResizeUninit, WithAndWithout) {\n  resize_call_count = 0;\n  resize_default_init_call_count = 0;\n  {\n    resizable_string rs;\n\n    EXPECT_EQ(resize_call_count, 0);\n    EXPECT_EQ(resize_default_init_call_count, 0);\n    EXPECT_FALSE(\n        absl::strings_internal::STLStringSupportsNontrashingResize(&rs));\n    EXPECT_EQ(resize_call_count, 0);\n    EXPECT_EQ(resize_default_init_call_count, 0);\n    absl::strings_internal::STLStringResizeUninitialized(&rs, 237);\n    EXPECT_EQ(resize_call_count, 1);\n    EXPECT_EQ(resize_default_init_call_count, 0);\n  }\n\n  resize_call_count = 0;\n  resize_default_init_call_count = 0;\n  {\n    default_init_string rus;\n\n    EXPECT_EQ(resize_call_count, 0);\n    EXPECT_EQ(resize_default_init_call_count, 0);\n    EXPECT_TRUE(\n        absl::strings_internal::STLStringSupportsNontrashingResize(&rus));\n    EXPECT_EQ(resize_call_count, 0);\n    EXPECT_EQ(resize_default_init_call_count, 0);\n    absl::strings_internal::STLStringResizeUninitialized(&rus, 237);\n    EXPECT_EQ(resize_call_count, 0);\n    EXPECT_EQ(resize_default_init_call_count, 1);\n  }\n}\n\nTEST(ResizeUninit, Amortized) {\n  std::string str;\n  size_t prev_cap = str.capacity();\n  int cap_increase_count = 0;\n  for (int i = 0; i < 1000; ++i) {\n    absl::strings_internal::STLStringResizeUninitializedAmortized(&str, i);\n    size_t new_cap = str.capacity();\n    if (new_cap > prev_cap) ++cap_increase_count;\n    prev_cap = new_cap;\n  }\n  EXPECT_LT(cap_increase_count, 50);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/stl_type_traits.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n// The file provides the IsStrictlyBaseOfAndConvertibleToSTLContainer type\n// trait metafunction to assist in working with the _GLIBCXX_DEBUG debug\n// wrappers of STL containers.\n//\n// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including\n// absl/strings/str_split.h.\n//\n// IWYU pragma: private, include \"absl/strings/str_split.h\"\n\n#ifndef ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_\n#define ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_\n\n#include <array>\n#include <bitset>\n#include <deque>\n#include <forward_list>\n#include <list>\n#include <map>\n#include <set>\n#include <type_traits>\n#include <unordered_map>\n#include <unordered_set>\n#include <vector>\n\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\ntemplate <typename C, template <typename...> class T>\nstruct IsSpecializationImpl : std::false_type {};\ntemplate <template <typename...> class T, typename... Args>\nstruct IsSpecializationImpl<T<Args...>, T> : std::true_type {};\ntemplate <typename C, template <typename...> class T>\nusing IsSpecialization = IsSpecializationImpl<absl::decay_t<C>, T>;\n\ntemplate <typename C>\nstruct IsArrayImpl : std::false_type {};\ntemplate <template <typename, size_t> class A, typename T, size_t N>\nstruct IsArrayImpl<A<T, N>> : std::is_same<A<T, N>, std::array<T, N>> {};\ntemplate <typename C>\nusing IsArray = IsArrayImpl<absl::decay_t<C>>;\n\ntemplate <typename C>\nstruct IsBitsetImpl : std::false_type {};\ntemplate <template <size_t> class B, size_t N>\nstruct IsBitsetImpl<B<N>> : std::is_same<B<N>, std::bitset<N>> {};\ntemplate <typename C>\nusing IsBitset = IsBitsetImpl<absl::decay_t<C>>;\n\ntemplate <typename C>\nstruct IsSTLContainer\n    : absl::disjunction<\n          IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>,\n          IsSpecialization<C, std::forward_list>,\n          IsSpecialization<C, std::list>, IsSpecialization<C, std::map>,\n          IsSpecialization<C, std::multimap>, IsSpecialization<C, std::set>,\n          IsSpecialization<C, std::multiset>,\n          IsSpecialization<C, std::unordered_map>,\n          IsSpecialization<C, std::unordered_multimap>,\n          IsSpecialization<C, std::unordered_set>,\n          IsSpecialization<C, std::unordered_multiset>,\n          IsSpecialization<C, std::vector>> {};\n\ntemplate <typename C, template <typename...> class T, typename = void>\nstruct IsBaseOfSpecializationImpl : std::false_type {};\n// IsBaseOfSpecializationImpl needs multiple partial specializations to SFINAE\n// on the existence of container dependent types and plug them into the STL\n// template.\ntemplate <typename C, template <typename, typename> class T>\nstruct IsBaseOfSpecializationImpl<\n    C, T, absl::void_t<typename C::value_type, typename C::allocator_type>>\n    : std::is_base_of<C,\n                      T<typename C::value_type, typename C::allocator_type>> {};\ntemplate <typename C, template <typename, typename, typename> class T>\nstruct IsBaseOfSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::key_compare,\n                 typename C::allocator_type>>\n    : std::is_base_of<C, T<typename C::key_type, typename C::key_compare,\n                           typename C::allocator_type>> {};\ntemplate <typename C, template <typename, typename, typename, typename> class T>\nstruct IsBaseOfSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::mapped_type,\n                 typename C::key_compare, typename C::allocator_type>>\n    : std::is_base_of<C,\n                      T<typename C::key_type, typename C::mapped_type,\n                        typename C::key_compare, typename C::allocator_type>> {\n};\ntemplate <typename C, template <typename, typename, typename, typename> class T>\nstruct IsBaseOfSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::hasher,\n                 typename C::key_equal, typename C::allocator_type>>\n    : std::is_base_of<C, T<typename C::key_type, typename C::hasher,\n                           typename C::key_equal, typename C::allocator_type>> {\n};\ntemplate <typename C,\n          template <typename, typename, typename, typename, typename> class T>\nstruct IsBaseOfSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::mapped_type,\n                 typename C::hasher, typename C::key_equal,\n                 typename C::allocator_type>>\n    : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type,\n                           typename C::hasher, typename C::key_equal,\n                           typename C::allocator_type>> {};\ntemplate <typename C, template <typename...> class T>\nusing IsBaseOfSpecialization = IsBaseOfSpecializationImpl<absl::decay_t<C>, T>;\n\ntemplate <typename C>\nstruct IsBaseOfArrayImpl : std::false_type {};\ntemplate <template <typename, size_t> class A, typename T, size_t N>\nstruct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> {\n};\ntemplate <typename C>\nusing IsBaseOfArray = IsBaseOfArrayImpl<absl::decay_t<C>>;\n\ntemplate <typename C>\nstruct IsBaseOfBitsetImpl : std::false_type {};\ntemplate <template <size_t> class B, size_t N>\nstruct IsBaseOfBitsetImpl<B<N>> : std::is_base_of<B<N>, std::bitset<N>> {};\ntemplate <typename C>\nusing IsBaseOfBitset = IsBaseOfBitsetImpl<absl::decay_t<C>>;\n\ntemplate <typename C>\nstruct IsBaseOfSTLContainer\n    : absl::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>,\n                        IsBaseOfSpecialization<C, std::deque>,\n                        IsBaseOfSpecialization<C, std::forward_list>,\n                        IsBaseOfSpecialization<C, std::list>,\n                        IsBaseOfSpecialization<C, std::map>,\n                        IsBaseOfSpecialization<C, std::multimap>,\n                        IsBaseOfSpecialization<C, std::set>,\n                        IsBaseOfSpecialization<C, std::multiset>,\n                        IsBaseOfSpecialization<C, std::unordered_map>,\n                        IsBaseOfSpecialization<C, std::unordered_multimap>,\n                        IsBaseOfSpecialization<C, std::unordered_set>,\n                        IsBaseOfSpecialization<C, std::unordered_multiset>,\n                        IsBaseOfSpecialization<C, std::vector>> {};\n\ntemplate <typename C, template <typename...> class T, typename = void>\nstruct IsConvertibleToSpecializationImpl : std::false_type {};\n// IsConvertibleToSpecializationImpl needs multiple partial specializations to\n// SFINAE on the existence of container dependent types and plug them into the\n// STL template.\ntemplate <typename C, template <typename, typename> class T>\nstruct IsConvertibleToSpecializationImpl<\n    C, T, absl::void_t<typename C::value_type, typename C::allocator_type>>\n    : std::is_convertible<\n          C, T<typename C::value_type, typename C::allocator_type>> {};\ntemplate <typename C, template <typename, typename, typename> class T>\nstruct IsConvertibleToSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::key_compare,\n                 typename C::allocator_type>>\n    : std::is_convertible<C, T<typename C::key_type, typename C::key_compare,\n                               typename C::allocator_type>> {};\ntemplate <typename C, template <typename, typename, typename, typename> class T>\nstruct IsConvertibleToSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::mapped_type,\n                 typename C::key_compare, typename C::allocator_type>>\n    : std::is_convertible<\n          C, T<typename C::key_type, typename C::mapped_type,\n               typename C::key_compare, typename C::allocator_type>> {};\ntemplate <typename C, template <typename, typename, typename, typename> class T>\nstruct IsConvertibleToSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::hasher,\n                 typename C::key_equal, typename C::allocator_type>>\n    : std::is_convertible<\n          C, T<typename C::key_type, typename C::hasher, typename C::key_equal,\n               typename C::allocator_type>> {};\ntemplate <typename C,\n          template <typename, typename, typename, typename, typename> class T>\nstruct IsConvertibleToSpecializationImpl<\n    C, T,\n    absl::void_t<typename C::key_type, typename C::mapped_type,\n                 typename C::hasher, typename C::key_equal,\n                 typename C::allocator_type>>\n    : std::is_convertible<C, T<typename C::key_type, typename C::mapped_type,\n                               typename C::hasher, typename C::key_equal,\n                               typename C::allocator_type>> {};\ntemplate <typename C, template <typename...> class T>\nusing IsConvertibleToSpecialization =\n    IsConvertibleToSpecializationImpl<absl::decay_t<C>, T>;\n\ntemplate <typename C>\nstruct IsConvertibleToArrayImpl : std::false_type {};\ntemplate <template <typename, size_t> class A, typename T, size_t N>\nstruct IsConvertibleToArrayImpl<A<T, N>>\n    : std::is_convertible<A<T, N>, std::array<T, N>> {};\ntemplate <typename C>\nusing IsConvertibleToArray = IsConvertibleToArrayImpl<absl::decay_t<C>>;\n\ntemplate <typename C>\nstruct IsConvertibleToBitsetImpl : std::false_type {};\ntemplate <template <size_t> class B, size_t N>\nstruct IsConvertibleToBitsetImpl<B<N>>\n    : std::is_convertible<B<N>, std::bitset<N>> {};\ntemplate <typename C>\nusing IsConvertibleToBitset = IsConvertibleToBitsetImpl<absl::decay_t<C>>;\n\ntemplate <typename C>\nstruct IsConvertibleToSTLContainer\n    : absl::disjunction<\n          IsConvertibleToArray<C>, IsConvertibleToBitset<C>,\n          IsConvertibleToSpecialization<C, std::deque>,\n          IsConvertibleToSpecialization<C, std::forward_list>,\n          IsConvertibleToSpecialization<C, std::list>,\n          IsConvertibleToSpecialization<C, std::map>,\n          IsConvertibleToSpecialization<C, std::multimap>,\n          IsConvertibleToSpecialization<C, std::set>,\n          IsConvertibleToSpecialization<C, std::multiset>,\n          IsConvertibleToSpecialization<C, std::unordered_map>,\n          IsConvertibleToSpecialization<C, std::unordered_multimap>,\n          IsConvertibleToSpecialization<C, std::unordered_set>,\n          IsConvertibleToSpecialization<C, std::unordered_multiset>,\n          IsConvertibleToSpecialization<C, std::vector>> {};\n\ntemplate <typename C>\nstruct IsStrictlyBaseOfAndConvertibleToSTLContainer\n    : absl::conjunction<absl::negation<IsSTLContainer<C>>,\n                        IsBaseOfSTLContainer<C>,\n                        IsConvertibleToSTLContainer<C>> {};\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/arg.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n//\n// POSIX spec:\n//   http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html\n//\n#include \"absl/strings/internal/str_format/arg.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <cwchar>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/container/fixed_array.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/internal/str_format/float_conversion.h\"\n#include \"absl/strings/internal/utf8.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\nnamespace {\n\n// Reduce *capacity by s.size(), clipped to a 0 minimum.\nvoid ReducePadding(string_view s, size_t *capacity) {\n  *capacity = Excess(s.size(), *capacity);\n}\n\n// Reduce *capacity by n, clipped to a 0 minimum.\nvoid ReducePadding(size_t n, size_t *capacity) {\n  *capacity = Excess(n, *capacity);\n}\n\ntemplate <typename T>\nstruct MakeUnsigned : std::make_unsigned<T> {};\ntemplate <>\nstruct MakeUnsigned<absl::int128> {\n  using type = absl::uint128;\n};\ntemplate <>\nstruct MakeUnsigned<absl::uint128> {\n  using type = absl::uint128;\n};\n\ntemplate <typename T>\nstruct IsSigned : std::is_signed<T> {};\ntemplate <>\nstruct IsSigned<absl::int128> : std::true_type {};\ntemplate <>\nstruct IsSigned<absl::uint128> : std::false_type {};\n\n// Integral digit printer.\n// Call one of the PrintAs* routines after construction once.\n// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.\nclass IntDigits {\n public:\n  // Print the unsigned integer as octal.\n  // Supports unsigned integral types and uint128.\n  template <typename T>\n  void PrintAsOct(T v) {\n    static_assert(!IsSigned<T>::value, \"\");\n    char *p = storage_ + sizeof(storage_);\n    do {\n      *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));\n      v >>= 3;\n    } while (v);\n    start_ = p;\n    size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);\n  }\n\n  // Print the signed or unsigned integer as decimal.\n  // Supports all integral types.\n  template <typename T>\n  void PrintAsDec(T v) {\n    static_assert(std::is_integral<T>::value, \"\");\n    start_ = storage_;\n    size_ = static_cast<size_t>(numbers_internal::FastIntToBuffer(v, storage_) -\n                                storage_);\n  }\n\n  void PrintAsDec(int128 v) {\n    auto u = static_cast<uint128>(v);\n    bool add_neg = false;\n    if (v < 0) {\n      add_neg = true;\n      u = uint128{} - u;\n    }\n    PrintAsDec(u, add_neg);\n  }\n\n  void PrintAsDec(uint128 v, bool add_neg = false) {\n    // This function can be sped up if needed. We can call FastIntToBuffer\n    // twice, or fix FastIntToBuffer to support uint128.\n    char *p = storage_ + sizeof(storage_);\n    do {\n      p -= 2;\n      numbers_internal::PutTwoDigits(static_cast<uint32_t>(v % 100), p);\n      v /= 100;\n    } while (v);\n    if (p[0] == '0') {\n      // We printed one too many hexits.\n      ++p;\n    }\n    if (add_neg) {\n      *--p = '-';\n    }\n    size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);\n    start_ = p;\n  }\n\n  // Print the unsigned integer as hex using lowercase.\n  // Supports unsigned integral types and uint128.\n  template <typename T>\n  void PrintAsHexLower(T v) {\n    static_assert(!IsSigned<T>::value, \"\");\n    char *p = storage_ + sizeof(storage_);\n\n    do {\n      p -= 2;\n      constexpr const char* table = numbers_internal::kHexTable;\n      std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);\n      if (sizeof(T) == 1) break;\n      v >>= 8;\n    } while (v);\n    if (p[0] == '0') {\n      // We printed one too many digits.\n      ++p;\n    }\n    start_ = p;\n    size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);\n  }\n\n  // Print the unsigned integer as hex using uppercase.\n  // Supports unsigned integral types and uint128.\n  template <typename T>\n  void PrintAsHexUpper(T v) {\n    static_assert(!IsSigned<T>::value, \"\");\n    char *p = storage_ + sizeof(storage_);\n\n    // kHexTable is only lowercase, so do it manually for uppercase.\n    do {\n      *--p = \"0123456789ABCDEF\"[static_cast<size_t>(v) & 15];\n      v >>= 4;\n    } while (v);\n    start_ = p;\n    size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);\n  }\n\n  // The printed value including the '-' sign if available.\n  // For inputs of value `0`, this will return \"0\"\n  string_view with_neg_and_zero() const { return {start_, size_}; }\n\n  // The printed value not including the '-' sign.\n  // For inputs of value `0`, this will return \"\".\n  string_view without_neg_or_zero() const {\n    static_assert('-' < '0', \"The check below verifies both.\");\n    size_t advance = start_[0] <= '0' ? 1 : 0;\n    return {start_ + advance, size_ - advance};\n  }\n\n  bool is_negative() const { return start_[0] == '-'; }\n\n private:\n  const char *start_;\n  size_t size_;\n  // Max size: 128 bit value as octal -> 43 digits, plus sign char\n  char storage_[128 / 3 + 1 + 1];\n};\n\n// Note: 'o' conversions do not have a base indicator, it's just that\n// the '#' flag is specified to modify the precision for 'o' conversions.\nstring_view BaseIndicator(const IntDigits &as_digits,\n                          const FormatConversionSpecImpl conv) {\n  // always show 0x for %p.\n  bool alt = conv.has_alt_flag() ||\n             conv.conversion_char() == FormatConversionCharInternal::p;\n  bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||\n              conv.conversion_char() == FormatConversionCharInternal::X ||\n              conv.conversion_char() == FormatConversionCharInternal::p);\n  // From the POSIX description of '#' flag:\n  //   \"For x or X conversion specifiers, a non-zero result shall have\n  //   0x (or 0X) prefixed to it.\"\n  if (alt && hex && !as_digits.without_neg_or_zero().empty()) {\n    return conv.conversion_char() == FormatConversionCharInternal::X ? \"0X\"\n                                                                     : \"0x\";\n  }\n  return {};\n}\n\nstring_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {\n  if (conv.conversion_char() == FormatConversionCharInternal::d ||\n      conv.conversion_char() == FormatConversionCharInternal::i) {\n    if (neg) return \"-\";\n    if (conv.has_show_pos_flag()) return \"+\";\n    if (conv.has_sign_col_flag()) return \" \";\n  }\n  return {};\n}\n\nbool ConvertCharImpl(char v,\n                     const FormatConversionSpecImpl conv,\n                     FormatSinkImpl* sink) {\n  size_t fill = 0;\n  if (conv.width() >= 0)\n    fill = static_cast<size_t>(conv.width());\n  ReducePadding(1, &fill);\n  if (!conv.has_left_flag()) sink->Append(fill, ' ');\n  sink->Append(1, v);\n  if (conv.has_left_flag()) sink->Append(fill, ' ');\n  return true;\n}\n\nbool ConvertIntImplInnerSlow(const IntDigits &as_digits,\n                             const FormatConversionSpecImpl conv,\n                             FormatSinkImpl *sink) {\n  // Print as a sequence of Substrings:\n  //   [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]\n  size_t fill = 0;\n  if (conv.width() >= 0)\n    fill = static_cast<size_t>(conv.width());\n\n  string_view formatted = as_digits.without_neg_or_zero();\n  ReducePadding(formatted, &fill);\n\n  string_view sign = SignColumn(as_digits.is_negative(), conv);\n  ReducePadding(sign, &fill);\n\n  string_view base_indicator = BaseIndicator(as_digits, conv);\n  ReducePadding(base_indicator, &fill);\n\n  bool precision_specified = conv.precision() >= 0;\n  size_t precision =\n      precision_specified ? static_cast<size_t>(conv.precision()) : size_t{1};\n\n  if (conv.has_alt_flag() &&\n      conv.conversion_char() == FormatConversionCharInternal::o) {\n    // From POSIX description of the '#' (alt) flag:\n    //   \"For o conversion, it increases the precision (if necessary) to\n    //   force the first digit of the result to be zero.\"\n    if (formatted.empty() || *formatted.begin() != '0') {\n      size_t needed = formatted.size() + 1;\n      precision = std::max(precision, needed);\n    }\n  }\n\n  size_t num_zeroes = Excess(formatted.size(), precision);\n  ReducePadding(num_zeroes, &fill);\n\n  size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;\n  size_t num_right_spaces = conv.has_left_flag() ? fill : 0;\n\n  // From POSIX description of the '0' (zero) flag:\n  //   \"For d, i, o, u, x, and X conversion specifiers, if a precision\n  //   is specified, the '0' flag is ignored.\"\n  if (!precision_specified && conv.has_zero_flag()) {\n    num_zeroes += num_left_spaces;\n    num_left_spaces = 0;\n  }\n\n  sink->Append(num_left_spaces, ' ');\n  sink->Append(sign);\n  sink->Append(base_indicator);\n  sink->Append(num_zeroes, '0');\n  sink->Append(formatted);\n  sink->Append(num_right_spaces, ' ');\n  return true;\n}\n\ntemplate <typename T>\nbool ConvertFloatArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) {\n  if (conv.conversion_char() == FormatConversionCharInternal::v) {\n    conv.set_conversion_char(FormatConversionCharInternal::g);\n  }\n\n  return FormatConversionCharIsFloat(conv.conversion_char()) &&\n         ConvertFloatImpl(v, conv, sink);\n}\n\ninline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,\n                             FormatSinkImpl *sink) {\n  if (conv.is_basic()) {\n    sink->Append(v);\n    return true;\n  }\n  return sink->PutPaddedString(v, conv.width(), conv.precision(),\n                               conv.has_left_flag());\n}\n\ninline bool ConvertStringArg(const wchar_t *v,\n                             size_t len,\n                             const FormatConversionSpecImpl conv,\n                             FormatSinkImpl *sink) {\n  FixedArray<char> mb(len * 4);\n  strings_internal::ShiftState s;\n  size_t chars_written = 0;\n  for (size_t i = 0; i < len; ++i) {\n    const size_t chars =\n        strings_internal::WideToUtf8(v[i], &mb[chars_written], s);\n    if (chars == static_cast<size_t>(-1)) { return false; }\n    chars_written += chars;\n  }\n  return ConvertStringArg(string_view(mb.data(), chars_written), conv, sink);\n}\n\nbool ConvertWCharTImpl(wchar_t v, const FormatConversionSpecImpl conv,\n                       FormatSinkImpl *sink) {\n  char mb[4];\n  strings_internal::ShiftState s;\n  const size_t chars_written = strings_internal::WideToUtf8(v, mb, s);\n  return chars_written != static_cast<size_t>(-1) && !s.saw_high_surrogate &&\n         ConvertStringArg(string_view(mb, chars_written), conv, sink);\n}\n\n}  // namespace\n\nbool ConvertBoolArg(bool v, FormatSinkImpl *sink) {\n  if (v) {\n    sink->Append(\"true\");\n  } else {\n    sink->Append(\"false\");\n  }\n  return true;\n}\n\ntemplate <typename T>\nbool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) {\n  using U = typename MakeUnsigned<T>::type;\n  IntDigits as_digits;\n\n  // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes\n  // it to complain about a switch/case type mismatch, even though both are\n  // FormatConversionChar.  Likely this is because at this point\n  // FormatConversionChar is declared, but not defined.\n  switch (static_cast<uint8_t>(conv.conversion_char())) {\n    case static_cast<uint8_t>(FormatConversionCharInternal::c):\n      return (std::is_same<T, wchar_t>::value ||\n              (conv.length_mod() == LengthMod::l))\n                 ? ConvertWCharTImpl(static_cast<wchar_t>(v), conv, sink)\n                 : ConvertCharImpl(static_cast<char>(v), conv, sink);\n\n    case static_cast<uint8_t>(FormatConversionCharInternal::o):\n      as_digits.PrintAsOct(static_cast<U>(v));\n      break;\n\n    case static_cast<uint8_t>(FormatConversionCharInternal::x):\n      as_digits.PrintAsHexLower(static_cast<U>(v));\n      break;\n    case static_cast<uint8_t>(FormatConversionCharInternal::X):\n      as_digits.PrintAsHexUpper(static_cast<U>(v));\n      break;\n\n    case static_cast<uint8_t>(FormatConversionCharInternal::u):\n      as_digits.PrintAsDec(static_cast<U>(v));\n      break;\n\n    case static_cast<uint8_t>(FormatConversionCharInternal::d):\n    case static_cast<uint8_t>(FormatConversionCharInternal::i):\n    case static_cast<uint8_t>(FormatConversionCharInternal::v):\n      as_digits.PrintAsDec(v);\n      break;\n\n    case static_cast<uint8_t>(FormatConversionCharInternal::a):\n    case static_cast<uint8_t>(FormatConversionCharInternal::e):\n    case static_cast<uint8_t>(FormatConversionCharInternal::f):\n    case static_cast<uint8_t>(FormatConversionCharInternal::g):\n    case static_cast<uint8_t>(FormatConversionCharInternal::A):\n    case static_cast<uint8_t>(FormatConversionCharInternal::E):\n    case static_cast<uint8_t>(FormatConversionCharInternal::F):\n    case static_cast<uint8_t>(FormatConversionCharInternal::G):\n      return ConvertFloatImpl(static_cast<double>(v), conv, sink);\n\n    default:\n      ABSL_ASSUME(false);\n  }\n\n  if (conv.is_basic()) {\n    sink->Append(as_digits.with_neg_and_zero());\n    return true;\n  }\n  return ConvertIntImplInnerSlow(as_digits, conv, sink);\n}\n\ntemplate bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,\n                                  FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<signed char>(signed char v,\n                                         FormatConversionSpecImpl conv,\n                                         FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<unsigned char>(unsigned char v,\n                                           FormatConversionSpecImpl conv,\n                                           FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<wchar_t>(wchar_t v, FormatConversionSpecImpl conv,\n                                     FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<short>(short v,  // NOLINT\n                                   FormatConversionSpecImpl conv,\n                                   FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<unsigned short>(unsigned short v,  // NOLINT\n                                            FormatConversionSpecImpl conv,\n                                            FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,\n                                 FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<unsigned int>(unsigned int v,\n                                          FormatConversionSpecImpl conv,\n                                          FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<long>(long v,  // NOLINT\n                                  FormatConversionSpecImpl conv,\n                                  FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<unsigned long>(unsigned long v,  // NOLINT\n                                           FormatConversionSpecImpl conv,\n                                           FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<long long>(long long v,  // NOLINT\n                                       FormatConversionSpecImpl conv,\n                                       FormatSinkImpl *sink);\ntemplate bool ConvertIntArg<unsigned long long>(unsigned long long v,  // NOLINT\n                                                FormatConversionSpecImpl conv,\n                                                FormatSinkImpl *sink);\n\n// ==================== Strings ====================\nStringConvertResult FormatConvertImpl(const std::string &v,\n                                      const FormatConversionSpecImpl conv,\n                                      FormatSinkImpl *sink) {\n  return {ConvertStringArg(v, conv, sink)};\n}\n\nStringConvertResult FormatConvertImpl(const std::wstring &v,\n                                      const FormatConversionSpecImpl conv,\n                                      FormatSinkImpl *sink) {\n  return {ConvertStringArg(v.data(), v.size(), conv, sink)};\n}\n\nStringConvertResult FormatConvertImpl(string_view v,\n                                      const FormatConversionSpecImpl conv,\n                                      FormatSinkImpl *sink) {\n  return {ConvertStringArg(v, conv, sink)};\n}\n\nStringConvertResult FormatConvertImpl(std::wstring_view v,\n                                      const FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* sink) {\n  return {ConvertStringArg(v.data(), v.size(), conv, sink)};\n}\n\nStringPtrConvertResult FormatConvertImpl(const char* v,\n                                         const FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink) {\n  if (conv.conversion_char() == FormatConversionCharInternal::p)\n    return {FormatConvertImpl(VoidPtr(v), conv, sink).value};\n  size_t len;\n  if (v == nullptr) {\n    len = 0;\n  } else if (conv.precision() < 0) {\n    len = std::strlen(v);\n  } else {\n    // If precision is set, we look for the NUL-terminator on the valid range.\n    len = static_cast<size_t>(std::find(v, v + conv.precision(), '\\0') - v);\n  }\n  return {ConvertStringArg(string_view(v, len), conv, sink)};\n}\n\nStringPtrConvertResult FormatConvertImpl(const wchar_t* v,\n                                         const FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink) {\n  if (conv.conversion_char() == FormatConversionCharInternal::p) {\n    return {FormatConvertImpl(VoidPtr(v), conv, sink).value};\n  }\n  size_t len;\n  if (v == nullptr) {\n    len = 0;\n  } else if (conv.precision() < 0) {\n    len = std::wcslen(v);\n  } else {\n    // If precision is set, we look for the NUL-terminator on the valid range.\n    len = static_cast<size_t>(std::find(v, v + conv.precision(), L'\\0') - v);\n  }\n  return {ConvertStringArg(v, len, conv, sink)};\n}\n\nStringPtrConvertResult FormatConvertImpl(std::nullptr_t,\n                                         const FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink) {\n  return FormatConvertImpl(static_cast<const char*>(nullptr), conv, sink);\n}\n\n// ==================== Raw pointers ====================\nArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(\n    VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {\n  if (!v.value) {\n    sink->Append(\"(nil)\");\n    return {true};\n  }\n  IntDigits as_digits;\n  as_digits.PrintAsHexLower(v.value);\n  return {ConvertIntImplInnerSlow(as_digits, conv, sink)};\n}\n\n// ==================== Floats ====================\nFloatingConvertResult FormatConvertImpl(float v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertFloatArg(v, conv, sink)};\n}\nFloatingConvertResult FormatConvertImpl(double v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertFloatArg(v, conv, sink)};\n}\nFloatingConvertResult FormatConvertImpl(long double v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertFloatArg(v, conv, sink)};\n}\n\n// ==================== Chars ====================\nCharConvertResult FormatConvertImpl(char v, const FormatConversionSpecImpl conv,\n                                    FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nCharConvertResult FormatConvertImpl(wchar_t v,\n                                    const FormatConversionSpecImpl conv,\n                                    FormatSinkImpl* sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\n\n// ==================== Ints ====================\nIntegralConvertResult FormatConvertImpl(signed char v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(unsigned char v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(short v,  // NOLINT\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(int v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(unsigned v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(long v,  // NOLINT\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(long long v,  // NOLINT\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(absl::int128 v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\nIntegralConvertResult FormatConvertImpl(absl::uint128 v,\n                                        const FormatConversionSpecImpl conv,\n                                        FormatSinkImpl *sink) {\n  return {ConvertIntArg(v, conv, sink)};\n}\n\nABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();\n\n\n\n}  // namespace str_format_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/arg.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_\n\n#include <string.h>\n#include <wchar.h>\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <limits>\n#include <memory>\n#include <sstream>\n#include <string>\n#include <string_view>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/has_absl_stringify.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass Cord;\nclass FormatCountCapture;\nclass FormatSink;\n\ntemplate <absl::FormatConversionCharSet C>\nstruct FormatConvertResult;\nclass FormatConversionSpec;\n\nnamespace str_format_internal {\n\ntemplate <FormatConversionCharSet C>\nstruct ArgConvertResult {\n  bool value;\n};\n\nusing IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(\n    FormatConversionCharSetInternal::c,\n    FormatConversionCharSetInternal::kNumeric,\n    FormatConversionCharSetInternal::kStar,\n    FormatConversionCharSetInternal::v)>;\nusing FloatingConvertResult = ArgConvertResult<FormatConversionCharSetUnion(\n    FormatConversionCharSetInternal::kFloating,\n    FormatConversionCharSetInternal::v)>;\nusing CharConvertResult = ArgConvertResult<FormatConversionCharSetUnion(\n    FormatConversionCharSetInternal::c,\n    FormatConversionCharSetInternal::kNumeric,\n    FormatConversionCharSetInternal::kStar)>;\n\ntemplate <typename T, typename = void>\nstruct HasUserDefinedConvert : std::false_type {};\n\ntemplate <typename T>\nstruct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(\n                                    std::declval<const T&>(),\n                                    std::declval<const FormatConversionSpec&>(),\n                                    std::declval<FormatSink*>()))>>\n    : std::true_type {};\n\n// These declarations prevent ADL lookup from continuing in absl namespaces,\n// we are deliberately using these as ADL hooks and want them to consider\n// non-absl namespaces only.\nvoid AbslFormatConvert();\nvoid AbslStringify();\n\ntemplate <typename T>\nbool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);\n\n// Forward declarations of internal `ConvertIntArg` function template\n// instantiations are here to avoid including the template body in the headers\n// and instantiating it in large numbers of translation units. Explicit\n// instantiations can be found in \"absl/strings/internal/str_format/arg.cc\"\nextern template bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink);\nextern template bool ConvertIntArg<signed char>(signed char v,\n                                                FormatConversionSpecImpl conv,\n                                                FormatSinkImpl* sink);\nextern template bool ConvertIntArg<unsigned char>(unsigned char v,\n                                                  FormatConversionSpecImpl conv,\n                                                  FormatSinkImpl* sink);\nextern template bool ConvertIntArg<wchar_t>(wchar_t v,\n                                            FormatConversionSpecImpl conv,\n                                            FormatSinkImpl* sink);\nextern template bool ConvertIntArg<short>(short v,  // NOLINT\n                                          FormatConversionSpecImpl conv,\n                                          FormatSinkImpl* sink);\nextern template bool ConvertIntArg<unsigned short>(   // NOLINT\n    unsigned short v, FormatConversionSpecImpl conv,  // NOLINT\n    FormatSinkImpl* sink);\nextern template bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nextern template bool ConvertIntArg<unsigned int>(unsigned int v,\n                                                 FormatConversionSpecImpl conv,\n                                                 FormatSinkImpl* sink);\nextern template bool ConvertIntArg<long>(                           // NOLINT\n    long v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);   // NOLINT\nextern template bool ConvertIntArg<unsigned long>(unsigned long v,  // NOLINT\n                                                  FormatConversionSpecImpl conv,\n                                                  FormatSinkImpl* sink);\nextern template bool ConvertIntArg<long long>(long long v,  // NOLINT\n                                              FormatConversionSpecImpl conv,\n                                              FormatSinkImpl* sink);\nextern template bool ConvertIntArg<unsigned long long>(   // NOLINT\n    unsigned long long v, FormatConversionSpecImpl conv,  // NOLINT\n    FormatSinkImpl* sink);\n\ntemplate <typename T>\nauto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,\n                       FormatSinkImpl* sink)\n    -> decltype(AbslFormatConvert(v,\n                                  std::declval<const FormatConversionSpec&>(),\n                                  std::declval<FormatSink*>())) {\n  using FormatConversionSpecT =\n      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;\n  using FormatSinkT =\n      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;\n  auto fcs = conv.Wrap<FormatConversionSpecT>();\n  auto fs = sink->Wrap<FormatSinkT>();\n  return AbslFormatConvert(v, fcs, &fs);\n}\n\ntemplate <typename T>\nauto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,\n                       FormatSinkImpl* sink)\n    -> std::enable_if_t<std::is_enum<T>::value &&\n                            std::is_void<decltype(AbslStringify(\n                                std::declval<FormatSink&>(), v))>::value,\n                        IntegralConvertResult> {\n  if (conv.conversion_char() == FormatConversionCharInternal::v) {\n    using FormatSinkT =\n        absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;\n    auto fs = sink->Wrap<FormatSinkT>();\n    AbslStringify(fs, v);\n    return {true};\n  } else {\n    return {ConvertIntArg(\n        static_cast<typename std::underlying_type<T>::type>(v), conv, sink)};\n  }\n}\n\ntemplate <typename T>\nauto FormatConvertImpl(const T& v, FormatConversionSpecImpl,\n                       FormatSinkImpl* sink)\n    -> std::enable_if_t<!std::is_enum<T>::value &&\n                            !std::is_same<T, absl::Cord>::value &&\n                            std::is_void<decltype(AbslStringify(\n                                std::declval<FormatSink&>(), v))>::value,\n                        ArgConvertResult<FormatConversionCharSetInternal::v>> {\n  using FormatSinkT =\n      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;\n  auto fs = sink->Wrap<FormatSinkT>();\n  AbslStringify(fs, v);\n  return {true};\n}\n\ntemplate <typename T>\nclass StreamedWrapper;\n\n// If 'v' can be converted (in the printf sense) according to 'conv',\n// then convert it, appending to `sink` and return `true`.\n// Otherwise fail and return `false`.\n\n// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'\n// as an extension mechanism. These FormatConvertImpl functions are the default\n// implementations.\n// The ADL search is augmented via the 'Sink*' parameter, which also\n// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'\n// functions in the namespaces associated with 'v'.\n\n// Raw pointers.\nstruct VoidPtr {\n  VoidPtr() = default;\n  template <typename T,\n            decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>\n  VoidPtr(T* ptr)  // NOLINT\n      : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}\n  uintptr_t value;\n};\n\ntemplate <FormatConversionCharSet C>\nconstexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {\n  return C;\n}\n\ntemplate <FormatConversionCharSet C>\nconstexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {\n  return C;\n}\n\nArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(\n    VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);\n\n// Strings.\nusing StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion(\n    FormatConversionCharSetInternal::s,\n    FormatConversionCharSetInternal::v)>;\nStringConvertResult FormatConvertImpl(const std::string& v,\n                                      FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* sink);\nStringConvertResult FormatConvertImpl(const std::wstring& v,\n                                      FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* sink);\nStringConvertResult FormatConvertImpl(string_view v,\n                                      FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* sink);\nStringConvertResult FormatConvertImpl(std::wstring_view v,\n                                      FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* sink);\n#if !defined(ABSL_USES_STD_STRING_VIEW)\ninline StringConvertResult FormatConvertImpl(std::string_view v,\n                                             FormatConversionSpecImpl conv,\n                                             FormatSinkImpl* sink) {\n  return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink);\n}\n#endif  // !ABSL_USES_STD_STRING_VIEW\n\nusing StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion(\n    FormatConversionCharSetInternal::s,\n    FormatConversionCharSetInternal::p)>;\nStringPtrConvertResult FormatConvertImpl(const char* v,\n                                         FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink);\nStringPtrConvertResult FormatConvertImpl(const wchar_t* v,\n                                         FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink);\n// This overload is needed to disambiguate, since `nullptr` could match either\n// of the other overloads equally well.\nStringPtrConvertResult FormatConvertImpl(std::nullptr_t,\n                                         FormatConversionSpecImpl conv,\n                                         FormatSinkImpl* sink);\n\ntemplate <class AbslCord, typename std::enable_if<std::is_same<\n                              AbslCord, absl::Cord>::value>::type* = nullptr>\nStringConvertResult FormatConvertImpl(const AbslCord& value,\n                                      FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* sink) {\n  bool is_left = conv.has_left_flag();\n  size_t space_remaining = 0;\n\n  int width = conv.width();\n  if (width >= 0) space_remaining = static_cast<size_t>(width);\n\n  size_t to_write = value.size();\n\n  int precision = conv.precision();\n  if (precision >= 0)\n    to_write = (std::min)(to_write, static_cast<size_t>(precision));\n\n  space_remaining = Excess(to_write, space_remaining);\n\n  if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');\n\n  for (string_view piece : value.Chunks()) {\n    if (piece.size() > to_write) {\n      piece.remove_suffix(piece.size() - to_write);\n      to_write = 0;\n    } else {\n      to_write -= piece.size();\n    }\n    sink->Append(piece);\n    if (to_write == 0) {\n      break;\n    }\n  }\n\n  if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');\n  return {true};\n}\n\nbool ConvertBoolArg(bool v, FormatSinkImpl* sink);\n\n// Floats.\nFloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nFloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nFloatingConvertResult FormatConvertImpl(long double v,\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\n\n// Chars.\nCharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,\n                                    FormatSinkImpl* sink);\nCharConvertResult FormatConvertImpl(wchar_t v,\n                                    FormatConversionSpecImpl conv,\n                                    FormatSinkImpl* sink);\n\n// Ints.\nIntegralConvertResult FormatConvertImpl(signed char v,\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(unsigned char v,\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(short v,  // NOLINT\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(unsigned v,\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(long v,  // NOLINT\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(long long v,  // NOLINT\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\nIntegralConvertResult FormatConvertImpl(uint128 v,\n                                        FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink);\n\n// This function needs to be a template due to ambiguity regarding type\n// conversions.\ntemplate <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>\nIntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,\n                                        FormatSinkImpl* sink) {\n  if (conv.conversion_char() == FormatConversionCharInternal::v) {\n    return {ConvertBoolArg(v, sink)};\n  }\n\n  return FormatConvertImpl(static_cast<int>(v), conv, sink);\n}\n\n// We provide this function to help the checker, but it is never defined.\n// FormatArgImpl will use the underlying Convert functions instead.\ntemplate <typename T>\ntypename std::enable_if<std::is_enum<T>::value &&\n                            !HasUserDefinedConvert<T>::value &&\n                            !HasAbslStringify<T>::value,\n                        IntegralConvertResult>::type\nFormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);\n\ntemplate <typename T>\nStringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,\n                                      FormatConversionSpecImpl conv,\n                                      FormatSinkImpl* out) {\n  std::ostringstream oss;\n  oss << v.v_;\n  if (!oss) return {false};\n  return str_format_internal::FormatConvertImpl(oss.str(), conv, out);\n}\n\n// Use templates and dependent types to delay evaluation of the function\n// until after FormatCountCapture is fully defined.\nstruct FormatCountCaptureHelper {\n  template <class T = int>\n  static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(\n      const FormatCountCapture& v, FormatConversionSpecImpl conv,\n      FormatSinkImpl* sink) {\n    const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;\n\n    if (conv.conversion_char() !=\n        str_format_internal::FormatConversionCharInternal::n) {\n      return {false};\n    }\n    *v2.p_ = static_cast<int>(sink->size());\n    return {true};\n  }\n};\n\ntemplate <class T = int>\nArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(\n    const FormatCountCapture& v, FormatConversionSpecImpl conv,\n    FormatSinkImpl* sink) {\n  return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);\n}\n\n// Helper friend struct to hide implementation details from the public API of\n// FormatArgImpl.\nstruct FormatArgImplFriend {\n  template <typename Arg>\n  static bool ToInt(Arg arg, int* out) {\n    // A value initialized FormatConversionSpecImpl has a `none` conv, which\n    // tells the dispatcher to run the `int` conversion.\n    return arg.dispatcher_(arg.data_, {}, out);\n  }\n\n  template <typename Arg>\n  static bool Convert(Arg arg, FormatConversionSpecImpl conv,\n                      FormatSinkImpl* out) {\n    return arg.dispatcher_(arg.data_, conv, out);\n  }\n\n  template <typename Arg>\n  static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {\n    return arg.dispatcher_;\n  }\n};\n\ntemplate <typename Arg>\nconstexpr FormatConversionCharSet ArgumentToConv() {\n  using ConvResult = decltype(str_format_internal::FormatConvertImpl(\n      std::declval<const Arg&>(),\n      std::declval<const FormatConversionSpecImpl&>(),\n      std::declval<FormatSinkImpl*>()));\n  return absl::str_format_internal::ExtractCharSet(ConvResult{});\n}\n\n// A type-erased handle to a format argument.\nclass FormatArgImpl {\n private:\n  enum { kInlinedSpace = 8 };\n\n  using VoidPtr = str_format_internal::VoidPtr;\n\n  union Data {\n    const void* ptr;\n    const volatile void* volatile_ptr;\n    char buf[kInlinedSpace];\n  };\n\n  using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);\n\n  template <typename T>\n  struct store_by_value\n      : std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&\n                                         (std::is_integral<T>::value ||\n                                          std::is_floating_point<T>::value ||\n                                          std::is_pointer<T>::value ||\n                                          std::is_same<VoidPtr, T>::value)> {};\n\n  enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };\n  template <typename T>\n  struct storage_policy\n      : std::integral_constant<StoragePolicy,\n                               (std::is_volatile<T>::value\n                                    ? ByVolatilePointer\n                                    : (store_by_value<T>::value ? ByValue\n                                                                : ByPointer))> {\n  };\n\n  // To reduce the number of vtables we will decay values before hand.\n  // Anything with a user-defined Convert will get its own vtable.\n  // For everything else:\n  //   - Decay char* and char arrays into `const char*`\n  //   - Decay wchar_t* and wchar_t arrays into `const wchar_t*`\n  //   - Decay any other pointer to `const void*`\n  //   - Decay all enums to the integral promotion of their underlying type.\n  //   - Decay function pointers to void*.\n  template <typename T, typename = void>\n  struct DecayType {\n    static constexpr bool kHasUserDefined =\n        str_format_internal::HasUserDefinedConvert<T>::value ||\n        HasAbslStringify<T>::value;\n    using type = typename std::conditional<\n        !kHasUserDefined && std::is_convertible<T, const char*>::value,\n        const char*,\n        typename std::conditional<\n            !kHasUserDefined && std::is_convertible<T, const wchar_t*>::value,\n            const wchar_t*,\n            typename std::conditional<\n                !kHasUserDefined && std::is_convertible<T, VoidPtr>::value,\n                VoidPtr,\n                const T&>::type>::type>::type;\n  };\n  template <typename T>\n  struct DecayType<\n      T, typename std::enable_if<\n             !str_format_internal::HasUserDefinedConvert<T>::value &&\n             !HasAbslStringify<T>::value && std::is_enum<T>::value>::type> {\n    using type = decltype(+typename std::underlying_type<T>::type());\n  };\n\n public:\n  template <typename T>\n  explicit FormatArgImpl(const T& value) {\n    using D = typename DecayType<T>::type;\n    static_assert(\n        std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,\n        \"Decayed types must be stored by value\");\n    Init(static_cast<D>(value));\n  }\n\n private:\n  friend struct str_format_internal::FormatArgImplFriend;\n  template <typename T, StoragePolicy = storage_policy<T>::value>\n  struct Manager;\n\n  template <typename T>\n  struct Manager<T, ByPointer> {\n    static Data SetValue(const T& value) {\n      Data data;\n      data.ptr = std::addressof(value);\n      return data;\n    }\n\n    static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }\n  };\n\n  template <typename T>\n  struct Manager<T, ByVolatilePointer> {\n    static Data SetValue(const T& value) {\n      Data data;\n      data.volatile_ptr = &value;\n      return data;\n    }\n\n    static const T& Value(Data arg) {\n      return *static_cast<const T*>(arg.volatile_ptr);\n    }\n  };\n\n  template <typename T>\n  struct Manager<T, ByValue> {\n    static Data SetValue(const T& value) {\n      Data data;\n      memcpy(data.buf, &value, sizeof(value));\n      return data;\n    }\n\n    static T Value(Data arg) {\n      T value;\n      memcpy(&value, arg.buf, sizeof(T));\n      return value;\n    }\n  };\n\n  template <typename T>\n  void Init(const T& value) {\n    data_ = Manager<T>::SetValue(value);\n    dispatcher_ = &Dispatch<T>;\n  }\n\n  template <typename T>\n  static int ToIntVal(const T& val) {\n    using CommonType = typename std::conditional<std::is_signed<T>::value,\n                                                 int64_t, uint64_t>::type;\n    if (static_cast<CommonType>(val) >\n        static_cast<CommonType>((std::numeric_limits<int>::max)())) {\n      return (std::numeric_limits<int>::max)();\n    } else if (std::is_signed<T>::value &&\n               static_cast<CommonType>(val) <\n                   static_cast<CommonType>((std::numeric_limits<int>::min)())) {\n      return (std::numeric_limits<int>::min)();\n    }\n    return static_cast<int>(val);\n  }\n\n  template <typename T>\n  static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,\n                    std::false_type) {\n    *out = ToIntVal(Manager<T>::Value(arg));\n    return true;\n  }\n\n  template <typename T>\n  static bool ToInt(Data arg, int* out, std::false_type,\n                    std::true_type /* is_enum */) {\n    *out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(\n        Manager<T>::Value(arg)));\n    return true;\n  }\n\n  template <typename T>\n  static bool ToInt(Data, int*, std::false_type, std::false_type) {\n    return false;\n  }\n\n  template <typename T>\n  static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {\n    // A `none` conv indicates that we want the `int` conversion.\n    if (ABSL_PREDICT_FALSE(spec.conversion_char() ==\n                           FormatConversionCharInternal::kNone)) {\n      return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),\n                      std::is_enum<T>());\n    }\n    if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),\n                                     spec.conversion_char()))) {\n      return false;\n    }\n    return str_format_internal::FormatConvertImpl(\n               Manager<T>::Value(arg), spec,\n               static_cast<FormatSinkImpl*>(out))\n        .value;\n  }\n\n  Data data_;\n  Dispatcher dispatcher_;\n};\n\n#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E)                     \\\n  E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \\\n                                             void*)\n\n#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(...)   \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \\\n                                             __VA_ARGS__);                     \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__);               \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__);               \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__);        \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__);      \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short,      /* NOLINT */ \\\n                                             __VA_ARGS__);                     \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__);                \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__);       \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */  \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long,      /* NOLINT */  \\\n                                             __VA_ARGS__);                     \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */           \\\n                                             __VA_ARGS__);                     \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \\\n                                             __VA_ARGS__);                     \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__);             \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__);        \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__);     \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__)\n\n#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)       \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \\\n      __VA_ARGS__);                                                \\\n  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__)\n\nABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);\n\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/arg_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/arg.h\"\n\n#include <limits>\n#include <string>\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\nnamespace {\n\nclass FormatArgImplTest : public ::testing::Test {\n public:\n  enum Color { kRed, kGreen, kBlue };\n\n  static const char *hi() { return \"hi\"; }\n\n  struct X {};\n\n  X x_;\n};\n\ninline FormatConvertResult<FormatConversionCharSet{}> AbslFormatConvert(\n    const FormatArgImplTest::X &, const FormatConversionSpec &, FormatSink *) {\n  return {false};\n}\n\nTEST_F(FormatArgImplTest, ToInt) {\n  int out = 0;\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(1), &out));\n  EXPECT_EQ(1, out);\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(-1), &out));\n  EXPECT_EQ(-1, out);\n  EXPECT_TRUE(\n      FormatArgImplFriend::ToInt(FormatArgImpl(static_cast<char>(64)), &out));\n  EXPECT_EQ(64, out);\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(\n      FormatArgImpl(static_cast<unsigned long long>(123456)), &out));  // NOLINT\n  EXPECT_EQ(123456, out);\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(\n      FormatArgImpl(static_cast<unsigned long long>(  // NOLINT\n                        std::numeric_limits<int>::max()) +\n                    1),\n      &out));\n  EXPECT_EQ(std::numeric_limits<int>::max(), out);\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(\n      FormatArgImpl(static_cast<long long>(  // NOLINT\n                        std::numeric_limits<int>::min()) -\n                    10),\n      &out));\n  EXPECT_EQ(std::numeric_limits<int>::min(), out);\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(false), &out));\n  EXPECT_EQ(0, out);\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(true), &out));\n  EXPECT_EQ(1, out);\n  EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(2.2), &out));\n  EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(3.2f), &out));\n  EXPECT_FALSE(FormatArgImplFriend::ToInt(\n      FormatArgImpl(static_cast<int *>(nullptr)), &out));\n  EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(hi()), &out));\n  EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(\"hi\"), &out));\n  EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(x_), &out));\n  EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(kBlue), &out));\n  EXPECT_EQ(2, out);\n}\n\nextern const char kMyArray[];\n\nTEST_F(FormatArgImplTest, CharArraysDecayToCharPtr) {\n  const char* a = \"\";\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(\"\")));\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(\"A\")));\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(\"ABC\")));\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(kMyArray)));\n}\n\nextern const wchar_t kMyWCharTArray[];\n\nTEST_F(FormatArgImplTest, WCharTArraysDecayToWCharTPtr) {\n  const wchar_t* a = L\"\";\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(L\"\")));\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(L\"A\")));\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n            FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(L\"ABC\")));\n  EXPECT_EQ(\n      FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(a)),\n      FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(kMyWCharTArray)));\n}\n\nTEST_F(FormatArgImplTest, OtherPtrDecayToVoidPtr) {\n  auto expected = FormatArgImplFriend::GetVTablePtrForTest(\n      FormatArgImpl(static_cast<void *>(nullptr)));\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(\n                FormatArgImpl(static_cast<int *>(nullptr))),\n            expected);\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(\n                FormatArgImpl(static_cast<volatile int *>(nullptr))),\n            expected);\n\n  auto p = static_cast<void (*)()>([] {});\n  EXPECT_EQ(FormatArgImplFriend::GetVTablePtrForTest(FormatArgImpl(p)),\n            expected);\n}\n\nTEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {\n  std::string s;\n  FormatSinkImpl sink(&s);\n  FormatConversionSpecImpl conv;\n  FormatConversionSpecImplFriend::SetConversionChar(\n      FormatConversionCharInternal::s, &conv);\n  FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);\n  FormatConversionSpecImplFriend::SetWidth(-1, &conv);\n  FormatConversionSpecImplFriend::SetPrecision(-1, &conv);\n  EXPECT_TRUE(\n      FormatArgImplFriend::Convert(FormatArgImpl(kMyArray), conv, &sink));\n  sink.Flush();\n  EXPECT_EQ(\"ABCDE\", s);\n}\nconst char kMyArray[] = \"ABCDE\";\n\nTEST_F(FormatArgImplTest, WorksWithWCharTArraysOfUnknownSize) {\n  std::string s;\n  FormatSinkImpl sink(&s);\n  FormatConversionSpecImpl conv;\n  FormatConversionSpecImplFriend::SetConversionChar(\n      FormatConversionCharInternal::s, &conv);\n  FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);\n  FormatConversionSpecImplFriend::SetWidth(-1, &conv);\n  FormatConversionSpecImplFriend::SetPrecision(-1, &conv);\n  EXPECT_TRUE(\n      FormatArgImplFriend::Convert(FormatArgImpl(kMyWCharTArray), conv, &sink));\n  sink.Flush();\n  EXPECT_EQ(\"ABCDE\", s);\n}\nconst wchar_t kMyWCharTArray[] = L\"ABCDE\";\n\n}  // namespace\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/bind.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/bind.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <cerrno>\n#include <cstddef>\n#include <cstdio>\n#include <ios>\n#include <limits>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/strings/internal/str_format/arg.h\"\n#include \"absl/strings/internal/str_format/constexpr_parser.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/internal/str_format/output.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nnamespace {\n\ninline bool BindFromPosition(int position, int* value,\n                             absl::Span<const FormatArgImpl> pack) {\n  assert(position > 0);\n  if (static_cast<size_t>(position) > pack.size()) {\n    return false;\n  }\n  // -1 because positions are 1-based\n  return FormatArgImplFriend::ToInt(pack[static_cast<size_t>(position) - 1],\n                                    value);\n}\n\nclass ArgContext {\n public:\n  explicit ArgContext(absl::Span<const FormatArgImpl> pack) : pack_(pack) {}\n\n  // Fill 'bound' with the results of applying the context's argument pack\n  // to the specified 'unbound'. We synthesize a BoundConversion by\n  // lining up a UnboundConversion with a user argument. We also\n  // resolve any '*' specifiers for width and precision, so after\n  // this call, 'bound' has all the information it needs to be formatted.\n  // Returns false on failure.\n  bool Bind(const UnboundConversion* unbound, BoundConversion* bound);\n\n private:\n  absl::Span<const FormatArgImpl> pack_;\n};\n\ninline bool ArgContext::Bind(const UnboundConversion* unbound,\n                             BoundConversion* bound) {\n  const FormatArgImpl* arg = nullptr;\n  int arg_position = unbound->arg_position;\n  if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;\n  arg = &pack_[static_cast<size_t>(arg_position - 1)];  // 1-based\n\n  if (unbound->flags != Flags::kBasic) {\n    int width = unbound->width.value();\n    bool force_left = false;\n    if (unbound->width.is_from_arg()) {\n      if (!BindFromPosition(unbound->width.get_from_arg(), &width, pack_))\n        return false;\n      if (width < 0) {\n        // \"A negative field width is taken as a '-' flag followed by a\n        // positive field width.\"\n        force_left = true;\n        // Make sure we don't overflow the width when negating it.\n        width = -std::max(width, -std::numeric_limits<int>::max());\n      }\n    }\n\n    int precision = unbound->precision.value();\n    if (unbound->precision.is_from_arg()) {\n      if (!BindFromPosition(unbound->precision.get_from_arg(), &precision,\n                            pack_))\n        return false;\n    }\n\n    FormatConversionSpecImplFriend::SetWidth(width, bound);\n    FormatConversionSpecImplFriend::SetPrecision(precision, bound);\n\n    if (force_left) {\n      FormatConversionSpecImplFriend::SetFlags(unbound->flags | Flags::kLeft,\n                                               bound);\n    } else {\n      FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);\n    }\n\n    FormatConversionSpecImplFriend::SetLengthMod(unbound->length_mod, bound);\n  } else {\n    FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);\n    FormatConversionSpecImplFriend::SetWidth(-1, bound);\n    FormatConversionSpecImplFriend::SetPrecision(-1, bound);\n  }\n  FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);\n  bound->set_arg(arg);\n  return true;\n}\n\ntemplate <typename Converter>\nclass ConverterConsumer {\n public:\n  ConverterConsumer(Converter converter, absl::Span<const FormatArgImpl> pack)\n      : converter_(converter), arg_context_(pack) {}\n\n  bool Append(string_view s) {\n    converter_.Append(s);\n    return true;\n  }\n  bool ConvertOne(const UnboundConversion& conv, string_view conv_string) {\n    BoundConversion bound;\n    if (!arg_context_.Bind(&conv, &bound)) return false;\n    return converter_.ConvertOne(bound, conv_string);\n  }\n\n private:\n  Converter converter_;\n  ArgContext arg_context_;\n};\n\ntemplate <typename Converter>\nbool ConvertAll(const UntypedFormatSpecImpl format,\n                absl::Span<const FormatArgImpl> args, Converter converter) {\n  if (format.has_parsed_conversion()) {\n    return format.parsed_conversion()->ProcessFormat(\n        ConverterConsumer<Converter>(converter, args));\n  } else {\n    return ParseFormatString(format.str(),\n                             ConverterConsumer<Converter>(converter, args));\n  }\n}\n\nclass DefaultConverter {\n public:\n  explicit DefaultConverter(FormatSinkImpl* sink) : sink_(sink) {}\n\n  void Append(string_view s) const { sink_->Append(s); }\n\n  bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {\n    return FormatArgImplFriend::Convert(*bound.arg(), bound, sink_);\n  }\n\n private:\n  FormatSinkImpl* sink_;\n};\n\nclass SummarizingConverter {\n public:\n  explicit SummarizingConverter(FormatSinkImpl* sink) : sink_(sink) {}\n\n  void Append(string_view s) const { sink_->Append(s); }\n\n  bool ConvertOne(const BoundConversion& bound, string_view /*conv*/) const {\n    UntypedFormatSpecImpl spec(\"%d\");\n\n    std::ostringstream ss;\n    ss << \"{\" << Streamable(spec, {*bound.arg()}) << \":\"\n       << FormatConversionSpecImplFriend::FlagsToString(bound);\n    if (bound.width() >= 0) ss << bound.width();\n    if (bound.precision() >= 0) ss << \".\" << bound.precision();\n    ss << bound.conversion_char() << \"}\";\n    Append(ss.str());\n    return true;\n  }\n\n private:\n  FormatSinkImpl* sink_;\n};\n\n}  // namespace\n\nbool BindWithPack(const UnboundConversion* props,\n                  absl::Span<const FormatArgImpl> pack,\n                  BoundConversion* bound) {\n  return ArgContext(pack).Bind(props, bound);\n}\n\nstd::string Summarize(const UntypedFormatSpecImpl format,\n                      absl::Span<const FormatArgImpl> args) {\n  typedef SummarizingConverter Converter;\n  std::string out;\n  {\n    // inner block to destroy sink before returning out. It ensures a last\n    // flush.\n    FormatSinkImpl sink(&out);\n    if (!ConvertAll(format, args, Converter(&sink))) {\n      return \"\";\n    }\n  }\n  return out;\n}\n\nbool FormatUntyped(FormatRawSinkImpl raw_sink,\n                   const UntypedFormatSpecImpl format,\n                   absl::Span<const FormatArgImpl> args) {\n  FormatSinkImpl sink(raw_sink);\n  using Converter = DefaultConverter;\n  return ConvertAll(format, args, Converter(&sink));\n}\n\nstd::ostream& Streamable::Print(std::ostream& os) const {\n  if (!FormatUntyped(&os, format_, args_)) os.setstate(std::ios::failbit);\n  return os;\n}\n\nstd::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,\n                        absl::Span<const FormatArgImpl> args) {\n  size_t orig = out->size();\n  if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {\n    out->erase(orig);\n  }\n  return *out;\n}\n\nstd::string FormatPack(UntypedFormatSpecImpl format,\n                       absl::Span<const FormatArgImpl> args) {\n  std::string out;\n  if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {\n    out.clear();\n  }\n  return out;\n}\n\nint FprintF(std::FILE* output, const UntypedFormatSpecImpl format,\n            absl::Span<const FormatArgImpl> args) {\n  FILERawSink sink(output);\n  if (!FormatUntyped(&sink, format, args)) {\n    errno = EINVAL;\n    return -1;\n  }\n  if (sink.error()) {\n    errno = sink.error();\n    return -1;\n  }\n  if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {\n    errno = EFBIG;\n    return -1;\n  }\n  return static_cast<int>(sink.count());\n}\n\nint SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format,\n             absl::Span<const FormatArgImpl> args) {\n  BufferRawSink sink(output, size ? size - 1 : 0);\n  if (!FormatUntyped(&sink, format, args)) {\n    errno = EINVAL;\n    return -1;\n  }\n  size_t total = sink.total_written();\n  if (size) output[std::min(total, size - 1)] = 0;\n  return static_cast<int>(total);\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/bind.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_\n\n#include <cassert>\n#include <cstdio>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/strings/internal/str_format/arg.h\"\n#include \"absl/strings/internal/str_format/checker.h\"\n#include \"absl/strings/internal/str_format/constexpr_parser.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/internal/str_format/parser.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass UntypedFormatSpec;\n\nnamespace str_format_internal {\n\nclass BoundConversion : public FormatConversionSpecImpl {\n public:\n  const FormatArgImpl* arg() const { return arg_; }\n  void set_arg(const FormatArgImpl* a) { arg_ = a; }\n\n private:\n  const FormatArgImpl* arg_;\n};\n\n// This is the type-erased class that the implementation uses.\nclass UntypedFormatSpecImpl {\n public:\n  UntypedFormatSpecImpl() = delete;\n\n  explicit UntypedFormatSpecImpl(string_view s)\n      : data_(s.data()), size_(s.size()) {}\n  explicit UntypedFormatSpecImpl(\n      const str_format_internal::ParsedFormatBase* pc)\n      : data_(pc), size_(~size_t{}) {}\n\n  bool has_parsed_conversion() const { return size_ == ~size_t{}; }\n\n  string_view str() const {\n    assert(!has_parsed_conversion());\n    return string_view(static_cast<const char*>(data_), size_);\n  }\n  const str_format_internal::ParsedFormatBase* parsed_conversion() const {\n    assert(has_parsed_conversion());\n    return static_cast<const str_format_internal::ParsedFormatBase*>(data_);\n  }\n\n  template <typename T>\n  static const UntypedFormatSpecImpl& Extract(const T& s) {\n    return s.spec_;\n  }\n\n private:\n  const void* data_;\n  size_t size_;\n};\n\ntemplate <typename T, FormatConversionCharSet...>\nstruct MakeDependent {\n  using type = T;\n};\n\n// Implicitly convertible from `const char*`, `string_view`, and the\n// `ExtendedParsedFormat` type. This abstraction allows all format functions to\n// operate on any without providing too many overloads.\ntemplate <FormatConversionCharSet... Args>\nclass FormatSpecTemplate\n    : public MakeDependent<UntypedFormatSpec, Args...>::type {\n  using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;\n\n  template <bool res>\n  struct ErrorMaker {\n    constexpr bool operator()(int) const { return res; }\n  };\n\n  template <int i, int j>\n  static constexpr bool CheckArity(ErrorMaker<true> SpecifierCount = {},\n                                   ErrorMaker<i == j> ParametersPassed = {}) {\n    static_assert(SpecifierCount(i) == ParametersPassed(j),\n                  \"Number of arguments passed must match the number of \"\n                  \"conversion specifiers.\");\n    return true;\n  }\n\n  template <FormatConversionCharSet specified, FormatConversionCharSet passed,\n            int arg>\n  static constexpr bool CheckMatch(\n      ErrorMaker<Contains(specified, passed)> MismatchedArgumentNumber = {}) {\n    static_assert(MismatchedArgumentNumber(arg),\n                  \"Passed argument must match specified format.\");\n    return true;\n  }\n\n  template <FormatConversionCharSet... C, size_t... I>\n  static bool CheckMatches(absl::index_sequence<I...>) {\n    bool res[] = {true, CheckMatch<Args, C, I + 1>()...};\n    (void)res;\n    return true;\n  }\n\n public:\n#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\n  // Honeypot overload for when the string is not constexpr.\n  // We use the 'unavailable' attribute to give a better compiler error than\n  // just 'method is deleted'.\n  FormatSpecTemplate(...)  // NOLINT\n      __attribute__((unavailable(\"Format string is not constexpr.\")));\n\n  // Honeypot overload for when the format is constexpr and invalid.\n  // We use the 'unavailable' attribute to give a better compiler error than\n  // just 'method is deleted'.\n  // To avoid checking the format twice, we just check that the format is\n  // constexpr. If it is valid, then the overload below will kick in.\n  // We add the template here to make this overload have lower priority.\n  template <typename = void>\n  FormatSpecTemplate(const char* s)  // NOLINT\n      __attribute__((\n          enable_if(str_format_internal::EnsureConstexpr(s), \"constexpr trap\"),\n          unavailable(\n              \"Format specified does not match the arguments passed.\")));\n\n  template <typename T = void>\n  FormatSpecTemplate(string_view s)  // NOLINT\n      __attribute__((enable_if(str_format_internal::EnsureConstexpr(s),\n                               \"constexpr trap\")))\n      : Base(\"to avoid noise in the compiler error\") {\n    static_assert(sizeof(T*) == 0,\n                  \"Format specified does not match the arguments passed.\");\n  }\n\n  // Good format overload.\n  FormatSpecTemplate(const char* s)  // NOLINT\n      __attribute__((enable_if(ValidFormatImpl<Args...>(s), \"bad format trap\")))\n      : Base(s) {}\n\n  FormatSpecTemplate(string_view s)  // NOLINT\n      __attribute__((enable_if(ValidFormatImpl<Args...>(s), \"bad format trap\")))\n      : Base(s) {}\n\n#else  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\n  FormatSpecTemplate(const char* s) : Base(s) {}  // NOLINT\n  FormatSpecTemplate(string_view s) : Base(s) {}  // NOLINT\n\n#endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\n  template <FormatConversionCharSet... C>\n  FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT\n      : Base(&pc) {\n    CheckArity<sizeof...(C), sizeof...(Args)>();\n    CheckMatches<C...>(absl::make_index_sequence<sizeof...(C)>{});\n  }\n};\n\nclass Streamable {\n public:\n  Streamable(const UntypedFormatSpecImpl& format,\n             absl::Span<const FormatArgImpl> args)\n      : format_(format), args_(args.begin(), args.end()) {}\n\n  std::ostream& Print(std::ostream& os) const;\n\n  friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {\n    return l.Print(os);\n  }\n\n private:\n  const UntypedFormatSpecImpl& format_;\n  absl::InlinedVector<FormatArgImpl, 4> args_;\n};\n\n// for testing\nstd::string Summarize(UntypedFormatSpecImpl format,\n                      absl::Span<const FormatArgImpl> args);\nbool BindWithPack(const UnboundConversion* props,\n                  absl::Span<const FormatArgImpl> pack, BoundConversion* bound);\n\nbool FormatUntyped(FormatRawSinkImpl raw_sink, UntypedFormatSpecImpl format,\n                   absl::Span<const FormatArgImpl> args);\n\nstd::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,\n                        absl::Span<const FormatArgImpl> args);\n\nstd::string FormatPack(UntypedFormatSpecImpl format,\n                       absl::Span<const FormatArgImpl> args);\n\nint FprintF(std::FILE* output, UntypedFormatSpecImpl format,\n            absl::Span<const FormatArgImpl> args);\nint SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,\n             absl::Span<const FormatArgImpl> args);\n\n// Returned by Streamed(v). Converts via '%s' to the std::string created\n// by std::ostream << v.\ntemplate <typename T>\nclass StreamedWrapper {\n public:\n  explicit StreamedWrapper(const T& v) : v_(v) {}\n\n private:\n  template <typename S>\n  friend ArgConvertResult<FormatConversionCharSetUnion(\n      FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>\n  FormatConvertImpl(const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,\n                    FormatSinkImpl* out);\n  const T& v_;\n};\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/bind_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/bind.h\"\n\n#include <string.h>\n#include <limits>\n\n#include \"gtest/gtest.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\nnamespace {\n\nclass FormatBindTest : public ::testing::Test {\n public:\n  bool Extract(const char *s, UnboundConversion *props, int *next) const {\n    return ConsumeUnboundConversion(s, s + strlen(s), props, next) ==\n           s + strlen(s);\n  }\n};\n\nTEST_F(FormatBindTest, BindSingle) {\n  struct Expectation {\n    int line;\n    const char *fmt;\n    int ok_phases;\n    const FormatArgImpl *arg;\n    int width;\n    int precision;\n    int next_arg;\n  };\n  const int no = -1;\n  const int ia[] = { 10, 20, 30, 40};\n  const FormatArgImpl args[] = {FormatArgImpl(ia[0]), FormatArgImpl(ia[1]),\n                                FormatArgImpl(ia[2]), FormatArgImpl(ia[3])};\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wmissing-field-initializers\"\n  const Expectation kExpect[] = {\n    {__LINE__, \"d\",          2, &args[0], no, no, 2},\n    {__LINE__, \"4d\",         2, &args[0],  4, no, 2},\n    {__LINE__, \".5d\",        2, &args[0], no,  5, 2},\n    {__LINE__, \"4.5d\",       2, &args[0],  4,  5, 2},\n    {__LINE__, \"*d\",         2, &args[1], 10, no, 3},\n    {__LINE__, \".*d\",        2, &args[1], no, 10, 3},\n    {__LINE__, \"*.*d\",       2, &args[2], 10, 20, 4},\n    {__LINE__, \"1$d\",        2, &args[0], no, no, 0},\n    {__LINE__, \"2$d\",        2, &args[1], no, no, 0},\n    {__LINE__, \"3$d\",        2, &args[2], no, no, 0},\n    {__LINE__, \"4$d\",        2, &args[3], no, no, 0},\n    {__LINE__, \"2$*1$d\",     2, &args[1], 10, no, 0},\n    {__LINE__, \"2$*2$d\",     2, &args[1], 20, no, 0},\n    {__LINE__, \"2$*3$d\",     2, &args[1], 30, no, 0},\n    {__LINE__, \"2$.*1$d\",    2, &args[1], no, 10, 0},\n    {__LINE__, \"2$.*2$d\",    2, &args[1], no, 20, 0},\n    {__LINE__, \"2$.*3$d\",    2, &args[1], no, 30, 0},\n    {__LINE__, \"2$*3$.*1$d\", 2, &args[1], 30, 10, 0},\n    {__LINE__, \"2$*2$.*2$d\", 2, &args[1], 20, 20, 0},\n    {__LINE__, \"2$*1$.*3$d\", 2, &args[1], 10, 30, 0},\n    {__LINE__, \"2$*3$.*1$d\", 2, &args[1], 30, 10, 0},\n    {__LINE__, \"1$*d\",       0},  // indexed, then positional\n    {__LINE__, \"*2$d\",       0},  // positional, then indexed\n    {__LINE__, \"6$d\",        1},  // arg position out of bounds\n    {__LINE__, \"1$6$d\",      0},  // width position incorrectly specified\n    {__LINE__, \"1$.6$d\",     0},  // precision position incorrectly specified\n    {__LINE__, \"1$*6$d\",     1},  // width position out of bounds\n    {__LINE__, \"1$.*6$d\",    1},  // precision position out of bounds\n  };\n#pragma GCC diagnostic pop\n  for (const Expectation &e : kExpect) {\n    SCOPED_TRACE(e.line);\n    SCOPED_TRACE(e.fmt);\n    UnboundConversion props;\n    BoundConversion bound;\n    int ok_phases = 0;\n    int next = 0;\n    if (Extract(e.fmt, &props, &next)) {\n      ++ok_phases;\n      if (BindWithPack(&props, args, &bound)) {\n        ++ok_phases;\n      }\n    }\n    EXPECT_EQ(e.ok_phases, ok_phases);\n    if (e.ok_phases < 2) continue;\n    if (e.arg != nullptr) {\n      EXPECT_EQ(e.arg, bound.arg());\n    }\n    EXPECT_EQ(e.width, bound.width());\n    EXPECT_EQ(e.precision, bound.precision());\n  }\n}\n\nTEST_F(FormatBindTest, WidthUnderflowRegression) {\n  UnboundConversion props;\n  BoundConversion bound;\n  int next = 0;\n  const int args_i[] = {std::numeric_limits<int>::min(), 17};\n  const FormatArgImpl args[] = {FormatArgImpl(args_i[0]),\n                                FormatArgImpl(args_i[1])};\n  ASSERT_TRUE(Extract(\"*d\", &props, &next));\n  ASSERT_TRUE(BindWithPack(&props, args, &bound));\n\n  EXPECT_EQ(bound.width(), std::numeric_limits<int>::max());\n  EXPECT_EQ(bound.arg(), args + 1);\n}\n\nTEST_F(FormatBindTest, FormatPack) {\n  struct Expectation {\n    int line;\n    const char *fmt;\n    const char *summary;\n  };\n  const int ia[] = { 10, 20, 30, 40, -10 };\n  const FormatArgImpl args[] = {FormatArgImpl(ia[0]), FormatArgImpl(ia[1]),\n                                FormatArgImpl(ia[2]), FormatArgImpl(ia[3]),\n                                FormatArgImpl(ia[4])};\n  const Expectation kExpect[] = {\n      {__LINE__, \"a%4db%dc\", \"a{10:4d}b{20:d}c\"},\n      {__LINE__, \"a%.4db%dc\", \"a{10:.4d}b{20:d}c\"},\n      {__LINE__, \"a%4.5db%dc\", \"a{10:4.5d}b{20:d}c\"},\n      {__LINE__, \"a%db%4.5dc\", \"a{10:d}b{20:4.5d}c\"},\n      {__LINE__, \"a%db%*.*dc\", \"a{10:d}b{40:20.30d}c\"},\n      {__LINE__, \"a%.*fb\", \"a{20:.10f}b\"},\n      {__LINE__, \"a%1$db%2$*3$.*4$dc\", \"a{10:d}b{20:30.40d}c\"},\n      {__LINE__, \"a%4$db%3$*2$.*1$dc\", \"a{40:d}b{30:20.10d}c\"},\n      {__LINE__, \"a%04ldb\", \"a{10:04d}b\"},\n      {__LINE__, \"a%-#04lldb\", \"a{10:-#04d}b\"},\n      {__LINE__, \"a%1$*5$db\", \"a{10:-10d}b\"},\n      {__LINE__, \"a%1$.*5$db\", \"a{10:d}b\"},\n  };\n  for (const Expectation &e : kExpect) {\n    absl::string_view fmt = e.fmt;\n    SCOPED_TRACE(e.line);\n    SCOPED_TRACE(e.fmt);\n    UntypedFormatSpecImpl format(fmt);\n    EXPECT_EQ(e.summary,\n              str_format_internal::Summarize(format, absl::MakeSpan(args)))\n        << \"line:\" << e.line;\n  }\n}\n\n}  // namespace\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/checker.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_\n\n#include <algorithm>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/strings/internal/str_format/arg.h\"\n#include \"absl/strings/internal/str_format/constexpr_parser.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n\n// Compile time check support for entry points.\n\n#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n// We disable format checker under vscode intellisense compilation.\n// See https://github.com/microsoft/vscode-cpptools/issues/3683 for\n// more details.\n#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__INTELLISENSE__)\n#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1\n#endif  // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__INTELLISENSE__)\n#endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\n#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\ntemplate <FormatConversionCharSet... C>\nconstexpr bool ValidFormatImpl(string_view format) {\n  int next_arg = 0;\n  const char* p = format.data();\n  const char* const end = p + format.size();\n  constexpr FormatConversionCharSet\n      kAllowedConvs[(std::max)(sizeof...(C), size_t{1})] = {C...};\n  bool used[(std::max)(sizeof...(C), size_t{1})]{};\n  constexpr int kNumArgs = sizeof...(C);\n  while (p != end) {\n    while (p != end && *p != '%') ++p;\n    if (p == end) {\n      break;\n    }\n    if (p + 1 >= end) return false;\n    if (p[1] == '%') {\n      // %%\n      p += 2;\n      continue;\n    }\n\n    UnboundConversion conv(absl::kConstInit);\n    p = ConsumeUnboundConversion(p + 1, end, &conv, &next_arg);\n    if (p == nullptr) return false;\n    if (conv.arg_position <= 0 || conv.arg_position > kNumArgs) {\n      return false;\n    }\n    if (!Contains(kAllowedConvs[conv.arg_position - 1], conv.conv)) {\n      return false;\n    }\n    used[conv.arg_position - 1] = true;\n    for (auto extra : {conv.width, conv.precision}) {\n      if (extra.is_from_arg()) {\n        int pos = extra.get_from_arg();\n        if (pos <= 0 || pos > kNumArgs) return false;\n        used[pos - 1] = true;\n        if (!Contains(kAllowedConvs[pos - 1], '*')) {\n          return false;\n        }\n      }\n    }\n  }\n  if (sizeof...(C) != 0) {\n    for (bool b : used) {\n      if (!b) return false;\n    }\n  }\n  return true;\n}\n\n#endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/checker_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\nnamespace {\n\nstd::string ConvToString(FormatConversionCharSet conv) {\n  std::string out;\n#define CONV_SET_CASE(c)                                    \\\n  if (Contains(conv, FormatConversionCharSetInternal::c)) { \\\n    out += #c;                                              \\\n  }\n  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )\n#undef CONV_SET_CASE\n  if (Contains(conv, FormatConversionCharSetInternal::kStar)) {\n    out += \"*\";\n  }\n  return out;\n}\n\nTEST(StrFormatChecker, ArgumentToConv) {\n  FormatConversionCharSet conv = ArgumentToConv<std::string>();\n  EXPECT_EQ(ConvToString(conv), \"sv\");\n\n  conv = ArgumentToConv<const char*>();\n  EXPECT_EQ(ConvToString(conv), \"sp\");\n\n  conv = ArgumentToConv<double>();\n  EXPECT_EQ(ConvToString(conv), \"fFeEgGaAv\");\n\n  conv = ArgumentToConv<int>();\n  EXPECT_EQ(ConvToString(conv), \"cdiouxXfFeEgGaAv*\");\n\n  conv = ArgumentToConv<std::string*>();\n  EXPECT_EQ(ConvToString(conv), \"p\");\n}\n\n#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\nstruct Case {\n  bool result;\n  const char* format;\n};\n\ntemplate <typename... Args>\nconstexpr Case ValidFormat(const char* format) {\n  return {ValidFormatImpl<ArgumentToConv<Args>()...>(format), format};\n}\n\nTEST(StrFormatChecker, ValidFormat) {\n  // We want to make sure these expressions are constexpr and they have the\n  // expected value.\n  // If they are not constexpr the attribute will just ignore them and not give\n  // a compile time error.\n  enum e {};\n  enum class e2 {};\n  constexpr Case trues[] = {\n      ValidFormat<>(\"abc\"),  //\n\n      ValidFormat<e>(\"%d\"),                             //\n      ValidFormat<e2>(\"%d\"),                            //\n      ValidFormat<int>(\"%% %d\"),                        //\n      ValidFormat<int>(\"%ld\"),                          //\n      ValidFormat<int>(\"%lld\"),                         //\n      ValidFormat<std::string>(\"%s\"),                   //\n      ValidFormat<std::string>(\"%10s\"),                 //\n      ValidFormat<int>(\"%.10x\"),                        //\n      ValidFormat<int, int>(\"%*.3x\"),                   //\n      ValidFormat<int>(\"%1.d\"),                         //\n      ValidFormat<int>(\"%.d\"),                          //\n      ValidFormat<int, double>(\"%d %g\"),                //\n      ValidFormat<int, std::string>(\"%*s\"),             //\n      ValidFormat<int, double>(\"%.*f\"),                 //\n      ValidFormat<void (*)(), volatile int*>(\"%p %p\"),  //\n      ValidFormat<string_view, const char*, double, void*>(\n          \"string_view=%s const char*=%s double=%f void*=%p)\"),\n      ValidFormat<int>(\"%v\"),  //\n\n      ValidFormat<int>(\"%% %1$d\"),               //\n      ValidFormat<int>(\"%1$ld\"),                 //\n      ValidFormat<int>(\"%1$lld\"),                //\n      ValidFormat<std::string>(\"%1$s\"),          //\n      ValidFormat<std::string>(\"%1$10s\"),        //\n      ValidFormat<int>(\"%1$.10x\"),               //\n      ValidFormat<int>(\"%1$*1$.*1$d\"),           //\n      ValidFormat<int, int>(\"%1$*2$.3x\"),        //\n      ValidFormat<int>(\"%1$1.d\"),                //\n      ValidFormat<int>(\"%1$.d\"),                 //\n      ValidFormat<double, int>(\"%2$d %1$g\"),     //\n      ValidFormat<int, std::string>(\"%2$*1$s\"),  //\n      ValidFormat<int, double>(\"%2$.*1$f\"),      //\n      ValidFormat<void*, string_view, const char*, double>(\n          \"string_view=%2$s const char*=%3$s double=%4$f void*=%1$p \"\n          \"repeat=%3$s)\"),\n      ValidFormat<std::string>(\"%1$v\"),\n  };\n\n  for (Case c : trues) {\n    EXPECT_TRUE(c.result) << c.format;\n  }\n\n  constexpr Case falses[] = {\n      ValidFormat<int>(\"\"),  //\n\n      ValidFormat<e>(\"%s\"),                  //\n      ValidFormat<e2>(\"%s\"),                 //\n      ValidFormat<>(\"%s\"),                   //\n      ValidFormat<>(\"%r\"),                   //\n      ValidFormat<int>(\"%s\"),                //\n      ValidFormat<int>(\"%.1.d\"),             //\n      ValidFormat<int>(\"%*1d\"),              //\n      ValidFormat<int>(\"%1-d\"),              //\n      ValidFormat<std::string, int>(\"%*s\"),  //\n      ValidFormat<int>(\"%*d\"),               //\n      ValidFormat<std::string>(\"%p\"),        //\n      ValidFormat<int (*)(int)>(\"%d\"),       //\n      ValidFormat<int>(\"%1v\"),               //\n      ValidFormat<int>(\"%.1v\"),              //\n\n      ValidFormat<>(\"%3$d\"),                     //\n      ValidFormat<>(\"%1$r\"),                     //\n      ValidFormat<int>(\"%1$s\"),                  //\n      ValidFormat<int>(\"%1$.1.d\"),               //\n      ValidFormat<int>(\"%1$*2$1d\"),              //\n      ValidFormat<int>(\"%1$1-d\"),                //\n      ValidFormat<std::string, int>(\"%2$*1$s\"),  //\n      ValidFormat<std::string>(\"%1$p\"),          //\n      ValidFormat<int>(\"%1$*2$v\"),               //\n\n      ValidFormat<int, int>(\"%d %2$d\"),  //\n  };\n\n  for (Case c : falses) {\n    EXPECT_FALSE(c.result) << \"format<\" << c.format << \">\";\n  }\n}\n\nTEST(StrFormatChecker, LongFormat) {\n#define CHARS_X_40 \"1234567890123456789012345678901234567890\"\n#define CHARS_X_400                                                            \\\n  CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 \\\n      CHARS_X_40 CHARS_X_40 CHARS_X_40\n#define CHARS_X_4000                                                      \\\n  CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 \\\n      CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400\n  constexpr char long_format[] =\n      CHARS_X_4000 \"%d\" CHARS_X_4000 \"%s\" CHARS_X_4000;\n  constexpr bool is_valid = ValidFormat<int, std::string>(long_format).result;\n  EXPECT_TRUE(is_valid);\n}\n\n#endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n\n}  // namespace\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/constexpr_parser.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_\n\n#include <cassert>\n#include <cstdint>\n#include <cstdio>\n#include <limits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\n// The analyzed properties of a single specified conversion.\nstruct UnboundConversion {\n  // This is a user defined default constructor on purpose to skip the\n  // initialization of parts of the object that are not necessary.\n  UnboundConversion() {}  // NOLINT\n\n  // This constructor is provided for the static checker. We don't want to do\n  // the unnecessary initialization in the normal case.\n  explicit constexpr UnboundConversion(absl::ConstInitType)\n      : arg_position{}, width{}, precision{} {}\n\n  class InputValue {\n   public:\n    constexpr void set_value(int value) {\n      assert(value >= 0);\n      value_ = value;\n    }\n    constexpr int value() const { return value_; }\n\n    // Marks the value as \"from arg\". aka the '*' format.\n    // Requires `value >= 1`.\n    // When set, is_from_arg() return true and get_from_arg() returns the\n    // original value.\n    // `value()`'s return value is unspecified in this state.\n    constexpr void set_from_arg(int value) {\n      assert(value > 0);\n      value_ = -value - 1;\n    }\n    constexpr bool is_from_arg() const { return value_ < -1; }\n    constexpr int get_from_arg() const {\n      assert(is_from_arg());\n      return -value_ - 1;\n    }\n\n   private:\n    int value_ = -1;\n  };\n\n  // No need to initialize. It will always be set in the parser.\n  int arg_position;\n\n  InputValue width;\n  InputValue precision;\n\n  Flags flags = Flags::kBasic;\n  LengthMod length_mod = LengthMod::none;\n  FormatConversionChar conv = FormatConversionCharInternal::kNone;\n};\n\n// Helper tag class for the table below.\n// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and\n// conversions.\nclass ConvTag {\n public:\n  constexpr ConvTag(FormatConversionChar conversion_char)  // NOLINT\n      : tag_(static_cast<uint8_t>(conversion_char)) {}\n  constexpr ConvTag(LengthMod length_mod)  // NOLINT\n      : tag_(0x80 | static_cast<uint8_t>(length_mod)) {}\n  constexpr ConvTag(Flags flags)  // NOLINT\n      : tag_(0xc0 | static_cast<uint8_t>(flags)) {}\n  constexpr ConvTag() : tag_(0xFF) {}\n\n  constexpr bool is_conv() const { return (tag_ & 0x80) == 0; }\n  constexpr bool is_length() const { return (tag_ & 0xC0) == 0x80; }\n  constexpr bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }\n\n  constexpr FormatConversionChar as_conv() const {\n    assert(is_conv());\n    assert(!is_length());\n    assert(!is_flags());\n    return static_cast<FormatConversionChar>(tag_);\n  }\n  constexpr LengthMod as_length() const {\n    assert(!is_conv());\n    assert(is_length());\n    assert(!is_flags());\n    return static_cast<LengthMod>(tag_ & 0x3F);\n  }\n  constexpr Flags as_flags() const {\n    assert(!is_conv());\n    assert(!is_length());\n    assert(is_flags());\n    return static_cast<Flags>(tag_ & 0x1F);\n  }\n\n private:\n  uint8_t tag_;\n};\n\nstruct ConvTagHolder {\n  using CC = FormatConversionCharInternal;\n  using LM = LengthMod;\n\n  // Abbreviations to fit in the table below.\n  static constexpr auto kFSign = Flags::kSignCol;\n  static constexpr auto kFAlt = Flags::kAlt;\n  static constexpr auto kFPos = Flags::kShowPos;\n  static constexpr auto kFLeft = Flags::kLeft;\n  static constexpr auto kFZero = Flags::kZero;\n\n  static constexpr ConvTag value[256] = {\n      {},     {},    {},    {},    {},    {},     {},    {},     // 00-07\n      {},     {},    {},    {},    {},    {},     {},    {},     // 08-0f\n      {},     {},    {},    {},    {},    {},     {},    {},     // 10-17\n      {},     {},    {},    {},    {},    {},     {},    {},     // 18-1f\n      kFSign, {},    {},    kFAlt, {},    {},     {},    {},     //  !\"#$%&'\n      {},     {},    {},    kFPos, {},    kFLeft, {},    {},     // ()*+,-./\n      kFZero, {},    {},    {},    {},    {},     {},    {},     // 01234567\n      {},     {},    {},    {},    {},    {},     {},    {},     // 89:;<=>?\n      {},     CC::A, {},    {},    {},    CC::E,  CC::F, CC::G,  // @ABCDEFG\n      {},     {},    {},    {},    LM::L, {},     {},    {},     // HIJKLMNO\n      {},     {},    {},    {},    {},    {},     {},    {},     // PQRSTUVW\n      CC::X,  {},    {},    {},    {},    {},     {},    {},     // XYZ[\\]^_\n      {},     CC::a, {},    CC::c, CC::d, CC::e,  CC::f, CC::g,  // `abcdefg\n      LM::h,  CC::i, LM::j, {},    LM::l, {},     CC::n, CC::o,  // hijklmno\n      CC::p,  LM::q, {},    CC::s, LM::t, CC::u,  CC::v, {},     // pqrstuvw\n      CC::x,  {},    LM::z, {},    {},    {},     {},    {},     // xyz{|}!\n      {},     {},    {},    {},    {},    {},     {},    {},     // 80-87\n      {},     {},    {},    {},    {},    {},     {},    {},     // 88-8f\n      {},     {},    {},    {},    {},    {},     {},    {},     // 90-97\n      {},     {},    {},    {},    {},    {},     {},    {},     // 98-9f\n      {},     {},    {},    {},    {},    {},     {},    {},     // a0-a7\n      {},     {},    {},    {},    {},    {},     {},    {},     // a8-af\n      {},     {},    {},    {},    {},    {},     {},    {},     // b0-b7\n      {},     {},    {},    {},    {},    {},     {},    {},     // b8-bf\n      {},     {},    {},    {},    {},    {},     {},    {},     // c0-c7\n      {},     {},    {},    {},    {},    {},     {},    {},     // c8-cf\n      {},     {},    {},    {},    {},    {},     {},    {},     // d0-d7\n      {},     {},    {},    {},    {},    {},     {},    {},     // d8-df\n      {},     {},    {},    {},    {},    {},     {},    {},     // e0-e7\n      {},     {},    {},    {},    {},    {},     {},    {},     // e8-ef\n      {},     {},    {},    {},    {},    {},     {},    {},     // f0-f7\n      {},     {},    {},    {},    {},    {},     {},    {},     // f8-ff\n  };\n};\n\n// Keep a single table for all the conversion chars and length modifiers.\nconstexpr ConvTag GetTagForChar(char c) {\n  return ConvTagHolder::value[static_cast<unsigned char>(c)];\n}\n\nconstexpr bool CheckFastPathSetting(const UnboundConversion& conv) {\n  bool width_precision_needed =\n      conv.width.value() >= 0 || conv.precision.value() >= 0;\n  if (width_precision_needed && conv.flags == Flags::kBasic) {\n#if defined(__clang__)\n    // Some compilers complain about this in constexpr even when not executed,\n    // so only enable the error dump in clang.\n    fprintf(stderr,\n            \"basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d \"\n            \"width=%d precision=%d\\n\",\n            conv.flags == Flags::kBasic ? 1 : 0,\n            FlagsContains(conv.flags, Flags::kLeft) ? 1 : 0,\n            FlagsContains(conv.flags, Flags::kShowPos) ? 1 : 0,\n            FlagsContains(conv.flags, Flags::kSignCol) ? 1 : 0,\n            FlagsContains(conv.flags, Flags::kAlt) ? 1 : 0,\n            FlagsContains(conv.flags, Flags::kZero) ? 1 : 0, conv.width.value(),\n            conv.precision.value());\n#endif  // defined(__clang__)\n    return false;\n  }\n  return true;\n}\n\nconstexpr int ParseDigits(char& c, const char*& pos, const char* const end) {\n  int digits = c - '0';\n  // We do not want to overflow `digits` so we consume at most digits10\n  // digits. If there are more digits the parsing will fail later on when the\n  // digit doesn't match the expected characters.\n  int num_digits = std::numeric_limits<int>::digits10;\n  for (;;) {\n    if (ABSL_PREDICT_FALSE(pos == end)) break;\n    c = *pos++;\n    if ('0' > c || c > '9') break;\n    --num_digits;\n    if (ABSL_PREDICT_FALSE(!num_digits)) break;\n    digits = 10 * digits + c - '0';\n  }\n  return digits;\n}\n\ntemplate <bool is_positional>\nconstexpr const char* ConsumeConversion(const char* pos, const char* const end,\n                                        UnboundConversion* conv,\n                                        int* next_arg) {\n  const char* const original_pos = pos;\n  char c = 0;\n  // Read the next char into `c` and update `pos`. Returns false if there are\n  // no more chars to read.\n#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR()          \\\n  do {                                                  \\\n    if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \\\n    c = *pos++;                                         \\\n  } while (0)\n\n  if (is_positional) {\n    ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n    if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;\n    conv->arg_position = ParseDigits(c, pos, end);\n    assert(conv->arg_position > 0);\n    if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;\n  }\n\n  ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n\n  // We should start with the basic flag on.\n  assert(conv->flags == Flags::kBasic);\n\n  // Any non alpha character makes this conversion not basic.\n  // This includes flags (-+ #0), width (1-9, *) or precision (.).\n  // All conversion characters and length modifiers are alpha characters.\n  if (c < 'A') {\n    while (c <= '0') {\n      auto tag = GetTagForChar(c);\n      if (tag.is_flags()) {\n        conv->flags = conv->flags | tag.as_flags();\n        ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n      } else {\n        break;\n      }\n    }\n\n    if (c <= '9') {\n      if (c >= '0') {\n        int maybe_width = ParseDigits(c, pos, end);\n        if (!is_positional && c == '$') {\n          if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;\n          // Positional conversion.\n          *next_arg = -1;\n          return ConsumeConversion<true>(original_pos, end, conv, next_arg);\n        }\n        conv->flags = conv->flags | Flags::kNonBasic;\n        conv->width.set_value(maybe_width);\n      } else if (c == '*') {\n        conv->flags = conv->flags | Flags::kNonBasic;\n        ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n        if (is_positional) {\n          if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;\n          conv->width.set_from_arg(ParseDigits(c, pos, end));\n          if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;\n          ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n        } else {\n          conv->width.set_from_arg(++*next_arg);\n        }\n      }\n    }\n\n    if (c == '.') {\n      conv->flags = conv->flags | Flags::kNonBasic;\n      ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n      if ('0' <= c && c <= '9') {\n        conv->precision.set_value(ParseDigits(c, pos, end));\n      } else if (c == '*') {\n        ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n        if (is_positional) {\n          if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;\n          conv->precision.set_from_arg(ParseDigits(c, pos, end));\n          if (c != '$') return nullptr;\n          ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n        } else {\n          conv->precision.set_from_arg(++*next_arg);\n        }\n      } else {\n        conv->precision.set_value(0);\n      }\n    }\n  }\n\n  auto tag = GetTagForChar(c);\n\n  if (ABSL_PREDICT_FALSE(c == 'v' && conv->flags != Flags::kBasic)) {\n    return nullptr;\n  }\n\n  if (ABSL_PREDICT_FALSE(!tag.is_conv())) {\n    if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;\n\n    // It is a length modifier.\n    LengthMod length_mod = tag.as_length();\n    ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n    if (c == 'h' && length_mod == LengthMod::h) {\n      conv->length_mod = LengthMod::hh;\n      ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n    } else if (c == 'l' && length_mod == LengthMod::l) {\n      conv->length_mod = LengthMod::ll;\n      ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();\n    } else {\n      conv->length_mod = length_mod;\n    }\n    tag = GetTagForChar(c);\n\n    if (ABSL_PREDICT_FALSE(c == 'v')) return nullptr;\n    if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;\n\n    // `wchar_t` args are marked non-basic so `Bind()` will copy the length mod.\n    if (conv->length_mod == LengthMod::l && c == 'c') {\n      conv->flags = conv->flags | Flags::kNonBasic;\n    }\n  }\n#undef ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR\n\n  assert(CheckFastPathSetting(*conv));\n  (void)(&CheckFastPathSetting);\n\n  conv->conv = tag.as_conv();\n  if (!is_positional) conv->arg_position = ++*next_arg;\n  return pos;\n}\n\n// Consume conversion spec prefix (not including '%') of [p, end) if valid.\n// Examples of valid specs would be e.g.: \"s\", \"d\", \"-12.6f\".\n// If valid, it returns the first character following the conversion spec,\n// and the spec part is broken down and returned in 'conv'.\n// If invalid, returns nullptr.\nconstexpr const char* ConsumeUnboundConversion(const char* p, const char* end,\n                                               UnboundConversion* conv,\n                                               int* next_arg) {\n  if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);\n  return ConsumeConversion<false>(p, end, conv, next_arg);\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/convert_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <assert.h>\n#include <locale.h>\n#include <stdarg.h>\n#include <stdio.h>\n\n#include <algorithm>\n#include <climits>\n#include <cmath>\n#include <cstdlib>\n#include <cstring>\n#include <cwctype>\n#include <limits>\n#include <optional>\n#include <set>\n#include <sstream>\n#include <string>\n#include <string_view>\n#include <thread>  // NOLINT\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/log/log.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/internal/str_format/arg.h\"\n#include \"absl/strings/internal/str_format/bind.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\nnamespace {\n\nstruct NativePrintfTraits {\n  bool hex_float_has_glibc_rounding;\n  bool hex_float_prefers_denormal_repr;\n  bool hex_float_uses_minimal_precision_when_not_specified;\n  bool hex_float_optimizes_leading_digit_bit_count;\n};\n\ntemplate <typename T, size_t N>\nsize_t ArraySize(T (&)[N]) {\n  return N;\n}\n\ntemplate <typename T>\nstruct AlwaysFalse : std::false_type {};\n\ntemplate <typename T>\nstd::string LengthModFor() {\n  static_assert(AlwaysFalse<T>::value, \"Unsupported type\");\n  return \"\";\n}\ntemplate <>\nstd::string LengthModFor<char>() {\n  return \"hh\";\n}\ntemplate <>\nstd::string LengthModFor<signed char>() {\n  return \"hh\";\n}\ntemplate <>\nstd::string LengthModFor<unsigned char>() {\n  return \"hh\";\n}\ntemplate <>\nstd::string LengthModFor<short>() {  // NOLINT\n  return \"h\";\n}\ntemplate <>\nstd::string LengthModFor<unsigned short>() {  // NOLINT\n  return \"h\";\n}\ntemplate <>\nstd::string LengthModFor<int>() {\n  return \"\";\n}\ntemplate <>\nstd::string LengthModFor<unsigned>() {\n  return \"\";\n}\ntemplate <>\nstd::string LengthModFor<long>() {  // NOLINT\n  return \"l\";\n}\ntemplate <>\nstd::string LengthModFor<unsigned long>() {  // NOLINT\n  return \"l\";\n}\ntemplate <>\nstd::string LengthModFor<long long>() {  // NOLINT\n  return \"ll\";\n}\ntemplate <>\nstd::string LengthModFor<unsigned long long>() {  // NOLINT\n  return \"ll\";\n}\n\n// An integral type of the same rank and signedness as `wchar_t`, that isn't\n// `wchar_t`.\nusing IntegralTypeForWCharT =\n    std::conditional_t<std::is_signed<wchar_t>::value,\n                       // Some STLs are broken and return `wchar_t` from\n                       // `std::make_[un]signed_t<wchar_t>` when the signedness\n                       // matches. Work around by round-tripping through the\n                       // opposite signedness.\n                       std::make_signed_t<std::make_unsigned_t<wchar_t>>,\n                       std::make_unsigned_t<std::make_signed_t<wchar_t>>>;\n\n// Given an integral type `T`, returns a type of the same rank and signedness\n// that is guaranteed to not be `wchar_t`.\ntemplate <typename T>\nusing MatchingIntegralType = std::conditional_t<std::is_same<T, wchar_t>::value,\n                                                IntegralTypeForWCharT, T>;\n\nstd::string EscCharImpl(int v) {\n  char buf[64];\n  int n = absl::ascii_isprint(static_cast<unsigned char>(v))\n              ? snprintf(buf, sizeof(buf), \"'%c'\", v)\n              : snprintf(buf, sizeof(buf), \"'\\\\x%.*x'\", CHAR_BIT / 4,\n                         static_cast<unsigned>(\n                             static_cast<std::make_unsigned_t<char>>(v)));\n  assert(n > 0 && static_cast<size_t>(n) < sizeof(buf));\n  return std::string(buf, static_cast<size_t>(n));\n}\n\nstd::string Esc(char v) { return EscCharImpl(v); }\nstd::string Esc(signed char v) { return EscCharImpl(v); }\nstd::string Esc(unsigned char v) { return EscCharImpl(v); }\n\nstd::string Esc(wchar_t v) {\n  char buf[64];\n  int n = std::iswprint(static_cast<wint_t>(v))\n              ? snprintf(buf, sizeof(buf), \"L'%lc'\", static_cast<wint_t>(v))\n              : snprintf(buf, sizeof(buf), \"L'\\\\x%.*llx'\",\n                         static_cast<int>(sizeof(wchar_t) * CHAR_BIT / 4),\n                         static_cast<unsigned long long>(\n                             static_cast<std::make_unsigned_t<wchar_t>>(v)));\n  assert(n > 0 && static_cast<size_t>(n) < sizeof(buf));\n  return std::string(buf, static_cast<size_t>(n));\n}\n\ntemplate <typename T>\nstd::string Esc(const T &v) {\n  std::ostringstream oss;\n  oss << v;\n  return oss.str();\n}\n\nvoid StrAppendV(std::string *dst, const char *format, va_list ap) {\n  // First try with a small fixed size buffer\n  static const int kSpaceLength = 1024;\n  char space[kSpaceLength];\n\n  // It's possible for methods that use a va_list to invalidate\n  // the data in it upon use.  The fix is to make a copy\n  // of the structure before using it and use that copy instead.\n  va_list backup_ap;\n  va_copy(backup_ap, ap);\n  int result = vsnprintf(space, kSpaceLength, format, backup_ap);\n  va_end(backup_ap);\n  if (result < kSpaceLength) {\n    if (result >= 0) {\n      // Normal case -- everything fit.\n      dst->append(space, static_cast<size_t>(result));\n      return;\n    }\n    if (result < 0) {\n      // Just an error.\n      return;\n    }\n  }\n\n  // Increase the buffer size to the size requested by vsnprintf,\n  // plus one for the closing \\0.\n  size_t length = static_cast<size_t>(result) + 1;\n  char *buf = new char[length];\n\n  // Restore the va_list before we use it again\n  va_copy(backup_ap, ap);\n  result = vsnprintf(buf, length, format, backup_ap);\n  va_end(backup_ap);\n\n  if (result >= 0 && static_cast<size_t>(result) < length) {\n    // It fit\n    dst->append(buf, static_cast<size_t>(result));\n  }\n  delete[] buf;\n}\n\nvoid StrAppend(std::string *, const char *, ...) ABSL_PRINTF_ATTRIBUTE(2, 3);\nvoid StrAppend(std::string *out, const char *format, ...) {\n  va_list ap;\n  va_start(ap, format);\n  StrAppendV(out, format, ap);\n  va_end(ap);\n}\n\nstd::string StrPrint(const char *, ...) ABSL_PRINTF_ATTRIBUTE(1, 2);\nstd::string StrPrint(const char *format, ...) {\n  va_list ap;\n  va_start(ap, format);\n  std::string result;\n  StrAppendV(&result, format, ap);\n  va_end(ap);\n  return result;\n}\n\nNativePrintfTraits VerifyNativeImplementationImpl() {\n  NativePrintfTraits result;\n\n  // >>> hex_float_has_glibc_rounding. To have glibc's rounding behavior we need\n  // to meet three requirements:\n  //\n  //   - The threshold for rounding up is 8 (for e.g. MSVC uses 9).\n  //   - If the digits lower than than the 8 are non-zero then we round up.\n  //   - If the digits lower than the 8 are all zero then we round toward even.\n  //\n  // The numbers below represent all the cases covering {below,at,above} the\n  // threshold (8) with both {zero,non-zero} lower bits and both {even,odd}\n  // preceding digits.\n  const double d0079 = 65657.0;  // 0x1.0079p+16\n  const double d0179 = 65913.0;  // 0x1.0179p+16\n  const double d0080 = 65664.0;  // 0x1.0080p+16\n  const double d0180 = 65920.0;  // 0x1.0180p+16\n  const double d0081 = 65665.0;  // 0x1.0081p+16\n  const double d0181 = 65921.0;  // 0x1.0181p+16\n  result.hex_float_has_glibc_rounding =\n      StartsWith(StrPrint(\"%.2a\", d0079), \"0x1.00\") &&\n      StartsWith(StrPrint(\"%.2a\", d0179), \"0x1.01\") &&\n      StartsWith(StrPrint(\"%.2a\", d0080), \"0x1.00\") &&\n      StartsWith(StrPrint(\"%.2a\", d0180), \"0x1.02\") &&\n      StartsWith(StrPrint(\"%.2a\", d0081), \"0x1.01\") &&\n      StartsWith(StrPrint(\"%.2a\", d0181), \"0x1.02\");\n\n  // >>> hex_float_prefers_denormal_repr. Formatting `denormal` on glibc yields\n  // \"0x0.0000000000001p-1022\", whereas on std libs that don't use denormal\n  // representation it would either be 0x1p-1074 or 0x1.0000000000000-1074.\n  const double denormal = std::numeric_limits<double>::denorm_min();\n  result.hex_float_prefers_denormal_repr =\n      StartsWith(StrPrint(\"%a\", denormal), \"0x0.0000000000001\");\n\n  // >>> hex_float_uses_minimal_precision_when_not_specified. Some (non-glibc)\n  // libs will format the following as \"0x1.0079000000000p+16\".\n  result.hex_float_uses_minimal_precision_when_not_specified =\n      (StrPrint(\"%a\", d0079) == \"0x1.0079p+16\");\n\n  // >>> hex_float_optimizes_leading_digit_bit_count. The number 1.5, when\n  // formatted by glibc should yield \"0x1.8p+0\" for `double` and \"0xcp-3\" for\n  // `long double`, i.e., number of bits in the leading digit is adapted to the\n  // number of bits in the mantissa.\n  const double d_15 = 1.5;\n  const long double ld_15 = 1.5;\n  result.hex_float_optimizes_leading_digit_bit_count =\n      StartsWith(StrPrint(\"%a\", d_15), \"0x1.8\") &&\n      StartsWith(StrPrint(\"%La\", ld_15), \"0xc\");\n\n  return result;\n}\n\nconst NativePrintfTraits &VerifyNativeImplementation() {\n  static NativePrintfTraits native_traits = VerifyNativeImplementationImpl();\n  return native_traits;\n}\n\nbool IsNativeHexFloatConversion(char f) { return f == 'a' || f == 'A'; }\nbool IsNativeFloatConversion(char f) {\n  return f == 'f' || f == 'F' || f == 'e' || f == 'E' || f == 'a' || f == 'A';\n}\n\nclass FormatConvertTest : public ::testing::Test { };\n\ntemplate <typename T>\nvoid TestStringConvert(const T& str) {\n  const FormatArgImpl args[] = {FormatArgImpl(str)};\n  struct Expectation {\n    const char *out;\n    const char *fmt;\n  };\n  const Expectation kExpect[] = {\n    {\"hello\",  \"%1$s\"      },\n    {\"\",       \"%1$.s\"     },\n    {\"\",       \"%1$.0s\"    },\n    {\"h\",      \"%1$.1s\"    },\n    {\"he\",     \"%1$.2s\"    },\n    {\"hello\",  \"%1$.10s\"   },\n    {\" hello\", \"%1$6s\"     },\n    {\"   he\",  \"%1$5.2s\"   },\n    {\"he   \",  \"%1$-5.2s\"  },\n    {\"hello \", \"%1$-6.10s\" },\n  };\n  for (const Expectation &e : kExpect) {\n    UntypedFormatSpecImpl format(e.fmt);\n    EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args)));\n  }\n}\n\nTEST_F(FormatConvertTest, BasicString) {\n  TestStringConvert(\"hello\");  // As char array.\n  TestStringConvert(L\"hello\");\n  TestStringConvert(static_cast<const char*>(\"hello\"));\n  TestStringConvert(static_cast<const wchar_t*>(L\"hello\"));\n  TestStringConvert(std::string(\"hello\"));\n  TestStringConvert(std::wstring(L\"hello\"));\n  TestStringConvert(string_view(\"hello\"));\n  TestStringConvert(std::string_view(\"hello\"));\n  TestStringConvert(std::wstring_view(L\"hello\"));\n}\n\nTEST_F(FormatConvertTest, NullString) {\n  const char* p = nullptr;\n  UntypedFormatSpecImpl format(\"%s\");\n  EXPECT_EQ(\"\", FormatPack(format, {FormatArgImpl(p)}));\n\n  const wchar_t* wp = nullptr;\n  UntypedFormatSpecImpl wformat(\"%ls\");\n  EXPECT_EQ(\"\", FormatPack(wformat, {FormatArgImpl(wp)}));\n}\n\nTEST_F(FormatConvertTest, StringPrecision) {\n  // We cap at the precision.\n  char c = 'a';\n  const char* p = &c;\n  UntypedFormatSpecImpl format(\"%.1s\");\n  EXPECT_EQ(\"a\", FormatPack(format, {FormatArgImpl(p)}));\n\n  wchar_t wc = L'a';\n  const wchar_t* wp = &wc;\n  UntypedFormatSpecImpl wformat(\"%.1ls\");\n  EXPECT_EQ(\"a\", FormatPack(wformat, {FormatArgImpl(wp)}));\n\n  // We cap at the NUL-terminator.\n  p = \"ABC\";\n  UntypedFormatSpecImpl format2(\"%.10s\");\n  EXPECT_EQ(\"ABC\", FormatPack(format2, {FormatArgImpl(p)}));\n\n  wp = L\"ABC\";\n  UntypedFormatSpecImpl wformat2(\"%.10ls\");\n  EXPECT_EQ(\"ABC\", FormatPack(wformat2, {FormatArgImpl(wp)}));\n}\n\n// Pointer formatting is implementation defined. This checks that the argument\n// can be matched to `ptr`.\nMATCHER_P(MatchesPointerString, ptr, \"\") {\n  if (ptr == nullptr && arg == \"(nil)\") {\n    return true;\n  }\n  void* parsed = nullptr;\n  if (sscanf(arg.c_str(), \"%p\", &parsed) != 1) {\n    LOG(FATAL) << \"Could not parse \" << arg;\n  }\n  return ptr == parsed;\n}\n\nTEST_F(FormatConvertTest, Pointer) {\n  static int x = 0;\n  const int *xp = &x;\n  char c = 'h';\n  char *mcp = &c;\n  const char *cp = \"hi\";\n  const char *cnil = nullptr;\n  wchar_t wc = L'h';\n  wchar_t *mwcp = &wc;\n  const wchar_t *wcp = L\"hi\";\n  const wchar_t *wcnil = nullptr;\n  const int *inil = nullptr;\n  using VoidF = void (*)();\n  VoidF fp = [] {}, fnil = nullptr;\n  volatile char vc;\n  volatile char *vcp = &vc;\n  volatile char *vcnil = nullptr;\n  volatile wchar_t vwc;\n  volatile wchar_t *vwcp = &vwc;\n  volatile wchar_t *vwcnil = nullptr;\n  const FormatArgImpl args_array[] = {\n      FormatArgImpl(xp),    FormatArgImpl(cp),     FormatArgImpl(wcp),\n      FormatArgImpl(inil),  FormatArgImpl(cnil),   FormatArgImpl(wcnil),\n      FormatArgImpl(mcp),   FormatArgImpl(mwcp),   FormatArgImpl(fp),\n      FormatArgImpl(fnil),  FormatArgImpl(vcp),    FormatArgImpl(vwcp),\n      FormatArgImpl(vcnil), FormatArgImpl(vwcnil),\n  };\n  auto args = absl::MakeConstSpan(args_array);\n\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%20p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%.1p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%.20p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%30.20p\"), args),\n              MatchesPointerString(&x));\n\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%-p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%-20p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%-.1p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%.20p\"), args),\n              MatchesPointerString(&x));\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%-30.20p\"), args),\n              MatchesPointerString(&x));\n\n  // const int*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%1$p\"), args),\n              MatchesPointerString(xp));\n  // const char*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%2$p\"), args),\n              MatchesPointerString(cp));\n  // const wchar_t*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%3$p\"), args),\n              MatchesPointerString(wcp));\n  // null const int*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%4$p\"), args),\n              MatchesPointerString(nullptr));\n  // null const char*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%5$p\"), args),\n              MatchesPointerString(nullptr));\n  // null const wchar_t*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%6$p\"), args),\n              MatchesPointerString(nullptr));\n  // nonconst char*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%7$p\"), args),\n              MatchesPointerString(mcp));\n  // nonconst wchar_t*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%8$p\"), args),\n              MatchesPointerString(mwcp));\n  // function pointer\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%9$p\"), args),\n              MatchesPointerString(reinterpret_cast<const void *>(fp)));\n  // null function pointer\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%10$p\"), args),\n              MatchesPointerString(nullptr));\n  // volatile char*\n  EXPECT_THAT(\n      FormatPack(UntypedFormatSpecImpl(\"%11$p\"), args),\n      MatchesPointerString(reinterpret_cast<volatile const void *>(vcp)));\n  // volatile wchar_t*\n  EXPECT_THAT(\n      FormatPack(UntypedFormatSpecImpl(\"%12$p\"), args),\n      MatchesPointerString(reinterpret_cast<volatile const void *>(vwcp)));\n  // null volatile char*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%13$p\"), args),\n              MatchesPointerString(nullptr));\n  // null volatile wchar_t*\n  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl(\"%14$p\"), args),\n              MatchesPointerString(nullptr));\n}\n\nstruct Cardinal {\n  enum Pos { k1 = 1, k2 = 2, k3 = 3 };\n  enum Neg { kM1 = -1, kM2 = -2, kM3 = -3 };\n};\n\nTEST_F(FormatConvertTest, Enum) {\n  const Cardinal::Pos k3 = Cardinal::k3;\n  const Cardinal::Neg km3 = Cardinal::kM3;\n  const FormatArgImpl args[] = {FormatArgImpl(k3), FormatArgImpl(km3)};\n  UntypedFormatSpecImpl format(\"%1$d\");\n  UntypedFormatSpecImpl format2(\"%2$d\");\n  EXPECT_EQ(\"3\", FormatPack(format, absl::MakeSpan(args)));\n  EXPECT_EQ(\"-3\", FormatPack(format2, absl::MakeSpan(args)));\n}\n\ntemplate <typename T>\nclass TypedFormatConvertTest : public FormatConvertTest { };\n\nTYPED_TEST_SUITE_P(TypedFormatConvertTest);\n\nstd::vector<std::string> AllFlagCombinations() {\n  const char kFlags[] = {'-', '#', '0', '+', ' '};\n  std::vector<std::string> result;\n  for (size_t fsi = 0; fsi < (1ull << ArraySize(kFlags)); ++fsi) {\n    std::string flag_set;\n    for (size_t fi = 0; fi < ArraySize(kFlags); ++fi)\n      if (fsi & (1ull << fi))\n        flag_set += kFlags[fi];\n    result.push_back(flag_set);\n  }\n  return result;\n}\n\nTYPED_TEST_P(TypedFormatConvertTest, AllIntsWithFlags) {\n  typedef TypeParam T;\n  typedef typename std::make_unsigned<T>::type UnsignedT;\n  using remove_volatile_t = typename std::remove_volatile<T>::type;\n  const T kMin = std::numeric_limits<remove_volatile_t>::min();\n  const T kMax = std::numeric_limits<remove_volatile_t>::max();\n  const T kVals[] = {\n      remove_volatile_t(1),\n      remove_volatile_t(2),\n      remove_volatile_t(3),\n      remove_volatile_t(123),\n      remove_volatile_t(-1),\n      remove_volatile_t(-2),\n      remove_volatile_t(-3),\n      remove_volatile_t(-123),\n      remove_volatile_t(0),\n      kMax - remove_volatile_t(1),\n      kMax,\n      kMin + remove_volatile_t(1),\n      kMin,\n  };\n  const char kConvChars[] = {'d', 'i', 'u', 'o', 'x', 'X'};\n  const std::string kWid[] = {\"\", \"4\", \"10\"};\n  const std::string kPrec[] = {\"\", \".\", \".0\", \".4\", \".10\"};\n\n  const std::vector<std::string> flag_sets = AllFlagCombinations();\n\n  for (size_t vi = 0; vi < ArraySize(kVals); ++vi) {\n    const T val = kVals[vi];\n    SCOPED_TRACE(Esc(val));\n    const FormatArgImpl args[] = {FormatArgImpl(val)};\n    for (size_t ci = 0; ci < ArraySize(kConvChars); ++ci) {\n      const char conv_char = kConvChars[ci];\n      for (size_t fsi = 0; fsi < flag_sets.size(); ++fsi) {\n        const std::string &flag_set = flag_sets[fsi];\n        for (size_t wi = 0; wi < ArraySize(kWid); ++wi) {\n          const std::string &wid = kWid[wi];\n          for (size_t pi = 0; pi < ArraySize(kPrec); ++pi) {\n            const std::string &prec = kPrec[pi];\n\n            const bool is_signed_conv = (conv_char == 'd' || conv_char == 'i');\n            const bool is_unsigned_to_signed =\n                !std::is_signed<T>::value && is_signed_conv;\n            // Don't consider sign-related flags '+' and ' ' when doing\n            // unsigned to signed conversions.\n            if (is_unsigned_to_signed &&\n                flag_set.find_first_of(\"+ \") != std::string::npos) {\n              continue;\n            }\n\n            std::string new_fmt(\"%\");\n            new_fmt += flag_set;\n            new_fmt += wid;\n            new_fmt += prec;\n            // old and new always agree up to here.\n            std::string old_fmt = new_fmt;\n            new_fmt += conv_char;\n            std::string old_result;\n            if (is_unsigned_to_signed) {\n              // don't expect agreement on unsigned formatted as signed,\n              // as printf can't do that conversion properly. For those\n              // cases, we do expect agreement with printf with a \"%u\"\n              // and the unsigned equivalent of 'val'.\n              UnsignedT uval =\n                  static_cast<std::remove_volatile_t<UnsignedT>>(val);\n              old_fmt += LengthModFor<\n                  MatchingIntegralType<std::remove_cv_t<decltype(uval)>>>();\n              old_fmt += \"u\";\n              old_result = StrPrint(old_fmt.c_str(), uval);\n            } else {\n              old_fmt += LengthModFor<\n                  MatchingIntegralType<std::remove_cv_t<decltype(val)>>>();\n              old_fmt += conv_char;\n              old_result = StrPrint(old_fmt.c_str(), val);\n            }\n\n            SCOPED_TRACE(std::string() + \" old_fmt: \\\"\" + old_fmt +\n                         \"\\\"'\"\n                         \" new_fmt: \\\"\" +\n                         new_fmt + \"\\\"\");\n            UntypedFormatSpecImpl format(new_fmt);\n            EXPECT_EQ(old_result, FormatPack(format, absl::MakeSpan(args)));\n          }\n        }\n      }\n    }\n  }\n}\n\ntemplate <typename T>\nstd::optional<std::string> StrPrintChar(T c) {\n  return StrPrint(\"%c\", static_cast<int>(c));\n}\ntemplate <>\nstd::optional<std::string> StrPrintChar(wchar_t c) {\n  // musl libc has a bug where (\"%lc\", 0) writes no characters, and Android\n  // doesn't support forcing UTF-8 via setlocale(). Hardcode the expected\n  // answers for ASCII inputs to maximize test coverage on these platforms.\n  if (static_cast<std::make_unsigned_t<wchar_t>>(c) < 0x80) {\n    return std::string(1, static_cast<char>(c));\n  }\n\n  // Force a UTF-8 locale to match the expected `StrFormat()` behavior.\n  // It's important to copy the string returned by `old_locale` here, because\n  // its contents are not guaranteed to be valid after the next `setlocale()`\n  // call.\n  std::string old_locale = setlocale(LC_CTYPE, nullptr);\n  if (!setlocale(LC_CTYPE, \"en_US.UTF-8\")) {\n    return std::nullopt;\n  }\n  const std::string output = StrPrint(\"%lc\", static_cast<wint_t>(c));\n  setlocale(LC_CTYPE, old_locale.c_str());\n  return output;\n}\n\ntemplate <typename T>\ntypename std::remove_volatile<T>::type GetMaxForConversion() {\n  return static_cast<typename std::remove_volatile<T>::type>(\n      std::numeric_limits<int>::max());\n}\n\ntemplate <>\nwchar_t GetMaxForConversion<wchar_t>() {\n  // Don't return values that aren't legal Unicode. For wchar_t conversions in a\n  // UTF-8 locale, conversion behavior for such values is unspecified, and we\n  // don't care about matching it.\n  return (sizeof(wchar_t) * CHAR_BIT <= 16) ? wchar_t{0xffff}\n                                            : static_cast<wchar_t>(0x10ffff);\n}\n\nTYPED_TEST_P(TypedFormatConvertTest, Char) {\n  // Pass a bunch of values of type TypeParam to both FormatPack and libc's\n  // vsnprintf(\"%c\", ...) (wrapped in StrPrint) to make sure we get the same\n  // value.\n  typedef TypeParam T;\n  using remove_volatile_t = typename std::remove_volatile<T>::type;\n  std::vector<remove_volatile_t> vals = {\n      remove_volatile_t(1),  remove_volatile_t(2),  remove_volatile_t(10),   //\n      remove_volatile_t(-1), remove_volatile_t(-2), remove_volatile_t(-10),  //\n      remove_volatile_t(0),\n  };\n\n  // We'd like to test values near std::numeric_limits::min() and\n  // std::numeric_limits::max(), too, but vsnprintf(\"%c\", ...) can't handle\n  // anything larger than an int. Add in the most extreme values we can without\n  // exceeding that range.\n  // Special case: Formatting a wchar_t should behave like vsnprintf(\"%lc\").\n  // Technically vsnprintf can accept a wint_t in this case, but since we must\n  // pass a wchar_t to FormatPack, the largest type we can use here is wchar_t.\n  using ArgType =\n      std::conditional_t<std::is_same<T, wchar_t>::value, wchar_t, int>;\n  static const T kMin =\n      static_cast<remove_volatile_t>(std::numeric_limits<ArgType>::min());\n  static const T kMax = GetMaxForConversion<T>();\n  vals.insert(vals.end(), {static_cast<remove_volatile_t>(kMin + 1), kMin,\n                           static_cast<remove_volatile_t>(kMax - 1), kMax});\n\n  static const auto kMaxWCharT =\n      static_cast<remove_volatile_t>(GetMaxForConversion<wchar_t>());\n  for (const T c : vals) {\n    SCOPED_TRACE(Esc(c));\n    const FormatArgImpl args[] = {FormatArgImpl(c)};\n    UntypedFormatSpecImpl format(\"%c\");\n    std::optional<std::string> result = StrPrintChar(c);\n    if (result.has_value()) {\n      EXPECT_EQ(result.value(), FormatPack(format, absl::MakeSpan(args)));\n    }\n\n    // Also test that if the format specifier is \"%lc\", the argument is treated\n    // as if it's a `wchar_t`.\n    const T wc =\n        std::max(remove_volatile_t{0},\n                 std::min(static_cast<remove_volatile_t>(c), kMaxWCharT));\n    SCOPED_TRACE(Esc(wc));\n    const FormatArgImpl wide_args[] = {FormatArgImpl(wc)};\n    UntypedFormatSpecImpl wide_format(\"%lc\");\n    result = StrPrintChar(static_cast<wchar_t>(wc));\n    if (result.has_value()) {\n      EXPECT_EQ(result.value(),\n                FormatPack(wide_format, absl::MakeSpan(wide_args)));\n    }\n  }\n}\n\nREGISTER_TYPED_TEST_SUITE_P(TypedFormatConvertTest, AllIntsWithFlags, Char);\n\ntypedef ::testing::Types<int, unsigned, volatile int, short,   // NOLINT\n                         unsigned short, long, unsigned long,  // NOLINT\n                         long long, unsigned long long,        // NOLINT\n                         signed char, unsigned char, char, wchar_t>\n    AllIntTypes;\nINSTANTIATE_TYPED_TEST_SUITE_P(TypedFormatConvertTestWithAllIntTypes,\n                               TypedFormatConvertTest, AllIntTypes);\nTEST_F(FormatConvertTest, VectorBool) {\n  // Make sure vector<bool>'s values behave as bools.\n  std::vector<bool> v = {true, false};\n  const std::vector<bool> cv = {true, false};\n  EXPECT_EQ(\"1,0,1,0\",\n            FormatPack(UntypedFormatSpecImpl(\"%d,%d,%d,%d\"),\n                       absl::Span<const FormatArgImpl>(\n                           {FormatArgImpl(v[0]), FormatArgImpl(v[1]),\n                            FormatArgImpl(cv[0]), FormatArgImpl(cv[1])})));\n}\n\nTEST_F(FormatConvertTest, UnicodeWideString) {\n  // StrFormat() should be able to convert wide strings containing Unicode\n  // characters (to UTF-8).\n  const FormatArgImpl args[] = {FormatArgImpl(L\"\\u47e3 \\U00011112\")};\n  // `u8\"\"` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn)\n  // without it. However, the resulting character type differs between pre-C++20\n  // (`char`) and C++20 (`char8_t`). So deduce the right character type for all\n  // C++ versions, init it with UTF-8, then `memcpy()` to get the result as a\n  // `char*`.\n  using ConstChar8T = std::remove_reference_t<decltype(*u8\"a\")>;\n  ConstChar8T kOutputUtf8[] = u8\"\\u47e3 \\U00011112\";\n  char output[sizeof kOutputUtf8];\n  std::memcpy(output, kOutputUtf8, sizeof kOutputUtf8);\n  EXPECT_EQ(output,\n            FormatPack(UntypedFormatSpecImpl(\"%ls\"), absl::MakeSpan(args)));\n}\n\nTEST_F(FormatConvertTest, Int128) {\n  absl::int128 positive = static_cast<absl::int128>(0x1234567890abcdef) * 1979;\n  absl::int128 negative = -positive;\n  absl::int128 max = absl::Int128Max(), min = absl::Int128Min();\n  const FormatArgImpl args[] = {FormatArgImpl(positive),\n                                FormatArgImpl(negative), FormatArgImpl(max),\n                                FormatArgImpl(min)};\n\n  struct Case {\n    const char* format;\n    const char* expected;\n  } cases[] = {\n      {\"%1$d\", \"2595989796776606496405\"},\n      {\"%1$30d\", \"        2595989796776606496405\"},\n      {\"%1$-30d\", \"2595989796776606496405        \"},\n      {\"%1$u\", \"2595989796776606496405\"},\n      {\"%1$x\", \"8cba9876066020f695\"},\n      {\"%2$d\", \"-2595989796776606496405\"},\n      {\"%2$30d\", \"       -2595989796776606496405\"},\n      {\"%2$-30d\", \"-2595989796776606496405       \"},\n      {\"%2$u\", \"340282366920938460867384810655161715051\"},\n      {\"%2$x\", \"ffffffffffffff73456789f99fdf096b\"},\n      {\"%3$d\", \"170141183460469231731687303715884105727\"},\n      {\"%3$u\", \"170141183460469231731687303715884105727\"},\n      {\"%3$x\", \"7fffffffffffffffffffffffffffffff\"},\n      {\"%4$d\", \"-170141183460469231731687303715884105728\"},\n      {\"%4$x\", \"80000000000000000000000000000000\"},\n  };\n\n  for (auto c : cases) {\n    UntypedFormatSpecImpl format(c.format);\n    EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args)));\n  }\n}\n\nTEST_F(FormatConvertTest, Uint128) {\n  absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;\n  absl::uint128 max = absl::Uint128Max();\n  const FormatArgImpl args[] = {FormatArgImpl(v), FormatArgImpl(max)};\n\n  struct Case {\n    const char* format;\n    const char* expected;\n  } cases[] = {\n      {\"%1$d\", \"2595989796776606496405\"},\n      {\"%1$30d\", \"        2595989796776606496405\"},\n      {\"%1$-30d\", \"2595989796776606496405        \"},\n      {\"%1$u\", \"2595989796776606496405\"},\n      {\"%1$x\", \"8cba9876066020f695\"},\n      {\"%2$d\", \"340282366920938463463374607431768211455\"},\n      {\"%2$u\", \"340282366920938463463374607431768211455\"},\n      {\"%2$x\", \"ffffffffffffffffffffffffffffffff\"},\n  };\n\n  for (auto c : cases) {\n    UntypedFormatSpecImpl format(c.format);\n    EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args)));\n  }\n}\n\ntemplate <typename Floating>\nvoid TestWithMultipleFormatsHelper(Floating tested_float) {\n  const NativePrintfTraits &native_traits = VerifyNativeImplementation();\n  // Reserve the space to ensure we don't allocate memory in the output itself.\n  std::string str_format_result;\n  str_format_result.reserve(1 << 20);\n  std::string string_printf_result;\n  string_printf_result.reserve(1 << 20);\n\n  const char *const kFormats[] = {\n      \"%\",  \"%.3\", \"%8.5\", \"%500\",   \"%.5000\", \"%.60\", \"%.30\",   \"%03\",\n      \"%+\", \"% \",  \"%-10\", \"%#15.3\", \"%#.0\",   \"%.0\",  \"%1$*2$\", \"%1$.*2$\"};\n\n  for (const char *fmt : kFormats) {\n    for (char f : {'f', 'F',  //\n                   'g', 'G',  //\n                   'a', 'A',  //\n                   'e', 'E'}) {\n      std::string fmt_str = std::string(fmt) + f;\n\n      if (fmt == absl::string_view(\"%.5000\") && !IsNativeFloatConversion(f)) {\n        // This particular test takes way too long with snprintf.\n        // Disable for the case we are not implementing natively.\n        continue;\n      }\n\n      if (IsNativeHexFloatConversion(f) &&\n          !native_traits.hex_float_has_glibc_rounding) {\n        continue;\n      }\n\n      if (!native_traits.hex_float_prefers_denormal_repr &&\n          IsNativeHexFloatConversion(f) &&\n          std::fpclassify(tested_float) == FP_SUBNORMAL) {\n        continue;\n      }\n        int i = -10;\n        FormatArgImpl args[2] = {FormatArgImpl(tested_float), FormatArgImpl(i)};\n        UntypedFormatSpecImpl format(fmt_str);\n\n        string_printf_result.clear();\n        StrAppend(&string_printf_result, fmt_str.c_str(), tested_float, i);\n        str_format_result.clear();\n\n        {\n          AppendPack(&str_format_result, format, absl::MakeSpan(args));\n        }\n\n        // For values that we know won't match the standard library\n        // implementation we skip verification, but still run the algorithm to\n        // catch asserts/sanitizer bugs.\n#ifdef _MSC_VER\n        // MSVC has a different rounding policy than us so we can't test our\n        // implementation against the native one there.\n        continue;\n#elif defined(__APPLE__)\n        // Apple formats NaN differently (+nan) vs. (nan)\n        if (std::isnan(tested_float)) continue;\n#endif\n        // We use ASSERT_EQ here because failures are usually correlated and a\n        // bug would print way too many failed expectations causing the test\n        // to time out.\n        ASSERT_EQ(string_printf_result, str_format_result)\n            << fmt_str << \" \" << StrPrint(\"%.18g\", tested_float) << \" \"\n            << StrPrint(\"%a\", tested_float) << \" \"\n            << StrPrint(\"%.50f\", tested_float);\n    }\n  }\n}\n\nTEST_F(FormatConvertTest, Float) {\n  std::vector<float> floats = {0.0f,\n                               -0.0f,\n                               .9999999f,\n                               9999999.f,\n                               std::numeric_limits<float>::max(),\n                               -std::numeric_limits<float>::max(),\n                               std::numeric_limits<float>::min(),\n                               -std::numeric_limits<float>::min(),\n                               std::numeric_limits<float>::lowest(),\n                               -std::numeric_limits<float>::lowest(),\n                               std::numeric_limits<float>::epsilon(),\n                               std::numeric_limits<float>::epsilon() + 1.0f,\n                               std::numeric_limits<float>::infinity(),\n                               -std::numeric_limits<float>::infinity(),\n                               std::nanf(\"\")};\n\n  // Some regression tests.\n  floats.push_back(0.999999989f);\n\n  if (std::numeric_limits<float>::has_denorm != std::denorm_absent) {\n    floats.push_back(std::numeric_limits<float>::denorm_min());\n    floats.push_back(-std::numeric_limits<float>::denorm_min());\n  }\n\n  for (float base :\n       {1.f, 12.f, 123.f, 1234.f, 12345.f, 123456.f, 1234567.f, 12345678.f,\n        123456789.f, 1234567890.f, 12345678901.f, 12345678.f, 12345678.f}) {\n    for (int exp = -123; exp <= 123; ++exp) {\n      for (int sign : {1, -1}) {\n        floats.push_back(sign * std::ldexp(base, exp));\n      }\n    }\n  }\n\n  for (int exp = -300; exp <= 300; ++exp) {\n    const float all_ones_mantissa = 0xffffff;\n    floats.push_back(std::ldexp(all_ones_mantissa, exp));\n  }\n\n  // Remove duplicates to speed up the logic below.\n  std::sort(floats.begin(), floats.end(), [](const float a, const float b) {\n    if (std::isnan(a)) return false;\n    if (std::isnan(b)) return true;\n    return a < b;\n  });\n  floats.erase(std::unique(floats.begin(), floats.end()), floats.end());\n\n  for (float f : floats) {\n    TestWithMultipleFormatsHelper(f);\n  }\n}\n\nTEST_F(FormatConvertTest, Double) {\n  std::vector<double> doubles = {0.0,\n                                 -0.0,\n                                 .99999999999999,\n                                 99999999999999.,\n                                 std::numeric_limits<double>::max(),\n                                 -std::numeric_limits<double>::max(),\n                                 std::numeric_limits<double>::min(),\n                                 -std::numeric_limits<double>::min(),\n                                 std::numeric_limits<double>::lowest(),\n                                 -std::numeric_limits<double>::lowest(),\n                                 std::numeric_limits<double>::epsilon(),\n                                 std::numeric_limits<double>::epsilon() + 1,\n                                 std::numeric_limits<double>::infinity(),\n                                 -std::numeric_limits<double>::infinity(),\n                                 std::nan(\"\")};\n\n  // Some regression tests.\n  doubles.push_back(0.99999999999999989);\n\n  if (std::numeric_limits<double>::has_denorm != std::denorm_absent) {\n    doubles.push_back(std::numeric_limits<double>::denorm_min());\n    doubles.push_back(-std::numeric_limits<double>::denorm_min());\n  }\n\n  for (double base :\n       {1., 12., 123., 1234., 12345., 123456., 1234567., 12345678., 123456789.,\n        1234567890., 12345678901., 123456789012., 1234567890123.}) {\n    for (int exp = -123; exp <= 123; ++exp) {\n      for (int sign : {1, -1}) {\n        doubles.push_back(sign * std::ldexp(base, exp));\n      }\n    }\n  }\n\n  for (int exp = -300; exp <= 300; ++exp) {\n    const double all_ones_mantissa = 0x1fffffffffffff;\n    doubles.push_back(std::ldexp(all_ones_mantissa, exp));\n  }\n\n  // Remove duplicates to speed up the logic below.\n  std::sort(doubles.begin(), doubles.end(), [](const double a, const double b) {\n    if (std::isnan(a)) return false;\n    if (std::isnan(b)) return true;\n    return a < b;\n  });\n  doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end());\n\n  for (double d : doubles) {\n    TestWithMultipleFormatsHelper(d);\n  }\n}\n\nTEST_F(FormatConvertTest, DoubleRound) {\n  std::string s;\n  const auto format = [&](const char *fmt, double d) -> std::string & {\n    s.clear();\n    FormatArgImpl args[1] = {FormatArgImpl(d)};\n    AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));\n#if !defined(_MSC_VER)\n    // MSVC has a different rounding policy than us so we can't test our\n    // implementation against the native one there.\n    EXPECT_EQ(StrPrint(fmt, d), s);\n#endif  // _MSC_VER\n\n    return s;\n  };\n  // All of these values have to be exactly represented.\n  // Otherwise we might not be testing what we think we are testing.\n\n  // These values can fit in a 64bit \"fast\" representation.\n  const double exact_value = 0.00000000000005684341886080801486968994140625;\n  assert(exact_value == std::pow(2, -44));\n  // Round up at a 5xx.\n  EXPECT_EQ(format(\"%.13f\", exact_value), \"0.0000000000001\");\n  // Round up at a >5\n  EXPECT_EQ(format(\"%.14f\", exact_value), \"0.00000000000006\");\n  // Round down at a <5\n  EXPECT_EQ(format(\"%.16f\", exact_value), \"0.0000000000000568\");\n  // Nine handling\n  EXPECT_EQ(format(\"%.35f\", exact_value),\n            \"0.00000000000005684341886080801486969\");\n  EXPECT_EQ(format(\"%.36f\", exact_value),\n            \"0.000000000000056843418860808014869690\");\n  // Round down the last nine.\n  EXPECT_EQ(format(\"%.37f\", exact_value),\n            \"0.0000000000000568434188608080148696899\");\n  EXPECT_EQ(format(\"%.10f\", 0.000003814697265625), \"0.0000038147\");\n  // Round up the last nine\n  EXPECT_EQ(format(\"%.11f\", 0.000003814697265625), \"0.00000381470\");\n  EXPECT_EQ(format(\"%.12f\", 0.000003814697265625), \"0.000003814697\");\n\n  // Round to even (down)\n  EXPECT_EQ(format(\"%.43f\", exact_value),\n            \"0.0000000000000568434188608080148696899414062\");\n  // Exact\n  EXPECT_EQ(format(\"%.44f\", exact_value),\n            \"0.00000000000005684341886080801486968994140625\");\n  // Round to even (up), let make the last digits 75 instead of 25\n  EXPECT_EQ(format(\"%.43f\", exact_value + std::pow(2, -43)),\n            \"0.0000000000001705302565824240446090698242188\");\n  // Exact, just to check.\n  EXPECT_EQ(format(\"%.44f\", exact_value + std::pow(2, -43)),\n            \"0.00000000000017053025658242404460906982421875\");\n\n  // This value has to be small enough that it won't fit in the uint128\n  // representation for printing.\n  const double small_exact_value =\n      0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625;  // NOLINT\n  assert(small_exact_value == std::pow(2, -120));\n  // Round up at a 5xx.\n  EXPECT_EQ(format(\"%.37f\", small_exact_value),\n            \"0.0000000000000000000000000000000000008\");\n  // Round down at a <5\n  EXPECT_EQ(format(\"%.38f\", small_exact_value),\n            \"0.00000000000000000000000000000000000075\");\n  // Round up at a >5\n  EXPECT_EQ(format(\"%.41f\", small_exact_value),\n            \"0.00000000000000000000000000000000000075232\");\n  // Nine handling\n  EXPECT_EQ(format(\"%.55f\", small_exact_value),\n            \"0.0000000000000000000000000000000000007523163845262640051\");\n  EXPECT_EQ(format(\"%.56f\", small_exact_value),\n            \"0.00000000000000000000000000000000000075231638452626400510\");\n  EXPECT_EQ(format(\"%.57f\", small_exact_value),\n            \"0.000000000000000000000000000000000000752316384526264005100\");\n  EXPECT_EQ(format(\"%.58f\", small_exact_value),\n            \"0.0000000000000000000000000000000000007523163845262640051000\");\n  // Round down the last nine\n  EXPECT_EQ(format(\"%.59f\", small_exact_value),\n            \"0.00000000000000000000000000000000000075231638452626400509999\");\n  // Round up the last nine\n  EXPECT_EQ(format(\"%.79f\", small_exact_value),\n            \"0.000000000000000000000000000000000000\"\n            \"7523163845262640050999913838222372338039460\");\n\n  // Round to even (down)\n  EXPECT_EQ(format(\"%.119f\", small_exact_value),\n            \"0.000000000000000000000000000000000000\"\n            \"75231638452626400509999138382223723380\"\n            \"394595633413601376560109201818704605102539062\");\n  // Exact\n  EXPECT_EQ(format(\"%.120f\", small_exact_value),\n            \"0.000000000000000000000000000000000000\"\n            \"75231638452626400509999138382223723380\"\n            \"3945956334136013765601092018187046051025390625\");\n  // Round to even (up), let make the last digits 75 instead of 25\n  EXPECT_EQ(format(\"%.119f\", small_exact_value + std::pow(2, -119)),\n            \"0.000000000000000000000000000000000002\"\n            \"25694915357879201529997415146671170141\"\n            \"183786900240804129680327605456113815307617188\");\n  // Exact, just to check.\n  EXPECT_EQ(format(\"%.120f\", small_exact_value + std::pow(2, -119)),\n            \"0.000000000000000000000000000000000002\"\n            \"25694915357879201529997415146671170141\"\n            \"1837869002408041296803276054561138153076171875\");\n\n  // Scientific exponent cases\n  // Round to even with all zeros after round digit\n  EXPECT_EQ(format(\"%0.13e\", 1671075773261250), \"1.6710757732612e+15\");\n\n  // Rounding where precision is in first digit run\n  EXPECT_EQ(format(\"%0.1e\", -1.93437090148818698e-297), \"-1.9e-297\");\n  EXPECT_EQ(format(\"%0.1e\", -9.92255780642280927e-298), \"-9.9e-298\");\n\n  // Rounding large negative exponent first digit\n  EXPECT_EQ(format(\"%0.1e\", -8.956e-294), \"-9.0e-294\");\n}\n\nTEST_F(FormatConvertTest, DoubleRoundA) {\n  const NativePrintfTraits &native_traits = VerifyNativeImplementation();\n  std::string s;\n  const auto format = [&](const char *fmt, double d) -> std::string & {\n    s.clear();\n    FormatArgImpl args[1] = {FormatArgImpl(d)};\n    AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));\n    if (native_traits.hex_float_has_glibc_rounding) {\n      EXPECT_EQ(StrPrint(fmt, d), s);\n    }\n    return s;\n  };\n\n  // 0x1.00018000p+100\n  const double on_boundary_odd = 1267679614447900152596896153600.0;\n  EXPECT_EQ(format(\"%.0a\", on_boundary_odd), \"0x1p+100\");\n  EXPECT_EQ(format(\"%.1a\", on_boundary_odd), \"0x1.0p+100\");\n  EXPECT_EQ(format(\"%.2a\", on_boundary_odd), \"0x1.00p+100\");\n  EXPECT_EQ(format(\"%.3a\", on_boundary_odd), \"0x1.000p+100\");\n  EXPECT_EQ(format(\"%.4a\", on_boundary_odd), \"0x1.0002p+100\");  // round\n  EXPECT_EQ(format(\"%.5a\", on_boundary_odd), \"0x1.00018p+100\");\n  EXPECT_EQ(format(\"%.6a\", on_boundary_odd), \"0x1.000180p+100\");\n\n  // 0x1.00028000p-2\n  const double on_boundary_even = 0.250009536743164062500;\n  EXPECT_EQ(format(\"%.0a\", on_boundary_even), \"0x1p-2\");\n  EXPECT_EQ(format(\"%.1a\", on_boundary_even), \"0x1.0p-2\");\n  EXPECT_EQ(format(\"%.2a\", on_boundary_even), \"0x1.00p-2\");\n  EXPECT_EQ(format(\"%.3a\", on_boundary_even), \"0x1.000p-2\");\n  EXPECT_EQ(format(\"%.4a\", on_boundary_even), \"0x1.0002p-2\");  // no round\n  EXPECT_EQ(format(\"%.5a\", on_boundary_even), \"0x1.00028p-2\");\n  EXPECT_EQ(format(\"%.6a\", on_boundary_even), \"0x1.000280p-2\");\n\n  // 0x1.00018001p+1\n  const double slightly_over = 2.00004577683284878730773925781250;\n  EXPECT_EQ(format(\"%.0a\", slightly_over), \"0x1p+1\");\n  EXPECT_EQ(format(\"%.1a\", slightly_over), \"0x1.0p+1\");\n  EXPECT_EQ(format(\"%.2a\", slightly_over), \"0x1.00p+1\");\n  EXPECT_EQ(format(\"%.3a\", slightly_over), \"0x1.000p+1\");\n  EXPECT_EQ(format(\"%.4a\", slightly_over), \"0x1.0002p+1\");\n  EXPECT_EQ(format(\"%.5a\", slightly_over), \"0x1.00018p+1\");\n  EXPECT_EQ(format(\"%.6a\", slightly_over), \"0x1.000180p+1\");\n\n  // 0x1.00017fffp+0\n  const double slightly_under = 1.000022887950763106346130371093750;\n  EXPECT_EQ(format(\"%.0a\", slightly_under), \"0x1p+0\");\n  EXPECT_EQ(format(\"%.1a\", slightly_under), \"0x1.0p+0\");\n  EXPECT_EQ(format(\"%.2a\", slightly_under), \"0x1.00p+0\");\n  EXPECT_EQ(format(\"%.3a\", slightly_under), \"0x1.000p+0\");\n  EXPECT_EQ(format(\"%.4a\", slightly_under), \"0x1.0001p+0\");\n  EXPECT_EQ(format(\"%.5a\", slightly_under), \"0x1.00018p+0\");\n  EXPECT_EQ(format(\"%.6a\", slightly_under), \"0x1.000180p+0\");\n  EXPECT_EQ(format(\"%.7a\", slightly_under), \"0x1.0001800p+0\");\n\n  // 0x1.1b3829ac28058p+3\n  const double hex_value = 8.85060580848964661981881363317370414733886718750;\n  EXPECT_EQ(format(\"%.0a\", hex_value), \"0x1p+3\");\n  EXPECT_EQ(format(\"%.1a\", hex_value), \"0x1.2p+3\");\n  EXPECT_EQ(format(\"%.2a\", hex_value), \"0x1.1bp+3\");\n  EXPECT_EQ(format(\"%.3a\", hex_value), \"0x1.1b4p+3\");\n  EXPECT_EQ(format(\"%.4a\", hex_value), \"0x1.1b38p+3\");\n  EXPECT_EQ(format(\"%.5a\", hex_value), \"0x1.1b383p+3\");\n  EXPECT_EQ(format(\"%.6a\", hex_value), \"0x1.1b382ap+3\");\n  EXPECT_EQ(format(\"%.7a\", hex_value), \"0x1.1b3829bp+3\");\n  EXPECT_EQ(format(\"%.8a\", hex_value), \"0x1.1b3829acp+3\");\n  EXPECT_EQ(format(\"%.9a\", hex_value), \"0x1.1b3829ac3p+3\");\n  EXPECT_EQ(format(\"%.10a\", hex_value), \"0x1.1b3829ac28p+3\");\n  EXPECT_EQ(format(\"%.11a\", hex_value), \"0x1.1b3829ac280p+3\");\n  EXPECT_EQ(format(\"%.12a\", hex_value), \"0x1.1b3829ac2806p+3\");\n  EXPECT_EQ(format(\"%.13a\", hex_value), \"0x1.1b3829ac28058p+3\");\n  EXPECT_EQ(format(\"%.14a\", hex_value), \"0x1.1b3829ac280580p+3\");\n  EXPECT_EQ(format(\"%.15a\", hex_value), \"0x1.1b3829ac2805800p+3\");\n  EXPECT_EQ(format(\"%.16a\", hex_value), \"0x1.1b3829ac28058000p+3\");\n  EXPECT_EQ(format(\"%.17a\", hex_value), \"0x1.1b3829ac280580000p+3\");\n  EXPECT_EQ(format(\"%.18a\", hex_value), \"0x1.1b3829ac2805800000p+3\");\n  EXPECT_EQ(format(\"%.19a\", hex_value), \"0x1.1b3829ac28058000000p+3\");\n  EXPECT_EQ(format(\"%.20a\", hex_value), \"0x1.1b3829ac280580000000p+3\");\n  EXPECT_EQ(format(\"%.21a\", hex_value), \"0x1.1b3829ac2805800000000p+3\");\n\n  // 0x1.0818283848586p+3\n  const double hex_value2 = 8.2529488658208371987257123691961169242858886718750;\n  EXPECT_EQ(format(\"%.0a\", hex_value2), \"0x1p+3\");\n  EXPECT_EQ(format(\"%.1a\", hex_value2), \"0x1.1p+3\");\n  EXPECT_EQ(format(\"%.2a\", hex_value2), \"0x1.08p+3\");\n  EXPECT_EQ(format(\"%.3a\", hex_value2), \"0x1.082p+3\");\n  EXPECT_EQ(format(\"%.4a\", hex_value2), \"0x1.0818p+3\");\n  EXPECT_EQ(format(\"%.5a\", hex_value2), \"0x1.08183p+3\");\n  EXPECT_EQ(format(\"%.6a\", hex_value2), \"0x1.081828p+3\");\n  EXPECT_EQ(format(\"%.7a\", hex_value2), \"0x1.0818284p+3\");\n  EXPECT_EQ(format(\"%.8a\", hex_value2), \"0x1.08182838p+3\");\n  EXPECT_EQ(format(\"%.9a\", hex_value2), \"0x1.081828385p+3\");\n  EXPECT_EQ(format(\"%.10a\", hex_value2), \"0x1.0818283848p+3\");\n  EXPECT_EQ(format(\"%.11a\", hex_value2), \"0x1.08182838486p+3\");\n  EXPECT_EQ(format(\"%.12a\", hex_value2), \"0x1.081828384858p+3\");\n  EXPECT_EQ(format(\"%.13a\", hex_value2), \"0x1.0818283848586p+3\");\n  EXPECT_EQ(format(\"%.14a\", hex_value2), \"0x1.08182838485860p+3\");\n  EXPECT_EQ(format(\"%.15a\", hex_value2), \"0x1.081828384858600p+3\");\n  EXPECT_EQ(format(\"%.16a\", hex_value2), \"0x1.0818283848586000p+3\");\n  EXPECT_EQ(format(\"%.17a\", hex_value2), \"0x1.08182838485860000p+3\");\n  EXPECT_EQ(format(\"%.18a\", hex_value2), \"0x1.081828384858600000p+3\");\n  EXPECT_EQ(format(\"%.19a\", hex_value2), \"0x1.0818283848586000000p+3\");\n  EXPECT_EQ(format(\"%.20a\", hex_value2), \"0x1.08182838485860000000p+3\");\n  EXPECT_EQ(format(\"%.21a\", hex_value2), \"0x1.081828384858600000000p+3\");\n}\n\nTEST_F(FormatConvertTest, LongDoubleRoundA) {\n  if (std::numeric_limits<long double>::digits % 4 != 0) {\n    // This test doesn't really make sense to run on platforms where a long\n    // double has a different mantissa size (mod 4) than Prod, since then the\n    // leading digit will be formatted differently.\n    return;\n  }\n  const NativePrintfTraits &native_traits = VerifyNativeImplementation();\n  std::string s;\n  const auto format = [&](const char *fmt, long double d) -> std::string & {\n    s.clear();\n    FormatArgImpl args[1] = {FormatArgImpl(d)};\n    AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));\n    if (native_traits.hex_float_has_glibc_rounding &&\n        native_traits.hex_float_optimizes_leading_digit_bit_count) {\n      EXPECT_EQ(StrPrint(fmt, d), s);\n    }\n    return s;\n  };\n\n  // 0x8.8p+4\n  const long double on_boundary_even = 136.0;\n  EXPECT_EQ(format(\"%.0La\", on_boundary_even), \"0x8p+4\");\n  EXPECT_EQ(format(\"%.1La\", on_boundary_even), \"0x8.8p+4\");\n  EXPECT_EQ(format(\"%.2La\", on_boundary_even), \"0x8.80p+4\");\n  EXPECT_EQ(format(\"%.3La\", on_boundary_even), \"0x8.800p+4\");\n  EXPECT_EQ(format(\"%.4La\", on_boundary_even), \"0x8.8000p+4\");\n  EXPECT_EQ(format(\"%.5La\", on_boundary_even), \"0x8.80000p+4\");\n  EXPECT_EQ(format(\"%.6La\", on_boundary_even), \"0x8.800000p+4\");\n\n  // 0x9.8p+4\n  const long double on_boundary_odd = 152.0;\n  EXPECT_EQ(format(\"%.0La\", on_boundary_odd), \"0xap+4\");\n  EXPECT_EQ(format(\"%.1La\", on_boundary_odd), \"0x9.8p+4\");\n  EXPECT_EQ(format(\"%.2La\", on_boundary_odd), \"0x9.80p+4\");\n  EXPECT_EQ(format(\"%.3La\", on_boundary_odd), \"0x9.800p+4\");\n  EXPECT_EQ(format(\"%.4La\", on_boundary_odd), \"0x9.8000p+4\");\n  EXPECT_EQ(format(\"%.5La\", on_boundary_odd), \"0x9.80000p+4\");\n  EXPECT_EQ(format(\"%.6La\", on_boundary_odd), \"0x9.800000p+4\");\n\n  // 0x8.80001p+24\n  const long double slightly_over = 142606352.0;\n  EXPECT_EQ(format(\"%.0La\", slightly_over), \"0x9p+24\");\n  EXPECT_EQ(format(\"%.1La\", slightly_over), \"0x8.8p+24\");\n  EXPECT_EQ(format(\"%.2La\", slightly_over), \"0x8.80p+24\");\n  EXPECT_EQ(format(\"%.3La\", slightly_over), \"0x8.800p+24\");\n  EXPECT_EQ(format(\"%.4La\", slightly_over), \"0x8.8000p+24\");\n  EXPECT_EQ(format(\"%.5La\", slightly_over), \"0x8.80001p+24\");\n  EXPECT_EQ(format(\"%.6La\", slightly_over), \"0x8.800010p+24\");\n\n  // 0x8.7ffffp+24\n  const long double slightly_under = 142606320.0;\n  EXPECT_EQ(format(\"%.0La\", slightly_under), \"0x8p+24\");\n  EXPECT_EQ(format(\"%.1La\", slightly_under), \"0x8.8p+24\");\n  EXPECT_EQ(format(\"%.2La\", slightly_under), \"0x8.80p+24\");\n  EXPECT_EQ(format(\"%.3La\", slightly_under), \"0x8.800p+24\");\n  EXPECT_EQ(format(\"%.4La\", slightly_under), \"0x8.8000p+24\");\n  EXPECT_EQ(format(\"%.5La\", slightly_under), \"0x8.7ffffp+24\");\n  EXPECT_EQ(format(\"%.6La\", slightly_under), \"0x8.7ffff0p+24\");\n  EXPECT_EQ(format(\"%.7La\", slightly_under), \"0x8.7ffff00p+24\");\n\n  // 0xc.0828384858688000p+128\n  const long double eights = 4094231060438608800781871108094404067328.0;\n  EXPECT_EQ(format(\"%.0La\", eights), \"0xcp+128\");\n  EXPECT_EQ(format(\"%.1La\", eights), \"0xc.1p+128\");\n  EXPECT_EQ(format(\"%.2La\", eights), \"0xc.08p+128\");\n  EXPECT_EQ(format(\"%.3La\", eights), \"0xc.083p+128\");\n  EXPECT_EQ(format(\"%.4La\", eights), \"0xc.0828p+128\");\n  EXPECT_EQ(format(\"%.5La\", eights), \"0xc.08284p+128\");\n  EXPECT_EQ(format(\"%.6La\", eights), \"0xc.082838p+128\");\n  EXPECT_EQ(format(\"%.7La\", eights), \"0xc.0828385p+128\");\n  EXPECT_EQ(format(\"%.8La\", eights), \"0xc.08283848p+128\");\n  EXPECT_EQ(format(\"%.9La\", eights), \"0xc.082838486p+128\");\n  EXPECT_EQ(format(\"%.10La\", eights), \"0xc.0828384858p+128\");\n  EXPECT_EQ(format(\"%.11La\", eights), \"0xc.08283848587p+128\");\n  EXPECT_EQ(format(\"%.12La\", eights), \"0xc.082838485868p+128\");\n  EXPECT_EQ(format(\"%.13La\", eights), \"0xc.0828384858688p+128\");\n  EXPECT_EQ(format(\"%.14La\", eights), \"0xc.08283848586880p+128\");\n  EXPECT_EQ(format(\"%.15La\", eights), \"0xc.082838485868800p+128\");\n  EXPECT_EQ(format(\"%.16La\", eights), \"0xc.0828384858688000p+128\");\n}\n\n// We don't actually store the results. This is just to exercise the rest of the\n// machinery.\nstruct NullSink {\n  friend void AbslFormatFlush(NullSink *, string_view) {}\n};\n\ntemplate <typename... T>\nbool FormatWithNullSink(absl::string_view fmt, const T &... a) {\n  NullSink sink;\n  FormatArgImpl args[] = {FormatArgImpl(a)...};\n  return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));\n}\n\nTEST_F(FormatConvertTest, ExtremeWidthPrecision) {\n  for (const char *fmt : {\"f\"}) {\n    for (double d : {1e-100, 1.0, 1e100}) {\n      constexpr int max = std::numeric_limits<int>::max();\n      EXPECT_TRUE(FormatWithNullSink(std::string(\"%.*\") + fmt, max, d));\n      EXPECT_TRUE(FormatWithNullSink(std::string(\"%1.*\") + fmt, max, d));\n      EXPECT_TRUE(FormatWithNullSink(std::string(\"%*\") + fmt, max, d));\n      EXPECT_TRUE(FormatWithNullSink(std::string(\"%*.*\") + fmt, max, max, d));\n    }\n  }\n}\n\nTEST_F(FormatConvertTest, LongDouble) {\n  const NativePrintfTraits &native_traits = VerifyNativeImplementation();\n  const char *const kFormats[] = {\"%\",    \"%.3\", \"%8.5\", \"%9\",  \"%.5000\",\n                                  \"%.60\", \"%+\",  \"% \",   \"%-10\"};\n\n  std::vector<long double> doubles = {\n      0.0,\n      -0.0,\n      std::numeric_limits<long double>::max(),\n      -std::numeric_limits<long double>::max(),\n      std::numeric_limits<long double>::min(),\n      -std::numeric_limits<long double>::min(),\n      std::numeric_limits<long double>::infinity(),\n      -std::numeric_limits<long double>::infinity()};\n\n  for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L,\n                           1234567.L, 12345678.L, 123456789.L, 1234567890.L,\n                           12345678901.L, 123456789012.L, 1234567890123.L,\n                           // This value is not representable in double, but it\n                           // is in long double that uses the extended format.\n                           // This is to verify that we are not truncating the\n                           // value mistakenly through a double.\n                           10000000000000000.25L}) {\n    for (int exp : {-1000, -500, 0, 500, 1000}) {\n      for (int sign : {1, -1}) {\n        doubles.push_back(sign * std::ldexp(base, exp));\n        doubles.push_back(sign / std::ldexp(base, exp));\n      }\n    }\n  }\n\n  // Regression tests\n  //\n  // Using a string literal because not all platforms support hex literals or it\n  // might be out of range.\n  doubles.push_back(std::strtold(\"-0xf.ffffffb5feafffbp-16324L\", nullptr));\n\n  for (const char *fmt : kFormats) {\n    for (char f : {'f', 'F',  //\n                   'g', 'G',  //\n                   'a', 'A',  //\n                   'e', 'E'}) {\n      std::string fmt_str = std::string(fmt) + 'L' + f;\n\n      if (fmt == absl::string_view(\"%.5000\") && !IsNativeFloatConversion(f)) {\n        // This particular test takes way too long with snprintf.\n        // Disable for the case we are not implementing natively.\n        continue;\n      }\n\n      if (IsNativeHexFloatConversion(f)) {\n        if (!native_traits.hex_float_has_glibc_rounding ||\n            !native_traits.hex_float_optimizes_leading_digit_bit_count) {\n          continue;\n        }\n      }\n\n      for (auto d : doubles) {\n        FormatArgImpl arg(d);\n        UntypedFormatSpecImpl format(fmt_str);\n        std::string result = FormatPack(format, {&arg, 1});\n\n#ifdef _MSC_VER\n        // MSVC has a different rounding policy than us so we can't test our\n        // implementation against the native one there.\n        continue;\n#endif  // _MSC_VER\n\n        // We use ASSERT_EQ here because failures are usually correlated and a\n        // bug would print way too many failed expectations causing the test to\n        // time out.\n        ASSERT_EQ(StrPrint(fmt_str.c_str(), d), result)\n            << fmt_str << \" \" << StrPrint(\"%.18Lg\", d) << \" \"\n            << StrPrint(\"%La\", d) << \" \" << StrPrint(\"%.1080Lf\", d);\n      }\n    }\n  }\n}\n\nTEST_F(FormatConvertTest, IntAsDouble) {\n  const NativePrintfTraits &native_traits = VerifyNativeImplementation();\n  const int kMin = std::numeric_limits<int>::min();\n  const int kMax = std::numeric_limits<int>::max();\n  const int ia[] = {\n    1, 2, 3, 123,\n    -1, -2, -3, -123,\n    0, kMax - 1, kMax, kMin + 1, kMin };\n  for (const int fx : ia) {\n    SCOPED_TRACE(fx);\n    const FormatArgImpl args[] = {FormatArgImpl(fx)};\n    struct Expectation {\n      int line;\n      std::string out;\n      const char *fmt;\n    };\n    const double dx = static_cast<double>(fx);\n    std::vector<Expectation> expect = {\n        {__LINE__, StrPrint(\"%f\", dx), \"%f\"},\n        {__LINE__, StrPrint(\"%12f\", dx), \"%12f\"},\n        {__LINE__, StrPrint(\"%.12f\", dx), \"%.12f\"},\n        {__LINE__, StrPrint(\"%.12a\", dx), \"%.12a\"},\n    };\n    if (native_traits.hex_float_uses_minimal_precision_when_not_specified) {\n      Expectation ex = {__LINE__, StrPrint(\"%12a\", dx), \"%12a\"};\n      expect.push_back(ex);\n    }\n    for (const Expectation &e : expect) {\n      SCOPED_TRACE(e.line);\n      SCOPED_TRACE(e.fmt);\n      UntypedFormatSpecImpl format(e.fmt);\n      EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args)));\n    }\n  }\n}\n\ntemplate <typename T>\nbool FormatFails(const char* test_format, T value) {\n  std::string format_string = std::string(\"<<\") + test_format + \">>\";\n  UntypedFormatSpecImpl format(format_string);\n\n  int one = 1;\n  const FormatArgImpl args[] = {FormatArgImpl(value), FormatArgImpl(one)};\n  EXPECT_EQ(FormatPack(format, absl::MakeSpan(args)), \"\")\n      << \"format=\" << test_format << \" value=\" << value;\n  return FormatPack(format, absl::MakeSpan(args)).empty();\n}\n\nTEST_F(FormatConvertTest, ExpectedFailures) {\n  // Int input\n  EXPECT_TRUE(FormatFails(\"%p\", 1));\n  EXPECT_TRUE(FormatFails(\"%s\", 1));\n  EXPECT_TRUE(FormatFails(\"%n\", 1));\n\n  // Double input\n  EXPECT_TRUE(FormatFails(\"%p\", 1.));\n  EXPECT_TRUE(FormatFails(\"%s\", 1.));\n  EXPECT_TRUE(FormatFails(\"%n\", 1.));\n  EXPECT_TRUE(FormatFails(\"%c\", 1.));\n  EXPECT_TRUE(FormatFails(\"%d\", 1.));\n  EXPECT_TRUE(FormatFails(\"%x\", 1.));\n  EXPECT_TRUE(FormatFails(\"%*d\", 1.));\n\n  // String input\n  EXPECT_TRUE(FormatFails(\"%n\", \"\"));\n  EXPECT_TRUE(FormatFails(\"%c\", \"\"));\n  EXPECT_TRUE(FormatFails(\"%d\", \"\"));\n  EXPECT_TRUE(FormatFails(\"%x\", \"\"));\n  EXPECT_TRUE(FormatFails(\"%f\", \"\"));\n  EXPECT_TRUE(FormatFails(\"%*d\", \"\"));\n}\n\n// Sanity check to make sure that we are testing what we think we're testing on\n// e.g. the x86_64+glibc platform.\nTEST_F(FormatConvertTest, GlibcHasCorrectTraits) {\n#if defined(__GLIBC__) && defined(__x86_64__)\n  constexpr bool kIsSupportedGlibc = true;\n#else\n  constexpr bool kIsSupportedGlibc = false;\n#endif\n\n  if (!kIsSupportedGlibc) {\n    GTEST_SKIP() << \"Test does not support this platform\";\n  }\n\n  const NativePrintfTraits &native_traits = VerifyNativeImplementation();\n  // If one of the following tests break then it is either because the above PP\n  // macro guards failed to exclude a new platform (likely) or because something\n  // has changed in the implementation of glibc sprintf float formatting\n  // behavior.  If the latter, then the code that computes these flags needs to\n  // be revisited and/or possibly the StrFormat implementation.\n  EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding);\n  EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr);\n  EXPECT_TRUE(\n      native_traits.hex_float_uses_minimal_precision_when_not_specified);\n  EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count);\n}\n\n}  // namespace\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/extension.cc",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/extension.h\"\n\n#include <errno.h>\n#include <algorithm>\n#include <string>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nstd::string FlagsToString(Flags v) {\n  std::string s;\n  s.append(FlagsContains(v, Flags::kLeft) ? \"-\" : \"\");\n  s.append(FlagsContains(v, Flags::kShowPos) ? \"+\" : \"\");\n  s.append(FlagsContains(v, Flags::kSignCol) ? \" \" : \"\");\n  s.append(FlagsContains(v, Flags::kAlt) ? \"#\" : \"\");\n  s.append(FlagsContains(v, Flags::kZero) ? \"0\" : \"\");\n  return s;\n}\n\nbool FormatSinkImpl::PutPaddedString(string_view value, int width,\n                                     int precision, bool left) {\n  size_t space_remaining = 0;\n  if (width >= 0)\n    space_remaining = static_cast<size_t>(width);\n  size_t n = value.size();\n  if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));\n  string_view shown(value.data(), n);\n  space_remaining = Excess(shown.size(), space_remaining);\n  if (!left) Append(space_remaining, ' ');\n  Append(shown);\n  if (left) Append(space_remaining, ' ');\n  return true;\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/extension.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_\n\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/internal/str_format/output.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nenum class FormatConversionChar : uint8_t;\nenum class FormatConversionCharSet : uint64_t;\nenum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };\n\nnamespace str_format_internal {\n\nclass FormatRawSinkImpl {\n public:\n  // Implicitly convert from any type that provides the hook function as\n  // described above.\n  template <typename T, decltype(str_format_internal::InvokeFlush(\n                            std::declval<T*>(), string_view()))* = nullptr>\n  FormatRawSinkImpl(T* raw)  // NOLINT\n      : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}\n\n  void Write(string_view s) { write_(sink_, s); }\n\n  template <typename T>\n  static FormatRawSinkImpl Extract(T s) {\n    return s.sink_;\n  }\n\n private:\n  template <typename T>\n  static void Flush(void* r, string_view s) {\n    str_format_internal::InvokeFlush(static_cast<T*>(r), s);\n  }\n\n  void* sink_;\n  void (*write_)(void*, string_view);\n};\n\n// An abstraction to which conversions write their string data.\nclass FormatSinkImpl {\n public:\n  explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}\n\n  ~FormatSinkImpl() { Flush(); }\n\n  void Flush() {\n    raw_.Write(string_view(buf_, static_cast<size_t>(pos_ - buf_)));\n    pos_ = buf_;\n  }\n\n  void Append(size_t n, char c) {\n    if (n == 0) return;\n    size_ += n;\n    auto raw_append = [&](size_t count) {\n      memset(pos_, c, count);\n      pos_ += count;\n    };\n    while (n > Avail()) {\n      n -= Avail();\n      if (Avail() > 0) {\n        raw_append(Avail());\n      }\n      Flush();\n    }\n    raw_append(n);\n  }\n\n  void Append(string_view v) {\n    size_t n = v.size();\n    if (n == 0) return;\n    size_ += n;\n    if (n >= Avail()) {\n      Flush();\n      raw_.Write(v);\n      return;\n    }\n    memcpy(pos_, v.data(), n);\n    pos_ += n;\n  }\n\n  size_t size() const { return size_; }\n\n  // Put 'v' to 'sink' with specified width, precision, and left flag.\n  bool PutPaddedString(string_view v, int width, int precision, bool left);\n\n  template <typename T>\n  T Wrap() {\n    return T(this);\n  }\n\n  template <typename T>\n  static FormatSinkImpl* Extract(T* s) {\n    return s->sink_;\n  }\n\n private:\n  size_t Avail() const {\n    return static_cast<size_t>(buf_ + sizeof(buf_) - pos_);\n  }\n\n  FormatRawSinkImpl raw_;\n  size_t size_ = 0;\n  char* pos_ = buf_;\n  char buf_[1024];\n};\n\nenum class Flags : uint8_t {\n  kBasic = 0,\n  kLeft = 1 << 0,\n  kShowPos = 1 << 1,\n  kSignCol = 1 << 2,\n  kAlt = 1 << 3,\n  kZero = 1 << 4,\n  // This is not a real flag. It just exists to turn off kBasic when no other\n  // flags are set. This is for when width/precision are specified, or a length\n  // modifier affects the behavior (\"%lc\").\n  kNonBasic = 1 << 5,\n};\n\nconstexpr Flags operator|(Flags a, Flags b) {\n  return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));\n}\n\nconstexpr bool FlagsContains(Flags haystack, Flags needle) {\n  return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) ==\n         static_cast<uint8_t>(needle);\n}\n\nstd::string FlagsToString(Flags v);\n\ninline std::ostream& operator<<(std::ostream& os, Flags v) {\n  return os << FlagsToString(v);\n}\n\n// clang-format off\n#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \\\n  /* text */ \\\n  X_VAL(c) X_SEP X_VAL(s) X_SEP \\\n  /* ints */ \\\n  X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \\\n  X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \\\n  /* floats */ \\\n  X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \\\n  X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \\\n  /* misc */ \\\n  X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)\n// clang-format on\n\n// This type should not be referenced, it exists only to provide labels\n// internally that match the values declared in FormatConversionChar in\n// str_format.h. This is meant to allow internal libraries to use the same\n// declared interface type as the public interface\n// (absl::StrFormatConversionChar) while keeping the definition in a public\n// header.\n// Internal libraries should use the form\n// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for\n// comparisons.  Use in switch statements is not recommended due to a bug in how\n// gcc 4.9 -Wswitch handles declared but undefined enums.\nstruct FormatConversionCharInternal {\n  FormatConversionCharInternal() = delete;\n\n private:\n  // clang-format off\n  enum class Enum : uint8_t {\n    c, s,                    // text\n    d, i, o, u, x, X,        // int\n    f, F, e, E, g, G, a, A,  // float\n    n, p, v,                    // misc\n    kNone\n  };\n  // clang-format on\n public:\n#define ABSL_INTERNAL_X_VAL(id)              \\\n  static constexpr FormatConversionChar id = \\\n      static_cast<FormatConversionChar>(Enum::id);\n  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )\n#undef ABSL_INTERNAL_X_VAL\n  static constexpr FormatConversionChar kNone =\n      static_cast<FormatConversionChar>(Enum::kNone);\n};\n// clang-format on\n\ninline FormatConversionChar FormatConversionCharFromChar(char c) {\n  switch (c) {\n#define ABSL_INTERNAL_X_VAL(id) \\\n  case #id[0]:                  \\\n    return FormatConversionCharInternal::id;\n    ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )\n#undef ABSL_INTERNAL_X_VAL\n  }\n  return FormatConversionCharInternal::kNone;\n}\n\ninline bool FormatConversionCharIsUpper(FormatConversionChar c) {\n  if (c == FormatConversionCharInternal::X ||\n      c == FormatConversionCharInternal::F ||\n      c == FormatConversionCharInternal::E ||\n      c == FormatConversionCharInternal::G ||\n      c == FormatConversionCharInternal::A) {\n    return true;\n  } else {\n    return false;\n  }\n}\n\ninline bool FormatConversionCharIsFloat(FormatConversionChar c) {\n  if (c == FormatConversionCharInternal::a ||\n      c == FormatConversionCharInternal::e ||\n      c == FormatConversionCharInternal::f ||\n      c == FormatConversionCharInternal::g ||\n      c == FormatConversionCharInternal::A ||\n      c == FormatConversionCharInternal::E ||\n      c == FormatConversionCharInternal::F ||\n      c == FormatConversionCharInternal::G) {\n    return true;\n  } else {\n    return false;\n  }\n}\n\ninline char FormatConversionCharToChar(FormatConversionChar c) {\n  if (c == FormatConversionCharInternal::kNone) {\n    return '\\0';\n\n#define ABSL_INTERNAL_X_VAL(e)                       \\\n  } else if (c == FormatConversionCharInternal::e) { \\\n    return #e[0];\n#define ABSL_INTERNAL_X_SEP\n  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,\n                                         ABSL_INTERNAL_X_SEP)\n  } else {\n    return '\\0';\n  }\n\n#undef ABSL_INTERNAL_X_VAL\n#undef ABSL_INTERNAL_X_SEP\n}\n\n// The associated char.\ninline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {\n  char c = FormatConversionCharToChar(v);\n  if (!c) c = '?';\n  return os << c;\n}\n\nstruct FormatConversionSpecImplFriend;\n\nclass FormatConversionSpecImpl {\n public:\n  // Width and precision are not specified, no flags are set.\n  bool is_basic() const { return flags_ == Flags::kBasic; }\n  bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }\n  bool has_show_pos_flag() const {\n    return FlagsContains(flags_, Flags::kShowPos);\n  }\n  bool has_sign_col_flag() const {\n    return FlagsContains(flags_, Flags::kSignCol);\n  }\n  bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }\n  bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }\n\n  LengthMod length_mod() const { return length_mod_; }\n\n  FormatConversionChar conversion_char() const {\n    // Keep this field first in the struct . It generates better code when\n    // accessing it when ConversionSpec is passed by value in registers.\n    static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, \"\");\n    return conv_;\n  }\n\n  void set_conversion_char(FormatConversionChar c) { conv_ = c; }\n\n  // Returns the specified width. If width is unspecfied, it returns a negative\n  // value.\n  int width() const { return width_; }\n  // Returns the specified precision. If precision is unspecfied, it returns a\n  // negative value.\n  int precision() const { return precision_; }\n\n  template <typename T>\n  T Wrap() {\n    return T(*this);\n  }\n\n private:\n  friend struct str_format_internal::FormatConversionSpecImplFriend;\n  FormatConversionChar conv_ = FormatConversionCharInternal::kNone;\n  Flags flags_;\n  LengthMod length_mod_ = LengthMod::none;\n  int width_;\n  int precision_;\n};\n\nstruct FormatConversionSpecImplFriend final {\n  static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {\n    conv->flags_ = f;\n  }\n  static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) {\n    conv->length_mod_ = l;\n  }\n  static void SetConversionChar(FormatConversionChar c,\n                                FormatConversionSpecImpl* conv) {\n    conv->conv_ = c;\n  }\n  static void SetWidth(int w, FormatConversionSpecImpl* conv) {\n    conv->width_ = w;\n  }\n  static void SetPrecision(int p, FormatConversionSpecImpl* conv) {\n    conv->precision_ = p;\n  }\n  static std::string FlagsToString(const FormatConversionSpecImpl& spec) {\n    return str_format_internal::FlagsToString(spec.flags_);\n  }\n};\n\n// Type safe OR operator.\n// We need this for two reasons:\n//  1. operator| on enums makes them decay to integers and the result is an\n//     integer. We need the result to stay as an enum.\n//  2. We use \"enum class\" which would not work even if we accepted the decay.\nconstexpr FormatConversionCharSet FormatConversionCharSetUnion(\n    FormatConversionCharSet a) {\n  return a;\n}\n\ntemplate <typename... CharSet>\nconstexpr FormatConversionCharSet FormatConversionCharSetUnion(\n    FormatConversionCharSet a, CharSet... rest) {\n  return static_cast<FormatConversionCharSet>(\n      static_cast<uint64_t>(a) |\n      static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));\n}\n\nconstexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {\n  return uint64_t{1} << (1 + static_cast<uint8_t>(c));\n}\n\nconstexpr uint64_t FormatConversionCharToConvInt(char conv) {\n  return\n#define ABSL_INTERNAL_CHAR_SET_CASE(c)                                 \\\n  conv == #c[0]                                                        \\\n      ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \\\n      :\n      ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )\n#undef ABSL_INTERNAL_CHAR_SET_CASE\n                  conv == '*'\n          ? 1\n          : 0;\n}\n\nconstexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {\n  return static_cast<FormatConversionCharSet>(\n      FormatConversionCharToConvInt(conv));\n}\n\nstruct FormatConversionCharSetInternal {\n#define ABSL_INTERNAL_CHAR_SET_CASE(c)         \\\n  static constexpr FormatConversionCharSet c = \\\n      FormatConversionCharToConvValue(#c[0]);\n  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )\n#undef ABSL_INTERNAL_CHAR_SET_CASE\n\n  // Used for width/precision '*' specification.\n  static constexpr FormatConversionCharSet kStar =\n      FormatConversionCharToConvValue('*');\n\n  static constexpr FormatConversionCharSet kIntegral =\n      FormatConversionCharSetUnion(d, i, u, o, x, X);\n  static constexpr FormatConversionCharSet kFloating =\n      FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);\n  static constexpr FormatConversionCharSet kNumeric =\n      FormatConversionCharSetUnion(kIntegral, kFloating);\n  static constexpr FormatConversionCharSet kPointer = p;\n};\n\n// Type safe OR operator.\n// We need this for two reasons:\n//  1. operator| on enums makes them decay to integers and the result is an\n//     integer. We need the result to stay as an enum.\n//  2. We use \"enum class\" which would not work even if we accepted the decay.\nconstexpr FormatConversionCharSet operator|(FormatConversionCharSet a,\n                                            FormatConversionCharSet b) {\n  return FormatConversionCharSetUnion(a, b);\n}\n\n// Overloaded conversion functions to support absl::ParsedFormat.\n// Get a conversion with a single character in it.\nconstexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {\n  return static_cast<FormatConversionCharSet>(\n      FormatConversionCharToConvValue(c));\n}\n\n// Get a conversion with a single character in it.\nconstexpr FormatConversionCharSet ToFormatConversionCharSet(\n    FormatConversionCharSet c) {\n  return c;\n}\n\ntemplate <typename T>\nvoid ToFormatConversionCharSet(T) = delete;\n\n// Checks whether `c` exists in `set`.\nconstexpr bool Contains(FormatConversionCharSet set, char c) {\n  return (static_cast<uint64_t>(set) &\n          static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;\n}\n\n// Checks whether all the characters in `c` are contained in `set`\nconstexpr bool Contains(FormatConversionCharSet set,\n                        FormatConversionCharSet c) {\n  return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==\n         static_cast<uint64_t>(c);\n}\n\n// Checks whether all the characters in `c` are contained in `set`\nconstexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {\n  return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;\n}\n\n// Return capacity - used, clipped to a minimum of 0.\ninline size_t Excess(size_t used, size_t capacity) {\n  return used < capacity ? capacity - used : 0;\n}\n\n}  // namespace str_format_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/extension_test.cc",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#include \"absl/strings/internal/str_format/extension.h\"\n\n#include <cstddef>\n#include <random>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace my_namespace {\nclass UserDefinedType {\n public:\n  UserDefinedType() = default;\n\n  void Append(absl::string_view str) { value_.append(str.data(), str.size()); }\n  const std::string& Value() const { return value_; }\n\n  friend void AbslFormatFlush(UserDefinedType* x, absl::string_view str) {\n    x->Append(str);\n  }\n\n private:\n  std::string value_;\n};\n}  // namespace my_namespace\n\nnamespace {\n\nstd::string MakeRandomString(size_t len) {\n  absl::InsecureBitGen gen;\n  std::uniform_int_distribution<> dis('a', 'z');\n  std::string s(len, '0');\n  for (char& c : s) {\n    c = dis(gen);\n  }\n  return s;\n}\n\nTEST(FormatExtensionTest, SinkAppendSubstring) {\n  for (size_t chunk_size : {1, 10, 100, 1000, 10000}) {\n    std::string expected, actual;\n    absl::str_format_internal::FormatSinkImpl sink(&actual);\n    for (size_t chunks = 0; chunks < 10; ++chunks) {\n      std::string rand = MakeRandomString(chunk_size);\n      expected += rand;\n      sink.Append(rand);\n    }\n    sink.Flush();\n    EXPECT_EQ(actual, expected);\n  }\n}\n\nTEST(FormatExtensionTest, SinkAppendChars) {\n  for (size_t chunk_size : {1, 10, 100, 1000, 10000}) {\n    std::string expected, actual;\n    absl::str_format_internal::FormatSinkImpl sink(&actual);\n    for (size_t chunks = 0; chunks < 10; ++chunks) {\n      std::string rand = MakeRandomString(1);\n      expected.append(chunk_size, rand[0]);\n      sink.Append(chunk_size, rand[0]);\n    }\n    sink.Flush();\n    EXPECT_EQ(actual, expected);\n  }\n}\n\nTEST(FormatExtensionTest, VerifyEnumEquality) {\n#define X_VAL(id)                           \\\n  EXPECT_EQ(absl::FormatConversionChar::id, \\\n            absl::str_format_internal::FormatConversionCharInternal::id);\n  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );\n#undef X_VAL\n\n#define X_VAL(id)                              \\\n  EXPECT_EQ(absl::FormatConversionCharSet::id, \\\n            absl::str_format_internal::FormatConversionCharSetInternal::id);\n  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );\n#undef X_VAL\n}\n\nTEST(FormatExtensionTest, SetConversionChar) {\n  absl::str_format_internal::FormatConversionSpecImpl spec;\n  EXPECT_EQ(spec.conversion_char(),\n            absl::str_format_internal::FormatConversionCharInternal::kNone);\n  spec.set_conversion_char(\n      absl::str_format_internal::FormatConversionCharInternal::d);\n  EXPECT_EQ(spec.conversion_char(),\n            absl::str_format_internal::FormatConversionCharInternal::d);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/str_format/float_conversion.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/float_conversion.h\"\n\n#include <string.h>\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cmath>\n#include <cstdint>\n#include <cstring>\n#include <limits>\n#include <optional>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/functional/function_ref.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/numeric/internal/representation.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nnamespace {\n\nusing ::absl::numeric_internal::IsDoubleDouble;\n\n// The code below wants to avoid heap allocations.\n// To do so it needs to allocate memory on the stack.\n// `StackArray` will allocate memory on the stack in the form of a uint32_t\n// array and call the provided callback with said memory.\n// It will allocate memory in increments of 512 bytes. We could allocate the\n// largest needed unconditionally, but that is more than we need in most of\n// cases. This way we use less stack in the common cases.\nclass StackArray {\n  using Func = absl::FunctionRef<void(absl::Span<uint32_t>)>;\n  static constexpr size_t kStep = 512 / sizeof(uint32_t);\n  // 5 steps is 2560 bytes, which is enough to hold a long double with the\n  // largest/smallest exponents.\n  // The operations below will static_assert their particular maximum.\n  static constexpr size_t kNumSteps = 5;\n\n  // We do not want this function to be inlined.\n  // Otherwise the caller will allocate the stack space unnecessarily for all\n  // the variants even though it only calls one.\n  template <size_t steps>\n  ABSL_ATTRIBUTE_NOINLINE static void RunWithCapacityImpl(Func f) {\n    uint32_t values[steps * kStep]{};\n    f(absl::MakeSpan(values));\n  }\n\n public:\n  static constexpr size_t kMaxCapacity = kStep * kNumSteps;\n\n  static void RunWithCapacity(size_t capacity, Func f) {\n    assert(capacity <= kMaxCapacity);\n    const size_t step = (capacity + kStep - 1) / kStep;\n    assert(step <= kNumSteps);\n    switch (step) {\n      case 1:\n        return RunWithCapacityImpl<1>(f);\n      case 2:\n        return RunWithCapacityImpl<2>(f);\n      case 3:\n        return RunWithCapacityImpl<3>(f);\n      case 4:\n        return RunWithCapacityImpl<4>(f);\n      case 5:\n        return RunWithCapacityImpl<5>(f);\n    }\n\n    assert(false && \"Invalid capacity\");\n  }\n};\n\n// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns\n// the carry.\n// Requires: `0 <= carry <= 9`\ntemplate <typename Int>\ninline char MultiplyBy10WithCarry(Int* v, char carry) {\n  using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;\n  BiggerInt tmp =\n      10 * static_cast<BiggerInt>(*v) + static_cast<BiggerInt>(carry);\n  *v = static_cast<Int>(tmp);\n  return static_cast<char>(tmp >> (sizeof(Int) * 8));\n}\n\n// Calculates `(2^64 * carry + *v) / 10`.\n// Stores the quotient in `*v` and returns the remainder.\n// Requires: `0 <= carry <= 9`\ninline char DivideBy10WithCarry(uint64_t* v, char carry) {\n  constexpr uint64_t divisor = 10;\n  // 2^64 / divisor = chunk_quotient + chunk_remainder / divisor\n  constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);\n  constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;\n\n  const uint64_t carry_u64 = static_cast<uint64_t>(carry);\n  const uint64_t mod = *v % divisor;\n  const uint64_t next_carry = chunk_remainder * carry_u64 + mod;\n  *v = *v / divisor + carry_u64 * chunk_quotient + next_carry / divisor;\n  return static_cast<char>(next_carry % divisor);\n}\n\nusing MaxFloatType =\n    typename std::conditional<IsDoubleDouble(), double, long double>::type;\n\n// Generates the decimal representation for an integer of the form `v * 2^exp`,\n// where `v` and `exp` are both positive integers.\n// It generates the digits from the left (ie the most significant digit first)\n// to allow for direct printing into the sink.\n//\n// Requires `0 <= exp` and `exp <= numeric_limits<MaxFloatType>::max_exponent`.\nclass BinaryToDecimal {\n  static constexpr size_t ChunksNeeded(int exp) {\n    // We will left shift a uint128 by `exp` bits, so we need `128+exp` total\n    // bits. Round up to 32.\n    // See constructor for details about adding `10%` to the value.\n    return static_cast<size_t>((128 + exp + 31) / 32 * 11 / 10);\n  }\n\n public:\n  // Run the conversion for `v * 2^exp` and call `f(binary_to_decimal)`.\n  // This function will allocate enough stack space to perform the conversion.\n  static void RunConversion(uint128 v, int exp,\n                            absl::FunctionRef<void(BinaryToDecimal)> f) {\n    assert(exp > 0);\n    assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);\n    static_assert(\n        StackArray::kMaxCapacity >=\n            ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),\n        \"\");\n\n    StackArray::RunWithCapacity(\n        ChunksNeeded(exp),\n        [=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });\n  }\n\n  size_t TotalDigits() const {\n    return (decimal_end_ - decimal_start_) * kDigitsPerChunk +\n           CurrentDigits().size();\n  }\n\n  // See the current block of digits.\n  absl::string_view CurrentDigits() const {\n    return absl::string_view(&digits_[kDigitsPerChunk - size_], size_);\n  }\n\n  // Advance the current view of digits.\n  // Returns `false` when no more digits are available.\n  bool AdvanceDigits() {\n    if (decimal_start_ >= decimal_end_) return false;\n\n    uint32_t w = data_[decimal_start_++];\n    for (size_ = 0; size_ < kDigitsPerChunk; w /= 10) {\n      digits_[kDigitsPerChunk - ++size_] = w % 10 + '0';\n    }\n    return true;\n  }\n\n private:\n  BinaryToDecimal(absl::Span<uint32_t> data, uint128 v, int exp) : data_(data) {\n    // We need to print the digits directly into the sink object without\n    // buffering them all first. To do this we need two things:\n    // - to know the total number of digits to do padding when necessary\n    // - to generate the decimal digits from the left.\n    //\n    // In order to do this, we do a two pass conversion.\n    // On the first pass we convert the binary representation of the value into\n    // a decimal representation in which each uint32_t chunk holds up to 9\n    // decimal digits.  In the second pass we take each decimal-holding-uint32_t\n    // value and generate the ascii decimal digits into `digits_`.\n    //\n    // The binary and decimal representations actually share the same memory\n    // region. As we go converting the chunks from binary to decimal we free\n    // them up and reuse them for the decimal representation. One caveat is that\n    // the decimal representation is around 7% less efficient in space than the\n    // binary one. We allocate an extra 10% memory to account for this. See\n    // ChunksNeeded for this calculation.\n    size_t after_chunk_index = static_cast<size_t>(exp / 32 + 1);\n    decimal_start_ = decimal_end_ = ChunksNeeded(exp);\n    const int offset = exp % 32;\n    // Left shift v by exp bits.\n    data_[after_chunk_index - 1] = static_cast<uint32_t>(v << offset);\n    for (v >>= (32 - offset); v; v >>= 32)\n      data_[++after_chunk_index - 1] = static_cast<uint32_t>(v);\n\n    while (after_chunk_index > 0) {\n      // While we have more than one chunk available, go in steps of 1e9.\n      // `data_[after_chunk_index - 1]` holds the highest non-zero binary chunk,\n      // so keep the variable updated.\n      uint32_t carry = 0;\n      for (size_t i = after_chunk_index; i > 0; --i) {\n        uint64_t tmp = uint64_t{data_[i - 1]} + (uint64_t{carry} << 32);\n        data_[i - 1] = static_cast<uint32_t>(tmp / uint64_t{1000000000});\n        carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});\n      }\n\n      // If the highest chunk is now empty, remove it from view.\n      if (data_[after_chunk_index - 1] == 0)\n        --after_chunk_index;\n\n      --decimal_start_;\n      assert(decimal_start_ != after_chunk_index - 1);\n      data_[decimal_start_] = carry;\n    }\n\n    // Fill the first set of digits. The first chunk might not be complete, so\n    // handle differently.\n    for (uint32_t first = data_[decimal_start_++]; first != 0; first /= 10) {\n      digits_[kDigitsPerChunk - ++size_] = first % 10 + '0';\n    }\n  }\n\n private:\n  static constexpr size_t kDigitsPerChunk = 9;\n\n  size_t decimal_start_;\n  size_t decimal_end_;\n\n  std::array<char, kDigitsPerChunk> digits_;\n  size_t size_ = 0;\n\n  absl::Span<uint32_t> data_;\n};\n\n// Converts a value of the form `x * 2^-exp` into a sequence of decimal digits.\n// Requires `-exp < 0` and\n// `-exp >= limits<MaxFloatType>::min_exponent - limits<MaxFloatType>::digits`.\nclass FractionalDigitGenerator {\n public:\n  // Run the conversion for `v * 2^exp` and call `f(generator)`.\n  // This function will allocate enough stack space to perform the conversion.\n  static void RunConversion(\n      uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {\n    using Limits = std::numeric_limits<MaxFloatType>;\n    assert(-exp < 0);\n    assert(-exp >= Limits::min_exponent - 128);\n    static_assert(StackArray::kMaxCapacity >=\n                      (Limits::digits + 128 - Limits::min_exponent + 31) / 32,\n                  \"\");\n    StackArray::RunWithCapacity(\n        static_cast<size_t>((Limits::digits + exp + 31) / 32),\n        [=](absl::Span<uint32_t> input) {\n          f(FractionalDigitGenerator(input, v, exp));\n        });\n  }\n\n  // Returns true if there are any more non-zero digits left.\n  bool HasMoreDigits() const { return next_digit_ != 0 || after_chunk_index_; }\n\n  // Returns true if the remainder digits are greater than 5000...\n  bool IsGreaterThanHalf() const {\n    return next_digit_ > 5 || (next_digit_ == 5 && after_chunk_index_);\n  }\n  // Returns true if the remainder digits are exactly 5000...\n  bool IsExactlyHalf() const { return next_digit_ == 5 && !after_chunk_index_; }\n\n  struct Digits {\n    char digit_before_nine;\n    size_t num_nines;\n  };\n\n  // Get the next set of digits.\n  // They are composed by a non-9 digit followed by a runs of zero or more 9s.\n  Digits GetDigits() {\n    Digits digits{next_digit_, 0};\n\n    next_digit_ = GetOneDigit();\n    while (next_digit_ == 9) {\n      ++digits.num_nines;\n      next_digit_ = GetOneDigit();\n    }\n\n    return digits;\n  }\n\n private:\n  // Return the next digit.\n  char GetOneDigit() {\n    if (!after_chunk_index_)\n      return 0;\n\n    char carry = 0;\n    for (size_t i = after_chunk_index_; i > 0; --i) {\n      carry = MultiplyBy10WithCarry(&data_[i - 1], carry);\n    }\n    // If the lowest chunk is now empty, remove it from view.\n    if (data_[after_chunk_index_ - 1] == 0)\n      --after_chunk_index_;\n    return carry;\n  }\n\n  FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)\n      : after_chunk_index_(static_cast<size_t>(exp / 32 + 1)), data_(data) {\n    const int offset = exp % 32;\n    // Right shift `v` by `exp` bits.\n    data_[after_chunk_index_ - 1] = static_cast<uint32_t>(v << (32 - offset));\n    v >>= offset;\n    // Make sure we don't overflow the data. We already calculated that\n    // non-zero bits fit, so we might not have space for leading zero bits.\n    for (size_t pos = after_chunk_index_ - 1; v; v >>= 32)\n      data_[--pos] = static_cast<uint32_t>(v);\n\n    // Fill next_digit_, as GetDigits expects it to be populated always.\n    next_digit_ = GetOneDigit();\n  }\n\n  char next_digit_;\n  size_t after_chunk_index_;\n  absl::Span<uint32_t> data_;\n};\n\n// Count the number of leading zero bits.\nint LeadingZeros(uint64_t v) { return countl_zero(v); }\nint LeadingZeros(uint128 v) {\n  auto high = static_cast<uint64_t>(v >> 64);\n  auto low = static_cast<uint64_t>(v);\n  return high != 0 ? countl_zero(high) : 64 + countl_zero(low);\n}\n\n// Round up the text digits starting at `p`.\n// The buffer must have an extra digit that is known to not need rounding.\n// This is done below by having an extra '0' digit on the left.\nvoid RoundUp(char *p) {\n  while (*p == '9' || *p == '.') {\n    if (*p == '9') *p = '0';\n    --p;\n  }\n  ++*p;\n}\n\n// Check the previous digit and round up or down to follow the round-to-even\n// policy.\nvoid RoundToEven(char *p) {\n  if (*p == '.') --p;\n  if (*p % 2 == 1) RoundUp(p);\n}\n\n// Simple integral decimal digit printing for values that fit in 64-bits.\n// Returns the pointer to the last written digit.\nchar *PrintIntegralDigitsFromRightFast(uint64_t v, char *p) {\n  do {\n    *--p = DivideBy10WithCarry(&v, 0) + '0';\n  } while (v != 0);\n  return p;\n}\n\n// Simple integral decimal digit printing for values that fit in 128-bits.\n// Returns the pointer to the last written digit.\nchar *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {\n  auto high = static_cast<uint64_t>(v >> 64);\n  auto low = static_cast<uint64_t>(v);\n\n  while (high != 0) {\n    char carry = DivideBy10WithCarry(&high, 0);\n    carry = DivideBy10WithCarry(&low, carry);\n    *--p = carry + '0';\n  }\n  return PrintIntegralDigitsFromRightFast(low, p);\n}\n\n// Simple fractional decimal digit printing for values that fir in 64-bits after\n// shifting.\n// Performs rounding if necessary to fit within `precision`.\n// Returns the pointer to one after the last character written.\nchar* PrintFractionalDigitsFast(uint64_t v,\n                                char* start,\n                                int exp,\n                                size_t precision) {\n  char *p = start;\n  v <<= (64 - exp);\n  while (precision > 0) {\n    if (!v) return p;\n    *p++ = MultiplyBy10WithCarry(&v, 0) + '0';\n    --precision;\n  }\n\n  // We need to round.\n  if (v < 0x8000000000000000) {\n    // We round down, so nothing to do.\n  } else if (v > 0x8000000000000000) {\n    // We round up.\n    RoundUp(p - 1);\n  } else {\n    RoundToEven(p - 1);\n  }\n\n  return p;\n}\n\n// Simple fractional decimal digit printing for values that fir in 128-bits\n// after shifting.\n// Performs rounding if necessary to fit within `precision`.\n// Returns the pointer to one after the last character written.\nchar* PrintFractionalDigitsFast(uint128 v,\n                                char* start,\n                                int exp,\n                                size_t precision) {\n  char *p = start;\n  v <<= (128 - exp);\n  auto high = static_cast<uint64_t>(v >> 64);\n  auto low = static_cast<uint64_t>(v);\n\n  // While we have digits to print and `low` is not empty, do the long\n  // multiplication.\n  while (precision > 0 && low != 0) {\n    char carry = MultiplyBy10WithCarry(&low, 0);\n    carry = MultiplyBy10WithCarry(&high, carry);\n\n    *p++ = carry + '0';\n    --precision;\n  }\n\n  // Now `low` is empty, so use a faster approach for the rest of the digits.\n  // This block is pretty much the same as the main loop for the 64-bit case\n  // above.\n  while (precision > 0) {\n    if (!high) return p;\n    *p++ = MultiplyBy10WithCarry(&high, 0) + '0';\n    --precision;\n  }\n\n  // We need to round.\n  if (high < 0x8000000000000000) {\n    // We round down, so nothing to do.\n  } else if (high > 0x8000000000000000 || low != 0) {\n    // We round up.\n    RoundUp(p - 1);\n  } else {\n    RoundToEven(p - 1);\n  }\n\n  return p;\n}\n\nstruct FractionalDigitPrinterResult {\n  char* end;\n  size_t skipped_zeros;\n  bool nonzero_remainder;\n};\n\nFractionalDigitPrinterResult PrintFractionalDigitsScientific(\n    uint64_t v, char* start, int exp, size_t precision, bool skip_zeros) {\n  char* p = start;\n  v <<= (64 - exp);\n\n  size_t skipped_zeros = 0;\n  while (v != 0 && precision > 0) {\n    char carry = MultiplyBy10WithCarry(&v, 0);\n    if (skip_zeros) {\n      if (carry == 0) {\n        ++skipped_zeros;\n        continue;\n      }\n      skip_zeros = false;\n    }\n    *p++ = carry + '0';\n    --precision;\n  }\n  return {p, skipped_zeros, v != 0};\n}\n\nFractionalDigitPrinterResult PrintFractionalDigitsScientific(\n    uint128 v, char* start, int exp, size_t precision, bool skip_zeros) {\n  char* p = start;\n  v <<= (128 - exp);\n  auto high = static_cast<uint64_t>(v >> 64);\n  auto low = static_cast<uint64_t>(v);\n\n  size_t skipped_zeros = 0;\n  while (precision > 0 && low != 0) {\n    char carry = MultiplyBy10WithCarry(&low, 0);\n    carry = MultiplyBy10WithCarry(&high, carry);\n    if (skip_zeros) {\n      if (carry == 0) {\n        ++skipped_zeros;\n        continue;\n      }\n      skip_zeros = false;\n    }\n    *p++ = carry + '0';\n    --precision;\n  }\n\n  while (precision > 0 && high != 0) {\n    char carry = MultiplyBy10WithCarry(&high, 0);\n    if (skip_zeros) {\n      if (carry == 0) {\n        ++skipped_zeros;\n        continue;\n      }\n      skip_zeros = false;\n    }\n    *p++ = carry + '0';\n    --precision;\n  }\n\n  return {p, skipped_zeros, high != 0 || low != 0};\n}\n\nstruct FormatState {\n  char sign_char;\n  size_t precision;\n  const FormatConversionSpecImpl &conv;\n  FormatSinkImpl *sink;\n\n  // In `alt` mode (flag #) we keep the `.` even if there are no fractional\n  // digits. In non-alt mode, we strip it.\n  bool ShouldPrintDot() const { return precision != 0 || conv.has_alt_flag(); }\n};\n\nstruct Padding {\n  size_t left_spaces;\n  size_t zeros;\n  size_t right_spaces;\n};\n\nPadding ExtraWidthToPadding(size_t total_size, const FormatState &state) {\n  if (state.conv.width() < 0 ||\n      static_cast<size_t>(state.conv.width()) <= total_size) {\n    return {0, 0, 0};\n  }\n  size_t missing_chars = static_cast<size_t>(state.conv.width()) - total_size;\n  if (state.conv.has_left_flag()) {\n    return {0, 0, missing_chars};\n  } else if (state.conv.has_zero_flag()) {\n    return {0, missing_chars, 0};\n  } else {\n    return {missing_chars, 0, 0};\n  }\n}\n\nvoid FinalPrint(const FormatState& state,\n                absl::string_view data,\n                size_t padding_offset,\n                size_t trailing_zeros,\n                absl::string_view data_postfix) {\n  if (state.conv.width() < 0) {\n    // No width specified. Fast-path.\n    if (state.sign_char != '\\0') state.sink->Append(1, state.sign_char);\n    state.sink->Append(data);\n    state.sink->Append(trailing_zeros, '0');\n    state.sink->Append(data_postfix);\n    return;\n  }\n\n  auto padding =\n      ExtraWidthToPadding((state.sign_char != '\\0' ? 1 : 0) + data.size() +\n                              data_postfix.size() + trailing_zeros,\n                          state);\n\n  state.sink->Append(padding.left_spaces, ' ');\n  if (state.sign_char != '\\0') state.sink->Append(1, state.sign_char);\n  // Padding in general needs to be inserted somewhere in the middle of `data`.\n  state.sink->Append(data.substr(0, padding_offset));\n  state.sink->Append(padding.zeros, '0');\n  state.sink->Append(data.substr(padding_offset));\n  state.sink->Append(trailing_zeros, '0');\n  state.sink->Append(data_postfix);\n  state.sink->Append(padding.right_spaces, ' ');\n}\n\n// Fastpath %f formatter for when the shifted value fits in a simple integral\n// type.\n// Prints `v*2^exp` with the options from `state`.\ntemplate <typename Int>\nvoid FormatFFast(Int v, int exp, const FormatState &state) {\n  constexpr int input_bits = sizeof(Int) * 8;\n\n  static constexpr size_t integral_size =\n      /* in case we need to round up an extra digit */ 1 +\n      /* decimal digits for uint128 */ 40 + 1;\n  char buffer[integral_size + /* . */ 1 + /* max digits uint128 */ 128];\n  buffer[integral_size] = '.';\n  char *const integral_digits_end = buffer + integral_size;\n  char *integral_digits_start;\n  char *const fractional_digits_start = buffer + integral_size + 1;\n  char *fractional_digits_end = fractional_digits_start;\n\n  if (exp >= 0) {\n    const int total_bits = input_bits - LeadingZeros(v) + exp;\n    integral_digits_start =\n        total_bits <= 64\n            ? PrintIntegralDigitsFromRightFast(static_cast<uint64_t>(v) << exp,\n                                               integral_digits_end)\n            : PrintIntegralDigitsFromRightFast(static_cast<uint128>(v) << exp,\n                                               integral_digits_end);\n  } else {\n    exp = -exp;\n\n    integral_digits_start = PrintIntegralDigitsFromRightFast(\n        exp < input_bits ? v >> exp : 0, integral_digits_end);\n    // PrintFractionalDigits may pull a carried 1 all the way up through the\n    // integral portion.\n    integral_digits_start[-1] = '0';\n\n    fractional_digits_end =\n        exp <= 64 ? PrintFractionalDigitsFast(v, fractional_digits_start, exp,\n                                              state.precision)\n                  : PrintFractionalDigitsFast(static_cast<uint128>(v),\n                                              fractional_digits_start, exp,\n                                              state.precision);\n    // There was a carry, so include the first digit too.\n    if (integral_digits_start[-1] != '0') --integral_digits_start;\n  }\n\n  size_t size =\n      static_cast<size_t>(fractional_digits_end - integral_digits_start);\n\n  // In `alt` mode (flag #) we keep the `.` even if there are no fractional\n  // digits. In non-alt mode, we strip it.\n  if (!state.ShouldPrintDot()) --size;\n  FinalPrint(state, absl::string_view(integral_digits_start, size),\n             /*padding_offset=*/0,\n             state.precision - static_cast<size_t>(fractional_digits_end -\n                                                   fractional_digits_start),\n             /*data_postfix=*/\"\");\n}\n\n// Slow %f formatter for when the shifted value does not fit in a uint128, and\n// `exp > 0`.\n// Prints `v*2^exp` with the options from `state`.\n// This one is guaranteed to not have fractional digits, so we don't have to\n// worry about anything after the `.`.\nvoid FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {\n  BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {\n    const size_t total_digits =\n        btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0);\n\n    const auto padding = ExtraWidthToPadding(\n        total_digits + (state.sign_char != '\\0' ? 1 : 0), state);\n\n    state.sink->Append(padding.left_spaces, ' ');\n    if (state.sign_char != '\\0')\n      state.sink->Append(1, state.sign_char);\n    state.sink->Append(padding.zeros, '0');\n\n    do {\n      state.sink->Append(btd.CurrentDigits());\n    } while (btd.AdvanceDigits());\n\n    if (state.ShouldPrintDot())\n      state.sink->Append(1, '.');\n    state.sink->Append(state.precision, '0');\n    state.sink->Append(padding.right_spaces, ' ');\n  });\n}\n\n// Slow %f formatter for when the shifted value does not fit in a uint128, and\n// `exp < 0`.\n// Prints `v*2^exp` with the options from `state`.\n// This one is guaranteed to be < 1.0, so we don't have to worry about integral\n// digits.\nvoid FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {\n  const size_t total_digits =\n      /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0);\n  auto padding =\n      ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);\n  padding.zeros += 1;\n  state.sink->Append(padding.left_spaces, ' ');\n  if (state.sign_char != '\\0') state.sink->Append(1, state.sign_char);\n  state.sink->Append(padding.zeros, '0');\n\n  if (state.ShouldPrintDot()) state.sink->Append(1, '.');\n\n  // Print digits\n  size_t digits_to_go = state.precision;\n\n  FractionalDigitGenerator::RunConversion(\n      v, exp, [&](FractionalDigitGenerator digit_gen) {\n        // There are no digits to print here.\n        if (state.precision == 0) return;\n\n        // We go one digit at a time, while keeping track of runs of nines.\n        // The runs of nines are used to perform rounding when necessary.\n\n        while (digits_to_go > 0 && digit_gen.HasMoreDigits()) {\n          auto digits = digit_gen.GetDigits();\n\n          // Now we have a digit and a run of nines.\n          // See if we can print them all.\n          if (digits.num_nines + 1 < digits_to_go) {\n            // We don't have to round yet, so print them.\n            state.sink->Append(1, digits.digit_before_nine + '0');\n            state.sink->Append(digits.num_nines, '9');\n            digits_to_go -= digits.num_nines + 1;\n\n          } else {\n            // We can't print all the nines, see where we have to truncate.\n\n            bool round_up = false;\n            if (digits.num_nines + 1 > digits_to_go) {\n              // We round up at a nine. No need to print them.\n              round_up = true;\n            } else {\n              // We can fit all the nines, but truncate just after it.\n              if (digit_gen.IsGreaterThanHalf()) {\n                round_up = true;\n              } else if (digit_gen.IsExactlyHalf()) {\n                // Round to even\n                round_up =\n                    digits.num_nines != 0 || digits.digit_before_nine % 2 == 1;\n              }\n            }\n\n            if (round_up) {\n              state.sink->Append(1, digits.digit_before_nine + '1');\n              --digits_to_go;\n              // The rest will be zeros.\n            } else {\n              state.sink->Append(1, digits.digit_before_nine + '0');\n              state.sink->Append(digits_to_go - 1, '9');\n              digits_to_go = 0;\n            }\n            return;\n          }\n        }\n      });\n\n  state.sink->Append(digits_to_go, '0');\n  state.sink->Append(padding.right_spaces, ' ');\n}\n\ntemplate <typename Int>\nvoid FormatF(Int mantissa, int exp, const FormatState &state) {\n  if (exp >= 0) {\n    const int total_bits =\n        static_cast<int>(sizeof(Int) * 8) - LeadingZeros(mantissa) + exp;\n\n    // Fallback to the slow stack-based approach if we can't do it in a 64 or\n    // 128 bit state.\n    if (ABSL_PREDICT_FALSE(total_bits > 128)) {\n      return FormatFPositiveExpSlow(mantissa, exp, state);\n    }\n  } else {\n    // Fallback to the slow stack-based approach if we can't do it in a 64 or\n    // 128 bit state.\n    if (ABSL_PREDICT_FALSE(exp < -128)) {\n      return FormatFNegativeExpSlow(mantissa, -exp, state);\n    }\n  }\n  return FormatFFast(mantissa, exp, state);\n}\n\n// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to\n// bits 4-7.\ntemplate <typename Int>\nuint8_t GetNibble(Int n, size_t nibble_index) {\n  constexpr Int mask_low_nibble = Int{0xf};\n  int shift = static_cast<int>(nibble_index * 4);\n  n &= mask_low_nibble << shift;\n  return static_cast<uint8_t>((n >> shift) & 0xf);\n}\n\n// Add one to the given nibble, applying carry to higher nibbles. Returns true\n// if overflow, false otherwise.\ntemplate <typename Int>\nbool IncrementNibble(size_t nibble_index, Int* n) {\n  constexpr size_t kShift = sizeof(Int) * 8 - 1;\n  constexpr size_t kNumNibbles = sizeof(Int) * 8 / 4;\n  Int before = *n >> kShift;\n  // Here we essentially want to take the number 1 and move it into the\n  // requested nibble, then add it to *n to effectively increment the nibble.\n  // However, ASan will complain if we try to shift the 1 beyond the limits of\n  // the Int, i.e., if the nibble_index is out of range. So therefore we check\n  // for this and if we are out of range we just add 0 which leaves *n\n  // unchanged, which seems like the reasonable thing to do in that case.\n  *n += ((nibble_index >= kNumNibbles)\n             ? 0\n             : (Int{1} << static_cast<int>(nibble_index * 4)));\n  Int after = *n >> kShift;\n  return (before && !after) || (nibble_index >= kNumNibbles);\n}\n\n// Return a mask with 1's in the given nibble and all lower nibbles.\ntemplate <typename Int>\nInt MaskUpToNibbleInclusive(size_t nibble_index) {\n  constexpr size_t kNumNibbles = sizeof(Int) * 8 / 4;\n  static const Int ones = ~Int{0};\n  ++nibble_index;\n  return ones >> static_cast<int>(\n                     4 * (std::max(kNumNibbles, nibble_index) - nibble_index));\n}\n\n// Return a mask with 1's below the given nibble.\ntemplate <typename Int>\nInt MaskUpToNibbleExclusive(size_t nibble_index) {\n  return nibble_index == 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);\n}\n\ntemplate <typename Int>\nInt MoveToNibble(uint8_t nibble, size_t nibble_index) {\n  return Int{nibble} << static_cast<int>(4 * nibble_index);\n}\n\n// Given mantissa size, find optimal # of mantissa bits to put in initial digit.\n//\n// In the hex representation we keep a single hex digit to the left of the dot.\n// However, the question as to how many bits of the mantissa should be put into\n// that hex digit in theory is arbitrary, but in practice it is optimal to\n// choose based on the size of the mantissa. E.g., for a `double`, there are 53\n// mantissa bits, so that means that we should put 1 bit to the left of the dot,\n// thereby leaving 52 bits to the right, which is evenly divisible by four and\n// thus all fractional digits represent actual precision. For a `long double`,\n// on the other hand, there are 64 bits of mantissa, thus we can use all four\n// bits for the initial hex digit and still have a number left over (60) that is\n// a multiple of four. Once again, the goal is to have all fractional digits\n// represent real precision.\ntemplate <typename Float>\nconstexpr size_t HexFloatLeadingDigitSizeInBits() {\n  return std::numeric_limits<Float>::digits % 4 > 0\n             ? static_cast<size_t>(std::numeric_limits<Float>::digits % 4)\n             : size_t{4};\n}\n\n// This function captures the rounding behavior of glibc for hex float\n// representations. E.g. when rounding 0x1.ab800000 to a precision of .2\n// (\"%.2a\") glibc will round up because it rounds toward the even number (since\n// 0xb is an odd number, it will round up to 0xc). However, when rounding at a\n// point that is not followed by 800000..., it disregards the parity and rounds\n// up if > 8 and rounds down if < 8.\ntemplate <typename Int>\nbool HexFloatNeedsRoundUp(Int mantissa,\n                          size_t final_nibble_displayed,\n                          uint8_t leading) {\n  // If the last nibble (hex digit) to be displayed is the lowest on in the\n  // mantissa then that means that we don't have any further nibbles to inform\n  // rounding, so don't round.\n  if (final_nibble_displayed == 0) {\n    return false;\n  }\n  size_t rounding_nibble_idx = final_nibble_displayed - 1;\n  constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;\n  assert(final_nibble_displayed <= kTotalNibbles);\n  Int mantissa_up_to_rounding_nibble_inclusive =\n      mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);\n  Int eight = MoveToNibble<Int>(8, rounding_nibble_idx);\n  if (mantissa_up_to_rounding_nibble_inclusive != eight) {\n    return mantissa_up_to_rounding_nibble_inclusive > eight;\n  }\n  // Nibble in question == 8.\n  uint8_t round_if_odd = (final_nibble_displayed == kTotalNibbles)\n                             ? leading\n                             : GetNibble(mantissa, final_nibble_displayed);\n  return round_if_odd % 2 == 1;\n}\n\n// Stores values associated with a Float type needed by the FormatA\n// implementation in order to avoid templatizing that function by the Float\n// type.\nstruct HexFloatTypeParams {\n  template <typename Float>\n  explicit HexFloatTypeParams(Float)\n      : min_exponent(std::numeric_limits<Float>::min_exponent - 1),\n        leading_digit_size_bits(HexFloatLeadingDigitSizeInBits<Float>()) {\n    assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4);\n  }\n\n  int min_exponent;\n  size_t leading_digit_size_bits;\n};\n\n// Hex Float Rounding. First check if we need to round; if so, then we do that\n// by manipulating (incrementing) the mantissa, that way we can later print the\n// mantissa digits by iterating through them in the same way regardless of\n// whether a rounding happened.\ntemplate <typename Int>\nvoid FormatARound(bool precision_specified, const FormatState &state,\n                  uint8_t *leading, Int *mantissa, int *exp) {\n  constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;\n  // Index of the last nibble that we could display given precision.\n  size_t final_nibble_displayed =\n      precision_specified\n          ? (std::max(kTotalNibbles, state.precision) - state.precision)\n          : 0;\n  if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {\n    // Need to round up.\n    bool overflow = IncrementNibble(final_nibble_displayed, mantissa);\n    *leading += (overflow ? 1 : 0);\n    if (ABSL_PREDICT_FALSE(*leading > 15)) {\n      // We have overflowed the leading digit. This would mean that we would\n      // need two hex digits to the left of the dot, which is not allowed. So\n      // adjust the mantissa and exponent so that the result is always 1.0eXXX.\n      *leading = 1;\n      *mantissa = 0;\n      *exp += 4;\n    }\n  }\n  // Now that we have handled a possible round-up we can go ahead and zero out\n  // all the nibbles of the mantissa that we won't need.\n  if (precision_specified) {\n    *mantissa &= ~MaskUpToNibbleExclusive<Int>(final_nibble_displayed);\n  }\n}\n\ntemplate <typename Int>\nvoid FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,\n                      Int *mantissa, int *exp) {\n  constexpr size_t kIntBits = sizeof(Int) * 8;\n  static const Int kHighIntBit = Int{1} << (kIntBits - 1);\n  const size_t kLeadDigitBitsCount = float_traits.leading_digit_size_bits;\n  // Normalize mantissa so that highest bit set is in MSB position, unless we\n  // get interrupted by the exponent threshold.\n  while (*mantissa && !(*mantissa & kHighIntBit)) {\n    if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) {\n      *mantissa >>= (float_traits.min_exponent - *exp);\n      *exp = float_traits.min_exponent;\n      return;\n    }\n    *mantissa <<= 1;\n    --*exp;\n  }\n  // Extract bits for leading digit then shift them away leaving the\n  // fractional part.\n  *leading = static_cast<uint8_t>(\n      *mantissa >> static_cast<int>(kIntBits - kLeadDigitBitsCount));\n  *exp -= (*mantissa != 0) ? static_cast<int>(kLeadDigitBitsCount) : *exp;\n  *mantissa <<= static_cast<int>(kLeadDigitBitsCount);\n}\n\ntemplate <typename Int>\nvoid FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,\n             bool uppercase, const FormatState &state) {\n  // Int properties.\n  constexpr size_t kIntBits = sizeof(Int) * 8;\n  constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;\n  // Did the user specify a precision explicitly?\n  const bool precision_specified = state.conv.precision() >= 0;\n\n  // ========== Normalize/Denormalize ==========\n  exp += kIntBits;  // make all digits fractional digits.\n  // This holds the (up to four) bits of leading digit, i.e., the '1' in the\n  // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal.\n  uint8_t leading = 0;\n  FormatANormalize(float_traits, &leading, &mantissa, &exp);\n\n  // =============== Rounding ==================\n  // Check if we need to round; if so, then we do that by manipulating\n  // (incrementing) the mantissa before beginning to print characters.\n  FormatARound(precision_specified, state, &leading, &mantissa, &exp);\n\n  // ============= Format Result ===============\n  // This buffer holds the \"0x1.ab1de3\" portion of \"0x1.ab1de3pe+2\". Compute the\n  // size with long double which is the largest of the floats.\n  constexpr size_t kBufSizeForHexFloatRepr =\n      2                                                // 0x\n      + std::numeric_limits<MaxFloatType>::digits / 4  // number of hex digits\n      + 1                                              // round up\n      + 1;                                             // \".\" (dot)\n  char digits_buffer[kBufSizeForHexFloatRepr];\n  char *digits_iter = digits_buffer;\n  const char *const digits =\n      static_cast<const char *>(\"0123456789ABCDEF0123456789abcdef\") +\n      (uppercase ? 0 : 16);\n\n  // =============== Hex Prefix ================\n  *digits_iter++ = '0';\n  *digits_iter++ = uppercase ? 'X' : 'x';\n\n  // ========== Non-Fractional Digit ===========\n  *digits_iter++ = digits[leading];\n\n  // ================== Dot ====================\n  // There are three reasons we might need a dot. Keep in mind that, at this\n  // point, the mantissa holds only the fractional part.\n  if ((precision_specified && state.precision > 0) ||\n      (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) {\n    *digits_iter++ = '.';\n  }\n\n  // ============ Fractional Digits ============\n  size_t digits_emitted = 0;\n  while (mantissa > 0) {\n    *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];\n    mantissa <<= 4;\n    ++digits_emitted;\n  }\n  size_t trailing_zeros = 0;\n  if (precision_specified) {\n    assert(state.precision >= digits_emitted);\n    trailing_zeros = state.precision - digits_emitted;\n  }\n  auto digits_result = string_view(\n      digits_buffer, static_cast<size_t>(digits_iter - digits_buffer));\n\n  // =============== Exponent ==================\n  constexpr size_t kBufSizeForExpDecRepr =\n      numbers_internal::kFastToBufferSize  // required for FastIntToBuffer\n      + 1                                  // 'p' or 'P'\n      + 1;                                 // '+' or '-'\n  char exp_buffer[kBufSizeForExpDecRepr];\n  exp_buffer[0] = uppercase ? 'P' : 'p';\n  exp_buffer[1] = exp >= 0 ? '+' : '-';\n  numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);\n\n  // ============ Assemble Result ==============\n  FinalPrint(state,\n             digits_result,                        // 0xN.NNN...\n             2,                                    // offset of any padding\n             static_cast<size_t>(trailing_zeros),  // remaining mantissa padding\n             exp_buffer);                          // exponent\n}\n\nchar *CopyStringTo(absl::string_view v, char *out) {\n  std::memcpy(out, v.data(), v.size());\n  return out + v.size();\n}\n\ntemplate <typename Float>\nbool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,\n                        FormatSinkImpl *sink) {\n  int w = conv.width() >= 0 ? conv.width() : 0;\n  int p = conv.precision() >= 0 ? conv.precision() : -1;\n  char fmt[32];\n  {\n    char *fp = fmt;\n    *fp++ = '%';\n    fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);\n    fp = CopyStringTo(\"*.*\", fp);\n    if (std::is_same<long double, Float>()) {\n      *fp++ = 'L';\n    }\n    *fp++ = FormatConversionCharToChar(conv.conversion_char());\n    *fp = 0;\n    assert(fp < fmt + sizeof(fmt));\n  }\n  std::string space(512, '\\0');\n  absl::string_view result;\n  while (true) {\n    int n = snprintf(&space[0], space.size(), fmt, w, p, v);\n    if (n < 0) return false;\n    if (static_cast<size_t>(n) < space.size()) {\n      result = absl::string_view(space.data(), static_cast<size_t>(n));\n      break;\n    }\n    space.resize(static_cast<size_t>(n) + 1);\n  }\n  sink->Append(result);\n  return true;\n}\n\n// 128-bits in decimal: ceil(128*log(2)/log(10))\n//   or std::numeric_limits<__uint128_t>::digits10\nconstexpr size_t kMaxFixedPrecision = 39;\n\nconstexpr size_t kBufferLength = /*sign*/ 1 +\n                                 /*integer*/ kMaxFixedPrecision +\n                                 /*point*/ 1 +\n                                 /*fraction*/ kMaxFixedPrecision +\n                                 /*exponent e+123*/ 5;\n\nstruct Buffer {\n  void push_front(char c) {\n    assert(begin > data);\n    *--begin = c;\n  }\n  void push_back(char c) {\n    assert(end < data + sizeof(data));\n    *end++ = c;\n  }\n  void pop_back() {\n    assert(begin < end);\n    --end;\n  }\n\n  char &back() const {\n    assert(begin < end);\n    return end[-1];\n  }\n\n  char last_digit() const { return end[-1] == '.' ? end[-2] : end[-1]; }\n\n  size_t size() const { return static_cast<size_t>(end - begin); }\n\n  char data[kBufferLength];\n  char *begin;\n  char *end;\n};\n\nenum class FormatStyle { Fixed, Precision };\n\n// If the value is Inf or Nan, print it and return true.\n// Otherwise, return false.\ntemplate <typename Float>\nbool ConvertNonNumericFloats(char sign_char, Float v,\n                             const FormatConversionSpecImpl &conv,\n                             FormatSinkImpl *sink) {\n  char text[4], *ptr = text;\n  if (sign_char != '\\0') *ptr++ = sign_char;\n  if (std::isnan(v)) {\n    ptr = std::copy_n(\n        FormatConversionCharIsUpper(conv.conversion_char()) ? \"NAN\" : \"nan\", 3,\n        ptr);\n  } else if (std::isinf(v)) {\n    ptr = std::copy_n(\n        FormatConversionCharIsUpper(conv.conversion_char()) ? \"INF\" : \"inf\", 3,\n        ptr);\n  } else {\n    return false;\n  }\n\n  return sink->PutPaddedString(\n      string_view(text, static_cast<size_t>(ptr - text)), conv.width(), -1,\n      conv.has_left_flag());\n}\n\n// Round up the last digit of the value.\n// It will carry over and potentially overflow. 'exp' will be adjusted in that\n// case.\ntemplate <FormatStyle mode>\nvoid RoundUp(Buffer *buffer, int *exp) {\n  char *p = &buffer->back();\n  while (p >= buffer->begin && (*p == '9' || *p == '.')) {\n    if (*p == '9') *p = '0';\n    --p;\n  }\n\n  if (p < buffer->begin) {\n    *p = '1';\n    buffer->begin = p;\n    if (mode == FormatStyle::Precision) {\n      std::swap(p[1], p[2]);  // move the .\n      ++*exp;\n      buffer->pop_back();\n    }\n  } else {\n    ++*p;\n  }\n}\n\nvoid PrintExponent(int exp, char e, Buffer *out) {\n  out->push_back(e);\n  if (exp < 0) {\n    out->push_back('-');\n    exp = -exp;\n  } else {\n    out->push_back('+');\n  }\n  // Exponent digits.\n  if (exp > 99) {\n    out->push_back(static_cast<char>(exp / 100 + '0'));\n    out->push_back(static_cast<char>(exp / 10 % 10 + '0'));\n    out->push_back(static_cast<char>(exp % 10 + '0'));\n  } else {\n    out->push_back(static_cast<char>(exp / 10 + '0'));\n    out->push_back(static_cast<char>(exp % 10 + '0'));\n  }\n}\n\ntemplate <typename Float, typename Int>\nconstexpr bool CanFitMantissa() {\n  return\n#if defined(__clang__) && (__clang_major__ < 9) && !defined(__SSE3__)\n      // Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289\n      // Casting from long double to uint64_t is miscompiled and drops bits.\n      (!std::is_same<Float, long double>::value ||\n       !std::is_same<Int, uint64_t>::value) &&\n#endif\n      std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits;\n}\n\ntemplate <typename Float>\nstruct Decomposed {\n  using MantissaType =\n      absl::conditional_t<std::is_same<long double, Float>::value, uint128,\n                          uint64_t>;\n  static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,\n                \"\");\n  MantissaType mantissa;\n  int exponent;\n};\n\n// Decompose the double into an integer mantissa and an exponent.\ntemplate <typename Float>\nDecomposed<Float> Decompose(Float v) {\n  int exp;\n  Float m = std::frexp(v, &exp);\n  m = std::ldexp(m, std::numeric_limits<Float>::digits);\n  exp -= std::numeric_limits<Float>::digits;\n\n  return {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};\n}\n\n// Print 'digits' as decimal.\n// In Fixed mode, we add a '.' at the end.\n// In Precision mode, we add a '.' after the first digit.\ntemplate <FormatStyle mode, typename Int>\nsize_t PrintIntegralDigits(Int digits, Buffer* out) {\n  size_t printed = 0;\n  if (digits) {\n    for (; digits; digits /= 10) out->push_front(digits % 10 + '0');\n    printed = out->size();\n    if (mode == FormatStyle::Precision) {\n      out->push_front(*out->begin);\n      out->begin[1] = '.';\n    } else {\n      out->push_back('.');\n    }\n  } else if (mode == FormatStyle::Fixed) {\n    out->push_front('0');\n    out->push_back('.');\n    printed = 1;\n  }\n  return printed;\n}\n\n// Back out 'extra_digits' digits and round up if necessary.\nvoid RemoveExtraPrecision(size_t extra_digits,\n                          bool has_leftover_value,\n                          Buffer* out,\n                          int* exp_out) {\n  // Back out the extra digits\n  out->end -= extra_digits;\n\n  bool needs_to_round_up = [&] {\n    // We look at the digit just past the end.\n    // There must be 'extra_digits' extra valid digits after end.\n    if (*out->end > '5') return true;\n    if (*out->end < '5') return false;\n    if (has_leftover_value || std::any_of(out->end + 1, out->end + extra_digits,\n                                          [](char c) { return c != '0'; }))\n      return true;\n\n    // Ends in ...50*, round to even.\n    return out->last_digit() % 2 == 1;\n  }();\n\n  if (needs_to_round_up) {\n    RoundUp<FormatStyle::Precision>(out, exp_out);\n  }\n}\n\n// Print the value into the buffer.\n// This will not include the exponent, which will be returned in 'exp_out' for\n// Precision mode.\ntemplate <typename Int, typename Float, FormatStyle mode>\nbool FloatToBufferImpl(Int int_mantissa,\n                       int exp,\n                       size_t precision,\n                       Buffer* out,\n                       int* exp_out) {\n  assert((CanFitMantissa<Float, Int>()));\n\n  const int int_bits = std::numeric_limits<Int>::digits;\n\n  // In precision mode, we start printing one char to the right because it will\n  // also include the '.'\n  // In fixed mode we put the dot afterwards on the right.\n  out->begin = out->end =\n      out->data + 1 + kMaxFixedPrecision + (mode == FormatStyle::Precision);\n\n  if (exp >= 0) {\n    if (std::numeric_limits<Float>::digits + exp > int_bits) {\n      // The value will overflow the Int\n      return false;\n    }\n    size_t digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);\n    size_t digits_to_zero_pad = precision;\n    if (mode == FormatStyle::Precision) {\n      *exp_out = static_cast<int>(digits_printed - 1);\n      if (digits_to_zero_pad < digits_printed - 1) {\n        RemoveExtraPrecision(digits_printed - 1 - digits_to_zero_pad, false,\n                             out, exp_out);\n        return true;\n      }\n      digits_to_zero_pad -= digits_printed - 1;\n    }\n    for (; digits_to_zero_pad-- > 0;) out->push_back('0');\n    return true;\n  }\n\n  exp = -exp;\n  // We need at least 4 empty bits for the next decimal digit.\n  // We will multiply by 10.\n  if (exp > int_bits - 4) return false;\n\n  const Int mask = (Int{1} << exp) - 1;\n\n  // Print the integral part first.\n  size_t digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);\n  int_mantissa &= mask;\n\n  size_t fractional_count = precision;\n  if (mode == FormatStyle::Precision) {\n    if (digits_printed == 0) {\n      // Find the first non-zero digit, when in Precision mode.\n      *exp_out = 0;\n      if (int_mantissa) {\n        while (int_mantissa <= mask) {\n          int_mantissa *= 10;\n          --*exp_out;\n        }\n      }\n      out->push_front(static_cast<char>(int_mantissa >> exp) + '0');\n      out->push_back('.');\n      int_mantissa &= mask;\n    } else {\n      // We already have a digit, and a '.'\n      *exp_out = static_cast<int>(digits_printed - 1);\n      if (fractional_count < digits_printed - 1) {\n        // If we had enough digits, return right away.\n        // The code below will try to round again otherwise.\n        RemoveExtraPrecision(digits_printed - 1 - fractional_count,\n                             int_mantissa != 0, out, exp_out);\n        return true;\n      }\n      fractional_count -= digits_printed - 1;\n    }\n  }\n\n  auto get_next_digit = [&] {\n    int_mantissa *= 10;\n    char digit = static_cast<char>(int_mantissa >> exp);\n    int_mantissa &= mask;\n    return digit;\n  };\n\n  // Print fractional_count more digits, if available.\n  for (; fractional_count > 0; --fractional_count) {\n    out->push_back(get_next_digit() + '0');\n  }\n\n  char next_digit = get_next_digit();\n  if (next_digit > 5 ||\n      (next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) {\n    RoundUp<mode>(out, exp_out);\n  }\n\n  return true;\n}\n\ntemplate <FormatStyle mode, typename Float>\nbool FloatToBuffer(Decomposed<Float> decomposed,\n                   size_t precision,\n                   Buffer* out,\n                   int* exp) {\n  if (precision > kMaxFixedPrecision) return false;\n\n  // Try with uint64_t.\n  if (CanFitMantissa<Float, std::uint64_t>() &&\n      FloatToBufferImpl<std::uint64_t, Float, mode>(\n          static_cast<std::uint64_t>(decomposed.mantissa), decomposed.exponent,\n          precision, out, exp))\n    return true;\n\n#if defined(ABSL_HAVE_INTRINSIC_INT128)\n  // If that is not enough, try with __uint128_t.\n  return CanFitMantissa<Float, __uint128_t>() &&\n         FloatToBufferImpl<__uint128_t, Float, mode>(\n             static_cast<__uint128_t>(decomposed.mantissa), decomposed.exponent,\n             precision, out, exp);\n#endif\n  return false;\n}\n\nvoid WriteBufferToSink(char sign_char, absl::string_view str,\n                       const FormatConversionSpecImpl &conv,\n                       FormatSinkImpl *sink) {\n  size_t left_spaces = 0, zeros = 0, right_spaces = 0;\n  size_t missing_chars = 0;\n  if (conv.width() >= 0) {\n    const size_t conv_width_size_t = static_cast<size_t>(conv.width());\n    const size_t existing_chars =\n        str.size() + static_cast<size_t>(sign_char != 0);\n    if (conv_width_size_t > existing_chars)\n      missing_chars = conv_width_size_t - existing_chars;\n  }\n  if (conv.has_left_flag()) {\n    right_spaces = missing_chars;\n  } else if (conv.has_zero_flag()) {\n    zeros = missing_chars;\n  } else {\n    left_spaces = missing_chars;\n  }\n\n  sink->Append(left_spaces, ' ');\n  if (sign_char != '\\0') sink->Append(1, sign_char);\n  sink->Append(zeros, '0');\n  sink->Append(str);\n  sink->Append(right_spaces, ' ');\n}\n\ntemplate <typename Int>\nvoid FormatE(Int mantissa, int exp, bool uppercase, const FormatState& state) {\n  if (exp > 0) {\n    const int total_bits =\n        static_cast<int>(sizeof(Int) * 8) - LeadingZeros(mantissa) + exp;\n    if (total_bits > 128) {\n      FormatEPositiveExpSlow(mantissa, exp, uppercase, state);\n      return;\n    }\n  } else {\n    if (ABSL_PREDICT_FALSE(exp < -128)) {\n      FormatENegativeExpSlow(mantissa, exp, uppercase, state);\n      return;\n    }\n  }\n  FormatEFast(mantissa, exp, uppercase, state);\n}\n\n// Guaranteed to fit into 128 bits at this point\ntemplate <typename Int>\nvoid FormatEFast(Int v, int exp, bool uppercase, const FormatState& state) {\n  if (!v) {\n    absl::string_view mantissa_str = state.ShouldPrintDot() ? \"0.\" : \"0\";\n    FinalPrint(state, mantissa_str, 0, state.precision,\n               uppercase ? \"E+00\" : \"e+00\");\n    return;\n  }\n  constexpr int kInputBits = sizeof(Int) * 8;\n  constexpr int kMaxFractionalDigits = 128;\n  constexpr int kBufferSize = 2 +                    // '.' + rounding\n                              kMaxFixedPrecision +   // Integral\n                              kMaxFractionalDigits;  // Fractional\n  const int total_bits = kInputBits - LeadingZeros(v) + exp;\n  char buffer[kBufferSize];\n  char* integral_start = buffer + 2;\n  char* integral_end = buffer + 2 + kMaxFixedPrecision;\n  char* final_start;\n  char* final_end;\n  bool zero_integral = false;\n  int scientific_exp = 0;\n  size_t digits_printed = 0;\n  size_t trailing_zeros = 0;\n  bool has_more_non_zero = false;\n\n  auto check_integral_zeros =\n      [](char* const begin, char* const end,\n         const size_t precision, size_t digits_processed) -> bool {\n    // When considering rounding to even, we care about the digits after the\n    // round digit which means the total digits to move from the start is\n    // precision + 2 since the first digit we print before the decimal point\n    // is not a part of precision.\n    size_t digit_upper_bound = precision + 2;\n    if (digits_processed > digit_upper_bound) {\n      return std::any_of(begin + digit_upper_bound, end,\n                         [](char c) { return c != '0'; });\n    }\n    return false;\n  };\n\n  if (exp >= 0) {\n    integral_end = total_bits <= 64 ? numbers_internal::FastIntToBuffer(\n                               static_cast<uint64_t>(v) << exp, integral_start)\n                         : numbers_internal::FastIntToBuffer(\n                               static_cast<uint128>(v) << exp, integral_start);\n    *integral_end = '0';\n    final_start = integral_start;\n    // Integral is guaranteed to be non-zero at this point.\n    scientific_exp = static_cast<int>(integral_end - integral_start) - 1;\n    digits_printed = static_cast<size_t>(integral_end - integral_start);\n    final_end = integral_end;\n    has_more_non_zero = check_integral_zeros(integral_start, integral_end,\n                                             state.precision, digits_printed);\n  } else {\n    exp = -exp;\n    if (exp < kInputBits) {\n      integral_end =\n          numbers_internal::FastIntToBuffer(v >> exp, integral_start);\n    }\n    *integral_end = '0';\n    // We didn't move integral_start and it gets set to 0 in\n    zero_integral = exp >= kInputBits || v >> exp == 0;\n    if (!zero_integral) {\n      digits_printed = static_cast<size_t>(integral_end - integral_start);\n      has_more_non_zero = check_integral_zeros(integral_start, integral_end,\n                                               state.precision, digits_printed);\n      final_end = integral_end;\n    }\n    // Print fractional digits\n    char* fractional_start = integral_end;\n\n    size_t digits_to_print = (state.precision + 1) >= digits_printed\n                                 ? state.precision + 1 - digits_printed\n                                 : 0;\n    bool print_extra = digits_printed <= state.precision + 1;\n    auto [fractional_end, skipped_zeros, has_nonzero_rem] =\n        exp <= 64 ? PrintFractionalDigitsScientific(\n                        v, fractional_start, exp, digits_to_print + print_extra,\n                        zero_integral)\n                  : PrintFractionalDigitsScientific(\n                        static_cast<uint128>(v), fractional_start, exp,\n                        digits_to_print + print_extra, zero_integral);\n    final_end = fractional_end;\n    *fractional_end = '0';\n    has_more_non_zero |= has_nonzero_rem;\n    digits_printed += static_cast<size_t>(fractional_end - fractional_start);\n    if (zero_integral) {\n      scientific_exp = -1 * static_cast<int>(skipped_zeros + 1);\n    } else {\n      scientific_exp = static_cast<int>(integral_end - integral_start) - 1;\n    }\n    // Don't do any rounding here, we will do it ourselves.\n    final_start = zero_integral ? fractional_start : integral_start;\n  }\n\n  // For rounding\n  if (digits_printed >= state.precision + 1) {\n    final_start[-1] = '0';\n    char* round_digit_ptr = final_start + 1 + state.precision;\n    if (*round_digit_ptr > '5') {\n      RoundUp(round_digit_ptr - 1);\n    } else if (*round_digit_ptr == '5') {\n      if (has_more_non_zero) {\n        RoundUp(round_digit_ptr - 1);\n      } else {\n        RoundToEven(round_digit_ptr - 1);\n      }\n    }\n    final_end = round_digit_ptr;\n    if (final_start[-1] == '1') {\n      --final_start;\n      ++scientific_exp;\n      --final_end;\n    }\n  } else {\n    // Need to pad with zeros.\n    trailing_zeros = state.precision - (digits_printed - 1);\n  }\n\n  if (state.precision > 0 || state.ShouldPrintDot()) {\n    final_start[-1] = *final_start;\n    *final_start = '.';\n    --final_start;\n  }\n\n  // We need to add 2 to the buffer size for the +/- sign and the e\n  constexpr size_t kExpBufferSize = numbers_internal::kFastToBufferSize + 2;\n  char exp_buffer[kExpBufferSize];\n  char* exp_ptr_start = exp_buffer;\n  char* exp_ptr = exp_ptr_start;\n  *exp_ptr++ = uppercase ? 'E' : 'e';\n  if (scientific_exp >= 0) {\n    *exp_ptr++ = '+';\n  } else {\n    *exp_ptr++ = '-';\n    scientific_exp = -scientific_exp;\n  }\n\n  if (scientific_exp < 10) {\n    *exp_ptr++ = '0';\n  }\n  exp_ptr = numbers_internal::FastIntToBuffer(scientific_exp, exp_ptr);\n  FinalPrint(state,\n             absl::string_view(final_start,\n                               static_cast<size_t>(final_end - final_start)),\n             0, trailing_zeros,\n             absl::string_view(exp_ptr_start,\n                               static_cast<size_t>(exp_ptr - exp_ptr_start)));\n}\n\nvoid FormatENegativeExpSlow(uint128 mantissa, int exp, bool uppercase,\n                            const FormatState& state) {\n  assert(exp < 0);\n\n  FractionalDigitGenerator::RunConversion(\n      mantissa, -exp,\n      [&](FractionalDigitGenerator digit_gen) {\n        int first_digit = 0;\n        size_t nines = 0;\n        int num_leading_zeros = 0;\n        while (digit_gen.HasMoreDigits()) {\n          auto digits = digit_gen.GetDigits();\n          if (digits.digit_before_nine != 0) {\n            first_digit = digits.digit_before_nine;\n            nines = digits.num_nines;\n            break;\n          } else if (digits.num_nines > 0) {\n            // This also means the first digit is 0\n            first_digit = 9;\n            nines = digits.num_nines - 1;\n            num_leading_zeros++;\n            break;\n          }\n          num_leading_zeros++;\n        }\n\n        bool change_to_zeros = false;\n        if (nines >= state.precision || state.precision == 0) {\n          bool round_up = false;\n          if (nines == state.precision) {\n            round_up = digit_gen.IsGreaterThanHalf();\n          } else {\n            round_up = nines > 0 || digit_gen.IsGreaterThanHalf();\n          }\n          if (round_up) {\n            first_digit = (first_digit == 9 ? 1 : first_digit + 1);\n            num_leading_zeros -= (first_digit == 1);\n            change_to_zeros = true;\n          }\n        }\n        int scientific_exp = -(num_leading_zeros + 1);\n        assert(scientific_exp < 0);\n        char exp_buffer[numbers_internal::kFastToBufferSize];\n        char* exp_start = exp_buffer;\n        *exp_start++ = '-';\n        if (scientific_exp > -10) {\n          *exp_start++ = '0';\n        }\n        scientific_exp *= -1;\n        char* exp_end =\n            numbers_internal::FastIntToBuffer(scientific_exp, exp_start);\n        const size_t total_digits =\n            1                                   // First digit\n            + (state.ShouldPrintDot() ? 1 : 0)  // Decimal point\n            + state.precision                   // Digits after decimal\n            + 1                                 // 'e' or 'E'\n            + static_cast<size_t>(exp_end - exp_buffer);  // Exponent digits\n\n        const auto padding = ExtraWidthToPadding(\n            total_digits + (state.sign_char != '\\0' ? 1 : 0), state);\n        state.sink->Append(padding.left_spaces, ' ');\n\n        if (state.sign_char != '\\0') {\n          state.sink->Append(1, state.sign_char);\n        }\n\n        state.sink->Append(1, static_cast<char>(first_digit + '0'));\n        if (state.ShouldPrintDot()) {\n          state.sink->Append(1, '.');\n        }\n        size_t digits_to_go = state.precision;\n        size_t nines_to_print = std::min(nines, digits_to_go);\n        state.sink->Append(nines_to_print, change_to_zeros ? '0' : '9');\n        digits_to_go -= nines_to_print;\n        while (digits_to_go > 0 && digit_gen.HasMoreDigits()) {\n          auto digits = digit_gen.GetDigits();\n\n          if (digits.num_nines + 1 < digits_to_go) {\n            state.sink->Append(1, digits.digit_before_nine + '0');\n            state.sink->Append(digits.num_nines, '9');\n            digits_to_go -= digits.num_nines + 1;\n          } else {\n            bool round_up = false;\n            if (digits.num_nines + 1 > digits_to_go) {\n              round_up = true;\n            } else if (digit_gen.IsGreaterThanHalf()) {\n              round_up = true;\n            } else if (digit_gen.IsExactlyHalf()) {\n              round_up =\n                  digits.num_nines != 0 || digits.digit_before_nine % 2 == 1;\n            }\n            if (round_up) {\n              state.sink->Append(1, digits.digit_before_nine + '1');\n              --digits_to_go;\n            } else {\n              state.sink->Append(1, digits.digit_before_nine + '0');\n              state.sink->Append(digits_to_go - 1, '9');\n              digits_to_go = 0;\n            }\n            break;\n          }\n        }\n        state.sink->Append(digits_to_go, '0');\n        state.sink->Append(1, uppercase ? 'E' : 'e');\n        state.sink->Append(absl::string_view(\n            exp_buffer, static_cast<size_t>(exp_end - exp_buffer)));\n        state.sink->Append(padding.right_spaces, ' ');\n      });\n}\n\nstd::optional<int> GetOneDigit(BinaryToDecimal& btd,\n                               absl::string_view& digits_view) {\n  if (digits_view.empty()) {\n    if (!btd.AdvanceDigits()) return std::nullopt;\n    digits_view = btd.CurrentDigits();\n  }\n  char d = digits_view.front();\n  digits_view.remove_prefix(1);\n  return d - '0';\n}\n\nstruct DigitRun {\n  std::optional<int> digit;\n  size_t nines;\n};\n\nDigitRun GetDigits(BinaryToDecimal& btd, absl::string_view& digits_view) {\n  auto peek_digit = [&]() -> std::optional<int> {\n    if (digits_view.empty()) {\n      if (!btd.AdvanceDigits()) return std::nullopt;\n      digits_view = btd.CurrentDigits();\n    }\n    return digits_view.front() - '0';\n  };\n\n  auto digit_before_nines = GetOneDigit(btd, digits_view);\n  if (!digit_before_nines.has_value()) return {std::nullopt, 0};\n\n  auto next_digit = peek_digit();\n  size_t num_nines = 0;\n  while (next_digit == 9) {\n    // consume the 9\n    GetOneDigit(btd, digits_view);\n    ++num_nines;\n    next_digit = peek_digit();\n  }\n  return digit_before_nines == 9\n             ? DigitRun{std::nullopt, num_nines + 1}\n             : DigitRun{digit_before_nines, num_nines};\n}\n\nvoid FormatEPositiveExpSlow(uint128 mantissa, int exp, bool uppercase,\n                            const FormatState& state) {\n  BinaryToDecimal::RunConversion(\n      mantissa, exp, [&](BinaryToDecimal btd) {\n        int scientific_exp = static_cast<int>(btd.TotalDigits() - 1);\n        absl::string_view digits_view = btd.CurrentDigits();\n\n        size_t digits_to_go = state.precision + 1;\n        auto [first_digit_opt, nines] = GetDigits(btd, digits_view);\n        if (!first_digit_opt.has_value() && nines == 0) {\n          return;\n        }\n\n        int first_digit = first_digit_opt.value_or(9);\n        if (!first_digit_opt) {\n          --nines;\n        }\n\n        // At this point we are guaranteed to have some sort of first digit\n        bool change_to_zeros = false;\n        if (nines + 1 >= digits_to_go) {\n          // Everything we need to print is in the first DigitRun\n          auto next_digit_opt = GetDigits(btd, digits_view).digit;\n          if (nines == state.precision) {\n            change_to_zeros = next_digit_opt.value_or(0) > 4;\n          } else {\n            change_to_zeros = true;\n          }\n          if (change_to_zeros) {\n            if (first_digit != 9) {\n              first_digit = first_digit + 1;\n            } else {\n              first_digit = 1;\n              ++scientific_exp;\n            }\n          }\n        }\n\n        char exp_buffer[numbers_internal::kFastToBufferSize];\n        char* exp_buffer_end =\n            numbers_internal::FastIntToBuffer(scientific_exp, exp_buffer);\n        const size_t total_digits_out =\n            1 + state.ShouldPrintDot() + state.precision + 2 +\n            (static_cast<size_t>(exp_buffer_end - exp_buffer));\n\n        const auto padding = ExtraWidthToPadding(\n            total_digits_out + (state.sign_char != '\\0' ? 1 : 0), state);\n\n        state.sink->Append(padding.left_spaces, ' ');\n        if (state.sign_char != '\\0') {\n          state.sink->Append(1, state.sign_char);\n        }\n        state.sink->Append(1, static_cast<char>(first_digit + '0'));\n        --digits_to_go;\n        if (state.precision > 0 || state.ShouldPrintDot()) {\n          state.sink->Append(1, '.');\n        }\n        state.sink->Append(std::min(digits_to_go, nines),\n                           change_to_zeros ? '0' : '9');\n        digits_to_go -= std::min(digits_to_go, nines);\n        while (digits_to_go > 0) {\n          auto [digit_opt, curr_nines] = GetDigits(btd, digits_view);\n          if (!digit_opt.has_value()) break;\n          int digit = *digit_opt;\n          if (curr_nines + 1 < digits_to_go) {\n            state.sink->Append(1, static_cast<char>(digit + '0'));\n            state.sink->Append(curr_nines, '9');\n            digits_to_go -= curr_nines + 1;\n          } else {\n            bool need_round_up = false;\n            auto next_digit_opt = GetDigits(btd, digits_view).digit;\n            if (digits_to_go == 1) {\n              need_round_up = curr_nines > 0 || next_digit_opt > 4;\n            } else if (digits_to_go == curr_nines + 1) {\n              // Only round if next digit is > 4\n              need_round_up = next_digit_opt.value_or(0) > 4;\n            } else {\n              // we know we need to round since nine is after precision ends\n              need_round_up = true;\n            }\n            state.sink->Append(1,\n                               static_cast<char>(digit + need_round_up + '0'));\n            state.sink->Append(digits_to_go - 1, need_round_up ? '0' : '9');\n            digits_to_go = 0;\n          }\n        }\n\n        if (digits_to_go > 0) {\n          state.sink->Append(digits_to_go, '0');\n        }\n        state.sink->Append(1, uppercase ? 'E' : 'e');\n        state.sink->Append(1, scientific_exp >= 0 ? '+' : '-');\n        if (scientific_exp < 10) {\n          state.sink->Append(1, '0');\n        }\n        state.sink->Append(absl::string_view(\n            exp_buffer, static_cast<size_t>(exp_buffer_end - exp_buffer)));\n        state.sink->Append(padding.right_spaces, ' ');\n      });\n}\n\ntemplate <typename Float>\nbool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,\n                 FormatSinkImpl *sink) {\n  // Print the sign or the sign column.\n  Float abs_v = v;\n  char sign_char = 0;\n  if (std::signbit(abs_v)) {\n    sign_char = '-';\n    abs_v = -abs_v;\n  } else if (conv.has_show_pos_flag()) {\n    sign_char = '+';\n  } else if (conv.has_sign_col_flag()) {\n    sign_char = ' ';\n  }\n\n  // Print nan/inf.\n  if (ConvertNonNumericFloats(sign_char, abs_v, conv, sink)) {\n    return true;\n  }\n\n  size_t precision =\n      conv.precision() < 0 ? 6 : static_cast<size_t>(conv.precision());\n\n  int exp = 0;\n\n  auto decomposed = Decompose(abs_v);\n\n  Buffer buffer;\n\n  FormatConversionChar c = conv.conversion_char();\n\n  if (c == FormatConversionCharInternal::f ||\n      c == FormatConversionCharInternal::F) {\n    FormatF(decomposed.mantissa, decomposed.exponent,\n            {sign_char, precision, conv, sink});\n    return true;\n  } else if (c == FormatConversionCharInternal::e ||\n             c == FormatConversionCharInternal::E) {\n    FormatE(decomposed.mantissa, decomposed.exponent,\n            FormatConversionCharIsUpper(conv.conversion_char()),\n            {sign_char, precision, conv, sink});\n    return true;\n  } else if (c == FormatConversionCharInternal::g ||\n             c == FormatConversionCharInternal::G) {\n    precision = std::max(precision, size_t{1}) - 1;\n    if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,\n                                               &exp)) {\n      return FallbackToSnprintf(v, conv, sink);\n    }\n    if ((exp < 0 || precision + 1 > static_cast<size_t>(exp)) && exp >= -4) {\n      if (exp < 0) {\n        // Have 1.23456, needs 0.00123456\n        // Move the first digit\n        buffer.begin[1] = *buffer.begin;\n        // Add some zeros\n        for (; exp < -1; ++exp) *buffer.begin-- = '0';\n        *buffer.begin-- = '.';\n        *buffer.begin = '0';\n      } else if (exp > 0) {\n        // Have 1.23456, needs 1234.56\n        // Move the '.' exp positions to the right.\n        std::rotate(buffer.begin + 1, buffer.begin + 2, buffer.begin + exp + 2);\n      }\n      exp = 0;\n    }\n    if (!conv.has_alt_flag()) {\n      while (buffer.back() == '0') buffer.pop_back();\n      if (buffer.back() == '.') buffer.pop_back();\n    }\n    if (exp) {\n      PrintExponent(\n          exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',\n          &buffer);\n    }\n  } else if (c == FormatConversionCharInternal::a ||\n             c == FormatConversionCharInternal::A) {\n    bool uppercase = (c == FormatConversionCharInternal::A);\n    FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa,\n            decomposed.exponent, uppercase, {sign_char, precision, conv, sink});\n    return true;\n  } else {\n    return false;\n  }\n\n  WriteBufferToSink(\n      sign_char,\n      absl::string_view(buffer.begin,\n                        static_cast<size_t>(buffer.end - buffer.begin)),\n      conv, sink);\n\n  return true;\n}\n\n}  // namespace\n\nbool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,\n                      FormatSinkImpl *sink) {\n  if (IsDoubleDouble()) {\n    // This is the `double-double` representation of `long double`. We do not\n    // handle it natively. Fallback to snprintf.\n    return FallbackToSnprintf(v, conv, sink);\n  }\n\n  return FloatToSink(v, conv, sink);\n}\n\nbool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,\n                      FormatSinkImpl *sink) {\n  return FloatToSink(static_cast<double>(v), conv, sink);\n}\n\nbool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,\n                      FormatSinkImpl *sink) {\n  return FloatToSink(v, conv, sink);\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/float_conversion.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_\n\n#include \"absl/strings/internal/str_format/extension.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nbool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,\n                      FormatSinkImpl *sink);\n\nbool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,\n                      FormatSinkImpl *sink);\n\nbool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,\n                      FormatSinkImpl *sink);\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/output.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/output.h\"\n\n#include <errno.h>\n#include <cstring>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nnamespace {\nstruct ClearErrnoGuard {\n  ClearErrnoGuard() : old_value(errno) { errno = 0; }\n  ~ClearErrnoGuard() {\n    if (!errno) errno = old_value;\n  }\n  int old_value;\n};\n}  // namespace\n\nvoid BufferRawSink::Write(string_view v) {\n  size_t to_write = std::min(v.size(), size_);\n  if (to_write > 0) {\n    std::memcpy(buffer_, v.data(), to_write);\n    buffer_ += to_write;\n    size_ -= to_write;\n  }\n  total_written_ += v.size();\n}\n\nvoid FILERawSink::Write(string_view v) {\n  while (!v.empty() && !error_) {\n    // Reset errno to zero in case the libc implementation doesn't set errno\n    // when a failure occurs.\n    ClearErrnoGuard guard;\n\n    if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {\n      // Some progress was made.\n      count_ += result;\n      v.remove_prefix(result);\n    } else {\n      if (errno == EINTR) {\n        continue;\n      } else if (errno) {\n        error_ = errno;\n      } else if (std::ferror(output_)) {\n        // Non-POSIX compliant libc implementations may not set errno, so we\n        // have check the streams error indicator.\n        error_ = EBADF;\n      } else {\n        // We're likely on a non-POSIX system that encountered EINTR but had no\n        // way of reporting it.\n        continue;\n      }\n    }\n  }\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/output.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// Output extension hooks for the Format library.\n// `internal::InvokeFlush` calls the appropriate flush function for the\n// specified output argument.\n// `BufferRawSink` is a simple output sink for a char buffer. Used by SnprintF.\n// `FILERawSink` is a std::FILE* based sink. Used by PrintF and FprintF.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_\n\n#include <cstdio>\n#include <ios>\n#include <ostream>\n#include <string>\n\n#include \"absl/base/port.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\n// RawSink implementation that writes into a char* buffer.\n// It will not overflow the buffer, but will keep the total count of chars\n// that would have been written.\nclass BufferRawSink {\n public:\n  BufferRawSink(char* buffer, size_t size) : buffer_(buffer), size_(size) {}\n\n  size_t total_written() const { return total_written_; }\n  void Write(string_view v);\n\n private:\n  char* buffer_;\n  size_t size_;\n  size_t total_written_ = 0;\n};\n\n// RawSink implementation that writes into a FILE*.\n// It keeps track of the total number of bytes written and any error encountered\n// during the writes.\nclass FILERawSink {\n public:\n  explicit FILERawSink(std::FILE* output) : output_(output) {}\n\n  void Write(string_view v);\n\n  size_t count() const { return count_; }\n  int error() const { return error_; }\n\n private:\n  std::FILE* output_;\n  int error_ = 0;\n  size_t count_ = 0;\n};\n\n// Provide RawSink integration with common types from the STL.\ninline void AbslFormatFlush(std::string* out, string_view s) {\n  out->append(s.data(), s.size());\n}\ninline void AbslFormatFlush(std::ostream* out, string_view s) {\n  out->write(s.data(), static_cast<std::streamsize>(s.size()));\n}\n\ninline void AbslFormatFlush(FILERawSink* sink, string_view v) {\n  sink->Write(v);\n}\n\ninline void AbslFormatFlush(BufferRawSink* sink, string_view v) {\n  sink->Write(v);\n}\n\n// This is a SFINAE to get a better compiler error message when the type\n// is not supported.\ntemplate <typename T>\nauto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {\n  AbslFormatFlush(out, s);\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/output_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/output.h\"\n\n#include <sstream>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/cord.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nTEST(InvokeFlush, String) {\n  std::string str = \"ABC\";\n  str_format_internal::InvokeFlush(&str, \"DEF\");\n  EXPECT_EQ(str, \"ABCDEF\");\n}\n\nTEST(InvokeFlush, Stream) {\n  std::stringstream str;\n  str << \"ABC\";\n  str_format_internal::InvokeFlush(&str, \"DEF\");\n  EXPECT_EQ(str.str(), \"ABCDEF\");\n}\n\nTEST(InvokeFlush, Cord) {\n  absl::Cord str(\"ABC\");\n  str_format_internal::InvokeFlush(&str, \"DEF\");\n  EXPECT_EQ(str, \"ABCDEF\");\n}\n\nTEST(BufferRawSink, Limits) {\n  char buf[16];\n  {\n    std::fill(std::begin(buf), std::end(buf), 'x');\n    str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1);\n    str_format_internal::InvokeFlush(&bufsink, \"Hello World237\");\n    EXPECT_EQ(std::string(buf, sizeof(buf)), \"Hello World237xx\");\n  }\n  {\n    std::fill(std::begin(buf), std::end(buf), 'x');\n    str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1);\n    str_format_internal::InvokeFlush(&bufsink, \"Hello World237237\");\n    EXPECT_EQ(std::string(buf, sizeof(buf)), \"Hello World2372x\");\n  }\n  {\n    std::fill(std::begin(buf), std::end(buf), 'x');\n    str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1);\n    str_format_internal::InvokeFlush(&bufsink, \"Hello World\");\n    str_format_internal::InvokeFlush(&bufsink, \"237\");\n    EXPECT_EQ(std::string(buf, sizeof(buf)), \"Hello World237xx\");\n  }\n  {\n    std::fill(std::begin(buf), std::end(buf), 'x');\n    str_format_internal::BufferRawSink bufsink(buf, sizeof(buf) - 1);\n    str_format_internal::InvokeFlush(&bufsink, \"Hello World\");\n    str_format_internal::InvokeFlush(&bufsink, \"237237\");\n    EXPECT_EQ(std::string(buf, sizeof(buf)), \"Hello World2372x\");\n  }\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/parser.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/parser.h\"\n\n#include <assert.h>\n#include <string.h>\n#include <wchar.h>\n#include <cctype>\n#include <cstdint>\n\n#include <algorithm>\n#include <initializer_list>\n#include <limits>\n#include <ostream>\n#include <string>\n#include <unordered_set>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\n// Define the array for non-constexpr uses.\nconstexpr ConvTag ConvTagHolder::value[256];\n\nABSL_ATTRIBUTE_NOINLINE const char* ConsumeUnboundConversionNoInline(\n    const char* p, const char* end, UnboundConversion* conv, int* next_arg) {\n  return ConsumeUnboundConversion(p, end, conv, next_arg);\n}\n\nstd::string LengthModToString(LengthMod v) {\n  switch (v) {\n    case LengthMod::h:\n      return \"h\";\n    case LengthMod::hh:\n      return \"hh\";\n    case LengthMod::l:\n      return \"l\";\n    case LengthMod::ll:\n      return \"ll\";\n    case LengthMod::L:\n      return \"L\";\n    case LengthMod::j:\n      return \"j\";\n    case LengthMod::z:\n      return \"z\";\n    case LengthMod::t:\n      return \"t\";\n    case LengthMod::q:\n      return \"q\";\n    case LengthMod::none:\n      return \"\";\n  }\n  return \"\";\n}\n\nstruct ParsedFormatBase::ParsedFormatConsumer {\n  explicit ParsedFormatConsumer(ParsedFormatBase *parsedformat)\n      : parsed(parsedformat), data_pos(parsedformat->data_.get()) {}\n\n  bool Append(string_view s) {\n    if (s.empty()) return true;\n\n    size_t text_end = AppendText(s);\n\n    if (!parsed->items_.empty() && !parsed->items_.back().is_conversion) {\n      // Let's extend the existing text run.\n      parsed->items_.back().text_end = text_end;\n    } else {\n      // Let's make a new text run.\n      parsed->items_.push_back({false, text_end, {}});\n    }\n    return true;\n  }\n\n  bool ConvertOne(const UnboundConversion &conv, string_view s) {\n    size_t text_end = AppendText(s);\n    parsed->items_.push_back({true, text_end, conv});\n    return true;\n  }\n\n  size_t AppendText(string_view s) {\n    memcpy(data_pos, s.data(), s.size());\n    data_pos += s.size();\n    return static_cast<size_t>(data_pos - parsed->data_.get());\n  }\n\n  ParsedFormatBase *parsed;\n  char* data_pos;\n};\n\nParsedFormatBase::ParsedFormatBase(\n    string_view format, bool allow_ignored,\n    std::initializer_list<FormatConversionCharSet> convs)\n    : data_(format.empty() ? nullptr : new char[format.size()]) {\n  has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) ||\n               !MatchesConversions(allow_ignored, convs);\n}\n\nbool ParsedFormatBase::MatchesConversions(\n    bool allow_ignored,\n    std::initializer_list<FormatConversionCharSet> convs) const {\n  std::unordered_set<int> used;\n  auto add_if_valid_conv = [&](int pos, char c) {\n    if (static_cast<size_t>(pos) > convs.size() ||\n        !Contains(convs.begin()[pos - 1], c))\n      return false;\n    used.insert(pos);\n    return true;\n  };\n  for (const ConversionItem &item : items_) {\n    if (!item.is_conversion) continue;\n    auto &conv = item.conv;\n    if (conv.precision.is_from_arg() &&\n        !add_if_valid_conv(conv.precision.get_from_arg(), '*'))\n      return false;\n    if (conv.width.is_from_arg() &&\n        !add_if_valid_conv(conv.width.get_from_arg(), '*'))\n      return false;\n    if (!add_if_valid_conv(conv.arg_position,\n                           FormatConversionCharToChar(conv.conv)))\n      return false;\n  }\n  return used.size() == convs.size() || allow_ignored;\n}\n\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_format/parser.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_\n#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_\n\n#include <stddef.h>\n#include <stdlib.h>\n\n#include <cassert>\n#include <cstring>\n#include <initializer_list>\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/strings/internal/str_format/checker.h\"\n#include \"absl/strings/internal/str_format/constexpr_parser.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nstd::string LengthModToString(LengthMod v);\n\nconst char* ConsumeUnboundConversionNoInline(const char* p, const char* end,\n                                             UnboundConversion* conv,\n                                             int* next_arg);\n\n// Parse the format string provided in 'src' and pass the identified items into\n// 'consumer'.\n// Text runs will be passed by calling\n//   Consumer::Append(string_view);\n// ConversionItems will be passed by calling\n//   Consumer::ConvertOne(UnboundConversion, string_view);\n// In the case of ConvertOne, the string_view that is passed is the\n// portion of the format string corresponding to the conversion, not including\n// the leading %. On success, it returns true. On failure, it stops and returns\n// false.\ntemplate <typename Consumer>\nbool ParseFormatString(string_view src, Consumer consumer) {\n  int next_arg = 0;\n  const char* p = src.data();\n  const char* const end = p + src.size();\n  while (p != end) {\n    const char* percent =\n        static_cast<const char*>(memchr(p, '%', static_cast<size_t>(end - p)));\n    if (!percent) {\n      // We found the last substring.\n      return consumer.Append(string_view(p, static_cast<size_t>(end - p)));\n    }\n    // We found a percent, so push the text run then process the percent.\n    if (ABSL_PREDICT_FALSE(!consumer.Append(\n            string_view(p, static_cast<size_t>(percent - p))))) {\n      return false;\n    }\n    if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false;\n\n    auto tag = GetTagForChar(percent[1]);\n    if (tag.is_conv()) {\n      if (ABSL_PREDICT_FALSE(next_arg < 0)) {\n        // This indicates an error in the format string.\n        // The only way to get `next_arg < 0` here is to have a positional\n        // argument first which sets next_arg to -1 and then a non-positional\n        // argument.\n        return false;\n      }\n      p = percent + 2;\n\n      // Keep this case separate from the one below.\n      // ConvertOne is more efficient when the compiler can see that the `basic`\n      // flag is set.\n      UnboundConversion conv;\n      conv.conv = tag.as_conv();\n      conv.arg_position = ++next_arg;\n      if (ABSL_PREDICT_FALSE(\n              !consumer.ConvertOne(conv, string_view(percent + 1, 1)))) {\n        return false;\n      }\n    } else if (percent[1] != '%') {\n      UnboundConversion conv;\n      p = ConsumeUnboundConversionNoInline(percent + 1, end, &conv, &next_arg);\n      if (ABSL_PREDICT_FALSE(p == nullptr)) return false;\n      if (ABSL_PREDICT_FALSE(!consumer.ConvertOne(\n              conv, string_view(percent + 1,\n                                static_cast<size_t>(p - (percent + 1)))))) {\n        return false;\n      }\n    } else {\n      if (ABSL_PREDICT_FALSE(!consumer.Append(\"%\"))) return false;\n      p = percent + 2;\n      continue;\n    }\n  }\n  return true;\n}\n\n// Always returns true, or fails to compile in a constexpr context if s does not\n// point to a constexpr char array.\nconstexpr bool EnsureConstexpr(string_view s) {\n  return s.empty() || s[0] == s[0];\n}\n\nclass ParsedFormatBase {\n public:\n  explicit ParsedFormatBase(\n      string_view format, bool allow_ignored,\n      std::initializer_list<FormatConversionCharSet> convs);\n\n  ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }\n\n  ParsedFormatBase(ParsedFormatBase&& other) { *this = std::move(other); }\n\n  ParsedFormatBase& operator=(const ParsedFormatBase& other) {\n    if (this == &other) return *this;\n    has_error_ = other.has_error_;\n    items_ = other.items_;\n    size_t text_size = items_.empty() ? 0 : items_.back().text_end;\n    data_ = std::make_unique<char[]>(text_size);\n    if (text_size > 0) {\n      memcpy(data_.get(), other.data_.get(), text_size);\n    }\n    return *this;\n  }\n\n  ParsedFormatBase& operator=(ParsedFormatBase&& other) {\n    if (this == &other) return *this;\n    has_error_ = other.has_error_;\n    data_ = std::move(other.data_);\n    items_ = std::move(other.items_);\n    // Reset the vector to make sure the invariants hold.\n    other.items_.clear();\n    return *this;\n  }\n\n  template <typename Consumer>\n  bool ProcessFormat(Consumer consumer) const {\n    const char* const base = data_.get();\n    string_view text(base, 0);\n    for (const auto& item : items_) {\n      const char* const end = text.data() + text.size();\n      text =\n          string_view(end, static_cast<size_t>((base + item.text_end) - end));\n      if (item.is_conversion) {\n        if (!consumer.ConvertOne(item.conv, text)) return false;\n      } else {\n        if (!consumer.Append(text)) return false;\n      }\n    }\n    return !has_error_;\n  }\n\n  bool has_error() const { return has_error_; }\n\n private:\n  // Returns whether the conversions match and if !allow_ignored it verifies\n  // that all conversions are used by the format.\n  bool MatchesConversions(\n      bool allow_ignored,\n      std::initializer_list<FormatConversionCharSet> convs) const;\n\n  struct ParsedFormatConsumer;\n\n  struct ConversionItem {\n    bool is_conversion;\n    // Points to the past-the-end location of this element in the data_ array.\n    size_t text_end;\n    UnboundConversion conv;\n  };\n\n  bool has_error_;\n  std::unique_ptr<char[]> data_;\n  std::vector<ConversionItem> items_;\n};\n\n\n// A value type representing a preparsed format.  These can be created, copied\n// around, and reused to speed up formatting loops.\n// The user must specify through the template arguments the conversion\n// characters used in the format. This will be checked at compile time.\n//\n// This class uses Conv enum values to specify each argument.\n// This allows for more flexibility as you can specify multiple possible\n// conversion characters for each argument.\n// ParsedFormat<char...> is a simplified alias for when the user only\n// needs to specify a single conversion character for each argument.\n//\n// Example:\n//   // Extended format supports multiple characters per argument:\n//   using MyFormat = ExtendedParsedFormat<Conv::d | Conv::x>;\n//   MyFormat GetFormat(bool use_hex) {\n//     if (use_hex) return MyFormat(\"foo %x bar\");\n//     return MyFormat(\"foo %d bar\");\n//   }\n//   // 'format' can be used with any value that supports 'd' and 'x',\n//   // like `int`.\n//   auto format = GetFormat(use_hex);\n//   value = StringF(format, i);\n//\n// This class also supports runtime format checking with the ::New() and\n// ::NewAllowIgnored() factory functions.\n// This is the only API that allows the user to pass a runtime specified format\n// string. These factory functions will return NULL if the format does not match\n// the conversions requested by the user.\ntemplate <FormatConversionCharSet... C>\nclass ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {\n public:\n  explicit ExtendedParsedFormat(string_view format)\n#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n      __attribute__((\n          enable_if(str_format_internal::EnsureConstexpr(format),\n                    \"Format string is not constexpr.\"),\n          enable_if(str_format_internal::ValidFormatImpl<C...>(format),\n                    \"Format specified does not match the template arguments.\")))\n#endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER\n      : ExtendedParsedFormat(format, false) {\n  }\n\n  // ExtendedParsedFormat factory function.\n  // The user still has to specify the conversion characters, but they will not\n  // be checked at compile time. Instead, it will be checked at runtime.\n  // This delays the checking to runtime, but allows the user to pass\n  // dynamically sourced formats.\n  // It returns NULL if the format does not match the conversion characters.\n  // The user is responsible for checking the return value before using it.\n  //\n  // The 'New' variant will check that all the specified arguments are being\n  // consumed by the format and return NULL if any argument is being ignored.\n  // The 'NewAllowIgnored' variant will not verify this and will allow formats\n  // that ignore arguments.\n  static std::unique_ptr<ExtendedParsedFormat> New(string_view format) {\n    return New(format, false);\n  }\n  static std::unique_ptr<ExtendedParsedFormat> NewAllowIgnored(\n      string_view format) {\n    return New(format, true);\n  }\n\n private:\n  static std::unique_ptr<ExtendedParsedFormat> New(string_view format,\n                                                   bool allow_ignored) {\n    std::unique_ptr<ExtendedParsedFormat> conv(\n        new ExtendedParsedFormat(format, allow_ignored));\n    if (conv->has_error()) return nullptr;\n    return conv;\n  }\n\n  ExtendedParsedFormat(string_view s, bool allow_ignored)\n      : ParsedFormatBase(s, allow_ignored, {C...}) {}\n};\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_\n"
  },
  {
    "path": "absl/strings/internal/str_format/parser_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/str_format/parser.h\"\n\n#include <string.h>\n#include <algorithm>\n#include <initializer_list>\n#include <string>\n#include <utility>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/internal/str_format/constexpr_parser.h\"\n#include \"absl/strings/internal/str_format/extension.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace str_format_internal {\n\nnamespace {\n\nusing testing::Pair;\n\nTEST(LengthModTest, Names) {\n  struct Expectation {\n    int line;\n    LengthMod mod;\n    const char *name;\n  };\n  const Expectation kExpect[] = {\n    {__LINE__, LengthMod::none, \"\"  },\n    {__LINE__, LengthMod::h,    \"h\" },\n    {__LINE__, LengthMod::hh,   \"hh\"},\n    {__LINE__, LengthMod::l,    \"l\" },\n    {__LINE__, LengthMod::ll,   \"ll\"},\n    {__LINE__, LengthMod::L,    \"L\" },\n    {__LINE__, LengthMod::j,    \"j\" },\n    {__LINE__, LengthMod::z,    \"z\" },\n    {__LINE__, LengthMod::t,    \"t\" },\n    {__LINE__, LengthMod::q,    \"q\" },\n  };\n  EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), 10);\n  for (auto e : kExpect) {\n    SCOPED_TRACE(e.line);\n    EXPECT_EQ(e.name, LengthModToString(e.mod));\n  }\n}\n\nTEST(ConversionCharTest, Names) {\n  struct Expectation {\n    FormatConversionChar id;\n    char name;\n  };\n  // clang-format off\n  const Expectation kExpect[] = {\n#define X(c) {FormatConversionCharInternal::c, #c[0]}\n    X(c), X(s),                                      // text\n    X(d), X(i), X(o), X(u), X(x), X(X),              // int\n    X(f), X(F), X(e), X(E), X(g), X(G), X(a), X(A),  // float\n    X(n), X(p),                                      // misc\n#undef X\n    {FormatConversionCharInternal::kNone, '\\0'},\n  };\n  // clang-format on\n  for (auto e : kExpect) {\n    SCOPED_TRACE(e.name);\n    FormatConversionChar v = e.id;\n    EXPECT_EQ(e.name, FormatConversionCharToChar(v));\n  }\n}\n\nclass ConsumeUnboundConversionTest : public ::testing::Test {\n public:\n  std::pair<string_view, string_view> Consume(string_view src) {\n    int next = 0;\n    o = UnboundConversion();  // refresh\n    const char* p = ConsumeUnboundConversion(\n        src.data(), src.data() + src.size(), &o, &next);\n    if (!p) return {{}, src};\n    return {string_view(src.data(), p - src.data()),\n            string_view(p, src.data() + src.size() - p)};\n  }\n\n  bool Run(const char *fmt, bool force_positional = false) {\n    int next = force_positional ? -1 : 0;\n    o = UnboundConversion();  // refresh\n    return ConsumeUnboundConversion(fmt, fmt + strlen(fmt), &o, &next) ==\n           fmt + strlen(fmt);\n  }\n  UnboundConversion o;\n};\n\nTEST_F(ConsumeUnboundConversionTest, ConsumeSpecification) {\n  struct Expectation {\n    int line;\n    string_view src;\n    string_view out;\n    string_view src_post;\n  };\n  const Expectation kExpect[] = {\n    {__LINE__, \"\",     \"\",     \"\"  },\n    {__LINE__, \"b\",    \"\",     \"b\" },  // 'b' is invalid\n    {__LINE__, \"ba\",   \"\",     \"ba\"},  // 'b' is invalid\n    {__LINE__, \"l\",    \"\",     \"l\" },  // just length mod isn't okay\n    {__LINE__, \"d\",    \"d\",    \"\"  },  // basic\n    {__LINE__, \"v\",    \"v\",    \"\"  },  // basic\n    {__LINE__, \"d \",   \"d\",    \" \" },  // leave suffix\n    {__LINE__, \"dd\",   \"d\",    \"d\" },  // don't be greedy\n    {__LINE__, \"d9\",   \"d\",    \"9\" },  // leave non-space suffix\n    {__LINE__, \"dzz\",  \"d\",    \"zz\"},  // length mod as suffix\n    {__LINE__, \"3v\",   \"\",     \"3v\"},  // 'v' cannot have modifiers\n    {__LINE__, \"hv\",   \"\",     \"hv\"},  // 'v' cannot have modifiers\n    {__LINE__, \"1$v\",   \"1$v\",     \"\"},  // 'v' can have use posix syntax\n    {__LINE__, \"1$*2$d\", \"1$*2$d\", \"\"  },  // arg indexing and * allowed.\n    {__LINE__, \"0-14.3hhd\", \"0-14.3hhd\", \"\"},  // precision, width\n    {__LINE__, \" 0-+#14.3hhd\", \" 0-+#14.3hhd\", \"\"},  // flags\n  };\n  for (const auto& e : kExpect) {\n    SCOPED_TRACE(e.line);\n    EXPECT_THAT(Consume(e.src), Pair(e.out, e.src_post));\n  }\n}\n\nTEST_F(ConsumeUnboundConversionTest, BasicConversion) {\n  EXPECT_FALSE(Run(\"\"));\n  EXPECT_FALSE(Run(\"z\"));\n\n  EXPECT_FALSE(Run(\"dd\"));  // no excess allowed\n\n  EXPECT_TRUE(Run(\"d\"));\n  EXPECT_EQ('d', FormatConversionCharToChar(o.conv));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_LT(o.width.value(), 0);\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_LT(o.precision.value(), 0);\n  EXPECT_EQ(1, o.arg_position);\n}\n\nTEST_F(ConsumeUnboundConversionTest, ArgPosition) {\n  EXPECT_TRUE(Run(\"d\"));\n  EXPECT_EQ(1, o.arg_position);\n  EXPECT_TRUE(Run(\"3$d\"));\n  EXPECT_EQ(3, o.arg_position);\n  EXPECT_TRUE(Run(\"1$d\"));\n  EXPECT_EQ(1, o.arg_position);\n  EXPECT_TRUE(Run(\"1$d\", true));\n  EXPECT_EQ(1, o.arg_position);\n  EXPECT_TRUE(Run(\"123$d\"));\n  EXPECT_EQ(123, o.arg_position);\n  EXPECT_TRUE(Run(\"123$d\", true));\n  EXPECT_EQ(123, o.arg_position);\n  EXPECT_TRUE(Run(\"10$d\"));\n  EXPECT_EQ(10, o.arg_position);\n  EXPECT_TRUE(Run(\"10$d\", true));\n  EXPECT_EQ(10, o.arg_position);\n\n  // Position can't be zero.\n  EXPECT_FALSE(Run(\"0$d\"));\n  EXPECT_FALSE(Run(\"0$d\", true));\n  EXPECT_FALSE(Run(\"1$*0$d\"));\n  EXPECT_FALSE(Run(\"1$.*0$d\"));\n\n  // Position can't start with a zero digit at all. That is not a 'decimal'.\n  EXPECT_FALSE(Run(\"01$p\"));\n  EXPECT_FALSE(Run(\"01$p\", true));\n  EXPECT_FALSE(Run(\"1$*01$p\"));\n  EXPECT_FALSE(Run(\"1$.*01$p\"));\n}\n\nTEST_F(ConsumeUnboundConversionTest, WidthAndPrecision) {\n  EXPECT_TRUE(Run(\"14d\"));\n  EXPECT_EQ('d', FormatConversionCharToChar(o.conv));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_EQ(14, o.width.value());\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_LT(o.precision.value(), 0);\n\n  EXPECT_TRUE(Run(\"14.d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_EQ(14, o.width.value());\n  EXPECT_EQ(0, o.precision.value());\n\n  EXPECT_TRUE(Run(\".d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_LT(o.width.value(), 0);\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_EQ(0, o.precision.value());\n\n  EXPECT_TRUE(Run(\".5d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_LT(o.width.value(), 0);\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_EQ(5, o.precision.value());\n\n  EXPECT_TRUE(Run(\".0d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_LT(o.width.value(), 0);\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_EQ(0, o.precision.value());\n\n  EXPECT_TRUE(Run(\"14.5d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_EQ(14, o.width.value());\n  EXPECT_EQ(5, o.precision.value());\n\n  EXPECT_TRUE(Run(\"*.*d\"));\n  EXPECT_TRUE(o.width.is_from_arg());\n  EXPECT_EQ(1, o.width.get_from_arg());\n  EXPECT_TRUE(o.precision.is_from_arg());\n  EXPECT_EQ(2, o.precision.get_from_arg());\n  EXPECT_EQ(3, o.arg_position);\n\n  EXPECT_TRUE(Run(\"*d\"));\n  EXPECT_TRUE(o.width.is_from_arg());\n  EXPECT_EQ(1, o.width.get_from_arg());\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_LT(o.precision.value(), 0);\n  EXPECT_EQ(2, o.arg_position);\n\n  EXPECT_TRUE(Run(\".*d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_LT(o.width.value(), 0);\n  EXPECT_TRUE(o.precision.is_from_arg());\n  EXPECT_EQ(1, o.precision.get_from_arg());\n  EXPECT_EQ(2, o.arg_position);\n\n  // mixed implicit and explicit: didn't specify arg position.\n  EXPECT_FALSE(Run(\"*23$.*34$d\"));\n\n  EXPECT_TRUE(Run(\"12$*23$.*34$d\"));\n  EXPECT_EQ(12, o.arg_position);\n  EXPECT_TRUE(o.width.is_from_arg());\n  EXPECT_EQ(23, o.width.get_from_arg());\n  EXPECT_TRUE(o.precision.is_from_arg());\n  EXPECT_EQ(34, o.precision.get_from_arg());\n\n  EXPECT_TRUE(Run(\"2$*5$.*9$d\"));\n  EXPECT_EQ(2, o.arg_position);\n  EXPECT_TRUE(o.width.is_from_arg());\n  EXPECT_EQ(5, o.width.get_from_arg());\n  EXPECT_TRUE(o.precision.is_from_arg());\n  EXPECT_EQ(9, o.precision.get_from_arg());\n\n  EXPECT_FALSE(Run(\".*0$d\")) << \"no arg 0\";\n\n  // Large values\n  EXPECT_TRUE(Run(\"999999999.999999999d\"));\n  EXPECT_FALSE(o.width.is_from_arg());\n  EXPECT_EQ(999999999, o.width.value());\n  EXPECT_FALSE(o.precision.is_from_arg());\n  EXPECT_EQ(999999999, o.precision.value());\n\n  EXPECT_FALSE(Run(\"1000000000.999999999d\"));\n  EXPECT_FALSE(Run(\"999999999.1000000000d\"));\n  EXPECT_FALSE(Run(\"9999999999d\"));\n  EXPECT_FALSE(Run(\".9999999999d\"));\n}\n\nTEST_F(ConsumeUnboundConversionTest, Flags) {\n  static const char kAllFlags[] = \"-+ #0\";\n  static const int kNumFlags = ABSL_ARRAYSIZE(kAllFlags) - 1;\n  for (int rev = 0; rev < 2; ++rev) {\n    for (int i = 0; i < 1 << kNumFlags; ++i) {\n      std::string fmt;\n      for (int k = 0; k < kNumFlags; ++k)\n        if ((i >> k) & 1) fmt += kAllFlags[k];\n      // flag order shouldn't matter\n      if (rev == 1) {\n        std::reverse(fmt.begin(), fmt.end());\n      }\n      fmt += 'd';\n      SCOPED_TRACE(fmt);\n      EXPECT_TRUE(Run(fmt.c_str()));\n      EXPECT_EQ(fmt.find('-') == std::string::npos,\n                !FlagsContains(o.flags, Flags::kLeft));\n      EXPECT_EQ(fmt.find('+') == std::string::npos,\n                !FlagsContains(o.flags, Flags::kShowPos));\n      EXPECT_EQ(fmt.find(' ') == std::string::npos,\n                !FlagsContains(o.flags, Flags::kSignCol));\n      EXPECT_EQ(fmt.find('#') == std::string::npos,\n                !FlagsContains(o.flags, Flags::kAlt));\n      EXPECT_EQ(fmt.find('0') == std::string::npos,\n                !FlagsContains(o.flags, Flags::kZero));\n    }\n  }\n}\n\nTEST_F(ConsumeUnboundConversionTest, BasicFlag) {\n  // Flag is on\n  for (const char* fmt : {\"d\", \"llx\", \"G\", \"1$X\"}) {\n    SCOPED_TRACE(fmt);\n    EXPECT_TRUE(Run(fmt));\n    EXPECT_EQ(o.flags, Flags::kBasic);\n  }\n\n  // Flag is off\n  for (const char* fmt : {\"3d\", \".llx\", \"-G\", \"1$#X\", \"lc\"}) {\n    SCOPED_TRACE(fmt);\n    EXPECT_TRUE(Run(fmt));\n    EXPECT_NE(o.flags, Flags::kBasic);\n  }\n}\n\nTEST_F(ConsumeUnboundConversionTest, LengthMod) {\n  EXPECT_TRUE(Run(\"d\"));\n  EXPECT_EQ(LengthMod::none, o.length_mod);\n  EXPECT_TRUE(Run(\"hd\"));\n  EXPECT_EQ(LengthMod::h, o.length_mod);\n  EXPECT_TRUE(Run(\"hhd\"));\n  EXPECT_EQ(LengthMod::hh, o.length_mod);\n  EXPECT_TRUE(Run(\"ld\"));\n  EXPECT_EQ(LengthMod::l, o.length_mod);\n  EXPECT_TRUE(Run(\"lld\"));\n  EXPECT_EQ(LengthMod::ll, o.length_mod);\n  EXPECT_TRUE(Run(\"Lf\"));\n  EXPECT_EQ(LengthMod::L, o.length_mod);\n  EXPECT_TRUE(Run(\"qf\"));\n  EXPECT_EQ(LengthMod::q, o.length_mod);\n  EXPECT_TRUE(Run(\"jd\"));\n  EXPECT_EQ(LengthMod::j, o.length_mod);\n  EXPECT_TRUE(Run(\"zd\"));\n  EXPECT_EQ(LengthMod::z, o.length_mod);\n  EXPECT_TRUE(Run(\"td\"));\n  EXPECT_EQ(LengthMod::t, o.length_mod);\n}\n\nstruct SummarizeConsumer {\n  std::string* out;\n  explicit SummarizeConsumer(std::string* out) : out(out) {}\n\n  bool Append(string_view s) {\n    *out += \"[\" + std::string(s) + \"]\";\n    return true;\n  }\n\n  bool ConvertOne(const UnboundConversion& conv, string_view s) {\n    *out += \"{\";\n    *out += std::string(s);\n    *out += \":\";\n    *out += std::to_string(conv.arg_position) + \"$\";\n    if (conv.width.is_from_arg()) {\n      *out += std::to_string(conv.width.get_from_arg()) + \"$*\";\n    }\n    if (conv.precision.is_from_arg()) {\n      *out += \".\" + std::to_string(conv.precision.get_from_arg()) + \"$*\";\n    }\n    *out += FormatConversionCharToChar(conv.conv);\n    *out += \"}\";\n    return true;\n  }\n};\n\nstd::string SummarizeParsedFormat(const ParsedFormatBase& pc) {\n  std::string out;\n  if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += \"!\";\n  return out;\n}\n\nclass ParsedFormatTest : public testing::Test {};\n\nTEST_F(ParsedFormatTest, ValueSemantics) {\n  ParsedFormatBase p1({}, true, {});  // empty format\n  EXPECT_EQ(\"\", SummarizeParsedFormat(p1));\n\n  ParsedFormatBase p2 = p1;  // copy construct (empty)\n  EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2));\n\n  p1 = ParsedFormatBase(\"hello%s\", true,\n                        {FormatConversionCharSetInternal::s});  // move assign\n  EXPECT_EQ(\"[hello]{s:1$s}\", SummarizeParsedFormat(p1));\n\n  ParsedFormatBase p3 = p1;  // copy construct (nonempty)\n  EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p3));\n\n  using std::swap;\n  swap(p1, p2);\n  EXPECT_EQ(\"\", SummarizeParsedFormat(p1));\n  EXPECT_EQ(\"[hello]{s:1$s}\", SummarizeParsedFormat(p2));\n  swap(p1, p2);  // undo\n\n  p2 = p1;  // copy assign\n  EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2));\n}\n\nstruct ExpectParse {\n  const char* in;\n  std::initializer_list<FormatConversionCharSet> conv_set;\n  const char* out;\n};\n\nTEST_F(ParsedFormatTest, Parsing) {\n  // Parse should be equivalent to that obtained by ConversionParseIterator.\n  // No need to retest the parsing edge cases here.\n  const ExpectParse kExpect[] = {\n      {\"\", {}, \"\"},\n      {\"ab\", {}, \"[ab]\"},\n      {\"a%d\", {FormatConversionCharSetInternal::d}, \"[a]{d:1$d}\"},\n      {\"a%+d\", {FormatConversionCharSetInternal::d}, \"[a]{+d:1$d}\"},\n      {\"a% d\", {FormatConversionCharSetInternal::d}, \"[a]{ d:1$d}\"},\n      {\"a%b %d\", {}, \"[a]!\"},  // stop after error\n  };\n  for (const auto& e : kExpect) {\n    SCOPED_TRACE(e.in);\n    EXPECT_EQ(e.out,\n              SummarizeParsedFormat(ParsedFormatBase(e.in, false, e.conv_set)));\n  }\n}\n\nTEST_F(ParsedFormatTest, ParsingFlagOrder) {\n  const ExpectParse kExpect[] = {\n      {\"a%+ 0d\", {FormatConversionCharSetInternal::d}, \"[a]{+ 0d:1$d}\"},\n      {\"a%+0 d\", {FormatConversionCharSetInternal::d}, \"[a]{+0 d:1$d}\"},\n      {\"a%0+ d\", {FormatConversionCharSetInternal::d}, \"[a]{0+ d:1$d}\"},\n      {\"a% +0d\", {FormatConversionCharSetInternal::d}, \"[a]{ +0d:1$d}\"},\n      {\"a%0 +d\", {FormatConversionCharSetInternal::d}, \"[a]{0 +d:1$d}\"},\n      {\"a% 0+d\", {FormatConversionCharSetInternal::d}, \"[a]{ 0+d:1$d}\"},\n      {\"a%+   0+d\", {FormatConversionCharSetInternal::d}, \"[a]{+   0+d:1$d}\"},\n  };\n  for (const auto& e : kExpect) {\n    SCOPED_TRACE(e.in);\n    EXPECT_EQ(e.out,\n              SummarizeParsedFormat(ParsedFormatBase(e.in, false, e.conv_set)));\n  }\n}\n\n}  // namespace\n}  // namespace str_format_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/str_join_internal.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n// This file declares INTERNAL parts of the Join API that are inlined/templated\n// or otherwise need to be available at compile time. The main abstractions\n// defined in this file are:\n//\n//   - A handful of default Formatters\n//   - JoinAlgorithm() overloads\n//   - JoinRange() overloads\n//   - JoinTuple()\n//\n// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including\n// absl/strings/str_join.h\n//\n// IWYU pragma: private, include \"absl/strings/str_join.h\"\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_\n#define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_\n\n#include <cstdint>\n#include <cstring>\n#include <initializer_list>\n#include <iterator>\n#include <limits>\n#include <memory>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/iterator_traits.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/internal/ostringstream.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n//\n// Formatter objects\n//\n// The following are implementation classes for standard Formatter objects. The\n// factory functions that users will call to create and use these formatters are\n// defined and documented in strings/join.h.\n//\n\n// The default formatter. Converts alpha-numeric types to strings.\nstruct AlphaNumFormatterImpl {\n  // This template is needed in order to support passing in a dereferenced\n  // vector<bool>::iterator\n  template <typename T>\n  void operator()(std::string* out, const T& t) const {\n    StrAppend(out, AlphaNum(t));\n  }\n\n  void operator()(std::string* out, const AlphaNum& t) const {\n    StrAppend(out, t);\n  }\n};\n\n// A type that's used to overload the JoinAlgorithm() function (defined below)\n// for ranges that do not require additional formatting (e.g., a range of\n// strings).\n\nstruct NoFormatter : public AlphaNumFormatterImpl {};\n\n// Formats types to strings using the << operator.\nclass StreamFormatterImpl {\n public:\n  // The method isn't const because it mutates state. Making it const will\n  // render StreamFormatterImpl thread-hostile.\n  template <typename T>\n  void operator()(std::string* out, const T& t) {\n    // The stream is created lazily to avoid paying the relatively high cost\n    // of its construction when joining an empty range.\n    if (strm_) {\n      strm_->clear();  // clear the bad, fail and eof bits in case they were set\n      strm_->str(out);\n    } else {\n      strm_.reset(new strings_internal::OStringStream(out));\n    }\n    *strm_ << t;\n  }\n\n private:\n  std::unique_ptr<strings_internal::OStringStream> strm_;\n};\n\n// Formats a std::pair<>. The 'first' member is formatted using f1_ and the\n// 'second' member is formatted using f2_. sep_ is the separator.\ntemplate <typename F1, typename F2>\nclass PairFormatterImpl {\n public:\n  PairFormatterImpl(F1 f1, absl::string_view sep, F2 f2)\n      : f1_(std::move(f1)), sep_(sep), f2_(std::move(f2)) {}\n\n  template <typename T>\n  void operator()(std::string* out, const T& p) {\n    f1_(out, p.first);\n    out->append(sep_);\n    f2_(out, p.second);\n  }\n\n  template <typename T>\n  void operator()(std::string* out, const T& p) const {\n    f1_(out, p.first);\n    out->append(sep_);\n    f2_(out, p.second);\n  }\n\n private:\n  F1 f1_;\n  std::string sep_;\n  F2 f2_;\n};\n\n// Wraps another formatter and dereferences the argument to operator() then\n// passes the dereferenced argument to the wrapped formatter. This can be\n// useful, for example, to join a std::vector<int*>.\ntemplate <typename Formatter>\nclass DereferenceFormatterImpl {\n public:\n  DereferenceFormatterImpl() : f_() {}\n  explicit DereferenceFormatterImpl(Formatter&& f)\n      : f_(std::forward<Formatter>(f)) {}\n\n  template <typename T>\n  void operator()(std::string* out, const T& t) {\n    f_(out, *t);\n  }\n\n  template <typename T>\n  void operator()(std::string* out, const T& t) const {\n    f_(out, *t);\n  }\n\n private:\n  Formatter f_;\n};\n\n// DefaultFormatter<T> is a traits class that selects a default Formatter to use\n// for the given type T. The ::Type member names the Formatter to use. This is\n// used by the strings::Join() functions that do NOT take a Formatter argument,\n// in which case a default Formatter must be chosen.\n//\n// AlphaNumFormatterImpl is the default in the base template, followed by\n// specializations for other types.\ntemplate <typename ValueType>\nstruct DefaultFormatter {\n  typedef AlphaNumFormatterImpl Type;\n};\ntemplate <>\nstruct DefaultFormatter<const char*> {\n  typedef AlphaNumFormatterImpl Type;\n};\ntemplate <>\nstruct DefaultFormatter<char*> {\n  typedef AlphaNumFormatterImpl Type;\n};\ntemplate <>\nstruct DefaultFormatter<std::string> {\n  typedef NoFormatter Type;\n};\ntemplate <>\nstruct DefaultFormatter<absl::string_view> {\n  typedef NoFormatter Type;\n};\ntemplate <typename ValueType>\nstruct DefaultFormatter<ValueType*> {\n  typedef DereferenceFormatterImpl<typename DefaultFormatter<ValueType>::Type>\n      Type;\n};\n\ntemplate <typename ValueType>\nstruct DefaultFormatter<std::unique_ptr<ValueType>>\n    : public DefaultFormatter<ValueType*> {};\n\n//\n// JoinAlgorithm() functions\n//\n\n// The main joining algorithm. This simply joins the elements in the given\n// iterator range, each separated by the given separator, into an output string,\n// and formats each element using the provided Formatter object.\ntemplate <typename Iterator, typename Formatter>\nstd::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,\n                          Formatter&& f) {\n  std::string result;\n  absl::string_view sep(\"\");\n  for (Iterator it = start; it != end; ++it) {\n    result.append(sep.data(), sep.size());\n    f(&result, *it);\n    sep = s;\n  }\n  return result;\n}\n\n// A joining algorithm that's optimized for a forward iterator range of\n// string-like objects that do not need any additional formatting. This is to\n// optimize the common case of joining, say, a std::vector<string> or a\n// std::vector<absl::string_view>.\n//\n// This is an overload of the previous JoinAlgorithm() function. Here the\n// Formatter argument is of type NoFormatter. Since NoFormatter is an internal\n// type, this overload is only invoked when strings::Join() is called with a\n// range of string-like objects (e.g., std::string, absl::string_view), and an\n// explicit Formatter argument was NOT specified.\n//\n// The optimization is that the needed space will be reserved in the output\n// string to avoid the need to resize while appending. To do this, the iterator\n// range will be traversed twice: once to calculate the total needed size, and\n// then again to copy the elements and delimiters to the output string.\ntemplate <typename Iterator,\n          typename = std::enable_if_t<\n              base_internal::IsAtLeastForwardIterator<Iterator>::value>>\nstd::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,\n                          NoFormatter) {\n  std::string result;\n  if (start != end) {\n    // Sums size\n    auto&& start_value = *start;\n    // Use uint64_t to prevent size_t overflow. We assume it is not possible for\n    // in memory strings to overflow a uint64_t.\n    uint64_t result_size = start_value.size();\n    for (Iterator it = start; ++it != end;) {\n      result_size += s.size();\n      result_size += (*it).size();\n    }\n\n    if (result_size > 0) {\n      constexpr uint64_t kMaxSize =\n          uint64_t{(std::numeric_limits<size_t>::max)()};\n      ABSL_INTERNAL_CHECK(result_size <= kMaxSize, \"size_t overflow\");\n\n      StringResizeAndOverwrite(\n          result, static_cast<size_t>(result_size),\n          [&start, &end, &start_value, s](char* result_buf,\n                                          size_t result_buf_size) {\n            // Joins strings\n            memcpy(result_buf, start_value.data(), start_value.size());\n            result_buf += start_value.size();\n            for (Iterator it = start; ++it != end;) {\n              memcpy(result_buf, s.data(), s.size());\n              result_buf += s.size();\n              auto&& value = *it;\n              memcpy(result_buf, value.data(), value.size());\n              result_buf += value.size();\n            }\n            return result_buf_size;\n          });\n    }\n  }\n  return result;\n}\n\n// JoinTupleLoop implements a loop over the elements of a std::tuple, which\n// are heterogeneous. The primary template matches the tuple interior case. It\n// continues the iteration after appending a separator (for nonzero indices)\n// and formatting an element of the tuple. The specialization for the I=N case\n// matches the end-of-tuple, and terminates the iteration.\ntemplate <size_t I, size_t N>\nstruct JoinTupleLoop {\n  template <typename Tup, typename Formatter>\n  void operator()(std::string* out, const Tup& tup, absl::string_view sep,\n                  Formatter&& fmt) {\n    if (I > 0) out->append(sep.data(), sep.size());\n    fmt(out, std::get<I>(tup));\n    JoinTupleLoop<I + 1, N>()(out, tup, sep, fmt);\n  }\n};\ntemplate <size_t N>\nstruct JoinTupleLoop<N, N> {\n  template <typename Tup, typename Formatter>\n  void operator()(std::string*, const Tup&, absl::string_view, Formatter&&) {}\n};\n\ntemplate <typename... T, typename Formatter>\nstd::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep,\n                          Formatter&& fmt) {\n  std::string result;\n  JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);\n  return result;\n}\n\ntemplate <typename Iterator>\nstd::string JoinRange(Iterator first, Iterator last,\n                      absl::string_view separator) {\n  // No formatter was explicitly given, so a default must be chosen.\n  typedef typename std::iterator_traits<Iterator>::value_type ValueType;\n  typedef typename DefaultFormatter<ValueType>::Type Formatter;\n  return JoinAlgorithm(first, last, separator, Formatter());\n}\n\ntemplate <typename Range, typename Formatter>\nstd::string JoinRange(const Range& range, absl::string_view separator,\n                      Formatter&& fmt) {\n  using std::begin;\n  using std::end;\n  return JoinAlgorithm(begin(range), end(range), separator, fmt);\n}\n\ntemplate <typename Range>\nstd::string JoinRange(const Range& range, absl::string_view separator) {\n  using std::begin;\n  using std::end;\n  return JoinRange(begin(range), end(range), separator);\n}\n\ntemplate <typename Tuple, std::size_t... I>\nstd::string JoinTuple(const Tuple& value, absl::string_view separator,\n                      std::index_sequence<I...>) {\n  return JoinRange(\n      std::initializer_list<absl::string_view>{\n          static_cast<const AlphaNum&>(std::get<I>(value)).Piece()...},\n      separator);\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_\n"
  },
  {
    "path": "absl/strings/internal/str_split_internal.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n// This file declares INTERNAL parts of the Split API that are inline/templated\n// or otherwise need to be available at compile time. The main abstractions\n// defined in here are\n//\n//   - ConvertibleToStringView\n//   - SplitIterator<>\n//   - Splitter<>\n//\n// DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including\n// absl/strings/str_split.h.\n//\n// IWYU pragma: private, include \"absl/strings/str_split.h\"\n\n#ifndef ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_\n#define ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_\n\n#include <array>\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <iterator>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/macros.h\"\n#include \"absl/base/port.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef _GLIBCXX_DEBUG\n#include \"absl/strings/internal/stl_type_traits.h\"\n#endif  // _GLIBCXX_DEBUG\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// This class is implicitly constructible from everything that absl::string_view\n// is implicitly constructible from, except for rvalue strings.  This means it\n// can be used as a function parameter in places where passing a temporary\n// string might cause memory lifetime issues.\nclass ConvertibleToStringView {\n public:\n  ConvertibleToStringView(const char* s)  // NOLINT(runtime/explicit)\n      : value_(s) {\n    assert(s != nullptr);\n  }\n  ConvertibleToStringView(char* s) : value_(s) {  // NOLINT(runtime/explicit)\n    assert(s != nullptr);\n  }\n  ConvertibleToStringView(absl::string_view s)     // NOLINT(runtime/explicit)\n      : value_(s) {}\n  ConvertibleToStringView(const std::string& s)  // NOLINT(runtime/explicit)\n      : value_(s) {}\n\n  // Disable conversion from rvalue strings.\n  ConvertibleToStringView(std::string&& s) = delete;\n  ConvertibleToStringView(const std::string&& s) = delete;\n\n  absl::string_view value() const { return value_; }\n\n private:\n  absl::string_view value_;\n};\n\n// An iterator that enumerates the parts of a string from a Splitter. The text\n// to be split, the Delimiter, and the Predicate are all taken from the given\n// Splitter object. Iterators may only be compared if they refer to the same\n// Splitter instance.\n//\n// This class is NOT part of the public splitting API.\ntemplate <typename Splitter>\nclass SplitIterator {\n public:\n  using iterator_category = std::input_iterator_tag;\n  using value_type = absl::string_view;\n  using difference_type = ptrdiff_t;\n  using pointer = const value_type*;\n  using reference = const value_type&;\n\n  enum State { kInitState, kLastState, kEndState };\n  SplitIterator(State state, const Splitter* splitter)\n      : pos_(0),\n        state_(state),\n        splitter_(splitter),\n        delimiter_(splitter->delimiter()),\n        predicate_(splitter->predicate()) {\n    // Hack to maintain backward compatibility. This one block makes it so an\n    // empty absl::string_view whose .data() happens to be nullptr behaves\n    // *differently* from an otherwise empty absl::string_view whose .data() is\n    // not nullptr. This is an undesirable difference in general, but this\n    // behavior is maintained to avoid breaking existing code that happens to\n    // depend on this old behavior/bug. Perhaps it will be fixed one day. The\n    // difference in behavior is as follows:\n    //   Split(absl::string_view(\"\"), '-');  // {\"\"}\n    //   Split(absl::string_view(), '-');    // {}\n    if (splitter_->text().data() == nullptr) {\n      state_ = kEndState;\n      pos_ = splitter_->text().size();\n      return;\n    }\n\n    if (state_ == kEndState) {\n      pos_ = splitter_->text().size();\n    } else {\n      ++(*this);\n    }\n  }\n\n  bool at_end() const { return state_ == kEndState; }\n\n  reference operator*() const { return curr_; }\n  pointer operator->() const { return &curr_; }\n\n  SplitIterator& operator++() {\n    do {\n      if (state_ == kLastState) {\n        state_ = kEndState;\n        return *this;\n      }\n      const absl::string_view text = splitter_->text();\n      const absl::string_view d = delimiter_.Find(text, pos_);\n      if (d.data() == text.data() + text.size()) state_ = kLastState;\n      curr_ = text.substr(pos_,\n                          static_cast<size_t>(d.data() - (text.data() + pos_)));\n      pos_ += curr_.size() + d.size();\n    } while (!predicate_(curr_));\n    return *this;\n  }\n\n  SplitIterator operator++(int) {\n    SplitIterator old(*this);\n    ++(*this);\n    return old;\n  }\n\n  friend bool operator==(const SplitIterator& a, const SplitIterator& b) {\n    return a.state_ == b.state_ && a.pos_ == b.pos_;\n  }\n\n  friend bool operator!=(const SplitIterator& a, const SplitIterator& b) {\n    return !(a == b);\n  }\n\n private:\n  size_t pos_;\n  State state_;\n  absl::string_view curr_;\n  const Splitter* splitter_;\n  typename Splitter::DelimiterType delimiter_;\n  typename Splitter::PredicateType predicate_;\n};\n\n// HasMappedType<T>::value is true iff there exists a type T::mapped_type.\ntemplate <typename T, typename = void>\nstruct HasMappedType : std::false_type {};\ntemplate <typename T>\nstruct HasMappedType<T, absl::void_t<typename T::mapped_type>>\n    : std::true_type {};\n\n// HasValueType<T>::value is true iff there exists a type T::value_type.\ntemplate <typename T, typename = void>\nstruct HasValueType : std::false_type {};\ntemplate <typename T>\nstruct HasValueType<T, absl::void_t<typename T::value_type>> : std::true_type {\n};\n\n// HasConstIterator<T>::value is true iff there exists a type T::const_iterator.\ntemplate <typename T, typename = void>\nstruct HasConstIterator : std::false_type {};\ntemplate <typename T>\nstruct HasConstIterator<T, absl::void_t<typename T::const_iterator>>\n    : std::true_type {};\n\n// HasEmplace<T>::value is true iff there exists a method T::emplace().\ntemplate <typename T, typename = void>\nstruct HasEmplace : std::false_type {};\ntemplate <typename T>\nstruct HasEmplace<T, absl::void_t<decltype(std::declval<T>().emplace())>>\n    : std::true_type {};\n\n// IsInitializerList<T>::value is true iff T is an std::initializer_list. More\n// details below in Splitter<> where this is used.\nstd::false_type IsInitializerListDispatch(...);  // default: No\ntemplate <typename T>\nstd::true_type IsInitializerListDispatch(std::initializer_list<T>*);\ntemplate <typename T>\nstruct IsInitializerList\n    : decltype(IsInitializerListDispatch(static_cast<T*>(nullptr))) {};\n\n// A SplitterIsConvertibleTo<C>::type alias exists iff the specified condition\n// is true for type 'C'.\n//\n// Restricts conversion to container-like types (by testing for the presence of\n// a const_iterator member type) and also to disable conversion to an\n// std::initializer_list (which also has a const_iterator). Otherwise, code\n// compiled in C++11 will get an error due to ambiguous conversion paths (in\n// C++11 std::vector<T>::operator= is overloaded to take either a std::vector<T>\n// or an std::initializer_list<T>).\n\ntemplate <typename C, bool has_value_type, bool has_mapped_type>\nstruct SplitterIsConvertibleToImpl : std::false_type {};\n\ntemplate <typename C>\nstruct SplitterIsConvertibleToImpl<C, true, false>\n    : std::is_constructible<typename C::value_type, absl::string_view> {};\n\ntemplate <typename C>\nstruct SplitterIsConvertibleToImpl<C, true, true>\n    : absl::conjunction<\n          std::is_constructible<typename C::key_type, absl::string_view>,\n          std::is_constructible<typename C::mapped_type, absl::string_view>> {};\n\ntemplate <typename C>\nstruct SplitterIsConvertibleTo\n    : SplitterIsConvertibleToImpl<\n          C,\n#ifdef _GLIBCXX_DEBUG\n          !IsStrictlyBaseOfAndConvertibleToSTLContainer<C>::value &&\n#endif  // _GLIBCXX_DEBUG\n              !IsInitializerList<\n                  typename std::remove_reference<C>::type>::value &&\n              HasValueType<C>::value && HasConstIterator<C>::value,\n          HasMappedType<C>::value> {\n};\n\ntemplate <typename StringType, typename Container, typename = void>\nstruct ShouldUseLifetimeBound : std::false_type {};\n\ntemplate <typename StringType, typename Container>\nstruct ShouldUseLifetimeBound<\n    StringType, Container,\n    std::enable_if_t<\n        std::is_same<StringType, std::string>::value &&\n        std::is_same<typename Container::value_type, absl::string_view>::value>>\n    : std::true_type {};\n\ntemplate <typename StringType, typename First, typename Second>\nusing ShouldUseLifetimeBoundForPair = std::integral_constant<\n    bool, std::is_same<StringType, std::string>::value &&\n              (std::is_same<First, absl::string_view>::value ||\n               std::is_same<Second, absl::string_view>::value)>;\n\ntemplate <typename StringType, typename ElementType, std::size_t Size>\nusing ShouldUseLifetimeBoundForArray = std::integral_constant<\n    bool, std::is_same<StringType, std::string>::value &&\n              std::is_same<ElementType, absl::string_view>::value>;\n\n// This class implements the range that is returned by absl::StrSplit(). This\n// class has templated conversion operators that allow it to be implicitly\n// converted to a variety of types that the caller may have specified on the\n// left-hand side of an assignment.\n//\n// The main interface for interacting with this class is through its implicit\n// conversion operators. However, this class may also be used like a container\n// in that it has .begin() and .end() member functions. It may also be used\n// within a range-for loop.\n//\n// Output containers can be collections of any type that is constructible from\n// an absl::string_view.\n//\n// An Predicate functor may be supplied. This predicate will be used to filter\n// the split strings: only strings for which the predicate returns true will be\n// kept. A Predicate object is any unary functor that takes an absl::string_view\n// and returns bool.\n//\n// The StringType parameter can be either string_view or string, depending on\n// whether the Splitter refers to a string stored elsewhere, or if the string\n// resides inside the Splitter itself.\ntemplate <typename Delimiter, typename Predicate, typename StringType>\nclass Splitter {\n public:\n  using DelimiterType = Delimiter;\n  using PredicateType = Predicate;\n  using const_iterator = strings_internal::SplitIterator<Splitter>;\n  using value_type = typename std::iterator_traits<const_iterator>::value_type;\n\n  Splitter(StringType input_text, Delimiter d, Predicate p)\n      : text_(std::move(input_text)),\n        delimiter_(std::move(d)),\n        predicate_(std::move(p)) {}\n\n  absl::string_view text() const { return text_; }\n  const Delimiter& delimiter() const { return delimiter_; }\n  const Predicate& predicate() const { return predicate_; }\n\n  // Range functions that iterate the split substrings as absl::string_view\n  // objects. These methods enable a Splitter to be used in a range-based for\n  // loop.\n  const_iterator begin() const { return {const_iterator::kInitState, this}; }\n  const_iterator end() const { return {const_iterator::kEndState, this}; }\n\n  // An implicit conversion operator that is restricted to only those containers\n  // that the splitter is convertible to.\n  template <\n      typename Container,\n      std::enable_if_t<ShouldUseLifetimeBound<StringType, Container>::value &&\n                           SplitterIsConvertibleTo<Container>::value,\n                       std::nullptr_t> = nullptr>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  operator Container() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return ConvertToContainer<Container, typename Container::value_type,\n                              HasMappedType<Container>::value>()(*this);\n  }\n\n  template <\n      typename Container,\n      std::enable_if_t<!ShouldUseLifetimeBound<StringType, Container>::value &&\n                           SplitterIsConvertibleTo<Container>::value,\n                       std::nullptr_t> = nullptr>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  operator Container() const {\n    return ConvertToContainer<Container, typename Container::value_type,\n                              HasMappedType<Container>::value>()(*this);\n  }\n\n  // Returns a pair with its .first and .second members set to the first two\n  // strings returned by the begin() iterator. Either/both of .first and .second\n  // will be constructed with empty strings if the iterator doesn't have a\n  // corresponding value.\n  template <typename First, typename Second,\n            std::enable_if_t<\n                ShouldUseLifetimeBoundForPair<StringType, First, Second>::value,\n                std::nullptr_t> = nullptr>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  operator std::pair<First, Second>() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return ConvertToPair<First, Second>();\n  }\n\n  template <typename First, typename Second,\n            std::enable_if_t<!ShouldUseLifetimeBoundForPair<StringType, First,\n                                                            Second>::value,\n                             std::nullptr_t> = nullptr>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  operator std::pair<First, Second>() const {\n    return ConvertToPair<First, Second>();\n  }\n\n  // Returns an array with its elements set to the first few strings returned by\n  // the begin() iterator.  If there is not a corresponding value the empty\n  // string is used.\n  template <typename ElementType, std::size_t Size,\n            std::enable_if_t<ShouldUseLifetimeBoundForArray<\n                                 StringType, ElementType, Size>::value,\n                             std::nullptr_t> = nullptr>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  operator std::array<ElementType, Size>() const ABSL_ATTRIBUTE_LIFETIME_BOUND {\n    return ConvertToArray<ElementType, Size>();\n  }\n\n  template <typename ElementType, std::size_t Size,\n            std::enable_if_t<!ShouldUseLifetimeBoundForArray<\n                                 StringType, ElementType, Size>::value,\n                             std::nullptr_t> = nullptr>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  operator std::array<ElementType, Size>() const {\n    return ConvertToArray<ElementType, Size>();\n  }\n\n private:\n  template <typename ElementType, std::size_t Size>\n  std::array<ElementType, Size> ConvertToArray() const {\n    std::array<ElementType, Size> a;\n    auto it = begin();\n    for (std::size_t i = 0; i < Size && it != end(); ++i, ++it) {\n      a[i] = ElementType(*it);\n    }\n    return a;\n  }\n\n  template <typename First, typename Second>\n  std::pair<First, Second> ConvertToPair() const {\n    absl::string_view first, second;\n    auto it = begin();\n    if (it != end()) {\n      first = *it;\n      if (++it != end()) {\n        second = *it;\n      }\n    }\n    return {First(first), Second(second)};\n  }\n\n  // ConvertToContainer is a functor converting a Splitter to the requested\n  // Container of ValueType. It is specialized below to optimize splitting to\n  // certain combinations of Container and ValueType.\n  //\n  // This base template handles the generic case of storing the split results in\n  // the requested non-map-like container and converting the split substrings to\n  // the requested type.\n  template <typename Container, typename ValueType, bool is_map = false>\n  struct ConvertToContainer {\n    Container operator()(const Splitter& splitter) const {\n      Container c;\n      auto it = std::inserter(c, c.end());\n      for (const auto& sp : splitter) {\n        *it++ = ValueType(sp);\n      }\n      return c;\n    }\n  };\n\n  // Partial specialization for a std::vector<absl::string_view>.\n  //\n  // Optimized for the common case of splitting to a\n  // std::vector<absl::string_view>. In this case we first split the results to\n  // a small array of absl::string_view on the stack, to reduce reallocations.\n  template <typename A>\n  struct ConvertToContainer<std::vector<absl::string_view, A>,\n                            absl::string_view, false> {\n    std::vector<absl::string_view, A> operator()(\n        const Splitter& splitter) const {\n      struct raw_view {\n        const char* data;\n        size_t size;\n        operator absl::string_view() const {  // NOLINT(runtime/explicit)\n          return {data, size};\n        }\n      };\n      std::vector<absl::string_view, A> v;\n      std::array<raw_view, 16> ar;\n      for (auto it = splitter.begin(); !it.at_end();) {\n        size_t index = 0;\n        do {\n          ar[index].data = it->data();\n          ar[index].size = it->size();\n          ++it;\n        } while (++index != ar.size() && !it.at_end());\n        // We static_cast index to a signed type to work around overzealous\n        // compiler warnings about signedness.\n        v.insert(v.end(), ar.begin(),\n                 ar.begin() + static_cast<ptrdiff_t>(index));\n      }\n      return v;\n    }\n  };\n\n  // Partial specialization for a std::vector<std::string>.\n  //\n  // Optimized for the common case of splitting to a std::vector<std::string>.\n  // In this case we first split the results to a std::vector<absl::string_view>\n  // so the returned std::vector<std::string> can have space reserved to avoid\n  // std::string moves.\n  template <typename A>\n  struct ConvertToContainer<std::vector<std::string, A>, std::string, false> {\n    std::vector<std::string, A> operator()(const Splitter& splitter) const {\n      const std::vector<absl::string_view> v = splitter;\n      return std::vector<std::string, A>(v.begin(), v.end());\n    }\n  };\n\n  // Partial specialization for containers of pairs (e.g., maps).\n  //\n  // The algorithm is to insert a new pair into the map for each even-numbered\n  // item, with the even-numbered item as the key with a default-constructed\n  // value. Each odd-numbered item will then be assigned to the last pair's\n  // value.\n  template <typename Container, typename First, typename Second>\n  struct ConvertToContainer<Container, std::pair<const First, Second>, true> {\n    using iterator = typename Container::iterator;\n\n    Container operator()(const Splitter& splitter) const {\n      Container m;\n      iterator it;\n      bool insert = true;\n      for (const absl::string_view sv : splitter) {\n        if (insert) {\n          it = InsertOrEmplace(&m, sv);\n        } else {\n          it->second = Second(sv);\n        }\n        insert = !insert;\n      }\n      return m;\n    }\n\n    // Inserts the key and an empty value into the map, returning an iterator to\n    // the inserted item. We use emplace() if available, otherwise insert().\n    template <typename M>\n    static absl::enable_if_t<HasEmplace<M>::value, iterator> InsertOrEmplace(\n        M* m, absl::string_view key) {\n      // Use piecewise_construct to support old versions of gcc in which pair\n      // constructor can't otherwise construct string from string_view.\n      return ToIter(m->emplace(std::piecewise_construct, std::make_tuple(key),\n                               std::tuple<>()));\n    }\n    template <typename M>\n    static absl::enable_if_t<!HasEmplace<M>::value, iterator> InsertOrEmplace(\n        M* m, absl::string_view key) {\n      return ToIter(m->insert(std::make_pair(First(key), Second(\"\"))));\n    }\n\n    static iterator ToIter(std::pair<iterator, bool> pair) {\n      return pair.first;\n    }\n    static iterator ToIter(iterator iter) { return iter; }\n  };\n\n  StringType text_;\n  Delimiter delimiter_;\n  Predicate predicate_;\n};\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_\n"
  },
  {
    "path": "absl/strings/internal/string_constant.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_\n#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_\n\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// StringConstant<T> represents a compile time string constant.\n// It can be accessed via its `absl::string_view value` static member.\n// It is guaranteed that the `string_view` returned has constant `.data()`,\n// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`\n//\n// The `T` is an opaque type. It is guaranteed that different string constants\n// will have different values of `T`. This allows users to associate the string\n// constant with other static state at compile time.\n//\n// Instances should be made using the `MakeStringConstant()` factory function\n// below.\ntemplate <typename T>\nstruct StringConstant {\n private:\n  static constexpr bool TryConstexprEval(absl::string_view view) {\n    return view.empty() || 2 * view[0] != 1;\n  }\n\n public:\n  static constexpr absl::string_view value = T{}();\n  constexpr absl::string_view operator()() const { return value; }\n\n  // Check to be sure `view` points to constant data.\n  // Otherwise, it can't be constant evaluated.\n  static_assert(TryConstexprEval(value),\n                \"The input string_view must point to constant data.\");\n};\n\n// Factory function for `StringConstant` instances.\n// It supports callables that have a constexpr default constructor and a\n// constexpr operator().\n// It must return an `absl::string_view` or `const char*` pointing to constant\n// data. This is validated at compile time.\ntemplate <typename T>\nconstexpr StringConstant<T> MakeStringConstant(T) {\n  return {};\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_\n"
  },
  {
    "path": "absl/strings/internal/string_constant_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/string_constant.h\"\n\n#include \"absl/meta/type_traits.h\"\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nnamespace {\n\nusing absl::strings_internal::MakeStringConstant;\n\nstruct Callable {\n  constexpr absl::string_view operator()() const {\n    return absl::string_view(\"Callable\", 8);\n  }\n};\n\nTEST(StringConstant, Traits) {\n  constexpr auto str = MakeStringConstant(Callable{});\n  using T = decltype(str);\n\n  EXPECT_TRUE(std::is_empty<T>::value);\n  EXPECT_TRUE(std::is_trivial<T>::value);\n  EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);\n  EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);\n  EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);\n  EXPECT_TRUE(absl::is_trivially_destructible<T>::value);\n}\n\nTEST(StringConstant, MakeFromCallable) {\n  constexpr auto str = MakeStringConstant(Callable{});\n  using T = decltype(str);\n  EXPECT_EQ(Callable{}(), T::value);\n  EXPECT_EQ(Callable{}(), str());\n}\n\nTEST(StringConstant, MakeFromStringConstant) {\n  // We want to make sure the StringConstant itself is a valid input to the\n  // factory function.\n  constexpr auto str = MakeStringConstant(Callable{});\n  constexpr auto str2 = MakeStringConstant(str);\n  using T = decltype(str2);\n  EXPECT_EQ(Callable{}(), T::value);\n  EXPECT_EQ(Callable{}(), str2());\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/internal/stringify_sink.cc",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/stringify_sink.h\"\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nvoid StringifySink::Append(size_t count, char ch) { buffer_.append(count, ch); }\n\nvoid StringifySink::Append(string_view v) {\n  buffer_.append(v.data(), v.size());\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/stringify_sink.h",
    "content": "// Copyright 2022 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_\n#define ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_\n\n#include <array>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/source_location.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace strings_internal {\nclass StringifySink {\n public:\n  void Append(size_t count, char ch);\n\n  void Append(string_view v);\n\n  // Support `absl::Format(&sink, format, args...)`.\n  friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {\n    sink->Append(v);\n  }\n\n private:\n  template <typename T>\n  friend string_view ExtractStringification(StringifySink& sink, const T& v);\n\n  std::string buffer_;\n};\n\ntemplate <typename T>\nstring_view ExtractStringification(StringifySink& sink, const T& v) {\n  AbslStringify(sink, v);\n  return sink.buffer_;\n}\n\n}  // namespace strings_internal\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, SourceLocation l) {\n  sink.Append(l.file_name());\n  sink.Append(\":\");\n  std::array<char, numbers_internal::kFastToBufferSize> buffer;\n  numbers_internal::FastIntToBuffer(l.line(), buffer.data());\n  sink.Append(buffer.data());\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_\n"
  },
  {
    "path": "absl/strings/internal/stringify_stream.h",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: stringify_stream.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_STRINGS_INTERNAL_STRINGIFY_STREAM_H_\n#define ABSL_STRINGS_INTERNAL_STRINGIFY_STREAM_H_\n\n// StringifyStream is an adaptor for any std::ostream, that provides a\n// stream insertion (<<) operator with the following behavior when inserting\n// some value of type T:\n//\n//   - If there is a suitable overload of operator<< already defined for T, it\n//     will be used.\n//\n//   - If there is no operator<< overload, but there is an AbslStringify defined\n//     for T, it will be used as a fallback.\n//\n//   - Otherwise it is a compilation error.\n//\n// For reference, AbslStringify typically has the form:\n//\n//   struct Foo {\n//     template <typename Sink>\n//     friend void AbslStringify(Sink& sink, const Foo& foo) { ... }\n//   };\n//\n// This permits the following usage, for example:\n//\n//   StringifyStream(std::cout) << Foo();\n//\n\n#include <cstddef>\n#include <ostream>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace strings_internal {\n\nclass StringifyStream {\n public:\n  // Constructor: adapts (but does not take ownership of) some underlying\n  // std::ostream instance.\n  explicit StringifyStream(std::ostream& os) : sink_{os} {}\n\n  // Stream insertion: delegate to an overload of operator<< if defined for type\n  // T, otherwise fall back to AbslStringify for T.\n  template <typename T>\n  friend StringifyStream& operator<<(StringifyStream& stream, const T& t) {\n    if constexpr (HasStreamInsertion<T>::value) {\n      stream.sink_.os << t;\n    } else {\n      AbslStringify(stream.sink_, t);\n    }\n    return stream;\n  }\n\n  // Rvalue-ref overload, required when the StringifyStream parameter hasn't\n  // been bound to a variable.\n  template <typename T>\n  friend StringifyStream& operator<<(StringifyStream&& stream, const T& t) {\n    return stream << t;\n  }\n\n private:\n  // Abseil \"stringify sink\" concept (stringify_sink.h)\n  struct Sink {\n    std::ostream& os;\n    void Append(size_t count, char ch) { os << std::string(count, ch); }\n    void Append(absl::string_view v) { os << v; }\n    friend void AbslFormatFlush(Sink* sink, absl::string_view v) {\n      sink->Append(v);\n    }\n  } sink_;\n\n  // SFINAE helper to identify types with a defined operator<< overload.\n  template <typename T, typename = void>\n  struct HasStreamInsertion : std::false_type {};\n\n  template <typename T>\n  struct HasStreamInsertion<T,\n                            std::void_t<decltype(std::declval<std::ostream&>()\n                                                 << std::declval<const T&>())>>\n      : std::true_type {};\n};\n\n}  // namespace strings_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_STRINGIFY_STREAM_H_\n"
  },
  {
    "path": "absl/strings/internal/stringify_stream_test.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/stringify_stream.h\"\n\n#include <cstddef>\n#include <ostream>\n#include <sstream>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\nnamespace {\n\n// Exercises the Append(size_t, char) overload\nstruct AppendNCharsTest {\n  size_t count;\n  char ch;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const AppendNCharsTest& t) {\n    sink.Append(t.count, t.ch);\n  }\n};\nTEST(StringifyStreamTest, AppendNChars) {\n  std::ostringstream os;\n  StringifyStream(os) << AppendNCharsTest{5, 'a'};\n  EXPECT_EQ(os.str(), \"aaaaa\");\n}\n\n// Exercises the Append(absl::string_view) overload\nstruct AppendStringViewTest {\n  absl::string_view v;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const AppendStringViewTest& t) {\n    sink.Append(t.v);\n  }\n};\nTEST(StringifyStreamTest, AppendStringView) {\n  std::ostringstream os;\n  StringifyStream(os) << AppendStringViewTest{\"abc\"};\n  EXPECT_EQ(os.str(), \"abc\");\n}\n\n// Exercises AbslFormatFlush(OStringStreamSink*, absl::string_view v)\nstruct AbslFormatFlushTest {\n  absl::string_view a, b, c;\n\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const AbslFormatFlushTest& t) {\n    absl::Format(&sink, \"%s, %s, %s\", t.a, t.b, t.c);\n  }\n};\nTEST(StringifyStreamTest, AbslFormatFlush) {\n  std::ostringstream os;\n  StringifyStream(os) << AbslFormatFlushTest{\"a\", \"b\", \"c\"};\n  EXPECT_EQ(os.str(), \"a, b, c\");\n}\n\n// If overloads of both AbslStringify and operator<< are defined for the type,\n// the operator<< overload should take precedence.\nstruct PreferStreamInsertionOverAbslStringifyTest {\n  friend std::ostream& operator<<(  // NOLINT(clang-diagnostic-unused-function)\n      std::ostream& os, const PreferStreamInsertionOverAbslStringifyTest&) {\n    return os << \"good\";\n  }\n\n  template <typename Sink>\n  friend void AbslStringify  // NOLINT(clang-diagnostic-unused-function)\n      (Sink& sink, const PreferStreamInsertionOverAbslStringifyTest&) {\n    sink.Append(\"bad\");\n  }\n};\nTEST(StringifyStreamTest, PreferStreamInsertionOverAbslStringify) {\n  std::ostringstream os;\n  StringifyStream(os) << PreferStreamInsertionOverAbslStringifyTest{};\n  EXPECT_EQ(os.str(), \"good\");\n}\n\n}  // namespace\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/utf8.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// UTF8 utilities, implemented to reduce dependencies.\n\n#include \"absl/strings/internal/utf8.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nsize_t EncodeUTF8Char(char* buffer, char32_t utf8_char) {\n  if (utf8_char <= 0x7F) {\n    *buffer = static_cast<char>(utf8_char);\n    return 1;\n  } else if (utf8_char <= 0x7FF) {\n    buffer[1] = static_cast<char>(0x80 | (utf8_char & 0x3F));\n    utf8_char >>= 6;\n    buffer[0] = static_cast<char>(0xC0 | utf8_char);\n    return 2;\n  } else if (utf8_char <= 0xFFFF) {\n    buffer[2] = static_cast<char>(0x80 | (utf8_char & 0x3F));\n    utf8_char >>= 6;\n    buffer[1] = static_cast<char>(0x80 | (utf8_char & 0x3F));\n    utf8_char >>= 6;\n    buffer[0] = static_cast<char>(0xE0 | utf8_char);\n    return 3;\n  } else {\n    buffer[3] = static_cast<char>(0x80 | (utf8_char & 0x3F));\n    utf8_char >>= 6;\n    buffer[2] = static_cast<char>(0x80 | (utf8_char & 0x3F));\n    utf8_char >>= 6;\n    buffer[1] = static_cast<char>(0x80 | (utf8_char & 0x3F));\n    utf8_char >>= 6;\n    buffer[0] = static_cast<char>(0xF0 | utf8_char);\n    return 4;\n  }\n}\n\nsize_t WideToUtf8(wchar_t wc, char* buf, ShiftState& s) {\n  // Reinterpret the output buffer `buf` as `unsigned char*` for subsequent\n  // bitwise operations. This ensures well-defined behavior for bit\n  // manipulations (avoiding issues with signed `char`) and is safe under C++\n  // aliasing rules, as `unsigned char` can alias any type.\n  auto* ubuf = reinterpret_cast<unsigned char*>(buf);\n  const uint32_t v = static_cast<uint32_t>(wc);\n  constexpr size_t kError = static_cast<size_t>(-1);\n\n  if (v <= 0x007F) {\n    // 1-byte sequence (U+0000 to U+007F).\n    // 0xxxxxxx.\n    ubuf[0] = (0b0111'1111 & v);\n    s = {};  // Reset surrogate state.\n    return 1;\n  } else if (0x0080 <= v && v <= 0x07FF) {\n    // 2-byte sequence (U+0080 to U+07FF).\n    // 110xxxxx 10xxxxxx.\n    ubuf[0] = 0b1100'0000 | (0b0001'1111 & (v >> 6));\n    ubuf[1] = 0b1000'0000 | (0b0011'1111 & v);\n    s = {};  // Reset surrogate state.\n    return 2;\n  } else if ((0x0800 <= v && v <= 0xD7FF) || (0xE000 <= v && v <= 0xFFFF)) {\n    // 3-byte sequence (U+0800 to U+D7FF or U+E000 to U+FFFF).\n    // Excludes surrogate code points U+D800-U+DFFF.\n    // 1110xxxx 10xxxxxx 10xxxxxx.\n    ubuf[0] = 0b1110'0000 | (0b0000'1111 & (v >> 12));\n    ubuf[1] = 0b1000'0000 | (0b0011'1111 & (v >> 6));\n    ubuf[2] = 0b1000'0000 | (0b0011'1111 & v);\n    s = {};  // Reset surrogate state.\n    return 3;\n  } else if (0xD800 <= v && v <= 0xDBFF) {\n    // High Surrogate (U+D800 to U+DBFF).\n    // This part forms the first two bytes of an eventual 4-byte UTF-8 sequence.\n    const unsigned char high_bits_val = (0b0000'1111 & (v >> 6)) + 1;\n\n    // First byte of the 4-byte UTF-8 sequence (11110xxx).\n    ubuf[0] = 0b1111'0000 | (0b0000'0111 & (high_bits_val >> 2));\n    // Second byte of the 4-byte UTF-8 sequence (10xxxxxx).\n    ubuf[1] = 0b1000'0000 |                           //\n              (0b0011'0000 & (high_bits_val << 4)) |  //\n              (0b0000'1111 & (v >> 2));\n    // Set state for high surrogate after writing to buffer.\n    s = {true, static_cast<unsigned char>(0b0000'0011 & v)};\n    return 2;  // Wrote 2 bytes, expecting 2 more from a low surrogate.\n  } else if (0xDC00 <= v && v <= 0xDFFF) {\n    // Low Surrogate (U+DC00 to U+DFFF).\n    // This part forms the last two bytes of a 4-byte UTF-8 sequence,\n    // using state from a preceding high surrogate.\n    if (!s.saw_high_surrogate) {\n      // Error: Isolated low surrogate without a preceding high surrogate.\n      // s remains in its current (problematic) state.\n      // Caller should handle error.\n      return kError;\n    }\n\n    // Third byte of the 4-byte UTF-8 sequence (10xxxxxx).\n    ubuf[0] = 0b1000'0000 |                    //\n              (0b0011'0000 & (s.bits << 4)) |  //\n              (0b0000'1111 & (v >> 6));\n    // Fourth byte of the 4-byte UTF-8 sequence (10xxxxxx).\n    ubuf[1] = 0b1000'0000 | (0b0011'1111 & v);\n\n    s = {};    // Reset surrogate state, pair complete.\n    return 2;  // Wrote 2 more bytes, completing the 4-byte sequence.\n  } else if constexpr (0xFFFF < std::numeric_limits<wchar_t>::max()) {\n    // Conditionally compile the 4-byte direct conversion branch.\n    // This block is compiled only if wchar_t can represent values > 0xFFFF.\n    // It's placed after surrogate checks to ensure surrogates are handled by\n    // their specific logic. This inner 'if' is the runtime check for the 4-byte\n    // range. At this point, v is known not to be in the 1, 2, or 3-byte BMP\n    // ranges, nor is it a surrogate code point.\n    if (0x10000 <= v && v <= 0x10FFFF) {\n      // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.\n      ubuf[0] = 0b1111'0000 | (0b0000'0111 & (v >> 18));\n      ubuf[1] = 0b1000'0000 | (0b0011'1111 & (v >> 12));\n      ubuf[2] = 0b1000'0000 | (0b0011'1111 & (v >> 6));\n      ubuf[3] = 0b1000'0000 | (0b0011'1111 & v);\n      s = {};  // Reset surrogate state.\n      return 4;\n    }\n  }\n\n  // Invalid wchar_t value (e.g., out of Unicode range, or unhandled after all\n  // checks).\n  s = {};  // Reset surrogate state.\n  return kError;\n}\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/internal/utf8.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// UTF8 utilities, implemented to reduce dependencies.\n\n#ifndef ABSL_STRINGS_INTERNAL_UTF8_H_\n#define ABSL_STRINGS_INTERNAL_UTF8_H_\n\n#include <cstddef>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\n// For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes\n// out the UTF-8 encoding into buffer, and returns the number of chars\n// it wrote.\n//\n// As described in https://tools.ietf.org/html/rfc3629#section-3 , the encodings\n// are:\n//    00 -     7F : 0xxxxxxx\n//    80 -    7FF : 110xxxxx 10xxxxxx\n//   800 -   FFFF : 1110xxxx 10xxxxxx 10xxxxxx\n// 10000 - 10FFFF : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n//\n// Values greater than 0x10FFFF are not supported and may or may not write\n// characters into buffer, however never will more than kMaxEncodedUTF8Size\n// bytes be written, regardless of the value of utf8_char.\nenum { kMaxEncodedUTF8Size = 4 };\nsize_t EncodeUTF8Char(char* buffer, char32_t utf8_char);\n\nstruct ShiftState {\n  bool saw_high_surrogate = false;\n  unsigned char bits = 0;\n};\n\n// Converts `wc` from UTF-16 or UTF-32 to UTF-8 and writes to `buf`. `buf` is\n// assumed to have enough space for the output. `s` is used to carry state\n// between successive calls with a UTF-16 surrogate pair. Returns the number of\n// chars written, or `static_cast<size_t>(-1)` on failure.\n//\n// This is basically std::wcrtomb(), but always outputting UTF-8 instead of\n// respecting the current locale.\nsize_t WideToUtf8(wchar_t wc, char* buf, ShiftState& s);\n\n}  // namespace strings_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_INTERNAL_UTF8_H_\n"
  },
  {
    "path": "absl/strings/internal/utf8_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/internal/utf8.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/port.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nusing ::absl::strings_internal::kMaxEncodedUTF8Size;\nusing ::absl::strings_internal::ShiftState;\nusing ::absl::strings_internal::WideToUtf8;\nusing ::testing::StartsWith;\nusing ::testing::TestParamInfo;\nusing ::testing::TestWithParam;\nusing ::testing::ValuesIn;\n\n#if !defined(__cpp_char8_t)\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wc++2a-compat\"\n#endif\nTEST(EncodeUTF8Char, BasicFunction) {\n  std::pair<char32_t, std::string> tests[] = {{0x0030, u8\"\\u0030\"},\n                                              {0x00A3, u8\"\\u00A3\"},\n                                              {0x00010000, u8\"\\U00010000\"},\n                                              {0x0000FFFF, u8\"\\U0000FFFF\"},\n                                              {0x0010FFFD, u8\"\\U0010FFFD\"}};\n  for (auto& test : tests) {\n    char buf0[7] = {'\\x00', '\\x00', '\\x00', '\\x00', '\\x00', '\\x00', '\\x00'};\n    char buf1[7] = {'\\xFF', '\\xFF', '\\xFF', '\\xFF', '\\xFF', '\\xFF', '\\xFF'};\n    char* buf0_written =\n        &buf0[absl::strings_internal::EncodeUTF8Char(buf0, test.first)];\n    char* buf1_written =\n        &buf1[absl::strings_internal::EncodeUTF8Char(buf1, test.first)];\n    int apparent_length = 7;\n    while (buf0[apparent_length - 1] == '\\x00' &&\n           buf1[apparent_length - 1] == '\\xFF') {\n      if (--apparent_length == 0) break;\n    }\n    EXPECT_EQ(apparent_length, buf0_written - buf0);\n    EXPECT_EQ(apparent_length, buf1_written - buf1);\n    EXPECT_EQ(apparent_length, test.second.length());\n    EXPECT_EQ(std::string(buf0, apparent_length), test.second);\n    EXPECT_EQ(std::string(buf1, apparent_length), test.second);\n  }\n  char buf[32] = \"Don't Tread On Me\";\n  EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf, 0x00110000),\n            absl::strings_internal::kMaxEncodedUTF8Size);\n  char buf2[32] = \"Negative is invalid but sane\";\n  EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf2, -1),\n            absl::strings_internal::kMaxEncodedUTF8Size);\n}\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n#endif  // !defined(__cpp_char8_t)\n\nstruct WideToUtf8TestCase {\n  std::string description;\n  wchar_t input;\n  std::string expected_utf8_str;\n  size_t expected_bytes_written;\n  ShiftState initial_state = {false, 0};\n  ShiftState expected_state = {false, 0};\n};\n\nstd::vector<WideToUtf8TestCase> GetWideToUtf8TestCases() {\n  constexpr size_t kError = static_cast<size_t>(-1);\n  std::vector<WideToUtf8TestCase> cases = {\n      {\"ASCII_A\", L'A', \"A\", 1},\n      {\"NullChar\", L'\\0', std::string(\"\\0\", 1), 1},\n      {\"ASCII_Max_7F\", L'\\x7F', \"\\x7F\", 1},\n\n      {\"TwoByte_Min_80\", L'\\u0080', \"\\xC2\\x80\", 2},\n      {\"PoundSign_A3\", L'\\u00A3', \"\\xC2\\xA3\", 2},\n      {\"TwoByte_Max_7FF\", L'\\u07FF', \"\\xDF\\xBF\", 2},\n\n      {\"ThreeByte_Min_800\", L'\\u0800', \"\\xE0\\xA0\\x80\", 3},\n      {\"EuroSign_20AC\", L'\\u20AC', \"\\xE2\\x82\\xAC\", 3},\n      {\"BMP_MaxBeforeSurrogates_D7FF\", L'\\uD7FF', \"\\xED\\x9F\\xBF\", 3},\n      {\"BMP_FFFF\", L'\\uFFFF', \"\\xEF\\xBF\\xBF\", 3},\n\n      {\"IsolatedHighSurr_D800\", L'\\xD800', \"\\xF0\\x90\", 2, {}, {true, 0}},\n      {\"IsolatedHighSurr_DBFF\", L'\\xDBFF', \"\\xF4\\x8F\", 2, {}, {true, 3}},\n\n      {\"HighSurr_D800_after_HighD800\",\n       L'\\xD800',\n       \"\\xF0\\x90\",\n       2,\n       {true, 0},\n       {true, 0}},\n      {\"HighSurr_DBFF_after_HighDBFF\",\n       L'\\xDBFF',\n       \"\\xF4\\x8F\",\n       2,\n       {true, 3},\n       {true, 3}},\n\n      {\"LowSurr_DC00_after_HighD800\", L'\\xDC00', \"\\x80\\x80\", 2, {true, 0}, {}},\n      {\"LowSurr_DFFD_after_HighDBFF\", L'\\xDFFD', \"\\xBF\\xBD\", 2, {true, 3}, {}},\n      {\"LowSurr_DC00_with_InitialState_saw_high_bits_1\",\n       L'\\xDC00',\n       \"\\x90\\x80\",\n       2,\n       {true, 1},\n       {}},\n\n      // Final state = initial on error.\n      {\"Error_IsolatedLowSurr_DC00_NoPriorHigh\", L'\\xDC00', \"\", kError, {}, {}},\n      {\"Error_IsolatedLowSurr_DFFF_NoPriorHigh\", L'\\xDFFF', \"\", kError, {}, {}},\n\n#if (defined(WCHAR_MAX) && WCHAR_MAX > 0xFFFF)\n      {\"DirectSupplementaryChars_U10000\", static_cast<wchar_t>(0x10000),\n       \"\\xF0\\x90\\x80\\x80\", 4},\n      {\"DirectSupplementaryChars_U10FFFD\", static_cast<wchar_t>(0x10FFFD),\n       \"\\xF4\\x8F\\xBF\\xBD\", 4},\n#endif\n  };\n\n  wchar_t minus_one = static_cast<wchar_t>(-1);\n  if constexpr (sizeof(wchar_t) == 2) {\n    cases.push_back({\"WChar_MinusOne_as_FFFF\", minus_one, \"\\xEF\\xBF\\xBF\", 3});\n  } else {\n    cases.push_back(\n        {\"Error_WChar_MinusOne_as_FFFFFFFF\", minus_one, \"\", kError, {}, {}});\n  }\n\n  if constexpr (sizeof(wchar_t) >= 4) {\n#ifdef WCHAR_MAX\n    if (static_cast<uintmax_t>(WCHAR_MAX) >= 0x110000UL) {\n      cases.push_back({\"Error_OutOfRange_110000\",\n                       static_cast<wchar_t>(0x110000UL),\n                       \"\",\n                       kError,\n                       {},\n                       {}});\n    }\n#else\n    cases.push_back({\"Error_OutOfRange_110000_fallback\",\n                     static_cast<wchar_t>(0x110000UL),\n                     \"\",\n                     kError,\n                     {},\n                     {}});\n#endif\n  }\n  return cases;\n}\n\nclass WideToUtf8ParamTest : public TestWithParam<WideToUtf8TestCase> {};\n\nTEST_P(WideToUtf8ParamTest, SingleCharConversion) {\n  const auto& test_case = GetParam();\n  ShiftState state = test_case.initial_state;\n  constexpr char kFillChar = '\\xAB';\n  std::string buffer(32, kFillChar);\n\n  size_t bytes_written = WideToUtf8(test_case.input, buffer.data(), state);\n\n  EXPECT_EQ(bytes_written, test_case.expected_bytes_written);\n  EXPECT_THAT(buffer, StartsWith(test_case.expected_utf8_str));\n\n  // The remaining bytes should be unchanged.\n  ASSERT_LT(test_case.expected_utf8_str.length(), buffer.size());\n  EXPECT_EQ(buffer[test_case.expected_utf8_str.length()], kFillChar);\n\n  EXPECT_EQ(state.saw_high_surrogate,\n            test_case.expected_state.saw_high_surrogate);\n  EXPECT_EQ(state.bits, test_case.expected_state.bits);\n}\n\nINSTANTIATE_TEST_SUITE_P(WideCharToUtf8Conversion, WideToUtf8ParamTest,\n                         ValuesIn(GetWideToUtf8TestCases()),\n                         [](auto info) { return info.param.description; });\n\n// Comprehensive test string for validating wchar_t to UTF-8 conversion.\n// This string is designed to cover a variety of Unicode character types and\n// sequences:\n// 1. Basic ASCII characters (within names, numbers, and spacing).\n// 2. Common 2-byte UTF-8 sequences:\n//    - Accented Latin characters (e.g., 'á' in \"Holá\").\n//    - Hebrew text with combining vowel points (e.g., \"שָׁלוֹם\").\n// 3. Common 3-byte UTF-8 sequences:\n//    - Currency symbols (e.g., '€').\n//    - CJK characters (e.g., \"你好\", \"中\").\n//    - Components of complex emojis like the Zero Width Joiner (ZWJ) and\n//      Heart symbol.\n// 4. Various 4-byte UTF-8 sequences (representing Supplementary Plane\n// characters):\n//    - An emoji with a skin tone modifier (\"👍🏻\").\n//    - A flag emoji composed of regional indicators (\"🇺🇸\").\n//    - A complex ZWJ emoji sequence (\"👩‍❤️‍💋‍👨\") combining\n//      SP characters (👩, 💋, 👨) with BMP characters (ZWJ and ❤️).\n//    - These are critical for testing the correct handling of surrogate pairs\n//      when wchar_t is 2 bytes (e.g., on Windows).\n// The goal is to ensure accurate conversion across a diverse set of\n// characters.\n//\n// clang-format off\n#define WIDE_STRING_LITERAL L\"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中\"\n#define UTF8_STRING_LITERAL u8\"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中\"\n// clang-format on\n\nabsl::string_view GetUtf8TestString() {\n  // `u8\"\"` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn)\n  // without it. However, the resulting character type differs between pre-C++20\n  // (`char`) and C++20 (`char8_t`). So deduce the right character type for all\n  // C++ versions, init it with UTF-8, then `memcpy()` to get the result as a\n  // `char*`\n  static absl::string_view kUtf8TestString = [] {\n    using ConstChar8T = std::remove_reference_t<decltype(*u8\"a\")>;\n    constexpr ConstChar8T kOutputUtf8[] = UTF8_STRING_LITERAL;\n    static char output[sizeof kOutputUtf8];\n    std::memcpy(output, kOutputUtf8, sizeof kOutputUtf8);\n    return output;\n  }();\n\n  return kUtf8TestString;\n}\n\nTEST(WideToUtf8, FullString) {\n  std::string buffer(kMaxEncodedUTF8Size * sizeof(WIDE_STRING_LITERAL), '\\0');\n  char* buffer_ptr = buffer.data();\n\n  ShiftState state;\n  for (const wchar_t wc : WIDE_STRING_LITERAL) {\n    buffer_ptr += WideToUtf8(wc, buffer_ptr, state);\n  }\n\n  EXPECT_THAT(buffer, StartsWith(GetUtf8TestString()));\n}\n\n#undef WIDE_STRING_LITERAL\n#undef UTF8_STRING_LITERAL\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/match.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/match.h\"\n\n#include <algorithm>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/internal/memutil.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nbool EqualsIgnoreCase(absl::string_view piece1,\n                      absl::string_view piece2) noexcept {\n  return (piece1.size() == piece2.size() &&\n          0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),\n                                                  piece1.size()));\n  // memcasecmp uses absl::ascii_tolower().\n}\n\nbool StrContainsIgnoreCase(absl::string_view haystack,\n                           absl::string_view needle) noexcept {\n  while (haystack.size() >= needle.size()) {\n    if (StartsWithIgnoreCase(haystack, needle)) return true;\n    haystack.remove_prefix(1);\n  }\n  return false;\n}\n\nbool StrContainsIgnoreCase(absl::string_view haystack,\n                           char needle) noexcept {\n  char upper_needle = absl::ascii_toupper(static_cast<unsigned char>(needle));\n  char lower_needle = absl::ascii_tolower(static_cast<unsigned char>(needle));\n  if (upper_needle == lower_needle) {\n    return StrContains(haystack, needle);\n  } else {\n    const char both_cstr[3] = {lower_needle, upper_needle, '\\0'};\n    return haystack.find_first_of(both_cstr) != absl::string_view::npos;\n  }\n}\n\nbool StartsWithIgnoreCase(absl::string_view text,\n                          absl::string_view prefix) noexcept {\n  return (text.size() >= prefix.size()) &&\n         EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);\n}\n\nbool EndsWithIgnoreCase(absl::string_view text,\n                        absl::string_view suffix) noexcept {\n  return (text.size() >= suffix.size()) &&\n         EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);\n}\n\nabsl::string_view FindLongestCommonPrefix(absl::string_view a,\n                                          absl::string_view b) {\n  const absl::string_view::size_type limit = std::min(a.size(), b.size());\n  const char* const pa = a.data();\n  const char* const pb = b.data();\n  absl::string_view::size_type count = (unsigned) 0;\n\n  if (ABSL_PREDICT_FALSE(limit < 8)) {\n    while (ABSL_PREDICT_TRUE(count + 2 <= limit)) {\n      uint16_t xor_bytes = absl::little_endian::Load16(pa + count) ^\n                           absl::little_endian::Load16(pb + count);\n      if (ABSL_PREDICT_FALSE(xor_bytes != 0)) {\n        if (ABSL_PREDICT_TRUE((xor_bytes & 0xff) == 0)) ++count;\n        return absl::string_view(pa, count);\n      }\n      count += 2;\n    }\n    if (ABSL_PREDICT_TRUE(count != limit)) {\n      if (ABSL_PREDICT_TRUE(pa[count] == pb[count])) ++count;\n    }\n    return absl::string_view(pa, count);\n  }\n\n  do {\n    uint64_t xor_bytes = absl::little_endian::Load64(pa + count) ^\n                         absl::little_endian::Load64(pb + count);\n    if (ABSL_PREDICT_FALSE(xor_bytes != 0)) {\n      count += static_cast<uint64_t>(absl::countr_zero(xor_bytes) >> 3);\n      return absl::string_view(pa, count);\n    }\n    count += 8;\n  } while (ABSL_PREDICT_TRUE(count + 8 < limit));\n\n  count = limit - 8;\n  uint64_t xor_bytes = absl::little_endian::Load64(pa + count) ^\n                       absl::little_endian::Load64(pb + count);\n  if (ABSL_PREDICT_TRUE(xor_bytes != 0)) {\n    count += static_cast<uint64_t>(absl::countr_zero(xor_bytes) >> 3);\n    return absl::string_view(pa, count);\n  }\n  return absl::string_view(pa, limit);\n}\n\nabsl::string_view FindLongestCommonSuffix(absl::string_view a,\n                                          absl::string_view b) {\n  const absl::string_view::size_type limit = std::min(a.size(), b.size());\n  if (limit == 0) return absl::string_view();\n\n  const char* pa = a.data() + a.size() - 1;\n  const char* pb = b.data() + b.size() - 1;\n  absl::string_view::size_type count = (unsigned) 0;\n  while (count < limit && *pa == *pb) {\n    --pa;\n    --pb;\n    ++count;\n  }\n\n  return absl::string_view(++pa, count);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/match.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: match.h\n// -----------------------------------------------------------------------------\n//\n// This file contains simple utilities for performing string matching checks.\n// All of these function parameters are specified as `absl::string_view`,\n// meaning that these functions can accept `std::string`, `absl::string_view` or\n// NUL-terminated C-style strings.\n//\n// Examples:\n//   std::string s = \"foo\";\n//   absl::string_view sv = \"f\";\n//   assert(absl::StrContains(s, sv));\n//\n// Note: The order of parameters in these functions is designed to mimic the\n// order an equivalent member function would exhibit;\n// e.g. `s.Contains(x)` ==> `absl::StrContains(s, x).\n#ifndef ABSL_STRINGS_MATCH_H_\n#define ABSL_STRINGS_MATCH_H_\n\n#include <cstring>\n\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// StrContains()\n//\n// Returns whether a given string `haystack` contains the substring `needle`.\ninline bool StrContains(absl::string_view haystack,\n                        absl::string_view needle) noexcept {\n  return haystack.find(needle, 0) != haystack.npos;\n}\n\ninline bool StrContains(absl::string_view haystack, char needle) noexcept {\n  return haystack.find(needle) != haystack.npos;\n}\n\n// StartsWith()\n//\n// Returns whether a given string `text` begins with `prefix`.\ninline constexpr bool StartsWith(absl::string_view text,\n                                 absl::string_view prefix) noexcept {\n  if (prefix.empty()) {\n    return true;\n  }\n  if (text.size() < prefix.size()) {\n    return false;\n  }\n  absl::string_view possible_match = text.substr(0, prefix.size());\n\n  return possible_match == prefix;\n}\n\n// EndsWith()\n//\n// Returns whether a given string `text` ends with `suffix`.\ninline constexpr bool EndsWith(absl::string_view text,\n                               absl::string_view suffix) noexcept {\n  if (suffix.empty()) {\n    return true;\n  }\n  if (text.size() < suffix.size()) {\n    return false;\n  }\n  absl::string_view possible_match = text.substr(text.size() - suffix.size());\n  return possible_match == suffix;\n}\n// StrContainsIgnoreCase()\n//\n// Returns whether a given ASCII string `haystack` contains the ASCII substring\n// `needle`, ignoring case in the comparison.\nbool StrContainsIgnoreCase(absl::string_view haystack,\n                           absl::string_view needle) noexcept;\n\nbool StrContainsIgnoreCase(absl::string_view haystack,\n                           char needle) noexcept;\n\n// EqualsIgnoreCase()\n//\n// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring\n// case in the comparison.\nbool EqualsIgnoreCase(absl::string_view piece1,\n                      absl::string_view piece2) noexcept;\n\n// StartsWithIgnoreCase()\n//\n// Returns whether a given ASCII string `text` starts with `prefix`,\n// ignoring case in the comparison.\nbool StartsWithIgnoreCase(absl::string_view text,\n                          absl::string_view prefix) noexcept;\n\n// EndsWithIgnoreCase()\n//\n// Returns whether a given ASCII string `text` ends with `suffix`, ignoring\n// case in the comparison.\nbool EndsWithIgnoreCase(absl::string_view text,\n                        absl::string_view suffix) noexcept;\n\n// Yields the longest prefix in common between both input strings.\n// Pointer-wise, the returned result is a subset of input \"a\".\nabsl::string_view FindLongestCommonPrefix(absl::string_view a,\n                                          absl::string_view b);\n\n// Yields the longest suffix in common between both input strings.\n// Pointer-wise, the returned result is a subset of input \"a\".\nabsl::string_view FindLongestCommonSuffix(absl::string_view a,\n                                          absl::string_view b);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_MATCH_H_\n"
  },
  {
    "path": "absl/strings/match_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/match.h\"\n\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nTEST(MatchTest, StartsWith) {\n  const std::string s1(\"123\\0abc\", 7);\n  const absl::string_view a(\"foobar\");\n  const absl::string_view b(s1);\n  const absl::string_view e;\n  EXPECT_TRUE(absl::StartsWith(a, a));\n  EXPECT_TRUE(absl::StartsWith(a, \"foo\"));\n  EXPECT_TRUE(absl::StartsWith(a, e));\n  EXPECT_TRUE(absl::StartsWith(b, s1));\n  EXPECT_TRUE(absl::StartsWith(b, b));\n  EXPECT_TRUE(absl::StartsWith(b, e));\n  EXPECT_TRUE(absl::StartsWith(e, \"\"));\n  EXPECT_FALSE(absl::StartsWith(a, b));\n  EXPECT_FALSE(absl::StartsWith(b, a));\n  EXPECT_FALSE(absl::StartsWith(e, a));\n}\n\nTEST(MatchTest, EndsWith) {\n  const std::string s1(\"123\\0abc\", 7);\n  const absl::string_view a(\"foobar\");\n  const absl::string_view b(s1);\n  const absl::string_view e;\n  EXPECT_TRUE(absl::EndsWith(a, a));\n  EXPECT_TRUE(absl::EndsWith(a, \"bar\"));\n  EXPECT_TRUE(absl::EndsWith(a, e));\n  EXPECT_TRUE(absl::EndsWith(b, s1));\n  EXPECT_TRUE(absl::EndsWith(b, b));\n  EXPECT_TRUE(absl::EndsWith(b, e));\n  EXPECT_TRUE(absl::EndsWith(e, \"\"));\n  EXPECT_FALSE(absl::EndsWith(a, b));\n  EXPECT_FALSE(absl::EndsWith(b, a));\n  EXPECT_FALSE(absl::EndsWith(e, a));\n}\n\nTEST(MatchTest, Contains) {\n  absl::string_view a(\"abcdefg\");\n  absl::string_view b(\"abcd\");\n  absl::string_view c(\"efg\");\n  absl::string_view d(\"gh\");\n  EXPECT_TRUE(absl::StrContains(a, a));\n  EXPECT_TRUE(absl::StrContains(a, b));\n  EXPECT_TRUE(absl::StrContains(a, c));\n  EXPECT_FALSE(absl::StrContains(a, d));\n  EXPECT_TRUE(absl::StrContains(\"\", \"\"));\n  EXPECT_TRUE(absl::StrContains(\"abc\", \"\"));\n  EXPECT_FALSE(absl::StrContains(\"\", \"a\"));\n}\n\nTEST(MatchTest, ContainsChar) {\n  absl::string_view a(\"abcdefg\");\n  absl::string_view b(\"abcd\");\n  EXPECT_TRUE(absl::StrContains(a, 'a'));\n  EXPECT_TRUE(absl::StrContains(a, 'b'));\n  EXPECT_TRUE(absl::StrContains(a, 'e'));\n  EXPECT_FALSE(absl::StrContains(a, 'h'));\n\n  EXPECT_TRUE(absl::StrContains(b, 'a'));\n  EXPECT_TRUE(absl::StrContains(b, 'b'));\n  EXPECT_FALSE(absl::StrContains(b, 'e'));\n  EXPECT_FALSE(absl::StrContains(b, 'h'));\n\n  EXPECT_FALSE(absl::StrContains(\"\", 'a'));\n  EXPECT_FALSE(absl::StrContains(\"\", 'a'));\n}\n\nTEST(MatchTest, ContainsNull) {\n  const std::string s = \"foo\";\n  const char* cs = \"foo\";\n  const absl::string_view sv(\"foo\");\n  const absl::string_view sv2(\"foo\\0bar\", 4);\n  EXPECT_EQ(s, \"foo\");\n  EXPECT_EQ(sv, \"foo\");\n  EXPECT_NE(sv2, \"foo\");\n  EXPECT_TRUE(absl::EndsWith(s, sv));\n  EXPECT_TRUE(absl::StartsWith(cs, sv));\n  EXPECT_TRUE(absl::StrContains(cs, sv));\n  EXPECT_FALSE(absl::StrContains(cs, sv2));\n}\n\nTEST(MatchTest, EqualsIgnoreCase) {\n  std::string text = \"the\";\n  absl::string_view data(text);\n\n  EXPECT_TRUE(absl::EqualsIgnoreCase(data, \"The\"));\n  EXPECT_TRUE(absl::EqualsIgnoreCase(data, \"THE\"));\n  EXPECT_TRUE(absl::EqualsIgnoreCase(data, \"the\"));\n  EXPECT_FALSE(absl::EqualsIgnoreCase(data, \"Quick\"));\n  EXPECT_FALSE(absl::EqualsIgnoreCase(data, \"then\"));\n}\n\nTEST(MatchTest, StartsWithIgnoreCase) {\n  EXPECT_TRUE(absl::StartsWithIgnoreCase(\"foo\", \"foo\"));\n  EXPECT_TRUE(absl::StartsWithIgnoreCase(\"foo\", \"Fo\"));\n  EXPECT_TRUE(absl::StartsWithIgnoreCase(\"foo\", \"\"));\n  EXPECT_FALSE(absl::StartsWithIgnoreCase(\"foo\", \"fooo\"));\n  EXPECT_FALSE(absl::StartsWithIgnoreCase(\"\", \"fo\"));\n}\n\nTEST(MatchTest, EndsWithIgnoreCase) {\n  EXPECT_TRUE(absl::EndsWithIgnoreCase(\"foo\", \"foo\"));\n  EXPECT_TRUE(absl::EndsWithIgnoreCase(\"foo\", \"Oo\"));\n  EXPECT_TRUE(absl::EndsWithIgnoreCase(\"foo\", \"\"));\n  EXPECT_FALSE(absl::EndsWithIgnoreCase(\"foo\", \"fooo\"));\n  EXPECT_FALSE(absl::EndsWithIgnoreCase(\"\", \"fo\"));\n}\n\nTEST(MatchTest, ContainsIgnoreCase) {\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"foo\", \"foo\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"FOO\", \"Foo\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"--FOO\", \"Foo\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"FOO--\", \"Foo\"));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(\"BAR\", \"Foo\"));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(\"BAR\", \"Foo\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"123456\", \"123456\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"123456\", \"234\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"\", \"\"));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(\"abc\", \"\"));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(\"\", \"a\"));\n}\n\nTEST(MatchTest, ContainsCharIgnoreCase) {\n  absl::string_view a(\"AaBCdefg!\");\n  absl::string_view b(\"AaBCd!\");\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'a'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'A'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'b'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'B'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'e'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'E'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(a, 'h'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(a, 'H'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(a, '!'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(a, '?'));\n\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'a'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'A'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'b'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'B'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'e'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'E'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'h'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'H'));\n  EXPECT_TRUE(absl::StrContainsIgnoreCase(b, '!'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(b, '?'));\n\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(\"\", 'a'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(\"\", 'A'));\n  EXPECT_FALSE(absl::StrContainsIgnoreCase(\"\", '0'));\n}\n\nTEST(MatchTest, FindLongestCommonPrefix) {\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"\", \"\"), \"\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"\", \"abc\"), \"\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"abc\", \"\"), \"\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"ab\", \"abc\"), \"ab\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"abc\", \"ab\"), \"ab\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"abc\", \"abd\"), \"ab\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"abc\", \"abcd\"), \"abc\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"abcd\", \"abcd\"), \"abcd\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\"abcd\", \"efgh\"), \"\");\n\n  // \"abcde\" v. \"abc\" but in the middle of other data\n  EXPECT_EQ(absl::FindLongestCommonPrefix(\n                absl::string_view(\"1234 abcdef\").substr(5, 5),\n                absl::string_view(\"5678 abcdef\").substr(5, 3)),\n            \"abc\");\n}\n\n// Since the little-endian implementation involves a bit of if-else and various\n// return paths, the following tests aims to provide full test coverage of the\n// implementation.\nTEST(MatchTest, FindLongestCommonPrefixLoad16Mismatch) {\n  const std::string x1 = \"abcdefgh\";\n  const std::string x2 = \"abcde_\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"abcde\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"abcde\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixLoad16MatchesNoLast) {\n  const std::string x1 = \"abcdef\";\n  const std::string x2 = \"abcdef\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"abcdef\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"abcdef\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixLoad16MatchesLastCharMismatches) {\n  const std::string x1 = \"abcdefg\";\n  const std::string x2 = \"abcdef_h\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"abcdef\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"abcdef\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixLoad16MatchesLastMatches) {\n  const std::string x1 = \"abcde\";\n  const std::string x2 = \"abcdefgh\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"abcde\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"abcde\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixSize8Load64Mismatches) {\n  const std::string x1 = \"abcdefghijk\";\n  const std::string x2 = \"abcde_g_\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"abcde\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"abcde\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixSize8Load64Matches) {\n  const std::string x1 = \"abcdefgh\";\n  const std::string x2 = \"abcdefgh\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"abcdefgh\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"abcdefgh\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixSize15Load64Mismatches) {\n  const std::string x1 = \"012345670123456\";\n  const std::string x2 = \"0123456701_34_6\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"0123456701\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"0123456701\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixSize15Load64Matches) {\n  const std::string x1 = \"012345670123456\";\n  const std::string x2 = \"0123456701234567\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"012345670123456\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"012345670123456\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixSizeFirstByteOfLast8BytesMismatch) {\n  const std::string x1 = \"012345670123456701234567\";\n  const std::string x2 = \"0123456701234567_1234567\";\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), \"0123456701234567\");\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), \"0123456701234567\");\n}\n\nTEST(MatchTest, FindLongestCommonPrefixLargeLastCharMismatches) {\n  const std::string x1(300, 'x');\n  std::string x2 = x1;\n  x2.back() = '#';\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), std::string(299, 'x'));\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), std::string(299, 'x'));\n}\n\nTEST(MatchTest, FindLongestCommonPrefixLargeFullMatch) {\n  const std::string x1(300, 'x');\n  const std::string x2 = x1;\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x1, x2), std::string(300, 'x'));\n  EXPECT_EQ(absl::FindLongestCommonPrefix(x2, x1), std::string(300, 'x'));\n}\n\nTEST(MatchTest, FindLongestCommonSuffix) {\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"\", \"\"), \"\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"\", \"abc\"), \"\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"abc\", \"\"), \"\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"bc\", \"abc\"), \"bc\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"abc\", \"bc\"), \"bc\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"abc\", \"dbc\"), \"bc\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"bcd\", \"abcd\"), \"bcd\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"abcd\", \"abcd\"), \"abcd\");\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\"abcd\", \"efgh\"), \"\");\n\n  // \"abcde\" v. \"cde\" but in the middle of other data\n  EXPECT_EQ(absl::FindLongestCommonSuffix(\n                absl::string_view(\"1234 abcdef\").substr(5, 5),\n                absl::string_view(\"5678 abcdef\").substr(7, 3)),\n            \"cde\");\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/numbers.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file contains string processing functions related to\n// numeric values.\n\n#include \"absl/strings/numbers.h\"\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cfloat>  // for DBL_DIG and FLT_DIG\n#include <cmath>   // for HUGE_VAL\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <iterator>\n#include <limits>\n#include <system_error>  // NOLINT(build/c++11)\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/charconv.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nbool SimpleAtof(absl::string_view str, float* absl_nonnull out) {\n  *out = 0.0;\n  str = StripAsciiWhitespace(str);\n  if (str.empty()) {\n    // absl::from_chars doesn't accept empty strings.\n    return false;\n  }\n  // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one\n  // is present, skip it, while avoiding accepting \"+-0\" as valid.\n  if (str[0] == '+') {\n    str.remove_prefix(1);\n    if (str.empty() || str[0] == '-') {\n      return false;\n    }\n  }\n  auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);\n  if (result.ec == std::errc::invalid_argument) {\n    return false;\n  }\n  if (result.ptr != str.data() + str.size()) {\n    // not all non-whitespace characters consumed\n    return false;\n  }\n  // from_chars() with DR 3081's current wording will return max() on\n  // overflow.  SimpleAtof returns infinity instead.\n  if (result.ec == std::errc::result_out_of_range) {\n    if (*out > 1.0) {\n      *out = std::numeric_limits<float>::infinity();\n    } else if (*out < -1.0) {\n      *out = -std::numeric_limits<float>::infinity();\n    }\n  }\n  return true;\n}\n\nbool SimpleAtod(absl::string_view str, double* absl_nonnull out) {\n  *out = 0.0;\n  str = StripAsciiWhitespace(str);\n  if (str.empty()) {\n    // absl::from_chars doesn't accept empty strings.\n    return false;\n  }\n  // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one\n  // is present, skip it, while avoiding accepting \"+-0\" as valid.\n  if (str[0] == '+') {\n    str.remove_prefix(1);\n    if (str.empty() || str[0] == '-') {\n      return false;\n    }\n  }\n  auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);\n  if (result.ec == std::errc::invalid_argument) {\n    return false;\n  }\n  if (result.ptr != str.data() + str.size()) {\n    // not all non-whitespace characters consumed\n    return false;\n  }\n  // from_chars() with DR 3081's current wording will return max() on\n  // overflow.  SimpleAtod returns infinity instead.\n  if (result.ec == std::errc::result_out_of_range) {\n    if (*out > 1.0) {\n      *out = std::numeric_limits<double>::infinity();\n    } else if (*out < -1.0) {\n      *out = -std::numeric_limits<double>::infinity();\n    }\n  }\n  return true;\n}\n\nbool SimpleAtob(absl::string_view str, bool* absl_nonnull out) {\n  ABSL_RAW_CHECK(out != nullptr, \"Output pointer must not be nullptr.\");\n  if (EqualsIgnoreCase(str, \"true\") || EqualsIgnoreCase(str, \"t\") ||\n      EqualsIgnoreCase(str, \"yes\") || EqualsIgnoreCase(str, \"y\") ||\n      EqualsIgnoreCase(str, \"1\")) {\n    *out = true;\n    return true;\n  }\n  if (EqualsIgnoreCase(str, \"false\") || EqualsIgnoreCase(str, \"f\") ||\n      EqualsIgnoreCase(str, \"no\") || EqualsIgnoreCase(str, \"n\") ||\n      EqualsIgnoreCase(str, \"0\")) {\n    *out = false;\n    return true;\n  }\n  return false;\n}\n\n// ----------------------------------------------------------------------\n// FastIntToBuffer() overloads\n//\n// Like the Fast*ToBuffer() functions above, these are intended for speed.\n// Unlike the Fast*ToBuffer() functions, however, these functions write\n// their output to the beginning of the buffer.  The caller is responsible\n// for ensuring that the buffer has enough space to hold the output.\n//\n// Returns a pointer to the end of the string (i.e. the null character\n// terminating the string).\n// ----------------------------------------------------------------------\n\nnamespace {\n\n// Various routines to encode integers to strings.\n\n// We split data encodings into a group of 2 digits, 4 digits, 8 digits as\n// it's easier to combine powers of two into scalar arithmetic.\n\n// Previous implementation used a lookup table of 200 bytes for every 2 bytes\n// and it was memory bound, any L1 cache miss would result in a much slower\n// result. When benchmarking with a cache eviction rate of several percent,\n// this implementation proved to be better.\n\n// These constants represent '00', '0000' and '00000000' as ascii strings in\n// integers. We can add these numbers if we encode to bytes from 0 to 9. as\n// 'i' = '0' + i for 0 <= i <= 9.\nconstexpr uint32_t kTwoZeroBytes = 0x0101 * '0';\nconstexpr uint64_t kFourZeroBytes = 0x01010101 * '0';\nconstexpr uint64_t kEightZeroBytes = 0x0101010101010101ull * '0';\n\n// * 103 / 1024 is a division by 10 for values from 0 to 99. It's also a\n// division of a structure [k takes 2 bytes][m takes 2 bytes], then * 103 / 1024\n// will be [k / 10][m / 10]. It allows parallel division.\nconstexpr uint64_t kDivisionBy10Mul = 103u;\nconstexpr uint64_t kDivisionBy10Div = 1 << 10;\n\n// * 10486 / 1048576 is a division by 100 for values from 0 to 9999.\nconstexpr uint64_t kDivisionBy100Mul = 10486u;\nconstexpr uint64_t kDivisionBy100Div = 1 << 20;\n\n// Encode functions write the ASCII output of input `n` to `out_str`.\ninline char* EncodeHundred(uint32_t n, char* absl_nonnull out_str) {\n  int num_digits = static_cast<int>(n - 10) >> 8;\n  uint32_t div10 = (n * kDivisionBy10Mul) / kDivisionBy10Div;\n  uint32_t mod10 = n - 10u * div10;\n  uint32_t base = kTwoZeroBytes + div10 + (mod10 << 8);\n  base >>= num_digits & 8;\n  little_endian::Store16(out_str, static_cast<uint16_t>(base));\n  return out_str + 2 + num_digits;\n}\n\ninline char* EncodeTenThousand(uint32_t n, char* absl_nonnull out_str) {\n  // We split lower 2 digits and upper 2 digits of n into 2 byte consecutive\n  // blocks. 123 ->  [\\0\\1][\\0\\23]. We divide by 10 both blocks\n  // (it's 1 division + zeroing upper bits), and compute modulo 10 as well \"in\n  // parallel\". Then we combine both results to have both ASCII digits,\n  // strip trailing zeros, add ASCII '0000' and return.\n  uint32_t div100 = (n * kDivisionBy100Mul) / kDivisionBy100Div;\n  uint32_t mod100 = n - 100ull * div100;\n  uint32_t hundreds = (mod100 << 16) + div100;\n  uint32_t tens = (hundreds * kDivisionBy10Mul) / kDivisionBy10Div;\n  tens &= (0xFull << 16) | 0xFull;\n  tens += (hundreds - 10ull * tens) << 8;\n  ABSL_ASSUME(tens != 0);\n  // The result can contain trailing zero bits, we need to strip them to a first\n  // significant byte in a final representation. For example, for n = 123, we\n  // have tens to have representation \\0\\1\\2\\3. We do `& -8` to round\n  // to a multiple to 8 to strip zero bytes, not all zero bits.\n  // countr_zero to help.\n  // 0 minus 8 to make MSVC happy.\n  uint32_t zeroes = static_cast<uint32_t>(absl::countr_zero(tens)) & (0 - 8u);\n  tens += kFourZeroBytes;\n  tens >>= zeroes;\n  little_endian::Store32(out_str, tens);\n  return out_str + sizeof(tens) - zeroes / 8;\n}\n\n// Helper function to produce an ASCII representation of `i`.\n//\n// Function returns an 8-byte integer which when summed with `kEightZeroBytes`,\n// can be treated as a printable buffer with ascii representation of `i`,\n// possibly with leading zeros.\n//\n// Example:\n//\n//  uint64_t buffer = PrepareEightDigits(102030) + kEightZeroBytes;\n//  char* ascii = reinterpret_cast<char*>(&buffer);\n//  // Note two leading zeros:\n//  EXPECT_EQ(absl::string_view(ascii, 8), \"00102030\");\n//\n// Pre-condition: `i` must be less than 100000000.\ninline uint64_t PrepareEightDigits(uint32_t i) {\n  ABSL_ASSUME(i < 10000'0000);\n  // Prepare 2 blocks of 4 digits \"in parallel\".\n  uint32_t hi = i / 10000;\n  uint32_t lo = i % 10000;\n  uint64_t merged = hi | (uint64_t{lo} << 32);\n  uint64_t div100 = ((merged * kDivisionBy100Mul) / kDivisionBy100Div) &\n                    ((0x7Full << 32) | 0x7Full);\n  uint64_t mod100 = merged - 100ull * div100;\n  uint64_t hundreds = (mod100 << 16) + div100;\n  uint64_t tens = (hundreds * kDivisionBy10Mul) / kDivisionBy10Div;\n  tens &= (0xFull << 48) | (0xFull << 32) | (0xFull << 16) | 0xFull;\n  tens += (hundreds - 10ull * tens) << 8;\n  return tens;\n}\n\n\n// Encodes v to buffer as 16 digits padded with leading zeros.\n// Pre-condition: v must be < 10^16.\ninline char* EncodePadded16(uint64_t v, char* absl_nonnull buffer) {\n  constexpr uint64_t k1e8 = 100000000;\n  uint32_t hi = static_cast<uint32_t>(v / k1e8);\n  uint32_t lo = static_cast<uint32_t>(v % k1e8);\n  little_endian::Store64(buffer, PrepareEightDigits(hi) + kEightZeroBytes);\n  little_endian::Store64(buffer + 8, PrepareEightDigits(lo) + kEightZeroBytes);\n  return buffer + 16;\n}\n\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE char* absl_nonnull EncodeFullU32(\n    uint32_t n, char* absl_nonnull out_str) {\n  if (n < 10) {\n    *out_str = static_cast<char>('0' + n);\n    return out_str + 1;\n  }\n  if (n < 100'000'000) {\n    uint64_t bottom = PrepareEightDigits(n);\n    ABSL_ASSUME(bottom != 0);\n    // 0 minus 8 to make MSVC happy.\n    uint32_t zeroes =\n        static_cast<uint32_t>(absl::countr_zero(bottom)) & (0 - 8u);\n    little_endian::Store64(out_str, (bottom + kEightZeroBytes) >> zeroes);\n    return out_str + sizeof(bottom) - zeroes / 8;\n  }\n  uint32_t div08 = n / 100'000'000;\n  uint32_t mod08 = n % 100'000'000;\n  uint64_t bottom = PrepareEightDigits(mod08) + kEightZeroBytes;\n  out_str = EncodeHundred(div08, out_str);\n  little_endian::Store64(out_str, bottom);\n  return out_str + sizeof(bottom);\n}\n\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE char* absl_nonnull EncodeFullU64(\n    uint64_t i, char* absl_nonnull buffer) {\n  if (i <= std::numeric_limits<uint32_t>::max()) {\n    return EncodeFullU32(static_cast<uint32_t>(i), buffer);\n  }\n  uint32_t mod08;\n  if (i < 1'0000'0000'0000'0000ull) {\n    uint32_t div08 = static_cast<uint32_t>(i / 100'000'000ull);\n    mod08 = static_cast<uint32_t>(i % 100'000'000ull);\n    buffer = EncodeFullU32(div08, buffer);\n  } else {\n    uint64_t div08 = i / 100'000'000ull;\n    mod08 = static_cast<uint32_t>(i % 100'000'000ull);\n    uint32_t div016 = static_cast<uint32_t>(div08 / 100'000'000ull);\n    uint32_t div08mod08 = static_cast<uint32_t>(div08 % 100'000'000ull);\n    uint64_t mid_result = PrepareEightDigits(div08mod08) + kEightZeroBytes;\n    buffer = EncodeTenThousand(div016, buffer);\n    little_endian::Store64(buffer, mid_result);\n    buffer += sizeof(mid_result);\n  }\n  uint64_t mod_result = PrepareEightDigits(mod08) + kEightZeroBytes;\n  little_endian::Store64(buffer, mod_result);\n  return buffer + sizeof(mod_result);\n}\n\ninline ABSL_ATTRIBUTE_ALWAYS_INLINE char* absl_nonnull EncodeFullU128(\n    uint128 i, char* absl_nonnull buffer) {\n  if (absl::Uint128High64(i) == 0) {\n    return EncodeFullU64(absl::Uint128Low64(i), buffer);\n  }\n  // We divide the number into 16-digit chunks because `EncodePadded16` is\n  // optimized to handle 16 digits at a time (as two 8-digit chunks).\n  constexpr uint64_t k1e16 = uint64_t{10'000'000'000'000'000};\n  uint128 high = i / k1e16;\n  uint64_t low = absl::Uint128Low64(i % k1e16);\n  uint64_t mid = absl::Uint128Low64(high % k1e16);\n  high /= k1e16;\n\n  if (high == 0) {\n    buffer = EncodeFullU64(mid, buffer);\n    buffer = EncodePadded16(low, buffer);\n  } else {\n    buffer = EncodeFullU64(absl::Uint128Low64(high), buffer);\n    buffer = EncodePadded16(mid, buffer);\n    buffer = EncodePadded16(low, buffer);\n  }\n  return buffer;\n}\n\n}  // namespace\n\nvoid numbers_internal::PutTwoDigits(uint32_t i, char* absl_nonnull buf) {\n  assert(i < 100);\n  uint32_t base = kTwoZeroBytes;\n  uint32_t div10 = (i * kDivisionBy10Mul) / kDivisionBy10Div;\n  uint32_t mod10 = i - 10u * div10;\n  base += div10 + (mod10 << 8);\n  little_endian::Store16(buf, static_cast<uint16_t>(base));\n}\n\nchar* absl_nonnull numbers_internal::FastIntToBuffer(\n    uint32_t n, char* absl_nonnull out_str) {\n  out_str = EncodeFullU32(n, out_str);\n  *out_str = '\\0';\n  return out_str;\n}\n\nchar* absl_nonnull numbers_internal::FastIntToBuffer(\n    int32_t i, char* absl_nonnull buffer) {\n  uint32_t u = static_cast<uint32_t>(i);\n  if (i < 0) {\n    *buffer++ = '-';\n    // We need to do the negation in modular (i.e., \"unsigned\")\n    // arithmetic; MSVC++ apparently warns for plain \"-u\", so\n    // we write the equivalent expression \"0 - u\" instead.\n    u = 0 - u;\n  }\n  buffer = EncodeFullU32(u, buffer);\n  *buffer = '\\0';\n  return buffer;\n}\n\nchar* absl_nonnull numbers_internal::FastIntToBuffer(\n    uint64_t i, char* absl_nonnull buffer) {\n  buffer = EncodeFullU64(i, buffer);\n  *buffer = '\\0';\n  return buffer;\n}\n\nchar* absl_nonnull numbers_internal::FastIntToBuffer(\n    int64_t i, char* absl_nonnull buffer) {\n  uint64_t u = static_cast<uint64_t>(i);\n  if (i < 0) {\n    *buffer++ = '-';\n    // We need to do the negation in modular (i.e., \"unsigned\")\n    // arithmetic; MSVC++ apparently warns for plain \"-u\", so\n    // we write the equivalent expression \"0 - u\" instead.\n    u = 0 - u;\n  }\n  buffer = EncodeFullU64(u, buffer);\n  *buffer = '\\0';\n  return buffer;\n}\n\nchar* absl_nonnull numbers_internal::FastIntToBuffer(\n    uint128 i, char* absl_nonnull buffer) {\n  buffer = EncodeFullU128(i, buffer);\n  *buffer = '\\0';\n  return buffer;\n}\n\nchar* absl_nonnull numbers_internal::FastIntToBuffer(\n    int128 i, char* absl_nonnull buffer) {\n  uint128 u = static_cast<uint128>(i);\n  if (i < 0) {\n    *buffer++ = '-';\n    u = -u;\n  }\n  buffer = EncodeFullU128(u, buffer);\n  *buffer = '\\0';\n  return buffer;\n}\n\n// Given a 128-bit number expressed as a pair of uint64_t, high half first,\n// return that number multiplied by the given 32-bit value.  If the result is\n// too large to fit in a 128-bit number, divide it by 2 until it fits.\nstatic std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num,\n                                           uint32_t mul) {\n  uint64_t bits0_31 = num.second & 0xFFFFFFFF;\n  uint64_t bits32_63 = num.second >> 32;\n  uint64_t bits64_95 = num.first & 0xFFFFFFFF;\n  uint64_t bits96_127 = num.first >> 32;\n\n  // The picture so far: each of these 64-bit values has only the lower 32 bits\n  // filled in.\n  // bits96_127:          [ 00000000 xxxxxxxx ]\n  // bits64_95:                    [ 00000000 xxxxxxxx ]\n  // bits32_63:                             [ 00000000 xxxxxxxx ]\n  // bits0_31:                                       [ 00000000 xxxxxxxx ]\n\n  bits0_31 *= mul;\n  bits32_63 *= mul;\n  bits64_95 *= mul;\n  bits96_127 *= mul;\n\n  // Now the top halves may also have value, though all 64 of their bits will\n  // never be set at the same time, since they are a result of a 32x32 bit\n  // multiply.  This makes the carry calculation slightly easier.\n  // bits96_127:          [ mmmmmmmm | mmmmmmmm ]\n  // bits64_95:                    [ | mmmmmmmm mmmmmmmm | ]\n  // bits32_63:                      |        [ mmmmmmmm | mmmmmmmm ]\n  // bits0_31:                       |                 [ | mmmmmmmm mmmmmmmm ]\n  // eventually:        [ bits128_up | ...bits64_127.... | ..bits0_63... ]\n\n  uint64_t bits0_63 = bits0_31 + (bits32_63 << 32);\n  uint64_t bits64_127 = bits64_95 + (bits96_127 << 32) + (bits32_63 >> 32) +\n                        (bits0_63 < bits0_31);\n  uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);\n  if (bits128_up == 0) return {bits64_127, bits0_63};\n\n  auto shift = static_cast<unsigned>(bit_width(bits128_up));\n  uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));\n  uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));\n  return {hi, lo};\n}\n\n// Compute num * 5 ^ expfive, and return the first 128 bits of the result,\n// where the first bit is always a one.  So PowFive(1, 0) starts 0b100000,\n// PowFive(1, 1) starts 0b101000, PowFive(1, 2) starts 0b110010, etc.\nstatic std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {\n  std::pair<uint64_t, uint64_t> result = {num, 0};\n  while (expfive >= 13) {\n    // 5^13 is the highest power of five that will fit in a 32-bit integer.\n    result = Mul32(result, 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5);\n    expfive -= 13;\n  }\n  constexpr uint32_t powers_of_five[13] = {\n      1,\n      5,\n      5 * 5,\n      5 * 5 * 5,\n      5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\n      5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};\n  result = Mul32(result, powers_of_five[expfive & 15]);\n  int shift = countl_zero(result.first);\n  if (shift != 0) {\n    result.first = (result.first << shift) + (result.second >> (64 - shift));\n    result.second = (result.second << shift);\n  }\n  return result;\n}\n\nstruct ExpDigits {\n  int32_t exponent;\n  char digits[6];\n};\n\n// SplitToSix converts value, a positive double-precision floating-point number,\n// into a base-10 exponent and 6 ASCII digits, where the first digit is never\n// zero.  For example, SplitToSix(1) returns an exponent of zero and a digits\n// array of {'1', '0', '0', '0', '0', '0'}.  If value is exactly halfway between\n// two possible representations, e.g. value = 100000.5, then \"round to even\" is\n// performed.\nstatic ExpDigits SplitToSix(const double value) {\n  ExpDigits exp_dig;\n  int exp = 5;\n  double d = value;\n  // First step: calculate a close approximation of the output, where the\n  // value d will be between 100,000 and 999,999, representing the digits\n  // in the output ASCII array, and exp is the base-10 exponent.  It would be\n  // faster to use a table here, and to look up the base-2 exponent of value,\n  // however value is an IEEE-754 64-bit number, so the table would have 2,000\n  // entries, which is not cache-friendly.\n  if (d >= 999999.5) {\n    if (d >= 1e+261) exp += 256, d *= 1e-256;\n    if (d >= 1e+133) exp += 128, d *= 1e-128;\n    if (d >= 1e+69) exp += 64, d *= 1e-64;\n    if (d >= 1e+37) exp += 32, d *= 1e-32;\n    if (d >= 1e+21) exp += 16, d *= 1e-16;\n    if (d >= 1e+13) exp += 8, d *= 1e-8;\n    if (d >= 1e+9) exp += 4, d *= 1e-4;\n    if (d >= 1e+7) exp += 2, d *= 1e-2;\n    if (d >= 1e+6) exp += 1, d *= 1e-1;\n  } else {\n    if (d < 1e-250) exp -= 256, d *= 1e256;\n    if (d < 1e-122) exp -= 128, d *= 1e128;\n    if (d < 1e-58) exp -= 64, d *= 1e64;\n    if (d < 1e-26) exp -= 32, d *= 1e32;\n    if (d < 1e-10) exp -= 16, d *= 1e16;\n    if (d < 1e-2) exp -= 8, d *= 1e8;\n    if (d < 1e+2) exp -= 4, d *= 1e4;\n    if (d < 1e+4) exp -= 2, d *= 1e2;\n    if (d < 1e+5) exp -= 1, d *= 1e1;\n  }\n  // At this point, d is in the range [99999.5..999999.5) and exp is in the\n  // range [-324..308]. Since we need to round d up, we want to add a half\n  // and truncate.\n  // However, the technique above may have lost some precision, due to its\n  // repeated multiplication by constants that each may be off by half a bit\n  // of precision.  This only matters if we're close to the edge though.\n  // Since we'd like to know if the fractional part of d is close to a half,\n  // we multiply it by 65536 and see if the fractional part is close to 32768.\n  // (The number doesn't have to be a power of two,but powers of two are faster)\n  uint64_t d64k = static_cast<uint64_t>(d * 65536);\n  uint32_t dddddd;  // A 6-digit decimal integer.\n  if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) {\n    // OK, it's fairly likely that precision was lost above, which is\n    // not a surprise given only 52 mantissa bits are available.  Therefore\n    // redo the calculation using 128-bit numbers.  (64 bits are not enough).\n\n    // Start out with digits rounded down; maybe add one below.\n    dddddd = static_cast<uint32_t>(d64k / 65536);\n\n    // mantissa is a 64-bit integer representing M.mmm... * 2^63.  The actual\n    // value we're representing, of course, is M.mmm... * 2^exp2.\n    int exp2;\n    double m = std::frexp(value, &exp2);\n    uint64_t mantissa =\n        static_cast<uint64_t>(m * (32768.0 * 65536.0 * 65536.0 * 65536.0));\n    // std::frexp returns an m value in the range [0.5, 1.0), however we\n    // can't multiply it by 2^64 and convert to an integer because some FPUs\n    // throw an exception when converting an number higher than 2^63 into an\n    // integer - even an unsigned 64-bit integer!  Fortunately it doesn't matter\n    // since m only has 52 significant bits anyway.\n    mantissa <<= 1;\n    exp2 -= 64;  // not needed, but nice for debugging\n\n    // OK, we are here to compare:\n    //     (dddddd + 0.5) * 10^(exp-5)  vs.  mantissa * 2^exp2\n    // so we can round up dddddd if appropriate.  Those values span the full\n    // range of 600 orders of magnitude of IEE 64-bit floating-point.\n    // Fortunately, we already know they are very close, so we don't need to\n    // track the base-2 exponent of both sides.  This greatly simplifies the\n    // the math since the 2^exp2 calculation is unnecessary and the power-of-10\n    // calculation can become a power-of-5 instead.\n\n    std::pair<uint64_t, uint64_t> edge, val;\n    if (exp >= 6) {\n      // Compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa\n      // Since we're tossing powers of two, 2 * dddddd + 1 is the\n      // same as dddddd + 0.5\n      edge = PowFive(2 * dddddd + 1, exp - 5);\n\n      val.first = mantissa;\n      val.second = 0;\n    } else {\n      // We can't compare (dddddd + 0.5) * 5 ^ (exp - 5) to mantissa as we did\n      // above because (exp - 5) is negative.  So we compare (dddddd + 0.5) to\n      // mantissa * 5 ^ (5 - exp)\n      edge = PowFive(2 * dddddd + 1, 0);\n\n      val = PowFive(mantissa, 5 - exp);\n    }\n    // printf(\"exp=%d %016lx %016lx vs %016lx %016lx\\n\", exp, val.first,\n    //        val.second, edge.first, edge.second);\n    if (val > edge) {\n      dddddd++;\n    } else if (val == edge) {\n      dddddd += (dddddd & 1);\n    }\n  } else {\n    // Here, we are not close to the edge.\n    dddddd = static_cast<uint32_t>((d64k + 32768) / 65536);\n  }\n  if (dddddd == 1000000) {\n    dddddd = 100000;\n    exp += 1;\n  }\n  exp_dig.exponent = exp;\n\n  uint32_t two_digits = dddddd / 10000;\n  dddddd -= two_digits * 10000;\n  numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);\n\n  two_digits = dddddd / 100;\n  dddddd -= two_digits * 100;\n  numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]);\n\n  numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]);\n  return exp_dig;\n}\n\n// Helper function for fast formatting of floating-point.\n// The result is the same as \"%g\", a.k.a. \"%.6g\".\nsize_t numbers_internal::SixDigitsToBuffer(double d,\n                                           char* absl_nonnull const buffer) {\n  static_assert(std::numeric_limits<float>::is_iec559,\n                \"IEEE-754/IEC-559 support only\");\n\n  char* out = buffer;  // we write data to out, incrementing as we go, but\n                       // FloatToBuffer always returns the address of the buffer\n                       // passed in.\n\n  if (std::isnan(d)) {\n    strcpy(out, \"nan\");  // NOLINT(runtime/printf)\n    return 3;\n  }\n  if (d == 0) {  // +0 and -0 are handled here\n    if (std::signbit(d)) *out++ = '-';\n    *out++ = '0';\n    *out = 0;\n    return static_cast<size_t>(out - buffer);\n  }\n  if (d < 0) {\n    *out++ = '-';\n    d = -d;\n  }\n  if (d > std::numeric_limits<double>::max()) {\n    strcpy(out, \"inf\");  // NOLINT(runtime/printf)\n    return static_cast<size_t>(out + 3 - buffer);\n  }\n\n  auto exp_dig = SplitToSix(d);\n  int exp = exp_dig.exponent;\n  const char* digits = exp_dig.digits;\n  out[0] = '0';\n  out[1] = '.';\n  switch (exp) {\n    case 5:\n      memcpy(out, &digits[0], 6), out += 6;\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n    case 4:\n      memcpy(out, &digits[0], 5), out += 5;\n      if (digits[5] != '0') {\n        *out++ = '.';\n        *out++ = digits[5];\n      }\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n    case 3:\n      memcpy(out, &digits[0], 4), out += 4;\n      if ((digits[5] | digits[4]) != '0') {\n        *out++ = '.';\n        *out++ = digits[4];\n        if (digits[5] != '0') *out++ = digits[5];\n      }\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n    case 2:\n      memcpy(out, &digits[0], 3), out += 3;\n      *out++ = '.';\n      memcpy(out, &digits[3], 3);\n      out += 3;\n      while (out[-1] == '0') --out;\n      if (out[-1] == '.') --out;\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n    case 1:\n      memcpy(out, &digits[0], 2), out += 2;\n      *out++ = '.';\n      memcpy(out, &digits[2], 4);\n      out += 4;\n      while (out[-1] == '0') --out;\n      if (out[-1] == '.') --out;\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n    case 0:\n      memcpy(out, &digits[0], 1), out += 1;\n      *out++ = '.';\n      memcpy(out, &digits[1], 5);\n      out += 5;\n      while (out[-1] == '0') --out;\n      if (out[-1] == '.') --out;\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n    case -4:\n      out[2] = '0';\n      ++out;\n      ABSL_FALLTHROUGH_INTENDED;\n    case -3:\n      out[2] = '0';\n      ++out;\n      ABSL_FALLTHROUGH_INTENDED;\n    case -2:\n      out[2] = '0';\n      ++out;\n      ABSL_FALLTHROUGH_INTENDED;\n    case -1:\n      out += 2;\n      memcpy(out, &digits[0], 6);\n      out += 6;\n      while (out[-1] == '0') --out;\n      *out = 0;\n      return static_cast<size_t>(out - buffer);\n  }\n  assert(exp < -4 || exp >= 6);\n  out[0] = digits[0];\n  assert(out[1] == '.');\n  out += 2;\n  memcpy(out, &digits[1], 5), out += 5;\n  while (out[-1] == '0') --out;\n  if (out[-1] == '.') --out;\n  *out++ = 'e';\n  if (exp > 0) {\n    *out++ = '+';\n  } else {\n    *out++ = '-';\n    exp = -exp;\n  }\n  if (exp > 99) {\n    int dig1 = exp / 100;\n    exp -= dig1 * 100;\n    *out++ = '0' + static_cast<char>(dig1);\n  }\n  PutTwoDigits(static_cast<uint32_t>(exp), out);\n  out += 2;\n  *out = 0;\n  return static_cast<size_t>(out - buffer);\n}\n\nnamespace {\n// Represents integer values of digits.\n// Uses 36 to indicate an invalid character since we support\n// bases up to 36.\nstatic constexpr std::array<int8_t, 256> kAsciiToInt = {\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  // 16 36s.\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0,  1,  2,  3,  4,  5,\n    6,  7,  8,  9,  36, 36, 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17,\n    18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\n    36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\n    24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,\n    36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36};\n\n// Parse the sign and optional hex or oct prefix in text.\ninline bool safe_parse_sign_and_base(\n    absl::string_view* absl_nonnull text /*inout*/,\n    int* absl_nonnull base_ptr /*inout*/,\n    bool* absl_nonnull negative_ptr /*output*/) {\n  if (text->data() == nullptr) {\n    return false;\n  }\n\n  const char* start = text->data();\n  const char* end = start + text->size();\n  int base = *base_ptr;\n\n  // Consume whitespace.\n  while (start < end &&\n         absl::ascii_isspace(static_cast<unsigned char>(start[0]))) {\n    ++start;\n  }\n  while (start < end &&\n         absl::ascii_isspace(static_cast<unsigned char>(end[-1]))) {\n    --end;\n  }\n  if (start >= end) {\n    return false;\n  }\n\n  // Consume sign.\n  *negative_ptr = (start[0] == '-');\n  if (*negative_ptr || start[0] == '+') {\n    ++start;\n    if (start >= end) {\n      return false;\n    }\n  }\n\n  // Consume base-dependent prefix.\n  //  base 0: \"0x\" -> base 16, \"0\" -> base 8, default -> base 10\n  //  base 16: \"0x\" -> base 16\n  // Also validate the base.\n  if (base == 0) {\n    if (end - start >= 2 && start[0] == '0' &&\n        (start[1] == 'x' || start[1] == 'X')) {\n      base = 16;\n      start += 2;\n      if (start >= end) {\n        // \"0x\" with no digits after is invalid.\n        return false;\n      }\n    } else if (end - start >= 1 && start[0] == '0') {\n      base = 8;\n      start += 1;\n    } else {\n      base = 10;\n    }\n  } else if (base == 16) {\n    if (end - start >= 2 && start[0] == '0' &&\n        (start[1] == 'x' || start[1] == 'X')) {\n      start += 2;\n      if (start >= end) {\n        // \"0x\" with no digits after is invalid.\n        return false;\n      }\n    }\n  } else if (base >= 2 && base <= 36) {\n    // okay\n  } else {\n    return false;\n  }\n  *text = absl::string_view(start, static_cast<size_t>(end - start));\n  *base_ptr = base;\n  return true;\n}\n\n// Consume digits.\n//\n// The classic loop:\n//\n//   for each digit\n//     value = value * base + digit\n//   value *= sign\n//\n// The classic loop needs overflow checking.  It also fails on the most\n// negative integer, -2147483648 in 32-bit two's complement representation.\n//\n// My improved loop:\n//\n//  if (!negative)\n//    for each digit\n//      value = value * base\n//      value = value + digit\n//  else\n//    for each digit\n//      value = value * base\n//      value = value - digit\n//\n// Overflow checking becomes simple.\n\n// Lookup tables per IntType:\n// vmax/base and vmin/base are precomputed because division costs at least 8ns.\n// TODO(junyer): Doing this per base instead (i.e. an array of structs, not a\n// struct of arrays) would probably be better in terms of d-cache for the most\n// commonly used bases.\ntemplate <typename IntType>\nstruct LookupTables {\n  ABSL_CONST_INIT static const IntType kVmaxOverBase[];\n  ABSL_CONST_INIT static const IntType kVminOverBase[];\n};\n\n// An array initializer macro for X/base where base in [0, 36].\n// However, note that lookups for base in [0, 1] should never happen because\n// base has been validated to be in [2, 36] by safe_parse_sign_and_base().\n#define X_OVER_BASE_INITIALIZER(X)                                        \\\n  {                                                                       \\\n    0, 0, X / 2, X / 3, X / 4, X / 5, X / 6, X / 7, X / 8, X / 9, X / 10, \\\n        X / 11, X / 12, X / 13, X / 14, X / 15, X / 16, X / 17, X / 18,   \\\n        X / 19, X / 20, X / 21, X / 22, X / 23, X / 24, X / 25, X / 26,   \\\n        X / 27, X / 28, X / 29, X / 30, X / 31, X / 32, X / 33, X / 34,   \\\n        X / 35, X / 36,                                                   \\\n  }\n\n// This kVmaxOverBase is generated with\n//  for (int base = 2; base < 37; ++base) {\n//    absl::uint128 max = std::numeric_limits<absl::uint128>::max();\n//    auto result = max / base;\n//    std::cout << \"    MakeUint128(\" << absl::Uint128High64(result) << \"u, \"\n//              << absl::Uint128Low64(result) << \"u),\\n\";\n//  }\n// See https://godbolt.org/z/aneYsb\n//\n// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting\n// array to avoid a static initializer.\ntemplate <>\nABSL_CONST_INIT const uint128 LookupTables<uint128>::kVmaxOverBase[] = {\n    0,\n    0,\n    MakeUint128(9223372036854775807u, 18446744073709551615u),\n    MakeUint128(6148914691236517205u, 6148914691236517205u),\n    MakeUint128(4611686018427387903u, 18446744073709551615u),\n    MakeUint128(3689348814741910323u, 3689348814741910323u),\n    MakeUint128(3074457345618258602u, 12297829382473034410u),\n    MakeUint128(2635249153387078802u, 5270498306774157604u),\n    MakeUint128(2305843009213693951u, 18446744073709551615u),\n    MakeUint128(2049638230412172401u, 14347467612885206812u),\n    MakeUint128(1844674407370955161u, 11068046444225730969u),\n    MakeUint128(1676976733973595601u, 8384883669867978007u),\n    MakeUint128(1537228672809129301u, 6148914691236517205u),\n    MakeUint128(1418980313362273201u, 4256940940086819603u),\n    MakeUint128(1317624576693539401u, 2635249153387078802u),\n    MakeUint128(1229782938247303441u, 1229782938247303441u),\n    MakeUint128(1152921504606846975u, 18446744073709551615u),\n    MakeUint128(1085102592571150095u, 1085102592571150095u),\n    MakeUint128(1024819115206086200u, 16397105843297379214u),\n    MakeUint128(970881267037344821u, 16504981539634861972u),\n    MakeUint128(922337203685477580u, 14757395258967641292u),\n    MakeUint128(878416384462359600u, 14054662151397753612u),\n    MakeUint128(838488366986797800u, 13415813871788764811u),\n    MakeUint128(802032351030850070u, 4812194106185100421u),\n    MakeUint128(768614336404564650u, 12297829382473034410u),\n    MakeUint128(737869762948382064u, 11805916207174113034u),\n    MakeUint128(709490156681136600u, 11351842506898185609u),\n    MakeUint128(683212743470724133u, 17080318586768103348u),\n    MakeUint128(658812288346769700u, 10540996613548315209u),\n    MakeUint128(636094623231363848u, 15266270957552732371u),\n    MakeUint128(614891469123651720u, 9838263505978427528u),\n    MakeUint128(595056260442243600u, 9520900167075897608u),\n    MakeUint128(576460752303423487u, 18446744073709551615u),\n    MakeUint128(558992244657865200u, 8943875914525843207u),\n    MakeUint128(542551296285575047u, 9765923333140350855u),\n    MakeUint128(527049830677415760u, 8432797290838652167u),\n    MakeUint128(512409557603043100u, 8198552921648689607u),\n};\n\n// This kVmaxOverBase generated with\n//   for (int base = 2; base < 37; ++base) {\n//    absl::int128 max = std::numeric_limits<absl::int128>::max();\n//    auto result = max / base;\n//    std::cout << \"\\tMakeInt128(\" << absl::Int128High64(result) << \", \"\n//              << absl::Int128Low64(result) << \"u),\\n\";\n//  }\n// See https://godbolt.org/z/7djYWz\n//\n// int128& operator/=(int128) is not constexpr, so hardcode the resulting array\n// to avoid a static initializer.\ntemplate <>\nABSL_CONST_INIT const int128 LookupTables<int128>::kVmaxOverBase[] = {\n    0,\n    0,\n    MakeInt128(4611686018427387903, 18446744073709551615u),\n    MakeInt128(3074457345618258602, 12297829382473034410u),\n    MakeInt128(2305843009213693951, 18446744073709551615u),\n    MakeInt128(1844674407370955161, 11068046444225730969u),\n    MakeInt128(1537228672809129301, 6148914691236517205u),\n    MakeInt128(1317624576693539401, 2635249153387078802u),\n    MakeInt128(1152921504606846975, 18446744073709551615u),\n    MakeInt128(1024819115206086200, 16397105843297379214u),\n    MakeInt128(922337203685477580, 14757395258967641292u),\n    MakeInt128(838488366986797800, 13415813871788764811u),\n    MakeInt128(768614336404564650, 12297829382473034410u),\n    MakeInt128(709490156681136600, 11351842506898185609u),\n    MakeInt128(658812288346769700, 10540996613548315209u),\n    MakeInt128(614891469123651720, 9838263505978427528u),\n    MakeInt128(576460752303423487, 18446744073709551615u),\n    MakeInt128(542551296285575047, 9765923333140350855u),\n    MakeInt128(512409557603043100, 8198552921648689607u),\n    MakeInt128(485440633518672410, 17475862806672206794u),\n    MakeInt128(461168601842738790, 7378697629483820646u),\n    MakeInt128(439208192231179800, 7027331075698876806u),\n    MakeInt128(419244183493398900, 6707906935894382405u),\n    MakeInt128(401016175515425035, 2406097053092550210u),\n    MakeInt128(384307168202282325, 6148914691236517205u),\n    MakeInt128(368934881474191032, 5902958103587056517u),\n    MakeInt128(354745078340568300, 5675921253449092804u),\n    MakeInt128(341606371735362066, 17763531330238827482u),\n    MakeInt128(329406144173384850, 5270498306774157604u),\n    MakeInt128(318047311615681924, 7633135478776366185u),\n    MakeInt128(307445734561825860, 4919131752989213764u),\n    MakeInt128(297528130221121800, 4760450083537948804u),\n    MakeInt128(288230376151711743, 18446744073709551615u),\n    MakeInt128(279496122328932600, 4471937957262921603u),\n    MakeInt128(271275648142787523, 14106333703424951235u),\n    MakeInt128(263524915338707880, 4216398645419326083u),\n    MakeInt128(256204778801521550, 4099276460824344803u),\n};\n\n// This kVminOverBase generated with\n//  for (int base = 2; base < 37; ++base) {\n//    absl::int128 min = std::numeric_limits<absl::int128>::min();\n//    auto result = min / base;\n//    std::cout << \"\\tMakeInt128(\" << absl::Int128High64(result) << \", \"\n//              << absl::Int128Low64(result) << \"u),\\n\";\n//  }\n//\n// See https://godbolt.org/z/7djYWz\n//\n// int128& operator/=(int128) is not constexpr, so hardcode the resulting array\n// to avoid a static initializer.\ntemplate <>\nABSL_CONST_INIT const int128 LookupTables<int128>::kVminOverBase[] = {\n    0,\n    0,\n    MakeInt128(-4611686018427387904, 0u),\n    MakeInt128(-3074457345618258603, 6148914691236517206u),\n    MakeInt128(-2305843009213693952, 0u),\n    MakeInt128(-1844674407370955162, 7378697629483820647u),\n    MakeInt128(-1537228672809129302, 12297829382473034411u),\n    MakeInt128(-1317624576693539402, 15811494920322472814u),\n    MakeInt128(-1152921504606846976, 0u),\n    MakeInt128(-1024819115206086201, 2049638230412172402u),\n    MakeInt128(-922337203685477581, 3689348814741910324u),\n    MakeInt128(-838488366986797801, 5030930201920786805u),\n    MakeInt128(-768614336404564651, 6148914691236517206u),\n    MakeInt128(-709490156681136601, 7094901566811366007u),\n    MakeInt128(-658812288346769701, 7905747460161236407u),\n    MakeInt128(-614891469123651721, 8608480567731124088u),\n    MakeInt128(-576460752303423488, 0u),\n    MakeInt128(-542551296285575048, 8680820740569200761u),\n    MakeInt128(-512409557603043101, 10248191152060862009u),\n    MakeInt128(-485440633518672411, 970881267037344822u),\n    MakeInt128(-461168601842738791, 11068046444225730970u),\n    MakeInt128(-439208192231179801, 11419412998010674810u),\n    MakeInt128(-419244183493398901, 11738837137815169211u),\n    MakeInt128(-401016175515425036, 16040647020617001406u),\n    MakeInt128(-384307168202282326, 12297829382473034411u),\n    MakeInt128(-368934881474191033, 12543785970122495099u),\n    MakeInt128(-354745078340568301, 12770822820260458812u),\n    MakeInt128(-341606371735362067, 683212743470724134u),\n    MakeInt128(-329406144173384851, 13176245766935394012u),\n    MakeInt128(-318047311615681925, 10813608594933185431u),\n    MakeInt128(-307445734561825861, 13527612320720337852u),\n    MakeInt128(-297528130221121801, 13686293990171602812u),\n    MakeInt128(-288230376151711744, 0u),\n    MakeInt128(-279496122328932601, 13974806116446630013u),\n    MakeInt128(-271275648142787524, 4340410370284600381u),\n    MakeInt128(-263524915338707881, 14230345428290225533u),\n    MakeInt128(-256204778801521551, 14347467612885206813u),\n};\n\ntemplate <typename IntType>\nABSL_CONST_INIT const IntType LookupTables<IntType>::kVmaxOverBase[] =\n    X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());\n\ntemplate <typename IntType>\nABSL_CONST_INIT const IntType LookupTables<IntType>::kVminOverBase[] =\n    X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::min());\n\n#undef X_OVER_BASE_INITIALIZER\n\ntemplate <typename IntType>\ninline bool safe_parse_positive_int(absl::string_view text, int base,\n                                    IntType* absl_nonnull value_p) {\n  IntType value = 0;\n  const IntType vmax = std::numeric_limits<IntType>::max();\n  assert(vmax > 0);\n  assert(base >= 0);\n  const IntType base_inttype = static_cast<IntType>(base);\n  assert(vmax >= base_inttype);\n  const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];\n  assert(base < 2 ||\n         std::numeric_limits<IntType>::max() / base_inttype == vmax_over_base);\n  const char* start = text.data();\n  const char* end = start + text.size();\n  // loop over digits\n  for (; start < end; ++start) {\n    unsigned char c = static_cast<unsigned char>(start[0]);\n    IntType digit = static_cast<IntType>(kAsciiToInt[c]);\n    if (digit >= base_inttype) {\n      *value_p = value;\n      return false;\n    }\n    if (value > vmax_over_base) {\n      *value_p = vmax;\n      return false;\n    }\n    value *= base_inttype;\n    if (value > vmax - digit) {\n      *value_p = vmax;\n      return false;\n    }\n    value += digit;\n  }\n  *value_p = value;\n  return true;\n}\n\ntemplate <typename IntType>\ninline bool safe_parse_negative_int(absl::string_view text, int base,\n                                    IntType* absl_nonnull value_p) {\n  IntType value = 0;\n  const IntType vmin = std::numeric_limits<IntType>::min();\n  assert(vmin < 0);\n  assert(vmin <= 0 - base);\n  IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];\n  assert(base < 2 ||\n         std::numeric_limits<IntType>::min() / base == vmin_over_base);\n  // 2003 c++ standard [expr.mul]\n  // \"... the sign of the remainder is implementation-defined.\"\n  // Although (vmin/base)*base + vmin%base is always vmin.\n  // 2011 c++ standard tightens the spec but we cannot rely on it.\n  // TODO(junyer): Handle this in the lookup table generation.\n  if (vmin % base > 0) {\n    vmin_over_base += 1;\n  }\n  const char* start = text.data();\n  const char* end = start + text.size();\n  // loop over digits\n  for (; start < end; ++start) {\n    unsigned char c = static_cast<unsigned char>(start[0]);\n    int digit = kAsciiToInt[c];\n    if (digit >= base) {\n      *value_p = value;\n      return false;\n    }\n    if (value < vmin_over_base) {\n      *value_p = vmin;\n      return false;\n    }\n    value *= base;\n    if (value < vmin + digit) {\n      *value_p = vmin;\n      return false;\n    }\n    value -= digit;\n  }\n  *value_p = value;\n  return true;\n}\n\n// Input format based on POSIX.1-2008 strtol\n// http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html\ntemplate <typename IntType>\ninline bool safe_int_internal(absl::string_view text,\n                              IntType* absl_nonnull value_p, int base) {\n  *value_p = 0;\n  bool negative;\n  if (!safe_parse_sign_and_base(&text, &base, &negative)) {\n    return false;\n  }\n  if (!negative) {\n    return safe_parse_positive_int(text, base, value_p);\n  } else {\n    return safe_parse_negative_int(text, base, value_p);\n  }\n}\n\ntemplate <typename IntType>\ninline bool safe_uint_internal(absl::string_view text,\n                               IntType* absl_nonnull value_p, int base) {\n  *value_p = 0;\n  bool negative;\n  if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) {\n    return false;\n  }\n  return safe_parse_positive_int(text, base, value_p);\n}\n}  // anonymous namespace\n\nnamespace numbers_internal {\n\n// Digit conversion.\nABSL_CONST_INIT ABSL_DLL const char kHexChar[] =\n    \"0123456789abcdef\";\n\nABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =\n    \"000102030405060708090a0b0c0d0e0f\"\n    \"101112131415161718191a1b1c1d1e1f\"\n    \"202122232425262728292a2b2c2d2e2f\"\n    \"303132333435363738393a3b3c3d3e3f\"\n    \"404142434445464748494a4b4c4d4e4f\"\n    \"505152535455565758595a5b5c5d5e5f\"\n    \"606162636465666768696a6b6c6d6e6f\"\n    \"707172737475767778797a7b7c7d7e7f\"\n    \"808182838485868788898a8b8c8d8e8f\"\n    \"909192939495969798999a9b9c9d9e9f\"\n    \"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf\"\n    \"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf\"\n    \"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf\"\n    \"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf\"\n    \"e0e1e2e3e4e5e6e7e8e9eaebecedeeef\"\n    \"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff\";\n\nbool safe_strto8_base(absl::string_view text, int8_t* absl_nonnull value,\n                      int base) {\n  return safe_int_internal<int8_t>(text, value, base);\n}\n\nbool safe_strto16_base(absl::string_view text, int16_t* absl_nonnull value,\n                       int base) {\n  return safe_int_internal<int16_t>(text, value, base);\n}\n\nbool safe_strto32_base(absl::string_view text, int32_t* absl_nonnull value,\n                       int base) {\n  return safe_int_internal<int32_t>(text, value, base);\n}\n\nbool safe_strto64_base(absl::string_view text, int64_t* absl_nonnull value,\n                       int base) {\n  return safe_int_internal<int64_t>(text, value, base);\n}\n\nbool safe_strto128_base(absl::string_view text, int128* absl_nonnull value,\n                        int base) {\n  return safe_int_internal<absl::int128>(text, value, base);\n}\n\nbool safe_strtou8_base(absl::string_view text, uint8_t* absl_nonnull value,\n                       int base) {\n  return safe_uint_internal<uint8_t>(text, value, base);\n}\n\nbool safe_strtou16_base(absl::string_view text, uint16_t* absl_nonnull value,\n                        int base) {\n  return safe_uint_internal<uint16_t>(text, value, base);\n}\n\nbool safe_strtou32_base(absl::string_view text, uint32_t* absl_nonnull value,\n                        int base) {\n  return safe_uint_internal<uint32_t>(text, value, base);\n}\n\nbool safe_strtou64_base(absl::string_view text, uint64_t* absl_nonnull value,\n                        int base) {\n  return safe_uint_internal<uint64_t>(text, value, base);\n}\n\nbool safe_strtou128_base(absl::string_view text, uint128* absl_nonnull value,\n                         int base) {\n  return safe_uint_internal<absl::uint128>(text, value, base);\n}\n\n}  // namespace numbers_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/numbers.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: numbers.h\n// -----------------------------------------------------------------------------\n//\n// This package contains functions for converting strings to numbers. For\n// converting numbers to strings, use `StrCat()` or `StrAppend()` in str_cat.h,\n// which automatically detect and convert most number values appropriately.\n\n#ifndef ABSL_STRINGS_NUMBERS_H_\n#define ABSL_STRINGS_NUMBERS_H_\n\n#ifdef __SSSE3__\n#include <tmmintrin.h>\n#endif\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#endif\n\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <ctime>\n#include <limits>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/endian.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/port.h\"\n#include \"absl/numeric/bits.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// SimpleAtoi()\n//\n// Converts the given string (optionally followed or preceded by ASCII\n// whitespace) into an integer value, returning `true` if successful. The string\n// must reflect a base-10 integer whose value falls within the range of the\n// integer type (optionally preceded by a `+` or `-`). If any errors are\n// encountered, this function returns `false`, leaving `out` in an unspecified\n// state.\ntemplate <typename int_type>\n[[nodiscard]] bool SimpleAtoi(absl::string_view str,\n                              int_type* absl_nonnull out);\n\n// SimpleAtof()\n//\n// Converts the given string (optionally followed or preceded by ASCII\n// whitespace) into a float, which may be rounded on overflow or underflow,\n// returning `true` if successful.\n// See https://en.cppreference.com/w/c/string/byte/strtof for details about the\n// allowed formats for `str`, except SimpleAtof() is locale-independent and will\n// always use the \"C\" locale. If any errors are encountered, this function\n// returns `false`, leaving `out` in an unspecified state.\n[[nodiscard]] bool SimpleAtof(absl::string_view str, float* absl_nonnull out);\n\n// SimpleAtod()\n//\n// Converts the given string (optionally followed or preceded by ASCII\n// whitespace) into a double, which may be rounded on overflow or underflow,\n// returning `true` if successful.\n// See https://en.cppreference.com/w/c/string/byte/strtof for details about the\n// allowed formats for `str`, except SimpleAtod is locale-independent and will\n// always use the \"C\" locale. If any errors are encountered, this function\n// returns `false`, leaving `out` in an unspecified state.\n[[nodiscard]] bool SimpleAtod(absl::string_view str, double* absl_nonnull out);\n\n// SimpleAtob()\n//\n// Converts the given string into a boolean, returning `true` if successful.\n// The following case-insensitive strings are interpreted as boolean `true`:\n// \"true\", \"t\", \"yes\", \"y\", \"1\". The following case-insensitive strings\n// are interpreted as boolean `false`: \"false\", \"f\", \"no\", \"n\", \"0\". If any\n// errors are encountered, this function returns `false`, leaving `out` in an\n// unspecified state.\n[[nodiscard]] bool SimpleAtob(absl::string_view str, bool* absl_nonnull out);\n\n// SimpleHexAtoi()\n//\n// Converts a hexadecimal string (optionally followed or preceded by ASCII\n// whitespace) to an integer, returning `true` if successful. Only valid base-16\n// hexadecimal integers whose value falls within the range of the integer type\n// (optionally preceded by a `+` or `-`) can be converted. A valid hexadecimal\n// value may include both upper and lowercase character symbols, and may\n// optionally include a leading \"0x\" (or \"0X\") number prefix, which is ignored\n// by this function. If any errors are encountered, this function returns\n// `false`, leaving `out` in an unspecified state.\ntemplate <typename int_type>\n[[nodiscard]] bool SimpleHexAtoi(absl::string_view str,\n                                 int_type* absl_nonnull out);\n\n// Overloads of SimpleHexAtoi() for 128 bit integers.\n[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,\n                                        absl::int128* absl_nonnull out);\n[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,\n                                        absl::uint128* absl_nonnull out);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// End of public API.  Implementation details follow.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace numbers_internal {\n\ntemplate <typename int_type>\nconstexpr bool is_signed() {\n  if constexpr (std::is_arithmetic<int_type>::value) {\n    // Use std::numeric_limits<T>::is_signed where it's defined to work.\n    return std::numeric_limits<int_type>::is_signed;\n  }\n  // TODO(jorg): This signed-ness check is used because it works correctly\n  // with enums, and it also serves to check that int_type is not a pointer.\n  // If one day something like std::is_signed<enum E> works, switch to it.\n  return static_cast<int_type>(1) - 2 < 0;\n}\n\n// Digit conversion.\nABSL_DLL extern const char kHexChar[17];  // 0123456789abcdef\nABSL_DLL extern const char\n    kHexTable[513];  // 000102030405060708090a0b0c0d0e0f1011...\n\n// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the\n// range 0 <= i < 100, and buf must have space for two characters. Example:\n//   char buf[2];\n//   PutTwoDigits(42, buf);\n//   // buf[0] == '4'\n//   // buf[1] == '2'\nvoid PutTwoDigits(uint32_t i, char* absl_nonnull buf);\n\n// safe_strto?() functions for implementing SimpleAtoi()\n\nbool safe_strto8_base(absl::string_view text, int8_t* absl_nonnull value,\n                      int base);\nbool safe_strto16_base(absl::string_view text, int16_t* absl_nonnull value,\n                       int base);\nbool safe_strto32_base(absl::string_view text, int32_t* absl_nonnull value,\n                       int base);\nbool safe_strto64_base(absl::string_view text, int64_t* absl_nonnull value,\n                       int base);\nbool safe_strto128_base(absl::string_view text,\n                        absl::int128* absl_nonnull value, int base);\nbool safe_strtou8_base(absl::string_view text, uint8_t* absl_nonnull value,\n                       int base);\nbool safe_strtou16_base(absl::string_view text, uint16_t* absl_nonnull value,\n                        int base);\nbool safe_strtou32_base(absl::string_view text, uint32_t* absl_nonnull value,\n                        int base);\nbool safe_strtou64_base(absl::string_view text, uint64_t* absl_nonnull value,\n                        int base);\nbool safe_strtou128_base(absl::string_view text,\n                         absl::uint128* absl_nonnull value, int base);\n\ninline constexpr int kFastToBuffer128Size = 41;\ninline constexpr int kFastToBufferSize = 32;\ninline constexpr int kSixDigitsToBufferSize = 16;\n\n// Helper function for fast formatting of floating-point values.\n// The result is the same as printf's \"%g\", a.k.a. \"%.6g\"; that is, six\n// significant digits are returned, trailing zeros are removed, and numbers\n// outside the range 0.0001-999999 are output using scientific notation\n// (1.23456e+06). This routine is heavily optimized.\n// Required buffer size is `kSixDigitsToBufferSize`.\nsize_t SixDigitsToBuffer(double d, char* absl_nonnull buffer);\n\n// WARNING: These functions may write more characters than necessary, because\n// they are intended for speed. All functions take an output buffer\n// as an argument and return a pointer to the last byte they wrote, which is the\n// terminating '\\0'. The maximum size written is `kFastToBufferSize` for 64-bit\n// integers or less, and `kFastToBuffer128Size` for 128-bit integers.\nchar* absl_nonnull FastIntToBuffer(int32_t i, char* absl_nonnull buffer)\n    ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);\nchar* absl_nonnull FastIntToBuffer(uint32_t n, char* absl_nonnull out_str)\n    ABSL_INTERNAL_NEED_MIN_SIZE(out_str, kFastToBufferSize);\nchar* absl_nonnull FastIntToBuffer(int64_t i, char* absl_nonnull buffer)\n    ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);\nchar* absl_nonnull FastIntToBuffer(uint64_t i, char* absl_nonnull buffer)\n    ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);\nchar* absl_nonnull FastIntToBuffer(int128 i, char* absl_nonnull buffer)\n    ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBuffer128Size);\nchar* absl_nonnull FastIntToBuffer(uint128 i, char* absl_nonnull buffer)\n    ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBuffer128Size);\n\n// For enums and integer types that are up to 128 bits and are not an exact\n// match for the types above, use templates to call the appropriate one of the\n// four overloads above.\ntemplate <typename int_type>\nchar* absl_nonnull FastIntToBuffer(int_type i,\n                                          char* absl_nonnull buffer)\n    ABSL_INTERNAL_NEED_MIN_SIZE(\n        buffer, (sizeof(int_type) > 8 ? kFastToBuffer128Size\n                                      : kFastToBufferSize)) {\n  // These conditions are constexpr bools to suppress MSVC warning C4127.\n  constexpr bool kIsSigned = is_signed<int_type>();\n  constexpr bool kUse64Bit = sizeof(i) > 32 / 8;\n  constexpr bool kUse128Bit = sizeof(i) > 64 / 8;\n  if (kIsSigned) {\n    if constexpr (kUse128Bit) {\n      return FastIntToBuffer(static_cast<int128>(i), buffer);\n    } else if constexpr (kUse64Bit) {\n      return FastIntToBuffer(static_cast<int64_t>(i), buffer);\n    } else {\n      return FastIntToBuffer(static_cast<int32_t>(i), buffer);\n    }\n  } else {\n    if constexpr (kUse128Bit) {\n      return FastIntToBuffer(static_cast<uint128>(i), buffer);\n    } else if constexpr (kUse64Bit) {\n      return FastIntToBuffer(static_cast<uint64_t>(i), buffer);\n    } else {\n      return FastIntToBuffer(static_cast<uint32_t>(i), buffer);\n    }\n  }\n}\n\n// Implementation of SimpleAtoi, generalized to support arbitrary base (used\n// with base different from 10 elsewhere in Abseil implementation).\ntemplate <typename int_type>\n[[nodiscard]] bool safe_strtoi_base(absl::string_view s,\n                                    int_type* absl_nonnull out, int base) {\n  static_assert(sizeof(*out) == 1 || sizeof(*out) == 2 || sizeof(*out) == 4 ||\n                    sizeof(*out) == 8,\n                \"SimpleAtoi works only with 8, 16, 32, or 64-bit integers.\");\n  static_assert(!std::is_floating_point<int_type>::value,\n                \"Use SimpleAtof or SimpleAtod instead.\");\n  bool parsed;\n  // These conditions are constexpr bools to suppress MSVC warning C4127.\n  constexpr bool kIsSigned = is_signed<int_type>();\n  constexpr int kIntTypeSize = sizeof(*out) * 8;\n  if (kIsSigned) {\n    if (kIntTypeSize == 64) {\n      int64_t val;\n      parsed = numbers_internal::safe_strto64_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    } else if (kIntTypeSize == 32) {\n      int32_t val;\n      parsed = numbers_internal::safe_strto32_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    } else if (kIntTypeSize == 16) {\n      int16_t val;\n      parsed = numbers_internal::safe_strto16_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    } else if (kIntTypeSize == 8) {\n      int8_t val;\n      parsed = numbers_internal::safe_strto8_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    }\n  } else {\n    if (kIntTypeSize == 64) {\n      uint64_t val;\n      parsed = numbers_internal::safe_strtou64_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    } else if (kIntTypeSize == 32) {\n      uint32_t val;\n      parsed = numbers_internal::safe_strtou32_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    } else if (kIntTypeSize == 16) {\n      uint16_t val;\n      parsed = numbers_internal::safe_strtou16_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    } else if (kIntTypeSize == 8) {\n      uint8_t val;\n      parsed = numbers_internal::safe_strtou8_base(s, &val, base);\n      *out = static_cast<int_type>(val);\n    }\n  }\n  return parsed;\n}\n\n// FastHexToBufferZeroPad16()\n//\n// Outputs `val` into `out` as if by `snprintf(out, 17, \"%016x\", val)` but\n// without the terminating null character. Thus `out` must be of length >= 16.\n// Returns the number of non-pad digits of the output (it can never be zero\n// since 0 has one digit).\ninline size_t FastHexToBufferZeroPad16(uint64_t val, char* absl_nonnull out) {\n#ifdef ABSL_INTERNAL_HAVE_SSSE3\n  uint64_t be = absl::big_endian::FromHost64(val);\n  const auto kNibbleMask = _mm_set1_epi8(0xf);\n  const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',\n                                        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');\n  auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be));  // load lo dword\n  auto v4 = _mm_srli_epi64(v, 4);                            // shift 4 right\n  auto il = _mm_unpacklo_epi8(v4, v);                        // interleave bytes\n  auto m = _mm_and_si128(il, kNibbleMask);                   // mask out nibbles\n  auto hexchars = _mm_shuffle_epi8(kHexDigits, m);           // hex chars\n  _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);\n#else\n  for (int i = 0; i < 8; ++i) {\n    auto byte = (val >> (56 - 8 * i)) & 0xFF;\n    auto* hex = &absl::numbers_internal::kHexTable[byte * 2];\n    std::memcpy(out + 2 * i, hex, 2);\n  }\n#endif\n  // | 0x1 so that even 0 has 1 digit.\n  return 16 - static_cast<size_t>(countl_zero(val | 0x1) / 4);\n}\n\n}  // namespace numbers_internal\n\ntemplate <typename int_type>\n[[nodiscard]] bool SimpleAtoi(absl::string_view str,\n                              int_type* absl_nonnull out) {\n  return numbers_internal::safe_strtoi_base(str, out, 10);\n}\n\n[[nodiscard]] inline bool SimpleAtoi(absl::string_view str,\n                                     absl::int128* absl_nonnull out) {\n  return numbers_internal::safe_strto128_base(str, out, 10);\n}\n\n[[nodiscard]] inline bool SimpleAtoi(absl::string_view str,\n                                     absl::uint128* absl_nonnull out) {\n  return numbers_internal::safe_strtou128_base(str, out, 10);\n}\n\ntemplate <typename int_type>\n[[nodiscard]] bool SimpleHexAtoi(absl::string_view str,\n                                 int_type* absl_nonnull out) {\n  return numbers_internal::safe_strtoi_base(str, out, 16);\n}\n\n[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,\n                                        absl::int128* absl_nonnull out) {\n  return numbers_internal::safe_strto128_base(str, out, 16);\n}\n\n[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,\n                                        absl::uint128* absl_nonnull out) {\n  return numbers_internal::safe_strtou128_base(str, out, 16);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_NUMBERS_H_\n"
  },
  {
    "path": "absl/strings/numbers_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n#include <limits>\n#include <random>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/random/distributions.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\ntemplate <typename T>\nvoid BM_FastIntToBuffer(benchmark::State& state) {\n  const int inc = state.range(0);\n  char buf[absl::numbers_internal::kFastToBufferSize];\n  // Use the unsigned type to increment to take advantage of well-defined\n  // modular arithmetic.\n  typename std::make_unsigned<T>::type x = 0;\n  for (auto _ : state) {\n    absl::numbers_internal::FastIntToBuffer(static_cast<T>(x), buf);\n    x += inc;\n  }\n}\nBENCHMARK_TEMPLATE(BM_FastIntToBuffer, int32_t)->Range(0, 1 << 15);\nBENCHMARK_TEMPLATE(BM_FastIntToBuffer, int64_t)->Range(0, 1 << 30);\n\n// Creates an integer that would be printed as `num_digits` repeated 7s in the\n// given `base`. `base` must be greater than or equal to 8.\nint64_t RepeatedSevens(int num_digits, int base) {\n  ABSL_RAW_CHECK(base >= 8, \"\");\n  int64_t num = 7;\n  while (--num_digits) num = base * num + 7;\n  return num;\n}\n\nvoid BM_safe_strto32_string(benchmark::State& state) {\n  const int digits = state.range(0);\n  const int base = state.range(1);\n  std::string str(digits, '7');  // valid in octal, decimal and hex\n  int32_t value = 0;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(\n        absl::numbers_internal::safe_strto32_base(str, &value, base));\n  }\n  ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), \"\");\n}\nBENCHMARK(BM_safe_strto32_string)\n    ->ArgPair(1, 8)\n    ->ArgPair(1, 10)\n    ->ArgPair(1, 16)\n    ->ArgPair(2, 8)\n    ->ArgPair(2, 10)\n    ->ArgPair(2, 16)\n    ->ArgPair(4, 8)\n    ->ArgPair(4, 10)\n    ->ArgPair(4, 16)\n    ->ArgPair(8, 8)\n    ->ArgPair(8, 10)\n    ->ArgPair(8, 16)\n    ->ArgPair(10, 8)\n    ->ArgPair(9, 10);\n\nvoid BM_safe_strto64_string(benchmark::State& state) {\n  const int digits = state.range(0);\n  const int base = state.range(1);\n  std::string str(digits, '7');  // valid in octal, decimal and hex\n  int64_t value = 0;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(\n        absl::numbers_internal::safe_strto64_base(str, &value, base));\n  }\n  ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), \"\");\n}\nBENCHMARK(BM_safe_strto64_string)\n    ->ArgPair(1, 8)\n    ->ArgPair(1, 10)\n    ->ArgPair(1, 16)\n    ->ArgPair(2, 8)\n    ->ArgPair(2, 10)\n    ->ArgPair(2, 16)\n    ->ArgPair(4, 8)\n    ->ArgPair(4, 10)\n    ->ArgPair(4, 16)\n    ->ArgPair(8, 8)\n    ->ArgPair(8, 10)\n    ->ArgPair(8, 16)\n    ->ArgPair(16, 8)\n    ->ArgPair(16, 10)\n    ->ArgPair(16, 16);\n\nvoid BM_safe_strtou32_string(benchmark::State& state) {\n  const int digits = state.range(0);\n  const int base = state.range(1);\n  std::string str(digits, '7');  // valid in octal, decimal and hex\n  uint32_t value = 0;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(\n        absl::numbers_internal::safe_strtou32_base(str, &value, base));\n  }\n  ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), \"\");\n}\nBENCHMARK(BM_safe_strtou32_string)\n    ->ArgPair(1, 8)\n    ->ArgPair(1, 10)\n    ->ArgPair(1, 16)\n    ->ArgPair(2, 8)\n    ->ArgPair(2, 10)\n    ->ArgPair(2, 16)\n    ->ArgPair(4, 8)\n    ->ArgPair(4, 10)\n    ->ArgPair(4, 16)\n    ->ArgPair(8, 8)\n    ->ArgPair(8, 10)\n    ->ArgPair(8, 16)\n    ->ArgPair(10, 8)\n    ->ArgPair(9, 10);\n\nvoid BM_safe_strtou64_string(benchmark::State& state) {\n  const int digits = state.range(0);\n  const int base = state.range(1);\n  std::string str(digits, '7');  // valid in octal, decimal and hex\n  uint64_t value = 0;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(\n        absl::numbers_internal::safe_strtou64_base(str, &value, base));\n  }\n  ABSL_RAW_CHECK(value == RepeatedSevens(digits, base), \"\");\n}\nBENCHMARK(BM_safe_strtou64_string)\n    ->ArgPair(1, 8)\n    ->ArgPair(1, 10)\n    ->ArgPair(1, 16)\n    ->ArgPair(2, 8)\n    ->ArgPair(2, 10)\n    ->ArgPair(2, 16)\n    ->ArgPair(4, 8)\n    ->ArgPair(4, 10)\n    ->ArgPair(4, 16)\n    ->ArgPair(8, 8)\n    ->ArgPair(8, 10)\n    ->ArgPair(8, 16)\n    ->ArgPair(16, 8)\n    ->ArgPair(16, 10)\n    ->ArgPair(16, 16);\n\n// Returns a vector of `num_strings` strings. Each string represents a\n// floating point number with `num_digits` digits before the decimal point and\n// another `num_digits` digits after.\nstd::vector<std::string> MakeFloatStrings(int num_strings, int num_digits) {\n  // For convenience, use a random number generator to generate the test data.\n  // We don't actually need random properties, so use a fixed seed.\n  std::minstd_rand0 rng(1);\n  std::uniform_int_distribution<int> random_digit('0', '9');\n\n  std::vector<std::string> float_strings(num_strings);\n  for (std::string& s : float_strings) {\n    s.reserve(2 * num_digits + 1);\n    for (int i = 0; i < num_digits; ++i) {\n      s.push_back(static_cast<char>(random_digit(rng)));\n    }\n    s.push_back('.');\n    for (int i = 0; i < num_digits; ++i) {\n      s.push_back(static_cast<char>(random_digit(rng)));\n    }\n  }\n  return float_strings;\n}\n\ntemplate <typename StringType>\nStringType GetStringAs(const std::string& s) {\n  return static_cast<StringType>(s);\n}\ntemplate <>\nconst char* GetStringAs<const char*>(const std::string& s) {\n  return s.c_str();\n}\n\ntemplate <typename StringType>\nstd::vector<StringType> GetStringsAs(const std::vector<std::string>& strings) {\n  std::vector<StringType> result;\n  result.reserve(strings.size());\n  for (const std::string& s : strings) {\n    result.push_back(GetStringAs<StringType>(s));\n  }\n  return result;\n}\n\ntemplate <typename T>\nvoid BM_SimpleAtof(benchmark::State& state) {\n  const int num_strings = state.range(0);\n  const int num_digits = state.range(1);\n  std::vector<std::string> backing_strings =\n      MakeFloatStrings(num_strings, num_digits);\n  std::vector<T> inputs = GetStringsAs<T>(backing_strings);\n  float value;\n  for (auto _ : state) {\n    for (const T& input : inputs) {\n      benchmark::DoNotOptimize(absl::SimpleAtof(input, &value));\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_SimpleAtof, absl::string_view)\n    ->ArgPair(10, 1)\n    ->ArgPair(10, 2)\n    ->ArgPair(10, 4)\n    ->ArgPair(10, 8);\nBENCHMARK_TEMPLATE(BM_SimpleAtof, const char*)\n    ->ArgPair(10, 1)\n    ->ArgPair(10, 2)\n    ->ArgPair(10, 4)\n    ->ArgPair(10, 8);\nBENCHMARK_TEMPLATE(BM_SimpleAtof, std::string)\n    ->ArgPair(10, 1)\n    ->ArgPair(10, 2)\n    ->ArgPair(10, 4)\n    ->ArgPair(10, 8);\n\ntemplate <typename T>\nvoid BM_SimpleAtod(benchmark::State& state) {\n  const int num_strings = state.range(0);\n  const int num_digits = state.range(1);\n  std::vector<std::string> backing_strings =\n      MakeFloatStrings(num_strings, num_digits);\n  std::vector<T> inputs = GetStringsAs<T>(backing_strings);\n  double value;\n  for (auto _ : state) {\n    for (const T& input : inputs) {\n      benchmark::DoNotOptimize(absl::SimpleAtod(input, &value));\n    }\n  }\n}\nBENCHMARK_TEMPLATE(BM_SimpleAtod, absl::string_view)\n    ->ArgPair(10, 1)\n    ->ArgPair(10, 2)\n    ->ArgPair(10, 4)\n    ->ArgPair(10, 8);\nBENCHMARK_TEMPLATE(BM_SimpleAtod, const char*)\n    ->ArgPair(10, 1)\n    ->ArgPair(10, 2)\n    ->ArgPair(10, 4)\n    ->ArgPair(10, 8);\nBENCHMARK_TEMPLATE(BM_SimpleAtod, std::string)\n    ->ArgPair(10, 1)\n    ->ArgPair(10, 2)\n    ->ArgPair(10, 4)\n    ->ArgPair(10, 8);\n\nvoid BM_FastHexToBufferZeroPad16(benchmark::State& state) {\n  absl::BitGen rng;\n  std::vector<uint64_t> nums;\n  nums.resize(1000);\n  auto min = std::numeric_limits<uint64_t>::min();\n  auto max = std::numeric_limits<uint64_t>::max();\n  for (auto& num : nums) {\n    num = absl::LogUniform(rng, min, max);\n  }\n\n  char buf[16];\n  while (state.KeepRunningBatch(nums.size())) {\n    for (auto num : nums) {\n      auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(num, buf);\n      benchmark::DoNotOptimize(digits);\n      benchmark::DoNotOptimize(buf);\n    }\n  }\n}\nBENCHMARK(BM_FastHexToBufferZeroPad16);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/numbers_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file tests string processing functions related to numeric values.\n\n#include \"absl/strings/numbers.h\"\n\n#include <sys/types.h>\n\n#include <cfenv>  // NOLINT(build/c++11)\n#include <cfloat>\n#include <cinttypes>\n#include <climits>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <ios>\n#include <limits>\n#include <numeric>\n#include <random>\n#include <set>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/log/log.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/internal/numbers_test_common.h\"\n#include \"absl/strings/internal/ostringstream.h\"\n#include \"absl/strings/internal/pow10_helper.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nusing absl::SimpleAtoi;\nusing absl::SimpleHexAtoi;\nusing absl::numbers_internal::kSixDigitsToBufferSize;\nusing absl::numbers_internal::safe_strto16_base;\nusing absl::numbers_internal::safe_strto32_base;\nusing absl::numbers_internal::safe_strto64_base;\nusing absl::numbers_internal::safe_strto8_base;\nusing absl::numbers_internal::safe_strtou16_base;\nusing absl::numbers_internal::safe_strtou32_base;\nusing absl::numbers_internal::safe_strtou64_base;\nusing absl::numbers_internal::safe_strtou8_base;\nusing absl::numbers_internal::SixDigitsToBuffer;\nusing absl::strings_internal::Itoa;\nusing absl::strings_internal::strtouint32_test_cases;\nusing absl::strings_internal::strtouint64_test_cases;\nusing testing::Eq;\nusing testing::MatchesRegex;\nusing testing::Pointee;\n\n// Number of floats to test with.\n// 5,000,000 is a reasonable default for a test that only takes a few seconds.\n// 1,000,000,000+ triggers checking for all possible mantissa values for\n// double-precision tests. 2,000,000,000+ triggers checking for every possible\n// single-precision float.\nconst int kFloatNumCases = 5000000;\n\n// This is a slow, brute-force routine to compute the exact base-10\n// representation of a double-precision floating-point number.  It\n// is useful for debugging only.\nstd::string PerfectDtoa(double d) {\n  if (d == 0) return \"0\";\n  if (d < 0) return \"-\" + PerfectDtoa(-d);\n\n  // Basic theory: decompose d into mantissa and exp, where\n  // d = mantissa * 2^exp, and exp is as close to zero as possible.\n  int64_t mantissa, exp = 0;\n  while (d >= 1ULL << 63) ++exp, d *= 0.5;\n  while ((mantissa = d) != d) --exp, d *= 2.0;\n\n  // Then convert mantissa to ASCII, and either double it (if\n  // exp > 0) or halve it (if exp < 0) repeatedly.  \"halve it\"\n  // in this case means multiplying it by five and dividing by 10.\n  constexpr int maxlen = 1100;  // worst case is actually 1030 or so.\n  char buf[maxlen + 5];\n  for (int64_t num = mantissa, pos = maxlen; --pos >= 0;) {\n    buf[pos] = '0' + (num % 10);\n    num /= 10;\n  }\n  char* begin = &buf[0];\n  char* end = buf + maxlen;\n  for (int i = 0; i != exp; i += (exp > 0) ? 1 : -1) {\n    int carry = 0;\n    for (char* p = end; --p != begin;) {\n      int dig = *p - '0';\n      dig = dig * (exp > 0 ? 2 : 5) + carry;\n      carry = dig / 10;\n      dig %= 10;\n      *p = '0' + dig;\n    }\n  }\n  if (exp < 0) {\n    // \"dividing by 10\" above means we have to add the decimal point.\n    memmove(end + 1 + exp, end + exp, 1 - exp);\n    end[exp] = '.';\n    ++end;\n  }\n  while (*begin == '0' && begin[1] != '.') ++begin;\n  return {begin, end};\n}\n\nTEST(ToString, PerfectDtoa) {\n  EXPECT_THAT(PerfectDtoa(1), Eq(\"1\"));\n  EXPECT_THAT(PerfectDtoa(0.1),\n              Eq(\"0.1000000000000000055511151231257827021181583404541015625\"));\n  EXPECT_THAT(PerfectDtoa(1e24), Eq(\"999999999999999983222784\"));\n  EXPECT_THAT(PerfectDtoa(5e-324), MatchesRegex(\"0.0000.*625\"));\n  for (int i = 0; i < 100; ++i) {\n    for (double multiplier :\n         {1e-300, 1e-200, 1e-100, 0.1, 1.0, 10.0, 1e100, 1e300}) {\n      double d = multiplier * i;\n      std::string s = PerfectDtoa(d);\n      EXPECT_DOUBLE_EQ(d, strtod(s.c_str(), nullptr));\n    }\n  }\n}\n\ntemplate <typename integer>\nstruct MyInteger {\n  integer i;\n  explicit constexpr MyInteger(integer i) : i(i) {}\n  constexpr operator integer() const { return i; }\n\n  constexpr MyInteger operator+(MyInteger other) const { return i + other.i; }\n  constexpr MyInteger operator-(MyInteger other) const { return i - other.i; }\n  constexpr MyInteger operator*(MyInteger other) const { return i * other.i; }\n  constexpr MyInteger operator/(MyInteger other) const { return i / other.i; }\n\n  constexpr bool operator<(MyInteger other) const { return i < other.i; }\n  constexpr bool operator<=(MyInteger other) const { return i <= other.i; }\n  constexpr bool operator==(MyInteger other) const { return i == other.i; }\n  constexpr bool operator>=(MyInteger other) const { return i >= other.i; }\n  constexpr bool operator>(MyInteger other) const { return i > other.i; }\n  constexpr bool operator!=(MyInteger other) const { return i != other.i; }\n\n  integer as_integer() const { return i; }\n};\n\ntypedef MyInteger<int64_t> MyInt64;\ntypedef MyInteger<uint64_t> MyUInt64;\ntypedef MyInteger<absl::uint128> MyUInt128;\ntypedef MyInteger<absl::int128> MyInt128;\n\nvoid CheckInt32(int32_t x) {\n  char buffer[absl::numbers_internal::kFastToBufferSize];\n  char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);\n  std::string expected = std::to_string(x);\n  EXPECT_EQ(expected, std::string(buffer, actual)) << \" Input \" << x;\n\n  char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer);\n  EXPECT_EQ(expected, std::string(buffer, generic_actual)) << \" Input \" << x;\n}\n\nvoid CheckInt64(int64_t x) {\n  char buffer[absl::numbers_internal::kFastToBufferSize + 3];\n  buffer[0] = '*';\n  buffer[23] = '*';\n  buffer[24] = '*';\n  char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);\n  std::string expected = std::to_string(x);\n  EXPECT_EQ(expected, std::string(&buffer[1], actual)) << \" Input \" << x;\n  EXPECT_EQ(buffer[0], '*');\n  EXPECT_EQ(buffer[23], '*');\n  EXPECT_EQ(buffer[24], '*');\n\n  char* my_actual =\n      absl::numbers_internal::FastIntToBuffer(MyInt64(x), &buffer[1]);\n  EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << \" Input \" << x;\n}\n\nvoid CheckUInt32(uint32_t x) {\n  char buffer[absl::numbers_internal::kFastToBufferSize];\n  char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);\n  std::string expected = std::to_string(x);\n  EXPECT_EQ(expected, std::string(buffer, actual)) << \" Input \" << x;\n\n  char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer);\n  EXPECT_EQ(expected, std::string(buffer, generic_actual)) << \" Input \" << x;\n}\n\nvoid CheckUInt64(uint64_t x) {\n  char buffer[absl::numbers_internal::kFastToBufferSize + 1];\n  char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);\n  std::string expected = std::to_string(x);\n  EXPECT_EQ(expected, std::string(&buffer[1], actual)) << \" Input \" << x;\n\n  char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);\n  EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))\n      << \" Input \" << x;\n\n  char* my_actual =\n      absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);\n  EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << \" Input \" << x;\n}\n\nvoid CheckUInt128(absl::uint128 x) {\n  char buffer[absl::numbers_internal::kFastToBuffer128Size];\n  char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);\n  std::string s;\n  absl::strings_internal::OStringStream strm(&s);\n  strm << x;\n  EXPECT_EQ(s, std::string(buffer, actual)) << \" Input \" << s;\n\n  char* my_actual =\n      absl::numbers_internal::FastIntToBuffer(MyUInt128(x), buffer);\n  EXPECT_EQ(s, std::string(buffer, my_actual)) << \" Input \" << s;\n}\n\nvoid CheckInt128(absl::int128 x) {\n  char buffer[absl::numbers_internal::kFastToBuffer128Size];\n  char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);\n  std::string s;\n  absl::strings_internal::OStringStream strm(&s);\n  strm << x;\n  EXPECT_EQ(s, std::string(buffer, actual)) << \" Input \" << s;\n\n  char* my_actual =\n      absl::numbers_internal::FastIntToBuffer(MyInt128(x), buffer);\n  EXPECT_EQ(s, std::string(buffer, my_actual)) << \" Input \" << s;\n}\n\nvoid CheckHex64(uint64_t v) {\n  char expected[16 + 1];\n  std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));\n  snprintf(expected, sizeof(expected), \"%016\" PRIx64, static_cast<uint64_t>(v));\n  EXPECT_EQ(expected, actual) << \" Input \" << v;\n  actual = absl::StrCat(absl::Hex(v, absl::kSpacePad16));\n  snprintf(expected, sizeof(expected), \"%16\" PRIx64, static_cast<uint64_t>(v));\n  EXPECT_EQ(expected, actual) << \" Input \" << v;\n}\n\nTEST(Numbers, TestFastPrints) {\n  for (int i = -100; i <= 100; i++) {\n    CheckInt32(i);\n    CheckInt64(i);\n  }\n  for (int i = 0; i <= 100; i++) {\n    CheckUInt32(i);\n    CheckUInt64(i);\n  }\n  // Test min int to make sure that works\n  CheckInt32(INT_MIN);\n  CheckInt32(INT_MAX);\n  CheckInt64(LONG_MIN);\n  CheckInt64(uint64_t{1000000000});\n  CheckInt64(uint64_t{9999999999});\n  CheckInt64(uint64_t{100000000000000});\n  CheckInt64(uint64_t{999999999999999});\n  CheckInt64(uint64_t{1000000000000000000});\n  CheckInt64(uint64_t{1199999999999999999});\n  CheckInt64(int64_t{-700000000000000000});\n  CheckInt64(LONG_MAX);\n  CheckUInt32(std::numeric_limits<uint32_t>::max());\n  CheckUInt64(uint64_t{1000000000});\n  CheckUInt64(uint64_t{9999999999});\n  CheckUInt64(uint64_t{100000000000000});\n  CheckUInt64(uint64_t{999999999999999});\n  CheckUInt64(uint64_t{1000000000000000000});\n  CheckUInt64(uint64_t{1199999999999999999});\n  CheckUInt64(std::numeric_limits<uint64_t>::max());\n  CheckUInt128(0);\n  CheckUInt128(1);\n  CheckUInt128(9);\n  CheckUInt128(10);\n  CheckUInt128(99);\n  CheckUInt128(100);\n  CheckUInt128(std::numeric_limits<uint64_t>::max());\n  CheckUInt128(absl::uint128(std::numeric_limits<uint64_t>::max()) + 1);\n  CheckUInt128(absl::MakeUint128(1, 0));\n  absl::uint128 k1e16 = 10000000000000000ULL;\n  CheckUInt128(k1e16 - 1);\n  CheckUInt128(k1e16);\n  CheckUInt128(k1e16 + 1);\n  CheckUInt128(k1e16 * k1e16 - 1);\n  CheckUInt128(k1e16 * k1e16);\n  CheckUInt128(k1e16 * k1e16 + 1);\n  CheckUInt128(absl::Uint128Max() - 1);\n  CheckUInt128(absl::Uint128Max());\n\n  CheckInt128(0);\n  CheckInt128(1);\n  CheckInt128(-1);\n  CheckInt128(10);\n  CheckInt128(-10);\n  CheckInt128(absl::Int128Max());\n  CheckInt128(absl::Int128Min());\n  CheckInt128(absl::MakeInt128(-1, 1));\n  CheckInt128(absl::MakeInt128(-1, std::numeric_limits<uint64_t>::max()));\n\n  for (int i = 0; i < 10000; i++) {\n    CheckHex64(i);\n  }\n  CheckHex64(uint64_t{0x123456789abcdef0});\n}\n\ntemplate <typename int_type, typename in_val_type>\nvoid VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {\n  std::string s = absl::StrCat(in_value);\n  int_type x = static_cast<int_type>(~exp_value);\n  EXPECT_TRUE(SimpleAtoi(s, &x))\n      << \"in_value=\" << in_value << \" s=\" << s << \" x=\" << x;\n  EXPECT_EQ(exp_value, x);\n  x = static_cast<int_type>(~exp_value);\n  EXPECT_TRUE(SimpleAtoi(s.c_str(), &x));\n  EXPECT_EQ(exp_value, x);\n}\n\ntemplate <typename int_type, typename in_val_type>\nvoid VerifySimpleAtoiBad(in_val_type in_value) {\n  std::string s = absl::StrCat(in_value);\n  int_type x;\n  EXPECT_FALSE(SimpleAtoi(s, &x));\n  EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));\n}\n\nTEST(NumbersTest, Atoi) {\n  // SimpleAtoi(absl::string_view, int8_t)\n  VerifySimpleAtoiGood<int8_t>(0, 0);\n  VerifySimpleAtoiGood<int8_t>(42, 42);\n  VerifySimpleAtoiGood<int8_t>(-42, -42);\n\n  VerifySimpleAtoiGood<int8_t>(std::numeric_limits<int8_t>::min(),\n                               std::numeric_limits<int8_t>::min());\n  VerifySimpleAtoiGood<int8_t>(std::numeric_limits<int8_t>::max(),\n                               std::numeric_limits<int8_t>::max());\n\n  VerifySimpleAtoiBad<int8_t>(std::numeric_limits<uint8_t>::max());\n  VerifySimpleAtoiBad<int8_t>(std::numeric_limits<int16_t>::min());\n  VerifySimpleAtoiBad<int8_t>(std::numeric_limits<int16_t>::max());\n\n  // SimpleAtoi(absl::string_view, uint8_t)\n  VerifySimpleAtoiGood<uint8_t>(0, 0);\n  VerifySimpleAtoiGood<uint8_t>(42, 42);\n  VerifySimpleAtoiBad<uint8_t>(-42);\n\n  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<int8_t>::min());\n  VerifySimpleAtoiGood<uint8_t>(std::numeric_limits<int8_t>::max(),\n                                std::numeric_limits<int8_t>::max());\n  VerifySimpleAtoiGood<uint8_t>(std::numeric_limits<uint8_t>::max(),\n                                std::numeric_limits<uint8_t>::max());\n\n  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<int16_t>::min());\n  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<int16_t>::max());\n  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<uint16_t>::max());\n\n  // SimpleAtoi(absl::string_view, uint16_t)\n  VerifySimpleAtoiGood<int16_t>(0, 0);\n  VerifySimpleAtoiGood<int16_t>(42, 42);\n  VerifySimpleAtoiGood<int16_t>(-42, -42);\n\n  VerifySimpleAtoiGood<int16_t>(std::numeric_limits<int16_t>::min(),\n                                std::numeric_limits<int16_t>::min());\n  VerifySimpleAtoiGood<int16_t>(std::numeric_limits<int16_t>::max(),\n                                std::numeric_limits<int16_t>::max());\n\n  VerifySimpleAtoiBad<int16_t>(std::numeric_limits<uint16_t>::max());\n  VerifySimpleAtoiBad<int16_t>(std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiBad<int16_t>(std::numeric_limits<int32_t>::max());\n\n  // SimpleAtoi(absl::string_view, uint16_t)\n  VerifySimpleAtoiGood<uint16_t>(0, 0);\n  VerifySimpleAtoiGood<uint16_t>(42, 42);\n  VerifySimpleAtoiBad<uint16_t>(-42);\n\n  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<int16_t>::min());\n  VerifySimpleAtoiGood<uint16_t>(std::numeric_limits<int16_t>::max(),\n                                 std::numeric_limits<int16_t>::max());\n  VerifySimpleAtoiGood<uint16_t>(std::numeric_limits<uint16_t>::max(),\n                                 std::numeric_limits<uint16_t>::max());\n\n  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<int16_t>::min());\n  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<int32_t>::max());\n  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<uint32_t>::max());\n\n  // SimpleAtoi(absl::string_view, int32_t)\n  VerifySimpleAtoiGood<int32_t>(0, 0);\n  VerifySimpleAtoiGood<int32_t>(42, 42);\n  VerifySimpleAtoiGood<int32_t>(-42, -42);\n\n  VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(),\n                                std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(),\n                                std::numeric_limits<int32_t>::max());\n\n  // SimpleAtoi(absl::string_view, uint32_t)\n  VerifySimpleAtoiGood<uint32_t>(0, 0);\n  VerifySimpleAtoiGood<uint32_t>(42, 42);\n  VerifySimpleAtoiBad<uint32_t>(-42);\n\n  VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(),\n                                 std::numeric_limits<int32_t>::max());\n  VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(),\n                                 std::numeric_limits<uint32_t>::max());\n  VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min());\n  VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max());\n  VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max());\n\n  // SimpleAtoi(absl::string_view, int64_t)\n  VerifySimpleAtoiGood<int64_t>(0, 0);\n  VerifySimpleAtoiGood<int64_t>(42, 42);\n  VerifySimpleAtoiGood<int64_t>(-42, -42);\n\n  VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(),\n                                std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(),\n                                std::numeric_limits<int32_t>::max());\n  VerifySimpleAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(),\n                                std::numeric_limits<uint32_t>::max());\n  VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(),\n                                std::numeric_limits<int64_t>::min());\n  VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(),\n                                std::numeric_limits<int64_t>::max());\n  VerifySimpleAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max());\n\n  // SimpleAtoi(absl::string_view, uint64_t)\n  VerifySimpleAtoiGood<uint64_t>(0, 0);\n  VerifySimpleAtoiGood<uint64_t>(42, 42);\n  VerifySimpleAtoiBad<uint64_t>(-42);\n\n  VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(),\n                                 std::numeric_limits<int32_t>::max());\n  VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(),\n                                 std::numeric_limits<uint32_t>::max());\n  VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min());\n  VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(),\n                                 std::numeric_limits<int64_t>::max());\n  VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),\n                                 std::numeric_limits<uint64_t>::max());\n\n  // SimpleAtoi(absl::string_view, absl::uint128)\n  VerifySimpleAtoiGood<absl::uint128>(0, 0);\n  VerifySimpleAtoiGood<absl::uint128>(42, 42);\n  VerifySimpleAtoiBad<absl::uint128>(-42);\n\n  VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),\n                                      std::numeric_limits<int32_t>::max());\n  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),\n                                      std::numeric_limits<uint32_t>::max());\n  VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());\n  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),\n                                      std::numeric_limits<int64_t>::max());\n  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),\n                                      std::numeric_limits<uint64_t>::max());\n  VerifySimpleAtoiGood<absl::uint128>(\n      std::numeric_limits<absl::uint128>::max(),\n      std::numeric_limits<absl::uint128>::max());\n\n  // SimpleAtoi(absl::string_view, absl::int128)\n  VerifySimpleAtoiGood<absl::int128>(0, 0);\n  VerifySimpleAtoiGood<absl::int128>(42, 42);\n  VerifySimpleAtoiGood<absl::int128>(-42, -42);\n\n  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),\n                                      std::numeric_limits<int32_t>::min());\n  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),\n                                      std::numeric_limits<int32_t>::max());\n  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),\n                                      std::numeric_limits<uint32_t>::max());\n  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),\n                                      std::numeric_limits<int64_t>::min());\n  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),\n                                      std::numeric_limits<int64_t>::max());\n  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),\n                                      std::numeric_limits<uint64_t>::max());\n  VerifySimpleAtoiGood<absl::int128>(\n      std::numeric_limits<absl::int128>::min(),\n      std::numeric_limits<absl::int128>::min());\n  VerifySimpleAtoiGood<absl::int128>(\n      std::numeric_limits<absl::int128>::max(),\n      std::numeric_limits<absl::int128>::max());\n  VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());\n\n  // Some other types\n  VerifySimpleAtoiGood<short>(-42, -42);  // NOLINT: runtime-int\n  VerifySimpleAtoiGood<int>(-42, -42);\n  VerifySimpleAtoiGood<int32_t>(-42, -42);\n  VerifySimpleAtoiGood<uint32_t>(42, 42);\n  VerifySimpleAtoiGood<unsigned int>(42, 42);\n  VerifySimpleAtoiGood<int64_t>(-42, -42);\n  VerifySimpleAtoiGood<long>(-42, -42);  // NOLINT: runtime-int\n  VerifySimpleAtoiGood<uint64_t>(42, 42);\n  VerifySimpleAtoiGood<size_t>(42, 42);\n  VerifySimpleAtoiGood<std::string::size_type>(42, 42);\n}\n\nTEST(NumbersTest, AtodEmpty) {\n  double d;\n  EXPECT_FALSE(absl::SimpleAtod(\"\", &d));\n  // Empty string_view takes a different code path from \"\".\n  EXPECT_FALSE(absl::SimpleAtod({}, &d));\n}\n\nTEST(NumbersTest, AtofEmpty) {\n  float f;\n  EXPECT_FALSE(absl::SimpleAtof(\"\", &f));\n  // Empty string_view takes a different code path from \"\".\n  EXPECT_FALSE(absl::SimpleAtof({}, &f));\n}\n\nTEST(NumbersTest, Atod) {\n  // DBL_TRUE_MIN and FLT_TRUE_MIN were not mandated in <cfloat> before C++17.\n#if !defined(DBL_TRUE_MIN)\n  static constexpr double DBL_TRUE_MIN =\n      4.940656458412465441765687928682213723650598026143247644255856825e-324;\n#endif\n#if !defined(FLT_TRUE_MIN)\n  static constexpr float FLT_TRUE_MIN =\n      1.401298464324817070923729583289916131280261941876515771757068284e-45f;\n#endif\n\n  double d;\n  float f;\n\n  // NaN can be spelled in multiple ways.\n  EXPECT_TRUE(absl::SimpleAtod(\"NaN\", &d));\n  EXPECT_TRUE(std::isnan(d));\n  EXPECT_TRUE(absl::SimpleAtod(\"nAN\", &d));\n  EXPECT_TRUE(std::isnan(d));\n  EXPECT_TRUE(absl::SimpleAtod(\"-nan\", &d));\n  EXPECT_TRUE(std::isnan(d));\n\n  // Likewise for Infinity.\n  EXPECT_TRUE(absl::SimpleAtod(\"inf\", &d));\n  EXPECT_TRUE(std::isinf(d) && (d > 0));\n  EXPECT_TRUE(absl::SimpleAtod(\"+Infinity\", &d));\n  EXPECT_TRUE(std::isinf(d) && (d > 0));\n  EXPECT_TRUE(absl::SimpleAtod(\"-INF\", &d));\n  EXPECT_TRUE(std::isinf(d) && (d < 0));\n\n  // Parse DBL_MAX. Parsing something more than twice as big should also\n  // produce infinity.\n  EXPECT_TRUE(absl::SimpleAtod(\"1.7976931348623157e+308\", &d));\n  EXPECT_EQ(d, 1.7976931348623157e+308);\n  EXPECT_TRUE(absl::SimpleAtod(\"5e308\", &d));\n  EXPECT_TRUE(std::isinf(d) && (d > 0));\n  // Ditto, but for FLT_MAX.\n  EXPECT_TRUE(absl::SimpleAtof(\"3.4028234663852886e+38\", &f));\n  EXPECT_EQ(f, 3.4028234663852886e+38f);\n  EXPECT_TRUE(absl::SimpleAtof(\"7e38\", &f));\n  EXPECT_TRUE(std::isinf(f) && (f > 0));\n\n  // Parse the largest N such that parsing 1eN produces a finite value and the\n  // smallest M = N + 1 such that parsing 1eM produces infinity.\n  //\n  // The 309 exponent (and 39) confirms the \"definition of\n  // kEiselLemireMaxExclExp10\" comment in charconv.cc.\n  EXPECT_TRUE(absl::SimpleAtod(\"1e308\", &d));\n  EXPECT_EQ(d, 1e308);\n  EXPECT_FALSE(std::isinf(d));\n  EXPECT_TRUE(absl::SimpleAtod(\"1e309\", &d));\n  EXPECT_TRUE(std::isinf(d));\n  // Ditto, but for Atof instead of Atod.\n  EXPECT_TRUE(absl::SimpleAtof(\"1e38\", &f));\n  EXPECT_EQ(f, 1e38f);\n  EXPECT_FALSE(std::isinf(f));\n  EXPECT_TRUE(absl::SimpleAtof(\"1e39\", &f));\n  EXPECT_TRUE(std::isinf(f));\n\n  // Parse the largest N such that parsing 9.999999999999999999eN, with 19\n  // nines, produces a finite value.\n  //\n  // 9999999999999999999, with 19 nines but no decimal point, is the largest\n  // \"repeated nines\" integer that fits in a uint64_t.\n  EXPECT_TRUE(absl::SimpleAtod(\"9.999999999999999999e307\", &d));\n  EXPECT_EQ(d, 9.999999999999999999e307);\n  EXPECT_FALSE(std::isinf(d));\n  EXPECT_TRUE(absl::SimpleAtod(\"9.999999999999999999e308\", &d));\n  EXPECT_TRUE(std::isinf(d));\n  // Ditto, but for Atof instead of Atod.\n  EXPECT_TRUE(absl::SimpleAtof(\"9.999999999999999999e37\", &f));\n  EXPECT_EQ(f, 9.999999999999999999e37f);\n  EXPECT_FALSE(std::isinf(f));\n  EXPECT_TRUE(absl::SimpleAtof(\"9.999999999999999999e38\", &f));\n  EXPECT_TRUE(std::isinf(f));\n\n  // Parse DBL_MIN (normal), DBL_TRUE_MIN (subnormal) and (DBL_TRUE_MIN / 10)\n  // (effectively zero).\n  EXPECT_TRUE(absl::SimpleAtod(\"2.2250738585072014e-308\", &d));\n  EXPECT_EQ(d, 2.2250738585072014e-308);\n  EXPECT_TRUE(absl::SimpleAtod(\"4.9406564584124654e-324\", &d));\n  EXPECT_EQ(d, 4.9406564584124654e-324);\n  EXPECT_TRUE(absl::SimpleAtod(\"4.9406564584124654e-325\", &d));\n  EXPECT_EQ(d, 0);\n  // Ditto, but for FLT_MIN, FLT_TRUE_MIN and (FLT_TRUE_MIN / 10).\n  EXPECT_TRUE(absl::SimpleAtof(\"1.1754943508222875e-38\", &f));\n  EXPECT_EQ(f, 1.1754943508222875e-38f);\n  EXPECT_TRUE(absl::SimpleAtof(\"1.4012984643248171e-45\", &f));\n  EXPECT_EQ(f, 1.4012984643248171e-45f);\n  EXPECT_TRUE(absl::SimpleAtof(\"1.4012984643248171e-46\", &f));\n  EXPECT_EQ(f, 0);\n\n  // Parse the largest N (the most negative -N) such that parsing 1e-N produces\n  // a normal or subnormal (but still positive) or zero value.\n  EXPECT_TRUE(absl::SimpleAtod(\"1e-307\", &d));\n  EXPECT_EQ(d, 1e-307);\n  EXPECT_GE(d, DBL_MIN);\n  EXPECT_LT(d, DBL_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtod(\"1e-323\", &d));\n  EXPECT_EQ(d, 1e-323);\n  EXPECT_GE(d, DBL_TRUE_MIN);\n  EXPECT_LT(d, DBL_TRUE_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtod(\"1e-324\", &d));\n  EXPECT_EQ(d, 0);\n  // Ditto, but for Atof instead of Atod.\n  EXPECT_TRUE(absl::SimpleAtof(\"1e-37\", &f));\n  EXPECT_EQ(f, 1e-37f);\n  EXPECT_GE(f, FLT_MIN);\n  EXPECT_LT(f, FLT_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtof(\"1e-45\", &f));\n  EXPECT_EQ(f, 1e-45f);\n  EXPECT_GE(f, FLT_TRUE_MIN);\n  EXPECT_LT(f, FLT_TRUE_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtof(\"1e-46\", &f));\n  EXPECT_EQ(f, 0);\n\n  // Parse the largest N (the most negative -N) such that parsing\n  // 9.999999999999999999e-N, with 19 nines, produces a normal or subnormal\n  // (but still positive) or zero value.\n  //\n  // 9999999999999999999, with 19 nines but no decimal point, is the largest\n  // \"repeated nines\" integer that fits in a uint64_t.\n  //\n  // The -324/-325 exponents (and -46/-47) confirms the \"definition of\n  // kEiselLemireMinInclExp10\" comment in charconv.cc.\n  EXPECT_TRUE(absl::SimpleAtod(\"9.999999999999999999e-308\", &d));\n  EXPECT_EQ(d, 9.999999999999999999e-308);\n  EXPECT_GE(d, DBL_MIN);\n  EXPECT_LT(d, DBL_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtod(\"9.999999999999999999e-324\", &d));\n  EXPECT_EQ(d, 9.999999999999999999e-324);\n  EXPECT_GE(d, DBL_TRUE_MIN);\n  EXPECT_LT(d, DBL_TRUE_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtod(\"9.999999999999999999e-325\", &d));\n  EXPECT_EQ(d, 0);\n  // Ditto, but for Atof instead of Atod.\n  EXPECT_TRUE(absl::SimpleAtof(\"9.999999999999999999e-38\", &f));\n  EXPECT_EQ(f, 9.999999999999999999e-38f);\n  EXPECT_GE(f, FLT_MIN);\n  EXPECT_LT(f, FLT_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtof(\"9.999999999999999999e-46\", &f));\n  EXPECT_EQ(f, 9.999999999999999999e-46f);\n  EXPECT_GE(f, FLT_TRUE_MIN);\n  EXPECT_LT(f, FLT_TRUE_MIN * 10);\n  EXPECT_TRUE(absl::SimpleAtof(\"9.999999999999999999e-47\", &f));\n  EXPECT_EQ(f, 0);\n\n  // Leading and/or trailing whitespace is OK.\n  EXPECT_TRUE(absl::SimpleAtod(\"  \\t\\r\\n  2.718\", &d));\n  EXPECT_EQ(d, 2.718);\n  EXPECT_TRUE(absl::SimpleAtod(\"  3.141  \", &d));\n  EXPECT_EQ(d, 3.141);\n\n  // Leading or trailing not-whitespace is not OK.\n  EXPECT_FALSE(absl::SimpleAtod(\"n 0\", &d));\n  EXPECT_FALSE(absl::SimpleAtod(\"0n \", &d));\n\n  // Multiple leading 0s are OK.\n  EXPECT_TRUE(absl::SimpleAtod(\"000123\", &d));\n  EXPECT_EQ(d, 123);\n  EXPECT_TRUE(absl::SimpleAtod(\"000.456\", &d));\n  EXPECT_EQ(d, 0.456);\n\n  // An absent leading 0 (for a fraction < 1) is OK.\n  EXPECT_TRUE(absl::SimpleAtod(\".5\", &d));\n  EXPECT_EQ(d, 0.5);\n  EXPECT_TRUE(absl::SimpleAtod(\"-.707\", &d));\n  EXPECT_EQ(d, -0.707);\n\n  // Unary + is OK.\n  EXPECT_TRUE(absl::SimpleAtod(\"+6.0221408e+23\", &d));\n  EXPECT_EQ(d, 6.0221408e+23);\n\n  // Underscores are not OK.\n  EXPECT_FALSE(absl::SimpleAtod(\"123_456\", &d));\n\n  // The decimal separator must be '.' and is never ','.\n  EXPECT_TRUE(absl::SimpleAtod(\"8.9\", &d));\n  EXPECT_FALSE(absl::SimpleAtod(\"8,9\", &d));\n\n  // These examples are called out in the EiselLemire function's comments.\n  EXPECT_TRUE(absl::SimpleAtod(\"4503599627370497.5\", &d));\n  EXPECT_EQ(d, 4503599627370497.5);\n  EXPECT_TRUE(absl::SimpleAtod(\"1e+23\", &d));\n  EXPECT_EQ(d, 1e+23);\n  EXPECT_TRUE(absl::SimpleAtod(\"9223372036854775807\", &d));\n  EXPECT_EQ(d, 9223372036854775807);\n  // Ditto, but for Atof instead of Atod.\n  EXPECT_TRUE(absl::SimpleAtof(\"0.0625\", &f));\n  EXPECT_EQ(f, 0.0625f);\n  EXPECT_TRUE(absl::SimpleAtof(\"20040229.0\", &f));\n  EXPECT_EQ(f, 20040229.0f);\n  EXPECT_TRUE(absl::SimpleAtof(\"2147483647.0\", &f));\n  EXPECT_EQ(f, 2147483647.0f);\n\n  // Some parsing algorithms don't always round correctly (but absl::SimpleAtod\n  // should). This test case comes from\n  // https://github.com/serde-rs/json/issues/707\n  //\n  // See also atod_manual_test.cc for running many more test cases.\n  EXPECT_TRUE(absl::SimpleAtod(\"122.416294033786585\", &d));\n  EXPECT_EQ(d, 122.416294033786585);\n  EXPECT_TRUE(absl::SimpleAtof(\"122.416294033786585\", &f));\n  EXPECT_EQ(f, 122.416294033786585f);\n}\n\nTEST(NumbersTest, Prefixes) {\n  double d;\n  EXPECT_FALSE(absl::SimpleAtod(\"++1\", &d));\n  EXPECT_FALSE(absl::SimpleAtod(\"+-1\", &d));\n  EXPECT_FALSE(absl::SimpleAtod(\"-+1\", &d));\n  EXPECT_FALSE(absl::SimpleAtod(\"--1\", &d));\n  EXPECT_TRUE(absl::SimpleAtod(\"-1\", &d));\n  EXPECT_EQ(d, -1.);\n  EXPECT_TRUE(absl::SimpleAtod(\"+1\", &d));\n  EXPECT_EQ(d, +1.);\n\n  float f;\n  EXPECT_FALSE(absl::SimpleAtof(\"++1\", &f));\n  EXPECT_FALSE(absl::SimpleAtof(\"+-1\", &f));\n  EXPECT_FALSE(absl::SimpleAtof(\"-+1\", &f));\n  EXPECT_FALSE(absl::SimpleAtof(\"--1\", &f));\n  EXPECT_TRUE(absl::SimpleAtof(\"-1\", &f));\n  EXPECT_EQ(f, -1.f);\n  EXPECT_TRUE(absl::SimpleAtof(\"+1\", &f));\n  EXPECT_EQ(f, +1.f);\n}\n\nTEST(NumbersTest, Atoenum) {\n  enum E01 {\n    E01_zero = 0,\n    E01_one = 1,\n  };\n\n  VerifySimpleAtoiGood<E01>(E01_zero, E01_zero);\n  VerifySimpleAtoiGood<E01>(E01_one, E01_one);\n\n  enum E_101 {\n    E_101_minusone = -1,\n    E_101_zero = 0,\n    E_101_one = 1,\n  };\n\n  VerifySimpleAtoiGood<E_101>(E_101_minusone, E_101_minusone);\n  VerifySimpleAtoiGood<E_101>(E_101_zero, E_101_zero);\n  VerifySimpleAtoiGood<E_101>(E_101_one, E_101_one);\n\n  enum E_bigint {\n    E_bigint_zero = 0,\n    E_bigint_one = 1,\n    E_bigint_max31 = static_cast<int32_t>(0x7FFFFFFF),\n  };\n\n  VerifySimpleAtoiGood<E_bigint>(E_bigint_zero, E_bigint_zero);\n  VerifySimpleAtoiGood<E_bigint>(E_bigint_one, E_bigint_one);\n  VerifySimpleAtoiGood<E_bigint>(E_bigint_max31, E_bigint_max31);\n\n  enum E_fullint {\n    E_fullint_zero = 0,\n    E_fullint_one = 1,\n    E_fullint_max31 = static_cast<int32_t>(0x7FFFFFFF),\n    E_fullint_min32 = INT32_MIN,\n  };\n\n  VerifySimpleAtoiGood<E_fullint>(E_fullint_zero, E_fullint_zero);\n  VerifySimpleAtoiGood<E_fullint>(E_fullint_one, E_fullint_one);\n  VerifySimpleAtoiGood<E_fullint>(E_fullint_max31, E_fullint_max31);\n  VerifySimpleAtoiGood<E_fullint>(E_fullint_min32, E_fullint_min32);\n\n  enum E_biguint {\n    E_biguint_zero = 0,\n    E_biguint_one = 1,\n    E_biguint_max31 = static_cast<uint32_t>(0x7FFFFFFF),\n    E_biguint_max32 = static_cast<uint32_t>(0xFFFFFFFF),\n  };\n\n  VerifySimpleAtoiGood<E_biguint>(E_biguint_zero, E_biguint_zero);\n  VerifySimpleAtoiGood<E_biguint>(E_biguint_one, E_biguint_one);\n  VerifySimpleAtoiGood<E_biguint>(E_biguint_max31, E_biguint_max31);\n  VerifySimpleAtoiGood<E_biguint>(E_biguint_max32, E_biguint_max32);\n}\n\ntemplate <typename int_type, typename in_val_type>\nvoid VerifySimpleHexAtoiGood(in_val_type in_value, int_type exp_value) {\n  std::string s;\n  absl::strings_internal::OStringStream strm(&s);\n  if (in_value >= 0) {\n    if constexpr (std::is_arithmetic<in_val_type>::value) {\n      absl::StrAppend(&s, absl::Hex(in_value));\n    } else {\n      // absl::Hex doesn't work with absl::(u)int128.\n      strm << std::hex << in_value;\n    }\n  } else {\n    // Inefficient for small integers, but works with all integral types.\n    strm << \"-\" << std::hex << -absl::uint128(in_value);\n  }\n  int_type x = static_cast<int_type>(~exp_value);\n  EXPECT_TRUE(SimpleHexAtoi(s, &x))\n      << \"in_value=\" << std::hex << in_value << \" s=\" << s << \" x=\" << x;\n  EXPECT_EQ(exp_value, x);\n  x = static_cast<int_type>(~exp_value);\n  EXPECT_TRUE(SimpleHexAtoi(\n      s.c_str(), &x));  // NOLINT: readability-redundant-string-conversions\n  EXPECT_EQ(exp_value, x);\n}\n\ntemplate <typename int_type, typename in_val_type>\nvoid VerifySimpleHexAtoiBad(in_val_type in_value) {\n  std::string s;\n  absl::strings_internal::OStringStream strm(&s);\n  if (in_value >= 0) {\n    if constexpr (std::is_arithmetic<in_val_type>::value) {\n      absl::StrAppend(&s, absl::Hex(in_value));\n    } else {\n      // absl::Hex doesn't work with absl::(u)int128.\n      strm << std::hex << in_value;\n    }\n  } else {\n    // Inefficient for small integers, but works with all integral types.\n    strm << \"-\" << std::hex << -absl::uint128(in_value);\n  }\n  int_type x;\n  EXPECT_FALSE(SimpleHexAtoi(s, &x));\n  EXPECT_FALSE(SimpleHexAtoi(\n      s.c_str(), &x));  // NOLINT: readability-redundant-string-conversions\n}\n\nTEST(NumbersTest, HexAtoi) {\n  // SimpleHexAtoi(absl::string_view, int8_t)\n  VerifySimpleHexAtoiGood<int8_t>(0, 0);\n  VerifySimpleHexAtoiGood<int8_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<int8_t>(-0x42, -0x42);\n\n  VerifySimpleHexAtoiGood<int8_t>(std::numeric_limits<int8_t>::min(),\n                                  std::numeric_limits<int8_t>::min());\n  VerifySimpleHexAtoiGood<int8_t>(std::numeric_limits<int8_t>::max(),\n                                  std::numeric_limits<int8_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, uint8_t)\n  VerifySimpleHexAtoiGood<uint8_t>(0, 0);\n  VerifySimpleHexAtoiGood<uint8_t>(0x42, 0x42);\n  VerifySimpleHexAtoiBad<uint8_t>(-0x42);\n\n  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<int8_t>::min());\n  VerifySimpleHexAtoiGood<uint8_t>(std::numeric_limits<int8_t>::max(),\n                                   std::numeric_limits<int8_t>::max());\n  VerifySimpleHexAtoiGood<uint8_t>(std::numeric_limits<uint8_t>::max(),\n                                   std::numeric_limits<uint8_t>::max());\n  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<int16_t>::min());\n  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<int16_t>::max());\n  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<uint16_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, int16_t)\n  VerifySimpleHexAtoiGood<int16_t>(0, 0);\n  VerifySimpleHexAtoiGood<int16_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<int16_t>(-0x42, -0x42);\n\n  VerifySimpleHexAtoiGood<int16_t>(std::numeric_limits<int16_t>::min(),\n                                   std::numeric_limits<int16_t>::min());\n  VerifySimpleHexAtoiGood<int16_t>(std::numeric_limits<int16_t>::max(),\n                                   std::numeric_limits<int16_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, uint16_t)\n  VerifySimpleHexAtoiGood<uint16_t>(0, 0);\n  VerifySimpleHexAtoiGood<uint16_t>(0x42, 0x42);\n  VerifySimpleHexAtoiBad<uint16_t>(-0x42);\n\n  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<int16_t>::min());\n  VerifySimpleHexAtoiGood<uint16_t>(std::numeric_limits<int16_t>::max(),\n                                    std::numeric_limits<int16_t>::max());\n  VerifySimpleHexAtoiGood<uint16_t>(std::numeric_limits<uint16_t>::max(),\n                                    std::numeric_limits<uint16_t>::max());\n  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<int32_t>::min());\n  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<int32_t>::max());\n  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<uint32_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, int32_t)\n  VerifySimpleHexAtoiGood<int32_t>(0, 0);\n  VerifySimpleHexAtoiGood<int32_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);\n\n  VerifySimpleHexAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(),\n                                   std::numeric_limits<int32_t>::min());\n  VerifySimpleHexAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(),\n                                   std::numeric_limits<int32_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, uint32_t)\n  VerifySimpleHexAtoiGood<uint32_t>(0, 0);\n  VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);\n  VerifySimpleHexAtoiBad<uint32_t>(-0x42);\n\n  VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min());\n  VerifySimpleHexAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(),\n                                    std::numeric_limits<int32_t>::max());\n  VerifySimpleHexAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(),\n                                    std::numeric_limits<uint32_t>::max());\n  VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min());\n  VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max());\n  VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, int64_t)\n  VerifySimpleHexAtoiGood<int64_t>(0, 0);\n  VerifySimpleHexAtoiGood<int64_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<int64_t>(-0x42, -0x42);\n\n  VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(),\n                                   std::numeric_limits<int32_t>::min());\n  VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(),\n                                   std::numeric_limits<int32_t>::max());\n  VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(),\n                                   std::numeric_limits<uint32_t>::max());\n  VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(),\n                                   std::numeric_limits<int64_t>::min());\n  VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(),\n                                   std::numeric_limits<int64_t>::max());\n  VerifySimpleHexAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, uint64_t)\n  VerifySimpleHexAtoiGood<uint64_t>(0, 0);\n  VerifySimpleHexAtoiGood<uint64_t>(0x42, 0x42);\n  VerifySimpleHexAtoiBad<uint64_t>(-0x42);\n\n  VerifySimpleHexAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min());\n  VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(),\n                                    std::numeric_limits<int32_t>::max());\n  VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(),\n                                    std::numeric_limits<uint32_t>::max());\n  VerifySimpleHexAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min());\n  VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(),\n                                    std::numeric_limits<int64_t>::max());\n  VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),\n                                    std::numeric_limits<uint64_t>::max());\n\n  // SimpleHexAtoi(absl::string_view, absl::uint128)\n  VerifySimpleHexAtoiGood<absl::uint128>(0, 0);\n  VerifySimpleHexAtoiGood<absl::uint128>(0x42, 0x42);\n  VerifySimpleHexAtoiBad<absl::uint128>(-0x42);\n\n  VerifySimpleHexAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());\n  VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),\n                                         std::numeric_limits<int32_t>::max());\n  VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),\n                                         std::numeric_limits<uint32_t>::max());\n  VerifySimpleHexAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());\n  VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),\n                                         std::numeric_limits<int64_t>::max());\n  VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),\n                                         std::numeric_limits<uint64_t>::max());\n  VerifySimpleHexAtoiGood<absl::uint128>(\n      std::numeric_limits<absl::uint128>::max(),\n      std::numeric_limits<absl::uint128>::max());\n\n  // Some other types\n  VerifySimpleHexAtoiGood<short>(-0x42, -0x42);  // NOLINT: runtime-int\n  VerifySimpleHexAtoiGood<int>(-0x42, -0x42);\n  VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);\n  VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<unsigned int>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<int64_t>(-0x42, -0x42);\n  VerifySimpleHexAtoiGood<long>(-0x42, -0x42);  // NOLINT: runtime-int\n  VerifySimpleHexAtoiGood<uint64_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<size_t>(0x42, 0x42);\n  VerifySimpleHexAtoiGood<std::string::size_type>(0x42, 0x42);\n\n  // Number prefix\n  int32_t value;\n  EXPECT_TRUE(safe_strto32_base(\"0x34234324\", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"0X34234324\", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n\n  // ASCII whitespace\n  EXPECT_TRUE(safe_strto32_base(\" \\t\\n 34234324\", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"34234324 \\t\\n \", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n}\n\nTEST(stringtest, safe_strto8_base) {\n  int8_t value;\n  EXPECT_TRUE(safe_strto8_base(\"0x34\", &value, 16));\n  EXPECT_EQ(0x34, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"0X34\", &value, 16));\n  EXPECT_EQ(0x34, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"34\", &value, 16));\n  EXPECT_EQ(0x34, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"0\", &value, 16));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto8_base(\" \\t\\n -0x34\", &value, 16));\n  EXPECT_EQ(-0x34, value);\n\n  EXPECT_TRUE(safe_strto8_base(\" \\t\\n -34\", &value, 16));\n  EXPECT_EQ(-0x34, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"76\", &value, 8));\n  EXPECT_EQ(076, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"-0123\", &value, 8));\n  EXPECT_EQ(-0123, value);\n\n  EXPECT_FALSE(safe_strto8_base(\"183\", &value, 8));\n\n  // Autodetect base.\n  EXPECT_TRUE(safe_strto8_base(\"0\", &value, 0));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"077\", &value, 0));\n  EXPECT_EQ(077, value);  // Octal interpretation\n\n  // Leading zero indicates octal, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto8_base(\"088\", &value, 0));\n\n  // Leading 0x indicated hex, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto8_base(\"0xG\", &value, 0));\n\n  // Base-10 version.\n  EXPECT_TRUE(safe_strto8_base(\"124\", &value, 10));\n  EXPECT_EQ(124, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"0\", &value, 10));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto8_base(\" \\t\\n -124\", &value, 10));\n  EXPECT_EQ(-124, value);\n\n  EXPECT_TRUE(safe_strto8_base(\"124 \\n\\t \", &value, 10));\n  EXPECT_EQ(124, value);\n\n  // Invalid ints.\n  EXPECT_FALSE(safe_strto8_base(\"\", &value, 10));\n  EXPECT_FALSE(safe_strto8_base(\"  \", &value, 10));\n  EXPECT_FALSE(safe_strto8_base(\"abc\", &value, 10));\n  EXPECT_FALSE(safe_strto8_base(\"34a\", &value, 10));\n  EXPECT_FALSE(safe_strto8_base(\"34.3\", &value, 10));\n\n  // Out of bounds.\n  EXPECT_FALSE(safe_strto8_base(\"128\", &value, 10));\n  EXPECT_FALSE(safe_strto8_base(\"-129\", &value, 10));\n\n  // String version.\n  EXPECT_TRUE(safe_strto8_base(std::string(\"0x12\"), &value, 16));\n  EXPECT_EQ(0x12, value);\n\n  // Base-10 string version.\n  EXPECT_TRUE(safe_strto8_base(\"123\", &value, 10));\n  EXPECT_EQ(123, value);\n}\n\nTEST(stringtest, safe_strto16_base) {\n  int16_t value;\n  EXPECT_TRUE(safe_strto16_base(\"0x3423\", &value, 16));\n  EXPECT_EQ(0x3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"0X3423\", &value, 16));\n  EXPECT_EQ(0x3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"3423\", &value, 16));\n  EXPECT_EQ(0x3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"0\", &value, 16));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto16_base(\" \\t\\n -0x3423\", &value, 16));\n  EXPECT_EQ(-0x3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\" \\t\\n -3423\", &value, 16));\n  EXPECT_EQ(-0x3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"34567\", &value, 8));\n  EXPECT_EQ(034567, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"-01234\", &value, 8));\n  EXPECT_EQ(-01234, value);\n\n  EXPECT_FALSE(safe_strto16_base(\"1834\", &value, 8));\n\n  // Autodetect base.\n  EXPECT_TRUE(safe_strto16_base(\"0\", &value, 0));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"077\", &value, 0));\n  EXPECT_EQ(077, value);  // Octal interpretation\n\n  // Leading zero indicates octal, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto16_base(\"088\", &value, 0));\n\n  // Leading 0x indicated hex, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto16_base(\"0xG\", &value, 0));\n\n  // Base-10 version.\n  EXPECT_TRUE(safe_strto16_base(\"3423\", &value, 10));\n  EXPECT_EQ(3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"0\", &value, 10));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto16_base(\" \\t\\n -3423\", &value, 10));\n  EXPECT_EQ(-3423, value);\n\n  EXPECT_TRUE(safe_strto16_base(\"3423 \\n\\t \", &value, 10));\n  EXPECT_EQ(3423, value);\n\n  // Invalid ints.\n  EXPECT_FALSE(safe_strto16_base(\"\", &value, 10));\n  EXPECT_FALSE(safe_strto16_base(\"  \", &value, 10));\n  EXPECT_FALSE(safe_strto16_base(\"abc\", &value, 10));\n  EXPECT_FALSE(safe_strto16_base(\"324a\", &value, 10));\n  EXPECT_FALSE(safe_strto16_base(\"4234.3\", &value, 10));\n\n  // Out of bounds.\n  EXPECT_FALSE(safe_strto16_base(\"32768\", &value, 10));\n  EXPECT_FALSE(safe_strto16_base(\"-32769\", &value, 10));\n\n  // String version.\n  EXPECT_TRUE(safe_strto16_base(std::string(\"0x1234\"), &value, 16));\n  EXPECT_EQ(0x1234, value);\n\n  // Base-10 string version.\n  EXPECT_TRUE(safe_strto16_base(\"1234\", &value, 10));\n  EXPECT_EQ(1234, value);\n}\n\nTEST(stringtest, safe_strto32_base) {\n  int32_t value;\n  EXPECT_TRUE(safe_strto32_base(\"0x34234324\", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"0X34234324\", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"34234324\", &value, 16));\n  EXPECT_EQ(0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"0\", &value, 16));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto32_base(\" \\t\\n -0x34234324\", &value, 16));\n  EXPECT_EQ(-0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\" \\t\\n -34234324\", &value, 16));\n  EXPECT_EQ(-0x34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"7654321\", &value, 8));\n  EXPECT_EQ(07654321, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"-01234\", &value, 8));\n  EXPECT_EQ(-01234, value);\n\n  EXPECT_FALSE(safe_strto32_base(\"1834\", &value, 8));\n\n  // Autodetect base.\n  EXPECT_TRUE(safe_strto32_base(\"0\", &value, 0));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"077\", &value, 0));\n  EXPECT_EQ(077, value);  // Octal interpretation\n\n  // Leading zero indicates octal, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto32_base(\"088\", &value, 0));\n\n  // Leading 0x indicated hex, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto32_base(\"0xG\", &value, 0));\n\n  // Base-10 version.\n  EXPECT_TRUE(safe_strto32_base(\"34234324\", &value, 10));\n  EXPECT_EQ(34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"0\", &value, 10));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto32_base(\" \\t\\n -34234324\", &value, 10));\n  EXPECT_EQ(-34234324, value);\n\n  EXPECT_TRUE(safe_strto32_base(\"34234324 \\n\\t \", &value, 10));\n  EXPECT_EQ(34234324, value);\n\n  // Invalid ints.\n  EXPECT_FALSE(safe_strto32_base(\"\", &value, 10));\n  EXPECT_FALSE(safe_strto32_base(\"  \", &value, 10));\n  EXPECT_FALSE(safe_strto32_base(\"abc\", &value, 10));\n  EXPECT_FALSE(safe_strto32_base(\"34234324a\", &value, 10));\n  EXPECT_FALSE(safe_strto32_base(\"34234.3\", &value, 10));\n\n  // Out of bounds.\n  EXPECT_FALSE(safe_strto32_base(\"2147483648\", &value, 10));\n  EXPECT_FALSE(safe_strto32_base(\"-2147483649\", &value, 10));\n\n  // String version.\n  EXPECT_TRUE(safe_strto32_base(std::string(\"0x1234\"), &value, 16));\n  EXPECT_EQ(0x1234, value);\n\n  // Base-10 string version.\n  EXPECT_TRUE(safe_strto32_base(\"1234\", &value, 10));\n  EXPECT_EQ(1234, value);\n}\n\nTEST(stringtest, safe_strto64_base) {\n  int64_t value;\n  EXPECT_TRUE(safe_strto64_base(\"0x3423432448783446\", &value, 16));\n  EXPECT_EQ(int64_t{0x3423432448783446}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"3423432448783446\", &value, 16));\n  EXPECT_EQ(int64_t{0x3423432448783446}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"0\", &value, 16));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto64_base(\" \\t\\n -0x3423432448783446\", &value, 16));\n  EXPECT_EQ(int64_t{-0x3423432448783446}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\" \\t\\n -3423432448783446\", &value, 16));\n  EXPECT_EQ(int64_t{-0x3423432448783446}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"123456701234567012\", &value, 8));\n  EXPECT_EQ(int64_t{0123456701234567012}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"-017777777777777\", &value, 8));\n  EXPECT_EQ(int64_t{-017777777777777}, value);\n\n  EXPECT_FALSE(safe_strto64_base(\"19777777777777\", &value, 8));\n\n  // Autodetect base.\n  EXPECT_TRUE(safe_strto64_base(\"0\", &value, 0));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"077\", &value, 0));\n  EXPECT_EQ(077, value);  // Octal interpretation\n\n  // Leading zero indicates octal, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto64_base(\"088\", &value, 0));\n\n  // Leading 0x indicated hex, but then followed by invalid digit.\n  EXPECT_FALSE(safe_strto64_base(\"0xG\", &value, 0));\n\n  // Base-10 version.\n  EXPECT_TRUE(safe_strto64_base(\"34234324487834466\", &value, 10));\n  EXPECT_EQ(int64_t{34234324487834466}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"0\", &value, 10));\n  EXPECT_EQ(0, value);\n\n  EXPECT_TRUE(safe_strto64_base(\" \\t\\n -34234324487834466\", &value, 10));\n  EXPECT_EQ(int64_t{-34234324487834466}, value);\n\n  EXPECT_TRUE(safe_strto64_base(\"34234324487834466 \\n\\t \", &value, 10));\n  EXPECT_EQ(int64_t{34234324487834466}, value);\n\n  // Invalid ints.\n  EXPECT_FALSE(safe_strto64_base(\"\", &value, 10));\n  EXPECT_FALSE(safe_strto64_base(\"  \", &value, 10));\n  EXPECT_FALSE(safe_strto64_base(\"abc\", &value, 10));\n  EXPECT_FALSE(safe_strto64_base(\"34234324487834466a\", &value, 10));\n  EXPECT_FALSE(safe_strto64_base(\"34234487834466.3\", &value, 10));\n\n  // Out of bounds.\n  EXPECT_FALSE(safe_strto64_base(\"9223372036854775808\", &value, 10));\n  EXPECT_FALSE(safe_strto64_base(\"-9223372036854775809\", &value, 10));\n\n  // String version.\n  EXPECT_TRUE(safe_strto64_base(std::string(\"0x1234\"), &value, 16));\n  EXPECT_EQ(0x1234, value);\n\n  // Base-10 string version.\n  EXPECT_TRUE(safe_strto64_base(\"1234\", &value, 10));\n  EXPECT_EQ(1234, value);\n}\n\nTEST(stringtest, safe_strto8_range) {\n  // These tests verify underflow/overflow behaviour.\n  int8_t value;\n  EXPECT_FALSE(safe_strto8_base(\"128\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int8_t>::max(), value);\n\n  EXPECT_TRUE(safe_strto8_base(\"-128\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int8_t>::min(), value);\n\n  EXPECT_FALSE(safe_strto8_base(\"-129\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int8_t>::min(), value);\n}\n\nTEST(stringtest, safe_strto16_range) {\n  // These tests verify underflow/overflow behaviour.\n  int16_t value;\n  EXPECT_FALSE(safe_strto16_base(\"32768\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int16_t>::max(), value);\n\n  EXPECT_TRUE(safe_strto16_base(\"-32768\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int16_t>::min(), value);\n\n  EXPECT_FALSE(safe_strto16_base(\"-32769\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int16_t>::min(), value);\n}\n\nTEST(stringtest, safe_strto32_range) {\n  // These tests verify underflow/overflow behaviour.\n  int32_t value;\n  EXPECT_FALSE(safe_strto32_base(\"2147483648\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int32_t>::max(), value);\n\n  EXPECT_TRUE(safe_strto32_base(\"-2147483648\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);\n\n  EXPECT_FALSE(safe_strto32_base(\"-2147483649\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);\n}\n\nTEST(stringtest, safe_strto64_range) {\n  // These tests verify underflow/overflow behaviour.\n  int64_t value;\n  EXPECT_FALSE(safe_strto64_base(\"9223372036854775808\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);\n\n  EXPECT_TRUE(safe_strto64_base(\"-9223372036854775808\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);\n\n  EXPECT_FALSE(safe_strto64_base(\"-9223372036854775809\", &value, 10));\n  EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);\n}\n\nTEST(stringtest, safe_strto8_leading_substring) {\n  // These tests verify this comment in numbers.h:\n  // On error, returns false, and sets *value to: [...]\n  //   conversion of leading substring if available (\"123@@@\" -> 123)\n  //   0 if no leading substring available\n  int8_t value;\n  EXPECT_FALSE(safe_strto8_base(\"069@@@\", &value, 10));\n  EXPECT_EQ(69, value);\n\n  EXPECT_FALSE(safe_strto8_base(\"01769@@@\", &value, 8));\n  EXPECT_EQ(0176, value);\n\n  EXPECT_FALSE(safe_strto8_base(\"069balloons\", &value, 10));\n  EXPECT_EQ(69, value);\n\n  EXPECT_FALSE(safe_strto8_base(\"07bland\", &value, 16));\n  EXPECT_EQ(0x7b, value);\n\n  EXPECT_FALSE(safe_strto8_base(\"@@@\", &value, 10));\n  EXPECT_EQ(0, value);  // there was no leading substring\n}\n\nTEST(stringtest, safe_strto16_leading_substring) {\n  // These tests verify this comment in numbers.h:\n  // On error, returns false, and sets *value to: [...]\n  //   conversion of leading substring if available (\"123@@@\" -> 123)\n  //   0 if no leading substring available\n  int16_t value;\n  EXPECT_FALSE(safe_strto16_base(\"04069@@@\", &value, 10));\n  EXPECT_EQ(4069, value);\n\n  EXPECT_FALSE(safe_strto16_base(\"04069@@@\", &value, 8));\n  EXPECT_EQ(0406, value);\n\n  EXPECT_FALSE(safe_strto16_base(\"04069balloons\", &value, 10));\n  EXPECT_EQ(4069, value);\n\n  EXPECT_FALSE(safe_strto16_base(\"069balloons\", &value, 16));\n  EXPECT_EQ(0x69ba, value);\n\n  EXPECT_FALSE(safe_strto16_base(\"@@@\", &value, 10));\n  EXPECT_EQ(0, value);  // there was no leading substring\n}\n\nTEST(stringtest, safe_strto32_leading_substring) {\n  // These tests verify this comment in numbers.h:\n  // On error, returns false, and sets *value to: [...]\n  //   conversion of leading substring if available (\"123@@@\" -> 123)\n  //   0 if no leading substring available\n  int32_t value;\n  EXPECT_FALSE(safe_strto32_base(\"04069@@@\", &value, 10));\n  EXPECT_EQ(4069, value);\n\n  EXPECT_FALSE(safe_strto32_base(\"04069@@@\", &value, 8));\n  EXPECT_EQ(0406, value);\n\n  EXPECT_FALSE(safe_strto32_base(\"04069balloons\", &value, 10));\n  EXPECT_EQ(4069, value);\n\n  EXPECT_FALSE(safe_strto32_base(\"04069balloons\", &value, 16));\n  EXPECT_EQ(0x4069ba, value);\n\n  EXPECT_FALSE(safe_strto32_base(\"@@@\", &value, 10));\n  EXPECT_EQ(0, value);  // there was no leading substring\n}\n\nTEST(stringtest, safe_strto64_leading_substring) {\n  // These tests verify this comment in numbers.h:\n  // On error, returns false, and sets *value to: [...]\n  //   conversion of leading substring if available (\"123@@@\" -> 123)\n  //   0 if no leading substring available\n  int64_t value;\n  EXPECT_FALSE(safe_strto64_base(\"04069@@@\", &value, 10));\n  EXPECT_EQ(4069, value);\n\n  EXPECT_FALSE(safe_strto64_base(\"04069@@@\", &value, 8));\n  EXPECT_EQ(0406, value);\n\n  EXPECT_FALSE(safe_strto64_base(\"04069balloons\", &value, 10));\n  EXPECT_EQ(4069, value);\n\n  EXPECT_FALSE(safe_strto64_base(\"04069balloons\", &value, 16));\n  EXPECT_EQ(0x4069ba, value);\n\n  EXPECT_FALSE(safe_strto64_base(\"@@@\", &value, 10));\n  EXPECT_EQ(0, value);  // there was no leading substring\n}\n\nconst size_t kNumRandomTests = 10000;\n\ntemplate <typename IntType,\n          bool parse_func(absl::string_view, IntType* value, int base)>\nvoid test_random_integer_parse_base() {\n  absl::InsecureBitGen rng;\n  std::uniform_int_distribution<IntType> random_int(\n      std::numeric_limits<IntType>::min());\n  std::uniform_int_distribution<int> random_base(2, 36);\n  for (size_t i = 0; i < kNumRandomTests; i++) {\n    IntType value = random_int(rng);\n    int base = random_base(rng);\n    std::string str_value;\n    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));\n    IntType parsed_value;\n\n    // Test successful parse\n    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));\n    EXPECT_EQ(parsed_value, value);\n\n    // Test overflow\n    EXPECT_FALSE(\n        parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),\n                   &parsed_value, base));\n\n    // Test underflow\n    if (std::numeric_limits<IntType>::min() < 0) {\n      EXPECT_FALSE(\n          parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),\n                     &parsed_value, base));\n    } else {\n      EXPECT_FALSE(parse_func(absl::StrCat(\"-\", value), &parsed_value, base));\n    }\n  }\n}\n\nTEST(stringtest, safe_strto16_random) {\n  test_random_integer_parse_base<int16_t, safe_strto16_base>();\n}\nTEST(stringtest, safe_strto32_random) {\n  test_random_integer_parse_base<int32_t, safe_strto32_base>();\n}\nTEST(stringtest, safe_strto64_random) {\n  test_random_integer_parse_base<int64_t, safe_strto64_base>();\n}\nTEST(stringtest, safe_strtou16_random) {\n  test_random_integer_parse_base<uint16_t, safe_strtou16_base>();\n}\nTEST(stringtest, safe_strtou32_random) {\n  test_random_integer_parse_base<uint32_t, safe_strtou32_base>();\n}\nTEST(stringtest, safe_strtou64_random) {\n  test_random_integer_parse_base<uint64_t, safe_strtou64_base>();\n}\nTEST(stringtest, safe_strtou128_random) {\n  // random number generators don't work for uint128 so this code must be custom\n  // implemented for uint128, but is generally the same as what's above.\n  // test_random_integer_parse_base<absl::uint128>(\n  //     &absl::numbers_internal::safe_strtou128_base);\n  using IntType = absl::uint128;\n  constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;\n\n  absl::InsecureBitGen rng;\n  std::uniform_int_distribution<uint64_t> random_uint64(\n      std::numeric_limits<uint64_t>::min());\n  std::uniform_int_distribution<int> random_base(2, 36);\n\n  for (size_t i = 0; i < kNumRandomTests; i++) {\n    IntType value = random_uint64(rng);\n    value = (value << 64) + random_uint64(rng);\n    int base = random_base(rng);\n    std::string str_value;\n    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));\n    IntType parsed_value;\n\n    // Test successful parse\n    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));\n    EXPECT_EQ(parsed_value, value);\n\n    // Test overflow\n    EXPECT_FALSE(\n        parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),\n                   &parsed_value, base));\n\n    // Test underflow\n    EXPECT_FALSE(parse_func(absl::StrCat(\"-\", value), &parsed_value, base));\n  }\n}\nTEST(stringtest, safe_strto128_random) {\n  // random number generators don't work for int128 so this code must be custom\n  // implemented for int128, but is generally the same as what's above.\n  // test_random_integer_parse_base<absl::int128>(\n  //     &absl::numbers_internal::safe_strto128_base);\n  using IntType = absl::int128;\n  constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;\n\n  absl::InsecureBitGen rng;\n  std::uniform_int_distribution<int64_t> random_int64(\n      std::numeric_limits<int64_t>::min());\n  std::uniform_int_distribution<uint64_t> random_uint64(\n      std::numeric_limits<uint64_t>::min());\n  std::uniform_int_distribution<int> random_base(2, 36);\n\n  for (size_t i = 0; i < kNumRandomTests; ++i) {\n    int64_t high = random_int64(rng);\n    uint64_t low = random_uint64(rng);\n    IntType value = absl::MakeInt128(high, low);\n\n    int base = random_base(rng);\n    std::string str_value;\n    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));\n    IntType parsed_value;\n\n    // Test successful parse\n    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));\n    EXPECT_EQ(parsed_value, value);\n\n    // Test overflow\n    EXPECT_FALSE(\n        parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),\n                   &parsed_value, base));\n\n    // Test underflow\n    EXPECT_FALSE(\n        parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),\n                   &parsed_value, base));\n  }\n}\n\nTEST(stringtest, safe_strtou8_exhaustive) {\n  // Testing the entire space for uint8_t since it is small.\n  using IntType = uint8_t;\n  constexpr auto parse_func = &absl::numbers_internal::safe_strtou8_base;\n\n  for (int i = std::numeric_limits<IntType>::min();\n       i <= std::numeric_limits<IntType>::max(); i++) {\n    IntType value = static_cast<IntType>(i);\n    for (int base = 2; base <= 36; base++) {\n      std::string str_value;\n      EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));\n      IntType parsed_value;\n\n      // Test successful parse\n      EXPECT_TRUE(parse_func(str_value, &parsed_value, base));\n      EXPECT_EQ(parsed_value, value);\n\n      // Test overflow\n      EXPECT_FALSE(\n          parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),\n                     &parsed_value, base));\n      // Test underflow\n      EXPECT_FALSE(parse_func(absl::StrCat(\"-\", value), &parsed_value, base));\n    }\n  }\n}\n\nTEST(stringtest, safe_strto8_exhaustive) {\n  // Testing the entire space for int8_t since it is small.\n  using IntType = int8_t;\n  constexpr auto parse_func = &absl::numbers_internal::safe_strto8_base;\n\n  for (int i = std::numeric_limits<IntType>::min();\n       i <= std::numeric_limits<IntType>::max(); i++) {\n    IntType value = static_cast<IntType>(i);\n    for (int base = 2; base <= 36; base++) {\n      std::string str_value;\n      EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));\n      IntType parsed_value;\n\n      // Test successful parse\n      EXPECT_TRUE(parse_func(str_value, &parsed_value, base));\n      EXPECT_EQ(parsed_value, value);\n\n      // Test overflow\n      EXPECT_FALSE(\n          parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),\n                     &parsed_value, base));\n      // Test underflow\n      EXPECT_FALSE(\n          parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),\n                     &parsed_value, base));\n    }\n  }\n}\n\nTEST(stringtest, safe_strtou32_base) {\n  for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {\n    const auto& e = strtouint32_test_cases()[i];\n    uint32_t value;\n    EXPECT_EQ(e.expect_ok, safe_strtou32_base(e.str, &value, e.base))\n        << \"str=\\\"\" << e.str << \"\\\" base=\" << e.base;\n    if (e.expect_ok) {\n      EXPECT_EQ(e.expected, value) << \"i=\" << i << \" str=\\\"\" << e.str\n                                   << \"\\\" base=\" << e.base;\n    }\n  }\n}\n\nTEST(stringtest, safe_strtou32_base_length_delimited) {\n  for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {\n    const auto& e = strtouint32_test_cases()[i];\n    std::string tmp(e.str);\n    tmp.append(\"12\");  // Adds garbage at the end.\n\n    uint32_t value;\n    EXPECT_EQ(e.expect_ok,\n              safe_strtou32_base(absl::string_view(tmp.data(), strlen(e.str)),\n                                 &value, e.base))\n        << \"str=\\\"\" << e.str << \"\\\" base=\" << e.base;\n    if (e.expect_ok) {\n      EXPECT_EQ(e.expected, value) << \"i=\" << i << \" str=\" << e.str\n                                   << \" base=\" << e.base;\n    }\n  }\n}\n\nTEST(stringtest, safe_strtou64_base) {\n  for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {\n    const auto& e = strtouint64_test_cases()[i];\n    uint64_t value;\n    EXPECT_EQ(e.expect_ok, safe_strtou64_base(e.str, &value, e.base))\n        << \"str=\\\"\" << e.str << \"\\\" base=\" << e.base;\n    if (e.expect_ok) {\n      EXPECT_EQ(e.expected, value) << \"str=\" << e.str << \" base=\" << e.base;\n    }\n  }\n}\n\nTEST(stringtest, safe_strtou64_base_length_delimited) {\n  for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {\n    const auto& e = strtouint64_test_cases()[i];\n    std::string tmp(e.str);\n    tmp.append(\"12\");  // Adds garbage at the end.\n\n    uint64_t value;\n    EXPECT_EQ(e.expect_ok,\n              safe_strtou64_base(absl::string_view(tmp.data(), strlen(e.str)),\n                                 &value, e.base))\n        << \"str=\\\"\" << e.str << \"\\\" base=\" << e.base;\n    if (e.expect_ok) {\n      EXPECT_EQ(e.expected, value) << \"str=\\\"\" << e.str << \"\\\" base=\" << e.base;\n    }\n  }\n}\n\n// feenableexcept() and fedisableexcept() are extensions supported by some libc\n// implementations.\n#if defined(__GLIBC__) || defined(__BIONIC__)\n#define ABSL_HAVE_FEENABLEEXCEPT 1\n#define ABSL_HAVE_FEDISABLEEXCEPT 1\n#endif\n\nclass SimpleDtoaTest : public testing::Test {\n protected:\n  void SetUp() override {\n    // Store the current floating point env & clear away any pending exceptions.\n    feholdexcept(&fp_env_);\n#ifdef ABSL_HAVE_FEENABLEEXCEPT\n    // Turn on floating point exceptions.\n    feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);\n#endif\n  }\n\n  void TearDown() override {\n    // Restore the floating point environment to the original state.\n    // In theory fedisableexcept is unnecessary; fesetenv will also do it.\n    // In practice, our toolchains have subtle bugs.\n#ifdef ABSL_HAVE_FEDISABLEEXCEPT\n    fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);\n#endif\n    fesetenv(&fp_env_);\n  }\n\n  std::string ToNineDigits(double value) {\n    char buffer[16];  // more than enough for %.9g\n    snprintf(buffer, sizeof(buffer), \"%.9g\", value);\n    return buffer;\n  }\n\n  fenv_t fp_env_;\n};\n\n// Run the given runnable functor for \"cases\" test cases, chosen over the\n// available range of float.  pi and e and 1/e are seeded, and then all\n// available integer powers of 2 and 10 are multiplied against them.  In\n// addition to trying all those values, we try the next higher and next lower\n// float, and then we add additional test cases evenly distributed between them.\n// Each test case is passed to runnable as both a positive and negative value.\ntemplate <typename R>\nvoid ExhaustiveFloat(uint32_t cases, R&& runnable) {\n  runnable(0.0f);\n  runnable(-0.0f);\n  if (cases >= 2e9) {  // more than 2 billion?  Might as well run them all.\n    for (float f = 0; f < std::numeric_limits<float>::max(); ) {\n      f = nextafterf(f, std::numeric_limits<float>::max());\n      runnable(-f);\n      runnable(f);\n    }\n    return;\n  }\n  std::set<float> floats = {3.4028234e38f};\n  for (float f : {1.0, 3.14159265, 2.718281828, 1 / 2.718281828}) {\n    for (float testf = f; testf != 0; testf *= 0.1f) floats.insert(testf);\n    for (float testf = f; testf != 0; testf *= 0.5f) floats.insert(testf);\n    for (float testf = f; testf < 3e38f / 2; testf *= 2.0f)\n      floats.insert(testf);\n    for (float testf = f; testf < 3e38f / 10; testf *= 10) floats.insert(testf);\n  }\n\n  float last = *floats.begin();\n\n  runnable(last);\n  runnable(-last);\n  int iters_per_float = cases / floats.size();\n  if (iters_per_float == 0) iters_per_float = 1;\n  for (float f : floats) {\n    if (f == last) continue;\n    float testf = std::nextafter(last, std::numeric_limits<float>::max());\n    runnable(testf);\n    runnable(-testf);\n    last = testf;\n    if (f == last) continue;\n    double step = (double{f} - last) / iters_per_float;\n    for (double d = last + step; d < f; d += step) {\n      testf = d;\n      if (testf != last) {\n        runnable(testf);\n        runnable(-testf);\n        last = testf;\n      }\n    }\n    testf = std::nextafter(f, 0.0f);\n    if (testf > last) {\n      runnable(testf);\n      runnable(-testf);\n      last = testf;\n    }\n    if (f != last) {\n      runnable(f);\n      runnable(-f);\n      last = f;\n    }\n  }\n}\n\nTEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) {\n  uint64_t test_count = 0;\n  std::vector<double> mismatches;\n  auto checker = [&](double d) {\n    if (d != d) return;  // rule out NaNs\n    ++test_count;\n    char sixdigitsbuf[kSixDigitsToBufferSize] = {0};\n    SixDigitsToBuffer(d, sixdigitsbuf);\n    char snprintfbuf[kSixDigitsToBufferSize] = {0};\n    snprintf(snprintfbuf, kSixDigitsToBufferSize, \"%g\", d);\n    if (strcmp(sixdigitsbuf, snprintfbuf) != 0) {\n      mismatches.push_back(d);\n      if (mismatches.size() < 10) {\n        LOG(ERROR) << \"Six-digit failure with double.  d=\" << d\n                   << \" sixdigits=\" << sixdigitsbuf\n                   << \" printf(%g)=\" << snprintfbuf;\n      }\n    }\n  };\n  // Some quick sanity checks...\n  checker(5e-324);\n  checker(1e-308);\n  checker(1.0);\n  checker(1.000005);\n  checker(1.7976931348623157e308);\n  checker(0.00390625);\n#ifndef _MSC_VER\n  // on MSVC, snprintf() rounds it to 0.00195313. SixDigitsToBuffer() rounds it\n  // to 0.00195312 (round half to even).\n  checker(0.001953125);\n#endif\n  checker(0.005859375);\n  // Some cases where the rounding is very very close\n  checker(1.089095e-15);\n  checker(3.274195e-55);\n  checker(6.534355e-146);\n  checker(2.920845e+234);\n\n  if (mismatches.empty()) {\n    test_count = 0;\n    ExhaustiveFloat(kFloatNumCases, checker);\n\n    test_count = 0;\n    std::vector<int> digit_testcases{\n        100000, 100001, 100002, 100005, 100010, 100020, 100050, 100100,  // misc\n        195312, 195313,  // 1.953125 is a case where we round down, just barely.\n        200000, 500000, 800000,  // misc mid-range cases\n        585937, 585938,  // 5.859375 is a case where we round up, just barely.\n        900000, 990000, 999000, 999900, 999990, 999996, 999997, 999998, 999999};\n    if (kFloatNumCases >= 1e9) {\n      // If at least 1 billion test cases were requested, user wants an\n      // exhaustive test. So let's test all mantissas, too.\n      constexpr int min_mantissa = 100000, max_mantissa = 999999;\n      digit_testcases.resize(max_mantissa - min_mantissa + 1);\n      std::iota(digit_testcases.begin(), digit_testcases.end(), min_mantissa);\n    }\n\n    for (int exponent = -324; exponent <= 308; ++exponent) {\n      double powten = absl::strings_internal::Pow10(exponent);\n      if (powten == 0) powten = 5e-324;\n      if (kFloatNumCases >= 1e9) {\n        // The exhaustive test takes a very long time, so log progress.\n        char buf[kSixDigitsToBufferSize];\n        LOG(INFO) << \"Exp \" << exponent << \" powten=\" << powten << \"(\" << powten\n                  << \") (\"\n                  << absl::string_view(buf, SixDigitsToBuffer(powten, buf))\n                  << \")\";\n      }\n      for (int digits : digit_testcases) {\n        if (exponent == 308 && digits >= 179769) break;  // don't overflow!\n        double digiform = (digits + 0.5) * 0.00001;\n        double testval = digiform * powten;\n        double pretestval = nextafter(testval, 0);\n        double posttestval = nextafter(testval, 1.7976931348623157e308);\n        checker(testval);\n        checker(pretestval);\n        checker(posttestval);\n      }\n    }\n  } else {\n    EXPECT_EQ(mismatches.size(), 0);\n    for (size_t i = 0; i < mismatches.size(); ++i) {\n      if (i > 100) i = mismatches.size() - 1;\n      double d = mismatches[i];\n      char sixdigitsbuf[kSixDigitsToBufferSize] = {0};\n      SixDigitsToBuffer(d, sixdigitsbuf);\n      char snprintfbuf[kSixDigitsToBufferSize] = {0};\n      snprintf(snprintfbuf, kSixDigitsToBufferSize, \"%g\", d);\n      double before = nextafter(d, 0.0);\n      double after = nextafter(d, 1.7976931348623157e308);\n      char b1[32], b2[kSixDigitsToBufferSize];\n      LOG(ERROR) << \"Mismatch #\" << i << \"  d=\" << d << \" (\" << ToNineDigits(d)\n                 << \") sixdigits='\" << sixdigitsbuf << \"' snprintf='\"\n                 << snprintfbuf << \"' Before.=\" << PerfectDtoa(before) << \" \"\n                 << (SixDigitsToBuffer(before, b2), b2) << \" vs snprintf=\"\n                 << (snprintf(b1, sizeof(b1), \"%g\", before), b1)\n                 << \" Perfect=\" << PerfectDtoa(d) << \" \"\n                 << (SixDigitsToBuffer(d, b2), b2)\n                 << \" vs snprintf=\" << (snprintf(b1, sizeof(b1), \"%g\", d), b1)\n                 << \" After.=.\" << PerfectDtoa(after) << \" \"\n                 << (SixDigitsToBuffer(after, b2), b2) << \" vs snprintf=\"\n                 << (snprintf(b1, sizeof(b1), \"%g\", after), b1);\n    }\n  }\n}\n\nTEST(StrToInt8, Partial) {\n  struct Int8TestLine {\n    std::string input;\n    bool status;\n    int8_t value;\n  };\n  const int8_t int8_min = std::numeric_limits<int8_t>::min();\n  const int8_t int8_max = std::numeric_limits<int8_t>::max();\n  Int8TestLine int8_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(int8_min, int8_max), false, int8_min},\n      {absl::StrCat(int8_max, int8_max), false, int8_max},\n  };\n\n  for (const Int8TestLine& test_line : int8_test_line) {\n    int8_t value = -2;\n    bool status = safe_strto8_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto8_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto8_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToUint8, Partial) {\n  struct Uint8TestLine {\n    std::string input;\n    bool status;\n    uint8_t value;\n  };\n  const uint8_t uint8_max = std::numeric_limits<uint8_t>::max();\n  Uint8TestLine uint8_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(uint8_max, uint8_max), false, uint8_max},\n  };\n\n  for (const Uint8TestLine& test_line : uint8_test_line) {\n    uint8_t value = 2;\n    bool status = safe_strtou8_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou8_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou8_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToInt16, Partial) {\n  struct Int16TestLine {\n    std::string input;\n    bool status;\n    int16_t value;\n  };\n  const int16_t int16_min = std::numeric_limits<int16_t>::min();\n  const int16_t int16_max = std::numeric_limits<int16_t>::max();\n  Int16TestLine int16_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(int16_min, int16_max), false, int16_min},\n      {absl::StrCat(int16_max, int16_max), false, int16_max},\n  };\n\n  for (const Int16TestLine& test_line : int16_test_line) {\n    int16_t value = -2;\n    bool status = safe_strto16_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto16_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto16_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToUint16, Partial) {\n  struct Uint16TestLine {\n    std::string input;\n    bool status;\n    uint16_t value;\n  };\n  const uint16_t uint16_max = std::numeric_limits<uint16_t>::max();\n  Uint16TestLine uint16_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(uint16_max, uint16_max), false, uint16_max},\n  };\n\n  for (const Uint16TestLine& test_line : uint16_test_line) {\n    uint16_t value = 2;\n    bool status = safe_strtou16_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou16_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou16_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToInt32, Partial) {\n  struct Int32TestLine {\n    std::string input;\n    bool status;\n    int32_t value;\n  };\n  const int32_t int32_min = std::numeric_limits<int32_t>::min();\n  const int32_t int32_max = std::numeric_limits<int32_t>::max();\n  Int32TestLine int32_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(int32_min, int32_max), false, int32_min},\n      {absl::StrCat(int32_max, int32_max), false, int32_max},\n  };\n\n  for (const Int32TestLine& test_line : int32_test_line) {\n    int32_t value = -2;\n    bool status = safe_strto32_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto32_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto32_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToUint32, Partial) {\n  struct Uint32TestLine {\n    std::string input;\n    bool status;\n    uint32_t value;\n  };\n  const uint32_t uint32_max = std::numeric_limits<uint32_t>::max();\n  Uint32TestLine uint32_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(uint32_max, uint32_max), false, uint32_max},\n  };\n\n  for (const Uint32TestLine& test_line : uint32_test_line) {\n    uint32_t value = 2;\n    bool status = safe_strtou32_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou32_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou32_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToInt64, Partial) {\n  struct Int64TestLine {\n    std::string input;\n    bool status;\n    int64_t value;\n  };\n  const int64_t int64_min = std::numeric_limits<int64_t>::min();\n  const int64_t int64_max = std::numeric_limits<int64_t>::max();\n  Int64TestLine int64_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(int64_min, int64_max), false, int64_min},\n      {absl::StrCat(int64_max, int64_max), false, int64_max},\n  };\n\n  for (const Int64TestLine& test_line : int64_test_line) {\n    int64_t value = -2;\n    bool status = safe_strto64_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto64_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = -2;\n    status = safe_strto64_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToUint64, Partial) {\n  struct Uint64TestLine {\n    std::string input;\n    bool status;\n    uint64_t value;\n  };\n  const uint64_t uint64_max = std::numeric_limits<uint64_t>::max();\n  Uint64TestLine uint64_test_line[] = {\n      {\"\", false, 0},\n      {\" \", false, 0},\n      {\"-\", false, 0},\n      {\"123@@@\", false, 123},\n      {absl::StrCat(uint64_max, uint64_max), false, uint64_max},\n  };\n\n  for (const Uint64TestLine& test_line : uint64_test_line) {\n    uint64_t value = 2;\n    bool status = safe_strtou64_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou64_base(test_line.input, &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n    value = 2;\n    status = safe_strtou64_base(absl::string_view(test_line.input), &value, 10);\n    EXPECT_EQ(test_line.status, status) << test_line.input;\n    EXPECT_EQ(test_line.value, value) << test_line.input;\n  }\n}\n\nTEST(StrToInt32Base, PrefixOnly) {\n  struct Int32TestLine {\n    std::string input;\n    bool status;\n    int32_t value;\n  };\n  Int32TestLine int32_test_line[] = {\n    { \"\", false, 0 },\n    { \"-\", false, 0 },\n    { \"-0\", true, 0 },\n    { \"0\", true, 0 },\n    { \"0x\", false, 0 },\n    { \"-0x\", false, 0 },\n  };\n  const int base_array[] = { 0, 2, 8, 10, 16 };\n\n  for (const Int32TestLine& line : int32_test_line) {\n    for (const int base : base_array) {\n      int32_t value = 2;\n      bool status = safe_strto32_base(line.input.c_str(), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strto32_base(line.input, &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strto32_base(absl::string_view(line.input), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n    }\n  }\n}\n\nTEST(StrToUint32Base, PrefixOnly) {\n  struct Uint32TestLine {\n    std::string input;\n    bool status;\n    uint32_t value;\n  };\n  Uint32TestLine uint32_test_line[] = {\n    { \"\", false, 0 },\n    { \"0\", true, 0 },\n    { \"0x\", false, 0 },\n  };\n  const int base_array[] = { 0, 2, 8, 10, 16 };\n\n  for (const Uint32TestLine& line : uint32_test_line) {\n    for (const int base : base_array) {\n      uint32_t value = 2;\n      bool status = safe_strtou32_base(line.input.c_str(), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strtou32_base(line.input, &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strtou32_base(absl::string_view(line.input), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n    }\n  }\n}\n\nTEST(StrToInt64Base, PrefixOnly) {\n  struct Int64TestLine {\n    std::string input;\n    bool status;\n    int64_t value;\n  };\n  Int64TestLine int64_test_line[] = {\n    { \"\", false, 0 },\n    { \"-\", false, 0 },\n    { \"-0\", true, 0 },\n    { \"0\", true, 0 },\n    { \"0x\", false, 0 },\n    { \"-0x\", false, 0 },\n  };\n  const int base_array[] = { 0, 2, 8, 10, 16 };\n\n  for (const Int64TestLine& line : int64_test_line) {\n    for (const int base : base_array) {\n      int64_t value = 2;\n      bool status = safe_strto64_base(line.input.c_str(), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strto64_base(line.input, &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strto64_base(absl::string_view(line.input), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n    }\n  }\n}\n\nTEST(StrToUint64Base, PrefixOnly) {\n  struct Uint64TestLine {\n    std::string input;\n    bool status;\n    uint64_t value;\n  };\n  Uint64TestLine uint64_test_line[] = {\n    { \"\", false, 0 },\n    { \"0\", true, 0 },\n    { \"0x\", false, 0 },\n  };\n  const int base_array[] = { 0, 2, 8, 10, 16 };\n\n  for (const Uint64TestLine& line : uint64_test_line) {\n    for (const int base : base_array) {\n      uint64_t value = 2;\n      bool status = safe_strtou64_base(line.input.c_str(), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strtou64_base(line.input, &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n      value = 2;\n      status = safe_strtou64_base(absl::string_view(line.input), &value, base);\n      EXPECT_EQ(line.status, status) << line.input << \" \" << base;\n      EXPECT_EQ(line.value, value) << line.input << \" \" << base;\n    }\n  }\n}\n\nvoid TestFastHexToBufferZeroPad16(uint64_t v) {\n  char buf[16];\n  auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(v, buf);\n  absl::string_view res(buf, 16);\n  char buf2[17];\n  snprintf(buf2, sizeof(buf2), \"%016\" PRIx64, v);\n  EXPECT_EQ(res, buf2) << v;\n  size_t expected_digits = snprintf(buf2, sizeof(buf2), \"%\" PRIx64, v);\n  EXPECT_EQ(digits, expected_digits) << v;\n}\n\nTEST(FastHexToBufferZeroPad16, Smoke) {\n  TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::min());\n  TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::max());\n  TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::min());\n  TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::max());\n  absl::BitGen rng;\n  for (int i = 0; i < 100000; ++i) {\n    TestFastHexToBufferZeroPad16(\n        absl::LogUniform(rng, std::numeric_limits<uint64_t>::min(),\n                         std::numeric_limits<uint64_t>::max()));\n  }\n}\n\ntemplate <typename Int>\nvoid ExpectWritesNull() {\n  {\n    char buf[absl::numbers_internal::kFastToBufferSize];\n    Int x = std::numeric_limits<Int>::min();\n    EXPECT_THAT(absl::numbers_internal::FastIntToBuffer(x, buf), Pointee('\\0'));\n  }\n  {\n    char buf[absl::numbers_internal::kFastToBufferSize];\n    Int x = std::numeric_limits<Int>::max();\n    EXPECT_THAT(absl::numbers_internal::FastIntToBuffer(x, buf), Pointee('\\0'));\n  }\n}\n\nTEST(FastIntToBuffer, WritesNull) {\n  ExpectWritesNull<int8_t>();\n  ExpectWritesNull<uint8_t>();\n  ExpectWritesNull<int16_t>();\n  ExpectWritesNull<uint16_t>();\n  ExpectWritesNull<int32_t>();\n  ExpectWritesNull<uint32_t>();\n  ExpectWritesNull<int64_t>();\n  ExpectWritesNull<uint32_t>();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/resize_and_overwrite.h",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: resize_and_overwrite.h\n// -----------------------------------------------------------------------------\n//\n// This file contains a polyfill for C++23's\n// std::basic_string<CharT,Traits,Allocator>::resize_and_overwrite\n//\n// The polyfill takes the form of a free function:\n\n// template<typename T, typename Op>\n// void StringResizeAndOverwrite(T& str, typename T::size_type count, Op op);\n//\n// This avoids the cost of initializing a suitably-sized std::string when it is\n// intended to be used as a char array, for example, to be populated by a\n// C-style API.\n//\n// Example usage:\n//\n// std::string IntToString(int n) {\n//   std::string result;\n//   constexpr size_t kMaxIntChars = 10;\n//   absl::StringResizeAndOverwrite(\n//       result, kMaxIntChars, [n](char* buffer, size_t buffer_size) {\n//         return snprintf(buffer, buffer_size, \"%d\", n);\n//       });\n//   return result;\n//  }\n//\n// https://en.cppreference.com/w/cpp/string/basic_string/resize_and_overwrite.html\n// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1072r10.html\n\n#ifndef ABSL_STRINGS_RESIZE_AND_OVERWRITE_H_\n#define ABSL_STRINGS_RESIZE_AND_OVERWRITE_H_\n\n#include <cstddef>\n#include <string>  // IWYU pragma: keep\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/throw_delegate.h\"\n\n#if defined(__cpp_lib_string_resize_and_overwrite) && \\\n    __cpp_lib_string_resize_and_overwrite >= 202110L\n#define ABSL_INTERNAL_HAS_RESIZE_AND_OVERWRITE 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace strings_internal {\n\n#ifndef ABSL_INTERNAL_HAS_RESIZE_AND_OVERWRITE\n\ninline size_t ProbeResizeAndOverwriteOp(char*, size_t) { return 0; }\n\n// Prior to C++23, Google's libc++ backports resize_and_overwrite as\n// __google_nonstandard_backport_resize_and_overwrite\ntemplate <typename T, typename = void>\nstruct has__google_nonstandard_backport_resize_and_overwrite : std::false_type {\n};\n\ntemplate <typename T>\nstruct has__google_nonstandard_backport_resize_and_overwrite<\n    T,\n    std::void_t<\n        decltype(std::declval<T&>()\n                     .__google_nonstandard_backport_resize_and_overwrite(\n                         std::declval<size_t>(), ProbeResizeAndOverwriteOp))>>\n    : std::true_type {};\n\n// Prior to C++23, the version of libstdc++ that shipped with GCC >= 14\n// has __resize_and_overwrite.\ntemplate <typename T, typename = void>\nstruct has__resize_and_overwrite : std::false_type {};\n\ntemplate <typename T>\nstruct has__resize_and_overwrite<\n    T, std::void_t<decltype(std::declval<T&>().__resize_and_overwrite(\n           std::declval<size_t>(), ProbeResizeAndOverwriteOp))>>\n    : std::true_type {};\n\n// libc++ used  __resize_default_init to achieve uninitialized string resizes\n// before removing it September 2025, in favor of resize_and_overwrite.\n// https://github.com/llvm/llvm-project/commit/92f5d8df361bb1bb6dea88f86faeedfd295ab970\ntemplate <typename T, typename = void>\nstruct has__resize_default_init : std::false_type {};\n\ntemplate <typename T>\nstruct has__resize_default_init<\n    T, std::void_t<decltype(std::declval<T&>().__resize_default_init(42))>>\n    : std::true_type {};\n\n// Prior to C++23, some versions of MSVC have _Resize_and_overwrite.\ntemplate <typename T, typename = void>\nstruct has_Resize_and_overwrite : std::false_type {};\n\ntemplate <typename T>\nstruct has_Resize_and_overwrite<\n    T, std::void_t<decltype(std::declval<T&>()._Resize_and_overwrite(\n           std::declval<size_t>(), ProbeResizeAndOverwriteOp))>>\n    : std::true_type {};\n\n#endif  // ifndef ABSL_INTERNAL_HAS_RESIZE_AND_OVERWRITE\n\n// A less-efficient fallback implementation that uses resize().\ntemplate <typename T, typename Op>\nvoid StringResizeAndOverwriteFallback(T& str, typename T::size_type n, Op op) {\n  if (ABSL_PREDICT_FALSE(n > str.max_size())) {\n    ThrowStdLengthError(\"absl::StringResizeAndOverwrite\");\n  }\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n  auto old_size = str.size();\n#endif\n  str.resize(n);\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\n  if (old_size < n) {\n    ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(str.data() + old_size, n - old_size);\n  }\n#endif\n  auto new_size = std::move(op)(str.data(), n);\n  ABSL_HARDENING_ASSERT(new_size >= 0 && new_size <= n);\n  ABSL_HARDENING_ASSERT(str.data()[n] == typename T::value_type{});\n  str.erase(static_cast<typename T::size_type>(new_size));\n}\n\ntemplate <typename T, typename Op>\nvoid StringResizeAndOverwriteImpl(T& str, typename T::size_type n, Op op) {\n#ifdef ABSL_INTERNAL_HAS_RESIZE_AND_OVERWRITE\n  str.resize_and_overwrite(n, std::move(op));\n#else\n  if constexpr (strings_internal::\n                    has__google_nonstandard_backport_resize_and_overwrite<\n                        T>::value) {\n    str.__google_nonstandard_backport_resize_and_overwrite(n, std::move(op));\n  } else if constexpr (strings_internal::has__resize_and_overwrite<T>::value) {\n    str.__resize_and_overwrite(n, std::move(op));\n  } else if constexpr (strings_internal::has__resize_default_init<T>::value) {\n    str.__resize_default_init(n);\n    str.__resize_default_init(\n        static_cast<typename T::size_type>(std::move(op)(str.data(), n)));\n  } else if constexpr (strings_internal::has_Resize_and_overwrite<T>::value) {\n    str._Resize_and_overwrite(n, std::move(op));\n  } else {\n    strings_internal::StringResizeAndOverwriteFallback(str, n, std::move(op));\n  }\n#endif\n}\n\n}  // namespace strings_internal\n\n// Resizes `str` to contain at most `n` characters, using the user-provided\n// operation `op` to modify the possibly indeterminate contents. `op` must\n// return the finalized length of `str`.\n//\n// Invalidates all iterators, pointers, and references into `str`, regardless\n// of whether reallocation occurs.\n//\n// `op(value_type* buf, size_t buf_size)` is allowed to write `value_type{}` to\n// `buf[buf_size]`, which facilitiates interoperation with functions that write\n// a trailing NUL. Please note that this requirement is more strict than\n// `basic_string::resize_and_overwrite()`, which allows writing an abitrary\n// value to `buf[buf_size]`.\ntemplate <typename T, typename Op>\nvoid StringResizeAndOverwrite(T& str, typename T::size_type n, Op op) {\n  strings_internal::StringResizeAndOverwriteImpl(str, n, std::move(op));\n#if defined(ABSL_HAVE_MEMORY_SANITIZER)\n  __msan_check_mem_is_initialized(str.data(), str.size());\n#endif\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef ABSL_INTERNAL_HAS_RESIZE_AND_OVERWRITE\n\n#endif  // ABSL_STRINGS_RESIZE_AND_OVERWRITE_H_\n"
  },
  {
    "path": "absl/strings/resize_and_overwrite_test.cc",
    "content": "// Copyright 2025 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/resize_and_overwrite.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/log/absl_check.h\"\n\nnamespace {\n\nstruct ResizeAndOverwriteParam {\n  size_t initial_size;\n  size_t requested_capacity;\n  size_t final_size;\n};\n\nusing StringResizeAndOverwriteTest =\n    ::testing::TestWithParam<ResizeAndOverwriteParam>;\n\nTEST_P(StringResizeAndOverwriteTest, StringResizeAndOverwrite) {\n  const auto& param = GetParam();\n  std::string s(param.initial_size, 'a');\n  absl::StringResizeAndOverwrite(\n      s, param.requested_capacity, [&](char* p, size_t n) {\n        ABSL_CHECK_EQ(n, param.requested_capacity);\n        if (param.final_size >= param.initial_size) {\n          // Append case.\n          std::fill(p + param.initial_size, p + param.final_size, 'b');\n        } else if (param.final_size > 0) {\n          // Truncate case.\n          p[param.final_size - 1] = 'b';\n        }\n        p[param.final_size] = '\\0';\n        return param.final_size;\n      });\n\n  std::string expected;\n  if (param.final_size >= param.initial_size) {\n    // Append case.\n    expected = std::string(param.initial_size, 'a') +\n               std::string(param.final_size - param.initial_size, 'b');\n  } else if (param.final_size > 0) {\n    // Truncate case.\n    expected = std::string(param.final_size - 1, 'a') + std::string(\"b\");\n  }\n\n  EXPECT_EQ(s, expected);\n  EXPECT_EQ(s.c_str()[param.final_size], '\\0');\n}\n\nTEST_P(StringResizeAndOverwriteTest, StringResizeAndOverwriteFallback) {\n  const auto& param = GetParam();\n  std::string s(param.initial_size, 'a');\n  absl::strings_internal::StringResizeAndOverwriteFallback(\n      s, param.requested_capacity, [&](char* p, size_t n) {\n        ABSL_CHECK_EQ(n, param.requested_capacity);\n        if (param.final_size >= param.initial_size) {\n          // Append case.\n          std::fill(p + param.initial_size, p + param.final_size, 'b');\n        } else if (param.final_size > 0) {\n          // Truncate case.\n          p[param.final_size - 1] = 'b';\n        }\n        p[param.final_size] = '\\0';\n        return param.final_size;\n      });\n\n  std::string expected;\n  if (param.final_size >= param.initial_size) {\n    // Append case.\n    expected = std::string(param.initial_size, 'a') +\n               std::string(param.final_size - param.initial_size, 'b');\n  } else if (param.final_size > 0) {\n    // Truncate case.\n    expected = std::string(param.final_size - 1, 'a') + std::string(\"b\");\n  }\n\n  EXPECT_EQ(s, expected);\n  EXPECT_EQ(s.c_str()[param.final_size], '\\0');\n}\n\n#ifdef ABSL_HAVE_MEMORY_SANITIZER\nconstexpr bool kMSan = true;\n#else\nconstexpr bool kMSan = false;\n#endif\n\nTEST_P(StringResizeAndOverwriteTest, Initialized) {\n  if (!kMSan) {\n    GTEST_SKIP() << \"Skipping test without MSan.\";\n  }\n\n  const auto& param = GetParam();\n  std::string s(param.initial_size, 'a');\n\n  auto op = [&]() {\n    absl::StringResizeAndOverwrite(s, param.requested_capacity,\n                                   [&](char*, size_t) {\n                                     // Fail to initialize the buffer in full.\n                                     return param.final_size;\n                                   });\n  };\n\n  if (param.initial_size < param.final_size) {\n#ifndef NDEBUG\n    EXPECT_DEATH_IF_SUPPORTED(op(),\n                              \"MemorySanitizer: use-of-uninitialized-value\");\n#endif\n  } else {\n    // The string is fully initialized from the initial constructor, or we skip\n    // the check in optimized builds.\n    op();\n  }\n}\n\n// clang-format off\nINSTANTIATE_TEST_SUITE_P(StringResizeAndOverwriteTestSuite,\n                         StringResizeAndOverwriteTest,\n                         ::testing::ValuesIn<ResizeAndOverwriteParam>({\n                             // Append cases.\n                             {0,  10,  5},\n                             {10, 10, 10},\n                             {10, 15, 15},\n                             {10, 20, 15},\n                             {10, 40, 40},\n                             {10, 50, 40},\n                             {30, 35, 35},\n                             {30, 45, 35},\n                             {10, 30, 15},\n                             // Truncate cases.\n                             {15, 15, 10},\n                             {40, 40, 35},\n                             {40, 30, 10},\n                             {10, 15, 0},\n                         }));\n// clang-format on\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_cat.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/str_cat.h\"\n\n#include <assert.h>\n\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <initializer_list>\n#include <limits>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/internal/append_and_overwrite.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// ----------------------------------------------------------------------\n// StrCat()\n//    This merges the given strings or integers, with no delimiter. This\n//    is designed to be the fastest possible way to construct a string out\n//    of a mix of raw C strings, string_views, strings, and integer values.\n// ----------------------------------------------------------------------\n\nnamespace {\n// Append is merely a version of memcpy that returns the address of the byte\n// after the area just overwritten.\ninline char* absl_nonnull Append(char* absl_nonnull out, const AlphaNum& x) {\n  // memcpy is allowed to overwrite arbitrary memory, so doing this after the\n  // call would force an extra fetch of x.size().\n  char* after = out + x.size();\n  if (x.size() != 0) {\n    memcpy(out, x.data(), x.size());\n  }\n  return after;\n}\n\n}  // namespace\n\nstd::string StrCat(const AlphaNum& a, const AlphaNum& b) {\n  std::string result;\n  // Use uint64_t to prevent size_t overflow. We assume it is not possible for\n  // in memory strings to overflow a uint64_t.\n  constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()};\n  const uint64_t result_size =\n      static_cast<uint64_t>(a.size()) + static_cast<uint64_t>(b.size());\n  ABSL_INTERNAL_CHECK(result_size <= kMaxSize, \"size_t overflow\");\n  absl::StringResizeAndOverwrite(result, static_cast<size_t>(result_size),\n                                 [&a, &b](char* const begin, size_t buf_size) {\n                                   char* out = begin;\n                                   out = Append(out, a);\n                                   out = Append(out, b);\n                                   assert(out == begin + buf_size);\n                                   return buf_size;\n                                 });\n  return result;\n}\n\nstd::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {\n  std::string result;\n  // Use uint64_t to prevent size_t overflow. We assume it is not possible for\n  // in memory strings to overflow a uint64_t.\n  constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()};\n  const uint64_t result_size = static_cast<uint64_t>(a.size()) +\n                               static_cast<uint64_t>(b.size()) +\n                               static_cast<uint64_t>(c.size());\n  ABSL_INTERNAL_CHECK(result_size <= kMaxSize, \"size_t overflow\");\n  absl::StringResizeAndOverwrite(\n      result, static_cast<size_t>(result_size),\n      [&a, &b, &c](char* const begin, size_t buf_size) {\n        char* out = begin;\n        out = Append(out, a);\n        out = Append(out, b);\n        out = Append(out, c);\n        assert(out == begin + buf_size);\n        return buf_size;\n      });\n  return result;\n}\n\nstd::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,\n                   const AlphaNum& d) {\n  std::string result;\n  // Use uint64_t to prevent size_t overflow. We assume it is not possible for\n  // in memory strings to overflow a uint64_t.\n  constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()};\n  const uint64_t result_size =\n      static_cast<uint64_t>(a.size()) + static_cast<uint64_t>(b.size()) +\n      static_cast<uint64_t>(c.size()) + static_cast<uint64_t>(d.size());\n  ABSL_INTERNAL_CHECK(result_size <= kMaxSize, \"size_t overflow\");\n  absl::StringResizeAndOverwrite(\n      result, static_cast<size_t>(result_size),\n      [&a, &b, &c, &d](char* const begin, size_t buf_size) {\n        char* out = begin;\n        out = Append(out, a);\n        out = Append(out, b);\n        out = Append(out, c);\n        out = Append(out, d);\n        assert(out == begin + buf_size);\n        return buf_size;\n      });\n  return result;\n}\n\nnamespace strings_internal {\n\n// Do not call directly - these are not part of the public API.\nstd::string CatPieces(std::initializer_list<absl::string_view> pieces) {\n  std::string result;\n  // Use uint64_t to prevent size_t overflow. We assume it is not possible for\n  // in memory strings to overflow a uint64_t.\n  constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()};\n  uint64_t total_size = 0;\n  for (absl::string_view piece : pieces) {\n    total_size += piece.size();\n  }\n  ABSL_INTERNAL_CHECK(total_size <= kMaxSize, \"size_t overflow\");\n  absl::StringResizeAndOverwrite(result, static_cast<size_t>(total_size),\n                                 [&pieces](char* const begin, size_t buf_size) {\n                                   char* out = begin;\n                                   for (absl::string_view piece : pieces) {\n                                     const size_t this_size = piece.size();\n                                     if (this_size != 0) {\n                                       memcpy(out, piece.data(), this_size);\n                                       out += this_size;\n                                     }\n                                   }\n                                   assert(out == begin + buf_size);\n                                   return buf_size;\n                                 });\n  return result;\n}\n\n// It's possible to call StrAppend with an absl::string_view that is itself a\n// fragment of the string we're appending to.  However the results of this are\n// random. Therefore, check for this in debug mode.  Use unsigned math so we\n// only have to do one comparison. Note, there's an exception case: appending an\n// empty string is always allowed.\n#define ASSERT_NO_OVERLAP(dest, src) \\\n  assert(((src).size() == 0) ||      \\\n         (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))\n\nvoid AppendPieces(std::string* absl_nonnull dest,\n                  std::initializer_list<absl::string_view> pieces) {\n  size_t to_append = 0;\n  for (absl::string_view piece : pieces) {\n    ASSERT_NO_OVERLAP(*dest, piece);\n    to_append += piece.size();\n  }\n  StringAppendAndOverwrite(*dest, to_append,\n                           [&pieces](char* const buf, size_t buf_size) {\n                             char* out = buf;\n                             for (absl::string_view piece : pieces) {\n                               const size_t this_size = piece.size();\n                               if (this_size != 0) {\n                                 memcpy(out, piece.data(), this_size);\n                                 out += this_size;\n                               }\n                             }\n                             assert(out == buf + buf_size);\n                             return buf_size;\n                           });\n}\n\n}  // namespace strings_internal\n\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a) {\n  ASSERT_NO_OVERLAP(*dest, a);\n  strings_internal::StringAppendAndOverwrite(\n      *dest, a.size(), [&a](char* const buf, size_t buf_size) {\n        char* out = buf;\n        out = Append(out, a);\n        assert(out == buf + buf_size);\n        return buf_size;\n      });\n}\n\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n               const AlphaNum& b) {\n  ASSERT_NO_OVERLAP(*dest, a);\n  ASSERT_NO_OVERLAP(*dest, b);\n  strings_internal::StringAppendAndOverwrite(\n      *dest, a.size() + b.size(), [&a, &b](char* const buf, size_t buf_size) {\n        char* out = buf;\n        out = Append(out, a);\n        out = Append(out, b);\n        assert(out == buf + buf_size);\n        return buf_size;\n      });\n}\n\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n               const AlphaNum& b, const AlphaNum& c) {\n  ASSERT_NO_OVERLAP(*dest, a);\n  ASSERT_NO_OVERLAP(*dest, b);\n  ASSERT_NO_OVERLAP(*dest, c);\n  strings_internal::StringAppendAndOverwrite(\n      *dest, a.size() + b.size() + c.size(),\n      [&a, &b, &c](char* const buf, size_t buf_size) {\n        char* out = buf;\n        out = Append(out, a);\n        out = Append(out, b);\n        out = Append(out, c);\n        assert(out == buf + buf_size);\n        return buf_size;\n      });\n}\n\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n               const AlphaNum& b, const AlphaNum& c, const AlphaNum& d) {\n  ASSERT_NO_OVERLAP(*dest, a);\n  ASSERT_NO_OVERLAP(*dest, b);\n  ASSERT_NO_OVERLAP(*dest, c);\n  ASSERT_NO_OVERLAP(*dest, d);\n  strings_internal::StringAppendAndOverwrite(\n      *dest, a.size() + b.size() + c.size() + d.size(),\n      [&a, &b, &c, &d](char* const buf, size_t buf_size) {\n        char* out = buf;\n        out = Append(out, a);\n        out = Append(out, b);\n        out = Append(out, c);\n        out = Append(out, d);\n        assert(out == buf + buf_size);\n        return buf_size;\n      });\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/str_cat.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: str_cat.h\n// -----------------------------------------------------------------------------\n//\n// This package contains functions for efficiently concatenating and appending\n// strings: `StrCat()` and `StrAppend()`. Most of the work within these routines\n// is actually handled through use of a special AlphaNum type, which was\n// designed to be used as a parameter type that efficiently manages conversion\n// to strings and avoids copies in the above operations.\n//\n// Any routine accepting either a string or a number may accept `AlphaNum`.\n// The basic idea is that by accepting a `const AlphaNum &` as an argument\n// to your function, your callers will automagically convert bools, integers,\n// and floating point values to strings for you.\n//\n// NOTE: Use of `AlphaNum` outside of the //absl/strings package is unsupported\n// except for the specific case of function parameters of type `AlphaNum` or\n// `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a\n// stack variable is not supported.\n//\n// Conversion from 8-bit values is not accepted because, if it were, then an\n// attempt to pass ':' instead of \":\" might result in a 58 ending up in your\n// result.\n//\n// Bools convert to \"0\" or \"1\". Pointers to types other than `char *` are not\n// valid inputs. No output is generated for null `char *` pointers.\n//\n// Floating point numbers are formatted with six-digit precision, which is\n// the default for \"std::cout <<\" or printf \"%g\" (the same as \"%.6g\").\n//\n// You can convert to hexadecimal output rather than decimal output using the\n// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to\n// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using\n// a `PadSpec` enum.\n//\n// User-defined types can be formatted with the `AbslStringify()` customization\n// point. The API relies on detecting an overload in the user-defined type's\n// namespace of a free (non-member) `AbslStringify()` function as a definition\n// (typically declared as a friend and implemented in-line.\n// with the following signature:\n//\n// class MyClass { ... };\n//\n// template <typename Sink>\n// void AbslStringify(Sink& sink, const MyClass& value);\n//\n// An `AbslStringify()` overload for a type should only be declared in the same\n// file and namespace as said type.\n//\n// Note that `AbslStringify()` also supports use with `absl::StrFormat()` and\n// `absl::Substitute()`.\n//\n// Example:\n//\n// struct Point {\n//   // To add formatting support to `Point`, we simply need to add a free\n//   // (non-member) function `AbslStringify()`. This method specifies how\n//   // Point should be printed when absl::StrCat() is called on it. You can add\n//   // such a free function using a friend declaration within the body of the\n//   // class. The sink parameter is a templated type to avoid requiring\n//   // dependencies.\n//   template <typename Sink> friend void AbslStringify(Sink&\n//   sink, const Point& p) {\n//     absl::Format(&sink, \"(%v, %v)\", p.x, p.y);\n//   }\n//\n//   int x;\n//   int y;\n// };\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_STRINGS_STR_CAT_H_\n#define ABSL_STRINGS_STR_CAT_H_\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <initializer_list>\n#include <limits>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/port.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/has_absl_stringify.h\"\n#include \"absl/strings/internal/stringify_sink.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/resize_and_overwrite.h\"\n#include \"absl/strings/string_view.h\"\n\n#if !defined(ABSL_USES_STD_STRING_VIEW)\n#include <string_view>\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace strings_internal {\n// AlphaNumBuffer allows a way to pass a string to StrCat without having to do\n// memory allocation.  It is simply a pair of a fixed-size character array, and\n// a size.  Please don't use outside of absl, yet.\ntemplate <size_t max_size>\nstruct AlphaNumBuffer {\n  std::array<char, max_size> data;\n  size_t size;\n};\n\n}  // namespace strings_internal\n\n// Enum that specifies the number of significant digits to return in a `Hex` or\n// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,\n// would produce hexadecimal strings such as \"0a\",\"0f\" and a 'kSpacePad5' value\n// would produce hexadecimal strings such as \"    a\",\"    f\".\nenum PadSpec : uint8_t {\n  kNoPad = 1,\n  kZeroPad2,\n  kZeroPad3,\n  kZeroPad4,\n  kZeroPad5,\n  kZeroPad6,\n  kZeroPad7,\n  kZeroPad8,\n  kZeroPad9,\n  kZeroPad10,\n  kZeroPad11,\n  kZeroPad12,\n  kZeroPad13,\n  kZeroPad14,\n  kZeroPad15,\n  kZeroPad16,\n  kZeroPad17,\n  kZeroPad18,\n  kZeroPad19,\n  kZeroPad20,\n\n  kSpacePad2 = kZeroPad2 + 64,\n  kSpacePad3,\n  kSpacePad4,\n  kSpacePad5,\n  kSpacePad6,\n  kSpacePad7,\n  kSpacePad8,\n  kSpacePad9,\n  kSpacePad10,\n  kSpacePad11,\n  kSpacePad12,\n  kSpacePad13,\n  kSpacePad14,\n  kSpacePad15,\n  kSpacePad16,\n  kSpacePad17,\n  kSpacePad18,\n  kSpacePad19,\n  kSpacePad20,\n};\n\n// -----------------------------------------------------------------------------\n// Hex\n// -----------------------------------------------------------------------------\n//\n// `Hex` stores a set of hexadecimal string conversion parameters for use\n// within `AlphaNum` string conversions.\nstruct Hex {\n  uint64_t value;\n  uint8_t width;\n  char fill;\n\n  template <typename Int>\n  explicit Hex(\n      Int v, PadSpec spec = absl::kNoPad,\n      std::enable_if_t<sizeof(Int) == 1 && !std::is_pointer<Int>::value, bool> =\n          true)\n      : Hex(spec, static_cast<uint8_t>(v)) {}\n  template <typename Int>\n  explicit Hex(\n      Int v, PadSpec spec = absl::kNoPad,\n      std::enable_if_t<sizeof(Int) == 2 && !std::is_pointer<Int>::value, bool> =\n          true)\n      : Hex(spec, static_cast<uint16_t>(v)) {}\n  template <typename Int>\n  explicit Hex(\n      Int v, PadSpec spec = absl::kNoPad,\n      std::enable_if_t<sizeof(Int) == 4 && !std::is_pointer<Int>::value, bool> =\n          true)\n      : Hex(spec, static_cast<uint32_t>(v)) {}\n  template <typename Int>\n  explicit Hex(\n      Int v, PadSpec spec = absl::kNoPad,\n      std::enable_if_t<sizeof(Int) == 8 && !std::is_pointer<Int>::value, bool> =\n          true)\n      : Hex(spec, static_cast<uint64_t>(v)) {}\n  template <typename Pointee>\n  explicit Hex(Pointee* absl_nullable v, PadSpec spec = absl::kNoPad)\n      : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}\n\n  template <typename S>\n  friend void AbslStringify(S& sink, Hex hex) {\n    static_assert(\n        numbers_internal::kFastToBufferSize >= 32,\n        \"This function only works when output buffer >= 32 bytes long\");\n    char buffer[numbers_internal::kFastToBufferSize];\n    char* const end = &buffer[numbers_internal::kFastToBufferSize];\n    auto real_width =\n        absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);\n    if (real_width >= hex.width) {\n      sink.Append(absl::string_view(end - real_width, real_width));\n    } else {\n      // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and\n      // max pad width can be up to 20.\n      std::memset(end - 32, hex.fill, 16);\n      // Patch up everything else up to the real_width.\n      std::memset(end - real_width - 16, hex.fill, 16);\n      sink.Append(absl::string_view(end - hex.width, hex.width));\n    }\n  }\n\n private:\n  Hex(PadSpec spec, uint64_t v)\n      : value(v),\n        width(spec == absl::kNoPad\n                  ? 1\n                  : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2\n                                             : spec - absl::kZeroPad2 + 2),\n        fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}\n};\n\n// -----------------------------------------------------------------------------\n// Dec\n// -----------------------------------------------------------------------------\n//\n// `Dec` stores a set of decimal string conversion parameters for use\n// within `AlphaNum` string conversions.  Dec is slower than the default\n// integer conversion, so use it only if you need padding.\nstruct Dec {\n  uint64_t value;\n  uint8_t width;\n  char fill;\n  bool neg;\n\n  template <typename Int>\n  explicit Dec(Int v, PadSpec spec = absl::kNoPad,\n               std::enable_if_t<sizeof(Int) <= 8, bool> = true)\n      : value(v >= 0 ? static_cast<uint64_t>(v)\n                     : uint64_t{0} - static_cast<uint64_t>(v)),\n        width(spec == absl::kNoPad       ? 1\n              : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2\n                                         : spec - absl::kZeroPad2 + 2),\n        fill(spec >= absl::kSpacePad2 ? ' ' : '0'),\n        neg(v < 0) {}\n\n  template <typename S>\n  friend void AbslStringify(S& sink, Dec dec) {\n    assert(dec.width <= numbers_internal::kFastToBufferSize);\n    char buffer[numbers_internal::kFastToBufferSize];\n    char* const end = &buffer[numbers_internal::kFastToBufferSize];\n    char* const minfill = end - dec.width;\n    char* writer = end;\n    uint64_t val = dec.value;\n    while (val > 9) {\n      *--writer = '0' + (val % 10);\n      val /= 10;\n    }\n    *--writer = '0' + static_cast<char>(val);\n    if (dec.neg) *--writer = '-';\n\n    ptrdiff_t fillers = writer - minfill;\n    if (fillers > 0) {\n      // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>\n      // But...: if the fill character is '0', then it's <+/-><fill><digits>\n      bool add_sign_again = false;\n      if (dec.neg && dec.fill == '0') {  // If filling with '0',\n        ++writer;                    // ignore the sign we just added\n        add_sign_again = true;       // and re-add the sign later.\n      }\n      writer -= fillers;\n      std::fill_n(writer, fillers, dec.fill);\n      if (add_sign_again) *--writer = '-';\n    }\n\n    sink.Append(absl::string_view(writer, static_cast<size_t>(end - writer)));\n  }\n};\n\n// -----------------------------------------------------------------------------\n// AlphaNum\n// -----------------------------------------------------------------------------\n//\n// The `AlphaNum` class acts as the main parameter type for `StrCat()` and\n// `StrAppend()`, providing efficient conversion of numeric, boolean, decimal,\n// and hexadecimal values (through the `Dec` and `Hex` types) into strings.\n// `AlphaNum` should only be used as a function parameter. Do not instantiate\n//  `AlphaNum` directly as a stack variable.\n\nclass AlphaNum {\n public:\n  // No bool ctor -- bools convert to an integral type.\n  // A bool ctor would also convert incoming pointers (bletch).\n\n  // Prevent brace initialization\n  template <typename T>\n  AlphaNum(std::initializer_list<T>) = delete;  // NOLINT(runtime/explicit)\n\n  AlphaNum(int x)  // NOLINT(runtime/explicit)\n      : piece_(digits_, static_cast<size_t>(\n                            numbers_internal::FastIntToBuffer(x, digits_) -\n                            &digits_[0])) {}\n  AlphaNum(unsigned int x)  // NOLINT(runtime/explicit)\n      : piece_(digits_, static_cast<size_t>(\n                            numbers_internal::FastIntToBuffer(x, digits_) -\n                            &digits_[0])) {}\n  AlphaNum(long x)  // NOLINT(*)\n      : piece_(digits_, static_cast<size_t>(\n                            numbers_internal::FastIntToBuffer(x, digits_) -\n                            &digits_[0])) {}\n  AlphaNum(unsigned long x)  // NOLINT(*)\n      : piece_(digits_, static_cast<size_t>(\n                            numbers_internal::FastIntToBuffer(x, digits_) -\n                            &digits_[0])) {}\n  AlphaNum(long long x)  // NOLINT(*)\n      : piece_(digits_, static_cast<size_t>(\n                            numbers_internal::FastIntToBuffer(x, digits_) -\n                            &digits_[0])) {}\n  AlphaNum(unsigned long long x)  // NOLINT(*)\n      : piece_(digits_, static_cast<size_t>(\n                            numbers_internal::FastIntToBuffer(x, digits_) -\n                            &digits_[0])) {}\n\n  AlphaNum(float f)  // NOLINT(runtime/explicit)\n      : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}\n  AlphaNum(double f)  // NOLINT(runtime/explicit)\n      : piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}\n\n  template <size_t size>\n  AlphaNum(  // NOLINT(runtime/explicit)\n      const strings_internal::AlphaNumBuffer<size>& buf\n          ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : piece_(&buf.data[0], buf.size) {}\n\n  AlphaNum(const char* absl_nullable c_str  // NOLINT(runtime/explicit)\n               ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : piece_(NullSafeStringView(c_str)) {}\n  AlphaNum(absl::string_view pc  // NOLINT(runtime/explicit)\n               ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : piece_(pc) {}\n\n#if !defined(ABSL_USES_STD_STRING_VIEW)\n  AlphaNum(std::string_view pc  // NOLINT(runtime/explicit)\n               ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : piece_(pc.data(), pc.size()) {}\n#endif  // !ABSL_USES_STD_STRING_VIEW\n\n  template <typename T, typename = typename std::enable_if<\n                            HasAbslStringify<T>::value>::type>\n  AlphaNum(  // NOLINT(runtime/explicit)\n      const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      strings_internal::StringifySink&& sink ABSL_ATTRIBUTE_LIFETIME_BOUND = {})\n      : piece_(strings_internal::ExtractStringification(sink, v)) {}\n\n  template <typename Allocator>\n  AlphaNum(  // NOLINT(runtime/explicit)\n      const std::basic_string<char, std::char_traits<char>, Allocator>& str\n          ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : piece_(str) {}\n\n  // Use string literals \":\" instead of character literals ':'.\n  AlphaNum(char c) = delete;  // NOLINT(runtime/explicit)\n\n  AlphaNum(const AlphaNum&) = delete;\n  AlphaNum& operator=(const AlphaNum&) = delete;\n\n  absl::string_view::size_type size() const { return piece_.size(); }\n  const char* absl_nullable data() const { return piece_.data(); }\n  absl::string_view Piece() const { return piece_; }\n\n  // Match unscoped enums.  Use integral promotion so that a `char`-backed\n  // enum becomes a wider integral type AlphaNum will accept.\n  template <typename T,\n            typename = typename std::enable_if<\n                std::is_enum<T>{} && std::is_convertible<T, int>{} &&\n                !HasAbslStringify<T>::value>::type>\n  AlphaNum(T e)  // NOLINT(runtime/explicit)\n      : AlphaNum(+e) {}\n\n  // This overload matches scoped enums.  We must explicitly cast to the\n  // underlying type, but use integral promotion for the same reason as above.\n  template <typename T,\n            typename std::enable_if<std::is_enum<T>{} &&\n                                        !std::is_convertible<T, int>{} &&\n                                        !HasAbslStringify<T>::value,\n                                    char*>::type = nullptr>\n  AlphaNum(T e)  // NOLINT(runtime/explicit)\n      : AlphaNum(+static_cast<typename std::underlying_type<T>::type>(e)) {}\n\n  // vector<bool>::reference and const_reference require special help to\n  // convert to `AlphaNum` because it requires two user defined conversions.\n  template <\n      typename T,\n      typename std::enable_if<\n          std::is_class<T>::value &&\n          (std::is_same<T, std::vector<bool>::reference>::value ||\n           std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =\n          nullptr>\n  AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {}  // NOLINT(runtime/explicit)\n\n private:\n  absl::string_view piece_;\n  char digits_[numbers_internal::kFastToBufferSize];\n};\n\n// -----------------------------------------------------------------------------\n// StrCat()\n// -----------------------------------------------------------------------------\n//\n// Merges given strings or numbers, using no delimiter(s), returning the merged\n// result as a string.\n//\n// `StrCat()` is designed to be the fastest possible way to construct a string\n// out of a mix of raw C strings, string_views, strings, bool values,\n// and numeric values.\n//\n// Don't use `StrCat()` for user-visible strings. The localization process\n// works poorly on strings built up out of fragments.\n//\n// For clarity and performance, don't use `StrCat()` when appending to a\n// string. Use `StrAppend()` instead. In particular, avoid using any of these\n// (anti-)patterns:\n//\n//   str.append(StrCat(...))\n//   str += StrCat(...)\n//   str = StrCat(str, ...)\n//\n// The last case is the worst, with a potential to change a loop\n// from a linear time operation with O(1) dynamic allocations into a\n// quadratic time operation with O(n) dynamic allocations.\n//\n// See `StrAppend()` below for more information.\n\nnamespace strings_internal {\n\n// Do not call directly - this is not part of the public API.\nstd::string CatPieces(std::initializer_list<absl::string_view> pieces);\nvoid AppendPieces(std::string* absl_nonnull dest,\n                  std::initializer_list<absl::string_view> pieces);\n\ntemplate <typename Integer>\nstd::string IntegerToString(Integer i) {\n  // Any integer (signed/unsigned) up to 64 bits can be formatted into a buffer\n  // with 22 bytes (including NULL at the end).\n  constexpr size_t kMaxDigits10 = 22;\n  std::string result;\n  StringResizeAndOverwrite(\n      result, kMaxDigits10, [i](char* start, size_t buf_size) {\n        // Note: This can be optimized to not write last zero.\n        char* end = numbers_internal::FastIntToBuffer(i, start);\n        auto size = static_cast<size_t>(end - start);\n        ABSL_ASSERT(size < buf_size);\n        return size;\n      });\n  return result;\n}\n\ntemplate <typename Float>\nstd::string FloatToString(Float f) {\n  std::string result;\n  StringResizeAndOverwrite(result, numbers_internal::kSixDigitsToBufferSize,\n                           [f](char* start, size_t buf_size) {\n                             size_t size =\n                                 numbers_internal::SixDigitsToBuffer(f, start);\n                             ABSL_ASSERT(size < buf_size);\n                             return size;\n                           });\n  return result;\n}\n\n// `SingleArgStrCat` overloads take built-in `int`, `long` and `long long` types\n// (signed / unsigned) to avoid ambiguity on the call side. If we used int32_t\n// and int64_t, then at least one of the three (`int` / `long` / `long long`)\n// would have been ambiguous when passed to `SingleArgStrCat`.\ninline std::string SingleArgStrCat(int x) { return IntegerToString(x); }\ninline std::string SingleArgStrCat(unsigned int x) {\n  return IntegerToString(x);\n}\n// NOLINTNEXTLINE\ninline std::string SingleArgStrCat(long x) { return IntegerToString(x); }\n// NOLINTNEXTLINE\ninline std::string SingleArgStrCat(unsigned long x) {\n  return IntegerToString(x);\n}\n// NOLINTNEXTLINE\ninline std::string SingleArgStrCat(long long x) { return IntegerToString(x); }\n// NOLINTNEXTLINE\ninline std::string SingleArgStrCat(unsigned long long x) {\n  return IntegerToString(x);\n}\ninline std::string SingleArgStrCat(float x) { return FloatToString(x); }\ninline std::string SingleArgStrCat(double x) { return FloatToString(x); }\n\n// As of September 2023, the SingleArgStrCat() optimization is only enabled for\n// libc++. The reasons for this are:\n// 1) The SSO size for libc++ is 23, while libstdc++ and MSSTL have an SSO size\n// of 15. Since IntegerToString unconditionally resizes the string to 22 bytes,\n// this causes both libstdc++ and MSSTL to allocate.\n// 2) strings_internal::STLStringResizeUninitialized() only has an\n// implementation that avoids initialization when using libc++. This isn't as\n// relevant as (1), and the cost should be benchmarked if (1) ever changes on\n// libstc++ or MSSTL.\n#ifdef _LIBCPP_VERSION\n#define ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE true\n#else\n#define ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE false\n#endif\n\ntemplate <typename T, typename = std::enable_if_t<\n                          ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE &&\n                          std::is_arithmetic<T>{} && !std::is_same<T, char>{}>>\nusing EnableIfFastCase = T;\n\n#undef ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE\n\n}  // namespace strings_internal\n\n[[nodiscard]] inline std::string StrCat() { return std::string(); }\n\ntemplate <typename T>\n[[nodiscard]] inline std::string StrCat(\n    strings_internal::EnableIfFastCase<T> a) {\n  return strings_internal::SingleArgStrCat(a);\n}\n[[nodiscard]] inline std::string StrCat(const AlphaNum& a) {\n  return std::string(a.data(), a.size());\n}\n\n[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b);\n[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b,\n                                 const AlphaNum& c);\n[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b,\n                                 const AlphaNum& c, const AlphaNum& d);\n\n// Support 5 or more arguments\ntemplate <typename... AV>\n[[nodiscard]] inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,\n                                        const AlphaNum& c, const AlphaNum& d,\n                                        const AlphaNum& e, const AV&... args) {\n  return strings_internal::CatPieces(\n      {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),\n       static_cast<const AlphaNum&>(args).Piece()...});\n}\n\n// -----------------------------------------------------------------------------\n// StrAppend()\n// -----------------------------------------------------------------------------\n//\n// Appends a string or set of strings to an existing string, in a similar\n// fashion to `StrCat()`.\n//\n// WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the\n// a, b, c, parameters be a reference into str. For speed, `StrAppend()` does\n// not try to check each of its input arguments to be sure that they are not\n// a subset of the string being appended to. That is, while this will work:\n//\n//   std::string s = \"foo\";\n//   s += s;\n//\n// This output is undefined:\n//\n//   std::string s = \"foo\";\n//   StrAppend(&s, s);\n//\n// This output is undefined as well, since `absl::string_view` does not own its\n// data:\n//\n//   std::string s = \"foobar\";\n//   absl::string_view p = s;\n//   StrAppend(&s, p);\n\ninline void StrAppend(std::string* absl_nonnull) {}\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a);\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n               const AlphaNum& b);\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n               const AlphaNum& b, const AlphaNum& c);\nvoid StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n               const AlphaNum& b, const AlphaNum& c, const AlphaNum& d);\n\n// Support 5 or more arguments\ntemplate <typename... AV>\ninline void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,\n                      const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,\n                      const AlphaNum& e, const AV&... args) {\n  strings_internal::AppendPieces(\n      dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),\n             static_cast<const AlphaNum&>(args).Piece()...});\n}\n\n// Helper function for the future StrCat default floating-point format, %.6g\n// This is fast.\ninline strings_internal::AlphaNumBuffer<\n    numbers_internal::kSixDigitsToBufferSize>\nSixDigits(double d) {\n  strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>\n      result;\n  result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);\n  return result;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STR_CAT_H_\n"
  },
  {
    "path": "absl/strings/str_cat_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <array>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <string>\n#include <tuple>\n#include <utility>\n\n#include \"absl/random/log_uniform_int_distribution.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/substitute.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nconst char kStringOne[] = \"Once Upon A Time, \";\nconst char kStringTwo[] = \"There was a string benchmark\";\n\n// We want to include negative numbers in the benchmark, so this function\n// is used to count 0, 1, -1, 2, -2, 3, -3, ...\ninline int IncrementAlternatingSign(int i) {\n  return i > 0 ? -i : 1 - i;\n}\n\nvoid BM_Sum_By_StrCat(benchmark::State& state) {\n  int i = 0;\n  char foo[100];\n  for (auto _ : state) {\n    // NOLINTNEXTLINE(runtime/printf)\n    strcpy(foo, absl::StrCat(kStringOne, i, kStringTwo, i * 65536ULL).c_str());\n    int sum = 0;\n    for (char* f = &foo[0]; *f != 0; ++f) {\n      sum += *f;\n    }\n    benchmark::DoNotOptimize(sum);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_Sum_By_StrCat);\n\nvoid BM_StrCat_By_snprintf(benchmark::State& state) {\n  int i = 0;\n  char on_stack[1000];\n  for (auto _ : state) {\n    snprintf(on_stack, sizeof(on_stack), \"%s %s:%d\", kStringOne, kStringTwo, i);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_StrCat_By_snprintf);\n\nvoid BM_StrCat_By_Strings(benchmark::State& state) {\n  int i = 0;\n  for (auto _ : state) {\n    std::string result =\n        std::string(kStringOne) + \" \" + kStringTwo + \":\" + absl::StrCat(i);\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_StrCat_By_Strings);\n\nvoid BM_StrCat_By_StringOpPlus(benchmark::State& state) {\n  int i = 0;\n  for (auto _ : state) {\n    std::string result = kStringOne;\n    result += \" \";\n    result += kStringTwo;\n    result += \":\";\n    result += absl::StrCat(i);\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_StrCat_By_StringOpPlus);\n\nvoid BM_StrCat_By_StrCat(benchmark::State& state) {\n  int i = 0;\n  for (auto _ : state) {\n    std::string result = absl::StrCat(kStringOne, \" \", kStringTwo, \":\", i);\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_StrCat_By_StrCat);\n\nvoid BM_HexCat_By_StrCat(benchmark::State& state) {\n  int i = 0;\n  for (auto _ : state) {\n    std::string result =\n        absl::StrCat(kStringOne, \" \", absl::Hex(int64_t{i} + 0x10000000));\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_HexCat_By_StrCat);\n\nvoid BM_HexCat_By_StrFormat(benchmark::State& state) {\n  int i = 0;\n  for (auto _ : state) {\n    std::string result =\n        absl::StrFormat(\"%s %x\", kStringOne, int64_t{i} + 0x10000000);\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_HexCat_By_StrFormat);\n\nvoid BM_HexCat_By_Substitute(benchmark::State& state) {\n  int i = 0;\n  for (auto _ : state) {\n    std::string result = absl::Substitute(\n        \"$0 $1\", kStringOne, reinterpret_cast<void*>(int64_t{i} + 0x10000000));\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_HexCat_By_Substitute);\n\nvoid BM_FloatToString_By_StrCat(benchmark::State& state) {\n  int i = 0;\n  float foo = 0.0f;\n  for (auto _ : state) {\n    std::string result = absl::StrCat(foo += 1.001f, \" != \", int64_t{i});\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_FloatToString_By_StrCat);\n\nvoid BM_DoubleToString_By_SixDigits(benchmark::State& state) {\n  int i = 0;\n  double foo = 0.0;\n  for (auto _ : state) {\n    std::string result =\n        absl::StrCat(absl::SixDigits(foo += 1.001), \" != \", int64_t{i});\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_DoubleToString_By_SixDigits);\n\nvoid BM_FloatToString_By_StrFormat(benchmark::State& state) {\n  int i = 0;\n  float foo = 0.0f;\n  for (auto _ : state) {\n    std::string result =\n        absl::StrFormat(\"%f != %lld\", foo += 1.001f, int64_t{i});\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\nBENCHMARK(BM_FloatToString_By_StrFormat);\n\ntemplate <typename Table, size_t... Index>\nvoid BM_StrAppendImpl(benchmark::State& state, Table table, size_t total_bytes,\n                      std::index_sequence<Index...>) {\n  for (auto s : state) {\n    const size_t table_size = table.size();\n    size_t i = 0;\n    std::string result;\n    while (result.size() < total_bytes) {\n      absl::StrAppend(&result, std::get<Index>(table[i])...);\n      benchmark::DoNotOptimize(result);\n      ++i;\n      i -= i >= table_size ? table_size : 0;\n    }\n  }\n}\n\ntemplate <typename Array>\nvoid BM_StrAppend(benchmark::State& state, Array&& table) {\n  const size_t total_bytes = state.range(0);\n  const int chunks_at_a_time = state.range(1);\n\n  switch (chunks_at_a_time) {\n    case 1:\n      return BM_StrAppendImpl(state, std::forward<Array>(table), total_bytes,\n                              std::make_index_sequence<1>());\n    case 2:\n      return BM_StrAppendImpl(state, std::forward<Array>(table), total_bytes,\n                              std::make_index_sequence<2>());\n    case 4:\n      return BM_StrAppendImpl(state, std::forward<Array>(table), total_bytes,\n                              std::make_index_sequence<4>());\n    case 8:\n      return BM_StrAppendImpl(state, std::forward<Array>(table), total_bytes,\n                              std::make_index_sequence<8>());\n    default:\n      std::abort();\n  }\n}\n\nvoid BM_StrAppendStr(benchmark::State& state) {\n  using T = absl::string_view;\n  using Row = std::tuple<T, T, T, T, T, T, T, T>;\n  constexpr absl::string_view kChunk = \"0123456789\";\n  Row row = {kChunk, kChunk, kChunk, kChunk, kChunk, kChunk, kChunk, kChunk};\n  return BM_StrAppend(state, std::array<Row, 1>({row}));\n}\n\ntemplate <typename T>\nvoid BM_StrAppendInt(benchmark::State& state) {\n  absl::BitGen rng;\n  absl::log_uniform_int_distribution<T> dist;\n  std::array<std::tuple<T, T, T, T, T, T, T, T>, (1 << 7)> table;\n  for (size_t i = 0; i < table.size(); ++i) {\n    table[i] = {dist(rng), dist(rng), dist(rng), dist(rng),\n                dist(rng), dist(rng), dist(rng), dist(rng)};\n  }\n  return BM_StrAppend(state, table);\n}\n\nvoid StrAppendConfig(::benchmark::Benchmark* benchmark) {\n  for (int bytes : {10, 100, 1000, 10000}) {\n    for (int chunks : {1, 2, 4, 8}) {\n      // Only add the ones that divide properly. Otherwise we are over counting.\n      if (bytes % (10 * chunks) == 0) {\n        benchmark->Args({bytes, chunks});\n      }\n    }\n  }\n}\n\nBENCHMARK(BM_StrAppendStr)->Apply(StrAppendConfig);\nBENCHMARK(BM_StrAppendInt<int64_t>)->Apply(StrAppendConfig);\nBENCHMARK(BM_StrAppendInt<uint64_t>)->Apply(StrAppendConfig);\nBENCHMARK(BM_StrAppendInt<int32_t>)->Apply(StrAppendConfig);\nBENCHMARK(BM_StrAppendInt<uint32_t>)->Apply(StrAppendConfig);\n\ntemplate <typename... Chunks>\nvoid BM_StrCatImpl(benchmark::State& state,\n                      Chunks... chunks) {\n  for (auto s : state) {\n    std::string result = absl::StrCat(chunks...);\n    benchmark::DoNotOptimize(result);\n  }\n}\n\nvoid BM_StrCat(benchmark::State& state) {\n  const int chunks_at_a_time = state.range(0);\n  const absl::string_view kChunk = \"0123456789\";\n\n  switch (chunks_at_a_time) {\n    case 1:\n      return BM_StrCatImpl(state, kChunk);\n    case 2:\n      return BM_StrCatImpl(state, kChunk, kChunk);\n    case 3:\n      return BM_StrCatImpl(state, kChunk, kChunk, kChunk);\n    case 4:\n      return BM_StrCatImpl(state, kChunk, kChunk, kChunk, kChunk);\n    default:\n      std::abort();\n  }\n}\n\nBENCHMARK(BM_StrCat)->Arg(1)->Arg(2)->Arg(3)->Arg(4);\n\nvoid BM_StrCat_int(benchmark::State& state) {\n  int i = 0;\n  for (auto s : state) {\n    std::string result = absl::StrCat(i);\n    benchmark::DoNotOptimize(result);\n    i = IncrementAlternatingSign(i);\n  }\n}\n\nBENCHMARK(BM_StrCat_int);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_cat_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Unit tests for all str_cat.h functions\n\n#include \"absl/strings/str_cat.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <limits>\n#include <string>\n#include <string_view>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/strings/string_view.h\"\n\n#ifdef __ANDROID__\n// Android assert messages only go to system log, so death tests cannot inspect\n// the message for matching.\n#define ABSL_EXPECT_DEBUG_DEATH(statement, regex) \\\n  EXPECT_DEBUG_DEATH(statement, \".*\")\n#else\n#define ABSL_EXPECT_DEBUG_DEATH(statement, regex) \\\n  EXPECT_DEBUG_DEATH(statement, regex)\n#endif\n\nnamespace {\n\n// Test absl::StrCat of ints and longs of various sizes and signdedness.\nTEST(StrCat, Ints) {\n  const short s = -1;  // NOLINT(runtime/int)\n  const uint16_t us = 2;\n  const int i = -3;\n  const unsigned int ui = 4;\n  const long l = -5;                 // NOLINT(runtime/int)\n  const unsigned long ul = 6;        // NOLINT(runtime/int)\n  const long long ll = -7;           // NOLINT(runtime/int)\n  const unsigned long long ull = 8;  // NOLINT(runtime/int)\n  const ptrdiff_t ptrdiff = -9;\n  const size_t size = 10;\n  const intptr_t intptr = -12;\n  const uintptr_t uintptr = 13;\n  std::string answer;\n  answer = absl::StrCat(s, us);\n  EXPECT_EQ(answer, \"-12\");\n  answer = absl::StrCat(i, ui);\n  EXPECT_EQ(answer, \"-34\");\n  answer = absl::StrCat(l, ul);\n  EXPECT_EQ(answer, \"-56\");\n  answer = absl::StrCat(ll, ull);\n  EXPECT_EQ(answer, \"-78\");\n  answer = absl::StrCat(ptrdiff, size);\n  EXPECT_EQ(answer, \"-910\");\n  answer = absl::StrCat(ptrdiff, intptr);\n  EXPECT_EQ(answer, \"-9-12\");\n  answer = absl::StrCat(uintptr, 0);\n  EXPECT_EQ(answer, \"130\");\n}\n\nTEST(StrCat, Enums) {\n  enum SmallNumbers { One = 1, Ten = 10 } e = Ten;\n  EXPECT_EQ(\"10\", absl::StrCat(e));\n  EXPECT_EQ(\"1\", absl::StrCat(One));\n\n  enum class Option { Boxers = 1, Briefs = -1 };\n\n  EXPECT_EQ(\"-1\", absl::StrCat(Option::Briefs));\n\n  enum class Airplane : uint64_t {\n    Airbus = 1,\n    Boeing = 1000,\n    Canary = 10000000000  // too big for \"int\"\n  };\n\n  EXPECT_EQ(\"10000000000\", absl::StrCat(Airplane::Canary));\n\n  enum class TwoGig : int32_t {\n    TwoToTheZero = 1,\n    TwoToTheSixteenth = 1 << 16,\n    TwoToTheThirtyFirst = INT32_MIN\n  };\n  EXPECT_EQ(\"65536\", absl::StrCat(TwoGig::TwoToTheSixteenth));\n  EXPECT_EQ(\"-2147483648\", absl::StrCat(TwoGig::TwoToTheThirtyFirst));\n  EXPECT_EQ(\"-1\", absl::StrCat(static_cast<TwoGig>(-1)));\n\n  enum class FourGig : uint32_t {\n    TwoToTheZero = 1,\n    TwoToTheSixteenth = 1 << 16,\n    TwoToTheThirtyFirst = 1U << 31  // too big for \"int\"\n  };\n  EXPECT_EQ(\"65536\", absl::StrCat(FourGig::TwoToTheSixteenth));\n  EXPECT_EQ(\"2147483648\", absl::StrCat(FourGig::TwoToTheThirtyFirst));\n  EXPECT_EQ(\"4294967295\", absl::StrCat(static_cast<FourGig>(-1)));\n\n  EXPECT_EQ(\"10000000000\", absl::StrCat(Airplane::Canary));\n}\n\nTEST(StrCat, Basics) {\n  std::string result;\n\n  std::string strs[] = {\"Hello\", \"Cruel\", \"World\"};\n\n  std::string stdstrs[] = {\n    \"std::Hello\",\n    \"std::Cruel\",\n    \"std::World\"\n  };\n\n  absl::string_view pieces[] = {\"Hello\", \"Cruel\", \"World\"};\n\n  const char* c_strs[] = {\n    \"Hello\",\n    \"Cruel\",\n    \"World\"\n  };\n\n  int32_t i32s[] = {'H', 'C', 'W'};\n  uint64_t ui64s[] = {12345678910LL, 10987654321LL};\n\n  EXPECT_EQ(absl::StrCat(), \"\");\n\n  result = absl::StrCat(false, true, 2, 3);\n  EXPECT_EQ(result, \"0123\");\n\n  result = absl::StrCat(-1);\n  EXPECT_EQ(result, \"-1\");\n\n  result = absl::StrCat(absl::SixDigits(0.5));\n  EXPECT_EQ(result, \"0.5\");\n\n  result = absl::StrCat(strs[1], pieces[2]);\n  EXPECT_EQ(result, \"CruelWorld\");\n\n  result = absl::StrCat(stdstrs[1], \" \", stdstrs[2]);\n  EXPECT_EQ(result, \"std::Cruel std::World\");\n\n  result = absl::StrCat(strs[0], \", \", pieces[2]);\n  EXPECT_EQ(result, \"Hello, World\");\n\n  result = absl::StrCat(strs[0], \", \", strs[1], \" \", strs[2], \"!\");\n  EXPECT_EQ(result, \"Hello, Cruel World!\");\n\n  result = absl::StrCat(pieces[0], \", \", pieces[1], \" \", pieces[2]);\n  EXPECT_EQ(result, \"Hello, Cruel World\");\n\n  result = absl::StrCat(c_strs[0], \", \", c_strs[1], \" \", c_strs[2]);\n  EXPECT_EQ(result, \"Hello, Cruel World\");\n\n  result = absl::StrCat(\"ASCII \", i32s[0], \", \", i32s[1], \" \", i32s[2], \"!\");\n  EXPECT_EQ(result, \"ASCII 72, 67 87!\");\n\n  result = absl::StrCat(ui64s[0], \", \", ui64s[1], \"!\");\n  EXPECT_EQ(result, \"12345678910, 10987654321!\");\n\n  std::string one =\n      \"1\";  // Actually, it's the size of this string that we want; a\n            // 64-bit build distinguishes between size_t and uint64_t,\n            // even though they're both unsigned 64-bit values.\n  result = absl::StrCat(\"And a \", one.size(), \" and a \",\n                        &result[2] - &result[0], \" and a \", one, \" 2 3 4\", \"!\");\n  EXPECT_EQ(result, \"And a 1 and a 2 and a 1 2 3 4!\");\n\n  // result = absl::StrCat(\"Single chars won't compile\", '!');\n  // result = absl::StrCat(\"Neither will nullptrs\", nullptr);\n  result =\n      absl::StrCat(\"To output a char by ASCII/numeric value, use +: \", '!' + 0);\n  EXPECT_EQ(result, \"To output a char by ASCII/numeric value, use +: 33\");\n\n  float f = 100000.5;\n  result = absl::StrCat(\"A hundred K and a half is \", absl::SixDigits(f));\n  EXPECT_EQ(result, \"A hundred K and a half is 100000\");\n\n  f = 100001.5;\n  result =\n      absl::StrCat(\"A hundred K and one and a half is \", absl::SixDigits(f));\n  EXPECT_EQ(result, \"A hundred K and one and a half is 100002\");\n\n  double d = 100000.5;\n  d *= d;\n  result =\n      absl::StrCat(\"A hundred K and a half squared is \", absl::SixDigits(d));\n  EXPECT_EQ(result, \"A hundred K and a half squared is 1.00001e+10\");\n\n  result = absl::StrCat(1, 2, 333, 4444, 55555, 666666, 7777777, 88888888,\n                        999999999);\n  EXPECT_EQ(result, \"12333444455555666666777777788888888999999999\");\n}\n\nTEST(StrCat, CornerCases) {\n  std::string result;\n\n  result = absl::StrCat(\"\");  // NOLINT\n  EXPECT_EQ(result, \"\");\n  result = absl::StrCat(\"\", \"\");\n  EXPECT_EQ(result, \"\");\n  result = absl::StrCat(\"\", \"\", \"\");\n  EXPECT_EQ(result, \"\");\n  result = absl::StrCat(\"\", \"\", \"\", \"\");\n  EXPECT_EQ(result, \"\");\n  result = absl::StrCat(\"\", \"\", \"\", \"\", \"\");\n  EXPECT_EQ(result, \"\");\n}\n\nTEST(StrCat, StdStringView) {\n  std::string_view pieces[] = {\"Hello\", \", \", \"World\", \"!\"};\n  EXPECT_EQ(absl::StrCat(pieces[0], pieces[1], pieces[2], pieces[3]),\n                         \"Hello, World!\");\n}\n\nTEST(StrCat, NullConstCharPtr) {\n  const char* null = nullptr;\n  EXPECT_EQ(absl::StrCat(\"mon\", null, \"key\"), \"monkey\");\n}\n\n// A minimal allocator that uses malloc().\ntemplate <typename T>\nstruct Mallocator {\n  typedef T value_type;\n  typedef size_t size_type;\n  typedef ptrdiff_t difference_type;\n  typedef T* pointer;\n  typedef const T* const_pointer;\n  typedef T& reference;\n  typedef const T& const_reference;\n\n  size_type max_size() const {\n    return size_t(std::numeric_limits<size_type>::max()) / sizeof(value_type);\n  }\n  template <typename U>\n  struct rebind {\n    typedef Mallocator<U> other;\n  };\n  Mallocator() = default;\n  template <class U>\n  Mallocator(const Mallocator<U>&) {}  // NOLINT(runtime/explicit)\n\n  T* allocate(size_t n) { return static_cast<T*>(std::malloc(n * sizeof(T))); }\n  void deallocate(T* p, size_t) { std::free(p); }\n};\ntemplate <typename T, typename U>\nbool operator==(const Mallocator<T>&, const Mallocator<U>&) {\n  return true;\n}\ntemplate <typename T, typename U>\nbool operator!=(const Mallocator<T>&, const Mallocator<U>&) {\n  return false;\n}\n\nTEST(StrCat, CustomAllocator) {\n  using mstring =\n      std::basic_string<char, std::char_traits<char>, Mallocator<char>>;\n  const mstring str1(\"PARACHUTE OFF A BLIMP INTO MOSCONE!!\");\n\n  const mstring str2(\"Read this book about coffee tables\");\n\n  std::string result = absl::StrCat(str1, str2);\n  EXPECT_EQ(result,\n            \"PARACHUTE OFF A BLIMP INTO MOSCONE!!\"\n            \"Read this book about coffee tables\");\n}\n\nTEST(StrCat, MaxArgs) {\n  std::string result;\n  // Test 10 up to 26 arguments, the old maximum\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\");\n  EXPECT_EQ(result, \"123456789a\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\");\n  EXPECT_EQ(result, \"123456789ab\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\");\n  EXPECT_EQ(result, \"123456789abc\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\");\n  EXPECT_EQ(result, \"123456789abcd\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\");\n  EXPECT_EQ(result, \"123456789abcde\");\n  result =\n      absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\");\n  EXPECT_EQ(result, \"123456789abcdef\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\");\n  EXPECT_EQ(result, \"123456789abcdefg\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\");\n  EXPECT_EQ(result, \"123456789abcdefgh\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\");\n  EXPECT_EQ(result, \"123456789abcdefghi\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\");\n  EXPECT_EQ(result, \"123456789abcdefghij\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\");\n  EXPECT_EQ(result, \"123456789abcdefghijk\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\", \"l\");\n  EXPECT_EQ(result, \"123456789abcdefghijkl\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\");\n  EXPECT_EQ(result, \"123456789abcdefghijklm\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\");\n  EXPECT_EQ(result, \"123456789abcdefghijklmn\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\");\n  EXPECT_EQ(result, \"123456789abcdefghijklmno\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\");\n  EXPECT_EQ(result, \"123456789abcdefghijklmnop\");\n  result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\",\n                        \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\");\n  EXPECT_EQ(result, \"123456789abcdefghijklmnopq\");\n  // No limit thanks to C++11's variadic templates\n  result = absl::StrCat(\n      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\",\n      \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\",\n      \"x\", \"y\", \"z\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\",\n      \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\");\n  EXPECT_EQ(result,\n            \"12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n}\n\nTEST(StrAppend, Basics) {\n  std::string result = \"existing text\";\n\n  std::string strs[] = {\"Hello\", \"Cruel\", \"World\"};\n\n  std::string stdstrs[] = {\n    \"std::Hello\",\n    \"std::Cruel\",\n    \"std::World\"\n  };\n\n  absl::string_view pieces[] = {\"Hello\", \"Cruel\", \"World\"};\n\n  const char* c_strs[] = {\n    \"Hello\",\n    \"Cruel\",\n    \"World\"\n  };\n\n  int32_t i32s[] = {'H', 'C', 'W'};\n  uint64_t ui64s[] = {12345678910LL, 10987654321LL};\n\n  std::string::size_type old_size = result.size();\n  absl::StrAppend(&result);\n  EXPECT_EQ(result.size(), old_size);\n\n  old_size = result.size();\n  absl::StrAppend(&result, strs[0]);\n  EXPECT_EQ(result.substr(old_size), \"Hello\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, strs[1], pieces[2]);\n  EXPECT_EQ(result.substr(old_size), \"CruelWorld\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, stdstrs[0], \", \", pieces[2]);\n  EXPECT_EQ(result.substr(old_size), \"std::Hello, World\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, strs[0], \", \", stdstrs[1], \" \", strs[2], \"!\");\n  EXPECT_EQ(result.substr(old_size), \"Hello, std::Cruel World!\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, pieces[0], \", \", pieces[1], \" \", pieces[2]);\n  EXPECT_EQ(result.substr(old_size), \"Hello, Cruel World\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, c_strs[0], \", \", c_strs[1], \" \", c_strs[2]);\n  EXPECT_EQ(result.substr(old_size), \"Hello, Cruel World\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, \"ASCII \", i32s[0], \", \", i32s[1], \" \", i32s[2], \"!\");\n  EXPECT_EQ(result.substr(old_size), \"ASCII 72, 67 87!\");\n\n  old_size = result.size();\n  absl::StrAppend(&result, ui64s[0], \", \", ui64s[1], \"!\");\n  EXPECT_EQ(result.substr(old_size), \"12345678910, 10987654321!\");\n\n  std::string one =\n      \"1\";  // Actually, it's the size of this string that we want; a\n            // 64-bit build distinguishes between size_t and uint64_t,\n            // even though they're both unsigned 64-bit values.\n  old_size = result.size();\n  absl::StrAppend(&result, \"And a \", one.size(), \" and a \",\n                  &result[2] - &result[0], \" and a \", one, \" 2 3 4\", \"!\");\n  EXPECT_EQ(result.substr(old_size), \"And a 1 and a 2 and a 1 2 3 4!\");\n\n  // result = absl::StrCat(\"Single chars won't compile\", '!');\n  // result = absl::StrCat(\"Neither will nullptrs\", nullptr);\n  old_size = result.size();\n  absl::StrAppend(&result,\n                  \"To output a char by ASCII/numeric value, use +: \", '!' + 0);\n  EXPECT_EQ(result.substr(old_size),\n            \"To output a char by ASCII/numeric value, use +: 33\");\n\n  // Test 9 arguments, the old maximum\n  old_size = result.size();\n  absl::StrAppend(&result, 1, 22, 333, 4444, 55555, 666666, 7777777, 88888888,\n                  9);\n  EXPECT_EQ(result.substr(old_size), \"1223334444555556666667777777888888889\");\n\n  // No limit thanks to C++11's variadic templates\n  old_size = result.size();\n  absl::StrAppend(\n      &result, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,                           //\n      \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\",  //\n      \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\",  //\n      \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\",  //\n      \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\",  //\n      \"No limit thanks to C++11's variadic templates\");\n  EXPECT_EQ(result.substr(old_size),\n            \"12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n            \"No limit thanks to C++11's variadic templates\");\n}\n\nTEST(StrCat, VectorBoolReferenceTypes) {\n  std::vector<bool> v;\n  v.push_back(true);\n  v.push_back(false);\n  std::vector<bool> const& cv = v;\n  // Test that vector<bool>::reference and vector<bool>::const_reference\n  // are handled as if the were really bool types and not the proxy types\n  // they really are.\n  std::string result = absl::StrCat(v[0], v[1], cv[0], cv[1]); // NOLINT\n  EXPECT_EQ(result, \"1010\");\n}\n\n// Passing nullptr to memcpy is undefined behavior and this test\n// provides coverage of codepaths that handle empty strings with nullptrs.\nTEST(StrCat, AvoidsMemcpyWithNullptr) {\n  EXPECT_EQ(absl::StrCat(42, absl::string_view{}), \"42\");\n\n  // Cover CatPieces code.\n  EXPECT_EQ(absl::StrCat(1, 2, 3, 4, 5, absl::string_view{}), \"12345\");\n\n  // Cover AppendPieces.\n  std::string result;\n  absl::StrAppend(&result, 1, 2, 3, 4, 5, absl::string_view{});\n  EXPECT_EQ(result, \"12345\");\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(StrAppend, Death) {\n  std::string s = \"self\";\n  // on linux it's \"assertion\", on mac it's \"Assertion\",\n  // on chromiumos it's \"Assertion ... failed\".\n  ABSL_EXPECT_DEBUG_DEATH(absl::StrAppend(&s, s.c_str() + 1),\n                          \"ssertion.*failed\");\n  ABSL_EXPECT_DEBUG_DEATH(absl::StrAppend(&s, s), \"ssertion.*failed\");\n}\n#endif  // GTEST_HAS_DEATH_TEST\n\nTEST(StrAppend, CornerCases) {\n  std::string result;\n  absl::StrAppend(&result, \"\");\n  EXPECT_EQ(result, \"\");\n  absl::StrAppend(&result, \"\", \"\");\n  EXPECT_EQ(result, \"\");\n  absl::StrAppend(&result, \"\", \"\", \"\");\n  EXPECT_EQ(result, \"\");\n  absl::StrAppend(&result, \"\", \"\", \"\", \"\");\n  EXPECT_EQ(result, \"\");\n  absl::StrAppend(&result, \"\", \"\", \"\", \"\", \"\");\n  EXPECT_EQ(result, \"\");\n}\n\nTEST(StrAppend, CornerCasesNonEmptyAppend) {\n  for (std::string result : {\"hello\", \"a string too long to fit in the SSO\"}) {\n    const std::string expected = result;\n    absl::StrAppend(&result, \"\");\n    EXPECT_EQ(result, expected);\n    absl::StrAppend(&result, \"\", \"\");\n    EXPECT_EQ(result, expected);\n    absl::StrAppend(&result, \"\", \"\", \"\");\n    EXPECT_EQ(result, expected);\n    absl::StrAppend(&result, \"\", \"\", \"\", \"\");\n    EXPECT_EQ(result, expected);\n    absl::StrAppend(&result, \"\", \"\", \"\", \"\", \"\");\n    EXPECT_EQ(result, expected);\n  }\n}\n\ntemplate <typename IntType>\nvoid CheckHex(IntType v, const char* nopad_format, const char* zeropad_format,\n              const char* spacepad_format) {\n  char expected[256];\n\n  std::string actual = absl::StrCat(absl::Hex(v, absl::kNoPad));\n  snprintf(expected, sizeof(expected), nopad_format, v);\n  EXPECT_EQ(expected, actual) << \" decimal value \" << v;\n\n  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) {\n    std::string actual =\n        absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec)));\n    snprintf(expected, sizeof(expected), zeropad_format,\n             spec - absl::kZeroPad2 + 2, v);\n    EXPECT_EQ(expected, actual) << \" decimal value \" << v;\n  }\n\n  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) {\n    std::string actual =\n        absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec)));\n    snprintf(expected, sizeof(expected), spacepad_format,\n             spec - absl::kSpacePad2 + 2, v);\n    EXPECT_EQ(expected, actual) << \" decimal value \" << v;\n  }\n}\n\ntemplate <typename IntType>\nvoid CheckDec(IntType v, const char* nopad_format, const char* zeropad_format,\n              const char* spacepad_format) {\n  char expected[256];\n\n  std::string actual = absl::StrCat(absl::Dec(v, absl::kNoPad));\n  snprintf(expected, sizeof(expected), nopad_format, v);\n  EXPECT_EQ(expected, actual) << \" decimal value \" << v;\n\n  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) {\n    std::string actual =\n        absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));\n    snprintf(expected, sizeof(expected), zeropad_format,\n             spec - absl::kZeroPad2 + 2, v);\n    EXPECT_EQ(expected, actual)\n        << \" decimal value \" << v << \" format '\" << zeropad_format\n        << \"' digits \" << (spec - absl::kZeroPad2 + 2);\n  }\n\n  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) {\n    std::string actual =\n        absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));\n    snprintf(expected, sizeof(expected), spacepad_format,\n             spec - absl::kSpacePad2 + 2, v);\n    EXPECT_EQ(expected, actual)\n        << \" decimal value \" << v << \" format '\" << spacepad_format\n        << \"' digits \" << (spec - absl::kSpacePad2 + 2);\n  }\n}\n\nvoid CheckHexDec64(uint64_t v) {\n  unsigned long long ullv = v;  // NOLINT(runtime/int)\n\n  CheckHex(ullv, \"%llx\", \"%0*llx\", \"%*llx\");\n  CheckDec(ullv, \"%llu\", \"%0*llu\", \"%*llu\");\n\n  long long llv = static_cast<long long>(ullv);  // NOLINT(runtime/int)\n  CheckDec(llv, \"%lld\", \"%0*lld\", \"%*lld\");\n\n  if (sizeof(v) == sizeof(&v)) {\n    auto uintptr = static_cast<uintptr_t>(v);\n    void* ptr = reinterpret_cast<void*>(uintptr);\n    CheckHex(ptr, \"%llx\", \"%0*llx\", \"%*llx\");\n  }\n}\n\nvoid CheckHexDec32(uint32_t uv) {\n  CheckHex(uv, \"%x\", \"%0*x\", \"%*x\");\n  CheckDec(uv, \"%u\", \"%0*u\", \"%*u\");\n  int32_t v = static_cast<int32_t>(uv);\n  CheckDec(v, \"%d\", \"%0*d\", \"%*d\");\n\n  if (sizeof(v) == sizeof(&v)) {\n    auto uintptr = static_cast<uintptr_t>(v);\n    void* ptr = reinterpret_cast<void*>(uintptr);\n    CheckHex(ptr, \"%x\", \"%0*x\", \"%*x\");\n  }\n}\n\nvoid CheckAll(uint64_t v) {\n  CheckHexDec64(v);\n  CheckHexDec32(static_cast<uint32_t>(v));\n}\n\nvoid TestFastPrints() {\n  // Test all small ints; there aren't many and they're common.\n  for (int i = 0; i < 10000; i++) {\n    CheckAll(i);\n  }\n\n  CheckAll(std::numeric_limits<uint64_t>::max());\n  CheckAll(std::numeric_limits<uint64_t>::max() - 1);\n  CheckAll(std::numeric_limits<int64_t>::min());\n  CheckAll(std::numeric_limits<int64_t>::min() + 1);\n  CheckAll(std::numeric_limits<uint32_t>::max());\n  CheckAll(std::numeric_limits<uint32_t>::max() - 1);\n  CheckAll(std::numeric_limits<int32_t>::min());\n  CheckAll(std::numeric_limits<int32_t>::min() + 1);\n  CheckAll(999999999);              // fits in 32 bits\n  CheckAll(1000000000);             // fits in 32 bits\n  CheckAll(9999999999);             // doesn't fit in 32 bits\n  CheckAll(10000000000);            // doesn't fit in 32 bits\n  CheckAll(999999999999999999);     // fits in signed 64-bit\n  CheckAll(9999999999999999999u);   // fits in unsigned 64-bit, but not signed.\n  CheckAll(1000000000000000000);    // fits in signed 64-bit\n  CheckAll(10000000000000000000u);  // fits in unsigned 64-bit, but not signed.\n\n  CheckAll(999999999876543210);    // check all decimal digits, signed\n  CheckAll(9999999999876543210u);  // check all decimal digits, unsigned.\n  CheckAll(0x123456789abcdef0);    // check all hex digits\n  CheckAll(0x12345678);\n\n  int8_t minus_one_8bit = -1;\n  EXPECT_EQ(\"ff\", absl::StrCat(absl::Hex(minus_one_8bit)));\n\n  int16_t minus_one_16bit = -1;\n  EXPECT_EQ(\"ffff\", absl::StrCat(absl::Hex(minus_one_16bit)));\n}\n\nTEST(Numbers, TestFunctionsMovedOverFromNumbersMain) {\n  TestFastPrints();\n}\n\nstruct PointStringify {\n  template <typename FormatSink>\n  friend void AbslStringify(FormatSink& sink, const PointStringify& p) {\n    sink.Append(\"(\");\n    sink.Append(absl::StrCat(p.x));\n    sink.Append(\", \");\n    sink.Append(absl::StrCat(p.y));\n    sink.Append(\")\");\n  }\n\n  double x = 10.0;\n  double y = 20.0;\n};\n\nTEST(StrCat, AbslStringifyExample) {\n  PointStringify p;\n  EXPECT_EQ(absl::StrCat(p), \"(10, 20)\");\n  EXPECT_EQ(absl::StrCat(\"a \", p, \" z\"), \"a (10, 20) z\");\n}\n\nstruct PointStringifyUsingFormat {\n  template <typename FormatSink>\n  friend void AbslStringify(FormatSink& sink,\n                            const PointStringifyUsingFormat& p) {\n    absl::Format(&sink, \"(%g, %g)\", p.x, p.y);\n  }\n\n  double x = 10.0;\n  double y = 20.0;\n};\n\nTEST(StrCat, AbslStringifyExampleUsingFormat) {\n  PointStringifyUsingFormat p;\n  EXPECT_EQ(absl::StrCat(p), \"(10, 20)\");\n  EXPECT_EQ(absl::StrCat(\"a \", p, \" z\"), \"a (10, 20) z\");\n}\n\nenum class EnumWithStringify { Many = 0, Choices = 1 };\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, EnumWithStringify e) {\n  absl::Format(&sink, \"%s\", e == EnumWithStringify::Many ? \"Many\" : \"Choices\");\n}\n\nTEST(StrCat, AbslStringifyWithEnum) {\n  const auto e = EnumWithStringify::Choices;\n  EXPECT_EQ(absl::StrCat(e), \"Choices\");\n}\n\ntemplate <typename Integer>\nvoid CheckSingleArgumentIntegerLimits() {\n  Integer max = std::numeric_limits<Integer>::max();\n  Integer min = std::numeric_limits<Integer>::min();\n\n  EXPECT_EQ(absl::StrCat(max), std::to_string(max));\n  EXPECT_EQ(absl::StrCat(min), std::to_string(min));\n}\n\nTEST(StrCat, SingleArgumentLimits) {\n  CheckSingleArgumentIntegerLimits<int32_t>();\n  CheckSingleArgumentIntegerLimits<uint32_t>();\n  CheckSingleArgumentIntegerLimits<int64_t>();\n  CheckSingleArgumentIntegerLimits<uint64_t>();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_format.h",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: str_format.h\n// -----------------------------------------------------------------------------\n//\n// The `str_format` library is a typesafe replacement for the family of\n// `printf()` string formatting routines within the `<cstdio>` standard library\n// header. Like the `printf` family, `str_format` uses a \"format string\" to\n// perform argument substitutions based on types. See the `FormatSpec` section\n// below for format string documentation.\n//\n// Example:\n//\n//   std::string s = absl::StrFormat(\n//                      \"%s %s You have $%d!\", \"Hello\", name, dollars);\n//\n// The library consists of the following basic utilities:\n//\n//   * `absl::StrFormat()`, a type-safe replacement for `std::sprintf()`, to\n//     write a format string to a `string` value.\n//   * `absl::StrAppendFormat()` to append a format string to a `string`\n//   * `absl::StreamFormat()` to more efficiently write a format string to a\n//     stream, such as`std::cout`.\n//   * `absl::PrintF()`, `absl::FPrintF()` and `absl::SNPrintF()` as\n//     drop-in replacements for `std::printf()`, `std::fprintf()` and\n//     `std::snprintf()`.\n//\n//     Note: An `absl::SPrintF()` drop-in replacement is not supported as it\n//     is generally unsafe due to buffer overflows. Use `absl::StrFormat` which\n//     returns the string as output instead of expecting a pre-allocated buffer.\n//\n// Additionally, you can provide a format string (and its associated arguments)\n// using one of the following abstractions:\n//\n//   * A `FormatSpec` class template fully encapsulates a format string and its\n//     type arguments and is usually provided to `str_format` functions as a\n//     variadic argument of type `FormatSpec<Arg...>`. The `FormatSpec<Args...>`\n//     template is evaluated at compile-time, providing type safety.\n//   * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled\n//     format string for a specific set of type(s), and which can be passed\n//     between API boundaries. (The `FormatSpec` type should not be used\n//     directly except as an argument type for wrapper functions.)\n//\n// The `str_format` library provides the ability to output its format strings to\n// arbitrary sink types:\n//\n//   * A generic `Format()` function to write outputs to arbitrary sink types,\n//     which must implement a `FormatRawSink` interface.\n//\n//   * A `FormatUntyped()` function that is similar to `Format()` except it is\n//     loosely typed. `FormatUntyped()` is not a template and does not perform\n//     any compile-time checking of the format string; instead, it returns a\n//     boolean from a runtime check.\n//\n// In addition, the `str_format` library provides extension points for\n// augmenting formatting to new types.  See \"StrFormat Extensions\" below.\n\n#ifndef ABSL_STRINGS_STR_FORMAT_H_\n#define ABSL_STRINGS_STR_FORMAT_H_\n\n#include <cstdint>\n#include <cstdio>\n#include <string>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/internal/str_format/arg.h\"  // IWYU pragma: export\n#include \"absl/strings/internal/str_format/bind.h\"  // IWYU pragma: export\n#include \"absl/strings/internal/str_format/checker.h\"  // IWYU pragma: export\n#include \"absl/strings/internal/str_format/extension.h\"  // IWYU pragma: export\n#include \"absl/strings/internal/str_format/parser.h\"  // IWYU pragma: export\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// UntypedFormatSpec\n//\n// A type-erased class that can be used directly within untyped API entry\n// points. An `UntypedFormatSpec` is specifically used as an argument to\n// `FormatUntyped()`.\n//\n// Example:\n//\n//   absl::UntypedFormatSpec format(\"%d\");\n//   std::string out;\n//   CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)}));\nclass UntypedFormatSpec {\n public:\n  UntypedFormatSpec() = delete;\n  UntypedFormatSpec(const UntypedFormatSpec&) = delete;\n  UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete;\n\n  explicit UntypedFormatSpec(string_view s) : spec_(s) {}\n\n protected:\n  explicit UntypedFormatSpec(\n      const str_format_internal::ParsedFormatBase* absl_nonnull pc)\n      : spec_(pc) {}\n\n private:\n  friend str_format_internal::UntypedFormatSpecImpl;\n  str_format_internal::UntypedFormatSpecImpl spec_;\n};\n\n// FormatStreamed()\n//\n// Takes a streamable argument and returns an object that can print it\n// with '%s'. Allows printing of types that have an `operator<<` but no\n// intrinsic type support within `StrFormat()` itself.\n//\n// Example:\n//\n//   absl::StrFormat(\"%s\", absl::FormatStreamed(obj));\ntemplate <typename T>\nstr_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {\n  return str_format_internal::StreamedWrapper<T>(v);\n}\n\n// FormatCountCapture\n//\n// This class provides a way to safely wrap `StrFormat()` captures of `%n`\n// conversions, which denote the number of characters written by a formatting\n// operation to this point, into an integer value.\n//\n// This wrapper is designed to allow safe usage of `%n` within `StrFormat(); in\n// the `printf()` family of functions, `%n` is not safe to use, as the `int *`\n// buffer can be used to capture arbitrary data.\n//\n// Example:\n//\n//   int n = 0;\n//   std::string s = absl::StrFormat(\"%s%d%n\", \"hello\", 123,\n//                       absl::FormatCountCapture(&n));\n//   EXPECT_EQ(8, n);\nclass FormatCountCapture {\n public:\n  explicit FormatCountCapture(int* absl_nonnull p) : p_(p) {}\n\n private:\n  // FormatCountCaptureHelper is used to define FormatConvertImpl() for this\n  // class.\n  friend struct str_format_internal::FormatCountCaptureHelper;\n  // Unused() is here because of the false positive from -Wunused-private-field\n  // p_ is used in the templated function of the friend FormatCountCaptureHelper\n  // class.\n  int* absl_nonnull Unused() { return p_; }\n  int* absl_nonnull p_;\n};\n\n// FormatSpec\n//\n// The `FormatSpec` type defines the makeup of a format string within the\n// `str_format` library. It is a variadic class template that is evaluated at\n// compile-time, according to the format string and arguments that are passed to\n// it.\n//\n// You should not need to manipulate this type directly. You should only name it\n// if you are writing wrapper functions which accept format arguments that will\n// be provided unmodified to functions in this library. Such a wrapper function\n// might be a class method that provides format arguments and/or internally uses\n// the result of formatting.\n//\n// For a `FormatSpec` to be valid at compile-time, it must be provided as\n// either:\n//\n// * A `constexpr` literal or `absl::string_view`, which is how it is most often\n//   used.\n// * A `ParsedFormat` instantiation, which ensures the format string is\n//   valid before use. (See below.)\n//\n// Example:\n//\n//   // Provided as a string literal.\n//   absl::StrFormat(\"Welcome to %s, Number %d!\", \"The Village\", 6);\n//\n//   // Provided as a constexpr absl::string_view.\n//   constexpr absl::string_view formatString = \"Welcome to %s, Number %d!\";\n//   absl::StrFormat(formatString, \"The Village\", 6);\n//\n//   // Provided as a pre-compiled ParsedFormat object.\n//   // Note that this example is useful only for illustration purposes.\n//   absl::ParsedFormat<'s', 'd'> formatString(\"Welcome to %s, Number %d!\");\n//   absl::StrFormat(formatString, \"TheVillage\", 6);\n//\n// A format string generally follows the POSIX syntax as used within the POSIX\n// `printf` specification. (Exceptions are noted below.)\n//\n// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html)\n//\n// In specific, the `FormatSpec` supports the following type specifiers:\n//   * `c` for characters\n//   * `s` for strings\n//   * `d` or `i` for integers\n//   * `o` for unsigned integer conversions into octal\n//   * `x` or `X` for unsigned integer conversions into hex\n//   * `u` for unsigned integers\n//   * `f` or `F` for floating point values into decimal notation\n//   * `e` or `E` for floating point values into exponential notation\n//   * `a` or `A` for floating point values into hex exponential notation\n//   * `g` or `G` for floating point values into decimal or exponential\n//     notation based on their precision\n//   * `p` for pointer address values\n//   * `n` for the special case of writing out the number of characters\n//     written to this point. The resulting value must be captured within an\n//     `absl::FormatCountCapture` type.\n//   * `v` for values using the default format for a deduced type. These deduced\n//     types include many of the primitive types denoted here as well as\n//     user-defined types containing the proper extensions. (See below for more\n//     information.)\n//\n// Implementation-defined behavior:\n//   * A null pointer provided to \"%s\" or \"%p\" is output as \"(nil)\".\n//   * A non-null pointer provided to \"%p\" is output in hex as if by %#x or\n//     %#lx.\n//\n// NOTE: `o`, `x\\X` and `u` will convert signed values to their unsigned\n// counterpart before formatting.\n//\n// Examples:\n//     \"%c\", 'a'                -> \"a\"\n//     \"%c\", 32                 -> \" \"\n//     \"%s\", \"C\"                -> \"C\"\n//     \"%s\", std::string(\"C++\") -> \"C++\"\n//     \"%d\", -10                -> \"-10\"\n//     \"%o\", 10                 -> \"12\"\n//     \"%x\", 16                 -> \"10\"\n//     \"%f\", 123456789          -> \"123456789.000000\"\n//     \"%e\", .01                -> \"1.00000e-2\"\n//     \"%a\", -3.0               -> \"-0x1.8p+1\"\n//     \"%g\", .01                -> \"1e-2\"\n//     \"%p\", (void*)&value      -> \"0x7ffdeb6ad2a4\"\n//\n//     int n = 0;\n//     std::string s = absl::StrFormat(\n//         \"%s%d%n\", \"hello\", 123, absl::FormatCountCapture(&n));\n//     EXPECT_EQ(8, n);\n//\n// NOTE: the `v` specifier (for \"value\") is a type specifier not present in the\n// POSIX specification. %v will format values according to their deduced type.\n// `v` uses `d` for signed integer values, `u` for unsigned integer values, `g`\n// for floating point values, and formats boolean values as \"true\"/\"false\"\n// (instead of 1 or 0 for booleans formatted using d). `const char*` is not\n// supported; please use `std::string` and `string_view`. `char` is also not\n// supported due to ambiguity of the type. This specifier does not support\n// modifiers.\n//\n// The `FormatSpec` intrinsically supports all of these fundamental C++ types:\n//\n// *   Characters: `char`, `signed char`, `unsigned char`, `wchar_t`\n// *   Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`,\n//         `unsigned long`, `long long`, `unsigned long long`\n// *   Enums: printed as their underlying integral value\n// *   Floating-point: `float`, `double`, `long double`\n//\n// However, in the `str_format` library, a format conversion specifies a broader\n// C++ conceptual category instead of an exact type. For example, `%s` binds to\n// any string-like argument, so `std::string`, `std::wstring`,\n// `absl::string_view`, `const char*`, and `const wchar_t*` are all accepted.\n// Likewise, `%d` accepts any integer-like argument, etc.\n\ntemplate <typename... Args>\nusing FormatSpec = str_format_internal::FormatSpecTemplate<\n    str_format_internal::ArgumentToConv<Args>()...>;\n\n// ParsedFormat\n//\n// A `ParsedFormat` is a class template representing a preparsed `FormatSpec`,\n// with template arguments specifying the conversion characters used within the\n// format string. Such characters must be valid format type specifiers, and\n// these type specifiers are checked at compile-time.\n//\n// Instances of `ParsedFormat` can be created, copied, and reused to speed up\n// formatting loops. A `ParsedFormat` may either be constructed statically, or\n// dynamically through its `New()` factory function, which only constructs a\n// runtime object if the format is valid at that time.\n//\n// Example:\n//\n//   // Verified at compile time.\n//   absl::ParsedFormat<'s', 'd'> format_string(\"Welcome to %s, Number %d!\");\n//   absl::StrFormat(format_string, \"TheVillage\", 6);\n//\n//   // Verified at runtime.\n//   auto format_runtime = absl::ParsedFormat<'d'>::New(format_string);\n//   if (format_runtime) {\n//     value = absl::StrFormat(*format_runtime, i);\n//   } else {\n//     ... error case ...\n//   }\n\n#if defined(__cpp_nontype_template_parameter_auto)\n// If C++17 is available, an 'extended' format is also allowed that can specify\n// multiple conversion characters per format argument, using a combination of\n// `absl::FormatConversionCharSet` enum values (logically a set union)\n//  via the `|` operator. (Single character-based arguments are still accepted,\n// but cannot be combined). Some common conversions also have predefined enum\n// values, such as `absl::FormatConversionCharSet::kIntegral`.\n//\n// Example:\n//   // Extended format supports multiple conversion characters per argument,\n//   // specified via a combination of `FormatConversionCharSet` enums.\n//   using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |\n//                                       absl::FormatConversionCharSet::x>;\n//   MyFormat GetFormat(bool use_hex) {\n//     if (use_hex) return MyFormat(\"foo %x bar\");\n//     return MyFormat(\"foo %d bar\");\n//   }\n//   // `format` can be used with any value that supports 'd' and 'x',\n//   // like `int`.\n//   auto format = GetFormat(use_hex);\n//   value = StringF(format, i);\ntemplate <auto... Conv>\nusing ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<\n    absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;\n#else\ntemplate <char... Conv>\nusing ParsedFormat = str_format_internal::ExtendedParsedFormat<\n    absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;\n#endif  // defined(__cpp_nontype_template_parameter_auto)\n\n// StrFormat()\n//\n// Returns a `string` given a `printf()`-style format string and zero or more\n// additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the\n// primary formatting function within the `str_format` library, and should be\n// used in most cases where you need type-safe conversion of types into\n// formatted strings.\n//\n// The format string generally consists of ordinary character data along with\n// one or more format conversion specifiers (denoted by the `%` character).\n// Ordinary character data is returned unchanged into the result string, while\n// each conversion specification performs a type substitution from\n// `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full\n// information on the makeup of this format string.\n//\n// Example:\n//\n//   std::string s = absl::StrFormat(\n//       \"Welcome to %s, Number %d!\", \"The Village\", 6);\n//   EXPECT_EQ(\"Welcome to The Village, Number 6!\", s);\n//\n// Returns an empty string in case of error.\ntemplate <typename... Args>\n[[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,\n                                    const Args&... args) {\n  return str_format_internal::FormatPack(\n      str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// StrAppendFormat()\n//\n// Appends to a `dst` string given a format string, and zero or more additional\n// arguments, returning `*dst` as a convenience for chaining purposes. Appends\n// nothing in case of error (but possibly alters its capacity).\n//\n// Example:\n//\n//   std::string orig(\"For example PI is approximately \");\n//   std::cout << StrAppendFormat(&orig, \"%12.6f\", 3.14);\ntemplate <typename... Args>\nstd::string& StrAppendFormat(std::string* absl_nonnull dst,\n                             const FormatSpec<Args...>& format,\n                             const Args&... args) {\n  return str_format_internal::AppendPack(\n      dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// StreamFormat()\n//\n// Writes to an output stream given a format string and zero or more arguments,\n// generally in a manner that is more efficient than streaming the result of\n// `absl::StrFormat()`. The returned object must be streamed before the full\n// expression ends.\n//\n// Example:\n//\n//   std::cout << StreamFormat(\"%12.6f\", 3.14);\ntemplate <typename... Args>\n[[nodiscard]] str_format_internal::Streamable StreamFormat(\n    const FormatSpec<Args...>& format, const Args&... args) {\n  return str_format_internal::Streamable(\n      str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// PrintF()\n//\n// Writes to stdout given a format string and zero or more arguments. This\n// function is functionally equivalent to `std::printf()` (and type-safe);\n// prefer `absl::PrintF()` over `std::printf()`.\n//\n// Example:\n//\n//   std::string_view s = \"Ulaanbaatar\";\n//   absl::PrintF(\"The capital of Mongolia is %s\", s);\n//\n//   Outputs: \"The capital of Mongolia is Ulaanbaatar\"\n//\ntemplate <typename... Args>\nint PrintF(const FormatSpec<Args...>& format, const Args&... args) {\n  return str_format_internal::FprintF(\n      stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// FPrintF()\n//\n// Writes to a file given a format string and zero or more arguments. This\n// function is functionally equivalent to `std::fprintf()` (and type-safe);\n// prefer `absl::FPrintF()` over `std::fprintf()`.\n//\n// Example:\n//\n//   std::string_view s = \"Ulaanbaatar\";\n//   absl::FPrintF(stdout, \"The capital of Mongolia is %s\", s);\n//\n//   Outputs: \"The capital of Mongolia is Ulaanbaatar\"\n//\ntemplate <typename... Args>\nint FPrintF(std::FILE* absl_nonnull output, const FormatSpec<Args...>& format,\n            const Args&... args) {\n  return str_format_internal::FprintF(\n      output, str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// SNPrintF()\n//\n// Writes to a sized buffer given a format string and zero or more arguments.\n// This function is functionally equivalent to `std::snprintf()` (and\n// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.\n//\n// In particular, a successful call to `absl::SNPrintF()` writes at most `size`\n// bytes of the formatted output to `output`, including a NUL-terminator, and\n// returns the number of bytes that would have been written if truncation did\n// not occur. In the event of an error, a negative value is returned and `errno`\n// is set.\n//\n// Example:\n//\n//   std::string_view s = \"Ulaanbaatar\";\n//   char output[128];\n//   absl::SNPrintF(output, sizeof(output),\n//                  \"The capital of Mongolia is %s\", s);\n//\n//   Post-condition: output == \"The capital of Mongolia is Ulaanbaatar\"\n//\ntemplate <typename... Args>\nint SNPrintF(char* absl_nonnull output, std::size_t size,\n             const FormatSpec<Args...>& format, const Args&... args) {\n  return str_format_internal::SnprintF(\n      output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// -----------------------------------------------------------------------------\n// Custom Output Formatting Functions\n// -----------------------------------------------------------------------------\n\n// FormatRawSink\n//\n// FormatRawSink is a type erased wrapper around arbitrary sink objects\n// specifically used as an argument to `Format()`.\n//\n// All the object has to do define an overload of `AbslFormatFlush()` for the\n// sink, usually by adding a ADL-based free function in the same namespace as\n// the sink:\n//\n//   void AbslFormatFlush(MySink* dest, absl::string_view part);\n//\n// where `dest` is the pointer passed to `absl::Format()`. The function should\n// append `part` to `dest`.\n//\n// FormatRawSink does not own the passed sink object. The passed object must\n// outlive the FormatRawSink.\nclass FormatRawSink {\n public:\n  // Implicitly convert from any type that provides the hook function as\n  // described above.\n  template <typename T,\n            typename = typename std::enable_if<std::is_constructible<\n                str_format_internal::FormatRawSinkImpl, T*>::value>::type>\n  FormatRawSink(T* absl_nonnull raw)  // NOLINT\n      : sink_(raw) {}\n\n private:\n  friend str_format_internal::FormatRawSinkImpl;\n  str_format_internal::FormatRawSinkImpl sink_;\n};\n\n// Format()\n//\n// Writes a formatted string to an arbitrary sink object (implementing the\n// `absl::FormatRawSink` interface), using a format string and zero or more\n// additional arguments.\n//\n// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as\n// destination objects. If a `std::string` is used the formatted string is\n// appended to it.\n//\n// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for\n// custom sinks. The format string, like format strings for `StrFormat()`, is\n// checked at compile-time.\n//\n// On failure, this function returns `false` and the state of the sink is\n// unspecified.\ntemplate <typename... Args>\nbool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,\n            const Args&... args) {\n  return str_format_internal::FormatUntyped(\n      str_format_internal::FormatRawSinkImpl::Extract(raw_sink),\n      str_format_internal::UntypedFormatSpecImpl::Extract(format),\n      {str_format_internal::FormatArgImpl(args)...});\n}\n\n// FormatArg\n//\n// A type-erased handle to a format argument specifically used as an argument to\n// `FormatUntyped()`. You may construct `FormatArg` by passing\n// reference-to-const of any printable type. `FormatArg` is both copyable and\n// assignable. The source data must outlive the `FormatArg` instance. See\n// example below.\n//\nusing FormatArg = str_format_internal::FormatArgImpl;\n\n// FormatUntyped()\n//\n// Writes a formatted string to an arbitrary sink object (implementing the\n// `absl::FormatRawSink` interface), using an `UntypedFormatSpec` and zero or\n// more additional arguments.\n//\n// This function acts as the most generic formatting function in the\n// `str_format` library. The caller provides a raw sink, an unchecked format\n// string, and (usually) a runtime specified list of arguments; no compile-time\n// checking of formatting is performed within this function. As a result, a\n// caller should check the return value to verify that no error occurred.\n// On failure, this function returns `false` and the state of the sink is\n// unspecified.\n//\n// The arguments are provided in an `absl::Span<const absl::FormatArg>`.\n// Each `absl::FormatArg` object binds to a single argument and keeps a\n// reference to it. The values used to create the `FormatArg` objects must\n// outlive this function call.\n//\n// Example:\n//\n//   std::optional<std::string> FormatDynamic(\n//       const std::string& in_format,\n//       const vector<std::string>& in_args) {\n//     std::string out;\n//     std::vector<absl::FormatArg> args;\n//     for (const auto& v : in_args) {\n//       // It is important that 'v' is a reference to the objects in in_args.\n//       // The values we pass to FormatArg must outlive the call to\n//       // FormatUntyped.\n//       args.emplace_back(v);\n//     }\n//     absl::UntypedFormatSpec format(in_format);\n//     if (!absl::FormatUntyped(&out, format, args)) {\n//       return std::nullopt;\n//     }\n//     return std::move(out);\n//   }\n//\n[[nodiscard]] inline bool FormatUntyped(FormatRawSink raw_sink,\n                                        const UntypedFormatSpec& format,\n                                        absl::Span<const FormatArg> args) {\n  return str_format_internal::FormatUntyped(\n      str_format_internal::FormatRawSinkImpl::Extract(raw_sink),\n      str_format_internal::UntypedFormatSpecImpl::Extract(format), args);\n}\n\n//------------------------------------------------------------------------------\n// StrFormat Extensions\n//------------------------------------------------------------------------------\n//\n// AbslStringify()\n//\n// A simpler customization API for formatting user-defined types using\n// absl::StrFormat(). The API relies on detecting an overload in the\n// user-defined type's namespace of a free (non-member) `AbslStringify()`\n// function as a friend definition with the following signature:\n//\n// template <typename Sink>\n// void AbslStringify(Sink& sink, const X& value);\n//\n// An `AbslStringify()` overload for a type should only be declared in the same\n// file and namespace as said type.\n//\n// Note that unlike with AbslFormatConvert(), AbslStringify() does not allow\n// customization of allowed conversion characters. AbslStringify() uses `%v` as\n// the underlying conversion specifier. Additionally, AbslStringify() supports\n// use with absl::StrCat while AbslFormatConvert() does not.\n//\n// Example:\n//\n// struct Point {\n//   // To add formatting support to `Point`, we simply need to add a free\n//   // (non-member) function `AbslStringify()`. This method prints in the\n//   // request format using the underlying `%v` specifier. You can add such a\n//   // free function using a friend declaration within the body of the class.\n//   // The sink parameter is a templated type to avoid requiring dependencies.\n//   template <typename Sink>\n//   friend void AbslStringify(Sink& sink, const Point& p) {\n//     absl::Format(&sink, \"(%v, %v)\", p.x, p.y);\n//   }\n//\n//   int x;\n//   int y;\n// };\n//\n// AbslFormatConvert()\n//\n// The StrFormat library provides a customization API for formatting\n// user-defined types using absl::StrFormat(). The API relies on detecting an\n// overload in the user-defined type's namespace of a free (non-member)\n// `AbslFormatConvert()` function, usually as a friend definition with the\n// following signature:\n//\n// absl::FormatConvertResult<...> AbslFormatConvert(\n//     const X& value,\n//     const absl::FormatConversionSpec& spec,\n//     absl::FormatSink *sink);\n//\n// An `AbslFormatConvert()` overload for a type should only be declared in the\n// same file and namespace as said type.\n//\n// The abstractions within this definition include:\n//\n// * An `absl::FormatConversionSpec` to specify the fields to pull from a\n//   user-defined type's format string\n// * An `absl::FormatSink` to hold the converted string data during the\n//   conversion process.\n// * An `absl::FormatConvertResult` to hold the status of the returned\n//   formatting operation\n//\n// The return type encodes all the conversion characters that your\n// AbslFormatConvert() routine accepts.  The return value should be {true}.\n// A return value of {false} will result in `StrFormat()` returning\n// an empty string.  This result will be propagated to the result of\n// `FormatUntyped`.\n//\n// Example:\n//\n// struct Point {\n//   // To add formatting support to `Point`, we simply need to add a free\n//   // (non-member) function `AbslFormatConvert()`.  This method interprets\n//   // `spec` to print in the request format. The allowed conversion characters\n//   // can be restricted via the type of the result, in this example\n//   // string and integral formatting are allowed (but not, for instance\n//   // floating point characters like \"%f\").  You can add such a free function\n//   // using a friend declaration within the body of the class:\n//   friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |\n//                                    absl::FormatConversionCharSet::kIntegral>\n//   AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,\n//                     absl::FormatSink* s) {\n//     if (spec.conversion_char() == absl::FormatConversionChar::s) {\n//       absl::Format(s, \"x=%vy=%v\", p.x, p.y);\n//     } else {\n//       absl::Format(s, \"%v,%v\", p.x, p.y);\n//     }\n//     return {true};\n//   }\n//\n//   int x;\n//   int y;\n// };\n\n// clang-format off\n\n// FormatConversionChar\n//\n// Specifies the formatting character provided in the format string\n// passed to `StrFormat()`.\nenum class FormatConversionChar : uint8_t {\n  c, s,                    // text\n  d, i, o, u, x, X,        // int\n  f, F, e, E, g, G, a, A,  // float\n  n, p, v                  // misc\n};\n// clang-format on\n\n// FormatConversionSpec\n//\n// Specifies modifications to the conversion of the format string, through use\n// of one or more format flags in the source format string.\nclass FormatConversionSpec {\n public:\n  // FormatConversionSpec::is_basic()\n  //\n  // Indicates that width and precision are not specified, and no additional\n  // flags are set for this conversion character in the format string.\n  bool is_basic() const { return impl_.is_basic(); }\n\n  // FormatConversionSpec::has_left_flag()\n  //\n  // Indicates whether the result should be left justified for this conversion\n  // character in the format string. This flag is set through use of a '-'\n  // character in the format string. E.g. \"%-s\"\n  bool has_left_flag() const { return impl_.has_left_flag(); }\n\n  // FormatConversionSpec::has_show_pos_flag()\n  //\n  // Indicates whether a sign column is prepended to the result for this\n  // conversion character in the format string, even if the result is positive.\n  // This flag is set through use of a '+' character in the format string.\n  // E.g. \"%+d\"\n  bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }\n\n  // FormatConversionSpec::has_sign_col_flag()\n  //\n  // Indicates whether a mandatory sign column is added to the result for this\n  // conversion character. This flag is set through use of a space character\n  // (' ') in the format string. E.g. \"% i\"\n  bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }\n\n  // FormatConversionSpec::has_alt_flag()\n  //\n  // Indicates whether an \"alternate\" format is applied to the result for this\n  // conversion character. Alternative forms depend on the type of conversion\n  // character, and unallowed alternatives are undefined. This flag is set\n  // through use of a '#' character in the format string. E.g. \"%#h\"\n  bool has_alt_flag() const { return impl_.has_alt_flag(); }\n\n  // FormatConversionSpec::has_zero_flag()\n  //\n  // Indicates whether zeroes should be prepended to the result for this\n  // conversion character instead of spaces. This flag is set through use of the\n  // '0' character in the format string. E.g. \"%0f\"\n  bool has_zero_flag() const { return impl_.has_zero_flag(); }\n\n  // FormatConversionSpec::conversion_char()\n  //\n  // Returns the underlying conversion character.\n  FormatConversionChar conversion_char() const {\n    return impl_.conversion_char();\n  }\n\n  // FormatConversionSpec::width()\n  //\n  // Returns the specified width (indicated through use of a non-zero integer\n  // value or '*' character) of the conversion character. If width is\n  // unspecified, it returns a negative value.\n  int width() const { return impl_.width(); }\n\n  // FormatConversionSpec::precision()\n  //\n  // Returns the specified precision (through use of the '.' character followed\n  // by a non-zero integer value or '*' character) of the conversion character.\n  // If precision is unspecified, it returns a negative value.\n  int precision() const { return impl_.precision(); }\n\n private:\n  explicit FormatConversionSpec(\n      str_format_internal::FormatConversionSpecImpl impl)\n      : impl_(impl) {}\n\n  friend str_format_internal::FormatConversionSpecImpl;\n\n  absl::str_format_internal::FormatConversionSpecImpl impl_;\n};\n\n// Type safe OR operator for FormatConversionCharSet to allow accepting multiple\n// conversion chars in custom format converters.\nconstexpr FormatConversionCharSet operator|(FormatConversionCharSet a,\n                                            FormatConversionCharSet b) {\n  return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |\n                                              static_cast<uint64_t>(b));\n}\n\n// FormatConversionCharSet\n//\n// Specifies the _accepted_ conversion types as a template parameter to\n// FormatConvertResult for custom implementations of `AbslFormatConvert`.\n// Note the helper predefined alias definitions (kIntegral, etc.) below.\nenum class FormatConversionCharSet : uint64_t {\n  // text\n  c = str_format_internal::FormatConversionCharToConvInt('c'),\n  s = str_format_internal::FormatConversionCharToConvInt('s'),\n  // integer\n  d = str_format_internal::FormatConversionCharToConvInt('d'),\n  i = str_format_internal::FormatConversionCharToConvInt('i'),\n  o = str_format_internal::FormatConversionCharToConvInt('o'),\n  u = str_format_internal::FormatConversionCharToConvInt('u'),\n  x = str_format_internal::FormatConversionCharToConvInt('x'),\n  X = str_format_internal::FormatConversionCharToConvInt('X'),\n  // Float\n  f = str_format_internal::FormatConversionCharToConvInt('f'),\n  F = str_format_internal::FormatConversionCharToConvInt('F'),\n  e = str_format_internal::FormatConversionCharToConvInt('e'),\n  E = str_format_internal::FormatConversionCharToConvInt('E'),\n  g = str_format_internal::FormatConversionCharToConvInt('g'),\n  G = str_format_internal::FormatConversionCharToConvInt('G'),\n  a = str_format_internal::FormatConversionCharToConvInt('a'),\n  A = str_format_internal::FormatConversionCharToConvInt('A'),\n  // misc\n  n = str_format_internal::FormatConversionCharToConvInt('n'),\n  p = str_format_internal::FormatConversionCharToConvInt('p'),\n  v = str_format_internal::FormatConversionCharToConvInt('v'),\n\n  // Used for width/precision '*' specification.\n  kStar = static_cast<uint64_t>(\n      absl::str_format_internal::FormatConversionCharSetInternal::kStar),\n  // Some predefined values:\n  kIntegral = d | i | u | o | x | X,\n  kFloating = a | e | f | g | A | E | F | G,\n  kNumeric = kIntegral | kFloating,\n  kString = s,\n  kPointer = p,\n};\n\n// FormatSink\n//\n// A format sink is a generic abstraction to which conversions may write their\n// formatted string data. `absl::FormatConvert()` uses this sink to write its\n// formatted string.\n//\nclass FormatSink {\n public:\n  // FormatSink::Append()\n  //\n  // Appends `count` copies of `ch` to the format sink.\n  void Append(size_t count, char ch) { sink_->Append(count, ch); }\n\n  // Overload of FormatSink::Append() for appending the characters of a string\n  // view to a format sink.\n  void Append(string_view v) { sink_->Append(v); }\n\n  // FormatSink::PutPaddedString()\n  //\n  // Appends `precision` number of bytes of `v` to the format sink. If this is\n  // less than `width`, spaces will be appended first (if `left` is false), or\n  // after (if `left` is true) to ensure the total amount appended is\n  // at least `width`.\n  bool PutPaddedString(string_view v, int width, int precision, bool left) {\n    return sink_->PutPaddedString(v, width, precision, left);\n  }\n\n  // Support `absl::Format(&sink, format, args...)`.\n  friend void AbslFormatFlush(FormatSink* absl_nonnull sink,\n                              absl::string_view v) {\n    sink->Append(v);\n  }\n\n private:\n  friend str_format_internal::FormatSinkImpl;\n  explicit FormatSink(str_format_internal::FormatSinkImpl* absl_nonnull s)\n      : sink_(s) {}\n  str_format_internal::FormatSinkImpl* absl_nonnull sink_;\n};\n\n// FormatConvertResult\n//\n// Indicates whether a call to AbslFormatConvert() was successful.\n// This return type informs the StrFormat extension framework (through\n// ADL but using the return type) of what conversion characters are supported.\n// It is strongly discouraged to return {false}, as this will result in an\n// empty string in StrFormat.\ntemplate <FormatConversionCharSet C>\nstruct FormatConvertResult {\n  bool value;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STR_FORMAT_H_\n"
  },
  {
    "path": "absl/strings/str_format_test.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/str_format.h\"\n\n#include <cerrno>\n#include <cstdarg>\n#include <cstdint>\n#include <cstdio>\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/cord.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\nusing str_format_internal::FormatArgImpl;\n\nusing FormatEntryPointTest = ::testing::Test;\n\nTEST_F(FormatEntryPointTest, Format) {\n  std::string sink;\n  EXPECT_TRUE(Format(&sink, \"A format %d\", 123));\n  EXPECT_EQ(\"A format 123\", sink);\n  sink.clear();\n\n  ParsedFormat<'d'> pc(\"A format %d\");\n  EXPECT_TRUE(Format(&sink, pc, 123));\n  EXPECT_EQ(\"A format 123\", sink);\n}\n\nTEST_F(FormatEntryPointTest, FormatWithV) {\n  std::string sink;\n  EXPECT_TRUE(Format(&sink, \"A format %v\", 123));\n  EXPECT_EQ(\"A format 123\", sink);\n  sink.clear();\n\n  ParsedFormat<'v'> pc(\"A format %v\");\n  EXPECT_TRUE(Format(&sink, pc, 123));\n  EXPECT_EQ(\"A format 123\", sink);\n}\n\nTEST_F(FormatEntryPointTest, UntypedFormat) {\n  constexpr const char* formats[] = {\n    \"\",\n    \"a\",\n    \"%80d\",\n#if !defined(_MSC_VER) && !defined(__ANDROID__)\n    // MSVC and Android don't support positional syntax.\n    \"complicated multipart %% %1$d format %1$0999d\",\n#endif  // _MSC_VER\n  };\n  for (const char* fmt : formats) {\n    std::string actual;\n    int i = 123;\n    FormatArgImpl arg_123(i);\n    absl::Span<const FormatArgImpl> args(&arg_123, 1);\n    UntypedFormatSpec format(fmt);\n\n    EXPECT_TRUE(FormatUntyped(&actual, format, args));\n    char buf[4096]{};\n    snprintf(buf, sizeof(buf), fmt, 123);\n    EXPECT_EQ(\n        str_format_internal::FormatPack(\n            str_format_internal::UntypedFormatSpecImpl::Extract(format), args),\n        buf);\n    EXPECT_EQ(actual, buf);\n  }\n  // The internal version works with a preparsed format.\n  ParsedFormat<'d'> pc(\"A format %d\");\n  int i = 345;\n  FormatArg arg(i);\n  std::string out;\n  EXPECT_TRUE(str_format_internal::FormatUntyped(\n      &out, str_format_internal::UntypedFormatSpecImpl(&pc), {&arg, 1}));\n  EXPECT_EQ(\"A format 345\", out);\n}\n\nTEST_F(FormatEntryPointTest, StringFormat) {\n  EXPECT_EQ(\"123\", StrFormat(\"%d\", 123));\n  constexpr absl::string_view view(\"=%d=\", 4);\n  EXPECT_EQ(\"=123=\", StrFormat(view, 123));\n}\n\nTEST_F(FormatEntryPointTest, StringFormatV) {\n  std::string hello = \"hello\";\n  EXPECT_EQ(\"hello\", StrFormat(\"%v\", hello));\n  EXPECT_EQ(\"123\", StrFormat(\"%v\", 123));\n  constexpr absl::string_view view(\"=%v=\", 4);\n  EXPECT_EQ(\"=123=\", StrFormat(view, 123));\n}\n\nTEST_F(FormatEntryPointTest, AppendFormat) {\n  std::string s;\n  std::string& r = StrAppendFormat(&s, \"%d\", 123);\n  EXPECT_EQ(&s, &r);  // should be same object\n  EXPECT_EQ(\"123\", r);\n}\n\nTEST_F(FormatEntryPointTest, AppendFormatWithV) {\n  std::string s;\n  std::string& r = StrAppendFormat(&s, \"%v\", 123);\n  EXPECT_EQ(&s, &r);  // should be same object\n  EXPECT_EQ(\"123\", r);\n}\n\nTEST_F(FormatEntryPointTest, AppendFormatFail) {\n  std::string s = \"orig\";\n\n  UntypedFormatSpec format(\" more %d\");\n  FormatArgImpl arg(\"not an int\");\n\n  EXPECT_EQ(\"orig\",\n            str_format_internal::AppendPack(\n                &s, str_format_internal::UntypedFormatSpecImpl::Extract(format),\n                {&arg, 1}));\n}\n\nTEST_F(FormatEntryPointTest, AppendFormatFailWithV) {\n  std::string s = \"orig\";\n\n  UntypedFormatSpec format(\" more %v\");\n  FormatArgImpl arg(\"not an int\");\n\n  EXPECT_EQ(\"orig\",\n            str_format_internal::AppendPack(\n                &s, str_format_internal::UntypedFormatSpecImpl::Extract(format),\n                {&arg, 1}));\n}\n\nTEST_F(FormatEntryPointTest, ManyArgs) {\n  EXPECT_EQ(\n      \"60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 \"\n      \"36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 \"\n      \"12 11 10 9 8 7 6 5 4 3 2 1\",\n      StrFormat(\"%60$d %59$d %58$d %57$d %56$d %55$d %54$d %53$d %52$d %51$d \"\n                \"%50$d %49$d %48$d %47$d %46$d %45$d %44$d %43$d %42$d %41$d \"\n                \"%40$d %39$d %38$d %37$d %36$d %35$d %34$d %33$d %32$d %31$d \"\n                \"%30$d %29$d %28$d %27$d %26$d %25$d %24$d %23$d %22$d %21$d \"\n                \"%20$d %19$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d \"\n                \"%10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d\",\n                1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,\n                19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,\n                35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,\n                51, 52, 53, 54, 55, 56, 57, 58, 59, 60));\n}\n\nTEST_F(FormatEntryPointTest, Preparsed) {\n  ParsedFormat<'d'> pc(\"%d\");\n  EXPECT_EQ(\"123\", StrFormat(pc, 123));\n  // rvalue ok?\n  EXPECT_EQ(\"123\", StrFormat(ParsedFormat<'d'>(\"%d\"), 123));\n  constexpr absl::string_view view(\"=%d=\", 4);\n  EXPECT_EQ(\"=123=\", StrFormat(ParsedFormat<'d'>(view), 123));\n}\n\nTEST_F(FormatEntryPointTest, PreparsedWithV) {\n  ParsedFormat<'v'> pc(\"%v\");\n  EXPECT_EQ(\"123\", StrFormat(pc, 123));\n  // rvalue ok?\n  EXPECT_EQ(\"123\", StrFormat(ParsedFormat<'v'>(\"%v\"), 123));\n  constexpr absl::string_view view(\"=%v=\", 4);\n  EXPECT_EQ(\"=123=\", StrFormat(ParsedFormat<'v'>(view), 123));\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCapture) {\n  int n = 0;\n  EXPECT_EQ(\"\", StrFormat(\"%n\", FormatCountCapture(&n)));\n  EXPECT_EQ(0, n);\n  EXPECT_EQ(\"123\", StrFormat(\"%d%n\", 123, FormatCountCapture(&n)));\n  EXPECT_EQ(3, n);\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCaptureWithV) {\n  int n = 0;\n  EXPECT_EQ(\"\", StrFormat(\"%n\", FormatCountCapture(&n)));\n  EXPECT_EQ(0, n);\n  EXPECT_EQ(\"123\", StrFormat(\"%v%n\", 123, FormatCountCapture(&n)));\n  EXPECT_EQ(3, n);\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) {\n  // Should reject int*.\n  int n = 0;\n  UntypedFormatSpec format(\"%d%n\");\n  int i = 123, *ip = &n;\n  FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};\n\n  EXPECT_EQ(\"\", str_format_internal::FormatPack(\n                    str_format_internal::UntypedFormatSpecImpl::Extract(format),\n                    absl::MakeSpan(args)));\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCaptureWrongTypeWithV) {\n  // Should reject int*.\n  int n = 0;\n  UntypedFormatSpec format(\"%v%n\");\n  int i = 123, *ip = &n;\n  FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};\n\n  EXPECT_EQ(\"\", str_format_internal::FormatPack(\n                    str_format_internal::UntypedFormatSpecImpl::Extract(format),\n                    absl::MakeSpan(args)));\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) {\n  int n1 = 0;\n  int n2 = 0;\n  EXPECT_EQ(\"    1         2\",\n            StrFormat(\"%5d%n%10d%n\", 1, FormatCountCapture(&n1), 2,\n                      FormatCountCapture(&n2)));\n  EXPECT_EQ(5, n1);\n  EXPECT_EQ(15, n2);\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCaptureExample) {\n  int n;\n  std::string s;\n  StrAppendFormat(&s, \"%s: %n%s\\n\", \"(1,1)\", FormatCountCapture(&n), \"(1,2)\");\n  StrAppendFormat(&s, \"%*s%s\\n\", n, \"\", \"(2,2)\");\n  EXPECT_EQ(7, n);\n  EXPECT_EQ(\n      \"(1,1): (1,2)\\n\"\n      \"       (2,2)\\n\",\n      s);\n}\n\nTEST_F(FormatEntryPointTest, FormatCountCaptureExampleWithV) {\n  int n;\n  std::string s;\n  std::string a1 = \"(1,1)\";\n  std::string a2 = \"(1,2)\";\n  std::string a3 = \"(2,2)\";\n  StrAppendFormat(&s, \"%v: %n%v\\n\", a1, FormatCountCapture(&n), a2);\n  StrAppendFormat(&s, \"%*s%v\\n\", n, \"\", a3);\n  EXPECT_EQ(7, n);\n  EXPECT_EQ(\n      \"(1,1): (1,2)\\n\"\n      \"       (2,2)\\n\",\n      s);\n}\n\nTEST_F(FormatEntryPointTest, Stream) {\n  const std::string formats[] = {\n    \"\",\n    \"a\",\n    \"%80d\",\n    \"%d %u %c %s %f %g\",\n#if !defined(_MSC_VER) && !defined(__ANDROID__)\n    // MSVC and Android don't support positional syntax.\n    \"complicated multipart %% %1$d format %1$080d\",\n#endif  // _MSC_VER\n  };\n  std::string buf(4096, '\\0');\n  for (const auto& fmt : formats) {\n    const auto parsed =\n        ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt);\n    std::ostringstream oss;\n    oss << StreamFormat(*parsed, 123, 3, 49, \"multistreaming!!!\", 1.01, 1.01);\n    int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(),  //\n                              123, 3, 49, \"multistreaming!!!\", 1.01, 1.01);\n    ASSERT_TRUE(oss) << fmt;\n    ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())\n        << fmt_result;\n    EXPECT_EQ(buf.c_str(), oss.str());\n  }\n}\n\nTEST_F(FormatEntryPointTest, StreamWithV) {\n  const std::string formats[] = {\n      \"\",\n      \"a\",\n      \"%v %u %c %v %f %v\",\n  };\n\n  const std::string formats_for_buf[] = {\n      \"\",\n      \"a\",\n      \"%d %u %c %s %f %g\",\n  };\n\n  std::string buf(4096, '\\0');\n  for (auto i = 0; i < ABSL_ARRAYSIZE(formats); ++i) {\n    const auto parsed =\n        ParsedFormat<'v', 'u', 'c', 'v', 'f', 'v'>::NewAllowIgnored(formats[i]);\n    std::ostringstream oss;\n    oss << StreamFormat(*parsed, 123, 3, 49,\n                        absl::string_view(\"multistreaming!!!\"), 1.01, 1.01);\n    int fmt_result =\n        snprintf(&*buf.begin(), buf.size(), formats_for_buf[i].c_str(),  //\n                 123, 3, 49, \"multistreaming!!!\", 1.01, 1.01);\n    ASSERT_TRUE(oss) << formats[i];\n    ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())\n        << fmt_result;\n    EXPECT_EQ(buf.c_str(), oss.str());\n  }\n}\n\nTEST_F(FormatEntryPointTest, StreamOk) {\n  std::ostringstream oss;\n  oss << StreamFormat(\"hello %d\", 123);\n  EXPECT_EQ(\"hello 123\", oss.str());\n  EXPECT_TRUE(oss.good());\n}\n\nTEST_F(FormatEntryPointTest, StreamOkWithV) {\n  std::ostringstream oss;\n  oss << StreamFormat(\"hello %v\", 123);\n  EXPECT_EQ(\"hello 123\", oss.str());\n  EXPECT_TRUE(oss.good());\n}\n\nTEST_F(FormatEntryPointTest, StreamFail) {\n  std::ostringstream oss;\n  UntypedFormatSpec format(\"hello %d\");\n  FormatArgImpl arg(\"non-numeric\");\n  oss << str_format_internal::Streamable(\n      str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1});\n  EXPECT_EQ(\"hello \", oss.str());  // partial write\n  EXPECT_TRUE(oss.fail());\n}\n\nTEST_F(FormatEntryPointTest, StreamFailWithV) {\n  std::ostringstream oss;\n  UntypedFormatSpec format(\"hello %v\");\n  FormatArgImpl arg(\"non-numeric\");\n  oss << str_format_internal::Streamable(\n      str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1});\n  EXPECT_EQ(\"hello \", oss.str());  // partial write\n  EXPECT_TRUE(oss.fail());\n}\n\nstd::string WithSnprintf(const char* fmt, ...) {\n  std::string buf;\n  buf.resize(128);\n  va_list va;\n  va_start(va, fmt);\n  int r = vsnprintf(&*buf.begin(), buf.size(), fmt, va);\n  va_end(va);\n  EXPECT_GE(r, 0);\n  EXPECT_LT(r, buf.size());\n  buf.resize(r);\n  return buf;\n}\n\nTEST_F(FormatEntryPointTest, FloatPrecisionArg) {\n  // Test that positional parameters for width and precision\n  // are indexed to precede the value.\n  // Also sanity check the same formats against snprintf.\n  EXPECT_EQ(\"0.1\", StrFormat(\"%.1f\", 0.1));\n  EXPECT_EQ(\"0.1\", WithSnprintf(\"%.1f\", 0.1));\n  EXPECT_EQ(\"  0.1\", StrFormat(\"%*.1f\", 5, 0.1));\n  EXPECT_EQ(\"  0.1\", WithSnprintf(\"%*.1f\", 5, 0.1));\n  EXPECT_EQ(\"0.1\", StrFormat(\"%.*f\", 1, 0.1));\n  EXPECT_EQ(\"0.1\", WithSnprintf(\"%.*f\", 1, 0.1));\n  EXPECT_EQ(\"  0.1\", StrFormat(\"%*.*f\", 5, 1, 0.1));\n  EXPECT_EQ(\"  0.1\", WithSnprintf(\"%*.*f\", 5, 1, 0.1));\n}\nnamespace streamed_test {\nstruct X {};\nstd::ostream& operator<<(std::ostream& os, const X&) {\n  return os << \"X\";\n}\n}  // streamed_test\n\nTEST_F(FormatEntryPointTest, FormatStreamed) {\n  EXPECT_EQ(\"123\", StrFormat(\"%s\", FormatStreamed(123)));\n  EXPECT_EQ(\"  123\", StrFormat(\"%5s\", FormatStreamed(123)));\n  EXPECT_EQ(\"123  \", StrFormat(\"%-5s\", FormatStreamed(123)));\n  EXPECT_EQ(\"X\", StrFormat(\"%s\", FormatStreamed(streamed_test::X())));\n  EXPECT_EQ(\"123\", StrFormat(\"%s\", FormatStreamed(StreamFormat(\"%d\", 123))));\n}\n\nTEST_F(FormatEntryPointTest, FormatStreamedWithV) {\n  EXPECT_EQ(\"123\", StrFormat(\"%v\", FormatStreamed(123)));\n  EXPECT_EQ(\"X\", StrFormat(\"%v\", FormatStreamed(streamed_test::X())));\n  EXPECT_EQ(\"123\", StrFormat(\"%v\", FormatStreamed(StreamFormat(\"%d\", 123))));\n}\n\n// Helper class that creates a temporary file and exposes a FILE* to it.\n// It will close the file on destruction.\nclass TempFile {\n public:\n  TempFile() : file_(std::tmpfile()) {}\n  ~TempFile() { std::fclose(file_); }\n\n  std::FILE* file() const { return file_; }\n\n  // Read the file into a string.\n  std::string ReadFile() {\n    std::fseek(file_, 0, SEEK_END);\n    int size = std::ftell(file_);\n    EXPECT_GT(size, 0);\n    std::rewind(file_);\n    std::string str(2 * size, ' ');\n    int read_bytes = std::fread(&str[0], 1, str.size(), file_);\n    EXPECT_EQ(read_bytes, size);\n    str.resize(read_bytes);\n    EXPECT_TRUE(std::feof(file_));\n    return str;\n  }\n\n private:\n  std::FILE* file_;\n};\n\nTEST_F(FormatEntryPointTest, FPrintF) {\n  TempFile tmp;\n  int result =\n      FPrintF(tmp.file(), \"STRING: %s NUMBER: %010d\", std::string(\"ABC\"), -19);\n  EXPECT_EQ(result, 30);\n  EXPECT_EQ(tmp.ReadFile(), \"STRING: ABC NUMBER: -000000019\");\n}\n\nTEST_F(FormatEntryPointTest, FPrintFWithV) {\n  TempFile tmp;\n  int result =\n      FPrintF(tmp.file(), \"STRING: %v NUMBER: %010d\", std::string(\"ABC\"), -19);\n  EXPECT_EQ(result, 30);\n  EXPECT_EQ(tmp.ReadFile(), \"STRING: ABC NUMBER: -000000019\");\n}\n\nTEST_F(FormatEntryPointTest, FPrintFError) {\n  errno = 0;\n  int result = FPrintF(stdin, \"ABC\");\n  EXPECT_LT(result, 0);\n  EXPECT_EQ(errno, EBADF);\n}\n\n#ifdef __GLIBC__\nTEST_F(FormatEntryPointTest, FprintfTooLarge) {\n  std::FILE* f = std::fopen(\"/dev/null\", \"w\");\n  int width = 2000000000;\n  errno = 0;\n  int result = FPrintF(f, \"%*d %*d\", width, 0, width, 0);\n  EXPECT_LT(result, 0);\n  EXPECT_EQ(errno, EFBIG);\n  std::fclose(f);\n}\n\nTEST_F(FormatEntryPointTest, PrintF) {\n  int stdout_tmp = dup(STDOUT_FILENO);\n\n  TempFile tmp;\n  std::fflush(stdout);\n  dup2(fileno(tmp.file()), STDOUT_FILENO);\n\n  int result = PrintF(\"STRING: %s NUMBER: %010d\", std::string(\"ABC\"), -19);\n\n  std::fflush(stdout);\n  dup2(stdout_tmp, STDOUT_FILENO);\n  close(stdout_tmp);\n\n  EXPECT_EQ(result, 30);\n  EXPECT_EQ(tmp.ReadFile(), \"STRING: ABC NUMBER: -000000019\");\n}\n\nTEST_F(FormatEntryPointTest, PrintFWithV) {\n  int stdout_tmp = dup(STDOUT_FILENO);\n\n  TempFile tmp;\n  std::fflush(stdout);\n  dup2(fileno(tmp.file()), STDOUT_FILENO);\n\n  int result = PrintF(\"STRING: %v NUMBER: %010d\", std::string(\"ABC\"), -19);\n\n  std::fflush(stdout);\n  dup2(stdout_tmp, STDOUT_FILENO);\n  close(stdout_tmp);\n\n  EXPECT_EQ(result, 30);\n  EXPECT_EQ(tmp.ReadFile(), \"STRING: ABC NUMBER: -000000019\");\n}\n#endif  // __GLIBC__\n\nTEST_F(FormatEntryPointTest, SNPrintF) {\n  char buffer[16];\n  int result =\n      SNPrintF(buffer, sizeof(buffer), \"STRING: %s\", std::string(\"ABC\"));\n  EXPECT_EQ(result, 11);\n  EXPECT_EQ(std::string(buffer), \"STRING: ABC\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %d\", 123456);\n  EXPECT_EQ(result, 14);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 123456\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %d\", 1234567);\n  EXPECT_EQ(result, 15);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 1234567\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %d\", 12345678);\n  EXPECT_EQ(result, 16);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 1234567\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %d\", 123456789);\n  EXPECT_EQ(result, 17);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 1234567\");\n\n  // Test that the buffer is never written to if the size is zero.\n  buffer[0] = '\\0';\n  result = SNPrintF(buffer, 0, \"Just checking the %s of the output.\", \"size\");\n  EXPECT_EQ(result, 37);\n  EXPECT_EQ(buffer[0], '\\0');\n}\n\nTEST_F(FormatEntryPointTest, SNPrintFWithV) {\n  char buffer[16];\n  int result =\n      SNPrintF(buffer, sizeof(buffer), \"STRING: %v\", std::string(\"ABC\"));\n  EXPECT_EQ(result, 11);\n  EXPECT_EQ(std::string(buffer), \"STRING: ABC\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %v\", 123456);\n  EXPECT_EQ(result, 14);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 123456\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %v\", 1234567);\n  EXPECT_EQ(result, 15);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 1234567\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %v\", 12345678);\n  EXPECT_EQ(result, 16);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 1234567\");\n\n  result = SNPrintF(buffer, sizeof(buffer), \"NUMBER: %v\", 123456789);\n  EXPECT_EQ(result, 17);\n  EXPECT_EQ(std::string(buffer), \"NUMBER: 1234567\");\n\n  std::string size = \"size\";\n\n  // Test that the buffer is never written to if the size is zero.\n  buffer[0] = '\\0';\n  result = SNPrintF(buffer, 0, \"Just checking the %v of the output.\", size);\n  EXPECT_EQ(result, 37);\n  EXPECT_EQ(buffer[0], '\\0');\n}\n\nTEST(StrFormat, BehavesAsDocumented) {\n  std::string s = absl::StrFormat(\"%s, %d!\", \"Hello\", 123);\n  EXPECT_EQ(\"Hello, 123!\", s);\n  std::string hello = \"Hello\";\n  std::string s2 = absl::StrFormat(\"%v, %v!\", hello, 123);\n  EXPECT_EQ(\"Hello, 123!\", s2);\n  // The format of a replacement is\n  // '%'[position][flags][width['.'precision]][length_modifier][format]\n  EXPECT_EQ(absl::StrFormat(\"%1$+3.2Lf\", 1.1), \"+1.10\");\n  // Text conversion:\n  //     \"c\" - Character.              Eg: 'a' -> \"A\", 20 -> \" \"\n  EXPECT_EQ(StrFormat(\"%c\", 'a'), \"a\");\n  EXPECT_EQ(StrFormat(\"%c\", 0x20), \" \");\n  //           Formats char and integral types: int, long, uint64_t, etc.\n  EXPECT_EQ(StrFormat(\"%c\", int{'a'}), \"a\");\n  EXPECT_EQ(StrFormat(\"%c\", long{'a'}), \"a\");  // NOLINT\n  EXPECT_EQ(StrFormat(\"%c\", uint64_t{'a'}), \"a\");\n  //     \"s\" - string       Eg: \"C\" -> \"C\", std::string(\"C++\") -> \"C++\"\n  //           Formats std::string, char*, string_view, and Cord.\n  EXPECT_EQ(StrFormat(\"%s\", \"C\"), \"C\");\n  EXPECT_EQ(StrFormat(\"%v\", std::string(\"C\")), \"C\");\n  EXPECT_EQ(StrFormat(\"%s\", std::string(\"C++\")), \"C++\");\n  EXPECT_EQ(StrFormat(\"%v\", std::string(\"C++\")), \"C++\");\n  EXPECT_EQ(StrFormat(\"%s\", string_view(\"view\")), \"view\");\n  EXPECT_EQ(StrFormat(\"%v\", string_view(\"view\")), \"view\");\n  EXPECT_EQ(StrFormat(\"%s\", absl::Cord(\"cord\")), \"cord\");\n  EXPECT_EQ(StrFormat(\"%v\", absl::Cord(\"cord\")), \"cord\");\n  // Integral Conversion\n  //     These format integral types: char, int, long, uint64_t, etc.\n  EXPECT_EQ(StrFormat(\"%d\", char{10}), \"10\");\n  EXPECT_EQ(StrFormat(\"%d\", int{10}), \"10\");\n  EXPECT_EQ(StrFormat(\"%d\", long{10}), \"10\");  // NOLINT\n  EXPECT_EQ(StrFormat(\"%d\", uint64_t{10}), \"10\");\n  EXPECT_EQ(StrFormat(\"%v\", int{10}), \"10\");\n  EXPECT_EQ(StrFormat(\"%v\", long{10}), \"10\");  // NOLINT\n  EXPECT_EQ(StrFormat(\"%v\", uint64_t{10}), \"10\");\n  //     d,i - signed decimal          Eg: -10 -> \"-10\"\n  EXPECT_EQ(StrFormat(\"%d\", -10), \"-10\");\n  EXPECT_EQ(StrFormat(\"%i\", -10), \"-10\");\n  EXPECT_EQ(StrFormat(\"%v\", -10), \"-10\");\n  //      o  - octal                   Eg:  10 -> \"12\"\n  EXPECT_EQ(StrFormat(\"%o\", 10), \"12\");\n  //      u  - unsigned decimal        Eg:  10 -> \"10\"\n  EXPECT_EQ(StrFormat(\"%u\", 10), \"10\");\n  EXPECT_EQ(StrFormat(\"%v\", 10), \"10\");\n  //     x/X - lower,upper case hex    Eg:  10 -> \"a\"/\"A\"\n  EXPECT_EQ(StrFormat(\"%x\", 10), \"a\");\n  EXPECT_EQ(StrFormat(\"%X\", 10), \"A\");\n  // Floating-point, with upper/lower-case output.\n  //     These format floating points types: float, double, long double, etc.\n  EXPECT_EQ(StrFormat(\"%.1f\", float{1}), \"1.0\");\n  EXPECT_EQ(StrFormat(\"%.1f\", double{1}), \"1.0\");\n  const long double long_double = 1.0;\n  EXPECT_EQ(StrFormat(\"%.1f\", long_double), \"1.0\");\n  //     These also format integral types: char, int, long, uint64_t, etc.:\n  EXPECT_EQ(StrFormat(\"%.1f\", char{1}), \"1.0\");\n  EXPECT_EQ(StrFormat(\"%.1f\", int{1}), \"1.0\");\n  EXPECT_EQ(StrFormat(\"%.1f\", long{1}), \"1.0\");  // NOLINT\n  EXPECT_EQ(StrFormat(\"%.1f\", uint64_t{1}), \"1.0\");\n  //     f/F - decimal.                Eg: 123456789 -> \"123456789.000000\"\n  EXPECT_EQ(StrFormat(\"%f\", 123456789), \"123456789.000000\");\n  EXPECT_EQ(StrFormat(\"%F\", 123456789), \"123456789.000000\");\n  //     e/E - exponentiated           Eg: .01 -> \"1.00000e-2\"/\"1.00000E-2\"\n  EXPECT_EQ(StrFormat(\"%e\", .01), \"1.000000e-02\");\n  EXPECT_EQ(StrFormat(\"%E\", .01), \"1.000000E-02\");\n  //     g/G - exponentiate to fit     Eg: .01 -> \"0.01\", 1e10 ->\"1e+10\"/\"1E+10\"\n  EXPECT_EQ(StrFormat(\"%g\", .01), \"0.01\");\n  EXPECT_EQ(StrFormat(\"%g\", 1e10), \"1e+10\");\n  EXPECT_EQ(StrFormat(\"%G\", 1e10), \"1E+10\");\n  EXPECT_EQ(StrFormat(\"%v\", .01), \"0.01\");\n  EXPECT_EQ(StrFormat(\"%v\", 1e10), \"1e+10\");\n  //     a/A - lower,upper case hex    Eg: -3.0 -> \"-0x1.8p+1\"/\"-0X1.8P+1\"\n\n// On Android platform <=21, there is a regression in hexfloat formatting.\n#if !defined(__ANDROID_API__) || __ANDROID_API__ > 21\n  EXPECT_EQ(StrFormat(\"%.1a\", -3.0), \"-0x1.8p+1\");  // .1 to fix MSVC output\n  EXPECT_EQ(StrFormat(\"%.1A\", -3.0), \"-0X1.8P+1\");  // .1 to fix MSVC output\n#endif\n\n  // Other conversion\n  int64_t value = 0x7ffdeb4;\n  auto ptr_value = static_cast<uintptr_t>(value);\n  const int& something = *reinterpret_cast<const int*>(ptr_value);\n  EXPECT_EQ(StrFormat(\"%p\", &something), StrFormat(\"0x%x\", ptr_value));\n\n  // The output of formatting a null pointer is not documented as being a\n  // specific thing, but the attempt should at least compile.\n  (void)StrFormat(\"%p\", nullptr);\n\n  // Output widths are supported, with optional flags.\n  EXPECT_EQ(StrFormat(\"%3d\", 1), \"  1\");\n  EXPECT_EQ(StrFormat(\"%3d\", 123456), \"123456\");\n  EXPECT_EQ(StrFormat(\"%06.2f\", 1.234), \"001.23\");\n  EXPECT_EQ(StrFormat(\"%+d\", 1), \"+1\");\n  EXPECT_EQ(StrFormat(\"% d\", 1), \" 1\");\n  EXPECT_EQ(StrFormat(\"%-4d\", -1), \"-1  \");\n  EXPECT_EQ(StrFormat(\"%#o\", 10), \"012\");\n  EXPECT_EQ(StrFormat(\"%#x\", 15), \"0xf\");\n  EXPECT_EQ(StrFormat(\"%04d\", 8), \"0008\");\n  EXPECT_EQ(StrFormat(\"%#04x\", 0), \"0000\");\n  EXPECT_EQ(StrFormat(\"%#04x\", 1), \"0x01\");\n  // Posix positional substitution.\n  EXPECT_EQ(absl::StrFormat(\"%2$s, %3$s, %1$s!\", \"vici\", \"veni\", \"vidi\"),\n            \"veni, vidi, vici!\");\n  // Length modifiers are ignored.\n  EXPECT_EQ(StrFormat(\"%hhd\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%hd\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%ld\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%lld\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%Ld\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%jd\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%zd\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%td\", int{1}), \"1\");\n  EXPECT_EQ(StrFormat(\"%qd\", int{1}), \"1\");\n\n  // Bool is handled correctly depending on whether %v is used\n  EXPECT_EQ(StrFormat(\"%v\", true), \"true\");\n  EXPECT_EQ(StrFormat(\"%v\", false), \"false\");\n  EXPECT_EQ(StrFormat(\"%d\", true), \"1\");\n}\n\nusing str_format_internal::ExtendedParsedFormat;\nusing str_format_internal::ParsedFormatBase;\n\nstruct SummarizeConsumer {\n  std::string* out;\n  explicit SummarizeConsumer(std::string* out) : out(out) {}\n\n  bool Append(string_view s) {\n    *out += \"[\" + std::string(s) + \"]\";\n    return true;\n  }\n\n  bool ConvertOne(const str_format_internal::UnboundConversion& conv,\n                  string_view s) {\n    *out += \"{\";\n    *out += std::string(s);\n    *out += \":\";\n    *out += std::to_string(conv.arg_position) + \"$\";\n    if (conv.width.is_from_arg()) {\n      *out += std::to_string(conv.width.get_from_arg()) + \"$*\";\n    }\n    if (conv.precision.is_from_arg()) {\n      *out += \".\" + std::to_string(conv.precision.get_from_arg()) + \"$*\";\n    }\n    *out += str_format_internal::FormatConversionCharToChar(conv.conv);\n    *out += \"}\";\n    return true;\n  }\n};\n\nstd::string SummarizeParsedFormat(const ParsedFormatBase& pc) {\n  std::string out;\n  if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += \"!\";\n  return out;\n}\n\nusing ParsedFormatTest = ::testing::Test;\n\nTEST_F(ParsedFormatTest, SimpleChecked) {\n  EXPECT_EQ(\"[ABC]{d:1$d}[DEF]\",\n            SummarizeParsedFormat(ParsedFormat<'d'>(\"ABC%dDEF\")));\n  EXPECT_EQ(\"{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}\",\n            SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>(\"%sFFF%dZZZ%f\")));\n  EXPECT_EQ(\"{s:1$s}[ ]{.*d:3$.2$*d}\",\n            SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>(\"%s %.*d\")));\n}\n\nTEST_F(ParsedFormatTest, SimpleCheckedWithV) {\n  EXPECT_EQ(\"[ABC]{v:1$v}[DEF]\",\n            SummarizeParsedFormat(ParsedFormat<'v'>(\"ABC%vDEF\")));\n  EXPECT_EQ(\"{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}\",\n            SummarizeParsedFormat(ParsedFormat<'v', 'v', 'f'>(\"%vFFF%vZZZ%f\")));\n  EXPECT_EQ(\"{v:1$v}[ ]{.*d:3$.2$*d}\",\n            SummarizeParsedFormat(ParsedFormat<'v', '*', 'd'>(\"%v %.*d\")));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {\n  auto f = ParsedFormat<'d'>::New(\"ABC%dDEF\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]{d:1$d}[DEF]\", SummarizeParsedFormat(*f));\n\n  std::string format = \"%sFFF%dZZZ%f\";\n  auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format);\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}\", SummarizeParsedFormat(*f2));\n\n  f2 = ParsedFormat<'s', 'd', 'f'>::New(\"%s %d %f\");\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{s:1$s}[ ]{d:2$d}[ ]{f:3$f}\", SummarizeParsedFormat(*f2));\n\n  auto star = ParsedFormat<'*', 'd'>::New(\"%*d\");\n  ASSERT_TRUE(star);\n  EXPECT_EQ(\"{*d:2$1$*d}\", SummarizeParsedFormat(*star));\n\n  auto dollar = ParsedFormat<'d', 's'>::New(\"%2$s %1$d\");\n  ASSERT_TRUE(dollar);\n  EXPECT_EQ(\"{2$s:2$s}[ ]{1$d:1$d}\", SummarizeParsedFormat(*dollar));\n  // with reuse\n  dollar = ParsedFormat<'d', 's'>::New(\"%2$s %1$d %1$d\");\n  ASSERT_TRUE(dollar);\n  EXPECT_EQ(\"{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}\",\n            SummarizeParsedFormat(*dollar));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedCorrectWithV) {\n  auto f = ParsedFormat<'v'>::New(\"ABC%vDEF\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]{v:1$v}[DEF]\", SummarizeParsedFormat(*f));\n\n  std::string format = \"%vFFF%vZZZ%f\";\n  auto f2 = ParsedFormat<'v', 'v', 'f'>::New(format);\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}\", SummarizeParsedFormat(*f2));\n\n  f2 = ParsedFormat<'v', 'v', 'f'>::New(\"%v %v %f\");\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{v:1$v}[ ]{v:2$v}[ ]{f:3$f}\", SummarizeParsedFormat(*f2));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {\n  EXPECT_FALSE((ParsedFormat<'d', 's'>::New(\"ABC\")));\n  EXPECT_FALSE((ParsedFormat<'d', 's'>::New(\"%dABC\")));\n  EXPECT_FALSE((ParsedFormat<'d', 's'>::New(\"ABC%2$s\")));\n  auto f = ParsedFormat<'d', 's'>::NewAllowIgnored(\"ABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]\", SummarizeParsedFormat(*f));\n  f = ParsedFormat<'d', 's'>::NewAllowIgnored(\"%dABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"{d:1$d}[ABC]\", SummarizeParsedFormat(*f));\n  f = ParsedFormat<'d', 's'>::NewAllowIgnored(\"ABC%2$s\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]{2$s:2$s}\", SummarizeParsedFormat(*f));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgsWithV) {\n  EXPECT_FALSE((ParsedFormat<'v', 'v'>::New(\"ABC\")));\n  EXPECT_FALSE((ParsedFormat<'v', 'v'>::New(\"%vABC\")));\n  EXPECT_FALSE((ParsedFormat<'v', 's'>::New(\"ABC%2$s\")));\n  auto f = ParsedFormat<'v', 'v'>::NewAllowIgnored(\"ABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]\", SummarizeParsedFormat(*f));\n  f = ParsedFormat<'v', 'v'>::NewAllowIgnored(\"%vABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"{v:1$v}[ABC]\", SummarizeParsedFormat(*f));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {\n  EXPECT_FALSE(ParsedFormat<'d'>::New(\"%1$d %1$x\"));\n  EXPECT_FALSE(ParsedFormat<'x'>::New(\"%1$d %1$x\"));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {\n  EXPECT_FALSE(ParsedFormat<'d'>::New(\"\"));\n\n  EXPECT_FALSE(ParsedFormat<'d'>::New(\"ABC%dDEF%d\"));\n\n  std::string format = \"%sFFF%dZZZ%f\";\n  EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));\n}\n\nTEST_F(ParsedFormatTest, SimpleUncheckedIncorrectWithV) {\n  EXPECT_FALSE(ParsedFormat<'v'>::New(\"\"));\n\n  EXPECT_FALSE(ParsedFormat<'v'>::New(\"ABC%vDEF%v\"));\n\n  std::string format = \"%vFFF%vZZZ%f\";\n  EXPECT_FALSE((ParsedFormat<'v', 'v', 'g'>::New(format)));\n}\n\n#if defined(__cpp_nontype_template_parameter_auto)\n\ntemplate <auto T>\nstd::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);\n\ntemplate <auto T>\nstd::false_type IsValidParsedFormatArgTest(...);\n\ntemplate <auto T>\nusing IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));\n\nTEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {\n  ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);\n\n  ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);\n\n  ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |\n                                     absl::FormatConversionCharSet::x>::value);\n  ASSERT_TRUE(\n      IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);\n\n  // This is an easy mistake to make, however, this will reduce to an integer\n  // which has no meaning, so we need to ensure it doesn't compile.\n  ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);\n\n  // For now, we disallow construction based on ConversionChar (rather than\n  // CharSet)\n  ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);\n}\n\nTEST_F(ParsedFormatTest, ExtendedTyping) {\n  EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(\"\"));\n  ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New(\"%d\"));\n  auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New(\"%d%s\");\n  ASSERT_TRUE(v1);\n  auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New(\"%d%s\");\n  ASSERT_TRUE(v2);\n  auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |\n                             absl::FormatConversionCharSet::s,\n                         's'>::New(\"%d%s\");\n  ASSERT_TRUE(v3);\n  auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |\n                             absl::FormatConversionCharSet::s,\n                         's'>::New(\"%s%s\");\n  ASSERT_TRUE(v4);\n}\n\nTEST_F(ParsedFormatTest, ExtendedTypingWithV) {\n  EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::v>::New(\"\"));\n  ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::v>::New(\"%v\"));\n  auto v1 = ParsedFormat<'v', absl::FormatConversionCharSet::v>::New(\"%v%v\");\n  ASSERT_TRUE(v1);\n  auto v2 = ParsedFormat<absl::FormatConversionCharSet::v, 'v'>::New(\"%v%v\");\n  ASSERT_TRUE(v2);\n  auto v3 = ParsedFormat<absl::FormatConversionCharSet::v |\n                             absl::FormatConversionCharSet::v,\n                         'v'>::New(\"%v%v\");\n  ASSERT_TRUE(v3);\n  auto v4 = ParsedFormat<absl::FormatConversionCharSet::v |\n                             absl::FormatConversionCharSet::v,\n                         'v'>::New(\"%v%v\");\n  ASSERT_TRUE(v4);\n}\n#endif\n\nTEST_F(ParsedFormatTest, UncheckedCorrect) {\n  auto f =\n      ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(\"ABC%dDEF\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]{d:1$d}[DEF]\", SummarizeParsedFormat(*f));\n\n  std::string format = \"%sFFF%dZZZ%f\";\n  auto f2 = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,\n      absl::FormatConversionCharSet::kFloating>::New(format);\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}\", SummarizeParsedFormat(*f2));\n\n  f2 = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,\n      absl::FormatConversionCharSet::kFloating>::New(\"%s %d %f\");\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{s:1$s}[ ]{d:2$d}[ ]{f:3$f}\", SummarizeParsedFormat(*f2));\n\n  auto star =\n      ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,\n                           absl::FormatConversionCharSet::d>::New(\"%*d\");\n  ASSERT_TRUE(star);\n  EXPECT_EQ(\"{*d:2$1$*d}\", SummarizeParsedFormat(*star));\n\n  auto dollar =\n      ExtendedParsedFormat<absl::FormatConversionCharSet::d,\n                           absl::FormatConversionCharSet::s>::New(\"%2$s %1$d\");\n  ASSERT_TRUE(dollar);\n  EXPECT_EQ(\"{2$s:2$s}[ ]{1$d:1$d}\", SummarizeParsedFormat(*dollar));\n  // with reuse\n  dollar = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::d,\n      absl::FormatConversionCharSet::s>::New(\"%2$s %1$d %1$d\");\n  ASSERT_TRUE(dollar);\n  EXPECT_EQ(\"{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}\",\n            SummarizeParsedFormat(*dollar));\n}\n\nTEST_F(ParsedFormatTest, UncheckedCorrectWithV) {\n  auto f =\n      ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(\"ABC%vDEF\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]{v:1$v}[DEF]\", SummarizeParsedFormat(*f));\n\n  std::string format = \"%vFFF%vZZZ%f\";\n  auto f2 = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,\n      absl::FormatConversionCharSet::kFloating>::New(format);\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}\", SummarizeParsedFormat(*f2));\n\n  f2 = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,\n      absl::FormatConversionCharSet::kFloating>::New(\"%v %v %f\");\n\n  ASSERT_TRUE(f2);\n  EXPECT_EQ(\"{v:1$v}[ ]{v:2$v}[ ]{f:3$f}\", SummarizeParsedFormat(*f2));\n}\n\nTEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,\n                            absl::FormatConversionCharSet::s>::New(\"ABC\")));\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,\n                            absl::FormatConversionCharSet::s>::New(\"%dABC\")));\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,\n                            absl::FormatConversionCharSet::s>::New(\"ABC%2$s\")));\n  auto f = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::d,\n      absl::FormatConversionCharSet::s>::NewAllowIgnored(\"ABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]\", SummarizeParsedFormat(*f));\n  f = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::d,\n      absl::FormatConversionCharSet::s>::NewAllowIgnored(\"%dABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"{d:1$d}[ABC]\", SummarizeParsedFormat(*f));\n  f = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::d,\n      absl::FormatConversionCharSet::s>::NewAllowIgnored(\"ABC%2$s\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]{2$s:2$s}\", SummarizeParsedFormat(*f));\n}\n\nTEST_F(ParsedFormatTest, UncheckedIgnoredArgsWithV) {\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::v,\n                            absl::FormatConversionCharSet::v>::New(\"ABC\")));\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::v,\n                            absl::FormatConversionCharSet::v>::New(\"%vABC\")));\n  EXPECT_FALSE((ExtendedParsedFormat<absl::FormatConversionCharSet::v,\n                                     absl::FormatConversionCharSet::s>::\n                    New(\"ABC%2$s\")));\n  auto f = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::v,\n      absl::FormatConversionCharSet::v>::NewAllowIgnored(\"ABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"[ABC]\", SummarizeParsedFormat(*f));\n  f = ExtendedParsedFormat<\n      absl::FormatConversionCharSet::v,\n      absl::FormatConversionCharSet::v>::NewAllowIgnored(\"%vABC\");\n  ASSERT_TRUE(f);\n  EXPECT_EQ(\"{v:1$v}[ABC]\", SummarizeParsedFormat(*f));\n}\n\nTEST_F(ParsedFormatTest, UncheckedMultipleTypes) {\n  auto dx =\n      ExtendedParsedFormat<absl::FormatConversionCharSet::d |\n                           absl::FormatConversionCharSet::x>::New(\"%1$d %1$x\");\n  EXPECT_TRUE(dx);\n  EXPECT_EQ(\"{1$d:1$d}[ ]{1$x:1$x}\", SummarizeParsedFormat(*dx));\n\n  dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |\n                            absl::FormatConversionCharSet::x>::New(\"%1$d\");\n  EXPECT_TRUE(dx);\n  EXPECT_EQ(\"{1$d:1$d}\", SummarizeParsedFormat(*dx));\n}\n\nTEST_F(ParsedFormatTest, UncheckedIncorrect) {\n  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(\"\"));\n\n  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(\n      \"ABC%dDEF%d\"));\n\n  std::string format = \"%sFFF%dZZZ%f\";\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::s,\n                            absl::FormatConversionCharSet::d,\n                            absl::FormatConversionCharSet::g>::New(format)));\n}\n\nTEST_F(ParsedFormatTest, UncheckedIncorrectWithV) {\n  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(\"\"));\n\n  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(\n      \"ABC%vDEF%v\"));\n\n  std::string format = \"%vFFF%vZZZ%f\";\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::v,\n                            absl::FormatConversionCharSet::g>::New(format)));\n}\n\nTEST_F(ParsedFormatTest, RegressionMixPositional) {\n  EXPECT_FALSE(\n      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,\n                            absl::FormatConversionCharSet::o>::New(\"%1$d %o\")));\n}\n\nTEST_F(ParsedFormatTest, DisallowModifiersWithV) {\n  auto f = ParsedFormat<'v'>::New(\"ABC%80vDEF\");\n  EXPECT_EQ(f, nullptr);\n\n  f = ParsedFormat<'v'>::New(\"ABC%0vDEF\");\n  EXPECT_EQ(f, nullptr);\n\n  f = ParsedFormat<'v'>::New(\"ABC%.1vDEF\");\n  EXPECT_EQ(f, nullptr);\n}\n\nusing FormatWrapperTest = ::testing::Test;\n\n// Plain wrapper for StrFormat.\ntemplate <typename... Args>\nstd::string WrappedFormat(const absl::FormatSpec<Args...>& format,\n                          const Args&... args) {\n  return StrFormat(format, args...);\n}\n\nTEST_F(FormatWrapperTest, ConstexprStringFormat) {\n  EXPECT_EQ(WrappedFormat(\"%s there\", \"hello\"), \"hello there\");\n}\n\nTEST_F(FormatWrapperTest, ConstexprStringFormatWithV) {\n  std::string hello = \"hello\";\n  EXPECT_EQ(WrappedFormat(\"%v there\", hello), \"hello there\");\n}\n\nTEST_F(FormatWrapperTest, ParsedFormat) {\n  ParsedFormat<'s'> format(\"%s there\");\n  EXPECT_EQ(WrappedFormat(format, \"hello\"), \"hello there\");\n}\n\nTEST_F(FormatWrapperTest, ParsedFormatWithV) {\n  std::string hello = \"hello\";\n  ParsedFormat<'v'> format(\"%v there\");\n  EXPECT_EQ(WrappedFormat(format, hello), \"hello there\");\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n\nnamespace {\nusing FormatExtensionTest = ::testing::Test;\n\nstruct Point {\n  friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |\n                                   absl::FormatConversionCharSet::kIntegral |\n                                   absl::FormatConversionCharSet::v>\n  AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,\n                    absl::FormatSink* s) {\n    if (spec.conversion_char() == absl::FormatConversionChar::s) {\n      s->Append(absl::StrCat(\"x=\", p.x, \" y=\", p.y));\n    } else {\n      s->Append(absl::StrCat(p.x, \",\", p.y));\n    }\n    return {true};\n  }\n\n  int x = 10;\n  int y = 20;\n};\n\nTEST_F(FormatExtensionTest, AbslFormatConvertExample) {\n  Point p;\n  EXPECT_EQ(absl::StrFormat(\"a %s z\", p), \"a x=10 y=20 z\");\n  EXPECT_EQ(absl::StrFormat(\"a %d z\", p), \"a 10,20 z\");\n  EXPECT_EQ(absl::StrFormat(\"a %v z\", p), \"a 10,20 z\");\n\n  // Typed formatting will fail to compile an invalid format.\n  // StrFormat(\"%f\", p);  // Does not compile.\n  std::string actual;\n  absl::UntypedFormatSpec f1(\"%f\");\n  // FormatUntyped will return false for bad character.\n  EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));\n}\n\nstruct PointStringify {\n  template <typename FormatSink>\n  friend void AbslStringify(FormatSink& sink, const PointStringify& p) {\n    sink.Append(absl::StrCat(\"(\", p.x, \", \", p.y, \")\"));\n  }\n\n  double x = 10.0;\n  double y = 20.0;\n};\n\nTEST_F(FormatExtensionTest, AbslStringifyExample) {\n  PointStringify p;\n  EXPECT_EQ(absl::StrFormat(\"a %v z\", p), \"a (10, 20) z\");\n}\n\nstruct PointStringifyUsingFormat {\n  template <typename FormatSink>\n  friend void AbslStringify(FormatSink& sink,\n                            const PointStringifyUsingFormat& p) {\n    absl::Format(&sink, \"(%g, %g)\", p.x, p.y);\n  }\n\n  double x = 10.0;\n  double y = 20.0;\n};\n\nTEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) {\n  PointStringifyUsingFormat p;\n  EXPECT_EQ(absl::StrFormat(\"a %v z\", p), \"a (10, 20) z\");\n}\n\nenum class EnumClassWithStringify { Many = 0, Choices = 1 };\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, EnumClassWithStringify e) {\n  absl::Format(&sink, \"%s\",\n               e == EnumClassWithStringify::Many ? \"Many\" : \"Choices\");\n}\n\nenum EnumWithStringify { Many, Choices };\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, EnumWithStringify e) {\n  absl::Format(&sink, \"%s\", e == EnumWithStringify::Many ? \"Many\" : \"Choices\");\n}\n\nTEST_F(FormatExtensionTest, AbslStringifyWithEnumWithV) {\n  const auto e_class = EnumClassWithStringify::Choices;\n  EXPECT_EQ(absl::StrFormat(\"My choice is %v\", e_class),\n            \"My choice is Choices\");\n\n  const auto e = EnumWithStringify::Choices;\n  EXPECT_EQ(absl::StrFormat(\"My choice is %v\", e), \"My choice is Choices\");\n}\n\nTEST_F(FormatExtensionTest, AbslStringifyEnumWithD) {\n  const auto e_class = EnumClassWithStringify::Many;\n  EXPECT_EQ(absl::StrFormat(\"My choice is %d\", e_class), \"My choice is 0\");\n\n  const auto e = EnumWithStringify::Choices;\n  EXPECT_EQ(absl::StrFormat(\"My choice is %d\", e), \"My choice is 1\");\n}\n\nenum class EnumWithLargerValue { x = 32 };\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, EnumWithLargerValue e) {\n  absl::Format(&sink, \"%s\", \"Many\");\n}\n\nTEST_F(FormatExtensionTest, AbslStringifyEnumOtherSpecifiers) {\n  const auto e = EnumWithLargerValue::x;\n  EXPECT_EQ(absl::StrFormat(\"My choice is %g\", e), \"My choice is 32\");\n  EXPECT_EQ(absl::StrFormat(\"My choice is %x\", e), \"My choice is 20\");\n}\n\n}  // namespace\n\n// Some codegen thunks that we can use to easily dump the generated assembly for\n// different StrFormat calls.\n\nstd::string CodegenAbslStrFormatInt(int i) {  // NOLINT\n  return absl::StrFormat(\"%d\", i);\n}\n\nstd::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,\n                                               int64_t i64) {  // NOLINT\n  return absl::StrFormat(\"%d %s %d\", i, s, i64);\n}\n\nvoid CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT\n  absl::StrAppendFormat(out, \"%d\", i);\n}\n\nvoid CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,\n                                              const std::string& s,\n                                              int64_t i64) {  // NOLINT\n  absl::StrAppendFormat(out, \"%d %s %d\", i, s, i64);\n}\n"
  },
  {
    "path": "absl/strings/str_join.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: str_join.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains functions for joining a range of elements and\n// returning the result as a std::string. StrJoin operations are specified by\n// passing a range, a separator string to use between the elements joined, and\n// an optional Formatter responsible for converting each argument in the range\n// to a string. If omitted, a default `AlphaNumFormatter()` is called on the\n// elements to be joined, using the same formatting that `absl::StrCat()` uses.\n// This package defines a number of default formatters, and you can define your\n// own implementations.\n//\n// Ranges are specified by passing a container with `std::begin()` and\n// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a\n// brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous\n// objects. The separator string is specified as an `absl::string_view`.\n//\n// Because the default formatter uses the `absl::AlphaNum` class,\n// `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on\n// collections of strings, ints, floats, doubles, etc.\n//\n// Example:\n//\n//   std::vector<std::string> v = {\"foo\", \"bar\", \"baz\"};\n//   std::string s = absl::StrJoin(v, \"-\");\n//   EXPECT_EQ(\"foo-bar-baz\", s);\n//\n// See comments on the `absl::StrJoin()` function for more examples.\n\n#ifndef ABSL_STRINGS_STR_JOIN_H_\n#define ABSL_STRINGS_STR_JOIN_H_\n\n#include <cstdio>\n#include <cstring>\n#include <initializer_list>\n#include <iterator>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/macros.h\"\n#include \"absl/strings/internal/str_join_internal.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// Concept: Formatter\n// -----------------------------------------------------------------------------\n//\n// A Formatter is a function object that is responsible for formatting its\n// argument as a string and appending it to a given output std::string.\n// Formatters may be implemented as function objects, lambdas, or normal\n// functions. You may provide your own Formatter to enable `absl::StrJoin()` to\n// work with arbitrary types.\n//\n// The following is an example of a custom Formatter that uses\n// `absl::FormatDuration` to join a list of `absl::Duration`s.\n//\n//   std::vector<absl::Duration> v = {absl::Seconds(1), absl::Milliseconds(10)};\n//   std::string s =\n//       absl::StrJoin(v, \", \", [](std::string* out, absl::Duration dur) {\n//         absl::StrAppend(out, absl::FormatDuration(dur));\n//       });\n//   EXPECT_EQ(s, \"1s, 10ms\");\n//\n// The following standard formatters are provided within this file:\n//\n// - `AlphaNumFormatter()` (the default)\n// - `StreamFormatter()`\n// - `PairFormatter()`\n// - `DereferenceFormatter()`\n\n// AlphaNumFormatter()\n//\n// Default formatter used if none is specified. Uses `absl::AlphaNum` to convert\n// numeric arguments to strings.\ninline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() {\n  return strings_internal::AlphaNumFormatterImpl();\n}\n\n// StreamFormatter()\n//\n// Formats its argument using the << operator.\ninline strings_internal::StreamFormatterImpl StreamFormatter() {\n  return strings_internal::StreamFormatterImpl();\n}\n\n// Function Template: PairFormatter(Formatter, absl::string_view, Formatter)\n//\n// Formats a `std::pair` by putting a given separator between the pair's\n// `.first` and `.second` members. This formatter allows you to specify\n// custom Formatters for both the first and second member of each pair.\ntemplate <typename FirstFormatter, typename SecondFormatter>\ninline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>\nPairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) {\n  return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(\n      std::move(f1), sep, std::move(f2));\n}\n\n// Function overload of PairFormatter() for using a default\n// `AlphaNumFormatter()` for each Formatter in the pair.\ninline strings_internal::PairFormatterImpl<\n    strings_internal::AlphaNumFormatterImpl,\n    strings_internal::AlphaNumFormatterImpl>\nPairFormatter(absl::string_view sep) {\n  return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());\n}\n\n// Function Template: DereferenceFormatter(Formatter)\n//\n// Formats its argument by dereferencing it and then applying the given\n// formatter. This formatter is useful for formatting a container of\n// pointer-to-T. This pattern often shows up when joining repeated fields in\n// protocol buffers.\ntemplate <typename Formatter>\nstrings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(\n    Formatter&& f) {\n  return strings_internal::DereferenceFormatterImpl<Formatter>(\n      std::forward<Formatter>(f));\n}\n\n// Function overload of `DereferenceFormatter()` for using a default\n// `AlphaNumFormatter()`.\ninline strings_internal::DereferenceFormatterImpl<\n    strings_internal::AlphaNumFormatterImpl>\nDereferenceFormatter() {\n  return strings_internal::DereferenceFormatterImpl<\n      strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());\n}\n\n// -----------------------------------------------------------------------------\n// StrJoin()\n// -----------------------------------------------------------------------------\n//\n// Joins a range of elements and returns the result as a std::string.\n// `absl::StrJoin()` takes a range, a separator string to use between the\n// elements joined, and an optional Formatter responsible for converting each\n// argument in the range to a string.\n//\n// If omitted, the default `AlphaNumFormatter()` is called on the elements to be\n// joined.\n//\n// Example 1:\n//   // Joins a collection of strings. This pattern also works with a collection\n//   // of `absl::string_view` or even `const char*`.\n//   std::vector<std::string> v = {\"foo\", \"bar\", \"baz\"};\n//   std::string s = absl::StrJoin(v, \"-\");\n//   EXPECT_EQ(s, \"foo-bar-baz\");\n//\n// Example 2:\n//   // Joins the values in the given `std::initializer_list<>` specified using\n//   // brace initialization. This pattern also works with an initializer_list\n//   // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.\n//   std::string s = absl::StrJoin({\"foo\", \"bar\", \"baz\"}, \"-\");\n//   EXPECT_EQs, \"foo-bar-baz\");\n//\n// Example 3:\n//   // Joins a collection of ints. This pattern also works with floats,\n//   // doubles, int64s -- any `StrCat()`-compatible type.\n//   std::vector<int> v = {1, 2, 3, -4};\n//   std::string s = absl::StrJoin(v, \"-\");\n//   EXPECT_EQ(s, \"1-2-3--4\");\n//\n// Example 4:\n//   // Joins a collection of pointer-to-int. By default, pointers are\n//   // dereferenced and the pointee is formatted using the default format for\n//   // that type; such dereferencing occurs for all levels of indirection, so\n//   // this pattern works just as well for `std::vector<int**>` as for\n//   // `std::vector<int*>`.\n//   int x = 1, y = 2, z = 3;\n//   std::vector<int*> v = {&x, &y, &z};\n//   std::string s = absl::StrJoin(v, \"-\");\n//   EXPECT_EQ(s, \"1-2-3\");\n//\n// Example 5:\n//   // Dereferencing of `std::unique_ptr<>` is also supported:\n//   std::vector<std::unique_ptr<int>> v\n//   v.emplace_back(new int(1));\n//   v.emplace_back(new int(2));\n//   v.emplace_back(new int(3));\n//   std::string s = absl::StrJoin(v, \"-\");\n//   EXPECT_EQ(s, \"1-2-3\");\n//\n// Example 6:\n//   // Joins a `std::map`, with each key-value pair separated by an equals\n//   // sign. This pattern would also work with, say, a\n//   // `std::vector<std::pair<>>`.\n//   std::map<std::string, int> m = {\n//       {\"a\", 1},\n//       {\"b\", 2},\n//       {\"c\", 3}};\n//   std::string s = absl::StrJoin(m, \",\", absl::PairFormatter(\"=\"));\n//   EXPECT_EQ(s, \"a=1,b=2,c=3\");\n//\n// Example 7:\n//   // These examples show how `absl::StrJoin()` handles a few common edge\n//   // cases:\n//   std::vector<std::string> v_empty;\n//   EXPECT_EQ(absl::StrJoin(v_empty, \"-\"), \"\");\n//\n//   std::vector<std::string> v_one_item = {\"foo\"};\n//   EXPECT_EQ(absl::StrJoin(v_one_item, \"-\"), \"foo\");\n//\n//   std::vector<std::string> v_empty_string = {\"\"};\n//   EXPECT_EQ(absl::StrJoin(v_empty_string, \"-\"), \"\");\n//\n//   std::vector<std::string> v_one_item_empty_string = {\"a\", \"\"};\n//   EXPECT_EQ(absl::StrJoin(v_one_item_empty_string, \"-\"), \"a-\");\n//\n//   std::vector<std::string> v_two_empty_string = {\"\", \"\"};\n//   EXPECT_EQ(absl::StrJoin(v_two_empty_string, \"-\"), \"-\");\n//\n// Example 8:\n//   // Joins a `std::tuple<T...>` of heterogeneous types, converting each to\n//   // a std::string using the `absl::AlphaNum` class.\n//   std::string s = absl::StrJoin(std::make_tuple(123, \"abc\", 0.456), \"-\");\n//   EXPECT_EQ(s, \"123-abc-0.456\");\n\ntemplate <typename Iterator, typename Formatter>\nstd::string StrJoin(Iterator start, Iterator end, absl::string_view sep,\n                    Formatter&& fmt) {\n  return strings_internal::JoinAlgorithm(start, end, sep, fmt);\n}\n\ntemplate <typename Range, typename Formatter>\nstd::string StrJoin(const Range& range, absl::string_view separator,\n                    Formatter&& fmt) {\n  return strings_internal::JoinRange(range, separator, fmt);\n}\n\ntemplate <typename T, typename Formatter,\n          typename = typename std::enable_if<\n              !std::is_convertible<T, absl::string_view>::value>::type>\nstd::string StrJoin(std::initializer_list<T> il, absl::string_view separator,\n                    Formatter&& fmt) {\n  return strings_internal::JoinRange(il, separator, fmt);\n}\n\ntemplate <typename Formatter>\ninline std::string StrJoin(std::initializer_list<absl::string_view> il,\n                           absl::string_view separator, Formatter&& fmt) {\n  return strings_internal::JoinRange(il, separator, fmt);\n}\n\ntemplate <typename... T, typename Formatter>\nstd::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,\n                    Formatter&& fmt) {\n  return strings_internal::JoinAlgorithm(value, separator, fmt);\n}\n\ntemplate <typename Iterator>\nstd::string StrJoin(Iterator start, Iterator end, absl::string_view separator) {\n  return strings_internal::JoinRange(start, end, separator);\n}\n\ntemplate <typename Range>\nstd::string StrJoin(const Range& range, absl::string_view separator) {\n  return strings_internal::JoinRange(range, separator);\n}\n\ntemplate <typename T, typename = typename std::enable_if<!std::is_convertible<\n                          T, absl::string_view>::value>::type>\nstd::string StrJoin(std::initializer_list<T> il, absl::string_view separator) {\n  return strings_internal::JoinRange(il, separator);\n}\n\ninline std::string StrJoin(std::initializer_list<absl::string_view> il,\n                           absl::string_view separator) {\n  return strings_internal::JoinRange(il, separator);\n}\n\ntemplate <typename... T>\nstd::string StrJoin(const std::tuple<T...>& value,\n                    absl::string_view separator) {\n  return strings_internal::JoinTuple(value, separator,\n                                     std::index_sequence_for<T...>{});\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STR_JOIN_H_\n"
  },
  {
    "path": "absl/strings/str_join_benchmark.cc",
    "content": "//\n// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#include \"absl/strings/str_join.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_Join2_Strings(benchmark::State& state) {\n  const int string_len = state.range(0);\n  const int num_strings = state.range(1);\n  const std::string s(string_len, 'x');\n  const std::vector<std::string> v(num_strings, s);\n  for (auto _ : state) {\n    std::string s = absl::StrJoin(v, \"-\");\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_Join2_Strings)\n    ->ArgPair(1 << 0, 1 << 3)\n    ->ArgPair(1 << 10, 1 << 3)\n    ->ArgPair(1 << 13, 1 << 3)\n    ->ArgPair(1 << 0, 1 << 10)\n    ->ArgPair(1 << 10, 1 << 10)\n    ->ArgPair(1 << 13, 1 << 10)\n    ->ArgPair(1 << 0, 1 << 13)\n    ->ArgPair(1 << 10, 1 << 13)\n    ->ArgPair(1 << 13, 1 << 13);\n\nvoid BM_Join2_Ints(benchmark::State& state) {\n  const int num_ints = state.range(0);\n  const std::vector<int> v(num_ints, 42);\n  for (auto _ : state) {\n    std::string s = absl::StrJoin(v, \"-\");\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_Join2_Ints)->Range(0, 1 << 13);\n\nvoid BM_Join2_KeysAndValues(benchmark::State& state) {\n  const int string_len = state.range(0);\n  const int num_pairs = state.range(1);\n  const std::string s(string_len, 'x');\n  const std::vector<std::pair<std::string, int>> v(num_pairs,\n                                                   std::make_pair(s, 42));\n  for (auto _ : state) {\n    std::string s = absl::StrJoin(v, \",\", absl::PairFormatter(\"=\"));\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_Join2_KeysAndValues)\n    ->ArgPair(1 << 0, 1 << 3)\n    ->ArgPair(1 << 10, 1 << 3)\n    ->ArgPair(1 << 13, 1 << 3)\n    ->ArgPair(1 << 0, 1 << 10)\n    ->ArgPair(1 << 10, 1 << 10)\n    ->ArgPair(1 << 13, 1 << 10)\n    ->ArgPair(1 << 0, 1 << 13)\n    ->ArgPair(1 << 10, 1 << 13)\n    ->ArgPair(1 << 13, 1 << 13);\n\nvoid BM_JoinStreamable(benchmark::State& state) {\n  const int string_len = state.range(0);\n  const int num_strings = state.range(1);\n  const std::vector<std::string> v(num_strings, std::string(string_len, 'x'));\n  for (auto _ : state) {\n    std::string s = absl::StrJoin(v, \"\", absl::StreamFormatter());\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_JoinStreamable)\n    ->ArgPair(0, 0)\n    ->ArgPair(16, 1)\n    ->ArgPair(256, 1)\n    ->ArgPair(16, 16)\n    ->ArgPair(256, 16)\n    ->ArgPair(16, 256)\n    ->ArgPair(256, 256);\n\nvoid BM_JoinTuple(benchmark::State& state) {\n  for (auto _ : state) {\n    std::string s =\n        absl::StrJoin(std::make_tuple(123456789, 987654321, 24680, 13579), \"/\");\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_JoinTuple);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_join_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Unit tests for all join.h functions\n\n#include \"absl/strings/str_join.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <functional>\n#include <initializer_list>\n#include <iterator>\n#include <map>\n#include <memory>\n#include <ostream>\n#include <string>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nTEST(StrJoin, APIExamples) {\n  {\n    // Collection of strings\n    std::vector<std::string> v = {\"foo\", \"bar\", \"baz\"};\n    EXPECT_EQ(\"foo-bar-baz\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Collection of absl::string_view\n    std::vector<absl::string_view> v = {\"foo\", \"bar\", \"baz\"};\n    EXPECT_EQ(\"foo-bar-baz\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Collection of const char*\n    std::vector<const char*> v = {\"foo\", \"bar\", \"baz\"};\n    EXPECT_EQ(\"foo-bar-baz\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Collection of non-const char*\n    std::string a = \"foo\", b = \"bar\", c = \"baz\";\n    std::vector<char*> v = {&a[0], &b[0], &c[0]};\n    EXPECT_EQ(\"foo-bar-baz\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Collection of ints\n    std::vector<int> v = {1, 2, 3, -4};\n    EXPECT_EQ(\"1-2-3--4\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Literals passed as a std::initializer_list\n    std::string s = absl::StrJoin({\"a\", \"b\", \"c\"}, \"-\");\n    EXPECT_EQ(\"a-b-c\", s);\n  }\n  {\n    // Join a std::tuple<T...>.\n    std::string s = absl::StrJoin(std::make_tuple(123, \"abc\", 0.456), \"-\");\n    EXPECT_EQ(\"123-abc-0.456\", s);\n  }\n\n  {\n    // Collection of unique_ptrs\n    std::vector<std::unique_ptr<int>> v;\n    v.emplace_back(new int(1));\n    v.emplace_back(new int(2));\n    v.emplace_back(new int(3));\n    EXPECT_EQ(\"1-2-3\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Array of ints\n    const int a[] = {1, 2, 3, -4};\n    EXPECT_EQ(\"1-2-3--4\", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), \"-\"));\n  }\n\n  {\n    // Collection of pointers\n    int x = 1, y = 2, z = 3;\n    std::vector<int*> v = {&x, &y, &z};\n    EXPECT_EQ(\"1-2-3\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Collection of pointers to pointers\n    int x = 1, y = 2, z = 3;\n    int *px = &x, *py = &y, *pz = &z;\n    std::vector<int**> v = {&px, &py, &pz};\n    EXPECT_EQ(\"1-2-3\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // Collection of pointers to std::string\n    std::string a(\"a\"), b(\"b\");\n    std::vector<std::string*> v = {&a, &b};\n    EXPECT_EQ(\"a-b\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // A std::map, which is a collection of std::pair<>s.\n    std::map<std::string, int> m = {{\"a\", 1}, {\"b\", 2}, {\"c\", 3}};\n    EXPECT_EQ(\"a=1,b=2,c=3\", absl::StrJoin(m, \",\", absl::PairFormatter(\"=\")));\n  }\n\n  {\n    // Shows absl::StrSplit and absl::StrJoin working together. This example is\n    // equivalent to s/=/-/g.\n    const std::string s = \"a=b=c=d\";\n    EXPECT_EQ(\"a-b-c-d\", absl::StrJoin(absl::StrSplit(s, \"=\"), \"-\"));\n  }\n\n  //\n  // A few examples of edge cases\n  //\n\n  {\n    // Empty range yields an empty string.\n    std::vector<std::string> v;\n    EXPECT_EQ(\"\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // A range of 1 element gives a string with that element but no\n    // separator.\n    std::vector<std::string> v = {\"foo\"};\n    EXPECT_EQ(\"foo\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // A range with a single empty string element\n    std::vector<std::string> v = {\"\"};\n    EXPECT_EQ(\"\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // A range with 2 elements, one of which is an empty string\n    std::vector<std::string> v = {\"a\", \"\"};\n    EXPECT_EQ(\"a-\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // A range with 2 empty elements.\n    std::vector<std::string> v = {\"\", \"\"};\n    EXPECT_EQ(\"-\", absl::StrJoin(v, \"-\"));\n  }\n\n  {\n    // A std::vector of bool.\n    std::vector<bool> v = {true, false, true};\n    EXPECT_EQ(\"1-0-1\", absl::StrJoin(v, \"-\"));\n  }\n}\n\nTEST(StrJoin, CustomFormatter) {\n  std::vector<std::string> v{\"One\", \"Two\", \"Three\"};\n  {\n    std::string joined =\n        absl::StrJoin(v, \"\", [](std::string* out, const std::string& in) {\n          absl::StrAppend(out, \"(\", in, \")\");\n        });\n    EXPECT_EQ(\"(One)(Two)(Three)\", joined);\n  }\n  {\n    class ImmovableFormatter {\n     public:\n      void operator()(std::string* out, const std::string& in) {\n        absl::StrAppend(out, \"(\", in, \")\");\n      }\n      ImmovableFormatter() {}\n      ImmovableFormatter(const ImmovableFormatter&) = delete;\n    };\n    EXPECT_EQ(\"(One)(Two)(Three)\", absl::StrJoin(v, \"\", ImmovableFormatter()));\n  }\n  {\n    class OverloadedFormatter {\n     public:\n      void operator()(std::string* out, const std::string& in) {\n        absl::StrAppend(out, \"(\", in, \")\");\n      }\n      void operator()(std::string* out, const std::string& in) const {\n        absl::StrAppend(out, \"[\", in, \"]\");\n      }\n    };\n    EXPECT_EQ(\"(One)(Two)(Three)\", absl::StrJoin(v, \"\", OverloadedFormatter()));\n    const OverloadedFormatter fmt = {};\n    EXPECT_EQ(\"[One][Two][Three]\", absl::StrJoin(v, \"\", fmt));\n  }\n}\n\n//\n// Tests the Formatters\n//\n\nTEST(AlphaNumFormatter, FormatterAPI) {\n  // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test\n  // of what AlphaNum can convert.\n  auto f = absl::AlphaNumFormatter();\n  std::string s;\n  f(&s, \"Testing: \");\n  f(&s, static_cast<int>(1));\n  f(&s, static_cast<int16_t>(2));\n  f(&s, static_cast<int64_t>(3));\n  f(&s, static_cast<float>(4));\n  f(&s, static_cast<double>(5));\n  f(&s, static_cast<unsigned>(6));\n  f(&s, static_cast<size_t>(7));\n  f(&s, absl::string_view(\" OK\"));\n  EXPECT_EQ(\"Testing: 1234567 OK\", s);\n}\n\n// Make sure people who are mistakenly using std::vector<bool> even though\n// they're not memory-constrained can use absl::AlphaNumFormatter().\nTEST(AlphaNumFormatter, VectorOfBool) {\n  auto f = absl::AlphaNumFormatter();\n  std::string s;\n  std::vector<bool> v = {true, false, true};\n  f(&s, *v.cbegin());\n  f(&s, *v.begin());\n  f(&s, v[1]);\n  EXPECT_EQ(\"110\", s);\n}\n\nTEST(AlphaNumFormatter, AlphaNum) {\n  auto f = absl::AlphaNumFormatter();\n  std::string s;\n  f(&s, absl::AlphaNum(\"hello\"));\n  EXPECT_EQ(\"hello\", s);\n}\n\nstruct StreamableType {\n  std::string contents;\n};\ninline std::ostream& operator<<(std::ostream& os, const StreamableType& t) {\n  os << \"Streamable:\" << t.contents;\n  return os;\n}\n\nTEST(StreamFormatter, FormatterAPI) {\n  auto f = absl::StreamFormatter();\n  std::string s;\n  f(&s, \"Testing: \");\n  f(&s, static_cast<int>(1));\n  f(&s, static_cast<int16_t>(2));\n  f(&s, static_cast<int64_t>(3));\n  f(&s, static_cast<float>(4));\n  f(&s, static_cast<double>(5));\n  f(&s, static_cast<unsigned>(6));\n  f(&s, static_cast<size_t>(7));\n  f(&s, absl::string_view(\" OK \"));\n  StreamableType streamable = {\"object\"};\n  f(&s, streamable);\n  EXPECT_EQ(\"Testing: 1234567 OK Streamable:object\", s);\n}\n\n// A dummy formatter that wraps each element in parens. Used in some tests\n// below.\nstruct TestingParenFormatter {\n  template <typename T>\n  void operator()(std::string* s, const T& t) {\n    absl::StrAppend(s, \"(\", t, \")\");\n  }\n};\n\nTEST(PairFormatter, FormatterAPI) {\n  {\n    // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the\n    // 'first' and 'second' members.\n    const auto f = absl::PairFormatter(\"=\");\n    std::string s;\n    f(&s, std::make_pair(\"a\", \"b\"));\n    f(&s, std::make_pair(1, 2));\n    EXPECT_EQ(\"a=b1=2\", s);\n  }\n\n  {\n    // Tests using a custom formatter for the 'first' and 'second' members.\n    auto f = absl::PairFormatter(TestingParenFormatter(), \"=\",\n                                 TestingParenFormatter());\n    std::string s;\n    f(&s, std::make_pair(\"a\", \"b\"));\n    f(&s, std::make_pair(1, 2));\n    EXPECT_EQ(\"(a)=(b)(1)=(2)\", s);\n  }\n}\n\nTEST(DereferenceFormatter, FormatterAPI) {\n  {\n    // Tests wrapping the default AlphaNumFormatter.\n    const absl::strings_internal::DereferenceFormatterImpl<\n        absl::strings_internal::AlphaNumFormatterImpl>\n        f;\n    int x = 1, y = 2, z = 3;\n    std::string s;\n    f(&s, &x);\n    f(&s, &y);\n    f(&s, &z);\n    EXPECT_EQ(\"123\", s);\n  }\n\n  {\n    // Tests wrapping std::string's default formatter.\n    absl::strings_internal::DereferenceFormatterImpl<\n        absl::strings_internal::DefaultFormatter<std::string>::Type>\n        f;\n\n    std::string x = \"x\";\n    std::string y = \"y\";\n    std::string z = \"z\";\n    std::string s;\n    f(&s, &x);\n    f(&s, &y);\n    f(&s, &z);\n    EXPECT_EQ(s, \"xyz\");\n  }\n\n  {\n    // Tests wrapping a custom formatter.\n    auto f = absl::DereferenceFormatter(TestingParenFormatter());\n    int x = 1, y = 2, z = 3;\n    std::string s;\n    f(&s, &x);\n    f(&s, &y);\n    f(&s, &z);\n    EXPECT_EQ(\"(1)(2)(3)\", s);\n  }\n\n  {\n    absl::strings_internal::DereferenceFormatterImpl<\n        absl::strings_internal::AlphaNumFormatterImpl>\n        f;\n    auto x = std::unique_ptr<int>(new int(1));\n    auto y = std::unique_ptr<int>(new int(2));\n    auto z = std::unique_ptr<int>(new int(3));\n    std::string s;\n    f(&s, x);\n    f(&s, y);\n    f(&s, z);\n    EXPECT_EQ(\"123\", s);\n  }\n}\n\n//\n// Tests the interfaces for the 4 public Join function overloads. The semantics\n// of the algorithm is covered in the above APIExamples test.\n//\nTEST(StrJoin, PublicAPIOverloads) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\"};\n\n  // Iterators + formatter\n  EXPECT_EQ(\"a-b-c\",\n            absl::StrJoin(v.begin(), v.end(), \"-\", absl::AlphaNumFormatter()));\n  // Range + formatter\n  EXPECT_EQ(\"a-b-c\", absl::StrJoin(v, \"-\", absl::AlphaNumFormatter()));\n  // Iterators, no formatter\n  EXPECT_EQ(\"a-b-c\", absl::StrJoin(v.begin(), v.end(), \"-\"));\n  // Range, no formatter\n  EXPECT_EQ(\"a-b-c\", absl::StrJoin(v, \"-\"));\n}\n\nTEST(StrJoin, Array) {\n  const absl::string_view a[] = {\"a\", \"b\", \"c\"};\n  EXPECT_EQ(\"a-b-c\", absl::StrJoin(a, \"-\"));\n}\n\nTEST(StrJoin, InitializerList) {\n  { EXPECT_EQ(\"a-b-c\", absl::StrJoin({\"a\", \"b\", \"c\"}, \"-\")); }\n\n  {\n    auto a = {\"a\", \"b\", \"c\"};\n    EXPECT_EQ(\"a-b-c\", absl::StrJoin(a, \"-\"));\n  }\n\n  {\n    std::initializer_list<const char*> a = {\"a\", \"b\", \"c\"};\n    EXPECT_EQ(\"a-b-c\", absl::StrJoin(a, \"-\"));\n  }\n\n  {\n    std::initializer_list<std::string> a = {\"a\", \"b\", \"c\"};\n    EXPECT_EQ(\"a-b-c\", absl::StrJoin(a, \"-\"));\n  }\n\n  {\n    std::initializer_list<absl::string_view> a = {\"a\", \"b\", \"c\"};\n    EXPECT_EQ(\"a-b-c\", absl::StrJoin(a, \"-\"));\n  }\n\n  {\n    // Tests initializer_list with a non-default formatter\n    auto a = {\"a\", \"b\", \"c\"};\n    TestingParenFormatter f;\n    EXPECT_EQ(\"(a)-(b)-(c)\", absl::StrJoin(a, \"-\", f));\n  }\n\n  {\n    // initializer_list of ints\n    EXPECT_EQ(\"1-2-3\", absl::StrJoin({1, 2, 3}, \"-\"));\n  }\n\n  {\n    // Tests initializer_list of ints with a non-default formatter\n    auto a = {1, 2, 3};\n    TestingParenFormatter f;\n    EXPECT_EQ(\"(1)-(2)-(3)\", absl::StrJoin(a, \"-\", f));\n  }\n}\n\nTEST(StrJoin, StringViewInitializerList) {\n  {\n    // Tests initializer_list of string_views\n    std::string b = \"b\";\n    EXPECT_EQ(\"a-b-c\", absl::StrJoin({\"a\", b, \"c\"}, \"-\"));\n  }\n  {\n    // Tests initializer_list of string_views with a non-default formatter\n    TestingParenFormatter f;\n    std::string b = \"b\";\n    EXPECT_EQ(\"(a)-(b)-(c)\", absl::StrJoin({\"a\", b, \"c\"}, \"-\", f));\n  }\n\n  class NoCopy {\n   public:\n    explicit NoCopy(absl::string_view view) : view_(view) {}\n    NoCopy(const NoCopy&) = delete;\n    operator absl::string_view() { return view_; }  // NOLINT\n   private:\n    absl::string_view view_;\n  };\n  {\n    // Tests initializer_list of string_views preferred over initializer_list<T>\n    // for T that is implicitly convertible to string_view\n    EXPECT_EQ(\"a-b-c\",\n              absl::StrJoin({NoCopy(\"a\"), NoCopy(\"b\"), NoCopy(\"c\")}, \"-\"));\n  }\n  {\n    // Tests initializer_list of string_views preferred over initializer_list<T>\n    // for T that is implicitly convertible to string_view\n    TestingParenFormatter f;\n    EXPECT_EQ(\"(a)-(b)-(c)\",\n              absl::StrJoin({NoCopy(\"a\"), NoCopy(\"b\"), NoCopy(\"c\")}, \"-\", f));\n  }\n}\n\nTEST(StrJoin, Tuple) {\n  EXPECT_EQ(\"\", absl::StrJoin(std::make_tuple(), \"-\"));\n  EXPECT_EQ(\"hello\", absl::StrJoin(std::make_tuple(\"hello\"), \"-\"));\n\n  int x(10);\n  std::string y(\"hello\");\n  double z(3.14);\n  EXPECT_EQ(\"10-hello-3.14\", absl::StrJoin(std::make_tuple(x, y, z), \"-\"));\n\n  // Faster! Faster!!\n  EXPECT_EQ(\"10-hello-3.14\",\n            absl::StrJoin(std::make_tuple(x, std::cref(y), z), \"-\"));\n\n  struct TestFormatter {\n    char buffer[128];\n    void operator()(std::string* out, int v) {\n      snprintf(buffer, sizeof(buffer), \"%#.8x\", v);\n      out->append(buffer);\n    }\n    void operator()(std::string* out, double v) {\n      snprintf(buffer, sizeof(buffer), \"%#.0f\", v);\n      out->append(buffer);\n    }\n    void operator()(std::string* out, const std::string& v) {\n      snprintf(buffer, sizeof(buffer), \"%.4s\", v.c_str());\n      out->append(buffer);\n    }\n  };\n  EXPECT_EQ(\"0x0000000a-hell-3.\",\n            absl::StrJoin(std::make_tuple(x, y, z), \"-\", TestFormatter()));\n  EXPECT_EQ(\n      \"0x0000000a-hell-3.\",\n      absl::StrJoin(std::make_tuple(x, std::cref(y), z), \"-\", TestFormatter()));\n  EXPECT_EQ(\"0x0000000a-hell-3.\",\n            absl::StrJoin(std::make_tuple(&x, &y, &z), \"-\",\n                          absl::DereferenceFormatter(TestFormatter())));\n  EXPECT_EQ(\"0x0000000a-hell-3.\",\n            absl::StrJoin(std::make_tuple(absl::make_unique<int>(x),\n                                          absl::make_unique<std::string>(y),\n                                          absl::make_unique<double>(z)),\n                          \"-\", absl::DereferenceFormatter(TestFormatter())));\n  EXPECT_EQ(\"0x0000000a-hell-3.\",\n            absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z),\n                          \"-\", absl::DereferenceFormatter(TestFormatter())));\n}\n\n// A minimal value type for `StrJoin` inputs.\n// Used to ensure we do not excessively require more a specific type, such as a\n// `string_view`.\n//\n// Anything that can be  `data()` and `size()` is OK.\nclass TestValue {\n public:\n  TestValue(const char* data, size_t size) : data_(data), size_(size) {}\n  const char* data() const { return data_; }\n  size_t size() const { return size_; }\n\n private:\n  const char* data_;\n  size_t size_;\n};\n\n// A minimal C++20 forward iterator, used to test that we do not impose\n// excessive requirements on StrJoin inputs.\n//\n// The 2 main differences between pre-C++20 LegacyForwardIterator and the\n// C++20 ForwardIterator are:\n// 1. `operator->` is not required in C++20.\n// 2. `operator*` result does not need to be an lvalue (a reference).\n//\n// The `operator->` requirement was removed on page 17 in:\n// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1037r0.pdf\n//\n// See the `[iterator.requirements]` section of the C++ standard.\n//\n// The value type is a template parameter so that we can test the behaviour\n// of `StrJoin` specializations, e.g. the NoFormatter specialization for\n// `string_view`.\ntemplate <typename ValueT>\nclass TestIterator {\n public:\n  using iterator_category = std::forward_iterator_tag;\n  using value_type = ValueT;\n  using pointer = void;\n  using reference = const value_type&;\n  using difference_type = int;\n\n  // `data` must outlive the result.\n  static TestIterator begin(const std::vector<absl::string_view>& data) {\n    return TestIterator(&data, 0);\n  }\n\n  static TestIterator end(const std::vector<absl::string_view>& data) {\n    return TestIterator(nullptr, data.size());\n  }\n\n  bool operator==(const TestIterator& other) const {\n    return pos_ == other.pos_;\n  }\n  bool operator!=(const TestIterator& other) const {\n    return pos_ != other.pos_;\n  }\n\n  // This deliberately returns a `prvalue`.\n  // The requirement to return a reference was removed in C++20.\n  value_type operator*() const {\n    return ValueT((*data_)[pos_].data(), (*data_)[pos_].size());\n  }\n\n  // `operator->()` is deliberately omitted.\n  // The requirement to provide it was removed in C++20.\n\n  TestIterator& operator++() {\n    ++pos_;\n    return *this;\n  }\n\n  TestIterator operator++(int) {\n    TestIterator result = *this;\n    ++(*this);\n    return result;\n  }\n\n  TestIterator& operator--() {\n    --pos_;\n    return *this;\n  }\n\n  TestIterator operator--(int) {\n    TestIterator result = *this;\n    --(*this);\n    return result;\n  }\n\n private:\n  TestIterator(const std::vector<absl::string_view>* data, size_t pos)\n      : data_(data), pos_(pos) {}\n\n  const std::vector<absl::string_view>* data_;\n  size_t pos_;\n};\n\ntemplate <typename ValueT>\nclass TestIteratorRange {\n public:\n  // `data` must be non-null and must outlive the result.\n  explicit TestIteratorRange(const std::vector<absl::string_view>& data)\n      : begin_(TestIterator<ValueT>::begin(data)),\n        end_(TestIterator<ValueT>::end(data)) {}\n\n  const TestIterator<ValueT>& begin() const { return begin_; }\n  const TestIterator<ValueT>& end() const { return end_; }\n\n private:\n  TestIterator<ValueT> begin_;\n  TestIterator<ValueT> end_;\n};\n\nTEST(StrJoin, TestIteratorRequirementsNoFormatter) {\n  const std::vector<absl::string_view> a = {\"a\", \"b\", \"c\"};\n\n  // When the value type is string-like (`std::string` or `string_view`),\n  // the NoFormatter template specialization is used internally.\n  EXPECT_EQ(\"a-b-c\",\n            absl::StrJoin(TestIteratorRange<absl::string_view>(a), \"-\"));\n}\n\nTEST(StrJoin, TestIteratorRequirementsCustomFormatter) {\n  const std::vector<absl::string_view> a = {\"a\", \"b\", \"c\"};\n  EXPECT_EQ(\"a-b-c\",\n            absl::StrJoin(TestIteratorRange<TestValue>(a), \"-\",\n                          [](std::string* out, const TestValue& value) {\n                            absl::StrAppend(\n                                out,\n                                absl::string_view(value.data(), value.size()));\n                          }));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_replace.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/str_replace.h\"\n\n#include <cstddef>\n#include <initializer_list>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace strings_internal {\n\nusing FixedMapping =\n    std::initializer_list<std::pair<absl::string_view, absl::string_view>>;\n\n// Applies the ViableSubstitutions in subs_ptr to the absl::string_view s, and\n// stores the result in *result_ptr. Returns the number of substitutions that\n// occurred.\nint ApplySubstitutions(\n    absl::string_view s,\n    std::vector<strings_internal::ViableSubstitution>* absl_nonnull subs_ptr,\n    std::string* absl_nonnull result_ptr) {\n  auto& subs = *subs_ptr;\n  int substitutions = 0;\n  size_t pos = 0;\n  while (!subs.empty()) {\n    auto& sub = subs.back();\n    if (sub.offset >= pos) {\n      if (pos <= s.size()) {\n        StrAppend(result_ptr, s.substr(pos, sub.offset - pos), sub.replacement);\n      }\n      pos = sub.offset + sub.old.size();\n      substitutions += 1;\n    }\n    sub.offset = s.find(sub.old, pos);\n    if (sub.offset == s.npos) {\n      subs.pop_back();\n    } else {\n      // Insertion sort to ensure the last ViableSubstitution continues to be\n      // before all the others.\n      size_t index = subs.size();\n      while (--index && subs[index - 1].OccursBefore(subs[index])) {\n        std::swap(subs[index], subs[index - 1]);\n      }\n    }\n  }\n  result_ptr->append(s.data() + pos, s.size() - pos);\n  return substitutions;\n}\n\n}  // namespace strings_internal\n\n// We can implement this in terms of the generic StrReplaceAll, but\n// we must specify the template overload because C++ cannot deduce the type\n// of an initializer_list parameter to a function, and also if we don't specify\n// the type, we just call ourselves.\n//\n// Note that we implement them here, rather than in the header, so that they\n// aren't inlined.\n\nstd::string StrReplaceAll(absl::string_view s,\n                          strings_internal::FixedMapping replacements) {\n  return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);\n}\n\nint StrReplaceAll(strings_internal::FixedMapping replacements,\n                  std::string* absl_nonnull target) {\n  return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/str_replace.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: str_replace.h\n// -----------------------------------------------------------------------------\n//\n// This file defines `absl::StrReplaceAll()`, a general-purpose string\n// replacement function designed for large, arbitrary text substitutions,\n// especially on strings which you are receiving from some other system for\n// further processing (e.g. processing regular expressions, escaping HTML\n// entities, etc.). `StrReplaceAll` is designed to be efficient even when only\n// one substitution is being performed, or when substitution is rare.\n//\n// If the string being modified is known at compile-time, and the substitutions\n// vary, `absl::Substitute()` may be a better choice.\n//\n// Example:\n//\n// std::string html_escaped = absl::StrReplaceAll(user_input, {\n//                                                {\"&\", \"&amp;\"},\n//                                                {\"<\", \"&lt;\"},\n//                                                {\">\", \"&gt;\"},\n//                                                {\"\\\"\", \"&quot;\"},\n//                                                {\"'\", \"&#39;\"}});\n#ifndef ABSL_STRINGS_STR_REPLACE_H_\n#define ABSL_STRINGS_STR_REPLACE_H_\n\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// StrReplaceAll()\n//\n// Replaces character sequences within a given string with replacements provided\n// within an initializer list of key/value pairs. Candidate replacements are\n// considered in order as they occur within the string, with earlier matches\n// taking precedence, and longer matches taking precedence for candidates\n// starting at the same position in the string. Once a substitution is made, the\n// replaced text is not considered for any further substitutions.\n//\n// Example:\n//\n//   std::string s = absl::StrReplaceAll(\n//       \"$who bought $count #Noun. Thanks $who!\",\n//       {{\"$count\", absl::StrCat(5)},\n//        {\"$who\", \"Bob\"},\n//        {\"#Noun\", \"Apples\"}});\n//   EXPECT_EQ(\"Bob bought 5 Apples. Thanks Bob!\", s);\n[[nodiscard]] std::string StrReplaceAll(\n    absl::string_view s,\n    std::initializer_list<std::pair<absl::string_view, absl::string_view>>\n        replacements);\n\n// Overload of `StrReplaceAll()` to accept a container of key/value replacement\n// pairs (typically either an associative map or a `std::vector` of `std::pair`\n// elements). A vector of pairs is generally more efficient.\n//\n// Examples:\n//\n//   std::map<const absl::string_view, const absl::string_view> replacements;\n//   replacements[\"$who\"] = \"Bob\";\n//   replacements[\"$count\"] = \"5\";\n//   replacements[\"#Noun\"] = \"Apples\";\n//   std::string s = absl::StrReplaceAll(\n//       \"$who bought $count #Noun. Thanks $who!\",\n//       replacements);\n//   EXPECT_EQ(\"Bob bought 5 Apples. Thanks Bob!\", s);\n//\n//   // A std::vector of std::pair elements can be more efficient.\n//   std::vector<std::pair<const absl::string_view, std::string>> replacements;\n//   replacements.push_back({\"&\", \"&amp;\"});\n//   replacements.push_back({\"<\", \"&lt;\"});\n//   replacements.push_back({\">\", \"&gt;\"});\n//   std::string s = absl::StrReplaceAll(\"if (ptr < &foo)\",\n//                                  replacements);\n//   EXPECT_EQ(\"if (ptr &lt; &amp;foo)\", s);\ntemplate <typename StrToStrMapping>\nstd::string StrReplaceAll(absl::string_view s,\n                          const StrToStrMapping& replacements);\n\n// Overload of `StrReplaceAll()` to replace character sequences within a given\n// output string *in place* with replacements provided within an initializer\n// list of key/value pairs, returning the number of substitutions that occurred.\n//\n// Example:\n//\n//   std::string s = std::string(\"$who bought $count #Noun. Thanks $who!\");\n//   int count;\n//   count = absl::StrReplaceAll({{\"$count\", absl::StrCat(5)},\n//                               {\"$who\", \"Bob\"},\n//                               {\"#Noun\", \"Apples\"}}, &s);\n//  EXPECT_EQ(count, 4);\n//  EXPECT_EQ(\"Bob bought 5 Apples. Thanks Bob!\", s);\nint StrReplaceAll(\n    std::initializer_list<std::pair<absl::string_view, absl::string_view>>\n        replacements,\n    std::string* absl_nonnull target);\n\n// Overload of `StrReplaceAll()` to replace patterns within a given output\n// string *in place* with replacements provided within a container of key/value\n// pairs.\n//\n// Example:\n//\n//   std::string s = std::string(\"if (ptr < &foo)\");\n//   int count = absl::StrReplaceAll({{\"&\", \"&amp;\"},\n//                                    {\"<\", \"&lt;\"},\n//                                    {\">\", \"&gt;\"}}, &s);\n//  EXPECT_EQ(count, 2);\n//  EXPECT_EQ(\"if (ptr &lt; &amp;foo)\", s);\ntemplate <typename StrToStrMapping>\nint StrReplaceAll(const StrToStrMapping& replacements,\n                  std::string* absl_nonnull target);\n\n// Implementation details only, past this point.\nnamespace strings_internal {\n\nstruct ViableSubstitution {\n  absl::string_view old;\n  absl::string_view replacement;\n  size_t offset;\n\n  ViableSubstitution(absl::string_view old_str,\n                     absl::string_view replacement_str, size_t offset_val)\n      : old(old_str), replacement(replacement_str), offset(offset_val) {}\n\n  // One substitution occurs \"before\" another (takes priority) if either\n  // it has the lowest offset, or it has the same offset but a larger size.\n  bool OccursBefore(const ViableSubstitution& y) const {\n    if (offset != y.offset) return offset < y.offset;\n    return old.size() > y.old.size();\n  }\n};\n\n// Build a vector of ViableSubstitutions based on the given list of\n// replacements. subs can be implemented as a priority_queue. However, it turns\n// out that most callers have small enough a list of substitutions that the\n// overhead of such a queue isn't worth it.\ntemplate <typename StrToStrMapping>\nstd::vector<ViableSubstitution> FindSubstitutions(\n    absl::string_view s, const StrToStrMapping& replacements) {\n  std::vector<ViableSubstitution> subs;\n  subs.reserve(replacements.size());\n\n  for (const auto& rep : replacements) {\n    using std::get;\n    absl::string_view old(get<0>(rep));\n\n    size_t pos = s.find(old);\n    if (pos == s.npos) continue;\n\n    // Ignore attempts to replace \"\". This condition is almost never true,\n    // but above condition is frequently true. That's why we test for this\n    // now and not before.\n    if (old.empty()) continue;\n\n    subs.emplace_back(old, get<1>(rep), pos);\n\n    // Insertion sort to ensure the last ViableSubstitution comes before\n    // all the others.\n    size_t index = subs.size();\n    while (--index && subs[index - 1].OccursBefore(subs[index])) {\n      std::swap(subs[index], subs[index - 1]);\n    }\n  }\n  return subs;\n}\n\nint ApplySubstitutions(absl::string_view s,\n                       std::vector<ViableSubstitution>* absl_nonnull subs_ptr,\n                       std::string* absl_nonnull result_ptr);\n\n}  // namespace strings_internal\n\ntemplate <typename StrToStrMapping>\nstd::string StrReplaceAll(absl::string_view s,\n                          const StrToStrMapping& replacements) {\n  auto subs = strings_internal::FindSubstitutions(s, replacements);\n  std::string result;\n  result.reserve(s.size());\n  strings_internal::ApplySubstitutions(s, &subs, &result);\n  return result;\n}\n\ntemplate <typename StrToStrMapping>\nint StrReplaceAll(const StrToStrMapping& replacements,\n                  std::string* absl_nonnull target) {\n  auto subs = strings_internal::FindSubstitutions(*target, replacements);\n  if (subs.empty()) return 0;\n\n  std::string result;\n  result.reserve(target->size());\n  int substitutions =\n      strings_internal::ApplySubstitutions(*target, &subs, &result);\n  target->swap(result);\n  return substitutions;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STR_REPLACE_H_\n"
  },
  {
    "path": "absl/strings/str_replace_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstring>\n#include <string>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/str_replace.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nstd::string* big_string;\nstd::string* after_replacing_the;\nstd::string* after_replacing_many;\n\nstruct Replacement {\n  const char* needle;\n  const char* replacement;\n} replacements[] = {\n    {\"the\", \"box\"},          //\n    {\"brown\", \"quick\"},      //\n    {\"jumped\", \"liquored\"},  //\n    {\"dozen\", \"brown\"},      //\n    {\"lazy\", \"pack\"},        //\n    {\"liquor\", \"shakes\"},    //\n};\n\n// Here, we set up a string for use in global-replace benchmarks.\n// We started with a million blanks, and then deterministically insert\n// 10,000 copies each of two pangrams.  The result is a string that is\n// 40% blank space and 60% these words.  'the' occurs 18,247 times and\n// all the substitutions together occur 49,004 times.\n//\n// We then create \"after_replacing_the\" to be a string that is a result of\n// replacing \"the\" with \"box\" in big_string.\n//\n// And then we create \"after_replacing_many\" to be a string that is result\n// of preferring several substitutions.\nvoid SetUpStrings() {\n  if (big_string == nullptr) {\n    size_t r = 0;\n    big_string = new std::string(1000 * 1000, ' ');\n    for (std::string phrase : {\"the quick brown fox jumped over the lazy dogs\",\n                               \"pack my box with the five dozen liquor jugs\"}) {\n      for (int i = 0; i < 10 * 1000; ++i) {\n        r = r * 237 + 41;  // not very random.\n        memcpy(&(*big_string)[r % (big_string->size() - phrase.size())],\n               phrase.data(), phrase.size());\n      }\n    }\n    // big_string->resize(50);\n    // OK, we've set up the string, now let's set up expectations - first by\n    // just replacing \"the\" with \"box\"\n    after_replacing_the = new std::string(*big_string);\n    for (size_t pos = 0;\n         (pos = after_replacing_the->find(\"the\", pos)) != std::string::npos;) {\n      memcpy(&(*after_replacing_the)[pos], \"box\", 3);\n    }\n    // And then with all the replacements.\n    after_replacing_many = new std::string(*big_string);\n    for (size_t pos = 0;;) {\n      size_t next_pos = static_cast<size_t>(-1);\n      const char* needle_string = nullptr;\n      const char* replacement_string = nullptr;\n      for (const auto& r : replacements) {\n        auto needlepos = after_replacing_many->find(r.needle, pos);\n        if (needlepos != std::string::npos && needlepos < next_pos) {\n          next_pos = needlepos;\n          needle_string = r.needle;\n          replacement_string = r.replacement;\n        }\n      }\n      if (next_pos > after_replacing_many->size()) break;\n      after_replacing_many->replace(next_pos, strlen(needle_string),\n                                    replacement_string);\n      next_pos += strlen(replacement_string);\n      pos = next_pos;\n    }\n  }\n}\n\nvoid BM_StrReplaceAllOneReplacement(benchmark::State& state) {\n  SetUpStrings();\n  std::string src = *big_string;\n  for (auto _ : state) {\n    std::string dest = absl::StrReplaceAll(src, {{\"the\", \"box\"}});\n    ABSL_RAW_CHECK(dest == *after_replacing_the,\n                   \"not benchmarking intended behavior\");\n  }\n}\nBENCHMARK(BM_StrReplaceAllOneReplacement);\n\nvoid BM_StrReplaceAll(benchmark::State& state) {\n  SetUpStrings();\n  std::string src = *big_string;\n  for (auto _ : state) {\n    std::string dest = absl::StrReplaceAll(src, {{\"the\", \"box\"},\n                                                 {\"brown\", \"quick\"},\n                                                 {\"jumped\", \"liquored\"},\n                                                 {\"dozen\", \"brown\"},\n                                                 {\"lazy\", \"pack\"},\n                                                 {\"liquor\", \"shakes\"}});\n    ABSL_RAW_CHECK(dest == *after_replacing_many,\n                   \"not benchmarking intended behavior\");\n  }\n}\nBENCHMARK(BM_StrReplaceAll);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_replace_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/str_replace.h\"\n\n#include <list>\n#include <map>\n#include <string>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n\nTEST(StrReplaceAll, OneReplacement) {\n  std::string s;\n\n  // Empty string.\n  s = absl::StrReplaceAll(s, {{\"\", \"\"}});\n  EXPECT_EQ(s, \"\");\n  s = absl::StrReplaceAll(s, {{\"x\", \"\"}});\n  EXPECT_EQ(s, \"\");\n  s = absl::StrReplaceAll(s, {{\"\", \"y\"}});\n  EXPECT_EQ(s, \"\");\n  s = absl::StrReplaceAll(s, {{\"x\", \"y\"}});\n  EXPECT_EQ(s, \"\");\n\n  // Empty substring.\n  s = absl::StrReplaceAll(\"abc\", {{\"\", \"\"}});\n  EXPECT_EQ(s, \"abc\");\n  s = absl::StrReplaceAll(\"abc\", {{\"\", \"y\"}});\n  EXPECT_EQ(s, \"abc\");\n  s = absl::StrReplaceAll(\"abc\", {{\"x\", \"\"}});\n  EXPECT_EQ(s, \"abc\");\n\n  // Substring not found.\n  s = absl::StrReplaceAll(\"abc\", {{\"xyz\", \"123\"}});\n  EXPECT_EQ(s, \"abc\");\n\n  // Replace entire string.\n  s = absl::StrReplaceAll(\"abc\", {{\"abc\", \"xyz\"}});\n  EXPECT_EQ(s, \"xyz\");\n\n  // Replace once at the start.\n  s = absl::StrReplaceAll(\"abc\", {{\"a\", \"x\"}});\n  EXPECT_EQ(s, \"xbc\");\n\n  // Replace once in the middle.\n  s = absl::StrReplaceAll(\"abc\", {{\"b\", \"x\"}});\n  EXPECT_EQ(s, \"axc\");\n\n  // Replace once at the end.\n  s = absl::StrReplaceAll(\"abc\", {{\"c\", \"x\"}});\n  EXPECT_EQ(s, \"abx\");\n\n  // Replace multiple times with varying lengths of original/replacement.\n  s = absl::StrReplaceAll(\"ababa\", {{\"a\", \"xxx\"}});\n  EXPECT_EQ(s, \"xxxbxxxbxxx\");\n\n  s = absl::StrReplaceAll(\"ababa\", {{\"b\", \"xxx\"}});\n  EXPECT_EQ(s, \"axxxaxxxa\");\n\n  s = absl::StrReplaceAll(\"aaabaaabaaa\", {{\"aaa\", \"x\"}});\n  EXPECT_EQ(s, \"xbxbx\");\n\n  s = absl::StrReplaceAll(\"abbbabbba\", {{\"bbb\", \"x\"}});\n  EXPECT_EQ(s, \"axaxa\");\n\n  // Overlapping matches are replaced greedily.\n  s = absl::StrReplaceAll(\"aaa\", {{\"aa\", \"x\"}});\n  EXPECT_EQ(s, \"xa\");\n\n  // The replacements are not recursive.\n  s = absl::StrReplaceAll(\"aaa\", {{\"aa\", \"a\"}});\n  EXPECT_EQ(s, \"aa\");\n}\n\nTEST(StrReplaceAll, ManyReplacements) {\n  std::string s;\n\n  // Empty string.\n  s = absl::StrReplaceAll(\"\", {{\"\", \"\"}, {\"x\", \"\"}, {\"\", \"y\"}, {\"x\", \"y\"}});\n  EXPECT_EQ(s, \"\");\n\n  // Empty substring.\n  s = absl::StrReplaceAll(\"abc\", {{\"\", \"\"}, {\"\", \"y\"}, {\"x\", \"\"}});\n  EXPECT_EQ(s, \"abc\");\n\n  // Replace entire string, one char at a time\n  s = absl::StrReplaceAll(\"abc\", {{\"a\", \"x\"}, {\"b\", \"y\"}, {\"c\", \"z\"}});\n  EXPECT_EQ(s, \"xyz\");\n  s = absl::StrReplaceAll(\"zxy\", {{\"z\", \"x\"}, {\"x\", \"y\"}, {\"y\", \"z\"}});\n  EXPECT_EQ(s, \"xyz\");\n\n  // Replace once at the start (longer matches take precedence)\n  s = absl::StrReplaceAll(\"abc\", {{\"a\", \"x\"}, {\"ab\", \"xy\"}, {\"abc\", \"xyz\"}});\n  EXPECT_EQ(s, \"xyz\");\n\n  // Replace once in the middle.\n  s = absl::StrReplaceAll(\n      \"Abc!\", {{\"a\", \"x\"}, {\"ab\", \"xy\"}, {\"b\", \"y\"}, {\"bc\", \"yz\"}, {\"c\", \"z\"}});\n  EXPECT_EQ(s, \"Ayz!\");\n\n  // Replace once at the end.\n  s = absl::StrReplaceAll(\n      \"Abc!\",\n      {{\"a\", \"x\"}, {\"ab\", \"xy\"}, {\"b\", \"y\"}, {\"bc!\", \"yz?\"}, {\"c!\", \"z;\"}});\n  EXPECT_EQ(s, \"Ayz?\");\n\n  // Replace multiple times with varying lengths of original/replacement.\n  s = absl::StrReplaceAll(\"ababa\", {{\"a\", \"xxx\"}, {\"b\", \"XXXX\"}});\n  EXPECT_EQ(s, \"xxxXXXXxxxXXXXxxx\");\n\n  // Overlapping matches are replaced greedily.\n  s = absl::StrReplaceAll(\"aaa\", {{\"aa\", \"x\"}, {\"a\", \"X\"}});\n  EXPECT_EQ(s, \"xX\");\n  s = absl::StrReplaceAll(\"aaa\", {{\"a\", \"X\"}, {\"aa\", \"x\"}});\n  EXPECT_EQ(s, \"xX\");\n\n  // Two well-known sentences\n  s = absl::StrReplaceAll(\"the quick brown fox jumped over the lazy dogs\",\n                          {\n                              {\"brown\", \"box\"},\n                              {\"dogs\", \"jugs\"},\n                              {\"fox\", \"with\"},\n                              {\"jumped\", \"five\"},\n                              {\"over\", \"dozen\"},\n                              {\"quick\", \"my\"},\n                              {\"the\", \"pack\"},\n                              {\"the lazy\", \"liquor\"},\n                          });\n  EXPECT_EQ(s, \"pack my box with five dozen liquor jugs\");\n}\n\nTEST(StrReplaceAll, ManyReplacementsInMap) {\n  std::map<const char *, const char *> replacements;\n  replacements[\"$who\"] = \"Bob\";\n  replacements[\"$count\"] = \"5\";\n  replacements[\"#Noun\"] = \"Apples\";\n  std::string s = absl::StrReplaceAll(\"$who bought $count #Noun. Thanks $who!\",\n                                      replacements);\n  EXPECT_EQ(\"Bob bought 5 Apples. Thanks Bob!\", s);\n}\n\nTEST(StrReplaceAll, ReplacementsInPlace) {\n  std::string s = std::string(\"$who bought $count #Noun. Thanks $who!\");\n  int count;\n  count = absl::StrReplaceAll({{\"$count\", absl::StrCat(5)},\n                              {\"$who\", \"Bob\"},\n                              {\"#Noun\", \"Apples\"}}, &s);\n  EXPECT_EQ(count, 4);\n  EXPECT_EQ(\"Bob bought 5 Apples. Thanks Bob!\", s);\n}\n\nTEST(StrReplaceAll, ReplacementsInPlaceInMap) {\n  std::string s = std::string(\"$who bought $count #Noun. Thanks $who!\");\n  std::map<absl::string_view, absl::string_view> replacements;\n  replacements[\"$who\"] = \"Bob\";\n  replacements[\"$count\"] = \"5\";\n  replacements[\"#Noun\"] = \"Apples\";\n  int count;\n  count = absl::StrReplaceAll(replacements, &s);\n  EXPECT_EQ(count, 4);\n  EXPECT_EQ(\"Bob bought 5 Apples. Thanks Bob!\", s);\n}\n\nstruct Cont {\n  Cont() = default;\n  explicit Cont(absl::string_view src) : data(src) {}\n\n  absl::string_view data;\n};\n\ntemplate <int index>\nabsl::string_view get(const Cont& c) {\n  auto splitter = absl::StrSplit(c.data, ':');\n  auto it = splitter.begin();\n  for (int i = 0; i < index; ++i) ++it;\n\n  return *it;\n}\n\nTEST(StrReplaceAll, VariableNumber) {\n  std::string s;\n  {\n    std::vector<std::pair<std::string, std::string>> replacements;\n\n    s = \"abc\";\n    EXPECT_EQ(0, absl::StrReplaceAll(replacements, &s));\n    EXPECT_EQ(\"abc\", s);\n\n    s = \"abc\";\n    replacements.push_back({\"a\", \"A\"});\n    EXPECT_EQ(1, absl::StrReplaceAll(replacements, &s));\n    EXPECT_EQ(\"Abc\", s);\n\n    s = \"abc\";\n    replacements.push_back({\"b\", \"B\"});\n    EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));\n    EXPECT_EQ(\"ABc\", s);\n\n    s = \"abc\";\n    replacements.push_back({\"d\", \"D\"});\n    EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));\n    EXPECT_EQ(\"ABc\", s);\n\n    EXPECT_EQ(\"ABcABc\", absl::StrReplaceAll(\"abcabc\", replacements));\n  }\n\n  {\n    std::map<const char*, const char*> replacements;\n    replacements[\"aa\"] = \"x\";\n    replacements[\"a\"] = \"X\";\n    s = \"aaa\";\n    EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));\n    EXPECT_EQ(\"xX\", s);\n\n    EXPECT_EQ(\"xxX\", absl::StrReplaceAll(\"aaaaa\", replacements));\n  }\n\n  {\n    std::list<std::pair<absl::string_view, absl::string_view>> replacements = {\n        {\"a\", \"x\"}, {\"b\", \"y\"}, {\"c\", \"z\"}};\n\n    std::string s = absl::StrReplaceAll(\"abc\", replacements);\n    EXPECT_EQ(s, \"xyz\");\n  }\n\n  {\n    using X = std::tuple<absl::string_view, std::string, int>;\n    std::vector<X> replacements(3);\n    replacements[0] = X{\"a\", \"x\", 1};\n    replacements[1] = X{\"b\", \"y\", 0};\n    replacements[2] = X{\"c\", \"z\", -1};\n\n    std::string s = absl::StrReplaceAll(\"abc\", replacements);\n    EXPECT_EQ(s, \"xyz\");\n  }\n\n  {\n    std::vector<Cont> replacements(3);\n    replacements[0] = Cont{\"a:x\"};\n    replacements[1] = Cont{\"b:y\"};\n    replacements[2] = Cont{\"c:z\"};\n\n    std::string s = absl::StrReplaceAll(\"abc\", replacements);\n    EXPECT_EQ(s, \"xyz\");\n  }\n}\n\n// Same as above, but using the in-place variant of absl::StrReplaceAll,\n// that returns the # of replacements performed.\nTEST(StrReplaceAll, Inplace) {\n  std::string s;\n  int reps;\n\n  // Empty string.\n  s = \"\";\n  reps = absl::StrReplaceAll({{\"\", \"\"}, {\"x\", \"\"}, {\"\", \"y\"}, {\"x\", \"y\"}}, &s);\n  EXPECT_EQ(reps, 0);\n  EXPECT_EQ(s, \"\");\n\n  // Empty substring.\n  s = \"abc\";\n  reps = absl::StrReplaceAll({{\"\", \"\"}, {\"\", \"y\"}, {\"x\", \"\"}}, &s);\n  EXPECT_EQ(reps, 0);\n  EXPECT_EQ(s, \"abc\");\n\n  // Replace entire string, one char at a time\n  s = \"abc\";\n  reps = absl::StrReplaceAll({{\"a\", \"x\"}, {\"b\", \"y\"}, {\"c\", \"z\"}}, &s);\n  EXPECT_EQ(reps, 3);\n  EXPECT_EQ(s, \"xyz\");\n  s = \"zxy\";\n  reps = absl::StrReplaceAll({{\"z\", \"x\"}, {\"x\", \"y\"}, {\"y\", \"z\"}}, &s);\n  EXPECT_EQ(reps, 3);\n  EXPECT_EQ(s, \"xyz\");\n\n  // Replace once at the start (longer matches take precedence)\n  s = \"abc\";\n  reps = absl::StrReplaceAll({{\"a\", \"x\"}, {\"ab\", \"xy\"}, {\"abc\", \"xyz\"}}, &s);\n  EXPECT_EQ(reps, 1);\n  EXPECT_EQ(s, \"xyz\");\n\n  // Replace once in the middle.\n  s = \"Abc!\";\n  reps = absl::StrReplaceAll(\n      {{\"a\", \"x\"}, {\"ab\", \"xy\"}, {\"b\", \"y\"}, {\"bc\", \"yz\"}, {\"c\", \"z\"}}, &s);\n  EXPECT_EQ(reps, 1);\n  EXPECT_EQ(s, \"Ayz!\");\n\n  // Replace once at the end.\n  s = \"Abc!\";\n  reps = absl::StrReplaceAll(\n      {{\"a\", \"x\"}, {\"ab\", \"xy\"}, {\"b\", \"y\"}, {\"bc!\", \"yz?\"}, {\"c!\", \"z;\"}}, &s);\n  EXPECT_EQ(reps, 1);\n  EXPECT_EQ(s, \"Ayz?\");\n\n  // Replace multiple times with varying lengths of original/replacement.\n  s = \"ababa\";\n  reps = absl::StrReplaceAll({{\"a\", \"xxx\"}, {\"b\", \"XXXX\"}}, &s);\n  EXPECT_EQ(reps, 5);\n  EXPECT_EQ(s, \"xxxXXXXxxxXXXXxxx\");\n\n  // Overlapping matches are replaced greedily.\n  s = \"aaa\";\n  reps = absl::StrReplaceAll({{\"aa\", \"x\"}, {\"a\", \"X\"}}, &s);\n  EXPECT_EQ(reps, 2);\n  EXPECT_EQ(s, \"xX\");\n  s = \"aaa\";\n  reps = absl::StrReplaceAll({{\"a\", \"X\"}, {\"aa\", \"x\"}}, &s);\n  EXPECT_EQ(reps, 2);\n  EXPECT_EQ(s, \"xX\");\n\n  // Two well-known sentences\n  s = \"the quick brown fox jumped over the lazy dogs\";\n  reps = absl::StrReplaceAll(\n      {\n          {\"brown\", \"box\"},\n          {\"dogs\", \"jugs\"},\n          {\"fox\", \"with\"},\n          {\"jumped\", \"five\"},\n          {\"over\", \"dozen\"},\n          {\"quick\", \"my\"},\n          {\"the\", \"pack\"},\n          {\"the lazy\", \"liquor\"},\n      },\n      &s);\n  EXPECT_EQ(reps, 8);\n  EXPECT_EQ(s, \"pack my box with five dozen liquor jugs\");\n}\n"
  },
  {
    "path": "absl/strings/str_split.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/str_split.h\"\n\n#include <algorithm>\n#include <cstddef>\n#include <cstdlib>\n#include <cstring>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\n// This GenericFind() template function encapsulates the finding algorithm\n// shared between the ByString and ByAnyChar delimiters. The FindPolicy\n// template parameter allows each delimiter to customize the actual find\n// function to use and the length of the found delimiter. For example, the\n// Literal delimiter will ultimately use absl::string_view::find(), and the\n// AnyOf delimiter will use absl::string_view::find_first_of().\ntemplate <typename FindPolicy>\nabsl::string_view GenericFind(absl::string_view text,\n                              absl::string_view delimiter, size_t pos,\n                              FindPolicy find_policy) {\n  if (delimiter.empty() && text.length() > 0) {\n    // Special case for empty string delimiters: always return a zero-length\n    // absl::string_view referring to the item at position 1 past pos.\n    return absl::string_view(text.data() + pos + 1, 0);\n  }\n  size_t found_pos = absl::string_view::npos;\n  absl::string_view found(text.data() + text.size(),\n                          0);  // By default, not found\n  found_pos = find_policy.Find(text, delimiter, pos);\n  if (found_pos != absl::string_view::npos) {\n    found = absl::string_view(text.data() + found_pos,\n                              find_policy.Length(delimiter));\n  }\n  return found;\n}\n\n// Finds using absl::string_view::find(), therefore the length of the found\n// delimiter is delimiter.length().\nstruct LiteralPolicy {\n  static size_t Find(absl::string_view text, absl::string_view delimiter,\n                     size_t pos) {\n    return text.find(delimiter, pos);\n  }\n  static size_t Length(absl::string_view delimiter) {\n    return delimiter.length();\n  }\n};\n\n// Finds using absl::string_view::find_first_of(), therefore the length of the\n// found delimiter is 1.\nstruct AnyOfPolicy {\n  static size_t Find(absl::string_view text, absl::string_view delimiter,\n                     size_t pos) {\n    return text.find_first_of(delimiter, pos);\n  }\n  static size_t Length(absl::string_view /* delimiter */) { return 1; }\n};\n\n}  // namespace\n\n//\n// ByString\n//\n\nByString::ByString(absl::string_view sp) : delimiter_(sp) {}\n\nabsl::string_view ByString::Find(absl::string_view text, size_t pos) const {\n  if (delimiter_.length() == 1) {\n    // Much faster to call find on a single character than on an\n    // absl::string_view.\n    size_t found_pos = text.find(delimiter_[0], pos);\n    if (found_pos == absl::string_view::npos)\n      return absl::string_view(text.data() + text.size(), 0);\n    return text.substr(found_pos, 1);\n  }\n  return GenericFind(text, delimiter_, pos, LiteralPolicy());\n}\n\nabsl::string_view ByAsciiWhitespace::Find(absl::string_view text,\n                                          size_t pos) const {\n  return GenericFind(text, \" \\t\\v\\f\\r\\n\", pos, AnyOfPolicy());\n}\n\n//\n// ByChar\n//\n\nabsl::string_view ByChar::Find(absl::string_view text, size_t pos) const {\n  size_t found_pos = text.find(c_, pos);\n  if (found_pos == absl::string_view::npos)\n    return absl::string_view(text.data() + text.size(), 0);\n  return text.substr(found_pos, 1);\n}\n\n//\n// ByAnyChar\n//\n\nByAnyChar::ByAnyChar(absl::string_view sp) : delimiters_(sp) {}\n\nabsl::string_view ByAnyChar::Find(absl::string_view text, size_t pos) const {\n  return GenericFind(text, delimiters_, pos, AnyOfPolicy());\n}\n\n//\n// ByLength\n//\nByLength::ByLength(ptrdiff_t length) : length_(length) {\n  ABSL_RAW_CHECK(length > 0, \"\");\n}\n\nabsl::string_view ByLength::Find(absl::string_view text, size_t pos) const {\n  pos = std::min(pos, text.size());  // truncate `pos`\n  absl::string_view substr = text.substr(pos);\n  // If the string is shorter than the chunk size we say we\n  // \"can't find the delimiter\" so this will be the last chunk.\n  if (substr.length() <= static_cast<size_t>(length_))\n    return absl::string_view(text.data() + text.size(), 0);\n\n  return absl::string_view(substr.data() + length_, 0);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/str_split.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: str_split.h\n// -----------------------------------------------------------------------------\n//\n// This file contains functions for splitting strings. It defines the main\n// `StrSplit()` function, several delimiters for determining the boundaries on\n// which to split the string, and predicates for filtering delimited results.\n// `StrSplit()` adapts the returned collection to the type specified by the\n// caller.\n//\n// Example:\n//\n//   // Splits the given string on commas. Returns the results in a\n//   // vector of strings.\n//   std::vector<std::string> v = absl::StrSplit(\"a,b,c\", ',');\n//   // Can also use \",\"\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\"\n//\n// See StrSplit() below for more information.\n#ifndef ABSL_STRINGS_STR_SPLIT_H_\n#define ABSL_STRINGS_STR_SPLIT_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <map>\n#include <set>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/internal/str_split_internal.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n//------------------------------------------------------------------------------\n// Delimiters\n//------------------------------------------------------------------------------\n//\n// `StrSplit()` uses delimiters to define the boundaries between elements in the\n// provided input. Several `Delimiter` types are defined below. If a string\n// (`const char*`, `std::string`, or `absl::string_view`) is passed in place of\n// an explicit `Delimiter` object, `StrSplit()` treats it the same way as if it\n// were passed a `ByString` delimiter.\n//\n// A `Delimiter` is an object with a `Find()` function that knows how to find\n// the first occurrence of itself in a given `absl::string_view`.\n//\n// The following `Delimiter` types are available for use within `StrSplit()`:\n//\n//   - `ByString` (default for string arguments)\n//   - `ByChar` (default for a char argument)\n//   - `ByAnyChar`\n//   - `ByLength`\n//   - `MaxSplits`\n//\n// A Delimiter's `Find()` member function will be passed an input `text` that is\n// to be split and a position (`pos`) to begin searching for the next delimiter\n// in `text`. The returned absl::string_view should refer to the next occurrence\n// (after `pos`) of the represented delimiter; this returned absl::string_view\n// represents the next location where the input `text` should be broken.\n//\n// The returned absl::string_view may be zero-length if the Delimiter does not\n// represent a part of the string (e.g., a fixed-length delimiter). If no\n// delimiter is found in the input `text`, a zero-length absl::string_view\n// referring to `text.end()` should be returned (e.g.,\n// `text.substr(text.size())`). It is important that the returned\n// absl::string_view always be within the bounds of the input `text` given as an\n// argument--it must not refer to a string that is physically located outside of\n// the given string.\n//\n// The following example is a simple Delimiter object that is created with a\n// single char and will look for that char in the text passed to the `Find()`\n// function:\n//\n//   struct SimpleDelimiter {\n//     const char c_;\n//     explicit SimpleDelimiter(char c) : c_(c) {}\n//     absl::string_view Find(absl::string_view text, size_t pos) {\n//       auto found = text.find(c_, pos);\n//       if (found == absl::string_view::npos)\n//         return text.substr(text.size());\n//\n//       return text.substr(found, 1);\n//     }\n//   };\n\n// ByString\n//\n// A sub-string delimiter. If `StrSplit()` is passed a string in place of a\n// `Delimiter` object, the string will be implicitly converted into a\n// `ByString` delimiter.\n//\n// Example:\n//\n//   // Because a string literal is converted to an `absl::ByString`,\n//   // the following two splits are equivalent.\n//\n//   std::vector<std::string> v1 = absl::StrSplit(\"a, b, c\", \", \");\n//\n//   using absl::ByString;\n//   std::vector<std::string> v2 = absl::StrSplit(\"a, b, c\",\n//                                                ByString(\", \"));\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\"\nclass ByString {\n public:\n  explicit ByString(absl::string_view sp);\n  absl::string_view Find(absl::string_view text, size_t pos) const;\n\n private:\n  std::string delimiter_;\n};\n\n// ByAsciiWhitespace\n//\n// A sub-string delimiter that splits by ASCII whitespace\n// (space, tab, vertical tab, formfeed, linefeed, or carriage return).\n// Note: you probably want to use absl::SkipEmpty() as well!\n//\n// This class is equivalent to ByAnyChar with ASCII whitespace chars.\n//\n// Example:\n//\n//   std::vector<std::string> v = absl::StrSplit(\n//       \"a b\\tc\\n  d  \\n\", absl::ByAsciiWhitespace(), absl::SkipEmpty());\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\", v[3] == \"d\"\nclass ByAsciiWhitespace {\n public:\n  absl::string_view Find(absl::string_view text, size_t pos) const;\n};\n\n// ByChar\n//\n// A single character delimiter. `ByChar` is functionally equivalent to a\n// 1-char string within a `ByString` delimiter, but slightly more efficient.\n//\n// Example:\n//\n//   // Because a char literal is converted to a absl::ByChar,\n//   // the following two splits are equivalent.\n//   std::vector<std::string> v1 = absl::StrSplit(\"a,b,c\", ',');\n//   using absl::ByChar;\n//   std::vector<std::string> v2 = absl::StrSplit(\"a,b,c\", ByChar(','));\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\"\n//\n// `ByChar` is also the default delimiter if a single character is given\n// as the delimiter to `StrSplit()`. For example, the following calls are\n// equivalent:\n//\n//   std::vector<std::string> v = absl::StrSplit(\"a-b\", '-');\n//\n//   using absl::ByChar;\n//   std::vector<std::string> v = absl::StrSplit(\"a-b\", ByChar('-'));\n//\nclass ByChar {\n public:\n  explicit ByChar(char c) : c_(c) {}\n  absl::string_view Find(absl::string_view text, size_t pos) const;\n\n private:\n  char c_;\n};\n\n// ByAnyChar\n//\n// A delimiter that will match any of the given byte-sized characters within\n// its provided string.\n//\n// Note: this delimiter works with single-byte string data, but does not work\n// with variable-width encodings, such as UTF-8.\n//\n// Example:\n//\n//   using absl::ByAnyChar;\n//   std::vector<std::string> v = absl::StrSplit(\"a,b=c\", ByAnyChar(\",=\"));\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\"\n//\n// If `ByAnyChar` is given the empty string, it behaves exactly like\n// `ByString` and matches each individual character in the input string.\n//\nclass ByAnyChar {\n public:\n  explicit ByAnyChar(absl::string_view sp);\n  absl::string_view Find(absl::string_view text, size_t pos) const;\n\n private:\n  const std::string delimiters_;\n};\n\n// ByLength\n//\n// A delimiter for splitting into equal-length strings. The length argument to\n// the constructor must be greater than 0.\n//\n// Note: this delimiter works with single-byte string data, but does not work\n// with variable-width encodings, such as UTF-8.\n//\n// Example:\n//\n//   using absl::ByLength;\n//   std::vector<std::string> v = absl::StrSplit(\"123456789\", ByLength(3));\n\n//   // v[0] == \"123\", v[1] == \"456\", v[2] == \"789\"\n//\n// Note that the string does not have to be a multiple of the fixed split\n// length. In such a case, the last substring will be shorter.\n//\n//   using absl::ByLength;\n//   std::vector<std::string> v = absl::StrSplit(\"12345\", ByLength(2));\n//\n//   // v[0] == \"12\", v[1] == \"34\", v[2] == \"5\"\nclass ByLength {\n public:\n  explicit ByLength(ptrdiff_t length);\n  absl::string_view Find(absl::string_view text, size_t pos) const;\n\n private:\n  const ptrdiff_t length_;\n};\n\nnamespace strings_internal {\n\n// A traits-like metafunction for selecting the default Delimiter object type\n// for a particular Delimiter type. The base case simply exposes type Delimiter\n// itself as the delimiter's Type. However, there are specializations for\n// string-like objects that map them to the ByString delimiter object.\n// This allows functions like absl::StrSplit() and absl::MaxSplits() to accept\n// string-like objects (e.g., ',') as delimiter arguments but they will be\n// treated as if a ByString delimiter was given.\ntemplate <typename Delimiter>\nstruct SelectDelimiter {\n  using type = Delimiter;\n};\n\ntemplate <>\nstruct SelectDelimiter<char> {\n  using type = ByChar;\n};\ntemplate <>\nstruct SelectDelimiter<char*> {\n  using type = ByString;\n};\ntemplate <>\nstruct SelectDelimiter<const char*> {\n  using type = ByString;\n};\ntemplate <>\nstruct SelectDelimiter<absl::string_view> {\n  using type = ByString;\n};\ntemplate <>\nstruct SelectDelimiter<std::string> {\n  using type = ByString;\n};\n\n// Wraps another delimiter and sets a max number of matches for that delimiter.\ntemplate <typename Delimiter>\nclass MaxSplitsImpl {\n public:\n  MaxSplitsImpl(Delimiter delimiter, int limit)\n      : delimiter_(std::move(delimiter)), limit_(limit), count_(0) {}\n  absl::string_view Find(absl::string_view text, size_t pos) {\n    if (count_++ == limit_) {\n      return absl::string_view(text.data() + text.size(),\n                               0);  // No more matches.\n    }\n    return delimiter_.Find(text, pos);\n  }\n\n private:\n  Delimiter delimiter_;\n  const int limit_;\n  int count_;\n};\n\n}  // namespace strings_internal\n\n// MaxSplits()\n//\n// A delimiter that limits the number of matches which can occur to the passed\n// `limit`. The last element in the returned collection will contain all\n// remaining unsplit pieces, which may contain instances of the delimiter.\n// The collection will contain at most `limit` + 1 elements.\n// Example:\n//\n//   using absl::MaxSplits;\n//   std::vector<std::string> v = absl::StrSplit(\"a,b,c\", MaxSplits(',', 1));\n//\n//   // v[0] == \"a\", v[1] == \"b,c\"\ntemplate <typename Delimiter>\ninline strings_internal::MaxSplitsImpl<\n    typename strings_internal::SelectDelimiter<Delimiter>::type>\nMaxSplits(Delimiter delimiter, int limit) {\n  typedef\n      typename strings_internal::SelectDelimiter<Delimiter>::type DelimiterType;\n  return strings_internal::MaxSplitsImpl<DelimiterType>(\n      DelimiterType(delimiter), limit);\n}\n\n//------------------------------------------------------------------------------\n// Predicates\n//------------------------------------------------------------------------------\n//\n// Predicates filter the results of a `StrSplit()` by determining whether or not\n// a resultant element is included in the result set. A predicate may be passed\n// as an optional third argument to the `StrSplit()` function.\n//\n// Predicates are unary functions (or functors) that take a single\n// `absl::string_view` argument and return a bool indicating whether the\n// argument should be included (`true`) or excluded (`false`).\n//\n// Predicates are useful when filtering out empty substrings. By default, empty\n// substrings may be returned by `StrSplit()`, which is similar to the way split\n// functions work in other programming languages.\n\n// AllowEmpty()\n//\n// Always returns `true`, indicating that all strings--including empty\n// strings--should be included in the split output. This predicate is not\n// strictly needed because this is the default behavior of `StrSplit()`;\n// however, it might be useful at some call sites to make the intent explicit.\n//\n// Example:\n//\n//  std::vector<std::string> v = absl::StrSplit(\" a , ,,b,\", ',', AllowEmpty());\n//\n//  // v[0] == \" a \", v[1] == \" \", v[2] == \"\", v[3] = \"b\", v[4] == \"\"\nstruct AllowEmpty {\n  bool operator()(absl::string_view) const { return true; }\n};\n\n// SkipEmpty()\n//\n// Returns `false` if the given `absl::string_view` is empty, indicating that\n// `StrSplit()` should omit the empty string.\n//\n// Example:\n//\n//   std::vector<std::string> v = absl::StrSplit(\",a,,b,\", ',', SkipEmpty());\n//\n//   // v[0] == \"a\", v[1] == \"b\"\n//\n// Note: `SkipEmpty()` does not consider a string containing only whitespace\n// to be empty. To skip such whitespace as well, use the `SkipWhitespace()`\n// predicate.\nstruct SkipEmpty {\n  bool operator()(absl::string_view sp) const { return !sp.empty(); }\n};\n\n// SkipWhitespace()\n//\n// Returns `false` if the given `absl::string_view` is empty *or* contains only\n// whitespace, indicating that `StrSplit()` should omit the string.\n//\n// Example:\n//\n//   std::vector<std::string> v = absl::StrSplit(\" a , ,,b,\",\n//                                               ',', SkipWhitespace());\n//   // v[0] == \" a \", v[1] == \"b\"\n//\n//   // SkipEmpty() would return whitespace elements\n//   std::vector<std::string> v = absl::StrSplit(\" a , ,,b,\", ',', SkipEmpty());\n//   // v[0] == \" a \", v[1] == \" \", v[2] == \"b\"\nstruct SkipWhitespace {\n  bool operator()(absl::string_view sp) const {\n    sp = absl::StripLeadingAsciiWhitespace(sp);\n    return !sp.empty();\n  }\n};\n\ntemplate <typename T>\nusing EnableSplitIfString =\n    typename std::enable_if<std::is_same<T, std::string>::value ||\n                            std::is_same<T, const std::string>::value,\n                            int>::type;\n\n//------------------------------------------------------------------------------\n//                                  StrSplit()\n//------------------------------------------------------------------------------\n\n// StrSplit()\n//\n// Splits a given string based on the provided `Delimiter` object, returning the\n// elements within the type specified by the caller. Optionally, you may pass a\n// `Predicate` to `StrSplit()` indicating whether to include or exclude the\n// resulting element within the final result set. (See the overviews for\n// Delimiters and Predicates above.)\n//\n// Example:\n//\n//   std::vector<std::string> v = absl::StrSplit(\"a,b,c,d\", ',');\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\", v[3] == \"d\"\n//\n// You can also provide an explicit `Delimiter` object:\n//\n// Example:\n//\n//   using absl::ByAnyChar;\n//   std::vector<std::string> v = absl::StrSplit(\"a,b=c\", ByAnyChar(\",=\"));\n//   // v[0] == \"a\", v[1] == \"b\", v[2] == \"c\"\n//\n// See above for more information on delimiters.\n//\n// By default, empty strings are included in the result set. You can optionally\n// include a third `Predicate` argument to apply a test for whether the\n// resultant element should be included in the result set:\n//\n// Example:\n//\n//   std::vector<std::string> v = absl::StrSplit(\" a , ,,b,\",\n//                                               ',', SkipWhitespace());\n//   // v[0] == \" a \", v[1] == \"b\"\n//\n// See above for more information on predicates.\n//\n//------------------------------------------------------------------------------\n// StrSplit() Return Types\n//------------------------------------------------------------------------------\n//\n// The `StrSplit()` function adapts the returned collection to the collection\n// specified by the caller (e.g. `std::vector` above). The returned collections\n// may contain `std::string`, `absl::string_view` (in which case the original\n// string being split must ensure that it outlives the collection), or any\n// object that can be explicitly created from an `absl::string_view`. This\n// behavior works for:\n//\n// 1) All standard STL containers including `std::vector`, `std::list`,\n//    `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`.\n// 2) `std::pair` (which is not actually a container). See below.\n// 3) `std::array`, which is a container but has different behavior due to its\n//    fixed size. See below.\n//\n// Example:\n//\n//   // The results are returned as `absl::string_view` objects. Note that we\n//   // have to ensure that the input string outlives any results.\n//   std::vector<absl::string_view> v = absl::StrSplit(\"a,b,c\", ',');\n//\n//   // Stores results in a std::set<std::string>, which also performs\n//   // de-duplication and orders the elements in ascending order.\n//   std::set<std::string> a = absl::StrSplit(\"b,a,c,a,b\", ',');\n//   // a[0] == \"a\", a[1] == \"b\", a[2] == \"c\"\n//\n//   // `StrSplit()` can be used within a range-based for loop, in which case\n//   // each element will be of type `absl::string_view`.\n//   std::vector<std::string> v;\n//   for (const auto sv : absl::StrSplit(\"a,b,c\", ',')) {\n//     if (sv != \"b\") v.emplace_back(sv);\n//   }\n//   // v[0] == \"a\", v[1] == \"c\"\n//\n//   // Stores results in a map. The map implementation assumes that the input\n//   // is provided as a series of key/value pairs. For example, the 0th element\n//   // resulting from the split will be stored as a key to the 1st element. If\n//   // an odd number of elements are resolved, the last element is paired with\n//   // a default-constructed value (e.g., empty string).\n//   std::map<std::string, std::string> m = absl::StrSplit(\"a,b,c\", ',');\n//   // m[\"a\"] == \"b\", m[\"c\"] == \"\"     // last component value equals \"\"\n//\n// Splitting to `std::pair` is an interesting case because it can hold only two\n// elements and is not a collection type. When splitting to a `std::pair` the\n// first two split strings become the `std::pair` `.first` and `.second`\n// members, respectively. The remaining split substrings are discarded. If there\n// are less than two split substrings, the empty string is used for the\n// corresponding `std::pair` member.\n//\n// Example:\n//\n//   // Stores first two split strings as the members in a std::pair.\n//   std::pair<std::string, std::string> p = absl::StrSplit(\"a,b,c\", ',');\n//   // p.first == \"a\", p.second == \"b\"       // \"c\" is omitted.\n//\n//\n// Splitting to `std::array` is similar to splitting to `std::pair`, but for\n// N elements instead of two; missing elements are filled with the empty string\n// and extra elements are discarded.\n//\n// Examples:\n//\n//   // Stores first two split strings as the elements in a std::array.\n//   std::array<std::string, 2> a = absl::StrSplit(\"a,b,c\", ',');\n//   // a[0] == \"a\", a[1] == \"b\"   // \"c\" is omitted.\n//\n//   // The second element is empty.\n//   std::array<std::string, 2> a = absl::StrSplit(\"a,\", ',');\n//   // a[0] == \"a\", a[1] == \"\"\n//\n// The `StrSplit()` function can be used multiple times to perform more\n// complicated splitting logic, such as intelligently parsing key-value pairs.\n//\n// Example:\n//\n//   // The input string \"a=b=c,d=e,f=,g\" becomes\n//   // { \"a\" => \"b=c\", \"d\" => \"e\", \"f\" => \"\", \"g\" => \"\" }\n//   std::map<std::string, std::string> m;\n//   for (absl::string_view sp : absl::StrSplit(\"a=b=c,d=e,f=,g\", ',')) {\n//     m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));\n//   }\n//   EXPECT_EQ(\"b=c\", m.find(\"a\")->second);\n//   EXPECT_EQ(\"e\", m.find(\"d\")->second);\n//   EXPECT_EQ(\"\", m.find(\"f\")->second);\n//   EXPECT_EQ(\"\", m.find(\"g\")->second);\n//\n// WARNING: Due to a legacy bug that is maintained for backward compatibility,\n// splitting the following empty string_views produces different results:\n//\n//   absl::StrSplit(absl::string_view(\"\"), '-');  // {\"\"}\n//   absl::StrSplit(absl::string_view(), '-');    // {}, but should be {\"\"}\n//\n// Try not to depend on this distinction because the bug may one day be fixed.\ntemplate <typename Delimiter>\nstrings_internal::Splitter<\n    typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,\n    absl::string_view>\nStrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {\n  using DelimiterType =\n      typename strings_internal::SelectDelimiter<Delimiter>::type;\n  return strings_internal::Splitter<DelimiterType, AllowEmpty,\n                                    absl::string_view>(\n      text.value(), DelimiterType(d), AllowEmpty());\n}\n\ntemplate <typename Delimiter, typename StringType,\n          EnableSplitIfString<StringType> = 0>\nstrings_internal::Splitter<\n    typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,\n    std::string>\nStrSplit(StringType&& text, Delimiter d) {\n  using DelimiterType =\n      typename strings_internal::SelectDelimiter<Delimiter>::type;\n  return strings_internal::Splitter<DelimiterType, AllowEmpty, std::string>(\n      std::move(text), DelimiterType(d), AllowEmpty());\n}\n\ntemplate <typename Delimiter, typename Predicate>\nstrings_internal::Splitter<\n    typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,\n    absl::string_view>\nStrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,\n         Predicate p) {\n  using DelimiterType =\n      typename strings_internal::SelectDelimiter<Delimiter>::type;\n  return strings_internal::Splitter<DelimiterType, Predicate,\n                                    absl::string_view>(\n      text.value(), DelimiterType(std::move(d)), std::move(p));\n}\n\ntemplate <typename Delimiter, typename Predicate, typename StringType,\n          EnableSplitIfString<StringType> = 0>\nstrings_internal::Splitter<\n    typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,\n    std::string>\nStrSplit(StringType&& text, Delimiter d, Predicate p) {\n  using DelimiterType =\n      typename strings_internal::SelectDelimiter<Delimiter>::type;\n  return strings_internal::Splitter<DelimiterType, Predicate, std::string>(\n      std::move(text), DelimiterType(d), std::move(p));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STR_SPLIT_H_\n"
  },
  {
    "path": "absl/strings/str_split_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <iterator>\n#include <string>\n#include <unordered_map>\n#include <unordered_set>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nstd::string MakeTestString(int desired_length) {\n  static const int kAverageValueLen = 25;\n  std::string test(desired_length * kAverageValueLen, 'x');\n  for (int i = 1; i < test.size(); i += kAverageValueLen) {\n    test[i] = ';';\n  }\n  return test;\n}\n\nvoid BM_Split2StringView(benchmark::State& state) {\n  std::string test = MakeTestString(state.range(0));\n  for (auto _ : state) {\n    std::vector<absl::string_view> result = absl::StrSplit(test, ';');\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20);\n\nstatic const absl::string_view kDelimiters = \";:,.\";\n\nstd::string MakeMultiDelimiterTestString(int desired_length) {\n  static const int kAverageValueLen = 25;\n  std::string test(desired_length * kAverageValueLen, 'x');\n  for (int i = 0; i * kAverageValueLen < test.size(); ++i) {\n    // Cycle through a variety of delimiters.\n    test[i * kAverageValueLen] = kDelimiters[i % kDelimiters.size()];\n  }\n  return test;\n}\n\n// Measure StrSplit with ByAnyChar with four delimiters to choose from.\nvoid BM_Split2StringViewByAnyChar(benchmark::State& state) {\n  std::string test = MakeMultiDelimiterTestString(state.range(0));\n  for (auto _ : state) {\n    std::vector<absl::string_view> result =\n        absl::StrSplit(test, absl::ByAnyChar(kDelimiters));\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_Split2StringViewByAnyChar, 0, 1 << 20);\n\nvoid BM_Split2StringViewLifted(benchmark::State& state) {\n  std::string test = MakeTestString(state.range(0));\n  std::vector<absl::string_view> result;\n  for (auto _ : state) {\n    result = absl::StrSplit(test, ';');\n  }\n  benchmark::DoNotOptimize(result);\n}\nBENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20);\n\nvoid BM_Split2String(benchmark::State& state) {\n  std::string test = MakeTestString(state.range(0));\n  for (auto _ : state) {\n    std::vector<std::string> result = absl::StrSplit(test, ';');\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_Split2String, 0, 1 << 20);\n\n// This benchmark is for comparing Split2 to Split1 (SplitStringUsing). In\n// particular, this benchmark uses SkipEmpty() to match SplitStringUsing's\n// behavior.\nvoid BM_Split2SplitStringUsing(benchmark::State& state) {\n  std::string test = MakeTestString(state.range(0));\n  for (auto _ : state) {\n    std::vector<std::string> result =\n        absl::StrSplit(test, ';', absl::SkipEmpty());\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_Split2SplitStringUsing, 0, 1 << 20);\n\nvoid BM_SplitStringToUnorderedSet(benchmark::State& state) {\n  const int len = state.range(0);\n  std::string test(len, 'x');\n  for (int i = 1; i < len; i += 2) {\n    test[i] = ';';\n  }\n  for (auto _ : state) {\n    std::unordered_set<std::string> result =\n        absl::StrSplit(test, ':', absl::SkipEmpty());\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_SplitStringToUnorderedSet, 0, 1 << 20);\n\nvoid BM_SplitStringToUnorderedMap(benchmark::State& state) {\n  const int len = state.range(0);\n  std::string test(len, 'x');\n  for (int i = 1; i < len; i += 2) {\n    test[i] = ';';\n  }\n  for (auto _ : state) {\n    std::unordered_map<std::string, std::string> result =\n        absl::StrSplit(test, ':', absl::SkipEmpty());\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_SplitStringToUnorderedMap, 0, 1 << 20);\n\nvoid BM_SplitStringAllowEmpty(benchmark::State& state) {\n  const int len = state.range(0);\n  std::string test(len, 'x');\n  for (int i = 1; i < len; i += 2) {\n    test[i] = ';';\n  }\n  for (auto _ : state) {\n    std::vector<std::string> result = absl::StrSplit(test, ';');\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK_RANGE(BM_SplitStringAllowEmpty, 0, 1 << 20);\n\nstruct OneCharLiteral {\n  char operator()() const { return 'X'; }\n};\n\nstruct OneCharStringLiteral {\n  const char* operator()() const { return \"X\"; }\n};\n\ntemplate <typename DelimiterFactory>\nvoid BM_SplitStringWithOneChar(benchmark::State& state) {\n  const auto delimiter = DelimiterFactory()();\n  std::vector<absl::string_view> pieces;\n  size_t v = 0;\n  for (auto _ : state) {\n    pieces = absl::StrSplit(\"The quick brown fox jumps over the lazy dog\",\n                            delimiter);\n    v += pieces.size();\n  }\n  ABSL_RAW_CHECK(v == state.iterations(), \"\");\n}\nBENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharLiteral);\nBENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharStringLiteral);\n\ntemplate <typename DelimiterFactory>\nvoid BM_SplitStringWithOneCharNoVector(benchmark::State& state) {\n  const auto delimiter = DelimiterFactory()();\n  size_t v = 0;\n  for (auto _ : state) {\n    auto splitter = absl::StrSplit(\n        \"The quick brown fox jumps over the lazy dog\", delimiter);\n    v += std::distance(splitter.begin(), splitter.end());\n  }\n  ABSL_RAW_CHECK(v == state.iterations(), \"\");\n}\nBENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral);\nBENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/str_split_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/str_split.h\"\n\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n#include <initializer_list>\n#include <list>\n#include <map>\n#include <memory>\n#include <set>\n#include <string>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/container/btree_map.h\"\n#include \"absl/container/btree_set.h\"\n#include \"absl/container/flat_hash_map.h\"\n#include \"absl/container/node_hash_map.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::IsEmpty;\nusing ::testing::Pair;\nusing ::testing::UnorderedElementsAre;\n\nTEST(Split, TraitsTest) {\n  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value,\n                \"\");\n  static_assert(\n      !absl::strings_internal::SplitterIsConvertibleTo<std::string>::value, \"\");\n  static_assert(absl::strings_internal::SplitterIsConvertibleTo<\n                    std::vector<std::string>>::value,\n                \"\");\n  static_assert(\n      !absl::strings_internal::SplitterIsConvertibleTo<std::vector<int>>::value,\n      \"\");\n  static_assert(absl::strings_internal::SplitterIsConvertibleTo<\n                    std::vector<absl::string_view>>::value,\n                \"\");\n  static_assert(absl::strings_internal::SplitterIsConvertibleTo<\n                    std::map<std::string, std::string>>::value,\n                \"\");\n  static_assert(absl::strings_internal::SplitterIsConvertibleTo<\n                    std::map<absl::string_view, absl::string_view>>::value,\n                \"\");\n  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<\n                    std::map<int, std::string>>::value,\n                \"\");\n  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<\n                    std::map<std::string, int>>::value,\n                \"\");\n}\n\n// This tests the overall split API, which is made up of the absl::StrSplit()\n// function and the Delimiter objects in the absl:: namespace.\n// This TEST macro is outside of any namespace to require full specification of\n// namespaces just like callers will need to use.\nTEST(Split, APIExamples) {\n  {\n    // Passes string delimiter. Assumes the default of ByString.\n    std::vector<std::string> v = absl::StrSplit(\"a,b,c\", \",\");  // NOLINT\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n\n    // Equivalent to...\n    using absl::ByString;\n    v = absl::StrSplit(\"a,b,c\", ByString(\",\"));\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n\n    // Equivalent to...\n    EXPECT_THAT(absl::StrSplit(\"a,b,c\", ByString(\",\")),\n                ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Same as above, but using a single character as the delimiter.\n    std::vector<std::string> v = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n\n    // Equivalent to...\n    using absl::ByChar;\n    v = absl::StrSplit(\"a,b,c\", ByChar(','));\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Uses the Literal string \"=>\" as the delimiter.\n    const std::vector<std::string> v = absl::StrSplit(\"a=>b=>c\", \"=>\");\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // The substrings are returned as string_views, eliminating copying.\n    std::vector<absl::string_view> v = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Leading and trailing empty substrings.\n    std::vector<std::string> v = absl::StrSplit(\",a,b,c,\", ',');\n    EXPECT_THAT(v, ElementsAre(\"\", \"a\", \"b\", \"c\", \"\"));\n  }\n\n  {\n    // Splits on a delimiter that is not found.\n    std::vector<std::string> v = absl::StrSplit(\"abc\", ',');\n    EXPECT_THAT(v, ElementsAre(\"abc\"));\n  }\n\n  {\n    // Splits the input string into individual characters by using an empty\n    // string as the delimiter.\n    std::vector<std::string> v = absl::StrSplit(\"abc\", \"\");\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Splits string data with embedded NUL characters, using NUL as the\n    // delimiter. A simple delimiter of \"\\0\" doesn't work because strlen() will\n    // say that's the empty string when constructing the absl::string_view\n    // delimiter. Instead, a non-empty string containing NUL can be used as the\n    // delimiter.\n    std::string embedded_nulls(\"a\\0b\\0c\", 5);\n    std::string null_delim(\"\\0\", 1);\n    std::vector<std::string> v = absl::StrSplit(embedded_nulls, null_delim);\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Stores first two split strings as the members in a std::pair.\n    std::pair<std::string, std::string> p = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_EQ(\"a\", p.first);\n    EXPECT_EQ(\"b\", p.second);\n    // \"c\" is omitted because std::pair can hold only two elements.\n  }\n\n  {\n    // Results stored in std::set<std::string>\n    std::set<std::string> v = absl::StrSplit(\"a,b,c,a,b,c,a,b,c\", ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Uses a non-const char* delimiter.\n    char a[] = \",\";\n    char* d = a + 0;\n    std::vector<std::string> v = absl::StrSplit(\"a,b,c\", d);\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Results split using either of , or ;\n    using absl::ByAnyChar;\n    std::vector<std::string> v = absl::StrSplit(\"a,b;c\", ByAnyChar(\",;\"));\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Uses the SkipWhitespace predicate.\n    using absl::SkipWhitespace;\n    std::vector<std::string> v =\n        absl::StrSplit(\" a , ,,b,\", ',', SkipWhitespace());\n    EXPECT_THAT(v, ElementsAre(\" a \", \"b\"));\n  }\n\n  {\n    // Uses the ByLength delimiter.\n    using absl::ByLength;\n    std::vector<std::string> v = absl::StrSplit(\"abcdefg\", ByLength(3));\n    EXPECT_THAT(v, ElementsAre(\"abc\", \"def\", \"g\"));\n  }\n\n  {\n    // Different forms of initialization / conversion.\n    std::vector<std::string> v1 = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(v1, ElementsAre(\"a\", \"b\", \"c\"));\n    std::vector<std::string> v2(absl::StrSplit(\"a,b,c\", ','));\n    EXPECT_THAT(v2, ElementsAre(\"a\", \"b\", \"c\"));\n    auto v3 = std::vector<std::string>(absl::StrSplit(\"a,b,c\", ','));\n    EXPECT_THAT(v3, ElementsAre(\"a\", \"b\", \"c\"));\n    v3 = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(v3, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Results stored in a std::map.\n    std::map<std::string, std::string> m = absl::StrSplit(\"a,1,b,2,a,3\", ',');\n    EXPECT_EQ(2, m.size());\n    EXPECT_EQ(\"3\", m[\"a\"]);\n    EXPECT_EQ(\"2\", m[\"b\"]);\n  }\n\n  {\n    // Results stored in a std::multimap.\n    std::multimap<std::string, std::string> m =\n        absl::StrSplit(\"a,1,b,2,a,3\", ',');\n    EXPECT_EQ(3, m.size());\n    auto it = m.lower_bound(\"a\");\n    EXPECT_EQ(\"1\", it->second);\n    ++it;\n    EXPECT_EQ(\"3\", it->second);\n    it = m.find(\"b\");\n    EXPECT_EQ(\"2\", it->second);\n  }\n\n  {\n    // Demonstrates use in a range-based for loop in C++11.\n    std::string s = \"x,x,x,x,x,x,x\";\n    for (absl::string_view sp : absl::StrSplit(s, ',')) {\n      EXPECT_EQ(\"x\", sp);\n    }\n  }\n\n  {\n    // Demonstrates use with a Predicate in a range-based for loop.\n    using absl::SkipWhitespace;\n    std::string s = \" ,x,,x,,x,x,x,,\";\n    for (absl::string_view sp : absl::StrSplit(s, ',', SkipWhitespace())) {\n      EXPECT_EQ(\"x\", sp);\n    }\n  }\n\n  {\n    // Demonstrates a \"smart\" split to std::map using two separate calls to\n    // absl::StrSplit. One call to split the records, and another call to split\n    // the keys and values. This also uses the Limit delimiter so that the\n    // std::string \"a=b=c\" will split to \"a\" -> \"b=c\".\n    std::map<std::string, std::string> m;\n    for (absl::string_view sp : absl::StrSplit(\"a=b=c,d=e,f=,g\", ',')) {\n      m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));\n    }\n    EXPECT_EQ(\"b=c\", m.find(\"a\")->second);\n    EXPECT_EQ(\"e\", m.find(\"d\")->second);\n    EXPECT_EQ(\"\", m.find(\"f\")->second);\n    EXPECT_EQ(\"\", m.find(\"g\")->second);\n  }\n}\n\n//\n// Tests for SplitIterator\n//\n\nTEST(SplitIterator, Basics) {\n  auto splitter = absl::StrSplit(\"a,b\", ',');\n  auto it = splitter.begin();\n  auto end = splitter.end();\n\n  EXPECT_NE(it, end);\n  EXPECT_EQ(\"a\", *it);  // tests dereference\n  ++it;                 // tests preincrement\n  EXPECT_NE(it, end);\n  EXPECT_EQ(\"b\",\n            std::string(it->data(), it->size()));  // tests dereference as ptr\n  it++;                                            // tests postincrement\n  EXPECT_EQ(it, end);\n}\n\n// Simple Predicate to skip a particular string.\nclass Skip {\n public:\n  explicit Skip(const std::string& s) : s_(s) {}\n  bool operator()(absl::string_view sp) { return sp != s_; }\n\n private:\n  std::string s_;\n};\n\nTEST(SplitIterator, Predicate) {\n  auto splitter = absl::StrSplit(\"a,b,c\", ',', Skip(\"b\"));\n  auto it = splitter.begin();\n  auto end = splitter.end();\n\n  EXPECT_NE(it, end);\n  EXPECT_EQ(\"a\", *it);  // tests dereference\n  ++it;                 // tests preincrement -- \"b\" should be skipped here.\n  EXPECT_NE(it, end);\n  EXPECT_EQ(\"c\",\n            std::string(it->data(), it->size()));  // tests dereference as ptr\n  it++;                                            // tests postincrement\n  EXPECT_EQ(it, end);\n}\n\nTEST(SplitIterator, EdgeCases) {\n  // Expected input and output, assuming a delimiter of ','\n  struct {\n    std::string in;\n    std::vector<std::string> expect;\n  } specs[] = {\n      {\"\", {\"\"}},\n      {\"foo\", {\"foo\"}},\n      {\",\", {\"\", \"\"}},\n      {\",foo\", {\"\", \"foo\"}},\n      {\"foo,\", {\"foo\", \"\"}},\n      {\",foo,\", {\"\", \"foo\", \"\"}},\n      {\"foo,bar\", {\"foo\", \"bar\"}},\n  };\n\n  for (const auto& spec : specs) {\n    SCOPED_TRACE(spec.in);\n    auto splitter = absl::StrSplit(spec.in, ',');\n    auto it = splitter.begin();\n    auto end = splitter.end();\n    for (const auto& expected : spec.expect) {\n      EXPECT_NE(it, end);\n      EXPECT_EQ(expected, *it++);\n    }\n    EXPECT_EQ(it, end);\n  }\n}\n\nTEST(Splitter, Const) {\n  const auto splitter = absl::StrSplit(\"a,b,c\", ',');\n  EXPECT_THAT(splitter, ElementsAre(\"a\", \"b\", \"c\"));\n}\n\nTEST(Split, EmptyAndNull) {\n  // Attention: Splitting a null absl::string_view is different than splitting\n  // an empty absl::string_view even though both string_views are considered\n  // equal. This behavior is likely surprising and undesirable. However, to\n  // maintain backward compatibility, there is a small \"hack\" in\n  // str_split_internal.h that preserves this behavior. If that behavior is ever\n  // changed/fixed, this test will need to be updated.\n  EXPECT_THAT(absl::StrSplit(absl::string_view(\"\"), '-'), ElementsAre(\"\"));\n  EXPECT_THAT(absl::StrSplit(absl::string_view(), '-'), ElementsAre());\n}\n\nTEST(SplitIterator, EqualityAsEndCondition) {\n  auto splitter = absl::StrSplit(\"a,b,c\", ',');\n  auto it = splitter.begin();\n  auto it2 = it;\n\n  // Increments it2 twice to point to \"c\" in the input text.\n  ++it2;\n  ++it2;\n  EXPECT_EQ(\"c\", *it2);\n\n  // This test uses a non-end SplitIterator as the terminating condition in a\n  // for loop. This relies on SplitIterator equality for non-end SplitIterators\n  // working correctly. At this point it2 points to \"c\", and we use that as the\n  // \"end\" condition in this test.\n  std::vector<absl::string_view> v;\n  for (; it != it2; ++it) {\n    v.push_back(*it);\n  }\n  EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n}\n\n//\n// Tests for Splitter\n//\n\nTEST(Splitter, RangeIterators) {\n  auto splitter = absl::StrSplit(\"a,b,c\", ',');\n  std::vector<absl::string_view> output;\n  for (absl::string_view p : splitter) {\n    output.push_back(p);\n  }\n  EXPECT_THAT(output, ElementsAre(\"a\", \"b\", \"c\"));\n}\n\n// Some template functions for use in testing conversion operators\ntemplate <typename ContainerType, typename Splitter>\nvoid TestConversionOperator(const Splitter& splitter) {\n  ContainerType output = splitter;\n  EXPECT_THAT(output, UnorderedElementsAre(\"a\", \"b\", \"c\", \"d\"));\n}\n\ntemplate <typename MapType, typename Splitter>\nvoid TestMapConversionOperator(const Splitter& splitter) {\n  MapType m = splitter;\n  EXPECT_THAT(m, UnorderedElementsAre(Pair(\"a\", \"b\"), Pair(\"c\", \"d\")));\n}\n\ntemplate <typename FirstType, typename SecondType, typename Splitter>\nvoid TestPairConversionOperator(const Splitter& splitter) {\n  std::pair<FirstType, SecondType> p = splitter;\n  EXPECT_EQ(p, (std::pair<FirstType, SecondType>(\"a\", \"b\")));\n}\n\ntemplate <typename StringType, typename Splitter>\nvoid TestArrayConversionOperator(const Splitter& splitter) {\n  std::array<StringType, 2> a = splitter;\n  EXPECT_THAT(a, ElementsAre(\"a\", \"b\"));\n}\n\nTEST(Splitter, ConversionOperator) {\n  auto splitter = absl::StrSplit(\"a,b,c,d\", ',');\n\n  TestConversionOperator<std::vector<absl::string_view>>(splitter);\n  TestConversionOperator<std::vector<std::string>>(splitter);\n  TestConversionOperator<std::list<absl::string_view>>(splitter);\n  TestConversionOperator<std::list<std::string>>(splitter);\n  TestConversionOperator<std::deque<absl::string_view>>(splitter);\n  TestConversionOperator<std::deque<std::string>>(splitter);\n  TestConversionOperator<std::set<absl::string_view>>(splitter);\n  TestConversionOperator<std::set<std::string>>(splitter);\n  TestConversionOperator<std::multiset<absl::string_view>>(splitter);\n  TestConversionOperator<std::multiset<std::string>>(splitter);\n  TestConversionOperator<absl::btree_set<absl::string_view>>(splitter);\n  TestConversionOperator<absl::btree_set<std::string>>(splitter);\n  TestConversionOperator<absl::btree_multiset<absl::string_view>>(splitter);\n  TestConversionOperator<absl::btree_multiset<std::string>>(splitter);\n  TestConversionOperator<std::unordered_set<std::string>>(splitter);\n  TestConversionOperator<\n      std::unordered_set<absl::string_view, absl::Hash<absl::string_view>>>(\n      splitter);\n\n  // Tests conversion to map-like objects.\n\n  TestMapConversionOperator<std::map<absl::string_view, absl::string_view>>(\n      splitter);\n  TestMapConversionOperator<std::map<absl::string_view, std::string>>(splitter);\n  TestMapConversionOperator<std::map<std::string, absl::string_view>>(splitter);\n  TestMapConversionOperator<std::map<std::string, std::string>>(splitter);\n  TestMapConversionOperator<\n      std::multimap<absl::string_view, absl::string_view>>(splitter);\n  TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(\n      splitter);\n  TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(\n      splitter);\n  TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);\n  TestMapConversionOperator<\n      absl::btree_map<absl::string_view, absl::string_view>>(splitter);\n  TestMapConversionOperator<absl::btree_map<absl::string_view, std::string>>(\n      splitter);\n  TestMapConversionOperator<absl::btree_map<std::string, absl::string_view>>(\n      splitter);\n  TestMapConversionOperator<absl::btree_map<std::string, std::string>>(\n      splitter);\n  TestMapConversionOperator<\n      absl::btree_multimap<absl::string_view, absl::string_view>>(splitter);\n  TestMapConversionOperator<\n      absl::btree_multimap<absl::string_view, std::string>>(splitter);\n  TestMapConversionOperator<\n      absl::btree_multimap<std::string, absl::string_view>>(splitter);\n  TestMapConversionOperator<absl::btree_multimap<std::string, std::string>>(\n      splitter);\n  TestMapConversionOperator<std::unordered_map<std::string, std::string>>(\n      splitter);\n  TestMapConversionOperator<std::unordered_map<\n      absl::string_view, absl::string_view, absl::Hash<absl::string_view>>>(\n      splitter);\n  TestMapConversionOperator<std::unordered_map<absl::string_view, std::string,\n                                               absl::Hash<absl::string_view>>>(\n      splitter);\n  TestMapConversionOperator<std::unordered_map<std::string, absl::string_view,\n                                               absl::Hash<absl::string_view>>>(\n      splitter);\n  TestMapConversionOperator<\n      absl::node_hash_map<absl::string_view, absl::string_view>>(splitter);\n  TestMapConversionOperator<\n      absl::node_hash_map<absl::string_view, std::string>>(splitter);\n  TestMapConversionOperator<\n      absl::node_hash_map<std::string, absl::string_view>>(splitter);\n  TestMapConversionOperator<\n      absl::flat_hash_map<absl::string_view, absl::string_view>>(splitter);\n  TestMapConversionOperator<\n      absl::flat_hash_map<absl::string_view, std::string>>(splitter);\n  TestMapConversionOperator<\n      absl::flat_hash_map<std::string, absl::string_view>>(splitter);\n\n  // Tests conversion to std::pair\n\n  TestPairConversionOperator<absl::string_view, absl::string_view>(splitter);\n  TestPairConversionOperator<absl::string_view, std::string>(splitter);\n  TestPairConversionOperator<std::string, absl::string_view>(splitter);\n  TestPairConversionOperator<std::string, std::string>(splitter);\n\n  // Tests conversion to std::array\n  TestArrayConversionOperator<std::string>(splitter);\n  TestArrayConversionOperator<absl::string_view>(splitter);\n}\n\n// A few additional tests for conversion to std::pair. This conversion is\n// different from others because a std::pair always has exactly two elements:\n// .first and .second. The split has to work even when the split has\n// less-than, equal-to, and more-than 2 strings.\nTEST(Splitter, ToPair) {\n  {\n    // Empty string\n    std::pair<std::string, std::string> p = absl::StrSplit(\"\", ',');\n    EXPECT_EQ(\"\", p.first);\n    EXPECT_EQ(\"\", p.second);\n  }\n\n  {\n    // Only first\n    std::pair<std::string, std::string> p = absl::StrSplit(\"a\", ',');\n    EXPECT_EQ(\"a\", p.first);\n    EXPECT_EQ(\"\", p.second);\n  }\n\n  {\n    // Only second\n    std::pair<std::string, std::string> p = absl::StrSplit(\",b\", ',');\n    EXPECT_EQ(\"\", p.first);\n    EXPECT_EQ(\"b\", p.second);\n  }\n\n  {\n    // First and second.\n    std::pair<std::string, std::string> p = absl::StrSplit(\"a,b\", ',');\n    EXPECT_EQ(\"a\", p.first);\n    EXPECT_EQ(\"b\", p.second);\n  }\n\n  {\n    // First and second and then more stuff that will be ignored.\n    std::pair<std::string, std::string> p = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_EQ(\"a\", p.first);\n    EXPECT_EQ(\"b\", p.second);\n    // \"c\" is omitted.\n  }\n}\n\n// std::array tests similar to std::pair tests above, testing fewer, exactly,\n// or more elements than the array size.\nTEST(Splitter, ToArray) {\n  {\n    // Empty string\n    std::array<std::string, 2> p = absl::StrSplit(\"\", ',');\n    EXPECT_THAT(p, ElementsAre(\"\", \"\"));\n  }\n\n  {\n    // Only first\n    std::array<std::string, 2> p = absl::StrSplit(\"a\", ',');\n    EXPECT_THAT(p, ElementsAre(\"a\", \"\"));\n  }\n\n  {\n    // Only second\n    std::array<std::string, 2> p = absl::StrSplit(\",b\", ',');\n    EXPECT_THAT(p, ElementsAre(\"\", \"b\"));\n  }\n\n  {\n    // First and second.\n    std::array<std::string, 2> p = absl::StrSplit(\"a,b\", ',');\n    EXPECT_THAT(p, ElementsAre(\"a\", \"b\"));\n  }\n\n  {\n    // First and second and then more stuff that will be ignored.\n    std::array<std::string, 2> p = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(p, ElementsAre(\"a\", \"b\"));\n    // \"c\" is omitted.\n  }\n}\n\nTEST(Splitter, Predicates) {\n  static const char kTestChars[] = \",a, ,b,\";\n  using absl::AllowEmpty;\n  using absl::SkipEmpty;\n  using absl::SkipWhitespace;\n\n  {\n    // No predicate. Does not skip empties.\n    auto splitter = absl::StrSplit(kTestChars, ',');\n    std::vector<std::string> v = splitter;\n    EXPECT_THAT(v, ElementsAre(\"\", \"a\", \" \", \"b\", \"\"));\n  }\n\n  {\n    // Allows empty strings. Same behavior as no predicate at all.\n    auto splitter = absl::StrSplit(kTestChars, ',', AllowEmpty());\n    std::vector<std::string> v_allowempty = splitter;\n    EXPECT_THAT(v_allowempty, ElementsAre(\"\", \"a\", \" \", \"b\", \"\"));\n\n    // Ensures AllowEmpty equals the behavior with no predicate.\n    auto splitter_nopredicate = absl::StrSplit(kTestChars, ',');\n    std::vector<std::string> v_nopredicate = splitter_nopredicate;\n    EXPECT_EQ(v_allowempty, v_nopredicate);\n  }\n\n  {\n    // Skips empty strings.\n    auto splitter = absl::StrSplit(kTestChars, ',', SkipEmpty());\n    std::vector<std::string> v = splitter;\n    EXPECT_THAT(v, ElementsAre(\"a\", \" \", \"b\"));\n  }\n\n  {\n    // Skips empty and all-whitespace strings.\n    auto splitter = absl::StrSplit(kTestChars, ',', SkipWhitespace());\n    std::vector<std::string> v = splitter;\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n  }\n}\n\n//\n// Tests for StrSplit()\n//\n\nTEST(Split, Basics) {\n  {\n    // Doesn't really do anything useful because the return value is ignored,\n    // but it should work.\n    absl::StrSplit(\"a,b,c\", ',');\n  }\n\n  {\n    std::vector<absl::string_view> v = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    std::vector<std::string> v = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n  }\n\n  {\n    // Ensures that assignment works. This requires a little extra work with\n    // C++11 because of overloads with initializer_list.\n    std::vector<std::string> v;\n    v = absl::StrSplit(\"a,b,c\", ',');\n\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\", \"c\"));\n    std::map<std::string, std::string> m;\n    m = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_EQ(2, m.size());\n    std::unordered_map<std::string, std::string> hm;\n    hm = absl::StrSplit(\"a,b,c\", ',');\n    EXPECT_EQ(2, hm.size());\n  }\n}\n\nabsl::string_view ReturnStringView() { return \"Hello World\"; }\nconst char* ReturnConstCharP() { return \"Hello World\"; }\nchar* ReturnCharP() { return const_cast<char*>(\"Hello World\"); }\n\nTEST(Split, AcceptsCertainTemporaries) {\n  std::vector<std::string> v;\n  v = absl::StrSplit(ReturnStringView(), ' ');\n  EXPECT_THAT(v, ElementsAre(\"Hello\", \"World\"));\n  v = absl::StrSplit(ReturnConstCharP(), ' ');\n  EXPECT_THAT(v, ElementsAre(\"Hello\", \"World\"));\n  v = absl::StrSplit(ReturnCharP(), ' ');\n  EXPECT_THAT(v, ElementsAre(\"Hello\", \"World\"));\n}\n\nTEST(Split, Temporary) {\n  // Use a std::string longer than the SSO length, so that when the temporary is\n  // destroyed, if the splitter keeps a reference to the string's contents,\n  // it'll reference freed memory instead of just dead on-stack memory.\n  const char input[] = \"a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u\";\n  EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input))\n      << \"Input should be larger than fits on the stack.\";\n\n  // This happens more often in C++11 as part of a range-based for loop.\n  auto splitter = absl::StrSplit(std::string(input), ',');\n  std::string expected = \"a\";\n  for (absl::string_view letter : splitter) {\n    EXPECT_EQ(expected, letter);\n    ++expected[0];\n  }\n  EXPECT_EQ(\"v\", expected);\n\n  // This happens more often in C++11 as part of a range-based for loop.\n  auto std_splitter = absl::StrSplit(std::string(input), ',');\n  expected = \"a\";\n  for (absl::string_view letter : std_splitter) {\n    EXPECT_EQ(expected, letter);\n    ++expected[0];\n  }\n  EXPECT_EQ(\"v\", expected);\n}\n\ntemplate <typename T>\nstatic std::unique_ptr<T> CopyToHeap(const T& value) {\n  return std::unique_ptr<T>(new T(value));\n}\n\nTEST(Split, LvalueCaptureIsCopyable) {\n  std::string input = \"a,b\";\n  auto heap_splitter = CopyToHeap(absl::StrSplit(input, ','));\n  auto stack_splitter = *heap_splitter;\n  heap_splitter.reset();\n  std::vector<std::string> result = stack_splitter;\n  EXPECT_THAT(result, testing::ElementsAre(\"a\", \"b\"));\n}\n\nTEST(Split, TemporaryCaptureIsCopyable) {\n  auto heap_splitter = CopyToHeap(absl::StrSplit(std::string(\"a,b\"), ','));\n  auto stack_splitter = *heap_splitter;\n  heap_splitter.reset();\n  std::vector<std::string> result = stack_splitter;\n  EXPECT_THAT(result, testing::ElementsAre(\"a\", \"b\"));\n}\n\nTEST(Split, SplitterIsCopyableAndMoveable) {\n  auto a = absl::StrSplit(\"foo\", '-');\n\n  // Ensures that the following expressions compile.\n  auto b = a;             // Copy construct\n  auto c = std::move(a);  // Move construct\n  b = c;                  // Copy assign\n  c = std::move(b);       // Move assign\n\n  EXPECT_THAT(c, ElementsAre(\"foo\"));\n}\n\nTEST(Split, StringDelimiter) {\n  {\n    std::vector<absl::string_view> v = absl::StrSplit(\"a,b\", ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n  }\n\n  {\n    std::vector<absl::string_view> v = absl::StrSplit(\"a,b\", std::string(\",\"));\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n  }\n\n  {\n    std::vector<absl::string_view> v =\n        absl::StrSplit(\"a,b\", absl::string_view(\",\"));\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n  }\n}\n\n#if !defined(__cpp_char8_t)\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wc++2a-compat\"\n#endif\nTEST(Split, UTF8) {\n  // Tests splitting utf8 strings and utf8 delimiters.\n  std::string utf8_string = u8\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\";\n  {\n    // A utf8 input string with an ascii delimiter.\n    std::string to_split = \"a,\" + utf8_string;\n    std::vector<absl::string_view> v = absl::StrSplit(to_split, ',');\n    EXPECT_THAT(v, ElementsAre(\"a\", utf8_string));\n  }\n\n  {\n    // A utf8 input string and a utf8 delimiter.\n    std::string to_split = \"a,\" + utf8_string + \",b\";\n    std::string unicode_delimiter = \",\" + utf8_string + \",\";\n    std::vector<absl::string_view> v =\n        absl::StrSplit(to_split, unicode_delimiter);\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n  }\n\n  {\n    // A utf8 input string and ByAnyChar with ascii chars.\n    std::vector<absl::string_view> v =\n        absl::StrSplit(u8\"Foo h\\u00E4llo th\\u4E1Ere\", absl::ByAnyChar(\" \\t\"));\n    EXPECT_THAT(v, ElementsAre(\"Foo\", u8\"h\\u00E4llo\", u8\"th\\u4E1Ere\"));\n  }\n}\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n#endif  // !defined(__cpp_char8_t)\n\nTEST(Split, EmptyStringDelimiter) {\n  {\n    std::vector<std::string> v = absl::StrSplit(\"\", \"\");\n    EXPECT_THAT(v, ElementsAre(\"\"));\n  }\n\n  {\n    std::vector<std::string> v = absl::StrSplit(\"a\", \"\");\n    EXPECT_THAT(v, ElementsAre(\"a\"));\n  }\n\n  {\n    std::vector<std::string> v = absl::StrSplit(\"ab\", \"\");\n    EXPECT_THAT(v, ElementsAre(\"a\", \"b\"));\n  }\n\n  {\n    std::vector<std::string> v = absl::StrSplit(\"a b\", \"\");\n    EXPECT_THAT(v, ElementsAre(\"a\", \" \", \"b\"));\n  }\n}\n\nTEST(Split, SubstrDelimiter) {\n  std::vector<absl::string_view> results;\n  absl::string_view delim(\"//\");\n\n  results = absl::StrSplit(\"\", delim);\n  EXPECT_THAT(results, ElementsAre(\"\"));\n\n  results = absl::StrSplit(\"//\", delim);\n  EXPECT_THAT(results, ElementsAre(\"\", \"\"));\n\n  results = absl::StrSplit(\"ab\", delim);\n  EXPECT_THAT(results, ElementsAre(\"ab\"));\n\n  results = absl::StrSplit(\"ab//\", delim);\n  EXPECT_THAT(results, ElementsAre(\"ab\", \"\"));\n\n  results = absl::StrSplit(\"ab/\", delim);\n  EXPECT_THAT(results, ElementsAre(\"ab/\"));\n\n  results = absl::StrSplit(\"a/b\", delim);\n  EXPECT_THAT(results, ElementsAre(\"a/b\"));\n\n  results = absl::StrSplit(\"a//b\", delim);\n  EXPECT_THAT(results, ElementsAre(\"a\", \"b\"));\n\n  results = absl::StrSplit(\"a///b\", delim);\n  EXPECT_THAT(results, ElementsAre(\"a\", \"/b\"));\n\n  results = absl::StrSplit(\"a////b\", delim);\n  EXPECT_THAT(results, ElementsAre(\"a\", \"\", \"b\"));\n}\n\nTEST(Split, EmptyResults) {\n  std::vector<absl::string_view> results;\n\n  results = absl::StrSplit(\"\", '#');\n  EXPECT_THAT(results, ElementsAre(\"\"));\n\n  results = absl::StrSplit(\"#\", '#');\n  EXPECT_THAT(results, ElementsAre(\"\", \"\"));\n\n  results = absl::StrSplit(\"#cd\", '#');\n  EXPECT_THAT(results, ElementsAre(\"\", \"cd\"));\n\n  results = absl::StrSplit(\"ab#cd#\", '#');\n  EXPECT_THAT(results, ElementsAre(\"ab\", \"cd\", \"\"));\n\n  results = absl::StrSplit(\"ab##cd\", '#');\n  EXPECT_THAT(results, ElementsAre(\"ab\", \"\", \"cd\"));\n\n  results = absl::StrSplit(\"ab##\", '#');\n  EXPECT_THAT(results, ElementsAre(\"ab\", \"\", \"\"));\n\n  results = absl::StrSplit(\"ab#ab#\", '#');\n  EXPECT_THAT(results, ElementsAre(\"ab\", \"ab\", \"\"));\n\n  results = absl::StrSplit(\"aaaa\", 'a');\n  EXPECT_THAT(results, ElementsAre(\"\", \"\", \"\", \"\", \"\"));\n\n  results = absl::StrSplit(\"\", '#', absl::SkipEmpty());\n  EXPECT_THAT(results, ElementsAre());\n}\n\ntemplate <typename Delimiter>\nstatic bool IsFoundAtStartingPos(absl::string_view text, Delimiter d,\n                                 size_t starting_pos, int expected_pos) {\n  absl::string_view found = d.Find(text, starting_pos);\n  return found.data() != text.data() + text.size() &&\n         expected_pos == found.data() - text.data();\n}\n\n// Helper function for testing Delimiter objects. Returns true if the given\n// Delimiter is found in the given string at the given position. This function\n// tests two cases:\n//   1. The actual text given, staring at position 0\n//   2. The text given with leading padding that should be ignored\ntemplate <typename Delimiter>\nstatic bool IsFoundAt(absl::string_view text, Delimiter d, int expected_pos) {\n  const std::string leading_text = \",x,y,z,\";\n  return IsFoundAtStartingPos(text, d, 0, expected_pos) &&\n         IsFoundAtStartingPos(leading_text + std::string(text), d,\n                              leading_text.length(),\n                              expected_pos + leading_text.length());\n}\n\n//\n// Tests for ByString\n//\n\n// Tests using any delimiter that represents a single comma.\ntemplate <typename Delimiter>\nvoid TestComma(Delimiter d) {\n  EXPECT_TRUE(IsFoundAt(\",\", d, 0));\n  EXPECT_TRUE(IsFoundAt(\"a,\", d, 1));\n  EXPECT_TRUE(IsFoundAt(\",b\", d, 0));\n  EXPECT_TRUE(IsFoundAt(\"a,b\", d, 1));\n  EXPECT_TRUE(IsFoundAt(\"a,b,\", d, 1));\n  EXPECT_TRUE(IsFoundAt(\"a,b,c\", d, 1));\n  EXPECT_FALSE(IsFoundAt(\"\", d, -1));\n  EXPECT_FALSE(IsFoundAt(\" \", d, -1));\n  EXPECT_FALSE(IsFoundAt(\"a\", d, -1));\n  EXPECT_FALSE(IsFoundAt(\"a b c\", d, -1));\n  EXPECT_FALSE(IsFoundAt(\"a;b;c\", d, -1));\n  EXPECT_FALSE(IsFoundAt(\";\", d, -1));\n}\n\nTEST(Delimiter, ByString) {\n  using absl::ByString;\n  TestComma(ByString(\",\"));\n\n  // Works as named variable.\n  ByString comma_string(\",\");\n  TestComma(comma_string);\n\n  // The first occurrence of empty string (\"\") in a string is at position 0.\n  // There is a test below that demonstrates this for absl::string_view::find().\n  // If the ByString delimiter returned position 0 for this, there would\n  // be an infinite loop in the SplitIterator code. To avoid this, empty string\n  // is a special case in that it always returns the item at position 1.\n  absl::string_view abc(\"abc\");\n  EXPECT_EQ(0, abc.find(\"\"));  // \"\" is found at position 0\n  ByString empty(\"\");\n  EXPECT_FALSE(IsFoundAt(\"\", empty, 0));\n  EXPECT_FALSE(IsFoundAt(\"a\", empty, 0));\n  EXPECT_TRUE(IsFoundAt(\"ab\", empty, 1));\n  EXPECT_TRUE(IsFoundAt(\"abc\", empty, 1));\n}\n\nTEST(Split, ByChar) {\n  using absl::ByChar;\n  TestComma(ByChar(','));\n\n  // Works as named variable.\n  ByChar comma_char(',');\n  TestComma(comma_char);\n}\n\n//\n// Tests for ByAnyChar\n//\n\nTEST(Delimiter, ByAnyChar) {\n  using absl::ByAnyChar;\n  ByAnyChar one_delim(\",\");\n  // Found\n  EXPECT_TRUE(IsFoundAt(\",\", one_delim, 0));\n  EXPECT_TRUE(IsFoundAt(\"a,\", one_delim, 1));\n  EXPECT_TRUE(IsFoundAt(\"a,b\", one_delim, 1));\n  EXPECT_TRUE(IsFoundAt(\",b\", one_delim, 0));\n  // Not found\n  EXPECT_FALSE(IsFoundAt(\"\", one_delim, -1));\n  EXPECT_FALSE(IsFoundAt(\" \", one_delim, -1));\n  EXPECT_FALSE(IsFoundAt(\"a\", one_delim, -1));\n  EXPECT_FALSE(IsFoundAt(\"a;b;c\", one_delim, -1));\n  EXPECT_FALSE(IsFoundAt(\";\", one_delim, -1));\n\n  ByAnyChar two_delims(\",;\");\n  // Found\n  EXPECT_TRUE(IsFoundAt(\",\", two_delims, 0));\n  EXPECT_TRUE(IsFoundAt(\";\", two_delims, 0));\n  EXPECT_TRUE(IsFoundAt(\",;\", two_delims, 0));\n  EXPECT_TRUE(IsFoundAt(\";,\", two_delims, 0));\n  EXPECT_TRUE(IsFoundAt(\",;b\", two_delims, 0));\n  EXPECT_TRUE(IsFoundAt(\";,b\", two_delims, 0));\n  EXPECT_TRUE(IsFoundAt(\"a;,\", two_delims, 1));\n  EXPECT_TRUE(IsFoundAt(\"a,;\", two_delims, 1));\n  EXPECT_TRUE(IsFoundAt(\"a;,b\", two_delims, 1));\n  EXPECT_TRUE(IsFoundAt(\"a,;b\", two_delims, 1));\n  // Not found\n  EXPECT_FALSE(IsFoundAt(\"\", two_delims, -1));\n  EXPECT_FALSE(IsFoundAt(\" \", two_delims, -1));\n  EXPECT_FALSE(IsFoundAt(\"a\", two_delims, -1));\n  EXPECT_FALSE(IsFoundAt(\"a=b=c\", two_delims, -1));\n  EXPECT_FALSE(IsFoundAt(\"=\", two_delims, -1));\n\n  // ByAnyChar behaves just like ByString when given a delimiter of empty\n  // string. That is, it always returns a zero-length absl::string_view\n  // referring to the item at position 1, not position 0.\n  ByAnyChar empty(\"\");\n  EXPECT_FALSE(IsFoundAt(\"\", empty, 0));\n  EXPECT_FALSE(IsFoundAt(\"a\", empty, 0));\n  EXPECT_TRUE(IsFoundAt(\"ab\", empty, 1));\n  EXPECT_TRUE(IsFoundAt(\"abc\", empty, 1));\n}\n\n//\n// Tests for ByAsciiWhitespace\n//\nTEST(Split, ByAsciiWhitespace) {\n  using absl::ByAsciiWhitespace;\n  using absl::SkipEmpty;\n  std::vector<absl::string_view> results;\n\n  results = absl::StrSplit(\"aaaa\\n\", ByAsciiWhitespace());\n  EXPECT_THAT(results, ElementsAre(\"aaaa\", \"\"));\n\n  results = absl::StrSplit(\"aaaa\\n\", ByAsciiWhitespace(), SkipEmpty());\n  EXPECT_THAT(results, ElementsAre(\"aaaa\"));\n\n  results = absl::StrSplit(\" \", ByAsciiWhitespace());\n  EXPECT_THAT(results, ElementsAre(\"\", \"\"));\n\n  results = absl::StrSplit(\" \", ByAsciiWhitespace(), SkipEmpty());\n  EXPECT_THAT(results, IsEmpty());\n\n  results = absl::StrSplit(\"a\", ByAsciiWhitespace());\n  EXPECT_THAT(results, ElementsAre(\"a\"));\n\n  results = absl::StrSplit(\"\", ByAsciiWhitespace());\n  EXPECT_THAT(results, ElementsAre(\"\"));\n\n  results = absl::StrSplit(\"\", ByAsciiWhitespace(), SkipEmpty());\n  EXPECT_THAT(results, IsEmpty());\n\n  results = absl::StrSplit(\"a b\\tc\\n  d\\n\", ByAsciiWhitespace());\n  EXPECT_THAT(results, ElementsAre(\"a\", \"b\", \"c\", \"\", \"\", \"d\", \"\"));\n\n  results = absl::StrSplit(\"a b\\tc\\n  d  \\n\", ByAsciiWhitespace(), SkipEmpty());\n  EXPECT_THAT(results, ElementsAre(\"a\", \"b\", \"c\", \"d\"));\n\n  results = absl::StrSplit(\"a\\t\\n\\v\\f\\r b\", ByAsciiWhitespace(), SkipEmpty());\n  EXPECT_THAT(results, ElementsAre(\"a\", \"b\"));\n}\n\n//\n// Tests for ByLength\n//\n\nTEST(Delimiter, ByLength) {\n  using absl::ByLength;\n\n  ByLength four_char_delim(4);\n\n  // Found\n  EXPECT_TRUE(IsFoundAt(\"abcde\", four_char_delim, 4));\n  EXPECT_TRUE(IsFoundAt(\"abcdefghijklmnopqrstuvwxyz\", four_char_delim, 4));\n  EXPECT_TRUE(IsFoundAt(\"a b,c\\nd\", four_char_delim, 4));\n  // Not found\n  EXPECT_FALSE(IsFoundAt(\"\", four_char_delim, 0));\n  EXPECT_FALSE(IsFoundAt(\"a\", four_char_delim, 0));\n  EXPECT_FALSE(IsFoundAt(\"ab\", four_char_delim, 0));\n  EXPECT_FALSE(IsFoundAt(\"abc\", four_char_delim, 0));\n  EXPECT_FALSE(IsFoundAt(\"abcd\", four_char_delim, 0));\n}\n\nTEST(Split, WorksWithLargeStrings) {\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)\n  constexpr size_t kSize = (uint32_t{1} << 26) + 1;  // 64M + 1 byte\n#else\n  constexpr size_t kSize = (uint32_t{1} << 31) + 1;  // 2G + 1 byte\n#endif\n  if (sizeof(size_t) > 4) {\n    std::string s(kSize, 'x');\n    s.back() = '-';\n    std::vector<absl::string_view> v = absl::StrSplit(s, '-');\n    EXPECT_EQ(2, v.size());\n    // The first element will contain 2G of 'x's.\n    // testing::StartsWith is too slow with a 2G string.\n    EXPECT_EQ('x', v[0][0]);\n    EXPECT_EQ('x', v[0][1]);\n    EXPECT_EQ('x', v[0][3]);\n    EXPECT_EQ(\"\", v[1]);\n  }\n}\n\nTEST(SplitInternalTest, TypeTraits) {\n  EXPECT_FALSE(absl::strings_internal::HasMappedType<int>::value);\n  EXPECT_TRUE(\n      (absl::strings_internal::HasMappedType<std::map<int, int>>::value));\n  EXPECT_FALSE(absl::strings_internal::HasValueType<int>::value);\n  EXPECT_TRUE(\n      (absl::strings_internal::HasValueType<std::map<int, int>>::value));\n  EXPECT_FALSE(absl::strings_internal::HasConstIterator<int>::value);\n  EXPECT_TRUE(\n      (absl::strings_internal::HasConstIterator<std::map<int, int>>::value));\n  EXPECT_FALSE(absl::strings_internal::IsInitializerList<int>::value);\n  EXPECT_TRUE((absl::strings_internal::IsInitializerList<\n               std::initializer_list<int>>::value));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/string_view.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: string_view.h\n// -----------------------------------------------------------------------------\n//\n// Historical note: Abseil once provided an implementation of\n// `absl::string_view` as a polyfill for `std::string_view` prior to C++17. Now\n// that C++17 is required, `absl::string_view` is an alias for\n// `std::string_view`\n\n#ifndef ABSL_STRINGS_STRING_VIEW_H_\n#define ABSL_STRINGS_STRING_VIEW_H_\n\n#include <string_view>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nusing std::string_view;\n\n// ClippedSubstr()\n//\n// Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`.\n// Provided because std::string_view::substr throws if `pos > size()`\ninline string_view ClippedSubstr(string_view s ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                                 size_t pos, size_t n = string_view::npos) {\n  pos = (std::min)(pos, static_cast<size_t>(s.size()));\n  return s.substr(pos, n);\n}\n\n// NullSafeStringView()\n//\n// Creates an `absl::string_view` from a pointer `p` even if it's null-valued.\n// This function should be used where an `absl::string_view` can be created from\n// a possibly-null pointer.\nconstexpr string_view NullSafeStringView(const char* absl_nullable p) {\n  return p ? string_view(p) : string_view();\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STRING_VIEW_H_\n"
  },
  {
    "path": "absl/strings/string_view_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/string_view.h\"\n\n#include <array>\n#include <cstddef>\n#include <cstdlib>\n#include <cstring>\n#include <iomanip>\n#include <ios>\n#include <iterator>\n#include <limits>\n#include <map>\n#include <memory>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace {\n\nTEST(StringViewTest, TruncSubstr) {\n  const absl::string_view hi(\"hi\");\n  EXPECT_EQ(\"\", absl::ClippedSubstr(hi, 0, 0));\n  EXPECT_EQ(\"h\", absl::ClippedSubstr(hi, 0, 1));\n  EXPECT_EQ(\"hi\", absl::ClippedSubstr(hi, 0));\n  EXPECT_EQ(\"i\", absl::ClippedSubstr(hi, 1));\n  EXPECT_EQ(\"\", absl::ClippedSubstr(hi, 2));\n  EXPECT_EQ(\"\", absl::ClippedSubstr(hi, 3));  // truncation\n  EXPECT_EQ(\"\", absl::ClippedSubstr(hi, 3, 2));  // truncation\n}\n\nTEST(StringViewTest, NullSafeStringView) {\n  {\n    absl::string_view s = absl::NullSafeStringView(nullptr);\n    EXPECT_EQ(nullptr, s.data());\n    EXPECT_EQ(0u, s.size());\n    EXPECT_EQ(absl::string_view(), s);\n  }\n  {\n    static const char kHi[] = \"hi\";\n    absl::string_view s = absl::NullSafeStringView(kHi);\n    EXPECT_EQ(kHi, s.data());\n    EXPECT_EQ(strlen(kHi), s.size());\n    EXPECT_EQ(absl::string_view(\"hi\"), s);\n  }\n}\n\nTEST(StringViewTest, ConstexprNullSafeStringView) {\n  {\n    constexpr absl::string_view s = absl::NullSafeStringView(nullptr);\n    EXPECT_EQ(nullptr, s.data());\n    EXPECT_EQ(0u, s.size());\n    EXPECT_EQ(absl::string_view(), s);\n  }\n  {\n    static constexpr char kHi[] = \"hi\";\n    absl::string_view s = absl::NullSafeStringView(kHi);\n    EXPECT_EQ(kHi, s.data());\n    EXPECT_EQ(strlen(kHi), s.size());\n    EXPECT_EQ(absl::string_view(\"hi\"), s);\n  }\n  {\n    constexpr absl::string_view s = absl::NullSafeStringView(\"hello\");\n    EXPECT_EQ(s.size(), 5u);\n    EXPECT_EQ(\"hello\", s);\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/strip.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: strip.h\n// -----------------------------------------------------------------------------\n//\n// This file contains various functions for stripping substrings from a string.\n#ifndef ABSL_STRINGS_STRIP_H_\n#define ABSL_STRINGS_STRIP_H_\n\n#include <cstddef>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// ConsumePrefix()\n//\n// Strips the `expected` prefix, if found, from the start of `str`.\n// If the operation succeeded, `true` is returned.  If not, `false`\n// is returned and `str` is not modified.\n//\n// Example:\n//\n//   absl::string_view input(\"abc\");\n//   EXPECT_TRUE(absl::ConsumePrefix(&input, \"a\"));\n//   EXPECT_EQ(input, \"bc\");\ninline constexpr bool ConsumePrefix(absl::string_view* absl_nonnull str,\n                                    absl::string_view expected) {\n  if (!absl::StartsWith(*str, expected)) return false;\n  str->remove_prefix(expected.size());\n  return true;\n}\n// ConsumeSuffix()\n//\n// Strips the `expected` suffix, if found, from the end of `str`.\n// If the operation succeeded, `true` is returned.  If not, `false`\n// is returned and `str` is not modified.\n//\n// Example:\n//\n//   absl::string_view input(\"abcdef\");\n//   EXPECT_TRUE(absl::ConsumeSuffix(&input, \"def\"));\n//   EXPECT_EQ(input, \"abc\");\ninline constexpr bool ConsumeSuffix(absl::string_view* absl_nonnull str,\n                                    absl::string_view expected) {\n  if (!absl::EndsWith(*str, expected)) return false;\n  str->remove_suffix(expected.size());\n  return true;\n}\n\n// StripPrefix()\n//\n// Returns a view into the input string `str` with the given `prefix` removed,\n// but leaving the original string intact. If the prefix does not match at the\n// start of the string, returns the original string instead.\n[[nodiscard]] inline constexpr absl::string_view StripPrefix(\n    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,\n    absl::string_view prefix) {\n  if (absl::StartsWith(str, prefix)) str.remove_prefix(prefix.size());\n  return str;\n}\n\n// StripSuffix()\n//\n// Returns a view into the input string `str` with the given `suffix` removed,\n// but leaving the original string intact. If the suffix does not match at the\n// end of the string, returns the original string instead.\n[[nodiscard]] inline constexpr absl::string_view StripSuffix(\n    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,\n    absl::string_view suffix) {\n  if (absl::EndsWith(str, suffix)) str.remove_suffix(suffix.size());\n  return str;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_STRIP_H_\n"
  },
  {
    "path": "absl/strings/strip_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file contains functions that remove a defined part from the string,\n// i.e., strip the string.\n\n#include \"absl/strings/strip.h\"\n\n#include <cassert>\n#include <cstdio>\n#include <cstring>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nTEST(Strip, ConsumePrefixOneChar) {\n  absl::string_view input(\"abc\");\n  EXPECT_TRUE(absl::ConsumePrefix(&input, \"a\"));\n  EXPECT_EQ(input, \"bc\");\n\n  EXPECT_FALSE(absl::ConsumePrefix(&input, \"x\"));\n  EXPECT_EQ(input, \"bc\");\n\n  EXPECT_TRUE(absl::ConsumePrefix(&input, \"b\"));\n  EXPECT_EQ(input, \"c\");\n\n  EXPECT_TRUE(absl::ConsumePrefix(&input, \"c\"));\n  EXPECT_EQ(input, \"\");\n\n  EXPECT_FALSE(absl::ConsumePrefix(&input, \"a\"));\n  EXPECT_EQ(input, \"\");\n}\n\nTEST(Strip, ConsumePrefix) {\n  absl::string_view input(\"abcdef\");\n  EXPECT_FALSE(absl::ConsumePrefix(&input, \"abcdefg\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_FALSE(absl::ConsumePrefix(&input, \"abce\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_TRUE(absl::ConsumePrefix(&input, \"\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_FALSE(absl::ConsumePrefix(&input, \"abcdeg\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_TRUE(absl::ConsumePrefix(&input, \"abcdef\"));\n  EXPECT_EQ(input, \"\");\n\n  input = \"abcdef\";\n  EXPECT_TRUE(absl::ConsumePrefix(&input, \"abcde\"));\n  EXPECT_EQ(input, \"f\");\n}\n\nTEST(Strip, ConsumeSuffix) {\n  absl::string_view input(\"abcdef\");\n  EXPECT_FALSE(absl::ConsumeSuffix(&input, \"abcdefg\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_TRUE(absl::ConsumeSuffix(&input, \"\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_TRUE(absl::ConsumeSuffix(&input, \"def\"));\n  EXPECT_EQ(input, \"abc\");\n\n  input = \"abcdef\";\n  EXPECT_FALSE(absl::ConsumeSuffix(&input, \"abcdeg\"));\n  EXPECT_EQ(input, \"abcdef\");\n\n  EXPECT_TRUE(absl::ConsumeSuffix(&input, \"f\"));\n  EXPECT_EQ(input, \"abcde\");\n\n  EXPECT_TRUE(absl::ConsumeSuffix(&input, \"abcde\"));\n  EXPECT_EQ(input, \"\");\n}\n\nTEST(Strip, StripPrefix) {\n  const absl::string_view null_str;\n\n  EXPECT_EQ(absl::StripPrefix(\"foobar\", \"foo\"), \"bar\");\n  EXPECT_EQ(absl::StripPrefix(\"foobar\", \"\"), \"foobar\");\n  EXPECT_EQ(absl::StripPrefix(\"foobar\", null_str), \"foobar\");\n  EXPECT_EQ(absl::StripPrefix(\"foobar\", \"foobar\"), \"\");\n  EXPECT_EQ(absl::StripPrefix(\"foobar\", \"bar\"), \"foobar\");\n  EXPECT_EQ(absl::StripPrefix(\"foobar\", \"foobarr\"), \"foobar\");\n  EXPECT_EQ(absl::StripPrefix(\"\", \"\"), \"\");\n}\n\nTEST(Strip, StripSuffix) {\n  const absl::string_view null_str;\n\n  EXPECT_EQ(absl::StripSuffix(\"foobar\", \"bar\"), \"foo\");\n  EXPECT_EQ(absl::StripSuffix(\"foobar\", \"\"), \"foobar\");\n  EXPECT_EQ(absl::StripSuffix(\"foobar\", null_str), \"foobar\");\n  EXPECT_EQ(absl::StripSuffix(\"foobar\", \"foobar\"), \"\");\n  EXPECT_EQ(absl::StripSuffix(\"foobar\", \"foo\"), \"foobar\");\n  EXPECT_EQ(absl::StripSuffix(\"foobar\", \"ffoobar\"), \"foobar\");\n  EXPECT_EQ(absl::StripSuffix(\"\", \"\"), \"\");\n}\n\nTEST(Strip, RemoveExtraAsciiWhitespace) {\n  const char* inputs[] = {\n      \"No extra space\",\n      \"  Leading whitespace\",\n      \"Trailing whitespace  \",\n      \"  Leading and trailing  \",\n      \" Whitespace \\t  in\\v   middle  \",\n      \"'Eeeeep!  \\n Newlines!\\n\",\n      \"nospaces\",\n  };\n  const char* outputs[] = {\n      \"No extra space\",\n      \"Leading whitespace\",\n      \"Trailing whitespace\",\n      \"Leading and trailing\",\n      \"Whitespace in middle\",\n      \"'Eeeeep! Newlines!\",\n      \"nospaces\",\n  };\n  int NUM_TESTS = 7;\n\n  for (int i = 0; i < NUM_TESTS; i++) {\n    std::string s(inputs[i]);\n    absl::RemoveExtraAsciiWhitespace(&s);\n    EXPECT_STREQ(outputs[i], s.c_str());\n  }\n\n  // Test that absl::RemoveExtraAsciiWhitespace returns immediately for empty\n  // strings (It was adding the \\0 character to the C++ std::string, which broke\n  // tests involving empty())\n  std::string zero_string = \"\";\n  assert(zero_string.empty());\n  absl::RemoveExtraAsciiWhitespace(&zero_string);\n  EXPECT_EQ(zero_string.size(), 0);\n  EXPECT_TRUE(zero_string.empty());\n}\n\nTEST(Strip, StripTrailingAsciiWhitespace) {\n  std::string test = \"foo  \";\n  absl::StripTrailingAsciiWhitespace(&test);\n  EXPECT_EQ(test, \"foo\");\n\n  test = \"   \";\n  absl::StripTrailingAsciiWhitespace(&test);\n  EXPECT_EQ(test, \"\");\n\n  test = \"\";\n  absl::StripTrailingAsciiWhitespace(&test);\n  EXPECT_EQ(test, \"\");\n\n  test = \" abc\\t\";\n  absl::StripTrailingAsciiWhitespace(&test);\n  EXPECT_EQ(test, \" abc\");\n}\n\nTEST(String, StripLeadingAsciiWhitespace) {\n  absl::string_view orig = \"\\t  \\n\\f\\r\\n\\vfoo\";\n  EXPECT_EQ(\"foo\", absl::StripLeadingAsciiWhitespace(orig));\n  orig = \"\\t  \\n\\f\\r\\v\\n\\t  \\n\\f\\r\\v\\n\";\n  EXPECT_EQ(absl::string_view(), absl::StripLeadingAsciiWhitespace(orig));\n}\n\nTEST(Strip, StripAsciiWhitespace) {\n  std::string test2 = \"\\t  \\f\\r\\n\\vfoo \\t\\f\\r\\v\\n\";\n  absl::StripAsciiWhitespace(&test2);\n  EXPECT_EQ(test2, \"foo\");\n  std::string test3 = \"bar\";\n  absl::StripAsciiWhitespace(&test3);\n  EXPECT_EQ(test3, \"bar\");\n  std::string test4 = \"\\t  \\f\\r\\n\\vfoo\";\n  absl::StripAsciiWhitespace(&test4);\n  EXPECT_EQ(test4, \"foo\");\n  std::string test5 = \"foo \\t\\f\\r\\v\\n\";\n  absl::StripAsciiWhitespace(&test5);\n  EXPECT_EQ(test5, \"foo\");\n  absl::string_view test6(\"\\t  \\f\\r\\n\\vfoo \\t\\f\\r\\v\\n\");\n  test6 = absl::StripAsciiWhitespace(test6);\n  EXPECT_EQ(test6, \"foo\");\n  test6 = absl::StripAsciiWhitespace(test6);\n  EXPECT_EQ(test6, \"foo\");  // already stripped\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/substitute.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/substitute.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/internal/append_and_overwrite.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace substitute_internal {\n\nvoid SubstituteAndAppendArray(std::string* absl_nonnull output,\n                              absl::string_view format,\n                              const absl::string_view* absl_nullable args_array,\n                              size_t num_args) {\n  // Determine total size needed.\n  size_t size = 0;\n  for (size_t i = 0; i < format.size(); i++) {\n    if (format[i] == '$') {\n      if (i + 1 >= format.size()) {\n#ifndef NDEBUG\n        ABSL_RAW_LOG(FATAL,\n                     \"Invalid absl::Substitute() format string: \\\"%s\\\".\",\n                     absl::CEscape(format).c_str());\n#endif\n        return;\n      } else if (absl::ascii_isdigit(\n                     static_cast<unsigned char>(format[i + 1]))) {\n        int index = format[i + 1] - '0';\n        if (static_cast<size_t>(index) >= num_args) {\n#ifndef NDEBUG\n          ABSL_RAW_LOG(\n              FATAL,\n              \"Invalid absl::Substitute() format string: asked for \\\"$\"\n              \"%d\\\", but only %d args were given.  Full format string was: \"\n              \"\\\"%s\\\".\",\n              index, static_cast<int>(num_args), absl::CEscape(format).c_str());\n#endif\n          return;\n        }\n        size += args_array[index].size();\n        ++i;  // Skip next char.\n      } else if (format[i + 1] == '$') {\n        ++size;\n        ++i;  // Skip next char.\n      } else {\n#ifndef NDEBUG\n        ABSL_RAW_LOG(FATAL,\n                     \"Invalid absl::Substitute() format string: \\\"%s\\\".\",\n                     absl::CEscape(format).c_str());\n#endif\n        return;\n      }\n    } else {\n      ++size;\n    }\n  }\n\n  if (size == 0) return;\n\n  // Build the string.\n  ABSL_INTERNAL_CHECK(size <= output->max_size() - output->size(),\n                      \"Exceeds std::string::max_size()\");\n  strings_internal::StringAppendAndOverwrite(\n      *output, size, [format, args_array](char* const buf, size_t buf_size) {\n        char* target = buf;\n        for (size_t i = 0; i < format.size(); i++) {\n          if (format[i] == '$') {\n            if (absl::ascii_isdigit(\n                    static_cast<unsigned char>(format[i + 1]))) {\n              const absl::string_view src = args_array[format[i + 1] - '0'];\n              target = std::copy(src.begin(), src.end(), target);\n              ++i;  // Skip next char.\n            } else if (format[i + 1] == '$') {\n              *target++ = '$';\n              ++i;  // Skip next char.\n            }\n          } else {\n            *target++ = format[i];\n          }\n        }\n        assert(target == buf + buf_size);\n        return buf_size;\n      });\n}\n\nArg::Arg(const void* absl_nullable value) {\n  static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,\n                \"fix sizeof(scratch_)\");\n  if (value == nullptr) {\n    piece_ = \"NULL\";\n  } else {\n    char* ptr = scratch_ + sizeof(scratch_);\n    uintptr_t num = reinterpret_cast<uintptr_t>(value);\n    do {\n      *--ptr = absl::numbers_internal::kHexChar[num & 0xf];\n      num >>= 4;\n    } while (num != 0);\n    *--ptr = 'x';\n    *--ptr = '0';\n    piece_ = absl::string_view(\n        ptr, static_cast<size_t>(scratch_ + sizeof(scratch_) - ptr));\n  }\n}\n\n// TODO(jorg): Don't duplicate so much code between here and str_cat.cc\nArg::Arg(Hex hex) {\n  char* const end = &scratch_[numbers_internal::kFastToBufferSize];\n  char* writer = end;\n  uint64_t value = hex.value;\n  do {\n    *--writer = absl::numbers_internal::kHexChar[value & 0xF];\n    value >>= 4;\n  } while (value != 0);\n\n  char* beg;\n  if (end - writer < hex.width) {\n    beg = end - hex.width;\n    std::fill_n(beg, writer - beg, hex.fill);\n  } else {\n    beg = writer;\n  }\n\n  piece_ = absl::string_view(beg, static_cast<size_t>(end - beg));\n}\n\n// TODO(jorg): Don't duplicate so much code between here and str_cat.cc\nArg::Arg(Dec dec) {\n  assert(dec.width <= numbers_internal::kFastToBufferSize);\n  char* const end = &scratch_[numbers_internal::kFastToBufferSize];\n  char* const minfill = end - dec.width;\n  char* writer = end;\n  uint64_t value = dec.value;\n  bool neg = dec.neg;\n  while (value > 9) {\n    *--writer = '0' + (value % 10);\n    value /= 10;\n  }\n  *--writer = '0' + static_cast<char>(value);\n  if (neg) *--writer = '-';\n\n  ptrdiff_t fillers = writer - minfill;\n  if (fillers > 0) {\n    // Tricky: if the fill character is ' ', then it's <fill><+/-><digits>\n    // But...: if the fill character is '0', then it's <+/-><fill><digits>\n    bool add_sign_again = false;\n    if (neg && dec.fill == '0') {  // If filling with '0',\n      ++writer;                    // ignore the sign we just added\n      add_sign_again = true;       // and re-add the sign later.\n    }\n    writer -= fillers;\n    std::fill_n(writer, fillers, dec.fill);\n    if (add_sign_again) *--writer = '-';\n  }\n\n  piece_ = absl::string_view(writer, static_cast<size_t>(end - writer));\n}\n\n}  // namespace substitute_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/strings/substitute.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: substitute.h\n// -----------------------------------------------------------------------------\n//\n// This package contains functions for efficiently performing string\n// substitutions using a format string with positional notation:\n// `Substitute()` and `SubstituteAndAppend()`.\n//\n// Unlike printf-style format specifiers, `Substitute()` functions do not need\n// to specify the type of the substitution arguments. Supported arguments\n// following the format string, such as strings, string_views, ints,\n// floats, and bools, are automatically converted to strings during the\n// substitution process. (See below for a full list of supported types.)\n//\n// `Substitute()` does not allow you to specify *how* to format a value, beyond\n// the default conversion to string. For example, you cannot format an integer\n// in hex.\n//\n// The format string uses positional identifiers indicated by a dollar sign ($)\n// and single digit positional ids to indicate which substitution arguments to\n// use at that location within the format string.\n//\n// A '$$' sequence in the format string causes a literal '$' character to be\n// output.\n//\n// Example 1:\n//   std::string s = Substitute(\"$1 purchased $0 $2 for $$10. Thanks $1!\",\n//                              5, \"Bob\", \"Apples\");\n//   EXPECT_EQ(\"Bob purchased 5 Apples for $10. Thanks Bob!\", s);\n//\n// Example 2:\n//   std::string s = \"Hi. \";\n//   SubstituteAndAppend(&s, \"My name is $0 and I am $1 years old.\", \"Bob\", 5);\n//   EXPECT_EQ(\"Hi. My name is Bob and I am 5 years old.\", s);\n//\n// Supported types:\n//   * absl::string_view, std::string, const char* (null is equivalent to \"\")\n//   * int32_t, int64_t, uint32_t, uint64_t\n//   * float, double\n//   * bool (Printed as \"true\" or \"false\")\n//   * pointer types other than char* (Printed as \"0x<lower case hex string>\",\n//     except that null is printed as \"NULL\")\n//   * user-defined types via the `AbslStringify()` customization point. See the\n//     documentation for `absl::StrCat` for an explanation on how to use this.\n//\n// If an invalid format string is provided, Substitute returns an empty string\n// and SubstituteAndAppend does not change the provided output string.\n// A format string is invalid if it:\n//   * ends in an unescaped $ character,\n//     e.g. \"Hello $\", or\n//   * calls for a position argument which is not provided,\n//     e.g. Substitute(\"Hello $2\", \"world\"), or\n//   * specifies a non-digit, non-$ character after an unescaped $ character,\n//     e.g. \"Hello $f\".\n// In debug mode, i.e. #ifndef NDEBUG, such errors terminate the program.\n\n#ifndef ABSL_STRINGS_SUBSTITUTE_H_\n#define ABSL_STRINGS_SUBSTITUTE_H_\n\n#include <cstring>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/port.h\"\n#include \"absl/strings/ascii.h\"\n#include \"absl/strings/escaping.h\"\n#include \"absl/strings/internal/stringify_sink.h\"\n#include \"absl/strings/numbers.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/str_split.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace substitute_internal {\n\n// Arg\n//\n// This class provides an argument type for `absl::Substitute()` and\n// `absl::SubstituteAndAppend()`. `Arg` handles implicit conversion of various\n// types to a string. (`Arg` is very similar to the `AlphaNum` class in\n// `StrCat()`.)\n//\n// This class has implicit constructors.\nclass Arg {\n public:\n  // Overloads for string-y things\n  //\n  // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.\n  Arg(const char* absl_nullable value)  // NOLINT(google-explicit-constructor)\n      : piece_(absl::NullSafeStringView(value)) {}\n  template <typename Allocator>\n  Arg(  // NOLINT\n      const std::basic_string<char, std::char_traits<char>, Allocator>&\n          value) noexcept\n      : piece_(value) {}\n  Arg(absl::string_view value)  // NOLINT(google-explicit-constructor)\n      : piece_(value) {}\n\n  // Overloads for primitives\n  //\n  // No overloads are available for signed and unsigned char because if people\n  // are explicitly declaring their chars as signed or unsigned then they are\n  // probably using them as 8-bit integers and would probably prefer an integer\n  // representation. However, we can't really know, so we make the caller decide\n  // what to do.\n  Arg(char value)  // NOLINT(google-explicit-constructor)\n      : piece_(scratch_, 1) {\n    scratch_[0] = value;\n  }\n  Arg(short value)  // NOLINT(*)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(unsigned short value)  // NOLINT(*)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(int value)  // NOLINT(google-explicit-constructor)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(unsigned int value)  // NOLINT(google-explicit-constructor)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(long value)  // NOLINT(*)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(unsigned long value)  // NOLINT(*)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(long long value)  // NOLINT(*)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(unsigned long long value)  // NOLINT(*)\n      : piece_(scratch_,\n               static_cast<size_t>(\n                   numbers_internal::FastIntToBuffer(value, scratch_) -\n                   scratch_)) {}\n  Arg(float value)  // NOLINT(google-explicit-constructor)\n      : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {\n  }\n  Arg(double value)  // NOLINT(google-explicit-constructor)\n      : piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {\n  }\n  Arg(bool value)  // NOLINT(google-explicit-constructor)\n      : piece_(value ? \"true\" : \"false\") {}\n\n  template <typename T, typename = typename std::enable_if<\n                            HasAbslStringify<T>::value>::type>\n  Arg(  // NOLINT(google-explicit-constructor)\n      const T& v, strings_internal::StringifySink&& sink = {})\n      : piece_(strings_internal::ExtractStringification(sink, v)) {}\n\n  Arg(Hex hex);  // NOLINT(google-explicit-constructor)\n  Arg(Dec dec);  // NOLINT(google-explicit-constructor)\n\n  // vector<bool>::reference and const_reference require special help to convert\n  // to `Arg` because it requires two user defined conversions.\n  template <\n      typename T,\n      std::enable_if_t<\n          std::is_class<T>::value &&\n              (std::is_same<T, std::vector<bool>::reference>::value ||\n               std::is_same<T, std::vector<bool>::const_reference>::value),\n          bool> = true>\n  Arg(T value)  // NOLINT(google-explicit-constructor)\n      : Arg(static_cast<bool>(value)) {}\n\n  // `void*` values, with the exception of `char*`, are printed as\n  // \"0x<hex value>\". However, in the case of `nullptr`, \"NULL\" is printed.\n  Arg(  // NOLINT(google-explicit-constructor)\n      const void* absl_nullable value);\n\n  // Normal enums are already handled by the integer formatters.\n  // This overload matches only scoped enums.\n  template <typename T,\n            typename = typename std::enable_if<\n                std::is_enum<T>{} && !std::is_convertible<T, int>{} &&\n                !HasAbslStringify<T>::value>::type>\n  Arg(T value)  // NOLINT(google-explicit-constructor)\n      : Arg(static_cast<typename std::underlying_type<T>::type>(value)) {}\n\n  Arg(const Arg&) = delete;\n  Arg& operator=(const Arg&) = delete;\n\n  absl::string_view piece() const { return piece_; }\n\n private:\n  absl::string_view piece_;\n  char scratch_[numbers_internal::kFastToBufferSize];\n};\n\n// Internal helper function. Don't call this from outside this implementation.\n// This interface may change without notice.\nvoid SubstituteAndAppendArray(std::string* absl_nonnull output,\n                              absl::string_view format,\n                              const absl::string_view* absl_nullable args_array,\n                              size_t num_args);\n\n#if defined(ABSL_BAD_CALL_IF)\nconstexpr int CalculateOneBit(const char* absl_nonnull format) {\n  // Returns:\n  // * 2^N for '$N' when N is in [0-9]\n  // * 0 for correct '$' escaping: '$$'.\n  // * -1 otherwise.\n  return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)\n                                          : (1 << (*format - '0'));\n}\n\nconstexpr const char* absl_nonnull SkipNumber(const char* absl_nonnull format) {\n  return !*format ? format : (format + 1);\n}\n\nconstexpr int PlaceholderBitmask(const char* absl_nonnull format) {\n  return !*format\n             ? 0\n             : *format != '$' ? PlaceholderBitmask(format + 1)\n                              : (CalculateOneBit(format + 1) |\n                                 PlaceholderBitmask(SkipNumber(format + 1)));\n}\n#endif  // ABSL_BAD_CALL_IF\n\n}  // namespace substitute_internal\n\n//\n// PUBLIC API\n//\n\n// SubstituteAndAppend()\n//\n// Substitutes variables into a given format string and appends to a given\n// output string. See file comments above for usage.\n//\n// The declarations of `SubstituteAndAppend()` below consist of overloads\n// for passing 0 to 10 arguments, respectively.\n//\n// NOTE: A zero-argument `SubstituteAndAppend()` may be used within variadic\n// templates to allow a variable number of arguments.\n//\n// Example:\n//  template <typename... Args>\n//  void VarMsg(std::string* boilerplate, absl::string_view format,\n//      const Args&... args) {\n//    absl::SubstituteAndAppend(boilerplate, format, args...);\n//  }\n//\ninline void SubstituteAndAppend(std::string* absl_nonnull output,\n                                absl::string_view format) {\n  substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);\n}\n\ninline void SubstituteAndAppend(std::string* absl_nonnull output,\n                                absl::string_view format,\n                                const substitute_internal::Arg& a0) {\n  const absl::string_view args[] = {a0.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(std::string* absl_nonnull output,\n                                absl::string_view format,\n                                const substitute_internal::Arg& a0,\n                                const substitute_internal::Arg& a1) {\n  const absl::string_view args[] = {a0.piece(), a1.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(std::string* absl_nonnull output,\n                                absl::string_view format,\n                                const substitute_internal::Arg& a0,\n                                const substitute_internal::Arg& a1,\n                                const substitute_internal::Arg& a2) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(std::string* absl_nonnull output,\n                                absl::string_view format,\n                                const substitute_internal::Arg& a0,\n                                const substitute_internal::Arg& a1,\n                                const substitute_internal::Arg& a2,\n                                const substitute_internal::Arg& a3) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),\n                                    a3.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(std::string* absl_nonnull output,\n                                absl::string_view format,\n                                const substitute_internal::Arg& a0,\n                                const substitute_internal::Arg& a1,\n                                const substitute_internal::Arg& a2,\n                                const substitute_internal::Arg& a3,\n                                const substitute_internal::Arg& a4) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),\n                                    a3.piece(), a4.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(\n    std::string* absl_nonnull output, absl::string_view format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),\n                                    a3.piece(), a4.piece(), a5.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(\n    std::string* absl_nonnull output, absl::string_view format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),\n                                    a3.piece(), a4.piece(), a5.piece(),\n                                    a6.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(\n    std::string* absl_nonnull output, absl::string_view format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),\n                                    a3.piece(), a4.piece(), a5.piece(),\n                                    a6.piece(), a7.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(\n    std::string* absl_nonnull output, absl::string_view format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,\n    const substitute_internal::Arg& a8) {\n  const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),\n                                    a3.piece(), a4.piece(), a5.piece(),\n                                    a6.piece(), a7.piece(), a8.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\ninline void SubstituteAndAppend(\n    std::string* absl_nonnull output, absl::string_view format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,\n    const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) {\n  const absl::string_view args[] = {\n      a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(),\n      a5.piece(), a6.piece(), a7.piece(), a8.piece(), a9.piece()};\n  substitute_internal::SubstituteAndAppendArray(output, format, args,\n                                                ABSL_ARRAYSIZE(args));\n}\n\n#if defined(ABSL_BAD_CALL_IF)\n// This body of functions catches cases where the number of placeholders\n// doesn't match the number of data arguments.\nvoid SubstituteAndAppend(std::string* absl_nonnull output,\n                         const char* absl_nonnull format)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 0,\n        \"There were no substitution arguments \"\n        \"but this format string either has a $[0-9] in it or contains \"\n        \"an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(std::string* absl_nonnull output,\n                         const char* absl_nonnull format,\n                         const substitute_internal::Arg& a0)\n    ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,\n                     \"There was 1 substitution argument given, but \"\n                     \"this format string is missing its $0, contains \"\n                     \"one of $1-$9, or contains an unescaped $ character (use \"\n                     \"$$ instead)\");\n\nvoid SubstituteAndAppend(std::string* absl_nonnull output,\n                         const char* absl_nonnull format,\n                         const substitute_internal::Arg& a0,\n                         const substitute_internal::Arg& a1)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 3,\n        \"There were 2 substitution arguments given, but this format string is \"\n        \"missing its $0/$1, contains one of $2-$9, or contains an \"\n        \"unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(std::string* absl_nonnull output,\n                         const char* absl_nonnull format,\n                         const substitute_internal::Arg& a0,\n                         const substitute_internal::Arg& a1,\n                         const substitute_internal::Arg& a2)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 7,\n        \"There were 3 substitution arguments given, but \"\n        \"this format string is missing its $0/$1/$2, contains one of \"\n        \"$3-$9, or contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(std::string* absl_nonnull output,\n                         const char* absl_nonnull format,\n                         const substitute_internal::Arg& a0,\n                         const substitute_internal::Arg& a1,\n                         const substitute_internal::Arg& a2,\n                         const substitute_internal::Arg& a3)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 15,\n        \"There were 4 substitution arguments given, but \"\n        \"this format string is missing its $0-$3, contains one of \"\n        \"$4-$9, or contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(std::string* absl_nonnull output,\n                         const char* absl_nonnull format,\n                         const substitute_internal::Arg& a0,\n                         const substitute_internal::Arg& a1,\n                         const substitute_internal::Arg& a2,\n                         const substitute_internal::Arg& a3,\n                         const substitute_internal::Arg& a4)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 31,\n        \"There were 5 substitution arguments given, but \"\n        \"this format string is missing its $0-$4, contains one of \"\n        \"$5-$9, or contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(\n    std::string* absl_nonnull output, const char* absl_nonnull format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 63,\n        \"There were 6 substitution arguments given, but \"\n        \"this format string is missing its $0-$5, contains one of \"\n        \"$6-$9, or contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(\n    std::string* absl_nonnull output, const char* absl_nonnull format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 127,\n        \"There were 7 substitution arguments given, but \"\n        \"this format string is missing its $0-$6, contains one of \"\n        \"$7-$9, or contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(\n    std::string* absl_nonnull output, const char* absl_nonnull format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6, const substitute_internal::Arg& a7)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 255,\n        \"There were 8 substitution arguments given, but \"\n        \"this format string is missing its $0-$7, contains one of \"\n        \"$8-$9, or contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(\n    std::string* absl_nonnull output, const char* absl_nonnull format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,\n    const substitute_internal::Arg& a8)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 511,\n        \"There were 9 substitution arguments given, but \"\n        \"this format string is missing its $0-$8, contains a $9, or \"\n        \"contains an unescaped $ character (use $$ instead)\");\n\nvoid SubstituteAndAppend(\n    std::string* absl_nonnull output, const char* absl_nonnull format,\n    const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,\n    const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,\n    const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,\n    const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,\n    const substitute_internal::Arg& a8, const substitute_internal::Arg& a9)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 1023,\n        \"There were 10 substitution arguments given, but this \"\n        \"format string either doesn't contain all of $0 through $9 or \"\n        \"contains an unescaped $ character (use $$ instead)\");\n#endif  // ABSL_BAD_CALL_IF\n\n// Substitute()\n//\n// Substitutes variables into a given format string. See file comments above\n// for usage.\n//\n// The declarations of `Substitute()` below consist of overloads for passing 0\n// to 10 arguments, respectively.\n//\n// NOTE: A zero-argument `Substitute()` may be used within variadic templates to\n// allow a variable number of arguments.\n//\n// Example:\n//  template <typename... Args>\n//  void VarMsg(absl::string_view format, const Args&... args) {\n//    std::string s = absl::Substitute(format, args...);\n\n[[nodiscard]] inline std::string Substitute(absl::string_view format) {\n  std::string result;\n  SubstituteAndAppend(&result, format);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,\n    const substitute_internal::Arg& a7) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,\n    const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8);\n  return result;\n}\n\n[[nodiscard]] inline std::string Substitute(\n    absl::string_view format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,\n    const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,\n    const substitute_internal::Arg& a9) {\n  std::string result;\n  SubstituteAndAppend(&result, format, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);\n  return result;\n}\n\n#if defined(ABSL_BAD_CALL_IF)\n// This body of functions catches cases where the number of placeholders\n// doesn't match the number of data arguments.\nstd::string Substitute(const char* absl_nonnull format)\n    ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,\n                     \"There were no substitution arguments \"\n                     \"but this format string either has a $[0-9] in it or \"\n                     \"contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(const char* absl_nonnull format,\n                       const substitute_internal::Arg& a0)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 1,\n        \"There was 1 substitution argument given, but \"\n        \"this format string is missing its $0, contains one of $1-$9, \"\n        \"or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(const char* absl_nonnull format,\n                       const substitute_internal::Arg& a0,\n                       const substitute_internal::Arg& a1)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 3,\n        \"There were 2 substitution arguments given, but \"\n        \"this format string is missing its $0/$1, contains one of \"\n        \"$2-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(const char* absl_nonnull format,\n                       const substitute_internal::Arg& a0,\n                       const substitute_internal::Arg& a1,\n                       const substitute_internal::Arg& a2)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 7,\n        \"There were 3 substitution arguments given, but \"\n        \"this format string is missing its $0/$1/$2, contains one of \"\n        \"$3-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(const char* absl_nonnull format,\n                       const substitute_internal::Arg& a0,\n                       const substitute_internal::Arg& a1,\n                       const substitute_internal::Arg& a2,\n                       const substitute_internal::Arg& a3)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 15,\n        \"There were 4 substitution arguments given, but \"\n        \"this format string is missing its $0-$3, contains one of \"\n        \"$4-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(const char* absl_nonnull format,\n                       const substitute_internal::Arg& a0,\n                       const substitute_internal::Arg& a1,\n                       const substitute_internal::Arg& a2,\n                       const substitute_internal::Arg& a3,\n                       const substitute_internal::Arg& a4)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 31,\n        \"There were 5 substitution arguments given, but \"\n        \"this format string is missing its $0-$4, contains one of \"\n        \"$5-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(const char* absl_nonnull format,\n                       const substitute_internal::Arg& a0,\n                       const substitute_internal::Arg& a1,\n                       const substitute_internal::Arg& a2,\n                       const substitute_internal::Arg& a3,\n                       const substitute_internal::Arg& a4,\n                       const substitute_internal::Arg& a5)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 63,\n        \"There were 6 substitution arguments given, but \"\n        \"this format string is missing its $0-$5, contains one of \"\n        \"$6-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(\n    const char* absl_nonnull format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 127,\n        \"There were 7 substitution arguments given, but \"\n        \"this format string is missing its $0-$6, contains one of \"\n        \"$7-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(\n    const char* absl_nonnull format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,\n    const substitute_internal::Arg& a7)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 255,\n        \"There were 8 substitution arguments given, but \"\n        \"this format string is missing its $0-$7, contains one of \"\n        \"$8-$9, or contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(\n    const char* absl_nonnull format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,\n    const substitute_internal::Arg& a7, const substitute_internal::Arg& a8)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 511,\n        \"There were 9 substitution arguments given, but \"\n        \"this format string is missing its $0-$8, contains a $9, or \"\n        \"contains an unescaped $ character (use $$ instead)\");\n\nstd::string Substitute(\n    const char* absl_nonnull format, const substitute_internal::Arg& a0,\n    const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,\n    const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,\n    const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,\n    const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,\n    const substitute_internal::Arg& a9)\n    ABSL_BAD_CALL_IF(\n        substitute_internal::PlaceholderBitmask(format) != 1023,\n        \"There were 10 substitution arguments given, but this \"\n        \"format string either doesn't contain all of $0 through $9 or \"\n        \"contains an unescaped $ character (use $$ instead)\");\n#endif  // ABSL_BAD_CALL_IF\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_STRINGS_SUBSTITUTE_H_\n"
  },
  {
    "path": "absl/strings/substitute_benchmark.cc",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstdint>\n#include <string>\n\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/substitute.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_Substitute(benchmark::State& state) {\n  std::string s(state.range(0), 'x');\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result = absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$\", s,\n                                          s, s, s, s, s, s, s, s, s);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_Substitute)->Range(0, 1024);\n\n// Like BM_Substitute, but use char* strings (which must then be copied\n// to STL strings) for all parameters.  This demonstrates that it is faster\n// to use absl::Substitute() even if your inputs are char* strings.\nvoid BM_SubstituteCstr(benchmark::State& state) {\n  std::string s(state.range(0), 'x');\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result =\n        absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$\", s.c_str(),\n                         s.c_str(), s.c_str(), s.c_str(), s.c_str(), s.c_str(),\n                         s.c_str(), s.c_str(), s.c_str(), s.c_str());\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_SubstituteCstr)->Range(0, 1024);\n\n// For comparison with BM_Substitute.\nvoid BM_StringPrintf(benchmark::State& state) {\n  std::string s(state.range(0), 'x');\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result = absl::StrCat(s, \" \", s, \" \", s, \" \", s, \" \", s, \" \", s,\n                                      \" \", s, \" \", s, \" \", s, \" \", s);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_StringPrintf)->Range(0, 1024);\n\n// Benchmark using absl::Substitute() together with SimpleItoa() to print\n// numbers.  This demonstrates that absl::Substitute() is faster than\n// StringPrintf() even when the inputs are numbers.\nvoid BM_SubstituteNumber(benchmark::State& state) {\n  const int n = state.range(0);\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result =\n        absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$\", n, n + 1, n + 2,\n                         n + 3, n + 4, n + 5, n + 6, n + 7, n + 8, n + 9);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_SubstituteNumber)->Arg(0)->Arg(1 << 20);\n\n// For comparison with BM_SubstituteNumber.\nvoid BM_StrCatNumber(benchmark::State& state) {\n  const int n = state.range(0);\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result =\n        absl::StrCat(n, \" \", n + 1, \" \", n + 2, \" \", n + 3, \" \", n + 4, \" \",\n                     n + 5, \" \", n + 6, \" \", n + 7, \" \", n + 8, \" \", n + 9);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_StrCatNumber)->Arg(0)->Arg(1 << 20);\n\n// Benchmark using absl::Substitute() with a single substitution, to test the\n// speed at which it copies simple text.  Even in this case, it's faster\n// that StringPrintf().\nvoid BM_SubstituteSimpleText(benchmark::State& state) {\n  std::string s(state.range(0), 'x');\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result = absl::Substitute(\"$0\", s.c_str());\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_SubstituteSimpleText)->Range(0, 1024);\n\n// For comparison with BM_SubstituteSimpleText.\nvoid BM_StrCatSimpleText(benchmark::State& state) {\n  std::string s(state.range(0), 'x');\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result = absl::StrCat(\"\", s);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_StrCatSimpleText)->Range(0, 1024);\n\nstd::string MakeFormatByDensity(int density, bool subs_mode) {\n  std::string format((2 + density) * 10, 'x');\n  for (size_t i = 0; i < 10; ++i) {\n    format[density * i] = subs_mode ? '$' : '%';\n    format[density * i + 1] = subs_mode ? ('0' + i) : 's';\n  }\n  return format;\n}\n\nvoid BM_SubstituteDensity(benchmark::State& state) {\n  const std::string s(10, 'x');\n  const std::string format = MakeFormatByDensity(state.range(0), true);\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result = absl::Substitute(format, s, s, s, s, s, s, s, s, s, s);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_SubstituteDensity)->Range(0, 256);\n\nvoid BM_StrCatDensity(benchmark::State& state) {\n  const std::string s(10, 'x');\n  const std::string format(state.range(0), 'x');\n  int64_t bytes = 0;\n  for (auto _ : state) {\n    std::string result =\n        absl::StrCat(s, format, s, format, s, format, s, format, s, format, s,\n                     format, s, format, s, format, s, format, s, format);\n    bytes += result.size();\n  }\n  state.SetBytesProcessed(bytes);\n}\nBENCHMARK(BM_StrCatDensity)->Range(0, 256);\n\n}  // namespace\n"
  },
  {
    "path": "absl/strings/substitute_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/strings/substitute.h\"\n\n#include <cstdint>\n#include <cstring>\n#include <string>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nstruct MyStruct {\n  template <typename Sink>\n  friend void AbslStringify(Sink& sink, const MyStruct& s) {\n    sink.Append(\"MyStruct{.value = \");\n    sink.Append(absl::StrCat(s.value));\n    sink.Append(\"}\");\n  }\n  int value;\n};\n\nTEST(SubstituteTest, Substitute) {\n  // Basic.\n  EXPECT_EQ(\"Hello, world!\", absl::Substitute(\"$0, $1!\", \"Hello\", \"world\"));\n\n  // Non-char* types.\n  EXPECT_EQ(\"123 0.2 0.1 foo true false x\",\n            absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6\", 123, 0.2, 0.1f,\n                             std::string(\"foo\"), true, false, 'x'));\n\n  // All int types.\n  EXPECT_EQ(\n      \"-32767 65535 \"\n      \"-1234567890 3234567890 \"\n      \"-1234567890 3234567890 \"\n      \"-1234567890123456789 9234567890123456789\",\n      absl::Substitute(\n          \"$0 $1 $2 $3 $4 $5 $6 $7\",\n          static_cast<short>(-32767),          // NOLINT(runtime/int)\n          static_cast<unsigned short>(65535),  // NOLINT(runtime/int)\n          -1234567890, 3234567890U, -1234567890L, 3234567890UL,\n          -int64_t{1234567890123456789}, uint64_t{9234567890123456789u}));\n\n  // Hex format\n  EXPECT_EQ(\"0 1 f ffff0ffff 0123456789abcdef\",\n            absl::Substitute(\"$0$1$2$3$4 $5\",  //\n                             absl::Hex(0), absl::Hex(1, absl::kSpacePad2),\n                             absl::Hex(0xf, absl::kSpacePad2),\n                             absl::Hex(int16_t{-1}, absl::kSpacePad5),\n                             absl::Hex(int16_t{-1}, absl::kZeroPad5),\n                             absl::Hex(0x123456789abcdef, absl::kZeroPad16)));\n\n  // Dec format\n  EXPECT_EQ(\"0 115   -1-0001 81985529216486895\",\n            absl::Substitute(\"$0$1$2$3$4 $5\",  //\n                             absl::Dec(0), absl::Dec(1, absl::kSpacePad2),\n                             absl::Dec(0xf, absl::kSpacePad2),\n                             absl::Dec(int16_t{-1}, absl::kSpacePad5),\n                             absl::Dec(int16_t{-1}, absl::kZeroPad5),\n                             absl::Dec(0x123456789abcdef, absl::kZeroPad16)));\n\n  // Pointer.\n  const int* int_p = reinterpret_cast<const int*>(0x12345);\n  std::string str = absl::Substitute(\"$0\", int_p);\n  EXPECT_EQ(absl::StrCat(\"0x\", absl::Hex(int_p)), str);\n\n  // Volatile Pointer.\n  // Like C++ streamed I/O, such pointers implicitly become bool\n  volatile int vol = 237;\n  volatile int* volatile volptr = &vol;\n  str = absl::Substitute(\"$0\", volptr);\n  EXPECT_EQ(\"true\", str);\n\n  // null is special. StrCat prints 0x0. Substitute prints NULL.\n  const uint64_t* null_p = nullptr;\n  str = absl::Substitute(\"$0\", null_p);\n  EXPECT_EQ(\"NULL\", str);\n\n  // char* is also special.\n  const char* char_p = \"print me\";\n  str = absl::Substitute(\"$0\", char_p);\n  EXPECT_EQ(\"print me\", str);\n\n  char char_buf[16];\n  strncpy(char_buf, \"print me too\", sizeof(char_buf));\n  str = absl::Substitute(\"$0\", char_buf);\n  EXPECT_EQ(\"print me too\", str);\n\n  // null char* is \"doubly\" special. Represented as the empty string.\n  char_p = nullptr;\n  str = absl::Substitute(\"$0\", char_p);\n  EXPECT_EQ(\"\", str);\n\n  // Out-of-order.\n  EXPECT_EQ(\"b, a, c, b\", absl::Substitute(\"$1, $0, $2, $1\", \"a\", \"b\", \"c\"));\n\n  // Literal $\n  EXPECT_EQ(\"$\", absl::Substitute(\"$$\"));\n\n  EXPECT_EQ(\"$1\", absl::Substitute(\"$$1\"));\n\n  // Test all overloads.\n  EXPECT_EQ(\"a\", absl::Substitute(\"$0\", \"a\"));\n  EXPECT_EQ(\"a b\", absl::Substitute(\"$0 $1\", \"a\", \"b\"));\n  EXPECT_EQ(\"a b c\", absl::Substitute(\"$0 $1 $2\", \"a\", \"b\", \"c\"));\n  EXPECT_EQ(\"a b c d\", absl::Substitute(\"$0 $1 $2 $3\", \"a\", \"b\", \"c\", \"d\"));\n  EXPECT_EQ(\"a b c d e\",\n            absl::Substitute(\"$0 $1 $2 $3 $4\", \"a\", \"b\", \"c\", \"d\", \"e\"));\n  EXPECT_EQ(\"a b c d e f\", absl::Substitute(\"$0 $1 $2 $3 $4 $5\", \"a\", \"b\", \"c\",\n                                            \"d\", \"e\", \"f\"));\n  EXPECT_EQ(\"a b c d e f g\", absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6\", \"a\", \"b\",\n                                              \"c\", \"d\", \"e\", \"f\", \"g\"));\n  EXPECT_EQ(\"a b c d e f g h\",\n            absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7\", \"a\", \"b\", \"c\", \"d\", \"e\",\n                             \"f\", \"g\", \"h\"));\n  EXPECT_EQ(\"a b c d e f g h i\",\n            absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7 $8\", \"a\", \"b\", \"c\", \"d\",\n                             \"e\", \"f\", \"g\", \"h\", \"i\"));\n  EXPECT_EQ(\"a b c d e f g h i j\",\n            absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9\", \"a\", \"b\", \"c\",\n                             \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"));\n  EXPECT_EQ(\"a b c d e f g h i j b0\",\n            absl::Substitute(\"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10\", \"a\", \"b\", \"c\",\n                             \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"));\n\n  const char* null_cstring = nullptr;\n  EXPECT_EQ(\"Text: ''\", absl::Substitute(\"Text: '$0'\", null_cstring));\n\n  MyStruct s1 = MyStruct{17};\n  MyStruct s2 = MyStruct{1043};\n  EXPECT_EQ(\"MyStruct{.value = 17}, MyStruct{.value = 1043}\",\n            absl::Substitute(\"$0, $1\", s1, s2));\n}\n\nTEST(SubstituteTest, SubstituteAndAppend) {\n  std::string str = \"Hello\";\n  absl::SubstituteAndAppend(&str, \", $0!\", \"world\");\n  EXPECT_EQ(\"Hello, world!\", str);\n\n  // Test all overloads.\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0\", \"a\");\n  EXPECT_EQ(\"a\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1\", \"a\", \"b\");\n  EXPECT_EQ(\"a b\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2\", \"a\", \"b\", \"c\");\n  EXPECT_EQ(\"a b c\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3\", \"a\", \"b\", \"c\", \"d\");\n  EXPECT_EQ(\"a b c d\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3 $4\", \"a\", \"b\", \"c\", \"d\", \"e\");\n  EXPECT_EQ(\"a b c d e\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3 $4 $5\", \"a\", \"b\", \"c\", \"d\", \"e\",\n                            \"f\");\n  EXPECT_EQ(\"a b c d e f\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3 $4 $5 $6\", \"a\", \"b\", \"c\", \"d\",\n                            \"e\", \"f\", \"g\");\n  EXPECT_EQ(\"a b c d e f g\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3 $4 $5 $6 $7\", \"a\", \"b\", \"c\", \"d\",\n                            \"e\", \"f\", \"g\", \"h\");\n  EXPECT_EQ(\"a b c d e f g h\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3 $4 $5 $6 $7 $8\", \"a\", \"b\", \"c\",\n                            \"d\", \"e\", \"f\", \"g\", \"h\", \"i\");\n  EXPECT_EQ(\"a b c d e f g h i\", str);\n  str.clear();\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9\", \"a\", \"b\",\n                            \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\");\n  EXPECT_EQ(\"a b c d e f g h i j\", str);\n\n  str.clear();\n  MyStruct s1 = MyStruct{17};\n  MyStruct s2 = MyStruct{1043};\n  absl::SubstituteAndAppend(&str, \"$0, $1\", s1, s2);\n  EXPECT_EQ(\"MyStruct{.value = 17}, MyStruct{.value = 1043}\", str);\n}\n\nTEST(SubstituteTest, VectorBoolRef) {\n  std::vector<bool> v = {true, false};\n  const auto& cv = v;\n  EXPECT_EQ(\"true false true false\",\n            absl::Substitute(\"$0 $1 $2 $3\", v[0], v[1], cv[0], cv[1]));\n\n  std::string str = \"Logic be like: \";\n  absl::SubstituteAndAppend(&str, \"$0 $1 $2 $3\", v[0], v[1], cv[0], cv[1]);\n  EXPECT_EQ(\"Logic be like: true false true false\", str);\n}\n\nTEST(SubstituteTest, Enums) {\n  enum UnscopedEnum { kEnum0 = 0, kEnum1 = 1 };\n  EXPECT_EQ(\"0 1\", absl::Substitute(\"$0 $1\", UnscopedEnum::kEnum0,\n                                    UnscopedEnum::kEnum1));\n\n  enum class ScopedEnum { kEnum0 = 0, kEnum1 = 1 };\n  EXPECT_EQ(\"0 1\",\n            absl::Substitute(\"$0 $1\", ScopedEnum::kEnum0, ScopedEnum::kEnum1));\n\n  enum class ScopedEnumInt32 : int32_t { kEnum0 = 989, kEnum1 = INT32_MIN };\n  EXPECT_EQ(\"989 -2147483648\",\n            absl::Substitute(\"$0 $1\", ScopedEnumInt32::kEnum0,\n                             ScopedEnumInt32::kEnum1));\n\n  enum class ScopedEnumUInt32 : uint32_t { kEnum0 = 1, kEnum1 = UINT32_MAX };\n  EXPECT_EQ(\"1 4294967295\", absl::Substitute(\"$0 $1\", ScopedEnumUInt32::kEnum0,\n                                             ScopedEnumUInt32::kEnum1));\n\n  enum class ScopedEnumInt64 : int64_t { kEnum0 = -1, kEnum1 = 42949672950 };\n  EXPECT_EQ(\"-1 42949672950\", absl::Substitute(\"$0 $1\", ScopedEnumInt64::kEnum0,\n                                               ScopedEnumInt64::kEnum1));\n\n  enum class ScopedEnumUInt64 : uint64_t { kEnum0 = 1, kEnum1 = 42949672950 };\n  EXPECT_EQ(\"1 42949672950\", absl::Substitute(\"$0 $1\", ScopedEnumUInt64::kEnum0,\n                                              ScopedEnumUInt64::kEnum1));\n\n  enum class ScopedEnumChar : signed char { kEnum0 = -1, kEnum1 = 1 };\n  EXPECT_EQ(\"-1 1\", absl::Substitute(\"$0 $1\", ScopedEnumChar::kEnum0,\n                                     ScopedEnumChar::kEnum1));\n\n  enum class ScopedEnumUChar : unsigned char {\n    kEnum0 = 0,\n    kEnum1 = 1,\n    kEnumMax = 255\n  };\n  EXPECT_EQ(\"0 1 255\", absl::Substitute(\"$0 $1 $2\", ScopedEnumUChar::kEnum0,\n                                        ScopedEnumUChar::kEnum1,\n                                        ScopedEnumUChar::kEnumMax));\n\n  enum class ScopedEnumInt16 : int16_t { kEnum0 = -100, kEnum1 = 10000 };\n  EXPECT_EQ(\"-100 10000\", absl::Substitute(\"$0 $1\", ScopedEnumInt16::kEnum0,\n                                           ScopedEnumInt16::kEnum1));\n\n  enum class ScopedEnumUInt16 : uint16_t { kEnum0 = 0, kEnum1 = 10000 };\n  EXPECT_EQ(\"0 10000\", absl::Substitute(\"$0 $1\", ScopedEnumUInt16::kEnum0,\n                                        ScopedEnumUInt16::kEnum1));\n}\n\nenum class EnumWithStringify { Many = 0, Choices = 1 };\n\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, EnumWithStringify e) {\n  sink.Append(e == EnumWithStringify::Many ? \"Many\" : \"Choices\");\n}\n\nTEST(SubstituteTest, AbslStringifyWithEnum) {\n  const auto e = EnumWithStringify::Choices;\n  EXPECT_EQ(absl::Substitute(\"$0\", e), \"Choices\");\n}\n\n#if GTEST_HAS_DEATH_TEST\n\nTEST(SubstituteDeathTest, SubstituteDeath) {\n  EXPECT_DEBUG_DEATH(\n      static_cast<void>(absl::Substitute(absl::string_view(\"-$2\"), \"a\", \"b\")),\n      \"Invalid absl::Substitute\\\\(\\\\) format string: asked for \\\"\\\\$2\\\", \"\n      \"but only 2 args were given.\");\n  EXPECT_DEBUG_DEATH(\n      static_cast<void>(absl::Substitute(absl::string_view(\"-$z-\"))),\n      \"Invalid absl::Substitute\\\\(\\\\) format string: \\\"-\\\\$z-\\\"\");\n  EXPECT_DEBUG_DEATH(\n      static_cast<void>(absl::Substitute(absl::string_view(\"-$\"))),\n      \"Invalid absl::Substitute\\\\(\\\\) format string: \\\"-\\\\$\\\"\");\n}\n\n#endif  // GTEST_HAS_DEATH_TEST\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:private\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\n# Internal data structure for efficiently detecting mutex dependency cycles\ncc_library(\n    name = \"graphcycles_internal\",\n    srcs = [\n        \"internal/graphcycles.cc\",\n    ],\n    hdrs = [\n        \"internal/graphcycles.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS + select({\n        \"//conditions:default\": [],\n    }),\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:base_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:malloc_internal\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_library(\n    name = \"kernel_timeout_internal\",\n    srcs = [\"internal/kernel_timeout.cc\"],\n    hdrs = [\"internal/kernel_timeout.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n    ],\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/time\",\n    ],\n)\n\ncc_test(\n    name = \"kernel_timeout_internal_test\",\n    srcs = [\"internal/kernel_timeout_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":kernel_timeout_internal\",\n        \"//absl/base:config\",\n        \"//absl/random\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"synchronization\",\n    srcs = [\n        \"barrier.cc\",\n        \"blocking_counter.cc\",\n        \"internal/create_thread_identity.cc\",\n        \"internal/futex_waiter.cc\",\n        \"internal/per_thread_sem.cc\",\n        \"internal/pthread_waiter.cc\",\n        \"internal/sem_waiter.cc\",\n        \"internal/stdcpp_waiter.cc\",\n        \"internal/waiter_base.cc\",\n        \"internal/win32_waiter.cc\",\n        \"mutex.cc\",\n        \"notification.cc\",\n    ],\n    hdrs = [\n        \"barrier.h\",\n        \"blocking_counter.h\",\n        \"internal/create_thread_identity.h\",\n        \"internal/futex.h\",\n        \"internal/futex_waiter.h\",\n        \"internal/per_thread_sem.h\",\n        \"internal/pthread_waiter.h\",\n        \"internal/sem_waiter.h\",\n        \"internal/stdcpp_waiter.h\",\n        \"internal/waiter.h\",\n        \"internal/waiter_base.h\",\n        \"internal/win32_waiter.h\",\n        \"mutex.h\",\n        \"notification.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = select({\n        \"@rules_cc//cc/compiler:msvc-cl\": [],\n        \"@rules_cc//cc/compiler:clang-cl\": [],\n        \"@rules_cc//cc/compiler:emscripten\": [],\n        \"//conditions:default\": [\"-pthread\"],\n    }) + ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":graphcycles_internal\",\n        \":kernel_timeout_internal\",\n        \"//absl/base\",\n        \"//absl/base:atomic_hook\",\n        \"//absl/base:base_internal\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:dynamic_annotations\",\n        \"//absl/base:malloc_internal\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/base:tracing_internal\",\n        \"//absl/debugging:stacktrace\",\n        \"//absl/debugging:symbolize\",\n        \"//absl/meta:type_traits\",\n        \"//absl/time\",\n    ] + select({\n        \"//conditions:default\": [],\n    }),\n)\n\ncc_test(\n    name = \"barrier_test\",\n    size = \"small\",\n    srcs = [\"barrier_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",  # b/122473323\n    ],\n    deps = [\n        \":synchronization\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"blocking_counter_test\",\n    size = \"small\",\n    srcs = [\"blocking_counter_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",  # b/122473323\n    ],\n    deps = [\n        \":synchronization\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:tracing_internal\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"blocking_counter_benchmark\",\n    testonly = True,\n    srcs = [\"blocking_counter_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"benchmark\"],\n    deps = [\n        \":synchronization\",\n        \":thread_pool\",\n        \"//absl/base:no_destructor\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_test(\n    name = \"graphcycles_test\",\n    size = \"medium\",\n    srcs = [\"internal/graphcycles_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":graphcycles_internal\",\n        \"//absl/base:core_headers\",\n        \"//absl/log\",\n        \"//absl/log:check\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"graphcycles_benchmark\",\n    srcs = [\"internal/graphcycles_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"benchmark\",\n    ],\n    deps = [\n        \":graphcycles_internal\",\n        \"//absl/base:raw_logging_internal\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"thread_pool\",\n    testonly = True,\n    hdrs = [\"internal/thread_pool.h\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:__subpackages__\",\n    ],\n    deps = [\n        \":synchronization\",\n        \"//absl/base:core_headers\",\n        \"//absl/functional:any_invocable\",\n    ],\n)\n\ncc_test(\n    name = \"mutex_test\",\n    size = \"large\",\n    srcs = [\"mutex_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    shard_count = 25,\n    deps = [\n        \":synchronization\",\n        \":thread_pool\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/log\",\n        \"//absl/log:check\",\n        \"//absl/memory\",\n        \"//absl/random\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"mutex_method_pointer_test\",\n    srcs = [\"mutex_method_pointer_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":synchronization\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"mutex_benchmark_common\",\n    testonly = True,\n    srcs = [\"mutex_benchmark.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":synchronization\",\n        \":thread_pool\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:no_destructor\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n    alwayslink = 1,\n)\n\ncc_binary(\n    name = \"mutex_benchmark\",\n    testonly = True,\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":mutex_benchmark_common\",\n    ],\n)\n\ncc_test(\n    name = \"notification_test\",\n    size = \"small\",\n    srcs = [\"notification_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\"no_test_lexan\"],\n    deps = [\n        \":synchronization\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:tracing_internal\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"per_thread_sem_test_common\",\n    testonly = True,\n    srcs = [\"internal/per_thread_sem_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\n        \"//absl:friends\",\n    ],\n    deps = [\n        \":synchronization\",\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n    ],\n    alwayslink = 1,\n)\n\ncc_test(\n    name = \"per_thread_sem_test\",\n    size = \"large\",\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_wasm\",\n        \"noubsan\",  # TODO(b/417700722):  timeouts under UBSAN.\n    ],\n    deps = [\n        \":per_thread_sem_test_common\",\n        \":synchronization\",\n        \"//absl/strings\",\n        \"//absl/time\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"waiter_test\",\n    srcs = [\"internal/waiter_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    flaky = 1,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":kernel_timeout_internal\",\n        \":synchronization\",\n        \":thread_pool\",\n        \"//absl/base:config\",\n        \"//absl/random\",\n        \"//absl/time\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"lifetime_test\",\n    srcs = [\n        \"lifetime_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_ios_x86_64\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":synchronization\",\n        \"//absl/base:core_headers\",\n        \"//absl/log:check\",\n    ],\n)\n"
  },
  {
    "path": "absl/synchronization/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    graphcycles_internal\n  HDRS\n    \"internal/graphcycles.h\"\n  SRCS\n    \"internal/graphcycles.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::base_internal\n    absl::config\n    absl::core_headers\n    absl::malloc_internal\n    absl::raw_logging_internal\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    kernel_timeout_internal\n  HDRS\n    \"internal/kernel_timeout.h\"\n  SRCS\n    \"internal/kernel_timeout.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::raw_logging_internal\n    absl::time\n)\n\nabsl_cc_test(\n  NAME\n    kernel_timeout_internal_test\n  SRCS\n    \"internal/kernel_timeout_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::kernel_timeout_internal\n    absl::config\n    absl::random_random\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    synchronization\n  HDRS\n    \"barrier.h\"\n    \"blocking_counter.h\"\n    \"internal/create_thread_identity.h\"\n    \"internal/futex.h\"\n    \"internal/futex_waiter.h\"\n    \"internal/per_thread_sem.h\"\n    \"internal/pthread_waiter.h\"\n    \"internal/sem_waiter.h\"\n    \"internal/stdcpp_waiter.h\"\n    \"internal/waiter.h\"\n    \"internal/waiter_base.h\"\n    \"internal/win32_waiter.h\"\n    \"mutex.h\"\n    \"notification.h\"\n  SRCS\n    \"barrier.cc\"\n    \"blocking_counter.cc\"\n    \"internal/create_thread_identity.cc\"\n    \"internal/futex_waiter.cc\"\n    \"internal/per_thread_sem.cc\"\n    \"internal/pthread_waiter.cc\"\n    \"internal/sem_waiter.cc\"\n    \"internal/stdcpp_waiter.cc\"\n    \"internal/waiter_base.cc\"\n    \"internal/win32_waiter.cc\"\n    \"notification.cc\"\n    \"mutex.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::graphcycles_internal\n    absl::kernel_timeout_internal\n    absl::atomic_hook\n    absl::base\n    absl::base_internal\n    absl::config\n    absl::core_headers\n    absl::dynamic_annotations\n    absl::malloc_internal\n    absl::meta\n    absl::nullability\n    absl::raw_logging_internal\n    absl::stacktrace\n    absl::symbolize\n    absl::time\n    absl::tracing_internal\n    Threads::Threads\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    barrier_test\n  SRCS\n    \"barrier_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::synchronization\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    blocking_counter_test\n  SRCS\n    \"blocking_counter_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::synchronization\n    absl::time\n    absl::tracing_internal\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    graphcycles_test\n  SRCS\n    \"internal/graphcycles_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::check\n    absl::core_headers\n    absl::graphcycles_internal\n    absl::log\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    thread_pool\n  HDRS\n    \"internal/thread_pool.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::any_invocable\n    absl::core_headers\n    absl::synchronization\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    mutex_test\n  SRCS\n    \"mutex_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::synchronization\n    absl::thread_pool\n    absl::base\n    absl::check\n    absl::config\n    absl::core_headers\n    absl::log\n    absl::memory\n    absl::random_random\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    mutex_method_pointer_test\n  SRCS\n    \"mutex_method_pointer_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::synchronization\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    notification_test\n  SRCS\n    \"notification_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::synchronization\n    absl::time\n    absl::tracing_internal\n    GTest::gmock_main\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    per_thread_sem_test_common\n  SRCS\n    \"internal/per_thread_sem_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::synchronization\n    absl::base\n    absl::config\n    absl::strings\n    absl::time\n    GTest::gmock\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    per_thread_sem_test\n  SRCS\n    \"internal/per_thread_sem_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::per_thread_sem_test_common\n    absl::synchronization\n    absl::strings\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    waiter_test\n  SRCS\n    \"internal/waiter_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::kernel_timeout_internal\n    absl::random_random\n    absl::synchronization\n    absl::thread_pool\n    absl::time\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    lifetime_test\n  SRCS\n    \"lifetime_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::synchronization\n    absl::core_headers\n    absl::check\n)\n"
  },
  {
    "path": "absl/synchronization/barrier.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/barrier.h\"\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Return whether int *arg is zero.\nstatic bool IsZero(void *arg) {\n  return 0 == *reinterpret_cast<int *>(arg);\n}\n\nbool Barrier::Block() {\n  MutexLock l(this->lock_);\n\n  this->num_to_block_--;\n  if (this->num_to_block_ < 0) {\n    ABSL_RAW_LOG(\n        FATAL,\n        \"Block() called too many times.  num_to_block_=%d out of total=%d\",\n        this->num_to_block_, this->num_to_exit_);\n  }\n\n  this->lock_.Await(Condition(IsZero, &this->num_to_block_));\n\n  // Determine which thread can safely delete this Barrier object\n  this->num_to_exit_--;\n  ABSL_RAW_CHECK(this->num_to_exit_ >= 0, \"barrier underflow\");\n\n  // If num_to_exit_ == 0 then all other threads in the barrier have\n  // exited the Wait() and have released the Mutex so this thread is\n  // free to delete the barrier.\n  return this->num_to_exit_ == 0;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/barrier.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// barrier.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_SYNCHRONIZATION_BARRIER_H_\n#define ABSL_SYNCHRONIZATION_BARRIER_H_\n\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Barrier\n//\n// This class creates a barrier which blocks threads until a prespecified\n// threshold of threads (`num_threads`) utilizes the barrier. A thread utilizes\n// the `Barrier` by calling `Block()` on the barrier, which will block that\n// thread; no call to `Block()` will return until `num_threads` threads have\n// called it.\n//\n// Exactly one call to `Block()` will return `true`, which is then responsible\n// for destroying the barrier; because stack allocation will cause the barrier\n// to be deleted when it is out of scope, barriers should not be stack\n// allocated.\n//\n// Example:\n//\n//   // Main thread creates a `Barrier`:\n//   barrier = new Barrier(num_threads);\n//\n//   // Each participating thread could then call:\n//   if (barrier->Block()) delete barrier;  // Exactly one call to `Block()`\n//                                          // returns `true`; that call\n//                                          // deletes the barrier.\nclass Barrier {\n public:\n  // `num_threads` is the number of threads that will participate in the barrier\n  explicit Barrier(int num_threads)\n      : num_to_block_(num_threads), num_to_exit_(num_threads) {}\n\n  Barrier(const Barrier&) = delete;\n  Barrier& operator=(const Barrier&) = delete;\n\n  // Barrier::Block()\n  //\n  // Blocks the current thread, and returns only when the `num_threads`\n  // threshold of threads utilizing this barrier has been reached. `Block()`\n  // returns `true` for precisely one caller, which may then destroy the\n  // barrier.\n  //\n  // Memory ordering: For any threads X and Y, any action taken by X\n  // before X calls `Block()` will be visible to Y after Y returns from\n  // `Block()`.\n  bool Block();\n\n private:\n  Mutex lock_;\n  int num_to_block_ ABSL_GUARDED_BY(lock_);\n  int num_to_exit_ ABSL_GUARDED_BY(lock_);\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_SYNCHRONIZATION_BARRIER_H_\n"
  },
  {
    "path": "absl/synchronization/barrier_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/barrier.h\"\n\n#include <thread>  // NOLINT(build/c++11)\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/clock.h\"\n\n\nTEST(Barrier, SanityTest) {\n  constexpr int kNumThreads = 10;\n  absl::Barrier* barrier = new absl::Barrier(kNumThreads);\n\n  absl::Mutex mutex;\n  int counter = 0;  // Guarded by mutex.\n\n  auto thread_func = [&] {\n    if (barrier->Block()) {\n      // This thread is the last thread to reach the barrier so it is\n      // responsible for deleting it.\n      delete barrier;\n    }\n\n    // Increment the counter.\n    absl::MutexLock lock(mutex);\n    ++counter;\n  };\n\n  // Start (kNumThreads - 1) threads running thread_func.\n  std::vector<std::thread> threads;\n  for (int i = 0; i < kNumThreads - 1; ++i) {\n    threads.push_back(std::thread(thread_func));\n  }\n\n  // Give (kNumThreads - 1) threads a chance to reach the barrier.\n  // This test assumes at least one thread will have run after the\n  // sleep has elapsed. Sleeping in a test is usually bad form, but we\n  // need to make sure that we are testing the barrier instead of some\n  // other synchronization method.\n  absl::SleepFor(absl::Seconds(1));\n\n  // The counter should still be zero since no thread should have\n  // been able to pass the barrier yet.\n  {\n    absl::MutexLock lock(mutex);\n    EXPECT_EQ(counter, 0);\n  }\n\n  // Start 1 more thread. This should make all threads pass the barrier.\n  threads.push_back(std::thread(thread_func));\n\n  // All threads should now be able to proceed and finish.\n  for (auto& thread : threads) {\n    thread.join();\n  }\n\n  // All threads should now have incremented the counter.\n  absl::MutexLock lock(mutex);\n  EXPECT_EQ(counter, kNumThreads);\n}\n"
  },
  {
    "path": "absl/synchronization/blocking_counter.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/blocking_counter.h\"\n\n#include <atomic>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/tracing.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\n// Return whether int *arg is true.\nbool IsDone(void *arg) { return *reinterpret_cast<bool *>(arg); }\n\n}  // namespace\n\nBlockingCounter::BlockingCounter(int initial_count)\n    : count_(initial_count),\n      num_waiting_(0),\n      done_{initial_count == 0 ? true : false} {\n  ABSL_RAW_CHECK(initial_count >= 0, \"BlockingCounter initial_count negative\");\n}\n\nbool BlockingCounter::DecrementCount() {\n  int count = count_.fetch_sub(1, std::memory_order_acq_rel) - 1;\n  ABSL_RAW_CHECK(count >= 0,\n                 \"BlockingCounter::DecrementCount() called too many times\");\n  if (count == 0) {\n    base_internal::TraceSignal(this, TraceObjectKind());\n    MutexLock l(lock_);\n    done_ = true;\n    return true;\n  }\n  return false;\n}\n\nvoid BlockingCounter::Wait() {\n  base_internal::TraceWait(this, TraceObjectKind());\n  {\n    MutexLock l(this->lock_);\n\n    // only one thread may call Wait(). To support more than one thread,\n    // implement a counter num_to_exit, like in the Barrier class.\n    ABSL_RAW_CHECK(num_waiting_ == 0, \"multiple threads called Wait()\");\n    num_waiting_++;\n\n    this->lock_.Await(Condition(IsDone, &this->done_));\n\n    // At this point, we know that all threads executing DecrementCount\n    // will not touch this object again.\n    // Therefore, the thread calling this method is free to delete the object\n    // after we return from this method.\n  }\n  base_internal::TraceContinue(this, TraceObjectKind());\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/blocking_counter.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// blocking_counter.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_\n#define ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_\n\n#include <atomic>\n\n#include \"absl/base/internal/tracing.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// BlockingCounter\n//\n// This class allows a thread to block for a pre-specified number of actions.\n// `BlockingCounter` maintains a single non-negative abstract integer \"count\"\n// with an initial value `initial_count`. A thread can then call `Wait()` on\n// this blocking counter to block until the specified number of events occur;\n// worker threads then call 'DecrementCount()` on the counter upon completion of\n// their work. Once the counter's internal \"count\" reaches zero, the blocked\n// thread unblocks.\n//\n// A `BlockingCounter` requires the following:\n//     - its `initial_count` is non-negative.\n//     - the number of calls to `DecrementCount()` on it is at most\n//       `initial_count`.\n//     - `Wait()` is called at most once on it.\n//\n// Given the above requirements, a `BlockingCounter` provides the following\n// guarantees:\n//     - Once its internal \"count\" reaches zero, no legal action on the object\n//       can further change the value of \"count\".\n//     - When `Wait()` returns, it is legal to destroy the `BlockingCounter`.\n//     - When `Wait()` returns, the number of calls to `DecrementCount()` on\n//       this blocking counter exactly equals `initial_count`.\n//\n// Example:\n//     BlockingCounter bcount(N);         // there are N items of work\n//     ... Allow worker threads to start.\n//     ... On completing each work item, workers do:\n//     ... bcount.DecrementCount();      // an item of work has been completed\n//\n//     bcount.Wait();                    // wait for all work to be complete\n//\nclass BlockingCounter {\n public:\n  explicit BlockingCounter(int initial_count);\n\n  BlockingCounter(const BlockingCounter&) = delete;\n  BlockingCounter& operator=(const BlockingCounter&) = delete;\n\n  // BlockingCounter::DecrementCount()\n  //\n  // Decrements the counter's \"count\" by one, and return \"count == 0\". This\n  // function requires that \"count != 0\" when it is called.\n  //\n  // Memory ordering: For any threads X and Y, any action taken by X\n  // before it calls `DecrementCount()` is visible to thread Y after\n  // Y's call to `DecrementCount()`, provided Y's call returns `true`.\n  bool DecrementCount();\n\n  // BlockingCounter::Wait()\n  //\n  // Blocks until the counter reaches zero. This function may be called at most\n  // once. On return, `DecrementCount()` will have been called \"initial_count\"\n  // times and the blocking counter may be destroyed.\n  //\n  // Memory ordering: For any threads X and Y, any action taken by X\n  // before X calls `DecrementCount()` is visible to Y after Y returns\n  // from `Wait()`.\n  void Wait();\n\n private:\n  // Convenience helper to reduce verbosity at call sites.\n  static inline constexpr base_internal::ObjectKind TraceObjectKind() {\n    return base_internal::ObjectKind::kBlockingCounter;\n  }\n\n  Mutex lock_;\n  std::atomic<int> count_;\n  int num_waiting_ ABSL_GUARDED_BY(lock_);\n  bool done_ ABSL_GUARDED_BY(lock_);\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_\n"
  },
  {
    "path": "absl/synchronization/blocking_counter_benchmark.cc",
    "content": "// Copyright 2021 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <limits>\n\n#include \"absl/base/no_destructor.h\"\n#include \"absl/synchronization/blocking_counter.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_BlockingCounter_SingleThread(benchmark::State& state) {\n  for (auto _ : state) {\n    int iterations = state.range(0);\n    absl::BlockingCounter counter{iterations};\n    for (int i = 0; i < iterations; ++i) {\n      counter.DecrementCount();\n    }\n    counter.Wait();\n  }\n}\nBENCHMARK(BM_BlockingCounter_SingleThread)\n    ->ArgName(\"iterations\")\n    ->Arg(2)\n    ->Arg(4)\n    ->Arg(16)\n    ->Arg(64)\n    ->Arg(256);\n\nvoid BM_BlockingCounter_DecrementCount(benchmark::State& state) {\n  static absl::NoDestructor<absl::BlockingCounter> counter(\n      std::numeric_limits<int>::max());\n  for (auto _ : state) {\n    counter->DecrementCount();\n  }\n}\nBENCHMARK(BM_BlockingCounter_DecrementCount)\n    ->Threads(2)\n    ->Threads(4)\n    ->Threads(6)\n    ->Threads(8)\n    ->Threads(10)\n    ->Threads(12)\n    ->Threads(16)\n    ->Threads(32)\n    ->Threads(64)\n    ->Threads(128);\n\nvoid BM_BlockingCounter_Wait(benchmark::State& state) {\n  int num_threads = state.range(0);\n  absl::synchronization_internal::ThreadPool pool(num_threads);\n  for (auto _ : state) {\n    absl::BlockingCounter counter{num_threads};\n    pool.Schedule([num_threads, &counter, &pool]() {\n      for (int i = 0; i < num_threads; ++i) {\n        pool.Schedule([&counter]() { counter.DecrementCount(); });\n      }\n    });\n    counter.Wait();\n  }\n}\nBENCHMARK(BM_BlockingCounter_Wait)\n    ->ArgName(\"threads\")\n    ->Arg(2)\n    ->Arg(4)\n    ->Arg(8)\n    ->Arg(16)\n    ->Arg(32)\n    ->Arg(64)\n    ->Arg(128);\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/blocking_counter_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/blocking_counter.h\"\n\n#include <thread>  // NOLINT(build/c++11)\n#include <tuple>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/tracing.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nvoid PauseAndDecreaseCounter(BlockingCounter* counter, int* done) {\n  absl::SleepFor(absl::Seconds(1));\n  *done = 1;\n  counter->DecrementCount();\n}\n\nTEST(BlockingCounterTest, BasicFunctionality) {\n  // This test verifies that BlockingCounter functions correctly. Starts a\n  // number of threads that just sleep for a second and decrement a counter.\n\n  // Initialize the counter.\n  const int num_workers = 10;\n  BlockingCounter counter(num_workers);\n\n  std::vector<std::thread> workers;\n  std::vector<int> done(num_workers, 0);\n\n  // Start a number of parallel tasks that will just wait for a seconds and\n  // then decrement the count.\n  workers.reserve(num_workers);\n  for (int k = 0; k < num_workers; k++) {\n    workers.emplace_back(\n        [&counter, &done, k] { PauseAndDecreaseCounter(&counter, &done[k]); });\n  }\n\n  // Wait for the threads to have all finished.\n  counter.Wait();\n\n  // Check that all the workers have completed.\n  for (int k = 0; k < num_workers; k++) {\n    EXPECT_EQ(1, done[k]);\n  }\n\n  for (std::thread& w : workers) {\n    w.join();\n  }\n}\n\nTEST(BlockingCounterTest, WaitZeroInitialCount) {\n  BlockingCounter counter(0);\n  counter.Wait();\n}\n\n#if GTEST_HAS_DEATH_TEST\nTEST(BlockingCounterTest, WaitNegativeInitialCount) {\n  EXPECT_DEATH(BlockingCounter counter(-1),\n               \"BlockingCounter initial_count negative\");\n}\n#endif\n\n}  // namespace\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\n\nnamespace base_internal {\n\nnamespace {\n\nusing TraceRecord = std::tuple<const void*, ObjectKind>;\n\nthread_local TraceRecord tls_signal;\nthread_local TraceRecord tls_wait;\nthread_local TraceRecord tls_continue;\n\n}  // namespace\n\n// Strong extern \"C\" implementation.\nextern \"C\" {\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,\n                                                   ObjectKind kind) {\n  tls_wait = {object, kind};\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,\n                                                       ObjectKind kind) {\n  tls_continue = {object, kind};\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,\n                                                     ObjectKind kind) {\n  tls_signal = {object, kind};\n}\n\n}  // extern \"C\"\n\nTEST(BlockingCounterTest, TracesSignal) {\n  BlockingCounter counter(2);\n\n  tls_signal = {};\n  counter.DecrementCount();\n  EXPECT_EQ(tls_signal, TraceRecord(nullptr, ObjectKind::kUnknown));\n\n  tls_signal = {};\n  counter.DecrementCount();\n  EXPECT_EQ(tls_signal, TraceRecord(&counter, ObjectKind::kBlockingCounter));\n}\n\nTEST(BlockingCounterTest, TracesWaitContinue) {\n  BlockingCounter counter(1);\n  counter.DecrementCount();\n\n  tls_wait = {};\n  tls_continue = {};\n  counter.Wait();\n  EXPECT_EQ(tls_wait, TraceRecord(&counter, ObjectKind::kBlockingCounter));\n  EXPECT_EQ(tls_continue, TraceRecord(&counter, ObjectKind::kBlockingCounter));\n}\n\n}  // namespace base_internal\n\n#endif  // ABSL_HAVE_ATTRIBUTE_WEAK\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/internal/create_thread_identity.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <stdint.h>\n\n#include <new>\n\n// This file is a no-op if the required LowLevelAlloc support is missing.\n#include \"absl/base/internal/low_level_alloc.h\"\n#include \"absl/synchronization/internal/waiter.h\"\n#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING\n\n#include <string.h>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// ThreadIdentity storage is persistent, we maintain a free-list of previously\n// released ThreadIdentity objects.\nABSL_CONST_INIT static base_internal::SpinLock freelist_lock(\n    base_internal::SCHEDULE_KERNEL_ONLY);\nABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist;\n\n// A per-thread destructor for reclaiming associated ThreadIdentity objects.\n// Since we must preserve their storage, we cache them for re-use instead of\n// truly destructing the object.\nstatic void ReclaimThreadIdentity(void* v) {\n  base_internal::ThreadIdentity* identity =\n      static_cast<base_internal::ThreadIdentity*>(v);\n\n  // all_locks might have been allocated by the Mutex implementation.\n  // We free it here when we are notified that our thread is dying.\n  if (identity->per_thread_synch.all_locks != nullptr) {\n    base_internal::LowLevelAlloc::Free(identity->per_thread_synch.all_locks);\n  }\n\n  // We must explicitly clear the current thread's identity:\n  // (a) Subsequent (unrelated) per-thread destructors may require an identity.\n  //     We must guarantee a new identity is used in this case (this instructor\n  //     will be reinvoked up to PTHREAD_DESTRUCTOR_ITERATIONS in this case).\n  // (b) ThreadIdentity implementations may depend on memory that is not\n  //     reinitialized before reuse.  We must allow explicit clearing of the\n  //     association state in this case.\n  base_internal::ClearCurrentThreadIdentity();\n  {\n    base_internal::SpinLockHolder l(freelist_lock);\n    identity->next = thread_identity_freelist;\n    thread_identity_freelist = identity;\n  }\n}\n\n// Return value rounded up to next multiple of align.\n// Align must be a power of two.\nstatic intptr_t RoundUp(intptr_t addr, intptr_t align) {\n  return (addr + align - 1) & ~(align - 1);\n}\n\nvoid OneTimeInitThreadIdentity(base_internal::ThreadIdentity* identity) {\n  PerThreadSem::Init(identity);\n  identity->ticker.store(0, std::memory_order_relaxed);\n  identity->wait_start.store(0, std::memory_order_relaxed);\n  identity->is_idle.store(false, std::memory_order_relaxed);\n  // To avoid a circular dependency we declare only the storage in the header\n  // and use placement new to construct the SpinLock.\n  static_assert(\n      sizeof(base_internal::ThreadIdentity::SchedulerState::\n                 association_lock_word) == sizeof(base_internal::SpinLock),\n      \"Wrong size for SpinLock\");\n  // Protects the association between this identity and its schedulable.  Should\n  // never be cooperative.\n  new (&identity->scheduler_state.association_lock_word)\n      base_internal::SpinLock(base_internal::SCHEDULE_KERNEL_ONLY);\n}\n\nstatic void ResetThreadIdentityBetweenReuse(\n    base_internal::ThreadIdentity* identity) {\n  base_internal::PerThreadSynch* pts = &identity->per_thread_synch;\n  pts->next = nullptr;\n  pts->skip = nullptr;\n  pts->may_skip = false;\n  pts->waitp = nullptr;\n  pts->suppress_fatal_errors = false;\n  pts->readers = 0;\n  pts->priority = 0;\n  pts->next_priority_read_cycles = 0;\n  pts->state.store(base_internal::PerThreadSynch::State::kAvailable,\n                   std::memory_order_relaxed);\n  pts->maybe_unlocking = false;\n  pts->wake = false;\n  pts->cond_waiter = false;\n  pts->all_locks = nullptr;\n  base_internal::ThreadIdentity::SchedulerState* ss =\n      &identity->scheduler_state;\n  ss->bound_schedulable.store(nullptr, std::memory_order_relaxed);\n  ss->association_lock_word = 0;\n  ss->scheduling_disabled_depth.store(0, std::memory_order_relaxed);\n  ss->potentially_blocking_depth = 0;\n  ss->schedule_next_state = 0;\n  ss->waking_designated_waker = false;\n  identity->static_initialization_depth = 0;\n  identity->wait_state.store(base_internal::ThreadIdentity::WaitState::kActive,\n                             std::memory_order_relaxed);\n  identity->blocked_count_ptr = nullptr;\n  identity->ticker.store(0, std::memory_order_relaxed);\n  identity->wait_start.store(0, std::memory_order_relaxed);\n  identity->is_idle.store(false, std::memory_order_relaxed);\n  identity->next = nullptr;\n}\n\nstatic base_internal::ThreadIdentity* NewThreadIdentity() {\n  base_internal::ThreadIdentity* identity = nullptr;\n\n  {\n    // Re-use a previously released object if possible.\n    base_internal::SpinLockHolder l(freelist_lock);\n    if (thread_identity_freelist) {\n      identity = thread_identity_freelist;  // Take list-head.\n      thread_identity_freelist = thread_identity_freelist->next;\n    }\n  }\n\n  if (identity == nullptr) {\n    // Allocate enough space to align ThreadIdentity to a multiple of\n    // PerThreadSynch::kAlignment. This space is never released (it is\n    // added to a freelist by ReclaimThreadIdentity instead).\n    void* allocation = base_internal::LowLevelAlloc::Alloc(\n        sizeof(*identity) + base_internal::PerThreadSynch::kAlignment - 1);\n    // Round up the address to the required alignment.\n    identity = reinterpret_cast<base_internal::ThreadIdentity*>(\n        RoundUp(reinterpret_cast<intptr_t>(allocation),\n                base_internal::PerThreadSynch::kAlignment));\n    // Note that *identity is never constructed.\n    // TODO(b/357097463): change this \"one time init\" to be a proper\n    // constructor.\n    OneTimeInitThreadIdentity(identity);\n  }\n  ResetThreadIdentityBetweenReuse(identity);\n\n  return identity;\n}\n\n// Allocates and attaches ThreadIdentity object for the calling thread.  Returns\n// the new identity.\n// REQUIRES: CurrentThreadIdentity(false) == nullptr\nbase_internal::ThreadIdentity* CreateThreadIdentity() {\n  base_internal::ThreadIdentity* identity = NewThreadIdentity();\n  // Associate the value with the current thread, and attach our destructor.\n  base_internal::SetCurrentThreadIdentity(identity, ReclaimThreadIdentity);\n  return identity;\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOW_LEVEL_ALLOC_MISSING\n"
  },
  {
    "path": "absl/synchronization/internal/create_thread_identity.h",
    "content": "/*\n * Copyright 2017 The Abseil Authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Interface for getting the current ThreadIdentity, creating one if necessary.\n// See thread_identity.h.\n//\n// This file is separate from thread_identity.h because creating a new\n// ThreadIdentity requires slightly higher level libraries (per_thread_sem\n// and low_level_alloc) than accessing an existing one.  This separation allows\n// us to have a smaller //absl/base:base.\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_\n\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/port.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// Allocates and attaches a ThreadIdentity object for the calling thread.\n// For private use only.\nbase_internal::ThreadIdentity* CreateThreadIdentity();\n\n// Returns the ThreadIdentity object representing the calling thread; guaranteed\n// to be unique for its lifetime.  The returned object will remain valid for the\n// program's lifetime; although it may be re-assigned to a subsequent thread.\n// If one does not exist for the calling thread, allocate it now.\ninline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() {\n  base_internal::ThreadIdentity* identity =\n      base_internal::CurrentThreadIdentityIfPresent();\n  if (ABSL_PREDICT_FALSE(identity == nullptr)) {\n    return CreateThreadIdentity();\n  }\n  return identity;\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_\n"
  },
  {
    "path": "absl/synchronization/internal/futex.h",
    "content": "// Copyright 2020 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_\n\n#include \"absl/base/config.h\"\n\n#ifndef _WIN32\n#include <sys/time.h>\n#include <unistd.h>\n#endif\n\n#ifdef __linux__\n#include <linux/futex.h>\n#include <sys/syscall.h>\n#endif\n\n#include <errno.h>\n#include <stdio.h>\n#include <time.h>\n\n#include <atomic>\n#include <cstdint>\n#include <limits>\n\n#include \"absl/base/optimization.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_FUTEX\n#error ABSL_INTERNAL_HAVE_FUTEX may not be set on the command line\n#elif defined(__BIONIC__)\n// Bionic supports all the futex operations we need even when some of the futex\n// definitions are missing.\n#define ABSL_INTERNAL_HAVE_FUTEX\n#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)\n// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.\n#define ABSL_INTERNAL_HAVE_FUTEX\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_FUTEX\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// Some Android headers are missing these definitions even though they\n// support these futex operations.\n#ifdef __BIONIC__\n#ifndef SYS_futex\n#define SYS_futex __NR_futex\n#endif\n#ifndef FUTEX_WAIT_BITSET\n#define FUTEX_WAIT_BITSET 9\n#endif\n#ifndef FUTEX_PRIVATE_FLAG\n#define FUTEX_PRIVATE_FLAG 128\n#endif\n#ifndef FUTEX_CLOCK_REALTIME\n#define FUTEX_CLOCK_REALTIME 256\n#endif\n#ifndef FUTEX_BITSET_MATCH_ANY\n#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF\n#endif\n#endif\n\n#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)\n#define SYS_futex_time64 __NR_futex_time64\n#endif\n\n#if defined(SYS_futex_time64) && !defined(SYS_futex)\n#define SYS_futex SYS_futex_time64\nusing FutexTimespec = struct timespec;\n#else\n// Some libc implementations have switched to an unconditional 64-bit `time_t`\n// definition. This means that `struct timespec` may not match the layout\n// expected by the kernel ABI on 32-bit platforms. So we define the\n// FutexTimespec that matches the kernel timespec definition. It should be safe\n// to use this struct for 64-bit userspace builds too, since it will use another\n// SYS_futex kernel call with 64-bit tv_sec inside timespec.\nstruct FutexTimespec {\n  long tv_sec;   // NOLINT\n  long tv_nsec;  // NOLINT\n};\n#endif\n\nclass FutexImpl {\n public:\n  // Atomically check that `*v == val`, and if it is, then sleep until the until\n  // woken by `Wake()`.\n  static int Wait(std::atomic<int32_t>* v, int32_t val) {\n    return WaitAbsoluteTimeout(v, val, nullptr);\n  }\n\n  // Atomically check that `*v == val`, and if it is, then sleep until\n  // CLOCK_REALTIME reaches `*abs_timeout`, or until woken by `Wake()`.\n  static int WaitAbsoluteTimeout(std::atomic<int32_t>* v, int32_t val,\n                                 const struct timespec* abs_timeout) {\n    FutexTimespec ts;\n    // https://locklessinc.com/articles/futex_cheat_sheet/\n    // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.\n    auto err = syscall(\n        SYS_futex, reinterpret_cast<int32_t*>(v),\n        FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,\n        ToFutexTimespec(abs_timeout, &ts), nullptr, FUTEX_BITSET_MATCH_ANY);\n    if (err != 0) {\n      return -errno;\n    }\n    return 0;\n  }\n\n  // Atomically check that `*v == val`, and if it is, then sleep until\n  // `*rel_timeout` has elapsed, or until woken by `Wake()`.\n  static int WaitRelativeTimeout(std::atomic<int32_t>* v, int32_t val,\n                                 const struct timespec* rel_timeout) {\n    FutexTimespec ts;\n    // Atomically check that the futex value is still 0, and if it\n    // is, sleep until abs_timeout or until woken by FUTEX_WAKE.\n    auto err =\n        syscall(SYS_futex, reinterpret_cast<int32_t*>(v), FUTEX_PRIVATE_FLAG,\n                val, ToFutexTimespec(rel_timeout, &ts));\n    if (err != 0) {\n      return -errno;\n    }\n    return 0;\n  }\n\n  // Wakes at most `count` waiters that have entered the sleep state on `v`.\n  static int Wake(std::atomic<int32_t>* v, int32_t count) {\n    auto err = syscall(SYS_futex, reinterpret_cast<int32_t*>(v),\n                       FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);\n    if (ABSL_PREDICT_FALSE(err < 0)) {\n      return -errno;\n    }\n    return 0;\n  }\n\n private:\n  static FutexTimespec* ToFutexTimespec(const struct timespec* userspace_ts,\n                                        FutexTimespec* futex_ts) {\n    if (userspace_ts == nullptr) {\n      return nullptr;\n    }\n\n    using FutexSeconds = decltype(futex_ts->tv_sec);\n    using FutexNanoseconds = decltype(futex_ts->tv_nsec);\n\n    constexpr auto kMaxSeconds{(std::numeric_limits<FutexSeconds>::max)()};\n    if (userspace_ts->tv_sec > kMaxSeconds) {\n      futex_ts->tv_sec = kMaxSeconds;\n    } else {\n      futex_ts->tv_sec = static_cast<FutexSeconds>(userspace_ts->tv_sec);\n    }\n    futex_ts->tv_nsec = static_cast<FutexNanoseconds>(userspace_ts->tv_nsec);\n    return futex_ts;\n  }\n};\n\nclass Futex : public FutexImpl {};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_FUTEX\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_\n"
  },
  {
    "path": "absl/synchronization/internal/futex_waiter.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/futex_waiter.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_FUTEX_WAITER\n\n#include <atomic>\n#include <cstdint>\n#include <cerrno>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/futex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nint FutexWaiter::WaitUntil(std::atomic<int32_t>* v, int32_t val,\n                           KernelTimeout t) {\n#ifdef CLOCK_MONOTONIC\n  constexpr bool kHasClockMonotonic = true;\n#else\n  constexpr bool kHasClockMonotonic = false;\n#endif\n\n  // We can't call Futex::WaitUntil() here because the prodkernel implementation\n  // does not know about KernelTimeout::SupportsSteadyClock().\n  if (!t.has_timeout()) {\n    return Futex::Wait(v, val);\n  } else if (kHasClockMonotonic && KernelTimeout::SupportsSteadyClock() &&\n             t.is_relative_timeout()) {\n    auto rel_timespec = t.MakeRelativeTimespec();\n    return Futex::WaitRelativeTimeout(v, val, &rel_timespec);\n  } else {\n    auto abs_timespec = t.MakeAbsTimespec();\n    return Futex::WaitAbsoluteTimeout(v, val, &abs_timespec);\n  }\n}\n\nbool FutexWaiter::Wait(KernelTimeout t) {\n  // Loop until we can atomically decrement futex from a positive\n  // value, waiting on a futex while we believe it is zero.\n  // Note that, since the thread ticker is just reset, we don't need to check\n  // whether the thread is idle on the very first pass of the loop.\n  bool first_pass = true;\n  while (true) {\n    int32_t x = futex_.load(std::memory_order_relaxed);\n    while (x != 0) {\n      if (!futex_.compare_exchange_weak(x, x - 1,\n                                        std::memory_order_acquire,\n                                        std::memory_order_relaxed)) {\n        continue;  // Raced with someone, retry.\n      }\n      return true;  // Consumed a wakeup, we are done.\n    }\n\n    if (!first_pass) MaybeBecomeIdle();\n    const int err = WaitUntil(&futex_, 0, t);\n    if (err != 0) {\n      if (err == -EINTR || err == -EWOULDBLOCK) {\n        // Do nothing, the loop will retry.\n      } else if (err == -ETIMEDOUT) {\n        return false;\n      } else {\n        ABSL_RAW_LOG(FATAL, \"Futex operation failed with error %d\\n\", err);\n      }\n    }\n    first_pass = false;\n  }\n}\n\nvoid FutexWaiter::Post() {\n  if (futex_.fetch_add(1, std::memory_order_release) == 0) {\n    // We incremented from 0, need to wake a potential waiter.\n    Poke();\n  }\n}\n\nvoid FutexWaiter::Poke() {\n  // Wake one thread waiting on the futex.\n  const int err = Futex::Wake(&futex_, 1);\n  if (ABSL_PREDICT_FALSE(err < 0)) {\n    ABSL_RAW_LOG(FATAL, \"Futex operation failed with error %d\\n\", err);\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_FUTEX_WAITER\n"
  },
  {
    "path": "absl/synchronization/internal/futex_waiter.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_WAITER_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_WAITER_H_\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/futex.h\"\n#include \"absl/synchronization/internal/waiter_base.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_FUTEX\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n#define ABSL_INTERNAL_HAVE_FUTEX_WAITER 1\n\nclass FutexWaiter : public WaiterCrtp<FutexWaiter> {\n public:\n  FutexWaiter() : futex_(0) {}\n\n  bool Wait(KernelTimeout t);\n  void Post();\n  void Poke();\n\n  static constexpr char kName[] = \"FutexWaiter\";\n\n private:\n  // Atomically check that `*v == val`, and if it is, then sleep until the\n  // timeout `t` has been reached, or until woken by `Wake()`.\n  static int WaitUntil(std::atomic<int32_t>* v, int32_t val,\n                       KernelTimeout t);\n\n  // Futexes are defined by specification to be 32-bits.\n  // Thus std::atomic<int32_t> must be just an int32_t with lockfree methods.\n  std::atomic<int32_t> futex_;\n  static_assert(sizeof(int32_t) == sizeof(futex_), \"Wrong size for futex\");\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_FUTEX\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_WAITER_H_\n"
  },
  {
    "path": "absl/synchronization/internal/graphcycles.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// GraphCycles provides incremental cycle detection on a dynamic\n// graph using the following algorithm:\n//\n// A dynamic topological sort algorithm for directed acyclic graphs\n// David J. Pearce, Paul H. J. Kelly\n// Journal of Experimental Algorithmics (JEA) JEA Homepage archive\n// Volume 11, 2006, Article No. 1.7\n//\n// Brief summary of the algorithm:\n//\n// (1) Maintain a rank for each node that is consistent\n//     with the topological sort of the graph. I.e., path from x to y\n//     implies rank[x] < rank[y].\n// (2) When a new edge (x->y) is inserted, do nothing if rank[x] < rank[y].\n// (3) Otherwise: adjust ranks in the neighborhood of x and y.\n\n#include \"absl/base/attributes.h\"\n// This file is a no-op if the required LowLevelAlloc support is missing.\n#include \"absl/base/internal/low_level_alloc.h\"\n#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING\n\n#include <algorithm>\n#include <array>\n#include <cinttypes>\n#include <limits>\n\n#include \"absl/base/internal/hide_ptr.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/synchronization/internal/graphcycles.h\"\n\n// Do not use STL.   This module does not use standard memory allocation.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nnamespace {\n\n// Avoid LowLevelAlloc's default arena since it calls malloc hooks in\n// which people are doing things like acquiring Mutexes.\nABSL_CONST_INIT static absl::base_internal::SpinLock arena_mu(\n    base_internal::SCHEDULE_KERNEL_ONLY);\nABSL_CONST_INIT static base_internal::LowLevelAlloc::Arena* arena;\n\nstatic void InitArenaIfNecessary() {\n  base_internal::SpinLockHolder l(arena_mu);\n  if (arena == nullptr) {\n    arena = base_internal::LowLevelAlloc::NewArena(0);\n  }\n}\n\n// Number of inlined elements in Vec.  Hash table implementation\n// relies on this being a power of two.\nstatic const uint32_t kInline = 8;\n\n// A simple LowLevelAlloc based resizable vector with inlined storage\n// for a few elements.  T must be a plain type since constructor\n// and destructor are not run on elements of type T managed by Vec.\ntemplate <typename T>\nclass Vec {\n public:\n  Vec() { Init(); }\n  ~Vec() { Discard(); }\n\n  void clear() {\n    Discard();\n    Init();\n  }\n\n  bool empty() const { return size_ == 0; }\n  uint32_t size() const { return size_; }\n  T* begin() { return ptr_; }\n  T* end() { return ptr_ + size_; }\n  const T& operator[](uint32_t i) const { return ptr_[i]; }\n  T& operator[](uint32_t i) { return ptr_[i]; }\n  const T& back() const { return ptr_[size_ - 1]; }\n  void pop_back() { size_--; }\n\n  void push_back(const T& v) {\n    if (size_ == capacity_) Grow(size_ + 1);\n    ptr_[size_] = v;\n    size_++;\n  }\n\n  void resize(uint32_t n) {\n    if (n > capacity_) Grow(n);\n    size_ = n;\n  }\n\n  void fill(const T& val) {\n    for (uint32_t i = 0; i < size(); i++) {\n      ptr_[i] = val;\n    }\n  }\n\n  // Guarantees src is empty at end.\n  // Provided for the hash table resizing code below.\n  void MoveFrom(Vec<T>* src) {\n    if (src->ptr_ == src->space_) {\n      // Need to actually copy\n      resize(src->size_);\n      std::copy_n(src->ptr_, src->size_, ptr_);\n      src->size_ = 0;\n    } else {\n      Discard();\n      ptr_ = src->ptr_;\n      size_ = src->size_;\n      capacity_ = src->capacity_;\n      src->Init();\n    }\n  }\n\n private:\n  T* ptr_;\n  T space_[kInline];\n  uint32_t size_;\n  uint32_t capacity_;\n\n  void Init() {\n    ptr_ = space_;\n    size_ = 0;\n    capacity_ = kInline;\n  }\n\n  void Discard() {\n    if (ptr_ != space_) base_internal::LowLevelAlloc::Free(ptr_);\n  }\n\n  void Grow(uint32_t n) {\n    while (capacity_ < n) {\n      capacity_ *= 2;\n    }\n    size_t request = static_cast<size_t>(capacity_) * sizeof(T);\n    T* copy = static_cast<T*>(\n        base_internal::LowLevelAlloc::AllocWithArena(request, arena));\n    std::copy_n(ptr_, size_, copy);\n    Discard();\n    ptr_ = copy;\n  }\n\n  Vec(const Vec&) = delete;\n  Vec& operator=(const Vec&) = delete;\n};\n\n// A hash set of non-negative int32_t that uses Vec for its underlying storage.\nclass NodeSet {\n public:\n  NodeSet() { Init(); }\n\n  void clear() { Init(); }\n  bool contains(int32_t v) const { return table_[FindIndex(v)] == v; }\n\n  bool insert(int32_t v) {\n    uint32_t i = FindIndex(v);\n    if (table_[i] == v) {\n      return false;\n    }\n    if (table_[i] == kEmpty) {\n      // Only inserting over an empty cell increases the number of occupied\n      // slots.\n      occupied_++;\n    }\n    table_[i] = v;\n    // Double when 75% full.\n    if (occupied_ >= table_.size() - table_.size() / 4) Grow();\n    return true;\n  }\n\n  void erase(int32_t v) {\n    uint32_t i = FindIndex(v);\n    if (table_[i] == v) {\n      table_[i] = kDel;\n    }\n  }\n\n  // Iteration: is done via HASH_FOR_EACH\n  // Example:\n  //    HASH_FOR_EACH(elem, node->out) { ... }\n#define HASH_FOR_EACH(elem, eset) \\\n  for (int32_t elem, _cursor = 0; (eset).Next(&_cursor, &elem);)\n  bool Next(int32_t* cursor, int32_t* elem) {\n    while (static_cast<uint32_t>(*cursor) < table_.size()) {\n      int32_t v = table_[static_cast<uint32_t>(*cursor)];\n      (*cursor)++;\n      if (v >= 0) {\n        *elem = v;\n        return true;\n      }\n    }\n    return false;\n  }\n\n private:\n  enum : int32_t { kEmpty = -1, kDel = -2 };\n  Vec<int32_t> table_;\n  uint32_t occupied_;  // Count of non-empty slots (includes deleted slots)\n\n  static uint32_t Hash(int32_t a) { return static_cast<uint32_t>(a) * 41; }\n\n  // Return index for storing v.  May return an empty index or deleted index\n  uint32_t FindIndex(int32_t v) const {\n    // Search starting at hash index.\n    const uint32_t mask = table_.size() - 1;\n    uint32_t i = Hash(v) & mask;\n    uint32_t deleted_index = 0;  // index of first deleted element we see\n    bool seen_deleted_element = false;\n    while (true) {\n      int32_t e = table_[i];\n      if (v == e) {\n        return i;\n      } else if (e == kEmpty) {\n        // Return any previously encountered deleted slot.\n        return seen_deleted_element ? deleted_index : i;\n      } else if (e == kDel && !seen_deleted_element) {\n        // Keep searching since v might be present later.\n        deleted_index = i;\n        seen_deleted_element = true;\n      }\n      i = (i + 1) & mask;  // Linear probing; quadratic is slightly slower.\n    }\n  }\n\n  void Init() {\n    table_.clear();\n    table_.resize(kInline);\n    table_.fill(kEmpty);\n    occupied_ = 0;\n  }\n\n  void Grow() {\n    Vec<int32_t> copy;\n    copy.MoveFrom(&table_);\n    occupied_ = 0;\n    table_.resize(copy.size() * 2);\n    table_.fill(kEmpty);\n\n    for (const auto& e : copy) {\n      if (e >= 0) insert(e);\n    }\n  }\n\n  NodeSet(const NodeSet&) = delete;\n  NodeSet& operator=(const NodeSet&) = delete;\n};\n\n// We encode a node index and a node version in GraphId.  The version\n// number is incremented when the GraphId is freed which automatically\n// invalidates all copies of the GraphId.\n\ninline GraphId MakeId(int32_t index, uint32_t version) {\n  GraphId g;\n  g.handle =\n      (static_cast<uint64_t>(version) << 32) | static_cast<uint32_t>(index);\n  return g;\n}\n\ninline int32_t NodeIndex(GraphId id) { return static_cast<int32_t>(id.handle); }\n\ninline uint32_t NodeVersion(GraphId id) {\n  return static_cast<uint32_t>(id.handle >> 32);\n}\n\nstruct Node {\n  int32_t rank;          // rank number assigned by Pearce-Kelly algorithm\n  uint32_t version;      // Current version number\n  int32_t next_hash;     // Next entry in hash table\n  bool visited;          // Temporary marker used by depth-first-search\n  uintptr_t masked_ptr;  // User-supplied pointer\n  NodeSet in;            // List of immediate predecessor nodes in graph\n  NodeSet out;           // List of immediate successor nodes in graph\n  int priority;          // Priority of recorded stack trace.\n  int nstack;            // Depth of recorded stack trace.\n  void* stack[40];       // stack[0,nstack-1] holds stack trace for node.\n};\n\n// Hash table for pointer to node index lookups.\nclass PointerMap {\n public:\n  explicit PointerMap(const Vec<Node*>* nodes) : nodes_(nodes) {\n    table_.fill(-1);\n  }\n\n  int32_t Find(void* ptr) {\n    auto masked = base_internal::HidePtr(ptr);\n    for (int32_t i = table_[Hash(ptr)]; i != -1;) {\n      Node* n = (*nodes_)[static_cast<uint32_t>(i)];\n      if (n->masked_ptr == masked) return i;\n      i = n->next_hash;\n    }\n    return -1;\n  }\n\n  void Add(void* ptr, int32_t i) {\n    int32_t* head = &table_[Hash(ptr)];\n    (*nodes_)[static_cast<uint32_t>(i)]->next_hash = *head;\n    *head = i;\n  }\n\n  int32_t Remove(void* ptr) {\n    // Advance through linked list while keeping track of the\n    // predecessor slot that points to the current entry.\n    auto masked = base_internal::HidePtr(ptr);\n    for (int32_t* slot = &table_[Hash(ptr)]; *slot != -1;) {\n      int32_t index = *slot;\n      Node* n = (*nodes_)[static_cast<uint32_t>(index)];\n      if (n->masked_ptr == masked) {\n        *slot = n->next_hash;  // Remove n from linked list\n        n->next_hash = -1;\n        return index;\n      }\n      slot = &n->next_hash;\n    }\n    return -1;\n  }\n\n private:\n  // Number of buckets in hash table for pointer lookups.\n  static constexpr uint32_t kHashTableSize = 262139;  // should be prime\n\n  const Vec<Node*>* nodes_;\n  std::array<int32_t, kHashTableSize> table_;\n\n  static uint32_t Hash(void* ptr) {\n    return reinterpret_cast<uintptr_t>(ptr) % kHashTableSize;\n  }\n};\n\n}  // namespace\n\nstruct GraphCycles::Rep {\n  Vec<Node*> nodes_;\n  Vec<int32_t> free_nodes_;  // Indices for unused entries in nodes_\n  PointerMap ptrmap_;\n\n  // Temporary state.\n  Vec<int32_t> deltaf_;  // Results of forward DFS\n  Vec<int32_t> deltab_;  // Results of backward DFS\n  Vec<int32_t> list_;    // All nodes to reprocess\n  Vec<int32_t> merged_;  // Rank values to assign to list_ entries\n  Vec<int32_t> stack_;   // Emulates recursion stack for depth-first searches\n\n  Rep() : ptrmap_(&nodes_) {}\n};\n\nstatic Node* FindNode(GraphCycles::Rep* rep, GraphId id) {\n  Node* n = rep->nodes_[static_cast<uint32_t>(NodeIndex(id))];\n  return (n->version == NodeVersion(id)) ? n : nullptr;\n}\n\nvoid GraphCycles::TestOnlyAddNodes(uint32_t n) {\n  uint32_t old_size = rep_->nodes_.size();\n  rep_->nodes_.resize(n);\n  for (auto i = old_size; i < n; ++i) {\n    rep_->nodes_[i] = nullptr;\n  }\n}\n\nGraphCycles::GraphCycles() {\n  InitArenaIfNecessary();\n  rep_ = new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Rep), arena))\n      Rep;\n}\n\nGraphCycles::~GraphCycles() {\n  for (auto* node : rep_->nodes_) {\n    if (node == nullptr) {\n      continue;\n    }\n    node->Node::~Node();\n    base_internal::LowLevelAlloc::Free(node);\n  }\n  rep_->Rep::~Rep();\n  base_internal::LowLevelAlloc::Free(rep_);\n}\n\nbool GraphCycles::CheckInvariants() const {\n  Rep* r = rep_;\n  NodeSet ranks;  // Set of ranks seen so far.\n  for (uint32_t x = 0; x < r->nodes_.size(); x++) {\n    Node* nx = r->nodes_[x];\n    void* ptr = base_internal::UnhidePtr<void>(nx->masked_ptr);\n    if (ptr != nullptr && static_cast<uint32_t>(r->ptrmap_.Find(ptr)) != x) {\n      ABSL_RAW_LOG(FATAL, \"Did not find live node in hash table %\" PRIu32 \" %p\",\n                   x, ptr);\n    }\n    if (nx->visited) {\n      ABSL_RAW_LOG(FATAL, \"Did not clear visited marker on node %\" PRIu32, x);\n    }\n    if (!ranks.insert(nx->rank)) {\n      ABSL_RAW_LOG(FATAL, \"Duplicate occurrence of rank %\" PRId32, nx->rank);\n    }\n    HASH_FOR_EACH(y, nx->out) {\n      Node* ny = r->nodes_[static_cast<uint32_t>(y)];\n      if (nx->rank >= ny->rank) {\n        ABSL_RAW_LOG(FATAL,\n                     \"Edge %\" PRIu32 \" ->%\" PRId32\n                     \" has bad rank assignment %\" PRId32 \"->%\" PRId32,\n                     x, y, nx->rank, ny->rank);\n      }\n    }\n  }\n  return true;\n}\n\nGraphId GraphCycles::GetId(void* ptr) {\n  int32_t i = rep_->ptrmap_.Find(ptr);\n  if (i != -1) {\n    return MakeId(i, rep_->nodes_[static_cast<uint32_t>(i)]->version);\n  } else if (rep_->free_nodes_.empty()) {\n    Node* n =\n        new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Node), arena))\n            Node;\n    n->version = 1;  // Avoid 0 since it is used by InvalidGraphId()\n    n->visited = false;\n    n->rank = static_cast<int32_t>(rep_->nodes_.size());\n    n->masked_ptr = base_internal::HidePtr(ptr);\n    n->nstack = 0;\n    n->priority = 0;\n    rep_->nodes_.push_back(n);\n    rep_->ptrmap_.Add(ptr, n->rank);\n    return MakeId(n->rank, n->version);\n  } else {\n    // Preserve preceding rank since the set of ranks in use must be\n    // a permutation of [0,rep_->nodes_.size()-1].\n    int32_t r = rep_->free_nodes_.back();\n    rep_->free_nodes_.pop_back();\n    Node* n = rep_->nodes_[static_cast<uint32_t>(r)];\n    n->masked_ptr = base_internal::HidePtr(ptr);\n    n->nstack = 0;\n    n->priority = 0;\n    rep_->ptrmap_.Add(ptr, r);\n    return MakeId(r, n->version);\n  }\n}\n\nvoid GraphCycles::RemoveNode(void* ptr) {\n  int32_t i = rep_->ptrmap_.Remove(ptr);\n  if (i == -1) {\n    return;\n  }\n  Node* x = rep_->nodes_[static_cast<uint32_t>(i)];\n  HASH_FOR_EACH(y, x->out) {\n    rep_->nodes_[static_cast<uint32_t>(y)]->in.erase(i);\n  }\n  HASH_FOR_EACH(y, x->in) {\n    rep_->nodes_[static_cast<uint32_t>(y)]->out.erase(i);\n  }\n  x->in.clear();\n  x->out.clear();\n  x->masked_ptr = base_internal::HidePtr<void>(nullptr);\n  if (x->version == std::numeric_limits<uint32_t>::max()) {\n    // Cannot use x any more\n  } else {\n    x->version++;  // Invalidates all copies of node.\n    rep_->free_nodes_.push_back(i);\n  }\n}\n\nvoid* GraphCycles::Ptr(GraphId id) {\n  Node* n = FindNode(rep_, id);\n  return n == nullptr ? nullptr : base_internal::UnhidePtr<void>(n->masked_ptr);\n}\n\nbool GraphCycles::HasNode(GraphId node) {\n  return FindNode(rep_, node) != nullptr;\n}\n\nbool GraphCycles::HasEdge(GraphId x, GraphId y) const {\n  Node* xn = FindNode(rep_, x);\n  return xn && FindNode(rep_, y) && xn->out.contains(NodeIndex(y));\n}\n\nvoid GraphCycles::RemoveEdge(GraphId x, GraphId y) {\n  Node* xn = FindNode(rep_, x);\n  Node* yn = FindNode(rep_, y);\n  if (xn && yn) {\n    xn->out.erase(NodeIndex(y));\n    yn->in.erase(NodeIndex(x));\n    // No need to update the rank assignment since a previous valid\n    // rank assignment remains valid after an edge deletion.\n  }\n}\n\nstatic bool ForwardDFS(GraphCycles::Rep* r, int32_t n, int32_t upper_bound);\nstatic void BackwardDFS(GraphCycles::Rep* r, int32_t n, int32_t lower_bound);\nstatic void Reorder(GraphCycles::Rep* r);\nstatic void Sort(const Vec<Node*>&, Vec<int32_t>* delta);\nstatic void MoveToList(GraphCycles::Rep* r, Vec<int32_t>* src,\n                       Vec<int32_t>* dst);\n\nbool GraphCycles::InsertEdge(GraphId idx, GraphId idy) {\n  Rep* r = rep_;\n  const int32_t x = NodeIndex(idx);\n  const int32_t y = NodeIndex(idy);\n  Node* nx = FindNode(r, idx);\n  Node* ny = FindNode(r, idy);\n  if (nx == nullptr || ny == nullptr) return true;  // Expired ids\n\n  if (nx == ny) return false;  // Self edge\n  if (!nx->out.insert(y)) {\n    // Edge already exists.\n    return true;\n  }\n\n  ny->in.insert(x);\n\n  if (nx->rank <= ny->rank) {\n    // New edge is consistent with existing rank assignment.\n    return true;\n  }\n\n  // Current rank assignments are incompatible with the new edge.  Recompute.\n  // We only need to consider nodes that fall in the range [ny->rank,nx->rank].\n  if (!ForwardDFS(r, y, nx->rank)) {\n    // Found a cycle.  Undo the insertion and tell caller.\n    nx->out.erase(y);\n    ny->in.erase(x);\n    // Since we do not call Reorder() on this path, clear any visited\n    // markers left by ForwardDFS.\n    for (const auto& d : r->deltaf_) {\n      r->nodes_[static_cast<uint32_t>(d)]->visited = false;\n    }\n    return false;\n  }\n  BackwardDFS(r, x, ny->rank);\n  Reorder(r);\n  return true;\n}\n\nstatic bool ForwardDFS(GraphCycles::Rep* r, int32_t n, int32_t upper_bound) {\n  // Avoid recursion since stack space might be limited.\n  // We instead keep a stack of nodes to visit.\n  r->deltaf_.clear();\n  r->stack_.clear();\n  r->stack_.push_back(n);\n  while (!r->stack_.empty()) {\n    n = r->stack_.back();\n    r->stack_.pop_back();\n    Node* nn = r->nodes_[static_cast<uint32_t>(n)];\n    if (nn->visited) continue;\n\n    nn->visited = true;\n    r->deltaf_.push_back(n);\n\n    HASH_FOR_EACH(w, nn->out) {\n      Node* nw = r->nodes_[static_cast<uint32_t>(w)];\n      if (nw->rank == upper_bound) {\n        return false;  // Cycle\n      }\n      if (!nw->visited && nw->rank < upper_bound) {\n        r->stack_.push_back(w);\n      }\n    }\n  }\n  return true;\n}\n\nstatic void BackwardDFS(GraphCycles::Rep* r, int32_t n, int32_t lower_bound) {\n  r->deltab_.clear();\n  r->stack_.clear();\n  r->stack_.push_back(n);\n  while (!r->stack_.empty()) {\n    n = r->stack_.back();\n    r->stack_.pop_back();\n    Node* nn = r->nodes_[static_cast<uint32_t>(n)];\n    if (nn->visited) continue;\n\n    nn->visited = true;\n    r->deltab_.push_back(n);\n\n    HASH_FOR_EACH(w, nn->in) {\n      Node* nw = r->nodes_[static_cast<uint32_t>(w)];\n      if (!nw->visited && lower_bound < nw->rank) {\n        r->stack_.push_back(w);\n      }\n    }\n  }\n}\n\nstatic void Reorder(GraphCycles::Rep* r) {\n  Sort(r->nodes_, &r->deltab_);\n  Sort(r->nodes_, &r->deltaf_);\n\n  // Adds contents of delta lists to list_ (backwards deltas first).\n  r->list_.clear();\n  MoveToList(r, &r->deltab_, &r->list_);\n  MoveToList(r, &r->deltaf_, &r->list_);\n\n  // Produce sorted list of all ranks that will be reassigned.\n  r->merged_.resize(r->deltab_.size() + r->deltaf_.size());\n  std::merge(r->deltab_.begin(), r->deltab_.end(), r->deltaf_.begin(),\n             r->deltaf_.end(), r->merged_.begin());\n\n  // Assign the ranks in order to the collected list.\n  for (uint32_t i = 0; i < r->list_.size(); i++) {\n    r->nodes_[static_cast<uint32_t>(r->list_[i])]->rank = r->merged_[i];\n  }\n}\n\nstatic void Sort(const Vec<Node*>& nodes, Vec<int32_t>* delta) {\n  struct ByRank {\n    const Vec<Node*>* nodes;\n    bool operator()(int32_t a, int32_t b) const {\n      return (*nodes)[static_cast<uint32_t>(a)]->rank <\n             (*nodes)[static_cast<uint32_t>(b)]->rank;\n    }\n  };\n  ByRank cmp;\n  cmp.nodes = &nodes;\n  std::sort(delta->begin(), delta->end(), cmp);\n}\n\nstatic void MoveToList(GraphCycles::Rep* r, Vec<int32_t>* src,\n                       Vec<int32_t>* dst) {\n  for (auto& v : *src) {\n    int32_t w = v;\n    // Replace v entry with its rank\n    v = r->nodes_[static_cast<uint32_t>(w)]->rank;\n    // Prepare for future DFS calls\n    r->nodes_[static_cast<uint32_t>(w)]->visited = false;\n    dst->push_back(w);\n  }\n}\n\nint GraphCycles::FindPath(GraphId idx, GraphId idy, int max_path_len,\n                          GraphId path[]) const {\n  Rep* r = rep_;\n  if (FindNode(r, idx) == nullptr || FindNode(r, idy) == nullptr) return 0;\n  const int32_t x = NodeIndex(idx);\n  const int32_t y = NodeIndex(idy);\n\n  // Forward depth first search starting at x until we hit y.\n  // As we descend into a node, we push it onto the path.\n  // As we leave a node, we remove it from the path.\n  int path_len = 0;\n\n  NodeSet seen;\n  r->stack_.clear();\n  r->stack_.push_back(x);\n  while (!r->stack_.empty()) {\n    int32_t n = r->stack_.back();\n    r->stack_.pop_back();\n    if (n < 0) {\n      // Marker to indicate that we are leaving a node\n      path_len--;\n      continue;\n    }\n\n    if (path_len < max_path_len) {\n      path[path_len] =\n          MakeId(n, rep_->nodes_[static_cast<uint32_t>(n)]->version);\n    }\n    path_len++;\n    r->stack_.push_back(-1);  // Will remove tentative path entry\n\n    if (n == y) {\n      return path_len;\n    }\n\n    HASH_FOR_EACH(w, r->nodes_[static_cast<uint32_t>(n)]->out) {\n      if (seen.insert(w)) {\n        r->stack_.push_back(w);\n      }\n    }\n  }\n\n  return 0;\n}\n\nbool GraphCycles::IsReachable(GraphId x, GraphId y) const {\n  return FindPath(x, y, 0, nullptr) > 0;\n}\n\nvoid GraphCycles::UpdateStackTrace(GraphId id, int priority,\n                                   int (*get_stack_trace)(void** stack, int)) {\n  Node* n = FindNode(rep_, id);\n  if (n == nullptr || n->priority >= priority) {\n    return;\n  }\n  n->nstack = (*get_stack_trace)(n->stack, ABSL_ARRAYSIZE(n->stack));\n  n->priority = priority;\n}\n\nint GraphCycles::GetStackTrace(GraphId id, void*** ptr) {\n  Node* n = FindNode(rep_, id);\n  if (n == nullptr) {\n    *ptr = nullptr;\n    return 0;\n  } else {\n    *ptr = n->stack;\n    return n->nstack;\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_LOW_LEVEL_ALLOC_MISSING\n"
  },
  {
    "path": "absl/synchronization/internal/graphcycles.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_\n\n// GraphCycles detects the introduction of a cycle into a directed\n// graph that is being built up incrementally.\n//\n// Nodes are identified by small integers.  It is not possible to\n// record multiple edges with the same (source, destination) pair;\n// requests to add an edge where one already exists are silently\n// ignored.\n//\n// It is also not possible to introduce a cycle; an attempt to insert\n// an edge that would introduce a cycle fails and returns false.\n//\n// GraphCycles uses no internal locking; calls into it should be\n// serialized externally.\n\n// Performance considerations:\n//   Works well on sparse graphs, poorly on dense graphs.\n//   Extra information is maintained incrementally to detect cycles quickly.\n//   InsertEdge() is very fast when the edge already exists, and reasonably fast\n//   otherwise.\n//   FindPath() is linear in the size of the graph.\n// The current implementation uses O(|V|+|E|) space.\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// Opaque identifier for a graph node.\nstruct GraphId {\n  uint64_t handle;\n\n  bool operator==(const GraphId& x) const { return handle == x.handle; }\n  bool operator!=(const GraphId& x) const { return handle != x.handle; }\n};\n\n// Return an invalid graph id that will never be assigned by GraphCycles.\ninline GraphId InvalidGraphId() {\n  return GraphId{0};\n}\n\nclass GraphCycles {\n public:\n  GraphCycles();\n  ~GraphCycles();\n\n  // Return the id to use for ptr, assigning one if necessary.\n  // Subsequent calls with the same ptr value will return the same id\n  // until Remove().\n  GraphId GetId(void* ptr);\n\n  // Remove \"ptr\" from the graph.  Its corresponding node and all\n  // edges to and from it are removed.\n  void RemoveNode(void* ptr);\n\n  // Return the pointer associated with id, or nullptr if id is not\n  // currently in the graph.\n  void* Ptr(GraphId id);\n\n  // Attempt to insert an edge from source_node to dest_node.  If the\n  // edge would introduce a cycle, return false without making any\n  // changes. Otherwise add the edge and return true.\n  bool InsertEdge(GraphId source_node, GraphId dest_node);\n\n  // Remove any edge that exists from source_node to dest_node.\n  void RemoveEdge(GraphId source_node, GraphId dest_node);\n\n  // Return whether node exists in the graph.\n  bool HasNode(GraphId node);\n\n  // Return whether there is an edge directly from source_node to dest_node.\n  bool HasEdge(GraphId source_node, GraphId dest_node) const;\n\n  // Return whether dest_node is reachable from source_node\n  // by following edges.\n  bool IsReachable(GraphId source_node, GraphId dest_node) const;\n\n  // Find a path from \"source\" to \"dest\".  If such a path exists,\n  // place the nodes on the path in the array path[], and return\n  // the number of nodes on the path.  If the path is longer than\n  // max_path_len nodes, only the first max_path_len nodes are placed\n  // in path[].  The client should compare the return value with\n  // max_path_len\" to see when this occurs.  If no path exists, return\n  // 0.  Any valid path stored in path[] will start with \"source\" and\n  // end with \"dest\".  There is no guarantee that the path is the\n  // shortest, but no node will appear twice in the path, except the\n  // source and destination node if they are identical; therefore, the\n  // return value is at most one greater than the number of nodes in\n  // the graph.\n  int FindPath(GraphId source, GraphId dest, int max_path_len,\n               GraphId path[]) const;\n\n  // Update the stack trace recorded for id with the current stack\n  // trace if the last time it was updated had a smaller priority\n  // than the priority passed on this call.\n  //\n  // *get_stack_trace is called to get the stack trace.\n  void UpdateStackTrace(GraphId id, int priority,\n                        int (*get_stack_trace)(void**, int));\n\n  // Set *ptr to the beginning of the array that holds the recorded\n  // stack trace for id and return the depth of the stack trace.\n  int GetStackTrace(GraphId id, void*** ptr);\n\n  // Check internal invariants. Crashes on failure, returns true on success.\n  // Expensive: should only be called from graphcycles_test.cc.\n  bool CheckInvariants() const;\n\n  // Test-only method to add more nodes. The nodes will not be valid, and this\n  // method should only be used to test the behavior of the graph when it is\n  // very full.\n  void TestOnlyAddNodes(uint32_t n);\n\n  // ----------------------------------------------------\n  struct Rep;\n private:\n  Rep *rep_;      // opaque representation\n  GraphCycles(const GraphCycles&) = delete;\n  GraphCycles& operator=(const GraphCycles&) = delete;\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif\n"
  },
  {
    "path": "absl/synchronization/internal/graphcycles_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <algorithm>\n#include <cstdint>\n#include <vector>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/synchronization/internal/graphcycles.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_StressTest(benchmark::State& state) {\n  const int num_nodes = state.range(0);\n  while (state.KeepRunningBatch(num_nodes)) {\n    absl::synchronization_internal::GraphCycles g;\n    std::vector<absl::synchronization_internal::GraphId> nodes(num_nodes);\n    for (int i = 0; i < num_nodes; i++) {\n      nodes[i] = g.GetId(reinterpret_cast<void*>(static_cast<uintptr_t>(i)));\n    }\n    for (int i = 0; i < num_nodes; i++) {\n      int end = std::min(num_nodes, i + 5);\n      for (int j = i + 1; j < end; j++) {\n        ABSL_RAW_CHECK(g.InsertEdge(nodes[i], nodes[j]), \"\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_StressTest)->Range(2048, 1048576);\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/internal/graphcycles_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/graphcycles.h\"\n\n#include <climits>\n#include <cstdint>\n#include <map>\n#include <random>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/log.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// We emulate a GraphCycles object with a node vector and an edge vector.\n// We then compare the two implementations.\n\nusing Nodes = std::vector<int>;\nstruct Edge {\n  int from;\n  int to;\n};\nusing Edges = std::vector<Edge>;\nusing RandomEngine = std::mt19937_64;\n\n// Mapping from integer index to GraphId.\ntypedef std::map<int, GraphId> IdMap;\nstatic GraphId Get(const IdMap& id, int num) {\n  auto iter = id.find(num);\n  return (iter == id.end()) ? InvalidGraphId() : iter->second;\n}\n\n// Return whether \"to\" is reachable from \"from\".\nstatic bool IsReachable(Edges *edges, int from, int to,\n                        std::unordered_set<int> *seen) {\n  seen->insert(from);     // we are investigating \"from\"; don't do it again\n  if (from == to) return true;\n  for (const auto &edge : *edges) {\n    if (edge.from == from) {\n      if (edge.to == to) {  // success via edge directly\n        return true;\n      } else if (seen->find(edge.to) == seen->end() &&  // success via edge\n                 IsReachable(edges, edge.to, to, seen)) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nstatic void PrintEdges(Edges *edges) {\n  LOG(INFO) << \"EDGES (\" << edges->size() << \")\";\n  for (const auto &edge : *edges) {\n    int a = edge.from;\n    int b = edge.to;\n    LOG(INFO) << a << \" \" << b;\n  }\n  LOG(INFO) << \"---\";\n}\n\nstatic void PrintGCEdges(Nodes *nodes, const IdMap &id, GraphCycles *gc) {\n  LOG(INFO) << \"GC EDGES\";\n  for (int a : *nodes) {\n    for (int b : *nodes) {\n      if (gc->HasEdge(Get(id, a), Get(id, b))) {\n        LOG(INFO) << a << \" \" << b;\n      }\n    }\n  }\n  LOG(INFO) << \"---\";\n}\n\nstatic void PrintTransitiveClosure(Nodes *nodes, Edges *edges) {\n  LOG(INFO) << \"Transitive closure\";\n  for (int a : *nodes) {\n    for (int b : *nodes) {\n      std::unordered_set<int> seen;\n      if (IsReachable(edges, a, b, &seen)) {\n        LOG(INFO) << a << \" \" << b;\n      }\n    }\n  }\n  LOG(INFO) << \"---\";\n}\n\nstatic void PrintGCTransitiveClosure(Nodes *nodes, const IdMap &id,\n                                     GraphCycles *gc) {\n  LOG(INFO) << \"GC Transitive closure\";\n  for (int a : *nodes) {\n    for (int b : *nodes) {\n      if (gc->IsReachable(Get(id, a), Get(id, b))) {\n        LOG(INFO) << a << \" \" << b;\n      }\n    }\n  }\n  LOG(INFO) << \"---\";\n}\n\nstatic void CheckTransitiveClosure(Nodes *nodes, Edges *edges, const IdMap &id,\n                                   GraphCycles *gc) {\n  std::unordered_set<int> seen;\n  for (const auto &a : *nodes) {\n    for (const auto &b : *nodes) {\n      seen.clear();\n      bool gc_reachable = gc->IsReachable(Get(id, a), Get(id, b));\n      bool reachable = IsReachable(edges, a, b, &seen);\n      if (gc_reachable != reachable) {\n        PrintEdges(edges);\n        PrintGCEdges(nodes, id, gc);\n        PrintTransitiveClosure(nodes, edges);\n        PrintGCTransitiveClosure(nodes, id, gc);\n        LOG(FATAL) << \"gc_reachable \" << gc_reachable << \" reachable \"\n                   << reachable << \" a \" << a << \" b \" << b;\n      }\n    }\n  }\n}\n\nstatic void CheckEdges(Nodes *nodes, Edges *edges, const IdMap &id,\n                       GraphCycles *gc) {\n  int count = 0;\n  for (const auto &edge : *edges) {\n    int a = edge.from;\n    int b = edge.to;\n    if (!gc->HasEdge(Get(id, a), Get(id, b))) {\n      PrintEdges(edges);\n      PrintGCEdges(nodes, id, gc);\n      LOG(FATAL) << \"!gc->HasEdge(\" << a << \", \" << b << \")\";\n    }\n  }\n  for (const auto &a : *nodes) {\n    for (const auto &b : *nodes) {\n      if (gc->HasEdge(Get(id, a), Get(id, b))) {\n        count++;\n      }\n    }\n  }\n  if (count != edges->size()) {\n    PrintEdges(edges);\n    PrintGCEdges(nodes, id, gc);\n    LOG(FATAL) << \"edges->size() \" << edges->size() << \"  count \" << count;\n  }\n}\n\nstatic void CheckInvariants(const GraphCycles &gc) {\n  CHECK(gc.CheckInvariants()) << \"CheckInvariants\";\n}\n\n// Returns the index of a randomly chosen node in *nodes.\n// Requires *nodes be non-empty.\nstatic int RandomNode(RandomEngine* rng, Nodes *nodes) {\n  std::uniform_int_distribution<int> uniform(0, nodes->size()-1);\n  return uniform(*rng);\n}\n\n// Returns the index of a randomly chosen edge in *edges.\n// Requires *edges be non-empty.\nstatic int RandomEdge(RandomEngine* rng, Edges *edges) {\n  std::uniform_int_distribution<int> uniform(0, edges->size()-1);\n  return uniform(*rng);\n}\n\n// Returns the index of edge (from, to) in *edges or -1 if it is not in *edges.\nstatic int EdgeIndex(Edges *edges, int from, int to) {\n  int i = 0;\n  while (i != edges->size() &&\n         ((*edges)[i].from != from || (*edges)[i].to != to)) {\n    i++;\n  }\n  return i == edges->size()? -1 : i;\n}\n\nTEST(GraphCycles, RandomizedTest) {\n  int next_node = 0;\n  Nodes nodes;\n  Edges edges;   // from, to\n  IdMap id;\n  GraphCycles graph_cycles;\n  static const int kMaxNodes = 7;  // use <= 7 nodes to keep test short\n  static const int kDataOffset = 17;  // an offset to the node-specific data\n  int n = 100000;\n  int op = 0;\n  RandomEngine rng(testing::UnitTest::GetInstance()->random_seed());\n  std::uniform_int_distribution<int> uniform(0, 5);\n\n  auto ptr = [](intptr_t i) {\n    return reinterpret_cast<void*>(i + kDataOffset);\n  };\n\n  for (int iter = 0; iter != n; iter++) {\n    for (const auto &node : nodes) {\n      ASSERT_EQ(graph_cycles.Ptr(Get(id, node)), ptr(node)) << \" node \" << node;\n    }\n    CheckEdges(&nodes, &edges, id, &graph_cycles);\n    CheckTransitiveClosure(&nodes, &edges, id, &graph_cycles);\n    op = uniform(rng);\n    switch (op) {\n    case 0:     // Add a node\n      if (nodes.size() < kMaxNodes) {\n        int new_node = next_node++;\n        GraphId new_gnode = graph_cycles.GetId(ptr(new_node));\n        ASSERT_NE(new_gnode, InvalidGraphId());\n        id[new_node] = new_gnode;\n        ASSERT_EQ(ptr(new_node), graph_cycles.Ptr(new_gnode));\n        nodes.push_back(new_node);\n      }\n      break;\n\n    case 1:    // Remove a node\n      if (nodes.size() > 0) {\n        int node_index = RandomNode(&rng, &nodes);\n        int node = nodes[node_index];\n        nodes[node_index] = nodes.back();\n        nodes.pop_back();\n        graph_cycles.RemoveNode(ptr(node));\n        ASSERT_EQ(graph_cycles.Ptr(Get(id, node)), nullptr);\n        id.erase(node);\n        int i = 0;\n        while (i != edges.size()) {\n          if (edges[i].from == node || edges[i].to == node) {\n            edges[i] = edges.back();\n            edges.pop_back();\n          } else {\n            i++;\n          }\n        }\n      }\n      break;\n\n    case 2:   // Add an edge\n      if (nodes.size() > 0) {\n        int from = RandomNode(&rng, &nodes);\n        int to = RandomNode(&rng, &nodes);\n        if (EdgeIndex(&edges, nodes[from], nodes[to]) == -1) {\n          if (graph_cycles.InsertEdge(id[nodes[from]], id[nodes[to]])) {\n            Edge new_edge;\n            new_edge.from = nodes[from];\n            new_edge.to = nodes[to];\n            edges.push_back(new_edge);\n          } else {\n            std::unordered_set<int> seen;\n            ASSERT_TRUE(IsReachable(&edges, nodes[to], nodes[from], &seen))\n                << \"Edge \" << nodes[to] << \"->\" << nodes[from];\n          }\n        }\n      }\n      break;\n\n    case 3:    // Remove an edge\n      if (edges.size() > 0) {\n        int i = RandomEdge(&rng, &edges);\n        int from = edges[i].from;\n        int to = edges[i].to;\n        ASSERT_EQ(i, EdgeIndex(&edges, from, to));\n        edges[i] = edges.back();\n        edges.pop_back();\n        ASSERT_EQ(-1, EdgeIndex(&edges, from, to));\n        graph_cycles.RemoveEdge(id[from], id[to]);\n      }\n      break;\n\n    case 4:   // Check a path\n      if (nodes.size() > 0) {\n        int from = RandomNode(&rng, &nodes);\n        int to = RandomNode(&rng, &nodes);\n        GraphId path[2*kMaxNodes];\n        int path_len = graph_cycles.FindPath(id[nodes[from]], id[nodes[to]],\n                                             ABSL_ARRAYSIZE(path), path);\n        std::unordered_set<int> seen;\n        bool reachable = IsReachable(&edges, nodes[from], nodes[to], &seen);\n        bool gc_reachable =\n            graph_cycles.IsReachable(Get(id, nodes[from]), Get(id, nodes[to]));\n        ASSERT_EQ(path_len != 0, reachable);\n        ASSERT_EQ(path_len != 0, gc_reachable);\n        // In the following line, we add one because a node can appear\n        // twice, if the path is from that node to itself, perhaps via\n        // every other node.\n        ASSERT_LE(path_len, kMaxNodes + 1);\n        if (path_len != 0) {\n          ASSERT_EQ(id[nodes[from]], path[0]);\n          ASSERT_EQ(id[nodes[to]], path[path_len-1]);\n          for (int i = 1; i < path_len; i++) {\n            ASSERT_TRUE(graph_cycles.HasEdge(path[i-1], path[i]));\n          }\n        }\n      }\n      break;\n\n    case 5:  // Check invariants\n      CheckInvariants(graph_cycles);\n      break;\n\n    default:\n      LOG(FATAL) << \"op \" << op;\n    }\n\n    // Very rarely, test graph expansion by adding then removing many nodes.\n    std::bernoulli_distribution one_in_1024(1.0 / 1024);\n    if (one_in_1024(rng)) {\n      CheckEdges(&nodes, &edges, id, &graph_cycles);\n      CheckTransitiveClosure(&nodes, &edges, id, &graph_cycles);\n      for (int i = 0; i != 256; i++) {\n        int new_node = next_node++;\n        GraphId new_gnode = graph_cycles.GetId(ptr(new_node));\n        ASSERT_NE(InvalidGraphId(), new_gnode);\n        id[new_node] = new_gnode;\n        ASSERT_EQ(ptr(new_node), graph_cycles.Ptr(new_gnode));\n        for (const auto &node : nodes) {\n          ASSERT_NE(node, new_node);\n        }\n        nodes.push_back(new_node);\n      }\n      for (int i = 0; i != 256; i++) {\n        ASSERT_GT(nodes.size(), 0);\n        int node_index = RandomNode(&rng, &nodes);\n        int node = nodes[node_index];\n        nodes[node_index] = nodes.back();\n        nodes.pop_back();\n        graph_cycles.RemoveNode(ptr(node));\n        id.erase(node);\n        int j = 0;\n        while (j != edges.size()) {\n          if (edges[j].from == node || edges[j].to == node) {\n            edges[j] = edges.back();\n            edges.pop_back();\n          } else {\n            j++;\n          }\n        }\n      }\n      CheckInvariants(graph_cycles);\n    }\n  }\n}\n\nclass GraphCyclesTest : public ::testing::Test {\n public:\n  IdMap id_;\n  GraphCycles g_;\n\n  static void* Ptr(int i) {\n    return reinterpret_cast<void*>(static_cast<uintptr_t>(i));\n  }\n\n  static int Num(void* ptr) {\n    return static_cast<int>(reinterpret_cast<uintptr_t>(ptr));\n  }\n\n  // Test relies on ith NewNode() call returning Node numbered i\n  GraphCyclesTest() {\n    for (int i = 0; i < 100; i++) {\n      id_[i] = g_.GetId(Ptr(i));\n    }\n    CheckInvariants(g_);\n  }\n\n  bool AddEdge(int x, int y) {\n    return g_.InsertEdge(Get(id_, x), Get(id_, y));\n  }\n\n  void AddMultiples() {\n    // For every node x > 0: add edge to 2*x, 3*x\n    for (int x = 1; x < 25; x++) {\n      EXPECT_TRUE(AddEdge(x, 2*x)) << x;\n      EXPECT_TRUE(AddEdge(x, 3*x)) << x;\n    }\n    CheckInvariants(g_);\n  }\n\n  std::string Path(int x, int y) {\n    GraphId path[5];\n    int np = g_.FindPath(Get(id_, x), Get(id_, y), ABSL_ARRAYSIZE(path), path);\n    std::string result;\n    for (int i = 0; i < np; i++) {\n      if (i >= ABSL_ARRAYSIZE(path)) {\n        result += \" ...\";\n        break;\n      }\n      if (!result.empty()) result.push_back(' ');\n      char buf[20];\n      snprintf(buf, sizeof(buf), \"%d\", Num(g_.Ptr(path[i])));\n      result += buf;\n    }\n    return result;\n  }\n};\n\nTEST_F(GraphCyclesTest, NoCycle) {\n  AddMultiples();\n  CheckInvariants(g_);\n}\n\nTEST_F(GraphCyclesTest, SimpleCycle) {\n  AddMultiples();\n  EXPECT_FALSE(AddEdge(8, 4));\n  EXPECT_EQ(\"4 8\", Path(4, 8));\n  CheckInvariants(g_);\n}\n\nTEST_F(GraphCyclesTest, IndirectCycle) {\n  AddMultiples();\n  EXPECT_TRUE(AddEdge(16, 9));\n  CheckInvariants(g_);\n  EXPECT_FALSE(AddEdge(9, 2));\n  EXPECT_EQ(\"2 4 8 16 9\", Path(2, 9));\n  CheckInvariants(g_);\n}\n\nTEST_F(GraphCyclesTest, LongPath) {\n  ASSERT_TRUE(AddEdge(2, 4));\n  ASSERT_TRUE(AddEdge(4, 6));\n  ASSERT_TRUE(AddEdge(6, 8));\n  ASSERT_TRUE(AddEdge(8, 10));\n  ASSERT_TRUE(AddEdge(10, 12));\n  ASSERT_FALSE(AddEdge(12, 2));\n  EXPECT_EQ(\"2 4 6 8 10 ...\", Path(2, 12));\n  CheckInvariants(g_);\n}\n\nTEST_F(GraphCyclesTest, RemoveNode) {\n  ASSERT_TRUE(AddEdge(1, 2));\n  ASSERT_TRUE(AddEdge(2, 3));\n  ASSERT_TRUE(AddEdge(3, 4));\n  ASSERT_TRUE(AddEdge(4, 5));\n  g_.RemoveNode(g_.Ptr(id_[3]));\n  id_.erase(3);\n  ASSERT_TRUE(AddEdge(5, 1));\n}\n\nTEST_F(GraphCyclesTest, ManyEdges) {\n  const int N = 50;\n  for (int i = 0; i < N; i++) {\n    for (int j = 1; j < N; j++) {\n      ASSERT_TRUE(AddEdge(i, i+j));\n    }\n  }\n  CheckInvariants(g_);\n  ASSERT_TRUE(AddEdge(2*N-1, 0));\n  CheckInvariants(g_);\n  ASSERT_FALSE(AddEdge(10, 9));\n  CheckInvariants(g_);\n}\n\nTEST(GraphCycles, IntegerOverflow) {\n  GraphCycles graph_cycles;\n  uintptr_t buf = 0;\n  GraphId prev_id = graph_cycles.GetId(reinterpret_cast<void*>(buf));\n  buf += 1;\n  GraphId id = graph_cycles.GetId(reinterpret_cast<void*>(buf));\n  ASSERT_TRUE(graph_cycles.InsertEdge(prev_id, id));\n\n  // INT_MAX / 40 is enough to cause an overflow when multiplied by 41.\n  graph_cycles.TestOnlyAddNodes(INT_MAX / 40);\n\n  buf += 1;\n  GraphId newid = graph_cycles.GetId(reinterpret_cast<void*>(buf));\n  graph_cycles.HasEdge(prev_id, newid);\n\n  graph_cycles.RemoveNode(reinterpret_cast<void*>(buf));\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/internal/kernel_timeout.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\n#ifndef _WIN32\n#include <sys/types.h>\n#endif\n\n#include <algorithm>\n#include <chrono>  // NOLINT(build/c++11)\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <ctime>\n#include <limits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nint64_t KernelTimeout::SteadyClockNow() {\n  if (!SupportsSteadyClock()) {\n    return absl::GetCurrentTimeNanos();\n  }\n  return std::chrono::duration_cast<std::chrono::nanoseconds>(\n             std::chrono::steady_clock::now().time_since_epoch())\n      .count();\n}\n\nKernelTimeout::KernelTimeout(absl::Time t) {\n  // `absl::InfiniteFuture()` is a common \"no timeout\" value and cheaper to\n  // compare than convert.\n  if (t == absl::InfiniteFuture()) {\n    rep_ = kNoTimeout;\n    return;\n  }\n\n  int64_t unix_nanos = absl::ToUnixNanos(t);\n\n  // A timeout that lands before the unix epoch is converted to 0.\n  // In theory implementations should expire these timeouts immediately.\n  if (unix_nanos < 0) {\n    unix_nanos = 0;\n  }\n\n  // Values greater than or equal to kMaxNanos are converted to infinite.\n  if (unix_nanos >= kMaxNanos) {\n    rep_ = kNoTimeout;\n    return;\n  }\n\n  rep_ = static_cast<uint64_t>(unix_nanos) << 1;\n}\n\nKernelTimeout::KernelTimeout(absl::Duration d) {\n  // `absl::InfiniteDuration()` is a common \"no timeout\" value and cheaper to\n  // compare than convert.\n  if (d == absl::InfiniteDuration()) {\n    rep_ = kNoTimeout;\n    return;\n  }\n\n  int64_t nanos = absl::ToInt64Nanoseconds(d);\n\n  // Negative durations are normalized to 0.\n  // In theory implementations should expire these timeouts immediately.\n  if (nanos < 0) {\n    nanos = 0;\n  }\n\n  int64_t now = SteadyClockNow();\n  if (nanos > kMaxNanos - now) {\n    // Durations that would be greater than kMaxNanos are converted to infinite.\n    rep_ = kNoTimeout;\n    return;\n  }\n\n  nanos += now;\n  rep_ = (static_cast<uint64_t>(nanos) << 1) | uint64_t{1};\n}\n\nint64_t KernelTimeout::MakeAbsNanos() const {\n  if (!has_timeout()) {\n    return kMaxNanos;\n  }\n\n  int64_t nanos = RawAbsNanos();\n\n  if (is_relative_timeout()) {\n    // We need to change epochs, because the relative timeout might be\n    // represented by an absolute timestamp from another clock.\n    nanos = std::max<int64_t>(nanos - SteadyClockNow(), 0);\n    int64_t now = absl::GetCurrentTimeNanos();\n    if (nanos > kMaxNanos - now) {\n      // Overflow.\n      nanos = kMaxNanos;\n    } else {\n      nanos += now;\n    }\n  } else if (nanos == 0) {\n    // Some callers have assumed that 0 means no timeout, so instead we return a\n    // time of 1 nanosecond after the epoch.\n    nanos = 1;\n  }\n\n  return nanos;\n}\n\nint64_t KernelTimeout::InNanosecondsFromNow() const {\n  if (!has_timeout()) {\n    return kMaxNanos;\n  }\n\n  int64_t nanos = RawAbsNanos();\n  if (is_absolute_timeout()) {\n    return std::max<int64_t>(nanos - absl::GetCurrentTimeNanos(), 0);\n  }\n  return std::max<int64_t>(nanos - SteadyClockNow(), 0);\n}\n\nstruct timespec KernelTimeout::MakeAbsTimespec() const {\n  return absl::ToTimespec(absl::Nanoseconds(MakeAbsNanos()));\n}\n\nstruct timespec KernelTimeout::MakeRelativeTimespec() const {\n  return absl::ToTimespec(absl::Nanoseconds(InNanosecondsFromNow()));\n}\n\n#ifndef _WIN32\nstruct timespec KernelTimeout::MakeClockAbsoluteTimespec(clockid_t c) const {\n  if (!has_timeout()) {\n    return absl::ToTimespec(absl::Nanoseconds(kMaxNanos));\n  }\n\n  int64_t nanos = RawAbsNanos();\n  if (is_absolute_timeout()) {\n    nanos -= absl::GetCurrentTimeNanos();\n  } else {\n    nanos -= SteadyClockNow();\n  }\n\n  struct timespec now;\n  ABSL_RAW_CHECK(clock_gettime(c, &now) == 0, \"clock_gettime() failed\");\n  absl::Duration from_clock_epoch =\n      absl::DurationFromTimespec(now) + absl::Nanoseconds(nanos);\n  if (from_clock_epoch <= absl::ZeroDuration()) {\n    // Some callers have assumed that 0 means no timeout, so instead we return a\n    // time of 1 nanosecond after the epoch. For safety we also do not return\n    // negative values.\n    return absl::ToTimespec(absl::Nanoseconds(1));\n  }\n  return absl::ToTimespec(from_clock_epoch);\n}\n#endif\n\nKernelTimeout::DWord KernelTimeout::InMillisecondsFromNow() const {\n  constexpr DWord kInfinite = std::numeric_limits<DWord>::max();\n\n  if (!has_timeout()) {\n    return kInfinite;\n  }\n\n  constexpr uint64_t kNanosInMillis = uint64_t{1'000'000};\n  constexpr uint64_t kMaxValueNanos =\n      std::numeric_limits<int64_t>::max() - kNanosInMillis + 1;\n\n  uint64_t ns_from_now = static_cast<uint64_t>(InNanosecondsFromNow());\n  if (ns_from_now >= kMaxValueNanos) {\n    // Rounding up would overflow.\n    return kInfinite;\n  }\n  // Convert to milliseconds, always rounding up.\n  uint64_t ms_from_now = (ns_from_now + kNanosInMillis - 1) / kNanosInMillis;\n  if (ms_from_now > kInfinite) {\n    return kInfinite;\n  }\n  return static_cast<DWord>(ms_from_now);\n}\n\nstd::chrono::time_point<std::chrono::system_clock>\nKernelTimeout::ToChronoTimePoint() const {\n  if (!has_timeout()) {\n    return std::chrono::time_point<std::chrono::system_clock>::max();\n  }\n\n  // The cast to std::microseconds is because (on some platforms) the\n  // std::ratio used by std::chrono::steady_clock doesn't convert to\n  // std::nanoseconds, so it doesn't compile.\n  auto micros = std::chrono::duration_cast<std::chrono::microseconds>(\n      std::chrono::nanoseconds(MakeAbsNanos()));\n  return std::chrono::system_clock::from_time_t(0) + micros;\n}\n\nstd::chrono::nanoseconds KernelTimeout::ToChronoDuration() const {\n  if (!has_timeout()) {\n    return std::chrono::nanoseconds::max();\n  }\n  return std::chrono::nanoseconds(InNanosecondsFromNow());\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/internal/kernel_timeout.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_\n\n#ifndef _WIN32\n#include <sys/types.h>\n#endif\n\n#include <algorithm>\n#include <chrono>  // NOLINT(build/c++11)\n#include <cstdint>\n#include <ctime>\n#include <limits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// An optional timeout, with nanosecond granularity.\n//\n// This is a private low-level API for use by a handful of low-level\n// components. Higher-level components should build APIs based on\n// absl::Time and absl::Duration.\nclass KernelTimeout {\n public:\n  // Construct an absolute timeout that should expire at `t`.\n  explicit KernelTimeout(absl::Time t);\n\n  // Construct a relative timeout that should expire after `d`.\n  explicit KernelTimeout(absl::Duration d);\n\n  // Infinite timeout.\n  constexpr KernelTimeout() : rep_(kNoTimeout) {}\n\n  // A more explicit factory for those who prefer it.\n  // Equivalent to `KernelTimeout()`.\n  static constexpr KernelTimeout Never() { return KernelTimeout(); }\n\n  // Returns true if there is a timeout that will eventually expire.\n  // Returns false if the timeout is infinite.\n  bool has_timeout() const { return rep_ != kNoTimeout; }\n\n  // If `has_timeout()` is true, returns true if the timeout was provided as an\n  // `absl::Time`. The return value is undefined if `has_timeout()` is false\n  // because all indefinite timeouts are equivalent.\n  bool is_absolute_timeout() const { return (rep_ & 1) == 0; }\n\n  // If `has_timeout()` is true, returns true if the timeout was provided as an\n  // `absl::Duration`. The return value is undefined if `has_timeout()` is false\n  // because all indefinite timeouts are equivalent.\n  bool is_relative_timeout() const { return (rep_ & 1) == 1; }\n\n  // Convert to `struct timespec` for interfaces that expect an absolute\n  // timeout. If !has_timeout() or is_relative_timeout(), attempts to convert to\n  // a reasonable absolute timeout, but callers should to test has_timeout() and\n  // is_relative_timeout() and prefer to use a more appropriate interface.\n  struct timespec MakeAbsTimespec() const;\n\n  // Convert to `struct timespec` for interfaces that expect a relative\n  // timeout. If !has_timeout() or is_absolute_timeout(), attempts to convert to\n  // a reasonable relative timeout, but callers should to test has_timeout() and\n  // is_absolute_timeout() and prefer to use a more appropriate interface. Since\n  // the return value is a relative duration, it should be recomputed by calling\n  // this method in the case of a spurious wakeup.\n  struct timespec MakeRelativeTimespec() const;\n\n#ifndef _WIN32\n  // Convert to `struct timespec` for interfaces that expect an absolute timeout\n  // on a specific clock `c`. This is similar to `MakeAbsTimespec()`, but\n  // callers usually want to use this method with `CLOCK_MONOTONIC` when\n  // relative timeouts are requested, and when the appropriate interface expects\n  // an absolute timeout relative to a specific clock (for example,\n  // pthread_cond_clockwait() or sem_clockwait()). If !has_timeout(), attempts\n  // to convert to a reasonable absolute timeout, but callers should to test\n  // has_timeout() prefer to use a more appropriate interface.\n  struct timespec MakeClockAbsoluteTimespec(clockid_t c) const;\n#endif\n\n  // Convert to unix epoch nanos for interfaces that expect an absolute timeout\n  // in nanoseconds. If !has_timeout() or is_relative_timeout(), attempts to\n  // convert to a reasonable absolute timeout, but callers should to test\n  // has_timeout() and is_relative_timeout() and prefer to use a more\n  // appropriate interface.\n  int64_t MakeAbsNanos() const;\n\n  // Converts to milliseconds from now, or INFINITE when\n  // !has_timeout(). For use by SleepConditionVariableSRW on\n  // Windows. Callers should recognize that the return value is a\n  // relative duration (it should be recomputed by calling this method\n  // in the case of a spurious wakeup).\n  // This header file may be included transitively by public header files,\n  // so we define our own DWORD and INFINITE instead of getting them from\n  // <intsafe.h> and <WinBase.h>.\n  typedef unsigned long DWord;  // NOLINT\n  DWord InMillisecondsFromNow() const;\n\n  // Convert to std::chrono::time_point for interfaces that expect an absolute\n  // timeout, like std::condition_variable::wait_until(). If !has_timeout() or\n  // is_relative_timeout(), attempts to convert to a reasonable absolute\n  // timeout, but callers should test has_timeout() and is_relative_timeout()\n  // and prefer to use a more appropriate interface.\n  std::chrono::time_point<std::chrono::system_clock> ToChronoTimePoint() const;\n\n  // Convert to std::chrono::time_point for interfaces that expect a relative\n  // timeout, like std::condition_variable::wait_for(). If !has_timeout() or\n  // is_absolute_timeout(), attempts to convert to a reasonable relative\n  // timeout, but callers should test has_timeout() and is_absolute_timeout()\n  // and prefer to use a more appropriate interface. Since the return value is a\n  // relative duration, it should be recomputed by calling this method in the\n  // case of a spurious wakeup.\n  std::chrono::nanoseconds ToChronoDuration() const;\n\n  // Returns true if steady (aka monotonic) clocks are supported by the system.\n  // This currently returns true on all platforms, but we have encountered\n  // platforms that once lacked steady clock support.\n  static constexpr bool SupportsSteadyClock() { return true; }\n\n private:\n  // Returns the current time, expressed as a count of nanoseconds since the\n  // epoch used by an arbitrary clock. The implementation tries to use a steady\n  // (monotonic) clock if one is available.\n  static int64_t SteadyClockNow();\n\n  // Internal representation.\n  //   - If the value is kNoTimeout, then the timeout is infinite, and\n  //     has_timeout() will return true.\n  //   - If the low bit is 0, then the high 63 bits is the number of nanoseconds\n  //     after the unix epoch.\n  //   - If the low bit is 1, then the high 63 bits is the number of nanoseconds\n  //     after the epoch used by SteadyClockNow().\n  //\n  // In all cases the time is stored as an absolute time, the only difference is\n  // the clock epoch. The use of absolute times is important since in the case\n  // of a relative timeout with a spurious wakeup, the program would have to\n  // restart the wait, and thus needs a way of recomputing the remaining time.\n  uint64_t rep_;\n\n  // Returns the number of nanoseconds stored in the internal representation.\n  // When combined with the clock epoch indicated by the low bit (which is\n  // accessed through is_absolute_timeout() and is_relative_timeout()), the\n  // return value is used to compute when the timeout should occur.\n  int64_t RawAbsNanos() const { return static_cast<int64_t>(rep_ >> 1); }\n\n  // Converts to nanoseconds from now. Since the return value is a relative\n  // duration, it should be recomputed by calling this method in the case of a\n  // spurious wakeup.\n  int64_t InNanosecondsFromNow() const;\n\n  // A value that represents no timeout (or an infinite timeout).\n  static constexpr uint64_t kNoTimeout = (std::numeric_limits<uint64_t>::max)();\n\n  // The maximum value that can be stored in the high 63 bits.\n  static constexpr int64_t kMaxNanos = (std::numeric_limits<int64_t>::max)();\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_\n"
  },
  {
    "path": "absl/synchronization/internal/kernel_timeout_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\n#include <ctime>\n#include <chrono>  // NOLINT(build/c++11)\n#include <limits>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/random.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n#include \"gtest/gtest.h\"\n\n#if 0  // All supported platforms currently have steady clocks.\n#define ABSL_INTERNAL_KERNEL_TIMEOUT_SUPPORTS_STEADY_CLOCK 0\n#else\n#define ABSL_INTERNAL_KERNEL_TIMEOUT_SUPPORTS_STEADY_CLOCK 1\n#endif\n\nstatic_assert(\n    absl::synchronization_internal::KernelTimeout::SupportsSteadyClock() ==\n    static_cast<bool>(ABSL_INTERNAL_KERNEL_TIMEOUT_SUPPORTS_STEADY_CLOCK));\n\n// Randomizing the value of clock_gettime() for CLOCK_MONOTONIC.\n// This works by overriding a weak symbol in glibc.\n// We should be resistant to this randomization when !SupportsSteadyClock().\n#if !ABSL_INTERNAL_KERNEL_TIMEOUT_SUPPORTS_STEADY_CLOCK && \\\n    !defined(ABSL_HAVE_ADDRESS_SANITIZER) &&               \\\n    !defined(ABSL_HAVE_MEMORY_SANITIZER) &&                \\\n    !defined(ABSL_HAVE_THREAD_SANITIZER)\nextern \"C\" int __clock_gettime(clockid_t c, struct timespec* ts);\n\nextern \"C\" int clock_gettime(clockid_t c, struct timespec* ts) {\n  if (c == CLOCK_MONOTONIC &&\n      !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) {\n    thread_local absl::BitGen gen;  // NOLINT\n    ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000);\n    ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000);\n    return 0;\n  }\n  return __clock_gettime(c, ts);\n}\n#endif\n\nnamespace {\n\n#if defined(ABSL_HAVE_ADDRESS_SANITIZER) ||                        \\\n    defined(ABSL_HAVE_MEMORY_SANITIZER) ||                         \\\n    defined(ABSL_HAVE_THREAD_SANITIZER) || defined(__ANDROID__) || \\\n    defined(__APPLE__) || defined(_WIN32) || defined(_WIN64)\nconstexpr absl::Duration kTimingBound = absl::Milliseconds(5);\n#else\nconstexpr absl::Duration kTimingBound = absl::Microseconds(250);\n#endif\n\nusing absl::synchronization_internal::KernelTimeout;\n\n// TODO(b/348224897): re-enabled when the flakiness is fixed.\nTEST(KernelTimeout, DISABLED_FiniteTimes) {\n  constexpr absl::Duration kDurationsToTest[] = {\n    absl::ZeroDuration(),\n    absl::Nanoseconds(1),\n    absl::Microseconds(1),\n    absl::Milliseconds(1),\n    absl::Seconds(1),\n    absl::Minutes(1),\n    absl::Hours(1),\n    absl::Hours(1000),\n    -absl::Nanoseconds(1),\n    -absl::Microseconds(1),\n    -absl::Milliseconds(1),\n    -absl::Seconds(1),\n    -absl::Minutes(1),\n    -absl::Hours(1),\n    -absl::Hours(1000),\n  };\n\n  for (auto duration : kDurationsToTest) {\n    const absl::Time now = absl::Now();\n    const absl::Time when = now + duration;\n    SCOPED_TRACE(duration);\n    KernelTimeout t(when);\n    EXPECT_TRUE(t.has_timeout());\n    EXPECT_TRUE(t.is_absolute_timeout());\n    EXPECT_FALSE(t.is_relative_timeout());\n    EXPECT_EQ(absl::TimeFromTimespec(t.MakeAbsTimespec()), when);\n#ifndef _WIN32\n    EXPECT_LE(\n        absl::AbsDuration(absl::Now() + duration -\n                          absl::TimeFromTimespec(\n                              t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),\n        absl::Milliseconds(10));\n#endif\n    EXPECT_LE(\n        absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -\n                          std::max(duration, absl::ZeroDuration())),\n        kTimingBound);\n    EXPECT_EQ(absl::FromUnixNanos(t.MakeAbsNanos()), when);\n    EXPECT_LE(absl::AbsDuration(absl::Milliseconds(t.InMillisecondsFromNow()) -\n                                std::max(duration, absl::ZeroDuration())),\n              absl::Milliseconds(5));\n    EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoTimePoint()) - when),\n              absl::Microseconds(1));\n    EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) -\n                                std::max(duration, absl::ZeroDuration())),\n              kTimingBound);\n  }\n}\n\nTEST(KernelTimeout, InfiniteFuture) {\n  KernelTimeout t(absl::InfiniteFuture());\n  EXPECT_FALSE(t.has_timeout());\n  // Callers are expected to check has_timeout() instead of using the methods\n  // below, but we do try to do something reasonable if they don't. We may not\n  // be able to round-trip back to absl::InfiniteDuration() or\n  // absl::InfiniteFuture(), but we should return a very large value.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_EQ(t.InMillisecondsFromNow(),\n            std::numeric_limits<KernelTimeout::DWord>::max());\n  EXPECT_EQ(t.ToChronoTimePoint(),\n            std::chrono::time_point<std::chrono::system_clock>::max());\n  EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());\n}\n\nTEST(KernelTimeout, DefaultConstructor) {\n  // The default constructor is equivalent to absl::InfiniteFuture().\n  KernelTimeout t;\n  EXPECT_FALSE(t.has_timeout());\n  // Callers are expected to check has_timeout() instead of using the methods\n  // below, but we do try to do something reasonable if they don't. We may not\n  // be able to round-trip back to absl::InfiniteDuration() or\n  // absl::InfiniteFuture(), but we should return a very large value.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_EQ(t.InMillisecondsFromNow(),\n            std::numeric_limits<KernelTimeout::DWord>::max());\n  EXPECT_EQ(t.ToChronoTimePoint(),\n            std::chrono::time_point<std::chrono::system_clock>::max());\n  EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());\n}\n\nTEST(KernelTimeout, TimeMaxNanos) {\n  // Time >= kMaxNanos should behave as no timeout.\n  KernelTimeout t(absl::FromUnixNanos(std::numeric_limits<int64_t>::max()));\n  EXPECT_FALSE(t.has_timeout());\n  // Callers are expected to check has_timeout() instead of using the methods\n  // below, but we do try to do something reasonable if they don't. We may not\n  // be able to round-trip back to absl::InfiniteDuration() or\n  // absl::InfiniteFuture(), but we should return a very large value.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_EQ(t.InMillisecondsFromNow(),\n            std::numeric_limits<KernelTimeout::DWord>::max());\n  EXPECT_EQ(t.ToChronoTimePoint(),\n            std::chrono::time_point<std::chrono::system_clock>::max());\n  EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());\n}\n\nTEST(KernelTimeout, Never) {\n  // KernelTimeout::Never() is equivalent to absl::InfiniteFuture().\n  KernelTimeout t = KernelTimeout::Never();\n  EXPECT_FALSE(t.has_timeout());\n  // Callers are expected to check has_timeout() instead of using the methods\n  // below, but we do try to do something reasonable if they don't. We may not\n  // be able to round-trip back to absl::InfiniteDuration() or\n  // absl::InfiniteFuture(), but we should return a very large value.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_EQ(t.InMillisecondsFromNow(),\n            std::numeric_limits<KernelTimeout::DWord>::max());\n  EXPECT_EQ(t.ToChronoTimePoint(),\n            std::chrono::time_point<std::chrono::system_clock>::max());\n  EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());\n}\n\nTEST(KernelTimeout, InfinitePast) {\n  KernelTimeout t(absl::InfinitePast());\n  EXPECT_TRUE(t.has_timeout());\n  EXPECT_TRUE(t.is_absolute_timeout());\n  EXPECT_FALSE(t.is_relative_timeout());\n  EXPECT_LE(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::FromUnixNanos(1));\n#ifndef _WIN32\n  EXPECT_LE(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::FromUnixSeconds(1));\n#endif\n  EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::ZeroDuration());\n  EXPECT_LE(absl::FromUnixNanos(t.MakeAbsNanos()), absl::FromUnixNanos(1));\n  EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});\n  EXPECT_LT(t.ToChronoTimePoint(), std::chrono::system_clock::from_time_t(0) +\n                                       std::chrono::seconds(1));\n  EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));\n}\n\n// TODO(b/348224897): re-enabled when the flakiness is fixed.\nTEST(KernelTimeout, DISABLED_FiniteDurations) {\n  constexpr absl::Duration kDurationsToTest[] = {\n    absl::ZeroDuration(),\n    absl::Nanoseconds(1),\n    absl::Microseconds(1),\n    absl::Milliseconds(1),\n    absl::Seconds(1),\n    absl::Minutes(1),\n    absl::Hours(1),\n    absl::Hours(1000),\n  };\n\n  for (auto duration : kDurationsToTest) {\n    SCOPED_TRACE(duration);\n    KernelTimeout t(duration);\n    EXPECT_TRUE(t.has_timeout());\n    EXPECT_FALSE(t.is_absolute_timeout());\n    EXPECT_TRUE(t.is_relative_timeout());\n    EXPECT_LE(absl::AbsDuration(absl::Now() + duration -\n                                absl::TimeFromTimespec(t.MakeAbsTimespec())),\n              absl::Milliseconds(5));\n#ifndef _WIN32\n    EXPECT_LE(\n        absl::AbsDuration(absl::Now() + duration -\n                          absl::TimeFromTimespec(\n                              t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),\n        absl::Milliseconds(5));\n#endif\n    EXPECT_LE(\n        absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -\n                          duration),\n        kTimingBound);\n    EXPECT_LE(absl::AbsDuration(absl::Now() + duration -\n                                absl::FromUnixNanos(t.MakeAbsNanos())),\n              absl::Milliseconds(5));\n    EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,\n              absl::Milliseconds(5));\n    EXPECT_LE(absl::AbsDuration(absl::Now() + duration -\n                                absl::FromChrono(t.ToChronoTimePoint())),\n              kTimingBound);\n    EXPECT_LE(\n        absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - duration),\n        kTimingBound);\n  }\n}\n\n// TODO(b/348224897): re-enabled when the flakiness is fixed.\nTEST(KernelTimeout, DISABLED_NegativeDurations) {\n  constexpr absl::Duration kDurationsToTest[] = {\n    -absl::ZeroDuration(),\n    -absl::Nanoseconds(1),\n    -absl::Microseconds(1),\n    -absl::Milliseconds(1),\n    -absl::Seconds(1),\n    -absl::Minutes(1),\n    -absl::Hours(1),\n    -absl::Hours(1000),\n    -absl::InfiniteDuration(),\n  };\n\n  for (auto duration : kDurationsToTest) {\n    // Negative durations should all be converted to zero durations or \"now\".\n    SCOPED_TRACE(duration);\n    KernelTimeout t(duration);\n    EXPECT_TRUE(t.has_timeout());\n    EXPECT_FALSE(t.is_absolute_timeout());\n    EXPECT_TRUE(t.is_relative_timeout());\n    EXPECT_LE(absl::AbsDuration(absl::Now() -\n                                absl::TimeFromTimespec(t.MakeAbsTimespec())),\n              absl::Milliseconds(5));\n#ifndef _WIN32\n    EXPECT_LE(absl::AbsDuration(absl::Now() - absl::TimeFromTimespec(\n                                                  t.MakeClockAbsoluteTimespec(\n                                                      CLOCK_REALTIME))),\n              absl::Milliseconds(5));\n#endif\n    EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n              absl::ZeroDuration());\n    EXPECT_LE(\n        absl::AbsDuration(absl::Now() - absl::FromUnixNanos(t.MakeAbsNanos())),\n        absl::Milliseconds(5));\n    EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});\n    EXPECT_LE(absl::AbsDuration(absl::Now() -\n                                absl::FromChrono(t.ToChronoTimePoint())),\n              absl::Milliseconds(5));\n    EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));\n  }\n}\n\nTEST(KernelTimeout, InfiniteDuration) {\n  KernelTimeout t(absl::InfiniteDuration());\n  EXPECT_FALSE(t.has_timeout());\n  // Callers are expected to check has_timeout() instead of using the methods\n  // below, but we do try to do something reasonable if they don't. We may not\n  // be able to round-trip back to absl::InfiniteDuration() or\n  // absl::InfiniteFuture(), but we should return a very large value.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_EQ(t.InMillisecondsFromNow(),\n            std::numeric_limits<KernelTimeout::DWord>::max());\n  EXPECT_EQ(t.ToChronoTimePoint(),\n            std::chrono::time_point<std::chrono::system_clock>::max());\n  EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());\n}\n\nTEST(KernelTimeout, DurationMaxNanos) {\n  // Duration >= kMaxNanos should behave as no timeout.\n  KernelTimeout t(absl::Nanoseconds(std::numeric_limits<int64_t>::max()));\n  EXPECT_FALSE(t.has_timeout());\n  // Callers are expected to check has_timeout() instead of using the methods\n  // below, but we do try to do something reasonable if they don't. We may not\n  // be able to round-trip back to absl::InfiniteDuration() or\n  // absl::InfiniteFuture(), but we should return a very large value.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_EQ(t.InMillisecondsFromNow(),\n            std::numeric_limits<KernelTimeout::DWord>::max());\n  EXPECT_EQ(t.ToChronoTimePoint(),\n            std::chrono::time_point<std::chrono::system_clock>::max());\n  EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());\n}\n\nTEST(KernelTimeout, OverflowNanos) {\n  // Test what happens when KernelTimeout is constructed with an absl::Duration\n  // that would overflow now_nanos + duration.\n  int64_t now_nanos = absl::ToUnixNanos(absl::Now());\n  int64_t limit = std::numeric_limits<int64_t>::max() - now_nanos;\n  absl::Duration duration = absl::Nanoseconds(limit) + absl::Seconds(1);\n  KernelTimeout t(duration);\n  // Timeouts should still be far in the future.\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),\n            absl::Now() + absl::Hours(100000));\n#ifndef _WIN32\n  EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),\n            absl::Now() + absl::Hours(100000));\n#endif\n  EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),\n            absl::Hours(100000));\n  EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),\n            absl::Now() + absl::Hours(100000));\n  EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,\n            absl::Milliseconds(5));\n  EXPECT_GT(t.ToChronoTimePoint(),\n            std::chrono::system_clock::now() + std::chrono::hours(100000));\n  EXPECT_GT(t.ToChronoDuration(), std::chrono::hours(100000));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/internal/per_thread_sem.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This file is a no-op if the required LowLevelAlloc support is missing.\n#include \"absl/base/internal/low_level_alloc.h\"\n#ifndef ABSL_LOW_LEVEL_ALLOC_MISSING\n\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n\n#include <atomic>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/synchronization/internal/waiter.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nvoid PerThreadSem::SetThreadBlockedCounter(std::atomic<int> *counter) {\n  base_internal::ThreadIdentity *identity;\n  identity = GetOrCreateCurrentThreadIdentity();\n  identity->blocked_count_ptr = counter;\n}\n\nstd::atomic<int> *PerThreadSem::GetThreadBlockedCounter() {\n  base_internal::ThreadIdentity *identity;\n  identity = GetOrCreateCurrentThreadIdentity();\n  return identity->blocked_count_ptr;\n}\n\nvoid PerThreadSem::Tick(base_internal::ThreadIdentity *identity) {\n  const int ticker =\n      identity->ticker.fetch_add(1, std::memory_order_relaxed) + 1;\n  const int wait_start = identity->wait_start.load(std::memory_order_relaxed);\n  const bool is_idle = identity->is_idle.load(std::memory_order_relaxed);\n  if (wait_start && (ticker - wait_start > Waiter::kIdlePeriods) && !is_idle) {\n    // Wakeup the waiting thread since it is time for it to become idle.\n    ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPoke)(identity);\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nextern \"C\" {\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(\n    absl::base_internal::ThreadIdentity *identity) {\n  new (absl::synchronization_internal::Waiter::GetWaiter(identity))\n      absl::synchronization_internal::Waiter();\n}\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(\n    absl::base_internal::ThreadIdentity *identity) {\n  absl::synchronization_internal::Waiter::GetWaiter(identity)->Post();\n}\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPoke)(\n    absl::base_internal::ThreadIdentity *identity) {\n  absl::synchronization_internal::Waiter::GetWaiter(identity)->Poke();\n}\n\nABSL_ATTRIBUTE_WEAK bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(\n    absl::synchronization_internal::KernelTimeout t) {\n  bool timeout = false;\n  absl::base_internal::ThreadIdentity *identity;\n  identity = absl::synchronization_internal::GetOrCreateCurrentThreadIdentity();\n\n  // Ensure wait_start != 0.\n  int ticker = identity->ticker.load(std::memory_order_relaxed);\n  identity->wait_start.store(ticker ? ticker : 1, std::memory_order_relaxed);\n  identity->is_idle.store(false, std::memory_order_relaxed);\n\n  if (identity->blocked_count_ptr != nullptr) {\n    // Increment count of threads blocked in a given thread pool.\n    identity->blocked_count_ptr->fetch_add(1, std::memory_order_relaxed);\n  }\n\n  timeout =\n      !absl::synchronization_internal::Waiter::GetWaiter(identity)->Wait(t);\n\n  if (identity->blocked_count_ptr != nullptr) {\n    identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed);\n  }\n\n  identity->is_idle.store(false, std::memory_order_relaxed);\n  identity->wait_start.store(0, std::memory_order_relaxed);\n  return !timeout;\n}\n\n}  // extern \"C\"\n\n#endif  // ABSL_LOW_LEVEL_ALLOC_MISSING\n"
  },
  {
    "path": "absl/synchronization/internal/per_thread_sem.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n// PerThreadSem is a low-level synchronization primitive controlling the\n// runnability of a single thread, used internally by Mutex and CondVar.\n//\n// This is NOT a general-purpose synchronization mechanism, and should not be\n// used directly by applications.  Applications should use Mutex and CondVar.\n//\n// The semantics of PerThreadSem are the same as that of a counting semaphore.\n// Each thread maintains an abstract \"count\" value associated with its identity.\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_\n\n#include <atomic>\n\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/synchronization/internal/create_thread_identity.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass Mutex;\n\nnamespace synchronization_internal {\n\nclass PerThreadSem {\n public:\n  PerThreadSem() = delete;\n  PerThreadSem(const PerThreadSem&) = delete;\n  PerThreadSem& operator=(const PerThreadSem&) = delete;\n\n  // Routine invoked periodically (once a second) by a background thread.\n  // Has no effect on user-visible state.\n  static void Tick(base_internal::ThreadIdentity* identity);\n\n  // ---------------------------------------------------------------------------\n  // Routines used by autosizing threadpools to detect when threads are\n  // blocked.  Each thread has a counter pointer, initially zero.  If non-zero,\n  // the implementation atomically increments the counter when it blocks on a\n  // semaphore, a decrements it again when it wakes.  This allows a threadpool\n  // to keep track of how many of its threads are blocked.\n  // SetThreadBlockedCounter() should be used only by threadpool\n  // implementations.  GetThreadBlockedCounter() should be used by modules that\n  // block threads; if the pointer returned is non-zero, the location should be\n  // incremented before the thread blocks, and decremented after it wakes.\n  static void SetThreadBlockedCounter(std::atomic<int> *counter);\n  static std::atomic<int> *GetThreadBlockedCounter();\n\n private:\n  // Create the PerThreadSem associated with \"identity\".  Initializes count=0.\n  // REQUIRES: May only be called by ThreadIdentity.\n  static inline void Init(base_internal::ThreadIdentity* identity);\n\n  // Increments \"identity\"'s count.\n  static inline void Post(base_internal::ThreadIdentity* identity);\n\n  // Waits until either our count > 0 or t has expired.\n  // If count > 0, decrements count and returns true.  Otherwise returns false.\n  // !t.has_timeout() => Wait(t) will return true.\n  static inline bool Wait(KernelTimeout t);\n\n  // Permitted callers.\n  friend class PerThreadSemTest;\n  friend class absl::Mutex;\n  friend void OneTimeInitThreadIdentity(absl::base_internal::ThreadIdentity*);\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// In some build configurations we pass --detect-odr-violations to the\n// gold linker.  This causes it to flag weak symbol overrides as ODR\n// violations.  Because ODR only applies to C++ and not C,\n// --detect-odr-violations ignores symbols not mangled with C++ names.\n// By changing our extension points to be extern \"C\", we dodge this\n// check.\nextern \"C\" {\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(\n    absl::base_internal::ThreadIdentity* identity);\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(\n    absl::base_internal::ThreadIdentity* identity);\nbool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(\n    absl::synchronization_internal::KernelTimeout t);\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPoke)(\n    absl::base_internal::ThreadIdentity* identity);\n}  // extern \"C\"\n\nvoid absl::synchronization_internal::PerThreadSem::Init(\n    absl::base_internal::ThreadIdentity* identity) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(identity);\n}\n\nvoid absl::synchronization_internal::PerThreadSem::Post(\n    absl::base_internal::ThreadIdentity* identity) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(identity);\n}\n\nbool absl::synchronization_internal::PerThreadSem::Wait(\n    absl::synchronization_internal::KernelTimeout t) {\n  return ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(t);\n}\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_\n"
  },
  {
    "path": "absl/synchronization/internal/per_thread_sem_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n\n#include <atomic>\n#include <condition_variable>  // NOLINT(build/c++11)\n#include <functional>\n#include <limits>\n#include <mutex>               // NOLINT(build/c++11)\n#include <string>\n#include <thread>              // NOLINT(build/c++11)\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/cycleclock.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\n// In this test we explicitly avoid the use of synchronization\n// primitives which might use PerThreadSem, most notably absl::Mutex.\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nclass SimpleSemaphore {\n public:\n  SimpleSemaphore() : count_(0) {}\n\n  // Decrements (locks) the semaphore. If the semaphore's value is\n  // greater than zero, then the decrement proceeds, and the function\n  // returns, immediately. If the semaphore currently has the value\n  // zero, then the call blocks until it becomes possible to perform\n  // the decrement.\n  void Wait() {\n    std::unique_lock<std::mutex> lock(mu_);\n    cv_.wait(lock, [this]() { return count_ > 0; });\n    --count_;\n    cv_.notify_one();\n  }\n\n  // Increments (unlocks) the semaphore. If the semaphore's value\n  // consequently becomes greater than zero, then another thread\n  // blocked Wait() call will be woken up and proceed to lock the\n  // semaphore.\n  void Post() {\n    std::lock_guard<std::mutex> lock(mu_);\n    ++count_;\n    cv_.notify_one();\n  }\n\n private:\n  std::mutex mu_;\n  std::condition_variable cv_;\n  int count_;\n};\n\nstruct ThreadData {\n  int num_iterations;                 // Number of replies to send.\n  SimpleSemaphore identity2_written;  // Posted by thread writing identity2.\n  base_internal::ThreadIdentity *identity1;  // First Post()-er.\n  base_internal::ThreadIdentity *identity2;  // First Wait()-er.\n  KernelTimeout timeout;\n};\n\n// Need friendship with PerThreadSem.\nclass PerThreadSemTest : public testing::Test {\n public:\n  static void TimingThread(ThreadData* t) {\n    t->identity2 = GetOrCreateCurrentThreadIdentity();\n    t->identity2_written.Post();\n    while (t->num_iterations--) {\n      Wait(t->timeout);\n      Post(t->identity1);\n    }\n  }\n\n  void TestTiming(const char *msg, bool timeout) {\n    static const int kNumIterations = 100;\n    ThreadData t;\n    t.num_iterations = kNumIterations;\n    t.timeout = timeout ?\n        KernelTimeout(absl::Now() + absl::Seconds(10000))  // far in the future\n        : KernelTimeout::Never();\n    t.identity1 = GetOrCreateCurrentThreadIdentity();\n\n    // We can't use the Thread class here because it uses the Mutex\n    // class which will invoke PerThreadSem, so we use std::thread instead.\n    std::thread partner_thread(std::bind(TimingThread, &t));\n\n    // Wait for our partner thread to register their identity.\n    t.identity2_written.Wait();\n\n    int64_t min_cycles = std::numeric_limits<int64_t>::max();\n    int64_t total_cycles = 0;\n    for (int i = 0; i < kNumIterations; ++i) {\n      absl::SleepFor(absl::Milliseconds(20));\n      int64_t cycles = base_internal::CycleClock::Now();\n      Post(t.identity2);\n      Wait(t.timeout);\n      cycles = base_internal::CycleClock::Now() - cycles;\n      min_cycles = std::min(min_cycles, cycles);\n      total_cycles += cycles;\n    }\n    std::string out = StrCat(\n        msg, \"min cycle count=\", min_cycles, \" avg cycle count=\",\n        absl::SixDigits(static_cast<double>(total_cycles) / kNumIterations));\n    printf(\"%s\\n\", out.c_str());\n\n    partner_thread.join();\n  }\n\n protected:\n  static void Post(base_internal::ThreadIdentity *id) {\n    PerThreadSem::Post(id);\n  }\n  static bool Wait(KernelTimeout t) {\n    return PerThreadSem::Wait(t);\n  }\n\n  // convenience overload\n  static bool Wait(absl::Time t) {\n    return Wait(KernelTimeout(t));\n  }\n\n  static void Tick(base_internal::ThreadIdentity *identity) {\n    PerThreadSem::Tick(identity);\n  }\n};\n\nnamespace {\n\nTEST_F(PerThreadSemTest, WithoutTimeout) {\n  PerThreadSemTest::TestTiming(\"Without timeout: \", false);\n}\n\nTEST_F(PerThreadSemTest, WithTimeout) {\n  PerThreadSemTest::TestTiming(\"With timeout:    \", true);\n}\n\nTEST_F(PerThreadSemTest, Timeouts) {\n  const absl::Duration delay = absl::Milliseconds(50);\n  const absl::Time start = absl::Now();\n  EXPECT_FALSE(Wait(start + delay));\n  const absl::Duration elapsed = absl::Now() - start;\n  // Allow for a slight early return, to account for quality of implementation\n  // issues on various platforms.\n  absl::Duration slop = absl::Milliseconds(1);\n#ifdef _MSC_VER\n  // Use higher slop on MSVC due to flaky test failures.\n  slop = absl::Milliseconds(16);\n#endif\n  EXPECT_LE(delay - slop, elapsed)\n      << \"Wait returned \" << delay - elapsed\n      << \" early (with \" << slop << \" slop), start time was \" << start;\n\n  absl::Time negative_timeout = absl::UnixEpoch() - absl::Milliseconds(100);\n  EXPECT_FALSE(Wait(negative_timeout));\n  EXPECT_LE(negative_timeout, absl::Now() + slop);  // trivially true :)\n\n  Post(GetOrCreateCurrentThreadIdentity());\n  // The wait here has an expired timeout, but we have a wake to consume,\n  // so this should succeed\n  EXPECT_TRUE(Wait(negative_timeout));\n}\n\nTEST_F(PerThreadSemTest, ThreadIdentityReuse) {\n  // Create a base_internal::ThreadIdentity object and keep reusing it. There\n  // should be no memory or resource leaks.\n  for (int i = 0; i < 10000; i++) {\n    std::thread t([]() { GetOrCreateCurrentThreadIdentity(); });\n    t.join();\n  }\n}\n\n}  // namespace\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/internal/pthread_waiter.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/pthread_waiter.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_PTHREAD_WAITER\n\n#include <pthread.h>\n#include <sys/time.h>\n#include <unistd.h>\n\n#include <cassert>\n#include <cerrno>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nnamespace {\nclass PthreadMutexHolder {\n public:\n  explicit PthreadMutexHolder(pthread_mutex_t *mu) : mu_(mu) {\n    const int err = pthread_mutex_lock(mu_);\n    if (err != 0) {\n      ABSL_RAW_LOG(FATAL, \"pthread_mutex_lock failed: %d\", err);\n    }\n  }\n\n  PthreadMutexHolder(const PthreadMutexHolder &rhs) = delete;\n  PthreadMutexHolder &operator=(const PthreadMutexHolder &rhs) = delete;\n\n  ~PthreadMutexHolder() {\n    const int err = pthread_mutex_unlock(mu_);\n    if (err != 0) {\n      ABSL_RAW_LOG(FATAL, \"pthread_mutex_unlock failed: %d\", err);\n    }\n  }\n\n private:\n  pthread_mutex_t *mu_;\n};\n}  // namespace\n\nPthreadWaiter::PthreadWaiter() : waiter_count_(0), wakeup_count_(0) {\n  const int err = pthread_mutex_init(&mu_, 0);\n  if (err != 0) {\n    ABSL_RAW_LOG(FATAL, \"pthread_mutex_init failed: %d\", err);\n  }\n\n  const int err2 = pthread_cond_init(&cv_, 0);\n  if (err2 != 0) {\n    ABSL_RAW_LOG(FATAL, \"pthread_cond_init failed: %d\", err2);\n  }\n}\n\n#ifdef __APPLE__\n#define ABSL_INTERNAL_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1\n#endif\n\n#if defined(__GLIBC__) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 30))\n#define ABSL_INTERNAL_HAVE_PTHREAD_COND_CLOCKWAIT 1\n#elif defined(__ANDROID_API__) && __ANDROID_API__ >= 30\n#define ABSL_INTERNAL_HAVE_PTHREAD_COND_CLOCKWAIT 1\n#endif\n\n// Calls pthread_cond_timedwait() or possibly something else like\n// pthread_cond_timedwait_relative_np() depending on the platform and\n// KernelTimeout requested. The return value is the same as the return\n// value of pthread_cond_timedwait().\nint PthreadWaiter::TimedWait(KernelTimeout t) {\n  assert(t.has_timeout());\n  if (KernelTimeout::SupportsSteadyClock() && t.is_relative_timeout()) {\n#ifdef ABSL_INTERNAL_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP\n    const auto rel_timeout = t.MakeRelativeTimespec();\n    return pthread_cond_timedwait_relative_np(&cv_, &mu_, &rel_timeout);\n#elif defined(ABSL_INTERNAL_HAVE_PTHREAD_COND_CLOCKWAIT) && \\\n    defined(CLOCK_MONOTONIC)\n    const auto abs_clock_timeout = t.MakeClockAbsoluteTimespec(CLOCK_MONOTONIC);\n    return pthread_cond_clockwait(&cv_, &mu_, CLOCK_MONOTONIC,\n                                  &abs_clock_timeout);\n#endif\n  }\n\n  const auto abs_timeout = t.MakeAbsTimespec();\n  return pthread_cond_timedwait(&cv_, &mu_, &abs_timeout);\n}\n\nbool PthreadWaiter::Wait(KernelTimeout t) {\n  PthreadMutexHolder h(&mu_);\n  ++waiter_count_;\n  // Loop until we find a wakeup to consume or timeout.\n  // Note that, since the thread ticker is just reset, we don't need to check\n  // whether the thread is idle on the very first pass of the loop.\n  bool first_pass = true;\n  while (wakeup_count_ == 0) {\n    if (!first_pass) MaybeBecomeIdle();\n    // No wakeups available, time to wait.\n    if (!t.has_timeout()) {\n      const int err = pthread_cond_wait(&cv_, &mu_);\n      if (err != 0) {\n        ABSL_RAW_LOG(FATAL, \"pthread_cond_wait failed: %d\", err);\n      }\n    } else {\n      const int err = TimedWait(t);\n      if (err == ETIMEDOUT) {\n        --waiter_count_;\n        return false;\n      }\n      if (err != 0) {\n        ABSL_RAW_LOG(FATAL, \"PthreadWaiter::TimedWait() failed: %d\", err);\n      }\n    }\n    first_pass = false;\n  }\n  // Consume a wakeup and we're done.\n  --wakeup_count_;\n  --waiter_count_;\n  return true;\n}\n\nvoid PthreadWaiter::Post() {\n  PthreadMutexHolder h(&mu_);\n  ++wakeup_count_;\n  InternalCondVarPoke();\n}\n\nvoid PthreadWaiter::Poke() {\n  PthreadMutexHolder h(&mu_);\n  InternalCondVarPoke();\n}\n\nvoid PthreadWaiter::InternalCondVarPoke() {\n  if (waiter_count_ != 0) {\n    const int err = pthread_cond_signal(&cv_);\n    if (ABSL_PREDICT_FALSE(err != 0)) {\n      ABSL_RAW_LOG(FATAL, \"pthread_cond_signal failed: %d\", err);\n    }\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_PTHREAD_WAITER\n"
  },
  {
    "path": "absl/synchronization/internal/pthread_waiter.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_PTHREAD_WAITER_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_PTHREAD_WAITER_H_\n\n#if !defined(_WIN32) && !defined(__MINGW32__)\n#include <pthread.h>\n\n#include \"absl/base/config.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/waiter_base.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n#define ABSL_INTERNAL_HAVE_PTHREAD_WAITER 1\n\nclass PthreadWaiter : public WaiterCrtp<PthreadWaiter> {\n public:\n  PthreadWaiter();\n\n  bool Wait(KernelTimeout t);\n  void Post();\n  void Poke();\n\n  static constexpr char kName[] = \"PthreadWaiter\";\n\n private:\n  int TimedWait(KernelTimeout t);\n\n  // REQUIRES: mu_ must be held.\n  void InternalCondVarPoke();\n\n  pthread_mutex_t mu_;\n  pthread_cond_t cv_;\n  int waiter_count_;\n  int wakeup_count_;  // Unclaimed wakeups.\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // !defined(_WIN32) && !defined(__MINGW32__)\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_PTHREAD_WAITER_H_\n"
  },
  {
    "path": "absl/synchronization/internal/sem_waiter.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/sem_waiter.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_SEM_WAITER\n\n#include <semaphore.h>\n\n#include <atomic>\n#include <cassert>\n#include <cstdint>\n#include <cerrno>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nSemWaiter::SemWaiter() : wakeups_(0) {\n  if (sem_init(&sem_, 0, 0) != 0) {\n    ABSL_RAW_LOG(FATAL, \"sem_init failed with errno %d\\n\", errno);\n  }\n}\n\n#if defined(__GLIBC__) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 30))\n#define ABSL_INTERNAL_HAVE_SEM_CLOCKWAIT 1\n#elif defined(__ANDROID_API__) && __ANDROID_API__ >= 30\n#define ABSL_INTERNAL_HAVE_SEM_CLOCKWAIT 1\n#endif\n\n// Calls sem_timedwait() or possibly something else like\n// sem_clockwait() depending on the platform and\n// KernelTimeout requested. The return value is the same as a call to the return\n// value to a call to sem_timedwait().\nint SemWaiter::TimedWait(KernelTimeout t) {\n  if (KernelTimeout::SupportsSteadyClock() && t.is_relative_timeout()) {\n#if defined(ABSL_INTERNAL_HAVE_SEM_CLOCKWAIT) && defined(CLOCK_MONOTONIC)\n    const auto abs_clock_timeout = t.MakeClockAbsoluteTimespec(CLOCK_MONOTONIC);\n    return sem_clockwait(&sem_, CLOCK_MONOTONIC, &abs_clock_timeout);\n#endif\n  }\n\n  const auto abs_timeout = t.MakeAbsTimespec();\n  return sem_timedwait(&sem_, &abs_timeout);\n}\n\nbool SemWaiter::Wait(KernelTimeout t) {\n  // Loop until we timeout or consume a wakeup.\n  // Note that, since the thread ticker is just reset, we don't need to check\n  // whether the thread is idle on the very first pass of the loop.\n  bool first_pass = true;\n  while (true) {\n    int x = wakeups_.load(std::memory_order_relaxed);\n    while (x != 0) {\n      if (!wakeups_.compare_exchange_weak(x, x - 1,\n                                          std::memory_order_acquire,\n                                          std::memory_order_relaxed)) {\n        continue;  // Raced with someone, retry.\n      }\n      // Successfully consumed a wakeup, we're done.\n      return true;\n    }\n\n    if (!first_pass) MaybeBecomeIdle();\n    // Nothing to consume, wait (looping on EINTR).\n    while (true) {\n      if (!t.has_timeout()) {\n        if (sem_wait(&sem_) == 0) break;\n        if (errno == EINTR) continue;\n        ABSL_RAW_LOG(FATAL, \"sem_wait failed: %d\", errno);\n      } else {\n        if (TimedWait(t) == 0) break;\n        if (errno == EINTR) continue;\n        if (errno == ETIMEDOUT) return false;\n        ABSL_RAW_LOG(FATAL, \"SemWaiter::TimedWait() failed: %d\", errno);\n      }\n    }\n    first_pass = false;\n  }\n}\n\nvoid SemWaiter::Post() {\n  // Post a wakeup.\n  if (wakeups_.fetch_add(1, std::memory_order_release) == 0) {\n    // We incremented from 0, need to wake a potential waiter.\n    Poke();\n  }\n}\n\nvoid SemWaiter::Poke() {\n  if (sem_post(&sem_) != 0) {  // Wake any semaphore waiter.\n    ABSL_RAW_LOG(FATAL, \"sem_post failed with errno %d\\n\", errno);\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_SEM_WAITER\n"
  },
  {
    "path": "absl/synchronization/internal/sem_waiter.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_SEM_WAITER_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_SEM_WAITER_H_\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_HAVE_SEMAPHORE_H\n#include <semaphore.h>\n\n#include <atomic>\n#include <cstdint>\n\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/synchronization/internal/futex.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/waiter_base.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n#define ABSL_INTERNAL_HAVE_SEM_WAITER 1\n\nclass SemWaiter : public WaiterCrtp<SemWaiter> {\n public:\n  SemWaiter();\n\n  bool Wait(KernelTimeout t);\n  void Post();\n  void Poke();\n\n  static constexpr char kName[] = \"SemWaiter\";\n\n private:\n  int TimedWait(KernelTimeout t);\n\n  sem_t sem_;\n\n  // This seems superfluous, but for Poke() we need to cause spurious\n  // wakeups on the semaphore. Hence we can't actually use the\n  // semaphore's count.\n  std::atomic<int> wakeups_;\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_HAVE_SEMAPHORE_H\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_SEM_WAITER_H_\n"
  },
  {
    "path": "absl/synchronization/internal/stdcpp_waiter.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/stdcpp_waiter.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER\n\n#include <chrono>  // NOLINT(build/c++11)\n#include <condition_variable>  // NOLINT(build/c++11)\n#include <mutex>  // NOLINT(build/c++11)\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nStdcppWaiter::StdcppWaiter() : waiter_count_(0), wakeup_count_(0) {}\n\nbool StdcppWaiter::Wait(KernelTimeout t) {\n  std::unique_lock<std::mutex> lock(mu_);\n  ++waiter_count_;\n\n  // Loop until we find a wakeup to consume or timeout.\n  // Note that, since the thread ticker is just reset, we don't need to check\n  // whether the thread is idle on the very first pass of the loop.\n  bool first_pass = true;\n  while (wakeup_count_ == 0) {\n    if (!first_pass) MaybeBecomeIdle();\n    // No wakeups available, time to wait.\n    if (!t.has_timeout()) {\n      cv_.wait(lock);\n    } else {\n      auto wait_result = t.SupportsSteadyClock() && t.is_relative_timeout()\n                             ? cv_.wait_for(lock, t.ToChronoDuration())\n                             : cv_.wait_until(lock, t.ToChronoTimePoint());\n      if (wait_result == std::cv_status::timeout) {\n        --waiter_count_;\n        return false;\n      }\n    }\n    first_pass = false;\n  }\n\n  // Consume a wakeup and we're done.\n  --wakeup_count_;\n  --waiter_count_;\n  return true;\n}\n\nvoid StdcppWaiter::Post() {\n  std::lock_guard<std::mutex> lock(mu_);\n  ++wakeup_count_;\n  InternalCondVarPoke();\n}\n\nvoid StdcppWaiter::Poke() {\n  std::lock_guard<std::mutex> lock(mu_);\n  InternalCondVarPoke();\n}\n\nvoid StdcppWaiter::InternalCondVarPoke() {\n  if (waiter_count_ != 0) {\n    cv_.notify_one();\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_STDCPP_WAITER\n"
  },
  {
    "path": "absl/synchronization/internal/stdcpp_waiter.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_STDCPP_WAITER_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_STDCPP_WAITER_H_\n\n#include <condition_variable>  // NOLINT(build/c++11)\n#include <mutex>  // NOLINT(build/c++11)\n\n#include \"absl/base/config.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/waiter_base.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n#define ABSL_INTERNAL_HAVE_STDCPP_WAITER 1\n\nclass StdcppWaiter : public WaiterCrtp<StdcppWaiter> {\n public:\n  StdcppWaiter();\n\n  bool Wait(KernelTimeout t);\n  void Post();\n  void Poke();\n\n  static constexpr char kName[] = \"StdcppWaiter\";\n\n private:\n  // REQUIRES: mu_ must be held.\n  void InternalCondVarPoke();\n\n  std::mutex mu_;\n  std::condition_variable cv_;\n  int waiter_count_;\n  int wakeup_count_;  // Unclaimed wakeups.\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_STDCPP_WAITER_H_\n"
  },
  {
    "path": "absl/synchronization/internal/thread_pool.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_\n\n#include <cassert>\n#include <cstddef>\n#include <functional>\n#include <queue>\n#include <thread>  // NOLINT(build/c++11)\n#include <utility>\n#include <vector>\n\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/functional/any_invocable.h\"\n#include \"absl/synchronization/mutex.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// A simple ThreadPool implementation for tests.\nclass ThreadPool {\n public:\n  explicit ThreadPool(int num_threads) {\n    threads_.reserve(num_threads);\n    for (int i = 0; i < num_threads; ++i) {\n      threads_.push_back(std::thread(&ThreadPool::WorkLoop, this));\n    }\n  }\n\n  ThreadPool(const ThreadPool &) = delete;\n  ThreadPool &operator=(const ThreadPool &) = delete;\n\n  ~ThreadPool() {\n    {\n      absl::MutexLock l(mu_);\n      for (size_t i = 0; i < threads_.size(); i++) {\n        queue_.push(nullptr);  // Shutdown signal.\n      }\n    }\n    for (auto &t : threads_) {\n      t.join();\n    }\n  }\n\n  // Schedule a function to be run on a ThreadPool thread immediately.\n  void Schedule(absl::AnyInvocable<void()> func) {\n    assert(func != nullptr);\n    absl::MutexLock l(mu_);\n    queue_.push(std::move(func));\n  }\n\n private:\n  bool WorkAvailable() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {\n    return !queue_.empty();\n  }\n\n  void WorkLoop() {\n    while (true) {\n      absl::AnyInvocable<void()> func;\n      {\n        absl::MutexLock l(mu_);\n        mu_.Await(absl::Condition(this, &ThreadPool::WorkAvailable));\n        func = std::move(queue_.front());\n        queue_.pop();\n      }\n      if (func == nullptr) {  // Shutdown signal.\n        break;\n      }\n      func();\n    }\n  }\n\n  absl::Mutex mu_;\n  std::queue<absl::AnyInvocable<void()>> queue_ ABSL_GUARDED_BY(mu_);\n  std::vector<std::thread> threads_;\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_\n"
  },
  {
    "path": "absl/synchronization/internal/waiter.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/synchronization/internal/futex_waiter.h\"\n#include \"absl/synchronization/internal/pthread_waiter.h\"\n#include \"absl/synchronization/internal/sem_waiter.h\"\n#include \"absl/synchronization/internal/stdcpp_waiter.h\"\n#include \"absl/synchronization/internal/win32_waiter.h\"\n\n// May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index>\n#define ABSL_WAITER_MODE_FUTEX 0\n#define ABSL_WAITER_MODE_SEM 1\n#define ABSL_WAITER_MODE_CONDVAR 2\n#define ABSL_WAITER_MODE_WIN32 3\n#define ABSL_WAITER_MODE_STDCPP 4\n\n#if defined(ABSL_FORCE_WAITER_MODE)\n#define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE\n#elif defined(ABSL_INTERNAL_HAVE_WIN32_WAITER)\n#define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32\n#elif defined(ABSL_INTERNAL_HAVE_FUTEX_WAITER)\n#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX\n#elif defined(ABSL_INTERNAL_HAVE_SEM_WAITER)\n#define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM\n#elif defined(ABSL_INTERNAL_HAVE_PTHREAD_WAITER)\n#define ABSL_WAITER_MODE ABSL_WAITER_MODE_CONDVAR\n#elif defined(ABSL_INTERNAL_HAVE_STDCPP_WAITER)\n#define ABSL_WAITER_MODE ABSL_WAITER_MODE_STDCPP\n#else\n#error ABSL_WAITER_MODE is undefined\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n#if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX\nusing Waiter = FutexWaiter;\n#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM\nusing Waiter = SemWaiter;\n#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR\nusing Waiter = PthreadWaiter;\n#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32\nusing Waiter = Win32Waiter;\n#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_STDCPP\nusing Waiter = StdcppWaiter;\n#endif\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_\n"
  },
  {
    "path": "absl/synchronization/internal/waiter_base.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/waiter_base.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/thread_identity.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nvoid WaiterBase::MaybeBecomeIdle() {\n  base_internal::ThreadIdentity *identity =\n      base_internal::CurrentThreadIdentityIfPresent();\n  assert(identity != nullptr);\n  const bool is_idle = identity->is_idle.load(std::memory_order_relaxed);\n  const int ticker = identity->ticker.load(std::memory_order_relaxed);\n  const int wait_start = identity->wait_start.load(std::memory_order_relaxed);\n  if (!is_idle && ticker - wait_start > kIdlePeriods) {\n    identity->is_idle.store(true, std::memory_order_relaxed);\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/internal/waiter_base.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_WAITER_BASE_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_WAITER_BASE_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n// `Waiter` is a platform specific semaphore implementation that `PerThreadSem`\n// waits on to implement blocking in `absl::Mutex`.  Implementations should\n// inherit from `WaiterCrtp` and must implement `Wait()`, `Post()`, and `Poke()`\n// as described in `WaiterBase`.  `waiter.h` selects the implementation and uses\n// static-dispatch for performance.\nclass WaiterBase {\n public:\n  WaiterBase() = default;\n\n  // Not copyable or movable\n  WaiterBase(const WaiterBase&) = delete;\n  WaiterBase& operator=(const WaiterBase&) = delete;\n\n  // Blocks the calling thread until a matching call to `Post()` or\n  // `t` has passed. Returns `true` if woken (`Post()` called),\n  // `false` on timeout.\n  //\n  // bool Wait(KernelTimeout t);\n\n  // Restart the caller of `Wait()` as with a normal semaphore.\n  //\n  // void Post();\n\n  // If anyone is waiting, wake them up temporarily and cause them to\n  // call `MaybeBecomeIdle()`. They will then return to waiting for a\n  // `Post()` or timeout.\n  //\n  // void Poke();\n\n  // Returns the name of this implementation. Used only for debugging.\n  //\n  // static constexpr char kName[];\n\n  // How many periods to remain idle before releasing resources\n#ifndef ABSL_HAVE_THREAD_SANITIZER\n  static constexpr int kIdlePeriods = 60;\n#else\n  // Memory consumption under ThreadSanitizer is a serious concern,\n  // so we release resources sooner. The value of 1 leads to 1 to 2 second\n  // delay before marking a thread as idle.\n  static constexpr int kIdlePeriods = 1;\n#endif\n\n protected:\n  static void MaybeBecomeIdle();\n};\n\ntemplate <typename T>\nclass WaiterCrtp : public WaiterBase {\n public:\n  // Returns the Waiter associated with the identity.\n  static T* GetWaiter(base_internal::ThreadIdentity* identity) {\n    static_assert(\n        sizeof(T) <= sizeof(base_internal::ThreadIdentity::WaiterState),\n        \"Insufficient space for Waiter\");\n    return reinterpret_cast<T*>(identity->waiter_state.data);\n  }\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_BASE_H_\n"
  },
  {
    "path": "absl/synchronization/internal/waiter_test.cc",
    "content": "// Copyright 2023 The Abseil Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/waiter.h\"\n\n#include <ctime>\n#include <iostream>\n#include <ostream>\n\n#include \"absl/base/config.h\"\n#include \"absl/random/random.h\"\n#include \"absl/synchronization/internal/create_thread_identity.h\"\n#include \"absl/synchronization/internal/futex_waiter.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/pthread_waiter.h\"\n#include \"absl/synchronization/internal/sem_waiter.h\"\n#include \"absl/synchronization/internal/stdcpp_waiter.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/internal/win32_waiter.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n#include \"gtest/gtest.h\"\n\n// Test go/btm support by randomizing the value of clock_gettime() for\n// CLOCK_MONOTONIC. This works by overriding a weak symbol in glibc.\n// We should be resistant to this randomization when !SupportsSteadyClock().\n#if defined(__GOOGLE_GRTE_VERSION__) &&      \\\n    !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \\\n    !defined(ABSL_HAVE_MEMORY_SANITIZER) &&  \\\n    !defined(ABSL_HAVE_THREAD_SANITIZER)\nextern \"C\" int __clock_gettime(clockid_t c, struct timespec* ts);\n\nextern \"C\" int clock_gettime(clockid_t c, struct timespec* ts) {\n  if (c == CLOCK_MONOTONIC &&\n      !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) {\n    thread_local absl::BitGen gen;  // NOLINT\n    ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000);\n    ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000);\n    return 0;\n  }\n  return __clock_gettime(c, ts);\n}\n#endif\n\nnamespace {\n\nTEST(Waiter, PrintPlatformImplementation) {\n  // Allows us to verify that the platform is using the expected implementation.\n  std::cout << absl::synchronization_internal::Waiter::kName << std::endl;\n}\n\ntemplate <typename T>\nclass WaiterTest : public ::testing::Test {\n public:\n  // Waiter implementations assume that a ThreadIdentity has already been\n  // created.\n  WaiterTest() {\n    absl::synchronization_internal::GetOrCreateCurrentThreadIdentity();\n  }\n};\n\nTYPED_TEST_SUITE_P(WaiterTest);\n\nabsl::Duration WithTolerance(absl::Duration d) { return d * 0.95; }\n\nTYPED_TEST_P(WaiterTest, WaitNoTimeout) {\n  absl::synchronization_internal::ThreadPool tp(1);\n  TypeParam waiter;\n  tp.Schedule([&]() {\n    // Include some `Poke()` calls to ensure they don't cause `waiter` to return\n    // from `Wait()`.\n    waiter.Poke();\n    absl::SleepFor(absl::Seconds(1));\n    waiter.Poke();\n    absl::SleepFor(absl::Seconds(1));\n    waiter.Post();\n  });\n  absl::Time start = absl::Now();\n  EXPECT_TRUE(\n      waiter.Wait(absl::synchronization_internal::KernelTimeout::Never()));\n  absl::Duration waited = absl::Now() - start;\n  EXPECT_GE(waited, WithTolerance(absl::Seconds(2)));\n}\n\nTYPED_TEST_P(WaiterTest, WaitDurationWoken) {\n  absl::synchronization_internal::ThreadPool tp(1);\n  TypeParam waiter;\n  tp.Schedule([&]() {\n    // Include some `Poke()` calls to ensure they don't cause `waiter` to return\n    // from `Wait()`.\n    waiter.Poke();\n    absl::SleepFor(absl::Milliseconds(500));\n    waiter.Post();\n  });\n  absl::Time start = absl::Now();\n  EXPECT_TRUE(waiter.Wait(\n      absl::synchronization_internal::KernelTimeout(absl::Seconds(10))));\n  absl::Duration waited = absl::Now() - start;\n  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));\n#ifndef _MSC_VER\n  // Skip on MSVC due to flakiness.\n  EXPECT_LT(waited, absl::Seconds(2));\n#endif\n}\n\nTYPED_TEST_P(WaiterTest, WaitTimeWoken) {\n  absl::synchronization_internal::ThreadPool tp(1);\n  TypeParam waiter;\n  tp.Schedule([&]() {\n    // Include some `Poke()` calls to ensure they don't cause `waiter` to return\n    // from `Wait()`.\n    waiter.Poke();\n    absl::SleepFor(absl::Milliseconds(500));\n    waiter.Post();\n  });\n  absl::Time start = absl::Now();\n  EXPECT_TRUE(waiter.Wait(absl::synchronization_internal::KernelTimeout(\n      start + absl::Seconds(10))));\n  absl::Duration waited = absl::Now() - start;\n  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));\n  #ifndef _MSC_VER\n    // Skip on MSVC due to flakiness.\n    EXPECT_LT(waited, absl::Seconds(2));\n  #endif\n}\n\nTYPED_TEST_P(WaiterTest, WaitDurationReached) {\n  TypeParam waiter;\n  absl::Time start = absl::Now();\n  EXPECT_FALSE(waiter.Wait(\n      absl::synchronization_internal::KernelTimeout(absl::Milliseconds(500))));\n  absl::Duration waited = absl::Now() - start;\n  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));\n  #ifndef _MSC_VER\n    // Skip on MSVC due to flakiness.\n    EXPECT_LT(waited, absl::Seconds(1));\n  #endif\n}\n\nTYPED_TEST_P(WaiterTest, WaitTimeReached) {\n  TypeParam waiter;\n  absl::Time start = absl::Now();\n  EXPECT_FALSE(waiter.Wait(absl::synchronization_internal::KernelTimeout(\n      start + absl::Milliseconds(500))));\n  absl::Duration waited = absl::Now() - start;\n  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));\n  #ifndef _MSC_VER\n    // Skip on MSVC due to flakiness.\n    EXPECT_LT(waited, absl::Seconds(1));\n  #endif\n}\n\nREGISTER_TYPED_TEST_SUITE_P(WaiterTest,\n                            WaitNoTimeout,\n                            WaitDurationWoken,\n                            WaitTimeWoken,\n                            WaitDurationReached,\n                            WaitTimeReached);\n\n#ifdef ABSL_INTERNAL_HAVE_FUTEX_WAITER\nINSTANTIATE_TYPED_TEST_SUITE_P(Futex, WaiterTest,\n                               absl::synchronization_internal::FutexWaiter);\n#endif\n#ifdef ABSL_INTERNAL_HAVE_PTHREAD_WAITER\nINSTANTIATE_TYPED_TEST_SUITE_P(Pthread, WaiterTest,\n                               absl::synchronization_internal::PthreadWaiter);\n#endif\n#ifdef ABSL_INTERNAL_HAVE_SEM_WAITER\nINSTANTIATE_TYPED_TEST_SUITE_P(Sem, WaiterTest,\n                               absl::synchronization_internal::SemWaiter);\n#endif\n#ifdef ABSL_INTERNAL_HAVE_WIN32_WAITER\nINSTANTIATE_TYPED_TEST_SUITE_P(Win32, WaiterTest,\n                               absl::synchronization_internal::Win32Waiter);\n#endif\n#ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER\nINSTANTIATE_TYPED_TEST_SUITE_P(Stdcpp, WaiterTest,\n                               absl::synchronization_internal::StdcppWaiter);\n#endif\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/internal/win32_waiter.cc",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/internal/win32_waiter.h\"\n\n#ifdef ABSL_INTERNAL_HAVE_WIN32_WAITER\n\n#include <windows.h>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\nclass Win32Waiter::WinHelper {\n public:\n  static SRWLOCK *GetLock(Win32Waiter *w) {\n    return reinterpret_cast<SRWLOCK *>(&w->mu_storage_);\n  }\n\n  static CONDITION_VARIABLE *GetCond(Win32Waiter *w) {\n    return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_);\n  }\n\n  static_assert(sizeof(SRWLOCK) == sizeof(void *),\n                \"`mu_storage_` does not have the same size as SRWLOCK\");\n  static_assert(alignof(SRWLOCK) == alignof(void *),\n                \"`mu_storage_` does not have the same alignment as SRWLOCK\");\n\n  static_assert(sizeof(CONDITION_VARIABLE) == sizeof(void *),\n                \"`ABSL_CONDITION_VARIABLE_STORAGE` does not have the same size \"\n                \"as `CONDITION_VARIABLE`\");\n  static_assert(\n      alignof(CONDITION_VARIABLE) == alignof(void *),\n      \"`cv_storage_` does not have the same alignment as `CONDITION_VARIABLE`\");\n\n  // The SRWLOCK and CONDITION_VARIABLE types must be trivially constructible\n  // and destructible because we never call their constructors or destructors.\n  static_assert(std::is_trivially_constructible<SRWLOCK>::value,\n                \"The `SRWLOCK` type must be trivially constructible\");\n  static_assert(\n      std::is_trivially_constructible<CONDITION_VARIABLE>::value,\n      \"The `CONDITION_VARIABLE` type must be trivially constructible\");\n  static_assert(std::is_trivially_destructible<SRWLOCK>::value,\n                \"The `SRWLOCK` type must be trivially destructible\");\n  static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value,\n                \"The `CONDITION_VARIABLE` type must be trivially destructible\");\n};\n\nclass LockHolder {\n public:\n  explicit LockHolder(SRWLOCK* mu) : mu_(mu) {\n    AcquireSRWLockExclusive(mu_);\n  }\n\n  LockHolder(const LockHolder&) = delete;\n  LockHolder& operator=(const LockHolder&) = delete;\n\n  ~LockHolder() {\n    ReleaseSRWLockExclusive(mu_);\n  }\n\n private:\n  SRWLOCK* mu_;\n};\n\nWin32Waiter::Win32Waiter() {\n  auto *mu = ::new (static_cast<void *>(&mu_storage_)) SRWLOCK;\n  auto *cv = ::new (static_cast<void *>(&cv_storage_)) CONDITION_VARIABLE;\n  InitializeSRWLock(mu);\n  InitializeConditionVariable(cv);\n  waiter_count_ = 0;\n  wakeup_count_ = 0;\n}\n\nbool Win32Waiter::Wait(KernelTimeout t) {\n  SRWLOCK *mu = WinHelper::GetLock(this);\n  CONDITION_VARIABLE *cv = WinHelper::GetCond(this);\n\n  LockHolder h(mu);\n  ++waiter_count_;\n\n  // Loop until we find a wakeup to consume or timeout.\n  // Note that, since the thread ticker is just reset, we don't need to check\n  // whether the thread is idle on the very first pass of the loop.\n  bool first_pass = true;\n  while (wakeup_count_ == 0) {\n    if (!first_pass) MaybeBecomeIdle();\n    // No wakeups available, time to wait.\n    if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) {\n      // GetLastError() returns a Win32 DWORD, but we assign to\n      // unsigned long to simplify the ABSL_RAW_LOG case below.  The uniform\n      // initialization guarantees this is not a narrowing conversion.\n      const unsigned long err{GetLastError()};  // NOLINT(runtime/int)\n      if (err == ERROR_TIMEOUT) {\n        --waiter_count_;\n        return false;\n      } else {\n        ABSL_RAW_LOG(FATAL, \"SleepConditionVariableSRW failed: %lu\", err);\n      }\n    }\n    first_pass = false;\n  }\n  // Consume a wakeup and we're done.\n  --wakeup_count_;\n  --waiter_count_;\n  return true;\n}\n\nvoid Win32Waiter::Post() {\n  LockHolder h(WinHelper::GetLock(this));\n  ++wakeup_count_;\n  InternalCondVarPoke();\n}\n\nvoid Win32Waiter::Poke() {\n  LockHolder h(WinHelper::GetLock(this));\n  InternalCondVarPoke();\n}\n\nvoid Win32Waiter::InternalCondVarPoke() {\n  if (waiter_count_ != 0) {\n    WakeConditionVariable(WinHelper::GetCond(this));\n  }\n}\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_INTERNAL_HAVE_WIN32_WAITER\n"
  },
  {
    "path": "absl/synchronization/internal/win32_waiter.h",
    "content": "// Copyright 2023 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n#ifndef ABSL_SYNCHRONIZATION_INTERNAL_WIN32_WAITER_H_\n#define ABSL_SYNCHRONIZATION_INTERNAL_WIN32_WAITER_H_\n\n#ifdef _WIN32\n#include <sdkddkver.h>\n#endif\n\n#if defined(_WIN32) && !defined(__MINGW32__) && \\\n    _WIN32_WINNT >= _WIN32_WINNT_VISTA\n\n#include \"absl/base/config.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/waiter_base.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace synchronization_internal {\n\n#define ABSL_INTERNAL_HAVE_WIN32_WAITER 1\n\nclass Win32Waiter : public WaiterCrtp<Win32Waiter> {\n public:\n  Win32Waiter();\n\n  bool Wait(KernelTimeout t);\n  void Post();\n  void Poke();\n\n  static constexpr char kName[] = \"Win32Waiter\";\n\n private:\n  // WinHelper - Used to define utilities for accessing the lock and\n  // condition variable storage once the types are complete.\n  class WinHelper;\n\n  // REQUIRES: WinHelper::GetLock(this) must be held.\n  void InternalCondVarPoke();\n\n  // We can't include Windows.h in our headers, so we use aligned character\n  // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE.\n  // SRW locks and condition variables do not need to be explicitly destroyed.\n  // https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initializesrwlock\n  // https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with\n  alignas(void*) unsigned char mu_storage_[sizeof(void*)];\n  alignas(void*) unsigned char cv_storage_[sizeof(void*)];\n  int waiter_count_;\n  int wakeup_count_;\n};\n\n}  // namespace synchronization_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // defined(_WIN32) && !defined(__MINGW32__) &&\n        // _WIN32_WINNT >= _WIN32_WINNT_VISTA\n\n#endif  // ABSL_SYNCHRONIZATION_INTERNAL_WIN32_WAITER_H_\n"
  },
  {
    "path": "absl/synchronization/lifetime_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdlib>\n#include <thread>  // NOLINT(build/c++11), Abseil test\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/log/check.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/synchronization/notification.h\"\n\nnamespace {\n\n// A two-threaded test which checks that Mutex, CondVar, and Notification have\n// correct basic functionality.  The intent is to establish that they\n// function correctly in various phases of construction and destruction.\n//\n// Thread one acquires a lock on 'mutex', wakes thread two via 'notification',\n// then waits for 'state' to be set, as signalled by 'condvar'.\n//\n// Thread two waits on 'notification', then sets 'state' inside the 'mutex',\n// signalling the change via 'condvar'.\n//\n// These tests use CHECK to validate invariants, rather than EXPECT or ASSERT\n// from gUnit, because we need to invoke them during global destructors, when\n// gUnit teardown would have already begun.\nvoid ThreadOne(absl::Mutex* mutex, absl::CondVar* condvar,\n               absl::Notification* notification, bool* state) {\n  // Test that the notification is in a valid initial state.\n  CHECK(!notification->HasBeenNotified()) << \"invalid Notification\";\n  CHECK(!*state) << \"*state not initialized\";\n\n  {\n    absl::MutexLock lock(*mutex);\n\n    notification->Notify();\n    CHECK(notification->HasBeenNotified()) << \"invalid Notification\";\n\n    while (*state == false) {\n      condvar->Wait(mutex);\n    }\n  }\n}\n\nvoid ThreadTwo(absl::Mutex* mutex, absl::CondVar* condvar,\n               absl::Notification* notification, bool* state) {\n  CHECK(!*state) << \"*state not initialized\";\n\n  // Wake thread one\n  notification->WaitForNotification();\n  CHECK(notification->HasBeenNotified()) << \"invalid Notification\";\n  {\n    absl::MutexLock lock(*mutex);\n    *state = true;\n    condvar->Signal();\n  }\n}\n\n// Launch thread 1 and thread 2, and block on their completion.\n// If any of 'mutex', 'condvar', or 'notification' is nullptr, use a locally\n// constructed instance instead.\nvoid RunTests(absl::Mutex* mutex, absl::CondVar* condvar) {\n  absl::Mutex default_mutex;\n  absl::CondVar default_condvar;\n  absl::Notification notification;\n  if (!mutex) {\n    mutex = &default_mutex;\n  }\n  if (!condvar) {\n    condvar = &default_condvar;\n  }\n  bool state = false;\n  std::thread thread_one(ThreadOne, mutex, condvar, &notification, &state);\n  std::thread thread_two(ThreadTwo, mutex, condvar, &notification, &state);\n  thread_one.join();\n  thread_two.join();\n}\n\nvoid TestLocals() {\n  absl::Mutex mutex;\n  absl::CondVar condvar;\n  RunTests(&mutex, &condvar);\n}\n\n// Normal kConstInit usage\nABSL_CONST_INIT absl::Mutex const_init_mutex(absl::kConstInit);\nvoid TestConstInitGlobal() { RunTests(&const_init_mutex, nullptr); }\n\n// Global variables during start and termination\n//\n// In a translation unit, static storage duration variables are initialized in\n// the order of their definitions, and destroyed in the reverse order of their\n// definitions.  We can use this to arrange for tests to be run on these objects\n// before they are created, and after they are destroyed.\n\nusing Function = void (*)();\n\nclass OnConstruction {\n public:\n  explicit OnConstruction(Function fn) { fn(); }\n};\n\nclass OnDestruction {\n public:\n  explicit OnDestruction(Function fn) : fn_(fn) {}\n  ~OnDestruction() { fn_(); }\n private:\n  Function fn_;\n};\n\n// These tests require that the compiler correctly supports C++11 constant\n// initialization... but MSVC has a known regression (since v19.10) till v19.25:\n// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html\n#if defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER < 1925)\n// kConstInit\n// Test early usage.  (Declaration comes first; definitions must appear after\n// the test runner.)\nextern absl::Mutex early_const_init_mutex;\n// (Normally I'd write this +[], to make the cast-to-function-pointer explicit,\n// but in some MSVC setups we support, lambdas provide conversion operators to\n// different flavors of function pointers, making this trick ambiguous.)\nOnConstruction test_early_const_init([] {\n  RunTests(&early_const_init_mutex, nullptr);\n});\n// This definition appears before test_early_const_init, but it should be\n// initialized first (due to constant initialization).  Test that the object\n// actually works when constructed this way.\nABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);\n\n// Furthermore, test that the const-init c'tor doesn't stomp over the state of\n// a Mutex.  Really, this is a test that the platform under test correctly\n// supports C++11 constant initialization.  (The constant-initialization\n// constructors of globals \"happen at link time\"; memory is pre-initialized,\n// before the constructors of either grab_lock or check_still_locked are run.)\nextern absl::Mutex const_init_sanity_mutex;\nOnConstruction grab_lock([]() ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  const_init_sanity_mutex.lock();\n});\nABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);\nOnConstruction check_still_locked([]() ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  const_init_sanity_mutex.AssertHeld();\n  const_init_sanity_mutex.unlock();\n});\n#endif  // defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900)\n\n// Test shutdown usage.  (Declarations come first; definitions must appear after\n// the test runner.)\nextern absl::Mutex late_const_init_mutex;\n// OnDestruction is being used here as a global variable, even though it has a\n// non-trivial destructor.  This is against the style guide.  We're violating\n// that rule here to check that the exception we allow for kConstInit is safe.\n// NOLINTNEXTLINE\nOnDestruction test_late_const_init([] {\n  RunTests(&late_const_init_mutex, nullptr);\n});\nABSL_CONST_INIT absl::Mutex late_const_init_mutex(absl::kConstInit);\n\n}  // namespace\n\nint main() {\n  TestLocals();\n  TestConstInitGlobal();\n  // Explicitly call exit(0) here, to make it clear that we intend for the\n  // above global object destructors to run.\n  std::exit(0);\n}\n"
  },
  {
    "path": "absl/synchronization/mutex.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/mutex.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#ifdef ERROR\n#undef ERROR\n#endif\n#else\n#include <fcntl.h>\n#include <pthread.h>\n#include <sched.h>\n#include <sys/time.h>\n#endif\n\n#include <assert.h>\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <algorithm>\n#include <atomic>\n#include <cstddef>\n#include <cstdlib>\n#include <cstring>\n#include <thread>  // NOLINT(build/c++11)\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/call_once.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/dynamic_annotations.h\"\n#include \"absl/base/internal/atomic_hook.h\"\n#include \"absl/base/internal/cycleclock.h\"\n#include \"absl/base/internal/hide_ptr.h\"\n#include \"absl/base/internal/low_level_alloc.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/internal/tsan_mutex_interface.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/debugging/stacktrace.h\"\n#include \"absl/debugging/symbolize.h\"\n#include \"absl/synchronization/internal/graphcycles.h\"\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n#include \"absl/time/time.h\"\n\nusing absl::base_internal::CurrentThreadIdentityIfPresent;\nusing absl::base_internal::CycleClock;\nusing absl::base_internal::PerThreadSynch;\nusing absl::base_internal::SchedulingGuard;\nusing absl::base_internal::ThreadIdentity;\nusing absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;\nusing absl::synchronization_internal::GraphCycles;\nusing absl::synchronization_internal::GraphId;\nusing absl::synchronization_internal::InvalidGraphId;\nusing absl::synchronization_internal::KernelTimeout;\nusing absl::synchronization_internal::PerThreadSem;\n\nextern \"C\" {\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)() {\n  std::this_thread::yield();\n}\n}  // extern \"C\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\n#if defined(ABSL_HAVE_THREAD_SANITIZER)\nconstexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore;\n#else\nconstexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort;\n#endif\n\nABSL_CONST_INIT std::atomic<OnDeadlockCycle> synch_deadlock_detection(\n    kDeadlockDetectionDefault);\nABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);\n\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\nabsl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>\n    submit_profile_data;\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(\n    const char* msg, const void* obj, int64_t wait_cycles)>\n    mutex_tracer;\nABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES\nabsl::base_internal::AtomicHook<void (*)(const char* msg, const void* cv)>\n    cond_var_tracer;\n\n}  // namespace\n\nstatic inline bool EvalConditionAnnotated(const Condition* cond, Mutex* mu,\n                                          bool locking, bool trylock,\n                                          bool read_lock);\n\nvoid RegisterMutexProfiler(void (*fn)(int64_t wait_cycles)) {\n  submit_profile_data.Store(fn);\n}\n\nvoid RegisterMutexTracer(void (*fn)(const char* msg, const void* obj,\n                                    int64_t wait_cycles)) {\n  mutex_tracer.Store(fn);\n}\n\nvoid RegisterCondVarTracer(void (*fn)(const char* msg, const void* cv)) {\n  cond_var_tracer.Store(fn);\n}\n\nnamespace {\n// Represents the strategy for spin and yield.\n// See the comment in GetMutexGlobals() for more information.\nenum DelayMode { AGGRESSIVE, GENTLE };\n\nstruct ABSL_CACHELINE_ALIGNED MutexGlobals {\n  absl::once_flag once;\n  // Note: this variable is initialized separately in Mutex::LockSlow,\n  // so that Mutex::Lock does not have a stack frame in optimized build.\n  std::atomic<int> spinloop_iterations{0};\n  int32_t mutex_sleep_spins[2] = {};\n  absl::Duration mutex_sleep_time;\n};\n\nABSL_CONST_INIT static MutexGlobals globals;\n\nabsl::Duration MeasureTimeToYield() {\n  absl::Time before = absl::Now();\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();\n  return absl::Now() - before;\n}\n\nconst MutexGlobals& GetMutexGlobals() {\n  absl::base_internal::LowLevelCallOnce(&globals.once, [&]() {\n    if (absl::base_internal::NumCPUs() > 1) {\n      // If the mode is aggressive then spin many times before yielding.\n      // If the mode is gentle then spin only a few times before yielding.\n      // Aggressive spinning is used to ensure that an Unlock() call,\n      // which must get the spin lock for any thread to make progress gets it\n      // without undue delay.\n      globals.mutex_sleep_spins[AGGRESSIVE] = 5000;\n      globals.mutex_sleep_spins[GENTLE] = 250;\n      globals.mutex_sleep_time = absl::Microseconds(10);\n    } else {\n      // If this a uniprocessor, only yield/sleep. Real-time threads are often\n      // unable to yield, so the sleep time needs to be long enough to keep\n      // the calling thread asleep until scheduling happens.\n      globals.mutex_sleep_spins[AGGRESSIVE] = 0;\n      globals.mutex_sleep_spins[GENTLE] = 0;\n      globals.mutex_sleep_time = MeasureTimeToYield() * 5;\n      globals.mutex_sleep_time =\n          std::min(globals.mutex_sleep_time, absl::Milliseconds(1));\n      globals.mutex_sleep_time =\n          std::max(globals.mutex_sleep_time, absl::Microseconds(10));\n    }\n  });\n  return globals;\n}\n}  // namespace\n\nnamespace synchronization_internal {\n// Returns the Mutex delay on iteration `c` depending on the given `mode`.\n// The returned value should be used as `c` for the next call to `MutexDelay`.\nint MutexDelay(int32_t c, int mode) {\n  const int32_t limit = GetMutexGlobals().mutex_sleep_spins[mode];\n  const absl::Duration sleep_time = GetMutexGlobals().mutex_sleep_time;\n  if (c < limit) {\n    // Spin.\n    c++;\n  } else {\n    SchedulingGuard::ScopedEnable enable_rescheduling;\n    ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);\n    if (c == limit) {\n      // Yield once.\n      ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();\n      c++;\n    } else {\n      // Then wait.\n      absl::SleepFor(sleep_time);\n      c = 0;\n    }\n    ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);\n  }\n  return c;\n}\n}  // namespace synchronization_internal\n\n// --------------------------Generic atomic ops\n// Ensure that \"(*pv & bits) == bits\" by doing an atomic update of \"*pv\" to\n// \"*pv | bits\" if necessary.  Wait until (*pv & wait_until_clear)==0\n// before making any change.\n// Returns true if bits were previously unset and set by the call.\n// This is used to set flags in mutex and condition variable words.\nstatic bool AtomicSetBits(std::atomic<intptr_t>* pv, intptr_t bits,\n                          intptr_t wait_until_clear) {\n  for (;;) {\n    intptr_t v = pv->load(std::memory_order_relaxed);\n    if ((v & bits) == bits) {\n      return false;\n    }\n    if ((v & wait_until_clear) != 0) {\n      continue;\n    }\n    if (pv->compare_exchange_weak(v, v | bits, std::memory_order_release,\n                                  std::memory_order_relaxed)) {\n      return true;\n    }\n  }\n}\n\n//------------------------------------------------------------------\n\n// Data for doing deadlock detection.\nABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu(\n    base_internal::SCHEDULE_KERNEL_ONLY);\n\n// Graph used to detect deadlocks.\nABSL_CONST_INIT static GraphCycles* deadlock_graph\n    ABSL_GUARDED_BY(deadlock_graph_mu) ABSL_PT_GUARDED_BY(deadlock_graph_mu);\n\n//------------------------------------------------------------------\n// An event mechanism for debugging mutex use.\n// It also allows mutexes to be given names for those who can't handle\n// addresses, and instead like to give their data structures names like\n// \"Henry\", \"Fido\", or \"Rupert IV, King of Yondavia\".\n\nnamespace {  // to prevent name pollution\nenum {       // Mutex and CondVar events passed as \"ev\" to PostSynchEvent\n             // Mutex events\n  SYNCH_EV_TRYLOCK_SUCCESS,\n  SYNCH_EV_TRYLOCK_FAILED,\n  SYNCH_EV_READERTRYLOCK_SUCCESS,\n  SYNCH_EV_READERTRYLOCK_FAILED,\n  SYNCH_EV_LOCK,\n  SYNCH_EV_LOCK_RETURNING,\n  SYNCH_EV_READERLOCK,\n  SYNCH_EV_READERLOCK_RETURNING,\n  SYNCH_EV_UNLOCK,\n  SYNCH_EV_READERUNLOCK,\n\n  // CondVar events\n  SYNCH_EV_WAIT,\n  SYNCH_EV_WAIT_RETURNING,\n  SYNCH_EV_SIGNAL,\n  SYNCH_EV_SIGNALALL,\n};\n\nenum {                    // Event flags\n  SYNCH_F_R = 0x01,       // reader event\n  SYNCH_F_LCK = 0x02,     // PostSynchEvent called with mutex held\n  SYNCH_F_TRY = 0x04,     // TryLock or ReaderTryLock\n  SYNCH_F_UNLOCK = 0x08,  // Unlock or ReaderUnlock\n\n  SYNCH_F_LCK_W = SYNCH_F_LCK,\n  SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R,\n};\n}  // anonymous namespace\n\n// Properties of the events.\nstatic const struct {\n  int flags;\n  const char* msg;\n} event_properties[] = {\n    {SYNCH_F_LCK_W | SYNCH_F_TRY, \"TryLock succeeded \"},\n    {0, \"TryLock failed \"},\n    {SYNCH_F_LCK_R | SYNCH_F_TRY, \"ReaderTryLock succeeded \"},\n    {0, \"ReaderTryLock failed \"},\n    {0, \"Lock blocking \"},\n    {SYNCH_F_LCK_W, \"Lock returning \"},\n    {0, \"ReaderLock blocking \"},\n    {SYNCH_F_LCK_R, \"ReaderLock returning \"},\n    {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, \"Unlock \"},\n    {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, \"ReaderUnlock \"},\n    {0, \"Wait on \"},\n    {0, \"Wait unblocked \"},\n    {0, \"Signal on \"},\n    {0, \"SignalAll on \"},\n};\n\nABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu(\n    base_internal::SCHEDULE_KERNEL_ONLY);\n\n// Hash table size; should be prime > 2.\n// Can't be too small, as it's used for deadlock detection information.\nstatic constexpr uint32_t kNSynchEvent = 1031;\n\nstatic struct SynchEvent {  // this is a trivial hash table for the events\n  // struct is freed when refcount reaches 0\n  int refcount ABSL_GUARDED_BY(synch_event_mu);\n\n  // buckets have linear, 0-terminated  chains\n  SynchEvent* next ABSL_GUARDED_BY(synch_event_mu);\n\n  // Constant after initialization\n  uintptr_t masked_addr;  // object at this address is called \"name\"\n\n  // No explicit synchronization used.  Instead we assume that the\n  // client who enables/disables invariants/logging on a Mutex does so\n  // while the Mutex is not being concurrently accessed by others.\n  void (*invariant)(void* arg);  // called on each event\n  void* arg;                     // first arg to (*invariant)()\n  bool log;                      // logging turned on\n\n  // Constant after initialization\n  char name[1];  // actually longer---NUL-terminated string\n}* synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);\n\n// Ensure that the object at \"addr\" has a SynchEvent struct associated with it,\n// set \"bits\" in the word there (waiting until lockbit is clear before doing\n// so), and return a refcounted reference that will remain valid until\n// UnrefSynchEvent() is called.  If a new SynchEvent is allocated,\n// the string name is copied into it.\n// When used with a mutex, the caller should also ensure that kMuEvent\n// is set in the mutex word, and similarly for condition variables and kCVEvent.\nstatic SynchEvent* EnsureSynchEvent(std::atomic<intptr_t>* addr,\n                                    const char* name, intptr_t bits,\n                                    intptr_t lockbit) {\n  uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;\n  synch_event_mu.lock();\n  // When a Mutex/CondVar is destroyed, we don't remove the associated\n  // SynchEvent to keep destructors empty in release builds for performance\n  // reasons. If the current call is the first to set bits (kMuEvent/kCVEvent),\n  // we don't look up the existing even because (if it exists, it must be for\n  // the previous Mutex/CondVar that existed at the same address).\n  // The leaking events must not be a problem for tests, which should create\n  // bounded amount of events. And debug logging is not supposed to be enabled\n  // in production. However, if it's accidentally enabled, or briefly enabled\n  // for some debugging, we don't want to crash the program. Instead we drop\n  // all events, if we accumulated too many of them. Size of a single event\n  // is ~48 bytes, so 100K events is ~5 MB.\n  // Additionally we could delete the old event for the same address,\n  // but it would require a better hashmap (if we accumulate too many events,\n  // linked lists will grow and traversing them will be very slow).\n  constexpr size_t kMaxSynchEventCount = 100 << 10;\n  // Total number of live synch events.\n  static size_t synch_event_count ABSL_GUARDED_BY(synch_event_mu);\n  if (++synch_event_count > kMaxSynchEventCount) {\n    synch_event_count = 0;\n    ABSL_RAW_LOG(ERROR,\n                 \"Accumulated %zu Mutex debug objects. If you see this\"\n                 \" in production, it may mean that the production code\"\n                 \" accidentally calls \"\n                 \"Mutex/CondVar::EnableDebugLog/EnableInvariantDebugging.\",\n                 kMaxSynchEventCount);\n    for (auto*& head : synch_event) {\n      for (auto* e = head; e != nullptr;) {\n        SynchEvent* next = e->next;\n        if (--(e->refcount) == 0) {\n          base_internal::LowLevelAlloc::Free(e);\n        }\n        e = next;\n      }\n      head = nullptr;\n    }\n  }\n  SynchEvent* e = nullptr;\n  if (!AtomicSetBits(addr, bits, lockbit)) {\n    for (e = synch_event[h];\n         e != nullptr && e->masked_addr != base_internal::HidePtr(addr);\n         e = e->next) {\n    }\n  }\n  if (e == nullptr) {  // no SynchEvent struct found; make one.\n    if (name == nullptr) {\n      name = \"\";\n    }\n    size_t l = strlen(name);\n    e = reinterpret_cast<SynchEvent*>(\n        base_internal::LowLevelAlloc::Alloc(sizeof(*e) + l));\n    e->refcount = 2;  // one for return value, one for linked list\n    e->masked_addr = base_internal::HidePtr(addr);\n    e->invariant = nullptr;\n    e->arg = nullptr;\n    e->log = false;\n    strcpy(e->name, name);  // NOLINT(runtime/printf)\n    e->next = synch_event[h];\n    synch_event[h] = e;\n  } else {\n    e->refcount++;  // for return value\n  }\n  synch_event_mu.unlock();\n  return e;\n}\n\n// Decrement the reference count of *e, or do nothing if e==null.\nstatic void UnrefSynchEvent(SynchEvent* e) {\n  if (e != nullptr) {\n    synch_event_mu.lock();\n    bool del = (--(e->refcount) == 0);\n    synch_event_mu.unlock();\n    if (del) {\n      base_internal::LowLevelAlloc::Free(e);\n    }\n  }\n}\n\n// Return a refcounted reference to the SynchEvent of the object at address\n// \"addr\", if any.  The pointer returned is valid until the UnrefSynchEvent() is\n// called.\nstatic SynchEvent* GetSynchEvent(const void* addr) {\n  uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;\n  SynchEvent* e;\n  synch_event_mu.lock();\n  for (e = synch_event[h];\n       e != nullptr && e->masked_addr != base_internal::HidePtr(addr);\n       e = e->next) {\n  }\n  if (e != nullptr) {\n    e->refcount++;\n  }\n  synch_event_mu.unlock();\n  return e;\n}\n\n// Called when an event \"ev\" occurs on a Mutex of CondVar \"obj\"\n// if event recording is on\nstatic void PostSynchEvent(void* obj, int ev) {\n  SynchEvent* e = GetSynchEvent(obj);\n  // logging is on if event recording is on and either there's no event struct,\n  // or it explicitly says to log\n  if (e == nullptr || e->log) {\n    void* pcs[40];\n    int n = absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 1);\n    // A buffer with enough space for the ASCII for all the PCs, even on a\n    // 64-bit machine.\n    char buffer[ABSL_ARRAYSIZE(pcs) * 24];\n    int pos = snprintf(buffer, sizeof(buffer), \" @\");\n    for (int i = 0; i != n; i++) {\n      int b = snprintf(&buffer[pos], sizeof(buffer) - static_cast<size_t>(pos),\n                       \" %p\", pcs[i]);\n      if (b < 0 ||\n          static_cast<size_t>(b) >= sizeof(buffer) - static_cast<size_t>(pos)) {\n        break;\n      }\n      pos += b;\n    }\n    ABSL_RAW_LOG(INFO, \"%s%p %s %s\", event_properties[ev].msg, obj,\n                 (e == nullptr ? \"\" : e->name), buffer);\n  }\n  const int flags = event_properties[ev].flags;\n  if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) {\n    // Calling the invariant as is causes problems under ThreadSanitizer.\n    // We are currently inside of Mutex Lock/Unlock and are ignoring all\n    // memory accesses and synchronization. If the invariant transitively\n    // synchronizes something else and we ignore the synchronization, we will\n    // get false positive race reports later.\n    // Reuse EvalConditionAnnotated to properly call into user code.\n    struct local {\n      static bool pred(SynchEvent* ev) {\n        (*ev->invariant)(ev->arg);\n        return false;\n      }\n    };\n    Condition cond(&local::pred, e);\n    Mutex* mu = static_cast<Mutex*>(obj);\n    const bool locking = (flags & SYNCH_F_UNLOCK) == 0;\n    const bool trylock = (flags & SYNCH_F_TRY) != 0;\n    const bool read_lock = (flags & SYNCH_F_R) != 0;\n    EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock);\n  }\n  UnrefSynchEvent(e);\n}\n\n//------------------------------------------------------------------\n\n// The SynchWaitParams struct encapsulates the way in which a thread is waiting:\n// whether it has a timeout, the condition, exclusive/shared, and whether a\n// condition variable wait has an associated Mutex (as opposed to another\n// type of lock).  It also points to the PerThreadSynch struct of its thread.\n// cv_word tells Enqueue() to enqueue on a CondVar using CondVarEnqueue().\n//\n// This structure is held on the stack rather than directly in\n// PerThreadSynch because a thread can be waiting on multiple Mutexes if,\n// while waiting on one Mutex, the implementation calls a client callback\n// (such as a Condition function) that acquires another Mutex. We don't\n// strictly need to allow this, but programmers become confused if we do not\n// allow them to use functions such a LOG() within Condition functions.  The\n// PerThreadSynch struct points at the most recent SynchWaitParams struct when\n// the thread is on a Mutex's waiter queue.\nstruct SynchWaitParams {\n  SynchWaitParams(Mutex::MuHow how_arg, const Condition* cond_arg,\n                  KernelTimeout timeout_arg, Mutex* cvmu_arg,\n                  PerThreadSynch* thread_arg,\n                  std::atomic<intptr_t>* cv_word_arg)\n      : how(how_arg),\n        cond(cond_arg),\n        timeout(timeout_arg),\n        cvmu(cvmu_arg),\n        thread(thread_arg),\n        cv_word(cv_word_arg),\n        contention_start_cycles(CycleClock::Now()),\n        should_submit_contention_data(false) {}\n\n  const Mutex::MuHow how;  // How this thread needs to wait.\n  const Condition* cond;   // The condition that this thread is waiting for.\n                           // In Mutex, this field is set to zero if a timeout\n                           // expires.\n  KernelTimeout timeout;   // timeout expiry---absolute time\n                           // In Mutex, this field is set to zero if a timeout\n                           // expires.\n  Mutex* const cvmu;       // used for transfer from cond var to mutex\n  PerThreadSynch* const thread;  // thread that is waiting\n\n  // If not null, thread should be enqueued on the CondVar whose state\n  // word is cv_word instead of queueing normally on the Mutex.\n  std::atomic<intptr_t>* cv_word;\n\n  int64_t contention_start_cycles;  // Time (in cycles) when this thread started\n                                    // to contend for the mutex.\n  bool should_submit_contention_data;\n};\n\nstruct SynchLocksHeld {\n  int n;          // number of valid entries in locks[]\n  bool overflow;  // true iff we overflowed the array at some point\n  struct {\n    Mutex* mu;      // lock acquired\n    int32_t count;  // times acquired\n    GraphId id;     // deadlock_graph id of acquired lock\n  } locks[40];\n  // If a thread overfills the array during deadlock detection, we\n  // continue, discarding information as needed.  If no overflow has\n  // taken place, we can provide more error checking, such as\n  // detecting when a thread releases a lock it does not hold.\n};\n\n// A sentinel value in lists that is not 0.\n// A 0 value is used to mean \"not on a list\".\nstatic PerThreadSynch* const kPerThreadSynchNull =\n    reinterpret_cast<PerThreadSynch*>(1);\n\nstatic SynchLocksHeld* LocksHeldAlloc() {\n  SynchLocksHeld* ret = reinterpret_cast<SynchLocksHeld*>(\n      base_internal::LowLevelAlloc::Alloc(sizeof(SynchLocksHeld)));\n  ret->n = 0;\n  ret->overflow = false;\n  return ret;\n}\n\n// Return the PerThreadSynch-struct for this thread.\nstatic PerThreadSynch* Synch_GetPerThread() {\n  ThreadIdentity* identity = GetOrCreateCurrentThreadIdentity();\n  return &identity->per_thread_synch;\n}\n\nstatic PerThreadSynch* Synch_GetPerThreadAnnotated(Mutex* mu) {\n  if (mu) {\n    ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);\n  }\n  PerThreadSynch* w = Synch_GetPerThread();\n  if (mu) {\n    ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);\n  }\n  return w;\n}\n\nstatic SynchLocksHeld* Synch_GetAllLocks() {\n  PerThreadSynch* s = Synch_GetPerThread();\n  if (s->all_locks == nullptr) {\n    s->all_locks = LocksHeldAlloc();  // Freed by ReclaimThreadIdentity.\n  }\n  return s->all_locks;\n}\n\n// Post on \"w\"'s associated PerThreadSem.\nvoid Mutex::IncrementSynchSem(Mutex* mu, PerThreadSynch* w) {\n  static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.\n  ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);\n  // We miss synchronization around passing PerThreadSynch between threads\n  // since it happens inside of the Mutex code, so we need to ignore all\n  // accesses to the object.\n  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();\n  PerThreadSem::Post(w->thread_identity());\n  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();\n  ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);\n}\n\n// Wait on \"w\"'s associated PerThreadSem; returns false if timeout expired.\nbool Mutex::DecrementSynchSem(Mutex* mu, PerThreadSynch* w, KernelTimeout t) {\n  static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.\n  ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);\n  assert(w == Synch_GetPerThread());\n  static_cast<void>(w);\n  bool res = PerThreadSem::Wait(t);\n  ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);\n  return res;\n}\n\n// We're in a fatal signal handler that hopes to use Mutex and to get\n// lucky by not deadlocking.  We try to improve its chances of success\n// by effectively disabling some of the consistency checks.  This will\n// prevent certain ABSL_RAW_CHECK() statements from being triggered when\n// re-rentry is detected.  The ABSL_RAW_CHECK() statements are those in the\n// Mutex code checking that the \"waitp\" field has not been reused.\nvoid Mutex::InternalAttemptToUseMutexInFatalSignalHandler() {\n  // Fix the per-thread state only if it exists.\n  ThreadIdentity* identity = CurrentThreadIdentityIfPresent();\n  if (identity != nullptr) {\n    identity->per_thread_synch.suppress_fatal_errors = true;\n  }\n  // Don't do deadlock detection when we are already failing.\n  synch_deadlock_detection.store(OnDeadlockCycle::kIgnore,\n                                 std::memory_order_release);\n}\n\n// --------------------------Mutexes\n\n// In the layout below, the msb of the bottom byte is currently unused.  Also,\n// the following constraints were considered in choosing the layout:\n//  o Both the debug allocator's \"uninitialized\" and \"freed\" patterns (0xab and\n//    0xcd) are illegal: reader and writer lock both held.\n//  o kMuWriter and kMuEvent should exceed kMuDesig and kMuWait, to enable the\n//    bit-twiddling trick in Mutex::Unlock().\n//  o kMuWriter / kMuReader == kMuWrWait / kMuWait,\n//    to enable the bit-twiddling trick in CheckForMutexCorruption().\nstatic const intptr_t kMuReader = 0x0001L;  // a reader holds the lock\n// There's a designated waker.\n// INVARIANT1:  there's a thread that was blocked on the mutex, is\n// no longer, yet has not yet acquired the mutex.  If there's a\n// designated waker, all threads can avoid taking the slow path in\n// unlock because the designated waker will subsequently acquire\n// the lock and wake someone.  To maintain INVARIANT1 the bit is\n// set when a thread is unblocked(INV1a), and threads that were\n// unblocked reset the bit when they either acquire or re-block (INV1b).\nstatic const intptr_t kMuDesig = 0x0002L;\nstatic const intptr_t kMuWait = 0x0004L;    // threads are waiting\nstatic const intptr_t kMuWriter = 0x0008L;  // a writer holds the lock\nstatic const intptr_t kMuEvent = 0x0010L;   // record this mutex's events\n// Runnable writer is waiting for a reader.\n// If set, new readers will not lock the mutex to avoid writer starvation.\n// Note: if a reader has higher priority than the writer, it will still lock\n// the mutex ahead of the waiting writer, but in a very inefficient manner:\n// the reader will first queue itself and block, but then the last unlocking\n// reader will wake it.\nstatic const intptr_t kMuWrWait = 0x0020L;\nstatic const intptr_t kMuSpin = 0x0040L;  // spinlock protects wait list\nstatic const intptr_t kMuLow = 0x00ffL;   // mask all mutex bits\nstatic const intptr_t kMuHigh = ~kMuLow;  // mask pointer/reader count\n\nstatic_assert((0xab & (kMuWriter | kMuReader)) == (kMuWriter | kMuReader),\n              \"The debug allocator's uninitialized pattern (0xab) must be an \"\n              \"invalid mutex state\");\nstatic_assert((0xcd & (kMuWriter | kMuReader)) == (kMuWriter | kMuReader),\n              \"The debug allocator's freed pattern (0xcd) must be an invalid \"\n              \"mutex state\");\n\n// Hack to make constant values available to gdb pretty printer\nenum {\n  kGdbMuSpin = kMuSpin,\n  kGdbMuEvent = kMuEvent,\n  kGdbMuWait = kMuWait,\n  kGdbMuWriter = kMuWriter,\n  kGdbMuDesig = kMuDesig,\n  kGdbMuWrWait = kMuWrWait,\n  kGdbMuReader = kMuReader,\n  kGdbMuLow = kMuLow,\n};\n\n// kMuWrWait implies kMuWait.\n// kMuReader and kMuWriter are mutually exclusive.\n// If kMuReader is zero, there are no readers.\n// Otherwise, if kMuWait is zero, the high order bits contain a count of the\n// number of readers.  Otherwise, the reader count is held in\n// PerThreadSynch::readers of the most recently queued waiter, again in the\n// bits above kMuLow.\nstatic const intptr_t kMuOne = 0x0100;  // a count of one reader\n\n// flags passed to Enqueue and LockSlow{,WithTimeout,Loop}\nstatic const int kMuHasBlocked = 0x01;  // already blocked (MUST == 1)\nstatic const int kMuIsCond = 0x02;      // conditional waiter (CV or Condition)\nstatic const int kMuIsFer = 0x04;       // wait morphing from a CondVar\n\nstatic_assert(PerThreadSynch::kAlignment > kMuLow,\n              \"PerThreadSynch::kAlignment must be greater than kMuLow\");\n\n// This struct contains various bitmasks to be used in\n// acquiring and releasing a mutex in a particular mode.\nstruct MuHowS {\n  // if all the bits in fast_need_zero are zero, the lock can be acquired by\n  // adding fast_add and oring fast_or.  The bit kMuDesig should be reset iff\n  // this is the designated waker.\n  intptr_t fast_need_zero;\n  intptr_t fast_or;\n  intptr_t fast_add;\n\n  intptr_t slow_need_zero;  // fast_need_zero with events (e.g. logging)\n\n  intptr_t slow_inc_need_zero;  // if all the bits in slow_inc_need_zero are\n                                // zero a reader can acquire a read share by\n                                // setting the reader bit and incrementing\n                                // the reader count (in last waiter since\n                                // we're now slow-path).  kMuWrWait be may\n                                // be ignored if we already waited once.\n};\n\nstatic const MuHowS kSharedS = {\n    // shared or read lock\n    kMuWriter | kMuWait | kMuEvent,   // fast_need_zero\n    kMuReader,                        // fast_or\n    kMuOne,                           // fast_add\n    kMuWriter | kMuWait,              // slow_need_zero\n    kMuSpin | kMuWriter | kMuWrWait,  // slow_inc_need_zero\n};\nstatic const MuHowS kExclusiveS = {\n    // exclusive or write lock\n    kMuWriter | kMuReader | kMuEvent,  // fast_need_zero\n    kMuWriter,                         // fast_or\n    0,                                 // fast_add\n    kMuWriter | kMuReader,             // slow_need_zero\n    ~static_cast<intptr_t>(0),         // slow_inc_need_zero\n};\nstatic const Mutex::MuHow kShared = &kSharedS;        // shared lock\nstatic const Mutex::MuHow kExclusive = &kExclusiveS;  // exclusive lock\n\n#ifdef NDEBUG\nstatic constexpr bool kDebugMode = false;\n#else\nstatic constexpr bool kDebugMode = true;\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE\nstatic unsigned TsanFlags(Mutex::MuHow how) {\n  return how == kShared ? __tsan_mutex_read_lock : 0;\n}\n#endif\n\n#if defined(__APPLE__) || defined(ABSL_BUILD_DLL)\n// When building a dll symbol export lists may reference the destructor\n// and want it to be an exported symbol rather than an inline function.\n// Some apple builds also do dynamic library build but don't say it explicitly.\nMutex::~Mutex() { Dtor(); }\n#endif\n\n#if !defined(NDEBUG) || defined(ABSL_HAVE_THREAD_SANITIZER) || \\\n    defined(ABSL_BUILD_DLL)\nvoid Mutex::Dtor() {\n  if (kDebugMode) {\n    this->ForgetDeadlockInfo();\n  }\n  ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static);\n}\n#endif\n\nvoid Mutex::EnableDebugLog(const char* name) {\n  // Need to disable writes here and in EnableInvariantDebugging to prevent\n  // false race reports on SynchEvent objects. TSan ignores synchronization\n  // on synch_event_mu in Lock/Unlock/etc methods due to mutex annotations,\n  // but it sees few accesses to SynchEvent in EvalConditionAnnotated.\n  // If we don't ignore accesses here, it can result in false races\n  // between EvalConditionAnnotated and SynchEvent reuse in EnsureSynchEvent.\n  ABSL_ANNOTATE_IGNORE_WRITES_BEGIN();\n  SynchEvent* e = EnsureSynchEvent(&this->mu_, name, kMuEvent, kMuSpin);\n  e->log = true;\n  UnrefSynchEvent(e);\n  // This prevents \"error: undefined symbol: absl::Mutex::~Mutex()\"\n  // in a release build (NDEBUG defined) when a test does \"#undef NDEBUG\"\n  // to use assert macro. In such case, the test does not get the dtor\n  // definition because it's supposed to be outline when NDEBUG is not defined,\n  // and this source file does not define one either because NDEBUG is defined.\n  // Since it's not possible to take address of a destructor, we move the\n  // actual destructor code into the separate Dtor function and force the\n  // compiler to emit this function even if it's inline by taking its address.\n  ABSL_ATTRIBUTE_UNUSED volatile auto dtor = &Mutex::Dtor;\n  ABSL_ANNOTATE_IGNORE_WRITES_END();\n}\n\nvoid EnableMutexInvariantDebugging(bool enabled) {\n  synch_check_invariants.store(enabled, std::memory_order_release);\n}\n\nvoid Mutex::EnableInvariantDebugging(void (*invariant)(void*), void* arg) {\n  ABSL_ANNOTATE_IGNORE_WRITES_BEGIN();\n  if (synch_check_invariants.load(std::memory_order_acquire) &&\n      invariant != nullptr) {\n    SynchEvent* e = EnsureSynchEvent(&this->mu_, nullptr, kMuEvent, kMuSpin);\n    e->invariant = invariant;\n    e->arg = arg;\n    UnrefSynchEvent(e);\n  }\n  ABSL_ANNOTATE_IGNORE_WRITES_END();\n}\n\nvoid SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) {\n  synch_deadlock_detection.store(mode, std::memory_order_release);\n}\n\n// Return true iff threads x and y are part of the same equivalence\n// class of waiters. An equivalence class is defined as the set of\n// waiters with the same condition, type of lock, and thread priority.\n//\n// Requires that x and y be waiting on the same Mutex queue.\nstatic bool MuEquivalentWaiter(PerThreadSynch* x, PerThreadSynch* y) {\n  return x->waitp->how == y->waitp->how && x->priority == y->priority &&\n         Condition::GuaranteedEqual(x->waitp->cond, y->waitp->cond);\n}\n\n// Given the contents of a mutex word containing a PerThreadSynch pointer,\n// return the pointer.\nstatic inline PerThreadSynch* GetPerThreadSynch(intptr_t v) {\n  return reinterpret_cast<PerThreadSynch*>(v & kMuHigh);\n}\n\n// The next several routines maintain the per-thread next and skip fields\n// used in the Mutex waiter queue.\n// The queue is a circular singly-linked list, of which the \"head\" is the\n// last element, and head->next if the first element.\n// The skip field has the invariant:\n//   For thread x, x->skip is one of:\n//     - invalid (iff x is not in a Mutex wait queue),\n//     - null, or\n//     - a pointer to a distinct thread waiting later in the same Mutex queue\n//       such that all threads in [x, x->skip] have the same condition, priority\n//       and lock type (MuEquivalentWaiter() is true for all pairs in [x,\n//       x->skip]).\n// In addition, if x->skip is  valid, (x->may_skip || x->skip == null)\n//\n// By the spec of MuEquivalentWaiter(), it is not necessary when removing the\n// first runnable thread y from the front a Mutex queue to adjust the skip\n// field of another thread x because if x->skip==y, x->skip must (have) become\n// invalid before y is removed.  The function TryRemove can remove a specified\n// thread from an arbitrary position in the queue whether runnable or not, so\n// it fixes up skip fields that would otherwise be left dangling.\n// The statement\n//     if (x->may_skip && MuEquivalentWaiter(x, x->next)) { x->skip = x->next; }\n// maintains the invariant provided x is not the last waiter in a Mutex queue\n// The statement\n//          if (x->skip != null) { x->skip = x->skip->skip; }\n// maintains the invariant.\n\n// Returns the last thread y in a mutex waiter queue such that all threads in\n// [x, y] inclusive share the same condition.  Sets skip fields of some threads\n// in that range to optimize future evaluation of Skip() on x values in\n// the range.  Requires thread x is in a mutex waiter queue.\n// The locking is unusual.  Skip() is called under these conditions:\n//   - spinlock is held in call from Enqueue(), with maybe_unlocking == false\n//   - Mutex is held in call from UnlockSlow() by last unlocker, with\n//     maybe_unlocking == true\n//   - both Mutex and spinlock are held in call from DequeueAllWakeable() (from\n//     UnlockSlow()) and TryRemove()\n// These cases are mutually exclusive, so Skip() never runs concurrently\n// with itself on the same Mutex.   The skip chain is used in these other places\n// that cannot occur concurrently:\n//   - FixSkip() (from TryRemove()) - spinlock and Mutex are held)\n//   - Dequeue() (with spinlock and Mutex held)\n//   - UnlockSlow() (with spinlock and Mutex held)\n// A more complex case is Enqueue()\n//   - Enqueue() (with spinlock held and maybe_unlocking == false)\n//               This is the first case in which Skip is called, above.\n//   - Enqueue() (without spinlock held; but queue is empty and being freshly\n//                formed)\n//   - Enqueue() (with spinlock held and maybe_unlocking == true)\n// The first case has mutual exclusion, and the second isolation through\n// working on an otherwise unreachable data structure.\n// In the last case, Enqueue() is required to change no skip/next pointers\n// except those in the added node and the former \"head\" node.  This implies\n// that the new node is added after head, and so must be the new head or the\n// new front of the queue.\nstatic PerThreadSynch* Skip(PerThreadSynch* x) {\n  PerThreadSynch* x0 = nullptr;\n  PerThreadSynch* x1 = x;\n  PerThreadSynch* x2 = x->skip;\n  if (x2 != nullptr) {\n    // Each iteration attempts to advance sequence (x0,x1,x2) to next sequence\n    // such that   x1 == x0->skip && x2 == x1->skip\n    while ((x0 = x1, x1 = x2, x2 = x2->skip) != nullptr) {\n      x0->skip = x2;  // short-circuit skip from x0 to x2\n    }\n    x->skip = x1;  // short-circuit skip from x to result\n  }\n  return x1;\n}\n\n// \"ancestor\" appears before \"to_be_removed\" in the same Mutex waiter queue.\n// The latter is going to be removed out of order, because of a timeout.\n// Check whether \"ancestor\" has a skip field pointing to \"to_be_removed\",\n// and fix it if it does.\nstatic void FixSkip(PerThreadSynch* ancestor, PerThreadSynch* to_be_removed) {\n  if (ancestor->skip == to_be_removed) {  // ancestor->skip left dangling\n    if (to_be_removed->skip != nullptr) {\n      ancestor->skip = to_be_removed->skip;  // can skip past to_be_removed\n    } else if (ancestor->next != to_be_removed) {  // they are not adjacent\n      ancestor->skip = ancestor->next;             // can skip one past ancestor\n    } else {\n      ancestor->skip = nullptr;  // can't skip at all\n    }\n  }\n}\n\nstatic void CondVarEnqueue(SynchWaitParams* waitp);\n\n// Enqueue thread \"waitp->thread\" on a waiter queue.\n// Called with mutex spinlock held if head != nullptr\n// If head==nullptr and waitp->cv_word==nullptr, then Enqueue() is\n// idempotent; it alters no state associated with the existing (empty)\n// queue.\n//\n// If waitp->cv_word == nullptr, queue the thread at either the front or\n// the end (according to its priority) of the circular mutex waiter queue whose\n// head is \"head\", and return the new head.  mu is the previous mutex state,\n// which contains the reader count (perhaps adjusted for the operation in\n// progress) if the list was empty and a read lock held, and the holder hint if\n// the list was empty and a write lock held.  (flags & kMuIsCond) indicates\n// whether this thread was transferred from a CondVar or is waiting for a\n// non-trivial condition.  In this case, Enqueue() never returns nullptr\n//\n// If waitp->cv_word != nullptr, CondVarEnqueue() is called, and \"head\" is\n// returned. This mechanism is used by CondVar to queue a thread on the\n// condition variable queue instead of the mutex queue in implementing Wait().\n// In this case, Enqueue() can return nullptr (if head==nullptr).\nstatic PerThreadSynch* Enqueue(PerThreadSynch* head, SynchWaitParams* waitp,\n                               intptr_t mu, int flags) {\n  // If we have been given a cv_word, call CondVarEnqueue() and return\n  // the previous head of the Mutex waiter queue.\n  if (waitp->cv_word != nullptr) {\n    CondVarEnqueue(waitp);\n    return head;\n  }\n\n  PerThreadSynch* s = waitp->thread;\n  ABSL_RAW_CHECK(\n      s->waitp == nullptr ||    // normal case\n          s->waitp == waitp ||  // Fer()---transfer from condition variable\n          s->suppress_fatal_errors,\n      \"detected illegal recursion into Mutex code\");\n  s->waitp = waitp;\n  s->skip = nullptr;   // maintain skip invariant (see above)\n  s->may_skip = true;  // always true on entering queue\n  s->wake = false;     // not being woken\n  s->cond_waiter = ((flags & kMuIsCond) != 0);\n#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM\n  if ((flags & kMuIsFer) == 0) {\n    assert(s == Synch_GetPerThread());\n    int64_t now_cycles = CycleClock::Now();\n    if (s->next_priority_read_cycles < now_cycles) {\n      // Every so often, update our idea of the thread's priority.\n      // pthread_getschedparam() is 5% of the block/wakeup time;\n      // CycleClock::Now() is 0.5%.\n      int policy;\n      struct sched_param param;\n      const int err = pthread_getschedparam(pthread_self(), &policy, &param);\n      if (err != 0) {\n        ABSL_RAW_LOG(ERROR, \"pthread_getschedparam failed: %d\", err);\n      } else {\n        s->priority = param.sched_priority;\n        s->next_priority_read_cycles =\n            now_cycles + static_cast<int64_t>(CycleClock::Frequency());\n      }\n    }\n  }\n#endif\n  if (head == nullptr) {         // s is the only waiter\n    s->next = s;                 // it's the only entry in the cycle\n    s->readers = mu;             // reader count is from mu word\n    s->maybe_unlocking = false;  // no one is searching an empty list\n    head = s;                    // s is new head\n  } else {\n    PerThreadSynch* enqueue_after = nullptr;  // we'll put s after this element\n#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM\n    if (s->priority > head->priority) {  // s's priority is above head's\n      // try to put s in priority-fifo order, or failing that at the front.\n      if (!head->maybe_unlocking) {\n        // No unlocker can be scanning the queue, so we can insert into the\n        // middle of the queue.\n        //\n        // Within a skip chain, all waiters have the same priority, so we can\n        // skip forward through the chains until we find one with a lower\n        // priority than the waiter to be enqueued.\n        PerThreadSynch* advance_to = head;  // next value of enqueue_after\n        do {\n          enqueue_after = advance_to;\n          // (side-effect: optimizes skip chain)\n          advance_to = Skip(enqueue_after->next);\n        } while (s->priority <= advance_to->priority);\n        // termination guaranteed because s->priority > head->priority\n        // and head is the end of a skip chain\n      } else if (waitp->how == kExclusive && waitp->cond == nullptr) {\n        // An unlocker could be scanning the queue, but we know it will recheck\n        // the queue front for writers that have no condition, which is what s\n        // is, so an insert at front is safe.\n        enqueue_after = head;  // add after head, at front\n      }\n    }\n#endif\n    if (enqueue_after != nullptr) {\n      s->next = enqueue_after->next;\n      enqueue_after->next = s;\n\n      // enqueue_after can be: head, Skip(...), or cur.\n      // The first two imply enqueue_after->skip == nullptr, and\n      // the last is used only if MuEquivalentWaiter(s, cur).\n      // We require this because clearing enqueue_after->skip\n      // is impossible; enqueue_after's predecessors might also\n      // incorrectly skip over s if we were to allow other\n      // insertion points.\n      ABSL_RAW_CHECK(enqueue_after->skip == nullptr ||\n                         MuEquivalentWaiter(enqueue_after, s),\n                     \"Mutex Enqueue failure\");\n\n      if (enqueue_after != head && enqueue_after->may_skip &&\n          MuEquivalentWaiter(enqueue_after, enqueue_after->next)) {\n        // enqueue_after can skip to its new successor, s\n        enqueue_after->skip = enqueue_after->next;\n      }\n      if (MuEquivalentWaiter(s, s->next)) {  // s->may_skip is known to be true\n        s->skip = s->next;                   // s may skip to its successor\n      }\n    } else if ((flags & kMuHasBlocked) &&\n               (s->priority >= head->next->priority) &&\n               (!head->maybe_unlocking ||\n                (waitp->how == kExclusive &&\n                 Condition::GuaranteedEqual(waitp->cond, nullptr)))) {\n      // This thread has already waited, then was woken, then failed to acquire\n      // the mutex and now tries to requeue. Try to requeue it at head,\n      // otherwise it can suffer bad latency (wait whole queue several times).\n      // However, we need to be conservative. First, we need to ensure that we\n      // respect priorities. Then, we need to be careful to not break wait\n      // queue invariants: we require either that unlocker is not scanning\n      // the queue or that the current thread is a writer with no condition\n      // (unlocker will recheck the queue for such waiters).\n      s->next = head->next;\n      head->next = s;\n      if (MuEquivalentWaiter(s, s->next)) {  // s->may_skip is known to be true\n        s->skip = s->next;                   // s may skip to its successor\n      }\n    } else {  // enqueue not done any other way, so\n              // we're inserting s at the back\n      // s will become new head; copy data from head into it\n      s->next = head->next;  // add s after head\n      head->next = s;\n      s->readers = head->readers;  // reader count is from previous head\n      s->maybe_unlocking = head->maybe_unlocking;  // same for unlock hint\n      if (head->may_skip && MuEquivalentWaiter(head, s)) {\n        // head now has successor; may skip\n        head->skip = s;\n      }\n      head = s;  // s is new head\n    }\n  }\n  s->state.store(PerThreadSynch::kQueued, std::memory_order_relaxed);\n  return head;\n}\n\n// Dequeue the successor pw->next of thread pw from the Mutex waiter queue\n// whose last element is head.  The new head element is returned, or null\n// if the list is made empty.\n// Dequeue is called with both spinlock and Mutex held.\nstatic PerThreadSynch* Dequeue(PerThreadSynch* head, PerThreadSynch* pw) {\n  PerThreadSynch* w = pw->next;\n  pw->next = w->next;                 // snip w out of list\n  if (head == w) {                    // we removed the head\n    head = (pw == w) ? nullptr : pw;  // either emptied list, or pw is new head\n  } else if (pw != head && MuEquivalentWaiter(pw, pw->next)) {\n    // pw can skip to its new successor\n    if (pw->next->skip !=\n        nullptr) {  // either skip to its successors skip target\n      pw->skip = pw->next->skip;\n    } else {  // or to pw's successor\n      pw->skip = pw->next;\n    }\n  }\n  return head;\n}\n\n// Traverse the elements [ pw->next, h] of the circular list whose last element\n// is head.\n// Remove all elements with wake==true and place them in the\n// singly-linked list wake_list in the order found.   Assumes that\n// there is only one such element if the element has how == kExclusive.\n// Return the new head.\nstatic PerThreadSynch* DequeueAllWakeable(PerThreadSynch* head,\n                                          PerThreadSynch* pw,\n                                          PerThreadSynch** wake_tail) {\n  PerThreadSynch* orig_h = head;\n  PerThreadSynch* w = pw->next;\n  bool skipped = false;\n  do {\n    if (w->wake) {  // remove this element\n      ABSL_RAW_CHECK(pw->skip == nullptr, \"bad skip in DequeueAllWakeable\");\n      // we're removing pw's successor so either pw->skip is zero or we should\n      // already have removed pw since if pw->skip!=null, pw has the same\n      // condition as w.\n      head = Dequeue(head, pw);\n      w->next = *wake_tail;               // keep list terminated\n      *wake_tail = w;                     // add w to wake_list;\n      wake_tail = &w->next;               // next addition to end\n      if (w->waitp->how == kExclusive) {  // wake at most 1 writer\n        break;\n      }\n    } else {         // not waking this one; skip\n      pw = Skip(w);  // skip as much as possible\n      skipped = true;\n    }\n    w = pw->next;\n    // We want to stop processing after we've considered the original head,\n    // orig_h.  We can't test for w==orig_h in the loop because w may skip over\n    // it; we are guaranteed only that w's predecessor will not skip over\n    // orig_h.  When we've considered orig_h, either we've processed it and\n    // removed it (so orig_h != head), or we considered it and skipped it (so\n    // skipped==true && pw == head because skipping from head always skips by\n    // just one, leaving pw pointing at head).  So we want to\n    // continue the loop with the negation of that expression.\n  } while (orig_h == head && (pw != head || !skipped));\n  return head;\n}\n\n// Try to remove thread s from the list of waiters on this mutex.\n// Does nothing if s is not on the waiter list.\nvoid Mutex::TryRemove(PerThreadSynch* s) {\n  SchedulingGuard::ScopedDisable disable_rescheduling;\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  // acquire spinlock & lock\n  if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait &&\n      mu_.compare_exchange_strong(v, v | kMuSpin | kMuWriter,\n                                  std::memory_order_acquire,\n                                  std::memory_order_relaxed)) {\n    PerThreadSynch* h = GetPerThreadSynch(v);\n    if (h != nullptr) {\n      PerThreadSynch* pw = h;  // pw is w's predecessor\n      PerThreadSynch* w;\n      if ((w = pw->next) != s) {  // search for thread,\n        do {                      // processing at least one element\n          // If the current element isn't equivalent to the waiter to be\n          // removed, we can skip the entire chain.\n          if (!MuEquivalentWaiter(s, w)) {\n            pw = Skip(w);  // so skip all that won't match\n            // we don't have to worry about dangling skip fields\n            // in the threads we skipped; none can point to s\n            // because they are in a different equivalence class.\n          } else {          // seeking same condition\n            FixSkip(w, s);  // fix up any skip pointer from w to s\n            pw = w;\n          }\n          // don't search further if we found the thread, or we're about to\n          // process the first thread again.\n        } while ((w = pw->next) != s && pw != h);\n      }\n      if (w == s) {  // found thread; remove it\n        // pw->skip may be non-zero here; the loop above ensured that\n        // no ancestor of s can skip to s, so removal is safe anyway.\n        h = Dequeue(h, pw);\n        s->next = nullptr;\n        s->state.store(PerThreadSynch::kAvailable, std::memory_order_release);\n      }\n    }\n    intptr_t nv;\n    do {  // release spinlock and lock\n      v = mu_.load(std::memory_order_relaxed);\n      nv = v & (kMuDesig | kMuEvent);\n      if (h != nullptr) {\n        nv |= kMuWait | reinterpret_cast<intptr_t>(h);\n        h->readers = 0;              // we hold writer lock\n        h->maybe_unlocking = false;  // finished unlocking\n      }\n    } while (!mu_.compare_exchange_weak(v, nv, std::memory_order_release,\n                                        std::memory_order_relaxed));\n  }\n}\n\n// Wait until thread \"s\", which must be the current thread, is removed from the\n// this mutex's waiter queue.  If \"s->waitp->timeout\" has a timeout, wake up\n// if the wait extends past the absolute time specified, even if \"s\" is still\n// on the mutex queue.  In this case, remove \"s\" from the queue and return\n// true, otherwise return false.\nvoid Mutex::Block(PerThreadSynch* s) {\n  while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {\n    if (!DecrementSynchSem(this, s, s->waitp->timeout)) {\n      // After a timeout, we go into a spin loop until we remove ourselves\n      // from the queue, or someone else removes us.  We can't be sure to be\n      // able to remove ourselves in a single lock acquisition because this\n      // mutex may be held, and the holder has the right to read the centre\n      // of the waiter queue without holding the spinlock.\n      this->TryRemove(s);\n      int c = 0;\n      while (s->next != nullptr) {\n        c = synchronization_internal::MutexDelay(c, GENTLE);\n        this->TryRemove(s);\n      }\n      if (kDebugMode) {\n        // This ensures that we test the case that TryRemove() is called when s\n        // is not on the queue.\n        this->TryRemove(s);\n      }\n      s->waitp->timeout = KernelTimeout::Never();  // timeout is satisfied\n      s->waitp->cond = nullptr;  // condition no longer relevant for wakeups\n    }\n  }\n  ABSL_RAW_CHECK(s->waitp != nullptr || s->suppress_fatal_errors,\n                 \"detected illegal recursion in Mutex code\");\n  s->waitp = nullptr;\n}\n\n// Wake thread w, and return the next thread in the list.\nPerThreadSynch* Mutex::Wakeup(PerThreadSynch* w) {\n  PerThreadSynch* next = w->next;\n  w->next = nullptr;\n  w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);\n  IncrementSynchSem(this, w);\n\n  return next;\n}\n\nstatic GraphId GetGraphIdLocked(Mutex* mu)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {\n  if (!deadlock_graph) {  // (re)create the deadlock graph.\n    deadlock_graph =\n        new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph)))\n            GraphCycles;\n  }\n  return deadlock_graph->GetId(mu);\n}\n\nstatic GraphId GetGraphId(Mutex* mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) {\n  base_internal::SpinLockHolder l(deadlock_graph_mu);\n  GraphId id = GetGraphIdLocked(mu);\n  return id;\n}\n\n// Record a lock acquisition.  This is used in debug mode for deadlock\n// detection.  The held_locks pointer points to the relevant data\n// structure for each case.\nstatic void LockEnter(Mutex* mu, GraphId id, SynchLocksHeld* held_locks) {\n  int n = held_locks->n;\n  int i = 0;\n  while (i != n && held_locks->locks[i].id != id) {\n    i++;\n  }\n  if (i == n) {\n    if (n == ABSL_ARRAYSIZE(held_locks->locks)) {\n      held_locks->overflow = true;  // lost some data\n    } else {                        // we have room for lock\n      held_locks->locks[i].mu = mu;\n      held_locks->locks[i].count = 1;\n      held_locks->locks[i].id = id;\n      held_locks->n = n + 1;\n    }\n  } else {\n    held_locks->locks[i].count++;\n  }\n}\n\n// Record a lock release.  Each call to LockEnter(mu, id, x) should be\n// eventually followed by a call to LockLeave(mu, id, x) by the same thread.\n// It does not process the event if is not needed when deadlock detection is\n// disabled.\nstatic void LockLeave(Mutex* mu, GraphId id, SynchLocksHeld* held_locks) {\n  int n = held_locks->n;\n  int i = 0;\n  while (i != n && held_locks->locks[i].id != id) {\n    i++;\n  }\n  if (i == n) {\n    if (!held_locks->overflow) {\n      // The deadlock id may have been reassigned after ForgetDeadlockInfo,\n      // but in that case mu should still be present.\n      i = 0;\n      while (i != n && held_locks->locks[i].mu != mu) {\n        i++;\n      }\n      if (i == n) {  // mu missing means releasing unheld lock\n        SynchEvent* mu_events = GetSynchEvent(mu);\n        ABSL_RAW_LOG(FATAL,\n                     \"thread releasing lock it does not hold: %p %s; \"\n                     ,\n                     static_cast<void*>(mu),\n                     mu_events == nullptr ? \"\" : mu_events->name);\n      }\n    }\n  } else if (held_locks->locks[i].count == 1) {\n    held_locks->n = n - 1;\n    held_locks->locks[i] = held_locks->locks[n - 1];\n    held_locks->locks[n - 1].id = InvalidGraphId();\n    held_locks->locks[n - 1].mu =\n        nullptr;  // clear mu to please the leak detector.\n  } else {\n    assert(held_locks->locks[i].count > 0);\n    held_locks->locks[i].count--;\n  }\n}\n\n// Call LockEnter() if in debug mode and deadlock detection is enabled.\nstatic inline void DebugOnlyLockEnter(Mutex* mu) {\n  if (kDebugMode) {\n    if (synch_deadlock_detection.load(std::memory_order_acquire) !=\n        OnDeadlockCycle::kIgnore) {\n      LockEnter(mu, GetGraphId(mu), Synch_GetAllLocks());\n    }\n  }\n}\n\n// Call LockEnter() if in debug mode and deadlock detection is enabled.\nstatic inline void DebugOnlyLockEnter(Mutex* mu, GraphId id) {\n  if (kDebugMode) {\n    if (synch_deadlock_detection.load(std::memory_order_acquire) !=\n        OnDeadlockCycle::kIgnore) {\n      LockEnter(mu, id, Synch_GetAllLocks());\n    }\n  }\n}\n\n// Call LockLeave() if in debug mode and deadlock detection is enabled.\nstatic inline void DebugOnlyLockLeave(Mutex* mu) {\n  if (kDebugMode) {\n    if (synch_deadlock_detection.load(std::memory_order_acquire) !=\n        OnDeadlockCycle::kIgnore) {\n      LockLeave(mu, GetGraphId(mu), Synch_GetAllLocks());\n    }\n  }\n}\n\nstatic char* StackString(void** pcs, int n, char* buf, int maxlen,\n                         bool symbolize) {\n  static constexpr int kSymLen = 200;\n  char sym[kSymLen];\n  int len = 0;\n  for (int i = 0; i != n; i++) {\n    if (len >= maxlen) return buf;\n    size_t count = static_cast<size_t>(maxlen - len);\n    if (symbolize) {\n      if (!absl::Symbolize(pcs[i], sym, kSymLen)) {\n        sym[0] = '\\0';\n      }\n      snprintf(buf + len, count, \"%s\\t@ %p %s\\n\", (i == 0 ? \"\\n\" : \"\"), pcs[i],\n               sym);\n    } else {\n      snprintf(buf + len, count, \" %p\", pcs[i]);\n    }\n    len += static_cast<int>(strlen(&buf[len]));\n  }\n  return buf;\n}\n\nstatic char* CurrentStackString(char* buf, int maxlen, bool symbolize) {\n  void* pcs[40];\n  return StackString(pcs, absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 2), buf,\n                     maxlen, symbolize);\n}\n\nnamespace {\nenum {\n  kMaxDeadlockPathLen = 10\n};  // maximum length of a deadlock cycle;\n    // a path this long would be remarkable\n// Buffers required to report a deadlock.\n// We do not allocate them on stack to avoid large stack frame.\nstruct DeadlockReportBuffers {\n  char buf[6100];\n  GraphId path[kMaxDeadlockPathLen];\n};\n\nstruct ScopedDeadlockReportBuffers {\n  ScopedDeadlockReportBuffers() {\n    b = reinterpret_cast<DeadlockReportBuffers*>(\n        base_internal::LowLevelAlloc::Alloc(sizeof(*b)));\n  }\n  ~ScopedDeadlockReportBuffers() { base_internal::LowLevelAlloc::Free(b); }\n  DeadlockReportBuffers* b;\n};\n\n// Helper to pass to GraphCycles::UpdateStackTrace.\nint GetStack(void** stack, int max_depth) {\n  return absl::GetStackTrace(stack, max_depth, 3);\n}\n}  // anonymous namespace\n\n// Called in debug mode when a thread is about to acquire a lock in a way that\n// may block.\nstatic GraphId DeadlockCheck(Mutex* mu) {\n  if (synch_deadlock_detection.load(std::memory_order_acquire) ==\n      OnDeadlockCycle::kIgnore) {\n    return InvalidGraphId();\n  }\n\n  SynchLocksHeld* all_locks = Synch_GetAllLocks();\n\n  absl::base_internal::SpinLockHolder lock(deadlock_graph_mu);\n  const GraphId mu_id = GetGraphIdLocked(mu);\n\n  if (all_locks->n == 0) {\n    // There are no other locks held. Return now so that we don't need to\n    // call GetSynchEvent(). This way we do not record the stack trace\n    // for this Mutex. It's ok, since if this Mutex is involved in a deadlock,\n    // it can't always be the first lock acquired by a thread.\n    return mu_id;\n  }\n\n  // We prefer to keep stack traces that show a thread holding and acquiring\n  // as many locks as possible.  This increases the chances that a given edge\n  // in the acquires-before graph will be represented in the stack traces\n  // recorded for the locks.\n  deadlock_graph->UpdateStackTrace(mu_id, all_locks->n + 1, GetStack);\n\n  // For each other mutex already held by this thread:\n  for (int i = 0; i != all_locks->n; i++) {\n    const GraphId other_node_id = all_locks->locks[i].id;\n    const Mutex* other =\n        static_cast<const Mutex*>(deadlock_graph->Ptr(other_node_id));\n    if (other == nullptr) {\n      // Ignore stale lock\n      continue;\n    }\n\n    // Add the acquired-before edge to the graph.\n    if (!deadlock_graph->InsertEdge(other_node_id, mu_id)) {\n      ScopedDeadlockReportBuffers scoped_buffers;\n      DeadlockReportBuffers* b = scoped_buffers.b;\n      static int number_of_reported_deadlocks = 0;\n      number_of_reported_deadlocks++;\n      // Symbolize only 2 first deadlock report to avoid huge slowdowns.\n      bool symbolize = number_of_reported_deadlocks <= 2;\n      ABSL_RAW_LOG(ERROR, \"Potential Mutex deadlock: %s\",\n                   CurrentStackString(b->buf, sizeof (b->buf), symbolize));\n      size_t len = 0;\n      for (int j = 0; j != all_locks->n; j++) {\n        void* pr = deadlock_graph->Ptr(all_locks->locks[j].id);\n        if (pr != nullptr) {\n          snprintf(b->buf + len, sizeof(b->buf) - len, \" %p\", pr);\n          len += strlen(&b->buf[len]);\n        }\n      }\n      ABSL_RAW_LOG(ERROR,\n                   \"Acquiring absl::Mutex %p while holding %s; a cycle in the \"\n                   \"historical lock ordering graph has been observed\",\n                   static_cast<void*>(mu), b->buf);\n      ABSL_RAW_LOG(ERROR, \"Cycle: \");\n      int path_len = deadlock_graph->FindPath(mu_id, other_node_id,\n                                              ABSL_ARRAYSIZE(b->path), b->path);\n      for (int j = 0; j != path_len && j != ABSL_ARRAYSIZE(b->path); j++) {\n        GraphId id = b->path[j];\n        Mutex* path_mu = static_cast<Mutex*>(deadlock_graph->Ptr(id));\n        if (path_mu == nullptr) continue;\n        void** stack;\n        int depth = deadlock_graph->GetStackTrace(id, &stack);\n        snprintf(b->buf, sizeof(b->buf),\n                 \"mutex@%p stack: \", static_cast<void*>(path_mu));\n        StackString(stack, depth, b->buf + strlen(b->buf),\n                    static_cast<int>(sizeof(b->buf) - strlen(b->buf)),\n                    symbolize);\n        ABSL_RAW_LOG(ERROR, \"%s\", b->buf);\n      }\n      if (path_len > static_cast<int>(ABSL_ARRAYSIZE(b->path))) {\n        ABSL_RAW_LOG(ERROR, \"(long cycle; list truncated)\");\n      }\n      if (synch_deadlock_detection.load(std::memory_order_acquire) ==\n          OnDeadlockCycle::kAbort) {\n        deadlock_graph_mu.unlock();  // avoid deadlock in fatal sighandler\n        ABSL_RAW_LOG(FATAL, \"dying due to potential deadlock\");\n        return mu_id;\n      }\n      break;  // report at most one potential deadlock per acquisition\n    }\n  }\n\n  return mu_id;\n}\n\n// Invoke DeadlockCheck() iff we're in debug mode and\n// deadlock checking has been enabled.\nstatic inline GraphId DebugOnlyDeadlockCheck(Mutex* mu) {\n  if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) !=\n                        OnDeadlockCycle::kIgnore) {\n    return DeadlockCheck(mu);\n  } else {\n    return InvalidGraphId();\n  }\n}\n\nvoid Mutex::ForgetDeadlockInfo() {\n  if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) !=\n                        OnDeadlockCycle::kIgnore) {\n    deadlock_graph_mu.lock();\n    if (deadlock_graph != nullptr) {\n      deadlock_graph->RemoveNode(this);\n    }\n    deadlock_graph_mu.unlock();\n  }\n}\n\nvoid Mutex::AssertNotHeld() const {\n  // We have the data to allow this check only if in debug mode and deadlock\n  // detection is enabled.\n  if (kDebugMode &&\n      (mu_.load(std::memory_order_relaxed) & (kMuWriter | kMuReader)) != 0 &&\n      synch_deadlock_detection.load(std::memory_order_acquire) !=\n          OnDeadlockCycle::kIgnore) {\n    GraphId id = GetGraphId(const_cast<Mutex*>(this));\n    SynchLocksHeld* locks = Synch_GetAllLocks();\n    for (int i = 0; i != locks->n; i++) {\n      if (locks->locks[i].id == id) {\n        SynchEvent* mu_events = GetSynchEvent(this);\n        ABSL_RAW_LOG(FATAL, \"thread should not hold mutex %p %s\",\n                     static_cast<const void*>(this),\n                     (mu_events == nullptr ? \"\" : mu_events->name));\n      }\n    }\n  }\n}\n\n// Attempt to acquire *mu, and return whether successful.  The implementation\n// may spin for a short while if the lock cannot be acquired immediately.\nstatic bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) {\n  int c = globals.spinloop_iterations.load(std::memory_order_relaxed);\n  do {  // do/while somewhat faster on AMD\n    intptr_t v = mu->load(std::memory_order_relaxed);\n    if ((v & (kMuReader | kMuEvent)) != 0) {\n      return false;                       // a reader or tracing -> give up\n    } else if (((v & kMuWriter) == 0) &&  // no holder -> try to acquire\n               mu->compare_exchange_strong(v, kMuWriter | v,\n                                           std::memory_order_acquire,\n                                           std::memory_order_relaxed)) {\n      return true;\n    }\n  } while (--c > 0);\n  return false;\n}\n\nvoid Mutex::lock() {\n  ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);\n  GraphId id = DebugOnlyDeadlockCheck(this);\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  // try fast acquire, then spin loop\n  if (ABSL_PREDICT_FALSE((v & (kMuWriter | kMuReader | kMuEvent)) != 0) ||\n      ABSL_PREDICT_FALSE(!mu_.compare_exchange_strong(\n          v, kMuWriter | v, std::memory_order_acquire,\n          std::memory_order_relaxed))) {\n    // try spin acquire, then slow loop\n    if (ABSL_PREDICT_FALSE(!TryAcquireWithSpinning(&this->mu_))) {\n      this->LockSlow(kExclusive, nullptr, 0);\n    }\n  }\n  DebugOnlyLockEnter(this, id);\n  ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);\n}\n\nvoid Mutex::lock_shared() {\n  ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock);\n  GraphId id = DebugOnlyDeadlockCheck(this);\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  for (;;) {\n    // If there are non-readers holding the lock, use the slow loop.\n    if (ABSL_PREDICT_FALSE(v & (kMuWriter | kMuWait | kMuEvent)) != 0) {\n      this->LockSlow(kShared, nullptr, 0);\n      break;\n    }\n    // We can avoid the loop and only use the CAS when the lock is free or\n    // only held by readers.\n    if (ABSL_PREDICT_TRUE(mu_.compare_exchange_weak(\n            v, (kMuReader | v) + kMuOne, std::memory_order_acquire,\n            std::memory_order_relaxed))) {\n      break;\n    }\n  }\n  DebugOnlyLockEnter(this, id);\n  ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0);\n}\n\nbool Mutex::LockWhenCommon(const Condition& cond,\n                           synchronization_internal::KernelTimeout t,\n                           bool write) {\n  MuHow how = write ? kExclusive : kShared;\n  ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));\n  GraphId id = DebugOnlyDeadlockCheck(this);\n  bool res = LockSlowWithDeadline(how, &cond, t, 0);\n  DebugOnlyLockEnter(this, id);\n  ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);\n  return res;\n}\n\nbool Mutex::AwaitCommon(const Condition& cond, KernelTimeout t) {\n  if (kDebugMode) {\n    this->AssertReaderHeld();\n  }\n  if (cond.Eval()) {  // condition already true; nothing to do\n    return true;\n  }\n  MuHow how =\n      (mu_.load(std::memory_order_relaxed) & kMuWriter) ? kExclusive : kShared;\n  ABSL_TSAN_MUTEX_PRE_UNLOCK(this, TsanFlags(how));\n  SynchWaitParams waitp(how, &cond, t, nullptr /*no cvmu*/,\n                        Synch_GetPerThreadAnnotated(this),\n                        nullptr /*no cv_word*/);\n  this->UnlockSlow(&waitp);\n  this->Block(waitp.thread);\n  ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how));\n  ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));\n  this->LockSlowLoop(&waitp, kMuHasBlocked | kMuIsCond);\n  bool res = waitp.cond != nullptr ||  // => cond known true from LockSlowLoop\n             EvalConditionAnnotated(&cond, this, true, false, how == kShared);\n  ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);\n  ABSL_RAW_CHECK(res || t.has_timeout(),\n                 \"condition untrue on return from Await\");\n  return res;\n}\n\nbool Mutex::try_lock() {\n  ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  // Try fast acquire.\n  if (ABSL_PREDICT_TRUE((v & (kMuWriter | kMuReader | kMuEvent)) == 0)) {\n    if (ABSL_PREDICT_TRUE(mu_.compare_exchange_strong(\n            v, kMuWriter | v, std::memory_order_acquire,\n            std::memory_order_relaxed))) {\n      DebugOnlyLockEnter(this);\n      ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);\n      return true;\n    }\n  } else if (ABSL_PREDICT_FALSE((v & kMuEvent) != 0)) {\n    // We're recording events.\n    return TryLockSlow();\n  }\n  ABSL_TSAN_MUTEX_POST_LOCK(\n      this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0);\n  return false;\n}\n\nABSL_ATTRIBUTE_NOINLINE bool Mutex::TryLockSlow() {\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  if ((v & kExclusive->slow_need_zero) == 0 &&  // try fast acquire\n      mu_.compare_exchange_strong(\n          v, (kExclusive->fast_or | v) + kExclusive->fast_add,\n          std::memory_order_acquire, std::memory_order_relaxed)) {\n    DebugOnlyLockEnter(this);\n    PostSynchEvent(this, SYNCH_EV_TRYLOCK_SUCCESS);\n    ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);\n    return true;\n  }\n  PostSynchEvent(this, SYNCH_EV_TRYLOCK_FAILED);\n  ABSL_TSAN_MUTEX_POST_LOCK(\n      this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0);\n  return false;\n}\n\nbool Mutex::try_lock_shared() {\n  ABSL_TSAN_MUTEX_PRE_LOCK(this,\n                           __tsan_mutex_read_lock | __tsan_mutex_try_lock);\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  // Clang tends to unroll the loop when compiling with optimization.\n  // But in this case it just unnecessary increases code size.\n  // If CAS is failing due to contention, the jump cost is negligible.\n#if defined(__clang__)\n#pragma nounroll\n#endif\n  // The while-loops (here and below) iterate only if the mutex word keeps\n  // changing (typically because the reader count changes) under the CAS.\n  // We limit the number of attempts to avoid having to think about livelock.\n  for (int loop_limit = 5; loop_limit != 0; loop_limit--) {\n    if (ABSL_PREDICT_FALSE((v & (kMuWriter | kMuWait | kMuEvent)) != 0)) {\n      break;\n    }\n    if (ABSL_PREDICT_TRUE(mu_.compare_exchange_strong(\n            v, (kMuReader | v) + kMuOne, std::memory_order_acquire,\n            std::memory_order_relaxed))) {\n      DebugOnlyLockEnter(this);\n      ABSL_TSAN_MUTEX_POST_LOCK(\n          this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0);\n      return true;\n    }\n  }\n  if (ABSL_PREDICT_TRUE((v & kMuEvent) == 0)) {\n    ABSL_TSAN_MUTEX_POST_LOCK(this,\n                              __tsan_mutex_read_lock | __tsan_mutex_try_lock |\n                                  __tsan_mutex_try_lock_failed,\n                              0);\n    return false;\n  }\n  // we're recording events\n  return ReaderTryLockSlow();\n}\n\nABSL_ATTRIBUTE_NOINLINE bool Mutex::ReaderTryLockSlow() {\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n#if defined(__clang__)\n#pragma nounroll\n#endif\n  for (int loop_limit = 5; loop_limit != 0; loop_limit--) {\n    if ((v & kShared->slow_need_zero) == 0 &&\n        mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne,\n                                    std::memory_order_acquire,\n                                    std::memory_order_relaxed)) {\n      DebugOnlyLockEnter(this);\n      PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_SUCCESS);\n      ABSL_TSAN_MUTEX_POST_LOCK(\n          this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0);\n      return true;\n    }\n  }\n  PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_FAILED);\n  ABSL_TSAN_MUTEX_POST_LOCK(this,\n                            __tsan_mutex_read_lock | __tsan_mutex_try_lock |\n                                __tsan_mutex_try_lock_failed,\n                            0);\n  return false;\n}\n\nvoid Mutex::unlock() {\n  ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);\n  DebugOnlyLockLeave(this);\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n\n  if (kDebugMode && ((v & (kMuWriter | kMuReader)) != kMuWriter)) {\n    ABSL_RAW_LOG(FATAL, \"Mutex unlocked when destroyed or not locked: v=0x%x\",\n                 static_cast<unsigned>(v));\n  }\n\n  // should_try_cas is whether we'll try a compare-and-swap immediately.\n  // NOTE: optimized out when kDebugMode is false.\n  bool should_try_cas = ((v & (kMuEvent | kMuWriter)) == kMuWriter &&\n                         (v & (kMuWait | kMuDesig)) != kMuWait);\n\n  // But, we can use an alternate computation of it, that compilers\n  // currently don't find on their own.  When that changes, this function\n  // can be simplified.\n  //\n  // should_try_cas is true iff the bits satisfy the following conditions:\n  //\n  //                   Ev Wr Wa De\n  // equal to           0  1\n  // and not equal to         1  0\n  //\n  // after xoring by    0  1  0  1,  this is equivalent to:\n  //\n  // equal to           0  0\n  // and not equal to         1  1,  which is the same as:\n  //\n  // smaller than       0  0  1  1\n  static_assert(kMuEvent > kMuWait, \"Needed for should_try_cas_fast\");\n  static_assert(kMuEvent > kMuDesig, \"Needed for should_try_cas_fast\");\n  static_assert(kMuWriter > kMuWait, \"Needed for should_try_cas_fast\");\n  static_assert(kMuWriter > kMuDesig, \"Needed for should_try_cas_fast\");\n\n  bool should_try_cas_fast =\n      ((v ^ (kMuWriter | kMuDesig)) &\n       (kMuEvent | kMuWriter | kMuWait | kMuDesig)) < (kMuWait | kMuDesig);\n\n  if (kDebugMode && should_try_cas != should_try_cas_fast) {\n    // We would usually use PRIdPTR here, but is not correctly implemented\n    // within the android toolchain.\n    ABSL_RAW_LOG(FATAL, \"internal logic error %llx %llx %llx\\n\",\n                 static_cast<long long>(v),\n                 static_cast<long long>(should_try_cas),\n                 static_cast<long long>(should_try_cas_fast));\n  }\n  if (should_try_cas_fast &&\n      mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),\n                                  std::memory_order_release,\n                                  std::memory_order_relaxed)) {\n    // fast writer release (writer with no waiters or with designated waker)\n  } else {\n    this->UnlockSlow(nullptr /*no waitp*/);  // take slow path\n  }\n  ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);\n}\n\n// Requires v to represent a reader-locked state.\nstatic bool ExactlyOneReader(intptr_t v) {\n  assert((v & (kMuWriter | kMuReader)) == kMuReader);\n  assert((v & kMuHigh) != 0);\n  // The more straightforward \"(v & kMuHigh) == kMuOne\" also works, but\n  // on some architectures the following generates slightly smaller code.\n  // It may be faster too.\n  constexpr intptr_t kMuMultipleWaitersMask = kMuHigh ^ kMuOne;\n  return (v & kMuMultipleWaitersMask) == 0;\n}\n\nvoid Mutex::unlock_shared() {\n  ABSL_TSAN_MUTEX_PRE_UNLOCK(this, __tsan_mutex_read_lock);\n  DebugOnlyLockLeave(this);\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  assert((v & (kMuWriter | kMuReader)) == kMuReader);\n  for (;;) {\n    if (ABSL_PREDICT_FALSE((v & (kMuReader | kMuWait | kMuEvent)) !=\n                           kMuReader)) {\n      this->UnlockSlow(nullptr /*no waitp*/);  // take slow path\n      break;\n    }\n    // fast reader release (reader with no waiters)\n    intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne;\n    if (ABSL_PREDICT_TRUE(\n            mu_.compare_exchange_strong(v, v - clear, std::memory_order_release,\n                                        std::memory_order_relaxed))) {\n      break;\n    }\n  }\n  ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock);\n}\n\n// Clears the designated waker flag in the mutex if this thread has blocked, and\n// therefore may be the designated waker.\nstatic intptr_t ClearDesignatedWakerMask(int flag) {\n  assert(flag >= 0);\n  assert(flag <= 1);\n  switch (flag) {\n    case 0:  // not blocked\n      return ~static_cast<intptr_t>(0);\n    case 1:  // blocked; turn off the designated waker bit\n      return ~static_cast<intptr_t>(kMuDesig);\n  }\n  ABSL_UNREACHABLE();\n}\n\n// Conditionally ignores the existence of waiting writers if a reader that has\n// already blocked once wakes up.\nstatic intptr_t IgnoreWaitingWritersMask(int flag) {\n  assert(flag >= 0);\n  assert(flag <= 1);\n  switch (flag) {\n    case 0:  // not blocked\n      return ~static_cast<intptr_t>(0);\n    case 1:  // blocked; pretend there are no waiting writers\n      return ~static_cast<intptr_t>(kMuWrWait);\n  }\n  ABSL_UNREACHABLE();\n}\n\n// Internal version of LockWhen().  See LockSlowWithDeadline()\nABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition* cond,\n                                             int flags) {\n  // Note: we specifically initialize spinloop_iterations after the first use\n  // in TryAcquireWithSpinning so that Lock function does not have any non-tail\n  // calls and consequently a stack frame. It's fine to have spinloop_iterations\n  // uninitialized (meaning no spinning) in all initial uncontended Lock calls\n  // and in the first contended call. After that we will have\n  // spinloop_iterations properly initialized.\n  if (ABSL_PREDICT_FALSE(\n          globals.spinloop_iterations.load(std::memory_order_relaxed) == 0)) {\n    if (absl::base_internal::NumCPUs() > 1) {\n      // If this is multiprocessor, allow spinning.\n      globals.spinloop_iterations.store(1500, std::memory_order_relaxed);\n    } else {\n      // If this a uniprocessor, only yield/sleep.\n      globals.spinloop_iterations.store(-1, std::memory_order_relaxed);\n    }\n  }\n  ABSL_RAW_CHECK(\n      this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags),\n      \"condition untrue on return from LockSlow\");\n}\n\n// Compute cond->Eval() and tell race detectors that we do it under mutex mu.\nstatic inline bool EvalConditionAnnotated(const Condition* cond, Mutex* mu,\n                                          bool locking, bool trylock,\n                                          bool read_lock) {\n  // Delicate annotation dance.\n  // We are currently inside of read/write lock/unlock operation.\n  // All memory accesses are ignored inside of mutex operations + for unlock\n  // operation tsan considers that we've already released the mutex.\n  bool res = false;\n#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE\n  const uint32_t flags = read_lock ? __tsan_mutex_read_lock : 0;\n  const uint32_t tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);\n#endif\n  if (locking) {\n    // For lock we pretend that we have finished the operation,\n    // evaluate the predicate, then unlock the mutex and start locking it again\n    // to match the annotation at the end of outer lock operation.\n    // Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan\n    // will think the lock acquisition is recursive which will trigger\n    // deadlock detector.\n    ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0);\n    res = cond->Eval();\n    // There is no \"try\" version of Unlock, so use flags instead of tryflags.\n    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);\n    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);\n    ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags);\n  } else {\n    // Similarly, for unlock we pretend that we have unlocked the mutex,\n    // lock the mutex, evaluate the predicate, and start unlocking it again\n    // to match the annotation at the end of outer unlock operation.\n    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);\n    ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags);\n    ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0);\n    res = cond->Eval();\n    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);\n  }\n  // Prevent unused param warnings in non-TSAN builds.\n  static_cast<void>(mu);\n  static_cast<void>(trylock);\n  static_cast<void>(read_lock);\n  return res;\n}\n\n// Compute cond->Eval() hiding it from race detectors.\n// We are hiding it because inside of UnlockSlow we can evaluate a predicate\n// that was just added by a concurrent Lock operation; Lock adds the predicate\n// to the internal Mutex list without actually acquiring the Mutex\n// (it only acquires the internal spinlock, which is rightfully invisible for\n// tsan). As the result there is no tsan-visible synchronization between the\n// addition and this thread. So if we would enable race detection here,\n// it would race with the predicate initialization.\nstatic inline bool EvalConditionIgnored(Mutex* mu, const Condition* cond) {\n  // Memory accesses are already ignored inside of lock/unlock operations,\n  // but synchronization operations are also ignored. When we evaluate the\n  // predicate we must ignore only memory accesses but not synchronization,\n  // because missed synchronization can lead to false reports later.\n  // So we \"divert\" (which un-ignores both memory accesses and synchronization)\n  // and then separately turn on ignores of memory accesses.\n  ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);\n  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();\n  bool res = cond->Eval();\n  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();\n  ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);\n  static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.\n  return res;\n}\n\n// Internal equivalent of *LockWhenWithDeadline(), where\n//   \"t\" represents the absolute timeout; !t.has_timeout() means \"forever\".\n//   \"how\" is \"kShared\" (for ReaderLockWhen) or \"kExclusive\" (for LockWhen)\n// In flags, bits are ored together:\n// - kMuHasBlocked indicates that the client has already blocked on the call so\n//   the designated waker bit must be cleared and waiting writers should not\n//   obstruct this call\n// - kMuIsCond indicates that this is a conditional acquire (condition variable,\n//   Await,  LockWhen) so contention profiling should be suppressed.\nbool Mutex::LockSlowWithDeadline(MuHow how, const Condition* cond,\n                                 KernelTimeout t, int flags) {\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  bool unlock = false;\n  if ((v & how->fast_need_zero) == 0 &&  // try fast acquire\n      mu_.compare_exchange_strong(\n          v,\n          (how->fast_or |\n           (v & ClearDesignatedWakerMask(flags & kMuHasBlocked))) +\n              how->fast_add,\n          std::memory_order_acquire, std::memory_order_relaxed)) {\n    if (cond == nullptr ||\n        EvalConditionAnnotated(cond, this, true, false, how == kShared)) {\n      return true;\n    }\n    unlock = true;\n  }\n  SynchWaitParams waitp(how, cond, t, nullptr /*no cvmu*/,\n                        Synch_GetPerThreadAnnotated(this),\n                        nullptr /*no cv_word*/);\n  if (cond != nullptr) {\n    flags |= kMuIsCond;\n  }\n  if (unlock) {\n    this->UnlockSlow(&waitp);\n    this->Block(waitp.thread);\n    flags |= kMuHasBlocked;\n  }\n  this->LockSlowLoop(&waitp, flags);\n  return waitp.cond != nullptr ||  // => cond known true from LockSlowLoop\n         cond == nullptr ||\n         EvalConditionAnnotated(cond, this, true, false, how == kShared);\n}\n\n// RAW_CHECK_FMT() takes a condition, a printf-style format string, and\n// the printf-style argument list.   The format string must be a literal.\n// Arguments after the first are not evaluated unless the condition is true.\n#define RAW_CHECK_FMT(cond, ...)                                   \\\n  do {                                                             \\\n    if (ABSL_PREDICT_FALSE(!(cond))) {                             \\\n      ABSL_RAW_LOG(FATAL, \"Check \" #cond \" failed: \" __VA_ARGS__); \\\n    }                                                              \\\n  } while (0)\n\nstatic void CheckForMutexCorruption(intptr_t v, const char* label) {\n  // Test for either of two situations that should not occur in v:\n  //   kMuWriter and kMuReader\n  //   kMuWrWait and !kMuWait\n  const uintptr_t w = static_cast<uintptr_t>(v ^ kMuWait);\n  // By flipping that bit, we can now test for:\n  //   kMuWriter and kMuReader in w\n  //   kMuWrWait and kMuWait in w\n  // We've chosen these two pairs of values to be so that they will overlap,\n  // respectively, when the word is left shifted by three.  This allows us to\n  // save a branch in the common (correct) case of them not being coincident.\n  static_assert(kMuReader << 3 == kMuWriter, \"must match\");\n  static_assert(kMuWait << 3 == kMuWrWait, \"must match\");\n  if (ABSL_PREDICT_TRUE((w & (w << 3) & (kMuWriter | kMuWrWait)) == 0)) return;\n  RAW_CHECK_FMT((v & (kMuWriter | kMuReader)) != (kMuWriter | kMuReader),\n                \"%s: Mutex corrupt: both reader and writer lock held: %p\",\n                label, reinterpret_cast<void*>(v));\n  RAW_CHECK_FMT((v & (kMuWait | kMuWrWait)) != kMuWrWait,\n                \"%s: Mutex corrupt: waiting writer with no waiters: %p\", label,\n                reinterpret_cast<void*>(v));\n  assert(false);\n}\n\nvoid Mutex::LockSlowLoop(SynchWaitParams* waitp, int flags) {\n  SchedulingGuard::ScopedDisable disable_rescheduling;\n  int c = 0;\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  if ((v & kMuEvent) != 0) {\n    PostSynchEvent(\n        this, waitp->how == kExclusive ? SYNCH_EV_LOCK : SYNCH_EV_READERLOCK);\n  }\n  ABSL_RAW_CHECK(\n      waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,\n      \"detected illegal recursion into Mutex code\");\n  for (;;) {\n    v = mu_.load(std::memory_order_relaxed);\n    CheckForMutexCorruption(v, \"Lock\");\n    if ((v & waitp->how->slow_need_zero) == 0) {\n      if (mu_.compare_exchange_strong(\n              v,\n              (waitp->how->fast_or |\n               (v & ClearDesignatedWakerMask(flags & kMuHasBlocked))) +\n                  waitp->how->fast_add,\n              std::memory_order_acquire, std::memory_order_relaxed)) {\n        if (waitp->cond == nullptr ||\n            EvalConditionAnnotated(waitp->cond, this, true, false,\n                                   waitp->how == kShared)) {\n          break;  // we timed out, or condition true, so return\n        }\n        this->UnlockSlow(waitp);  // got lock but condition false\n        this->Block(waitp->thread);\n        flags |= kMuHasBlocked;\n        c = 0;\n      }\n    } else {  // need to access waiter list\n      bool dowait = false;\n      if ((v & (kMuSpin | kMuWait)) == 0) {  // no waiters\n        // This thread tries to become the one and only waiter.\n        PerThreadSynch* new_h = Enqueue(nullptr, waitp, v, flags);\n        intptr_t nv =\n            (v & ClearDesignatedWakerMask(flags & kMuHasBlocked) & kMuLow) |\n            kMuWait;\n        ABSL_RAW_CHECK(new_h != nullptr, \"Enqueue to empty list failed\");\n        if (waitp->how == kExclusive && (v & kMuReader) != 0) {\n          nv |= kMuWrWait;\n        }\n        if (mu_.compare_exchange_strong(\n                v, reinterpret_cast<intptr_t>(new_h) | nv,\n                std::memory_order_release, std::memory_order_relaxed)) {\n          dowait = true;\n        } else {  // attempted Enqueue() failed\n          // zero out the waitp field set by Enqueue()\n          waitp->thread->waitp = nullptr;\n        }\n      } else if ((v & waitp->how->slow_inc_need_zero &\n                  IgnoreWaitingWritersMask(flags & kMuHasBlocked)) == 0) {\n        // This is a reader that needs to increment the reader count,\n        // but the count is currently held in the last waiter.\n        if (mu_.compare_exchange_strong(\n                v,\n                (v & ClearDesignatedWakerMask(flags & kMuHasBlocked)) |\n                    kMuSpin | kMuReader,\n                std::memory_order_acquire, std::memory_order_relaxed)) {\n          PerThreadSynch* h = GetPerThreadSynch(v);\n          h->readers += kMuOne;  // inc reader count in waiter\n          do {                   // release spinlock\n            v = mu_.load(std::memory_order_relaxed);\n          } while (!mu_.compare_exchange_weak(v, (v & ~kMuSpin) | kMuReader,\n                                              std::memory_order_release,\n                                              std::memory_order_relaxed));\n          if (waitp->cond == nullptr ||\n              EvalConditionAnnotated(waitp->cond, this, true, false,\n                                     waitp->how == kShared)) {\n            break;  // we timed out, or condition true, so return\n          }\n          this->UnlockSlow(waitp);  // got lock but condition false\n          this->Block(waitp->thread);\n          flags |= kMuHasBlocked;\n          c = 0;\n        }\n      } else if ((v & kMuSpin) == 0 &&  // attempt to queue ourselves\n                 mu_.compare_exchange_strong(\n                     v,\n                     (v & ClearDesignatedWakerMask(flags & kMuHasBlocked)) |\n                         kMuSpin | kMuWait,\n                     std::memory_order_acquire, std::memory_order_relaxed)) {\n        PerThreadSynch* h = GetPerThreadSynch(v);\n        PerThreadSynch* new_h = Enqueue(h, waitp, v, flags);\n        intptr_t wr_wait = 0;\n        ABSL_RAW_CHECK(new_h != nullptr, \"Enqueue to list failed\");\n        if (waitp->how == kExclusive && (v & kMuReader) != 0) {\n          wr_wait = kMuWrWait;  // give priority to a waiting writer\n        }\n        do {  // release spinlock\n          v = mu_.load(std::memory_order_relaxed);\n        } while (!mu_.compare_exchange_weak(\n            v,\n            (v & (kMuLow & ~kMuSpin)) | kMuWait | wr_wait |\n                reinterpret_cast<intptr_t>(new_h),\n            std::memory_order_release, std::memory_order_relaxed));\n        dowait = true;\n      }\n      if (dowait) {\n        this->Block(waitp->thread);  // wait until removed from list or timeout\n        flags |= kMuHasBlocked;\n        c = 0;\n      }\n    }\n    ABSL_RAW_CHECK(\n        waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,\n        \"detected illegal recursion into Mutex code\");\n    // delay, then try again\n    c = synchronization_internal::MutexDelay(c, GENTLE);\n  }\n  ABSL_RAW_CHECK(\n      waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,\n      \"detected illegal recursion into Mutex code\");\n  if ((v & kMuEvent) != 0) {\n    PostSynchEvent(this, waitp->how == kExclusive\n                             ? SYNCH_EV_LOCK_RETURNING\n                             : SYNCH_EV_READERLOCK_RETURNING);\n  }\n}\n\n// Unlock this mutex, which is held by the current thread.\n// If waitp is non-zero, it must be the wait parameters for the current thread\n// which holds the lock but is not runnable because its condition is false\n// or it is in the process of blocking on a condition variable; it must requeue\n// itself on the mutex/condvar to wait for its condition to become true.\nABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) {\n  SchedulingGuard::ScopedDisable disable_rescheduling;\n  intptr_t v = mu_.load(std::memory_order_relaxed);\n  this->AssertReaderHeld();\n  CheckForMutexCorruption(v, \"Unlock\");\n  if ((v & kMuEvent) != 0) {\n    PostSynchEvent(\n        this, (v & kMuWriter) != 0 ? SYNCH_EV_UNLOCK : SYNCH_EV_READERUNLOCK);\n  }\n  int c = 0;\n  // the waiter under consideration to wake, or zero\n  PerThreadSynch* w = nullptr;\n  // the predecessor to w or zero\n  PerThreadSynch* pw = nullptr;\n  // head of the list searched previously, or zero\n  PerThreadSynch* old_h = nullptr;\n  // a condition that's known to be false.\n  PerThreadSynch* wake_list = kPerThreadSynchNull;  // list of threads to wake\n  intptr_t wr_wait = 0;  // set to kMuWrWait if we wake a reader and a\n                         // later writer could have acquired the lock\n                         // (starvation avoidance)\n  // When non-null, clear its \"woken_has_waiters\" field before returning.\n  absl::base_internal::ThreadIdentity* clear_waking_des_waker = nullptr;\n  ABSL_RAW_CHECK(waitp == nullptr || waitp->thread->waitp == nullptr ||\n                     waitp->thread->suppress_fatal_errors,\n                 \"detected illegal recursion into Mutex code\");\n  // This loop finds threads wake_list to wakeup if any, and removes them from\n  // the list of waiters.  In addition, it places waitp.thread on the queue of\n  // waiters if waitp is non-zero.\n  for (;;) {\n    v = mu_.load(std::memory_order_relaxed);\n    if ((v & kMuWriter) != 0 && (v & (kMuWait | kMuDesig)) != kMuWait &&\n        waitp == nullptr) {\n      // fast writer release (writer with no waiters or with designated waker)\n      if (mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),\n                                      std::memory_order_release,\n                                      std::memory_order_relaxed)) {\n        return;\n      }\n    } else if ((v & (kMuReader | kMuWait)) == kMuReader && waitp == nullptr) {\n      // fast reader release (reader with no waiters)\n      intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne;\n      if (mu_.compare_exchange_strong(v, v - clear, std::memory_order_release,\n                                      std::memory_order_relaxed)) {\n        return;\n      }\n    } else if ((v & kMuSpin) == 0 &&  // attempt to get spinlock\n               mu_.compare_exchange_strong(v, v | kMuSpin,\n                                           std::memory_order_acquire,\n                                           std::memory_order_relaxed)) {\n      if ((v & kMuWait) == 0) {  // no one to wake\n        intptr_t nv;\n        bool do_enqueue = true;  // always Enqueue() the first time\n        ABSL_RAW_CHECK(waitp != nullptr,\n                       \"UnlockSlow is confused\");  // about to sleep\n        do {  // must loop to release spinlock as reader count may change\n          v = mu_.load(std::memory_order_relaxed);\n          // decrement reader count if there are readers\n          intptr_t new_readers = (v >= kMuOne) ? v - kMuOne : v;\n          PerThreadSynch* new_h = nullptr;\n          if (do_enqueue) {\n            // If we are enqueuing on a CondVar (waitp->cv_word != nullptr) then\n            // we must not retry here.  The initial attempt will always have\n            // succeeded, further attempts would enqueue us against *this due to\n            // Fer() handling.\n            do_enqueue = (waitp->cv_word == nullptr);\n            new_h = Enqueue(nullptr, waitp, new_readers, kMuIsCond);\n          }\n          intptr_t clear = kMuWrWait | kMuWriter;  // by default clear write bit\n          if ((v & kMuWriter) == 0 && ExactlyOneReader(v)) {  // last reader\n            clear = kMuWrWait | kMuReader;                    // clear read bit\n          }\n          nv = (v & kMuLow & ~clear & ~kMuSpin);\n          if (new_h != nullptr) {\n            nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);\n          } else {  // new_h could be nullptr if we queued ourselves on a\n                    // CondVar\n            // In that case, we must place the reader count back in the mutex\n            // word, as Enqueue() did not store it in the new waiter.\n            nv |= new_readers & kMuHigh;\n          }\n          // release spinlock & our lock; retry if reader-count changed\n          // (writer count cannot change since we hold lock)\n        } while (!mu_.compare_exchange_weak(v, nv, std::memory_order_release,\n                                            std::memory_order_relaxed));\n        break;\n      }\n\n      // There are waiters.\n      // Set h to the head of the circular waiter list.\n      PerThreadSynch* h = GetPerThreadSynch(v);\n      if ((v & kMuReader) != 0 && (h->readers & kMuHigh) > kMuOne) {\n        // a reader but not the last\n        h->readers -= kMuOne;    // release our lock\n        intptr_t nv = v;         // normally just release spinlock\n        if (waitp != nullptr) {  // but waitp!=nullptr => must queue ourselves\n          PerThreadSynch* new_h = Enqueue(h, waitp, v, kMuIsCond);\n          ABSL_RAW_CHECK(new_h != nullptr,\n                         \"waiters disappeared during Enqueue()!\");\n          nv &= kMuLow;\n          nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);\n        }\n        mu_.store(nv, std::memory_order_release);  // release spinlock\n        // can release with a store because there were waiters\n        break;\n      }\n\n      // Either we didn't search before, or we marked the queue\n      // as \"maybe_unlocking\" and no one else should have changed it.\n      ABSL_RAW_CHECK(old_h == nullptr || h->maybe_unlocking,\n                     \"Mutex queue changed beneath us\");\n\n      // The lock is becoming free, and there's a waiter\n      if (old_h != nullptr &&\n          !old_h->may_skip) {    // we used old_h as a terminator\n        old_h->may_skip = true;  // allow old_h to skip once more\n        ABSL_RAW_CHECK(old_h->skip == nullptr, \"illegal skip from head\");\n        if (h != old_h && MuEquivalentWaiter(old_h, old_h->next)) {\n          old_h->skip = old_h->next;  // old_h not head & can skip to successor\n        }\n      }\n      if (h->next->waitp->how == kExclusive &&\n          h->next->waitp->cond == nullptr) {\n        // easy case: writer with no condition; no need to search\n        pw = h;  // wake w, the successor of h (=pw)\n        w = h->next;\n        w->wake = true;\n        // We are waking up a writer.  This writer may be racing against\n        // an already awake reader for the lock.  We want the\n        // writer to usually win this race,\n        // because if it doesn't, we can potentially keep taking a reader\n        // perpetually and writers will starve.  Worse than\n        // that, this can also starve other readers if kMuWrWait gets set\n        // later.\n        wr_wait = kMuWrWait;\n      } else if (w != nullptr && (w->waitp->how == kExclusive || h == old_h)) {\n        // we found a waiter w to wake on a previous iteration and either it's\n        // a writer, or we've searched the entire list so we have all the\n        // readers.\n        if (pw == nullptr) {  // if w's predecessor is unknown, it must be h\n          pw = h;\n        }\n      } else {\n        // At this point we don't know all the waiters to wake, and the first\n        // waiter has a condition or is a reader.  We avoid searching over\n        // waiters we've searched on previous iterations by starting at\n        // old_h if it's set.  If old_h==h, there's no one to wakeup at all.\n        if (old_h == h) {  // we've searched before, and nothing's new\n                           // so there's no one to wake.\n          intptr_t nv = (v & ~(kMuReader | kMuWriter | kMuWrWait));\n          h->readers = 0;\n          h->maybe_unlocking = false;  // finished unlocking\n          if (waitp != nullptr) {      // we must queue ourselves and sleep\n            PerThreadSynch* new_h = Enqueue(h, waitp, v, kMuIsCond);\n            nv &= kMuLow;\n            if (new_h != nullptr) {\n              nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);\n            }  // else new_h could be nullptr if we queued ourselves on a\n               // CondVar\n          }\n          // release spinlock & lock\n          // can release with a store because there were waiters\n          mu_.store(nv, std::memory_order_release);\n          break;\n        }\n\n        // set up to walk the list\n        PerThreadSynch* w_walk;   // current waiter during list walk\n        PerThreadSynch* pw_walk;  // previous waiter during list walk\n        if (old_h != nullptr) {   // we've searched up to old_h before\n          pw_walk = old_h;\n          w_walk = old_h->next;\n        } else {  // no prior search, start at beginning\n          pw_walk =\n              nullptr;  // h->next's predecessor may change; don't record it\n          w_walk = h->next;\n        }\n\n        h->may_skip = false;  // ensure we never skip past h in future searches\n                              // even if other waiters are queued after it.\n        ABSL_RAW_CHECK(h->skip == nullptr, \"illegal skip from head\");\n\n        h->maybe_unlocking = true;  // we're about to scan the waiter list\n                                    // without the spinlock held.\n                                    // Enqueue must be conservative about\n                                    // priority queuing.\n\n        // We must release the spinlock to evaluate the conditions.\n        mu_.store(v, std::memory_order_release);  // release just spinlock\n        // can release with a store because there were waiters\n\n        // h is the last waiter queued, and w_walk the first unsearched waiter.\n        // Without the spinlock, the locations mu_ and h->next may now change\n        // underneath us, but since we hold the lock itself, the only legal\n        // change is to add waiters between h and w_walk.  Therefore, it's safe\n        // to walk the path from w_walk to h inclusive. (TryRemove() can remove\n        // a waiter anywhere, but it acquires both the spinlock and the Mutex)\n\n        old_h = h;  // remember we searched to here\n\n        // Walk the path upto and including h looking for waiters we can wake.\n        while (pw_walk != h) {\n          w_walk->wake = false;\n          if (w_walk->waitp->cond ==\n                  nullptr ||  // no condition => vacuously true OR\n                              // this thread's condition is true\n              EvalConditionIgnored(this, w_walk->waitp->cond)) {\n            if (w == nullptr) {\n              w_walk->wake = true;  // can wake this waiter\n              w = w_walk;\n              pw = pw_walk;\n              if (w_walk->waitp->how == kExclusive) {\n                wr_wait = kMuWrWait;\n                break;  // bail if waking this writer\n              }\n            } else if (w_walk->waitp->how == kShared) {  // wake if a reader\n              w_walk->wake = true;\n            } else {  // writer with true condition\n              wr_wait = kMuWrWait;\n            }\n          }\n          if (w_walk->wake) {  // we're waking reader w_walk\n            pw_walk = w_walk;  // don't skip similar waiters\n          } else {             // not waking; skip as much as possible\n            pw_walk = Skip(w_walk);\n          }\n          // If pw_walk == h, then load of pw_walk->next can race with\n          // concurrent write in Enqueue(). However, at the same time\n          // we do not need to do the load, because we will bail out\n          // from the loop anyway.\n          if (pw_walk != h) {\n            w_walk = pw_walk->next;\n          }\n        }\n\n        continue;  // restart for(;;)-loop to wakeup w or to find more waiters\n      }\n      ABSL_RAW_CHECK(pw->next == w, \"pw not w's predecessor\");\n      // The first (and perhaps only) waiter we've chosen to wake is w, whose\n      // predecessor is pw.  If w is a reader, we must wake all the other\n      // waiters with wake==true as well.  We may also need to queue\n      // ourselves if waitp != null.  The spinlock and the lock are still\n      // held.\n\n      // This traverses the list in [ pw->next, h ], where h is the head,\n      // removing all elements with wake==true and placing them in the\n      // singly-linked list wake_list.  Returns the new head.\n      h = DequeueAllWakeable(h, pw, &wake_list);\n\n      intptr_t nv = (v & kMuEvent) | kMuDesig;\n      // assume no waiters left,\n      // set kMuDesig for INV1a\n\n      if (waitp != nullptr) {  // we must queue ourselves and sleep\n        h = Enqueue(h, waitp, v, kMuIsCond);\n        // h is new last waiter; could be null if we queued ourselves on a\n        // CondVar\n      }\n\n      ABSL_RAW_CHECK(wake_list != kPerThreadSynchNull,\n                     \"unexpected empty wake list\");\n\n      if (h != nullptr) {  // there are waiters left\n        h->readers = 0;\n        h->maybe_unlocking = false;  // finished unlocking\n        nv |= wr_wait | kMuWait | reinterpret_cast<intptr_t>(h);\n\n        // Signal to any Scheduler that we are waking from Mutex Unlock\n        // and there are more waiters left, signaling possible contention.\n        ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);\n        clear_waking_des_waker = GetOrCreateCurrentThreadIdentity();\n        ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);\n        clear_waking_des_waker->scheduler_state.waking_designated_waker = true;\n      }\n\n      // release both spinlock & lock\n      // can release with a store because there were waiters\n      mu_.store(nv, std::memory_order_release);\n      break;  // out of for(;;)-loop\n    }\n    // aggressive here; no one can proceed till we do\n    c = synchronization_internal::MutexDelay(c, AGGRESSIVE);\n  }  // end of for(;;)-loop\n\n  if (wake_list != kPerThreadSynchNull) {\n    int64_t total_wait_cycles = 0;\n    int64_t max_wait_cycles = 0;\n    int64_t now = CycleClock::Now();\n    do {\n      // Profile lock contention events only if the waiter was trying to acquire\n      // the lock, not waiting on a condition variable or Condition.\n      if (!wake_list->cond_waiter) {\n        int64_t cycles_waited =\n            (now - wake_list->waitp->contention_start_cycles);\n        total_wait_cycles += cycles_waited;\n        if (max_wait_cycles == 0) max_wait_cycles = cycles_waited;\n        wake_list->waitp->contention_start_cycles = now;\n        wake_list->waitp->should_submit_contention_data = true;\n      }\n      wake_list = Wakeup(wake_list);  // wake waiters\n    } while (wake_list != kPerThreadSynchNull);\n    if (total_wait_cycles > 0) {\n      mutex_tracer(\"slow release\", this, total_wait_cycles);\n      ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);\n      submit_profile_data(total_wait_cycles);\n      ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);\n    }\n  }\n\n  if (clear_waking_des_waker) {\n    clear_waking_des_waker->scheduler_state.waking_designated_waker = false;\n  }\n}\n\n// Used by CondVar implementation to reacquire mutex after waking from\n// condition variable.  This routine is used instead of Lock() because the\n// waiting thread may have been moved from the condition variable queue to the\n// mutex queue without a wakeup, by Trans().  In that case, when the thread is\n// finally woken, the woken thread will believe it has been woken from the\n// condition variable (i.e. its PC will be in when in the CondVar code), when\n// in fact it has just been woken from the mutex.  Thus, it must enter the slow\n// path of the mutex in the same state as if it had just woken from the mutex.\n// That is, it must ensure to clear kMuDesig (INV1b).\nvoid Mutex::Trans(MuHow how) {\n  this->LockSlow(how, nullptr, kMuHasBlocked | kMuIsCond);\n}\n\n// Used by CondVar implementation to effectively wake thread w from the\n// condition variable.  If this mutex is free, we simply wake the thread.\n// It will later acquire the mutex with high probability.  Otherwise, we\n// enqueue thread w on this mutex.\nvoid Mutex::Fer(PerThreadSynch* w) {\n  SchedulingGuard::ScopedDisable disable_rescheduling;\n  int c = 0;\n  ABSL_RAW_CHECK(w->waitp->cond == nullptr,\n                 \"Mutex::Fer while waiting on Condition\");\n  ABSL_RAW_CHECK(w->waitp->cv_word == nullptr,\n                 \"Mutex::Fer with pending CondVar queueing\");\n  // The CondVar timeout is not relevant for the Mutex wait.\n  w->waitp->timeout = {};\n  for (;;) {\n    intptr_t v = mu_.load(std::memory_order_relaxed);\n    // Note: must not queue if the mutex is unlocked (nobody will wake it).\n    // For example, we can have only kMuWait (conditional) or maybe\n    // kMuWait|kMuWrWait.\n    // conflicting != 0 implies that the waking thread cannot currently take\n    // the mutex, which in turn implies that someone else has it and can wake\n    // us if we queue.\n    const intptr_t conflicting =\n        kMuWriter | (w->waitp->how == kShared ? 0 : kMuReader);\n    if ((v & conflicting) == 0) {\n      w->next = nullptr;\n      w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);\n      IncrementSynchSem(this, w);\n      return;\n    } else {\n      if ((v & (kMuSpin | kMuWait)) == 0) {  // no waiters\n        // This thread tries to become the one and only waiter.\n        PerThreadSynch* new_h =\n            Enqueue(nullptr, w->waitp, v, kMuIsCond | kMuIsFer);\n        ABSL_RAW_CHECK(new_h != nullptr,\n                       \"Enqueue failed\");  // we must queue ourselves\n        if (mu_.compare_exchange_strong(\n                v, reinterpret_cast<intptr_t>(new_h) | (v & kMuLow) | kMuWait,\n                std::memory_order_release, std::memory_order_relaxed)) {\n          return;\n        }\n      } else if ((v & kMuSpin) == 0 &&\n                 mu_.compare_exchange_strong(v, v | kMuSpin | kMuWait)) {\n        PerThreadSynch* h = GetPerThreadSynch(v);\n        PerThreadSynch* new_h = Enqueue(h, w->waitp, v, kMuIsCond | kMuIsFer);\n        ABSL_RAW_CHECK(new_h != nullptr,\n                       \"Enqueue failed\");  // we must queue ourselves\n        do {\n          v = mu_.load(std::memory_order_relaxed);\n        } while (!mu_.compare_exchange_weak(\n            v,\n            (v & kMuLow & ~kMuSpin) | kMuWait |\n                reinterpret_cast<intptr_t>(new_h),\n            std::memory_order_release, std::memory_order_relaxed));\n        return;\n      }\n    }\n    c = synchronization_internal::MutexDelay(c, GENTLE);\n  }\n}\n\nvoid Mutex::AssertHeld() const {\n  if ((mu_.load(std::memory_order_relaxed) & kMuWriter) == 0) {\n    SynchEvent* e = GetSynchEvent(this);\n    ABSL_RAW_LOG(FATAL, \"thread should hold write lock on Mutex %p %s\",\n                 static_cast<const void*>(this), (e == nullptr ? \"\" : e->name));\n  }\n}\n\nvoid Mutex::AssertReaderHeld() const {\n  if ((mu_.load(std::memory_order_relaxed) & (kMuReader | kMuWriter)) == 0) {\n    SynchEvent* e = GetSynchEvent(this);\n    ABSL_RAW_LOG(FATAL,\n                 \"thread should hold at least a read lock on Mutex %p %s\",\n                 static_cast<const void*>(this), (e == nullptr ? \"\" : e->name));\n  }\n}\n\n// -------------------------------- condition variables\nstatic const intptr_t kCvSpin = 0x0001L;   // spinlock protects waiter list\nstatic const intptr_t kCvEvent = 0x0002L;  // record events\n\nstatic const intptr_t kCvLow = 0x0003L;  // low order bits of CV\n\n// Hack to make constant values available to gdb pretty printer\nenum {\n  kGdbCvSpin = kCvSpin,\n  kGdbCvEvent = kCvEvent,\n  kGdbCvLow = kCvLow,\n};\n\nstatic_assert(PerThreadSynch::kAlignment > kCvLow,\n              \"PerThreadSynch::kAlignment must be greater than kCvLow\");\n\nvoid CondVar::EnableDebugLog(const char* name) {\n  SynchEvent* e = EnsureSynchEvent(&this->cv_, name, kCvEvent, kCvSpin);\n  e->log = true;\n  UnrefSynchEvent(e);\n}\n\n// Remove thread s from the list of waiters on this condition variable.\nvoid CondVar::Remove(PerThreadSynch* s) {\n  SchedulingGuard::ScopedDisable disable_rescheduling;\n  intptr_t v;\n  int c = 0;\n  for (v = cv_.load(std::memory_order_relaxed);;\n       v = cv_.load(std::memory_order_relaxed)) {\n    if ((v & kCvSpin) == 0 &&  // attempt to acquire spinlock\n        cv_.compare_exchange_strong(v, v | kCvSpin, std::memory_order_acquire,\n                                    std::memory_order_relaxed)) {\n      PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);\n      if (h != nullptr) {\n        PerThreadSynch* w = h;\n        while (w->next != s && w->next != h) {  // search for thread\n          w = w->next;\n        }\n        if (w->next == s) {  // found thread; remove it\n          w->next = s->next;\n          if (h == s) {\n            h = (w == s) ? nullptr : w;\n          }\n          s->next = nullptr;\n          s->state.store(PerThreadSynch::kAvailable, std::memory_order_release);\n        }\n      }\n      // release spinlock\n      cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h),\n                std::memory_order_release);\n      return;\n    } else {\n      // try again after a delay\n      c = synchronization_internal::MutexDelay(c, GENTLE);\n    }\n  }\n}\n\n// Queue thread waitp->thread on condition variable word cv_word using\n// wait parameters waitp.\n// We split this into a separate routine, rather than simply doing it as part\n// of WaitCommon().  If we were to queue ourselves on the condition variable\n// before calling Mutex::UnlockSlow(), the Mutex code might be re-entered (via\n// the logging code, or via a Condition function) and might potentially attempt\n// to block this thread.  That would be a problem if the thread were already on\n// a condition variable waiter queue.  Thus, we use the waitp->cv_word to tell\n// the unlock code to call CondVarEnqueue() to queue the thread on the condition\n// variable queue just before the mutex is to be unlocked, and (most\n// importantly) after any call to an external routine that might re-enter the\n// mutex code.\nstatic void CondVarEnqueue(SynchWaitParams* waitp) {\n  // This thread might be transferred to the Mutex queue by Fer() when\n  // we are woken.  To make sure that is what happens, Enqueue() doesn't\n  // call CondVarEnqueue() again but instead uses its normal code.  We\n  // must do this before we queue ourselves so that cv_word will be null\n  // when seen by the dequeuer, who may wish immediately to requeue\n  // this thread on another queue.\n  std::atomic<intptr_t>* cv_word = waitp->cv_word;\n  waitp->cv_word = nullptr;\n\n  intptr_t v = cv_word->load(std::memory_order_relaxed);\n  int c = 0;\n  while ((v & kCvSpin) != 0 ||  // acquire spinlock\n         !cv_word->compare_exchange_weak(v, v | kCvSpin,\n                                         std::memory_order_acquire,\n                                         std::memory_order_relaxed)) {\n    c = synchronization_internal::MutexDelay(c, GENTLE);\n    v = cv_word->load(std::memory_order_relaxed);\n  }\n  ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, \"waiting when shouldn't be\");\n  waitp->thread->waitp = waitp;  // prepare ourselves for waiting\n  PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);\n  if (h == nullptr) {  // add this thread to waiter list\n    waitp->thread->next = waitp->thread;\n  } else {\n    waitp->thread->next = h->next;\n    h->next = waitp->thread;\n  }\n  waitp->thread->state.store(PerThreadSynch::kQueued,\n                             std::memory_order_relaxed);\n  cv_word->store((v & kCvEvent) | reinterpret_cast<intptr_t>(waitp->thread),\n                 std::memory_order_release);\n}\n\nbool CondVar::WaitCommon(Mutex* mutex, KernelTimeout t) {\n  bool rc = false;  // return value; true iff we timed-out\n\n  intptr_t mutex_v = mutex->mu_.load(std::memory_order_relaxed);\n  Mutex::MuHow mutex_how = ((mutex_v & kMuWriter) != 0) ? kExclusive : kShared;\n  ABSL_TSAN_MUTEX_PRE_UNLOCK(mutex, TsanFlags(mutex_how));\n\n  // maybe trace this call\n  intptr_t v = cv_.load(std::memory_order_relaxed);\n  cond_var_tracer(\"Wait\", this);\n  if ((v & kCvEvent) != 0) {\n    PostSynchEvent(this, SYNCH_EV_WAIT);\n  }\n\n  // Release mu and wait on condition variable.\n  SynchWaitParams waitp(mutex_how, nullptr, t, mutex,\n                        Synch_GetPerThreadAnnotated(mutex), &cv_);\n  // UnlockSlow() will call CondVarEnqueue() just before releasing the\n  // Mutex, thus queuing this thread on the condition variable.  See\n  // CondVarEnqueue() for the reasons.\n  mutex->UnlockSlow(&waitp);\n\n  // wait for signal\n  while (waitp.thread->state.load(std::memory_order_acquire) ==\n         PerThreadSynch::kQueued) {\n    if (!Mutex::DecrementSynchSem(mutex, waitp.thread, t)) {\n      // DecrementSynchSem returned due to timeout.\n      // Now we will either (1) remove ourselves from the wait list in Remove\n      // below, in which case Remove will set thread.state = kAvailable and\n      // we will not call DecrementSynchSem again; or (2) Signal/SignalAll\n      // has removed us concurrently and is calling Wakeup, which will set\n      // thread.state = kAvailable and post to the semaphore.\n      // It's important to reset the timeout for the case (2) because otherwise\n      // we can live-lock in this loop since DecrementSynchSem will always\n      // return immediately due to timeout, but Signal/SignalAll is not\n      // necessary set thread.state = kAvailable yet (and is not scheduled\n      // due to thread priorities or other scheduler artifacts).\n      // Note this could also be resolved if Signal/SignalAll would set\n      // thread.state = kAvailable while holding the wait list spin lock.\n      // But this can't be easily done for SignalAll since it grabs the whole\n      // wait list with a single compare-exchange and does not really grab\n      // the spin lock.\n      t = KernelTimeout::Never();\n      this->Remove(waitp.thread);\n      rc = true;\n    }\n  }\n\n  ABSL_RAW_CHECK(waitp.thread->waitp != nullptr, \"not waiting when should be\");\n  waitp.thread->waitp = nullptr;  // cleanup\n\n  // maybe trace this call\n  cond_var_tracer(\"Unwait\", this);\n  if ((v & kCvEvent) != 0) {\n    PostSynchEvent(this, SYNCH_EV_WAIT_RETURNING);\n  }\n\n  // From synchronization point of view Wait is unlock of the mutex followed\n  // by lock of the mutex. We've annotated start of unlock in the beginning\n  // of the function. Now, finish unlock and annotate lock of the mutex.\n  // (Trans is effectively lock).\n  ABSL_TSAN_MUTEX_POST_UNLOCK(mutex, TsanFlags(mutex_how));\n  ABSL_TSAN_MUTEX_PRE_LOCK(mutex, TsanFlags(mutex_how));\n  mutex->Trans(mutex_how);  // Reacquire mutex\n  ABSL_TSAN_MUTEX_POST_LOCK(mutex, TsanFlags(mutex_how), 0);\n  return rc;\n}\n\nvoid CondVar::Signal() {\n  SchedulingGuard::ScopedDisable disable_rescheduling;\n  ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);\n  intptr_t v;\n  int c = 0;\n  for (v = cv_.load(std::memory_order_relaxed); v != 0;\n       v = cv_.load(std::memory_order_relaxed)) {\n    if ((v & kCvSpin) == 0 &&  // attempt to acquire spinlock\n        cv_.compare_exchange_strong(v, v | kCvSpin, std::memory_order_acquire,\n                                    std::memory_order_relaxed)) {\n      PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);\n      PerThreadSynch* w = nullptr;\n      if (h != nullptr) {  // remove first waiter\n        w = h->next;\n        if (w == h) {\n          h = nullptr;\n        } else {\n          h->next = w->next;\n        }\n      }\n      // release spinlock\n      cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h),\n                std::memory_order_release);\n      if (w != nullptr) {\n        w->waitp->cvmu->Fer(w);  // wake waiter, if there was one\n        cond_var_tracer(\"Signal wakeup\", this);\n      }\n      if ((v & kCvEvent) != 0) {\n        PostSynchEvent(this, SYNCH_EV_SIGNAL);\n      }\n      ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);\n      return;\n    } else {\n      c = synchronization_internal::MutexDelay(c, GENTLE);\n    }\n  }\n  ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);\n}\n\nvoid CondVar::SignalAll() {\n  ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);\n  intptr_t v;\n  int c = 0;\n  for (v = cv_.load(std::memory_order_relaxed); v != 0;\n       v = cv_.load(std::memory_order_relaxed)) {\n    // empty the list if spinlock free\n    // We do this by simply setting the list to empty using\n    // compare and swap.   We then have the entire list in our hands,\n    // which cannot be changing since we grabbed it while no one\n    // held the lock.\n    if ((v & kCvSpin) == 0 &&\n        cv_.compare_exchange_strong(v, v & kCvEvent, std::memory_order_acquire,\n                                    std::memory_order_relaxed)) {\n      PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);\n      if (h != nullptr) {\n        PerThreadSynch* w;\n        PerThreadSynch* n = h->next;\n        do {  // for every thread, wake it up\n          w = n;\n          n = n->next;\n          w->waitp->cvmu->Fer(w);\n        } while (w != h);\n        cond_var_tracer(\"SignalAll wakeup\", this);\n      }\n      if ((v & kCvEvent) != 0) {\n        PostSynchEvent(this, SYNCH_EV_SIGNALALL);\n      }\n      ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);\n      return;\n    } else {\n      // try again after a delay\n      c = synchronization_internal::MutexDelay(c, GENTLE);\n    }\n  }\n  ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);\n}\n\nvoid ReleasableMutexLock::Release() {\n  ABSL_RAW_CHECK(this->mu_ != nullptr,\n                 \"ReleasableMutexLock::Release may only be called once\");\n  this->mu_->unlock();\n  this->mu_ = nullptr;\n}\n\n#ifdef ABSL_HAVE_THREAD_SANITIZER\nextern \"C\" void __tsan_read1(void* addr);\n#else\n#define __tsan_read1(addr)  // do nothing if TSan not enabled\n#endif\n\n// A function that just returns its argument, dereferenced\nstatic bool Dereference(void* arg) {\n  // ThreadSanitizer does not instrument this file for memory accesses.\n  // This function dereferences a user variable that can participate\n  // in a data race, so we need to manually tell TSan about this memory access.\n  __tsan_read1(arg);\n  return *(static_cast<bool*>(arg));\n}\n\nABSL_CONST_INIT const Condition Condition::kTrue;\n\nCondition::Condition(bool (*func)(void*), void* arg)\n    : eval_(&CallVoidPtrFunction), arg_(arg) {\n  static_assert(sizeof(&func) <= sizeof(callback_),\n                \"An overlarge function pointer passed to Condition.\");\n  StoreCallback(func);\n}\n\nbool Condition::CallVoidPtrFunction(const Condition* c) {\n  using FunctionPointer = bool (*)(void*);\n  FunctionPointer function_pointer;\n  std::memcpy(&function_pointer, c->callback_, sizeof(function_pointer));\n  return (*function_pointer)(c->arg_);\n}\n\nCondition::Condition(const bool* cond)\n    : eval_(CallVoidPtrFunction),\n      // const_cast is safe since Dereference does not modify arg\n      arg_(const_cast<bool*>(cond)) {\n  using FunctionPointer = bool (*)(void*);\n  const FunctionPointer dereference = Dereference;\n  StoreCallback(dereference);\n}\n\nbool Condition::Eval() const { return (*this->eval_)(this); }\n\nbool Condition::GuaranteedEqual(const Condition* a, const Condition* b) {\n  if (a == nullptr || b == nullptr) {\n    return a == b;\n  }\n  // Check equality of the representative fields.\n  return a->eval_ == b->eval_ && a->arg_ == b->arg_ &&\n         !memcmp(a->callback_, b->callback_, sizeof(a->callback_));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/mutex.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// mutex.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a `Mutex` -- a mutually exclusive lock -- and the\n// most common type of synchronization primitive for facilitating locks on\n// shared resources. A mutex is used to prevent multiple threads from accessing\n// and/or writing to a shared resource concurrently.\n//\n// Unlike a `std::mutex`, the Abseil `Mutex` provides the following additional\n// features:\n//   * Conditional predicates intrinsic to the `Mutex` object\n//   * Shared/reader locks, in addition to standard exclusive/writer locks\n//   * Deadlock detection and debug support.\n//\n// The following helper classes are also defined within this file:\n//\n//  MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/\n//              write access within the current scope.\n//\n//  ReaderMutexLock\n//            - An RAII wrapper to acquire and release a `Mutex` for shared/read\n//              access within the current scope.\n//\n//  WriterMutexLock\n//            - Effectively an alias for `MutexLock` above, designed for use in\n//              distinguishing reader and writer locks within code.\n//\n// In addition to simple mutex locks, this file also defines ways to perform\n// locking under certain conditions.\n//\n//  Condition - (Preferred) Used to wait for a particular predicate that\n//              depends on state protected by the `Mutex` to become true.\n//  CondVar   - A lower-level variant of `Condition` that relies on\n//              application code to explicitly signal the `CondVar` when\n//              a condition has been met.\n//\n// See below for more information on using `Condition` or `CondVar`.\n//\n// Mutexes and mutex behavior can be quite complicated. The information within\n// this header file is limited, as a result. Please consult the Mutex guide for\n// more complete information and examples.\n\n#ifndef ABSL_SYNCHRONIZATION_MUTEX_H_\n#define ABSL_SYNCHRONIZATION_MUTEX_H_\n\n#include <atomic>\n#include <cstdint>\n#include <cstring>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/const_init.h\"\n#include \"absl/base/internal/thread_identity.h\"\n#include \"absl/base/internal/tsan_mutex_interface.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/synchronization/internal/kernel_timeout.h\"\n#include \"absl/synchronization/internal/per_thread_sem.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass Condition;\nstruct SynchWaitParams;\n\nnamespace synchronization_internal {\n\ntemplate <typename T, typename = void>\nstruct HasConstMemberCallOperator : std::false_type {};\n\ntemplate <typename T>\nstruct HasConstMemberCallOperator<\n    T, std::void_t<decltype(static_cast<bool (T::*)() const>(&T::operator()))>>\n    : std::true_type {};\n\n}  // namespace synchronization_internal\n\n// -----------------------------------------------------------------------------\n// Mutex\n// -----------------------------------------------------------------------------\n//\n// A `Mutex` is a non-reentrant (aka non-recursive) Mutually Exclusive lock\n// on some resource, typically a variable or data structure with associated\n// invariants. Proper usage of mutexes prevents concurrent access by different\n// threads to the same resource.\n//\n// A `Mutex` has two basic operations: `Mutex::lock()` and `Mutex::unlock()`.\n// The `lock()` operation *acquires* a `Mutex` (in a state known as an\n// *exclusive* -- or *write* -- lock), and the `unlock()` operation *releases* a\n// Mutex. During the span of time between the lock() and unlock() operations,\n// a mutex is said to be *held*. By design, all mutexes support exclusive/write\n// locks, as this is the most common way to use a mutex.\n//\n// Mutex operations are only allowed under certain conditions; otherwise an\n// operation is \"invalid\", and disallowed by the API. The conditions concern\n// both the current state of the mutex and the identity of the threads that\n// are performing the operations.\n//\n// The `Mutex` state machine for basic lock/unlock operations is quite simple:\n//\n// |                | lock()                 | unlock() |\n// |----------------+------------------------+----------|\n// | Free           | Exclusive              | invalid  |\n// | Exclusive      | blocks, then exclusive | Free     |\n//\n// The full conditions are as follows.\n//\n// * Calls to `unlock()` require that the mutex be held, and must be made in the\n//   same thread that performed the corresponding `lock()` operation which\n//   acquired the mutex; otherwise the call is invalid.\n//\n// * The mutex being non-reentrant (or non-recursive) means that a call to\n//   `lock()` or `try_lock()` must not be made in a thread that already holds\n//   the mutex; such a call is invalid.\n//\n// * In other words, the state of being \"held\" has both a temporal component\n//   (from `lock()` until `unlock()`) as well as a thread identity component:\n//   the mutex is held *by a particular thread*.\n//\n// An \"invalid\" operation has undefined behavior. The `Mutex` implementation\n// is allowed to do anything on an invalid call, including, but not limited to,\n// crashing with a useful error message, silently succeeding, or corrupting\n// data structures. In debug mode, the implementation may crash with a useful\n// error message.\n//\n// `Mutex` is not guaranteed to be \"fair\" in prioritizing waiting threads; it\n// is, however, approximately fair over long periods, and starvation-free for\n// threads at the same priority.\n//\n// The lock/unlock primitives are now annotated with lock annotations\n// defined in (base/thread_annotations.h). When writing multi-threaded code,\n// you should use lock annotations whenever possible to document your lock\n// synchronization policy. Besides acting as documentation, these annotations\n// also help compilers or static analysis tools to identify and warn about\n// issues that could potentially result in race conditions and deadlocks.\n//\n// For more information about the lock annotations, please see\n// [Thread Safety\n// Analysis](http://clang.llvm.org/docs/ThreadSafetyAnalysis.html) in the Clang\n// documentation.\n//\n// See also `MutexLock`, below, for scoped `Mutex` acquisition.\n\nclass ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED Mutex {\n public:\n  // Creates a `Mutex` that is not held by anyone. This constructor is\n  // typically used for Mutexes allocated on the heap or the stack.\n  //\n  // To create `Mutex` instances with static storage duration\n  // (e.g. a namespace-scoped or global variable), see\n  // `Mutex::Mutex(absl::kConstInit)` below instead.\n  Mutex();\n\n  // Creates a mutex with static storage duration.  A global variable\n  // constructed this way avoids the lifetime issues that can occur on program\n  // startup and shutdown.  (See absl/base/const_init.h.)\n  //\n  // For Mutexes allocated on the heap and stack, instead use the default\n  // constructor, which can interact more fully with the thread sanitizer.\n  //\n  // Example usage:\n  //   namespace foo {\n  //   ABSL_CONST_INIT absl::Mutex mu(absl::kConstInit);\n  //   }\n  explicit constexpr Mutex(absl::ConstInitType);\n\n  ~Mutex();\n\n  // Mutex::lock()\n  //\n  // Blocks the calling thread, if necessary, until this `Mutex` is free, and\n  // then acquires it exclusively. (This lock is also known as a \"write lock.\")\n  void lock() ABSL_EXCLUSIVE_LOCK_FUNCTION();\n\n  ABSL_DEPRECATE_AND_INLINE()\n  inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { lock(); }\n\n  // Mutex::unlock()\n  //\n  // Releases this `Mutex` and returns it from the exclusive/write state to the\n  // free state. Calling thread must hold the `Mutex` exclusively.\n  void unlock() ABSL_UNLOCK_FUNCTION();\n\n  ABSL_DEPRECATE_AND_INLINE()\n  inline void Unlock() ABSL_UNLOCK_FUNCTION() { unlock(); }\n\n  // Mutex::try_lock()\n  //\n  // If the mutex can be acquired without blocking, does so exclusively and\n  // returns `true`. Otherwise, returns `false`. Returns `true` with high\n  // probability if the `Mutex` was free.\n  [[nodiscard]] bool try_lock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true);\n\n  ABSL_DEPRECATE_AND_INLINE()\n  [[nodiscard]] bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {\n    return try_lock();\n  }\n\n  // Mutex::AssertHeld()\n  //\n  // Require that the mutex be held exclusively (write mode) by this thread.\n  //\n  // If the mutex is not currently held by this thread, this function may report\n  // an error (typically by crashing with a diagnostic) or it may do nothing.\n  // This function is intended only as a tool to assist debugging; it doesn't\n  // guarantee correctness.\n  void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK();\n\n  // ---------------------------------------------------------------------------\n  // Reader-Writer Locking\n  // ---------------------------------------------------------------------------\n\n  // A Mutex can also be used as a starvation-free reader-writer lock.\n  // Neither read-locks nor write-locks are reentrant/recursive to avoid\n  // potential client programming errors.\n  //\n  // The Mutex API provides `Writer*()` aliases for the existing `lock()`,\n  // `unlock()` and `try_lock()` methods for use within applications mixing\n  // reader/writer locks. Using `*_shared()` and `Writer*()` operations in this\n  // manner can make locking behavior clearer when mixing read and write modes.\n  //\n  // Introducing reader locks necessarily complicates the `Mutex` state\n  // machine somewhat. The table below illustrates the allowed state transitions\n  // of a mutex in such cases. Note that lock_shared() may block even if the\n  // lock is held in shared mode; this occurs when another thread is blocked on\n  // a call to lock().\n  //\n  // ---------------------------------------------------------------------------\n  //     Operation: lock()       unlock()  lock_shared() unlock_shared()\n  // ---------------------------------------------------------------------------\n  // State\n  // ---------------------------------------------------------------------------\n  // Free           Exclusive    invalid   Shared(1)              invalid\n  // Shared(1)      blocks       invalid   Shared(2) or blocks    Free\n  // Shared(n) n>1  blocks       invalid   Shared(n+1) or blocks  Shared(n-1)\n  // Exclusive      blocks       Free      blocks                 invalid\n  // ---------------------------------------------------------------------------\n  //\n  // In comments below, \"shared\" refers to a state of Shared(n) for any n > 0.\n\n  // Mutex::lock_shared()\n  //\n  // Blocks the calling thread, if necessary, until this `Mutex` is either free,\n  // or in shared mode, and then acquires a share of it. Note that\n  // `lock_shared()` will block if some other thread has an exclusive/writer\n  // lock on the mutex.\n  void lock_shared() ABSL_SHARED_LOCK_FUNCTION();\n\n  ABSL_DEPRECATE_AND_INLINE()\n  void ReaderLock() ABSL_SHARED_LOCK_FUNCTION() { lock_shared(); }\n\n  // Mutex::unlock_shared()\n  //\n  // Releases a read share of this `Mutex`. `unlock_shared` may return a mutex\n  // to the free state if this thread holds the last reader lock on the mutex.\n  // Note that you cannot call `unlock_shared()` on a mutex held in write mode.\n  void unlock_shared() ABSL_UNLOCK_FUNCTION();\n\n  ABSL_DEPRECATE_AND_INLINE()\n  void ReaderUnlock() ABSL_UNLOCK_FUNCTION() { unlock_shared(); }\n\n  // Mutex::try_lock_shared()\n  //\n  // If the mutex can be acquired without blocking, acquires this mutex for\n  // shared access and returns `true`. Otherwise, returns `false`. Returns\n  // `true` with high probability if the `Mutex` was free or shared.\n  [[nodiscard]] bool try_lock_shared() ABSL_SHARED_TRYLOCK_FUNCTION(true);\n\n  ABSL_DEPRECATE_AND_INLINE()\n  [[nodiscard]] bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true) {\n    return try_lock_shared();\n  }\n\n  // Mutex::AssertReaderHeld()\n  //\n  // Require that the mutex be held at least in shared mode (read mode) by this\n  // thread.\n  //\n  // If the mutex is not currently held by this thread, this function may report\n  // an error (typically by crashing with a diagnostic) or it may do nothing.\n  // This function is intended only as a tool to assist debugging; it doesn't\n  // guarantee correctness.\n  void AssertReaderHeld() const ABSL_ASSERT_SHARED_LOCK();\n\n  // Mutex::WriterLock()\n  // Mutex::WriterUnlock()\n  // Mutex::WriterTryLock()\n  //\n  // Aliases for `Mutex::Lock()`, `Mutex::Unlock()`, and `Mutex::TryLock()`.\n  //\n  // These methods may be used (along with the complementary `Reader*()`\n  // methods) to distinguish simple exclusive `Mutex` usage (`Lock()`,\n  // etc.) from reader/writer lock usage.\n  ABSL_DEPRECATE_AND_INLINE()\n  void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { lock(); }\n\n  ABSL_DEPRECATE_AND_INLINE()\n  void WriterUnlock() ABSL_UNLOCK_FUNCTION() { unlock(); }\n\n  ABSL_DEPRECATE_AND_INLINE()\n  [[nodiscard]] bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {\n    return try_lock();\n  }\n\n  // ---------------------------------------------------------------------------\n  // Conditional Critical Regions\n  // ---------------------------------------------------------------------------\n\n  // Conditional usage of a `Mutex` can occur using two distinct paradigms:\n  //\n  //   * Use of `Mutex` member functions with `Condition` objects.\n  //   * Use of the separate `CondVar` abstraction.\n  //\n  // In general, prefer use of `Condition` and the `Mutex` member functions\n  // listed below over `CondVar`. When there are multiple threads waiting on\n  // distinctly different conditions, however, a battery of `CondVar`s may be\n  // more efficient. This section discusses use of `Condition` objects.\n  //\n  // `Mutex` contains member functions for performing lock operations only under\n  // certain conditions, of class `Condition`. For correctness, the `Condition`\n  // must return a boolean that is a pure function, only of state protected by\n  // the `Mutex`. The condition must be invariant w.r.t. environmental state\n  // such as thread, cpu id, or time, and must be `noexcept`. The condition will\n  // always be invoked with the mutex held in at least read mode, so you should\n  // not block it for long periods or sleep it on a timer.\n  //\n  // Since a condition must not depend directly on the current time, use\n  // `*WithTimeout()` member function variants to make your condition\n  // effectively true after a given duration, or `*WithDeadline()` variants to\n  // make your condition effectively true after a given time.\n  //\n  // The condition function should have no side-effects aside from debug\n  // logging; as a special exception, the function may acquire other mutexes\n  // provided it releases all those that it acquires.  (This exception was\n  // required to allow logging.)\n\n  // Mutex::Await()\n  //\n  // Unlocks this `Mutex` and blocks until simultaneously both `cond` is `true`\n  // and this `Mutex` can be reacquired, then reacquires this `Mutex` in the\n  // same mode in which it was previously held. If the condition is initially\n  // `true`, `Await()` *may* skip the release/re-acquire step.\n  //\n  // `Await()` requires that this thread holds this `Mutex` in some mode.\n  void Await(const Condition& cond) {\n    AwaitCommon(cond, synchronization_internal::KernelTimeout::Never());\n  }\n\n  // Mutex::LockWhen()\n  // Mutex::ReaderLockWhen()\n  // Mutex::WriterLockWhen()\n  //\n  // Blocks until simultaneously both `cond` is `true` and this `Mutex` can\n  // be acquired, then atomically acquires this `Mutex`. `LockWhen()` is\n  // logically equivalent to `*Lock(); Await();` though they may have different\n  // performance characteristics.\n  void LockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    LockWhenCommon(cond, synchronization_internal::KernelTimeout::Never(),\n                   true);\n  }\n\n  void ReaderLockWhen(const Condition& cond) ABSL_SHARED_LOCK_FUNCTION() {\n    LockWhenCommon(cond, synchronization_internal::KernelTimeout::Never(),\n                   false);\n  }\n\n  void WriterLockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    this->LockWhen(cond);\n  }\n\n  // ---------------------------------------------------------------------------\n  // Mutex Variants with Timeouts/Deadlines\n  // ---------------------------------------------------------------------------\n\n  // Mutex::AwaitWithTimeout()\n  // Mutex::AwaitWithDeadline()\n  //\n  // Unlocks this `Mutex` and blocks until simultaneously:\n  //   - either `cond` is true or the {timeout has expired, deadline has passed}\n  //     and\n  //   - this `Mutex` can be reacquired,\n  // then reacquire this `Mutex` in the same mode in which it was previously\n  // held, returning `true` iff `cond` is `true` on return.\n  //\n  // If the condition is initially `true`, the implementation *may* skip the\n  // release/re-acquire step and return immediately.\n  //\n  // Deadlines in the past are equivalent to an immediate deadline.\n  // Negative timeouts are equivalent to a zero timeout.\n  //\n  // This method requires that this thread holds this `Mutex` in some mode.\n  bool AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {\n    return AwaitCommon(cond, synchronization_internal::KernelTimeout{timeout});\n  }\n\n  bool AwaitWithDeadline(const Condition& cond, absl::Time deadline) {\n    return AwaitCommon(cond, synchronization_internal::KernelTimeout{deadline});\n  }\n\n  // Mutex::LockWhenWithTimeout()\n  // Mutex::ReaderLockWhenWithTimeout()\n  // Mutex::WriterLockWhenWithTimeout()\n  //\n  // Blocks until simultaneously both:\n  //   - either `cond` is `true` or the timeout has expired, and\n  //   - this `Mutex` can be acquired,\n  // then atomically acquires this `Mutex`, returning `true` iff `cond` is\n  // `true` on return.\n  //\n  // Negative timeouts are equivalent to a zero timeout.\n  bool LockWhenWithTimeout(const Condition& cond, absl::Duration timeout)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    return LockWhenCommon(\n        cond, synchronization_internal::KernelTimeout{timeout}, true);\n  }\n  bool ReaderLockWhenWithTimeout(const Condition& cond, absl::Duration timeout)\n      ABSL_SHARED_LOCK_FUNCTION() {\n    return LockWhenCommon(\n        cond, synchronization_internal::KernelTimeout{timeout}, false);\n  }\n  bool WriterLockWhenWithTimeout(const Condition& cond, absl::Duration timeout)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    return this->LockWhenWithTimeout(cond, timeout);\n  }\n\n  // Mutex::LockWhenWithDeadline()\n  // Mutex::ReaderLockWhenWithDeadline()\n  // Mutex::WriterLockWhenWithDeadline()\n  //\n  // Blocks until simultaneously both:\n  //   - either `cond` is `true` or the deadline has been passed, and\n  //   - this `Mutex` can be acquired,\n  // then atomically acquires this Mutex, returning `true` iff `cond` is `true`\n  // on return.\n  //\n  // Deadlines in the past are equivalent to an immediate deadline.\n  bool LockWhenWithDeadline(const Condition& cond, absl::Time deadline)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    return LockWhenCommon(\n        cond, synchronization_internal::KernelTimeout{deadline}, true);\n  }\n  bool ReaderLockWhenWithDeadline(const Condition& cond, absl::Time deadline)\n      ABSL_SHARED_LOCK_FUNCTION() {\n    return LockWhenCommon(\n        cond, synchronization_internal::KernelTimeout{deadline}, false);\n  }\n  bool WriterLockWhenWithDeadline(const Condition& cond, absl::Time deadline)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION() {\n    return this->LockWhenWithDeadline(cond, deadline);\n  }\n\n  // ---------------------------------------------------------------------------\n  // Debug Support: Invariant Checking, Deadlock Detection, Logging.\n  // ---------------------------------------------------------------------------\n\n  // Mutex::EnableInvariantDebugging()\n  //\n  // If `invariant`!=null and if invariant debugging has been enabled globally,\n  // cause `(*invariant)(arg)` to be called at moments when the invariant for\n  // this `Mutex` should hold (for example: just after acquire, just before\n  // release).\n  //\n  // The routine `invariant` should have no side-effects since it is not\n  // guaranteed how many times it will be called; it should check the invariant\n  // and crash if it does not hold. Enabling global invariant debugging may\n  // substantially reduce `Mutex` performance; it should be set only for\n  // non-production runs.  Optimization options may also disable invariant\n  // checks.\n  void EnableInvariantDebugging(\n      void (*absl_nullable invariant)(void* absl_nullability_unknown),\n      void* absl_nullability_unknown arg);\n\n  // Mutex::EnableDebugLog()\n  //\n  // Cause all subsequent uses of this `Mutex` to be logged via\n  // `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if no previous\n  // call to `EnableInvariantDebugging()` or `EnableDebugLog()` has been made.\n  //\n  // Note: This method substantially reduces `Mutex` performance.\n  void EnableDebugLog(const char* absl_nullable name);\n\n  // Deadlock detection\n\n  // Mutex::ForgetDeadlockInfo()\n  //\n  // Forget any deadlock-detection information previously gathered\n  // about this `Mutex`. Call this method in debug mode when the lock ordering\n  // of a `Mutex` changes.\n  void ForgetDeadlockInfo();\n\n  // Mutex::AssertNotHeld()\n  //\n  // Return immediately if this thread does not hold this `Mutex` in any\n  // mode; otherwise, may report an error (typically by crashing with a\n  // diagnostic), or may return immediately.\n  //\n  // Currently this check is performed only if all of:\n  //    - in debug mode\n  //    - SetMutexDeadlockDetectionMode() has been set to kReport or kAbort\n  //    - number of locks concurrently held by this thread is not large.\n  // are true.\n  void AssertNotHeld() const;\n\n  // Special cases.\n\n  // A `MuHow` is a constant that indicates how a lock should be acquired.\n  // Internal implementation detail.  Clients should ignore.\n  typedef const struct MuHowS* MuHow;\n\n  // Mutex::InternalAttemptToUseMutexInFatalSignalHandler()\n  //\n  // Causes the `Mutex` implementation to prepare itself for re-entry caused by\n  // future use of `Mutex` within a fatal signal handler. This method is\n  // intended for use only for last-ditch attempts to log crash information.\n  // It does not guarantee that attempts to use Mutexes within the handler will\n  // not deadlock; it merely makes other faults less likely.\n  //\n  // WARNING:  This routine must be invoked from a signal handler, and the\n  // signal handler must either loop forever or terminate the process.\n  // Attempts to return from (or `longjmp` out of) the signal handler once this\n  // call has been made may cause arbitrary program behaviour including\n  // crashes and deadlocks.\n  static void InternalAttemptToUseMutexInFatalSignalHandler();\n\n private:\n  std::atomic<intptr_t> mu_;  // The Mutex state.\n\n  // Post()/Wait() versus associated PerThreadSem; in class for required\n  // friendship with PerThreadSem.\n  static void IncrementSynchSem(Mutex* absl_nonnull mu,\n                                base_internal::PerThreadSynch* absl_nonnull w);\n  static bool DecrementSynchSem(Mutex* absl_nonnull mu,\n                                base_internal::PerThreadSynch* absl_nonnull w,\n                                synchronization_internal::KernelTimeout t);\n\n  // slow path acquire\n  void LockSlowLoop(SynchWaitParams* absl_nonnull waitp, int flags);\n  // wrappers around LockSlowLoop()\n  bool LockSlowWithDeadline(MuHow absl_nonnull how,\n                            const Condition* absl_nullable cond,\n                            synchronization_internal::KernelTimeout t,\n                            int flags);\n  void LockSlow(MuHow absl_nonnull how, const Condition* absl_nullable cond,\n                int flags) ABSL_ATTRIBUTE_COLD;\n  // slow path release\n  void UnlockSlow(SynchWaitParams* absl_nullable waitp) ABSL_ATTRIBUTE_COLD;\n  // TryLock slow path.\n  bool TryLockSlow();\n  // ReaderTryLock slow path.\n  bool ReaderTryLockSlow();\n  // Common code between Await() and AwaitWithTimeout/Deadline()\n  bool AwaitCommon(const Condition& cond,\n                   synchronization_internal::KernelTimeout t);\n  bool LockWhenCommon(const Condition& cond,\n                      synchronization_internal::KernelTimeout t, bool write);\n  // Attempt to remove thread s from queue.\n  void TryRemove(base_internal::PerThreadSynch* absl_nonnull s);\n  // Block a thread on mutex.\n  void Block(base_internal::PerThreadSynch* absl_nonnull s);\n  // Wake a thread; return successor.\n  base_internal::PerThreadSynch* absl_nullable Wakeup(\n      base_internal::PerThreadSynch* absl_nonnull w);\n  void Dtor();\n\n  friend class CondVar;                // for access to Trans()/Fer().\n  void Trans(MuHow absl_nonnull how);  // used for CondVar->Mutex transfer\n  void Fer(base_internal::PerThreadSynch* absl_nonnull\n               w);  // used for CondVar->Mutex transfer\n\n  // Catch the error of writing Mutex when intending MutexLock.\n  explicit Mutex(const volatile Mutex* absl_nullable /*ignored*/) {}\n\n  Mutex(const Mutex&) = delete;\n  Mutex& operator=(const Mutex&) = delete;\n};\n\n// -----------------------------------------------------------------------------\n// Mutex RAII Wrappers\n// -----------------------------------------------------------------------------\n\n// MutexLock\n//\n// `MutexLock` is a helper class, which acquires and releases a `Mutex` via\n// RAII.\n//\n// Example:\n//\n// Class Foo {\n//  public:\n//   Foo::Bar* Baz() {\n//     MutexLock lock(mu_);\n//     ...\n//     return bar;\n//   }\n//\n// private:\n//   Mutex mu_;\n// };\nclass ABSL_SCOPED_LOCKABLE MutexLock {\n public:\n  // Constructors\n\n  // Calls `mu.lock()` and returns when that call returns. That is, `mu` is\n  // guaranteed to be locked when this object is constructed.\n  explicit MutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    this->mu_.lock();\n  }\n\n  // Calls `mu->lock()` and returns when that call returns. That is, `*mu` is\n  // guaranteed to be locked when this object is constructed. Requires that\n  // `mu` be dereferenceable.\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit MutexLock(Mutex* absl_nonnull mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : MutexLock(*mu) {}\n\n  // Like above, but calls `mu.LockWhen(cond)` instead. That is, in addition to\n  // the above, the condition given by `cond` is also guaranteed to hold when\n  // this object is constructed.\n  explicit MutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n                     const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    this->mu_.LockWhen(cond);\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit MutexLock(Mutex* absl_nonnull mu, const Condition& cond)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : MutexLock(*mu, cond) {}\n\n  MutexLock(const MutexLock&) = delete;  // NOLINT(runtime/mutex)\n  MutexLock(MutexLock&&) = delete;       // NOLINT(runtime/mutex)\n  MutexLock& operator=(const MutexLock&) = delete;\n  MutexLock& operator=(MutexLock&&) = delete;\n\n  ~MutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_.unlock(); }\n\n private:\n  Mutex& mu_;\n};\n\n// ReaderMutexLock\n//\n// The `ReaderMutexLock` is a helper class, like `MutexLock`, which acquires and\n// releases a shared lock on a `Mutex` via RAII.\nclass ABSL_SCOPED_LOCKABLE ReaderMutexLock {\n public:\n  explicit ReaderMutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_SHARED_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    mu.lock_shared();\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit ReaderMutexLock(Mutex* absl_nonnull mu) ABSL_SHARED_LOCK_FUNCTION(mu)\n      : ReaderMutexLock(*mu) {}\n\n  explicit ReaderMutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n                           const Condition& cond) ABSL_SHARED_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    mu.ReaderLockWhen(cond);\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit ReaderMutexLock(Mutex* absl_nonnull mu, const Condition& cond)\n      ABSL_SHARED_LOCK_FUNCTION(mu)\n      : ReaderMutexLock(*mu, cond) {}\n\n  ReaderMutexLock(const ReaderMutexLock&) = delete;\n  ReaderMutexLock(ReaderMutexLock&&) = delete;\n  ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;\n  ReaderMutexLock& operator=(ReaderMutexLock&&) = delete;\n\n  ~ReaderMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_.unlock_shared(); }\n\n private:\n  Mutex& mu_;\n};\n\n// WriterMutexLock\n//\n// The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and\n// releases a write (exclusive) lock on a `Mutex` via RAII.\nclass ABSL_SCOPED_LOCKABLE WriterMutexLock {\n public:\n  explicit WriterMutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    mu.lock();\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit WriterMutexLock(Mutex* absl_nonnull mu)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : WriterMutexLock(*mu) {}\n\n  explicit WriterMutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n                           const Condition& cond)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    mu.WriterLockWhen(cond);\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit WriterMutexLock(Mutex* absl_nonnull mu, const Condition& cond)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : WriterMutexLock(*mu, cond) {}\n\n  WriterMutexLock(const WriterMutexLock&) = delete;\n  WriterMutexLock(WriterMutexLock&&) = delete;\n  WriterMutexLock& operator=(const WriterMutexLock&) = delete;\n  WriterMutexLock& operator=(WriterMutexLock&&) = delete;\n\n  ~WriterMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_.unlock(); }\n\n private:\n  Mutex& mu_;\n};\n\n// -----------------------------------------------------------------------------\n// Condition\n// -----------------------------------------------------------------------------\n//\n// `Mutex` contains a number of member functions which take a `Condition` as an\n// argument; clients can wait for conditions to become `true` before attempting\n// to acquire the mutex. These sections are known as \"condition critical\"\n// sections. To use a `Condition`, you simply need to construct it, and use\n// within an appropriate `Mutex` member function; everything else in the\n// `Condition` class is an implementation detail.\n//\n// A `Condition` is specified as a function pointer which returns a boolean.\n// `Condition` functions should be pure functions -- their results should depend\n// only on passed arguments, should not consult any external state (such as\n// clocks), and should have no side-effects, aside from debug logging. Any\n// objects that the function may access should be limited to those which are\n// constant while the mutex is blocked on the condition (e.g. a stack variable),\n// or objects of state protected explicitly by the mutex.\n//\n// No matter which construction is used for `Condition`, the underlying\n// function pointer / functor / callable must not throw any\n// exceptions. Correctness of `Mutex` / `Condition` is not guaranteed in\n// the face of a throwing `Condition`. (When Abseil is allowed to depend\n// on C++17, these function pointers will be explicitly marked\n// `noexcept`; until then this requirement cannot be enforced in the\n// type system.)\n//\n// Note: to use a `Condition`, you need only construct it and pass it to a\n// suitable `Mutex' member function, such as `Mutex::Await()`, or to the\n// constructor of one of the scope guard classes.\n//\n// Example using LockWhen/Unlock:\n//\n//   // assume count_ is not internal reference count\n//   int count_ ABSL_GUARDED_BY(mu_);\n//   Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);\n//\n//   mu_.LockWhen(count_is_zero);\n//   // ...\n//   mu_.Unlock();\n//\n// Example using a scope guard:\n//\n//   {\n//     MutexLock lock(mu_, count_is_zero);\n//     // ...\n//   }\n//\n// When multiple threads are waiting on exactly the same condition, make sure\n// that they are constructed with the same parameters (same pointer to function\n// + arg, or same pointer to object + method), so that the mutex implementation\n// can avoid redundantly evaluating the same condition for each thread.\nclass Condition {\n public:\n  // A Condition that returns the result of \"(*func)(arg)\"\n  Condition(bool (*absl_nonnull func)(void* absl_nullability_unknown),\n            void* absl_nullability_unknown arg);\n\n  // Templated version for people who are averse to casts.\n  //\n  // To use a lambda, prepend it with unary plus, which converts the lambda\n  // into a function pointer:\n  //     Condition(+[](T* t) { return ...; }, arg).\n  //\n  // Note: lambdas in this case must contain no bound variables.\n  //\n  // See class comment for performance advice.\n  template <typename T>\n  Condition(bool (*absl_nonnull func)(T* absl_nullability_unknown),\n            T* absl_nullability_unknown arg);\n\n  // Same as above, but allows for cases where `arg` comes from a pointer that\n  // is convertible to the function parameter type `T*` but not an exact match.\n  //\n  // For example, the argument might be `X*` but the function takes `const X*`,\n  // or the argument might be `Derived*` while the function takes `Base*`, and\n  // so on for cases where the argument pointer can be implicitly converted.\n  //\n  // Implementation notes: This constructor overload is required in addition to\n  // the one above to allow deduction of `T` from `arg` for cases such as where\n  // a function template is passed as `func`. Also, the dummy `typename = void`\n  // template parameter exists just to work around a MSVC mangling bug.\n  template <typename T, typename = void>\n  Condition(\n      bool (*absl_nonnull func)(T* absl_nullability_unknown),\n      typename absl::type_identity<T>::type* absl_nullability_unknown\n          arg);\n\n  // Templated version for invoking a method that returns a `bool`.\n  //\n  // `Condition(object, &Class::Method)` constructs a `Condition` that evaluates\n  // `object->Method()`.\n  //\n  // Implementation Note: `absl::type_identity` is used to allow\n  // methods to come from base classes. A simpler signature like\n  // `Condition(T*, bool (T::*)())` does not suffice.\n  template <typename T>\n  Condition(\n      T* absl_nonnull object,\n      bool (absl::type_identity<T>::type::* absl_nonnull method)());\n\n  // Same as above, for const members\n  template <typename T>\n  Condition(\n      const T* absl_nonnull object,\n      bool (absl::type_identity<T>::type::* absl_nonnull method)()\n          const);\n\n  // A Condition that returns the value of `*cond`\n  explicit Condition(const bool* absl_nonnull cond);\n\n  // Templated version for invoking a functor that returns a `bool`.\n  // This approach accepts pointers to non-mutable lambdas, `std::function`,\n  // the result of` std::bind` and user-defined functors that define\n  // `bool F::operator()() const`.\n  //\n  // Example:\n  //\n  //   auto reached = [this, current]() {\n  //     mu_.AssertReaderHeld();                // For annotalysis.\n  //     return processed_ >= current;\n  //   };\n  //   mu_.Await(Condition(&reached));\n  //\n  // NOTE: never use \"mu_.AssertHeld()\" instead of \"mu_.AssertReaderHeld()\" in\n  // the lambda as it may be called when the mutex is being unlocked from a\n  // scope holding only a reader lock, which will make the assertion not\n  // fulfilled and crash the binary.\n\n  // See class comment for performance advice. In particular, if there\n  // might be more than one waiter for the same condition, make sure\n  // that all waiters construct the condition with the same pointers.\n\n  // Implementation note: The second template parameter ensures that this\n  // constructor doesn't participate in overload resolution if T doesn't have\n  // `bool operator() const`.\n  template <typename T,\n            std::enable_if_t<\n                synchronization_internal::HasConstMemberCallOperator<T>::value,\n                int> = 0>\n  explicit Condition(const T* absl_nonnull obj)\n      : Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {}\n\n  // Constructor for functors that do not match the `bool operator()() const`\n  // signature, such as those using C++23 \"deducing this\" or static operator().\n  template <\n      typename T,\n      typename = std::enable_if_t<\n          !synchronization_internal::HasConstMemberCallOperator<T>::value &&\n          sizeof(static_cast<bool (*)(const T&)>(&T::operator())) != 0>>\n  explicit Condition(const T* absl_nonnull obj)\n      : Condition(&CallByRef<T>, obj) {}\n\n  // A Condition that always returns `true`.\n  // kTrue is only useful in a narrow set of circumstances, mostly when\n  // it's passed conditionally. For example:\n  //\n  //   mu.LockWhen(some_flag ? kTrue : SomeOtherCondition);\n  //\n  // Note: {LockWhen,Await}With{Deadline,Timeout} methods with kTrue condition\n  // don't return immediately when the timeout happens, they still block until\n  // the Mutex becomes available. The return value of these methods does\n  // not indicate if the timeout was reached; rather it indicates whether or\n  // not the condition is true.\n  ABSL_CONST_INIT static const Condition kTrue;\n\n  // Evaluates the condition.\n  bool Eval() const;\n\n  // Returns `true` if the two conditions are guaranteed to return the same\n  // value if evaluated at the same time, `false` if the evaluation *may* return\n  // different results.\n  //\n  // Two `Condition` values are guaranteed equal if both their `func` and `arg`\n  // components are the same. A null pointer is equivalent to a `true`\n  // condition.\n  static bool GuaranteedEqual(const Condition* absl_nullable a,\n                              const Condition* absl_nullable b);\n\n private:\n  // Sizing an allocation for a method pointer can be subtle. In the Itanium\n  // specifications, a method pointer has a predictable, uniform size. On the\n  // other hand, MSVC ABI, method pointer sizes vary based on the\n  // inheritance of the class. Specifically, method pointers from classes with\n  // multiple inheritance are bigger than those of classes with single\n  // inheritance. Other variations also exist.\n\n#ifndef _MSC_VER\n  // Allocation for a function pointer or method pointer.\n  // The {0} initializer ensures that all unused bytes of this buffer are\n  // always zeroed out.  This is necessary, because GuaranteedEqual() compares\n  // all of the bytes, unaware of which bytes are relevant to a given `eval_`.\n  using MethodPtr = bool (Condition::*)();\n  char callback_[sizeof(MethodPtr)] = {0};\n#else\n  // It is well known that the larget MSVC pointer-to-member is 24 bytes. This\n  // may be the largest known pointer-to-member of any platform. For this\n  // reason we will allocate 24 bytes for MSVC platform toolchains.\n  char callback_[24] = {0};\n#endif\n\n  // Function with which to evaluate callbacks and/or arguments.\n  bool (*absl_nullable eval_)(const Condition* absl_nonnull) = nullptr;\n\n  // Either an argument for a function call or an object for a method call.\n  void* absl_nullable arg_ = nullptr;\n\n  // Various functions eval_ can point to:\n  static bool CallVoidPtrFunction(const Condition* absl_nonnull c);\n  template <typename T>\n  static bool CastAndCallFunction(const Condition* absl_nonnull c);\n  template <typename T, typename ConditionMethodPtr>\n  static bool CastAndCallMethod(const Condition* absl_nonnull c);\n\n  template <typename T>\n  static bool CallByRef(const T* absl_nonnull self) {\n    return (*self)();\n  }\n\n  // Helper methods for storing, validating, and reading callback arguments.\n  template <typename T>\n  inline void StoreCallback(T callback) {\n    static_assert(\n        sizeof(callback) <= sizeof(callback_),\n        \"An overlarge pointer was passed as a callback to Condition.\");\n    std::memcpy(callback_, &callback, sizeof(callback));\n  }\n\n  template <typename T>\n  inline void ReadCallback(T* absl_nonnull callback) const {\n    std::memcpy(callback, callback_, sizeof(*callback));\n  }\n\n  static bool AlwaysTrue(const Condition* absl_nullable) { return true; }\n\n  // Used only to create kTrue.\n  constexpr Condition() : eval_(AlwaysTrue), arg_(nullptr) {}\n};\n\n// -----------------------------------------------------------------------------\n// CondVar\n// -----------------------------------------------------------------------------\n//\n// A condition variable, reflecting state evaluated separately outside of the\n// `Mutex` object, which can be signaled to wake callers.\n// This class is not normally needed; use `Mutex` member functions such as\n// `Mutex::Await()` and intrinsic `Condition` abstractions. In rare cases\n// with many threads and many conditions, `CondVar` may be faster.\n//\n// The implementation may deliver signals to any condition variable at\n// any time, even when no call to `Signal()` or `SignalAll()` is made; as a\n// result, upon being awoken, you must check the logical condition you have\n// been waiting upon.\n//\n// Examples:\n//\n// Usage for a thread waiting for some condition C protected by mutex mu:\n//       mu.Lock();\n//       while (!C) { cv->Wait(&mu); }        // releases and reacquires mu\n//       //  C holds; process data\n//       mu.Unlock();\n//\n// Usage to wake T is:\n//       mu.Lock();\n//       // process data, possibly establishing C\n//       if (C) { cv->Signal(); }\n//       mu.Unlock();\n//\n// If C may be useful to more than one waiter, use `SignalAll()` instead of\n// `Signal()`.\n//\n// With this implementation it is efficient to use `Signal()/SignalAll()` inside\n// the locked region; this usage can make reasoning about your program easier.\n//\nclass CondVar {\n public:\n  // A `CondVar` allocated on the heap or on the stack can use the this\n  // constructor.\n  CondVar();\n\n  // CondVar::Wait()\n  //\n  // Atomically releases a `Mutex` and blocks on this condition variable.\n  // Waits until awakened by a call to `Signal()` or `SignalAll()` (or a\n  // spurious wakeup), then reacquires the `Mutex` and returns.\n  //\n  // Requires and ensures that the current thread holds the `Mutex`.\n  void Wait(Mutex* absl_nonnull mu) {\n    WaitCommon(mu, synchronization_internal::KernelTimeout::Never());\n  }\n\n  // CondVar::WaitWithTimeout()\n  //\n  // Atomically releases a `Mutex` and blocks on this condition variable.\n  // Waits until awakened by a call to `Signal()` or `SignalAll()` (or a\n  // spurious wakeup), or until the timeout has expired, then reacquires\n  // the `Mutex` and returns.\n  //\n  // Returns true if the timeout has expired without this `CondVar`\n  // being signalled in any manner. If both the timeout has expired\n  // and this `CondVar` has been signalled, the implementation is free\n  // to return `true` or `false`.\n  //\n  // Requires and ensures that the current thread holds the `Mutex`.\n  bool WaitWithTimeout(Mutex* absl_nonnull mu, absl::Duration timeout) {\n    return WaitCommon(mu, synchronization_internal::KernelTimeout(timeout));\n  }\n\n  // CondVar::WaitWithDeadline()\n  //\n  // Atomically releases a `Mutex` and blocks on this condition variable.\n  // Waits until awakened by a call to `Signal()` or `SignalAll()` (or a\n  // spurious wakeup), or until the deadline has passed, then reacquires\n  // the `Mutex` and returns.\n  //\n  // Deadlines in the past are equivalent to an immediate deadline.\n  //\n  // Returns true if the deadline has passed without this `CondVar`\n  // being signalled in any manner. If both the deadline has passed\n  // and this `CondVar` has been signalled, the implementation is free\n  // to return `true` or `false`.\n  //\n  // Requires and ensures that the current thread holds the `Mutex`.\n  bool WaitWithDeadline(Mutex* absl_nonnull mu, absl::Time deadline) {\n    return WaitCommon(mu, synchronization_internal::KernelTimeout(deadline));\n  }\n\n  // CondVar::Signal()\n  //\n  // Signal this `CondVar`; wake at least one waiter if one exists.\n  void Signal();\n\n  // CondVar::SignalAll()\n  //\n  // Signal this `CondVar`; wake all waiters.\n  void SignalAll();\n\n  // CondVar::EnableDebugLog()\n  //\n  // Causes all subsequent uses of this `CondVar` to be logged via\n  // `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if `name != 0`.\n  // Note: this method substantially reduces `CondVar` performance.\n  void EnableDebugLog(const char* absl_nullable name);\n\n private:\n  bool WaitCommon(Mutex* absl_nonnull mutex,\n                  synchronization_internal::KernelTimeout t);\n  void Remove(base_internal::PerThreadSynch* absl_nonnull s);\n  std::atomic<intptr_t> cv_;  // Condition variable state.\n  CondVar(const CondVar&) = delete;\n  CondVar& operator=(const CondVar&) = delete;\n};\n\n// Variants of MutexLock.\n//\n// If you find yourself using one of these, consider instead using\n// Mutex::Unlock() and/or if-statements for clarity.\n\n// MutexLockMaybe\n//\n// MutexLockMaybe is like MutexLock, but is a no-op when mu is null.\nclass ABSL_SCOPED_LOCKABLE MutexLockMaybe {\n public:\n  explicit MutexLockMaybe(Mutex* absl_nullable mu)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    if (this->mu_ != nullptr) {\n      this->mu_->lock();\n    }\n  }\n\n  explicit MutexLockMaybe(Mutex* absl_nullable mu, const Condition& cond)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(mu) {\n    if (this->mu_ != nullptr) {\n      this->mu_->LockWhen(cond);\n    }\n  }\n\n  ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {\n    if (this->mu_ != nullptr) {\n      this->mu_->unlock();\n    }\n  }\n\n private:\n  Mutex* absl_nullable const mu_;\n  MutexLockMaybe(const MutexLockMaybe&) = delete;\n  MutexLockMaybe(MutexLockMaybe&&) = delete;\n  MutexLockMaybe& operator=(const MutexLockMaybe&) = delete;\n  MutexLockMaybe& operator=(MutexLockMaybe&&) = delete;\n};\n\n// ReleasableMutexLock\n//\n// ReleasableMutexLock is like MutexLock, but permits `Release()` of its\n// mutex before destruction. `Release()` may be called at most once.\nclass ABSL_SCOPED_LOCKABLE ReleasableMutexLock {\n public:\n  explicit ReleasableMutexLock(Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(\n      this)) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(&mu) {\n    this->mu_->lock();\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit ReleasableMutexLock(Mutex* absl_nonnull mu)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : ReleasableMutexLock(*mu) {}\n\n  explicit ReleasableMutexLock(\n      Mutex& mu ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),\n      const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : mu_(&mu) {\n    this->mu_->LockWhen(cond);\n  }\n\n  [[deprecated(\"Use the constructor that takes a reference instead\")]]\n  ABSL_REFACTOR_INLINE\n  explicit ReleasableMutexLock(Mutex* absl_nonnull mu, const Condition& cond)\n      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)\n      : ReleasableMutexLock(*mu, cond) {}\n\n  ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {\n    if (this->mu_ != nullptr) {\n      this->mu_->unlock();\n    }\n  }\n\n  void Release() ABSL_UNLOCK_FUNCTION();\n\n private:\n  Mutex* absl_nullable mu_;\n  ReleasableMutexLock(const ReleasableMutexLock&) = delete;\n  ReleasableMutexLock(ReleasableMutexLock&&) = delete;\n  ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete;\n  ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;\n};\n\ninline Mutex::Mutex() : mu_(0) {\n  ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);\n}\n\ninline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}\n\n#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL)\nABSL_ATTRIBUTE_ALWAYS_INLINE\ninline Mutex::~Mutex() { Dtor(); }\n#endif\n\n#if defined(NDEBUG) && !defined(ABSL_HAVE_THREAD_SANITIZER) && \\\n    !defined(ABSL_BUILD_DLL)\n// Under NDEBUG and without TSAN, Dtor is normally fully inlined for\n// performance. However, when building Abseil as a shared library\n// (ABSL_BUILD_DLL), we must provide an out-of-line definition. This ensures the\n// Mutex::Dtor symbol is exported from the DLL, maintaining ABI compatibility\n// with clients that might be built in debug mode and thus expect the symbol.\nABSL_ATTRIBUTE_ALWAYS_INLINE\ninline void Mutex::Dtor() {}\n#endif\n\ninline CondVar::CondVar() : cv_(0) {}\n\n// static\ntemplate <typename T, typename ConditionMethodPtr>\nbool Condition::CastAndCallMethod(const Condition* absl_nonnull c) {\n  T* object = static_cast<T*>(c->arg_);\n  ConditionMethodPtr condition_method_pointer;\n  c->ReadCallback(&condition_method_pointer);\n  return (object->*condition_method_pointer)();\n}\n\n// static\ntemplate <typename T>\nbool Condition::CastAndCallFunction(const Condition* absl_nonnull c) {\n  bool (*function)(T*);\n  c->ReadCallback(&function);\n  T* argument = static_cast<T*>(c->arg_);\n  return (*function)(argument);\n}\n\ntemplate <typename T>\ninline Condition::Condition(\n    bool (*absl_nonnull func)(T* absl_nullability_unknown),\n    T* absl_nullability_unknown arg)\n    : eval_(&CastAndCallFunction<T>),\n      arg_(const_cast<void*>(static_cast<const void*>(arg))) {\n  static_assert(sizeof(&func) <= sizeof(callback_),\n                \"An overlarge function pointer was passed to Condition.\");\n  StoreCallback(func);\n}\n\ntemplate <typename T, typename>\ninline Condition::Condition(\n    bool (*absl_nonnull func)(T* absl_nullability_unknown),\n    typename absl::type_identity<T>::type* absl_nullability_unknown\n        arg)\n    // Just delegate to the overload above.\n    : Condition(func, arg) {}\n\ntemplate <typename T>\ninline Condition::Condition(\n    T* absl_nonnull object,\n    bool (absl::type_identity<T>::type::* absl_nonnull method)())\n    : eval_(&CastAndCallMethod<T, decltype(method)>), arg_(object) {\n  static_assert(sizeof(&method) <= sizeof(callback_),\n                \"An overlarge method pointer was passed to Condition.\");\n  StoreCallback(method);\n}\n\ntemplate <typename T>\ninline Condition::Condition(\n    const T* absl_nonnull object,\n    bool (absl::type_identity<T>::type::* absl_nonnull method)()\n        const)\n    : eval_(&CastAndCallMethod<const T, decltype(method)>),\n      arg_(reinterpret_cast<void*>(const_cast<T*>(object))) {\n  StoreCallback(method);\n}\n\n// Register hooks for profiling support.\n//\n// The function pointer registered here will be called whenever a mutex is\n// contended.  The callback is given the cycles for which waiting happened (as\n// measured by //absl/base/internal/cycleclock.h, and which may not\n// be real \"cycle\" counts.)\n//\n// There is no ordering guarantee between when the hook is registered and when\n// callbacks will begin.  Only a single profiler can be installed in a running\n// binary; if this function is called a second time with a different function\n// pointer, the value is ignored (and will cause an assertion failure in debug\n// mode.)\nvoid RegisterMutexProfiler(void (*absl_nonnull fn)(int64_t wait_cycles));\n\n// Register a hook for Mutex tracing.\n//\n// The function pointer registered here will be called whenever a mutex is\n// contended.  The callback is given an opaque handle to the contended mutex,\n// an event name, and the number of wait cycles (as measured by\n// //absl/base/internal/cycleclock.h, and which may not be real\n// \"cycle\" counts.)\n//\n// The only event name currently sent is \"slow release\".\n//\n// This has the same ordering and single-use limitations as\n// RegisterMutexProfiler() above.\nvoid RegisterMutexTracer(void (*absl_nonnull fn)(const char* absl_nonnull msg,\n                                                 const void* absl_nonnull obj,\n                                                 int64_t wait_cycles));\n\n// Register a hook for CondVar tracing.\n//\n// The function pointer registered here will be called here on various CondVar\n// events.  The callback is given an opaque handle to the CondVar object and\n// a string identifying the event.  This is thread-safe, but only a single\n// tracer can be registered.\n//\n// Events that can be sent are \"Wait\", \"Unwait\", \"Signal wakeup\", and\n// \"SignalAll wakeup\".\n//\n// This has the same ordering and single-use limitations as\n// RegisterMutexProfiler() above.\nvoid RegisterCondVarTracer(void (*absl_nonnull fn)(\n    const char* absl_nonnull msg, const void* absl_nonnull cv));\n\n// EnableMutexInvariantDebugging()\n//\n// Enable or disable global support for Mutex invariant debugging.  If enabled,\n// then invariant predicates can be registered per-Mutex for debug checking.\n// See Mutex::EnableInvariantDebugging().\nvoid EnableMutexInvariantDebugging(bool enabled);\n\n// When in debug mode, and when the feature has been enabled globally, the\n// implementation will keep track of lock ordering and complain (or optionally\n// crash) if a cycle is detected in the acquired-before graph.\n\n// Possible modes of operation for the deadlock detector in debug mode.\nenum class OnDeadlockCycle {\n  kIgnore,  // Neither report on nor attempt to track cycles in lock ordering\n  kReport,  // Report lock cycles to stderr when detected\n  kAbort,   // Report lock cycles to stderr when detected, then abort\n};\n\n// SetMutexDeadlockDetectionMode()\n//\n// Enable or disable global support for detection of potential deadlocks\n// due to Mutex lock ordering inversions.  When set to 'kIgnore', tracking of\n// lock ordering is disabled.  Otherwise, in debug builds, a lock ordering graph\n// will be maintained internally, and detected cycles will be reported in\n// the manner chosen here.\nvoid SetMutexDeadlockDetectionMode(OnDeadlockCycle mode);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// In some build configurations we pass --detect-odr-violations to the\n// gold linker.  This causes it to flag weak symbol overrides as ODR\n// violations.  Because ODR only applies to C++ and not C,\n// --detect-odr-violations ignores symbols not mangled with C++ names.\n// By changing our extension points to be extern \"C\", we dodge this\n// check.\nextern \"C\" {\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();\n}  // extern \"C\"\n\n#endif  // ABSL_SYNCHRONIZATION_MUTEX_H_\n"
  },
  {
    "path": "absl/synchronization/mutex_benchmark.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n#include <mutex>  // NOLINT(build/c++11)\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/cycleclock.h\"\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/synchronization/blocking_counter.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_Mutex(benchmark::State& state) {\n  static absl::NoDestructor<absl::Mutex> mu;\n  for (auto _ : state) {\n    absl::MutexLock lock(*mu.get());\n  }\n}\nBENCHMARK(BM_Mutex)->UseRealTime()->Threads(1)->ThreadPerCpu();\n\nvoid BM_ReaderLock(benchmark::State& state) {\n  static absl::NoDestructor<absl::Mutex> mu;\n  for (auto _ : state) {\n    absl::ReaderMutexLock lock(*mu.get());\n  }\n}\nBENCHMARK(BM_ReaderLock)->UseRealTime()->Threads(1)->ThreadPerCpu();\n\nvoid BM_TryLock(benchmark::State& state) {\n  absl::Mutex mu;\n  for (auto _ : state) {\n    if (mu.try_lock()) {\n      mu.unlock();\n    }\n  }\n}\nBENCHMARK(BM_TryLock);\n\nvoid BM_ReaderTryLock(benchmark::State& state) {\n  static absl::NoDestructor<absl::Mutex> mu;\n  for (auto _ : state) {\n    if (mu->try_lock_shared()) {\n      mu->unlock_shared();\n    }\n  }\n}\nBENCHMARK(BM_ReaderTryLock)->UseRealTime()->Threads(1)->ThreadPerCpu();\n\nstatic void DelayNs(int64_t ns, int* data) {\n  int64_t end = absl::base_internal::CycleClock::Now() +\n                ns * absl::base_internal::CycleClock::Frequency() / 1e9;\n  while (absl::base_internal::CycleClock::Now() < end) {\n    ++(*data);\n    benchmark::DoNotOptimize(*data);\n  }\n}\n\n// RAII object to change the Mutex priority of the running thread.\nclass ScopedThreadMutexPriority {\n public:\n  explicit ScopedThreadMutexPriority(int priority) {\n    absl::base_internal::ThreadIdentity* identity =\n        absl::synchronization_internal::GetOrCreateCurrentThreadIdentity();\n    identity->per_thread_synch.priority = priority;\n    // Bump next_priority_read_cycles to the infinite future so that the\n    // implementation doesn't re-read the thread's actual scheduler priority\n    // and replace our temporary scoped priority.\n    identity->per_thread_synch.next_priority_read_cycles =\n        std::numeric_limits<int64_t>::max();\n  }\n  ~ScopedThreadMutexPriority() {\n    // Reset the \"next priority read time\" back to the infinite past so that\n    // the next time the Mutex implementation wants to know this thread's\n    // priority, it re-reads it from the OS instead of using our overridden\n    // priority.\n    absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()\n        ->per_thread_synch.next_priority_read_cycles =\n        std::numeric_limits<int64_t>::min();\n  }\n};\n\nvoid BM_MutexEnqueue(benchmark::State& state) {\n  // In the \"multiple priorities\" variant of the benchmark, one of the\n  // threads runs with Mutex priority 0 while the rest run at elevated priority.\n  // This benchmarks the performance impact of the presence of a low priority\n  // waiter when a higher priority waiter adds itself of the queue\n  // (b/175224064).\n  //\n  // NOTE: The actual scheduler priority is not modified in this benchmark:\n  // all of the threads get CPU slices with the same priority. Only the\n  // Mutex queueing behavior is modified.\n  const bool multiple_priorities = state.range(0);\n  ScopedThreadMutexPriority priority_setter(\n      (multiple_priorities && state.thread_index() != 0) ? 1 : 0);\n\n  struct Shared {\n    absl::Mutex mu;\n    std::atomic<int> looping_threads{0};\n    std::atomic<int> blocked_threads{0};\n    std::atomic<bool> thread_has_mutex{false};\n  };\n  static absl::NoDestructor<Shared> shared;\n\n  // Set up 'blocked_threads' to count how many threads are currently blocked\n  // in Abseil synchronization code.\n  //\n  // NOTE: Blocking done within the Google Benchmark library itself (e.g.\n  // the barrier which synchronizes threads entering and exiting the benchmark\n  // loop) does _not_ get registered in this counter. This is because Google\n  // Benchmark uses its own synchronization primitives based on std::mutex, not\n  // Abseil synchronization primitives. If at some point the benchmark library\n  // merges into Abseil, this code may break.\n  absl::synchronization_internal::PerThreadSem::SetThreadBlockedCounter(\n      &shared->blocked_threads);\n\n  // The benchmark framework may run several iterations in the same process,\n  // reusing the same static-initialized 'shared' object. Given the semantics\n  // of the members, here, we expect everything to be reset to zero by the\n  // end of any iteration. Assert that's the case, just to be sure.\n  ABSL_RAW_CHECK(\n      shared->looping_threads.load(std::memory_order_relaxed) == 0 &&\n          shared->blocked_threads.load(std::memory_order_relaxed) == 0 &&\n          !shared->thread_has_mutex.load(std::memory_order_relaxed),\n      \"Shared state isn't zeroed at start of benchmark iteration\");\n\n  static constexpr int kBatchSize = 1000;\n  while (state.KeepRunningBatch(kBatchSize)) {\n    shared->looping_threads.fetch_add(1);\n    for (int i = 0; i < kBatchSize; i++) {\n      {\n        absl::MutexLock l(shared->mu);\n        shared->thread_has_mutex.store(true, std::memory_order_relaxed);\n        // Spin until all other threads are either out of the benchmark loop\n        // or blocked on the mutex. This ensures that the mutex queue is kept\n        // at its maximal length to benchmark the performance of queueing on\n        // a highly contended mutex.\n        while (shared->looping_threads.load(std::memory_order_relaxed) -\n                   shared->blocked_threads.load(std::memory_order_relaxed) !=\n               1) {\n        }\n        shared->thread_has_mutex.store(false);\n      }\n      // Spin until some other thread has acquired the mutex before we block\n      // again. This ensures that we always go through the slow (queueing)\n      // acquisition path rather than reacquiring the mutex we just released.\n      while (!shared->thread_has_mutex.load(std::memory_order_relaxed) &&\n             shared->looping_threads.load(std::memory_order_relaxed) > 1) {\n      }\n    }\n    // The benchmark framework uses a barrier to ensure that all of the threads\n    // complete their benchmark loop together before any of the threads exit\n    // the loop. So, we need to remove ourselves from the \"looping threads\"\n    // counter here before potentially blocking on that barrier. Otherwise,\n    // another thread spinning above might wait forever for this thread to\n    // block on the mutex while we in fact are waiting to exit.\n    shared->looping_threads.fetch_add(-1);\n  }\n  absl::synchronization_internal::PerThreadSem::SetThreadBlockedCounter(\n      nullptr);\n}\n\nBENCHMARK(BM_MutexEnqueue)\n    ->Threads(4)\n    ->Threads(64)\n    ->Threads(128)\n    ->Threads(512)\n    ->ArgName(\"multiple_priorities\")\n    ->Arg(false)\n    ->Arg(true);\n\ntemplate <typename MutexType>\nvoid BM_Contended(benchmark::State& state) {\n  int priority = state.thread_index() % state.range(1);\n  ScopedThreadMutexPriority priority_setter(priority);\n\n  struct Shared {\n    MutexType mu;\n    int data = 0;\n  };\n  static absl::NoDestructor<Shared> shared;\n  int local = 0;\n  for (auto _ : state) {\n    // Here we model both local work outside of the critical section as well as\n    // some work inside of the critical section. The idea is to capture some\n    // more or less realisitic contention levels.\n    // If contention is too low, the benchmark won't measure anything useful.\n    // If contention is unrealistically high, the benchmark will favor\n    // bad mutex implementations that block and otherwise distract threads\n    // from the mutex and shared state for as much as possible.\n    // To achieve this amount of local work is multiplied by number of threads\n    // to keep ratio between local work and critical section approximately\n    // equal regardless of number of threads.\n    DelayNs(100 * state.threads(), &local);\n    std::scoped_lock locker(shared->mu);\n    DelayNs(state.range(0), &shared->data);\n  }\n}\nvoid SetupBenchmarkArgs(benchmark::internal::Benchmark* bm,\n                        bool do_test_priorities) {\n  const int max_num_priorities = do_test_priorities ? 2 : 1;\n  bm->UseRealTime()\n      // ThreadPerCpu poorly handles non-power-of-two CPU counts.\n      ->Threads(1)\n      ->Threads(2)\n      ->Threads(4)\n      ->Threads(6)\n      ->Threads(8)\n      ->Threads(12)\n      ->Threads(16)\n      ->Threads(24)\n      ->Threads(32)\n      ->Threads(48)\n      ->Threads(64)\n      ->Threads(96)\n      ->Threads(128)\n      ->Threads(192)\n      ->Threads(256)\n      ->ArgNames({\"cs_ns\", \"num_prios\"});\n  // Some empirically chosen amounts of work in critical section.\n  // 1 is low contention, 2000 is high contention and few values in between.\n  for (int critical_section_ns : {1, 20, 50, 200, 2000}) {\n    for (int num_priorities = 1; num_priorities <= max_num_priorities;\n         num_priorities++) {\n      bm->ArgPair(critical_section_ns, num_priorities);\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_Contended, absl::Mutex)\n    ->Apply([](benchmark::internal::Benchmark* bm) {\n      SetupBenchmarkArgs(bm, /*do_test_priorities=*/true);\n    });\n\nBENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock)\n    ->Apply([](benchmark::internal::Benchmark* bm) {\n      SetupBenchmarkArgs(bm, /*do_test_priorities=*/false);\n    });\n\nBENCHMARK_TEMPLATE(BM_Contended, std::mutex)\n    ->Apply([](benchmark::internal::Benchmark* bm) {\n      SetupBenchmarkArgs(bm, /*do_test_priorities=*/false);\n    });\n\n// Measure the overhead of conditions on mutex release (when they must be\n// evaluated).  Mutex has (some) support for equivalence classes allowing\n// Conditions with the same function/argument to potentially not be multiply\n// evaluated.\n//\n// num_classes==0 is used for the special case of every waiter being distinct.\nvoid BM_ConditionWaiters(benchmark::State& state) {\n  int num_classes = state.range(0);\n  int num_waiters = state.range(1);\n\n  struct Helper {\n    static void Waiter(absl::BlockingCounter* init, absl::Mutex* m, int* p) {\n      init->DecrementCount();\n      m->LockWhen(absl::Condition(\n          static_cast<bool (*)(int*)>([](int* v) { return *v == 0; }), p));\n      m->unlock();\n    }\n  };\n\n  if (num_classes == 0) {\n    // No equivalence classes.\n    num_classes = num_waiters;\n  }\n\n  absl::BlockingCounter init(num_waiters);\n  absl::Mutex mu;\n  std::vector<int> equivalence_classes(num_classes, 1);\n\n  // Must be declared last to be destroyed first.\n  absl::synchronization_internal::ThreadPool pool(num_waiters);\n\n  for (int i = 0; i < num_waiters; i++) {\n    // Mutex considers Conditions with the same function and argument\n    // to be equivalent.\n    pool.Schedule([&, i] {\n      Helper::Waiter(&init, &mu, &equivalence_classes[i % num_classes]);\n    });\n  }\n  init.Wait();\n\n  for (auto _ : state) {\n    mu.lock();\n    mu.unlock();  // Each unlock requires Condition evaluation for our waiters.\n  }\n\n  mu.lock();\n  for (int i = 0; i < num_classes; i++) {\n    equivalence_classes[i] = 0;\n  }\n  mu.unlock();\n}\n\n// Some configurations have higher thread limits than others.\n#if defined(__linux__) && !defined(ABSL_HAVE_THREAD_SANITIZER)\nconstexpr int kMaxConditionWaiters = 8192;\n#else\nconstexpr int kMaxConditionWaiters = 1024;\n#endif\nBENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters);\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/mutex_method_pointer_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/mutex.h\"\n\n#include <cstdlib>\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace {\n\nclass IncompleteClass;\n\n#ifdef _MSC_VER\n// These tests verify expectations about sizes of MSVC pointers to methods.\n// Pointers to methods are distinguished by whether their class hierarchies\n// contain single inheritance, multiple inheritance, or virtual inheritance.\n\n// Declare classes of the various MSVC inheritance types.\nclass __single_inheritance SingleInheritance{};\nclass __multiple_inheritance MultipleInheritance;\nclass __virtual_inheritance VirtualInheritance;\n\nTEST(MutexMethodPointerTest, MicrosoftMethodPointerSize) {\n  void (SingleInheritance::*single_inheritance_method_pointer)();\n  void (MultipleInheritance::*multiple_inheritance_method_pointer)();\n  void (VirtualInheritance::*virtual_inheritance_method_pointer)();\n\n#if defined(_M_IX86) || defined(_M_ARM)\n  static_assert(sizeof(single_inheritance_method_pointer) == 4,\n                \"Unexpected sizeof(single_inheritance_method_pointer).\");\n  static_assert(sizeof(multiple_inheritance_method_pointer) == 8,\n                \"Unexpected sizeof(multiple_inheritance_method_pointer).\");\n  static_assert(sizeof(virtual_inheritance_method_pointer) == 12,\n                \"Unexpected sizeof(virtual_inheritance_method_pointer).\");\n#elif defined(_M_X64) || defined(__aarch64__)\n  static_assert(sizeof(single_inheritance_method_pointer) == 8,\n                \"Unexpected sizeof(single_inheritance_method_pointer).\");\n  static_assert(sizeof(multiple_inheritance_method_pointer) == 16,\n                \"Unexpected sizeof(multiple_inheritance_method_pointer).\");\n  static_assert(sizeof(virtual_inheritance_method_pointer) == 16,\n                \"Unexpected sizeof(virtual_inheritance_method_pointer).\");\n#endif\n  void (IncompleteClass::*incomplete_class_method_pointer)();\n  static_assert(sizeof(incomplete_class_method_pointer) >=\n                    sizeof(virtual_inheritance_method_pointer),\n                \"Failed invariant: sizeof(incomplete_class_method_pointer) >= \"\n                \"sizeof(virtual_inheritance_method_pointer)!\");\n}\n\nclass Callback {\n  bool x = true;\n\n public:\n  Callback() {}\n  bool method() {\n    x = !x;\n    return x;\n  }\n};\n\nclass M2 {\n  bool x = true;\n\n public:\n  M2() {}\n  bool method2() {\n    x = !x;\n    return x;\n  }\n};\n\nclass MultipleInheritance : public Callback, public M2 {};\n\nTEST(MutexMethodPointerTest, ConditionWithMultipleInheritanceMethod) {\n  // This test ensures that Condition can deal with method pointers from classes\n  // with multiple inheritance.\n  MultipleInheritance object = MultipleInheritance();\n  absl::Condition condition(&object, &MultipleInheritance::method);\n  EXPECT_FALSE(condition.Eval());\n  EXPECT_TRUE(condition.Eval());\n}\n\nclass __virtual_inheritance VirtualInheritance : virtual public Callback {\n  bool x = false;\n\n public:\n  VirtualInheritance() {}\n  bool method() {\n    x = !x;\n    return x;\n  }\n};\n\nTEST(MutexMethodPointerTest, ConditionWithVirtualInheritanceMethod) {\n  // This test ensures that Condition can deal with method pointers from classes\n  // with virtual inheritance.\n  VirtualInheritance object = VirtualInheritance();\n  absl::Condition condition(&object, &VirtualInheritance::method);\n  EXPECT_TRUE(condition.Eval());\n  EXPECT_FALSE(condition.Eval());\n}\n#endif  // #ifdef _MSC_VER\n\nTEST(MutexMethodPointerTest, ConditionWithIncompleteClassMethod) {\n  using IncompleteClassMethodPointer = void (IncompleteClass::*)();\n\n  union CallbackSlot {\n    void (*anonymous_function_pointer)();\n    IncompleteClassMethodPointer incomplete_class_method_pointer;\n  };\n\n  static_assert(sizeof(CallbackSlot) >= sizeof(IncompleteClassMethodPointer),\n                \"The callback slot is not big enough for method pointers.\");\n  static_assert(\n      sizeof(CallbackSlot) == sizeof(IncompleteClassMethodPointer),\n      \"The callback slot is not big enough for anonymous function pointers.\");\n\n#if defined(_MSC_VER)\n  static_assert(sizeof(IncompleteClassMethodPointer) <= 24,\n                \"The pointer to a method of an incomplete class is too big.\");\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/mutex_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/mutex.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#include <algorithm>\n#include <atomic>\n#include <cstdlib>\n#include <functional>\n#include <memory>\n#include <mutex>  // NOLINT(build/c++11)\n#include <random>\n#include <shared_mutex>  // NOLINT(build/c++14)\n#include <string>\n#include <thread>  // NOLINT(build/c++11)\n#include <type_traits>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/sysinfo.h\"\n#include \"absl/log/check.h\"\n#include \"absl/log/log.h\"\n#include \"absl/memory/memory.h\"\n#include \"absl/random/random.h\"\n#include \"absl/synchronization/internal/create_thread_identity.h\"\n#include \"absl/synchronization/internal/thread_pool.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\n#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM\n#include <pthread.h>\n#include <string.h>\n#endif\n\nnamespace {\n\n// TODO(dmauro): Replace with a commandline flag.\nstatic constexpr bool kExtendedTest = false;\n\nstd::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool(\n    int threads) {\n  return absl::make_unique<absl::synchronization_internal::ThreadPool>(threads);\n}\n\nstd::unique_ptr<absl::synchronization_internal::ThreadPool>\nCreateDefaultPool() {\n  return CreatePool(kExtendedTest ? 32 : 10);\n}\n\n// Hack to schedule a function to run on a thread pool thread after a\n// duration has elapsed.\nstatic void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,\n                          absl::Duration after,\n                          const std::function<void()> &func) {\n  tp->Schedule([func, after] {\n    absl::SleepFor(after);\n    func();\n  });\n}\n\nstruct ScopedInvariantDebugging {\n  ScopedInvariantDebugging() { absl::EnableMutexInvariantDebugging(true); }\n  ~ScopedInvariantDebugging() { absl::EnableMutexInvariantDebugging(false); }\n};\n\nstruct TestContext {\n  int iterations;\n  int threads;\n  int g0;  // global 0\n  int g1;  // global 1\n  absl::Mutex mu;\n  absl::CondVar cv;\n};\n\n// To test whether the invariant check call occurs\nstatic std::atomic<bool> invariant_checked;\n\nstatic bool GetInvariantChecked() {\n  return invariant_checked.load(std::memory_order_relaxed);\n}\n\nstatic void SetInvariantChecked(bool new_value) {\n  invariant_checked.store(new_value, std::memory_order_relaxed);\n}\n\nstatic void CheckSumG0G1(void *v) {\n  TestContext *cxt = static_cast<TestContext *>(v);\n  CHECK_EQ(cxt->g0, -cxt->g1) << \"Error in CheckSumG0G1\";\n  SetInvariantChecked(true);\n}\n\nstatic void TestMu(TestContext *cxt, int c) {\n  for (int i = 0; i != cxt->iterations; i++) {\n    absl::MutexLock l(cxt->mu);\n    int a = cxt->g0 + 1;\n    cxt->g0 = a;\n    cxt->g1--;\n  }\n}\n\nstatic void TestTry(TestContext *cxt, int c) {\n  for (int i = 0; i != cxt->iterations; i++) {\n    do {\n      std::this_thread::yield();\n    } while (!cxt->mu.try_lock());\n    int a = cxt->g0 + 1;\n    cxt->g0 = a;\n    cxt->g1--;\n    cxt->mu.unlock();\n  }\n}\n\nstatic void TestR20ms(TestContext *cxt, int c) {\n  for (int i = 0; i != cxt->iterations; i++) {\n    absl::ReaderMutexLock l(cxt->mu);\n    absl::SleepFor(absl::Milliseconds(20));\n    cxt->mu.AssertReaderHeld();\n  }\n}\n\nstatic void TestRW(TestContext *cxt, int c) {\n  if ((c & 1) == 0) {\n    for (int i = 0; i != cxt->iterations; i++) {\n      absl::WriterMutexLock l(cxt->mu);\n      cxt->g0++;\n      cxt->g1--;\n      cxt->mu.AssertHeld();\n      cxt->mu.AssertReaderHeld();\n    }\n  } else {\n    for (int i = 0; i != cxt->iterations; i++) {\n      absl::ReaderMutexLock l(cxt->mu);\n      CHECK_EQ(cxt->g0, -cxt->g1) << \"Error in TestRW\";\n      cxt->mu.AssertReaderHeld();\n    }\n  }\n}\n\nstruct MyContext {\n  int target;\n  TestContext *cxt;\n  bool MyTurn();\n};\n\nbool MyContext::MyTurn() {\n  TestContext *cxt = this->cxt;\n  return cxt->g0 == this->target || cxt->g0 == cxt->iterations;\n}\n\nstatic void TestAwait(TestContext *cxt, int c) {\n  MyContext mc;\n  mc.target = c;\n  mc.cxt = cxt;\n  absl::MutexLock l(cxt->mu);\n  cxt->mu.AssertHeld();\n  while (cxt->g0 < cxt->iterations) {\n    cxt->mu.Await(absl::Condition(&mc, &MyContext::MyTurn));\n    CHECK(mc.MyTurn()) << \"Error in TestAwait\";\n    cxt->mu.AssertHeld();\n    if (cxt->g0 < cxt->iterations) {\n      int a = cxt->g0 + 1;\n      cxt->g0 = a;\n      mc.target += cxt->threads;\n    }\n  }\n}\n\nstatic void TestSignalAll(TestContext *cxt, int c) {\n  int target = c;\n  absl::MutexLock l(cxt->mu);\n  cxt->mu.AssertHeld();\n  while (cxt->g0 < cxt->iterations) {\n    while (cxt->g0 != target && cxt->g0 != cxt->iterations) {\n      cxt->cv.Wait(&cxt->mu);\n    }\n    if (cxt->g0 < cxt->iterations) {\n      int a = cxt->g0 + 1;\n      cxt->g0 = a;\n      cxt->cv.SignalAll();\n      target += cxt->threads;\n    }\n  }\n}\n\nstatic void TestSignal(TestContext *cxt, int c) {\n  CHECK_EQ(cxt->threads, 2) << \"TestSignal should use 2 threads\";\n  int target = c;\n  absl::MutexLock l(cxt->mu);\n  cxt->mu.AssertHeld();\n  while (cxt->g0 < cxt->iterations) {\n    while (cxt->g0 != target && cxt->g0 != cxt->iterations) {\n      cxt->cv.Wait(&cxt->mu);\n    }\n    if (cxt->g0 < cxt->iterations) {\n      int a = cxt->g0 + 1;\n      cxt->g0 = a;\n      cxt->cv.Signal();\n      target += cxt->threads;\n    }\n  }\n}\n\nstatic void TestCVTimeout(TestContext *cxt, int c) {\n  int target = c;\n  absl::MutexLock l(cxt->mu);\n  cxt->mu.AssertHeld();\n  while (cxt->g0 < cxt->iterations) {\n    while (cxt->g0 != target && cxt->g0 != cxt->iterations) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));\n    }\n    if (cxt->g0 < cxt->iterations) {\n      int a = cxt->g0 + 1;\n      cxt->g0 = a;\n      cxt->cv.SignalAll();\n      target += cxt->threads;\n    }\n  }\n}\n\nstatic bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; }\n\nstatic void TestTime(TestContext *cxt, int c, bool use_cv) {\n  CHECK_EQ(cxt->iterations, 1) << \"TestTime should only use 1 iteration\";\n  CHECK_GT(cxt->threads, 2) << \"TestTime should use more than 2 threads\";\n  const bool kFalse = false;\n  absl::Condition false_cond(&kFalse);\n  absl::Condition g0ge2(G0GE2, cxt);\n  if (c == 0) {\n    absl::MutexLock l(cxt->mu);\n\n    absl::Time start = absl::Now();\n    if (use_cv) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));\n    } else {\n      CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)))\n          << \"TestTime failed\";\n    }\n    absl::Duration elapsed = absl::Now() - start;\n    CHECK(absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0))\n        << \"TestTime failed\";\n    CHECK_EQ(cxt->g0, 1) << \"TestTime failed\";\n\n    start = absl::Now();\n    if (use_cv) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));\n    } else {\n      CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)))\n          << \"TestTime failed\";\n    }\n    elapsed = absl::Now() - start;\n    CHECK(absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0))\n        << \"TestTime failed\";\n    cxt->g0++;\n    if (use_cv) {\n      cxt->cv.Signal();\n    }\n\n    start = absl::Now();\n    if (use_cv) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(4));\n    } else {\n      CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(4)))\n          << \"TestTime failed\";\n    }\n    elapsed = absl::Now() - start;\n    CHECK(absl::Seconds(3.9) <= elapsed && elapsed <= absl::Seconds(6.0))\n        << \"TestTime failed\";\n    CHECK_GE(cxt->g0, 3) << \"TestTime failed\";\n\n    start = absl::Now();\n    if (use_cv) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));\n    } else {\n      CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)))\n          << \"TestTime failed\";\n    }\n    elapsed = absl::Now() - start;\n    CHECK(absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0))\n        << \"TestTime failed\";\n    if (use_cv) {\n      cxt->cv.SignalAll();\n    }\n\n    start = absl::Now();\n    if (use_cv) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));\n    } else {\n      CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)))\n          << \"TestTime failed\";\n    }\n    elapsed = absl::Now() - start;\n    CHECK(absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0))\n        << \"TestTime failed\";\n    CHECK_EQ(cxt->g0, cxt->threads) << \"TestTime failed\";\n\n  } else if (c == 1) {\n    absl::MutexLock l(cxt->mu);\n    const absl::Time start = absl::Now();\n    if (use_cv) {\n      cxt->cv.WaitWithTimeout(&cxt->mu, absl::Milliseconds(500));\n    } else {\n      CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)))\n          << \"TestTime failed\";\n    }\n    const absl::Duration elapsed = absl::Now() - start;\n    CHECK(absl::Seconds(0.4) <= elapsed && elapsed <= absl::Seconds(0.9))\n        << \"TestTime failed\";\n    cxt->g0++;\n  } else if (c == 2) {\n    absl::MutexLock l(cxt->mu);\n    if (use_cv) {\n      while (cxt->g0 < 2) {\n        cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));\n      }\n    } else {\n      CHECK(cxt->mu.AwaitWithTimeout(g0ge2, absl::Seconds(100)))\n          << \"TestTime failed\";\n    }\n    cxt->g0++;\n  } else {\n    absl::MutexLock l(cxt->mu);\n    if (use_cv) {\n      while (cxt->g0 < 2) {\n        cxt->cv.Wait(&cxt->mu);\n      }\n    } else {\n      cxt->mu.Await(g0ge2);\n    }\n    cxt->g0++;\n  }\n}\n\nstatic void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }\n\nstatic void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }\n\nstatic void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,\n                    const std::function<void(int)> &cb) {\n  mu->lock();\n  int c = (*c0)++;\n  mu->unlock();\n  cb(c);\n  absl::MutexLock l(*mu);\n  (*c1)++;\n  cv->Signal();\n}\n\n// Code common to RunTest() and RunTestWithInvariantDebugging().\nstatic int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),\n                         int threads, int iterations, int operations) {\n  absl::Mutex mu2;\n  absl::CondVar cv2;\n  int c0 = 0;\n  int c1 = 0;\n  cxt->g0 = 0;\n  cxt->g1 = 0;\n  cxt->iterations = iterations;\n  cxt->threads = threads;\n  absl::synchronization_internal::ThreadPool tp(threads);\n  for (int i = 0; i != threads; i++) {\n    tp.Schedule(std::bind(\n        &EndTest, &c0, &c1, &mu2, &cv2,\n        std::function<void(int)>(std::bind(test, cxt, std::placeholders::_1))));\n  }\n  mu2.lock();\n  while (c1 != threads) {\n    cv2.Wait(&mu2);\n  }\n  mu2.unlock();\n  return cxt->g0;\n}\n\n// Basis for the parameterized tests configured below.\nstatic int RunTest(void (*test)(TestContext *cxt, int), int threads,\n                   int iterations, int operations) {\n  TestContext cxt;\n  return RunTestCommon(&cxt, test, threads, iterations, operations);\n}\n\n// Like RunTest(), but sets an invariant on the tested Mutex and\n// verifies that the invariant check happened. The invariant function\n// will be passed the TestContext* as its arg and must call\n// SetInvariantChecked(true);\n#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)\nstatic int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),\n                                         int threads, int iterations,\n                                         int operations,\n                                         void (*invariant)(void *)) {\n  ScopedInvariantDebugging scoped_debugging;\n  SetInvariantChecked(false);\n  TestContext cxt;\n  cxt.mu.EnableInvariantDebugging(invariant, &cxt);\n  int ret = RunTestCommon(&cxt, test, threads, iterations, operations);\n  CHECK(GetInvariantChecked()) << \"Invariant not checked\";\n  return ret;\n}\n#endif\n\n// --------------------------------------------------------\n// Test for fix of bug in TryRemove()\nstruct TimeoutBugStruct {\n  absl::Mutex mu;\n  bool a;\n  int a_waiter_count;\n};\n\nstatic void WaitForA(TimeoutBugStruct *x) {\n  x->mu.LockWhen(absl::Condition(&x->a));\n  x->a_waiter_count--;\n  x->mu.unlock();\n}\n\nstatic bool NoAWaiters(TimeoutBugStruct *x) { return x->a_waiter_count == 0; }\n\n// Test that a CondVar.Wait(&mutex) can un-block a call to mutex.Await() in\n// another thread.\nTEST(Mutex, CondVarWaitSignalsAwait) {\n  // Use a struct so the lock annotations apply.\n  struct {\n    absl::Mutex barrier_mu;\n    bool barrier ABSL_GUARDED_BY(barrier_mu) = false;\n\n    absl::Mutex release_mu;\n    bool release ABSL_GUARDED_BY(release_mu) = false;\n    absl::CondVar released_cv;\n  } state;\n\n  auto pool = CreateDefaultPool();\n\n  // Thread A.  Sets barrier, waits for release using Mutex::Await, then\n  // signals released_cv.\n  pool->Schedule([&state] {\n    state.release_mu.lock();\n\n    state.barrier_mu.lock();\n    state.barrier = true;\n    state.barrier_mu.unlock();\n\n    state.release_mu.Await(absl::Condition(&state.release));\n    state.released_cv.Signal();\n    state.release_mu.unlock();\n  });\n\n  state.barrier_mu.LockWhen(absl::Condition(&state.barrier));\n  state.barrier_mu.unlock();\n  state.release_mu.lock();\n  // Thread A is now blocked on release by way of Mutex::Await().\n\n  // Set release.  Calling released_cv.Wait() should un-block thread A,\n  // which will signal released_cv.  If not, the test will hang.\n  state.release = true;\n  state.released_cv.Wait(&state.release_mu);\n  state.release_mu.unlock();\n}\n\n// Test that a CondVar.WaitWithTimeout(&mutex) can un-block a call to\n// mutex.Await() in another thread.\nTEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {\n  // Use a struct so the lock annotations apply.\n  struct {\n    absl::Mutex barrier_mu;\n    bool barrier ABSL_GUARDED_BY(barrier_mu) = false;\n\n    absl::Mutex release_mu;\n    bool release ABSL_GUARDED_BY(release_mu) = false;\n    absl::CondVar released_cv;\n  } state;\n\n  auto pool = CreateDefaultPool();\n\n  // Thread A.  Sets barrier, waits for release using Mutex::Await, then\n  // signals released_cv.\n  pool->Schedule([&state] {\n    state.release_mu.lock();\n\n    state.barrier_mu.lock();\n    state.barrier = true;\n    state.barrier_mu.unlock();\n\n    state.release_mu.Await(absl::Condition(&state.release));\n    state.released_cv.Signal();\n    state.release_mu.unlock();\n  });\n\n  state.barrier_mu.LockWhen(absl::Condition(&state.barrier));\n  state.barrier_mu.unlock();\n  state.release_mu.lock();\n  // Thread A is now blocked on release by way of Mutex::Await().\n\n  // Set release.  Calling released_cv.Wait() should un-block thread A,\n  // which will signal released_cv.  If not, the test will hang.\n  state.release = true;\n  EXPECT_TRUE(\n      !state.released_cv.WaitWithTimeout(&state.release_mu, absl::Seconds(10)))\n      << \"; Unrecoverable test failure: CondVar::WaitWithTimeout did not \"\n         \"unblock the absl::Mutex::Await call in another thread.\";\n\n  state.release_mu.unlock();\n}\n\n// Test for regression of a bug in loop of TryRemove()\nTEST(Mutex, MutexTimeoutBug) {\n  auto tp = CreateDefaultPool();\n\n  TimeoutBugStruct x;\n  x.a = false;\n  x.a_waiter_count = 2;\n  tp->Schedule(std::bind(&WaitForA, &x));\n  tp->Schedule(std::bind(&WaitForA, &x));\n  absl::SleepFor(absl::Seconds(1));  // Allow first two threads to hang.\n  // The skip field of the second will point to the first because there are\n  // only two.\n\n  // Now cause a thread waiting on an always-false to time out\n  // This would deadlock when the bug was present.\n  bool always_false = false;\n  x.mu.LockWhenWithTimeout(absl::Condition(&always_false),\n                           absl::Milliseconds(500));\n\n  // if we get here, the bug is not present.   Cleanup the state.\n\n  x.a = true;                                    // wakeup the two waiters on A\n  x.mu.Await(absl::Condition(&NoAWaiters, &x));  // wait for them to exit\n  x.mu.unlock();\n}\n\nstruct CondVarWaitDeadlock : testing::TestWithParam<int> {\n  absl::Mutex mu;\n  absl::CondVar cv;\n  bool cond1 = false;\n  bool cond2 = false;\n  bool read_lock1;\n  bool read_lock2;\n  bool signal_unlocked;\n\n  CondVarWaitDeadlock() {\n    read_lock1 = GetParam() & (1 << 0);\n    read_lock2 = GetParam() & (1 << 1);\n    signal_unlocked = GetParam() & (1 << 2);\n  }\n\n  void Waiter1() {\n    if (read_lock1) {\n      mu.lock_shared();\n      while (!cond1) {\n        cv.Wait(&mu);\n      }\n      mu.unlock_shared();\n    } else {\n      mu.lock();\n      while (!cond1) {\n        cv.Wait(&mu);\n      }\n      mu.unlock();\n    }\n  }\n\n  void Waiter2() {\n    if (read_lock2) {\n      mu.ReaderLockWhen(absl::Condition(&cond2));\n      mu.unlock_shared();\n    } else {\n      mu.LockWhen(absl::Condition(&cond2));\n      mu.unlock();\n    }\n  }\n};\n\n// Test for a deadlock bug in Mutex::Fer().\n// The sequence of events that lead to the deadlock is:\n// 1. waiter1 blocks on cv in read mode (mu bits = 0).\n// 2. waiter2 blocks on mu in either mode (mu bits = kMuWait).\n// 3. main thread locks mu, sets cond1, unlocks mu (mu bits = kMuWait).\n// 4. main thread signals on cv and this eventually calls Mutex::Fer().\n// Currently Fer wakes waiter1 since mu bits = kMuWait (mutex is unlocked).\n// Before the bug fix Fer neither woke waiter1 nor queued it on mutex,\n// which resulted in deadlock.\nTEST_P(CondVarWaitDeadlock, Test) {\n  auto waiter1 = CreatePool(1);\n  auto waiter2 = CreatePool(1);\n  waiter1->Schedule([this] { this->Waiter1(); });\n  waiter2->Schedule([this] { this->Waiter2(); });\n\n  // Wait while threads block (best-effort is fine).\n  absl::SleepFor(absl::Milliseconds(100));\n\n  // Wake condwaiter.\n  mu.lock();\n  cond1 = true;\n  if (signal_unlocked) {\n    mu.unlock();\n    cv.Signal();\n  } else {\n    cv.Signal();\n    mu.unlock();\n  }\n  waiter1.reset();  // \"join\" waiter1\n\n  // Wake waiter.\n  mu.lock();\n  cond2 = true;\n  mu.unlock();\n  waiter2.reset();  // \"join\" waiter2\n}\n\nINSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,\n                         ::testing::Range(0, 8),\n                         ::testing::PrintToStringParamName());\n\n// --------------------------------------------------------\n// Test for fix of bug in DequeueAllWakeable()\n// Bug was that if there was more than one waiting reader\n// and all should be woken, the most recently blocked one\n// would not be.\n\nstruct DequeueAllWakeableBugStruct {\n  absl::Mutex mu;\n  absl::Mutex mu2;       // protects all fields below\n  int unfinished_count;  // count of unfinished readers; under mu2\n  bool done1;            // unfinished_count == 0; under mu2\n  int finished_count;    // count of finished readers, under mu2\n  bool done2;            // finished_count == 0; under mu2\n};\n\n// Test for regression of a bug in loop of DequeueAllWakeable()\nstatic void AcquireAsReader(DequeueAllWakeableBugStruct *x) {\n  x->mu.lock_shared();\n  x->mu2.lock();\n  x->unfinished_count--;\n  x->done1 = (x->unfinished_count == 0);\n  x->mu2.unlock();\n  // make sure that both readers acquired mu before we release it.\n  absl::SleepFor(absl::Seconds(2));\n  x->mu.unlock_shared();\n\n  x->mu2.lock();\n  x->finished_count--;\n  x->done2 = (x->finished_count == 0);\n  x->mu2.unlock();\n}\n\n// Test for regression of a bug in loop of DequeueAllWakeable()\nTEST(Mutex, MutexReaderWakeupBug) {\n  auto tp = CreateDefaultPool();\n\n  DequeueAllWakeableBugStruct x;\n  x.unfinished_count = 2;\n  x.done1 = false;\n  x.finished_count = 2;\n  x.done2 = false;\n  x.mu.lock();  // acquire mu exclusively\n  // queue two thread that will block on reader locks on x.mu\n  tp->Schedule(std::bind(&AcquireAsReader, &x));\n  tp->Schedule(std::bind(&AcquireAsReader, &x));\n  absl::SleepFor(absl::Seconds(1));  // give time for reader threads to block\n  x.mu.unlock();                     // wake them up\n\n  // both readers should finish promptly\n  EXPECT_TRUE(\n      x.mu2.LockWhenWithTimeout(absl::Condition(&x.done1), absl::Seconds(10)));\n  x.mu2.unlock();\n\n  EXPECT_TRUE(\n      x.mu2.LockWhenWithTimeout(absl::Condition(&x.done2), absl::Seconds(10)));\n  x.mu2.unlock();\n}\n\nstruct LockWhenTestStruct {\n  absl::Mutex mu1;\n  bool cond = false;\n\n  absl::Mutex mu2;\n  bool waiting = false;\n};\n\nstatic bool LockWhenTestIsCond(LockWhenTestStruct *s) {\n  s->mu2.lock();\n  s->waiting = true;\n  s->mu2.unlock();\n  return s->cond;\n}\n\nstatic void LockWhenTestWaitForIsCond(LockWhenTestStruct *s) {\n  s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));\n  s->mu1.unlock();\n}\n\nTEST(Mutex, LockWhen) {\n  LockWhenTestStruct s;\n\n  std::thread t(LockWhenTestWaitForIsCond, &s);\n  s.mu2.LockWhen(absl::Condition(&s.waiting));\n  s.mu2.unlock();\n\n  s.mu1.lock();\n  s.cond = true;\n  s.mu1.unlock();\n\n  t.join();\n}\n\nTEST(Mutex, LockWhenGuard) {\n  absl::Mutex mu;\n  int n = 30;\n  bool done = false;\n\n  // We don't inline the lambda because the conversion is ambiguous in MSVC.\n  bool (*cond_eq_10)(int *) = [](int *p) { return *p == 10; };\n  bool (*cond_lt_10)(int *) = [](int *p) { return *p < 10; };\n\n  std::thread t1([&mu, &n, &done, cond_eq_10]() {\n    absl::ReaderMutexLock lock(mu, absl::Condition(cond_eq_10, &n));\n    done = true;\n  });\n\n  std::thread t2[10];\n  for (std::thread &t : t2) {\n    t = std::thread([&mu, &n, cond_lt_10]() {\n      absl::WriterMutexLock lock(mu, absl::Condition(cond_lt_10, &n));\n      ++n;\n    });\n  }\n\n  {\n    absl::MutexLock lock(mu);\n    n = 0;\n  }\n\n  for (std::thread &t : t2) t.join();\n  t1.join();\n\n  EXPECT_TRUE(done);\n  EXPECT_EQ(n, 10);\n}\n\n// --------------------------------------------------------\n// The following test requires Mutex::lock_shared to be a real shared\n// lock, which is not the case in all builds.\n#if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)\n\n// Test for fix of bug in UnlockSlow() that incorrectly decremented the reader\n// count when putting a thread to sleep waiting for a false condition when the\n// lock was not held.\n\n// For this bug to strike, we make a thread wait on a free mutex with no\n// waiters by causing its wakeup condition to be false.   Then the\n// next two acquirers must be readers.   The bug causes the lock\n// to be released when one reader unlocks, rather than both.\n\nstruct ReaderDecrementBugStruct {\n  bool cond;  // to delay first thread (under mu)\n  int done;   // reference count (under mu)\n  absl::Mutex mu;\n\n  bool waiting_on_cond;   // under mu2\n  bool have_reader_lock;  // under mu2\n  bool complete;          // under mu2\n  absl::Mutex mu2;        // > mu\n};\n\n// L >= mu, L < mu_waiting_on_cond\nstatic bool IsCond(void *v) {\n  ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);\n  x->mu2.lock();\n  x->waiting_on_cond = true;\n  x->mu2.unlock();\n  return x->cond;\n}\n\n// L >= mu\nstatic bool AllDone(void *v) {\n  ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);\n  return x->done == 0;\n}\n\n// L={}\nstatic void WaitForCond(ReaderDecrementBugStruct *x) {\n  absl::Mutex dummy;\n  absl::MutexLock l(dummy);\n  x->mu.LockWhen(absl::Condition(&IsCond, x));\n  x->done--;\n  x->mu.unlock();\n}\n\n// L={}\nstatic void GetReadLock(ReaderDecrementBugStruct *x) {\n  x->mu.lock_shared();\n  x->mu2.lock();\n  x->have_reader_lock = true;\n  x->mu2.Await(absl::Condition(&x->complete));\n  x->mu2.unlock();\n  x->mu.unlock_shared();\n  x->mu.lock();\n  x->done--;\n  x->mu.unlock();\n}\n\n// Test for reader counter being decremented incorrectly by waiter\n// with false condition.\nTEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  ReaderDecrementBugStruct x;\n  x.cond = false;\n  x.waiting_on_cond = false;\n  x.have_reader_lock = false;\n  x.complete = false;\n  x.done = 2;  // initial ref count\n\n  // Run WaitForCond() and wait for it to sleep\n  std::thread thread1(WaitForCond, &x);\n  x.mu2.LockWhen(absl::Condition(&x.waiting_on_cond));\n  x.mu2.unlock();\n\n  // Run GetReadLock(), and wait for it to get the read lock\n  std::thread thread2(GetReadLock, &x);\n  x.mu2.LockWhen(absl::Condition(&x.have_reader_lock));\n  x.mu2.unlock();\n\n  // Get the reader lock ourselves, and release it.\n  x.mu.lock_shared();\n  x.mu.unlock_shared();\n\n  // The lock should be held in read mode by GetReadLock().\n  // If we have the bug, the lock will be free.\n  x.mu.AssertReaderHeld();\n\n  // Wake up all the threads.\n  x.mu2.lock();\n  x.complete = true;\n  x.mu2.unlock();\n\n  // TODO(delesley): turn on analysis once lock upgrading is supported.\n  // (This call upgrades the lock from shared to exclusive.)\n  x.mu.lock();\n  x.cond = true;\n  x.mu.Await(absl::Condition(&AllDone, &x));\n  x.mu.unlock();\n\n  thread1.join();\n  thread2.join();\n}\n#endif  // !ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE\n\n// Test that we correctly handle the situation when a lock is\n// held and then destroyed (w/o unlocking).\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n// TSAN reports errors when locked Mutexes are destroyed.\nTEST(Mutex, DISABLED_LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n#else\nTEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n#endif\n  for (int i = 0; i != 10; i++) {\n    // Create, lock and destroy 10 locks.\n    const int kNumLocks = 10;\n    auto mu = absl::make_unique<absl::Mutex[]>(kNumLocks);\n    for (int j = 0; j != kNumLocks; j++) {\n      if ((j % 2) == 0) {\n        mu[j].lock();\n      } else {\n        mu[j].lock_shared();\n      }\n    }\n  }\n}\n\n// Some functions taking pointers to non-const.\nbool Equals42(int *p) { return *p == 42; }\nbool Equals43(int *p) { return *p == 43; }\n\n// Some functions taking pointers to const.\nbool ConstEquals42(const int *p) { return *p == 42; }\nbool ConstEquals43(const int *p) { return *p == 43; }\n\n// Some function templates taking pointers. Note it's possible for `T` to be\n// deduced as non-const or const, which creates the potential for ambiguity,\n// but which the implementation is careful to avoid.\ntemplate <typename T>\nbool TemplateEquals42(T *p) {\n  return *p == 42;\n}\ntemplate <typename T>\nbool TemplateEquals43(T *p) {\n  return *p == 43;\n}\n\nTEST(Mutex, FunctionPointerCondition) {\n  // Some arguments.\n  int x = 42;\n  const int const_x = 42;\n\n  // Parameter non-const, argument non-const.\n  EXPECT_TRUE(absl::Condition(Equals42, &x).Eval());\n  EXPECT_FALSE(absl::Condition(Equals43, &x).Eval());\n\n  // Parameter const, argument non-const.\n  EXPECT_TRUE(absl::Condition(ConstEquals42, &x).Eval());\n  EXPECT_FALSE(absl::Condition(ConstEquals43, &x).Eval());\n\n  // Parameter const, argument const.\n  EXPECT_TRUE(absl::Condition(ConstEquals42, &const_x).Eval());\n  EXPECT_FALSE(absl::Condition(ConstEquals43, &const_x).Eval());\n\n  // Parameter type deduced, argument non-const.\n  EXPECT_TRUE(absl::Condition(TemplateEquals42, &x).Eval());\n  EXPECT_FALSE(absl::Condition(TemplateEquals43, &x).Eval());\n\n  // Parameter type deduced, argument const.\n  EXPECT_TRUE(absl::Condition(TemplateEquals42, &const_x).Eval());\n  EXPECT_FALSE(absl::Condition(TemplateEquals43, &const_x).Eval());\n\n  // Parameter non-const, argument const is not well-formed.\n  EXPECT_FALSE((std::is_constructible<absl::Condition, decltype(Equals42),\n                                      decltype(&const_x)>::value));\n  // Validate use of is_constructible by contrasting to a well-formed case.\n  EXPECT_TRUE((std::is_constructible<absl::Condition, decltype(ConstEquals42),\n                                     decltype(&const_x)>::value));\n}\n\n// Example base and derived class for use in predicates and test below. Not a\n// particularly realistic example, but it suffices for testing purposes.\nstruct Base {\n  explicit Base(int v) : value(v) {}\n  int value;\n};\nstruct Derived : Base {\n  explicit Derived(int v) : Base(v) {}\n};\n\n// Some functions taking pointer to non-const `Base`.\nbool BaseEquals42(Base *p) { return p->value == 42; }\nbool BaseEquals43(Base *p) { return p->value == 43; }\n\n// Some functions taking pointer to const `Base`.\nbool ConstBaseEquals42(const Base *p) { return p->value == 42; }\nbool ConstBaseEquals43(const Base *p) { return p->value == 43; }\n\nTEST(Mutex, FunctionPointerConditionWithDerivedToBaseConversion) {\n  // Some arguments.\n  Derived derived(42);\n  const Derived const_derived(42);\n\n  // Parameter non-const base, argument derived non-const.\n  EXPECT_TRUE(absl::Condition(BaseEquals42, &derived).Eval());\n  EXPECT_FALSE(absl::Condition(BaseEquals43, &derived).Eval());\n\n  // Parameter const base, argument derived non-const.\n  EXPECT_TRUE(absl::Condition(ConstBaseEquals42, &derived).Eval());\n  EXPECT_FALSE(absl::Condition(ConstBaseEquals43, &derived).Eval());\n\n  // Parameter const base, argument derived const.\n  EXPECT_TRUE(absl::Condition(ConstBaseEquals42, &const_derived).Eval());\n  EXPECT_FALSE(absl::Condition(ConstBaseEquals43, &const_derived).Eval());\n\n  // Parameter const base, argument derived const.\n  EXPECT_TRUE(absl::Condition(ConstBaseEquals42, &const_derived).Eval());\n  EXPECT_FALSE(absl::Condition(ConstBaseEquals43, &const_derived).Eval());\n\n  // Parameter derived, argument base is not well-formed.\n  bool (*derived_pred)(const Derived *) = [](const Derived *) { return true; };\n  EXPECT_FALSE((std::is_constructible<absl::Condition, decltype(derived_pred),\n                                      Base *>::value));\n  EXPECT_FALSE((std::is_constructible<absl::Condition, decltype(derived_pred),\n                                      const Base *>::value));\n  // Validate use of is_constructible by contrasting to well-formed cases.\n  EXPECT_TRUE((std::is_constructible<absl::Condition, decltype(derived_pred),\n                                     Derived *>::value));\n  EXPECT_TRUE((std::is_constructible<absl::Condition, decltype(derived_pred),\n                                     const Derived *>::value));\n}\n\nstruct Constable {\n  bool WotsAllThisThen() const { return true; }\n};\n\nTEST(Mutex, FunctionPointerConditionWithConstMethod) {\n  const Constable chapman;\n  EXPECT_TRUE(absl::Condition(&chapman, &Constable::WotsAllThisThen).Eval());\n}\n\n#ifdef __cpp_explicit_this_parameter\nstruct TrueViaDeducingThis {\n  template <class This, class... Args>\n  bool operator()(this const This&, Args...) {\n    return true;\n  }\n};\n\nTEST(Mutex, FunctorConditionDeducingThis) {\n  TrueViaDeducingThis f;\n  EXPECT_TRUE(absl::Condition(&f).Eval());\n}\n#endif\n\nstruct True {\n  template <class... Args>\n  bool operator()(Args...) const {\n    return true;\n  }\n};\n\nstruct DerivedTrue : True {};\n\nTEST(Mutex, FunctorCondition) {\n  {  // Variadic\n    True f;\n    EXPECT_TRUE(absl::Condition(&f).Eval());\n  }\n\n  {  // Inherited\n    DerivedTrue g;\n    EXPECT_TRUE(absl::Condition(&g).Eval());\n  }\n\n  {  // lambda\n    int value = 3;\n    auto is_zero = [&value] { return value == 0; };\n    absl::Condition c(&is_zero);\n    EXPECT_FALSE(c.Eval());\n    value = 0;\n    EXPECT_TRUE(c.Eval());\n  }\n\n  {  // bind\n    int value = 0;\n    auto is_positive = std::bind(std::less<int>(), 0, std::cref(value));\n    absl::Condition c(&is_positive);\n    EXPECT_FALSE(c.Eval());\n    value = 1;\n    EXPECT_TRUE(c.Eval());\n  }\n\n  {  // std::function\n    int value = 3;\n    std::function<bool()> is_zero = [&value] { return value == 0; };\n    absl::Condition c(&is_zero);\n    EXPECT_FALSE(c.Eval());\n    value = 0;\n    EXPECT_TRUE(c.Eval());\n  }\n}\n\nTEST(Mutex, ConditionSwap) {\n  // Ensure that Conditions can be swap'ed.\n  bool b1 = true;\n  absl::Condition c1(&b1);\n  bool b2 = false;\n  absl::Condition c2(&b2);\n  EXPECT_TRUE(c1.Eval());\n  EXPECT_FALSE(c2.Eval());\n  std::swap(c1, c2);\n  EXPECT_FALSE(c1.Eval());\n  EXPECT_TRUE(c2.Eval());\n}\n\n// --------------------------------------------------------\n// Test for bug with pattern of readers using a condvar.  The bug was that if a\n// reader went to sleep on a condition variable while one or more other readers\n// held the lock, but there were no waiters, the reader count (held in the\n// mutex word) would be lost.  (This is because Enqueue() had at one time\n// always placed the thread on the Mutex queue.  Later (CL 4075610), to\n// tolerate re-entry into Mutex from a Condition predicate, Enqueue() was\n// changed so that it could also place a thread on a condition-variable.  This\n// introduced the case where Enqueue() returned with an empty queue, and this\n// case was handled incorrectly in one place.)\n\nstatic void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,\n                                     int *running) {\n  absl::InsecureBitGen gen;\n  std::uniform_int_distribution<int> random_millis(0, 15);\n  mu->lock_shared();\n  while (*running == 3) {\n    absl::SleepFor(absl::Milliseconds(random_millis(gen)));\n    cv->WaitWithTimeout(mu, absl::Milliseconds(random_millis(gen)));\n  }\n  mu->unlock_shared();\n  mu->lock();\n  (*running)--;\n  mu->unlock();\n}\n\nstatic bool IntIsZero(int *x) { return *x == 0; }\n\n// Test for reader waiting condition variable when there are other readers\n// but no waiters.\nTEST(Mutex, TestReaderOnCondVar) {\n  auto tp = CreateDefaultPool();\n  absl::Mutex mu;\n  absl::CondVar cv;\n  int running = 3;\n  tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));\n  tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));\n  absl::SleepFor(absl::Seconds(2));\n  mu.lock();\n  running--;\n  mu.Await(absl::Condition(&IntIsZero, &running));\n  mu.unlock();\n}\n\n// --------------------------------------------------------\nstruct AcquireFromConditionStruct {\n  absl::Mutex mu0;   // protects value, done\n  int value;         // times condition function is called; under mu0,\n  bool done;         // done with test?  under mu0\n  absl::Mutex mu1;   // used to attempt to mess up state of mu0\n  absl::CondVar cv;  // so the condition function can be invoked from\n                     // CondVar::Wait().\n};\n\nstatic bool ConditionWithAcquire(AcquireFromConditionStruct *x) {\n  x->value++;  // count times this function is called\n\n  if (x->value == 2 || x->value == 3) {\n    // On the second and third invocation of this function, sleep for 100ms,\n    // but with the side-effect of altering the state of a Mutex other than\n    // than one for which this is a condition.  The spec now explicitly allows\n    // this side effect; previously it did not.  it was illegal.\n    bool always_false = false;\n    x->mu1.LockWhenWithTimeout(absl::Condition(&always_false),\n                               absl::Milliseconds(100));\n    x->mu1.unlock();\n  }\n  CHECK_LT(x->value, 4) << \"should not be invoked a fourth time\";\n\n  // We arrange for the condition to return true on only the 2nd and 3rd calls.\n  return x->value == 2 || x->value == 3;\n}\n\nstatic void WaitForCond2(AcquireFromConditionStruct *x) {\n  // wait for cond0 to become true\n  x->mu0.LockWhen(absl::Condition(&ConditionWithAcquire, x));\n  x->done = true;\n  x->mu0.unlock();\n}\n\n// Test for Condition whose function acquires other Mutexes\nTEST(Mutex, AcquireFromCondition) {\n  auto tp = CreateDefaultPool();\n\n  AcquireFromConditionStruct x;\n  x.value = 0;\n  x.done = false;\n  tp->Schedule(\n      std::bind(&WaitForCond2, &x));  // run WaitForCond2() in a thread T\n  // T will hang because the first invocation of ConditionWithAcquire() will\n  // return false.\n  absl::SleepFor(absl::Milliseconds(500));  // allow T time to hang\n\n  x.mu0.lock();\n  x.cv.WaitWithTimeout(&x.mu0, absl::Milliseconds(500));  // wake T\n  // T will be woken because the Wait() will call ConditionWithAcquire()\n  // for the second time, and it will return true.\n\n  x.mu0.unlock();\n\n  // T will then acquire the lock and recheck its own condition.\n  // It will find the condition true, as this is the third invocation,\n  // but the use of another Mutex by the calling function will\n  // cause the old mutex implementation to think that the outer\n  // LockWhen() has timed out because the inner LockWhenWithTimeout() did.\n  // T will then check the condition a fourth time because it finds a\n  // timeout occurred.  This should not happen in the new\n  // implementation that allows the Condition function to use Mutexes.\n\n  // It should also succeed, even though the Condition function\n  // is being invoked from CondVar::Wait, and thus this thread\n  // is conceptually waiting both on the condition variable, and on mu2.\n\n  x.mu0.LockWhen(absl::Condition(&x.done));\n  x.mu0.unlock();\n}\n\nTEST(Mutex, DeadlockDetector) {\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);\n\n  // check that we can call ForgetDeadlockInfo() on a lock with the lock held\n  absl::Mutex m1;\n  absl::Mutex m2;\n  absl::Mutex m3;\n  absl::Mutex m4;\n\n  m1.lock();  // m1 gets ID1\n  m2.lock();  // m2 gets ID2\n  m3.lock();  // m3 gets ID3\n  m3.unlock();\n  m2.unlock();\n  // m1 still held\n  m1.ForgetDeadlockInfo();  // m1 loses ID\n  m2.lock();                // m2 gets ID2\n  m3.lock();                // m3 gets ID3\n  m4.lock();                // m4 gets ID4\n  m3.unlock();\n  m2.unlock();\n  m4.unlock();\n  m1.unlock();\n}\n\n// Bazel has a test \"warning\" file that programs can write to if the\n// test should pass with a warning.  This class disables the warning\n// file until it goes out of scope.\nclass ScopedDisableBazelTestWarnings {\n public:\n  ScopedDisableBazelTestWarnings() {\n#ifdef _WIN32\n    char file[MAX_PATH];\n    if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {\n      warnings_output_file_ = file;\n      SetEnvironmentVariableA(kVarName, nullptr);\n    }\n#else\n    const char *file = getenv(kVarName);\n    if (file != nullptr) {\n      warnings_output_file_ = file;\n      unsetenv(kVarName);\n    }\n#endif\n  }\n\n  ~ScopedDisableBazelTestWarnings() {\n    if (!warnings_output_file_.empty()) {\n#ifdef _WIN32\n      SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());\n#else\n      setenv(kVarName, warnings_output_file_.c_str(), 0);\n#endif\n    }\n  }\n\n private:\n  static const char kVarName[];\n  std::string warnings_output_file_;\n};\nconst char ScopedDisableBazelTestWarnings::kVarName[] =\n    \"TEST_WARNINGS_OUTPUT_FILE\";\n\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n// This test intentionally creates deadlocks to test the deadlock detector.\nTEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {\n#else\nTEST(Mutex, DeadlockDetectorBazelWarning) {\n#endif\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);\n\n  // Cause deadlock detection to detect something, if it's\n  // compiled in and enabled.  But turn off the bazel warning.\n  ScopedDisableBazelTestWarnings disable_bazel_test_warnings;\n\n  absl::Mutex mu0;\n  absl::Mutex mu1;\n  bool got_mu0 = mu0.try_lock();\n  mu1.lock();  // acquire mu1 while holding mu0\n  if (got_mu0) {\n    mu0.unlock();\n  }\n  if (mu0.try_lock()) {  // try lock shouldn't cause deadlock detector to fire\n    mu0.unlock();\n  }\n  mu0.lock();  // acquire mu0 while holding mu1; should get one deadlock\n               // report here\n  mu0.unlock();\n  mu1.unlock();\n\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);\n}\n\nTEST(Mutex, DeadlockDetectorLongCycle) {\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);\n\n  // This test generates a warning if it passes, and crashes otherwise.\n  // Cause bazel to ignore the warning.\n  ScopedDisableBazelTestWarnings disable_bazel_test_warnings;\n\n  // Check that we survive a deadlock with a lock cycle.\n  std::vector<absl::Mutex> mutex(100);\n  for (size_t i = 0; i != mutex.size(); i++) {\n    mutex[i].lock();\n    mutex[(i + 1) % mutex.size()].lock();\n    mutex[i].unlock();\n    mutex[(i + 1) % mutex.size()].unlock();\n  }\n\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);\n}\n\n// This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the\n// annotation-based static thread-safety analysis is not currently\n// predicate-aware and cannot tell if the two for-loops that acquire and\n// release the locks have the same predicates.\nTEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  // Stress test: Here we create a large number of locks and use all of them.\n  // If a deadlock detector keeps a full graph of lock acquisition order,\n  // it will likely be too slow for this test to pass.\n  const int n_locks = 1 << 17;\n  auto array_of_locks = absl::make_unique<absl::Mutex[]>(n_locks);\n  for (int i = 0; i < n_locks; i++) {\n    int end = std::min(n_locks, i + 5);\n    // acquire and then release locks i, i+1, ..., i+4\n    for (int j = i; j < end; j++) {\n      array_of_locks[j].lock();\n    }\n    for (int j = i; j < end; j++) {\n      array_of_locks[j].unlock();\n    }\n  }\n}\n\n#ifdef ABSL_HAVE_THREAD_SANITIZER\n// TSAN reports errors when locked Mutexes are destroyed.\nTEST(Mutex, DISABLED_DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n#else\nTEST(Mutex, DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n#endif\n  // Test a scenario where a cached deadlock graph node id in the\n  // list of held locks is not invalidated when the corresponding\n  // mutex is deleted.\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);\n  // Mutex that will be destroyed while being held\n  absl::Mutex *a = new absl::Mutex;\n  // Other mutexes needed by test\n  absl::Mutex b, c;\n\n  // Hold mutex.\n  a->lock();\n\n  // Force deadlock id assignment by acquiring another lock.\n  b.lock();\n  b.unlock();\n\n  // Delete the mutex. The Mutex destructor tries to remove held locks,\n  // but the attempt isn't foolproof.  It can fail if:\n  //   (a) Deadlock detection is currently disabled.\n  //   (b) The destruction is from another thread.\n  // We exploit (a) by temporarily disabling deadlock detection.\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);\n  delete a;\n  absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);\n\n  // Now acquire another lock which will force a deadlock id assignment.\n  // We should end up getting assigned the same deadlock id that was\n  // freed up when \"a\" was deleted, which will cause a spurious deadlock\n  // report if the held lock entry for \"a\" was not invalidated.\n  c.lock();\n  c.unlock();\n}\n\n// --------------------------------------------------------\n// Test for timeouts/deadlines on condition waits that are specified using\n// absl::Duration and absl::Time.  For each waiting function we test with\n// a timeout/deadline that has already expired/passed, one that is infinite\n// and so never expires/passes, and one that will expire/pass in the near\n// future.\n\nstatic absl::Duration TimeoutTestAllowedSchedulingDelay() {\n  // Note: we use a function here because Microsoft Visual Studio fails to\n  // properly initialize constexpr static absl::Duration variables.\n  return absl::Milliseconds(150);\n}\n\n// Returns true if `actual_delay` is close enough to `expected_delay` to pass\n// the timeouts/deadlines test.  Otherwise, logs warnings and returns false.\n[[nodiscard]]\nstatic bool DelayIsWithinBounds(absl::Duration expected_delay,\n                                absl::Duration actual_delay) {\n  bool pass = true;\n  // Do not allow the observed delay to be less than expected.  This may occur\n  // in practice due to clock skew or when the synchronization primitives use a\n  // different clock than absl::Now(), but these cases should be handled by the\n  // the retry mechanism in each TimeoutTest.\n  if (actual_delay < expected_delay) {\n    LOG(WARNING) << \"Actual delay \" << actual_delay\n                 << \" was too short, expected \" << expected_delay\n                 << \" (difference \" << actual_delay - expected_delay << \")\";\n    pass = false;\n  }\n  // If the expected delay is <= zero then allow a small error tolerance, since\n  // we do not expect context switches to occur during test execution.\n  // Otherwise, thread scheduling delays may be substantial in rare cases, so\n  // tolerate up to kTimeoutTestAllowedSchedulingDelay of error.\n  absl::Duration tolerance = expected_delay <= absl::ZeroDuration()\n                                 ? absl::Milliseconds(10)\n                                 : TimeoutTestAllowedSchedulingDelay();\n  if (actual_delay > expected_delay + tolerance) {\n    LOG(WARNING) << \"Actual delay \" << actual_delay\n                 << \" was too long, expected \" << expected_delay\n                 << \" (difference \" << actual_delay - expected_delay << \")\";\n    pass = false;\n  }\n  return pass;\n}\n\n// Parameters for TimeoutTest, below.\nstruct TimeoutTestParam {\n  // The file and line number (used for logging purposes only).\n  const char *from_file;\n  int from_line;\n\n  // Should the absolute deadline API based on absl::Time be tested?  If false,\n  // the relative deadline API based on absl::Duration is tested.\n  bool use_absolute_deadline;\n\n  // The deadline/timeout used when calling the API being tested\n  // (e.g. Mutex::LockWhenWithDeadline).\n  absl::Duration wait_timeout;\n\n  // The delay before the condition will be set true by the test code.  If zero\n  // or negative, the condition is set true immediately (before calling the API\n  // being tested).  Otherwise, if infinite, the condition is never set true.\n  // Otherwise a closure is scheduled for the future that sets the condition\n  // true.\n  absl::Duration satisfy_condition_delay;\n\n  // The expected result of the condition after the call to the API being\n  // tested. Generally `true` means the condition was true when the API returns,\n  // `false` indicates an expected timeout.\n  bool expected_result;\n\n  // The expected delay before the API under test returns.  This is inherently\n  // flaky, so some slop is allowed (see `DelayIsWithinBounds` above), and the\n  // test keeps trying indefinitely until this constraint passes.\n  absl::Duration expected_delay;\n};\n\n// Print a `TimeoutTestParam` to a debug log.\nstd::ostream &operator<<(std::ostream &os, const TimeoutTestParam &param) {\n  return os << \"from: \" << param.from_file << \":\" << param.from_line\n            << \" use_absolute_deadline: \"\n            << (param.use_absolute_deadline ? \"true\" : \"false\")\n            << \" wait_timeout: \" << param.wait_timeout\n            << \" satisfy_condition_delay: \" << param.satisfy_condition_delay\n            << \" expected_result: \"\n            << (param.expected_result ? \"true\" : \"false\")\n            << \" expected_delay: \" << param.expected_delay;\n}\n\n// Like `thread::Executor::ScheduleAt` except:\n// a) Delays zero or negative are executed immediately in the current thread.\n// b) Infinite delays are never scheduled.\n// c) Calls this test's `ScheduleAt` helper instead of using `pool` directly.\nstatic void RunAfterDelay(absl::Duration delay,\n                          absl::synchronization_internal::ThreadPool *pool,\n                          const std::function<void()> &callback) {\n  if (delay <= absl::ZeroDuration()) {\n    callback();  // immediate\n  } else if (delay != absl::InfiniteDuration()) {\n    ScheduleAfter(pool, delay, callback);\n  }\n}\n\nclass TimeoutTest : public ::testing::Test,\n                    public ::testing::WithParamInterface<TimeoutTestParam> {};\n\nstd::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {\n  // The `finite` delay is a finite, relatively short, delay.  We make it larger\n  // than our allowed scheduling delay (slop factor) to avoid confusion when\n  // diagnosing test failures.  The other constants here have clear meanings.\n  const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay();\n  const absl::Duration never = absl::InfiniteDuration();\n  const absl::Duration negative = -absl::InfiniteDuration();\n  const absl::Duration immediate = absl::ZeroDuration();\n\n  // Every test case is run twice; once using the absolute deadline API and once\n  // using the relative timeout API.\n  std::vector<TimeoutTestParam> values;\n  for (bool use_absolute_deadline : {false, true}) {\n    // Tests with a negative timeout (deadline in the past), which should\n    // immediately return current state of the condition.\n\n    // The condition is already true:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        negative,   // wait_timeout\n        immediate,  // satisfy_condition_delay\n        true,       // expected_result\n        immediate,  // expected_delay\n    });\n\n    // The condition becomes true, but the timeout has already expired:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        negative,  // wait_timeout\n        finite,    // satisfy_condition_delay\n        false,     // expected_result\n        immediate  // expected_delay\n    });\n\n    // The condition never becomes true:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        negative,  // wait_timeout\n        never,     // satisfy_condition_delay\n        false,     // expected_result\n        immediate  // expected_delay\n    });\n\n    // Tests with an infinite timeout (deadline in the infinite future), which\n    // should only return when the condition becomes true.\n\n    // The condition is already true:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        never,      // wait_timeout\n        immediate,  // satisfy_condition_delay\n        true,       // expected_result\n        immediate   // expected_delay\n    });\n\n    // The condition becomes true before the (infinite) expiry:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        never,   // wait_timeout\n        finite,  // satisfy_condition_delay\n        true,    // expected_result\n        finite,  // expected_delay\n    });\n\n    // Tests with a (small) finite timeout (deadline soon), with the condition\n    // becoming true both before and after its expiry.\n\n    // The condition is already true:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        never,      // wait_timeout\n        immediate,  // satisfy_condition_delay\n        true,       // expected_result\n        immediate   // expected_delay\n    });\n\n    // The condition becomes true before the expiry:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        finite * 2,  // wait_timeout\n        finite,      // satisfy_condition_delay\n        true,        // expected_result\n        finite       // expected_delay\n    });\n\n    // The condition becomes true, but the timeout has already expired:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        finite,      // wait_timeout\n        finite * 2,  // satisfy_condition_delay\n        false,       // expected_result\n        finite       // expected_delay\n    });\n\n    // The condition never becomes true:\n    values.push_back(TimeoutTestParam{\n        __FILE__, __LINE__, use_absolute_deadline,\n        finite,  // wait_timeout\n        never,   // satisfy_condition_delay\n        false,   // expected_result\n        finite   // expected_delay\n    });\n  }\n  return values;\n}\n\n// Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.\nINSTANTIATE_TEST_SUITE_P(All, TimeoutTest,\n                         testing::ValuesIn(MakeTimeoutTestParamValues()));\n\nTEST_P(TimeoutTest, Await) {\n  const TimeoutTestParam params = GetParam();\n  LOG(INFO) << \"Params: \" << params;\n\n  // Because this test asserts bounds on scheduling delays it is flaky.  To\n  // compensate it loops forever until it passes.  Failures express as test\n  // timeouts, in which case the test log can be used to diagnose the issue.\n  for (int attempt = 1;; ++attempt) {\n    LOG(INFO) << \"Attempt \" << attempt;\n\n    absl::Mutex mu;\n    bool value = false;  // condition value (under mu)\n\n    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =\n        CreateDefaultPool();\n    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {\n      absl::MutexLock l(mu);\n      value = true;\n    });\n\n    absl::MutexLock lock(mu);\n    absl::Time start_time = absl::Now();\n    absl::Condition cond(&value);\n    bool result =\n        params.use_absolute_deadline\n            ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout)\n            : mu.AwaitWithTimeout(cond, params.wait_timeout);\n    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {\n      EXPECT_EQ(params.expected_result, result);\n      break;\n    }\n  }\n}\n\nTEST_P(TimeoutTest, LockWhen) {\n  const TimeoutTestParam params = GetParam();\n  LOG(INFO) << \"Params: \" << params;\n\n  // Because this test asserts bounds on scheduling delays it is flaky.  To\n  // compensate it loops forever until it passes.  Failures express as test\n  // timeouts, in which case the test log can be used to diagnose the issue.\n  for (int attempt = 1;; ++attempt) {\n    LOG(INFO) << \"Attempt \" << attempt;\n\n    absl::Mutex mu;\n    bool value = false;  // condition value (under mu)\n\n    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =\n        CreateDefaultPool();\n    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {\n      absl::MutexLock l(mu);\n      value = true;\n    });\n\n    absl::Time start_time = absl::Now();\n    absl::Condition cond(&value);\n    bool result =\n        params.use_absolute_deadline\n            ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout)\n            : mu.LockWhenWithTimeout(cond, params.wait_timeout);\n    mu.unlock();\n\n    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {\n      EXPECT_EQ(params.expected_result, result);\n      break;\n    }\n  }\n}\n\nTEST_P(TimeoutTest, ReaderLockWhen) {\n  const TimeoutTestParam params = GetParam();\n  LOG(INFO) << \"Params: \" << params;\n\n  // Because this test asserts bounds on scheduling delays it is flaky.  To\n  // compensate it loops forever until it passes.  Failures express as test\n  // timeouts, in which case the test log can be used to diagnose the issue.\n  for (int attempt = 0;; ++attempt) {\n    LOG(INFO) << \"Attempt \" << attempt;\n\n    absl::Mutex mu;\n    bool value = false;  // condition value (under mu)\n\n    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =\n        CreateDefaultPool();\n    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {\n      absl::MutexLock l(mu);\n      value = true;\n    });\n\n    absl::Time start_time = absl::Now();\n    bool result =\n        params.use_absolute_deadline\n            ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value),\n                                            start_time + params.wait_timeout)\n            : mu.ReaderLockWhenWithTimeout(absl::Condition(&value),\n                                           params.wait_timeout);\n    mu.unlock_shared();\n\n    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {\n      EXPECT_EQ(params.expected_result, result);\n      break;\n    }\n  }\n}\n\nTEST_P(TimeoutTest, Wait) {\n  const TimeoutTestParam params = GetParam();\n  LOG(INFO) << \"Params: \" << params;\n\n  // Because this test asserts bounds on scheduling delays it is flaky.  To\n  // compensate it loops forever until it passes.  Failures express as test\n  // timeouts, in which case the test log can be used to diagnose the issue.\n  for (int attempt = 0;; ++attempt) {\n    LOG(INFO) << \"Attempt \" << attempt;\n\n    absl::Mutex mu;\n    bool value = false;  // condition value (under mu)\n    absl::CondVar cv;    // signals a change of `value`\n\n    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =\n        CreateDefaultPool();\n    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {\n      absl::MutexLock l(mu);\n      value = true;\n      cv.Signal();\n    });\n\n    absl::MutexLock lock(mu);\n    absl::Time start_time = absl::Now();\n    absl::Duration timeout = params.wait_timeout;\n    absl::Time deadline = start_time + timeout;\n    while (!value) {\n      if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline)\n                                       : cv.WaitWithTimeout(&mu, timeout)) {\n        break;  // deadline/timeout exceeded\n      }\n      timeout = deadline - absl::Now();  // recompute\n    }\n    bool result = value;  // note: `mu` is still held\n\n    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {\n      EXPECT_EQ(params.expected_result, result);\n      break;\n    }\n  }\n}\n\nTEST(Mutex, Logging) {\n  // Allow user to look at logging output\n  absl::Mutex logged_mutex;\n  logged_mutex.EnableDebugLog(\"fido_mutex\");\n  absl::CondVar logged_cv;\n  logged_cv.EnableDebugLog(\"rover_cv\");\n  logged_mutex.lock();\n  logged_cv.WaitWithTimeout(&logged_mutex, absl::Milliseconds(20));\n  logged_mutex.unlock();\n  logged_mutex.lock_shared();\n  logged_mutex.unlock_shared();\n  logged_mutex.lock();\n  logged_mutex.unlock();\n  logged_cv.Signal();\n  logged_cv.SignalAll();\n}\n\nTEST(Mutex, LoggingAddressReuse) {\n  // Repeatedly re-create a Mutex with debug logging at the same address.\n  ScopedInvariantDebugging scoped_debugging;\n  alignas(absl::Mutex) unsigned char storage[sizeof(absl::Mutex)];\n  auto invariant =\n      +[](void *alive) { EXPECT_TRUE(*static_cast<bool *>(alive)); };\n  constexpr size_t kIters = 10;\n  bool alive[kIters] = {};\n  for (size_t i = 0; i < kIters; ++i) {\n    absl::Mutex *mu = new (storage) absl::Mutex;\n    alive[i] = true;\n    mu->EnableDebugLog(\"Mutex\");\n    mu->EnableInvariantDebugging(invariant, &alive[i]);\n    mu->lock();\n    mu->unlock();\n    mu->~Mutex();\n    alive[i] = false;\n  }\n}\n\nTEST(Mutex, LoggingBankrupcy) {\n  // Test the case with too many live Mutexes with debug logging.\n  ScopedInvariantDebugging scoped_debugging;\n  std::vector<absl::Mutex> mus(1 << 20);\n  for (auto &mu : mus) {\n    mu.EnableDebugLog(\"Mutex\");\n  }\n}\n\nTEST(Mutex, SynchEventRace) {\n  // Regression test for a false TSan race report in\n  // EnableInvariantDebugging/EnableDebugLog related to SynchEvent reuse.\n  ScopedInvariantDebugging scoped_debugging;\n  std::vector<std::thread> threads;\n  for (size_t i = 0; i < 5; i++) {\n    threads.emplace_back([&] {\n      for (size_t j = 0; j < (1 << 17); j++) {\n        {\n          absl::Mutex mu;\n          mu.EnableInvariantDebugging([](void *) {}, nullptr);\n          mu.lock();\n          mu.unlock();\n        }\n        {\n          absl::Mutex mu;\n          mu.EnableDebugLog(\"Mutex\");\n        }\n      }\n    });\n  }\n  for (auto &thread : threads) {\n    thread.join();\n  }\n}\n\n// --------------------------------------------------------\n\n// Generate the vector of thread counts for tests parameterized on thread count.\nstatic std::vector<int> AllThreadCountValues() {\n  if (kExtendedTest) {\n    return {2, 4, 8, 10, 16, 20, 24, 30, 32};\n  }\n  return {2, 4, 10};\n}\n\n// A test fixture parameterized by thread count.\nclass MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};\n\n// Instantiate the above with AllThreadCountOptions().\nINSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,\n                         ::testing::ValuesIn(AllThreadCountValues()),\n                         ::testing::PrintToStringParamName());\n\n// Reduces iterations by some factor for slow platforms\n// (determined empirically).\nstatic int ScaleIterations(int x) {\n  // ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE is set in the implementation\n  // of Mutex that uses either std::mutex or pthread_mutex_t. Use\n  // these as keys to determine the slow implementation.\n#if defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)\n  return x / 10;\n#else\n  return x;\n#endif\n}\n\nTEST_P(MutexVariableThreadCountTest, Mutex) {\n  int threads = GetParam();\n  int iterations = ScaleIterations(10000000) / threads;\n  int operations = threads * iterations;\n  EXPECT_EQ(RunTest(&TestMu, threads, iterations, operations), operations);\n#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)\n  iterations = std::min(iterations, 10);\n  operations = threads * iterations;\n  EXPECT_EQ(RunTestWithInvariantDebugging(&TestMu, threads, iterations,\n                                          operations, CheckSumG0G1),\n            operations);\n#endif\n}\n\nTEST_P(MutexVariableThreadCountTest, Try) {\n  int threads = GetParam();\n  int iterations = 1000000 / threads;\n  int operations = iterations * threads;\n  EXPECT_EQ(RunTest(&TestTry, threads, iterations, operations), operations);\n#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)\n  iterations = std::min(iterations, 10);\n  operations = threads * iterations;\n  EXPECT_EQ(RunTestWithInvariantDebugging(&TestTry, threads, iterations,\n                                          operations, CheckSumG0G1),\n            operations);\n#endif\n}\n\nTEST_P(MutexVariableThreadCountTest, R20ms) {\n  int threads = GetParam();\n  int iterations = 100;\n  int operations = iterations * threads;\n  EXPECT_EQ(RunTest(&TestR20ms, threads, iterations, operations), 0);\n}\n\nTEST_P(MutexVariableThreadCountTest, RW) {\n  int threads = GetParam();\n  int iterations = ScaleIterations(20000000) / threads;\n  int operations = iterations * threads;\n  EXPECT_EQ(RunTest(&TestRW, threads, iterations, operations), operations / 2);\n#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)\n  iterations = std::min(iterations, 10);\n  operations = threads * iterations;\n  EXPECT_EQ(RunTestWithInvariantDebugging(&TestRW, threads, iterations,\n                                          operations, CheckSumG0G1),\n            operations / 2);\n#endif\n}\n\nTEST_P(MutexVariableThreadCountTest, Await) {\n  int threads = GetParam();\n  int iterations = ScaleIterations(500000);\n  int operations = iterations;\n  EXPECT_EQ(RunTest(&TestAwait, threads, iterations, operations), operations);\n}\n\nTEST_P(MutexVariableThreadCountTest, SignalAll) {\n  int threads = GetParam();\n  int iterations = 200000 / threads;\n  int operations = iterations;\n  EXPECT_EQ(RunTest(&TestSignalAll, threads, iterations, operations),\n            operations);\n}\n\nTEST(Mutex, Signal) {\n  int threads = 2;  // TestSignal must use two threads\n  int iterations = 200000;\n  int operations = iterations;\n  EXPECT_EQ(RunTest(&TestSignal, threads, iterations, operations), operations);\n}\n\nTEST(Mutex, Timed) {\n  int threads = 10;  // Use a fixed thread count of 10\n  int iterations = 1000;\n  int operations = iterations;\n  EXPECT_EQ(RunTest(&TestCVTimeout, threads, iterations, operations),\n            operations);\n}\n\nTEST(Mutex, CVTime) {\n  int threads = 10;  // Use a fixed thread count of 10\n  int iterations = 1;\n  EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1), threads * iterations);\n}\n\nTEST(Mutex, MuTime) {\n  int threads = 10;  // Use a fixed thread count of 10\n  int iterations = 1;\n  EXPECT_EQ(RunTest(&TestMuTime, threads, iterations, 1), threads * iterations);\n}\n\nTEST(Mutex, SignalExitedThread) {\n  // The test may expose a race when Mutex::unlock signals a thread\n  // that has already exited.\n#if defined(__wasm__) || defined(__asmjs__)\n  constexpr int kThreads = 1;  // OOMs under WASM\n#else\n  constexpr int kThreads = 100;\n#endif\n  std::vector<std::thread> top;\n  for (unsigned i = 0; i < 2 * std::thread::hardware_concurrency(); i++) {\n    top.emplace_back([&]() {\n      for (int i = 0; i < kThreads; i++) {\n        absl::Mutex mu;\n        std::thread t([&]() {\n          mu.lock();\n          mu.unlock();\n        });\n        mu.lock();\n        mu.unlock();\n        t.join();\n      }\n    });\n  }\n  for (auto &th : top) th.join();\n}\n\nTEST(Mutex, WriterPriority) {\n  absl::Mutex mu;\n  bool wrote = false;\n  std::atomic<bool> saw_wrote{false};\n  auto readfunc = [&]() {\n    for (size_t i = 0; i < 10; ++i) {\n      absl::ReaderMutexLock lock(mu);\n      if (wrote) {\n        saw_wrote = true;\n        break;\n      }\n      absl::SleepFor(absl::Seconds(1));\n    }\n  };\n  std::thread t1(readfunc);\n  absl::SleepFor(absl::Milliseconds(500));\n  std::thread t2(readfunc);\n  // Note: this test guards against a bug that was related to an uninit\n  // PerThreadSynch::priority, so the writer intentionally runs on a new thread.\n  std::thread t3([&]() {\n    // The writer should be able squeeze between the two alternating readers.\n    absl::MutexLock lock(mu);\n    wrote = true;\n  });\n  t1.join();\n  t2.join();\n  t3.join();\n  EXPECT_TRUE(saw_wrote.load());\n}\n\n#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM\nTEST(Mutex, CondVarPriority) {\n  // A regression test for a bug in condition variable wait morphing,\n  // which resulted in the waiting thread getting priority of the waking thread.\n  int err = 0;\n  sched_param param;\n  param.sched_priority = 7;\n  std::thread test([&]() {\n    err = pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);\n  });\n  test.join();\n  if (err) {\n    // Setting priority usually requires special privileges.\n    GTEST_SKIP() << \"failed to set priority: \" << strerror(err);\n  }\n  absl::Mutex mu;\n  absl::CondVar cv;\n  bool locked = false;\n  bool notified = false;\n  bool waiting = false;\n  bool morph = false;\n  std::thread th([&]() {\n    EXPECT_EQ(0, pthread_setschedparam(pthread_self(), SCHED_FIFO, &param));\n    mu.lock();\n    locked = true;\n    mu.Await(absl::Condition(&notified));\n    mu.unlock();\n    EXPECT_EQ(absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()\n                  ->per_thread_synch.priority,\n              param.sched_priority);\n    mu.lock();\n    mu.Await(absl::Condition(&waiting));\n    morph = true;\n    absl::SleepFor(absl::Seconds(1));\n    cv.Signal();\n    mu.unlock();\n  });\n  mu.lock();\n  mu.Await(absl::Condition(&locked));\n  notified = true;\n  mu.unlock();\n  mu.lock();\n  waiting = true;\n  while (!morph) {\n    cv.Wait(&mu);\n  }\n  mu.unlock();\n  th.join();\n  EXPECT_NE(absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()\n                ->per_thread_synch.priority,\n            param.sched_priority);\n}\n#endif\n\nTEST(Mutex, LockWhenWithTimeoutResult) {\n  // Check various corner cases for Await/LockWhen return value\n  // with always true/always false conditions.\n  absl::Mutex mu;\n  const bool kAlwaysTrue = true, kAlwaysFalse = false;\n  const absl::Condition kTrueCond(&kAlwaysTrue), kFalseCond(&kAlwaysFalse);\n  EXPECT_TRUE(mu.LockWhenWithTimeout(kTrueCond, absl::Milliseconds(1)));\n  mu.unlock();\n  EXPECT_FALSE(mu.LockWhenWithTimeout(kFalseCond, absl::Milliseconds(1)));\n  EXPECT_TRUE(mu.AwaitWithTimeout(kTrueCond, absl::Milliseconds(1)));\n  EXPECT_FALSE(mu.AwaitWithTimeout(kFalseCond, absl::Milliseconds(1)));\n  std::thread th1([&]() {\n    EXPECT_TRUE(mu.LockWhenWithTimeout(kTrueCond, absl::Milliseconds(1)));\n    mu.unlock();\n  });\n  std::thread th2([&]() {\n    EXPECT_FALSE(mu.LockWhenWithTimeout(kFalseCond, absl::Milliseconds(1)));\n    mu.unlock();\n  });\n  absl::SleepFor(absl::Milliseconds(100));\n  mu.unlock();\n  th1.join();\n  th2.join();\n}\n\nTEST(Mutex, ScopedLock) {\n  absl::Mutex mu;\n  {\n    std::scoped_lock l(mu);\n  }\n\n  {\n    std::shared_lock l(mu);\n    EXPECT_TRUE(l.owns_lock());\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/synchronization/notification.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/notification.h\"\n\n#include <atomic>\n\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/internal/tracing.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nvoid Notification::Notify() {\n  base_internal::TraceSignal(this, TraceObjectKind());\n  MutexLock l(this->mutex_);\n\n#ifndef NDEBUG\n  if (ABSL_PREDICT_FALSE(notified_yet_.load(std::memory_order_relaxed))) {\n    ABSL_RAW_LOG(\n        FATAL,\n        \"Notify() method called more than once for Notification object %p\",\n        static_cast<void *>(this));\n  }\n#endif\n\n  notified_yet_.store(true, std::memory_order_release);\n}\n\nNotification::~Notification() {\n  // Make sure that the thread running Notify() exits before the object is\n  // destructed.\n  MutexLock l(this->mutex_);\n}\n\nvoid Notification::WaitForNotification() const {\n  base_internal::TraceWait(this, TraceObjectKind());\n  if (!HasBeenNotifiedInternal(&this->notified_yet_)) {\n    this->mutex_.LockWhen(\n        Condition(&HasBeenNotifiedInternal, &this->notified_yet_));\n    this->mutex_.unlock();\n  }\n  base_internal::TraceContinue(this, TraceObjectKind());\n}\n\nbool Notification::WaitForNotificationWithTimeout(\n    absl::Duration timeout) const {\n  base_internal::TraceWait(this, TraceObjectKind());\n  bool notified = HasBeenNotifiedInternal(&this->notified_yet_);\n  if (!notified) {\n    notified = this->mutex_.LockWhenWithTimeout(\n        Condition(&HasBeenNotifiedInternal, &this->notified_yet_), timeout);\n    this->mutex_.unlock();\n  }\n  base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind());\n  return notified;\n}\n\nbool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const {\n  base_internal::TraceWait(this, TraceObjectKind());\n  bool notified = HasBeenNotifiedInternal(&this->notified_yet_);\n  if (!notified) {\n    notified = this->mutex_.LockWhenWithDeadline(\n        Condition(&HasBeenNotifiedInternal, &this->notified_yet_), deadline);\n    this->mutex_.unlock();\n  }\n  base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind());\n  return notified;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/synchronization/notification.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// notification.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a `Notification` abstraction, which allows threads\n// to receive notification of a single occurrence of a single event.\n//\n// The `Notification` object maintains a private boolean \"notified\" state that\n// transitions to `true` at most once. The `Notification` class provides the\n// following primary member functions:\n//   * `HasBeenNotified()` to query its state\n//   * `WaitForNotification*()` to have threads wait until the \"notified\" state\n//      is `true`.\n//   * `Notify()` to set the notification's \"notified\" state to `true` and\n//     notify all waiting threads that the event has occurred.\n//     This method may only be called once.\n//\n// Note that while `Notify()` may only be called once, it is perfectly valid to\n// call any of the `WaitForNotification*()` methods multiple times, from\n// multiple threads -- even after the notification's \"notified\" state has been\n// set -- in which case those methods will immediately return.\n//\n// Note that the lifetime of a `Notification` requires careful consideration;\n// it might not be safe to destroy a notification after calling `Notify()` since\n// it is still legal for other threads to call `WaitForNotification*()` methods\n// on the notification. However, observers responding to a \"notified\" state of\n// `true` can safely delete the notification without interfering with the call\n// to `Notify()` in the other thread.\n//\n// Memory ordering: For any threads X and Y, if X calls `Notify()`, then any\n// action taken by X before it calls `Notify()` is visible to thread Y after:\n//  * Y returns from `WaitForNotification()`, or\n//  * Y receives a `true` return value from either `HasBeenNotified()` or\n//    `WaitForNotificationWithTimeout()`.\n\n#ifndef ABSL_SYNCHRONIZATION_NOTIFICATION_H_\n#define ABSL_SYNCHRONIZATION_NOTIFICATION_H_\n\n#include <atomic>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/tracing.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// -----------------------------------------------------------------------------\n// Notification\n// -----------------------------------------------------------------------------\nclass Notification {\n public:\n  // Initializes the \"notified\" state to unnotified.\n  Notification() : notified_yet_(false) {}\n  explicit Notification(bool prenotify) : notified_yet_(prenotify) {}\n  Notification(const Notification&) = delete;\n  Notification& operator=(const Notification&) = delete;\n  ~Notification();\n\n  // Notification::HasBeenNotified()\n  //\n  // Returns the value of the notification's internal \"notified\" state.\n  [[nodiscard]] bool HasBeenNotified() const {\n    if (HasBeenNotifiedInternal(&this->notified_yet_)) {\n      base_internal::TraceObserved(this, TraceObjectKind());\n      return true;\n    }\n    return false;\n  }\n\n  // Notification::WaitForNotification()\n  //\n  // Blocks the calling thread until the notification's \"notified\" state is\n  // `true`. Note that if `Notify()` has been previously called on this\n  // notification, this function will immediately return.\n  void WaitForNotification() const;\n\n  // Notification::WaitForNotificationWithTimeout()\n  //\n  // Blocks until either the notification's \"notified\" state is `true` (which\n  // may occur immediately) or the timeout has elapsed, returning the value of\n  // its \"notified\" state in either case.\n  bool WaitForNotificationWithTimeout(absl::Duration timeout) const;\n\n  // Notification::WaitForNotificationWithDeadline()\n  //\n  // Blocks until either the notification's \"notified\" state is `true` (which\n  // may occur immediately) or the deadline has expired, returning the value of\n  // its \"notified\" state in either case.\n  bool WaitForNotificationWithDeadline(absl::Time deadline) const;\n\n  // Notification::Notify()\n  //\n  // Sets the \"notified\" state of this notification to `true` and wakes waiting\n  // threads. Note: do not call `Notify()` multiple times on the same\n  // `Notification`; calling `Notify()` more than once on the same notification\n  // results in undefined behavior.\n  void Notify();\n\n private:\n  // Convenience helper to reduce verbosity at call sites.\n  static inline constexpr base_internal::ObjectKind TraceObjectKind() {\n    return base_internal::ObjectKind::kNotification;\n  }\n\n  static inline bool HasBeenNotifiedInternal(\n      const std::atomic<bool>* notified_yet) {\n    return notified_yet->load(std::memory_order_acquire);\n  }\n\n  mutable Mutex mutex_;\n  std::atomic<bool> notified_yet_;  // written under mutex_\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_SYNCHRONIZATION_NOTIFICATION_H_\n"
  },
  {
    "path": "absl/synchronization/notification_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/synchronization/notification.h\"\n\n#include <thread>  // NOLINT(build/c++11)\n#include <tuple>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/tracing.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// A thread-safe class that holds a counter.\nclass ThreadSafeCounter {\n public:\n  ThreadSafeCounter() : count_(0) {}\n\n  void Increment() {\n    MutexLock lock(mutex_);\n    ++count_;\n  }\n\n  int Get() const {\n    MutexLock lock(mutex_);\n    return count_;\n  }\n\n  void WaitUntilGreaterOrEqual(int n) {\n    MutexLock lock(mutex_);\n    auto cond = [this, n]() { return count_ >= n; };\n    mutex_.Await(Condition(&cond));\n  }\n\n private:\n  mutable Mutex mutex_;\n  int count_;\n};\n\n// Runs the |i|'th worker thread for the tests in BasicTests().  Increments the\n// |ready_counter|, waits on the |notification|, and then increments the\n// |done_counter|.\nstatic void RunWorker(int i, ThreadSafeCounter* ready_counter,\n                      Notification* notification,\n                      ThreadSafeCounter* done_counter) {\n  ready_counter->Increment();\n  notification->WaitForNotification();\n  done_counter->Increment();\n}\n\n// Tests that the |notification| properly blocks and awakens threads.  Assumes\n// that the |notification| is not yet triggered.  If |notify_before_waiting| is\n// true, the |notification| is triggered before any threads are created, so the\n// threads never block in WaitForNotification().  Otherwise, the |notification|\n// is triggered at a later point when most threads are likely to be blocking in\n// WaitForNotification().\nstatic void BasicTests(bool notify_before_waiting, Notification* notification) {\n  EXPECT_FALSE(notification->HasBeenNotified());\n  EXPECT_FALSE(\n      notification->WaitForNotificationWithTimeout(absl::Milliseconds(0)));\n  EXPECT_FALSE(notification->WaitForNotificationWithDeadline(absl::Now()));\n\n  const absl::Duration delay = absl::Milliseconds(50);\n  const absl::Time start = absl::Now();\n  EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));\n  const absl::Duration elapsed = absl::Now() - start;\n\n  // Allow for a slight early return, to account for quality of implementation\n  // issues on various platforms.\n  absl::Duration slop = absl::Milliseconds(5);\n#ifdef _MSC_VER\n  // Avoid flakiness on MSVC.\n  slop = absl::Milliseconds(15);\n#endif\n  EXPECT_LE(delay - slop, elapsed)\n      << \"WaitForNotificationWithTimeout returned \" << delay - elapsed\n      << \" early (with \" << slop << \" slop), start time was \" << start;\n\n  ThreadSafeCounter ready_counter;\n  ThreadSafeCounter done_counter;\n\n  if (notify_before_waiting) {\n    notification->Notify();\n  }\n\n  // Create a bunch of threads that increment the |done_counter| after being\n  // notified.\n  const int kNumThreads = 10;\n  std::vector<std::thread> workers;\n  for (int i = 0; i < kNumThreads; ++i) {\n    workers.push_back(std::thread(&RunWorker, i, &ready_counter, notification,\n                                  &done_counter));\n  }\n\n  if (!notify_before_waiting) {\n    ready_counter.WaitUntilGreaterOrEqual(kNumThreads);\n\n    // Workers have not been notified yet, so the |done_counter| should be\n    // unmodified.\n    EXPECT_EQ(0, done_counter.Get());\n\n    notification->Notify();\n  }\n\n  // After notifying and then joining the workers, both counters should be\n  // fully incremented.\n  notification->WaitForNotification();  // should exit immediately\n  EXPECT_TRUE(notification->HasBeenNotified());\n  EXPECT_TRUE(notification->WaitForNotificationWithTimeout(absl::Seconds(0)));\n  EXPECT_TRUE(notification->WaitForNotificationWithDeadline(absl::Now()));\n  for (std::thread& worker : workers) {\n    worker.join();\n  }\n  EXPECT_EQ(kNumThreads, ready_counter.Get());\n  EXPECT_EQ(kNumThreads, done_counter.Get());\n}\n\nTEST(NotificationTest, SanityTest) {\n  Notification local_notification1, local_notification2;\n  BasicTests(false, &local_notification1);\n  BasicTests(true, &local_notification2);\n}\n\n#if ABSL_HAVE_ATTRIBUTE_WEAK\n\nnamespace base_internal {\n\nnamespace {\n\nusing TraceRecord = std::tuple<const void*, ObjectKind>;\n\nthread_local TraceRecord tls_signal;\nthread_local TraceRecord tls_wait;\nthread_local TraceRecord tls_continue;\nthread_local TraceRecord tls_observed;\n\n}  // namespace\n\n// Strong extern \"C\" implementation.\nextern \"C\" {\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,\n                                                   ObjectKind kind) {\n  tls_wait = {object, kind};\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,\n                                                       ObjectKind kind) {\n  tls_continue = {object, kind};\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,\n                                                     ObjectKind kind) {\n  tls_signal = {object, kind};\n}\n\nvoid ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,\n                                                       ObjectKind kind) {\n  tls_observed = {object, kind};\n}\n\n}  // extern \"C\"\n\nTEST(NotificationTest, TracesNotify) {\n  Notification n;\n  tls_signal = {};\n  n.Notify();\n  EXPECT_EQ(tls_signal, TraceRecord(&n, ObjectKind::kNotification));\n}\n\nTEST(NotificationTest, TracesWaitForNotification) {\n  Notification n;\n  n.Notify();\n  tls_wait = tls_continue = {};\n  n.WaitForNotification();\n  EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));\n  EXPECT_EQ(tls_continue, TraceRecord(&n, ObjectKind::kNotification));\n}\n\nTEST(NotificationTest, TracesWaitForNotificationWithTimeout) {\n  Notification n;\n\n  tls_wait = tls_continue = {};\n  n.WaitForNotificationWithTimeout(absl::Milliseconds(1));\n  EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));\n  EXPECT_EQ(tls_continue, TraceRecord(nullptr, ObjectKind::kNotification));\n\n  n.Notify();\n  tls_wait = tls_continue = {};\n  n.WaitForNotificationWithTimeout(absl::Milliseconds(1));\n  EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));\n  EXPECT_EQ(tls_continue, TraceRecord(&n, ObjectKind::kNotification));\n}\n\nTEST(NotificationTest, TracesHasBeenNotified) {\n  Notification n;\n\n  tls_observed = {};\n  ASSERT_FALSE(n.HasBeenNotified());\n  EXPECT_EQ(tls_observed, TraceRecord(nullptr, ObjectKind::kUnknown));\n\n  n.Notify();\n  tls_observed = {};\n  ASSERT_TRUE(n.HasBeenNotified());\n  EXPECT_EQ(tls_observed, TraceRecord(&n, ObjectKind::kNotification));\n}\n\n}  // namespace base_internal\n\n#endif  // ABSL_HAVE_ATTRIBUTE_WEAK\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"time\",\n    srcs = [\n        \"civil_time.cc\",\n        \"clock.cc\",\n        \"duration.cc\",\n        \"format.cc\",\n        \"internal/get_current_time_chrono.inc\",\n        \"internal/get_current_time_posix.inc\",\n        \"time.cc\",\n    ],\n    hdrs = [\n        \"civil_time.h\",\n        \"clock.h\",\n        \"time.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/numeric:int128\",\n        \"//absl/strings\",\n        \"//absl/strings:string_view\",\n        \"//absl/time/internal/cctz:civil_time\",\n        \"//absl/time/internal/cctz:time_zone\",\n        \"//absl/types:optional\",\n    ],\n)\n\ncc_library(\n    name = \"clock_interface\",\n    srcs = [\n        \"clock_interface.cc\",\n    ],\n    hdrs = [\n        \"clock_interface.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":time\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:no_destructor\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"simulated_clock\",\n    testonly = True,\n    srcs = [\n        \"simulated_clock.cc\",\n    ],\n    hdrs = [\n        \"simulated_clock.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":clock_interface\",\n        \":time\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/synchronization\",\n    ],\n)\n\ncc_library(\n    name = \"test_util\",\n    testonly = True,\n    srcs = [\"internal/test_util.cc\"],\n    hdrs = [\"internal/test_util.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":time\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n    ],\n)\n\ncc_test(\n    name = \"time_test\",\n    srcs = [\n        \"civil_time_test.cc\",\n        \"clock_test.cc\",\n        \"duration_test.cc\",\n        \"format_test.cc\",\n        \"time_test.cc\",\n        \"time_zone_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    data = [\"//absl/time/internal/cctz:zoneinfo\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":test_util\",\n        \":time\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/numeric:int128\",\n        \"//absl/random\",\n        \"//absl/strings:str_format\",\n        \"//absl/time/internal/cctz:time_zone\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"clock_interface_test\",\n    srcs = [\n        \"clock_interface_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":clock_interface\",\n        \":time\",\n        \"//absl/functional:bind_front\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"simulated_clock_test\",\n    srcs = [\n        \"simulated_clock_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":clock_interface\",\n        \":simulated_clock\",\n        \":time\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/functional:bind_front\",\n        \"//absl/random\",\n        \"//absl/synchronization\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"flag_test\",\n    srcs = [\n        \"flag_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_android_arm\",\n        \"no_test_android_arm64\",\n        \"no_test_android_x86\",\n        \"no_test_ios_sim_arm64\",\n        \"no_test_ios_x86_64\",\n        \"no_test_lexan\",\n        \"no_test_loonix\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":time\",\n        \"//absl/flags:flag\",\n        \"//absl/flags:reflection\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"time_benchmark\",\n    testonly = True,\n    srcs = [\n        \"civil_time_benchmark.cc\",\n        \"clock_benchmark.cc\",\n        \"duration_benchmark.cc\",\n        \"format_benchmark.cc\",\n        \"time_benchmark.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    data = [\"//absl/time/internal/cctz:zoneinfo\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"benchmark\",\n    ],\n    deps = [\n        \":test_util\",\n        \":time\",\n        \"//absl/base\",\n        \"//absl/base:core_headers\",\n        \"//absl/flags:flag\",\n        \"//absl/hash\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/time/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    time\n  HDRS\n    \"civil_time.h\"\n    \"clock.h\"\n    \"time.h\"\n  SRCS\n    \"civil_time.cc\"\n    \"clock.cc\"\n    \"duration.cc\"\n    \"format.cc\"\n    \"internal/get_current_time_chrono.inc\"\n    \"internal/get_current_time_posix.inc\"\n    \"time.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::base\n    absl::civil_time\n    absl::core_headers\n    absl::int128\n    absl::raw_logging_internal\n    absl::strings\n    absl::time_zone\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    civil_time\n  HDRS\n    \"internal/cctz/include/cctz/civil_time.h\"\n    \"internal/cctz/include/cctz/civil_time_detail.h\"\n  SRCS\n    \"internal/cctz/src/civil_time_detail.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n)\n\nabsl_cc_library(\n  NAME\n    time_zone\n  HDRS\n    \"internal/cctz/include/cctz/time_zone.h\"\n    \"internal/cctz/include/cctz/zone_info_source.h\"\n  SRCS\n    \"internal/cctz/src/time_zone_fixed.cc\"\n    \"internal/cctz/src/time_zone_fixed.h\"\n    \"internal/cctz/src/time_zone_format.cc\"\n    \"internal/cctz/src/time_zone_if.cc\"\n    \"internal/cctz/src/time_zone_if.h\"\n    \"internal/cctz/src/time_zone_impl.cc\"\n    \"internal/cctz/src/time_zone_impl.h\"\n    \"internal/cctz/src/time_zone_info.cc\"\n    \"internal/cctz/src/time_zone_info.h\"\n    \"internal/cctz/src/time_zone_libc.cc\"\n    \"internal/cctz/src/time_zone_libc.h\"\n    \"internal/cctz/src/time_zone_lookup.cc\"\n    \"internal/cctz/src/time_zone_posix.cc\"\n    \"internal/cctz/src/time_zone_posix.h\"\n    \"internal/cctz/src/tzfile.h\"\n    \"internal/cctz/src/zone_info_source.cc\"\n    $<$<PLATFORM_ID:Windows>:internal/cctz/src/time_zone_name_win.cc>\n    $<$<PLATFORM_ID:Windows>:internal/cctz/src/time_zone_name_win.h>\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    Threads::Threads\n    # TODO(#1495): Use $<LINK_LIBRARY:FRAMEWORK,CoreFoundation> once our\n    # minimum CMake version >= 3.24\n    $<$<PLATFORM_ID:Darwin,iOS,tvOS,visionOS,watchOS>:-Wl,-framework,CoreFoundation>\n)\n\n# Internal-only target, do not depend on directly.\nabsl_cc_library(\n  NAME\n    time_internal_test_util\n  HDRS\n    \"internal/test_util.h\"\n  SRCS\n    \"internal/test_util.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::time\n    absl::config\n    absl::raw_logging_internal\n    absl::time_zone\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    time_test\n  SRCS\n    \"civil_time_test.cc\"\n    \"clock_test.cc\"\n    \"duration_test.cc\"\n    \"format_test.cc\"\n    \"time_test.cc\"\n    \"time_zone_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::time_internal_test_util\n    absl::time\n    absl::config\n    absl::core_headers\n    absl::hash_testing\n    absl::random_random\n    absl::strings\n    absl::str_format\n    absl::time_zone\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    clock_interface\n  HDRS\n    \"clock_interface.h\"\n  SRCS\n    \"clock_interface.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::time\n    absl::config\n    absl::core_headers\n    absl::no_destructor\n    absl::nullability\n    absl::raw_logging_internal\n    absl::synchronization\n)\n\nabsl_cc_test(\n  NAME\n    clock_interface_test\n  SRCS\n    \"clock_interface_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::clock_interface\n    absl::time\n    absl::config\n    absl::bind_front\n    absl::synchronization\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    simulated_clock\n  HDRS\n    \"simulated_clock.h\"\n  SRCS\n    \"simulated_clock.cc\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::clock_interface\n    absl::time\n    absl::config\n    absl::core_headers\n    absl::nullability\n    absl::synchronization\n  TESTONLY\n)\n\nabsl_cc_test(\n  NAME\n    simulated_clock_test\n  SRCS\n    \"simulated_clock_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::clock_interface\n    absl::simulated_clock\n    absl::time\n    absl::config\n    absl::bind_front\n    absl::random_random\n    absl::raw_logging_internal\n    absl::synchronization\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    flag_test\n  SRCS\n    \"flag_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::flags\n    absl::flags_reflection\n    GTest::gmock_main\n)\n"
  },
  {
    "path": "absl/time/civil_time.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/civil_time.h\"\n\n#include <cerrno>\n#include <cstdlib>\n#include <ostream>\n#include <string>\n\n#include \"absl/strings/str_cat.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\n// Since a civil time has a larger year range than absl::Time (64-bit years vs\n// 64-bit seconds, respectively) we normalize years to roughly +/- 400 years\n// around the year 2400, which will produce an equivalent year in a range that\n// absl::Time can handle.\ninline civil_year_t NormalizeYear(civil_year_t year) {\n  return 2400 + year % 400;\n}\n\n// Formats the given CivilSecond according to the given format.\nstd::string FormatYearAnd(string_view fmt, CivilSecond cs) {\n  const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(),\n                        cs.hour(), cs.minute(), cs.second());\n  const TimeZone utc = UTCTimeZone();\n  return StrCat(cs.year(), FormatTime(fmt, FromCivil(ncs, utc), utc));\n}\n\ntemplate <typename CivilT>\nbool ParseYearAnd(string_view fmt, string_view s, CivilT* c) {\n  // Civil times support a larger year range than absl::Time, so we need to\n  // parse the year separately, normalize it, then use absl::ParseTime on the\n  // normalized string.\n  const std::string ss = std::string(s);  // TODO(absl-team): Avoid conversion.\n  const char* const np = ss.c_str();\n  char* endp;\n  errno = 0;\n  const civil_year_t y =\n      std::strtoll(np, &endp, 10);  // NOLINT(runtime/deprecated_fn)\n  if (endp == np || errno == ERANGE) return false;\n  const std::string norm = StrCat(NormalizeYear(y), endp);\n\n  const TimeZone utc = UTCTimeZone();\n  Time t;\n  if (ParseTime(StrCat(\"%Y\", fmt), norm, utc, &t, nullptr)) {\n    const auto cs = ToCivilSecond(t, utc);\n    *c = CivilT(y, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second());\n    return true;\n  }\n\n  return false;\n}\n\n// Tries to parse the type as a CivilT1, but then assigns the result to the\n// argument of type CivilT2.\ntemplate <typename CivilT1, typename CivilT2>\nbool ParseAs(string_view s, CivilT2* c) {\n  CivilT1 t1;\n  if (ParseCivilTime(s, &t1)) {\n    *c = CivilT2(t1);\n    return true;\n  }\n  return false;\n}\n\ntemplate <typename CivilT>\nbool ParseLenient(string_view s, CivilT* c) {\n  // A fastpath for when the given string data parses exactly into the given\n  // type T (e.g., s=\"YYYY-MM-DD\" and CivilT=CivilDay).\n  if (ParseCivilTime(s, c)) return true;\n  // Try parsing as each of the 6 types, trying the most common types first\n  // (based on csearch results).\n  if (ParseAs<CivilDay>(s, c)) return true;\n  if (ParseAs<CivilSecond>(s, c)) return true;\n  if (ParseAs<CivilHour>(s, c)) return true;\n  if (ParseAs<CivilMonth>(s, c)) return true;\n  if (ParseAs<CivilMinute>(s, c)) return true;\n  if (ParseAs<CivilYear>(s, c)) return true;\n  return false;\n}\n}  // namespace\n\nstd::string FormatCivilTime(CivilSecond c) {\n  return FormatYearAnd(\"-%m-%d%ET%H:%M:%S\", c);\n}\nstd::string FormatCivilTime(CivilMinute c) {\n  return FormatYearAnd(\"-%m-%d%ET%H:%M\", c);\n}\nstd::string FormatCivilTime(CivilHour c) {\n  return FormatYearAnd(\"-%m-%d%ET%H\", c);\n}\nstd::string FormatCivilTime(CivilDay c) { return FormatYearAnd(\"-%m-%d\", c); }\nstd::string FormatCivilTime(CivilMonth c) { return FormatYearAnd(\"-%m\", c); }\nstd::string FormatCivilTime(CivilYear c) { return FormatYearAnd(\"\", c); }\n\nbool ParseCivilTime(string_view s, CivilSecond* c) {\n  return ParseYearAnd(\"-%m-%d%ET%H:%M:%S\", s, c);\n}\nbool ParseCivilTime(string_view s, CivilMinute* c) {\n  return ParseYearAnd(\"-%m-%d%ET%H:%M\", s, c);\n}\nbool ParseCivilTime(string_view s, CivilHour* c) {\n  return ParseYearAnd(\"-%m-%d%ET%H\", s, c);\n}\nbool ParseCivilTime(string_view s, CivilDay* c) {\n  return ParseYearAnd(\"-%m-%d\", s, c);\n}\nbool ParseCivilTime(string_view s, CivilMonth* c) {\n  return ParseYearAnd(\"-%m\", s, c);\n}\nbool ParseCivilTime(string_view s, CivilYear* c) {\n  return ParseYearAnd(\"\", s, c);\n}\n\nbool ParseLenientCivilTime(string_view s, CivilSecond* c) {\n  return ParseLenient(s, c);\n}\nbool ParseLenientCivilTime(string_view s, CivilMinute* c) {\n  return ParseLenient(s, c);\n}\nbool ParseLenientCivilTime(string_view s, CivilHour* c) {\n  return ParseLenient(s, c);\n}\nbool ParseLenientCivilTime(string_view s, CivilDay* c) {\n  return ParseLenient(s, c);\n}\nbool ParseLenientCivilTime(string_view s, CivilMonth* c) {\n  return ParseLenient(s, c);\n}\nbool ParseLenientCivilTime(string_view s, CivilYear* c) {\n  return ParseLenient(s, c);\n}\n\nnamespace time_internal {\n\nstd::ostream& operator<<(std::ostream& os, CivilYear y) {\n  return os << FormatCivilTime(y);\n}\nstd::ostream& operator<<(std::ostream& os, CivilMonth m) {\n  return os << FormatCivilTime(m);\n}\nstd::ostream& operator<<(std::ostream& os, CivilDay d) {\n  return os << FormatCivilTime(d);\n}\nstd::ostream& operator<<(std::ostream& os, CivilHour h) {\n  return os << FormatCivilTime(h);\n}\nstd::ostream& operator<<(std::ostream& os, CivilMinute m) {\n  return os << FormatCivilTime(m);\n}\nstd::ostream& operator<<(std::ostream& os, CivilSecond s) {\n  return os << FormatCivilTime(s);\n}\n\nbool AbslParseFlag(string_view s, CivilSecond* c, std::string*) {\n  return ParseLenientCivilTime(s, c);\n}\nbool AbslParseFlag(string_view s, CivilMinute* c, std::string*) {\n  return ParseLenientCivilTime(s, c);\n}\nbool AbslParseFlag(string_view s, CivilHour* c, std::string*) {\n  return ParseLenientCivilTime(s, c);\n}\nbool AbslParseFlag(string_view s, CivilDay* c, std::string*) {\n  return ParseLenientCivilTime(s, c);\n}\nbool AbslParseFlag(string_view s, CivilMonth* c, std::string*) {\n  return ParseLenientCivilTime(s, c);\n}\nbool AbslParseFlag(string_view s, CivilYear* c, std::string*) {\n  return ParseLenientCivilTime(s, c);\n}\nstd::string AbslUnparseFlag(CivilSecond c) { return FormatCivilTime(c); }\nstd::string AbslUnparseFlag(CivilMinute c) { return FormatCivilTime(c); }\nstd::string AbslUnparseFlag(CivilHour c) { return FormatCivilTime(c); }\nstd::string AbslUnparseFlag(CivilDay c) { return FormatCivilTime(c); }\nstd::string AbslUnparseFlag(CivilMonth c) { return FormatCivilTime(c); }\nstd::string AbslUnparseFlag(CivilYear c) { return FormatCivilTime(c); }\n\n}  // namespace time_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/civil_time.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: civil_time.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines abstractions for computing with \"civil time\".\n// The term \"civil time\" refers to the legally recognized human-scale time\n// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A \"date\"\n// is perhaps the most common example of a civil time (represented here as\n// an `absl::CivilDay`).\n//\n// Modern-day civil time follows the Gregorian Calendar and is a\n// time-zone-independent concept: a civil time of \"2015-06-01 12:00:00\", for\n// example, is not tied to a time zone. Put another way, a civil time does not\n// map to a unique point in time; a civil time must be mapped to an absolute\n// time *through* a time zone.\n//\n// Because a civil time is what most people think of as \"time,\" it is common to\n// map absolute times to civil times to present to users.\n//\n// Time zones define the relationship between absolute and civil times. Given an\n// absolute or civil time and a time zone, you can compute the other time:\n//\n//   Civil Time = F(Absolute Time, Time Zone)\n//   Absolute Time = G(Civil Time, Time Zone)\n//\n// The Abseil time library allows you to construct such civil times from\n// absolute times; consult time.h for such functionality.\n//\n// This library provides six classes for constructing civil-time objects, and\n// provides several helper functions for rounding, iterating, and performing\n// arithmetic on civil-time objects, while avoiding complications like\n// daylight-saving time (DST):\n//\n//   * `absl::CivilSecond`\n//   * `absl::CivilMinute`\n//   * `absl::CivilHour`\n//   * `absl::CivilDay`\n//   * `absl::CivilMonth`\n//   * `absl::CivilYear`\n//\n// Example:\n//\n//   // Construct a civil-time object for a specific day\n//   const absl::CivilDay cd(1969, 7, 20);\n//\n//   // Construct a civil-time object for a specific second\n//   const absl::CivilSecond cd(2018, 8, 1, 12, 0, 1);\n//\n// Note: In C++14 and later, this library is usable in a constexpr context.\n//\n// Example:\n//\n//   // Valid in C++14\n//   constexpr absl::CivilDay cd(1969, 7, 20);\n\n#ifndef ABSL_TIME_CIVIL_TIME_H_\n#define ABSL_TIME_CIVIL_TIME_H_\n\n#include <iosfwd>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace time_internal {\nstruct second_tag : cctz::detail::second_tag {};\nstruct minute_tag : second_tag, cctz::detail::minute_tag {};\nstruct hour_tag : minute_tag, cctz::detail::hour_tag {};\nstruct day_tag : hour_tag, cctz::detail::day_tag {};\nstruct month_tag : day_tag, cctz::detail::month_tag {};\nstruct year_tag : month_tag, cctz::detail::year_tag {};\n}  // namespace time_internal\n\n// -----------------------------------------------------------------------------\n// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear\n// -----------------------------------------------------------------------------\n//\n// Each of these civil-time types is a simple value type with the same\n// interface for construction and the same six accessors for each of the civil\n// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These\n// classes differ only in their alignment, which is indicated by the type name\n// and specifies the field on which arithmetic operates.\n//\n// CONSTRUCTION\n//\n// Each of the civil-time types can be constructed in two ways: by directly\n// passing to the constructor up to six integers representing the YMDHMS fields,\n// or by copying the YMDHMS fields from a differently aligned civil-time type.\n// Omitted fields are assigned their minimum valid value. Hours, minutes, and\n// seconds will be set to 0, month and day will be set to 1. Since there is no\n// minimum year, the default is 1970.\n//\n// Examples:\n//\n//   absl::CivilDay default_value;               // 1970-01-01 00:00:00\n//\n//   absl::CivilDay a(2015, 2, 3);               // 2015-02-03 00:00:00\n//   absl::CivilDay b(2015, 2, 3, 4, 5, 6);      // 2015-02-03 00:00:00\n//   absl::CivilDay c(2015);                     // 2015-01-01 00:00:00\n//\n//   absl::CivilSecond ss(2015, 2, 3, 4, 5, 6);  // 2015-02-03 04:05:06\n//   absl::CivilMinute mm(ss);                   // 2015-02-03 04:05:00\n//   absl::CivilHour hh(mm);                     // 2015-02-03 04:00:00\n//   absl::CivilDay d(hh);                       // 2015-02-03 00:00:00\n//   absl::CivilMonth m(d);                      // 2015-02-01 00:00:00\n//   absl::CivilYear y(m);                       // 2015-01-01 00:00:00\n//\n//   m = absl::CivilMonth(y);                    // 2015-01-01 00:00:00\n//   d = absl::CivilDay(m);                      // 2015-01-01 00:00:00\n//   hh = absl::CivilHour(d);                    // 2015-01-01 00:00:00\n//   mm = absl::CivilMinute(hh);                 // 2015-01-01 00:00:00\n//   ss = absl::CivilSecond(mm);                 // 2015-01-01 00:00:00\n//\n// Each civil-time class is aligned to the civil-time field indicated in the\n// class's name after normalization. Alignment is performed by setting all the\n// inferior fields to their minimum valid value (as described above). The\n// following are examples of how each of the six types would align the fields\n// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the\n// string format used here is not important; it's just a shorthand way of\n// showing the six YMDHMS fields.)\n//\n//   absl::CivilSecond   : 2015-11-22 12:34:56\n//   absl::CivilMinute   : 2015-11-22 12:34:00\n//   absl::CivilHour     : 2015-11-22 12:00:00\n//   absl::CivilDay      : 2015-11-22 00:00:00\n//   absl::CivilMonth    : 2015-11-01 00:00:00\n//   absl::CivilYear     : 2015-01-01 00:00:00\n//\n// Each civil-time type performs arithmetic on the field to which it is\n// aligned. This means that adding 1 to an absl::CivilDay increments the day\n// field (normalizing as necessary), and subtracting 7 from an absl::CivilMonth\n// operates on the month field (normalizing as necessary). All arithmetic\n// produces a valid civil time. Difference requires two similarly aligned\n// civil-time objects and returns the scalar answer in units of the objects'\n// alignment. For example, the difference between two absl::CivilHour objects\n// will give an answer in units of civil hours.\n//\n// ALIGNMENT CONVERSION\n//\n// The alignment of a civil-time object cannot change, but the object may be\n// used to construct a new object with a different alignment. This is referred\n// to as \"realigning\". When realigning to a type with the same or more\n// precision (e.g., absl::CivilDay -> absl::CivilSecond), the conversion may be\n// performed implicitly since no information is lost. However, if information\n// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must\n// be explicit at the call site.\n//\n// Examples:\n//\n//   void UseDay(absl::CivilDay day);\n//\n//   absl::CivilSecond cs;\n//   UseDay(cs);                  // Won't compile because data may be discarded\n//   UseDay(absl::CivilDay(cs));  // OK: explicit conversion\n//\n//   absl::CivilDay cd;\n//   UseDay(cd);                  // OK: no conversion needed\n//\n//   absl::CivilMonth cm;\n//   UseDay(cm);                  // OK: implicit conversion to absl::CivilDay\n//\n// NORMALIZATION\n//\n// Normalization takes invalid values and adjusts them to produce valid values.\n// Within the civil-time library, integer arguments passed to the Civil*\n// constructors may be out-of-range, in which case they are normalized by\n// carrying overflow into a field of courser granularity to produce valid\n// civil-time objects. This normalization enables natural arithmetic on\n// constructor arguments without worrying about the field's range.\n//\n// Examples:\n//\n//   // Out-of-range; normalized to 2016-11-01\n//   absl::CivilDay d(2016, 10, 32);\n//   // Out-of-range, negative: normalized to 2016-10-30T23\n//   absl::CivilHour h1(2016, 10, 31, -1);\n//   // Normalization is cumulative: normalized to 2016-10-30T23\n//   absl::CivilHour h2(2016, 10, 32, -25);\n//\n// Note: If normalization is undesired, you can signal an error by comparing\n// the constructor arguments to the normalized values returned by the YMDHMS\n// properties.\n//\n// COMPARISON\n//\n// Comparison between civil-time objects considers all six YMDHMS fields,\n// regardless of the type's alignment. Comparison between differently aligned\n// civil-time types is allowed.\n//\n// Examples:\n//\n//   absl::CivilDay feb_3(2015, 2, 3);  // 2015-02-03 00:00:00\n//   absl::CivilDay mar_4(2015, 3, 4);  // 2015-03-04 00:00:00\n//   // feb_3 < mar_4\n//   // absl::CivilYear(feb_3) == absl::CivilYear(mar_4)\n//\n//   absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0);  // 2015-02-03 12:00:00\n//   // feb_3 < feb_3_noon\n//   // feb_3 == absl::CivilDay(feb_3_noon)\n//\n//   // Iterates all the days of February 2015.\n//   for (absl::CivilDay d(2015, 2, 1); d < absl::CivilMonth(2015, 3); ++d) {\n//     // ...\n//   }\n//\n// ARITHMETIC\n//\n// Civil-time types support natural arithmetic operators such as addition,\n// subtraction, and difference. Arithmetic operates on the civil-time field\n// indicated in the type's name. Difference operators require arguments with\n// the same alignment and return the answer in units of the alignment.\n//\n// Example:\n//\n//   absl::CivilDay a(2015, 2, 3);\n//   ++a;                              // 2015-02-04 00:00:00\n//   --a;                              // 2015-02-03 00:00:00\n//   absl::CivilDay b = a + 1;         // 2015-02-04 00:00:00\n//   absl::CivilDay c = 1 + b;         // 2015-02-05 00:00:00\n//   int n = c - a;                    // n = 2 (civil days)\n//   int m = c - absl::CivilMonth(c);  // Won't compile: different types.\n//\n// ACCESSORS\n//\n// Each civil-time type has accessors for all six of the civil-time fields:\n// year, month, day, hour, minute, and second.\n//\n// civil_year_t year()\n// int          month()\n// int          day()\n// int          hour()\n// int          minute()\n// int          second()\n//\n// Recall that fields inferior to the type's alignment will be set to their\n// minimum valid value.\n//\n// Example:\n//\n//   absl::CivilDay d(2015, 6, 28);\n//   // d.year() == 2015\n//   // d.month() == 6\n//   // d.day() == 28\n//   // d.hour() == 0\n//   // d.minute() == 0\n//   // d.second() == 0\n//\n// CASE STUDY: Adding a month to January 31.\n//\n// One of the classic questions that arises when considering a civil time\n// library (or a date library or a date/time library) is this:\n//   \"What is the result of adding a month to January 31?\"\n// This is an interesting question because it is unclear what is meant by a\n// \"month\", and several different answers are possible, depending on context:\n//\n//   1. March 3 (or 2 if a leap year), if \"add a month\" means to add a month to\n//      the current month, and adjust the date to overflow the extra days into\n//      March. In this case the result of \"February 31\" would be normalized as\n//      within the civil-time library.\n//   2. February 28 (or 29 if a leap year), if \"add a month\" means to add a\n//      month, and adjust the date while holding the resulting month constant.\n//      In this case, the result of \"February 31\" would be truncated to the last\n//      day in February.\n//   3. An error. The caller may get some error, an exception, an invalid date\n//      object, or perhaps return `false`. This may make sense because there is\n//      no single unambiguously correct answer to the question.\n//\n// Practically speaking, any answer that is not what the programmer intended\n// is the wrong answer.\n//\n// The Abseil time library avoids this problem by making it impossible to\n// ask ambiguous questions. All civil-time objects are aligned to a particular\n// civil-field boundary (such as aligned to a year, month, day, hour, minute,\n// or second), and arithmetic operates on the field to which the object is\n// aligned. This means that in order to \"add a month\" the object must first be\n// aligned to a month boundary, which is equivalent to the first day of that\n// month.\n//\n// Of course, there are ways to compute an answer the question at hand using\n// this Abseil time library, but they require the programmer to be explicit\n// about the answer they expect. To illustrate, let's see how to compute all\n// three of the above possible answers to the question of \"Jan 31 plus 1\n// month\":\n//\n// Example:\n//\n//   const absl::CivilDay d(2015, 1, 31);\n//\n//   // Answer 1:\n//   // Add 1 to the month field in the constructor, and rely on normalization.\n//   const auto normalized = absl::CivilDay(d.year(), d.month() + 1, d.day());\n//   // normalized == 2015-03-03 (aka Feb 31)\n//\n//   // Answer 2:\n//   // Add 1 to month field, capping to the end of next month.\n//   const auto next_month = absl::CivilMonth(d) + 1;\n//   const auto last_day_of_next_month = absl::CivilDay(next_month + 1) - 1;\n//   const auto capped = std::min(normalized, last_day_of_next_month);\n//   // capped == 2015-02-28\n//\n//   // Answer 3:\n//   // Signal an error if the normalized answer is not in next month.\n//   if (absl::CivilMonth(normalized) != next_month) {\n//     // error, month overflow\n//   }\n//\nusing CivilSecond =\n    time_internal::cctz::detail::civil_time<time_internal::second_tag>;\nusing CivilMinute =\n    time_internal::cctz::detail::civil_time<time_internal::minute_tag>;\nusing CivilHour =\n    time_internal::cctz::detail::civil_time<time_internal::hour_tag>;\nusing CivilDay =\n    time_internal::cctz::detail::civil_time<time_internal::day_tag>;\nusing CivilMonth =\n    time_internal::cctz::detail::civil_time<time_internal::month_tag>;\nusing CivilYear =\n    time_internal::cctz::detail::civil_time<time_internal::year_tag>;\n\n// civil_year_t\n//\n// Type alias of a civil-time year value. This type is guaranteed to (at least)\n// support any year value supported by `time_t`.\n//\n// Example:\n//\n//   absl::CivilSecond cs = ...;\n//   absl::civil_year_t y = cs.year();\n//   cs = absl::CivilSecond(y, 1, 1, 0, 0, 0);  // CivilSecond(CivilYear(cs))\n//\nusing civil_year_t = time_internal::cctz::year_t;\n\n// civil_diff_t\n//\n// Type alias of the difference between two civil-time values.\n// This type is used to indicate arguments that are not\n// normalized (such as parameters to the civil-time constructors), the results\n// of civil-time subtraction, or the operand to civil-time addition.\n//\n// Example:\n//\n//   absl::civil_diff_t n_sec = cs1 - cs2;             // cs1 == cs2 + n_sec;\n//\nusing civil_diff_t = time_internal::cctz::diff_t;\n\n// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday,\n// Weekday::friday, Weekday::saturday, Weekday::sunday\n//\n// The Weekday enum class represents the civil-time concept of a \"weekday\" with\n// members for all days of the week.\n//\n//   absl::Weekday wd = absl::Weekday::thursday;\n//\nusing Weekday = time_internal::cctz::weekday;\n\n// GetWeekday()\n//\n// Returns the absl::Weekday for the given (realigned) civil-time value.\n//\n// Example:\n//\n//   absl::CivilDay a(2015, 8, 13);\n//   absl::Weekday wd = absl::GetWeekday(a);  // wd == absl::Weekday::thursday\n//\ninline Weekday GetWeekday(CivilSecond cs) {\n  return time_internal::cctz::get_weekday(cs);\n}\n\n// NextWeekday()\n// PrevWeekday()\n//\n// Returns the absl::CivilDay that strictly follows or precedes a given\n// absl::CivilDay, and that falls on the given absl::Weekday.\n//\n// Example, given the following month:\n//\n//       August 2015\n//   Su Mo Tu We Th Fr Sa\n//                      1\n//    2  3  4  5  6  7  8\n//    9 10 11 12 13 14 15\n//   16 17 18 19 20 21 22\n//   23 24 25 26 27 28 29\n//   30 31\n//\n//   absl::CivilDay a(2015, 8, 13);\n//   // absl::GetWeekday(a) == absl::Weekday::thursday\n//   absl::CivilDay b = absl::NextWeekday(a, absl::Weekday::thursday);\n//   // b = 2015-08-20\n//   absl::CivilDay c = absl::PrevWeekday(a, absl::Weekday::thursday);\n//   // c = 2015-08-06\n//\n//   absl::CivilDay d = ...\n//   // Gets the following Thursday if d is not already Thursday\n//   absl::CivilDay thurs1 = absl::NextWeekday(d - 1, absl::Weekday::thursday);\n//   // Gets the previous Thursday if d is not already Thursday\n//   absl::CivilDay thurs2 = absl::PrevWeekday(d + 1, absl::Weekday::thursday);\n//\ninline CivilDay NextWeekday(CivilDay cd, Weekday wd) {\n  return CivilDay(time_internal::cctz::next_weekday(cd, wd));\n}\ninline CivilDay PrevWeekday(CivilDay cd, Weekday wd) {\n  return CivilDay(time_internal::cctz::prev_weekday(cd, wd));\n}\n\n// GetYearDay()\n//\n// Returns the day-of-year for the given (realigned) civil-time value.\n//\n// Example:\n//\n//   absl::CivilDay a(2015, 1, 1);\n//   int yd_jan_1 = absl::GetYearDay(a);   // yd_jan_1 = 1\n//   absl::CivilDay b(2015, 12, 31);\n//   int yd_dec_31 = absl::GetYearDay(b);  // yd_dec_31 = 365\n//\ninline int GetYearDay(CivilSecond cs) {\n  return time_internal::cctz::get_yearday(cs);\n}\n\n// FormatCivilTime()\n//\n// Formats the given civil-time value into a string value of the following\n// format:\n//\n//  Type        | Format\n//  ---------------------------------\n//  CivilSecond | YYYY-MM-DDTHH:MM:SS\n//  CivilMinute | YYYY-MM-DDTHH:MM\n//  CivilHour   | YYYY-MM-DDTHH\n//  CivilDay    | YYYY-MM-DD\n//  CivilMonth  | YYYY-MM\n//  CivilYear   | YYYY\n//\n// Example:\n//\n//   absl::CivilDay d = absl::CivilDay(1969, 7, 20);\n//   std::string day_string = absl::FormatCivilTime(d);  // \"1969-07-20\"\n//\nstd::string FormatCivilTime(CivilSecond c);\nstd::string FormatCivilTime(CivilMinute c);\nstd::string FormatCivilTime(CivilHour c);\nstd::string FormatCivilTime(CivilDay c);\nstd::string FormatCivilTime(CivilMonth c);\nstd::string FormatCivilTime(CivilYear c);\n\n// Support for StrFormat(), StrCat(), etc\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CivilSecond c) {\n  sink.Append(FormatCivilTime(c));\n}\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CivilMinute c) {\n  sink.Append(FormatCivilTime(c));\n}\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CivilHour c) {\n  sink.Append(FormatCivilTime(c));\n}\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CivilDay c) {\n  sink.Append(FormatCivilTime(c));\n}\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CivilMonth c) {\n  sink.Append(FormatCivilTime(c));\n}\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, CivilYear c) {\n  sink.Append(FormatCivilTime(c));\n}\n\n// absl::ParseCivilTime()\n//\n// Parses a civil-time value from the specified `absl::string_view` into the\n// passed output parameter. Returns `true` upon successful parsing.\n//\n// The expected form of the input string is as follows:\n//\n//  Type        | Format\n//  ---------------------------------\n//  CivilSecond | YYYY-MM-DDTHH:MM:SS\n//  CivilMinute | YYYY-MM-DDTHH:MM\n//  CivilHour   | YYYY-MM-DDTHH\n//  CivilDay    | YYYY-MM-DD\n//  CivilMonth  | YYYY-MM\n//  CivilYear   | YYYY\n//\n// Example:\n//\n//   absl::CivilDay d;\n//   bool ok = absl::ParseCivilTime(\"2018-01-02\", &d); // OK\n//\n// Note that parsing will fail if the string's format does not match the\n// expected type exactly. `ParseLenientCivilTime()` below is more lenient.\n//\nbool ParseCivilTime(absl::string_view s, CivilSecond* c);\nbool ParseCivilTime(absl::string_view s, CivilMinute* c);\nbool ParseCivilTime(absl::string_view s, CivilHour* c);\nbool ParseCivilTime(absl::string_view s, CivilDay* c);\nbool ParseCivilTime(absl::string_view s, CivilMonth* c);\nbool ParseCivilTime(absl::string_view s, CivilYear* c);\n\n// ParseLenientCivilTime()\n//\n// Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more\n// lenient if the format of the string does not exactly match the associated\n// type.\n//\n// Example:\n//\n//   absl::CivilDay d;\n//   bool ok = absl::ParseLenientCivilTime(\"1969-07-20\", &d); // OK\n//   ok = absl::ParseLenientCivilTime(\"1969-07-20T10\", &d);   // OK: T10 floored\n//   ok = absl::ParseLenientCivilTime(\"1969-07\", &d);   // OK: day defaults to 1\n//\nbool ParseLenientCivilTime(absl::string_view s, CivilSecond* c);\nbool ParseLenientCivilTime(absl::string_view s, CivilMinute* c);\nbool ParseLenientCivilTime(absl::string_view s, CivilHour* c);\nbool ParseLenientCivilTime(absl::string_view s, CivilDay* c);\nbool ParseLenientCivilTime(absl::string_view s, CivilMonth* c);\nbool ParseLenientCivilTime(absl::string_view s, CivilYear* c);\n\nnamespace time_internal {  // For functions found via ADL on civil-time tags.\n\n// Streaming Operators\n//\n// Each civil-time type may be sent to an output stream using operator<<().\n// The result matches the string produced by `FormatCivilTime()`.\n//\n// Example:\n//\n//   absl::CivilDay d = absl::CivilDay(1969, 7, 20);\n//   std::cout << \"Date is: \" << d << \"\\n\";\n//\nstd::ostream& operator<<(std::ostream& os, CivilYear y);\nstd::ostream& operator<<(std::ostream& os, CivilMonth m);\nstd::ostream& operator<<(std::ostream& os, CivilDay d);\nstd::ostream& operator<<(std::ostream& os, CivilHour h);\nstd::ostream& operator<<(std::ostream& os, CivilMinute m);\nstd::ostream& operator<<(std::ostream& os, CivilSecond s);\n\n// AbslParseFlag()\n//\n// Parses the command-line flag string representation `s` into a civil-time\n// value. Flags must be specified in a format that is valid for\n// `absl::ParseLenientCivilTime()`.\nbool AbslParseFlag(absl::string_view s, CivilSecond* c, std::string* error);\nbool AbslParseFlag(absl::string_view s, CivilMinute* c, std::string* error);\nbool AbslParseFlag(absl::string_view s, CivilHour* c, std::string* error);\nbool AbslParseFlag(absl::string_view s, CivilDay* c, std::string* error);\nbool AbslParseFlag(absl::string_view s, CivilMonth* c, std::string* error);\nbool AbslParseFlag(absl::string_view s, CivilYear* c, std::string* error);\n\n// AbslUnparseFlag()\n//\n// Unparses a civil-time value into a command-line string representation using\n// the format specified by `absl::ParseCivilTime()`.\nstd::string AbslUnparseFlag(CivilSecond c);\nstd::string AbslUnparseFlag(CivilMinute c);\nstd::string AbslUnparseFlag(CivilHour c);\nstd::string AbslUnparseFlag(CivilDay c);\nstd::string AbslUnparseFlag(CivilMonth c);\nstd::string AbslUnparseFlag(CivilYear c);\n\n}  // namespace time_internal\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_CIVIL_TIME_H_\n"
  },
  {
    "path": "absl/time/civil_time_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <numeric>\n#include <string>\n#include <vector>\n\n#include \"absl/hash/hash.h\"\n#include \"absl/time/civil_time.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\n// Run on (12 X 3492 MHz CPUs); 2018-11-05T13:44:29.814239103-08:00\n// CPU: Intel Haswell with HyperThreading (6 cores) dL1:32KB dL2:256KB dL3:15MB\n// Benchmark                 Time(ns)        CPU(ns)     Iterations\n// ----------------------------------------------------------------\n// BM_Difference_Days              14.5           14.5     48531105\n// BM_Step_Days                    12.6           12.6     54876006\n// BM_Format                      587            587        1000000\n// BM_Parse                       692            692        1000000\n// BM_RoundTripFormatParse       1309           1309         532075\n// BM_CivilYearAbslHash             0.710          0.710  976400000\n// BM_CivilMonthAbslHash            1.13           1.13   619500000\n// BM_CivilDayAbslHash              1.70           1.70   426000000\n// BM_CivilHourAbslHash             2.45           2.45   287600000\n// BM_CivilMinuteAbslHash           3.21           3.21   226200000\n// BM_CivilSecondAbslHash           4.10           4.10   171800000\n\nvoid BM_Difference_Days(benchmark::State& state) {\n  const absl::CivilDay c(2014, 8, 22);\n  const absl::CivilDay epoch(1970, 1, 1);\n  while (state.KeepRunning()) {\n    absl::civil_diff_t n = c - epoch;\n    benchmark::DoNotOptimize(n);\n  }\n}\nBENCHMARK(BM_Difference_Days);\n\nvoid BM_Step_Days(benchmark::State& state) {\n  const absl::CivilDay kStart(2014, 8, 22);\n  absl::CivilDay c = kStart;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(++c);\n  }\n}\nBENCHMARK(BM_Step_Days);\n\nvoid BM_Format(benchmark::State& state) {\n  const absl::CivilSecond c(2014, 1, 2, 3, 4, 5);\n  while (state.KeepRunning()) {\n    std::string s = absl::FormatCivilTime(c);\n    benchmark::DoNotOptimize(s);\n  }\n}\nBENCHMARK(BM_Format);\n\nvoid BM_Parse(benchmark::State& state) {\n  const std::string f = \"2014-01-02T03:04:05\";\n  absl::CivilSecond c;\n  while (state.KeepRunning()) {\n    bool b = absl::ParseCivilTime(f, &c);\n    benchmark::DoNotOptimize(b);\n  }\n}\nBENCHMARK(BM_Parse);\n\nvoid BM_RoundTripFormatParse(benchmark::State& state) {\n  const absl::CivilSecond c(2014, 1, 2, 3, 4, 5);\n  absl::CivilSecond out;\n  while (state.KeepRunning()) {\n    bool b = absl::ParseCivilTime(absl::FormatCivilTime(c), &out);\n    benchmark::DoNotOptimize(b);\n  }\n}\nBENCHMARK(BM_RoundTripFormatParse);\n\ntemplate <typename T>\nvoid BM_CivilTimeAbslHash(benchmark::State& state) {\n  const int kSize = 100000;\n  std::vector<T> civil_times(kSize);\n  std::iota(civil_times.begin(), civil_times.end(), T(2018));\n\n  absl::Hash<T> absl_hasher;\n  while (state.KeepRunningBatch(kSize)) {\n    for (const T civil_time : civil_times) {\n      size_t hash = absl_hasher(civil_time);\n      benchmark::DoNotOptimize(hash);\n    }\n  }\n}\nvoid BM_CivilYearAbslHash(benchmark::State& state) {\n  BM_CivilTimeAbslHash<absl::CivilYear>(state);\n}\nvoid BM_CivilMonthAbslHash(benchmark::State& state) {\n  BM_CivilTimeAbslHash<absl::CivilMonth>(state);\n}\nvoid BM_CivilDayAbslHash(benchmark::State& state) {\n  BM_CivilTimeAbslHash<absl::CivilDay>(state);\n}\nvoid BM_CivilHourAbslHash(benchmark::State& state) {\n  BM_CivilTimeAbslHash<absl::CivilHour>(state);\n}\nvoid BM_CivilMinuteAbslHash(benchmark::State& state) {\n  BM_CivilTimeAbslHash<absl::CivilMinute>(state);\n}\nvoid BM_CivilSecondAbslHash(benchmark::State& state) {\n  BM_CivilTimeAbslHash<absl::CivilSecond>(state);\n}\nBENCHMARK(BM_CivilYearAbslHash);\nBENCHMARK(BM_CivilMonthAbslHash);\nBENCHMARK(BM_CivilDayAbslHash);\nBENCHMARK(BM_CivilHourAbslHash);\nBENCHMARK(BM_CivilMinuteAbslHash);\nBENCHMARK(BM_CivilSecondAbslHash);\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/civil_time_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/civil_time.h\"\n\n#include <iomanip>\n#include <limits>\n#include <sstream>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/strings/str_format.h\"\n\nnamespace {\n\nTEST(CivilTime, DefaultConstruction) {\n  absl::CivilSecond ss;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", absl::FormatCivilTime(ss));\n\n  absl::CivilMinute mm;\n  EXPECT_EQ(\"1970-01-01T00:00\", absl::FormatCivilTime(mm));\n\n  absl::CivilHour hh;\n  EXPECT_EQ(\"1970-01-01T00\", absl::FormatCivilTime(hh));\n\n  absl::CivilDay d;\n  EXPECT_EQ(\"1970-01-01\", absl::FormatCivilTime(d));\n\n  absl::CivilMonth m;\n  EXPECT_EQ(\"1970-01\", absl::FormatCivilTime(m));\n\n  absl::CivilYear y;\n  EXPECT_EQ(\"1970\", absl::FormatCivilTime(y));\n}\n\nTEST(CivilTime, StructMember) {\n  struct S {\n    absl::CivilDay day;\n  };\n  S s = {};\n  EXPECT_EQ(absl::CivilDay{}, s.day);\n}\n\nTEST(CivilTime, FieldsConstruction) {\n  EXPECT_EQ(\"2015-01-02T03:04:05\",\n            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02T03:04:00\",\n            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02T03:00:00\",\n            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02T00:00:00\",\n            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01T00:00:00\",\n            absl::FormatCivilTime(absl::CivilSecond(2015, 1)));\n  EXPECT_EQ(\"2015-01-01T00:00:00\",\n            absl::FormatCivilTime(absl::CivilSecond(2015)));\n\n  EXPECT_EQ(\"2015-01-02T03:04\",\n            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02T03:04\",\n            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02T03:00\",\n            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02T00:00\",\n            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01T00:00\",\n            absl::FormatCivilTime(absl::CivilMinute(2015, 1)));\n  EXPECT_EQ(\"2015-01-01T00:00\", absl::FormatCivilTime(absl::CivilMinute(2015)));\n\n  EXPECT_EQ(\"2015-01-02T03\",\n            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02T03\",\n            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02T03\",\n            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02T00\",\n            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01T00\", absl::FormatCivilTime(absl::CivilHour(2015, 1)));\n  EXPECT_EQ(\"2015-01-01T00\", absl::FormatCivilTime(absl::CivilHour(2015)));\n\n  EXPECT_EQ(\"2015-01-02\",\n            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02\",\n            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(absl::CivilDay(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01\", absl::FormatCivilTime(absl::CivilDay(2015, 1)));\n  EXPECT_EQ(\"2015-01-01\", absl::FormatCivilTime(absl::CivilDay(2015)));\n\n  EXPECT_EQ(\"2015-01\",\n            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01\",\n            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(absl::CivilMonth(2015, 1)));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(absl::CivilMonth(2015)));\n\n  EXPECT_EQ(\"2015\",\n            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(absl::CivilYear(2015, 1, 2)));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(absl::CivilYear(2015, 1)));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(absl::CivilYear(2015)));\n}\n\nTEST(CivilTime, FieldsConstructionLimits) {\n  const int kIntMax = std::numeric_limits<int>::max();\n  EXPECT_EQ(\"2038-01-19T03:14:07\", absl::FormatCivilTime(absl::CivilSecond(\n                                       1970, 1, 1, 0, 0, kIntMax)));\n  EXPECT_EQ(\"6121-02-11T05:21:07\", absl::FormatCivilTime(absl::CivilSecond(\n                                       1970, 1, 1, 0, kIntMax, kIntMax)));\n  EXPECT_EQ(\"251104-11-20T12:21:07\",\n            absl::FormatCivilTime(\n                absl::CivilSecond(1970, 1, 1, kIntMax, kIntMax, kIntMax)));\n  EXPECT_EQ(\"6130715-05-30T12:21:07\",\n            absl::FormatCivilTime(absl::CivilSecond(1970, 1, kIntMax, kIntMax,\n                                                    kIntMax, kIntMax)));\n  EXPECT_EQ(\"185087685-11-26T12:21:07\",\n            absl::FormatCivilTime(absl::CivilSecond(\n                1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax)));\n\n  const int kIntMin = std::numeric_limits<int>::min();\n  EXPECT_EQ(\"1901-12-13T20:45:52\", absl::FormatCivilTime(absl::CivilSecond(\n                                       1970, 1, 1, 0, 0, kIntMin)));\n  EXPECT_EQ(\"-2182-11-20T18:37:52\", absl::FormatCivilTime(absl::CivilSecond(\n                                        1970, 1, 1, 0, kIntMin, kIntMin)));\n  EXPECT_EQ(\"-247165-02-11T10:37:52\",\n            absl::FormatCivilTime(\n                absl::CivilSecond(1970, 1, 1, kIntMin, kIntMin, kIntMin)));\n  EXPECT_EQ(\"-6126776-08-01T10:37:52\",\n            absl::FormatCivilTime(absl::CivilSecond(1970, 1, kIntMin, kIntMin,\n                                                    kIntMin, kIntMin)));\n  EXPECT_EQ(\"-185083747-10-31T10:37:52\",\n            absl::FormatCivilTime(absl::CivilSecond(\n                1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin)));\n}\n\nTEST(CivilTime, RangeLimits) {\n  const absl::civil_year_t kYearMax =\n      std::numeric_limits<absl::civil_year_t>::max();\n  EXPECT_EQ(absl::CivilYear(kYearMax), absl::CivilYear::max());\n  EXPECT_EQ(absl::CivilMonth(kYearMax, 12), absl::CivilMonth::max());\n  EXPECT_EQ(absl::CivilDay(kYearMax, 12, 31), absl::CivilDay::max());\n  EXPECT_EQ(absl::CivilHour(kYearMax, 12, 31, 23), absl::CivilHour::max());\n  EXPECT_EQ(absl::CivilMinute(kYearMax, 12, 31, 23, 59),\n            absl::CivilMinute::max());\n  EXPECT_EQ(absl::CivilSecond(kYearMax, 12, 31, 23, 59, 59),\n            absl::CivilSecond::max());\n\n  const absl::civil_year_t kYearMin =\n      std::numeric_limits<absl::civil_year_t>::min();\n  EXPECT_EQ(absl::CivilYear(kYearMin), absl::CivilYear::min());\n  EXPECT_EQ(absl::CivilMonth(kYearMin, 1), absl::CivilMonth::min());\n  EXPECT_EQ(absl::CivilDay(kYearMin, 1, 1), absl::CivilDay::min());\n  EXPECT_EQ(absl::CivilHour(kYearMin, 1, 1, 0), absl::CivilHour::min());\n  EXPECT_EQ(absl::CivilMinute(kYearMin, 1, 1, 0, 0), absl::CivilMinute::min());\n  EXPECT_EQ(absl::CivilSecond(kYearMin, 1, 1, 0, 0, 0),\n            absl::CivilSecond::min());\n}\n\nTEST(CivilTime, ImplicitCrossAlignment) {\n  absl::CivilYear year(2015);\n  absl::CivilMonth month = year;\n  absl::CivilDay day = month;\n  absl::CivilHour hour = day;\n  absl::CivilMinute minute = hour;\n  absl::CivilSecond second = minute;\n\n  second = year;\n  EXPECT_EQ(second, year);\n  second = month;\n  EXPECT_EQ(second, month);\n  second = day;\n  EXPECT_EQ(second, day);\n  second = hour;\n  EXPECT_EQ(second, hour);\n  second = minute;\n  EXPECT_EQ(second, minute);\n\n  minute = year;\n  EXPECT_EQ(minute, year);\n  minute = month;\n  EXPECT_EQ(minute, month);\n  minute = day;\n  EXPECT_EQ(minute, day);\n  minute = hour;\n  EXPECT_EQ(minute, hour);\n\n  hour = year;\n  EXPECT_EQ(hour, year);\n  hour = month;\n  EXPECT_EQ(hour, month);\n  hour = day;\n  EXPECT_EQ(hour, day);\n\n  day = year;\n  EXPECT_EQ(day, year);\n  day = month;\n  EXPECT_EQ(day, month);\n\n  month = year;\n  EXPECT_EQ(month, year);\n\n  // Ensures unsafe conversions are not allowed.\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilSecond, absl::CivilMinute>::value));\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilSecond, absl::CivilHour>::value));\n  EXPECT_FALSE((std::is_convertible<absl::CivilSecond, absl::CivilDay>::value));\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilSecond, absl::CivilMonth>::value));\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilSecond, absl::CivilYear>::value));\n\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilMinute, absl::CivilHour>::value));\n  EXPECT_FALSE((std::is_convertible<absl::CivilMinute, absl::CivilDay>::value));\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilMinute, absl::CivilMonth>::value));\n  EXPECT_FALSE(\n      (std::is_convertible<absl::CivilMinute, absl::CivilYear>::value));\n\n  EXPECT_FALSE((std::is_convertible<absl::CivilHour, absl::CivilDay>::value));\n  EXPECT_FALSE((std::is_convertible<absl::CivilHour, absl::CivilMonth>::value));\n  EXPECT_FALSE((std::is_convertible<absl::CivilHour, absl::CivilYear>::value));\n\n  EXPECT_FALSE((std::is_convertible<absl::CivilDay, absl::CivilMonth>::value));\n  EXPECT_FALSE((std::is_convertible<absl::CivilDay, absl::CivilYear>::value));\n\n  EXPECT_FALSE((std::is_convertible<absl::CivilMonth, absl::CivilYear>::value));\n}\n\nTEST(CivilTime, ExplicitCrossAlignment) {\n  //\n  // Assign from smaller units -> larger units\n  //\n\n  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(second));\n\n  absl::CivilMinute minute(second);\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(minute));\n\n  absl::CivilHour hour(minute);\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(hour));\n\n  absl::CivilDay day(hour);\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(day));\n\n  absl::CivilMonth month(day);\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(month));\n\n  absl::CivilYear year(month);\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(year));\n\n  //\n  // Now assign from larger units -> smaller units\n  //\n\n  month = absl::CivilMonth(year);\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(month));\n\n  day = absl::CivilDay(month);\n  EXPECT_EQ(\"2015-01-01\", absl::FormatCivilTime(day));\n\n  hour = absl::CivilHour(day);\n  EXPECT_EQ(\"2015-01-01T00\", absl::FormatCivilTime(hour));\n\n  minute = absl::CivilMinute(hour);\n  EXPECT_EQ(\"2015-01-01T00:00\", absl::FormatCivilTime(minute));\n\n  second = absl::CivilSecond(minute);\n  EXPECT_EQ(\"2015-01-01T00:00:00\", absl::FormatCivilTime(second));\n}\n\n// Metafunction to test whether difference is allowed between two types.\ntemplate <typename T1, typename T2>\nstruct HasDiff {\n  template <typename U1, typename U2>\n  static std::false_type test(...);\n  template <typename U1, typename U2>\n  static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>()));\n  static constexpr bool value = decltype(test<T1, T2>(0))::value;\n};\n\nTEST(CivilTime, DisallowCrossAlignedDifference) {\n  // Difference is allowed between types with the same alignment.\n  static_assert(HasDiff<absl::CivilSecond, absl::CivilSecond>::value, \"\");\n  static_assert(HasDiff<absl::CivilMinute, absl::CivilMinute>::value, \"\");\n  static_assert(HasDiff<absl::CivilHour, absl::CivilHour>::value, \"\");\n  static_assert(HasDiff<absl::CivilDay, absl::CivilDay>::value, \"\");\n  static_assert(HasDiff<absl::CivilMonth, absl::CivilMonth>::value, \"\");\n  static_assert(HasDiff<absl::CivilYear, absl::CivilYear>::value, \"\");\n\n  // Difference is disallowed between types with different alignments.\n  static_assert(!HasDiff<absl::CivilSecond, absl::CivilMinute>::value, \"\");\n  static_assert(!HasDiff<absl::CivilSecond, absl::CivilHour>::value, \"\");\n  static_assert(!HasDiff<absl::CivilSecond, absl::CivilDay>::value, \"\");\n  static_assert(!HasDiff<absl::CivilSecond, absl::CivilMonth>::value, \"\");\n  static_assert(!HasDiff<absl::CivilSecond, absl::CivilYear>::value, \"\");\n\n  static_assert(!HasDiff<absl::CivilMinute, absl::CivilHour>::value, \"\");\n  static_assert(!HasDiff<absl::CivilMinute, absl::CivilDay>::value, \"\");\n  static_assert(!HasDiff<absl::CivilMinute, absl::CivilMonth>::value, \"\");\n  static_assert(!HasDiff<absl::CivilMinute, absl::CivilYear>::value, \"\");\n\n  static_assert(!HasDiff<absl::CivilHour, absl::CivilDay>::value, \"\");\n  static_assert(!HasDiff<absl::CivilHour, absl::CivilMonth>::value, \"\");\n  static_assert(!HasDiff<absl::CivilHour, absl::CivilYear>::value, \"\");\n\n  static_assert(!HasDiff<absl::CivilDay, absl::CivilMonth>::value, \"\");\n  static_assert(!HasDiff<absl::CivilDay, absl::CivilYear>::value, \"\");\n\n  static_assert(!HasDiff<absl::CivilMonth, absl::CivilYear>::value, \"\");\n}\n\nTEST(CivilTime, ValueSemantics) {\n  const absl::CivilHour a(2015, 1, 2, 3);\n  const absl::CivilHour b = a;\n  const absl::CivilHour c(b);\n  absl::CivilHour d;\n  d = c;\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(d));\n}\n\nTEST(CivilTime, Relational) {\n  // Tests that the alignment unit is ignored in comparison.\n  const absl::CivilYear year(2014);\n  const absl::CivilMonth month(year);\n  EXPECT_EQ(year, month);\n\n#define TEST_RELATIONAL(OLDER, YOUNGER) \\\n  do {                                  \\\n    EXPECT_FALSE(OLDER < OLDER);        \\\n    EXPECT_FALSE(OLDER > OLDER);        \\\n    EXPECT_TRUE(OLDER >= OLDER);        \\\n    EXPECT_TRUE(OLDER <= OLDER);        \\\n    EXPECT_FALSE(YOUNGER < YOUNGER);    \\\n    EXPECT_FALSE(YOUNGER > YOUNGER);    \\\n    EXPECT_TRUE(YOUNGER >= YOUNGER);    \\\n    EXPECT_TRUE(YOUNGER <= YOUNGER);    \\\n    EXPECT_EQ(OLDER, OLDER);            \\\n    EXPECT_NE(OLDER, YOUNGER);          \\\n    EXPECT_LT(OLDER, YOUNGER);          \\\n    EXPECT_LE(OLDER, YOUNGER);          \\\n    EXPECT_GT(YOUNGER, OLDER);          \\\n    EXPECT_GE(YOUNGER, OLDER);          \\\n  } while (0)\n\n  // Alignment is ignored in comparison (verified above), so CivilSecond is\n  // used to test comparison in all field positions.\n  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),\n                  absl::CivilSecond(2015, 1, 1, 0, 0, 0));\n  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),\n                  absl::CivilSecond(2014, 2, 1, 0, 0, 0));\n  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),\n                  absl::CivilSecond(2014, 1, 2, 0, 0, 0));\n  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),\n                  absl::CivilSecond(2014, 1, 1, 1, 0, 0));\n  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 0, 0),\n                  absl::CivilSecond(2014, 1, 1, 1, 1, 0));\n  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 1, 0),\n                  absl::CivilSecond(2014, 1, 1, 1, 1, 1));\n\n  // Tests the relational operators of two different civil-time types.\n  TEST_RELATIONAL(absl::CivilDay(2014, 1, 1),\n                  absl::CivilMinute(2014, 1, 1, 1, 1));\n  TEST_RELATIONAL(absl::CivilDay(2014, 1, 1), absl::CivilMonth(2014, 2));\n\n#undef TEST_RELATIONAL\n}\n\nTEST(CivilTime, Arithmetic) {\n  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(\"2015-01-02T03:04:06\", absl::FormatCivilTime(second += 1));\n  EXPECT_EQ(\"2015-01-02T03:04:07\", absl::FormatCivilTime(second + 1));\n  EXPECT_EQ(\"2015-01-02T03:04:08\", absl::FormatCivilTime(2 + second));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(second - 1));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(second -= 1));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(second++));\n  EXPECT_EQ(\"2015-01-02T03:04:07\", absl::FormatCivilTime(++second));\n  EXPECT_EQ(\"2015-01-02T03:04:07\", absl::FormatCivilTime(second--));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(--second));\n\n  absl::CivilMinute minute(2015, 1, 2, 3, 4);\n  EXPECT_EQ(\"2015-01-02T03:05\", absl::FormatCivilTime(minute += 1));\n  EXPECT_EQ(\"2015-01-02T03:06\", absl::FormatCivilTime(minute + 1));\n  EXPECT_EQ(\"2015-01-02T03:07\", absl::FormatCivilTime(2 + minute));\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(minute - 1));\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(minute -= 1));\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(minute++));\n  EXPECT_EQ(\"2015-01-02T03:06\", absl::FormatCivilTime(++minute));\n  EXPECT_EQ(\"2015-01-02T03:06\", absl::FormatCivilTime(minute--));\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(--minute));\n\n  absl::CivilHour hour(2015, 1, 2, 3);\n  EXPECT_EQ(\"2015-01-02T04\", absl::FormatCivilTime(hour += 1));\n  EXPECT_EQ(\"2015-01-02T05\", absl::FormatCivilTime(hour + 1));\n  EXPECT_EQ(\"2015-01-02T06\", absl::FormatCivilTime(2 + hour));\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(hour - 1));\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(hour -= 1));\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(hour++));\n  EXPECT_EQ(\"2015-01-02T05\", absl::FormatCivilTime(++hour));\n  EXPECT_EQ(\"2015-01-02T05\", absl::FormatCivilTime(hour--));\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(--hour));\n\n  absl::CivilDay day(2015, 1, 2);\n  EXPECT_EQ(\"2015-01-03\", absl::FormatCivilTime(day += 1));\n  EXPECT_EQ(\"2015-01-04\", absl::FormatCivilTime(day + 1));\n  EXPECT_EQ(\"2015-01-05\", absl::FormatCivilTime(2 + day));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(day - 1));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(day -= 1));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(day++));\n  EXPECT_EQ(\"2015-01-04\", absl::FormatCivilTime(++day));\n  EXPECT_EQ(\"2015-01-04\", absl::FormatCivilTime(day--));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(--day));\n\n  absl::CivilMonth month(2015, 1);\n  EXPECT_EQ(\"2015-02\", absl::FormatCivilTime(month += 1));\n  EXPECT_EQ(\"2015-03\", absl::FormatCivilTime(month + 1));\n  EXPECT_EQ(\"2015-04\", absl::FormatCivilTime(2 + month));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(month - 1));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(month -= 1));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(month++));\n  EXPECT_EQ(\"2015-03\", absl::FormatCivilTime(++month));\n  EXPECT_EQ(\"2015-03\", absl::FormatCivilTime(month--));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(--month));\n\n  absl::CivilYear year(2015);\n  EXPECT_EQ(\"2016\", absl::FormatCivilTime(year += 1));\n  EXPECT_EQ(\"2017\", absl::FormatCivilTime(year + 1));\n  EXPECT_EQ(\"2018\", absl::FormatCivilTime(2 + year));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(year - 1));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(year -= 1));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(year++));\n  EXPECT_EQ(\"2017\", absl::FormatCivilTime(++year));\n  EXPECT_EQ(\"2017\", absl::FormatCivilTime(year--));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(--year));\n}\n\nTEST(CivilTime, ArithmeticLimits) {\n  const int kIntMax = std::numeric_limits<int>::max();\n  const int kIntMin = std::numeric_limits<int>::min();\n\n  absl::CivilSecond second(1970, 1, 1, 0, 0, 0);\n  second += kIntMax;\n  EXPECT_EQ(\"2038-01-19T03:14:07\", absl::FormatCivilTime(second));\n  second -= kIntMax;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", absl::FormatCivilTime(second));\n  second += kIntMin;\n  EXPECT_EQ(\"1901-12-13T20:45:52\", absl::FormatCivilTime(second));\n  second -= kIntMin;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", absl::FormatCivilTime(second));\n\n  absl::CivilMinute minute(1970, 1, 1, 0, 0);\n  minute += kIntMax;\n  EXPECT_EQ(\"6053-01-23T02:07\", absl::FormatCivilTime(minute));\n  minute -= kIntMax;\n  EXPECT_EQ(\"1970-01-01T00:00\", absl::FormatCivilTime(minute));\n  minute += kIntMin;\n  EXPECT_EQ(\"-2114-12-08T21:52\", absl::FormatCivilTime(minute));\n  minute -= kIntMin;\n  EXPECT_EQ(\"1970-01-01T00:00\", absl::FormatCivilTime(minute));\n\n  absl::CivilHour hour(1970, 1, 1, 0);\n  hour += kIntMax;\n  EXPECT_EQ(\"246953-10-09T07\", absl::FormatCivilTime(hour));\n  hour -= kIntMax;\n  EXPECT_EQ(\"1970-01-01T00\", absl::FormatCivilTime(hour));\n  hour += kIntMin;\n  EXPECT_EQ(\"-243014-03-24T16\", absl::FormatCivilTime(hour));\n  hour -= kIntMin;\n  EXPECT_EQ(\"1970-01-01T00\", absl::FormatCivilTime(hour));\n\n  absl::CivilDay day(1970, 1, 1);\n  day += kIntMax;\n  EXPECT_EQ(\"5881580-07-11\", absl::FormatCivilTime(day));\n  day -= kIntMax;\n  EXPECT_EQ(\"1970-01-01\", absl::FormatCivilTime(day));\n  day += kIntMin;\n  EXPECT_EQ(\"-5877641-06-23\", absl::FormatCivilTime(day));\n  day -= kIntMin;\n  EXPECT_EQ(\"1970-01-01\", absl::FormatCivilTime(day));\n\n  absl::CivilMonth month(1970, 1);\n  month += kIntMax;\n  EXPECT_EQ(\"178958940-08\", absl::FormatCivilTime(month));\n  month -= kIntMax;\n  EXPECT_EQ(\"1970-01\", absl::FormatCivilTime(month));\n  month += kIntMin;\n  EXPECT_EQ(\"-178955001-05\", absl::FormatCivilTime(month));\n  month -= kIntMin;\n  EXPECT_EQ(\"1970-01\", absl::FormatCivilTime(month));\n\n  absl::CivilYear year(0);\n  year += kIntMax;\n  EXPECT_EQ(\"2147483647\", absl::FormatCivilTime(year));\n  year -= kIntMax;\n  EXPECT_EQ(\"0\", absl::FormatCivilTime(year));\n  year += kIntMin;\n  EXPECT_EQ(\"-2147483648\", absl::FormatCivilTime(year));\n  year -= kIntMin;\n  EXPECT_EQ(\"0\", absl::FormatCivilTime(year));\n}\n\nTEST(CivilTime, Difference) {\n  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(0, second - second);\n  EXPECT_EQ(10, (second + 10) - second);\n  EXPECT_EQ(-10, (second - 10) - second);\n\n  absl::CivilMinute minute(2015, 1, 2, 3, 4);\n  EXPECT_EQ(0, minute - minute);\n  EXPECT_EQ(10, (minute + 10) - minute);\n  EXPECT_EQ(-10, (minute - 10) - minute);\n\n  absl::CivilHour hour(2015, 1, 2, 3);\n  EXPECT_EQ(0, hour - hour);\n  EXPECT_EQ(10, (hour + 10) - hour);\n  EXPECT_EQ(-10, (hour - 10) - hour);\n\n  absl::CivilDay day(2015, 1, 2);\n  EXPECT_EQ(0, day - day);\n  EXPECT_EQ(10, (day + 10) - day);\n  EXPECT_EQ(-10, (day - 10) - day);\n\n  absl::CivilMonth month(2015, 1);\n  EXPECT_EQ(0, month - month);\n  EXPECT_EQ(10, (month + 10) - month);\n  EXPECT_EQ(-10, (month - 10) - month);\n\n  absl::CivilYear year(2015);\n  EXPECT_EQ(0, year - year);\n  EXPECT_EQ(10, (year + 10) - year);\n  EXPECT_EQ(-10, (year - 10) - year);\n}\n\nTEST(CivilTime, DifferenceLimits) {\n  const absl::civil_diff_t kDiffMax =\n      std::numeric_limits<absl::civil_diff_t>::max();\n  const absl::civil_diff_t kDiffMin =\n      std::numeric_limits<absl::civil_diff_t>::min();\n\n  // Check day arithmetic at the end of the year range.\n  const absl::CivilDay max_day(kDiffMax, 12, 31);\n  EXPECT_EQ(1, max_day - (max_day - 1));\n  EXPECT_EQ(-1, (max_day - 1) - max_day);\n\n  // Check day arithmetic at the start of the year range.\n  const absl::CivilDay min_day(kDiffMin, 1, 1);\n  EXPECT_EQ(1, (min_day + 1) - min_day);\n  EXPECT_EQ(-1, min_day - (min_day + 1));\n\n  // Check the limits of the return value.\n  const absl::CivilDay d1(1970, 1, 1);\n  const absl::CivilDay d2(25252734927768524, 7, 27);\n  EXPECT_EQ(kDiffMax, d2 - d1);\n  EXPECT_EQ(kDiffMin, d1 - (d2 + 1));\n}\n\nTEST(CivilTime, Properties) {\n  absl::CivilSecond ss(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, ss.year());\n  EXPECT_EQ(2, ss.month());\n  EXPECT_EQ(3, ss.day());\n  EXPECT_EQ(4, ss.hour());\n  EXPECT_EQ(5, ss.minute());\n  EXPECT_EQ(6, ss.second());\n  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ss));\n  EXPECT_EQ(34, absl::GetYearDay(ss));\n\n  absl::CivilMinute mm(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, mm.year());\n  EXPECT_EQ(2, mm.month());\n  EXPECT_EQ(3, mm.day());\n  EXPECT_EQ(4, mm.hour());\n  EXPECT_EQ(5, mm.minute());\n  EXPECT_EQ(0, mm.second());\n  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(mm));\n  EXPECT_EQ(34, absl::GetYearDay(mm));\n\n  absl::CivilHour hh(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, hh.year());\n  EXPECT_EQ(2, hh.month());\n  EXPECT_EQ(3, hh.day());\n  EXPECT_EQ(4, hh.hour());\n  EXPECT_EQ(0, hh.minute());\n  EXPECT_EQ(0, hh.second());\n  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(hh));\n  EXPECT_EQ(34, absl::GetYearDay(hh));\n\n  absl::CivilDay d(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, d.year());\n  EXPECT_EQ(2, d.month());\n  EXPECT_EQ(3, d.day());\n  EXPECT_EQ(0, d.hour());\n  EXPECT_EQ(0, d.minute());\n  EXPECT_EQ(0, d.second());\n  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(d));\n  EXPECT_EQ(34, absl::GetYearDay(d));\n\n  absl::CivilMonth m(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, m.year());\n  EXPECT_EQ(2, m.month());\n  EXPECT_EQ(1, m.day());\n  EXPECT_EQ(0, m.hour());\n  EXPECT_EQ(0, m.minute());\n  EXPECT_EQ(0, m.second());\n  EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(m));\n  EXPECT_EQ(32, absl::GetYearDay(m));\n\n  absl::CivilYear y(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, y.year());\n  EXPECT_EQ(1, y.month());\n  EXPECT_EQ(1, y.day());\n  EXPECT_EQ(0, y.hour());\n  EXPECT_EQ(0, y.minute());\n  EXPECT_EQ(0, y.second());\n  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(y));\n  EXPECT_EQ(1, absl::GetYearDay(y));\n}\n\nTEST(CivilTime, Format) {\n  absl::CivilSecond ss;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", absl::FormatCivilTime(ss));\n\n  absl::CivilMinute mm;\n  EXPECT_EQ(\"1970-01-01T00:00\", absl::FormatCivilTime(mm));\n\n  absl::CivilHour hh;\n  EXPECT_EQ(\"1970-01-01T00\", absl::FormatCivilTime(hh));\n\n  absl::CivilDay d;\n  EXPECT_EQ(\"1970-01-01\", absl::FormatCivilTime(d));\n\n  absl::CivilMonth m;\n  EXPECT_EQ(\"1970-01\", absl::FormatCivilTime(m));\n\n  absl::CivilYear y;\n  EXPECT_EQ(\"1970\", absl::FormatCivilTime(y));\n}\n\nTEST(CivilTime, Parse) {\n  absl::CivilSecond ss;\n  absl::CivilMinute mm;\n  absl::CivilHour hh;\n  absl::CivilDay d;\n  absl::CivilMonth m;\n  absl::CivilYear y;\n\n  // CivilSecond OK; others fail\n  EXPECT_TRUE(absl::ParseCivilTime(\"2015-01-02T03:04:05\", &ss));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(ss));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04:05\", &mm));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04:05\", &hh));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04:05\", &d));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04:05\", &m));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04:05\", &y));\n\n  // CivilMinute OK; others fail\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04\", &ss));\n  EXPECT_TRUE(absl::ParseCivilTime(\"2015-01-02T03:04\", &mm));\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(mm));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04\", &hh));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04\", &d));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04\", &m));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03:04\", &y));\n\n  // CivilHour OK; others fail\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03\", &ss));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03\", &mm));\n  EXPECT_TRUE(absl::ParseCivilTime(\"2015-01-02T03\", &hh));\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(hh));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03\", &d));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03\", &m));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02T03\", &y));\n\n  // CivilDay OK; others fail\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02\", &ss));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02\", &mm));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02\", &hh));\n  EXPECT_TRUE(absl::ParseCivilTime(\"2015-01-02\", &d));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(d));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02\", &m));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01-02\", &y));\n\n  // CivilMonth OK; others fail\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01\", &ss));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01\", &mm));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01\", &hh));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01\", &d));\n  EXPECT_TRUE(absl::ParseCivilTime(\"2015-01\", &m));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(m));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015-01\", &y));\n\n  // CivilYear OK; others fail\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015\", &ss));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015\", &mm));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015\", &hh));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015\", &d));\n  EXPECT_FALSE(absl::ParseCivilTime(\"2015\", &m));\n  EXPECT_TRUE(absl::ParseCivilTime(\"2015\", &y));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(y));\n}\n\nTEST(CivilTime, FormatAndParseLenient) {\n  absl::CivilSecond ss;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", absl::FormatCivilTime(ss));\n\n  absl::CivilMinute mm;\n  EXPECT_EQ(\"1970-01-01T00:00\", absl::FormatCivilTime(mm));\n\n  absl::CivilHour hh;\n  EXPECT_EQ(\"1970-01-01T00\", absl::FormatCivilTime(hh));\n\n  absl::CivilDay d;\n  EXPECT_EQ(\"1970-01-01\", absl::FormatCivilTime(d));\n\n  absl::CivilMonth m;\n  EXPECT_EQ(\"1970-01\", absl::FormatCivilTime(m));\n\n  absl::CivilYear y;\n  EXPECT_EQ(\"1970\", absl::FormatCivilTime(y));\n\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-01-02T03:04:05\", &ss));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", absl::FormatCivilTime(ss));\n\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-01-02T03:04:05\", &mm));\n  EXPECT_EQ(\"2015-01-02T03:04\", absl::FormatCivilTime(mm));\n\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-01-02T03:04:05\", &hh));\n  EXPECT_EQ(\"2015-01-02T03\", absl::FormatCivilTime(hh));\n\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-01-02T03:04:05\", &d));\n  EXPECT_EQ(\"2015-01-02\", absl::FormatCivilTime(d));\n\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-01-02T03:04:05\", &m));\n  EXPECT_EQ(\"2015-01\", absl::FormatCivilTime(m));\n\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-01-02T03:04:05\", &y));\n  EXPECT_EQ(\"2015\", absl::FormatCivilTime(y));\n}\n\nTEST(CivilTime, ParseEdgeCases) {\n  absl::CivilSecond ss;\n  EXPECT_TRUE(\n      absl::ParseLenientCivilTime(\"9223372036854775807-12-31T23:59:59\", &ss));\n  EXPECT_EQ(\"9223372036854775807-12-31T23:59:59\", absl::FormatCivilTime(ss));\n  EXPECT_TRUE(\n      absl::ParseLenientCivilTime(\"-9223372036854775808-01-01T00:00:00\", &ss));\n  EXPECT_EQ(\"-9223372036854775808-01-01T00:00:00\", absl::FormatCivilTime(ss));\n\n  absl::CivilMinute mm;\n  EXPECT_TRUE(\n      absl::ParseLenientCivilTime(\"9223372036854775807-12-31T23:59\", &mm));\n  EXPECT_EQ(\"9223372036854775807-12-31T23:59\", absl::FormatCivilTime(mm));\n  EXPECT_TRUE(\n      absl::ParseLenientCivilTime(\"-9223372036854775808-01-01T00:00\", &mm));\n  EXPECT_EQ(\"-9223372036854775808-01-01T00:00\", absl::FormatCivilTime(mm));\n\n  absl::CivilHour hh;\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"9223372036854775807-12-31T23\", &hh));\n  EXPECT_EQ(\"9223372036854775807-12-31T23\", absl::FormatCivilTime(hh));\n  EXPECT_TRUE(\n      absl::ParseLenientCivilTime(\"-9223372036854775808-01-01T00\", &hh));\n  EXPECT_EQ(\"-9223372036854775808-01-01T00\", absl::FormatCivilTime(hh));\n\n  absl::CivilDay d;\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"9223372036854775807-12-31\", &d));\n  EXPECT_EQ(\"9223372036854775807-12-31\", absl::FormatCivilTime(d));\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"-9223372036854775808-01-01\", &d));\n  EXPECT_EQ(\"-9223372036854775808-01-01\", absl::FormatCivilTime(d));\n\n  absl::CivilMonth m;\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"9223372036854775807-12\", &m));\n  EXPECT_EQ(\"9223372036854775807-12\", absl::FormatCivilTime(m));\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"-9223372036854775808-01\", &m));\n  EXPECT_EQ(\"-9223372036854775808-01\", absl::FormatCivilTime(m));\n\n  absl::CivilYear y;\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"9223372036854775807\", &y));\n  EXPECT_EQ(\"9223372036854775807\", absl::FormatCivilTime(y));\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"-9223372036854775808\", &y));\n  EXPECT_EQ(\"-9223372036854775808\", absl::FormatCivilTime(y));\n\n  // Tests some valid, but interesting, cases\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"0\", &ss)) << ss;\n  EXPECT_EQ(absl::CivilYear(0), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"0-1\", &ss)) << ss;\n  EXPECT_EQ(absl::CivilMonth(0, 1), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\" 2015 \", &ss)) << ss;\n  EXPECT_EQ(absl::CivilYear(2015), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\" 2015-6 \", &ss)) << ss;\n  EXPECT_EQ(absl::CivilMonth(2015, 6), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-6-7\", &ss)) << ss;\n  EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\" 2015-6-7 \", &ss)) << ss;\n  EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"2015-06-07T10:11:12 \", &ss)) << ss;\n  EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\" 2015-06-07T10:11:12 \", &ss)) << ss;\n  EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss);\n  EXPECT_TRUE(absl::ParseLenientCivilTime(\"-01-01\", &ss)) << ss;\n  EXPECT_EQ(absl::CivilMonth(-1, 1), ss);\n\n  // Tests some invalid cases\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"01-01-2015\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015-\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"0xff-01\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015-02-30T04:05:06\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015-02-03T04:05:96\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"X2015-02-03T04:05:06\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015-02-03T04:05:003\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015 -02-03T04:05:06\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015-02-03-04:05:06\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"2015:02:03T04-05-06\", &ss)) << ss;\n  EXPECT_FALSE(absl::ParseLenientCivilTime(\"9223372036854775808\", &y)) << y;\n}\n\nTEST(CivilTime, AbslStringify) {\n  EXPECT_EQ(\"2015-01-02T03:04:05\",\n            absl::StrFormat(\"%v\", absl::CivilSecond(2015, 1, 2, 3, 4, 5)));\n\n  EXPECT_EQ(\"2015-01-02T03:04\",\n            absl::StrFormat(\"%v\", absl::CivilMinute(2015, 1, 2, 3, 4)));\n\n  EXPECT_EQ(\"2015-01-02T03\",\n            absl::StrFormat(\"%v\", absl::CivilHour(2015, 1, 2, 3)));\n\n  EXPECT_EQ(\"2015-01-02\", absl::StrFormat(\"%v\", absl::CivilDay(2015, 1, 2)));\n\n  EXPECT_EQ(\"2015-01\", absl::StrFormat(\"%v\", absl::CivilMonth(2015, 1)));\n\n  EXPECT_EQ(\"2015\", absl::StrFormat(\"%v\", absl::CivilYear(2015)));\n}\n\nTEST(CivilTime, OutputStream) {\n  absl::CivilSecond cs(2016, 2, 3, 4, 5, 6);\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::CivilYear(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016.................X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::CivilMonth(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02..............X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::CivilDay(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03...........X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::CivilHour(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03T04........X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::CivilMinute(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03T04:05.....X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::CivilSecond(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03T04:05:06..X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << absl::Weekday::wednesday;\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..Wednesday............X..\", ss.str());\n  }\n}\n\nTEST(CivilTime, Weekday) {\n  absl::CivilDay d(1970, 1, 1);\n  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(d)) << d;\n\n  // We used to get this wrong for years < -30.\n  d = absl::CivilDay(-31, 12, 24);\n  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(d)) << d;\n}\n\nTEST(CivilTime, NextPrevWeekday) {\n  // Jan 1, 1970 was a Thursday.\n  const absl::CivilDay thursday(1970, 1, 1);\n\n  // Thursday -> Thursday\n  absl::CivilDay d = absl::NextWeekday(thursday, absl::Weekday::thursday);\n  EXPECT_EQ(7, d - thursday) << d;\n  EXPECT_EQ(d - 14, absl::PrevWeekday(thursday, absl::Weekday::thursday));\n\n  // Thursday -> Friday\n  d = absl::NextWeekday(thursday, absl::Weekday::friday);\n  EXPECT_EQ(1, d - thursday) << d;\n  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::friday));\n\n  // Thursday -> Saturday\n  d = absl::NextWeekday(thursday, absl::Weekday::saturday);\n  EXPECT_EQ(2, d - thursday) << d;\n  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::saturday));\n\n  // Thursday -> Sunday\n  d = absl::NextWeekday(thursday, absl::Weekday::sunday);\n  EXPECT_EQ(3, d - thursday) << d;\n  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::sunday));\n\n  // Thursday -> Monday\n  d = absl::NextWeekday(thursday, absl::Weekday::monday);\n  EXPECT_EQ(4, d - thursday) << d;\n  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::monday));\n\n  // Thursday -> Tuesday\n  d = absl::NextWeekday(thursday, absl::Weekday::tuesday);\n  EXPECT_EQ(5, d - thursday) << d;\n  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::tuesday));\n\n  // Thursday -> Wednesday\n  d = absl::NextWeekday(thursday, absl::Weekday::wednesday);\n  EXPECT_EQ(6, d - thursday) << d;\n  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::wednesday));\n}\n\n// NOTE: Run this with --copt=-ftrapv to detect overflow problems.\nTEST(CivilTime, DifferenceWithHugeYear) {\n  absl::CivilDay d1(9223372036854775807, 1, 1);\n  absl::CivilDay d2(9223372036854775807, 12, 31);\n  EXPECT_EQ(364, d2 - d1);\n\n  d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1);\n  d2 = absl::CivilDay(-9223372036854775807 - 1, 12, 31);\n  EXPECT_EQ(365, d2 - d1);\n\n  // Check the limits of the return value at the end of the year range.\n  d1 = absl::CivilDay(9223372036854775807, 1, 1);\n  d2 = absl::CivilDay(9198119301927009252, 6, 6);\n  EXPECT_EQ(9223372036854775807, d1 - d2);\n  d2 = d2 - 1;\n  EXPECT_EQ(-9223372036854775807 - 1, d2 - d1);\n\n  // Check the limits of the return value at the start of the year range.\n  d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1);\n  d2 = absl::CivilDay(-9198119301927009254, 7, 28);\n  EXPECT_EQ(9223372036854775807, d2 - d1);\n  d2 = d2 + 1;\n  EXPECT_EQ(-9223372036854775807 - 1, d1 - d2);\n\n  // Check the limits of the return value from either side of year 0.\n  d1 = absl::CivilDay(-12626367463883278, 9, 3);\n  d2 = absl::CivilDay(12626367463883277, 3, 28);\n  EXPECT_EQ(9223372036854775807, d2 - d1);\n  d2 = d2 + 1;\n  EXPECT_EQ(-9223372036854775807 - 1, d1 - d2);\n}\n\n// NOTE: Run this with --copt=-ftrapv to detect overflow problems.\nTEST(CivilTime, DifferenceNoIntermediateOverflow) {\n  // The difference up to the minute field would be below the minimum\n  // int64_t, but the 52 extra seconds brings us back to the minimum.\n  absl::CivilSecond s1(-292277022657, 1, 27, 8, 29 - 1, 52);\n  absl::CivilSecond s2(1970, 1, 1, 0, 0 - 1, 0);\n  EXPECT_EQ(-9223372036854775807 - 1, s1 - s2);\n\n  // The difference up to the minute field would be above the maximum\n  // int64_t, but the -53 extra seconds brings us back to the maximum.\n  s1 = absl::CivilSecond(292277026596, 12, 4, 15, 30, 7 - 7);\n  s2 = absl::CivilSecond(1970, 1, 1, 0, 0, 0 - 7);\n  EXPECT_EQ(9223372036854775807, s1 - s2);\n}\n\nTEST(CivilTime, NormalizeSimpleOverflow) {\n  absl::CivilSecond cs;\n  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 59 + 1);\n  EXPECT_EQ(\"2013-11-15T16:33:00\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16, 59 + 1, 14);\n  EXPECT_EQ(\"2013-11-15T17:00:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 23 + 1, 32, 14);\n  EXPECT_EQ(\"2013-11-16T00:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 30 + 1, 16, 32, 14);\n  EXPECT_EQ(\"2013-12-01T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 12 + 1, 15, 16, 32, 14);\n  EXPECT_EQ(\"2014-01-15T16:32:14\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeSimpleUnderflow) {\n  absl::CivilSecond cs;\n  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 0 - 1);\n  EXPECT_EQ(\"2013-11-15T16:31:59\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16, 0 - 1, 14);\n  EXPECT_EQ(\"2013-11-15T15:59:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 0 - 1, 32, 14);\n  EXPECT_EQ(\"2013-11-14T23:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 1 - 1, 16, 32, 14);\n  EXPECT_EQ(\"2013-10-31T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 1 - 1, 15, 16, 32, 14);\n  EXPECT_EQ(\"2012-12-15T16:32:14\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeMultipleOverflow) {\n  absl::CivilSecond cs(2013, 12, 31, 23, 59, 59 + 1);\n  EXPECT_EQ(\"2014-01-01T00:00:00\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeMultipleUnderflow) {\n  absl::CivilSecond cs(2014, 1, 1, 0, 0, 0 - 1);\n  EXPECT_EQ(\"2013-12-31T23:59:59\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeOverflowLimits) {\n  absl::CivilSecond cs;\n\n  const int kintmax = std::numeric_limits<int>::max();\n  cs = absl::CivilSecond(0, kintmax, kintmax, kintmax, kintmax, kintmax);\n  EXPECT_EQ(\"185085715-11-27T12:21:07\", absl::FormatCivilTime(cs));\n\n  const int kintmin = std::numeric_limits<int>::min();\n  cs = absl::CivilSecond(0, kintmin, kintmin, kintmin, kintmin, kintmin);\n  EXPECT_EQ(\"-185085717-10-31T10:37:52\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeComplexOverflow) {\n  absl::CivilSecond cs;\n  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 + 123456789);\n  EXPECT_EQ(\"2017-10-14T14:05:23\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16, 32 + 1234567, 14);\n  EXPECT_EQ(\"2016-03-22T00:39:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16 + 123456, 32, 14);\n  EXPECT_EQ(\"2027-12-16T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15 + 1234, 16, 32, 14);\n  EXPECT_EQ(\"2017-04-02T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11 + 123, 15, 16, 32, 14);\n  EXPECT_EQ(\"2024-02-15T16:32:14\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeComplexUnderflow) {\n  absl::CivilSecond cs;\n  cs = absl::CivilSecond(1999, 3, 0, 0, 0, 0);  // year 400\n  EXPECT_EQ(\"1999-02-28T00:00:00\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 - 123456789);\n  EXPECT_EQ(\"2009-12-17T18:59:05\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16, 32 - 1234567, 14);\n  EXPECT_EQ(\"2011-07-12T08:25:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15, 16 - 123456, 32, 14);\n  EXPECT_EQ(\"1999-10-16T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11, 15 - 1234, 16, 32, 14);\n  EXPECT_EQ(\"2010-06-30T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11 - 123, 15, 16, 32, 14);\n  EXPECT_EQ(\"2003-08-15T16:32:14\", absl::FormatCivilTime(cs));\n}\n\nTEST(CivilTime, NormalizeMishmash) {\n  absl::CivilSecond cs;\n  cs = absl::CivilSecond(2013, 11 - 123, 15 + 1234, 16 - 123456, 32 + 1234567,\n                         14 - 123456789);\n  EXPECT_EQ(\"1991-05-09T03:06:05\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11 + 123, 15 - 1234, 16 + 123456, 32 - 1234567,\n                         14 + 123456789);\n  EXPECT_EQ(\"2036-05-24T05:58:23\", absl::FormatCivilTime(cs));\n\n  cs = absl::CivilSecond(2013, 11, -146097 + 1, 16, 32, 14);\n  EXPECT_EQ(\"1613-11-01T16:32:14\", absl::FormatCivilTime(cs));\n  cs = absl::CivilSecond(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14);\n  EXPECT_EQ(\"2013-11-01T16:32:14\", absl::FormatCivilTime(cs));\n}\n\n// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)\n// and check that they normalize to the expected time.  146097 days span\n// the 400-year Gregorian cycle used during normalization.\nTEST(CivilTime, NormalizeAllTheDays) {\n  absl::CivilDay expected(1970, 1, 1);\n  for (int day = 1; day <= 146097; ++day) {\n    absl::CivilSecond cs(1970, 1, day, 0, 0, 0);\n    EXPECT_EQ(expected, cs);\n    ++expected;\n  }\n}\n\nTEST(CivilTime, NormalizeWithHugeYear) {\n  absl::CivilMonth c(9223372036854775807, 1);\n  EXPECT_EQ(\"9223372036854775807-01\", absl::FormatCivilTime(c));\n  c = c - 1;  // Causes normalization\n  EXPECT_EQ(\"9223372036854775806-12\", absl::FormatCivilTime(c));\n\n  c = absl::CivilMonth(-9223372036854775807 - 1, 1);\n  EXPECT_EQ(\"-9223372036854775808-01\", absl::FormatCivilTime(c));\n  c = c + 12;  // Causes normalization\n  EXPECT_EQ(\"-9223372036854775807-01\", absl::FormatCivilTime(c));\n}\n\nTEST(CivilTime, LeapYears) {\n  const absl::CivilSecond s1(2013, 2, 28 + 1, 0, 0, 0);\n  EXPECT_EQ(\"2013-03-01T00:00:00\", absl::FormatCivilTime(s1));\n\n  const absl::CivilSecond s2(2012, 2, 28 + 1, 0, 0, 0);\n  EXPECT_EQ(\"2012-02-29T00:00:00\", absl::FormatCivilTime(s2));\n\n  const absl::CivilSecond s3(1900, 2, 28 + 1, 0, 0, 0);\n  EXPECT_EQ(\"1900-03-01T00:00:00\", absl::FormatCivilTime(s3));\n\n  const struct {\n    int year;\n    int days;\n    struct {\n      int month;\n      int day;\n    } leap_day;  // The date of the day after Feb 28.\n  } kLeapYearTable[]{\n      {1900, 365, {3, 1}},  {1999, 365, {3, 1}},\n      {2000, 366, {2, 29}},  // leap year\n      {2001, 365, {3, 1}},  {2002, 365, {3, 1}},\n      {2003, 365, {3, 1}},  {2004, 366, {2, 29}},  // leap year\n      {2005, 365, {3, 1}},  {2006, 365, {3, 1}},\n      {2007, 365, {3, 1}},  {2008, 366, {2, 29}},  // leap year\n      {2009, 365, {3, 1}},  {2100, 365, {3, 1}},\n  };\n\n  for (int i = 0; i < ABSL_ARRAYSIZE(kLeapYearTable); ++i) {\n    const int y = kLeapYearTable[i].year;\n    const int m = kLeapYearTable[i].leap_day.month;\n    const int d = kLeapYearTable[i].leap_day.day;\n    const int n = kLeapYearTable[i].days;\n\n    // Tests incrementing through the leap day.\n    const absl::CivilDay feb28(y, 2, 28);\n    const absl::CivilDay next_day = feb28 + 1;\n    EXPECT_EQ(m, next_day.month());\n    EXPECT_EQ(d, next_day.day());\n\n    // Tests difference in days of leap years.\n    const absl::CivilYear year(feb28);\n    const absl::CivilYear next_year = year + 1;\n    EXPECT_EQ(n, absl::CivilDay(next_year) - absl::CivilDay(year));\n  }\n}\n\nTEST(CivilTime, FirstThursdayInMonth) {\n  const absl::CivilDay nov1(2014, 11, 1);\n  const absl::CivilDay thursday =\n      absl::NextWeekday(nov1 - 1, absl::Weekday::thursday);\n  EXPECT_EQ(\"2014-11-06\", absl::FormatCivilTime(thursday));\n\n  // Bonus: Date of Thanksgiving in the United States\n  // Rule: Fourth Thursday of November\n  const absl::CivilDay thanksgiving = thursday + 7 * 3;\n  EXPECT_EQ(\"2014-11-27\", absl::FormatCivilTime(thanksgiving));\n}\n\nTEST(CivilTime, DocumentationExample) {\n  absl::CivilSecond second(2015, 6, 28, 1, 2, 3);  // 2015-06-28 01:02:03\n  absl::CivilMinute minute(second);                // 2015-06-28 01:02:00\n  absl::CivilDay day(minute);                      // 2015-06-28 00:00:00\n\n  second -= 1;                    // 2015-06-28 01:02:02\n  --second;                       // 2015-06-28 01:02:01\n  EXPECT_EQ(minute, second - 1);  // Comparison between types\n  EXPECT_LT(minute, second);\n\n  // int diff = second - minute;  // ERROR: Mixed types, won't compile\n\n  absl::CivilDay june_1(2015, 6, 1);  // Pass fields to c'tor.\n  int diff = day - june_1;            // Num days between 'day' and June 1\n  EXPECT_EQ(27, diff);\n\n  // Fields smaller than alignment are floored to their minimum value.\n  absl::CivilDay day_floor(2015, 1, 2, 9, 9, 9);\n  EXPECT_EQ(0, day_floor.hour());  // 09:09:09 is floored\n  EXPECT_EQ(absl::CivilDay(2015, 1, 2), day_floor);\n\n  // Unspecified fields default to their minimum value\n  absl::CivilDay day_default(2015);  // Defaults to Jan 1\n  EXPECT_EQ(absl::CivilDay(2015, 1, 1), day_default);\n\n  // Iterates all the days of June.\n  absl::CivilMonth june(day);  // CivilDay -> CivilMonth\n  absl::CivilMonth july = june + 1;\n  for (absl::CivilDay day = june_1; day < july; ++day) {\n    // ...\n  }\n}\n\nTEST(CivilTime, SupportsHash) {\n  // To check that every field is used by the hash implementation, test\n  // with values that have all fields the same bar one, for each field.\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::CivilYear(2017),\n      absl::CivilYear(2018),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::CivilMonth(2017, 1),\n      absl::CivilMonth(2017, 2),\n      absl::CivilMonth(2018, 1),\n      absl::CivilMonth(2018, 2),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::CivilDay(2017, 1, 1),\n      absl::CivilDay(2017, 1, 2),\n      absl::CivilDay(2017, 2, 1),\n      absl::CivilDay(2017, 2, 2),\n      absl::CivilDay(2018, 1, 1),\n      absl::CivilDay(2018, 1, 2),\n      absl::CivilDay(2018, 2, 1),\n      absl::CivilDay(2018, 2, 2),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::CivilHour(2017, 1, 1, 0),\n      absl::CivilHour(2017, 1, 1, 1),\n      absl::CivilHour(2017, 1, 2, 0),\n      absl::CivilHour(2017, 1, 2, 1),\n      absl::CivilHour(2017, 2, 1, 0),\n      absl::CivilHour(2017, 2, 1, 1),\n      absl::CivilHour(2017, 2, 2, 0),\n      absl::CivilHour(2017, 2, 2, 1),\n      absl::CivilHour(2018, 1, 1, 0),\n      absl::CivilHour(2018, 1, 1, 1),\n      absl::CivilHour(2018, 1, 2, 0),\n      absl::CivilHour(2018, 1, 2, 1),\n      absl::CivilHour(2018, 2, 1, 0),\n      absl::CivilHour(2018, 2, 1, 1),\n      absl::CivilHour(2018, 2, 2, 0),\n      absl::CivilHour(2018, 2, 2, 1),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::CivilMinute(2017, 1, 1, 0, 0), absl::CivilMinute(2017, 1, 1, 0, 1),\n      absl::CivilMinute(2017, 1, 1, 1, 0), absl::CivilMinute(2017, 1, 1, 1, 1),\n      absl::CivilMinute(2017, 1, 2, 0, 0), absl::CivilMinute(2017, 1, 2, 0, 1),\n      absl::CivilMinute(2017, 1, 2, 1, 0), absl::CivilMinute(2017, 1, 2, 1, 1),\n      absl::CivilMinute(2017, 2, 1, 0, 0), absl::CivilMinute(2017, 2, 1, 0, 1),\n      absl::CivilMinute(2017, 2, 1, 1, 0), absl::CivilMinute(2017, 2, 1, 1, 1),\n      absl::CivilMinute(2017, 2, 2, 0, 0), absl::CivilMinute(2017, 2, 2, 0, 1),\n      absl::CivilMinute(2017, 2, 2, 1, 0), absl::CivilMinute(2017, 2, 2, 1, 1),\n      absl::CivilMinute(2018, 1, 1, 0, 0), absl::CivilMinute(2018, 1, 1, 0, 1),\n      absl::CivilMinute(2018, 1, 1, 1, 0), absl::CivilMinute(2018, 1, 1, 1, 1),\n      absl::CivilMinute(2018, 1, 2, 0, 0), absl::CivilMinute(2018, 1, 2, 0, 1),\n      absl::CivilMinute(2018, 1, 2, 1, 0), absl::CivilMinute(2018, 1, 2, 1, 1),\n      absl::CivilMinute(2018, 2, 1, 0, 0), absl::CivilMinute(2018, 2, 1, 0, 1),\n      absl::CivilMinute(2018, 2, 1, 1, 0), absl::CivilMinute(2018, 2, 1, 1, 1),\n      absl::CivilMinute(2018, 2, 2, 0, 0), absl::CivilMinute(2018, 2, 2, 0, 1),\n      absl::CivilMinute(2018, 2, 2, 1, 0), absl::CivilMinute(2018, 2, 2, 1, 1),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::CivilSecond(2017, 1, 1, 0, 0, 0),\n      absl::CivilSecond(2017, 1, 1, 0, 0, 1),\n      absl::CivilSecond(2017, 1, 1, 0, 1, 0),\n      absl::CivilSecond(2017, 1, 1, 0, 1, 1),\n      absl::CivilSecond(2017, 1, 1, 1, 0, 0),\n      absl::CivilSecond(2017, 1, 1, 1, 0, 1),\n      absl::CivilSecond(2017, 1, 1, 1, 1, 0),\n      absl::CivilSecond(2017, 1, 1, 1, 1, 1),\n      absl::CivilSecond(2017, 1, 2, 0, 0, 0),\n      absl::CivilSecond(2017, 1, 2, 0, 0, 1),\n      absl::CivilSecond(2017, 1, 2, 0, 1, 0),\n      absl::CivilSecond(2017, 1, 2, 0, 1, 1),\n      absl::CivilSecond(2017, 1, 2, 1, 0, 0),\n      absl::CivilSecond(2017, 1, 2, 1, 0, 1),\n      absl::CivilSecond(2017, 1, 2, 1, 1, 0),\n      absl::CivilSecond(2017, 1, 2, 1, 1, 1),\n      absl::CivilSecond(2017, 2, 1, 0, 0, 0),\n      absl::CivilSecond(2017, 2, 1, 0, 0, 1),\n      absl::CivilSecond(2017, 2, 1, 0, 1, 0),\n      absl::CivilSecond(2017, 2, 1, 0, 1, 1),\n      absl::CivilSecond(2017, 2, 1, 1, 0, 0),\n      absl::CivilSecond(2017, 2, 1, 1, 0, 1),\n      absl::CivilSecond(2017, 2, 1, 1, 1, 0),\n      absl::CivilSecond(2017, 2, 1, 1, 1, 1),\n      absl::CivilSecond(2017, 2, 2, 0, 0, 0),\n      absl::CivilSecond(2017, 2, 2, 0, 0, 1),\n      absl::CivilSecond(2017, 2, 2, 0, 1, 0),\n      absl::CivilSecond(2017, 2, 2, 0, 1, 1),\n      absl::CivilSecond(2017, 2, 2, 1, 0, 0),\n      absl::CivilSecond(2017, 2, 2, 1, 0, 1),\n      absl::CivilSecond(2017, 2, 2, 1, 1, 0),\n      absl::CivilSecond(2017, 2, 2, 1, 1, 1),\n      absl::CivilSecond(2018, 1, 1, 0, 0, 0),\n      absl::CivilSecond(2018, 1, 1, 0, 0, 1),\n      absl::CivilSecond(2018, 1, 1, 0, 1, 0),\n      absl::CivilSecond(2018, 1, 1, 0, 1, 1),\n      absl::CivilSecond(2018, 1, 1, 1, 0, 0),\n      absl::CivilSecond(2018, 1, 1, 1, 0, 1),\n      absl::CivilSecond(2018, 1, 1, 1, 1, 0),\n      absl::CivilSecond(2018, 1, 1, 1, 1, 1),\n      absl::CivilSecond(2018, 1, 2, 0, 0, 0),\n      absl::CivilSecond(2018, 1, 2, 0, 0, 1),\n      absl::CivilSecond(2018, 1, 2, 0, 1, 0),\n      absl::CivilSecond(2018, 1, 2, 0, 1, 1),\n      absl::CivilSecond(2018, 1, 2, 1, 0, 0),\n      absl::CivilSecond(2018, 1, 2, 1, 0, 1),\n      absl::CivilSecond(2018, 1, 2, 1, 1, 0),\n      absl::CivilSecond(2018, 1, 2, 1, 1, 1),\n      absl::CivilSecond(2018, 2, 1, 0, 0, 0),\n      absl::CivilSecond(2018, 2, 1, 0, 0, 1),\n      absl::CivilSecond(2018, 2, 1, 0, 1, 0),\n      absl::CivilSecond(2018, 2, 1, 0, 1, 1),\n      absl::CivilSecond(2018, 2, 1, 1, 0, 0),\n      absl::CivilSecond(2018, 2, 1, 1, 0, 1),\n      absl::CivilSecond(2018, 2, 1, 1, 1, 0),\n      absl::CivilSecond(2018, 2, 1, 1, 1, 1),\n      absl::CivilSecond(2018, 2, 2, 0, 0, 0),\n      absl::CivilSecond(2018, 2, 2, 0, 0, 1),\n      absl::CivilSecond(2018, 2, 2, 0, 1, 0),\n      absl::CivilSecond(2018, 2, 2, 0, 1, 1),\n      absl::CivilSecond(2018, 2, 2, 1, 0, 0),\n      absl::CivilSecond(2018, 2, 2, 1, 0, 1),\n      absl::CivilSecond(2018, 2, 2, 1, 1, 0),\n      absl::CivilSecond(2018, 2, 2, 1, 1, 1),\n  }));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/clock.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/clock.h\"\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/optimization.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#include <algorithm>\n#include <atomic>\n#include <cerrno>\n#include <cstdint>\n#include <ctime>\n#include <limits>\n\n#include \"absl/base/internal/spinlock.h\"\n#include \"absl/base/internal/unscaledcycleclock.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/port.h\"\n#include \"absl/base/thread_annotations.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nTime Now() {\n  // TODO(bww): Get a timespec instead so we don't have to divide.\n  int64_t n = absl::GetCurrentTimeNanos();\n  if (n >= 0) {\n    return time_internal::FromUnixDuration(\n        time_internal::MakeDuration(n / 1000000000, n % 1000000000 * 4));\n  }\n  return time_internal::FromUnixDuration(absl::Nanoseconds(n));\n}\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// Decide if we should use the fast GetCurrentTimeNanos() algorithm based on the\n// cyclecounter, otherwise just get the time directly from the OS on every call.\n// By default, the fast algorithm based on the cyclecount is disabled because in\n// certain situations, for example, if the OS enters a \"sleep\" mode, it may\n// produce incorrect values immediately upon waking.\n// This can be chosen at compile-time via\n// -DABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS=[0|1]\n#ifndef ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS\n#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 0\n#endif\n\n#if defined(__APPLE__) || defined(_WIN32)\n#include \"absl/time/internal/get_current_time_chrono.inc\"\n#else\n#include \"absl/time/internal/get_current_time_posix.inc\"\n#endif\n\n// Allows override by test.\n#ifndef GET_CURRENT_TIME_NANOS_FROM_SYSTEM\n#define GET_CURRENT_TIME_NANOS_FROM_SYSTEM() \\\n  ::absl::time_internal::GetCurrentTimeNanosFromSystem()\n#endif\n\n#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nint64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); }\nABSL_NAMESPACE_END\n}  // namespace absl\n#else  // Use the cyclecounter-based implementation below.\n\n// Allows override by test.\n#ifndef GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW\n#define GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW() \\\n  ::absl::time_internal::UnscaledCycleClockWrapperForGetCurrentTime::Now()\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\n\n// On some processors, consecutive reads of the cycle counter may yield the\n// same value (weakly-increasing). In debug mode, clear the least significant\n// bits to discourage depending on a strictly-increasing Now() value.\n// In x86-64's debug mode, discourage depending on a strictly-increasing Now()\n// value.\n#if !defined(NDEBUG) && defined(__x86_64__)\nconstexpr int64_t kCycleClockNowMask = ~int64_t{0xff};\n#else\nconstexpr int64_t kCycleClockNowMask = ~int64_t{0};\n#endif\n\n// This is a friend wrapper around UnscaledCycleClock::Now()\n// (needed to access UnscaledCycleClock).\nclass UnscaledCycleClockWrapperForGetCurrentTime {\n public:\n  static int64_t Now() {\n    return base_internal::UnscaledCycleClock::Now() & kCycleClockNowMask;\n  }\n};\n}  // namespace time_internal\n\n// uint64_t is used in this module to provide an extra bit in multiplications\n\n// ---------------------------------------------------------------------\n// An implementation of reader-write locks that use no atomic ops in the read\n// case.  This is a generalization of Lamport's method for reading a multiword\n// clock.  Increment a word on each write acquisition, using the low-order bit\n// as a spinlock; the word is the high word of the \"clock\".  Readers read the\n// high word, then all other data, then the high word again, and repeat the\n// read if the reads of the high words yields different answers, or an odd\n// value (either case suggests possible interference from a writer).\n// Here we use a spinlock to ensure only one writer at a time, rather than\n// spinning on the bottom bit of the word to benefit from SpinLock\n// spin-delay tuning.\n\n// Acquire seqlock (*seq) and return the value to be written to unlock.\nstatic inline uint64_t SeqAcquire(std::atomic<uint64_t>* seq) {\n  uint64_t x = seq->fetch_add(1, std::memory_order_relaxed);\n\n  // We put a release fence between update to *seq and writes to shared data.\n  // Thus all stores to shared data are effectively release operations and\n  // update to *seq above cannot be re-ordered past any of them.  Note that\n  // this barrier is not for the fetch_add above.  A release barrier for the\n  // fetch_add would be before it, not after.\n  std::atomic_thread_fence(std::memory_order_release);\n\n  return x + 2;  // original word plus 2\n}\n\n// Release seqlock (*seq) by writing x to it---a value previously returned by\n// SeqAcquire.\nstatic inline void SeqRelease(std::atomic<uint64_t>* seq, uint64_t x) {\n  // The unlock store to *seq must have release ordering so that all\n  // updates to shared data must finish before this store.\n  seq->store(x, std::memory_order_release);  // release lock for readers\n}\n\n// ---------------------------------------------------------------------\n\n// \"nsscaled\" is unit of time equal to a (2**kScale)th of a nanosecond.\nenum { kScale = 30 };\n\n// The minimum interval between samples of the time base.\n// We pick enough time to amortize the cost of the sample,\n// to get a reasonably accurate cycle counter rate reading,\n// and not so much that calculations will overflow 64-bits.\nstatic const uint64_t kMinNSBetweenSamples = 2000 << 20;\n\n// We require that kMinNSBetweenSamples shifted by kScale\n// have at least a bit left over for 64-bit calculations.\nstatic_assert(((kMinNSBetweenSamples << (kScale + 1)) >> (kScale + 1)) ==\n                  kMinNSBetweenSamples,\n              \"cannot represent kMaxBetweenSamplesNSScaled\");\n\n// data from a sample of the kernel's time value\nstruct TimeSampleAtomic {\n  std::atomic<uint64_t> raw_ns{0};              // raw kernel time\n  std::atomic<uint64_t> base_ns{0};             // our estimate of time\n  std::atomic<uint64_t> base_cycles{0};         // cycle counter reading\n  std::atomic<uint64_t> nsscaled_per_cycle{0};  // cycle period\n  // cycles before we'll sample again (a scaled reciprocal of the period,\n  // to avoid a division on the fast path).\n  std::atomic<uint64_t> min_cycles_per_sample{0};\n};\n// Same again, but with non-atomic types\nstruct TimeSample {\n  uint64_t raw_ns = 0;                 // raw kernel time\n  uint64_t base_ns = 0;                // our estimate of time\n  uint64_t base_cycles = 0;            // cycle counter reading\n  uint64_t nsscaled_per_cycle = 0;     // cycle period\n  uint64_t min_cycles_per_sample = 0;  // approx cycles before next sample\n};\n\nstruct ABSL_CACHELINE_ALIGNED TimeState {\n  std::atomic<uint64_t> seq{0};\n  TimeSampleAtomic last_sample;  // the last sample; under seq\n\n  // The following counters are used only by the test code.\n  int64_t stats_initializations{0};\n  int64_t stats_reinitializations{0};\n  int64_t stats_calibrations{0};\n  int64_t stats_slow_paths{0};\n  int64_t stats_fast_slow_paths{0};\n\n  uint64_t last_now_cycles ABSL_GUARDED_BY(lock){0};\n\n  // Used by GetCurrentTimeNanosFromKernel().\n  // We try to read clock values at about the same time as the kernel clock.\n  // This value gets adjusted up or down as estimate of how long that should\n  // take, so we can reject attempts that take unusually long.\n  std::atomic<uint64_t> approx_syscall_time_in_cycles{10 * 1000};\n  // Number of times in a row we've seen a kernel time call take substantially\n  // less than approx_syscall_time_in_cycles.\n  std::atomic<uint32_t> kernel_time_seen_smaller{0};\n\n  // A reader-writer lock protecting the static locations below.\n  // See SeqAcquire() and SeqRelease() above.\n  absl::base_internal::SpinLock lock{base_internal::SCHEDULE_KERNEL_ONLY};\n};\nABSL_CONST_INIT static TimeState time_state;\n\n// Return the time in ns as told by the kernel interface.  Place in *cycleclock\n// the value of the cycleclock at about the time of the syscall.\n// This call represents the time base that this module synchronizes to.\n// Ensures that *cycleclock does not step back by up to (1 << 16) from\n// last_cycleclock, to discard small backward counter steps.  (Larger steps are\n// assumed to be complete resyncs, which shouldn't happen.  If they do, a full\n// reinitialization of the outer algorithm should occur.)\nstatic int64_t GetCurrentTimeNanosFromKernel(uint64_t last_cycleclock,\n                                             uint64_t* cycleclock)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_state.lock) {\n  uint64_t local_approx_syscall_time_in_cycles =  // local copy\n      time_state.approx_syscall_time_in_cycles.load(std::memory_order_relaxed);\n\n  int64_t current_time_nanos_from_system;\n  uint64_t before_cycles;\n  uint64_t after_cycles;\n  uint64_t elapsed_cycles;\n  int loops = 0;\n  do {\n    before_cycles =\n        static_cast<uint64_t>(GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW());\n    current_time_nanos_from_system = GET_CURRENT_TIME_NANOS_FROM_SYSTEM();\n    after_cycles =\n        static_cast<uint64_t>(GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW());\n    // elapsed_cycles is unsigned, so is large on overflow\n    elapsed_cycles = after_cycles - before_cycles;\n    if (elapsed_cycles >= local_approx_syscall_time_in_cycles &&\n        ++loops == 20) {  // clock changed frequencies?  Back off.\n      loops = 0;\n      if (local_approx_syscall_time_in_cycles < 1000 * 1000) {\n        local_approx_syscall_time_in_cycles =\n            (local_approx_syscall_time_in_cycles + 1) << 1;\n      }\n      time_state.approx_syscall_time_in_cycles.store(\n          local_approx_syscall_time_in_cycles, std::memory_order_relaxed);\n    }\n  } while (elapsed_cycles >= local_approx_syscall_time_in_cycles ||\n           last_cycleclock - after_cycles < (static_cast<uint64_t>(1) << 16));\n\n  // Adjust approx_syscall_time_in_cycles to be within a factor of 2\n  // of the typical time to execute one iteration of the loop above.\n  if ((local_approx_syscall_time_in_cycles >> 1) < elapsed_cycles) {\n    // measured time is no smaller than half current approximation\n    time_state.kernel_time_seen_smaller.store(0, std::memory_order_relaxed);\n  } else if (time_state.kernel_time_seen_smaller.fetch_add(\n                 1, std::memory_order_relaxed) >= 3) {\n    // smaller delays several times in a row; reduce approximation by 12.5%\n    const uint64_t new_approximation =\n        local_approx_syscall_time_in_cycles -\n        (local_approx_syscall_time_in_cycles >> 3);\n    time_state.approx_syscall_time_in_cycles.store(new_approximation,\n                                                   std::memory_order_relaxed);\n    time_state.kernel_time_seen_smaller.store(0, std::memory_order_relaxed);\n  }\n\n  *cycleclock = after_cycles;\n  return current_time_nanos_from_system;\n}\n\nstatic int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD;\n\n// Read the contents of *atomic into *sample.\n// Each field is read atomically, but to maintain atomicity between fields,\n// the access must be done under a lock.\nstatic void ReadTimeSampleAtomic(const struct TimeSampleAtomic* atomic,\n                                 struct TimeSample* sample) {\n  sample->base_ns = atomic->base_ns.load(std::memory_order_relaxed);\n  sample->base_cycles = atomic->base_cycles.load(std::memory_order_relaxed);\n  sample->nsscaled_per_cycle =\n      atomic->nsscaled_per_cycle.load(std::memory_order_relaxed);\n  sample->min_cycles_per_sample =\n      atomic->min_cycles_per_sample.load(std::memory_order_relaxed);\n  sample->raw_ns = atomic->raw_ns.load(std::memory_order_relaxed);\n}\n\n// Public routine.\n// Algorithm:  We wish to compute real time from a cycle counter.  In normal\n// operation, we construct a piecewise linear approximation to the kernel time\n// source, using the cycle counter value.  The start of each line segment is at\n// the same point as the end of the last, but may have a different slope (that\n// is, a different idea of the cycle counter frequency).  Every couple of\n// seconds, the kernel time source is sampled and compared with the current\n// approximation.  A new slope is chosen that, if followed for another couple\n// of seconds, will correct the error at the current position.  The information\n// for a sample is in the \"last_sample\" struct.  The linear approximation is\n//   estimated_time = last_sample.base_ns +\n//     last_sample.ns_per_cycle * (counter_reading - last_sample.base_cycles)\n// (ns_per_cycle is actually stored in different units and scaled, to avoid\n// overflow).  The base_ns of the next linear approximation is the\n// estimated_time using the last approximation; the base_cycles is the cycle\n// counter value at that time; the ns_per_cycle is the number of ns per cycle\n// measured since the last sample, but adjusted so that most of the difference\n// between the estimated_time and the kernel time will be corrected by the\n// estimated time to the next sample.  In normal operation, this algorithm\n// relies on:\n// - the cycle counter and kernel time rates not changing a lot in a few\n//   seconds.\n// - the client calling into the code often compared to a couple of seconds, so\n//   the time to the next correction can be estimated.\n// Any time ns_per_cycle is not known, a major error is detected, or the\n// assumption about frequent calls is violated, the implementation returns the\n// kernel time.  It records sufficient data that a linear approximation can\n// resume a little later.\n\nint64_t GetCurrentTimeNanos() {\n  // read the data from the \"last_sample\" struct (but don't need raw_ns yet)\n  // The reads of \"seq\" and test of the values emulate a reader lock.\n  uint64_t base_ns;\n  uint64_t base_cycles;\n  uint64_t nsscaled_per_cycle;\n  uint64_t min_cycles_per_sample;\n  uint64_t seq_read0;\n  uint64_t seq_read1;\n\n  // If we have enough information to interpolate, the value returned will be\n  // derived from this cycleclock-derived time estimate.  On some platforms\n  // (POWER) the function to retrieve this value has enough complexity to\n  // contribute to register pressure - reading it early before initializing\n  // the other pieces of the calculation minimizes spill/restore instructions,\n  // minimizing icache cost.\n  uint64_t now_cycles =\n      static_cast<uint64_t>(GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW());\n\n  // Acquire pairs with the barrier in SeqRelease - if this load sees that\n  // store, the shared-data reads necessarily see that SeqRelease's updates\n  // to the same shared data.\n  seq_read0 = time_state.seq.load(std::memory_order_acquire);\n\n  // The algorithm does not require that the following four loads be ordered\n  // with respect to one another; it requires only that they precede the load of\n  // time_state.seq below them. Nevertheless, we mark each of them as an\n  // acquire-load, rather than using a barrier immediately before the\n  // time_state.seq load, because the former is likely faster on most CPUs of\n  // interest. Architectures that may see a regression because of this approach\n  // include PowerPC and MIPS.\n  base_ns = time_state.last_sample.base_ns.load(std::memory_order_acquire);\n  base_cycles =\n      time_state.last_sample.base_cycles.load(std::memory_order_acquire);\n  nsscaled_per_cycle =\n      time_state.last_sample.nsscaled_per_cycle.load(std::memory_order_acquire);\n  min_cycles_per_sample = time_state.last_sample.min_cycles_per_sample.load(\n      std::memory_order_acquire);\n\n  // The shared-data reads are effectively acquire ordered, and the\n  // shared-data writes are effectively release ordered. Therefore if our\n  // shared-data reads see any of a particular update's shared-data writes,\n  // seq_read1 is guaranteed to see that update's SeqAcquire.\n  seq_read1 = time_state.seq.load(std::memory_order_relaxed);\n\n  // Fast path.  Return if min_cycles_per_sample has not yet elapsed since the\n  // last sample, and we read a consistent sample.  The fast path activates\n  // only when min_cycles_per_sample is non-zero, which happens when we get an\n  // estimate for the cycle time.  The predicate will fail if now_cycles <\n  // base_cycles, or if some other thread is in the slow path.\n  //\n  // Since we now read now_cycles before base_ns, it is possible for now_cycles\n  // to be less than base_cycles (if we were interrupted between those loads and\n  // last_sample was updated). This is harmless, because delta_cycles will wrap\n  // and report a time much much bigger than min_cycles_per_sample. In that case\n  // we will take the slow path.\n  uint64_t delta_cycles;\n  if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 &&\n      (delta_cycles = now_cycles - base_cycles) < min_cycles_per_sample) {\n    return static_cast<int64_t>(\n        base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale));\n  }\n  return GetCurrentTimeNanosSlowPath();\n}\n\n// Return (a << kScale)/b.\n// Zero is returned if b==0.   Scaling is performed internally to\n// preserve precision without overflow.\nstatic uint64_t SafeDivideAndScale(uint64_t a, uint64_t b) {\n  // Find maximum safe_shift so that\n  //  0 <= safe_shift <= kScale  and  (a << safe_shift) does not overflow.\n  int safe_shift = kScale;\n  while (((a << safe_shift) >> safe_shift) != a) {\n    safe_shift--;\n  }\n  uint64_t scaled_b = b >> (kScale - safe_shift);\n  uint64_t quotient = 0;\n  if (scaled_b != 0) {\n    quotient = (a << safe_shift) / scaled_b;\n  }\n  return quotient;\n}\n\nstatic uint64_t UpdateLastSample(\n    uint64_t now_cycles, uint64_t now_ns, uint64_t delta_cycles,\n    const struct TimeSample* sample) ABSL_ATTRIBUTE_COLD;\n\n// The slow path of GetCurrentTimeNanos().  This is taken while gathering\n// initial samples, when enough time has elapsed since the last sample, and if\n// any other thread is writing to last_sample.\n//\n// Manually mark this 'noinline' to minimize stack frame size of the fast\n// path.  Without this, sometimes a compiler may inline this big block of code\n// into the fast path.  That causes lots of register spills and reloads that\n// are unnecessary unless the slow path is taken.\n//\n// TODO(absl-team): Remove this attribute when our compiler is smart enough\n// to do the right thing.\nABSL_ATTRIBUTE_NOINLINE\nstatic int64_t GetCurrentTimeNanosSlowPath()\n    ABSL_LOCKS_EXCLUDED(time_state.lock) {\n  // Serialize access to slow-path.  Fast-path readers are not blocked yet, and\n  // code below must not modify last_sample until the seqlock is acquired.\n  base_internal::SpinLockHolder l(time_state.lock);\n\n  // Sample the kernel time base.  This is the definition of\n  // \"now\" if we take the slow path.\n  uint64_t now_cycles;\n  uint64_t now_ns = static_cast<uint64_t>(\n      GetCurrentTimeNanosFromKernel(time_state.last_now_cycles, &now_cycles));\n  time_state.last_now_cycles = now_cycles;\n\n  uint64_t estimated_base_ns;\n\n  // ----------\n  // Read the \"last_sample\" values again; this time holding the write lock.\n  struct TimeSample sample;\n  ReadTimeSampleAtomic(&time_state.last_sample, &sample);\n\n  // ----------\n  // Try running the fast path again; another thread may have updated the\n  // sample between our run of the fast path and the sample we just read.\n  uint64_t delta_cycles = now_cycles - sample.base_cycles;\n  if (delta_cycles < sample.min_cycles_per_sample) {\n    // Another thread updated the sample.  This path does not take the seqlock\n    // so that blocked readers can make progress without blocking new readers.\n    estimated_base_ns =\n        sample.base_ns + ((delta_cycles * sample.nsscaled_per_cycle) >> kScale);\n    time_state.stats_fast_slow_paths++;\n  } else {\n    estimated_base_ns =\n        UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample);\n  }\n\n  return static_cast<int64_t>(estimated_base_ns);\n}\n\n// Main part of the algorithm.  Locks out readers, updates the approximation\n// using the new sample from the kernel, and stores the result in last_sample\n// for readers.  Returns the new estimated time.\nstatic uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,\n                                 uint64_t delta_cycles,\n                                 const struct TimeSample* sample)\n    ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_state.lock) {\n  uint64_t estimated_base_ns = now_ns;\n  uint64_t lock_value =\n      SeqAcquire(&time_state.seq);  // acquire seqlock to block readers\n\n  // The 5s in the next if-statement limits the time for which we will trust\n  // the cycle counter and our last sample to give a reasonable result.\n  // Errors in the rate of the source clock can be multiplied by the ratio\n  // between this limit and kMinNSBetweenSamples.\n  if (sample->raw_ns == 0 ||  // no recent sample, or clock went backwards\n      sample->raw_ns + static_cast<uint64_t>(5) * 1000 * 1000 * 1000 < now_ns ||\n      now_ns < sample->raw_ns || now_cycles < sample->base_cycles) {\n    // record this sample, and forget any previously known slope.\n    time_state.last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);\n    time_state.last_sample.base_ns.store(estimated_base_ns,\n                                         std::memory_order_relaxed);\n    time_state.last_sample.base_cycles.store(now_cycles,\n                                             std::memory_order_relaxed);\n    time_state.last_sample.nsscaled_per_cycle.store(0,\n                                                    std::memory_order_relaxed);\n    time_state.last_sample.min_cycles_per_sample.store(\n        0, std::memory_order_relaxed);\n    time_state.stats_initializations++;\n  } else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns &&\n             sample->base_cycles + 50 < now_cycles) {\n    // Enough time has passed to compute the cycle time.\n    if (sample->nsscaled_per_cycle != 0) {  // Have a cycle time estimate.\n      // Compute time from counter reading, but avoiding overflow\n      // delta_cycles may be larger than on the fast path.\n      uint64_t estimated_scaled_ns;\n      int s = -1;\n      do {\n        s++;\n        estimated_scaled_ns = (delta_cycles >> s) * sample->nsscaled_per_cycle;\n      } while (estimated_scaled_ns / sample->nsscaled_per_cycle !=\n               (delta_cycles >> s));\n      estimated_base_ns =\n          sample->base_ns + (estimated_scaled_ns >> (kScale - s));\n    }\n\n    // Compute the assumed cycle time kMinNSBetweenSamples ns into the future\n    // assuming the cycle counter rate stays the same as the last interval.\n    uint64_t ns = now_ns - sample->raw_ns;\n    uint64_t measured_nsscaled_per_cycle = SafeDivideAndScale(ns, delta_cycles);\n\n    uint64_t assumed_next_sample_delta_cycles =\n        SafeDivideAndScale(kMinNSBetweenSamples, measured_nsscaled_per_cycle);\n\n    // Estimate low by this much.\n    int64_t diff_ns = static_cast<int64_t>(now_ns - estimated_base_ns);\n\n    // We want to set nsscaled_per_cycle so that our estimate of the ns time\n    // at the assumed cycle time is the assumed ns time.\n    // That is, we want to set nsscaled_per_cycle so:\n    //  kMinNSBetweenSamples + diff_ns  ==\n    //  (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale\n    // But we wish to damp oscillations, so instead correct only most\n    // of our current error, by solving:\n    //  kMinNSBetweenSamples + diff_ns - (diff_ns / 16) ==\n    //  (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale\n    ns = static_cast<uint64_t>(static_cast<int64_t>(kMinNSBetweenSamples) +\n                               diff_ns - (diff_ns / 16));\n    uint64_t new_nsscaled_per_cycle =\n        SafeDivideAndScale(ns, assumed_next_sample_delta_cycles);\n    if (new_nsscaled_per_cycle != 0 && diff_ns < 100 * 1000 * 1000 &&\n        -diff_ns < 100 * 1000 * 1000) {\n      // record the cycle time measurement\n      time_state.last_sample.nsscaled_per_cycle.store(\n          new_nsscaled_per_cycle, std::memory_order_relaxed);\n      uint64_t new_min_cycles_per_sample =\n          SafeDivideAndScale(kMinNSBetweenSamples, new_nsscaled_per_cycle);\n      time_state.last_sample.min_cycles_per_sample.store(\n          new_min_cycles_per_sample, std::memory_order_relaxed);\n      time_state.stats_calibrations++;\n    } else {  // something went wrong; forget the slope\n      time_state.last_sample.nsscaled_per_cycle.store(\n          0, std::memory_order_relaxed);\n      time_state.last_sample.min_cycles_per_sample.store(\n          0, std::memory_order_relaxed);\n      estimated_base_ns = now_ns;\n      time_state.stats_reinitializations++;\n    }\n    time_state.last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);\n    time_state.last_sample.base_ns.store(estimated_base_ns,\n                                         std::memory_order_relaxed);\n    time_state.last_sample.base_cycles.store(now_cycles,\n                                             std::memory_order_relaxed);\n  } else {\n    // have a sample, but no slope; waiting for enough time for a calibration\n    time_state.stats_slow_paths++;\n  }\n\n  SeqRelease(&time_state.seq, lock_value);  // release the readers\n\n  return estimated_base_ns;\n}\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\n// Returns the maximum duration that SleepOnce() can sleep for.\nconstexpr absl::Duration MaxSleep() {\n#ifdef _WIN32\n  // Windows Sleep() takes unsigned long argument in milliseconds.\n  return absl::Milliseconds(\n      std::numeric_limits<unsigned long>::max());  // NOLINT(runtime/int)\n#else\n  return absl::Seconds(std::numeric_limits<time_t>::max());\n#endif\n}\n\n// Sleeps for the given duration.\n// REQUIRES: to_sleep <= MaxSleep().\nvoid SleepOnce(absl::Duration to_sleep) {\n#ifdef _WIN32\n  Sleep(static_cast<DWORD>(to_sleep / absl::Milliseconds(1)));\n#else\n  struct timespec sleep_time = absl::ToTimespec(to_sleep);\n  while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {\n    // Ignore signals and wait for the full interval to elapse.\n  }\n#endif\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n\nextern \"C\" {\n\nABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(\n    absl::Duration duration) {\n  while (duration > absl::ZeroDuration()) {\n    absl::Duration to_sleep = std::min(duration, absl::MaxSleep());\n    absl::SleepOnce(to_sleep);\n    duration -= to_sleep;\n  }\n}\n\n}  // extern \"C\"\n"
  },
  {
    "path": "absl/time/clock.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: clock.h\n// -----------------------------------------------------------------------------\n//\n// This header file contains utility functions for working with the system-wide\n// realtime clock. For descriptions of the main time abstractions used within\n// this header file, consult the time.h header file.\n#ifndef ABSL_TIME_CLOCK_H_\n#define ABSL_TIME_CLOCK_H_\n\n#include <cstdint>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Now()\n//\n// Returns the current time, expressed as an `absl::Time` absolute time value.\n//\n// To improve testability, consider injecting an absl::Clock and using\n// absl::Clock::TimeNow() instead.\nabsl::Time Now();\n\n// GetCurrentTimeNanos()\n//\n// Returns the current time, expressed as a count of nanoseconds since the Unix\n// Epoch (https://en.wikipedia.org/wiki/Unix_time). Prefer `absl::Now()` instead\n// for all but the most performance-sensitive cases (i.e. when you are calling\n// this function hundreds of thousands of times per second).\nint64_t GetCurrentTimeNanos();\n\n// SleepFor()\n//\n// Sleeps for the specified duration, expressed as an `absl::Duration`.\n//\n// Notes:\n// * Signal interruptions will not reduce the sleep duration.\n// * Returns immediately when passed a nonpositive duration.\nvoid SleepFor(absl::Duration duration);\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// -----------------------------------------------------------------------------\n// Implementation Details\n// -----------------------------------------------------------------------------\n\n// In some build configurations we pass --detect-odr-violations to the\n// gold linker.  This causes it to flag weak symbol overrides as ODR\n// violations.  Because ODR only applies to C++ and not C,\n// --detect-odr-violations ignores symbols not mangled with C++ names.\n// By changing our extension points to be extern \"C\", we dodge this\n// check.\nextern \"C\" {\nABSL_DLL void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(\n    absl::Duration duration);\n}  // extern \"C\"\n\ninline void absl::SleepFor(absl::Duration duration) {\n  ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(duration);\n}\n\n#endif  // ABSL_TIME_CLOCK_H_\n"
  },
  {
    "path": "absl/time/clock_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/clock.h\"\n\n#if !defined(_WIN32)\n#include <sys/time.h>\n#else\n#include <winsock2.h>\n#endif  // _WIN32\n#include <cstdio>\n\n#include \"absl/base/internal/cycleclock.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nvoid BM_Clock_Now_AbslTime(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Now());\n  }\n}\nBENCHMARK(BM_Clock_Now_AbslTime);\n\nvoid BM_Clock_Now_GetCurrentTimeNanos(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::GetCurrentTimeNanos());\n  }\n}\nBENCHMARK(BM_Clock_Now_GetCurrentTimeNanos);\n\nvoid BM_Clock_Now_AbslTime_ToUnixNanos(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToUnixNanos(absl::Now()));\n  }\n}\nBENCHMARK(BM_Clock_Now_AbslTime_ToUnixNanos);\n\nvoid BM_Clock_Now_CycleClock(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::base_internal::CycleClock::Now());\n  }\n}\nBENCHMARK(BM_Clock_Now_CycleClock);\n\n#if !defined(_WIN32)\nstatic void BM_Clock_Now_gettimeofday(benchmark::State& state) {\n  struct timeval tv;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(gettimeofday(&tv, nullptr));\n  }\n}\nBENCHMARK(BM_Clock_Now_gettimeofday);\n\nstatic void BM_Clock_Now_clock_gettime(benchmark::State& state) {\n  struct timespec ts;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(clock_gettime(CLOCK_REALTIME, &ts));\n  }\n}\nBENCHMARK(BM_Clock_Now_clock_gettime);\n#endif  // _WIN32\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/clock_interface.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/clock_interface.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/no_destructor.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\nclass RealTimeClock final : public Clock {\n private:\n#ifdef _MSC_VER\n  // Disable MSVC warning \"destructor never returns, potential memory leak\"\n#pragma warning(push)\n#pragma warning(disable : 4722)\n#endif\n  ~RealTimeClock() override {\n    ABSL_RAW_LOG(FATAL, \"RealTimeClock should never be destroyed\");\n  }\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n public:\n  absl::Time TimeNow() override { return absl::Now(); }\n\n  void Sleep(absl::Duration d) override { absl::SleepFor(d); }\n\n  void SleepUntil(absl::Time wakeup_time) override {\n    absl::Duration d = wakeup_time - TimeNow();\n    if (d > absl::ZeroDuration()) {\n      Sleep(d);\n    }\n  }\n\n  bool AwaitWithDeadline(absl::Mutex* mu, const absl::Condition& cond,\n                         absl::Time deadline) override {\n    return mu->AwaitWithDeadline(cond, deadline);\n  }\n};\n\n}  // namespace\n\nClock::~Clock() = default;  // go/key-method\n\nClock& Clock::GetRealClock() {\n  static absl::NoDestructor<RealTimeClock> rtclock;\n  return *rtclock;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/clock_interface.h",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: clock_interface.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_TIME_CLOCK_INTERFACE_H_\n#define ABSL_TIME_CLOCK_INTERFACE_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// An abstract interface representing a Clock, which is an object that can\n// tell you the current time, sleep, and wait for a condition variable.\n//\n// This interface allows decoupling code that uses time from the code that\n// creates a point in time.  You can use this to your advantage by injecting\n// Clocks into interfaces rather than having implementations call absl::Now()\n// directly.\n//\n// Implementations of this interface must be thread-safe.\n//\n// The Clock::GetRealClock() function returns a reference to the global realtime\n// clock.\n//\n// Example:\n//\n//   bool IsWeekend(Clock& clock) {\n//     absl::Time now = clock.TimeNow();\n//     // ... code to check if 'now' is a weekend.\n//   }\n//\n//   // Production code.\n//   IsWeekend(Clock::GetRealClock());\n//\n//   // Test code:\n//   MyTestClock test_clock(SATURDAY);\n//   IsWeekend(test_clock);\n//\nclass Clock {\n public:\n  // Returns a reference to the global realtime clock.\n  // The returned clock is thread-safe.\n  static Clock& GetRealClock();\n\n  virtual ~Clock();\n\n  // Returns the current time.\n  virtual absl::Time TimeNow() = 0;\n\n  // Sleeps for the specified duration.\n  virtual void Sleep(absl::Duration d) = 0;\n\n  // Sleeps until the specified time.\n  virtual void SleepUntil(absl::Time wakeup_time) = 0;\n\n  // Returns when cond is true or the deadline has passed.  Returns true iff\n  // cond holds when returning.\n  //\n  // Requires *mu to be held at least in shared mode.  It will be held when\n  // evaluating cond, and upon return, but it may be released and reacquired\n  // in the meantime.\n  //\n  // This method is similar to mu->AwaitWithDeadline() except that the\n  // latter only works with real-time deadlines.  This call works properly\n  // with simulated time if invoked on a simulated clock.\n  virtual bool AwaitWithDeadline(absl::Mutex* absl_nonnull mu,\n                                 const absl::Condition& cond,\n                                 absl::Time deadline) = 0;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_CLOCK_INTERFACE_H_\n"
  },
  {
    "path": "absl/time/clock_interface_test.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/clock_interface.h\"\n\n#include <cstdint>\n#include <functional>\n#include <thread>  // NOLINT(build/c++11)\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/functional/bind_front.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/synchronization/notification.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace {\n\nconstexpr absl::Duration kLongPause = absl::Milliseconds(150);\n\n#ifdef _MSC_VER\n// As of 2026-01-29, multithreaded tests on MSVC are too flaky.\nconst char* kSkipFlakyReason =\n    \"Skipping this timing test because it is too flaky\";\n#else\nconst char* kSkipFlakyReason = nullptr;\n#endif\n\n\nvoid AwaitWithDeadlineAndNotify(absl::Clock* clock, absl::Mutex* mu,\n                                absl::Condition* cond, absl::Time wakeup_time,\n                                absl::Notification* note, bool* return_val) {\n  mu->lock_shared();\n  *return_val = clock->AwaitWithDeadline(mu, *cond, wakeup_time);\n  mu->unlock_shared();\n  note->Notify();\n}\n\nTEST(RealClockTest, AwaitWithVeryLargeDeadline) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::Clock& clock = absl::Clock::GetRealClock();\n  absl::Mutex mu;\n  bool f = false;\n  absl::Condition cond(&f);\n  absl::Notification note;\n  bool return_val;\n\n  std::thread thread(AwaitWithDeadlineAndNotify, &clock, &mu, &cond,\n                     absl::InfiniteFuture(), &note, &return_val);\n\n  EXPECT_FALSE(note.HasBeenNotified());\n\n  mu.lock();\n  f = true;\n  mu.unlock();\n\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  EXPECT_TRUE(return_val);\n  note.WaitForNotification();  // In case the expectation fails.\n  thread.join();\n}\n\nTEST(RealClockTest, AwaitWithPastDeadline) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::Clock& clock = absl::Clock::GetRealClock();\n  absl::Mutex mu;\n  bool f = false;\n  absl::Condition cond(&f);\n  absl::Notification note;\n  bool return_val;\n\n  std::thread thread(AwaitWithDeadlineAndNotify, &clock, &mu, &cond,\n                     clock.TimeNow() - absl::Seconds(10), &note, &return_val);\n  absl::Time start = absl::Now();\n  note.WaitForNotification();  // AwaitWithDeadline() should ping note.\n  EXPECT_GE(kLongPause, absl::Now() - start);\n  EXPECT_FALSE(return_val);\n  thread.join();\n}\n\nTEST(RealClockTest, AwaitWithSmallDeadline) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::Clock& clock = absl::Clock::GetRealClock();\n  absl::Mutex mu;\n  bool f = false;\n  absl::Condition cond(&f);\n\n  for (int i = 0; i < 5; ++i) {\n    absl::Duration wait_time = absl::Milliseconds(i);\n    absl::Duration elapsed_time;\n    {\n      absl::MutexLock lock(mu);\n      absl::Time start = clock.TimeNow();\n      absl::Time wakeup_time = start + wait_time;\n      EXPECT_FALSE(clock.AwaitWithDeadline(&mu, cond, wakeup_time));\n      elapsed_time = clock.TimeNow() - start;\n    }\n    if (elapsed_time >= absl::ZeroDuration()) {  // ignore jumps backwards\n      // 60 microseconds of slop to allow for non-monotonic clocks.\n      EXPECT_GE(elapsed_time, wait_time - absl::Microseconds(60));\n    }\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/clock_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/clock.h\"\n\n#include \"absl/base/config.h\"\n#if defined(ABSL_HAVE_ALARM)\n#include <signal.h>\n#include <unistd.h>\n#ifdef _AIX\n// sig_t is not defined in AIX.\ntypedef void (*sig_t)(int);\n#endif\n#elif defined(__linux__) || defined(__APPLE__)\n#error all known Linux and Apple targets have alarm\n#endif\n\n#include \"gtest/gtest.h\"\n#include \"absl/time/time.h\"\n\nnamespace {\n\nTEST(Time, Now) {\n  const absl::Time before = absl::FromUnixNanos(absl::GetCurrentTimeNanos());\n  const absl::Time now = absl::Now();\n  const absl::Time after = absl::FromUnixNanos(absl::GetCurrentTimeNanos());\n  EXPECT_GE(now, before);\n  EXPECT_GE(after, now);\n}\n\nenum class AlarmPolicy { kWithoutAlarm, kWithAlarm };\n\n#if defined(ABSL_HAVE_ALARM)\nbool alarm_handler_invoked = false;\n\nvoid AlarmHandler(int signo) {\n  ASSERT_EQ(signo, SIGALRM);\n  alarm_handler_invoked = true;\n}\n#endif\n\n// Does SleepFor(d) take between lower_bound and upper_bound at least\n// once between now and (now + timeout)?  If requested (and supported),\n// add an alarm for the middle of the sleep period and expect it to fire.\nbool SleepForBounded(absl::Duration d, absl::Duration lower_bound,\n                     absl::Duration upper_bound, absl::Duration timeout,\n                     AlarmPolicy alarm_policy, int* attempts) {\n  const absl::Time deadline = absl::Now() + timeout;\n  while (absl::Now() < deadline) {\n#if defined(ABSL_HAVE_ALARM)\n    sig_t old_alarm = SIG_DFL;\n    if (alarm_policy == AlarmPolicy::kWithAlarm) {\n      alarm_handler_invoked = false;\n      old_alarm = signal(SIGALRM, AlarmHandler);\n      alarm(absl::ToInt64Seconds(d / 2));\n    }\n#else\n    EXPECT_EQ(alarm_policy, AlarmPolicy::kWithoutAlarm);\n#endif\n    ++*attempts;\n    absl::Time start = absl::Now();\n    absl::SleepFor(d);\n    absl::Duration actual = absl::Now() - start;\n#if defined(ABSL_HAVE_ALARM)\n    if (alarm_policy == AlarmPolicy::kWithAlarm) {\n      signal(SIGALRM, old_alarm);\n      if (!alarm_handler_invoked) continue;\n    }\n#endif\n    if (lower_bound <= actual && actual <= upper_bound) {\n      return true;  // yes, the SleepFor() was correctly bounded\n    }\n  }\n  return false;\n}\n\ntesting::AssertionResult AssertSleepForBounded(absl::Duration d,\n                                               absl::Duration early,\n                                               absl::Duration late,\n                                               absl::Duration timeout,\n                                               AlarmPolicy alarm_policy) {\n  const absl::Duration lower_bound = d - early;\n  const absl::Duration upper_bound = d + late;\n  int attempts = 0;\n  if (SleepForBounded(d, lower_bound, upper_bound, timeout, alarm_policy,\n                      &attempts)) {\n    return testing::AssertionSuccess();\n  }\n  return testing::AssertionFailure()\n         << \"SleepFor(\" << d << \") did not return within [\" << lower_bound\n         << \":\" << upper_bound << \"] in \" << attempts << \" attempt\"\n         << (attempts == 1 ? \"\" : \"s\") << \" over \" << timeout\n         << (alarm_policy == AlarmPolicy::kWithAlarm ? \" with\" : \" without\")\n         << \" an alarm\";\n}\n\n// Tests that SleepFor() returns neither too early nor too late.\nTEST(SleepFor, Bounded) {\n  const absl::Duration d = absl::Milliseconds(2500);\n  const absl::Duration early = absl::Milliseconds(100);\n  const absl::Duration late = absl::Milliseconds(300);\n  const absl::Duration timeout = 48 * d;\n  EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout,\n                                    AlarmPolicy::kWithoutAlarm));\n#if defined(ABSL_HAVE_ALARM)\n  EXPECT_TRUE(\n      AssertSleepForBounded(d, early, late, timeout, AlarmPolicy::kWithAlarm));\n#endif\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/duration.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// The implementation of the absl::Duration class, which is declared in\n// //absl/time.h.  This class behaves like a numeric type; it has no public\n// methods and is used only through the operators defined here.\n//\n// Implementation notes:\n//\n// An absl::Duration is represented as\n//\n//   rep_hi_ : (int64_t)  Whole seconds\n//   rep_lo_ : (uint32_t) Fractions of a second\n//\n// The seconds value (rep_hi_) may be positive or negative as appropriate.\n// The fractional seconds (rep_lo_) is always a positive offset from rep_hi_.\n// The API for Duration guarantees at least nanosecond resolution, which\n// means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds.\n// However, to utilize more of the available 32 bits of space in rep_lo_,\n// we instead store quarters of a nanosecond in rep_lo_ resulting in a max\n// value of 4B - 1.  This allows us to correctly handle calculations like\n// 0.5 nanos + 0.5 nanos = 1 nano.  The following example shows the actual\n// Duration rep using quarters of a nanosecond.\n//\n//    2.5 sec = {rep_hi_=2,  rep_lo_=2000000000}  // lo = 4 * 500000000\n//   -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000}\n//\n// Infinite durations are represented as Durations with the rep_lo_ field set\n// to all 1s.\n//\n//   +InfiniteDuration:\n//     rep_hi_ : kint64max\n//     rep_lo_ : ~0U\n//\n//   -InfiniteDuration:\n//     rep_hi_ : kint64min\n//     rep_lo_ : ~0U\n//\n// Arithmetic overflows/underflows to +/- infinity and saturates.\n\n#if defined(_MSC_VER)\n#include <winsock2.h>  // for timeval\n#endif\n\n#include <algorithm>\n#include <cassert>\n#include <chrono>  // NOLINT(build/c++11)\n#include <cmath>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <ctime>\n#include <functional>\n#include <limits>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/casts.h\"\n#include \"absl/base/config.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/strings/strip.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\nusing time_internal::kTicksPerNanosecond;\nusing time_internal::kTicksPerSecond;\n\nconstexpr int64_t kint64max = std::numeric_limits<int64_t>::max();\nconstexpr int64_t kint64min = std::numeric_limits<int64_t>::min();\n\n// Can't use std::isinfinite() because it doesn't exist on windows.\ninline bool IsFinite(double d) {\n  if (std::isnan(d)) return false;\n  return d != std::numeric_limits<double>::infinity() &&\n         d != -std::numeric_limits<double>::infinity();\n}\n\ninline bool IsValidDivisor(double d) {\n  if (std::isnan(d)) return false;\n  return d != 0.0;\n}\n\n// *sec may be positive or negative.  *ticks must be in the range\n// -kTicksPerSecond < *ticks < kTicksPerSecond.  If *ticks is negative it\n// will be normalized to a positive value by adjusting *sec accordingly.\ninline void NormalizeTicks(int64_t* sec, int64_t* ticks) {\n  if (*ticks < 0) {\n    --*sec;\n    *ticks += kTicksPerSecond;\n  }\n}\n\n// Makes a uint128 from the absolute value of the given scalar.\ninline uint128 MakeU128(int64_t a) {\n  uint128 u128 = 0;\n  if (a < 0) {\n    ++u128;\n    ++a;  // Makes it safe to negate 'a'\n    a = -a;\n  }\n  u128 += static_cast<uint64_t>(a);\n  return u128;\n}\n\n// Makes a uint128 count of ticks out of the absolute value of the Duration.\ninline uint128 MakeU128Ticks(Duration d) {\n  int64_t rep_hi = time_internal::GetRepHi(d);\n  uint32_t rep_lo = time_internal::GetRepLo(d);\n  if (rep_hi < 0) {\n    ++rep_hi;\n    rep_hi = -rep_hi;\n    rep_lo = kTicksPerSecond - rep_lo;\n  }\n  uint128 u128 = static_cast<uint64_t>(rep_hi);\n  u128 *= static_cast<uint64_t>(kTicksPerSecond);\n  u128 += rep_lo;\n  return u128;\n}\n\n// Breaks a uint128 of ticks into a Duration.\ninline Duration MakeDurationFromU128(uint128 u128, bool is_neg) {\n  int64_t rep_hi;\n  uint32_t rep_lo;\n  const uint64_t h64 = Uint128High64(u128);\n  const uint64_t l64 = Uint128Low64(u128);\n  if (h64 == 0) {  // fastpath\n    const uint64_t hi = l64 / kTicksPerSecond;\n    rep_hi = static_cast<int64_t>(hi);\n    rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond);\n  } else {\n    // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond).\n    // Any positive tick count whose high 64 bits are >= kMaxRepHi64\n    // is not representable as a Duration.  A negative tick count can\n    // have its high 64 bits == kMaxRepHi64 but only when the low 64\n    // bits are all zero, otherwise it is not representable either.\n    const uint64_t kMaxRepHi64 = 0x77359400UL;\n    if (h64 >= kMaxRepHi64) {\n      if (is_neg && h64 == kMaxRepHi64 && l64 == 0) {\n        // Avoid trying to represent -kint64min below.\n        return time_internal::MakeDuration(kint64min);\n      }\n      return is_neg ? -InfiniteDuration() : InfiniteDuration();\n    }\n    const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond);\n    const uint128 hi = u128 / kTicksPerSecond128;\n    rep_hi = static_cast<int64_t>(Uint128Low64(hi));\n    rep_lo =\n        static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128));\n  }\n  if (is_neg) {\n    rep_hi = -rep_hi;\n    if (rep_lo != 0) {\n      --rep_hi;\n      rep_lo = kTicksPerSecond - rep_lo;\n    }\n  }\n  return time_internal::MakeDuration(rep_hi, rep_lo);\n}\n\n// Convert between int64_t and uint64_t, preserving representation. This\n// allows us to do arithmetic in the unsigned domain, where overflow has\n// well-defined behavior. See operator+=() and operator-=().\n//\n// C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, \"The typedef\n// name intN_t designates a signed integer type with width N, no padding\n// bits, and a two's complement representation.\" So, we can convert to\n// and from the corresponding uint64_t value using a bit cast.\ninline uint64_t EncodeTwosComp(int64_t v) {\n  return absl::bit_cast<uint64_t>(v);\n}\ninline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); }\n\n// Note: The overflow detection in this function is done using greater/less *or\n// equal* because kint64max/min is too large to be represented exactly in a\n// double (which only has 53 bits of precision). In order to avoid assigning to\n// rep->hi a double value that is too large for an int64_t (and therefore is\n// undefined), we must consider computations that equal kint64max/min as a\n// double as overflow cases.\ninline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) {\n  double c = a_hi + b_hi;\n  if (c >= static_cast<double>(kint64max)) {\n    *d = InfiniteDuration();\n    return false;\n  }\n  if (c <= static_cast<double>(kint64min)) {\n    *d = -InfiniteDuration();\n    return false;\n  }\n  *d = time_internal::MakeDuration(static_cast<int64_t>(c),\n                                   time_internal::GetRepLo(*d));\n  return true;\n}\n\n// A functor that's similar to std::multiplies<T>, except this returns the max\n// T value instead of overflowing. This is only defined for uint128.\ntemplate <typename Ignored>\nstruct SafeMultiply {\n  uint128 operator()(uint128 a, uint128 b) const {\n    // b hi is always zero because it originated as an int64_t.\n    assert(Uint128High64(b) == 0);\n    // Fastpath to avoid the expensive overflow check with division.\n    if (Uint128High64(a) == 0) {\n      return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0)\n                 ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b))\n                 : a * b;\n    }\n    return b == 0 ? b : (a > Uint128Max() / b) ? Uint128Max() : a * b;\n  }\n};\n\n// Scales (i.e., multiplies or divides, depending on the Operation template)\n// the Duration d by the int64_t r.\ntemplate <template <typename> class Operation>\ninline Duration ScaleFixed(Duration d, int64_t r) {\n  const uint128 a = MakeU128Ticks(d);\n  const uint128 b = MakeU128(r);\n  const uint128 q = Operation<uint128>()(a, b);\n  const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0);\n  return MakeDurationFromU128(q, is_neg);\n}\n\n// Scales (i.e., multiplies or divides, depending on the Operation template)\n// the Duration d by the double r.\ntemplate <template <typename> class Operation>\ninline Duration ScaleDouble(Duration d, double r) {\n  Operation<double> op;\n  double hi_doub = op(static_cast<double>(time_internal::GetRepHi(d)), r);\n  double lo_doub = op(static_cast<double>(time_internal::GetRepLo(d)), r);\n\n  double hi_int = 0;\n  double hi_frac = std::modf(hi_doub, &hi_int);\n\n  // Moves hi's fractional bits to lo.\n  lo_doub /= kTicksPerSecond;\n  lo_doub += hi_frac;\n\n  double lo_int = 0;\n  double lo_frac = std::modf(lo_doub, &lo_int);\n\n  // Rolls lo into hi if necessary.\n  int64_t lo64 = static_cast<int64_t>(std::round(lo_frac * kTicksPerSecond));\n\n  Duration ans;\n  if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans;\n  int64_t hi64 = time_internal::GetRepHi(ans);\n  if (!SafeAddRepHi(static_cast<double>(hi64),\n                    static_cast<double>(lo64 / kTicksPerSecond), &ans)) {\n    return ans;\n  }\n  hi64 = time_internal::GetRepHi(ans);\n  lo64 %= kTicksPerSecond;\n  NormalizeTicks(&hi64, &lo64);\n  return time_internal::MakeDuration(hi64, lo64);\n}\n\n// Tries to divide num by den as fast as possible by looking for common, easy\n// cases. If the division was done, the quotient is in *q and the remainder is\n// in *rem and true will be returned.\ninline bool IDivFastPath(const Duration num, const Duration den, int64_t* q,\n                         Duration* rem) {\n  // Bail if num or den is an infinity.\n  if (time_internal::IsInfiniteDuration(num) ||\n      time_internal::IsInfiniteDuration(den))\n    return false;\n\n  int64_t num_hi = time_internal::GetRepHi(num);\n  uint32_t num_lo = time_internal::GetRepLo(num);\n  int64_t den_hi = time_internal::GetRepHi(den);\n  uint32_t den_lo = time_internal::GetRepLo(den);\n\n  if (den_hi == 0) {\n    if (den_lo == kTicksPerNanosecond) {\n      // Dividing by 1ns\n      if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) {\n        *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond;\n        *rem = time_internal::MakeDuration(0, num_lo % den_lo);\n        return true;\n      }\n    } else if (den_lo == 100 * kTicksPerNanosecond) {\n      // Dividing by 100ns (common when converting to Universal time)\n      if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) {\n        *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond);\n        *rem = time_internal::MakeDuration(0, num_lo % den_lo);\n        return true;\n      }\n    } else if (den_lo == 1000 * kTicksPerNanosecond) {\n      // Dividing by 1us\n      if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) {\n        *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond);\n        *rem = time_internal::MakeDuration(0, num_lo % den_lo);\n        return true;\n      }\n    } else if (den_lo == 1000000 * kTicksPerNanosecond) {\n      // Dividing by 1ms\n      if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) {\n        *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond);\n        *rem = time_internal::MakeDuration(0, num_lo % den_lo);\n        return true;\n      }\n    }\n  } else if (den_hi > 0 && den_lo == 0) {\n    // Dividing by positive multiple of 1s\n    if (num_hi >= 0) {\n      if (den_hi == 1) {\n        *q = num_hi;\n        *rem = time_internal::MakeDuration(0, num_lo);\n        return true;\n      }\n      *q = num_hi / den_hi;\n      *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo);\n      return true;\n    }\n    if (num_lo != 0) {\n      num_hi += 1;\n    }\n    int64_t quotient = num_hi / den_hi;\n    int64_t rem_sec = num_hi % den_hi;\n    if (rem_sec > 0) {\n      rem_sec -= den_hi;\n      quotient += 1;\n    }\n    if (num_lo != 0) {\n      rem_sec -= 1;\n    }\n    *q = quotient;\n    *rem = time_internal::MakeDuration(rem_sec, num_lo);\n    return true;\n  }\n\n  return false;\n}\n\n}  // namespace\n\nnamespace {\n\nint64_t IDivSlowPath(bool satq, const Duration num, const Duration den,\n                     Duration* rem) {\n  const bool num_neg = num < ZeroDuration();\n  const bool den_neg = den < ZeroDuration();\n  const bool quotient_neg = num_neg != den_neg;\n\n  if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {\n    *rem = num_neg ? -InfiniteDuration() : InfiniteDuration();\n    return quotient_neg ? kint64min : kint64max;\n  }\n  if (time_internal::IsInfiniteDuration(den)) {\n    *rem = num;\n    return 0;\n  }\n\n  const uint128 a = MakeU128Ticks(num);\n  const uint128 b = MakeU128Ticks(den);\n  uint128 quotient128 = a / b;\n\n  if (satq) {\n    // Limits the quotient to the range of int64_t.\n    if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) {\n      quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min))\n                                 : uint128(static_cast<uint64_t>(kint64max));\n    }\n  }\n\n  const uint128 remainder128 = a - quotient128 * b;\n  *rem = MakeDurationFromU128(remainder128, num_neg);\n\n  if (!quotient_neg || quotient128 == 0) {\n    return Uint128Low64(quotient128) & kint64max;\n  }\n  // The quotient needs to be negated, but we need to carefully handle\n  // quotient128s with the top bit on.\n  return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1;\n}\n\n// The 'satq' argument indicates whether the quotient should saturate at the\n// bounds of int64_t.  If it does saturate, the difference will spill over to\n// the remainder.  If it does not saturate, the remainder remain accurate,\n// but the returned quotient will over/underflow int64_t and should not be used.\nABSL_ATTRIBUTE_ALWAYS_INLINE inline int64_t IDivDurationImpl(bool satq,\n                                                             const Duration num,\n                                                             const Duration den,\n                                                             Duration* rem) {\n  int64_t q = 0;\n  if (IDivFastPath(num, den, &q, rem)) {\n    return q;\n  }\n  return IDivSlowPath(satq, num, den, rem);\n}\n\n}  // namespace\n\nint64_t IDivDuration(Duration num, Duration den, Duration* rem) {\n  return IDivDurationImpl(true, num, den,\n                          rem);  // trunc towards zero\n}\n\n//\n// Additive operators.\n//\n\nDuration& Duration::operator+=(Duration rhs) {\n  if (time_internal::IsInfiniteDuration(*this)) return *this;\n  if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs;\n  const int64_t orig_rep_hi = rep_hi_.Get();\n  rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) +\n                           EncodeTwosComp(rhs.rep_hi_.Get()));\n  if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) {\n    rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) + 1);\n    rep_lo_ -= kTicksPerSecond;\n  }\n  rep_lo_ += rhs.rep_lo_;\n  if (rhs.rep_hi_.Get() < 0 ? rep_hi_.Get() > orig_rep_hi\n                            : rep_hi_.Get() < orig_rep_hi) {\n    return *this =\n               rhs.rep_hi_.Get() < 0 ? -InfiniteDuration() : InfiniteDuration();\n  }\n  return *this;\n}\n\nDuration& Duration::operator-=(Duration rhs) {\n  if (time_internal::IsInfiniteDuration(*this)) return *this;\n  if (time_internal::IsInfiniteDuration(rhs)) {\n    return *this = rhs.rep_hi_.Get() >= 0 ? -InfiniteDuration()\n                                          : InfiniteDuration();\n  }\n  const int64_t orig_rep_hi = rep_hi_.Get();\n  rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) -\n                           EncodeTwosComp(rhs.rep_hi_.Get()));\n  if (rep_lo_ < rhs.rep_lo_) {\n    rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) - 1);\n    rep_lo_ += kTicksPerSecond;\n  }\n  rep_lo_ -= rhs.rep_lo_;\n  if (rhs.rep_hi_.Get() < 0 ? rep_hi_.Get() < orig_rep_hi\n                            : rep_hi_.Get() > orig_rep_hi) {\n    return *this = rhs.rep_hi_.Get() >= 0 ? -InfiniteDuration()\n                                          : InfiniteDuration();\n  }\n  return *this;\n}\n\n//\n// Multiplicative operators.\n//\n\nDuration& Duration::operator*=(int64_t r) {\n  if (time_internal::IsInfiniteDuration(*this)) {\n    const bool is_neg = (r < 0) != (rep_hi_.Get() < 0);\n    return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();\n  }\n  return *this = ScaleFixed<SafeMultiply>(*this, r);\n}\n\nDuration& Duration::operator*=(double r) {\n  if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) {\n    const bool is_neg = std::isnan(r) || std::signbit(r) != (rep_hi_.Get() < 0);\n    return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();\n  }\n  return *this = ScaleDouble<std::multiplies>(*this, r);\n}\n\nDuration& Duration::operator/=(int64_t r) {\n  if (time_internal::IsInfiniteDuration(*this) || r == 0) {\n    const bool is_neg = (r < 0) != (rep_hi_.Get() < 0);\n    return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();\n  }\n  return *this = ScaleFixed<std::divides>(*this, r);\n}\n\nDuration& Duration::operator/=(double r) {\n  if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) {\n    const bool is_neg = std::isnan(r) || std::signbit(r) != (rep_hi_.Get() < 0);\n    return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();\n  }\n  return *this = ScaleDouble<std::divides>(*this, r);\n}\n\nDuration& Duration::operator%=(Duration rhs) {\n  IDivDurationImpl(false, *this, rhs, this);\n  return *this;\n}\n\ndouble FDivDuration(Duration num, Duration den) {\n  // Arithmetic with infinity is sticky.\n  if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {\n    return (num < ZeroDuration()) == (den < ZeroDuration())\n               ? std::numeric_limits<double>::infinity()\n               : -std::numeric_limits<double>::infinity();\n  }\n  if (time_internal::IsInfiniteDuration(den)) return 0.0;\n\n  double a =\n      static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond +\n      time_internal::GetRepLo(num);\n  double b =\n      static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond +\n      time_internal::GetRepLo(den);\n  return a / b;\n}\n\n//\n// Trunc/Floor/Ceil.\n//\n\nDuration Trunc(Duration d, Duration unit) { return d - (d % unit); }\n\nDuration Floor(const Duration d, const Duration unit) {\n  const absl::Duration td = Trunc(d, unit);\n  return td <= d ? td : td - AbsDuration(unit);\n}\n\nDuration Ceil(const Duration d, const Duration unit) {\n  const absl::Duration td = Trunc(d, unit);\n  return td >= d ? td : td + AbsDuration(unit);\n}\n\n//\n// Factory functions.\n//\n\nDuration DurationFromTimespec(timespec ts) {\n  if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) {\n    int64_t ticks = ts.tv_nsec * kTicksPerNanosecond;\n    return time_internal::MakeDuration(ts.tv_sec, ticks);\n  }\n  return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec);\n}\n\nDuration DurationFromTimeval(timeval tv) {\n  if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) {\n    int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond;\n    return time_internal::MakeDuration(tv.tv_sec, ticks);\n  }\n  return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec);\n}\n\n//\n// Conversion to other duration types.\n//\ndouble ToDoubleNanoseconds(Duration d) {\n  return FDivDuration(d, Nanoseconds(1));\n}\ndouble ToDoubleMicroseconds(Duration d) {\n  return FDivDuration(d, Microseconds(1));\n}\ndouble ToDoubleMilliseconds(Duration d) {\n  return FDivDuration(d, Milliseconds(1));\n}\ndouble ToDoubleSeconds(Duration d) { return FDivDuration(d, Seconds(1)); }\ndouble ToDoubleMinutes(Duration d) { return FDivDuration(d, Minutes(1)); }\ndouble ToDoubleHours(Duration d) { return FDivDuration(d, Hours(1)); }\n\ntimespec ToTimespec(Duration d) {\n  timespec ts;\n  if (!time_internal::IsInfiniteDuration(d)) {\n    int64_t rep_hi = time_internal::GetRepHi(d);\n    uint32_t rep_lo = time_internal::GetRepLo(d);\n    if (rep_hi < 0) {\n      // Tweak the fields so that unsigned division of rep_lo\n      // maps to truncation (towards zero) for the timespec.\n      rep_lo += kTicksPerNanosecond - 1;\n      if (rep_lo >= kTicksPerSecond) {\n        rep_hi += 1;\n        rep_lo -= kTicksPerSecond;\n      }\n    }\n    ts.tv_sec = static_cast<decltype(ts.tv_sec)>(rep_hi);\n    if (ts.tv_sec == rep_hi) {  // no time_t narrowing\n      ts.tv_nsec = rep_lo / kTicksPerNanosecond;\n      return ts;\n    }\n  }\n  if (d >= ZeroDuration()) {\n    ts.tv_sec = std::numeric_limits<time_t>::max();\n    ts.tv_nsec = 1000 * 1000 * 1000 - 1;\n  } else {\n    ts.tv_sec = std::numeric_limits<time_t>::min();\n    ts.tv_nsec = 0;\n  }\n  return ts;\n}\n\ntimeval ToTimeval(Duration d) {\n  timeval tv;\n  timespec ts = ToTimespec(d);\n  if (ts.tv_sec < 0) {\n    // Tweak the fields so that positive division of tv_nsec\n    // maps to truncation (towards zero) for the timeval.\n    ts.tv_nsec += 1000 - 1;\n    if (ts.tv_nsec >= 1000 * 1000 * 1000) {\n      ts.tv_sec += 1;\n      ts.tv_nsec -= 1000 * 1000 * 1000;\n    }\n  }\n  tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);\n  if (tv.tv_sec != ts.tv_sec) {  // narrowing\n    if (ts.tv_sec < 0) {\n      tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();\n      tv.tv_usec = 0;\n    } else {\n      tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();\n      tv.tv_usec = 1000 * 1000 - 1;\n    }\n    return tv;\n  }\n  tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);  // suseconds_t\n  return tv;\n}\n\nstd::chrono::nanoseconds ToChronoNanoseconds(Duration d) {\n  return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d);\n}\nstd::chrono::microseconds ToChronoMicroseconds(Duration d) {\n  return time_internal::ToChronoDuration<std::chrono::microseconds>(d);\n}\nstd::chrono::milliseconds ToChronoMilliseconds(Duration d) {\n  return time_internal::ToChronoDuration<std::chrono::milliseconds>(d);\n}\nstd::chrono::seconds ToChronoSeconds(Duration d) {\n  return time_internal::ToChronoDuration<std::chrono::seconds>(d);\n}\nstd::chrono::minutes ToChronoMinutes(Duration d) {\n  return time_internal::ToChronoDuration<std::chrono::minutes>(d);\n}\nstd::chrono::hours ToChronoHours(Duration d) {\n  return time_internal::ToChronoDuration<std::chrono::hours>(d);\n}\n\n//\n// To/From string formatting.\n//\n\nnamespace {\n\n// Formats a positive 64-bit integer in the given field width.  Note that\n// it is up to the caller of Format64() to ensure that there is sufficient\n// space before ep to hold the conversion.\nchar* Format64(char* ep, int width, int64_t v) {\n  do {\n    --width;\n    *--ep = static_cast<char>('0' + (v % 10));  // contiguous digits\n  } while (v /= 10);\n  while (--width >= 0) *--ep = '0';  // zero pad\n  return ep;\n}\n\n// Helpers for FormatDuration() that format 'n' and append it to 'out'\n// followed by the given 'unit'.  If 'n' formats to \"0\", nothing is\n// appended (not even the unit).\n\n// A type that encapsulates how to display a value of a particular unit. For\n// values that are displayed with fractional parts, the precision indicates\n// where to round the value. The precision varies with the display unit because\n// a Duration can hold only quarters of a nanosecond, so displaying information\n// beyond that is just noise.\n//\n// For example, a microsecond value of 42.00025xxxxx should not display beyond 5\n// fractional digits, because it is in the noise of what a Duration can\n// represent.\nstruct DisplayUnit {\n  absl::string_view abbr;\n  int prec;\n  double pow10;\n};\nconstexpr DisplayUnit kDisplayNano = {\"ns\", 2, 1e2};\nconstexpr DisplayUnit kDisplayMicro = {\"us\", 5, 1e5};\nconstexpr DisplayUnit kDisplayMilli = {\"ms\", 8, 1e8};\nconstexpr DisplayUnit kDisplaySec = {\"s\", 11, 1e11};\nconstexpr DisplayUnit kDisplayMin = {\"m\", -1, 0.0};   // prec ignored\nconstexpr DisplayUnit kDisplayHour = {\"h\", -1, 0.0};  // prec ignored\n\nvoid AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {\n  char buf[sizeof(\"2562047788015216\")];  // hours in max duration\n  char* const ep = buf + sizeof(buf);\n  char* bp = Format64(ep, 0, n);\n  if (*bp != '0' || bp + 1 != ep) {\n    out->append(bp, static_cast<size_t>(ep - bp));\n    out->append(unit.abbr.data(), unit.abbr.size());\n  }\n}\n\n// Note: unit.prec is limited to double's digits10 value (typically 15) so it\n// always fits in buf[].\nvoid AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {\n  constexpr int kBufferSize = std::numeric_limits<double>::digits10;\n  const int prec = std::min(kBufferSize, unit.prec);\n  char buf[kBufferSize];  // also large enough to hold integer part\n  char* ep = buf + sizeof(buf);\n  double d = 0;\n  int64_t frac_part =\n      static_cast<int64_t>(std::round(std::modf(n, &d) * unit.pow10));\n  int64_t int_part = static_cast<int64_t>(d);\n  if (int_part != 0 || frac_part != 0) {\n    char* bp = Format64(ep, 0, int_part);  // always < 1000\n    out->append(bp, static_cast<size_t>(ep - bp));\n    if (frac_part != 0) {\n      out->push_back('.');\n      bp = Format64(ep, prec, frac_part);\n      while (ep[-1] == '0') --ep;\n      out->append(bp, static_cast<size_t>(ep - bp));\n    }\n    out->append(unit.abbr.data(), unit.abbr.size());\n  }\n}\n\n}  // namespace\n\n// From Go's doc at https://golang.org/pkg/time/#Duration.String\n//   [FormatDuration] returns a string representing the duration in the\n//   form \"72h3m0.5s\". Leading zero units are omitted.  As a special\n//   case, durations less than one second format use a smaller unit\n//   (milli-, micro-, or nanoseconds) to ensure that the leading digit\n//   is non-zero.\n// Unlike Go, we format the zero duration as 0, with no unit.\nstd::string FormatDuration(Duration d) {\n  constexpr Duration kMinDuration = Seconds(kint64min);\n  std::string s;\n  if (d == kMinDuration) {\n    // Avoid needing to negate kint64min by directly returning what the\n    // following code should produce in that case.\n    s = \"-2562047788015215h30m8s\";\n    return s;\n  }\n  if (d < ZeroDuration()) {\n    s.append(\"-\");\n    d = -d;\n  }\n  if (d == InfiniteDuration()) {\n    s.append(\"inf\");\n  } else if (d < Seconds(1)) {\n    // Special case for durations with a magnitude < 1 second.  The duration\n    // is printed as a fraction of a single unit, e.g., \"1.2ms\".\n    if (d < Microseconds(1)) {\n      AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano);\n    } else if (d < Milliseconds(1)) {\n      AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro);\n    } else {\n      AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli);\n    }\n  } else {\n    AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour);\n    AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin);\n    AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec);\n  }\n  if (s.empty() || s == \"-\") {\n    s = \"0\";\n  }\n  return s;\n}\n\nnamespace {\n\n// A helper for ParseDuration() that parses a leading number from the given\n// string and stores the result in *int_part/*frac_part/*frac_scale.  The\n// given string pointer is modified to point to the first unconsumed char.\nbool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part,\n                           int64_t* frac_part, int64_t* frac_scale) {\n  *int_part = 0;\n  *frac_part = 0;\n  *frac_scale = 1;  // invariant: *frac_part < *frac_scale\n  const char* start = *dpp;\n  for (; *dpp != ep; *dpp += 1) {\n    const int d = **dpp - '0';  // contiguous digits\n    if (d < 0 || 10 <= d) break;\n\n    if (*int_part > kint64max / 10) return false;\n    *int_part *= 10;\n    if (*int_part > kint64max - d) return false;\n    *int_part += d;\n  }\n  const bool int_part_empty = (*dpp == start);\n  if (*dpp == ep || **dpp != '.') return !int_part_empty;\n\n  for (*dpp += 1; *dpp != ep; *dpp += 1) {\n    const int d = **dpp - '0';  // contiguous digits\n    if (d < 0 || 10 <= d) break;\n    if (*frac_scale <= kint64max / 10) {\n      *frac_part *= 10;\n      *frac_part += d;\n      *frac_scale *= 10;\n    }\n  }\n  return !int_part_empty || *frac_scale != 1;\n}\n\n// A helper for ParseDuration() that parses a leading unit designator (e.g.,\n// ns, us, ms, s, m, h) from the given string and stores the resulting unit\n// in \"*unit\".  The given string pointer is modified to point to the first\n// unconsumed char.\nbool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) {\n  size_t size = static_cast<size_t>(end - *start);\n  switch (size) {\n    case 0:\n      return false;\n    default:\n      switch (**start) {\n        case 'n':\n          if (*(*start + 1) == 's') {\n            *start += 2;\n            *unit = Nanoseconds(1);\n            return true;\n          }\n          break;\n        case 'u':\n          if (*(*start + 1) == 's') {\n            *start += 2;\n            *unit = Microseconds(1);\n            return true;\n          }\n          break;\n        case 'm':\n          if (*(*start + 1) == 's') {\n            *start += 2;\n            *unit = Milliseconds(1);\n            return true;\n          }\n          break;\n        default:\n          break;\n      }\n      ABSL_FALLTHROUGH_INTENDED;\n    case 1:\n      switch (**start) {\n        case 's':\n          *unit = Seconds(1);\n          *start += 1;\n          return true;\n        case 'm':\n          *unit = Minutes(1);\n          *start += 1;\n          return true;\n        case 'h':\n          *unit = Hours(1);\n          *start += 1;\n          return true;\n        default:\n          return false;\n      }\n  }\n}\n\n}  // namespace\n\n// From Go's doc at https://golang.org/pkg/time/#ParseDuration\n//   [ParseDuration] parses a duration string. A duration string is\n//   a possibly signed sequence of decimal numbers, each with optional\n//   fraction and a unit suffix, such as \"300ms\", \"-1.5h\" or \"2h45m\".\n//   Valid time units are \"ns\", \"us\" \"ms\", \"s\", \"m\", \"h\".\nbool ParseDuration(absl::string_view dur_sv, Duration* d) {\n  int sign = 1;\n  if (absl::ConsumePrefix(&dur_sv, \"-\")) {\n    sign = -1;\n  } else {\n    absl::ConsumePrefix(&dur_sv, \"+\");\n  }\n  if (dur_sv.empty()) return false;\n\n  // Special case for a string of \"0\".\n  if (dur_sv == \"0\") {\n    *d = ZeroDuration();\n    return true;\n  }\n\n  if (dur_sv == \"inf\") {\n    *d = sign * InfiniteDuration();\n    return true;\n  }\n\n  const char* start = dur_sv.data();\n  const char* end = start + dur_sv.size();\n\n  Duration dur;\n  while (start != end) {\n    int64_t int_part;\n    int64_t frac_part;\n    int64_t frac_scale;\n    Duration unit;\n    if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part,\n                               &frac_scale) ||\n        !ConsumeDurationUnit(&start, end, &unit)) {\n      return false;\n    }\n    if (int_part != 0) dur += sign * int_part * unit;\n    if (frac_part != 0) dur += sign * frac_part * unit / frac_scale;\n  }\n  *d = dur;\n  return true;\n}\n\nbool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) {\n  return ParseDuration(text, dst);\n}\n\nstd::string AbslUnparseFlag(Duration d) { return FormatDuration(d); }\nbool ParseFlag(const std::string& text, Duration* dst, std::string* ) {\n  return ParseDuration(text, dst);\n}\n\nstd::string UnparseFlag(Duration d) { return FormatDuration(d); }\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/duration_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <ctime>\n#include <string>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/time/time.h\"\n#include \"benchmark/benchmark.h\"\n\nABSL_FLAG(absl::Duration, absl_duration_flag_for_benchmark,\n          absl::Milliseconds(1),\n          \"Flag to use for benchmarking duration flag access speed.\");\n\nnamespace {\n\n//\n// Factory functions\n//\n\nvoid BM_Duration_Factory_Nanoseconds(benchmark::State& state) {\n  int64_t i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Nanoseconds(i));\n    i += 314159;\n  }\n}\nBENCHMARK(BM_Duration_Factory_Nanoseconds);\n\nvoid BM_Duration_Factory_Microseconds(benchmark::State& state) {\n  int64_t i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Microseconds(i));\n    i += 314;\n  }\n}\nBENCHMARK(BM_Duration_Factory_Microseconds);\n\nvoid BM_Duration_Factory_Milliseconds(benchmark::State& state) {\n  int64_t i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Milliseconds(i));\n    i += 1;\n  }\n}\nBENCHMARK(BM_Duration_Factory_Milliseconds);\n\nvoid BM_Duration_Factory_Seconds(benchmark::State& state) {\n  int64_t i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Seconds(i));\n    i += 1;\n  }\n}\nBENCHMARK(BM_Duration_Factory_Seconds);\n\nvoid BM_Duration_Factory_Minutes(benchmark::State& state) {\n  int64_t i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Minutes(i));\n    i += 1;\n  }\n}\nBENCHMARK(BM_Duration_Factory_Minutes);\n\nvoid BM_Duration_Factory_Hours(benchmark::State& state) {\n  int64_t i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Hours(i));\n    i += 1;\n  }\n}\nBENCHMARK(BM_Duration_Factory_Hours);\n\nvoid BM_Duration_Factory_DoubleNanoseconds(benchmark::State& state) {\n  double d = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Nanoseconds(d));\n    d = d * 1.00000001 + 1;\n  }\n}\nBENCHMARK(BM_Duration_Factory_DoubleNanoseconds);\n\nvoid BM_Duration_Factory_DoubleMicroseconds(benchmark::State& state) {\n  double d = 1e-3;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Microseconds(d));\n    d = d * 1.00000001 + 1e-3;\n  }\n}\nBENCHMARK(BM_Duration_Factory_DoubleMicroseconds);\n\nvoid BM_Duration_Factory_DoubleMilliseconds(benchmark::State& state) {\n  double d = 1e-6;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Milliseconds(d));\n    d = d * 1.00000001 + 1e-6;\n  }\n}\nBENCHMARK(BM_Duration_Factory_DoubleMilliseconds);\n\nvoid BM_Duration_Factory_DoubleSeconds(benchmark::State& state) {\n  double d = 1e-9;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Seconds(d));\n    d = d * 1.00000001 + 1e-9;\n  }\n}\nBENCHMARK(BM_Duration_Factory_DoubleSeconds);\n\nvoid BM_Duration_Factory_DoubleMinutes(benchmark::State& state) {\n  double d = 1e-9;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Minutes(d));\n    d = d * 1.00000001 + 1e-9;\n  }\n}\nBENCHMARK(BM_Duration_Factory_DoubleMinutes);\n\nvoid BM_Duration_Factory_DoubleHours(benchmark::State& state) {\n  double d = 1e-9;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::Hours(d));\n    d = d * 1.00000001 + 1e-9;\n  }\n}\nBENCHMARK(BM_Duration_Factory_DoubleHours);\n\n//\n// Arithmetic\n//\n\nvoid BM_Duration_Addition(benchmark::State& state) {\n  absl::Duration d = absl::Nanoseconds(1);\n  absl::Duration step = absl::Milliseconds(1);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d += step);\n  }\n}\nBENCHMARK(BM_Duration_Addition);\n\nvoid BM_Duration_Subtraction(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(std::numeric_limits<int64_t>::max());\n  absl::Duration step = absl::Milliseconds(1);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d -= step);\n  }\n}\nBENCHMARK(BM_Duration_Subtraction);\n\nvoid BM_Duration_Multiplication_Fixed(benchmark::State& state) {\n  absl::Duration d = absl::Milliseconds(1);\n  absl::Duration s;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(s += d * (i + 1));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_Multiplication_Fixed);\n\nvoid BM_Duration_Multiplication_Double(benchmark::State& state) {\n  absl::Duration d = absl::Milliseconds(1);\n  absl::Duration s;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(s += d * (i + 1.0));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_Multiplication_Double);\n\nvoid BM_Duration_Division_Fixed(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(1);\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d /= i + 1);\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_Division_Fixed);\n\nvoid BM_Duration_Division_Double(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(1);\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d /= i + 1.0);\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_Division_Double);\n\nvoid BM_Duration_FDivDuration_Nanoseconds(benchmark::State& state) {\n  double d = 1;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        d += absl::FDivDuration(absl::Milliseconds(i), absl::Nanoseconds(1)));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_FDivDuration_Nanoseconds);\n\nvoid BM_Duration_IDivDuration_Nanoseconds(benchmark::State& state) {\n  int64_t a = 1;\n  absl::Duration ignore;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(a +=\n                             absl::IDivDuration(absl::Nanoseconds(i),\n                                                absl::Nanoseconds(1), &ignore));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_IDivDuration_Nanoseconds);\n\nvoid BM_Duration_IDivDuration_Microseconds(benchmark::State& state) {\n  int64_t a = 1;\n  absl::Duration ignore;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Microseconds(i),\n                                                     absl::Microseconds(1),\n                                                     &ignore));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_IDivDuration_Microseconds);\n\nvoid BM_Duration_IDivDuration_Milliseconds(benchmark::State& state) {\n  int64_t a = 1;\n  absl::Duration ignore;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(a += absl::IDivDuration(absl::Milliseconds(i),\n                                                     absl::Milliseconds(1),\n                                                     &ignore));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_IDivDuration_Milliseconds);\n\nvoid BM_Duration_IDivDuration_Seconds(benchmark::State& state) {\n  int64_t a = 1;\n  absl::Duration ignore;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        a += absl::IDivDuration(absl::Seconds(i), absl::Seconds(1), &ignore));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_IDivDuration_Seconds);\n\nvoid BM_Duration_IDivDuration_Minutes(benchmark::State& state) {\n  int64_t a = 1;\n  absl::Duration ignore;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        a += absl::IDivDuration(absl::Minutes(i), absl::Minutes(1), &ignore));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_IDivDuration_Minutes);\n\nvoid BM_Duration_IDivDuration_Hours(benchmark::State& state) {\n  int64_t a = 1;\n  absl::Duration ignore;\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        a += absl::IDivDuration(absl::Hours(i), absl::Hours(1), &ignore));\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_IDivDuration_Hours);\n\nvoid BM_Duration_Modulo(benchmark::State& state) {\n  int i = 0;\n  while (state.KeepRunning()) {\n    auto mod = absl::Seconds(i) % absl::Nanoseconds(12345);\n    benchmark::DoNotOptimize(mod);\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_Modulo);\n\nvoid BM_Duration_Modulo_FastPath(benchmark::State& state) {\n  int i = 0;\n  while (state.KeepRunning()) {\n    auto mod = absl::Seconds(i) % absl::Milliseconds(1);\n    benchmark::DoNotOptimize(mod);\n    ++i;\n  }\n}\nBENCHMARK(BM_Duration_Modulo_FastPath);\n\nvoid BM_Duration_ToInt64Nanoseconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToInt64Nanoseconds(d));\n  }\n}\nBENCHMARK(BM_Duration_ToInt64Nanoseconds);\n\nvoid BM_Duration_ToInt64Microseconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToInt64Microseconds(d));\n  }\n}\nBENCHMARK(BM_Duration_ToInt64Microseconds);\n\nvoid BM_Duration_ToInt64Milliseconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToInt64Milliseconds(d));\n  }\n}\nBENCHMARK(BM_Duration_ToInt64Milliseconds);\n\nvoid BM_Duration_ToInt64Seconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToInt64Seconds(d));\n  }\n}\nBENCHMARK(BM_Duration_ToInt64Seconds);\n\nvoid BM_Duration_ToInt64Minutes(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToInt64Minutes(d));\n  }\n}\nBENCHMARK(BM_Duration_ToInt64Minutes);\n\nvoid BM_Duration_ToInt64Hours(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToInt64Hours(d));\n  }\n}\nBENCHMARK(BM_Duration_ToInt64Hours);\n\n//\n// ToDoubleXYZ\n//\nvoid BM_Duration_ToDoubleNanoseconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d);\n    double result = absl::ToDoubleNanoseconds(d);\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleNanoseconds);\n\nvoid BM_Duration_ToDoubleMicroseconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d);\n    double result = absl::ToDoubleMicroseconds(d);\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleMicroseconds);\n\nvoid BM_Duration_ToDoubleMilliseconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d);\n    double result = absl::ToDoubleMilliseconds(d);\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleMilliseconds);\n\nvoid BM_Duration_ToDoubleSeconds(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d);\n    double result = absl::ToDoubleSeconds(d);\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleSeconds);\n\nvoid BM_Duration_ToDoubleMinutes(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d);\n    double result = absl::ToDoubleMinutes(d);\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleMinutes);\n\nvoid BM_Duration_ToDoubleHours(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(100000);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d);\n    double result = absl::ToDoubleHours(d);\n    benchmark::DoNotOptimize(result);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleHours);\n\n//\n// ToDoubleXYZ Latency\n//\nvoid BM_Duration_ToDoubleNanoseconds_Latency(benchmark::State& state) {\n  absl::Duration d1 = absl::Seconds(100000);\n  absl::Duration d2 = absl::Seconds(100000);\n  double result = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d1);\n    benchmark::DoNotOptimize(d2);\n    benchmark::DoNotOptimize(result);\n    result = absl::ToDoubleNanoseconds(result < 0 ? d1 : d2);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleNanoseconds_Latency);\n\nvoid BM_Duration_ToDoubleMicroseconds_Latency(benchmark::State& state) {\n  absl::Duration d1 = absl::Seconds(100000);\n  absl::Duration d2 = absl::Seconds(100000);\n  double result = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d1);\n    benchmark::DoNotOptimize(d2);\n    benchmark::DoNotOptimize(result);\n    result = absl::ToDoubleMicroseconds(result < 0 ? d1 : d2);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleMicroseconds_Latency);\n\nvoid BM_Duration_ToDoubleMilliseconds_Latency(benchmark::State& state) {\n  absl::Duration d1 = absl::Seconds(100000);\n  absl::Duration d2 = absl::Seconds(100000);\n  double result = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d1);\n    benchmark::DoNotOptimize(d2);\n    benchmark::DoNotOptimize(result);\n    result = absl::ToDoubleMilliseconds(result < 0 ? d1 : d2);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleMilliseconds_Latency);\n\nvoid BM_Duration_ToDoubleSeconds_Latency(benchmark::State& state) {\n  absl::Duration d1 = absl::Seconds(100000);\n  absl::Duration d2 = absl::Seconds(100000);\n  double result = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d1);\n    benchmark::DoNotOptimize(d2);\n    benchmark::DoNotOptimize(result);\n    result = absl::ToDoubleSeconds(result < 0 ? d1 : d2);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleSeconds_Latency);\n\nvoid BM_Duration_ToDoubleMinutes_Latency(benchmark::State& state) {\n  absl::Duration d1 = absl::Seconds(100000);\n  absl::Duration d2 = absl::Seconds(100000);\n  double result = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d1);\n    benchmark::DoNotOptimize(d2);\n    benchmark::DoNotOptimize(result);\n    result = absl::ToDoubleMinutes(result < 0 ? d1 : d2);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleMinutes_Latency);\n\nvoid BM_Duration_ToDoubleHours_Latency(benchmark::State& state) {\n  absl::Duration d1 = absl::Seconds(100000);\n  absl::Duration d2 = absl::Seconds(100000);\n  double result = 1;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(d1);\n    benchmark::DoNotOptimize(d2);\n    benchmark::DoNotOptimize(result);\n    result = absl::ToDoubleHours(result < 0 ? d1 : d2);\n  }\n}\nBENCHMARK(BM_Duration_ToDoubleHours_Latency);\n\n//\n// To/FromTimespec\n//\n\nvoid BM_Duration_ToTimespec_AbslTime(benchmark::State& state) {\n  absl::Duration d = absl::Seconds(1);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToTimespec(d));\n  }\n}\nBENCHMARK(BM_Duration_ToTimespec_AbslTime);\n\nABSL_ATTRIBUTE_NOINLINE timespec DoubleToTimespec(double seconds) {\n  timespec ts;\n  ts.tv_sec = seconds;\n  ts.tv_nsec = (seconds - ts.tv_sec) * (1000 * 1000 * 1000);\n  return ts;\n}\n\nvoid BM_Duration_ToTimespec_Double(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(DoubleToTimespec(1.0));\n  }\n}\nBENCHMARK(BM_Duration_ToTimespec_Double);\n\nvoid BM_Duration_FromTimespec_AbslTime(benchmark::State& state) {\n  timespec ts;\n  ts.tv_sec = 0;\n  ts.tv_nsec = 0;\n  while (state.KeepRunning()) {\n    if (++ts.tv_nsec == 1000 * 1000 * 1000) {\n      ++ts.tv_sec;\n      ts.tv_nsec = 0;\n    }\n    benchmark::DoNotOptimize(absl::DurationFromTimespec(ts));\n  }\n}\nBENCHMARK(BM_Duration_FromTimespec_AbslTime);\n\nABSL_ATTRIBUTE_NOINLINE double TimespecToDouble(timespec ts) {\n  return ts.tv_sec + (ts.tv_nsec / (1000 * 1000 * 1000));\n}\n\nvoid BM_Duration_FromTimespec_Double(benchmark::State& state) {\n  timespec ts;\n  ts.tv_sec = 0;\n  ts.tv_nsec = 0;\n  while (state.KeepRunning()) {\n    if (++ts.tv_nsec == 1000 * 1000 * 1000) {\n      ++ts.tv_sec;\n      ts.tv_nsec = 0;\n    }\n    benchmark::DoNotOptimize(TimespecToDouble(ts));\n  }\n}\nBENCHMARK(BM_Duration_FromTimespec_Double);\n\n//\n// String conversions\n//\n\nconst char* const kDurations[] = {\n    \"0\",                                   // 0\n    \"123ns\",                               // 1\n    \"1h2m3s\",                              // 2\n    \"-2h3m4.005006007s\",                   // 3\n    \"2562047788015215h30m7.99999999975s\",  // 4\n};\nconst int kNumDurations = sizeof(kDurations) / sizeof(kDurations[0]);\n\nvoid BM_Duration_FormatDuration(benchmark::State& state) {\n  const std::string s = kDurations[state.range(0)];\n  state.SetLabel(s);\n  absl::Duration d;\n  absl::ParseDuration(kDurations[state.range(0)], &d);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::FormatDuration(d));\n  }\n}\nBENCHMARK(BM_Duration_FormatDuration)->DenseRange(0, kNumDurations - 1);\n\nvoid BM_Duration_ParseDuration(benchmark::State& state) {\n  const std::string s = kDurations[state.range(0)];\n  state.SetLabel(s);\n  absl::Duration d;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ParseDuration(s, &d));\n  }\n}\nBENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1);\n\n//\n// Flag access\n//\nvoid BM_Duration_GetFlag(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        absl::GetFlag(FLAGS_absl_duration_flag_for_benchmark));\n  }\n}\nBENCHMARK(BM_Duration_GetFlag);\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/duration_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#if defined(_MSC_VER)\n#include <winsock2.h>  // for timeval\n#endif\n\n#include \"absl/base/config.h\"\n\n// For feature testing and determining which headers can be included.\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <version>\n#endif\n\n#include <array>\n#include <cfloat>\n#include <chrono>  // NOLINT(build/c++11)\n#ifdef __cpp_lib_three_way_comparison\n#include <compare>\n#endif  // __cpp_lib_three_way_comparison\n#include <cmath>\n#include <cstdint>\n#include <ctime>\n#include <iomanip>\n#include <limits>\n#include <random>\n#include <string>\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/random/random.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/time/time.h\"\n\nnamespace {\n\nconstexpr int64_t kint64max = std::numeric_limits<int64_t>::max();\nconstexpr int64_t kint64min = std::numeric_limits<int64_t>::min();\n\n// Approximates the given number of years. This is only used to make some test\n// code more readable.\nabsl::Duration ApproxYears(int64_t n) { return absl::Hours(n) * 365 * 24; }\n\n// A gMock matcher to match timespec values. Use this matcher like:\n// timespec ts1, ts2;\n// EXPECT_THAT(ts1, TimespecMatcher(ts2));\nMATCHER_P(TimespecMatcher, ts, \"\") {\n  if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) return true;\n  *result_listener << \"expected: {\" << ts.tv_sec << \", \" << ts.tv_nsec << \"} \";\n  *result_listener << \"actual: {\" << arg.tv_sec << \", \" << arg.tv_nsec << \"}\";\n  return false;\n}\n\n// A gMock matcher to match timeval values. Use this matcher like:\n// timeval tv1, tv2;\n// EXPECT_THAT(tv1, TimevalMatcher(tv2));\nMATCHER_P(TimevalMatcher, tv, \"\") {\n  if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) return true;\n  *result_listener << \"expected: {\" << tv.tv_sec << \", \" << tv.tv_usec << \"} \";\n  *result_listener << \"actual: {\" << arg.tv_sec << \", \" << arg.tv_usec << \"}\";\n  return false;\n}\n\nTEST(Duration, ConstExpr) {\n  static_assert(std::is_trivially_destructible<absl::Duration>::value,\n                \"Duration is documented as being trivially destructible\");\n  constexpr absl::Duration d0 = absl::ZeroDuration();\n  static_assert(d0 == absl::ZeroDuration(), \"ZeroDuration()\");\n  constexpr absl::Duration d1 = absl::Seconds(1);\n  static_assert(d1 == absl::Seconds(1), \"Seconds(1)\");\n  static_assert(d1 != absl::ZeroDuration(), \"Seconds(1)\");\n  constexpr absl::Duration d2 = absl::InfiniteDuration();\n  static_assert(d2 == absl::InfiniteDuration(), \"InfiniteDuration()\");\n  static_assert(d2 != absl::ZeroDuration(), \"InfiniteDuration()\");\n}\n\nTEST(Duration, ValueSemantics) {\n  // If this compiles, the test passes.\n  constexpr absl::Duration a;      // Default construction\n  constexpr absl::Duration b = a;  // Copy construction\n  constexpr absl::Duration c(b);   // Copy construction (again)\n\n  absl::Duration d;\n  d = c;  // Assignment\n}\n\nTEST(Duration, Factories) {\n  constexpr absl::Duration zero = absl::ZeroDuration();\n  constexpr absl::Duration nano = absl::Nanoseconds(1);\n  constexpr absl::Duration micro = absl::Microseconds(1);\n  constexpr absl::Duration milli = absl::Milliseconds(1);\n  constexpr absl::Duration sec = absl::Seconds(1);\n  constexpr absl::Duration min = absl::Minutes(1);\n  constexpr absl::Duration hour = absl::Hours(1);\n\n  EXPECT_EQ(zero, absl::Duration());\n  EXPECT_EQ(zero, absl::Seconds(0));\n  EXPECT_EQ(nano, absl::Nanoseconds(1));\n  EXPECT_EQ(micro, absl::Nanoseconds(1000));\n  EXPECT_EQ(milli, absl::Microseconds(1000));\n  EXPECT_EQ(sec, absl::Milliseconds(1000));\n  EXPECT_EQ(min, absl::Seconds(60));\n  EXPECT_EQ(hour, absl::Minutes(60));\n\n  // Tests factory limits\n  const absl::Duration inf = absl::InfiniteDuration();\n\n  EXPECT_GT(inf, absl::Seconds(kint64max));\n  EXPECT_LT(-inf, absl::Seconds(kint64min));\n  EXPECT_LT(-inf, absl::Seconds(-kint64max));\n\n  EXPECT_EQ(inf, absl::Minutes(kint64max));\n  EXPECT_EQ(-inf, absl::Minutes(kint64min));\n  EXPECT_EQ(-inf, absl::Minutes(-kint64max));\n  EXPECT_GT(inf, absl::Minutes(kint64max / 60));\n  EXPECT_LT(-inf, absl::Minutes(kint64min / 60));\n  EXPECT_LT(-inf, absl::Minutes(-kint64max / 60));\n\n  EXPECT_EQ(inf, absl::Hours(kint64max));\n  EXPECT_EQ(-inf, absl::Hours(kint64min));\n  EXPECT_EQ(-inf, absl::Hours(-kint64max));\n  EXPECT_GT(inf, absl::Hours(kint64max / 3600));\n  EXPECT_LT(-inf, absl::Hours(kint64min / 3600));\n  EXPECT_LT(-inf, absl::Hours(-kint64max / 3600));\n}\n\nTEST(Duration, ToConversion) {\n#define TEST_DURATION_CONVERSION(UNIT)                                  \\\n  do {                                                                  \\\n    const absl::Duration d = absl::UNIT(1.5);                           \\\n    constexpr absl::Duration z = absl::ZeroDuration();                  \\\n    constexpr absl::Duration inf = absl::InfiniteDuration();            \\\n    constexpr double dbl_inf = std::numeric_limits<double>::infinity(); \\\n    EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf));                    \\\n    EXPECT_EQ(-1, absl::ToInt64##UNIT(-d));                             \\\n    EXPECT_EQ(0, absl::ToInt64##UNIT(z));                               \\\n    EXPECT_EQ(1, absl::ToInt64##UNIT(d));                               \\\n    EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf));                     \\\n    EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf));                    \\\n    EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d));                          \\\n    EXPECT_EQ(0, absl::ToDouble##UNIT(z));                              \\\n    EXPECT_EQ(1.5, absl::ToDouble##UNIT(d));                            \\\n    EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf));                      \\\n  } while (0)\n\n  TEST_DURATION_CONVERSION(Nanoseconds);\n  TEST_DURATION_CONVERSION(Microseconds);\n  TEST_DURATION_CONVERSION(Milliseconds);\n  TEST_DURATION_CONVERSION(Seconds);\n  TEST_DURATION_CONVERSION(Minutes);\n  TEST_DURATION_CONVERSION(Hours);\n\n#undef TEST_DURATION_CONVERSION\n}\n\ntemplate <int64_t N>\nvoid TestToConversion() {\n  constexpr absl::Duration nano = absl::Nanoseconds(N);\n  EXPECT_EQ(N, absl::ToInt64Nanoseconds(nano));\n  EXPECT_EQ(0, absl::ToInt64Microseconds(nano));\n  EXPECT_EQ(0, absl::ToInt64Milliseconds(nano));\n  EXPECT_EQ(0, absl::ToInt64Seconds(nano));\n  EXPECT_EQ(0, absl::ToInt64Minutes(nano));\n  EXPECT_EQ(0, absl::ToInt64Hours(nano));\n  const absl::Duration micro = absl::Microseconds(N);\n  EXPECT_EQ(N * 1000, absl::ToInt64Nanoseconds(micro));\n  EXPECT_EQ(N, absl::ToInt64Microseconds(micro));\n  EXPECT_EQ(0, absl::ToInt64Milliseconds(micro));\n  EXPECT_EQ(0, absl::ToInt64Seconds(micro));\n  EXPECT_EQ(0, absl::ToInt64Minutes(micro));\n  EXPECT_EQ(0, absl::ToInt64Hours(micro));\n  const absl::Duration milli = absl::Milliseconds(N);\n  EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Nanoseconds(milli));\n  EXPECT_EQ(N * 1000, absl::ToInt64Microseconds(milli));\n  EXPECT_EQ(N, absl::ToInt64Milliseconds(milli));\n  EXPECT_EQ(0, absl::ToInt64Seconds(milli));\n  EXPECT_EQ(0, absl::ToInt64Minutes(milli));\n  EXPECT_EQ(0, absl::ToInt64Hours(milli));\n  const absl::Duration sec = absl::Seconds(N);\n  EXPECT_EQ(N * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(sec));\n  EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Microseconds(sec));\n  EXPECT_EQ(N * 1000, absl::ToInt64Milliseconds(sec));\n  EXPECT_EQ(N, absl::ToInt64Seconds(sec));\n  EXPECT_EQ(0, absl::ToInt64Minutes(sec));\n  EXPECT_EQ(0, absl::ToInt64Hours(sec));\n  const absl::Duration min = absl::Minutes(N);\n  EXPECT_EQ(N * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(min));\n  EXPECT_EQ(N * 60 * 1000 * 1000, absl::ToInt64Microseconds(min));\n  EXPECT_EQ(N * 60 * 1000, absl::ToInt64Milliseconds(min));\n  EXPECT_EQ(N * 60, absl::ToInt64Seconds(min));\n  EXPECT_EQ(N, absl::ToInt64Minutes(min));\n  EXPECT_EQ(0, absl::ToInt64Hours(min));\n  const absl::Duration hour = absl::Hours(N);\n  EXPECT_EQ(N * 60 * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(hour));\n  EXPECT_EQ(N * 60 * 60 * 1000 * 1000, absl::ToInt64Microseconds(hour));\n  EXPECT_EQ(N * 60 * 60 * 1000, absl::ToInt64Milliseconds(hour));\n  EXPECT_EQ(N * 60 * 60, absl::ToInt64Seconds(hour));\n  EXPECT_EQ(N * 60, absl::ToInt64Minutes(hour));\n  EXPECT_EQ(N, absl::ToInt64Hours(hour));\n}\n\nTEST(Duration, ToConversionDeprecated) {\n  TestToConversion<43>();\n  TestToConversion<1>();\n  TestToConversion<0>();\n  TestToConversion<-1>();\n  TestToConversion<-43>();\n}\n\ntemplate <int64_t N>\nvoid TestFromChronoBasicEquality() {\n  using std::chrono::hours;\n  using std::chrono::microseconds;\n  using std::chrono::milliseconds;\n  using std::chrono::minutes;\n  using std::chrono::nanoseconds;\n  using std::chrono::seconds;\n\n  static_assert(absl::Nanoseconds(N) == absl::FromChrono(nanoseconds(N)), \"\");\n  static_assert(absl::Microseconds(N) == absl::FromChrono(microseconds(N)), \"\");\n  static_assert(absl::Milliseconds(N) == absl::FromChrono(milliseconds(N)), \"\");\n  static_assert(absl::Seconds(N) == absl::FromChrono(seconds(N)), \"\");\n  static_assert(absl::Minutes(N) == absl::FromChrono(minutes(N)), \"\");\n  static_assert(absl::Hours(N) == absl::FromChrono(hours(N)), \"\");\n}\n\nTEST(Duration, FromChrono) {\n  TestFromChronoBasicEquality<-123>();\n  TestFromChronoBasicEquality<-1>();\n  TestFromChronoBasicEquality<0>();\n  TestFromChronoBasicEquality<1>();\n  TestFromChronoBasicEquality<123>();\n\n  // Minutes (might, depending on the platform) saturate at +inf.\n  const auto chrono_minutes_max = std::chrono::minutes::max();\n  const auto minutes_max = absl::FromChrono(chrono_minutes_max);\n  const int64_t minutes_max_count = chrono_minutes_max.count();\n  if (minutes_max_count > kint64max / 60) {\n    EXPECT_EQ(absl::InfiniteDuration(), minutes_max);\n  } else {\n    EXPECT_EQ(absl::Minutes(minutes_max_count), minutes_max);\n  }\n\n  // Minutes (might, depending on the platform) saturate at -inf.\n  const auto chrono_minutes_min = std::chrono::minutes::min();\n  const auto minutes_min = absl::FromChrono(chrono_minutes_min);\n  const int64_t minutes_min_count = chrono_minutes_min.count();\n  if (minutes_min_count < kint64min / 60) {\n    EXPECT_EQ(-absl::InfiniteDuration(), minutes_min);\n  } else {\n    EXPECT_EQ(absl::Minutes(minutes_min_count), minutes_min);\n  }\n\n  // Hours (might, depending on the platform) saturate at +inf.\n  const auto chrono_hours_max = std::chrono::hours::max();\n  const auto hours_max = absl::FromChrono(chrono_hours_max);\n  const int64_t hours_max_count = chrono_hours_max.count();\n  if (hours_max_count > kint64max / 3600) {\n    EXPECT_EQ(absl::InfiniteDuration(), hours_max);\n  } else {\n    EXPECT_EQ(absl::Hours(hours_max_count), hours_max);\n  }\n\n  // Hours (might, depending on the platform) saturate at -inf.\n  const auto chrono_hours_min = std::chrono::hours::min();\n  const auto hours_min = absl::FromChrono(chrono_hours_min);\n  const int64_t hours_min_count = chrono_hours_min.count();\n  if (hours_min_count < kint64min / 3600) {\n    EXPECT_EQ(-absl::InfiniteDuration(), hours_min);\n  } else {\n    EXPECT_EQ(absl::Hours(hours_min_count), hours_min);\n  }\n}\n\ntemplate <int64_t N>\nvoid TestToChrono() {\n  using std::chrono::hours;\n  using std::chrono::microseconds;\n  using std::chrono::milliseconds;\n  using std::chrono::minutes;\n  using std::chrono::nanoseconds;\n  using std::chrono::seconds;\n\n  EXPECT_EQ(nanoseconds(N), absl::ToChronoNanoseconds(absl::Nanoseconds(N)));\n  EXPECT_EQ(microseconds(N), absl::ToChronoMicroseconds(absl::Microseconds(N)));\n  EXPECT_EQ(milliseconds(N), absl::ToChronoMilliseconds(absl::Milliseconds(N)));\n  EXPECT_EQ(seconds(N), absl::ToChronoSeconds(absl::Seconds(N)));\n\n  constexpr auto absl_minutes = absl::Minutes(N);\n  auto chrono_minutes = minutes(N);\n  if (absl_minutes == -absl::InfiniteDuration()) {\n    chrono_minutes = minutes::min();\n  } else if (absl_minutes == absl::InfiniteDuration()) {\n    chrono_minutes = minutes::max();\n  }\n  EXPECT_EQ(chrono_minutes, absl::ToChronoMinutes(absl_minutes));\n\n  constexpr auto absl_hours = absl::Hours(N);\n  auto chrono_hours = hours(N);\n  if (absl_hours == -absl::InfiniteDuration()) {\n    chrono_hours = hours::min();\n  } else if (absl_hours == absl::InfiniteDuration()) {\n    chrono_hours = hours::max();\n  }\n  EXPECT_EQ(chrono_hours, absl::ToChronoHours(absl_hours));\n}\n\nTEST(Duration, ToChrono) {\n  using std::chrono::hours;\n  using std::chrono::microseconds;\n  using std::chrono::milliseconds;\n  using std::chrono::minutes;\n  using std::chrono::nanoseconds;\n  using std::chrono::seconds;\n\n  TestToChrono<kint64min>();\n  TestToChrono<-1>();\n  TestToChrono<0>();\n  TestToChrono<1>();\n  TestToChrono<kint64max>();\n\n  // Verify truncation toward zero.\n  const auto tick = absl::Nanoseconds(1) / 4;\n  EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(tick));\n  EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(-tick));\n  EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(tick));\n  EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(-tick));\n  EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(tick));\n  EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(-tick));\n  EXPECT_EQ(seconds(0), absl::ToChronoSeconds(tick));\n  EXPECT_EQ(seconds(0), absl::ToChronoSeconds(-tick));\n  EXPECT_EQ(minutes(0), absl::ToChronoMinutes(tick));\n  EXPECT_EQ(minutes(0), absl::ToChronoMinutes(-tick));\n  EXPECT_EQ(hours(0), absl::ToChronoHours(tick));\n  EXPECT_EQ(hours(0), absl::ToChronoHours(-tick));\n\n  // Verifies +/- infinity saturation at max/min.\n  constexpr auto inf = absl::InfiniteDuration();\n  EXPECT_EQ(nanoseconds::min(), absl::ToChronoNanoseconds(-inf));\n  EXPECT_EQ(nanoseconds::max(), absl::ToChronoNanoseconds(inf));\n  EXPECT_EQ(microseconds::min(), absl::ToChronoMicroseconds(-inf));\n  EXPECT_EQ(microseconds::max(), absl::ToChronoMicroseconds(inf));\n  EXPECT_EQ(milliseconds::min(), absl::ToChronoMilliseconds(-inf));\n  EXPECT_EQ(milliseconds::max(), absl::ToChronoMilliseconds(inf));\n  EXPECT_EQ(seconds::min(), absl::ToChronoSeconds(-inf));\n  EXPECT_EQ(seconds::max(), absl::ToChronoSeconds(inf));\n  EXPECT_EQ(minutes::min(), absl::ToChronoMinutes(-inf));\n  EXPECT_EQ(minutes::max(), absl::ToChronoMinutes(inf));\n  EXPECT_EQ(hours::min(), absl::ToChronoHours(-inf));\n  EXPECT_EQ(hours::max(), absl::ToChronoHours(inf));\n}\n\nTEST(Duration, FactoryOverloads) {\n  enum E { kOne = 1 };\n#define TEST_FACTORY_OVERLOADS(NAME)                                          \\\n  EXPECT_EQ(1, NAME(kOne) / NAME(kOne));                                      \\\n  EXPECT_EQ(1, NAME(static_cast<int8_t>(1)) / NAME(1));                       \\\n  EXPECT_EQ(1, NAME(static_cast<int16_t>(1)) / NAME(1));                      \\\n  EXPECT_EQ(1, NAME(static_cast<int32_t>(1)) / NAME(1));                      \\\n  EXPECT_EQ(1, NAME(static_cast<int64_t>(1)) / NAME(1));                      \\\n  EXPECT_EQ(1, NAME(static_cast<uint8_t>(1)) / NAME(1));                      \\\n  EXPECT_EQ(1, NAME(static_cast<uint16_t>(1)) / NAME(1));                     \\\n  EXPECT_EQ(1, NAME(static_cast<uint32_t>(1)) / NAME(1));                     \\\n  EXPECT_EQ(1, NAME(static_cast<uint64_t>(1)) / NAME(1));                     \\\n  EXPECT_EQ(NAME(1) / 2, NAME(static_cast<float>(0.5)));                      \\\n  EXPECT_EQ(NAME(1) / 2, NAME(static_cast<double>(0.5)));                     \\\n  EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast<float>(1.5)), NAME(1))); \\\n  EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast<double>(1.5)), NAME(1)));\n\n  TEST_FACTORY_OVERLOADS(absl::Nanoseconds);\n  TEST_FACTORY_OVERLOADS(absl::Microseconds);\n  TEST_FACTORY_OVERLOADS(absl::Milliseconds);\n  TEST_FACTORY_OVERLOADS(absl::Seconds);\n  TEST_FACTORY_OVERLOADS(absl::Minutes);\n  TEST_FACTORY_OVERLOADS(absl::Hours);\n\n#undef TEST_FACTORY_OVERLOADS\n\n  EXPECT_EQ(absl::Milliseconds(1500), absl::Seconds(1.5));\n  EXPECT_LT(absl::Nanoseconds(1), absl::Nanoseconds(1.5));\n  EXPECT_GT(absl::Nanoseconds(2), absl::Nanoseconds(1.5));\n\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n  EXPECT_EQ(absl::InfiniteDuration(), absl::Nanoseconds(dbl_inf));\n  EXPECT_EQ(absl::InfiniteDuration(), absl::Microseconds(dbl_inf));\n  EXPECT_EQ(absl::InfiniteDuration(), absl::Milliseconds(dbl_inf));\n  EXPECT_EQ(absl::InfiniteDuration(), absl::Seconds(dbl_inf));\n  EXPECT_EQ(absl::InfiniteDuration(), absl::Minutes(dbl_inf));\n  EXPECT_EQ(absl::InfiniteDuration(), absl::Hours(dbl_inf));\n  EXPECT_EQ(-absl::InfiniteDuration(), absl::Nanoseconds(-dbl_inf));\n  EXPECT_EQ(-absl::InfiniteDuration(), absl::Microseconds(-dbl_inf));\n  EXPECT_EQ(-absl::InfiniteDuration(), absl::Milliseconds(-dbl_inf));\n  EXPECT_EQ(-absl::InfiniteDuration(), absl::Seconds(-dbl_inf));\n  EXPECT_EQ(-absl::InfiniteDuration(), absl::Minutes(-dbl_inf));\n  EXPECT_EQ(-absl::InfiniteDuration(), absl::Hours(-dbl_inf));\n}\n\nTEST(Duration, InfinityExamples) {\n  // These examples are used in the documentation in time.h. They are\n  // written so that they can be copy-n-pasted easily.\n\n  constexpr absl::Duration inf = absl::InfiniteDuration();\n  constexpr absl::Duration d = absl::Seconds(1);  // Any finite duration\n\n  EXPECT_TRUE(inf == inf + inf);\n  EXPECT_TRUE(inf == inf + d);\n  EXPECT_TRUE(inf == inf - inf);\n  EXPECT_TRUE(-inf == d - inf);\n\n  EXPECT_TRUE(inf == d * 1e100);\n  EXPECT_TRUE(0 == d / inf);  // NOLINT(readability/check)\n\n  // Division by zero returns infinity, or kint64min/MAX where necessary.\n  EXPECT_TRUE(inf == d / 0);\n  EXPECT_TRUE(kint64max == d / absl::ZeroDuration());\n}\n\nTEST(Duration, InfinityComparison) {\n  const absl::Duration inf = absl::InfiniteDuration();\n  const absl::Duration any_dur = absl::Seconds(1);\n\n  // Equality\n  EXPECT_EQ(inf, inf);\n  EXPECT_EQ(-inf, -inf);\n  EXPECT_NE(inf, -inf);\n  EXPECT_NE(any_dur, inf);\n  EXPECT_NE(any_dur, -inf);\n\n  // Relational\n  EXPECT_GT(inf, any_dur);\n  EXPECT_LT(-inf, any_dur);\n  EXPECT_LT(-inf, inf);\n  EXPECT_GT(inf, -inf);\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n  EXPECT_EQ(inf <=> inf, std::strong_ordering::equal);\n  EXPECT_EQ(-inf <=> -inf, std::strong_ordering::equal);\n  EXPECT_EQ(-inf <=> inf, std::strong_ordering::less);\n  EXPECT_EQ(inf <=> -inf, std::strong_ordering::greater);\n  EXPECT_EQ(any_dur <=> inf, std::strong_ordering::less);\n  EXPECT_EQ(any_dur <=> -inf, std::strong_ordering::greater);\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n}\n\nTEST(Duration, InfinityAddition) {\n  const absl::Duration sec_max = absl::Seconds(kint64max);\n  const absl::Duration sec_min = absl::Seconds(kint64min);\n  const absl::Duration any_dur = absl::Seconds(1);\n  const absl::Duration inf = absl::InfiniteDuration();\n\n  // Addition\n  EXPECT_EQ(inf, inf + inf);\n  EXPECT_EQ(inf, inf + -inf);\n  EXPECT_EQ(-inf, -inf + inf);\n  EXPECT_EQ(-inf, -inf + -inf);\n\n  EXPECT_EQ(inf, inf + any_dur);\n  EXPECT_EQ(inf, any_dur + inf);\n  EXPECT_EQ(-inf, -inf + any_dur);\n  EXPECT_EQ(-inf, any_dur + -inf);\n\n  // Interesting case\n  absl::Duration almost_inf = sec_max + absl::Nanoseconds(999999999);\n  EXPECT_GT(inf, almost_inf);\n  almost_inf += -absl::Nanoseconds(999999999);\n  EXPECT_GT(inf, almost_inf);\n\n  // Addition overflow/underflow\n  EXPECT_EQ(inf, sec_max + absl::Seconds(1));\n  EXPECT_EQ(inf, sec_max + sec_max);\n  EXPECT_EQ(-inf, sec_min + -absl::Seconds(1));\n  EXPECT_EQ(-inf, sec_min + -sec_max);\n\n  // For reference: IEEE 754 behavior\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n  EXPECT_TRUE(std::isinf(dbl_inf + dbl_inf));\n  EXPECT_TRUE(std::isnan(dbl_inf + -dbl_inf));  // We return inf\n  EXPECT_TRUE(std::isnan(-dbl_inf + dbl_inf));  // We return inf\n  EXPECT_TRUE(std::isinf(-dbl_inf + -dbl_inf));\n}\n\nTEST(Duration, InfinitySubtraction) {\n  const absl::Duration sec_max = absl::Seconds(kint64max);\n  const absl::Duration sec_min = absl::Seconds(kint64min);\n  const absl::Duration any_dur = absl::Seconds(1);\n  const absl::Duration inf = absl::InfiniteDuration();\n\n  // Subtraction\n  EXPECT_EQ(inf, inf - inf);\n  EXPECT_EQ(inf, inf - -inf);\n  EXPECT_EQ(-inf, -inf - inf);\n  EXPECT_EQ(-inf, -inf - -inf);\n\n  EXPECT_EQ(inf, inf - any_dur);\n  EXPECT_EQ(-inf, any_dur - inf);\n  EXPECT_EQ(-inf, -inf - any_dur);\n  EXPECT_EQ(inf, any_dur - -inf);\n\n  // Subtraction overflow/underflow\n  EXPECT_EQ(inf, sec_max - -absl::Seconds(1));\n  EXPECT_EQ(inf, sec_max - -sec_max);\n  EXPECT_EQ(-inf, sec_min - absl::Seconds(1));\n  EXPECT_EQ(-inf, sec_min - sec_max);\n\n  // Interesting case\n  absl::Duration almost_neg_inf = sec_min;\n  EXPECT_LT(-inf, almost_neg_inf);\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n  EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less);\n  EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater);\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  almost_neg_inf -= -absl::Nanoseconds(1);\n  EXPECT_LT(-inf, almost_neg_inf);\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n  EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less);\n  EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater);\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  // For reference: IEEE 754 behavior\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n  EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf));  // We return inf\n  EXPECT_TRUE(std::isinf(dbl_inf - -dbl_inf));\n  EXPECT_TRUE(std::isinf(-dbl_inf - dbl_inf));\n  EXPECT_TRUE(std::isnan(-dbl_inf - -dbl_inf));  // We return inf\n}\n\nTEST(Duration, InfinityMultiplication) {\n  const absl::Duration sec_max = absl::Seconds(kint64max);\n  const absl::Duration sec_min = absl::Seconds(kint64min);\n  const absl::Duration inf = absl::InfiniteDuration();\n\n#define TEST_INF_MUL_WITH_TYPE(T)                                    \\\n  EXPECT_EQ(inf, inf* static_cast<T>(2));                            \\\n  EXPECT_EQ(-inf, inf* static_cast<T>(-2));                          \\\n  EXPECT_EQ(-inf, -inf* static_cast<T>(2));                          \\\n  EXPECT_EQ(inf, -inf* static_cast<T>(-2));                          \\\n  EXPECT_EQ(inf, inf* static_cast<T>(0));                            \\\n  EXPECT_EQ(-inf, -inf* static_cast<T>(0));                          \\\n  EXPECT_EQ(inf, sec_max* static_cast<T>(2));                        \\\n  EXPECT_EQ(inf, sec_min* static_cast<T>(-2));                       \\\n  EXPECT_EQ(inf, (sec_max / static_cast<T>(2)) * static_cast<T>(3)); \\\n  EXPECT_EQ(-inf, sec_max* static_cast<T>(-2));                      \\\n  EXPECT_EQ(-inf, sec_min* static_cast<T>(2));                       \\\n  EXPECT_EQ(-inf, (sec_min / static_cast<T>(2)) * static_cast<T>(3));\n\n  TEST_INF_MUL_WITH_TYPE(int64_t);  // NOLINT(readability/function)\n  TEST_INF_MUL_WITH_TYPE(double);   // NOLINT(readability/function)\n\n#undef TEST_INF_MUL_WITH_TYPE\n\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n  EXPECT_EQ(inf, inf * dbl_inf);\n  EXPECT_EQ(-inf, -inf * dbl_inf);\n  EXPECT_EQ(-inf, inf * -dbl_inf);\n  EXPECT_EQ(inf, -inf * -dbl_inf);\n\n  const absl::Duration any_dur = absl::Seconds(1);\n  EXPECT_EQ(inf, any_dur * dbl_inf);\n  EXPECT_EQ(-inf, -any_dur * dbl_inf);\n  EXPECT_EQ(-inf, any_dur * -dbl_inf);\n  EXPECT_EQ(inf, -any_dur * -dbl_inf);\n\n  // Fixed-point multiplication will produce a finite value, whereas floating\n  // point fuzziness will overflow to inf.\n  EXPECT_NE(absl::InfiniteDuration(), absl::Seconds(1) * kint64max);\n  EXPECT_EQ(inf, absl::Seconds(1) * static_cast<double>(kint64max));\n  EXPECT_NE(-absl::InfiniteDuration(), absl::Seconds(1) * kint64min);\n  EXPECT_EQ(-inf, absl::Seconds(1) * static_cast<double>(kint64min));\n\n  // Note that sec_max * or / by 1.0 overflows to inf due to the 53-bit\n  // limitations of double.\n  EXPECT_NE(inf, sec_max);\n  EXPECT_NE(inf, sec_max / 1);\n  EXPECT_EQ(inf, sec_max / 1.0);\n  EXPECT_NE(inf, sec_max * 1);\n  EXPECT_EQ(inf, sec_max * 1.0);\n}\n\nTEST(Duration, InfinityDivision) {\n  const absl::Duration sec_max = absl::Seconds(kint64max);\n  const absl::Duration sec_min = absl::Seconds(kint64min);\n  const absl::Duration inf = absl::InfiniteDuration();\n\n  // Division of Duration by a double\n#define TEST_INF_DIV_WITH_TYPE(T)            \\\n  EXPECT_EQ(inf, inf / static_cast<T>(2));   \\\n  EXPECT_EQ(-inf, inf / static_cast<T>(-2)); \\\n  EXPECT_EQ(-inf, -inf / static_cast<T>(2)); \\\n  EXPECT_EQ(inf, -inf / static_cast<T>(-2));\n\n  TEST_INF_DIV_WITH_TYPE(int64_t);  // NOLINT(readability/function)\n  TEST_INF_DIV_WITH_TYPE(double);   // NOLINT(readability/function)\n\n#undef TEST_INF_DIV_WITH_TYPE\n\n  // Division of Duration by a double overflow/underflow\n  EXPECT_EQ(inf, sec_max / 0.5);\n  EXPECT_EQ(inf, sec_min / -0.5);\n  EXPECT_EQ(inf, ((sec_max / 0.5) + absl::Seconds(1)) / 0.5);\n  EXPECT_EQ(-inf, sec_max / -0.5);\n  EXPECT_EQ(-inf, sec_min / 0.5);\n  EXPECT_EQ(-inf, ((sec_min / 0.5) - absl::Seconds(1)) / 0.5);\n\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n  EXPECT_EQ(inf, inf / dbl_inf);\n  EXPECT_EQ(-inf, inf / -dbl_inf);\n  EXPECT_EQ(-inf, -inf / dbl_inf);\n  EXPECT_EQ(inf, -inf / -dbl_inf);\n\n  const absl::Duration any_dur = absl::Seconds(1);\n  EXPECT_EQ(absl::ZeroDuration(), any_dur / dbl_inf);\n  EXPECT_EQ(absl::ZeroDuration(), any_dur / -dbl_inf);\n  EXPECT_EQ(absl::ZeroDuration(), -any_dur / dbl_inf);\n  EXPECT_EQ(absl::ZeroDuration(), -any_dur / -dbl_inf);\n}\n\nTEST(Duration, InfinityModulus) {\n  const absl::Duration sec_max = absl::Seconds(kint64max);\n  const absl::Duration any_dur = absl::Seconds(1);\n  const absl::Duration inf = absl::InfiniteDuration();\n\n  EXPECT_EQ(inf, inf % inf);\n  EXPECT_EQ(inf, inf % -inf);\n  EXPECT_EQ(-inf, -inf % -inf);\n  EXPECT_EQ(-inf, -inf % inf);\n\n  EXPECT_EQ(any_dur, any_dur % inf);\n  EXPECT_EQ(any_dur, any_dur % -inf);\n  EXPECT_EQ(-any_dur, -any_dur % inf);\n  EXPECT_EQ(-any_dur, -any_dur % -inf);\n\n  EXPECT_EQ(inf, inf % -any_dur);\n  EXPECT_EQ(inf, inf % any_dur);\n  EXPECT_EQ(-inf, -inf % -any_dur);\n  EXPECT_EQ(-inf, -inf % any_dur);\n\n  // Remainder isn't affected by overflow.\n  EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Seconds(1));\n  EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Milliseconds(1));\n  EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Microseconds(1));\n  EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Nanoseconds(1));\n  EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Nanoseconds(1) / 4);\n}\n\nTEST(Duration, InfinityIDiv) {\n  const absl::Duration sec_max = absl::Seconds(kint64max);\n  const absl::Duration any_dur = absl::Seconds(1);\n  const absl::Duration inf = absl::InfiniteDuration();\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n\n  // IDivDuration (int64_t return value + a remainer)\n  absl::Duration rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64max, absl::IDivDuration(inf, inf, &rem));\n  EXPECT_EQ(inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64max, absl::IDivDuration(-inf, -inf, &rem));\n  EXPECT_EQ(-inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64max, absl::IDivDuration(inf, any_dur, &rem));\n  EXPECT_EQ(inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(0, absl::IDivDuration(any_dur, inf, &rem));\n  EXPECT_EQ(any_dur, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64max, absl::IDivDuration(-inf, -any_dur, &rem));\n  EXPECT_EQ(-inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(0, absl::IDivDuration(-any_dur, -inf, &rem));\n  EXPECT_EQ(-any_dur, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64min, absl::IDivDuration(-inf, inf, &rem));\n  EXPECT_EQ(-inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64min, absl::IDivDuration(inf, -inf, &rem));\n  EXPECT_EQ(inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64min, absl::IDivDuration(-inf, any_dur, &rem));\n  EXPECT_EQ(-inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(0, absl::IDivDuration(-any_dur, inf, &rem));\n  EXPECT_EQ(-any_dur, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(kint64min, absl::IDivDuration(inf, -any_dur, &rem));\n  EXPECT_EQ(inf, rem);\n\n  rem = absl::ZeroDuration();\n  EXPECT_EQ(0, absl::IDivDuration(any_dur, -inf, &rem));\n  EXPECT_EQ(any_dur, rem);\n\n  // IDivDuration overflow/underflow\n  rem = any_dur;\n  EXPECT_EQ(kint64max,\n            absl::IDivDuration(sec_max, absl::Nanoseconds(1) / 4, &rem));\n  EXPECT_EQ(sec_max - absl::Nanoseconds(kint64max) / 4, rem);\n\n  rem = any_dur;\n  EXPECT_EQ(kint64max,\n            absl::IDivDuration(sec_max, absl::Milliseconds(1), &rem));\n  EXPECT_EQ(sec_max - absl::Milliseconds(kint64max), rem);\n\n  rem = any_dur;\n  EXPECT_EQ(kint64max,\n            absl::IDivDuration(-sec_max, -absl::Milliseconds(1), &rem));\n  EXPECT_EQ(-sec_max + absl::Milliseconds(kint64max), rem);\n\n  rem = any_dur;\n  EXPECT_EQ(kint64min,\n            absl::IDivDuration(-sec_max, absl::Milliseconds(1), &rem));\n  EXPECT_EQ(-sec_max - absl::Milliseconds(kint64min), rem);\n\n  rem = any_dur;\n  EXPECT_EQ(kint64min,\n            absl::IDivDuration(sec_max, -absl::Milliseconds(1), &rem));\n  EXPECT_EQ(sec_max + absl::Milliseconds(kint64min), rem);\n\n  //\n  // operator/(Duration, Duration) is a wrapper for IDivDuration().\n  //\n\n  // IEEE 754 says inf / inf should be nan, but int64_t doesn't have\n  // nan so we'll return kint64max/kint64min instead.\n  EXPECT_TRUE(std::isnan(dbl_inf / dbl_inf));\n  EXPECT_EQ(kint64max, inf / inf);\n  EXPECT_EQ(kint64max, -inf / -inf);\n  EXPECT_EQ(kint64min, -inf / inf);\n  EXPECT_EQ(kint64min, inf / -inf);\n\n  EXPECT_TRUE(std::isinf(dbl_inf / 2.0));\n  EXPECT_EQ(kint64max, inf / any_dur);\n  EXPECT_EQ(kint64max, -inf / -any_dur);\n  EXPECT_EQ(kint64min, -inf / any_dur);\n  EXPECT_EQ(kint64min, inf / -any_dur);\n\n  EXPECT_EQ(0.0, 2.0 / dbl_inf);\n  EXPECT_EQ(0, any_dur / inf);\n  EXPECT_EQ(0, any_dur / -inf);\n  EXPECT_EQ(0, -any_dur / inf);\n  EXPECT_EQ(0, -any_dur / -inf);\n  EXPECT_EQ(0, absl::ZeroDuration() / inf);\n\n  // Division of Duration by a Duration overflow/underflow\n  EXPECT_EQ(kint64max, sec_max / absl::Milliseconds(1));\n  EXPECT_EQ(kint64max, -sec_max / -absl::Milliseconds(1));\n  EXPECT_EQ(kint64min, -sec_max / absl::Milliseconds(1));\n  EXPECT_EQ(kint64min, sec_max / -absl::Milliseconds(1));\n}\n\nTEST(Duration, InfinityFDiv) {\n  const absl::Duration any_dur = absl::Seconds(1);\n  const absl::Duration inf = absl::InfiniteDuration();\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n\n  EXPECT_EQ(dbl_inf, absl::FDivDuration(inf, inf));\n  EXPECT_EQ(dbl_inf, absl::FDivDuration(-inf, -inf));\n  EXPECT_EQ(dbl_inf, absl::FDivDuration(inf, any_dur));\n  EXPECT_EQ(0.0, absl::FDivDuration(any_dur, inf));\n  EXPECT_EQ(dbl_inf, absl::FDivDuration(-inf, -any_dur));\n  EXPECT_EQ(0.0, absl::FDivDuration(-any_dur, -inf));\n\n  EXPECT_EQ(-dbl_inf, absl::FDivDuration(-inf, inf));\n  EXPECT_EQ(-dbl_inf, absl::FDivDuration(inf, -inf));\n  EXPECT_EQ(-dbl_inf, absl::FDivDuration(-inf, any_dur));\n  EXPECT_EQ(0.0, absl::FDivDuration(-any_dur, inf));\n  EXPECT_EQ(-dbl_inf, absl::FDivDuration(inf, -any_dur));\n  EXPECT_EQ(0.0, absl::FDivDuration(any_dur, -inf));\n}\n\nTEST(Duration, DivisionByZero) {\n  const absl::Duration zero = absl::ZeroDuration();\n  const absl::Duration inf = absl::InfiniteDuration();\n  const absl::Duration any_dur = absl::Seconds(1);\n  const double dbl_inf = std::numeric_limits<double>::infinity();\n  const double dbl_denorm = std::numeric_limits<double>::denorm_min();\n\n  // Operator/(Duration, double)\n  EXPECT_EQ(inf, zero / 0.0);\n  EXPECT_EQ(-inf, zero / -0.0);\n  EXPECT_EQ(inf, any_dur / 0.0);\n  EXPECT_EQ(-inf, any_dur / -0.0);\n  EXPECT_EQ(-inf, -any_dur / 0.0);\n  EXPECT_EQ(inf, -any_dur / -0.0);\n\n  // Tests dividing by a number very close to, but not quite zero.\n  EXPECT_EQ(zero, zero / dbl_denorm);\n  EXPECT_EQ(zero, zero / -dbl_denorm);\n  EXPECT_EQ(inf, any_dur / dbl_denorm);\n  EXPECT_EQ(-inf, any_dur / -dbl_denorm);\n  EXPECT_EQ(-inf, -any_dur / dbl_denorm);\n  EXPECT_EQ(inf, -any_dur / -dbl_denorm);\n\n  // IDiv\n  absl::Duration rem = zero;\n  EXPECT_EQ(kint64max, absl::IDivDuration(zero, zero, &rem));\n  EXPECT_EQ(inf, rem);\n\n  rem = zero;\n  EXPECT_EQ(kint64max, absl::IDivDuration(any_dur, zero, &rem));\n  EXPECT_EQ(inf, rem);\n\n  rem = zero;\n  EXPECT_EQ(kint64min, absl::IDivDuration(-any_dur, zero, &rem));\n  EXPECT_EQ(-inf, rem);\n\n  // Operator/(Duration, Duration)\n  EXPECT_EQ(kint64max, zero / zero);\n  EXPECT_EQ(kint64max, any_dur / zero);\n  EXPECT_EQ(kint64min, -any_dur / zero);\n\n  // FDiv\n  EXPECT_EQ(dbl_inf, absl::FDivDuration(zero, zero));\n  EXPECT_EQ(dbl_inf, absl::FDivDuration(any_dur, zero));\n  EXPECT_EQ(-dbl_inf, absl::FDivDuration(-any_dur, zero));\n}\n\nTEST(Duration, NaN) {\n  // Note that IEEE 754 does not define the behavior of a nan's sign when it is\n  // copied. We return -InfiniteDuration in either case.\n#define TEST_NAN_HANDLING(NAME, NAN)           \\\n  do {                                         \\\n    const auto inf = absl::InfiniteDuration(); \\\n    auto x = NAME(NAN);                        \\\n    EXPECT_TRUE(x == -inf);                    \\\n    auto y = NAME(42);                         \\\n    y *= NAN;                                  \\\n    EXPECT_TRUE(y == -inf);                    \\\n    auto z = NAME(42);                         \\\n    z /= NAN;                                  \\\n    EXPECT_TRUE(z == -inf);                    \\\n  } while (0)\n\n  const double nan = std::numeric_limits<double>::quiet_NaN();\n  TEST_NAN_HANDLING(absl::Nanoseconds, nan);\n  TEST_NAN_HANDLING(absl::Microseconds, nan);\n  TEST_NAN_HANDLING(absl::Milliseconds, nan);\n  TEST_NAN_HANDLING(absl::Seconds, nan);\n  TEST_NAN_HANDLING(absl::Minutes, nan);\n  TEST_NAN_HANDLING(absl::Hours, nan);\n\n  TEST_NAN_HANDLING(absl::Nanoseconds, -nan);\n  TEST_NAN_HANDLING(absl::Microseconds, -nan);\n  TEST_NAN_HANDLING(absl::Milliseconds, -nan);\n  TEST_NAN_HANDLING(absl::Seconds, -nan);\n  TEST_NAN_HANDLING(absl::Minutes, -nan);\n  TEST_NAN_HANDLING(absl::Hours, -nan);\n\n#undef TEST_NAN_HANDLING\n}\n\nTEST(Duration, Range) {\n  const absl::Duration range = ApproxYears(100 * 1e9);\n  const absl::Duration range_future = range;\n  const absl::Duration range_past = -range;\n\n  EXPECT_LT(range_future, absl::InfiniteDuration());\n  EXPECT_GT(range_past, -absl::InfiniteDuration());\n\n  const absl::Duration full_range = range_future - range_past;\n  EXPECT_GT(full_range, absl::ZeroDuration());\n  EXPECT_LT(full_range, absl::InfiniteDuration());\n\n  const absl::Duration neg_full_range = range_past - range_future;\n  EXPECT_LT(neg_full_range, absl::ZeroDuration());\n  EXPECT_GT(neg_full_range, -absl::InfiniteDuration());\n\n  EXPECT_LT(neg_full_range, full_range);\n  EXPECT_EQ(neg_full_range, -full_range);\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n  EXPECT_EQ(range_future <=> absl::InfiniteDuration(),\n            std::strong_ordering::less);\n  EXPECT_EQ(range_past <=> -absl::InfiniteDuration(),\n            std::strong_ordering::greater);\n  EXPECT_EQ(full_range <=> absl::ZeroDuration(),  //\n            std::strong_ordering::greater);\n  EXPECT_EQ(full_range <=> -absl::InfiniteDuration(),\n            std::strong_ordering::greater);\n  EXPECT_EQ(neg_full_range <=> -absl::InfiniteDuration(),\n            std::strong_ordering::greater);\n  EXPECT_EQ(neg_full_range <=> full_range, std::strong_ordering::less);\n  EXPECT_EQ(neg_full_range <=> -full_range, std::strong_ordering::equal);\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n}\n\nTEST(Duration, RelationalOperators) {\n#define TEST_REL_OPS(UNIT)               \\\n  static_assert(UNIT(2) == UNIT(2), \"\"); \\\n  static_assert(UNIT(1) != UNIT(2), \"\"); \\\n  static_assert(UNIT(1) < UNIT(2), \"\");  \\\n  static_assert(UNIT(3) > UNIT(2), \"\");  \\\n  static_assert(UNIT(1) <= UNIT(2), \"\"); \\\n  static_assert(UNIT(2) <= UNIT(2), \"\"); \\\n  static_assert(UNIT(3) >= UNIT(2), \"\"); \\\n  static_assert(UNIT(2) >= UNIT(2), \"\");\n\n  TEST_REL_OPS(absl::Nanoseconds);\n  TEST_REL_OPS(absl::Microseconds);\n  TEST_REL_OPS(absl::Milliseconds);\n  TEST_REL_OPS(absl::Seconds);\n  TEST_REL_OPS(absl::Minutes);\n  TEST_REL_OPS(absl::Hours);\n\n#undef TEST_REL_OPS\n}\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nTEST(Duration, SpaceshipOperators) {\n#define TEST_REL_OPS(UNIT)                                               \\\n  static_assert(UNIT(2) <=> UNIT(2) == std::strong_ordering::equal, \"\"); \\\n  static_assert(UNIT(1) <=> UNIT(2) == std::strong_ordering::less, \"\");  \\\n  static_assert(UNIT(3) <=> UNIT(2) == std::strong_ordering::greater, \"\");\n\n  TEST_REL_OPS(absl::Nanoseconds);\n  TEST_REL_OPS(absl::Microseconds);\n  TEST_REL_OPS(absl::Milliseconds);\n  TEST_REL_OPS(absl::Seconds);\n  TEST_REL_OPS(absl::Minutes);\n  TEST_REL_OPS(absl::Hours);\n\n#undef TEST_REL_OPS\n}\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nTEST(Duration, Addition) {\n#define TEST_ADD_OPS(UNIT)                  \\\n  do {                                      \\\n    EXPECT_EQ(UNIT(2), UNIT(1) + UNIT(1));  \\\n    EXPECT_EQ(UNIT(1), UNIT(2) - UNIT(1));  \\\n    EXPECT_EQ(UNIT(0), UNIT(2) - UNIT(2));  \\\n    EXPECT_EQ(UNIT(-1), UNIT(1) - UNIT(2)); \\\n    EXPECT_EQ(UNIT(-2), UNIT(0) - UNIT(2)); \\\n    EXPECT_EQ(UNIT(-2), UNIT(1) - UNIT(3)); \\\n    absl::Duration a = UNIT(1);             \\\n    a += UNIT(1);                           \\\n    EXPECT_EQ(UNIT(2), a);                  \\\n    a -= UNIT(1);                           \\\n    EXPECT_EQ(UNIT(1), a);                  \\\n  } while (0)\n\n  TEST_ADD_OPS(absl::Nanoseconds);\n  TEST_ADD_OPS(absl::Microseconds);\n  TEST_ADD_OPS(absl::Milliseconds);\n  TEST_ADD_OPS(absl::Seconds);\n  TEST_ADD_OPS(absl::Minutes);\n  TEST_ADD_OPS(absl::Hours);\n\n#undef TEST_ADD_OPS\n\n  EXPECT_EQ(absl::Seconds(2), absl::Seconds(3) - 2 * absl::Milliseconds(500));\n  EXPECT_EQ(absl::Seconds(2) + absl::Milliseconds(500),\n            absl::Seconds(3) - absl::Milliseconds(500));\n\n  EXPECT_EQ(absl::Seconds(1) + absl::Milliseconds(998),\n            absl::Milliseconds(999) + absl::Milliseconds(999));\n\n  EXPECT_EQ(absl::Milliseconds(-1),\n            absl::Milliseconds(998) - absl::Milliseconds(999));\n\n  // Tests fractions of a nanoseconds. These are implementation details only.\n  EXPECT_GT(absl::Nanoseconds(1), absl::Nanoseconds(1) / 2);\n  EXPECT_EQ(absl::Nanoseconds(1),\n            absl::Nanoseconds(1) / 2 + absl::Nanoseconds(1) / 2);\n  EXPECT_GT(absl::Nanoseconds(1) / 4, absl::Nanoseconds(0));\n  EXPECT_EQ(absl::Nanoseconds(1) / 8, absl::Nanoseconds(0));\n\n  // Tests subtraction that will cause wrap around of the rep_lo_ bits.\n  absl::Duration d_7_5 = absl::Seconds(7) + absl::Milliseconds(500);\n  absl::Duration d_3_7 = absl::Seconds(3) + absl::Milliseconds(700);\n  absl::Duration ans_3_8 = absl::Seconds(3) + absl::Milliseconds(800);\n  EXPECT_EQ(ans_3_8, d_7_5 - d_3_7);\n\n  // Subtracting min_duration\n  absl::Duration min_dur = absl::Seconds(kint64min);\n  EXPECT_EQ(absl::Seconds(0), min_dur - min_dur);\n  EXPECT_EQ(absl::Seconds(kint64max), absl::Seconds(-1) - min_dur);\n}\n\nTEST(Duration, Negation) {\n  // By storing negations of various values in constexpr variables we\n  // verify that the initializers are constant expressions.\n  constexpr absl::Duration negated_zero_duration = -absl::ZeroDuration();\n  EXPECT_EQ(negated_zero_duration, absl::ZeroDuration());\n\n  constexpr absl::Duration negated_infinite_duration =\n      -absl::InfiniteDuration();\n  EXPECT_NE(negated_infinite_duration, absl::InfiniteDuration());\n  EXPECT_EQ(-negated_infinite_duration, absl::InfiniteDuration());\n\n  // The public APIs to check if a duration is infinite depend on using\n  // -InfiniteDuration(), but we're trying to test operator- here, so we\n  // need to use the lower-level internal query IsInfiniteDuration.\n  EXPECT_TRUE(\n      absl::time_internal::IsInfiniteDuration(negated_infinite_duration));\n\n  // The largest Duration is kint64max seconds and kTicksPerSecond - 1 ticks.\n  // Using the absl::time_internal::MakeDuration API is the cleanest way to\n  // construct that Duration.\n  constexpr absl::Duration max_duration = absl::time_internal::MakeDuration(\n      kint64max, absl::time_internal::kTicksPerSecond - 1);\n  constexpr absl::Duration negated_max_duration = -max_duration;\n  // The largest negatable value is one tick above the minimum representable;\n  // it's the negation of max_duration.\n  constexpr absl::Duration nearly_min_duration =\n      absl::time_internal::MakeDuration(kint64min, int64_t{1});\n  constexpr absl::Duration negated_nearly_min_duration = -nearly_min_duration;\n\n  EXPECT_EQ(negated_max_duration, nearly_min_duration);\n  EXPECT_EQ(negated_nearly_min_duration, max_duration);\n  EXPECT_EQ(-(-max_duration), max_duration);\n\n  constexpr absl::Duration min_duration =\n      absl::time_internal::MakeDuration(kint64min);\n  constexpr absl::Duration negated_min_duration = -min_duration;\n  EXPECT_EQ(negated_min_duration, absl::InfiniteDuration());\n}\n\nTEST(Duration, AbsoluteValue) {\n  EXPECT_EQ(absl::ZeroDuration(), AbsDuration(absl::ZeroDuration()));\n  EXPECT_EQ(absl::Seconds(1), AbsDuration(absl::Seconds(1)));\n  EXPECT_EQ(absl::Seconds(1), AbsDuration(absl::Seconds(-1)));\n\n  EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(absl::InfiniteDuration()));\n  EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(-absl::InfiniteDuration()));\n\n  absl::Duration max_dur =\n      absl::Seconds(kint64max) + (absl::Seconds(1) - absl::Nanoseconds(1) / 4);\n  EXPECT_EQ(max_dur, AbsDuration(max_dur));\n\n  absl::Duration min_dur = absl::Seconds(kint64min);\n  EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(min_dur));\n  EXPECT_EQ(max_dur, AbsDuration(min_dur + absl::Nanoseconds(1) / 4));\n}\n\nTEST(Duration, Multiplication) {\n#define TEST_MUL_OPS(UNIT)                                    \\\n  do {                                                        \\\n    EXPECT_EQ(UNIT(5), UNIT(2) * 2.5);                        \\\n    EXPECT_EQ(UNIT(2), UNIT(5) / 2.5);                        \\\n    EXPECT_EQ(UNIT(-5), UNIT(-2) * 2.5);                      \\\n    EXPECT_EQ(UNIT(-5), -UNIT(2) * 2.5);                      \\\n    EXPECT_EQ(UNIT(-5), UNIT(2) * -2.5);                      \\\n    EXPECT_EQ(UNIT(-2), UNIT(-5) / 2.5);                      \\\n    EXPECT_EQ(UNIT(-2), -UNIT(5) / 2.5);                      \\\n    EXPECT_EQ(UNIT(-2), UNIT(5) / -2.5);                      \\\n    EXPECT_EQ(UNIT(2), UNIT(11) % UNIT(3));                   \\\n    absl::Duration a = UNIT(2);                               \\\n    a *= 2.5;                                                 \\\n    EXPECT_EQ(UNIT(5), a);                                    \\\n    a /= 2.5;                                                 \\\n    EXPECT_EQ(UNIT(2), a);                                    \\\n    a %= UNIT(1);                                             \\\n    EXPECT_EQ(UNIT(0), a);                                    \\\n    absl::Duration big = UNIT(1000000000);                    \\\n    big *= 3;                                                 \\\n    big /= 3;                                                 \\\n    EXPECT_EQ(UNIT(1000000000), big);                         \\\n    EXPECT_EQ(-UNIT(2), -UNIT(2));                            \\\n    EXPECT_EQ(-UNIT(2), UNIT(2) * -1);                        \\\n    EXPECT_EQ(-UNIT(2), -1 * UNIT(2));                        \\\n    EXPECT_EQ(-UNIT(-2), UNIT(2));                            \\\n    EXPECT_EQ(2, UNIT(2) / UNIT(1));                          \\\n    absl::Duration rem;                                       \\\n    EXPECT_EQ(2, absl::IDivDuration(UNIT(2), UNIT(1), &rem)); \\\n    EXPECT_EQ(2.0, absl::FDivDuration(UNIT(2), UNIT(1)));     \\\n  } while (0)\n\n  TEST_MUL_OPS(absl::Nanoseconds);\n  TEST_MUL_OPS(absl::Microseconds);\n  TEST_MUL_OPS(absl::Milliseconds);\n  TEST_MUL_OPS(absl::Seconds);\n  TEST_MUL_OPS(absl::Minutes);\n  TEST_MUL_OPS(absl::Hours);\n\n#undef TEST_MUL_OPS\n\n  // Ensures that multiplication and division by 1 with a maxed-out durations\n  // doesn't lose precision.\n  absl::Duration max_dur =\n      absl::Seconds(kint64max) + (absl::Seconds(1) - absl::Nanoseconds(1) / 4);\n  absl::Duration min_dur = absl::Seconds(kint64min);\n  EXPECT_EQ(max_dur, max_dur * 1);\n  EXPECT_EQ(max_dur, max_dur / 1);\n  EXPECT_EQ(min_dur, min_dur * 1);\n  EXPECT_EQ(min_dur, min_dur / 1);\n\n  // Tests division on a Duration with a large number of significant digits.\n  // Tests when the digits span hi and lo as well as only in hi.\n  absl::Duration sigfigs = absl::Seconds(2000000000) + absl::Nanoseconds(3);\n  EXPECT_EQ(absl::Seconds(666666666) + absl::Nanoseconds(666666667) +\n                absl::Nanoseconds(1) / 2,\n            sigfigs / 3);\n  sigfigs = absl::Seconds(int64_t{7000000000});\n  EXPECT_EQ(absl::Seconds(2333333333) + absl::Nanoseconds(333333333) +\n                absl::Nanoseconds(1) / 4,\n            sigfigs / 3);\n\n  EXPECT_EQ(absl::Seconds(7) + absl::Milliseconds(500), absl::Seconds(3) * 2.5);\n  EXPECT_EQ(absl::Seconds(8) * -1 + absl::Milliseconds(300),\n            (absl::Seconds(2) + absl::Milliseconds(200)) * -3.5);\n  EXPECT_EQ(-absl::Seconds(8) + absl::Milliseconds(300),\n            (absl::Seconds(2) + absl::Milliseconds(200)) * -3.5);\n  EXPECT_EQ(absl::Seconds(1) + absl::Milliseconds(875),\n            (absl::Seconds(7) + absl::Milliseconds(500)) / 4);\n  EXPECT_EQ(absl::Seconds(30),\n            (absl::Seconds(7) + absl::Milliseconds(500)) / 0.25);\n  EXPECT_EQ(absl::Seconds(3),\n            (absl::Seconds(7) + absl::Milliseconds(500)) / 2.5);\n\n  // Tests division remainder.\n  EXPECT_EQ(absl::Nanoseconds(0), absl::Nanoseconds(7) % absl::Nanoseconds(1));\n  EXPECT_EQ(absl::Nanoseconds(0), absl::Nanoseconds(0) % absl::Nanoseconds(10));\n  EXPECT_EQ(absl::Nanoseconds(2), absl::Nanoseconds(7) % absl::Nanoseconds(5));\n  EXPECT_EQ(absl::Nanoseconds(2), absl::Nanoseconds(2) % absl::Nanoseconds(5));\n\n  EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(10) % absl::Nanoseconds(3));\n  EXPECT_EQ(absl::Nanoseconds(1),\n            absl::Nanoseconds(10) % absl::Nanoseconds(-3));\n  EXPECT_EQ(absl::Nanoseconds(-1),\n            absl::Nanoseconds(-10) % absl::Nanoseconds(3));\n  EXPECT_EQ(absl::Nanoseconds(-1),\n            absl::Nanoseconds(-10) % absl::Nanoseconds(-3));\n\n  EXPECT_EQ(absl::Milliseconds(100),\n            absl::Seconds(1) % absl::Milliseconds(300));\n  EXPECT_EQ(\n      absl::Milliseconds(300),\n      (absl::Seconds(3) + absl::Milliseconds(800)) % absl::Milliseconds(500));\n\n  EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(1) % absl::Seconds(1));\n  EXPECT_EQ(absl::Nanoseconds(-1), absl::Nanoseconds(-1) % absl::Seconds(1));\n  EXPECT_EQ(0, absl::Nanoseconds(-1) / absl::Seconds(1));  // Actual -1e-9\n\n  // Tests identity a = (a/b)*b + a%b\n#define TEST_MOD_IDENTITY(a, b) EXPECT_EQ((a), ((a) / (b)) * (b) + ((a) % (b)))\n\n  TEST_MOD_IDENTITY(absl::Seconds(0), absl::Seconds(2));\n  TEST_MOD_IDENTITY(absl::Seconds(1), absl::Seconds(1));\n  TEST_MOD_IDENTITY(absl::Seconds(1), absl::Seconds(2));\n  TEST_MOD_IDENTITY(absl::Seconds(2), absl::Seconds(1));\n\n  TEST_MOD_IDENTITY(absl::Seconds(-2), absl::Seconds(1));\n  TEST_MOD_IDENTITY(absl::Seconds(2), absl::Seconds(-1));\n  TEST_MOD_IDENTITY(absl::Seconds(-2), absl::Seconds(-1));\n\n  TEST_MOD_IDENTITY(absl::Nanoseconds(0), absl::Nanoseconds(2));\n  TEST_MOD_IDENTITY(absl::Nanoseconds(1), absl::Nanoseconds(1));\n  TEST_MOD_IDENTITY(absl::Nanoseconds(1), absl::Nanoseconds(2));\n  TEST_MOD_IDENTITY(absl::Nanoseconds(2), absl::Nanoseconds(1));\n\n  TEST_MOD_IDENTITY(absl::Nanoseconds(-2), absl::Nanoseconds(1));\n  TEST_MOD_IDENTITY(absl::Nanoseconds(2), absl::Nanoseconds(-1));\n  TEST_MOD_IDENTITY(absl::Nanoseconds(-2), absl::Nanoseconds(-1));\n\n  // Mixed seconds + subseconds\n  absl::Duration mixed_a = absl::Seconds(1) + absl::Nanoseconds(2);\n  absl::Duration mixed_b = absl::Seconds(1) + absl::Nanoseconds(3);\n\n  TEST_MOD_IDENTITY(absl::Seconds(0), mixed_a);\n  TEST_MOD_IDENTITY(mixed_a, mixed_a);\n  TEST_MOD_IDENTITY(mixed_a, mixed_b);\n  TEST_MOD_IDENTITY(mixed_b, mixed_a);\n\n  TEST_MOD_IDENTITY(-mixed_a, mixed_b);\n  TEST_MOD_IDENTITY(mixed_a, -mixed_b);\n  TEST_MOD_IDENTITY(-mixed_a, -mixed_b);\n\n#undef TEST_MOD_IDENTITY\n}\n\nTEST(Duration, Truncation) {\n  const absl::Duration d = absl::Nanoseconds(1234567890);\n  const absl::Duration inf = absl::InfiniteDuration();\n  for (int unit_sign : {1, -1}) {  // sign shouldn't matter\n    EXPECT_EQ(absl::Nanoseconds(1234567890),\n              Trunc(d, unit_sign * absl::Nanoseconds(1)));\n    EXPECT_EQ(absl::Microseconds(1234567),\n              Trunc(d, unit_sign * absl::Microseconds(1)));\n    EXPECT_EQ(absl::Milliseconds(1234),\n              Trunc(d, unit_sign * absl::Milliseconds(1)));\n    EXPECT_EQ(absl::Seconds(1), Trunc(d, unit_sign * absl::Seconds(1)));\n    EXPECT_EQ(inf, Trunc(inf, unit_sign * absl::Seconds(1)));\n\n    EXPECT_EQ(absl::Nanoseconds(-1234567890),\n              Trunc(-d, unit_sign * absl::Nanoseconds(1)));\n    EXPECT_EQ(absl::Microseconds(-1234567),\n              Trunc(-d, unit_sign * absl::Microseconds(1)));\n    EXPECT_EQ(absl::Milliseconds(-1234),\n              Trunc(-d, unit_sign * absl::Milliseconds(1)));\n    EXPECT_EQ(absl::Seconds(-1), Trunc(-d, unit_sign * absl::Seconds(1)));\n    EXPECT_EQ(-inf, Trunc(-inf, unit_sign * absl::Seconds(1)));\n  }\n}\n\nTEST(Duration, Flooring) {\n  const absl::Duration d = absl::Nanoseconds(1234567890);\n  const absl::Duration inf = absl::InfiniteDuration();\n  for (int unit_sign : {1, -1}) {  // sign shouldn't matter\n    EXPECT_EQ(absl::Nanoseconds(1234567890),\n              absl::Floor(d, unit_sign * absl::Nanoseconds(1)));\n    EXPECT_EQ(absl::Microseconds(1234567),\n              absl::Floor(d, unit_sign * absl::Microseconds(1)));\n    EXPECT_EQ(absl::Milliseconds(1234),\n              absl::Floor(d, unit_sign * absl::Milliseconds(1)));\n    EXPECT_EQ(absl::Seconds(1), absl::Floor(d, unit_sign * absl::Seconds(1)));\n    EXPECT_EQ(inf, absl::Floor(inf, unit_sign * absl::Seconds(1)));\n\n    EXPECT_EQ(absl::Nanoseconds(-1234567890),\n              absl::Floor(-d, unit_sign * absl::Nanoseconds(1)));\n    EXPECT_EQ(absl::Microseconds(-1234568),\n              absl::Floor(-d, unit_sign * absl::Microseconds(1)));\n    EXPECT_EQ(absl::Milliseconds(-1235),\n              absl::Floor(-d, unit_sign * absl::Milliseconds(1)));\n    EXPECT_EQ(absl::Seconds(-2), absl::Floor(-d, unit_sign * absl::Seconds(1)));\n    EXPECT_EQ(-inf, absl::Floor(-inf, unit_sign * absl::Seconds(1)));\n  }\n}\n\nTEST(Duration, Ceiling) {\n  const absl::Duration d = absl::Nanoseconds(1234567890);\n  const absl::Duration inf = absl::InfiniteDuration();\n  for (int unit_sign : {1, -1}) {  // // sign shouldn't matter\n    EXPECT_EQ(absl::Nanoseconds(1234567890),\n              absl::Ceil(d, unit_sign * absl::Nanoseconds(1)));\n    EXPECT_EQ(absl::Microseconds(1234568),\n              absl::Ceil(d, unit_sign * absl::Microseconds(1)));\n    EXPECT_EQ(absl::Milliseconds(1235),\n              absl::Ceil(d, unit_sign * absl::Milliseconds(1)));\n    EXPECT_EQ(absl::Seconds(2), absl::Ceil(d, unit_sign * absl::Seconds(1)));\n    EXPECT_EQ(inf, absl::Ceil(inf, unit_sign * absl::Seconds(1)));\n\n    EXPECT_EQ(absl::Nanoseconds(-1234567890),\n              absl::Ceil(-d, unit_sign * absl::Nanoseconds(1)));\n    EXPECT_EQ(absl::Microseconds(-1234567),\n              absl::Ceil(-d, unit_sign * absl::Microseconds(1)));\n    EXPECT_EQ(absl::Milliseconds(-1234),\n              absl::Ceil(-d, unit_sign * absl::Milliseconds(1)));\n    EXPECT_EQ(absl::Seconds(-1), absl::Ceil(-d, unit_sign * absl::Seconds(1)));\n    EXPECT_EQ(-inf, absl::Ceil(-inf, unit_sign * absl::Seconds(1)));\n  }\n}\n\nTEST(Duration, RoundTripUnits) {\n  const int kRange = 100000;\n\n#define ROUND_TRIP_UNIT(U, LOW, HIGH)          \\\n  do {                                         \\\n    for (int64_t i = LOW; i < HIGH; ++i) {     \\\n      absl::Duration d = absl::U(i);           \\\n      if (d == absl::InfiniteDuration())       \\\n        EXPECT_EQ(kint64max, d / absl::U(1));  \\\n      else if (d == -absl::InfiniteDuration()) \\\n        EXPECT_EQ(kint64min, d / absl::U(1));  \\\n      else                                     \\\n        EXPECT_EQ(i, absl::U(i) / absl::U(1)); \\\n    }                                          \\\n  } while (0)\n\n  ROUND_TRIP_UNIT(Nanoseconds, kint64min, kint64min + kRange);\n  ROUND_TRIP_UNIT(Nanoseconds, -kRange, kRange);\n  ROUND_TRIP_UNIT(Nanoseconds, kint64max - kRange, kint64max);\n\n  ROUND_TRIP_UNIT(Microseconds, kint64min, kint64min + kRange);\n  ROUND_TRIP_UNIT(Microseconds, -kRange, kRange);\n  ROUND_TRIP_UNIT(Microseconds, kint64max - kRange, kint64max);\n\n  ROUND_TRIP_UNIT(Milliseconds, kint64min, kint64min + kRange);\n  ROUND_TRIP_UNIT(Milliseconds, -kRange, kRange);\n  ROUND_TRIP_UNIT(Milliseconds, kint64max - kRange, kint64max);\n\n  ROUND_TRIP_UNIT(Seconds, kint64min, kint64min + kRange);\n  ROUND_TRIP_UNIT(Seconds, -kRange, kRange);\n  ROUND_TRIP_UNIT(Seconds, kint64max - kRange, kint64max);\n\n  ROUND_TRIP_UNIT(Minutes, kint64min / 60, kint64min / 60 + kRange);\n  ROUND_TRIP_UNIT(Minutes, -kRange, kRange);\n  ROUND_TRIP_UNIT(Minutes, kint64max / 60 - kRange, kint64max / 60);\n\n  ROUND_TRIP_UNIT(Hours, kint64min / 3600, kint64min / 3600 + kRange);\n  ROUND_TRIP_UNIT(Hours, -kRange, kRange);\n  ROUND_TRIP_UNIT(Hours, kint64max / 3600 - kRange, kint64max / 3600);\n\n#undef ROUND_TRIP_UNIT\n}\n\nTEST(Duration, TruncConversions) {\n  // Tests ToTimespec()/DurationFromTimespec()\n  const struct {\n    absl::Duration d;\n    timespec ts;\n  } to_ts[] = {\n      {absl::Seconds(1) + absl::Nanoseconds(1), {1, 1}},\n      {absl::Seconds(1) + absl::Nanoseconds(1) / 2, {1, 0}},\n      {absl::Seconds(1) + absl::Nanoseconds(0), {1, 0}},\n      {absl::Seconds(0) + absl::Nanoseconds(0), {0, 0}},\n      {absl::Seconds(0) - absl::Nanoseconds(1) / 2, {0, 0}},\n      {absl::Seconds(0) - absl::Nanoseconds(1), {-1, 999999999}},\n      {absl::Seconds(-1) + absl::Nanoseconds(1), {-1, 1}},\n      {absl::Seconds(-1) + absl::Nanoseconds(1) / 2, {-1, 1}},\n      {absl::Seconds(-1) + absl::Nanoseconds(0), {-1, 0}},\n      {absl::Seconds(-1) - absl::Nanoseconds(1) / 2, {-1, 0}},\n  };\n  for (const auto& test : to_ts) {\n    EXPECT_THAT(absl::ToTimespec(test.d), TimespecMatcher(test.ts));\n  }\n  const struct {\n    timespec ts;\n    absl::Duration d;\n  } from_ts[] = {\n      {{1, 1}, absl::Seconds(1) + absl::Nanoseconds(1)},\n      {{1, 0}, absl::Seconds(1) + absl::Nanoseconds(0)},\n      {{0, 0}, absl::Seconds(0) + absl::Nanoseconds(0)},\n      {{0, -1}, absl::Seconds(0) - absl::Nanoseconds(1)},\n      {{-1, 999999999}, absl::Seconds(0) - absl::Nanoseconds(1)},\n      {{-1, 1}, absl::Seconds(-1) + absl::Nanoseconds(1)},\n      {{-1, 0}, absl::Seconds(-1) + absl::Nanoseconds(0)},\n      {{-1, -1}, absl::Seconds(-1) - absl::Nanoseconds(1)},\n      {{-2, 999999999}, absl::Seconds(-1) - absl::Nanoseconds(1)},\n  };\n  for (const auto& test : from_ts) {\n    EXPECT_EQ(test.d, absl::DurationFromTimespec(test.ts));\n  }\n\n  // Tests ToTimeval()/DurationFromTimeval() (same as timespec above)\n  const struct {\n    absl::Duration d;\n    timeval tv;\n  } to_tv[] = {\n      {absl::Seconds(1) + absl::Microseconds(1), {1, 1}},\n      {absl::Seconds(1) + absl::Microseconds(1) / 2, {1, 0}},\n      {absl::Seconds(1) + absl::Microseconds(0), {1, 0}},\n      {absl::Seconds(0) + absl::Microseconds(0), {0, 0}},\n      {absl::Seconds(0) - absl::Microseconds(1) / 2, {0, 0}},\n      {absl::Seconds(0) - absl::Microseconds(1), {-1, 999999}},\n      {absl::Seconds(-1) + absl::Microseconds(1), {-1, 1}},\n      {absl::Seconds(-1) + absl::Microseconds(1) / 2, {-1, 1}},\n      {absl::Seconds(-1) + absl::Microseconds(0), {-1, 0}},\n      {absl::Seconds(-1) - absl::Microseconds(1) / 2, {-1, 0}},\n  };\n  for (const auto& test : to_tv) {\n    EXPECT_THAT(absl::ToTimeval(test.d), TimevalMatcher(test.tv));\n  }\n  const struct {\n    timeval tv;\n    absl::Duration d;\n  } from_tv[] = {\n      {{1, 1}, absl::Seconds(1) + absl::Microseconds(1)},\n      {{1, 0}, absl::Seconds(1) + absl::Microseconds(0)},\n      {{0, 0}, absl::Seconds(0) + absl::Microseconds(0)},\n      {{0, -1}, absl::Seconds(0) - absl::Microseconds(1)},\n      {{-1, 999999}, absl::Seconds(0) - absl::Microseconds(1)},\n      {{-1, 1}, absl::Seconds(-1) + absl::Microseconds(1)},\n      {{-1, 0}, absl::Seconds(-1) + absl::Microseconds(0)},\n      {{-1, -1}, absl::Seconds(-1) - absl::Microseconds(1)},\n      {{-2, 999999}, absl::Seconds(-1) - absl::Microseconds(1)},\n  };\n  for (const auto& test : from_tv) {\n    EXPECT_EQ(test.d, absl::DurationFromTimeval(test.tv));\n  }\n}\n\nTEST(Duration, SmallConversions) {\n  // Special tests for conversions of small durations.\n\n  EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0));\n  // TODO(bww): Is the next one OK?\n  EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(0.125e-9, 0)));\n  EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.125e-9));\n  EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.250e-9));\n  EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.375e-9));\n  EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.500e-9));\n  EXPECT_EQ(absl::Nanoseconds(3) / 4, absl::Seconds(0.625e-9));\n  EXPECT_EQ(absl::Nanoseconds(3) / 4, absl::Seconds(0.750e-9));\n  EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9));\n  EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9));\n\n  EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(-0.125e-9, 0)));\n  EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9));\n  EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9));\n  EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9));\n  EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.500e-9));\n  EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.625e-9));\n  EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.750e-9));\n  EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-0.875e-9));\n  EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-1.000e-9));\n\n  timespec ts;\n  ts.tv_sec = 0;\n  ts.tv_nsec = 0;\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(0)), TimespecMatcher(ts));\n  // TODO(bww): Are the next three OK?\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(1) / 4), TimespecMatcher(ts));\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(2) / 4), TimespecMatcher(ts));\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(3) / 4), TimespecMatcher(ts));\n  ts.tv_nsec = 1;\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(4) / 4), TimespecMatcher(ts));\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(5) / 4), TimespecMatcher(ts));\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(6) / 4), TimespecMatcher(ts));\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(7) / 4), TimespecMatcher(ts));\n  ts.tv_nsec = 2;\n  EXPECT_THAT(ToTimespec(absl::Nanoseconds(8) / 4), TimespecMatcher(ts));\n\n  timeval tv;\n  tv.tv_sec = 0;\n  tv.tv_usec = 0;\n  EXPECT_THAT(ToTimeval(absl::Nanoseconds(0)), TimevalMatcher(tv));\n  // TODO(bww): Is the next one OK?\n  EXPECT_THAT(ToTimeval(absl::Nanoseconds(999)), TimevalMatcher(tv));\n  tv.tv_usec = 1;\n  EXPECT_THAT(ToTimeval(absl::Nanoseconds(1000)), TimevalMatcher(tv));\n  EXPECT_THAT(ToTimeval(absl::Nanoseconds(1999)), TimevalMatcher(tv));\n  tv.tv_usec = 2;\n  EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv));\n}\n\nvoid VerifyApproxSameAsMul(double time_as_seconds, int* const misses) {\n  auto direct_seconds = absl::Seconds(time_as_seconds);\n  auto mul_by_one_second = time_as_seconds * absl::Seconds(1);\n  // These are expected to differ by up to one tick due to fused multiply/add\n  // contraction.\n  if (absl::AbsDuration(direct_seconds - mul_by_one_second) >\n      absl::time_internal::MakeDuration(0, 1u)) {\n    if (*misses > 10) return;\n    ASSERT_LE(++(*misses), 10) << \"Too many errors, not reporting more.\";\n    EXPECT_EQ(direct_seconds, mul_by_one_second)\n        << \"given double time_as_seconds = \" << std::setprecision(17)\n        << time_as_seconds;\n  }\n}\n\n// For a variety of interesting durations, we find the exact point\n// where one double converts to that duration, and the very next double\n// converts to the next duration.  For both of those points, verify that\n// Seconds(point) returns a duration near point * Seconds(1.0). (They may\n// not be exactly equal due to fused multiply/add contraction.)\nTEST(Duration, ToDoubleSecondsCheckEdgeCases) {\n#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0\n  // We're using an x87-compatible FPU, and intermediate operations can be\n  // performed with 80-bit floats. This means the edge cases are different than\n  // what we expect here, so just skip this test.\n  GTEST_SKIP()\n      << \"Skipping the test because we detected x87 floating-point semantics\";\n#endif\n\n  constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond;\n  constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u);\n  int misses = 0;\n  for (int64_t seconds = 0; seconds < 99; ++seconds) {\n    uint32_t tick_vals[] = {0, +999, +999999, +999999999, kTicksPerSecond - 1,\n                            0, 1000, 1000000, 1000000000, kTicksPerSecond,\n                            1, 1001, 1000001, 1000000001, kTicksPerSecond + 1,\n                            2, 1002, 1000002, 1000000002, kTicksPerSecond + 2,\n                            3, 1003, 1000003, 1000000003, kTicksPerSecond + 3,\n                            4, 1004, 1000004, 1000000004, kTicksPerSecond + 4,\n                            5, 6,    7,       8,          9};\n    for (uint32_t ticks : tick_vals) {\n      absl::Duration s_plus_t = absl::Seconds(seconds) + ticks * duration_tick;\n      for (absl::Duration d : {s_plus_t, -s_plus_t}) {\n        absl::Duration after_d = d + duration_tick;\n        EXPECT_NE(d, after_d);\n        EXPECT_EQ(after_d - d, duration_tick);\n\n        double low_edge = ToDoubleSeconds(d);\n        EXPECT_EQ(d, absl::Seconds(low_edge));\n\n        double high_edge = ToDoubleSeconds(after_d);\n        EXPECT_EQ(after_d, absl::Seconds(high_edge));\n\n        for (;;) {\n          double midpoint = low_edge + (high_edge - low_edge) / 2;\n          if (midpoint == low_edge || midpoint == high_edge) break;\n          absl::Duration mid_duration = absl::Seconds(midpoint);\n          if (mid_duration == d) {\n            low_edge = midpoint;\n          } else {\n            EXPECT_EQ(mid_duration, after_d);\n            high_edge = midpoint;\n          }\n        }\n        // Now low_edge is the highest double that converts to Duration d,\n        // and high_edge is the lowest double that converts to Duration after_d.\n        VerifyApproxSameAsMul(low_edge, &misses);\n        VerifyApproxSameAsMul(high_edge, &misses);\n      }\n    }\n  }\n}\n\nTEST(Duration, ToDoubleSecondsCheckRandom) {\n  absl::InsecureBitGen gen;\n  // We want doubles distributed from 1/8ns up to 2^63, where\n  // as many values are tested from 1ns to 2ns as from 1sec to 2sec,\n  // so even distribute along a log-scale of those values, and\n  // exponentiate before using them.  (9.223377e+18 is just slightly\n  // out of bounds for absl::Duration.)\n  std::uniform_real_distribution<double> uniform(std::log(0.125e-9),\n                                                 std::log(9.223377e+18));\n  int misses = 0;\n  for (int i = 0; i < 1000000; ++i) {\n    double d = std::exp(uniform(gen));\n    VerifyApproxSameAsMul(d, &misses);\n    VerifyApproxSameAsMul(-d, &misses);\n  }\n}\n\nTEST(Duration, ConversionSaturation) {\n  absl::Duration d;\n\n  const auto max_timeval_sec =\n      std::numeric_limits<decltype(timeval::tv_sec)>::max();\n  const auto min_timeval_sec =\n      std::numeric_limits<decltype(timeval::tv_sec)>::min();\n  timeval tv;\n  tv.tv_sec = max_timeval_sec;\n  tv.tv_usec = 999998;\n  d = absl::DurationFromTimeval(tv);\n  tv = ToTimeval(d);\n  EXPECT_EQ(max_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(999998, tv.tv_usec);\n  d += absl::Microseconds(1);\n  tv = ToTimeval(d);\n  EXPECT_EQ(max_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(999999, tv.tv_usec);\n  d += absl::Microseconds(1);  // no effect\n  tv = ToTimeval(d);\n  EXPECT_EQ(max_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(999999, tv.tv_usec);\n\n  tv.tv_sec = min_timeval_sec;\n  tv.tv_usec = 1;\n  d = absl::DurationFromTimeval(tv);\n  tv = ToTimeval(d);\n  EXPECT_EQ(min_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(1, tv.tv_usec);\n  d -= absl::Microseconds(1);\n  tv = ToTimeval(d);\n  EXPECT_EQ(min_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(0, tv.tv_usec);\n  d -= absl::Microseconds(1);  // no effect\n  tv = ToTimeval(d);\n  EXPECT_EQ(min_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(0, tv.tv_usec);\n\n  const auto max_timespec_sec =\n      std::numeric_limits<decltype(timespec::tv_sec)>::max();\n  const auto min_timespec_sec =\n      std::numeric_limits<decltype(timespec::tv_sec)>::min();\n  timespec ts;\n  ts.tv_sec = max_timespec_sec;\n  ts.tv_nsec = 999999998;\n  d = absl::DurationFromTimespec(ts);\n  ts = absl::ToTimespec(d);\n  EXPECT_EQ(max_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(999999998, ts.tv_nsec);\n  d += absl::Nanoseconds(1);\n  ts = absl::ToTimespec(d);\n  EXPECT_EQ(max_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(999999999, ts.tv_nsec);\n  d += absl::Nanoseconds(1);  // no effect\n  ts = absl::ToTimespec(d);\n  EXPECT_EQ(max_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(999999999, ts.tv_nsec);\n\n  ts.tv_sec = min_timespec_sec;\n  ts.tv_nsec = 1;\n  d = absl::DurationFromTimespec(ts);\n  ts = absl::ToTimespec(d);\n  EXPECT_EQ(min_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(1, ts.tv_nsec);\n  d -= absl::Nanoseconds(1);\n  ts = absl::ToTimespec(d);\n  EXPECT_EQ(min_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(0, ts.tv_nsec);\n  d -= absl::Nanoseconds(1);  // no effect\n  ts = absl::ToTimespec(d);\n  EXPECT_EQ(min_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(0, ts.tv_nsec);\n}\n\nTEST(Duration, FormatDuration) {\n  // Example from Go's docs.\n  EXPECT_EQ(\"72h3m0.5s\",\n            absl::FormatDuration(absl::Hours(72) + absl::Minutes(3) +\n                                 absl::Milliseconds(500)));\n  // Go's largest time: 2540400h10m10.000000000s\n  EXPECT_EQ(\"2540400h10m10s\",\n            absl::FormatDuration(absl::Hours(2540400) + absl::Minutes(10) +\n                                 absl::Seconds(10)));\n\n  EXPECT_EQ(\"0\", absl::FormatDuration(absl::ZeroDuration()));\n  EXPECT_EQ(\"0\", absl::FormatDuration(absl::Seconds(0)));\n  EXPECT_EQ(\"0\", absl::FormatDuration(absl::Nanoseconds(0)));\n\n  EXPECT_EQ(\"1ns\", absl::FormatDuration(absl::Nanoseconds(1)));\n  EXPECT_EQ(\"1us\", absl::FormatDuration(absl::Microseconds(1)));\n  EXPECT_EQ(\"1ms\", absl::FormatDuration(absl::Milliseconds(1)));\n  EXPECT_EQ(\"1s\", absl::FormatDuration(absl::Seconds(1)));\n  EXPECT_EQ(\"1m\", absl::FormatDuration(absl::Minutes(1)));\n  EXPECT_EQ(\"1h\", absl::FormatDuration(absl::Hours(1)));\n\n  EXPECT_EQ(\"1h1m\", absl::FormatDuration(absl::Hours(1) + absl::Minutes(1)));\n  EXPECT_EQ(\"1h1s\", absl::FormatDuration(absl::Hours(1) + absl::Seconds(1)));\n  EXPECT_EQ(\"1m1s\", absl::FormatDuration(absl::Minutes(1) + absl::Seconds(1)));\n\n  EXPECT_EQ(\"1h0.25s\",\n            absl::FormatDuration(absl::Hours(1) + absl::Milliseconds(250)));\n  EXPECT_EQ(\"1m0.25s\",\n            absl::FormatDuration(absl::Minutes(1) + absl::Milliseconds(250)));\n  EXPECT_EQ(\"1h1m0.25s\",\n            absl::FormatDuration(absl::Hours(1) + absl::Minutes(1) +\n                                 absl::Milliseconds(250)));\n  EXPECT_EQ(\"1h0.0005s\",\n            absl::FormatDuration(absl::Hours(1) + absl::Microseconds(500)));\n  EXPECT_EQ(\"1h0.0000005s\",\n            absl::FormatDuration(absl::Hours(1) + absl::Nanoseconds(500)));\n\n  // Subsecond special case.\n  EXPECT_EQ(\"1.5ns\", absl::FormatDuration(absl::Nanoseconds(1) +\n                                          absl::Nanoseconds(1) / 2));\n  EXPECT_EQ(\"1.25ns\", absl::FormatDuration(absl::Nanoseconds(1) +\n                                           absl::Nanoseconds(1) / 4));\n  EXPECT_EQ(\"1ns\", absl::FormatDuration(absl::Nanoseconds(1) +\n                                        absl::Nanoseconds(1) / 9));\n  EXPECT_EQ(\"1.2us\", absl::FormatDuration(absl::Microseconds(1) +\n                                          absl::Nanoseconds(200)));\n  EXPECT_EQ(\"1.2ms\", absl::FormatDuration(absl::Milliseconds(1) +\n                                          absl::Microseconds(200)));\n  EXPECT_EQ(\"1.0002ms\", absl::FormatDuration(absl::Milliseconds(1) +\n                                             absl::Nanoseconds(200)));\n  EXPECT_EQ(\"1.00001ms\", absl::FormatDuration(absl::Milliseconds(1) +\n                                              absl::Nanoseconds(10)));\n  EXPECT_EQ(\"1.000001ms\",\n            absl::FormatDuration(absl::Milliseconds(1) + absl::Nanoseconds(1)));\n\n  // Negative durations.\n  EXPECT_EQ(\"-1ns\", absl::FormatDuration(absl::Nanoseconds(-1)));\n  EXPECT_EQ(\"-1us\", absl::FormatDuration(absl::Microseconds(-1)));\n  EXPECT_EQ(\"-1ms\", absl::FormatDuration(absl::Milliseconds(-1)));\n  EXPECT_EQ(\"-1s\", absl::FormatDuration(absl::Seconds(-1)));\n  EXPECT_EQ(\"-1m\", absl::FormatDuration(absl::Minutes(-1)));\n  EXPECT_EQ(\"-1h\", absl::FormatDuration(absl::Hours(-1)));\n\n  EXPECT_EQ(\"-1h1m\",\n            absl::FormatDuration(-(absl::Hours(1) + absl::Minutes(1))));\n  EXPECT_EQ(\"-1h1s\",\n            absl::FormatDuration(-(absl::Hours(1) + absl::Seconds(1))));\n  EXPECT_EQ(\"-1m1s\",\n            absl::FormatDuration(-(absl::Minutes(1) + absl::Seconds(1))));\n\n  EXPECT_EQ(\"-1ns\", absl::FormatDuration(absl::Nanoseconds(-1)));\n  EXPECT_EQ(\"-1.2us\", absl::FormatDuration(\n                          -(absl::Microseconds(1) + absl::Nanoseconds(200))));\n  EXPECT_EQ(\"-1.2ms\", absl::FormatDuration(\n                          -(absl::Milliseconds(1) + absl::Microseconds(200))));\n  EXPECT_EQ(\"-1.0002ms\", absl::FormatDuration(-(absl::Milliseconds(1) +\n                                                absl::Nanoseconds(200))));\n  EXPECT_EQ(\"-1.00001ms\", absl::FormatDuration(-(absl::Milliseconds(1) +\n                                                 absl::Nanoseconds(10))));\n  EXPECT_EQ(\"-1.000001ms\", absl::FormatDuration(-(absl::Milliseconds(1) +\n                                                  absl::Nanoseconds(1))));\n\n  //\n  // Interesting corner cases.\n  //\n\n  const absl::Duration qns = absl::Nanoseconds(1) / 4;\n  const absl::Duration max_dur =\n      absl::Seconds(kint64max) + (absl::Seconds(1) - qns);\n  const absl::Duration min_dur = absl::Seconds(kint64min);\n\n  EXPECT_EQ(\"0.25ns\", absl::FormatDuration(qns));\n  EXPECT_EQ(\"-0.25ns\", absl::FormatDuration(-qns));\n  EXPECT_EQ(\"2562047788015215h30m7.99999999975s\",\n            absl::FormatDuration(max_dur));\n  EXPECT_EQ(\"-2562047788015215h30m8s\", absl::FormatDuration(min_dur));\n\n  // Tests printing full precision from units that print using FDivDuration\n  EXPECT_EQ(\"55.00000000025s\", absl::FormatDuration(absl::Seconds(55) + qns));\n  EXPECT_EQ(\"55.00000025ms\",\n            absl::FormatDuration(absl::Milliseconds(55) + qns));\n  EXPECT_EQ(\"55.00025us\", absl::FormatDuration(absl::Microseconds(55) + qns));\n  EXPECT_EQ(\"55.25ns\", absl::FormatDuration(absl::Nanoseconds(55) + qns));\n\n  // Formatting infinity\n  EXPECT_EQ(\"inf\", absl::FormatDuration(absl::InfiniteDuration()));\n  EXPECT_EQ(\"-inf\", absl::FormatDuration(-absl::InfiniteDuration()));\n\n  // Formatting approximately +/- 100 billion years\n  const absl::Duration huge_range = ApproxYears(100000000000);\n  EXPECT_EQ(\"876000000000000h\", absl::FormatDuration(huge_range));\n  EXPECT_EQ(\"-876000000000000h\", absl::FormatDuration(-huge_range));\n\n  EXPECT_EQ(\"876000000000000h0.999999999s\",\n            absl::FormatDuration(huge_range +\n                                 (absl::Seconds(1) - absl::Nanoseconds(1))));\n  EXPECT_EQ(\"876000000000000h0.9999999995s\",\n            absl::FormatDuration(\n                huge_range + (absl::Seconds(1) - absl::Nanoseconds(1) / 2)));\n  EXPECT_EQ(\"876000000000000h0.99999999975s\",\n            absl::FormatDuration(\n                huge_range + (absl::Seconds(1) - absl::Nanoseconds(1) / 4)));\n\n  EXPECT_EQ(\"-876000000000000h0.999999999s\",\n            absl::FormatDuration(-huge_range -\n                                 (absl::Seconds(1) - absl::Nanoseconds(1))));\n  EXPECT_EQ(\"-876000000000000h0.9999999995s\",\n            absl::FormatDuration(\n                -huge_range - (absl::Seconds(1) - absl::Nanoseconds(1) / 2)));\n  EXPECT_EQ(\"-876000000000000h0.99999999975s\",\n            absl::FormatDuration(\n                -huge_range - (absl::Seconds(1) - absl::Nanoseconds(1) / 4)));\n}\n\nTEST(Duration, ParseDuration) {\n  absl::Duration d;\n\n  // No specified unit. Should only work for zero and infinity.\n  EXPECT_TRUE(absl::ParseDuration(\"0\", &d));\n  EXPECT_EQ(absl::ZeroDuration(), d);\n  EXPECT_TRUE(absl::ParseDuration(\"+0\", &d));\n  EXPECT_EQ(absl::ZeroDuration(), d);\n  EXPECT_TRUE(absl::ParseDuration(\"-0\", &d));\n  EXPECT_EQ(absl::ZeroDuration(), d);\n\n  EXPECT_TRUE(absl::ParseDuration(\"inf\", &d));\n  EXPECT_EQ(absl::InfiniteDuration(), d);\n  EXPECT_TRUE(absl::ParseDuration(\"+inf\", &d));\n  EXPECT_EQ(absl::InfiniteDuration(), d);\n  EXPECT_TRUE(absl::ParseDuration(\"-inf\", &d));\n  EXPECT_EQ(-absl::InfiniteDuration(), d);\n  EXPECT_FALSE(absl::ParseDuration(\"infBlah\", &d));\n\n  // Illegal input forms.\n  EXPECT_FALSE(absl::ParseDuration(\"\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"0.0\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\".0\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\".\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"01\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"1\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"-1\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"2\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"2 s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\".s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"-.s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\" 2s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"2s \", &d));\n  EXPECT_FALSE(absl::ParseDuration(\" 2s \", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"2mt\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"1e3s\", &d));\n\n  // One unit type.\n  EXPECT_TRUE(absl::ParseDuration(\"1ns\", &d));\n  EXPECT_EQ(absl::Nanoseconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1us\", &d));\n  EXPECT_EQ(absl::Microseconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1ms\", &d));\n  EXPECT_EQ(absl::Milliseconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1s\", &d));\n  EXPECT_EQ(absl::Seconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"2m\", &d));\n  EXPECT_EQ(absl::Minutes(2), d);\n  EXPECT_TRUE(absl::ParseDuration(\"2h\", &d));\n  EXPECT_EQ(absl::Hours(2), d);\n\n  // Huge counts of a unit.\n  EXPECT_TRUE(absl::ParseDuration(\"9223372036854775807us\", &d));\n  EXPECT_EQ(absl::Microseconds(9223372036854775807), d);\n  EXPECT_TRUE(absl::ParseDuration(\"-9223372036854775807us\", &d));\n  EXPECT_EQ(absl::Microseconds(-9223372036854775807), d);\n\n  // Multiple units.\n  EXPECT_TRUE(absl::ParseDuration(\"2h3m4s\", &d));\n  EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4), d);\n  EXPECT_TRUE(absl::ParseDuration(\"3m4s5us\", &d));\n  EXPECT_EQ(absl::Minutes(3) + absl::Seconds(4) + absl::Microseconds(5), d);\n  EXPECT_TRUE(absl::ParseDuration(\"2h3m4s5ms6us7ns\", &d));\n  EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4) +\n                absl::Milliseconds(5) + absl::Microseconds(6) +\n                absl::Nanoseconds(7),\n            d);\n\n  // Multiple units out of order.\n  EXPECT_TRUE(absl::ParseDuration(\"2us3m4s5h\", &d));\n  EXPECT_EQ(absl::Hours(5) + absl::Minutes(3) + absl::Seconds(4) +\n                absl::Microseconds(2),\n            d);\n\n  // Fractional values of units.\n  EXPECT_TRUE(absl::ParseDuration(\"1.5ns\", &d));\n  EXPECT_EQ(1.5 * absl::Nanoseconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1.5us\", &d));\n  EXPECT_EQ(1.5 * absl::Microseconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1.5ms\", &d));\n  EXPECT_EQ(1.5 * absl::Milliseconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1.5s\", &d));\n  EXPECT_EQ(1.5 * absl::Seconds(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1.5m\", &d));\n  EXPECT_EQ(1.5 * absl::Minutes(1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"1.5h\", &d));\n  EXPECT_EQ(1.5 * absl::Hours(1), d);\n\n  // Huge fractional counts of a unit.\n  EXPECT_TRUE(absl::ParseDuration(\"0.4294967295s\", &d));\n  EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d);\n  EXPECT_TRUE(absl::ParseDuration(\"0.429496729501234567890123456789s\", &d));\n  EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d);\n\n  // Negative durations.\n  EXPECT_TRUE(absl::ParseDuration(\"-1s\", &d));\n  EXPECT_EQ(absl::Seconds(-1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"-1m\", &d));\n  EXPECT_EQ(absl::Minutes(-1), d);\n  EXPECT_TRUE(absl::ParseDuration(\"-1h\", &d));\n  EXPECT_EQ(absl::Hours(-1), d);\n\n  EXPECT_TRUE(absl::ParseDuration(\"-1h2s\", &d));\n  EXPECT_EQ(-(absl::Hours(1) + absl::Seconds(2)), d);\n  EXPECT_FALSE(absl::ParseDuration(\"1h-2s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"-1h-2s\", &d));\n  EXPECT_FALSE(absl::ParseDuration(\"-1h -2s\", &d));\n}\n\nTEST(Duration, FormatParseRoundTrip) {\n#define TEST_PARSE_ROUNDTRIP(d)                \\\n  do {                                         \\\n    std::string s = absl::FormatDuration(d);   \\\n    absl::Duration dur;                        \\\n    EXPECT_TRUE(absl::ParseDuration(s, &dur)); \\\n    EXPECT_EQ(d, dur);                         \\\n  } while (0)\n\n  TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1));\n  TEST_PARSE_ROUNDTRIP(absl::Microseconds(1));\n  TEST_PARSE_ROUNDTRIP(absl::Milliseconds(1));\n  TEST_PARSE_ROUNDTRIP(absl::Seconds(1));\n  TEST_PARSE_ROUNDTRIP(absl::Minutes(1));\n  TEST_PARSE_ROUNDTRIP(absl::Hours(1));\n  TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(2));\n\n  TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(-1));\n  TEST_PARSE_ROUNDTRIP(absl::Microseconds(-1));\n  TEST_PARSE_ROUNDTRIP(absl::Milliseconds(-1));\n  TEST_PARSE_ROUNDTRIP(absl::Seconds(-1));\n  TEST_PARSE_ROUNDTRIP(absl::Minutes(-1));\n  TEST_PARSE_ROUNDTRIP(absl::Hours(-1));\n\n  TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(2));\n  TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(-2));\n  TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(-2));\n\n  TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1) +\n                       absl::Nanoseconds(1) / 4);  // 1.25ns\n\n  const absl::Duration huge_range = ApproxYears(100000000000);\n  TEST_PARSE_ROUNDTRIP(huge_range);\n  TEST_PARSE_ROUNDTRIP(huge_range + (absl::Seconds(1) - absl::Nanoseconds(1)));\n\n#undef TEST_PARSE_ROUNDTRIP\n}\n\nTEST(Duration, AbslStringify) {\n  // FormatDuration is already well tested, so just use one test case here to\n  // verify that StrFormat(\"%v\", d) works as expected.\n  absl::Duration d = absl::Seconds(1);\n  EXPECT_EQ(absl::StrFormat(\"%v\", d), absl::FormatDuration(d));\n}\n\nTEST(Duration, NoPadding) {\n  // Should match the size of a struct with uint32_t alignment and no padding.\n  using NoPadding = std::array<uint32_t, 3>;\n  EXPECT_EQ(sizeof(NoPadding), sizeof(absl::Duration));\n  EXPECT_EQ(alignof(NoPadding), alignof(absl::Duration));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/flag_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/flags/flag.h\"\n\n#include <string>\n\n#include \"gtest/gtest.h\"\n#include \"absl/flags/reflection.h\"\n#include \"absl/time/civil_time.h\"\n#include \"absl/time/time.h\"\n\nABSL_FLAG(absl::CivilSecond, test_flag_civil_second,\n          absl::CivilSecond(2015, 1, 2, 3, 4, 5), \"\");\nABSL_FLAG(absl::CivilMinute, test_flag_civil_minute,\n          absl::CivilMinute(2015, 1, 2, 3, 4), \"\");\nABSL_FLAG(absl::CivilHour, test_flag_civil_hour, absl::CivilHour(2015, 1, 2, 3),\n          \"\");\nABSL_FLAG(absl::CivilDay, test_flag_civil_day, absl::CivilDay(2015, 1, 2), \"\");\nABSL_FLAG(absl::CivilMonth, test_flag_civil_month, absl::CivilMonth(2015, 1),\n          \"\");\nABSL_FLAG(absl::CivilYear, test_flag_civil_year, absl::CivilYear(2015), \"\");\n\nABSL_FLAG(absl::Duration, test_duration_flag, absl::Seconds(5),\n          \"For testing support for Duration flags\");\nABSL_FLAG(absl::Time, test_time_flag, absl::InfinitePast(),\n          \"For testing support for Time flags\");\n\nnamespace {\n\nbool SetFlagValue(absl::string_view flag_name, absl::string_view value) {\n  auto* flag = absl::FindCommandLineFlag(flag_name);\n  if (!flag) return false;\n  std::string err;\n  return flag->ParseFrom(value, &err);\n}\n\nbool GetFlagValue(absl::string_view flag_name, std::string& value) {\n  auto* flag = absl::FindCommandLineFlag(flag_name);\n  if (!flag) return false;\n  value = flag->CurrentValue();\n  return true;\n}\n\nTEST(CivilTime, FlagSupport) {\n  // Tests the default setting of the flags.\n  const absl::CivilSecond kDefaultSec(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(absl::CivilSecond(kDefaultSec),\n            absl::GetFlag(FLAGS_test_flag_civil_second));\n  EXPECT_EQ(absl::CivilMinute(kDefaultSec),\n            absl::GetFlag(FLAGS_test_flag_civil_minute));\n  EXPECT_EQ(absl::CivilHour(kDefaultSec),\n            absl::GetFlag(FLAGS_test_flag_civil_hour));\n  EXPECT_EQ(absl::CivilDay(kDefaultSec),\n            absl::GetFlag(FLAGS_test_flag_civil_day));\n  EXPECT_EQ(absl::CivilMonth(kDefaultSec),\n            absl::GetFlag(FLAGS_test_flag_civil_month));\n  EXPECT_EQ(absl::CivilYear(kDefaultSec),\n            absl::GetFlag(FLAGS_test_flag_civil_year));\n\n  // Sets flags to a new value.\n  const absl::CivilSecond kNewSec(2016, 6, 7, 8, 9, 10);\n  absl::SetFlag(&FLAGS_test_flag_civil_second, absl::CivilSecond(kNewSec));\n  absl::SetFlag(&FLAGS_test_flag_civil_minute, absl::CivilMinute(kNewSec));\n  absl::SetFlag(&FLAGS_test_flag_civil_hour, absl::CivilHour(kNewSec));\n  absl::SetFlag(&FLAGS_test_flag_civil_day, absl::CivilDay(kNewSec));\n  absl::SetFlag(&FLAGS_test_flag_civil_month, absl::CivilMonth(kNewSec));\n  absl::SetFlag(&FLAGS_test_flag_civil_year, absl::CivilYear(kNewSec));\n\n  EXPECT_EQ(absl::CivilSecond(kNewSec),\n            absl::GetFlag(FLAGS_test_flag_civil_second));\n  EXPECT_EQ(absl::CivilMinute(kNewSec),\n            absl::GetFlag(FLAGS_test_flag_civil_minute));\n  EXPECT_EQ(absl::CivilHour(kNewSec),\n            absl::GetFlag(FLAGS_test_flag_civil_hour));\n  EXPECT_EQ(absl::CivilDay(kNewSec), absl::GetFlag(FLAGS_test_flag_civil_day));\n  EXPECT_EQ(absl::CivilMonth(kNewSec),\n            absl::GetFlag(FLAGS_test_flag_civil_month));\n  EXPECT_EQ(absl::CivilYear(kNewSec),\n            absl::GetFlag(FLAGS_test_flag_civil_year));\n}\n\nTEST(Duration, FlagSupport) {\n  EXPECT_EQ(absl::Seconds(5), absl::GetFlag(FLAGS_test_duration_flag));\n\n  absl::SetFlag(&FLAGS_test_duration_flag, absl::Seconds(10));\n  EXPECT_EQ(absl::Seconds(10), absl::GetFlag(FLAGS_test_duration_flag));\n\n  EXPECT_TRUE(SetFlagValue(\"test_duration_flag\", \"20s\"));\n  EXPECT_EQ(absl::Seconds(20), absl::GetFlag(FLAGS_test_duration_flag));\n\n  std::string current_flag_value;\n  EXPECT_TRUE(GetFlagValue(\"test_duration_flag\", current_flag_value));\n  EXPECT_EQ(\"20s\", current_flag_value);\n}\n\nTEST(Time, FlagSupport) {\n  EXPECT_EQ(absl::InfinitePast(), absl::GetFlag(FLAGS_test_time_flag));\n\n  const absl::Time t = absl::FromCivil(absl::CivilSecond(2016, 1, 2, 3, 4, 5),\n                                       absl::UTCTimeZone());\n  absl::SetFlag(&FLAGS_test_time_flag, t);\n  EXPECT_EQ(t, absl::GetFlag(FLAGS_test_time_flag));\n\n  // Successful parse\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:06Z\"));\n  EXPECT_EQ(t + absl::Seconds(1), absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:07.0Z\"));\n  EXPECT_EQ(t + absl::Seconds(2), absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:08.000Z\"));\n  EXPECT_EQ(t + absl::Seconds(3), absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:09+00:00\"));\n  EXPECT_EQ(t + absl::Seconds(4), absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:05.123+00:00\"));\n  EXPECT_EQ(t + absl::Milliseconds(123), absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:05.123+08:00\"));\n  EXPECT_EQ(t + absl::Milliseconds(123) - absl::Hours(8),\n            absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"infinite-future\"));\n  EXPECT_EQ(absl::InfiniteFuture(), absl::GetFlag(FLAGS_test_time_flag));\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"infinite-past\"));\n  EXPECT_EQ(absl::InfinitePast(), absl::GetFlag(FLAGS_test_time_flag));\n\n  EXPECT_FALSE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:06\"));\n  EXPECT_FALSE(SetFlagValue(\"test_time_flag\", \"2016-01-02\"));\n  EXPECT_FALSE(SetFlagValue(\"test_time_flag\", \"2016-01-02Z\"));\n  EXPECT_FALSE(SetFlagValue(\"test_time_flag\", \"2016-01-02+00:00\"));\n  EXPECT_FALSE(SetFlagValue(\"test_time_flag\", \"2016-99-99T03:04:06Z\"));\n\n  EXPECT_TRUE(SetFlagValue(\"test_time_flag\", \"2016-01-02T03:04:05Z\"));\n  std::string current_flag_value;\n  EXPECT_TRUE(GetFlagValue(\"test_time_flag\", current_flag_value));\n  EXPECT_EQ(\"2016-01-02T03:04:05+00:00\", current_flag_value);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/format.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <string.h>\n\n#include <cctype>\n#include <cstdint>\n#include <utility>\n\n#include \"absl/strings/match.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n#include \"absl/time/time.h\"\n\nnamespace cctz = absl::time_internal::cctz;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nABSL_DLL extern const char RFC3339_full[] = \"%Y-%m-%d%ET%H:%M:%E*S%Ez\";\nABSL_DLL extern const char RFC3339_sec[] = \"%Y-%m-%d%ET%H:%M:%S%Ez\";\n\nABSL_DLL extern const char RFC1123_full[] = \"%a, %d %b %E4Y %H:%M:%S %z\";\nABSL_DLL extern const char RFC1123_no_wday[] = \"%d %b %E4Y %H:%M:%S %z\";\n\nnamespace {\n\nconst char kInfiniteFutureStr[] = \"infinite-future\";\nconst char kInfinitePastStr[] = \"infinite-past\";\n\nstruct cctz_parts {\n  cctz::time_point<cctz::seconds> sec;\n  cctz::detail::femtoseconds fem;\n};\n\ninline cctz::time_point<cctz::seconds> unix_epoch() {\n  return std::chrono::time_point_cast<cctz::seconds>(\n      std::chrono::system_clock::from_time_t(0));\n}\n\n// Splits a Time into seconds and femtoseconds, which can be used with CCTZ.\n// Requires that 't' is finite. See duration.cc for details about rep_hi and\n// rep_lo.\ncctz_parts Split(absl::Time t) {\n  const auto d = time_internal::ToUnixDuration(t);\n  const int64_t rep_hi = time_internal::GetRepHi(d);\n  const int64_t rep_lo = time_internal::GetRepLo(d);\n  const auto sec = unix_epoch() + cctz::seconds(rep_hi);\n  const auto fem = cctz::detail::femtoseconds(rep_lo * (1000 * 1000 / 4));\n  return {sec, fem};\n}\n\n// Joins the given seconds and femtoseconds into a Time. See duration.cc for\n// details about rep_hi and rep_lo.\nabsl::Time Join(const cctz_parts& parts) {\n  const int64_t rep_hi = (parts.sec - unix_epoch()).count();\n  const uint32_t rep_lo =\n      static_cast<uint32_t>(parts.fem.count() / (1000 * 1000 / 4));\n  const auto d = time_internal::MakeDuration(rep_hi, rep_lo);\n  return time_internal::FromUnixDuration(d);\n}\n\n}  // namespace\n\nstd::string FormatTime(absl::string_view format, absl::Time t,\n                       absl::TimeZone tz) {\n  if (t == absl::InfiniteFuture()) return std::string(kInfiniteFutureStr);\n  if (t == absl::InfinitePast()) return std::string(kInfinitePastStr);\n  const auto parts = Split(t);\n  return cctz::detail::format(std::string(format), parts.sec, parts.fem,\n                              cctz::time_zone(tz));\n}\n\nstd::string FormatTime(absl::Time t, absl::TimeZone tz) {\n  return FormatTime(RFC3339_full, t, tz);\n}\n\nstd::string FormatTime(absl::Time t) {\n  return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());\n}\n\nbool ParseTime(absl::string_view format, absl::string_view input,\n               absl::Time* time, std::string* err) {\n  return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);\n}\n\n// If the input string does not contain an explicit UTC offset, interpret\n// the fields with respect to the given TimeZone.\nbool ParseTime(absl::string_view format, absl::string_view input,\n               absl::TimeZone tz, absl::Time* time, std::string* err) {\n  auto strip_leading_space = [](absl::string_view* sv) {\n    while (!sv->empty()) {\n      if (!std::isspace(sv->front())) return;\n      sv->remove_prefix(1);\n    }\n  };\n\n  // Portable toolchains means we don't get nice constexpr here.\n  struct Literal {\n    const char* name;\n    size_t size;\n    absl::Time value;\n  };\n  static Literal literals[] = {\n      {kInfiniteFutureStr, strlen(kInfiniteFutureStr), InfiniteFuture()},\n      {kInfinitePastStr, strlen(kInfinitePastStr), InfinitePast()},\n  };\n  strip_leading_space(&input);\n  for (const auto& lit : literals) {\n    if (absl::StartsWith(input, absl::string_view(lit.name, lit.size))) {\n      absl::string_view tail = input;\n      tail.remove_prefix(lit.size);\n      strip_leading_space(&tail);\n      if (tail.empty()) {\n        *time = lit.value;\n        return true;\n      }\n    }\n  }\n\n  std::string error;\n  cctz_parts parts;\n  const bool b =\n      cctz::detail::parse(std::string(format), std::string(input),\n                          cctz::time_zone(tz), &parts.sec, &parts.fem, &error);\n  if (b) {\n    *time = Join(parts);\n  } else if (err != nullptr) {\n    *err = std::move(error);\n  }\n  return b;\n}\n\n// Functions required to support absl::Time flags.\nbool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) {\n  return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);\n}\n\nstd::string AbslUnparseFlag(absl::Time t) {\n  return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());\n}\nbool ParseFlag(const std::string& text, absl::Time* t, std::string* error) {\n  return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);\n}\n\nstd::string UnparseFlag(absl::Time t) {\n  return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/format_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <string>\n\n#include \"absl/time/internal/test_util.h\"\n#include \"absl/time/time.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\nnamespace {\nconst char* const kFormats[] = {\n    absl::RFC1123_full,     // 0\n    absl::RFC1123_no_wday,  // 1\n    absl::RFC3339_full,     // 2\n    absl::RFC3339_sec,      // 3\n    \"%Y-%m-%d%ET%H:%M:%S\",  // 4\n    \"%Y-%m-%d\",             // 5\n};\nconst int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);\n}  // namespace\n\nvoid BM_Format_FormatTime(benchmark::State& state) {\n  const std::string fmt = kFormats[state.range(0)];\n  state.SetLabel(fmt);\n  const absl::TimeZone lax =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  const absl::Time t =\n      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) +\n      absl::Nanoseconds(1);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::FormatTime(fmt, t, lax).length());\n  }\n}\nBENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1);\n\nvoid BM_Format_ParseTime(benchmark::State& state) {\n  const std::string fmt = kFormats[state.range(0)];\n  state.SetLabel(fmt);\n  const absl::TimeZone lax =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  absl::Time t = absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) +\n                 absl::Nanoseconds(1);\n  const std::string when = absl::FormatTime(fmt, t, lax);\n  std::string err;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ParseTime(fmt, when, lax, &t, &err));\n  }\n}\nBENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1);\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/format_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstdint>\n#include <limits>\n#include <string>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/time/internal/test_util.h\"\n#include \"absl/time/time.h\"\n\nusing testing::HasSubstr;\n\nnamespace {\n\n// A helper that tests the given format specifier by itself, and with leading\n// and trailing characters.  For example: TestFormatSpecifier(t, \"%a\", \"Thu\").\nvoid TestFormatSpecifier(absl::Time t, absl::TimeZone tz,\n                         const std::string& fmt, const std::string& ans) {\n  EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));\n  EXPECT_EQ(\"xxx \" + ans, absl::FormatTime(\"xxx \" + fmt, t, tz));\n  EXPECT_EQ(ans + \" yyy\", absl::FormatTime(fmt + \" yyy\", t, tz));\n  EXPECT_EQ(\"xxx \" + ans + \" yyy\",\n            absl::FormatTime(\"xxx \" + fmt + \" yyy\", t, tz));\n}\n\n//\n// Testing FormatTime()\n//\n\nTEST(FormatTime, Basics) {\n  absl::TimeZone tz = absl::UTCTimeZone();\n  absl::Time t = absl::FromTimeT(0);\n\n  // Starts with a couple basic edge cases.\n  EXPECT_EQ(\"\", absl::FormatTime(\"\", t, tz));\n  EXPECT_EQ(\" \", absl::FormatTime(\" \", t, tz));\n  EXPECT_EQ(\"  \", absl::FormatTime(\"  \", t, tz));\n  EXPECT_EQ(\"xxx\", absl::FormatTime(\"xxx\", t, tz));\n  std::string big(128, 'x');\n  EXPECT_EQ(big, absl::FormatTime(big, t, tz));\n  // Cause the 1024-byte buffer to grow.\n  std::string bigger(100000, 'x');\n  EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz));\n\n  t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5);\n  t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);\n  EXPECT_EQ(\"1970-01-01\", absl::FormatTime(\"%Y-%m-%d\", t, tz));\n  EXPECT_EQ(\"13:04:05\", absl::FormatTime(\"%H:%M:%S\", t, tz));\n  EXPECT_EQ(\"13:04:05.006\", absl::FormatTime(\"%H:%M:%E3S\", t, tz));\n  EXPECT_EQ(\"13:04:05.006007\", absl::FormatTime(\"%H:%M:%E6S\", t, tz));\n  EXPECT_EQ(\"13:04:05.006007008\", absl::FormatTime(\"%H:%M:%E9S\", t, tz));\n}\n\nTEST(FormatTime, LocaleSpecific) {\n  const absl::TimeZone tz = absl::UTCTimeZone();\n  absl::Time t = absl::FromTimeT(0);\n\n  TestFormatSpecifier(t, tz, \"%a\", \"Thu\");\n  TestFormatSpecifier(t, tz, \"%A\", \"Thursday\");\n  TestFormatSpecifier(t, tz, \"%b\", \"Jan\");\n  TestFormatSpecifier(t, tz, \"%B\", \"January\");\n\n  // %c should at least produce the numeric year and time-of-day.\n  const std::string s =\n      absl::FormatTime(\"%c\", absl::FromTimeT(0), absl::UTCTimeZone());\n  EXPECT_THAT(s, HasSubstr(\"1970\"));\n  EXPECT_THAT(s, HasSubstr(\"00:00:00\"));\n\n  TestFormatSpecifier(t, tz, \"%p\", \"AM\");\n  TestFormatSpecifier(t, tz, \"%x\", \"01/01/70\");\n  TestFormatSpecifier(t, tz, \"%X\", \"00:00:00\");\n}\n\nTEST(FormatTime, ExtendedSeconds) {\n  const absl::TimeZone tz = absl::UTCTimeZone();\n\n  // No subseconds.\n  absl::Time t = absl::FromTimeT(0) + absl::Seconds(5);\n  EXPECT_EQ(\"05\", absl::FormatTime(\"%E*S\", t, tz));\n  EXPECT_EQ(\"05.000000000000000\", absl::FormatTime(\"%E15S\", t, tz));\n\n  // With subseconds.\n  t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);\n  EXPECT_EQ(\"05.006007008\", absl::FormatTime(\"%E*S\", t, tz));\n  EXPECT_EQ(\"05\", absl::FormatTime(\"%E0S\", t, tz));\n  EXPECT_EQ(\"05.006007008000000\", absl::FormatTime(\"%E15S\", t, tz));\n\n  // Times before the Unix epoch.\n  t = absl::FromUnixMicros(-1);\n  EXPECT_EQ(\"1969-12-31 23:59:59.999999\",\n            absl::FormatTime(\"%Y-%m-%d %H:%M:%E*S\", t, tz));\n\n  // Here is a \"%E*S\" case we got wrong for a while.  While the first\n  // instant below is correctly rendered as \"...:07.333304\", the second\n  // one used to appear as \"...:07.33330499999999999\".\n  t = absl::FromUnixMicros(1395024427333304);\n  EXPECT_EQ(\"2014-03-17 02:47:07.333304\",\n            absl::FormatTime(\"%Y-%m-%d %H:%M:%E*S\", t, tz));\n  t += absl::Microseconds(1);\n  EXPECT_EQ(\"2014-03-17 02:47:07.333305\",\n            absl::FormatTime(\"%Y-%m-%d %H:%M:%E*S\", t, tz));\n}\n\nTEST(FormatTime, RFC1123FormatPadsYear) {  // locale specific\n  absl::TimeZone tz = absl::UTCTimeZone();\n\n  // A year of 77 should be padded to 0077.\n  absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);\n  EXPECT_EQ(\"Mon, 28 Jun 0077 09:08:07 +0000\",\n            absl::FormatTime(absl::RFC1123_full, t, tz));\n  EXPECT_EQ(\"28 Jun 0077 09:08:07 +0000\",\n            absl::FormatTime(absl::RFC1123_no_wday, t, tz));\n}\n\nTEST(FormatTime, InfiniteTime) {\n  absl::TimeZone tz = absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n\n  // The format and timezone are ignored.\n  EXPECT_EQ(\"infinite-future\",\n            absl::FormatTime(\"%H:%M blah\", absl::InfiniteFuture(), tz));\n  EXPECT_EQ(\"infinite-past\",\n            absl::FormatTime(\"%H:%M blah\", absl::InfinitePast(), tz));\n}\n\n//\n// Testing ParseTime()\n//\n\nTEST(ParseTime, Basics) {\n  absl::Time t = absl::FromTimeT(1234567890);\n  std::string err;\n\n  // Simple edge cases.\n  EXPECT_TRUE(absl::ParseTime(\"\", \"\", &t, &err)) << err;\n  EXPECT_EQ(absl::UnixEpoch(), t);  // everything defaulted\n  EXPECT_TRUE(absl::ParseTime(\" \", \" \", &t, &err)) << err;\n  EXPECT_TRUE(absl::ParseTime(\"  \", \"  \", &t, &err)) << err;\n  EXPECT_TRUE(absl::ParseTime(\"x\", \"x\", &t, &err)) << err;\n  EXPECT_TRUE(absl::ParseTime(\"xxx\", \"xxx\", &t, &err)) << err;\n\n  EXPECT_TRUE(absl::ParseTime(\"%Y-%m-%d %H:%M:%S %z\",\n                              \"2013-06-28 19:08:09 -0800\", &t, &err))\n      << err;\n  const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);\n  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);\n  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);\n}\n\nTEST(ParseTime, NullErrorString) {\n  absl::Time t;\n  EXPECT_FALSE(absl::ParseTime(\"%Q\", \"invalid format\", &t, nullptr));\n  EXPECT_FALSE(absl::ParseTime(\"%H\", \"12 trailing data\", &t, nullptr));\n  EXPECT_FALSE(\n      absl::ParseTime(\"%H out of range\", \"42 out of range\", &t, nullptr));\n}\n\nTEST(ParseTime, WithTimeZone) {\n  const absl::TimeZone tz =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  absl::Time t;\n  std::string e;\n\n  // We can parse a string without a UTC offset if we supply a timezone.\n  EXPECT_TRUE(\n      absl::ParseTime(\"%Y-%m-%d %H:%M:%S\", \"2013-06-28 19:08:09\", tz, &t, &e))\n      << e;\n  auto ci = tz.At(t);\n  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);\n  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);\n\n  // But the timezone is ignored when a UTC offset is present.\n  EXPECT_TRUE(absl::ParseTime(\"%Y-%m-%d %H:%M:%S %z\",\n                              \"2013-06-28 19:08:09 +0800\", tz, &t, &e))\n      << e;\n  ci = absl::FixedTimeZone(8 * 60 * 60).At(t);\n  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);\n  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);\n}\n\nTEST(ParseTime, ErrorCases) {\n  absl::Time t = absl::FromTimeT(0);\n  std::string err;\n\n  EXPECT_FALSE(absl::ParseTime(\"%S\", \"123\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n\n  // Can't parse an illegal format specifier.\n  err.clear();\n  EXPECT_FALSE(absl::ParseTime(\"%Q\", \"x\", &t, &err)) << err;\n  // Exact contents of \"err\" are platform-dependent because of\n  // differences in the strptime implementation between macOS and Linux.\n  EXPECT_FALSE(err.empty());\n\n  // Fails because of trailing, unparsed data \"blah\".\n  EXPECT_FALSE(absl::ParseTime(\"%m-%d\", \"2-3 blah\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n\n  // Feb 31 requires normalization.\n  EXPECT_FALSE(absl::ParseTime(\"%m-%d\", \"2-31\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Out-of-range\"));\n\n  // Check that we cannot have spaces in UTC offsets.\n  EXPECT_TRUE(absl::ParseTime(\"%z\", \"-0203\", &t, &err)) << err;\n  EXPECT_FALSE(absl::ParseTime(\"%z\", \"- 2 3\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_TRUE(absl::ParseTime(\"%Ez\", \"-02:03\", &t, &err)) << err;\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"- 2: 3\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n\n  // Check that we reject other malformed UTC offsets.\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"+-08:00\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"-+08:00\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n\n  // Check that we do not accept \"-0\" in fields that allow zero.\n  EXPECT_FALSE(absl::ParseTime(\"%Y\", \"-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%E4Y\", \"-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%H\", \"-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%M\", \"-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%S\", \"-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%z\", \"+-000\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"+-0:00\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n  EXPECT_FALSE(absl::ParseTime(\"%z\", \"-00-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"-00:-0\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n\n  // Check that we do not accept strings with embedded NULs.\n  EXPECT_FALSE(\n      absl::ParseTime(\"%Y\", std::string(\"2026\\0payload\", 12), &t, &err));\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n}\n\nTEST(ParseTime, ExtendedSeconds) {\n  std::string err;\n  absl::Time t;\n\n  // Here is a \"%E*S\" case we got wrong for a while.  The fractional\n  // part of the first instant is less than 2^31 and was correctly\n  // parsed, while the second (and any subsecond field >=2^31) failed.\n  t = absl::UnixEpoch();\n  EXPECT_TRUE(absl::ParseTime(\"%E*S\", \"0.2147483647\", &t, &err)) << err;\n  EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +\n                absl::Nanoseconds(1) / 2,\n            t);\n  t = absl::UnixEpoch();\n  EXPECT_TRUE(absl::ParseTime(\"%E*S\", \"0.2147483648\", &t, &err)) << err;\n  EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +\n                absl::Nanoseconds(3) / 4,\n            t);\n\n  // We should also be able to specify long strings of digits far\n  // beyond the current resolution and have them convert the same way.\n  t = absl::UnixEpoch();\n  EXPECT_TRUE(absl::ParseTime(\n      \"%E*S\", \"0.214748364801234567890123456789012345678901234567890123456789\",\n      &t, &err))\n      << err;\n  EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +\n                absl::Nanoseconds(3) / 4,\n            t);\n}\n\nTEST(ParseTime, ExtendedOffsetErrors) {\n  std::string err;\n  absl::Time t;\n\n  // %z against +-HHMM.\n  EXPECT_FALSE(absl::ParseTime(\"%z\", \"-123\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n\n  // %z against +-HH.\n  EXPECT_FALSE(absl::ParseTime(\"%z\", \"-1\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n\n  // %Ez against +-HH:MM.\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"-12:3\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n\n  // %Ez against +-HHMM.\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"-123\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Illegal trailing data\"));\n\n  // %Ez against +-HH.\n  EXPECT_FALSE(absl::ParseTime(\"%Ez\", \"-1\", &t, &err)) << err;\n  EXPECT_THAT(err, HasSubstr(\"Failed to parse\"));\n}\n\nTEST(ParseTime, InfiniteTime) {\n  absl::Time t;\n  std::string err;\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"infinite-future\", &t, &err));\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n\n  // Surrounding whitespace.\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"  infinite-future\", &t, &err));\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"infinite-future  \", &t, &err));\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"  infinite-future  \", &t, &err));\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"infinite-past\", &t, &err));\n  EXPECT_EQ(absl::InfinitePast(), t);\n\n  // Surrounding whitespace.\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"  infinite-past\", &t, &err));\n  EXPECT_EQ(absl::InfinitePast(), t);\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"infinite-past  \", &t, &err));\n  EXPECT_EQ(absl::InfinitePast(), t);\n  EXPECT_TRUE(absl::ParseTime(\"%H:%M blah\", \"  infinite-past  \", &t, &err));\n  EXPECT_EQ(absl::InfinitePast(), t);\n\n  // \"infinite-future\" as literal string\n  absl::TimeZone tz = absl::UTCTimeZone();\n  EXPECT_TRUE(absl::ParseTime(\"infinite-future %H:%M\", \"infinite-future 03:04\",\n                              &t, &err));\n  EXPECT_NE(absl::InfiniteFuture(), t);\n  EXPECT_EQ(3, tz.At(t).cs.hour());\n  EXPECT_EQ(4, tz.At(t).cs.minute());\n\n  // \"infinite-past\" as literal string\n  EXPECT_TRUE(\n      absl::ParseTime(\"infinite-past %H:%M\", \"infinite-past 03:04\", &t, &err));\n  EXPECT_NE(absl::InfinitePast(), t);\n  EXPECT_EQ(3, tz.At(t).cs.hour());\n  EXPECT_EQ(4, tz.At(t).cs.minute());\n\n  // The input doesn't match the format.\n  EXPECT_FALSE(absl::ParseTime(\"infinite-future %H:%M\", \"03:04\", &t, &err));\n  EXPECT_FALSE(absl::ParseTime(\"infinite-past %H:%M\", \"03:04\", &t, &err));\n}\n\nTEST(ParseTime, FailsOnUnrepresentableTime) {\n  const absl::TimeZone utc = absl::UTCTimeZone();\n  absl::Time t;\n  EXPECT_FALSE(\n      absl::ParseTime(\"%Y-%m-%d\", \"-292277022657-01-27\", utc, &t, nullptr));\n  EXPECT_TRUE(\n      absl::ParseTime(\"%Y-%m-%d\", \"-292277022657-01-28\", utc, &t, nullptr));\n  EXPECT_TRUE(\n      absl::ParseTime(\"%Y-%m-%d\", \"292277026596-12-04\", utc, &t, nullptr));\n  EXPECT_FALSE(\n      absl::ParseTime(\"%Y-%m-%d\", \"292277026596-12-05\", utc, &t, nullptr));\n}\n\n//\n// Roundtrip test for FormatTime()/ParseTime().\n//\n\nTEST(FormatParse, RoundTrip) {\n  const absl::TimeZone lax =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  const absl::Time in =\n      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);\n  const absl::Duration subseconds = absl::Nanoseconds(654321);\n  std::string err;\n\n  // RFC3339, which renders subseconds.\n  {\n    absl::Time out;\n    const std::string s =\n        absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);\n    EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))\n        << s << \": \" << err;\n    EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez\n  }\n\n  // RFC1123, which only does whole seconds.\n  {\n    absl::Time out;\n    const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);\n    EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))\n        << s << \": \" << err;\n    EXPECT_EQ(in, out);  // RFC1123_full includes %z\n  }\n\n  // `absl::FormatTime()` falls back to strftime() for \"%c\", which appears to\n  // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which\n  // appears to fail on \"%c\" (or at least on the \"%c\" text produced by\n  // `strftime()`). This makes it fail the round-trip test.\n  //\n  // Under the emscripten compiler `absl::ParseTime() falls back to\n  // `strptime()`, but that ends up using a different definition for \"%c\"\n  // compared to `strftime()`, also causing the round-trip test to fail\n  // (see https://github.com/kripken/emscripten/pull/7491).\n#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)\n  // Even though we don't know what %c will produce, it should roundtrip,\n  // but only in the 0-offset timezone.\n  {\n    absl::Time out;\n    const std::string s = absl::FormatTime(\"%c\", in, absl::UTCTimeZone());\n    EXPECT_TRUE(absl::ParseTime(\"%c\", s, &out, &err)) << s << \": \" << err;\n    EXPECT_EQ(in, out);\n  }\n#endif  // !_MSC_VER && !__EMSCRIPTEN__\n}\n\nTEST(FormatParse, RoundTripDistantFuture) {\n  const absl::TimeZone tz = absl::UTCTimeZone();\n  const absl::Time in =\n      absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());\n  std::string err;\n\n  absl::Time out;\n  const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);\n  EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))\n      << s << \": \" << err;\n  EXPECT_EQ(in, out);\n}\n\nTEST(FormatParse, RoundTripDistantPast) {\n  const absl::TimeZone tz = absl::UTCTimeZone();\n  const absl::Time in =\n      absl::FromUnixSeconds(std::numeric_limits<int64_t>::min());\n  std::string err;\n\n  absl::Time out;\n  const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);\n  EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))\n      << s << \": \" << err;\n  EXPECT_EQ(in, out);\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/internal/cctz/BUILD.bazel",
    "content": "# Copyright 2016 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   https://www.apache.org/licenses/LICENSE-2.0\n#\n#   Unless required by applicable law or agreed to in writing, software\n#   distributed under the License is distributed on an \"AS IS\" BASIS,\n#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#   See the License for the specific language governing permissions and\n#   limitations under the License.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\"//absl:copts/configure_copts.bzl\", \"ABSL_DEFAULT_COPTS\", \"ABSL_DEFAULT_LINKOPTS\", \"ABSL_TEST_COPTS\")\n\npackage(features = [\n    \"header_modules\",\n    \"layering_check\",\n    \"parse_headers\",\n])\n\nlicenses([\"notice\"])\n\n### libraries\n\ncc_library(\n    name = \"civil_time\",\n    srcs = [\"src/civil_time_detail.cc\"],\n    hdrs = [\n        \"include/cctz/civil_time.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    textual_hdrs = [\"include/cctz/civil_time_detail.h\"],\n    visibility = [\"//visibility:public\"],\n    deps = [\"//absl/base:config\"],\n)\n\ncc_library(\n    name = \"time_zone\",\n    srcs = [\n        \"src/time_zone_fixed.cc\",\n        \"src/time_zone_fixed.h\",\n        \"src/time_zone_format.cc\",\n        \"src/time_zone_if.cc\",\n        \"src/time_zone_if.h\",\n        \"src/time_zone_impl.cc\",\n        \"src/time_zone_impl.h\",\n        \"src/time_zone_info.cc\",\n        \"src/time_zone_info.h\",\n        \"src/time_zone_libc.cc\",\n        \"src/time_zone_libc.h\",\n        \"src/time_zone_lookup.cc\",\n        \"src/time_zone_posix.cc\",\n        \"src/time_zone_posix.h\",\n        \"src/tzfile.h\",\n        \"src/zone_info_source.cc\",\n    ] + select({\n        \"@platforms//os:windows\": [\n            \"src/time_zone_name_win.cc\",\n            \"src/time_zone_name_win.h\",\n        ],\n        \"//conditions:default\": [],\n    }),\n    hdrs = [\n        \"include/cctz/time_zone.h\",\n        \"include/cctz/zone_info_source.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS + select({\n        \"@platforms//os:osx\": [\"-Wl,-framework,CoreFoundation\"],\n        \"@platforms//os:ios\": [\"-Wl,-framework,CoreFoundation\"],\n        \"//conditions:default\": [],\n    }),\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":civil_time\",\n        \"//absl/base:config\",\n    ] + select(\n        {\n            \"//conditions:default\": [],\n        },\n    ),\n)\n\n### tests\n\ncc_library(\n    name = \"test_time_zone_names\",\n    testonly = True,\n    srcs = [\"src/test_time_zone_names.cc\"],\n    hdrs = [\"src/test_time_zone_names.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    visibility = [\"//visibility:private\"],\n    deps = [\"//absl/base:config\"],\n)\n\ncc_test(\n    name = \"civil_time_test\",\n    size = \"small\",\n    srcs = [\"src/civil_time_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":civil_time\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"time_zone_format_test\",\n    size = \"small\",\n    srcs = [\"src/time_zone_format_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    data = [\":zoneinfo\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_android_arm\",\n        \"no_test_android_arm64\",\n        \"no_test_android_x86\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":civil_time\",\n        \":time_zone\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_test(\n    name = \"time_zone_lookup_test\",\n    size = \"small\",\n    timeout = \"moderate\",\n    srcs = [\"src/time_zone_lookup_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    data = [\":zoneinfo\"],\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    tags = [\n        \"no_test_android_arm\",\n        \"no_test_android_arm64\",\n        \"no_test_android_x86\",\n        \"no_test_wasm\",\n    ],\n    deps = [\n        \":civil_time\",\n        \":test_time_zone_names\",\n        \":time_zone\",\n        \"//absl/base:config\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\n### benchmarks\n\ncc_test(\n    name = \"cctz_benchmark\",\n    srcs = [\n        \"src/cctz_benchmark.cc\",\n        \"src/time_zone_if.h\",\n        \"src/time_zone_impl.h\",\n        \"src/time_zone_info.h\",\n        \"src/tzfile.h\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    linkstatic = 1,\n    tags = [\"benchmark\"],\n    deps = [\n        \":civil_time\",\n        \":test_time_zone_names\",\n        \":time_zone\",\n        \"//absl/base:config\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\n### examples\n\n### binaries\n\nfilegroup(\n    name = \"zoneinfo\",\n    srcs = glob([\"testdata/zoneinfo/**\"]),\n    visibility = [\"//absl/time:__subpackages__\"],\n)\n"
  },
  {
    "path": "absl/time/internal/cctz/include/cctz/civil_time.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_\n#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time_detail.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// The term \"civil time\" refers to the legally recognized human-scale time\n// that is represented by the six fields YYYY-MM-DD hh:mm:ss. Modern-day civil\n// time follows the Gregorian Calendar and is a time-zone-independent concept.\n// A \"date\" is perhaps the most common example of a civil time (represented in\n// this library as cctz::civil_day). This library provides six classes and a\n// handful of functions that help with rounding, iterating, and arithmetic on\n// civil times while avoiding complications like daylight-saving time (DST).\n//\n// The following six classes form the core of this civil-time library:\n//\n//   * civil_second\n//   * civil_minute\n//   * civil_hour\n//   * civil_day\n//   * civil_month\n//   * civil_year\n//\n// Each class is a simple value type with the same interface for construction\n// and the same six accessors for each of the civil fields (year, month, day,\n// hour, minute, and second, aka YMDHMS). These classes differ only in their\n// alignment, which is indicated by the type name and specifies the field on\n// which arithmetic operates.\n//\n// Each class can be constructed by passing up to six optional integer\n// arguments representing the YMDHMS fields (in that order) to the\n// constructor. Omitted fields are assigned their minimum valid value. Hours,\n// minutes, and seconds will be set to 0, month and day will be set to 1, and\n// since there is no minimum valid year, it will be set to 1970. So, a\n// default-constructed civil-time object will have YMDHMS fields representing\n// \"1970-01-01 00:00:00\". Fields that are out-of-range are normalized (e.g.,\n// October 32 -> November 1) so that all civil-time objects represent valid\n// values.\n//\n// Each civil-time class is aligned to the civil-time field indicated in the\n// class's name after normalization. Alignment is performed by setting all the\n// inferior fields to their minimum valid value (as described above). The\n// following are examples of how each of the six types would align the fields\n// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the\n// string format used here is not important; it's just a shorthand way of\n// showing the six YMDHMS fields.)\n//\n//   civil_second  2015-11-22 12:34:56\n//   civil_minute  2015-11-22 12:34:00\n//   civil_hour    2015-11-22 12:00:00\n//   civil_day     2015-11-22 00:00:00\n//   civil_month   2015-11-01 00:00:00\n//   civil_year    2015-01-01 00:00:00\n//\n// Each civil-time type performs arithmetic on the field to which it is\n// aligned. This means that adding 1 to a civil_day increments the day field\n// (normalizing as necessary), and subtracting 7 from a civil_month operates\n// on the month field (normalizing as necessary). All arithmetic produces a\n// valid civil time. Difference requires two similarly aligned civil-time\n// objects and returns the scalar answer in units of the objects' alignment.\n// For example, the difference between two civil_hour objects will give an\n// answer in units of civil hours.\n//\n// In addition to the six civil-time types just described, there are\n// a handful of helper functions and algorithms for performing common\n// calculations. These are described below.\n//\n// Note: In C++14 and later, this library is usable in a constexpr context.\n//\n// CONSTRUCTION:\n//\n// Each of the civil-time types can be constructed in two ways: by directly\n// passing to the constructor up to six (optional) integers representing the\n// YMDHMS fields, or by copying the YMDHMS fields from a differently aligned\n// civil-time type.\n//\n//   civil_day default_value;  // 1970-01-01 00:00:00\n//\n//   civil_day a(2015, 2, 3);           // 2015-02-03 00:00:00\n//   civil_day b(2015, 2, 3, 4, 5, 6);  // 2015-02-03 00:00:00\n//   civil_day c(2015);                 // 2015-01-01 00:00:00\n//\n//   civil_second ss(2015, 2, 3, 4, 5, 6);  // 2015-02-03 04:05:06\n//   civil_minute mm(ss);                   // 2015-02-03 04:05:00\n//   civil_hour hh(mm);                     // 2015-02-03 04:00:00\n//   civil_day d(hh);                       // 2015-02-03 00:00:00\n//   civil_month m(d);                      // 2015-02-01 00:00:00\n//   civil_year y(m);                       // 2015-01-01 00:00:00\n//\n//   m = civil_month(y);     // 2015-01-01 00:00:00\n//   d = civil_day(m);       // 2015-01-01 00:00:00\n//   hh = civil_hour(d);     // 2015-01-01 00:00:00\n//   mm = civil_minute(hh);  // 2015-01-01 00:00:00\n//   ss = civil_second(mm);  // 2015-01-01 00:00:00\n//\n// ALIGNMENT CONVERSION:\n//\n// The alignment of a civil-time object cannot change, but the object may be\n// used to construct a new object with a different alignment. This is referred\n// to as \"realigning\". When realigning to a type with the same or more\n// precision (e.g., civil_day -> civil_second), the conversion may be\n// performed implicitly since no information is lost. However, if information\n// could be discarded (e.g., civil_second -> civil_day), the conversion must\n// be explicit at the call site.\n//\n//   void fun(const civil_day& day);\n//\n//   civil_second cs;\n//   fun(cs);  // Won't compile because data may be discarded\n//   fun(civil_day(cs));  // OK: explicit conversion\n//\n//   civil_day cd;\n//   fun(cd);  // OK: no conversion needed\n//\n//   civil_month cm;\n//   fun(cm);  // OK: implicit conversion to civil_day\n//\n// NORMALIZATION:\n//\n// Integer arguments passed to the constructor may be out-of-range, in which\n// case they are normalized to produce a valid civil-time object. This enables\n// natural arithmetic on constructor arguments without worrying about the\n// field's range. Normalization guarantees that there are no invalid\n// civil-time objects.\n//\n//   civil_day d(2016, 10, 32);  // Out-of-range day; normalized to 2016-11-01\n//\n// Note: If normalization is undesired, you can signal an error by comparing\n// the constructor arguments to the normalized values returned by the YMDHMS\n// properties.\n//\n// PROPERTIES:\n//\n// All civil-time types have accessors for all six of the civil-time fields:\n// year, month, day, hour, minute, and second. Recall that fields inferior to\n// the type's alignment will be set to their minimum valid value.\n//\n//   civil_day d(2015, 6, 28);\n//   // d.year() == 2015\n//   // d.month() == 6\n//   // d.day() == 28\n//   // d.hour() == 0\n//   // d.minute() == 0\n//   // d.second() == 0\n//\n// COMPARISON:\n//\n// Comparison always considers all six YMDHMS fields, regardless of the type's\n// alignment. Comparison between differently aligned civil-time types is\n// allowed.\n//\n//   civil_day feb_3(2015, 2, 3);  // 2015-02-03 00:00:00\n//   civil_day mar_4(2015, 3, 4);  // 2015-03-04 00:00:00\n//   // feb_3 < mar_4\n//   // civil_year(feb_3) == civil_year(mar_4)\n//\n//   civil_second feb_3_noon(2015, 2, 3, 12, 0, 0);  // 2015-02-03 12:00:00\n//   // feb_3 < feb_3_noon\n//   // feb_3 == civil_day(feb_3_noon)\n//\n//   // Iterates all the days of February 2015.\n//   for (civil_day d(2015, 2, 1); d < civil_month(2015, 3); ++d) {\n//     // ...\n//   }\n//\n// STREAMING:\n//\n// Each civil-time type may be sent to an output stream using operator<<().\n// The output format follows the pattern \"YYYY-MM-DDThh:mm:ss\" where fields\n// inferior to the type's alignment are omitted.\n//\n//   civil_second cs(2015, 2, 3, 4, 5, 6);\n//   std::cout << cs << \"\\n\";  // Outputs: 2015-02-03T04:05:06\n//\n//   civil_day cd(cs);\n//   std::cout << cd << \"\\n\";  // Outputs: 2015-02-03\n//\n//   civil_year cy(cs);\n//   std::cout << cy << \"\\n\";  // Outputs: 2015\n//\n// ARITHMETIC:\n//\n// Civil-time types support natural arithmetic operators such as addition,\n// subtraction, and difference. Arithmetic operates on the civil-time field\n// indicated in the type's name. Difference requires arguments with the same\n// alignment and returns the answer in units of the alignment.\n//\n//   civil_day a(2015, 2, 3);\n//   ++a;                         // 2015-02-04 00:00:00\n//   --a;                         // 2015-02-03 00:00:00\n//   civil_day b = a + 1;         // 2015-02-04 00:00:00\n//   civil_day c = 1 + b;         // 2015-02-05 00:00:00\n//   int n = c - a;               // n = 2 (civil days)\n//   int m = c - civil_month(c);  // Won't compile: different types.\n//\n// EXAMPLE: Adding a month to January 31.\n//\n// One of the classic questions that arises when considering a civil-time\n// library (or a date library or a date/time library) is this: \"What happens\n// when you add a month to January 31?\" This is an interesting question\n// because there could be a number of possible answers:\n//\n//   1. March 3 (or 2 if a leap year). This may make sense if the operation\n//      wants the equivalent of February 31.\n//   2. February 28 (or 29 if a leap year). This may make sense if the operation\n//      wants the last day of January to go to the last day of February.\n//   3. Error. The caller may get some error, an exception, an invalid date\n//      object, or maybe false is returned. This may make sense because there is\n//      no single unambiguously correct answer to the question.\n//\n// Practically speaking, any answer that is not what the programmer intended\n// is the wrong answer.\n//\n// This civil-time library avoids the problem by making it impossible to ask\n// ambiguous questions. All civil-time objects are aligned to a particular\n// civil-field boundary (such as aligned to a year, month, day, hour, minute,\n// or second), and arithmetic operates on the field to which the object is\n// aligned. This means that in order to \"add a month\" the object must first be\n// aligned to a month boundary, which is equivalent to the first day of that\n// month.\n//\n// Of course, there are ways to compute an answer the question at hand using\n// this civil-time library, but they require the programmer to be explicit\n// about the answer they expect. To illustrate, let's see how to compute all\n// three of the above possible answers to the question of \"Jan 31 plus 1\n// month\":\n//\n//   const civil_day d(2015, 1, 31);\n//\n//   // Answer 1:\n//   // Add 1 to the month field in the constructor, and rely on normalization.\n//   const auto ans_normalized = civil_day(d.year(), d.month() + 1, d.day());\n//   // ans_normalized == 2015-03-03 (aka Feb 31)\n//\n//   // Answer 2:\n//   // Add 1 to month field, capping to the end of next month.\n//   const auto next_month = civil_month(d) + 1;\n//   const auto last_day_of_next_month = civil_day(next_month + 1) - 1;\n//   const auto ans_capped = std::min(ans_normalized, last_day_of_next_month);\n//   // ans_capped == 2015-02-28\n//\n//   // Answer 3:\n//   // Signal an error if the normalized answer is not in next month.\n//   if (civil_month(ans_normalized) != next_month) {\n//     // error, month overflow\n//   }\n//\nusing civil_year = detail::civil_year;\nusing civil_month = detail::civil_month;\nusing civil_day = detail::civil_day;\nusing civil_hour = detail::civil_hour;\nusing civil_minute = detail::civil_minute;\nusing civil_second = detail::civil_second;\n\n// An enum class with members monday, tuesday, wednesday, thursday, friday,\n// saturday, and sunday. These enum values may be sent to an output stream\n// using operator<<(). The result is the full weekday name in English with a\n// leading capital letter.\n//\n//   weekday wd = weekday::thursday;\n//   std::cout << wd << \"\\n\";  // Outputs: Thursday\n//\nusing detail::weekday;\n\n// Returns the weekday for the given civil-time value.\n//\n//   civil_day a(2015, 8, 13);\n//   weekday wd = get_weekday(a);  // wd == weekday::thursday\n//\nusing detail::get_weekday;\n\n// Returns the civil_day that strictly follows or precedes the given\n// civil_day, and that falls on the given weekday.\n//\n// For example, given:\n//\n//     August 2015\n// Su Mo Tu We Th Fr Sa\n//                    1\n//  2  3  4  5  6  7  8\n//  9 10 11 12 13 14 15\n// 16 17 18 19 20 21 22\n// 23 24 25 26 27 28 29\n// 30 31\n//\n//   civil_day a(2015, 8, 13);  // get_weekday(a) == weekday::thursday\n//   civil_day b = next_weekday(a, weekday::thursday);  // b = 2015-08-20\n//   civil_day c = prev_weekday(a, weekday::thursday);  // c = 2015-08-06\n//\n//   civil_day d = ...\n//   // Gets the following Thursday if d is not already Thursday\n//   civil_day thurs1 = next_weekday(d - 1, weekday::thursday);\n//   // Gets the previous Thursday if d is not already Thursday\n//   civil_day thurs2 = prev_weekday(d + 1, weekday::thursday);\n//\nusing detail::next_weekday;\nusing detail::prev_weekday;\n\n// Returns the day-of-year for the given civil-time value.\n//\n//   civil_day a(2015, 1, 1);\n//   int yd_jan_1 = get_yearday(a);   // yd_jan_1 = 1\n//   civil_day b(2015, 12, 31);\n//   int yd_dec_31 = get_yearday(b);  // yd_dec_31 = 365\n//\nusing detail::get_yearday;\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/include/cctz/civil_time_detail.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_\n#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_\n\n#include <cstdint>\n#include <limits>\n#include <ostream>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n\n// Disable constexpr support unless we are in C++14 mode.\n#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)\n#define CONSTEXPR_D constexpr  // data\n#define CONSTEXPR_F constexpr  // function\n#define CONSTEXPR_M constexpr  // member\n#else\n#define CONSTEXPR_D const\n#define CONSTEXPR_F inline\n#define CONSTEXPR_M\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// Support years that at least span the range of 64-bit time_t values.\nusing year_t = std::int_fast64_t;\n\n// Type alias that indicates an argument is not normalized (e.g., the\n// constructor parameters and operands/results of addition/subtraction).\nusing diff_t = std::int_fast64_t;\n\nnamespace detail {\n\n// Type aliases that indicate normalized argument values.\nusing month_t = std::int_fast8_t;   // [1:12]\nusing day_t = std::int_fast8_t;     // [1:31]\nusing hour_t = std::int_fast8_t;    // [0:23]\nusing minute_t = std::int_fast8_t;  // [0:59]\nusing second_t = std::int_fast8_t;  // [0:59]\n\n// Normalized civil-time fields: Y-M-D HH:MM:SS.\nstruct fields {\n  CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour,\n                     minute_t minute, second_t second)\n      : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {}\n  std::int_least64_t y;\n  std::int_least8_t m;\n  std::int_least8_t d;\n  std::int_least8_t hh;\n  std::int_least8_t mm;\n  std::int_least8_t ss;\n};\n\nstruct second_tag {};\nstruct minute_tag : second_tag {};\nstruct hour_tag : minute_tag {};\nstruct day_tag : hour_tag {};\nstruct month_tag : day_tag {};\nstruct year_tag : month_tag {};\n\n////////////////////////////////////////////////////////////////////////\n\n// Field normalization (without avoidable overflow).\n\nnamespace impl {\n\nCONSTEXPR_F bool is_leap_year(year_t y) noexcept {\n  return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);\n}\nCONSTEXPR_F int year_index(year_t y, month_t m) noexcept {\n  const int yi = static_cast<int>((y + (m > 2)) % 400);\n  return yi < 0 ? yi + 400 : yi;\n}\nCONSTEXPR_F int days_per_century(int yi) noexcept {\n  return 36524 + (yi == 0 || yi > 300);\n}\nCONSTEXPR_F int days_per_4years(int yi) noexcept {\n  return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96);\n}\nCONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept {\n  return is_leap_year(y + (m > 2)) ? 366 : 365;\n}\n// The compiler cannot optimize away the check if we use\n// -fsanitize=array-bounds.\n// m is guaranteed to be in [1:12] in the caller, but the compiler cannot\n// optimize away the check even when this function is inlined into BreakTime.\n// To reduce the overhead, we use no_sanitize to skip the unnecessary\n// -fsanitize=array-bounds check. Remove no_sanitize once the missed\n// optimization is fixed.\n#if defined(__clang__) && defined(__has_cpp_attribute)\n#if __has_cpp_attribute(clang::no_sanitize)\n[[clang::no_sanitize(\"array-bounds\")]]\n#endif\n#endif\nCONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept {\n  CONSTEXPR_D int k_days_per_month[1 + 12] = {\n      -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  // non leap year\n  };\n  return k_days_per_month[m] + (m == 2 && is_leap_year(y));\n}\n\nCONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh,\n                         minute_t mm, second_t ss) noexcept {\n  year_t ey = y % 400;\n  const year_t oey = ey;\n  ey += (cd / 146097) * 400;\n  cd %= 146097;\n  if (cd < 0) {\n    ey -= 400;\n    cd += 146097;\n  }\n  ey += (d / 146097) * 400;\n  d = d % 146097 + cd;\n  if (d > 0) {\n    if (d > 146097) {\n      ey += 400;\n      d -= 146097;\n    }\n  } else {\n    if (d > -365) {\n      // We often hit the previous year when stepping a civil time backwards,\n      // so special case it to avoid counting up by 100/4/1-year chunks.\n      ey -= 1;\n      d += days_per_year(ey, m);\n    } else {\n      ey -= 400;\n      d += 146097;\n    }\n  }\n  if (d > 365) {\n    int yi = year_index(ey, m);  // Index into Gregorian 400 year cycle.\n    for (;;) {\n      int n = days_per_century(yi);\n      if (d <= n) break;\n      d -= n;\n      ey += 100;\n      yi += 100;\n      if (yi >= 400) yi -= 400;\n    }\n    for (;;) {\n      int n = days_per_4years(yi);\n      if (d <= n) break;\n      d -= n;\n      ey += 4;\n      yi += 4;\n      if (yi >= 400) yi -= 400;\n    }\n    for (;;) {\n      int n = days_per_year(ey, m);\n      if (d <= n) break;\n      d -= n;\n      ++ey;\n    }\n  }\n  if (d > 28) {\n    for (;;) {\n      int n = days_per_month(ey, m);\n      if (d <= n) break;\n      d -= n;\n      if (++m > 12) {\n        ++ey;\n        m = 1;\n      }\n    }\n  }\n  return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss);\n}\nCONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh,\n                         minute_t mm, second_t ss) noexcept {\n  if (m != 12) {\n    y += m / 12;\n    m %= 12;\n    if (m <= 0) {\n      y -= 1;\n      m += 12;\n    }\n  }\n  return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss);\n}\nCONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh,\n                          minute_t mm, second_t ss) noexcept {\n  cd += hh / 24;\n  hh %= 24;\n  if (hh < 0) {\n    cd -= 1;\n    hh += 24;\n  }\n  return n_mon(y, m, d, cd, static_cast<hour_t>(hh), mm, ss);\n}\nCONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch,\n                         diff_t mm, second_t ss) noexcept {\n  ch += mm / 60;\n  mm %= 60;\n  if (mm < 0) {\n    ch -= 1;\n    mm += 60;\n  }\n  return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24,\n                static_cast<minute_t>(mm), ss);\n}\nCONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm,\n                         diff_t ss) noexcept {\n  // Optimization for when (non-constexpr) fields are already normalized.\n  if (0 <= ss && ss < 60) {\n    const second_t nss = static_cast<second_t>(ss);\n    if (0 <= mm && mm < 60) {\n      const minute_t nmm = static_cast<minute_t>(mm);\n      if (0 <= hh && hh < 24) {\n        const hour_t nhh = static_cast<hour_t>(hh);\n        if (1 <= d && d <= 28 && 1 <= m && m <= 12) {\n          const day_t nd = static_cast<day_t>(d);\n          const month_t nm = static_cast<month_t>(m);\n          return fields(y, nm, nd, nhh, nmm, nss);\n        }\n        return n_mon(y, m, d, 0, nhh, nmm, nss);\n      }\n      return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss);\n    }\n    return n_min(y, m, d, hh, mm / 60, mm % 60, nss);\n  }\n  diff_t cm = ss / 60;\n  ss %= 60;\n  if (ss < 0) {\n    cm -= 1;\n    ss += 60;\n  }\n  return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60,\n               static_cast<second_t>(ss));\n}\n\n}  // namespace impl\n\n////////////////////////////////////////////////////////////////////////\n\n// Increments the indicated (normalized) field by \"n\".\nCONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept {\n  return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60);\n}\nCONSTEXPR_F fields step(minute_tag, fields f, diff_t n) noexcept {\n  return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss);\n}\nCONSTEXPR_F fields step(hour_tag, fields f, diff_t n) noexcept {\n  return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss);\n}\nCONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept {\n  return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss);\n}\nCONSTEXPR_F fields step(month_tag, fields f, diff_t n) noexcept {\n  return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss);\n}\nCONSTEXPR_F fields step(year_tag, fields f, diff_t n) noexcept {\n  return fields(f.y + n, f.m, f.d, f.hh, f.mm, f.ss);\n}\n\n////////////////////////////////////////////////////////////////////////\n\nnamespace impl {\n\n// Returns (v * f + a) but avoiding intermediate overflow when possible.\nCONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept {\n  return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f;\n}\n\n// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01.\n// Probably overflows for years outside [-292277022656:292277026595].\nCONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept {\n  const diff_t eyear = (m <= 2) ? y - 1 : y;\n  const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400;\n  const diff_t yoe = eyear - era * 400;\n  const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;\n  const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;\n  return era * 146097 + doe - 719468;\n}\n\n// Returns the difference in days between two normalized Y-M-D tuples.\n// ymd_ord() will encounter integer overflow given extreme year values,\n// yet the difference between two such extreme values may actually be\n// small, so we take a little care to avoid overflow when possible by\n// exploiting the 146097-day cycle.\nCONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2,\n                                  month_t m2, day_t d2) noexcept {\n  const diff_t a_c4_off = y1 % 400;\n  const diff_t b_c4_off = y2 % 400;\n  diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off);\n  diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2);\n  if (c4_diff > 0 && delta < 0) {\n    delta += 2 * 146097;\n    c4_diff -= 2 * 400;\n  } else if (c4_diff < 0 && delta > 0) {\n    delta -= 2 * 146097;\n    c4_diff += 2 * 400;\n  }\n  return (c4_diff / 400 * 146097) + delta;\n}\n\n}  // namespace impl\n\n// Returns the difference between fields structs using the indicated unit.\nCONSTEXPR_F diff_t difference(year_tag, fields f1, fields f2) noexcept {\n  return f1.y - f2.y;\n}\nCONSTEXPR_F diff_t difference(month_tag, fields f1, fields f2) noexcept {\n  return impl::scale_add(difference(year_tag{}, f1, f2), 12, (f1.m - f2.m));\n}\nCONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept {\n  return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d);\n}\nCONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept {\n  return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh));\n}\nCONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept {\n  return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm));\n}\nCONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept {\n  return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss);\n}\n\n////////////////////////////////////////////////////////////////////////\n\n// Aligns the (normalized) fields struct to the indicated field.\nCONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; }\nCONSTEXPR_F fields align(minute_tag, fields f) noexcept {\n  return fields{f.y, f.m, f.d, f.hh, f.mm, 0};\n}\nCONSTEXPR_F fields align(hour_tag, fields f) noexcept {\n  return fields{f.y, f.m, f.d, f.hh, 0, 0};\n}\nCONSTEXPR_F fields align(day_tag, fields f) noexcept {\n  return fields{f.y, f.m, f.d, 0, 0, 0};\n}\nCONSTEXPR_F fields align(month_tag, fields f) noexcept {\n  return fields{f.y, f.m, 1, 0, 0, 0};\n}\nCONSTEXPR_F fields align(year_tag, fields f) noexcept {\n  return fields{f.y, 1, 1, 0, 0, 0};\n}\n\n////////////////////////////////////////////////////////////////////////\n\nnamespace impl {\n\ntemplate <typename H>\nH AbslHashValueImpl(second_tag, H h, fields f) {\n  return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss);\n}\ntemplate <typename H>\nH AbslHashValueImpl(minute_tag, H h, fields f) {\n  return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm);\n}\ntemplate <typename H>\nH AbslHashValueImpl(hour_tag, H h, fields f) {\n  return H::combine(std::move(h), f.y, f.m, f.d, f.hh);\n}\ntemplate <typename H>\nH AbslHashValueImpl(day_tag, H h, fields f) {\n  return H::combine(std::move(h), f.y, f.m, f.d);\n}\ntemplate <typename H>\nH AbslHashValueImpl(month_tag, H h, fields f) {\n  return H::combine(std::move(h), f.y, f.m);\n}\ntemplate <typename H>\nH AbslHashValueImpl(year_tag, H h, fields f) {\n  return H::combine(std::move(h), f.y);\n}\n\n}  // namespace impl\n\n////////////////////////////////////////////////////////////////////////\n\ntemplate <typename T>\nclass civil_time {\n public:\n  explicit CONSTEXPR_M civil_time(year_t y, diff_t m = 1, diff_t d = 1,\n                                  diff_t hh = 0, diff_t mm = 0,\n                                  diff_t ss = 0) noexcept\n      : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {}\n\n  CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {}\n  civil_time(const civil_time&) = default;\n  civil_time& operator=(const civil_time&) = default;\n\n  // Conversion between civil times of different alignment. Conversion to\n  // a more precise alignment is allowed implicitly (e.g., day -> hour),\n  // but conversion where information is discarded must be explicit\n  // (e.g., second -> minute).\n  template <typename U, typename S>\n  using preserves_data =\n      typename std::enable_if<std::is_base_of<U, S>::value>::type;\n  template <typename U>\n  CONSTEXPR_M civil_time(const civil_time<U>& ct,\n                         preserves_data<T, U>* = nullptr) noexcept\n      : civil_time(ct.f_) {}\n  template <typename U>\n  explicit CONSTEXPR_M civil_time(const civil_time<U>& ct,\n                                  preserves_data<U, T>* = nullptr) noexcept\n      : civil_time(ct.f_) {}\n\n  // Factories for the maximum/minimum representable civil_time.\n  static CONSTEXPR_F auto(max)() -> civil_time {\n    const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();\n    return civil_time(max_year, 12, 31, 23, 59, 59);\n  }\n  static CONSTEXPR_F auto(min)() -> civil_time {\n    const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();\n    return civil_time(min_year, 1, 1, 0, 0, 0);\n  }\n\n  // Field accessors.  Note: All but year() return an int.\n  CONSTEXPR_M year_t year() const noexcept { return f_.y; }\n  CONSTEXPR_M int month() const noexcept { return f_.m; }\n  CONSTEXPR_M int day() const noexcept { return f_.d; }\n  CONSTEXPR_M int hour() const noexcept { return f_.hh; }\n  CONSTEXPR_M int minute() const noexcept { return f_.mm; }\n  CONSTEXPR_M int second() const noexcept { return f_.ss; }\n\n  // Assigning arithmetic.\n  CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {\n    return *this = *this + n;\n  }\n  CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {\n    return *this = *this - n;\n  }\n  CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }\n  CONSTEXPR_M civil_time operator++(int) noexcept {\n    const civil_time a = *this;\n    ++*this;\n    return a;\n  }\n  CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; }\n  CONSTEXPR_M civil_time operator--(int) noexcept {\n    const civil_time a = *this;\n    --*this;\n    return a;\n  }\n\n  // Binary arithmetic operators.\n  friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {\n    return civil_time(step(T{}, a.f_, n));\n  }\n  friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {\n    return a + n;\n  }\n  friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {\n    return n != (std::numeric_limits<diff_t>::min)()\n               ? civil_time(step(T{}, a.f_, -n))\n               : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));\n  }\n  friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {\n    return difference(T{}, lhs.f_, rhs.f_);\n  }\n\n  template <typename H>\n  friend H AbslHashValue(H h, civil_time a) {\n    return impl::AbslHashValueImpl(T{}, std::move(h), a.f_);\n  }\n\n private:\n  // All instantiations of this template are allowed to call the following\n  // private constructor and access the private fields member.\n  template <typename U>\n  friend class civil_time;\n\n  // The designated constructor that all others eventually call.\n  explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {}\n\n  fields f_;\n};\n\n// Disallows difference between differently aligned types.\n// auto n = civil_day(...) - civil_hour(...);  // would be confusing.\ntemplate <typename T, typename U>\nCONSTEXPR_F diff_t operator-(civil_time<T>, civil_time<U>) = delete;\n\nusing civil_year = civil_time<year_tag>;\nusing civil_month = civil_time<month_tag>;\nusing civil_day = civil_time<day_tag>;\nusing civil_hour = civil_time<hour_tag>;\nusing civil_minute = civil_time<minute_tag>;\nusing civil_second = civil_time<second_tag>;\n\n////////////////////////////////////////////////////////////////////////\n\n// Relational operators that work with differently aligned objects.\n// Always compares all six fields.\ntemplate <typename T1, typename T2>\nCONSTEXPR_F bool operator<(const civil_time<T1>& lhs,\n                           const civil_time<T2>& rhs) noexcept {\n  return (\n      lhs.year() < rhs.year() ||\n      (lhs.year() == rhs.year() &&\n       (lhs.month() < rhs.month() ||\n        (lhs.month() == rhs.month() &&\n         (lhs.day() < rhs.day() || (lhs.day() == rhs.day() &&\n                                    (lhs.hour() < rhs.hour() ||\n                                     (lhs.hour() == rhs.hour() &&\n                                      (lhs.minute() < rhs.minute() ||\n                                       (lhs.minute() == rhs.minute() &&\n                                        (lhs.second() < rhs.second())))))))))));\n}\ntemplate <typename T1, typename T2>\nCONSTEXPR_F bool operator<=(const civil_time<T1>& lhs,\n                            const civil_time<T2>& rhs) noexcept {\n  return !(rhs < lhs);\n}\ntemplate <typename T1, typename T2>\nCONSTEXPR_F bool operator>=(const civil_time<T1>& lhs,\n                            const civil_time<T2>& rhs) noexcept {\n  return !(lhs < rhs);\n}\ntemplate <typename T1, typename T2>\nCONSTEXPR_F bool operator>(const civil_time<T1>& lhs,\n                           const civil_time<T2>& rhs) noexcept {\n  return rhs < lhs;\n}\ntemplate <typename T1, typename T2>\nCONSTEXPR_F bool operator==(const civil_time<T1>& lhs,\n                            const civil_time<T2>& rhs) noexcept {\n  return lhs.year() == rhs.year() && lhs.month() == rhs.month() &&\n         lhs.day() == rhs.day() && lhs.hour() == rhs.hour() &&\n         lhs.minute() == rhs.minute() && lhs.second() == rhs.second();\n}\ntemplate <typename T1, typename T2>\nCONSTEXPR_F bool operator!=(const civil_time<T1>& lhs,\n                            const civil_time<T2>& rhs) noexcept {\n  return !(lhs == rhs);\n}\n\n////////////////////////////////////////////////////////////////////////\n\nenum class weekday {\n  monday,\n  tuesday,\n  wednesday,\n  thursday,\n  friday,\n  saturday,\n  sunday,\n};\n\nCONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept {\n  CONSTEXPR_D weekday k_weekday_by_mon_off[13] = {\n      weekday::monday,    weekday::tuesday,  weekday::wednesday,\n      weekday::thursday,  weekday::friday,   weekday::saturday,\n      weekday::sunday,    weekday::monday,   weekday::tuesday,\n      weekday::wednesday, weekday::thursday, weekday::friday,\n      weekday::saturday,\n  };\n  CONSTEXPR_D int k_weekday_offsets[1 + 12] = {\n      -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4,\n  };\n  year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3);\n  wd += wd / 4 - wd / 100 + wd / 400;\n  wd += k_weekday_offsets[cs.month()] + cs.day();\n  return k_weekday_by_mon_off[wd % 7 + 6];\n}\n\n////////////////////////////////////////////////////////////////////////\n\nCONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept {\n  CONSTEXPR_D weekday k_weekdays_forw[14] = {\n      weekday::monday,    weekday::tuesday,  weekday::wednesday,\n      weekday::thursday,  weekday::friday,   weekday::saturday,\n      weekday::sunday,    weekday::monday,   weekday::tuesday,\n      weekday::wednesday, weekday::thursday, weekday::friday,\n      weekday::saturday,  weekday::sunday,\n  };\n  weekday base = get_weekday(cd);\n  for (int i = 0;; ++i) {\n    if (base == k_weekdays_forw[i]) {\n      for (int j = i + 1;; ++j) {\n        if (wd == k_weekdays_forw[j]) {\n          return cd + (j - i);\n        }\n      }\n    }\n  }\n}\n\nCONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept {\n  CONSTEXPR_D weekday k_weekdays_back[14] = {\n      weekday::sunday,   weekday::saturday,  weekday::friday,\n      weekday::thursday, weekday::wednesday, weekday::tuesday,\n      weekday::monday,   weekday::sunday,    weekday::saturday,\n      weekday::friday,   weekday::thursday,  weekday::wednesday,\n      weekday::tuesday,  weekday::monday,\n  };\n  weekday base = get_weekday(cd);\n  for (int i = 0;; ++i) {\n    if (base == k_weekdays_back[i]) {\n      for (int j = i + 1;; ++j) {\n        if (wd == k_weekdays_back[j]) {\n          return cd - (j - i);\n        }\n      }\n    }\n  }\n}\n\nCONSTEXPR_F int get_yearday(const civil_second& cs) noexcept {\n  CONSTEXPR_D int k_month_offsets[1 + 12] = {\n      -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,\n  };\n  const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year()));\n  return k_month_offsets[cs.month()] + feb29 + cs.day();\n}\n\n////////////////////////////////////////////////////////////////////////\n\nstd::ostream& operator<<(std::ostream& os, const civil_year& y);\nstd::ostream& operator<<(std::ostream& os, const civil_month& m);\nstd::ostream& operator<<(std::ostream& os, const civil_day& d);\nstd::ostream& operator<<(std::ostream& os, const civil_hour& h);\nstd::ostream& operator<<(std::ostream& os, const civil_minute& m);\nstd::ostream& operator<<(std::ostream& os, const civil_second& s);\nstd::ostream& operator<<(std::ostream& os, weekday wd);\n\n}  // namespace detail\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#undef CONSTEXPR_M\n#undef CONSTEXPR_F\n#undef CONSTEXPR_D\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/include/cctz/time_zone.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n// A library for translating between absolute times (represented by\n// std::chrono::time_points of the std::chrono::system_clock) and civil\n// times (represented by cctz::civil_second) using the rules defined by\n// a time zone (cctz::time_zone).\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_\n\n#include <chrono>\n#include <cstdint>\n#include <limits>\n#include <ratio>  // NOLINT: We use std::ratio in this header\n#include <string>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// Convenience aliases. Not intended as public API points.\ntemplate <typename D>\nusing time_point = std::chrono::time_point<std::chrono::system_clock, D>;\nusing seconds = std::chrono::duration<std::int_fast64_t>;\nusing sys_seconds = seconds;  // Deprecated.  Use cctz::seconds instead.\n\nnamespace detail {\ntemplate <typename D>\nstd::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp);\nstd::pair<time_point<seconds>, seconds> split_seconds(\n    const time_point<seconds>& tp);\n}  // namespace detail\n\n// cctz::time_zone is an opaque, small, value-type class representing a\n// geo-political region within which particular rules are used for mapping\n// between absolute and civil times. Time zones are named using the TZ\n// identifiers from the IANA Time Zone Database, such as \"America/Los_Angeles\"\n// or \"Australia/Sydney\". Time zones are created from factory functions such\n// as load_time_zone(). Note: strings like \"PST\" and \"EDT\" are not valid TZ\n// identifiers.\n//\n// Example:\n//   cctz::time_zone utc = cctz::utc_time_zone();\n//   cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8));\n//   cctz::time_zone loc = cctz::local_time_zone();\n//   cctz::time_zone lax;\n//   if (!cctz::load_time_zone(\"America/Los_Angeles\", &lax)) { ... }\n//\n// See also:\n// - http://www.iana.org/time-zones\n// - https://en.wikipedia.org/wiki/Zoneinfo\nclass time_zone {\n public:\n  time_zone() : time_zone(nullptr) {}  // Equivalent to UTC\n  time_zone(const time_zone&) = default;\n  time_zone& operator=(const time_zone&) = default;\n\n  std::string name() const;\n\n  // An absolute_lookup represents the civil time (cctz::civil_second) within\n  // this time_zone at the given absolute time (time_point). There are\n  // additionally a few other fields that may be useful when working with\n  // older APIs, such as std::tm.\n  //\n  // Example:\n  //   const cctz::time_zone tz = ...\n  //   const auto tp = std::chrono::system_clock::now();\n  //   const cctz::time_zone::absolute_lookup al = tz.lookup(tp);\n  struct absolute_lookup {\n    civil_second cs;\n    // Note: The following fields exist for backward compatibility with older\n    // APIs. Accessing these fields directly is a sign of imprudent logic in\n    // the calling code. Modern time-related code should only access this data\n    // indirectly by way of cctz::format().\n    int offset;        // civil seconds east of UTC\n    bool is_dst;       // is offset non-standard?\n    const char* abbr;  // time-zone abbreviation (e.g., \"PST\")\n  };\n  absolute_lookup lookup(const time_point<seconds>& tp) const;\n  template <typename D>\n  absolute_lookup lookup(const time_point<D>& tp) const {\n    return lookup(detail::split_seconds(tp).first);\n  }\n\n  // A civil_lookup represents the absolute time(s) (time_point) that\n  // correspond to the given civil time (cctz::civil_second) within this\n  // time_zone. Usually the given civil time represents a unique instant\n  // in time, in which case the conversion is unambiguous. However,\n  // within this time zone, the given civil time may be skipped (e.g.,\n  // during a positive UTC offset shift), or repeated (e.g., during a\n  // negative UTC offset shift). To account for these possibilities,\n  // civil_lookup is richer than just a single time_point.\n  //\n  // In all cases the civil_lookup::kind enum will indicate the nature\n  // of the given civil-time argument, and the pre, trans, and post\n  // members will give the absolute time answers using the pre-transition\n  // offset, the transition point itself, and the post-transition offset,\n  // respectively (all three times are equal if kind == UNIQUE). If any\n  // of these three absolute times is outside the representable range of a\n  // time_point<seconds> the field is set to its maximum/minimum value.\n  //\n  // Example:\n  //   cctz::time_zone lax;\n  //   if (!cctz::load_time_zone(\"America/Los_Angeles\", &lax)) { ... }\n  //\n  //   // A unique civil time.\n  //   auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0));\n  //   // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE\n  //   // jan01.pre    is 2011/01/01 00:00:00 -0800\n  //   // jan01.trans  is 2011/01/01 00:00:00 -0800\n  //   // jan01.post   is 2011/01/01 00:00:00 -0800\n  //\n  //   // A Spring DST transition, when there is a gap in civil time.\n  //   auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0));\n  //   // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED\n  //   // mar13.pre   is 2011/03/13 03:15:00 -0700\n  //   // mar13.trans is 2011/03/13 03:00:00 -0700\n  //   // mar13.post  is 2011/03/13 01:15:00 -0800\n  //\n  //   // A Fall DST transition, when civil times are repeated.\n  //   auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0));\n  //   // nov06.kind == cctz::time_zone::civil_lookup::REPEATED\n  //   // nov06.pre   is 2011/11/06 01:15:00 -0700\n  //   // nov06.trans is 2011/11/06 01:00:00 -0800\n  //   // nov06.post  is 2011/11/06 01:15:00 -0800\n  struct civil_lookup {\n    enum civil_kind {\n      UNIQUE,    // the civil time was singular (pre == trans == post)\n      SKIPPED,   // the civil time did not exist (pre >= trans > post)\n      REPEATED,  // the civil time was ambiguous (pre < trans <= post)\n    } kind;\n    time_point<seconds> pre;    // uses the pre-transition offset\n    time_point<seconds> trans;  // instant of civil-offset change\n    time_point<seconds> post;   // uses the post-transition offset\n  };\n  civil_lookup lookup(const civil_second& cs) const;\n\n  // Finds the time of the next/previous offset change in this time zone.\n  //\n  // By definition, next_transition(tp, &trans) returns false when tp has\n  // its maximum value, and prev_transition(tp, &trans) returns false\n  // when tp has its minimum value. If the zone has no transitions, the\n  // result will also be false no matter what the argument.\n  //\n  // Otherwise, when tp has its minimum value, next_transition(tp, &trans)\n  // returns true and sets trans to the first recorded transition. Chains\n  // of calls to next_transition()/prev_transition() will eventually return\n  // false, but it is unspecified exactly when next_transition(tp, &trans)\n  // jumps to false, or what time is set by prev_transition(tp, &trans) for\n  // a very distant tp.\n  //\n  // Note: Enumeration of time-zone transitions is for informational purposes\n  // only. Modern time-related code should not care about when offset changes\n  // occur.\n  //\n  // Example:\n  //   cctz::time_zone nyc;\n  //   if (!cctz::load_time_zone(\"America/New_York\", &nyc)) { ... }\n  //   const auto now = std::chrono::system_clock::now();\n  //   auto tp = cctz::time_point<cctz::seconds>::min();\n  //   cctz::time_zone::civil_transition trans;\n  //   while (tp <= now && nyc.next_transition(tp, &trans)) {\n  //     // transition: trans.from -> trans.to\n  //     tp = nyc.lookup(trans.to).trans;\n  //   }\n  struct civil_transition {\n    civil_second from;  // the civil time we jump from\n    civil_second to;    // the civil time we jump to\n  };\n  bool next_transition(const time_point<seconds>& tp,\n                       civil_transition* trans) const;\n  template <typename D>\n  bool next_transition(const time_point<D>& tp, civil_transition* trans) const {\n    return next_transition(detail::split_seconds(tp).first, trans);\n  }\n  bool prev_transition(const time_point<seconds>& tp,\n                       civil_transition* trans) const;\n  template <typename D>\n  bool prev_transition(const time_point<D>& tp, civil_transition* trans) const {\n    return prev_transition(detail::split_seconds(tp).first, trans);\n  }\n\n  // version() and description() provide additional information about the\n  // time zone. The content of each of the returned strings is unspecified,\n  // however, when the IANA Time Zone Database is the underlying data source\n  // the version() string will be in the familiar form (e.g, \"2018e\") or\n  // empty when unavailable.\n  //\n  // Note: These functions are for informational or testing purposes only.\n  std::string version() const;  // empty when unknown\n  std::string description() const;\n\n  // Relational operators.\n  friend bool operator==(time_zone lhs, time_zone rhs) {\n    return &lhs.effective_impl() == &rhs.effective_impl();\n  }\n  friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); }\n\n  template <typename H>\n  friend H AbslHashValue(H h, time_zone tz) {\n    return H::combine(std::move(h), &tz.effective_impl());\n  }\n\n  class Impl;\n\n private:\n  explicit time_zone(const Impl* impl) : impl_(impl) {}\n  const Impl& effective_impl() const;  // handles implicit UTC\n  const Impl* impl_;\n};\n\n// Loads the named time zone. May perform I/O on the initial load.\n// If the name is invalid, or some other kind of error occurs, returns\n// false and \"*tz\" is set to the UTC time zone.\nbool load_time_zone(const std::string& name, time_zone* tz);\n\n// Returns a time_zone representing UTC. Cannot fail.\ntime_zone utc_time_zone();\n\n// Returns a time zone that is a fixed offset (seconds east) from UTC.\n// Note: If the absolute value of the offset is greater than 24 hours\n// you'll get UTC (i.e., zero offset) instead.\ntime_zone fixed_time_zone(const seconds& offset);\n\n// Returns a time zone representing the local time zone. Falls back to UTC.\n// Note: local_time_zone.name() may only be something like \"localtime\".\ntime_zone local_time_zone();\n\n// Returns the civil time (cctz::civil_second) within the given time zone at\n// the given absolute time (time_point). Since the additional fields provided\n// by the time_zone::absolute_lookup struct should rarely be needed in modern\n// code, this convert() function is simpler and should be preferred.\ntemplate <typename D>\ninline civil_second convert(const time_point<D>& tp, const time_zone& tz) {\n  return tz.lookup(tp).cs;\n}\n\n// Returns the absolute time (time_point) that corresponds to the given civil\n// time within the given time zone. If the civil time is not unique (i.e., if\n// it was either repeated or non-existent), then the returned time_point is\n// the best estimate that preserves relative order. That is, this function\n// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz).\ninline time_point<seconds> convert(const civil_second& cs,\n                                   const time_zone& tz) {\n  const time_zone::civil_lookup cl = tz.lookup(cs);\n  if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans;\n  return cl.pre;\n}\n\nnamespace detail {\nusing femtoseconds = std::chrono::duration<std::int_fast64_t, std::femto>;\nstd::string format(const std::string&, const time_point<seconds>&,\n                   const femtoseconds&, const time_zone&);\nbool parse(const std::string&, const std::string&, const time_zone&,\n           time_point<seconds>*, femtoseconds*, std::string* err = nullptr);\ntemplate <typename Rep, std::intmax_t Denom>\nbool join_seconds(\n    const time_point<seconds>& sec, const femtoseconds& fs,\n    time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp);\ntemplate <typename Rep, std::intmax_t Num>\nbool join_seconds(\n    const time_point<seconds>& sec, const femtoseconds& fs,\n    time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp);\ntemplate <typename Rep>\nbool join_seconds(\n    const time_point<seconds>& sec, const femtoseconds& fs,\n    time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp);\nbool join_seconds(const time_point<seconds>& sec, const femtoseconds&,\n                  time_point<seconds>* tpp);\n}  // namespace detail\n\n// Formats the given time_point in the given cctz::time_zone according to\n// the provided format string. Uses strftime()-like formatting options,\n// with the following extensions:\n//\n//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)\n//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)\n//   - %E#S - Seconds with # digits of fractional precision\n//   - %E*S - Seconds with full fractional precision (a literal '*')\n//   - %E#f - Fractional seconds with # digits of precision\n//   - %E*f - Fractional seconds with full precision (a literal '*')\n//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)\n//   - %ET  - The RFC3339 \"date-time\" separator \"T\"\n//\n// Note that %E0S behaves like %S, and %E0f produces no characters. In\n// contrast %E*f always produces at least one digit, which may be '0'.\n//\n// Note that %Y produces as many characters as it takes to fully render the\n// year. A year outside of [-999:9999] when formatted with %E4Y will produce\n// more than four characters, just like %Y.\n//\n// Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z)\n// so that the resulting string uniquely identifies an absolute time.\n//\n// Example:\n//   cctz::time_zone lax;\n//   if (!cctz::load_time_zone(\"America/Los_Angeles\", &lax)) { ... }\n//   auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax);\n//   std::string f = cctz::format(\"%H:%M:%S\", tp, lax);  // \"03:04:05\"\n//   f = cctz::format(\"%H:%M:%E3S\", tp, lax);            // \"03:04:05.000\"\ntemplate <typename D>\ninline std::string format(const std::string& fmt, const time_point<D>& tp,\n                          const time_zone& tz) {\n  const auto p = detail::split_seconds(tp);\n  const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second);\n  return detail::format(fmt, p.first, n, tz);\n}\n\n// Parses an input string according to the provided format string and\n// returns the corresponding time_point. Uses strftime()-like formatting\n// options, with the same extensions as cctz::format(), but with the\n// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez\n// and %E*z also accept the same inputs, which (along with %z) includes\n// 'z' and 'Z' as synonyms for +00:00.  %ET accepts either 'T' or 't'.\n//\n// %Y consumes as many numeric characters as it can, so the matching data\n// should always be terminated with a non-numeric. %E4Y always consumes\n// exactly four characters, including any sign.\n//\n// Unspecified fields are taken from the default date and time of ...\n//\n//   \"1970-01-01 00:00:00.0 +0000\"\n//\n// For example, parsing a string of \"15:45\" (%H:%M) will return a time_point\n// that represents \"1970-01-01 15:45:00.0 +0000\".\n//\n// Note that parse() returns time instants, so it makes most sense to parse\n// fully-specified date/time strings that include a UTC offset (%z, %Ez, or\n// %E*z).\n//\n// Note also that parse() only heeds the fields year, month, day, hour,\n// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a\n// or %A), while parsed for syntactic validity, are ignored in the conversion.\n//\n// Date and time fields that are out-of-range will be treated as errors rather\n// than normalizing them like cctz::civil_second() would do. For example, it\n// is an error to parse the date \"Oct 32, 2013\" because 32 is out of range.\n//\n// A second of \":60\" is normalized to \":00\" of the following minute with\n// fractional seconds discarded. The following table shows how the given\n// seconds and subseconds will be parsed:\n//\n//   \"59.x\" -> 59.x  // exact\n//   \"60.x\" -> 00.0  // normalized\n//   \"00.x\" -> 00.x  // exact\n//\n// Errors are indicated by returning false.\n//\n// Example:\n//   const cctz::time_zone tz = ...\n//   std::chrono::system_clock::time_point tp;\n//   if (cctz::parse(\"%Y-%m-%d\", \"2015-10-09\", tz, &tp)) {\n//     ...\n//   }\ntemplate <typename D>\ninline bool parse(const std::string& fmt, const std::string& input,\n                  const time_zone& tz, time_point<D>* tpp) {\n  time_point<seconds> sec;\n  detail::femtoseconds fs;\n  return detail::parse(fmt, input, tz, &sec, &fs) &&\n         detail::join_seconds(sec, fs, tpp);\n}\n\nnamespace detail {\n\n// Split a time_point<D> into a time_point<seconds> and a D subseconds.\n// Undefined behavior if time_point<seconds> is not of sufficient range.\n// Note that this means it is UB to call cctz::time_zone::lookup(tp) or\n// cctz::format(fmt, tp, tz) with a time_point that is outside the range\n// of a 64-bit std::time_t.\ntemplate <typename D>\nstd::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp) {\n  auto sec = std::chrono::time_point_cast<seconds>(tp);\n  auto sub = tp - sec;\n  if (sub.count() < 0) {\n    sec -= seconds(1);\n    sub += seconds(1);\n  }\n  return {sec, std::chrono::duration_cast<D>(sub)};\n}\n\ninline std::pair<time_point<seconds>, seconds> split_seconds(\n    const time_point<seconds>& tp) {\n  return {tp, seconds::zero()};\n}\n\n// Join a time_point<seconds> and femto subseconds into a time_point<D>.\n// Floors to the resolution of time_point<D>. Returns false if time_point<D>\n// is not of sufficient range.\ntemplate <typename Rep, std::intmax_t Denom>\nbool join_seconds(\n    const time_point<seconds>& sec, const femtoseconds& fs,\n    time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp) {\n  using D = std::chrono::duration<Rep, std::ratio<1, Denom>>;\n  // TODO(#199): Return false if result unrepresentable as a time_point<D>.\n  *tpp = std::chrono::time_point_cast<D>(sec);\n  *tpp += std::chrono::duration_cast<D>(fs);\n  return true;\n}\n\ntemplate <typename Rep, std::intmax_t Num>\nbool join_seconds(\n    const time_point<seconds>& sec, const femtoseconds&,\n    time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp) {\n  using D = std::chrono::duration<Rep, std::ratio<Num, 1>>;\n  auto count = sec.time_since_epoch().count();\n  if (count >= 0 || count % Num == 0) {\n    count /= Num;\n  } else {\n    count /= Num;\n    count -= 1;\n  }\n  if (count > (std::numeric_limits<Rep>::max)()) return false;\n  if (count < (std::numeric_limits<Rep>::min)()) return false;\n  *tpp = time_point<D>() + D{static_cast<Rep>(count)};\n  return true;\n}\n\ntemplate <typename Rep>\nbool join_seconds(\n    const time_point<seconds>& sec, const femtoseconds&,\n    time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp) {\n  using D = std::chrono::duration<Rep, std::ratio<1, 1>>;\n  auto count = sec.time_since_epoch().count();\n  if (count > (std::numeric_limits<Rep>::max)()) return false;\n  if (count < (std::numeric_limits<Rep>::min)()) return false;\n  *tpp = time_point<D>() + D{static_cast<Rep>(count)};\n  return true;\n}\n\ninline bool join_seconds(const time_point<seconds>& sec, const femtoseconds&,\n                         time_point<seconds>* tpp) {\n  *tpp = sec;\n  return true;\n}\n\n}  // namespace detail\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/include/cctz/zone_info_source.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_\n#define ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_\n\n#include <cstddef>\n#include <functional>\n#include <memory>\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// A stdio-like interface for providing zoneinfo data for a particular zone.\nclass ZoneInfoSource {\n public:\n  virtual ~ZoneInfoSource();\n\n  virtual std::size_t Read(void* ptr, std::size_t size) = 0;  // like fread()\n  virtual int Skip(std::size_t offset) = 0;                   // like fseek()\n\n  // Until the zoneinfo data supports versioning information, we provide\n  // a way for a ZoneInfoSource to indicate it out-of-band.  The default\n  // implementation returns an empty string.\n  virtual std::string Version() const;\n};\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz_extension {\n\n// A function-pointer type for a factory that returns a ZoneInfoSource\n// given the name of a time zone and a fallback factory.  Returns null\n// when the data for the named zone cannot be found.\nusing ZoneInfoSourceFactory =\n    std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> (*)(\n        const std::string&,\n        const std::function<std::unique_ptr<\n            absl::time_internal::cctz::ZoneInfoSource>(const std::string&)>&);\n\n// The user can control the mapping of zone names to zoneinfo data by\n// providing a definition for cctz_extension::zone_info_source_factory.\n// For example, given functions my_factory() and my_other_factory() that\n// can return a ZoneInfoSource for a named zone, we could inject them into\n// cctz::load_time_zone() with:\n//\n//   namespace cctz_extension {\n//   namespace {\n//   std::unique_ptr<cctz::ZoneInfoSource> CustomFactory(\n//       const std::string& name,\n//       const std::function<std::unique_ptr<cctz::ZoneInfoSource>(\n//           const std::string& name)>& fallback_factory) {\n//     if (auto zip = my_factory(name)) return zip;\n//     if (auto zip = fallback_factory(name)) return zip;\n//     if (auto zip = my_other_factory(name)) return zip;\n//     return nullptr;\n//   }\n//   }  // namespace\n//   ZoneInfoSourceFactory zone_info_source_factory = CustomFactory;\n//   }  // namespace cctz_extension\n//\n// This might be used, say, to use zoneinfo data embedded in the program,\n// or read from a (possibly compressed) file archive, or both.\n//\n// cctz_extension::zone_info_source_factory() will be called:\n//   (1) from the same thread as the cctz::load_time_zone() call,\n//   (2) only once for any zone name, and\n//   (3) serially (i.e., no concurrent execution).\n//\n// The fallback factory obtains zoneinfo data by reading files in ${TZDIR},\n// and it is used automatically when no zone_info_source_factory definition\n// is linked into the program.\nextern ZoneInfoSourceFactory zone_info_source_factory;\n\n}  // namespace cctz_extension\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/cctz_benchmark.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include <algorithm>\n#include <cassert>\n#include <chrono>\n#include <ctime>\n#include <random>\n#include <string>\n#include <vector>\n\n#include \"benchmark/benchmark.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n#include \"absl/time/internal/cctz/src/test_time_zone_names.h\"\n#include \"absl/time/internal/cctz/src/time_zone_impl.h\"\n\nnamespace {\n\nnamespace cctz = absl::time_internal::cctz;\n\nvoid BM_Difference_Days(benchmark::State& state) {\n  const cctz::civil_day c(2014, 8, 22);\n  const cctz::civil_day epoch(1970, 1, 1);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(c - epoch);\n  }\n}\nBENCHMARK(BM_Difference_Days);\n\nvoid BM_Step_Days(benchmark::State& state) {\n  const cctz::civil_day kStart(2014, 8, 22);\n  cctz::civil_day c = kStart;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(++c);\n  }\n}\nBENCHMARK(BM_Step_Days);\n\nvoid BM_GetWeekday(benchmark::State& state) {\n  const cctz::civil_day c(2014, 8, 22);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::get_weekday(c));\n  }\n}\nBENCHMARK(BM_GetWeekday);\n\nvoid BM_NextWeekday(benchmark::State& state) {\n  const cctz::civil_day kStart(2014, 8, 22);\n  const cctz::civil_day kDays[7] = {\n      kStart + 0, kStart + 1, kStart + 2, kStart + 3,\n      kStart + 4, kStart + 5, kStart + 6,\n  };\n  const cctz::weekday kWeekdays[7] = {\n      cctz::weekday::monday,   cctz::weekday::tuesday, cctz::weekday::wednesday,\n      cctz::weekday::thursday, cctz::weekday::friday,  cctz::weekday::saturday,\n      cctz::weekday::sunday,\n  };\n  while (state.KeepRunningBatch(7 * 7)) {\n    for (const auto from : kDays) {\n      for (const auto to : kWeekdays) {\n        benchmark::DoNotOptimize(cctz::next_weekday(from, to));\n      }\n    }\n  }\n}\nBENCHMARK(BM_NextWeekday);\n\nvoid BM_PrevWeekday(benchmark::State& state) {\n  const cctz::civil_day kStart(2014, 8, 22);\n  const cctz::civil_day kDays[7] = {\n      kStart + 0, kStart + 1, kStart + 2, kStart + 3,\n      kStart + 4, kStart + 5, kStart + 6,\n  };\n  const cctz::weekday kWeekdays[7] = {\n      cctz::weekday::monday,   cctz::weekday::tuesday, cctz::weekday::wednesday,\n      cctz::weekday::thursday, cctz::weekday::friday,  cctz::weekday::saturday,\n      cctz::weekday::sunday,\n  };\n  while (state.KeepRunningBatch(7 * 7)) {\n    for (const auto from : kDays) {\n      for (const auto to : kWeekdays) {\n        benchmark::DoNotOptimize(cctz::prev_weekday(from, to));\n      }\n    }\n  }\n}\nBENCHMARK(BM_PrevWeekday);\n\nconst char RFC3339_full[] = \"%Y-%m-%d%ET%H:%M:%E*S%Ez\";\nconst char RFC3339_sec[] = \"%Y-%m-%d%ET%H:%M:%S%Ez\";\n\nconst char RFC1123_full[] = \"%a, %d %b %Y %H:%M:%S %z\";\nconst char RFC1123_no_wday[] = \"%d %b %Y %H:%M:%S %z\";\n\nstd::vector<std::string> AllTimeZoneNames() {\n  std::vector<std::string> names;\n  for (const char* const* namep = cctz::kTimeZoneNames; *namep != nullptr;\n       ++namep) {\n    names.push_back(std::string(\"file:\") + *namep);\n  }\n  assert(!names.empty());\n\n  std::mt19937 urbg(42);  // a UniformRandomBitGenerator with fixed seed\n  std::shuffle(names.begin(), names.end(), urbg);\n  return names;\n}\n\ncctz::time_zone TestTimeZone() {\n  cctz::time_zone tz;\n  cctz::load_time_zone(\"America/Los_Angeles\", &tz);\n  return tz;\n}\n\nvoid BM_Zone_LoadUTCTimeZoneFirst(benchmark::State& state) {\n  cctz::time_zone tz;\n  cctz::load_time_zone(\"UTC\", &tz);  // in case we're first\n  cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::load_time_zone(\"UTC\", &tz));\n  }\n}\nBENCHMARK(BM_Zone_LoadUTCTimeZoneFirst);\n\nvoid BM_Zone_LoadUTCTimeZoneLast(benchmark::State& state) {\n  cctz::time_zone tz;\n  for (const auto& name : AllTimeZoneNames()) {\n    cctz::load_time_zone(name, &tz);  // prime cache\n  }\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::load_time_zone(\"UTC\", &tz));\n  }\n}\nBENCHMARK(BM_Zone_LoadUTCTimeZoneLast);\n\nvoid BM_Zone_LoadTimeZoneFirst(benchmark::State& state) {\n  cctz::time_zone tz = cctz::utc_time_zone();  // in case we're first\n  const std::string name = \"file:America/Los_Angeles\";\n  while (state.KeepRunning()) {\n    state.PauseTiming();\n    cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();\n    state.ResumeTiming();\n    benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz));\n  }\n}\nBENCHMARK(BM_Zone_LoadTimeZoneFirst);\n\nvoid BM_Zone_LoadTimeZoneCached(benchmark::State& state) {\n  cctz::time_zone tz = cctz::utc_time_zone();  // in case we're first\n  cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();\n  const std::string name = \"file:America/Los_Angeles\";\n  cctz::load_time_zone(name, &tz);  // prime cache\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz));\n  }\n}\nBENCHMARK(BM_Zone_LoadTimeZoneCached);\n\nvoid BM_Zone_LoadLocalTimeZoneCached(benchmark::State& state) {\n  cctz::utc_time_zone();  // in case we're first\n  cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();\n  cctz::local_time_zone();  // prime cache\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::local_time_zone());\n  }\n}\nBENCHMARK(BM_Zone_LoadLocalTimeZoneCached);\n\nvoid BM_Zone_LoadAllTimeZonesFirst(benchmark::State& state) {\n  cctz::time_zone tz;\n  const std::vector<std::string> names = AllTimeZoneNames();\n  for (auto index = names.size(); state.KeepRunning(); ++index) {\n    if (index == names.size()) {\n      index = 0;\n    }\n    if (index == 0) {\n      state.PauseTiming();\n      cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();\n      state.ResumeTiming();\n    }\n    benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz));\n  }\n}\nBENCHMARK(BM_Zone_LoadAllTimeZonesFirst);\n\nvoid BM_Zone_LoadAllTimeZonesCached(benchmark::State& state) {\n  cctz::time_zone tz;\n  const std::vector<std::string> names = AllTimeZoneNames();\n  for (const auto& name : names) {\n    cctz::load_time_zone(name, &tz);  // prime cache\n  }\n  for (auto index = names.size(); state.KeepRunning(); ++index) {\n    if (index == names.size()) {\n      index = 0;\n    }\n    benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz));\n  }\n}\nBENCHMARK(BM_Zone_LoadAllTimeZonesCached);\n\nvoid BM_Zone_TimeZoneEqualityImplicit(benchmark::State& state) {\n  cctz::time_zone tz;  // implicit UTC\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(tz == tz);\n  }\n}\nBENCHMARK(BM_Zone_TimeZoneEqualityImplicit);\n\nvoid BM_Zone_TimeZoneEqualityExplicit(benchmark::State& state) {\n  cctz::time_zone tz = cctz::utc_time_zone();  // explicit UTC\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(tz == tz);\n  }\n}\nBENCHMARK(BM_Zone_TimeZoneEqualityExplicit);\n\nvoid BM_Zone_UTCTimeZone(benchmark::State& state) {\n  cctz::time_zone tz;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::utc_time_zone());\n  }\n}\nBENCHMARK(BM_Zone_UTCTimeZone);\n\n// In each \"ToCivil\" benchmark we switch between two instants separated\n// by at least one transition in order to defeat any internal caching of\n// previous results (e.g., see local_time_hint_).\n//\n// The \"UTC\" variants use UTC instead of the Google/local time zone.\n\nvoid BM_Time_ToCivil_CCTZ(benchmark::State& state) {\n  const cctz::time_zone tz = TestTimeZone();\n  std::chrono::system_clock::time_point tp =\n      std::chrono::system_clock::from_time_t(1384569027);\n  std::chrono::system_clock::time_point tp2 =\n      std::chrono::system_clock::from_time_t(1418962578);\n  while (state.KeepRunning()) {\n    std::swap(tp, tp2);\n    tp += std::chrono::seconds(1);\n    benchmark::DoNotOptimize(cctz::convert(tp, tz));\n  }\n}\nBENCHMARK(BM_Time_ToCivil_CCTZ);\n\nvoid BM_Time_ToCivil_Libc(benchmark::State& state) {\n  // No timezone support, so just use localtime.\n  time_t t = 1384569027;\n  time_t t2 = 1418962578;\n  struct tm tm;\n  while (state.KeepRunning()) {\n    std::swap(t, t2);\n    t += 1;\n#if defined(_WIN32) || defined(_WIN64)\n    benchmark::DoNotOptimize(localtime_s(&tm, &t));\n#else\n    benchmark::DoNotOptimize(localtime_r(&t, &tm));\n#endif\n  }\n}\nBENCHMARK(BM_Time_ToCivil_Libc);\n\nvoid BM_Time_ToCivilUTC_CCTZ(benchmark::State& state) {\n  const cctz::time_zone tz = cctz::utc_time_zone();\n  std::chrono::system_clock::time_point tp =\n      std::chrono::system_clock::from_time_t(1384569027);\n  while (state.KeepRunning()) {\n    tp += std::chrono::seconds(1);\n    benchmark::DoNotOptimize(cctz::convert(tp, tz));\n  }\n}\nBENCHMARK(BM_Time_ToCivilUTC_CCTZ);\n\nvoid BM_Time_ToCivilUTC_Libc(benchmark::State& state) {\n  time_t t = 1384569027;\n  struct tm tm;\n  while (state.KeepRunning()) {\n    t += 1;\n#if defined(_WIN32) || defined(_WIN64)\n    benchmark::DoNotOptimize(gmtime_s(&tm, &t));\n#else\n    benchmark::DoNotOptimize(gmtime_r(&t, &tm));\n#endif\n  }\n}\nBENCHMARK(BM_Time_ToCivilUTC_Libc);\n\n// In each \"FromCivil\" benchmark we switch between two YMDhms values\n// separated by at least one transition in order to defeat any internal\n// caching of previous results (e.g., see time_local_hint_).\n//\n// The \"UTC\" variants use UTC instead of the Google/local time zone.\n// The \"Day0\" variants require normalization of the day of month.\n\nvoid BM_Time_FromCivil_CCTZ(benchmark::State& state) {\n  const cctz::time_zone tz = TestTimeZone();\n  int i = 0;\n  while (state.KeepRunning()) {\n    if ((i++ & 1) == 0) {\n      benchmark::DoNotOptimize(\n          cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz));\n    } else {\n      benchmark::DoNotOptimize(\n          cctz::convert(cctz::civil_second(2013, 11, 15, 18, 30, 27), tz));\n    }\n  }\n}\nBENCHMARK(BM_Time_FromCivil_CCTZ);\n\nvoid BM_Time_FromCivil_Libc(benchmark::State& state) {\n  // No timezone support, so just use localtime.\n  int i = 0;\n  while (state.KeepRunning()) {\n    struct tm tm;\n    if ((i++ & 1) == 0) {\n      tm.tm_year = 2014 - 1900;\n      tm.tm_mon = 12 - 1;\n      tm.tm_mday = 18;\n      tm.tm_hour = 20;\n      tm.tm_min = 16;\n      tm.tm_sec = 18;\n    } else {\n      tm.tm_year = 2013 - 1900;\n      tm.tm_mon = 11 - 1;\n      tm.tm_mday = 15;\n      tm.tm_hour = 18;\n      tm.tm_min = 30;\n      tm.tm_sec = 27;\n    }\n    tm.tm_isdst = -1;\n    benchmark::DoNotOptimize(mktime(&tm));\n  }\n}\nBENCHMARK(BM_Time_FromCivil_Libc);\n\nvoid BM_Time_FromCivilUTC_CCTZ(benchmark::State& state) {\n  const cctz::time_zone tz = cctz::utc_time_zone();\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz));\n  }\n}\nBENCHMARK(BM_Time_FromCivilUTC_CCTZ);\n\n// There is no BM_Time_FromCivilUTC_Libc.\n\nvoid BM_Time_FromCivilDay0_CCTZ(benchmark::State& state) {\n  const cctz::time_zone tz = TestTimeZone();\n  int i = 0;\n  while (state.KeepRunning()) {\n    if ((i++ & 1) == 0) {\n      benchmark::DoNotOptimize(\n          cctz::convert(cctz::civil_second(2014, 12, 0, 20, 16, 18), tz));\n    } else {\n      benchmark::DoNotOptimize(\n          cctz::convert(cctz::civil_second(2013, 11, 0, 18, 30, 27), tz));\n    }\n  }\n}\nBENCHMARK(BM_Time_FromCivilDay0_CCTZ);\n\nvoid BM_Time_FromCivilDay0_Libc(benchmark::State& state) {\n  // No timezone support, so just use localtime.\n  int i = 0;\n  while (state.KeepRunning()) {\n    struct tm tm;\n    if ((i++ & 1) == 0) {\n      tm.tm_year = 2014 - 1900;\n      tm.tm_mon = 12 - 1;\n      tm.tm_mday = 0;\n      tm.tm_hour = 20;\n      tm.tm_min = 16;\n      tm.tm_sec = 18;\n    } else {\n      tm.tm_year = 2013 - 1900;\n      tm.tm_mon = 11 - 1;\n      tm.tm_mday = 0;\n      tm.tm_hour = 18;\n      tm.tm_min = 30;\n      tm.tm_sec = 27;\n    }\n    tm.tm_isdst = -1;\n    benchmark::DoNotOptimize(mktime(&tm));\n  }\n}\nBENCHMARK(BM_Time_FromCivilDay0_Libc);\n\nconst char* const kFormats[] = {\n    RFC1123_full,           // 0\n    RFC1123_no_wday,        // 1\n    RFC3339_full,           // 2\n    RFC3339_sec,            // 3\n    \"%Y-%m-%d%ET%H:%M:%S\",  // 4\n    \"%Y-%m-%d\",             // 5\n    \"%F%ET%T\",              // 6\n};\nconst int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);\n\nvoid BM_Format_FormatTime(benchmark::State& state) {\n  const std::string fmt = kFormats[state.range(0)];\n  state.SetLabel(fmt);\n  const cctz::time_zone tz = TestTimeZone();\n  const std::chrono::system_clock::time_point tp =\n      cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) +\n      std::chrono::microseconds(1);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::format(fmt, tp, tz));\n  }\n}\nBENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1);\n\nvoid BM_Format_ParseTime(benchmark::State& state) {\n  const std::string fmt = kFormats[state.range(0)];\n  state.SetLabel(fmt);\n  const cctz::time_zone tz = TestTimeZone();\n  std::chrono::system_clock::time_point tp =\n      cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) +\n      std::chrono::microseconds(1);\n  const std::string when = cctz::format(fmt, tp, tz);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(cctz::parse(fmt, when, tz, &tp));\n  }\n}\nBENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1);\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/internal/cctz/src/civil_time_detail.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/include/cctz/civil_time_detail.h\"\n\n#include <iomanip>\n#include <ostream>\n#include <sstream>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\nnamespace detail {\n\n// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss,\n// while omitting fields inferior to the type's alignment. For example,\n// civil_day is formatted only as YYYY-MM-DD.\nstd::ostream& operator<<(std::ostream& os, const civil_year& y) {\n  std::stringstream ss;\n  ss << y.year();  // No padding.\n  return os << ss.str();\n}\nstd::ostream& operator<<(std::ostream& os, const civil_month& m) {\n  std::stringstream ss;\n  ss << civil_year(m) << '-';\n  ss << std::setfill('0') << std::setw(2) << m.month();\n  return os << ss.str();\n}\nstd::ostream& operator<<(std::ostream& os, const civil_day& d) {\n  std::stringstream ss;\n  ss << civil_month(d) << '-';\n  ss << std::setfill('0') << std::setw(2) << d.day();\n  return os << ss.str();\n}\nstd::ostream& operator<<(std::ostream& os, const civil_hour& h) {\n  std::stringstream ss;\n  ss << civil_day(h) << 'T';\n  ss << std::setfill('0') << std::setw(2) << h.hour();\n  return os << ss.str();\n}\nstd::ostream& operator<<(std::ostream& os, const civil_minute& m) {\n  std::stringstream ss;\n  ss << civil_hour(m) << ':';\n  ss << std::setfill('0') << std::setw(2) << m.minute();\n  return os << ss.str();\n}\nstd::ostream& operator<<(std::ostream& os, const civil_second& s) {\n  std::stringstream ss;\n  ss << civil_minute(s) << ':';\n  ss << std::setfill('0') << std::setw(2) << s.second();\n  return os << ss.str();\n}\n\n////////////////////////////////////////////////////////////////////////\n\nstd::ostream& operator<<(std::ostream& os, weekday wd) {\n  switch (wd) {\n    case weekday::monday:\n      return os << \"Monday\";\n    case weekday::tuesday:\n      return os << \"Tuesday\";\n    case weekday::wednesday:\n      return os << \"Wednesday\";\n    case weekday::thursday:\n      return os << \"Thursday\";\n    case weekday::friday:\n      return os << \"Friday\";\n    case weekday::saturday:\n      return os << \"Saturday\";\n    case weekday::sunday:\n      return os << \"Sunday\";\n  }\n  return os;  // Should never get here, but -Wreturn-type may warn without this.\n}\n\n}  // namespace detail\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/civil_time_test.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n\n#include <iomanip>\n#include <limits>\n#include <sstream>\n#include <string>\n#include <type_traits>\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\ntemplate <typename T>\nstd::string Format(const T& t) {\n  std::stringstream ss;\n  ss << t;\n  return ss.str();\n}\n\n}  // namespace\n\n#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)\n// Construction constexpr tests\n\nTEST(CivilTime, Normal) {\n  constexpr civil_second css(2016, 1, 28, 17, 14, 12);\n  static_assert(css.second() == 12, \"Normal.second\");\n  constexpr civil_minute cmm(2016, 1, 28, 17, 14);\n  static_assert(cmm.minute() == 14, \"Normal.minute\");\n  constexpr civil_hour chh(2016, 1, 28, 17);\n  static_assert(chh.hour() == 17, \"Normal.hour\");\n  constexpr civil_day cd(2016, 1, 28);\n  static_assert(cd.day() == 28, \"Normal.day\");\n  constexpr civil_month cm(2016, 1);\n  static_assert(cm.month() == 1, \"Normal.month\");\n  constexpr civil_year cy(2016);\n  static_assert(cy.year() == 2016, \"Normal.year\");\n}\n\nTEST(CivilTime, Conversion) {\n  constexpr civil_year cy(2016);\n  static_assert(cy.year() == 2016, \"Conversion.year\");\n  constexpr civil_month cm(cy);\n  static_assert(cm.month() == 1, \"Conversion.month\");\n  constexpr civil_day cd(cm);\n  static_assert(cd.day() == 1, \"Conversion.day\");\n  constexpr civil_hour chh(cd);\n  static_assert(chh.hour() == 0, \"Conversion.hour\");\n  constexpr civil_minute cmm(chh);\n  static_assert(cmm.minute() == 0, \"Conversion.minute\");\n  constexpr civil_second css(cmm);\n  static_assert(css.second() == 0, \"Conversion.second\");\n}\n\n// Normalization constexpr tests\n\nTEST(CivilTime, Normalized) {\n  constexpr civil_second cs(2016, 1, 28, 17, 14, 12);\n  static_assert(cs.year() == 2016, \"Normalized.year\");\n  static_assert(cs.month() == 1, \"Normalized.month\");\n  static_assert(cs.day() == 28, \"Normalized.day\");\n  static_assert(cs.hour() == 17, \"Normalized.hour\");\n  static_assert(cs.minute() == 14, \"Normalized.minute\");\n  static_assert(cs.second() == 12, \"Normalized.second\");\n}\n\nTEST(CivilTime, SecondOverflow) {\n  constexpr civil_second cs(2016, 1, 28, 17, 14, 121);\n  static_assert(cs.year() == 2016, \"SecondOverflow.year\");\n  static_assert(cs.month() == 1, \"SecondOverflow.month\");\n  static_assert(cs.day() == 28, \"SecondOverflow.day\");\n  static_assert(cs.hour() == 17, \"SecondOverflow.hour\");\n  static_assert(cs.minute() == 16, \"SecondOverflow.minute\");\n  static_assert(cs.second() == 1, \"SecondOverflow.second\");\n}\n\nTEST(CivilTime, SecondUnderflow) {\n  constexpr civil_second cs(2016, 1, 28, 17, 14, -121);\n  static_assert(cs.year() == 2016, \"SecondUnderflow.year\");\n  static_assert(cs.month() == 1, \"SecondUnderflow.month\");\n  static_assert(cs.day() == 28, \"SecondUnderflow.day\");\n  static_assert(cs.hour() == 17, \"SecondUnderflow.hour\");\n  static_assert(cs.minute() == 11, \"SecondUnderflow.minute\");\n  static_assert(cs.second() == 59, \"SecondUnderflow.second\");\n}\n\nTEST(CivilTime, MinuteOverflow) {\n  constexpr civil_second cs(2016, 1, 28, 17, 121, 12);\n  static_assert(cs.year() == 2016, \"MinuteOverflow.year\");\n  static_assert(cs.month() == 1, \"MinuteOverflow.month\");\n  static_assert(cs.day() == 28, \"MinuteOverflow.day\");\n  static_assert(cs.hour() == 19, \"MinuteOverflow.hour\");\n  static_assert(cs.minute() == 1, \"MinuteOverflow.minute\");\n  static_assert(cs.second() == 12, \"MinuteOverflow.second\");\n}\n\nTEST(CivilTime, MinuteUnderflow) {\n  constexpr civil_second cs(2016, 1, 28, 17, -121, 12);\n  static_assert(cs.year() == 2016, \"MinuteUnderflow.year\");\n  static_assert(cs.month() == 1, \"MinuteUnderflow.month\");\n  static_assert(cs.day() == 28, \"MinuteUnderflow.day\");\n  static_assert(cs.hour() == 14, \"MinuteUnderflow.hour\");\n  static_assert(cs.minute() == 59, \"MinuteUnderflow.minute\");\n  static_assert(cs.second() == 12, \"MinuteUnderflow.second\");\n}\n\nTEST(CivilTime, HourOverflow) {\n  constexpr civil_second cs(2016, 1, 28, 49, 14, 12);\n  static_assert(cs.year() == 2016, \"HourOverflow.year\");\n  static_assert(cs.month() == 1, \"HourOverflow.month\");\n  static_assert(cs.day() == 30, \"HourOverflow.day\");\n  static_assert(cs.hour() == 1, \"HourOverflow.hour\");\n  static_assert(cs.minute() == 14, \"HourOverflow.minute\");\n  static_assert(cs.second() == 12, \"HourOverflow.second\");\n}\n\nTEST(CivilTime, HourUnderflow) {\n  constexpr civil_second cs(2016, 1, 28, -49, 14, 12);\n  static_assert(cs.year() == 2016, \"HourUnderflow.year\");\n  static_assert(cs.month() == 1, \"HourUnderflow.month\");\n  static_assert(cs.day() == 25, \"HourUnderflow.day\");\n  static_assert(cs.hour() == 23, \"HourUnderflow.hour\");\n  static_assert(cs.minute() == 14, \"HourUnderflow.minute\");\n  static_assert(cs.second() == 12, \"HourUnderflow.second\");\n}\n\nTEST(CivilTime, MonthOverflow) {\n  constexpr civil_second cs(2016, 25, 28, 17, 14, 12);\n  static_assert(cs.year() == 2018, \"MonthOverflow.year\");\n  static_assert(cs.month() == 1, \"MonthOverflow.month\");\n  static_assert(cs.day() == 28, \"MonthOverflow.day\");\n  static_assert(cs.hour() == 17, \"MonthOverflow.hour\");\n  static_assert(cs.minute() == 14, \"MonthOverflow.minute\");\n  static_assert(cs.second() == 12, \"MonthOverflow.second\");\n}\n\nTEST(CivilTime, MonthUnderflow) {\n  constexpr civil_second cs(2016, -25, 28, 17, 14, 12);\n  static_assert(cs.year() == 2013, \"MonthUnderflow.year\");\n  static_assert(cs.month() == 11, \"MonthUnderflow.month\");\n  static_assert(cs.day() == 28, \"MonthUnderflow.day\");\n  static_assert(cs.hour() == 17, \"MonthUnderflow.hour\");\n  static_assert(cs.minute() == 14, \"MonthUnderflow.minute\");\n  static_assert(cs.second() == 12, \"MonthUnderflow.second\");\n}\n\nTEST(CivilTime, C4Overflow) {\n  constexpr civil_second cs(2016, 1, 292195, 17, 14, 12);\n  static_assert(cs.year() == 2816, \"C4Overflow.year\");\n  static_assert(cs.month() == 1, \"C4Overflow.month\");\n  static_assert(cs.day() == 1, \"C4Overflow.day\");\n  static_assert(cs.hour() == 17, \"C4Overflow.hour\");\n  static_assert(cs.minute() == 14, \"C4Overflow.minute\");\n  static_assert(cs.second() == 12, \"C4Overflow.second\");\n}\n\nTEST(CivilTime, C4Underflow) {\n  constexpr civil_second cs(2016, 1, -292195, 17, 14, 12);\n  static_assert(cs.year() == 1215, \"C4Underflow.year\");\n  static_assert(cs.month() == 12, \"C4Underflow.month\");\n  static_assert(cs.day() == 30, \"C4Underflow.day\");\n  static_assert(cs.hour() == 17, \"C4Underflow.hour\");\n  static_assert(cs.minute() == 14, \"C4Underflow.minute\");\n  static_assert(cs.second() == 12, \"C4Underflow.second\");\n}\n\nTEST(CivilTime, MixedNormalization) {\n  constexpr civil_second cs(2016, -42, 122, 99, -147, 4949);\n  static_assert(cs.year() == 2012, \"MixedNormalization.year\");\n  static_assert(cs.month() == 10, \"MixedNormalization.month\");\n  static_assert(cs.day() == 4, \"MixedNormalization.day\");\n  static_assert(cs.hour() == 1, \"MixedNormalization.hour\");\n  static_assert(cs.minute() == 55, \"MixedNormalization.minute\");\n  static_assert(cs.second() == 29, \"MixedNormalization.second\");\n}\n\n// Relational constexpr tests\n\nTEST(CivilTime, Less) {\n  constexpr civil_second cs1(2016, 1, 28, 17, 14, 12);\n  constexpr civil_second cs2(2016, 1, 28, 17, 14, 13);\n  constexpr bool less = cs1 < cs2;\n  static_assert(less, \"Less\");\n}\n\n// Arithmetic constexpr tests\n\nTEST(CivilTime, Addition) {\n  constexpr civil_second cs1(2016, 1, 28, 17, 14, 12);\n  constexpr civil_second cs2 = cs1 + 50;\n  static_assert(cs2.year() == 2016, \"Addition.year\");\n  static_assert(cs2.month() == 1, \"Addition.month\");\n  static_assert(cs2.day() == 28, \"Addition.day\");\n  static_assert(cs2.hour() == 17, \"Addition.hour\");\n  static_assert(cs2.minute() == 15, \"Addition.minute\");\n  static_assert(cs2.second() == 2, \"Addition.second\");\n}\n\nTEST(CivilTime, Subtraction) {\n  constexpr civil_second cs1(2016, 1, 28, 17, 14, 12);\n  constexpr civil_second cs2 = cs1 - 50;\n  static_assert(cs2.year() == 2016, \"Subtraction.year\");\n  static_assert(cs2.month() == 1, \"Subtraction.month\");\n  static_assert(cs2.day() == 28, \"Subtraction.day\");\n  static_assert(cs2.hour() == 17, \"Subtraction.hour\");\n  static_assert(cs2.minute() == 13, \"Subtraction.minute\");\n  static_assert(cs2.second() == 22, \"Subtraction.second\");\n}\n\nTEST(CivilTime, Difference) {\n  constexpr civil_day cd1(2016, 1, 28);\n  constexpr civil_day cd2(2015, 1, 28);\n  constexpr int diff = cd1 - cd2;\n  static_assert(diff == 365, \"Difference\");\n}\n\n// NOTE: Run this with --copt=-ftrapv to detect overflow problems.\nTEST(CivilTime, ConstructionWithHugeYear) {\n  constexpr civil_hour h(-9223372036854775807, 1, 1, -1);\n  static_assert(h.year() == -9223372036854775807 - 1,\n                \"ConstructionWithHugeYear\");\n  static_assert(h.month() == 12, \"ConstructionWithHugeYear\");\n  static_assert(h.day() == 31, \"ConstructionWithHugeYear\");\n  static_assert(h.hour() == 23, \"ConstructionWithHugeYear\");\n}\n\n// NOTE: Run this with --copt=-ftrapv to detect overflow problems.\nTEST(CivilTime, DifferenceWithHugeYear) {\n  {\n    constexpr civil_day d1(9223372036854775807, 1, 1);\n    constexpr civil_day d2(9223372036854775807, 12, 31);\n    static_assert(d2 - d1 == 364, \"DifferenceWithHugeYear\");\n  }\n  {\n    constexpr civil_day d1(-9223372036854775807 - 1, 1, 1);\n    constexpr civil_day d2(-9223372036854775807 - 1, 12, 31);\n    static_assert(d2 - d1 == 365, \"DifferenceWithHugeYear\");\n  }\n  {\n    // Check the limits of the return value at the end of the year range.\n    constexpr civil_day d1(9223372036854775807, 1, 1);\n    constexpr civil_day d2(9198119301927009252, 6, 6);\n    static_assert(d1 - d2 == 9223372036854775807, \"DifferenceWithHugeYear\");\n    static_assert((d2 - 1) - d1 == -9223372036854775807 - 1,\n                  \"DifferenceWithHugeYear\");\n  }\n  {\n    // Check the limits of the return value at the start of the year range.\n    constexpr civil_day d1(-9223372036854775807 - 1, 1, 1);\n    constexpr civil_day d2(-9198119301927009254, 7, 28);\n    static_assert(d2 - d1 == 9223372036854775807, \"DifferenceWithHugeYear\");\n    static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1,\n                  \"DifferenceWithHugeYear\");\n  }\n  {\n    // Check the limits of the return value from either side of year 0.\n    constexpr civil_day d1(-12626367463883278, 9, 3);\n    constexpr civil_day d2(12626367463883277, 3, 28);\n    static_assert(d2 - d1 == 9223372036854775807, \"DifferenceWithHugeYear\");\n    static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1,\n                  \"DifferenceWithHugeYear\");\n  }\n}\n\n// NOTE: Run this with --copt=-ftrapv to detect overflow problems.\nTEST(CivilTime, DifferenceNoIntermediateOverflow) {\n  {\n    // The difference up to the minute field would be below the minimum\n    // diff_t, but the 52 extra seconds brings us back to the minimum.\n    constexpr civil_second s1(-292277022657, 1, 27, 8, 29 - 1, 52);\n    constexpr civil_second s2(1970, 1, 1, 0, 0 - 1, 0);\n    static_assert(s1 - s2 == -9223372036854775807 - 1,\n                  \"DifferenceNoIntermediateOverflow\");\n  }\n  {\n    // The difference up to the minute field would be above the maximum\n    // diff_t, but the -53 extra seconds brings us back to the maximum.\n    constexpr civil_second s1(292277026596, 12, 4, 15, 30, 7 - 7);\n    constexpr civil_second s2(1970, 1, 1, 0, 0, 0 - 7);\n    static_assert(s1 - s2 == 9223372036854775807,\n                  \"DifferenceNoIntermediateOverflow\");\n  }\n}\n\n// Helper constexpr tests\n\nTEST(CivilTime, WeekDay) {\n  constexpr civil_day cd(2016, 1, 28);\n  constexpr weekday wd = get_weekday(cd);\n  static_assert(wd == weekday::thursday, \"Weekday\");\n}\n\nTEST(CivilTime, NextWeekDay) {\n  constexpr civil_day cd(2016, 1, 28);\n  constexpr civil_day next = next_weekday(cd, weekday::thursday);\n  static_assert(next.year() == 2016, \"NextWeekDay.year\");\n  static_assert(next.month() == 2, \"NextWeekDay.month\");\n  static_assert(next.day() == 4, \"NextWeekDay.day\");\n}\n\nTEST(CivilTime, PrevWeekDay) {\n  constexpr civil_day cd(2016, 1, 28);\n  constexpr civil_day prev = prev_weekday(cd, weekday::thursday);\n  static_assert(prev.year() == 2016, \"PrevWeekDay.year\");\n  static_assert(prev.month() == 1, \"PrevWeekDay.month\");\n  static_assert(prev.day() == 21, \"PrevWeekDay.day\");\n}\n\nTEST(CivilTime, YearDay) {\n  constexpr civil_day cd(2016, 1, 28);\n  constexpr int yd = get_yearday(cd);\n  static_assert(yd == 28, \"YearDay\");\n}\n#endif  // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)\n\n// The remaining tests do not use constexpr.\n\nTEST(CivilTime, DefaultConstruction) {\n  civil_second ss;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", Format(ss));\n\n  civil_minute mm;\n  EXPECT_EQ(\"1970-01-01T00:00\", Format(mm));\n\n  civil_hour hh;\n  EXPECT_EQ(\"1970-01-01T00\", Format(hh));\n\n  civil_day d;\n  EXPECT_EQ(\"1970-01-01\", Format(d));\n\n  civil_month m;\n  EXPECT_EQ(\"1970-01\", Format(m));\n\n  civil_year y;\n  EXPECT_EQ(\"1970\", Format(y));\n}\n\nTEST(CivilTime, StructMember) {\n  struct S {\n    civil_day day;\n  };\n  S s = {};\n  EXPECT_EQ(civil_day{}, s.day);\n}\n\nTEST(CivilTime, FieldsConstruction) {\n  EXPECT_EQ(\"2015-01-02T03:04:05\", Format(civil_second(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02T03:04:00\", Format(civil_second(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02T03:00:00\", Format(civil_second(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02T00:00:00\", Format(civil_second(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01T00:00:00\", Format(civil_second(2015, 1)));\n  EXPECT_EQ(\"2015-01-01T00:00:00\", Format(civil_second(2015)));\n\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(civil_minute(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(civil_minute(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02T03:00\", Format(civil_minute(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02T00:00\", Format(civil_minute(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01T00:00\", Format(civil_minute(2015, 1)));\n  EXPECT_EQ(\"2015-01-01T00:00\", Format(civil_minute(2015)));\n\n  EXPECT_EQ(\"2015-01-02T03\", Format(civil_hour(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02T03\", Format(civil_hour(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02T03\", Format(civil_hour(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02T00\", Format(civil_hour(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01T00\", Format(civil_hour(2015, 1)));\n  EXPECT_EQ(\"2015-01-01T00\", Format(civil_hour(2015)));\n\n  EXPECT_EQ(\"2015-01-02\", Format(civil_day(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01-02\", Format(civil_day(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01-02\", Format(civil_day(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01-02\", Format(civil_day(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01-01\", Format(civil_day(2015, 1)));\n  EXPECT_EQ(\"2015-01-01\", Format(civil_day(2015)));\n\n  EXPECT_EQ(\"2015-01\", Format(civil_month(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015-01\", Format(civil_month(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015-01\", Format(civil_month(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015-01\", Format(civil_month(2015, 1, 2)));\n  EXPECT_EQ(\"2015-01\", Format(civil_month(2015, 1)));\n  EXPECT_EQ(\"2015-01\", Format(civil_month(2015)));\n\n  EXPECT_EQ(\"2015\", Format(civil_year(2015, 1, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2015\", Format(civil_year(2015, 1, 2, 3, 4)));\n  EXPECT_EQ(\"2015\", Format(civil_year(2015, 1, 2, 3)));\n  EXPECT_EQ(\"2015\", Format(civil_year(2015, 1, 2)));\n  EXPECT_EQ(\"2015\", Format(civil_year(2015, 1)));\n  EXPECT_EQ(\"2015\", Format(civil_year(2015)));\n}\n\nTEST(CivilTime, FieldsConstructionLimits) {\n  const int kIntMax = std::numeric_limits<int>::max();\n  EXPECT_EQ(\"2038-01-19T03:14:07\",\n            Format(civil_second(1970, 1, 1, 0, 0, kIntMax)));\n  EXPECT_EQ(\"6121-02-11T05:21:07\",\n            Format(civil_second(1970, 1, 1, 0, kIntMax, kIntMax)));\n  EXPECT_EQ(\"251104-11-20T12:21:07\",\n            Format(civil_second(1970, 1, 1, kIntMax, kIntMax, kIntMax)));\n  EXPECT_EQ(\"6130715-05-30T12:21:07\",\n            Format(civil_second(1970, 1, kIntMax, kIntMax, kIntMax, kIntMax)));\n  EXPECT_EQ(\n      \"185087685-11-26T12:21:07\",\n      Format(civil_second(1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax)));\n\n  const int kIntMin = std::numeric_limits<int>::min();\n  EXPECT_EQ(\"1901-12-13T20:45:52\",\n            Format(civil_second(1970, 1, 1, 0, 0, kIntMin)));\n  EXPECT_EQ(\"-2182-11-20T18:37:52\",\n            Format(civil_second(1970, 1, 1, 0, kIntMin, kIntMin)));\n  EXPECT_EQ(\"-247165-02-11T10:37:52\",\n            Format(civil_second(1970, 1, 1, kIntMin, kIntMin, kIntMin)));\n  EXPECT_EQ(\"-6126776-08-01T10:37:52\",\n            Format(civil_second(1970, 1, kIntMin, kIntMin, kIntMin, kIntMin)));\n  EXPECT_EQ(\n      \"-185083747-10-31T10:37:52\",\n      Format(civil_second(1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin)));\n}\n\nTEST(CivilTime, ImplicitCrossAlignment) {\n  civil_year year(2015);\n  civil_month month = year;\n  civil_day day = month;\n  civil_hour hour = day;\n  civil_minute minute = hour;\n  civil_second second = minute;\n\n  second = year;\n  EXPECT_EQ(second, year);\n  second = month;\n  EXPECT_EQ(second, month);\n  second = day;\n  EXPECT_EQ(second, day);\n  second = hour;\n  EXPECT_EQ(second, hour);\n  second = minute;\n  EXPECT_EQ(second, minute);\n\n  minute = year;\n  EXPECT_EQ(minute, year);\n  minute = month;\n  EXPECT_EQ(minute, month);\n  minute = day;\n  EXPECT_EQ(minute, day);\n  minute = hour;\n  EXPECT_EQ(minute, hour);\n\n  hour = year;\n  EXPECT_EQ(hour, year);\n  hour = month;\n  EXPECT_EQ(hour, month);\n  hour = day;\n  EXPECT_EQ(hour, day);\n\n  day = year;\n  EXPECT_EQ(day, year);\n  day = month;\n  EXPECT_EQ(day, month);\n\n  month = year;\n  EXPECT_EQ(month, year);\n\n  // Ensures unsafe conversions are not allowed.\n  EXPECT_FALSE((std::is_convertible<civil_second, civil_minute>::value));\n  EXPECT_FALSE((std::is_convertible<civil_second, civil_hour>::value));\n  EXPECT_FALSE((std::is_convertible<civil_second, civil_day>::value));\n  EXPECT_FALSE((std::is_convertible<civil_second, civil_month>::value));\n  EXPECT_FALSE((std::is_convertible<civil_second, civil_year>::value));\n\n  EXPECT_FALSE((std::is_convertible<civil_minute, civil_hour>::value));\n  EXPECT_FALSE((std::is_convertible<civil_minute, civil_day>::value));\n  EXPECT_FALSE((std::is_convertible<civil_minute, civil_month>::value));\n  EXPECT_FALSE((std::is_convertible<civil_minute, civil_year>::value));\n\n  EXPECT_FALSE((std::is_convertible<civil_hour, civil_day>::value));\n  EXPECT_FALSE((std::is_convertible<civil_hour, civil_month>::value));\n  EXPECT_FALSE((std::is_convertible<civil_hour, civil_year>::value));\n\n  EXPECT_FALSE((std::is_convertible<civil_day, civil_month>::value));\n  EXPECT_FALSE((std::is_convertible<civil_day, civil_year>::value));\n\n  EXPECT_FALSE((std::is_convertible<civil_month, civil_year>::value));\n}\n\nTEST(CivilTime, ExplicitCrossAlignment) {\n  //\n  // Assign from smaller units -> larger units\n  //\n\n  civil_second second(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(\"2015-01-02T03:04:05\", Format(second));\n\n  civil_minute minute(second);\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(minute));\n\n  civil_hour hour(minute);\n  EXPECT_EQ(\"2015-01-02T03\", Format(hour));\n\n  civil_day day(hour);\n  EXPECT_EQ(\"2015-01-02\", Format(day));\n\n  civil_month month(day);\n  EXPECT_EQ(\"2015-01\", Format(month));\n\n  civil_year year(month);\n  EXPECT_EQ(\"2015\", Format(year));\n\n  //\n  // Now assign from larger units -> smaller units\n  //\n\n  month = civil_month(year);\n  EXPECT_EQ(\"2015-01\", Format(month));\n\n  day = civil_day(month);\n  EXPECT_EQ(\"2015-01-01\", Format(day));\n\n  hour = civil_hour(day);\n  EXPECT_EQ(\"2015-01-01T00\", Format(hour));\n\n  minute = civil_minute(hour);\n  EXPECT_EQ(\"2015-01-01T00:00\", Format(minute));\n\n  second = civil_second(minute);\n  EXPECT_EQ(\"2015-01-01T00:00:00\", Format(second));\n}\n\n// Metafunction to test whether difference is allowed between two types.\ntemplate <typename T1, typename T2>\nstruct HasDifference {\n  template <typename U1, typename U2>\n  static std::false_type test(...);\n  template <typename U1, typename U2>\n  static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>()));\n  static constexpr bool value = decltype(test<T1, T2>(0))::value;\n};\n\nTEST(CivilTime, DisallowCrossAlignedDifference) {\n  // Difference is allowed between types with the same alignment.\n  static_assert(HasDifference<civil_second, civil_second>::value, \"\");\n  static_assert(HasDifference<civil_minute, civil_minute>::value, \"\");\n  static_assert(HasDifference<civil_hour, civil_hour>::value, \"\");\n  static_assert(HasDifference<civil_day, civil_day>::value, \"\");\n  static_assert(HasDifference<civil_month, civil_month>::value, \"\");\n  static_assert(HasDifference<civil_year, civil_year>::value, \"\");\n\n  // Difference is disallowed between types with different alignments.\n  static_assert(!HasDifference<civil_second, civil_minute>::value, \"\");\n  static_assert(!HasDifference<civil_second, civil_hour>::value, \"\");\n  static_assert(!HasDifference<civil_second, civil_day>::value, \"\");\n  static_assert(!HasDifference<civil_second, civil_month>::value, \"\");\n  static_assert(!HasDifference<civil_second, civil_year>::value, \"\");\n\n  static_assert(!HasDifference<civil_minute, civil_hour>::value, \"\");\n  static_assert(!HasDifference<civil_minute, civil_day>::value, \"\");\n  static_assert(!HasDifference<civil_minute, civil_month>::value, \"\");\n  static_assert(!HasDifference<civil_minute, civil_year>::value, \"\");\n\n  static_assert(!HasDifference<civil_hour, civil_day>::value, \"\");\n  static_assert(!HasDifference<civil_hour, civil_month>::value, \"\");\n  static_assert(!HasDifference<civil_hour, civil_year>::value, \"\");\n\n  static_assert(!HasDifference<civil_day, civil_month>::value, \"\");\n  static_assert(!HasDifference<civil_day, civil_year>::value, \"\");\n\n  static_assert(!HasDifference<civil_month, civil_year>::value, \"\");\n}\n\nTEST(CivilTime, ValueSemantics) {\n  const civil_hour a(2015, 1, 2, 3);\n  const civil_hour b = a;\n  const civil_hour c(b);\n  civil_hour d;\n  d = c;\n  EXPECT_EQ(\"2015-01-02T03\", Format(d));\n}\n\nTEST(CivilTime, Relational) {\n  // Tests that the alignment unit is ignored in comparison.\n  const civil_year year(2014);\n  const civil_month month(year);\n  EXPECT_EQ(year, month);\n\n#define TEST_RELATIONAL(OLDER, YOUNGER) \\\n  do {                                  \\\n    EXPECT_FALSE(OLDER < OLDER);        \\\n    EXPECT_FALSE(OLDER > OLDER);        \\\n    EXPECT_TRUE(OLDER >= OLDER);        \\\n    EXPECT_TRUE(OLDER <= OLDER);        \\\n    EXPECT_FALSE(YOUNGER < YOUNGER);    \\\n    EXPECT_FALSE(YOUNGER > YOUNGER);    \\\n    EXPECT_TRUE(YOUNGER >= YOUNGER);    \\\n    EXPECT_TRUE(YOUNGER <= YOUNGER);    \\\n    EXPECT_EQ(OLDER, OLDER);            \\\n    EXPECT_NE(OLDER, YOUNGER);          \\\n    EXPECT_LT(OLDER, YOUNGER);          \\\n    EXPECT_LE(OLDER, YOUNGER);          \\\n    EXPECT_GT(YOUNGER, OLDER);          \\\n    EXPECT_GE(YOUNGER, OLDER);          \\\n  } while (0)\n\n  // Alignment is ignored in comparison (verified above), so kSecond is used\n  // to test comparison in all field positions.\n  TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0),\n                  civil_second(2015, 1, 1, 0, 0, 0));\n  TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0),\n                  civil_second(2014, 2, 1, 0, 0, 0));\n  TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0),\n                  civil_second(2014, 1, 2, 0, 0, 0));\n  TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0),\n                  civil_second(2014, 1, 1, 1, 0, 0));\n  TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 0, 0),\n                  civil_second(2014, 1, 1, 1, 1, 0));\n  TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0),\n                  civil_second(2014, 1, 1, 1, 1, 1));\n\n  // Tests the relational operators of two different civil-time types.\n  TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1));\n  TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2));\n\n#undef TEST_RELATIONAL\n}\n\nTEST(CivilTime, Arithmetic) {\n  civil_second second(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(\"2015-01-02T03:04:06\", Format(second += 1));\n  EXPECT_EQ(\"2015-01-02T03:04:07\", Format(second + 1));\n  EXPECT_EQ(\"2015-01-02T03:04:08\", Format(2 + second));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", Format(second - 1));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", Format(second -= 1));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", Format(second++));\n  EXPECT_EQ(\"2015-01-02T03:04:07\", Format(++second));\n  EXPECT_EQ(\"2015-01-02T03:04:07\", Format(second--));\n  EXPECT_EQ(\"2015-01-02T03:04:05\", Format(--second));\n\n  civil_minute minute(2015, 1, 2, 3, 4);\n  EXPECT_EQ(\"2015-01-02T03:05\", Format(minute += 1));\n  EXPECT_EQ(\"2015-01-02T03:06\", Format(minute + 1));\n  EXPECT_EQ(\"2015-01-02T03:07\", Format(2 + minute));\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(minute - 1));\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(minute -= 1));\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(minute++));\n  EXPECT_EQ(\"2015-01-02T03:06\", Format(++minute));\n  EXPECT_EQ(\"2015-01-02T03:06\", Format(minute--));\n  EXPECT_EQ(\"2015-01-02T03:04\", Format(--minute));\n\n  civil_hour hour(2015, 1, 2, 3);\n  EXPECT_EQ(\"2015-01-02T04\", Format(hour += 1));\n  EXPECT_EQ(\"2015-01-02T05\", Format(hour + 1));\n  EXPECT_EQ(\"2015-01-02T06\", Format(2 + hour));\n  EXPECT_EQ(\"2015-01-02T03\", Format(hour - 1));\n  EXPECT_EQ(\"2015-01-02T03\", Format(hour -= 1));\n  EXPECT_EQ(\"2015-01-02T03\", Format(hour++));\n  EXPECT_EQ(\"2015-01-02T05\", Format(++hour));\n  EXPECT_EQ(\"2015-01-02T05\", Format(hour--));\n  EXPECT_EQ(\"2015-01-02T03\", Format(--hour));\n\n  civil_day day(2015, 1, 2);\n  EXPECT_EQ(\"2015-01-03\", Format(day += 1));\n  EXPECT_EQ(\"2015-01-04\", Format(day + 1));\n  EXPECT_EQ(\"2015-01-05\", Format(2 + day));\n  EXPECT_EQ(\"2015-01-02\", Format(day - 1));\n  EXPECT_EQ(\"2015-01-02\", Format(day -= 1));\n  EXPECT_EQ(\"2015-01-02\", Format(day++));\n  EXPECT_EQ(\"2015-01-04\", Format(++day));\n  EXPECT_EQ(\"2015-01-04\", Format(day--));\n  EXPECT_EQ(\"2015-01-02\", Format(--day));\n\n  civil_month month(2015, 1);\n  EXPECT_EQ(\"2015-02\", Format(month += 1));\n  EXPECT_EQ(\"2015-03\", Format(month + 1));\n  EXPECT_EQ(\"2015-04\", Format(2 + month));\n  EXPECT_EQ(\"2015-01\", Format(month - 1));\n  EXPECT_EQ(\"2015-01\", Format(month -= 1));\n  EXPECT_EQ(\"2015-01\", Format(month++));\n  EXPECT_EQ(\"2015-03\", Format(++month));\n  EXPECT_EQ(\"2015-03\", Format(month--));\n  EXPECT_EQ(\"2015-01\", Format(--month));\n\n  civil_year year(2015);\n  EXPECT_EQ(\"2016\", Format(year += 1));\n  EXPECT_EQ(\"2017\", Format(year + 1));\n  EXPECT_EQ(\"2018\", Format(2 + year));\n  EXPECT_EQ(\"2015\", Format(year - 1));\n  EXPECT_EQ(\"2015\", Format(year -= 1));\n  EXPECT_EQ(\"2015\", Format(year++));\n  EXPECT_EQ(\"2017\", Format(++year));\n  EXPECT_EQ(\"2017\", Format(year--));\n  EXPECT_EQ(\"2015\", Format(--year));\n}\n\nTEST(CivilTime, ArithmeticLimits) {\n  const int kIntMax = std::numeric_limits<int>::max();\n  const int kIntMin = std::numeric_limits<int>::min();\n\n  civil_second second(1970, 1, 1, 0, 0, 0);\n  second += kIntMax;\n  EXPECT_EQ(\"2038-01-19T03:14:07\", Format(second));\n  second -= kIntMax;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", Format(second));\n  second += kIntMin;\n  EXPECT_EQ(\"1901-12-13T20:45:52\", Format(second));\n  second -= kIntMin;\n  EXPECT_EQ(\"1970-01-01T00:00:00\", Format(second));\n\n  civil_minute minute(1970, 1, 1, 0, 0);\n  minute += kIntMax;\n  EXPECT_EQ(\"6053-01-23T02:07\", Format(minute));\n  minute -= kIntMax;\n  EXPECT_EQ(\"1970-01-01T00:00\", Format(minute));\n  minute += kIntMin;\n  EXPECT_EQ(\"-2114-12-08T21:52\", Format(minute));\n  minute -= kIntMin;\n  EXPECT_EQ(\"1970-01-01T00:00\", Format(minute));\n\n  civil_hour hour(1970, 1, 1, 0);\n  hour += kIntMax;\n  EXPECT_EQ(\"246953-10-09T07\", Format(hour));\n  hour -= kIntMax;\n  EXPECT_EQ(\"1970-01-01T00\", Format(hour));\n  hour += kIntMin;\n  EXPECT_EQ(\"-243014-03-24T16\", Format(hour));\n  hour -= kIntMin;\n  EXPECT_EQ(\"1970-01-01T00\", Format(hour));\n\n  civil_day day(1970, 1, 1);\n  day += kIntMax;\n  EXPECT_EQ(\"5881580-07-11\", Format(day));\n  day -= kIntMax;\n  EXPECT_EQ(\"1970-01-01\", Format(day));\n  day += kIntMin;\n  EXPECT_EQ(\"-5877641-06-23\", Format(day));\n  day -= kIntMin;\n  EXPECT_EQ(\"1970-01-01\", Format(day));\n\n  civil_month month(1970, 1);\n  month += kIntMax;\n  EXPECT_EQ(\"178958940-08\", Format(month));\n  month -= kIntMax;\n  EXPECT_EQ(\"1970-01\", Format(month));\n  month += kIntMin;\n  EXPECT_EQ(\"-178955001-05\", Format(month));\n  month -= kIntMin;\n  EXPECT_EQ(\"1970-01\", Format(month));\n\n  civil_year year(0);\n  year += kIntMax;\n  EXPECT_EQ(\"2147483647\", Format(year));\n  year -= kIntMax;\n  EXPECT_EQ(\"0\", Format(year));\n  year += kIntMin;\n  EXPECT_EQ(\"-2147483648\", Format(year));\n  year -= kIntMin;\n  EXPECT_EQ(\"0\", Format(year));\n}\n\nTEST(CivilTime, ArithmeticDifference) {\n  civil_second second(2015, 1, 2, 3, 4, 5);\n  EXPECT_EQ(0, second - second);\n  EXPECT_EQ(10, (second + 10) - second);\n  EXPECT_EQ(-10, (second - 10) - second);\n\n  civil_minute minute(2015, 1, 2, 3, 4);\n  EXPECT_EQ(0, minute - minute);\n  EXPECT_EQ(10, (minute + 10) - minute);\n  EXPECT_EQ(-10, (minute - 10) - minute);\n\n  civil_hour hour(2015, 1, 2, 3);\n  EXPECT_EQ(0, hour - hour);\n  EXPECT_EQ(10, (hour + 10) - hour);\n  EXPECT_EQ(-10, (hour - 10) - hour);\n\n  civil_day day(2015, 1, 2);\n  EXPECT_EQ(0, day - day);\n  EXPECT_EQ(10, (day + 10) - day);\n  EXPECT_EQ(-10, (day - 10) - day);\n\n  civil_month month(2015, 1);\n  EXPECT_EQ(0, month - month);\n  EXPECT_EQ(10, (month + 10) - month);\n  EXPECT_EQ(-10, (month - 10) - month);\n\n  civil_year year(2015);\n  EXPECT_EQ(0, year - year);\n  EXPECT_EQ(10, (year + 10) - year);\n  EXPECT_EQ(-10, (year - 10) - year);\n}\n\nTEST(CivilTime, DifferenceLimits) {\n  const int kIntMax = std::numeric_limits<int>::max();\n  const int kIntMin = std::numeric_limits<int>::min();\n\n  // Check day arithmetic at the end of the year range.\n  const civil_day max_day(kIntMax, 12, 31);\n  EXPECT_EQ(1, max_day - (max_day - 1));\n  EXPECT_EQ(-1, (max_day - 1) - max_day);\n\n  // Check day arithmetic at the end of the year range.\n  const civil_day min_day(kIntMin, 1, 1);\n  EXPECT_EQ(1, (min_day + 1) - min_day);\n  EXPECT_EQ(-1, min_day - (min_day + 1));\n\n  // Check the limits of the return value.\n  const civil_day d1(1970, 1, 1);\n  const civil_day d2(5881580, 7, 11);\n  EXPECT_EQ(kIntMax, d2 - d1);\n  EXPECT_EQ(kIntMin, d1 - (d2 + 1));\n}\n\nTEST(CivilTime, Properties) {\n  civil_second ss(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, ss.year());\n  EXPECT_EQ(2, ss.month());\n  EXPECT_EQ(3, ss.day());\n  EXPECT_EQ(4, ss.hour());\n  EXPECT_EQ(5, ss.minute());\n  EXPECT_EQ(6, ss.second());\n  EXPECT_EQ(weekday::tuesday, get_weekday(ss));\n  EXPECT_EQ(34, get_yearday(ss));\n\n  civil_minute mm(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, mm.year());\n  EXPECT_EQ(2, mm.month());\n  EXPECT_EQ(3, mm.day());\n  EXPECT_EQ(4, mm.hour());\n  EXPECT_EQ(5, mm.minute());\n  EXPECT_EQ(0, mm.second());\n  EXPECT_EQ(weekday::tuesday, get_weekday(mm));\n  EXPECT_EQ(34, get_yearday(mm));\n\n  civil_hour hh(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, hh.year());\n  EXPECT_EQ(2, hh.month());\n  EXPECT_EQ(3, hh.day());\n  EXPECT_EQ(4, hh.hour());\n  EXPECT_EQ(0, hh.minute());\n  EXPECT_EQ(0, hh.second());\n  EXPECT_EQ(weekday::tuesday, get_weekday(hh));\n  EXPECT_EQ(34, get_yearday(hh));\n\n  civil_day d(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, d.year());\n  EXPECT_EQ(2, d.month());\n  EXPECT_EQ(3, d.day());\n  EXPECT_EQ(0, d.hour());\n  EXPECT_EQ(0, d.minute());\n  EXPECT_EQ(0, d.second());\n  EXPECT_EQ(weekday::tuesday, get_weekday(d));\n  EXPECT_EQ(34, get_yearday(d));\n\n  civil_month m(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, m.year());\n  EXPECT_EQ(2, m.month());\n  EXPECT_EQ(1, m.day());\n  EXPECT_EQ(0, m.hour());\n  EXPECT_EQ(0, m.minute());\n  EXPECT_EQ(0, m.second());\n  EXPECT_EQ(weekday::sunday, get_weekday(m));\n  EXPECT_EQ(32, get_yearday(m));\n\n  civil_year y(2015, 2, 3, 4, 5, 6);\n  EXPECT_EQ(2015, y.year());\n  EXPECT_EQ(1, y.month());\n  EXPECT_EQ(1, y.day());\n  EXPECT_EQ(0, y.hour());\n  EXPECT_EQ(0, y.minute());\n  EXPECT_EQ(0, y.second());\n  EXPECT_EQ(weekday::thursday, get_weekday(y));\n  EXPECT_EQ(1, get_yearday(y));\n}\n\nTEST(CivilTime, OutputStream) {\n  // Tests formatting of civil_year, which does not pad.\n  EXPECT_EQ(\"2016\", Format(civil_year(2016)));\n  EXPECT_EQ(\"123\", Format(civil_year(123)));\n  EXPECT_EQ(\"0\", Format(civil_year(0)));\n  EXPECT_EQ(\"-1\", Format(civil_year(-1)));\n\n  // Tests formatting of sub-year types, which pad to 2 digits\n  EXPECT_EQ(\"2016-02\", Format(civil_month(2016, 2)));\n  EXPECT_EQ(\"2016-02-03\", Format(civil_day(2016, 2, 3)));\n  EXPECT_EQ(\"2016-02-03T04\", Format(civil_hour(2016, 2, 3, 4)));\n  EXPECT_EQ(\"2016-02-03T04:05\", Format(civil_minute(2016, 2, 3, 4, 5)));\n  EXPECT_EQ(\"2016-02-03T04:05:06\", Format(civil_second(2016, 2, 3, 4, 5, 6)));\n\n  // Tests formatting of weekday.\n  EXPECT_EQ(\"Monday\", Format(weekday::monday));\n  EXPECT_EQ(\"Tuesday\", Format(weekday::tuesday));\n  EXPECT_EQ(\"Wednesday\", Format(weekday::wednesday));\n  EXPECT_EQ(\"Thursday\", Format(weekday::thursday));\n  EXPECT_EQ(\"Friday\", Format(weekday::friday));\n  EXPECT_EQ(\"Saturday\", Format(weekday::saturday));\n  EXPECT_EQ(\"Sunday\", Format(weekday::sunday));\n}\n\nTEST(CivilTime, OutputStreamLeftFillWidth) {\n  civil_second cs(2016, 2, 3, 4, 5, 6);\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << civil_year(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016.................X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << civil_month(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02..............X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << civil_day(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03...........X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << civil_hour(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03T04........X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << civil_minute(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03T04:05.....X..\", ss.str());\n  }\n  {\n    std::stringstream ss;\n    ss << std::left << std::setfill('.');\n    ss << std::setw(3) << 'X';\n    ss << std::setw(21) << civil_second(cs);\n    ss << std::setw(3) << 'X';\n    EXPECT_EQ(\"X..2016-02-03T04:05:06..X..\", ss.str());\n  }\n}\n\nTEST(CivilTime, NextPrevWeekday) {\n  // Jan 1, 1970 was a Thursday.\n  const civil_day thursday(1970, 1, 1);\n  EXPECT_EQ(weekday::thursday, get_weekday(thursday));\n\n  // Thursday -> Thursday\n  civil_day d = next_weekday(thursday, weekday::thursday);\n  EXPECT_EQ(7, d - thursday) << Format(d);\n  EXPECT_EQ(d - 14, prev_weekday(thursday, weekday::thursday));\n\n  // Thursday -> Friday\n  d = next_weekday(thursday, weekday::friday);\n  EXPECT_EQ(1, d - thursday) << Format(d);\n  EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::friday));\n\n  // Thursday -> Saturday\n  d = next_weekday(thursday, weekday::saturday);\n  EXPECT_EQ(2, d - thursday) << Format(d);\n  EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::saturday));\n\n  // Thursday -> Sunday\n  d = next_weekday(thursday, weekday::sunday);\n  EXPECT_EQ(3, d - thursday) << Format(d);\n  EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::sunday));\n\n  // Thursday -> Monday\n  d = next_weekday(thursday, weekday::monday);\n  EXPECT_EQ(4, d - thursday) << Format(d);\n  EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::monday));\n\n  // Thursday -> Tuesday\n  d = next_weekday(thursday, weekday::tuesday);\n  EXPECT_EQ(5, d - thursday) << Format(d);\n  EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::tuesday));\n\n  // Thursday -> Wednesday\n  d = next_weekday(thursday, weekday::wednesday);\n  EXPECT_EQ(6, d - thursday) << Format(d);\n  EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::wednesday));\n}\n\nTEST(CivilTime, NormalizeWithHugeYear) {\n  civil_month c(9223372036854775807, 1);\n  EXPECT_EQ(\"9223372036854775807-01\", Format(c));\n  c = c - 1;  // Causes normalization\n  EXPECT_EQ(\"9223372036854775806-12\", Format(c));\n\n  c = civil_month(-9223372036854775807 - 1, 1);\n  EXPECT_EQ(\"-9223372036854775808-01\", Format(c));\n  c = c + 12;  // Causes normalization\n  EXPECT_EQ(\"-9223372036854775807-01\", Format(c));\n}\n\nTEST(CivilTime, LeapYears) {\n  // Test data for leap years.\n  const struct {\n    int year;\n    int days;\n    struct {\n      int month;\n      int day;\n    } leap_day;  // The date of the day after Feb 28.\n  } kLeapYearTable[]{\n      {1900, 365, {3, 1}},  {1999, 365, {3, 1}},\n      {2000, 366, {2, 29}},  // leap year\n      {2001, 365, {3, 1}},  {2002, 365, {3, 1}},\n      {2003, 365, {3, 1}},  {2004, 366, {2, 29}},  // leap year\n      {2005, 365, {3, 1}},  {2006, 365, {3, 1}},\n      {2007, 365, {3, 1}},  {2008, 366, {2, 29}},  // leap year\n      {2009, 365, {3, 1}},  {2100, 365, {3, 1}},\n  };\n\n  for (const auto& e : kLeapYearTable) {\n    // Tests incrementing through the leap day.\n    const civil_day feb28(e.year, 2, 28);\n    const civil_day next_day = feb28 + 1;\n    EXPECT_EQ(e.leap_day.month, next_day.month());\n    EXPECT_EQ(e.leap_day.day, next_day.day());\n\n    // Tests difference in days of leap years.\n    const civil_year year(feb28);\n    const civil_year next_year = year + 1;\n    EXPECT_EQ(e.days, civil_day(next_year) - civil_day(year));\n  }\n}\n\nTEST(CivilTime, FirstThursdayInMonth) {\n  const civil_day nov1(2014, 11, 1);\n  const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday);\n  EXPECT_EQ(\"2014-11-06\", Format(thursday));\n\n  // Bonus: Date of Thanksgiving in the United States\n  // Rule: Fourth Thursday of November\n  const civil_day thanksgiving = thursday + 7 * 3;\n  EXPECT_EQ(\"2014-11-27\", Format(thanksgiving));\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/test_time_zone_names.cc",
    "content": "// Copyright 2025 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/src/test_time_zone_names.h\"\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// A list of known time-zone names.\nconst char* const kTimeZoneNames[] = {\"Africa/Abidjan\",\n                                      \"Africa/Accra\",\n                                      \"Africa/Addis_Ababa\",\n                                      \"Africa/Algiers\",\n                                      \"Africa/Asmara\",\n                                      \"Africa/Bamako\",\n                                      \"Africa/Bangui\",\n                                      \"Africa/Banjul\",\n                                      \"Africa/Bissau\",\n                                      \"Africa/Blantyre\",\n                                      \"Africa/Brazzaville\",\n                                      \"Africa/Bujumbura\",\n                                      \"Africa/Cairo\",\n                                      \"Africa/Casablanca\",\n                                      \"Africa/Ceuta\",\n                                      \"Africa/Conakry\",\n                                      \"Africa/Dakar\",\n                                      \"Africa/Dar_es_Salaam\",\n                                      \"Africa/Djibouti\",\n                                      \"Africa/Douala\",\n                                      \"Africa/El_Aaiun\",\n                                      \"Africa/Freetown\",\n                                      \"Africa/Gaborone\",\n                                      \"Africa/Harare\",\n                                      \"Africa/Johannesburg\",\n                                      \"Africa/Juba\",\n                                      \"Africa/Kampala\",\n                                      \"Africa/Khartoum\",\n                                      \"Africa/Kigali\",\n                                      \"Africa/Kinshasa\",\n                                      \"Africa/Lagos\",\n                                      \"Africa/Libreville\",\n                                      \"Africa/Lome\",\n                                      \"Africa/Luanda\",\n                                      \"Africa/Lubumbashi\",\n                                      \"Africa/Lusaka\",\n                                      \"Africa/Malabo\",\n                                      \"Africa/Maputo\",\n                                      \"Africa/Maseru\",\n                                      \"Africa/Mbabane\",\n                                      \"Africa/Mogadishu\",\n                                      \"Africa/Monrovia\",\n                                      \"Africa/Nairobi\",\n                                      \"Africa/Ndjamena\",\n                                      \"Africa/Niamey\",\n                                      \"Africa/Nouakchott\",\n                                      \"Africa/Ouagadougou\",\n                                      \"Africa/Porto-Novo\",\n                                      \"Africa/Sao_Tome\",\n                                      \"Africa/Timbuktu\",\n                                      \"Africa/Tripoli\",\n                                      \"Africa/Tunis\",\n                                      \"Africa/Windhoek\",\n                                      \"America/Adak\",\n                                      \"America/Anchorage\",\n                                      \"America/Anguilla\",\n                                      \"America/Antigua\",\n                                      \"America/Araguaina\",\n                                      \"America/Argentina/Buenos_Aires\",\n                                      \"America/Argentina/Catamarca\",\n                                      \"America/Argentina/Cordoba\",\n                                      \"America/Argentina/Jujuy\",\n                                      \"America/Argentina/La_Rioja\",\n                                      \"America/Argentina/Mendoza\",\n                                      \"America/Argentina/Rio_Gallegos\",\n                                      \"America/Argentina/Salta\",\n                                      \"America/Argentina/San_Juan\",\n                                      \"America/Argentina/San_Luis\",\n                                      \"America/Argentina/Tucuman\",\n                                      \"America/Argentina/Ushuaia\",\n                                      \"America/Aruba\",\n                                      \"America/Asuncion\",\n                                      \"America/Atikokan\",\n                                      \"America/Atka\",\n                                      \"America/Bahia\",\n                                      \"America/Bahia_Banderas\",\n                                      \"America/Barbados\",\n                                      \"America/Belem\",\n                                      \"America/Belize\",\n                                      \"America/Blanc-Sablon\",\n                                      \"America/Boa_Vista\",\n                                      \"America/Bogota\",\n                                      \"America/Boise\",\n                                      \"America/Cambridge_Bay\",\n                                      \"America/Campo_Grande\",\n                                      \"America/Cancun\",\n                                      \"America/Caracas\",\n                                      \"America/Cayenne\",\n                                      \"America/Cayman\",\n                                      \"America/Chicago\",\n                                      \"America/Chihuahua\",\n                                      \"America/Ciudad_Juarez\",\n                                      \"America/Coral_Harbour\",\n                                      \"America/Costa_Rica\",\n                                      \"America/Coyhaique\",\n                                      \"America/Creston\",\n                                      \"America/Cuiaba\",\n                                      \"America/Curacao\",\n                                      \"America/Danmarkshavn\",\n                                      \"America/Dawson\",\n                                      \"America/Dawson_Creek\",\n                                      \"America/Denver\",\n                                      \"America/Detroit\",\n                                      \"America/Dominica\",\n                                      \"America/Edmonton\",\n                                      \"America/Eirunepe\",\n                                      \"America/El_Salvador\",\n                                      \"America/Ensenada\",\n                                      \"America/Fort_Nelson\",\n                                      \"America/Fortaleza\",\n                                      \"America/Glace_Bay\",\n                                      \"America/Goose_Bay\",\n                                      \"America/Grand_Turk\",\n                                      \"America/Grenada\",\n                                      \"America/Guadeloupe\",\n                                      \"America/Guatemala\",\n                                      \"America/Guayaquil\",\n                                      \"America/Guyana\",\n                                      \"America/Halifax\",\n                                      \"America/Havana\",\n                                      \"America/Hermosillo\",\n                                      \"America/Indiana/Indianapolis\",\n                                      \"America/Indiana/Knox\",\n                                      \"America/Indiana/Marengo\",\n                                      \"America/Indiana/Petersburg\",\n                                      \"America/Indiana/Tell_City\",\n                                      \"America/Indiana/Vevay\",\n                                      \"America/Indiana/Vincennes\",\n                                      \"America/Indiana/Winamac\",\n                                      \"America/Inuvik\",\n                                      \"America/Iqaluit\",\n                                      \"America/Jamaica\",\n                                      \"America/Juneau\",\n                                      \"America/Kentucky/Louisville\",\n                                      \"America/Kentucky/Monticello\",\n                                      \"America/Kralendijk\",\n                                      \"America/La_Paz\",\n                                      \"America/Lima\",\n                                      \"America/Los_Angeles\",\n                                      \"America/Lower_Princes\",\n                                      \"America/Maceio\",\n                                      \"America/Managua\",\n                                      \"America/Manaus\",\n                                      \"America/Marigot\",\n                                      \"America/Martinique\",\n                                      \"America/Matamoros\",\n                                      \"America/Mazatlan\",\n                                      \"America/Menominee\",\n                                      \"America/Merida\",\n                                      \"America/Metlakatla\",\n                                      \"America/Mexico_City\",\n                                      \"America/Miquelon\",\n                                      \"America/Moncton\",\n                                      \"America/Monterrey\",\n                                      \"America/Montevideo\",\n                                      \"America/Montreal\",\n                                      \"America/Montserrat\",\n                                      \"America/Nassau\",\n                                      \"America/New_York\",\n                                      \"America/Nipigon\",\n                                      \"America/Nome\",\n                                      \"America/Noronha\",\n                                      \"America/North_Dakota/Beulah\",\n                                      \"America/North_Dakota/Center\",\n                                      \"America/North_Dakota/New_Salem\",\n                                      \"America/Nuuk\",\n                                      \"America/Ojinaga\",\n                                      \"America/Panama\",\n                                      \"America/Pangnirtung\",\n                                      \"America/Paramaribo\",\n                                      \"America/Phoenix\",\n                                      \"America/Port-au-Prince\",\n                                      \"America/Port_of_Spain\",\n                                      \"America/Porto_Acre\",\n                                      \"America/Porto_Velho\",\n                                      \"America/Puerto_Rico\",\n                                      \"America/Punta_Arenas\",\n                                      \"America/Rainy_River\",\n                                      \"America/Rankin_Inlet\",\n                                      \"America/Recife\",\n                                      \"America/Regina\",\n                                      \"America/Resolute\",\n                                      \"America/Rio_Branco\",\n                                      \"America/Santa_Isabel\",\n                                      \"America/Santarem\",\n                                      \"America/Santiago\",\n                                      \"America/Santo_Domingo\",\n                                      \"America/Sao_Paulo\",\n                                      \"America/Scoresbysund\",\n                                      \"America/Shiprock\",\n                                      \"America/Sitka\",\n                                      \"America/St_Barthelemy\",\n                                      \"America/St_Johns\",\n                                      \"America/St_Kitts\",\n                                      \"America/St_Lucia\",\n                                      \"America/St_Thomas\",\n                                      \"America/St_Vincent\",\n                                      \"America/Swift_Current\",\n                                      \"America/Tegucigalpa\",\n                                      \"America/Thule\",\n                                      \"America/Thunder_Bay\",\n                                      \"America/Tijuana\",\n                                      \"America/Toronto\",\n                                      \"America/Tortola\",\n                                      \"America/Vancouver\",\n                                      \"America/Virgin\",\n                                      \"America/Whitehorse\",\n                                      \"America/Winnipeg\",\n                                      \"America/Yakutat\",\n                                      \"America/Yellowknife\",\n                                      \"Antarctica/Casey\",\n                                      \"Antarctica/Davis\",\n                                      \"Antarctica/DumontDUrville\",\n                                      \"Antarctica/Macquarie\",\n                                      \"Antarctica/Mawson\",\n                                      \"Antarctica/McMurdo\",\n                                      \"Antarctica/Palmer\",\n                                      \"Antarctica/Rothera\",\n                                      \"Antarctica/Syowa\",\n                                      \"Antarctica/Troll\",\n                                      \"Antarctica/Vostok\",\n                                      \"Arctic/Longyearbyen\",\n                                      \"Asia/Aden\",\n                                      \"Asia/Almaty\",\n                                      \"Asia/Amman\",\n                                      \"Asia/Anadyr\",\n                                      \"Asia/Aqtau\",\n                                      \"Asia/Aqtobe\",\n                                      \"Asia/Ashgabat\",\n                                      \"Asia/Atyrau\",\n                                      \"Asia/Baghdad\",\n                                      \"Asia/Bahrain\",\n                                      \"Asia/Baku\",\n                                      \"Asia/Bangkok\",\n                                      \"Asia/Barnaul\",\n                                      \"Asia/Beirut\",\n                                      \"Asia/Bishkek\",\n                                      \"Asia/Brunei\",\n                                      \"Asia/Chita\",\n                                      \"Asia/Choibalsan\",\n                                      \"Asia/Chongqing\",\n                                      \"Asia/Colombo\",\n                                      \"Asia/Damascus\",\n                                      \"Asia/Dhaka\",\n                                      \"Asia/Dili\",\n                                      \"Asia/Dubai\",\n                                      \"Asia/Dushanbe\",\n                                      \"Asia/Famagusta\",\n                                      \"Asia/Gaza\",\n                                      \"Asia/Harbin\",\n                                      \"Asia/Hebron\",\n                                      \"Asia/Ho_Chi_Minh\",\n                                      \"Asia/Hong_Kong\",\n                                      \"Asia/Hovd\",\n                                      \"Asia/Irkutsk\",\n                                      \"Asia/Istanbul\",\n                                      \"Asia/Jakarta\",\n                                      \"Asia/Jayapura\",\n                                      \"Asia/Jerusalem\",\n                                      \"Asia/Kabul\",\n                                      \"Asia/Kamchatka\",\n                                      \"Asia/Karachi\",\n                                      \"Asia/Kashgar\",\n                                      \"Asia/Kathmandu\",\n                                      \"Asia/Khandyga\",\n                                      \"Asia/Kolkata\",\n                                      \"Asia/Krasnoyarsk\",\n                                      \"Asia/Kuala_Lumpur\",\n                                      \"Asia/Kuching\",\n                                      \"Asia/Kuwait\",\n                                      \"Asia/Macau\",\n                                      \"Asia/Magadan\",\n                                      \"Asia/Makassar\",\n                                      \"Asia/Manila\",\n                                      \"Asia/Muscat\",\n                                      \"Asia/Nicosia\",\n                                      \"Asia/Novokuznetsk\",\n                                      \"Asia/Novosibirsk\",\n                                      \"Asia/Omsk\",\n                                      \"Asia/Oral\",\n                                      \"Asia/Phnom_Penh\",\n                                      \"Asia/Pontianak\",\n                                      \"Asia/Pyongyang\",\n                                      \"Asia/Qatar\",\n                                      \"Asia/Qostanay\",\n                                      \"Asia/Qyzylorda\",\n                                      \"Asia/Riyadh\",\n                                      \"Asia/Sakhalin\",\n                                      \"Asia/Samarkand\",\n                                      \"Asia/Seoul\",\n                                      \"Asia/Shanghai\",\n                                      \"Asia/Singapore\",\n                                      \"Asia/Srednekolymsk\",\n                                      \"Asia/Taipei\",\n                                      \"Asia/Tashkent\",\n                                      \"Asia/Tbilisi\",\n                                      \"Asia/Tehran\",\n                                      \"Asia/Tel_Aviv\",\n                                      \"Asia/Thimphu\",\n                                      \"Asia/Tokyo\",\n                                      \"Asia/Tomsk\",\n                                      \"Asia/Ulaanbaatar\",\n                                      \"Asia/Urumqi\",\n                                      \"Asia/Ust-Nera\",\n                                      \"Asia/Vientiane\",\n                                      \"Asia/Vladivostok\",\n                                      \"Asia/Yakutsk\",\n                                      \"Asia/Yangon\",\n                                      \"Asia/Yekaterinburg\",\n                                      \"Asia/Yerevan\",\n                                      \"Atlantic/Azores\",\n                                      \"Atlantic/Bermuda\",\n                                      \"Atlantic/Canary\",\n                                      \"Atlantic/Cape_Verde\",\n                                      \"Atlantic/Faroe\",\n                                      \"Atlantic/Jan_Mayen\",\n                                      \"Atlantic/Madeira\",\n                                      \"Atlantic/Reykjavik\",\n                                      \"Atlantic/South_Georgia\",\n                                      \"Atlantic/St_Helena\",\n                                      \"Atlantic/Stanley\",\n                                      \"Australia/Adelaide\",\n                                      \"Australia/Brisbane\",\n                                      \"Australia/Broken_Hill\",\n                                      \"Australia/Canberra\",\n                                      \"Australia/Currie\",\n                                      \"Australia/Darwin\",\n                                      \"Australia/Eucla\",\n                                      \"Australia/Hobart\",\n                                      \"Australia/Lindeman\",\n                                      \"Australia/Lord_Howe\",\n                                      \"Australia/Melbourne\",\n                                      \"Australia/Perth\",\n                                      \"Australia/Sydney\",\n                                      \"Australia/Yancowinna\",\n                                      \"Etc/GMT\",\n                                      \"Etc/GMT+0\",\n                                      \"Etc/GMT+1\",\n                                      \"Etc/GMT+10\",\n                                      \"Etc/GMT+11\",\n                                      \"Etc/GMT+12\",\n                                      \"Etc/GMT+2\",\n                                      \"Etc/GMT+3\",\n                                      \"Etc/GMT+4\",\n                                      \"Etc/GMT+5\",\n                                      \"Etc/GMT+6\",\n                                      \"Etc/GMT+7\",\n                                      \"Etc/GMT+8\",\n                                      \"Etc/GMT+9\",\n                                      \"Etc/GMT-0\",\n                                      \"Etc/GMT-1\",\n                                      \"Etc/GMT-10\",\n                                      \"Etc/GMT-11\",\n                                      \"Etc/GMT-12\",\n                                      \"Etc/GMT-13\",\n                                      \"Etc/GMT-14\",\n                                      \"Etc/GMT-2\",\n                                      \"Etc/GMT-3\",\n                                      \"Etc/GMT-4\",\n                                      \"Etc/GMT-5\",\n                                      \"Etc/GMT-6\",\n                                      \"Etc/GMT-7\",\n                                      \"Etc/GMT-8\",\n                                      \"Etc/GMT-9\",\n                                      \"Etc/GMT0\",\n                                      \"Etc/Greenwich\",\n                                      \"Etc/UCT\",\n                                      \"Etc/UTC\",\n                                      \"Etc/Universal\",\n                                      \"Etc/Zulu\",\n                                      \"Europe/Amsterdam\",\n                                      \"Europe/Andorra\",\n                                      \"Europe/Astrakhan\",\n                                      \"Europe/Athens\",\n                                      \"Europe/Belfast\",\n                                      \"Europe/Belgrade\",\n                                      \"Europe/Berlin\",\n                                      \"Europe/Bratislava\",\n                                      \"Europe/Brussels\",\n                                      \"Europe/Bucharest\",\n                                      \"Europe/Budapest\",\n                                      \"Europe/Busingen\",\n                                      \"Europe/Chisinau\",\n                                      \"Europe/Copenhagen\",\n                                      \"Europe/Dublin\",\n                                      \"Europe/Gibraltar\",\n                                      \"Europe/Guernsey\",\n                                      \"Europe/Helsinki\",\n                                      \"Europe/Isle_of_Man\",\n                                      \"Europe/Istanbul\",\n                                      \"Europe/Jersey\",\n                                      \"Europe/Kaliningrad\",\n                                      \"Europe/Kirov\",\n                                      \"Europe/Kyiv\",\n                                      \"Europe/Lisbon\",\n                                      \"Europe/Ljubljana\",\n                                      \"Europe/London\",\n                                      \"Europe/Luxembourg\",\n                                      \"Europe/Madrid\",\n                                      \"Europe/Malta\",\n                                      \"Europe/Mariehamn\",\n                                      \"Europe/Minsk\",\n                                      \"Europe/Monaco\",\n                                      \"Europe/Moscow\",\n                                      \"Europe/Nicosia\",\n                                      \"Europe/Oslo\",\n                                      \"Europe/Paris\",\n                                      \"Europe/Podgorica\",\n                                      \"Europe/Prague\",\n                                      \"Europe/Riga\",\n                                      \"Europe/Rome\",\n                                      \"Europe/Samara\",\n                                      \"Europe/San_Marino\",\n                                      \"Europe/Sarajevo\",\n                                      \"Europe/Saratov\",\n                                      \"Europe/Simferopol\",\n                                      \"Europe/Skopje\",\n                                      \"Europe/Sofia\",\n                                      \"Europe/Stockholm\",\n                                      \"Europe/Tallinn\",\n                                      \"Europe/Tirane\",\n                                      \"Europe/Tiraspol\",\n                                      \"Europe/Ulyanovsk\",\n                                      \"Europe/Vaduz\",\n                                      \"Europe/Vatican\",\n                                      \"Europe/Vienna\",\n                                      \"Europe/Vilnius\",\n                                      \"Europe/Volgograd\",\n                                      \"Europe/Warsaw\",\n                                      \"Europe/Zagreb\",\n                                      \"Europe/Zurich\",\n                                      \"Factory\",\n                                      \"Indian/Antananarivo\",\n                                      \"Indian/Chagos\",\n                                      \"Indian/Christmas\",\n                                      \"Indian/Cocos\",\n                                      \"Indian/Comoro\",\n                                      \"Indian/Kerguelen\",\n                                      \"Indian/Mahe\",\n                                      \"Indian/Maldives\",\n                                      \"Indian/Mauritius\",\n                                      \"Indian/Mayotte\",\n                                      \"Indian/Reunion\",\n                                      \"Pacific/Apia\",\n                                      \"Pacific/Auckland\",\n                                      \"Pacific/Bougainville\",\n                                      \"Pacific/Chatham\",\n                                      \"Pacific/Chuuk\",\n                                      \"Pacific/Easter\",\n                                      \"Pacific/Efate\",\n                                      \"Pacific/Fakaofo\",\n                                      \"Pacific/Fiji\",\n                                      \"Pacific/Funafuti\",\n                                      \"Pacific/Galapagos\",\n                                      \"Pacific/Gambier\",\n                                      \"Pacific/Guadalcanal\",\n                                      \"Pacific/Guam\",\n                                      \"Pacific/Honolulu\",\n                                      \"Pacific/Johnston\",\n                                      \"Pacific/Kanton\",\n                                      \"Pacific/Kiritimati\",\n                                      \"Pacific/Kosrae\",\n                                      \"Pacific/Kwajalein\",\n                                      \"Pacific/Majuro\",\n                                      \"Pacific/Marquesas\",\n                                      \"Pacific/Midway\",\n                                      \"Pacific/Nauru\",\n                                      \"Pacific/Niue\",\n                                      \"Pacific/Norfolk\",\n                                      \"Pacific/Noumea\",\n                                      \"Pacific/Pago_Pago\",\n                                      \"Pacific/Palau\",\n                                      \"Pacific/Pitcairn\",\n                                      \"Pacific/Pohnpei\",\n                                      \"Pacific/Port_Moresby\",\n                                      \"Pacific/Rarotonga\",\n                                      \"Pacific/Saipan\",\n                                      \"Pacific/Samoa\",\n                                      \"Pacific/Tahiti\",\n                                      \"Pacific/Tarawa\",\n                                      \"Pacific/Tongatapu\",\n                                      \"Pacific/Wake\",\n                                      \"Pacific/Wallis\",\n                                      \"Pacific/Yap\",\n                                      \"UTC\",\n                                      nullptr};\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/test_time_zone_names.h",
    "content": "// Copyright 2025 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TEST_TIME_ZONE_NAMES_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TEST_TIME_ZONE_NAMES_H_\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// A list of known time-zone names.\nextern const char* const kTimeZoneNames[];\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TEST_TIME_ZONE_NAMES_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_fixed.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/src/time_zone_fixed.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <chrono>\n#include <cstring>\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\n// The prefix used for the internal names of fixed-offset zones.\nconst char kFixedZonePrefix[] = \"Fixed/UTC\";\n\nconst char kDigits[] = \"0123456789\";\n\nchar* Format02d(char* p, int v) {\n  *p++ = kDigits[(v / 10) % 10];\n  *p++ = kDigits[v % 10];\n  return p;\n}\n\nint Parse02d(const char* p) {\n  if (const char* ap = std::strchr(kDigits, *p)) {\n    int v = static_cast<int>(ap - kDigits);\n    if (const char* bp = std::strchr(kDigits, *++p)) {\n      return (v * 10) + static_cast<int>(bp - kDigits);\n    }\n  }\n  return -1;\n}\n\n}  // namespace\n\nbool FixedOffsetFromName(const std::string& name, seconds* offset) {\n  if (name == \"UTC\" || name == \"UTC0\") {\n    *offset = seconds::zero();\n    return true;\n  }\n\n  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;\n  const char* const ep = kFixedZonePrefix + prefix_len;\n  if (name.size() != prefix_len + 9)  // <prefix>+99:99:99\n    return false;\n  if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false;\n  const char* np = name.data() + prefix_len;\n  if (np[0] != '+' && np[0] != '-') return false;\n  if (np[3] != ':' || np[6] != ':')  // see note below about large offsets\n    return false;\n\n  int hours = Parse02d(np + 1);\n  if (hours == -1) return false;\n  int mins = Parse02d(np + 4);\n  if (mins == -1) return false;\n  int secs = Parse02d(np + 7);\n  if (secs == -1) return false;\n\n  secs += ((hours * 60) + mins) * 60;\n  if (secs > 24 * 60 * 60) return false;  // outside supported offset range\n  *offset = seconds(secs * (np[0] == '-' ? -1 : 1));  // \"-\" means west\n  return true;\n}\n\nstd::string FixedOffsetToName(const seconds& offset) {\n  if (offset == seconds::zero()) return \"UTC\";\n  if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) {\n    // We don't support fixed-offset zones more than 24 hours\n    // away from UTC to avoid complications in rendering such\n    // offsets and to (somewhat) limit the total number of zones.\n    return \"UTC\";\n  }\n  int offset_seconds = static_cast<int>(offset.count());\n  const char sign = (offset_seconds < 0 ? '-' : '+');\n  int offset_minutes = offset_seconds / 60;\n  offset_seconds %= 60;\n  if (sign == '-') {\n    if (offset_seconds > 0) {\n      offset_seconds -= 60;\n      offset_minutes += 1;\n    }\n    offset_seconds = -offset_seconds;\n    offset_minutes = -offset_minutes;\n  }\n  int offset_hours = offset_minutes / 60;\n  offset_minutes %= 60;\n  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;\n  char buf[prefix_len + sizeof(\"-24:00:00\")];\n  char* ep = std::copy_n(kFixedZonePrefix, prefix_len, buf);\n  *ep++ = sign;\n  ep = Format02d(ep, offset_hours);\n  *ep++ = ':';\n  ep = Format02d(ep, offset_minutes);\n  *ep++ = ':';\n  ep = Format02d(ep, offset_seconds);\n  *ep++ = '\\0';\n  assert(ep == buf + sizeof(buf));\n  return buf;\n}\n\nstd::string FixedOffsetToAbbr(const seconds& offset) {\n  std::string abbr = FixedOffsetToName(offset);\n  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;\n  if (abbr.size() == prefix_len + 9) {         // <prefix>+99:99:99\n    abbr.erase(0, prefix_len);                 // +99:99:99\n    abbr.erase(6, 1);                          // +99:9999\n    abbr.erase(3, 1);                          // +999999\n    if (abbr[5] == '0' && abbr[6] == '0') {    // +999900\n      abbr.erase(5, 2);                        // +9999\n      if (abbr[3] == '0' && abbr[4] == '0') {  // +9900\n        abbr.erase(3, 2);                      // +99\n      }\n    }\n  }\n  return abbr;\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_fixed.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// Helper functions for dealing with the names and abbreviations\n// of time zones that are a fixed offset (seconds east) from UTC.\n// FixedOffsetFromName() extracts the offset from a valid fixed-offset\n// name, while FixedOffsetToName() and FixedOffsetToAbbr() generate\n// the canonical zone name and abbreviation respectively for the given\n// offset.\n//\n// A fixed-offset name looks like \"Fixed/UTC<+-><hours>:<mins>:<secs>\".\n// Its abbreviation is of the form \"UTC(<+->H?H(MM(SS)?)?)?\" where the\n// optional pieces are omitted when their values are zero.  (Note that\n// the sign is the opposite of that used in a POSIX TZ specification.)\n//\n// Note: FixedOffsetFromName() fails on syntax errors or when the parsed\n// offset exceeds 24 hours.  FixedOffsetToName() and FixedOffsetToAbbr()\n// both produce \"UTC\" when the argument offset exceeds 24 hours.\nbool FixedOffsetFromName(const std::string& name, seconds* offset);\nstd::string FixedOffsetToName(const seconds& offset);\nstd::string FixedOffsetToAbbr(const seconds& offset);\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_format.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#if !defined(HAS_STRPTIME)\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__VXWORKS__)\n#define HAS_STRPTIME 0\n#else\n#define HAS_STRPTIME 1  // Assume everyone else has strptime().\n#endif\n#endif\n\n#if HAS_STRPTIME\n#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__OpenBSD__)\n#define _XOPEN_SOURCE 500  // Exposes definitions for SUSv2 (UNIX 98).\n#endif\n#endif\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\n// Include time.h directly since, by C++ standards, ctime doesn't have to\n// declare strptime.\n#include <time.h>\n\n#include <cctype>\n#include <chrono>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <ctime>\n#include <limits>\n#include <string>\n#if !HAS_STRPTIME\n#include <iomanip>\n#include <sstream>\n#endif\n\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/src/time_zone_if.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\nnamespace detail {\n\nnamespace {\n\n#if !HAS_STRPTIME\n// Build a strptime() using C++11's std::get_time().\nchar* strptime(const char* s, const char* fmt, std::tm* tm) {\n  std::istringstream input(s);\n  input >> std::get_time(tm, fmt);\n  if (input.fail()) return nullptr;\n  return const_cast<char*>(s) +\n         (input.eof() ? strlen(s) : static_cast<std::size_t>(input.tellg()));\n}\n#endif\n\n// Convert a cctz::weekday to a tm_wday value (0-6, Sunday = 0).\nint ToTmWday(weekday wd) {\n  switch (wd) {\n    case weekday::sunday:\n      return 0;\n    case weekday::monday:\n      return 1;\n    case weekday::tuesday:\n      return 2;\n    case weekday::wednesday:\n      return 3;\n    case weekday::thursday:\n      return 4;\n    case weekday::friday:\n      return 5;\n    case weekday::saturday:\n      return 6;\n  }\n  return 0; /*NOTREACHED*/\n}\n\n// Convert a tm_wday value (0-6, Sunday = 0) to a cctz::weekday.\nweekday FromTmWday(int tm_wday) {\n  switch (tm_wday) {\n    case 0:\n      return weekday::sunday;\n    case 1:\n      return weekday::monday;\n    case 2:\n      return weekday::tuesday;\n    case 3:\n      return weekday::wednesday;\n    case 4:\n      return weekday::thursday;\n    case 5:\n      return weekday::friday;\n    case 6:\n      return weekday::saturday;\n  }\n  return weekday::sunday; /*NOTREACHED*/\n}\n\nstd::tm ToTM(const time_zone::absolute_lookup& al) {\n  std::tm tm{};\n  tm.tm_sec = al.cs.second();\n  tm.tm_min = al.cs.minute();\n  tm.tm_hour = al.cs.hour();\n  tm.tm_mday = al.cs.day();\n  tm.tm_mon = al.cs.month() - 1;\n\n  // Saturate tm.tm_year in cases of over/underflow.\n  if (al.cs.year() < std::numeric_limits<int>::min() + 1900) {\n    tm.tm_year = std::numeric_limits<int>::min();\n  } else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) {\n    tm.tm_year = std::numeric_limits<int>::max();\n  } else {\n    tm.tm_year = static_cast<int>(al.cs.year() - 1900);\n  }\n\n  tm.tm_wday = ToTmWday(get_weekday(al.cs));\n  tm.tm_yday = get_yearday(al.cs) - 1;\n  tm.tm_isdst = al.is_dst ? 1 : 0;\n  return tm;\n}\n\n// Returns the week of the year [0:53] given a civil day and the day on\n// which weeks are defined to start.\nint ToWeek(const civil_day& cd, weekday week_start) {\n  const civil_day d(cd.year() % 400, cd.month(), cd.day());\n  return static_cast<int>((d - prev_weekday(civil_year(d), week_start)) / 7);\n}\n\nconst char kDigits[] = \"0123456789\";\n\n// Formats a 64-bit integer in the given field width.  Note that it is up\n// to the caller of Format64() [and Format02d()/FormatOffset()] to ensure\n// that there is sufficient space before ep to hold the conversion.\nchar* Format64(char* ep, int width, std::int_fast64_t v) {\n  bool neg = false;\n  if (v < 0) {\n    --width;\n    neg = true;\n    if (v == std::numeric_limits<std::int_fast64_t>::min()) {\n      // Avoid negating minimum value.\n      std::int_fast64_t last_digit = -(v % 10);\n      v /= 10;\n      if (last_digit < 0) {\n        ++v;\n        last_digit += 10;\n      }\n      --width;\n      *--ep = kDigits[last_digit];\n    }\n    v = -v;\n  }\n  do {\n    --width;\n    *--ep = kDigits[v % 10];\n  } while (v /= 10);\n  while (--width >= 0) *--ep = '0';  // zero pad\n  if (neg) *--ep = '-';\n  return ep;\n}\n\n// Formats [0 .. 99] as %02d.\nchar* Format02d(char* ep, int v) {\n  *--ep = kDigits[v % 10];\n  *--ep = kDigits[(v / 10) % 10];\n  return ep;\n}\n\n// Formats a UTC offset, like +00:00.\nchar* FormatOffset(char* ep, int offset, const char* mode) {\n  // TODO: Follow the RFC3339 \"Unknown Local Offset Convention\" and\n  // generate a \"negative zero\" when we're formatting a zero offset\n  // as the result of a failed load_time_zone().\n  char sign = '+';\n  if (offset < 0) {\n    offset = -offset;  // bounded by 24h so no overflow\n    sign = '-';\n  }\n  const int seconds = offset % 60;\n  const int minutes = (offset /= 60) % 60;\n  const int hours = offset /= 60;\n  const char sep = mode[0];\n  const bool ext = (sep != '\\0' && mode[1] == '*');\n  const bool ccc = (ext && mode[2] == ':');\n  if (ext && (!ccc || seconds != 0)) {\n    ep = Format02d(ep, seconds);\n    *--ep = sep;\n  } else {\n    // If we're not rendering seconds, sub-minute negative offsets\n    // should get a positive sign (e.g., offset=-10s => \"+00:00\").\n    if (hours == 0 && minutes == 0) sign = '+';\n  }\n  if (!ccc || minutes != 0 || seconds != 0) {\n    ep = Format02d(ep, minutes);\n    if (sep != '\\0') *--ep = sep;\n  }\n  ep = Format02d(ep, hours);\n  *--ep = sign;\n  return ep;\n}\n\n// Formats a std::tm using strftime(3).\nvoid FormatTM(std::string* out, const std::string& fmt, const std::tm& tm) {\n  // We assume that 16 times the length of the format string will\n  // be sufficient to store the result.  The extreme case appears\n  // to be \"%c\" (2 chars), which, in the POSIX locale, produces\n  // \"Thu Jan 1 00:00:00 1970\" (24 chars).\n  auto out_size = out->size();\n  auto buf_size = (16 * fmt.size()) + 1;\n  out->resize(out_size + buf_size);\n  auto len = strftime(&(*out)[out_size], buf_size, fmt.c_str(), &tm);\n  out->resize(out_size + len);\n}\n\n// Used for %E#S/%E#f specifiers and for data values in parse().\ntemplate <typename T>\nconst char* ParseInt(const char* dp, int width, T min, T max, T* vp) {\n  if (dp != nullptr) {\n    const T kmin = std::numeric_limits<T>::min();\n    bool erange = false;\n    bool neg = false;\n    T value = 0;\n    if (*dp == '-') {\n      neg = true;\n      if (width <= 0 || --width != 0) {\n        ++dp;\n      } else {\n        dp = nullptr;  // width was 1\n      }\n    }\n    if (const char* const bp = dp) {\n      while (const char* cp = strchr(kDigits, *dp)) {\n        int d = static_cast<int>(cp - kDigits);\n        if (d >= 10) break;\n        if (value < kmin / 10) {\n          erange = true;\n          break;\n        }\n        value *= 10;\n        if (value < kmin + d) {\n          erange = true;\n          break;\n        }\n        value -= d;\n        dp += 1;\n        if (width > 0 && --width == 0) break;\n      }\n      if (dp != bp && !erange && (neg || value != kmin)) {\n        if (!neg || value != 0) {\n          if (!neg) value = -value;  // make positive\n          if (min <= value && value <= max) {\n            *vp = value;\n          } else {\n            dp = nullptr;\n          }\n        } else {\n          dp = nullptr;\n        }\n      } else {\n        dp = nullptr;\n      }\n    }\n  }\n  return dp;\n}\n\n// The number of base-10 digits that can be represented by a signed 64-bit\n// integer.  That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1).\nconst int kDigits10_64 = 18;\n\n// 10^n for everything that can be represented by a signed 64-bit integer.\nconst std::int_fast64_t kExp10[kDigits10_64 + 1] = {\n    1,\n    10,\n    100,\n    1000,\n    10000,\n    100000,\n    1000000,\n    10000000,\n    100000000,\n    1000000000,\n    10000000000,\n    100000000000,\n    1000000000000,\n    10000000000000,\n    100000000000000,\n    1000000000000000,\n    10000000000000000,\n    100000000000000000,\n    1000000000000000000,\n};\n\n}  // namespace\n\n// Uses strftime(3) to format the given Time.  The following extended format\n// specifiers are also supported:\n//\n//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)\n//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)\n//   - %E#S - Seconds with # digits of fractional precision\n//   - %E*S - Seconds with full fractional precision (a literal '*')\n//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)\n//   - %ET  - The RFC3339 \"date-time\" separator \"T\"\n//\n// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are\n// handled internally for performance reasons.  strftime(3) is slow due to\n// a POSIX requirement to respect changes to ${TZ}.\n//\n// The TZ/GNU %s extension is handled internally because strftime() has\n// to use mktime() to generate it, and that assumes the local time zone.\n//\n// We also handle the %z and %Z specifiers to accommodate platforms that do\n// not support the tm_gmtoff and tm_zone extensions to std::tm.\n//\n// Requires that zero() <= fs < seconds(1).\nstd::string format(const std::string& format, const time_point<seconds>& tp,\n                   const detail::femtoseconds& fs, const time_zone& tz) {\n  std::string result;\n  result.reserve(2 * format.size());  // A guess for the result size.\n  const time_zone::absolute_lookup al = tz.lookup(tp);\n  const std::tm tm = ToTM(al);\n\n  // Scratch buffer for internal conversions.\n  char buf[6 + (kDigits10_64 + 2)];  // enough for longest conversion (%F)\n  char* const ep = buf + sizeof(buf);\n  char* bp;  // works back from ep\n\n  // Maintain three, disjoint subsequences that span format.\n  //   [format.begin() ... pending) : already formatted into result\n  //   [pending ... cur) : formatting pending, but no special cases\n  //   [cur ... format.end()) : unexamined\n  // Initially, everything is in the unexamined part.\n  const char* pending = format.data();\n  const char* cur = pending;\n  const char* const end = pending + format.size();\n\n  while (cur != end) {  // while something is unexamined\n    // Moves cur to the next percent sign.\n    const char* start = cur;\n    while (cur != end && *cur != '%') {\n      if (*cur == '\\0' && pending != start) {\n        FormatTM(&result, std::string(pending, cur), tm);\n        pending = start = cur;\n      }\n      ++cur;\n    }\n\n    // If the new pending text is all ordinary, copy it out.\n    if (cur != start && pending == start) {\n      result.append(pending, cur);\n      pending = start = cur;\n    }\n\n    // Span the sequential percent signs.\n    const char* const percent = cur;\n    while (cur != end && *cur == '%') ++cur;\n\n    // If the new pending text is all percents, copy out one\n    // percent for every matched pair, then skip those pairs.\n    if (cur != start && pending == start) {\n      std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2;\n      result.append(pending, escaped);\n      pending += escaped * 2;\n      // Also copy out a single trailing percent.\n      if (pending != cur && cur == end) {\n        result.push_back(*pending++);\n      }\n    }\n\n    // Loop unless we have an unescaped percent.\n    if (cur == end || (cur - percent) % 2 == 0) continue;\n\n    // Simple specifiers that we handle ourselves.\n    if (*cur == '\\0' || strchr(\"YmdeFUuWwHMSTzZs%\", *cur)) {\n      FormatTM(&result, std::string(pending, cur - 1), tm);\n      switch (*cur) {\n        case '\\0':\n          // Because we allow NULs in the format string, we must give\n          // some meaning to the \"%\\0\" specifier.  We choose the common\n          // (but undefined) strftime() behavior of echoing unknown\n          // specifiers.\n          result.push_back('%');\n          result.push_back('\\0');\n          break;\n        case 'Y':\n          // This avoids the tm.tm_year overflow problem for %Y, however\n          // tm.tm_year will still be used by other specifiers like %D.\n          bp = Format64(ep, 0, al.cs.year());\n          result.append(bp, ep);\n          break;\n        case 'm':\n          bp = Format02d(ep, al.cs.month());\n          result.append(bp, ep);\n          break;\n        case 'd':\n        case 'e':\n          bp = Format02d(ep, al.cs.day());\n          if (*cur == 'e' && *bp == '0') *bp = ' ';  // for Windows\n          result.append(bp, ep);\n          break;\n        case 'F':\n          bp = Format02d(ep, al.cs.day());\n          *--bp = '-';\n          bp = Format02d(bp, al.cs.month());\n          *--bp = '-';\n          bp = Format64(bp, 0, al.cs.year());\n          result.append(bp, ep);\n          break;\n        case 'U':\n          bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday));\n          result.append(bp, ep);\n          break;\n        case 'u':\n          bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7);\n          result.append(bp, ep);\n          break;\n        case 'W':\n          bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday));\n          result.append(bp, ep);\n          break;\n        case 'w':\n          bp = Format64(ep, 0, tm.tm_wday);\n          result.append(bp, ep);\n          break;\n        case 'H':\n          bp = Format02d(ep, al.cs.hour());\n          result.append(bp, ep);\n          break;\n        case 'M':\n          bp = Format02d(ep, al.cs.minute());\n          result.append(bp, ep);\n          break;\n        case 'S':\n          bp = Format02d(ep, al.cs.second());\n          result.append(bp, ep);\n          break;\n        case 'T':\n          bp = Format02d(ep, al.cs.second());\n          *--bp = ':';\n          bp = Format02d(bp, al.cs.minute());\n          *--bp = ':';\n          bp = Format02d(bp, al.cs.hour());\n          result.append(bp, ep);\n          break;\n        case 'z':\n          bp = FormatOffset(ep, al.offset, \"\");\n          result.append(bp, ep);\n          break;\n        case 'Z':\n          result.append(al.abbr);\n          break;\n        case 's':\n          bp = Format64(ep, 0, ToUnixSeconds(tp));\n          result.append(bp, ep);\n          break;\n        case '%':\n          result.push_back('%');\n          break;\n      }\n      pending = ++cur;\n      continue;\n    }\n\n    // More complex specifiers that we handle ourselves.\n    if (*cur == ':' && cur + 1 != end) {\n      if (*(cur + 1) == 'z') {\n        // Formats %:z.\n        FormatTM(&result, std::string(pending, cur - 1), tm);\n        bp = FormatOffset(ep, al.offset, \":\");\n        result.append(bp, ep);\n        pending = cur += 2;\n        continue;\n      }\n      if (*(cur + 1) == ':' && cur + 2 != end) {\n        if (*(cur + 2) == 'z') {\n          // Formats %::z.\n          FormatTM(&result, std::string(pending, cur - 1), tm);\n          bp = FormatOffset(ep, al.offset, \":*\");\n          result.append(bp, ep);\n          pending = cur += 3;\n          continue;\n        }\n        if (*(cur + 2) == ':' && cur + 3 != end) {\n          if (*(cur + 3) == 'z') {\n            // Formats %:::z.\n            FormatTM(&result, std::string(pending, cur - 1), tm);\n            bp = FormatOffset(ep, al.offset, \":*:\");\n            result.append(bp, ep);\n            pending = cur += 4;\n            continue;\n          }\n        }\n      }\n    }\n\n    // Loop if there is no E modifier.\n    if (*cur != 'E' || ++cur == end) continue;\n\n    // Format our extensions.\n    if (*cur == 'T') {\n      // Formats %ET.\n      FormatTM(&result, std::string(pending, cur - 2), tm);\n      result.append(\"T\");\n      pending = ++cur;\n    } else if (*cur == 'z') {\n      // Formats %Ez.\n      FormatTM(&result, std::string(pending, cur - 2), tm);\n      bp = FormatOffset(ep, al.offset, \":\");\n      result.append(bp, ep);\n      pending = ++cur;\n    } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') {\n      // Formats %E*z.\n      FormatTM(&result, std::string(pending, cur - 2), tm);\n      bp = FormatOffset(ep, al.offset, \":*\");\n      result.append(bp, ep);\n      pending = cur += 2;\n    } else if (*cur == '*' && cur + 1 != end &&\n               (*(cur + 1) == 'S' || *(cur + 1) == 'f')) {\n      // Formats %E*S or %E*F.\n      FormatTM(&result, std::string(pending, cur - 2), tm);\n      char* cp = ep;\n      bp = Format64(cp, 15, fs.count());\n      while (cp != bp && cp[-1] == '0') --cp;\n      switch (*(cur + 1)) {\n        case 'S':\n          if (cp != bp) *--bp = '.';\n          bp = Format02d(bp, al.cs.second());\n          break;\n        case 'f':\n          if (cp == bp) *--bp = '0';\n          break;\n      }\n      result.append(bp, cp);\n      pending = cur += 2;\n    } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') {\n      // Formats %E4Y.\n      FormatTM(&result, std::string(pending, cur - 2), tm);\n      bp = Format64(ep, 4, al.cs.year());\n      result.append(bp, ep);\n      pending = cur += 2;\n    } else if (std::isdigit(*cur)) {\n      // Possibly found %E#S or %E#f.\n      int n = 0;\n      if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) {\n        if (*np == 'S' || *np == 'f') {\n          // Formats %E#S or %E#f.\n          FormatTM(&result, std::string(pending, cur - 2), tm);\n          bp = ep;\n          if (n > 0) {\n            if (n > kDigits10_64) n = kDigits10_64;\n            bp = Format64(bp, n,\n                          (n > 15) ? fs.count() * kExp10[n - 15]\n                                   : fs.count() / kExp10[15 - n]);\n            if (*np == 'S') *--bp = '.';\n          }\n          if (*np == 'S') bp = Format02d(bp, al.cs.second());\n          result.append(bp, ep);\n          pending = cur = ++np;\n        }\n      }\n    }\n  }\n\n  // Formats any remaining data.\n  FormatTM(&result, std::string(pending, end), tm);\n\n  return result;\n}\n\nnamespace {\n\nconst char* ParseOffset(const char* dp, const char* mode, int* offset) {\n  if (dp != nullptr) {\n    const char first = *dp++;\n    if (first == '+' || first == '-') {\n      char sep = mode[0];\n      int hours = 0;\n      int minutes = 0;\n      int seconds = 0;\n      const char* ap = ParseInt(dp, 2, 0, 23, &hours);\n      if (ap != nullptr && ap - dp == 2) {\n        dp = ap;\n        if (sep != '\\0' && *ap == sep) ++ap;\n        const char* bp = ParseInt(ap, 2, 0, 59, &minutes);\n        if (bp != nullptr && bp - ap == 2) {\n          dp = bp;\n          if (sep != '\\0' && *bp == sep) ++bp;\n          const char* cp = ParseInt(bp, 2, 0, 59, &seconds);\n          if (cp != nullptr && cp - bp == 2) dp = cp;\n        }\n        *offset = ((hours * 60 + minutes) * 60) + seconds;\n        if (first == '-') *offset = -*offset;\n      } else {\n        dp = nullptr;\n      }\n    } else if (first == 'Z' || first == 'z') {  // Zulu\n      *offset = 0;\n    } else {\n      dp = nullptr;\n    }\n  }\n  return dp;\n}\n\nconst char* ParseZone(const char* dp, std::string* zone) {\n  zone->clear();\n  if (dp != nullptr) {\n    while (*dp != '\\0' && !std::isspace(*dp)) zone->push_back(*dp++);\n    if (zone->empty()) dp = nullptr;\n  }\n  return dp;\n}\n\nconst char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) {\n  if (dp != nullptr) {\n    std::int_fast64_t v = 0;\n    std::int_fast64_t exp = 0;\n    const char* const bp = dp;\n    while (const char* cp = strchr(kDigits, *dp)) {\n      int d = static_cast<int>(cp - kDigits);\n      if (d >= 10) break;\n      if (exp < 15) {\n        exp += 1;\n        v *= 10;\n        v += d;\n      }\n      ++dp;\n    }\n    if (dp != bp) {\n      v *= kExp10[15 - exp];\n      *subseconds = detail::femtoseconds(v);\n    } else {\n      dp = nullptr;\n    }\n  }\n  return dp;\n}\n\n// Parses a string into a std::tm using strptime(3).\nconst char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {\n  if (dp != nullptr) {\n    dp = strptime(dp, fmt, tm);\n  }\n  return dp;\n}\n\n// Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday,\n// and the day on which weeks are defined to start.  Returns false if year\n// would need to move outside its bounds.\nbool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {\n  const civil_year y(*year % 400);\n  civil_day cd = prev_weekday(y, week_start);  // week 0\n  cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7);\n  if (const year_t shift = cd.year() - y.year()) {\n    if (shift > 0) {\n      if (*year > std::numeric_limits<year_t>::max() - shift) return false;\n    } else {\n      if (*year < std::numeric_limits<year_t>::min() - shift) return false;\n    }\n    *year += shift;\n  }\n  tm->tm_mon = cd.month() - 1;\n  tm->tm_mday = cd.day();\n  return true;\n}\n\n}  // namespace\n\n// Uses strptime(3) to parse the given input.  Supports the same extended\n// format specifiers as format(), although %E#S and %E*S are treated\n// identically (and similarly for %E#f and %E*f).  %Ez and %E*z also accept\n// the same inputs. %ET accepts either 'T' or 't'.\n//\n// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are\n// handled internally so that we can normally avoid strptime() altogether\n// (which is particularly helpful when the native implementation is broken).\n//\n// The TZ/GNU %s extension is handled internally because strptime() has to\n// use localtime_r() to generate it, and that assumes the local time zone.\n//\n// We also handle the %z specifier to accommodate platforms that do not\n// support the tm_gmtoff extension to std::tm.  %Z is parsed but ignored.\nbool parse(const std::string& format, const std::string& input,\n           const time_zone& tz, time_point<seconds>* sec,\n           detail::femtoseconds* fs, std::string* err) {\n  // The unparsed input.  Even though we allow NULs in input, and\n  // match them against corresponding NULs in format, we depend on\n  // *edata being a NUL so that we can call strptime().  This also\n  // makes our handling of input easier.\n  const char* data = input.c_str();  // NUL terminated\n  const char* const edata = data + input.size();\n\n  // Skips leading whitespace.\n  while (std::isspace(*data)) ++data;\n\n  const year_t kyearmax = std::numeric_limits<year_t>::max();\n  const year_t kyearmin = std::numeric_limits<year_t>::min();\n\n  // Sets default values for unspecified fields.\n  bool saw_year = false;\n  year_t year = 1970;\n  std::tm tm{};\n  tm.tm_year = 1970 - 1900;\n  tm.tm_mon = 1 - 1;  // Jan\n  tm.tm_mday = 1;\n  tm.tm_hour = 0;\n  tm.tm_min = 0;\n  tm.tm_sec = 0;\n  tm.tm_wday = 4;  // Thu\n  tm.tm_yday = 0;\n  tm.tm_isdst = 0;\n  auto subseconds = detail::femtoseconds::zero();\n  bool saw_offset = false;\n  int offset = 0;  // No offset from passed tz.\n  std::string zone = \"UTC\";\n\n  // Even though we allow NULs in format, and match them against\n  // corresponding NULs in input, we simplify its handling by also\n  // ensuring that *efmt is a NUL.\n  const char* fmt = format.c_str();  // NUL terminated\n  const char* const efmt = fmt + format.size();\n  bool twelve_hour = false;\n  bool afternoon = false;\n  int week_num = -1;\n  weekday week_start = weekday::sunday;\n\n  bool saw_percent_s = false;\n  std::int_fast64_t percent_s = 0;\n\n  // Steps through format, one specifier at a time.\n  while (data != nullptr && fmt != efmt) {\n    if (std::isspace(*fmt)) {\n      while (std::isspace(*data)) ++data;\n      while (std::isspace(*++fmt)) continue;\n      continue;\n    }\n\n    if (*fmt != '%') {\n      if (data != edata && *data == *fmt) {\n        ++data;\n        ++fmt;\n      } else {\n        data = nullptr;\n      }\n      continue;\n    }\n\n    const char* const percent = fmt;\n    if (++fmt == efmt) {\n      data = nullptr;\n      continue;\n    }\n    switch (*fmt++) {\n      case '\\0':\n        // Because we allow NULs in the format string, we must give\n        // some meaning to the \"%\\0\" specifier.  We choose the common\n        // (but undefined) strptime() behavior of failing on unknown\n        // specifiers.\n        data = nullptr;\n        continue;\n      case 'Y':\n        // Symmetrically with format(), directly handing %Y avoids the\n        // tm.tm_year overflow problem.  However, tm.tm_year will still be\n        // used by other specifiers like %D.\n        data = ParseInt(data, 0, kyearmin, kyearmax, &year);\n        if (data != nullptr) saw_year = true;\n        continue;\n      case 'm':\n        data = ParseInt(data, 2, 1, 12, &tm.tm_mon);\n        if (data != nullptr) tm.tm_mon -= 1;\n        week_num = -1;\n        continue;\n      case 'd':\n      case 'e':\n        data = ParseInt(data, 2, 1, 31, &tm.tm_mday);\n        week_num = -1;\n        continue;\n      case 'F':\n        data = ParseInt(data, 0, kyearmin, kyearmax, &year);\n        if (data != nullptr) {\n          saw_year = true;\n          data = (*data == '-' ? data + 1 : nullptr);\n        }\n        data = ParseInt(data, 2, 1, 12, &tm.tm_mon);\n        if (data != nullptr) {\n          tm.tm_mon -= 1;\n          data = (*data == '-' ? data + 1 : nullptr);\n        }\n        data = ParseInt(data, 2, 1, 31, &tm.tm_mday);\n        week_num = -1;\n        continue;\n      case 'U':\n        data = ParseInt(data, 0, 0, 53, &week_num);\n        week_start = weekday::sunday;\n        continue;\n      case 'W':\n        data = ParseInt(data, 0, 0, 53, &week_num);\n        week_start = weekday::monday;\n        continue;\n      case 'u':\n        data = ParseInt(data, 0, 1, 7, &tm.tm_wday);\n        if (data != nullptr) tm.tm_wday %= 7;\n        continue;\n      case 'w':\n        data = ParseInt(data, 0, 0, 6, &tm.tm_wday);\n        continue;\n      case 'H':\n        data = ParseInt(data, 2, 0, 23, &tm.tm_hour);\n        twelve_hour = false;\n        continue;\n      case 'M':\n        data = ParseInt(data, 2, 0, 59, &tm.tm_min);\n        continue;\n      case 'S':\n        data = ParseInt(data, 2, 0, 60, &tm.tm_sec);\n        continue;\n      case 'T':\n        data = ParseInt(data, 2, 0, 23, &tm.tm_hour);\n        twelve_hour = false;\n        data = (data != nullptr && *data == ':' ? data + 1 : nullptr);\n        data = ParseInt(data, 2, 0, 59, &tm.tm_min);\n        data = (data != nullptr && *data == ':' ? data + 1 : nullptr);\n        data = ParseInt(data, 2, 0, 60, &tm.tm_sec);\n        continue;\n      case 'I':\n      case 'l':\n      case 'r':  // probably uses %I\n        twelve_hour = true;\n        break;\n      case 'R':  // uses %H\n      case 'c':  // probably uses %H\n      case 'X':  // probably uses %H\n        twelve_hour = false;\n        break;\n      case 'z':\n        data = ParseOffset(data, \"\", &offset);\n        if (data != nullptr) saw_offset = true;\n        continue;\n      case 'Z':  // ignored; zone abbreviations are ambiguous\n        data = ParseZone(data, &zone);\n        continue;\n      case 's':\n        data =\n            ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(),\n                     std::numeric_limits<std::int_fast64_t>::max(), &percent_s);\n        if (data != nullptr) saw_percent_s = true;\n        continue;\n      case ':':\n        if (fmt[0] == 'z' ||\n            (fmt[0] == ':' &&\n             (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {\n          data = ParseOffset(data, \":\", &offset);\n          if (data != nullptr) saw_offset = true;\n          fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;\n          continue;\n        }\n        break;\n      case '%':\n        data = (*data == '%' ? data + 1 : nullptr);\n        continue;\n      case 'E':\n        if (fmt[0] == 'T') {\n          if (*data == 'T' || *data == 't') {\n            ++data;\n            ++fmt;\n          } else {\n            data = nullptr;\n          }\n          continue;\n        }\n        if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {\n          data = ParseOffset(data, \":\", &offset);\n          if (data != nullptr) saw_offset = true;\n          fmt += (fmt[0] == 'z') ? 1 : 2;\n          continue;\n        }\n        if (fmt[0] == '*' && fmt[1] == 'S') {\n          data = ParseInt(data, 2, 0, 60, &tm.tm_sec);\n          if (data != nullptr && *data == '.') {\n            data = ParseSubSeconds(data + 1, &subseconds);\n          }\n          fmt += 2;\n          continue;\n        }\n        if (fmt[0] == '*' && fmt[1] == 'f') {\n          if (data != nullptr && std::isdigit(*data)) {\n            data = ParseSubSeconds(data, &subseconds);\n          }\n          fmt += 2;\n          continue;\n        }\n        if (fmt[0] == '4' && fmt[1] == 'Y') {\n          const char* bp = data;\n          data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);\n          if (data != nullptr) {\n            if (data - bp == 4) {\n              saw_year = true;\n            } else {\n              data = nullptr;  // stopped too soon\n            }\n          }\n          fmt += 2;\n          continue;\n        }\n        if (std::isdigit(*fmt)) {\n          int n = 0;  // value ignored\n          if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) {\n            if (*np == 'S') {\n              data = ParseInt(data, 2, 0, 60, &tm.tm_sec);\n              if (data != nullptr && *data == '.') {\n                data = ParseSubSeconds(data + 1, &subseconds);\n              }\n              fmt = ++np;\n              continue;\n            }\n            if (*np == 'f') {\n              if (data != nullptr && std::isdigit(*data)) {\n                data = ParseSubSeconds(data, &subseconds);\n              }\n              fmt = ++np;\n              continue;\n            }\n          }\n        }\n        if (*fmt == 'c') twelve_hour = false;  // probably uses %H\n        if (*fmt == 'X') twelve_hour = false;  // probably uses %H\n        if (*fmt != '\\0') ++fmt;\n        break;\n      case 'O':\n        if (*fmt == 'H') twelve_hour = false;\n        if (*fmt == 'I') twelve_hour = true;\n        if (*fmt != '\\0') ++fmt;\n        break;\n    }\n\n    // Parses the current specifier.\n    const char* const orig_data = data;\n    std::string spec(percent, fmt);\n    data = ParseTM(data, spec.c_str(), &tm);\n\n    // If we successfully parsed %p we need to remember whether the result\n    // was AM or PM so that we can adjust tm_hour before time_zone::lookup().\n    // So reparse the input with a known AM hour, and check if it is shifted\n    // to a PM hour.\n    if (spec == \"%p\" && data != nullptr) {\n      std::string test_input = \"1\";\n      test_input.append(orig_data, data);\n      std::tm tmp{};\n      ParseTM(test_input.c_str(), \"%I%p\", &tmp);\n      afternoon = (tmp.tm_hour == 13);\n    }\n  }\n\n  // Adjust a 12-hour tm_hour value if it should be in the afternoon.\n  if (twelve_hour && afternoon && tm.tm_hour < 12) {\n    tm.tm_hour += 12;\n  }\n\n  if (data == nullptr) {\n    if (err != nullptr) *err = \"Failed to parse input\";\n    return false;\n  }\n\n  // Skip any remaining whitespace.\n  while (std::isspace(*data)) ++data;\n\n  // parse() must consume the entire input string.\n  if (data != edata) {\n    if (err != nullptr) *err = \"Illegal trailing data in input string\";\n    return false;\n  }\n\n  // If we saw %s then we ignore anything else and return that time.\n  if (saw_percent_s) {\n    *sec = FromUnixSeconds(percent_s);\n    *fs = detail::femtoseconds::zero();\n    return true;\n  }\n\n  // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields\n  // in UTC and then shift by that offset.  Otherwise we want to interpret\n  // the fields directly in the passed time_zone.\n  time_zone ptz = saw_offset ? utc_time_zone() : tz;\n\n  // Allows a leap second of 60 to normalize forward to the following \":00\".\n  if (tm.tm_sec == 60) {\n    tm.tm_sec -= 1;\n    offset -= 1;\n    subseconds = detail::femtoseconds::zero();\n  }\n\n  if (!saw_year) {\n    year = year_t{tm.tm_year};\n    if (year > kyearmax - 1900) {\n      // Platform-dependent, maybe unreachable.\n      if (err != nullptr) *err = \"Out-of-range year\";\n      return false;\n    }\n    year += 1900;\n  }\n\n  // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number.\n  if (week_num != -1) {\n    if (!FromWeek(week_num, week_start, &year, &tm)) {\n      if (err != nullptr) *err = \"Out-of-range field\";\n      return false;\n    }\n  }\n\n  const int month = tm.tm_mon + 1;\n  civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);\n\n  // parse() should not allow normalization. Due to the restricted field\n  // ranges above (see ParseInt()), the only possibility is for days to roll\n  // into months. That is, parsing \"Sep 31\" should not produce \"Oct 1\".\n  if (cs.month() != month || cs.day() != tm.tm_mday) {\n    if (err != nullptr) *err = \"Out-of-range field\";\n    return false;\n  }\n\n  // Accounts for the offset adjustment before converting to absolute time.\n  if ((offset < 0 && cs > civil_second::max() + offset) ||\n      (offset > 0 && cs < civil_second::min() + offset)) {\n    if (err != nullptr) *err = \"Out-of-range field\";\n    return false;\n  }\n  cs -= offset;\n\n  const auto tp = ptz.lookup(cs).pre;\n  // Checks for overflow/underflow and returns an error as necessary.\n  if (tp == time_point<seconds>::max()) {\n    const auto al = ptz.lookup(time_point<seconds>::max());\n    if (cs > al.cs) {\n      if (err != nullptr) *err = \"Out-of-range field\";\n      return false;\n    }\n  }\n  if (tp == time_point<seconds>::min()) {\n    const auto al = ptz.lookup(time_point<seconds>::min());\n    if (cs < al.cs) {\n      if (err != nullptr) *err = \"Out-of-range field\";\n      return false;\n    }\n  }\n\n  *sec = tp;\n  *fs = subseconds;\n  return true;\n}\n\n}  // namespace detail\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_format_test.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include <chrono>\n#include <cstdint>\n#include <iomanip>\n#include <sstream>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n#if defined(__linux__)\n#include <features.h>\n#endif\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n\nnamespace chrono = std::chrono;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\n// This helper is a macro so that failed expectations show up with the\n// correct line numbers.\n#define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \\\n  do {                                                            \\\n    time_zone::absolute_lookup al = tz.lookup(tp);                \\\n    EXPECT_EQ(y, al.cs.year());                                   \\\n    EXPECT_EQ(m, al.cs.month());                                  \\\n    EXPECT_EQ(d, al.cs.day());                                    \\\n    EXPECT_EQ(hh, al.cs.hour());                                  \\\n    EXPECT_EQ(mm, al.cs.minute());                                \\\n    EXPECT_EQ(ss, al.cs.second());                                \\\n    EXPECT_EQ(off, al.offset);                                    \\\n    EXPECT_TRUE(isdst == al.is_dst);                              \\\n    EXPECT_STREQ(zone, al.abbr);                                  \\\n  } while (0)\n\nconst char RFC3339_full[] = \"%Y-%m-%d%ET%H:%M:%E*S%Ez\";\nconst char RFC3339_sec[] = \"%Y-%m-%d%ET%H:%M:%S%Ez\";\n\nconst char RFC1123_full[] = \"%a, %d %b %Y %H:%M:%S %z\";\nconst char RFC1123_no_wday[] = \"%d %b %Y %H:%M:%S %z\";\n\n// A helper that tests the given format specifier by itself, and with leading\n// and trailing characters.  For example: TestFormatSpecifier(tp, \"%a\", \"Thu\").\ntemplate <typename D>\nvoid TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,\n                         const std::string& ans) {\n  EXPECT_EQ(ans, absl::time_internal::cctz::format(fmt, tp, tz)) << fmt;\n  EXPECT_EQ(\"xxx \" + ans,\n            absl::time_internal::cctz::format(\"xxx \" + fmt, tp, tz));\n  EXPECT_EQ(ans + \" yyy\",\n            absl::time_internal::cctz::format(fmt + \" yyy\", tp, tz));\n  EXPECT_EQ(\"xxx \" + ans + \" yyy\",\n            absl::time_internal::cctz::format(\"xxx \" + fmt + \" yyy\", tp, tz));\n}\n\n}  // namespace\n\n//\n// Testing format()\n//\n\nTEST(Format, TimePointResolution) {\n  const char kFmt[] = \"%H:%M:%E*S\";\n  const time_zone utc = utc_time_zone();\n  const time_point<chrono::nanoseconds> t0 =\n      chrono::system_clock::from_time_t(1420167845) +\n      chrono::milliseconds(123) + chrono::microseconds(456) +\n      chrono::nanoseconds(789);\n  EXPECT_EQ(\"03:04:05.123456789\",\n            absl::time_internal::cctz::format(\n                kFmt, chrono::time_point_cast<chrono::nanoseconds>(t0), utc));\n  EXPECT_EQ(\"03:04:05.123456\",\n            absl::time_internal::cctz::format(\n                kFmt, chrono::time_point_cast<chrono::microseconds>(t0), utc));\n  EXPECT_EQ(\"03:04:05.123\",\n            absl::time_internal::cctz::format(\n                kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));\n  EXPECT_EQ(\"03:04:05\",\n            absl::time_internal::cctz::format(\n                kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));\n  EXPECT_EQ(\n      \"03:04:05\",\n      absl::time_internal::cctz::format(\n          kFmt, chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),\n          utc));\n  EXPECT_EQ(\"03:04:00\",\n            absl::time_internal::cctz::format(\n                kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));\n  EXPECT_EQ(\"03:00:00\",\n            absl::time_internal::cctz::format(\n                kFmt, chrono::time_point_cast<chrono::hours>(t0), utc));\n}\n\nTEST(Format, TimePointExtendedResolution) {\n  const char kFmt[] = \"%H:%M:%E*S\";\n  const time_zone utc = utc_time_zone();\n  const time_point<absl::time_internal::cctz::seconds> tp =\n      chrono::time_point_cast<absl::time_internal::cctz::seconds>(\n          chrono::system_clock::from_time_t(0)) +\n      chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56);\n\n  EXPECT_EQ(\n      \"12:34:56.123456789012345\",\n      detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc));\n  EXPECT_EQ(\n      \"12:34:56.012345678901234\",\n      detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));\n  EXPECT_EQ(\"12:34:56.001234567890123\",\n            detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));\n  EXPECT_EQ(\"12:34:56.000123456789012\",\n            detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));\n\n  EXPECT_EQ(\"12:34:56.000000000000123\",\n            detail::format(kFmt, tp, detail::femtoseconds(123), utc));\n  EXPECT_EQ(\"12:34:56.000000000000012\",\n            detail::format(kFmt, tp, detail::femtoseconds(12), utc));\n  EXPECT_EQ(\"12:34:56.000000000000001\",\n            detail::format(kFmt, tp, detail::femtoseconds(1), utc));\n}\n\nTEST(Format, Basics) {\n  time_zone tz = utc_time_zone();\n  time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);\n\n  // Start with basic edge cases.\n  EXPECT_EQ(\"\", absl::time_internal::cctz::format(\"\", tp, tz));\n  EXPECT_EQ(\" \", absl::time_internal::cctz::format(\" \", tp, tz));\n  EXPECT_EQ(\"  \", absl::time_internal::cctz::format(\"  \", tp, tz));\n  EXPECT_EQ(\"xxx\", absl::time_internal::cctz::format(\"xxx\", tp, tz));\n  std::string big(128, 'x');\n  EXPECT_EQ(big, absl::time_internal::cctz::format(big, tp, tz));\n  // Cause the 1024-byte buffer to grow.\n  std::string bigger(100000, 'x');\n  EXPECT_EQ(bigger, absl::time_internal::cctz::format(bigger, tp, tz));\n\n  tp += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5);\n  tp += chrono::milliseconds(6) + chrono::microseconds(7) +\n        chrono::nanoseconds(8);\n  EXPECT_EQ(\"1970-01-01\",\n            absl::time_internal::cctz::format(\"%Y-%m-%d\", tp, tz));\n  EXPECT_EQ(\"13:04:05\", absl::time_internal::cctz::format(\"%H:%M:%S\", tp, tz));\n  EXPECT_EQ(\"13:04:05.006\",\n            absl::time_internal::cctz::format(\"%H:%M:%E3S\", tp, tz));\n  EXPECT_EQ(\"13:04:05.006007\",\n            absl::time_internal::cctz::format(\"%H:%M:%E6S\", tp, tz));\n  EXPECT_EQ(\"13:04:05.006007008\",\n            absl::time_internal::cctz::format(\"%H:%M:%E9S\", tp, tz));\n}\n\nTEST(Format, PosixConversions) {\n  const time_zone tz = utc_time_zone();\n  auto tp =\n      chrono::system_clock::from_time_t(308189482);  // 1979-10-08T00:11:22Z\n\n  TestFormatSpecifier(tp, tz, \"%d\", \"08\");\n  TestFormatSpecifier(tp, tz, \"%e\", \" 8\");  // extension but internal support\n  TestFormatSpecifier(tp, tz, \"%H\", \"00\");\n  TestFormatSpecifier(tp, tz, \"%I\", \"12\");\n  TestFormatSpecifier(tp, tz, \"%j\", \"281\");\n  TestFormatSpecifier(tp, tz, \"%m\", \"10\");\n  TestFormatSpecifier(tp, tz, \"%M\", \"11\");\n  TestFormatSpecifier(tp, tz, \"%S\", \"22\");\n  TestFormatSpecifier(tp, tz, \"%U\", \"40\");\n  TestFormatSpecifier(tp, tz, \"%w\", \"1\");  // 1=Monday\n  TestFormatSpecifier(tp, tz, \"%W\", \"41\");\n  TestFormatSpecifier(tp, tz, \"%y\", \"79\");\n  TestFormatSpecifier(tp, tz, \"%Y\", \"1979\");\n  TestFormatSpecifier(tp, tz, \"%z\", \"+0000\");\n  TestFormatSpecifier(tp, tz, \"%Z\", \"UTC\");\n  TestFormatSpecifier(tp, tz, \"%%\", \"%\");\n\n#if defined(__linux__)\n  // SU/C99/TZ extensions\n  TestFormatSpecifier(tp, tz, \"%C\", \"19\");\n  TestFormatSpecifier(tp, tz, \"%D\", \"10/08/79\");\n  TestFormatSpecifier(tp, tz, \"%F\", \"1979-10-08\");\n  TestFormatSpecifier(tp, tz, \"%g\", \"79\");\n  TestFormatSpecifier(tp, tz, \"%G\", \"1979\");\n#if defined(__GLIBC__)\n  TestFormatSpecifier(tp, tz, \"%k\", \" 0\");\n  TestFormatSpecifier(tp, tz, \"%l\", \"12\");\n#endif\n  TestFormatSpecifier(tp, tz, \"%n\", \"\\n\");\n  TestFormatSpecifier(tp, tz, \"%R\", \"00:11\");\n  TestFormatSpecifier(tp, tz, \"%t\", \"\\t\");\n  TestFormatSpecifier(tp, tz, \"%T\", \"00:11:22\");\n  TestFormatSpecifier(tp, tz, \"%u\", \"1\");  // 1=Monday\n  TestFormatSpecifier(tp, tz, \"%V\", \"41\");\n  TestFormatSpecifier(tp, tz, \"%s\", \"308189482\");\n#endif\n}\n\nTEST(Format, LocaleSpecific) {\n  const time_zone tz = utc_time_zone();\n  auto tp = chrono::system_clock::from_time_t(0);\n\n  TestFormatSpecifier(tp, tz, \"%a\", \"Thu\");\n  TestFormatSpecifier(tp, tz, \"%A\", \"Thursday\");\n  TestFormatSpecifier(tp, tz, \"%b\", \"Jan\");\n  TestFormatSpecifier(tp, tz, \"%B\", \"January\");\n\n  // %c should at least produce the numeric year and time-of-day.\n  const std::string s =\n      absl::time_internal::cctz::format(\"%c\", tp, utc_time_zone());\n  EXPECT_THAT(s, testing::HasSubstr(\"1970\"));\n  EXPECT_THAT(s, testing::HasSubstr(\"00:00:00\"));\n\n  TestFormatSpecifier(tp, tz, \"%p\", \"AM\");\n  TestFormatSpecifier(tp, tz, \"%x\", \"01/01/70\");\n  TestFormatSpecifier(tp, tz, \"%X\", \"00:00:00\");\n\n#if defined(__linux__)\n  // SU/C99/TZ extensions\n  TestFormatSpecifier(tp, tz, \"%h\", \"Jan\");  // Same as %b\n#if defined(__GLIBC__)\n  TestFormatSpecifier(tp, tz, \"%P\", \"am\");\n#endif\n  TestFormatSpecifier(tp, tz, \"%r\", \"12:00:00 AM\");\n\n  // Modified conversion specifiers %E_\n  TestFormatSpecifier(tp, tz, \"%Ec\", \"Thu Jan  1 00:00:00 1970\");\n  TestFormatSpecifier(tp, tz, \"%EC\", \"19\");\n  TestFormatSpecifier(tp, tz, \"%Ex\", \"01/01/70\");\n  TestFormatSpecifier(tp, tz, \"%EX\", \"00:00:00\");\n  TestFormatSpecifier(tp, tz, \"%Ey\", \"70\");\n  TestFormatSpecifier(tp, tz, \"%EY\", \"1970\");\n\n  // Modified conversion specifiers %O_\n  TestFormatSpecifier(tp, tz, \"%Od\", \"01\");\n  TestFormatSpecifier(tp, tz, \"%Oe\", \" 1\");\n  TestFormatSpecifier(tp, tz, \"%OH\", \"00\");\n  TestFormatSpecifier(tp, tz, \"%OI\", \"12\");\n  TestFormatSpecifier(tp, tz, \"%Om\", \"01\");\n  TestFormatSpecifier(tp, tz, \"%OM\", \"00\");\n  TestFormatSpecifier(tp, tz, \"%OS\", \"00\");\n  TestFormatSpecifier(tp, tz, \"%Ou\", \"4\");  // 4=Thursday\n  TestFormatSpecifier(tp, tz, \"%OU\", \"00\");\n  TestFormatSpecifier(tp, tz, \"%OV\", \"01\");\n  TestFormatSpecifier(tp, tz, \"%Ow\", \"4\");  // 4=Thursday\n  TestFormatSpecifier(tp, tz, \"%OW\", \"00\");\n  TestFormatSpecifier(tp, tz, \"%Oy\", \"70\");\n#endif\n}\n\nTEST(Format, Escaping) {\n  const time_zone tz = utc_time_zone();\n  auto tp = chrono::system_clock::from_time_t(0);\n\n  TestFormatSpecifier(tp, tz, \"%%\", \"%\");\n  TestFormatSpecifier(tp, tz, \"%%a\", \"%a\");\n  TestFormatSpecifier(tp, tz, \"%%b\", \"%b\");\n  TestFormatSpecifier(tp, tz, \"%%Ea\", \"%Ea\");\n  TestFormatSpecifier(tp, tz, \"%%Es\", \"%Es\");\n  TestFormatSpecifier(tp, tz, \"%%E3S\", \"%E3S\");\n  TestFormatSpecifier(tp, tz, \"%%OS\", \"%OS\");\n  TestFormatSpecifier(tp, tz, \"%%O3S\", \"%O3S\");\n\n  // Multiple levels of escaping.\n  TestFormatSpecifier(tp, tz, \"%%%Y\", \"%1970\");\n  TestFormatSpecifier(tp, tz, \"%%%E3S\", \"%00.000\");\n  TestFormatSpecifier(tp, tz, \"%%%%E3S\", \"%%E3S\");\n}\n\nTEST(Format, ExtendedSeconds) {\n  const time_zone tz = utc_time_zone();\n\n  // No subseconds.\n  time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);\n  tp += chrono::seconds(5);\n  EXPECT_EQ(\"05\", absl::time_internal::cctz::format(\"%E*S\", tp, tz));\n  EXPECT_EQ(\"05\", absl::time_internal::cctz::format(\"%E0S\", tp, tz));\n  EXPECT_EQ(\"05.0\", absl::time_internal::cctz::format(\"%E1S\", tp, tz));\n  EXPECT_EQ(\"05.00\", absl::time_internal::cctz::format(\"%E2S\", tp, tz));\n  EXPECT_EQ(\"05.000\", absl::time_internal::cctz::format(\"%E3S\", tp, tz));\n  EXPECT_EQ(\"05.0000\", absl::time_internal::cctz::format(\"%E4S\", tp, tz));\n  EXPECT_EQ(\"05.00000\", absl::time_internal::cctz::format(\"%E5S\", tp, tz));\n  EXPECT_EQ(\"05.000000\", absl::time_internal::cctz::format(\"%E6S\", tp, tz));\n  EXPECT_EQ(\"05.0000000\", absl::time_internal::cctz::format(\"%E7S\", tp, tz));\n  EXPECT_EQ(\"05.00000000\", absl::time_internal::cctz::format(\"%E8S\", tp, tz));\n  EXPECT_EQ(\"05.000000000\", absl::time_internal::cctz::format(\"%E9S\", tp, tz));\n  EXPECT_EQ(\"05.0000000000\",\n            absl::time_internal::cctz::format(\"%E10S\", tp, tz));\n  EXPECT_EQ(\"05.00000000000\",\n            absl::time_internal::cctz::format(\"%E11S\", tp, tz));\n  EXPECT_EQ(\"05.000000000000\",\n            absl::time_internal::cctz::format(\"%E12S\", tp, tz));\n  EXPECT_EQ(\"05.0000000000000\",\n            absl::time_internal::cctz::format(\"%E13S\", tp, tz));\n  EXPECT_EQ(\"05.00000000000000\",\n            absl::time_internal::cctz::format(\"%E14S\", tp, tz));\n  EXPECT_EQ(\"05.000000000000000\",\n            absl::time_internal::cctz::format(\"%E15S\", tp, tz));\n\n  // With subseconds.\n  tp += chrono::milliseconds(6) + chrono::microseconds(7) +\n        chrono::nanoseconds(8);\n  EXPECT_EQ(\"05.006007008\", absl::time_internal::cctz::format(\"%E*S\", tp, tz));\n  EXPECT_EQ(\"05\", absl::time_internal::cctz::format(\"%E0S\", tp, tz));\n  EXPECT_EQ(\"05.0\", absl::time_internal::cctz::format(\"%E1S\", tp, tz));\n  EXPECT_EQ(\"05.00\", absl::time_internal::cctz::format(\"%E2S\", tp, tz));\n  EXPECT_EQ(\"05.006\", absl::time_internal::cctz::format(\"%E3S\", tp, tz));\n  EXPECT_EQ(\"05.0060\", absl::time_internal::cctz::format(\"%E4S\", tp, tz));\n  EXPECT_EQ(\"05.00600\", absl::time_internal::cctz::format(\"%E5S\", tp, tz));\n  EXPECT_EQ(\"05.006007\", absl::time_internal::cctz::format(\"%E6S\", tp, tz));\n  EXPECT_EQ(\"05.0060070\", absl::time_internal::cctz::format(\"%E7S\", tp, tz));\n  EXPECT_EQ(\"05.00600700\", absl::time_internal::cctz::format(\"%E8S\", tp, tz));\n  EXPECT_EQ(\"05.006007008\", absl::time_internal::cctz::format(\"%E9S\", tp, tz));\n  EXPECT_EQ(\"05.0060070080\",\n            absl::time_internal::cctz::format(\"%E10S\", tp, tz));\n  EXPECT_EQ(\"05.00600700800\",\n            absl::time_internal::cctz::format(\"%E11S\", tp, tz));\n  EXPECT_EQ(\"05.006007008000\",\n            absl::time_internal::cctz::format(\"%E12S\", tp, tz));\n  EXPECT_EQ(\"05.0060070080000\",\n            absl::time_internal::cctz::format(\"%E13S\", tp, tz));\n  EXPECT_EQ(\"05.00600700800000\",\n            absl::time_internal::cctz::format(\"%E14S\", tp, tz));\n  EXPECT_EQ(\"05.006007008000000\",\n            absl::time_internal::cctz::format(\"%E15S\", tp, tz));\n\n  // Times before the Unix epoch.\n  tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);\n  EXPECT_EQ(\"1969-12-31 23:59:59.999999\",\n            absl::time_internal::cctz::format(\"%Y-%m-%d %H:%M:%E*S\", tp, tz));\n\n  // Here is a \"%E*S\" case we got wrong for a while.  While the first\n  // instant below is correctly rendered as \"...:07.333304\", the second\n  // one used to appear as \"...:07.33330499999999999\".\n  tp = chrono::system_clock::from_time_t(0) +\n       chrono::microseconds(1395024427333304);\n  EXPECT_EQ(\"2014-03-17 02:47:07.333304\",\n            absl::time_internal::cctz::format(\"%Y-%m-%d %H:%M:%E*S\", tp, tz));\n  tp += chrono::microseconds(1);\n  EXPECT_EQ(\"2014-03-17 02:47:07.333305\",\n            absl::time_internal::cctz::format(\"%Y-%m-%d %H:%M:%E*S\", tp, tz));\n}\n\nTEST(Format, ExtendedSubeconds) {\n  const time_zone tz = utc_time_zone();\n\n  // No subseconds.\n  time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);\n  tp += chrono::seconds(5);\n  EXPECT_EQ(\"0\", absl::time_internal::cctz::format(\"%E*f\", tp, tz));\n  EXPECT_EQ(\"\", absl::time_internal::cctz::format(\"%E0f\", tp, tz));\n  EXPECT_EQ(\"0\", absl::time_internal::cctz::format(\"%E1f\", tp, tz));\n  EXPECT_EQ(\"00\", absl::time_internal::cctz::format(\"%E2f\", tp, tz));\n  EXPECT_EQ(\"000\", absl::time_internal::cctz::format(\"%E3f\", tp, tz));\n  EXPECT_EQ(\"0000\", absl::time_internal::cctz::format(\"%E4f\", tp, tz));\n  EXPECT_EQ(\"00000\", absl::time_internal::cctz::format(\"%E5f\", tp, tz));\n  EXPECT_EQ(\"000000\", absl::time_internal::cctz::format(\"%E6f\", tp, tz));\n  EXPECT_EQ(\"0000000\", absl::time_internal::cctz::format(\"%E7f\", tp, tz));\n  EXPECT_EQ(\"00000000\", absl::time_internal::cctz::format(\"%E8f\", tp, tz));\n  EXPECT_EQ(\"000000000\", absl::time_internal::cctz::format(\"%E9f\", tp, tz));\n  EXPECT_EQ(\"0000000000\", absl::time_internal::cctz::format(\"%E10f\", tp, tz));\n  EXPECT_EQ(\"00000000000\", absl::time_internal::cctz::format(\"%E11f\", tp, tz));\n  EXPECT_EQ(\"000000000000\", absl::time_internal::cctz::format(\"%E12f\", tp, tz));\n  EXPECT_EQ(\"0000000000000\",\n            absl::time_internal::cctz::format(\"%E13f\", tp, tz));\n  EXPECT_EQ(\"00000000000000\",\n            absl::time_internal::cctz::format(\"%E14f\", tp, tz));\n  EXPECT_EQ(\"000000000000000\",\n            absl::time_internal::cctz::format(\"%E15f\", tp, tz));\n\n  // With subseconds.\n  tp += chrono::milliseconds(6) + chrono::microseconds(7) +\n        chrono::nanoseconds(8);\n  EXPECT_EQ(\"006007008\", absl::time_internal::cctz::format(\"%E*f\", tp, tz));\n  EXPECT_EQ(\"\", absl::time_internal::cctz::format(\"%E0f\", tp, tz));\n  EXPECT_EQ(\"0\", absl::time_internal::cctz::format(\"%E1f\", tp, tz));\n  EXPECT_EQ(\"00\", absl::time_internal::cctz::format(\"%E2f\", tp, tz));\n  EXPECT_EQ(\"006\", absl::time_internal::cctz::format(\"%E3f\", tp, tz));\n  EXPECT_EQ(\"0060\", absl::time_internal::cctz::format(\"%E4f\", tp, tz));\n  EXPECT_EQ(\"00600\", absl::time_internal::cctz::format(\"%E5f\", tp, tz));\n  EXPECT_EQ(\"006007\", absl::time_internal::cctz::format(\"%E6f\", tp, tz));\n  EXPECT_EQ(\"0060070\", absl::time_internal::cctz::format(\"%E7f\", tp, tz));\n  EXPECT_EQ(\"00600700\", absl::time_internal::cctz::format(\"%E8f\", tp, tz));\n  EXPECT_EQ(\"006007008\", absl::time_internal::cctz::format(\"%E9f\", tp, tz));\n  EXPECT_EQ(\"0060070080\", absl::time_internal::cctz::format(\"%E10f\", tp, tz));\n  EXPECT_EQ(\"00600700800\", absl::time_internal::cctz::format(\"%E11f\", tp, tz));\n  EXPECT_EQ(\"006007008000\", absl::time_internal::cctz::format(\"%E12f\", tp, tz));\n  EXPECT_EQ(\"0060070080000\",\n            absl::time_internal::cctz::format(\"%E13f\", tp, tz));\n  EXPECT_EQ(\"00600700800000\",\n            absl::time_internal::cctz::format(\"%E14f\", tp, tz));\n  EXPECT_EQ(\"006007008000000\",\n            absl::time_internal::cctz::format(\"%E15f\", tp, tz));\n\n  // Times before the Unix epoch.\n  tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);\n  EXPECT_EQ(\n      \"1969-12-31 23:59:59.999999\",\n      absl::time_internal::cctz::format(\"%Y-%m-%d %H:%M:%S.%E*f\", tp, tz));\n\n  // Here is a \"%E*S\" case we got wrong for a while.  While the first\n  // instant below is correctly rendered as \"...:07.333304\", the second\n  // one used to appear as \"...:07.33330499999999999\".\n  tp = chrono::system_clock::from_time_t(0) +\n       chrono::microseconds(1395024427333304);\n  EXPECT_EQ(\n      \"2014-03-17 02:47:07.333304\",\n      absl::time_internal::cctz::format(\"%Y-%m-%d %H:%M:%S.%E*f\", tp, tz));\n  tp += chrono::microseconds(1);\n  EXPECT_EQ(\n      \"2014-03-17 02:47:07.333305\",\n      absl::time_internal::cctz::format(\"%Y-%m-%d %H:%M:%S.%E*f\", tp, tz));\n}\n\nTEST(Format, CompareExtendSecondsVsSubseconds) {\n  const time_zone tz = utc_time_zone();\n\n  // This test case illustrates the differences/similarities between:\n  //   fmt_A: %E<prec>S\n  //   fmt_B: %S.%E<prec>f\n  auto fmt_A = [](const std::string& prec) { return \"%E\" + prec + \"S\"; };\n  auto fmt_B = [](const std::string& prec) { return \"%S.%E\" + prec + \"f\"; };\n\n  // No subseconds:\n  time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);\n  tp += chrono::seconds(5);\n  // ... %E*S and %S.%E*f are different.\n  EXPECT_EQ(\"05\", absl::time_internal::cctz::format(fmt_A(\"*\"), tp, tz));\n  EXPECT_EQ(\"05.0\", absl::time_internal::cctz::format(fmt_B(\"*\"), tp, tz));\n  // ... %E0S and %S.%E0f are different.\n  EXPECT_EQ(\"05\", absl::time_internal::cctz::format(fmt_A(\"0\"), tp, tz));\n  EXPECT_EQ(\"05.\", absl::time_internal::cctz::format(fmt_B(\"0\"), tp, tz));\n  // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].\n  for (int prec = 1; prec <= 15; ++prec) {\n    const std::string a =\n        absl::time_internal::cctz::format(fmt_A(std::to_string(prec)), tp, tz);\n    const std::string b =\n        absl::time_internal::cctz::format(fmt_B(std::to_string(prec)), tp, tz);\n    EXPECT_EQ(a, b) << \"prec=\" << prec;\n  }\n\n  // With subseconds:\n  // ... %E*S and %S.%E*f are the same.\n  tp += chrono::milliseconds(6) + chrono::microseconds(7) +\n        chrono::nanoseconds(8);\n  EXPECT_EQ(\"05.006007008\",\n            absl::time_internal::cctz::format(fmt_A(\"*\"), tp, tz));\n  EXPECT_EQ(\"05.006007008\",\n            absl::time_internal::cctz::format(fmt_B(\"*\"), tp, tz));\n  // ... %E0S and %S.%E0f are different.\n  EXPECT_EQ(\"05\", absl::time_internal::cctz::format(fmt_A(\"0\"), tp, tz));\n  EXPECT_EQ(\"05.\", absl::time_internal::cctz::format(fmt_B(\"0\"), tp, tz));\n  // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].\n  for (int prec = 1; prec <= 15; ++prec) {\n    const std::string a =\n        absl::time_internal::cctz::format(fmt_A(std::to_string(prec)), tp, tz);\n    const std::string b =\n        absl::time_internal::cctz::format(fmt_B(std::to_string(prec)), tp, tz);\n    EXPECT_EQ(a, b) << \"prec=\" << prec;\n  }\n}\n\nTEST(Format, ExtendedOffset) {\n  const auto tp = chrono::system_clock::from_time_t(0);\n\n  auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());\n  TestFormatSpecifier(tp, tz, \"%z\", \"+0000\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+00:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+00:00\");\n\n  tz = fixed_time_zone(chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+0000\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+00:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+00:00\");\n\n  tz = fixed_time_zone(-chrono::seconds(56));  // NOTE: +00:00\n  TestFormatSpecifier(tp, tz, \"%z\", \"+0000\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+00:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+00:00\");\n\n  tz = fixed_time_zone(chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+0034\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+00:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+00:34\");\n\n  tz = fixed_time_zone(-chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%z\", \"-0034\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"-00:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"-00:34\");\n\n  tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+0034\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+00:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+00:34\");\n\n  tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"-0034\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"-00:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"-00:34\");\n\n  tz = fixed_time_zone(chrono::hours(12));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+1200\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+12:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+12:00\");\n\n  tz = fixed_time_zone(-chrono::hours(12));\n  TestFormatSpecifier(tp, tz, \"%z\", \"-1200\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"-12:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"-12:00\");\n\n  tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+1200\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+12:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+12:00\");\n\n  tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"-1200\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"-12:00\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"-12:00\");\n\n  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+1234\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+12:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+12:34\");\n\n  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%z\", \"-1234\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"-12:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"-12:34\");\n\n  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +\n                       chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"+1234\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"+12:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"+12:34\");\n\n  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -\n                       chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%z\", \"-1234\");\n  TestFormatSpecifier(tp, tz, \"%:z\", \"-12:34\");\n  TestFormatSpecifier(tp, tz, \"%Ez\", \"-12:34\");\n}\n\nTEST(Format, ExtendedSecondOffset) {\n  const auto tp = chrono::system_clock::from_time_t(0);\n\n  auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+00:00:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+00:00:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+00\");\n\n  tz = fixed_time_zone(chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+00:00:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+00:00:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+00:00:56\");\n\n  tz = fixed_time_zone(-chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-00:00:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-00:00:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-00:00:56\");\n\n  tz = fixed_time_zone(chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+00:34:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+00:34:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+00:34\");\n\n  tz = fixed_time_zone(-chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-00:34:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-00:34:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-00:34\");\n\n  tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+00:34:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+00:34:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+00:34:56\");\n\n  tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-00:34:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-00:34:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-00:34:56\");\n\n  tz = fixed_time_zone(chrono::hours(12));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+12:00:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+12:00:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+12\");\n\n  tz = fixed_time_zone(-chrono::hours(12));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-12:00:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-12:00:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-12\");\n\n  tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+12:00:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+12:00:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+12:00:56\");\n\n  tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-12:00:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-12:00:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-12:00:56\");\n\n  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+12:34:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+12:34:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+12:34\");\n\n  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-12:34:00\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-12:34:00\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-12:34\");\n\n  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +\n                       chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"+12:34:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"+12:34:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"+12:34:56\");\n\n  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -\n                       chrono::seconds(56));\n  TestFormatSpecifier(tp, tz, \"%E*z\", \"-12:34:56\");\n  TestFormatSpecifier(tp, tz, \"%::z\", \"-12:34:56\");\n  TestFormatSpecifier(tp, tz, \"%:::z\", \"-12:34:56\");\n}\n\nTEST(Format, ExtendedYears) {\n  const time_zone utc = utc_time_zone();\n  const char e4y_fmt[] = \"%E4Y%m%d\";  // no separators\n\n  // %E4Y zero-pads the year to produce at least 4 chars, including the sign.\n  auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"-9991127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"-0991127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"-0091127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"-0011127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"00001127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"00011127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"00091127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"00991127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"09991127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"99991127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n\n  // When the year is outside [-999:9999], more than 4 chars are produced.\n  tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"-10001127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n  tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc);\n  EXPECT_EQ(\"100001127\", absl::time_internal::cctz::format(e4y_fmt, tp, utc));\n}\n\nTEST(Format, RFC3339Format) {\n  time_zone tz;\n  EXPECT_TRUE(load_time_zone(\"America/Los_Angeles\", &tz));\n\n  time_point<chrono::nanoseconds> tp =\n      convert(civil_second(1977, 6, 28, 9, 8, 7), tz);\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::milliseconds(100);\n  EXPECT_EQ(\"1977-06-28T09:08:07.1-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::milliseconds(20);\n  EXPECT_EQ(\"1977-06-28T09:08:07.12-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::milliseconds(3);\n  EXPECT_EQ(\"1977-06-28T09:08:07.123-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::microseconds(400);\n  EXPECT_EQ(\"1977-06-28T09:08:07.1234-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::microseconds(50);\n  EXPECT_EQ(\"1977-06-28T09:08:07.12345-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::microseconds(6);\n  EXPECT_EQ(\"1977-06-28T09:08:07.123456-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::nanoseconds(700);\n  EXPECT_EQ(\"1977-06-28T09:08:07.1234567-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::nanoseconds(80);\n  EXPECT_EQ(\"1977-06-28T09:08:07.12345678-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n\n  tp += chrono::nanoseconds(9);\n  EXPECT_EQ(\"1977-06-28T09:08:07.123456789-07:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, tz));\n  EXPECT_EQ(\"1977-06-28T09:08:07-07:00\",\n            absl::time_internal::cctz::format(RFC3339_sec, tp, tz));\n}\n\nTEST(Format, RFC1123Format) {  // locale specific\n  time_zone tz;\n  EXPECT_TRUE(load_time_zone(\"America/Los_Angeles\", &tz));\n\n  auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);\n  EXPECT_EQ(\"Tue, 28 Jun 1977 09:08:07 -0700\",\n            absl::time_internal::cctz::format(RFC1123_full, tp, tz));\n  EXPECT_EQ(\"28 Jun 1977 09:08:07 -0700\",\n            absl::time_internal::cctz::format(RFC1123_no_wday, tp, tz));\n}\n\nTEST(Format, Week) {\n  const time_zone utc = utc_time_zone();\n\n  auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);\n  EXPECT_EQ(\"2017-01-7\",\n            absl::time_internal::cctz::format(\"%Y-%U-%u\", tp, utc));\n  EXPECT_EQ(\"2017-00-0\",\n            absl::time_internal::cctz::format(\"%Y-%W-%w\", tp, utc));\n\n  tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);\n  EXPECT_EQ(\"2017-53-7\",\n            absl::time_internal::cctz::format(\"%Y-%U-%u\", tp, utc));\n  EXPECT_EQ(\"2017-52-0\",\n            absl::time_internal::cctz::format(\"%Y-%W-%w\", tp, utc));\n\n  tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);\n  EXPECT_EQ(\"2018-00-1\",\n            absl::time_internal::cctz::format(\"%Y-%U-%u\", tp, utc));\n  EXPECT_EQ(\"2018-01-1\",\n            absl::time_internal::cctz::format(\"%Y-%W-%w\", tp, utc));\n\n  tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);\n  EXPECT_EQ(\"2018-52-1\",\n            absl::time_internal::cctz::format(\"%Y-%U-%u\", tp, utc));\n  EXPECT_EQ(\"2018-53-1\",\n            absl::time_internal::cctz::format(\"%Y-%W-%w\", tp, utc));\n\n  tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);\n  EXPECT_EQ(\"2019-00-2\",\n            absl::time_internal::cctz::format(\"%Y-%U-%u\", tp, utc));\n  EXPECT_EQ(\"2019-00-2\",\n            absl::time_internal::cctz::format(\"%Y-%W-%w\", tp, utc));\n\n  tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);\n  EXPECT_EQ(\"2019-52-2\",\n            absl::time_internal::cctz::format(\"%Y-%U-%u\", tp, utc));\n  EXPECT_EQ(\"2019-52-2\",\n            absl::time_internal::cctz::format(\"%Y-%W-%w\", tp, utc));\n}\n\nTEST(Format, NULsInFormatString) {\n  time_zone tz = utc_time_zone();\n  time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);\n\n  // All NULs.\n  std::string nuls(32, '\\0');\n  EXPECT_EQ(nuls, absl::time_internal::cctz::format(nuls, tp, tz));\n\n  // NULs amongst ordinary text plus the internal \"%\\0\" specifier.\n  std::string percent_nul(\"\\0X\\0\\0X%\\0\\0X\\0\\0X\\0\", 13);\n  EXPECT_EQ(percent_nul,\n            absl::time_internal::cctz::format(percent_nul, tp, tz));\n\n  // NULs amongst ordinary text plus a non-internal specifier (%I).\n  EXPECT_EQ(std::string(\"X\\0\\0\\0X12\\0X\\0\\0\\0X\", 13),\n            absl::time_internal::cctz::format(\n                std::string(\"X\\0\\0\\0X%I\\0X\\0\\0\\0X\", 13), tp, tz));\n\n#if defined(__linux__) && defined(__GLIBC__)\n  // Depending upon strftime() behavior on \"%E\"\n  // and \"%O\", \"%E\\0\" and \"%0\\0\" produce themselves.\n  std::string percent_E_nul(\"abc%E\\0xyz\", 9);\n  EXPECT_EQ(percent_E_nul,\n            absl::time_internal::cctz::format(percent_E_nul, tp, tz));\n  std::string percent_O_nul(\"abc%O\\0xyz\", 9);\n  EXPECT_EQ(percent_O_nul,\n            absl::time_internal::cctz::format(percent_O_nul, tp, tz));\n#endif\n}\n\n//\n// Testing parse()\n//\n\nTEST(Parse, TimePointResolution) {\n  const char kFmt[] = \"%H:%M:%E*S\";\n  const time_zone utc = utc_time_zone();\n\n  time_point<chrono::nanoseconds> tp_ns;\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123456789\", utc, &tp_ns));\n  EXPECT_EQ(\"03:04:05.123456789\",\n            absl::time_internal::cctz::format(kFmt, tp_ns, utc));\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123456\", utc, &tp_ns));\n  EXPECT_EQ(\"03:04:05.123456\",\n            absl::time_internal::cctz::format(kFmt, tp_ns, utc));\n\n  time_point<chrono::microseconds> tp_us;\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123456789\", utc, &tp_us));\n  EXPECT_EQ(\"03:04:05.123456\",\n            absl::time_internal::cctz::format(kFmt, tp_us, utc));\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123456\", utc, &tp_us));\n  EXPECT_EQ(\"03:04:05.123456\",\n            absl::time_internal::cctz::format(kFmt, tp_us, utc));\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123\", utc, &tp_us));\n  EXPECT_EQ(\"03:04:05.123\",\n            absl::time_internal::cctz::format(kFmt, tp_us, utc));\n\n  time_point<chrono::milliseconds> tp_ms;\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123456\", utc, &tp_ms));\n  EXPECT_EQ(\"03:04:05.123\",\n            absl::time_internal::cctz::format(kFmt, tp_ms, utc));\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123\", utc, &tp_ms));\n  EXPECT_EQ(\"03:04:05.123\",\n            absl::time_internal::cctz::format(kFmt, tp_ms, utc));\n  EXPECT_TRUE(parse(kFmt, \"03:04:05\", utc, &tp_ms));\n  EXPECT_EQ(\"03:04:05\", absl::time_internal::cctz::format(kFmt, tp_ms, utc));\n\n  time_point<chrono::seconds> tp_s;\n  EXPECT_TRUE(parse(kFmt, \"03:04:05.123\", utc, &tp_s));\n  EXPECT_EQ(\"03:04:05\", absl::time_internal::cctz::format(kFmt, tp_s, utc));\n  EXPECT_TRUE(parse(kFmt, \"03:04:05\", utc, &tp_s));\n  EXPECT_EQ(\"03:04:05\", absl::time_internal::cctz::format(kFmt, tp_s, utc));\n\n  time_point<chrono::minutes> tp_m;\n  EXPECT_TRUE(parse(kFmt, \"03:04:05\", utc, &tp_m));\n  EXPECT_EQ(\"03:04:00\", absl::time_internal::cctz::format(kFmt, tp_m, utc));\n\n  time_point<chrono::hours> tp_h;\n  EXPECT_TRUE(parse(kFmt, \"03:04:05\", utc, &tp_h));\n  EXPECT_EQ(\"03:00:00\", absl::time_internal::cctz::format(kFmt, tp_h, utc));\n}\n\nTEST(Parse, TimePointExtendedResolution) {\n  const char kFmt[] = \"%H:%M:%E*S\";\n  const time_zone utc = utc_time_zone();\n\n  time_point<absl::time_internal::cctz::seconds> tp;\n  detail::femtoseconds fs;\n  EXPECT_TRUE(detail::parse(kFmt, \"12:34:56.123456789012345\", utc, &tp, &fs));\n  EXPECT_EQ(\"12:34:56.123456789012345\", detail::format(kFmt, tp, fs, utc));\n  EXPECT_TRUE(detail::parse(kFmt, \"12:34:56.012345678901234\", utc, &tp, &fs));\n  EXPECT_EQ(\"12:34:56.012345678901234\", detail::format(kFmt, tp, fs, utc));\n  EXPECT_TRUE(detail::parse(kFmt, \"12:34:56.001234567890123\", utc, &tp, &fs));\n  EXPECT_EQ(\"12:34:56.001234567890123\", detail::format(kFmt, tp, fs, utc));\n  EXPECT_TRUE(detail::parse(kFmt, \"12:34:56.000000000000123\", utc, &tp, &fs));\n  EXPECT_EQ(\"12:34:56.000000000000123\", detail::format(kFmt, tp, fs, utc));\n  EXPECT_TRUE(detail::parse(kFmt, \"12:34:56.000000000000012\", utc, &tp, &fs));\n  EXPECT_EQ(\"12:34:56.000000000000012\", detail::format(kFmt, tp, fs, utc));\n  EXPECT_TRUE(detail::parse(kFmt, \"12:34:56.000000000000001\", utc, &tp, &fs));\n  EXPECT_EQ(\"12:34:56.000000000000001\", detail::format(kFmt, tp, fs, utc));\n}\n\nTEST(Parse, Basics) {\n  time_zone tz = utc_time_zone();\n  time_point<chrono::nanoseconds> tp =\n      chrono::system_clock::from_time_t(1234567890);\n\n  // Simple edge cases.\n  EXPECT_TRUE(parse(\"\", \"\", tz, &tp));\n  EXPECT_EQ(chrono::system_clock::from_time_t(0), tp);  // everything defaulted\n  EXPECT_TRUE(parse(\" \", \" \", tz, &tp));\n  EXPECT_TRUE(parse(\"  \", \"  \", tz, &tp));\n  EXPECT_TRUE(parse(\"x\", \"x\", tz, &tp));\n  EXPECT_TRUE(parse(\"xxx\", \"xxx\", tz, &tp));\n\n  EXPECT_TRUE(\n      parse(\"%Y-%m-%d %H:%M:%S %z\", \"2013-06-28 19:08:09 -0800\", tz, &tp));\n  ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, \"UTC\");\n}\n\nTEST(Parse, WithTimeZone) {\n  time_zone tz;\n  EXPECT_TRUE(load_time_zone(\"America/Los_Angeles\", &tz));\n  time_point<chrono::nanoseconds> tp;\n\n  // We can parse a string without a UTC offset if we supply a timezone.\n  EXPECT_TRUE(parse(\"%Y-%m-%d %H:%M:%S\", \"2013-06-28 19:08:09\", tz, &tp));\n  ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, \"PDT\");\n\n  // But the timezone is ignored when a UTC offset is present.\n  EXPECT_TRUE(parse(\"%Y-%m-%d %H:%M:%S %z\", \"2013-06-28 19:08:09 +0800\",\n                    utc_time_zone(), &tp));\n  ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, \"PDT\");\n\n  // Check a skipped time (a Spring DST transition). parse() uses the\n  // pre-transition offset.\n  EXPECT_TRUE(parse(\"%Y-%m-%d %H:%M:%S\", \"2011-03-13 02:15:00\", tz, &tp));\n  ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, \"PDT\");\n\n  // Check a repeated time (a Fall DST transition).  parse() uses the\n  // pre-transition offset.\n  EXPECT_TRUE(parse(\"%Y-%m-%d %H:%M:%S\", \"2011-11-06 01:15:00\", tz, &tp));\n  ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, \"PDT\");\n}\n\nTEST(Parse, LeapSecond) {\n  time_zone tz;\n  EXPECT_TRUE(load_time_zone(\"America/Los_Angeles\", &tz));\n  time_point<chrono::nanoseconds> tp;\n\n  // \":59\" -> \":59\"\n  EXPECT_TRUE(parse(RFC3339_full, \"2013-06-28T07:08:59-08:00\", tz, &tp));\n  ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, \"PDT\");\n\n  // \":59.5\" -> \":59.5\"\n  EXPECT_TRUE(parse(RFC3339_full, \"2013-06-28T07:08:59.5-08:00\", tz, &tp));\n  ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, \"PDT\");\n\n  // \":60\" -> \":00\"\n  EXPECT_TRUE(parse(RFC3339_full, \"2013-06-28T07:08:60-08:00\", tz, &tp));\n  ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, \"PDT\");\n\n  // \":60.5\" -> \":00.0\"\n  EXPECT_TRUE(parse(RFC3339_full, \"2013-06-28T07:08:60.5-08:00\", tz, &tp));\n  ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, \"PDT\");\n\n  // \":61\" -> error\n  EXPECT_FALSE(parse(RFC3339_full, \"2013-06-28T07:08:61-08:00\", tz, &tp));\n}\n\nTEST(Parse, ErrorCases) {\n  const time_zone tz = utc_time_zone();\n  auto tp = chrono::system_clock::from_time_t(0);\n\n  // No data.\n  EXPECT_FALSE(parse(\"X\", \"\", tz, &tp));\n\n  // Illegal trailing data.\n  EXPECT_FALSE(parse(\"%S\", \"123\", tz, &tp));\n\n  // Can't parse an illegal format specifier.\n  EXPECT_FALSE(parse(\"%Q\", \"x\", tz, &tp));\n\n  // Fails because of trailing, unparsed data \"blah\".\n  EXPECT_FALSE(parse(\"%m-%d\", \"2-3 blah\", tz, &tp));\n\n  // Trailing whitespace is allowed.\n  EXPECT_TRUE(parse(\"%m-%d\", \"2-3  \", tz, &tp));\n  EXPECT_EQ(2, convert(tp, utc_time_zone()).month());\n  EXPECT_EQ(3, convert(tp, utc_time_zone()).day());\n\n  // Feb 31 requires normalization.\n  EXPECT_FALSE(parse(\"%m-%d\", \"2-31\", tz, &tp));\n\n  // Check that we cannot have spaces in UTC offsets.\n  EXPECT_TRUE(parse(\"%z\", \"-0203\", tz, &tp));\n  EXPECT_FALSE(parse(\"%z\", \"- 2 3\", tz, &tp));\n  EXPECT_TRUE(parse(\"%Ez\", \"-02:03\", tz, &tp));\n  EXPECT_FALSE(parse(\"%Ez\", \"- 2: 3\", tz, &tp));\n\n  // Check that we reject other malformed UTC offsets.\n  EXPECT_FALSE(parse(\"%Ez\", \"+-08:00\", tz, &tp));\n  EXPECT_FALSE(parse(\"%Ez\", \"-+08:00\", tz, &tp));\n\n  // Check that we do not accept \"-0\" in fields that allow zero.\n  EXPECT_FALSE(parse(\"%Y\", \"-0\", tz, &tp));\n  EXPECT_FALSE(parse(\"%E4Y\", \"-0\", tz, &tp));\n  EXPECT_FALSE(parse(\"%H\", \"-0\", tz, &tp));\n  EXPECT_FALSE(parse(\"%M\", \"-0\", tz, &tp));\n  EXPECT_FALSE(parse(\"%S\", \"-0\", tz, &tp));\n  EXPECT_FALSE(parse(\"%z\", \"+-000\", tz, &tp));\n  EXPECT_FALSE(parse(\"%Ez\", \"+-0:00\", tz, &tp));\n  EXPECT_FALSE(parse(\"%z\", \"-00-0\", tz, &tp));\n  EXPECT_FALSE(parse(\"%Ez\", \"-00:-0\", tz, &tp));\n}\n\nTEST(Parse, PosixConversions) {\n  time_zone tz = utc_time_zone();\n  auto tp = chrono::system_clock::from_time_t(0);\n  const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%d\", \"15\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).day());\n\n  // %e is an extension, but is supported internally.\n  tp = reset;\n  EXPECT_TRUE(parse(\"%e\", \"15\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%H\", \"17\", tz, &tp));\n  EXPECT_EQ(17, convert(tp, tz).hour());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%I\", \"5\", tz, &tp));\n  EXPECT_EQ(5, convert(tp, tz).hour());\n\n  // %j is parsed but ignored.\n  EXPECT_TRUE(parse(\"%j\", \"32\", tz, &tp));\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%m\", \"11\", tz, &tp));\n  EXPECT_EQ(11, convert(tp, tz).month());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%M\", \"33\", tz, &tp));\n  EXPECT_EQ(33, convert(tp, tz).minute());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%S\", \"55\", tz, &tp));\n  EXPECT_EQ(55, convert(tp, tz).second());\n\n  // %U is parsed but ignored.\n  EXPECT_TRUE(parse(\"%U\", \"15\", tz, &tp));\n\n  // %w is parsed but ignored.\n  EXPECT_TRUE(parse(\"%w\", \"2\", tz, &tp));\n\n  // %W is parsed but ignored.\n  EXPECT_TRUE(parse(\"%W\", \"22\", tz, &tp));\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%y\", \"04\", tz, &tp));\n  EXPECT_EQ(2004, convert(tp, tz).year());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Y\", \"2004\", tz, &tp));\n  EXPECT_EQ(2004, convert(tp, tz).year());\n\n  EXPECT_TRUE(parse(\"%%\", \"%\", tz, &tp));\n\n#if defined(__linux__)\n  // SU/C99/TZ extensions\n\n  // Because we handle each (non-internal) specifier in a separate call\n  // to strptime(), there is no way to group %C and %y together.  So we\n  // just skip the %C/%y case.\n#if 0\n  tp = reset;\n  EXPECT_TRUE(parse(\"%C %y\", \"20 04\", tz, &tp));\n  EXPECT_EQ(2004, convert(tp, tz).year());\n#endif\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%D\", \"02/03/04\", tz, &tp));\n  EXPECT_EQ(2, convert(tp, tz).month());\n  EXPECT_EQ(3, convert(tp, tz).day());\n  EXPECT_EQ(2004, convert(tp, tz).year());\n\n  EXPECT_TRUE(parse(\"%n\", \"\\n\", tz, &tp));\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%R\", \"03:44\", tz, &tp));\n  EXPECT_EQ(3, convert(tp, tz).hour());\n  EXPECT_EQ(44, convert(tp, tz).minute());\n\n  EXPECT_TRUE(parse(\"%t\", \"\\t\\v\\f\\n\\r \", tz, &tp));\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%T\", \"03:44:55\", tz, &tp));\n  EXPECT_EQ(3, convert(tp, tz).hour());\n  EXPECT_EQ(44, convert(tp, tz).minute());\n  EXPECT_EQ(55, convert(tp, tz).second());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%s\", \"1234567890\", tz, &tp));\n  EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);\n\n  // %s conversion, like %z/%Ez, pays no heed to the optional zone.\n  time_zone lax;\n  EXPECT_TRUE(load_time_zone(\"America/Los_Angeles\", &lax));\n  tp = reset;\n  EXPECT_TRUE(parse(\"%s\", \"1234567890\", lax, &tp));\n  EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);\n\n  // This is most important when the time has the same YMDhms\n  // breakdown in the zone as some other time.  For example, ...\n  //  1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT)\n  //  1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST)\n  tp = reset;\n  EXPECT_TRUE(parse(\"%s\", \"1414917000\", lax, &tp));\n  EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp);\n  tp = reset;\n  EXPECT_TRUE(parse(\"%s\", \"1414920600\", lax, &tp));\n  EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp);\n#endif\n}\n\nTEST(Parse, LocaleSpecific) {\n  time_zone tz = utc_time_zone();\n  auto tp = chrono::system_clock::from_time_t(0);\n  const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);\n\n  // %a is parsed but ignored.\n  EXPECT_TRUE(parse(\"%a\", \"Mon\", tz, &tp));\n\n  // %A is parsed but ignored.\n  EXPECT_TRUE(parse(\"%A\", \"Monday\", tz, &tp));\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%b\", \"Feb\", tz, &tp));\n  EXPECT_EQ(2, convert(tp, tz).month());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%B\", \"February\", tz, &tp));\n  EXPECT_EQ(2, convert(tp, tz).month());\n\n  // %p is parsed but ignored if it's alone.  But it's used with %I.\n  EXPECT_TRUE(parse(\"%p\", \"AM\", tz, &tp));\n  tp = reset;\n  EXPECT_TRUE(parse(\"%I %p\", \"5 PM\", tz, &tp));\n  EXPECT_EQ(17, convert(tp, tz).hour());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%x\", \"02/03/04\", tz, &tp));\n  if (convert(tp, tz).month() == 2) {\n    EXPECT_EQ(3, convert(tp, tz).day());\n  } else {\n    EXPECT_EQ(2, convert(tp, tz).day());\n    EXPECT_EQ(3, convert(tp, tz).month());\n  }\n  EXPECT_EQ(2004, convert(tp, tz).year());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%X\", \"15:44:55\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).hour());\n  EXPECT_EQ(44, convert(tp, tz).minute());\n  EXPECT_EQ(55, convert(tp, tz).second());\n\n#if defined(__linux__)\n  // SU/C99/TZ extensions\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%h\", \"Feb\", tz, &tp));\n  EXPECT_EQ(2, convert(tp, tz).month());  // Equivalent to %b\n\n#if defined(__GLIBC__)\n  tp = reset;\n  EXPECT_TRUE(parse(\"%l %p\", \"5 PM\", tz, &tp));\n  EXPECT_EQ(17, convert(tp, tz).hour());\n#endif\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%r\", \"03:44:55 PM\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).hour());\n  EXPECT_EQ(44, convert(tp, tz).minute());\n  EXPECT_EQ(55, convert(tp, tz).second());\n\n#if defined(__GLIBC__)\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Ec\", \"Tue Nov 19 05:06:07 2013\", tz, &tp));\n  EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp);\n\n  // Modified conversion specifiers %E_\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Ex\", \"02/03/04\", tz, &tp));\n  EXPECT_EQ(2, convert(tp, tz).month());\n  EXPECT_EQ(3, convert(tp, tz).day());\n  EXPECT_EQ(2004, convert(tp, tz).year());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%EX\", \"15:44:55\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).hour());\n  EXPECT_EQ(44, convert(tp, tz).minute());\n  EXPECT_EQ(55, convert(tp, tz).second());\n\n  // %Ey, the year offset from %EC, doesn't really make sense alone as there\n  // is no way to represent it in tm_year (%EC is not simply the century).\n  // Yet, because we handle each (non-internal) specifier in a separate call\n  // to strptime(), there is no way to group %EC and %Ey either.  So we just\n  // skip the %EC and %Ey cases.\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%EY\", \"2004\", tz, &tp));\n  EXPECT_EQ(2004, convert(tp, tz).year());\n\n  // Modified conversion specifiers %O_\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Od\", \"15\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).day());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Oe\", \"15\", tz, &tp));\n  EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%OH\", \"17\", tz, &tp));\n  EXPECT_EQ(17, convert(tp, tz).hour());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%OI\", \"5\", tz, &tp));\n  EXPECT_EQ(5, convert(tp, tz).hour());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Om\", \"11\", tz, &tp));\n  EXPECT_EQ(11, convert(tp, tz).month());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%OM\", \"33\", tz, &tp));\n  EXPECT_EQ(33, convert(tp, tz).minute());\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%OS\", \"55\", tz, &tp));\n  EXPECT_EQ(55, convert(tp, tz).second());\n\n  // %OU is parsed but ignored.\n  EXPECT_TRUE(parse(\"%OU\", \"15\", tz, &tp));\n\n  // %Ow is parsed but ignored.\n  EXPECT_TRUE(parse(\"%Ow\", \"2\", tz, &tp));\n\n  // %OW is parsed but ignored.\n  EXPECT_TRUE(parse(\"%OW\", \"22\", tz, &tp));\n\n  tp = reset;\n  EXPECT_TRUE(parse(\"%Oy\", \"04\", tz, &tp));\n  EXPECT_EQ(2004, convert(tp, tz).year());\n#endif\n#endif\n}\n\nTEST(Parse, ExtendedSeconds) {\n  const time_zone tz = utc_time_zone();\n  const time_point<chrono::nanoseconds> unix_epoch =\n      chrono::system_clock::from_time_t(0);\n\n  // All %E<prec>S cases are treated the same as %E*S on input.\n  auto precisions = {\"*\", \"0\", \"1\",  \"2\",  \"3\",  \"4\",  \"5\",  \"6\", \"7\",\n                     \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\"};\n  for (const std::string prec : precisions) {\n    const std::string fmt = \"%E\" + prec + \"S\";\n    SCOPED_TRACE(fmt);\n    time_point<chrono::nanoseconds> tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"5\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.0\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.00\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.6\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.60\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.600\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.67\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.670\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"05.678\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp);\n  }\n\n  // Here is a \"%E*S\" case we got wrong for a while.  The fractional\n  // part of the first instant is less than 2^31 and was correctly\n  // parsed, while the second (and any subsecond field >=2^31) failed.\n  time_point<chrono::nanoseconds> tp = unix_epoch;\n  EXPECT_TRUE(parse(\"%E*S\", \"0.2147483647\", tz, &tp));\n  EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);\n  tp = unix_epoch;\n  EXPECT_TRUE(parse(\"%E*S\", \"0.2147483648\", tz, &tp));\n  EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);\n\n  // We should also be able to specify long strings of digits far\n  // beyond the current resolution and have them convert the same way.\n  tp = unix_epoch;\n  EXPECT_TRUE(parse(\n      \"%E*S\", \"0.214748364801234567890123456789012345678901234567890123456789\",\n      tz, &tp));\n  EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);\n}\n\nTEST(Parse, ExtendedSecondsScan) {\n  const time_zone tz = utc_time_zone();\n  time_point<chrono::nanoseconds> tp;\n  for (int ms = 0; ms < 1000; ms += 111) {\n    for (int us = 0; us < 1000; us += 27) {\n      const int micros = ms * 1000 + us;\n      for (int ns = 0; ns < 1000; ns += 9) {\n        const auto expected = chrono::system_clock::from_time_t(0) +\n                              chrono::nanoseconds(micros * 1000 + ns);\n        std::ostringstream oss;\n        oss << \"0.\" << std::setfill('0') << std::setw(3);\n        oss << ms << std::setw(3) << us << std::setw(3) << ns;\n        const std::string input = oss.str();\n        EXPECT_TRUE(parse(\"%E*S\", input, tz, &tp));\n        EXPECT_EQ(expected, tp) << input;\n      }\n    }\n  }\n}\n\nTEST(Parse, ExtendedSubeconds) {\n  const time_zone tz = utc_time_zone();\n  const time_point<chrono::nanoseconds> unix_epoch =\n      chrono::system_clock::from_time_t(0);\n\n  // All %E<prec>f cases are treated the same as %E*f on input.\n  auto precisions = {\"*\", \"0\", \"1\",  \"2\",  \"3\",  \"4\",  \"5\",  \"6\", \"7\",\n                     \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\"};\n  for (const std::string prec : precisions) {\n    const std::string fmt = \"%E\" + prec + \"f\";\n    SCOPED_TRACE(fmt);\n    time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1);\n    EXPECT_TRUE(parse(fmt, \"\", tz, &tp));\n    EXPECT_EQ(unix_epoch, tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"6\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"60\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"600\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"67\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"670\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"678\", tz, &tp));\n    EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp);\n    tp = unix_epoch;\n    EXPECT_TRUE(parse(fmt, \"6789\", tz, &tp));\n    EXPECT_EQ(\n        unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp);\n  }\n\n  // Here is a \"%E*f\" case we got wrong for a while.  The fractional\n  // part of the first instant is less than 2^31 and was correctly\n  // parsed, while the second (and any subsecond field >=2^31) failed.\n  time_point<chrono::nanoseconds> tp = unix_epoch;\n  EXPECT_TRUE(parse(\"%E*f\", \"2147483647\", tz, &tp));\n  EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);\n  tp = unix_epoch;\n  EXPECT_TRUE(parse(\"%E*f\", \"2147483648\", tz, &tp));\n  EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);\n\n  // We should also be able to specify long strings of digits far\n  // beyond the current resolution and have them convert the same way.\n  tp = unix_epoch;\n  EXPECT_TRUE(parse(\n      \"%E*f\", \"214748364801234567890123456789012345678901234567890123456789\",\n      tz, &tp));\n  EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);\n}\n\nTEST(Parse, ExtendedSubecondsScan) {\n  time_point<chrono::nanoseconds> tp;\n  const time_zone tz = utc_time_zone();\n  for (int ms = 0; ms < 1000; ms += 111) {\n    for (int us = 0; us < 1000; us += 27) {\n      const int micros = ms * 1000 + us;\n      for (int ns = 0; ns < 1000; ns += 9) {\n        std::ostringstream oss;\n        oss << std::setfill('0') << std::setw(3) << ms;\n        oss << std::setw(3) << us << std::setw(3) << ns;\n        const std::string nanos = oss.str();\n        const auto expected = chrono::system_clock::from_time_t(0) +\n                              chrono::nanoseconds(micros * 1000 + ns);\n        for (int ps = 0; ps < 1000; ps += 250) {\n          std::ostringstream ps_oss;\n          oss << std::setfill('0') << std::setw(3) << ps;\n          const std::string input = nanos + ps_oss.str() + \"999\";\n          EXPECT_TRUE(parse(\"%E*f\", input, tz, &tp));\n          EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;\n        }\n      }\n    }\n  }\n}\n\nTEST(Parse, ExtendedOffset) {\n  const time_zone utc = utc_time_zone();\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  EXPECT_TRUE(parse(\"%Ez\", \"+00:00\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(\"%Ez\", \"-12:34\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);\n  EXPECT_TRUE(parse(\"%Ez\", \"+12:34\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);\n  EXPECT_FALSE(parse(\"%Ez\", \"-12:3\", utc, &tp));\n\n  for (auto fmt : {\"%Ez\", \"%z\"}) {\n    EXPECT_TRUE(parse(fmt, \"+0000\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-1234\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+1234\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-123\", utc, &tp));\n\n    EXPECT_TRUE(parse(fmt, \"+00\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-12\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+12\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-1\", utc, &tp));\n  }\n}\n\nTEST(Parse, ExtendedSecondOffset) {\n  const time_zone utc = utc_time_zone();\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  for (auto fmt : {\"%Ez\", \"%E*z\", \"%:z\", \"%::z\", \"%:::z\"}) {\n    EXPECT_TRUE(parse(fmt, \"+00:00:00\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-12:34:56\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+12:34:56\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-12:34:5\", utc, &tp));\n\n    EXPECT_TRUE(parse(fmt, \"+000000\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-123456\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+123456\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-12345\", utc, &tp));\n\n    EXPECT_TRUE(parse(fmt, \"+00:00\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-12:34\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+12:34\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-12:3\", utc, &tp));\n\n    EXPECT_TRUE(parse(fmt, \"+0000\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-1234\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+1234\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-123\", utc, &tp));\n\n    EXPECT_TRUE(parse(fmt, \"+00\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"-12\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);\n    EXPECT_TRUE(parse(fmt, \"+12\", utc, &tp));\n    EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);\n    EXPECT_FALSE(parse(fmt, \"-1\", utc, &tp));\n  }\n}\n\nTEST(Parse, ExtendedYears) {\n  const time_zone utc = utc_time_zone();\n  const char e4y_fmt[] = \"%E4Y%m%d\";  // no separators\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  // %E4Y consumes exactly four chars, including any sign.\n  EXPECT_TRUE(parse(e4y_fmt, \"-9991127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"-0991127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"-0091127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"-0011127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"00001127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"00011127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"00091127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"00991127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"09991127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp);\n  EXPECT_TRUE(parse(e4y_fmt, \"99991127\", utc, &tp));\n  EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp);\n\n  // When the year is outside [-999:9999], the parse fails.\n  EXPECT_FALSE(parse(e4y_fmt, \"-10001127\", utc, &tp));\n  EXPECT_FALSE(parse(e4y_fmt, \"100001127\", utc, &tp));\n}\n\nTEST(Parse, RFC3339Format) {\n  const time_zone tz = utc_time_zone();\n  time_point<chrono::nanoseconds> tp;\n  EXPECT_TRUE(parse(RFC3339_sec, \"2014-02-12T20:21:00+00:00\", tz, &tp));\n  ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, \"UTC\");\n\n  // Check that %ET also accepts \"t\".\n  time_point<chrono::nanoseconds> tp2;\n  EXPECT_TRUE(parse(RFC3339_sec, \"2014-02-12t20:21:00+00:00\", tz, &tp2));\n  EXPECT_EQ(tp, tp2);\n\n  // Check that %Ez also accepts \"Z\" as a synonym for \"+00:00\".\n  time_point<chrono::nanoseconds> tp3;\n  EXPECT_TRUE(parse(RFC3339_sec, \"2014-02-12T20:21:00Z\", tz, &tp3));\n  EXPECT_EQ(tp, tp3);\n\n  // Check that %Ez also accepts \"z\" as a synonym for \"+00:00\".\n  time_point<chrono::nanoseconds> tp4;\n  EXPECT_TRUE(parse(RFC3339_sec, \"2014-02-12T20:21:00z\", tz, &tp4));\n  EXPECT_EQ(tp, tp4);\n}\n\nTEST(Parse, Week) {\n  const time_zone utc = utc_time_zone();\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2017-01-7\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2017-00-0\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2017-53-7\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2017-52-0\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2018-00-1\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2018-01-1\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2018-52-1\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2018-53-1\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2019-00-2\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2019-00-2\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2019-52-2\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2019-52-2\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n}\n\nTEST(Parse, WeekYearShift) {\n  // %U/%W conversions with week values in {0, 52, 53} can slip\n  // into the previous/following calendar years.\n  const time_zone utc = utc_time_zone();\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2020-00-2\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2020-00-2\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc);\n  EXPECT_TRUE(parse(\"%Y-%U-%u\", \"2020-52-5\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n  EXPECT_TRUE(parse(\"%Y-%W-%w\", \"2020-52-5\", utc, &tp));\n  EXPECT_EQ(exp, tp);\n\n  // Slipping into the previous/following calendar years should fail when\n  // we're already at the extremes.\n  EXPECT_FALSE(parse(\"%Y-%U-%u\", \"-9223372036854775808-0-7\", utc, &tp));\n  EXPECT_FALSE(parse(\"%Y-%U-%u\", \"9223372036854775807-53-7\", utc, &tp));\n}\n\nTEST(Parse, NULsInFormatAndInputStrings) {\n  const time_zone utc = utc_time_zone();\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  // Check that NULs are parsed just like any other chars.\n  EXPECT_FALSE(\n      parse(std::string(\"abc\\0def\", 7), std::string(\"abc\\0xyz\", 7), utc, &tp));\n  EXPECT_FALSE(\n      parse(std::string(\"%Y\\0def\", 6), std::string(\"2026\\0xyz\", 8), utc, &tp));\n  EXPECT_TRUE(\n      parse(std::string(\"%Y\\0xyz\", 6), std::string(\"2026\\0xyz\", 8), utc, &tp));\n  ExpectTime(tp, utc, 2026, 1, 1, 0, 0, 0, 0, false, \"UTC\");\n\n  // All NULs.\n  std::string nuls(32, '\\0');\n  EXPECT_TRUE(parse(nuls, nuls, utc, &tp));\n  ExpectTime(tp, utc, 1970, 1, 1, 0, 0, 0, 0, false, \"UTC\");\n\n  // The \"%\\0\" specifier never matches, even on the empty string and itself.\n  std::string percent_nul(\"%\\0\", 2);\n  EXPECT_FALSE(parse(percent_nul, \"\", utc, &tp));\n  EXPECT_FALSE(parse(percent_nul, percent_nul, utc, &tp));\n\n#if defined(__linux__) && defined(__GLIBC__)\n  // Depending upon strptime() behavior on \"%E\"\n  // and \"%O\", \"%E\\0\" and \"%0\\0\" also never match.\n  std::string percent_E_nul(\"%E\\0\", 3);\n  EXPECT_FALSE(parse(percent_E_nul, \"\", utc, &tp));\n  EXPECT_FALSE(parse(percent_E_nul, percent_E_nul, utc, &tp));\n  std::string percent_O_nul(\"%O\\0\", 3);\n  EXPECT_FALSE(parse(percent_O_nul, \"\", utc, &tp));\n  EXPECT_FALSE(parse(percent_O_nul, percent_O_nul, utc, &tp));\n#endif\n}\n\nTEST(Parse, MaxRange) {\n  const time_zone utc = utc_time_zone();\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  // tests the upper limit using +00:00 offset\n  EXPECT_TRUE(\n      parse(RFC3339_sec, \"292277026596-12-04T15:30:07+00:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());\n  EXPECT_FALSE(\n      parse(RFC3339_sec, \"292277026596-12-04T15:30:08+00:00\", utc, &tp));\n\n  // tests the upper limit using -01:00 offset\n  EXPECT_TRUE(\n      parse(RFC3339_sec, \"292277026596-12-04T14:30:07-01:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());\n  EXPECT_FALSE(\n      parse(RFC3339_sec, \"292277026596-12-04T14:30:08-01:00\", utc, &tp));\n\n  // tests the lower limit using +00:00 offset\n  EXPECT_TRUE(\n      parse(RFC3339_sec, \"-292277022657-01-27T08:29:52+00:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min());\n  EXPECT_FALSE(\n      parse(RFC3339_sec, \"-292277022657-01-27T08:29:51+00:00\", utc, &tp));\n\n  // tests the lower limit using +01:00 offset\n  EXPECT_TRUE(\n      parse(RFC3339_sec, \"-292277022657-01-27T09:29:52+01:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min());\n  EXPECT_FALSE(\n      parse(RFC3339_sec, \"-292277022657-01-27T08:29:51+01:00\", utc, &tp));\n\n  // tests max/min civil-second overflow\n  EXPECT_FALSE(\n      parse(RFC3339_sec, \"9223372036854775807-12-31T23:59:59-00:01\", utc, &tp));\n  EXPECT_FALSE(parse(RFC3339_sec, \"-9223372036854775808-01-01T00:00:00+00:01\",\n                     utc, &tp));\n}\n\nTEST(Parse, TimePointOverflow) {\n  const time_zone utc = utc_time_zone();\n\n  using D = chrono::duration<std::int64_t, std::nano>;\n  time_point<D> tp;\n\n  EXPECT_TRUE(\n      parse(RFC3339_full, \"2262-04-11T23:47:16.8547758079+00:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<D>::max());\n  EXPECT_EQ(\"2262-04-11T23:47:16.854775807+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, utc));\n#if 0\n  // TODO(#199): Will fail until cctz::parse() properly detects overflow.\n  EXPECT_FALSE(\n      parse(RFC3339_full, \"2262-04-11T23:47:16.8547758080+00:00\", utc, &tp));\n  EXPECT_TRUE(\n      parse(RFC3339_full, \"1677-09-21T00:12:43.1452241920+00:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<D>::min());\n  EXPECT_EQ(\"1677-09-21T00:12:43.145224192+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, utc));\n  EXPECT_FALSE(\n      parse(RFC3339_full, \"1677-09-21T00:12:43.1452241919+00:00\", utc, &tp));\n#endif\n\n  using DS = chrono::duration<std::int8_t, chrono::seconds::period>;\n  time_point<DS> stp;\n\n  EXPECT_TRUE(parse(RFC3339_full, \"1970-01-01T00:02:07.9+00:00\", utc, &stp));\n  EXPECT_EQ(stp, time_point<DS>::max());\n  EXPECT_EQ(\"1970-01-01T00:02:07+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, stp, utc));\n  EXPECT_FALSE(parse(RFC3339_full, \"1970-01-01T00:02:08+00:00\", utc, &stp));\n\n  EXPECT_TRUE(parse(RFC3339_full, \"1969-12-31T23:57:52+00:00\", utc, &stp));\n  EXPECT_EQ(stp, time_point<DS>::min());\n  EXPECT_EQ(\"1969-12-31T23:57:52+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, stp, utc));\n  EXPECT_FALSE(parse(RFC3339_full, \"1969-12-31T23:57:51.9+00:00\", utc, &stp));\n\n  using DM = chrono::duration<std::int8_t, chrono::minutes::period>;\n  time_point<DM> mtp;\n\n  EXPECT_TRUE(parse(RFC3339_full, \"1970-01-01T02:07:59+00:00\", utc, &mtp));\n  EXPECT_EQ(mtp, time_point<DM>::max());\n  EXPECT_EQ(\"1970-01-01T02:07:00+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, mtp, utc));\n  EXPECT_FALSE(parse(RFC3339_full, \"1970-01-01T02:08:00+00:00\", utc, &mtp));\n\n  EXPECT_TRUE(parse(RFC3339_full, \"1969-12-31T21:52:00+00:00\", utc, &mtp));\n  EXPECT_EQ(mtp, time_point<DM>::min());\n  EXPECT_EQ(\"1969-12-31T21:52:00+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, mtp, utc));\n  EXPECT_FALSE(parse(RFC3339_full, \"1969-12-31T21:51:59+00:00\", utc, &mtp));\n}\n\nTEST(Parse, TimePointOverflowFloor) {\n  const time_zone utc = utc_time_zone();\n\n  using D = chrono::duration<std::int64_t, std::micro>;\n  time_point<D> tp;\n\n  EXPECT_TRUE(\n      parse(RFC3339_full, \"294247-01-10T04:00:54.7758079+00:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<D>::max());\n  EXPECT_EQ(\"294247-01-10T04:00:54.775807+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, utc));\n#if 0\n  // TODO(#199): Will fail until cctz::parse() properly detects overflow.\n  EXPECT_FALSE(\n      parse(RFC3339_full, \"294247-01-10T04:00:54.7758080+00:00\", utc, &tp));\n  EXPECT_TRUE(\n      parse(RFC3339_full, \"-290308-12-21T19:59:05.2241920+00:00\", utc, &tp));\n  EXPECT_EQ(tp, time_point<D>::min());\n  EXPECT_EQ(\"-290308-12-21T19:59:05.224192+00:00\",\n            absl::time_internal::cctz::format(RFC3339_full, tp, utc));\n  EXPECT_FALSE(\n      parse(RFC3339_full, \"-290308-12-21T19:59:05.2241919+00:00\", utc, &tp));\n#endif\n}\n\n//\n// Roundtrip test for format()/parse().\n//\n\nTEST(FormatParse, RoundTrip) {\n  time_zone lax;\n  EXPECT_TRUE(load_time_zone(\"America/Los_Angeles\", &lax));\n  const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax);\n  const auto subseconds = chrono::nanoseconds(654321);\n\n  // No format specifiers, but include NUL.\n  {\n    time_point<chrono::nanoseconds> out;\n    const auto fmt = std::string(\"\\0\\1\\2\\3\\4\\5\\6\\7abcdefgh01234567\");\n    const auto s = absl::time_internal::cctz::format(fmt, in, lax);\n    EXPECT_TRUE(parse(fmt, s, lax, &out)) << s;\n  }\n\n  // RFC3339, which renders subseconds.\n  {\n    time_point<chrono::nanoseconds> out;\n    const auto s =\n        absl::time_internal::cctz::format(RFC3339_full, in + subseconds, lax);\n    EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s;\n    EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez\n  }\n\n  // RFC1123, which only does whole seconds.\n  {\n    time_point<chrono::nanoseconds> out;\n    const auto s = absl::time_internal::cctz::format(RFC1123_full, in, lax);\n    EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s;\n    EXPECT_EQ(in, out);  // RFC1123_full includes %z\n  }\n\n#if defined(_WIN32) || defined(_WIN64)\n  // Initial investigations indicate the %c does not roundtrip on Windows.\n  // TODO: Figure out what is going on here (perhaps a locale problem).\n#elif defined(__EMSCRIPTEN__)\n  // strftime() and strptime() use different defintions for \"%c\" under\n  // emscripten (see https://github.com/kripken/emscripten/pull/7491),\n  // causing its round-trip test to fail.\n#else\n  // Even though we don't know what %c will produce, it should roundtrip,\n  // but only in the 0-offset timezone.\n  {\n    time_point<chrono::nanoseconds> out;\n    time_zone utc = utc_time_zone();\n    const auto s = absl::time_internal::cctz::format(\"%c\", in, utc);\n    EXPECT_TRUE(parse(\"%c\", s, utc, &out)) << s;\n    EXPECT_EQ(in, out);\n  }\n#endif\n}\n\nTEST(FormatParse, RoundTripDistantFuture) {\n  const time_zone utc = utc_time_zone();\n  const time_point<absl::time_internal::cctz::seconds> in =\n      time_point<absl::time_internal::cctz::seconds>::max();\n  const std::string s =\n      absl::time_internal::cctz::format(RFC3339_full, in, utc);\n  time_point<absl::time_internal::cctz::seconds> out;\n  EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;\n  EXPECT_EQ(in, out);\n}\n\nTEST(FormatParse, RoundTripDistantPast) {\n  const time_zone utc = utc_time_zone();\n  const time_point<absl::time_internal::cctz::seconds> in =\n      time_point<absl::time_internal::cctz::seconds>::min();\n  const std::string s =\n      absl::time_internal::cctz::format(RFC3339_full, in, utc);\n  time_point<absl::time_internal::cctz::seconds> out;\n  EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;\n  EXPECT_EQ(in, out);\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_if.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/src/time_zone_if.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/src/time_zone_info.h\"\n#include \"absl/time/internal/cctz/src/time_zone_libc.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nstd::unique_ptr<TimeZoneIf> TimeZoneIf::UTC() { return TimeZoneInfo::UTC(); }\n\nstd::unique_ptr<TimeZoneIf> TimeZoneIf::Make(const std::string& name) {\n  // Support \"libc:localtime\" and \"libc:*\" to access the legacy\n  // localtime and UTC support respectively from the C library.\n  // NOTE: The \"libc:*\" zones are internal, test-only interfaces, and\n  // are subject to change/removal without notice. Do not use them.\n  if (name.compare(0, 5, \"libc:\") == 0) {\n    return TimeZoneLibC::Make(name.substr(5));\n  }\n\n  // Otherwise use the \"zoneinfo\" implementation.\n  return TimeZoneInfo::Make(name);\n}\n\n// Defined out-of-line to avoid emitting a weak vtable in all TUs.\nTimeZoneIf::~TimeZoneIf() {}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_if.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_\n\n#include <chrono>\n#include <cstdint>\n#include <memory>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// A simple interface used to hide time-zone complexities from time_zone::Impl.\n// Subclasses implement the functions for civil-time conversions in the zone.\nclass TimeZoneIf {\n public:\n  // Factory functions for TimeZoneIf implementations.\n  static std::unique_ptr<TimeZoneIf> UTC();  // never fails\n  static std::unique_ptr<TimeZoneIf> Make(const std::string& name);\n\n  virtual ~TimeZoneIf();\n\n  virtual time_zone::absolute_lookup BreakTime(\n      const time_point<seconds>& tp) const = 0;\n  virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0;\n\n  virtual bool NextTransition(const time_point<seconds>& tp,\n                              time_zone::civil_transition* trans) const = 0;\n  virtual bool PrevTransition(const time_point<seconds>& tp,\n                              time_zone::civil_transition* trans) const = 0;\n\n  virtual std::string Version() const = 0;\n  virtual std::string Description() const = 0;\n\n protected:\n  TimeZoneIf() = default;\n  TimeZoneIf(const TimeZoneIf&) = delete;\n  TimeZoneIf& operator=(const TimeZoneIf&) = delete;\n};\n\n// Convert between time_point<seconds> and a count of seconds since the\n// Unix epoch.  We assume that the std::chrono::system_clock and the\n// Unix clock are second aligned, and that the results are representable.\n// (That is, that they share an epoch, which is required since C++20.)\ninline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) {\n  return (tp - std::chrono::time_point_cast<seconds>(\n                   std::chrono::system_clock::from_time_t(0)))\n      .count();\n}\ninline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {\n  return std::chrono::time_point_cast<seconds>(\n             std::chrono::system_clock::from_time_t(0)) +\n         seconds(t);\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_impl.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/src/time_zone_impl.h\"\n\n#include <deque>\n#include <memory>\n#include <mutex>\n#include <string>\n#include <unordered_map>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/src/time_zone_fixed.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\n// time_zone::Impls are linked into a map to support fast lookup by name.\nusing TimeZoneImplByName =\n    std::unordered_map<std::string, const time_zone::Impl*>;\nTimeZoneImplByName* time_zone_map = nullptr;\n\n// Mutual exclusion for time_zone_map.\nstd::mutex& TimeZoneMutex() {\n  // This mutex is intentionally \"leaked\" to avoid the static deinitialization\n  // order fiasco (std::mutex's destructor is not trivial on many platforms).\n  static std::mutex* time_zone_mutex = new std::mutex;\n  return *time_zone_mutex;\n}\n\n}  // namespace\n\ntime_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); }\n\nbool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {\n  const Impl* const utc_impl = UTCImpl();\n\n  // Check for UTC (which is never a key in time_zone_map).\n  auto offset = seconds::zero();\n  if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) {\n    *tz = time_zone(utc_impl);\n    return true;\n  }\n\n  // Check whether the time zone has already been loaded.\n  {\n    std::lock_guard<std::mutex> lock(TimeZoneMutex());\n    if (time_zone_map != nullptr) {\n      TimeZoneImplByName::const_iterator itr = time_zone_map->find(name);\n      if (itr != time_zone_map->end()) {\n        *tz = time_zone(itr->second);\n        return itr->second != utc_impl;\n      }\n    }\n  }\n\n  // Load the new time zone (outside the lock).\n  std::unique_ptr<const Impl> new_impl(new Impl(name));\n\n  // Add the new time zone to the map.\n  std::lock_guard<std::mutex> lock(TimeZoneMutex());\n  if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName;\n  const Impl*& impl = (*time_zone_map)[name];\n  if (impl == nullptr) {  // this thread won any load race\n    impl = new_impl->zone_ ? new_impl.release() : utc_impl;\n  }\n  *tz = time_zone(impl);\n  return impl != utc_impl;\n}\n\nvoid time_zone::Impl::ClearTimeZoneMapTestOnly() {\n  std::lock_guard<std::mutex> lock(TimeZoneMutex());\n  if (time_zone_map != nullptr) {\n    // Existing time_zone::Impl* entries are in the wild, so we can't delete\n    // them. Instead, we move them to a private container, where they are\n    // logically unreachable but not \"leaked\".  Future requests will result\n    // in reloading the data.\n    static auto* cleared = new std::deque<const time_zone::Impl*>;\n    for (const auto& element : *time_zone_map) {\n      cleared->push_back(element.second);\n    }\n    time_zone_map->clear();\n  }\n}\n\ntime_zone::Impl::Impl() : name_(\"UTC\"), zone_(TimeZoneIf::UTC()) {}\n\ntime_zone::Impl::Impl(const std::string& name)\n    : name_(name), zone_(TimeZoneIf::Make(name_)) {}\n\nconst time_zone::Impl* time_zone::Impl::UTCImpl() {\n  static const Impl* utc_impl = new Impl;\n  return utc_impl;\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_impl.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_\n\n#include <memory>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n#include \"absl/time/internal/cctz/src/time_zone_if.h\"\n#include \"absl/time/internal/cctz/src/time_zone_info.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// time_zone::Impl is the internal object referenced by a cctz::time_zone.\nclass time_zone::Impl {\n public:\n  // The UTC time zone. Also used for other time zones that fail to load.\n  static time_zone UTC();\n\n  // Load a named time zone. Returns false if the name is invalid, or if\n  // some other kind of error occurs. Note that loading \"UTC\" never fails.\n  static bool LoadTimeZone(const std::string& name, time_zone* tz);\n\n  // Clears the map of cached time zones.  Primarily for use in benchmarks\n  // that gauge the performance of loading/parsing the time-zone data.\n  static void ClearTimeZoneMapTestOnly();\n\n  // The primary key is the time-zone ID (e.g., \"America/New_York\").\n  const std::string& Name() const {\n    // TODO: It would nice if the zoneinfo data included the zone name.\n    return name_;\n  }\n\n  // Breaks a time_point down to civil-time components in this time zone.\n  time_zone::absolute_lookup BreakTime(const time_point<seconds>& tp) const {\n    return zone_->BreakTime(tp);\n  }\n\n  // Converts the civil-time components in this time zone into a time_point.\n  // That is, the opposite of BreakTime(). The requested civil time may be\n  // ambiguous or illegal due to a change of UTC offset.\n  time_zone::civil_lookup MakeTime(const civil_second& cs) const {\n    return zone_->MakeTime(cs);\n  }\n\n  // Finds the time of the next/previous offset change in this time zone.\n  bool NextTransition(const time_point<seconds>& tp,\n                      time_zone::civil_transition* trans) const {\n    return zone_->NextTransition(tp, trans);\n  }\n  bool PrevTransition(const time_point<seconds>& tp,\n                      time_zone::civil_transition* trans) const {\n    return zone_->PrevTransition(tp, trans);\n  }\n\n  // Returns an implementation-defined version string for this time zone.\n  std::string Version() const { return zone_->Version(); }\n\n  // Returns an implementation-defined description of this time zone.\n  std::string Description() const { return zone_->Description(); }\n\n private:\n  Impl();\n  explicit Impl(const std::string& name);\n  Impl(const Impl&) = delete;\n  Impl& operator=(const Impl&) = delete;\n\n  static const Impl* UTCImpl();\n\n  const std::string name_;\n  std::unique_ptr<TimeZoneIf> zone_;\n};\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_info.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n// This file implements the TimeZoneIf interface using the \"zoneinfo\"\n// data provided by the IANA Time Zone Database (i.e., the only real game\n// in town).\n//\n// TimeZoneInfo represents the history of UTC-offset changes within a time\n// zone. Most changes are due to daylight-saving rules, but occasionally\n// shifts are made to the time-zone's base offset. The database only attempts\n// to be definitive for times since 1970, so be wary of local-time conversions\n// before that. Also, rule and zone-boundary changes are made at the whim\n// of governments, so the conversion of future times needs to be taken with\n// a grain of salt.\n//\n// For more information see tzfile(5), http://www.iana.org/time-zones, or\n// https://en.wikipedia.org/wiki/Zoneinfo.\n//\n// Note that we assume the proleptic Gregorian calendar and 60-second\n// minutes throughout.\n\n#include \"absl/time/internal/cctz/src/time_zone_info.h\"\n\n#include <algorithm>\n#include <cassert>\n#include <chrono>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <fstream>\n#include <functional>\n#include <memory>\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/src/time_zone_fixed.h\"\n#include \"absl/time/internal/cctz/src/time_zone_posix.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\ninline bool IsLeap(year_t year) {\n  return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);\n}\n\n// The number of days in non-leap and leap years respectively.\nconst std::int_least32_t kDaysPerYear[2] = {365, 366};\n\n// The day offsets of the beginning of each (1-based) month in non-leap and\n// leap years respectively (e.g., 335 days before December in a leap year).\nconst std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = {\n    {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},\n    {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},\n};\n\n// We reject leap-second encoded zoneinfo and so assume 60-second minutes.\nconst std::int_least32_t kSecsPerDay = 24 * 60 * 60;\n\n// 400-year chunks always have 146097 days (20871 weeks).\nconst std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay;\n\n// Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay.\nconst std::int_least32_t kSecsPerYear[2] = {\n    365 * kSecsPerDay,\n    366 * kSecsPerDay,\n};\n\n// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat).\ninline int ToPosixWeekday(weekday wd) {\n  switch (wd) {\n    case weekday::sunday:\n      return 0;\n    case weekday::monday:\n      return 1;\n    case weekday::tuesday:\n      return 2;\n    case weekday::wednesday:\n      return 3;\n    case weekday::thursday:\n      return 4;\n    case weekday::friday:\n      return 5;\n    case weekday::saturday:\n      return 6;\n  }\n  return 0; /*NOTREACHED*/\n}\n\n// Single-byte, unsigned numeric values are encoded directly.\ninline std::uint_fast8_t Decode8(const char* cp) {\n  return static_cast<std::uint_fast8_t>(*cp) & 0xff;\n}\n\n// Multi-byte, numeric values are encoded using a MSB first,\n// twos-complement representation. These helpers decode, from\n// the given address, 4-byte and 8-byte values respectively.\n// Note: If int_fastXX_t == intXX_t and this machine is not\n// twos complement, then there will be at least one input value\n// we cannot represent.\nstd::int_fast32_t Decode32(const char* cp) {\n  std::uint_fast32_t v = 0;\n  for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++);\n  const std::int_fast32_t s32max = 0x7fffffff;\n  const auto s32maxU = static_cast<std::uint_fast32_t>(s32max);\n  if (v <= s32maxU) return static_cast<std::int_fast32_t>(v);\n  return static_cast<std::int_fast32_t>(v - s32maxU - 1) - s32max - 1;\n}\n\nstd::int_fast64_t Decode64(const char* cp) {\n  std::uint_fast64_t v = 0;\n  for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++);\n  const std::int_fast64_t s64max = 0x7fffffffffffffff;\n  const auto s64maxU = static_cast<std::uint_fast64_t>(s64max);\n  if (v <= s64maxU) return static_cast<std::int_fast64_t>(v);\n  return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1;\n}\n\nstruct Header {            // counts of:\n  std::size_t timecnt;     // transition times\n  std::size_t typecnt;     // transition types\n  std::size_t charcnt;     // zone abbreviation characters\n  std::size_t leapcnt;     // leap seconds (we expect none)\n  std::size_t ttisstdcnt;  // UTC/local indicators (unused)\n  std::size_t ttisutcnt;   // standard/wall indicators (unused)\n\n  bool Build(const tzhead& tzh);\n  std::size_t DataLength(std::size_t time_len) const;\n};\n\n// Builds the in-memory header using the raw bytes from the file.\nbool Header::Build(const tzhead& tzh) {\n  std::int_fast32_t v;\n  if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false;\n  timecnt = static_cast<std::size_t>(v);\n  if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false;\n  typecnt = static_cast<std::size_t>(v);\n  if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false;\n  charcnt = static_cast<std::size_t>(v);\n  if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false;\n  leapcnt = static_cast<std::size_t>(v);\n  if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false;\n  ttisstdcnt = static_cast<std::size_t>(v);\n  if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false;\n  ttisutcnt = static_cast<std::size_t>(v);\n  return true;\n}\n\n// How many bytes of data are associated with this header. The result\n// depends upon whether this is a section with 4-byte or 8-byte times.\nstd::size_t Header::DataLength(std::size_t time_len) const {\n  std::size_t len = 0;\n  len += (time_len + 1) * timecnt;  // unix_time + type_index\n  len += (4 + 1 + 1) * typecnt;     // utc_offset + is_dst + abbr_index\n  len += 1 * charcnt;               // abbreviations\n  len += (time_len + 4) * leapcnt;  // leap-time + TAI-UTC\n  len += 1 * ttisstdcnt;            // UTC/local indicators\n  len += 1 * ttisutcnt;             // standard/wall indicators\n  return len;\n}\n\n// Does the rule for future transitions call for year-round daylight time?\n// See tz/zic.c:stringzone() for the details on how such rules are encoded.\nbool AllYearDST(const PosixTimeZone& posix) {\n  if (posix.dst_start.date.fmt != PosixTransition::N) return false;\n  if (posix.dst_start.date.n.day != 0) return false;\n  if (posix.dst_start.time.offset != 0) return false;\n\n  if (posix.dst_end.date.fmt != PosixTransition::J) return false;\n  if (posix.dst_end.date.j.day != kDaysPerYear[0]) return false;\n  const auto offset = posix.std_offset - posix.dst_offset;\n  if (posix.dst_end.time.offset + offset != kSecsPerDay) return false;\n\n  return true;\n}\n\n// Generate a year-relative offset for a PosixTransition.\nstd::int_fast64_t TransOffset(bool leap_year, int jan1_weekday,\n                              const PosixTransition& pt) {\n  std::int_fast64_t days = 0;\n  switch (pt.date.fmt) {\n    case PosixTransition::J: {\n      days = pt.date.j.day;\n      if (!leap_year || days < kMonthOffsets[1][3]) days -= 1;\n      break;\n    }\n    case PosixTransition::N: {\n      days = pt.date.n.day;\n      break;\n    }\n    case PosixTransition::M: {\n      const bool last_week = (pt.date.m.week == 5);\n      days = kMonthOffsets[leap_year][pt.date.m.month + last_week];\n      const std::int_fast64_t weekday = (jan1_weekday + days) % 7;\n      if (last_week) {\n        days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1;\n      } else {\n        days += (pt.date.m.weekday + 7 - weekday) % 7;\n        days += (pt.date.m.week - 1) * 7;\n      }\n      break;\n    }\n  }\n  return (days * kSecsPerDay) + pt.time.offset;\n}\n\ninline time_zone::civil_lookup MakeUnique(const time_point<seconds>& tp) {\n  time_zone::civil_lookup cl;\n  cl.kind = time_zone::civil_lookup::UNIQUE;\n  cl.pre = cl.trans = cl.post = tp;\n  return cl;\n}\n\ninline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) {\n  return MakeUnique(FromUnixSeconds(unix_time));\n}\n\ninline time_zone::civil_lookup MakeSkipped(const Transition& tr,\n                                           const civil_second& cs) {\n  time_zone::civil_lookup cl;\n  cl.kind = time_zone::civil_lookup::SKIPPED;\n  cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec));\n  cl.trans = FromUnixSeconds(tr.unix_time);\n  cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs));\n  return cl;\n}\n\ninline time_zone::civil_lookup MakeRepeated(const Transition& tr,\n                                            const civil_second& cs) {\n  time_zone::civil_lookup cl;\n  cl.kind = time_zone::civil_lookup::REPEATED;\n  cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs));\n  cl.trans = FromUnixSeconds(tr.unix_time);\n  cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec));\n  return cl;\n}\n\ninline civil_second YearShift(const civil_second& cs, year_t shift) {\n  return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(),\n                      cs.minute(), cs.second());\n}\n\n}  // namespace\n\n// Find/make a transition type with these attributes.\nbool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,\n                                     const std::string& abbr,\n                                     std::uint_least8_t* index) {\n  std::size_t type_index = 0;\n  std::size_t abbr_index = abbreviations_.size();\n  for (; type_index != transition_types_.size(); ++type_index) {\n    const TransitionType& tt(transition_types_[type_index]);\n    const char* tt_abbr = &abbreviations_[tt.abbr_index];\n    if (tt_abbr == abbr) abbr_index = tt.abbr_index;\n    if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) {\n      if (abbr_index == tt.abbr_index) break;  // reuse\n    }\n  }\n  if (type_index > 255 || abbr_index > 255) {\n    // No index space (8 bits) available for a new type or abbreviation.\n    return false;\n  }\n  if (type_index == transition_types_.size()) {\n    TransitionType& tt(*transition_types_.emplace(transition_types_.end()));\n    tt.utc_offset = static_cast<std::int_least32_t>(utc_offset);\n    tt.is_dst = is_dst;\n    if (abbr_index == abbreviations_.size()) {\n      abbreviations_.append(abbr);\n      abbreviations_.append(1, '\\0');\n    }\n    tt.abbr_index = static_cast<std::uint_least8_t>(abbr_index);\n  }\n  *index = static_cast<std::uint_least8_t>(type_index);\n  return true;\n}\n\n// zic(8) can generate no-op transitions when a zone changes rules at an\n// instant when there is actually no discontinuity.  So we check whether\n// two transitions have equivalent types (same offset/is_dst/abbr).\nbool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index,\n                                    std::uint_fast8_t tt2_index) const {\n  if (tt1_index == tt2_index) return true;\n  const TransitionType& tt1(transition_types_[tt1_index]);\n  const TransitionType& tt2(transition_types_[tt2_index]);\n  if (tt1.utc_offset != tt2.utc_offset) return false;\n  if (tt1.is_dst != tt2.is_dst) return false;\n  if (tt1.abbr_index != tt2.abbr_index) return false;\n  return true;\n}\n\n// Use the POSIX-TZ-environment-variable-style string to handle times\n// in years after the last transition stored in the zoneinfo data.\nbool TimeZoneInfo::ExtendTransitions() {\n  extended_ = false;\n  if (future_spec_.empty()) return true;  // last transition prevails\n\n  PosixTimeZone posix;\n  if (!ParsePosixSpec(future_spec_, &posix)) return false;\n\n  // Find transition type for the future std specification.\n  std::uint_least8_t std_ti;\n  if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti))\n    return false;\n\n  if (posix.dst_abbr.empty()) {  // std only\n    // The future specification should match the last transition, and\n    // that means that handling the future will fall out naturally.\n    return EquivTransitions(transitions_.back().type_index, std_ti);\n  }\n\n  // Find transition type for the future dst specification.\n  std::uint_least8_t dst_ti;\n  if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti))\n    return false;\n\n  if (AllYearDST(posix)) {  // dst only\n    // The future specification should match the last transition, and\n    // that means that handling the future will fall out naturally.\n    return EquivTransitions(transitions_.back().type_index, dst_ti);\n  }\n\n  // Extend the transitions for an additional 401 years using the future\n  // specification. Years beyond those can be handled by mapping back to\n  // a cycle-equivalent year within that range. Note that we need 401\n  // (well, at least the first transition in the 401st year) so that the\n  // end of the 400th year is mapped back to an extended year. And first\n  // we may also need two additional transitions for the current year.\n  transitions_.reserve(transitions_.size() + 2 + 401 * 2);\n  extended_ = true;\n\n  const Transition& last(transitions_.back());\n  const std::int_fast64_t last_time = last.unix_time;\n  const TransitionType& last_tt(transition_types_[last.type_index]);\n  last_year_ = LocalTime(last_time, last_tt).cs.year();\n  bool leap_year = IsLeap(last_year_);\n  const civil_second jan1(last_year_);\n  std::int_fast64_t jan1_time = jan1 - civil_second();\n  int jan1_weekday = ToPosixWeekday(get_weekday(jan1));\n\n  Transition dst = {0, dst_ti, civil_second(), civil_second()};\n  Transition std = {0, std_ti, civil_second(), civil_second()};\n  for (const year_t limit = last_year_ + 401;; ++last_year_) {\n    auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start);\n    auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end);\n    dst.unix_time = jan1_time + dst_trans_off - posix.std_offset;\n    std.unix_time = jan1_time + std_trans_off - posix.dst_offset;\n    const auto* ta = dst.unix_time < std.unix_time ? &dst : &std;\n    const auto* tb = dst.unix_time < std.unix_time ? &std : &dst;\n    if (last_time < tb->unix_time) {\n      if (last_time < ta->unix_time) transitions_.push_back(*ta);\n      transitions_.push_back(*tb);\n    }\n    if (last_year_ == limit) break;\n    jan1_time += kSecsPerYear[leap_year];\n    jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;\n    leap_year = !leap_year && IsLeap(last_year_ + 1);\n  }\n\n  return true;\n}\n\nnamespace {\n\nusing FilePtr = std::unique_ptr<FILE, int (*)(FILE*)>;\n\n// fopen(3) adaptor.\ninline FilePtr FOpen(const char* path, const char* mode) {\n#if defined(_MSC_VER)\n  FILE* fp;\n  if (fopen_s(&fp, path, mode) != 0) fp = nullptr;\n  return FilePtr(fp, fclose);\n#else\n  // TODO: Enable the close-on-exec flag.\n  return FilePtr(fopen(path, mode), fclose);\n#endif\n}\n\n// A stdio(3)-backed implementation of ZoneInfoSource.\nclass FileZoneInfoSource : public ZoneInfoSource {\n public:\n  static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);\n\n  std::size_t Read(void* ptr, std::size_t size) override {\n    size = std::min(size, len_);\n    std::size_t nread = fread(ptr, 1, size, fp_.get());\n    len_ -= nread;\n    return nread;\n  }\n  int Skip(std::size_t offset) override {\n    offset = std::min(offset, len_);\n    int rc = fseek(fp_.get(), static_cast<long>(offset), SEEK_CUR);\n    if (rc == 0) len_ -= offset;\n    return rc;\n  }\n  std::string Version() const override {\n    // TODO: It would nice if the zoneinfo data included the tzdb version.\n    return std::string();\n  }\n\n protected:\n  explicit FileZoneInfoSource(\n      FilePtr fp, std::size_t len = std::numeric_limits<std::size_t>::max())\n      : fp_(std::move(fp)), len_(len) {}\n\n private:\n  FilePtr fp_;\n  std::size_t len_;\n};\n\nstd::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(\n    const std::string& name) {\n  // Use of the \"file:\" prefix is intended for testing purposes only.\n  const std::size_t pos = (name.compare(0, 5, \"file:\") == 0) ? 5 : 0;\n\n  // Map the time-zone name to a path name.\n  std::string path;\n  if (pos == name.size() || name[pos] != '/') {\n    const char* tzdir = \"/usr/share/zoneinfo\";\n    char* tzdir_env = nullptr;\n#if defined(_MSC_VER)\n    _dupenv_s(&tzdir_env, nullptr, \"TZDIR\");\n#else\n    tzdir_env = std::getenv(\"TZDIR\");\n#endif\n    if (tzdir_env && *tzdir_env) tzdir = tzdir_env;\n    path += tzdir;\n    path += '/';\n#if defined(_MSC_VER)\n    free(tzdir_env);\n#endif\n  }\n  path.append(name, pos, std::string::npos);\n\n  // Open the zoneinfo file.\n  auto fp = FOpen(path.c_str(), \"rb\");\n  if (fp == nullptr) return nullptr;\n  return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(std::move(fp)));\n}\n\nclass AndroidZoneInfoSource : public FileZoneInfoSource {\n public:\n  static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);\n  std::string Version() const override { return version_; }\n\n private:\n  explicit AndroidZoneInfoSource(FilePtr fp, std::size_t len,\n                                 std::string version)\n      : FileZoneInfoSource(std::move(fp), len), version_(std::move(version)) {}\n  std::string version_;\n};\n\nstd::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(\n    const std::string& name) {\n  // Use of the \"file:\" prefix is intended for testing purposes only.\n  const std::size_t pos = (name.compare(0, 5, \"file:\") == 0) ? 5 : 0;\n\n  // See Android's libc/tzcode/bionic.cpp for additional information.\n  for (const char* tzdata : {\"/apex/com.android.tzdata/etc/tz/tzdata\",\n                             \"/data/misc/zoneinfo/current/tzdata\",\n                             \"/system/usr/share/zoneinfo/tzdata\"}) {\n    auto fp = FOpen(tzdata, \"rb\");\n    if (fp == nullptr) continue;\n\n    char hbuf[24];  // covers header.zonetab_offset too\n    if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue;\n    if (strncmp(hbuf, \"tzdata\", 6) != 0) continue;\n    const char* vers = (hbuf[11] == '\\0') ? hbuf + 6 : \"\";\n    const std::int_fast32_t index_offset = Decode32(hbuf + 12);\n    const std::int_fast32_t data_offset = Decode32(hbuf + 16);\n    if (index_offset < 0 || data_offset < index_offset) continue;\n    if (fseek(fp.get(), static_cast<long>(index_offset), SEEK_SET) != 0)\n      continue;\n\n    char ebuf[52];  // covers entry.unused too\n    const std::size_t index_size =\n        static_cast<std::size_t>(data_offset - index_offset);\n    const std::size_t zonecnt = index_size / sizeof(ebuf);\n    if (zonecnt * sizeof(ebuf) != index_size) continue;\n    for (std::size_t i = 0; i != zonecnt; ++i) {\n      if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break;\n      const std::int_fast32_t start = data_offset + Decode32(ebuf + 40);\n      const std::int_fast32_t length = Decode32(ebuf + 44);\n      if (start < 0 || length < 0) break;\n      ebuf[40] = '\\0';  // ensure zone name is NUL terminated\n      if (strcmp(name.c_str() + pos, ebuf) == 0) {\n        if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break;\n        return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource(\n            std::move(fp), static_cast<std::size_t>(length), vers));\n      }\n    }\n  }\n\n  return nullptr;\n}\n\n// A zoneinfo source for use inside Fuchsia components. This attempts to\n// read zoneinfo files from one of several known paths in a component's\n// incoming namespace. [Config data][1] is preferred, but package-specific\n// resources are also supported.\n//\n// Fuchsia's implementation supports `FileZoneInfoSource::Version()`.\n//\n// [1]:\n// https://fuchsia.dev/fuchsia-src/development/components/data#using_config_data_in_your_component\nclass FuchsiaZoneInfoSource : public FileZoneInfoSource {\n public:\n  static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);\n  std::string Version() const override { return version_; }\n\n private:\n  explicit FuchsiaZoneInfoSource(FilePtr fp, std::string version)\n      : FileZoneInfoSource(std::move(fp)), version_(std::move(version)) {}\n  std::string version_;\n};\n\nstd::unique_ptr<ZoneInfoSource> FuchsiaZoneInfoSource::Open(\n    const std::string& name) {\n  // Use of the \"file:\" prefix is intended for testing purposes only.\n  const std::size_t pos = (name.compare(0, 5, \"file:\") == 0) ? 5 : 0;\n\n  // Prefixes where a Fuchsia component might find zoneinfo files,\n  // in descending order of preference.\n  const auto kTzdataPrefixes = {\n      // The tzdata from `config-data`.\n      \"/config/data/tzdata/\",\n      // The tzdata bundled in the component's package.\n      \"/pkg/data/tzdata/\",\n      // General data storage.\n      \"/data/tzdata/\",\n      // The recommended path for routed-in tzdata files.\n      // See for details:\n      // https://fuchsia.dev/fuchsia-src/concepts/process/namespaces?hl=en#typical_directory_structure\n      \"/config/tzdata/\",\n  };\n  const auto kEmptyPrefix = {\"\"};\n  const bool name_absolute = (pos != name.size() && name[pos] == '/');\n  const auto prefixes = name_absolute ? kEmptyPrefix : kTzdataPrefixes;\n\n  // Fuchsia builds place zoneinfo files at \"<prefix><format><name>\".\n  for (const std::string prefix : prefixes) {\n    std::string path = prefix;\n    if (!prefix.empty()) path += \"zoneinfo/tzif2/\";  // format\n    path.append(name, pos, std::string::npos);\n\n    auto fp = FOpen(path.c_str(), \"rb\");\n    if (fp == nullptr) continue;\n\n    std::string version;\n    if (!prefix.empty()) {\n      // Fuchsia builds place the version in \"<prefix>revision.txt\".\n      std::ifstream version_stream(prefix + \"revision.txt\");\n      if (version_stream.is_open()) {\n        // revision.txt should contain no newlines, but to be\n        // defensive we read just the first line.\n        std::getline(version_stream, version);\n      }\n    }\n\n    return std::unique_ptr<ZoneInfoSource>(\n        new FuchsiaZoneInfoSource(std::move(fp), std::move(version)));\n  }\n\n  return nullptr;\n}\n\n}  // namespace\n\n// What (no leap-seconds) UTC+seconds zoneinfo would look like.\nbool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {\n  transition_types_.resize(1);\n  TransitionType& tt(transition_types_.back());\n  tt.utc_offset = static_cast<std::int_least32_t>(offset.count());\n  tt.is_dst = false;\n  tt.abbr_index = 0;\n\n  // We temporarily add some redundant, contemporary (2015 through 2025)\n  // transitions for performance reasons.  See TimeZoneInfo::LocalTime().\n  // TODO: Fix the performance issue and remove the extra transitions.\n  transitions_.clear();\n  transitions_.reserve(12);\n  for (const std::int_fast64_t unix_time : {\n           -(1LL << 59),  // a \"first half\" transition\n           1420070400LL,  // 2015-01-01T00:00:00+00:00\n           1451606400LL,  // 2016-01-01T00:00:00+00:00\n           1483228800LL,  // 2017-01-01T00:00:00+00:00\n           1514764800LL,  // 2018-01-01T00:00:00+00:00\n           1546300800LL,  // 2019-01-01T00:00:00+00:00\n           1577836800LL,  // 2020-01-01T00:00:00+00:00\n           1609459200LL,  // 2021-01-01T00:00:00+00:00\n           1640995200LL,  // 2022-01-01T00:00:00+00:00\n           1672531200LL,  // 2023-01-01T00:00:00+00:00\n           1704067200LL,  // 2024-01-01T00:00:00+00:00\n           1735689600LL,  // 2025-01-01T00:00:00+00:00\n       }) {\n    Transition& tr(*transitions_.emplace(transitions_.end()));\n    tr.unix_time = unix_time;\n    tr.type_index = 0;\n    tr.civil_sec = LocalTime(tr.unix_time, tt).cs;\n    tr.prev_civil_sec = tr.civil_sec - 1;\n  }\n\n  default_transition_type_ = 0;\n  abbreviations_ = FixedOffsetToAbbr(offset);\n  abbreviations_.append(1, '\\0');\n  future_spec_.clear();  // never needed for a fixed-offset zone\n  extended_ = false;\n\n  tt.civil_max = LocalTime(seconds::max().count(), tt).cs;\n  tt.civil_min = LocalTime(seconds::min().count(), tt).cs;\n\n  transitions_.shrink_to_fit();\n  return true;\n}\n\nbool TimeZoneInfo::Load(ZoneInfoSource* zip) {\n  // Read and validate the header.\n  tzhead tzh;\n  if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;\n  if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)\n    return false;\n  Header hdr;\n  if (!hdr.Build(tzh)) return false;\n  std::size_t time_len = 4;\n  if (tzh.tzh_version[0] != '\\0') {\n    // Skip the 4-byte data.\n    if (zip->Skip(hdr.DataLength(time_len)) != 0) return false;\n    // Read and validate the header for the 8-byte data.\n    if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;\n    if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)\n      return false;\n    if (tzh.tzh_version[0] == '\\0') return false;\n    if (!hdr.Build(tzh)) return false;\n    time_len = 8;\n  }\n  if (hdr.typecnt == 0) return false;\n  if (hdr.leapcnt != 0) {\n    // This code assumes 60-second minutes so we do not want\n    // the leap-second encoded zoneinfo. We could reverse the\n    // compensation, but the \"right\" encoding is rarely used\n    // so currently we simply reject such data.\n    return false;\n  }\n  if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false;\n  if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false;\n\n  // Read the data into a local buffer.\n  std::size_t len = hdr.DataLength(time_len);\n  std::vector<char> tbuf(len);\n  if (zip->Read(tbuf.data(), len) != len) return false;\n  const char* bp = tbuf.data();\n\n  // Decode and validate the transitions.\n  transitions_.reserve(hdr.timecnt + 2);\n  transitions_.resize(hdr.timecnt);\n  for (std::size_t i = 0; i != hdr.timecnt; ++i) {\n    transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp);\n    bp += time_len;\n    if (i != 0) {\n      // Check that the transitions are ordered by time (as zic guarantees).\n      if (!Transition::ByUnixTime()(transitions_[i - 1], transitions_[i]))\n        return false;  // out of order\n    }\n  }\n  bool seen_type_0 = false;\n  for (std::size_t i = 0; i != hdr.timecnt; ++i) {\n    transitions_[i].type_index = Decode8(bp++);\n    if (transitions_[i].type_index >= hdr.typecnt) return false;\n    if (transitions_[i].type_index == 0) seen_type_0 = true;\n  }\n\n  // Decode and validate the transition types.\n  transition_types_.reserve(hdr.typecnt + 2);\n  transition_types_.resize(hdr.typecnt);\n  for (std::size_t i = 0; i != hdr.typecnt; ++i) {\n    transition_types_[i].utc_offset =\n        static_cast<std::int_least32_t>(Decode32(bp));\n    if (transition_types_[i].utc_offset >= kSecsPerDay ||\n        transition_types_[i].utc_offset <= -kSecsPerDay)\n      return false;\n    bp += 4;\n    transition_types_[i].is_dst = (Decode8(bp++) != 0);\n    transition_types_[i].abbr_index = Decode8(bp++);\n    if (transition_types_[i].abbr_index >= hdr.charcnt) return false;\n  }\n\n  // Determine the before-first-transition type.\n  default_transition_type_ = 0;\n  if (seen_type_0 && hdr.timecnt != 0) {\n    std::uint_fast8_t index = 0;\n    if (transition_types_[0].is_dst) {\n      index = transitions_[0].type_index;\n      while (index != 0 && transition_types_[index].is_dst) --index;\n    }\n    while (index != hdr.typecnt && transition_types_[index].is_dst) ++index;\n    if (index != hdr.typecnt) default_transition_type_ = index;\n  }\n\n  // Copy all the abbreviations.\n  abbreviations_.reserve(hdr.charcnt + 10);\n  abbreviations_.assign(bp, hdr.charcnt);\n  bp += hdr.charcnt;\n\n  // Skip the unused portions. We've already dispensed with leap-second\n  // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when\n  // interpreting a POSIX spec that does not include start/end rules, and\n  // that isn't the case here (see \"zic -p\").\n  bp += (time_len + 4) * hdr.leapcnt;  // leap-time + TAI-UTC\n  bp += 1 * hdr.ttisstdcnt;            // UTC/local indicators\n  bp += 1 * hdr.ttisutcnt;             // standard/wall indicators\n  assert(bp == tbuf.data() + tbuf.size());\n\n  future_spec_.clear();\n  if (tzh.tzh_version[0] != '\\0') {\n    // Snarf up the NL-enclosed future POSIX spec. Note\n    // that version '3' files utilize an extended format.\n    auto get_char = [](ZoneInfoSource* azip) -> int {\n      unsigned char ch;  // all non-EOF results are positive\n      return (azip->Read(&ch, 1) == 1) ? ch : EOF;\n    };\n    if (get_char(zip) != '\\n') return false;\n    for (int c = get_char(zip); c != '\\n'; c = get_char(zip)) {\n      if (c == EOF) return false;\n      future_spec_.push_back(static_cast<char>(c));\n    }\n  }\n\n  // We don't check for EOF so that we're forwards compatible.\n\n  // If we did not find version information during the standard loading\n  // process (as of tzh_version '3' that is unsupported), then ask the\n  // ZoneInfoSource for any out-of-bound version string it may be privy to.\n  if (version_.empty()) {\n    version_ = zip->Version();\n  }\n\n  // Ensure that there is always a transition in the first half of the\n  // time line (the second half is handled below) so that the signed\n  // difference between a civil_second and the civil_second of its\n  // previous transition is always representable, without overflow.\n  if (transitions_.empty() || transitions_.front().unix_time >= 0) {\n    Transition& tr(*transitions_.emplace(transitions_.begin()));\n    tr.unix_time = -(1LL << 59);  // -18267312070-10-26T17:01:52+00:00\n    tr.type_index = default_transition_type_;\n  }\n\n  // Extend the transitions using the future specification.\n  if (!ExtendTransitions()) return false;\n\n  // Ensure that there is always a transition in the second half of the\n  // time line (the first half is handled above) so that the signed\n  // difference between a civil_second and the civil_second of its\n  // previous transition is always representable, without overflow.\n  const Transition& last(transitions_.back());\n  if (last.unix_time < 0) {\n    const std::uint_fast8_t type_index = last.type_index;\n    Transition& tr(*transitions_.emplace(transitions_.end()));\n    tr.unix_time = 2147483647;  // 2038-01-19T03:14:07+00:00\n    tr.type_index = type_index;\n  }\n\n  // Compute the local civil time for each transition and the preceding\n  // second. These will be used for reverse conversions in MakeTime().\n  const TransitionType* ttp = &transition_types_[default_transition_type_];\n  for (std::size_t i = 0; i != transitions_.size(); ++i) {\n    Transition& tr(transitions_[i]);\n    tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1;\n    ttp = &transition_types_[tr.type_index];\n    tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs;\n    if (i != 0) {\n      // Check that the transitions are ordered by civil time. Essentially\n      // this means that an offset change cannot cross another such change.\n      // No one does this in practice, and we depend on it in MakeTime().\n      if (!Transition::ByCivilTime()(transitions_[i - 1], tr))\n        return false;  // out of order\n    }\n  }\n\n  // Compute the maximum/minimum civil times that can be converted to a\n  // time_point<seconds> for each of the zone's transition types.\n  for (auto& tt : transition_types_) {\n    tt.civil_max = LocalTime(seconds::max().count(), tt).cs;\n    tt.civil_min = LocalTime(seconds::min().count(), tt).cs;\n  }\n\n  transitions_.shrink_to_fit();\n  return true;\n}\n\nbool TimeZoneInfo::Load(const std::string& name) {\n  // We can ensure that the loading of UTC or any other fixed-offset\n  // zone never fails because the simple, fixed-offset state can be\n  // internally generated. Note that this depends on our choice to not\n  // accept leap-second encoded (\"right\") zoneinfo.\n  auto offset = seconds::zero();\n  if (FixedOffsetFromName(name, &offset)) {\n    return ResetToBuiltinUTC(offset);\n  }\n\n  // Find and use a ZoneInfoSource to load the named zone.\n  auto zip = cctz_extension::zone_info_source_factory(\n      name, [](const std::string& n) -> std::unique_ptr<ZoneInfoSource> {\n        if (auto z = FileZoneInfoSource::Open(n)) return z;\n        if (auto z = AndroidZoneInfoSource::Open(n)) return z;\n        if (auto z = FuchsiaZoneInfoSource::Open(n)) return z;\n        return nullptr;\n      });\n  return zip != nullptr && Load(zip.get());\n}\n\nstd::unique_ptr<TimeZoneInfo> TimeZoneInfo::UTC() {\n  auto tz = std::unique_ptr<TimeZoneInfo>(new TimeZoneInfo);\n  tz->ResetToBuiltinUTC(seconds::zero());\n  return tz;\n}\n\nstd::unique_ptr<TimeZoneInfo> TimeZoneInfo::Make(const std::string& name) {\n  auto tz = std::unique_ptr<TimeZoneInfo>(new TimeZoneInfo);\n  if (!tz->Load(name)) tz.reset();  // fallback to UTC\n  return tz;\n}\n\n// BreakTime() translation for a particular transition type.\ntime_zone::absolute_lookup TimeZoneInfo::LocalTime(\n    std::int_fast64_t unix_time, const TransitionType& tt) const {\n  // A civil time in \"+offset\" looks like (time+offset) in UTC.\n  // Note: We perform two additions in the civil_second domain to\n  // sidestep the chance of overflow in (unix_time + tt.utc_offset).\n  return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset,\n          tt.is_dst, &abbreviations_[tt.abbr_index]};\n}\n\n// BreakTime() translation for a particular transition.\ntime_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time,\n                                                   const Transition& tr) const {\n  const TransitionType& tt = transition_types_[tr.type_index];\n  // Note: (unix_time - tr.unix_time) will never overflow as we\n  // have ensured that there is always a \"nearby\" transition.\n  return {tr.civil_sec + (unix_time - tr.unix_time),  // TODO: Optimize.\n          tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};\n}\n\n// MakeTime() translation with a conversion-preserving +N * 400-year shift.\ntime_zone::civil_lookup TimeZoneInfo::TimeLocal(const civil_second& cs,\n                                                year_t c4_shift) const {\n  assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_);\n  time_zone::civil_lookup cl = MakeTime(cs);\n  if (c4_shift > seconds::max().count() / kSecsPer400Years) {\n    cl.pre = cl.trans = cl.post = time_point<seconds>::max();\n  } else {\n    const auto offset = seconds(c4_shift * kSecsPer400Years);\n    const auto limit = time_point<seconds>::max() - offset;\n    for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) {\n      if (*tp > limit) {\n        *tp = time_point<seconds>::max();\n      } else {\n        *tp += offset;\n      }\n    }\n  }\n  return cl;\n}\n\ntime_zone::absolute_lookup TimeZoneInfo::BreakTime(\n    const time_point<seconds>& tp) const {\n  std::int_fast64_t unix_time = ToUnixSeconds(tp);\n  const std::size_t timecnt = transitions_.size();\n  assert(timecnt != 0);  // We always add a transition.\n\n  if (unix_time < transitions_[0].unix_time) {\n    return LocalTime(unix_time, transition_types_[default_transition_type_]);\n  }\n  if (unix_time >= transitions_[timecnt - 1].unix_time) {\n    // After the last transition. If we extended the transitions using\n    // future_spec_, shift back to a supported year using the 400-year\n    // cycle of calendaric equivalence and then compensate accordingly.\n    if (extended_) {\n      const std::int_fast64_t diff =\n          unix_time - transitions_[timecnt - 1].unix_time;\n      const year_t shift = diff / kSecsPer400Years + 1;\n      const auto d = seconds(shift * kSecsPer400Years);\n      time_zone::absolute_lookup al = BreakTime(tp - d);\n      al.cs = YearShift(al.cs, shift * 400);\n      return al;\n    }\n    return LocalTime(unix_time, transitions_[timecnt - 1]);\n  }\n\n  const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed);\n  if (0 < hint && hint < timecnt) {\n    if (transitions_[hint - 1].unix_time <= unix_time) {\n      if (unix_time < transitions_[hint].unix_time) {\n        return LocalTime(unix_time, transitions_[hint - 1]);\n      }\n    }\n  }\n\n  const Transition target = {unix_time, 0, civil_second(), civil_second()};\n  const Transition* begin = &transitions_[0];\n  const Transition* tr = std::upper_bound(begin, begin + timecnt, target,\n                                          Transition::ByUnixTime());\n  local_time_hint_.store(static_cast<std::size_t>(tr - begin),\n                         std::memory_order_relaxed);\n  return LocalTime(unix_time, *--tr);\n}\n\ntime_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const {\n  const std::size_t timecnt = transitions_.size();\n  assert(timecnt != 0);  // We always add a transition.\n\n  // Find the first transition after our target civil time.\n  const Transition* tr = nullptr;\n  const Transition* begin = &transitions_[0];\n  const Transition* end = begin + timecnt;\n  if (cs < begin->civil_sec) {\n    tr = begin;\n  } else if (cs >= transitions_[timecnt - 1].civil_sec) {\n    tr = end;\n  } else {\n    const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed);\n    if (0 < hint && hint < timecnt) {\n      if (transitions_[hint - 1].civil_sec <= cs) {\n        if (cs < transitions_[hint].civil_sec) {\n          tr = begin + hint;\n        }\n      }\n    }\n    if (tr == nullptr) {\n      const Transition target = {0, 0, cs, civil_second()};\n      tr = std::upper_bound(begin, end, target, Transition::ByCivilTime());\n      time_local_hint_.store(static_cast<std::size_t>(tr - begin),\n                             std::memory_order_relaxed);\n    }\n  }\n\n  if (tr == begin) {\n    if (tr->prev_civil_sec >= cs) {\n      // Before first transition, so use the default offset.\n      const TransitionType& tt(transition_types_[default_transition_type_]);\n      if (cs < tt.civil_min) return MakeUnique(time_point<seconds>::min());\n      return MakeUnique(cs - (civil_second() + tt.utc_offset));\n    }\n    // tr->prev_civil_sec < cs < tr->civil_sec\n    return MakeSkipped(*tr, cs);\n  }\n\n  if (tr == end) {\n    if (cs > (--tr)->prev_civil_sec) {\n      // After the last transition. If we extended the transitions using\n      // future_spec_, shift back to a supported year using the 400-year\n      // cycle of calendaric equivalence and then compensate accordingly.\n      if (extended_ && cs.year() > last_year_) {\n        const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1;\n        return TimeLocal(YearShift(cs, shift * -400), shift);\n      }\n      const TransitionType& tt(transition_types_[tr->type_index]);\n      if (cs > tt.civil_max) return MakeUnique(time_point<seconds>::max());\n      return MakeUnique(tr->unix_time + (cs - tr->civil_sec));\n    }\n    // tr->civil_sec <= cs <= tr->prev_civil_sec\n    return MakeRepeated(*tr, cs);\n  }\n\n  if (tr->prev_civil_sec < cs) {\n    // tr->prev_civil_sec < cs < tr->civil_sec\n    return MakeSkipped(*tr, cs);\n  }\n\n  if (cs <= (--tr)->prev_civil_sec) {\n    // tr->civil_sec <= cs <= tr->prev_civil_sec\n    return MakeRepeated(*tr, cs);\n  }\n\n  // In between transitions.\n  return MakeUnique(tr->unix_time + (cs - tr->civil_sec));\n}\n\nstd::string TimeZoneInfo::Version() const { return version_; }\n\nstd::string TimeZoneInfo::Description() const {\n  std::ostringstream oss;\n  oss << \"#trans=\" << transitions_.size();\n  oss << \" #types=\" << transition_types_.size();\n  oss << \" spec='\" << future_spec_ << \"'\";\n  return oss.str();\n}\n\nbool TimeZoneInfo::NextTransition(const time_point<seconds>& tp,\n                                  time_zone::civil_transition* trans) const {\n  if (transitions_.empty()) return false;\n  const Transition* begin = &transitions_[0];\n  const Transition* end = begin + transitions_.size();\n  if (begin->unix_time <= -(1LL << 59)) {\n    // Do not report the BIG_BANG found in some zoneinfo data as it is\n    // really a sentinel, not a transition.  See pre-2018f tz/zic.c.\n    ++begin;\n  }\n  std::int_fast64_t unix_time = ToUnixSeconds(tp);\n  const Transition target = {unix_time, 0, civil_second(), civil_second()};\n  const Transition* tr =\n      std::upper_bound(begin, end, target, Transition::ByUnixTime());\n  for (; tr != end; ++tr) {  // skip no-op transitions\n    std::uint_fast8_t prev_type_index =\n        (tr == begin) ? default_transition_type_ : tr[-1].type_index;\n    if (!EquivTransitions(prev_type_index, tr[0].type_index)) break;\n  }\n  // When tr == end we return false, ignoring future_spec_.\n  if (tr == end) return false;\n  trans->from = tr->prev_civil_sec + 1;\n  trans->to = tr->civil_sec;\n  return true;\n}\n\nbool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,\n                                  time_zone::civil_transition* trans) const {\n  if (transitions_.empty()) return false;\n  const Transition* begin = &transitions_[0];\n  const Transition* end = begin + transitions_.size();\n  if (begin->unix_time <= -(1LL << 59)) {\n    // Do not report the BIG_BANG found in some zoneinfo data as it is\n    // really a sentinel, not a transition.  See pre-2018f tz/zic.c.\n    ++begin;\n  }\n  std::int_fast64_t unix_time = ToUnixSeconds(tp);\n  if (FromUnixSeconds(unix_time) != tp) {\n    if (unix_time == std::numeric_limits<std::int_fast64_t>::max()) {\n      if (end == begin) return false;  // Ignore future_spec_.\n      trans->from = (--end)->prev_civil_sec + 1;\n      trans->to = end->civil_sec;\n      return true;\n    }\n    unix_time += 1;  // ceils\n  }\n  const Transition target = {unix_time, 0, civil_second(), civil_second()};\n  const Transition* tr =\n      std::lower_bound(begin, end, target, Transition::ByUnixTime());\n  for (; tr != begin; --tr) {  // skip no-op transitions\n    std::uint_fast8_t prev_type_index =\n        (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index;\n    if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break;\n  }\n  // When tr == end we return the \"last\" transition, ignoring future_spec_.\n  if (tr == begin) return false;\n  trans->from = (--tr)->prev_civil_sec + 1;\n  trans->to = tr->civil_sec;\n  return true;\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_info.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_\n\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n#include \"absl/time/internal/cctz/include/cctz/zone_info_source.h\"\n#include \"absl/time/internal/cctz/src/time_zone_if.h\"\n#include \"absl/time/internal/cctz/src/tzfile.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// A transition to a new UTC offset.\nstruct Transition {\n  std::int_least64_t unix_time;   // the instant of this transition\n  std::uint_least8_t type_index;  // index of the transition type\n  civil_second civil_sec;         // local civil time of transition\n  civil_second prev_civil_sec;    // local civil time one second earlier\n\n  struct ByUnixTime {\n    inline bool operator()(const Transition& lhs, const Transition& rhs) const {\n      return lhs.unix_time < rhs.unix_time;\n    }\n  };\n  struct ByCivilTime {\n    inline bool operator()(const Transition& lhs, const Transition& rhs) const {\n      return lhs.civil_sec < rhs.civil_sec;\n    }\n  };\n};\n\n// The characteristics of a particular transition.\nstruct TransitionType {\n  std::int_least32_t utc_offset;  // the new prevailing UTC offset\n  civil_second civil_max;         // max convertible civil time for offset\n  civil_second civil_min;         // min convertible civil time for offset\n  bool is_dst;                    // did we move into daylight-saving time\n  std::uint_least8_t abbr_index;  // index of the new abbreviation\n};\n\n// A time zone backed by the IANA Time Zone Database (zoneinfo).\nclass TimeZoneInfo : public TimeZoneIf {\n public:\n  // Factories.\n  static std::unique_ptr<TimeZoneInfo> UTC();  // never fails\n  static std::unique_ptr<TimeZoneInfo> Make(const std::string& name);\n\n  // TimeZoneIf implementations.\n  time_zone::absolute_lookup BreakTime(\n      const time_point<seconds>& tp) const override;\n  time_zone::civil_lookup MakeTime(const civil_second& cs) const override;\n  bool NextTransition(const time_point<seconds>& tp,\n                      time_zone::civil_transition* trans) const override;\n  bool PrevTransition(const time_point<seconds>& tp,\n                      time_zone::civil_transition* trans) const override;\n  std::string Version() const override;\n  std::string Description() const override;\n\n private:\n  TimeZoneInfo() = default;\n  TimeZoneInfo(const TimeZoneInfo&) = delete;\n  TimeZoneInfo& operator=(const TimeZoneInfo&) = delete;\n\n  bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,\n                         const std::string& abbr, std::uint_least8_t* index);\n  bool EquivTransitions(std::uint_fast8_t tt1_index,\n                        std::uint_fast8_t tt2_index) const;\n  bool ExtendTransitions();\n\n  bool ResetToBuiltinUTC(const seconds& offset);\n  bool Load(const std::string& name);\n  bool Load(ZoneInfoSource* zip);\n\n  // Helpers for BreakTime() and MakeTime().\n  time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,\n                                       const TransitionType& tt) const;\n  time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,\n                                       const Transition& tr) const;\n  time_zone::civil_lookup TimeLocal(const civil_second& cs,\n                                    year_t c4_shift) const;\n\n  std::vector<Transition> transitions_;  // ordered by unix_time and civil_sec\n  std::vector<TransitionType> transition_types_;  // distinct transition types\n  std::uint_fast8_t default_transition_type_;     // for before first transition\n  std::string abbreviations_;  // all the NUL-terminated abbreviations\n\n  std::string version_;      // the tzdata version if available\n  std::string future_spec_;  // for after the last zic transition\n  bool extended_;            // future_spec_ was used to generate transitions\n  year_t last_year_;         // the final year of the generated transitions\n\n  // We remember the transitions found during the last BreakTime() and\n  // MakeTime() calls. If the next request is for the same transition we\n  // will avoid re-searching.\n  mutable std::atomic<std::size_t> local_time_hint_ = {};  // BreakTime() hint\n  mutable std::atomic<std::size_t> time_local_hint_ = {};  // MakeTime() hint\n};\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_libc.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_WIN32)\n#define _CRT_SECURE_NO_WARNINGS 1\n#endif\n\n#include \"absl/time/internal/cctz/src/time_zone_libc.h\"\n\n#include <chrono>\n#include <ctime>\n#include <limits>\n#include <utility>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\n#if defined(_AIX)\nextern \"C\" {\nextern long altzone;\n}\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\n#if defined(_WIN32) || defined(_WIN64)\n// Uses the globals: '_timezone', '_dstbias' and '_tzname'.\nauto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return _timezone + (is_dst ? _dstbias : 0);\n}\nauto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return _tzname[is_dst];\n}\n#elif defined(__sun) || defined(_AIX)\n// Uses the globals: 'timezone', 'altzone' and 'tzname'.\nauto tm_gmtoff(const std::tm& tm) -> decltype(timezone) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return is_dst ? altzone : timezone;\n}\nauto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return tzname[is_dst];\n}\n#elif defined(__native_client__) || defined(__myriad2__) || \\\n    defined(__EMSCRIPTEN__)\n// Uses the globals: '_timezone' and 'tzname'.\nauto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return _timezone + (is_dst ? 60 * 60 : 0);\n}\nauto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return tzname[is_dst];\n}\n#elif defined(__VXWORKS__)\n// Uses the globals: 'timezone' and 'tzname'.\nauto tm_gmtoff(const std::tm& tm) -> decltype(timezone + 0) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return timezone + (is_dst ? 60 * 60 : 0);\n}\nauto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {\n  const bool is_dst = tm.tm_isdst > 0;\n  return tzname[is_dst];\n}\n#else\n// Adapt to different spellings of the struct std::tm extension fields.\n#if defined(tm_gmtoff)\nauto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) {\n  return tm.tm_gmtoff;\n}\n#elif defined(__tm_gmtoff)\nauto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) {\n  return tm.__tm_gmtoff;\n}\n#else\ntemplate <typename T>\nauto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) {\n  return tm.tm_gmtoff;\n}\ntemplate <typename T>\nauto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) {\n  return tm.__tm_gmtoff;\n}\n#endif  // tm_gmtoff\n#if defined(tm_zone)\nauto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { return tm.tm_zone; }\n#elif defined(__tm_zone)\nauto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) {\n  return tm.__tm_zone;\n}\n#else\ntemplate <typename T>\nauto tm_zone(const T& tm) -> decltype(tm.tm_zone) {\n  return tm.tm_zone;\n}\ntemplate <typename T>\nauto tm_zone(const T& tm) -> decltype(tm.__tm_zone) {\n  return tm.__tm_zone;\n}\n#endif  // tm_zone\n#endif\nusing tm_gmtoff_t = decltype(tm_gmtoff(std::tm{}));\n\ninline std::tm* gm_time(const std::time_t* timep, std::tm* result) {\n#if defined(_WIN32) || defined(_WIN64)\n  return gmtime_s(result, timep) ? nullptr : result;\n#else\n  return gmtime_r(timep, result);\n#endif\n}\n\ninline std::tm* local_time(const std::time_t* timep, std::tm* result) {\n#if defined(_WIN32) || defined(_WIN64)\n  return localtime_s(result, timep) ? nullptr : result;\n#else\n  return localtime_r(timep, result);\n#endif\n}\n\n// Converts a civil second and \"dst\" flag into a time_t and a struct tm.\n// Returns false if time_t cannot represent the requested civil second.\n// Caller must have already checked that cs.year() will fit into a tm_year.\nbool make_time(const civil_second& cs, int is_dst, std::time_t* t,\n               std::tm* tm) {\n  tm->tm_year = static_cast<int>(cs.year() - year_t{1900});\n  tm->tm_mon = cs.month() - 1;\n  tm->tm_mday = cs.day();\n  tm->tm_hour = cs.hour();\n  tm->tm_min = cs.minute();\n  tm->tm_sec = cs.second();\n  tm->tm_isdst = is_dst;\n  *t = std::mktime(tm);\n  if (*t == std::time_t{-1}) {\n    std::tm tm2;\n    const std::tm* tmp = local_time(t, &tm2);\n    if (tmp == nullptr || tmp->tm_year != tm->tm_year ||\n        tmp->tm_mon != tm->tm_mon || tmp->tm_mday != tm->tm_mday ||\n        tmp->tm_hour != tm->tm_hour || tmp->tm_min != tm->tm_min ||\n        tmp->tm_sec != tm->tm_sec) {\n      // A true error (not just one second before the epoch).\n      return false;\n    }\n  }\n  return true;\n}\n\n// Find the least time_t in [lo:hi] where local time matches offset, given:\n// (1) lo doesn't match, (2) hi does, and (3) there is only one transition.\nstd::time_t find_trans(std::time_t lo, std::time_t hi, tm_gmtoff_t offset) {\n  std::tm tm;\n  while (lo + 1 != hi) {\n    const std::time_t mid = lo + (hi - lo) / 2;\n    std::tm* tmp = local_time(&mid, &tm);\n    if (tmp != nullptr) {\n      if (tm_gmtoff(*tmp) == offset) {\n        hi = mid;\n      } else {\n        lo = mid;\n      }\n    } else {\n      // If std::tm cannot hold some result we resort to a linear search,\n      // ignoring all failed conversions.  Slow, but never really happens.\n      while (++lo != hi) {\n        tmp = local_time(&lo, &tm);\n        if (tmp != nullptr) {\n          if (tm_gmtoff(*tmp) == offset) break;\n        }\n      }\n      return lo;\n    }\n  }\n  return hi;\n}\n\n}  // namespace\n\nstd::unique_ptr<TimeZoneLibC> TimeZoneLibC::Make(const std::string& name) {\n  return std::unique_ptr<TimeZoneLibC>(new TimeZoneLibC(name));\n}\n\ntime_zone::absolute_lookup TimeZoneLibC::BreakTime(\n    const time_point<seconds>& tp) const {\n  time_zone::absolute_lookup al;\n  al.offset = 0;\n  al.is_dst = false;\n  al.abbr = \"-00\";\n\n  const std::int_fast64_t s = ToUnixSeconds(tp);\n\n  // If std::time_t cannot hold the input we saturate the output.\n  if (s < std::numeric_limits<std::time_t>::min()) {\n    al.cs = civil_second::min();\n    return al;\n  }\n  if (s > std::numeric_limits<std::time_t>::max()) {\n    al.cs = civil_second::max();\n    return al;\n  }\n\n  const std::time_t t = static_cast<std::time_t>(s);\n  std::tm tm;\n  std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm);\n\n  // If std::tm cannot hold the result we saturate the output.\n  if (tmp == nullptr) {\n    al.cs = (s < 0) ? civil_second::min() : civil_second::max();\n    return al;\n  }\n\n  const year_t year = tmp->tm_year + year_t{1900};\n  al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour,\n                       tmp->tm_min, tmp->tm_sec);\n  al.offset = static_cast<int>(tm_gmtoff(*tmp));\n  al.abbr = local_ ? tm_zone(*tmp) : \"UTC\";  // as expected by cctz\n  al.is_dst = tmp->tm_isdst > 0;\n  return al;\n}\n\ntime_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {\n  if (!local_) {\n    // If time_point<seconds> cannot hold the result we saturate.\n    static const civil_second min_tp_cs =\n        civil_second() + ToUnixSeconds(time_point<seconds>::min());\n    static const civil_second max_tp_cs =\n        civil_second() + ToUnixSeconds(time_point<seconds>::max());\n    const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min()\n                                   : (cs > max_tp_cs)\n                                       ? time_point<seconds>::max()\n                                       : FromUnixSeconds(cs - civil_second());\n    return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};\n  }\n\n  // If tm_year cannot hold the requested year we saturate the result.\n  if (cs.year() < 0) {\n    if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) {\n      const time_point<seconds> tp = time_point<seconds>::min();\n      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};\n    }\n  } else {\n    if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) {\n      const time_point<seconds> tp = time_point<seconds>::max();\n      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};\n    }\n  }\n\n  // We probe with \"is_dst\" values of 0 and 1 to try to distinguish unique\n  // civil seconds from skipped or repeated ones.  This is not always possible\n  // however, as the \"dst\" flag does not change over some offset transitions.\n  // We are also subject to the vagaries of mktime() implementations. For\n  // example, some implementations treat \"tm_isdst\" as a demand (useless),\n  // and some as a disambiguator (useful).\n  std::time_t t0, t1;\n  std::tm tm0, tm1;\n  if (make_time(cs, 0, &t0, &tm0) && make_time(cs, 1, &t1, &tm1)) {\n    if (tm0.tm_isdst == tm1.tm_isdst) {\n      // The civil time was singular (pre == trans == post).\n      const time_point<seconds> tp = FromUnixSeconds(tm0.tm_isdst ? t1 : t0);\n      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};\n    }\n\n    tm_gmtoff_t offset = tm_gmtoff(tm0);\n    if (t0 < t1) {  // negative DST\n      std::swap(t0, t1);\n      offset = tm_gmtoff(tm1);\n    }\n\n    const std::time_t tt = find_trans(t1, t0, offset);\n    const time_point<seconds> trans = FromUnixSeconds(tt);\n\n    if (tm0.tm_isdst) {\n      // The civil time did not exist (pre >= trans > post).\n      const time_point<seconds> pre = FromUnixSeconds(t0);\n      const time_point<seconds> post = FromUnixSeconds(t1);\n      return {time_zone::civil_lookup::SKIPPED, pre, trans, post};\n    }\n\n    // The civil time was ambiguous (pre < trans <= post).\n    const time_point<seconds> pre = FromUnixSeconds(t1);\n    const time_point<seconds> post = FromUnixSeconds(t0);\n    return {time_zone::civil_lookup::REPEATED, pre, trans, post};\n  }\n\n  // make_time() failed somehow so we saturate the result.\n  const time_point<seconds> tp = (cs < civil_second())\n                                     ? time_point<seconds>::min()\n                                     : time_point<seconds>::max();\n  return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};\n}\n\nbool TimeZoneLibC::NextTransition(const time_point<seconds>&,\n                                  time_zone::civil_transition*) const {\n  return false;\n}\n\nbool TimeZoneLibC::PrevTransition(const time_point<seconds>&,\n                                  time_zone::civil_transition*) const {\n  return false;\n}\n\nstd::string TimeZoneLibC::Version() const {\n  return std::string();  // unknown\n}\n\nstd::string TimeZoneLibC::Description() const {\n  return local_ ? \"localtime\" : \"UTC\";\n}\n\nTimeZoneLibC::TimeZoneLibC(const std::string& name)\n    : local_(name == \"localtime\") {}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_libc.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_\n\n#include <memory>\n#include <string>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/src/time_zone_if.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3),\n// and which therefore only supports UTC and the local time zone.\nclass TimeZoneLibC : public TimeZoneIf {\n public:\n  // Factory.\n  static std::unique_ptr<TimeZoneLibC> Make(const std::string& name);\n\n  // TimeZoneIf implementations.\n  time_zone::absolute_lookup BreakTime(\n      const time_point<seconds>& tp) const override;\n  time_zone::civil_lookup MakeTime(const civil_second& cs) const override;\n  bool NextTransition(const time_point<seconds>& tp,\n                      time_zone::civil_transition* trans) const override;\n  bool PrevTransition(const time_point<seconds>& tp,\n                      time_zone::civil_transition* trans) const override;\n  std::string Version() const override;\n  std::string Description() const override;\n\n private:\n  explicit TimeZoneLibC(const std::string& name);\n  TimeZoneLibC(const TimeZoneLibC&) = delete;\n  TimeZoneLibC& operator=(const TimeZoneLibC&) = delete;\n\n  const bool local_;  // localtime or UTC\n};\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_lookup.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\n#if defined(__ANDROID__)\n#include <sys/system_properties.h>\n#endif\n\n#if defined(__APPLE__)\n#include <CoreFoundation/CFTimeZone.h>\n\n#include <vector>\n#endif\n\n#if defined(__Fuchsia__)\n#include <fuchsia/intl/cpp/fidl.h>\n#include <lib/async-loop/cpp/loop.h>\n#include <lib/fdio/directory.h>\n#include <zircon/types.h>\n#endif\n\n#include <array>\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <string>\n\n#include \"absl/time/internal/cctz/src/time_zone_fixed.h\"\n#include \"absl/time/internal/cctz/src/time_zone_impl.h\"\n\n#if defined(_WIN32)\n#include \"absl/time/internal/cctz/src/time_zone_name_win.h\"\n#endif  // _WIN32\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nstd::string time_zone::name() const { return effective_impl().Name(); }\n\ntime_zone::absolute_lookup time_zone::lookup(\n    const time_point<seconds>& tp) const {\n  return effective_impl().BreakTime(tp);\n}\n\ntime_zone::civil_lookup time_zone::lookup(const civil_second& cs) const {\n  return effective_impl().MakeTime(cs);\n}\n\nbool time_zone::next_transition(const time_point<seconds>& tp,\n                                civil_transition* trans) const {\n  return effective_impl().NextTransition(tp, trans);\n}\n\nbool time_zone::prev_transition(const time_point<seconds>& tp,\n                                civil_transition* trans) const {\n  return effective_impl().PrevTransition(tp, trans);\n}\n\nstd::string time_zone::version() const { return effective_impl().Version(); }\n\nstd::string time_zone::description() const {\n  return effective_impl().Description();\n}\n\nconst time_zone::Impl& time_zone::effective_impl() const {\n  if (impl_ == nullptr) {\n    // Dereferencing an implicit-UTC time_zone is expected to be\n    // rare, so we don't mind paying a small synchronization cost.\n    return *time_zone::Impl::UTC().impl_;\n  }\n  return *impl_;\n}\n\nbool load_time_zone(const std::string& name, time_zone* tz) {\n  return time_zone::Impl::LoadTimeZone(name, tz);\n}\n\ntime_zone utc_time_zone() {\n  return time_zone::Impl::UTC();  // avoid name lookup\n}\n\ntime_zone fixed_time_zone(const seconds& offset) {\n  time_zone tz;\n  load_time_zone(FixedOffsetToName(offset), &tz);\n  return tz;\n}\n\ntime_zone local_time_zone() {\n  const char* zone = \":localtime\";\n#if defined(__ANDROID__)\n  char sysprop[PROP_VALUE_MAX];\n  if (__system_property_get(\"persist.sys.timezone\", sysprop) > 0) {\n    zone = sysprop;\n  }\n#endif\n#if defined(__APPLE__)\n  std::vector<char> buffer;\n  CFTimeZoneRef tz_default = CFTimeZoneCopyDefault();\n  if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) {\n    CFStringEncoding encoding = kCFStringEncodingUTF8;\n    CFIndex length = CFStringGetLength(tz_name);\n    CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, encoding) + 1;\n    buffer.resize(static_cast<size_t>(max_size));\n    if (CFStringGetCString(tz_name, &buffer[0], max_size, encoding)) {\n      zone = &buffer[0];\n    }\n  }\n  CFRelease(tz_default);\n#endif\n#if defined(__Fuchsia__)\n  std::string primary_tz;\n  [&]() {\n    // Note: We can't use the synchronous FIDL API here because it doesn't\n    // allow timeouts; if the FIDL call failed, local_time_zone() would never\n    // return.\n\n    const zx::duration kTimeout = zx::msec(500);\n\n    // Don't attach to the thread because otherwise the thread's dispatcher\n    // would be set to null when the loop is destroyed, causing any other FIDL\n    // code running on the same thread to crash.\n    async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);\n\n    fuchsia::intl::PropertyProviderHandle handle;\n    zx_status_t status = fdio_service_connect_by_name(\n        fuchsia::intl::PropertyProvider::Name_,\n        handle.NewRequest().TakeChannel().release());\n    if (status != ZX_OK) {\n      return;\n    }\n\n    fuchsia::intl::PropertyProviderPtr intl_provider;\n    status = intl_provider.Bind(std::move(handle), loop.dispatcher());\n    if (status != ZX_OK) {\n      return;\n    }\n\n    intl_provider->GetProfile(\n        [&loop, &primary_tz](fuchsia::intl::Profile profile) {\n          if (!profile.time_zones().empty()) {\n            primary_tz = profile.time_zones()[0].id;\n          }\n          loop.Quit();\n        });\n    loop.Run(zx::deadline_after(kTimeout));\n  }();\n\n  if (!primary_tz.empty()) {\n    zone = primary_tz.c_str();\n  }\n#endif\n#if defined(_WIN32)\n  std::string win32_tz = GetWindowsLocalTimeZone();\n  if (!win32_tz.empty()) {\n    zone = win32_tz.c_str();\n  }\n#endif\n\n  // Allow ${TZ} to override to default zone.\n  char* tz_env = nullptr;\n#if defined(_MSC_VER)\n  _dupenv_s(&tz_env, nullptr, \"TZ\");\n#else\n  tz_env = std::getenv(\"TZ\");\n#endif\n  if (tz_env) zone = tz_env;\n\n  // We only support the \"[:]<zone-name>\" form.\n  if (*zone == ':') ++zone;\n\n  // Map \"localtime\" to a system-specific name, but\n  // allow ${LOCALTIME} to override the default name.\n  char* localtime_env = nullptr;\n  if (strcmp(zone, \"localtime\") == 0) {\n#if defined(_MSC_VER)\n    // System-specific default is just \"localtime\".\n    _dupenv_s(&localtime_env, nullptr, \"LOCALTIME\");\n#else\n    zone = \"/etc/localtime\";  // System-specific default.\n    localtime_env = std::getenv(\"LOCALTIME\");\n#endif\n    if (localtime_env) zone = localtime_env;\n  }\n\n  const std::string name = zone;\n#if defined(_MSC_VER)\n  free(localtime_env);\n  free(tz_env);\n#endif\n\n  time_zone tz;\n  load_time_zone(name, &tz);  // Falls back to UTC.\n  // TODO: Follow the RFC3339 \"Unknown Local Offset Convention\" and\n  // arrange for %z to generate \"-0000\" when we don't know the local\n  // offset because the load_time_zone() failed and we're using UTC.\n  return tz;\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_lookup_test.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include <chrono>\n#include <cstddef>\n#include <cstdlib>\n#include <future>\n#include <limits>\n#include <string>\n#include <thread>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n#if defined(__linux__)\n#include <features.h>\n#endif\n\n#include \"gtest/gtest.h\"\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/src/test_time_zone_names.h\"\n\nnamespace chrono = std::chrono;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\n// Helper to return a loaded time zone by value (UTC on error).\ntime_zone LoadZone(const std::string& name) {\n  time_zone tz;\n  load_time_zone(name, &tz);\n  return tz;\n}\n\n// This helper is a macro so that failed expectations show up with the\n// correct line numbers.\n#define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \\\n  do {                                                            \\\n    time_zone::absolute_lookup al = tz.lookup(tp);                \\\n    EXPECT_EQ(y, al.cs.year());                                   \\\n    EXPECT_EQ(m, al.cs.month());                                  \\\n    EXPECT_EQ(d, al.cs.day());                                    \\\n    EXPECT_EQ(hh, al.cs.hour());                                  \\\n    EXPECT_EQ(mm, al.cs.minute());                                \\\n    EXPECT_EQ(ss, al.cs.second());                                \\\n    EXPECT_EQ(off, al.offset);                                    \\\n    EXPECT_TRUE(isdst == al.is_dst);                              \\\n    /* EXPECT_STREQ(zone, al.abbr); */                            \\\n  } while (0)\n\n// These tests sometimes run on platforms that have zoneinfo data so old\n// that the transition we are attempting to check does not exist, most\n// notably Android emulators.  Fortunately, AndroidZoneInfoSource supports\n// time_zone::version() so, in cases where we've learned that it matters,\n// we can make the check conditionally.\nint VersionCmp(time_zone tz, const std::string& target) {\n  std::string version = tz.version();\n  if (version.empty() && !target.empty()) return 1;  // unknown > known\n  return version.compare(target);\n}\n\n}  // namespace\n\n#if !defined(__EMSCRIPTEN__)\nTEST(TimeZones, LoadZonesConcurrently) {\n  std::promise<void> ready_promise;\n  std::shared_future<void> ready_future(ready_promise.get_future());\n  auto load_zones = [ready_future](std::promise<void>* started,\n                                   std::set<std::string>* failures) {\n    started->set_value();\n    ready_future.wait();\n    for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {\n      std::string zone = *np;\n      time_zone tz;\n      if (load_time_zone(zone, &tz)) {\n        EXPECT_EQ(zone, tz.name());\n      } else {\n        failures->insert(zone);\n      }\n    }\n  };\n\n  const std::size_t n_threads = 128;\n  std::vector<std::thread> threads;\n  std::vector<std::set<std::string>> thread_failures(n_threads);\n  for (std::size_t i = 0; i != n_threads; ++i) {\n    std::promise<void> started;\n    threads.emplace_back(load_zones, &started, &thread_failures[i]);\n    started.get_future().wait();\n  }\n  ready_promise.set_value();\n  for (auto& thread : threads) {\n    thread.join();\n  }\n\n  // Allow a small number of failures to account for skew between\n  // the contents of kTimeZoneNames and the zoneinfo data source.\n#if defined(__ANDROID__)\n  // Cater to the possibility of using an even older zoneinfo data\n  // source when running on Android, where it is difficult to override\n  // the bionic tzdata provided by the test environment.\n  const std::size_t max_failures = 20;\n#else\n  const std::size_t max_failures = 3;\n#endif\n  std::set<std::string> failures;\n  for (const auto& thread_failure : thread_failures) {\n    failures.insert(thread_failure.begin(), thread_failure.end());\n  }\n  EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);\n}\n#endif\n\nTEST(TimeZone, UTC) {\n  const time_zone utc = utc_time_zone();\n\n  time_zone loaded_utc;\n  EXPECT_TRUE(load_time_zone(\"UTC\", &loaded_utc));\n  EXPECT_EQ(loaded_utc, utc);\n\n  time_zone loaded_utc0;\n  EXPECT_TRUE(load_time_zone(\"UTC0\", &loaded_utc0));\n  EXPECT_EQ(loaded_utc0, utc);\n\n  time_zone loaded_bad;\n  EXPECT_FALSE(load_time_zone(\"Invalid/TimeZone\", &loaded_bad));\n  EXPECT_EQ(loaded_bad, utc);\n}\n\nTEST(TimeZone, NamedTimeZones) {\n  const time_zone utc = utc_time_zone();\n  EXPECT_EQ(\"UTC\", utc.name());\n  const time_zone nyc = LoadZone(\"America/New_York\");\n  EXPECT_EQ(\"America/New_York\", nyc.name());\n  const time_zone syd = LoadZone(\"Australia/Sydney\");\n  EXPECT_EQ(\"Australia/Sydney\", syd.name());\n  const time_zone fixed0 =\n      fixed_time_zone(absl::time_internal::cctz::seconds::zero());\n  EXPECT_EQ(\"UTC\", fixed0.name());\n  const time_zone fixed_pos = fixed_time_zone(\n      chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45));\n  EXPECT_EQ(\"Fixed/UTC+03:25:45\", fixed_pos.name());\n  const time_zone fixed_neg = fixed_time_zone(\n      -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56)));\n  EXPECT_EQ(\"Fixed/UTC-12:34:56\", fixed_neg.name());\n}\n\nTEST(TimeZone, Failures) {\n  time_zone tz;\n  EXPECT_FALSE(load_time_zone(\":America/Los_Angeles\", &tz));\n\n  tz = LoadZone(\"America/Los_Angeles\");\n  EXPECT_FALSE(load_time_zone(\"Invalid/TimeZone\", &tz));\n  EXPECT_EQ(chrono::system_clock::from_time_t(0),\n            convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC\n\n  // Ensures that the load still fails on a subsequent attempt.\n  tz = LoadZone(\"America/Los_Angeles\");\n  EXPECT_FALSE(load_time_zone(\"Invalid/TimeZone\", &tz));\n  EXPECT_EQ(chrono::system_clock::from_time_t(0),\n            convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC\n\n  // Loading an empty string timezone should fail.\n  tz = LoadZone(\"America/Los_Angeles\");\n  EXPECT_FALSE(load_time_zone(\"\", &tz));\n  EXPECT_EQ(chrono::system_clock::from_time_t(0),\n            convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC\n}\n\nTEST(TimeZone, Equality) {\n  const time_zone a;\n  const time_zone b;\n  EXPECT_EQ(a, b);\n  EXPECT_EQ(a.name(), b.name());\n\n  const time_zone implicit_utc;\n  const time_zone explicit_utc = utc_time_zone();\n  EXPECT_EQ(implicit_utc, explicit_utc);\n  EXPECT_EQ(implicit_utc.name(), explicit_utc.name());\n\n  const time_zone fixed_zero =\n      fixed_time_zone(absl::time_internal::cctz::seconds::zero());\n  EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name()));\n  EXPECT_EQ(fixed_zero, explicit_utc);\n\n  const time_zone fixed_utc = LoadZone(\"Fixed/UTC+00:00:00\");\n  EXPECT_EQ(fixed_utc, LoadZone(fixed_utc.name()));\n  EXPECT_EQ(fixed_utc, explicit_utc);\n\n  const time_zone fixed_pos = fixed_time_zone(\n      chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45));\n  EXPECT_EQ(fixed_pos, LoadZone(fixed_pos.name()));\n  EXPECT_NE(fixed_pos, explicit_utc);\n  const time_zone fixed_neg = fixed_time_zone(\n      -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56)));\n  EXPECT_EQ(fixed_neg, LoadZone(fixed_neg.name()));\n  EXPECT_NE(fixed_neg, explicit_utc);\n\n  const time_zone fixed_lim = fixed_time_zone(chrono::hours(24));\n  EXPECT_EQ(fixed_lim, LoadZone(fixed_lim.name()));\n  EXPECT_NE(fixed_lim, explicit_utc);\n  const time_zone fixed_ovfl =\n      fixed_time_zone(chrono::hours(24) + chrono::seconds(1));\n  EXPECT_EQ(fixed_ovfl, LoadZone(fixed_ovfl.name()));\n  EXPECT_EQ(fixed_ovfl, explicit_utc);\n\n  EXPECT_EQ(fixed_time_zone(chrono::seconds(1)),\n            fixed_time_zone(chrono::seconds(1)));\n\n  const time_zone local = local_time_zone();\n  EXPECT_EQ(local, LoadZone(local.name()));\n\n  time_zone la = LoadZone(\"America/Los_Angeles\");\n  time_zone nyc = LoadZone(\"America/New_York\");\n  EXPECT_NE(la, nyc);\n}\n\nTEST(StdChronoTimePoint, TimeTAlignment) {\n  // Ensures that the Unix epoch and the system clock epoch are an integral\n  // number of seconds apart. This simplifies conversions to/from time_t.\n  auto diff =\n      chrono::system_clock::time_point() - chrono::system_clock::from_time_t(0);\n  EXPECT_EQ(chrono::system_clock::time_point::duration::zero(),\n            diff % chrono::seconds(1));\n}\n\nTEST(BreakTime, TimePointResolution) {\n  const time_zone utc = utc_time_zone();\n  const auto t0 = chrono::system_clock::from_time_t(0);\n\n  ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc, 1970, 1, 1,\n             0, 0, 0, 0, false, \"UTC\");\n  ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc, 1970, 1, 1,\n             0, 0, 0, 0, false, \"UTC\");\n  ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc, 1970, 1, 1,\n             0, 0, 0, 0, false, \"UTC\");\n  ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc, 1970, 1, 1, 0,\n             0, 0, 0, false, \"UTC\");\n  ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),\n             utc, 1970, 1, 1, 0, 0, 0, 0, false, \"UTC\");\n  ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc, 1970, 1, 1, 0,\n             0, 0, 0, false, \"UTC\");\n  ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc, 1970, 1, 1, 0, 0,\n             0, 0, false, \"UTC\");\n}\n\nTEST(BreakTime, LocalTimeInUTC) {\n  const time_zone tz = utc_time_zone();\n  const auto tp = chrono::system_clock::from_time_t(0);\n  ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, \"UTC\");\n  EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));\n}\n\nTEST(BreakTime, LocalTimeInUTCUnaligned) {\n  const time_zone tz = utc_time_zone();\n  const auto tp =\n      chrono::system_clock::from_time_t(0) - chrono::milliseconds(500);\n  ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, \"UTC\");\n  EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));\n}\n\nTEST(BreakTime, LocalTimePosix) {\n  // See IEEE Std 1003.1-1988 B.2.3 General Terms, Epoch.\n  const time_zone tz = utc_time_zone();\n  const auto tp = chrono::system_clock::from_time_t(536457599);\n  ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, \"UTC\");\n  EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));\n}\n\nTEST(TimeZoneImpl, LocalTimeInFixed) {\n  const absl::time_internal::cctz::seconds offset =\n      -(chrono::hours(8) + chrono::minutes(33) + chrono::seconds(47));\n  const time_zone tz = fixed_time_zone(offset);\n  const auto tp = chrono::system_clock::from_time_t(0);\n  ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false,\n             \"-083347\");\n  EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));\n}\n\nTEST(BreakTime, LocalTimeInNewYork) {\n  const time_zone tz = LoadZone(\"America/New_York\");\n  const auto tp = chrono::system_clock::from_time_t(45);\n  ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, \"EST\");\n  EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));\n}\n\nTEST(BreakTime, LocalTimeInMTV) {\n  const time_zone tz = LoadZone(\"America/Los_Angeles\");\n  const auto tp = chrono::system_clock::from_time_t(1380855729);\n  ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, \"PDT\");\n  EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));\n}\n\nTEST(BreakTime, LocalTimeInSydney) {\n  const time_zone tz = LoadZone(\"Australia/Sydney\");\n  const auto tp = chrono::system_clock::from_time_t(90);\n  ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, \"AEST\");\n  EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));\n}\n\nTEST(MakeTime, TimePointResolution) {\n  const time_zone utc = utc_time_zone();\n  const time_point<chrono::nanoseconds> tp_ns =\n      convert(civil_second(2015, 1, 2, 3, 4, 5), utc);\n  EXPECT_EQ(\"04:05\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_ns, utc));\n  const time_point<chrono::microseconds> tp_us =\n      convert(civil_second(2015, 1, 2, 3, 4, 5), utc);\n  EXPECT_EQ(\"04:05\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_us, utc));\n  const time_point<chrono::milliseconds> tp_ms =\n      convert(civil_second(2015, 1, 2, 3, 4, 5), utc);\n  EXPECT_EQ(\"04:05\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_ms, utc));\n  const time_point<chrono::seconds> tp_s =\n      convert(civil_second(2015, 1, 2, 3, 4, 5), utc);\n  EXPECT_EQ(\"04:05\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_s, utc));\n  const time_point<absl::time_internal::cctz::seconds> tp_s64 =\n      convert(civil_second(2015, 1, 2, 3, 4, 5), utc);\n  EXPECT_EQ(\"04:05\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_s64, utc));\n\n  // These next two require chrono::time_point_cast because the conversion\n  // from a resolution of seconds (the return value of convert()) to a\n  // coarser resolution requires an explicit cast.\n  const time_point<chrono::minutes> tp_m =\n      chrono::time_point_cast<chrono::minutes>(\n          convert(civil_second(2015, 1, 2, 3, 4, 5), utc));\n  EXPECT_EQ(\"04:00\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_m, utc));\n  const time_point<chrono::hours> tp_h = chrono::time_point_cast<chrono::hours>(\n      convert(civil_second(2015, 1, 2, 3, 4, 5), utc));\n  EXPECT_EQ(\"00:00\", absl::time_internal::cctz::format(\"%M:%E*S\", tp_h, utc));\n}\n\nTEST(MakeTime, Normalization) {\n  const time_zone tz = LoadZone(\"America/New_York\");\n  const auto tp = convert(civil_second(2009, 2, 13, 18, 31, 30), tz);\n  EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);\n\n  // Now requests for the same time_point but with out-of-range fields.\n  EXPECT_EQ(tp, convert(civil_second(2008, 14, 13, 18, 31, 30), tz));  // month\n  EXPECT_EQ(tp, convert(civil_second(2009, 1, 44, 18, 31, 30), tz));   // day\n  EXPECT_EQ(tp, convert(civil_second(2009, 2, 12, 42, 31, 30), tz));   // hour\n  EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 17, 91, 30), tz));   // minute\n  EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz));   // second\n}\n\n// NOTE: Run this with -ftrapv to detect overflow problems.\nTEST(MakeTime, SysSecondsLimits) {\n  const char RFC3339[] = \"%Y-%m-%d%ET%H:%M:%S%Ez\";\n  const time_zone utc = utc_time_zone();\n  const time_zone east = fixed_time_zone(chrono::hours(14));\n  const time_zone west = fixed_time_zone(-chrono::hours(14));\n  time_point<absl::time_internal::cctz::seconds> tp;\n\n  // Approach the maximal time_point<cctz::seconds> value from below.\n  tp = convert(civil_second(292277026596, 12, 4, 15, 30, 6), utc);\n  EXPECT_EQ(\"292277026596-12-04T15:30:06+00:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, utc));\n  tp = convert(civil_second(292277026596, 12, 4, 15, 30, 7), utc);\n  EXPECT_EQ(\"292277026596-12-04T15:30:07+00:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, utc));\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n  tp = convert(civil_second(292277026596, 12, 4, 15, 30, 8), utc);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n  tp = convert(civil_second::max(), utc);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n\n  // Checks that we can also get the maximal value for a far-east zone.\n  tp = convert(civil_second(292277026596, 12, 5, 5, 30, 7), east);\n  EXPECT_EQ(\"292277026596-12-05T05:30:07+14:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, east));\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n  tp = convert(civil_second(292277026596, 12, 5, 5, 30, 8), east);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n  tp = convert(civil_second::max(), east);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n\n  // Checks that we can also get the maximal value for a far-west zone.\n  tp = convert(civil_second(292277026596, 12, 4, 1, 30, 7), west);\n  EXPECT_EQ(\"292277026596-12-04T01:30:07-14:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, west));\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n  tp = convert(civil_second(292277026596, 12, 4, 7, 30, 8), west);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n  tp = convert(civil_second::max(), west);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);\n\n  // Approach the minimal time_point<cctz::seconds> value from above.\n  tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 53), utc);\n  EXPECT_EQ(\"-292277022657-01-27T08:29:53+00:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, utc));\n  tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 52), utc);\n  EXPECT_EQ(\"-292277022657-01-27T08:29:52+00:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, utc));\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n  tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 51), utc);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n  tp = convert(civil_second::min(), utc);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n\n  // Checks that we can also get the minimal value for a far-east zone.\n  tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 52), east);\n  EXPECT_EQ(\"-292277022657-01-27T22:29:52+14:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, east));\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n  tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 51), east);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n  tp = convert(civil_second::min(), east);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n\n  // Checks that we can also get the minimal value for a far-west zone.\n  tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 52), west);\n  EXPECT_EQ(\"-292277022657-01-26T18:29:52-14:00\",\n            absl::time_internal::cctz::format(RFC3339, tp, west));\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n  tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 51), west);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n  tp = convert(civil_second::min(), west);\n  EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);\n\n  // Some similar checks for the \"libc\" time-zone implementation.\n  if (sizeof(std::time_t) >= 8) {\n    // Checks that \"tm_year + 1900\", as used by the \"libc\" implementation,\n    // can produce year values beyond the range on an int without overflow.\n#if defined(_WIN32) || defined(_WIN64)\n    // localtime_s() and gmtime_s() don't believe in years outside [1970:3000].\n#else\n    const time_zone cut = LoadZone(\"libc:UTC\");\n    const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;\n    tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut);\n#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)\n    // Some gmtime_r() impls fail on extreme positive values.\n#else\n    EXPECT_EQ(\"2147485547-12-31T23:59:59+00:00\",\n              absl::time_internal::cctz::format(RFC3339, tp, cut));\n#endif\n    const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;\n    tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut);\n#if defined(__Fuchsia__) || defined(__EMSCRIPTEN__)\n    // Some gmtime_r() impls fail on extreme negative values (fxbug.dev/78527).\n#else\n    EXPECT_EQ(\"-2147481748-01-01T00:00:00+00:00\",\n              absl::time_internal::cctz::format(RFC3339, tp, cut));\n#endif\n#endif\n  }\n}\n\nTEST(MakeTime, LocalTimeLibC) {\n  // Checks that cctz and libc agree on transition points in [1970:2037].\n  //\n  // We limit this test case to environments where:\n  //  1) we know how to change the time zone used by localtime()/mktime(),\n  //  2) cctz and localtime()/mktime() will use similar-enough tzdata, and\n  //  3) we have some idea about how mktime() behaves during transitions.\n#if defined(__linux__) && defined(__GLIBC__) && !defined(__ANDROID__)\n  const char* const ep = getenv(\"TZ\");\n  std::string tz_name = (ep != nullptr) ? ep : \"\";\n  for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {\n    ASSERT_EQ(0, setenv(\"TZ\", *np, 1));  // change what \"localtime\" means\n    const auto zi = local_time_zone();\n    const auto lc = LoadZone(\"libc:localtime\");\n    time_zone::civil_transition transition;\n    for (auto tp = zi.lookup(civil_second()).trans;\n         zi.next_transition(tp, &transition);\n         tp = zi.lookup(transition.to).trans) {\n      const auto fcl = zi.lookup(transition.from);\n      const auto tcl = zi.lookup(transition.to);\n      civil_second cs, us;  // compare cs and us in zi and lc\n      if (fcl.kind == time_zone::civil_lookup::UNIQUE) {\n        if (tcl.kind == time_zone::civil_lookup::UNIQUE) {\n          // Both unique; must be an is_dst or abbr change.\n          ASSERT_EQ(transition.from, transition.to);\n          const auto trans = fcl.trans;\n          const auto tal = zi.lookup(trans);\n          const auto tprev = trans - absl::time_internal::cctz::seconds(1);\n          const auto pal = zi.lookup(tprev);\n          if (pal.is_dst == tal.is_dst) {\n            ASSERT_STRNE(pal.abbr, tal.abbr);\n          }\n          continue;\n        }\n        ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);\n        cs = transition.to;\n        us = transition.from;\n      } else {\n        ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);\n        ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);\n        cs = transition.from;\n        us = transition.to;\n      }\n      if (us.year() > 2037) break;  // limit test time (and to 32-bit time_t)\n      const auto cl_zi = zi.lookup(cs);\n      if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) {\n        // The \"libc\" implementation cannot correctly classify transitions\n        // that don't change the \"tm_isdst\" flag.  In Europe/Volgograd, for\n        // example, there is a SKIPPED transition from +03 to +04 with dst=F\n        // on both sides ...\n        //   1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800]\n        //   1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400]\n        // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike,\n        // say, the similar Europe/Chisinau transition from +02 to +03 ...\n        //   1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200]\n        //   1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800]\n        // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and\n        // returns 1521936000.\n        continue;\n      }\n      if (cs == civil_second(2037, 10, 4, 2, 0, 0)) {\n        const std::string tzname = *np;\n        if (tzname == \"Africa/Casablanca\" || tzname == \"Africa/El_Aaiun\") {\n          // The \"libc\" implementation gets this transition wrong (at least\n          // until 2018g when it was removed), returning an offset of 3600\n          // instead of 0.  TODO: Revert this when 2018g is ubiquitous.\n          continue;\n        }\n      }\n      const auto cl_lc = lc.lookup(cs);\n      SCOPED_TRACE(testing::Message() << \"For \" << cs << \" in \" << *np);\n      EXPECT_EQ(cl_zi.kind, cl_lc.kind);\n      EXPECT_EQ(cl_zi.pre, cl_lc.pre);\n      EXPECT_EQ(cl_zi.trans, cl_lc.trans);\n      EXPECT_EQ(cl_zi.post, cl_lc.post);\n      const auto ucl_zi = zi.lookup(us);\n      const auto ucl_lc = lc.lookup(us);\n      SCOPED_TRACE(testing::Message() << \"For \" << us << \" in \" << *np);\n      EXPECT_EQ(ucl_zi.kind, ucl_lc.kind);\n      EXPECT_EQ(ucl_zi.pre, ucl_lc.pre);\n      EXPECT_EQ(ucl_zi.trans, ucl_lc.trans);\n      EXPECT_EQ(ucl_zi.post, ucl_lc.post);\n    }\n  }\n  if (ep == nullptr) {\n    ASSERT_EQ(0, unsetenv(\"TZ\"));\n  } else {\n    ASSERT_EQ(0, setenv(\"TZ\", tz_name.c_str(), 1));\n  }\n#endif\n}\n\nTEST(NextTransition, UTC) {\n  const auto tz = utc_time_zone();\n  time_zone::civil_transition trans;\n\n  auto tp = time_point<absl::time_internal::cctz::seconds>::min();\n  EXPECT_FALSE(tz.next_transition(tp, &trans));\n\n  tp = time_point<absl::time_internal::cctz::seconds>::max();\n  EXPECT_FALSE(tz.next_transition(tp, &trans));\n}\n\nTEST(PrevTransition, UTC) {\n  const auto tz = utc_time_zone();\n  time_zone::civil_transition trans;\n\n  auto tp = time_point<absl::time_internal::cctz::seconds>::max();\n  EXPECT_FALSE(tz.prev_transition(tp, &trans));\n\n  tp = time_point<absl::time_internal::cctz::seconds>::min();\n  EXPECT_FALSE(tz.prev_transition(tp, &trans));\n}\n\nTEST(NextTransition, AmericaNewYork) {\n  const auto tz = LoadZone(\"America/New_York\");\n  time_zone::civil_transition trans;\n\n  auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz);\n  EXPECT_TRUE(tz.next_transition(tp, &trans));\n  EXPECT_EQ(civil_second(2018, 11, 4, 2, 0, 0), trans.from);\n  EXPECT_EQ(civil_second(2018, 11, 4, 1, 0, 0), trans.to);\n\n  tp = time_point<absl::time_internal::cctz::seconds>::max();\n  EXPECT_FALSE(tz.next_transition(tp, &trans));\n\n  tp = time_point<absl::time_internal::cctz::seconds>::min();\n  EXPECT_TRUE(tz.next_transition(tp, &trans));\n  if (trans.from == civil_second(1918, 3, 31, 2, 0, 0)) {\n    // It looks like the tzdata is only 32 bit (probably macOS),\n    // which bottoms out at 1901-12-13T20:45:52+00:00.\n    EXPECT_EQ(civil_second(1918, 3, 31, 3, 0, 0), trans.to);\n  } else {\n    EXPECT_EQ(civil_second(1883, 11, 18, 12, 3, 58), trans.from);\n    EXPECT_EQ(civil_second(1883, 11, 18, 12, 0, 0), trans.to);\n  }\n}\n\nTEST(PrevTransition, AmericaNewYork) {\n  const auto tz = LoadZone(\"America/New_York\");\n  time_zone::civil_transition trans;\n\n  auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz);\n  EXPECT_TRUE(tz.prev_transition(tp, &trans));\n  EXPECT_EQ(civil_second(2018, 3, 11, 2, 0, 0), trans.from);\n  EXPECT_EQ(civil_second(2018, 3, 11, 3, 0, 0), trans.to);\n\n  tp = time_point<absl::time_internal::cctz::seconds>::min();\n  EXPECT_FALSE(tz.prev_transition(tp, &trans));\n\n  tp = time_point<absl::time_internal::cctz::seconds>::max();\n  EXPECT_TRUE(tz.prev_transition(tp, &trans));\n  // We have a transition but we don't know which one.\n}\n\nTEST(NextTransition, Scan) {\n  for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {\n    SCOPED_TRACE(testing::Message() << \"In \" << *np);\n    time_zone tz;\n    // EXPECT_TRUE(load_time_zone(*np, &tz));\n    if (!load_time_zone(*np, &tz)) {\n      continue;  // tolerate kTimeZoneNames/zoneinfo skew\n    }\n\n    auto tp = time_point<absl::time_internal::cctz::seconds>::min();\n    time_zone::civil_transition trans;\n    while (tz.next_transition(tp, &trans)) {\n      time_zone::civil_lookup from_cl = tz.lookup(trans.from);\n      EXPECT_NE(from_cl.kind, time_zone::civil_lookup::REPEATED);\n      time_zone::civil_lookup to_cl = tz.lookup(trans.to);\n      EXPECT_NE(to_cl.kind, time_zone::civil_lookup::SKIPPED);\n\n      auto trans_tp = to_cl.trans;\n      time_zone::absolute_lookup trans_al = tz.lookup(trans_tp);\n      EXPECT_EQ(trans_al.cs, trans.to);\n      auto pre_trans_tp = trans_tp - absl::time_internal::cctz::seconds(1);\n      time_zone::absolute_lookup pre_trans_al = tz.lookup(pre_trans_tp);\n      EXPECT_EQ(pre_trans_al.cs + 1, trans.from);\n\n      auto offset_delta = trans_al.offset - pre_trans_al.offset;\n      EXPECT_EQ(offset_delta, trans.to - trans.from);\n      if (offset_delta == 0) {\n        // This \"transition\" is only an is_dst or abbr change.\n        EXPECT_EQ(to_cl.kind, time_zone::civil_lookup::UNIQUE);\n        if (trans_al.is_dst == pre_trans_al.is_dst) {\n          EXPECT_STRNE(trans_al.abbr, pre_trans_al.abbr);\n        }\n      }\n\n      tp = trans_tp;  // continue scan from transition\n    }\n  }\n}\n\nTEST(TimeZoneEdgeCase, AmericaNewYork) {\n  const time_zone tz = LoadZone(\"America/New_York\");\n\n  // Spring 1:59:59 -> 3:00:00\n  auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -5 * 3600, false, \"EST\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -4 * 3600, true, \"EDT\");\n\n  // Fall 1:59:59 -> 1:00:00\n  tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -4 * 3600, true, \"EDT\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -5 * 3600, false, \"EST\");\n}\n\nTEST(TimeZoneEdgeCase, AmericaLosAngeles) {\n  const time_zone tz = LoadZone(\"America/Los_Angeles\");\n\n  // Spring 1:59:59 -> 3:00:00\n  auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -8 * 3600, false, \"PST\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -7 * 3600, true, \"PDT\");\n\n  // Fall 1:59:59 -> 1:00:00\n  tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, true, \"PDT\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -8 * 3600, false, \"PST\");\n}\n\nTEST(TimeZoneEdgeCase, ArizonaNoTransition) {\n  const time_zone tz = LoadZone(\"America/Phoenix\");\n\n  // No transition in Spring.\n  auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -7 * 3600, false, \"MST\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 3, 10, 2, 0, 0, -7 * 3600, false, \"MST\");\n\n  // No transition in Fall.\n  tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, false, \"MST\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 11, 3, 2, 0, 0, -7 * 3600, false, \"MST\");\n}\n\nTEST(TimeZoneEdgeCase, AsiaKathmandu) {\n  const time_zone tz = LoadZone(\"Asia/Kathmandu\");\n\n  // A non-DST offset change from +0530 to +0545\n  //\n  //   504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (+0530)\n  //   504901800 == Wed,  1 Jan 1986 00:15:00 +0545 (+0545)\n  auto tp = convert(civil_second(1985, 12, 31, 23, 59, 59), tz);\n  ExpectTime(tp, tz, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, \"+0530\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, \"+0545\");\n}\n\nTEST(TimeZoneEdgeCase, PacificChatham) {\n  const time_zone tz = LoadZone(\"Pacific/Chatham\");\n\n  // One-hour DST offset changes, but at atypical values\n  //\n  //   1365256799 == Sun,  7 Apr 2013 03:44:59 +1345 (+1345)\n  //   1365256800 == Sun,  7 Apr 2013 02:45:00 +1245 (+1245)\n  auto tp = convert(civil_second(2013, 4, 7, 3, 44, 59), tz);\n  ExpectTime(tp, tz, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, \"+1345\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, \"+1245\");\n\n  //   1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (+1245)\n  //   1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (+1345)\n  tp = convert(civil_second(2013, 9, 29, 2, 44, 59), tz);\n  ExpectTime(tp, tz, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, \"+1245\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, \"+1345\");\n}\n\nTEST(TimeZoneEdgeCase, AustraliaLordHowe) {\n  const time_zone tz = LoadZone(\"Australia/Lord_Howe\");\n\n  // Half-hour DST offset changes\n  //\n  //   1365260399 == Sun,  7 Apr 2013 01:59:59 +1100 (+11)\n  //   1365260400 == Sun,  7 Apr 2013 01:30:00 +1030 (+1030)\n  auto tp = convert(civil_second(2013, 4, 7, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, \"+11\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, \"+1030\");\n\n  //   1380986999 == Sun,  6 Oct 2013 01:59:59 +1030 (+1030)\n  //   1380987000 == Sun,  6 Oct 2013 02:30:00 +1100 (+11)\n  tp = convert(civil_second(2013, 10, 6, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, \"+1030\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, \"+11\");\n}\n\nTEST(TimeZoneEdgeCase, PacificApia) {\n  const time_zone tz = LoadZone(\"Pacific/Apia\");\n\n  // At the end of December 2011, Samoa jumped forward by one day,\n  // skipping 30 December from the local calendar, when the nation\n  // moved to the west of the International Date Line.\n  //\n  // A one-day, non-DST offset change\n  //\n  //   1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (-10)\n  //   1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14)\n  auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz);\n  ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, \"-10\");\n  EXPECT_EQ(363, get_yearday(convert(tp, tz)));\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, \"+14\");\n  EXPECT_EQ(365, get_yearday(convert(tp, tz)));\n}\n\nTEST(TimeZoneEdgeCase, AfricaCairo) {\n  const time_zone tz = LoadZone(\"Africa/Cairo\");\n\n  if (VersionCmp(tz, \"2014c\") >= 0) {\n    // An interesting case of midnight not existing.\n    //\n    //   1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET)\n    //   1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST)\n    auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz);\n    ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, \"EET\");\n    tp += absl::time_internal::cctz::seconds(1);\n    ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, \"EEST\");\n  }\n}\n\nTEST(TimeZoneEdgeCase, AfricaMonrovia) {\n  const time_zone tz = LoadZone(\"Africa/Monrovia\");\n\n  if (VersionCmp(tz, \"2017b\") >= 0) {\n    // Strange offset change -00:44:30 -> +00:00:00 (non-DST)\n    //\n    //   63593069 == Thu,  6 Jan 1972 23:59:59 -0044 (MMT)\n    //   63593070 == Fri,  7 Jan 1972 00:44:30 +0000 (GMT)\n    auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz);\n    ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, \"MMT\");\n    tp += absl::time_internal::cctz::seconds(1);\n    ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, \"GMT\");\n  }\n}\n\nTEST(TimeZoneEdgeCase, AmericaJamaica) {\n  // Jamaica discontinued DST transitions in 1983, and is now at a\n  // constant -0500.  This makes it an interesting edge-case target.\n  // Note that the 32-bit times used in a (tzh_version == 0) zoneinfo\n  // file cannot represent the abbreviation-only transition of 1890,\n  // so we ignore the abbreviation by expecting what we received.\n  const time_zone tz = LoadZone(\"America/Jamaica\");\n\n  // Before the first transition.\n  if (!tz.version().empty() && VersionCmp(tz, \"2018d\") >= 0) {\n    // We avoid the expectations on the -18430 offset below unless we are\n    // certain we have commit 907241e (Fix off-by-1 error for Jamaica and\n    // T&C before 1913) from 2018d.  TODO: Remove the \"version() not empty\"\n    // part when 2018d is generally available from /usr/share/zoneinfo.\n    auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz);\n    ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false,\n               tz.lookup(tp).abbr);\n\n    // Over the first (abbreviation-change only) transition.\n    //   -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT)\n    //   -2524503169 == Wed,  1 Jan 1890 00:00:00 -0507 (KMT)\n    tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz);\n    ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false,\n               tz.lookup(tp).abbr);\n    tp += absl::time_internal::cctz::seconds(1);\n    ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, \"KMT\");\n  }\n\n  // Over the last (DST) transition.\n  //     436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT)\n  //     436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST)\n  auto tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz);\n  ExpectTime(tp, tz, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, \"EDT\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, \"EST\");\n\n  // After the last transition.\n  tp = convert(civil_second(1983, 12, 31, 23, 59, 59), tz);\n  ExpectTime(tp, tz, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, \"EST\");\n}\n\nTEST(TimeZoneEdgeCase, EuropeLisbon) {\n  // Cover a non-existent time within a forward transition.\n  const time_zone tz = LoadZone(\"Europe/Lisbon\");\n\n  // Over a forward transition.\n  //     354671999 == Sat, 28 Mar 1981 23:59:59 +0000 (WET)\n  //     354672000 == Sun, 29 Mar 1981 01:00:00 +0100 (WEST)\n  auto tp = convert(civil_second(1981, 3, 28, 23, 59, 59), tz);\n  ExpectTime(tp, tz, 1981, 3, 28, 23, 59, 59, 0, false, \"WET\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 1981, 3, 29, 1, 0, 0, 1 * 3600, true, \"WEST\");\n\n  // A non-existent time within the transition.\n  time_zone::civil_lookup cl1 = tz.lookup(civil_second(1981, 3, 29, 0, 15, 0));\n  EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl1.kind);\n  ExpectTime(cl1.pre, tz, 1981, 3, 29, 1, 15, 0, 1 * 3600, true, \"WEST\");\n  ExpectTime(cl1.trans, tz, 1981, 3, 29, 1, 0, 0, 1 * 3600, true, \"WEST\");\n  ExpectTime(cl1.post, tz, 1981, 3, 28, 23, 15, 0, 0 * 3600, false, \"WET\");\n}\n\nTEST(TimeZoneEdgeCase, FixedOffsets) {\n  const time_zone gmtm5 = LoadZone(\"Etc/GMT+5\");  // -0500\n  auto tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtm5);\n  ExpectTime(tp, gmtm5, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, \"-05\");\n  EXPECT_EQ(chrono::system_clock::from_time_t(5 * 3600), tp);\n\n  const time_zone gmtp5 = LoadZone(\"Etc/GMT-5\");  // +0500\n  tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtp5);\n  ExpectTime(tp, gmtp5, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, \"+05\");\n  EXPECT_EQ(chrono::system_clock::from_time_t(-5 * 3600), tp);\n}\n\nTEST(TimeZoneEdgeCase, NegativeYear) {\n  // Tests transition from year 0 (aka 1BCE) to year -1.\n  const time_zone tz = utc_time_zone();\n  auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz);\n  ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, \"UTC\");\n  EXPECT_EQ(weekday::saturday, get_weekday(convert(tp, tz)));\n  tp -= absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, \"UTC\");\n  EXPECT_EQ(weekday::friday, get_weekday(convert(tp, tz)));\n}\n\nTEST(TimeZoneEdgeCase, UTC32bitLimit) {\n  const time_zone tz = utc_time_zone();\n\n  // Limits of signed 32-bit time_t\n  //\n  //   2147483647 == Tue, 19 Jan 2038 03:14:07 +0000 (UTC)\n  //   2147483648 == Tue, 19 Jan 2038 03:14:08 +0000 (UTC)\n  auto tp = convert(civil_second(2038, 1, 19, 3, 14, 7), tz);\n  ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 7, 0 * 3600, false, \"UTC\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 8, 0 * 3600, false, \"UTC\");\n}\n\nTEST(TimeZoneEdgeCase, UTC5DigitYear) {\n  const time_zone tz = utc_time_zone();\n\n  // Rollover to 5-digit year\n  //\n  //   253402300799 == Fri, 31 Dec 9999 23:59:59 +0000 (UTC)\n  //   253402300800 == Sat,  1 Jan 1000 00:00:00 +0000 (UTC)\n  auto tp = convert(civil_second(9999, 12, 31, 23, 59, 59), tz);\n  ExpectTime(tp, tz, 9999, 12, 31, 23, 59, 59, 0 * 3600, false, \"UTC\");\n  tp += absl::time_internal::cctz::seconds(1);\n  ExpectTime(tp, tz, 10000, 1, 1, 0, 0, 0, 0 * 3600, false, \"UTC\");\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_name_win.cc",
    "content": "// Copyright 2025 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/src/time_zone_name_win.h\"\n\n#include \"absl/base/config.h\"\n\n#if !defined(NOMINMAX)\n#define NOMINMAX\n#endif  // !defined(NOMINMAX)\n#include <windows.h>\n\n#include <algorithm>\n#include <atomic>\n#include <cstddef>\n#include <cstdint>\n#include <limits>\n#include <string>\n#include <type_traits>\n#include <utility>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\nnamespace {\n\n// Define UChar as wchar_t here because Win32 APIs receive UTF-16 strings as\n// wchar_t* instead of char16_t*. Using char16_t would require additional casts.\nusing UChar = wchar_t;\n\nenum UErrorCode : std::int32_t {\n  U_ZERO_ERROR = 0,\n  U_BUFFER_OVERFLOW_ERROR = 15,\n};\n\nbool U_SUCCESS(UErrorCode error) { return error <= U_ZERO_ERROR; }\n\nusing ucal_getTimeZoneIDForWindowsID_func = std::int32_t(__cdecl*)(\n    const UChar* winid, std::int32_t len, const char* region, UChar* id,\n    std::int32_t id_capacity, UErrorCode* status);\n\nstd::atomic<bool> g_unavailable;\nstd::atomic<ucal_getTimeZoneIDForWindowsID_func>\n    g_ucal_getTimeZoneIDForWindowsID;\n\ntemplate <typename T>\nstatic T AsProcAddress(HMODULE module, const char* name) {\n  static_assert(\n      std::is_pointer<T>::value &&\n          std::is_function<typename std::remove_pointer<T>::type>::value,\n      \"T must be a function pointer type\");\n  const auto proc_address = ::GetProcAddress(module, name);\n  return reinterpret_cast<T>(reinterpret_cast<void*>(proc_address));\n}\n\nstd::wstring GetSystem32Dir() {\n  std::wstring result;\n  std::uint32_t len = std::max<std::uint32_t>(\n      static_cast<std::uint32_t>(std::min<size_t>(\n          result.capacity(), std::numeric_limits<std::uint32_t>::max())),\n      1);\n  do {\n    result.resize(len);\n    len = ::GetSystemDirectoryW(&result[0], len);\n  } while (len > result.size());\n  result.resize(len);\n  return result;\n}\n\nucal_getTimeZoneIDForWindowsID_func LoadIcuGetTimeZoneIDForWindowsID() {\n  // This function is intended to be lock free to avoid potential deadlocks\n  // with loader-lock taken inside LoadLibraryW. As LoadLibraryW and\n  // GetProcAddress are idempotent unless the DLL is unloaded, we just need to\n  // make sure global variables are read/written atomically, where\n  // memory_order_relaxed is also acceptable.\n\n  if (g_unavailable.load(std::memory_order_relaxed)) {\n    return nullptr;\n  }\n\n  {\n    const auto ucal_getTimeZoneIDForWindowsIDRef =\n        g_ucal_getTimeZoneIDForWindowsID.load(std::memory_order_relaxed);\n    if (ucal_getTimeZoneIDForWindowsIDRef != nullptr) {\n      return ucal_getTimeZoneIDForWindowsIDRef;\n    }\n  }\n\n  const std::wstring system32_dir = GetSystem32Dir();\n  if (system32_dir.empty()) {\n    g_unavailable.store(true, std::memory_order_relaxed);\n    return nullptr;\n  }\n\n  // Here LoadLibraryExW(L\"icu.dll\", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) does\n  // not work if \"icu.dll\" is already loaded from somewhere other than the\n  // system32 directory. Specifying the full path with LoadLibraryW is more\n  // reliable.\n  const std::wstring icu_dll_path = system32_dir + L\"\\\\icu.dll\";\n  const HMODULE icu_dll = ::LoadLibraryW(icu_dll_path.c_str());\n  if (icu_dll == nullptr) {\n    g_unavailable.store(true, std::memory_order_relaxed);\n    return nullptr;\n  }\n\n  const auto ucal_getTimeZoneIDForWindowsIDRef =\n      AsProcAddress<ucal_getTimeZoneIDForWindowsID_func>(\n          icu_dll, \"ucal_getTimeZoneIDForWindowsID\");\n  if (ucal_getTimeZoneIDForWindowsIDRef != nullptr) {\n    g_unavailable.store(true, std::memory_order_relaxed);\n    return nullptr;\n  }\n\n  g_ucal_getTimeZoneIDForWindowsID.store(ucal_getTimeZoneIDForWindowsIDRef,\n                                         std::memory_order_relaxed);\n\n  return ucal_getTimeZoneIDForWindowsIDRef;\n}\n\n// Convert wchar_t array (UTF-16) to UTF-8 string\nstd::string Utf16ToUtf8(const wchar_t* ptr, size_t size) {\n  if (size > static_cast<size_t>(std::numeric_limits<int>::max())) {\n    return std::string();\n  }\n  const int chars_len = static_cast<int>(size);\n  std::string result;\n  std::size_t len = std::max<std::size_t>(\n      std::min<size_t>(result.capacity(), std::numeric_limits<int>::max()), 1);\n  do {\n    result.resize(len);\n    len = static_cast<std::size_t>(::WideCharToMultiByte(\n        CP_UTF8, WC_ERR_INVALID_CHARS, ptr, chars_len, &result[0],\n        static_cast<int>(len), nullptr, nullptr));\n  } while (len > result.size());\n  result.resize(len);\n  return result;\n}\n\n}  // namespace\n\nstd::string GetWindowsLocalTimeZone() {\n  const auto getTimeZoneIDForWindowsID = LoadIcuGetTimeZoneIDForWindowsID();\n  if (getTimeZoneIDForWindowsID == nullptr) {\n    return std::string();\n  }\n\n  DYNAMIC_TIME_ZONE_INFORMATION info = {};\n  if (::GetDynamicTimeZoneInformation(&info) == TIME_ZONE_ID_INVALID) {\n    return std::string();\n  }\n\n  std::wstring result;\n  std::size_t len = std::max<std::size_t>(\n      std::min<size_t>(result.capacity(), std::numeric_limits<int>::max()), 1);\n  for (;;) {\n    UErrorCode status = U_ZERO_ERROR;\n    result.resize(len);\n    len = static_cast<std::size_t>(\n        getTimeZoneIDForWindowsID(info.TimeZoneKeyName, -1, nullptr, &result[0],\n                                  static_cast<int>(len), &status));\n    if (U_SUCCESS(status)) {\n      return Utf16ToUtf8(result.data(), len);\n    }\n    if (status != U_BUFFER_OVERFLOW_ERROR) {\n      return std::string();\n    }\n  }\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_name_win.h",
    "content": "// Copyright 2025 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_NAME_WIN_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_NAME_WIN_H_\n\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// Returns the local time zone ID in IANA format (e.g. \"America/Los_Angeles\"),\n// or the empty string on failure. Not supported on Windows 10 1809 and earlier,\n// where \"icu.dll\" is not available in the System32 directory.\nstd::string GetWindowsLocalTimeZone();\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_NAME_WIN_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_posix.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/src/time_zone_posix.h\"\n\n#include <cstddef>\n#include <cstring>\n#include <limits>\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\nnamespace {\n\nconst char kDigits[] = \"0123456789\";\n\nconst char* ParseInt(const char* p, int min, int max, int* vp) {\n  int value = 0;\n  const char* op = p;\n  const int kMaxInt = std::numeric_limits<int>::max();\n  for (; const char* dp = strchr(kDigits, *p); ++p) {\n    int d = static_cast<int>(dp - kDigits);\n    if (d >= 10) break;  // '\\0'\n    if (value > kMaxInt / 10) return nullptr;\n    value *= 10;\n    if (value > kMaxInt - d) return nullptr;\n    value += d;\n  }\n  if (p == op || value < min || value > max) return nullptr;\n  *vp = value;\n  return p;\n}\n\n// abbr = <.*?> | [^-+,\\d]{3,}\nconst char* ParseAbbr(const char* p, std::string* abbr) {\n  const char* op = p;\n  if (*p == '<') {  // special zoneinfo <...> form\n    while (*++p != '>') {\n      if (*p == '\\0') return nullptr;\n    }\n    abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1);\n    return ++p;\n  }\n  while (*p != '\\0') {\n    if (strchr(\"-+,\", *p)) break;\n    if (strchr(kDigits, *p)) break;\n    ++p;\n  }\n  if (p - op < 3) return nullptr;\n  abbr->assign(op, static_cast<std::size_t>(p - op));\n  return p;\n}\n\n// offset = [+|-]hh[:mm[:ss]] (aggregated into single seconds value)\nconst char* ParseOffset(const char* p, int min_hour, int max_hour, int sign,\n                        std::int_fast32_t* offset) {\n  if (p == nullptr) return nullptr;\n  if (*p == '+' || *p == '-') {\n    if (*p++ == '-') sign = -sign;\n  }\n  int hours = 0;\n  int minutes = 0;\n  int seconds = 0;\n\n  p = ParseInt(p, min_hour, max_hour, &hours);\n  if (p == nullptr) return nullptr;\n  if (*p == ':') {\n    p = ParseInt(p + 1, 0, 59, &minutes);\n    if (p == nullptr) return nullptr;\n    if (*p == ':') {\n      p = ParseInt(p + 1, 0, 59, &seconds);\n      if (p == nullptr) return nullptr;\n    }\n  }\n  *offset = sign * ((((hours * 60) + minutes) * 60) + seconds);\n  return p;\n}\n\n// datetime = ( Jn | n | Mm.w.d ) [ / offset ]\nconst char* ParseDateTime(const char* p, PosixTransition* res) {\n  if (p != nullptr && *p == ',') {\n    if (*++p == 'M') {\n      int month = 0;\n      if ((p = ParseInt(p + 1, 1, 12, &month)) != nullptr && *p == '.') {\n        int week = 0;\n        if ((p = ParseInt(p + 1, 1, 5, &week)) != nullptr && *p == '.') {\n          int weekday = 0;\n          if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) {\n            res->date.fmt = PosixTransition::M;\n            res->date.m.month = static_cast<std::int_fast8_t>(month);\n            res->date.m.week = static_cast<std::int_fast8_t>(week);\n            res->date.m.weekday = static_cast<std::int_fast8_t>(weekday);\n          }\n        }\n      }\n    } else if (*p == 'J') {\n      int day = 0;\n      if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) {\n        res->date.fmt = PosixTransition::J;\n        res->date.j.day = static_cast<std::int_fast16_t>(day);\n      }\n    } else {\n      int day = 0;\n      if ((p = ParseInt(p, 0, 365, &day)) != nullptr) {\n        res->date.fmt = PosixTransition::N;\n        res->date.n.day = static_cast<std::int_fast16_t>(day);\n      }\n    }\n  }\n  if (p != nullptr) {\n    res->time.offset = 2 * 60 * 60;  // default offset is 02:00:00\n    if (*p == '/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset);\n  }\n  return p;\n}\n\n}  // namespace\n\n// spec = std offset [ dst [ offset ] , datetime , datetime ]\nbool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) {\n  const char* p = spec.c_str();\n  if (*p == ':') return false;\n\n  p = ParseAbbr(p, &res->std_abbr);\n  p = ParseOffset(p, 0, 24, -1, &res->std_offset);\n  if (p == nullptr) return false;\n  if (*p == '\\0') return true;\n\n  p = ParseAbbr(p, &res->dst_abbr);\n  if (p == nullptr) return false;\n  res->dst_offset = res->std_offset + (60 * 60);  // default\n  if (*p != ',') p = ParseOffset(p, 0, 24, -1, &res->dst_offset);\n\n  p = ParseDateTime(p, &res->dst_start);\n  p = ParseDateTime(p, &res->dst_end);\n\n  return p != nullptr && *p == '\\0';\n}\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/src/time_zone_posix.h",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n// Parsing of a POSIX zone spec as described in the TZ part of section 8.3 in\n// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html.\n//\n// The current POSIX spec for America/Los_Angeles is \"PST8PDT,M3.2.0,M11.1.0\",\n// which would be broken down as ...\n//\n//   PosixTimeZone {\n//     std_abbr = \"PST\"\n//     std_offset = -28800\n//     dst_abbr = \"PDT\"\n//     dst_offset = -25200\n//     dst_start = PosixTransition {\n//       date {\n//         m {\n//           month = 3\n//           week = 2\n//           weekday = 0\n//         }\n//       }\n//       time {\n//         offset = 7200\n//       }\n//     }\n//     dst_end = PosixTransition {\n//       date {\n//         m {\n//           month = 11\n//           week = 1\n//           weekday = 0\n//         }\n//       }\n//       time {\n//         offset = 7200\n//       }\n//     }\n//   }\n\n#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_\n#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_\n\n#include <cstdint>\n#include <string>\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// The date/time of the transition. The date is specified as either:\n// (J) the Nth day of the year (1 <= N <= 365), excluding leap days, or\n// (N) the Nth day of the year (0 <= N <= 365), including leap days, or\n// (M) the Nth weekday of a month (e.g., the 2nd Sunday in March).\n// The time, specified as a day offset, identifies the particular moment\n// of the transition, and may be negative or >= 24h, and in which case\n// it would take us to another day, and perhaps week, or even month.\nstruct PosixTransition {\n  enum DateFormat { J, N, M };\n\n  struct Date {\n    struct NonLeapDay {\n      std::int_fast16_t day;  // day of non-leap year [1:365]\n    };\n    struct Day {\n      std::int_fast16_t day;  // day of year [0:365]\n    };\n    struct MonthWeekWeekday {\n      std::int_fast8_t month;    // month of year [1:12]\n      std::int_fast8_t week;     // week of month [1:5] (5==last)\n      std::int_fast8_t weekday;  // 0==Sun, ..., 6=Sat\n    };\n\n    DateFormat fmt;\n\n    union {\n      NonLeapDay j;\n      Day n;\n      MonthWeekWeekday m;\n    };\n  };\n\n  struct Time {\n    std::int_fast32_t offset;  // seconds before/after 00:00:00\n  };\n\n  Date date;\n  Time time;\n};\n\n// The entirety of a POSIX-string specified time-zone rule. The standard\n// abbreviation and offset are always given. If the time zone includes\n// daylight saving, then the daylight abbreviation is non-empty and the\n// remaining fields are also valid. Note that the start/end transitions\n// are not ordered---in the southern hemisphere the transition to end\n// daylight time occurs first in any particular year.\nstruct PosixTimeZone {\n  std::string std_abbr;\n  std::int_fast32_t std_offset;\n\n  std::string dst_abbr;\n  std::int_fast32_t dst_offset;\n  PosixTransition dst_start;\n  PosixTransition dst_end;\n};\n\n// Breaks down a POSIX time-zone specification into its constituent pieces,\n// filling in any missing values (DST offset, or start/end transition times)\n// with the standard-defined defaults. Returns false if the specification\n// could not be parsed (although some fields of *res may have been altered).\nbool ParsePosixSpec(const std::string& spec, PosixTimeZone* res);\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_\n"
  },
  {
    "path": "absl/time/internal/cctz/src/tzfile.h",
    "content": "/* Layout and location of TZif files.  */\n\n#ifndef TZFILE_H\n\n#define TZFILE_H\n\n/*\n** This file is in the public domain, so clarified as of\n** 1996-06-05 by Arthur David Olson.\n*/\n\n/*\n** This header is for use ONLY with the time conversion code.\n** There is no guarantee that it will remain unchanged,\n** or that it will remain at all.\n** Do NOT copy it to any system include directory.\n** Thank you!\n*/\n\n/* Information about time zone files.\n   See Internet RFC 9636 for more details about the following format.  */\n\n/*\n** Each file begins with. . .\n*/\n\n#define TZ_MAGIC \"TZif\"\n\nstruct tzhead {\n  char tzh_magic[4];      /* TZ_MAGIC */\n  char tzh_version[1];    /* '\\0' or '2'-'4' as of 2021 */\n  char tzh_reserved[15];  /* reserved; must be zero */\n  char tzh_ttisutcnt[4];  /* coded number of trans. time flags */\n  char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */\n  char tzh_leapcnt[4];    /* coded number of leap seconds */\n  char tzh_timecnt[4];    /* coded number of transition times */\n  char tzh_typecnt[4];    /* coded number of local time types */\n  char tzh_charcnt[4];    /* coded number of abbr. chars */\n};\n\n/*\n** . . .followed by. . .\n**\n**\ttzh_timecnt (char [4])s\t\tcoded transition times a la time(2)\n**\ttzh_timecnt (unsigned char)s\ttypes of local time starting at above\n**\ttzh_typecnt repetitions of\n**\t\tone (char [4])\t\tcoded UT offset in seconds\n**\t\tone (unsigned char)\tused to set tm_isdst\n**\t\tone (unsigned char)\tthat's an abbreviation list index\n**\ttzh_charcnt (char)s\t\t'\\0'-terminated zone abbreviations\n**\ttzh_leapcnt repetitions of\n**\t\tone (char [4])\t\tcoded leap second transition times\n**\t\tone (char [4])\t\ttotal correction after above\n**\ttzh_ttisstdcnt (char)s\t\tindexed by type; if 1, transition\n**\t\t\t\t\ttime is standard time, if 0,\n**\t\t\t\t\ttransition time is local (wall clock)\n**\t\t\t\t\ttime; if absent, transition times are\n**\t\t\t\t\tassumed to be local time\n**\ttzh_ttisutcnt (char)s\t\tindexed by type; if 1, transition\n**\t\t\t\t\ttime is UT, if 0, transition time is\n**\t\t\t\t\tlocal time; if absent, transition\n**\t\t\t\t\ttimes are assumed to be local time.\n**\t\t\t\t\tWhen this is 1, the corresponding\n**\t\t\t\t\tstd/wall indicator must also be 1.\n*/\n\n/*\n** If tzh_version is '2' or greater, the above is followed by a second instance\n** of tzhead and a second instance of the data in which each coded transition\n** time uses 8 rather than 4 chars,\n** then a POSIX.1-2017 proleptic TZ string for use in handling\n** instants after the last transition time stored in the file\n** (with nothing between the newlines if there is no POSIX.1-2017\n** representation for such instants).\n**\n** If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024\n** proleptic TZ string, which means the above is extended as follows.\n** First, the TZ string's hour offset may range from -167\n** through 167 as compared to the range 0 through 24 required\n** by POSIX.1-2017 and earlier.\n** Second, its DST start time may be January 1 at 00:00 and its stop\n** time December 31 at 24:00 plus the difference between DST and\n** standard time, indicating DST all year.\n*/\n\n/*\n** In the current implementation, \"tzset()\" refuses to deal with files that\n** exceed any of the limits below.\n*/\n\n#ifndef TZ_MAX_TIMES\n/* The following limit applies to localtime.c; zic has no such limit.\n   The limit must be at least 310 for Asia/Hebron with 'zic -b fat'.  */\n#define TZ_MAX_TIMES 2000\n#endif /* !defined TZ_MAX_TIMES */\n\n#ifndef TZ_MAX_TYPES\n/* This must be at least 18 for Europe/Vilnius with 'zic -b fat'.  */\n#define TZ_MAX_TYPES 256 /* Limited to 256 by Internet RFC 9636.  */\n#endif                   /* !defined TZ_MAX_TYPES */\n\n#ifndef TZ_MAX_CHARS\n/* This must be at least 40 for America/Anchorage.  */\n#define TZ_MAX_CHARS 256 /* Maximum number of abbreviation characters */\n                         /* (limited to 256 by Internet RFC 9636) */\n#endif                   /* !defined TZ_MAX_CHARS */\n\n#ifndef TZ_MAX_LEAPS\n/* The following limit applies to localtime.c; zic has no such limit.\n   The limit must be at least 27 for leap seconds from 1972 through mid-2023.\n   There's a plan to discontinue leap seconds by 2035.  */\n#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */\n#endif                  /* !defined TZ_MAX_LEAPS */\n\n#endif /* !defined TZFILE_H */\n"
  },
  {
    "path": "absl/time/internal/cctz/src/zone_info_source.cc",
    "content": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//   https://www.apache.org/licenses/LICENSE-2.0\n//\n//   Unless required by applicable law or agreed to in writing, software\n//   distributed under the License is distributed on an \"AS IS\" BASIS,\n//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//   See the License for the specific language governing permissions and\n//   limitations under the License.\n\n#include \"absl/time/internal/cctz/include/cctz/zone_info_source.h\"\n\n#include \"absl/base/config.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz {\n\n// Defined out-of-line to avoid emitting a weak vtable in all TUs.\nZoneInfoSource::~ZoneInfoSource() {}\nstd::string ZoneInfoSource::Version() const { return std::string(); }\n\n}  // namespace cctz\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\nnamespace cctz_extension {\n\nnamespace {\n\n// A default for cctz_extension::zone_info_source_factory, which simply\n// defers to the fallback factory.\nstd::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(\n    const std::string& name,\n    const std::function<\n        std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(\n            const std::string& name)>& fallback_factory) {\n  return fallback_factory(name);\n}\n\n}  // namespace\n\n// A \"weak\" definition for cctz_extension::zone_info_source_factory.\n// The user may override this with their own \"strong\" definition (see\n// zone_info_source.h).\n#if !defined(__has_attribute)\n#define __has_attribute(x) 0\n#endif\n// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the\n// Windows linker cannot handle that. Nor does the MinGW compiler know how to\n// pass \"#pragma comment(linker, ...)\" to the Windows linker.\n#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) && \\\n    !defined(__CYGWIN__)\nZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) =\n    DefaultFactory;\n#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION)\nextern ZoneInfoSourceFactory zone_info_source_factory;\nextern ZoneInfoSourceFactory default_factory;\nZoneInfoSourceFactory default_factory = DefaultFactory;\n#if defined(_M_IX86) || defined(_M_ARM)\n#pragma comment(                                                                                                         \\\n    linker,                                                                                                              \\\n    \"/alternatename:?zone_info_source_factory@cctz_extension@time_internal@\" ABSL_INTERNAL_MANGLED_NS                    \\\n    \"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                 \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                   \\\n    \"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \\\n    \"@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                   \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                   \\\n    \"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE \\\n    \"@@ZA=?default_factory@cctz_extension@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                       \\\n    \"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                 \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                   \\\n    \"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \\\n    \"@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                   \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                   \\\n    \"@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE \\\n    \"@@ZA\")\n#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)\n#pragma comment(                                                                                                          \\\n    linker,                                                                                                               \\\n    \"/alternatename:?zone_info_source_factory@cctz_extension@time_internal@\" ABSL_INTERNAL_MANGLED_NS                     \\\n    \"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                  \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                    \\\n    \"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \\\n    \"@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                   \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                    \\\n    \"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE \\\n    \"@@ZEA=?default_factory@cctz_extension@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                       \\\n    \"@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                  \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                    \\\n    \"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \\\n    \"@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                   \\\n    \"@@U?$default_delete@VZoneInfoSource@cctz@time_internal@\" ABSL_INTERNAL_MANGLED_NS                                    \\\n    \"@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@\" ABSL_INTERNAL_MANGLED_BACKREFERENCE \\\n    \"@@ZEA\")\n#else\n#error Unsupported MSVC platform\n#endif  // _M_<PLATFORM>\n#else\n// Make it a \"strong\" definition if we have no other choice.\nZoneInfoSourceFactory zone_info_source_factory = DefaultFactory;\n#endif\n\n}  // namespace cctz_extension\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/cctz/testdata/README.zoneinfo",
    "content": "testdata/zoneinfo contains time-zone data files that may be used with CCTZ.\nInstall them in a location referenced by the ${TZDIR} environment variable.\nSymbolic and hard links have been eliminated for portability.\n\nOn Linux systems the distribution's versions of these files can probably\nalready be found in the default ${TZDIR} location, /usr/share/zoneinfo.\n\nNew versions can be generated using the following shell script.\n\n  #!/bin/sh -\n  set -e\n  DESTDIR=$(mktemp -d)\n  trap \"rm -fr ${DESTDIR}\" 0 2 15\n  (\n    cd ${DESTDIR}\n    git clone https://github.com/eggert/tz.git\n    make --directory=tz \\\n        install DESTDIR=${DESTDIR} \\\n                DATAFORM=vanguard \\\n                TZDIR=/zoneinfo \\\n                REDO=posix_only \\\n                LOCALTIME=Factory \\\n                TZDATA_TEXT= \\\n                PACKRATDATA=backzone PACKRATLIST=zone.tab \\\n                ZONETABLES=zone1970.tab\\ zonenow.tab\n    tar --create --dereference --hard-dereference --file tzfile.tar \\\n        --directory=tz tzfile.h\n    tar --create --dereference --hard-dereference --file zoneinfo.tar \\\n        --exclude=zoneinfo/posixrules zoneinfo \\\n        --directory=tz version\n  )\n  tar --extract --directory src --file ${DESTDIR}/tzfile.tar\n  tar --extract --directory testdata --file ${DESTDIR}/zoneinfo.tar\n  exit 0\n\nTo run the CCTZ tests using the testdata/zoneinfo files, execute:\n\n  bazel test --test_env=TZDIR=${PWD}/testdata/zoneinfo ...\n"
  },
  {
    "path": "absl/time/internal/cctz/testdata/version",
    "content": "2026a\n"
  },
  {
    "path": "absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab",
    "content": "# ISO 3166 alpha-2 country codes\n#\n# This file is in the public domain, so clarified as of\n# 2009-05-17 by Arthur David Olson.\n#\n# From Paul Eggert (2025-07-01):\n# This file contains a table of two-letter country codes.  Columns are\n# separated by a single tab.  Lines beginning with ‘#’ are comments.\n# All text uses UTF-8 encoding.  The columns of the table are as follows:\n#\n# 1.  ISO 3166-1 alpha-2 country code, current as of\n#     ISO/TC 46 N1127 (2024-02-29).  See: ISO/TC 46 Documents\n#     https://www.iso.org/committee/48750.html?view=documents\n# 2.  The usual English name for the coded region.  This sometimes\n#     departs from ISO-listed names, sometimes so that sorted subsets\n#     of names are useful (e.g., “Samoa (American)” and “Samoa\n#     (western)” rather than “American Samoa” and “Samoa”),\n#     sometimes to avoid confusion among non-experts (e.g.,\n#     “Czech Republic” and “Turkey” rather than “Czechia” and “Türkiye”),\n#     and sometimes to omit needless detail or churn (e.g., “Netherlands”\n#     rather than “Netherlands (the)” or “Netherlands (Kingdom of the)”).\n#\n# The table is sorted by country code.\n#\n# This table is intended as an aid for users, to help them select time\n# zone data appropriate for their practical needs.  It is not intended\n# to take or endorse any position on legal or territorial claims.\n#\n#country-\n#code\tname of country, territory, area, or subdivision\nAD\tAndorra\nAE\tUnited Arab Emirates\nAF\tAfghanistan\nAG\tAntigua & Barbuda\nAI\tAnguilla\nAL\tAlbania\nAM\tArmenia\nAO\tAngola\nAQ\tAntarctica\nAR\tArgentina\nAS\tSamoa (American)\nAT\tAustria\nAU\tAustralia\nAW\tAruba\nAX\tÅland Islands\nAZ\tAzerbaijan\nBA\tBosnia & Herzegovina\nBB\tBarbados\nBD\tBangladesh\nBE\tBelgium\nBF\tBurkina Faso\nBG\tBulgaria\nBH\tBahrain\nBI\tBurundi\nBJ\tBenin\nBL\tSt Barthelemy\nBM\tBermuda\nBN\tBrunei\nBO\tBolivia\nBQ\tCaribbean NL\nBR\tBrazil\nBS\tBahamas\nBT\tBhutan\nBV\tBouvet Island\nBW\tBotswana\nBY\tBelarus\nBZ\tBelize\nCA\tCanada\nCC\tCocos (Keeling) Islands\nCD\tCongo (Dem. Rep.)\nCF\tCentral African Rep.\nCG\tCongo (Rep.)\nCH\tSwitzerland\nCI\tCôte d’Ivoire\nCK\tCook Islands\nCL\tChile\nCM\tCameroon\nCN\tChina\nCO\tColombia\nCR\tCosta Rica\nCU\tCuba\nCV\tCape Verde\nCW\tCuraçao\nCX\tChristmas Island\nCY\tCyprus\nCZ\tCzech Republic\nDE\tGermany\nDJ\tDjibouti\nDK\tDenmark\nDM\tDominica\nDO\tDominican Republic\nDZ\tAlgeria\nEC\tEcuador\nEE\tEstonia\nEG\tEgypt\nEH\tWestern Sahara\nER\tEritrea\nES\tSpain\nET\tEthiopia\nFI\tFinland\nFJ\tFiji\nFK\tFalkland Islands\nFM\tMicronesia\nFO\tFaroe Islands\nFR\tFrance\nGA\tGabon\nGB\tBritain (UK)\nGD\tGrenada\nGE\tGeorgia\nGF\tFrench Guiana\nGG\tGuernsey\nGH\tGhana\nGI\tGibraltar\nGL\tGreenland\nGM\tGambia\nGN\tGuinea\nGP\tGuadeloupe\nGQ\tEquatorial Guinea\nGR\tGreece\nGS\tSouth Georgia & the South Sandwich Islands\nGT\tGuatemala\nGU\tGuam\nGW\tGuinea-Bissau\nGY\tGuyana\nHK\tHong Kong\nHM\tHeard Island & McDonald Islands\nHN\tHonduras\nHR\tCroatia\nHT\tHaiti\nHU\tHungary\nID\tIndonesia\nIE\tIreland\nIL\tIsrael\nIM\tIsle of Man\nIN\tIndia\nIO\tBritish Indian Ocean Territory\nIQ\tIraq\nIR\tIran\nIS\tIceland\nIT\tItaly\nJE\tJersey\nJM\tJamaica\nJO\tJordan\nJP\tJapan\nKE\tKenya\nKG\tKyrgyzstan\nKH\tCambodia\nKI\tKiribati\nKM\tComoros\nKN\tSt Kitts & Nevis\nKP\tKorea (North)\nKR\tKorea (South)\nKW\tKuwait\nKY\tCayman Islands\nKZ\tKazakhstan\nLA\tLaos\nLB\tLebanon\nLC\tSt Lucia\nLI\tLiechtenstein\nLK\tSri Lanka\nLR\tLiberia\nLS\tLesotho\nLT\tLithuania\nLU\tLuxembourg\nLV\tLatvia\nLY\tLibya\nMA\tMorocco\nMC\tMonaco\nMD\tMoldova\nME\tMontenegro\nMF\tSt Martin (French)\nMG\tMadagascar\nMH\tMarshall Islands\nMK\tNorth Macedonia\nML\tMali\nMM\tMyanmar (Burma)\nMN\tMongolia\nMO\tMacau\nMP\tNorthern Mariana Islands\nMQ\tMartinique\nMR\tMauritania\nMS\tMontserrat\nMT\tMalta\nMU\tMauritius\nMV\tMaldives\nMW\tMalawi\nMX\tMexico\nMY\tMalaysia\nMZ\tMozambique\nNA\tNamibia\nNC\tNew Caledonia\nNE\tNiger\nNF\tNorfolk Island\nNG\tNigeria\nNI\tNicaragua\nNL\tNetherlands\nNO\tNorway\nNP\tNepal\nNR\tNauru\nNU\tNiue\nNZ\tNew Zealand\nOM\tOman\nPA\tPanama\nPE\tPeru\nPF\tFrench Polynesia\nPG\tPapua New Guinea\nPH\tPhilippines\nPK\tPakistan\nPL\tPoland\nPM\tSt Pierre & Miquelon\nPN\tPitcairn\nPR\tPuerto Rico\nPS\tPalestine\nPT\tPortugal\nPW\tPalau\nPY\tParaguay\nQA\tQatar\nRE\tRéunion\nRO\tRomania\nRS\tSerbia\nRU\tRussia\nRW\tRwanda\nSA\tSaudi Arabia\nSB\tSolomon Islands\nSC\tSeychelles\nSD\tSudan\nSE\tSweden\nSG\tSingapore\nSH\tSt Helena\nSI\tSlovenia\nSJ\tSvalbard & Jan Mayen\nSK\tSlovakia\nSL\tSierra Leone\nSM\tSan Marino\nSN\tSenegal\nSO\tSomalia\nSR\tSuriname\nSS\tSouth Sudan\nST\tSao Tome & Principe\nSV\tEl Salvador\nSX\tSt Maarten (Dutch)\nSY\tSyria\nSZ\tEswatini (Swaziland)\nTC\tTurks & Caicos Is\nTD\tChad\nTF\tFrench S. Terr.\nTG\tTogo\nTH\tThailand\nTJ\tTajikistan\nTK\tTokelau\nTL\tEast Timor\nTM\tTurkmenistan\nTN\tTunisia\nTO\tTonga\nTR\tTurkey\nTT\tTrinidad & Tobago\nTV\tTuvalu\nTW\tTaiwan\nTZ\tTanzania\nUA\tUkraine\nUG\tUganda\nUM\tUS minor outlying islands\nUS\tUnited States\nUY\tUruguay\nUZ\tUzbekistan\nVA\tVatican City\nVC\tSt Vincent\nVE\tVenezuela\nVG\tVirgin Islands (UK)\nVI\tVirgin Islands (US)\nVN\tVietnam\nVU\tVanuatu\nWF\tWallis & Futuna\nWS\tSamoa (western)\nYE\tYemen\nYT\tMayotte\nZA\tSouth Africa\nZM\tZambia\nZW\tZimbabwe\n"
  },
  {
    "path": "absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab",
    "content": "# tzdb timezone descriptions\n#\n# This file is in the public domain.\n#\n# From Paul Eggert (2025-05-15):\n# This file contains a table where each row stands for a timezone where\n# civil timestamps have agreed since 1970.  Columns are separated by\n# a single tab.  Lines beginning with ‘#’ are comments.  All text uses\n# UTF-8 encoding.  The columns of the table are as follows:\n#\n# 1.  The countries that overlap the timezone, as a comma-separated list\n#     of ISO 3166 2-character country codes.\n# 2.  Latitude and longitude of the timezone’s principal location\n#     in ISO 6709 sign-degrees-minutes-seconds format,\n#     either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS,\n#     first latitude (+ is north), then longitude (+ is east).\n# 3.  Timezone name used in value of TZ environment variable.\n#     Please see the theory.html file for how these names are chosen.\n#     If multiple timezones overlap a country, each has a row in the\n#     table, with each column 1 containing the country code.\n# 4.  Comments; present if and only if countries have multiple timezones,\n#     and useful only for those countries.  For example, the comments\n#     for the row with countries CH,DE,LI and name Europe/Zurich\n#     are useful only for DE, since CH and LI have no other timezones.\n#\n# If a timezone covers multiple countries, the most-populous city is used,\n# and that country is listed first in column 1; any other countries\n# are listed alphabetically by country code.  The table is sorted\n# first by country code, then (if possible) by an order within the\n# country that (1) makes some geographical sense, and (2) puts the\n# most populous timezones first, where that does not contradict (1).\n#\n# This table is intended as an aid for users, to help them select timezones\n# appropriate for their practical needs.  It is not intended to take or\n# endorse any position on legal or territorial claims.\n#\n#country-\n#codes\tcoordinates\tTZ\tcomments\nAD\t+4230+00131\tEurope/Andorra\nAE,OM,RE,SC,TF\t+2518+05518\tAsia/Dubai\tCrozet\nAF\t+3431+06912\tAsia/Kabul\nAL\t+4120+01950\tEurope/Tirane\nAM\t+4011+04430\tAsia/Yerevan\nAQ\t-6617+11031\tAntarctica/Casey\tCasey\nAQ\t-6835+07758\tAntarctica/Davis\tDavis\nAQ\t-6736+06253\tAntarctica/Mawson\tMawson\nAQ\t-6448-06406\tAntarctica/Palmer\tPalmer\nAQ\t-6734-06808\tAntarctica/Rothera\tRothera\nAQ\t-720041+0023206\tAntarctica/Troll\tTroll\nAQ\t-7824+10654\tAntarctica/Vostok\tVostok\nAR\t-3436-05827\tAmerica/Argentina/Buenos_Aires\tBuenos Aires (BA, CF)\nAR\t-3124-06411\tAmerica/Argentina/Cordoba\tmost areas: CB, CC, CN, ER, FM, MN, SE, SF\nAR\t-2447-06525\tAmerica/Argentina/Salta\tSalta (SA, LP, NQ, RN)\nAR\t-2411-06518\tAmerica/Argentina/Jujuy\tJujuy (JY)\nAR\t-2649-06513\tAmerica/Argentina/Tucuman\tTucumán (TM)\nAR\t-2828-06547\tAmerica/Argentina/Catamarca\tCatamarca (CT), Chubut (CH)\nAR\t-2926-06651\tAmerica/Argentina/La_Rioja\tLa Rioja (LR)\nAR\t-3132-06831\tAmerica/Argentina/San_Juan\tSan Juan (SJ)\nAR\t-3253-06849\tAmerica/Argentina/Mendoza\tMendoza (MZ)\nAR\t-3319-06621\tAmerica/Argentina/San_Luis\tSan Luis (SL)\nAR\t-5138-06913\tAmerica/Argentina/Rio_Gallegos\tSanta Cruz (SC)\nAR\t-5448-06818\tAmerica/Argentina/Ushuaia\tTierra del Fuego (TF)\nAS,UM\t-1416-17042\tPacific/Pago_Pago\tMidway\nAT\t+4813+01620\tEurope/Vienna\nAU\t-3133+15905\tAustralia/Lord_Howe\tLord Howe Island\nAU\t-5430+15857\tAntarctica/Macquarie\tMacquarie Island\nAU\t-4253+14719\tAustralia/Hobart\tTasmania\nAU\t-3749+14458\tAustralia/Melbourne\tVictoria\nAU\t-3352+15113\tAustralia/Sydney\tNew South Wales (most areas)\nAU\t-3157+14127\tAustralia/Broken_Hill\tNew South Wales (Yancowinna)\nAU\t-2728+15302\tAustralia/Brisbane\tQueensland (most areas)\nAU\t-2016+14900\tAustralia/Lindeman\tQueensland (Whitsunday Islands)\nAU\t-3455+13835\tAustralia/Adelaide\tSouth Australia\nAU\t-1228+13050\tAustralia/Darwin\tNorthern Territory\nAU\t-3157+11551\tAustralia/Perth\tWestern Australia (most areas)\nAU\t-3143+12852\tAustralia/Eucla\tWestern Australia (Eucla)\nAZ\t+4023+04951\tAsia/Baku\nBB\t+1306-05937\tAmerica/Barbados\nBD\t+2343+09025\tAsia/Dhaka\nBE,LU,NL\t+5050+00420\tEurope/Brussels\nBG\t+4241+02319\tEurope/Sofia\nBM\t+3217-06446\tAtlantic/Bermuda\nBO\t-1630-06809\tAmerica/La_Paz\nBR\t-0351-03225\tAmerica/Noronha\tAtlantic islands\nBR\t-0127-04829\tAmerica/Belem\tPará (east), Amapá\nBR\t-0343-03830\tAmerica/Fortaleza\tBrazil (northeast: MA, PI, CE, RN, PB)\nBR\t-0803-03454\tAmerica/Recife\tPernambuco\nBR\t-0712-04812\tAmerica/Araguaina\tTocantins\nBR\t-0940-03543\tAmerica/Maceio\tAlagoas, Sergipe\nBR\t-1259-03831\tAmerica/Bahia\tBahia\nBR\t-2332-04637\tAmerica/Sao_Paulo\tBrazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS)\nBR\t-2027-05437\tAmerica/Campo_Grande\tMato Grosso do Sul\nBR\t-1535-05605\tAmerica/Cuiaba\tMato Grosso\nBR\t-0226-05452\tAmerica/Santarem\tPará (west)\nBR\t-0846-06354\tAmerica/Porto_Velho\tRondônia\nBR\t+0249-06040\tAmerica/Boa_Vista\tRoraima\nBR\t-0308-06001\tAmerica/Manaus\tAmazonas (east)\nBR\t-0640-06952\tAmerica/Eirunepe\tAmazonas (west)\nBR\t-0958-06748\tAmerica/Rio_Branco\tAcre\nBT\t+2728+08939\tAsia/Thimphu\nBY\t+5354+02734\tEurope/Minsk\nBZ\t+1730-08812\tAmerica/Belize\nCA\t+4734-05243\tAmerica/St_Johns\tNewfoundland, Labrador (SE)\nCA\t+4439-06336\tAmerica/Halifax\tAtlantic - NS (most areas), PE\nCA\t+4612-05957\tAmerica/Glace_Bay\tAtlantic - NS (Cape Breton)\nCA\t+4606-06447\tAmerica/Moncton\tAtlantic - New Brunswick\nCA\t+5320-06025\tAmerica/Goose_Bay\tAtlantic - Labrador (most areas)\nCA,BS\t+4339-07923\tAmerica/Toronto\tEastern - ON & QC (most areas)\nCA\t+6344-06828\tAmerica/Iqaluit\tEastern - NU (most areas)\nCA\t+4953-09709\tAmerica/Winnipeg\tCentral - ON (west), Manitoba\nCA\t+744144-0944945\tAmerica/Resolute\tCentral - NU (Resolute)\nCA\t+624900-0920459\tAmerica/Rankin_Inlet\tCentral - NU (central)\nCA\t+5024-10439\tAmerica/Regina\tCST - SK (most areas)\nCA\t+5017-10750\tAmerica/Swift_Current\tCST - SK (midwest)\nCA\t+5333-11328\tAmerica/Edmonton\tMountain - AB, BC(E), NT(E), SK(W)\nCA\t+690650-1050310\tAmerica/Cambridge_Bay\tMountain - NU (west)\nCA\t+682059-1334300\tAmerica/Inuvik\tMountain - NT (west)\nCA\t+5546-12014\tAmerica/Dawson_Creek\tMST - BC (Dawson Cr, Ft St John)\nCA\t+5848-12242\tAmerica/Fort_Nelson\tMST - BC (Ft Nelson)\nCA\t+6043-13503\tAmerica/Whitehorse\tMST - Yukon (east)\nCA\t+6404-13925\tAmerica/Dawson\tMST - Yukon (west)\nCA\t+4916-12307\tAmerica/Vancouver\tPacific - BC (most areas)\nCH,DE,LI\t+4723+00832\tEurope/Zurich\tBüsingen\nCI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG\t+0519-00402\tAfrica/Abidjan\nCK\t-2114-15946\tPacific/Rarotonga\nCL\t-3327-07040\tAmerica/Santiago\tmost of Chile\nCL\t-4534-07204\tAmerica/Coyhaique\tAysén Region\nCL\t-5309-07055\tAmerica/Punta_Arenas\tMagallanes Region\nCL\t-2709-10926\tPacific/Easter\tEaster Island\nCN\t+3114+12128\tAsia/Shanghai\tBeijing Time\nCN\t+4348+08735\tAsia/Urumqi\tXinjiang Time\nCO\t+0436-07405\tAmerica/Bogota\nCR\t+0956-08405\tAmerica/Costa_Rica\nCU\t+2308-08222\tAmerica/Havana\nCV\t+1455-02331\tAtlantic/Cape_Verde\nCY\t+3510+03322\tAsia/Nicosia\tmost of Cyprus\nCY\t+3507+03357\tAsia/Famagusta\tNorthern Cyprus\nCZ,SK\t+5005+01426\tEurope/Prague\nDE,DK,NO,SE,SJ\t+5230+01322\tEurope/Berlin\tmost of Germany\nDO\t+1828-06954\tAmerica/Santo_Domingo\nDZ\t+3647+00303\tAfrica/Algiers\nEC\t-0210-07950\tAmerica/Guayaquil\tEcuador (mainland)\nEC\t-0054-08936\tPacific/Galapagos\tGalápagos Islands\nEE\t+5925+02445\tEurope/Tallinn\nEG\t+3003+03115\tAfrica/Cairo\nEH\t+2709-01312\tAfrica/El_Aaiun\nES\t+4024-00341\tEurope/Madrid\tSpain (mainland)\nES\t+3553-00519\tAfrica/Ceuta\tCeuta, Melilla\nES\t+2806-01524\tAtlantic/Canary\tCanary Islands\nFI,AX\t+6010+02458\tEurope/Helsinki\nFJ\t-1808+17825\tPacific/Fiji\nFK\t-5142-05751\tAtlantic/Stanley\nFM\t+0519+16259\tPacific/Kosrae\tKosrae\nFO\t+6201-00646\tAtlantic/Faroe\nFR,MC\t+4852+00220\tEurope/Paris\nGB,GG,IM,JE\t+513030-0000731\tEurope/London\nGE\t+4143+04449\tAsia/Tbilisi\nGF\t+0456-05220\tAmerica/Cayenne\nGI\t+3608-00521\tEurope/Gibraltar\nGL\t+6411-05144\tAmerica/Nuuk\tmost of Greenland\nGL\t+7646-01840\tAmerica/Danmarkshavn\tNational Park (east coast)\nGL\t+7029-02158\tAmerica/Scoresbysund\tScoresbysund/Ittoqqortoormiit\nGL\t+7634-06847\tAmerica/Thule\tThule/Pituffik\nGR\t+3758+02343\tEurope/Athens\nGS\t-5416-03632\tAtlantic/South_Georgia\nGT\t+1438-09031\tAmerica/Guatemala\nGU,MP\t+1328+14445\tPacific/Guam\nGW\t+1151-01535\tAfrica/Bissau\nGY\t+0648-05810\tAmerica/Guyana\nHK\t+2217+11409\tAsia/Hong_Kong\nHN\t+1406-08713\tAmerica/Tegucigalpa\nHT\t+1832-07220\tAmerica/Port-au-Prince\nHU\t+4730+01905\tEurope/Budapest\nID\t-0610+10648\tAsia/Jakarta\tJava, Sumatra\nID\t-0002+10920\tAsia/Pontianak\tBorneo (west, central)\nID\t-0507+11924\tAsia/Makassar\tBorneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)\nID\t-0232+14042\tAsia/Jayapura\tNew Guinea (West Papua / Irian Jaya), Malukus/Moluccas\nIE\t+5320-00615\tEurope/Dublin\nIL\t+314650+0351326\tAsia/Jerusalem\nIN\t+2232+08822\tAsia/Kolkata\nIO\t-0720+07225\tIndian/Chagos\nIQ\t+3321+04425\tAsia/Baghdad\nIR\t+3540+05126\tAsia/Tehran\nIT,SM,VA\t+4154+01229\tEurope/Rome\nJM\t+175805-0764736\tAmerica/Jamaica\nJO\t+3157+03556\tAsia/Amman\nJP,AU\t+353916+1394441\tAsia/Tokyo\tEyre Bird Observatory\nKE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT\t-0117+03649\tAfrica/Nairobi\nKG\t+4254+07436\tAsia/Bishkek\nKI,MH,TV,UM,WF\t+0125+17300\tPacific/Tarawa\tGilberts, Marshalls, Wake\nKI\t-0247-17143\tPacific/Kanton\tPhoenix Islands\nKI\t+0152-15720\tPacific/Kiritimati\tLine Islands\nKP\t+3901+12545\tAsia/Pyongyang\nKR\t+3733+12658\tAsia/Seoul\nKZ\t+4315+07657\tAsia/Almaty\tmost of Kazakhstan\nKZ\t+4448+06528\tAsia/Qyzylorda\tQyzylorda/Kyzylorda/Kzyl-Orda\nKZ\t+5312+06337\tAsia/Qostanay\tQostanay/Kostanay/Kustanay\nKZ\t+5017+05710\tAsia/Aqtobe\tAqtöbe/Aktobe\nKZ\t+4431+05016\tAsia/Aqtau\tMangghystaū/Mankistau\nKZ\t+4707+05156\tAsia/Atyrau\tAtyraū/Atirau/Gur’yev\nKZ\t+5113+05121\tAsia/Oral\tWest Kazakhstan\nLB\t+3353+03530\tAsia/Beirut\nLK\t+0656+07951\tAsia/Colombo\nLR\t+0618-01047\tAfrica/Monrovia\nLT\t+5441+02519\tEurope/Vilnius\nLV\t+5657+02406\tEurope/Riga\nLY\t+3254+01311\tAfrica/Tripoli\nMA\t+3339-00735\tAfrica/Casablanca\nMD\t+4700+02850\tEurope/Chisinau\nMH\t+0905+16720\tPacific/Kwajalein\tKwajalein\nMM,CC\t+1647+09610\tAsia/Yangon\nMN\t+4755+10653\tAsia/Ulaanbaatar\tmost of Mongolia\nMN\t+4801+09139\tAsia/Hovd\tBayan-Ölgii, Hovd, Uvs\nMO\t+221150+1133230\tAsia/Macau\nMQ\t+1436-06105\tAmerica/Martinique\nMT\t+3554+01431\tEurope/Malta\nMU\t-2010+05730\tIndian/Mauritius\nMV,TF\t+0410+07330\tIndian/Maldives\tKerguelen, St Paul I, Amsterdam I\nMX\t+1924-09909\tAmerica/Mexico_City\tCentral Mexico\nMX\t+2105-08646\tAmerica/Cancun\tQuintana Roo\nMX\t+2058-08937\tAmerica/Merida\tCampeche, Yucatán\nMX\t+2540-10019\tAmerica/Monterrey\tDurango; Coahuila, Nuevo León, Tamaulipas (most areas)\nMX\t+2550-09730\tAmerica/Matamoros\tCoahuila, Nuevo León, Tamaulipas (US border)\nMX\t+2838-10605\tAmerica/Chihuahua\tChihuahua (most areas)\nMX\t+3144-10629\tAmerica/Ciudad_Juarez\tChihuahua (US border - west)\nMX\t+2934-10425\tAmerica/Ojinaga\tChihuahua (US border - east)\nMX\t+2313-10625\tAmerica/Mazatlan\tBaja California Sur, Nayarit (most areas), Sinaloa\nMX\t+2048-10515\tAmerica/Bahia_Banderas\tBahía de Banderas\nMX\t+2904-11058\tAmerica/Hermosillo\tSonora\nMX\t+3232-11701\tAmerica/Tijuana\tBaja California\nMY,BN\t+0133+11020\tAsia/Kuching\tSabah, Sarawak\nMZ,BI,BW,CD,MW,RW,ZM,ZW\t-2558+03235\tAfrica/Maputo\tCentral Africa Time\nNA\t-2234+01706\tAfrica/Windhoek\nNC\t-2216+16627\tPacific/Noumea\nNF\t-2903+16758\tPacific/Norfolk\nNG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE\t+0627+00324\tAfrica/Lagos\tWest Africa Time\nNI\t+1209-08617\tAmerica/Managua\nNP\t+2743+08519\tAsia/Kathmandu\nNR\t-0031+16655\tPacific/Nauru\nNU\t-1901-16955\tPacific/Niue\nNZ,AQ\t-3652+17446\tPacific/Auckland\tNew Zealand time\nNZ\t-4357-17633\tPacific/Chatham\tChatham Islands\nPA,CA,KY\t+0858-07932\tAmerica/Panama\tEST - ON (Atikokan), NU (Coral H)\nPE\t-1203-07703\tAmerica/Lima\nPF\t-1732-14934\tPacific/Tahiti\tSociety Islands\nPF\t-0900-13930\tPacific/Marquesas\tMarquesas Islands\nPF\t-2308-13457\tPacific/Gambier\tGambier Islands\nPG,AQ,FM\t-0930+14710\tPacific/Port_Moresby\tPapua New Guinea (most areas), Chuuk, Yap, Dumont d’Urville\nPG\t-0613+15534\tPacific/Bougainville\tBougainville\nPH\t+143512+1205804\tAsia/Manila\nPK\t+2452+06703\tAsia/Karachi\nPL\t+5215+02100\tEurope/Warsaw\nPM\t+4703-05620\tAmerica/Miquelon\nPN\t-2504-13005\tPacific/Pitcairn\nPR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI\t+182806-0660622\tAmerica/Puerto_Rico\tAST - QC (Lower North Shore)\nPS\t+3130+03428\tAsia/Gaza\tGaza Strip\nPS\t+313200+0350542\tAsia/Hebron\tWest Bank\nPT\t+3843-00908\tEurope/Lisbon\tPortugal (mainland)\nPT\t+3238-01654\tAtlantic/Madeira\tMadeira Islands\nPT\t+3744-02540\tAtlantic/Azores\tAzores\nPW\t+0720+13429\tPacific/Palau\nPY\t-2516-05740\tAmerica/Asuncion\nQA,BH\t+2517+05132\tAsia/Qatar\nRO\t+4426+02606\tEurope/Bucharest\nRS,BA,HR,ME,MK,SI\t+4450+02030\tEurope/Belgrade\nRU\t+5443+02030\tEurope/Kaliningrad\tMSK-01 - Kaliningrad\nRU\t+554521+0373704\tEurope/Moscow\tMSK+00 - Moscow area\n# Mention RU and UA alphabetically.  See “territorial claims” above.\nRU,UA\t+4457+03406\tEurope/Simferopol\tCrimea\nRU\t+5836+04939\tEurope/Kirov\tMSK+00 - Kirov\nRU\t+4844+04425\tEurope/Volgograd\tMSK+00 - Volgograd\nRU\t+4621+04803\tEurope/Astrakhan\tMSK+01 - Astrakhan\nRU\t+5134+04602\tEurope/Saratov\tMSK+01 - Saratov\nRU\t+5420+04824\tEurope/Ulyanovsk\tMSK+01 - Ulyanovsk\nRU\t+5312+05009\tEurope/Samara\tMSK+01 - Samara, Udmurtia\nRU\t+5651+06036\tAsia/Yekaterinburg\tMSK+02 - Urals\nRU\t+5500+07324\tAsia/Omsk\tMSK+03 - Omsk\nRU\t+5502+08255\tAsia/Novosibirsk\tMSK+04 - Novosibirsk\nRU\t+5322+08345\tAsia/Barnaul\tMSK+04 - Altai\nRU\t+5630+08458\tAsia/Tomsk\tMSK+04 - Tomsk\nRU\t+5345+08707\tAsia/Novokuznetsk\tMSK+04 - Kemerovo\nRU\t+5601+09250\tAsia/Krasnoyarsk\tMSK+04 - Krasnoyarsk area\nRU\t+5216+10420\tAsia/Irkutsk\tMSK+05 - Irkutsk, Buryatia\nRU\t+5203+11328\tAsia/Chita\tMSK+06 - Zabaykalsky\nRU\t+6200+12940\tAsia/Yakutsk\tMSK+06 - Lena River\nRU\t+623923+1353314\tAsia/Khandyga\tMSK+06 - Tomponsky, Ust-Maysky\nRU\t+4310+13156\tAsia/Vladivostok\tMSK+07 - Amur River\nRU\t+643337+1431336\tAsia/Ust-Nera\tMSK+07 - Oymyakonsky\nRU\t+5934+15048\tAsia/Magadan\tMSK+08 - Magadan\nRU\t+4658+14242\tAsia/Sakhalin\tMSK+08 - Sakhalin Island\nRU\t+6728+15343\tAsia/Srednekolymsk\tMSK+08 - Sakha (E), N Kuril Is\nRU\t+5301+15839\tAsia/Kamchatka\tMSK+09 - Kamchatka\nRU\t+6445+17729\tAsia/Anadyr\tMSK+09 - Bering Sea\nSA,AQ,KW,YE\t+2438+04643\tAsia/Riyadh\tSyowa\nSB,FM\t-0932+16012\tPacific/Guadalcanal\tPohnpei\nSD\t+1536+03232\tAfrica/Khartoum\nSG,AQ,MY\t+0117+10351\tAsia/Singapore\tpeninsular Malaysia, Concordia\nSR\t+0550-05510\tAmerica/Paramaribo\nSS\t+0451+03137\tAfrica/Juba\nST\t+0020+00644\tAfrica/Sao_Tome\nSV\t+1342-08912\tAmerica/El_Salvador\nSY\t+3330+03618\tAsia/Damascus\nTC\t+2128-07108\tAmerica/Grand_Turk\nTD\t+1207+01503\tAfrica/Ndjamena\nTH,CX,KH,LA,VN\t+1345+10031\tAsia/Bangkok\tnorth Vietnam\nTJ\t+3835+06848\tAsia/Dushanbe\nTK\t-0922-17114\tPacific/Fakaofo\nTL\t-0833+12535\tAsia/Dili\nTM\t+3757+05823\tAsia/Ashgabat\nTN\t+3648+01011\tAfrica/Tunis\nTO\t-210800-1751200\tPacific/Tongatapu\nTR\t+4101+02858\tEurope/Istanbul\nTW\t+2503+12130\tAsia/Taipei\nUA\t+5026+03031\tEurope/Kyiv\tmost of Ukraine\nUS\t+404251-0740023\tAmerica/New_York\tEastern (most areas)\nUS\t+421953-0830245\tAmerica/Detroit\tEastern - MI (most areas)\nUS\t+381515-0854534\tAmerica/Kentucky/Louisville\tEastern - KY (Louisville area)\nUS\t+364947-0845057\tAmerica/Kentucky/Monticello\tEastern - KY (Wayne)\nUS\t+394606-0860929\tAmerica/Indiana/Indianapolis\tEastern - IN (most areas)\nUS\t+384038-0873143\tAmerica/Indiana/Vincennes\tEastern - IN (Da, Du, K, Mn)\nUS\t+410305-0863611\tAmerica/Indiana/Winamac\tEastern - IN (Pulaski)\nUS\t+382232-0862041\tAmerica/Indiana/Marengo\tEastern - IN (Crawford)\nUS\t+382931-0871643\tAmerica/Indiana/Petersburg\tEastern - IN (Pike)\nUS\t+384452-0850402\tAmerica/Indiana/Vevay\tEastern - IN (Switzerland)\nUS\t+415100-0873900\tAmerica/Chicago\tCentral (most areas)\nUS\t+375711-0864541\tAmerica/Indiana/Tell_City\tCentral - IN (Perry)\nUS\t+411745-0863730\tAmerica/Indiana/Knox\tCentral - IN (Starke)\nUS\t+450628-0873651\tAmerica/Menominee\tCentral - MI (Wisconsin border)\nUS\t+470659-1011757\tAmerica/North_Dakota/Center\tCentral - ND (Oliver)\nUS\t+465042-1012439\tAmerica/North_Dakota/New_Salem\tCentral - ND (Morton rural)\nUS\t+471551-1014640\tAmerica/North_Dakota/Beulah\tCentral - ND (Mercer)\nUS\t+394421-1045903\tAmerica/Denver\tMountain (most areas)\nUS\t+433649-1161209\tAmerica/Boise\tMountain - ID (south), OR (east)\nUS,CA\t+332654-1120424\tAmerica/Phoenix\tMST - AZ (most areas), Creston BC\nUS\t+340308-1181434\tAmerica/Los_Angeles\tPacific\nUS\t+611305-1495401\tAmerica/Anchorage\tAlaska (most areas)\nUS\t+581807-1342511\tAmerica/Juneau\tAlaska - Juneau area\nUS\t+571035-1351807\tAmerica/Sitka\tAlaska - Sitka area\nUS\t+550737-1313435\tAmerica/Metlakatla\tAlaska - Annette Island\nUS\t+593249-1394338\tAmerica/Yakutat\tAlaska - Yakutat\nUS\t+643004-1652423\tAmerica/Nome\tAlaska (west)\nUS\t+515248-1763929\tAmerica/Adak\tAlaska - western Aleutians\nUS\t+211825-1575130\tPacific/Honolulu\tHawaii\nUY\t-345433-0561245\tAmerica/Montevideo\nUZ\t+3940+06648\tAsia/Samarkand\tUzbekistan (west)\nUZ\t+4120+06918\tAsia/Tashkent\tUzbekistan (east)\nVE\t+1030-06656\tAmerica/Caracas\nVN\t+1045+10640\tAsia/Ho_Chi_Minh\tsouth Vietnam\nVU\t-1740+16825\tPacific/Efate\nWS\t-1350-17144\tPacific/Apia\nZA,LS,SZ\t-2615+02800\tAfrica/Johannesburg\n#\n# The next section contains experimental tab-separated comments for\n# use by user agents like tzselect that identify continents and oceans.\n#\n# For example, the comment ‘#@AQ<tab>Antarctica/’ means the country code\n# AQ is in the continent Antarctica regardless of the Zone name,\n# so Pacific/Auckland should be listed under Antarctica as well as\n# under the Pacific because its line’s country codes include AQ.\n#\n# If more than one country code is affected each is listed separated\n# by commas, e.g., ‘#@IS,SH<tab>Atlantic/’.  If a country code is in\n# more than one continent or ocean, each is listed separated by\n# commas, e.g., the second column of ‘#@CY,TR<tab>Asia/,Europe/’.\n#\n# These experimental comments are present only for country codes where\n# the continent or ocean is not already obvious from the Zone name.\n# For example, there is no such comment for RU since it already\n# corresponds to Zone names starting with both ‘Europe/’ and ‘Asia/’.\n#\n#@AQ\tAntarctica/\n#@IS,SH\tAtlantic/\n#@CY,TR\tAsia/,Europe/\n#@SJ\tArctic/\n#@CC,CX,KM,MG,YT\tIndian/\n"
  },
  {
    "path": "absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab",
    "content": "# tzdb timezone descriptions, for users who do not care about old timestamps\n#\n# This file is in the public domain.\n#\n# From Paul Eggert (2023-12-18):\n# This file contains a table where each row stands for a timezone\n# where civil timestamps are predicted to agree from now on.\n# This file is like zone1970.tab (see zone1970.tab’s comments),\n# but with the following changes:\n#\n# 1.  Each timezone corresponds to a set of clocks that are planned\n#     to agree from now on.  This is a larger set of clocks than in\n#     zone1970.tab, where each timezone’s clocks must agree from 1970 on.\n# 2.  The first column is irrelevant and ignored.\n# 3.  The table is sorted in a different way:\n#     first by standard time UTC offset;\n#     then, if DST is used, by daylight saving UTC offset;\n#     then by time zone abbreviation.\n# 4.  Every timezone has a nonempty comments column, with wording\n#     distinguishing the timezone only from other timezones with the\n#     same UTC offset at some point during the year.\n#\n# The format of this table is experimental, and may change in future versions.\n#\n# This table is intended as an aid for users, to help them select timezones\n# appropriate for their practical needs.  It is not intended to take or\n# endorse any position on legal or territorial claims.\n#\n#XX\tcoordinates\tTZ\tcomments\n#\n# -11 - SST\nXX\t-1416-17042\tPacific/Pago_Pago\tMidway; Samoa (SST)\n#\n# -11\nXX\t-1901-16955\tPacific/Niue\tNiue\n#\n# -10 - HST\nXX\t+211825-1575130\tPacific/Honolulu\tHawaii (HST)\n#\n# -10\nXX\t-1732-14934\tPacific/Tahiti\tTahiti; Cook Islands\n#\n# -10/-09 - HST / HDT (North America DST)\nXX\t+515248-1763929\tAmerica/Adak\twestern Aleutians in Alaska (HST/HDT)\n#\n# -09:30\nXX\t-0900-13930\tPacific/Marquesas\tMarquesas\n#\n# -09\nXX\t-2308-13457\tPacific/Gambier\tGambier\n#\n# -09/-08 - AKST/AKDT (North America DST)\nXX\t+611305-1495401\tAmerica/Anchorage\tmost of Alaska (AKST/AKDT)\n#\n# -08\nXX\t-2504-13005\tPacific/Pitcairn\tPitcairn\n#\n# -08/-07 - PST/PDT (North America DST)\nXX\t+340308-1181434\tAmerica/Los_Angeles\tPacific (PST/PDT) - US & Canada; Mexico near US border\n#\n# -07 - MST\nXX\t+332654-1120424\tAmerica/Phoenix\tMountain Standard (MST) - Arizona; western Mexico; Yukon\n#\n# -07/-06 - MST/MDT (North America DST)\nXX\t+394421-1045903\tAmerica/Denver\tMountain (MST/MDT) - US & Canada; Mexico near US border\n#\n# -06\nXX\t-0054-08936\tPacific/Galapagos\tGalápagos\n#\n# -06 - CST\nXX\t+1924-09909\tAmerica/Mexico_City\tCentral Standard (CST) - Saskatchewan; central Mexico; Central America\n#\n# -06/-05 (Chile DST)\nXX\t-2709-10926\tPacific/Easter\tEaster Island\n#\n# -06/-05 - CST/CDT (North America DST)\nXX\t+415100-0873900\tAmerica/Chicago\tCentral (CST/CDT) - US & Canada; Mexico near US border\n#\n# -05\nXX\t-1203-07703\tAmerica/Lima\teastern South America\n#\n# -05 - EST\nXX\t+175805-0764736\tAmerica/Jamaica\tEastern Standard (EST) - Caymans; Jamaica; eastern Mexico; Panama\n#\n# -05/-04 - CST/CDT (Cuba DST)\nXX\t+2308-08222\tAmerica/Havana\tCuba\n#\n# -05/-04 - EST/EDT (North America DST)\nXX\t+404251-0740023\tAmerica/New_York\tEastern (EST/EDT) - US & Canada\n#\n# -04\nXX\t+1030-06656\tAmerica/Caracas\twestern South America\n#\n# -04 - AST\nXX\t+1828-06954\tAmerica/Santo_Domingo\tAtlantic Standard (AST) - eastern Caribbean\n#\n# -04/-03 (Chile DST)\nXX\t-3327-07040\tAmerica/Santiago\tmost of Chile\n#\n# -04/-03 - AST/ADT (North America DST)\nXX\t+4439-06336\tAmerica/Halifax\tAtlantic (AST/ADT) - Canada; Bermuda\n#\n# -03:30/-02:30 - NST/NDT (North America DST)\nXX\t+4734-05243\tAmerica/St_Johns\tNewfoundland (NST/NDT)\n#\n# -03\nXX\t-2332-04637\tAmerica/Sao_Paulo\teastern and southern South America\n#\n# -03/-02 (North America DST)\nXX\t+4703-05620\tAmerica/Miquelon\tSt Pierre & Miquelon\n#\n# -02\nXX\t-0351-03225\tAmerica/Noronha\tFernando de Noronha; South Georgia\n#\n# -02/-01 (EU DST)\nXX\t+6411-05144\tAmerica/Nuuk\tmost of Greenland\n#\n# -01\nXX\t+1455-02331\tAtlantic/Cape_Verde\tCape Verde\n#\n# -01/+00 (EU DST)\nXX\t+3744-02540\tAtlantic/Azores\tAzores\n#\n# +00 - GMT\nXX\t+0519-00402\tAfrica/Abidjan\tfar western Africa; Iceland (GMT)\n#\n# +00/+01 - GMT/BST (EU DST)\nXX\t+513030-0000731\tEurope/London\tUnited Kingdom (GMT/BST)\n#\n# +00/+01 - WET/WEST (EU DST)\nXX\t+3843-00908\tEurope/Lisbon\twestern Europe (WET/WEST)\n#\n# +00/+02 - Troll DST\nXX\t-720041+0023206\tAntarctica/Troll\tTroll Station in Antarctica\n#\n# +01 - CET\nXX\t+3647+00303\tAfrica/Algiers\tAlgeria, Tunisia (CET)\n#\n# +01 - WAT\nXX\t+0627+00324\tAfrica/Lagos\twestern Africa (WAT)\n#\n# +01/+00 - IST/GMT (EU DST in reverse)\nXX\t+5320-00615\tEurope/Dublin\tIreland (IST/GMT)\n#\n# +01/+00 - (Morocco DST)\nXX\t+3339-00735\tAfrica/Casablanca\tMorocco\n#\n# +01/+02 - CET/CEST (EU DST)\nXX\t+4852+00220\tEurope/Paris\tcentral Europe (CET/CEST)\n#\n# +02 - CAT\nXX\t-2558+03235\tAfrica/Maputo\tcentral Africa (CAT)\n#\n# +02 - EET\nXX\t+3254+01311\tAfrica/Tripoli\tLibya; Kaliningrad (EET)\n#\n# +02 - SAST\nXX\t-2615+02800\tAfrica/Johannesburg\tsouthern Africa (SAST)\n#\n# +02/+03 - EET/EEST (EU DST)\nXX\t+3758+02343\tEurope/Athens\teastern Europe (EET/EEST)\n#\n# +02/+03 - EET/EEST (Egypt DST)\nXX\t+3003+03115\tAfrica/Cairo\tEgypt\n#\n# +02/+03 - EET/EEST (Lebanon DST)\nXX\t+3353+03530\tAsia/Beirut\tLebanon\n#\n# +02/+03 - EET/EEST (Palestine DST)\nXX\t+3130+03428\tAsia/Gaza\tPalestine\n#\n# +02/+03 - IST/IDT (Israel DST)\nXX\t+314650+0351326\tAsia/Jerusalem\tIsrael\n#\n# +03\nXX\t+4101+02858\tEurope/Istanbul\tNear East; Belarus\n#\n# +03 - EAT\nXX\t-0117+03649\tAfrica/Nairobi\teastern Africa (EAT)\n#\n# +03 - MSK\nXX\t+554521+0373704\tEurope/Moscow\tMoscow (MSK)\n#\n# +03:30\nXX\t+3540+05126\tAsia/Tehran\tIran\n#\n# +04\nXX\t+2518+05518\tAsia/Dubai\tRussia; Caucasus; Persian Gulf; Seychelles; Réunion\n#\n# +04:30\nXX\t+3431+06912\tAsia/Kabul\tAfghanistan\n#\n# +05\nXX\t+4120+06918\tAsia/Tashkent\tRussia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives\n#\n# +05 - PKT\nXX\t+2452+06703\tAsia/Karachi\tPakistan (PKT)\n#\n# +05:30\nXX\t+0656+07951\tAsia/Colombo\tSri Lanka\n#\n# +05:30 - IST\nXX\t+2232+08822\tAsia/Kolkata\tIndia (IST)\n#\n# +05:45\nXX\t+2743+08519\tAsia/Kathmandu\tNepal\n#\n# +06\nXX\t+2343+09025\tAsia/Dhaka\tRussia; Kyrgyzstan; Bhutan; Bangladesh; Chagos\n#\n# +06:30\nXX\t+1647+09610\tAsia/Yangon\tMyanmar; Cocos\n#\n# +07\nXX\t+1345+10031\tAsia/Bangkok\tRussia; Indochina; Christmas Island\n#\n# +07 - WIB\nXX\t-0610+10648\tAsia/Jakarta\tIndonesia (WIB)\n#\n# +08\nXX\t+0117+10351\tAsia/Singapore\tRussia; Brunei; Malaysia; Singapore; Concordia\n#\n# +08 - AWST\nXX\t-3157+11551\tAustralia/Perth\tWestern Australia (AWST)\n#\n# +08 - CST\nXX\t+3114+12128\tAsia/Shanghai\tChina (CST)\n#\n# +08 - HKT\nXX\t+2217+11409\tAsia/Hong_Kong\tHong Kong (HKT)\n#\n# +08 - PHT\nXX\t+143512+1205804\tAsia/Manila\tPhilippines (PHT)\n#\n# +08 - WITA\nXX\t-0507+11924\tAsia/Makassar\tIndonesia (WITA)\n#\n# +08:45\nXX\t-3143+12852\tAustralia/Eucla\tEucla\n#\n# +09\nXX\t+5203+11328\tAsia/Chita\tRussia; Palau; East Timor\n#\n# +09 - JST\nXX\t+353916+1394441\tAsia/Tokyo\tJapan (JST); Eyre Bird Observatory\n#\n# +09 - KST\nXX\t+3733+12658\tAsia/Seoul\tKorea (KST)\n#\n# +09 - WIT\nXX\t-0232+14042\tAsia/Jayapura\tIndonesia (WIT)\n#\n# +09:30 - ACST\nXX\t-1228+13050\tAustralia/Darwin\tNorthern Territory (ACST)\n#\n# +09:30/+10:30 - ACST/ACDT (Australia DST)\nXX\t-3455+13835\tAustralia/Adelaide\tSouth Australia (ACST/ACDT)\n#\n# +10\nXX\t+4310+13156\tAsia/Vladivostok\tRussia; Yap; Chuuk; Papua New Guinea; Dumont d’Urville\n#\n# +10 - AEST\nXX\t-2728+15302\tAustralia/Brisbane\tQueensland (AEST)\n#\n# +10 - ChST\nXX\t+1328+14445\tPacific/Guam\tMariana Islands (ChST)\n#\n# +10/+11 - AEST/AEDT (Australia DST)\nXX\t-3352+15113\tAustralia/Sydney\tsoutheast Australia (AEST/AEDT)\n#\n# +10:30/+11\nXX\t-3133+15905\tAustralia/Lord_Howe\tLord Howe Island\n#\n# +11\nXX\t-0613+15534\tPacific/Bougainville\tRussia; Kosrae; Bougainville; Solomons\n#\n# +11/+12 (Australia DST)\nXX\t-2903+16758\tPacific/Norfolk\tNorfolk Island\n#\n# +12\nXX\t+5301+15839\tAsia/Kamchatka\tRussia; Tuvalu; Fiji; etc.\n#\n# +12/+13 (New Zealand DST)\nXX\t-3652+17446\tPacific/Auckland\tNew Zealand (NZST/NZDT)\n#\n# +12:45/+13:45 (Chatham DST)\nXX\t-4357-17633\tPacific/Chatham\tChatham Islands\n#\n# +13\nXX\t-210800-1751200\tPacific/Tongatapu\tKanton; Tokelau; Samoa (western); Tonga\n#\n# +14\nXX\t+0152-15720\tPacific/Kiritimati\tKiritimati\n"
  },
  {
    "path": "absl/time/internal/get_current_time_chrono.inc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <chrono>\n#include <cstdint>\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\n\nstatic int64_t GetCurrentTimeNanosFromSystem() {\n  return std::chrono::duration_cast<std::chrono::nanoseconds>(\n             std::chrono::system_clock::now() -\n             std::chrono::system_clock::from_time_t(0))\n      .count();\n}\n\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/get_current_time_posix.inc",
    "content": "#include \"absl/time/clock.h\"\n\n#include <sys/time.h>\n#include <ctime>\n#include <cstdint>\n\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\n\nstatic int64_t GetCurrentTimeNanosFromSystem() {\n  const int64_t kNanosPerSecond = 1000 * 1000 * 1000;\n  struct timespec ts;\n  ABSL_RAW_CHECK(clock_gettime(CLOCK_REALTIME, &ts) == 0,\n                 \"Failed to read real-time clock.\");\n  return (int64_t{ts.tv_sec} * kNanosPerSecond +\n          int64_t{ts.tv_nsec});\n}\n\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/test_util.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/internal/test_util.h\"\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\n\nTimeZone LoadTimeZone(const std::string& name) {\n  TimeZone tz;\n  ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str());\n  return tz;\n}\n\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/internal/test_util.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_TIME_INTERNAL_TEST_UTIL_H_\n#define ABSL_TIME_INTERNAL_TEST_UTIL_H_\n\n#include <string>\n\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace time_internal {\n\n// Loads the named timezone, but dies on any failure.\nabsl::TimeZone LoadTimeZone(const std::string& name);\n\n}  // namespace time_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_INTERNAL_TEST_UTIL_H_\n"
  },
  {
    "path": "absl/time/simulated_clock.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/simulated_clock.h\"\n\n#include <cstdint>\n#include <map>\n#include <memory>\n#include <optional>\n#include <utility>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// There are a few tricky details in the implementation of SimulatedClock.\n//\n// The external mutex that is passed as a param of AwaitWithDeadline() is not\n// under the control of SimulatedClock; in particular, it can be destroyed any\n// time after AwaitWithDeadline() returns.  This requires the wakeup call from\n// AdvanceTime() to avoid grabbing the external mutex if AwaitWithDeadline()\n// has returned.  This is accomplished by allowing the waiter to be cancelled\n// via a bool guarded by a mutex in WakeUpInfo.\n//\n// Once AwaitWithDeadline() has released lock_, someone nefarious might call\n// the SimulatedClock destructor, so it isn't possible for AwaitWithDeadline()\n// to remove the wakeup call from waiters_ if the condition it is awaiting\n// becomes true; it cancels the waiter instead.  This means that,\n// theoretically, many obsolete entries could pile up in waiters_ if\n// AwaitWithDeadline() keeps being called but simulated time is not advanced.\n// This seems unlikely to happen in practice.\n//\n// The WakeUpInfo in waiters_ are always awoken via WakeUp() (and\n// removed) or cancelled before AwaitWithDeadline() returns.  If a\n// waiters_ value is cancelled then calling its WakeUp() method will\n// short-circuit before touching the external mutex.\n\nclass SimulatedClock::WakeUpInfo {\n public:\n  WakeUpInfo(absl::Mutex* mu, absl::Condition cond)\n      : mu_(mu),\n        cond_(cond),\n        wakeup_time_passed_(false),\n        cancelled_(false),\n        wakeup_called_(false) {}\n\n  void WakeUp() {\n    // If we are cancelled then AwaitWithDeadline may have returned, in which\n    // case we can't lock mu_.\n    {\n      absl::MutexLock lock(cancellation_mu_);\n      if (cancelled_) return;\n      wakeup_called_ = true;\n    }\n    absl::MutexLock lock(*mu_);\n    wakeup_time_passed_ = true;\n  }\n\n  void AwaitConditionOrWakeUp() {\n    mu_->Await(absl::Condition(this, &WakeUpInfo::Ready));\n  }\n\n  void CancelOrAwaitWakeUp() {\n    bool wakeup_called;\n    {\n      absl::MutexLock lock(cancellation_mu_);\n      cancelled_ = true;\n      wakeup_called = wakeup_called_;\n    }\n    if (wakeup_called && !wakeup_time_passed_) {\n      // Wait for WakeUp to complete.\n      //\n      // Note that this will unlock 'mu_'; this is actually necessary\n      // so that WakeUp() can unblock and complete.  This does allow\n      // for 'cond_' to potentially change from true to false; that is\n      // OK, since WakeUp() is being called, so the deadline must be\n      // past, and so this method is fulfilling its duties.  (Well, the\n      // destructor might be calling WakeUp(), but if you're deleting\n      // time itself while waiting for a deadline to pass, you deserve\n      // what you get.)\n      mu_->Await(absl::Condition(&wakeup_time_passed_));\n    }\n  }\n\n private:\n  bool Ready() const { return wakeup_time_passed_ || cond_.Eval(); }\n\n  absl::Mutex* mu_;\n  absl::Condition cond_;\n  bool wakeup_time_passed_;\n  absl::Mutex cancellation_mu_;\n  bool cancelled_ ABSL_GUARDED_BY(cancellation_mu_);\n  bool wakeup_called_ ABSL_GUARDED_BY(cancellation_mu_);\n};\n\nSimulatedClock::SimulatedClock(absl::Time t) : now_(t) {}\n\nSimulatedClock::~SimulatedClock() {\n  // Wake up all existing waiters.\n  WaiterList waiters;\n  {\n    absl::MutexLock l(lock_);\n    waiters.swap(waiters_);\n  }\n  for (auto& iter : waiters) {\n    iter.second->WakeUp();\n  }\n}\n\nabsl::Time SimulatedClock::TimeNow() {\n  absl::ReaderMutexLock l(lock_);\n  return now_;\n}\n\nvoid SimulatedClock::Sleep(absl::Duration d) { SleepUntil(TimeNow() + d); }\n\nint64_t SimulatedClock::SetTime(absl::Time t) ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  return UpdateTime([this, t]()\n                        ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock_) { now_ = t; });\n}\n\nint64_t SimulatedClock::AdvanceTime(absl::Duration d)\n    ABSL_NO_THREAD_SAFETY_ANALYSIS {\n  return UpdateTime([this, d]()\n                        ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock_) { now_ += d; });\n}\n\ntemplate <class T>\nint64_t SimulatedClock::UpdateTime(const T& now_updater) {\n  // Deadlock could occur if UpdateTime() were to hold lock_ while waking up\n  // waiters, since waking up requires acquiring the external mutex, and\n  // AwaitWithDeadline() acquires the mutexes in the opposite order.  So let's\n  // first grab all the wakeup callbacks, then release lock_, then call the\n  // callbacks.\n  std::vector<WaiterList::mapped_type> wakeup_calls;\n\n  lock_.lock();\n  now_updater();  // reset now_\n  WaiterList::iterator iter;\n  while (((iter = waiters_.begin()) != waiters_.end()) &&\n         (iter->first <= now_)) {\n    wakeup_calls.push_back(std::move(iter->second));\n    waiters_.erase(iter);\n  }\n  lock_.unlock();\n\n  for (const auto& wakeup_call : wakeup_calls) {\n    wakeup_call->WakeUp();\n  }\n\n  return static_cast<int64_t>(wakeup_calls.size());\n}\n\nvoid SimulatedClock::SleepUntil(absl::Time wakeup_time) {\n  absl::Mutex mu;\n  absl::MutexLock lock(mu);\n  bool f = false;\n  AwaitWithDeadline(&mu, absl::Condition(&f), wakeup_time);\n}\n\nbool SimulatedClock::AwaitWithDeadline(absl::Mutex* mu,\n                                       const absl::Condition& cond,\n                                       absl::Time deadline) {\n  mu->AssertReaderHeld();\n\n  // Evaluate cond outside our own lock to minimize contention.\n  const bool ready = cond.Eval();\n\n  lock_.lock();\n  num_await_calls_++;\n\n  // Return now if the deadline is already past, or if the condition is true.\n  // This avoids creating a WakeUpInfo that won't be deleted until an\n  // appropriate UpdateTime() call.\n  if (deadline <= now_ || ready) {\n    lock_.unlock();\n    return ready;\n  }\n\n  auto wakeup_info = std::make_shared<WakeUpInfo>(mu, cond);\n  waiters_.insert(std::make_pair(deadline, wakeup_info));\n\n  lock_.unlock();\n  // SimulatedClock may be destroyed any time after this, so we can't\n  // acquire lock_ again.\n\n  // Wait until either cond.Eval() becomes true, or the deadline has passed.\n  wakeup_info->AwaitConditionOrWakeUp();\n\n  // Cancel the wakeup call, or if it's already in progress, wait for it to\n  // finish, since we must ensure no one touches 'mu' or 'cond' after we return.\n  wakeup_info->CancelOrAwaitWakeUp();\n\n  return cond.Eval();\n}\n\nstd::optional<absl::Time> SimulatedClock::GetEarliestWakeupTime() const {\n  absl::ReaderMutexLock l(lock_);\n  if (waiters_.empty()) {\n    return std::nullopt;\n  }\n  return waiters_.begin()->first;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/simulated_clock.h",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: simulated_clock.h\n// -----------------------------------------------------------------------------\n\n#ifndef ABSL_TIME_SIMULATED_CLOCK_H_\n#define ABSL_TIME_SIMULATED_CLOCK_H_\n\n#include <cstdint>\n#include <map>\n#include <memory>\n#include <optional>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/clock_interface.h\"\n#include \"absl/time/time.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// A simulated clock is a concrete Clock implementation that does not \"tick\"\n// on its own.  Time is advanced by explicit calls to the AdvanceTime() or\n// SetTime() functions.\n//\n// Example:\n//   absl::SimulatedClock sim_clock;\n//   absl::Time now = sim_clock.TimeNow();\n//   // now == absl::UnixEpoch()\n//\n//   now = sim_clock.TimeNow();\n//   // now == absl::UnixEpoch() (still)\n//\n//   sim_clock.AdvanceTime(absl::Seconds(3));\n//   now = sim_clock.TimeNow();\n//   // now == absl::UnixEpoch() + absl::Seconds(3)\n//\n// This class is thread-safe.\nclass SimulatedClock : public Clock {\n public:\n  explicit SimulatedClock(absl::Time t);\n  SimulatedClock() : SimulatedClock(absl::UnixEpoch()) {}\n\n  // The destructor should be called only if all Sleep(), etc. and\n  // AdvanceTime() calls have completed. The code does its best to let\n  // any pending calls finish gracefully, but there are no guarantees.\n  ~SimulatedClock() override;\n\n  // Returns the simulated time.\n  absl::Time TimeNow() override;\n\n  // Sleeps until the specified duration has elapsed according to this clock.\n  void Sleep(absl::Duration d) override;\n\n  // Sleeps until the specified wakeup_time.\n  void SleepUntil(absl::Time wakeup_time) override;\n\n  // Sets the simulated time to the argument.  Wakes up any threads whose\n  // sleeps have now expired. Returns the number of woken threads.\n  int64_t SetTime(absl::Time t);\n\n  // Advances the simulated time by the specified duration.  Wakes up any\n  // threads whose sleeps have now expired. Returns the number of woken threads.\n  int64_t AdvanceTime(absl::Duration d);\n\n  // Blocks until the condition is true or until the simulated clock is\n  // advanced to or beyond the wakeup time (or both).\n  bool AwaitWithDeadline(absl::Mutex* absl_nonnull mu,\n                         const absl::Condition& cond,\n                         absl::Time deadline) override\n      ABSL_SHARED_LOCKS_REQUIRED(mu);\n\n  // Returns the earliest wakeup time.\n  std::optional<absl::Time> GetEarliestWakeupTime() const;\n\n private:\n  template <class T>\n  int64_t UpdateTime(const T& now_updater) ABSL_LOCKS_EXCLUDED(lock_);\n\n  class WakeUpInfo;\n  using WaiterList = std::multimap<absl::Time, std::shared_ptr<WakeUpInfo>>;\n\n  mutable absl::Mutex lock_;\n  absl::Time now_ ABSL_GUARDED_BY(lock_);\n  WaiterList waiters_ ABSL_GUARDED_BY(lock_);\n  int64_t num_await_calls_ ABSL_GUARDED_BY(lock_) = 0;\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_SIMULATED_CLOCK_H_\n"
  },
  {
    "path": "absl/time/simulated_clock_test.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/simulated_clock.h\"\n\n#include <cstddef>\n#include <cstdint>\n#include <memory>\n#include <thread>  // NOLINT(build/c++11)\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/thread_annotations.h\"\n#include \"absl/random/random.h\"\n#include \"absl/synchronization/blocking_counter.h\"\n#include \"absl/synchronization/mutex.h\"\n#include \"absl/synchronization/notification.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/clock_interface.h\"\n#include \"absl/time/time.h\"\n\nnamespace {\n\nconstexpr absl::Duration kShortPause = absl::Milliseconds(20);\nconstexpr absl::Duration kLongPause = absl::Milliseconds(1000);\n\n#ifdef _MSC_VER\n// As of 2026-01-29, multithreaded tests on MSVC are too flaky.\nconst char* kSkipFlakyReason =\n    \"Skipping this timing test because it is too flaky\";\n#else\nconst char* kSkipFlakyReason = nullptr;\n#endif\n\nTEST(SimulatedClock, TimeInitializedToZero) {\n  absl::SimulatedClock simclock;\n  EXPECT_EQ(absl::UnixEpoch(), simclock.TimeNow());\n}\n\nTEST(SimulatedClock, NowSetTime) {\n  absl::SimulatedClock simclock;\n  absl::Time now = simclock.TimeNow();\n\n  now += absl::Seconds(123);\n  simclock.SetTime(now);\n  EXPECT_EQ(now, simclock.TimeNow());\n\n  now += absl::Seconds(123);\n  simclock.SetTime(now);\n  EXPECT_EQ(now, simclock.TimeNow());\n\n  now += absl::ZeroDuration();\n  simclock.SetTime(now);\n  EXPECT_EQ(now, simclock.TimeNow());\n}\n\nTEST(SimulatedClock, NowAdvanceTime) {\n  absl::SimulatedClock simclock;\n  absl::Time now = simclock.TimeNow();\n\n  simclock.AdvanceTime(absl::Seconds(123));\n  now += absl::Seconds(123);\n  EXPECT_EQ(now, simclock.TimeNow());\n\n  simclock.AdvanceTime(absl::Seconds(123));\n  now += absl::Seconds(123);\n  EXPECT_EQ(now, simclock.TimeNow());\n\n  simclock.AdvanceTime(absl::ZeroDuration());\n  now += absl::ZeroDuration();\n  EXPECT_EQ(now, simclock.TimeNow());\n}\n\nvoid SleepAndNotify(absl::Clock* clock, absl::Duration sleep_secs,\n                    absl::Notification* note) {\n  clock->Sleep(sleep_secs);\n  note->Notify();\n}\n\nTEST(SimulatedClock, Sleep_SetToSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);\n\n  // wait for SleepAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.SetTime(absl::FromUnixSeconds(122));\n  // give Sleep() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.SetTime(absl::FromUnixSeconds(122 + 1));\n  // wait for Sleep() to return\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepAdvanceToSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);\n  // wait for SleepAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.AdvanceTime(absl::Seconds(122));\n  // give Sleep() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.AdvanceTime(absl::Seconds(1));\n  // wait for Sleep() to return\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepSetPastSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);\n  // wait for SleepAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.SetTime(absl::FromUnixSeconds(122));\n  // give Sleep() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.SetTime(absl::FromUnixSeconds(122 + 2));\n  // wait for Sleep() to return\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepAdvancePastSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);\n  // wait for SleepAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.AdvanceTime(absl::Seconds(122));\n  // give Sleep() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.AdvanceTime(absl::Seconds(2));\n  // wait for Sleep() to return\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepZeroSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  std::thread tr(SleepAndNotify, &simclock, absl::ZeroDuration(), &note);\n  // wait for SleepAndNotify() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nvoid SleepUntilAndNotify(absl::Clock* clock, absl::Time wakeup_time,\n                         absl::Notification* note) {\n  clock->SleepUntil(wakeup_time);\n  note->Notify();\n}\n\nTEST(SimulatedClock, SleepUntilSetToSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  simclock.SetTime(absl::FromUnixSeconds(123));\n  std::thread tr(SleepUntilAndNotify, &simclock,\n                 absl::UnixEpoch() + absl::Seconds(246), &note);\n  // wait for SleepUntilAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.SetTime(absl::FromUnixSeconds(123 + 122));\n  // give SleepUntil() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.SetTime(absl::FromUnixSeconds(123 + 122 + 1));\n  absl::Time start = absl::Now();\n  note.WaitForNotification();  // SleepUntilAndNotify() should ping note\n  EXPECT_GE(absl::Milliseconds(50), absl::Now() - start);\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepUntilAdvanceToSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  simclock.AdvanceTime(absl::Seconds(123));\n  std::thread tr(SleepUntilAndNotify, &simclock,\n                 absl::UnixEpoch() + absl::Seconds(246), &note);\n  // wait for SleepUntilAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.AdvanceTime(absl::Seconds(122));\n  // give SleepUntil() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.AdvanceTime(absl::Seconds(1));\n  absl::Time start = absl::Now();\n  note.WaitForNotification();  // SleepUntilAndNotify() should ping note\n  EXPECT_GE(absl::Milliseconds(70), absl::Now() - start);\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepUntilSetPastSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  simclock.SetTime(absl::FromUnixSeconds(123));\n  std::thread tr(SleepUntilAndNotify, &simclock,\n                 absl::UnixEpoch() + absl::Seconds(246), &note);\n  // wait for SleepUntilAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.SetTime(absl::FromUnixSeconds(123 + 122));\n  // give SleepUntil() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.SetTime(absl::FromUnixSeconds(123 + 122 + 2));\n  // wait for SleepUntilAndNotify() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepUntilAdvancePastSleepTime) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  simclock.AdvanceTime(absl::Seconds(123));\n  std::thread tr(SleepUntilAndNotify, &simclock,\n                 absl::UnixEpoch() + absl::Seconds(246), &note);\n  // wait for SleepUntilAndNotify() to block\n  absl::SleepFor(kLongPause);\n  simclock.AdvanceTime(absl::Seconds(122));\n  // give SleepUntil() the opportunity to fail\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.AdvanceTime(absl::Seconds(2));\n  // wait for SleepUntilAndNotify() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, SleepUntilTimeAlreadyPassed) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Notification note;\n\n  simclock.AdvanceTime(absl::Seconds(123));\n  std::thread tr(SleepUntilAndNotify, &simclock,\n                 absl::UnixEpoch() + absl::Seconds(123), &note);\n  // wait for SleepUntilAndNotify() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nvoid AwaitWithDeadlineAndNotify(absl::Clock* clock, absl::Mutex* mu,\n                                absl::Condition* cond, absl::Time wakeup_time,\n                                absl::Notification* note, bool* return_val) {\n  mu->lock_shared();\n  *return_val = clock->AwaitWithDeadline(mu, *cond, wakeup_time);\n  mu->unlock_shared();\n  note->Notify();\n}\n\nTEST(SimulatedClock, AwaitWithDeadlineConditionInitiallyTrue) {\n  absl::SimulatedClock simclock;\n  absl::Mutex mu;\n  bool f = true;\n  absl::Condition cond(&f);\n  absl::MutexLock lock(mu);\n  ASSERT_TRUE(simclock.AwaitWithDeadline(&mu, cond, absl::InfiniteFuture()));\n}\n\nTEST(SimulatedClock, AwaitWithDeadlineConditionInitiallyFalse) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Mutex mu;\n  bool f = false;\n  absl::Condition cond(&f);\n  absl::Notification note;\n  bool return_val;\n\n  std::thread tr(AwaitWithDeadlineAndNotify, &simclock, &mu, &cond,\n                 absl::UnixEpoch() + absl::Seconds(123), &note, &return_val);\n  // wait for AwaitWithDeadline...() to block\n  absl::SleepFor(kShortPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  mu.lock();\n  f = true;\n  mu.unlock();\n  // wait for AwaitWithDeadline...() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  EXPECT_TRUE(return_val);\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, AwaitWithDeadlineDeadlinePassed) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Mutex mu;\n  bool f = false;\n  absl::Condition cond(&f);\n  absl::Notification note;\n  bool return_val;\n\n  std::thread tr(AwaitWithDeadlineAndNotify, &simclock, &mu, &cond,\n                 absl::UnixEpoch() + absl::Seconds(123), &note, &return_val);\n  // wait for AwaitWithDeadline...() to block\n  absl::SleepFor(kLongPause);\n  EXPECT_FALSE(note.HasBeenNotified());\n  simclock.AdvanceTime(absl::Seconds(124));\n  // wait for AwaitWithDeadline...() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  EXPECT_FALSE(return_val);\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nTEST(SimulatedClock, AwaitWithDeadlineDeadlineAlreadyPassed) {\n  if (kSkipFlakyReason != nullptr) {\n    GTEST_SKIP() << kSkipFlakyReason;\n  }\n\n  absl::SimulatedClock simclock;\n  absl::Mutex mu;\n  bool f = false;\n  absl::Condition cond(&f);\n  absl::Notification note;\n  bool return_val;\n\n  std::thread tr(AwaitWithDeadlineAndNotify, &simclock, &mu, &cond,\n                 absl::UnixEpoch(), &note, &return_val);\n  // wait for AwaitWithDeadline...() to ping note\n  absl::SleepFor(kLongPause);\n  EXPECT_TRUE(note.HasBeenNotified());\n  EXPECT_FALSE(return_val);\n  note.WaitForNotification();  // in case the expectation fails\n  tr.join();\n}\n\nvoid RacerMakesConditionTrue(absl::Notification* start_note, absl::Mutex* mu,\n                             bool* f, absl::BlockingCounter* threads_done) {\n  start_note->WaitForNotification();\n  absl::SleepFor(absl::Milliseconds(1));\n  mu->lock();\n  *f = true;\n  mu->unlock();\n  threads_done->DecrementCount();\n}\n\nvoid RacerAdvancesTime(absl::Notification* start_note,\n                       absl::SimulatedClock* simclock, absl::Duration d,\n                       absl::BlockingCounter* threads_done) {\n  start_note->WaitForNotification();\n  absl::SleepFor(absl::Milliseconds(1));\n  simclock->AdvanceTime(d);\n  threads_done->DecrementCount();\n}\n\nTEST(SimulatedClock, SimultaneousConditionTrueAndDeadline) {\n  absl::SimulatedClock simclock;\n  for (int iteration = 0; iteration < 100; ++iteration) {\n    auto mu = std::make_unique<absl::Mutex>();\n    bool f = false;\n    absl::Condition cond(&f);\n    absl::Notification note_start;\n    absl::BlockingCounter threads_done(2);\n    std::thread tr1(RacerMakesConditionTrue, &note_start, mu.get(), &f,\n                    &threads_done);\n    std::thread tr2(RacerAdvancesTime, &note_start, &simclock,\n                    absl::Seconds(20), &threads_done);\n    note_start.Notify();\n    mu->lock();\n    absl::Time deadline = simclock.TimeNow() + absl::Seconds(10);\n    simclock.AwaitWithDeadline(mu.get(), cond, deadline);\n    EXPECT_TRUE(f || (simclock.TimeNow() >= deadline));\n    if (f) {\n      // RacerMakesConditionTrue has unlocked mu and AwaitWithDeadline has\n      // returned, so it is safe to destruct mu. Do so while RacerAdvancesTime\n      // is possibly still running in an attempt to catch simclock holding on\n      // to a reference to mu and using it after AwaitWithDeadline returns.\n      mu->unlock();\n      mu = nullptr;\n    } else {\n      mu->unlock();\n    }\n    threads_done.Wait();\n    tr1.join();\n    tr2.join();\n  }\n}\n\nvoid RacerDeletesClock(absl::Mutex* mu, absl::Notification* start_note,\n                       absl::Clock* clock,\n                       absl::BlockingCounter* threads_done) {\n  start_note->WaitForNotification();\n  // mu is acquired temporarily to make sure that AwaitWithDeadline() in\n  // SimultaneousConditionTrueAndDestruction has blocked.\n  mu->lock();\n  mu->unlock();\n  absl::SleepFor(absl::Milliseconds(1));\n  delete clock;\n  threads_done->DecrementCount();\n}\n\nTEST(SimulatedClock, SimultaneousConditionTrueAndDestruction) {\n  for (int iteration = 0; iteration < 100; ++iteration) {\n    absl::Clock* clock = new absl::SimulatedClock();\n    absl::Mutex mu;\n    bool f = false;\n    absl::Condition cond(&f);\n    absl::Notification note_start;\n    absl::BlockingCounter threads_done(2);\n    std::thread tr1([&note_start, &mu, &f, &threads_done] {\n      RacerMakesConditionTrue(&note_start, &mu, &f, &threads_done);\n    });\n    std::thread tr2([&mu, &note_start, clock, &threads_done] {\n      RacerDeletesClock(&mu, &note_start, clock, &threads_done);\n    });\n    mu.lock();\n    note_start.Notify();\n    absl::Time deadline = absl::UnixEpoch() + absl::Seconds(100000);\n    clock->AwaitWithDeadline(&mu, cond, deadline);\n    mu.unlock();\n    threads_done.Wait();\n    tr1.join();\n    tr2.join();\n  }\n}\n\nclass SimulatedClockTorturer {\n public:\n  SimulatedClockTorturer(absl::SimulatedClock* simclock, int num_threads,\n                         int num_iterations)\n      : simclock_(simclock),\n        num_threads_(num_threads),\n        num_iterations_(num_iterations),\n        num_flags_(2 * num_threads),\n        mutex_and_flag_(static_cast<size_t>(num_flags_)) {}\n\n  // Implements a torture test.\n  //\n  // This method uses several groups of:\n  //   SimulatedClock\n  //   Mutex protected flag\n  // It starts several threads that call AwaitWithDeadline() and several\n  // threads that call AdvanceTime() or toggle flag values.\n  void DoTorture() {\n    // The threads calling AwaitWithDeadline() have a separate BlockingCounter\n    // than the threads calling AdvanceTime()/toggling flags, since the former\n    // would be deadlocked if all the threads that might unblock them had\n    // already finished.\n    absl::Notification go;\n    absl::BlockingCounter await_threads_done(num_threads_);\n    absl::Notification signal_threads_should_exit;\n    absl::BlockingCounter signal_threads_done(num_threads_);\n    std::vector<std::thread> trs;\n    for (int i = 0; i < num_threads_; ++i) {\n      trs.emplace_back(&SimulatedClockTorturer::AwaitRandomly, this, &go,\n                       &await_threads_done);\n    }\n    for (int i = 0; i < num_threads_; ++i) {\n      trs.emplace_back(&SimulatedClockTorturer::SignalRandomly, this, &go,\n                       &signal_threads_should_exit, &signal_threads_done);\n    }\n    go.Notify();\n    await_threads_done.Wait();\n    signal_threads_should_exit.Notify();\n    signal_threads_done.Wait();\n    for (auto& thread : trs) {\n      thread.join();\n    }\n  }\n\n private:\n  // Randomly call AwaitWithDeadline() for num_iterations_ times.\n  void AwaitRandomly(absl::Notification* go,\n                     absl::BlockingCounter* threads_done) {\n    go->WaitForNotification();\n\n    absl::BitGen gen;\n    for (int i = 0; i < num_iterations_; ++i) {\n      auto& [mu, f] = mutex_and_flag_[absl::Uniform<size_t>(gen, size_t{0},\n                                         static_cast<size_t>(num_flags_))];\n      absl::MutexLock lock(mu);\n      absl::Time deadline = simclock_->TimeNow() + absl::Seconds(1);\n      simclock_->AwaitWithDeadline(&mu, absl::Condition(&f), deadline);\n      ABSL_RAW_CHECK(f || simclock_->TimeNow() >= deadline, \"\");\n    }\n\n    threads_done->DecrementCount();\n  }\n\n  // Randomly call AdvanceTime() or toggle a flag value until notified to\n  // stop.\n  void SignalRandomly(absl::Notification* go, absl::Notification* should_exit,\n                      absl::BlockingCounter* threads_done) {\n    go->WaitForNotification();\n\n    absl::BitGen gen;\n    while (!should_exit->HasBeenNotified()) {\n      int action = absl::Uniform<int>(gen, 0, num_flags_ + 1);\n      if (action < num_flags_) {\n        // Change a flag value.\n        auto& [mutex, flag] = mutex_and_flag_[static_cast<size_t>(action)];\n        absl::MutexLock lock(mutex);\n        flag = !flag;\n      } else {\n        // Advance time.\n        simclock_->AdvanceTime(absl::Seconds(1));\n      }\n    }\n\n    threads_done->DecrementCount();\n  }\n\n  absl::SimulatedClock* simclock_;\n  int num_threads_;\n  int num_iterations_;\n  int num_flags_;\n\n  struct MutexAndFlag {\n    absl::Mutex mutex;\n    bool flag ABSL_GUARDED_BY(mutex) = false;\n  };\n  std::vector<MutexAndFlag> mutex_and_flag_;\n};\n\nTEST(SimulatedClock, Torture) {\n  absl::SimulatedClock simclock;\n  constexpr int kNumThreads = 10;\n  constexpr int kNumIterations = 1000;\n  SimulatedClockTorturer torturer(&simclock, kNumThreads, kNumIterations);\n  torturer.DoTorture();\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/time.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// The implementation of the absl::Time class, which is declared in\n// //absl/time.h.\n//\n// The representation for an absl::Time is an absl::Duration offset from the\n// epoch.  We use the traditional Unix epoch (1970-01-01 00:00:00 +0000)\n// for convenience, but this is not exposed in the API and could be changed.\n//\n// NOTE: To keep type verbosity to a minimum, the following variable naming\n// conventions are used throughout this file.\n//\n// tz: An absl::TimeZone\n// ci: An absl::TimeZone::CivilInfo\n// ti: An absl::TimeZone::TimeInfo\n// cd: An absl::CivilDay or a cctz::civil_day\n// cs: An absl::CivilSecond or a cctz::civil_second\n// bd: An absl::Time::Breakdown\n// cl: A cctz::time_zone::civil_lookup\n// al: A cctz::time_zone::absolute_lookup\n\n#include \"absl/time/time.h\"\n\n#if defined(_MSC_VER)\n#include <winsock2.h>  // for timeval\n#endif\n\n#include <cstring>\n#include <ctime>\n#include <limits>\n\n#include \"absl/time/internal/cctz/include/cctz/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\nnamespace cctz = absl::time_internal::cctz;\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nnamespace {\n\ninline cctz::time_point<cctz::seconds> unix_epoch() {\n  return std::chrono::time_point_cast<cctz::seconds>(\n      std::chrono::system_clock::from_time_t(0));\n}\n\n// Floors d to the next unit boundary closer to negative infinity.\ninline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {\n  absl::Duration rem;\n  int64_t q = absl::IDivDuration(d, unit, &rem);\n  return (q > 0 || rem >= ZeroDuration() ||\n          q == std::numeric_limits<int64_t>::min())\n             ? q\n             : q - 1;\n}\n\nABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\ninline absl::Time::Breakdown InfiniteFutureBreakdown() {\n  absl::Time::Breakdown bd;\n  bd.year = std::numeric_limits<int64_t>::max();\n  bd.month = 12;\n  bd.day = 31;\n  bd.hour = 23;\n  bd.minute = 59;\n  bd.second = 59;\n  bd.subsecond = absl::InfiniteDuration();\n  bd.weekday = 4;\n  bd.yearday = 365;\n  bd.offset = 0;\n  bd.is_dst = false;\n  bd.zone_abbr = \"-00\";\n  return bd;\n}\n\ninline absl::Time::Breakdown InfinitePastBreakdown() {\n  Time::Breakdown bd;\n  bd.year = std::numeric_limits<int64_t>::min();\n  bd.month = 1;\n  bd.day = 1;\n  bd.hour = 0;\n  bd.minute = 0;\n  bd.second = 0;\n  bd.subsecond = -absl::InfiniteDuration();\n  bd.weekday = 7;\n  bd.yearday = 1;\n  bd.offset = 0;\n  bd.is_dst = false;\n  bd.zone_abbr = \"-00\";\n  return bd;\n}\nABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n\ninline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {\n  TimeZone::CivilInfo ci;\n  ci.cs = CivilSecond::max();\n  ci.subsecond = InfiniteDuration();\n  ci.offset = 0;\n  ci.is_dst = false;\n  ci.zone_abbr = \"-00\";\n  return ci;\n}\n\ninline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {\n  TimeZone::CivilInfo ci;\n  ci.cs = CivilSecond::min();\n  ci.subsecond = -InfiniteDuration();\n  ci.offset = 0;\n  ci.is_dst = false;\n  ci.zone_abbr = \"-00\";\n  return ci;\n}\n\nABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\ninline absl::TimeConversion InfiniteFutureTimeConversion() {\n  absl::TimeConversion tc;\n  tc.pre = tc.trans = tc.post = absl::InfiniteFuture();\n  tc.kind = absl::TimeConversion::UNIQUE;\n  tc.normalized = true;\n  return tc;\n}\n\ninline TimeConversion InfinitePastTimeConversion() {\n  absl::TimeConversion tc;\n  tc.pre = tc.trans = tc.post = absl::InfinitePast();\n  tc.kind = absl::TimeConversion::UNIQUE;\n  tc.normalized = true;\n  return tc;\n}\nABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n\n// Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as\n// necessary. If sec is min/max, then consult cs+tz to check for overflow.\nTime MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec,\n                          const cctz::civil_second& cs,\n                          const cctz::time_zone& tz,\n                          bool* normalized = nullptr) {\n  const auto max = cctz::time_point<cctz::seconds>::max();\n  const auto min = cctz::time_point<cctz::seconds>::min();\n  if (sec == max) {\n    const auto al = tz.lookup(max);\n    if (cs > al.cs) {\n      if (normalized) *normalized = true;\n      return absl::InfiniteFuture();\n    }\n  }\n  if (sec == min) {\n    const auto al = tz.lookup(min);\n    if (cs < al.cs) {\n      if (normalized) *normalized = true;\n      return absl::InfinitePast();\n    }\n  }\n  const auto hi = (sec - unix_epoch()).count();\n  return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));\n}\n\n// Returns Mon=1..Sun=7.\ninline int MapWeekday(const cctz::weekday& wd) {\n  switch (wd) {\n    case cctz::weekday::monday:\n      return 1;\n    case cctz::weekday::tuesday:\n      return 2;\n    case cctz::weekday::wednesday:\n      return 3;\n    case cctz::weekday::thursday:\n      return 4;\n    case cctz::weekday::friday:\n      return 5;\n    case cctz::weekday::saturday:\n      return 6;\n    case cctz::weekday::sunday:\n      return 7;\n  }\n  return 1;\n}\n\nbool FindTransition(const cctz::time_zone& tz,\n                    bool (cctz::time_zone::*find_transition)(\n                        const cctz::time_point<cctz::seconds>& tp,\n                        cctz::time_zone::civil_transition* trans) const,\n                    Time t, TimeZone::CivilTransition* trans) {\n  // Transitions are second-aligned, so we can discard any fractional part.\n  const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));\n  cctz::time_zone::civil_transition tr;\n  if (!(tz.*find_transition)(tp, &tr)) return false;\n  trans->from = CivilSecond(tr.from);\n  trans->to = CivilSecond(tr.to);\n  return true;\n}\n\n}  // namespace\n\n//\n// Time\n//\n\nABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\nabsl::Time::Breakdown Time::In(absl::TimeZone tz) const {\n  if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();\n  if (*this == absl::InfinitePast()) return InfinitePastBreakdown();\n\n  const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));\n  const auto al = cctz::time_zone(tz).lookup(tp);\n  const auto cs = al.cs;\n  const auto cd = cctz::civil_day(cs);\n\n  absl::Time::Breakdown bd;\n  bd.year = cs.year();\n  bd.month = cs.month();\n  bd.day = cs.day();\n  bd.hour = cs.hour();\n  bd.minute = cs.minute();\n  bd.second = cs.second();\n  bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));\n  bd.weekday = MapWeekday(cctz::get_weekday(cd));\n  bd.yearday = cctz::get_yearday(cd);\n  bd.offset = al.offset;\n  bd.is_dst = al.is_dst;\n  bd.zone_abbr = al.abbr;\n  return bd;\n}\nABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n\n//\n// Conversions from/to other time types.\n//\n\nabsl::Time FromUDate(double udate) {\n  return time_internal::FromUnixDuration(absl::Milliseconds(udate));\n}\n\nabsl::Time FromUniversal(int64_t universal) {\n  return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);\n}\n\nint64_t ToUnixNanos(Time t) {\n  if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&\n      time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {\n    return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000 *\n            1000 * 1000) +\n           (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4);\n  }\n  return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1));\n}\n\nint64_t ToUnixMicros(Time t) {\n  if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&\n      time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) {\n    return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000 *\n            1000) +\n           (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000);\n  }\n  return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1));\n}\n\nint64_t ToUnixMillis(Time t) {\n  if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&\n      time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) {\n    return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) +\n           (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) /\n            (4000 * 1000));\n  }\n  return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1));\n}\n\nint64_t ToUnixSeconds(Time t) {\n  return time_internal::GetRepHi(time_internal::ToUnixDuration(t));\n}\n\ntime_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }\n\ndouble ToUDate(Time t) {\n  return absl::FDivDuration(time_internal::ToUnixDuration(t),\n                            absl::Milliseconds(1));\n}\n\nint64_t ToUniversal(absl::Time t) {\n  return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));\n}\n\nabsl::Time TimeFromTimespec(timespec ts) {\n  return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));\n}\n\nabsl::Time TimeFromTimeval(timeval tv) {\n  return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));\n}\n\ntimespec ToTimespec(Time t) {\n  timespec ts;\n  absl::Duration d = time_internal::ToUnixDuration(t);\n  if (!time_internal::IsInfiniteDuration(d)) {\n    ts.tv_sec = static_cast<decltype(ts.tv_sec)>(time_internal::GetRepHi(d));\n    if (ts.tv_sec == time_internal::GetRepHi(d)) {  // no time_t narrowing\n      ts.tv_nsec = time_internal::GetRepLo(d) / 4;  // floor\n      return ts;\n    }\n  }\n  if (d >= absl::ZeroDuration()) {\n    ts.tv_sec = std::numeric_limits<time_t>::max();\n    ts.tv_nsec = 1000 * 1000 * 1000 - 1;\n  } else {\n    ts.tv_sec = std::numeric_limits<time_t>::min();\n    ts.tv_nsec = 0;\n  }\n  return ts;\n}\n\ntimeval ToTimeval(Time t) {\n  timeval tv;\n  timespec ts = absl::ToTimespec(t);\n  tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);\n  if (tv.tv_sec != ts.tv_sec) {  // narrowing\n    if (ts.tv_sec < 0) {\n      tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();\n      tv.tv_usec = 0;\n    } else {\n      tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();\n      tv.tv_usec = 1000 * 1000 - 1;\n    }\n    return tv;\n  }\n  tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);  // suseconds_t\n  return tv;\n}\n\nTime FromChrono(const std::chrono::system_clock::time_point& tp) {\n  return time_internal::FromUnixDuration(time_internal::FromChrono(\n      tp - std::chrono::system_clock::from_time_t(0)));\n}\n\nstd::chrono::system_clock::time_point ToChronoTime(absl::Time t) {\n  using D = std::chrono::system_clock::duration;\n  auto d = time_internal::ToUnixDuration(t);\n  if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1}));\n  return std::chrono::system_clock::from_time_t(0) +\n         time_internal::ToChronoDuration<D>(d);\n}\n\n//\n// TimeZone\n//\n\nabsl::TimeZone::CivilInfo TimeZone::At(Time t) const {\n  if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();\n  if (t == absl::InfinitePast()) return InfinitePastCivilInfo();\n\n  const auto ud = time_internal::ToUnixDuration(t);\n  const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));\n  const auto al = cz_.lookup(tp);\n\n  TimeZone::CivilInfo ci;\n  ci.cs = CivilSecond(al.cs);\n  ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));\n  ci.offset = al.offset;\n  ci.is_dst = al.is_dst;\n  ci.zone_abbr = al.abbr;\n  return ci;\n}\n\nabsl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {\n  const cctz::civil_second cs(ct);\n  const auto cl = cz_.lookup(cs);\n\n  TimeZone::TimeInfo ti;\n  switch (cl.kind) {\n    case cctz::time_zone::civil_lookup::UNIQUE:\n      ti.kind = TimeZone::TimeInfo::UNIQUE;\n      break;\n    case cctz::time_zone::civil_lookup::SKIPPED:\n      ti.kind = TimeZone::TimeInfo::SKIPPED;\n      break;\n    case cctz::time_zone::civil_lookup::REPEATED:\n      ti.kind = TimeZone::TimeInfo::REPEATED;\n      break;\n  }\n  ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);\n  ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);\n  ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);\n  return ti;\n}\n\nbool TimeZone::NextTransition(Time t, CivilTransition* trans) const {\n  return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);\n}\n\nbool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {\n  return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);\n}\n\n//\n// Conversions involving time zones.\n//\nABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\nabsl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,\n                                     int min, int sec, TimeZone tz) {\n  // Avoids years that are too extreme for CivilSecond to normalize.\n  if (year > 300000000000) return InfiniteFutureTimeConversion();\n  if (year < -300000000000) return InfinitePastTimeConversion();\n\n  const CivilSecond cs(year, mon, day, hour, min, sec);\n  const auto ti = tz.At(cs);\n\n  TimeConversion tc;\n  tc.pre = ti.pre;\n  tc.trans = ti.trans;\n  tc.post = ti.post;\n  switch (ti.kind) {\n    case TimeZone::TimeInfo::UNIQUE:\n      tc.kind = TimeConversion::UNIQUE;\n      break;\n    case TimeZone::TimeInfo::SKIPPED:\n      tc.kind = TimeConversion::SKIPPED;\n      break;\n    case TimeZone::TimeInfo::REPEATED:\n      tc.kind = TimeConversion::REPEATED;\n      break;\n  }\n  tc.normalized = false;\n  if (year != cs.year() || mon != cs.month() || day != cs.day() ||\n      hour != cs.hour() || min != cs.minute() || sec != cs.second()) {\n    tc.normalized = true;\n  }\n  return tc;\n}\nABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n\nabsl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {\n  civil_year_t tm_year = tm.tm_year;\n  // Avoids years that are too extreme for CivilSecond to normalize.\n  if (tm_year > 300000000000ll) return InfiniteFuture();\n  if (tm_year < -300000000000ll) return InfinitePast();\n  int tm_mon = tm.tm_mon;\n  if (tm_mon == std::numeric_limits<int>::max()) {\n    tm_mon -= 12;\n    tm_year += 1;\n  }\n  const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,\n                                    tm.tm_hour, tm.tm_min, tm.tm_sec));\n  return tm.tm_isdst == 0 ? ti.post : ti.pre;\n}\n\nstruct tm ToTM(absl::Time t, absl::TimeZone tz) {\n  struct tm tm = {};\n\n  const auto ci = tz.At(t);\n  const auto& cs = ci.cs;\n  tm.tm_sec = cs.second();\n  tm.tm_min = cs.minute();\n  tm.tm_hour = cs.hour();\n  tm.tm_mday = cs.day();\n  tm.tm_mon = cs.month() - 1;\n\n  // Saturates tm.tm_year in cases of over/underflow, accounting for the fact\n  // that tm.tm_year is years since 1900.\n  if (cs.year() < std::numeric_limits<int>::min() + 1900) {\n    tm.tm_year = std::numeric_limits<int>::min();\n  } else if (cs.year() > std::numeric_limits<int>::max()) {\n    tm.tm_year = std::numeric_limits<int>::max() - 1900;\n  } else {\n    tm.tm_year = static_cast<int>(cs.year() - 1900);\n  }\n\n  switch (GetWeekday(cs)) {\n    case Weekday::sunday:\n      tm.tm_wday = 0;\n      break;\n    case Weekday::monday:\n      tm.tm_wday = 1;\n      break;\n    case Weekday::tuesday:\n      tm.tm_wday = 2;\n      break;\n    case Weekday::wednesday:\n      tm.tm_wday = 3;\n      break;\n    case Weekday::thursday:\n      tm.tm_wday = 4;\n      break;\n    case Weekday::friday:\n      tm.tm_wday = 5;\n      break;\n    case Weekday::saturday:\n      tm.tm_wday = 6;\n      break;\n  }\n  tm.tm_yday = GetYearDay(cs) - 1;\n  tm.tm_isdst = ci.is_dst ? 1 : 0;\n\n  return tm;\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/time/time.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: time.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines abstractions for computing with absolute points\n// in time, durations of time, and formatting and parsing time within a given\n// time zone. The following abstractions are defined:\n//\n//  * `absl::Time` defines an absolute, specific instance in time\n//  * `absl::Duration` defines a signed, fixed-length span of time\n//  * `absl::TimeZone` defines geopolitical time zone regions (as collected\n//     within the IANA Time Zone database (https://www.iana.org/time-zones)).\n//\n// Note: Absolute times are distinct from civil times, which refer to the\n// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping\n// between absolute and civil times can be specified by use of time zones\n// (`absl::TimeZone` within this API). That is:\n//\n//   Civil Time = F(Absolute Time, Time Zone)\n//   Absolute Time = G(Civil Time, Time Zone)\n//\n// See civil_time.h for abstractions related to constructing and manipulating\n// civil time.\n//\n// Example:\n//\n//   absl::TimeZone nyc;\n//   // LoadTimeZone() may fail so it's always better to check for success.\n//   if (!absl::LoadTimeZone(\"America/New_York\", &nyc)) {\n//      // handle error case\n//   }\n//\n//   // My flight leaves NYC on Jan 2, 2017 at 03:04:05\n//   absl::CivilSecond cs(2017, 1, 2, 3, 4, 5);\n//   absl::Time takeoff = absl::FromCivil(cs, nyc);\n//\n//   absl::Duration flight_duration = absl::Hours(21) + absl::Minutes(35);\n//   absl::Time landing = takeoff + flight_duration;\n//\n//   absl::TimeZone syd;\n//   if (!absl::LoadTimeZone(\"Australia/Sydney\", &syd)) {\n//      // handle error case\n//   }\n//   std::string s = absl::FormatTime(\n//       \"My flight will land in Sydney on %Y-%m-%d at %H:%M:%S\",\n//       landing, syd);\n\n#ifndef ABSL_TIME_TIME_H_\n#define ABSL_TIME_TIME_H_\n\n#if !defined(_MSC_VER)\n#include <sys/time.h>\n#else\n// We don't include `winsock2.h` because it drags in `windows.h` and friends,\n// and they define conflicting macros like OPAQUE, ERROR, and more. This has the\n// potential to break Abseil users.\n//\n// Instead we only forward declare `timeval` and require Windows users include\n// `winsock2.h` themselves. This is both inconsistent and troublesome, but so is\n// including 'windows.h' so we are picking the lesser of two evils here.\nstruct timeval;\n#endif\n\n#include \"absl/base/config.h\"\n\n// For feature testing and determining which headers can be included.\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <version>\n#endif\n\n#include <chrono>  // NOLINT(build/c++11)\n#include <cmath>\n#ifdef __cpp_lib_three_way_comparison\n#include <compare>\n#endif  // __cpp_lib_three_way_comparison\n#include <cstdint>\n#include <ctime>\n#include <limits>\n#include <ostream>\n#include <ratio>  // NOLINT(build/c++11)\n#include <string>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/time/civil_time.h\"\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\n#if defined(__cpp_impl_three_way_comparison) && \\\n    defined(__cpp_lib_three_way_comparison)\n#define ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON 1\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\nclass Duration;  // Defined below\nclass Time;      // Defined below\nclass TimeZone;  // Defined below\n\nnamespace time_internal {\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,\n                                                              uint32_t lo);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,\n                                                              int64_t lo);\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration MakePosDoubleDuration(double n);\nconstexpr int64_t kTicksPerNanosecond = 4;\nconstexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond;\ntemplate <std::intmax_t N>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,\n                                                           std::ratio<1, N>);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,\n                                                           std::ratio<60>);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,\n                                                           std::ratio<3600>);\ntemplate <typename T>\nusing EnableIfIntegral = typename std::enable_if<\n    std::is_integral<T>::value || std::is_enum<T>::value, int>::type;\ntemplate <typename T>\nusing EnableIfFloat =\n    typename std::enable_if<std::is_floating_point<T>::value, int>::type;\n}  // namespace time_internal\n\n// Duration\n//\n// The `absl::Duration` class represents a signed, fixed-length amount of time.\n// A `Duration` is generated using a unit-specific factory function, or is\n// the result of subtracting one `absl::Time` from another. Durations behave\n// like unit-safe integers and they support all the natural integer-like\n// arithmetic operations. Arithmetic overflows and saturates at +/- infinity.\n// `Duration` is trivially destructible and should be passed by value rather\n// than const reference.\n//\n// Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`,\n// `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for\n// creation of constexpr `Duration` values\n//\n// Examples:\n//\n//   constexpr absl::Duration ten_ns = absl::Nanoseconds(10);\n//   constexpr absl::Duration min = absl::Minutes(1);\n//   constexpr absl::Duration hour = absl::Hours(1);\n//   absl::Duration dur = 60 * min;  // dur == hour\n//   absl::Duration half_sec = absl::Milliseconds(500);\n//   absl::Duration quarter_sec = 0.25 * absl::Seconds(1);\n//\n// `Duration` values can be easily converted to an integral number of units\n// using the division operator.\n//\n// Example:\n//\n//   constexpr absl::Duration dur = absl::Milliseconds(1500);\n//   int64_t ns = dur / absl::Nanoseconds(1);   // ns == 1500000000\n//   int64_t ms = dur / absl::Milliseconds(1);  // ms == 1500\n//   int64_t sec = dur / absl::Seconds(1);    // sec == 1 (subseconds truncated)\n//   int64_t min = dur / absl::Minutes(1);    // min == 0\n//\n// See the `IDivDuration()` and `FDivDuration()` functions below for details on\n// how to access the fractional parts of the quotient.\n//\n// Alternatively, conversions can be performed using helpers such as\n// `ToInt64Microseconds()` and `ToDoubleSeconds()`.\nclass Duration {\n public:\n  // Value semantics.\n  constexpr Duration() : rep_hi_(0), rep_lo_(0) {}  // zero-length duration\n\n  // Copyable.\n#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1930\n  // Explicitly defining the constexpr copy constructor avoids an MSVC bug.\n  constexpr Duration(const Duration& d)\n      : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {}\n#else\n  constexpr Duration(const Duration& d) = default;\n#endif\n  Duration& operator=(const Duration& d) = default;\n\n  // Compound assignment operators.\n  Duration& operator+=(Duration d);\n  Duration& operator-=(Duration d);\n  Duration& operator*=(int64_t r);\n  Duration& operator*=(double r);\n  Duration& operator/=(int64_t r);\n  Duration& operator/=(double r);\n  Duration& operator%=(Duration rhs);\n\n  // Overloads that forward to either the int64_t or double overloads above.\n  // Integer operands must be representable as int64_t. Integer division is\n  // truncating, so values less than the resolution will be returned as zero.\n  // Floating-point multiplication and division is rounding (halfway cases\n  // rounding away from zero), so values less than the resolution may be\n  // returned as either the resolution or zero.  In particular, `d / 2.0`\n  // can produce `d` when it is the resolution and \"even\".\n  template <typename T, time_internal::EnableIfIntegral<T> = 0>\n  Duration& operator*=(T r) {\n    int64_t x = r;\n    return *this *= x;\n  }\n\n  template <typename T, time_internal::EnableIfIntegral<T> = 0>\n  Duration& operator/=(T r) {\n    int64_t x = r;\n    return *this /= x;\n  }\n\n  template <typename T, time_internal::EnableIfFloat<T> = 0>\n  Duration& operator*=(T r) {\n    double x = r;\n    return *this *= x;\n  }\n\n  template <typename T, time_internal::EnableIfFloat<T> = 0>\n  Duration& operator/=(T r) {\n    double x = r;\n    return *this /= x;\n  }\n\n  template <typename H>\n  friend H AbslHashValue(H h, Duration d) {\n    return H::combine(std::move(h), d.rep_hi_.Get(), d.rep_lo_);\n  }\n\n private:\n  friend constexpr int64_t time_internal::GetRepHi(Duration d);\n  friend constexpr uint32_t time_internal::GetRepLo(Duration d);\n  friend constexpr Duration time_internal::MakeDuration(int64_t hi,\n                                                        uint32_t lo);\n  constexpr Duration(int64_t hi, uint32_t lo) : rep_hi_(hi), rep_lo_(lo) {}\n\n  // We store `rep_hi_` 4-byte rather than 8-byte aligned to avoid 4 bytes of\n  // tail padding.\n  class HiRep {\n   public:\n    // Default constructor default-initializes `hi_`, which has the same\n    // semantics as default-initializing an `int64_t` (undetermined value).\n    HiRep() = default;\n\n    HiRep(const HiRep&) = default;\n    HiRep& operator=(const HiRep&) = default;\n\n    explicit constexpr HiRep(const int64_t value)\n        :  // C++17 forbids default-initialization in constexpr contexts. We can\n           // remove this in C++20.\n#if defined(ABSL_IS_BIG_ENDIAN) && ABSL_IS_BIG_ENDIAN\n          hi_(0),\n          lo_(0)\n#else\n          lo_(0),\n          hi_(0)\n#endif\n    {\n      *this = value;\n    }\n\n    constexpr int64_t Get() const {\n      const uint64_t unsigned_value =\n          (static_cast<uint64_t>(hi_) << 32) | static_cast<uint64_t>(lo_);\n      // `static_cast<int64_t>(unsigned_value)` is implementation-defined\n      // before c++20. On all supported platforms the behaviour is that mandated\n      // by c++20, i.e. \"If the destination type is signed, [...] the result is\n      // the unique value of the destination type equal to the source value\n      // modulo 2^n, where n is the number of bits used to represent the\n      // destination type.\"\n      static_assert(\n          (static_cast<int64_t>((std::numeric_limits<uint64_t>::max)()) ==\n           int64_t{-1}) &&\n              (static_cast<int64_t>(static_cast<uint64_t>(\n                                        (std::numeric_limits<int64_t>::max)()) +\n                                    1) ==\n               (std::numeric_limits<int64_t>::min)()),\n          \"static_cast<int64_t>(uint64_t) does not have c++20 semantics\");\n      return static_cast<int64_t>(unsigned_value);\n    }\n\n    constexpr HiRep& operator=(const int64_t value) {\n      // \"If the destination type is unsigned, the resulting value is the\n      // smallest unsigned value equal to the source value modulo 2^n\n      // where `n` is the number of bits used to represent the destination\n      // type\".\n      const auto unsigned_value = static_cast<uint64_t>(value);\n      hi_ = static_cast<uint32_t>(unsigned_value >> 32);\n      lo_ = static_cast<uint32_t>(unsigned_value);\n      return *this;\n    }\n\n   private:\n    // Notes:\n    //  - Ideally we would use a `char[]` and `std::bitcast`, but the latter\n    //    does not exist (and is not constexpr in `absl`) before c++20.\n    //  - Order is optimized depending on endianness so that the compiler can\n    //    turn `Get()` (resp. `operator=()`) into a single 8-byte load (resp.\n    //    store).\n#if defined(ABSL_IS_BIG_ENDIAN) && ABSL_IS_BIG_ENDIAN\n    uint32_t hi_;\n    uint32_t lo_;\n#else\n    uint32_t lo_;\n    uint32_t hi_;\n#endif\n  };\n  HiRep rep_hi_;\n  uint32_t rep_lo_;\n};\n\n// Relational Operators\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(\n    Duration lhs, Duration rhs);\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,\n                                                       Duration rhs);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs,\n                                                       Duration rhs) {\n  return rhs < lhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>=(Duration lhs,\n                                                        Duration rhs) {\n  return !(lhs < rhs);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<=(Duration lhs,\n                                                        Duration rhs) {\n  return !(rhs < lhs);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,\n                                                        Duration rhs);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator!=(Duration lhs,\n                                                        Duration rhs) {\n  return !(lhs == rhs);\n}\n\n// Additive Operators\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration operator-(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator+(Duration lhs,\n                                                        Duration rhs) {\n  return lhs += rhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Duration lhs,\n                                                        Duration rhs) {\n  return lhs -= rhs;\n}\n\n// IDivDuration()\n//\n// Divides a numerator `Duration` by a denominator `Duration`, returning the\n// quotient and remainder. The remainder always has the same sign as the\n// numerator. The returned quotient and remainder respect the identity:\n//\n//   numerator = denominator * quotient + remainder\n//\n// Returned quotients are capped to the range of `int64_t`, with the difference\n// spilling into the remainder to uphold the above identity. This means that the\n// remainder returned could differ from the remainder returned by\n// `Duration::operator%` for huge quotients.\n//\n// See also the notes on `InfiniteDuration()` below regarding the behavior of\n// division involving zero and infinite durations.\n//\n// Example:\n//\n//   constexpr absl::Duration a =\n//       absl::Seconds(std::numeric_limits<int64_t>::max());  // big\n//   constexpr absl::Duration b = absl::Nanoseconds(1);       // small\n//\n//   absl::Duration rem = a % b;\n//   // rem == absl::ZeroDuration()\n//\n//   // Here, q would overflow int64_t, so rem accounts for the difference.\n//   int64_t q = absl::IDivDuration(a, b, &rem);\n//   // q == std::numeric_limits<int64_t>::max(), rem == a - b * q\nint64_t IDivDuration(Duration num, Duration den, Duration* rem);\n\n// FDivDuration()\n//\n// Divides a `Duration` numerator into a fractional number of units of a\n// `Duration` denominator.\n//\n// See also the notes on `InfiniteDuration()` below regarding the behavior of\n// division involving zero and infinite durations.\n//\n// Example:\n//\n//   double d = absl::FDivDuration(absl::Milliseconds(1500), absl::Seconds(1));\n//   // d == 1.5\nABSL_ATTRIBUTE_CONST_FUNCTION double FDivDuration(Duration num, Duration den);\n\n// Multiplicative Operators\n// Integer operands must be representable as int64_t.\ntemplate <typename T>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(Duration lhs, T rhs) {\n  return lhs *= rhs;\n}\ntemplate <typename T>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(T lhs, Duration rhs) {\n  return rhs *= lhs;\n}\ntemplate <typename T>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration operator/(Duration lhs, T rhs) {\n  return lhs /= rhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t operator/(Duration lhs,\n                                                       Duration rhs) {\n  return IDivDuration(lhs, rhs,\n                      &lhs);  // trunc towards zero\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator%(Duration lhs,\n                                                        Duration rhs) {\n  return lhs %= rhs;\n}\n\n// ZeroDuration()\n//\n// Returns a zero-length duration. This function behaves just like the default\n// constructor, but the name helps make the semantics clear at call sites.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ZeroDuration() {\n  return Duration();\n}\n\n// AbsDuration()\n//\n// Returns the absolute value of a duration.\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration AbsDuration(Duration d) {\n  return (d < ZeroDuration()) ? -d : d;\n}\n\n// Trunc()\n//\n// Truncates a duration (toward zero) to a multiple of a non-zero unit.\n//\n// Example:\n//\n//   absl::Duration d = absl::Nanoseconds(123456789);\n//   absl::Duration a = absl::Trunc(d, absl::Microseconds(1));  // 123456us\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Trunc(Duration d, Duration unit);\n\n// Floor()\n//\n// Floors a duration using the passed duration unit to its largest value not\n// greater than the duration.\n//\n// Example:\n//\n//   absl::Duration d = absl::Nanoseconds(123456789);\n//   absl::Duration b = absl::Floor(d, absl::Microseconds(1));  // 123456us\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Floor(Duration d, Duration unit);\n\n// Ceil()\n//\n// Returns the ceiling of a duration using the passed duration unit to its\n// smallest value not less than the duration.\n//\n// Example:\n//\n//   absl::Duration d = absl::Nanoseconds(123456789);\n//   absl::Duration c = absl::Ceil(d, absl::Microseconds(1));   // 123457us\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Ceil(Duration d, Duration unit);\n\n// InfiniteDuration()\n//\n// Returns an infinite `Duration`.  To get a `Duration` representing negative\n// infinity, use `-InfiniteDuration()`.\n//\n// Duration arithmetic overflows to +/- infinity and saturates. In general,\n// arithmetic with `Duration` infinities is similar to IEEE 754 infinities\n// except where IEEE 754 NaN would be involved, in which case +/-\n// `InfiniteDuration()` is used in place of a \"nan\" Duration.\n//\n// Examples:\n//\n//   constexpr absl::Duration inf = absl::InfiniteDuration();\n//   const absl::Duration d = ... any finite duration ...\n//\n//   inf == inf + inf\n//   inf == inf + d\n//   inf == inf - inf\n//   -inf == d - inf\n//\n//   inf == d * 1e100\n//   inf == inf / 2\n//   0 == d / inf\n//   INT64_MAX == inf / d\n//\n//   d < inf\n//   -inf < d\n//\n//   // Division by zero returns infinity, or INT64_MIN/MAX where appropriate.\n//   inf == d / 0\n//   INT64_MAX == d / absl::ZeroDuration()\n//\n// The examples involving the `/` operator above also apply to `IDivDuration()`\n// and `FDivDuration()`.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration InfiniteDuration();\n\n// Nanoseconds()\n// Microseconds()\n// Milliseconds()\n// Seconds()\n// Minutes()\n// Hours()\n//\n// Factory functions for constructing `Duration` values from an integral number\n// of the unit indicated by the factory function's name. The number must be\n// representable as int64_t.\n//\n// NOTE: no \"Days()\" factory function exists because \"a day\" is ambiguous.\n// Civil days are not always 24 hours long, and a 24-hour duration often does\n// not correspond with a civil day. If a 24-hour duration is needed, use\n// `absl::Hours(24)`. If you actually want a civil day, use absl::CivilDay\n// from civil_time.h.\n//\n// Example:\n//\n//   absl::Duration a = absl::Seconds(60);\n//   absl::Duration b = absl::Minutes(1);  // b == a\ntemplate <typename T, time_internal::EnableIfIntegral<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Nanoseconds(T n) {\n  return time_internal::FromInt64(n, std::nano{});\n}\ntemplate <typename T, time_internal::EnableIfIntegral<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Microseconds(T n) {\n  return time_internal::FromInt64(n, std::micro{});\n}\ntemplate <typename T, time_internal::EnableIfIntegral<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Milliseconds(T n) {\n  return time_internal::FromInt64(n, std::milli{});\n}\ntemplate <typename T, time_internal::EnableIfIntegral<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Seconds(T n) {\n  return time_internal::FromInt64(n, std::ratio<1>{});\n}\ntemplate <typename T, time_internal::EnableIfIntegral<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Minutes(T n) {\n  return time_internal::FromInt64(n, std::ratio<60>{});\n}\ntemplate <typename T, time_internal::EnableIfIntegral<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Hours(T n) {\n  return time_internal::FromInt64(n, std::ratio<3600>{});\n}\n\n// Factory overloads for constructing `Duration` values from a floating-point\n// number of the unit indicated by the factory function's name. These functions\n// exist for convenience, but they are not as efficient as the integral\n// factories, which should be preferred.\n//\n// Example:\n//\n//   auto a = absl::Seconds(1.5);        // OK\n//   auto b = absl::Milliseconds(1500);  // BETTER\ntemplate <typename T, time_internal::EnableIfFloat<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Nanoseconds(T n) {\n  return n * Nanoseconds(1);\n}\ntemplate <typename T, time_internal::EnableIfFloat<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Microseconds(T n) {\n  return n * Microseconds(1);\n}\ntemplate <typename T, time_internal::EnableIfFloat<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Milliseconds(T n) {\n  return n * Milliseconds(1);\n}\ntemplate <typename T, time_internal::EnableIfFloat<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Seconds(T n) {\n  if (n >= 0) {  // Note: `NaN >= 0` is false.\n    if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) {\n      return InfiniteDuration();\n    }\n    return time_internal::MakePosDoubleDuration(n);\n  } else {\n    if (std::isnan(n)) return -InfiniteDuration();\n    if (n <= static_cast<T>((std::numeric_limits<int64_t>::min)())) {\n      return -InfiniteDuration();\n    }\n    return -time_internal::MakePosDoubleDuration(-n);\n  }\n}\ntemplate <typename T, time_internal::EnableIfFloat<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Minutes(T n) {\n  return n * Minutes(1);\n}\ntemplate <typename T, time_internal::EnableIfFloat<T> = 0>\nABSL_ATTRIBUTE_CONST_FUNCTION Duration Hours(T n) {\n  return n * Hours(1);\n}\n\n// ToInt64Nanoseconds()\n// ToInt64Microseconds()\n// ToInt64Milliseconds()\n// ToInt64Seconds()\n// ToInt64Minutes()\n// ToInt64Hours()\n//\n// Helper functions that convert a Duration to an integral count of the\n// indicated unit. These return the same results as the `IDivDuration()`\n// function, though they usually do so more efficiently; see the\n// documentation of `IDivDuration()` for details about overflow, etc.\n//\n// Example:\n//\n//   absl::Duration d = absl::Milliseconds(1500);\n//   int64_t isec = absl::ToInt64Seconds(d);  // isec == 1\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Nanoseconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Microseconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Milliseconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Seconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Minutes(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Hours(Duration d);\n\n// ToDoubleNanoseconds()\n// ToDoubleMicroseconds()\n// ToDoubleMilliseconds()\n// ToDoubleSeconds()\n// ToDoubleMinutes()\n// ToDoubleHours()\n//\n// Helper functions that convert a Duration to a floating point count of the\n// indicated unit. These functions are shorthand for the `FDivDuration()`\n// function above; see its documentation for details about overflow, etc.\n//\n// Example:\n//\n//   absl::Duration d = absl::Milliseconds(1500);\n//   double dsec = absl::ToDoubleSeconds(d);  // dsec == 1.5\nABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleNanoseconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMicroseconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMilliseconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleSeconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMinutes(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleHours(Duration d);\n\n// FromChrono()\n//\n// Converts any of the pre-defined std::chrono durations to an absl::Duration.\n//\n// Example:\n//\n//   std::chrono::milliseconds ms(123);\n//   absl::Duration d = absl::FromChrono(ms);\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::nanoseconds& d);\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::microseconds& d);\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::milliseconds& d);\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::seconds& d);\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::minutes& d);\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::hours& d);\n\n// ToChronoNanoseconds()\n// ToChronoMicroseconds()\n// ToChronoMilliseconds()\n// ToChronoSeconds()\n// ToChronoMinutes()\n// ToChronoHours()\n//\n// Converts an absl::Duration to any of the pre-defined std::chrono durations.\n// If overflow would occur, the returned value will saturate at the min/max\n// chrono duration value instead.\n//\n// Example:\n//\n//   absl::Duration d = absl::Microseconds(123);\n//   auto x = absl::ToChronoMicroseconds(d);\n//   auto y = absl::ToChronoNanoseconds(d);  // x == y\n//   auto z = absl::ToChronoSeconds(absl::InfiniteDuration());\n//   // z == std::chrono::seconds::max()\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::nanoseconds ToChronoNanoseconds(\n    Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::microseconds ToChronoMicroseconds(\n    Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::milliseconds ToChronoMilliseconds(\n    Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::seconds ToChronoSeconds(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::minutes ToChronoMinutes(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::hours ToChronoHours(Duration d);\n\n// FormatDuration()\n//\n// Returns a string representing the duration in the form \"72h3m0.5s\".\n// Returns \"inf\" or \"-inf\" for +/- `InfiniteDuration()`.\nABSL_ATTRIBUTE_CONST_FUNCTION std::string FormatDuration(Duration d);\n\n// Output stream operator.\ninline std::ostream& operator<<(std::ostream& os, Duration d) {\n  return os << FormatDuration(d);\n}\n\n// Support for StrFormat(), StrCat() etc.\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, Duration d) {\n  sink.Append(FormatDuration(d));\n}\n\n// ParseDuration()\n//\n// Parses a duration string consisting of a possibly signed sequence of\n// decimal numbers, each with an optional fractional part and a unit\n// suffix.  The valid suffixes are \"ns\", \"us\" \"ms\", \"s\", \"m\", and \"h\".\n// Simple examples include \"300ms\", \"-1.5h\", and \"2h45m\".  Parses \"0\" as\n// `ZeroDuration()`. Parses \"inf\" and \"-inf\" as +/- `InfiniteDuration()`.\nbool ParseDuration(absl::string_view dur_string, Duration* d);\n\n// AbslParseFlag()\n//\n// Parses a command-line flag string representation `text` into a Duration\n// value. Duration flags must be specified in a format that is valid input for\n// `absl::ParseDuration()`.\nbool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error);\n\n// AbslUnparseFlag()\n//\n// Unparses a Duration value into a command-line string representation using\n// the format specified by `absl::ParseDuration()`.\nstd::string AbslUnparseFlag(Duration d);\n\nABSL_DEPRECATED(\"Use AbslParseFlag() instead.\")\nbool ParseFlag(const std::string& text, Duration* dst, std::string* error);\nABSL_DEPRECATED(\"Use AbslUnparseFlag() instead.\")\nstd::string UnparseFlag(Duration d);\n\n// Time\n//\n// An `absl::Time` represents a specific instant in time. Arithmetic operators\n// are provided for naturally expressing time calculations. Instances are\n// created using `absl::Now()` and the `absl::From*()` factory functions that\n// accept the gamut of other time representations. Formatting and parsing\n// functions are provided for conversion to and from strings. `absl::Time` is\n// trivially destructible and should be passed by value rather than const\n// reference.\n//\n// `absl::Time` assumes there are 60 seconds in a minute, which means the\n// underlying time scales must be \"smeared\" to eliminate leap seconds.\n// See https://developers.google.com/time/smear.\n//\n// Even though `absl::Time` supports a wide range of timestamps, exercise\n// caution when using values in the distant past. `absl::Time` uses the\n// Proleptic Gregorian calendar, which extends the Gregorian calendar backward\n// to dates before its introduction in 1582.\n// See https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar\n// for more information. Use the ICU calendar classes to convert a date in\n// some other calendar (http://userguide.icu-project.org/datetime/calendar).\n//\n// Similarly, standardized time zones are a reasonably recent innovation, with\n// the Greenwich prime meridian being established in 1884. The TZ database\n// itself does not profess accurate offsets for timestamps prior to 1970. The\n// breakdown of future timestamps is subject to the whim of regional\n// governments.\n//\n// The `absl::Time` class represents an instant in time as a count of clock\n// ticks of some granularity (resolution) from some starting point (epoch).\n//\n// `absl::Time` uses a resolution that is high enough to avoid loss in\n// precision, and a range that is wide enough to avoid overflow, when\n// converting between tick counts in most Google time scales (i.e., resolution\n// of at least one nanosecond, and range +/-100 billion years).  Conversions\n// between the time scales are performed by truncating (towards negative\n// infinity) to the nearest representable point.\n//\n// Examples:\n//\n//   absl::Time t1 = ...;\n//   absl::Time t2 = t1 + absl::Minutes(2);\n//   absl::Duration d = t2 - t1;  // == absl::Minutes(2)\n//\nclass Time {\n public:\n  // Value semantics.\n\n  // Returns the Unix epoch.  However, those reading your code may not know\n  // or expect the Unix epoch as the default value, so make your code more\n  // readable by explicitly initializing all instances before use.\n  //\n  // Example:\n  //   absl::Time t = absl::UnixEpoch();\n  //   absl::Time t = absl::Now();\n  //   absl::Time t = absl::TimeFromTimeval(tv);\n  //   absl::Time t = absl::InfinitePast();\n  constexpr Time() = default;\n\n  // Copyable.\n  constexpr Time(const Time& t) = default;\n  Time& operator=(const Time& t) = default;\n\n  // Assignment operators.\n  Time& operator+=(Duration d) {\n    rep_ += d;\n    return *this;\n  }\n  Time& operator-=(Duration d) {\n    rep_ -= d;\n    return *this;\n  }\n\n  // Time::Breakdown\n  //\n  // The calendar and wall-clock (aka \"civil time\") components of an\n  // `absl::Time` in a certain `absl::TimeZone`. This struct is not\n  // intended to represent an instant in time. So, rather than passing\n  // a `Time::Breakdown` to a function, pass an `absl::Time` and an\n  // `absl::TimeZone`.\n  //\n  // Deprecated. Use `absl::TimeZone::CivilInfo`.\n  struct ABSL_DEPRECATED(\"Use `absl::TimeZone::CivilInfo`.\") Breakdown {\n    int64_t year;        // year (e.g., 2013)\n    int month;           // month of year [1:12]\n    int day;             // day of month [1:31]\n    int hour;            // hour of day [0:23]\n    int minute;          // minute of hour [0:59]\n    int second;          // second of minute [0:59]\n    Duration subsecond;  // [Seconds(0):Seconds(1)) if finite\n    int weekday;         // 1==Mon, ..., 7=Sun\n    int yearday;         // day of year [1:366]\n\n    // Note: The following fields exist for backward compatibility\n    // with older APIs.  Accessing these fields directly is a sign of\n    // imprudent logic in the calling code.  Modern time-related code\n    // should only access this data indirectly by way of FormatTime().\n    // These fields are undefined for InfiniteFuture() and InfinitePast().\n    int offset;             // seconds east of UTC\n    bool is_dst;            // is offset non-standard?\n    const char* zone_abbr;  // time-zone abbreviation (e.g., \"PST\")\n  };\n\n  // Time::In()\n  //\n  // Returns the breakdown of this instant in the given TimeZone.\n  //\n  // Deprecated. Use `absl::TimeZone::At(Time)`.\n  ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\n  ABSL_DEPRECATED(\"Use `absl::TimeZone::At(Time)`.\")\n  Breakdown In(TimeZone tz) const;\n  ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n\n  template <typename H>\n  friend H AbslHashValue(H h, Time t) {\n    return H::combine(std::move(h), t.rep_);\n  }\n\n private:\n  friend constexpr Time time_internal::FromUnixDuration(Duration d);\n  friend constexpr Duration time_internal::ToUnixDuration(Time t);\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n  friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs);\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  friend constexpr bool operator<(Time lhs, Time rhs);\n  friend constexpr bool operator==(Time lhs, Time rhs);\n  friend Duration operator-(Time lhs, Time rhs);\n  friend constexpr Time UniversalEpoch();\n  friend constexpr Time InfiniteFuture();\n  friend constexpr Time InfinitePast();\n  constexpr explicit Time(Duration rep) : rep_(rep) {}\n  Duration rep_;\n};\n\n// Relational Operators\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(\n    Time lhs, Time rhs) {\n  return lhs.rep_ <=> rhs.rep_;\n}\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {\n  return lhs.rep_ < rhs.rep_;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Time lhs, Time rhs) {\n  return rhs < lhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>=(Time lhs, Time rhs) {\n  return !(lhs < rhs);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<=(Time lhs, Time rhs) {\n  return !(rhs < lhs);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Time lhs, Time rhs) {\n  return lhs.rep_ == rhs.rep_;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator!=(Time lhs, Time rhs) {\n  return !(lhs == rhs);\n}\n\n// Additive Operators\nABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator+(Time lhs, Duration rhs) {\n  return lhs += rhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator+(Duration lhs, Time rhs) {\n  return rhs += lhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator-(Time lhs, Duration rhs) {\n  return lhs -= rhs;\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Time lhs, Time rhs) {\n  return lhs.rep_ - rhs.rep_;\n}\n\n// UnixEpoch()\n//\n// Returns the `absl::Time` representing \"1970-01-01 00:00:00.0 +0000\".\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time UnixEpoch() { return Time(); }\n\n// UniversalEpoch()\n//\n// Returns the `absl::Time` representing \"0001-01-01 00:00:00.0 +0000\", the\n// epoch of the ICU Universal Time Scale.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time UniversalEpoch() {\n  // 719162 is the number of days from 0001-01-01 to 1970-01-01,\n  // assuming the Gregorian calendar.\n  return Time(\n      time_internal::MakeDuration(-24 * 719162 * int64_t{3600}, uint32_t{0}));\n}\n\n// InfiniteFuture()\n//\n// Returns an `absl::Time` that is infinitely far in the future.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time InfiniteFuture() {\n  return Time(time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),\n                                          ~uint32_t{0}));\n}\n\n// InfinitePast()\n//\n// Returns an `absl::Time` that is infinitely far in the past.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time InfinitePast() {\n  return Time(time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(),\n                                          ~uint32_t{0}));\n}\n\n// FromUnixNanos()\n// FromUnixMicros()\n// FromUnixMillis()\n// FromUnixSeconds()\n// FromTimeT()\n// FromUDate()\n// FromUniversal()\n//\n// Creates an `absl::Time` from a variety of other representations.  See\n// https://unicode-org.github.io/icu/userguide/datetime/universaltimescale.html\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixNanos(int64_t ns);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMicros(int64_t us);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMillis(int64_t ms);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixSeconds(int64_t s);\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t);\nABSL_ATTRIBUTE_CONST_FUNCTION Time FromUDate(double udate);\nABSL_ATTRIBUTE_CONST_FUNCTION Time FromUniversal(int64_t universal);\n\n// ToUnixNanos()\n// ToUnixMicros()\n// ToUnixMillis()\n// ToUnixSeconds()\n// ToTimeT()\n// ToUDate()\n// ToUniversal()\n//\n// Converts an `absl::Time` to a variety of other representations.  See\n// https://unicode-org.github.io/icu/userguide/datetime/universaltimescale.html\n//\n// Note that these operations round down toward negative infinity where\n// necessary to adjust to the resolution of the result type.  Beware of\n// possible time_t over/underflow in ToTime{T,val,spec}() on 32-bit platforms.\nABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixNanos(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixMicros(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixMillis(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixSeconds(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION time_t ToTimeT(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION double ToUDate(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUniversal(Time t);\n\n// DurationFromTimespec()\n// DurationFromTimeval()\n// ToTimespec()\n// ToTimeval()\n// TimeFromTimespec()\n// TimeFromTimeval()\n// ToTimespec()\n// ToTimeval()\n//\n// Some APIs use a timespec or a timeval as a Duration (e.g., nanosleep(2)\n// and select(2)), while others use them as a Time (e.g. clock_gettime(2)\n// and gettimeofday(2)), so conversion functions are provided for both cases.\n// The \"to timespec/val\" direction is easily handled via overloading, but\n// for \"from timespec/val\" the desired type is part of the function name.\nABSL_ATTRIBUTE_CONST_FUNCTION Duration DurationFromTimespec(timespec ts);\nABSL_ATTRIBUTE_CONST_FUNCTION Duration DurationFromTimeval(timeval tv);\nABSL_ATTRIBUTE_CONST_FUNCTION timespec ToTimespec(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION timeval ToTimeval(Duration d);\nABSL_ATTRIBUTE_CONST_FUNCTION Time TimeFromTimespec(timespec ts);\nABSL_ATTRIBUTE_CONST_FUNCTION Time TimeFromTimeval(timeval tv);\nABSL_ATTRIBUTE_CONST_FUNCTION timespec ToTimespec(Time t);\nABSL_ATTRIBUTE_CONST_FUNCTION timeval ToTimeval(Time t);\n\n// FromChrono()\n//\n// Converts a std::chrono::system_clock::time_point to an absl::Time.\n//\n// Example:\n//\n//   auto tp = std::chrono::system_clock::from_time_t(123);\n//   absl::Time t = absl::FromChrono(tp);\n//   // t == absl::FromTimeT(123)\nABSL_ATTRIBUTE_PURE_FUNCTION Time\nFromChrono(const std::chrono::system_clock::time_point& tp);\n\n// ToChronoTime()\n//\n// Converts an absl::Time to a std::chrono::system_clock::time_point. If\n// overflow would occur, the returned value will saturate at the min/max time\n// point value instead.\n//\n// Example:\n//\n//   absl::Time t = absl::FromTimeT(123);\n//   auto tp = absl::ToChronoTime(t);\n//   // tp == std::chrono::system_clock::from_time_t(123);\nABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::system_clock::time_point\n    ToChronoTime(Time);\n\n// AbslParseFlag()\n//\n// Parses the command-line flag string representation `text` into a Time value.\n// Time flags must be specified in a format that matches absl::RFC3339_full.\n//\n// For example:\n//\n//   --start_time=2016-01-02T03:04:05.678+08:00\n//\n// Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required.\n//\n// Additionally, if you'd like to specify a time as a count of\n// seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag\n// and add that duration to absl::UnixEpoch() to get an absl::Time.\nbool AbslParseFlag(absl::string_view text, Time* t, std::string* error);\n\n// AbslUnparseFlag()\n//\n// Unparses a Time value into a command-line string representation using\n// the format specified by `absl::ParseTime()`.\nstd::string AbslUnparseFlag(Time t);\n\nABSL_DEPRECATED(\"Use AbslParseFlag() instead.\")\nbool ParseFlag(const std::string& text, Time* t, std::string* error);\nABSL_DEPRECATED(\"Use AbslUnparseFlag() instead.\")\nstd::string UnparseFlag(Time t);\n\n// TimeZone\n//\n// The `absl::TimeZone` is an opaque, small, value-type class representing a\n// geo-political region within which particular rules are used for converting\n// between absolute and civil times (see https://git.io/v59Ly). `absl::TimeZone`\n// values are named using the TZ identifiers from the IANA Time Zone Database,\n// such as \"America/Los_Angeles\" or \"Australia/Sydney\". `absl::TimeZone` values\n// are created from factory functions such as `absl::LoadTimeZone()`. Note:\n// strings like \"PST\" and \"EDT\" are not valid TZ identifiers. Prefer to pass by\n// value rather than const reference.\n//\n// For more on the fundamental concepts of time zones, absolute times, and civil\n// times, see https://github.com/google/cctz#fundamental-concepts\n//\n// Examples:\n//\n//   absl::TimeZone utc = absl::UTCTimeZone();\n//   absl::TimeZone pst = absl::FixedTimeZone(-8 * 60 * 60);\n//   absl::TimeZone loc = absl::LocalTimeZone();\n//   absl::TimeZone lax;\n//   if (!absl::LoadTimeZone(\"America/Los_Angeles\", &lax)) {\n//     // handle error case\n//   }\n//\n// See also:\n// - https://github.com/google/cctz\n// - https://www.iana.org/time-zones\n// - https://en.wikipedia.org/wiki/Zoneinfo\nclass TimeZone {\n public:\n  explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {}\n  TimeZone() = default;  // UTC, but prefer UTCTimeZone() to be explicit.\n\n  // Copyable.\n  TimeZone(const TimeZone&) = default;\n  TimeZone& operator=(const TimeZone&) = default;\n\n  explicit operator time_internal::cctz::time_zone() const { return cz_; }\n\n  std::string name() const { return cz_.name(); }\n\n  // TimeZone::CivilInfo\n  //\n  // Information about the civil time corresponding to an absolute time.\n  // This struct is not intended to represent an instant in time. So, rather\n  // than passing a `TimeZone::CivilInfo` to a function, pass an `absl::Time`\n  // and an `absl::TimeZone`.\n  struct CivilInfo {\n    CivilSecond cs;\n    Duration subsecond;\n\n    // Note: The following fields exist for backward compatibility\n    // with older APIs.  Accessing these fields directly is a sign of\n    // imprudent logic in the calling code.  Modern time-related code\n    // should only access this data indirectly by way of FormatTime().\n    // These fields are undefined for InfiniteFuture() and InfinitePast().\n    int offset;             // seconds east of UTC\n    bool is_dst;            // is offset non-standard?\n    const char* zone_abbr;  // time-zone abbreviation (e.g., \"PST\")\n  };\n\n  // TimeZone::At(Time)\n  //\n  // Returns the civil time for this TimeZone at a certain `absl::Time`.\n  // If the input time is infinite, the output civil second will be set to\n  // CivilSecond::max() or min(), and the subsecond will be infinite.\n  //\n  // Example:\n  //\n  //   const auto epoch = lax.At(absl::UnixEpoch());\n  //   // epoch.cs == 1969-12-31 16:00:00\n  //   // epoch.subsecond == absl::ZeroDuration()\n  //   // epoch.offset == -28800\n  //   // epoch.is_dst == false\n  //   // epoch.abbr == \"PST\"\n  CivilInfo At(Time t) const;\n\n  // TimeZone::TimeInfo\n  //\n  // Information about the absolute times corresponding to a civil time.\n  // (Subseconds must be handled separately.)\n  //\n  // It is possible for a caller to pass a civil-time value that does\n  // not represent an actual or unique instant in time (due to a shift\n  // in UTC offset in the TimeZone, which results in a discontinuity in\n  // the civil-time components). For example, a daylight-saving-time\n  // transition skips or repeats civil times---in the United States,\n  // March 13, 2011 02:15 never occurred, while November 6, 2011 01:15\n  // occurred twice---so requests for such times are not well-defined.\n  // To account for these possibilities, `absl::TimeZone::TimeInfo` is\n  // richer than just a single `absl::Time`.\n  struct TimeInfo {\n    enum CivilKind {\n      UNIQUE,    // the civil time was singular (pre == trans == post)\n      SKIPPED,   // the civil time did not exist (pre >= trans > post)\n      REPEATED,  // the civil time was ambiguous (pre < trans <= post)\n    } kind;\n    Time pre;    // time calculated using the pre-transition offset\n    Time trans;  // when the civil-time discontinuity occurred\n    Time post;   // time calculated using the post-transition offset\n  };\n\n  // TimeZone::At(CivilSecond)\n  //\n  // Returns an `absl::TimeInfo` containing the absolute time(s) for this\n  // TimeZone at an `absl::CivilSecond`. When the civil time is skipped or\n  // repeated, returns times calculated using the pre-transition and post-\n  // transition UTC offsets, plus the transition time itself.\n  //\n  // Examples:\n  //\n  //   // A unique civil time\n  //   const auto jan01 = lax.At(absl::CivilSecond(2011, 1, 1, 0, 0, 0));\n  //   // jan01.kind == TimeZone::TimeInfo::UNIQUE\n  //   // jan01.pre    is 2011-01-01 00:00:00 -0800\n  //   // jan01.trans  is 2011-01-01 00:00:00 -0800\n  //   // jan01.post   is 2011-01-01 00:00:00 -0800\n  //\n  //   // A Spring DST transition, when there is a gap in civil time\n  //   const auto mar13 = lax.At(absl::CivilSecond(2011, 3, 13, 2, 15, 0));\n  //   // mar13.kind == TimeZone::TimeInfo::SKIPPED\n  //   // mar13.pre   is 2011-03-13 03:15:00 -0700\n  //   // mar13.trans is 2011-03-13 03:00:00 -0700\n  //   // mar13.post  is 2011-03-13 01:15:00 -0800\n  //\n  //   // A Fall DST transition, when civil times are repeated\n  //   const auto nov06 = lax.At(absl::CivilSecond(2011, 11, 6, 1, 15, 0));\n  //   // nov06.kind == TimeZone::TimeInfo::REPEATED\n  //   // nov06.pre   is 2011-11-06 01:15:00 -0700\n  //   // nov06.trans is 2011-11-06 01:00:00 -0800\n  //   // nov06.post  is 2011-11-06 01:15:00 -0800\n  TimeInfo At(CivilSecond ct) const;\n\n  // TimeZone::NextTransition()\n  // TimeZone::PrevTransition()\n  //\n  // Finds the time of the next/previous offset change in this time zone.\n  //\n  // By definition, `NextTransition(t, &trans)` returns false when `t` is\n  // `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false\n  // when `t` is `InfinitePast()`. If the zone has no transitions, the\n  // result will also be false no matter what the argument.\n  //\n  // Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)`\n  // returns true and sets `trans` to the first recorded transition. Chains\n  // of calls to `NextTransition()/PrevTransition()` will eventually return\n  // false, but it is unspecified exactly when `NextTransition(t, &trans)`\n  // jumps to false, or what time is set by `PrevTransition(t, &trans)` for\n  // a very distant `t`.\n  //\n  // Note: Enumeration of time-zone transitions is for informational purposes\n  // only. Modern time-related code should not care about when offset changes\n  // occur.\n  //\n  // Example:\n  //   absl::TimeZone nyc;\n  //   if (!absl::LoadTimeZone(\"America/New_York\", &nyc)) { ... }\n  //   const auto now = absl::Now();\n  //   auto t = absl::InfinitePast();\n  //   absl::TimeZone::CivilTransition trans;\n  //   while (t <= now && nyc.NextTransition(t, &trans)) {\n  //     // transition: trans.from -> trans.to\n  //     t = nyc.At(trans.to).trans;\n  //   }\n  struct CivilTransition {\n    CivilSecond from;  // the civil time we jump from\n    CivilSecond to;    // the civil time we jump to\n  };\n  bool NextTransition(Time t, CivilTransition* trans) const;\n  bool PrevTransition(Time t, CivilTransition* trans) const;\n\n  template <typename H>\n  friend H AbslHashValue(H h, TimeZone tz) {\n    return H::combine(std::move(h), tz.cz_);\n  }\n\n private:\n  friend bool operator==(TimeZone a, TimeZone b) { return a.cz_ == b.cz_; }\n  friend bool operator!=(TimeZone a, TimeZone b) { return a.cz_ != b.cz_; }\n  friend std::ostream& operator<<(std::ostream& os, TimeZone tz) {\n    return os << tz.name();\n  }\n\n  time_internal::cctz::time_zone cz_;\n};\n\n// LoadTimeZone()\n//\n// Loads the named zone. May perform I/O on the initial load of the named\n// zone. If the name is invalid, or some other kind of error occurs, returns\n// `false` and `*tz` is set to the UTC time zone.\ninline bool LoadTimeZone(absl::string_view name, TimeZone* tz) {\n  if (name == \"localtime\") {\n    *tz = TimeZone(time_internal::cctz::local_time_zone());\n    return true;\n  }\n  time_internal::cctz::time_zone cz;\n  const bool b = time_internal::cctz::load_time_zone(std::string(name), &cz);\n  *tz = TimeZone(cz);\n  return b;\n}\n\n// FixedTimeZone()\n//\n// Returns a TimeZone that is a fixed offset (seconds east) from UTC.\n// Note: If the absolute value of the offset is greater than 24 hours\n// you'll get UTC (i.e., no offset) instead.\ninline TimeZone FixedTimeZone(int seconds) {\n  return TimeZone(\n      time_internal::cctz::fixed_time_zone(std::chrono::seconds(seconds)));\n}\n\n// UTCTimeZone()\n//\n// Convenience method returning the UTC time zone.\ninline TimeZone UTCTimeZone() {\n  return TimeZone(time_internal::cctz::utc_time_zone());\n}\n\n// LocalTimeZone()\n//\n// Convenience method returning the local time zone, or UTC if there is\n// no configured local zone.  Warning: Be wary of using LocalTimeZone(),\n// and particularly so in a server process, as the zone configured for the\n// local machine should be irrelevant.  Prefer an explicit zone name.\ninline TimeZone LocalTimeZone() {\n  return TimeZone(time_internal::cctz::local_time_zone());\n}\n\n// ToCivilSecond()\n// ToCivilMinute()\n// ToCivilHour()\n// ToCivilDay()\n// ToCivilMonth()\n// ToCivilYear()\n//\n// Helpers for TimeZone::At(Time) to return particularly aligned civil times.\n//\n// Example:\n//\n//   absl::Time t = ...;\n//   absl::TimeZone tz = ...;\n//   const auto cd = absl::ToCivilDay(t, tz);\nABSL_ATTRIBUTE_PURE_FUNCTION inline CivilSecond ToCivilSecond(Time t,\n                                                              TimeZone tz) {\n  return tz.At(t).cs;  // already a CivilSecond\n}\nABSL_ATTRIBUTE_PURE_FUNCTION inline CivilMinute ToCivilMinute(Time t,\n                                                              TimeZone tz) {\n  return CivilMinute(tz.At(t).cs);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION inline CivilHour ToCivilHour(Time t, TimeZone tz) {\n  return CivilHour(tz.At(t).cs);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION inline CivilDay ToCivilDay(Time t, TimeZone tz) {\n  return CivilDay(tz.At(t).cs);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION inline CivilMonth ToCivilMonth(Time t,\n                                                            TimeZone tz) {\n  return CivilMonth(tz.At(t).cs);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION inline CivilYear ToCivilYear(Time t, TimeZone tz) {\n  return CivilYear(tz.At(t).cs);\n}\n\n// FromCivil()\n//\n// Helper for TimeZone::At(CivilSecond) that provides \"order-preserving\n// semantics.\" If the civil time maps to a unique time, that time is\n// returned. If the civil time is repeated in the given time zone, the\n// time using the pre-transition offset is returned. Otherwise, the\n// civil time is skipped in the given time zone, and the transition time\n// is returned. This means that for any two civil times, ct1 and ct2,\n// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case\n// being when two non-existent civil times map to the same transition time.\n//\n// Note: Accepts civil times of any alignment.\nABSL_ATTRIBUTE_PURE_FUNCTION inline Time FromCivil(CivilSecond ct,\n                                                   TimeZone tz) {\n  const auto ti = tz.At(ct);\n  if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans;\n  return ti.pre;\n}\n\n// TimeConversion\n//\n// An `absl::TimeConversion` represents the conversion of year, month, day,\n// hour, minute, and second values (i.e., a civil time), in a particular\n// `absl::TimeZone`, to a time instant (an absolute time), as returned by\n// `absl::ConvertDateTime()`. Legacy version of `absl::TimeZone::TimeInfo`.\n//\n// Deprecated. Use `absl::TimeZone::TimeInfo`.\nstruct ABSL_DEPRECATED(\"Use `absl::TimeZone::TimeInfo`.\") TimeConversion {\n  Time pre;    // time calculated using the pre-transition offset\n  Time trans;  // when the civil-time discontinuity occurred\n  Time post;   // time calculated using the post-transition offset\n\n  enum Kind {\n    UNIQUE,    // the civil time was singular (pre == trans == post)\n    SKIPPED,   // the civil time did not exist\n    REPEATED,  // the civil time was ambiguous\n  };\n  Kind kind;\n\n  bool normalized;  // input values were outside their valid ranges\n};\n\n// ConvertDateTime()\n//\n// Legacy version of `absl::TimeZone::At(absl::CivilSecond)` that takes\n// the civil time as six, separate values (YMDHMS).\n//\n// The input month, day, hour, minute, and second values can be outside\n// of their valid ranges, in which case they will be \"normalized\" during\n// the conversion.\n//\n// Example:\n//\n//   // \"October 32\" normalizes to \"November 1\".\n//   absl::TimeConversion tc =\n//       absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, lax);\n//   // tc.kind == TimeConversion::UNIQUE && tc.normalized == true\n//   // absl::ToCivilDay(tc.pre, tz).month() == 11\n//   // absl::ToCivilDay(tc.pre, tz).day() == 1\n//\n// Deprecated. Use `absl::TimeZone::At(CivilSecond)`.\nABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\nABSL_DEPRECATED(\"Use `absl::TimeZone::At(CivilSecond)`.\")\nTimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,\n                               int min, int sec, TimeZone tz);\nABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n\n// FromDateTime()\n//\n// A convenience wrapper for `absl::ConvertDateTime()` that simply returns\n// the \"pre\" `absl::Time`.  That is, the unique result, or the instant that\n// is correct using the pre-transition offset (as if the transition never\n// happened).\n//\n// Example:\n//\n//   absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax);\n//   // t = 2017-09-26 09:30:00 -0700\n//\n// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the\n// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil\n// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`.\nABSL_DEPRECATED(\"Use `absl::FromCivil(CivilSecond, TimeZone)`.\")\ninline Time FromDateTime(int64_t year, int mon, int day, int hour, int min,\n                         int sec, TimeZone tz) {\n  ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING\n  return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre;\n  ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING\n}\n\n// FromTM()\n//\n// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and\n// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)\n// for a description of the expected values of the tm fields. If the civil time\n// is unique (see `absl::TimeZone::At(absl::CivilSecond)` above), the matching\n// time instant is returned.  Otherwise, the `tm_isdst` field is consulted to\n// choose between the possible results.  For a repeated civil time, `tm_isdst !=\n// 0` returns the matching DST instant, while `tm_isdst == 0` returns the\n// matching non-DST instant.  For a skipped civil time there is no matching\n// instant, so `tm_isdst != 0` returns the DST instant, and `tm_isdst == 0`\n// returns the non-DST instant, that would have matched if the transition never\n// happened.\nABSL_ATTRIBUTE_PURE_FUNCTION Time FromTM(const struct tm& tm, TimeZone tz);\n\n// ToTM()\n//\n// Converts the given `absl::Time` to a struct tm using the given time zone.\n// See ctime(3) for a description of the values of the tm fields.\nABSL_ATTRIBUTE_PURE_FUNCTION struct tm ToTM(Time t, TimeZone tz);\n\n// RFC3339_full\n// RFC3339_sec\n//\n// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings,\n// with trailing zeros trimmed or with fractional seconds omitted altogether.\n//\n// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and\n// time with UTC offset.  Also note the use of \"%Y\": RFC3339 mandates that\n// years have exactly four digits, but we allow them to take their natural\n// width.\nABSL_DLL extern const char RFC3339_full[];  // %Y-%m-%d%ET%H:%M:%E*S%Ez\nABSL_DLL extern const char RFC3339_sec[];   // %Y-%m-%d%ET%H:%M:%S%Ez\n\n// RFC1123_full\n// RFC1123_no_wday\n//\n// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.\nABSL_DLL extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z\nABSL_DLL extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z\n\n// FormatTime()\n//\n// Formats the given `absl::Time` in the `absl::TimeZone` according to the\n// provided format string. Uses strftime()-like formatting options, with\n// the following extensions:\n//\n//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)\n//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)\n//   - %E#S - Seconds with # digits of fractional precision\n//   - %E*S - Seconds with full fractional precision (a literal '*')\n//   - %E#f - Fractional seconds with # digits of precision\n//   - %E*f - Fractional seconds with full precision (a literal '*')\n//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)\n//   - %ET  - The RFC3339 \"date-time\" separator \"T\"\n//\n// Note that %E0S behaves like %S, and %E0f produces no characters.  In\n// contrast %E*f always produces at least one digit, which may be '0'.\n//\n// Note that %Y produces as many characters as it takes to fully render the\n// year.  A year outside of [-999:9999] when formatted with %E4Y will produce\n// more than four characters, just like %Y.\n//\n// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)\n// so that the result uniquely identifies a time instant.\n//\n// Example:\n//\n//   absl::CivilSecond cs(2013, 1, 2, 3, 4, 5);\n//   absl::Time t = absl::FromCivil(cs, lax);\n//   std::string f = absl::FormatTime(\"%H:%M:%S\", t, lax);  // \"03:04:05\"\n//   f = absl::FormatTime(\"%H:%M:%E3S\", t, lax);  // \"03:04:05.000\"\n//\n// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned\n// string will be exactly \"infinite-future\". If the given `absl::Time` is\n// `absl::InfinitePast()`, the returned string will be exactly \"infinite-past\".\n// In both cases the given format string and `absl::TimeZone` are ignored.\n//\nABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(absl::string_view format,\n                                                    Time t, TimeZone tz);\n\n// Convenience functions that format the given time using the RFC3339_full\n// format.  The first overload uses the provided TimeZone, while the second\n// uses LocalTimeZone().\nABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t, TimeZone tz);\nABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);\n\n// Output stream operator.\ninline std::ostream& operator<<(std::ostream& os, Time t) {\n  return os << FormatTime(t);\n}\n\n// Support for StrFormat(), StrCat() etc.\ntemplate <typename Sink>\nvoid AbslStringify(Sink& sink, Time t) {\n  sink.Append(FormatTime(t));\n}\n\n// ParseTime()\n//\n// Parses an input string according to the provided format string and\n// returns the corresponding `absl::Time`. Uses strftime()-like formatting\n// options, with the same extensions as FormatTime(), but with the\n// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez\n// and %E*z also accept the same inputs, which (along with %z) includes\n// 'z' and 'Z' as synonyms for +00:00.  %ET accepts either 'T' or 't'.\n//\n// %Y consumes as many numeric characters as it can, so the matching data\n// should always be terminated with a non-numeric.  %E4Y always consumes\n// exactly four characters, including any sign.\n//\n// Unspecified fields are taken from the default date and time of ...\n//\n//   \"1970-01-01 00:00:00.0 +0000\"\n//\n// For example, parsing a string of \"15:45\" (%H:%M) will return an absl::Time\n// that represents \"1970-01-01 15:45:00.0 +0000\".\n//\n// Note that since ParseTime() returns time instants, it makes the most sense\n// to parse fully-specified date/time strings that include a UTC offset (%z,\n// %Ez, or %E*z).\n//\n// Note also that `absl::ParseTime()` only heeds the fields year, month, day,\n// hour, minute, (fractional) second, and UTC offset.  Other fields, like\n// weekday (%a or %A), while parsed for syntactic validity, are ignored\n// in the conversion.\n//\n// Date and time fields that are out-of-range will be treated as errors\n// rather than normalizing them like `absl::CivilSecond` does.  For example,\n// it is an error to parse the date \"Oct 32, 2013\" because 32 is out of range.\n//\n// A leap second of \":60\" is normalized to \":00\" of the following minute\n// with fractional seconds discarded.  The following table shows how the\n// given seconds and subseconds will be parsed:\n//\n//   \"59.x\" -> 59.x  // exact\n//   \"60.x\" -> 00.0  // normalized\n//   \"00.x\" -> 00.x  // exact\n//\n// Errors are indicated by returning false and assigning an error message\n// to the \"err\" out param if it is non-null.\n//\n// Note: If the input string is exactly \"infinite-future\", the returned\n// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned.\n// If the input string is \"infinite-past\", the returned `absl::Time` will be\n// `absl::InfinitePast()` and `true` will be returned.\n//\nbool ParseTime(absl::string_view format, absl::string_view input, Time* time,\n               std::string* err);\n\n// Like ParseTime() above, but if the format string does not contain a UTC\n// offset specification (%z/%Ez/%E*z) then the input is interpreted in the\n// given TimeZone.  This means that the input, by itself, does not identify a\n// unique instant.  Being time-zone dependent, it also admits the possibility\n// of ambiguity or non-existence, in which case the \"pre\" time (as defined\n// by TimeZone::TimeInfo) is returned.  For these reasons we recommend that\n// all date/time strings include a UTC offset so they're context independent.\nbool ParseTime(absl::string_view format, absl::string_view input, TimeZone tz,\n               Time* time, std::string* err);\n\n// ============================================================================\n// Implementation Details Follow\n// ============================================================================\n\nnamespace time_internal {\n\n// Creates a Duration with a given representation.\n// REQUIRES: hi,lo is a valid representation of a Duration as specified\n// in time/duration.cc.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,\n                                                              uint32_t lo = 0) {\n  return Duration(hi, lo);\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,\n                                                              int64_t lo) {\n  return MakeDuration(hi, static_cast<uint32_t>(lo));\n}\n\n// Make a Duration value from a floating-point number, as long as that number\n// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as\n// it's positive and can be converted to int64_t without risk of UB.\nABSL_ATTRIBUTE_CONST_FUNCTION inline Duration MakePosDoubleDuration(double n) {\n  const int64_t int_secs = static_cast<int64_t>(n);\n  const uint32_t ticks = static_cast<uint32_t>(\n      std::round((n - static_cast<double>(int_secs)) * kTicksPerSecond));\n  return ticks < kTicksPerSecond\n             ? MakeDuration(int_secs, ticks)\n             : MakeDuration(int_secs + 1, ticks - kTicksPerSecond);\n}\n\n// Creates a normalized Duration from an almost-normalized (sec,ticks)\n// pair. sec may be positive or negative.  ticks must be in the range\n// -kTicksPerSecond < *ticks < kTicksPerSecond.  If ticks is negative it\n// will be normalized to a positive value in the resulting Duration.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeNormalizedDuration(\n    int64_t sec, int64_t ticks) {\n  return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond)\n                     : MakeDuration(sec, ticks);\n}\n\n// Provide access to the Duration representation.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d) {\n  return d.rep_hi_.Get();\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d) {\n  return d.rep_lo_;\n}\n\n// Returns true iff d is positive or negative infinity.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool IsInfiniteDuration(Duration d) {\n  return GetRepLo(d) == ~uint32_t{0};\n}\n\n// Returns an infinite Duration with the opposite sign.\n// REQUIRES: IsInfiniteDuration(d)\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration OppositeInfinity(Duration d) {\n  return GetRepHi(d) < 0\n             ? MakeDuration((std::numeric_limits<int64_t>::max)(), ~uint32_t{0})\n             : MakeDuration((std::numeric_limits<int64_t>::min)(),\n                            ~uint32_t{0});\n}\n\n// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t NegateAndSubtractOne(\n    int64_t n) {\n  // Note: Good compilers will optimize this expression to ~n when using\n  // a two's-complement representation (which is required for int64_t).\n  return (n < 0) ? -(n + 1) : (-n) - 1;\n}\n\n// Map between a Time and a Duration since the Unix epoch.  Note that these\n// functions depend on the above mentioned choice of the Unix epoch for the\n// Time representation (and both need to be Time friends).  Without this\n// knowledge, we would need to add-in/subtract-out UnixEpoch() respectively.\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d) {\n  return Time(d);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t) {\n  return t.rep_;\n}\n\ntemplate <std::intmax_t N>\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,\n                                                           std::ratio<1, N>) {\n  static_assert(0 < N && N <= 1000 * 1000 * 1000, \"Unsupported ratio\");\n  // Subsecond ratios cannot overflow.\n  return MakeNormalizedDuration(\n      v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,\n                                                           std::ratio<60>) {\n  return (v <= (std::numeric_limits<int64_t>::max)() / 60 &&\n          v >= (std::numeric_limits<int64_t>::min)() / 60)\n             ? MakeDuration(v * 60)\n         : v > 0 ? InfiniteDuration()\n                 : -InfiniteDuration();\n}\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,\n                                                           std::ratio<3600>) {\n  return (v <= (std::numeric_limits<int64_t>::max)() / 3600 &&\n          v >= (std::numeric_limits<int64_t>::min)() / 3600)\n             ? MakeDuration(v * 3600)\n         : v > 0 ? InfiniteDuration()\n                 : -InfiniteDuration();\n}\n\n// IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is\n// valid. That is, if a T can be assigned to an int64_t without narrowing.\ntemplate <typename T>\nconstexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) {\n  return true;\n}\ntemplate <typename T>\nconstexpr auto IsValidRep64(char) -> bool {\n  return false;\n}\n\n// Converts a std::chrono::duration to an absl::Duration.\ntemplate <typename Rep, typename Period>\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::duration<Rep, Period>& d) {\n  static_assert(IsValidRep64<Rep>(0), \"duration::rep is invalid\");\n  return FromInt64(int64_t{d.count()}, Period{});\n}\n\ntemplate <typename Ratio>\nABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64(Duration d, Ratio) {\n  // Note: This may be used on MSVC, which may have a system_clock period of\n  // std::ratio<1, 10 * 1000 * 1000>\n  return ToInt64Seconds(d * Ratio::den / Ratio::num);\n}\n// Fastpath implementations for the 6 common duration units.\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::nano) {\n  return ToInt64Nanoseconds(d);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::micro) {\n  return ToInt64Microseconds(d);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::milli) {\n  return ToInt64Milliseconds(d);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,\n                                                     std::ratio<1>) {\n  return ToInt64Seconds(d);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,\n                                                     std::ratio<60>) {\n  return ToInt64Minutes(d);\n}\nABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,\n                                                     std::ratio<3600>) {\n  return ToInt64Hours(d);\n}\n\n// Converts an absl::Duration to a chrono duration of type T.\ntemplate <typename T>\nABSL_ATTRIBUTE_CONST_FUNCTION T ToChronoDuration(Duration d) {\n  using Rep = typename T::rep;\n  using Period = typename T::period;\n  static_assert(IsValidRep64<Rep>(0), \"duration::rep is invalid\");\n  if (time_internal::IsInfiniteDuration(d))\n    return d < ZeroDuration() ? (T::min)() : (T::max)();\n  const auto v = ToInt64(d, Period{});\n  if (v > (std::numeric_limits<Rep>::max)()) return (T::max)();\n  if (v < (std::numeric_limits<Rep>::min)()) return (T::min)();\n  return T{v};\n}\n\n}  // namespace time_internal\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,\n                                                       Duration rhs) {\n  return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)\n             ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)\n         : time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)()\n             ? time_internal::GetRepLo(lhs) + 1 <\n                   time_internal::GetRepLo(rhs) + 1\n             : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);\n}\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(\n    Duration lhs, Duration rhs) {\n  const int64_t lhs_hi = time_internal::GetRepHi(lhs);\n  const int64_t rhs_hi = time_internal::GetRepHi(rhs);\n  if (auto c = lhs_hi <=> rhs_hi; c != std::strong_ordering::equal) {\n    return c;\n  }\n  const uint32_t lhs_lo = time_internal::GetRepLo(lhs);\n  const uint32_t rhs_lo = time_internal::GetRepLo(rhs);\n  return (lhs_hi == (std::numeric_limits<int64_t>::min)())\n             ? (lhs_lo + 1) <=> (rhs_lo + 1)\n             : lhs_lo <=> rhs_lo;\n}\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,\n                                                        Duration rhs) {\n  return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) &&\n         time_internal::GetRepLo(lhs) == time_internal::GetRepLo(rhs);\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration operator-(Duration d) {\n  // This is a little interesting because of the special cases.\n  //\n  // If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're\n  // dealing with an integral number of seconds, and the only special case is\n  // the maximum negative finite duration, which can't be negated.\n  //\n  // Infinities stay infinite, and just change direction.\n  //\n  // Finally we're in the case where rep_lo_ is non-zero, and we can borrow\n  // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1\n  // is safe).\n  return time_internal::GetRepLo(d) == 0\n             ? time_internal::GetRepHi(d) ==\n                       (std::numeric_limits<int64_t>::min)()\n                   ? InfiniteDuration()\n                   : time_internal::MakeDuration(-time_internal::GetRepHi(d))\n         : time_internal::IsInfiniteDuration(d)\n             ? time_internal::OppositeInfinity(d)\n             : time_internal::MakeDuration(\n                   time_internal::NegateAndSubtractOne(\n                       time_internal::GetRepHi(d)),\n                   time_internal::kTicksPerSecond - time_internal::GetRepLo(d));\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration InfiniteDuration() {\n  return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),\n                                     ~uint32_t{0});\n}\n\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::nanoseconds& d) {\n  return time_internal::FromChrono(d);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::microseconds& d) {\n  return time_internal::FromChrono(d);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::milliseconds& d) {\n  return time_internal::FromChrono(d);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::seconds& d) {\n  return time_internal::FromChrono(d);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::minutes& d) {\n  return time_internal::FromChrono(d);\n}\nABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(\n    const std::chrono::hours& d) {\n  return time_internal::FromChrono(d);\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixNanos(int64_t ns) {\n  return time_internal::FromUnixDuration(Nanoseconds(ns));\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMicros(int64_t us) {\n  return time_internal::FromUnixDuration(Microseconds(us));\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMillis(int64_t ms) {\n  return time_internal::FromUnixDuration(Milliseconds(ms));\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixSeconds(int64_t s) {\n  return time_internal::FromUnixDuration(Seconds(s));\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t) {\n  return time_internal::FromUnixDuration(Seconds(t));\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Nanoseconds(Duration d) {\n  if (time_internal::GetRepHi(d) >= 0 &&\n      time_internal::GetRepHi(d) >> 33 == 0) {\n    return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +\n           (time_internal::GetRepLo(d) / time_internal::kTicksPerNanosecond);\n  } else {\n    return d / Nanoseconds(1);\n  }\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Microseconds(\n    Duration d) {\n  if (time_internal::GetRepHi(d) >= 0 &&\n      time_internal::GetRepHi(d) >> 43 == 0) {\n    return (time_internal::GetRepHi(d) * 1000 * 1000) +\n           (time_internal::GetRepLo(d) /\n            (time_internal::kTicksPerNanosecond * 1000));\n  } else {\n    return d / Microseconds(1);\n  }\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Milliseconds(\n    Duration d) {\n  if (time_internal::GetRepHi(d) >= 0 &&\n      time_internal::GetRepHi(d) >> 53 == 0) {\n    return (time_internal::GetRepHi(d) * 1000) +\n           (time_internal::GetRepLo(d) /\n            (time_internal::kTicksPerNanosecond * 1000 * 1000));\n  } else {\n    return d / Milliseconds(1);\n  }\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Seconds(Duration d) {\n  int64_t hi = time_internal::GetRepHi(d);\n  if (time_internal::IsInfiniteDuration(d)) return hi;\n  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;\n  return hi;\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Minutes(Duration d) {\n  int64_t hi = time_internal::GetRepHi(d);\n  if (time_internal::IsInfiniteDuration(d)) return hi;\n  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;\n  return hi / 60;\n}\n\nABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Hours(Duration d) {\n  int64_t hi = time_internal::GetRepHi(d);\n  if (time_internal::IsInfiniteDuration(d)) return hi;\n  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;\n  return hi / (60 * 60);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TIME_TIME_H_\n"
  },
  {
    "path": "absl/time/time_benchmark.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/time.h\"\n\n#if !defined(_WIN32)\n#include <sys/time.h>\n#endif  // _WIN32\n#include <algorithm>\n#include <cmath>\n#include <cstddef>\n#include <cstring>\n#include <ctime>\n#include <memory>\n#include <string>\n\n#include \"absl/time/clock.h\"\n#include \"absl/time/internal/test_util.h\"\n#include \"benchmark/benchmark.h\"\n\nnamespace {\n\n//\n// Addition/Subtraction of a duration\n//\n\nvoid BM_Time_Arithmetic(benchmark::State& state) {\n  const absl::Duration nano = absl::Nanoseconds(1);\n  const absl::Duration sec = absl::Seconds(1);\n  absl::Time t = absl::UnixEpoch();\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(t += nano);\n    benchmark::DoNotOptimize(t -= sec);\n  }\n}\nBENCHMARK(BM_Time_Arithmetic);\n\n//\n// Time difference\n//\n\nvoid BM_Time_Difference(benchmark::State& state) {\n  absl::Time start = absl::Now();\n  absl::Time end = start + absl::Nanoseconds(1);\n  absl::Duration diff;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(diff += end - start);\n  }\n}\nBENCHMARK(BM_Time_Difference);\n\n//\n// ToDateTime\n//\n// In each \"ToDateTime\" benchmark we switch between two instants\n// separated by at least one transition in order to defeat any\n// internal caching of previous results (e.g., see local_time_hint_).\n//\n// The \"UTC\" variants use UTC instead of the Google/local time zone.\n//\n\nvoid BM_Time_ToDateTime_Absl(benchmark::State& state) {\n  const absl::TimeZone tz =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  absl::Time t = absl::FromUnixSeconds(1384569027);\n  absl::Time t2 = absl::FromUnixSeconds(1418962578);\n  while (state.KeepRunning()) {\n    std::swap(t, t2);\n    t += absl::Seconds(1);\n    benchmark::DoNotOptimize(t.In(tz));\n  }\n}\nBENCHMARK(BM_Time_ToDateTime_Absl);\n\nvoid BM_Time_ToDateTime_Libc(benchmark::State& state) {\n  // No timezone support, so just use localtime.\n  time_t t = 1384569027;\n  time_t t2 = 1418962578;\n  while (state.KeepRunning()) {\n    std::swap(t, t2);\n    t += 1;\n    struct tm tm;\n#if !defined(_WIN32)\n    benchmark::DoNotOptimize(localtime_r(&t, &tm));\n#else   // _WIN32\n    benchmark::DoNotOptimize(localtime_s(&tm, &t));\n#endif  // _WIN32\n  }\n}\nBENCHMARK(BM_Time_ToDateTime_Libc);\n\nvoid BM_Time_ToDateTimeUTC_Absl(benchmark::State& state) {\n  const absl::TimeZone tz = absl::UTCTimeZone();\n  absl::Time t = absl::FromUnixSeconds(1384569027);\n  while (state.KeepRunning()) {\n    t += absl::Seconds(1);\n    benchmark::DoNotOptimize(t.In(tz));\n  }\n}\nBENCHMARK(BM_Time_ToDateTimeUTC_Absl);\n\nvoid BM_Time_ToDateTimeUTC_Libc(benchmark::State& state) {\n  time_t t = 1384569027;\n  while (state.KeepRunning()) {\n    t += 1;\n    struct tm tm;\n#if !defined(_WIN32)\n    benchmark::DoNotOptimize(gmtime_r(&t, &tm));\n#else   // _WIN32\n    benchmark::DoNotOptimize(gmtime_s(&tm, &t));\n#endif  // _WIN32\n  }\n}\nBENCHMARK(BM_Time_ToDateTimeUTC_Libc);\n\n//\n// FromUnixMicros\n//\n\nvoid BM_Time_FromUnixMicros(benchmark::State& state) {\n  int i = 0;\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::FromUnixMicros(i));\n    ++i;\n  }\n}\nBENCHMARK(BM_Time_FromUnixMicros);\n\nvoid BM_Time_ToUnixNanos(benchmark::State& state) {\n  const absl::Time t = absl::UnixEpoch() + absl::Seconds(123);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(ToUnixNanos(t));\n  }\n}\nBENCHMARK(BM_Time_ToUnixNanos);\n\nvoid BM_Time_ToUnixMicros(benchmark::State& state) {\n  const absl::Time t = absl::UnixEpoch() + absl::Seconds(123);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(ToUnixMicros(t));\n  }\n}\nBENCHMARK(BM_Time_ToUnixMicros);\n\nvoid BM_Time_ToUnixMillis(benchmark::State& state) {\n  const absl::Time t = absl::UnixEpoch() + absl::Seconds(123);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(ToUnixMillis(t));\n  }\n}\nBENCHMARK(BM_Time_ToUnixMillis);\n\nvoid BM_Time_ToUnixSeconds(benchmark::State& state) {\n  const absl::Time t = absl::UnixEpoch() + absl::Seconds(123);\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToUnixSeconds(t));\n  }\n}\nBENCHMARK(BM_Time_ToUnixSeconds);\n\n//\n// FromCivil\n//\n// In each \"FromCivil\" benchmark we switch between two YMDhms values\n// separated by at least one transition in order to defeat any internal\n// caching of previous results (e.g., see time_local_hint_).\n//\n// The \"UTC\" variants use UTC instead of the Google/local time zone.\n// The \"Day0\" variants require normalization of the day of month.\n//\n\nvoid BM_Time_FromCivil_Absl(benchmark::State& state) {\n  const absl::TimeZone tz =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  int i = 0;\n  while (state.KeepRunning()) {\n    if ((i & 1) == 0) {\n      benchmark::DoNotOptimize(\n          absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz));\n    } else {\n      benchmark::DoNotOptimize(\n          absl::FromCivil(absl::CivilSecond(2013, 11, 15, 18, 30, 27), tz));\n    }\n    ++i;\n  }\n}\nBENCHMARK(BM_Time_FromCivil_Absl);\n\nvoid BM_Time_FromCivil_Libc(benchmark::State& state) {\n  // No timezone support, so just use localtime.\n  int i = 0;\n  while (state.KeepRunning()) {\n    struct tm tm;\n    if ((i & 1) == 0) {\n      tm.tm_year = 2014 - 1900;\n      tm.tm_mon = 12 - 1;\n      tm.tm_mday = 18;\n      tm.tm_hour = 20;\n      tm.tm_min = 16;\n      tm.tm_sec = 18;\n    } else {\n      tm.tm_year = 2013 - 1900;\n      tm.tm_mon = 11 - 1;\n      tm.tm_mday = 15;\n      tm.tm_hour = 18;\n      tm.tm_min = 30;\n      tm.tm_sec = 27;\n    }\n    tm.tm_isdst = -1;\n    mktime(&tm);\n    ++i;\n  }\n}\nBENCHMARK(BM_Time_FromCivil_Libc);\n\nvoid BM_Time_FromCivilUTC_Absl(benchmark::State& state) {\n  const absl::TimeZone tz = absl::UTCTimeZone();\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(\n        absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz));\n  }\n}\nBENCHMARK(BM_Time_FromCivilUTC_Absl);\n\nvoid BM_Time_FromCivilDay0_Absl(benchmark::State& state) {\n  const absl::TimeZone tz =\n      absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  int i = 0;\n  while (state.KeepRunning()) {\n    if ((i & 1) == 0) {\n      benchmark::DoNotOptimize(\n          absl::FromCivil(absl::CivilSecond(2014, 12, 0, 20, 16, 18), tz));\n    } else {\n      benchmark::DoNotOptimize(\n          absl::FromCivil(absl::CivilSecond(2013, 11, 0, 18, 30, 27), tz));\n    }\n    ++i;\n  }\n}\nBENCHMARK(BM_Time_FromCivilDay0_Absl);\n\nvoid BM_Time_FromCivilDay0_Libc(benchmark::State& state) {\n  // No timezone support, so just use localtime.\n  int i = 0;\n  while (state.KeepRunning()) {\n    struct tm tm;\n    if ((i & 1) == 0) {\n      tm.tm_year = 2014 - 1900;\n      tm.tm_mon = 12 - 1;\n      tm.tm_mday = 0;\n      tm.tm_hour = 20;\n      tm.tm_min = 16;\n      tm.tm_sec = 18;\n    } else {\n      tm.tm_year = 2013 - 1900;\n      tm.tm_mon = 11 - 1;\n      tm.tm_mday = 0;\n      tm.tm_hour = 18;\n      tm.tm_min = 30;\n      tm.tm_sec = 27;\n    }\n    tm.tm_isdst = -1;\n    mktime(&tm);\n    ++i;\n  }\n}\nBENCHMARK(BM_Time_FromCivilDay0_Libc);\n\n//\n// To/FromTimespec\n//\n\nvoid BM_Time_ToTimespec(benchmark::State& state) {\n  absl::Time now = absl::Now();\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::ToTimespec(now));\n  }\n}\nBENCHMARK(BM_Time_ToTimespec);\n\nvoid BM_Time_FromTimespec(benchmark::State& state) {\n  timespec ts = absl::ToTimespec(absl::Now());\n  while (state.KeepRunning()) {\n    if (++ts.tv_nsec == 1000 * 1000 * 1000) {\n      ++ts.tv_sec;\n      ts.tv_nsec = 0;\n    }\n    benchmark::DoNotOptimize(absl::TimeFromTimespec(ts));\n  }\n}\nBENCHMARK(BM_Time_FromTimespec);\n\n//\n// Comparison with InfiniteFuture/Past\n//\n\nvoid BM_Time_InfiniteFuture(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::InfiniteFuture());\n  }\n}\nBENCHMARK(BM_Time_InfiniteFuture);\n\nvoid BM_Time_InfinitePast(benchmark::State& state) {\n  while (state.KeepRunning()) {\n    benchmark::DoNotOptimize(absl::InfinitePast());\n  }\n}\nBENCHMARK(BM_Time_InfinitePast);\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/time_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/time.h\"\n\n#include \"absl/time/civil_time.h\"\n\n#if defined(_MSC_VER)\n#include <winsock2.h>  // for timeval\n#endif\n\n#include \"absl/base/config.h\"\n\n// For feature testing and determining which headers can be included.\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n#include <version>\n#endif\n\n#include <chrono>  // NOLINT(build/c++11)\n#ifdef __cpp_lib_three_way_comparison\n#include <compare>\n#endif  // __cpp_lib_three_way_comparison\n#include <cstdint>\n#include <cstring>\n#include <ctime>\n#include <iomanip>\n#include <ios>\n#include <limits>\n#include <string>\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/numeric/int128.h\"\n#include \"absl/strings/str_format.h\"\n#include \"absl/time/clock.h\"\n#include \"absl/time/internal/test_util.h\"\n\nnamespace {\n\n#if defined(GTEST_USES_SIMPLE_RE) && GTEST_USES_SIMPLE_RE\nconst char kZoneAbbrRE[] = \".*\";  // just punt\n#else\nconst char kZoneAbbrRE[] = \"[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?\";\n#endif\n\n// This helper is a macro so that failed expectations show up with the\n// correct line numbers.\n#define EXPECT_CIVIL_INFO(ci, y, m, d, h, min, s, off, isdst)      \\\n  do {                                                             \\\n    EXPECT_EQ(y, ci.cs.year());                                    \\\n    EXPECT_EQ(m, ci.cs.month());                                   \\\n    EXPECT_EQ(d, ci.cs.day());                                     \\\n    EXPECT_EQ(h, ci.cs.hour());                                    \\\n    EXPECT_EQ(min, ci.cs.minute());                                \\\n    EXPECT_EQ(s, ci.cs.second());                                  \\\n    EXPECT_EQ(off, ci.offset);                                     \\\n    EXPECT_EQ(isdst, ci.is_dst);                                   \\\n    EXPECT_THAT(ci.zone_abbr, testing::MatchesRegex(kZoneAbbrRE)); \\\n  } while (0)\n\n// A gMock matcher to match timespec values. Use this matcher like:\n// timespec ts1, ts2;\n// EXPECT_THAT(ts1, TimespecMatcher(ts2));\nMATCHER_P(TimespecMatcher, ts, \"\") {\n  if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) return true;\n  *result_listener << \"expected: {\" << ts.tv_sec << \", \" << ts.tv_nsec << \"} \";\n  *result_listener << \"actual: {\" << arg.tv_sec << \", \" << arg.tv_nsec << \"}\";\n  return false;\n}\n\n// A gMock matcher to match timeval values. Use this matcher like:\n// timeval tv1, tv2;\n// EXPECT_THAT(tv1, TimevalMatcher(tv2));\nMATCHER_P(TimevalMatcher, tv, \"\") {\n  if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) return true;\n  *result_listener << \"expected: {\" << tv.tv_sec << \", \" << tv.tv_usec << \"} \";\n  *result_listener << \"actual: {\" << arg.tv_sec << \", \" << arg.tv_usec << \"}\";\n  return false;\n}\n\nTEST(Time, ConstExpr) {\n  static_assert(std::is_trivially_destructible<absl::Time>::value,\n                \"Time is documented as being trivially destructible\");\n  constexpr absl::Time t0 = absl::UnixEpoch();\n  static_assert(t0 == absl::UnixEpoch(), \"UnixEpoch\");\n  constexpr absl::Time t1 = absl::InfiniteFuture();\n  static_assert(t1 != absl::UnixEpoch(), \"InfiniteFuture\");\n  constexpr absl::Time t2 = absl::InfinitePast();\n  static_assert(t2 != absl::UnixEpoch(), \"InfinitePast\");\n  constexpr absl::Time t3 = absl::FromUnixNanos(0);\n  static_assert(t3 == absl::UnixEpoch(), \"FromUnixNanos\");\n  constexpr absl::Time t4 = absl::FromUnixMicros(0);\n  static_assert(t4 == absl::UnixEpoch(), \"FromUnixMicros\");\n  constexpr absl::Time t5 = absl::FromUnixMillis(0);\n  static_assert(t5 == absl::UnixEpoch(), \"FromUnixMillis\");\n  constexpr absl::Time t6 = absl::FromUnixSeconds(0);\n  static_assert(t6 == absl::UnixEpoch(), \"FromUnixSeconds\");\n  constexpr absl::Time t7 = absl::FromTimeT(0);\n  static_assert(t7 == absl::UnixEpoch(), \"FromTimeT\");\n}\n\nTEST(Time, ValueSemantics) {\n  absl::Time a;      // Default construction\n  absl::Time b = a;  // Copy construction\n  EXPECT_EQ(a, b);\n  absl::Time c(a);  // Copy construction (again)\n  EXPECT_EQ(a, b);\n  EXPECT_EQ(a, c);\n  EXPECT_EQ(b, c);\n  b = c;  // Assignment\n  EXPECT_EQ(a, b);\n  EXPECT_EQ(a, c);\n  EXPECT_EQ(b, c);\n}\n\nTEST(Time, UnixEpoch) {\n  const auto ci = absl::UTCTimeZone().At(absl::UnixEpoch());\n  EXPECT_EQ(absl::CivilSecond(1970, 1, 1, 0, 0, 0), ci.cs);\n  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);\n  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs));\n}\n\nTEST(Time, Breakdown) {\n  absl::TimeZone tz = absl::time_internal::LoadTimeZone(\"America/New_York\");\n  absl::Time t = absl::UnixEpoch();\n\n  // The Unix epoch as seen in NYC.\n  auto ci = tz.At(t);\n  EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 19, 0, 0, -18000, false);\n  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);\n  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs));\n\n  // Just before the epoch.\n  t -= absl::Nanoseconds(1);\n  ci = tz.At(t);\n  EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 18, 59, 59, -18000, false);\n  EXPECT_EQ(absl::Nanoseconds(999999999), ci.subsecond);\n  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs));\n\n  // Some time later.\n  t += absl::Hours(24) * 2735;\n  t += absl::Hours(18) + absl::Minutes(30) + absl::Seconds(15) +\n       absl::Nanoseconds(9);\n  ci = tz.At(t);\n  EXPECT_CIVIL_INFO(ci, 1977, 6, 28, 14, 30, 15, -14400, true);\n  EXPECT_EQ(8, ci.subsecond / absl::Nanoseconds(1));\n  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ci.cs));\n}\n\nTEST(Time, AdditiveOperators) {\n  const absl::Duration d = absl::Nanoseconds(1);\n  const absl::Time t0;\n  const absl::Time t1 = t0 + d;\n\n  EXPECT_EQ(d, t1 - t0);\n  EXPECT_EQ(-d, t0 - t1);\n  EXPECT_EQ(t0, t1 - d);\n\n  absl::Time t(t0);\n  EXPECT_EQ(t0, t);\n  t += d;\n  EXPECT_EQ(t0 + d, t);\n  EXPECT_EQ(d, t - t0);\n  t -= d;\n  EXPECT_EQ(t0, t);\n\n  // Tests overflow between subseconds and seconds.\n  t = absl::UnixEpoch();\n  t += absl::Milliseconds(500);\n  EXPECT_EQ(absl::UnixEpoch() + absl::Milliseconds(500), t);\n  t += absl::Milliseconds(600);\n  EXPECT_EQ(absl::UnixEpoch() + absl::Milliseconds(1100), t);\n  t -= absl::Milliseconds(600);\n  EXPECT_EQ(absl::UnixEpoch() + absl::Milliseconds(500), t);\n  t -= absl::Milliseconds(500);\n  EXPECT_EQ(absl::UnixEpoch(), t);\n}\n\nTEST(Time, RelationalOperators) {\n  constexpr absl::Time t1 = absl::FromUnixNanos(0);\n  constexpr absl::Time t2 = absl::FromUnixNanos(1);\n  constexpr absl::Time t3 = absl::FromUnixNanos(2);\n\n  static_assert(absl::UnixEpoch() == t1, \"\");\n  static_assert(t1 == t1, \"\");\n  static_assert(t2 == t2, \"\");\n  static_assert(t3 == t3, \"\");\n\n  static_assert(t1 < t2, \"\");\n  static_assert(t2 < t3, \"\");\n  static_assert(t1 < t3, \"\");\n\n  static_assert(t1 <= t1, \"\");\n  static_assert(t1 <= t2, \"\");\n  static_assert(t2 <= t2, \"\");\n  static_assert(t2 <= t3, \"\");\n  static_assert(t3 <= t3, \"\");\n  static_assert(t1 <= t3, \"\");\n\n  static_assert(t2 > t1, \"\");\n  static_assert(t3 > t2, \"\");\n  static_assert(t3 > t1, \"\");\n\n  static_assert(t2 >= t2, \"\");\n  static_assert(t2 >= t1, \"\");\n  static_assert(t3 >= t3, \"\");\n  static_assert(t3 >= t2, \"\");\n  static_assert(t1 >= t1, \"\");\n  static_assert(t3 >= t1, \"\");\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  static_assert((t1 <=> t1) == std::strong_ordering::equal, \"\");\n  static_assert((t2 <=> t2) == std::strong_ordering::equal, \"\");\n  static_assert((t3 <=> t3) == std::strong_ordering::equal, \"\");\n\n  static_assert((t1 <=> t2) == std::strong_ordering::less, \"\");\n  static_assert((t2 <=> t3) == std::strong_ordering::less, \"\");\n  static_assert((t1 <=> t3) == std::strong_ordering::less, \"\");\n\n  static_assert((t2 <=> t1) == std::strong_ordering::greater, \"\");\n  static_assert((t3 <=> t2) == std::strong_ordering::greater, \"\");\n  static_assert((t3 <=> t1) == std::strong_ordering::greater, \"\");\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n}\n\nTEST(Time, Infinity) {\n  constexpr absl::Time ifuture = absl::InfiniteFuture();\n  constexpr absl::Time ipast = absl::InfinitePast();\n\n  static_assert(ifuture == ifuture, \"\");\n  static_assert(ipast == ipast, \"\");\n  static_assert(ipast < ifuture, \"\");\n  static_assert(ifuture > ipast, \"\");\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  static_assert((ifuture <=> ifuture) == std::strong_ordering::equal, \"\");\n  static_assert((ipast <=> ipast) == std::strong_ordering::equal, \"\");\n  static_assert((ipast <=> ifuture) == std::strong_ordering::less, \"\");\n  static_assert((ifuture <=> ipast) == std::strong_ordering::greater, \"\");\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  // Arithmetic saturates\n  EXPECT_EQ(ifuture, ifuture + absl::Seconds(1));\n  EXPECT_EQ(ifuture, ifuture - absl::Seconds(1));\n  EXPECT_EQ(ipast, ipast + absl::Seconds(1));\n  EXPECT_EQ(ipast, ipast - absl::Seconds(1));\n\n  EXPECT_EQ(absl::InfiniteDuration(), ifuture - ifuture);\n  EXPECT_EQ(absl::InfiniteDuration(), ifuture - ipast);\n  EXPECT_EQ(-absl::InfiniteDuration(), ipast - ifuture);\n  EXPECT_EQ(-absl::InfiniteDuration(), ipast - ipast);\n\n  constexpr absl::Time t = absl::UnixEpoch();  // Any finite time.\n  static_assert(t < ifuture, \"\");\n  static_assert(t > ipast, \"\");\n\n#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  static_assert((t <=> ifuture) == std::strong_ordering::less, \"\");\n  static_assert((t <=> ipast) == std::strong_ordering::greater, \"\");\n  static_assert((ipast <=> t) == std::strong_ordering::less, \"\");\n  static_assert((ifuture <=> t) == std::strong_ordering::greater, \"\");\n\n#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON\n\n  EXPECT_EQ(ifuture, t + absl::InfiniteDuration());\n  EXPECT_EQ(ipast, t - absl::InfiniteDuration());\n}\n\nTEST(Time, FloorConversion) {\n#define TEST_FLOOR_CONVERSION(TO, FROM) \\\n  EXPECT_EQ(1, TO(FROM(1001)));         \\\n  EXPECT_EQ(1, TO(FROM(1000)));         \\\n  EXPECT_EQ(0, TO(FROM(999)));          \\\n  EXPECT_EQ(0, TO(FROM(1)));            \\\n  EXPECT_EQ(0, TO(FROM(0)));            \\\n  EXPECT_EQ(-1, TO(FROM(-1)));          \\\n  EXPECT_EQ(-1, TO(FROM(-999)));        \\\n  EXPECT_EQ(-1, TO(FROM(-1000)));       \\\n  EXPECT_EQ(-2, TO(FROM(-1001)));\n\n  TEST_FLOOR_CONVERSION(absl::ToUnixMicros, absl::FromUnixNanos);\n  TEST_FLOOR_CONVERSION(absl::ToUnixMillis, absl::FromUnixMicros);\n  TEST_FLOOR_CONVERSION(absl::ToUnixSeconds, absl::FromUnixMillis);\n  TEST_FLOOR_CONVERSION(absl::ToTimeT, absl::FromUnixMillis);\n\n#undef TEST_FLOOR_CONVERSION\n\n  // Tests ToUnixNanos.\n  EXPECT_EQ(1, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(3) / 2));\n  EXPECT_EQ(1, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(1)));\n  EXPECT_EQ(0, absl::ToUnixNanos(absl::UnixEpoch() + absl::Nanoseconds(1) / 2));\n  EXPECT_EQ(0, absl::ToUnixNanos(absl::UnixEpoch() + absl::ZeroDuration()));\n  EXPECT_EQ(-1,\n            absl::ToUnixNanos(absl::UnixEpoch() - absl::Nanoseconds(1) / 2));\n  EXPECT_EQ(-1, absl::ToUnixNanos(absl::UnixEpoch() - absl::Nanoseconds(1)));\n  EXPECT_EQ(-2,\n            absl::ToUnixNanos(absl::UnixEpoch() - absl::Nanoseconds(3) / 2));\n\n  // Tests ToUniversal, which uses a different epoch than the tests above.\n  EXPECT_EQ(1,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(101)));\n  EXPECT_EQ(1,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(100)));\n  EXPECT_EQ(0,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(99)));\n  EXPECT_EQ(0,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(1)));\n  EXPECT_EQ(0,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::ZeroDuration()));\n  EXPECT_EQ(-1,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-1)));\n  EXPECT_EQ(-1,\n            absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-99)));\n  EXPECT_EQ(\n      -1, absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-100)));\n  EXPECT_EQ(\n      -2, absl::ToUniversal(absl::UniversalEpoch() + absl::Nanoseconds(-101)));\n\n  // Tests ToTimespec()/TimeFromTimespec()\n  const struct {\n    absl::Time t;\n    timespec ts;\n  } to_ts[] = {\n      {absl::FromUnixSeconds(1) + absl::Nanoseconds(1), {1, 1}},\n      {absl::FromUnixSeconds(1) + absl::Nanoseconds(1) / 2, {1, 0}},\n      {absl::FromUnixSeconds(1) + absl::ZeroDuration(), {1, 0}},\n      {absl::FromUnixSeconds(0) + absl::ZeroDuration(), {0, 0}},\n      {absl::FromUnixSeconds(0) - absl::Nanoseconds(1) / 2, {-1, 999999999}},\n      {absl::FromUnixSeconds(0) - absl::Nanoseconds(1), {-1, 999999999}},\n      {absl::FromUnixSeconds(-1) + absl::Nanoseconds(1), {-1, 1}},\n      {absl::FromUnixSeconds(-1) + absl::Nanoseconds(1) / 2, {-1, 0}},\n      {absl::FromUnixSeconds(-1) + absl::ZeroDuration(), {-1, 0}},\n      {absl::FromUnixSeconds(-1) - absl::Nanoseconds(1) / 2, {-2, 999999999}},\n  };\n  for (const auto& test : to_ts) {\n    EXPECT_THAT(absl::ToTimespec(test.t), TimespecMatcher(test.ts));\n  }\n  const struct {\n    timespec ts;\n    absl::Time t;\n  } from_ts[] = {\n      {{1, 1}, absl::FromUnixSeconds(1) + absl::Nanoseconds(1)},\n      {{1, 0}, absl::FromUnixSeconds(1) + absl::ZeroDuration()},\n      {{0, 0}, absl::FromUnixSeconds(0) + absl::ZeroDuration()},\n      {{0, -1}, absl::FromUnixSeconds(0) - absl::Nanoseconds(1)},\n      {{-1, 999999999}, absl::FromUnixSeconds(0) - absl::Nanoseconds(1)},\n      {{-1, 1}, absl::FromUnixSeconds(-1) + absl::Nanoseconds(1)},\n      {{-1, 0}, absl::FromUnixSeconds(-1) + absl::ZeroDuration()},\n      {{-1, -1}, absl::FromUnixSeconds(-1) - absl::Nanoseconds(1)},\n      {{-2, 999999999}, absl::FromUnixSeconds(-1) - absl::Nanoseconds(1)},\n  };\n  for (const auto& test : from_ts) {\n    EXPECT_EQ(test.t, absl::TimeFromTimespec(test.ts));\n  }\n\n  // Tests  absl::ToTimeval()/TimeFromTimeval() (same as timespec above)\n  const struct {\n    absl::Time t;\n    timeval tv;\n  } to_tv[] = {\n      {absl::FromUnixSeconds(1) + absl::Microseconds(1), {1, 1}},\n      {absl::FromUnixSeconds(1) + absl::Microseconds(1) / 2, {1, 0}},\n      {absl::FromUnixSeconds(1) + absl::ZeroDuration(), {1, 0}},\n      {absl::FromUnixSeconds(0) + absl::ZeroDuration(), {0, 0}},\n      {absl::FromUnixSeconds(0) - absl::Microseconds(1) / 2, {-1, 999999}},\n      {absl::FromUnixSeconds(0) - absl::Microseconds(1), {-1, 999999}},\n      {absl::FromUnixSeconds(-1) + absl::Microseconds(1), {-1, 1}},\n      {absl::FromUnixSeconds(-1) + absl::Microseconds(1) / 2, {-1, 0}},\n      {absl::FromUnixSeconds(-1) + absl::ZeroDuration(), {-1, 0}},\n      {absl::FromUnixSeconds(-1) - absl::Microseconds(1) / 2, {-2, 999999}},\n  };\n  for (const auto& test : to_tv) {\n    EXPECT_THAT(absl::ToTimeval(test.t), TimevalMatcher(test.tv));\n  }\n  const struct {\n    timeval tv;\n    absl::Time t;\n  } from_tv[] = {\n      {{1, 1}, absl::FromUnixSeconds(1) + absl::Microseconds(1)},\n      {{1, 0}, absl::FromUnixSeconds(1) + absl::ZeroDuration()},\n      {{0, 0}, absl::FromUnixSeconds(0) + absl::ZeroDuration()},\n      {{0, -1}, absl::FromUnixSeconds(0) - absl::Microseconds(1)},\n      {{-1, 999999}, absl::FromUnixSeconds(0) - absl::Microseconds(1)},\n      {{-1, 1}, absl::FromUnixSeconds(-1) + absl::Microseconds(1)},\n      {{-1, 0}, absl::FromUnixSeconds(-1) + absl::ZeroDuration()},\n      {{-1, -1}, absl::FromUnixSeconds(-1) - absl::Microseconds(1)},\n      {{-2, 999999}, absl::FromUnixSeconds(-1) - absl::Microseconds(1)},\n  };\n  for (const auto& test : from_tv) {\n    EXPECT_EQ(test.t, absl::TimeFromTimeval(test.tv));\n  }\n\n  // Tests flooring near negative infinity.\n  const int64_t min_plus_1 = std::numeric_limits<int64_t>::min() + 1;\n  EXPECT_EQ(min_plus_1, absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1)));\n  EXPECT_EQ(std::numeric_limits<int64_t>::min(),\n            absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1) -\n                                absl::Nanoseconds(1) / 2));\n\n  // Tests flooring near positive infinity.\n  EXPECT_EQ(std::numeric_limits<int64_t>::max(),\n            absl::ToUnixSeconds(\n                absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()) +\n                absl::Nanoseconds(1) / 2));\n  EXPECT_EQ(std::numeric_limits<int64_t>::max(),\n            absl::ToUnixSeconds(\n                absl::FromUnixSeconds(std::numeric_limits<int64_t>::max())));\n  EXPECT_EQ(std::numeric_limits<int64_t>::max() - 1,\n            absl::ToUnixSeconds(\n                absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()) -\n                absl::Nanoseconds(1) / 2));\n}\n\nTEST(Time, RoundtripConversion) {\n#define TEST_CONVERSION_ROUND_TRIP(SOURCE, FROM, TO, MATCHER) \\\n  EXPECT_THAT(TO(FROM(SOURCE)), MATCHER(SOURCE))\n\n  // FromUnixNanos() and ToUnixNanos()\n  int64_t now_ns = absl::GetCurrentTimeNanos();\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixNanos, absl::ToUnixNanos,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixNanos, absl::ToUnixNanos,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixNanos, absl::ToUnixNanos,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(now_ns, absl::FromUnixNanos, absl::ToUnixNanos,\n                             testing::Eq)\n      << now_ns;\n\n  // FromUnixMicros() and ToUnixMicros()\n  int64_t now_us = absl::GetCurrentTimeNanos() / 1000;\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixMicros, absl::ToUnixMicros,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixMicros, absl::ToUnixMicros,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixMicros, absl::ToUnixMicros,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(now_us, absl::FromUnixMicros, absl::ToUnixMicros,\n                             testing::Eq)\n      << now_us;\n\n  // FromUnixMillis() and ToUnixMillis()\n  int64_t now_ms = absl::GetCurrentTimeNanos() / 1000000;\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixMillis, absl::ToUnixMillis,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixMillis, absl::ToUnixMillis,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixMillis, absl::ToUnixMillis,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(now_ms, absl::FromUnixMillis, absl::ToUnixMillis,\n                             testing::Eq)\n      << now_ms;\n\n  // FromUnixSeconds() and ToUnixSeconds()\n  int64_t now_s = std::time(nullptr);\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUnixSeconds, absl::ToUnixSeconds,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromUnixSeconds, absl::ToUnixSeconds,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromUnixSeconds, absl::ToUnixSeconds,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(now_s, absl::FromUnixSeconds, absl::ToUnixSeconds,\n                             testing::Eq)\n      << now_s;\n\n  // FromTimeT() and ToTimeT()\n  time_t now_time_t = std::time(nullptr);\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromTimeT, absl::ToTimeT, testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromTimeT, absl::ToTimeT, testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromTimeT, absl::ToTimeT, testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(now_time_t, absl::FromTimeT, absl::ToTimeT,\n                             testing::Eq)\n      << now_time_t;\n\n  // TimeFromTimeval() and  absl::ToTimeval()\n  timeval tv;\n  tv.tv_sec = -1;\n  tv.tv_usec = 0;\n  TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval,\n                             TimevalMatcher);\n  tv.tv_sec = -1;\n  tv.tv_usec = 999999;\n  TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval,\n                             TimevalMatcher);\n  tv.tv_sec = 0;\n  tv.tv_usec = 0;\n  TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval,\n                             TimevalMatcher);\n  tv.tv_sec = 0;\n  tv.tv_usec = 1;\n  TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval,\n                             TimevalMatcher);\n  tv.tv_sec = 1;\n  tv.tv_usec = 0;\n  TEST_CONVERSION_ROUND_TRIP(tv, absl::TimeFromTimeval, absl::ToTimeval,\n                             TimevalMatcher);\n\n  // TimeFromTimespec() and ToTimespec()\n  timespec ts;\n  ts.tv_sec = -1;\n  ts.tv_nsec = 0;\n  TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec,\n                             TimespecMatcher);\n  ts.tv_sec = -1;\n  ts.tv_nsec = 999999999;\n  TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec,\n                             TimespecMatcher);\n  ts.tv_sec = 0;\n  ts.tv_nsec = 0;\n  TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec,\n                             TimespecMatcher);\n  ts.tv_sec = 0;\n  ts.tv_nsec = 1;\n  TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec,\n                             TimespecMatcher);\n  ts.tv_sec = 1;\n  ts.tv_nsec = 0;\n  TEST_CONVERSION_ROUND_TRIP(ts, absl::TimeFromTimespec, absl::ToTimespec,\n                             TimespecMatcher);\n\n  // FromUDate() and ToUDate()\n  double now_ud = absl::GetCurrentTimeNanos() / 1000000;\n  TEST_CONVERSION_ROUND_TRIP(-1.5, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(-0.5, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(0.5, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(1.5, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq);\n  TEST_CONVERSION_ROUND_TRIP(now_ud, absl::FromUDate, absl::ToUDate,\n                             testing::DoubleEq)\n      << std::fixed << std::setprecision(17) << now_ud;\n\n  // FromUniversal() and ToUniversal()\n  int64_t now_uni = ((719162LL * (24 * 60 * 60)) * (1000 * 1000 * 10)) +\n                    (absl::GetCurrentTimeNanos() / 100);\n  TEST_CONVERSION_ROUND_TRIP(-1, absl::FromUniversal, absl::ToUniversal,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(0, absl::FromUniversal, absl::ToUniversal,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(1, absl::FromUniversal, absl::ToUniversal,\n                             testing::Eq);\n  TEST_CONVERSION_ROUND_TRIP(now_uni, absl::FromUniversal, absl::ToUniversal,\n                             testing::Eq)\n      << now_uni;\n\n#undef TEST_CONVERSION_ROUND_TRIP\n}\n\ntemplate <typename Duration>\nstd::chrono::system_clock::time_point MakeChronoUnixTime(const Duration& d) {\n  return std::chrono::system_clock::from_time_t(0) + d;\n}\n\nTEST(Time, FromChrono) {\n  EXPECT_EQ(absl::FromTimeT(-1),\n            absl::FromChrono(std::chrono::system_clock::from_time_t(-1)));\n  EXPECT_EQ(absl::FromTimeT(0),\n            absl::FromChrono(std::chrono::system_clock::from_time_t(0)));\n  EXPECT_EQ(absl::FromTimeT(1),\n            absl::FromChrono(std::chrono::system_clock::from_time_t(1)));\n\n  EXPECT_EQ(\n      absl::FromUnixMillis(-1),\n      absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(-1))));\n  EXPECT_EQ(absl::FromUnixMillis(0),\n            absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(0))));\n  EXPECT_EQ(absl::FromUnixMillis(1),\n            absl::FromChrono(MakeChronoUnixTime(std::chrono::milliseconds(1))));\n\n  // Chrono doesn't define exactly its range and precision (neither does\n  // absl::Time), so let's simply test +/- ~100 years to make sure things work.\n  const auto century_sec = 60 * 60 * 24 * 365 * int64_t{100};\n  const auto century = std::chrono::seconds(century_sec);\n  const auto chrono_future = MakeChronoUnixTime(century);\n  const auto chrono_past = MakeChronoUnixTime(-century);\n  EXPECT_EQ(absl::FromUnixSeconds(century_sec),\n            absl::FromChrono(chrono_future));\n  EXPECT_EQ(absl::FromUnixSeconds(-century_sec), absl::FromChrono(chrono_past));\n\n  // Roundtrip them both back to chrono.\n  EXPECT_EQ(chrono_future,\n            absl::ToChronoTime(absl::FromUnixSeconds(century_sec)));\n  EXPECT_EQ(chrono_past,\n            absl::ToChronoTime(absl::FromUnixSeconds(-century_sec)));\n}\n\nTEST(Time, ToChronoTime) {\n  EXPECT_EQ(std::chrono::system_clock::from_time_t(-1),\n            absl::ToChronoTime(absl::FromTimeT(-1)));\n  EXPECT_EQ(std::chrono::system_clock::from_time_t(0),\n            absl::ToChronoTime(absl::FromTimeT(0)));\n  EXPECT_EQ(std::chrono::system_clock::from_time_t(1),\n            absl::ToChronoTime(absl::FromTimeT(1)));\n\n  EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(-1)),\n            absl::ToChronoTime(absl::FromUnixMillis(-1)));\n  EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(0)),\n            absl::ToChronoTime(absl::FromUnixMillis(0)));\n  EXPECT_EQ(MakeChronoUnixTime(std::chrono::milliseconds(1)),\n            absl::ToChronoTime(absl::FromUnixMillis(1)));\n\n  // Time before the Unix epoch should floor, not trunc.\n  const auto tick = absl::Nanoseconds(1) / 4;\n  EXPECT_EQ(std::chrono::system_clock::from_time_t(0) -\n                std::chrono::system_clock::duration(1),\n            absl::ToChronoTime(absl::UnixEpoch() - tick));\n}\n\n// Check that absl::int128 works as a std::chrono::duration representation.\nTEST(Time, Chrono128) {\n  // Define a std::chrono::time_point type whose time[sic]_since_epoch() is\n  // a signed 128-bit count of attoseconds. This has a range and resolution\n  // (currently) beyond those of absl::Time, and undoubtedly also beyond those\n  // of std::chrono::system_clock::time_point.\n  //\n  // Note: The to/from-chrono support should probably be updated to handle\n  // such wide representations.\n  using Timestamp =\n      std::chrono::time_point<std::chrono::system_clock,\n                              std::chrono::duration<absl::int128, std::atto>>;\n\n  // Expect that we can round-trip the std::chrono::system_clock::time_point\n  // extremes through both absl::Time and Timestamp, and that Timestamp can\n  // handle the (current) absl::Time extremes.\n  //\n  // Note: We should use std::chrono::floor() instead of time_point_cast(),\n  // but floor() is only available since c++17.\n  for (const auto tp : {std::chrono::system_clock::time_point::min(),\n                        std::chrono::system_clock::time_point::max()}) {\n    EXPECT_EQ(tp, absl::ToChronoTime(absl::FromChrono(tp)));\n    EXPECT_EQ(tp, std::chrono::time_point_cast<\n                      std::chrono::system_clock::time_point::duration>(\n                      std::chrono::time_point_cast<Timestamp::duration>(tp)));\n  }\n  Timestamp::duration::rep v = std::numeric_limits<int64_t>::min();\n  v *= Timestamp::duration::period::den;\n  auto ts = Timestamp(Timestamp::duration(v));\n  ts += std::chrono::duration<int64_t, std::atto>(0);\n  EXPECT_EQ(std::numeric_limits<int64_t>::min(),\n            ts.time_since_epoch().count() / Timestamp::duration::period::den);\n  EXPECT_EQ(0,\n            ts.time_since_epoch().count() % Timestamp::duration::period::den);\n  v = std::numeric_limits<int64_t>::max();\n  v *= Timestamp::duration::period::den;\n  ts = Timestamp(Timestamp::duration(v));\n  ts += std::chrono::duration<int64_t, std::atto>(999999999750000000);\n  EXPECT_EQ(std::numeric_limits<int64_t>::max(),\n            ts.time_since_epoch().count() / Timestamp::duration::period::den);\n  EXPECT_EQ(999999999750000000,\n            ts.time_since_epoch().count() % Timestamp::duration::period::den);\n}\n\nTEST(Time, TimeZoneAt) {\n  const absl::TimeZone nyc =\n      absl::time_internal::LoadTimeZone(\"America/New_York\");\n  const std::string fmt = \"%a, %e %b %Y %H:%M:%S %z (%Z)\";\n\n  // A non-transition where the civil time is unique.\n  absl::CivilSecond nov01(2013, 11, 1, 8, 30, 0);\n  const auto nov01_ci = nyc.At(nov01);\n  EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, nov01_ci.kind);\n  EXPECT_EQ(\"Fri,  1 Nov 2013 08:30:00 -0400 (EDT)\",\n            absl::FormatTime(fmt, nov01_ci.pre, nyc));\n  EXPECT_EQ(nov01_ci.pre, nov01_ci.trans);\n  EXPECT_EQ(nov01_ci.pre, nov01_ci.post);\n  EXPECT_EQ(nov01_ci.pre, absl::FromCivil(nov01, nyc));\n\n  // A Spring DST transition, when there is a gap in civil time\n  // and we prefer the later of the possible interpretations of a\n  // non-existent time.\n  absl::CivilSecond mar13(2011, 3, 13, 2, 15, 0);\n  const auto mar_ci = nyc.At(mar13);\n  EXPECT_EQ(absl::TimeZone::TimeInfo::SKIPPED, mar_ci.kind);\n  EXPECT_EQ(\"Sun, 13 Mar 2011 03:15:00 -0400 (EDT)\",\n            absl::FormatTime(fmt, mar_ci.pre, nyc));\n  EXPECT_EQ(\"Sun, 13 Mar 2011 03:00:00 -0400 (EDT)\",\n            absl::FormatTime(fmt, mar_ci.trans, nyc));\n  EXPECT_EQ(\"Sun, 13 Mar 2011 01:15:00 -0500 (EST)\",\n            absl::FormatTime(fmt, mar_ci.post, nyc));\n  EXPECT_EQ(mar_ci.trans, absl::FromCivil(mar13, nyc));\n\n  // A Fall DST transition, when civil times are repeated and\n  // we prefer the earlier of the possible interpretations of an\n  // ambiguous time.\n  absl::CivilSecond nov06(2011, 11, 6, 1, 15, 0);\n  const auto nov06_ci = nyc.At(nov06);\n  EXPECT_EQ(absl::TimeZone::TimeInfo::REPEATED, nov06_ci.kind);\n  EXPECT_EQ(\"Sun,  6 Nov 2011 01:15:00 -0400 (EDT)\",\n            absl::FormatTime(fmt, nov06_ci.pre, nyc));\n  EXPECT_EQ(\"Sun,  6 Nov 2011 01:00:00 -0500 (EST)\",\n            absl::FormatTime(fmt, nov06_ci.trans, nyc));\n  EXPECT_EQ(\"Sun,  6 Nov 2011 01:15:00 -0500 (EST)\",\n            absl::FormatTime(fmt, nov06_ci.post, nyc));\n  EXPECT_EQ(nov06_ci.pre, absl::FromCivil(nov06, nyc));\n\n  // Check that (time_t) -1 is handled correctly.\n  absl::CivilSecond minus1(1969, 12, 31, 18, 59, 59);\n  const auto minus1_cl = nyc.At(minus1);\n  EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, minus1_cl.kind);\n  EXPECT_EQ(-1, absl::ToTimeT(minus1_cl.pre));\n  EXPECT_EQ(\"Wed, 31 Dec 1969 18:59:59 -0500 (EST)\",\n            absl::FormatTime(fmt, minus1_cl.pre, nyc));\n  EXPECT_EQ(\"Wed, 31 Dec 1969 23:59:59 +0000 (UTC)\",\n            absl::FormatTime(fmt, minus1_cl.pre, absl::UTCTimeZone()));\n}\n\n// FromCivil(CivilSecond(year, mon, day, hour, min, sec), UTCTimeZone())\n// has a specialized fastpath implementation, which we exercise here.\nTEST(Time, FromCivilUTC) {\n  const absl::TimeZone utc = absl::UTCTimeZone();\n  const std::string fmt = \"%a, %e %b %Y %H:%M:%S %z (%Z)\";\n  const int kMax = std::numeric_limits<int>::max();\n  const int kMin = std::numeric_limits<int>::min();\n  absl::Time t;\n\n  // 292091940881 is the last positive year to use the fastpath.\n  t = absl::FromCivil(\n      absl::CivilSecond(292091940881, kMax, kMax, kMax, kMax, kMax), utc);\n  EXPECT_EQ(\"Fri, 25 Nov 292277026596 12:21:07 +0000 (UTC)\",\n            absl::FormatTime(fmt, t, utc));\n  t = absl::FromCivil(\n      absl::CivilSecond(292091940882, kMax, kMax, kMax, kMax, kMax), utc);\n  EXPECT_EQ(\"infinite-future\", absl::FormatTime(fmt, t, utc));  // no overflow\n\n  // -292091936940 is the last negative year to use the fastpath.\n  t = absl::FromCivil(\n      absl::CivilSecond(-292091936940, kMin, kMin, kMin, kMin, kMin), utc);\n  EXPECT_EQ(\"Fri,  1 Nov -292277022657 10:37:52 +0000 (UTC)\",\n            absl::FormatTime(fmt, t, utc));\n  t = absl::FromCivil(\n      absl::CivilSecond(-292091936941, kMin, kMin, kMin, kMin, kMin), utc);\n  EXPECT_EQ(\"infinite-past\", absl::FormatTime(fmt, t, utc));  // no underflow\n\n  // Check that we're counting leap years correctly.\n  t = absl::FromCivil(absl::CivilSecond(1900, 2, 28, 23, 59, 59), utc);\n  EXPECT_EQ(\"Wed, 28 Feb 1900 23:59:59 +0000 (UTC)\",\n            absl::FormatTime(fmt, t, utc));\n  t = absl::FromCivil(absl::CivilSecond(1900, 3, 1, 0, 0, 0), utc);\n  EXPECT_EQ(\"Thu,  1 Mar 1900 00:00:00 +0000 (UTC)\",\n            absl::FormatTime(fmt, t, utc));\n  t = absl::FromCivil(absl::CivilSecond(2000, 2, 29, 23, 59, 59), utc);\n  EXPECT_EQ(\"Tue, 29 Feb 2000 23:59:59 +0000 (UTC)\",\n            absl::FormatTime(fmt, t, utc));\n  t = absl::FromCivil(absl::CivilSecond(2000, 3, 1, 0, 0, 0), utc);\n  EXPECT_EQ(\"Wed,  1 Mar 2000 00:00:00 +0000 (UTC)\",\n            absl::FormatTime(fmt, t, utc));\n}\n\nTEST(Time, ToTM) {\n  const absl::TimeZone utc = absl::UTCTimeZone();\n\n  // Compares the results of absl::ToTM() to gmtime_r() for lots of times over\n  // the course of a few days.\n  const absl::Time start =\n      absl::FromCivil(absl::CivilSecond(2014, 1, 2, 3, 4, 5), utc);\n  const absl::Time end =\n      absl::FromCivil(absl::CivilSecond(2014, 1, 5, 3, 4, 5), utc);\n  for (absl::Time t = start; t < end; t += absl::Seconds(30)) {\n    const struct tm tm_bt = absl::ToTM(t, utc);\n    const time_t tt = absl::ToTimeT(t);\n    struct tm tm_lc;\n#ifdef _WIN32\n    gmtime_s(&tm_lc, &tt);\n#else\n    gmtime_r(&tt, &tm_lc);\n#endif\n    EXPECT_EQ(tm_lc.tm_year, tm_bt.tm_year);\n    EXPECT_EQ(tm_lc.tm_mon, tm_bt.tm_mon);\n    EXPECT_EQ(tm_lc.tm_mday, tm_bt.tm_mday);\n    EXPECT_EQ(tm_lc.tm_hour, tm_bt.tm_hour);\n    EXPECT_EQ(tm_lc.tm_min, tm_bt.tm_min);\n    EXPECT_EQ(tm_lc.tm_sec, tm_bt.tm_sec);\n    EXPECT_EQ(tm_lc.tm_wday, tm_bt.tm_wday);\n    EXPECT_EQ(tm_lc.tm_yday, tm_bt.tm_yday);\n    EXPECT_EQ(tm_lc.tm_isdst, tm_bt.tm_isdst);\n\n    ASSERT_FALSE(HasFailure());\n  }\n\n  // Checks that the tm_isdst field is correct when in standard time.\n  const absl::TimeZone nyc =\n      absl::time_internal::LoadTimeZone(\"America/New_York\");\n  absl::Time t = absl::FromCivil(absl::CivilSecond(2014, 3, 1, 0, 0, 0), nyc);\n  struct tm tm = absl::ToTM(t, nyc);\n  EXPECT_FALSE(tm.tm_isdst);\n\n  // Checks that the tm_isdst field is correct when in daylight time.\n  t = absl::FromCivil(absl::CivilSecond(2014, 4, 1, 0, 0, 0), nyc);\n  tm = absl::ToTM(t, nyc);\n  EXPECT_TRUE(tm.tm_isdst);\n\n  // Checks overflow.\n  tm = absl::ToTM(absl::InfiniteFuture(), nyc);\n  EXPECT_EQ(std::numeric_limits<int>::max() - 1900, tm.tm_year);\n  EXPECT_EQ(11, tm.tm_mon);\n  EXPECT_EQ(31, tm.tm_mday);\n  EXPECT_EQ(23, tm.tm_hour);\n  EXPECT_EQ(59, tm.tm_min);\n  EXPECT_EQ(59, tm.tm_sec);\n  EXPECT_EQ(4, tm.tm_wday);\n  EXPECT_EQ(364, tm.tm_yday);\n  EXPECT_FALSE(tm.tm_isdst);\n\n  // Checks underflow.\n  tm = absl::ToTM(absl::InfinitePast(), nyc);\n  EXPECT_EQ(std::numeric_limits<int>::min(), tm.tm_year);\n  EXPECT_EQ(0, tm.tm_mon);\n  EXPECT_EQ(1, tm.tm_mday);\n  EXPECT_EQ(0, tm.tm_hour);\n  EXPECT_EQ(0, tm.tm_min);\n  EXPECT_EQ(0, tm.tm_sec);\n  EXPECT_EQ(0, tm.tm_wday);\n  EXPECT_EQ(0, tm.tm_yday);\n  EXPECT_FALSE(tm.tm_isdst);\n}\n\nTEST(Time, FromTM) {\n  const absl::TimeZone nyc =\n      absl::time_internal::LoadTimeZone(\"America/New_York\");\n\n  // Verifies that tm_isdst doesn't affect anything when the time is unique.\n  struct tm tm;\n  std::memset(&tm, 0, sizeof(tm));\n  tm.tm_year = 2014 - 1900;\n  tm.tm_mon = 6 - 1;\n  tm.tm_mday = 28;\n  tm.tm_hour = 1;\n  tm.tm_min = 2;\n  tm.tm_sec = 3;\n  tm.tm_isdst = -1;\n  absl::Time t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-06-28T01:02:03-04:00\", absl::FormatTime(t, nyc));  // DST\n  tm.tm_isdst = 0;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-06-28T01:02:03-04:00\", absl::FormatTime(t, nyc));  // DST\n  tm.tm_isdst = 1;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-06-28T01:02:03-04:00\", absl::FormatTime(t, nyc));  // DST\n\n  // Adjusts tm to refer to an ambiguous time.\n  tm.tm_year = 2014 - 1900;\n  tm.tm_mon = 11 - 1;\n  tm.tm_mday = 2;\n  tm.tm_hour = 1;\n  tm.tm_min = 30;\n  tm.tm_sec = 42;\n  tm.tm_isdst = -1;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-11-02T01:30:42-04:00\", absl::FormatTime(t, nyc));  // DST\n  tm.tm_isdst = 0;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-11-02T01:30:42-05:00\", absl::FormatTime(t, nyc));  // STD\n  tm.tm_isdst = 1;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-11-02T01:30:42-04:00\", absl::FormatTime(t, nyc));  // DST\n\n  // Adjusts tm to refer to a skipped time.\n  tm.tm_year = 2014 - 1900;\n  tm.tm_mon = 3 - 1;\n  tm.tm_mday = 9;\n  tm.tm_hour = 2;\n  tm.tm_min = 30;\n  tm.tm_sec = 42;\n  tm.tm_isdst = -1;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-03-09T03:30:42-04:00\", absl::FormatTime(t, nyc));  // DST\n  tm.tm_isdst = 0;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-03-09T01:30:42-05:00\", absl::FormatTime(t, nyc));  // STD\n  tm.tm_isdst = 1;\n  t = absl::FromTM(tm, nyc);\n  EXPECT_EQ(\"2014-03-09T03:30:42-04:00\", absl::FormatTime(t, nyc));  // DST\n\n  // Adjusts tm to refer to a time with a year larger than 2147483647.\n  tm.tm_year = 2147483647 - 1900 + 1;\n  tm.tm_mon = 6 - 1;\n  tm.tm_mday = 28;\n  tm.tm_hour = 1;\n  tm.tm_min = 2;\n  tm.tm_sec = 3;\n  tm.tm_isdst = -1;\n  t = absl::FromTM(tm, absl::UTCTimeZone());\n  EXPECT_EQ(\"2147483648-06-28T01:02:03+00:00\",\n            absl::FormatTime(t, absl::UTCTimeZone()));\n\n  // Adjusts tm to refer to a time with a very large month.\n  tm.tm_year = 2019 - 1900;\n  tm.tm_mon = 2147483647;\n  tm.tm_mday = 28;\n  tm.tm_hour = 1;\n  tm.tm_min = 2;\n  tm.tm_sec = 3;\n  tm.tm_isdst = -1;\n  t = absl::FromTM(tm, absl::UTCTimeZone());\n  EXPECT_EQ(\"178958989-08-28T01:02:03+00:00\",\n            absl::FormatTime(t, absl::UTCTimeZone()));\n}\n\nTEST(Time, TMRoundTrip) {\n  const absl::TimeZone nyc =\n      absl::time_internal::LoadTimeZone(\"America/New_York\");\n\n  // Test round-tripping across a skipped transition\n  absl::Time start = absl::FromCivil(absl::CivilHour(2014, 3, 9, 0), nyc);\n  absl::Time end = absl::FromCivil(absl::CivilHour(2014, 3, 9, 4), nyc);\n  for (absl::Time t = start; t < end; t += absl::Minutes(1)) {\n    struct tm tm = absl::ToTM(t, nyc);\n    absl::Time rt = absl::FromTM(tm, nyc);\n    EXPECT_EQ(rt, t);\n  }\n\n  // Test round-tripping across an ambiguous transition\n  start = absl::FromCivil(absl::CivilHour(2014, 11, 2, 0), nyc);\n  end = absl::FromCivil(absl::CivilHour(2014, 11, 2, 4), nyc);\n  for (absl::Time t = start; t < end; t += absl::Minutes(1)) {\n    struct tm tm = absl::ToTM(t, nyc);\n    absl::Time rt = absl::FromTM(tm, nyc);\n    EXPECT_EQ(rt, t);\n  }\n\n  // Test round-tripping of unique instants crossing a day boundary\n  start = absl::FromCivil(absl::CivilHour(2014, 6, 27, 22), nyc);\n  end = absl::FromCivil(absl::CivilHour(2014, 6, 28, 4), nyc);\n  for (absl::Time t = start; t < end; t += absl::Minutes(1)) {\n    struct tm tm = absl::ToTM(t, nyc);\n    absl::Time rt = absl::FromTM(tm, nyc);\n    EXPECT_EQ(rt, t);\n  }\n}\n\nTEST(Time, Range) {\n  // The API's documented range is +/- 100 billion years.\n  const absl::Duration range = absl::Hours(24) * 365.2425 * 100000000000;\n\n  // Arithmetic and comparison still works at +/-range around base values.\n  absl::Time bases[2] = {absl::UnixEpoch(), absl::Now()};\n  for (const auto base : bases) {\n    absl::Time bottom = base - range;\n    EXPECT_GT(bottom, bottom - absl::Nanoseconds(1));\n    EXPECT_LT(bottom, bottom + absl::Nanoseconds(1));\n    absl::Time top = base + range;\n    EXPECT_GT(top, top - absl::Nanoseconds(1));\n    EXPECT_LT(top, top + absl::Nanoseconds(1));\n    absl::Duration full_range = 2 * range;\n    EXPECT_EQ(full_range, top - bottom);\n    EXPECT_EQ(-full_range, bottom - top);\n  }\n}\n\nTEST(Time, Limits) {\n  // It is an implementation detail that Time().rep_ == ZeroDuration(),\n  // and that the resolution of a Duration is 1/4 of a nanosecond.\n  const absl::Time zero;\n  const absl::Time max =\n      zero + absl::Seconds(std::numeric_limits<int64_t>::max()) +\n      absl::Nanoseconds(999999999) + absl::Nanoseconds(3) / 4;\n  const absl::Time min =\n      zero + absl::Seconds(std::numeric_limits<int64_t>::min());\n\n  // Some simple max/min bounds checks.\n  EXPECT_LT(max, absl::InfiniteFuture());\n  EXPECT_GT(min, absl::InfinitePast());\n  EXPECT_LT(zero, max);\n  EXPECT_GT(zero, min);\n  EXPECT_GE(absl::UnixEpoch(), min);\n  EXPECT_LT(absl::UnixEpoch(), max);\n\n  // Check sign of Time differences.\n  EXPECT_LT(absl::ZeroDuration(), max - zero);\n  EXPECT_LT(absl::ZeroDuration(),\n            zero - absl::Nanoseconds(1) / 4 - min);  // avoid zero - min\n\n  // Arithmetic works at max - 0.25ns and min + 0.25ns.\n  EXPECT_GT(max, max - absl::Nanoseconds(1) / 4);\n  EXPECT_LT(min, min + absl::Nanoseconds(1) / 4);\n}\n\nTEST(Time, ConversionSaturation) {\n  const absl::TimeZone utc = absl::UTCTimeZone();\n  absl::Time t;\n\n  const auto max_time_t = std::numeric_limits<time_t>::max();\n  const auto min_time_t = std::numeric_limits<time_t>::min();\n  time_t tt = max_time_t - 1;\n  t = absl::FromTimeT(tt);\n  tt = absl::ToTimeT(t);\n  EXPECT_EQ(max_time_t - 1, tt);\n  t += absl::Seconds(1);\n  tt = absl::ToTimeT(t);\n  EXPECT_EQ(max_time_t, tt);\n  t += absl::Seconds(1);  // no effect\n  tt = absl::ToTimeT(t);\n  EXPECT_EQ(max_time_t, tt);\n\n  tt = min_time_t + 1;\n  t = absl::FromTimeT(tt);\n  tt = absl::ToTimeT(t);\n  EXPECT_EQ(min_time_t + 1, tt);\n  t -= absl::Seconds(1);\n  tt = absl::ToTimeT(t);\n  EXPECT_EQ(min_time_t, tt);\n  t -= absl::Seconds(1);  // no effect\n  tt = absl::ToTimeT(t);\n  EXPECT_EQ(min_time_t, tt);\n\n  const auto max_timeval_sec =\n      std::numeric_limits<decltype(timeval::tv_sec)>::max();\n  const auto min_timeval_sec =\n      std::numeric_limits<decltype(timeval::tv_sec)>::min();\n  timeval tv;\n  tv.tv_sec = max_timeval_sec;\n  tv.tv_usec = 999998;\n  t = absl::TimeFromTimeval(tv);\n  tv = absl::ToTimeval(t);\n  EXPECT_EQ(max_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(999998, tv.tv_usec);\n  t += absl::Microseconds(1);\n  tv = absl::ToTimeval(t);\n  EXPECT_EQ(max_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(999999, tv.tv_usec);\n  t += absl::Microseconds(1);  // no effect\n  tv = absl::ToTimeval(t);\n  EXPECT_EQ(max_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(999999, tv.tv_usec);\n\n  tv.tv_sec = min_timeval_sec;\n  tv.tv_usec = 1;\n  t = absl::TimeFromTimeval(tv);\n  tv = absl::ToTimeval(t);\n  EXPECT_EQ(min_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(1, tv.tv_usec);\n  t -= absl::Microseconds(1);\n  tv = absl::ToTimeval(t);\n  EXPECT_EQ(min_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(0, tv.tv_usec);\n  t -= absl::Microseconds(1);  // no effect\n  tv = absl::ToTimeval(t);\n  EXPECT_EQ(min_timeval_sec, tv.tv_sec);\n  EXPECT_EQ(0, tv.tv_usec);\n\n  const auto max_timespec_sec =\n      std::numeric_limits<decltype(timespec::tv_sec)>::max();\n  const auto min_timespec_sec =\n      std::numeric_limits<decltype(timespec::tv_sec)>::min();\n  timespec ts;\n  ts.tv_sec = max_timespec_sec;\n  ts.tv_nsec = 999999998;\n  t = absl::TimeFromTimespec(ts);\n  ts = absl::ToTimespec(t);\n  EXPECT_EQ(max_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(999999998, ts.tv_nsec);\n  t += absl::Nanoseconds(1);\n  ts = absl::ToTimespec(t);\n  EXPECT_EQ(max_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(999999999, ts.tv_nsec);\n  t += absl::Nanoseconds(1);  // no effect\n  ts = absl::ToTimespec(t);\n  EXPECT_EQ(max_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(999999999, ts.tv_nsec);\n\n  ts.tv_sec = min_timespec_sec;\n  ts.tv_nsec = 1;\n  t = absl::TimeFromTimespec(ts);\n  ts = absl::ToTimespec(t);\n  EXPECT_EQ(min_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(1, ts.tv_nsec);\n  t -= absl::Nanoseconds(1);\n  ts = absl::ToTimespec(t);\n  EXPECT_EQ(min_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(0, ts.tv_nsec);\n  t -= absl::Nanoseconds(1);  // no effect\n  ts = absl::ToTimespec(t);\n  EXPECT_EQ(min_timespec_sec, ts.tv_sec);\n  EXPECT_EQ(0, ts.tv_nsec);\n\n  // Checks how TimeZone::At() saturates on infinities.\n  auto ci = utc.At(absl::InfiniteFuture());\n  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59,\n                    0, false);\n  EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond);\n  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs));\n  EXPECT_EQ(365, absl::GetYearDay(ci.cs));\n  EXPECT_STREQ(\"-00\", ci.zone_abbr);  // artifact of TimeZone::At()\n  ci = utc.At(absl::InfinitePast());\n  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0, 0, 0,\n                    false);\n  EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond);\n  EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(ci.cs));\n  EXPECT_EQ(1, absl::GetYearDay(ci.cs));\n  EXPECT_STREQ(\"-00\", ci.zone_abbr);  // artifact of TimeZone::At()\n\n  // Approach the maximal Time value from below.\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 6), utc);\n  EXPECT_EQ(\"292277026596-12-04T15:30:06+00:00\",\n            absl::FormatTime(absl::RFC3339_full, t, utc));\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 7), utc);\n  EXPECT_EQ(\"292277026596-12-04T15:30:07+00:00\",\n            absl::FormatTime(absl::RFC3339_full, t, utc));\n  EXPECT_EQ(\n      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),\n      t);\n\n  // Checks that we can also get the maximal Time value for a far-east zone.\n  const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60);\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 5, 30, 7), plus14);\n  EXPECT_EQ(\"292277026596-12-05T05:30:07+14:00\",\n            absl::FormatTime(absl::RFC3339_full, t, plus14));\n  EXPECT_EQ(\n      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),\n      t);\n\n  // One second later should push us to infinity.\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc);\n  EXPECT_EQ(\"infinite-future\", absl::FormatTime(absl::RFC3339_full, t, utc));\n\n  // Approach the minimal Time value from above.\n  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 53), utc);\n  EXPECT_EQ(\"-292277022657-01-27T08:29:53+00:00\",\n            absl::FormatTime(absl::RFC3339_full, t, utc));\n  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 52), utc);\n  EXPECT_EQ(\"-292277022657-01-27T08:29:52+00:00\",\n            absl::FormatTime(absl::RFC3339_full, t, utc));\n  EXPECT_EQ(\n      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),\n      t);\n\n  // Checks that we can also get the minimal Time value for a far-west zone.\n  const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60);\n  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 26, 20, 29, 52),\n                      minus12);\n  EXPECT_EQ(\"-292277022657-01-26T20:29:52-12:00\",\n            absl::FormatTime(absl::RFC3339_full, t, minus12));\n  EXPECT_EQ(\n      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),\n      t);\n\n  // One second before should push us to -infinity.\n  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc);\n  EXPECT_EQ(\"infinite-past\", absl::FormatTime(absl::RFC3339_full, t, utc));\n}\n\n// In zones with POSIX-style recurring rules we use special logic to\n// handle conversions in the distant future.  Here we check the limits\n// of those conversions, particularly with respect to integer overflow.\nTEST(Time, ExtendedConversionSaturation) {\n  const absl::TimeZone syd =\n      absl::time_internal::LoadTimeZone(\"Australia/Sydney\");\n  const absl::TimeZone nyc =\n      absl::time_internal::LoadTimeZone(\"America/New_York\");\n  const absl::Time max =\n      absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());\n  absl::TimeZone::CivilInfo ci;\n  absl::Time t;\n\n  // The maximal time converted in each zone.\n  ci = syd.At(max);\n  EXPECT_CIVIL_INFO(ci, 292277026596, 12, 5, 2, 30, 7, 39600, true);\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 7), syd);\n  EXPECT_EQ(max, t);\n  ci = nyc.At(max);\n  EXPECT_CIVIL_INFO(ci, 292277026596, 12, 4, 10, 30, 7, -18000, false);\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 7), nyc);\n  EXPECT_EQ(max, t);\n\n  // One second later should push us to infinity.\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 8), syd);\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 8), nyc);\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n\n  // And we should stick there.\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 9), syd);\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 9), nyc);\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n\n  // All the way up to a saturated date/time, without overflow.\n  t = absl::FromCivil(absl::CivilSecond::max(), syd);\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n  t = absl::FromCivil(absl::CivilSecond::max(), nyc);\n  EXPECT_EQ(absl::InfiniteFuture(), t);\n}\n\nTEST(Time, FromCivilAlignment) {\n  const absl::TimeZone utc = absl::UTCTimeZone();\n  const absl::CivilSecond cs(2015, 2, 3, 4, 5, 6);\n  absl::Time t = absl::FromCivil(cs, utc);\n  EXPECT_EQ(\"2015-02-03T04:05:06+00:00\", absl::FormatTime(t, utc));\n  t = absl::FromCivil(absl::CivilMinute(cs), utc);\n  EXPECT_EQ(\"2015-02-03T04:05:00+00:00\", absl::FormatTime(t, utc));\n  t = absl::FromCivil(absl::CivilHour(cs), utc);\n  EXPECT_EQ(\"2015-02-03T04:00:00+00:00\", absl::FormatTime(t, utc));\n  t = absl::FromCivil(absl::CivilDay(cs), utc);\n  EXPECT_EQ(\"2015-02-03T00:00:00+00:00\", absl::FormatTime(t, utc));\n  t = absl::FromCivil(absl::CivilMonth(cs), utc);\n  EXPECT_EQ(\"2015-02-01T00:00:00+00:00\", absl::FormatTime(t, utc));\n  t = absl::FromCivil(absl::CivilYear(cs), utc);\n  EXPECT_EQ(\"2015-01-01T00:00:00+00:00\", absl::FormatTime(t, utc));\n}\n\nTEST(Time, LegacyDateTime) {\n  const absl::TimeZone utc = absl::UTCTimeZone();\n  const std::string ymdhms = \"%Y-%m-%d %H:%M:%S\";\n  const int kMax = std::numeric_limits<int>::max();\n  const int kMin = std::numeric_limits<int>::min();\n  absl::Time t;\n\n  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(), kMax,\n                         kMax, kMax, kMax, kMax, utc);\n  EXPECT_EQ(\"infinite-future\",\n            absl::FormatTime(ymdhms, t, utc));  // no overflow\n  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(), kMin,\n                         kMin, kMin, kMin, kMin, utc);\n  EXPECT_EQ(\"infinite-past\", absl::FormatTime(ymdhms, t, utc));  // no overflow\n\n  // Check normalization.\n  EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized);\n  t = absl::FromDateTime(2015, 1, 1, 0, 0, 60, utc);\n  EXPECT_EQ(\"2015-01-01 00:01:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, 1, 0, 60, 0, utc);\n  EXPECT_EQ(\"2015-01-01 01:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, 1, 24, 0, 0, utc);\n  EXPECT_EQ(\"2015-01-02 00:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, 32, 0, 0, 0, utc);\n  EXPECT_EQ(\"2015-02-01 00:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 13, 1, 0, 0, 0, utc);\n  EXPECT_EQ(\"2016-01-01 00:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 13, 32, 60, 60, 60, utc);\n  EXPECT_EQ(\"2016-02-03 13:01:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, 1, 0, 0, -1, utc);\n  EXPECT_EQ(\"2014-12-31 23:59:59\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, 1, 0, -1, 0, utc);\n  EXPECT_EQ(\"2014-12-31 23:59:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, 1, -1, 0, 0, utc);\n  EXPECT_EQ(\"2014-12-31 23:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, 1, -1, 0, 0, 0, utc);\n  EXPECT_EQ(\"2014-12-30 00:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, -1, 1, 0, 0, 0, utc);\n  EXPECT_EQ(\"2014-11-01 00:00:00\", absl::FormatTime(ymdhms, t, utc));\n  t = absl::FromDateTime(2015, -1, -1, -1, -1, -1, utc);\n  EXPECT_EQ(\"2014-10-29 22:58:59\", absl::FormatTime(ymdhms, t, utc));\n}\n\nTEST(Time, NextTransitionUTC) {\n  const auto tz = absl::UTCTimeZone();\n  absl::TimeZone::CivilTransition trans;\n\n  auto t = absl::InfinitePast();\n  EXPECT_FALSE(tz.NextTransition(t, &trans));\n\n  t = absl::InfiniteFuture();\n  EXPECT_FALSE(tz.NextTransition(t, &trans));\n}\n\nTEST(Time, PrevTransitionUTC) {\n  const auto tz = absl::UTCTimeZone();\n  absl::TimeZone::CivilTransition trans;\n\n  auto t = absl::InfiniteFuture();\n  EXPECT_FALSE(tz.PrevTransition(t, &trans));\n\n  t = absl::InfinitePast();\n  EXPECT_FALSE(tz.PrevTransition(t, &trans));\n}\n\nTEST(Time, NextTransitionNYC) {\n  const auto tz = absl::time_internal::LoadTimeZone(\"America/New_York\");\n  absl::TimeZone::CivilTransition trans;\n\n  auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz);\n  EXPECT_TRUE(tz.NextTransition(t, &trans));\n  EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 2, 0, 0), trans.from);\n  EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 1, 0, 0), trans.to);\n\n  t = absl::InfiniteFuture();\n  EXPECT_FALSE(tz.NextTransition(t, &trans));\n\n  t = absl::InfinitePast();\n  EXPECT_TRUE(tz.NextTransition(t, &trans));\n  if (trans.from == absl::CivilSecond(1918, 03, 31, 2, 0, 0)) {\n    // It looks like the tzdata is only 32 bit (probably macOS),\n    // which bottoms out at 1901-12-13T20:45:52+00:00.\n    EXPECT_EQ(absl::CivilSecond(1918, 3, 31, 3, 0, 0), trans.to);\n  } else {\n    EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 3, 58), trans.from);\n    EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 0, 0), trans.to);\n  }\n}\n\nTEST(Time, PrevTransitionNYC) {\n  const auto tz = absl::time_internal::LoadTimeZone(\"America/New_York\");\n  absl::TimeZone::CivilTransition trans;\n\n  auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz);\n  EXPECT_TRUE(tz.PrevTransition(t, &trans));\n  EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 2, 0, 0), trans.from);\n  EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 3, 0, 0), trans.to);\n\n  t = absl::InfinitePast();\n  EXPECT_FALSE(tz.PrevTransition(t, &trans));\n\n  t = absl::InfiniteFuture();\n  EXPECT_TRUE(tz.PrevTransition(t, &trans));\n  // We have a transition but we don't know which one.\n}\n\nTEST(Time, AbslStringify) {\n  // FormatTime is already well tested, so just use one test case here to\n  // verify that StrFormat(\"%v\", t) works as expected.\n  absl::Time t = absl::Now();\n  EXPECT_EQ(absl::StrFormat(\"%v\", t), absl::FormatTime(t));\n}\n\nTEST(Time, SupportsHash) {\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::UTCTimeZone(),\n      absl::FixedTimeZone(-8 * 60 * 60),\n      absl::UTCTimeZone(),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::Now(),\n      absl::UnixEpoch(),\n      absl::UnixEpoch() + absl::Seconds(60),\n      absl::UnixEpoch() + absl::Minutes(1),\n      absl::InfiniteFuture(),\n      absl::InfinitePast(),\n  }));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      absl::Seconds(1),\n      absl::Seconds(60),\n      absl::Minutes(1),\n      absl::InfiniteDuration(),\n      -absl::InfiniteDuration(),\n  }));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/time/time_zone_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/time/internal/cctz/include/cctz/time_zone.h\"\n\n#include \"gtest/gtest.h\"\n#include \"absl/time/internal/test_util.h\"\n#include \"absl/time/time.h\"\n\nnamespace cctz = absl::time_internal::cctz;\n\nnamespace {\n\nTEST(TimeZone, ValueSemantics) {\n  absl::TimeZone tz;\n  absl::TimeZone tz2 = tz;  // Copy-construct\n  EXPECT_EQ(tz, tz2);\n  tz2 = tz;  // Copy-assign\n  EXPECT_EQ(tz, tz2);\n}\n\nTEST(TimeZone, Equality) {\n  absl::TimeZone a, b;\n  EXPECT_EQ(a, b);\n  EXPECT_EQ(a.name(), b.name());\n\n  absl::TimeZone implicit_utc;\n  absl::TimeZone explicit_utc = absl::UTCTimeZone();\n  EXPECT_EQ(implicit_utc, explicit_utc);\n  EXPECT_EQ(implicit_utc.name(), explicit_utc.name());\n\n  absl::TimeZone la = absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  absl::TimeZone nyc = absl::time_internal::LoadTimeZone(\"America/New_York\");\n  EXPECT_NE(la, nyc);\n}\n\nTEST(TimeZone, CCTZConversion) {\n  const cctz::time_zone cz = cctz::utc_time_zone();\n  const absl::TimeZone tz(cz);\n  EXPECT_EQ(cz, cctz::time_zone(tz));\n}\n\nTEST(TimeZone, DefaultTimeZones) {\n  absl::TimeZone tz;\n  EXPECT_EQ(\"UTC\", absl::TimeZone().name());\n  EXPECT_EQ(\"UTC\", absl::UTCTimeZone().name());\n}\n\nTEST(TimeZone, FixedTimeZone) {\n  const absl::TimeZone tz = absl::FixedTimeZone(123);\n  const cctz::time_zone cz = cctz::fixed_time_zone(cctz::seconds(123));\n  EXPECT_EQ(tz, absl::TimeZone(cz));\n}\n\nTEST(TimeZone, LocalTimeZone) {\n  const absl::TimeZone local_tz = absl::LocalTimeZone();\n  absl::TimeZone tz = absl::time_internal::LoadTimeZone(\"localtime\");\n  EXPECT_EQ(tz, local_tz);\n}\n\nTEST(TimeZone, NamedTimeZones) {\n  absl::TimeZone nyc = absl::time_internal::LoadTimeZone(\"America/New_York\");\n  EXPECT_EQ(\"America/New_York\", nyc.name());\n  absl::TimeZone syd = absl::time_internal::LoadTimeZone(\"Australia/Sydney\");\n  EXPECT_EQ(\"Australia/Sydney\", syd.name());\n  absl::TimeZone fixed = absl::FixedTimeZone((((3 * 60) + 25) * 60) + 45);\n  EXPECT_EQ(\"Fixed/UTC+03:25:45\", fixed.name());\n}\n\nTEST(TimeZone, Failures) {\n  absl::TimeZone tz = absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  EXPECT_FALSE(LoadTimeZone(\"Invalid/TimeZone\", &tz));\n  EXPECT_EQ(absl::UTCTimeZone(), tz);  // guaranteed fallback to UTC\n\n  // Ensures that the load still fails on a subsequent attempt.\n  tz = absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  EXPECT_FALSE(LoadTimeZone(\"Invalid/TimeZone\", &tz));\n  EXPECT_EQ(absl::UTCTimeZone(), tz);  // guaranteed fallback to UTC\n\n  // Loading an empty string timezone should fail.\n  tz = absl::time_internal::LoadTimeZone(\"America/Los_Angeles\");\n  EXPECT_FALSE(LoadTimeZone(\"\", &tz));\n  EXPECT_EQ(absl::UTCTimeZone(), tz);  // guaranteed fallback to UTC\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/types/BUILD.bazel",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:cc_binary.bzl\", \"cc_binary\")\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\"@rules_cc//cc:cc_test.bzl\", \"cc_test\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n    \"ABSL_TEST_COPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"any\",\n    hdrs = [\"any.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"bad_any_cast\",\n    deprecation = \"bad_any_cast dependency is empty can be removed\",\n)\n\ncc_library(\n    name = \"source_location\",\n    hdrs = [\"source_location.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:nullability\",\n    ],\n)\n\ncc_test(\n    name = \"source_location_test\",\n    size = \"small\",\n    srcs = [\"source_location_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":source_location\",\n        \"//absl/base:config\",\n        \"//absl/strings:string_view\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"span\",\n    srcs = [\n        \"internal/span.h\",\n    ],\n    hdrs = [\n        \"span.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/algorithm\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/hash:weakly_mixed_integer\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"span_test\",\n    size = \"small\",\n    srcs = [\"span_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":span\",\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:exception_testing\",\n        \"//absl/container:fixed_array\",\n        \"//absl/container:inlined_vector\",\n        \"//absl/hash\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"any_span\",\n    srcs = [\"internal/any_span.h\"],\n    hdrs = [\n        \"any_span.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/base:nullability\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/base:throw_delegate\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"any_span_test\",\n    size = \"small\",\n    srcs = [\"any_span_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":any_span\",\n        \":span\",\n        \"//absl/base:config\",\n        \"//absl/base:exception_testing\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/hash:hash_testing\",\n        \"//absl/meta:type_traits\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_binary(\n    name = \"any_span_benchmark\",\n    testonly = True,\n    srcs = [\"any_span_benchmark.cc\"],\n    tags = [\"benchmark\"],\n    deps = [\n        \":any_span\",\n        \":span\",\n        \"//absl/base:config\",\n        \"//absl/base:raw_logging_internal\",\n        \"//absl/flags:flag\",\n        \"//absl/strings\",\n        \"//absl/strings:string_view\",\n        \"@google_benchmark//:benchmark_main\",\n    ],\n)\n\ncc_library(\n    name = \"optional\",\n    hdrs = [\"optional.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"bad_optional_access\",\n    deprecation = \"bad_optional_access dependency is empty can be removed\",\n)\n\ncc_library(\n    name = \"variant\",\n    hdrs = [\"variant.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/utility\",\n    ],\n)\n\ncc_library(\n    name = \"bad_variant_access\",\n    deprecation = \"bad_variant_access dependency is empty can be removed\",\n)\n\ncc_test(\n    name = \"variant_test\",\n    size = \"small\",\n    srcs = [\"variant_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \":variant\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"compare\",\n    hdrs = [\"compare.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n\ncc_test(\n    name = \"compare_test\",\n    size = \"small\",\n    srcs = [\n        \"compare_test.cc\",\n    ],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":compare\",\n        \"//absl/base\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n\ncc_library(\n    name = \"optional_ref\",\n    hdrs = [\"optional_ref.h\"],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/base:core_headers\",\n    ],\n)\n\ncc_test(\n    name = \"optional_ref_test\",\n    size = \"small\",\n    srcs = [\"optional_ref_test.cc\"],\n    copts = ABSL_TEST_COPTS,\n    deps = [\n        \":optional_ref\",\n        \"//absl/base:config\",\n        \"//absl/log\",\n        \"//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@googletest//:gtest_main\",\n    ],\n)\n"
  },
  {
    "path": "absl/types/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nabsl_cc_library(\n  NAME\n    any\n  HDRS\n    \"any.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    any_span\n  HDRS\n    \"any_span.h\"\n  SRCS\n    \"internal/any_span.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::nullability\n    absl::raw_logging_internal\n    absl::throw_delegate\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    any_span_test\n  SRCS\n    \"any_span_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::exception_testing\n    absl::hash_testing\n    absl::raw_logging_internal\n    absl::span\n    absl::strings\n    absl::type_traits\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    span\n  HDRS\n    \"span.h\"\n  SRCS\n    \"internal/span.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::algorithm\n    absl::config\n    absl::core_headers\n    absl::nullability\n    absl::throw_delegate\n    absl::type_traits\n    absl::weakly_mixed_integer\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    span_test\n  SRCS\n    \"span_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::span\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::exception_testing\n    absl::fixed_array\n    absl::hash\n    absl::inlined_vector\n    absl::hash_testing\n    absl::strings\n    absl::type_traits\n    GTest::gmock_main\n)\n\nabsl_cc_test(\n  NAME\n    span_test_noexceptions\n  SRCS\n    \"span_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::span\n    absl::base\n    absl::config\n    absl::core_headers\n    absl::exception_testing\n    absl::fixed_array\n    absl::inlined_vector\n    absl::hash_testing\n    absl::strings\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    optional\n  HDRS\n    \"optional.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_library(\n  NAME\n    variant\n  HDRS\n    \"variant.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::utility\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    variant_test\n  SRCS\n    \"variant_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::variant\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    source_location\n  HDRS\n    \"source_location.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::nullability\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    source_location_test\n  SRCS\n    \"source_location_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::config\n    absl::source_location\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    compare\n  HDRS\n    \"compare.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n    absl::type_traits\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    compare_test\n  SRCS\n    \"compare_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::compare\n    GTest::gmock_main\n)\n\nabsl_cc_library(\n  NAME\n    internal_optional_ref\n  HDRS\n    \"optional_ref.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::core_headers\n  PUBLIC\n)\n\nabsl_cc_test(\n  NAME\n    optional_ref_test\n  SRCS\n    \"optional_ref_test.cc\"\n  COPTS\n    ${ABSL_TEST_COPTS}\n  DEPS\n    absl::base\n    absl::config\n    absl::internal_optional_ref\n    absl::strings\n    GTest::gmock_main\n)\n\n# Deprecated empty library.\n# Clients should remove this dependency.\nabsl_cc_library(\n  NAME\n    bad_any_cast\n  PUBLIC\n)\n\n# Deprecated empty library.\n# Clients should remove this dependency.\nabsl_cc_library(\n  NAME\n    bad_optional_access\n  PUBLIC\n)\n\n# Deprecated empty library.\n# Clients should remove this dependency.\nabsl_cc_library(\n  NAME\n    bad_variant_access\n  PUBLIC\n)\n"
  },
  {
    "path": "absl/types/any.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// any.h\n// -----------------------------------------------------------------------------\n//\n// Historical note: Abseil once provided an implementation of `absl::any` as a\n// polyfill for `std::any` prior to C++17. Now that C++17 is required,\n// `absl::any` is an alias for `std::any`.\n\n#ifndef ABSL_TYPES_ANY_H_\n#define ABSL_TYPES_ANY_H_\n\n#include <any>  // IWYU pragma: export\n\n#include \"absl/base/config.h\"\n\n// Include-what-you-use cleanup required for these headers.\n#include \"absl/base/attributes.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nusing std::any;\nusing std::any_cast;\nusing std::bad_any_cast;\nusing std::make_any;\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_ANY_H_\n"
  },
  {
    "path": "absl/types/any_span.h",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: any_span.h\n// -----------------------------------------------------------------------------\n//\n// AnySpan provides a view of a random access container, much like absl::Span\n// (go/totw/93). See also go/totw/145#gtlanyspan for an introduction of AnySpan.\n//\n// The primary differences from absl::Span are:\n//  * AnySpan works with any random access container, whereas Span only works if\n//    elements are contiguous in memory -- both will work with std::vector, but\n//    only AnySpan will work with std::deque.\n//  * AnySpan performs a variety of transformations, such as dereferencing\n//    containers of pointers, or accessing specific members from a collection of\n//    structs, whereas Span does not offer such capability. For example,\n//    AnySpan<std::string> can handle both std::vector<std::string> and\n//    std::vector<std::string*>. Safe implicit conversions for a container's\n//    value type (such as up-casting from child classes, or converting\n//    reference_wrapper<T> to const T&) will happen implicitly.\n//  * AnySpan's generality has some small runtime cost, usually only a\n//    conditional branch per element access, or a function-pointer call in the\n//    worst case. Span may be preferable when the inputs are likely to be\n//    contiguous and performance is critical.\n//\n// AnySpan<T> is a mutable view to the elements and AnySpan<const T> is a\n// read-only view to the elements, similar to absl::Span.\n//\n// AnySpan only requires containers to provide a size() and an operator[] that\n// returns a reference. It will use data() if it returns a pointer to the type\n// returned by operator[], which allows it to perform some internal\n// optimizations (this should apply to many well behaved random access\n// containers that use arrays internally, but notably\n// RepeatedPtrField<T>::data() returns T** instead of T*).\n//\n// Using AnySpan as an input parameter:\n//\n// To write a function that can accept vector<MyMessage>,\n// vector<unique_ptr<MyMessage>>, or RepeatedPtrField<MyMessage> as inputs, you\n// can use AnySpan as the input to the function. AnySpan should be passed by\n// value and it is trivially copyable so it does not need to be moved:\n//\n//   void MyFunction(AnySpan<const MyMessage> messages);\n//\n// You can invoke MyFunction with a vector<MyMessage> or deque<MyMessage>:\n//\n//  std::vector<MyMessage> messages = ...;\n//  MyFunction(messages);\n//\n// Or a container of smart pointers:\n//\n//  std::deque<std::unique_ptr<MyMessage>> message_ptrs = ...;\n//  MyFunction(AnySpan<const MyMessage>(\n//      message_ptrs, any_span_transform::Deref()));\n//\n// Or, you can call the same function with a repeated proto field of type\n// MyMessage:\n//\n//  OtherMessage proto_message = ...;\n//  MyFunction(proto_message.repeated_field());\n//\n//\n// Using AnySpan as an output parameter:\n//\n// To write a function that allows mutation of a fixed-size container of\n// objects, you can use AnySpan with a non-const value type.\n//\n//   void MyMutatingFunction(AnySpan<MyMessage> messages);\n//\n// To bind a mutable AnySpan to a container, callers must construct it\n// explicitly around an lvalue:\n//\n//   std::vector<MyMessage> messages = ...;\n//   MyMutatingFunction(AnySpan<MyMessages>(messages));\n//\n// Or use one of the \"Make\" functions:\n//\n//   std::vector<MyMessage*> message_ptrs = ...;\n//   MyMutatingFunction(MakeDerefAnySpan(message_ptrs));\n//\n// Or, if you are already dealing with a mutable view-like object, construction\n// can usually be implicit:\n//\n//   absl::Span<MyMessage> mutable_span = ...;\n//   MyMutatingFunction(mutable_span);\n//\n// Transforming Spans:\n//\n// A set of useful transformation functors are provided (see the\n// any_span_transform namespace), but you can provide your own transforms as\n// well.\n//\n// Transforms work for both mutable and const values. When a transform is used\n// for a mutable AnySpan, it will usually have to accept its argument as a\n// mutable reference.\n//\n// Transforms can be any object supported by std::invoke, such as\n// callable objects, function pointers, member function pointers, and even data\n// members. Invoking a transform must return a reference to T or a reference to\n// a compatible object such as a std::reference_wrapper or a child class.\n// Transforms that return value types will not compile and would return\n// dangling references if they did.\n//\n//  struct MyStruct {\n//    int member;\n//  }\n//\n//  std::vector<MyStruct> structs = ...;\n//\n//  // Create an AnySpan<const int> that accesses the members of 'structs':\n//  auto mem_ptr = &MyStruct::member;\n//  AnySpan<const int> members(structs, mem_ptr);\n//\n//  // Or, using a lambda:\n//  auto get_member = [](const MyStruct& s) -> const int& {\n//    return s.member;\n//  };\n//  AnySpan<const int> members_from_lambda(structs, get_member);\n//\n// Transforms must outlive the spans that use them (even member/method pointers,\n// but not function pointer). Callable transforms must provide a const call\n// operator that takes a single argument and returns a reference. Transforms\n// will be executed every time an element is accessed, so complex transforms may\n// have significant performance consequences.\n//\n// Factory Functions:\n//\n// A set of useful functions for constructing common types of AnySpans are\n// provided. Factories with \"Const\" in the name produce AnySpans of const\n// elements. Factories with \"Deref\" in the name will dereference elements of the\n// container or array:\n//\n//  AnySpan<T> MakeAnySpan(Container& c);\n//  AnySpan<T> MakeDerefAnySpan(Container& c);\n//  AnySpan<T> MakeAnySpan(T* ptr, std::size_t size);\n//  AnySpan<const T> MakeConstAnySpan(const Container& c);\n//  AnySpan<const T> MakeConstDerefAnySpan(const Container& c);\n//  AnySpan<const T> MakeConstAnySpan(const T* ptr, std::size_t size);\n//\n// Lifetime Gotchas:\n//\n// Take care when constructing spans as named variables! AnySpan captures all\n// arguments by reference, even if it's a pointer:\n//\n//  AnySpan<T> span(v, &MyClass::SomeMethod);  // Dangling reference!\n//\n//  // Also bad! The lambda is destroyed before the span.\n//  AnySpan<T> span(v, [](U& u) { return SomeFunction(u); });\n//\n// Free functions are ok:\n//\n//  AnySpan<T> span(v, SomeFunction);  // This is OK.\n//  AnySpan<T> span(v, &SomeFunction);  // This is OK too.\n//\n// In all other cases, you must ensure that the object used as a transform\n// outlives the span, even if that object is a pointer type.\n//\n// AnySpan is also capable of capturing another AnySpan, so watch out for\n// implicit conversions between types of AnySpans:\n//\n//   // MakeDerefAnySpan() returns an AnySpan<Derived>, leaving 's' pointing to\n//   // a temporary!\n//   vector<Derived*> v;\n//   AnySpan<Base> s = MakeDerefAnySpan(v);\n//\n// Adapting Spans:\n//\n// Since AnySpan only expects operator[] and size(), it is relatively simple to\n// write light-weight adaptor classes that can behave like containers. See the\n// any_span_adaptor namespace for a utility class that does this for iterators\n// and views.\n//\n// Adapters are more powerful than transforms, since they allow you to change\n// the value type and element order of a container, but transforms will\n// generally perform better and leave code with fewer object lifetime concerns.\n//\n//\n// Note about RepeatedPtrField performance:\n//\n// AnySpan will use data() when it returns a pointer to the same type returned\n// by operator[], however RepeatedPtrField's operator[] returns T& and its\n// data() returns a T**. Because of this, AnySpan will fall back to a less\n// efficient version of type-erasure. If you have a performance critical use of\n// RepeatedPtrField, you might find this pattern to have better performance:\n//\n//  MyFunction(AnySpan<const MyMessage>(\n//      proto_message.repeated_field().data(),\n//      proto_message.repeated_field().size(),\n//      any_span_transform::Deref()));\n//\n#ifndef ABSL_TYPES_ANY_SPAN_H_\n#define ABSL_TYPES_ANY_SPAN_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <functional>\n#include <initializer_list>\n#include <iterator>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/types/internal/any_span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// The accessors in the 'any_span_transform' namespace return references to\n// Transform functors that may be passed to AnySpan. Generally you should\n// prefer to use these functors whenever possible, as they may trigger internal\n// optimizations that are otherwise not possible, and they are valid for the\n// duration of the program, so you do not have to worry about their lifetime.\nnamespace any_span_transform {\n\n//\n// Identity() returns a functor that returns whatever is passed to it. Generally\n// you should prefer to use AnySpan's implicit constructor directly, but this\n// may be useful if you are writing templates on top of AnySpan.\n//\n// Returns a const reference so that callers don't have to worry about\n// lifetime of the functor.\n//\n\nstruct IdentityT {\n  template <typename T>\n  T& operator()(T& v) const {  // NOLINT(runtime/references)\n    return v;\n  }\n};\n\ninline const IdentityT& Identity() {\n  static const IdentityT f = {};\n  return f;\n}\n\nstruct DerefT {\n  template <typename Ptr>\n  auto operator()(Ptr& ptr) const  // NOLINT(runtime/references)\n      -> decltype(*ptr) {\n    ABSL_RAW_DCHECK(ptr, \"Cannot dereference null pointer\");\n    return *ptr;\n  }\n};\n\n// Deref() returns a functor that dereferences whatever is passed to it. It\n// works for smart and raw pointers, as well as std::optional. Do not use this\n// with containers that may contain elements that cannot be dereferenced, such\n// as null pointers.\n//\n// Returns a const reference so that callers don't have to worry about lifetime\n// of the functor.\ninline const DerefT& Deref() {\n  static const DerefT f = {};\n  return f;\n}\n\n}  // namespace any_span_transform\n\n// Utilities for adapting things to look like the interface that AnySpan\n// expects. For the most part this is based on iterators and views, and is\n// intended to be composed with absl/types/iterator_adaptors.h.\nnamespace any_span_adaptor {\n\n// Adapts a pair of iterators into a container-like object that AnySpan can\n// wrap. This is useful if you are faced with a range or view of random access\n// iterators. Iter must be a valid random access iterator.\ntemplate <typename Iter>\nclass Range {\n public:\n  static_assert(\n      std::is_same<typename std::iterator_traits<Iter>::iterator_category,\n                   std::random_access_iterator_tag>::value,\n      \"Iter must be a random access iterator.\");\n\n  Range(Iter begin, Iter end) {\n    ABSL_HARDENING_ASSERT(begin <= end);\n    begin_ = begin;\n    end_ = end;\n  }\n\n  std::size_t size() const { return end_ - begin_; }\n\n  decltype(std::declval<Iter>()[0]) operator[](std::size_t i) const {\n    ABSL_HARDENING_ASSERT(i < (end_ - begin_));\n    return begin_[i];\n  }\n\n private:\n  Iter begin_;\n  Iter end_;\n};\n\n// Returns a Range adaptor that wraps the given pair of iterators. The return\n// value of this function must outlive any spans that use it. Iter must be a\n// valid random access iterator.\ntemplate <typename Iter>\nRange<Iter> MakeAdaptorFromRange(Iter begin, Iter end) {\n  return Range<Iter>(begin, end);\n}\n\n// Returns a Range adaptor that wraps the given view. The begin() and end()\n// functions of the given view must return valid random access iterators. The\n// return value of this function must outlive any spans that use it.\ntemplate <typename View>\nauto MakeAdaptorFromView(View& view)  // NOLINT(runtime/references)\n    -> Range<decltype(view.begin())> {\n  return Range<decltype(view.begin())>(view.begin(), view.end());\n}\n\n}  // namespace any_span_adaptor\n\ntemplate <typename T>\nclass AnySpan;\n\n// Returns a subspan of the given span, but truncated to the given length.\n// The start position must be valid; it is not adjusted to fit the span.\n// TODO(b/226581285): Remove this once the old subspan() is gone.\ntemplate <class T>\n[[deprecated(\n    \"Avoid relying on this API, as it is a temporary migration aid from the \"\n    \"nonstandard subspan(). Instead, manually clamp at the call site, such as \"\n    \"via: span.subspan(i, \"\n    \"std::min\"  // Separated so linter doesn't complain about parentheses\n    \"(n, span.size() - i))\")]]\nconstexpr AnySpan<T> SubspanOrTruncate(\n    AnySpan<T> span, typename AnySpan<T>::size_type pos,\n    typename AnySpan<T>::size_type len = AnySpan<T>::npos) {\n  return AnySpan<T>(span.subspan(pos).getter_,\n                    (std::min)(len, span.size() - pos));\n}\n\ntemplate <typename T>\nclass ABSL_ATTRIBUTE_VIEW AnySpan {\n private:\n  template <typename Iter, typename Value>\n  class IteratorBase;\n\n  template <typename U>\n  using EnableIfMutable = std::enable_if_t<!std::is_const<T>::value, U>;\n\n  template <typename U>\n  using EnableIfConst = std::enable_if_t<std::is_const<T>::value, U>;\n\n  static std::true_type CreatesATemporaryImpl(std::decay_t<T>&&);\n  static std::false_type CreatesATemporaryImpl(const T&);\n  template <typename U,\n            typename B = decltype(CreatesATemporaryImpl(std::declval<U>()))>\n  struct CreatesATemporary : B {};\n\n  // Enable if invoke(transform, element) is valid and if a reference to T can\n  // bind to its output. This prevents situations where the constructor may be\n  // ambiguous.\n  // We also verify that the conversion from TransformResult to T& does not\n  // create a temporary. Otherwise, we would get a false positive in the\n  // enabler where `const char*` looks like can be converted to\n  // `const std::string&`.\n  template <typename Transform, typename Element,\n            typename TransformResult = decltype(std::invoke(\n                std::declval<const Transform&>(), std::declval<Element>()))>\n  using EnableIfTransformIsValid =\n      std::enable_if_t<std::is_convertible_v<TransformResult, T&> &&\n                       !CreatesATemporary<TransformResult>::value>;\n\n  // Enable if Container appears to be a valid container. Just checks for size()\n  // and makes sure the class is not an AnySpan for now.\n  template <typename Container>\n  using EnableIfContainer =\n      std::enable_if_t<any_span_internal::HasSize<Container>::value &&\n                       !any_span_internal::IsAnySpan<Container>::value>;\n\n  template <typename Element>\n  using EnableIfDifferentElementType =\n      std::enable_if_t<!std::is_same<T, Element>::value &&\n                       !std::is_same<T, const Element>::value>;\n\n  template <typename Transform>\n  using EnableIfTransformIsByCopy =\n      std::enable_if_t<any_span_internal::kIsTransformCopied<Transform>, bool>;\n  template <typename Transform>\n  using EnableIfTransformIsByRef =\n      std::enable_if_t<!any_span_internal::kIsTransformCopied<Transform>, bool>;\n\n public:\n  using element_type = T;\n  using value_type = typename std::remove_const<T>::type;\n  using size_type = std::size_t;\n  using difference_type = std::ptrdiff_t;\n  using absl_internal_is_view = std::true_type;\n\n  static const size_type npos = static_cast<size_type>(-1);  // NOLINT\n\n  using reference = T&;\n  using const_reference = typename std::add_const<T>::type&;\n\n  using pointer = T*;\n  using const_pointer = typename std::add_const<T>::type*;\n\n  // Note that iterator will be const if T is const.\n  class iterator;\n  class const_iterator;\n\n  using reverse_iterator = std::reverse_iterator<iterator>;\n  using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n\n  // Null and empty by default.\n  AnySpan() = default;\n\n  // Creates a span that wraps an initializer list. This makes it possible to\n  // pass a brace-enclosed initializer list to a function expecting an AnySpan.\n  //\n  // Example:\n  //\n  //   void Process(AnySpan<const int> x);\n  //   Process({1, 2, 3});\n  //\n  // The initializer_list must outlive this AnySpan.\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      std::initializer_list<value_type> l ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : AnySpan(l.begin(), l.size()) {}\n\n  // Creates a span that wraps an initializer list of a type other than\n  // value_type, or with an explicit transform. Applies the optional transform\n  // to elements before returning them.\n  //\n  // Example:\n  //\n  //   struct Base {};\n  //   struct Derived : Base {};\n  //\n  //   void Process(AnySpan<const Base> x);\n  //   Process({Derived(a), Derived(b), Derived(c)});\n  //\n  //     where the default identity transform would apply an implicit\n  //     derived-to-base  conversion.\n  //\n  // The initializer_list must outlive this AnySpan.\n  template <typename Element, typename Transform,\n            typename = EnableIfTransformIsValid<Transform, const Element&>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr AnySpan(std::initializer_list<Element> l\n                        ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                    const Transform& transform)\n      : AnySpan(l.begin(), l.size(), transform) {}\n  template <typename Element,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfTransformIsValid<Transform, const Element&>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr AnySpan(std::initializer_list<Element> l\n                        ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                    const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n                        any_span_transform::Identity())\n      : AnySpan(l.begin(), l.size(), transform) {}\n\n  // Creates a span that wraps an array. Applies the optional transform to\n  // elements before returning them.\n  //\n  // Transform must be a function object with a const operator() that takes\n  // Element as an argument and return a reference to T or compatible object.\n  //\n  // Both the transform and array must outlive this span.\n  template <typename Element, typename Transform,\n            typename = EnableIfTransformIsValid<Transform, const Element&>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr AnySpan(const Element* absl_nullable ptr\n                        ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                    size_type size, const Transform& transform)\n      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}\n  template <typename Element,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfTransformIsValid<Transform, const Element&>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr AnySpan(const Element* absl_nullable ptr\n                        ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                    size_type size,\n                    const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n                        any_span_transform::Identity())\n      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}\n\n  // Creates a span that wraps an array of fixed size. Applies the optional\n  // transform to elements before returning them.\n  //\n  // Transform must be a function object with a const operator() that takes\n  // Element as an argument and return a reference to T or compatible object.\n  //\n  // Both the transform and array must outlive this span.\n  template <typename Element, size_type N, typename Transform,\n            typename = EnableIfTransformIsValid<Transform, const Element&>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],\n      const Transform& transform)\n      : AnySpan(array, N, transform) {}\n  template <typename Element, size_type N,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfTransformIsValid<Transform, const Element&>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],\n      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n          any_span_transform::Identity())\n      : AnySpan(array, N, transform) {}\n\n  // Creates a span that wraps a const container. Applies the optional transform\n  // to elements before returning them.\n  //\n  // This constructor is enabled even for mutable spans, since some\n  // container-like objects provide mutable element access even when the object\n  // itself is const (such as absl::Span)\n  //\n  // Transform must be a function object with a const operator() that takes the\n  // value type of Container as an argument and return a reference to T or\n  // compatible object.\n  //\n  // The transform, container, and the container's underlying storage must\n  // outlive this span. Any operation that may reallocate the container's\n  // storage or change its size will invalidate the span.\n  template <typename Container, typename Transform,\n            typename = EnableIfContainer<Container>,\n            typename = EnableIfTransformIsValid<\n                Transform, decltype(std::declval<const Container&>()[0])>,\n            EnableIfTransformIsByCopy<std::enable_if_t<\n                absl::type_traits_internal::IsView<Container>::value,\n                Transform>> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const Container& container, const Transform& transform)\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),\n                container.size()) {}\n  template <typename Container, typename Transform,\n            typename = EnableIfContainer<Container>,\n            typename = EnableIfTransformIsValid<\n                Transform, decltype(std::declval<const Container&>()[0])>,\n            EnableIfTransformIsByCopy<std::enable_if_t<\n                !absl::type_traits_internal::IsView<Container>::value,\n                Transform>> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      const Transform& transform)\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),\n                container.size()) {}\n  template <\n      typename Container, typename Transform = any_span_transform::IdentityT,\n      typename = EnableIfContainer<Container>,\n      typename = EnableIfTransformIsValid<\n          Transform, decltype(std::declval<const Container&>()[0])>,\n      EnableIfTransformIsByRef<\n          std::enable_if_t<absl::type_traits_internal::IsView<Container>::value,\n                           Transform>> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const Container& container,\n      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n          any_span_transform::Identity())\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),\n                container.size()) {}\n  template <typename Container,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfContainer<Container>,\n            typename = EnableIfTransformIsValid<\n                Transform, decltype(std::declval<const Container&>()[0])>,\n            EnableIfTransformIsByRef<std::enable_if_t<\n                !absl::type_traits_internal::IsView<Container>::value,\n                Transform>> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n          any_span_transform::Identity())\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),\n                container.size()) {}\n\n  // Creates a span that wraps a mutable array. Applies the optional transform\n  // to elements before returning them.\n  //\n  // Transform must be a function object with a const operator() that takes\n  // Element as an argument and return a reference to T or compatible object.\n  //\n  // Both the transform and array must outlive this span.\n  template <typename Element, typename Transform,\n            typename = EnableIfMutable<Element>,\n            typename = EnableIfTransformIsValid<Transform, Element&>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr AnySpan(Element* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                    size_type size, const Transform& transform)\n      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}\n  template <typename Element,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfMutable<Element>,\n            typename = EnableIfTransformIsValid<Transform, Element&>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr AnySpan(Element* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                    size_type size,\n                    const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n                        any_span_transform::Identity())\n      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}\n\n  // Creates a span that wraps a mutable array of fixed size. Applies the\n  // optional transform to elements before returning them.\n  //\n  // Transform must be a function object with a const operator() that takes\n  // Element as an argument and return a reference to T or compatible object.\n  //\n  // Both the transform and array must outlive this span.\n  template <typename Element, size_type N, typename Transform,\n            typename = EnableIfMutable<Element>,\n            typename = EnableIfTransformIsValid<Transform, Element&>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],\n      const Transform& transform)\n      : AnySpan(array, N, transform) {}\n  template <typename Element, size_type N,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfMutable<Element>,\n            typename = EnableIfTransformIsValid<Transform, Element&>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],\n      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n          any_span_transform::Identity())\n      : AnySpan(array, N, transform) {}\n\n  // Creates a span that wraps a mutable container. Only enabled if T is\n  // mutable. Applies the optional transform to elements before returning them.\n  //\n  // Transform must be a function object with a const operator() that takes the\n  // value type of Container as an argument and return a reference to T or\n  // compatible object.\n  //\n  // The transform, container, and the container's underlying storage must\n  // outlive this span. Any operation that may reallocate the container's\n  // storage or change its size will invalidate the span.\n  template <typename Container, typename Transform,\n            typename = EnableIfMutable<Container>,\n            typename = EnableIfContainer<Container>,\n            typename = EnableIfTransformIsValid<\n                Transform, decltype(std::declval<Container&>()[0])>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr explicit AnySpan(  // NOLINT(google-explicit-constructor)\n      Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      const Transform& transform)\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),\n                container.size()) {}\n  template <typename Container,\n            typename Transform = any_span_transform::IdentityT,\n            typename = EnableIfMutable<Container>,\n            typename = EnableIfContainer<Container>,\n            typename = EnableIfTransformIsValid<\n                Transform, decltype(std::declval<Container&>()[0])>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr explicit AnySpan(  // NOLINT(google-explicit-constructor)\n      Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =\n          any_span_transform::Identity())\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),\n                container.size()) {}\n\n  // Converts a mutable span to a const span by copying the internal state\n  // (rather than wrapping the other span).\n  // TODO(b/179783710): add ABSL_ATTRIBUTE_LIFETIME_BOUND.\n  template <typename LazyT = T, typename = EnableIfConst<LazyT>>\n  constexpr AnySpan(  // NOLINT(google-explicit-constructor)\n      const AnySpan<typename std::remove_const<T>::type>& other)\n      : getter_(other.getter_), size_(other.size()) {}\n\n  // Creates a span that wraps around another span of different type.\n  //\n  // This has performance and lifetime consequences, and can easily happen by\n  // mistake. We make such conversions explicit here.\n  template <typename Element, typename = EnableIfDifferentElementType<Element>,\n            typename = EnableIfTransformIsValid<any_span_transform::IdentityT,\n                                                Element&>>\n  constexpr explicit AnySpan(\n      const AnySpan<Element>& other ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(\n                    other, any_span_transform::Identity()),\n                other.size()) {}\n\n  // Creates a span that wraps around another span. Applies the non-optional\n  // transform to elements before returning them.\n  //\n  // This has lifetime consequences, and may happen by mistake. We make it\n  // explicit here.\n  template <typename Element, typename Transform,\n            typename = EnableIfTransformIsValid<Transform, Element&>,\n            EnableIfTransformIsByCopy<Transform> = true>\n  constexpr explicit AnySpan(const AnySpan<Element>& other\n                                 ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                             const Transform& transform)\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(other, transform),\n                other.size()) {}\n  template <typename Element, typename Transform,\n            typename = EnableIfTransformIsValid<Transform, Element&>,\n            EnableIfTransformIsByRef<Transform> = true>\n  constexpr explicit AnySpan(\n      const AnySpan<Element>& other ABSL_ATTRIBUTE_LIFETIME_BOUND,\n      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : AnySpan(any_span_internal::MakeContainerGetter<T>(other, transform),\n                other.size()) {}\n\n  // Returns a subspan of this span. This span may become invalid before the\n  // subspan, but both the container and transform must remain valid.\n  // pos must be non-negative and <= size().\n  // len must be non-negative and will be pinned to at most x.size() - pos.\n  // If len==npos, the subspan continues till the end of this span.\n  ABSL_DEPRECATE_AND_INLINE()\n  constexpr AnySpan subspan(size_type pos, size_type len) const {\n    return absl::SubspanOrTruncate(*this, pos, len);\n  }\n\n  // TODO(b/226581285): Merge this function with the sized overload. This\n  // function only exists to prevent infinite recursion while we are migrating\n  // to absl::SubspanOrTruncate().\n  constexpr AnySpan subspan(size_type pos) const {\n    ABSL_HARDENING_ASSERT(pos <= size());\n    return AnySpan(getter_.Offset(pos), size() - pos);\n  }\n\n  // Returns a `AnySpan` containing first `len` elements. Parameter `len` must\n  // be non-negative.\n  // TODO(b/226581285): Remove this function and replace it with the\n  // non-truncating behavior once the uses are gone.\n  ABSL_DEPRECATE_AND_INLINE() constexpr AnySpan first(size_type len) const {\n    return absl::SubspanOrTruncate(*this, 0, len);\n  }\n\n  // Returns a `AnySpan` containing last `len` elements. Parameter `len` must be\n  // non-negative and <= size().\n  constexpr AnySpan last(size_type len) const { return subspan(size() - len); }\n\n  // Size operations.\n  constexpr size_type size() const { return size_; }\n  ABSL_DEPRECATE_AND_INLINE() size_type length() const { return size(); }\n  constexpr bool empty() const { return size() == 0; }\n\n  // Element access.\n  constexpr reference operator[](size_type index) const {\n    ABSL_HARDENING_ASSERT(index < size());\n    return getter_.Get(index);\n  }\n  constexpr reference at(size_type index) const {\n    if (ABSL_PREDICT_FALSE(index >= size())) {\n      absl::ThrowStdOutOfRange(\"AnySpan::at failed bounds check\");\n    }\n    return getter_.Get(index);\n  }\n  constexpr reference front() const {\n    ABSL_HARDENING_ASSERT(size() > 0);\n    return (*this)[0];\n  }\n  constexpr reference back() const {\n    ABSL_HARDENING_ASSERT(size() > 0);\n    return (*this)[size() - 1];\n  }\n\n  // Iterator accessors.\n  constexpr iterator begin() const { return iterator(this, 0); }\n  constexpr iterator end() const { return iterator(this, size_); }\n  constexpr reverse_iterator rbegin() const { return reverse_iterator(end()); }\n  constexpr reverse_iterator rend() const { return reverse_iterator(begin()); }\n  constexpr const_iterator cbegin() const { return const_iterator(this, 0); }\n  constexpr const_iterator cend() const { return const_iterator(this, size_); }\n  constexpr const_reverse_iterator crbegin() const { return rbegin(); }\n  constexpr const_reverse_iterator crend() const { return rend(); }\n\n  // Constructs from a getter and size. Not for external use.\n  AnySpan(any_span_internal::Getter<T> getter, size_type size)\n      : getter_(getter), size_(size) {}\n\n  // Support for absl::Hash.\n  template <typename H>\n  friend constexpr H AbslHashValue(H state, AnySpan any_span) {\n    for (const auto& v : any_span) {\n      state = H::combine(std::move(state), v);\n    }\n    return H::combine(std::move(state), any_span.size());\n  }\n\n private:\n  template <typename U>\n  friend class AnySpan;\n\n  template <typename U>\n  friend bool any_span_internal::IsCheap(AnySpan<U> s);\n\n  // Getter to access elements.\n  any_span_internal::Getter<T> getter_;\n\n  // The size of this span.\n  size_type size_ = 0;\n\n  friend AnySpan<T> absl::SubspanOrTruncate<T>(AnySpan<T>, size_type,\n                                               size_type);\n\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wnon-template-friend\"\n#endif\n  // The technical reasons we need to declare these friends in this manner are\n  // quite subtle and confusing, but they're necessary on some toolchains to\n  // allow all mutable/const combinations with this & other range types while\n  // avoiding symbol collisions or ODR violations.\n  friend bool operator==(AnySpan<const T> a, AnySpan<const T> b);\n  friend bool operator!=(AnySpan<const T> a, AnySpan<const T> b);\n#if defined(__GNUC__) && !defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n  // operator==\n  friend bool operator==(AnySpan a, AnySpan b) {\n    return any_span_internal::EqualImpl<const T>(a, b);\n  }\n  friend bool operator!=(AnySpan a, AnySpan b) { return !(a == b); }\n};\n\n// Constructs an AnySpan from a container or array.\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::ElementType<Container>>\nstd::enable_if_t<\n    absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,\n    AnySpan<T>>\nMakeAnySpan(Container& c) {\n  return AnySpan<T>(c);\n}\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::ElementType<Container>>\nstd::enable_if_t<\n    !absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,\n    AnySpan<T>>\nMakeAnySpan(Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return AnySpan<T>(c);\n}\n\n// Constructs an AnySpan that dereferences a container or array of pointers.\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::DerefElementType<Container>>\nstd::enable_if_t<\n    absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,\n    AnySpan<T>>\nMakeDerefAnySpan(Container& c) {\n  return AnySpan<T>(c, any_span_transform::Deref());\n}\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::DerefElementType<Container>>\nstd::enable_if_t<\n    !absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,\n    AnySpan<T>>\nMakeDerefAnySpan(Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return AnySpan<T>(c, any_span_transform::Deref());\n}\n\n// Constructs an AnySpan from a pointer and size.\ntemplate <int&... ExplicitArgumentBarrier, typename T>\nAnySpan<T> MakeAnySpan(T* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                       std::size_t size) {\n  return AnySpan<T>(ptr, size);\n}\n\n// Constructs a const AnySpan from a container or array.\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::ElementType<const Container>>\nstd::enable_if_t<absl::type_traits_internal::IsView<Container>::value,\n                 AnySpan<const T>>\nMakeConstAnySpan(const Container& c) {\n  return AnySpan<const T>(c);\n}\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::ElementType<const Container>>\nstd::enable_if_t<!absl::type_traits_internal::IsView<Container>::value,\n                 AnySpan<const T>>\nMakeConstAnySpan(const Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return AnySpan<const T>(c);\n}\n\n// Constructs a const AnySpan that dereferences a container or array of\n// pointers.\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::DerefElementType<const Container>>\nstd::enable_if_t<absl::type_traits_internal::IsView<Container>::value,\n                 AnySpan<const T>>\nMakeConstDerefAnySpan(const Container& c) {\n  return AnySpan<const T>(c, any_span_transform::Deref());\n}\ntemplate <int&... ExplicitArgumentBarrier, typename Container,\n          typename T = any_span_internal::DerefElementType<const Container>>\nstd::enable_if_t<!absl::type_traits_internal::IsView<Container>::value,\n                 AnySpan<const T>>\nMakeConstDerefAnySpan(const Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {\n  return AnySpan<const T>(c, any_span_transform::Deref());\n}\n\n// Constructs an AnySpan from a pointer and size.\ntemplate <int&... ExplicitArgumentBarrier, typename T>\nAnySpan<const T> MakeConstAnySpan(const T* absl_nullable ptr,\n                                  std::size_t size) {\n  return AnySpan<const T>(ptr, size);\n}\n\n//\n// Implementation details follow.\n//\n\ntemplate <typename T>\nconst typename AnySpan<T>::size_type AnySpan<T>::npos;\n\n// Iterator base class. Uses CRTP (Iter should be the child class). Constness of\n// the iterator is determined by the constness of Value.\ntemplate <typename T>\ntemplate <typename Iter, typename Value>\nclass ABSL_ATTRIBUTE_VIEW AnySpan<T>::IteratorBase {\n private:\n  // Returns a reference to this as the child class.\n  const Iter& self() const { return static_cast<const Iter&>(*this); }\n  Iter& self() { return static_cast<Iter&>(*this); }\n\n public:\n  using iterator_category = std::random_access_iterator_tag;\n  using value_type = typename std::remove_const<Value>::type;\n  using difference_type = std::ptrdiff_t;\n  using reference = Value&;\n  using pointer = Value*;\n\n  // Constructs an invalid iterator.\n  IteratorBase() = default;\n\n  reference operator*() const { return (*container_)[index_]; }\n\n  pointer absl_nonnull operator->() const { return &(*container_)[index_]; }\n\n  reference operator[](difference_type i) const {\n    return (*container_)[index_ + i];\n  }\n\n  Iter& operator+=(difference_type d) {\n    index_ += d;\n    return self();\n  }\n\n  Iter& operator-=(difference_type d) { return self() += -d; }\n\n  Iter& operator++() {\n    self() += 1;\n    return self();\n  }\n\n  Iter operator++(int) {\n    Iter copy(self());\n    ++self();\n    return copy;\n  }\n\n  Iter& operator--() {\n    self() -= 1;\n    return self();\n  }\n\n  Iter operator--(int) {\n    Iter copy(self());\n    --self();\n    return copy;\n  }\n\n  Iter operator+(difference_type d) const {\n    Iter tmp = self();\n    tmp += d;\n    return tmp;\n  }\n\n  friend Iter operator+(difference_type d, Iter i) { return i + d; }\n\n  Iter operator-(difference_type d) const { return self() + (-d); }\n\n  difference_type operator-(const Iter& other) const {\n    return index_ - other.index_;\n  }\n\n  friend bool operator==(const Iter& a, const Iter& b) {\n    return a.index_ == b.index_;\n  }\n\n  friend bool operator!=(const Iter& a, const Iter& b) {\n    return a.index_ != b.index_;\n  }\n\n  friend bool operator<(const Iter& a, const Iter& b) {\n    return a.index_ < b.index_;\n  }\n\n  friend bool operator<=(const Iter& a, const Iter& b) {\n    return a.index_ <= b.index_;\n  }\n\n  friend bool operator>(const Iter& a, const Iter& b) {\n    return a.index_ > b.index_;\n  }\n\n  friend bool operator>=(const Iter& a, const Iter& b) {\n    return a.index_ >= b.index_;\n  }\n\n protected:\n  // Constructs an iterator that points to the given index of the given span.\n  IteratorBase(const AnySpan* absl_nullable container, size_type index)\n      : container_(container), index_(index) {}\n\n  const AnySpan* absl_nullable container_ = nullptr;\n  size_type index_ = 0;\n};\n\n// iterator implementation. This mostly just forwards to IteratorBase.\ntemplate <typename T>\nclass ABSL_ATTRIBUTE_VIEW AnySpan<T>::iterator\n    : public IteratorBase<iterator, T> {\n private:\n  using Base = IteratorBase<iterator, T>;\n\n public:\n  using typename Base::difference_type;\n  using typename Base::iterator_category;\n  using typename Base::pointer;\n  using typename Base::reference;\n  using typename Base::value_type;\n\n  iterator() = default;\n\n private:\n  // Only let AnySpan construct valid instances.\n  friend class AnySpan;\n\n  iterator(const AnySpan* absl_nullable container, size_type index)\n      : Base(container, index) {}\n};\n\n// const_iterator implementation. This mostly just forwards to IteratorBase,\n// but also provides conversion from MutableIterator.\ntemplate <typename T>\nclass AnySpan<T>::const_iterator\n    : public IteratorBase<const_iterator, typename std::add_const<T>::type> {\n private:\n  using Base = IteratorBase<const_iterator, typename std::add_const<T>::type>;\n\n public:\n  using typename Base::difference_type;\n  using typename Base::iterator_category;\n  using typename Base::pointer;\n  using typename Base::reference;\n  using typename Base::value_type;\n\n  const_iterator() = default;\n\n  // Support conversion from mutable iterators.\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  const_iterator(const iterator& other)  // NOLINT(runtime/explicit)\n      : Base(other.container_, other.index_) {}\n\n private:\n  // Only let AnySpan construct valid instances.\n  friend class AnySpan;\n\n  const_iterator(const AnySpan* absl_nullable container, size_type index)\n      : Base(container, index) {}\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_ANY_SPAN_H_\n"
  },
  {
    "path": "absl/types/any_span_benchmark.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include <cstddef>\n#include <cstdint>\n#include <deque>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/flags/flag.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/any_span.h\"\n#include \"absl/types/span.h\"\n#include \"benchmark/benchmark.h\"\n\nABSL_FLAG(uint64_t, benchmark_container_size, 2000,\n          \"The size of the containers to use for benchmarking.\");\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\n//\n// Benchmarks and supporting code follows.\n//\n\ntemplate <typename T>\nT MakeElement(int) {\n  ABSL_RAW_LOG(FATAL, \"Not implemented.\");\n}\n\ntemplate <>\nstd::string MakeElement<std::string>(int i) {\n  return absl::StrCat(i, i, i);\n}\n\ntemplate <>\nint MakeElement<int>(int i) {\n  return i;\n}\n\ntemplate <typename Container>\nContainer MakeContainer() {\n  const size_t container_size = absl::GetFlag(FLAGS_benchmark_container_size);\n  Container c;\n  for (size_t i = 0; i < container_size; ++i) {\n    c.push_back(\n        MakeElement<typename Container::value_type>(static_cast<int>(i)));\n  }\n  return c;\n}\n\ntemplate <typename Container, typename SourceContainer>\nContainer MakePointerContainer(SourceContainer* source) {\n  Container c;\n  for (auto& value : *source) {\n    c.push_back(&value);\n  }\n  return c;\n}\n\n//\n// Sequential Access Benchmarks\n//\n\n// Control run, iterating original container.\ntemplate <typename Container>\nvoid BM_Sequential(benchmark::State& state) {\n  auto a = MakeContainer<Container>();\n  benchmark::DoNotOptimize(a);\n  for (auto _ : state) {\n    for (auto& v : a) {\n      benchmark::DoNotOptimize(v);\n    }\n  }\n}\n\n// Wraps the container with a Span.\ntemplate <typename Container>\nvoid BM_Sequential_Span(benchmark::State& state) {\n  auto container = MakeContainer<Container>();\n  absl::Span<typename Container::value_type> array_span(container);\n  benchmark::DoNotOptimize(array_span);\n  for (auto _ : state) {\n    for (auto& v : array_span) {\n      benchmark::DoNotOptimize(v);\n    }\n  }\n}\n\n// Same as BM_Sequential_Span, but uses a container of pointers and\n// dereferences it.\ntemplate <typename Container>\nvoid BM_Sequential_DerefSpan(benchmark::State& state) {\n  using T = typename std::remove_pointer<typename Container::value_type>::type;\n  auto values = MakeContainer<std::vector<T>>();\n  const auto container = MakePointerContainer<Container>(&values);\n  absl::Span<T* const> array_span(container);\n  benchmark::DoNotOptimize(array_span);\n  for (auto _ : state) {\n    for (const auto& v : array_span) {\n      benchmark::DoNotOptimize(*v);\n    }\n  }\n}\n\n// Wraps a AnySpan<const T> around a Container. Sequentially reads the\n// entire span.\ntemplate <typename Container>\nvoid BM_Sequential_AnySpan(benchmark::State& state) {\n  using T = typename Container::value_type;\n  auto container = MakeContainer<Container>();\n  AnySpan<T> span(container);\n  benchmark::DoNotOptimize(span);\n  for (auto _ : state) {\n    for (T& s : span) {\n      benchmark::DoNotOptimize(s);\n    }\n  }\n}\n\n// Same as BM_Sequential_AnySpan, but dereferences the elements.\ntemplate <typename Container>\nvoid BM_Sequential_AnySpanDeref(benchmark::State& state) {\n  using T = typename std::remove_pointer<typename Container::value_type>::type;\n  auto values = MakeContainer<std::vector<T>>();\n  auto container = MakePointerContainer<Container>(&values);\n  AnySpan<T> span(container, any_span_transform::Deref());\n  benchmark::DoNotOptimize(span);\n  for (auto _ : state) {\n    for (auto& s : span) {\n      benchmark::DoNotOptimize(s);\n    }\n  }\n}\n\n//\n// Random Access Benchmarks\n//\n\n// Control run, accessing the original container.\ntemplate <typename Container>\nvoid BM_Random(benchmark::State& state) {\n  auto a = MakeContainer<Container>();\n  auto* b = &a;\n  benchmark::DoNotOptimize(a);\n  benchmark::DoNotOptimize(b);\n  for (auto _ : state) {\n    uint64_t index_seed = 0;\n    for (size_t j = 0; j < a.size(); ++j) {\n      index_seed += 5623;\n      const uint64_t index = index_seed % a.size();\n      benchmark::DoNotOptimize((*b)[index]);\n    }\n  }\n}\n\n// Wraps a Span around a Container. Randomly reads the span.\ntemplate <typename Container>\nvoid BM_Random_Span(benchmark::State& state) {\n  using T = typename Container::value_type;\n  auto v = MakeContainer<Container>();\n  absl::Span<T> array_span(v);\n  benchmark::DoNotOptimize(array_span);\n  for (auto _ : state) {\n    uint64_t index_seed = 0;\n    for (size_t j = 0; j < v.size(); ++j) {\n      index_seed += 5623;\n      const uint64_t index = index_seed % v.size();\n      benchmark::DoNotOptimize(array_span[index]);\n    }\n  }\n}\n\n// Wraps a AnySpan around a Container. Randomly reads the span.\ntemplate <typename Container>\nvoid BM_Random_AnySpan(benchmark::State& state) {\n  using T = typename Container::value_type;\n  auto container = MakeContainer<Container>();\n  AnySpan<T> span(container);\n  benchmark::DoNotOptimize(span);\n  for (auto _ : state) {\n    uint64_t index_seed = 0;\n    for (size_t j = 0; j < container.size(); ++j) {\n      index_seed += 5623;\n      const uint64_t index = index_seed % span.size();\n      benchmark::DoNotOptimize(span[index]);\n    }\n  }\n}\n\n// Same as BM_Random_AnySpan, but dereferences elements.\ntemplate <typename Container>\nvoid BM_Random_AnySpanDeref(benchmark::State& state) {\n  using T = typename std::remove_pointer<typename Container::value_type>::type;\n  auto values = MakeContainer<std::vector<T>>();\n  auto container = MakePointerContainer<Container>(&values);\n  AnySpan<T> span(container, any_span_transform::Deref());\n  benchmark::DoNotOptimize(span);\n  for (auto _ : state) {\n    uint64_t index_seed = 0;\n    for (size_t j = 0; j < container.size(); ++j) {\n      index_seed += 5623;\n      const uint64_t index = index_seed % span.size();\n      benchmark::DoNotOptimize(span[index]);\n    }\n  }\n}\n\n// Sequential access int.\nBENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>);\nBENCHMARK_TEMPLATE(BM_Sequential, std::deque<int>);\nBENCHMARK_TEMPLATE(BM_Sequential_Span, std::vector<int>);\nBENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::vector<int>);\nBENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::deque<int>);\n\n// Sequential access string.\nBENCHMARK_TEMPLATE(BM_Sequential, std::vector<std::string>);\nBENCHMARK_TEMPLATE(BM_Sequential, std::deque<std::string>);\nBENCHMARK_TEMPLATE(BM_Sequential_Span, std::vector<std::string>);\nBENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::vector<std::string>);\nBENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::deque<std::string>);\nBENCHMARK_TEMPLATE(BM_Sequential_DerefSpan, std::vector<std::string*>);\nBENCHMARK_TEMPLATE(BM_Sequential_AnySpanDeref, std::vector<std::string*>);\n\n// Random access int.\nBENCHMARK_TEMPLATE(BM_Random, std::vector<int>);\nBENCHMARK_TEMPLATE(BM_Random, std::deque<int>);\nBENCHMARK_TEMPLATE(BM_Random_Span, std::vector<int>);\nBENCHMARK_TEMPLATE(BM_Random_AnySpan, std::vector<int>);\nBENCHMARK_TEMPLATE(BM_Random_AnySpan, std::deque<int>);\n\n// Random access string.\nBENCHMARK_TEMPLATE(BM_Random, std::vector<std::string>);\nBENCHMARK_TEMPLATE(BM_Random, std::deque<std::string>);\nBENCHMARK_TEMPLATE(BM_Random_Span, std::vector<std::string>);\nBENCHMARK_TEMPLATE(BM_Random_AnySpan, std::vector<std::string>);\nBENCHMARK_TEMPLATE(BM_Random_AnySpan, std::deque<std::string>);\nBENCHMARK_TEMPLATE(BM_Random_AnySpanDeref, std::vector<std::string*>);\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/types/any_span_test.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/types/any_span.h\"\n\n#include <cstddef>\n#include <deque>\n#include <functional>\n#include <iterator>\n#include <memory>\n#include <optional>\n#include <string>\n#include <string_view>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/exception_testing.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/str_cat.h\"\n#include \"absl/strings/string_view.h\"\n#include \"absl/types/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nusing testing::ElementsAre;\n\nstatic_assert(!absl::type_traits_internal::IsOwner<AnySpan<int>>::value &&\n                  absl::type_traits_internal::IsView<AnySpan<int>>::value,\n              \"AnySpan is a view, not an owner\");\n\n// Tests that the span points to all of the elements of the given container.\ntemplate <typename T, typename Container>\nvoid ExpectSpanEqualsContainer(AnySpan<T> span, const Container& c) {\n  EXPECT_EQ(span.size(), c.size());\n  EXPECT_EQ(span.length(), c.size());\n  typename AnySpan<const T>::size_type index = 0;\n  for (const T& s : span) {\n    SCOPED_TRACE(index);\n    const T& expected = c[index];\n    EXPECT_EQ(expected, s);\n    EXPECT_EQ(expected, span[index]);\n    EXPECT_EQ(&expected, &span[index]);\n    ++index;\n  }\n  EXPECT_EQ(index, span.size());\n}\n\n// AnySpanTest covers parts of AnySpan that make sense for both const and\n// non-const elements. How the given tests will run is determined by whether or\n// not ElementsAreConst is true_type or false_type.\ntemplate <typename ElementsAreConst>\nclass AnySpanTest : public ::testing::Test {\n public:\n  using IsConstTest = ElementsAreConst;\n\n  // Const T if this test instantiation is supposed to cover const AnySpans.\n  // T if this test instantiation is supposed to cover mutable AnySpans.\n  template <typename T>\n  using MaybeConst =\n      typename std::conditional<IsConstTest::value, const T, T>::type;\n\n  // Initalizes a AnySpan around the given container and tests for\n  // equality in a variety of ways.\n  template <typename T, typename Container, typename Transform>\n  static void TestContainer(Container c, const Transform& t) {\n    AnySpan<MaybeConst<T>> span(c, t);\n    EXPECT_NO_FATAL_FAILURE(ExpectSpanEqualsContainer(span, c));\n  }\n\n  // Initializes a dereferencing AnySpan around the given container of pointers\n  // and tests for equality in a variety of ways.\n  template <typename T, typename Container>\n  static void TestPointerContainer(Container* c) {\n    AnySpan<const T> span(*c, any_span_transform::Deref());\n    EXPECT_EQ(span.size(), c->size());\n    int index = 0;\n    for (const T& s : span) {\n      const T& expected = *(*c)[index];\n      EXPECT_EQ(expected, s);\n      EXPECT_EQ(expected, span[index]);\n      EXPECT_EQ(&expected, &span[index]);\n      index++;\n    }\n    EXPECT_EQ(index, span.size());\n  }\n};\n\nusing ElementsAreConst = ::testing::Types<std::true_type, std::false_type>;\n\nTYPED_TEST_SUITE(AnySpanTest, ElementsAreConst);\n\nTYPED_TEST(AnySpanTest, NullAndEmpty) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  AnySpan<T> empty;\n  EXPECT_TRUE(empty.empty());\n  EXPECT_EQ(empty.size(), 0);\n  for (const std::string& a : empty) {\n    (void)a;\n    ABSL_RAW_LOG(FATAL, \"Empty container should not iterate.\");\n  }\n  EXPECT_EQ(empty.begin(), empty.end());\n}\n\nTYPED_TEST(AnySpanTest, Ptr) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<T> span1(v.data(), v.size());\n  EXPECT_EQ(&span1[0], &v[0]);\n  AnySpan<T> span2(v.data(), v.size());\n  EXPECT_EQ(&span2[0], &v[0]);\n}\n\nTYPED_TEST(AnySpanTest, PtrPtr) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  int i;\n  std::vector<int*> v = {&i};\n  AnySpan<T> span(v.data(), v.size(), any_span_transform::Deref());\n  EXPECT_EQ(&span[0], &i);\n}\n\nTYPED_TEST(AnySpanTest, DerefOptional) {\n  const std::vector<std::optional<int>> v = {17, 19};\n  const AnySpan<const int> span = absl::MakeDerefAnySpan(v);\n  EXPECT_THAT(span, ElementsAre(17, 19));\n}\n\nTYPED_TEST(AnySpanTest, ArrayOfKnownSize) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::string a[] = {\"a\", \"b\", \"c\", \"d\"};\n\n  AnySpan<T> span(a);\n  EXPECT_EQ(span.size(), 4);\n  EXPECT_EQ(&span[0], &a[0]);\n}\n\n// This gets its own test because AnySpan(array, size) has the potential to be\n// ambiguous with AnySpan(array, transform).\nTYPED_TEST(AnySpanTest, ArrayWithExplicitSize) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::string a[] = {\"a\", \"b\", \"c\", \"d\"};\n\n  AnySpan<T> span(a, 4);\n  EXPECT_EQ(span.size(), 4);\n  EXPECT_EQ(&span[0], &a[0]);\n}\n\nTYPED_TEST(AnySpanTest, PtrArrayOfKnownSize) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::string s;\n  std::string* a[] = {&s, &s, &s, &s};\n\n  AnySpan<T> span(a, any_span_transform::Deref());\n  EXPECT_EQ(span.size(), 4);\n  EXPECT_EQ(&span[0], &s);\n}\n\nTYPED_TEST(AnySpanTest, Range) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> a = {\"a\", \"b\", \"c\", \"d\"};\n  auto range = any_span_adaptor::MakeAdaptorFromRange(a.begin(), a.end());\n  AnySpan<T> span(range);\n  EXPECT_NO_FATAL_FAILURE(ExpectSpanEqualsContainer(span, a));\n}\n\nTYPED_TEST(AnySpanTest, View) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> a = {\"a\", \"b\", \"c\", \"d\"};\n  auto range = any_span_adaptor::MakeAdaptorFromView(a);\n  AnySpan<T> span(range);\n  EXPECT_NO_FATAL_FAILURE(ExpectSpanEqualsContainer(span, a));\n}\n\nTYPED_TEST(AnySpanTest, VectorString) {\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<std::string>(\n      std::vector<std::string>{\"a\", \"b\", \"c\", \"d\"},\n      any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, VectorInt) {\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<int>(\n      std::vector<int>{1, 2, 3, 4}, any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, VectorStringPointer) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  std::vector<std::string*> vp;\n  for (std::string& s : v) {\n    vp.push_back(&s);\n  }\n  TestFixture::template TestPointerContainer<std::string>(&vp);\n}\n\nTYPED_TEST(AnySpanTest, VectorStringUniquePointer) {\n  std::vector<std::unique_ptr<std::string>> v;\n  for (const std::string& s : std::vector<std::string>{\"a\", \"b\", \"c\", \"d\"}) {\n    v.emplace_back(new std::string(s));\n  }\n  TestFixture::template TestPointerContainer<std::string>(&v);\n}\n\nTYPED_TEST(AnySpanTest, VectorIntPointer) {\n  std::vector<int> v = {1, 2, 3, 4};\n  std::vector<int*> vp;\n  for (int& i : v) {\n    vp.push_back(&i);\n  }\n  TestFixture::template TestPointerContainer<int>(&vp);\n}\n\nTYPED_TEST(AnySpanTest, DequeString) {\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<std::string>(\n      std::deque<std::string>{\"a\", \"b\", \"c\", \"d\"},\n      any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, DequeInt) {\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<int>(\n      std::deque<int>{1, 2, 3, 4}, any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, DequeStringPtr) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  std::deque<std::string*> dp;\n  for (std::string& s : v) {\n    dp.push_back(&s);\n  }\n  TestFixture::template TestPointerContainer<std::string>(&dp);\n}\n\nTYPED_TEST(AnySpanTest, ImplicitConversions) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::string one = \"1\";\n  std::string two = \"2\";\n  std::vector<std::reference_wrapper<std::string>> v(\n      {std::ref(one), std::ref(two)});\n  AnySpan<T> span(v);\n\n  EXPECT_THAT(span, ElementsAre(\"1\", \"2\"));\n}\n\nTYPED_TEST(AnySpanTest, TrivialSubspan) {\n  EXPECT_EQ(AnySpan<int>().subspan(0).size(), 0);\n}\n\nTYPED_TEST(AnySpanTest, TrivialFirst) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  EXPECT_EQ(AnySpan<T>().first(0).size(), 0);\n}\n\nTYPED_TEST(AnySpanTest, TrivialLast) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  EXPECT_EQ(AnySpan<T>().last(0).size(), 0);\n}\n\nstruct Base1 {\n  virtual ~Base1() = default;\n  bool operator==(const Base1& other) const { return this == &other; }\n  int b1 = 1;\n};\nstruct Base2 {\n  virtual ~Base2() = default;\n  bool operator==(const Base2& other) const { return this == &other; }\n  int b2 = 2;\n};\nstruct Child : public Base1, public Base2 {\n  bool operator==(const Child& other) const { return this == &other; }\n};\n\nTYPED_TEST(AnySpanTest, VectorBaseClass) {\n  std::vector<Child> v;\n  v.resize(20);\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(\n      v, any_span_transform::Identity()));\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(\n      v, any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, AnySpanVectorBaseClass) {\n  std::vector<Child> v;\n  v.resize(20);\n  AnySpan<Child> span(v);\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(\n      span, any_span_transform::Identity()));\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(\n      span, any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, DerefAnySpanVectorBaseClass) {\n  Child c;\n  std::vector<Child*> v_ptrs(20, &c);\n  AnySpan<Child> span(v_ptrs, any_span_transform::Deref());\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(\n      span, any_span_transform::Identity()));\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(\n      span, any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, AnySpanDequeBaseClass) {\n  std::deque<Child> v;\n  v.resize(20);\n  AnySpan<Child> span(v);\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(\n      span, any_span_transform::Identity()));\n  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(\n      span, any_span_transform::Identity()));\n}\n\nTYPED_TEST(AnySpanTest, VectorSubspan) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {1, 2, 3, 4};\n  auto span = AnySpan<T>(v).subspan(1, 2);\n  EXPECT_EQ(span.size(), 2);\n  EXPECT_EQ(span[0], 2);\n  EXPECT_EQ(span[1], 3);\n  span = AnySpan<T>(v).subspan(1);\n  EXPECT_EQ(span.size(), 3);\n  EXPECT_EQ(span[2], 4);\n\n  std::vector<int> zero_length_vector;\n  auto zero_length_subspan = AnySpan<T>(zero_length_vector).subspan(0);\n  EXPECT_EQ(zero_length_subspan.size(), 0);\n}\n\nTYPED_TEST(AnySpanTest, DequeSubspan) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::deque<int> v = {1, 2, 3, 4};\n  auto span = AnySpan<T>(v).subspan(1, 2);\n  EXPECT_EQ(span.size(), 2);\n  EXPECT_EQ(span[0], 2);\n  EXPECT_EQ(span[1], 3);\n}\n\nTYPED_TEST(AnySpanTest, VectorFirst) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {1, 2, 3, 4};\n  auto span = AnySpan<T>(v).first(2);\n  EXPECT_THAT(span, ElementsAre(1, 2));\n  span = AnySpan<T>(v).first(4);\n  EXPECT_THAT(span, ElementsAre(1, 2, 3, 4));\n  span = AnySpan<T>(v).first(6);\n  EXPECT_THAT(span, ElementsAre(1, 2, 3, 4));\n\n  std::vector<int> zero_length_vector;\n  auto zero_length_subspan = AnySpan<T>(zero_length_vector).first(0);\n  EXPECT_EQ(zero_length_subspan.size(), 0);\n}\n\nTYPED_TEST(AnySpanTest, DequeFirst) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::deque<int> v = {1, 2, 3, 4};\n  auto span = AnySpan<T>(v).first(2);\n  EXPECT_THAT(span, ElementsAre(1, 2));\n}\n\nTYPED_TEST(AnySpanTest, VectorLast) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {1, 2, 3, 4};\n  auto span = AnySpan<T>(v).last(2);\n  EXPECT_THAT(span, ElementsAre(3, 4));\n  span = AnySpan<T>(v).last(4);\n  EXPECT_THAT(span, ElementsAre(1, 2, 3, 4));\n\n  std::vector<int> zero_length_vector;\n  auto zero_length_subspan = AnySpan<T>(zero_length_vector).last(0);\n  EXPECT_EQ(zero_length_subspan.size(), 0);\n}\n\nTYPED_TEST(AnySpanTest, DequeLast) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::deque<int> v = {1, 2, 3, 4};\n  auto span = AnySpan<T>(v).last(2);\n  EXPECT_THAT(span, ElementsAre(3, 4));\n}\n\nTYPED_TEST(AnySpanTest, LambdaTransformFromVector) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"b\", \"a\", \"d\", \"c\"};\n  std::vector<int> alphabetical_order = {1, 0, 3, 2};\n  auto subscript_v = [&v](size_t i) -> std::string& { return v[i]; };\n  AnySpan<T> span(alphabetical_order, subscript_v);\n  EXPECT_EQ(span[0], \"a\");\n  EXPECT_EQ(span[1], \"b\");\n  EXPECT_EQ(span[2], \"c\");\n  EXPECT_EQ(span[3], \"d\");\n}\n\nTYPED_TEST(AnySpanTest, LambdaTransformFromSpanOfDifferentType) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  using U = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"b\", \"a\", \"d\", \"c\"};\n  std::vector<int> alphabetical_order = {1, 0, 3, 2};\n  AnySpan<T> alphabetical_order_as_span(alphabetical_order);\n  auto subscript_v = [&v](size_t i) -> std::string& { return v[i]; };\n  AnySpan<U> span(alphabetical_order_as_span, subscript_v);\n  EXPECT_EQ(span[0], \"a\");\n  EXPECT_EQ(span[1], \"b\");\n  EXPECT_EQ(span[2], \"c\");\n  EXPECT_EQ(span[3], \"d\");\n}\n\nTYPED_TEST(AnySpanTest, LambdaTransformFromSpanOfSameType) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {2, 1, 4, 3};\n  std::vector<int> sorted_order = {1, 0, 3, 2};\n  AnySpan<T> sorted_order_as_span(sorted_order);\n  auto subscript_v = [&v](size_t i) -> int& { return v[i]; };\n  AnySpan<T> span(sorted_order_as_span, subscript_v);\n  EXPECT_EQ(span[0], 1);\n  EXPECT_EQ(span[1], 2);\n  EXPECT_EQ(span[2], 3);\n  EXPECT_EQ(span[3], 4);\n}\n\nTYPED_TEST(AnySpanTest, MakeAnySpanFromVector) {\n  using V = typename TestFixture::template MaybeConst<std::vector<int>>;\n  using T = typename TestFixture::template MaybeConst<int>;\n  V v = {1, 2, 3, 4};\n  auto span = MakeAnySpan(v);\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));\n  EXPECT_EQ(span.size(), 4);\n  for (size_t i = 0; i < 4; ++i) {\n    EXPECT_EQ(&span[i], &v[i]);\n  }\n}\n\nTYPED_TEST(AnySpanTest, MakeAnySpanFromPtrAndSize) {\n  using V = typename TestFixture::template MaybeConst<std::vector<int>>;\n  using T = typename TestFixture::template MaybeConst<int>;\n  V v = {1, 2, 3, 4};\n  auto span = MakeAnySpan(v.data(), v.size());\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));\n  EXPECT_EQ(span.size(), 4);\n  for (int i = 0; i < 4; ++i) {\n    EXPECT_EQ(&span[i], &v[i]);\n  }\n}\n\nTYPED_TEST(AnySpanTest, MakeAnySpanFromArray) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  T a[] = {1, 2, 3, 4};\n  auto span = MakeAnySpan(a);\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));\n  EXPECT_EQ(span.size(), 4);\n  for (int i = 0; i < 4; ++i) {\n    EXPECT_EQ(&span[i], &a[i]);\n  }\n}\n\nTYPED_TEST(AnySpanTest, MakeDerefAnySpanFromArray) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  T v = 0;\n  T* a[] = {&v, &v, &v};\n  auto span = MakeDerefAnySpan(a);\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));\n  EXPECT_EQ(span.size(), 3);\n  for (int i = 0; i < 3; ++i) {\n    EXPECT_EQ(&span[i], a[i]);\n  }\n}\n\n// Tests transforms that are supported by std::invoke.\nTYPED_TEST(AnySpanTest, InvokableTransforms) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  struct S;\n  using SRef = typename TestFixture::template MaybeConst<S>&;\n  struct S {\n    std::string a, b;\n    static T& Fun(SRef p) { return p.a; }\n    std::string& MemFun() { return a; }\n    const std::string& MemFun() const { return a; }\n  };\n\n  // For const span tests, we need a pointer to constant member function. We\n  // choose the correct type of member function here.\n  using MemFunPtr =\n      typename std::conditional<TestFixture::IsConstTest::value,\n                                T& (S::*)() const, T& (S::*)()>::type;\n\n  std::vector<S> v = {{\"1\", \"2\"}, {\"3\", \"4\"}};\n  S a[] = {{\"1\", \"2\"}, {\"3\", \"4\"}};\n  T& (*fun_ptr)(SRef) = &S::Fun;\n  MemFunPtr mem_fun_ptr = &S::MemFun;\n  T S::* mem_ptr = &S::a;\n\n  AnySpan<T> spans[] = {\n      // Function reference.\n      AnySpan<T>(v, S::Fun),\n      AnySpan<T>(a, S::Fun),\n      AnySpan<T>(a, 2, S::Fun),\n\n      // Function pointer prvalue.\n      AnySpan<T>(v, &S::Fun),\n      AnySpan<T>(a, &S::Fun),\n      AnySpan<T>(a, 2, &S::Fun),\n\n      // Function pointer lvalue.\n      AnySpan<T>(v, fun_ptr),\n      AnySpan<T>(a, fun_ptr),\n      AnySpan<T>(a, 2, fun_ptr),\n\n      // Dereferenced function pointer variable.\n      AnySpan<T>(v, *fun_ptr),\n      AnySpan<T>(a, *fun_ptr),\n      AnySpan<T>(a, 2, *fun_ptr),\n\n      // Member function pointer.\n      AnySpan<T>(v, mem_fun_ptr),\n      AnySpan<T>(a, mem_fun_ptr),\n      AnySpan<T>(a, 2, mem_fun_ptr),\n\n      // Data member.\n      AnySpan<T>(v, mem_ptr),\n      AnySpan<T>(a, mem_ptr),\n      AnySpan<T>(a, 2, mem_ptr),\n  };\n\n  for (const auto& span : spans) {\n    EXPECT_EQ(span[0], \"1\");\n    EXPECT_EQ(span[1], \"3\");\n  }\n}\n\nTYPED_TEST(AnySpanTest, VectorPtrSubspan) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {1, 2, 3, 4};\n  std::vector<int*> vp;\n  for (int& i : v) {\n    vp.push_back(&i);\n  }\n  AnySpan<T> span = AnySpan<T>(vp, any_span_transform::Deref()).subspan(1, 2);\n  EXPECT_EQ(span.size(), 2);\n  EXPECT_EQ(span[0], 2);\n  EXPECT_EQ(span[1], 3);\n}\n\nTYPED_TEST(AnySpanTest, VectorPtrFirst) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {1, 2, 3, 4};\n  std::vector<int*> vp;\n  for (int& i : v) {\n    vp.push_back(&i);\n  }\n  AnySpan<T> span = AnySpan<T>(vp, any_span_transform::Deref()).first(2);\n  EXPECT_THAT(span, ElementsAre(1, 2));\n}\n\nTYPED_TEST(AnySpanTest, VectorPtrLast) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  std::vector<int> v = {1, 2, 3, 4};\n  std::vector<int*> vp;\n  for (int& i : v) {\n    vp.push_back(&i);\n  }\n  AnySpan<T> span = AnySpan<T>(vp, any_span_transform::Deref()).last(2);\n  EXPECT_THAT(span, ElementsAre(3, 4));\n}\n\nTYPED_TEST(AnySpanTest, Iterator) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"0\", \"1\", \"2\", \"3\"};\n  AnySpan<T> span(v);\n\n  // Dereference.\n  auto it = span.begin();\n  EXPECT_EQ(\"0\", *it);\n\n  // Postfix increment.\n  EXPECT_EQ(\"0\", *(it++));\n  EXPECT_EQ(\"1\", *(it++));\n\n  // Postfix decrement.\n  EXPECT_EQ(\"2\", *(it--));\n  EXPECT_EQ(\"1\", *(it--));\n\n  // Prefix increment.\n  EXPECT_EQ(it, span.begin());\n  EXPECT_EQ(\"1\", *(++it));\n  EXPECT_EQ(\"2\", *(++it));\n\n  // Postfix decrement.\n  EXPECT_EQ(\"1\", *(--it));\n  EXPECT_EQ(\"0\", *(--it));\n\n  // Increment by integer.\n  EXPECT_EQ(it, span.begin());\n  it += 3;\n  EXPECT_EQ(\"3\", *it);\n\n  // Decrement by integer.\n  it = span.end();\n  it -= 4;\n  EXPECT_EQ(\"0\", *it);\n\n  // Add and subtract.\n  EXPECT_EQ(v.begin() + 2, v.end() - 2);\n  EXPECT_EQ(2 + v.begin(), v.end() - 2);\n\n  // Index.\n  it = span.begin();\n  EXPECT_EQ(\"3\", v[3]);\n\n  // Relational operators.\n  EXPECT_TRUE(span.begin() != span.end());\n  EXPECT_TRUE(span.begin() == span.begin());\n  EXPECT_TRUE(span.begin() < span.end());\n  EXPECT_TRUE(span.begin() <= span.end());\n  EXPECT_TRUE(span.end() > span.begin());\n  EXPECT_TRUE(span.end() >= span.begin());\n}\n\nTYPED_TEST(AnySpanTest, ConstIterator) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"0\", \"1\", \"2\", \"3\"};\n  AnySpan<T> span(v);\n\n  // Dereference.\n  auto it = span.cbegin();\n  EXPECT_EQ(\"0\", *it);\n\n  // Postfix increment.\n  EXPECT_EQ(\"0\", *(it++));\n  EXPECT_EQ(\"1\", *(it++));\n\n  // Postfix decrement.\n  EXPECT_EQ(\"2\", *(it--));\n  EXPECT_EQ(\"1\", *(it--));\n\n  // Prefix increment.\n  EXPECT_EQ(it, span.cbegin());\n  EXPECT_EQ(\"1\", *(++it));\n  EXPECT_EQ(\"2\", *(++it));\n\n  // Postfix decrement.\n  EXPECT_EQ(\"1\", *(--it));\n  EXPECT_EQ(\"0\", *(--it));\n\n  // Increment by integer.\n  EXPECT_EQ(it, span.cbegin());\n  it += 3;\n  EXPECT_EQ(\"3\", *it);\n\n  // Decrement by integer.\n  it = span.cend();\n  it -= 4;\n  EXPECT_EQ(\"0\", *it);\n\n  // Add and subtract.\n  EXPECT_EQ(v.cbegin() + 2, v.cend() - 2);\n  EXPECT_EQ(2 + v.cbegin(), v.cend() - 2);\n\n  // Index.\n  it = span.cbegin();\n  EXPECT_EQ(\"3\", v[3]);\n\n  // Relational operators.\n  EXPECT_TRUE(span.cbegin() != span.cend());\n  EXPECT_TRUE(span.cbegin() == span.cbegin());\n  EXPECT_TRUE(span.cbegin() < span.cend());\n  EXPECT_TRUE(span.cbegin() <= span.cend());\n  EXPECT_TRUE(span.cend() > span.cbegin());\n  EXPECT_TRUE(span.cend() >= span.cbegin());\n}\n\nTYPED_TEST(AnySpanTest, ReverseIterator) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<T> span(v);\n  auto v_it = v.rbegin();\n  for (auto it = span.rbegin(); it != span.rend(); ++it, ++v_it) {\n    EXPECT_EQ(*v_it, *it);\n  }\n}\n\nTYPED_TEST(AnySpanTest, IndexingAt) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<T> span(v);\n  EXPECT_EQ(&v.at(0), &v.at(0));\n  EXPECT_EQ(&v.at(1), &v.at(1));\n  EXPECT_EQ(&v.at(3), &v.at(3));\n}\n\nTYPED_TEST(AnySpanTest, AtThrows) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<T> span(v);\n  ABSL_BASE_INTERNAL_EXPECT_FAIL(span.at(4), std::out_of_range,\n                                 \"failed bounds check\");\n}\n\nTYPED_TEST(AnySpanTest, FrontBack) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<T> span(v);\n  EXPECT_EQ(&v.front(), &span.front());\n  EXPECT_EQ(\"a\", span.front());\n  EXPECT_EQ(&v.back(), &span.back());\n  EXPECT_EQ(\"d\", span.back());\n}\n\n// Returns a reference to a default constructed instance of the given type.\ntemplate <typename Container>\nContainer& DefaultInstance() {\n  static auto* c = new Container;\n  return *c;\n}\n\n// This test reaches into the implementation a bit, but it buys a lot of\n// confidence that the flat-array optimizations are working correctly.\nTYPED_TEST(AnySpanTest, CheapTypes) {\n  using T = typename TestFixture::template MaybeConst<int>;\n  using any_span_internal::IsCheap;\n  EXPECT_FALSE(IsCheap(AnySpan<T>(DefaultInstance<std::deque<int>>())));\n  EXPECT_FALSE(\n      IsCheap(AnySpan<T>(DefaultInstance<std::vector<std::unique_ptr<int>>>(),\n                         any_span_transform::Deref())));\n  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int>>())));\n  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<absl::Span<int>>())));\n  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int>>())));\n  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int*>>(),\n                                 any_span_transform::Deref())));\n  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int*>>(),\n                                 any_span_transform::Deref())));\n  struct SomeContainer {\n    int& operator[](std::size_t) { ABSL_RAW_LOG(FATAL, \"Not implemented\"); }\n    const int& operator[](std::size_t) const {\n      ABSL_RAW_LOG(FATAL, \"Not implemented\");\n    }\n    std::size_t size() const { return 1; }\n  };\n  EXPECT_FALSE(IsCheap(AnySpan<T>(DefaultInstance<SomeContainer>())));\n  struct SomeCheapMutableContainer {\n    int& operator[](std::size_t) const {\n      ABSL_RAW_LOG(FATAL, \"Not implemented\");\n    }\n    int* data() const { return nullptr; }\n    std::size_t size() const { return 1; }\n  };\n  EXPECT_TRUE(\n      IsCheap(AnySpan<T>(DefaultInstance<SomeCheapMutableContainer>())));\n\n  struct SomeWonkyContainer {\n    int& operator[](std::size_t) const {\n      ABSL_RAW_LOG(FATAL, \"Not implemented\");\n    }\n    const int** data() const { return nullptr; }\n    std::size_t size() const { return 1; }\n  };\n  EXPECT_FALSE(IsCheap(AnySpan<T>(DefaultInstance<SomeWonkyContainer>())));\n}\n\nTYPED_TEST(AnySpanTest, TriviallyCopyable) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  // Note: we could use is_trivially_copyable, but it is not implemented in\n  // Crosstool v18 which is the current version at the time of writing.\n  EXPECT_TRUE(std::is_trivially_copy_constructible<AnySpan<T>>::value);\n  EXPECT_TRUE(std::is_trivially_copy_assignable<AnySpan<T>>::value);\n  EXPECT_TRUE(std::is_trivially_destructible<AnySpan<T>>::value);\n}\n\nTYPED_TEST(AnySpanTest, IsConstructible) {\n  using T = typename TestFixture::template MaybeConst<std::string>;\n  using U = typename TestFixture::template MaybeConst<int>;\n  using VectorT =\n      typename TestFixture::template MaybeConst<std::vector<std::string>>;\n  using VectorU = typename TestFixture::template MaybeConst<std::vector<int>>;\n  EXPECT_FALSE((std::is_constructible<AnySpan<T>, T>::value));\n  EXPECT_FALSE((std::is_constructible<AnySpan<T>, T*>::value));\n  EXPECT_FALSE((std::is_constructible<AnySpan<T>, U>::value));\n  EXPECT_FALSE((std::is_constructible<AnySpan<T>, U(&)[5]>::value));\n  EXPECT_FALSE((std::is_constructible<AnySpan<T>, U*, std::size_t>::value));\n  EXPECT_FALSE((std::is_constructible<AnySpan<T>, VectorU&>::value));\n\n  EXPECT_TRUE((std::is_constructible<AnySpan<T>, VectorT&>::value));\n  EXPECT_TRUE((std::is_constructible<AnySpan<T>, T(&)[5]>::value));\n  EXPECT_TRUE((std::is_constructible<AnySpan<T>, T*, std::size_t>::value));\n}\n\n//\n// ConstAnySpanTest covers parts of AnySpan interface that are only valid for\n// AnySpans with const elements.\n//\n\nTEST(ConstAnySpanTest, ImplicitConversion) {\n  std::vector<int> v = {1, 2, 3};\n  ExpectSpanEqualsContainer<const int>(v, v);\n}\n\nTEST(ConstAnySpanTest, TemporaryArrayOfKnownSize) {\n  const int i = 5;\n  EXPECT_THAT(AnySpan<const int>({&i, &i, &i}, any_span_transform::Deref()),\n              testing::ElementsAre(5, 5, 5));\n}\n\nTEST(ConstAnySpanTest, CheapTypes) {\n  using any_span_internal::IsCheap;\n  EXPECT_TRUE(IsCheap(AnySpan<const int>(std::vector<const int*>(),\n                                         any_span_transform::Deref())));\n  EXPECT_TRUE(IsCheap(AnySpan<const int>(std::vector<const int*>(),\n                                         any_span_transform::Deref())));\n  EXPECT_TRUE(\n      IsCheap(AnySpan<const int>(DefaultInstance<absl::Span<const int>>())));\n  struct SomeCheapConstContainer {\n    const int& operator[](std::size_t) const {\n      ABSL_RAW_LOG(FATAL, \"Not implemented\");\n    }\n    const int* data() const { return nullptr; }\n    std::size_t size() const { return 1; }\n  };\n  EXPECT_TRUE(IsCheap(AnySpan<const int>(SomeCheapConstContainer())));\n}\n\nTEST(ConstAnySpanTest, InitializerListInt) {\n  auto test = [](AnySpan<const int> span) {\n    int expected = 1;\n    for (int i : span) {\n      EXPECT_EQ(expected++, i);\n    }\n    EXPECT_EQ(expected, 5);\n  };\n  test({1, 2, 3, 4});\n}\n\nTEST(ConstAnySpanTest, InitializerListString) {\n  auto test = [](AnySpan<const std::string> span) {\n    int expected = 1;\n    for (const std::string& i : span) {\n      EXPECT_EQ(absl::StrCat(expected++), i);\n    }\n    EXPECT_EQ(expected, 5);\n  };\n  test({\"1\", \"2\", \"3\", \"4\"});\n}\n\nTEST(ConstAnySpanTest, InitializerListDerivedToBase) {\n  // Derived to base, implicit conversion.\n  [](AnySpan<const Base2> bases) {\n    for (const Base2& b : bases) {\n      EXPECT_EQ(b.b2, 2);\n      // Make sure the value was not sliced.\n      EXPECT_EQ(typeid(b), typeid(Child));\n    }\n  }({Child{}, Child{}, Child{}});\n\n  // Derived to base with explicit transform.\n  Child children[3];\n  [](AnySpan<const Base2> bases) {\n    for (const Base2& b : bases) {\n      EXPECT_EQ(b.b2, 2);\n      // Make sure the value was not sliced.\n      EXPECT_EQ(typeid(b), typeid(Child));\n    }\n  }({{Child{}, Child{}, Child{}},\n     [](auto& obj) -> const Base2& { return obj; }});\n}\n\nTEST(ConstAnySpanTest,\n     InitializerListUsesValueTypeWhenConversionNeedsTemporaries) {\n  // If this were to call the initializer_list<Element> overload it would fail\n  // when it tries to make an lvalue transform from std::string to\n  // std::string_view.\n  // Instead, it must be calling the initializer_list<value_type> overload,\n  // doing the conversion on the call site.\n  [](AnySpan<const std::string_view> s) {\n    EXPECT_THAT(s, ElementsAre(\"A\", \"B\", \"C\"));\n  }({\"A\", \"B\", \"C\"});\n}\n\nTEST(ConstAnySpanTest, MakeAnySpanFromVector) {\n  std::vector<int> v = {1, 2, 3, 4};\n  auto span = MakeConstAnySpan(v);\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));\n  EXPECT_EQ(span.size(), 4);\n  for (size_t i = 0; i < 4; ++i) {\n    EXPECT_EQ(&span[i], &v[i]);\n  }\n}\n\nTEST(ConstAnySpanTest, MakeAnySpanFromPtrAndSize) {\n  std::vector<int> v = {1, 2, 3, 4};\n  auto span = MakeConstAnySpan(v.data(), v.size());\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));\n  EXPECT_EQ(span.size(), 4);\n  for (size_t i = 0; i < 4; ++i) {\n    EXPECT_EQ(&span[i], &v[i]);\n  }\n}\n\nTEST(ConstAnySpanTest, MakeAnySpanFromArray) {\n  int a[] = {1, 2, 3, 4};\n  auto span = MakeConstAnySpan(a);\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));\n  EXPECT_EQ(span.size(), 4);\n  for (size_t i = 0; i < 4; ++i) {\n    EXPECT_EQ(&span[i], &a[i]);\n  }\n}\n\nTEST(ConstAnySpanTest, MakeDerefAnySpanFromArray) {\n  int v = 0;\n  int* a[] = {&v, &v, &v};\n  auto span = MakeConstDerefAnySpan(a);\n  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));\n  EXPECT_EQ(span.size(), 3);\n  for (size_t i = 0; i < 3; ++i) {\n    EXPECT_EQ(&span[i], a[i]);\n  }\n}\n\n//\n// MutableAnySpanTest covers parts of AnySpan interface that are only valid for\n// AnySpans with mutable elements.\n//\n\nTEST(MutableAnySpanTest, MutableVectorString) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<std::string> span(v);\n  span[0] = \"e\";\n  EXPECT_EQ(v[0], \"e\");\n}\n\nTEST(MutableAnySpanTest, MutableToConstConversion) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<std::string> mutable_span(v);\n  AnySpan<const std::string> const_span(mutable_span);\n  EXPECT_TRUE(any_span_internal::IsCheap(const_span));\n  mutable_span[0] = \"e\";\n  EXPECT_EQ(const_span[0], \"e\");\n  mutable_span.subspan(1)[0] = \"f\";\n  EXPECT_EQ(const_span[1], \"f\");\n\n  std::vector<std::string> v2 = {\"a\"};\n  mutable_span = AnySpan<std::string>(v2);\n  EXPECT_EQ(const_span[0], \"e\");\n}\n\nTEST(MutableAnySpanTest, DerefMutableToConstConversion) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  std::vector<std::string*> v_ptrs;\n  for (std::string& s : v) {\n    v_ptrs.push_back(&s);\n  }\n  AnySpan<std::string> mutable_span(v_ptrs, any_span_transform::Deref());\n  AnySpan<const std::string> const_span(mutable_span);\n  EXPECT_TRUE(any_span_internal::IsCheap(const_span));\n  mutable_span[0] = \"e\";\n  EXPECT_EQ(const_span[0], \"e\");\n  EXPECT_EQ(v[0], \"e\");\n  mutable_span.subspan(1)[0] = \"f\";\n  EXPECT_EQ(const_span[1], \"f\");\n}\n\nTEST(MutableAnySpanTest, MutableToConstDeque) {\n  std::deque<std::string> d = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<std::string> mutable_span(d);\n  AnySpan<const std::string> const_span(mutable_span);\n  EXPECT_FALSE(any_span_internal::IsCheap(const_span));\n  mutable_span[0] = \"e\";\n  EXPECT_EQ(const_span[0], \"e\");\n  mutable_span.subspan(1)[0] = \"f\";\n  EXPECT_EQ(const_span[1], \"f\");\n}\n\nTEST(MutableAnySpanTest, Deref) {\n  std::string s = \"a\";\n  AnySpan<std::string>({&s}, any_span_transform::Deref())[0] = \"b\";\n  EXPECT_EQ(s, \"b\");\n}\n\n// Checks that recommended usage works.\nTEST(MutableAnySpanTest, AsFunctionArgument) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  auto set_all_to_e = [](AnySpan<std::string> span) {\n    for (std::string& s : span) {\n      s = \"e\";\n    }\n  };\n  set_all_to_e(AnySpan<std::string>(v));\n  for (const std::string& e : v) {\n    EXPECT_EQ(e, \"e\");\n  }\n}\n\nTEST(MutableAnySpanTest, MutateThroughIterator) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  AnySpan<std::string> span(v);\n  AnySpan<std::string>::iterator it = span.begin();\n  it[2] = \"e\";\n  EXPECT_EQ(v[2], \"e\");\n  ++it;\n  *it = \"f\";\n  EXPECT_EQ(v[1], \"f\");\n  for (std::string& s : span) {\n    s = \"g\";\n  }\n  for (const std::string& e : v) {\n    EXPECT_EQ(e, \"g\");\n  }\n}\n\nTEST(MutableAnySpanTest, MutateThroughSubSpan) {\n  std::vector<int> v = {1, 2, 3, 4};\n  AnySpan<int> span(v);\n  span = span.subspan(1, 2);\n  for (int& i : span) {\n    i = 42;\n  }\n  EXPECT_THAT(v, ElementsAre(1, 42, 42, 4));\n}\n\nTEST(MutableAnySpanTest, IteratorToConstIteratorConversion) {\n  std::vector<int> v = {1};\n  AnySpan<int> span(v);\n  AnySpan<int>::iterator it = span.begin();\n  AnySpan<int>::const_iterator cit = it;\n  EXPECT_EQ(&*it, &*cit);\n}\n\n// Checks that implicit conversion from a mutable view works.\nTEST(MutableAnySpanTest, ImplicitConversionFromMutableSpan) {\n  std::vector<std::string> v = {\"a\", \"b\", \"c\", \"d\"};\n  absl::Span<std::string> mutable_slice(v);\n  auto set_all_to_e = [](AnySpan<std::string> span) {\n    for (std::string& s : span) {\n      s = \"e\";\n    }\n  };\n  set_all_to_e(mutable_slice);\n  for (const std::string& s : v) {\n    EXPECT_EQ(s, \"e\");\n  }\n}\n\nbool WantsStringOrAnySpan(absl::string_view /* ignored */) { return false; }\nbool WantsStringOrAnySpan(AnySpan<std::string> /* ignored */) { return true; }\nbool WantsStringOrConstAnySpan(absl::string_view /* ignored */) {\n  return false;\n}\nbool WantsStringOrConstAnySpan(AnySpan<const std::string> /* ignored */) {\n  return true;\n}\n// Checks that AnySpan(char (&array)[N]) is not used in the overload\n// resolution when building an AnySpan<string> (it would not compile anyway).\nTEST(MutableAnySpanTest, ResolveAmbiguityWithAnySpanOfChars) {\n  std::string foo;\n  AnySpan<std::string> bar;\n  EXPECT_FALSE(WantsStringOrAnySpan(\"abc\"));\n  EXPECT_FALSE(WantsStringOrAnySpan(foo));\n  EXPECT_TRUE(WantsStringOrAnySpan(bar));\n  EXPECT_FALSE(WantsStringOrConstAnySpan(\"abc\"));\n  EXPECT_FALSE(WantsStringOrConstAnySpan(foo));\n  EXPECT_TRUE(WantsStringOrConstAnySpan(bar));\n}\n\nTEST(AnySpanTest, SupportsAbslHash) {\n  std::vector<size_t> v = {1, 2, 3};\n  std::vector<std::string> vs = {\"1\", \"2\", \"3\"};\n  std::vector<std::unique_ptr<size_t>> vu;\n  vu.push_back(std::make_unique<size_t>(1));\n  vu.push_back(std::make_unique<size_t>(2));\n  vu.push_back(std::make_unique<size_t>(3));\n\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({\n      // {1, 2, 3}\n      AnySpan<const size_t>(v),\n      AnySpan<const size_t>(vu, any_span_transform::Deref()),\n      // {1, 2}\n      AnySpan<const size_t>(std::vector<size_t>({1, 2})),\n      AnySpan<const size_t>(std::deque<size_t>({1, 2})),\n      // {1, 2, 4}\n      AnySpan<const size_t>(std::vector<size_t>({1, 2, 4})),\n      AnySpan<const size_t>(std::deque<size_t>({1, 2, 4})),\n      // Empty.\n      AnySpan<const size_t>(),\n      AnySpan<const size_t>(std::vector<size_t>()),\n  }));\n}\n\n// This is necessary to avoid a bunch of lint warnings suggesting that we use\n// EXPECT_EQ/etc.\nbool Identity(bool b) { return b; }\n\ntemplate <typename T, typename U, typename V>\nvoid TestEquality(T&& orig, U&& eq, V&& diff) {\n  EXPECT_TRUE(Identity(std::forward<T>(orig) == std::forward<U>(eq)));\n  EXPECT_TRUE(Identity(std::forward<U>(eq) == std::forward<T>(orig)));\n  EXPECT_FALSE(Identity(std::forward<T>(orig) != std::forward<U>(eq)));\n  EXPECT_FALSE(Identity(std::forward<U>(eq) != std::forward<T>(orig)));\n\n  EXPECT_FALSE(Identity(std::forward<T>(orig) == std::forward<V>(diff)));\n  EXPECT_FALSE(Identity(std::forward<V>(diff) == std::forward<T>(orig)));\n  EXPECT_TRUE(Identity(std::forward<T>(orig) != std::forward<V>(diff)));\n  EXPECT_TRUE(Identity(std::forward<V>(diff) != std::forward<T>(orig)));\n}\n\nTEST(AnySpanTest, Equals) {\n  int arr[] = {1, 2, 3};\n  std::vector<int> eq(std::begin(arr), std::end(arr));\n  int diff[] = {1, 2, 4};\n  TestEquality(AnySpan<int>(arr), AnySpan<int>(eq), AnySpan<int>(diff));\n  TestEquality(AnySpan<const int>(arr), AnySpan<int>(eq), AnySpan<int>(diff));\n  TestEquality(AnySpan<int>(arr), AnySpan<const int>(eq),\n               AnySpan<const int>(diff));\n  TestEquality(AnySpan<const int>(arr), AnySpan<const int>(eq),\n               AnySpan<const int>(diff));\n\n  TestEquality(AnySpan<const int>(arr), eq, diff);\n  TestEquality(AnySpan<int>(arr), eq, diff);\n}\n\n// If an object is copied, mark the bool pointed by `copied` true.\nclass MarkIfCopied {\n public:\n  explicit MarkIfCopied(bool* copied) : copied_(copied) {}\n\n  // NOLINT_NEXT_LINE(google-explicit-constructor)\n  MarkIfCopied(const MarkIfCopied& other) { *this = other; }\n\n  MarkIfCopied& operator=(const MarkIfCopied& other) {\n    copied_ = other.copied_;\n    *copied_ = true;\n    return *this;\n  }\n\n private:\n  bool* copied_;\n};\n\nTEST(MarkIfCopied, EnsureWorks) {\n  bool copied = false;\n  MarkIfCopied item(&copied);\n  ASSERT_FALSE(copied);\n  MarkIfCopied _unused_copied_item(item);\n  EXPECT_TRUE(copied);\n}\n\nTEST(AnySpanTest, ReferenceWrapperNotCopied) {\n  bool copied1 = false;\n  bool copied2 = false;\n  MarkIfCopied item1(&copied1);\n  MarkIfCopied item2(&copied2);\n  std::vector<std::reference_wrapper<const MarkIfCopied>> items;\n  items.push_back(std::cref(item1));\n  items.push_back(std::cref(item2));\n  AnySpan<const MarkIfCopied> span(items);\n  EXPECT_EQ(2, span.size());\n  EXPECT_FALSE(copied1);\n  EXPECT_FALSE(copied2);\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/types/compare.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// compare.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines the `absl::partial_ordering`, `absl::weak_ordering`,\n// and `absl::strong_ordering` types for storing the results of three way\n// comparisons.\n//\n// Example:\n//   absl::weak_ordering compare(const std::string& a, const std::string& b);\n//\n// These are C++11 compatible versions of the C++20 corresponding types\n// (`std::partial_ordering`, etc.) and are designed to be drop-in replacements\n// for code compliant with C++20.\n\n#ifndef ABSL_TYPES_COMPARE_H_\n#define ABSL_TYPES_COMPARE_H_\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_USES_STD_ORDERING\n\n#include <compare>  // IWYU pragma: export\n#include <type_traits>\n\n#include \"absl/meta/type_traits.h\"\n\n#else\n\n#include <cstddef>\n#include <cstdint>\n#include <cstdlib>\n#include <type_traits>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/meta/type_traits.h\"\n\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n#ifdef ABSL_USES_STD_ORDERING\n\nusing std::partial_ordering;\nusing std::strong_ordering;\nusing std::weak_ordering;\n\n#else\n\nnamespace compare_internal {\n\nusing value_type = int8_t;\n\nclass OnlyLiteralZero {\n public:\n#if ABSL_HAVE_ATTRIBUTE(enable_if)\n  // On clang, we can avoid triggering modernize-use-nullptr by only enabling\n  // this overload when the value is a compile time integer constant equal to 0.\n  //\n  // In c++20, this could be a static_assert in a consteval function.\n  constexpr OnlyLiteralZero(int n)  // NOLINT\n      __attribute__((enable_if(n == 0, \"Only literal `0` is allowed.\"))) {}\n#else  // ABSL_HAVE_ATTRIBUTE(enable_if)\n  // Accept only literal zero since it can be implicitly converted to a pointer\n  // to member type. nullptr constants will be caught by the other constructor\n  // which accepts a nullptr_t.\n  //\n  // This constructor is not used for clang since it triggers\n  // modernize-use-nullptr.\n  constexpr OnlyLiteralZero(int OnlyLiteralZero::*) noexcept {}  // NOLINT\n#endif\n\n  // Fails compilation when `nullptr` or integral type arguments other than\n  // `int` are passed. This constructor doesn't accept `int` because literal `0`\n  // has type `int`. Literal `0` arguments will be implicitly converted to\n  // `std::nullptr_t` and accepted by the above constructor, while other `int`\n  // arguments will fail to be converted and cause compilation failure.\n  template <typename T, typename = typename std::enable_if<\n                            std::is_same<T, std::nullptr_t>::value ||\n                            (std::is_integral<T>::value &&\n                             !std::is_same<T, int>::value)>::type>\n  OnlyLiteralZero(T) {  // NOLINT\n    static_assert(sizeof(T) < 0, \"Only literal `0` is allowed.\");\n  }\n};\n\nenum class eq : value_type {\n  equal = 0,\n  equivalent = equal,\n  nonequal = 1,\n  nonequivalent = nonequal,\n};\n\nenum class ord : value_type { less = -1, greater = 1 };\n\nenum class ncmp : value_type { unordered = -127 };\n\n// Define macros to allow for creation or emulation of C++17 inline variables\n// based on whether the feature is supported. Note: we can't use\n// ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of\n// incomplete types so they need to be defined after the types are complete.\n#ifdef __cpp_inline_variables\n\n// A no-op expansion that can be followed by a semicolon at class level.\n#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, \"\")\n\n#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static const type name\n\n#define ABSL_COMPARE_INLINE_INIT(type, name, init) \\\n  inline constexpr type type::name(init)\n\n#else  // __cpp_inline_variables\n\n#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \\\n  ABSL_CONST_INIT static const T name\n\n// A no-op expansion that can be followed by a semicolon at class level.\n#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, \"\")\n\n#define ABSL_COMPARE_INLINE_INIT(type, name, init) \\\n  template <typename T>                            \\\n  const T compare_internal::type##_base<T>::name(init)\n\n#endif  // __cpp_inline_variables\n\n// These template base classes allow for defining the values of the constants\n// in the header file (for performance) without using inline variables (which\n// aren't available in C++11).\ntemplate <typename T>\nstruct partial_ordering_base {\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(less);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered);\n};\n\ntemplate <typename T>\nstruct weak_ordering_base {\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(less);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);\n};\n\ntemplate <typename T>\nstruct strong_ordering_base {\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(less);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(equal);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);\n  ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);\n};\n\n}  // namespace compare_internal\n\nclass partial_ordering\n    : public compare_internal::partial_ordering_base<partial_ordering> {\n  explicit constexpr partial_ordering(compare_internal::eq v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  explicit constexpr partial_ordering(compare_internal::ord v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  friend struct compare_internal::partial_ordering_base<partial_ordering>;\n\n  constexpr bool is_ordered() const noexcept {\n    return value_ !=\n           compare_internal::value_type(compare_internal::ncmp::unordered);\n  }\n\n public:\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered);\n\n  // Comparisons\n  friend constexpr bool operator==(partial_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.is_ordered() && v.value_ == 0;\n  }\n  friend constexpr bool operator!=(partial_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return !v.is_ordered() || v.value_ != 0;\n  }\n  friend constexpr bool operator<(partial_ordering v,\n                                  compare_internal::OnlyLiteralZero) noexcept {\n    return v.is_ordered() && v.value_ < 0;\n  }\n  friend constexpr bool operator<=(partial_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.is_ordered() && v.value_ <= 0;\n  }\n  friend constexpr bool operator>(partial_ordering v,\n                                  compare_internal::OnlyLiteralZero) noexcept {\n    return v.is_ordered() && v.value_ > 0;\n  }\n  friend constexpr bool operator>=(partial_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.is_ordered() && v.value_ >= 0;\n  }\n  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,\n                                   partial_ordering v) noexcept {\n    return v.is_ordered() && 0 == v.value_;\n  }\n  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,\n                                   partial_ordering v) noexcept {\n    return !v.is_ordered() || 0 != v.value_;\n  }\n  friend constexpr bool operator<(compare_internal::OnlyLiteralZero,\n                                  partial_ordering v) noexcept {\n    return v.is_ordered() && 0 < v.value_;\n  }\n  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,\n                                   partial_ordering v) noexcept {\n    return v.is_ordered() && 0 <= v.value_;\n  }\n  friend constexpr bool operator>(compare_internal::OnlyLiteralZero,\n                                  partial_ordering v) noexcept {\n    return v.is_ordered() && 0 > v.value_;\n  }\n  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,\n                                   partial_ordering v) noexcept {\n    return v.is_ordered() && 0 >= v.value_;\n  }\n  friend constexpr bool operator==(partial_ordering v1,\n                                   partial_ordering v2) noexcept {\n    return v1.value_ == v2.value_;\n  }\n  friend constexpr bool operator!=(partial_ordering v1,\n                                   partial_ordering v2) noexcept {\n    return v1.value_ != v2.value_;\n  }\n\n private:\n  compare_internal::value_type value_;\n};\nABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less);\nABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent,\n                         compare_internal::eq::equivalent);\nABSL_COMPARE_INLINE_INIT(partial_ordering, greater,\n                         compare_internal::ord::greater);\nABSL_COMPARE_INLINE_INIT(partial_ordering, unordered,\n                         compare_internal::ncmp::unordered);\n\nclass weak_ordering\n    : public compare_internal::weak_ordering_base<weak_ordering> {\n  explicit constexpr weak_ordering(compare_internal::eq v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  explicit constexpr weak_ordering(compare_internal::ord v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  friend struct compare_internal::weak_ordering_base<weak_ordering>;\n\n public:\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater);\n\n  // Conversions\n  constexpr operator partial_ordering() const noexcept {  // NOLINT\n    return value_ == 0 ? partial_ordering::equivalent\n                       : (value_ < 0 ? partial_ordering::less\n                                     : partial_ordering::greater);\n  }\n  // Comparisons\n  friend constexpr bool operator==(weak_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ == 0;\n  }\n  friend constexpr bool operator!=(weak_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ != 0;\n  }\n  friend constexpr bool operator<(weak_ordering v,\n                                  compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ < 0;\n  }\n  friend constexpr bool operator<=(weak_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ <= 0;\n  }\n  friend constexpr bool operator>(weak_ordering v,\n                                  compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ > 0;\n  }\n  friend constexpr bool operator>=(weak_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ >= 0;\n  }\n  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,\n                                   weak_ordering v) noexcept {\n    return 0 == v.value_;\n  }\n  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,\n                                   weak_ordering v) noexcept {\n    return 0 != v.value_;\n  }\n  friend constexpr bool operator<(compare_internal::OnlyLiteralZero,\n                                  weak_ordering v) noexcept {\n    return 0 < v.value_;\n  }\n  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,\n                                   weak_ordering v) noexcept {\n    return 0 <= v.value_;\n  }\n  friend constexpr bool operator>(compare_internal::OnlyLiteralZero,\n                                  weak_ordering v) noexcept {\n    return 0 > v.value_;\n  }\n  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,\n                                   weak_ordering v) noexcept {\n    return 0 >= v.value_;\n  }\n  friend constexpr bool operator==(weak_ordering v1,\n                                   weak_ordering v2) noexcept {\n    return v1.value_ == v2.value_;\n  }\n  friend constexpr bool operator!=(weak_ordering v1,\n                                   weak_ordering v2) noexcept {\n    return v1.value_ != v2.value_;\n  }\n\n private:\n  compare_internal::value_type value_;\n};\nABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less);\nABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent,\n                         compare_internal::eq::equivalent);\nABSL_COMPARE_INLINE_INIT(weak_ordering, greater,\n                         compare_internal::ord::greater);\n\nclass strong_ordering\n    : public compare_internal::strong_ordering_base<strong_ordering> {\n  explicit constexpr strong_ordering(compare_internal::eq v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  explicit constexpr strong_ordering(compare_internal::ord v) noexcept\n      : value_(static_cast<compare_internal::value_type>(v)) {}\n  friend struct compare_internal::strong_ordering_base<strong_ordering>;\n\n public:\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent);\n  ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater);\n\n  // Conversions\n  constexpr operator partial_ordering() const noexcept {  // NOLINT\n    return value_ == 0 ? partial_ordering::equivalent\n                       : (value_ < 0 ? partial_ordering::less\n                                     : partial_ordering::greater);\n  }\n  constexpr operator weak_ordering() const noexcept {  // NOLINT\n    return value_ == 0\n               ? weak_ordering::equivalent\n               : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);\n  }\n  // Comparisons\n  friend constexpr bool operator==(strong_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ == 0;\n  }\n  friend constexpr bool operator!=(strong_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ != 0;\n  }\n  friend constexpr bool operator<(strong_ordering v,\n                                  compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ < 0;\n  }\n  friend constexpr bool operator<=(strong_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ <= 0;\n  }\n  friend constexpr bool operator>(strong_ordering v,\n                                  compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ > 0;\n  }\n  friend constexpr bool operator>=(strong_ordering v,\n                                   compare_internal::OnlyLiteralZero) noexcept {\n    return v.value_ >= 0;\n  }\n  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,\n                                   strong_ordering v) noexcept {\n    return 0 == v.value_;\n  }\n  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,\n                                   strong_ordering v) noexcept {\n    return 0 != v.value_;\n  }\n  friend constexpr bool operator<(compare_internal::OnlyLiteralZero,\n                                  strong_ordering v) noexcept {\n    return 0 < v.value_;\n  }\n  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,\n                                   strong_ordering v) noexcept {\n    return 0 <= v.value_;\n  }\n  friend constexpr bool operator>(compare_internal::OnlyLiteralZero,\n                                  strong_ordering v) noexcept {\n    return 0 > v.value_;\n  }\n  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,\n                                   strong_ordering v) noexcept {\n    return 0 >= v.value_;\n  }\n  friend constexpr bool operator==(strong_ordering v1,\n                                   strong_ordering v2) noexcept {\n    return v1.value_ == v2.value_;\n  }\n  friend constexpr bool operator!=(strong_ordering v1,\n                                   strong_ordering v2) noexcept {\n    return v1.value_ != v2.value_;\n  }\n\n private:\n  compare_internal::value_type value_;\n};\nABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less);\nABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal);\nABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent,\n                         compare_internal::eq::equivalent);\nABSL_COMPARE_INLINE_INIT(strong_ordering, greater,\n                         compare_internal::ord::greater);\n\n#undef ABSL_COMPARE_INLINE_BASECLASS_DECL\n#undef ABSL_COMPARE_INLINE_SUBCLASS_DECL\n#undef ABSL_COMPARE_INLINE_INIT\n\n#endif  // ABSL_USES_STD_ORDERING\n\nnamespace compare_internal {\n// We also provide these comparator adapter functions for internal absl use.\n\n// Helper functions to do a boolean comparison of two keys given a boolean\n// or three-way comparator.\n// SFINAE prevents implicit conversions to bool (such as from int).\ntemplate <typename BoolT,\n          absl::enable_if_t<std::is_same<bool, BoolT>::value, int> = 0>\nconstexpr bool compare_result_as_less_than(const BoolT r) {\n  return r;\n}\nconstexpr bool compare_result_as_less_than(const absl::weak_ordering r) {\n  return r < 0;\n}\n\ntemplate <typename Compare, typename K, typename LK>\nconstexpr bool do_less_than_comparison(const Compare& compare, const K& x,\n                                       const LK& y) {\n  return compare_result_as_less_than(compare(x, y));\n}\n\n// Helper functions to do a three-way comparison of two keys given a boolean or\n// three-way comparator.\n// SFINAE prevents implicit conversions to int (such as from bool).\ntemplate <typename Int,\n          absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>\nconstexpr absl::weak_ordering compare_result_as_ordering(const Int c) {\n  return c < 0    ? absl::weak_ordering::less\n         : c == 0 ? absl::weak_ordering::equivalent\n                  : absl::weak_ordering::greater;\n}\nconstexpr absl::weak_ordering compare_result_as_ordering(\n    const absl::weak_ordering c) {\n  return c;\n}\n\ntemplate <typename Compare, typename K, typename LK,\n          absl::enable_if_t<\n              !std::is_same<\n                  bool, absl::result_of_t<Compare(const K&, const LK&)>>::value,\n              int> = 0>\nconstexpr absl::weak_ordering do_three_way_comparison(const Compare& compare,\n                                                      const K& x, const LK& y) {\n  return compare_result_as_ordering(compare(x, y));\n}\ntemplate <typename Compare, typename K, typename LK,\n          absl::enable_if_t<\n              std::is_same<\n                  bool, absl::result_of_t<Compare(const K&, const LK&)>>::value,\n              int> = 0>\nconstexpr absl::weak_ordering do_three_way_comparison(const Compare& compare,\n                                                      const K& x, const LK& y) {\n  return compare(x, y)   ? absl::weak_ordering::less\n         : compare(y, x) ? absl::weak_ordering::greater\n                         : absl::weak_ordering::equivalent;\n}\n\n}  // namespace compare_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_COMPARE_H_\n"
  },
  {
    "path": "absl/types/compare_test.cc",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/types/compare.h\"\n\n#include \"gtest/gtest.h\"\n#include \"absl/base/casts.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\n// This is necessary to avoid a bunch of lint warnings suggesting that we use\n// EXPECT_EQ/etc., which doesn't work in this case because they convert the `0`\n// to an int, which can't be converted to the unspecified zero type.\nbool Identity(bool b) { return b; }\n\nTEST(Compare, PartialOrdering) {\n  EXPECT_TRUE(Identity(partial_ordering::less < 0));\n  EXPECT_TRUE(Identity(0 > partial_ordering::less));\n  EXPECT_TRUE(Identity(partial_ordering::less <= 0));\n  EXPECT_TRUE(Identity(0 >= partial_ordering::less));\n  EXPECT_TRUE(Identity(partial_ordering::equivalent == 0));\n  EXPECT_TRUE(Identity(0 == partial_ordering::equivalent));\n  EXPECT_TRUE(Identity(partial_ordering::greater > 0));\n  EXPECT_TRUE(Identity(0 < partial_ordering::greater));\n  EXPECT_TRUE(Identity(partial_ordering::greater >= 0));\n  EXPECT_TRUE(Identity(0 <= partial_ordering::greater));\n  EXPECT_TRUE(Identity(partial_ordering::unordered != 0));\n  EXPECT_TRUE(Identity(0 != partial_ordering::unordered));\n  EXPECT_FALSE(Identity(partial_ordering::unordered < 0));\n  EXPECT_FALSE(Identity(0 < partial_ordering::unordered));\n  EXPECT_FALSE(Identity(partial_ordering::unordered <= 0));\n  EXPECT_FALSE(Identity(0 <= partial_ordering::unordered));\n  EXPECT_FALSE(Identity(partial_ordering::unordered > 0));\n  EXPECT_FALSE(Identity(0 > partial_ordering::unordered));\n  EXPECT_FALSE(Identity(partial_ordering::unordered >= 0));\n  EXPECT_FALSE(Identity(0 >= partial_ordering::unordered));\n  const partial_ordering values[] = {\n      partial_ordering::less, partial_ordering::equivalent,\n      partial_ordering::greater, partial_ordering::unordered};\n  for (const auto& lhs : values) {\n    for (const auto& rhs : values) {\n      const bool are_equal = &lhs == &rhs;\n      EXPECT_EQ(lhs == rhs, are_equal);\n      EXPECT_EQ(lhs != rhs, !are_equal);\n    }\n  }\n}\n\nTEST(Compare, WeakOrdering) {\n  EXPECT_TRUE(Identity(weak_ordering::less < 0));\n  EXPECT_TRUE(Identity(0 > weak_ordering::less));\n  EXPECT_TRUE(Identity(weak_ordering::less <= 0));\n  EXPECT_TRUE(Identity(0 >= weak_ordering::less));\n  EXPECT_TRUE(Identity(weak_ordering::equivalent == 0));\n  EXPECT_TRUE(Identity(0 == weak_ordering::equivalent));\n  EXPECT_TRUE(Identity(weak_ordering::greater > 0));\n  EXPECT_TRUE(Identity(0 < weak_ordering::greater));\n  EXPECT_TRUE(Identity(weak_ordering::greater >= 0));\n  EXPECT_TRUE(Identity(0 <= weak_ordering::greater));\n  const weak_ordering values[] = {\n      weak_ordering::less, weak_ordering::equivalent, weak_ordering::greater};\n  for (const auto& lhs : values) {\n    for (const auto& rhs : values) {\n      const bool are_equal = &lhs == &rhs;\n      EXPECT_EQ(lhs == rhs, are_equal);\n      EXPECT_EQ(lhs != rhs, !are_equal);\n    }\n  }\n}\n\nTEST(Compare, StrongOrdering) {\n  EXPECT_TRUE(Identity(strong_ordering::less < 0));\n  EXPECT_TRUE(Identity(0 > strong_ordering::less));\n  EXPECT_TRUE(Identity(strong_ordering::less <= 0));\n  EXPECT_TRUE(Identity(0 >= strong_ordering::less));\n  EXPECT_TRUE(Identity(strong_ordering::equal == 0));\n  EXPECT_TRUE(Identity(0 == strong_ordering::equal));\n  EXPECT_TRUE(Identity(strong_ordering::equivalent == 0));\n  EXPECT_TRUE(Identity(0 == strong_ordering::equivalent));\n  EXPECT_TRUE(Identity(strong_ordering::greater > 0));\n  EXPECT_TRUE(Identity(0 < strong_ordering::greater));\n  EXPECT_TRUE(Identity(strong_ordering::greater >= 0));\n  EXPECT_TRUE(Identity(0 <= strong_ordering::greater));\n  const strong_ordering values[] = {\n      strong_ordering::less, strong_ordering::equal, strong_ordering::greater};\n  for (const auto& lhs : values) {\n    for (const auto& rhs : values) {\n      const bool are_equal = &lhs == &rhs;\n      EXPECT_EQ(lhs == rhs, are_equal);\n      EXPECT_EQ(lhs != rhs, !are_equal);\n    }\n  }\n  EXPECT_TRUE(Identity(strong_ordering::equivalent == strong_ordering::equal));\n}\n\nTEST(Compare, Conversions) {\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(weak_ordering::less) != 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(weak_ordering::less) < 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(weak_ordering::less) <= 0));\n  EXPECT_TRUE(Identity(\n      implicit_cast<partial_ordering>(weak_ordering::equivalent) == 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(weak_ordering::greater) != 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(weak_ordering::greater) > 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(weak_ordering::greater) >= 0));\n\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::less) != 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::less) < 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::less) <= 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::equal) == 0));\n  EXPECT_TRUE(Identity(\n      implicit_cast<partial_ordering>(strong_ordering::equivalent) == 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::greater) != 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::greater) > 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<partial_ordering>(strong_ordering::greater) >= 0));\n\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::less) != 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::less) < 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::less) <= 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::equal) == 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::equivalent) == 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::greater) != 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::greater) > 0));\n  EXPECT_TRUE(\n      Identity(implicit_cast<weak_ordering>(strong_ordering::greater) >= 0));\n}\n\nstruct WeakOrderingLess {\n  template <typename T>\n  absl::weak_ordering operator()(const T& a, const T& b) const {\n    return a < b    ? absl::weak_ordering::less\n           : a == b ? absl::weak_ordering::equivalent\n                    : absl::weak_ordering::greater;\n  }\n};\n\nTEST(CompareResultAsLessThan, SanityTest) {\n  EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(false));\n  EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(true));\n\n  EXPECT_TRUE(\n      absl::compare_internal::compare_result_as_less_than(weak_ordering::less));\n  EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(\n      weak_ordering::equivalent));\n  EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(\n      weak_ordering::greater));\n}\n\nTEST(DoLessThanComparison, SanityTest) {\n  std::less<int> less;\n  WeakOrderingLess weak;\n\n  EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(less, -1, 0));\n  EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(weak, -1, 0));\n\n  EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 10));\n  EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 10));\n\n  EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 5));\n  EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 5));\n}\n\nTEST(CompareResultAsOrdering, SanityTest) {\n  EXPECT_TRUE(\n      Identity(absl::compare_internal::compare_result_as_ordering(-1) < 0));\n  EXPECT_FALSE(\n      Identity(absl::compare_internal::compare_result_as_ordering(-1) == 0));\n  EXPECT_FALSE(\n      Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0));\n  EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(\n                           weak_ordering::less) < 0));\n  EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(\n                            weak_ordering::less) == 0));\n  EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(\n                            weak_ordering::less) > 0));\n\n  EXPECT_FALSE(\n      Identity(absl::compare_internal::compare_result_as_ordering(0) < 0));\n  EXPECT_TRUE(\n      Identity(absl::compare_internal::compare_result_as_ordering(0) == 0));\n  EXPECT_FALSE(\n      Identity(absl::compare_internal::compare_result_as_ordering(0) > 0));\n  EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(\n                            weak_ordering::equivalent) < 0));\n  EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(\n                           weak_ordering::equivalent) == 0));\n  EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(\n                            weak_ordering::equivalent) > 0));\n\n  EXPECT_FALSE(\n      Identity(absl::compare_internal::compare_result_as_ordering(1) < 0));\n  EXPECT_FALSE(\n      Identity(absl::compare_internal::compare_result_as_ordering(1) == 0));\n  EXPECT_TRUE(\n      Identity(absl::compare_internal::compare_result_as_ordering(1) > 0));\n  EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(\n                            weak_ordering::greater) < 0));\n  EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(\n                            weak_ordering::greater) == 0));\n  EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(\n                           weak_ordering::greater) > 0));\n}\n\nTEST(DoThreeWayComparison, SanityTest) {\n  std::less<int> less;\n  WeakOrderingLess weak;\n\n  EXPECT_TRUE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, -1, 0) < 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, -1, 0) == 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, -1, 0) > 0));\n  EXPECT_TRUE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, -1, 0) < 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, -1, 0) == 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, -1, 0) > 0));\n\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, 10, 10) < 0));\n  EXPECT_TRUE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, 10, 10) == 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, 10, 10) > 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, 10, 10) < 0));\n  EXPECT_TRUE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, 10, 10) == 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, 10, 10) > 0));\n\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, 10, 5) < 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, 10, 5) == 0));\n  EXPECT_TRUE(Identity(\n      absl::compare_internal::do_three_way_comparison(less, 10, 5) > 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, 10, 5) < 0));\n  EXPECT_FALSE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, 10, 5) == 0));\n  EXPECT_TRUE(Identity(\n      absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0));\n}\n\n#ifdef __cpp_inline_variables\nTEST(Compare, StaticAsserts) {\n  static_assert(partial_ordering::less < 0, \"\");\n  static_assert(partial_ordering::equivalent == 0, \"\");\n  static_assert(partial_ordering::greater > 0, \"\");\n  static_assert(partial_ordering::unordered != 0, \"\");\n\n  static_assert(weak_ordering::less < 0, \"\");\n  static_assert(weak_ordering::equivalent == 0, \"\");\n  static_assert(weak_ordering::greater > 0, \"\");\n\n  static_assert(strong_ordering::less < 0, \"\");\n  static_assert(strong_ordering::equal == 0, \"\");\n  static_assert(strong_ordering::equivalent == 0, \"\");\n  static_assert(strong_ordering::greater > 0, \"\");\n}\n#endif  // __cpp_inline_variables\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/types/internal/any_span.h",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: internal/any_span.h\n// -----------------------------------------------------------------------------\n//\n// Helper types and functions used by AnySpan. This file should only be\n// included by any_span.h.\n#ifndef ABSL_TYPES_INTERNAL_ANY_SPAN_H_\n#define ABSL_TYPES_INTERNAL_ANY_SPAN_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <functional>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/raw_logging.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename T>\nclass AnySpan;\n\nnamespace any_span_transform {\nstruct IdentityT;\nstruct DerefT;\n}  // namespace any_span_transform\n\nnamespace any_span_internal {\n\n//\n// IsAnySpan inherits from true_type if T is an instance of AnySpan.\n//\n\ntemplate <typename T>\nstruct IsAnySpan : public std::false_type {};\n\ntemplate <typename T>\nstruct IsAnySpan<AnySpan<T>> : public std::true_type {};\n\n// A type suitable for storing any function pointer. The standard allows\n// function pointers to round-trip through other function pointers, but void* is\n// implementation defined.\nusing FunPtr = void (*)();\n\n// Whether a transform will be copied and therefore does not have to outlive\n// the AnySpan.\ntemplate <typename Transform>\nconstexpr bool kIsTransformCopied =\n    std::is_function_v<std::remove_pointer_t<Transform>>;\n\n// Type to pass as extra argument to TransformPtr to ensure that our\n// assumption about Transform copyability is valid.\ntemplate <typename Transform>\nusing IsTransformCopied =\n    std::integral_constant<bool, kIsTransformCopied<Transform>>;\n\n// A pointer to the transform function or functor that should be applied to\n// elements of the container.\nclass TransformPtr {\n public:\n  TransformPtr() = default;\n\n  // Construct from ptr to function.\n  template <typename R, typename... Args, typename CopiedTransform>\n  explicit TransformPtr(R (*f)(Args...),\n                        CopiedTransform copied_transform [[maybe_unused]])\n      : fun_ptr_(reinterpret_cast<FunPtr>(f)) {\n    static_assert(CopiedTransform::value);\n  }\n\n  // Construct from any other invokable object.\n  template <typename T, typename CopiedTransform>\n  explicit TransformPtr(const T& t,\n                        CopiedTransform copied_transform [[maybe_unused]])\n      : ptr_(&t) {\n    static_assert(!CopiedTransform::value);\n  }\n\n  // Casts the pointer to the given type.\n  template <typename Transform>\n  auto get() const {\n    if constexpr (std::is_function_v<Transform>) {\n      return reinterpret_cast<const Transform*>(fun_ptr_);\n    } else if constexpr (std::is_function_v<std::remove_pointer_t<Transform>>) {\n      return reinterpret_cast<const Transform>(fun_ptr_);\n    } else {\n      return static_cast<const Transform*>(ptr_);\n    }\n  }\n\n private:\n  union {\n    const void* ptr_ = nullptr;\n    FunPtr fun_ptr_;\n  };\n};\n\n// A void* pointer to the container and transform functor. These are always cast\n// to the correct type since we create this object and the GetterFunction at the\n// same time (from one of the Make*Getter functions below).\nstruct TransformedContainer {\n  // The container or array.\n  void* ptr;\n\n  // The transform being applied to the container.\n  TransformPtr transform;\n};\n\n// Applies transform (at the correct type) to the argument and returns the\n// result. Does some validity checking to make sure the result is not a\n// temporary (proxy containers are not allowed).\ntemplate <typename T, typename Transform, typename U>\nT& ApplyTransform(TransformPtr transform, U& u) {  // NOLINT(runtime/references)\n  const auto t = transform.get<Transform>();\n  ABSL_RAW_DCHECK(t != nullptr, \"pointer cannot be null\");\n\n  // If compilation fails here due to dropping a const qualifier, it usually\n  // means you tried to wrap a const container with a non-const AnySpan.\n  //\n  // If compilation fails here due to a reference to a temporary, it usually\n  // means that the container or transform cannot be converted to a reference to\n  // T. AnySpan requires that a valid instance of T exists, conversion to a\n  // value type (such as string -> StringPiece or int -> float) is not\n  // supported.\n  //\n  // If compilation fails here due to taking the address of a temporary object,\n  // it means that the transform is returning a temporary. This is disallowed.\n  // Transforms must return a reference to T, or a reference to an object that\n  // can be safely converted to a reference to T (such as a reference_wrapper or\n  // a class that inherits from T).\n  return *&std::invoke(*t, u);  // Failed compilation? See above.\n}\n\n// The return type of GetterFunction<T>. GetterFunctions return non-const\n// references to support mutable -> const conversion of spans without additional\n// indirection.\ntemplate <typename T>\nusing GetterFunctionResult = absl::remove_const_t<T>&;\n\n// A type of function pointer that can return an element of a\n// TransformedContainer.  This is used so that we can type-erase with a simple\n// function pointer instead of a vtable. Doing things this way has less pointer\n// indirection.\ntemplate <typename T>\nusing GetterFunction = GetterFunctionResult<T> (*)(const TransformedContainer&,\n                                                   std::size_t);\n\n// A GetterFunction that works on arrays.\ntemplate <typename T, typename Element, typename Transform>\nGetterFunctionResult<T> GetFromArray(const TransformedContainer& container,\n                                     std::size_t i) {\n  ABSL_RAW_DCHECK(container.ptr != nullptr, \"cannot dereference null pointer\");\n  auto* array = static_cast<Element*>(container.ptr);\n  return const_cast<GetterFunctionResult<T>>(\n      ApplyTransform<T, Transform>(container.transform, array[i]));\n}\n\n// A GetterFunction that works on containers.\ntemplate <typename T, typename Container, typename Transform>\nGetterFunctionResult<T> GetFromContainer(const TransformedContainer& container,\n                                         std::size_t i) {\n  ABSL_RAW_DCHECK(container.ptr != nullptr, \"cannot dereference null pointer\");\n  Container& c = *static_cast<Container*>(container.ptr);\n  return const_cast<GetterFunctionResult<T>>(\n      ApplyTransform<T, Transform>(container.transform, c[i]));\n}\n\n// A GetterFunction that crashes, indicating an invalid AnySpan has been\n// accessed..\ntemplate <typename T>\nGetterFunctionResult<T> GetFromUninitialized(const TransformedContainer&,\n                                             std::size_t) {\n  ABSL_RAW_LOG(FATAL, \"Uninitialized AnySpan access.\");\n}\n\n//\n// ArrayTag and PtrArrayTag are GetterFunctions that are never called. They are\n// used as a tag so Getter::Get can access flat arrays without a function\n// pointer.\n//\n\ntemplate <typename T>\nGetterFunctionResult<T> ArrayTag(const TransformedContainer&, std::size_t) {\n  ABSL_RAW_LOG(FATAL, \"ArrayTag should never be called.\");\n}\n\ntemplate <typename T>\nGetterFunctionResult<T> PtrArrayTag(const TransformedContainer&, std::size_t) {\n  ABSL_RAW_LOG(FATAL, \"PtrArrayTag should never be called.\");\n}\n\n//\n// HasSize<Container> inherets from true_type if Container has a size() member.\n// false_type otherwise.\n//\n\ntemplate <typename, typename = void>\nstruct HasSize : public std::false_type {};\n\ntemplate <class Container>\nstruct HasSize<Container,\n               absl::void_t<decltype(std::declval<Container&>().size())>>\n    : public std::true_type {};\n\n//\n// TypeOfData<Container>::type is the return type of data() if Container has a\n// data() member. It is NoData otherwise.\n//\n\nstruct NoData {};\n\ntemplate <typename, typename = void>\nstruct TypeOfData {\n  using type = NoData;\n};\n\ntemplate <class Container>\nstruct TypeOfData<Container,\n                  absl::void_t<decltype(std::declval<Container&>().data())>> {\n  using type = decltype(std::declval<Container&>().data());\n};\n\n// Element type of container based on operator[].\ntemplate <class Container>\nusing ElementType = typename std::remove_reference<\n    decltype(std::declval<Container&>()[0])>::type;\n\n// Element type of container when elements are dereferenced.\ntemplate <class Container>\nusing DerefElementType = typename std::remove_reference<\n    decltype(*std::declval<ElementType<Container>>())>::type;\n\n// DataIsValid is true_type if Container has a data() member that returns a\n// pointer to the type returned by operator[], false_type if there is no data()\n// member or if the types disagree.\ntemplate <class Container>\nusing DataIsValid =\n    std::is_same<ElementType<Container>*, typename TypeOfData<Container>::type>;\n\n// Used to access elements of a container or array.\ntemplate <typename T>\nstruct Getter {\n  Getter() {}\n\n  // Handle mutable -> const conversion.\n  template <typename LazyT = T, typename = typename std::enable_if<\n                                    std::is_const<LazyT>::value>::type>\n  explicit Getter(const Getter<absl::remove_const_t<T>>& other) {\n    using MutableT = absl::remove_const_t<T>;\n    if (other.fun == &ArrayTag<MutableT>) {\n      ABSL_RAW_DCHECK(other.offset == 0u, \"offset must be zero\");\n      fun = &ArrayTag<T>;\n      array = other.array;\n      offset = 0;\n    } else if (other.fun == &PtrArrayTag<MutableT>) {\n      ABSL_RAW_DCHECK(other.offset == 0u, \"offset must be zero\");\n      fun = &PtrArrayTag<T>;\n      ptr_array = other.ptr_array;\n      offset = 0;\n    } else {\n      fun = other.fun;\n      container = other.container;\n      offset = other.offset;\n    }\n  }\n\n  // Returns the element at the given index.\n  T& Get(std::size_t index) const {\n    ABSL_RAW_DCHECK(fun != nullptr, \"pointer cannot be null\");\n    if (ABSL_PREDICT_TRUE(fun == &ArrayTag<T>)) {\n      ABSL_RAW_DCHECK(array != nullptr, \"pointer cannot be null\");\n      return array[index];\n    }\n    if (fun == &PtrArrayTag<T>) {\n      ABSL_RAW_DCHECK(ptr_array != nullptr, \"pointer cannot be null\");\n      return *ptr_array[index];\n    }\n    return fun(container, index + offset);\n  }\n\n  // Returns a Getter offset into this one by pos.\n  Getter Offset(std::size_t pos) const {\n    // Special case when offset is zero. This safely handles empty spans and\n    // empty containers where data() can be null.\n    if (pos == 0) {\n      return *this;\n    }\n    ABSL_RAW_DCHECK(fun != nullptr, \"pointer cannot be null\");\n    Getter result;\n    result.fun = fun;\n    if (fun == &ArrayTag<T>) {\n      ABSL_RAW_DCHECK(array != nullptr, \"pointer cannot be null\");\n      ABSL_RAW_DCHECK(offset == 0u, \"offset must be zero\");\n      result.array = array + pos;\n      result.offset = 0;\n    } else if (fun == &PtrArrayTag<T>) {\n      ABSL_RAW_DCHECK(ptr_array != nullptr, \"pointer cannot be null\");\n      ABSL_RAW_DCHECK(offset == 0u, \"offset must be zero\");\n      result.ptr_array = ptr_array + pos;\n      result.offset = 0;\n    } else {\n      ABSL_RAW_DCHECK(container.ptr != nullptr, \"pointer cannot be null\");\n      result.container = container;\n      result.offset = offset + pos;\n    }\n    return result;\n  }\n\n  // A pointer to a function (or tag function) that specifies how to get an\n  // element from the array or container.\n  GetterFunction<T> fun = &GetFromUninitialized<T>;\n\n  union {\n    T* array;                        // Active if fun == ArrayTag<T>.\n    T* const* ptr_array;             // Active if fun == PtrArrayTag<T>.\n    TransformedContainer container;  // Active for all other fun.\n  };\n\n  // Offset into container. Always 0 for array or ptr_array.\n  std::size_t offset = 0;\n};\n\n//\n// MakeArrayGetter returns a Getter for an array.\n//\n// MakeArrayGetterImpl is specialised to use ArrayTag<T> when Element == T and\n// Transform == IdentityT, and to use PtrArrayTag<T> when Element == T* and\n// Transform == DerefT.\n//\n\ntemplate <typename SpanElement, typename ArrayElement, typename Transform>\nstruct MakeArrayGetterImpl {\n  template <typename U>\n  static Getter<U> Make(ArrayElement* array, const Transform& transform) {\n    Getter<U> result;\n    result.fun = &GetFromArray<U, ArrayElement, Transform>;\n    result.container.ptr = const_cast<void*>(static_cast<const void*>(array));\n    result.container.transform =\n        TransformPtr(transform, IsTransformCopied<Transform>{});\n    return result;\n  }\n};\n\n// When the span and the array are the same type.\ntemplate <typename T>\nstruct MakeArrayGetterImpl<T, T, any_span_transform::IdentityT> {\n  template <typename U>\n  static Getter<U> Make(T* array, const any_span_transform::IdentityT&) {\n    Getter<U> result;\n    result.fun = &ArrayTag<U>;\n    result.array = array;\n    return result;\n  }\n};\n\n// If we are dereferencing an array of mutable elements (T*), it is safe to add\n// constness (const T*).\ntemplate <typename T>\nstruct MakeArrayGetterImpl<const T, T, any_span_transform::IdentityT>\n    : public MakeArrayGetterImpl<const T, const T,\n                                 any_span_transform::IdentityT> {};\n\n// When the array is of pointers to elements of the same type as the span.\ntemplate <typename T>\nstruct MakeArrayGetterImpl<T, T*, any_span_transform::DerefT> {\n  template <typename U>\n  static Getter<U> Make(T* const* ptr_array,\n                        const any_span_transform::DerefT&) {\n    Getter<U> result;\n    result.fun = &PtrArrayTag<U>;\n    result.ptr_array = ptr_array;\n    return result;\n  }\n};\n\n// If we are dereferencing an array that is mutable along any extent, it is safe\n// to add constness.\ntemplate <typename T>\nstruct MakeArrayGetterImpl<const T, T*, any_span_transform::DerefT>\n    : public MakeArrayGetterImpl<const T, const T*,\n                                 any_span_transform::DerefT> {};\n\ntemplate <typename T>\nstruct MakeArrayGetterImpl<const T, T* const, any_span_transform::DerefT>\n    : public MakeArrayGetterImpl<const T, const T*,\n                                 any_span_transform::DerefT> {};\n\ntemplate <typename T>\nstruct MakeArrayGetterImpl<const T, const T* const, any_span_transform::DerefT>\n    : public MakeArrayGetterImpl<const T, const T*,\n                                 any_span_transform::DerefT> {};\n\ntemplate <typename T, typename Element, typename Transform>\nGetter<T> MakeArrayGetter(Element* array, const Transform& transform) {\n  return MakeArrayGetterImpl<T, Element, Transform>::template Make<T>(\n      array, transform);\n}\n\n//\n// MakeContainerGetter returns a Getter for a given container. It will pass\n// container.data() to MakeArrayGetter if possible, which allows element access\n// to be inline.\n//\n// The first argument to MakeArrayGetterImpl is expected to be of type\n// DataIsValid<container>.\n//\n\ntemplate <typename T, typename Container, typename Transform>\nGetter<T> MakeContainerGetterImpl(\n    std::true_type /* DataIsValid<Container> */,\n    Container& container,  // NOLINT(runtime/references)\n    const Transform& transform) {\n  return MakeArrayGetter<T, ElementType<Container>, Transform>(container.data(),\n                                                               transform);\n}\n\ntemplate <typename T, typename Container, typename Transform>\nGetter<T> MakeContainerGetterImpl(\n    std::false_type /* DataIsValid<Container> */,\n    Container& container,  // NOLINT(runtime/references)\n    const Transform& transform) {\n  Getter<T> result;\n  result.fun = &GetFromContainer<T, Container, Transform>;\n  result.container.ptr =\n      const_cast<void*>(static_cast<const void*>(&container));\n  result.container.transform =\n      TransformPtr(transform, IsTransformCopied<Transform>{});\n\n  return result;\n}\n\ntemplate <typename T, typename Container, typename Transform>\nGetter<T> MakeContainerGetter(\n    Container& container,  // NOLINT(runtime/references)\n    const Transform& transform) {\n  static_assert(std::is_reference<decltype(container[0])>::value,\n                \"AnySpan only works with containers that return a reference \"\n                \"(no vector<bool>, or containers that return by value).\");\n  return MakeContainerGetterImpl<T>(DataIsValid<Container>(), container,\n                                    transform);\n}\n\n// Used for testing. Returns true if the given AnySpan performs inline element\n// access.\ntemplate <typename T>\nbool IsCheap(AnySpan<T> s) {\n  return s.getter_.fun == &ArrayTag<T> || s.getter_.fun == &PtrArrayTag<T>;\n}\n\ntemplate <typename T>\nbool EqualImpl(AnySpan<T> a, AnySpan<T> b) {\n  static_assert(std::is_const<T>::value, \"\");\n  return std::equal(a.begin(), a.end(), b.begin(), b.end());\n}\n\n}  // namespace any_span_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_INTERNAL_ANY_SPAN_H_\n"
  },
  {
    "path": "absl/types/internal/span.h",
    "content": "//\n// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n#ifndef ABSL_TYPES_INTERNAL_SPAN_H_\n#define ABSL_TYPES_INTERNAL_SPAN_H_\n\n#include <algorithm>\n#include <cstddef>\n#include <string>\n#include <type_traits>\n\n#include \"absl/algorithm/algorithm.h\"\n#include \"absl/base/config.h\"\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename T>\nclass Span;\n\nnamespace span_internal {\n// Wrappers for access to container data pointers.\ntemplate <typename C>\nconstexpr auto GetDataImpl(C& c, char) noexcept  // NOLINT(runtime/references)\n    -> decltype(c.data()) {\n  return c.data();\n}\n\n// Before C++17, std::string::data returns a const char* in all cases.\ninline char* GetDataImpl(std::string& s,  // NOLINT(runtime/references)\n                         int) noexcept {\n  return &s[0];\n}\n\ntemplate <typename C>\nconstexpr auto GetData(C& c) noexcept  // NOLINT(runtime/references)\n    -> decltype(GetDataImpl(c, 0)) {\n  return GetDataImpl(c, 0);\n}\n\n// Detection idioms for size() and data().\ntemplate <typename C>\nusing HasSize =\n    std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;\n\n// We want to enable conversion from vector<T*> to Span<const T* const> but\n// disable conversion from vector<Derived> to Span<Base>. Here we use\n// the fact that U** is convertible to Q* const* if and only if Q is the same\n// type or a more cv-qualified version of U.  We also decay the result type of\n// data() to avoid problems with classes which have a member function data()\n// which returns a reference.\ntemplate <typename T, typename C>\nusing HasData =\n    std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,\n                        T* const*>;\n\n// Extracts value type from a Container\ntemplate <typename C>\nstruct ElementType {\n  using type = typename absl::remove_reference_t<C>::value_type;\n};\n\ntemplate <typename T, size_t N>\nstruct ElementType<T (&)[N]> {\n  using type = T;\n};\n\ntemplate <typename C>\nusing ElementT = typename ElementType<C>::type;\n\ntemplate <typename T>\nusing EnableIfMutable =\n    typename std::enable_if<!std::is_const<T>::value, int>::type;\n\ntemplate <template <typename> class SpanT, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool EqualImpl(SpanT<T> a, SpanT<T> b) {\n  static_assert(std::is_const<T>::value, \"\");\n  return std::equal(a.begin(), a.end(), b.begin(), b.end());\n}\n\ntemplate <template <typename> class SpanT, typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool LessThanImpl(SpanT<T> a, SpanT<T> b) {\n  // We can't use value_type since that is remove_cv_t<T>, so we go the long way\n  // around.\n  static_assert(std::is_const<T>::value, \"\");\n  return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n}\n\ntemplate <typename From, typename To>\nusing EnableIfConvertibleTo =\n    typename std::enable_if<std::is_convertible<From, To>::value>::type;\n\n// IsView is true for types where the return type of .data() is the same for\n// mutable and const instances. This isn't foolproof, but it's only used to\n// enable a compiler warning.\ntemplate <typename T, typename = void, typename = void>\nstruct IsView {\n  static constexpr bool value = false;\n};\n\ntemplate <typename T>\nstruct IsView<\n    T, absl::void_t<decltype(span_internal::GetData(std::declval<const T&>()))>,\n    absl::void_t<decltype(span_internal::GetData(std::declval<T&>()))>> {\n private:\n  using Container = std::remove_const_t<T>;\n  using ConstData =\n      decltype(span_internal::GetData(std::declval<const Container&>()));\n  using MutData = decltype(span_internal::GetData(std::declval<Container&>()));\n\n public:\n  static constexpr bool value = std::is_same<ConstData, MutData>::value;\n};\n\n// These enablers result in 'int' so they can be used as typenames or defaults\n// in template parameters lists.\ntemplate <typename T>\nusing EnableIfIsView = std::enable_if_t<IsView<T>::value, int>;\n\ntemplate <typename T>\nusing EnableIfNotIsView = std::enable_if_t<!IsView<T>::value, int>;\n\n}  // namespace span_internal\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_INTERNAL_SPAN_H_\n"
  },
  {
    "path": "absl/types/optional.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// optional.h\n// -----------------------------------------------------------------------------\n//\n// Historical note: Abseil once provided an implementation of `absl::optional`\n// as a polyfill for `std::optional` prior to C++17. Now that C++17 is required,\n// `absl::optional` is an alias for `std::optional`.\n\n#ifndef ABSL_TYPES_OPTIONAL_H_\n#define ABSL_TYPES_OPTIONAL_H_\n\n#include <optional>\n\n#include \"absl/base/config.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nusing std::bad_optional_access;\nusing std::make_optional;\nusing std::nullopt;\nusing std::nullopt_t;\nusing std::optional;\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_OPTIONAL_H_\n"
  },
  {
    "path": "absl/types/optional_ref.h",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: optional_ref.h\n// -----------------------------------------------------------------------------\n//\n// `optional_ref<T>` provides a `std::optional`-like interface around `T*`.\n// It is similar to C++26's `std::optional<T&>`, but with slight enhancements,\n// such as the fact that it permits construction from rvalues. That is, it\n// relaxes the std::reference_constructs_from_temporary constraint. Its intent\n// is to make it easier for functions to accept nullable object addresses,\n// regardless of whether or not they point to temporaries.\n//\n// It can be constructed in the following ways:\n//   * optional_ref<T> ref;\n//   * optional_ref<T> ref = std::nullopt;\n//   * T foo; optional_ref<T> ref = foo;\n//   * std::optional<T> foo; optional_ref<T> ref = foo;\n//   * T* foo = ...; optional_ref<T> ref = foo;\n//   * optional_ref<T> foo; optional_ref<const T> ref = foo;\n//\n// Since it is trivially copyable and destructible, it should be passed by\n// value.\n//\n// Other properties:\n//   * Assignment is not allowed. Example:\n//       optional_ref<int> ref;\n//       // Compile error.\n//       ref = 2;\n//\n//   * operator bool() is intentionally not defined, as it would be error prone\n//     for optional_ref<bool>.\n//\n// Example usage, assuming some type `T` that is expensive to copy:\n//   void ProcessT(optional_ref<const T> input) {\n//     if (!input.has_value()) {\n//       // Handle empty case.\n//       return;\n//     }\n//     const T& val = *input;\n//     // Do something with val.\n//   }\n//\n//   ProcessT(std::nullopt);\n//   ProcessT(BuildT());\n\n#ifndef ABSL_TYPES_OPTIONAL_REF_H_\n#define ABSL_TYPES_OPTIONAL_REF_H_\n\n#include <cstddef>\n#include <memory>\n#include <optional>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/optimization.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename T>\nclass optional_ref {\n  template <typename U>\n  using EnableIfConvertibleFrom =\n      std::enable_if_t<std::is_convertible_v<U*, T*>>;\n\n public:\n  using value_type = T;\n\n  constexpr optional_ref() : ptr_(nullptr) {}\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      std::nullopt_t)\n      : ptr_(nullptr) {}\n\n  // Constructor given a concrete value.\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      T& input ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : ptr_(std::addressof(input)) {}\n\n  // Constructors given an existing std::optional value.\n  // Templated on the input optional's type to avoid creating a temporary.\n  template <typename U, typename = EnableIfConvertibleFrom<const U>>\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      const std::optional<U>& input ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : ptr_(input.has_value() ? std::addressof(*input) : nullptr) {}\n  template <typename U, typename = EnableIfConvertibleFrom<U>>\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      std::optional<U>& input ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : ptr_(input.has_value() ? std::addressof(*input) : nullptr) {}\n\n  // Constructor given a T*, where nullptr indicates empty/absent.\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      T* input ABSL_ATTRIBUTE_LIFETIME_BOUND)\n      : ptr_(input) {}\n\n  // Don't allow naked nullptr as input, as this creates confusion in the case\n  // of optional_ref<T*>. Use std::nullopt instead to create an empty\n  // optional_ref.\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      std::nullptr_t) = delete;\n\n  // Copying is allowed.\n  optional_ref(const optional_ref<T>&) = default;\n  // Assignment is not allowed.\n  optional_ref<T>& operator=(const optional_ref<T>&) = delete;\n\n  // Conversion from optional_ref<U> is allowed iff U* is convertible to T*.\n  // (Note this also allows non-const to const conversions.)\n  template <typename U, typename = EnableIfConvertibleFrom<U>>\n  constexpr optional_ref(  // NOLINT(google-explicit-constructor)\n      optional_ref<U> input)\n      : ptr_(input.as_pointer()) {}\n\n  // Determines whether the `optional_ref` contains a value. Returns `false` if\n  // and only if `*this` is empty.\n  constexpr bool has_value() const { return ptr_ != nullptr; }\n\n  // Returns a reference to an `optional_ref`s underlying value. The constness\n  // and lvalue/rvalue-ness of the `optional_ref` is preserved to the view of\n  // the `T` sub-object. Throws the same error as `std::optional`'s `value()`\n  // when the `optional_ref` is empty.\n  constexpr T& value() const {\n    return ABSL_PREDICT_TRUE(ptr_ != nullptr)\n               ? *ptr_\n               // Replicate the same error logic as in `std::optional`'s\n               // `value()`. It either throws an exception or aborts the\n               // program. We intentionally ignore the return value of\n               // the constructed optional's value as we only need to run\n               // the code for error checking.\n               : ((void)std::optional<T>().value(), *ptr_);\n  }\n\n  // Returns the value iff *this has a value, otherwise returns `default_value`.\n  template <typename U>\n  constexpr T value_or(U&& default_value) const {\n    // Instantiate std::optional<T>::value_or(U) to trigger its static_asserts.\n    if (false) {\n      // We use `std::add_const_t` here since just using `const` makes MSVC\n      // complain about the syntax.\n      (void)std::add_const_t<std::optional<T>>{}.value_or(\n          std::forward<U>(default_value));\n    }\n    return ptr_ != nullptr ? *ptr_\n                           : static_cast<T>(std::forward<U>(default_value));\n  }\n\n  // Accesses the underlying `T` value of an `optional_ref`. If the\n  // `optional_ref` is empty, behavior is undefined.\n  constexpr T& operator*() const {\n    ABSL_HARDENING_ASSERT(ptr_ != nullptr);\n    return *ptr_;\n  }\n  constexpr T* operator->() const {\n    ABSL_HARDENING_ASSERT(ptr_ != nullptr);\n    return ptr_;\n  }\n\n  // Convenience function to represent the `optional_ref` as a `T*` pointer.\n  constexpr T* as_pointer() const { return ptr_; }\n  // Convenience function to represent the `optional_ref` as an `optional`,\n  // which incurs a copy when the `optional_ref` is non-empty. The template type\n  // allows for implicit type conversion; example:\n  //   optional_ref<std::string> a = ...;\n  //   std::optional<std::string_view> b = a.as_optional<std::string_view>();\n  template <typename U = std::decay_t<T>>\n  constexpr std::optional<U> as_optional() const {\n    if (ptr_ == nullptr) return std::nullopt;\n    return *ptr_;\n  }\n\n private:\n  T* const ptr_;\n\n  // T constraint checks.  You can't have an optional of nullopt_t or\n  // in_place_t.\n  static_assert(!std::is_same_v<std::nullopt_t, std::remove_cv_t<T>>,\n                \"optional_ref<nullopt_t> is not allowed.\");\n  static_assert(!std::is_same_v<std::in_place_t, std::remove_cv_t<T>>,\n                \"optional_ref<in_place_t> is not allowed.\");\n};\n\n// Template type deduction guides:\n\ntemplate <typename T>\noptional_ref(const T&) -> optional_ref<const T>;\ntemplate <typename T>\noptional_ref(T&) -> optional_ref<T>;\n\ntemplate <typename T>\noptional_ref(const std::optional<T>&) -> optional_ref<const T>;\ntemplate <typename T>\noptional_ref(std::optional<T>&) -> optional_ref<T>;\n\ntemplate <typename T>\noptional_ref(T*) -> optional_ref<T>;\n\nnamespace optional_ref_internal {\n\n// This is a C++-11 compatible version of std::equality_comparable_with that\n// only requires `t == u` is a valid boolean expression.\n//\n// We still need this for a couple reasons:\n// -  As of 2026-02-13, Abseil supports C++17.\n//  - Even for targets that are built with the default toolchain, using\n//    std::equality_comparable_with gives us an error due to mutual recursion\n//    between its definition and our definition of operator==.\n//\ntemplate <typename T, typename U>\nusing enable_if_equality_comparable_t = std::enable_if_t<std::is_convertible_v<\n    decltype(std::declval<T>() == std::declval<U>()), bool>>;\n\n}  // namespace optional_ref_internal\n\n// Compare an optional referenced value to std::nullopt.\n\ntemplate <typename T>\nconstexpr bool operator==(optional_ref<T> a, std::nullopt_t) {\n  return !a.has_value();\n}\ntemplate <typename T>\nconstexpr bool operator==(std::nullopt_t, optional_ref<T> b) {\n  return !b.has_value();\n}\ntemplate <typename T>\nconstexpr bool operator!=(optional_ref<T> a, std::nullopt_t) {\n  return a.has_value();\n}\ntemplate <typename T>\nconstexpr bool operator!=(std::nullopt_t, optional_ref<T> b) {\n  return b.has_value();\n}\n\n// Compare two optional referenced values. Note, this does not test that the\n// contained `ptr_`s are equal. If the caller wants \"shallow\" reference equality\n// semantics, they should use `as_pointer()` explicitly.\n\ntemplate <typename T, typename U>\nconstexpr bool operator==(optional_ref<T> a, optional_ref<U> b) {\n  return a.has_value() ? *a == b : !b.has_value();\n}\n\n// Compare an optional referenced value to a non-optional value.\n\ntemplate <\n    typename T, typename U,\n    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>\nconstexpr bool operator==(const T& a, optional_ref<U> b) {\n  return b.has_value() && a == *b;\n}\ntemplate <\n    typename T, typename U,\n    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>\nconstexpr bool operator==(optional_ref<T> a, const U& b) {\n  return b == a;\n}\n\n// Inequality operators, as above.\n\ntemplate <typename T, typename U>\nconstexpr bool operator!=(optional_ref<T> a, optional_ref<U> b) {\n  return !(a == b);\n}\ntemplate <\n    typename T, typename U,\n    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>\nconstexpr bool operator!=(optional_ref<T> a, const U& b) {\n  return !(a == b);\n}\ntemplate <\n    typename T, typename U,\n    typename = optional_ref_internal::enable_if_equality_comparable_t<T, U>>\nconstexpr bool operator!=(const T& a, optional_ref<U> b) {\n  return !(a == b);\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_OPTIONAL_REF_H_\n"
  },
  {
    "path": "absl/types/optional_ref_test.cc",
    "content": "// Copyright 2026 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/types/optional_ref.h\"\n\n#include <cstddef>\n#include <memory>\n#include <optional>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/config.h\"\n#include \"absl/log/log.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nnamespace {\n\nusing ::testing::Optional;\nusing ::testing::Pointee;\n\nTEST(OptionalRefTest, SimpleType) {\n  int val = 5;\n  optional_ref<int> ref = optional_ref(val);\n  optional_ref<int> empty_ref = std::nullopt;\n  EXPECT_THAT(ref, Optional(5));\n  EXPECT_TRUE(ref.has_value());\n  EXPECT_EQ(*ref, val);\n  EXPECT_EQ(ref.value(), val);\n  EXPECT_EQ(ref, ref);\n  EXPECT_EQ(ref, val);\n  EXPECT_EQ(val, ref);\n  EXPECT_NE(ref, empty_ref);\n  EXPECT_NE(empty_ref, ref);\n}\n\nTEST(OptionalRefTest, SimpleConstType) {\n  const int val = 5;\n  optional_ref<const int> ref = optional_ref(val);\n  EXPECT_THAT(ref, Optional(5));\n}\n\nTEST(OptionalRefTest, DefaultConstructed) {\n  optional_ref<int> ref;\n  EXPECT_EQ(ref, std::nullopt);\n  EXPECT_EQ(std::nullopt, ref);\n}\n\nTEST(OptionalRefTest, EmptyOptional) {\n  auto ref = optional_ref<int>(std::nullopt);\n  EXPECT_EQ(ref, std::nullopt);\n  EXPECT_EQ(std::nullopt, ref);\n}\n\nTEST(OptionalRefTest, OptionalType) {\n  const std::optional<int> val = 5;\n  optional_ref<const int> ref = val;\n  EXPECT_THAT(ref, Optional(5));\n  EXPECT_EQ(ref.as_pointer(), &*val);\n\n  const std::optional<int> empty;\n  optional_ref<const int> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n\n  // Cannot make non-const reference to const optional.\n  static_assert(\n      !std::is_convertible_v<const std::optional<int>&, optional_ref<int>>);\n}\n\nTEST(OptionalRefTest, NonConstOptionalType) {\n  std::optional<int> val = 5;\n  optional_ref<int> ref = val;\n  EXPECT_THAT(ref, Optional(5));\n  EXPECT_EQ(ref.as_pointer(), &*val);\n\n  std::optional<int> empty;\n  optional_ref<int> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n}\n\nTEST(OptionalRefTest, NonConstOptionalTypeToConstRef) {\n  std::optional<int> val = 5;\n  optional_ref<const int> ref = val;\n  EXPECT_THAT(ref, Optional(5));\n  EXPECT_EQ(ref.as_pointer(), &*val);\n\n  std::optional<int> empty;\n  optional_ref<const int> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n}\n\nTEST(OptionalRefTest, NonConstOptionalWithConstValueType) {\n  std::optional<const int> val = 5;\n  optional_ref<const int> ref = val;\n  EXPECT_THAT(ref, Optional(5));\n  EXPECT_EQ(ref.as_pointer(), &*val);\n\n  std::optional<const int> empty;\n  optional_ref<const int> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n\n  // Not possible to convert to non-const reference.\n  static_assert(\n      !std::is_convertible_v<std::optional<const int>&, optional_ref<int>>);\n}\n\nclass TestInterface {};\nclass TestDerivedClass : public TestInterface {};\n\nTEST(OptionalRefTest, BaseDerivedConvertibleOptionalType) {\n  const std::optional<TestDerivedClass> dc = TestDerivedClass{};\n  optional_ref<const TestInterface> ref = dc;\n  EXPECT_NE(ref, std::nullopt);\n  EXPECT_EQ(ref.as_pointer(), &*dc);\n\n  const std::optional<TestDerivedClass> empty;\n  optional_ref<const TestInterface> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<const std::optional<TestInterface>&,\n                                       optional_ref<const TestDerivedClass>>);\n  static_assert(!std::is_convertible_v<const std::optional<TestDerivedClass>&,\n                                       optional_ref<TestInterface>>);\n}\n\nTEST(OptionalRefTest, NonConstBaseDerivedConvertibleOptionalType) {\n  std::optional<TestDerivedClass> dc = TestDerivedClass{};\n  optional_ref<TestInterface> ref = dc;\n  EXPECT_NE(ref, std::nullopt);\n  EXPECT_EQ(ref.as_pointer(), &*dc);\n\n  std::optional<TestDerivedClass> empty;\n  optional_ref<TestInterface> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<std::optional<TestInterface>&,\n                                       optional_ref<TestDerivedClass>>);\n}\n\nTEST(OptionalRefTest, NonConstBaseDerivedConvertibleOptionalTypeToConstRef) {\n  std::optional<TestDerivedClass> dc = TestDerivedClass{};\n  optional_ref<const TestInterface> ref = dc;\n  EXPECT_NE(ref, std::nullopt);\n  EXPECT_EQ(ref.as_pointer(), &*dc);\n\n  std::optional<TestDerivedClass> empty;\n  optional_ref<const TestInterface> empty_ref = empty;\n  EXPECT_EQ(empty_ref, std::nullopt);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<std::optional<TestInterface>&,\n                                       optional_ref<const TestDerivedClass>>);\n  static_assert(!std::is_convertible_v<const std::optional<TestInterface>&,\n                                       optional_ref<const TestDerivedClass>>);\n}\n\nTEST(OptionalRefTest, PointerCtor) {\n  int val = 5;\n  optional_ref<const int> ref = &val;\n  EXPECT_THAT(ref, Optional(5));\n\n  auto auto_ref = optional_ref(&val);\n  static_assert(std::is_same_v<decltype(auto_ref), optional_ref<int>>,\n                \"optional_ref(T*) should deduce to optional_ref<T>.\");\n  EXPECT_THAT(auto_ref, Optional(5));\n\n  int* foo = nullptr;\n  optional_ref<const int> empty_ref = foo;\n  EXPECT_EQ(empty_ref, std::nullopt);\n\n  optional_ref<int*> ptr_ref = foo;\n  EXPECT_THAT(ptr_ref, Optional(nullptr));\n  static_assert(\n      !std::is_constructible_v<optional_ref<int*>, std::nullptr_t>,\n      \"optional_ref should not be constructible with std::nullptr_t.\");\n\n  // Pointer polymorphism works.\n  TestDerivedClass dc;\n  optional_ref<const TestInterface> dc_ref = &dc;\n  EXPECT_NE(dc_ref, std::nullopt);\n}\n\nTEST(OptionalRefTest, ValueDeathWhenEmpty) {\n  optional_ref<int> ref;\n#ifdef ABSL_HAVE_EXCEPTIONS\n  EXPECT_THROW(ref.value(), std::bad_optional_access);\n#else\n  EXPECT_DEATH_IF_SUPPORTED(ref.value(), \"\");\n#endif\n}\n\nTEST(OptionalRefTest, ImplicitCtor) {\n  const int val = 5;\n  optional_ref<const int> ref = val;\n  EXPECT_THAT(ref, Optional(5));\n}\n\nTEST(OptionalRefTest, DoesNotCopy) {\n  // Non-copyable type.\n  auto val = std::make_unique<int>(5);\n  optional_ref<std::unique_ptr<int>> ref = optional_ref(val);\n  EXPECT_THAT(ref, Optional(Pointee(5)));\n}\n\nTEST(OptionalRefTest, DoesNotCopyConst) {\n  // Non-copyable type.\n  const auto val = std::make_unique<int>(5);\n  optional_ref<const std::unique_ptr<int>> ref = optional_ref(val);\n  EXPECT_THAT(ref, Optional(Pointee(5)));\n}\n\nTEST(OptionalRefTest, RefCopyable) {\n  auto val = std::make_unique<int>(5);\n  optional_ref<std::unique_ptr<int>> ref = optional_ref(val);\n  optional_ref<std::unique_ptr<int>> copy = ref;\n  EXPECT_THAT(copy, Optional(Pointee(5)));\n}\n\nTEST(OptionalRefTest, ConstConvertible) {\n  auto val = std::make_unique<int>(5);\n  optional_ref<std::unique_ptr<int>> ref = optional_ref(val);\n  optional_ref<const std::unique_ptr<int>> converted = ref;\n  EXPECT_THAT(converted, Optional(Pointee(5)));\n  EXPECT_EQ(converted.as_pointer(), &val);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<optional_ref<const std::unique_ptr<int>>,\n                                       optional_ref<std::unique_ptr<int>>>);\n}\n\nTEST(OptionalRefTest, BaseDerivedConvertible) {\n  TestDerivedClass dc;\n  optional_ref<TestDerivedClass> dc_ref = dc;\n  optional_ref<TestInterface> converted = dc_ref;\n  EXPECT_NE(converted, std::nullopt);\n  EXPECT_EQ(converted.as_pointer(), &dc);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<optional_ref<TestInterface>,\n                                       optional_ref<TestDerivedClass>>);\n}\n\nTEST(OptionalRefTest, BaseDerivedConstConvertible) {\n  TestDerivedClass dc;\n  optional_ref<TestDerivedClass> dc_ref = dc;\n  optional_ref<const TestInterface> converted = dc_ref;\n  EXPECT_NE(converted, std::nullopt);\n  EXPECT_EQ(converted.as_pointer(), &dc);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<optional_ref<const TestInterface>,\n                                       optional_ref<TestDerivedClass>>);\n  static_assert(!std::is_convertible_v<optional_ref<const TestDerivedClass>,\n                                       optional_ref<TestInterface>>);\n}\n\nTEST(OptionalRefTest, BaseDerivedBothConstConvertible) {\n  TestDerivedClass dc;\n  optional_ref<const TestDerivedClass> dc_ref = dc;\n  optional_ref<const TestInterface> converted = dc_ref;\n  EXPECT_NE(converted, std::nullopt);\n  EXPECT_EQ(converted.as_pointer(), &dc);\n\n  // Not possible in the other direction.\n  static_assert(!std::is_convertible_v<optional_ref<const TestInterface>,\n                                       optional_ref<const TestDerivedClass>>);\n}\n\nTEST(OptionalRefTest, TriviallyCopyable) {\n  static_assert(\n      std::is_trivially_copyable_v<optional_ref<std::unique_ptr<int>>>);\n}\n\nTEST(OptionalRefTest, TriviallyDestructible) {\n  static_assert(\n      std::is_trivially_destructible_v<optional_ref<std::unique_ptr<int>>>);\n}\n\nTEST(OptionalRefTest, RefNotAssignable) {\n  static_assert(!std::is_copy_assignable_v<optional_ref<int>>);\n  static_assert(!std::is_move_assignable_v<optional_ref<int>>);\n}\n\nstruct TestStructWithCopy {\n  TestStructWithCopy() = default;\n  TestStructWithCopy(TestStructWithCopy&&) {\n    LOG(FATAL) << \"Move constructor should not be called\";\n  }\n  TestStructWithCopy(const TestStructWithCopy&) {\n    LOG(FATAL) << \"Copy constructor should not be called\";\n  }\n  TestStructWithCopy& operator=(const TestStructWithCopy&) {\n    LOG(FATAL) << \"Assign operator should not be called\";\n  }\n};\n\nTEST(OptionalRefTest, DoesNotCopyUsingFatalCopyAssignOps) {\n  TestStructWithCopy val;\n  optional_ref<TestStructWithCopy> ref = optional_ref(val);\n  EXPECT_NE(ref, std::nullopt);\n  EXPECT_NE(optional_ref(TestStructWithCopy{}), std::nullopt);\n}\n\nstd::string AddExclamation(optional_ref<const std::string> input) {\n  if (!input.has_value()) {\n    return \"\";\n  }\n  return absl::StrCat(*input, \"!\");\n}\n\nTEST(OptionalRefTest, RefAsFunctionParameter) {\n  EXPECT_EQ(AddExclamation(std::nullopt), \"\");\n  EXPECT_EQ(AddExclamation(std::string(\"abc\")), \"abc!\");\n  std::string s = \"def\";\n  EXPECT_EQ(AddExclamation(s), \"def!\");\n  EXPECT_EQ(AddExclamation(std::make_optional<std::string>(s)), \"def!\");\n}\n\nTEST(OptionalRefTest, ValueOrWhenHasValue) {\n  std::optional<int> val = 5;\n  EXPECT_EQ(optional_ref(val).value_or(2), 5);\n}\n\nTEST(OptionalRefTest, ValueOrWhenEmpty) {\n  std::optional<int> val = std::nullopt;\n  EXPECT_EQ(optional_ref(val).value_or(2), 2);\n}\n\nTEST(OptionalRefTest, AsOptional) {\n  EXPECT_EQ(optional_ref<int>().as_optional(), std::nullopt);\n  std::string val = \"foo\";\n  optional_ref<const std::string> ref = val;\n  static_assert(\n      std::is_same_v<decltype(ref.as_optional()), std::optional<std::string>>,\n      \"The type parameter of optional_ref should decay by default for the \"\n      \"return type in as_optional().\");\n  std::optional<std::string> opt_string = ref.as_optional();\n  EXPECT_THAT(opt_string, Optional(val));\n\n  std::optional<std::string_view> opt_view =\n      ref.as_optional<std::string_view>();\n  EXPECT_THAT(opt_view, Optional(val));\n}\n\nTEST(OptionalRefTest, Constexpr) {\n  static constexpr int foo = 123;\n  constexpr optional_ref<const int> ref(foo);\n  static_assert(ref.has_value() && *ref == foo && ref.value() == foo, \"\");\n}\n\n}  // namespace\nABSL_NAMESPACE_END\n}  // namespace absl\n"
  },
  {
    "path": "absl/types/source_location.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// File: source_location.h\n// -----------------------------------------------------------------------------\n//\n// absl::SourceLocation provides source-code location info for C++17 and later.\n//\n// Critically, it is a **view type** (like std::string_view). Unlike\n// std::source_location, it is not permanently valid and must not outlive its\n// source. Using an invalid location is an error and may result in warnings\n// or crashes.\n//\n// Additionally, it does not guarantee the retention of all caller information\n// (e.g. column or function name) and may e.g. return unspecified values for\n// performance reasons.\n//\n// To define a function that has access to the source location of the\n// callsite, define it with a parameter of type `absl::SourceLocation`. The\n// caller can then invoke the function, passing\n// `absl::SourceLocation::current()` as the argument.\n//\n// If at all possible, make the `absl::SourceLocation` parameter be the\n// function's last parameter. That way, when `std::source_location` is\n// available, you will be able to switch to it, and give the parameter a default\n// argument of `std::source_location::current()`. Users will then be able to\n// omit that argument, and the default will automatically capture the location\n// of the callsite.\n\n#ifndef ABSL_TYPES_SOURCE_LOCATION_H_\n#define ABSL_TYPES_SOURCE_LOCATION_H_\n\n#include <cstdint>\n#include <type_traits>\n\n#include \"absl/base/config.h\"\n#include \"absl/base/nullability.h\"\n\n// This needs to come after absl/base/config.h, which is responsible for\n// defining ABSL_HAVE_STD_SOURCE_LOCATION\n#ifdef ABSL_HAVE_STD_SOURCE_LOCATION\n#include <source_location>  // NOLINT(build/c++20)\n#endif\n\n// For OSS release, whether to alias to std::source_location is configurable via\n// config.h/options.h, similar to std::string_view/variant/etc.\n#if defined(ABSL_USES_STD_SOURCE_LOCATION) && \\\n    defined(ABSL_HAVE_STD_SOURCE_LOCATION)\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nusing SourceLocation = std::source_location;\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#else  // ABSL_HAVE_STD_SOURCE_LOCATION\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// C++17-compatible class representing a specific location in the source code of\n// a program. Similar to std::source_location, but with a few key differences\n// explained above.\nclass SourceLocation {\n  struct PrivateTag {\n   private:\n    explicit PrivateTag() = default;\n    friend class SourceLocation;\n  };\n\n public:\n  // Avoid this constructor; it populates the object with dummy values.\n  SourceLocation() = default;\n\n#ifdef ABSL_HAVE_STD_SOURCE_LOCATION\n  constexpr SourceLocation(  // NOLINT(google-explicit-constructor)\n      std::source_location loc)\n      : SourceLocation(loc.line(), loc.file_name()) {}\n#endif\n\n#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE\n  // SourceLocation::current\n  //\n  // Creates a `SourceLocation` based on the current source location. Currently,\n  // it only captures file and line information for efficiency purposes, but\n  // that is subject to change. APIs that accept a `SourceLocation` as a default\n  // parameter can use this to capture their caller's locations.\n  //\n  // Example:\n  //\n  //   void TracedAdd(int i, SourceLocation loc = SourceLocation::current()) {\n  //     std::cout << loc.file_name() << \":\" << loc.line() << \" added \" << i;\n  //     ...\n  //   }\n  //\n  //   void UserCode() {\n  //     TracedAdd(1);\n  //     TracedAdd(2);\n  //   }\n  static constexpr SourceLocation current(\n      PrivateTag = PrivateTag{}, std::uint_least32_t line = __builtin_LINE(),\n      const char* absl_nonnull file_name = __builtin_FILE()) {\n    return SourceLocation(line, file_name);\n  }\n#else\n  // Creates a dummy `SourceLocation` of \"<source_location>\" at line number 1,\n  // if no `SourceLocation::current()` implementation is available.\n  static constexpr SourceLocation current() {\n    return SourceLocation(1, \"<source_location>\");\n  }\n#endif\n  // The line number of the captured source location, or an unspecified value\n  // if this information is not available.\n  constexpr std::uint_least32_t line() const noexcept { return line_; }\n\n  // The column number of the captured source location, or an unspecified value\n  // if this information is not available.\n  constexpr std::uint_least32_t column() const noexcept { return 0; }\n\n  // The file name of the captured source location, or an unspecified string\n  // if this information is not available. Guaranteed to never be NULL.\n  constexpr const char* absl_nonnull file_name() const noexcept {\n    return file_name_;\n  }\n\n  // The function name of the captured source location, or an unspecified string\n  // if this information is not available. Guaranteed to never be NULL.\n  //\n  // NOTE: Currently, we deliberately avoid providing the function name, as it\n  // can bloat binary sizes and is non-critical. This may change in the future.\n  constexpr const char* absl_nonnull function_name() const noexcept {\n    return \"\";\n  }\n\n private:\n  // `file_name` must outlive all copies of the `absl::SourceLocation` object,\n  // so in practice it should be a string literal.\n  constexpr SourceLocation(std::uint_least32_t line,\n                           const char* absl_nonnull file_name)\n      : line_(line), file_name_(file_name) {}\n\n  // We would use [[maybe_unused]] here, but it doesn't work on all supported\n  // toolchains at the moment.\n  friend constexpr int UseUnused() {\n    static_assert(SourceLocation(0, nullptr).unused_column_ == 0,\n                  \"Use the otherwise-unused member.\");\n    return 0;\n  }\n\n  // \"unused\" members are present to minimize future changes in the size of this\n  // type.\n  std::uint_least32_t line_ = 0;\n  std::uint_least32_t unused_column_ = 0;\n  const char* absl_nonnull file_name_ = \"\";\n};\n\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_HAVE_STD_SOURCE_LOCATION\n\n#endif  // ABSL_TYPES_SOURCE_LOCATION_H_\n"
  },
  {
    "path": "absl/types/source_location_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/types/source_location.h\"\n\n#include \"absl/base/config.h\"\n\n#ifdef ABSL_HAVE_STD_SOURCE_LOCATION\n#include <source_location>  // NOLINT(build/c++20)\n#endif\n#include <type_traits>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/strings/string_view.h\"\n\nnamespace {\n\nusing ::absl::SourceLocation;\nusing ::testing::EndsWith;\n\nTEST(SourceLocationTest, DefaultConstructionWorks) {\n  static_assert(!std::is_trivially_default_constructible_v<SourceLocation>);\n  static_assert(std::is_nothrow_default_constructible_v<SourceLocation>);\n  constexpr SourceLocation loc1 [[maybe_unused]];\n  SourceLocation loc2 [[maybe_unused]]{};\n  EXPECT_EQ(loc1.line(), loc2.line());\n}\n\n#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE\n\nTEST(SourceLocationTest, ConstexprMembers) {\n  constexpr SourceLocation loc1 = absl::SourceLocation::current();\n  const SourceLocation loc2 = absl::SourceLocation::current();\n  EXPECT_EQ(loc1.line(), loc2.line() - 1);\n  EXPECT_EQ(absl::string_view(loc1.file_name()), loc2.file_name());\n}\n\nTEST(SourceLocationTest, ConversionFromStdSourceLocationWorks) {\n#ifndef ABSL_HAVE_STD_SOURCE_LOCATION\n  GTEST_SKIP() << \"std::source_location is not available\";\n#else\n  constexpr SourceLocation loc1 = std::source_location::current();\n  const std::source_location loc2 = std::source_location::current();\n  EXPECT_EQ(loc1.line(), loc2.line() - 1);\n  EXPECT_EQ(absl::string_view(loc1.file_name()), loc2.file_name());\n#endif\n}\n\nTEST(SourceLocationTest, CopyConstructionWorks) {\n  constexpr SourceLocation location = absl::SourceLocation::current();\n  constexpr int line = __LINE__ - 1;\n\n  EXPECT_EQ(location.line(), line);\n  EXPECT_THAT(location.file_name(), EndsWith(\"source_location_test.cc\"));\n}\n\nTEST(SourceLocationTest, CopyAssignmentWorks) {\n  SourceLocation location;\n  location = absl::SourceLocation::current();\n  constexpr int line = __LINE__ - 1;\n\n  EXPECT_EQ(location.line(), line);\n  EXPECT_THAT(location.file_name(), EndsWith(\"source_location_test.cc\"));\n}\n\nSourceLocation Echo(const SourceLocation& location) { return location; }\n\nTEST(SourceLocationTest, ExpectedUsageWorks) {\n  SourceLocation location = Echo(absl::SourceLocation::current());\n  constexpr int line = __LINE__ - 1;\n\n  EXPECT_EQ(location.line(), line);\n  EXPECT_THAT(location.file_name(), EndsWith(\"source_location_test.cc\"));\n}\n\nTEST(SourceLocationTest, CurrentWorks) {\n  constexpr SourceLocation location = SourceLocation::current();\n  constexpr int line = __LINE__ - 1;\n\n  EXPECT_EQ(location.line(), line);\n  EXPECT_THAT(location.file_name(), EndsWith(\"source_location_test.cc\"));\n}\n\nSourceLocation FuncWithDefaultParam(\n    SourceLocation loc = SourceLocation::current()) {\n  return loc;\n}\n\nTEST(SourceLocationTest, CurrentWorksAsDefaultParam) {\n  SourceLocation location = FuncWithDefaultParam();\n  constexpr int line = __LINE__ - 1;\n\n  EXPECT_EQ(location.line(), line);\n  EXPECT_THAT(location.file_name(), EndsWith(\"source_location_test.cc\"));\n}\n\n#endif\n\ntemplate <typename T>\nbool TryPassLineAndFile(decltype(T::current(0, \"\"))*) {\n  return true;\n}\ntemplate <typename T>\nbool TryPassLineAndFile(decltype(T::current({}, 0, \"\"))*) {\n  return true;\n}\ntemplate <typename T>\nbool TryPassLineAndFile(decltype(T::current(typename T::Tag{}, 0, \"\"))*) {\n  return true;\n}\ntemplate <typename T>\nbool TryPassLineAndFile(...) {\n  return false;\n}\n\nTEST(SourceLocationTest, CantPassLineAndFile) {\n#ifdef ABSL_HAVE_STD_SOURCE_LOCATION\n  using StdSourceLocation = std::source_location;\n#else\n  using StdSourceLocation = void;\n#endif\n  if constexpr (!std::is_same_v<absl::SourceLocation, StdSourceLocation>) {\n    EXPECT_FALSE(TryPassLineAndFile<absl::SourceLocation>(nullptr));\n  }\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/types/span.h",
    "content": "//\n// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// span.h\n// -----------------------------------------------------------------------------\n//\n// This header file defines a `Span<T>` type for holding a reference to existing\n// array data. The `Span` object, much like the `absl::string_view` object,\n// does not own such data itself, and the data being referenced by the span must\n// outlive the span itself. Unlike `view` type references, a span can hold a\n// reference to mutable data (and can mutate it for underlying types of\n// non-const T.) A span provides a lightweight way to pass a reference to such\n// data.\n//\n// Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()`\n// factory functions, for clearly creating spans of type `Span<T>` or read-only\n// `Span<const T>` when such types may be difficult to identify due to issues\n// with implicit conversion.\n//\n// The C++20 standard includes a `std::span` type. As of January 2026, the\n// differences between `absl::Span` and `std::span` are:\n//    * `absl::Span` has `operator==` (which is likely a design bug,\n//       per https://abseil.io/blog/20180531-regular-types)\n//    * `absl::Span` has the factory functions `MakeSpan()` and\n//      `MakeConstSpan()`\n//    * bounds-checked access to `absl::Span` is accomplished with `at()`\n//      however `std::span` now supports the same as of the draft C++26 standard\n//    * `absl::Span` has compiler-provided move and copy constructors and\n//      assignment. This is due to them being specified as `constexpr`, but that\n//      implies const in C++11.\n//    * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or\n//      `as_writable_bytes()` methods\n//    * `absl::Span` has no static extent template parameter, nor constructors\n//      which exist only because of the static extent parameter.\n//    * `absl::Span` has an explicit mutable-reference constructor\n//    * `absl::Span::subspan(pos, len)` always truncates `len` to\n//      `size() - pos`, whereas `std::span::subspan()` only truncates when the\n//      `len` parameter is defaulted.\n//\n// For more information, see the class comments below.\n#ifndef ABSL_TYPES_SPAN_H_\n#define ABSL_TYPES_SPAN_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <iterator>\n#include <type_traits>\n#include <utility>\n\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/macros.h\"\n#include \"absl/base/nullability.h\"\n#include \"absl/base/optimization.h\"\n#include \"absl/base/port.h\"  // TODO(strel): remove this include\n#include \"absl/base/throw_delegate.h\"\n#include \"absl/hash/internal/weakly_mixed_integer.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/types/internal/span.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\ntemplate <typename T>\nclass Span;\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n// If std::ranges is available, mark Span as satisfying the `view` and\n// `borrowed_range` concepts, just like std::span.\n#if !defined(__has_include)\n#define __has_include(header) 0\n#endif\n#if __has_include(<version>)\n#include <version>  // NOLINT(misc-include-cleaner)\n#endif\n#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L\n#include <ranges>  // NOLINT(build/c++20)\ntemplate <typename T>\n// NOLINTNEXTLINE(build/c++20)\ninline constexpr bool std::ranges::enable_view<absl::Span<T>> = true;\ntemplate <typename T>\n// NOLINTNEXTLINE(build/c++20)\ninline constexpr bool std::ranges::enable_borrowed_range<absl::Span<T>> = true;\n#endif\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n//------------------------------------------------------------------------------\n// Span\n//------------------------------------------------------------------------------\n//\n// A `Span` is an \"array reference\" type for holding a reference of contiguous\n// array data; the `Span` object does not and cannot own such data itself. A\n// span provides an easy way to provide overloads for anything operating on\n// contiguous sequences without needing to manage pointers and array lengths\n// manually.\n\n// A span is conceptually a pointer (ptr) and a length (size) into an already\n// existing array of contiguous memory; the array it represents references the\n// elements \"ptr[0] .. ptr[size-1]\". Passing a properly-constructed `Span`\n// instead of raw pointers avoids many issues related to index out of bounds\n// errors.\n//\n// Spans may also be constructed from containers holding contiguous sequences.\n// Such containers must supply `data()` and `size() const` methods (e.g\n// `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to\n// `absl::Span` from such containers will create spans of type `const T`;\n// spans which can mutate their values (of type `T`) must use explicit\n// constructors.\n//\n// A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array\n// of elements of type `T`, and unlike an `absl::string_view`, a span can hold a\n// reference to mutable data. A user of `Span` must ensure that the data being\n// pointed to outlives the `Span` itself.\n//\n// You can construct a `Span<T>` in several ways:\n//\n//   * Explicitly from a reference to a container type\n//   * Explicitly from a pointer and size\n//   * Implicitly from a container type (but only for spans of type `const T`)\n//   * Using the `MakeSpan()` or `MakeConstSpan()` factory functions.\n//\n// Examples:\n//\n//   // Construct a Span explicitly from a container:\n//   std::vector<int> v = {1, 2, 3, 4, 5};\n//   auto span = absl::Span<const int>(v);\n//\n//   // Construct a Span explicitly from a C-style array:\n//   int a[5] =  {1, 2, 3, 4, 5};\n//   auto span = absl::Span<const int>(a);\n//\n//   // Construct a Span implicitly from a container\n//   void MyRoutine(absl::Span<const int> a) {\n//     ...\n//   }\n//   std::vector v = {1,2,3,4,5};\n//   MyRoutine(v)                     // convert to Span<const T>\n//\n// Note that `Span` objects, in addition to requiring that the memory they\n// point to remains alive, must also ensure that such memory does not get\n// reallocated. Therefore, to avoid undefined behavior, containers with\n// associated spans should not invoke operations that may reallocate memory\n// (such as resizing) or invalidate iterators into the container.\n//\n// One common use for a `Span` is when passing arguments to a routine that can\n// accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`,\n// a C-style array, etc.). Instead of creating overloads for each case, you\n// can simply specify a `Span` as the argument to such a routine.\n//\n// Example:\n//\n//   void MyRoutine(absl::Span<const int> a) {\n//     ...\n//   }\n//\n//   std::vector v = {1,2,3,4,5};\n//   MyRoutine(v);\n//\n//   absl::InlinedVector<int, 4> my_inline_vector;\n//   MyRoutine(my_inline_vector);\n//\n//   // Explicit constructor from pointer,size\n//   int* my_array = new int[10];\n//   MyRoutine(absl::Span<const int>(my_array, 10));\ntemplate <typename T>\nclass ABSL_ATTRIBUTE_VIEW Span {\n private:\n  // Used to determine whether a Span can be constructed from a container of\n  // type C.\n  template <typename C>\n  using EnableIfConvertibleFrom =\n      std::enable_if_t<!std::is_same_v<Span, std::remove_reference_t<C>> &&\n                       span_internal::HasData<T, C>::value &&\n                       span_internal::HasSize<C>::value>;\n\n  // Used to SFINAE-enable a function when the slice elements are const.\n  template <typename U>\n  using EnableIfValueIsConst =\n      typename std::enable_if<std::is_const<T>::value, U>::type;\n\n  // Used to SFINAE-enable a function when the slice elements are mutable.\n  template <typename U>\n  using EnableIfValueIsMutable =\n      typename std::enable_if<!std::is_const<T>::value, U>::type;\n\n public:\n  using element_type = T;\n  using value_type = absl::remove_cv_t<T>;\n  // TODO(b/316099902) - pointer should be absl_nullable, but this makes it hard\n  // to recognize foreach loops as safe. absl_nullability_unknown is currently\n  // used to suppress -Wnullability-completeness warnings.\n  using pointer = T* absl_nullability_unknown;\n  using const_pointer = const T* absl_nullability_unknown;\n  using reference = T&;\n  using const_reference = const T&;\n  using iterator = pointer;\n  using const_iterator = const_pointer;\n  using reverse_iterator = std::reverse_iterator<iterator>;\n  using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n  using size_type = size_t;\n  using difference_type = ptrdiff_t;\n  using absl_internal_is_view = std::true_type;\n\n  // NOLINTNEXTLINE\n  static const size_type npos = ~(size_type(0));\n\n  constexpr Span() noexcept : Span(nullptr, 0) {}\n  constexpr Span(pointer array ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                 size_type length) noexcept\n      : ptr_(array), len_(length) {}\n\n  // Implicit conversion constructors\n  template <size_t N>\n  constexpr Span(T(  // NOLINT(google-explicit-constructor)\n      &a ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) noexcept\n      : Span(a, N) {}\n\n  // Explicit reference constructor for a mutable `Span<T>` type. Can be\n  // replaced with MakeSpan() to infer the type parameter.\n  template <typename V, typename = EnableIfConvertibleFrom<V>,\n            typename = EnableIfValueIsMutable<V>,\n            typename = span_internal::EnableIfNotIsView<V>>\n  explicit Span(\n      V& v\n          ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/references)\n      : Span(span_internal::GetData(v), v.size()) {}\n\n  // Implicit reference constructor for a read-only `Span<const T>` type\n  template <typename V, typename = EnableIfConvertibleFrom<V>,\n            typename = EnableIfValueIsConst<V>,\n            typename = span_internal::EnableIfNotIsView<V>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  constexpr Span(const V& v ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n      : Span(span_internal::GetData(v), v.size()) {}\n\n  // Overloads of the above two functions that are only enabled for view types.\n  // This is so we can drop the ABSL_ATTRIBUTE_LIFETIME_BOUND annotation. These\n  // overloads must be made unique by using a different template parameter list\n  // (hence the = 0 for the IsView enabler).\n  template <typename V, typename = EnableIfConvertibleFrom<V>,\n            typename = EnableIfValueIsMutable<V>,\n            span_internal::EnableIfIsView<V> = 0>\n  explicit Span(V& v) noexcept  // NOLINT(runtime/references)\n      : Span(span_internal::GetData(v), v.size()) {}\n  template <typename V, typename = EnableIfConvertibleFrom<V>,\n            typename = EnableIfValueIsConst<V>,\n            span_internal::EnableIfIsView<V> = 0>\n  constexpr Span(const V& v) noexcept  // NOLINT(google-explicit-constructor)\n      : Span(span_internal::GetData(v), v.size()) {}\n\n  // Implicit constructor from an initializer list, making it possible to pass a\n  // brace-enclosed initializer list to a function expecting a `Span`. Such\n  // spans constructed from an initializer list must be of type `Span<const T>`.\n  //\n  //   void Process(absl::Span<const int> x);\n  //   Process({1, 2, 3});\n  //\n  // Note that as always the array referenced by the span must outlive the span.\n  // Since an initializer list constructor acts as if it is fed a temporary\n  // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this\n  // constructor only when the `std::initializer_list` itself outlives the span.\n  // In order to meet this requirement it's sufficient to ensure that neither\n  // the span nor a copy of it is used outside of the expression in which it's\n  // created:\n  //\n  //   // Assume that this function uses the array directly, not retaining any\n  //   // copy of the span or pointer to any of its elements.\n  //   void Process(absl::Span<const int> ints);\n  //\n  //   // Okay: the std::initializer_list<int> will reference a temporary array\n  //   // that isn't destroyed until after the call to Process returns.\n  //   Process({ 17, 19 });\n  //\n  //   // Not okay: the storage used by the std::initializer_list<int> is not\n  //   // allowed to be referenced after the first line.\n  //   absl::Span<const int> ints = { 17, 19 };\n  //   Process(ints);\n  //\n  //   // Not okay for the same reason as above: even when the elements of the\n  //   // initializer list expression are not temporaries the underlying array\n  //   // is, so the initializer list must still outlive the span.\n  //   const int foo = 17;\n  //   absl::Span<const int> ints = { foo };\n  //   Process(ints);\n  //\n  template <typename LazyT = T,\n            typename = EnableIfValueIsConst<LazyT>>\n  Span(std::initializer_list<value_type> v\n           ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/explicit)\n      : Span(v.begin(), v.size()) {}\n\n  // Accessors\n\n  // Span::data()\n  //\n  // Returns a pointer to the span's underlying array of data (which is held\n  // outside the span).\n  constexpr pointer data() const noexcept { return ptr_; }\n\n  // Span::size()\n  //\n  // Returns the size of this span.\n  constexpr size_type size() const noexcept { return len_; }\n\n  // Span::length()\n  //\n  // Returns the length (size) of this span.\n  constexpr size_type length() const noexcept { return size(); }\n\n  // Span::empty()\n  //\n  // Returns a boolean indicating whether or not this span is considered empty.\n  constexpr bool empty() const noexcept { return size() == 0; }\n\n  // Span::operator[]\n  //\n  // Returns a reference to the i'th element of this span.\n  constexpr reference operator[](size_type i) const noexcept {\n    ABSL_HARDENING_ASSERT(i < size());\n    return ptr_[i];\n  }\n\n  // Span::at()\n  //\n  // Returns a reference to the i'th element of this span.\n  constexpr reference at(size_type i) const {\n    return ABSL_PREDICT_TRUE(i < size())  //\n               ? *(data() + i)\n               : (ThrowStdOutOfRange(\"Span::at failed bounds check\"),\n                  *(data() + i));\n  }\n\n  // Span::front()\n  //\n  // Returns a reference to the first element of this span. The span must not\n  // be empty.\n  constexpr reference front() const noexcept {\n    ABSL_HARDENING_ASSERT(size() > 0);\n    return *data();\n  }\n\n  // Span::back()\n  //\n  // Returns a reference to the last element of this span. The span must not\n  // be empty.\n  constexpr reference back() const noexcept {\n    ABSL_HARDENING_ASSERT(size() > 0);\n    return *(data() + size() - 1);\n  }\n\n  // Span::begin()\n  //\n  // Returns an iterator pointing to the first element of this span, or `end()`\n  // if the span is empty.\n  constexpr iterator begin() const noexcept { return data(); }\n\n  // Span::cbegin()\n  //\n  // Returns a const iterator pointing to the first element of this span, or\n  // `end()` if the span is empty.\n  constexpr const_iterator cbegin() const noexcept { return begin(); }\n\n  // Span::end()\n  //\n  // Returns an iterator pointing just beyond the last element at the\n  // end of this span. This iterator acts as a placeholder; attempting to\n  // access it results in undefined behavior.\n  constexpr iterator end() const noexcept { return data() + size(); }\n\n  // Span::cend()\n  //\n  // Returns a const iterator pointing just beyond the last element at the\n  // end of this span. This iterator acts as a placeholder; attempting to\n  // access it results in undefined behavior.\n  constexpr const_iterator cend() const noexcept { return end(); }\n\n  // Span::rbegin()\n  //\n  // Returns a reverse iterator pointing to the last element at the end of this\n  // span, or `rend()` if the span is empty.\n  constexpr reverse_iterator rbegin() const noexcept {\n    return reverse_iterator(end());\n  }\n\n  // Span::crbegin()\n  //\n  // Returns a const reverse iterator pointing to the last element at the end of\n  // this span, or `crend()` if the span is empty.\n  constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }\n\n  // Span::rend()\n  //\n  // Returns a reverse iterator pointing just before the first element\n  // at the beginning of this span. This pointer acts as a placeholder;\n  // attempting to access its element results in undefined behavior.\n  constexpr reverse_iterator rend() const noexcept {\n    return reverse_iterator(begin());\n  }\n\n  // Span::crend()\n  //\n  // Returns a reverse const iterator pointing just before the first element\n  // at the beginning of this span. This pointer acts as a placeholder;\n  // attempting to access its element results in undefined behavior.\n  constexpr const_reverse_iterator crend() const noexcept { return rend(); }\n\n  // Span mutations\n\n  // Span::remove_prefix()\n  //\n  // Removes the first `n` elements from the span.\n  void remove_prefix(size_type n) noexcept {\n    ABSL_HARDENING_ASSERT(size() >= n);\n    ptr_ += n;\n    len_ -= n;\n  }\n\n  // Span::remove_suffix()\n  //\n  // Removes the last `n` elements from the span.\n  void remove_suffix(size_type n) noexcept {\n    ABSL_HARDENING_ASSERT(size() >= n);\n    len_ -= n;\n  }\n\n  // Span::subspan()\n  //\n  // Returns a `Span` starting at element `pos` and of length `len`. Both `pos`\n  // and `len` are of type `size_type` and thus non-negative. Parameter `pos`\n  // must be <= size(). Any `len` value that points past the end of the span\n  // will be trimmed to at most size() - `pos`. A default `len` value of `npos`\n  // ensures the returned subspan continues until the end of the span.\n  //\n  // Note that trimming behavior differs from `std::span::subspan()`.\n  // `std::span::subspan()` requires `len == npos || pos + len <= size()`.\n  // In other words, `std::span::subspan()` only trims `len` when its value is\n  // defaulted.\n  //\n  // Examples:\n  //\n  //   std::vector<int> vec = {10, 11, 12, 13};\n  //   absl::MakeSpan(vec).subspan(1, 2);  // {11, 12}\n  //   absl::MakeSpan(vec).subspan(2, 8);  // {12, 13}\n  //   absl::MakeSpan(vec).subspan(1);     // {11, 12, 13}\n  //   absl::MakeSpan(vec).subspan(4);     // {}\n  //   absl::MakeSpan(vec).subspan(5);     // throws std::out_of_range\n  constexpr Span subspan(size_type pos = 0, size_type len = npos) const {\n    return (pos <= size()) ? Span(data() + pos, (std::min)(size() - pos, len))\n                           : (ThrowStdOutOfRange(\"pos > size()\"), Span());\n  }\n\n  // Span::first()\n  //\n  // Returns a `Span` containing first `len` elements. Parameter `len` is of\n  // type `size_type` and thus non-negative. `len` value must be <= size().\n  //\n  // Examples:\n  //\n  //   std::vector<int> vec = {10, 11, 12, 13};\n  //   absl::MakeSpan(vec).first(1);  // {10}\n  //   absl::MakeSpan(vec).first(3);  // {10, 11, 12}\n  //   absl::MakeSpan(vec).first(5);  // throws std::out_of_range\n  constexpr Span first(size_type len) const {\n    return (len <= size()) ? Span(data(), len)\n                           : (ThrowStdOutOfRange(\"len > size()\"), Span());\n  }\n\n  // Span::last()\n  //\n  // Returns a `Span` containing last `len` elements. Parameter `len` is of\n  // type `size_type` and thus non-negative. `len` value must be <= size().\n  //\n  // Examples:\n  //\n  //   std::vector<int> vec = {10, 11, 12, 13};\n  //   absl::MakeSpan(vec).last(1);  // {13}\n  //   absl::MakeSpan(vec).last(3);  // {11, 12, 13}\n  //   absl::MakeSpan(vec).last(5);  // throws std::out_of_range\n  constexpr Span last(size_type len) const {\n    return (len <= size()) ? Span(size() - len + data(), len)\n                           : (ThrowStdOutOfRange(\"len > size()\"), Span());\n  }\n\n  // Support for absl::Hash.\n  template <typename H>\n  friend H AbslHashValue(H h, Span v) {\n    return H::combine_contiguous(std::move(h), v.data(), v.size());\n  }\n\n private:\n  pointer ptr_;\n  size_type len_;\n};\n\ntemplate <typename T>\nconst typename Span<T>::size_type Span<T>::npos;\n\n// Span relationals\n\n// Equality is compared element-by-element, while ordering is lexicographical.\n// We provide three overloads for each operator to cover any combination on the\n// left or right hand side of mutable Span<T>, read-only Span<const T>, and\n// convertible-to-read-only Span<T>.\n// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering\n// template functions, 5 overloads per operator is needed as a workaround. We\n// should update them to 3 overloads per operator using non-deduced context like\n// string_view, i.e.\n// - (Span<T>, Span<T>)\n// - (Span<T>, non_deduced<Span<const T>>)\n// - (non_deduced<Span<const T>>, Span<T>)\n\n// operator==\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, Span<T> b) {\n  return span_internal::EqualImpl<Span, const T>(a, b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<const T> a,\n                                                    Span<T> b) {\n  return span_internal::EqualImpl<Span, const T>(a, b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a,\n                                                    Span<const T> b) {\n  return span_internal::EqualImpl<Span, const T>(a, b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(const U& a, Span<T> b) {\n  return span_internal::EqualImpl<Span, const T>(a, b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, const U& b) {\n  return span_internal::EqualImpl<Span, const T>(a, b);\n}\n\n// operator!=\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, Span<T> b) {\n  return !(a == b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<const T> a,\n                                                    Span<T> b) {\n  return !(a == b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a,\n                                                    Span<const T> b) {\n  return !(a == b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(const U& a, Span<T> b) {\n  return !(a == b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, const U& b) {\n  return !(a == b);\n}\n\n// operator<\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<T> b) {\n  return span_internal::LessThanImpl<Span, const T>(a, b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<const T> a, Span<T> b) {\n  return span_internal::LessThanImpl<Span, const T>(a, b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<const T> b) {\n  return span_internal::LessThanImpl<Span, const T>(a, b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(const U& a, Span<T> b) {\n  return span_internal::LessThanImpl<Span, const T>(a, b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, const U& b) {\n  return span_internal::LessThanImpl<Span, const T>(a, b);\n}\n\n// operator>\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<T> b) {\n  return b < a;\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<const T> a, Span<T> b) {\n  return b < a;\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<const T> b) {\n  return b < a;\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(const U& a, Span<T> b) {\n  return b < a;\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, const U& b) {\n  return b < a;\n}\n\n// operator<=\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, Span<T> b) {\n  return !(b < a);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<const T> a,\n                                                    Span<T> b) {\n  return !(b < a);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a,\n                                                    Span<const T> b) {\n  return !(b < a);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(const U& a, Span<T> b) {\n  return !(b < a);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, const U& b) {\n  return !(b < a);\n}\n\n// operator>=\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, Span<T> b) {\n  return !(a < b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<const T> a,\n                                                    Span<T> b) {\n  return !(a < b);\n}\ntemplate <typename T>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a,\n                                                    Span<const T> b) {\n  return !(a < b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(const U& a, Span<T> b) {\n  return !(a < b);\n}\ntemplate <\n    typename T, typename U,\n    typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>\nABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, const U& b) {\n  return !(a < b);\n}\n\n// MakeSpan()\n//\n// Constructs a mutable `Span<T>`, deducing `T` automatically from either a\n// container or pointer+size.\n//\n// Because a read-only `Span<const T>` is implicitly constructed from container\n// types regardless of whether the container itself is a const container,\n// constructing mutable spans of type `Span<T>` from containers requires\n// explicit constructors. The container-accepting version of `MakeSpan()`\n// deduces the type of `T` by the constness of the pointer received from the\n// container's `data()` member. Similarly, the pointer-accepting version returns\n// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise.\n//\n// Examples:\n//\n//   void MyRoutine(absl::Span<MyComplicatedType> a) {\n//     ...\n//   };\n//   // my_vector is a container of non-const types\n//   std::vector<MyComplicatedType> my_vector;\n//\n//   // Constructing a Span implicitly attempts to create a Span of type\n//   // `Span<const T>`\n//   MyRoutine(my_vector);                // error, type mismatch\n//\n//   // Explicitly constructing the Span is verbose\n//   MyRoutine(absl::Span<MyComplicatedType>(my_vector));\n//\n//   // Use MakeSpan() to make an absl::Span<T>\n//   MyRoutine(absl::MakeSpan(my_vector));\n//\n//   // Construct a span from an array ptr+size\n//   absl::Span<T> my_span() {\n//     return absl::MakeSpan(&array[0], num_elements_);\n//   }\n//\ntemplate <int&... ExplicitArgumentBarrier, typename T>\nconstexpr Span<T> MakeSpan(T* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                           size_t size) noexcept {\n  return Span<T>(ptr, size);\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename T>\nSpan<T> MakeSpan(T* absl_nullable begin ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                 T* absl_nullable end) noexcept {\n  ABSL_HARDENING_ASSERT(begin <= end);\n  return Span<T>(begin, static_cast<size_t>(end - begin));\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename C>\nconstexpr auto MakeSpan(C& c) noexcept  // NOLINT(runtime/references)\n    -> std::enable_if_t<span_internal::IsView<C>::value,\n                        decltype(absl::MakeSpan(span_internal::GetData(c),\n                                                c.size()))> {\n  return MakeSpan(span_internal::GetData(c), c.size());\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename C>\nconstexpr auto MakeSpan(\n    C& c ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/references)\n    -> std::enable_if_t<!span_internal::IsView<C>::value,\n                        decltype(absl::MakeSpan(span_internal::GetData(c),\n                                                c.size()))> {\n  return MakeSpan(span_internal::GetData(c), c.size());\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename T, size_t N>\nconstexpr Span<T> MakeSpan(\n    T (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) noexcept {\n  return Span<T>(array, N);\n}\n\n// MakeConstSpan()\n//\n// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically,\n// but always returning a `Span<const T>`.\n//\n// Examples:\n//\n//   void ProcessInts(absl::Span<const int> some_ints);\n//\n//   // Call with a pointer and size.\n//   int array[3] = { 0, 0, 0 };\n//   ProcessInts(absl::MakeConstSpan(&array[0], 3));\n//\n//   // Call with a [begin, end) pair.\n//   ProcessInts(absl::MakeConstSpan(&array[0], &array[3]));\n//\n//   // Call directly with an array.\n//   ProcessInts(absl::MakeConstSpan(array));\n//\n//   // Call with a contiguous container.\n//   std::vector<int> some_ints = ...;\n//   ProcessInts(absl::MakeConstSpan(some_ints));\n//   ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));\n//\ntemplate <int&... ExplicitArgumentBarrier, typename T>\nconstexpr Span<const T> MakeConstSpan(\n    T* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND, size_t size) noexcept {\n  return Span<const T>(ptr, size);\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename T>\nSpan<const T> MakeConstSpan(T* absl_nullable begin\n                                ABSL_ATTRIBUTE_LIFETIME_BOUND,\n                            T* absl_nullable end) noexcept {\n  ABSL_HARDENING_ASSERT(begin <= end);\n  return Span<const T>(begin, end - begin);\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename C>\nconstexpr auto MakeConstSpan(const C& c) noexcept\n    -> std::enable_if_t<span_internal::IsView<C>::value,\n                        decltype(MakeSpan(c))> {\n  return MakeSpan(c);\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename C>\nconstexpr auto MakeConstSpan(const C& c ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept\n    -> std::enable_if_t<!span_internal::IsView<C>::value,\n                        decltype(MakeSpan(c))> {\n  return MakeSpan(c);\n}\n\ntemplate <int&... ExplicitArgumentBarrier, typename T, size_t N>\nconstexpr Span<const T> MakeConstSpan(\n    const T (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) noexcept {\n  return Span<const T>(array, N);\n}\nABSL_NAMESPACE_END\n}  // namespace absl\n#endif  // ABSL_TYPES_SPAN_H_\n"
  },
  {
    "path": "absl/types/span_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/types/span.h\"\n\n#include <array>\n#include <initializer_list>\n#include <numeric>\n#include <stdexcept>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n#include \"absl/base/attributes.h\"\n#include \"absl/base/config.h\"\n#include \"absl/base/internal/exception_testing.h\"\n#include \"absl/base/options.h\"\n#include \"absl/container/fixed_array.h\"\n#include \"absl/container/inlined_vector.h\"\n#include \"absl/hash/hash.h\"\n#include \"absl/hash/hash_testing.h\"\n#include \"absl/meta/type_traits.h\"\n#include \"absl/strings/str_cat.h\"\n\nnamespace {\n\nstatic_assert(!absl::type_traits_internal::IsOwner<absl::Span<int>>::value &&\n                  absl::type_traits_internal::IsView<absl::Span<int>>::value,\n              \"Span is a view, not an owner\");\n\nusing S = absl::Span<int>;\n\nstatic_assert(\n    std::is_trivially_destructible_v<S> && std::is_trivially_copyable_v<S> &&\n        std::is_trivially_assignable_v<S, S&> &&\n        std::is_trivially_copy_assignable_v<S> &&\n        std::is_trivially_move_assignable_v<S> &&\n        std::is_trivially_assignable_v<S, const S&&> &&\n        std::is_trivially_constructible_v<S, S&> &&\n        std::is_trivially_copy_constructible_v<S> &&\n        std::is_trivially_move_constructible_v<S> &&\n        std::is_trivially_constructible_v<S, const S&&>,\n    \"Span should be trivial in everything except default-constructibility\");\n\nMATCHER_P(DataIs, data,\n          absl::StrCat(\"data() \", negation ? \"isn't \" : \"is \",\n                       testing::PrintToString(data))) {\n  return arg.data() == data;\n}\n\ntemplate <typename T>\nauto SpanIs(T data, size_t size)\n    -> decltype(testing::AllOf(DataIs(data), testing::SizeIs(size))) {\n  return testing::AllOf(DataIs(data), testing::SizeIs(size));\n}\n\ntemplate <typename Container>\nauto SpanIs(const Container& c) -> decltype(SpanIs(c.data(), c.size())) {\n  return SpanIs(c.data(), c.size());\n}\n\nstd::vector<int> MakeRamp(int len, int offset = 0) {\n  std::vector<int> v(len);\n  std::iota(v.begin(), v.end(), offset);\n  return v;\n}\n\nTEST(IntSpan, EmptyCtors) {\n  absl::Span<int> s;\n  EXPECT_THAT(s, SpanIs(nullptr, 0));\n}\n\nTEST(IntSpan, PtrLenCtor) {\n  int a[] = {1, 2, 3};\n  absl::Span<int> s(&a[0], 2);\n  EXPECT_THAT(s, SpanIs(a, 2));\n}\n\nTEST(IntSpan, ArrayCtor) {\n  int a[] = {1, 2, 3};\n  absl::Span<int> s(a);\n  EXPECT_THAT(s, SpanIs(a, 3));\n\n  EXPECT_TRUE((std::is_constructible<absl::Span<const int>, int[3]>::value));\n  EXPECT_TRUE(\n      (std::is_constructible<absl::Span<const int>, const int[3]>::value));\n  EXPECT_FALSE((std::is_constructible<absl::Span<int>, const int[3]>::value));\n  EXPECT_TRUE((std::is_convertible<int[3], absl::Span<const int>>::value));\n  EXPECT_TRUE(\n      (std::is_convertible<const int[3], absl::Span<const int>>::value));\n}\n\ntemplate <typename T>\nvoid TakesGenericSpan(absl::Span<T>) {}\n\nTEST(IntSpan, ContainerCtor) {\n  std::vector<int> empty;\n  absl::Span<int> s_empty(empty);\n  EXPECT_THAT(s_empty, SpanIs(empty));\n\n  std::vector<int> filled{1, 2, 3};\n  absl::Span<int> s_filled(filled);\n  EXPECT_THAT(s_filled, SpanIs(filled));\n\n  absl::Span<int> s_from_span(filled);\n  EXPECT_THAT(s_from_span, SpanIs(s_filled));\n\n  absl::Span<const int> const_filled = filled;\n  EXPECT_THAT(const_filled, SpanIs(filled));\n\n  absl::Span<const int> const_from_span = s_filled;\n  EXPECT_THAT(const_from_span, SpanIs(s_filled));\n\n  EXPECT_TRUE(\n      (std::is_convertible<std::vector<int>&, absl::Span<const int>>::value));\n  EXPECT_TRUE(\n      (std::is_convertible<absl::Span<int>&, absl::Span<const int>>::value));\n\n  TakesGenericSpan(absl::Span<int>(filled));\n}\n\n// A struct supplying shallow data() const.\nstruct ContainerWithShallowConstData {\n  std::vector<int> storage;\n  int* data() const { return const_cast<int*>(storage.data()); }\n  int size() const { return storage.size(); }\n};\n\nTEST(IntSpan, ShallowConstness) {\n  const ContainerWithShallowConstData c{MakeRamp(20)};\n  absl::Span<int> s(\n      c);  // We should be able to do this even though data() is const.\n  s[0] = -1;\n  EXPECT_EQ(c.storage[0], -1);\n}\n\nTEST(CharSpan, StringCtor) {\n  std::string empty = \"\";\n  absl::Span<char> s_empty(empty);\n  EXPECT_THAT(s_empty, SpanIs(empty));\n\n  std::string abc = \"abc\";\n  absl::Span<char> s_abc(abc);\n  EXPECT_THAT(s_abc, SpanIs(abc));\n\n  absl::Span<const char> s_const_abc = abc;\n  EXPECT_THAT(s_const_abc, SpanIs(abc));\n\n  EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value));\n  EXPECT_FALSE(\n      (std::is_constructible<absl::Span<const int>, std::string>::value));\n  EXPECT_TRUE(\n      (std::is_convertible<std::string, absl::Span<const char>>::value));\n}\n\nTEST(IntSpan, FromConstPointer) {\n  EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>,\n                                     std::vector<int*>>::value));\n  EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>,\n                                     std::vector<const int*>>::value));\n  EXPECT_FALSE((\n      std::is_constructible<absl::Span<const int*>, std::vector<int*>>::value));\n  EXPECT_FALSE((\n      std::is_constructible<absl::Span<int*>, std::vector<const int*>>::value));\n}\n\nstruct TypeWithMisleadingData {\n  int& data() { return i; }\n  int size() { return 1; }\n  int i;\n};\n\nstruct TypeWithMisleadingSize {\n  int* data() { return &i; }\n  const char* size() { return \"1\"; }\n  int i;\n};\n\nTEST(IntSpan, EvilTypes) {\n  EXPECT_FALSE(\n      (std::is_constructible<absl::Span<int>, TypeWithMisleadingData&>::value));\n  EXPECT_FALSE(\n      (std::is_constructible<absl::Span<int>, TypeWithMisleadingSize&>::value));\n}\n\nstruct Base {\n  int* data() { return &i; }\n  int size() { return 1; }\n  int i;\n};\nstruct Derived : Base {};\n\nTEST(IntSpan, SpanOfDerived) {\n  EXPECT_TRUE((std::is_constructible<absl::Span<int>, Base&>::value));\n  EXPECT_TRUE((std::is_constructible<absl::Span<int>, Derived&>::value));\n  EXPECT_FALSE(\n      (std::is_constructible<absl::Span<Base>, std::vector<Derived>>::value));\n}\n\nvoid TestInitializerList(absl::Span<const int> s, const std::vector<int>& v) {\n  EXPECT_TRUE(std::equal(s.begin(), s.end(), v.begin(), v.end()));\n}\n\nTEST(ConstIntSpan, InitializerListConversion) {\n  TestInitializerList({}, {});\n  TestInitializerList({1}, {1});\n  TestInitializerList({1, 2, 3}, {1, 2, 3});\n\n  EXPECT_FALSE((std::is_constructible<absl::Span<int>,\n                                      std::initializer_list<int>>::value));\n  EXPECT_FALSE((\n      std::is_convertible<absl::Span<int>, std::initializer_list<int>>::value));\n}\n\nTEST(IntSpan, Data) {\n  int i;\n  absl::Span<int> s(&i, 1);\n  EXPECT_EQ(&i, s.data());\n}\n\nTEST(IntSpan, SizeLengthEmpty) {\n  absl::Span<int> empty;\n  EXPECT_EQ(empty.size(), 0);\n  EXPECT_TRUE(empty.empty());\n  EXPECT_EQ(empty.size(), empty.length());\n\n  auto v = MakeRamp(10);\n  absl::Span<int> s(v);\n  EXPECT_EQ(s.size(), 10);\n  EXPECT_FALSE(s.empty());\n  EXPECT_EQ(s.size(), s.length());\n}\n\nTEST(IntSpan, ElementAccess) {\n  auto v = MakeRamp(10);\n  absl::Span<int> s(v);\n  for (int i = 0; i < s.size(); ++i) {\n    EXPECT_EQ(s[i], s.at(i));\n  }\n\n  EXPECT_EQ(s.front(), s[0]);\n  EXPECT_EQ(s.back(), s[9]);\n\n#if !defined(NDEBUG) || ABSL_OPTION_HARDENED\n  EXPECT_DEATH_IF_SUPPORTED(s[-1], \"\");\n  EXPECT_DEATH_IF_SUPPORTED(s[10], \"\");\n#endif\n}\n\nTEST(IntSpan, AtThrows) {\n  auto v = MakeRamp(10);\n  absl::Span<int> s(v);\n\n  EXPECT_EQ(s.at(9), 9);\n  ABSL_BASE_INTERNAL_EXPECT_FAIL(s.at(10), std::out_of_range,\n                                 \"failed bounds check\");\n}\n\nTEST(IntSpan, RemovePrefixAndSuffix) {\n  auto v = MakeRamp(20, 1);\n  absl::Span<int> s(v);\n  EXPECT_EQ(s.size(), 20);\n\n  s.remove_suffix(0);\n  s.remove_prefix(0);\n  EXPECT_EQ(s.size(), 20);\n\n  s.remove_prefix(1);\n  EXPECT_EQ(s.size(), 19);\n  EXPECT_EQ(s[0], 2);\n\n  s.remove_suffix(1);\n  EXPECT_EQ(s.size(), 18);\n  EXPECT_EQ(s.back(), 19);\n\n  s.remove_prefix(7);\n  EXPECT_EQ(s.size(), 11);\n  EXPECT_EQ(s[0], 9);\n\n  s.remove_suffix(11);\n  EXPECT_EQ(s.size(), 0);\n\n  EXPECT_EQ(v, MakeRamp(20, 1));\n\n#if !defined(NDEBUG) || ABSL_OPTION_HARDENED\n  absl::Span<int> prefix_death(v);\n  EXPECT_DEATH_IF_SUPPORTED(prefix_death.remove_prefix(21), \"\");\n  absl::Span<int> suffix_death(v);\n  EXPECT_DEATH_IF_SUPPORTED(suffix_death.remove_suffix(21), \"\");\n#endif\n}\n\nTEST(IntSpan, Subspan) {\n  std::vector<int> empty;\n  EXPECT_EQ(absl::MakeSpan(empty).subspan(), empty);\n  EXPECT_THAT(absl::MakeSpan(empty).subspan(0, 0), SpanIs(empty));\n  EXPECT_THAT(absl::MakeSpan(empty).subspan(0, absl::Span<const int>::npos),\n              SpanIs(empty));\n\n  auto ramp = MakeRamp(10);\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(), SpanIs(ramp));\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 10), SpanIs(ramp));\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, absl::Span<const int>::npos),\n              SpanIs(ramp));\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 3), SpanIs(ramp.data(), 3));\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(5, absl::Span<const int>::npos),\n              SpanIs(ramp.data() + 5, 5));\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(3, 3), SpanIs(ramp.data() + 3, 3));\n  EXPECT_THAT(absl::MakeSpan(ramp).subspan(10, 5), SpanIs(ramp.data() + 10, 0));\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n  EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range);\n#else\n  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), \"\");\n#endif\n}\n\nTEST(IntSpan, First) {\n  std::vector<int> empty;\n  EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty));\n\n  auto ramp = MakeRamp(10);\n  EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0));\n  EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp));\n  EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3));\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n  EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range);\n#else\n  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), \"\");\n#endif\n}\n\nTEST(IntSpan, Last) {\n  std::vector<int> empty;\n  EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty));\n\n  auto ramp = MakeRamp(10);\n  EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0));\n  EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp));\n  EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3));\n\n#ifdef ABSL_HAVE_EXCEPTIONS\n  EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range);\n#else\n  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), \"\");\n#endif\n}\n\nTEST(IntSpan, MakeSpanPtrLength) {\n  std::vector<int> empty;\n  auto s_empty = absl::MakeSpan(empty.data(), empty.size());\n  EXPECT_THAT(s_empty, SpanIs(empty));\n\n  std::array<int, 3> a{{1, 2, 3}};\n  auto s = absl::MakeSpan(a.data(), a.size());\n  EXPECT_THAT(s, SpanIs(a));\n\n  EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.size()), SpanIs(s_empty));\n  EXPECT_THAT(absl::MakeConstSpan(a.data(), a.size()), SpanIs(s));\n}\n\nTEST(IntSpan, MakeSpanTwoPtrs) {\n  std::vector<int> empty;\n  auto s_empty = absl::MakeSpan(empty.data(), empty.data());\n  EXPECT_THAT(s_empty, SpanIs(empty));\n\n  std::vector<int> v{1, 2, 3};\n  auto s = absl::MakeSpan(v.data(), v.data() + 1);\n  EXPECT_THAT(s, SpanIs(v.data(), 1));\n\n  EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.data()), SpanIs(s_empty));\n  EXPECT_THAT(absl::MakeConstSpan(v.data(), v.data() + 1), SpanIs(s));\n}\n\nTEST(IntSpan, MakeSpanContainer) {\n  std::vector<int> empty;\n  auto s_empty = absl::MakeSpan(empty);\n  EXPECT_THAT(s_empty, SpanIs(empty));\n\n  std::vector<int> v{1, 2, 3};\n  auto s = absl::MakeSpan(v);\n  EXPECT_THAT(s, SpanIs(v));\n\n  EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty));\n  EXPECT_THAT(absl::MakeConstSpan(v), SpanIs(s));\n\n  EXPECT_THAT(absl::MakeSpan(s), SpanIs(s));\n  EXPECT_THAT(absl::MakeConstSpan(s), SpanIs(s));\n}\n\nTEST(CharSpan, MakeSpanString) {\n  std::string empty = \"\";\n  auto s_empty = absl::MakeSpan(empty);\n  EXPECT_THAT(s_empty, SpanIs(empty));\n\n  std::string str = \"abc\";\n  auto s_str = absl::MakeSpan(str);\n  EXPECT_THAT(s_str, SpanIs(str));\n\n  EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty));\n  EXPECT_THAT(absl::MakeConstSpan(str), SpanIs(s_str));\n}\n\nTEST(IntSpan, MakeSpanArray) {\n  int a[] = {1, 2, 3};\n  auto s = absl::MakeSpan(a);\n  EXPECT_THAT(s, SpanIs(a, 3));\n\n  const int ca[] = {1, 2, 3};\n  auto s_ca = absl::MakeSpan(ca);\n  EXPECT_THAT(s_ca, SpanIs(ca, 3));\n\n  EXPECT_THAT(absl::MakeConstSpan(a), SpanIs(s));\n  EXPECT_THAT(absl::MakeConstSpan(ca), SpanIs(s_ca));\n}\n\n// Compile-asserts that the argument has the expected decayed type.\ntemplate <typename Expected, typename T>\nvoid CheckType(const T& /* value */) {\n  testing::StaticAssertTypeEq<Expected, T>();\n}\n\nTEST(IntSpan, MakeSpanTypes) {\n  std::vector<int> vec;\n  const std::vector<int> cvec;\n  int a[1];\n  const int ca[] = {1};\n  int* ip = a;\n  const int* cip = ca;\n  std::string s = \"\";\n  const std::string cs = \"\";\n  CheckType<absl::Span<int>>(absl::MakeSpan(vec));\n  CheckType<absl::Span<const int>>(absl::MakeSpan(cvec));\n  CheckType<absl::Span<int>>(absl::MakeSpan(ip, ip + 1));\n  CheckType<absl::Span<int>>(absl::MakeSpan(ip, 1));\n  CheckType<absl::Span<const int>>(absl::MakeSpan(cip, cip + 1));\n  CheckType<absl::Span<const int>>(absl::MakeSpan(cip, 1));\n  CheckType<absl::Span<int>>(absl::MakeSpan(a));\n  CheckType<absl::Span<int>>(absl::MakeSpan(a, a + 1));\n  CheckType<absl::Span<int>>(absl::MakeSpan(a, 1));\n  CheckType<absl::Span<const int>>(absl::MakeSpan(ca));\n  CheckType<absl::Span<const int>>(absl::MakeSpan(ca, ca + 1));\n  CheckType<absl::Span<const int>>(absl::MakeSpan(ca, 1));\n  CheckType<absl::Span<char>>(absl::MakeSpan(s));\n  CheckType<absl::Span<const char>>(absl::MakeSpan(cs));\n}\n\nTEST(ConstIntSpan, MakeConstSpanTypes) {\n  std::vector<int> vec;\n  const std::vector<int> cvec;\n  int array[1];\n  const int carray[] = {0};\n  int* ptr = array;\n  const int* cptr = carray;\n  std::string s = \"\";\n  std::string cs = \"\";\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(vec));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(cvec));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, ptr + 1));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, 1));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, cptr + 1));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, 1));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(array));\n  CheckType<absl::Span<const int>>(absl::MakeConstSpan(carray));\n  CheckType<absl::Span<const char>>(absl::MakeConstSpan(s));\n  CheckType<absl::Span<const char>>(absl::MakeConstSpan(cs));\n}\n\nTEST(IntSpan, Equality) {\n  const int arr1[] = {1, 2, 3, 4, 5};\n  int arr2[] = {1, 2, 3, 4, 5};\n  std::vector<int> vec1(std::begin(arr1), std::end(arr1));\n  std::vector<int> vec2 = vec1;\n  std::vector<int> other_vec = {2, 4, 6, 8, 10};\n  // These two slices are from different vectors, but have the same size and\n  // have the same elements (right now).  They should compare equal. Test both\n  // == and !=.\n  const absl::Span<const int> from1 = vec1;\n  const absl::Span<const int> from2 = vec2;\n  EXPECT_EQ(from1, from1);\n  EXPECT_FALSE(from1 != from1);\n  EXPECT_EQ(from1, from2);\n  EXPECT_FALSE(from1 != from2);\n\n  // These two slices have different underlying vector values. They should be\n  // considered not equal. Test both == and !=.\n  const absl::Span<const int> from_other = other_vec;\n  EXPECT_NE(from1, from_other);\n  EXPECT_FALSE(from1 == from_other);\n\n  // Comparison between a vector and its slice should be equal. And vice-versa.\n  // This ensures implicit conversion to Span works on both sides of ==.\n  EXPECT_EQ(vec1, from1);\n  EXPECT_FALSE(vec1 != from1);\n  EXPECT_EQ(from1, vec1);\n  EXPECT_FALSE(from1 != vec1);\n\n  // This verifies that absl::Span<T> can be compared freely with\n  // absl::Span<const T>.\n  const absl::Span<int> mutable_from1(vec1);\n  const absl::Span<int> mutable_from2(vec2);\n  EXPECT_EQ(from1, mutable_from1);\n  EXPECT_EQ(mutable_from1, from1);\n  EXPECT_EQ(mutable_from1, mutable_from2);\n  EXPECT_EQ(mutable_from2, mutable_from1);\n\n  // Comparison between a vector and its slice should be equal for mutable\n  // Spans as well.\n  EXPECT_EQ(vec1, mutable_from1);\n  EXPECT_FALSE(vec1 != mutable_from1);\n  EXPECT_EQ(mutable_from1, vec1);\n  EXPECT_FALSE(mutable_from1 != vec1);\n\n  // Comparison between convertible-to-Span-of-const and Span-of-mutable. Arrays\n  // are used because they're the only value type which converts to a\n  // Span-of-mutable. EXPECT_TRUE is used instead of EXPECT_EQ to avoid\n  // array-to-pointer decay.\n  EXPECT_TRUE(arr1 == mutable_from1);\n  EXPECT_FALSE(arr1 != mutable_from1);\n  EXPECT_TRUE(mutable_from1 == arr1);\n  EXPECT_FALSE(mutable_from1 != arr1);\n\n  // Comparison between convertible-to-Span-of-mutable and Span-of-const\n  EXPECT_TRUE(arr2 == from1);\n  EXPECT_FALSE(arr2 != from1);\n  EXPECT_TRUE(from1 == arr2);\n  EXPECT_FALSE(from1 != arr2);\n\n  // With a different size, the array slices should not be equal.\n  EXPECT_NE(from1, absl::Span<const int>(from1).subspan(0, from1.size() - 1));\n\n  // With different contents, the array slices should not be equal.\n  ++vec2.back();\n  EXPECT_NE(from1, from2);\n}\n\nclass IntSpanOrderComparisonTest : public testing::Test {\n public:\n  IntSpanOrderComparisonTest()\n      : arr_before_{1, 2, 3},\n        arr_after_{1, 2, 4},\n        carr_after_{1, 2, 4},\n        vec_before_(std::begin(arr_before_), std::end(arr_before_)),\n        vec_after_(std::begin(arr_after_), std::end(arr_after_)),\n        before_(vec_before_),\n        after_(vec_after_),\n        cbefore_(vec_before_),\n        cafter_(vec_after_) {}\n\n protected:\n  int arr_before_[3], arr_after_[3];\n  const int carr_after_[3];\n  std::vector<int> vec_before_, vec_after_;\n  absl::Span<int> before_, after_;\n  absl::Span<const int> cbefore_, cafter_;\n};\n\nTEST_F(IntSpanOrderComparisonTest, CompareSpans) {\n  EXPECT_TRUE(cbefore_ < cafter_);\n  EXPECT_TRUE(cbefore_ <= cafter_);\n  EXPECT_TRUE(cafter_ > cbefore_);\n  EXPECT_TRUE(cafter_ >= cbefore_);\n\n  EXPECT_FALSE(cbefore_ > cafter_);\n  EXPECT_FALSE(cafter_ < cbefore_);\n\n  EXPECT_TRUE(before_ < after_);\n  EXPECT_TRUE(before_ <= after_);\n  EXPECT_TRUE(after_ > before_);\n  EXPECT_TRUE(after_ >= before_);\n\n  EXPECT_FALSE(before_ > after_);\n  EXPECT_FALSE(after_ < before_);\n\n  EXPECT_TRUE(cbefore_ < after_);\n  EXPECT_TRUE(cbefore_ <= after_);\n  EXPECT_TRUE(after_ > cbefore_);\n  EXPECT_TRUE(after_ >= cbefore_);\n\n  EXPECT_FALSE(cbefore_ > after_);\n  EXPECT_FALSE(after_ < cbefore_);\n}\n\nTEST_F(IntSpanOrderComparisonTest, SpanOfConstAndContainer) {\n  EXPECT_TRUE(cbefore_ < vec_after_);\n  EXPECT_TRUE(cbefore_ <= vec_after_);\n  EXPECT_TRUE(vec_after_ > cbefore_);\n  EXPECT_TRUE(vec_after_ >= cbefore_);\n\n  EXPECT_FALSE(cbefore_ > vec_after_);\n  EXPECT_FALSE(vec_after_ < cbefore_);\n\n  EXPECT_TRUE(arr_before_ < cafter_);\n  EXPECT_TRUE(arr_before_ <= cafter_);\n  EXPECT_TRUE(cafter_ > arr_before_);\n  EXPECT_TRUE(cafter_ >= arr_before_);\n\n  EXPECT_FALSE(arr_before_ > cafter_);\n  EXPECT_FALSE(cafter_ < arr_before_);\n}\n\nTEST_F(IntSpanOrderComparisonTest, SpanOfMutableAndContainer) {\n  EXPECT_TRUE(vec_before_ < after_);\n  EXPECT_TRUE(vec_before_ <= after_);\n  EXPECT_TRUE(after_ > vec_before_);\n  EXPECT_TRUE(after_ >= vec_before_);\n\n  EXPECT_FALSE(vec_before_ > after_);\n  EXPECT_FALSE(after_ < vec_before_);\n\n  EXPECT_TRUE(before_ < carr_after_);\n  EXPECT_TRUE(before_ <= carr_after_);\n  EXPECT_TRUE(carr_after_ > before_);\n  EXPECT_TRUE(carr_after_ >= before_);\n\n  EXPECT_FALSE(before_ > carr_after_);\n  EXPECT_FALSE(carr_after_ < before_);\n}\n\nTEST_F(IntSpanOrderComparisonTest, EqualSpans) {\n  EXPECT_FALSE(before_ < before_);\n  EXPECT_TRUE(before_ <= before_);\n  EXPECT_FALSE(before_ > before_);\n  EXPECT_TRUE(before_ >= before_);\n}\n\nTEST_F(IntSpanOrderComparisonTest, Subspans) {\n  auto subspan = before_.subspan(0, 1);\n  EXPECT_TRUE(subspan < before_);\n  EXPECT_TRUE(subspan <= before_);\n  EXPECT_TRUE(before_ > subspan);\n  EXPECT_TRUE(before_ >= subspan);\n\n  EXPECT_FALSE(subspan > before_);\n  EXPECT_FALSE(before_ < subspan);\n}\n\nTEST_F(IntSpanOrderComparisonTest, EmptySpans) {\n  absl::Span<int> empty;\n  EXPECT_FALSE(empty < empty);\n  EXPECT_TRUE(empty <= empty);\n  EXPECT_FALSE(empty > empty);\n  EXPECT_TRUE(empty >= empty);\n\n  EXPECT_TRUE(empty < before_);\n  EXPECT_TRUE(empty <= before_);\n  EXPECT_TRUE(before_ > empty);\n  EXPECT_TRUE(before_ >= empty);\n\n  EXPECT_FALSE(empty > before_);\n  EXPECT_FALSE(before_ < empty);\n}\n\nTEST(IntSpan, ExposesContainerTypesAndConsts) {\n  absl::Span<int> slice;\n  CheckType<absl::Span<int>::iterator>(slice.begin());\n  EXPECT_TRUE((std::is_convertible<decltype(slice.begin()),\n                                   absl::Span<int>::const_iterator>::value));\n  CheckType<absl::Span<int>::const_iterator>(slice.cbegin());\n  EXPECT_TRUE((std::is_convertible<decltype(slice.end()),\n                                   absl::Span<int>::const_iterator>::value));\n  CheckType<absl::Span<int>::const_iterator>(slice.cend());\n  CheckType<absl::Span<int>::reverse_iterator>(slice.rend());\n  EXPECT_TRUE(\n      (std::is_convertible<decltype(slice.rend()),\n                           absl::Span<int>::const_reverse_iterator>::value));\n  CheckType<absl::Span<int>::const_reverse_iterator>(slice.crend());\n  testing::StaticAssertTypeEq<int, absl::Span<int>::value_type>();\n  testing::StaticAssertTypeEq<int, absl::Span<const int>::value_type>();\n  testing::StaticAssertTypeEq<int, absl::Span<int>::element_type>();\n  testing::StaticAssertTypeEq<const int, absl::Span<const int>::element_type>();\n  testing::StaticAssertTypeEq<int*, absl::Span<int>::pointer>();\n  testing::StaticAssertTypeEq<const int*, absl::Span<const int>::pointer>();\n  testing::StaticAssertTypeEq<int&, absl::Span<int>::reference>();\n  testing::StaticAssertTypeEq<const int&, absl::Span<const int>::reference>();\n  testing::StaticAssertTypeEq<const int&, absl::Span<int>::const_reference>();\n  testing::StaticAssertTypeEq<const int&,\n                              absl::Span<const int>::const_reference>();\n  EXPECT_EQ(static_cast<absl::Span<int>::size_type>(-1), absl::Span<int>::npos);\n}\n\nTEST(IntSpan, IteratorsAndReferences) {\n  auto accept_pointer = [](int*) {};\n  auto accept_reference = [](int&) {};\n  auto accept_iterator = [](absl::Span<int>::iterator) {};\n  auto accept_const_iterator = [](absl::Span<int>::const_iterator) {};\n  auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {};\n  auto accept_const_reverse_iterator =\n      [](absl::Span<int>::const_reverse_iterator) {};\n\n  int a[1];\n  absl::Span<int> s = a;\n\n  accept_pointer(s.data());\n  accept_iterator(s.begin());\n  accept_const_iterator(s.begin());\n  accept_const_iterator(s.cbegin());\n  accept_iterator(s.end());\n  accept_const_iterator(s.end());\n  accept_const_iterator(s.cend());\n  accept_reverse_iterator(s.rbegin());\n  accept_const_reverse_iterator(s.rbegin());\n  accept_const_reverse_iterator(s.crbegin());\n  accept_reverse_iterator(s.rend());\n  accept_const_reverse_iterator(s.rend());\n  accept_const_reverse_iterator(s.crend());\n\n  accept_reference(s[0]);\n  accept_reference(s.at(0));\n  accept_reference(s.front());\n  accept_reference(s.back());\n}\n\nTEST(IntSpan, IteratorsAndReferences_Const) {\n  auto accept_pointer = [](int*) {};\n  auto accept_reference = [](int&) {};\n  auto accept_iterator = [](absl::Span<int>::iterator) {};\n  auto accept_const_iterator = [](absl::Span<int>::const_iterator) {};\n  auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {};\n  auto accept_const_reverse_iterator =\n      [](absl::Span<int>::const_reverse_iterator) {};\n\n  int a[1];\n  const absl::Span<int> s = a;\n\n  accept_pointer(s.data());\n  accept_iterator(s.begin());\n  accept_const_iterator(s.begin());\n  accept_const_iterator(s.cbegin());\n  accept_iterator(s.end());\n  accept_const_iterator(s.end());\n  accept_const_iterator(s.cend());\n  accept_reverse_iterator(s.rbegin());\n  accept_const_reverse_iterator(s.rbegin());\n  accept_const_reverse_iterator(s.crbegin());\n  accept_reverse_iterator(s.rend());\n  accept_const_reverse_iterator(s.rend());\n  accept_const_reverse_iterator(s.crend());\n\n  accept_reference(s[0]);\n  accept_reference(s.at(0));\n  accept_reference(s.front());\n  accept_reference(s.back());\n}\n\nTEST(IntSpan, NoexceptTest) {\n  int a[] = {1, 2, 3};\n  std::vector<int> v;\n  EXPECT_TRUE(noexcept(absl::Span<const int>()));\n  EXPECT_TRUE(noexcept(absl::Span<const int>(a, 2)));\n  EXPECT_TRUE(noexcept(absl::Span<const int>(a)));\n  EXPECT_TRUE(noexcept(absl::Span<const int>(v)));\n  EXPECT_TRUE(noexcept(absl::Span<int>(v)));\n  EXPECT_TRUE(noexcept(absl::Span<const int>({1, 2, 3})));\n  EXPECT_TRUE(noexcept(absl::MakeSpan(v)));\n  EXPECT_TRUE(noexcept(absl::MakeSpan(a)));\n  EXPECT_TRUE(noexcept(absl::MakeSpan(a, 2)));\n  EXPECT_TRUE(noexcept(absl::MakeSpan(a, a + 1)));\n  EXPECT_TRUE(noexcept(absl::MakeConstSpan(v)));\n  EXPECT_TRUE(noexcept(absl::MakeConstSpan(a)));\n  EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, 2)));\n  EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, a + 1)));\n\n  absl::Span<int> s(v);\n  EXPECT_TRUE(noexcept(s.data()));\n  EXPECT_TRUE(noexcept(s.size()));\n  EXPECT_TRUE(noexcept(s.length()));\n  EXPECT_TRUE(noexcept(s.empty()));\n  EXPECT_TRUE(noexcept(s[0]));\n  EXPECT_TRUE(noexcept(s.front()));\n  EXPECT_TRUE(noexcept(s.back()));\n  EXPECT_TRUE(noexcept(s.begin()));\n  EXPECT_TRUE(noexcept(s.cbegin()));\n  EXPECT_TRUE(noexcept(s.end()));\n  EXPECT_TRUE(noexcept(s.cend()));\n  EXPECT_TRUE(noexcept(s.rbegin()));\n  EXPECT_TRUE(noexcept(s.crbegin()));\n  EXPECT_TRUE(noexcept(s.rend()));\n  EXPECT_TRUE(noexcept(s.crend()));\n  EXPECT_TRUE(noexcept(s.remove_prefix(0)));\n  EXPECT_TRUE(noexcept(s.remove_suffix(0)));\n}\n\n// ConstexprTester exercises expressions in a constexpr context. Simply placing\n// the expression in a constexpr function is not enough, as some compilers will\n// simply compile the constexpr function as runtime code. Using template\n// parameters forces compile-time execution.\ntemplate <int i>\nstruct ConstexprTester {};\n\n#define ABSL_TEST_CONSTEXPR(expr)                                          \\\n  do {                                                                     \\\n    ABSL_ATTRIBUTE_UNUSED ConstexprTester<(static_cast<void>(expr), 1)> t; \\\n  } while (0)\n\nstruct ContainerWithConstexprMethods {\n  constexpr int size() const { return 1; }\n  constexpr const int* data() const { return &i; }\n  const int i;\n};\n\nTEST(ConstIntSpan, ConstexprTest) {\n  static constexpr int a[] = {1, 2, 3};\n  static constexpr int sized_arr[2] = {1, 2};\n  static constexpr ContainerWithConstexprMethods c{1};\n  ABSL_TEST_CONSTEXPR(absl::Span<const int>());\n  ABSL_TEST_CONSTEXPR(absl::Span<const int>(a, 2));\n  ABSL_TEST_CONSTEXPR(absl::Span<const int>(sized_arr));\n  ABSL_TEST_CONSTEXPR(absl::Span<const int>(c));\n  ABSL_TEST_CONSTEXPR(absl::MakeSpan(&a[0], 1));\n  ABSL_TEST_CONSTEXPR(absl::MakeSpan(c));\n  ABSL_TEST_CONSTEXPR(absl::MakeSpan(a));\n  ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(&a[0], 1));\n  ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(c));\n  ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(a));\n\n  constexpr absl::Span<const int> span = c;\n  ABSL_TEST_CONSTEXPR(span.data());\n  ABSL_TEST_CONSTEXPR(span.size());\n  ABSL_TEST_CONSTEXPR(span.length());\n  ABSL_TEST_CONSTEXPR(span.empty());\n  ABSL_TEST_CONSTEXPR(span.begin());\n  ABSL_TEST_CONSTEXPR(span.cbegin());\n  ABSL_TEST_CONSTEXPR(span.subspan(0, 0));\n  ABSL_TEST_CONSTEXPR(span.first(1));\n  ABSL_TEST_CONSTEXPR(span.last(1));\n  ABSL_TEST_CONSTEXPR(span[0]);\n}\n\n#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \\\n    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\nTEST(ConstIntSpan, ConstexprRelOpsTest) {\n  static constexpr int lhs_data[] = {1, 2, 3};\n  static constexpr int rhs_data[] = {1, 2, 3};\n\n  constexpr absl::Span<const int> lhs = absl::MakeConstSpan(lhs_data, 3);\n  constexpr absl::Span<const int> rhs = absl::MakeConstSpan(rhs_data, 3);\n\n  ABSL_TEST_CONSTEXPR(lhs_data == rhs);\n  ABSL_TEST_CONSTEXPR(lhs_data != rhs);\n  ABSL_TEST_CONSTEXPR(lhs_data < rhs);\n  ABSL_TEST_CONSTEXPR(lhs_data <= rhs);\n  ABSL_TEST_CONSTEXPR(lhs_data > rhs);\n  ABSL_TEST_CONSTEXPR(lhs_data >= rhs);\n\n  ABSL_TEST_CONSTEXPR(lhs == rhs);\n  ABSL_TEST_CONSTEXPR(lhs != rhs);\n  ABSL_TEST_CONSTEXPR(lhs < rhs);\n  ABSL_TEST_CONSTEXPR(lhs <= rhs);\n  ABSL_TEST_CONSTEXPR(lhs > rhs);\n  ABSL_TEST_CONSTEXPR(lhs >= rhs);\n\n  ABSL_TEST_CONSTEXPR(lhs == rhs_data);\n  ABSL_TEST_CONSTEXPR(lhs != rhs_data);\n  ABSL_TEST_CONSTEXPR(lhs < rhs_data);\n  ABSL_TEST_CONSTEXPR(lhs <= rhs_data);\n  ABSL_TEST_CONSTEXPR(lhs > rhs_data);\n  ABSL_TEST_CONSTEXPR(lhs >= rhs_data);\n}\n\n#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&\n        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n\nstruct BigStruct {\n  char bytes[10000];\n};\n\nTEST(Span, SpanSize) {\n  EXPECT_LE(sizeof(absl::Span<int>), 2 * sizeof(void*));\n  EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*));\n}\n\nTEST(Span, Hash) {\n  int array[] = {1, 2, 3, 4};\n  int array2[] = {1, 2, 3};\n  using T = absl::Span<const int>;\n  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(\n      {// Empties\n       T(), T(nullptr, 0), T(array, 0), T(array2, 0),\n       // Different array with same value\n       T(array, 3), T(array2), T({1, 2, 3}),\n       // Same array, but different length\n       T(array, 1), T(array, 2),\n       // Same length, but different array\n       T(array + 1, 2), T(array + 2, 2)}));\n}\n\n// std::vector is implicitly convertible to absl::Span.\n// There are real life cases where clients rely on this consistency in order to\n// implement heterogeneous lookup.\nTEST(Span, HashConsistentWithVectorLike) {\n  EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})),\n            absl::HashOf(std::vector<int>{1, 2, 3}));\n  EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})),\n            absl::HashOf(absl::InlinedVector<int, 2>{1, 2, 3}));\n  EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})),\n            absl::HashOf(absl::FixedArray<int>{1, 2, 3}));\n}\n\n}  // namespace\n"
  },
  {
    "path": "absl/types/variant.h",
    "content": "// Copyright 2018 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// -----------------------------------------------------------------------------\n// variant.h\n// -----------------------------------------------------------------------------\n//\n// Historical note: Abseil once provided an implementation of `absl::variant`\n// as a polyfill for `std::variant` prior to C++17. Now that C++17 is required,\n// `absl::variant` is an alias for `std::variant`.\n\n#ifndef ABSL_TYPES_VARIANT_H_\n#define ABSL_TYPES_VARIANT_H_\n\n#include <variant>\n\n#include \"absl/base/config.h\"\n#include \"absl/utility/utility.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\nusing std::bad_variant_access;\nusing std::get;\nusing std::get_if;\nusing std::holds_alternative;\nusing std::monostate;\nusing std::variant;\nusing std::variant_alternative;\nusing std::variant_alternative_t;\nusing std::variant_npos;\nusing std::variant_size;\nusing std::variant_size_v;\nusing std::visit;\n\nnamespace variant_internal {\n// Helper visitor for converting a variant<Ts...>` into another type (mostly\n// variant) that can be constructed from any type.\ntemplate <typename To>\nstruct ConversionVisitor {\n  template <typename T>\n  To operator()(T&& v) const {\n    return To(std::forward<T>(v));\n  }\n};\n}  // namespace variant_internal\n\n// ConvertVariantTo()\n//\n// Helper functions to convert an `absl::variant` to a variant of another set of\n// types, provided that the alternative type of the new variant type can be\n// converted from any type in the source variant.\n//\n// Example:\n//\n//   absl::variant<name1, name2, float> InternalReq(const Req&);\n//\n//   // name1 and name2 are convertible to name\n//   absl::variant<name, float> ExternalReq(const Req& req) {\n//     return absl::ConvertVariantTo<absl::variant<name, float>>(\n//              InternalReq(req));\n//   }\ntemplate <typename To, typename Variant>\nTo ConvertVariantTo(Variant&& variant) {\n  return absl::visit(variant_internal::ConversionVisitor<To>{},\n                     std::forward<Variant>(variant));\n}\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_TYPES_VARIANT_H_\n"
  },
  {
    "path": "absl/types/variant_test.cc",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#include \"absl/types/variant.h\"\n\n#include <memory>\n#include <string>\n#include <variant>\n\n#include \"gmock/gmock.h\"\n#include \"gtest/gtest.h\"\n\nnamespace absl {\nnamespace {\n\nusing ::testing::DoubleEq;\nusing ::testing::Pointee;\nusing ::testing::VariantWith;\n\nstruct Convertible2;\nstruct Convertible1 {\n  Convertible1() {}\n  Convertible1(const Convertible1&) {}\n  Convertible1& operator=(const Convertible1&) { return *this; }\n\n  // implicit conversion from Convertible2\n  Convertible1(const Convertible2&) {}  // NOLINT(runtime/explicit)\n};\n\nstruct Convertible2 {\n  Convertible2() {}\n  Convertible2(const Convertible2&) {}\n  Convertible2& operator=(const Convertible2&) { return *this; }\n\n  // implicit conversion from Convertible1\n  Convertible2(const Convertible1&) {}  // NOLINT(runtime/explicit)\n};\n\nTEST(VariantTest, TestRvalueConversion) {\n  std::variant<Convertible1, Convertible2> v(\n      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(\n          (std::variant<Convertible2, Convertible1>(Convertible1()))));\n  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));\n\n  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(\n      std::variant<Convertible2, Convertible1>(Convertible2()));\n  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));\n}\n\nTEST(VariantTest, TestLvalueConversion) {\n  std::variant<Convertible2, Convertible1> source((Convertible1()));\n  std::variant<Convertible1, Convertible2> v(\n      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source));\n  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));\n\n  source = Convertible2();\n  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source);\n  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));\n}\n\nTEST(VariantTest, TestMoveConversion) {\n  using Variant = std::variant<std::unique_ptr<const int>,\n                               std::unique_ptr<const std::string>>;\n  using OtherVariant =\n      std::variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;\n\n  Variant var(\n      ConvertVariantTo<Variant>(OtherVariant{std::make_unique<int>(0)}));\n  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const int>>(var));\n  ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);\n  EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));\n\n  var = ConvertVariantTo<Variant>(\n      OtherVariant(std::make_unique<std::string>(\"foo\")));\n  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));\n  EXPECT_EQ(\"foo\", *absl::get<std::unique_ptr<const std::string>>(var));\n}\n\nTEST(VariantTest, DoesNotMoveFromLvalues) {\n  // We use shared_ptr here because it's both copyable and movable, and\n  // a moved-from shared_ptr is guaranteed to be null, so we can detect\n  // whether moving or copying has occurred.\n  using Variant = std::variant<std::shared_ptr<const int>,\n                               std::shared_ptr<const std::string>>;\n  using OtherVariant =\n      std::variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;\n\n  Variant v1(std::make_shared<const int>(0));\n\n  // Test copy constructor\n  Variant v2(v1);\n  EXPECT_EQ(absl::get<std::shared_ptr<const int>>(v1),\n            absl::get<std::shared_ptr<const int>>(v2));\n\n  // Test copy-assignment operator\n  v1 = std::make_shared<const std::string>(\"foo\");\n  v2 = v1;\n  EXPECT_EQ(absl::get<std::shared_ptr<const std::string>>(v1),\n            absl::get<std::shared_ptr<const std::string>>(v2));\n\n  // Test converting copy constructor\n  OtherVariant other(std::make_shared<int>(0));\n  Variant v3(ConvertVariantTo<Variant>(other));\n  EXPECT_EQ(absl::get<std::shared_ptr<int>>(other),\n            absl::get<std::shared_ptr<const int>>(v3));\n\n  other = std::make_shared<std::string>(\"foo\");\n  v3 = ConvertVariantTo<Variant>(other);\n  EXPECT_EQ(absl::get<std::shared_ptr<std::string>>(other),\n            absl::get<std::shared_ptr<const std::string>>(v3));\n}\n\nTEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {\n  variant<Convertible1, Convertible2> v(\n      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(\n          (std::variant<Convertible2, Convertible1>(Convertible1()))));\n  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));\n\n  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(\n      std::variant<Convertible2, Convertible1>(Convertible2()));\n  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));\n}\n\nTEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {\n  variant<Convertible2, Convertible1> source((Convertible1()));\n  variant<Convertible1, Convertible2> v(\n      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source));\n  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));\n\n  source = Convertible2();\n  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source);\n  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));\n}\n\nTEST(VariantTest, TestMoveConversionViaConvertVariantTo) {\n  using Variant = std::variant<std::unique_ptr<const int>,\n                               std::unique_ptr<const std::string>>;\n  using OtherVariant =\n      std::variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;\n\n  Variant var(\n      ConvertVariantTo<Variant>(OtherVariant{std::make_unique<int>(3)}));\n  EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),\n              Pointee(Pointee(3)));\n\n  var = ConvertVariantTo<Variant>(\n      OtherVariant(std::make_unique<std::string>(\"foo\")));\n  EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),\n              Pointee(Pointee(std::string(\"foo\"))));\n}\n\n}  // namespace\n}  // namespace absl\n"
  },
  {
    "path": "absl/utility/BUILD.bazel",
    "content": "#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nload(\"@rules_cc//cc:cc_library.bzl\", \"cc_library\")\nload(\n    \"//absl:copts/configure_copts.bzl\",\n    \"ABSL_DEFAULT_COPTS\",\n    \"ABSL_DEFAULT_LINKOPTS\",\n)\n\npackage(\n    default_visibility = [\"//visibility:public\"],\n    features = [\n        \"header_modules\",\n        \"layering_check\",\n        \"parse_headers\",\n    ],\n)\n\nlicenses([\"notice\"])\n\ncc_library(\n    name = \"utility\",\n    hdrs = [\n        \"utility.h\",\n    ],\n    copts = ABSL_DEFAULT_COPTS,\n    linkopts = ABSL_DEFAULT_LINKOPTS,\n    deps = [\n        \"//absl/base:config\",\n        \"//absl/meta:type_traits\",\n    ],\n)\n"
  },
  {
    "path": "absl/utility/CMakeLists.txt",
    "content": "#\n# Copyright 2017 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nabsl_cc_library(\n  NAME\n    utility\n  HDRS\n    \"utility.h\"\n  COPTS\n    ${ABSL_DEFAULT_COPTS}\n  DEPS\n    absl::config\n    absl::type_traits\n  PUBLIC\n)\n"
  },
  {
    "path": "absl/utility/utility.h",
    "content": "// Copyright 2017 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef ABSL_UTILITY_UTILITY_H_\n#define ABSL_UTILITY_UTILITY_H_\n\n#include <cstddef>\n#include <cstdlib>\n#include <tuple>\n#include <utility>\n\n#include \"absl/base/config.h\"\n\n// TODO(b/290784225): Include what you use cleanup required.\n#include \"absl/meta/type_traits.h\"\n\nnamespace absl {\nABSL_NAMESPACE_BEGIN\n\n// Historical note: Abseil once provided implementations of these\n// abstractions for platforms that had not yet provided them. Those\n// platforms are no longer supported. New code should simply use the\n// the ones from std directly.\nusing std::apply;\nusing std::exchange;\nusing std::forward;\nusing std::in_place;\nusing std::in_place_index;\nusing std::in_place_index_t;\nusing std::in_place_t;\nusing std::in_place_type;\nusing std::in_place_type_t;\nusing std::index_sequence;\nusing std::index_sequence_for;\nusing std::integer_sequence;\nusing std::make_from_tuple;\nusing std::make_index_sequence;\nusing std::make_integer_sequence;\nusing std::move;\n\n#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L\n// Backfill for std::nontype_t. An instance of this class can be provided as a\n// disambiguation tag to `absl::function_ref` to pass the address of a known\n// callable at compile time.\n// Requires C++20 due to `auto` template parameter.\ntemplate <auto>\nstruct nontype_t {\n  explicit nontype_t() = default;\n};\ntemplate <auto V>\nconstexpr nontype_t<V> nontype{};\n#endif\n\nABSL_NAMESPACE_END\n}  // namespace absl\n\n#endif  // ABSL_UTILITY_UTILITY_H_\n"
  },
  {
    "path": "ci/absl_alternate_options.h",
    "content": "// Copyright 2019 The Abseil Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//    https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Alternate options.h file, used in continuous integration testing to exercise\n// option settings not used by default.\n\n// SKIP_ABSL_INLINE_NAMESPACE_CHECK\n\n#ifndef ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_\n#define ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_\n\n#define ABSL_OPTION_USE_STD_SOURCE_LOCATION 0\n#define ABSL_OPTION_USE_STD_ORDERING 0\n#define ABSL_OPTION_USE_INLINE_NAMESPACE 1\n#define ABSL_OPTION_INLINE_NAMESPACE_NAME ns\n#define ABSL_OPTION_HARDENED 1\n\n#endif  // ABSL_CI_ABSL_ALTERNATE_OPTIONS_H_\n"
  },
  {
    "path": "ci/cmake_common.sh",
    "content": "# Copyright 2020 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# The commit of GoogleTest to be used in the CMake tests in this directory.\n# Keep this in sync with the commit in the MODULE.bazel file.\nreadonly ABSL_GOOGLETEST_VERSION=\"1.17.0\"\n\nABSL_GOOGLETEST_DOWNLOAD_URL=\"https://github.com/google/googletest/releases/download/v${ABSL_GOOGLETEST_VERSION}/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\"\n"
  },
  {
    "path": "ci/cmake_install_test.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${LINK_TYPE:-} ]]; then\n  LINK_TYPE=\"STATIC DYNAMIC\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/cmake_common.sh\"\n\n# Avoid depending on GitHub by looking for a cached copy of GoogleTest.\nif [[ -r \"${KOKORO_GFILE_DIR:-}/distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\" ]]; then\n  ABSL_GOOGLETEST_DOWNLOAD_URL=\"file:///distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\"\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}\n\n# Verify that everything works with the standard \"cmake && make && make install\"\n# without building tests or requiring GoogleTest.\ntime docker run \\\n    --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp-ro,readonly \\\n    --tmpfs=/buildfs:exec \\\n    --workdir=/buildfs \\\n    --rm \\\n    ${DOCKER_EXTRA_ARGS:-} \\\n    ${DOCKER_CONTAINER} \\\n    /bin/bash -c \"cmake /abseil-cpp-ro && make -j$(nproc) && make install\"\n\n# Verify that a more complicated project works.\nfor link_type in ${LINK_TYPE}; do\n  time docker run \\\n    --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp-ro,readonly \\\n    --tmpfs=/buildfs:exec \\\n    --tmpfs=/abseil-cpp:exec \\\n    --workdir=/abseil-cpp \\\n    --cap-add=SYS_PTRACE \\\n    -e \"ABSL_GOOGLETEST_VERSION=${ABSL_GOOGLETEST_VERSION}\" \\\n    -e \"ABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL}\" \\\n    -e \"LINK_TYPE=${link_type}\" \\\n    --rm \\\n    ${DOCKER_EXTRA_ARGS:-} \\\n    ${DOCKER_CONTAINER} \\\n    /bin/bash -c \"cp -r /abseil-cpp-ro/* . && CMake/install_test_project/test.sh\"\ndone\n"
  },
  {
    "path": "ci/linux_arm_clang-latest_libcxx_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17 c++20\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_ARM_CLANG_LATEST_CONTAINER}\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /opt/llvm/bin/clang -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  BAZEL_EXTRA_ARGS=\"--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\n# See https://bazel.build/external/vendor and the Dockerfile for\n# an explaination of how this works.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/opt/llvm/bin/clang\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \\\n        --env=\"BAZEL_LINKOPTS=-L/opt/llvm/lib/aarch64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/lib/aarch64-unknown-linux-gnu\" \\\n        --env=\"CPLUS_INCLUDE_PATH=/opt/llvm/include/c++/v1:/opt/llvm/include/aarch64-unknown-linux-gnu/c++/v1/\" \\\n        --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp-ro,readonly \\\n        --tmpfs=/abseil-cpp \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n          cp -r /abseil-cpp-ro/* /abseil-cpp/\n          if [ -n \\\"${ALTERNATE_OPTIONS:-}\\\" ]; then\n            cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1\n          fi\n          /usr/local/bin/bazel test ... \\\n            --compilation_mode=\\\"${compilation_mode}\\\" \\\n            --copt=\\\"${exceptions_mode}\\\" \\\n            --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n            --copt=-Werror \\\n            --define=\\\"absl=1\\\" \\\n            --features=external_include_paths \\\n            --keep_going \\\n            --per_file_copt=external/.*@-w \\\n            --show_timestamps \\\n            --test_env=\\\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\\\" \\\n            --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n            --test_output=errors \\\n            --test_tag_filters=-benchmark \\\n            ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_clang-latest_libcxx_asan_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17 c++20 c++23\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /opt/llvm/bin/clang -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  BAZEL_EXTRA_ARGS=\"--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Avoid depending on external sites like GitHub by checking --distdir for\n# external dependencies first.\n# https://docs.bazel.build/versions/master/guide.html#distdir\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d \"${KOKORO_GFILE_DIR}/distdir\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks\nreadonly UBSAN_CHECKS=\"float-divide-by-zero,nullability,undefined\"\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/opt/llvm/bin/clang\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \\\n        --env=\"BAZEL_LINKOPTS=-L/opt/llvm/lib/x86_64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/lib/x86_64-unknown-linux-gnu\" \\\n        --env=\"CPLUS_INCLUDE_PATH=/opt/llvm/include/c++/v1:/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1/\" \\\n        --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp,readonly \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n        /usr/local/bin/bazel test ... \\\n          --compilation_mode=\\\"${compilation_mode}\\\" \\\n          --copt=\\\"${exceptions_mode}\\\" \\\n          --copt=\\\"-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG\\\" \\\n          --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n          --copt=\\\"-fsanitize=address\\\" \\\n          --copt=\\\"-fsanitize=${UBSAN_CHECKS}\\\" \\\n          --copt=\\\"-fno-sanitize-recover=${UBSAN_CHECKS}\\\" \\\n          --copt=\\\"-fno-sanitize-blacklist\\\" \\\n          --copt=-Werror \\\n          --define=\\\"absl=1\\\" \\\n          --enable_bzlmod=true \\\n          --features=external_include_paths \\\n          --keep_going \\\n          --linkopt=\\\"-fsanitize=address\\\" \\\n          --linkopt=\\\"-fsanitize-link-c++-runtime\\\" \\\n          --per_file_copt=external/.*@-w \\\n          --show_timestamps \\\n          --test_env=\\\"ASAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer\\\" \\\n          --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n          --test_env=\\\"UBSAN_OPTIONS=print_stacktrace=1\\\" \\\n          --test_env=\\\"UBSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer\\\" \\\n          --test_output=errors \\\n          --test_tag_filters=\\\"-benchmark,-noasan\\\" \\\n          ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_clang-latest_libcxx_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17 c++20 c++23\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /opt/llvm/bin/clang -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  BAZEL_EXTRA_ARGS=\"--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\n# See https://bazel.build/external/vendor and the Dockerfile for\n# an explaination of how this works.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/opt/llvm/bin/clang\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \\\n        --env=\"BAZEL_LINKOPTS=-L/opt/llvm/lib/x86_64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/lib/x86_64-unknown-linux-gnu\" \\\n        --env=\"CPLUS_INCLUDE_PATH=/opt/llvm/include/c++/v1:/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1/\" \\\n        --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp-ro,readonly \\\n        --tmpfs=/abseil-cpp \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n          cp -r /abseil-cpp-ro/* /abseil-cpp/\n          if [ -n \\\"${ALTERNATE_OPTIONS:-}\\\" ]; then\n            cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1\n          fi\n          /usr/local/bin/bazel test ... \\\n            --compilation_mode=\\\"${compilation_mode}\\\" \\\n            --copt=\\\"${exceptions_mode}\\\" \\\n            --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n            --copt=-Werror \\\n            --define=\\\"absl=1\\\" \\\n            --enable_bzlmod=true \\\n            --features=external_include_paths \\\n            --keep_going \\\n            --per_file_copt=external/.*@-w \\\n            --show_timestamps \\\n            --test_env=\\\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\\\" \\\n            --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n            --test_output=errors \\\n            --test_tag_filters=-benchmark \\\n            ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_clang-latest_libcxx_tsan_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17 c++20 c++23\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /opt/llvm/bin/clang -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  BAZEL_EXTRA_ARGS=\"--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\n# See https://bazel.build/external/vendor and the Dockerfile for\n# an explaination of how this works.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/opt/llvm/bin/clang\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \\\n        --env=\"BAZEL_LINKOPTS=-L/opt/llvm-tsan/lib/x86_64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm-tsan/lib/x86_64-unknown-linux-gnu\" \\\n        --env=\"CPLUS_INCLUDE_PATH=/opt/llvm-tsan/include/c++/v1:/opt/llvm-tsan/include/x86_64-unknown-linux-gnu/c++/v1/\" \\\n        --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp,readonly \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n        /usr/local/bin/bazel test ... \\\n          --build_tag_filters=\\\"-notsan\\\" \\\n          --compilation_mode=\\\"${compilation_mode}\\\" \\\n          --copt=\\\"${exceptions_mode}\\\" \\\n          --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n          --copt=\\\"-fsanitize=thread\\\" \\\n          --copt=\\\"-fno-sanitize-blacklist\\\" \\\n          --copt=-Werror \\\n          --define=\\\"absl=1\\\" \\\n          --enable_bzlmod=true \\\n          --features=external_include_paths \\\n          --keep_going \\\n          --linkopt=\\\"-fsanitize=thread\\\" \\\n          --per_file_copt=external/.*@-w \\\n          --show_timestamps \\\n          --test_env=\\\"TSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer\\\" \\\n          --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n          --test_output=errors \\\n          --test_tag_filters=\\\"-benchmark,-notsan\\\" \\\n          ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_clang-latest_libstdcxx_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17 c++20 c++23\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /usr/local/bin/gcc -v\ndocker run \"${DOCKER_CONTAINER}\" /opt/llvm/bin/clang -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  BAZEL_EXTRA_ARGS=\"--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\n# See https://bazel.build/external/vendor and the Dockerfile for\n# an explaination of how this works.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/opt/llvm/bin/clang\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}\" \\\n        --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp,readonly \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n        /usr/local/bin/bazel test ... \\\n          --compilation_mode=\\\"${compilation_mode}\\\" \\\n          --copt=\\\"--gcc-toolchain=/usr/local\\\" \\\n          --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n          --copt=\\\"${exceptions_mode}\\\" \\\n          --copt=\\\"-march=haswell\\\" \\\n          --copt=-Werror \\\n          --define=\\\"absl=1\\\" \\\n          --enable_bzlmod=true \\\n          --features=external_include_paths \\\n          --keep_going \\\n          --linkopt=\\\"--gcc-toolchain=/usr/local\\\" \\\n          --per_file_copt=external/.*@-w \\\n          --show_timestamps \\\n          --test_env=\\\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\\\" \\\n          --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n          --test_output=errors \\\n          --test_tag_filters=-benchmark \\\n          ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_docker_containers.sh",
    "content": "# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# The file contains Docker container identifiers currently used by test scripts.\n# Test scripts should source this file to get the identifiers.\n\nreadonly LINUX_ALPINE_CONTAINER=\"gcr.io/google.com/absl-177019/alpine:20230612\"\nreadonly LINUX_CLANG_LATEST_CONTAINER=\"gcr.io/google.com/absl-177019/linux_hybrid-latest:20260131\"\nreadonly LINUX_ARM_CLANG_LATEST_CONTAINER=\"gcr.io/google.com/absl-177019/linux_arm_hybrid-latest:20260131\"\nreadonly LINUX_GCC_LATEST_CONTAINER=\"gcr.io/google.com/absl-177019/linux_hybrid-latest:20260131\"\nreadonly LINUX_GCC_FLOOR_CONTAINER=\"gcr.io/google.com/absl-177019/linux_hybrid-latest:20260131\"\n"
  },
  {
    "path": "ci/linux_gcc-floor_libstdcxx_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2020 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=\"${LINUX_GCC_FLOOR_CONTAINER}\"\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /opt/gcc-9/bin/gcc -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  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:-}\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\n# See https://bazel.build/external/vendor and the Dockerfile for\n# an explaination of how this works.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/opt/gcc-9/bin/gcc\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}\" \\\n        --env=\"BAZEL_LINKOPTS=-L/opt/gcc-9/lib64:-Wl,-rpath=/opt/gcc-9/lib64\" \\\n        --volume=\"${ABSEIL_ROOT}:/abseil-cpp:ro\" \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n        /usr/local/bin/bazel test ... \\\n          --compilation_mode=\\\"${compilation_mode}\\\" \\\n          --copt=\\\"${exceptions_mode}\\\" \\\n          --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n          --copt=-Werror \\\n          --define=\\\"absl=1\\\" \\\n          --features=external_include_paths \\\n          --keep_going \\\n          --per_file_copt=external/.*@-w \\\n          --show_timestamps \\\n          --test_env=\\\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\\\" \\\n          --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n          --test_output=errors \\\n          --test_tag_filters=-benchmark \\\n          ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_gcc-latest_libstdcxx_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script that can be invoked to test abseil-cpp in a hermetic environment\n# using a Docker image on Linux. You must have Docker installed to use this\n# script.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nif [[ -z ${STD:-} ]]; then\n  STD=\"c++17 c++20 c++23\"\nfi\n\nif [[ -z ${COMPILATION_MODE:-} ]]; then\n  COMPILATION_MODE=\"fastbuild opt\"\nfi\n\nif [[ -z ${EXCEPTIONS_MODE:-} ]]; then\n  EXCEPTIONS_MODE=\"-fno-exceptions -fexceptions\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}\n\n# Print information about the environment.\ndocker run \"${DOCKER_CONTAINER}\" /usr/bin/fastfetch -c ci\ndocker run \"${DOCKER_CONTAINER}\" /usr/local/bin/gcc -v\ndocker run \"${DOCKER_CONTAINER}\" cat /root/cached_bazel_versions\n\n# USE_BAZEL_CACHE=1 only works on Kokoro.\n# Without access to the credentials this won't work.\nif [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}\"\n  # Bazel doesn't track changes to tools outside of the workspace\n  # (e.g. /usr/bin/gcc), so by appending the docker container to the\n  # remote_http_cache url, we make changes to the container part of\n  # the cache key. Hashing the key is to make it shorter and url-safe.\n  container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)\n  BAZEL_EXTRA_ARGS=\"--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\n# See https://bazel.build/external/vendor and the Dockerfile for\n# an explaination of how this works.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\nfor std in ${STD}; do\n  for compilation_mode in ${COMPILATION_MODE}; do\n    for exceptions_mode in ${EXCEPTIONS_MODE}; do\n      echo \"--------------------------------------------------------------------\"\n      time docker run \\\n        --env=\"USE_BAZEL_VERSION=9.0.0\" \\\n        --env=\"CC=/usr/local/bin/gcc\" \\\n        --env=\"BAZEL_CXXOPTS=-std=${std}\" \\\n        --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp-ro,readonly \\\n        --tmpfs=/abseil-cpp \\\n        --workdir=/abseil-cpp \\\n        --cap-add=SYS_PTRACE \\\n        --rm \\\n        ${DOCKER_EXTRA_ARGS:-} \\\n        ${DOCKER_CONTAINER} \\\n        /bin/bash --login -c \"\n          cp -r /abseil-cpp-ro/* /abseil-cpp/\n          if [ -n \\\"${ALTERNATE_OPTIONS:-}\\\" ]; then\n            cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1\n          fi\n          /usr/local/bin/bazel test ... \\\n            --compilation_mode=\\\"${compilation_mode}\\\" \\\n            --copt=\\\"${exceptions_mode}\\\" \\\n            --copt=\\\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\\\" \\\n            --copt=-Werror \\\n            --define=\\\"absl=1\\\" \\\n            --enable_bzlmod=true \\\n            --features=external_include_paths \\\n            --keep_going \\\n            --per_file_copt=external/.*@-w \\\n            --show_timestamps \\\n            --test_env=\\\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\\\" \\\n            --test_env=\\\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\\\" \\\n            --test_output=errors \\\n            --test_tag_filters=-benchmark \\\n            ${BAZEL_EXTRA_ARGS:-}\"\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_gcc-latest_libstdcxx_cmake.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/cmake_common.sh\"\n\n# Avoid depending on GitHub by looking for a cached copy of GoogleTest.\nif [[ -r \"${KOKORO_GFILE_DIR:-}/distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\" ]]; then\n  ABSL_GOOGLETEST_DOWNLOAD_URL=\"file:///distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\"\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}\"\nfi\n\nif [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then\n  ABSL_CMAKE_CXX_STANDARDS=\"17 20\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then\n  ABSL_CMAKE_BUILD_TYPES=\"Debug Release\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then\n  ABSL_CMAKE_BUILD_SHARED=\"OFF ON\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS:-} ]]; then\n  ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS=\"OFF ON\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}\n\nfor std in ${ABSL_CMAKE_CXX_STANDARDS}; do\n  for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do\n    for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do\n      if [[ $build_shared == \"OFF\" ]]; then\n        monolithic_shared_options=\"OFF\"\n      else\n        monolithic_shared_options=\"$ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS\"\n      fi\n\n      for monolithic_shared in $monolithic_shared_options; do\n        time docker run \\\n          --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp,readonly \\\n          --tmpfs=/buildfs:exec \\\n          --workdir=/buildfs \\\n          --cap-add=SYS_PTRACE \\\n          --rm \\\n          -e CFLAGS=\"-Werror\" \\\n          -e CXXFLAGS=\"-Werror\" \\\n          ${DOCKER_EXTRA_ARGS:-} \\\n          \"${DOCKER_CONTAINER}\" \\\n          /bin/bash -c \"\n            cmake /abseil-cpp \\\n              -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \\\n              -DBUILD_SHARED_LIBS=${build_shared} \\\n              -DABSL_BUILD_TESTING=ON \\\n              -DCMAKE_BUILD_TYPE=${compilation_mode} \\\n              -DCMAKE_CXX_STANDARD=${std} \\\n              -DABSL_BUILD_MONOLITHIC_SHARED_LIBS=${monolithic_shared} \\\n              -DCMAKE_MODULE_LINKER_FLAGS=\\\"-Wl,--no-undefined\\\" && \\\n            make -j$(nproc) && \\\n            TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo \\\n            ctest -j$(nproc) --output-on-failure\"\n        done\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/linux_gcc_alpine_cmake.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -euox pipefail\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/cmake_common.sh\"\n\n# Avoid depending on GitHub by looking for a cached copy of GoogleTest.\nif [[ -r \"${KOKORO_GFILE_DIR:-}/distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\" ]]; then\n  ABSL_GOOGLETEST_DOWNLOAD_URL=\"file:///distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\"\n  DOCKER_EXTRA_ARGS=\"--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}\"\nfi\n\nif [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then\n  ABSL_CMAKE_CXX_STANDARDS=\"17\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then\n  ABSL_CMAKE_BUILD_TYPES=\"Debug Release\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then\n  ABSL_CMAKE_BUILD_SHARED=\"OFF ON\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS:-} ]]; then\n  ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS=\"OFF ON\"\nfi\n\nsource \"${ABSEIL_ROOT}/ci/linux_docker_containers.sh\"\nreadonly DOCKER_CONTAINER=${LINUX_ALPINE_CONTAINER}\n\nfor std in ${ABSL_CMAKE_CXX_STANDARDS}; do\n  for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do\n    for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do\n      if [[ $build_shared == \"OFF\" ]]; then\n        monolithic_shared_options=\"OFF\"\n      else\n        monolithic_shared_options=\"$ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS\"\n      fi\n\n      for monolithic_shared in $monolithic_shared_options; do\n        time docker run \\\n          --mount type=bind,source=\"${ABSEIL_ROOT}\",target=/abseil-cpp,readonly \\\n          --tmpfs=/buildfs:exec \\\n          --workdir=/buildfs \\\n          --cap-add=SYS_PTRACE \\\n          --rm \\\n          -e CFLAGS=\"-Werror\" \\\n          -e CXXFLAGS=\"-Werror\" \\\n          ${DOCKER_EXTRA_ARGS:-} \\\n          \"${DOCKER_CONTAINER}\" \\\n          /bin/sh -c \"\n            cmake /abseil-cpp \\\n              -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \\\n              -DBUILD_SHARED_LIBS=${build_shared} \\\n              -DABSL_BUILD_TESTING=ON \\\n              -DCMAKE_BUILD_TYPE=${compilation_mode} \\\n              -DCMAKE_CXX_STANDARD=${std} \\\n              -DABSL_BUILD_MONOLITHIC_SHARED_LIBS=${monolithic_shared} \\\n              -DCMAKE_MODULE_LINKER_FLAGS=\\\"-Wl,--no-undefined\\\" && \\\n            make -j$(nproc) && \\\n            TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo \\\n            ctest -j$(nproc) --output-on-failure\"\n        done\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/macos_xcode_bazel.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script is invoked on Kokoro to test Abseil on macOS.\n# It is not hermetic and may break when Kokoro is updated.\n\nset -euox pipefail\n\n# Use Xcode 26.2\nsudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(realpath $(dirname ${0})/..)\"\nfi\n\n# If we are running on Kokoro, check for a versioned Bazel binary.\nKOKORO_GFILE_BAZEL_BIN=\"bazel-9.0.0-darwin-x86_64\"\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then\n  BAZEL_BIN=\"${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}\"\n  chmod +x ${BAZEL_BIN}\nelse\n  BAZEL_BIN=\"bazel\"\nfi\n\n# Use Bazel Vendor mode to reduce reliance on external dependencies.\nif [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" ]]; then\n  tar -xf \"${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz\" -C \"${HOME}/\"\n  BAZEL_EXTRA_ARGS=\"--vendor_dir=${HOME}/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}\"\nfi\n\n# Print the compiler and Bazel versions.\necho \"---------------\"\ngcc -v\necho \"---------------\"\n${BAZEL_BIN} version\necho \"---------------\"\n\ncd ${ABSEIL_ROOT}\n\nif [[ -n \"${ALTERNATE_OPTIONS:-}\" ]]; then\n  cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1\nfi\n\n${BAZEL_BIN} test ... \\\n  --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \\\n  --copt=\"-Werror\" \\\n  --define=\"absl=1\" \\\n  --cxxopt=\"-std=c++17\" \\\n  --enable_bzlmod=true \\\n  --features=external_include_paths \\\n  --keep_going \\\n  --per_file_copt=external/.*@-w \\\n  --show_timestamps \\\n  --test_env=\"TZDIR=${ABSEIL_ROOT}/absl/time/internal/cctz/testdata/zoneinfo\" \\\n  --test_output=errors \\\n  --test_tag_filters=-benchmark \\\n  ${BAZEL_EXTRA_ARGS:-}\n"
  },
  {
    "path": "ci/macos_xcode_cmake.sh",
    "content": "#!/bin/bash\n#\n# Copyright 2019 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nset -euox pipefail\n\n# Use Xcode 26.2\nsudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer\n\nbrew install cmake\n\nexport CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)\nexport CTEST_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)\n\nif [[ -z ${ABSEIL_ROOT:-} ]]; then\n  ABSEIL_ROOT=\"$(dirname ${0})/..\"\nfi\nABSEIL_ROOT=$(realpath ${ABSEIL_ROOT})\n\nsource \"${ABSEIL_ROOT}/ci/cmake_common.sh\"\n\n# Avoid depending on GitHub by looking for a cached copy of GoogleTest.\nif [[ -r \"${KOKORO_GFILE_DIR:-}/distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\" ]]; then\n  ABSL_GOOGLETEST_DOWNLOAD_URL=\"${KOKORO_GFILE_DIR}/distdir/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then\n  ABSL_CMAKE_BUILD_TYPES=\"Debug\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then\n  ABSL_CMAKE_BUILD_SHARED=\"OFF ON\"\nfi\n\nif [[ -z ${ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS:-} ]]; then\n  ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS=\"OFF ON\"\nfi\n\nfor compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do\n  for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do\n    if [[ $build_shared == \"OFF\" ]]; then\n      monolithic_shared_options=\"OFF\"\n    else\n      monolithic_shared_options=\"$ABSL_CMAKE_BUILD_MONOLITHIC_SHARED_LIBS\"\n    fi\n\n    for monolithic_shared in $monolithic_shared_options; do\n      BUILD_DIR=$(mktemp -d ${compilation_mode}.XXXXXXXX)\n      cd ${BUILD_DIR}\n\n      # TODO(absl-team): Enable -Werror once all warnings are fixed.\n      time cmake ${ABSEIL_ROOT} \\\n        -GXcode \\\n        -DBUILD_SHARED_LIBS=${build_shared} \\\n        -DABSL_BUILD_TESTING=ON \\\n        -DCMAKE_BUILD_TYPE=${compilation_mode} \\\n        -DCMAKE_CXX_STANDARD=17 \\\n        -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" \\\n        -DABSL_BUILD_MONOLITHIC_SHARED_LIBS=${monolithic_shared} \\\n        -DABSL_GOOGLETEST_DOWNLOAD_URL=\"${ABSL_GOOGLETEST_DOWNLOAD_URL}\"\n      time cmake --build .\n      time TZDIR=${ABSEIL_ROOT}/absl/time/internal/cctz/testdata/zoneinfo \\\n        ctest -C ${compilation_mode} --output-on-failure\n    done\n  done\ndone\n"
  },
  {
    "path": "ci/windows_clangcl_bazel.bat",
    "content": ":: Copyright 2023 The Abseil Authors\n::\n:: Licensed under the Apache License, Version 2.0 (the \"License\");\n:: you may not use this file except in compliance with the License.\n:: You may obtain a copy of the License at\n::\n::     https://www.apache.org/licenses/LICENSE-2.0\n::\n:: Unless required by applicable law or agreed to in writing, software\n:: distributed under the License is distributed on an \"AS IS\" BASIS,\n:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n:: See the License for the specific language governing permissions and\n:: limitations under the License.\n\nSETLOCAL ENABLEDELAYEDEXPANSION\n\n:: Set LLVM directory.\nSET BAZEL_LLVM=C:\\Program Files\\LLVM\n\n:: Change directory to the root of the project.\nCD %~dp0\\..\nif %errorlevel% neq 0 EXIT /B 1\n\n:: Use Bazel Vendor mode to reduce reliance on external dependencies.\nIF EXIST \"%KOKORO_GFILE_DIR%\\distdir\\abseil-cpp_vendor.tar.gz\" (\n  tar --force-local -xf \"%KOKORO_GFILE_DIR%\\distdir\\abseil-cpp_vendor.tar.gz\" -C c:\\\n  SET VENDOR_FLAG=--vendor_dir=c:\\abseil-cpp_vendor\n) ELSE (\n  SET VENDOR_FLAG=\n)\n\n:: Set the standard version, [c++17|c++20|c++latest]\n:: https://msdn.microsoft.com/en-us/library/mt490614.aspx\n:: The default is c++17 if not set on command line.\nIF \"%STD%\"==\"\" SET STD=c++17\n\n:: Set the compilation_mode (fastbuild|opt|dbg)\n:: https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode\n:: The default is fastbuild\nIF \"%COMPILATION_MODE%\"==\"\" SET COMPILATION_MODE=fastbuild\n\n:: Copy the alternate option file, if specified.\nIF NOT \"%ALTERNATE_OPTIONS%\"==\"\" copy %ALTERNATE_OPTIONS% absl\\base\\options.h\n\n:: To upgrade Bazel, first download a new binary from\n:: https://github.com/bazelbuild/bazel/releases and copy it to\n:: /google/data/rw/teams/absl/kokoro/windows.\n::\n:: TODO(absl-team): Remove -Wno-microsoft-cast\n%KOKORO_GFILE_DIR%\\bazel-9.0.0-windows-x86_64.exe ^\n  test ... ^\n  --compilation_mode=%COMPILATION_MODE% ^\n  --compiler=clang-cl ^\n  --copt=/WX ^\n  --copt=-Wno-microsoft-cast ^\n  --cxxopt=/std:%STD% ^\n  --define=absl=1 ^\n  --enable_bzlmod=true ^\n  --extra_execution_platforms=//:x64_windows-clang-cl ^\n  --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl ^\n  --keep_going ^\n  --per_file_copt=external/.*@/w ^\n  --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" ^\n  --test_env=TZDIR=\"%CD%\\absl\\time\\internal\\cctz\\testdata\\zoneinfo\" ^\n  --test_output=errors ^\n  --test_tag_filters=-benchmark ^\n  %VENDOR_FLAG%\n\nif %errorlevel% neq 0 EXIT /B 1\nEXIT /B 0\n"
  },
  {
    "path": "ci/windows_msvc_bazel.bat",
    "content": ":: Copyright 2023 The Abseil Authors\n::\n:: Licensed under the Apache License, Version 2.0 (the \"License\");\n:: you may not use this file except in compliance with the License.\n:: You may obtain a copy of the License at\n::\n::     https://www.apache.org/licenses/LICENSE-2.0\n::\n:: Unless required by applicable law or agreed to in writing, software\n:: distributed under the License is distributed on an \"AS IS\" BASIS,\n:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n:: See the License for the specific language governing permissions and\n:: limitations under the License.\n\nSETLOCAL ENABLEDELAYEDEXPANSION\n\n:: Change directory to the root of the project.\nCD %~dp0\\..\nif %errorlevel% neq 0 EXIT /B 1\n\n:: Use Bazel Vendor mode to reduce reliance on external dependencies.\nIF EXIST \"%KOKORO_GFILE_DIR%\\distdir\\abseil-cpp_vendor.tar.gz\" (\n  tar --force-local -xf \"%KOKORO_GFILE_DIR%\\distdir\\abseil-cpp_vendor.tar.gz\" -C c:\\\n  SET VENDOR_FLAG=--vendor_dir=c:\\abseil-cpp_vendor\n) ELSE (\n  SET VENDOR_FLAG=\n)\n\n:: Set the standard version, [c++17|c++latest]\n:: https://msdn.microsoft.com/en-us/library/mt490614.aspx\n:: The default is c++17 if not set on command line.\nIF \"%STD%\"==\"\" SET STD=c++17\n\n:: Set the compilation_mode (fastbuild|opt|dbg)\n:: https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode\n:: The default is fastbuild\nIF \"%COMPILATION_MODE%\"==\"\" SET COMPILATION_MODE=fastbuild\n\n:: Copy the alternate option file, if specified.\nIF NOT \"%ALTERNATE_OPTIONS%\"==\"\" copy %ALTERNATE_OPTIONS% absl\\base\\options.h\n\n:: To upgrade Bazel, first download a new binary from\n:: https://github.com/bazelbuild/bazel/releases and copy it to\n:: /google/data/rw/teams/absl/kokoro/windows.\n\"%KOKORO_GFILE_DIR%\\bazel-9.0.0-windows-x86_64.exe\" ^\n  test ... ^\n  --compilation_mode=%COMPILATION_MODE% ^\n  --copt=/WX ^\n  --copt=/std:%STD% ^\n  --define=absl=1 ^\n  --enable_bzlmod=true ^\n  --keep_going ^\n  --per_file_copt=external/.*@/w ^\n  --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" ^\n  --test_env=TZDIR=\"%CD%\\absl\\time\\internal\\cctz\\testdata\\zoneinfo\" ^\n  --test_output=errors ^\n  --test_tag_filters=-benchmark ^\n  %VENDOR_FLAG%\n\nif %errorlevel% neq 0 EXIT /B 1\nEXIT /B 0\n"
  },
  {
    "path": "ci/windows_msvc_cmake.bat",
    "content": ":: Copyright 2023 The Abseil Authors\n::\n:: Licensed under the Apache License, Version 2.0 (the \"License\");\n:: you may not use this file except in compliance with the License.\n:: You may obtain a copy of the License at\n::\n::     https://www.apache.org/licenses/LICENSE-2.0\n::\n:: Unless required by applicable law or agreed to in writing, software\n:: distributed under the License is distributed on an \"AS IS\" BASIS,\n:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n:: See the License for the specific language governing permissions and\n:: limitations under the License.\n\nSETLOCAL ENABLEDELAYEDEXPANSION\n\n:: The version of GoogleTest to be used in the CMake tests in this directory.\n:: Keep this in sync with the version in the WORKSPACE file.\nSET ABSL_GOOGLETEST_VERSION=1.17.0\n\nIF EXIST %KOKORO_GFILE_DIR%\\distdir\\googletest-%ABSL_GOOGLETEST_VERSION%.tar.gz (\n  SET ABSL_GOOGLETEST_DOWNLOAD_URL=file://%KOKORO_GFILE_DIR%\\distdir\\googletest-%ABSL_GOOGLETEST_VERSION%.tar.gz\n) ELSE (\n  SET ABSL_GOOGLETEST_DOWNLOAD_URL=https://github.com/google/googletest/releases/download/v%ABSL_GOOGLETEST_VERSION%/googletest-%ABSL_GOOGLETEST_VERSION%.tar.gz\n)\n\n:: Replace '\\' with '/' in Windows paths for CMake.\n:: Note that this cannot go inside the IF block above, because BAT files are weird.\nSET ABSL_GOOGLETEST_DOWNLOAD_URL=%ABSL_GOOGLETEST_DOWNLOAD_URL:\\=/%\n\nIF EXIST \"C:\\Program Files\\CMake\\bin\\\" (\n  SET CMAKE_BIN=\"C:\\Program Files\\CMake\\bin\\cmake.exe\"\n  SET CTEST_BIN=\"C:\\Program Files\\CMake\\bin\\ctest.exe\"\n) ELSE (\n  SET CMAKE_BIN=\"cmake.exe\"\n  SET CTEST_BIN=\"ctest.exe\"\n)\n\nSET CTEST_OUTPUT_ON_FAILURE=1\nSET CMAKE_BUILD_PARALLEL_LEVEL=16\nSET CTEST_PARALLEL_LEVEL=16\n\n:: Change directory to the root of the project.\nCD %~dp0\\..\nif %errorlevel% neq 0 EXIT /B 1\n\nSET TZDIR=%CD%\\absl\\time\\internal\\cctz\\testdata\\zoneinfo\n\nMKDIR \"build\"\nCD \"build\"\n\nSET CXXFLAGS=\"/WX\"\n\n%CMAKE_BIN% ^\n  -DABSL_BUILD_TESTING=ON ^\n  -DABSL_GOOGLETEST_DOWNLOAD_URL=%ABSL_GOOGLETEST_DOWNLOAD_URL% ^\n  -DBUILD_SHARED_LIBS=%ABSL_CMAKE_BUILD_SHARED% ^\n  -DCMAKE_CXX_STANDARD=%ABSL_CMAKE_CXX_STANDARD% ^\n  -G \"%ABSL_CMAKE_GENERATOR%\" ^\n  ..\nIF %errorlevel% neq 0 EXIT /B 1\n\n%CMAKE_BIN% --build . --target ALL_BUILD --config %ABSL_CMAKE_BUILD_TYPE%\nIF %errorlevel% neq 0 EXIT /B 1\n\n%CTEST_BIN% -C %ABSL_CMAKE_BUILD_TYPE% -E \"absl_lifetime_test|absl_symbolize_test\"\nIF %errorlevel% neq 0 EXIT /B 1\n\nEXIT /B 0\n"
  },
  {
    "path": "conanfile.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n# Note: Conan is supported on a best-effort basis. Abseil doesn't use Conan\n# internally, so we won't know if it stops working. We may ask community\n# members to help us debug any problems that arise.\n\nfrom conans import ConanFile, CMake, tools\nfrom conans.errors import ConanInvalidConfiguration\nfrom conans.model.version import Version\n\n\nclass AbseilConan(ConanFile):\n    name = \"abseil\"\n    url = \"https://github.com/abseil/abseil-cpp\"\n    homepage = url\n    author = \"Abseil <abseil-io@googlegroups.com>\"\n    description = \"Abseil Common Libraries (C++) from Google\"\n    license = \"Apache-2.0\"\n    topics = (\"conan\", \"abseil\", \"abseil-cpp\", \"google\", \"common-libraries\")\n    exports = [\"LICENSE\"]\n    exports_sources = [\"CMakeLists.txt\", \"CMake/*\", \"absl/*\"]\n    generators = \"cmake\"\n    settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n    def configure(self):\n        if self.settings.os == \"Windows\" and \\\n           self.settings.compiler == \"Visual Studio\" and \\\n           Version(self.settings.compiler.version.value) < \"14\":\n            raise ConanInvalidConfiguration(\"Abseil does not support MSVC < 14\")\n\n    def build(self):\n        tools.replace_in_file(\"CMakeLists.txt\", \"project(absl LANGUAGES CXX)\", \"project(absl LANGUAGES CXX)\\ninclude(conanbuildinfo.cmake)\\nconan_basic_setup()\")\n        cmake = CMake(self)\n        cmake.definitions[\"BUILD_TESTING\"] = False\n        cmake.configure()\n        cmake.build()\n\n    def package(self):\n        self.copy(\"LICENSE\", dst=\"licenses\")\n        self.copy(\"*.h\", dst=\"include\", src=\".\")\n        self.copy(\"*.inc\", dst=\"include\", src=\".\")\n        self.copy(\"*.a\", dst=\"lib\", src=\".\", keep_path=False)\n        self.copy(\"*.lib\", dst=\"lib\", src=\".\", keep_path=False)\n\n    def package_info(self):\n        if self.settings.os == \"Linux\":\n            self.cpp_info.libs = [\"-Wl,--start-group\"]\n        self.cpp_info.libs.extend(tools.collect_libs(self))\n        if self.settings.os == \"Linux\":\n            self.cpp_info.libs.extend([\"-Wl,--end-group\", \"pthread\"])\n"
  },
  {
    "path": "create_lts.py",
    "content": "#!/usr/bin/env python3\n#\n# Copyright 2021 The Abseil Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"A script to do source transformations to create a new LTS release.\n\n   Usage: ./create_lts.py YYYYMMDD\n\"\"\"\n\nimport sys\n\n\ndef ReplaceStringsInFile(filename, replacement_dict):\n  \"\"\"Performs textual replacements in a file.\n\n  Rewrites filename with the keys in replacement_dict replaced with\n  their values. This function assumes the file can fit in memory.\n\n  Args:\n    filename: the filename to perform the replacement on\n    replacement_dict: a dictionary of key strings to be replaced with their\n      values\n\n  Raises:\n    Exception: A failure occurred\n  \"\"\"\n  f = open(filename, 'r')\n  content = f.read()\n  f.close()\n\n  for key, value in replacement_dict.items():\n    original = content\n    content = content.replace(key, value)\n    if content == original:\n      raise Exception('Failed to find {} in {}'.format(key, filename))\n\n  f = open(filename, 'w')\n  f.write(content)\n  f.close()\n\n\ndef StripContentBetweenTags(filename, strip_begin_tag, strip_end_tag):\n  \"\"\"Strip contents from a file.\n\n  Rewrites filename with by removing all content between\n  strip_begin_tag and strip_end_tag, including the tags themselves.\n\n  Args:\n    filename: the filename to perform the replacement on\n    strip_begin_tag: the start of the content to be removed\n    strip_end_tag: the end of the content to be removed\n\n  Raises:\n    Exception: A failure occurred\n  \"\"\"\n  f = open(filename, 'r')\n  content = f.read()\n  f.close()\n\n  while True:\n    begin = content.find(strip_begin_tag)\n    if begin == -1:\n      break\n    end = content.find(strip_end_tag, begin + len(strip_begin_tag))\n    if end == -1:\n      raise Exception('{}: imbalanced strip begin ({}) and '\n                      'end ({}) tags'.format(filename, strip_begin_tag,\n                                             strip_end_tag))\n    content = content.replace(content[begin:end + len(strip_end_tag)], '')\n\n  f = open(filename, 'w')\n  f.write(content)\n  f.close()\n\n\ndef main(argv):\n  if len(argv) != 2:\n    print('Usage: {} YYYYMMDD'.format(sys.argv[0], file=sys.stderr))\n    sys.exit(1)\n\n  datestamp = sys.argv[1]\n  if len(datestamp) != 8 or not datestamp.isdigit():\n    raise Exception(\n        'datestamp={} is not in the YYYYMMDD format'.format(datestamp))\n\n  # Replacement directives go here.\n  ReplaceStringsInFile(\n      'MODULE.bazel', {\n          'version = \"head\"':\n              'version = \"{}.0\"'.format(datestamp)\n      })\n  ReplaceStringsInFile(\n      'absl/base/config.h', {\n          '#undef ABSL_LTS_RELEASE_VERSION':\n              '#define ABSL_LTS_RELEASE_VERSION {}'.format(datestamp),\n          '#undef ABSL_LTS_RELEASE_PATCH_LEVEL':\n              '#define ABSL_LTS_RELEASE_PATCH_LEVEL 0'\n      })\n  ReplaceStringsInFile(\n      'absl/base/options.h', {\n          '#define ABSL_OPTION_USE_INLINE_NAMESPACE 0':\n              '#define ABSL_OPTION_USE_INLINE_NAMESPACE 1',\n          '#define ABSL_OPTION_INLINE_NAMESPACE_NAME head':\n              '#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_{}'.format(\n                  datestamp)\n      })\n  ReplaceStringsInFile(\n      'CMakeLists.txt',\n      {\n          'project(absl LANGUAGES CXX)': (\n              'project(absl LANGUAGES CXX VERSION {})'.format(datestamp)\n          ),\n          # Set the SOVERSION to YYMM.0.0 - The first 0 means we only have ABI\n          # compatible changes, and the second 0 means we can increment it to\n          # mark changes as ABI-compatible, for patch releases.  Note that we\n          # only use the last two digits of the year and the month because the\n          # MacOS linker requires the first part of the SOVERSION to fit into\n          # 16 bits.\n          # https://www.sicpers.info/2013/03/how-to-version-a-mach-o-library/\n          'ABSL_SOVERSION 0': 'ABSL_SOVERSION \"{}.0.0\"'.format(datestamp[2:6]),\n      },\n  )\n  StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin',\n                          '# absl:lts-remove-end')\n\n\nif __name__ == '__main__':\n  main(sys.argv)\n"
  }
]